diff --git a/cinderclient/tests/v2/fakes.py b/cinderclient/tests/v2/fakes.py index 826babcef..f44814b0a 100644 --- a/cinderclient/tests/v2/fakes.py +++ b/cinderclient/tests/v2/fakes.py @@ -572,6 +572,27 @@ class FakeHTTPClient(base_client.HTTPClient): return (200, {}, {'restore': _stub_restore()}) + def get_backups_76a17945_3c6f_435c_975b_b5685db10b62_export_record(self, + **kw): + return (200, + {}, + {'backup-record': {'backup_service': 'fake-backup-service', + 'backup_url': 'fake-backup-url'}}) + + def get_backups_1234_export_record(self, **kw): + return (200, + {}, + {'backup-record': {'backup_service': 'fake-backup-service', + 'backup_url': 'fake-backup-url'}}) + + def post_backups_import_record(self, **kw): + base_uri = 'http://localhost:8776' + tenant_id = '0fa851f6668144cf9cd8c8419c1646c1' + backup1 = '76a17945-3c6f-435c-975b-b5685db10b62' + return (200, + {}, + {'backup': _stub_backup(backup1, base_uri, tenant_id)}) + # # QoSSpecs # diff --git a/cinderclient/tests/v2/test_shell.py b/cinderclient/tests/v2/test_shell.py index 3c1a01134..90ef8cf3b 100644 --- a/cinderclient/tests/v2/test_shell.py +++ b/cinderclient/tests/v2/test_shell.py @@ -113,6 +113,16 @@ class ShellTest(utils.TestCase): self.run_command('backup-restore 1234') self.assert_called('POST', '/backups/1234/restore') + def test_record_export(self): + self.run_command('backup-export 1234') + self.assert_called('GET', '/backups/1234/export_record') + + def test_record_import(self): + self.run_command('backup-import fake.driver URL_STRING') + expected = {'backup-record': {'backup_service': 'fake.driver', + 'backup_url': 'URL_STRING'}} + self.assert_called('POST', '/backups/import_record', expected) + def test_snapshot_list_filter_volume_id(self): self.run_command('snapshot-list --volume-id=1234') self.assert_called('GET', '/snapshots/detail?volume_id=1234') diff --git a/cinderclient/tests/v2/test_volume_backups.py b/cinderclient/tests/v2/test_volume_backups.py index 44b1c54e9..916938de1 100644 --- a/cinderclient/tests/v2/test_volume_backups.py +++ b/cinderclient/tests/v2/test_volume_backups.py @@ -51,3 +51,17 @@ class VolumeBackupsTest(utils.TestCase): backup_id = '76a17945-3c6f-435c-975b-b5685db10b62' cs.restores.restore(backup_id) cs.assert_called('POST', '/backups/%s/restore' % backup_id) + + def test_record_export(self): + backup_id = '76a17945-3c6f-435c-975b-b5685db10b62' + cs.backups.export_record(backup_id) + cs.assert_called('GET', + '/backups/%s/export_record' % backup_id) + + def test_record_import(self): + backup_service = 'fake-backup-service' + backup_url = 'fake-backup-url' + expected_body = {'backup-record': {'backup_service': backup_service, + 'backup_url': backup_url}} + cs.backups.import_record(backup_service, backup_url) + cs.assert_called('POST', '/backups/import_record', expected_body) diff --git a/cinderclient/v2/shell.py b/cinderclient/v2/shell.py index 2e48339cd..3ae4208b2 100644 --- a/cinderclient/v2/shell.py +++ b/cinderclient/v2/shell.py @@ -1005,6 +1005,28 @@ def do_backup_restore(cs, args): cs.restores.restore(args.backup, volume_id) +@utils.arg('backup', metavar='', + help='ID of the backup to export.') +@utils.service_type('volumev2') +def do_backup_export(cs, args): + """Export backup metadata record.""" + info = cs.backups.export_record(args.backup) + utils.print_dict(info) + + +@utils.arg('backup_service', metavar='', + help='Backup service to use for importing the backup.') +@utils.arg('backup_url', metavar='', + help='Backup URL for importing the backup metadata.') +@utils.service_type('volumev2') +def do_backup_import(cs, args): + """Import backup metadata record.""" + info = cs.backups.import_record(args.backup_service, args.backup_url) + info.pop('links', None) + + utils.print_dict(info) + + @utils.arg('volume', metavar='', help='Name or ID of the volume to transfer.') @utils.arg('--name', diff --git a/cinderclient/v2/volume_backups.py b/cinderclient/v2/volume_backups.py index 89056af64..c28972ee7 100644 --- a/cinderclient/v2/volume_backups.py +++ b/cinderclient/v2/volume_backups.py @@ -74,3 +74,26 @@ class VolumeBackupManager(base.ManagerWithFind): :param backup: The :class:`VolumeBackup` to delete. """ self._delete("/backups/%s" % base.getid(backup)) + + def export_record(self, backup_id): + """Export volume backup metadata record. + + :param backup_id: The ID of the backup to export. + :rtype: :class:`VolumeBackup` + """ + resp, body = \ + self.api.client.get("/backups/%s/export_record" % backup_id) + return body['backup-record'] + + def import_record(self, backup_service, backup_url): + """Export volume backup metadata record. + + :param backup_service: Backup service to use for importing the backup + :param backup_urlBackup URL for importing the backup metadata + :rtype: :class:`VolumeBackup` + """ + body = {'backup-record': {'backup_service': backup_service, + 'backup_url': backup_url}} + self.run_hooks('modify_body_for_update', body, 'backup-record') + resp, body = self.api.client.post("/backups/import_record", body=body) + return body['backup']