diff --git a/doc/source/command-objects/quota.rst b/doc/source/command-objects/quota.rst index 9e09bd484f..dc5e362355 100644 --- a/doc/source/command-objects/quota.rst +++ b/doc/source/command-objects/quota.rst @@ -32,6 +32,20 @@ Set quotas for project [--volumes ] [--volume-type ] + # Network settings + [--floating-ips ] + [--secgroup-rules ] + [--secgroups ] + [--networks ] + [--subnets ] + [--ports ] + [--routers ] + [--rbac-policies ] + [--vips ] + [--subnetpools ] + [--members ] + [--health-monitors ] + Set quotas for class @@ -126,6 +140,42 @@ Set quotas for class Set quotas for a specific +.. option:: --networks + + New value for the networks quota + +.. option:: --subnets + + New value for the subnets quota + +.. option:: --ports + + New value for the ports quota + +.. option:: --routers + + New value for the routers quota + +.. option:: --rbac-policies + + New value for the rbac-policies quota + +.. option:: --vips + + New value for the vips quota + +.. option:: --subnetpools + + New value for the subnetpools quota + +.. option:: --members + + New value for the members quota + +.. option:: --health-monitors + + New value for the health-monitors quota + quota show ---------- diff --git a/functional/tests/common/test_quota.py b/functional/tests/common/test_quota.py index 22549efe8c..0bc93db283 100644 --- a/functional/tests/common/test_quota.py +++ b/functional/tests/common/test_quota.py @@ -16,7 +16,7 @@ from functional.common import test class QuotaTests(test.TestCase): """Functional tests for quota. """ # Test quota information for compute, network and volume. - EXPECTED_FIELDS = ['instances', 'network', 'volumes'] + EXPECTED_FIELDS = ['instances', 'networks', 'volumes'] PROJECT_NAME = None @classmethod @@ -25,12 +25,11 @@ class QuotaTests(test.TestCase): cls.get_openstack_configuration_value('auth.project_name') def test_quota_set(self): - # TODO(rtheis): Add --network option once supported on set. - self.openstack('quota set --instances 11 --volumes 11 ' + - self.PROJECT_NAME) + self.openstack('quota set --instances 11 --volumes 11 --networks 11 ' + + self.PROJECT_NAME) opts = self.get_show_opts(self.EXPECTED_FIELDS) raw_output = self.openstack('quota show ' + self.PROJECT_NAME + opts) - self.assertEqual("11\n10\n11\n", raw_output) + self.assertEqual("11\n11\n11\n", raw_output) def test_quota_show(self): raw_output = self.openstack('quota show ' + self.PROJECT_NAME) diff --git a/openstackclient/common/quota.py b/openstackclient/common/quota.py index b497a44d62..e177fbcee8 100644 --- a/openstackclient/common/quota.py +++ b/openstackclient/common/quota.py @@ -29,7 +29,6 @@ from openstackclient.common import utils COMPUTE_QUOTAS = { 'cores': 'cores', 'fixed_ips': 'fixed-ips', - 'floating_ips': 'floating-ips', 'injected_file_content_bytes': 'injected-file-size', 'injected_file_path_bytes': 'injected-path-size', 'injected_files': 'injected-files', @@ -37,8 +36,6 @@ COMPUTE_QUOTAS = { 'key_pairs': 'key-pairs', 'metadata_items': 'properties', 'ram': 'ram', - 'security_group_rules': 'secgroup-rules', - 'security_groups': 'secgroups', } VOLUME_QUOTAS = { @@ -47,16 +44,41 @@ VOLUME_QUOTAS = { 'volumes': 'volumes', } +NOVA_NETWORK_QUOTAS = { + 'floating_ips': 'floating-ips', + 'security_group_rules': 'secgroup-rules', + 'security_groups': 'secgroups', +} + NETWORK_QUOTAS = { 'floatingip': 'floating-ips', 'security_group_rule': 'secgroup-rules', 'security_group': 'secgroups', + 'network': 'networks', + 'subnet': 'subnets', + 'port': 'ports', + 'router': 'routers', + 'rbac_policy': 'rbac-policies', + 'vip': 'vips', + 'subnetpool': 'subnetpools', + 'member': 'members', + 'health_monitor': 'health-monitors', } class SetQuota(command.Command): """Set quotas for project or class""" + def _build_options_list(self): + if self.app.client_manager.is_network_endpoint_enabled(): + return itertools.chain(COMPUTE_QUOTAS.items(), + VOLUME_QUOTAS.items(), + NETWORK_QUOTAS.items()) + else: + return itertools.chain(COMPUTE_QUOTAS.items(), + VOLUME_QUOTAS.items(), + NOVA_NETWORK_QUOTAS.items()) + def get_parser(self, prog_name): parser = super(SetQuota, self).get_parser(prog_name) parser.add_argument( @@ -71,8 +93,7 @@ class SetQuota(command.Command): default=False, help='Set quotas for ', ) - for k, v in itertools.chain( - COMPUTE_QUOTAS.items(), VOLUME_QUOTAS.items()): + for k, v in self._build_options_list(): parser.add_argument( '--%s' % v, metavar='<%s>' % v, @@ -92,7 +113,7 @@ class SetQuota(command.Command): identity_client = self.app.client_manager.identity compute_client = self.app.client_manager.compute volume_client = self.app.client_manager.volume - + network_client = self.app.client_manager.network compute_kwargs = {} for k, v in COMPUTE_QUOTAS.items(): value = getattr(parsed_args, k, None) @@ -107,7 +128,20 @@ class SetQuota(command.Command): k = k + '_%s' % parsed_args.volume_type volume_kwargs[k] = value - if compute_kwargs == {} and volume_kwargs == {}: + network_kwargs = {} + if self.app.client_manager.is_network_endpoint_enabled(): + for k, v in NETWORK_QUOTAS.items(): + value = getattr(parsed_args, k, None) + if value is not None: + network_kwargs[k] = value + else: + for k, v in NOVA_NETWORK_QUOTAS.items(): + value = getattr(parsed_args, k, None) + if value is not None: + compute_kwargs[k] = value + + if (compute_kwargs == {} and volume_kwargs == {} + and network_kwargs == {}): sys.stderr.write("No quotas updated") return @@ -126,6 +160,9 @@ class SetQuota(command.Command): volume_client.quota_classes.update( project.id, **volume_kwargs) + if network_kwargs: + sys.stderr.write("Network quotas are ignored since quota class" + "is not supported.") else: if compute_kwargs: compute_client.quotas.update( @@ -135,6 +172,10 @@ class SetQuota(command.Command): volume_client.quotas.update( project.id, **volume_kwargs) + if network_kwargs: + network_client.update_quota( + project.id, + **network_kwargs) class ShowQuota(command.ShowOne): @@ -232,8 +273,8 @@ class ShowQuota(command.ShowOne): # neutron is enabled, quotas of these three resources # in nova will be replaced by neutron's. for k, v in itertools.chain( - COMPUTE_QUOTAS.items(), VOLUME_QUOTAS.items(), - NETWORK_QUOTAS.items()): + COMPUTE_QUOTAS.items(), NOVA_NETWORK_QUOTAS.items(), + VOLUME_QUOTAS.items(), NETWORK_QUOTAS.items()): if not k == v and info.get(k): info[v] = info[k] info.pop(k) diff --git a/openstackclient/tests/common/test_quota.py b/openstackclient/tests/common/test_quota.py index ba7ee469c9..c9ec5599f1 100644 --- a/openstackclient/tests/common/test_quota.py +++ b/openstackclient/tests/common/test_quota.py @@ -97,6 +97,9 @@ class TestQuotaSet(TestQuota): loaded=True, ) + self.network_mock = self.app.client_manager.network + self.network_mock.update_quota = mock.Mock() + self.cmd = quota.SetQuota(self.app, None) def test_quota_set(self): @@ -132,6 +135,7 @@ class TestQuotaSet(TestQuota): ('project', identity_fakes.project_name), ] + self.app.client_manager.network_endpoint_enabled = False parsed_args = self.check_parser(self.cmd, arglist, verifylist) self.cmd.take_action(parsed_args) @@ -185,6 +189,61 @@ class TestQuotaSet(TestQuota): **kwargs ) + def test_quota_set_network(self): + arglist = [ + '--subnets', str(network_fakes.QUOTA['subnet']), + '--networks', str(network_fakes.QUOTA['network']), + '--floating-ips', str(network_fakes.QUOTA['floatingip']), + '--subnetpools', str(network_fakes.QUOTA['subnetpool']), + '--secgroup-rules', + str(network_fakes.QUOTA['security_group_rule']), + '--secgroups', str(network_fakes.QUOTA['security_group']), + '--routers', str(network_fakes.QUOTA['router']), + '--rbac-policies', str(network_fakes.QUOTA['rbac_policy']), + '--ports', str(network_fakes.QUOTA['port']), + '--vips', str(network_fakes.QUOTA['vip']), + '--members', str(network_fakes.QUOTA['member']), + '--health-monitors', str(network_fakes.QUOTA['health_monitor']), + identity_fakes.project_name, + ] + verifylist = [ + ('subnet', network_fakes.QUOTA['subnet']), + ('network', network_fakes.QUOTA['network']), + ('floatingip', network_fakes.QUOTA['floatingip']), + ('subnetpool', network_fakes.QUOTA['subnetpool']), + ('security_group_rule', + network_fakes.QUOTA['security_group_rule']), + ('security_group', network_fakes.QUOTA['security_group']), + ('router', network_fakes.QUOTA['router']), + ('rbac_policy', network_fakes.QUOTA['rbac_policy']), + ('port', network_fakes.QUOTA['port']), + ('vip', network_fakes.QUOTA['vip']), + ('member', network_fakes.QUOTA['member']), + ('health_monitor', network_fakes.QUOTA['health_monitor']), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + self.cmd.take_action(parsed_args) + kwargs = { + 'subnet': network_fakes.QUOTA['subnet'], + 'network': network_fakes.QUOTA['network'], + 'floatingip': network_fakes.QUOTA['floatingip'], + 'subnetpool': network_fakes.QUOTA['subnetpool'], + 'security_group_rule': + network_fakes.QUOTA['security_group_rule'], + 'security_group': network_fakes.QUOTA['security_group'], + 'router': network_fakes.QUOTA['router'], + 'rbac_policy': network_fakes.QUOTA['rbac_policy'], + 'port': network_fakes.QUOTA['port'], + 'vip': network_fakes.QUOTA['vip'], + 'member': network_fakes.QUOTA['member'], + 'health_monitor': network_fakes.QUOTA['health_monitor'], + } + self.network_mock.update_quota.assert_called_with( + identity_fakes.project_id, + **kwargs + ) + class TestQuotaShow(TestQuota): diff --git a/openstackclient/tests/network/v2/fakes.py b/openstackclient/tests/network/v2/fakes.py index 84ede381bf..417cf26ee7 100644 --- a/openstackclient/tests/network/v2/fakes.py +++ b/openstackclient/tests/network/v2/fakes.py @@ -36,6 +36,9 @@ QUOTA = { "router": 10, "rbac_policy": -1, "port": 50, + "vip": 10, + "member": 10, + "health_monitor": 10, } diff --git a/releasenotes/notes/add-quota-set-for-network-11fcd7b9e08624b5.yaml b/releasenotes/notes/add-quota-set-for-network-11fcd7b9e08624b5.yaml new file mode 100644 index 0000000000..0f7dd55926 --- /dev/null +++ b/releasenotes/notes/add-quota-set-for-network-11fcd7b9e08624b5.yaml @@ -0,0 +1,9 @@ +--- +features: + - | + Add network support for ``quota set`` command. Options added includes + ``--networks --subnets --subnetpools --ports --routers --rbac-policies`` + ``--vips --members --health-monitors``. + Options ``--floating-ips --secgroup-rules --secgroups`` now support + both network and compute API. + [Bug `1489441 `_]