From 11010ec9eb1de02a8c2dbea1257eca72e66829e2 Mon Sep 17 00:00:00 2001 From: Sheel Rana <ranasheel2000@gmail.com> Date: Fri, 6 May 2016 19:01:46 +0530 Subject: [PATCH] Support for cinder backup force delete Cinder backup force delete is supported from cinder server side but cinderclient support is not present. This patchset adds support for cinder backup force delete from cinderclient side. Closes-Bug:#1567243 Partially-Implements: blueprint snapshot-backup-force-delete Change-Id: I4ec38376d57ef6f74fefdd3bd2fea7a10bc51672 --- .../tests/unit/v2/test_volume_backups.py | 26 +++++++++++++++++++ cinderclient/v3/shell.py | 7 ++++- cinderclient/v3/volume_backups.py | 12 ++++++--- 3 files changed, 40 insertions(+), 5 deletions(-) diff --git a/cinderclient/tests/unit/v2/test_volume_backups.py b/cinderclient/tests/unit/v2/test_volume_backups.py index ac8be24eb..d493080a8 100644 --- a/cinderclient/tests/unit/v2/test_volume_backups.py +++ b/cinderclient/tests/unit/v2/test_volume_backups.py @@ -92,6 +92,32 @@ class VolumeBackupsTest(utils.TestCase): '/backups/76a17945-3c6f-435c-975b-b5685db10b62') self._assert_request_id(del_back) + def test_force_delete_with_True_force_param_value(self): + """Tests delete backup with force parameter set to True""" + b = cs.backups.list()[0] + del_back = b.delete(force=True) + expected_body = {'os-force_delete': None} + cs.assert_called('POST', + '/backups/76a17945-3c6f-435c-975b-b5685db10b62/action', + expected_body) + self._assert_request_id(del_back) + + def test_force_delete_with_false_force_param_vaule(self): + """To delete backup with force parameter set to False""" + b = cs.backups.list()[0] + del_back = b.delete(force=False) + cs.assert_called('DELETE', + '/backups/76a17945-3c6f-435c-975b-b5685db10b62') + self._assert_request_id(del_back) + del_back = cs.backups.delete('76a17945-3c6f-435c-975b-b5685db10b62') + cs.assert_called('DELETE', + '/backups/76a17945-3c6f-435c-975b-b5685db10b62') + self._assert_request_id(del_back) + del_back = cs.backups.delete(b) + cs.assert_called('DELETE', + '/backups/76a17945-3c6f-435c-975b-b5685db10b62') + self._assert_request_id(del_back) + def test_restore(self): backup_id = '76a17945-3c6f-435c-975b-b5685db10b62' info = cs.restores.restore(backup_id) diff --git a/cinderclient/v3/shell.py b/cinderclient/v3/shell.py index f28dedb0b..c035bcc0a 100644 --- a/cinderclient/v3/shell.py +++ b/cinderclient/v3/shell.py @@ -1458,6 +1458,11 @@ def do_backup_list(cs, args): utils.print_list(backups, columns, sortby_index=sortby_index) +@utils.arg('--force', + action="store_true", + help='Allows deleting backup of a volume ' + 'when its status is other than "available" or "error". ' + 'Default=False.') @utils.arg('backup', metavar='<backup>', nargs='+', help='Name or ID of backup(s) to delete.') @utils.service_type('volumev3') @@ -1466,7 +1471,7 @@ def do_backup_delete(cs, args): failure_count = 0 for backup in args.backup: try: - _find_backup(cs, backup).delete() + _find_backup(cs, backup).delete(args.force) print("Request to delete backup %s has been accepted." % (backup)) except Exception as e: failure_count += 1 diff --git a/cinderclient/v3/volume_backups.py b/cinderclient/v3/volume_backups.py index b264dec89..0941fb86b 100644 --- a/cinderclient/v3/volume_backups.py +++ b/cinderclient/v3/volume_backups.py @@ -26,9 +26,9 @@ class VolumeBackup(base.Resource): def __repr__(self): return "<VolumeBackup: %s>" % self.id - def delete(self): + def delete(self, force=False): """Delete this volume backup.""" - return self.manager.delete(self) + return self.manager.delete(self, force) def reset_state(self, state): return self.manager.reset_state(self, state) @@ -81,12 +81,16 @@ class VolumeBackupManager(base.ManagerWithFind): limit=limit, sort=sort) return self._list(url, resource_type, limit=limit) - def delete(self, backup): + def delete(self, backup, force=False): """Delete a volume backup. :param backup: The :class:`VolumeBackup` to delete. + :param force: Allow delete in state other than error or available. """ - return self._delete("/backups/%s" % base.getid(backup)) + if force: + return self._action('os-force_delete', backup) + else: + return self._delete("/backups/%s" % base.getid(backup)) def reset_state(self, backup, state): """Update the specified volume backup with the provided state."""