├── debian ├── compat ├── copyright ├── source │ └── format ├── rules ├── changelog └── control ├── Makefile.ecf ├── TODO.md ├── t └── setup.sh ├── etc └── omdclient │ └── place.holder ├── usr ├── libexec │ └── omdclient │ │ └── git-hooks │ │ ├── post-receive │ │ ├── omd-sync │ │ └── email └── bin │ ├── omd-reinventory │ ├── omd-puppet-enc │ ├── omd-activate │ ├── omd-nagios-hostlist │ ├── omd-nagios-count │ ├── omd-host-tag │ ├── omd-nagios-ack │ ├── omd-nagios-downtime │ ├── omd-bulkimport │ ├── omd-host-report │ ├── omd-nagios-hosts-with-problem │ ├── omd-nagios-report │ └── omd-host-crud ├── LICENSE ├── .gitignore ├── MANIFEST ├── setup.py ├── Makefile.deb ├── CHANGELOG.md ├── Makefile.local ├── README.md ├── man └── man1 │ ├── omd-reinventory.1 │ ├── omd-nagios-report.1 │ ├── omd-activate.1 │ ├── omd-nagios-hostlist.1 │ ├── omd-host-tag.1 │ ├── omd-nagios-ack.1 │ ├── omd-puppet-enc.1 │ ├── omd-nagios-downtime.1 │ ├── omd-host-crud.1 │ └── omd-nagios-hosts-with-problem.1 ├── omdclient.spec └── omdclient └── __init__.py /debian/compat: -------------------------------------------------------------------------------- 1 | 10 2 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | ../LICENSE -------------------------------------------------------------------------------- /Makefile.ecf: -------------------------------------------------------------------------------- 1 | ../ecf-rpmtools/Makefile -------------------------------------------------------------------------------- /TODO.md: -------------------------------------------------------------------------------- 1 | * pip3 - add bs4 prereq 2 | -------------------------------------------------------------------------------- /debian/source/format: -------------------------------------------------------------------------------- 1 | 3.0 (quilt) 2 | -------------------------------------------------------------------------------- /t/setup.sh: -------------------------------------------------------------------------------- 1 | export PYTHONPATH=`pwd`/.. 2 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | 3 | %: 4 | dh $@ 5 | -------------------------------------------------------------------------------- /etc/omdclient/place.holder: -------------------------------------------------------------------------------- 1 | # this file is intentionally left blank 2 | -------------------------------------------------------------------------------- /usr/libexec/omdclient/git-hooks/post-receive: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | pee /usr/libexec/omdclient/git-hooks/omd-sync \ 4 | /usr/libexec/omdclient/git-hooks/email 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2015-2019, Fermi National Accelerator Laboratory 2 | 3 | This program is free software; you may redistribute it and/or modify 4 | it under the same terms as Perl. 5 | -------------------------------------------------------------------------------- /debian/changelog: -------------------------------------------------------------------------------- 1 | omdclient (1.2.0-2) UNRELEASED; urgency=medium 2 | 3 | * Initial release, converted from rpm tree. 4 | 5 | -- Tim Skirvin Mon, 04 Dec 2017 19:16:29 +0000 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | debian/debhelper-build-stamp 3 | debian/files 4 | debian/omdclient/ 5 | debian/omdclient.substvars 6 | ed/ 7 | etc/omdclient/*.yaml 8 | Makefile 9 | omdclient/*.pyc 10 | omdclient/*.pyo 11 | *egg-info 12 | dist/ 13 | installed_files 14 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: omdclient 2 | Maintainer: Tim Skirvin 3 | Section: misc 4 | Priority: optional 5 | Standards-Version: 3.9.2 6 | Build-Depends: debhelper (>= 9), python, perl 7 | 8 | Package: omdclient 9 | Architecture: any 10 | Depends: ${shlibs:Depends}, ${misc:Depends}, python 11 | Description: omd client tools for check_mk 12 | Tools to interact with a check_mk/OMD interface. 13 | -------------------------------------------------------------------------------- /MANIFEST: -------------------------------------------------------------------------------- 1 | # file GENERATED by distutils, do NOT edit 2 | setup.py 3 | man/man1/omd-activate.1 4 | man/man1/omd-host-crud.1 5 | man/man1/omd-host-tag.1 6 | man/man1/omd-nagios-ack.1 7 | man/man1/omd-nagios-downtime.1 8 | man/man1/omd-nagios-hostlist.1 9 | man/man1/omd-nagios-hosts-with-problem.1 10 | man/man1/omd-nagios-report.1 11 | man/man1/omd-puppet-enc.1 12 | man/man1/omd-reinventory.1 13 | omdclient/__init__.py 14 | usr/bin/omd-activate 15 | usr/bin/omd-bulkimport 16 | usr/bin/omd-host-crud 17 | usr/bin/omd-host-tag 18 | usr/bin/omd-nagios-ack 19 | usr/bin/omd-nagios-downtime 20 | usr/bin/omd-nagios-hostlist 21 | usr/bin/omd-nagios-hosts-with-problem 22 | usr/bin/omd-nagios-report 23 | usr/bin/omd-puppet-enc 24 | usr/bin/omd-reinventory 25 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | import glob, re, os 3 | 4 | ## get documentation from README.md 5 | with open("README.md", "r") as fh: 6 | long_description = fh.read() 7 | 8 | ## get version from spec file 9 | with open('omdclient.spec', 'r') as fh: 10 | for line in fh: 11 | m = re.search("^Version:\s+(.*)\s*$", line) 12 | if m: 13 | version=m.group(1) 14 | break 15 | 16 | ## get list of files to install 17 | pyfiles = glob.glob(os.path.join('*', '*.py')) 18 | pyfiles = [pyfile[:-3] for pyfile in pyfiles] 19 | 20 | scripts = glob.glob(os.path.join('usr/bin/*')) 21 | man = glob.glob(os.path.join('man/man1/*')) 22 | 23 | setup ( 24 | name = 'omdclient', 25 | version = version, 26 | description = 'omdclient check_mk + WATO/OMD interface', 27 | long_description = long_description, 28 | long_description_content_type = 'text/markdown', 29 | author = 'Tim Skirvin', 30 | author_email = 'tskirvin@fnal.gov', 31 | url = 'https://github.com/tskirvin/omdclient/', 32 | license = 'Perl Artistic', 33 | maintainer = 'Tim Skirvin', 34 | maintainer_email = 'tskirvin@fnal.gov', 35 | package_dir = { 'omdclient': 'omdclient' }, 36 | data_files = [ ( 'share/man/man1', man ) ], 37 | scripts = scripts, 38 | py_modules = pyfiles, 39 | keywords = ['check_mk', 'omd', 'nagios', 'api', 'wato'], 40 | install_requires = ['bs4>=4.0.0'], 41 | ) 42 | 43 | # add classifiers, platforms 44 | -------------------------------------------------------------------------------- /Makefile.deb: -------------------------------------------------------------------------------- 1 | ######################################################################### 2 | ### Central Configuration - EDIT AT YOUR OWN RISK ####################### 3 | ######################################################################### 4 | 5 | PACKAGE = $(shell egrep '^Name' *spec | cut -d':' -f2 | tr -d ' ') 6 | 7 | ## Package version string 8 | REL = $(shell egrep ^Release *.spec | cut -d':' -f2 | tr -d ' ' | sed s/\%\{\?dist\}/.el${RHL}/) 9 | VERS = $(shell egrep ^Version *.spec | cut -d':' -f2 | tr -d ' ') 10 | 11 | ## What files to track? Will decide whether we need to re-build the .tar 12 | FILES = Makefile.local Makefile.deb debian/ 13 | 14 | ## Include local configuration 15 | -include Makefile.local 16 | 17 | ######################################################################### 18 | ### main () ############################################################# 19 | ######################################################################### 20 | 21 | tar: $(FILES) $(FILES_LOCAL) man 22 | tar --exclude '.git' --exclude '*.tar*' --exclude '*.sw*' \ 23 | --exclude '.gitignore' $(TAR_EXCLUDE) \ 24 | -czpf $(PACKAGE)-$(VERS)-$(REL).tar.gz $(FILES) $(FILES_LOCAL) 25 | 26 | 27 | install: 28 | @mkdir -p /usr/local/man/man1 29 | python setup.py install 30 | for i in `ls usr/bin`; do \ 31 | pod2man usr/bin/$$i > /usr/local/man/man1/$$i.1; \ 32 | done 33 | 34 | man: 35 | @mkdir -p man/man1 36 | @rm -rf man/man1/* 37 | @for i in `ls usr/bin`; do \ 38 | pod2man usr/bin/$$i > man/man1/$$i.1; \ 39 | done 40 | 41 | build: tar man 42 | debuild -b -uc -us 43 | -------------------------------------------------------------------------------- /usr/libexec/omdclient/git-hooks/omd-sync: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Looks at a git commit for updated .yaml files; each updated file will have 3 | # its monitoring information updated with omd-puppet-enc. Meant to be used as 4 | # a post-receive hook for a puppet ENC git repository. 5 | 6 | tmp=$(mktemp -d /tmp/git.XXXXXX) 7 | exit_status=0 8 | 9 | while read oldref newref refname; do 10 | BRANCH=`echo $refname | sed -n 's/^refs\/heads\///p'` 11 | 12 | if [[ $BRANCH != 'master' ]]; then 13 | echo "we only look for OMD updates branch 'master'" 14 | else 15 | declare -a FILES 16 | FILES=$(git diff-tree --no-commit-id --name-only -r "${newref}") 17 | for file in ${FILES[@]}; do 18 | if [[ $file =~ [.]yaml$ ]]; then 19 | FILENAME=$tmp/`basename $file` 20 | git show "${newref}:${file}" > $FILENAME 21 | /usr/bin/omd-puppet-enc update $FILENAME 22 | if [[ $? -ne 0 ]]; then exit_status=2; fi 23 | fi 24 | done 25 | 26 | declare -a FILES_DELETE 27 | FILES_DELETE=$(git diff-tree --no-commit-id --diff-filter=D --name-only -r "${newref}") 28 | for file in ${FILES_DELETE[@]}; do 29 | if [[ $file =~ [.]yaml$ ]]; then 30 | FILENAME=$tmp/`basename $file` 31 | git show "${oldref}:${file}" > $FILENAME 32 | /usr/bin/omd-puppet-enc delete $FILENAME 33 | if [[ $? -ne 0 ]]; then exit_status=2; fi 34 | fi 35 | done 36 | fi 37 | done 38 | 39 | rm -rf $log $tmp $tree 40 | exit $exit_status 41 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | 5 | The format is based on [Keep a 6 | Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres 7 | to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). 8 | 9 | ## [Unreleased] 10 | 11 | ## [1.4.3-1] - 2023-10-31 12 | 13 | - omdclient.spec - EL9 support 14 | 15 | ## [1.4.3] - 2022-09-15 16 | 17 | ### Changed 18 | 19 | - omdclient.spec - CentOS 8 support (mostly in Requires: and BuildRequires:) 20 | - __init__.py - fixed a bad exception in loadCfg() 21 | - __init__.py - switching from load() to `safe_load()` in loadCfg() 22 | 23 | ## [1.4.2] - 2019-08-23 24 | 25 | ### Changed 26 | 27 | - init.py - decoding output from urllib requests (fixes "failed to run: a 28 | bytes-like object is required, not 'str'" bug) 29 | 30 | ## [1.4.1] - 2019-08-19 31 | 32 | ### Changed 33 | 34 | * ran all python through flake8 python linter, cleaned it up to match 35 | 36 | ## [1.4.0] - 2019-08-16 37 | 38 | ### Changed 39 | 40 | * `omdclient/__init__.py` - added some docs re: `tag_role` and 41 | `tag_instance` in the documentation (in short, we use them locally to 42 | tie together puppet + OMD, but they're not very interesting otherwise). 43 | * converted everything to Python 3 44 | 45 | ### Removed 46 | 47 | * dropping rpms for RHEL 6 48 | 49 | ## [1.3.5] - 2019-03-19 50 | 51 | ### Added 52 | 53 | * CHANGELOG.md - standardizing on a single changelog file 54 | 55 | ### Changed 56 | 57 | * Makefile.local - now includes Pypi (pip) bindings 58 | * setup.py, omdclient.spec - re-worked for setuptools instead of distutils.core 59 | * README.md - lots of updates on the path towards real distribution 60 | 61 | ### Removed 62 | 63 | * TODO.md - currently empty 64 | -------------------------------------------------------------------------------- /Makefile.local: -------------------------------------------------------------------------------- 1 | ############################################################################## 2 | ### cms-rpmtools Makefile.local ############################################## 3 | ############################################################################## 4 | ## Meant for use with the Makefile from cms-rpmtools. Assuming the package is 5 | ## at the same level, run: 6 | ## 7 | ## ln -s ../cms-rpmtools/Makefile . 8 | ## cp ../cms-rpmtools/Makefile.local . 9 | ## 10 | ## This should give you access to a consistent Makefile. You're in charge 11 | ## of your own *.spec file. 12 | 13 | ############################################################################## 14 | ### Tarball Configuration #################################################### 15 | ############################################################################## 16 | 17 | ## We will only rebuild our .tar file if one of these files changes: the 18 | ## Makefile itself, Makefile.local, the *.spec file, and anything listed in 19 | ## $(FILES_LOCAL). 20 | # FILES_LOCAL = usr etc 21 | FILES_LOCAL = omdclient etc usr setup.py man README.md omdclient.spec 22 | 23 | ## When creating the local 24 | # TAR_EXCLUDE = --exclude *.bak --exclude .git 25 | TAR_EXCLUDE = --exclude *.pyc --exclude *.pyo 26 | 27 | VERS := $(shell egrep ^Version *.spec | cut -d':' -f2 | tr -d ' ') 28 | 29 | ############################################################################## 30 | ### Targets ################################################################## 31 | ############################################################################## 32 | ## Set your own targets. Note that these will appear at the top. 33 | 34 | all: rpm-8-nosign rpm-9-nosign rpm-sign 35 | confirm: confirm-el8 confirm-el9 36 | deploy: deploy-8 deploy-9 37 | copy: copy-el8 copy-el9 38 | rpm-sign: sign-el8 sign-el9 39 | test: rpm-9-nosign 40 | 41 | ############################################################################# 42 | ### PyPi #################################################################### 43 | ############################################################################# 44 | 45 | pip-test: pip-build pip-send-test 46 | pip-commit: pip-build pip-send-main 47 | 48 | pip-clean: 49 | rm dist/* 50 | 51 | pip-build: 52 | python3 setup.py sdist bdist_wheel 53 | 54 | pip-send-test: 55 | python3 -m twine upload --repository-url https://test.pypi.org/legacy/ dist/*-$(VERS)* 56 | 57 | pip-send-main: 58 | python3 -m twine upload dist/*-$(VERS)* 59 | -------------------------------------------------------------------------------- /usr/libexec/omdclient/git-hooks/email: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # original code from: http://hunnur.com/blog/2010/10/dynamic-git-branch-puppet-environments/ 4 | # however, it has been heavily modified for our environment 5 | 6 | # Read input from stdin 7 | read oldrev newrev refname 8 | 9 | # Set the kerberos credentials 10 | KRB5CCNAME=FILE:/tmp/krb5cc_puppet && /usr/krb5/bin/kinit -k puppet/cms/cms-puppet.fnal.gov@FNAL.GOV -t /etc/puppet/keytab 11 | 12 | # try to get the configuration, else set some defaults 13 | if [ -e /etc/puppet/enc-githooks.conf ]; then 14 | . /etc/puppet/enc-githooks.conf 15 | else 16 | REPO="puppet@cms-git:/var/lib/puppet/enc.git" 17 | BRANCH_DIR="/srv/puppet/enc" 18 | PUPPET_SERVERS="puppet@cmssrv166.fnal.gov" 19 | fi 20 | BRANCH=`echo $refname | sed -n 's/^refs\/heads\///p'` 21 | 22 | # Define a log function that will echo to stdout as well as log to the system 23 | function logit 24 | { 25 | echo $1 26 | logger $1 27 | } 28 | 29 | function rm_branch { 30 | ssh $puppet_server /bin/sh <<-EOF 31 | cd $BRANCH_DIR && rm -rf $BRANCH 32 | EOF 33 | } 34 | 35 | function push_branch { 36 | remote_server=$1 37 | ssh ${remote_server} /bin/sh <<-EOF 38 | KRB5CCNAME=FILE:/tmp/krb5cc_puppet && /usr/krb5/bin/kinit -k puppet/cms/cms-puppet.fnal.gov@FNAL.GOV -t /etc/puppet/keytab 39 | { cd $BRANCH_DIR/$BRANCH && git pull origin $BRANCH ; } \ 40 | || { mkdir -p $BRANCH_DIR \ 41 | && cd $BRANCH_DIR \ 42 | && git clone $REPO $BRANCH \ 43 | && cd $BRANCH \ 44 | && git checkout -b $BRANCH origin/$BRANCH ; } 45 | EOF 46 | 47 | } 48 | 49 | # report what we received from stdin 50 | logit "Recieved from stdin:" 51 | logit " oldrev: $oldrev" 52 | logit " newrev: $newrev" 53 | logit " refname: $refname" 54 | 55 | # Send notification email 56 | echo $oldrev $newrev $refname | /usr/share/git-core/contrib/hooks/post-receive-email 57 | 58 | # report the configuration we are running with 59 | logit "Derived Configuration:" 60 | logit " REPO: $REPO" 61 | logit " BRANCH: $BRANCH" 62 | logit " BRANCH_DIR: $BRANCH_DIR" 63 | logit " PUPPET_SERVERS: $PUPPET_SERVERS" 64 | 65 | if [ "$newrev" -eq 0 ] 2> /dev/null ; then 66 | for puppet_server in $PUPPET_SERVERS 67 | do 68 | # branch is being deleted 69 | logit "Deleting remote branch $BRANCH_DIR/$BRANCH on $puppet_server" 70 | rm_branch 71 | done 72 | 73 | else 74 | for puppet_server in $PUPPET_SERVERS 75 | do 76 | # branch is being updated 77 | logit "Updating remote branch $BRANCH_DIR/$BRANCH on $puppet_server" 78 | push_branch ${puppet_server} 79 | done 80 | fi 81 | 82 | -------------------------------------------------------------------------------- /usr/bin/omd-reinventory: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Reinventory a given node (or nodes) 3 | 4 | ######################################################################### 5 | ### Declarations ######################################################## 6 | ######################################################################### 7 | 8 | import omdclient, os, sys 9 | 10 | ######################################################################### 11 | ### Configuration ####################################################### 12 | ######################################################################### 13 | ## Managed via central libraries and /etc/omd_client 14 | 15 | config_file_base = '/etc/omdclient/config.yaml' 16 | 17 | ## Text for --help 18 | text = "Reinventory a given node through the check_mk/WATO interface" 19 | usage_text = "usage: %prog [options]" 20 | 21 | ######################################################################### 22 | ### main () ############################################################# 23 | ######################################################################### 24 | 25 | def main(): 26 | config_file = os.environ.get('OMDCONFIG', config_file_base) 27 | try: 28 | config = omdclient.loadCfg(config_file) 29 | except Exception as e: 30 | print("failed to load config: %s" % (e)) 31 | sys.exit(3) 32 | 33 | p = omdclient.generateParser(text, usage_text, config) 34 | p.add_option('--tabula_rasa', dest='tabula_rasa', 35 | action="store_true", default=True, 36 | help="tabula-rasa refresh? (default: %default)") 37 | opt, args = p.parse_args() 38 | argdict = omdclient.parserArgDict(opt) 39 | argdict['tabula_rasa'] = opt.tabula_rasa 40 | 41 | error = 0 42 | for host in args: 43 | value, result = omdclient.discoverServicesHost(host, argdict) 44 | if value is False: 45 | if result is None: print("%s - unknown error" % host) 46 | else: print("error on inventory: %s" % result) 47 | error = 1 48 | else: 49 | print("%s - %s" % (host, result)) 50 | 51 | sys.exit(error) 52 | 53 | if __name__ == "__main__": 54 | main() 55 | 56 | ######################################################################### 57 | ### POD Documentation ################################################### 58 | ######################################################################### 59 | 60 | """ 61 | 62 | =head1 NAME 63 | 64 | omd-reinventory - reinventory a given node (or nodes) 65 | 66 | =head1 SYNOPSIS 67 | 68 | B HOSTNAME [HOSTNAME] 69 | 70 | =head1 USAGE 71 | 72 | omd-reinventory runs an inventory on a host or list of hosts. 73 | 74 | =head1 ARGUMENTS 75 | 76 | =over 4 77 | 78 | =item B<--debug> 79 | 80 | If set, print debugging information. 81 | 82 | =item B<--apikey> I 83 | 84 | Password for the API User. Default: comes from the configuration file. 85 | 86 | =item B<--server> I 87 | 88 | Host name of the server. Default: comes from the configuration file. 89 | 90 | =item B<--site> I 91 | 92 | Site name within the server. Default: comes from the configuration file. 93 | 94 | =item B<--user> I 95 | 96 | API User name. The user must exist on the server, and be an 'automation 97 | user'. Default: comes from the configuration file. 98 | 99 | =back 100 | 101 | =head1 FILES 102 | 103 | =over 4 104 | 105 | =item F 106 | 107 | =back 108 | 109 | =head1 SEE ALSO 110 | 111 | https://mathias-kettner.de/checkmk_wato_webapi.html 112 | 113 | =head1 AUTHOR 114 | 115 | Tim Skirvin 116 | 117 | =head1 LICENSE + COPYRIGHT 118 | 119 | Copyright 2016, Fermi National Accelerator Laboratory 120 | 121 | This program is free software; you may redistribute it and/or modify it 122 | under the same terms as Perl itself. 123 | 124 | =cut 125 | 126 | """ 127 | -------------------------------------------------------------------------------- /usr/bin/omd-puppet-enc: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Converts puppet ENC data to omd-host-crud commands, using the checkmk_role, 3 | # checkmk_instance, and checkmk_extra fields under 'parameters'. 4 | 5 | ACTION=$1 6 | FILE=$2 7 | if [[ ! -f $FILE ]]; then 8 | echo "Usage: $0 [update|delete] FILE.yaml" 9 | exit -1 10 | fi 11 | 12 | ENC_HOST=`basename $FILE | sed -e 's/\..*\.yaml//'` 13 | 14 | if [[ $ACTION == 'update' ]]; then 15 | CMK_ROLE=`cat $FILE | shyaml get-value parameters.checkmk_role 2>/dev/null` 16 | CMK_INSTANCE=`cat $FILE | shyaml get-value parameters.checkmk_instance 2>/dev/null` 17 | CMK_EXTRA=`cat $FILE | shyaml get-values parameters.checkmk_extra 2>/dev/null` 18 | 19 | if [[ $CMK_EXTRA =~ 'unmonitored' ]]; then 20 | CMD="omd-host-crud delete $ENC_HOST" 21 | else 22 | CMD="omd-host-crud update $ENC_HOST \ 23 | --role ${CMK_ROLE:-UNSET} \ 24 | --instance ${CMK_INSTANCE:-UNSET} 25 | --extra '${CMK_EXTRA:-UNSET}'" 26 | fi 27 | elif [[ $ACTION == 'delete' ]]; then 28 | CMD="omd-host-crud delete $ENC_HOST" 29 | else 30 | echo "Usage [update|delete] FILE.yaml" 31 | exit -1 32 | fi 33 | 34 | echo $CMD 35 | exec $CMD 36 | 37 | ############################################################################### 38 | ### Documentation ############################################################# 39 | ############################################################################### 40 | 41 | # Documentation. Use a hack to hide this from the shell. Because of the 42 | # above exit line, this should never be executed. 43 | DOCS=<<__END_OF_DOCS__ 44 | 45 | =head1 NAME 46 | 47 | omd-puppet-enc - converts puppet ENC data to omd-host-crud commands 48 | 49 | =head1 SYNOPSIS 50 | 51 | B update cmsdev43.fnal.gov.yaml 52 | 53 | B delete cmsdev43.fnal.gov.yaml 54 | 55 | =head1 DESCRIPTION 56 | 57 | This script parses standard ENC yaml, as defined at: 58 | 59 | https://docs.puppetlabs.com/guides/external_nodes.html 60 | 61 | It then runs appropriate omd-host-crud commands to either update or delete 62 | the upstream monitoring configuration based on the contents of the ENC. This 63 | can then be hooked into (say) a post-receive hook to automatically update 64 | monitoring data when hosts are added/removed/updated in the main node 65 | repository. 66 | 67 | =head1 PARAMETERS 68 | 69 | =over 4 70 | 71 | =item COMMAND 72 | 73 | Either I or I. Passed to B. 74 | 75 | =item FILENAME 76 | 77 | File to load. The name of the file should correspond to the fqdn of the host, 78 | plus '.yaml', in an arbitrary path. 79 | 80 | =back 81 | 82 | =head1 FIELDS 83 | 84 | We are parsing the following entries under the =parameters= hash in the ENC 85 | yaml: 86 | 87 | =over 4 88 | 89 | =item checkmk_role 90 | 91 | Primary sorting tag. More-or-less corresponds to the puppet role. 92 | 93 | Examples: bastion, htcondor_gpgrid_collector. 94 | 95 | =item checkmk_instance 96 | 97 | Secondary sorting tag. 98 | 99 | Examples: test, dev, backup, etc. 100 | 101 | =item checkmk_extra 102 | 103 | Array of extra fields. If we see I for one of them, then we will 104 | try to delete the host from monitoring. 105 | 106 | =back 107 | 108 | =head1 SAMPLE DATA 109 | 110 | cmsdev43.fnal.gov.yaml: 111 | classes: 112 | role::dev: 113 | 114 | parameters: 115 | checkmk_role: devhost 116 | checkmk_instance: dev 117 | checkmk_extra: 118 | - unmonitored 119 | - foo 120 | 121 | =head1 SEE ALSO 122 | 123 | B 124 | 125 | =head1 AUTHOR 126 | 127 | Tim Skirvin 128 | 129 | =head1 LICENSE 130 | 131 | Copyright 2015, Fermi National Accelerator Laboratory 132 | 133 | This program is free software; you may redistribute it and/or modify 134 | it under the same terms as Perl itself. 135 | 136 | =cut 137 | 138 | __END_OF_DOCS__ 139 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # omdclient 2 | 3 | omdclient provides a suite of command-line tools to interact with the APIs 4 | associated with the `check_mk`/Open Monitoring Distribution tool suite. 5 | 6 | ## WATO APIs 7 | 8 | WATO is used to create, remove, and modify entries within the OMD user 9 | suite. This is documented at: 10 | 11 | 12 | 13 | ### omd-activate 14 | 15 | Activates changes made by the API user. 16 | 17 | ### omd-bulkimport 18 | 19 | Takes a list of hosts on STDIN and adds them to a specific folder in OMD. 20 | 21 | ### omd-host-crud 22 | 23 | Creates/Reads/Updates/Deletes entries from an existing monitoring 24 | interface. 25 | 26 | ### omd-host-tag 27 | 28 | update/remove a given host tag in OMD 29 | 30 | ### omd-reinventory 31 | 32 | Reinventory a host in OMD. 33 | 34 | ## Multisite/Nagios 35 | 36 | 37 | 38 | ### omd-nagios-ack 39 | 40 | Acknowledges host/service alerts from the command-line. 41 | 42 | ### omd-nagios-downtime 43 | 44 | Schedules host/service downtimes from the command-line. 45 | 46 | ### omd-nagios-hostlist 47 | 48 | Print a list of all hosts in the given nagios instance. 49 | 50 | ### omd-nagios-hosts-with-problem 51 | 52 | Print a list of hosts that are currently exhibiting a specific problem. 53 | 54 | ### omd-nagios-report 55 | 56 | Prints a human-readable report on current host and service alerts. 57 | 58 | ## Setup / How To Use 59 | 60 | ### /etc/omdclient/config.yaml 61 | 62 | You'll have to populate this file on your own: 63 | 64 | server: 'xxxxxx.example' 65 | site: 'xxxxxx' 66 | user: 'xxxx-api' 67 | apikey: 'xxxxxx' 68 | 69 | If you set the 'OMDCONFIG' environment variable you can point at different 70 | configs, e.g.: 71 | 72 | OMDCONFIG=/tmp/myconfig.yaml omd-activate 73 | 74 | ### Configuration of 'expanded views' 75 | 76 | The report scripts depend on 'expanded view' versions of the 77 | `hostproblems` and `svcproblems` views, which add comments. In order to 78 | add these, you generally have to: 79 | 80 | 1. Edit view `hostproblems` - it's a default view, so you'll go to 'clone'. 81 | * Change the name from `hostproblems` to `hostproblems_expanded`. 82 | * Update the list of columns to read: 83 | 1. Hostname 84 | 2. Host icons 85 | 3. Host state 86 | 4. Output of host check plugin 87 | 5. Number of services in state OK 88 | 6. Number of services in state WARN 89 | 7. Number of services in state UNKNOWN 90 | 8. Number of services in state CRIT 91 | 9. Number of services in state PENDING 92 | 10. The age of the current host state 93 | 11. Host comments 94 | * (newer versions) set to 'public' and 'hidden'. 95 | * Save. 96 | 2. Edit the view `svcproblems` and created `svcproblems_expanded`, same 97 | as above but just add the column `Service Comments`. 98 | 99 | In newer versions of check\_mk, you may also need to make these views 100 | Public (check `Visibility` / `Make this view available for other users` / 101 | `Publish to all users`). Also, the `hostproblems` base view may have 102 | changed: I have for `hostproblems_expanded`: 103 | 104 | (Thanks to Christian Bryn - https://github.com/epleterte - for the docs!) 105 | 106 | ## How To Build 107 | 108 | There is a `Makefile.bak` and a `*.spec` file that mirrors my local build 109 | process for RPMs, if this matches your requirements; just run 110 | `make -f Makefile.bak build-nomock`. 111 | 112 | Otherwise, you may want to just follow the general instructions 113 | in `*.spec`. Scripts from `usr/bin/*` go into your path; create 114 | `/etc/omdclient/config.yaml` as described above; make man pages with 115 | `pod2man` if you're ambitious; and run `python setup.py install` to 116 | install the python library. 117 | 118 | ### Debian 119 | 120 | make -f Makefile.deb build 121 | 122 | That should build a full .deb package. 123 | -------------------------------------------------------------------------------- /usr/bin/omd-activate: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Activate changes made via the omdclient scripts. 3 | 4 | ######################################################################### 5 | ### Declarations ######################################################## 6 | ######################################################################### 7 | 8 | import omdclient, os, sys 9 | 10 | ######################################################################### 11 | ### Configuration ####################################################### 12 | ######################################################################### 13 | ## Managed via central libraries and /etc/omd_client 14 | 15 | config_file_base = '/etc/omdclient/config.yaml' 16 | 17 | ## Text for --help 18 | text = "Activate changes in check_mk/WATO interface" 19 | usage_text = "usage: %prog [options]" 20 | 21 | ######################################################################### 22 | ### main () ############################################################# 23 | ######################################################################### 24 | 25 | def main(): 26 | config_file = os.environ.get('OMDCONFIG', config_file_base) 27 | try: 28 | config = omdclient.loadCfg(config_file) 29 | except Exception as e: 30 | print("failed to load config: %s" % (e)) 31 | sys.exit(3) 32 | 33 | p = omdclient.generateParser(text, usage_text, config) 34 | p.add_option('--foreign_ok', dest='foreign_ok', 35 | action="store_true", default=True, 36 | help="apply foreign commits? (default: %default)") 37 | opt, args = p.parse_args() 38 | argdict = omdclient.parserArgDict(opt) 39 | argdict['foreign_ok'] = opt.foreign_ok 40 | 41 | try: 42 | value, result = omdclient.activateChanges(argdict) 43 | if not value: 44 | if result is None: print("unknown error") 45 | else: print(result) 46 | sys.exit(1) 47 | else: 48 | print(result) 49 | sys.exit(0) 50 | except Exception as e: 51 | print("failed to activate changes: %s" % (e)) 52 | sys.exit(-1) 53 | 54 | if __name__ == "__main__": 55 | main() 56 | 57 | ######################################################################### 58 | ### POD Documentation ################################################### 59 | ######################################################################### 60 | 61 | """ 62 | 63 | =head1 NAME 64 | 65 | omd-activate - activate changes on the OMD site 66 | 67 | =head1 SYNOPSIS 68 | 69 | B 70 | 71 | =head1 USAGE 72 | 73 | omd-activate simply activates the changes that were made in other scripts. 74 | It generally takes a long time to run, and (sometimes) get back a 503 http 75 | error because of how long it takes. 76 | 77 | =head1 ARGUMENTS 78 | 79 | =over 4 80 | 81 | =item B<--debug> 82 | 83 | If set, print debugging information. 84 | 85 | =item B<--apikey> I 86 | 87 | Password for the API User. Default: comes from the configuration file. 88 | 89 | =item B<--server> I 90 | 91 | Host name of the server. Default: comes from the configuration file. 92 | 93 | =item B<--site> I 94 | 95 | Site name within the server. Default: comes from the configuration file. 96 | 97 | =item B<--user> I 98 | 99 | API User name. The user must exist on the server, and be an 'automation 100 | user'. Default: comes from the configuration file. 101 | 102 | =back 103 | 104 | =head1 FILES 105 | 106 | =over 4 107 | 108 | =item F 109 | 110 | =back 111 | 112 | =head1 SEE ALSO 113 | 114 | https://mathias-kettner.de/checkmk_wato_webapi.html 115 | 116 | =head1 AUTHOR 117 | 118 | Tim Skirvin 119 | 120 | =head1 LICENSE + COPYRIGHT 121 | 122 | Copyright 2015, Fermi National Accelerator Laboratory 123 | 124 | This program is free software; you may redistribute it and/or modify it 125 | under the same terms as Perl itself. 126 | 127 | =cut 128 | 129 | """ 130 | -------------------------------------------------------------------------------- /usr/bin/omd-nagios-hostlist: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | List all hosts in Nagios. 4 | """ 5 | 6 | ######################################################################### 7 | ### Declarations ######################################################## 8 | ######################################################################### 9 | 10 | import omdclient, os, sys 11 | 12 | ######################################################################### 13 | ### Configuration ####################################################### 14 | ######################################################################### 15 | 16 | ## Central configuration file. 17 | config_file_base = '/etc/omdclient/config.yaml' 18 | 19 | ## Text for --help 20 | text = "List all hosts in Nagios, using the WATO API" 21 | usage_text = "usage: %prog PROBLEM [options]" 22 | 23 | ######################################################################### 24 | ### main () ############################################################# 25 | ######################################################################### 26 | 27 | def main(): 28 | config_file = os.environ.get('OMDCONFIG', config_file_base) 29 | try: 30 | config = omdclient.loadCfg(config_file) 31 | except Exception as e: 32 | print("failed to load config: %s" % (e)) 33 | sys.exit(3) 34 | 35 | p = omdclient.generateParser(text, usage_text, config) 36 | p.add_option('--verbose', dest='verbose', action="store_true", 37 | default=False, help='print more status information') 38 | p.add_option('--filter-site', dest='filter_site', 39 | default=False, help='Filter result by monitored site. Default: disabled') 40 | opt, args = p.parse_args() 41 | 42 | argdict = omdclient.parserArgDict(opt) 43 | 44 | try: 45 | if opt.filter_site: 46 | hosts = omdclient.listHostsFiltered(opt.filter_site, argdict) 47 | else: 48 | hosts = omdclient.listHosts(argdict) 49 | h = [] 50 | for i in hosts[1]: 51 | if i: h.append(i) 52 | h.sort() 53 | for i in h: print(i) 54 | 55 | except Exception as e: 56 | print("failed: %s" % (e)) 57 | sys.exit(-1) 58 | 59 | if __name__ == "__main__": 60 | main() 61 | 62 | ######################################################################### 63 | ### POD Documentation ################################################### 64 | ######################################################################### 65 | 66 | """ 67 | 68 | =head1 NAME 69 | 70 | omd-nagios-hostlist - list all hosts in nagios 71 | 72 | =head1 SYNOPSIS 73 | 74 | B 75 | 76 | =head1 USAGE 77 | 78 | omd-nagios-hostlist pulls the list of monitored hosts from check_mk and 79 | prints them to STDOUT. 80 | 81 | =head1 ARGUMENTS 82 | 83 | =head2 DEFAULT 84 | 85 | =over 4 86 | 87 | =item B<--debug> 88 | 89 | If set, print debugging information. 90 | 91 | =item B<--help> 92 | 93 | Print this information and exit. 94 | 95 | =item B<--filter-site> 96 | 97 | Filter host by site monitored. Default: disabled 98 | 99 | =back 100 | 101 | =head2 CONNECTION OPTIONS 102 | 103 | =over 4 104 | 105 | =item B<--apikey> I 106 | 107 | Password for the API User. Default: comes from the configuration file. 108 | 109 | =item B<--server> I 110 | 111 | Host name of the server. Default: comes from the configuration file. 112 | 113 | =item B<--site> I 114 | 115 | Site name within the server. Default: comes from the configuration file. 116 | 117 | =item B<--user> I 118 | 119 | API User name. The user must exist on the server, and be an 'automation 120 | user'. Default: comes from the configuration file. 121 | 122 | =back 123 | 124 | =head1 FILES 125 | 126 | =over 4 127 | 128 | =item F 129 | 130 | =back 131 | 132 | =head1 SEE ALSO 133 | 134 | https://mathias-kettner.de/checkmk_wato_webapi.html 135 | 136 | =head1 AUTHOR 137 | 138 | Tim Skirvin 139 | 140 | =head1 LICENSE + COPYRIGHT 141 | 142 | Copyright 2017, Fermi National Accelerator Laboratory 143 | 144 | This program is free software; you may redistribute it and/or modify it 145 | under the same terms as Perl itself. 146 | 147 | =cut 148 | 149 | """ 150 | -------------------------------------------------------------------------------- /usr/bin/omd-nagios-count: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Just lists the current host/service counts 3 | 4 | ######################################################################### 5 | ### Declarations ######################################################## 6 | ######################################################################### 7 | 8 | import omdclient, re, os, socket, sys 9 | from datetime import datetime 10 | 11 | ######################################################################### 12 | ### Configuration ####################################################### 13 | ######################################################################### 14 | ## Managed via central libraries and /etc/omd_client 15 | 16 | config_file_base = '/etc/omdclient/config.yaml' 17 | 18 | ## Text for --help 19 | text = "print a pretty host/service report to STDOUT" 20 | usage_text = "usage: %prog [options]" 21 | 22 | ######################################################################### 23 | ### Subroutines ######################################################### 24 | ######################################################################### 25 | 26 | ######################################################################### 27 | ### main () ############################################################# 28 | ######################################################################### 29 | 30 | def main(): 31 | config_file = os.environ.get('OMDCONFIG', config_file_base) 32 | try: 33 | config = omdclient.loadCfg(config_file) 34 | except Exception as e: 35 | print("failed to load config: %s" % (e)) 36 | sys.exit(3) 37 | 38 | p = omdclient.generateParser(text, usage_text, config) 39 | opt, args = p.parse_args() 40 | argdict = omdclient.parserArgDict(opt) 41 | 42 | try: 43 | host_ack = omdclient.nagiosReport('host_ack', argdict) 44 | host_unack = omdclient.nagiosReport('host_unack', argdict) 45 | svc_ack = omdclient.nagiosReport('svc_ack', argdict) 46 | svc_unack = omdclient.nagiosReport('svc_unack', argdict) 47 | 48 | string = "%10s Ack: %3d Unack: %3d" 49 | print(string % ('Hosts', len(host_ack), len(host_unack))) 50 | print(string % ('Services', len(svc_ack), len(svc_unack))) 51 | # print(string % ('Acknowledged Service Alerts', len(svc_ack))) 52 | # print(string % ('Unacknowledged Service Alerts', len(svc_unack))) 53 | 54 | except Exception as e: 55 | print("failed to generate the report: %s" % (e)) 56 | sys.exit(-1) 57 | 58 | if __name__ == "__main__": 59 | main() 60 | 61 | ######################################################################### 62 | ### POD Documentation ################################################### 63 | ######################################################################### 64 | 65 | """ 66 | 67 | =head1 NAME 68 | 69 | omd-nagios-count - just lists the current nagios report counts 70 | 71 | =head1 SYNOPSIS 72 | 73 | B 74 | 75 | =head1 USAGE 76 | 77 | Lists the count of ack'd and unack'd alerts in nagios. 78 | 79 | =head1 ARGUMENTS 80 | 81 | =over 4 82 | 83 | =item B<--debug> 84 | 85 | If set, print debugging information. 86 | 87 | =item B<--apikey> I 88 | 89 | Password for the API User. Default: comes from the configuration file. 90 | 91 | =item B<--server> I 92 | 93 | Host name of the server. Default: comes from the configuration file. 94 | 95 | =item B<--site> I 96 | 97 | Site name within the server. Default: comes from the configuration file. 98 | 99 | =item B<--user> I 100 | 101 | API User name. The user must exist on the server, and be an 'automation 102 | user'. Default: comes from the configuration file. 103 | 104 | =back 105 | 106 | =head1 FILES 107 | 108 | =over 4 109 | 110 | =item F 111 | 112 | =back 113 | 114 | =head1 SEE ALSO 115 | 116 | https://mathias-kettner.de/checkmk_wato_webapi.html 117 | 118 | =head1 AUTHOR 119 | 120 | Tim Skirvin 121 | 122 | =head1 LICENSE + COPYRIGHT 123 | 124 | Copyright 2025, Fermi National Accelerator Laboratory 125 | 126 | This program is free software; you may redistribute it and/or modify it 127 | under the same terms as Perl itself. 128 | 129 | =cut 130 | 131 | """ 132 | -------------------------------------------------------------------------------- /usr/bin/omd-host-tag: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | Update a given tag for a given host using the OMD WATO API. 4 | """ 5 | 6 | ######################################################################### 7 | ### Declarations ######################################################## 8 | ######################################################################### 9 | 10 | import omdclient, optparse, os, sys 11 | 12 | ######################################################################### 13 | ### Configuration ####################################################### 14 | ######################################################################### 15 | 16 | ## Central configuration file. 17 | config_file_base = '/etc/omdclient/config.yaml' 18 | 19 | ## Text for --help 20 | text = "update a given host tag in OMD, using the WATO API" 21 | usage_text = "usage: %prog HOSTNAME TAG VALUE" 22 | 23 | ######################################################################### 24 | ### main () ############################################################# 25 | ######################################################################### 26 | 27 | def main(): 28 | config_file = os.environ.get('OMDCONFIG', config_file_base) 29 | try: 30 | config = omdclient.loadCfg(config_file) 31 | except Exception as e: 32 | print("failed to load config: %s" % (e)) 33 | sys.exit(3) 34 | 35 | p = omdclient.generateParser(text, usage_text, config) 36 | group = optparse.OptionGroup(p, 'create/update options') 37 | p.add_option_group(group) 38 | opt, args = p.parse_args() 39 | 40 | argdict = omdclient.parserArgDict(opt) 41 | 42 | if len(args) != 3: 43 | p.print_help() 44 | sys.exit(1) 45 | 46 | host = args[0] 47 | tag = args[1] 48 | value = args[2] 49 | 50 | if value == 'UNDEF': argdict['unset'] = "tag_%s" % tag 51 | else: argdict['extra'] = "tag_%s=%s" % (tag, value) 52 | 53 | value, result = omdclient.updateHost(host, argdict) 54 | if value is False: 55 | if result is None: print("%s - unknown error" % host) 56 | else: print("error on update: %s" % result) 57 | sys.exit(1) 58 | 59 | print("%s - host updated, will now inventory..." % host) 60 | 61 | value1, result1 = omdclient.discoverServicesHost(host, argdict) 62 | if value1 is False: 63 | if result is None: print("%s - unknown error" % host) 64 | else: print("error on inventory: %s" % result) 65 | sys.exit(1) 66 | else: 67 | print("%s - %s" % (host, result1)) 68 | sys.exit(0) 69 | 70 | if __name__ == "__main__": 71 | main() 72 | 73 | ######################################################################### 74 | ### POD Documentation ################################################### 75 | ######################################################################### 76 | 77 | """ 78 | 79 | =head1 NAME 80 | 81 | omd-host-tag - update/remove a given host tag in OMD 82 | 83 | =head1 SYNOPSIS 84 | 85 | B cms-foo my_tag new_value 86 | 87 | B cms-foo my_tag UNDEF 88 | 89 | =head1 USAGE 90 | 91 | omd-host-tag provides a way to update or clear a tag for a specific 92 | host using hte OMD/WATO the OMD/WATO check_mk web interface. 93 | 94 | =head1 ARGUMENTS 95 | 96 | =head2 REQUIRED 97 | 98 | =over 4 99 | 100 | =item I 101 | 102 | Hostname for which to query. No default, must be set. 103 | 104 | =item I 105 | 106 | Tag to update. This tag must already exist. 107 | 108 | =item I 109 | 110 | Value of this tag. UNDEF means "unset the flag". 111 | 112 | =back 113 | 114 | =head2 DEFAULT 115 | 116 | =over 4 117 | 118 | =item B<--debug> 119 | 120 | If set, print debugging information. 121 | 122 | =item B<--help> 123 | 124 | Print this information and exit. 125 | 126 | =back 127 | 128 | =head2 CONNECTION OPTIONS 129 | 130 | =over 4 131 | 132 | =item B<--apikey> I 133 | 134 | Password for the API User. Default: comes from the configuration file. 135 | 136 | =item B<--server> I 137 | 138 | Host name of the server. Default: comes from the configuration file. 139 | 140 | =item B<--site> I 141 | 142 | Site name within the server. Default: comes from the configuration file. 143 | 144 | =item B<--user> I 145 | 146 | API User name. The user must exist on the server, and be an 'automation 147 | user'. Default: comes from the configuration file. 148 | 149 | =back 150 | 151 | =head1 FILES 152 | 153 | =over 4 154 | 155 | =item F 156 | 157 | =back 158 | 159 | =head1 SEE ALSO 160 | 161 | https://mathias-kettner.de/checkmk_wato_webapi.html 162 | 163 | =head1 AUTHOR 164 | 165 | Tim Skirvin 166 | 167 | =head1 LICENSE + COPYRIGHT 168 | 169 | Copyright 2017, Fermi National Accelerator Laboratory 170 | 171 | This program is free software; you may redistribute it and/or modify it 172 | under the same terms as Perl itself. 173 | 174 | =cut 175 | 176 | """ 177 | -------------------------------------------------------------------------------- /usr/bin/omd-nagios-ack: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Acknowledge host/service problems through OMD API 3 | 4 | ######################################################################### 5 | ### Declarations ######################################################## 6 | ######################################################################### 7 | 8 | import getpass, omdclient, os, sys 9 | 10 | ######################################################################### 11 | ### Configuration ####################################################### 12 | ######################################################################### 13 | ## Managed via central libraries and /etc/omd_client 14 | 15 | config_file_base = '/etc/omdclient/config.yaml' 16 | 17 | ## Text for --help 18 | text = "acknowledge problems using OMD API" 19 | usage_text = "usage: %prog [options] [host|service] HOST [SVC] HOURS comment" 20 | 21 | ######################################################################### 22 | ### main () ############################################################# 23 | ######################################################################### 24 | 25 | def main(): 26 | config_file = os.environ.get('OMDCONFIG', config_file_base) 27 | try: 28 | config = omdclient.loadCfg(config_file) 29 | except Exception as e: 30 | print("failed to load config: %s" % (e)) 31 | sys.exit(3) 32 | 33 | p = omdclient.generateParser(text, usage_text, config) 34 | p.add_option('--whoami', dest='whoami', action='store', 35 | default=getpass.getuser(), 36 | help='invoking user (default: %default)') 37 | opt, args = p.parse_args() 38 | params = omdclient.parserArgDict(opt) 39 | params['whoami'] = opt.whoami 40 | 41 | if len(args) < 3: 42 | p.print_help() 43 | sys.exit(1) 44 | 45 | type = args[0] 46 | if type == 'host': 47 | params['host'] = args[1] 48 | params['service'] = None 49 | params['comment'] = ' '.join(args[2:]) 50 | params['type'] = 'host' 51 | svc_text = '%s' % (params['host']) 52 | 53 | elif (type == 'service' or type == 'svc') and len(args) >= 4: 54 | params['host'] = args[1] 55 | params['service'] = args[2] 56 | params['comment'] = ' '.join(args[3:]) 57 | params['type'] = 'service' 58 | svc_text = '%s/%s' % (params['host'], params['service']) 59 | 60 | else: 61 | p.print_help() 62 | sys.exit(1) 63 | 64 | params['comment'] = "%s (%s)" % (params['comment'], params['whoami']) 65 | 66 | try: 67 | report = omdclient.nagiosAck(params) 68 | 69 | if len(report) > 0: 70 | print("%s - acknowledged (probably)" % (svc_text)) 71 | sys.exit(0) 72 | else: 73 | print("%s - no matching entries (probably failed)" 74 | % (svc_text)) 75 | sys.exit(1) 76 | 77 | except Exception as e: 78 | print("failed to run: %s" % (e)) 79 | sys.exit(-1) 80 | 81 | if __name__ == "__main__": 82 | main() 83 | 84 | ######################################################################### 85 | ### POD Documentation ################################################### 86 | ######################################################################### 87 | 88 | """ 89 | 90 | =head1 NAME 91 | 92 | omd-nagios-ack - acknowledge a host or service problem 93 | 94 | =head1 SYNOPSIS 95 | 96 | B host cmsadmin1 'known host is down' 97 | 98 | B service cmsadmin1 puppet-report 'known problem' 99 | 100 | =head1 USAGE 101 | 102 | omd-nagios-ack uses the OMD autmation API to acknowledge a host or service 103 | alert. It works on the standard nagios limitations - you can send a 104 | request, but there's no way to get back a response. We try to guess a 105 | response anyway, but it's not horribly reliable. 106 | 107 | =head1 ARGUMENTS 108 | 109 | =head1 REQUIRED 110 | 111 | =over 4 112 | 113 | =item I 114 | 115 | Are we ack'ing a host or a service? 116 | 117 | =item I 118 | 119 | Hostname of the host or service. 120 | 121 | =item [I] 122 | 123 | Service name of the service (only necessary for service requests). 124 | 125 | =item I 126 | 127 | Some explanatory text. 128 | 129 | =back 130 | 131 | =head2 OPTIONS 132 | 133 | =over 4 134 | 135 | =item B<--debug> 136 | 137 | If set, print debugging information. 138 | 139 | =item B<--apikey> I 140 | 141 | Password for the API User. Default: comes from the configuration file. 142 | 143 | =item B<--server> I 144 | 145 | Host name of the server. Default: comes from the configuration file. 146 | 147 | =item B<--site> I 148 | 149 | Site name within the server. Default: comes from the configuration file. 150 | 151 | =item B<--user> I 152 | 153 | API User name. The user must exist on the server, and be an 'automation 154 | user'. Default: comes from the configuration file. 155 | 156 | =back 157 | 158 | =head1 FILES 159 | 160 | =over 4 161 | 162 | =item F 163 | 164 | =back 165 | 166 | =head1 SEE ALSO 167 | 168 | https://mathias-kettner.de/checkmk_wato_webapi.html 169 | 170 | =head1 AUTHOR 171 | 172 | Tim Skirvin 173 | 174 | =head1 LICENSE + COPYRIGHT 175 | 176 | Copyright 2015, Fermi National Accelerator Laboratory 177 | 178 | This program is free software; you may redistribute it and/or modify it 179 | under the same terms as Perl itself. 180 | 181 | =cut 182 | 183 | """ 184 | -------------------------------------------------------------------------------- /usr/bin/omd-nagios-downtime: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Schedules host/service downtime 3 | 4 | ######################################################################### 5 | ### Declarations ######################################################## 6 | ######################################################################### 7 | 8 | import omdclient, os, sys 9 | 10 | ######################################################################### 11 | ### Configuration ####################################################### 12 | ######################################################################### 13 | ## Managed via central libraries and /etc/omd_client 14 | 15 | config_file_base = '/etc/omdclient/config.yaml' 16 | 17 | ## Text for --help 18 | text = "schedule host/service downtimes via OMD" 19 | usage_text = "usage: %prog [options] [host|service] HOST [SVC] HOURS comment" 20 | 21 | ######################################################################### 22 | ### main () ############################################################# 23 | ######################################################################### 24 | 25 | def main(): 26 | config_file = os.environ.get('OMDCONFIG', config_file_base) 27 | try: 28 | config = omdclient.loadCfg(config_file) 29 | except Exception as e: 30 | print("failed to load config: %s" % (e)) 31 | sys.exit(3) 32 | 33 | p = omdclient.generateParser(text, usage_text, config) 34 | opt, args = p.parse_args() 35 | params = omdclient.parserArgDict(opt) 36 | 37 | if len(args) < 2: 38 | p.print_help() 39 | sys.exit(1) 40 | 41 | type = args[0] 42 | 43 | if type == 'host': 44 | params['host'] = args[1] 45 | params['service'] = None 46 | params['type'] = 'host' 47 | if not params['remove']: 48 | params['hours'] = args[2] 49 | params['comment'] = ' '.join(args[3:]) 50 | svc_text = '%s' % (params['host']) 51 | 52 | elif (type == 'service' or type == 'svc') and len(args) >= 5: 53 | params['host'] = args[1] 54 | params['service'] = args[2] 55 | params['hours'] = args[3] 56 | params['comment'] = ' '.join(args[4:]) 57 | params['type'] = 'service' 58 | svc_text = '%s/%s' % (params['host'], params['service']) 59 | 60 | elif (type == 'service' or type == 'svc') and params['remove'] and len(args) >= 3: 61 | params['host'] = args[1] 62 | params['service'] = args[2] 63 | params['type'] = 'service' 64 | svc_text = '%s/%s' % (params['host'], params['service']) 65 | 66 | else: 67 | p.print_help() 68 | sys.exit(1) 69 | 70 | try: 71 | report = omdclient.nagiosDowntime(params) 72 | 73 | if len(report) > 0: 74 | if params['remove']: 75 | print("%s - downtime removed" % svc_text) 76 | else: 77 | print("%s - downtime for %d hour(s) (probably)" 78 | % (svc_text, int(params['hours']))) 79 | sys.exit(0) 80 | else: 81 | print("%s - no matching entries (probably failed)" % (svc_text)) 82 | sys.exit(1) 83 | 84 | except Exception as e: 85 | print("failed to run: %s" % (e)) 86 | sys.exit(-1) 87 | 88 | if __name__ == "__main__": 89 | main() 90 | 91 | ######################################################################### 92 | ### POD Documentation ################################################### 93 | ######################################################################### 94 | 95 | """ 96 | 97 | =head1 NAME 98 | 99 | omd-nagios-downtime - schedule downtime for a host or service 100 | 101 | =head1 SYNOPSIS 102 | 103 | B host cmsadmin1 1 'down for an hour' 104 | 105 | B service cmsadmin1 puppet-report 2 'down for 2 hours' 106 | 107 | =head1 USAGE 108 | 109 | omd-nagios-downtime uses the OMD autmation API to put a host or service 110 | into downtime. It works on the standard nagios limitations - you can send 111 | a request, but there's no way to get back a response. We try to guess a 112 | response anyway, but it's not horribly reliable. 113 | 114 | =head1 ARGUMENTS 115 | 116 | =head2 REQUIRED 117 | 118 | =over 4 119 | 120 | =item I 121 | 122 | Are we setting downtime for a host or a service? 123 | 124 | =item I 125 | 126 | Hostname of the host or service. 127 | 128 | =item [I] 129 | 130 | Service name of the service (only necessary for service requests). 131 | 132 | =item I 133 | 134 | How many hours should the downtime last? 135 | 136 | =item I 137 | 138 | Some explanatory text. 139 | 140 | =back 141 | 142 | =head2 OPTIONS 143 | 144 | =over 4 145 | 146 | =item B<--debug> 147 | 148 | If set, print debugging information. 149 | 150 | =item B<--apikey> I 151 | 152 | Password for the API User. Default: comes from the configuration file. 153 | 154 | =item B<--remove> 155 | 156 | If set, remove an existing downtime instead of creating a new one. 157 | 158 | =item B<--server> I 159 | 160 | Host name of the server. Default: comes from the configuration file. 161 | 162 | =item B<--site> I 163 | 164 | Site name within the server. Default: comes from the configuration file. 165 | 166 | =item B<--user> I 167 | 168 | API User name. The user must exist on the server, and be an 'automation 169 | user'. Default: comes from the configuration file. 170 | 171 | =back 172 | 173 | =head1 FILES 174 | 175 | =over 4 176 | 177 | =item F 178 | 179 | =back 180 | 181 | =head1 SEE ALSO 182 | 183 | https://mathias-kettner.de/checkmk_wato_webapi.html 184 | 185 | =head1 AUTHOR 186 | 187 | Tim Skirvin 188 | 189 | =head1 LICENSE + COPYRIGHT 190 | 191 | Copyright 2015, Fermi National Accelerator Laboratory 192 | 193 | This program is free software; you may redistribute it and/or modify it 194 | under the same terms as Perl itself. 195 | 196 | =cut 197 | 198 | """ 199 | -------------------------------------------------------------------------------- /man/man1/omd-reinventory.1: -------------------------------------------------------------------------------- 1 | .\" Automatically generated by Pod::Man 4.07 (Pod::Simple 3.32) 2 | .\" 3 | .\" Standard preamble: 4 | .\" ======================================================================== 5 | .de Sp \" Vertical space (when we can't use .PP) 6 | .if t .sp .5v 7 | .if n .sp 8 | .. 9 | .de Vb \" Begin verbatim text 10 | .ft CW 11 | .nf 12 | .ne \\$1 13 | .. 14 | .de Ve \" End verbatim text 15 | .ft R 16 | .fi 17 | .. 18 | .\" Set up some character translations and predefined strings. \*(-- will 19 | .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left 20 | .\" double quote, and \*(R" will give a right double quote. \*(C+ will 21 | .\" give a nicer C++. Capital omega is used to do unbreakable dashes and 22 | .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, 23 | .\" nothing in troff, for use with C<>. 24 | .tr \(*W- 25 | .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' 26 | .ie n \{\ 27 | . ds -- \(*W- 28 | . ds PI pi 29 | . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch 30 | . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch 31 | . ds L" "" 32 | . ds R" "" 33 | . ds C` "" 34 | . ds C' "" 35 | 'br\} 36 | .el\{\ 37 | . ds -- \|\(em\| 38 | . ds PI \(*p 39 | . ds L" `` 40 | . ds R" '' 41 | . ds C` 42 | . ds C' 43 | 'br\} 44 | .\" 45 | .\" Escape single quotes in literal strings from groff's Unicode transform. 46 | .ie \n(.g .ds Aq \(aq 47 | .el .ds Aq ' 48 | .\" 49 | .\" If the F register is >0, we'll generate index entries on stderr for 50 | .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index 51 | .\" entries marked with X<> in POD. Of course, you'll have to process the 52 | .\" output yourself in some meaningful fashion. 53 | .\" 54 | .\" Avoid warning from groff about undefined register 'F'. 55 | .de IX 56 | .. 57 | .if !\nF .nr F 0 58 | .if \nF>0 \{\ 59 | . de IX 60 | . tm Index:\\$1\t\\n%\t"\\$2" 61 | .. 62 | . if !\nF==2 \{\ 63 | . nr % 0 64 | . nr F 2 65 | . \} 66 | .\} 67 | .\" 68 | .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). 69 | .\" Fear. Run. Save yourself. No user-serviceable parts. 70 | . \" fudge factors for nroff and troff 71 | .if n \{\ 72 | . ds #H 0 73 | . ds #V .8m 74 | . ds #F .3m 75 | . ds #[ \f1 76 | . ds #] \fP 77 | .\} 78 | .if t \{\ 79 | . ds #H ((1u-(\\\\n(.fu%2u))*.13m) 80 | . ds #V .6m 81 | . ds #F 0 82 | . ds #[ \& 83 | . ds #] \& 84 | .\} 85 | . \" simple accents for nroff and troff 86 | .if n \{\ 87 | . ds ' \& 88 | . ds ` \& 89 | . ds ^ \& 90 | . ds , \& 91 | . ds ~ ~ 92 | . ds / 93 | .\} 94 | .if t \{\ 95 | . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" 96 | . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' 97 | . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' 98 | . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' 99 | . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' 100 | . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' 101 | .\} 102 | . \" troff and (daisy-wheel) nroff accents 103 | .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' 104 | .ds 8 \h'\*(#H'\(*b\h'-\*(#H' 105 | .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] 106 | .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' 107 | .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' 108 | .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] 109 | .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] 110 | .ds ae a\h'-(\w'a'u*4/10)'e 111 | .ds Ae A\h'-(\w'A'u*4/10)'E 112 | . \" corrections for vroff 113 | .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' 114 | .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' 115 | . \" for low resolution devices (crt and lpr) 116 | .if \n(.H>23 .if \n(.V>19 \ 117 | \{\ 118 | . ds : e 119 | . ds 8 ss 120 | . ds o a 121 | . ds d- d\h'-1'\(ga 122 | . ds D- D\h'-1'\(hy 123 | . ds th \o'bp' 124 | . ds Th \o'LP' 125 | . ds ae ae 126 | . ds Ae AE 127 | .\} 128 | .rm #[ #] #H #V #F C 129 | .\" ======================================================================== 130 | .\" 131 | .IX Title "OMD-REINVENTORY 1" 132 | .TH OMD-REINVENTORY 1 "2017-12-04" "perl v5.24.1" "User Contributed Perl Documentation" 133 | .\" For nroff, turn off justification. Always turn off hyphenation; it makes 134 | .\" way too many mistakes in technical documents. 135 | .if n .ad l 136 | .nh 137 | .SH "NAME" 138 | omd\-reinventory \- reinventory a given node (or nodes) 139 | .SH "SYNOPSIS" 140 | .IX Header "SYNOPSIS" 141 | \&\fBomd-reinventory\fR \s-1HOSTNAME\s0 [\s-1HOSTNAME\s0] 142 | .SH "USAGE" 143 | .IX Header "USAGE" 144 | omd-reinventory runs an inventory on a host or list of hosts. 145 | .SH "ARGUMENTS" 146 | .IX Header "ARGUMENTS" 147 | .IP "\fB\-\-debug\fR" 4 148 | .IX Item "--debug" 149 | If set, print debugging information. 150 | .IP "\fB\-\-apikey\fR \fIkey\fR" 4 151 | .IX Item "--apikey key" 152 | Password for the \s-1API\s0 User. Default: comes from the configuration file. 153 | .IP "\fB\-\-server\fR \fIserver\fR" 4 154 | .IX Item "--server server" 155 | Host name of the server. Default: comes from the configuration file. 156 | .IP "\fB\-\-site\fR \fIsite\fR" 4 157 | .IX Item "--site site" 158 | Site name within the server. Default: comes from the configuration file. 159 | .IP "\fB\-\-user\fR \fIuser\fR" 4 160 | .IX Item "--user user" 161 | \&\s-1API\s0 User name. The user must exist on the server, and be an 'automation 162 | user'. Default: comes from the configuration file. 163 | .SH "FILES" 164 | .IX Header "FILES" 165 | .IP "\fI/etc/omdclient/config.yaml\fR" 4 166 | .IX Item "/etc/omdclient/config.yaml" 167 | .SH "SEE ALSO" 168 | .IX Header "SEE ALSO" 169 | https://mathias\-kettner.de/checkmk_wato_webapi.html 170 | .SH "AUTHOR" 171 | .IX Header "AUTHOR" 172 | Tim Skirvin 173 | .SH "LICENSE + COPYRIGHT" 174 | .IX Header "LICENSE + COPYRIGHT" 175 | Copyright 2016, Fermi National Accelerator Laboratory 176 | .PP 177 | This program is free software; you may redistribute it and/or modify it 178 | under the same terms as Perl itself. 179 | -------------------------------------------------------------------------------- /man/man1/omd-nagios-report.1: -------------------------------------------------------------------------------- 1 | .\" Automatically generated by Pod::Man 4.07 (Pod::Simple 3.32) 2 | .\" 3 | .\" Standard preamble: 4 | .\" ======================================================================== 5 | .de Sp \" Vertical space (when we can't use .PP) 6 | .if t .sp .5v 7 | .if n .sp 8 | .. 9 | .de Vb \" Begin verbatim text 10 | .ft CW 11 | .nf 12 | .ne \\$1 13 | .. 14 | .de Ve \" End verbatim text 15 | .ft R 16 | .fi 17 | .. 18 | .\" Set up some character translations and predefined strings. \*(-- will 19 | .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left 20 | .\" double quote, and \*(R" will give a right double quote. \*(C+ will 21 | .\" give a nicer C++. Capital omega is used to do unbreakable dashes and 22 | .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, 23 | .\" nothing in troff, for use with C<>. 24 | .tr \(*W- 25 | .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' 26 | .ie n \{\ 27 | . ds -- \(*W- 28 | . ds PI pi 29 | . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch 30 | . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch 31 | . ds L" "" 32 | . ds R" "" 33 | . ds C` "" 34 | . ds C' "" 35 | 'br\} 36 | .el\{\ 37 | . ds -- \|\(em\| 38 | . ds PI \(*p 39 | . ds L" `` 40 | . ds R" '' 41 | . ds C` 42 | . ds C' 43 | 'br\} 44 | .\" 45 | .\" Escape single quotes in literal strings from groff's Unicode transform. 46 | .ie \n(.g .ds Aq \(aq 47 | .el .ds Aq ' 48 | .\" 49 | .\" If the F register is >0, we'll generate index entries on stderr for 50 | .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index 51 | .\" entries marked with X<> in POD. Of course, you'll have to process the 52 | .\" output yourself in some meaningful fashion. 53 | .\" 54 | .\" Avoid warning from groff about undefined register 'F'. 55 | .de IX 56 | .. 57 | .if !\nF .nr F 0 58 | .if \nF>0 \{\ 59 | . de IX 60 | . tm Index:\\$1\t\\n%\t"\\$2" 61 | .. 62 | . if !\nF==2 \{\ 63 | . nr % 0 64 | . nr F 2 65 | . \} 66 | .\} 67 | .\" 68 | .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). 69 | .\" Fear. Run. Save yourself. No user-serviceable parts. 70 | . \" fudge factors for nroff and troff 71 | .if n \{\ 72 | . ds #H 0 73 | . ds #V .8m 74 | . ds #F .3m 75 | . ds #[ \f1 76 | . ds #] \fP 77 | .\} 78 | .if t \{\ 79 | . ds #H ((1u-(\\\\n(.fu%2u))*.13m) 80 | . ds #V .6m 81 | . ds #F 0 82 | . ds #[ \& 83 | . ds #] \& 84 | .\} 85 | . \" simple accents for nroff and troff 86 | .if n \{\ 87 | . ds ' \& 88 | . ds ` \& 89 | . ds ^ \& 90 | . ds , \& 91 | . ds ~ ~ 92 | . ds / 93 | .\} 94 | .if t \{\ 95 | . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" 96 | . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' 97 | . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' 98 | . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' 99 | . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' 100 | . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' 101 | .\} 102 | . \" troff and (daisy-wheel) nroff accents 103 | .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' 104 | .ds 8 \h'\*(#H'\(*b\h'-\*(#H' 105 | .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] 106 | .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' 107 | .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' 108 | .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] 109 | .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] 110 | .ds ae a\h'-(\w'a'u*4/10)'e 111 | .ds Ae A\h'-(\w'A'u*4/10)'E 112 | . \" corrections for vroff 113 | .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' 114 | .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' 115 | . \" for low resolution devices (crt and lpr) 116 | .if \n(.H>23 .if \n(.V>19 \ 117 | \{\ 118 | . ds : e 119 | . ds 8 ss 120 | . ds o a 121 | . ds d- d\h'-1'\(ga 122 | . ds D- D\h'-1'\(hy 123 | . ds th \o'bp' 124 | . ds Th \o'LP' 125 | . ds ae ae 126 | . ds Ae AE 127 | .\} 128 | .rm #[ #] #H #V #F C 129 | .\" ======================================================================== 130 | .\" 131 | .IX Title "OMD-NAGIOS-REPORT 1" 132 | .TH OMD-NAGIOS-REPORT 1 "2017-12-04" "perl v5.24.1" "User Contributed Perl Documentation" 133 | .\" For nroff, turn off justification. Always turn off hyphenation; it makes 134 | .\" way too many mistakes in technical documents. 135 | .if n .ad l 136 | .nh 137 | .SH "NAME" 138 | omd\-nagios\-report \- prints a report of all open host and service alerts 139 | .SH "SYNOPSIS" 140 | .IX Header "SYNOPSIS" 141 | \&\fBomd-nagios-report\fR 142 | .SH "USAGE" 143 | .IX Header "USAGE" 144 | omd-nagios-report prints a report om all acknowledged and unacknowledged 145 | host and service alerts associated with the given server and site. 146 | .SH "ARGUMENTS" 147 | .IX Header "ARGUMENTS" 148 | .IP "\fB\-\-debug\fR" 4 149 | .IX Item "--debug" 150 | If set, print debugging information. 151 | .IP "\fB\-\-apikey\fR \fIkey\fR" 4 152 | .IX Item "--apikey key" 153 | Password for the \s-1API\s0 User. Default: comes from the configuration file. 154 | .IP "\fB\-\-server\fR \fIserver\fR" 4 155 | .IX Item "--server server" 156 | Host name of the server. Default: comes from the configuration file. 157 | .IP "\fB\-\-site\fR \fIsite\fR" 4 158 | .IX Item "--site site" 159 | Site name within the server. Default: comes from the configuration file. 160 | .IP "\fB\-\-user\fR \fIuser\fR" 4 161 | .IX Item "--user user" 162 | \&\s-1API\s0 User name. The user must exist on the server, and be an 'automation 163 | user'. Default: comes from the configuration file. 164 | .SH "FILES" 165 | .IX Header "FILES" 166 | .IP "\fI/etc/omdclient/config.yaml\fR" 4 167 | .IX Item "/etc/omdclient/config.yaml" 168 | .SH "SEE ALSO" 169 | .IX Header "SEE ALSO" 170 | https://mathias\-kettner.de/checkmk_wato_webapi.html 171 | .SH "AUTHOR" 172 | .IX Header "AUTHOR" 173 | Tim Skirvin 174 | .SH "LICENSE + COPYRIGHT" 175 | .IX Header "LICENSE + COPYRIGHT" 176 | Copyright 2015, Fermi National Accelerator Laboratory 177 | .PP 178 | This program is free software; you may redistribute it and/or modify it 179 | under the same terms as Perl itself. 180 | -------------------------------------------------------------------------------- /man/man1/omd-activate.1: -------------------------------------------------------------------------------- 1 | .\" Automatically generated by Pod::Man 4.07 (Pod::Simple 3.32) 2 | .\" 3 | .\" Standard preamble: 4 | .\" ======================================================================== 5 | .de Sp \" Vertical space (when we can't use .PP) 6 | .if t .sp .5v 7 | .if n .sp 8 | .. 9 | .de Vb \" Begin verbatim text 10 | .ft CW 11 | .nf 12 | .ne \\$1 13 | .. 14 | .de Ve \" End verbatim text 15 | .ft R 16 | .fi 17 | .. 18 | .\" Set up some character translations and predefined strings. \*(-- will 19 | .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left 20 | .\" double quote, and \*(R" will give a right double quote. \*(C+ will 21 | .\" give a nicer C++. Capital omega is used to do unbreakable dashes and 22 | .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, 23 | .\" nothing in troff, for use with C<>. 24 | .tr \(*W- 25 | .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' 26 | .ie n \{\ 27 | . ds -- \(*W- 28 | . ds PI pi 29 | . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch 30 | . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch 31 | . ds L" "" 32 | . ds R" "" 33 | . ds C` "" 34 | . ds C' "" 35 | 'br\} 36 | .el\{\ 37 | . ds -- \|\(em\| 38 | . ds PI \(*p 39 | . ds L" `` 40 | . ds R" '' 41 | . ds C` 42 | . ds C' 43 | 'br\} 44 | .\" 45 | .\" Escape single quotes in literal strings from groff's Unicode transform. 46 | .ie \n(.g .ds Aq \(aq 47 | .el .ds Aq ' 48 | .\" 49 | .\" If the F register is >0, we'll generate index entries on stderr for 50 | .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index 51 | .\" entries marked with X<> in POD. Of course, you'll have to process the 52 | .\" output yourself in some meaningful fashion. 53 | .\" 54 | .\" Avoid warning from groff about undefined register 'F'. 55 | .de IX 56 | .. 57 | .if !\nF .nr F 0 58 | .if \nF>0 \{\ 59 | . de IX 60 | . tm Index:\\$1\t\\n%\t"\\$2" 61 | .. 62 | . if !\nF==2 \{\ 63 | . nr % 0 64 | . nr F 2 65 | . \} 66 | .\} 67 | .\" 68 | .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). 69 | .\" Fear. Run. Save yourself. No user-serviceable parts. 70 | . \" fudge factors for nroff and troff 71 | .if n \{\ 72 | . ds #H 0 73 | . ds #V .8m 74 | . ds #F .3m 75 | . ds #[ \f1 76 | . ds #] \fP 77 | .\} 78 | .if t \{\ 79 | . ds #H ((1u-(\\\\n(.fu%2u))*.13m) 80 | . ds #V .6m 81 | . ds #F 0 82 | . ds #[ \& 83 | . ds #] \& 84 | .\} 85 | . \" simple accents for nroff and troff 86 | .if n \{\ 87 | . ds ' \& 88 | . ds ` \& 89 | . ds ^ \& 90 | . ds , \& 91 | . ds ~ ~ 92 | . ds / 93 | .\} 94 | .if t \{\ 95 | . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" 96 | . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' 97 | . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' 98 | . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' 99 | . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' 100 | . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' 101 | .\} 102 | . \" troff and (daisy-wheel) nroff accents 103 | .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' 104 | .ds 8 \h'\*(#H'\(*b\h'-\*(#H' 105 | .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] 106 | .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' 107 | .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' 108 | .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] 109 | .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] 110 | .ds ae a\h'-(\w'a'u*4/10)'e 111 | .ds Ae A\h'-(\w'A'u*4/10)'E 112 | . \" corrections for vroff 113 | .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' 114 | .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' 115 | . \" for low resolution devices (crt and lpr) 116 | .if \n(.H>23 .if \n(.V>19 \ 117 | \{\ 118 | . ds : e 119 | . ds 8 ss 120 | . ds o a 121 | . ds d- d\h'-1'\(ga 122 | . ds D- D\h'-1'\(hy 123 | . ds th \o'bp' 124 | . ds Th \o'LP' 125 | . ds ae ae 126 | . ds Ae AE 127 | .\} 128 | .rm #[ #] #H #V #F C 129 | .\" ======================================================================== 130 | .\" 131 | .IX Title "OMD-ACTIVATE 1" 132 | .TH OMD-ACTIVATE 1 "2017-12-04" "perl v5.24.1" "User Contributed Perl Documentation" 133 | .\" For nroff, turn off justification. Always turn off hyphenation; it makes 134 | .\" way too many mistakes in technical documents. 135 | .if n .ad l 136 | .nh 137 | .SH "NAME" 138 | omd\-activate \- activate changes on the OMD site 139 | .SH "SYNOPSIS" 140 | .IX Header "SYNOPSIS" 141 | \&\fBomd-activate\fR 142 | .SH "USAGE" 143 | .IX Header "USAGE" 144 | omd-activate simply activates the changes that were made in other scripts. 145 | It generally takes a long time to run, and (sometimes) get back a 503 http 146 | error because of how long it takes. 147 | .SH "ARGUMENTS" 148 | .IX Header "ARGUMENTS" 149 | .IP "\fB\-\-debug\fR" 4 150 | .IX Item "--debug" 151 | If set, print debugging information. 152 | .IP "\fB\-\-apikey\fR \fIkey\fR" 4 153 | .IX Item "--apikey key" 154 | Password for the \s-1API\s0 User. Default: comes from the configuration file. 155 | .IP "\fB\-\-server\fR \fIserver\fR" 4 156 | .IX Item "--server server" 157 | Host name of the server. Default: comes from the configuration file. 158 | .IP "\fB\-\-site\fR \fIsite\fR" 4 159 | .IX Item "--site site" 160 | Site name within the server. Default: comes from the configuration file. 161 | .IP "\fB\-\-user\fR \fIuser\fR" 4 162 | .IX Item "--user user" 163 | \&\s-1API\s0 User name. The user must exist on the server, and be an 'automation 164 | user'. Default: comes from the configuration file. 165 | .SH "FILES" 166 | .IX Header "FILES" 167 | .IP "\fI/etc/omdclient/config.yaml\fR" 4 168 | .IX Item "/etc/omdclient/config.yaml" 169 | .SH "SEE ALSO" 170 | .IX Header "SEE ALSO" 171 | https://mathias\-kettner.de/checkmk_wato_webapi.html 172 | .SH "AUTHOR" 173 | .IX Header "AUTHOR" 174 | Tim Skirvin 175 | .SH "LICENSE + COPYRIGHT" 176 | .IX Header "LICENSE + COPYRIGHT" 177 | Copyright 2015, Fermi National Accelerator Laboratory 178 | .PP 179 | This program is free software; you may redistribute it and/or modify it 180 | under the same terms as Perl itself. 181 | -------------------------------------------------------------------------------- /usr/bin/omd-bulkimport: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | Bulk import hosts into OMD from STDIN. 4 | """ 5 | 6 | ######################################################################### 7 | ### Declarations ######################################################## 8 | ######################################################################### 9 | 10 | import omdclient, optparse, os, socket, sys 11 | 12 | ######################################################################### 13 | ### Configuration ####################################################### 14 | ######################################################################### 15 | 16 | ## Central configuration file. 17 | config_file_base = '/etc/omdclient/config.yaml' 18 | 19 | ## Default values for role/instance/extra for create/update. 20 | folder = 'UNSET' 21 | 22 | ## Text for --help 23 | text = "Bulk host import for OMD, using the WATO API" 24 | usage_text = "usage: %prog [options] < HOSTLIST" 25 | 26 | ######################################################################### 27 | ### Subroutines ######################################################### 28 | ######################################################################### 29 | 30 | ######################################################################### 31 | ### main () ############################################################# 32 | ######################################################################### 33 | 34 | def main(): 35 | config_file = os.environ.get('OMDCONFIG', config_file_base) 36 | try: 37 | config = omdclient.loadCfg(config_file) 38 | except Exception as e: 39 | print("failed to load config: %s" % (e)) 40 | sys.exit(3) 41 | 42 | p = omdclient.generateParser(text, usage_text, config) 43 | group = optparse.OptionGroup(p, 'create/update options') 44 | group.add_option('--no_check_dns', dest='check_dns', default=True, 45 | action='store_false', 46 | help='check DNS before adding hosts? (default: %default)') 47 | group.add_option('--noop', dest='noop', default=False, action='store_true', 48 | help='take no actions (default: %default)') 49 | p.add_option_group(group) 50 | opt, args = p.parse_args() 51 | 52 | argdict = omdclient.parserArgDict(opt) 53 | 54 | if len(args) != 1: 55 | p.print_help() 56 | sys.exit(1) 57 | 58 | folder = args[0] 59 | 60 | hosts = [] 61 | for line in sys.stdin: 62 | host = line.rstrip() 63 | try: 64 | if socket.gethostbyname(host): 65 | hosts.append(host) 66 | else: 67 | print("host %s does not exist in DNS, skipping" % host) 68 | if not opt.check_dns: hosts.append(host) 69 | except socket.gaierror as e: 70 | print("error looking up host %s: %s" % (host, e)) 71 | if not opt.check_dns: hosts.append(host) 72 | except Exception as e: 73 | print("error looking up host %s: %s" % (host, e)) 74 | if not opt.check_dns: hosts.append(host) 75 | 76 | ret, omdhostlist = omdclient.listHosts(argdict) 77 | for host in hosts: 78 | if host in omdhostlist: 79 | h = omdhostlist[host] 80 | if 'path' in h and h['path'] == folder: 81 | if opt.debug: 82 | print("%s: already in folder %s, skipping" % (host, folder)) 83 | pass 84 | 85 | elif 'path' in h: 86 | if opt.noop: 87 | print("%s: was in folder %s, would delete/re-add to %s (noop)" % (host, h['path'], folder)) 88 | else: 89 | print("%s: was in folder %s, delete/re-add to %s" % (host, h['path'], folder)) 90 | new = argdict 91 | new['folder'] = folder 92 | 93 | omdclient.deleteHost(host, argdict) 94 | omdclient.createHost(host, new) 95 | 96 | else: 97 | if opt.noop: 98 | print("%s: would add to folder %s (noop)" % (host, folder)) 99 | else: 100 | print("%s: adding to folder %s" % (host, folder)) 101 | new = argdict 102 | new['folder'] = folder 103 | omdclient.createHost(host, new) 104 | 105 | if __name__ == "__main__": 106 | main() 107 | 108 | ######################################################################### 109 | ### POD Documentation ################################################### 110 | ######################################################################### 111 | 112 | """ 113 | 114 | =head1 NAME 115 | 116 | omd-bulkimport - import hosts into a given folder 117 | 118 | =head1 SYNOPSIS 119 | 120 | B --folder FOLDER < HOST_LIST 121 | 122 | =head1 USAGE 123 | 124 | Takes a list of hosts on STDIN and assigns all of them to the given folder 125 | F. 126 | 127 | =head1 ARGUMENTS 128 | 129 | =over 4 130 | 131 | =item B<--no_check_dns> 132 | 133 | If set, add the hsots even without checking DNS first to see if it exists. 134 | 135 | =item B<--noop> 136 | 137 | =back 138 | 139 | =head2 DEFAULT 140 | 141 | =over 4 142 | 143 | =item B<--debug> 144 | 145 | If set, print debugging information. 146 | 147 | =item B<--help> 148 | 149 | Print this information and exit. 150 | 151 | =back 152 | 153 | =head2 CONNECTION OPTIONS 154 | 155 | =over 4 156 | 157 | =item B<--apikey> I 158 | 159 | Password for the API User. Default: comes from the configuration file. 160 | 161 | =item B<--server> I 162 | 163 | Host name of the server. Default: comes from the configuration file. 164 | 165 | =item B<--site> I 166 | 167 | Site name within the server. Default: comes from the configuration file. 168 | 169 | =item B<--user> I 170 | 171 | API User name. The user must exist on the server, and be an 'automation 172 | user'. Default: comes from the configuration file. 173 | 174 | =back 175 | 176 | =head1 FILES 177 | 178 | =over 4 179 | 180 | =item F 181 | 182 | =back 183 | 184 | =head1 SEE ALSO 185 | 186 | https://mathias-kettner.de/checkmk_wato_webapi.html 187 | 188 | =head1 AUTHOR 189 | 190 | Tim Skirvin 191 | 192 | =head1 LICENSE + COPYRIGHT 193 | 194 | Copyright 2019, Fermi National Accelerator Laboratory 195 | 196 | This program is free software; you may redistribute it and/or modify it 197 | under the same terms as Perl itself. 198 | 199 | =cut 200 | 201 | """ 202 | -------------------------------------------------------------------------------- /man/man1/omd-nagios-hostlist.1: -------------------------------------------------------------------------------- 1 | .\" Automatically generated by Pod::Man 4.07 (Pod::Simple 3.32) 2 | .\" 3 | .\" Standard preamble: 4 | .\" ======================================================================== 5 | .de Sp \" Vertical space (when we can't use .PP) 6 | .if t .sp .5v 7 | .if n .sp 8 | .. 9 | .de Vb \" Begin verbatim text 10 | .ft CW 11 | .nf 12 | .ne \\$1 13 | .. 14 | .de Ve \" End verbatim text 15 | .ft R 16 | .fi 17 | .. 18 | .\" Set up some character translations and predefined strings. \*(-- will 19 | .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left 20 | .\" double quote, and \*(R" will give a right double quote. \*(C+ will 21 | .\" give a nicer C++. Capital omega is used to do unbreakable dashes and 22 | .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, 23 | .\" nothing in troff, for use with C<>. 24 | .tr \(*W- 25 | .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' 26 | .ie n \{\ 27 | . ds -- \(*W- 28 | . ds PI pi 29 | . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch 30 | . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch 31 | . ds L" "" 32 | . ds R" "" 33 | . ds C` "" 34 | . ds C' "" 35 | 'br\} 36 | .el\{\ 37 | . ds -- \|\(em\| 38 | . ds PI \(*p 39 | . ds L" `` 40 | . ds R" '' 41 | . ds C` 42 | . ds C' 43 | 'br\} 44 | .\" 45 | .\" Escape single quotes in literal strings from groff's Unicode transform. 46 | .ie \n(.g .ds Aq \(aq 47 | .el .ds Aq ' 48 | .\" 49 | .\" If the F register is >0, we'll generate index entries on stderr for 50 | .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index 51 | .\" entries marked with X<> in POD. Of course, you'll have to process the 52 | .\" output yourself in some meaningful fashion. 53 | .\" 54 | .\" Avoid warning from groff about undefined register 'F'. 55 | .de IX 56 | .. 57 | .if !\nF .nr F 0 58 | .if \nF>0 \{\ 59 | . de IX 60 | . tm Index:\\$1\t\\n%\t"\\$2" 61 | .. 62 | . if !\nF==2 \{\ 63 | . nr % 0 64 | . nr F 2 65 | . \} 66 | .\} 67 | .\" 68 | .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). 69 | .\" Fear. Run. Save yourself. No user-serviceable parts. 70 | . \" fudge factors for nroff and troff 71 | .if n \{\ 72 | . ds #H 0 73 | . ds #V .8m 74 | . ds #F .3m 75 | . ds #[ \f1 76 | . ds #] \fP 77 | .\} 78 | .if t \{\ 79 | . ds #H ((1u-(\\\\n(.fu%2u))*.13m) 80 | . ds #V .6m 81 | . ds #F 0 82 | . ds #[ \& 83 | . ds #] \& 84 | .\} 85 | . \" simple accents for nroff and troff 86 | .if n \{\ 87 | . ds ' \& 88 | . ds ` \& 89 | . ds ^ \& 90 | . ds , \& 91 | . ds ~ ~ 92 | . ds / 93 | .\} 94 | .if t \{\ 95 | . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" 96 | . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' 97 | . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' 98 | . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' 99 | . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' 100 | . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' 101 | .\} 102 | . \" troff and (daisy-wheel) nroff accents 103 | .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' 104 | .ds 8 \h'\*(#H'\(*b\h'-\*(#H' 105 | .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] 106 | .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' 107 | .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' 108 | .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] 109 | .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] 110 | .ds ae a\h'-(\w'a'u*4/10)'e 111 | .ds Ae A\h'-(\w'A'u*4/10)'E 112 | . \" corrections for vroff 113 | .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' 114 | .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' 115 | . \" for low resolution devices (crt and lpr) 116 | .if \n(.H>23 .if \n(.V>19 \ 117 | \{\ 118 | . ds : e 119 | . ds 8 ss 120 | . ds o a 121 | . ds d- d\h'-1'\(ga 122 | . ds D- D\h'-1'\(hy 123 | . ds th \o'bp' 124 | . ds Th \o'LP' 125 | . ds ae ae 126 | . ds Ae AE 127 | .\} 128 | .rm #[ #] #H #V #F C 129 | .\" ======================================================================== 130 | .\" 131 | .IX Title "OMD-NAGIOS-HOSTLIST 1" 132 | .TH OMD-NAGIOS-HOSTLIST 1 "2017-12-04" "perl v5.24.1" "User Contributed Perl Documentation" 133 | .\" For nroff, turn off justification. Always turn off hyphenation; it makes 134 | .\" way too many mistakes in technical documents. 135 | .if n .ad l 136 | .nh 137 | .SH "NAME" 138 | omd\-nagios\-hostlist \- list all hosts in nagios 139 | .SH "SYNOPSIS" 140 | .IX Header "SYNOPSIS" 141 | \&\fBomd-nagios-hostlist\fR 142 | .SH "USAGE" 143 | .IX Header "USAGE" 144 | omd-nagios-hostlist pulls the list of monitored hosts from check_mk and 145 | prints them to \s-1STDOUT.\s0 146 | .SH "ARGUMENTS" 147 | .IX Header "ARGUMENTS" 148 | .SS "\s-1DEFAULT\s0" 149 | .IX Subsection "DEFAULT" 150 | .IP "\fB\-\-debug\fR" 4 151 | .IX Item "--debug" 152 | If set, print debugging information. 153 | .IP "\fB\-\-help\fR" 4 154 | .IX Item "--help" 155 | Print this information and exit. 156 | .IP "\fB\-\-filter\-site\fR" 4 157 | .IX Item "--filter-site" 158 | Filter host by site monitored. Default: disabled 159 | .SS "\s-1CONNECTION OPTIONS\s0" 160 | .IX Subsection "CONNECTION OPTIONS" 161 | .IP "\fB\-\-apikey\fR \fIkey\fR" 4 162 | .IX Item "--apikey key" 163 | Password for the \s-1API\s0 User. Default: comes from the configuration file. 164 | .IP "\fB\-\-server\fR \fIserver\fR" 4 165 | .IX Item "--server server" 166 | Host name of the server. Default: comes from the configuration file. 167 | .IP "\fB\-\-site\fR \fIsite\fR" 4 168 | .IX Item "--site site" 169 | Site name within the server. Default: comes from the configuration file. 170 | .IP "\fB\-\-user\fR \fIuser\fR" 4 171 | .IX Item "--user user" 172 | \&\s-1API\s0 User name. The user must exist on the server, and be an 'automation 173 | user'. Default: comes from the configuration file. 174 | .SH "FILES" 175 | .IX Header "FILES" 176 | .IP "\fI/etc/omdclient/config.yaml\fR" 4 177 | .IX Item "/etc/omdclient/config.yaml" 178 | .SH "SEE ALSO" 179 | .IX Header "SEE ALSO" 180 | https://mathias\-kettner.de/checkmk_wato_webapi.html 181 | .SH "AUTHOR" 182 | .IX Header "AUTHOR" 183 | Tim Skirvin 184 | .SH "LICENSE + COPYRIGHT" 185 | .IX Header "LICENSE + COPYRIGHT" 186 | Copyright 2017, Fermi National Accelerator Laboratory 187 | .PP 188 | This program is free software; you may redistribute it and/or modify it 189 | under the same terms as Perl itself. 190 | -------------------------------------------------------------------------------- /omdclient.spec: -------------------------------------------------------------------------------- 1 | Name: omdclient 2 | Group: System Environment/Libraries 3 | Version: 1.4.4 4 | Release: 0%{?dist} 5 | Summary: OMD/WATO API check_mk connection tools for puppet 6 | URL: http://github.com/tskirvin/omdclient.git 7 | 8 | License: Artistic 2.0 9 | BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) 10 | BuildArch: noarch 11 | 12 | %if 0%{?rhel} >= 8 13 | Requires: rsync shyaml python3-beautifulsoup4 python3-requests 14 | BuildRequires: rsync python3 python3-setuptools python3-rpm-macros perl-podlators 15 | %else 16 | Requires: rsync shyaml moreutils python36-beautifulsoup4 python36-requests 17 | BuildRequires: rsync python36 python3-setuptools python3-rpm-macros perl-podlators 18 | %endif 19 | 20 | Source: omdclient-%{version}-%{release}.tar.gz 21 | 22 | %description 23 | Tools to interact with the OMD/WATO API for check_mk, and to tie them 24 | into puppet. 25 | 26 | %prep 27 | %setup -q -c -n omdclient 28 | 29 | %build 30 | # Empty build section added per rpmlint 31 | 32 | %install 33 | if [[ $RPM_BUILD_ROOT != "/" ]]; then 34 | rm -rf $RPM_BUILD_ROOT 35 | fi 36 | 37 | for i in etc usr; do 38 | rsync -Crlpt --delete ./${i} ${RPM_BUILD_ROOT} 39 | done 40 | 41 | for i in bin sbin; do 42 | if [ -d ${RPM_BUILD_ROOT}/$i ]; then 43 | chmod 0755 ${RPM_BUILD_ROOT}/${i} 44 | fi 45 | done 46 | 47 | mkdir -p ${RPM_BUILD_ROOT}/usr/share/man/man1 48 | for i in `ls usr/bin`; do 49 | pod2man --section 1 --center="System Commands" usr/bin/${i} \ 50 | > ${RPM_BUILD_ROOT}/usr/share/man/man1/${i}.1 ; 51 | done 52 | 53 | python3 setup.py install --prefix=${RPM_BUILD_ROOT}/usr \ 54 | --single-version-externally-managed --record=installed_files 55 | 56 | %clean 57 | # Adding empty clean section per rpmlint. 58 | 59 | %files 60 | %defattr(-,root,root) 61 | %config(noreplace) /etc/omdclient/config.yaml 62 | %config(noreplace) /etc/omdclient/place.holder 63 | %{_bindir}/omd-* 64 | /usr/share/man/man1/* 65 | /usr/libexec/omdclient/git-hooks/* 66 | %{python3_sitelib}/omdclient/*py* 67 | %{python3_sitelib}/*egg-info 68 | /etc/omdclient/* 69 | 70 | %changelog 71 | * Thu Feb 20 2025 Tim Skirvin 1.4.4-0 72 | - added omd-nagios-client 73 | 74 | * Thu Sep 15 2022 Tim Skirvin 1.4.3-0 75 | - __init__.py - loadCfg() fixes, uses safe_load() and a fixed exception now 76 | 77 | * Fri Aug 23 2019 Tim Skirvin 1.4.2-0 78 | - init.py - decoding output from urllib requests (fixes "failed to run: a 79 | bytes-like object is required, not 'str'" bug) 80 | 81 | * Mon Aug 19 2019 Tim Skirvin 1.4.1-0 82 | - flake8 python linting for all 83 | 84 | * Fri Aug 16 2019 Tim Skirvin 1.4.0-0 85 | - converting to python 3 86 | 87 | * Tue Mar 19 2019 Tim Skirvin 1.3.5-0 88 | - moving the changelog to CHANGELOG.md going forwards 89 | - generally re-working for distribution via pypi 90 | 91 | * Mon Mar 18 2019 Tim Skirvin 1.3.4-0 92 | - merging in previous 'mgusek' code 93 | 94 | * Mon Mar 18 2019 Tim Skirvin 1.3.3-4 95 | - tweaks support uploading to pypi.org 96 | 97 | * Wed Jan 09 2019 Tim Skirvin 1.3.3-1 98 | - omd-bulkimport - new script, does what it says on the tin 99 | 100 | * Mon Jan 07 2019 mgusek@github.com 1.3.2-1 101 | - omd-nagios-downtime: added '--remove' option to remove downtimes 102 | 103 | * Wed Dec 12 2018 Tim Skirvin 1.3.1-1 104 | - added OMDCONFIG support for all scripts so we can use multiple configs 105 | 106 | * Mon Apr 16 2018 Tim Skirvin 1.3.0-1 107 | - omd-nagios-activate - adding 'mode=dirty' to the URL 108 | 109 | * Tue Sep 26 2017 Tim Skirvin 1.2.0-2 110 | - adding RHEL7/SL7 support 111 | 112 | * Fri Sep 15 2017 Tim Skirvin 1.2.0-1 113 | - omd-host-tag - eliminating an extra print statement 114 | 115 | * Fri Sep 15 2017 Tim Skirvin 1.2.0-0 116 | - omd-host-crud - now prints all listed system tags 117 | - omd-host-tag - new script, set or unset tags for a given host 118 | - updateHost()'s unset_attributes bit should actually work now (tested as 119 | part of omd-host-tag) 120 | 121 | * Tue Sep 12 2017 Tim Skirvin 1.1.8-0 122 | - omd-host-crud - read functions only print relevant fields 123 | - listHostsFiltered() function - print hosts where the site matches 124 | 125 | * Fri Mar 24 2017 Tim Skirvin 1.1.7-0 126 | - omd-nagios-report - now deals with UTF-8 better 127 | 128 | * Fri Mar 24 2017 Tim Skirvin 1.1.6-0 129 | - omd-nagios-hostlist 130 | - some additional changes from epleterte involving IP addresses 131 | 132 | - omdclient/__init.py__ - inventories can now choose to do tabula rasa 133 | - omd-reinventory - allowed to select tabula rasa 134 | - omd-activate - allows us to activate foreign keys 135 | 136 | * Tue Jun 21 2016 Tim Skirvin 1.1.5-1 137 | - omdclient/__init.py__ - inventories can now choose to do tabula rasa 138 | - omd-reinventory - allowed to select tabula rasa 139 | - omd-activate - allows us to activate foreign keys 140 | 141 | * Tue Jun 21 2016 Tim Skirvin 1.1.5-0 142 | - omdclient/__init.py__ - inventories now do tabula rasa refresh 143 | 144 | * Tue Jun 21 2016 Tim Skirvin 1.1.4-0 145 | - omd-nagios-hosts-with-problem - discover hosts with a given problem 146 | - omd-reinventory - start a reinventory of a given host 147 | 148 | * Wed Jun 15 2016 Tim Skirvin 1.1.3-0 149 | - omd-nagos-report - skips errors on service prints rather than crashing 150 | - omdclient/__init__.py - actually sets downtimes now (I had the required 151 | date format wrong) 152 | 153 | * Thu Jun 25 2015 Tim Skirvin 1.1.2-0 154 | - omd-puppet-crud - adds 'inventory' option (kinda cheating) 155 | 156 | * Thu Jun 25 2015 Tim Skirvin 1.1.2-0 157 | - omd-puppet-enc - sends shyaml errors to stderr 158 | 159 | * Thu Jun 25 2015 Tim Skirvin 1.1.1-0 160 | - omd-puppet-enc - sends shyaml errors to stderr 161 | 162 | * Mon Jun 15 2015 Tim Skirvin 1.1.0-0 163 | - added omd-nagios-report, omd-nagios-ack, omd-nagios-downtime 164 | - fixed the git post-receive hook 165 | 166 | * Mon Jun 15 2015 Tim Skirvin 1.0.0-0 167 | - initial commit 168 | -------------------------------------------------------------------------------- /usr/bin/omd-host-report: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | Find hosts in Nagios that have a given problem. 4 | """ 5 | 6 | ######################################################################### 7 | ### Declarations ######################################################## 8 | ######################################################################### 9 | 10 | import omdclient, os, re, sys 11 | 12 | ######################################################################### 13 | ### Configuration ####################################################### 14 | ######################################################################### 15 | 16 | ## Central configuration file. 17 | config_file_base = '/etc/omdclient/config.yaml' 18 | 19 | ## Text for --help 20 | text = "Discover hosts with a given service problem, using the WATO API" 21 | usage_text = "usage: %prog PROBLEM [options]" 22 | 23 | ######################################################################### 24 | ### Subroutines ######################################################### 25 | ######################################################################### 26 | 27 | def printServiceStatusIfMatch(entry, opt): 28 | """ 29 | Print information from a svcproblems. If we get opt.verbose, then 30 | we'll print a longer string; otherwise, just print the host name. 31 | """ 32 | status = entry[0] 33 | host = entry[1] 34 | svc = entry[2] 35 | text = entry[4] 36 | 37 | if opt.verbose: text = "%s/%s: %s (%s)" % (host, svc, status, text) 38 | else: text = host 39 | 40 | print(text) 41 | 42 | # if status == 'CRIT': 43 | # if not opt.no_crit: print(text) 44 | # elif status == 'UNKN': 45 | # if not opt.no_unknown: print(text) 46 | # elif status == 'WARN': 47 | # if not opt.no_warn: print(text) 48 | 49 | ######################################################################### 50 | ### main () ############################################################# 51 | ######################################################################### 52 | 53 | def main(): 54 | config_file = os.environ.get('OMDCONFIG', config_file_base) 55 | try: 56 | config = omdclient.loadCfg(config_file) 57 | except Exception as e: 58 | print("failed to load config: %s" % (e)) 59 | sys.exit(3) 60 | 61 | p = omdclient.generateParser(text, usage_text, config) 62 | p.add_option('--verbose', dest='verbose', action="store_true", 63 | default=True, help='print more status information') 64 | opt, args = p.parse_args() 65 | 66 | argdict = omdclient.parserArgDict(opt) 67 | 68 | if len(args) != 1: 69 | p.print_help() 70 | sys.exit(1) 71 | 72 | problem = args[0] 73 | 74 | try: 75 | if problem == 'ping': 76 | report = omdclient.nagiosReport('svc_all', argdict) 77 | for e in report: print(e[0]) 78 | else: 79 | p = re.compile('^%s$' % problem, re.IGNORECASE) 80 | report = omdclient.nagiosReport('get_host', argdict) 81 | for e in report: 82 | if p.match(e[2]): printServiceStatusIfMatch(e, opt) 83 | 84 | except Exception as e: 85 | print("failed: %s" % (e)) 86 | sys.exit(-1) 87 | 88 | if __name__ == "__main__": 89 | main() 90 | 91 | ######################################################################### 92 | ### POD Documentation ################################################### 93 | ######################################################################### 94 | 95 | """ 96 | 97 | =head1 NAME 98 | 99 | omd-nagios-hosts-with-problem - find hosts in nagios with a given problem 100 | 101 | =head1 SYNOPSIS 102 | 103 | B ssi_check_puppetreport 104 | 105 | B '.*puppet.*' 106 | 107 | B ping 108 | 109 | =head1 USAGE 110 | 111 | omd-nagios-hosts-with-problem uses the WATO interface to discover hosts 112 | with a given service problem, and prints them to STDOUT. You can then use 113 | this information to script further automation - logging into the host to 114 | fix the problem, say, or re-inventorying the host. 115 | 116 | =head1 ARGUMENTS 117 | 118 | =over 4 119 | 120 | =item B 121 | 122 | What problem are we searching for? This can be a regular expression. We 123 | only print hosts that have service problems that match the regex. 124 | 125 | SPECIAL CASE: if the problem is 'ping', then we'll do a host check for 126 | down hosts. 127 | 128 | =item B<--no_critical> 129 | 130 | Skip 'CRIT' errors. 131 | 132 | =item B<--no_unknown> 133 | 134 | Skip 'UNKN' errors. 135 | 136 | =item B<--no_warnings> 137 | 138 | Skip 'WARN' errors. 139 | 140 | =item B<--verbose> 141 | 142 | Print more information than just the hostname. 143 | 144 | =back 145 | 146 | =head2 DEFAULT 147 | 148 | =over 4 149 | 150 | =item B<--debug> 151 | 152 | If set, print debugging information. 153 | 154 | =item B<--help> 155 | 156 | Print this information and exit. 157 | 158 | =back 159 | 160 | =head2 CONNECTION OPTIONS 161 | 162 | =over 4 163 | 164 | =item B<--apikey> I 165 | 166 | Password for the API User. Default: comes from the configuration file. 167 | 168 | =item B<--server> I 169 | 170 | Host name of the server. Default: comes from the configuration file. 171 | 172 | =item B<--site> I 173 | 174 | Site name within the server. Default: comes from the configuration file. 175 | 176 | =item B<--user> I 177 | 178 | API User name. The user must exist on the server, and be an 'automation 179 | user'. Default: comes from the configuration file. 180 | 181 | =back 182 | 183 | =head2 CREATE/UPDATE OPTIONS 184 | 185 | =over 4 186 | 187 | =item role 188 | 189 | check_mk role name. This can either be simple ('bastion') or more complex 190 | based on group name ('htcondor_cmsgrid_worker'). Must already exist on 191 | the server side. 192 | 193 | =item instance 194 | 195 | check_mk instance name. This can be 'test', 'dev', 'itb', or anything 196 | else that seems appropriate. Must already exist on the server side. 197 | 198 | =item extra 199 | 200 | Not yet in use. If you set to 'unmonitored', then we'll delete the entry. 201 | 202 | =back 203 | 204 | =head1 FILES 205 | 206 | =over 4 207 | 208 | =item F 209 | 210 | =back 211 | 212 | =head1 SEE ALSO 213 | 214 | https://mathias-kettner.de/checkmk_wato_webapi.html 215 | 216 | =head1 AUTHOR 217 | 218 | Tim Skirvin 219 | 220 | =head1 LICENSE + COPYRIGHT 221 | 222 | Copyright 2016, Fermi National Accelerator Laboratory 223 | 224 | This program is free software; you may redistribute it and/or modify it 225 | under the same terms as Perl itself. 226 | 227 | =cut 228 | 229 | """ 230 | -------------------------------------------------------------------------------- /man/man1/omd-host-tag.1: -------------------------------------------------------------------------------- 1 | .\" Automatically generated by Pod::Man 4.07 (Pod::Simple 3.32) 2 | .\" 3 | .\" Standard preamble: 4 | .\" ======================================================================== 5 | .de Sp \" Vertical space (when we can't use .PP) 6 | .if t .sp .5v 7 | .if n .sp 8 | .. 9 | .de Vb \" Begin verbatim text 10 | .ft CW 11 | .nf 12 | .ne \\$1 13 | .. 14 | .de Ve \" End verbatim text 15 | .ft R 16 | .fi 17 | .. 18 | .\" Set up some character translations and predefined strings. \*(-- will 19 | .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left 20 | .\" double quote, and \*(R" will give a right double quote. \*(C+ will 21 | .\" give a nicer C++. Capital omega is used to do unbreakable dashes and 22 | .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, 23 | .\" nothing in troff, for use with C<>. 24 | .tr \(*W- 25 | .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' 26 | .ie n \{\ 27 | . ds -- \(*W- 28 | . ds PI pi 29 | . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch 30 | . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch 31 | . ds L" "" 32 | . ds R" "" 33 | . ds C` "" 34 | . ds C' "" 35 | 'br\} 36 | .el\{\ 37 | . ds -- \|\(em\| 38 | . ds PI \(*p 39 | . ds L" `` 40 | . ds R" '' 41 | . ds C` 42 | . ds C' 43 | 'br\} 44 | .\" 45 | .\" Escape single quotes in literal strings from groff's Unicode transform. 46 | .ie \n(.g .ds Aq \(aq 47 | .el .ds Aq ' 48 | .\" 49 | .\" If the F register is >0, we'll generate index entries on stderr for 50 | .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index 51 | .\" entries marked with X<> in POD. Of course, you'll have to process the 52 | .\" output yourself in some meaningful fashion. 53 | .\" 54 | .\" Avoid warning from groff about undefined register 'F'. 55 | .de IX 56 | .. 57 | .if !\nF .nr F 0 58 | .if \nF>0 \{\ 59 | . de IX 60 | . tm Index:\\$1\t\\n%\t"\\$2" 61 | .. 62 | . if !\nF==2 \{\ 63 | . nr % 0 64 | . nr F 2 65 | . \} 66 | .\} 67 | .\" 68 | .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). 69 | .\" Fear. Run. Save yourself. No user-serviceable parts. 70 | . \" fudge factors for nroff and troff 71 | .if n \{\ 72 | . ds #H 0 73 | . ds #V .8m 74 | . ds #F .3m 75 | . ds #[ \f1 76 | . ds #] \fP 77 | .\} 78 | .if t \{\ 79 | . ds #H ((1u-(\\\\n(.fu%2u))*.13m) 80 | . ds #V .6m 81 | . ds #F 0 82 | . ds #[ \& 83 | . ds #] \& 84 | .\} 85 | . \" simple accents for nroff and troff 86 | .if n \{\ 87 | . ds ' \& 88 | . ds ` \& 89 | . ds ^ \& 90 | . ds , \& 91 | . ds ~ ~ 92 | . ds / 93 | .\} 94 | .if t \{\ 95 | . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" 96 | . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' 97 | . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' 98 | . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' 99 | . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' 100 | . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' 101 | .\} 102 | . \" troff and (daisy-wheel) nroff accents 103 | .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' 104 | .ds 8 \h'\*(#H'\(*b\h'-\*(#H' 105 | .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] 106 | .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' 107 | .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' 108 | .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] 109 | .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] 110 | .ds ae a\h'-(\w'a'u*4/10)'e 111 | .ds Ae A\h'-(\w'A'u*4/10)'E 112 | . \" corrections for vroff 113 | .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' 114 | .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' 115 | . \" for low resolution devices (crt and lpr) 116 | .if \n(.H>23 .if \n(.V>19 \ 117 | \{\ 118 | . ds : e 119 | . ds 8 ss 120 | . ds o a 121 | . ds d- d\h'-1'\(ga 122 | . ds D- D\h'-1'\(hy 123 | . ds th \o'bp' 124 | . ds Th \o'LP' 125 | . ds ae ae 126 | . ds Ae AE 127 | .\} 128 | .rm #[ #] #H #V #F C 129 | .\" ======================================================================== 130 | .\" 131 | .IX Title "OMD-HOST-TAG 1" 132 | .TH OMD-HOST-TAG 1 "2017-12-04" "perl v5.24.1" "User Contributed Perl Documentation" 133 | .\" For nroff, turn off justification. Always turn off hyphenation; it makes 134 | .\" way too many mistakes in technical documents. 135 | .if n .ad l 136 | .nh 137 | .SH "NAME" 138 | omd\-host\-tag \- update/remove a given host tag in OMD 139 | .SH "SYNOPSIS" 140 | .IX Header "SYNOPSIS" 141 | \&\fBomd-host-tag\fR cms-foo my_tag new_value 142 | .PP 143 | \&\fBomd-host-tag\fR cms-foo my_tag \s-1UNDEF\s0 144 | .SH "USAGE" 145 | .IX Header "USAGE" 146 | omd-host-tag provides a way to update or clear a tag for a specific 147 | host using hte \s-1OMD/WATO\s0 the \s-1OMD/WATO\s0 check_mk web interface. 148 | .SH "ARGUMENTS" 149 | .IX Header "ARGUMENTS" 150 | .SS "\s-1REQUIRED\s0" 151 | .IX Subsection "REQUIRED" 152 | .IP "\fIhostname\fR" 4 153 | .IX Item "hostname" 154 | Hostname for which to query. No default, must be set. 155 | .IP "\fItag\fR" 4 156 | .IX Item "tag" 157 | Tag to update. This tag must already exist. 158 | .IP "\fIvalue\fR" 4 159 | .IX Item "value" 160 | Value of this tag. \s-1UNDEF\s0 means \*(L"unset the flag\*(R". 161 | .SS "\s-1DEFAULT\s0" 162 | .IX Subsection "DEFAULT" 163 | .IP "\fB\-\-debug\fR" 4 164 | .IX Item "--debug" 165 | If set, print debugging information. 166 | .IP "\fB\-\-help\fR" 4 167 | .IX Item "--help" 168 | Print this information and exit. 169 | .SS "\s-1CONNECTION OPTIONS\s0" 170 | .IX Subsection "CONNECTION OPTIONS" 171 | .IP "\fB\-\-apikey\fR \fIkey\fR" 4 172 | .IX Item "--apikey key" 173 | Password for the \s-1API\s0 User. Default: comes from the configuration file. 174 | .IP "\fB\-\-server\fR \fIserver\fR" 4 175 | .IX Item "--server server" 176 | Host name of the server. Default: comes from the configuration file. 177 | .IP "\fB\-\-site\fR \fIsite\fR" 4 178 | .IX Item "--site site" 179 | Site name within the server. Default: comes from the configuration file. 180 | .IP "\fB\-\-user\fR \fIuser\fR" 4 181 | .IX Item "--user user" 182 | \&\s-1API\s0 User name. The user must exist on the server, and be an 'automation 183 | user'. Default: comes from the configuration file. 184 | .SH "FILES" 185 | .IX Header "FILES" 186 | .IP "\fI/etc/omdclient/config.yaml\fR" 4 187 | .IX Item "/etc/omdclient/config.yaml" 188 | .SH "SEE ALSO" 189 | .IX Header "SEE ALSO" 190 | https://mathias\-kettner.de/checkmk_wato_webapi.html 191 | .SH "AUTHOR" 192 | .IX Header "AUTHOR" 193 | Tim Skirvin 194 | .SH "LICENSE + COPYRIGHT" 195 | .IX Header "LICENSE + COPYRIGHT" 196 | Copyright 2017, Fermi National Accelerator Laboratory 197 | .PP 198 | This program is free software; you may redistribute it and/or modify it 199 | under the same terms as Perl itself. 200 | -------------------------------------------------------------------------------- /man/man1/omd-nagios-ack.1: -------------------------------------------------------------------------------- 1 | .\" Automatically generated by Pod::Man 4.07 (Pod::Simple 3.32) 2 | .\" 3 | .\" Standard preamble: 4 | .\" ======================================================================== 5 | .de Sp \" Vertical space (when we can't use .PP) 6 | .if t .sp .5v 7 | .if n .sp 8 | .. 9 | .de Vb \" Begin verbatim text 10 | .ft CW 11 | .nf 12 | .ne \\$1 13 | .. 14 | .de Ve \" End verbatim text 15 | .ft R 16 | .fi 17 | .. 18 | .\" Set up some character translations and predefined strings. \*(-- will 19 | .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left 20 | .\" double quote, and \*(R" will give a right double quote. \*(C+ will 21 | .\" give a nicer C++. Capital omega is used to do unbreakable dashes and 22 | .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, 23 | .\" nothing in troff, for use with C<>. 24 | .tr \(*W- 25 | .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' 26 | .ie n \{\ 27 | . ds -- \(*W- 28 | . ds PI pi 29 | . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch 30 | . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch 31 | . ds L" "" 32 | . ds R" "" 33 | . ds C` "" 34 | . ds C' "" 35 | 'br\} 36 | .el\{\ 37 | . ds -- \|\(em\| 38 | . ds PI \(*p 39 | . ds L" `` 40 | . ds R" '' 41 | . ds C` 42 | . ds C' 43 | 'br\} 44 | .\" 45 | .\" Escape single quotes in literal strings from groff's Unicode transform. 46 | .ie \n(.g .ds Aq \(aq 47 | .el .ds Aq ' 48 | .\" 49 | .\" If the F register is >0, we'll generate index entries on stderr for 50 | .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index 51 | .\" entries marked with X<> in POD. Of course, you'll have to process the 52 | .\" output yourself in some meaningful fashion. 53 | .\" 54 | .\" Avoid warning from groff about undefined register 'F'. 55 | .de IX 56 | .. 57 | .if !\nF .nr F 0 58 | .if \nF>0 \{\ 59 | . de IX 60 | . tm Index:\\$1\t\\n%\t"\\$2" 61 | .. 62 | . if !\nF==2 \{\ 63 | . nr % 0 64 | . nr F 2 65 | . \} 66 | .\} 67 | .\" 68 | .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). 69 | .\" Fear. Run. Save yourself. No user-serviceable parts. 70 | . \" fudge factors for nroff and troff 71 | .if n \{\ 72 | . ds #H 0 73 | . ds #V .8m 74 | . ds #F .3m 75 | . ds #[ \f1 76 | . ds #] \fP 77 | .\} 78 | .if t \{\ 79 | . ds #H ((1u-(\\\\n(.fu%2u))*.13m) 80 | . ds #V .6m 81 | . ds #F 0 82 | . ds #[ \& 83 | . ds #] \& 84 | .\} 85 | . \" simple accents for nroff and troff 86 | .if n \{\ 87 | . ds ' \& 88 | . ds ` \& 89 | . ds ^ \& 90 | . ds , \& 91 | . ds ~ ~ 92 | . ds / 93 | .\} 94 | .if t \{\ 95 | . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" 96 | . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' 97 | . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' 98 | . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' 99 | . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' 100 | . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' 101 | .\} 102 | . \" troff and (daisy-wheel) nroff accents 103 | .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' 104 | .ds 8 \h'\*(#H'\(*b\h'-\*(#H' 105 | .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] 106 | .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' 107 | .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' 108 | .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] 109 | .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] 110 | .ds ae a\h'-(\w'a'u*4/10)'e 111 | .ds Ae A\h'-(\w'A'u*4/10)'E 112 | . \" corrections for vroff 113 | .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' 114 | .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' 115 | . \" for low resolution devices (crt and lpr) 116 | .if \n(.H>23 .if \n(.V>19 \ 117 | \{\ 118 | . ds : e 119 | . ds 8 ss 120 | . ds o a 121 | . ds d- d\h'-1'\(ga 122 | . ds D- D\h'-1'\(hy 123 | . ds th \o'bp' 124 | . ds Th \o'LP' 125 | . ds ae ae 126 | . ds Ae AE 127 | .\} 128 | .rm #[ #] #H #V #F C 129 | .\" ======================================================================== 130 | .\" 131 | .IX Title "OMD-NAGIOS-ACK 1" 132 | .TH OMD-NAGIOS-ACK 1 "2017-12-04" "perl v5.24.1" "User Contributed Perl Documentation" 133 | .\" For nroff, turn off justification. Always turn off hyphenation; it makes 134 | .\" way too many mistakes in technical documents. 135 | .if n .ad l 136 | .nh 137 | .SH "NAME" 138 | omd\-nagios\-ack \- acknowledge a host or service problem 139 | .SH "SYNOPSIS" 140 | .IX Header "SYNOPSIS" 141 | \&\fBomd-nagios-ack\fR host cmsadmin1 'known host is down' 142 | .PP 143 | \&\fBomd-nagios-ack\fR service cmsadmin1 puppet-report 'known problem' 144 | .SH "USAGE" 145 | .IX Header "USAGE" 146 | omd-nagios-ack uses the \s-1OMD\s0 autmation \s-1API\s0 to acknowledge a host or service 147 | alert. It works on the standard nagios limitations \- you can send a 148 | request, but there's no way to get back a response. We try to guess a 149 | response anyway, but it's not horribly reliable. 150 | .SH "ARGUMENTS" 151 | .IX Header "ARGUMENTS" 152 | .SH "REQUIRED" 153 | .IX Header "REQUIRED" 154 | .IP "\fIhost|service\fR" 4 155 | .IX Item "host|service" 156 | Are we ack'ing a host or a service? 157 | .IP "\fI\s-1HOSTNAME\s0\fR" 4 158 | .IX Item "HOSTNAME" 159 | Hostname of the host or service. 160 | .IP "[\fI\s-1SERVICE\s0\fR]" 4 161 | .IX Item "[SERVICE]" 162 | Service name of the service (only necessary for service requests). 163 | .IP "\fI\s-1COMMENT\s0\fR" 4 164 | .IX Item "COMMENT" 165 | Some explanatory text. 166 | .SS "\s-1OPTIONS\s0" 167 | .IX Subsection "OPTIONS" 168 | .IP "\fB\-\-debug\fR" 4 169 | .IX Item "--debug" 170 | If set, print debugging information. 171 | .IP "\fB\-\-apikey\fR \fIkey\fR" 4 172 | .IX Item "--apikey key" 173 | Password for the \s-1API\s0 User. Default: comes from the configuration file. 174 | .IP "\fB\-\-server\fR \fIserver\fR" 4 175 | .IX Item "--server server" 176 | Host name of the server. Default: comes from the configuration file. 177 | .IP "\fB\-\-site\fR \fIsite\fR" 4 178 | .IX Item "--site site" 179 | Site name within the server. Default: comes from the configuration file. 180 | .IP "\fB\-\-user\fR \fIuser\fR" 4 181 | .IX Item "--user user" 182 | \&\s-1API\s0 User name. The user must exist on the server, and be an 'automation 183 | user'. Default: comes from the configuration file. 184 | .SH "FILES" 185 | .IX Header "FILES" 186 | .IP "\fI/etc/omdclient/config.yaml\fR" 4 187 | .IX Item "/etc/omdclient/config.yaml" 188 | .SH "SEE ALSO" 189 | .IX Header "SEE ALSO" 190 | https://mathias\-kettner.de/checkmk_wato_webapi.html 191 | .SH "AUTHOR" 192 | .IX Header "AUTHOR" 193 | Tim Skirvin 194 | .SH "LICENSE + COPYRIGHT" 195 | .IX Header "LICENSE + COPYRIGHT" 196 | Copyright 2015, Fermi National Accelerator Laboratory 197 | .PP 198 | This program is free software; you may redistribute it and/or modify it 199 | under the same terms as Perl itself. 200 | -------------------------------------------------------------------------------- /man/man1/omd-puppet-enc.1: -------------------------------------------------------------------------------- 1 | .\" Automatically generated by Pod::Man 4.07 (Pod::Simple 3.32) 2 | .\" 3 | .\" Standard preamble: 4 | .\" ======================================================================== 5 | .de Sp \" Vertical space (when we can't use .PP) 6 | .if t .sp .5v 7 | .if n .sp 8 | .. 9 | .de Vb \" Begin verbatim text 10 | .ft CW 11 | .nf 12 | .ne \\$1 13 | .. 14 | .de Ve \" End verbatim text 15 | .ft R 16 | .fi 17 | .. 18 | .\" Set up some character translations and predefined strings. \*(-- will 19 | .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left 20 | .\" double quote, and \*(R" will give a right double quote. \*(C+ will 21 | .\" give a nicer C++. Capital omega is used to do unbreakable dashes and 22 | .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, 23 | .\" nothing in troff, for use with C<>. 24 | .tr \(*W- 25 | .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' 26 | .ie n \{\ 27 | . ds -- \(*W- 28 | . ds PI pi 29 | . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch 30 | . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch 31 | . ds L" "" 32 | . ds R" "" 33 | . ds C` "" 34 | . ds C' "" 35 | 'br\} 36 | .el\{\ 37 | . ds -- \|\(em\| 38 | . ds PI \(*p 39 | . ds L" `` 40 | . ds R" '' 41 | . ds C` 42 | . ds C' 43 | 'br\} 44 | .\" 45 | .\" Escape single quotes in literal strings from groff's Unicode transform. 46 | .ie \n(.g .ds Aq \(aq 47 | .el .ds Aq ' 48 | .\" 49 | .\" If the F register is >0, we'll generate index entries on stderr for 50 | .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index 51 | .\" entries marked with X<> in POD. Of course, you'll have to process the 52 | .\" output yourself in some meaningful fashion. 53 | .\" 54 | .\" Avoid warning from groff about undefined register 'F'. 55 | .de IX 56 | .. 57 | .if !\nF .nr F 0 58 | .if \nF>0 \{\ 59 | . de IX 60 | . tm Index:\\$1\t\\n%\t"\\$2" 61 | .. 62 | . if !\nF==2 \{\ 63 | . nr % 0 64 | . nr F 2 65 | . \} 66 | .\} 67 | .\" 68 | .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). 69 | .\" Fear. Run. Save yourself. No user-serviceable parts. 70 | . \" fudge factors for nroff and troff 71 | .if n \{\ 72 | . ds #H 0 73 | . ds #V .8m 74 | . ds #F .3m 75 | . ds #[ \f1 76 | . ds #] \fP 77 | .\} 78 | .if t \{\ 79 | . ds #H ((1u-(\\\\n(.fu%2u))*.13m) 80 | . ds #V .6m 81 | . ds #F 0 82 | . ds #[ \& 83 | . ds #] \& 84 | .\} 85 | . \" simple accents for nroff and troff 86 | .if n \{\ 87 | . ds ' \& 88 | . ds ` \& 89 | . ds ^ \& 90 | . ds , \& 91 | . ds ~ ~ 92 | . ds / 93 | .\} 94 | .if t \{\ 95 | . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" 96 | . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' 97 | . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' 98 | . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' 99 | . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' 100 | . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' 101 | .\} 102 | . \" troff and (daisy-wheel) nroff accents 103 | .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' 104 | .ds 8 \h'\*(#H'\(*b\h'-\*(#H' 105 | .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] 106 | .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' 107 | .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' 108 | .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] 109 | .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] 110 | .ds ae a\h'-(\w'a'u*4/10)'e 111 | .ds Ae A\h'-(\w'A'u*4/10)'E 112 | . \" corrections for vroff 113 | .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' 114 | .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' 115 | . \" for low resolution devices (crt and lpr) 116 | .if \n(.H>23 .if \n(.V>19 \ 117 | \{\ 118 | . ds : e 119 | . ds 8 ss 120 | . ds o a 121 | . ds d- d\h'-1'\(ga 122 | . ds D- D\h'-1'\(hy 123 | . ds th \o'bp' 124 | . ds Th \o'LP' 125 | . ds ae ae 126 | . ds Ae AE 127 | .\} 128 | .rm #[ #] #H #V #F C 129 | .\" ======================================================================== 130 | .\" 131 | .IX Title "OMD-PUPPET-ENC 1" 132 | .TH OMD-PUPPET-ENC 1 "2017-12-04" "perl v5.24.1" "User Contributed Perl Documentation" 133 | .\" For nroff, turn off justification. Always turn off hyphenation; it makes 134 | .\" way too many mistakes in technical documents. 135 | .if n .ad l 136 | .nh 137 | .SH "NAME" 138 | omd\-puppet\-enc \- converts puppet ENC data to omd\-host\-crud commands 139 | .SH "SYNOPSIS" 140 | .IX Header "SYNOPSIS" 141 | \&\fBomd-puppet-enc\fR update cmsdev43.fnal.gov.yaml 142 | .PP 143 | \&\fBomd-puppet-enc\fR delete cmsdev43.fnal.gov.yaml 144 | .SH "DESCRIPTION" 145 | .IX Header "DESCRIPTION" 146 | This script parses standard \s-1ENC\s0 yaml, as defined at: 147 | .PP 148 | .Vb 1 149 | \& https://docs.puppetlabs.com/guides/external_nodes.html 150 | .Ve 151 | .PP 152 | It then runs appropriate omd-host-crud commands to either update or delete 153 | the upstream monitoring configuration based on the contents of the \s-1ENC. \s0 This 154 | can then be hooked into (say) a post-receive hook to automatically update 155 | monitoring data when hosts are added/removed/updated in the main node 156 | repository. 157 | .SH "PARAMETERS" 158 | .IX Header "PARAMETERS" 159 | .IP "\s-1COMMAND\s0" 4 160 | .IX Item "COMMAND" 161 | Either \fIupdate\fR or \fIdelete\fR. Passed to \fBomd-host-crud\fR. 162 | .IP "\s-1FILENAME\s0" 4 163 | .IX Item "FILENAME" 164 | File to load. The name of the file should correspond to the fqdn of the host, 165 | plus '.yaml', in an arbitrary path. 166 | .SH "FIELDS" 167 | .IX Header "FIELDS" 168 | We are parsing the following entries under the =parameters= hash in the \s-1ENC\s0 169 | yaml: 170 | .IP "checkmk_role" 4 171 | .IX Item "checkmk_role" 172 | Primary sorting tag. More-or-less corresponds to the puppet role. 173 | .Sp 174 | Examples: bastion, htcondor_gpgrid_collector. 175 | .IP "checkmk_instance" 4 176 | .IX Item "checkmk_instance" 177 | Secondary sorting tag. 178 | .Sp 179 | Examples: test, dev, backup, etc. 180 | .IP "checkmk_extra" 4 181 | .IX Item "checkmk_extra" 182 | Array of extra fields. If we see \fIunmonitored\fR for one of them, then we will 183 | try to delete the host from monitoring. 184 | .SH "SAMPLE DATA" 185 | .IX Header "SAMPLE DATA" 186 | .Vb 3 187 | \& cmsdev43.fnal.gov.yaml: 188 | \& classes: 189 | \& role::dev: 190 | \& 191 | \& parameters: 192 | \& checkmk_role: devhost 193 | \& checkmk_instance: dev 194 | \& checkmk_extra: 195 | \& \- unmonitored 196 | \& \- foo 197 | .Ve 198 | .SH "SEE ALSO" 199 | .IX Header "SEE ALSO" 200 | \&\fBomd-host-crud\fR 201 | .SH "AUTHOR" 202 | .IX Header "AUTHOR" 203 | Tim Skirvin 204 | .SH "LICENSE" 205 | .IX Header "LICENSE" 206 | Copyright 2015, Fermi National Accelerator Laboratory 207 | .PP 208 | This program is free software; you may redistribute it and/or modify 209 | it under the same terms as Perl itself. 210 | -------------------------------------------------------------------------------- /usr/bin/omd-nagios-hosts-with-problem: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | Find hosts in Nagios that have a given problem. 4 | """ 5 | 6 | ######################################################################### 7 | ### Declarations ######################################################## 8 | ######################################################################### 9 | 10 | import omdclient, os, re, sys 11 | 12 | ######################################################################### 13 | ### Configuration ####################################################### 14 | ######################################################################### 15 | 16 | ## Central configuration file. 17 | config_file_base = '/etc/omdclient/config.yaml' 18 | 19 | ## Text for --help 20 | text = "Discover hosts with a given service problem, using the WATO API" 21 | usage_text = "usage: %prog PROBLEM [options]" 22 | 23 | ######################################################################### 24 | ### Subroutines ######################################################### 25 | ######################################################################### 26 | 27 | def printServiceStatusIfMatch(entry, opt): 28 | """ 29 | Print information from a svcproblems. If we get opt.verbose, then 30 | we'll print a longer string; otherwise, just print the host name. 31 | """ 32 | status = entry[0] 33 | host = entry[1] 34 | svc = entry[2] 35 | text = entry[4] 36 | 37 | if opt.verbose: text = "%s/%s: %s (%s)" % (host, svc, status, text) 38 | else: text = host 39 | 40 | if status == 'CRIT': 41 | if not opt.no_crit: print(text) 42 | elif status == 'UNKN': 43 | if not opt.no_unknown: print(text) 44 | elif status == 'WARN': 45 | if not opt.no_warn: print(text) 46 | 47 | ######################################################################### 48 | ### main () ############################################################# 49 | ######################################################################### 50 | 51 | def main(): 52 | config_file = os.environ.get('OMDCONFIG', config_file_base) 53 | try: 54 | config = omdclient.loadCfg(config_file) 55 | except Exception as e: 56 | print("failed to load config: %s" % (e)) 57 | sys.exit(3) 58 | 59 | p = omdclient.generateParser(text, usage_text, config) 60 | p.add_option('--no_critical', dest='no_crit', action="store_true", 61 | default=False, help='do not include CRIT errors') 62 | p.add_option('--no_unknown', dest='no_unknown', action="store_true", 63 | default=False, help='do not include UNKN errors') 64 | p.add_option('--no_warnings', dest='no_warn', action="store_true", 65 | default=False, help='do not include WARN errors') 66 | p.add_option('--verbose', dest='verbose', action="store_true", 67 | default=False, help='print more status information') 68 | opt, args = p.parse_args() 69 | 70 | argdict = omdclient.parserArgDict(opt) 71 | 72 | if len(args) != 1: 73 | p.print_help() 74 | sys.exit(1) 75 | 76 | problem = args[0] 77 | 78 | try: 79 | if problem == 'ping': 80 | report = omdclient.nagiosReport('host', argdict) 81 | for e in report: print(e[0]) 82 | else: 83 | p = re.compile('^%s$' % problem, re.IGNORECASE) 84 | report = omdclient.nagiosReport('hostservice', argdict) 85 | for e in report: 86 | if p.match(e[2]): printServiceStatusIfMatch(e, opt) 87 | 88 | except Exception as e: 89 | print("failed: %s" % (e)) 90 | sys.exit(-1) 91 | 92 | if __name__ == "__main__": 93 | main() 94 | 95 | ######################################################################### 96 | ### POD Documentation ################################################### 97 | ######################################################################### 98 | 99 | """ 100 | 101 | =head1 NAME 102 | 103 | omd-nagios-hosts-with-problem - find hosts in nagios with a given problem 104 | 105 | =head1 SYNOPSIS 106 | 107 | B ssi_check_puppetreport 108 | 109 | B '.*puppet.*' 110 | 111 | B ping 112 | 113 | =head1 USAGE 114 | 115 | omd-nagios-hosts-with-problem uses the WATO interface to discover hosts 116 | with a given service problem, and prints them to STDOUT. You can then use 117 | this information to script further automation - logging into the host to 118 | fix the problem, say, or re-inventorying the host. 119 | 120 | =head1 ARGUMENTS 121 | 122 | =over 4 123 | 124 | =item B 125 | 126 | What problem are we searching for? This can be a regular expression. We 127 | only print hosts that have service problems that match the regex. 128 | 129 | SPECIAL CASE: if the problem is 'ping', then we'll do a host check for 130 | down hosts. 131 | 132 | =item B<--no_critical> 133 | 134 | Skip 'CRIT' errors. 135 | 136 | =item B<--no_unknown> 137 | 138 | Skip 'UNKN' errors. 139 | 140 | =item B<--no_warnings> 141 | 142 | Skip 'WARN' errors. 143 | 144 | =item B<--verbose> 145 | 146 | Print more information than just the hostname. 147 | 148 | =back 149 | 150 | =head2 DEFAULT 151 | 152 | =over 4 153 | 154 | =item B<--debug> 155 | 156 | If set, print debugging information. 157 | 158 | =item B<--help> 159 | 160 | Print this information and exit. 161 | 162 | =back 163 | 164 | =head2 CONNECTION OPTIONS 165 | 166 | =over 4 167 | 168 | =item B<--apikey> I 169 | 170 | Password for the API User. Default: comes from the configuration file. 171 | 172 | =item B<--server> I 173 | 174 | Host name of the server. Default: comes from the configuration file. 175 | 176 | =item B<--site> I 177 | 178 | Site name within the server. Default: comes from the configuration file. 179 | 180 | =item B<--user> I 181 | 182 | API User name. The user must exist on the server, and be an 'automation 183 | user'. Default: comes from the configuration file. 184 | 185 | =back 186 | 187 | =head2 CREATE/UPDATE OPTIONS 188 | 189 | =over 4 190 | 191 | =item role 192 | 193 | check_mk role name. This can either be simple ('bastion') or more complex 194 | based on group name ('htcondor_cmsgrid_worker'). Must already exist on 195 | the server side. 196 | 197 | =item instance 198 | 199 | check_mk instance name. This can be 'test', 'dev', 'itb', or anything 200 | else that seems appropriate. Must already exist on the server side. 201 | 202 | =item extra 203 | 204 | Not yet in use. If you set to 'unmonitored', then we'll delete the entry. 205 | 206 | =back 207 | 208 | =head1 FILES 209 | 210 | =over 4 211 | 212 | =item F 213 | 214 | =back 215 | 216 | =head1 SEE ALSO 217 | 218 | https://mathias-kettner.de/checkmk_wato_webapi.html 219 | 220 | =head1 AUTHOR 221 | 222 | Tim Skirvin 223 | 224 | =head1 LICENSE + COPYRIGHT 225 | 226 | Copyright 2016, Fermi National Accelerator Laboratory 227 | 228 | This program is free software; you may redistribute it and/or modify it 229 | under the same terms as Perl itself. 230 | 231 | =cut 232 | 233 | """ 234 | -------------------------------------------------------------------------------- /usr/bin/omd-nagios-report: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Prints a pretty nagios report. 3 | 4 | ######################################################################### 5 | ### Declarations ######################################################## 6 | ######################################################################### 7 | 8 | import omdclient, re, os, socket, sys 9 | from datetime import datetime 10 | 11 | ######################################################################### 12 | ### Configuration ####################################################### 13 | ######################################################################### 14 | ## Managed via central libraries and /etc/omd_client 15 | 16 | config_file_base = '/etc/omdclient/config.yaml' 17 | 18 | ## Text for --help 19 | text = "print a pretty host/service report to STDOUT" 20 | usage_text = "usage: %prog [options]" 21 | 22 | ######################################################################### 23 | ### Subroutines ######################################################### 24 | ######################################################################### 25 | 26 | def printHostReport(array): 27 | """ 28 | Print a 2-3 line report on a host. 29 | """ 30 | (host, icons, state, text, svc_ok, svc_warn, svc_crit, svc_unknown, 31 | svc_pending, state_age, comments) = array 32 | print("%-45s %-4s %.25s" % (host, state, state_age)) 33 | print(" %s" % text.encode('utf-8')) 34 | if comments: 35 | p = re.compile ('\(Nagios Process\): This .* has been scheduled for fixed downtime') 36 | comments = p.sub ('DOWNTIME', comments) 37 | print(" ACK - %-70.70s" % comments) 38 | 39 | 40 | def printSvcReport(array): 41 | """ 42 | Print a 2-3 line report on a service. 43 | """ 44 | (crit, host, svc, tags, text, state_age, check_age, perfometer, 45 | comments) = array 46 | print("%-45s %-4s %.25s" % ("%s/%s" % (host, svc), crit, state_age)) 47 | print(" %s" % text.encode('utf-8')) 48 | if comments: 49 | print(" ACK: %-70.70s" % comments) 50 | 51 | ######################################################################### 52 | ### main () ############################################################# 53 | ######################################################################### 54 | 55 | def main(): 56 | config_file = os.environ.get('OMDCONFIG', config_file_base) 57 | try: 58 | config = omdclient.loadCfg(config_file) 59 | except Exception as e: 60 | print("failed to load config: %s" % (e)) 61 | sys.exit(3) 62 | 63 | p = omdclient.generateParser(text, usage_text, config) 64 | opt, args = p.parse_args() 65 | argdict = omdclient.parserArgDict(opt) 66 | 67 | try: 68 | host_ack = omdclient.nagiosReport('host_ack', argdict) 69 | host_unack = omdclient.nagiosReport('host_unack', argdict) 70 | svc_ack = omdclient.nagiosReport('svc_ack', argdict) 71 | svc_unack = omdclient.nagiosReport('svc_unack', argdict) 72 | 73 | string = "%35s %3d matches" 74 | print(string % ('Acknowledged Host Alerts', len(host_ack))) 75 | print(string % ('Unacknowledged Host Alerts', len(host_unack))) 76 | print(string % ('Acknowledged Service Alerts', len(svc_ack))) 77 | print(string % ('Unacknowledged Service Alerts', len(svc_unack))) 78 | 79 | if len(host_unack) > 0: 80 | print("") 81 | print("Unacknowledged Host Alerts") 82 | print("==========================") 83 | for i in host_unack: 84 | print("") 85 | printHostReport(i) 86 | 87 | if len(host_ack) > 0: 88 | print("") 89 | print("Acknowledged Host Alerts") 90 | print("========================") 91 | for i in host_ack: 92 | print("") 93 | printHostReport(i) 94 | 95 | if len(svc_unack) > 0: 96 | print("") 97 | print("Unacknowledged Service Alerts") 98 | print("=============================") 99 | for i in svc_unack: 100 | print("") 101 | try: 102 | printSvcReport(i) 103 | except Exception as e: 104 | print("( error on print, skipping)") 105 | 106 | if len(svc_ack) > 0: 107 | print("") 108 | print("Acknowledged Service Alerts") 109 | print("===========================") 110 | for i in svc_ack: 111 | print("") 112 | try: 113 | printSvcReport(i) 114 | except Exception as e: 115 | print("( error on print, skipping)") 116 | 117 | print("") 118 | print("-- ") 119 | format = "%-15.15s %-61.61s" 120 | print(format % ("Generated At", 121 | datetime.now().strftime("%Y-%m-%d %H:%M:%S"))) 122 | print(format % ("Generated By", ("%s:%s" 123 | % (socket.gethostname(), sys.argv[0])))) 124 | print(format % ("Pulled From", 125 | ("https://%s/%s/check_mk" % (opt.server, opt.site)))) 126 | 127 | except Exception as e: 128 | print("failed to generate the report: %s" % (e)) 129 | sys.exit(-1) 130 | 131 | if __name__ == "__main__": 132 | main() 133 | 134 | ######################################################################### 135 | ### POD Documentation ################################################### 136 | ######################################################################### 137 | 138 | """ 139 | 140 | =head1 NAME 141 | 142 | omd-nagios-report - prints a report of all open host and service alerts 143 | 144 | =head1 SYNOPSIS 145 | 146 | B 147 | 148 | =head1 USAGE 149 | 150 | omd-nagios-report prints a report om all acknowledged and unacknowledged 151 | host and service alerts associated with the given server and site. 152 | 153 | =head1 ARGUMENTS 154 | 155 | =over 4 156 | 157 | =item B<--debug> 158 | 159 | If set, print debugging information. 160 | 161 | =item B<--apikey> I 162 | 163 | Password for the API User. Default: comes from the configuration file. 164 | 165 | =item B<--server> I 166 | 167 | Host name of the server. Default: comes from the configuration file. 168 | 169 | =item B<--site> I 170 | 171 | Site name within the server. Default: comes from the configuration file. 172 | 173 | =item B<--user> I 174 | 175 | API User name. The user must exist on the server, and be an 'automation 176 | user'. Default: comes from the configuration file. 177 | 178 | =back 179 | 180 | =head1 FILES 181 | 182 | =over 4 183 | 184 | =item F 185 | 186 | =back 187 | 188 | =head1 SEE ALSO 189 | 190 | https://mathias-kettner.de/checkmk_wato_webapi.html 191 | 192 | =head1 AUTHOR 193 | 194 | Tim Skirvin 195 | 196 | =head1 LICENSE + COPYRIGHT 197 | 198 | Copyright 2015, Fermi National Accelerator Laboratory 199 | 200 | This program is free software; you may redistribute it and/or modify it 201 | under the same terms as Perl itself. 202 | 203 | =cut 204 | 205 | """ 206 | -------------------------------------------------------------------------------- /man/man1/omd-nagios-downtime.1: -------------------------------------------------------------------------------- 1 | .\" Automatically generated by Pod::Man 4.07 (Pod::Simple 3.32) 2 | .\" 3 | .\" Standard preamble: 4 | .\" ======================================================================== 5 | .de Sp \" Vertical space (when we can't use .PP) 6 | .if t .sp .5v 7 | .if n .sp 8 | .. 9 | .de Vb \" Begin verbatim text 10 | .ft CW 11 | .nf 12 | .ne \\$1 13 | .. 14 | .de Ve \" End verbatim text 15 | .ft R 16 | .fi 17 | .. 18 | .\" Set up some character translations and predefined strings. \*(-- will 19 | .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left 20 | .\" double quote, and \*(R" will give a right double quote. \*(C+ will 21 | .\" give a nicer C++. Capital omega is used to do unbreakable dashes and 22 | .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, 23 | .\" nothing in troff, for use with C<>. 24 | .tr \(*W- 25 | .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' 26 | .ie n \{\ 27 | . ds -- \(*W- 28 | . ds PI pi 29 | . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch 30 | . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch 31 | . ds L" "" 32 | . ds R" "" 33 | . ds C` "" 34 | . ds C' "" 35 | 'br\} 36 | .el\{\ 37 | . ds -- \|\(em\| 38 | . ds PI \(*p 39 | . ds L" `` 40 | . ds R" '' 41 | . ds C` 42 | . ds C' 43 | 'br\} 44 | .\" 45 | .\" Escape single quotes in literal strings from groff's Unicode transform. 46 | .ie \n(.g .ds Aq \(aq 47 | .el .ds Aq ' 48 | .\" 49 | .\" If the F register is >0, we'll generate index entries on stderr for 50 | .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index 51 | .\" entries marked with X<> in POD. Of course, you'll have to process the 52 | .\" output yourself in some meaningful fashion. 53 | .\" 54 | .\" Avoid warning from groff about undefined register 'F'. 55 | .de IX 56 | .. 57 | .if !\nF .nr F 0 58 | .if \nF>0 \{\ 59 | . de IX 60 | . tm Index:\\$1\t\\n%\t"\\$2" 61 | .. 62 | . if !\nF==2 \{\ 63 | . nr % 0 64 | . nr F 2 65 | . \} 66 | .\} 67 | .\" 68 | .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). 69 | .\" Fear. Run. Save yourself. No user-serviceable parts. 70 | . \" fudge factors for nroff and troff 71 | .if n \{\ 72 | . ds #H 0 73 | . ds #V .8m 74 | . ds #F .3m 75 | . ds #[ \f1 76 | . ds #] \fP 77 | .\} 78 | .if t \{\ 79 | . ds #H ((1u-(\\\\n(.fu%2u))*.13m) 80 | . ds #V .6m 81 | . ds #F 0 82 | . ds #[ \& 83 | . ds #] \& 84 | .\} 85 | . \" simple accents for nroff and troff 86 | .if n \{\ 87 | . ds ' \& 88 | . ds ` \& 89 | . ds ^ \& 90 | . ds , \& 91 | . ds ~ ~ 92 | . ds / 93 | .\} 94 | .if t \{\ 95 | . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" 96 | . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' 97 | . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' 98 | . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' 99 | . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' 100 | . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' 101 | .\} 102 | . \" troff and (daisy-wheel) nroff accents 103 | .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' 104 | .ds 8 \h'\*(#H'\(*b\h'-\*(#H' 105 | .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] 106 | .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' 107 | .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' 108 | .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] 109 | .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] 110 | .ds ae a\h'-(\w'a'u*4/10)'e 111 | .ds Ae A\h'-(\w'A'u*4/10)'E 112 | . \" corrections for vroff 113 | .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' 114 | .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' 115 | . \" for low resolution devices (crt and lpr) 116 | .if \n(.H>23 .if \n(.V>19 \ 117 | \{\ 118 | . ds : e 119 | . ds 8 ss 120 | . ds o a 121 | . ds d- d\h'-1'\(ga 122 | . ds D- D\h'-1'\(hy 123 | . ds th \o'bp' 124 | . ds Th \o'LP' 125 | . ds ae ae 126 | . ds Ae AE 127 | .\} 128 | .rm #[ #] #H #V #F C 129 | .\" ======================================================================== 130 | .\" 131 | .IX Title "OMD-NAGIOS-DOWNTIME 1" 132 | .TH OMD-NAGIOS-DOWNTIME 1 "2017-12-04" "perl v5.24.1" "User Contributed Perl Documentation" 133 | .\" For nroff, turn off justification. Always turn off hyphenation; it makes 134 | .\" way too many mistakes in technical documents. 135 | .if n .ad l 136 | .nh 137 | .SH "NAME" 138 | omd\-nagios\-downtime \- schedule downtime for a host or service 139 | .SH "SYNOPSIS" 140 | .IX Header "SYNOPSIS" 141 | \&\fBomd-nagios-downtime\fR host cmsadmin1 1 'down for an hour' 142 | .PP 143 | \&\fBomd-nagios-downtime\fR service cmsadmin1 puppet-report 2 'down for 2 hours' 144 | .SH "USAGE" 145 | .IX Header "USAGE" 146 | omd-nagios-downtime uses the \s-1OMD\s0 autmation \s-1API\s0 to put a host or service 147 | into downtime. It works on the standard nagios limitations \- you can send 148 | a request, but there's no way to get back a response. We try to guess a 149 | response anyway, but it's not horribly reliable. 150 | .SH "ARGUMENTS" 151 | .IX Header "ARGUMENTS" 152 | .SS "\s-1REQUIRED\s0" 153 | .IX Subsection "REQUIRED" 154 | .IP "\fIhost|service\fR" 4 155 | .IX Item "host|service" 156 | Are we setting downtime for a host or a service? 157 | .IP "\fI\s-1HOSTNAME\s0\fR" 4 158 | .IX Item "HOSTNAME" 159 | Hostname of the host or service. 160 | .IP "[\fI\s-1SERVICE\s0\fR]" 4 161 | .IX Item "[SERVICE]" 162 | Service name of the service (only necessary for service requests). 163 | .IP "\fI\s-1HOURS\s0\fR" 4 164 | .IX Item "HOURS" 165 | How many hours should the downtime last? 166 | .IP "\fI\s-1COMMENT\s0\fR" 4 167 | .IX Item "COMMENT" 168 | Some explanatory text. 169 | .SS "\s-1OPTIONS\s0" 170 | .IX Subsection "OPTIONS" 171 | .IP "\fB\-\-debug\fR" 4 172 | .IX Item "--debug" 173 | If set, print debugging information. 174 | .IP "\fB\-\-apikey\fR \fIkey\fR" 4 175 | .IX Item "--apikey key" 176 | Password for the \s-1API\s0 User. Default: comes from the configuration file. 177 | .IP "\fB\-\-server\fR \fIserver\fR" 4 178 | .IX Item "--server server" 179 | Host name of the server. Default: comes from the configuration file. 180 | .IP "\fB\-\-site\fR \fIsite\fR" 4 181 | .IX Item "--site site" 182 | Site name within the server. Default: comes from the configuration file. 183 | .IP "\fB\-\-user\fR \fIuser\fR" 4 184 | .IX Item "--user user" 185 | \&\s-1API\s0 User name. The user must exist on the server, and be an 'automation 186 | user'. Default: comes from the configuration file. 187 | .SH "FILES" 188 | .IX Header "FILES" 189 | .IP "\fI/etc/omdclient/config.yaml\fR" 4 190 | .IX Item "/etc/omdclient/config.yaml" 191 | .SH "SEE ALSO" 192 | .IX Header "SEE ALSO" 193 | https://mathias\-kettner.de/checkmk_wato_webapi.html 194 | .SH "AUTHOR" 195 | .IX Header "AUTHOR" 196 | Tim Skirvin 197 | .SH "LICENSE + COPYRIGHT" 198 | .IX Header "LICENSE + COPYRIGHT" 199 | Copyright 2015, Fermi National Accelerator Laboratory 200 | .PP 201 | This program is free software; you may redistribute it and/or modify it 202 | under the same terms as Perl itself. 203 | -------------------------------------------------------------------------------- /man/man1/omd-host-crud.1: -------------------------------------------------------------------------------- 1 | .\" Automatically generated by Pod::Man 4.07 (Pod::Simple 3.32) 2 | .\" 3 | .\" Standard preamble: 4 | .\" ======================================================================== 5 | .de Sp \" Vertical space (when we can't use .PP) 6 | .if t .sp .5v 7 | .if n .sp 8 | .. 9 | .de Vb \" Begin verbatim text 10 | .ft CW 11 | .nf 12 | .ne \\$1 13 | .. 14 | .de Ve \" End verbatim text 15 | .ft R 16 | .fi 17 | .. 18 | .\" Set up some character translations and predefined strings. \*(-- will 19 | .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left 20 | .\" double quote, and \*(R" will give a right double quote. \*(C+ will 21 | .\" give a nicer C++. Capital omega is used to do unbreakable dashes and 22 | .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, 23 | .\" nothing in troff, for use with C<>. 24 | .tr \(*W- 25 | .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' 26 | .ie n \{\ 27 | . ds -- \(*W- 28 | . ds PI pi 29 | . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch 30 | . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch 31 | . ds L" "" 32 | . ds R" "" 33 | . ds C` "" 34 | . ds C' "" 35 | 'br\} 36 | .el\{\ 37 | . ds -- \|\(em\| 38 | . ds PI \(*p 39 | . ds L" `` 40 | . ds R" '' 41 | . ds C` 42 | . ds C' 43 | 'br\} 44 | .\" 45 | .\" Escape single quotes in literal strings from groff's Unicode transform. 46 | .ie \n(.g .ds Aq \(aq 47 | .el .ds Aq ' 48 | .\" 49 | .\" If the F register is >0, we'll generate index entries on stderr for 50 | .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index 51 | .\" entries marked with X<> in POD. Of course, you'll have to process the 52 | .\" output yourself in some meaningful fashion. 53 | .\" 54 | .\" Avoid warning from groff about undefined register 'F'. 55 | .de IX 56 | .. 57 | .if !\nF .nr F 0 58 | .if \nF>0 \{\ 59 | . de IX 60 | . tm Index:\\$1\t\\n%\t"\\$2" 61 | .. 62 | . if !\nF==2 \{\ 63 | . nr % 0 64 | . nr F 2 65 | . \} 66 | .\} 67 | .\" 68 | .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). 69 | .\" Fear. Run. Save yourself. No user-serviceable parts. 70 | . \" fudge factors for nroff and troff 71 | .if n \{\ 72 | . ds #H 0 73 | . ds #V .8m 74 | . ds #F .3m 75 | . ds #[ \f1 76 | . ds #] \fP 77 | .\} 78 | .if t \{\ 79 | . ds #H ((1u-(\\\\n(.fu%2u))*.13m) 80 | . ds #V .6m 81 | . ds #F 0 82 | . ds #[ \& 83 | . ds #] \& 84 | .\} 85 | . \" simple accents for nroff and troff 86 | .if n \{\ 87 | . ds ' \& 88 | . ds ` \& 89 | . ds ^ \& 90 | . ds , \& 91 | . ds ~ ~ 92 | . ds / 93 | .\} 94 | .if t \{\ 95 | . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" 96 | . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' 97 | . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' 98 | . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' 99 | . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' 100 | . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' 101 | .\} 102 | . \" troff and (daisy-wheel) nroff accents 103 | .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' 104 | .ds 8 \h'\*(#H'\(*b\h'-\*(#H' 105 | .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] 106 | .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' 107 | .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' 108 | .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] 109 | .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] 110 | .ds ae a\h'-(\w'a'u*4/10)'e 111 | .ds Ae A\h'-(\w'A'u*4/10)'E 112 | . \" corrections for vroff 113 | .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' 114 | .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' 115 | . \" for low resolution devices (crt and lpr) 116 | .if \n(.H>23 .if \n(.V>19 \ 117 | \{\ 118 | . ds : e 119 | . ds 8 ss 120 | . ds o a 121 | . ds d- d\h'-1'\(ga 122 | . ds D- D\h'-1'\(hy 123 | . ds th \o'bp' 124 | . ds Th \o'LP' 125 | . ds ae ae 126 | . ds Ae AE 127 | .\} 128 | .rm #[ #] #H #V #F C 129 | .\" ======================================================================== 130 | .\" 131 | .IX Title "OMD-HOST-CRUD 1" 132 | .TH OMD-HOST-CRUD 1 "2017-12-04" "perl v5.24.1" "User Contributed Perl Documentation" 133 | .\" For nroff, turn off justification. Always turn off hyphenation; it makes 134 | .\" way too many mistakes in technical documents. 135 | .if n .ad l 136 | .nh 137 | .SH "NAME" 138 | omd\-host\-crud \- create/read/update/delete omd host entries 139 | .SH "SYNOPSIS" 140 | .IX Header "SYNOPSIS" 141 | \&\fBomd-host-crud\fR create cms-foo \-\-role unconfigured 142 | .PP 143 | \&\fBomd-host-crud\fR inventory cms-foo 144 | .PP 145 | \&\fBomd-host-crud\fR read cms-foo 146 | .PP 147 | \&\fBomd-host-crud\fR update cms-foo \-\-instance dev 148 | .PP 149 | \&\fBomd-host-crud\fR delete cms-foo 150 | .SH "USAGE" 151 | .IX Header "USAGE" 152 | omd-host-crud provides a \s-1CRUD \s0(Create/Read/Update/Delete) interface 153 | to the \s-1OMD/WATO\s0 check_mk web interface. 154 | .SH "ARGUMENTS" 155 | .IX Header "ARGUMENTS" 156 | .SS "\s-1REQUIRED\s0" 157 | .IX Subsection "REQUIRED" 158 | .IP "\fIaction\fR" 4 159 | .IX Item "action" 160 | create, inventory, read, update, delete. 161 | .IP "\fIhostname\fR" 4 162 | .IX Item "hostname" 163 | Hostname for which to query. No default, must be set. 164 | .SS "\s-1DEFAULT\s0" 165 | .IX Subsection "DEFAULT" 166 | .IP "\fB\-\-debug\fR" 4 167 | .IX Item "--debug" 168 | If set, print debugging information. 169 | .IP "\fB\-\-help\fR" 4 170 | .IX Item "--help" 171 | Print this information and exit. 172 | .SS "\s-1CONNECTION OPTIONS\s0" 173 | .IX Subsection "CONNECTION OPTIONS" 174 | .IP "\fB\-\-apikey\fR \fIkey\fR" 4 175 | .IX Item "--apikey key" 176 | Password for the \s-1API\s0 User. Default: comes from the configuration file. 177 | .IP "\fB\-\-server\fR \fIserver\fR" 4 178 | .IX Item "--server server" 179 | Host name of the server. Default: comes from the configuration file. 180 | .IP "\fB\-\-site\fR \fIsite\fR" 4 181 | .IX Item "--site site" 182 | Site name within the server. Default: comes from the configuration file. 183 | .IP "\fB\-\-user\fR \fIuser\fR" 4 184 | .IX Item "--user user" 185 | \&\s-1API\s0 User name. The user must exist on the server, and be an 'automation 186 | user'. Default: comes from the configuration file. 187 | .SS "\s-1CREATE/UPDATE OPTIONS\s0" 188 | .IX Subsection "CREATE/UPDATE OPTIONS" 189 | .IP "role" 4 190 | .IX Item "role" 191 | check_mk role name. This can either be simple ('bastion') or more complex 192 | based on group name ('htcondor_cmsgrid_worker'). Must already exist on 193 | the server side. 194 | .IP "instance" 4 195 | .IX Item "instance" 196 | check_mk instance name. This can be 'test', 'dev', 'itb', or anything 197 | else that seems appropriate. Must already exist on the server side. 198 | .IP "extra" 4 199 | .IX Item "extra" 200 | Not yet in use. If you set to 'unmonitored', then we'll delete the entry. 201 | .SH "FILES" 202 | .IX Header "FILES" 203 | .IP "\fI/etc/omdclient/config.yaml\fR" 4 204 | .IX Item "/etc/omdclient/config.yaml" 205 | .SH "SEE ALSO" 206 | .IX Header "SEE ALSO" 207 | https://mathias\-kettner.de/checkmk_wato_webapi.html 208 | .SH "AUTHOR" 209 | .IX Header "AUTHOR" 210 | Tim Skirvin 211 | .SH "LICENSE + COPYRIGHT" 212 | .IX Header "LICENSE + COPYRIGHT" 213 | Copyright 2015\-2017, Fermi National Accelerator Laboratory 214 | .PP 215 | This program is free software; you may redistribute it and/or modify it 216 | under the same terms as Perl itself. 217 | -------------------------------------------------------------------------------- /man/man1/omd-nagios-hosts-with-problem.1: -------------------------------------------------------------------------------- 1 | .\" Automatically generated by Pod::Man 4.07 (Pod::Simple 3.32) 2 | .\" 3 | .\" Standard preamble: 4 | .\" ======================================================================== 5 | .de Sp \" Vertical space (when we can't use .PP) 6 | .if t .sp .5v 7 | .if n .sp 8 | .. 9 | .de Vb \" Begin verbatim text 10 | .ft CW 11 | .nf 12 | .ne \\$1 13 | .. 14 | .de Ve \" End verbatim text 15 | .ft R 16 | .fi 17 | .. 18 | .\" Set up some character translations and predefined strings. \*(-- will 19 | .\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left 20 | .\" double quote, and \*(R" will give a right double quote. \*(C+ will 21 | .\" give a nicer C++. Capital omega is used to do unbreakable dashes and 22 | .\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, 23 | .\" nothing in troff, for use with C<>. 24 | .tr \(*W- 25 | .ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' 26 | .ie n \{\ 27 | . ds -- \(*W- 28 | . ds PI pi 29 | . if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch 30 | . if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch 31 | . ds L" "" 32 | . ds R" "" 33 | . ds C` "" 34 | . ds C' "" 35 | 'br\} 36 | .el\{\ 37 | . ds -- \|\(em\| 38 | . ds PI \(*p 39 | . ds L" `` 40 | . ds R" '' 41 | . ds C` 42 | . ds C' 43 | 'br\} 44 | .\" 45 | .\" Escape single quotes in literal strings from groff's Unicode transform. 46 | .ie \n(.g .ds Aq \(aq 47 | .el .ds Aq ' 48 | .\" 49 | .\" If the F register is >0, we'll generate index entries on stderr for 50 | .\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index 51 | .\" entries marked with X<> in POD. Of course, you'll have to process the 52 | .\" output yourself in some meaningful fashion. 53 | .\" 54 | .\" Avoid warning from groff about undefined register 'F'. 55 | .de IX 56 | .. 57 | .if !\nF .nr F 0 58 | .if \nF>0 \{\ 59 | . de IX 60 | . tm Index:\\$1\t\\n%\t"\\$2" 61 | .. 62 | . if !\nF==2 \{\ 63 | . nr % 0 64 | . nr F 2 65 | . \} 66 | .\} 67 | .\" 68 | .\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). 69 | .\" Fear. Run. Save yourself. No user-serviceable parts. 70 | . \" fudge factors for nroff and troff 71 | .if n \{\ 72 | . ds #H 0 73 | . ds #V .8m 74 | . ds #F .3m 75 | . ds #[ \f1 76 | . ds #] \fP 77 | .\} 78 | .if t \{\ 79 | . ds #H ((1u-(\\\\n(.fu%2u))*.13m) 80 | . ds #V .6m 81 | . ds #F 0 82 | . ds #[ \& 83 | . ds #] \& 84 | .\} 85 | . \" simple accents for nroff and troff 86 | .if n \{\ 87 | . ds ' \& 88 | . ds ` \& 89 | . ds ^ \& 90 | . ds , \& 91 | . ds ~ ~ 92 | . ds / 93 | .\} 94 | .if t \{\ 95 | . ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" 96 | . ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' 97 | . ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' 98 | . ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' 99 | . ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' 100 | . ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' 101 | .\} 102 | . \" troff and (daisy-wheel) nroff accents 103 | .ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' 104 | .ds 8 \h'\*(#H'\(*b\h'-\*(#H' 105 | .ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] 106 | .ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' 107 | .ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' 108 | .ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] 109 | .ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] 110 | .ds ae a\h'-(\w'a'u*4/10)'e 111 | .ds Ae A\h'-(\w'A'u*4/10)'E 112 | . \" corrections for vroff 113 | .if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' 114 | .if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' 115 | . \" for low resolution devices (crt and lpr) 116 | .if \n(.H>23 .if \n(.V>19 \ 117 | \{\ 118 | . ds : e 119 | . ds 8 ss 120 | . ds o a 121 | . ds d- d\h'-1'\(ga 122 | . ds D- D\h'-1'\(hy 123 | . ds th \o'bp' 124 | . ds Th \o'LP' 125 | . ds ae ae 126 | . ds Ae AE 127 | .\} 128 | .rm #[ #] #H #V #F C 129 | .\" ======================================================================== 130 | .\" 131 | .IX Title "OMD-NAGIOS-HOSTS-WITH-PROBLEM 1" 132 | .TH OMD-NAGIOS-HOSTS-WITH-PROBLEM 1 "2017-12-04" "perl v5.24.1" "User Contributed Perl Documentation" 133 | .\" For nroff, turn off justification. Always turn off hyphenation; it makes 134 | .\" way too many mistakes in technical documents. 135 | .if n .ad l 136 | .nh 137 | .SH "NAME" 138 | omd\-nagios\-hosts\-with\-problem \- find hosts in nagios with a given problem 139 | .SH "SYNOPSIS" 140 | .IX Header "SYNOPSIS" 141 | \&\fBomd-nagios-hosts-with-problem\fR ssi_check_puppetreport 142 | .PP 143 | \&\fBomd-nagios-hosts-with-problem\fR '.*puppet.*' 144 | .PP 145 | \&\fBomd-nagios-hosts-with-problem\fR ping 146 | .SH "USAGE" 147 | .IX Header "USAGE" 148 | omd-nagios-hosts-with-problem uses the \s-1WATO\s0 interface to discover hosts 149 | with a given service problem, and prints them to \s-1STDOUT. \s0 You can then use 150 | this information to script further automation \- logging into the host to 151 | fix the problem, say, or re-inventorying the host. 152 | .SH "ARGUMENTS" 153 | .IX Header "ARGUMENTS" 154 | .IP "\fB\s-1PROBLEM\s0\fR" 4 155 | .IX Item "PROBLEM" 156 | What problem are we searching for? This can be a regular expression. We 157 | only print hosts that have service problems that match the regex. 158 | .Sp 159 | \&\s-1SPECIAL CASE:\s0 if the problem is 'ping', then we'll do a host check for 160 | down hosts. 161 | .IP "\fB\-\-no_critical\fR" 4 162 | .IX Item "--no_critical" 163 | Skip '\s-1CRIT\s0' errors. 164 | .IP "\fB\-\-no_unknown\fR" 4 165 | .IX Item "--no_unknown" 166 | Skip '\s-1UNKN\s0' errors. 167 | .IP "\fB\-\-no_warnings\fR" 4 168 | .IX Item "--no_warnings" 169 | Skip '\s-1WARN\s0' errors. 170 | .IP "\fB\-\-verbose\fR" 4 171 | .IX Item "--verbose" 172 | Print more information than just the hostname. 173 | .SS "\s-1DEFAULT\s0" 174 | .IX Subsection "DEFAULT" 175 | .IP "\fB\-\-debug\fR" 4 176 | .IX Item "--debug" 177 | If set, print debugging information. 178 | .IP "\fB\-\-help\fR" 4 179 | .IX Item "--help" 180 | Print this information and exit. 181 | .SS "\s-1CONNECTION OPTIONS\s0" 182 | .IX Subsection "CONNECTION OPTIONS" 183 | .IP "\fB\-\-apikey\fR \fIkey\fR" 4 184 | .IX Item "--apikey key" 185 | Password for the \s-1API\s0 User. Default: comes from the configuration file. 186 | .IP "\fB\-\-server\fR \fIserver\fR" 4 187 | .IX Item "--server server" 188 | Host name of the server. Default: comes from the configuration file. 189 | .IP "\fB\-\-site\fR \fIsite\fR" 4 190 | .IX Item "--site site" 191 | Site name within the server. Default: comes from the configuration file. 192 | .IP "\fB\-\-user\fR \fIuser\fR" 4 193 | .IX Item "--user user" 194 | \&\s-1API\s0 User name. The user must exist on the server, and be an 'automation 195 | user'. Default: comes from the configuration file. 196 | .SS "\s-1CREATE/UPDATE OPTIONS\s0" 197 | .IX Subsection "CREATE/UPDATE OPTIONS" 198 | .IP "role" 4 199 | .IX Item "role" 200 | check_mk role name. This can either be simple ('bastion') or more complex 201 | based on group name ('htcondor_cmsgrid_worker'). Must already exist on 202 | the server side. 203 | .IP "instance" 4 204 | .IX Item "instance" 205 | check_mk instance name. This can be 'test', 'dev', 'itb', or anything 206 | else that seems appropriate. Must already exist on the server side. 207 | .IP "extra" 4 208 | .IX Item "extra" 209 | Not yet in use. If you set to 'unmonitored', then we'll delete the entry. 210 | .SH "FILES" 211 | .IX Header "FILES" 212 | .IP "\fI/etc/omdclient/config.yaml\fR" 4 213 | .IX Item "/etc/omdclient/config.yaml" 214 | .SH "SEE ALSO" 215 | .IX Header "SEE ALSO" 216 | https://mathias\-kettner.de/checkmk_wato_webapi.html 217 | .SH "AUTHOR" 218 | .IX Header "AUTHOR" 219 | Tim Skirvin 220 | .SH "LICENSE + COPYRIGHT" 221 | .IX Header "LICENSE + COPYRIGHT" 222 | Copyright 2016, Fermi National Accelerator Laboratory 223 | .PP 224 | This program is free software; you may redistribute it and/or modify it 225 | under the same terms as Perl itself. 226 | -------------------------------------------------------------------------------- /usr/bin/omd-host-crud: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """ 3 | Created/Read/Update/Delete interface to the OMD WATO API. 4 | """ 5 | 6 | ######################################################################### 7 | ### Declarations ######################################################## 8 | ######################################################################### 9 | 10 | import omdclient, optparse, os, re, sys 11 | 12 | ######################################################################### 13 | ### Configuration ####################################################### 14 | ######################################################################### 15 | 16 | ## Central configuration file. 17 | config_file_base = '/etc/omdclient/config.yaml' 18 | 19 | ## Default values for role/instance/extra for create/update. 20 | role = 'UNSET' 21 | instance = 'UNSET' 22 | extra = 'UNSET' 23 | folder = 'UNSET' 24 | ip = 'UNSET' 25 | 26 | ## Text for --help 27 | text = "Manage a given host in OMD, using the WATO API" 28 | usage_text = "usage: %prog [create|read|update|delete] HOSTNAME [options]" 29 | 30 | ######################################################################### 31 | ### Subroutines ######################################################### 32 | ######################################################################### 33 | 34 | def printReport(result, opt): 35 | """ 36 | Given the result from query(), print a useful report regarding the 37 | host. 38 | """ 39 | att = result['attributes'] 40 | print(result['hostname']) 41 | if att.get('alias', None): 42 | print(" %-20s %s" % ('alias', att['alias'])) 43 | print(" %-20s %s" % ('folder', result['path'])) 44 | print(" tags") 45 | for i in sorted(att): 46 | m = re.search('tag_(.*)', i) 47 | if m: 48 | tag = m.group(1) 49 | if tag is not None: 50 | if i in att: 51 | print(" %-40s %s" % (tag, att.get(i))) 52 | 53 | ######################################################################### 54 | ### main () ############################################################# 55 | ######################################################################### 56 | 57 | def main(): 58 | config_file = os.environ.get('OMDCONFIG', config_file_base) 59 | try: 60 | config = omdclient.loadCfg(config_file) 61 | except Exception as e: 62 | print("failed to load config: %s" % (e)) 63 | sys.exit(3) 64 | 65 | p = omdclient.generateParser(text, usage_text, config) 66 | group = optparse.OptionGroup(p, 'create/update options') 67 | group.add_option('--role', dest='role', default=role, 68 | help='role name (default: %default)') 69 | group.add_option('--instance', dest='instance', default=instance, 70 | help='instance name (default: %default)') 71 | group.add_option('--extra', dest='extra', default=extra, 72 | help='extra flags (space separated, default: %default)') 73 | group.add_option('--folder', dest='folder', default=folder, 74 | help='set WATO folder (default: %default)') 75 | group.add_option('--ip', dest='ip', default=ip, 76 | help='set IP address') 77 | p.add_option_group(group) 78 | opt, args = p.parse_args() 79 | 80 | argdict = omdclient.parserArgDict(opt) 81 | argdict['instance'] = opt.instance 82 | argdict['role'] = opt.role 83 | argdict['extra'] = opt.extra 84 | if not opt.folder == 'UNSET': 85 | argdict['folder'] = opt.folder 86 | if not opt.ip == 'UNSET': 87 | argdict['ip'] = opt.ip 88 | 89 | if len(args) != 2: 90 | p.print_help() 91 | sys.exit(1) 92 | 93 | request = args[0] 94 | host = args[1] 95 | 96 | try: 97 | 98 | if request == 'create': 99 | value, result = omdclient.createHost(host, argdict) 100 | if value is False: 101 | if result is None: print("%s - unknown error" % host) 102 | else: print("error on create: %s" % result) 103 | sys.exit(1) 104 | 105 | print("%s - host created, will now inventory..." % host) 106 | 107 | value1, result1 = omdclient.discoverServicesHost(host, argdict) 108 | if value1 is False: 109 | if result is None: print("%s - unknown error" % host) 110 | else: print("error on inventory: %s" % result) 111 | sys.exit(1) 112 | else: 113 | print("%s - %s" % (host, result1)) 114 | sys.exit(0) 115 | 116 | elif request == 'inventory': 117 | value1, result1 = omdclient.discoverServicesHost(host, argdict) 118 | if value1 is False: 119 | if result is None: print("%s - unknown error" % host) 120 | else: print("error on inventory: %s" % result) 121 | sys.exit(1) 122 | else: 123 | print("%s - %s" % (host, result1)) 124 | sys.exit(0) 125 | 126 | elif request == 'read': 127 | value, result = omdclient.readHost(host, argdict) 128 | if value is False: 129 | if result is None: print("%s - unknown error" % host) 130 | else: print(result) 131 | sys.exit(1) 132 | else: 133 | printReport(result, opt) 134 | sys.exit(0) 135 | 136 | elif request == 'update': 137 | value, result = omdclient.updateHost(host, argdict) 138 | if value is False: 139 | if result is None: print("%s - unknown error" % host) 140 | else: print("error on update: %s" % result) 141 | sys.exit(1) 142 | 143 | print("%s - host updated, will now inventory..." % host) 144 | 145 | value1, result1 = omdclient.discoverServicesHost(host, argdict) 146 | if value1 is False: 147 | if result is None: print("%s - unknown error" % host) 148 | else: print("error on inventory: %s" % result) 149 | sys.exit(1) 150 | else: 151 | print("%s - %s" % (host, result1)) 152 | sys.exit(0) 153 | 154 | elif request == 'delete': 155 | value, result = omdclient.deleteHost(host, argdict) 156 | if value is False: 157 | if result is None: print("%s - unknown error" % host) 158 | else: print(result) 159 | sys.exit(1) 160 | else: 161 | print("%s - host deleted" % host) 162 | sys.exit(0) 163 | 164 | else: 165 | p.print_help('invalid request name: %s' % request) 166 | sys.exit(1) 167 | 168 | except Exception as e: 169 | print("failed to %s: %s" % (request, e)) 170 | sys.exit(-1) 171 | 172 | if __name__ == "__main__": 173 | main() 174 | 175 | ######################################################################### 176 | ### POD Documentation ################################################### 177 | ######################################################################### 178 | 179 | """ 180 | 181 | =head1 NAME 182 | 183 | omd-host-crud - create/read/update/delete omd host entries 184 | 185 | =head1 SYNOPSIS 186 | 187 | B create cms-foo --role unconfigured 188 | 189 | B inventory cms-foo 190 | 191 | B read cms-foo 192 | 193 | B update cms-foo --instance dev 194 | 195 | B delete cms-foo 196 | 197 | =head1 USAGE 198 | 199 | omd-host-crud provides a CRUD (Create/Read/Update/Delete) interface 200 | to the OMD/WATO check_mk web interface. 201 | 202 | =head1 ARGUMENTS 203 | 204 | =head2 REQUIRED 205 | 206 | =over 4 207 | 208 | =item I 209 | 210 | create, inventory, read, update, delete. 211 | 212 | =item I 213 | 214 | Hostname for which to query. No default, must be set. 215 | 216 | =back 217 | 218 | =head2 DEFAULT 219 | 220 | =over 4 221 | 222 | =item B<--debug> 223 | 224 | If set, print debugging information. 225 | 226 | =item B<--help> 227 | 228 | Print this information and exit. 229 | 230 | =back 231 | 232 | =head2 CONNECTION OPTIONS 233 | 234 | =over 4 235 | 236 | =item B<--apikey> I 237 | 238 | Password for the API User. Default: comes from the configuration file. 239 | 240 | =item B<--server> I 241 | 242 | Host name of the server. Default: comes from the configuration file. 243 | 244 | =item B<--site> I 245 | 246 | Site name within the server. Default: comes from the configuration file. 247 | 248 | =item B<--user> I 249 | 250 | API User name. The user must exist on the server, and be an 'automation 251 | user'. Default: comes from the configuration file. 252 | 253 | =back 254 | 255 | =head2 CREATE/UPDATE OPTIONS 256 | 257 | =over 4 258 | 259 | =item role 260 | 261 | check_mk role name. This can either be simple ('bastion') or more complex 262 | based on group name ('htcondor_cmsgrid_worker'). Must already exist on 263 | the server side. 264 | 265 | =item instance 266 | 267 | check_mk instance name. This can be 'test', 'dev', 'itb', or anything 268 | else that seems appropriate. Must already exist on the server side. 269 | 270 | =item extra 271 | 272 | Not yet in use. If you set to 'unmonitored', then we'll delete the entry. 273 | 274 | =back 275 | 276 | =head1 FILES 277 | 278 | =over 4 279 | 280 | =item F 281 | 282 | =back 283 | 284 | =head1 SEE ALSO 285 | 286 | https://mathias-kettner.de/checkmk_wato_webapi.html 287 | 288 | =head1 AUTHOR 289 | 290 | Tim Skirvin 291 | 292 | =head1 LICENSE + COPYRIGHT 293 | 294 | Copyright 2015-2017, Fermi National Accelerator Laboratory 295 | 296 | This program is free software; you may redistribute it and/or modify it 297 | under the same terms as Perl itself. 298 | 299 | =cut 300 | 301 | """ 302 | -------------------------------------------------------------------------------- /omdclient/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | Shared functions for interacting with an OMD site remotely. 3 | """ 4 | 5 | ######################################################################### 6 | ### Configuration ####################################################### 7 | ######################################################################### 8 | 9 | config = {} 10 | 11 | ######################################################################### 12 | ### Declarations ######################################################## 13 | ######################################################################### 14 | 15 | import datetime, json, optparse, re, sys, urllib.request, \ 16 | urllib.parse, urllib.error, urllib.request, urllib.error, \ 17 | urllib.parse, yaml 18 | from bs4 import BeautifulSoup 19 | from pprint import pprint 20 | 21 | ######################################################################### 22 | ### Script Helpers ###################################################### 23 | ######################################################################### 24 | 25 | def loadCfg(config_file): 26 | """ 27 | Load a .yaml configuration file into the config hash. 28 | """ 29 | 30 | try: 31 | config = yaml.safe_load(open(config_file, 'r')) 32 | except IOError as exc: 33 | raise Exception('%s' % exc) 34 | except yaml.YAMLError as exc: 35 | raise Exception('yaml error: %s' % exc) 36 | sys.exit(3) 37 | except Exception as exc: 38 | raise Exception('unknown error: %s' % exc) 39 | sys.exit(3) 40 | 41 | return config 42 | 43 | def generateParser(text, usage_text, config): 44 | """ 45 | Generate an OptionParser object for use across all scripts. We want 46 | something consistent so we can use the same server/site/user options 47 | globally. 48 | """ 49 | p = optparse.OptionParser(usage=usage_text, description=text) 50 | p.add_option('--debug', dest='debug', action='store_true', 51 | default=False, help='set to print debugging information') 52 | group = optparse.OptionGroup(p, "connection options") 53 | group.add_option('--server', dest='server', default=config['server'], 54 | help='server name (default: %default)') 55 | group.add_option('--site', dest='site', default=config['site'], 56 | help='site name (default: %default)') 57 | group.add_option('--user', dest='user', default=config['user'], 58 | help='user name (default: %default)') 59 | group.add_option('--apikey', dest='apikey', default=config['apikey'], 60 | help='api key (not printing the default)') 61 | group.add_option('--remove', action="store_true", dest='remove', default=False, 62 | help='removes a downtime') 63 | p.add_option_group(group) 64 | return p 65 | 66 | 67 | def parserArgDict(opthash): 68 | """ 69 | Converts the data from the OptionParser object into a dictionary 70 | object, so that we can easily use it elsewhere. 71 | """ 72 | args = { 73 | 'apikey': opthash.apikey, 74 | 'debug': opthash.debug, 75 | 'server': opthash.server, 76 | 'site': opthash.site, 77 | 'user': opthash.user, 78 | 'remove': opthash.remove 79 | } 80 | return args 81 | 82 | ######################################################################### 83 | ### URL Management ###################################################### 84 | ######################################################################### 85 | 86 | def generateUrl(action, args): 87 | """ 88 | Generate the URL used to interact with the server. 89 | action What action are we taking? Valid options: 90 | 91 | activate_changes 92 | add_host 93 | delete_host 94 | discover_services 95 | get_all_hosts 96 | get_host 97 | 98 | args Argument dict. You must have at least these keys: 99 | 100 | apikey 101 | server 102 | site 103 | user 104 | 105 | ...and you can optionally include: 106 | 107 | effective_attributes For 'get_host' 108 | foreign_ok For 'activate_changes' 109 | create_folders For 'add_host' 110 | 111 | If 'debug' is set, we'll print the URL to stdout (with the password 112 | blanked out). 113 | """ 114 | baseurl = 'https://%s/%s/check_mk/webapi.py?_username=%s' % \ 115 | (args['server'], args['site'], args['user']) 116 | url_parts = [baseurl] 117 | 118 | if action == 'activate_changes': 119 | url_parts.append('action=activate_changes') 120 | url_parts.append('mode=dirty') 121 | if 'foreign_ok' in list(args.keys()): 122 | if args['foreign_ok']: url_parts.append('allow_foreign_changes=1') 123 | 124 | elif action == 'add_host': 125 | url_parts.append('action=add_host') 126 | if 'create_folders' in list(args.keys()): 127 | if args['create_folders']: url_parts.append('create_folders=0') 128 | 129 | elif action == 'delete_host': 130 | url_parts.append('action=delete_host') 131 | 132 | elif action == 'edit_host': 133 | url_parts.append('action=edit_host') 134 | 135 | elif action == 'discover_services': 136 | url_parts.append('action=discover_services') 137 | if 'tabula_rasa' in list(args.keys()): 138 | if args['tabula_rasa']: url_parts.append('mode=refresh') 139 | 140 | elif action == 'get_all_hosts': 141 | url_parts.append('action=get_all_hosts') 142 | 143 | elif action == 'get_host': 144 | url_parts.append('action=get_host') 145 | if 'effective_attributes' in list(args.keys()): 146 | url_parts.append('effective_attributes=%s' 147 | % args['effective_attributes']) 148 | 149 | else: 150 | raise Exception('invalid action: %s' % action) 151 | 152 | if args['debug']: 153 | url_parts_clean = url_parts 154 | url_parts_clean.append('_secret=...') 155 | print("url: %s" % '&'.join(url_parts_clean)) 156 | 157 | url_parts.append('_secret=%s' % args['apikey']) 158 | 159 | return '&'.join(url_parts) 160 | 161 | def loadUrl(url, request_string): 162 | """ 163 | Load the URL and request string pair. Returns a urllib2 response. 164 | """ 165 | try: 166 | response = urllib.request.urlopen(url, request_string.encode('utf-8')) 167 | except urllib.error.HTTPError as err: 168 | if err.code == 404: 169 | raise Exception('Page not found') 170 | elif err.code == 403: 171 | raise Exception('Access Denied') 172 | else: 173 | raise Exception('http error, code %s' % err.code) 174 | except urllib.error.URLError as err: 175 | raise Exception('url error: %s' % err.reason) 176 | return response 177 | 178 | def processUrlResponse(response, debug): 179 | """ 180 | Process the response from loadUrl(). Returns two objects: did we get 181 | a 'True' response from the server, and the response itself. 182 | 183 | If 'debug' is set, we'll print a lot of extra debugging information. 184 | 185 | Code taken from Ed Simmonds . 186 | """ 187 | 188 | data = response.read().decode() 189 | 190 | try: 191 | jsonresult = json.loads(data) 192 | if debug: pprint(jsonresult) 193 | except ValueError: 194 | soup = BeautifulSoup(data, 'lxml') 195 | div1 = soup.find('div', attrs={'class': 'error'}) 196 | if div1 is not None: 197 | print("Error returned") 198 | print(div1.string) 199 | return False, None 200 | else: 201 | print("ValueError. Invalid JSON object returned, and could not extract error. Full response was:") 202 | print(data) 203 | return False, None 204 | 205 | if jsonresult['result_code'] == 0: 206 | return True, jsonresult['result'] 207 | else: 208 | if debug: print("result code was: %s" % jsonresult['result_code']) 209 | return False, jsonresult['result'] 210 | 211 | return False, jsonresult 212 | 213 | ######################################################################### 214 | ### WATO API Interactions ############################################### 215 | ######################################################################### 216 | 217 | def activateChanges(arghash): 218 | """ 219 | Activate changes. This can be slow. 220 | """ 221 | url = generateUrl('activate_changes', arghash) 222 | response = loadUrl(url, '') 223 | return processUrlResponse(response, arghash['debug']) 224 | 225 | def createHost(host, arghash): 226 | """ 227 | Create a host entry. 228 | 229 | folder Default: omdclient-api 230 | role 231 | instance 232 | extra 233 | 234 | Note that `tag_role` and `tag_instance` are tags used locally to tie 235 | together local local puppet instance and our OMD folders. You don't 236 | have to use them and may cheerfully ignore them. 237 | """ 238 | 239 | request = {} 240 | request['hostname'] = host 241 | 242 | if 'folder' in arghash: request['folder'] = arghash['folder'] 243 | else: request['folder'] = 'omdclient-api' 244 | 245 | attributes = {} 246 | if 'role' in arghash: 247 | if arghash['role'] != 'UNSET': 248 | attributes['tag_role'] = arghash['role'] 249 | if 'instance' in arghash: 250 | if arghash['instance'] != 'UNSET': 251 | attributes['tag_instance'] = arghash['instance'] 252 | if 'ip' in arghash: 253 | if arghash['ip'] != 'UNSET': 254 | attributes['ipaddress'] = arghash['ip'] 255 | if 'extra' in arghash: 256 | if arghash['extra'] != 'UNSET' and '=' in arghash['extra']: 257 | import shlex 258 | attributes.update(dict(token.split('=') for token in shlex.split(arghash['extra']))) 259 | request['attributes'] = attributes 260 | 261 | url = generateUrl('add_host', arghash) 262 | 263 | request_string = "request=%s" % json.dumps(request) 264 | if arghash['debug']: print(request_string) 265 | 266 | response = loadUrl(url, request_string) 267 | return processUrlResponse(response, arghash['debug']) 268 | 269 | def readHost(host, arghash): 270 | """ 271 | Get information about a host. 272 | """ 273 | url = generateUrl('get_host', arghash) 274 | 275 | request_string = 'request={"hostname" : "%s"}' % (host) 276 | response = loadUrl(url, request_string) 277 | return processUrlResponse(response, arghash['debug']) 278 | 279 | def updateHost(host, arghash): 280 | """ 281 | Update information from a host. If the host does not already exist, 282 | we'll call createHost instead. 283 | """ 284 | 285 | if readHost(host, arghash): pass 286 | else: 287 | return createHost(host, arghash) 288 | 289 | url = generateUrl('edit_host', arghash) 290 | 291 | request = {} 292 | request['hostname'] = host 293 | 294 | attributes = {} 295 | if 'role' in arghash: 296 | if arghash['role'] != 'UNSET': 297 | attributes['tag_role'] = arghash['role'] 298 | if 'instance' in arghash: 299 | if arghash['instance'] != 'UNSET': 300 | attributes['tag_instance'] = arghash['instance'] 301 | if 'ip' in arghash: 302 | if arghash['ip'] != 'UNSET': 303 | attributes['ipaddress'] = arghash['ip'] 304 | if 'extra' in arghash: 305 | if arghash['extra'] != 'UNSET' and '=' in arghash['extra']: 306 | import shlex 307 | attributes.update(dict(token.split('=') for token in shlex.split(arghash['extra']))) 308 | request['attributes'] = attributes 309 | 310 | if 'unset' in arghash: 311 | request['unset_attributes'] = [arghash['unset']] 312 | 313 | request_string = "request=%s" % json.dumps(request) 314 | if arghash['debug']: print(request_string) 315 | 316 | response = loadUrl(url, request_string) 317 | return processUrlResponse(response, arghash['debug']) 318 | 319 | def listHosts(arghash): 320 | """ 321 | List all hosts. 322 | """ 323 | url = generateUrl('get_all_hosts', arghash) 324 | response = loadUrl(url, '') 325 | return processUrlResponse(response, arghash['debug']) 326 | 327 | def listHostsFiltered(filter, arghash): 328 | """ 329 | List all hosts filtered by site. 330 | """ 331 | url = generateUrl('get_all_hosts', arghash) 332 | response = loadUrl(url, '') 333 | status, response = processUrlResponse(response, arghash['debug']) 334 | response_filtered = dict(response) 335 | for h in response: 336 | if response[h].get('attributes', {}).get('site', '') != filter: 337 | del response_filtered[h] 338 | return status, response_filtered 339 | 340 | def deleteHost(host, arghash): 341 | """ 342 | Remove a host from check_mk. 343 | """ 344 | url = generateUrl('delete_host', arghash) 345 | request_string = 'request={"hostname" : "%s"}' % (host) 346 | response = loadUrl(url, request_string) 347 | return processUrlResponse(response, arghash['debug']) 348 | 349 | def discoverServicesHost(host, arghash): 350 | """ 351 | Scan a host for services. 352 | """ 353 | url = generateUrl('discover_services', arghash) 354 | request_string = 'request={"hostname" : "%s"}' % (host) 355 | response = loadUrl(url, request_string) 356 | return processUrlResponse(response, arghash['debug']) 357 | 358 | ######################################################################### 359 | ### Nagios API Commands ################################################# 360 | ######################################################################### 361 | 362 | def generateNagiosUrl(action, args): 363 | """ 364 | Generate the URL used to interact with the server. 365 | action What action are we taking? Valid options: 366 | 367 | ack 368 | downtime 369 | hostreport 370 | svcreport 371 | 372 | args Argument dict. You must have at least these keys: 373 | 374 | apikey 375 | server 376 | site 377 | user 378 | view_name 379 | 380 | ...and you can optionally include: 381 | 382 | ack Associated with hostreport and svcreport; if set, 383 | we will only load acknowledged (1) or unacknowledged 384 | (0) alerts. 385 | end Associated with 'downtime': a datetime object 386 | indicating the end of the work. If not offered, 387 | we'll use start + 'hours' hours. 388 | hours Associated with 'downtime'; indicates a number of 389 | hours of downtime. Used if we don't have a set 390 | 'end' time. 391 | host Associated with 'downtime' and 'ack': hostname. 392 | service Associated with 'downtime' and 'ack': service name. 393 | start Associated with 'downtime'; a datetime object 394 | indicating the start of the work. If not offered, 395 | we'll just use 'now()'. 396 | type Associated with 'ack' or 'downtime'; must be one of 397 | 'host' or 'service'. 398 | 399 | If 'debug' is set, we'll print the URL to stdout (with the password 400 | blanked out). 401 | """ 402 | baseurl = 'https://%s/%s/check_mk/view.py' % (args['server'], args['site']) 403 | url_parts = {} 404 | url_parts['_username'] = args['user'] 405 | url_parts['_secret'] = args['apikey'] 406 | url_parts['output_format'] = 'json' 407 | 408 | if action == 'hostreport': 409 | url_parts['view_name'] = 'hostproblems_expanded' 410 | if 'ack' in list(args.keys()): 411 | url_parts['is_host_acknowledged'] = args['ack'] 412 | 413 | elif action == 'svcreport': 414 | url_parts['view_name'] = 'svcproblems_expanded' 415 | if 'ack' in list(args.keys()): 416 | url_parts['is_service_acknowledged'] = args['ack'] 417 | if 'all' in list(args.keys()): 418 | url_parts['is_service_acknowledged'] = args['all'] 419 | 420 | elif action == 'downtime': 421 | url_parts['_transid'] = '-1' 422 | url_parts['_do_confirm'] = 'yes' 423 | url_parts['_do_actions'] = 'yes' 424 | 425 | if args['remove']: 426 | url_parts['_remove_downtimes'] = 'Remove' 427 | url_parts['_down_remove'] = 'Remove' 428 | else: 429 | if 'start' in list(args.keys()): start = args['start'] 430 | else: start = datetime.datetime.now() 431 | if 'end' in list(args.keys()): end = args['end'] 432 | else: 433 | end = start + datetime.timedelta(hours=int(args['hours'])) 434 | 435 | url_parts['_down_custom'] = 'Custom+time_range' 436 | url_parts['_down_from_date'] = start.date() 437 | url_parts['_down_from_time'] = start.strftime('%H:%M') 438 | url_parts['_down_to_date'] = end.date() 439 | url_parts['_down_to_time'] = end.strftime('%H:%M') 440 | url_parts['_down_comment'] = args['comment'] 441 | 442 | if args['type'] == 'host': 443 | url_parts['host'] = args['host'] 444 | url_parts['view_name'] = 'hoststatus' 445 | elif args['type'] == 'svc' or args['type'] == 'service': 446 | url_parts['host'] = args['host'] 447 | url_parts['service'] = args['service'] 448 | url_parts['view_name'] = 'service' 449 | else: 450 | raise Exception('invalid downtime type: %s' % args['type']) 451 | 452 | elif action == 'ack': 453 | url_parts['_transid'] = '-1' 454 | url_parts['_do_confirm'] = 'yes' 455 | url_parts['_do_actions'] = 'yes' 456 | 457 | url_parts['_ack_comment'] = args['comment'] 458 | url_parts['_acknowledge'] = 'Acknowledge' 459 | if args['type'] == 'host': 460 | url_parts['host'] = args['host'] 461 | url_parts['view_name'] = 'hoststatus' 462 | elif args['type'] == 'svc' or args['type'] == 'service': 463 | url_parts['host'] = args['host'] 464 | url_parts['service'] = args['service'] 465 | url_parts['view_name'] = 'service' 466 | else: 467 | raise Exception('invalid ack type: %s' % args['type']) 468 | 469 | elif action == 'get_host': 470 | url_parts['action'] = 'get_host' 471 | url_parts['host'] = 'ssiadmin4' 472 | 473 | else: 474 | raise Exception('invalid action: %s' % action) 475 | 476 | if args['debug']: 477 | url_parts_clean = dict(url_parts) 478 | url_parts_clean['_secret'] = '...' 479 | print("url: %s?%s" % (baseurl, urllib.parse.urlencode(url_parts_clean))) 480 | 481 | url = "%s?%s" % (baseurl, urllib.parse.urlencode(url_parts)) 482 | return url 483 | 484 | 485 | def nagiosAck(params): 486 | """ 487 | Acknowledge an alert in Nagios. Returns a report, but the report may 488 | not be very helpful. 489 | """ 490 | url = generateNagiosUrl('ack', params) 491 | response = loadUrl(url, '') 492 | return processNagiosReport(response, params['debug']) 493 | 494 | def nagiosDowntime(params): 495 | """ 496 | Schedule downtime in Nagios. Returns a report, but the report may 497 | not be very helpful. 498 | """ 499 | url = generateNagiosUrl('downtime', params) 500 | response = loadUrl(url, '') 501 | return processNagiosReport(response, params['debug']) 502 | 503 | def nagiosReport(type, argdict): 504 | """ 505 | Generate a nagios report. Type can be one of 'svc_ack', 'svc_unack', 506 | 'host_ack', or 'host_unack'. 507 | """ 508 | args = argdict.copy() 509 | if type == 'svc_ack': 510 | action = 'svcreport' 511 | args['ack'] = 1 512 | elif type == 'svc_unack': 513 | action = 'svcreport' 514 | args['ack'] = 0 515 | elif type == 'host_ack': 516 | action = 'hostreport' 517 | args['ack'] = 1 518 | elif type == 'host_unack': 519 | action = 'hostreport' 520 | args['ack'] = 0 521 | elif type == 'host': 522 | action = 'hostreport' 523 | elif type == 'hostservice': 524 | action = 'svcreport' 525 | elif type == 'get_host': 526 | action = 'get_host' 527 | else: 528 | raise Exception('invalid report type: %s' % type) 529 | 530 | url = generateNagiosUrl(action, args) 531 | response = loadUrl(url, '') 532 | return processNagiosReport(response, argdict['debug']) 533 | 534 | def processNagiosReport(response, debug): 535 | """ 536 | Process the response from loadUrl(). Returns an array of matching 537 | objects, where we've trimmed off the first one (which described the 538 | fields of the later objects). 539 | 540 | If 'debug' is set, we'll print a lot of extra debugging information. 541 | 542 | Incidentally, we're doing some really ugly stuff here because check_mk 543 | isn't always returning with json, even when we ask it to. 544 | """ 545 | 546 | data = response.read().decode() 547 | 548 | try: 549 | jsonresult = json.loads(data) 550 | if debug: pprint(jsonresult) 551 | except ValueError: 552 | lines = data.split('\n') 553 | if re.match('^MESSAGE: .*$', lines[0]): 554 | return lines[0] 555 | soup = BeautifulSoup(data, 'lxml') 556 | div1 = soup.find('div', attrs={'class': 'error'}) 557 | if div1 is not None: 558 | print("Error returned") 559 | print(div1.string) 560 | return [] 561 | else: 562 | print("ValueError. Invalid JSON object returned, and could not extract error. Full response was:") 563 | print(data) 564 | return [] 565 | 566 | if len(jsonresult) <= 1: return [] 567 | 568 | jsonresult.pop(0) 569 | return jsonresult 570 | --------------------------------------------------------------------------------