From 1d5cf49317ad3d88cecda31a38a88fd82386a6a1 Mon Sep 17 00:00:00 2001 From: Sean McGinnis Date: Thu, 10 Sep 2020 20:05:01 -0500 Subject: [PATCH] Retire repo and note new content in openstack/osops Change-Id: I56f2e8ef904d9d844a65c2982b3b5f4fae38850e Signed-off-by: Sean McGinnis --- .gitignore | 54 --- LICENSE | 201 ---------- README.md | 32 +- monitoring-for-openstack/.testr.conf | 4 - monitoring-for-openstack/README.rst | 25 -- monitoring-for-openstack/doc/source/conf.py | 258 ------------- monitoring-for-openstack/doc/source/index.rst | 22 -- monitoring-for-openstack/oschecks/__init__.py | 0 monitoring-for-openstack/oschecks/amqp.py | 37 -- .../oschecks/ceilometer.py | 63 --- monitoring-for-openstack/oschecks/ceph.py | 143 ------- monitoring-for-openstack/oschecks/cinder.py | 285 -------------- monitoring-for-openstack/oschecks/glance.py | 145 ------- monitoring-for-openstack/oschecks/keystone.py | 48 --- monitoring-for-openstack/oschecks/neutron.py | 270 ------------- monitoring-for-openstack/oschecks/nova.py | 362 ------------------ .../oschecks/pacemaker_host_check.py | 161 -------- monitoring-for-openstack/oschecks/process.py | 37 -- .../oschecks/tests/__init__.py | 0 .../oschecks/tests/test_ceph.py | 45 --- .../oschecks/tests/test_script.py | 46 --- monitoring-for-openstack/oschecks/utils.py | 306 --------------- monitoring-for-openstack/requirements.txt | 9 - monitoring-for-openstack/setup.cfg | 52 --- monitoring-for-openstack/setup.py | 21 - .../test-requirements.txt | 3 - monitoring-for-openstack/tox.ini | 40 -- nagios-plugins/check_ceilometer_update.py | 87 ----- nagios-plugins/check_ip_pool.py | 81 ---- nagios-plugins/cinder-services.sh | 16 - nagios-plugins/glance-list.sh | 19 - nagios-plugins/horizon.sh | 28 -- nagios-plugins/keystone-token.sh | 12 - nagios-plugins/libvirt-virsh.sh | 12 - nagios-plugins/nova-services.sh | 16 - nagios-plugins/swift-healthcheck.sh | 10 - sensu-plugins/check_keystone-api.rb | 86 ----- 37 files changed, 10 insertions(+), 3026 deletions(-) delete mode 100644 .gitignore delete mode 100644 LICENSE delete mode 100644 monitoring-for-openstack/.testr.conf delete mode 100644 monitoring-for-openstack/README.rst delete mode 100644 monitoring-for-openstack/doc/source/conf.py delete mode 100644 monitoring-for-openstack/doc/source/index.rst delete mode 100644 monitoring-for-openstack/oschecks/__init__.py delete mode 100644 monitoring-for-openstack/oschecks/amqp.py delete mode 100644 monitoring-for-openstack/oschecks/ceilometer.py delete mode 100644 monitoring-for-openstack/oschecks/ceph.py delete mode 100644 monitoring-for-openstack/oschecks/cinder.py delete mode 100644 monitoring-for-openstack/oschecks/glance.py delete mode 100644 monitoring-for-openstack/oschecks/keystone.py delete mode 100644 monitoring-for-openstack/oschecks/neutron.py delete mode 100644 monitoring-for-openstack/oschecks/nova.py delete mode 100644 monitoring-for-openstack/oschecks/pacemaker_host_check.py delete mode 100644 monitoring-for-openstack/oschecks/process.py delete mode 100644 monitoring-for-openstack/oschecks/tests/__init__.py delete mode 100644 monitoring-for-openstack/oschecks/tests/test_ceph.py delete mode 100644 monitoring-for-openstack/oschecks/tests/test_script.py delete mode 100644 monitoring-for-openstack/oschecks/utils.py delete mode 100644 monitoring-for-openstack/requirements.txt delete mode 100644 monitoring-for-openstack/setup.cfg delete mode 100755 monitoring-for-openstack/setup.py delete mode 100644 monitoring-for-openstack/test-requirements.txt delete mode 100644 monitoring-for-openstack/tox.ini delete mode 100755 nagios-plugins/check_ceilometer_update.py delete mode 100755 nagios-plugins/check_ip_pool.py delete mode 100644 nagios-plugins/cinder-services.sh delete mode 100644 nagios-plugins/glance-list.sh delete mode 100644 nagios-plugins/horizon.sh delete mode 100644 nagios-plugins/keystone-token.sh delete mode 100644 nagios-plugins/libvirt-virsh.sh delete mode 100644 nagios-plugins/nova-services.sh delete mode 100644 nagios-plugins/swift-healthcheck.sh delete mode 100755 sensu-plugins/check_keystone-api.rb diff --git a/.gitignore b/.gitignore deleted file mode 100644 index 51cbe85..0000000 --- a/.gitignore +++ /dev/null @@ -1,54 +0,0 @@ -# Byte-compiled / optimized / DLL files -__pycache__/ -*.py[cod] - -# C extensions -*.so - -# Distribution / packaging -.Python -env/ -bin/ -build/ -develop-eggs/ -dist/ -eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -*.egg-info/ -.installed.cfg -*.egg - -# Installer logs -pip-log.txt -pip-delete-this-directory.txt - -# Unit test / coverage reports -htmlcov/ -.tox/ -.coverage -.cache -nosetests.xml -coverage.xml - -# Translations -*.mo - -# Mr Developer -.mr.developer.cfg -.project -.pydevproject - -# Rope -.ropeproject - -# Django stuff: -*.log -*.pot - -# Sphinx documentation -docs/_build/ - diff --git a/LICENSE b/LICENSE deleted file mode 100644 index 5c304d1..0000000 --- a/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ -Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "{}" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright {yyyy} {name of copyright owner} - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/README.md b/README.md index 2fed9ac..7cd561c 100644 --- a/README.md +++ b/README.md @@ -1,24 +1,12 @@ -# tools-monitoring +This project is no longer maintained. Its content has now moved to the +https://opendev.org/openstack/osops repo, and further development will +continue there. -Tools to monitor OpenStack +The contents of this repository are still available in the Git +source code management system. To see the contents of this +repository before it reached its end of life, please check out the +previous commit with "git checkout HEAD^1". -Please see the wiki page at https://wiki.openstack.org/wiki/Osops for other osops tools & repos. - -## Report bugs -Please use [launchpad][launchpad] to report bugs. - -[launchpad]: https://bugs.launchpad.net/osops - -## Directories - -[monitoring-for-openstack/](monitoring-for-openstack): a python application to help do some monitoring for OpenStack Clouds - -[sensu-plugins/](sensu-plugins): A collection of [sensu][sensu] specific plugins to help monitor OpenStack Clouds - -## External Links - -A collection of scripts to monitor various OpenStack components, for use with [Rackspace Cloud Monitoring (MaaS)][maas] can be found here: - - -[sensu]: https://sensuapp.org/ -[maas]: https://github.com/rcbops/rpc-maas +For any further questions, please email +openstack-discuss@lists.openstack.org or join #openstack-dev on +Freenode. diff --git a/monitoring-for-openstack/.testr.conf b/monitoring-for-openstack/.testr.conf deleted file mode 100644 index 4f48ace..0000000 --- a/monitoring-for-openstack/.testr.conf +++ /dev/null @@ -1,4 +0,0 @@ -[DEFAULT] -test_command=${PYTHON:-python} -m subunit.run discover ./oschecks/tests $LISTOPT $IDOPTION -test_id_option=--load-list $IDFILE -test_list_option=--list diff --git a/monitoring-for-openstack/README.rst b/monitoring-for-openstack/README.rst deleted file mode 100644 index d626c7b..0000000 --- a/monitoring-for-openstack/README.rst +++ /dev/null @@ -1,25 +0,0 @@ -======================== -Monitoring for OpenStack -======================== - -This is a set of Python scripts to help with the monitoring of -OpenStack services. - -Installation -============ - -* Clone the osops-tools-monitoring repository:: - - git clone https://github.com/openstack/osops-tools-monitoring - -* Change to the ``monitoring-for-openstack`` directory:: - - cd osops-tools-monitoring/monitoring-for-openstack - -* Install the requirements:: - - pip install -r requirements.txt - -* Install the ``monitoring-for-openstack`` scripts:: - - python setup.py install diff --git a/monitoring-for-openstack/doc/source/conf.py b/monitoring-for-openstack/doc/source/conf.py deleted file mode 100644 index e5a1293..0000000 --- a/monitoring-for-openstack/doc/source/conf.py +++ /dev/null @@ -1,258 +0,0 @@ -# -*- coding: utf-8 -*- -# -# monitoring-for-openstack documentation build configuration file, created by -# sphinx-quickstart on Tue Oct 28 18:03:41 2014. -# -# This file is execfile()d with the current directory set to its -# containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import sys -import os - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -#sys.path.insert(0, os.path.abspath('.')) - -# -- General configuration ------------------------------------------------ - -# If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The encoding of source files. -#source_encoding = 'utf-8-sig' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = u'monitoring-for-openstack' -copyright = u'2014, eNovance' - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -version = '1' -# The full version, including alpha/beta/rc tags. -release = '1' - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -#language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = [] - -# The reST default role (used for this markup: `text`) to use for all -# documents. -#default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -#add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -#show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] - -# If true, keep warnings as "system message" paragraphs in the built documents. -#keep_warnings = False - - -# -- Options for HTML output ---------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -html_theme = 'default' - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -#html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -#html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -#html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -#html_favicon = None - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -# Add any extra paths that contain custom files (such as robots.txt or -# .htaccess) here, relative to this directory. These files are copied -# directly to the root of the documentation. -#html_extra_path = [] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -#html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -#html_additional_pages = {} - -# If false, no module index is generated. -#html_domain_indices = True - -# If false, no index is generated. -#html_use_index = True - -# If true, the index is split into individual pages for each letter. -#html_split_index = False - -# If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -#html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None - -# Output file base name for HTML help builder. -htmlhelp_basename = 'monitoring-for-openstackdoc' - - -# -- Options for LaTeX output --------------------------------------------- - -latex_elements = { -# The paper size ('letterpaper' or 'a4paper'). -#'papersize': 'letterpaper', - -# The font size ('10pt', '11pt' or '12pt'). -#'pointsize': '10pt', - -# Additional stuff for the LaTeX preamble. -#'preamble': '', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, -# author, documentclass [howto, manual, or own class]). -latex_documents = [ - ('index', 'monitoring-for-openstack.tex', u'monitoring-for-openstack Documentation', - u'eNovance', 'manual'), -] - -# The name of an image file (relative to this directory) to place at the top of -# the title page. -#latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -#latex_use_parts = False - -# If true, show page references after internal links. -#latex_show_pagerefs = False - -# If true, show URL addresses after external links. -#latex_show_urls = False - -# Documents to append as an appendix to all manuals. -#latex_appendices = [] - -# If false, no module index is generated. -#latex_domain_indices = True - - -# -- Options for manual page output --------------------------------------- - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - ('index', 'monitoring-for-openstack', u'monitoring-for-openstack Documentation', - [u'eNovance'], 1) -] - -# If true, show URL addresses after external links. -#man_show_urls = False - - -# -- Options for Texinfo output ------------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - ('index', 'monitoring-for-openstack', u'monitoring-for-openstack Documentation', - u'eNovance', 'monitoring-for-openstack', 'One line description of project.', - 'Miscellaneous'), -] - -# Documents to append as an appendix to all manuals. -#texinfo_appendices = [] - -# If false, no module index is generated. -#texinfo_domain_indices = True - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -#texinfo_show_urls = 'footnote' - -# If true, do not generate a @detailmenu in the "Top" node's menu. -#texinfo_no_detailmenu = False diff --git a/monitoring-for-openstack/doc/source/index.rst b/monitoring-for-openstack/doc/source/index.rst deleted file mode 100644 index 10ef488..0000000 --- a/monitoring-for-openstack/doc/source/index.rst +++ /dev/null @@ -1,22 +0,0 @@ -.. monitoring-for-openstack documentation master file, created by - sphinx-quickstart on Tue Oct 28 18:03:41 2014. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -Welcome to monitoring-for-openstack's documentation! -==================================================== - -Contents: - -.. toctree:: - :maxdepth: 2 - - - -Indices and tables -================== - -* :ref:`genindex` -* :ref:`modindex` -* :ref:`search` - diff --git a/monitoring-for-openstack/oschecks/__init__.py b/monitoring-for-openstack/oschecks/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/monitoring-for-openstack/oschecks/amqp.py b/monitoring-for-openstack/oschecks/amqp.py deleted file mode 100644 index e308bf1..0000000 --- a/monitoring-for-openstack/oschecks/amqp.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Openstack Monitoring script for Sensu / Nagios -# -# Copyright © 2013-2014 eNovance -# -# Author: Mehdi Abaakouk -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import argparse - -from oschecks import utils - - -def check_amqp(): - parser = argparse.ArgumentParser( - description='Check amqp connection of an OpenStack service.') - parser.add_argument(dest='process_name', - help='Process name') - options = parser.parse_args() - utils.check_process_exists_and_amqp_connected(options.process_name) - - -def main(): - utils.safe_run(check_amqp) diff --git a/monitoring-for-openstack/oschecks/ceilometer.py b/monitoring-for-openstack/oschecks/ceilometer.py deleted file mode 100644 index 4785a0e..0000000 --- a/monitoring-for-openstack/oschecks/ceilometer.py +++ /dev/null @@ -1,63 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Openstack Monitoring script for Sensu / Nagios -# -# Copyright © 2013-2014 eNovance -# -# Author: Mehdi Abaakouk -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import json -import re - -from oschecks import utils -from ceilometerclient import exc - - -def _check_ceilometer_api(): - ceilometer = utils.Ceilometer() - ceilometer.add_argument('-w', dest='warning', type=int, default=5, - help='Warning timeout for Ceilometer APIs calls') - ceilometer.add_argument('-c', dest='critical', type=int, default=10, - help='Critical timeout for Ceilometer APIs calls') - options, client = ceilometer.setup() - - def meters_list(): - try: - return client.meters.list() - except exc.HTTPNotFound as ex: - utils.warning('Did not find Ceilometer API running ' - 'on given endpoint') - except Exception as ex: - utils.critical(str(ex)) - - - elapsed, meters = utils.timeit(meters_list) - if elapsed > options.critical: - utils.critical("Get meters took more than %d seconds, " - "it's too long.|response_time=%d" % - (options.critical, elapsed)) - elif elapsed > options.warning: - utils.warning("Get meters took more than %d seconds, " - "it's too long.|response_time=%d" % - (options.warning, elapsed)) - else: - utils.ok("Get meters, Ceilometer API is working: " - "list %d meters in %d seconds.|response_time=%d" % - (len(meters), elapsed, elapsed)) - - -def check_ceilometer_api(): - utils.safe_run(_check_ceilometer_api) diff --git a/monitoring-for-openstack/oschecks/ceph.py b/monitoring-for-openstack/oschecks/ceph.py deleted file mode 100644 index 5d5bda7..0000000 --- a/monitoring-for-openstack/oschecks/ceph.py +++ /dev/null @@ -1,143 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -# -# Copyright (C) 2014 eNovance SAS -# -# Author: Frederic Lepied -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -''' Nagios check using ceph health. -''' - -import json -import subprocess -import sys -import traceback - - -def per(percent, value): - return percent / 100 * value - - -def remaining(avail, total): - return "(%dMB/%dMB)" % (avail / 1024, total / 1024) - - -def interpret_output_df(output): - '''Parse the output of ceph health. - - Return an exit code and message compatible with nagios. - - ''' - - try: - data = json.loads(output) - except Exception: - return (1, 'CEPH WARNING: unable to parse ceph df %s' % - traceback.format_exc()) - - warn_percent = int(sys.argv[1]) if len(sys.argv) >= 2 else 85 - crit_percent = int(sys.argv[2]) if len(sys.argv) >= 3 else 98 - - if 'total_bytes' in data['stats']: - total = int(data['stats']['total_bytes']) - else: - total = int(data['stats']['total_space']) - if 'total_used_bytes' in data['stats']: - used = int(data['stats']['total_used_bytes']) - else: - used = int(data['stats']['total_used']) - - if 'total_avail_bytes' in data['stats']: - avail = int(data['stats']['total_avail_bytes']) - else: - avail = int(data['stats']['total_avail']) - - # Test correctness of values - if used + avail != total: - return (1, '[WARN] Used + Avail. != Total space') - elif avail < per(crit_percent, total): - return (2, "[ERR] Ceph df avail. critical %s" % - remaining(avail, total)) - elif avail < per(warn_percent, total): - return (1, "[WARN] Ceph df avail. waring %s" % - remaining(avail, total)) - else: - return (0, "[OK] Ceph df avail. seems good %s" % - remaining(avail, total)) - - -def check_ceph_df(): - 'Program entry point.' - - try: - ceph_args = ["ceph", "df", "--format=json"] - if len(sys.argv) >= 4: - ceph_args.append('-n') - ceph_args.append(sys.argv[3]) - - res = subprocess.check_output(ceph_args, - stderr=subprocess.STDOUT) - exit_code, message = interpret_output_df(res) - sys.stdout.write("%s\n" % message) - sys.exit(exit_code) - except subprocess.CalledProcessError as e: - sys.stdout.write('CEPH UNKNOWN: %s\n' % e.output) - sys.exit(3) - except OSError: - sys.stdout.write('CEPH UNKNOWN: unable to launch ceph health\n') - sys.exit(3) - - -def interpret_output_health(output): - '''Parse the output of ceph health. - - Return an exit code and message compatible with nagios. - - ''' - - tokens = output.split(' ') - if len(tokens) == 1: - tokens[0] = tokens[0].strip() - tokens.append('\n') - if tokens[0] == 'HEALTH_OK': - return (0, 'CEPH OK: ' + ' '.join(tokens[1:])) - elif tokens[0] == 'HEALTH_WARN': - return (1, 'CEPH WARNING: ' + ' '.join(tokens[1:])) - elif tokens[0] == 'HEALTH_ERR': - return (2, 'CEPH CRITICAL: ' + ' '.join(tokens[1:])) - else: - return (3, 'CEPH UNKNOWN: ' + ' '.join(tokens)) - - -def check_ceph_health(): - 'Program entry point.' - - try: - ceph_args = ["ceph", "health"] - if len(sys.argv) >= 2: - ceph_args.append('-n') - ceph_args.append(sys.argv[1]) - - res = subprocess.check_output(ceph_args, - stderr=subprocess.STDOUT) - exit_code, message = interpret_output_health(res) - sys.stdout.write(message) - sys.exit(exit_code) - except subprocess.CalledProcessError as e: - sys.stdout.write('CEPH UNKNOWN: %s\n' % e.output) - sys.exit(3) - except OSError: - sys.stdout.write('CEPH UNKNOWN: unable to launch ceph health\n') - sys.exit(3) diff --git a/monitoring-for-openstack/oschecks/cinder.py b/monitoring-for-openstack/oschecks/cinder.py deleted file mode 100644 index c623d15..0000000 --- a/monitoring-for-openstack/oschecks/cinder.py +++ /dev/null @@ -1,285 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Openstack Monitoring script for Sensu / Nagios -# -# Copyright © 2013-2014 eNovance -# -# Author: Mehdi Abaakouk -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -import argparse -import datetime -import logging -import os -import time -import urlparse - -from cinderclient.client import Client # noqa -from cinderclient import exceptions - -from oschecks import utils - - -def _check_cinder_api(): - cinder = utils.Cinder() - cinder.add_argument('-w', dest='warning', type=int, default=5, - help='Warning timeout for cinder APIs calls') - cinder.add_argument('-c', dest='critical', type=int, default=10, - help='Critical timeout for cinder APIs calls') - options, args, client = cinder.setup() - - def quotas_list(): - try: - return client.quotas.get( - getattr(options, 'os_project_name', - getattr(options, 'os_tenant_name', None) - ) - ) - except Exception as ex: - utils.critical(str(ex)) - - elapsed, quotas = utils.timeit(quotas_list) - if elapsed > options.critical: - utils.critical("Get quotas took more than %d seconds, " - "it's too long.|response_time=%d" % - (options.critical, elapsed)) - elif elapsed > options.warning: - utils.warning("Get quotas took more than %d seconds, " - "it's too long.|response_time=%d" % - (options.warning, elapsed)) - else: - utils.ok("Get quotas, cinder API is working: " - "list quota in %d seconds.|response_time=%d" % - (elapsed, elapsed)) - - -def check_cinder_api(): - utils.safe_run(_check_cinder_api) - - -class CinderUtils(object): - DAEMON_DEFAULT_PORT = 8776 - - def __init__(self, client, project): - self.client = client - self.msgs = [] - self.start = self.totimestamp() - self.notifications = ["volume_creation_time=%s" % self.start] - self.volume = None - self.connection_done = False - self.project = project - - # python has no "toepoch" method: http://bugs.python.org/issue2736 - # now, after checking http://stackoverflow.com/a/16307378, - # and http://stackoverflow.com/a/8778548 made my mind to this approach - @staticmethod - def totimestamp(dt=None, epoch=datetime.datetime(1970, 1, 1)): - if not dt: - dt = datetime.datetime.utcnow() - td = dt - epoch - # return td.total_seconds() - return int((td.microseconds + - (td.seconds + td.days * 24 * 3600) * 10**6) / 1e6) - - def check_connection(self, force=False): - if not self.connection_done or force: - try: - # force a connection to the server - self.connection_done = self.client.limits.get() - except Exception as e: - utils.critical("Cannot connect to cinder: %s" % e) - - def get_duration(self): - return self.totimestamp() - self.start - - def mangle_url(self, url): - # This first connection populate the structure we need inside - # the object. This does not cost anything if a connection has - # already been made. - self.check_connection() - try: - endpoint_url = urlparse.urlparse(url) - except Exception as e: - utils.unknown("you must provide an endpoint_url in the form" - ":/// (%s)" % e) - scheme = endpoint_url.scheme - if scheme is None: - utils.unknown("you must provide an endpoint_url in the form" - ":/// (%s)" % e) - catalog_url = None - try: - catalog_url = urlparse.urlparse( - self.client.client.management_url) - except Exception as e: - utils.unknown("unknown error parsing the catalog url : %s" % e) - - port = endpoint_url.port - if port is None: - if catalog_url.port is None: - port = self.DAEMON_DEFAULT_PORT - else: - port = catalog_url.port - - netloc = "%s:%i" % (endpoint_url.hostname, port) - url = urlparse.urlunparse([scheme, - netloc, - catalog_url.path, - catalog_url.params, - catalog_url.query, - catalog_url.fragment]) - self.client.client.management_url = url - - def check_existing_volume(self, volume_name, delete): - count = 0 - for s in self.client.volumes.list(): - if s.display_name == volume_name: - if delete: - # asynchronous call, we do not check that it worked - s.delete() - count += 1 - if count > 0: - if delete: - self.notifications.append("Found '%s' present %d time(s)" - % (volume_name, count)) - else: - self.msgs.append("Found '%s' present %d time(s). " % - (volume_name, count) + - "Won't create test volume. " - "Please check and delete.") - - def create_volume(self, volume_name, size, availability_zone, volume_type): - if not self.msgs: - try: - conf = {'name': volume_name, 'size': size} - if volume_type: - conf['volume_type'] = volume_type - if availability_zone: - conf['availability_zone'] = availability_zone - self.volume = self.client.volumes.create(**conf) - except Exception as e: - self.msgs.append("Cannot create the volume %s (%s)" - % (volume_name, e)) - - def volume_ready(self, timeout): - if not self.msgs: - timer = 0 - while self.volume.status != "available": - if timer >= timeout: - self.msgs.append("Cannot create the volume.") - break - time.sleep(1) - timer += 1 - try: - self.volume.get() - except Exception as e: - self.msgs.append("Problem getting the status of " - "the volume: %s" % e) - break - - def delete_volume(self): - if not self.msgs or self.volume is not None: - try: - self.volume.delete() - except Exception as e: - self.msgs.append("Problem deleting the volume: %s" % e) - - def volume_deleted(self, timeout): - deleted = False - timer = 0 - while not deleted and not self.msgs: - time.sleep(1) - if timer >= timeout: - self.msgs.append("Could not delete the volume within " - "%d seconds" % timer) - break - timer += 1 - try: - self.volume.get() - except exceptions.NotFound: - deleted = True - except Exception as e: - self.msgs.append("Cannot delete the volume (%s)" % e) - break - - -def _check_cinder_volume(): - cinder = utils.Cinder() - - cinder.add_argument('--endpoint_url', metavar='endpoint_url', type=str, - help='Override the catalog endpoint.') - - cinder.add_argument('--force_delete', action='store_true', - help='If matching volumes are found, delete ' - 'them and add a notification in the ' - 'message instead of getting out in ' - 'critical state.') - - cinder.add_argument('--volume_name', metavar='volume_name', type=str, - default="monitoring_test", - help='Name of the volume to create ' - '(monitoring_test by default)') - - cinder.add_argument('--volume_size', metavar='volume_size', type=int, - default=1, - help='Size of the volume to create (1 GB by default)') - - cinder.add_argument('--volume_type', metavar='volume_type', type=str, - default=None, - help='With multiple backends, choose the volume type.') - - cinder.add_argument('--availability_zone', metavar='availability_zone', - type=str, - default=None, - help='Specify availability zone.') - - options, args, client = cinder.setup() - project = (options.os_project_id if options.os_project_id else - options.os_project_name) - tenant = (options.os_tenant_id if options.os_tenant_id else - options.os_tenant_name) - util = CinderUtils(client, tenant or project) - - # Initiate the first connection and catch error. - util.check_connection() - - if options.endpoint_url: - util.mangle_url(options.endpoint_url) - # after mangling the url, the endpoint has changed. Check that - # it's valid. - util.check_connection(force=True) - - util.check_existing_volume(options.volume_name, options.force_delete) - util.create_volume(options.volume_name, - options.volume_size, - options.availability_zone, - options.volume_type) - util.volume_ready(options.timeout) - util.delete_volume() - util.volume_deleted(options.timeout) - - if util.msgs: - utils.critical(", ".join(util.msgs)) - - duration = util.get_duration() - notification = "" - - if util.notifications: - notification = "(" + ", ".join(util.notifications) + ")" - - utils.ok("Volume spawned and deleted in %d seconds %s| time=%d" - % (duration, notification, duration)) - - -def check_cinder_volume(): - utils.safe_run(_check_cinder_volume) diff --git a/monitoring-for-openstack/oschecks/glance.py b/monitoring-for-openstack/oschecks/glance.py deleted file mode 100644 index c892419..0000000 --- a/monitoring-for-openstack/oschecks/glance.py +++ /dev/null @@ -1,145 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Openstack Monitoring script for Sensu / Nagios -# -# Copyright © 2013-2014 eNovance -# -# Author: Mehdi Abaakouk -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -import StringIO - -from oschecks import utils - - -def _check_glance_api(): - glance = utils.Glance() - glance.add_argument('-w', dest='warning', type=int, default=5, - help='Warning timeout for Glance APIs calls') - glance.add_argument('-c', dest='critical', type=int, default=10, - help='Critical timeout for Glance APIs calls') - options, args, client = glance.setup() - - def images_list(): - try: - return list(client.images.list()) - except Exception as ex: - utils.critical(str(ex)) - - elapsed, images = utils.timeit(images_list) - if images and elapsed > options.critical: - utils.critical("Get images took more than %d seconds, " - "it's too long.|response_time=%d" % - (options.critical, elapsed)) - elif images and elapsed > options.warning: - utils.warning("Get images took more than %d seconds, " - "it's too long.|response_time=%d" % - (options.warning, elapsed)) - else: - utils.ok("Get images, Glance API is working: " - "list %d images in %d seconds.|response_time=%d" % - (len(images), elapsed, elapsed)) - - -def check_glance_api(): - utils.safe_run(_check_glance_api) - - -def _check_glance_image_exists(): - glance = utils.Glance() - glance.add_argument('--req_count', dest='req_count', type=int, - required=False, default=0, - help='minimum number of images in glance') - glance.add_argument('--req_images', metavar='req_images', type=str, - nargs='+', required=False, - help='name of images who must be available') - options, args, client = glance.setup() - - # Flags resultat - valid_image = 0 - count = len(list(client.images.list(**{"limit": options.req_count or 1}))) - - if options.req_images: - required_images = options.req_images - for image in required_images: - try: - if len(list(client.images.list( - **{"filters": {"name": image}}))) == 1: - valid_image = valid_image + 1 - except Exception: - pass - - if options.req_count and count < options.req_count: - utils.critical("Failed - less than %d images found (%d)" % - (options.req_count, count)) - - if options.req_images and valid_image < len(required_images): - utils.critical("Failed - '%s' %d/%d images found " % - (", ".join(required_images), valid_image, - len(required_images))) - - if options.req_images and options.req_count: - utils.ok("image %s found and enough images >=%d" % - (", ".join(required_images), options.req_count)) - elif options.req_images: - utils.ok("image %s found" % (", ".join(required_images))) - elif options.req_count: - utils.ok("more than %d images found" % (count)) - else: - utils.ok("Connection glance established") - - -def check_glance_image_exists(): - utils.safe_run(_check_glance_image_exists) - - -def _upload_image(client, name): - data = StringIO.StringIO("X" * 1024 * 1024) - img = client.images.create(name=name, - disk_format='raw', - container_format='bare') - try: - client.images.upload(img.id, data) - except Exception: - client.images.delete(img.id) - raise - return img.id - -def _check_glance_upload(): - glance = utils.Glance() - glance.add_argument('--monitoring-image', dest='image_name', type=str, - default="openstack-monitoring-test-image", - help='Name of the monitoring image') - options, args, client = glance.setup() - - elapsed, iid = utils.timeit(_upload_image, - client=client, - name=options.image_name) - try: - res = client.images.get(iid) - if res.status != 'active': - utils.critical("Unable to upload image in Glance") - finally: - client.images.delete(res.id) - - if elapsed > 20: - utils.warning("Upload image in 20 seconds, it's too long") - else: - utils.ok("Glance image uploaded in %s seconds" % elapsed) - - -def check_glance_upload(): - utils.safe_run(_check_glance_upload) diff --git a/monitoring-for-openstack/oschecks/keystone.py b/monitoring-for-openstack/oschecks/keystone.py deleted file mode 100644 index 1da4d52..0000000 --- a/monitoring-for-openstack/oschecks/keystone.py +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Openstack Monitoring script for Sensu / Nagios -# -# Copyright © 2013-2014 eNovance -# -# Author: Mehdi Abaakouk -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from oschecks import utils - - -def _check_keystone_api(): - keystone = utils.Keystone() - - def check_token(): - try: - return keystone.run() - except Exception as ex: - utils.critical(str(ex)) - - elapsed, result = utils.timeit(check_token) - rc, out = result - if rc: - utils.critical("Unable to get a token:\n{0}".format(out)) - - if elapsed > 10: - utils.warning("Got a token after 10 seconds, it's too long." - "|response_time=%s" % elapsed) - else: - utils.ok("Got a token, Keystone API is working." - "|response_time=%s" % elapsed) - - -def check_keystone_api(): - utils.safe_run(_check_keystone_api) diff --git a/monitoring-for-openstack/oschecks/neutron.py b/monitoring-for-openstack/oschecks/neutron.py deleted file mode 100644 index 20b2df0..0000000 --- a/monitoring-for-openstack/oschecks/neutron.py +++ /dev/null @@ -1,270 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Openstack Monitoring script for Sensu / Nagios -# -# Copyright © 2013-2014 eNovance -# -# Authors: Mehdi Abaakouk -# Sofer Athlan-Guyot -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -import argparse -import datetime -import logging -import os -import re -import urlparse - -from keystoneclient.v2_0 import client -from neutronclient.neutron import client as neutron - -from oschecks import utils - - -def _check_neutron_api(): - neutron = utils.Neutron() - neutron.add_argument('-w', dest='warning', type=int, default=5, - help='Warning timeout for neutron APIs calls') - neutron.add_argument('-c', dest='critical', type=int, default=10, - help='Critical timeout for neutron APIs calls') - options, args, client = neutron.setup() - - def network_list(): - try: - return client.list_networks() - except Exception as ex: - utils.critical(str(ex)) - - elapsed, networks = utils.timeit(network_list) - if not networks or len(networks.get('networks', [])) <= 0: - utils.critical("Unable to contact neutron API.") - - if elapsed > options.critical: - utils.critical("Get networks took more than %d seconds, " - "it's too long.|response_time=%d" % - (options.critical, elapsed)) - elif elapsed > options.warning: - utils.warning("Get networks took more than %d seconds, " - "it's too long.|response_time=%d" % - (options.warning, elapsed)) - else: - utils.ok("Get networks, neutron API is working: " - "list %d networks in %d seconds.|response_time=%d" % - (len(networks['networks']), elapsed, elapsed)) - - -def check_neutron_api(): - utils.safe_run(_check_neutron_api) - - -class NeutronUtils(object): - DAEMON_DEFAULT_PORT = 9696 - - def __init__(self, client, tenant_id): - self.client = client - self.msgs = [] - self.start = self.totimestamp() - self.notifications = ["floatingip_creation_time=%s" % self.start] - self.connection_done = False - self.all_floating_ips = [] - self.fip = None - self.network_id = None - self.tenant_id = tenant_id - - # python has no "toepoch" method: http://bugs.python.org/issue2736 - # now, after checking http://stackoverflow.com/a/16307378, - # and http://stackoverflow.com/a/8778548 made my mind to this approach - @staticmethod - def totimestamp(dt=None, epoch=datetime.datetime(1970, 1, 1)): - if not dt: - dt = datetime.datetime.utcnow() - td = dt - epoch - # return td.total_seconds() - return int((td.microseconds + - (td.seconds + td.days * 24 * 3600) * 10**6) / 1e6) - - def check_connection(self, force=False): - if not self.connection_done or force: - try: - # force a connection to the server - self.connection_done = self.client.list_ports() - except Exception as e: - utils.critical("Cannot connect to neutron: %s\n" % e) - - def mangle_url(self, url): - # This first connection populate the structure we need inside - # the object. This does not cost anything if a connection has - # already been made. - self.check_connection() - try: - endpoint_url = urlparse.urlparse(url) - except Exception as e: - utils.unknown("you must provide an endpoint_url in the form" - ":/// (%s)" % e) - scheme = endpoint_url.scheme - if scheme is None: - utils.unknown("you must provide an endpoint_url in the form" - ":/// (%s)" % e) - catalog_url = None - try: - catalog_url = urlparse.urlparse( - self.client.httpclient.endpoint_url) - except Exception as e: - utils.unknown("unknown error parsing the catalog url : %s" % e) - - port = endpoint_url.port - if port is None: - if catalog_url.port is None: - port = self.DAEMON_DEFAULT_PORT - else: - port = catalog_url.port - - netloc = "%s:%i" % (endpoint_url.hostname, port) - url = urlparse.urlunparse([scheme, - netloc, - catalog_url.path, - catalog_url.params, - catalog_url.query, - catalog_url.fragment]) - self.client.httpclient.endpoint_override = url - - def get_duration(self): - return self.totimestamp() - self.start - - def list_floating_ips(self): - if not self.all_floating_ips: - for floating_ip in self.client.list_floatingips( - fields=['floating_ip_address', 'id'], - tenant_id=self.tenant_id)['floatingips']: - self.all_floating_ips.append(floating_ip) - return self.all_floating_ips - - def check_existing_floatingip(self, floating_ip=None, delete=False): - count = 0 - found_ips = [] - for ip in self.list_floating_ips(): - if floating_ip == 'all' or floating_ip.match( - ip['floating_ip_address']): - if delete: - # asynchronous call, we do not check that it worked - self.client.delete_floatingip(ip['id']) - found_ips.append(ip['floating_ip_address']) - count += 1 - if count > 0: - if delete: - self.notifications.append("Found %d ip(s): %s" % - (count, '{' + ', '.join( - found_ips) + '}')) - else: - self.msgs.append("Found %d ip(s): %s. " % - (count, ', '.join(found_ips)) + - "Won't create test floating ip. " - "Please check and delete.") - - def get_network_id(self, ext_network_name): - if not self.msgs: - if not self.network_id: - try: - self.network_id = self.client.list_networks( - name=ext_network_name, fields='id')['networks'][0]['id'] - except Exception: - self.msgs.append("Cannot find ext network named '%s'." - % ext_network_name) - - def create_floating_ip(self): - if not self.msgs: - try: - body = {'floatingip': {'floating_network_id': self.network_id}} - self.fip = self.client.create_floatingip(body=body) - self.notifications.append( - "fip=%s" % self.fip['floatingip']['floating_ip_address']) - except Exception as e: - self.msgs.append("Cannot create a floating ip: %s" % e) - - def delete_floating_ip(self): - if not self.msgs: - try: - self.client.delete_floatingip( - self.fip['floatingip']['id']) - except Exception: - self.msgs.append("Cannot remove floating ip %s" - % self.fip['floatingip']['id']) - - -def fip_type(string): - if string == 'all': - return 'all' - else: - return re.compile(string) - - -def _check_neutron_floating_ip(): - neutron = utils.Neutron() - neutron.add_argument('--endpoint_url', metavar='endpoint_url', type=str, - help='Override the catalog endpoint.') - neutron.add_argument('--force_delete', action='store_true', - help=('If matching floating ip are found, delete ' - 'them and add a notification in the message ' - 'instead of getting out in critical state.')) - neutron.add_argument('--floating_ip', metavar='floating_ip', type=fip_type, - default=None, - help=('Regex of IP(s) to check for existance. ' - 'This value can be "all" for conveniance ' - '(match all ip). This permit to avoid certain ' - 'floating ip to be kept. Its default value ' - 'prevents the removal of any existing ' - 'floating ip')) - neutron.add_argument('--ext_network_name', metavar='ext_network_name', - type=str, default='public', - help=('Name of the "public" external network ' - '(public by default)')) - options, args, client = neutron.setup() - - project = (options.os_project_id if options.os_project_id else - options.os_project_name) - tenant = (options.os_tenant_id if options.os_tenant_id else - options.os_tenant_name) - util = NeutronUtils(client, tenant or project) - - # Initiate the first connection and catch error. - util.check_connection() - - if options.endpoint_url: - util.mangle_url(options.endpoint_url) - # after mangling the url, the endpoint has changed. Check that - # it's valid. - util.check_connection(force=True) - - if options.floating_ip: - util.check_existing_floatingip(options.floating_ip, - options.force_delete) - util.get_network_id(options.ext_network_name) - util.create_floating_ip() - util.delete_floating_ip() - - if util.msgs: - utils.critical(", ".join(util.msgs)) - - duration = util.get_duration() - notification = "" - - if util.notifications: - notification = "(" + ", ".join(util.notifications) + ")" - - utils.ok("Floating ip created and deleted %s| time=%d" - % (notification, duration)) - - -def check_neutron_floating_ip(): - utils.safe_run(_check_neutron_floating_ip) diff --git a/monitoring-for-openstack/oschecks/nova.py b/monitoring-for-openstack/oschecks/nova.py deleted file mode 100644 index 5c84f02..0000000 --- a/monitoring-for-openstack/oschecks/nova.py +++ /dev/null @@ -1,362 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Openstack Monitoring script for Sensu / Nagios -# -# Copyright © 2012-2014 eNovance -# -# Authors: Mehdi Abaakouk -# Sofer Athlan-Guyot -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -import argparse -import datetime -import logging -import os -import time - -from novaclient.client import Client # noqa -from novaclient import exceptions -from six.moves import urllib - -from oschecks import utils - - -def _check_nova_api(): - nova = utils.Nova() - nova.add_argument('-w', dest='warning', type=int, default=5, - help='Warning timeout for nova APIs calls') - nova.add_argument('-c', dest='critical', type=int, default=10, - help='Critical timeout for nova APIs calls') - options, args, client = nova.setup() - - def flavors_list(): - try: - return list(client.flavors.list()) - except Exception as ex: - utils.critical(str(ex)) - - elapsed, flavors = utils.timeit(flavors_list) - if elapsed > options.critical: - utils.critical("Get flavors took more than %d seconds, " - "it's too long.|response_time=%d" % - (options.critical, elapsed)) - elif elapsed > options.warning: - utils.warning("Get flavors took more than %d seconds, " - "it's too long.|response_time=%d" % - (options.warning, elapsed)) - else: - utils.ok("Get flavors, nova API is working: " - "list %d flavors in %d seconds.|response_time=%d" % - (len(flavors), elapsed, elapsed)) - - -def check_nova_api(): - utils.safe_run(_check_nova_api) - - -default_image_name = 'cirros' -default_flavor_name = 'm1.tiny' -default_instance_name = 'monitoring_test' - - -class Novautils(object): - def __init__(self, nova_client): - self.nova_client = nova_client - self.msgs = [] - self.start = self.totimestamp() - self.notifications = ["instance_creation_time=%s" % self.start] - self.performances = [] - self.instance = None - self.connection_done = False - - # python has no "toepoch" method: http://bugs.python.org/issue2736 - # now, after checking http://stackoverflow.com/a/16307378, - # and http://stackoverflow.com/a/8778548 made my mind to this approach - @staticmethod - def totimestamp(dt=None, epoch=datetime.datetime(1970, 1, 1)): - if not dt: - dt = datetime.datetime.utcnow() - td = dt - epoch - # return td.total_seconds() - return int((td.microseconds + - (td.seconds + td.days * 24 * 3600) * 10**6) / 1e6) - - def check_connection(self, force=False): - if not self.connection_done or force: - try: - # force a connection to the server - self.connection_done = self.nova_client.limits.get() - except Exception as e: - utils.critical("Cannot connect to nova: %s\n" % e) - - def get_duration(self): - return self.totimestamp() - self.start - - def mangle_url(self, url): - self.check_connection() - - try: - endpoint_url = urllib.parse.urlparse(url) - except Exception as e: - utils.unknown("you must provide an endpoint_url in the form" - ":/// (%s)\n" % e) - scheme = endpoint_url.scheme - if scheme is None: - utils.unknown("you must provide an endpoint_url in the form" - ":/// (%s)\n" % e) - catalog_url = None - try: - catalog_url = urllib.parse.urlparse( - self.nova_client.client.management_url) - except Exception as e: - utils.unknown("unknown error parsing the catalog url : %s\n" % e) - - port = endpoint_url.port - if port is None: - if catalog_url.port is None: - port = 8774 - else: - port = catalog_url.port - - netloc = "%s:%i" % (endpoint_url.hostname, port) - url = urllib.parse.urlunparse([scheme, - netloc, - catalog_url.path, - catalog_url.params, - catalog_url.query, - catalog_url.fragment]) - self.nova_client.client.set_management_url(url) - - def check_existing_instance(self, instance_name, delete, timeout=45): - count = 0 - for s in self.nova_client.servers.list(): - if s.name == instance_name: - if delete: - s.delete() - self._instance_status(s, timeout, count) - self.performances.append("undeleted_server_%s_%d=%s" - % (s.name, count, s.created)) - count += 1 - if count > 0: - if delete: - self.notifications.append("Found '%s' present %d time(s)" - % (instance_name, count)) - else: - self.msgs.append( - "Found '%s' present %d time(s). " % - (instance_name, count) + - "Won't create test instance. " - "Please check and delete.") - - def get_image(self, image_name): - if not self.msgs: - try: - if hasattr(self.nova_client, 'images'): - self.image = self.nova_client.images.find(name=image_name) - else: - self.image = self.nova_client.glance.find_image(image_name) - except Exception as e: - self.msgs.append("Cannot find the image %s (%s)" - % (image_name, e)) - - def get_flavor(self, flavor_name): - if not self.msgs: - try: - self.flavor = self.nova_client.flavors.find(name=flavor_name) - except Exception as e: - self.msgs.append("Cannot find the flavor %s (%s)" - % (flavor_name, e)) - - def get_network(self, network_name): - if self.msgs or not network_name: - self.network = None - elif hasattr(self.nova_client, 'networks'): - self.network = self.nova_client.networks.find(name=image_name) - else: - self.network = self.nova_client.neutron.find_network(image_name) - - def create_instance(self, instance_name): - if not self.msgs: - kwargs = {} - - try: - if self.network: - try: - network = self.nova_client.networks.find( - label=network).id - except exceptions.NotFound: - try: - network = self.nova_client.networks.find( - id=network).id - except exceptions.NotFound: - self.msgs.append("Cannot find network %s" % - network) - return - kwargs['nics'] = [{'net-id': self.network}] - self.instance = self.nova_client.servers.create( - name=instance_name, - image=self.image, - flavor=self.flavor, **kwargs) - except Exception as e: - self.msgs.append("Cannot create the vm %s (%s)" - % (instance_name, e)) - - def instance_ready(self, timeout): - if not self.msgs: - timer = 0 - while self.instance.status != "ACTIVE": - if timer >= timeout: - self.msgs.append("Cannot create the vm") - break - time.sleep(1) - timer += 1 - try: - self.instance.get() - except Exception as e: - self.msgs.append("Problem getting the status of the vm: %s" - % e) - break - - def delete_instance(self): - if not self.msgs or self.instance is not None: - try: - self.instance.delete() - except Exception as e: - self.msgs.append("Problem deleting the vm: %s" % e) - - def instance_deleted(self, timeout): - deleted = False - timer = 0 - while not deleted and not self.msgs: - time.sleep(1) - if timer >= timeout: - self.msgs.append("Could not delete the vm within %d seconds" - % timer) - break - timer += 1 - try: - self.instance.get() - except exceptions.NotFound: - deleted = True - except Exception as e: - self.msgs.append("Cannot delete the vm (%s)" % e) - break - - def _instance_status(self, instance, timeout, count): - deleted = False - timer = 0 - while not deleted: - time.sleep(1) - if timer >= timeout: - self.msgs.append( - "Could not delete the vm %s within %d seconds " % - (instance.name, timer) + "(created at %s)" % - instance.created) - break - timer += 1 - try: - instance.get() - except exceptions.NotFound: - deleted = True - except Exception as e: - self.msgs.append("Cannot delete the vm %s (%s)" - % (instance.name, e)) - self.performances.append("undeleted_server_%s_%d=%s" - % (instance.name, - count, - instance.created)) - break - - -def _check_nova_instance(): - nova = utils.Nova() - nova.add_argument('--endpoint_url', metavar='endpoint_url', type=str, - help='Override the catalog endpoint.') - - nova.add_argument('--image_name', metavar='image_name', type=str, - default=default_image_name, - help="Image name to use (%s by default)" - % default_image_name) - - nova.add_argument('--flavor_name', metavar='flavor_name', type=str, - default=default_flavor_name, - help="Flavor name to use (%s by default)" - % default_flavor_name) - - nova.add_argument('--instance_name', metavar='instance_name', type=str, - default=default_instance_name, - help="Instance name to use (%s by default)" - % default_instance_name) - - nova.add_argument('--force_delete', action='store_true', - help='If matching instances are found delete ' - 'them and add a notification in the message' - ' instead of getting out in critical state.') - - nova.add_argument('--timeout_delete', metavar='timeout_delete', - type=int, default=45, - help='Max number of second to delete an existing ' - 'instance (45 by default).') - - nova.add_argument('--network', metavar='network', type=str, default=None, - help="Override the network name to use") - - nova.add_argument('--verbose', action='count', - help='Print requests on stderr.') - - options, args, nova_client = nova.setup() - - util = Novautils(nova_client) - - if options.verbose: - ch = logging.StreamHandler() - nova_client.client._logger.setLevel(logging.DEBUG) - nova_client.client._logger.addHandler(ch) - - # Initiate the first connection and catch error. - util.check_connection() - - if options.endpoint_url: - util.mangle_url(options.endpoint_url) - # after mangling the url, the endpoint has changed. Check that - # it's valid. - util.check_connection(force=True) - - util.check_existing_instance(options.instance_name, - options.force_delete, - options.timeout_delete) - util.get_image(options.image_name) - util.get_flavor(options.flavor_name) - util.get_network(options.network) - util.create_instance(options.instance_name) - util.instance_ready(options.timeout) - util.delete_instance() - util.instance_deleted(options.timeout) - - if util.msgs: - utils.critical(", ".join(util.msgs)) - - duration = util.get_duration() - notification = "" - if util.notifications: - notification = "(" + ", ".join(util.notifications) + ")" - performance = "" - if util.performances: - performance = " ".join(util.performances) - utils.ok("Nova instance spawned and deleted in %d seconds %s| time=%d %s" - % (duration, notification, duration, performance)) - - -def check_nova_instance(): - utils.safe_run(_check_nova_instance) diff --git a/monitoring-for-openstack/oschecks/pacemaker_host_check.py b/monitoring-for-openstack/oschecks/pacemaker_host_check.py deleted file mode 100644 index 144daa5..0000000 --- a/monitoring-for-openstack/oschecks/pacemaker_host_check.py +++ /dev/null @@ -1,161 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Openstack Monitoring script for Sensu / Nagios -# -# Copyright © 2013-2014 eNovance -# -# Author:Mehdi Abaakouk -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import argparse -import os -import shlex -import subprocess -import re - -try: - import utils -except ImportError: - from oschecks import utils - -def _ok_run_script(options): - '''If there is a script to run it is executed otherwise a default message. - - Argument: - options (Object) -- main program arguments - ''' - if options.script: - script = shlex.split(options.script) - os.execvp(script[0], script) - else: - utils.ok("pacemaker resource %s is running" - % options.pacemaker_resource) - -def _check_resource_in_host(remaining, match_word, options, local_hostname): - '''Searches for resource and a local_hostname on the rest of the line - - It checks if the resource is the second or third word on the line and - search for the host on the running nodes - - Arguments: - :param remaining: (str)-- the rest of the line - :param match_word: (str)-- 'Started:'-->Clone or 'Master'-->Master/Slave - :param options: (object)-- main program arguments - :param local_hostname: -- localhost - ''' - engine = re.compile('Set: ('+options.pacemaker_resource+' \[.*\]|.* \[' - +options.pacemaker_resource+'\]) '+match_word+' (\[.*?\])') - patterns = re.search(engine, remaining) - if patterns is not None: - host_list = patterns.group(2).split()[1:-1] - for host in host_list: - if host == local_hostname: - _ok_run_script(options) - utils.ok( - "pacemaker resource %s doesn't run on this node " - "(but on %s)" % (options.pacemaker_resource, patterns.group(2)) - ) - -def _check_resource_in_docker_host(remaining, options, local_hostname): - '''Searches for Docker container set resources in an active state and - matches the local_hostname on the rest of the line - - Arguments: - :param remaining: (str)-- the rest of the line - :param options: (object)-- main program arguments - :param local_hostname: -- localhost - ''' - engine = re.compile('(container set: '+options.pacemaker_resource+'' - ' \[.*\].*)') - engine2 = re.compile('(?: Master | Slave | Started )(\S*)') - pattern = re.search(engine, remaining) - if pattern is not None: - sremaining = pattern.group(1).split('):') - for line in sremaining: - host = re.search(engine2, line) - if host is not None: - if host.group(1) == local_hostname: - _ok_run_script(options) - -def _pacemaker_host_check(): - parser = argparse.ArgumentParser( - description='Check amqp connection of an OpenStack service.') - parser.add_argument('-r', dest='pacemaker_resource', - help='pacemaker resource', required=True) - parser.add_argument('-s', dest='script', required=False, - help='Script') - parser.add_argument('--crm', dest='crm', required=False, - help='Use "crm_mon -1" instead of "pcs status"', - action='store_true', default=False) - options = parser.parse_args() - - if options.script and (not os.path.isfile(options.script) - or not os.access(options.script, os.X_OK)): - utils.critical('the script %s could not be read' % options.script) - - local_hostname = subprocess.check_output(['hostname', '-s']).strip() - try: - if options.crm : - p = subprocess.Popen(['crm_mon', '-1'], stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - output, error = p.communicate() - else: - p = subprocess.Popen(['pcs', 'status'], stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - output, error = p.communicate() - if p.returncode !=0: - if options.crm: - utils.critical('pcs status with status {}: {}' - .format(p.returncode, output.strip())) - else: - utils.critical('pcs status with status {}: {}' - .format(p.returncode, error.strip())) - except OSError: - utils.critical('pcs not found') - - for line in re.sub("\n +", " ", output).splitlines(): - line = " ".join(line.strip().split()) # Sanitize separator - if not line: - continue - resource, remaining = line.split(None, 1) - if resource == options.pacemaker_resource: - agent, __, remaining = remaining.partition(' ') - if ' ' in remaining: - status, __, current_hostname = remaining.partition(' ') - else: - status, current_hostname = remaining, '' - if status != "Started": - utils.critical("pacemaker resource %s is not started (%s)" % - (resource, status)) - if current_hostname != local_hostname: - utils.ok("pacemaker resource %s doesn't run on this node " - "(but on %s)" % (resource, current_hostname)) - _ok_run_script(options) - elif resource == 'Clone' : - _check_resource_in_host(remaining, 'Started:', options, - local_hostname) - elif resource == 'Docker': - _check_resource_in_docker_host(remaining, options, - local_hostname) - elif resource == 'Master/Slave': - _check_resource_in_host(remaining, 'Masters:', options, - local_hostname) - - else: - utils.critical('pacemaker resource %s not found' % - options.pacemaker_resource) - -def pacemaker_host_check(): - utils.safe_run(_pacemaker_host_check) diff --git a/monitoring-for-openstack/oschecks/process.py b/monitoring-for-openstack/oschecks/process.py deleted file mode 100644 index 6cf7465..0000000 --- a/monitoring-for-openstack/oschecks/process.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Openstack Monitoring script for Sensu / Nagios -# -# Copyright © 2013-2014 eNovance -# -# Author: Emilien Macchi -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import argparse - -from oschecks import utils - - -def check_process(): - parser = argparse.ArgumentParser( - description='Check process existence of an OpenStack service.') - parser.add_argument(dest='process_name', - help='Process name') - options = parser.parse_args() - utils.check_process_exists(options.process_name) - - -def main(): - utils.safe_run(check_process) diff --git a/monitoring-for-openstack/oschecks/tests/__init__.py b/monitoring-for-openstack/oschecks/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/monitoring-for-openstack/oschecks/tests/test_ceph.py b/monitoring-for-openstack/oschecks/tests/test_ceph.py deleted file mode 100644 index cac4326..0000000 --- a/monitoring-for-openstack/oschecks/tests/test_ceph.py +++ /dev/null @@ -1,45 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2014 eNovance SAS -# -# Author: Frederic Lepied -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import unittest - -from oschecks import ceph - - -class TestCephHealth(unittest.TestCase): - - def test_interpret_output_ok(self): - exit_code, message = ceph.interpret_output_health('HEALTH_OK message') - self.assertEqual(exit_code, 0) - self.assertEqual(message, 'CEPH OK: message') - - def test_interpret_output_warn(self): - exit_code, message = ceph.interpret_output_health('HEALTH_WARN ' - 'message') - self.assertEqual(exit_code, 1) - self.assertEqual(message, 'CEPH WARNING: message') - - def test_interpret_output_critical(self): - exit_code, message = ceph.interpret_output_health('HEALTH_ERR message') - self.assertEqual(exit_code, 2) - self.assertEqual(message, 'CEPH CRITICAL: message') - - def test_interpret_output_unknown(self): - exit_code, message = ceph.interpret_output_health('strange message') - self.assertEqual(exit_code, 3) - self.assertEqual(message, 'CEPH UNKNOWN: strange message') diff --git a/monitoring-for-openstack/oschecks/tests/test_script.py b/monitoring-for-openstack/oschecks/tests/test_script.py deleted file mode 100644 index 51b2a9a..0000000 --- a/monitoring-for-openstack/oschecks/tests/test_script.py +++ /dev/null @@ -1,46 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2014 eNovance SAS -# -# Author: Julien Danjou -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -import subprocess -import unittest - - -class TestScripts(unittest.TestCase): - SCRIPTS = [ - 'amqp', - 'ceilometer_api', - 'ceph_df', - 'ceph_health', - 'cinder_api', - 'cinder_volume', - 'glance_api', - 'glance_image_exists', - 'glance_upload', - 'keystone_api', - 'neutron_api', - 'neutron_floating_ip', - 'nova_api', - 'nova_instance', - ] - - -for script in TestScripts.SCRIPTS: - def test_check_script(self): - proc = subprocess.Popen("oschecks-check_" + script) - proc.wait() - self.assertEqual(2, proc.returncode) - setattr(TestScripts, "test_script_check_" + script, test_check_script) diff --git a/monitoring-for-openstack/oschecks/utils.py b/monitoring-for-openstack/oschecks/utils.py deleted file mode 100644 index 5167332..0000000 --- a/monitoring-for-openstack/oschecks/utils.py +++ /dev/null @@ -1,306 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Openstack Monitoring script for Sensu / Nagios -# -# Copyright © 2013-2014 eNovance -# -# Author: Mehdi Abaakouk -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - - -import copy -import itertools -import os -import sys -import time -import traceback - -import psutil - -AMQP_PORT = 5672 - - -def unknown(msg): - print("UNKNOWN: %s" % msg) - sys.exit(3) - - -def critical(msg): - print("CRITICAL: %s" % msg) - sys.exit(2) - - -def warning(msg): - print("WARNING: %s" % msg) - sys.exit(1) - - -def ok(msg): - print("OK: %s" % msg) - sys.exit(0) - - -def check_process_name(name, p): - try: - len(p.cmdline) - except TypeError: - pname = p.name() - pcmdline = p.cmdline() - else: - pname = p.name - pcmdline = p.cmdline - - if pname == name: - return True - # name can be truncated and a script so check also if it can be an - # argument to an interpreter - if len(pcmdline) > 0 and os.path.basename(pcmdline[0]) == name: - return True - if len(pcmdline) > 1 and os.path.basename(pcmdline[1]) == name: - return True - return False - - -def check_process_exists_and_amqp_connected(name): - processes = filter(lambda p: check_process_name(name, p), - psutil.process_iter()) - if not processes: - critical("%s is not running" % name) - for p in processes: - try: - conn_func = getattr(p, 'get_connections', p.connections) - connections = conn_func(kind='inet') - except psutil.NoSuchProcess: - continue - found_amqp = ( - len(list(itertools.takewhile(lambda c: - len(getattr(c, 'remote_address', c.raddr)) <= 1 or - getattr(c, 'remote_address', c.raddr)[1] != AMQP_PORT, - connections))) != len(connections)) - if found_amqp: - ok("%s is working." % name) - critical("%s is not connected to AMQP" % name) - - -def check_process_exists(name): - processes = filter(lambda p: check_process_name(name, p), - psutil.process_iter()) - if not processes: - critical("%s is not running" % name) - ok("%s is working." % name) - - -def timeit_wrapper(func): - def wrapper(*arg, **kw): - t1 = time.time() - res = func(*arg, **kw) - t2 = time.time() - return (t2 - t1), res - return wrapper - - -@timeit_wrapper -def timeit(func, *args, **kwargs): - return func(*args, **kwargs) - - -def safe_run(method): - try: - method() - except Exception: - critical(traceback.format_exc()) - - -class Nova(object): - def __init__(self): - from novaclient import shell - self.nova = shell.OpenStackComputeShell() - self.base_argv = copy.deepcopy(sys.argv[1:]) - self.nova.parser = self.nova.get_base_parser(self.base_argv) - self.add_argument = self.nova.parser.add_argument - - def setup(self, api_version='2.1'): - from novaclient.client import Client - (options, args) = self.nova.parser.parse_known_args(self.base_argv) - if options.help: - options.command = None - self.nova.do_help(options) - sys.exit(2) - auth_token = getattr(args, 'os_token', None) - api_version = ( - getattr(options, 'os_compute_api_version', api_version) or - api_version - ) - try: - nova_client = Client( - api_version, - username=options.os_username, - password=options.os_password, - project_name=getattr( - options, 'os_project_name', getattr( - options, 'os_tenant_name', None - ) - ), - project_id=getattr( - options, 'os_project_id', getattr( - options, 'os_tenant_id', None - ) - ), - auth_token=auth_token, - auth_url=options.os_auth_url, - region_name=options.os_region_name, - cacert=options.os_cacert, - insecure=options.insecure, - timeout=options.timeout) - except Exception as ex: - critical(ex) - return options, args, nova_client - - -class Glance(object): - def __init__(self): - from glanceclient import shell - self.glance = shell.OpenStackImagesShell() - self.base_argv = copy.deepcopy(sys.argv[1:]) - self.glance.parser = self.glance.get_base_parser(sys.argv) - self.add_argument = self.glance.parser.add_argument - - def setup(self, api_version=2): - (options, args) = self.glance.parser.parse_known_args(self.base_argv) - if options.help: - options.command = None - self.glance.do_help(options, self.glance.parser) - sys.exit(2) - api_version = ( - getattr(options, 'os_image_api_version', api_version) or - api_version - ) - try: - client = self.glance._get_versioned_client(api_version, options) - except Exception as ex: - critical(ex) - return options, args, client - - -class Ceilometer(object): - def __init__(self): - from ceilometerclient import shell - self.ceilometer = shell.CeilometerShell() - self.base_argv = copy.deepcopy(sys.argv[1:]) - self.ceilometer.parser = self.ceilometer.get_base_parser() - self.add_argument = self.ceilometer.parser.add_argument - - def setup(self, api_version=2): - from ceilometerclient import client - (options, args) = self.ceilometer.parser.parse_known_args( - self.base_argv) - if options.help: - options.command = None - self.ceilometer.do_help(options) - sys.exit(2) - client_kwargs = vars(options) - try: - return options, client.get_client(api_version, **client_kwargs) - except Exception as ex: - critical(ex) - - -class Cinder(object): - def __init__(self): - from cinderclient import shell - self.cinder = shell.OpenStackCinderShell() - self.base_argv = copy.deepcopy(sys.argv[1:]) - self.cinder.parser = self.cinder.get_base_parser() - self.add_argument = self.cinder.parser.add_argument - - def setup(self, api_version='1'): - from cinderclient import client - (options, args) = self.cinder.parser.parse_known_args(self.base_argv) - if options.help: - options.command = None - self.cinder.do_help(options) - sys.exit(2) - if options.os_volume_api_version: - api_version = options.os_volume_api_version - try: - client = client.get_client_class(api_version)( - options.os_username, - options.os_password, - project_id=getattr( - options, 'os_project_name', getattr( - options, 'os_tenant_name', None - ) - ), - auth_url=options.os_auth_url, - region_name=options.os_region_name, - cacert=options.os_cacert, - insecure=options.insecure) - except Exception as ex: - critical(ex) - return options, args, client - - -class Neutron(object): - def __init__(self): - from neutronclient import shell - self.neutron = shell.NeutronShell('2.0') - self.base_argv = copy.deepcopy(sys.argv[1:]) - self.neutron.parser = self.neutron.build_option_parser( - "Neutron client", "2.0") - self.add_argument = self.neutron.parser.add_argument - - def setup(self): - (options, args) = self.neutron.parser.parse_known_args(self.base_argv) - self.neutron.options = options - self.neutron.api_version = {'network': self.neutron.api_version} - try: - self.neutron.authenticate_user() - return options, args, self.neutron.client_manager.neutron - except Exception as ex: - critical(ex) - - -class Keystone(object): - def __init__(self): - if (sys.version_info > (3, 0)): - # Python 3 code in this block - from io import StringIO - else: - # Python 2 code in this block - from StringIO import StringIO - - from openstackclient import shell - self.shell = shell.OpenStackShell() - self.shell.stdout = StringIO() - self.shell.stderr = StringIO() - self.help = False - - def run(self): - command = ['token', 'issue'] - vformat = ['-f', 'value', '-c', 'id'] - if 'help' in sys.argv or '--help' in sys.argv or '-h' in sys.argv: - rc = self.shell.run(command) - else: - cmd_arg = sys.argv[1:] - # removes parameters used in vformat - for opt in ['-f', '-c']: - if opt in cmd_arg: - index = cmd_arg.index(opt) - if len(cmd_arg) > (index + 1): - for i in range(2): - cmd_arg.pop(index) - rc = self.shell.run(command + cmd_arg + vformat) - out = self.shell.stdout.getvalue() - return rc, out diff --git a/monitoring-for-openstack/requirements.txt b/monitoring-for-openstack/requirements.txt deleted file mode 100644 index 3f9c398..0000000 --- a/monitoring-for-openstack/requirements.txt +++ /dev/null @@ -1,9 +0,0 @@ -psutil -python-ceilometerclient -python-cinderclient -python-glanceclient -python-keystoneclient -python-neutronclient -python-novaclient -python-openstackclient -six diff --git a/monitoring-for-openstack/setup.cfg b/monitoring-for-openstack/setup.cfg deleted file mode 100644 index b2d78dc..0000000 --- a/monitoring-for-openstack/setup.cfg +++ /dev/null @@ -1,52 +0,0 @@ -[metadata] -name = monitoring-for-openstack -version = 1.0.1 -summary = OpenStack monitoring tools -description-file = README.rst -author = OpenStack -author-email = openstack-discuss@lists.openstack.org -classifier = - Environment :: OpenStack - Intended Audience :: Information Technology - Intended Audience :: System Administrators - License :: OSI Approved :: Apache Software License - Operating System :: POSIX :: Linux - Programming Language :: Python - Programming Language :: Python :: 2 - Programming Language :: Python :: 2.7 - Programming Language :: Python :: 3.5 - Topic :: System :: Monitoring - -[global] -setup-hooks = - pbr.hooks.setup_hook - -[files] -packages = - oschecks - -[entry_points] -console_scripts = - oschecks-check_amqp = oschecks.amqp:main - oschecks-check_ceilometer_api = oschecks.ceilometer:check_ceilometer_api - oschecks-check_ceph_df = oschecks.ceph:check_ceph_df - oschecks-check_ceph_health = oschecks.ceph:check_ceph_health - oschecks-check_cinder_api = oschecks.cinder:check_cinder_api - oschecks-check_cinder_volume = oschecks.cinder:check_cinder_volume - oschecks-check_glance_api = oschecks.glance:check_glance_api - oschecks-check_glance_image_exists = oschecks.glance:check_glance_image_exists - oschecks-check_glance_upload = oschecks.glance:check_glance_upload - oschecks-check_keystone_api = oschecks.keystone:check_keystone_api - oschecks-check_neutron_api = oschecks.neutron:check_neutron_api - oschecks-check_neutron_floating_ip = oschecks.neutron:check_neutron_floating_ip - oschecks-check_nova_api = oschecks.nova:check_nova_api - oschecks-check_nova_instance = oschecks.nova:check_nova_instance - oschecks-pacemaker_host_check = oschecks.pacemaker_host_check:pacemaker_host_check - -[install] -install-scripts = /usr/libexec/openstack-monitoring/checks/ - -[build_sphinx] -all_files = 1 -build-dir = doc/build -source-dir = doc/source diff --git a/monitoring-for-openstack/setup.py b/monitoring-for-openstack/setup.py deleted file mode 100755 index b96f524..0000000 --- a/monitoring-for-openstack/setup.py +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2014 eNovance -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import setuptools - -setuptools.setup( - setup_requires=['pbr'], - pbr=True) diff --git a/monitoring-for-openstack/test-requirements.txt b/monitoring-for-openstack/test-requirements.txt deleted file mode 100644 index aa6278d..0000000 --- a/monitoring-for-openstack/test-requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -testrepository -python-subunit>=0.0.18 -sphinx diff --git a/monitoring-for-openstack/tox.ini b/monitoring-for-openstack/tox.ini deleted file mode 100644 index df34b39..0000000 --- a/monitoring-for-openstack/tox.ini +++ /dev/null @@ -1,40 +0,0 @@ -[tox] -minversion = 1.6 -skipsdist = True -envlist = py35,py27,pep8 - -[testenv] -usedevelop = True -sitepackages = False -deps = -r{toxinidir}/requirements.txt - -r{toxinidir}/test-requirements.txt -install_command = pip install -U {opts} {packages} -commands = python setup.py testr --slowest --testr-args="{posargs}" - -[testenv:bashate] -basepython = python3 -deps = bashate -whitelist_externals = bash -commands = bash -c "find {toxinidir} \ - -not \( -type d -name .?\* -prune \) \ - -not \( -type d -name contrib -prune \) \ - -type f \ - -not -name \*~ \ - -not -name \*.md \ - -name \*.sh \ - -print0 | xargs -0 bashate -v" - -[testenv:pep8] -basepython = python3 -deps = {[testenv]deps} - hacking>=0.9.2,<0.10 -commands = flake8 - -[testenv:venv] -basepython = python3 -commands = {posargs} - -[flake8] -IGNORE= H105,H405 -exclude = .tox,doc -show-source = true diff --git a/nagios-plugins/check_ceilometer_update.py b/nagios-plugins/check_ceilometer_update.py deleted file mode 100755 index 861659a..0000000 --- a/nagios-plugins/check_ceilometer_update.py +++ /dev/null @@ -1,87 +0,0 @@ -#!/usr/bin/env python -# pylint: disable=import-error,too-few-public-methods -""" -Check ceilometer has recent data -""" - -from ceilometerclient import client -import datetime -import argparse -import sys -import iso8601 -import pytz - -NAGIOS_OK = 0 -NAGIOS_WARNING = 1 -NAGIOS_CRITICAL = 2 -NAGIOS_UNKNOWN = 3 - -class CeilometerConnect(object): - """ - Ceilometer connection class - """ - def __init__(self, args): - version = '2' - self.ceilo_connect = client.get_client(version, - os_username=args.username, - os_password=args.password, - os_tenant_name=args.tenant_name, - os_auth_url=args.auth_url) - - def check_samples(self): - """ - Check meters are incrementing - """ - # Get last sample - sample = self.ceilo_connect.samples.list(meter_name='cpu', limit='1') - if sample: - return sample[0].recorded_at - else: - return False - -def utcnow(): - """ - Return timezone aware UTC date - """ - return datetime.datetime.now(tz=pytz.utc) - -def get_args(): - """ - Parse CLI arguments - """ - parser = argparse.ArgumentParser() - parser.add_argument('-u', '--username', required=True) - parser.add_argument('-p', '--password', required=True) - parser.add_argument('-t', '--tenant_name', required=True) - parser.add_argument('-a', '--auth_url', required=True) - parser.add_argument('-w', '--warn', type=int, required=True) - parser.add_argument('-c', '--crit', type=int, required=True) - args = parser.parse_args() - return args - -def main(): - """ - Main script body - """ - args = get_args() - - ceilo_connect = CeilometerConnect(args) - sample = ceilo_connect.check_samples() - - if sample: - delta = utcnow() - iso8601.parse_date(sample) - if delta >= datetime.timedelta(minutes=args.crit): - print "CRITICAL: Ceilometer data behind by %s" % delta - sys.exit(NAGIOS_CRITICAL) - elif delta >= datetime.timedelta(minutes=args.warn): - print "WARNING: Ceilometer data behind by %s" % delta - sys.exit(NAGIOS_WARNING) - else: - print "OK: Ceilometer data updating - last updated at %s" % sample - sys.exit(NAGIOS_OK) - else: - print "UNKNOWN: Ceilometer data not returning" - sys.exit(NAGIOS_UNKNOWN) - -if __name__ == "__main__": - main() diff --git a/nagios-plugins/check_ip_pool.py b/nagios-plugins/check_ip_pool.py deleted file mode 100755 index 4cf5c44..0000000 --- a/nagios-plugins/check_ip_pool.py +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/env python -""" -Check for remaining IP addresses -""" -# pylint: disable=import-error - -from neutronclient.v2_0 import client -from ipaddress import ip_network -import sys -import argparse - -NAGIOS_OK = 0 -NAGIOS_WARNING = 1 -NAGIOS_CRITICAL = 2 -NAGIOS_UNKNOWN = 3 - -def main(): - """ - Main script body - """ - parser = argparse.ArgumentParser() - parser.add_argument('-u', '--username', required=True) - parser.add_argument('-p', '--password', required=True) - parser.add_argument('-t', '--tenant_name', required=True) - parser.add_argument('-a', '--auth_url', required=True) - parser.add_argument('-w', '--warn', type=int, required=True) - parser.add_argument('-c', '--critical', type=int, required=True) - args = parser.parse_args() - - neutron = client.Client(username=args.username, password=args.password, - tenant_name=args.tenant_name, - auth_url=args.auth_url) - neutron.format = 'json' - - for arg in [args.warn, args.critical]: - if not 0 <= arg <= 100: - print "Alert parameters must be valid percentages" - sys.exit(NAGIOS_UNKNOWN) - - # Get external network - # Assume a single external network for the minute - ext_net = [net for net in neutron.list_networks()['networks'] - if net['router:external']] - - total_addresses = 0 - for subnet in neutron.show_network(ext_net[0]['id'])['network']['subnets']: - total_addresses += ip_network(neutron.show_subnet(subnet) - ['subnet']['cidr']).num_addresses - - floating_ips = len(neutron.list_floatingips()['floatingips']) - router_ips = len([router for router in neutron.list_routers()['routers'] - if router['external_gateway_info']]) - - total_used = floating_ips + router_ips - - percentage_used = 100 * total_used/total_addresses - - if percentage_used >= args.warn: - code = NAGIOS_WARNING - msg = 'WARNING' - elif percentage_used >= args.critical: - code = NAGIOS_CRITICAL - msg = 'CRITICAL' - else: - code = NAGIOS_OK - msg = 'OK' - - print '{0}: {1}% of IP pool used, '\ - '{2} out of {5} addresses in use | '\ - 'total_used={2};{3};{4};;{5} '\ - 'total_available={5} '\ - 'floating_ips_used={6} '\ - 'ext_routers_used={7}'\ - .format(msg, percentage_used, total_used, - (total_addresses * args.warn)/100, - (total_addresses * args.critical)/100, - total_addresses, floating_ips, router_ips) - sys.exit(code) - -if __name__ == "__main__": - main() diff --git a/nagios-plugins/cinder-services.sh b/nagios-plugins/cinder-services.sh deleted file mode 100644 index 4436a81..0000000 --- a/nagios-plugins/cinder-services.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -source ~/openrc - -output=$(cinder service-list | grep down) -if [ $? -eq 0 ]; then - echo -n "CRITICAL - OpenStack Cinder services down: " - echo "${output}" | awk '{print $2,$4}' | while read LINE; do - echo -n "${LINE}; " - done - echo "" - exit 2 -else - echo "OK - All nodes up" - exit 0 -fi diff --git a/nagios-plugins/glance-list.sh b/nagios-plugins/glance-list.sh deleted file mode 100644 index af3440e..0000000 --- a/nagios-plugins/glance-list.sh +++ /dev/null @@ -1,19 +0,0 @@ -#!/bin/bash - -source ~/openrc - -if [ -z "${1}" ]; then - image="CirrOS" -else - image="${1}" -fi - -glance image-list | grep -q "${image}" - -if [ $? == 0 ]; then - echo "OK - Glance is working." - exit 0 -else - echo "CRITICAL - Glance is not working." - exit 2 -fi diff --git a/nagios-plugins/horizon.sh b/nagios-plugins/horizon.sh deleted file mode 100644 index 9e6c4af..0000000 --- a/nagios-plugins/horizon.sh +++ /dev/null @@ -1,28 +0,0 @@ -#!/bin/bash - -source ~/openrc - -# The login URL to access horizon. -# Example: http://example.com/auth/login/ -HORIZON_URL="${1}" - -# If you don't use regions, this will generally be OPENSTACK_KEYSTONE_URL in local_settings.py. -# View the source on the Horizon page for more information and search for "region". -REGION="${2}" - -curl -sL -c /tmp/cookie.txt -b /tmp/cookie.txt $1 -o /dev/null -CSRF_TOKEN=$(grep csrftoken /tmp/cookie.txt | awk '{print $NF}') - -TIMEOUT_CHECK=$(curl -sL -b /tmp/cookie.txt -d "username=${OS_USERNAME}" -d "password=${OS_PASSWORD}" -d "region=${REGION}" -d "csrfmiddlewaretoken=${CSRF_TOKEN}" -m 20 --referer ${HORIZON_URL} ${HORIZON_URL} | tee /tmp/horizon.txt) -LOGIN_CHECK=$(grep alert-error /tmp/horizon.txt) - -rm /tmp/cookie.txt -rm /tmp/horizon.txt - -if [ "${TIMEOUT_CHECK}" == "" ] || [ "${LOGIN_CHECK}" != "" ]; then - echo "CRITICAL - Horizon is inaccessible" - exit 2 -fi - -echo "Horizon Login OK" -exit 0 diff --git a/nagios-plugins/keystone-token.sh b/nagios-plugins/keystone-token.sh deleted file mode 100644 index ca721e6..0000000 --- a/nagios-plugins/keystone-token.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash - -source ~/openrc - -keystone token-get 2>&1 > /dev/null -if [ $? == 0 ]; then - echo "OK - Got a Keystone token." - exit 0 -else - echo "CRITICAL - Unable to get a Keystone token." - exit 2 -fi diff --git a/nagios-plugins/libvirt-virsh.sh b/nagios-plugins/libvirt-virsh.sh deleted file mode 100644 index 6ce7bcf..0000000 --- a/nagios-plugins/libvirt-virsh.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -# Uses sudo, so an entry in /etc/sudoers is most likely required. - -sudo virsh list 2>&1 > /dev/null -if [ $? -eq 1 ]; then - echo "CRITICAL - problem with libvirt" - exit 3 -else - vms=$(sudo virsh list | grep instance | wc -l) - echo "OK - ${vms} running" - exit 0 -fi diff --git a/nagios-plugins/nova-services.sh b/nagios-plugins/nova-services.sh deleted file mode 100644 index df88a59..0000000 --- a/nagios-plugins/nova-services.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -source ~/openrc - -output=$(nova service-list | grep down) -if [ $? -eq 0 ]; then - echo -n "CRITICAL - OpenStack Nova services down: " - echo "${output}" | awk '{print $2,$4}' | while read LINE; do - echo -n "${LINE}; " - done - echo "" - exit 2 -else - echo "OK - All nodes up" - exit 0 -fi diff --git a/nagios-plugins/swift-healthcheck.sh b/nagios-plugins/swift-healthcheck.sh deleted file mode 100644 index 110042c..0000000 --- a/nagios-plugins/swift-healthcheck.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/bash - -x=$(/usr/bin/curl -s https://${1}:8080/healthcheck) -if [ "${x}" == "OK" ]; then - echo "OK - Swift Proxy healthcheck is reporting ${x}" - exit 0 -else - echo "CRITICAL - Swift Proxy healthcheck is reporting ${x}" - exit 3 -fi diff --git a/sensu-plugins/check_keystone-api.rb b/sensu-plugins/check_keystone-api.rb deleted file mode 100755 index fad6c34..0000000 --- a/sensu-plugins/check_keystone-api.rb +++ /dev/null @@ -1,86 +0,0 @@ -#!/usr/bin/env ruby -# -# Keystone API monitoring script for Sensu -# -# Copyright © 2014 Christopher Eckhardt -# -# Author: Christopher Eckhardt -# -# Released under the same terms as Sensu (the MIT license); see LICENSE -# for details. -# -require 'rubygems' if RUBY_VERSION < '1.9.0' -require 'sensu-plugin/check/cli' -require 'net/http' -require 'net/https' -require 'json' - -class CheckKeystoneAPI < Sensu::Plugin::Check::CLI - - option :url, :short => '-u URL' - option :tenant, :short => '-T TENANT' - option :user, :short => '-U USERNAME' - option :pass, :short => '-P PASSWORD' - option :timeout, :short => '-t SECONDS', :proc => proc {|a| a.to_i}, :default => 10 - - - def run - if config[:url] - uri = URI.parse(config[:url]) - config[:host] = uri.host - config[:port] = uri.port - config[:path] = uri.path + '/tokens' - config[:ssl] = uri.scheme == 'https' - else - unless config[:host] and config[:path] - unknown 'No URL specified' - end - config[:port] ||= 5000 - end - - begin - timeout(config[:timeout]) do - request_token - end - rescue Timeout::Error - critical "Keystone API timed out" - rescue => e - critical "Keystone API Connection error: #{e.message}" - end - end - - - def request_token - - conn = Net::HTTP.new(config[:host], config[:port]) - - if config[:ssl] - conn.use_ssl = true - conn.verify_mode = OpenSSL::SSL::VERIFY_NONE - end - - api_request = { - 'auth' => { - 'passwordCredentials' => { - 'username' => config[:user], - 'password' => config[:pass] - }, - 'tenantName' => config[:tenant] - } - }.to_json - - req = Net::HTTP::Post.new(config[:path]) - req.body = api_request - req['Content-Type'] = 'application/json' - res = conn.start{|http| http.request(req)} - - case res.code - when /^2/ - ok res.code + res.body - when /^[45]/ - critical res.code + res.body - else - warning res.code + res.body - end - end -end