Merge "Add backup notification to cinder-volume-usage-audit"
This commit is contained in:
commit
3c2d1ab145
@ -246,4 +246,75 @@ def main():
|
||||
LOG.exception(_LE("Delete snapshot notification failed: %s"),
|
||||
exc_msg, resource=snapshot_ref)
|
||||
|
||||
backups = db.backup_get_active_by_window(admin_context,
|
||||
begin, end)
|
||||
|
||||
LOG.debug("Found %d backups", len(backups))
|
||||
for backup_ref in backups:
|
||||
try:
|
||||
LOG.debug("Send notification for <backup_id: %(backup_id)s> "
|
||||
"<project_id %(project_id)s> <%(extra_info)s>",
|
||||
{'backup_id': backup_ref.id,
|
||||
'project_id': backup_ref.project_id,
|
||||
'extra_info': extra_info})
|
||||
cinder.volume.utils.notify_about_backup_usage(admin_context,
|
||||
backup_ref,
|
||||
'exists',
|
||||
extra_info)
|
||||
except Exception as exc_msg:
|
||||
LOG.error(_LE("Exists backups notification failed: %s"),
|
||||
exc_msg)
|
||||
|
||||
if (CONF.send_actions and
|
||||
backup_ref.created_at > begin and
|
||||
backup_ref.created_at < end):
|
||||
try:
|
||||
local_extra_info = {
|
||||
'audit_period_beginning': str(backup_ref.created_at),
|
||||
'audit_period_ending': str(backup_ref.created_at),
|
||||
}
|
||||
LOG.debug("Send create notification for "
|
||||
"<backup_id: %(backup_id)s> "
|
||||
"<project_id %(project_id)s> <%(extra_info)s>",
|
||||
{'backup_id': backup_ref.id,
|
||||
'project_id': backup_ref.project_id,
|
||||
'extra_info': local_extra_info})
|
||||
cinder.volume.utils.notify_about_backup_usage(
|
||||
admin_context,
|
||||
backup_ref,
|
||||
'create.start', extra_usage_info=local_extra_info)
|
||||
cinder.volume.utils.notify_about_backup_usage(
|
||||
admin_context,
|
||||
backup_ref,
|
||||
'create.end', extra_usage_info=local_extra_info)
|
||||
except Exception as exc_msg:
|
||||
LOG.error(_LE("Create backup notification failed: %s"),
|
||||
exc_msg)
|
||||
|
||||
if (CONF.send_actions and backup_ref.deleted_at and
|
||||
backup_ref.deleted_at > begin and
|
||||
backup_ref.deleted_at < end):
|
||||
try:
|
||||
local_extra_info = {
|
||||
'audit_period_beginning': str(backup_ref.deleted_at),
|
||||
'audit_period_ending': str(backup_ref.deleted_at),
|
||||
}
|
||||
LOG.debug("Send delete notification for "
|
||||
"<backup_id: %(backup_id)s> "
|
||||
"<project_id %(project_id)s> <%(extra_info)s>",
|
||||
{'backup_id': backup_ref.id,
|
||||
'project_id': backup_ref.project_id,
|
||||
'extra_info': local_extra_info})
|
||||
cinder.volume.utils.notify_about_backup_usage(
|
||||
admin_context,
|
||||
backup_ref,
|
||||
'delete.start', extra_usage_info=local_extra_info)
|
||||
cinder.volume.utils.notify_about_backup_usage(
|
||||
admin_context,
|
||||
backup_ref,
|
||||
'delete.end', extra_usage_info=local_extra_info)
|
||||
except Exception as exc_msg:
|
||||
LOG.error(_LE("Delete backup notification failed: %s"),
|
||||
exc_msg)
|
||||
|
||||
LOG.debug("Volume usage audit completed")
|
||||
|
@ -1155,6 +1155,14 @@ def backup_get_all_by_volume(context, volume_id, filters=None):
|
||||
filters=filters)
|
||||
|
||||
|
||||
def backup_get_active_by_window(context, begin, end=None, project_id=None):
|
||||
"""Get all the backups inside the window.
|
||||
|
||||
Specifying a project_id will filter for a certain project.
|
||||
"""
|
||||
return IMPL.backup_get_active_by_window(context, begin, end, project_id)
|
||||
|
||||
|
||||
def backup_update(context, backup_id, values):
|
||||
"""Set the given properties on a backup and update it.
|
||||
|
||||
|
@ -4696,6 +4696,21 @@ def backup_get_all_by_volume(context, volume_id, filters=None):
|
||||
return _backup_get_all(context, filters)
|
||||
|
||||
|
||||
@require_context
|
||||
def backup_get_active_by_window(context, begin, end=None, project_id=None):
|
||||
"""Return backups that were active during window."""
|
||||
|
||||
query = model_query(context, models.Backup, read_deleted="yes")
|
||||
query = query.filter(or_(models.Backup.deleted_at == None, # noqa
|
||||
models.Backup.deleted_at > begin))
|
||||
if end:
|
||||
query = query.filter(models.Backup.created_at < end)
|
||||
if project_id:
|
||||
query = query.filter_by(project_id=project_id)
|
||||
|
||||
return query.all()
|
||||
|
||||
|
||||
@handle_db_data_error
|
||||
@require_context
|
||||
def backup_create(context, values):
|
||||
|
@ -20,6 +20,8 @@ ATTACHMENT2_ID = 'ac2439fe-c071-468f-94e3-547bedb95de0'
|
||||
BACKUP_ID = '707844eb-6d8a-4ac1-8b98-618e1c0b3a3a'
|
||||
BACKUP2_ID = '40e8462a-c9d8-462f-a810-b732a1790535'
|
||||
BACKUP3_ID = '30ae7641-017e-4221-a642-855687c8bd71'
|
||||
BACKUP4_ID = '23f8605b-8273-4f49-9b3d-1eeca81a63c2'
|
||||
BACKUP5_ID = '50c97b22-51ea-440b-8d01-ded20a55d7e0'
|
||||
CGSNAPSHOT_ID = '5e34cce3-bc97-46b7-a127-5cfb95ef445d'
|
||||
CGSNAPSHOT_NAME = 'cgsnapshot-5e34cce3-bc97-46b7-a127-5cfb95ef445d'
|
||||
CGSNAPSHOT2_ID = '5c36d762-d6ba-4f04-bd07-88a298cc410a'
|
||||
|
@ -1754,6 +1754,72 @@ class TestCinderVolumeUsageAuditCmd(test.TestCase):
|
||||
extra_usage_info=local_extra_info_delete)
|
||||
])
|
||||
|
||||
@mock.patch('cinder.volume.utils.notify_about_backup_usage')
|
||||
@mock.patch('cinder.db.backup_get_active_by_window')
|
||||
@mock.patch('cinder.volume.utils.notify_about_volume_usage')
|
||||
@mock.patch('cinder.db.volume_get_active_by_window')
|
||||
@mock.patch('cinder.utils.last_completed_audit_period')
|
||||
@mock.patch('cinder.rpc.init')
|
||||
@mock.patch('cinder.version.version_string')
|
||||
@mock.patch('cinder.context.get_admin_context')
|
||||
def test_main_send_backup_error(self, get_admin_context,
|
||||
version_string, rpc_init,
|
||||
last_completed_audit_period,
|
||||
volume_get_active_by_window,
|
||||
notify_about_volume_usage,
|
||||
backup_get_active_by_window,
|
||||
notify_about_backup_usage):
|
||||
CONF.set_override('send_actions', True)
|
||||
CONF.set_override('start_time', '2014-01-01 01:00:00')
|
||||
CONF.set_override('end_time', '2014-02-02 02:00:00')
|
||||
begin = datetime.datetime(2014, 1, 1, 1, 0)
|
||||
end = datetime.datetime(2014, 2, 2, 2, 0)
|
||||
ctxt = context.RequestContext('fake-user', 'fake-project')
|
||||
get_admin_context.return_value = ctxt
|
||||
last_completed_audit_period.return_value = (begin, end)
|
||||
backup1_created = datetime.datetime(2014, 1, 1, 2, 0)
|
||||
backup1_deleted = datetime.datetime(2014, 1, 1, 3, 0)
|
||||
backup1 = mock.MagicMock(id=fake.BACKUP_ID,
|
||||
project_id=fake.PROJECT_ID,
|
||||
created_at=backup1_created,
|
||||
deleted_at=backup1_deleted)
|
||||
volume_get_active_by_window.return_value = []
|
||||
backup_get_active_by_window.return_value = [backup1]
|
||||
extra_info = {
|
||||
'audit_period_beginning': str(begin),
|
||||
'audit_period_ending': str(end),
|
||||
}
|
||||
local_extra_info_create = {
|
||||
'audit_period_beginning': str(backup1.created_at),
|
||||
'audit_period_ending': str(backup1.created_at),
|
||||
}
|
||||
local_extra_info_delete = {
|
||||
'audit_period_beginning': str(backup1.deleted_at),
|
||||
'audit_period_ending': str(backup1.deleted_at),
|
||||
}
|
||||
|
||||
notify_about_backup_usage.side_effect = Exception()
|
||||
|
||||
volume_usage_audit.main()
|
||||
|
||||
get_admin_context.assert_called_once_with()
|
||||
self.assertEqual('cinder', CONF.project)
|
||||
self.assertEqual(CONF.version, version.version_string())
|
||||
rpc_init.assert_called_once_with(CONF)
|
||||
last_completed_audit_period.assert_called_once_with()
|
||||
volume_get_active_by_window.assert_called_once_with(ctxt, begin, end)
|
||||
self.assertFalse(notify_about_volume_usage.called)
|
||||
notify_about_backup_usage.assert_any_call(ctxt, backup1, 'exists',
|
||||
extra_info)
|
||||
notify_about_backup_usage.assert_any_call(
|
||||
ctxt, backup1, 'create.start',
|
||||
extra_usage_info=local_extra_info_create)
|
||||
notify_about_backup_usage.assert_any_call(
|
||||
ctxt, backup1, 'delete.start',
|
||||
extra_usage_info=local_extra_info_delete)
|
||||
|
||||
@mock.patch('cinder.volume.utils.notify_about_backup_usage')
|
||||
@mock.patch('cinder.db.backup_get_active_by_window')
|
||||
@mock.patch('cinder.volume.utils.notify_about_snapshot_usage')
|
||||
@mock.patch('cinder.objects.snapshot.SnapshotList.get_active_by_window')
|
||||
@mock.patch('cinder.volume.utils.notify_about_volume_usage')
|
||||
@ -1767,7 +1833,8 @@ class TestCinderVolumeUsageAuditCmd(test.TestCase):
|
||||
def test_main(self, get_admin_context, log_setup, get_logger,
|
||||
version_string, rpc_init, last_completed_audit_period,
|
||||
volume_get_active_by_window, notify_about_volume_usage,
|
||||
snapshot_get_active_by_window, notify_about_snapshot_usage):
|
||||
snapshot_get_active_by_window, notify_about_snapshot_usage,
|
||||
backup_get_active_by_window, notify_about_backup_usage):
|
||||
CONF.set_override('send_actions', True)
|
||||
CONF.set_override('start_time', '2014-01-01 01:00:00')
|
||||
CONF.set_override('end_time', '2014-02-02 02:00:00')
|
||||
@ -1812,6 +1879,22 @@ class TestCinderVolumeUsageAuditCmd(test.TestCase):
|
||||
'audit_period_ending': str(snapshot1.deleted_at),
|
||||
}
|
||||
|
||||
backup1_created = datetime.datetime(2014, 1, 1, 2, 0)
|
||||
backup1_deleted = datetime.datetime(2014, 1, 1, 3, 0)
|
||||
backup1 = mock.MagicMock(id=fake.BACKUP_ID,
|
||||
project_id=fake.PROJECT_ID,
|
||||
created_at=backup1_created,
|
||||
deleted_at=backup1_deleted)
|
||||
backup_get_active_by_window.return_value = [backup1]
|
||||
extra_info_backup_create = {
|
||||
'audit_period_beginning': str(backup1.created_at),
|
||||
'audit_period_ending': str(backup1.created_at),
|
||||
}
|
||||
extra_info_backup_delete = {
|
||||
'audit_period_beginning': str(backup1.deleted_at),
|
||||
'audit_period_ending': str(backup1.deleted_at),
|
||||
}
|
||||
|
||||
volume_usage_audit.main()
|
||||
|
||||
get_admin_context.assert_called_once_with()
|
||||
@ -1845,3 +1928,15 @@ class TestCinderVolumeUsageAuditCmd(test.TestCase):
|
||||
mock.call(ctxt, snapshot1, 'delete.end',
|
||||
extra_usage_info=extra_info_snapshot_delete)
|
||||
])
|
||||
|
||||
notify_about_backup_usage.assert_has_calls([
|
||||
mock.call(ctxt, backup1, 'exists', extra_info),
|
||||
mock.call(ctxt, backup1, 'create.start',
|
||||
extra_usage_info=extra_info_backup_create),
|
||||
mock.call(ctxt, backup1, 'create.end',
|
||||
extra_usage_info=extra_info_backup_create),
|
||||
mock.call(ctxt, backup1, 'delete.start',
|
||||
extra_usage_info=extra_info_backup_delete),
|
||||
mock.call(ctxt, backup1, 'delete.end',
|
||||
extra_usage_info=extra_info_backup_delete)
|
||||
])
|
||||
|
@ -5924,7 +5924,6 @@ class GetActiveByWindowTestCase(BaseVolumeTestCase):
|
||||
'deleted': True, 'status': 'deleted',
|
||||
'deleted_at': datetime.datetime(1, 2, 1, 1, 1, 1),
|
||||
},
|
||||
|
||||
{
|
||||
'id': fake.VOLUME2_ID,
|
||||
'host': 'devstack',
|
||||
@ -5998,6 +5997,48 @@ class GetActiveByWindowTestCase(BaseVolumeTestCase):
|
||||
}
|
||||
]
|
||||
|
||||
self.db_back_attrs = [
|
||||
{
|
||||
'id': fake.BACKUP_ID,
|
||||
'host': 'devstack',
|
||||
'project_id': fake.PROJECT_ID,
|
||||
'created_at': datetime.datetime(1, 1, 1, 1, 1, 1),
|
||||
'deleted': 1,
|
||||
'status': 'deleted',
|
||||
'deleted_at': datetime.datetime(1, 2, 1, 1, 1, 1)
|
||||
},
|
||||
{
|
||||
'id': fake.BACKUP2_ID,
|
||||
'host': 'devstack',
|
||||
'project_id': fake.PROJECT_ID,
|
||||
'created_at': datetime.datetime(1, 1, 1, 1, 1, 1),
|
||||
'deleted': 1,
|
||||
'status': 'deleted',
|
||||
'deleted_at': datetime.datetime(1, 3, 10, 1, 1, 1)
|
||||
},
|
||||
{
|
||||
'id': fake.BACKUP3_ID,
|
||||
'host': 'devstack',
|
||||
'project_id': fake.PROJECT_ID,
|
||||
'created_at': datetime.datetime(1, 1, 1, 1, 1, 1),
|
||||
'deleted': 1,
|
||||
'status': 'deleted',
|
||||
'deleted_at': datetime.datetime(1, 5, 1, 1, 1, 1)
|
||||
},
|
||||
{
|
||||
'id': fake.BACKUP4_ID,
|
||||
'host': 'devstack',
|
||||
'project_id': fake.PROJECT_ID,
|
||||
'created_at': datetime.datetime(1, 3, 10, 1, 1, 1),
|
||||
},
|
||||
{
|
||||
'id': fake.BACKUP5_ID,
|
||||
'host': 'devstack',
|
||||
'project_id': fake.PROJECT_ID,
|
||||
'created_at': datetime.datetime(1, 5, 1, 1, 1, 1),
|
||||
},
|
||||
]
|
||||
|
||||
def test_volume_get_active_by_window(self):
|
||||
# Find all all volumes valid within a timeframe window.
|
||||
|
||||
@ -6069,6 +6110,38 @@ class GetActiveByWindowTestCase(BaseVolumeTestCase):
|
||||
self.assertEqual(snap4.id, snapshots[2].id)
|
||||
self.assertEqual(fake.VOLUME_ID, snapshots[2].volume_id)
|
||||
|
||||
def test_backup_get_active_by_window(self):
|
||||
# Find all backups valid within a timeframe window.
|
||||
db.volume_create(self.context, {'id': fake.VOLUME_ID})
|
||||
for i in range(5):
|
||||
self.db_back_attrs[i]['volume_id'] = fake.VOLUME_ID
|
||||
|
||||
# Not in window
|
||||
db.backup_create(self.ctx, self.db_back_attrs[0])
|
||||
|
||||
# In - deleted in window
|
||||
db.backup_create(self.ctx, self.db_back_attrs[1])
|
||||
|
||||
# In - deleted after window
|
||||
db.backup_create(self.ctx, self.db_back_attrs[2])
|
||||
|
||||
# In - created in window
|
||||
db.backup_create(self.ctx, self.db_back_attrs[3])
|
||||
|
||||
# Not of window
|
||||
db.backup_create(self.ctx, self.db_back_attrs[4])
|
||||
|
||||
backups = db.backup_get_active_by_window(
|
||||
self.context,
|
||||
datetime.datetime(1, 3, 1, 1, 1, 1),
|
||||
datetime.datetime(1, 4, 1, 1, 1, 1),
|
||||
project_id=fake.PROJECT_ID
|
||||
)
|
||||
self.assertEqual(3, len(backups))
|
||||
self.assertEqual(fake.BACKUP2_ID, backups[0].id)
|
||||
self.assertEqual(fake.BACKUP3_ID, backups[1].id)
|
||||
self.assertEqual(fake.BACKUP4_ID, backups[2].id)
|
||||
|
||||
|
||||
class DriverTestCase(test.TestCase):
|
||||
"""Base Test class for Drivers."""
|
||||
|
Loading…
x
Reference in New Issue
Block a user