Add support for volume API v1 QoS commands
This commit adds the following commands: volume qos associate volume qos create volume qos delete volume qos disassociate volume qos list volume qos set volume qos show volume qos unset Change-Id: I72ea1b9a4d0bd0e35eda03071ea438b75439fce9 Partial-Bug: #1467967
This commit is contained in:
		| @@ -79,6 +79,42 @@ IMAGE = { | |||||||
|     'name': image_name, |     'name': image_name, | ||||||
| } | } | ||||||
|  |  | ||||||
|  | type_id = "5520dc9e-6f9b-4378-a719-729911c0f407" | ||||||
|  | type_name = "fake-lvmdriver-1" | ||||||
|  |  | ||||||
|  | TYPE = { | ||||||
|  |     'id': type_id, | ||||||
|  |     'name': type_name | ||||||
|  | } | ||||||
|  |  | ||||||
|  | qos_id = '6f2be1de-997b-4230-b76c-a3633b59e8fb' | ||||||
|  | qos_consumer = 'front-end' | ||||||
|  | qos_default_consumer = 'both' | ||||||
|  | qos_name = "fake-qos-specs" | ||||||
|  | qos_specs = { | ||||||
|  |     'foo': 'bar', | ||||||
|  |     'iops': '9001' | ||||||
|  | } | ||||||
|  |  | ||||||
|  | QOS = { | ||||||
|  |     'id': qos_id, | ||||||
|  |     'consumer': qos_consumer, | ||||||
|  |     'name': qos_name | ||||||
|  | } | ||||||
|  |  | ||||||
|  | QOS_DEFAULT_CONSUMER = { | ||||||
|  |     'id': qos_id, | ||||||
|  |     'consumer': qos_default_consumer, | ||||||
|  |     'name': qos_name | ||||||
|  | } | ||||||
|  |  | ||||||
|  | QOS_WITH_SPECS = { | ||||||
|  |     'id': qos_id, | ||||||
|  |     'consumer': qos_consumer, | ||||||
|  |     'name': qos_name, | ||||||
|  |     'specs': qos_specs | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
| class FakeImagev1Client(object): | class FakeImagev1Client(object): | ||||||
|     def __init__(self, **kwargs): |     def __init__(self, **kwargs): | ||||||
| @@ -93,6 +129,10 @@ class FakeVolumev1Client(object): | |||||||
|         self.services.resource_class = fakes.FakeResource(None, {}) |         self.services.resource_class = fakes.FakeResource(None, {}) | ||||||
|         self.extensions = mock.Mock() |         self.extensions = mock.Mock() | ||||||
|         self.extensions.resource_class = fakes.FakeResource(None, {}) |         self.extensions.resource_class = fakes.FakeResource(None, {}) | ||||||
|  |         self.qos_specs = mock.Mock() | ||||||
|  |         self.qos_specs.resource_class = fakes.FakeResource(None, {}) | ||||||
|  |         self.volume_types = mock.Mock() | ||||||
|  |         self.volume_types.resource_class = fakes.FakeResource(None, {}) | ||||||
|         self.auth_token = kwargs['token'] |         self.auth_token = kwargs['token'] | ||||||
|         self.management_url = kwargs['endpoint'] |         self.management_url = kwargs['endpoint'] | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										348
									
								
								openstackclient/tests/volume/v1/test_qos_specs.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										348
									
								
								openstackclient/tests/volume/v1/test_qos_specs.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,348 @@ | |||||||
|  | #   Copyright 2015 iWeb Technologies Inc. | ||||||
|  | # | ||||||
|  | #   Licensed under the Apache License, Version 2.0 (the "License"); you may | ||||||
|  | #   not use this file except in compliance with the License. You may obtain | ||||||
|  | #   a copy of the License at | ||||||
|  | # | ||||||
|  | #        http://www.apache.org/licenses/LICENSE-2.0 | ||||||
|  | # | ||||||
|  | #   Unless required by applicable law or agreed to in writing, software | ||||||
|  | #   distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||||||
|  | #   WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||||||
|  | #   License for the specific language governing permissions and limitations | ||||||
|  | #   under the License. | ||||||
|  | # | ||||||
|  |  | ||||||
|  | import copy | ||||||
|  |  | ||||||
|  | from openstackclient.tests import fakes | ||||||
|  | from openstackclient.tests.volume.v1 import fakes as volume_fakes | ||||||
|  | from openstackclient.volume.v1 import qos_specs | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class TestQos(volume_fakes.TestVolumev1): | ||||||
|  |  | ||||||
|  |     def setUp(self): | ||||||
|  |         super(TestQos, self).setUp() | ||||||
|  |  | ||||||
|  |         self.qos_mock = self.app.client_manager.volume.qos_specs | ||||||
|  |         self.qos_mock.reset_mock() | ||||||
|  |  | ||||||
|  |         self.types_mock = self.app.client_manager.volume.volume_types | ||||||
|  |         self.types_mock.reset_mock() | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class TestQosCreate(TestQos): | ||||||
|  |     def setUp(self): | ||||||
|  |         super(TestQosCreate, self).setUp() | ||||||
|  |  | ||||||
|  |         # Get the command object to test | ||||||
|  |         self.cmd = qos_specs.CreateQos(self.app, None) | ||||||
|  |  | ||||||
|  |     def test_qos_create_without_properties(self): | ||||||
|  |         self.qos_mock.create.return_value = fakes.FakeResource( | ||||||
|  |             None, | ||||||
|  |             copy.deepcopy(volume_fakes.QOS_DEFAULT_CONSUMER), | ||||||
|  |             loaded=True | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |         arglist = [ | ||||||
|  |             volume_fakes.qos_name, | ||||||
|  |         ] | ||||||
|  |         verifylist = [ | ||||||
|  |             ('name', volume_fakes.qos_name), | ||||||
|  |         ] | ||||||
|  |         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||||
|  |  | ||||||
|  |         columns, data = self.cmd.take_action(parsed_args) | ||||||
|  |  | ||||||
|  |         self.qos_mock.create.assert_called_with( | ||||||
|  |             volume_fakes.qos_name, | ||||||
|  |             {'consumer': volume_fakes.qos_default_consumer} | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |         collist = ( | ||||||
|  |             'consumer', | ||||||
|  |             'id', | ||||||
|  |             'name' | ||||||
|  |         ) | ||||||
|  |         self.assertEqual(collist, columns) | ||||||
|  |         datalist = ( | ||||||
|  |             volume_fakes.qos_default_consumer, | ||||||
|  |             volume_fakes.qos_id, | ||||||
|  |             volume_fakes.qos_name | ||||||
|  |         ) | ||||||
|  |         self.assertEqual(datalist, data) | ||||||
|  |  | ||||||
|  |     def test_qos_create_with_consumer(self): | ||||||
|  |         self.qos_mock.create.return_value = fakes.FakeResource( | ||||||
|  |             None, | ||||||
|  |             copy.deepcopy(volume_fakes.QOS), | ||||||
|  |             loaded=True | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |         arglist = [ | ||||||
|  |             volume_fakes.qos_name, | ||||||
|  |             '--consumer', volume_fakes.qos_consumer | ||||||
|  |         ] | ||||||
|  |         verifylist = [ | ||||||
|  |             ('name', volume_fakes.qos_name), | ||||||
|  |             ('consumer', volume_fakes.qos_consumer) | ||||||
|  |         ] | ||||||
|  |         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||||
|  |  | ||||||
|  |         columns, data = self.cmd.take_action(parsed_args) | ||||||
|  |  | ||||||
|  |         self.qos_mock.create.assert_called_with( | ||||||
|  |             volume_fakes.qos_name, | ||||||
|  |             {'consumer': volume_fakes.qos_consumer} | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |         collist = ( | ||||||
|  |             'consumer', | ||||||
|  |             'id', | ||||||
|  |             'name' | ||||||
|  |         ) | ||||||
|  |         self.assertEqual(collist, columns) | ||||||
|  |         datalist = ( | ||||||
|  |             volume_fakes.qos_consumer, | ||||||
|  |             volume_fakes.qos_id, | ||||||
|  |             volume_fakes.qos_name | ||||||
|  |         ) | ||||||
|  |         self.assertEqual(datalist, data) | ||||||
|  |  | ||||||
|  |     def test_qos_create_with_properties(self): | ||||||
|  |         self.qos_mock.create.return_value = fakes.FakeResource( | ||||||
|  |             None, | ||||||
|  |             copy.deepcopy(volume_fakes.QOS_WITH_SPECS), | ||||||
|  |             loaded=True | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |         arglist = [ | ||||||
|  |             volume_fakes.qos_name, | ||||||
|  |             '--consumer', volume_fakes.qos_consumer, | ||||||
|  |             '--property', 'foo=bar', | ||||||
|  |             '--property', 'iops=9001' | ||||||
|  |         ] | ||||||
|  |         verifylist = [ | ||||||
|  |             ('name', volume_fakes.qos_name), | ||||||
|  |             ('consumer', volume_fakes.qos_consumer), | ||||||
|  |             ('property', volume_fakes.qos_specs) | ||||||
|  |         ] | ||||||
|  |         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||||
|  |  | ||||||
|  |         columns, data = self.cmd.take_action(parsed_args) | ||||||
|  |  | ||||||
|  |         specs = volume_fakes.qos_specs.copy() | ||||||
|  |         specs.update({'consumer': volume_fakes.qos_consumer}) | ||||||
|  |         self.qos_mock.create.assert_called_with( | ||||||
|  |             volume_fakes.qos_name, | ||||||
|  |             specs | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |         collist = ( | ||||||
|  |             'consumer', | ||||||
|  |             'id', | ||||||
|  |             'name', | ||||||
|  |             'specs', | ||||||
|  |         ) | ||||||
|  |         self.assertEqual(collist, columns) | ||||||
|  |         datalist = ( | ||||||
|  |             volume_fakes.qos_consumer, | ||||||
|  |             volume_fakes.qos_id, | ||||||
|  |             volume_fakes.qos_name, | ||||||
|  |             volume_fakes.qos_specs, | ||||||
|  |         ) | ||||||
|  |         self.assertEqual(datalist, data) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class TestQosDelete(TestQos): | ||||||
|  |     def setUp(self): | ||||||
|  |         super(TestQosDelete, self).setUp() | ||||||
|  |  | ||||||
|  |         self.qos_mock.get.return_value = fakes.FakeResource( | ||||||
|  |             None, | ||||||
|  |             copy.deepcopy(volume_fakes.QOS), | ||||||
|  |             loaded=True, | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |         # Get the command object to test | ||||||
|  |         self.cmd = qos_specs.DeleteQos(self.app, None) | ||||||
|  |  | ||||||
|  |     def test_qos_delete_with_id(self): | ||||||
|  |         arglist = [ | ||||||
|  |             volume_fakes.qos_id | ||||||
|  |         ] | ||||||
|  |         verifylist = [ | ||||||
|  |             ('qos_specs', volume_fakes.qos_id) | ||||||
|  |         ] | ||||||
|  |  | ||||||
|  |         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||||
|  |  | ||||||
|  |         self.cmd.take_action(parsed_args) | ||||||
|  |         self.qos_mock.delete.assert_called_with(volume_fakes.qos_id) | ||||||
|  |  | ||||||
|  |     def test_qos_delete_with_name(self): | ||||||
|  |         arglist = [ | ||||||
|  |             volume_fakes.qos_name | ||||||
|  |         ] | ||||||
|  |         verifylist = [ | ||||||
|  |             ('qos_specs', volume_fakes.qos_name) | ||||||
|  |         ] | ||||||
|  |  | ||||||
|  |         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||||
|  |  | ||||||
|  |         self.cmd.take_action(parsed_args) | ||||||
|  |         self.qos_mock.delete.assert_called_with(volume_fakes.qos_id) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class TestQosSet(TestQos): | ||||||
|  |     def setUp(self): | ||||||
|  |         super(TestQosSet, self).setUp() | ||||||
|  |  | ||||||
|  |         # Get the command object to test | ||||||
|  |         self.cmd = qos_specs.SetQos(self.app, None) | ||||||
|  |  | ||||||
|  |     def test_qos_set_with_properties_with_id(self): | ||||||
|  |         self.qos_mock.get.return_value = fakes.FakeResource( | ||||||
|  |             None, | ||||||
|  |             copy.deepcopy(volume_fakes.QOS_WITH_SPECS), | ||||||
|  |             loaded=True | ||||||
|  |         ) | ||||||
|  |         arglist = [ | ||||||
|  |             volume_fakes.qos_id, | ||||||
|  |             '--property', 'foo=bar', | ||||||
|  |             '--property', 'iops=9001' | ||||||
|  |         ] | ||||||
|  |         verifylist = [ | ||||||
|  |             ('qos_specs', volume_fakes.qos_id), | ||||||
|  |             ('property', volume_fakes.qos_specs) | ||||||
|  |         ] | ||||||
|  |         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||||
|  |  | ||||||
|  |         self.cmd.take_action(parsed_args) | ||||||
|  |         self.qos_mock.set_keys.assert_called_with( | ||||||
|  |             volume_fakes.qos_id, | ||||||
|  |             volume_fakes.qos_specs | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class TestQosUnset(TestQos): | ||||||
|  |     def setUp(self): | ||||||
|  |         super(TestQosUnset, self).setUp() | ||||||
|  |  | ||||||
|  |         # Get the command object to test | ||||||
|  |         self.cmd = qos_specs.UnsetQos(self.app, None) | ||||||
|  |  | ||||||
|  |     def test_qos_unset_with_properties(self): | ||||||
|  |         self.qos_mock.get.return_value = fakes.FakeResource( | ||||||
|  |             None, | ||||||
|  |             copy.deepcopy(volume_fakes.QOS), | ||||||
|  |             loaded=True | ||||||
|  |         ) | ||||||
|  |         arglist = [ | ||||||
|  |             volume_fakes.qos_id, | ||||||
|  |             '--property', 'iops', | ||||||
|  |             '--property', 'foo' | ||||||
|  |         ] | ||||||
|  |  | ||||||
|  |         verifylist = [ | ||||||
|  |             ('qos_specs', volume_fakes.qos_id), | ||||||
|  |             ('property', ['iops', 'foo']) | ||||||
|  |         ] | ||||||
|  |         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||||
|  |  | ||||||
|  |         self.cmd.take_action(parsed_args) | ||||||
|  |         self.qos_mock.unset_keys.assert_called_with( | ||||||
|  |             volume_fakes.qos_id, | ||||||
|  |             ['iops', 'foo'] | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class TestQosAssociate(TestQos): | ||||||
|  |     def setUp(self): | ||||||
|  |         super(TestQosAssociate, self).setUp() | ||||||
|  |  | ||||||
|  |         # Get the command object to test | ||||||
|  |         self.cmd = qos_specs.AssociateQos(self.app, None) | ||||||
|  |  | ||||||
|  |     def test_qos_associate(self): | ||||||
|  |         self.qos_mock.get.return_value = fakes.FakeResource( | ||||||
|  |             None, | ||||||
|  |             copy.deepcopy(volume_fakes.QOS), | ||||||
|  |             loaded=True | ||||||
|  |         ) | ||||||
|  |         self.types_mock.get.return_value = fakes.FakeResource( | ||||||
|  |             None, | ||||||
|  |             copy.deepcopy(volume_fakes.TYPE), | ||||||
|  |             loaded=True | ||||||
|  |         ) | ||||||
|  |         arglist = [ | ||||||
|  |             volume_fakes.qos_id, | ||||||
|  |             volume_fakes.type_id | ||||||
|  |         ] | ||||||
|  |         verifylist = [ | ||||||
|  |             ('qos_specs', volume_fakes.qos_id), | ||||||
|  |             ('volume_type', volume_fakes.type_id) | ||||||
|  |         ] | ||||||
|  |         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||||
|  |  | ||||||
|  |         self.cmd.take_action(parsed_args) | ||||||
|  |         self.qos_mock.associate.assert_called_with( | ||||||
|  |             volume_fakes.qos_id, | ||||||
|  |             volume_fakes.type_id | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class TestQosDisassociate(TestQos): | ||||||
|  |     def setUp(self): | ||||||
|  |         super(TestQosDisassociate, self).setUp() | ||||||
|  |  | ||||||
|  |         # Get the command object to test | ||||||
|  |         self.cmd = qos_specs.DisassociateQos(self.app, None) | ||||||
|  |  | ||||||
|  |     def test_qos_disassociate_with_volume_type(self): | ||||||
|  |         self.qos_mock.get.return_value = fakes.FakeResource( | ||||||
|  |             None, | ||||||
|  |             copy.deepcopy(volume_fakes.QOS), | ||||||
|  |             loaded=True | ||||||
|  |         ) | ||||||
|  |         self.types_mock.get.return_value = fakes.FakeResource( | ||||||
|  |             None, | ||||||
|  |             copy.deepcopy(volume_fakes.TYPE), | ||||||
|  |             loaded=True | ||||||
|  |         ) | ||||||
|  |         arglist = [ | ||||||
|  |             volume_fakes.qos_id, | ||||||
|  |             '--volume-type', volume_fakes.type_id | ||||||
|  |         ] | ||||||
|  |         verifylist = [ | ||||||
|  |             ('qos_specs', volume_fakes.qos_id), | ||||||
|  |             ('volume_type', volume_fakes.type_id) | ||||||
|  |         ] | ||||||
|  |         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||||
|  |  | ||||||
|  |         self.cmd.take_action(parsed_args) | ||||||
|  |         self.qos_mock.disassociate.assert_called_with( | ||||||
|  |             volume_fakes.qos_id, | ||||||
|  |             volume_fakes.type_id | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |     def test_qos_disassociate_with_all_volume_types(self): | ||||||
|  |         self.qos_mock.get.return_value = fakes.FakeResource( | ||||||
|  |             None, | ||||||
|  |             copy.deepcopy(volume_fakes.QOS), | ||||||
|  |             loaded=True | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |         arglist = [ | ||||||
|  |             volume_fakes.qos_id, | ||||||
|  |             '--all' | ||||||
|  |         ] | ||||||
|  |         verifylist = [ | ||||||
|  |             ('qos_specs', volume_fakes.qos_id) | ||||||
|  |         ] | ||||||
|  |         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||||
|  |  | ||||||
|  |         self.cmd.take_action(parsed_args) | ||||||
|  |         self.qos_mock.disassociate_all.assert_called_with(volume_fakes.qos_id) | ||||||
							
								
								
									
										307
									
								
								openstackclient/volume/v1/qos_specs.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										307
									
								
								openstackclient/volume/v1/qos_specs.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,307 @@ | |||||||
|  | #   Copyright 2015 iWeb Technologies Inc. | ||||||
|  | # | ||||||
|  | #   Licensed under the Apache License, Version 2.0 (the "License"); you may | ||||||
|  | #   not use this file except in compliance with the License. You may obtain | ||||||
|  | #   a copy of the License at | ||||||
|  | # | ||||||
|  | #        http://www.apache.org/licenses/LICENSE-2.0 | ||||||
|  | # | ||||||
|  | #   Unless required by applicable law or agreed to in writing, software | ||||||
|  | #   distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||||||
|  | #   WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||||||
|  | #   License for the specific language governing permissions and limitations | ||||||
|  | #   under the License. | ||||||
|  | # | ||||||
|  |  | ||||||
|  | """Volume v1 QoS action implementations""" | ||||||
|  |  | ||||||
|  | import logging | ||||||
|  | import six | ||||||
|  |  | ||||||
|  | from cliff import command | ||||||
|  | from cliff import lister | ||||||
|  | from cliff import show | ||||||
|  |  | ||||||
|  | from openstackclient.common import parseractions | ||||||
|  | from openstackclient.common import utils | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class CreateQos(show.ShowOne): | ||||||
|  |     """Create new QoS specification""" | ||||||
|  |  | ||||||
|  |     log = logging.getLogger(__name__ + '.CreateQos') | ||||||
|  |  | ||||||
|  |     def get_parser(self, prog_name): | ||||||
|  |         parser = super(CreateQos, self).get_parser(prog_name) | ||||||
|  |         parser.add_argument( | ||||||
|  |             'name', | ||||||
|  |             metavar='<name>', | ||||||
|  |             help='New QoS specification name', | ||||||
|  |         ) | ||||||
|  |         consumer_choices = ['front-end', 'back-end', 'both'] | ||||||
|  |         parser.add_argument( | ||||||
|  |             '--consumer', | ||||||
|  |             metavar='<consumer>', | ||||||
|  |             choices=consumer_choices, | ||||||
|  |             default='both', | ||||||
|  |             help='Consumer of the QoS. Valid consumers: %s ' | ||||||
|  |                  "(defaults to 'both')" % utils.format_list(consumer_choices) | ||||||
|  |         ) | ||||||
|  |         parser.add_argument( | ||||||
|  |             '--property', | ||||||
|  |             metavar='<key=value>', | ||||||
|  |             action=parseractions.KeyValueAction, | ||||||
|  |             help='Set a QoS specification property ' | ||||||
|  |                  '(repeat option to set multiple properties)', | ||||||
|  |         ) | ||||||
|  |         return parser | ||||||
|  |  | ||||||
|  |     def take_action(self, parsed_args): | ||||||
|  |         self.log.debug('take_action(%s)', parsed_args) | ||||||
|  |         volume_client = self.app.client_manager.volume | ||||||
|  |         specs = {} | ||||||
|  |         specs.update({'consumer': parsed_args.consumer}) | ||||||
|  |  | ||||||
|  |         if parsed_args.property: | ||||||
|  |             specs.update(parsed_args.property) | ||||||
|  |  | ||||||
|  |         qos_specs = volume_client.qos_specs.create(parsed_args.name, specs) | ||||||
|  |  | ||||||
|  |         return zip(*sorted(six.iteritems(qos_specs._info))) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class DeleteQos(command.Command): | ||||||
|  |     """Delete QoS specification""" | ||||||
|  |  | ||||||
|  |     log = logging.getLogger(__name__ + '.DeleteQos') | ||||||
|  |  | ||||||
|  |     def get_parser(self, prog_name): | ||||||
|  |         parser = super(DeleteQos, self).get_parser(prog_name) | ||||||
|  |         parser.add_argument( | ||||||
|  |             'qos_specs', | ||||||
|  |             metavar='<qos-specs>', | ||||||
|  |             help='QoS specification to delete (name or ID)', | ||||||
|  |         ) | ||||||
|  |         return parser | ||||||
|  |  | ||||||
|  |     def take_action(self, parsed_args): | ||||||
|  |         self.log.debug('take_action(%s)', parsed_args) | ||||||
|  |         volume_client = self.app.client_manager.volume | ||||||
|  |         qos_specs = utils.find_resource(volume_client.qos_specs, | ||||||
|  |                                         parsed_args.qos_specs) | ||||||
|  |  | ||||||
|  |         volume_client.qos_specs.delete(qos_specs.id) | ||||||
|  |  | ||||||
|  |         return | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class ListQos(lister.Lister): | ||||||
|  |     """List QoS specifications""" | ||||||
|  |  | ||||||
|  |     log = logging.getLogger(__name__ + '.ListQos') | ||||||
|  |  | ||||||
|  |     def get_parser(self, prog_name): | ||||||
|  |         parser = super(ListQos, self).get_parser(prog_name) | ||||||
|  |         return parser | ||||||
|  |  | ||||||
|  |     def take_action(self, parsed_args): | ||||||
|  |         self.log.debug('take_action(%s)', parsed_args) | ||||||
|  |         volume_client = self.app.client_manager.volume | ||||||
|  |         qos_specs_list = volume_client.qos_specs.list() | ||||||
|  |  | ||||||
|  |         for qos in qos_specs_list: | ||||||
|  |             qos_associations = volume_client.qos_specs.get_associations(qos) | ||||||
|  |             if qos_associations: | ||||||
|  |                 associations = [association.name | ||||||
|  |                                 for association in qos_associations] | ||||||
|  |                 qos._info.update({'associations': associations}) | ||||||
|  |  | ||||||
|  |         columns = ('ID', 'Name', 'Consumer', 'Associations', 'Specs') | ||||||
|  |         return (columns, | ||||||
|  |                 (utils.get_dict_properties( | ||||||
|  |                     s._info, columns, | ||||||
|  |                     formatters={ | ||||||
|  |                         'Specs': utils.format_dict, | ||||||
|  |                         'Associations': utils.format_list | ||||||
|  |                     }, | ||||||
|  |                 ) for s in qos_specs_list)) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class ShowQos(show.ShowOne): | ||||||
|  |     """Display QoS specification details""" | ||||||
|  |  | ||||||
|  |     log = logging.getLogger(__name__ + '.ShowQos') | ||||||
|  |  | ||||||
|  |     def get_parser(self, prog_name): | ||||||
|  |         parser = super(ShowQos, self).get_parser(prog_name) | ||||||
|  |         parser.add_argument( | ||||||
|  |             'qos_specs', | ||||||
|  |             metavar='<qos-specs>', | ||||||
|  |             help='QoS specification to display (name or ID)', | ||||||
|  |         ) | ||||||
|  |         return parser | ||||||
|  |  | ||||||
|  |     def take_action(self, parsed_args): | ||||||
|  |         self.log.debug('take_action(%s)', parsed_args) | ||||||
|  |         volume_client = self.app.client_manager.volume | ||||||
|  |         qos_specs = utils.find_resource(volume_client.qos_specs, | ||||||
|  |                                         parsed_args.qos_specs) | ||||||
|  |  | ||||||
|  |         qos_associations = volume_client.qos_specs.get_associations(qos_specs) | ||||||
|  |         if qos_associations: | ||||||
|  |             associations = [association.name | ||||||
|  |                             for association in qos_associations] | ||||||
|  |             qos_specs._info.update({ | ||||||
|  |                 'associations': utils.format_list(associations) | ||||||
|  |             }) | ||||||
|  |         qos_specs._info.update({'specs': utils.format_dict(qos_specs.specs)}) | ||||||
|  |  | ||||||
|  |         return zip(*sorted(six.iteritems(qos_specs._info))) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class SetQos(command.Command): | ||||||
|  |     """Set QoS specification properties""" | ||||||
|  |  | ||||||
|  |     log = logging.getLogger(__name__ + '.SetQos') | ||||||
|  |  | ||||||
|  |     def get_parser(self, prog_name): | ||||||
|  |         parser = super(SetQos, self).get_parser(prog_name) | ||||||
|  |         parser.add_argument( | ||||||
|  |             'qos_specs', | ||||||
|  |             metavar='<qos-specs>', | ||||||
|  |             help='QoS specification to modify (name or ID)', | ||||||
|  |         ) | ||||||
|  |         parser.add_argument( | ||||||
|  |             '--property', | ||||||
|  |             metavar='<key=value>', | ||||||
|  |             action=parseractions.KeyValueAction, | ||||||
|  |             help='Property to add or modify for this QoS specification ' | ||||||
|  |                  '(repeat option to set multiple properties)', | ||||||
|  |         ) | ||||||
|  |         return parser | ||||||
|  |  | ||||||
|  |     def take_action(self, parsed_args): | ||||||
|  |         self.log.debug('take_action(%s)', parsed_args) | ||||||
|  |         volume_client = self.app.client_manager.volume | ||||||
|  |         qos_specs = utils.find_resource(volume_client.qos_specs, | ||||||
|  |                                         parsed_args.qos_specs) | ||||||
|  |  | ||||||
|  |         if parsed_args.property: | ||||||
|  |             volume_client.qos_specs.set_keys(qos_specs.id, | ||||||
|  |                                              parsed_args.property) | ||||||
|  |         else: | ||||||
|  |             self.app.log.error("No changes requested\n") | ||||||
|  |  | ||||||
|  |         return | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class UnsetQos(command.Command): | ||||||
|  |     """Unset QoS specification properties""" | ||||||
|  |  | ||||||
|  |     log = logging.getLogger(__name__ + '.SetQos') | ||||||
|  |  | ||||||
|  |     def get_parser(self, prog_name): | ||||||
|  |         parser = super(UnsetQos, self).get_parser(prog_name) | ||||||
|  |         parser.add_argument( | ||||||
|  |             'qos_specs', | ||||||
|  |             metavar='<qos-specs>', | ||||||
|  |             help='QoS specification to modify (name or ID)', | ||||||
|  |         ) | ||||||
|  |         parser.add_argument( | ||||||
|  |             '--property', | ||||||
|  |             metavar='<key>', | ||||||
|  |             action='append', | ||||||
|  |             default=[], | ||||||
|  |             help='Property to remove from the QoS specification. ' | ||||||
|  |                  '(repeat option to unset multiple properties)', | ||||||
|  |         ) | ||||||
|  |         return parser | ||||||
|  |  | ||||||
|  |     def take_action(self, parsed_args): | ||||||
|  |         self.log.debug('take_action(%s)', parsed_args) | ||||||
|  |         volume_client = self.app.client_manager.volume | ||||||
|  |         qos_specs = utils.find_resource(volume_client.qos_specs, | ||||||
|  |                                         parsed_args.qos_specs) | ||||||
|  |  | ||||||
|  |         if parsed_args.property: | ||||||
|  |             volume_client.qos_specs.unset_keys(qos_specs.id, | ||||||
|  |                                                parsed_args.property) | ||||||
|  |         else: | ||||||
|  |             self.app.log.error("No changes requested\n") | ||||||
|  |  | ||||||
|  |         return | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class AssociateQos(command.Command): | ||||||
|  |     """Associate a QoS specification to a volume type""" | ||||||
|  |  | ||||||
|  |     log = logging.getLogger(__name__ + '.AssociateQos') | ||||||
|  |  | ||||||
|  |     def get_parser(self, prog_name): | ||||||
|  |         parser = super(AssociateQos, self).get_parser(prog_name) | ||||||
|  |         parser.add_argument( | ||||||
|  |             'qos_specs', | ||||||
|  |             metavar='<qos-specs>', | ||||||
|  |             help='QoS specification to modify (name or ID)', | ||||||
|  |         ) | ||||||
|  |         parser.add_argument( | ||||||
|  |             'volume_type', | ||||||
|  |             metavar='<volume-type>', | ||||||
|  |             help='Volume type to associate the QoS (name or ID)', | ||||||
|  |         ) | ||||||
|  |         return parser | ||||||
|  |  | ||||||
|  |     def take_action(self, parsed_args): | ||||||
|  |         self.log.debug('take_action(%s)', parsed_args) | ||||||
|  |         volume_client = self.app.client_manager.volume | ||||||
|  |         qos_specs = utils.find_resource(volume_client.qos_specs, | ||||||
|  |                                         parsed_args.qos_specs) | ||||||
|  |         volume_type = utils.find_resource(volume_client.volume_types, | ||||||
|  |                                           parsed_args.volume_type) | ||||||
|  |  | ||||||
|  |         volume_client.qos_specs.associate(qos_specs.id, volume_type.id) | ||||||
|  |  | ||||||
|  |         return | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class DisassociateQos(command.Command): | ||||||
|  |     """Disassociate a QoS specification from a volume type""" | ||||||
|  |  | ||||||
|  |     log = logging.getLogger(__name__ + '.DisassociateQos') | ||||||
|  |  | ||||||
|  |     def get_parser(self, prog_name): | ||||||
|  |         parser = super(DisassociateQos, self).get_parser(prog_name) | ||||||
|  |         parser.add_argument( | ||||||
|  |             'qos_specs', | ||||||
|  |             metavar='<qos-specs>', | ||||||
|  |             help='QoS specification to modify (name or ID)', | ||||||
|  |         ) | ||||||
|  |         volume_type_group = parser.add_mutually_exclusive_group() | ||||||
|  |         volume_type_group.add_argument( | ||||||
|  |             '--volume-type', | ||||||
|  |             metavar='<volume-type>', | ||||||
|  |             help='Volume type to disassociate the QoS from (name or ID)', | ||||||
|  |         ) | ||||||
|  |         volume_type_group.add_argument( | ||||||
|  |             '--all', | ||||||
|  |             action='store_true', | ||||||
|  |             default=False, | ||||||
|  |             help='Disassociate the QoS from every volume type', | ||||||
|  |         ) | ||||||
|  |  | ||||||
|  |         return parser | ||||||
|  |  | ||||||
|  |     def take_action(self, parsed_args): | ||||||
|  |         self.log.debug('take_action(%s)', parsed_args) | ||||||
|  |         volume_client = self.app.client_manager.volume | ||||||
|  |         qos_specs = utils.find_resource(volume_client.qos_specs, | ||||||
|  |                                         parsed_args.qos_specs) | ||||||
|  |  | ||||||
|  |         if parsed_args.volume_type: | ||||||
|  |             volume_type = utils.find_resource(volume_client.volume_types, | ||||||
|  |                                               parsed_args.volume_type) | ||||||
|  |             volume_client.qos_specs.disassociate(qos_specs.id, volume_type.id) | ||||||
|  |         elif parsed_args.all: | ||||||
|  |             volume_client.qos_specs.disassociate_all(qos_specs.id) | ||||||
|  |  | ||||||
|  |         return | ||||||
| @@ -366,6 +366,15 @@ openstack.volume.v1 = | |||||||
|     volume_type_set = openstackclient.volume.v1.type:SetVolumeType |     volume_type_set = openstackclient.volume.v1.type:SetVolumeType | ||||||
|     volume_type_unset = openstackclient.volume.v1.type:UnsetVolumeType |     volume_type_unset = openstackclient.volume.v1.type:UnsetVolumeType | ||||||
|  |  | ||||||
|  |     volume_qos_create = openstackclient.volume.v1.qos_specs:CreateQos | ||||||
|  |     volume_qos_delete = openstackclient.volume.v1.qos_specs:DeleteQos | ||||||
|  |     volume_qos_list = openstackclient.volume.v1.qos_specs:ListQos | ||||||
|  |     volume_qos_show = openstackclient.volume.v1.qos_specs:ShowQos | ||||||
|  |     volume_qos_set = openstackclient.volume.v1.qos_specs:SetQos | ||||||
|  |     volume_qos_unset = openstackclient.volume.v1.qos_specs:UnsetQos | ||||||
|  |     volume_qos_associate = openstackclient.volume.v1.qos_specs:AssociateQos | ||||||
|  |     volume_qos_disassociate = openstackclient.volume.v1.qos_specs:DisassociateQos | ||||||
|  |  | ||||||
| openstack.volume.v2 = | openstack.volume.v2 = | ||||||
|     backup_create = openstackclient.volume.v2.backup:CreateBackup |     backup_create = openstackclient.volume.v2.backup:CreateBackup | ||||||
|     backup_delete = openstackclient.volume.v2.backup:DeleteBackup |     backup_delete = openstackclient.volume.v2.backup:DeleteBackup | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 David Moreau Simard
					David Moreau Simard