diff options
Diffstat (limited to 'cinderclient')
-rw-r--r-- | cinderclient/tests/unit/v2/fakes.py | 8 | ||||
-rw-r--r-- | cinderclient/tests/unit/v2/test_shell.py | 17 | ||||
-rw-r--r-- | cinderclient/v2/shell.py | 54 | ||||
-rw-r--r-- | cinderclient/v2/volumes.py | 56 |
4 files changed, 135 insertions, 0 deletions
diff --git a/cinderclient/tests/unit/v2/fakes.py b/cinderclient/tests/unit/v2/fakes.py index f641ee7..b0c78b9 100644 --- a/cinderclient/tests/unit/v2/fakes.py +++ b/cinderclient/tests/unit/v2/fakes.py @@ -437,6 +437,14 @@ class FakeHTTPClient(base_client.HTTPClient): elif action == 'os-migrate_volume': assert 'host' in body[action] assert 'force_host_copy' in body[action] + elif action == 'os-enable_replication': + assert body[action] is None + elif action == 'os-disable_replication': + assert body[action] is None + elif action == 'os-list_replication_targets': + assert body[action] is None + elif action == 'os-failover_replication': + assert 'secondary' in body[action] elif action == 'os-update_readonly_flag': assert list(body[action]) == ['readonly'] elif action == 'os-retype': diff --git a/cinderclient/tests/unit/v2/test_shell.py b/cinderclient/tests/unit/v2/test_shell.py index 42c3dc7..1c140cb 100644 --- a/cinderclient/tests/unit/v2/test_shell.py +++ b/cinderclient/tests/unit/v2/test_shell.py @@ -794,6 +794,23 @@ class ShellTest(utils.TestCase): self.assert_called('POST', '/volumes/1234/action', body=expected) + def test_replication_enable(self): + self.run_command('replication-enable 1234') + self.assert_called('POST', '/volumes/1234/action') + + def test_replication_disable(self): + self.run_command('replication-disable 1234') + self.assert_called('POST', '/volumes/1234/action') + + def test_replication_list_targets(self): + self.run_command('replication-list-targets 1234') + self.assert_called('POST', '/volumes/1234/action') + + def test_replication_failover(self): + self.run_command('replication-failover 1234 target') + expected = {'os-failover_replication': {'secondary': 'target'}} + self.assert_called('POST', '/volumes/1234/action', body=expected) + def test_snapshot_metadata_set(self): self.run_command('snapshot-metadata 1234 set key1=val1 key2=val2') self.assert_called('POST', '/snapshots/1234/metadata', diff --git a/cinderclient/v2/shell.py b/cinderclient/v2/shell.py index c9da264..eb489a9 100644 --- a/cinderclient/v2/shell.py +++ b/cinderclient/v2/shell.py @@ -1246,6 +1246,60 @@ def do_migrate(cs, args): six.text_type(e))) +@utils.arg('volume', + metavar='<volume>', + help='ID of volume to enable replication.') +@utils.service_type('volumev2') +def do_replication_enable(cs, args): + """Enables volume replication on a given volume.""" + volume = utils.find_volume(cs, args.volume) + volume.replication_enable(args.volume) + + +@utils.arg('volume', + metavar='<volume>', + help='ID of volume to disable replication.') +@utils.service_type('volumev2') +def do_replication_disable(cs, args): + """Disables volume replication on a given volume.""" + volume = utils.find_volume(cs, args.volume) + volume.replication_disable(args.volume) + + +@utils.arg('volume', + metavar='<volume>', + help='ID of volume to list available replication targets.') +@utils.service_type('volumev2') +def do_replication_list_targets(cs, args): + """List replication targets available for a volume.""" + volume = utils.find_volume(cs, args.volume) + resp, body = volume.replication_list_targets(args.volume) + if body: + targets = body['targets'] + columns = ['target_device_id'] + if targets: + utils.print_list(targets, columns) + else: + print("There are no replication targets found for volume %s." % + args.volume) + else: + print("There is no replication information for volume %s." % + args.volume) + + +@utils.arg('volume', + metavar='<volume>', + help='ID of volume to failover.') +@utils.arg('secondary', + metavar='<secondary>', + help='A unqiue identifier that represents a failover target.') +@utils.service_type('volumev2') +def do_replication_failover(cs, args): + """Failover a volume to a secondary target""" + volume = utils.find_volume(cs, args.volume) + volume.replication_failover(args.volume, args.secondary) + + @utils.arg('volume', metavar='<volume>', help='Name or ID of volume for which to modify type.') @utils.arg('new_type', metavar='<volume-type>', help='New volume type.') diff --git a/cinderclient/v2/volumes.py b/cinderclient/v2/volumes.py index e700649..19bec81 100644 --- a/cinderclient/v2/volumes.py +++ b/cinderclient/v2/volumes.py @@ -144,6 +144,22 @@ class Volume(base.Resource): """Migrate the volume to a new host.""" self.manager.migrate_volume(self, host, force_host_copy, lock_volume) + def replication_enable(self, volume): + """Enables volume replication on a given volume.""" + return self.manager.replication_enable(volume) + + def replication_disable(self, volume): + """Disables volume replication on a given volume.""" + return self.manager.replication_disable(volume) + + def replication_list_targets(self, volume): + """List replication targets available for a volume.""" + return self.manager.replication_list_targets(volume) + + def replication_failover(self, volume, secondary): + """Failover a volume to a secondary target.""" + return self.manager.replication_failover(volume, secondary) + def retype(self, volume_type, policy): """Change a volume's type.""" self.manager.retype(self, volume_type, policy) @@ -512,6 +528,46 @@ class VolumeManager(base.ManagerWithFind): old_volume, {'new_volume': new_volume_id, 'error': error})[1] + def replication_enable(self, volume_id): + """ + Enables volume replication on a given volume. + + :param volume_id: The id of the volume to query + """ + return self._action('os-enable_replication', + volume_id) + + def replication_disable(self, volume_id): + """ + Disables volume replication on a given volume. + + :param volume_id: The id of the volume to query + """ + return self._action('os-disable_replication', + volume_id) + + def replication_list_targets(self, volume_id): + """ + List replication targets available for a volume. + + :param volume_id: The id of the volume to query + :return: a list of available replication targets + """ + return self._action('os-list_replication_targets', + volume_id) + + def replication_failover(self, volume_id, secondary): + """ + Failover a volume to a secondary target. + + :param volume_id: The id of the volume to query + :param secondary: A unqiue identifier that represents a failover + target + """ + return self._action('os-failover_replication', + volume_id, + {"secondary": secondary}) + def update_all_metadata(self, volume, metadata): """Update all metadata of a volume. |