Add "--type" and "--retype-policy" options to "volume set" command
Add "--type" and "--retype-policy" options to "volume set" command in volume v2 (v2 only) to support changing the volume type for a volume Change-Id: I0153abdb967aee790586a57cef31930e32005c1b Implements: bp cinder-command-support
This commit is contained in:
		@@ -254,6 +254,8 @@ Set volume properties
 | 
			
		||||
        [--property <key=value> [...] ]
 | 
			
		||||
        [--image-property <key=value> [...] ]
 | 
			
		||||
        [--state <state>]
 | 
			
		||||
        [--type <volume-type>]
 | 
			
		||||
        [--retype-policy <retype-policy>]
 | 
			
		||||
        [--bootable | --non-bootable]
 | 
			
		||||
        [--read-only | --read-write]
 | 
			
		||||
        <volume>
 | 
			
		||||
@@ -274,6 +276,20 @@ Set volume properties
 | 
			
		||||
 | 
			
		||||
    Set a property on this volume (repeat option to set multiple properties)
 | 
			
		||||
 | 
			
		||||
.. option:: --type <volume-type>
 | 
			
		||||
 | 
			
		||||
    New volume type (name or ID)
 | 
			
		||||
 | 
			
		||||
    *Volume version 2 only*
 | 
			
		||||
 | 
			
		||||
.. option:: --retype-policy <retype-policy>
 | 
			
		||||
 | 
			
		||||
    Migration policy while re-typing volume
 | 
			
		||||
    ("never" or "on-demand", default is "never" )
 | 
			
		||||
    (available only when "--type" option is specified)
 | 
			
		||||
 | 
			
		||||
    *Volume version 2 only*
 | 
			
		||||
 | 
			
		||||
.. option:: --bootable
 | 
			
		||||
 | 
			
		||||
    Mark volume as bootable
 | 
			
		||||
 
 | 
			
		||||
@@ -46,6 +46,9 @@ class TestVolume(volume_fakes.TestVolume):
 | 
			
		||||
        self.snapshots_mock = self.app.client_manager.volume.volume_snapshots
 | 
			
		||||
        self.snapshots_mock.reset_mock()
 | 
			
		||||
 | 
			
		||||
        self.types_mock = self.app.client_manager.volume.volume_types
 | 
			
		||||
        self.types_mock.reset_mock()
 | 
			
		||||
 | 
			
		||||
        self.consistencygroups_mock = (
 | 
			
		||||
            self.app.client_manager.volume.consistencygroups)
 | 
			
		||||
        self.consistencygroups_mock.reset_mock()
 | 
			
		||||
@@ -1088,11 +1091,14 @@ class TestVolumeMigrate(TestVolume):
 | 
			
		||||
 | 
			
		||||
class TestVolumeSet(TestVolume):
 | 
			
		||||
 | 
			
		||||
    volume_type = volume_fakes.FakeType.create_one_type()
 | 
			
		||||
 | 
			
		||||
    def setUp(self):
 | 
			
		||||
        super(TestVolumeSet, self).setUp()
 | 
			
		||||
 | 
			
		||||
        self.new_volume = volume_fakes.FakeVolume.create_one_volume()
 | 
			
		||||
        self.volumes_mock.get.return_value = self.new_volume
 | 
			
		||||
        self.types_mock.get.return_value = self.volume_type
 | 
			
		||||
 | 
			
		||||
        # Get the command object to test
 | 
			
		||||
        self.cmd = volume.SetVolume(self.app, None)
 | 
			
		||||
