From a6cdd1daced1080c42caabfcd9cb0ee509d8a269 Mon Sep 17 00:00:00 2001 From: Rodolfo Alonso Hernandez Date: Thu, 2 Jun 2016 09:39:10 +0100 Subject: [PATCH] Add QoS egress minimum bandwidth rule to neutronclient The following patch implements the QoS egress minimum bandwidth assurance in neutronclient. Change-Id: I025522f73a9a8e3a9f69f097cedaeba330b9914a Depends-On: I6b619a96a2bfde164646c71409b671352bc6ce7d Depends-On: I13c54be22f35ac7eb5835d8424a919d0b61a8e95 Partial-Bug: #1560963 --- .../v2_0/qos/minimum_bandwidth_rule.py | 111 ++++++++++++++ neutronclient/shell.py | 16 ++ .../qos/test_cli20_minimum_bandwidth_rule.py | 142 ++++++++++++++++++ .../tests/unit/qos/test_cli20_rule.py | 7 +- neutronclient/v2_0/client.py | 34 +++++ ...os_minimum_bandwidth-dc4adb23c51de30b.yaml | 4 + 6 files changed, 312 insertions(+), 2 deletions(-) create mode 100644 neutronclient/neutron/v2_0/qos/minimum_bandwidth_rule.py create mode 100644 neutronclient/tests/unit/qos/test_cli20_minimum_bandwidth_rule.py create mode 100644 releasenotes/notes/qos_minimum_bandwidth-dc4adb23c51de30b.yaml diff --git a/neutronclient/neutron/v2_0/qos/minimum_bandwidth_rule.py b/neutronclient/neutron/v2_0/qos/minimum_bandwidth_rule.py new file mode 100644 index 000000000..cc64549af --- /dev/null +++ b/neutronclient/neutron/v2_0/qos/minimum_bandwidth_rule.py @@ -0,0 +1,111 @@ +# Copyright (c) 2016 Intel Corporation. +# All Rights Reserved +# +# 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. +# + +from neutronclient._i18n import _ +from neutronclient.common import utils +from neutronclient.neutron import v2_0 as neutronv20 +from neutronclient.neutron.v2_0.qos import rule as qos_rule + + +MINIMUM_BANDWIDTH_RULE_RESOURCE = 'minimum_bandwidth_rule' + + +def add_minimum_bandwidth_arguments(parser): + parser.add_argument( + '--min-kbps', + required=True, + type=str, + help=_('QoS minimum bandwidth assurance, expressed in kilobits ' + 'per second.')) + # NOTE(ralonsoh): the only direction implemented is "egress". Please, + # refer to the spec (https://review.openstack.org/#/c/316082/). + parser.add_argument( + '--direction', + # NOTE(ihrachys): though server picks the default for us (egress), it's + # better to require the argument to make the UI more explicit and the + # intentions more clear in the future when we add other values for the + # attribute on server side. + required=True, + type=utils.convert_to_lowercase, + choices=['egress'], + help=_('Traffic direction.')) + + +def update_minimum_bandwidth_args2body(parsed_args, body): + neutronv20.update_dict(parsed_args, body, ['min_kbps', 'direction']) + + +class CreateQoSMinimumBandwidthRule(qos_rule.QosRuleMixin, + neutronv20.CreateCommand): + """Create a qos minimum bandwidth rule.""" + + resource = MINIMUM_BANDWIDTH_RULE_RESOURCE + + def add_known_arguments(self, parser): + super(CreateQoSMinimumBandwidthRule, self).add_known_arguments( + parser) + add_minimum_bandwidth_arguments(parser) + + def args2body(self, parsed_args): + body = {} + update_minimum_bandwidth_args2body(parsed_args, body) + return {self.resource: body} + + +class ListQoSMinimumBandwidthRules(qos_rule.QosRuleMixin, + neutronv20.ListCommand): + """List all qos minimum bandwidth rules belonging to the specified policy. + + """ + + resource = MINIMUM_BANDWIDTH_RULE_RESOURCE + _formatters = {} + pagination_support = True + sorting_support = True + + +class ShowQoSMinimumBandwidthRule(qos_rule.QosRuleMixin, + neutronv20.ShowCommand): + """Show information about the given qos minimum bandwidth rule.""" + + resource = MINIMUM_BANDWIDTH_RULE_RESOURCE + allow_names = False + + +class UpdateQoSMinimumBandwidthRule(qos_rule.QosRuleMixin, + neutronv20.UpdateCommand): + """Update the given qos minimum bandwidth rule.""" + + resource = MINIMUM_BANDWIDTH_RULE_RESOURCE + allow_names = False + + def add_known_arguments(self, parser): + super(UpdateQoSMinimumBandwidthRule, self).add_known_arguments( + parser) + add_minimum_bandwidth_arguments(parser) + + def args2body(self, parsed_args): + body = {} + update_minimum_bandwidth_args2body(parsed_args, body) + return {self.resource: body} + + +class DeleteQoSMinimumBandwidthRule(qos_rule.QosRuleMixin, + neutronv20.DeleteCommand): + """Delete a given qos minimum bandwidth rule.""" + + resource = MINIMUM_BANDWIDTH_RULE_RESOURCE + allow_names = False diff --git a/neutronclient/shell.py b/neutronclient/shell.py index dad8d48ed..39ab0aa58 100644 --- a/neutronclient/shell.py +++ b/neutronclient/shell.py @@ -73,6 +73,7 @@ from neutronclient.neutron.v2_0 import port from neutronclient.neutron.v2_0 import purge from neutronclient.neutron.v2_0.qos import bandwidth_limit_rule from neutronclient.neutron.v2_0.qos import dscp_marking_rule +from neutronclient.neutron.v2_0.qos import minimum_bandwidth_rule from neutronclient.neutron.v2_0.qos import policy as qos_policy from neutronclient.neutron.v2_0.qos import rule as qos_rule from neutronclient.neutron.v2_0 import quota @@ -397,6 +398,21 @@ COMMAND_V2 = { 'qos-dscp-marking-rule-delete': ( dscp_marking_rule.DeleteQoSDscpMarkingRule ), + 'qos-minimum-bandwidth-rule-create': ( + minimum_bandwidth_rule.CreateQoSMinimumBandwidthRule + ), + 'qos-minimum-bandwidth-rule-show': ( + minimum_bandwidth_rule.ShowQoSMinimumBandwidthRule + ), + 'qos-minimum-bandwidth-rule-list': ( + minimum_bandwidth_rule.ListQoSMinimumBandwidthRules + ), + 'qos-minimum-bandwidth-rule-update': ( + minimum_bandwidth_rule.UpdateQoSMinimumBandwidthRule + ), + 'qos-minimum-bandwidth-rule-delete': ( + minimum_bandwidth_rule.DeleteQoSMinimumBandwidthRule + ), 'qos-available-rule-types': qos_rule.ListQoSRuleTypes, 'flavor-list': flavor.ListFlavor, 'flavor-show': flavor.ShowFlavor, diff --git a/neutronclient/tests/unit/qos/test_cli20_minimum_bandwidth_rule.py b/neutronclient/tests/unit/qos/test_cli20_minimum_bandwidth_rule.py new file mode 100644 index 000000000..0c44f5cd7 --- /dev/null +++ b/neutronclient/tests/unit/qos/test_cli20_minimum_bandwidth_rule.py @@ -0,0 +1,142 @@ +# Copyright (c) 2016 Intel Corporation. +# All Rights Reserved +# +# 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 sys + +from neutronclient.neutron.v2_0.qos import minimum_bandwidth_rule as bw_rule +from neutronclient.tests.unit import test_cli20 + + +class CLITestV20QoSMinimumBandwidthRuleJSON(test_cli20.CLITestV20Base): + + non_admin_status_resources = ['minimum_bandwidth_rule'] + + def setUp(self): + super(CLITestV20QoSMinimumBandwidthRuleJSON, self).setUp() + self.res = 'minimum_bandwidth_rule' + self.cmd_res = 'qos_minimum_bandwidth_rule' + self.ress = self.res + 's' + self.cmd_ress = self.cmd_res + 's' + + def test_create_minimum_bandwidth_rule_min_kbps_only(self): + cmd = bw_rule.CreateQoSMinimumBandwidthRule( + test_cli20.MyApp(sys.stdout), None) + my_id = 'my-id' + min_kbps = '1500' + policy_id = 'policy_id' + args = ['--min-kbps', min_kbps, + policy_id] + position_names = ['min_kbps'] + position_values = [min_kbps] + self.assertRaises(SystemExit, self._test_create_resource, + self.res, cmd, '', my_id, args, + position_names, position_values, + cmd_resource=self.cmd_res, + parent_id=policy_id, + no_api_call=True) + + def test_create_minimum_bandwidth_rule_direction_only(self): + cmd = bw_rule.CreateQoSMinimumBandwidthRule( + test_cli20.MyApp(sys.stdout), None) + my_id = 'my-id' + direction = 'egress' + policy_id = 'policy_id' + args = ['--direction', direction, + policy_id] + position_names = ['direction'] + position_values = [direction] + self.assertRaises(SystemExit, self._test_create_resource, + self.res, cmd, '', my_id, args, + position_names, position_values, + cmd_resource=self.cmd_res, + parent_id=policy_id, + no_api_call=True) + + def test_create_minimum_bandwidth_rule_none(self): + cmd = bw_rule.CreateQoSMinimumBandwidthRule( + test_cli20.MyApp(sys.stdout), None) + my_id = 'my-id' + policy_id = 'policy_id' + args = [policy_id] + position_names = [] + position_values = [] + self.assertRaises(SystemExit, self._test_create_resource, + self.res, cmd, '', my_id, args, + position_names, position_values, + cmd_resource=self.cmd_res, + parent_id=policy_id, + no_api_call=True) + + def test_create_minimum_bandwidth_rule_all(self): + cmd = bw_rule.CreateQoSMinimumBandwidthRule( + test_cli20.MyApp(sys.stdout), None) + my_id = 'my-id' + min_kbps = '1500' + direction = 'egress' + policy_id = 'policy_id' + args = ['--min-kbps', min_kbps, + '--direction', direction, + policy_id] + position_names = ['direction', 'min_kbps'] + position_values = [direction, min_kbps] + self._test_create_resource(self.res, cmd, '', my_id, args, + position_names, position_values, + cmd_resource=self.cmd_res, + parent_id=policy_id) + + def test_update_minimum_bandwidth_rule(self): + cmd = bw_rule.UpdateQoSMinimumBandwidthRule( + test_cli20.MyApp(sys.stdout), None) + my_id = 'my-id' + min_kbps = '1200' + direction = 'egress' + policy_id = 'policy_id' + args = ['--min-kbps', min_kbps, + '--direction', direction, + my_id, policy_id] + self._test_update_resource(self.res, cmd, my_id, args, + {'min_kbps': min_kbps, + 'direction': direction}, + cmd_resource=self.cmd_res, + parent_id=policy_id) + + def test_delete_minimum_bandwidth_rule(self): + cmd = bw_rule.DeleteQoSMinimumBandwidthRule( + test_cli20.MyApp(sys.stdout), None) + my_id = 'my-id' + policy_id = 'policy_id' + args = [my_id, policy_id] + self._test_delete_resource(self.res, cmd, my_id, args, + cmd_resource=self.cmd_res, + parent_id=policy_id) + + def test_show_minimum_bandwidth_rule(self): + cmd = bw_rule.ShowQoSMinimumBandwidthRule( + test_cli20.MyApp(sys.stdout), None) + policy_id = 'policy_id' + args = [self.test_id, policy_id] + self._test_show_resource(self.res, cmd, self.test_id, args, + [], cmd_resource=self.cmd_res, + parent_id=policy_id) + + def test_list_minimum_bandwidth_rule(self): + cmd = bw_rule.ListQoSMinimumBandwidthRules( + test_cli20.MyApp(sys.stdout), None) + policy_id = 'policy_id' + args = [policy_id] + contents = [{'name': 'rule1', 'min-kbps': 1000, 'direction': 'egress'}] + self._test_list_resources(self.cmd_ress, cmd, parent_id=policy_id, + base_args=args, response_contents=contents) diff --git a/neutronclient/tests/unit/qos/test_cli20_rule.py b/neutronclient/tests/unit/qos/test_cli20_rule.py index bdbf52df9..c1da5afef 100644 --- a/neutronclient/tests/unit/qos/test_cli20_rule.py +++ b/neutronclient/tests/unit/qos/test_cli20_rule.py @@ -22,7 +22,9 @@ from neutronclient.tests.unit import test_cli20 class CLITestV20QoSRuleJSON(test_cli20.CLITestV20Base): - non_admin_status_resources = ['bandwidth_limit_rule', 'dscp_marking_rule'] + non_admin_status_resources = ['bandwidth_limit_rule', + 'dscp_marking_rule', + 'minimum_bandwidth_rule'] def setUp(self): super(CLITestV20QoSRuleJSON, self).setUp() @@ -32,7 +34,8 @@ class CLITestV20QoSRuleJSON(test_cli20.CLITestV20Base): resources = 'rule_types' cmd_resources = 'qos_rule_types' response_contents = [{'type': 'bandwidth_limit', - 'type': 'dscp_marking'}] + 'type': 'dscp_marking', + 'type': 'minimum_bandwidth'}] cmd = qos_rule.ListQoSRuleTypes(test_cli20.MyApp(sys.stdout), None) diff --git a/neutronclient/v2_0/client.py b/neutronclient/v2_0/client.py index a01cc91e9..95324a704 100644 --- a/neutronclient/v2_0/client.py +++ b/neutronclient/v2_0/client.py @@ -595,6 +595,10 @@ class Client(ClientBase): qos_bandwidth_limit_rule_path = "/qos/policies/%s/bandwidth_limit_rules/%s" qos_dscp_marking_rules_path = "/qos/policies/%s/dscp_marking_rules" qos_dscp_marking_rule_path = "/qos/policies/%s/dscp_marking_rules/%s" + qos_minimum_bandwidth_rules_path = \ + "/qos/policies/%s/minimum_bandwidth_rules" + qos_minimum_bandwidth_rule_path = \ + "/qos/policies/%s/minimum_bandwidth_rules/%s" qos_rule_types_path = "/qos/rule-types" qos_rule_type_path = "/qos/rule-types/%s" flavors_path = "/flavors" @@ -660,6 +664,7 @@ class Client(ClientBase): 'qos_policies': 'qos_policy', 'policies': 'policy', 'bandwidth_limit_rules': 'bandwidth_limit_rule', + 'minimum_bandwidth_rules': 'minimum_bandwidth_rule', 'rules': 'rule', 'dscp_marking_rules': 'dscp_marking_rule', 'rule_types': 'rule_type', @@ -1740,6 +1745,35 @@ class Client(ClientBase): return self.delete(self.qos_dscp_marking_rule_path % (policy, rule)) + def list_minimum_bandwidth_rules(self, policy_id, retrieve_all=True, + **_params): + """Fetches a list of all minimum bandwidth rules for the given policy. + + """ + return self.list('qos_minimum_bandwidth_rules', + self.qos_minimum_bandwidth_rules_path % + policy_id, retrieve_all, **_params) + + def show_minimum_bandwidth_rule(self, rule, policy, body=None): + """Fetches information of a certain minimum bandwidth rule.""" + return self.get(self.qos_minimum_bandwidth_rule_path % + (policy, rule), body=body) + + def create_minimum_bandwidth_rule(self, policy, body=None): + """Creates a new minimum bandwidth rule.""" + return self.post(self.qos_minimum_bandwidth_rules_path % policy, + body=body) + + def update_minimum_bandwidth_rule(self, rule, policy, body=None): + """Updates a minimum bandwidth rule.""" + return self.put(self.qos_minimum_bandwidth_rule_path % + (policy, rule), body=body) + + def delete_minimum_bandwidth_rule(self, rule, policy): + """Deletes a minimum bandwidth rule.""" + return self.delete(self.qos_minimum_bandwidth_rule_path % + (policy, rule)) + def create_flavor(self, body=None): """Creates a new Neutron service flavor.""" return self.post(self.flavors_path, body=body) diff --git a/releasenotes/notes/qos_minimum_bandwidth-dc4adb23c51de30b.yaml b/releasenotes/notes/qos_minimum_bandwidth-dc4adb23c51de30b.yaml new file mode 100644 index 000000000..2d1002f07 --- /dev/null +++ b/releasenotes/notes/qos_minimum_bandwidth-dc4adb23c51de30b.yaml @@ -0,0 +1,4 @@ +--- +features: + - New create, update, list, show, and delete commands are added for the QoS + minimum bandwidth rule.