diff --git a/bin/cinder-volume-usage-audit b/bin/cinder-volume-usage-audit index 6d3aac43147..53ea460ae21 100755 --- a/bin/cinder-volume-usage-audit +++ b/bin/cinder-volume-usage-audit @@ -34,6 +34,7 @@ from __future__ import print_function +from datetime import datetime import os import sys import traceback @@ -51,8 +52,6 @@ if os.path.exists(os.path.join(POSSIBLE_TOPDIR, 'cinder', '__init__.py')): from cinder.openstack.common import gettextutils gettextutils.install('cinder') -# Need to register global_opts -from cinder.common import config # noqa from cinder import context from cinder import db from cinder.openstack.common import log as logging @@ -62,6 +61,23 @@ import cinder.volume.utils CONF = cfg.CONF +script_opts = [ + cfg.StrOpt('start_time', + default=None, + help="If this option is specified then the start time " + "specified is used instead of the start time of the " + "last completed audit period."), + cfg.StrOpt('end_time', + default=None, + help="If this option is specified then the end time " + "specified is used instead of the end time of the " + "last completed audit period."), + cfg.BoolOpt('send_actions', + default=False, + help="Send the volume and snapshot create and delete " + "notifications generated in the specified period."), +] +CONF.register_cli_opts(script_opts) if __name__ == '__main__': @@ -69,7 +85,19 @@ if __name__ == '__main__': CONF(sys.argv[1:], project='cinder', version=version.version_string()) logging.setup("cinder") + LOG = logging.getLogger("cinder") begin, end = utils.last_completed_audit_period() + if CONF.start_time: + begin = datetime.strptime(CONF.start_time, "%Y-%m-%d %H:%M:%S") + if CONF.end_time: + end = datetime.strptime(CONF.end_time, "%Y-%m-%d %H:%M:%S") + if not end > begin: + msg = _("The end time (%(end)s) must be after the start " + "time (%(start)s).") % {'start': begin, + 'end': end} + print(msg) + LOG.error(msg) + sys.exit(-1) print(_("Starting volume usage audit")) msg = _("Creating usages for %(begin_period)s until %(end_period)s") print(msg % {"begin_period": str(begin), "end_period": str(end)}) @@ -85,22 +113,147 @@ if __name__ == '__main__': print(_("Found %d volumes") % len(volumes)) for volume_ref in volumes: try: - cinder.volume.utils.notify_usage_exists(admin_context, - volume_ref) + LOG.debug(_("Send exists notification for " + "<%(extra_info)s>") % + {'volume_id': volume_ref.id, + 'project_id': volume_ref.project_id, + 'extra_info': extra_info}) + cinder.volume.utils.notify_about_volume_usage( + admin_context, + volume_ref, + 'exists', extra_usage_info=extra_info) except Exception as e: + LOG.error(_("Failed to send exists notification for volume %s.") % + volume_ref.id) print(traceback.format_exc(e)) + if (CONF.send_actions and + volume_ref.created_at > begin and + volume_ref.created_at < end): + try: + local_extra_info = { + 'audit_period_beginning': str(volume_ref.created_at), + 'audit_period_ending': str(volume_ref.created_at), + } + LOG.debug(_("Send create notification for " + " " + " <%(extra_info)s>") % + {'volume_id': volume_ref.id, + 'project_id': volume_ref.project_id, + 'extra_info': local_extra_info}) + cinder.volume.utils.notify_about_volume_usage( + admin_context, + volume_ref, + 'create.start', extra_usage_info=local_extra_info) + cinder.volume.utils.notify_about_volume_usage( + admin_context, + volume_ref, + 'create.end', extra_usage_info=local_extra_info) + except Exception as e: + LOG.error(_("Failed to send create notification for " + "volume %s.") % volume_ref.id) + print(traceback.format_exc(e)) + + if (CONF.send_actions and volume_ref.deleted_at and + volume_ref.deleted_at > begin and + volume_ref.deleted_at < end): + try: + local_extra_info = { + 'audit_period_beginning': str(volume_ref.deleted_at), + 'audit_period_ending': str(volume_ref.deleted_at), + } + LOG.debug(_("Send delete notification for " + " " + " <%(extra_info)s>") % + {'volume_id': volume_ref.id, + 'project_id': volume_ref.project_id, + 'extra_info': local_extra_info}) + cinder.volume.utils.notify_about_volume_usage( + admin_context, + volume_ref, + 'delete.start', extra_usage_info=local_extra_info) + cinder.volume.utils.notify_about_volume_usage( + admin_context, + volume_ref, + 'delete.end', extra_usage_info=local_extra_info) + except Exception as e: + LOG.error(_("Failed to send delete notification for volume " + "%s.") % volume_ref.id) + print(traceback.format_exc(e)) + snapshots = db.snapshot_get_active_by_window(admin_context, begin, end) print(_("Found %d snapshots") % len(snapshots)) for snapshot_ref in snapshots: try: + LOG.debug(_("Send notification for " + " <%(extra_info)s>") % + {'snapshot_id': snapshot_ref.id, + 'project_id': snapshot_ref.project_id, + 'extra_info': extra_info}) cinder.volume.utils.notify_about_snapshot_usage(admin_context, snapshot_ref, 'exists', extra_info) except Exception as e: + LOG.error(_("Failed to send exists notification for snapshot %s.") + % snapshot_ref.id) print(traceback.format_exc(e)) + if (CONF.send_actions and + snapshot_ref.created_at > begin and + snapshot_ref.created_at < end): + try: + local_extra_info = { + 'audit_period_beginning': str(snapshot_ref.created_at), + 'audit_period_ending': str(snapshot_ref.created_at), + } + LOG.debug(_("Send create notification for " + " " + " <%(extra_info)s>") % + {'snapshot_id': snapshot_ref.id, + 'project_id': snapshot_ref.project_id, + 'extra_info': local_extra_info}) + cinder.volume.utils.notify_about_snapshot_usage( + admin_context, + snapshot_ref, + 'create.start', extra_usage_info=local_extra_info) + cinder.volume.utils.notify_about_snapshot_usage( + admin_context, + snapshot_ref, + 'create.end', extra_usage_info=local_extra_info) + except Exception as e: + LOG.error(_("Failed to send create notification for snapshot " + "%s.") % snapshot_ref.id) + print(traceback.format_exc(e)) + + if (CONF.send_actions and snapshot_ref.deleted_at and + snapshot_ref.deleted_at > begin and + snapshot_ref.deleted_at < end): + try: + local_extra_info = { + 'audit_period_beginning': str(snapshot_ref.deleted_at), + 'audit_period_ending': str(snapshot_ref.deleted_at), + } + LOG.debug(_("Send delete notification for " + " " + " <%(extra_info)s>") % + {'snapshot_id': snapshot_ref.id, + 'project_id': snapshot_ref.project_id, + 'extra_info': local_extra_info}) + cinder.volume.utils.notify_about_snapshot_usage( + admin_context, + snapshot_ref, + 'delete.start', extra_usage_info=local_extra_info) + cinder.volume.utils.notify_about_snapshot_usage( + admin_context, + snapshot_ref, + 'delete.end', extra_usage_info=local_extra_info) + except Exception as e: + LOG.error(_("Failed to send delete notification for snapshot " + "%s.") % snapshot_ref.id) + print(traceback.format_exc(e)) + print(_("Volume usage audit completed"))