Add support for volume API v2 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: If3c679557ac9abb0dfc75d290b96fb9c8d46c7b7 Partial-Bug: #1467967
This commit is contained in:
		 David Moreau Simard
					David Moreau Simard
				
			
				
					committed by
					
						 gustavo panizzo
						gustavo panizzo
					
				
			
			
				
	
			
			
			 gustavo panizzo
						gustavo panizzo
					
				
			
						parent
						
							9c92dce870
						
					
				
				
					commit
					9a705a1f6d
				
			| @@ -117,6 +117,47 @@ BACKUP = { | ||||
| BACKUP_columns = tuple(sorted(BACKUP)) | ||||
| BACKUP_data = tuple((BACKUP[x] for x in sorted(BACKUP))) | ||||
|  | ||||
| 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_association = { | ||||
|     'association_type': 'volume_type', | ||||
|     'name': type_name, | ||||
|     'id': type_id | ||||
| } | ||||
|  | ||||
| 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 | ||||
| } | ||||
|  | ||||
| QOS_WITH_ASSOCIATIONS = { | ||||
|     'id': qos_id, | ||||
|     'consumer': qos_consumer, | ||||
|     'name': qos_name, | ||||
|     'specs': qos_specs, | ||||
|     'associations': [qos_association] | ||||
| } | ||||
|  | ||||
|  | ||||
| class FakeVolumeClient(object): | ||||
|     def __init__(self, **kwargs): | ||||
| @@ -130,6 +171,8 @@ class FakeVolumeClient(object): | ||||
|         self.volume_types.resource_class = fakes.FakeResource(None, {}) | ||||
|         self.restores = mock.Mock() | ||||
|         self.restores.resource_class = fakes.FakeResource(None, {}) | ||||
|         self.qos_specs = mock.Mock() | ||||
|         self.qos_specs.resource_class = fakes.FakeResource(None, {}) | ||||
|         self.auth_token = kwargs['token'] | ||||
|         self.management_url = kwargs['endpoint'] | ||||
|  | ||||
|   | ||||
							
								
								
									
										446
									
								
								openstackclient/tests/volume/v2/test_qos_specs.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										446
									
								
								openstackclient/tests/volume/v2/test_qos_specs.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,446 @@ | ||||
