From 2255fc99da9752737dcaa96ae4507b646074afb2 Mon Sep 17 00:00:00 2001 From: j-griffith Date: Thu, 7 Sep 2017 23:51:37 +0000 Subject: [PATCH] Implement metadata for backup create/update We have a gap in the micro versions implemented in the cinderclient and the MAX version being reported by the client. This patch addresses the missing changes for micro version 3.43 which adds support for metadata for backup create and update. Change-Id: I14c7205784c53ec3ab0985a4460a88f59de171fb Partial-Bug: #1715759 --- cinderclient/tests/unit/v3/test_shell.py | 8 +++ cinderclient/v3/shell.py | 77 +++++++++++++++++++++++- cinderclient/v3/volume_backups.py | 32 +++++++++- 3 files changed, 115 insertions(+), 2 deletions(-) diff --git a/cinderclient/tests/unit/v3/test_shell.py b/cinderclient/tests/unit/v3/test_shell.py index a7be695d4..ccfb45b35 100644 --- a/cinderclient/tests/unit/v3/test_shell.py +++ b/cinderclient/tests/unit/v3/test_shell.py @@ -990,3 +990,11 @@ class ShellTest(utils.TestCase): self.assertEqual([mock.call(poll_period)] * 2, mock_time.sleep.call_args_list) self.assertEqual([mock.call(some_id)] * 2, poll_fn.call_args_list) + + def test_backup_with_metadata(self): + cmd = '--os-volume-api-version 3.43 ' + cmd += 'backup-create ' + cmd += '--metadata foo=bar ' + cmd += '1234' + self.run_command(cmd) + self.assert_called('POST', '/backups') diff --git a/cinderclient/v3/shell.py b/cinderclient/v3/shell.py index 97740e4c2..d81bb03c5 100644 --- a/cinderclient/v3/shell.py +++ b/cinderclient/v3/shell.py @@ -858,13 +858,19 @@ def do_upload_to_image(cs, args): args.disk_format)) -@api_versions.wraps('3.9') +@api_versions.wraps('3.9', '3.43') @utils.arg('backup', metavar='', help='Name or ID of backup to rename.') @utils.arg('--name', nargs='?', metavar='', help='New name for backup.') @utils.arg('--description', metavar='', help='Backup description. Default=None.') +@utils.arg('--metadata', + nargs='*', + metavar='', + default=None, + help='Metadata key and value pairs. Default=None.', + start_version='3.43') def do_backup_update(cs, args): """Renames a backup.""" kwargs = {} @@ -875,6 +881,10 @@ def do_backup_update(cs, args): if args.description is not None: kwargs['description'] = args.description + if cs.api_version >= api_versions.APIVersion("3.43"): + if args.metadata is not None: + kwargs['metadata'] = args.metadata + if not kwargs: msg = 'Must supply either name or description.' raise exceptions.ClientException(code=1, message=msg) @@ -2005,3 +2015,68 @@ def do_service_get_log(cs, args): args.prefix) columns = ('Binary', 'Host', 'Prefix', 'Level') utils.print_list(log_levels, columns) + +@api_versions.wraps('3.43') +@utils.arg('volume', metavar='', + help='Name or ID of volume to backup.') +@utils.arg('--container', metavar='', + default=None, + help='Backup container name. Default=None.') +@utils.arg('--display-name', + help=argparse.SUPPRESS) +@utils.arg('--name', metavar='', + default=None, + help='Backup name. Default=None.') +@utils.arg('--display-description', + help=argparse.SUPPRESS) +@utils.arg('--description', + metavar='', + default=None, + help='Backup description. Default=None.') +@utils.arg('--incremental', + action='store_true', + help='Incremental backup. Default=False.', + default=False) +@utils.arg('--force', + action='store_true', + help='Allows or disallows backup of a volume ' + 'when the volume is attached to an instance. ' + 'If set to True, backs up the volume whether ' + 'its status is "available" or "in-use". The backup ' + 'of an "in-use" volume means your data is crash ' + 'consistent. Default=False.', + default=False) +@utils.arg('--snapshot-id', + metavar='', + default=None, + help='ID of snapshot to backup. Default=None.') +@utils.arg('--metadata', + nargs='*', + metavar='', + default=None, + help='Metadata key and value pairs. Default=None.') +def do_backup_create(cs, args): + """Creates a volume backup.""" + if args.display_name is not None: + args.name = args.display_name + + if args.display_description is not None: + args.description = args.display_description + + volume = utils.find_volume(cs, args.volume) + backup = cs.backups.create(volume.id, + args.container, + args.name, + args.description, + args.incremental, + args.force, + args.snapshot_id, + args.metadata) + + info = {"volume_id": volume.id} + info.update(backup._info) + + if 'links' in info: + info.pop('links') + + utils.print_dict(info) diff --git a/cinderclient/v3/volume_backups.py b/cinderclient/v3/volume_backups.py index 4d0594803..0ac9e1b93 100644 --- a/cinderclient/v3/volume_backups.py +++ b/cinderclient/v3/volume_backups.py @@ -26,15 +26,45 @@ VolumeBackup = volume_backups.VolumeBackup class VolumeBackupManager(volume_backups.VolumeBackupManager): - @api_versions.wraps("3.9") + @api_versions.wraps("3.9", "3.43") def update(self, backup, **kwargs): """Update the name or description for a backup. :param backup: The :class:`Backup` to update. """ + # NOTE(jdg): Placing 3.43 in versions.wraps above for clarity, + # but it's irrelevant as this just uses the kwargs, should we + # remove that? if not kwargs: return body = {"backup": kwargs} return self._update("/backups/%s" % base.getid(backup), body) + + @api_versions.wraps("3.43") + def create(self, volume_id, container=None, + name=None, description=None, + incremental=False, force=False, + snapshot_id=None, + metadata=None): + """Creates a volume backup. + + :param volume_id: The ID of the volume to backup. + :param container: The name of the backup service container. + :param name: The name of the backup. + :param description: The description of the backup. + :param incremental: Incremental backup. + :param force: If True, allows an in-use volume to be backed up. + :param metadata: Key Value pairs + :rtype: :class:`VolumeBackup` + """ + body = {'backup': {'volume_id': volume_id, + 'container': container, + 'name': name, + 'description': description, + 'incremental': incremental, + 'force': force, + 'snapshot_id': snapshot_id, + 'metadata': metadata, }} + return self._create('/backups', body, 'backup')