diff --git a/.gitignore b/.gitignore deleted file mode 100644 index e8e153c..0000000 --- a/.gitignore +++ /dev/null @@ -1,7 +0,0 @@ -.tox -AUTHORS -ChangeLog -*.egg-info -*.pyc -.testrepository -doc/build diff --git a/.gitreview b/.gitreview deleted file mode 100644 index 8743cd7..0000000 --- a/.gitreview +++ /dev/null @@ -1,4 +0,0 @@ -[gerrit] -host=review.openstack.org -port=29418 -project=stackforge/monitoring-for-openstack.git diff --git a/.testr.conf b/.testr.conf deleted file mode 100644 index 4f48ace..0000000 --- a/.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/LICENSE b/LICENSE deleted file mode 100644 index 37ec93a..0000000 --- a/LICENSE +++ /dev/null @@ -1,191 +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: - -You must give any other recipients of the Work or Derivative Works a copy of -this License; and -You must cause any modified files to carry prominent notices stating that You -changed the files; and -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 -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.rst b/README.rst index 791cc45..828f94b 100644 --- a/README.rst +++ b/README.rst @@ -1,23 +1,17 @@ monitoring-for-openstack ======================== -A bunch of scripts that you can use to monitor OpenStack Services +This project is no longer maintained. -License -======= +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". -Apache License 2.0 +(Optional:) +For an alternative project, please see osops-tools-monitoring at +https://git.openstack.org/openstack/osops-tools-monitoring . -Copyright 2012-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. +For any further questions, please email +openstack-dev@lists.openstack.org or join #openstack-dev on +Freenode. diff --git a/doc/source/conf.py b/doc/source/conf.py deleted file mode 100644 index e5a1293..0000000 --- a/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/doc/source/index.rst b/doc/source/index.rst deleted file mode 100644 index 10ef488..0000000 --- a/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/legacy/oschecks-check_horizon_login b/legacy/oschecks-check_horizon_login deleted file mode 100755 index abff662..0000000 --- a/legacy/oschecks-check_horizon_login +++ /dev/null @@ -1,114 +0,0 @@ -#!/bin/bash -# -# Nova create instance monitoring script for Sensu / Nagios -# -# Copyright 2014 eNovance -# -# Author: Florian Lambert -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Requirement: curl -# - -# Nagios/Sensu return codes -STATE_OK=0 -STATE_WARNING=1 -STATE_CRITICAL=2 -STATE_UNKNOWN=3 -STATE_DEPENDENT=4 - -# Script options - -usage () -{ - echo "Usage: $0 [OPTIONS]" - echo " -h Get help" - echo " -E URL for horizon dashboard. Ex: http://os.enocloud.com" - echo " -U Username to use to get an auth token" - echo " -P Password to use ro get an auth token" - echo " -c Temporaire file to store cookie. Ex: /tmp/check_horizon_cookieFile" -} - -output_result () { - # Output check result & refresh cache if requested - MSG="$1" - RETCODE=$2 - - echo "$MSG" - exit $RETCODE -} - -while getopts 'hH:U:P:E:c' OPTION -do - case $OPTION in - h) - usage - exit 0 - ;; - E) - export HORIZON_URL=$OPTARG - ;; - U) - export OS_USERNAME=$OPTARG - ;; - P) - export OS_PASSWORD=$OPTARG - ;; - c) - export COOKIE_FILE=$OPTARG - ;; - *) - usage - exit 1 - ;; - esac -done - -COOKIE_FILE=${COOKIE_FILE:-"/tmp/check_horizon_cookieFile"} - -if [ -z "$OS_USERNAME" ] || [ -z "$OS_PASSWORD" ] || [ -z "$HORIZON_URL" ] -then - usage - exit 1 -fi - -if ! which curl > /dev/null 2>&1 -then - output_result "UNKNOWN - curl is not installed." $STATE_UNKNOWN -fi - - -# Get CSRFTOKEN and REGION on index -GET_INDEX=$(curl -s -c $COOKIE_FILE -i $HORIZON_URL) - -if [ -z "$GET_INDEX" ] -then - output_result "CRITICAL - $HORIZON_URL not respond." $STATE_CRITICAL -fi - -CSRFTOKEN=$(echo $GET_INDEX | sed -r "s/.*csrfmiddlewaretoken['\"] value=['\"]([^'\"]+)['\"].*/\1/") -REGION=$(echo $GET_INDEX | sed -r "s/.*region['\"] value=['\"]([^\"']+)['\"].*/\1/") - -# Send POST login with CSRFTOKEN and REGION on /auth/login/ -RESULT=$(curl -s -L -b "$COOKIE_FILE" --referer $HORIZON_URL --data "username=$OS_USERNAME&password=$OS_PASSWORD®ion=$REGION&csrfmiddlewaretoken=$CSRFTOKEN" $HORIZON_URL/auth/login/) - - -# If Auth work, find patterns Overview -if [ ` echo $RESULT | grep OpenStack | wc -l ` -ne 0 ] -then - output_result "OK - Found string OpenStack in $HORIZON_URL" $STATE_OK -else - output_result "CRITICAL - String \"Overview\" not found in $HORIZON_URL" $STATE_CRITICAL -fi diff --git a/legacy/oschecks-check_swift b/legacy/oschecks-check_swift deleted file mode 100755 index 58eb7a7..0000000 --- a/legacy/oschecks-check_swift +++ /dev/null @@ -1,122 +0,0 @@ -#!/bin/bash -# -# Swift monitoring script for Nagios -# -# Copyright 2012 eNovance -# -# Author: Julien Danjou -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# - -set -e - -STATE_OK=0 -STATE_WARNING=1 -STATE_CRITICAL=2 -STATE_UNKNOWN=3 -STATE_DEPENDENT=4 - -usage () -{ - echo "Usage: $0 [OPTIONS]" - echo " -h Get help" - echo " -A URL for obtaining an auth token" - echo " -U Username to use to get an auth token" - echo " -K Password to use to get an auth token" - echo " -T Tenant name to use" - echo " -V Version for authentication" - echo " -c Container to upload to" - echo " -s Determine maximum file size in KB" - echo " (default: 1024)" -} - -while getopts 'hH:A:U:K:T:V:c:s:' OPTION -do - case $OPTION in - h) - usage - exit 0 - ;; - A) - export OS_AUTH_URL=$OPTARG - ;; - U) - export OS_USERNAME=$OPTARG - ;; - K) - export OS_PASSWORD=$OPTARG - ;; - T) - export OS_TENANT_NAME=$OPTARG - ;; - V) - export ST_AUTH_VERSION=$OPTARG - ;; - c) - container=$OPTARG - ;; - s) - multi=$OPTARG - ;; - *) - usage - exit 1 - ;; - esac -done - -multi=${multi:-1024} -container=${container:-check_swift} - -if ! which swift >/dev/null 2>&1 -then - echo "Swift command not found" - exit $STATE_UNKNOWN -fi - -delete_files () -{ - test -n "$KEY" && swift delete "$container" "$KEY" >/dev/null 2>&1 || true - rm -f "$TMPFILE" "$TMPFILE_TARGET" -} - -trap delete_files EXIT - -TMPFILE=`mktemp` -BLOCK_NUMBER=$(($RANDOM * $multi / 32767)) -BLOCK_SIZE=1024 -dd if=/dev/urandom of=$TMPFILE count=$BLOCK_NUMBER bs=$BLOCK_SIZE >/dev/null 2>&1 - -TMPFILE_TARGET=`mktemp` - -if ! KEY=$(swift upload "$container" "$TMPFILE" 2>/dev/null) -then - echo "Unable to upload file" - exit $STATE_CRITICAL -fi - -if ! swift download "$container" "$KEY" -o "$TMPFILE_TARGET" >/dev/null 2>&1 -then - echo "File upload OK, but unable to download file" - exit $STATE_CRITICAL -fi - -if ! swift delete "$container" "$KEY" >/dev/null 2>&1 -then - echo "File upload+download OK, but unable to delete uploaded file" - exit $STATE_CRITICAL -fi - -echo "Upload+download+delete of $(($BLOCK_NUMBER * $BLOCK_SIZE / 1024)) KiB file in container $container" diff --git a/legacy/oschecks-check_swift_dispersion b/legacy/oschecks-check_swift_dispersion deleted file mode 100755 index acb5281..0000000 --- a/legacy/oschecks-check_swift_dispersion +++ /dev/null @@ -1,59 +0,0 @@ -#!/usr/bin/env python -# -*- encoding: utf-8 -*- -# -# Swift dispersion monitoring script for Nagios -# -# Copyright © 2012 eNovance -# -# Author: Julien Danjou -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# - -import os -import sys -import json - -STATE_OK=0 -STATE_WARNING=1 -STATE_CRITICAL=2 -STATE_UNKNOWN=3 -STATE_DEPENDENT=4 - -with os.popen("swift-dispersion-report -j %s" \ - % os.getenv("SWIFT_DISPERSION_CONFIG", "/etc/swift/dispersion.conf")) as report: - stats = json.load(report) - -msgs = [] -state = STATE_OK - -# type_ is either "objects", "container" -for type_, values in stats.iteritems(): - - msgs.append("%.2f%% %ss found" % (values['pct_found'], type_)) - - if values.get('missing_one', 0)> 0: - msgs.append("%d %ss missing one copy" % (values['missing_one'], type_)) - state = max(state, STATE_WARNING) - - if values.get('missing_two', 0) > 0: - msgs.append("%d %ss missing two copies" % (values['missing_two'], type_)) - state = max(state, STATE_WARNING) - - if values.get('missing_all', 0) > 0: - msgs.append("%d %ss missing ALL copies" % (values['missing_all'], type_)) - state = max(state, STATE_CRITICAL) - -print ", ".join(msgs) -sys.exit(state) diff --git a/legacy/oschecks-check_swift_object_servers b/legacy/oschecks-check_swift_object_servers deleted file mode 100755 index cacf5ac..0000000 --- a/legacy/oschecks-check_swift_object_servers +++ /dev/null @@ -1,70 +0,0 @@ -#!/bin/sh -# -# check_swift_object_servers - Check OpenStack Swift object servers status -# -# Copyright 2012 eNovance -# -# Author: Julien Danjou -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# - - -PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin - -PROGNAME=`basename $0` -REVISION="1.0" - -STATE_OK=0 -STATE_WARNING=1 -STATE_CRITICAL=2 -STATE_UNKNOWN=3 -STATE_DEPENDENT=4 - - -print_usage() { - echo "Usage: $PROGNAME" -} - -print_help() { - print_usage - echo "This plugin checks Swift status using the swift-recon program." - exit 0 -} - -case "$1" in - --help|-h) - print_help - exit 0 - ;; -esac - -if ! which swift-recon >/dev/null 2>&1 -then - echo "swift-recon command not found" - exit $STATE_UNKNOWN -fi - -CHECK=$(swift-recon --md5 | grep ' error') -echo $CHECK - -if echo "$CHECK" | grep -q ' 0 error' -then - exit $STATE_OK -elif echo "$CHECK" | grep -q ' 1 error' -then - exit $STATE_WARNING -else - exit $STATE_CRITICAL -fi diff --git a/legacy/oschecks-check_swift_recon b/legacy/oschecks-check_swift_recon deleted file mode 100755 index 75c3fc8..0000000 --- a/legacy/oschecks-check_swift_recon +++ /dev/null @@ -1,135 +0,0 @@ -#!/bin/bash -# -# check_swift_recon - Check OpenStack Swift recon values -# -# Copyright 2012 eNovance -# -# Author: Mehdi Abaakouk -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU Affero General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Affero General Public License for more details. -# -# You should have received a copy of the GNU Affero General Public License -# along with this program. If not, see . -# - - -PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin - -PROGNAME=`basename $0` -REVISION="1.0" - -STATE_OK=0 -STATE_WARNING=1 -STATE_CRITICAL=2 -STATE_UNKNOWN=3 -STATE_DEPENDENT=4 - - -print_usage() { - echo "Usage: $PROGNAME [--field|-f] FIELD [[--critical|-c] VALUE [--warning|-w] VALUE]" -} - -print_help() { - print_usage - echo "This plugin checks Swift status using the swift-recon program." - exit 1 -} - -while [ "$1" ]; do - case "$1" in - --help|-h) - print_help - exit 0 - ;; - --field|-f) - field=$2 - shift ; shift - ;; - --critical|-c) - critical=$2 - shift ; shift - ;; - --warning|-w) - warning=$2 - shift ; shift - ;; - esac -done - -[ ! "$field" ] && print_help - -if ! which swift-recon >/dev/null 2>&1 -then - echo "swift-recon command not found" - exit $STATE_UNKNOWN -fi - - -case $field in - async_pending) - opt="--async" - no_hosts_data_is_ok=1 - ;; - replication_time) - opt="--replication" - ;; - ALL_auditor|ZBF_auditor) - opt="--auditor" - ;; - updater_last_sweep) - opt="--updater" - ;; - object_expiration_pass|expired_last_pass) - opt="--expirer" - ;; - quarantined_objects|quarantined_accounts|quarantined_containers) - opt="--quarantined" - ;; - orphan|tcp_in_use|time_wait|tcp6_in_use|tcp_mem_allocated_bytes) - opt="--sockstat" - ;; -esac - -data=$(swift-recon $opt | sed -n 's/^\['$field'\] //gp') -eval $(echo $data | sed -n 's/^low: \([[:digit:]\.]*\), high: \([[:digit:]\.]*\), avg: \([[:digit:]\.]*\), total: \([[:digit:]\.]*\), Failed: \([[:digit:]\.]*\)%, no_result: \([[:digit:]\.]*\), reported: \([[:digit:]\.]*\)/low="\1";high="\2";avg="\3";total="\4";failed="\5";no_result="\6";reported="\7"/gp') - -if [ "$(echo $data | grep 'No hosts returned valid data')" ] ; then - no_host_data=1 -else - failed=$(( ${failed/./} / 10 )) # change percent in perthousand - avg=$(( ${avg/./} / 10 )) # change percent in perthousand -fi - -if [ "$no_host_data" ]; then - if [ "$no_hosts_data_is_ok" ]; then - echo "OK - No data" - exit $STATE_OK - else - echo "CRITICAL - $data" - exit $STATE_CRITICAL - fi -elif [ "$no_result" != "0" ]; then - echo "CRITICAL - $data" - exit $STATE_CRITICAL -elif [ "$failed" != "0" ]; then - echo "CRITICAL - $data" - exit $STATE_CRITICAL -elif [ -n "$critical" -a -n "$warning" ]; then - if [ $avg -ge $warning -a $avg -lt $critical ]; then - echo "WARNING - $data" - exit $STATE_WARNING - elif [ $avg -ge $critical ]; then - echo "CRITICAL - $data" - exit $STATE_CRITICAL - fi -fi -echo "OK - $data" -exit $STATE_OK diff --git a/legacy/oschecks-check_swift_ring_usage b/legacy/oschecks-check_swift_ring_usage deleted file mode 100755 index 36cdf53..0000000 --- a/legacy/oschecks-check_swift_ring_usage +++ /dev/null @@ -1,91 +0,0 @@ -#!/bin/bash -# -# Check the disk usage of the Swift ring -# -# Copyright 2014 eNovance -# -# Author: Gaetan Trellu -# -# This program is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program. If not, see . -# -# Requirement : swift-recon -# -set -e - -STATE_OK=0 -STATE_WARNING=1 -STATE_CRITICAL=2 -STATE_UNKNOWN=3 - -RECON_BINARY=/usr/bin/swift-recon - -function usage() { - echo "This plugin checks the ring disk usage by using the swift-recon command." - echo - echo "Usage: `basename $0` [OPTIONS]" - echo " -h Display this help" - echo " -c Set the critical limit in % for the ring usage. Ex: 95" - echo " -w Set the warning limit in % for the ring usage. Ex: 90" - echo -} - -while getopts 'w:c:h' OPTION -do - case $OPTION in - h) - usage - exit 0 - ;; - c) - export CRITICAL=$OPTARG - ;; - w) - export WARNING=$OPTARG - ;; - *) - usage - exit 1 - ;; - esac -done - -#Default values -CRITICAL=${CRITICAL:-"90"} -WARNING=${WARNING:-"80"} - -if [ ! -x $RECON_BINARY ] -then - echo "CRITICAL: Unable to use the swift-recon binary" - exit $STATE_CRITICAL -else - - RING_USAGE=$(swift-recon -d | grep "avg" | awk '{ print $NF }' | cut -d"." -f1) - - if [ "$RING_USAGE" -ge "$WARNING" -a "$RING_USAGE" -lt "$CRITICAL" ] - then - echo "WARNING: $RING_USAGE% space used" - exit $STATUS_WARNING - fi - - if [ "$RING_USAGE" -ge "$CRITICAL" ] - then - echo "CRITICAL: $RING_USAGE% space used" - exit $STATUS_CRITICAL - else - echo "OK: $RING_USAGE% space used" - exit $STATUS_OK - fi - -fi - diff --git a/oschecks/__init__.py b/oschecks/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/oschecks/amqp.py b/oschecks/amqp.py deleted file mode 100755 index 9c4f007..0000000 --- a/oschecks/amqp.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env python -# -*- encoding: 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/oschecks/ceilometer.py b/oschecks/ceilometer.py deleted file mode 100755 index ffe4035..0000000 --- a/oschecks/ceilometer.py +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env python -# -*- encoding: 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_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() - - elapsed, meters = utils.timeit(client.meters.list) - if not meters: - utils.critical("Unable to contact Ceilometer API.") - - 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/oschecks/ceph.py b/oschecks/ceph.py deleted file mode 100644 index aaab6e4..0000000 --- a/oschecks/ceph.py +++ /dev/null @@ -1,120 +0,0 @@ -#!/usr/bin/env python -# -# 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 remaning(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 - - total = int(data['stats']['total_space']) - used = int(data['stats']['total_used']) - 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" % remaning(avail, total)) - elif avail < per(warn_percent, total): - return (1, "[WARN] Ceph df avail. waring %s" % remaning(avail, total)) - else: - return (0, "[OK] Ceph df avail. seems good %s" % - remaning(avail, total)) - - -def check_ceph_df(): - 'Program entry point.' - - try: - res = subprocess.check_output(["ceph", "df", "--format=json"], - 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: - res = subprocess.check_output(["ceph", "health"], - 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/oschecks/cinder.py b/oschecks/cinder.py deleted file mode 100644 index bf102f0..0000000 --- a/oschecks/cinder.py +++ /dev/null @@ -1,327 +0,0 @@ -#!/usr/bin/env python -# -*- encoding: 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(): - return client.quotas.get(options.os_tenant_name) - - elapsed, quotas = utils.timeit(quotas_list) - if not quotas: - utils.critical("Unable to contact cinder API.") - - 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 Novautils(object): - DAEMON_DEFAULT_PORT = 8776 - - def __init__(self, nova_client): - self.nova_client = nova_client - self.msgs = [] - self.start = self.totimestamp() - self.notifications = ["volume_creation_time=%s" % self.start] - self.volume = 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 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.nova_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.nova_client.client.management_url = url - - def check_existing_volume(self, volume_name, delete): - count = 0 - for s in self.nova_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 = {'display_name': volume_name, - 'size': size} - if volume_type: - conf['volume_type'] = volume_type - if availability_zone: - conf['availability_zone'] = availability_zone - self.volume = self.nova_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(): - parser = argparse.ArgumentParser( - description='Check an OpenStack Keystone server.') - parser.add_argument('--auth_url', metavar='URL', type=str, - default=os.getenv('OS_AUTH_URL'), - help='Keystone URL') - - parser.add_argument('--username', metavar='username', type=str, - default=os.getenv('OS_USERNAME'), - help='username to use for authentication') - - parser.add_argument('--password', metavar='password', type=str, - default=os.getenv('OS_PASSWORD'), - help='password to use for authentication') - - parser.add_argument('--tenant', metavar='tenant', type=str, - default=os.getenv('OS_TENANT_NAME'), - help='tenant name to use for authentication') - - parser.add_argument('--endpoint_url', metavar='endpoint_url', type=str, - help='Override the catalog endpoint.') - - parser.add_argument('--endpoint_type', metavar='endpoint_type', type=str, - default="publicURL", - help='Endpoint type in the catalog request. ' - + 'Public by default.') - - parser.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.') - - parser.add_argument('--api_version', metavar='api_version', type=str, - default='1', - help='Version of the API to use. 1 by default.') - - parser.add_argument('--timeout', metavar='timeout', type=int, - default=120, - help='Max number of second to create/delete a volume ' - + '(120 by default).') - - parser.add_argument('--volume_name', metavar='volume_name', type=str, - default="monitoring_test", - help='Name of the volume to create ' - + '(monitoring_test by default)') - - parser.add_argument('--volume_size', metavar='volume_size', type=int, - default=1, - help='Size of the volume to create (1 GB by default)') - - parser.add_argument('--volume_type', metavar='volume_type', type=str, - default=None, - help='With multiple backends, choose the volume type.') - - parser.add_argument('--availability_zone', metavar='availability_zone', - type=str, - default=None, - help='Specify availability zone.') - - parser.add_argument('--verbose', action='count', - help='Print requests on stderr.') - - args = parser.parse_args() - - # this shouldn't raise any exception as no connection is done when - # creating the object. But It may change, so I catch everything. - try: - nova_client = Client(args.api_version, - username=args.username, - project_id=args.tenant, - api_key=args.password, - auth_url=args.auth_url, - endpoint_type=args.endpoint_type, - http_log_debug=args.verbose) - except Exception as e: - utils.critical("Error creating cinder communication object: %s" % e) - - util = Novautils(nova_client) - - if args.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 args.endpoint_url: - util.mangle_url(args.endpoint_url) - # after mangling the url, the endpoint has changed. Check that - # it's valid. - util.check_connection(force=True) - - util.check_existing_volume(args.volume_name, args.force_delete) - util.create_volume(args.volume_name, - args.volume_size, - args.availability_zone, - args.volume_type) - util.volume_ready(args.timeout) - util.delete_volume() - util.volume_deleted(args.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/oschecks/glance.py b/oschecks/glance.py deleted file mode 100644 index 0af60f7..0000000 --- a/oschecks/glance.py +++ /dev/null @@ -1,130 +0,0 @@ -#!/usr/bin/env python -# -*- encoding: 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_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(): - return list(client.images.list()) - - elapsed, images = utils.timeit(images_list) - if not images: - utils.critical("Unable to contact Glance API.") - - if elapsed > options.critical: - utils.critical("Get images took more than %d seconds, " - "it's too long.|response_time=%d" % - (options.critical, elapsed)) - elif 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 _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() - - data_raw = "X" * 1024 * 1024 - elapsed, res = utils.timeit(client.images.create, - data=data_raw, - disk_format='raw', - container_format='bare', - name=options.image_name) - if not res or not res.id or res.status != 'active': - utils.critical("Unable to upload image in Glance") - - res.delete() - - 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/oschecks/keystone.py b/oschecks/keystone.py deleted file mode 100644 index aaf767e..0000000 --- a/oschecks/keystone.py +++ /dev/null @@ -1,44 +0,0 @@ -#!/usr/bin/env python -# -*- encoding: 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(): - options, args, client = keystone.setup() - return client.service_catalog.get_token() - - elapsed, token = utils.timeit(check_token) - if not token: - utils.critical("Unable to get a token") - - 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/oschecks/neutron.py b/oschecks/neutron.py deleted file mode 100644 index 8f70f1a..0000000 --- a/oschecks/neutron.py +++ /dev/null @@ -1,307 +0,0 @@ -#!/usr/bin/env python -# -*- encoding: 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() - - elapsed, networks = utils.timeit(client.list_networks) - 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) - - -DAEMON_DEFAULT_PORT = 9696 - - -def mangle_url(orig_url, url): - try: - endpoint_url = urlparse.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 = urlparse.urlparse(orig_url) - - port = endpoint_url.port - if port is None: - if catalog_url.port is None: - port = 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]) - return url - - -class Novautils(object): - def __init__(self, nova_client, tenant_id): - self.nova_client = nova_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.nova_client.list_ports() - except Exception as e: - utils.critical("Cannot connect to neutron: %s\n" % e) - - 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.nova_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.nova_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, router_name): - if not self.msgs: - if not self.network_id: - try: - self.network_id = self.nova_client.list_networks( - name=router_name, fields='id')['networks'][0]['id'] - except Exception: - self.msgs.append("Cannot find ext router named '%s'." - % router_name) - - def create_floating_ip(self): - if not self.msgs: - try: - body = {'floatingip': {'floating_network_id': self.network_id}} - self.fip = self.nova_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.nova_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(): - parser = argparse.ArgumentParser( - description='Check an Floating ip creation. Note that it is able ' - + 'to delete *all* floating ips from a account, so ' - + 'ensure that nothing important is running on the ' - + 'specified account.') - parser.add_argument('--auth_url', metavar='URL', type=str, - default=os.getenv('OS_AUTH_URL'), - help='Keystone URL') - - parser.add_argument('--username', metavar='username', type=str, - default=os.getenv('OS_USERNAME'), - help='username to use for authentication') - - parser.add_argument('--password', metavar='password', type=str, - default=os.getenv('OS_PASSWORD'), - help='password to use for authentication') - - parser.add_argument('--tenant', metavar='tenant', type=str, - default=os.getenv('OS_TENANT_NAME'), - help='tenant name to use for authentication') - - parser.add_argument('--endpoint_url', metavar='endpoint_url', type=str, - help='Override the catalog endpoint.') - - parser.add_argument('--endpoint_type', metavar='endpoint_type', type=str, - default="publicURL", - help='Endpoint type in the catalog request. ' - + 'Public by default.') - - parser.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.') - - parser.add_argument('--timeout', metavar='timeout', type=int, - default=120, - help='Max number of second to create/delete a ' - + 'floating ip (120 by default).') - - parser.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') - - parser.add_argument('--ext_router_name', metavar='ext_router_name', - type=str, default='public', - help='Name of the "public" router (public by default)') - - parser.add_argument('--verbose', action='count', - help='Print requests on stderr.') - - args = parser.parse_args() - - # this shouldn't raise any exception as no connection is done when - # creating the object. But It may change, so I catch everything. - try: - nova_client = client.Client( - username=args.username, - tenant_name=args.tenant, - password=args.password, - auth_url=args.auth_url, - ) - nova_client.authenticate() - except Exception as e: - utils.critical("Authentication error: %s\n" % e) - - try: - endpoint = nova_client.service_catalog.get_endpoints( - 'network')['network'][0][args.endpoint_type] - if args.endpoint_url: - endpoint = mangle_url(endpoint, args.endpoint_url) - - token = nova_client.service_catalog.get_token()['id'] - if args.verbose: - logging.basicConfig(level=logging.DEBUG) - neutron_client = neutron.Client('2.0', endpoint_url=endpoint, - token=token) - - except Exception as e: - utils.critical("Error creating neutron object: %s\n" % e) - util = Novautils(neutron_client, nova_client.tenant_id) - - # Initiate the first connection and catch error. - util.check_connection() - - if args.floating_ip: - util.check_existing_floatingip(args.floating_ip, args.force_delete) - util.get_network_id(args.ext_router_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/oschecks/nova.py b/oschecks/nova.py deleted file mode 100644 index f488a5e..0000000 --- a/oschecks/nova.py +++ /dev/null @@ -1,396 +0,0 @@ -#!/usr/bin/env python -# -*- encoding: 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(): - return list(client.flavors.list()) - - elapsed, flavors = utils.timeit(flavors_list) - if not flavors: - utils.critical("Unable to contact nova API.") - - 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: - self.image = self.nova_client.images.find(name=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 create_instance(self, instance_name, network): - if not self.msgs: - kwargs = {} - try: - if 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 found network %s" % - network) - return - kwargs['nics'] = [{'net-id': 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(): - parser = argparse.ArgumentParser( - description='Check an OpenStack Keystone server.') - parser.add_argument('--auth_url', metavar='URL', type=str, - default=os.getenv('OS_AUTH_URL'), - help='Keystone URL') - - parser.add_argument('--username', metavar='username', type=str, - default=os.getenv('OS_USERNAME'), - help='username to use for authentication') - - parser.add_argument('--password', metavar='password', type=str, - default=os.getenv('OS_PASSWORD'), - help='password to use for authentication') - - parser.add_argument('--tenant', metavar='tenant', type=str, - default=os.getenv('OS_TENANT_NAME'), - help='tenant name to use for authentication') - - parser.add_argument('--endpoint_url', metavar='endpoint_url', type=str, - help='Override the catalog endpoint.') - - parser.add_argument('--endpoint_type', metavar='endpoint_type', type=str, - default="publicURL", - help='Endpoint type in the catalog request.' - + 'Public by default.') - - parser.add_argument('--image_name', metavar='image_name', type=str, - default=default_image_name, - help="Image name to use (%s by default)" - % default_image_name) - - parser.add_argument('--flavor_name', metavar='flavor_name', type=str, - default=default_flavor_name, - help="Flavor name to use (%s by default)" - % default_flavor_name) - - parser.add_argument('--instance_name', metavar='instance_name', type=str, - default=default_instance_name, - help="Instance name to use (%s by default)" - % default_instance_name) - - parser.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.') - - parser.add_argument('--api_version', metavar='api_version', type=str, - default='2', - help='Version of the API to use. 2 by default.') - - parser.add_argument('--timeout', metavar='timeout', type=int, - default=120, - help='Max number of second to create a instance' - + '(120 by default)') - - parser.add_argument('--timeout_delete', metavar='timeout_delete', type=int, - default=45, - help='Max number of second to delete an existing ' - + 'instance (45 by default).') - - parser.add_argument('--insecure', action='store_true', - help="The server's cert will not be verified") - - parser.add_argument('--network', metavar='network', type=str, - help="Override the network name or ID to use") - - parser.add_argument('--verbose', action='count', - help='Print requests on stderr.') - - args = parser.parse_args() - - # this shouldn't raise any exception as no connection is done when - # creating the object. But It may change, so I catch everything. - try: - nova_client = Client(args.api_version, - username=args.username, - project_id=args.tenant, - api_key=args.password, - auth_url=args.auth_url, - endpoint_type=args.endpoint_type, - http_log_debug=args.verbose, - insecure=args.insecure) - except Exception as e: - utils.critical("Error creating nova communication object: %s\n" % e) - - util = Novautils(nova_client) - - if args.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 args.endpoint_url: - util.mangle_url(args.endpoint_url) - # after mangling the url, the endpoint has changed. Check that - # it's valid. - util.check_connection(force=True) - - util.check_existing_instance(args.instance_name, - args.force_delete, - args.timeout_delete) - util.get_image(args.image_name) - util.get_flavor(args.flavor_name) - util.create_instance(args.instance_name, args.network) - util.instance_ready(args.timeout) - util.delete_instance() - util.instance_deleted(args.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/oschecks/pacemaker_host_check.py b/oschecks/pacemaker_host_check.py deleted file mode 100755 index 64caf80..0000000 --- a/oschecks/pacemaker_host_check.py +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env python -# -*- encoding: 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 - -try: - import utils -except ImportError: - from oschecks import utils - - -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=True, - help='Script') - options = parser.parse_args() - - local_hostname = subprocess.check_output(['hostname', '-s']).strip() - - try: - output = subprocess.check_output(['pcs', 'status']) - except subprocess.CalledProcessError as e: - utils.critical('pcs status with status %s: %s' % - e.returncode, e.output) - except OSError: - utils.critical('pcs not found') - for line in 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 on this node " - "(but on %s)" % (resource, current_hostname)) - script = shlex.split(options.script) - os.execvp(script[0], script) - - else: - utils.critical('pacemaker resource %s not found' % - options.pacemaker_resource) - - -def pacemaker_host_check(): - utils.safe_run(_pacemaker_host_check) diff --git a/oschecks/process.py b/oschecks/process.py deleted file mode 100755 index 94b85ac..0000000 --- a/oschecks/process.py +++ /dev/null @@ -1,36 +0,0 @@ -#!/usr/bin/env python -# -*- encoding: 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/oschecks/tests/__init__.py b/oschecks/tests/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/oschecks/tests/test_ceph.py b/oschecks/tests/test_ceph.py deleted file mode 100644 index 9cc4593..0000000 --- a/oschecks/tests/test_ceph.py +++ /dev/null @@ -1,44 +0,0 @@ -# -# 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/oschecks/tests/test_script.py b/oschecks/tests/test_script.py deleted file mode 100644 index 8711ce0..0000000 --- a/oschecks/tests/test_script.py +++ /dev/null @@ -1,45 +0,0 @@ -# -# 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/oschecks/utils.py b/oschecks/utils.py deleted file mode 100755 index bfd7893..0000000 --- a/oschecks/utils.py +++ /dev/null @@ -1,276 +0,0 @@ -#!/usr/bin/env python -# -*- encoding: 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): - if p.name == name: - return True - # name can be truncated and a script so check also if it can be an - # argument to an interpreter - if len(p.cmdline) > 0 and os.path.basename(p.cmdline[0]) == name: - return True - if len(p.cmdline) > 1 and os.path.basename(p.cmdline[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: - connections = p.get_connections(kind='inet') - except psutil.NoSuchProcess: - continue - found_amqp = ( - len(list(itertools.takewhile(lambda c: len(c.remote_address) <= 1 - or c.remote_address[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.add_argument = self.nova.parser.add_argument - - def setup(self, api_version='1.1'): - from novaclient 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 = None - if options.os_auth_token and options.os_endpoint: - auth_token = options.os_auth_token - if options.os_compute_api_version: - api_version = options.os_compute_api_version - client = client.get_client_class(api_version)( - options.os_username, - options.os_password, - options.os_tenant_name, - tenant_id=options.os_tenant_id, - 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) - return options, args, 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() - self.add_argument = self.glance.parser.add_argument - - def setup(self, api_version=1): - (options, args) = self.glance.parser.parse_known_args(self.base_argv) - if options.help: - options.command = None - self.glance.do_help(options) - sys.exit(2) - client = self.glance._get_versioned_client(api_version, options, - force_auth=True) - 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:]) - # NOTE(gordc): workaround for bug1434264 - if not hasattr(self.ceilometer, 'auth_plugin'): - from ceilometerclient import client - if hasattr(client, 'AuthPlugin'): - self.ceilometer.auth_plugin = client.AuthPlugin() - 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.do_help(options) - sys.exit(2) - client_kwargs = vars(options) - return options, client.get_client(api_version, **client_kwargs) - - -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 - client = client.get_client_class(api_version)( - options.os_username, - options.os_password, - options.os_tenant_name, - tenant_id=options.os_tenant_id, - auth_url=options.os_auth_url, - region_name=options.os_region_name, - cacert=options.os_cacert, - insecure=options.insecure) - 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} - self.neutron.authenticate_user() - return options, args, self.neutron.client_manager.neutron - - -class Keystone(object): - def __init__(self): - from keystoneclient import shell - self.keystone = shell.OpenStackIdentityShell() - self.base_argv = copy.deepcopy(sys.argv[1:]) - self.keystone.parser = self.keystone.get_base_parser() - self.add_argument = self.keystone.parser.add_argument - - def setup(self, api_version="2.0"): - (options, args) = self.keystone.parser.parse_known_args(self.base_argv) - if options.help: - self.keystone.do_help(options) - sys.exit(2) - self.keystone.auth_check(options) - token = None - if options.os_token and options.os_endpoint: - token = options.os_token - if options.os_identity_api_version: - api_version = options.os_identity_api_version - client = self.keystone.get_api_class(api_version)( - username=options.os_username, - tenant_name=options.os_tenant_name, - tenant_id=options.os_tenant_id, - token=token, - endpoint=options.os_endpoint, - password=options.os_password, - auth_url=options.os_auth_url, - region_name=options.os_region_name, - cacert=options.os_cacert, - key=options.os_key, - cert=options.os_cert, - insecure=options.insecure, - debug=options.debug, - use_keyring=options.os_cache, - force_new_token=options.force_new_token, - stale_duration=options.stale_duration, - timeout=options.timeout) - return options, args, client diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 2516930..0000000 --- a/requirements.txt +++ /dev/null @@ -1,8 +0,0 @@ -psutil -python-ceilometerclient -python-cinderclient -python-glanceclient -python-keystoneclient -python-neutronclient -python-novaclient -six diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 9e599f1..0000000 --- a/setup.cfg +++ /dev/null @@ -1,60 +0,0 @@ -[metadata] -name = monitoring-for-openstack -version = 1 -summary = OpenStack monitoring tools -description-file = - README.rst -author = eNovance -author-email = techs@enovance.com -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.6 - Programming Language :: Python :: 2.7 - Programming Language :: Python :: 3.3 - Programming Language :: Python :: 3.4 - Topic :: System :: Monitoring - -[global] -setup-hooks = - pbr.hooks.setup_hook - -[files] -packages = - oschecks - -scripts = - legacy/oschecks-check_horizon_login - legacy/oschecks-check_swift - legacy/oschecks-check_swift_dispersion - legacy/oschecks-check_swift_object_servers - legacy/oschecks-check_swift_recon - legacy/oschecks-check_swift_ring_usage - -[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 - -[build_sphinx] -all_files = 1 -build-dir = doc/build -source-dir = doc/source diff --git a/setup.py b/setup.py deleted file mode 100755 index b96f524..0000000 --- a/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/test-requirements.txt b/test-requirements.txt deleted file mode 100644 index b09fe3f..0000000 --- a/test-requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -testrepository -discover -sphinx diff --git a/tox.ini b/tox.ini deleted file mode 100644 index 89dccab..0000000 --- a/tox.ini +++ /dev/null @@ -1,22 +0,0 @@ -[tox] -envlist = py26,py27,py33,py34,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:pep8] -deps = {[testenv]deps} - hacking>=0.9.2,<0.10 -commands = flake8 - -[testenv:venv] -commands = {posargs} - -[flake8] -exclude = .tox,doc -show-source = true