From 3b131c626b5d2dc3c9e4aeb2c9aecb0c565efa76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20M=C3=A1gr?= Date: Mon, 6 Nov 2017 13:21:27 +0100 Subject: [PATCH] Fix for check_cinder_volume - applied DRY principle on authentication - fixed confusing naming - removed conflicting parameters - switched to Cinder API V2+ - compatibility with python-cinder-11.0.0 Change-Id: If8e7f5a39ddaa9c15e1acc9f4f1c2a695954bde4 --- monitoring-for-openstack/oschecks/cinder.py | 125 ++++++-------------- 1 file changed, 39 insertions(+), 86 deletions(-) diff --git a/monitoring-for-openstack/oschecks/cinder.py b/monitoring-for-openstack/oschecks/cinder.py index 4fe959e..58ce45b 100644 --- a/monitoring-for-openstack/oschecks/cinder.py +++ b/monitoring-for-openstack/oschecks/cinder.py @@ -67,16 +67,17 @@ def check_cinder_api(): utils.safe_run(_check_cinder_api) -class Novautils(object): +class CinderUtils(object): DAEMON_DEFAULT_PORT = 8776 - def __init__(self, nova_client): - self.nova_client = nova_client + def __init__(self, client, project): + self.client = client self.msgs = [] self.start = self.totimestamp() self.notifications = ["volume_creation_time=%s" % self.start] self.volume = None self.connection_done = False + self.project = project # python has no "toepoch" method: http://bugs.python.org/issue2736 # now, after checking http://stackoverflow.com/a/16307378, @@ -94,7 +95,8 @@ class Novautils(object): if not self.connection_done or force: try: # force a connection to the server - self.connection_done = self.nova_client.limits.get() + self.connection_done = self.client.limits.get( + tenant_id=self.project) except Exception as e: utils.critical("Cannot connect to cinder: %s" % e) @@ -118,7 +120,7 @@ class Novautils(object): catalog_url = None try: catalog_url = urlparse.urlparse( - self.nova_client.client.management_url) + self.client.client.management_url) except Exception as e: utils.unknown("unknown error parsing the catalog url : %s" % e) @@ -136,11 +138,11 @@ class Novautils(object): catalog_url.params, catalog_url.query, catalog_url.fragment]) - self.nova_client.client.management_url = url + self.client.client.management_url = url def check_existing_volume(self, volume_name, delete): count = 0 - for s in self.nova_client.volumes.list(): + for s in self.client.volumes.list(): if s.display_name == volume_name: if delete: # asynchronous call, we do not check that it worked @@ -159,13 +161,12 @@ class Novautils(object): def create_volume(self, volume_name, size, availability_zone, volume_type): if not self.msgs: try: - conf = {'display_name': volume_name, - 'size': size} + conf = {'name': volume_name, 'size': size} if volume_type: conf['volume_type'] = volume_type if availability_zone: conf['availability_zone'] = availability_zone - self.volume = self.nova_client.volumes.create(**conf) + self.volume = self.client.volumes.create(**conf) except Exception as e: self.msgs.append("Cannot create the volume %s (%s)" % (volume_name, e)) @@ -213,107 +214,59 @@ class Novautils(object): 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') + cinder = utils.Cinder() - 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, + cinder.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.""") + cinder.add_argument('--force_delete', action='store_true', + help='If matching volumes are found, delete ' + 'them and add a notification in the ' + 'message instead of getting out in ' + 'critical state.') - 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, + cinder.add_argument('--volume_name', metavar='volume_name', type=str, default="monitoring_test", - help="""Name of the volume to create """ - """(monitoring_test by default)""") + help='Name of the volume to create ' + '(monitoring_test by default)') - parser.add_argument('--volume_size', metavar='volume_size', type=int, + cinder.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, + cinder.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', + cinder.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) + options, args, client = cinder.setup() + project = (options.os_project_id if options.os_project_id else + options.os_project_name) + tenant = (options.os_tenant_id if options.os_tenant_id else + options.os_tenant_name) + util = CinderUtils(client, tenant or project) # Initiate the first connection and catch error. util.check_connection() - if args.endpoint_url: - util.mangle_url(args.endpoint_url) + if options.endpoint_url: + util.mangle_url(options.endpoint_url) # after mangling the url, the endpoint has changed. Check that # it's valid. util.check_connection(force=True) - util.check_existing_volume(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.check_existing_volume(options.volume_name, options.force_delete) + util.create_volume(options.volume_name, + options.volume_size, + options.availability_zone, + options.volume_type) + util.volume_ready(options.timeout) util.delete_volume() - util.volume_deleted(args.timeout) + util.volume_deleted(options.timeout) if util.msgs: utils.critical(", ".join(util.msgs))