@@ -1221,6 +1227,66 @@ class TestVolumeSet(TestVolume):
 | 
			
		||||
            False)
 | 
			
		||||
        self.assertIsNone(result)
 | 
			
		||||
 | 
			
		||||
    def test_volume_set_type(self):
 | 
			
		||||
        arglist = [
 | 
			
		||||
            '--type', self.volume_type.id,
 | 
			
		||||
            self.new_volume.id
 | 
			
		||||
        ]
 | 
			
		||||
        verifylist = [
 | 
			
		||||
            ('retype_policy', None),
 | 
			
		||||
            ('type', self.volume_type.id),
 | 
			
		||||
            ('volume', self.new_volume.id)
 | 
			
		||||
        ]
 | 
			
		||||
 | 
			
		||||
        parsed_args = self.check_parser(self.cmd, arglist, verifylist)
 | 
			
		||||
 | 
			
		||||
        result = self.cmd.take_action(parsed_args)
 | 
			
		||||
        self.volumes_mock.retype.assert_called_once_with(
 | 
			
		||||
            self.new_volume.id,
 | 
			
		||||
            self.volume_type.id,
 | 
			
		||||
            'never')
 | 
			
		||||
        self.assertIsNone(result)
 | 
			
		||||
 | 
			
		||||
    def test_volume_set_type_with_policy(self):
 | 
			
		||||
        arglist = [
 | 
			
		||||
            '--retype-policy', 'on-demand',
 | 
			
		||||
            '--type', self.volume_type.id,
 | 
			
		||||
            self.new_volume.id
 | 
			
		||||
        ]
 | 
			
		||||
        verifylist = [
 | 
			
		||||
            ('retype_policy', 'on-demand'),
 | 
			
		||||
            ('type', self.volume_type.id),
 | 
			
		||||
            ('volume', self.new_volume.id)
 | 
			
		||||
        ]
 | 
			
		||||
 | 
			
		||||
        parsed_args = self.check_parser(self.cmd, arglist, verifylist)
 | 
			
		||||
 | 
			
		||||
        result = self.cmd.take_action(parsed_args)
 | 
			
		||||
        self.volumes_mock.retype.assert_called_once_with(
 | 
			
		||||
            self.new_volume.id,
 | 
			
		||||
            self.volume_type.id,
 | 
			
		||||
            'on-demand')
 | 
			
		||||
        self.assertIsNone(result)
 | 
			
		||||
 | 
			
		||||
    @mock.patch.object(volume.LOG, 'warning')
 | 
			
		||||
    def test_volume_set_with_only_retype_policy(self, mock_warning):
 | 
			
		||||
        arglist = [
 | 
			
		||||
            '--retype-policy', 'on-demand',
 | 
			
		||||
            self.new_volume.id
 | 
			
		||||
        ]
 | 
			
		||||
        verifylist = [
 | 
			
		||||
            ('retype_policy', 'on-demand'),
 | 
			
		||||
            ('volume', self.new_volume.id)
 | 
			
		||||
        ]
 | 
			
		||||
 | 
			
		||||
        parsed_args = self.check_parser(self.cmd, arglist, verifylist)
 | 
			
		||||
 | 
			
		||||
        result = self.cmd.take_action(parsed_args)
 | 
			
		||||
        self.volumes_mock.retype.assert_not_called()
 | 
			
		||||
        mock_warning.assert_called_with("'--retype-policy' option will "
 | 
			
		||||
                                        "not work without '--type' option")
 | 
			
		||||
        self.assertIsNone(result)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TestVolumeShow(TestVolume):
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -509,6 +509,19 @@ class SetVolume(command.Command):
 | 
			
		||||
                   'in the database with no regard to actual status, '
 | 
			
		||||
                   'exercise caution when using)'),
 | 
			
		||||
        )
 | 
			
		||||
        parser.add_argument(
 | 
			
		||||
            '--type',
 | 
			
		||||
            metavar='<volume-type>',
 | 
			
		||||
            help=_('New volume type (name or ID)'),
 | 
			
		||||
        )
 | 
			
		||||
        parser.add_argument(
 | 
			
		||||
            '--retype-policy',
 | 
			
		||||
            metavar='<retype-policy>',
 | 
			
		||||
            choices=['never', 'on-demand'],
 | 
			
		||||
            help=_('Migration policy while re-typing volume '
 | 
			
		||||
                   '("never" or "on-demand", default is "never" ) '
 | 
			
		||||
                   '(available only when "--type" option is specified)'),
 | 
			
		||||
        )
 | 
			
		||||
        bootable_group = parser.add_mutually_exclusive_group()
 | 
			
		||||
        bootable_group.add_argument(
 | 
			
		||||
            "--bootable",
 | 
			
		||||
@@ -590,6 +603,28 @@ class SetVolume(command.Command):
 | 
			
		||||
                LOG.error(_("Failed to set volume read-only access "
 | 
			
		||||
                            "mode flag: %s"), e)
 | 
			
		||||
                result += 1
 | 
			
		||||
        if parsed_args.type:
 | 
			
		||||
            # get the migration policy
 | 
			
		||||
            migration_policy = 'never'
 | 
			
		||||
            if parsed_args.retype_policy:
 | 
			
		||||
                migration_policy = parsed_args.retype_policy
 | 
			
		||||
            try:
 | 
			
		||||
                # find the volume type
 | 
			
		||||
                volume_type = utils.find_resource(
 | 
			
		||||
                    volume_client.volume_types,
 | 
			
		||||
                    parsed_args.type)
 | 
			
		||||
                # reset to the new volume type
 | 
			
		||||
                volume_client.volumes.retype(
 | 
			
		||||
                    volume.id,
 | 
			
		||||
                    volume_type.id,
 | 
			
		||||
                    migration_policy)
 | 
			
		||||
            except Exception as e:
 | 
			
		||||
                LOG.error(_("Failed to set volume type: %s"), e)
 | 
			
		||||
                result += 1
 | 
			
		||||
        elif parsed_args.retype_policy:
 | 
			
		||||
            # If the "--retype-policy" is specified without "--type"
 | 
			
		||||
            LOG.warning(_("'--retype-policy' option will not work "
 | 
			
		||||
                          "without '--type' option"))
 | 
			
		||||
 | 
			
		||||
        kwargs = {}
 | 
			
		||||
        if parsed_args.name:
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,5 @@
 | 
			
		||||
---
 | 
			
		||||
features:
 | 
			
		||||
  - |
 | 
			
		||||
    Add ``--type`` and ``--retype-policy`` options to ``volume set`` command.
 | 
			
		||||
    [Blueprint `cinder-command-support <https://blueprints.launchpad.net/python-openstackclient/+spec/cinder-command-support>`_]
 | 
			
		||||
		Reference in New Issue
	
	Block a user