| #   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.common import utils | ||||
| from openstackclient.tests import fakes | ||||
| from openstackclient.tests.volume.v2 import fakes as volume_fakes | ||||
| from openstackclient.volume.v2 import qos_specs | ||||
|  | ||||
|  | ||||
| class TestQos(volume_fakes.TestVolume): | ||||
|  | ||||
|     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 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 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 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) | ||||
|  | ||||
|  | ||||
| class TestQosList(TestQos): | ||||
|     def setUp(self): | ||||
|         super(TestQosList, self).setUp() | ||||
|  | ||||
|         self.qos_mock.get.return_value = fakes.FakeResource( | ||||
|             None, | ||||
|             copy.deepcopy(volume_fakes.QOS_WITH_ASSOCIATIONS), | ||||
|             loaded=True, | ||||
|         ) | ||||
|         self.qos_mock.list.return_value = [self.qos_mock.get.return_value] | ||||
|         self.qos_mock.get_associations.return_value = [fakes.FakeResource( | ||||
|             None, | ||||
|             copy.deepcopy(volume_fakes.qos_association), | ||||
|             loaded=True, | ||||
|         )] | ||||
|  | ||||
|         # Get the command object to test | ||||
|         self.cmd = qos_specs.ListQos(self.app, None) | ||||
|  | ||||
|     def test_qos_list(self): | ||||
|         arglist = [] | ||||
|         verifylist = [] | ||||
|  | ||||
|         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||
|  | ||||
|         columns, data = self.cmd.take_action(parsed_args) | ||||
|         self.qos_mock.list.assert_called() | ||||
|  | ||||
|         collist = ( | ||||
|             'ID', | ||||
|             'Name', | ||||
|             'Consumer', | ||||
|             'Associations', | ||||
|             'Specs', | ||||
|         ) | ||||
|         self.assertEqual(collist, columns) | ||||
|         datalist = (( | ||||
|             volume_fakes.qos_id, | ||||
|             volume_fakes.qos_name, | ||||
|             volume_fakes.qos_consumer, | ||||
|             volume_fakes.type_name, | ||||
|             utils.format_dict(volume_fakes.qos_specs), | ||||
|         ), ) | ||||
|         self.assertEqual(datalist, tuple(data)) | ||||
|  | ||||
|  | ||||
| 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 TestQosShow(TestQos): | ||||
|     def setUp(self): | ||||
|         super(TestQosShow, self).setUp() | ||||
|  | ||||
|         self.qos_mock.get.return_value = fakes.FakeResource( | ||||
|             None, | ||||
|             copy.deepcopy(volume_fakes.QOS_WITH_ASSOCIATIONS), | ||||
|             loaded=True, | ||||
|         ) | ||||
|         self.qos_mock.get_associations.return_value = [fakes.FakeResource( | ||||
|             None, | ||||
|             copy.deepcopy(volume_fakes.qos_association), | ||||
|             loaded=True, | ||||
|         )] | ||||
|  | ||||
|         # Get the command object to test | ||||
|         self.cmd = qos_specs.ShowQos(self.app, None) | ||||
|  | ||||
|     def test_qos_show(self): | ||||
|         arglist = [ | ||||
|             volume_fakes.qos_id | ||||
|         ] | ||||
|         verifylist = [ | ||||
|             ('qos_specs', volume_fakes.qos_id) | ||||
|         ] | ||||
|  | ||||
|         parsed_args = self.check_parser(self.cmd, arglist, verifylist) | ||||
|  | ||||
|         columns, data = self.cmd.take_action(parsed_args) | ||||
|         self.qos_mock.get.assert_called_with( | ||||
|             volume_fakes.qos_id | ||||
|         ) | ||||
|  | ||||
|         collist = ( | ||||
|             'associations', | ||||
|             'consumer', | ||||
|             'id', | ||||
|             'name', | ||||
|             'specs' | ||||
|         ) | ||||
|         self.assertEqual(collist, columns) | ||||
|         datalist = ( | ||||
|             volume_fakes.type_name, | ||||
|             volume_fakes.qos_consumer, | ||||
|             volume_fakes.qos_id, | ||||
|             volume_fakes.qos_name, | ||||
|             utils.format_dict(volume_fakes.qos_specs), | ||||
|         ) | ||||
|         self.assertEqual(datalist, tuple(data)) | ||||
|  | ||||
|  | ||||
| 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'] | ||||
|         ) | ||||
							
								
								
									
										303
									
								
								openstackclient/volume/v2/qos_specs.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										303
									
								
								openstackclient/volume/v2/qos_specs.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,303 @@ | ||||
| #   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 v2 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 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 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 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 | ||||
|  | ||||
|  | ||||
| class ListQos(lister.Lister): | ||||
|     """List QoS specifications""" | ||||
|  | ||||
|     log = logging.getLogger(__name__ + '.ListQos') | ||||
|  | ||||
|     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 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 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 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 | ||||
| @@ -395,6 +395,15 @@ openstack.volume.v2 = | ||||
|     volume_type_delete = openstackclient.volume.v2.volume_type:DeleteVolumeType | ||||
|     volume_type_show = openstackclient.volume.v2.volume_type:ShowVolumeType | ||||
|  | ||||
|     volume_qos_associate = openstackclient.volume.v2.qos_specs:AssociateQos | ||||
|     volume_qos_create = openstackclient.volume.v2.qos_specs:CreateQos | ||||
|     volume_qos_delete = openstackclient.volume.v2.qos_specs:DeleteQos | ||||
|     volume_qos_disassociate = openstackclient.volume.v2.qos_specs:DisassociateQos | ||||
|     volume_qos_list = openstackclient.volume.v2.qos_specs:ListQos | ||||
|     volume_qos_set = openstackclient.volume.v2.qos_specs:SetQos | ||||
|     volume_qos_show = openstackclient.volume.v2.qos_specs:ShowQos | ||||
|     volume_qos_unset = openstackclient.volume.v2.qos_specs:UnsetQos | ||||
|  | ||||
| [build_sphinx] | ||||
| source-dir = doc/source | ||||
| build-dir = doc/build | ||||
|   | ||||
		Reference in New Issue
	
	Block a user