diff --git a/openstackclient/tests/unit/volume/v3/test_volume.py b/openstackclient/tests/unit/volume/v3/test_volume.py index 3338ccff0b..703aa04fd3 100644 --- a/openstackclient/tests/unit/volume/v3/test_volume.py +++ b/openstackclient/tests/unit/volume/v3/test_volume.py @@ -1723,9 +1723,10 @@ class TestVolumeMigrate(volume_fakes.TestVolume): host="host@backend-name#pool", force_host_copy=False, lock_volume=False, + cluster=None, ) - def test_volume_migrate_with_option(self): + def test_volume_migrate_with_host(self): arglist = [ "--force-host-copy", "--lock-volume", @@ -1752,9 +1753,66 @@ class TestVolumeMigrate(volume_fakes.TestVolume): host="host@backend-name#pool", force_host_copy=True, lock_volume=True, + cluster=None, ) - def test_volume_migrate_without_host(self): + def test_volume_migrate_with_cluster(self): + self.set_volume_api_version('3.16') + arglist = [ + "--cluster", + "cluster@backend-name#pool", + self.volume.id, + ] + verifylist = [ + ( + "cluster", + "cluster@backend-name#pool", + ), + ("volume", self.volume.id), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + result = self.cmd.take_action(parsed_args) + self.assertIsNone(result) + + self.volume_sdk_client.find_volume.assert_called_with( + self.volume.id, ignore_missing=False + ) + self.volume_sdk_client.migrate_volume.assert_called_once_with( + self.volume.id, + host=None, + force_host_copy=False, + lock_volume=False, + cluster="cluster@backend-name#pool", + ) + + def test_volume_migrate_with_cluster_pre_v316(self): + self.set_volume_api_version('3.15') + arglist = [ + "--cluster", + "cluster@backend-name#pool", + self.volume.id, + ] + verifylist = [ + ( + "cluster", + "cluster@backend-name#pool", + ), + ("volume", self.volume.id), + ] + + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + self.assertRaises( + exceptions.CommandError, + self.cmd.take_action, + parsed_args, + ) + + self.volume_sdk_client.migrate_volume.assert_not_called() + + def test_volume_migrate_without_host_and_cluster(self): arglist = [ self.volume.id, ] @@ -1771,7 +1829,6 @@ class TestVolumeMigrate(volume_fakes.TestVolume): arglist, verifylist, ) - self.volume_sdk_client.find_volume.assert_not_called() self.volume_sdk_client.migrate_volume.assert_not_called() diff --git a/openstackclient/volume/v3/volume.py b/openstackclient/volume/v3/volume.py index 1c5b03e46d..a29b77b564 100644 --- a/openstackclient/volume/v3/volume.py +++ b/openstackclient/volume/v3/volume.py @@ -743,14 +743,22 @@ class MigrateVolume(command.Command): metavar="", help=_("Volume to migrate (name or ID)"), ) - parser.add_argument( + destination_group = parser.add_mutually_exclusive_group(required=True) + destination_group.add_argument( '--host', metavar="", - required=True, help=_( "Destination host (takes the form: host@backend-name#pool)" ), ) + destination_group.add_argument( + '--cluster', + metavar="", + help=_( + "Destination cluster to migrate the volume to " + "(requires --os-volume-api-version 3.16 or higher)" + ), + ) parser.add_argument( '--force-host-copy', action="store_true", @@ -768,7 +776,6 @@ class MigrateVolume(command.Command): "(possibly by another operation)" ), ) - # TODO(stephenfin): Add --cluster argument return parser def take_action(self, parsed_args): @@ -776,11 +783,22 @@ class MigrateVolume(command.Command): volume = volume_client.find_volume( parsed_args.volume, ignore_missing=False ) + + if parsed_args.cluster and not sdk_utils.supports_microversion( + volume_client, '3.16' + ): + msg = _( + "--os-volume-api-version 3.16 or greater is required to " + "support the volume migration with cluster" + ) + raise exceptions.CommandError(msg) + volume_client.migrate_volume( volume.id, host=parsed_args.host, force_host_copy=parsed_args.force_host_copy, lock_volume=parsed_args.lock_volume, + cluster=parsed_args.cluster, ) diff --git a/releasenotes/notes/add-cluster-option-to-volume-migration-9fe0cc84e9c80a4c.yaml b/releasenotes/notes/add-cluster-option-to-volume-migration-9fe0cc84e9c80a4c.yaml new file mode 100644 index 0000000000..5b9e878056 --- /dev/null +++ b/releasenotes/notes/add-cluster-option-to-volume-migration-9fe0cc84e9c80a4c.yaml @@ -0,0 +1,7 @@ +--- +features: + - | + The ``volume migration`` command now supports the ``--cluster`` + optional argument, allowing volumes to be migrated to a destination + cluster. This feature requires Cinder API microversion 3.16 or + higher and is mutually exclusive with the ``--host`` option. \ No newline at end of file