summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzitptan <nitish.patcherla@est.tech>2021-08-17 14:37:00 +0530
committerelajkat <lajos.katona@est.tech>2022-02-17 13:40:39 +0100
commitaa83752f20225c9817196263915ad02b9d823cb7 (patch)
treec764e668725197292988a1a2e2e1a880300963ef
parent12bb9fe5184c9dd3329ba17b3d03c90887dbcc3d (diff)
downloadhorizon-aa83752f20225c9817196263915ad02b9d823cb7.tar.gz
Add Rules operation to Network QoS Policy
Added create, edit, and delete rules operation to the network qos policy. Rules: Minimum-Bandwidth, DSCP-Marking, and Bandwidth-Limit, Minimum-Packet-Rate Partially-Implements: https://blueprints.launchpad.net/horizon/+spec/create-network-qos-policy Change-Id: I49058036f1d78ef022d966f6b375cdc984755813
-rw-r--r--openstack_dashboard/api/neutron.py183
-rw-r--r--openstack_dashboard/api/rest/neutron.py154
-rw-r--r--openstack_dashboard/static/app/core/network_qos/actions/actions.module.js34
-rw-r--r--openstack_dashboard/static/app/core/network_qos/actions/actions.module.spec.js15
-rw-r--r--openstack_dashboard/static/app/core/network_qos/actions/add-rule.action.service.js182
-rw-r--r--openstack_dashboard/static/app/core/network_qos/actions/add-rule.action.service.spec.js154
-rw-r--r--openstack_dashboard/static/app/core/network_qos/actions/add-rule.controller.js74
-rw-r--r--openstack_dashboard/static/app/core/network_qos/actions/add-rule.controller.spec.js130
-rw-r--r--openstack_dashboard/static/app/core/network_qos/actions/add-rule.html98
-rw-r--r--openstack_dashboard/static/app/core/network_qos/actions/delete-rule.action.service.js117
-rw-r--r--openstack_dashboard/static/app/core/network_qos/actions/delete-rule.action.service.spec.js224
-rw-r--r--openstack_dashboard/static/app/core/network_qos/actions/edit-rule.action.service.js173
-rw-r--r--openstack_dashboard/static/app/core/network_qos/actions/edit-rule.action.service.spec.js244
-rw-r--r--openstack_dashboard/static/app/core/network_qos/actions/edit-rule.controller.js104
-rw-r--r--openstack_dashboard/static/app/core/network_qos/actions/edit-rule.controller.spec.js161
-rw-r--r--openstack_dashboard/static/app/core/network_qos/actions/edit-rule.html106
-rw-r--r--openstack_dashboard/static/app/core/network_qos/actions/rule.description.html18
-rw-r--r--openstack_dashboard/static/app/core/network_qos/actions/workflow/delete-rule.workflow.service.js118
-rw-r--r--openstack_dashboard/static/app/core/network_qos/actions/workflow/delete-rule.workflow.service.spec.js97
-rw-r--r--openstack_dashboard/static/app/core/network_qos/details/overview.controller.js58
-rw-r--r--openstack_dashboard/static/app/core/network_qos/details/overview.html37
-rw-r--r--openstack_dashboard/static/app/core/openstack-service-api/neutron.service.js366
-rw-r--r--openstack_dashboard/static/app/core/openstack-service-api/neutron.service.spec.js108
-rw-r--r--openstack_dashboard/test/test_data/neutron_data.py51
-rw-r--r--openstack_dashboard/test/unit/api/test_neutron.py259
-rw-r--r--releasenotes/notes/network_qos_rules-cd103f9383b6cdf9.yaml8
26 files changed, 3259 insertions, 14 deletions
diff --git a/openstack_dashboard/api/neutron.py b/openstack_dashboard/api/neutron.py
index 0f06a1b22..ccf0d6782 100644
--- a/openstack_dashboard/api/neutron.py
+++ b/openstack_dashboard/api/neutron.py
@@ -2012,6 +2012,189 @@ def policy_delete(request, policy_id):
neutronclient(request).delete_qos_policy(policy_id)
+class DSCPMarkingRule(NeutronAPIDictWrapper):
+ """Wrapper for neutron DSCPMarkingRule."""
+
+
+@profiler.trace
+def dscp_marking_rule_create(request, policy_id, **kwargs):
+ """Create a DSCP Marking rule.
+
+ :param request: request context
+ :param policy_id: Id of the policy
+ :param dscp_mark: integer
+ :return: A dscp_mark_rule object.
+ """
+ if 'tenant_id' not in kwargs:
+ kwargs['tenant_id'] = request.user.project_id
+ body = {'dscp_marking_rule': kwargs}
+ rule = 'dscp_marking_rule'
+ dscp_marking_rule = neutronclient(request)\
+ .create_dscp_marking_rule(policy_id, body).get(rule)
+ return DSCPMarkingRule(dscp_marking_rule)
+
+
+@profiler.trace
+def dscp_marking_rule_update(request, policy_id, rule_id, **kwargs):
+ """Update a DSCP Marking Limit Rule."""
+
+ body = {'dscp_marking_rule': kwargs}
+ ruleType = 'dscp_marking_rule'
+ dscpmarking_update = neutronclient(request)\
+ .update_dscp_marking_rule(rule_id, policy_id, body).get(ruleType)
+ return DSCPMarkingRule(dscpmarking_update)
+
+
+def dscp_marking_rule_delete(request, policy_id, rule_id):
+ """Deletes a DSCP Marking Rule."""
+
+ neutronclient(request).delete_dscp_marking_rule(rule_id, policy_id)
+
+
+class MinimumBandwidthRule(NeutronAPIDictWrapper):
+ """Wrapper for neutron MinimumBandwidthRule."""
+
+
+@profiler.trace
+def minimum_bandwidth_rule_create(request, policy_id, **kwargs):
+ """Create a Minimum Bandwidth rule.
+
+ :param request: request context
+ :param policy_id: Id of the policy
+ :param min_kbps: integer
+ :param direction: string (egress or ingress)
+ :return: A minimum_bandwidth_rule object.
+ """
+ if 'tenant_id' not in kwargs:
+ kwargs['tenant_id'] = request.user.project_id
+ body = {'minimum_bandwidth_rule': kwargs}
+ rule = 'minimum_bandwidth_rule'
+ minimum_bandwidth_rule = neutronclient(request)\
+ .create_minimum_bandwidth_rule(policy_id, body).get(rule)
+ return MinimumBandwidthRule(minimum_bandwidth_rule)
+
+
+@profiler.trace
+def minimum_bandwidth_rule_update(request, policy_id, rule_id, **kwargs):
+ """Update a Minimum Bandwidth rule.
+
+ :param request: request context
+ :param policy_id: Id of the policy
+ :param min_kbps: integer
+ :param direction: string (egress or ingress)
+ :return: A minimum_bandwidth_rule object.
+ """
+ body = {'minimum_bandwidth_rule': kwargs}
+ ruleType = 'minimum_bandwidth_rule'
+ minbandwidth_update = neutronclient(request)\
+ .update_minimum_bandwidth_rule(rule_id, policy_id, body)\
+ .get(ruleType)
+ return MinimumBandwidthRule(minbandwidth_update)
+
+
+def minimum_bandwidth_rule_delete(request, policy_id, rule_id):
+ """Deletes a Minimum Bandwidth Rule."""
+
+ neutronclient(request).delete_minimum_bandwidth_rule(rule_id, policy_id)
+
+
+class BandwidthLimitRule(NeutronAPIDictWrapper):
+ """Wrapper for neutron BandwidthLimitRule."""
+
+
+@profiler.trace
+def bandwidth_limit_rule_create(request, policy_id, **kwargs):
+ """Create a Bandwidth Limit rule.
+
+ :param request: request context
+ :param policy_id: Id of the policy
+ :param max_kbps: integer
+ :param max_burst_kbps: integer
+ :param direction: string (egress or ingress)
+ :return: A bandwidth_limit_rule object.
+ """
+ body = {'bandwidth_limit_rule': kwargs}
+ if 'tenant_id' not in kwargs:
+ kwargs['tenant_id'] = request.user.project_id
+ body = {'bandwidth_limit_rule': kwargs}
+ rule = 'bandwidth_limit_rule'
+ bandwidth_limit_rule = neutronclient(request)\
+ .create_bandwidth_limit_rule(policy_id, body).get(rule)
+ return BandwidthLimitRule(bandwidth_limit_rule)
+
+
+@profiler.trace
+def bandwidth_limit_rule_update(request, policy_id, rule_id, **kwargs):
+ """Update a Bandwidth Limit rule.
+
+ :param request: request context
+ :param policy_id: Id of the policy
+ :param max_kbps: integer
+ :param max_burst_kbps: integer
+ :param direction: string (egress or ingress)
+ :return: A bandwidth_limit_rule object.
+ """
+ body = {'bandwidth_limit_rule': kwargs}
+ ruleType = 'bandwidth_limit_rule'
+ bandwidthlimit_update = neutronclient(request)\
+ .update_bandwidth_limit_rule(rule_id, policy_id, body)\
+ .get(ruleType)
+ return BandwidthLimitRule(bandwidthlimit_update)
+
+
+@profiler.trace
+def bandwidth_limit_rule_delete(request, policy_id, rule_id):
+ """Deletes a Bandwidth Limit Rule."""
+ neutronclient(request).delete_bandwidth_limit_rule(rule_id, policy_id)
+
+
+class MinimumPacketRateRule(NeutronAPIDictWrapper):
+ """Wrapper for neutron MinimumPacketRateRule."""
+
+
+@profiler.trace
+def minimum_packet_rate_rule_create(request, policy_id, **kwargs):
+ """Create a Minimum Packet Rate rule.
+
+ :param request: request context
+ :param policy_id: Id of the policy
+ :param min_kpps: integer
+ :param direction: string (egress or ingress)
+ :return: A minimum_packet_rate_rule object.
+ """
+ body = {'minimum_packet_rate_rule': kwargs}
+ if 'tenant_id' not in kwargs:
+ kwargs['tenant_id'] = request.user.project_id
+ body = {'minimum_packet_rate_rule': kwargs}
+ rule = 'minimum_packet_rate_rule'
+ minimum_packet_rate_rule = neutronclient(request)\
+ .create_minimum_packet_rate_rule(policy_id, body).get(rule)
+ return MinimumPacketRateRule(minimum_packet_rate_rule)
+
+
+@profiler.trace
+def minimum_packet_rate_rule_update(request, policy_id, rule_id, **kwargs):
+ """Update a Minimum Packet Rate rule.
+
+ :param request: request context
+ :param policy_id: Id of the policy
+ :param min_kpps: integer
+ :param direction: string (egress or ingress)
+ :return: A minimum_packet_rate_rule object.
+ """
+ body = {'minimum_packet_rate_rule': kwargs}
+ ruleType = 'minimum_packet_rate_rule'
+ minpacketrate_update = neutronclient(request)\
+ .update_minimum_packet_rate_rule(rule_id, policy_id, body)\
+ .get(ruleType)
+ return MinimumPacketRateRule(minpacketrate_update)
+
+
+def minimum_packet_rate_rule_delete(request, policy_id, rule_id):
+ """Deletes a Minimum Packet Rate Rule."""
+ neutronclient(request).delete_minimum_packet_rate_rule(rule_id, policy_id)
+
+
@profiler.trace
def list_availability_zones(request, resource=None, state=None):
az_list = neutronclient(request).list_availability_zones().get(
diff --git a/openstack_dashboard/api/rest/neutron.py b/openstack_dashboard/api/rest/neutron.py
index ae1e7944d..df5df49fd 100644
--- a/openstack_dashboard/api/rest/neutron.py
+++ b/openstack_dashboard/api/rest/neutron.py
@@ -330,3 +330,157 @@ class QoSPolicy(generic.View):
"""Get a specific policy"""
policy = api.neutron.policy_get(request, policy_id)
return policy.to_dict()
+
+
+@urls.register
+class MinimumBandwidthRules(generic.View):
+ """API for Minimum Bandwidth Rule create."""
+ url_regex = (
+ r'neutron/qos/policies/' +
+ r'(?P<policy_id>[^/]+)/minimum_bandwidth_rules/$')
+
+ @rest_utils.ajax(data_required=True)
+ def post(self, req, policy_id):
+ minimum_bandwidth_rule = api.neutron.minimum_bandwidth_rule_create(
+ req, policy_id, **req.DATA)
+ return rest_utils.CreatedResponse(
+ '/api/neutron/qospolicies/minimumbandwidthrules/%s'
+ % minimum_bandwidth_rule.id,
+ minimum_bandwidth_rule.to_dict()
+ )
+
+
+@urls.register
+class MinimumBandwidthRule(generic.View):
+ """API for Minimum Bandwidth Rule update and delete."""
+ url_regex = (
+ r'neutron/qos/policies/' +
+ r'(?P<policy_id>[^/]+)/minimum_bandwidth_rules/(?P<rule_id>[^/]+)$'
+ )
+
+ @rest_utils.ajax(data_required=True)
+ def patch(self, req, policy_id, rule_id):
+ """Update a QoS Minimum Bandwidth rule."""
+ return api.neutron.minimum_bandwidth_rule_update(
+ req, policy_id, rule_id, **req.DATA)
+
+ @rest_utils.ajax()
+ def delete(self, req, policy_id, rule_id):
+ """Delete a QoS Minimum Badwidth rule"""
+ api.neutron.minimum_bandwidth_rule_delete(req, policy_id, rule_id)
+
+
+@urls.register
+class DSCPMarkingRules(generic.View):
+ """API for DSCP Marking Rule create"""
+ url_regex = (
+ r'neutron/qos/policies/(?P<policy_id>[^/]+)' +
+ r'/dscp_marking_rules/$')
+
+ @rest_utils.ajax(data_required=True)
+ def post(self, req, policy_id):
+ """Create QoS DSCP Marking rules."""
+ dscp_marking_rule = api.neutron.dscp_marking_rule_create(
+ req, policy_id, **req.DATA)
+ return rest_utils.CreatedResponse(
+ '/api/neutron/qospolicies/dscpmarkingrules/%s'
+ % dscp_marking_rule.id,
+ dscp_marking_rule.to_dict()
+ )
+
+
+@urls.register
+class DSCPMarkingRule(generic.View):
+ """API for DSCP Marking Rule Delete and Update"""
+ url_regex = (
+ r'neutron/qos/policies/(?P<policy_id>[^/]+)' +
+ r'/dscp_marking_rules/(?P<rule_id>[^/]+)$')
+
+ @rest_utils.ajax(data_required=True)
+ def patch(self, req, policy_id, rule_id):
+ """Update a qos DSCP Marking rule."""
+ return api.neutron.dscp_marking_rule_update(
+ req, policy_id, rule_id, **req.DATA)
+
+ @rest_utils.ajax()
+ def delete(self, req, policy_id, rule_id):
+ """Delete a qos DSCP Marking rule."""
+ api.neutron.dscp_marking_rule_delete(req, policy_id, rule_id)
+
+
+@urls.register
+class BandwidthLimitRules(generic.View):
+ """API for Bandwidth Limit Rule Create"""
+ url_regex = (
+ r'neutron/qos/policies/(?P<policy_id>[^/]+)' +
+ r'/bandwidth_limit_rules/$'
+ )
+
+ @rest_utils.ajax(data_required=True)
+ def post(self, req, policy_id):
+ """Create QoS Bandwidth Limit rules."""
+ bandwidth_limit_rule = api.neutron.bandwidth_limit_rule_create(
+ req, policy_id, **req.DATA)
+ return rest_utils.CreatedResponse(
+ '/api/neutron/qospolicies/bandwidthlimitrules/%s'
+ % bandwidth_limit_rule.id,
+ bandwidth_limit_rule.to_dict()
+ )
+
+
+@urls.register
+class BandwidthLimitRule(generic.View):
+ """API for Bandwidth Limit Rule Update and Delete"""
+ url_regex = (
+ r'neutron/qos/policies/(?P<policy_id>[^/]+)' +
+ r'/bandwidth_limit_rules/(?P<rule_id>[^/]+)$')
+
+ @rest_utils.ajax(data_required=True)
+ def patch(self, req, policy_id, rule_id):
+ """Update a QoS Bandwidth Limit rule."""
+ return api.neutron.bandwidth_limit_rule_update(
+ req, policy_id, rule_id, **req.DATA)
+
+ @rest_utils.ajax()
+ def delete(self, req, policy_id, rule_id):
+ """Delete a QoS Bandwidth Limit rule."""
+ api.neutron.bandwidth_limit_rule_delete(req, policy_id, rule_id)
+
+
+@urls.register
+class MinimumPacketRateRules(generic.View):
+ """API for Minimum Packet Rate Rule Create."""
+ url_regex = (
+ r'neutron/qos/policies/' +
+ r'(?P<policy_id>[^/]+)/minimum_packet_rate_rules/$')
+
+ @rest_utils.ajax(data_required=True)
+ def post(self, req, policy_id):
+ """Create QoS Minimum Packet Rate rules."""
+ minimum_packet_rate_rule = api.neutron.minimum_packet_rate_rule_create(
+ req, policy_id, **req.DATA)
+ return rest_utils.CreatedResponse(
+ '/api/neutron/qospolicies/minimumpacketraterules/%s'
+ % minimum_packet_rate_rule.id,
+ minimum_packet_rate_rule.to_dict()
+ )
+
+
+@urls.register
+class MinimumPacketRateRule(generic.View):
+ """API for Updating and Deleting Minimum Packet Rate Rule"""
+ url_regex = (
+ r'neutron/qos/policies/' +
+ r'(?P<policy_id>[^/]+)/minimum_packet_rate_rules/(?P<rule_id>[^/]+)$'
+ )
+
+ @rest_utils.ajax(data_required=True)
+ def patch(self, req, policy_id, rule_id):
+ """Update a QoS Minimum Packet Rate rule."""
+ return api.neutron.minimum_packet_rate_rule_update(
+ req, policy_id, rule_id, **req.DATA)
+
+ @rest_utils.ajax()
+ def delete(self, req, policy_id, rule_id):
+ """Delete a QoS Minimum Packet Rate rule."""
+ api.neutron.minimum_packet_rate_rule_delete(req, policy_id, rule_id)
diff --git a/openstack_dashboard/static/app/core/network_qos/actions/actions.module.js b/openstack_dashboard/static/app/core/network_qos/actions/actions.module.js
index 31239d943..2611c256f 100644
--- a/openstack_dashboard/static/app/core/network_qos/actions/actions.module.js
+++ b/openstack_dashboard/static/app/core/network_qos/actions/actions.module.js
@@ -33,6 +33,9 @@
'horizon.framework.conf.resource-type-registry.service',
'horizon.app.core.network_qos.actions.create.service',
'horizon.app.core.network_qos.actions.delete.service',
+ 'horizon.app.core.network_qos.actions.add-rule.service',
+ 'horizon.app.core.network_qos.actions.edit-rule.service',
+ 'horizon.app.core.network_qos.actions.delete-rule.service',
'horizon.app.core.network_qos.resourceType'
];
@@ -40,6 +43,9 @@
registry,
createService,
deleteService,
+ addRuleService,
+ editRuleService,
+ deleteRuleService,
qosResourceTypeCode
) {
var qosResourceType = registry.getResourceType(qosResourceTypeCode);
@@ -57,6 +63,34 @@
qosResourceType.itemActions
.append({
+ id: 'addRulePolicyAction',
+ service: addRuleService,
+ template: {
+ text: gettext('Add Rule')
+ }
+ });
+
+ qosResourceType.itemActions
+ .append({
+ id: 'editRuleAction',
+ service: editRuleService,
+ template: {
+ text: gettext('Edit Rule')
+ }
+ });
+
+ qosResourceType.itemActions
+ .append({
+ id: 'deleteRuleAction',
+ service: deleteRuleService,
+ template: {
+ text: gettext('Delete Rule'),
+ type: 'delete'
+ }
+ });
+
+ qosResourceType.itemActions
+ .append({
id: 'deletePolicyAction',
service: deleteService,
template: {
diff --git a/openstack_dashboard/static/app/core/network_qos/actions/actions.module.spec.js b/openstack_dashboard/static/app/core/network_qos/actions/actions.module.spec.js
index 34cb8c518..72df2f128 100644
--- a/openstack_dashboard/static/app/core/network_qos/actions/actions.module.spec.js
+++ b/openstack_dashboard/static/app/core/network_qos/actions/actions.module.spec.js
@@ -28,6 +28,21 @@
expect(actionHasId(actions, 'createPolicyAction')).toBe(true);
});
+ it('registers Create Rule as a global action', function() {
+ var actions = registry.getResourceType('OS::Neutron::QoSPolicy').itemActions;
+ expect(actionHasId(actions, 'addRulePolicyAction')).toBe(true);
+ });
+
+ it('registers Edit Rule as a global action', function() {
+ var actions = registry.getResourceType('OS::Neutron::QoSPolicy').itemActions;
+ expect(actionHasId(actions, 'editRuleAction')).toBe(true);
+ });
+
+ it('registers Delete Rule as a global action', function() {
+ var actions = registry.getResourceType('OS::Neutron::QoSPolicy').itemActions;
+ expect(actionHasId(actions, 'deleteRuleAction')).toBe(true);
+ });
+
it('registers Delete Policy as an item action', function() {
var actions = registry.getResourceType('OS::Neutron::QoSPolicy').itemActions;
expect(actionHasId(actions, 'deletePolicyAction')).toBe(true);
diff --git a/openstack_dashboard/static/app/core/network_qos/actions/add-rule.action.service.js b/openstack_dashboard/static/app/core/network_qos/actions/add-rule.action.service.js
new file mode 100644
index 000000000..50f4f6da7
--- /dev/null
+++ b/openstack_dashboard/static/app/core/network_qos/actions/add-rule.action.service.js
@@ -0,0 +1,182 @@
+/* Liscensed 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.
+ */
+
+(function() {
+ 'use strict';
+
+ /**
+ * @ngdoc overview
+ * @ngname horizon.app.core.network_qos.actions.add-rule.service
+ *
+ * @description
+ * Provides all of the actions for creating rule to a network qos policy.
+ */
+
+ angular
+ .module('horizon.app.core.network_qos')
+ .factory('horizon.app.core.network_qos.actions.add-rule.service', addRuleService);
+
+ addRuleService.$inject = [
+ 'horizon.app.core.openstack-service-api.neutron',
+ 'horizon.app.core.openstack-service-api.policy',
+ 'horizon.app.core.network_qos.resourceType',
+ 'horizon.framework.widgets.form.ModalFormService',
+ 'horizon.framework.widgets.toast.service',
+ 'horizon.framework.util.actions.action-result.service',
+ 'horizon.app.core.network_qos.basePath'
+ ];
+
+ function addRuleService(
+ neutronAPI,
+ policy,
+ resourceType,
+ modal,
+ toast,
+ actionResultService,
+ basePath
+ ) {
+
+ var caption = gettext("Add Rule");
+
+ // schema
+ var schema = {
+ type: "object",
+ properties: {
+ qospolicy: {
+ title: gettext('QoS Policy Id'),
+ type: 'string',
+ readOnly: true
+ },
+ qospolicyname: {
+ title: gettext('QoS Policy Name'),
+ type: 'string',
+ readOnly: true
+ },
+ type: {
+ title: gettext('Type'),
+ type: 'string',
+ enum: ['bandwidth_limit', 'dscp_marking', 'minimum_bandwidth', 'minimum_packet_rate']
+ }
+ },
+ required: ['type']
+ };
+
+ // form
+ var form = [
+ {
+ type: "section",
+ htmlClass: "row",
+ items: [
+ {
+ type: "section",
+ htmlClass: "col-sm-12",
+ items: [
+ {
+ key: ["qospolicy", "qospolicyname", "type"],
+ type: "template",
+ templateUrl: basePath + "actions/add-rule.html"
+ }
+ ]
+ }
+ ]
+ }
+ ];
+
+ // model
+ var model = {};
+
+ var service = {
+ allowed: allowed,
+ perform: perform,
+ submit: submit
+ };
+
+ return service;
+
+ //////////////
+
+ function allowed() {
+ return policy.ifAllowed(
+ {rules: [['network', 'create_policy_dscp_marking_rule'],
+ ['network', 'create_policy_minimum_bandwidth_rule'],
+ ['network', 'create_policy_bandwidth_limit_rule']]});
+ }
+
+ function perform(qospolicy) {
+ model = {"qospolicy": qospolicy.id, "qospolicyname": qospolicy.name};
+ var config = {
+ "title": caption,
+ "submitText": caption,
+ "schema": schema,
+ "form": form,
+ "model": model,
+ "submitIcon": "plus",
+ "helpUrl": basePath + "actions/rule.description.html"
+ };
+ return modal.open(config).then(submit);
+ }
+
+ function submit(context) {
+ var id = context.model.qospolicy;
+ var data = {};
+ if (context.model.rule_type === 'dscp_marking') {
+ data = {
+ dscp_mark: context.model.dscpmarking
+ };
+ return neutronAPI.createDSCPMarkingRule(id, data).then(onAddRule);
+ }
+ else if (context.model.rule_type === 'minimum_bandwidth') {
+ data = {
+ direction: context.model.direction,
+ min_kbps: context.model.minkbps
+ };
+ return neutronAPI.createMinimumBandwidthRule(id, data).then(onAddRule);
+ }
+ else if (context.model.rule_type === 'bandwidth_limit') {
+ var direction = context.model.direction !== undefined
+ ? context.model.direction : 'egress';
+ data = {
+ direction: direction,
+ max_burst_kbps: context.model.maxburstkbps,
+ max_kbps: context.model.maxkbps
+ };
+ return neutronAPI.createBandwidthLimitRule(id, data).then(onAddRule);
+ }
+ else if (context.model.rule_type === 'minimum_packet_rate') {
+ data = {
+ direction: context.model.direction,
+ min_kpps: context.model.minkpps
+ };
+ return neutronAPI.createMinimumPacketRateRule(id, data).then(onAddRule);
+ }
+ }
+
+ /**
+ * @ngdoc function
+ * @name onAddRule
+ * @description
+ * Informs the user about the added rule.
+ */
+
+ function onAddRule(response) {
+ var ruleRes = response.data;
+ toast.add('success', interpolate('QoS Policy Rule successfully created'));
+
+ return actionResultService.getActionResult()
+ .created(resourceType, ruleRes.id)
+ .result;
+ }
+
+ }
+})();
+
diff --git a/openstack_dashboard/static/app/core/network_qos/actions/add-rule.action.service.spec.js b/openstack_dashboard/static/app/core/network_qos/actions/add-rule.action.service.spec.js
new file mode 100644
index 000000000..ca8c4eec7
--- /dev/null
+++ b/openstack_dashboard/static/app/core/network_qos/actions/add-rule.action.service.spec.js
@@ -0,0 +1,154 @@
+/* Liscensed 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.
+ */
+
+(function() {
+ 'use strict';
+
+ describe('horizon.app.core.network_qos.actions.add-rule.service', function() {
+
+ var $q, $scope, neutronAPI, service, modalFormService, toast, nbwdLmtRule,
+ qosPolicy, dscpRule, minBwdRule, bwdLmtRule, policyAPI, minpckRtRule;
+
+ ///////////////////////
+
+ beforeEach(module('horizon.framework'));
+ beforeEach(module('horizon.app.core'));
+ beforeEach(module('horizon.app.core.network_qos'));
+
+ beforeEach(inject(function($injector, _$rootScope_, _$q_) {
+ $scope = _$rootScope_.$new();
+ $q = _$q_;
+ service = $injector.get('horizon.app.core.network_qos.actions.add-rule.service');
+ toast = $injector.get('horizon.framework.widgets.toast.service');
+ policyAPI = $injector.get('horizon.app.core.openstack-service-api.policy');
+ modalFormService = $injector.get('horizon.framework.widgets.form.ModalFormService');
+ neutronAPI = $injector.get('horizon.app.core.openstack-service-api.neutron');
+ qosPolicy = {model: {id: '1', name: 'qos', description: "qos rules", shared: 'yes'}};
+ dscpRule = {model: {qospolicy: '1', rule_type: "dscp_marking", dscpmarking: 0}};
+ minBwdRule = {
+ model: {
+ qospolicy: '1', rule_type: "minimum_bandwidth",
+ minkbps: 128, direction: "egress"
+ }};
+ minpckRtRule = {
+ model: {
+ qospolicy: '1', rule_type: "minimum_packet_rate",
+ minkpps: 1000, direction: "egress"
+ }};
+ bwdLmtRule = {
+ model: {
+ qospolicy: '1', rule_type: "bandwidth_limit",
+ maxkbps: 1000, direction: "egress", maxburstkbps: 1100
+ }};
+ nbwdLmtRule = {
+ model: {
+ qospolicy: '1', rule_type: "bandwidth_limit",
+ maxkbps: 1000, direction: undefined, maxburstkbps: 1100
+ }};
+ }));
+
+ it('should check policy is allowed or not', function() {
+ spyOn(policyAPI, 'ifAllowed').and.callThrough();
+ var allowed = service.allowed();
+ expect(allowed).toBeTruthy();
+ expect(policyAPI.ifAllowed).toHaveBeenCalledWith(
+ { rules: [['network', 'create_policy_dscp_marking_rule'],
+ ['network', 'create_policy_minimum_bandwidth_rule'],
+ ['network', 'create_policy_bandwidth_limit_rule']] });
+ });
+
+ it('should open the modal for selecting rule', function() {
+ spyOn(modalFormService, 'open').and.returnValue($q.defer().promise);
+ service.perform(qosPolicy);
+ expect(modalFormService.open).toHaveBeenCalled();
+ });
+
+ it('should submit DSCP Marking add rule request to neutron', function() {
+ var deferred = $q.defer();
+ var data = {"dscp_mark": 0};
+ spyOn(toast, 'add').and.callFake(angular.noop);
+ spyOn(neutronAPI, 'createDSCPMarkingRule').and.returnValue(deferred.promise);
+ deferred.resolve({data: {dscp_mark: 0, id: '1'}});
+ service.submit(dscpRule).then(service.onAddRule);
+ $scope.$apply();
+ expect(neutronAPI.createDSCPMarkingRule).toHaveBeenCalledWith(
+ '1', data);
+ expect(toast.add).toHaveBeenCalledWith(
+ 'success', 'QoS Policy Rule successfully created'
+ );
+ });
+
+ it('should submit Minimum Bandwidth add rule request to neutron', function() {
+ var deferred = $q.defer();
+ var data = {"min_kbps": 128, "direction": "egress"};
+ spyOn(neutronAPI, 'createMinimumBandwidthRule').and.returnValue(deferred.promise);
+ spyOn(toast, 'add').and.callFake(angular.noop);
+ deferred.resolve({data: {mainbps: 128, direction: "egress", id:'1'}});
+ service.submit(minBwdRule).then(service.onAddRule);
+ $scope.$apply();
+ expect(neutronAPI.createMinimumBandwidthRule).toHaveBeenCalledWith(
+ '1', data);
+ expect(toast.add).toHaveBeenCalledWith(
+ 'success', 'QoS Policy Rule successfully created'
+ );
+ });
+
+ it('should submit Bandwidth Limit add rule request to neutron', function() {
+ var deferred = $q.defer();
+ var data = {"max_kbps": 1000, "direction": "egress", "max_burst_kbps": 1100};
+ spyOn(neutronAPI, 'createBandwidthLimitRule').and.returnValue(deferred.promise);
+ spyOn(toast, 'add').and.callFake(angular.noop);
+ deferred.resolve({data: {"max_kbps": 1000, "direction": "egress",
+ "max_burst_kbps": 1100, id: '1'}});
+ service.submit(bwdLmtRule).then(service.onAddRule);
+ $scope.$apply();
+ expect(neutronAPI.createBandwidthLimitRule).toHaveBeenCalledWith(
+ '1', data);
+ expect(toast.add).toHaveBeenCalledWith(
+ 'success', 'QoS Policy Rule successfully created'
+ );
+ });
+
+ it('should submit Bandwidth Limit with undefined add rule request to neutron', function() {
+ var deferred = $q.defer();
+ var data = {"max_kbps": 1000, "direction": "egress", "max_burst_kbps": 1100};
+ spyOn(neutronAPI, 'createBandwidthLimitRule').and.returnValue(deferred.promise);
+ spyOn(toast, 'add').and.callFake(angular.noop);
+ deferred.resolve({data: {"max_kbps": 1000, "direction": "egress",
+ "max_burst_kbps": 1100, id: '1'}});
+ service.submit(nbwdLmtRule).then(service.onAddRule);
+ $scope.$apply();
+ expect(neutronAPI.createBandwidthLimitRule).toHaveBeenCalledWith(
+ '1', data);
+ expect(toast.add).toHaveBeenCalledWith(
+ 'success', 'QoS Policy Rule successfully created'
+ );
+ });
+
+ it('should submit add Minimum Packet Rate rule request to neutron', function() {
+ var deferred = $q.defer();
+ var data = {"min_kpps": 1000, "direction": "egress"};
+ spyOn(neutronAPI, 'createMinimumPacketRateRule').and.returnValue(deferred.promise);
+ spyOn(toast, 'add').and.callFake(angular.noop);
+ deferred.resolve({data: {minkpps: 1000, direction: "egress", id:'1'}});
+ service.submit(minpckRtRule).then(service.onAddRule);
+ $scope.$apply();
+ expect(neutronAPI.createMinimumPacketRateRule).toHaveBeenCalledWith(
+ '1', data);
+ expect(toast.add).toHaveBeenCalledWith(
+ 'success', 'QoS Policy Rule successfully created'
+ );
+ });
+
+ });
+})();
diff --git a/openstack_dashboard/static/app/core/network_qos/actions/add-rule.controller.js b/openstack_dashboard/static/app/core/network_qos/actions/add-rule.controller.js
new file mode 100644
index 000000000..a00025708
--- /dev/null
+++ b/openstack_dashboard/static/app/core/network_qos/actions/add-rule.controller.js
@@ -0,0 +1,74 @@
+/**
+ * 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.
+ */
+
+(function() {
+ 'use strict';
+
+ /**
+ * @ngdoc controller
+ * @name horizon.app.core.network_qos.actions.AddQoSRuleController
+ * @ngController
+ *
+ * @description
+ * Controller for the adding rules for qos policy
+ */
+ angular
+ .module('horizon.app.core.network_qos.actions')
+ .controller('horizon.app.core.network_qos.actions.AddQoSRuleController',
+ addQoSRuleController);
+
+ addQoSRuleController.$inject = [
+ '$scope'
+ ];
+
+ function addQoSRuleController($scope) {
+ var ctrl = this;
+ ctrl.qospolicy = $scope.model.qospolicy;
+ ctrl.qospolicyname = $scope.model.qospolicyname;
+ ctrl.rule_types = {
+ 'bandwidth_limit': gettext("Bandwidth Limit"),
+ 'dscp_marking': gettext("DSCP Marking"),
+ 'minimum_bandwidth': gettext("Minimum Bandwidth"),
+ 'minimum_packet_rate': gettext("Minimum Packet Rate")
+ };
+ ctrl.directions = {
+ "egress": gettext("egress"),
+ "ingress": gettext("ingress")
+ };
+ ctrl.ppsDirections = {
+ "egress": gettext("egress"),
+ "ingress": gettext("ingress"),
+ "any": gettext("any")
+ };
+ ctrl.onRuleTypeChange = function(ruleType) {
+ $scope.model.rule_type = ruleType;
+ };
+ ctrl.bwdLimit = function(bwd) {
+ $scope.model.maxkbps = bwd.maxkbps;
+ $scope.model.maxburstkbps = bwd.maxburstkbps;
+ $scope.model.direction = bwd.direction || 'egress';
+ };
+ ctrl.onDSCPChange = function(dscpmark) {
+ $scope.model.dscpmarking = dscpmark;
+ };
+ ctrl.minBandwidth = function(mb) {
+ $scope.model.minkbps = mb.minkbps;
+ $scope.model.direction = mb.direction || 'egress';
+ };
+ ctrl.minPacketRate = function(mpr) {
+ $scope.model.minkpps = mpr.minkpps;
+ $scope.model.direction = mpr.direction || 'egress';
+ };
+ }
+})();
diff --git a/openstack_dashboard/static/app/core/network_qos/actions/add-rule.controller.spec.js b/openstack_dashboard/static/app/core/network_qos/actions/add-rule.controller.spec.js
new file mode 100644
index 000000000..911afbe97
--- /dev/null
+++ b/openstack_dashboard/static/app/core/network_qos/actions/add-rule.controller.spec.js
@@ -0,0 +1,130 @@
+/*
+ * 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.
+ */
+
+(function() {
+ 'use strict';
+
+ describe('qos rules datails', function() {
+
+ var ctrl, rules, directions, ppsDirections, $controller, $scope,
+ $rootScope, dscp, minBwd, nminBwd, bwdLmt, nbwdLmt, minPckRt,
+ nminPckRt;
+
+ beforeEach(module('horizon.app.core.network_qos'));
+
+ beforeEach(inject(function(_$controller_, _$rootScope_) {
+ $controller = _$controller_;
+ $rootScope = _$rootScope_;
+ $scope = $rootScope.$new();
+
+ $scope = {
+ model: {
+ qospolicy: "1",
+ qospolicyname: "test-qos"
+ }
+ };
+
+ ctrl = $controller('horizon.app.core.network_qos.actions.AddQoSRuleController',
+ {
+ $scope: $scope
+ }
+ );
+
+ rules = {
+ 'bandwidth_limit': "Bandwidth Limit",
+ 'dscp_marking': "DSCP Marking",
+ 'minimum_bandwidth': "Minimum Bandwidth",
+ 'minimum_packet_rate': "Minimum Packet Rate"
+ };
+ directions = {
+ "egress": "egress",
+ "ingress": "ingress"
+ };
+ ppsDirections = {
+ "egress": "egress",
+ "ingress": "ingress",
+ "any": "any"
+ };
+ dscp = {
+ model: {
+ dscpmarking: 0
+ }
+ };
+ minBwd = {
+ model: {
+ minkbps: 1000,
+ direction: 'egress'
+ }
+ };
+ nminBwd = {
+ model: {
+ minkbps: 1000,
+ direction: ''
+ }
+ };
+ bwdLmt = {
+ model: {
+ maxkbps: 2000,
+ maxburstkbps: 3000,
+ direction: 'egress'
+ }
+ };
+ nbwdLmt = {
+ model: {
+ maxkbps: 2000,
+ maxburstkbps: 3000,
+ direction: ''
+ }
+ };
+ minPckRt = {
+ model: {
+ minkpps: 1000,
+ direction: 'egress'
+ }
+ };
+ nminPckRt = {
+ model: {
+ minkpps: 1000,
+ direction: ''
+ }
+ };
+ }));
+
+ it('sets ctrl', inject(function() {
+ expect(ctrl.qospolicy).toEqual($scope.model.qospolicy);
+ expect(ctrl.qospolicy).not.toEqual('2');
+ expect(ctrl.qospolicyname).toEqual($scope.model.qospolicyname);
+ expect(ctrl.rule_types).toEqual(rules);
+ ctrl.onRuleTypeChange('dscp_mark');
+ expect(ctrl.onRuleTypeChange).toBeDefined();
+ expect(ctrl.directions).toEqual(directions);
+ expect(ctrl.ppsDirections).toEqual(ppsDirections);
+ ctrl.onDSCPChange(dscp.model);
+ expect(ctrl.onDSCPChange).toBeDefined();
+ ctrl.minBandwidth(minBwd.model);
+ expect(ctrl.minBandwidth).toBeDefined();
+ ctrl.minBandwidth(nminBwd.model);
+ expect(ctrl.minBandwidth).toBeDefined();
+ ctrl.bwdLimit(bwdLmt.model);
+ expect(ctrl.bwdLimit).toBeDefined();
+ ctrl.bwdLimit(nbwdLmt.model);
+ expect(ctrl.nbwdLimit).not.toBeDefined();
+ ctrl.minPacketRate(minPckRt.model);
+ expect(ctrl.minPacketRate).toBeDefined();
+ ctrl.minPacketRate(nminPckRt.model);
+ expect(ctrl.minPacketRate).toBeDefined();
+ }));
+
+ });
+})();
diff --git a/openstack_dashboard/static/app/core/network_qos/actions/add-rule.html b/openstack_dashboard/static/app/core/network_qos/actions/add-rule.html
new file mode 100644
index 000000000..71a4949eb
--- /dev/null
+++ b/openstack_dashboard/static/app/core/network_qos/actions/add-rule.html
@@ -0,0 +1,98 @@
+<div ng-controller="horizon.app.core.network_qos.actions.AddQoSRuleController as ctrl" class="form-group">
+ <label class="control-label required">
+ <translate>QoS Policy ID</translate>
+ <span class="hz-icon-required fa fa-asterisk"></span>
+ </label>
+ <input class="form-control ng-pristine ng-untouched ng-valid" ng-value="ctrl.qospolicy" name="qospolicyid" readonly>
+ <label class="control-label required">
+ <translate>QoS Policy Name</translate>
+ <span class="hz-icon-required fa fa-asterisk"></span>
+ </label>
+ <input class="form-control ng-pristine ng-untouched ng-valid" ng-value="ctrl.qospolicyname" name="qospolicyname" readonly>
+ <label class="control-label required">
+ <translate>Rule Type</translate>
+ <span class="hz-icon-required fa fa-asterisk"></span>
+ </label>
+ <select class="form-control switchable ng-pristine ng-untouched ng-valid"
+ ng-model="rule_type"
+ ng-options="val as label for (val, label) in ctrl.rule_types"
+ name="add-rule"
+ ng-change="ctrl.onRuleTypeChange(rule_type)">
+ </select>
+ <div ng-show="rule_type === 'bandwidth_limit'">
+ <label class="control-label required">
+ <translate>Max bandwidth (in kbps)</translate>
+ <span class="hz-icon-required fa fa-asterisk"></span>
+ </label>
+ <input class="form-control ng-pristine ng-untouched ng-valid"
+ ng-model="bwd.maxkbps"
+ name="maxkbps"
+ ng-change="ctrl.bwdLimit(bwd)">
+ <label class="control-label required">
+ <translate>Max Burst Size (in kbps)</translate>
+ </label>
+ <input class="form-control ng-pristine ng-untouched ng-valid"
+ ng-model="bwd.maxburstkbps"
+ name="maxburstkbps"
+ ng-change="ctrl.bwdLimit(bwd)">
+ <label class="control-label required">
+ <translate>Direction</translate>
+ </label>
+ <select class="form-control switchable ng-pristine ng-untouched ng-valid"
+ ng-model="bwd.direction"
+ ng-options="val as label for (val, label) in ctrl.directions"
+ name="direction"
+ ng-change="ctrl.bwdLimit(bwd)">
+ </select>
+ </div>
+ <div ng-show="rule_type === 'dscp_marking'">
+ <label class="control-label required">
+ <translate>DSCP mark</translate>
+ <span class="hz-icon-required fa fa-asterisk"></span>
+ </label>
+ <input class="form-control ng-pristine ng-untouched ng-valid"
+ ng-model="dscpmark"
+ name="dscpmarking"
+ placeholder="valid DSCP marks are:
+ 0, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 46, 48, 56"
+ ng-change="ctrl.onDSCPChange(dscpmark)">
+ </div>
+ <div ng-show="rule_type === 'minimum_bandwidth'">
+ <label class="control-label required">
+ <translate>Minimum bandwidth (in kbps)</translate>
+ <span class="hz-icon-required fa fa-asterisk"></span>
+ </label>
+ <input class="form-control ng-pristine ng-untouched ng-valid"
+ ng-model="mb.minkbps"
+ name="minkbps"
+ ng-change="ctrl.minBandwidth(mb)">
+ <label class="control-label required">
+ <translate>Direction</translate>
+ </label>
+ <select class="form-control switchable ng-pristine ng-untouched ng-valid"
+ ng-model="mb.direction"
+ ng-options="val as label for (val, label) in ctrl.directions"
+ name="direction"
+ ng-change="ctrl.minBandwidth(mb)">
+ </select>
+ </div>
+ <div ng-show="rule_type === 'minimum_packet_rate'">
+ <label class="control-label required">
+ <translate>Minimum packet rate (in kpps)</translate>
+ <span class="hz-icon-required fa fa-asterisk"></span>
+ </label>
+ <input class="form-control ng-pristine ng-untouched ng-valid"
+ ng-model="mpr.minkpps"
+ name="minkpps"
+ ng-change="ctrl.minPacketRate(mpr)">
+ <label class="control-label required">
+ <translate>Direction</translate>
+ </label>
+ <select class="form-control switchable ng-pristine ng-untouched ng-valid"
+ ng-model="mpr.direction"
+ ng-options="val as label for (val, label) in ctrl.ppsDirections"
+ name="direction"
+ ng-change="ctrl.minPacketRate(mpr)">
+ </select>
+ </div>
+ </div> \ No newline at end of file
diff --git a/openstack_dashboard/static/app/core/network_qos/actions/delete-rule.action.service.js b/openstack_dashboard/static/app/core/network_qos/actions/delete-rule.action.service.js
new file mode 100644
index 000000000..f23689671
--- /dev/null
+++ b/openstack_dashboard/static/app/core/network_qos/actions/delete-rule.action.service.js
@@ -0,0 +1,117 @@
+/* Liscensed 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.
+ */
+
+(function() {
+ 'use strict';
+
+ /**
+ * @ngdoc overview
+ * @ngname horizon.app.core.network_qos.actions.delete-rule.service
+ *
+ * @description
+ * Provides all of the actions for deleting rule to a network qos policy.
+ */
+
+ angular
+ .module('horizon.app.core.network_qos')
+ .factory('horizon.app.core.network_qos.actions.delete-rule.service', deleteRuleService);
+
+ deleteRuleService.$inject = [
+ 'horizon.app.core.openstack-service-api.neutron',
+ 'horizon.app.core.openstack-service-api.policy',
+ 'horizon.app.core.network_qos.actions.deleteRuleWorkflow',
+ 'horizon.app.core.network_qos.resourceType',
+ 'horizon.framework.widgets.form.ModalFormService',
+ 'horizon.framework.widgets.toast.service',
+ 'horizon.framework.util.actions.action-result.service',
+ 'horizon.framework.widgets.modal.deleteModalService'
+ ];
+
+ function deleteRuleService(
+ neutronAPI,
+ policy,
+ workflow,
+ resourceType,
+ modalFormService,
+ toast,
+ actionResultService
+ ) {
+
+ var service = {
+ allowed: allowed,
+ perform: perform,
+ submit: submit
+ };
+
+ return service;
+
+ //////////////
+
+ function allowed() {
+ return policy.ifAllowed(
+ {rules: [['network', 'delete_policy_bandwidth_limit_rule'],
+ ['network', 'delete_policy_dscp_marking_rule'],
+ ['network', 'delete_policy_minimum_bandwidth_rule']]});
+ }
+
+ function perform(qospolicy) {
+ if (qospolicy.rules.length !== 0) {
+ var config = workflow.init(qospolicy);
+ config.title = gettext("Delete Rule");
+ config.model.qospolicy = qospolicy.id;
+ config.model.qospolicyname = qospolicy.name;
+ config.model.rules = qospolicy.rules;
+ config.submitText = 'Delete';
+ config.submitIcon = 'delete';
+ return modalFormService.open(config).then(submit);
+ }
+ else {
+ toast.add('info', interpolate(
+ gettext('There are no rules to delete.')));
+ return actionResultService.getActionResult().result;
+ }
+ }
+
+ function submit(context) {
+ var id = context.model.qospolicy;
+ var ruleid = [context.model.ruleid];
+ var ruleType = '';
+ angular.forEach(context.model.rules, function(k) {
+ if ((k.id).toString() === (ruleid).toString()) {
+ ruleType = (k.type).toString();
+ }
+ }, this);
+ if (ruleType === 'bandwidth_limit') {
+ return neutronAPI.deleteBandwidthLimitRule(id, ruleid).then(onDeleteRule);
+ }
+ else if (ruleType === 'dscp_marking') {
+ return neutronAPI.deleteDSCPMarkingRule(id, ruleid).then(onDeleteRule);
+ }
+ else if (ruleType === 'minimum_bandwidth') {
+ return neutronAPI.deleteMinimumBandwidthRule(id, ruleid).then(onDeleteRule);
+ }
+ else if (ruleType === 'minimum_packet_rate') {
+ return neutronAPI.deleteMinimumPacketRateRule(id, ruleid).then(onDeleteRule);
+ }
+ }
+
+ function onDeleteRule() {
+ toast.add('success', interpolate(
+ gettext('Qos Policy Rule was successfully deleted.')));
+
+ return actionResultService.getActionResult()
+ .result;
+ }
+ }
+
+})();
diff --git a/openstack_dashboard/static/app/core/network_qos/actions/delete-rule.action.service.spec.js b/openstack_dashboard/static/app/core/network_qos/actions/delete-rule.action.service.spec.js
new file mode 100644
index 000000000..e69fbc511
--- /dev/null
+++ b/openstack_dashboard/static/app/core/network_qos/actions/delete-rule.action.service.spec.js
@@ -0,0 +1,224 @@
+/* Liscensed 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.
+ */
+
+(function() {
+ 'use strict';
+
+ describe('horizon.app.core.network_qos.actions.delete-rule.service', function() {
+
+ var $q, $scope, neutronAPI, service, modalFormService, toast, nqosPolicy, edscpRule,
+ qosPolicy, dscpRule, bwdLmtRule, minBwdRule, policyAPI;
+
+ ///////////////////////
+
+ beforeEach(module('horizon.framework'));
+ beforeEach(module('horizon.app.core'));
+ beforeEach(module('horizon.app.core.network_qos'));
+
+ beforeEach(inject(function($injector, _$rootScope_, _$q_) {
+ $scope = _$rootScope_.$new();
+ $q = _$q_;
+ service = $injector.get('horizon.app.core.network_qos.actions.delete-rule.service');
+ toast = $injector.get('horizon.framework.widgets.toast.service');
+ policyAPI = $injector.get('horizon.app.core.openstack-service-api.policy');
+ modalFormService = $injector.get('horizon.framework.widgets.form.ModalFormService');
+ neutronAPI = $injector.get('horizon.app.core.openstack-service-api.neutron');
+ qosPolicy = {
+ "id": "6",
+ "name": "qos",
+ "description": "qos rules",
+ "shared": "yes",
+ "rules": [
+ {
+ "direction": "egress",
+ "id": "8",
+ "max_burst_kbps": 22000,
+ "max_kbps": 20000,
+ "qos_policy_id": "6",
+ "type": "bandwidth_limit"
+ },
+ {
+ "dscp_mark": 26,
+ "id": "5",
+ "qos_policy_id": "6",
+ "type": "dscp_marking"
+ },
+ {
+ "direction": "egress",
+ "id": "2",
+ "min_kbps": 1000,
+ "qos_policy_id": "6",
+ "type": "minimum_bandwidth"
+ }
+ ]
+ };
+ nqosPolicy = {
+ "id": "6",
+ "name": "qos",
+ "description": "qos rules",
+ "shared": "yes",
+ "rules": []
+ };
+ dscpRule = {
+ "model": {
+ "qospolicy": "6",
+ "qospolicyname": "test",
+ "ruleid": "2",
+ "rules": [
+ {
+ "dscp_mark": 0,
+ "id": "2",
+ "qos_policy_id": "6",
+ "type": "dscp_marking"
+ }
+ ]
+ }
+ };
+ edscpRule = {
+ "model": {
+ "qospolicy": "6",
+ "qospolicyname": "test",
+ "ruleid": "3",
+ "rules": [
+ {
+ "dscp_mark": 0,
+ "id": "2",
+ "qos_policy_id": "6",
+ "type": "dscp_marking"
+ }
+ ]
+ }
+ };
+ minBwdRule = {
+ "model": {
+ "qospolicy": "6",
+ "qospolicyname": "test",
+ "ruleid": "2",
+ "rules": [
+ {
+ "min_kbps": 0,
+ "direction": "egress",
+ "id": 2,
+ "qos_policy_id": "6",
+ "type": "minimum_bandwidth"
+ }
+ ]
+ }
+ };
+ bwdLmtRule = {
+ "model": {
+ "qospolicy": "6",
+ "qospolicyname": "test",
+ "ruleid": "2",
+ "rules": [
+ {
+ "max_kbps": 0,
+ "direction": "egress",
+ "id": 2,
+ "qos_policy_id": "6",
+ "type": "bandwidth_limit"
+ }
+ ]
+ }
+ };
+ }));
+
+ it('should check policy is allowed or not', function() {
+ spyOn(policyAPI, 'ifAllowed').and.callThrough();
+ var allowed = service.allowed();
+ expect(allowed).toBeTruthy();
+ expect(policyAPI.ifAllowed).toHaveBeenCalledWith(
+ { rules: [['network', 'delete_policy_bandwidth_limit_rule'],
+ ['network', 'delete_policy_dscp_marking_rule'],
+ ['network', 'delete_policy_minimum_bandwidth_rule']] });
+ });
+
+ it('should open the modal with existing rule', function() {
+ spyOn(modalFormService, 'open').and.returnValue($q.defer().promise);
+
+ service.perform(qosPolicy);
+
+ expect(modalFormService.open).toHaveBeenCalled();
+ });
+
+ it('should not open the modal', function() {
+ spyOn(modalFormService, 'open').and.returnValue($q.defer().promise);
+ spyOn(toast, 'add').and.callFake(angular.noop);
+
+ service.perform(nqosPolicy);
+
+ expect(modalFormService.open).not.toHaveBeenCalled();
+ expect(toast.add).toHaveBeenCalledWith(
+ 'info', 'There are no rules to delete.'
+ );
+ });
+
+ it('should submit DSCP Marking delete rule request to neutron', function() {
+ var deferred = $q.defer();
+ spyOn(toast, 'add').and.callFake(angular.noop);
+ spyOn(neutronAPI, 'deleteDSCPMarkingRule').and.returnValue(deferred.promise);
+ deferred.resolve({data: {"id": "2", "dscp_mark": 12}});
+ service.submit(dscpRule).then(service.success);
+ $scope.$apply();
+ expect(neutronAPI.deleteDSCPMarkingRule).toHaveBeenCalledWith(
+ qosPolicy.id, [dscpRule.model.ruleid]);
+ expect(toast.add).toHaveBeenCalledWith(
+ 'success', 'Qos Policy Rule was successfully deleted.'
+ );
+ });
+
+ it('should submit DSCP Marking check delete rule request to neutron', function() {
+ var deferred = $q.defer();
+ spyOn(toast, 'add').and.callFake(angular.noop);
+ spyOn(neutronAPI, 'deleteDSCPMarkingRule').and.returnValue(deferred.promise);
+ deferred.resolve({data: {"id": "3", "dscp_mark": 0}});
+ service.submit(edscpRule);
+ $scope.$apply();
+ expect(neutronAPI.deleteDSCPMarkingRule).not.toHaveBeenCalledWith(
+ qosPolicy.id, [dscpRule.model.ruleid]);
+ expect(toast.add).not.toHaveBeenCalledWith(
+ 'success', 'Qos Policy Rule was successfully deleted.'
+ );
+ });
+
+ it('should submit Bandwidth Limit delete rule request to neutron', function() {
+ var deferred = $q.defer();
+ spyOn(toast, 'add').and.callFake(angular.noop);
+ spyOn(neutronAPI, 'deleteBandwidthLimitRule').and.returnValue(deferred.promise);
+ deferred.resolve({data: {"id": "2", "max_kbps": 1000, "direction": "ingress",
+ "max_burst_kbps": 1200}});
+ service.submit(bwdLmtRule).then(service.onDeleteRule);
+ $scope.$apply();
+ expect(neutronAPI.deleteBandwidthLimitRule).toHaveBeenCalledWith(
+ qosPolicy.id, [bwdLmtRule.model.ruleid]);
+ expect(toast.add).toHaveBeenCalledWith(
+ 'success', 'Qos Policy Rule was successfully deleted.'
+ );
+ });
+
+ it('should submit Minimum Bandwidth Limit edit rule request to neutron', function() {
+ var deferred = $q.defer();
+ spyOn(toast, 'add').and.callFake(angular.noop);
+ spyOn(neutronAPI, 'deleteMinimumBandwidthRule').and.returnValue(deferred.promise);
+ deferred.resolve({data: {"id": "2", "min_kbps": 100, "direction": "ingress"}});
+ service.submit(minBwdRule).then(service.success);
+ $scope.$apply();
+ expect(neutronAPI.deleteMinimumBandwidthRule).toHaveBeenCalledWith(
+ qosPolicy.id, [minBwdRule.model.ruleid]);
+ expect(toast.add).toHaveBeenCalledWith(
+ 'success', 'Qos Policy Rule was successfully deleted.'
+ );
+ });
+
+ });
+})();
diff --git a/openstack_dashboard/static/app/core/network_qos/actions/edit-rule.action.service.js b/openstack_dashboard/static/app/core/network_qos/actions/edit-rule.action.service.js
new file mode 100644
index 000000000..cf3337be6
--- /dev/null
+++ b/openstack_dashboard/static/app/core/network_qos/actions/edit-rule.action.service.js
@@ -0,0 +1,173 @@
+/* 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.
+ */
+
+(function() {
+ 'use strict';
+
+ /**
+ * @ngdoc overview
+ * @ngname horizon.app.core.network_qos.actions.edit-rule.service
+ *
+ * @description
+ * Provides all of the actions for editing rule to a network qos policy.
+ */
+
+ angular
+ .module('horizon.app.core.network_qos')
+ .factory('horizon.app.core.network_qos.actions.edit-rule.service', editRuleService);
+
+ editRuleService.$inject = [
+ 'horizon.app.core.openstack-service-api.neutron',
+ 'horizon.app.core.openstack-service-api.policy',
+ 'horizon.app.core.network_qos.resourceType',
+ 'horizon.framework.widgets.form.ModalFormService',
+ 'horizon.framework.widgets.toast.service',
+ 'horizon.framework.util.actions.action-result.service',
+ 'horizon.app.core.network_qos.basePath'
+ ];
+
+ function editRuleService(
+ neutronAPI,
+ policy,
+ resourceType,
+ modalFormService,
+ toast,
+ actionResultService,
+ basePath
+ ) {
+
+ var caption = gettext("Edit Rule");
+
+ var schema = {
+ type: 'object',
+ properties: {
+ qospolicy: {
+ title: gettext('QoSPolicyId'),
+ type: 'string',
+ readOnly: true
+ },
+ qospolicyname: {
+ title: gettext('QoSPolicyName'),
+ type: 'string',
+ readOnly: true
+ },
+ ruleid: {
+ title: gettext('RuleId'),
+ type: 'string'
+ }
+ },
+ required: ['ruleid']
+ };
+
+ var form = [
+ {
+ type: "section",
+ htmlClass: "row",
+ items: [
+ {
+ type: "section",
+ htmlClass: "col-sm-12",
+ items: [
+ {
+ key: ["qospolicy", "qospolicyname", "type"],
+ type: "template",
+ templateUrl: basePath + "actions/edit-rule.html"
+ }
+ ]
+ }
+ ]
+ }
+ ];
+
+ var model = {};
+
+ var service = {
+ allowed: allowed,
+ perform: perform,
+ submit: submit
+ };
+
+ return service;
+
+ //////////////
+
+ function allowed() {
+ return policy.ifAllowed(
+ {rules: [['network', 'update_policy_bandwidth_limit_rule'],
+ ['network', 'update_policy_dscp_marking_rule'],
+ ['network', 'update_policy_minimum_bandwidth_rule']]});
+ }
+
+ function perform(qospolicy) {
+ if (qospolicy.rules.length !== 0) {
+ model = {"qospolicy": qospolicy.id, "qospolicyname": qospolicy.name,
+ "rules": qospolicy.rules};
+ var config = {
+ "title": caption,
+ "submitText": caption,
+ "schema": schema,
+ "form": form,
+ "model": model,
+ "submitIcon": "pen",
+ "helpUrl": basePath + "actions/rule.description.html"
+ };
+ return modalFormService.open(config).then(submit);
+ }
+ else {
+ toast.add('info', interpolate(
+ gettext('There are no rules to modify.')));
+ return actionResultService.getActionResult()
+ .result;
+
+ }
+ }
+
+ function submit(context) {
+ var id = context.model.qospolicy;
+ var ruleid = [context.model.ruleid];
+ var rule = context.model.rule_type;
+ var data = '';
+
+ if (rule === 'bandwidth_limit') {
+ data = {direction: context.model.direction,
+ max_burst_kbps: context.model.maxburstkbps,
+ max_kbps: context.model.maxkbps};
+ return neutronAPI.updateBandwidthRule(id, ruleid, data).then(onEditRule);
+ }
+ else if (rule === 'dscp_marking') {
+ data = { dscp_mark: context.model.dscpmarking };
+ return neutronAPI.updateDSCPMarkingRule(id, ruleid, data).then(onEditRule);
+ }
+ else if (rule === 'minimum_bandwidth') {
+ data = {direction: context.model.direction,
+ min_kbps: context.model.minkbps};
+ return neutronAPI.updateMinimumBandwidthRule(id, ruleid, data).then(onEditRule);
+ }
+ else if (rule === 'minimum_packet_rate') {
+ data = {direction: context.model.direction,
+ min_kpps: context.model.minkpps};
+ return neutronAPI.updateMinimumPacketRateRule(id, ruleid, data).then(onEditRule);
+ }
+ }
+
+ function onEditRule(response) {
+ var qosrule = response.data;
+ toast.add('success', interpolate(
+ gettext('Qos Policy Rule %s was successfully updated.'),[qosrule.id]));
+
+ return actionResultService.getActionResult()
+ .result;
+ }
+
+ }
+})();
diff --git a/openstack_dashboard/static/app/core/network_qos/actions/edit-rule.action.service.spec.js b/openstack_dashboard/static/app/core/network_qos/actions/edit-rule.action.service.spec.js
new file mode 100644
index 000000000..7e6a6b44c
--- /dev/null
+++ b/openstack_dashboard/static/app/core/network_qos/actions/edit-rule.action.service.spec.js
@@ -0,0 +1,244 @@
+/* Liscensed 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.
+ */
+
+(function() {
+ 'use strict';
+
+ describe('horizon.app.core.network_qos.actions.edit-rule.service', function() {
+
+ var $q, $scope, neutronAPI, service, modalFormService, toast, nqosPolicy,
+ qosPolicy, dscpRule, bwdLmtRule, minBwdRule, policyAPI, minPckRtRule;
+
+ ///////////////////////
+
+ beforeEach(module('horizon.framework'));
+ beforeEach(module('horizon.app.core'));
+ beforeEach(module('horizon.app.core.network_qos'));
+
+ beforeEach(inject(function($injector, _$rootScope_, _$q_) {
+ $scope = _$rootScope_.$new();
+ $q = _$q_;
+ service = $injector.get('horizon.app.core.network_qos.actions.edit-rule.service');
+ toast = $injector.get('horizon.framework.widgets.toast.service');
+ policyAPI = $injector.get('horizon.app.core.openstack-service-api.policy');
+ modalFormService = $injector.get('horizon.framework.widgets.form.ModalFormService');
+ neutronAPI = $injector.get('horizon.app.core.openstack-service-api.neutron');
+ qosPolicy = {
+ "id": "6",
+ "name": "qos",
+ "description": "qos rules",
+ "shared": "yes",
+ "rules": [
+ {
+ "direction": "egress",
+ "id": "8",
+ "max_burst_kbps": 22000,
+ "max_kbps": 20000,
+ "qos_policy_id": "6",
+ "type": "bandwidth_limit"
+ },
+ {
+ "dscp_mark": 26,
+ "id": "5",
+ "qos_policy_id": "6",
+ "type": "dscp_marking"
+ },
+ {
+ "direction": "egress",
+ "id": "2",
+ "min_kbps": 1000,
+ "qos_policy_id": "6",
+ "type": "minimum_bandwidth"
+ },
+ {
+ "direction": "egress",
+ "id": "2",
+ "min_kbps": 10000,
+ "qos_policy_id": "6",
+ "type": "minimum_packet_rate"
+ }
+ ]
+ };
+ nqosPolicy = {
+ "id": "6",
+ "name": "qos",
+ "description": "qos rules",
+ "shared": "yes",
+ "rules": []
+ };
+ dscpRule = {
+ "model": {
+ "qospolicy": "6",
+ "qospolicyname": "test",
+ "ruleid": "2",
+ "rule_type": "dscp_marking",
+ "dscpmarking": 26,
+ "rules": [
+ {
+ "dscp_mark": 0,
+ "id": 2,
+ "qos_policy_id": "6",
+ "type": "dscp_marking"
+ }
+ ]
+ }
+ };
+ minBwdRule = {
+ "model": {
+ "qospolicy": "6",
+ "qospolicyname": "test",
+ "ruleid": "2",
+ "rule_type": "minimum_bandwidth",
+ "minkbps": 128,
+ "direction": "egress",
+ "rules": [
+ {
+ "min_kbps": 0,
+ "direction": "egress",
+ "id": 2,
+ "qos_policy_id": "6",
+ "type": "minimum_bandwidth"
+ }
+ ]
+ }
+ };
+ bwdLmtRule = {
+ "model": {
+ "qospolicy": "6",
+ "qospolicyname": "test",
+ "ruleid": "2",
+ "rule_type": "bandwidth_limit",
+ "maxkbps": 1000,
+ "maxburstkbps": 1100,
+ "direction": "egress",
+ "rules": [
+ {
+ "max_kbps": 0,
+ "direction": "egress",
+ "id": 2,
+ "qos_policy_id": "6",
+ "type": "bandwidth_limit"
+ }
+ ]
+ }
+ };
+ minPckRtRule = {
+ "model": {
+ "qospolicy": "6",
+ "qospolicyname": "test",
+ "ruleid": "2",
+ "rule_type": "minimum_packet_rate",
+ "minkpps": 20000,
+ "direction": "ingress",
+ "rules": [
+ {
+ "min_kpps": 10000,
+ "direction": "egress",
+ "id": 2,
+ "qos_policy_id": "6",
+ "type": "minimum_packet_rate"
+ }
+ ]
+ }
+ };
+ }));
+
+ it('should check policy is allowed or not', function() {
+ spyOn(policyAPI, 'ifAllowed').and.callThrough();
+ var allowed = service.allowed();
+ expect(allowed).toBeTruthy();
+ expect(policyAPI.ifAllowed).toHaveBeenCalledWith(
+ { rules: [['network', 'update_policy_bandwidth_limit_rule'],
+ ['network', 'update_policy_dscp_marking_rule'],
+ ['network', 'update_policy_minimum_bandwidth_rule']] });
+ });
+
+ it('should open the modal with existing rule', function() {
+ spyOn(modalFormService, 'open').and.returnValue($q.defer().promise);
+ service.perform(qosPolicy);
+ expect(modalFormService.open).toHaveBeenCalled();
+ });
+
+ it('should not open the modal', function() {
+ spyOn(modalFormService, 'open').and.returnValue($q.defer().promise);
+ spyOn(toast, 'add').and.callFake(angular.noop);
+ service.perform(nqosPolicy);
+ expect(modalFormService.open).not.toHaveBeenCalled();
+ expect(toast.add).toHaveBeenCalledWith(
+ 'info', 'There are no rules to modify.'
+ );
+ });
+
+ it('should submit DSCP Marking edit rule request to neutron', function() {
+ var deferred = $q.defer();
+ var data = {"dscp_mark": 26};
+ spyOn(toast, 'add').and.callFake(angular.noop);
+ spyOn(neutronAPI, 'updateDSCPMarkingRule').and.returnValue(deferred.promise);
+ deferred.resolve({data: {dscp_mark: 26, id: '2'}});
+ service.submit(dscpRule).then(service.success);
+ $scope.$apply();
+ expect(neutronAPI.updateDSCPMarkingRule).toHaveBeenCalledWith(
+ qosPolicy.id, [dscpRule.model.ruleid], data);
+ expect(toast.add).toHaveBeenCalledWith(
+ 'success', 'Qos Policy Rule 2 was successfully updated.'
+ );
+ });
+
+ it('should submit Bandwidth Limit edit rule request to neutron', function() {
+ var deferred = $q.defer();
+ var data = {"max_kbps": 1000, "direction": "egress", "max_burst_kbps": 1100};
+ spyOn(toast, 'add').and.callFake(angular.noop);
+ spyOn(neutronAPI, 'updateBandwidthRule').and.returnValue(deferred.promise);
+ deferred.resolve({data: {"id": "2", "max_kbps": 1000, "direction": "egress",
+ "max_burst_kbps": 1100}});
+ service.submit(bwdLmtRule).then(service.success);
+ $scope.$apply();
+ expect(neutronAPI.updateBandwidthRule).toHaveBeenCalledWith(
+ qosPolicy.id, [bwdLmtRule.model.ruleid], data);
+ expect(toast.add).toHaveBeenCalledWith(
+ 'success', 'Qos Policy Rule 2 was successfully updated.'
+ );
+ });
+
+ it('should submit Minimum BandwidthLimit edit rule request to neutron', function() {
+ var deferred = $q.defer();
+ var data = {"min_kbps": 128, "direction": "egress"};
+ spyOn(toast, 'add').and.callFake(angular.noop);
+ spyOn(neutronAPI, 'updateMinimumBandwidthRule').and.returnValue(deferred.promise);
+ deferred.resolve({data: {"id": "2", "min_kbps": 128, "direction": "egress"}});
+ service.submit(minBwdRule).then(service.success);
+ $scope.$apply();
+ expect(neutronAPI.updateMinimumBandwidthRule).toHaveBeenCalledWith(
+ qosPolicy.id, [minBwdRule.model.ruleid], data);
+ expect(toast.add).toHaveBeenCalledWith(
+ 'success', 'Qos Policy Rule 2 was successfully updated.'
+ );
+ });
+
+ it('should submit Minimum Packet Rate edit rule request to neutron', function() {
+ var deferred = $q.defer();
+ var data = {"min_kpps": 20000, "direction": "ingress"};
+ spyOn(toast, 'add').and.callFake(angular.noop);
+ spyOn(neutronAPI, 'updateMinimumPacketRateRule').and.returnValue(deferred.promise);
+ deferred.resolve({data: {"id": "2", "min_kpps": 20000, "direction": "ingress"}});
+ service.submit(minPckRtRule).then(service.success);
+ $scope.$apply();
+ expect(neutronAPI.updateMinimumPacketRateRule).toHaveBeenCalledWith(
+ qosPolicy.id, [minPckRtRule.model.ruleid], data);
+ expect(toast.add).toHaveBeenCalledWith(
+ 'success', 'Qos Policy Rule 2 was successfully updated.'
+ );
+ });
+
+ });
+})();
diff --git a/openstack_dashboard/static/app/core/network_qos/actions/edit-rule.controller.js b/openstack_dashboard/static/app/core/network_qos/actions/edit-rule.controller.js
new file mode 100644
index 000000000..49840d3d6
--- /dev/null
+++ b/openstack_dashboard/static/app/core/network_qos/actions/edit-rule.controller.js
@@ -0,0 +1,104 @@
+/**
+ * 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.
+ */
+
+(function() {
+ 'use strict';
+
+ /**
+ * @ngdoc controller
+ * @name horizon.app.core.network_qos.actions.EditQoSRuleController
+ * @ngController
+ *
+ * @description
+ * Controller for the editing rules for qos policy
+ */
+ angular
+ .module('horizon.app.core.network_qos.actions')
+ .controller('horizon.app.core.network_qos.actions.EditQoSRuleController',
+ editQoSRuleController);
+
+ editQoSRuleController.$inject = [
+ '$scope'
+ ];
+
+ function editQoSRuleController($scope) {
+ var ctrl = this;
+ ctrl.qospolicy = $scope.model.qospolicy;
+ ctrl.qospolicyname = $scope.model.qospolicyname;
+ ctrl.rule_types = [];
+ angular.forEach($scope.model.rules, function(k) {
+ if (k.type === 'bandwidth_limit') {
+ ctrl.rule_types.push({name: 'bandwidth_limit', val: gettext('Bandwidth Limit - ' +
+ k.id + ', ' + k.max_kbps + ', ' + k.max_burst_kbps + ', ' + k.direction)});
+ ctrl.bwdid = k.id;
+ ctrl.maxkbps = k.max_kbps;
+ ctrl.maxburstkbps = k.max_burst_kbps || 0;
+ ctrl.bwddirection = k.direction;
+ }
+ else if (k.type === 'dscp_marking') {
+ ctrl.rule_types.push({name: 'dscp_marking',
+ val: gettext("DSCP Mark - " + k.id + ', ' + k.dscp_mark)});
+ ctrl.dscpid = k.id;
+ ctrl.dscpmark = k.dscp_mark;
+ }
+ else if (k.type === 'minimum_bandwidth') {
+ ctrl.rule_types.push({name: 'minimum_bandwidth',
+ val: gettext('Minimum Bandwidth - ' + k.id + ', ' + k.min_kbps + ', ' + k.direction)});
+ ctrl.minbwdid = k.id;
+ ctrl.minkbps = k.min_kbps;
+ ctrl.minbwddirection = k.direction;
+ }
+ else if (k.type === 'minimum_packet_rate') {
+ ctrl.rule_types.push({name: 'minimum_packet_rate',
+ val: gettext('Minimum Packet Rate - ' + k.id + ', ' + k.min_kpps + ', ' +
+ k.direction)});
+ ctrl.minpckrtid = k.id;
+ ctrl.minkpps = k.min_kpps;
+ ctrl.minpckrtdirection = k.direction;
+ }
+ }, this);
+ ctrl.directions = {
+ "egress": gettext("egress"),
+ "ingress": gettext("ingress")
+ };
+ ctrl.ppsDirections = {
+ "egress": gettext("egress"),
+ "ingress": gettext("ingress"),
+ "any": gettext("any")
+ };
+ ctrl.onRuleTypeChange = function(ruleType) {
+ $scope.model.rule_type = ruleType.name;
+ };
+ ctrl.bwdLimit = function(bwd) {
+ $scope.model.ruleid = ctrl.bwdid;
+ $scope.model.maxkbps = bwd.maxkbps || ctrl.maxkbps;
+ $scope.model.maxburstkbps = bwd.maxburstkbps || ctrl.maxburstkbps;
+ $scope.model.direction = bwd.direction || ctrl.bwddirection;
+ };
+ ctrl.onDSCPChange = function(dscpmark) {
+ $scope.model.ruleid = ctrl.dscpid;
+ $scope.model.dscpmarking = dscpmark || ctrl.dscpmark;
+ };
+ ctrl.minBandwidth = function(mb) {
+ $scope.model.ruleid = ctrl.minbwdid;
+ $scope.model.minkbps = mb.minkbps || ctrl.minkbps;
+ $scope.model.direction = mb.direction || ctrl.minbwddirection;
+ };
+ ctrl.minPacketRate = function(mpr) {
+ $scope.model.ruleid = ctrl.minpckrtid;
+ $scope.model.minkpps = mpr.minkpps || ctrl.minkpps;
+ $scope.model.direction = mpr.direction || ctrl.minpckrtdirection;
+ };
+ }
+})();
diff --git a/openstack_dashboard/static/app/core/network_qos/actions/edit-rule.controller.spec.js b/openstack_dashboard/static/app/core/network_qos/actions/edit-rule.controller.spec.js
new file mode 100644
index 000000000..3ba4dc6d7
--- /dev/null
+++ b/openstack_dashboard/static/app/core/network_qos/actions/edit-rule.controller.spec.js
@@ -0,0 +1,161 @@
+/*
+ * 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.
+ */
+
+(function() {
+ 'use strict';
+
+ describe('qos rules datails', function() {
+
+ var ctrl, rules, directions, ppsDirections, $controller, $scope,
+ $rootScope, dscp, ndscp, minBwd, nminBwd, bwdLmt, nbwdLmt,
+ minPckRt, nminPckRt;
+
+ beforeEach(module('horizon.app.core.network_qos'));
+
+ beforeEach(inject(function(_$controller_, _$rootScope_) {
+ $controller = _$controller_;
+ $rootScope = _$rootScope_;
+ $scope = $rootScope.$new();
+
+ $scope = {
+ model: {
+ qospolicy: "1",
+ qospolicyname: "test_qos",
+ rules: [
+ {
+ type: "bandwidth_limit",
+ id: 1, max_kbps: 1000,
+ max_burst_kbps: 100, direction: "egress"
+ },
+ {
+ type: "dscp_marking",
+ id: 1, dscp_mark: 12
+ },
+ {
+ type: "minimum_bandwidth",
+ id: 1, min_kbps: 100,
+ direction: "egress"
+ },
+ {
+ type: "minimum_packet_rate",
+ id: 1, min_kpps: 10000,
+ direction: "egress"
+ }
+ ]
+ }
+ };
+
+ ctrl = $controller('horizon.app.core.network_qos.actions.EditQoSRuleController',
+ {
+ $scope: $scope
+ }
+ );
+
+ rules = [
+ {name: "bandwidth_limit", val: "Bandwidth Limit - 1, 1000, 100, egress"},
+ {name: "dscp_marking", val: "DSCP Mark - 1, 12"},
+ {name: "minimum_bandwidth", val: "Minimum Bandwidth - 1, 100, egress"},
+ {name: "minimum_packet_rate", val: "Minimum Packet Rate - 1, 10000, egress"}
+ ];
+ directions = {
+ "egress": "egress",
+ "ingress": "ingress"
+ };
+ ppsDirections = {
+ "egress": "egress",
+ "ingress": "ingress",
+ "any": "any"
+ };
+ dscp = {
+ model: {
+ dscpmarking: 0
+ }
+ };
+ ndscp = {
+ model: {
+ dscpmarking: undefined
+ }
+ };
+ minBwd = {
+ model: {
+ minkbps: 1000,
+ direction: 'egress'
+ }
+ };
+ nminBwd = {
+ model: {
+ minkbps: '',
+ direction: ''
+ }
+ };
+ bwdLmt = {
+ model: {
+ maxkbps: 2000,
+ maxburstkbps: 3000,
+ direction: 'egress'
+ }
+ };
+ nbwdLmt = {
+ model: {
+ maxkbps: '',
+ maxburstkbps: '',
+ direction: ''
+ }
+ };
+ minPckRt = {
+ model: {
+ minkpps: 10000,
+ direction: 'egress'
+ }
+ };
+ nminPckRt = {
+ model: {
+ minkpps: '',
+ direction: ''
+ }
+ };
+ }));
+
+ it('sets edit ctrl', inject(function() {
+ expect(ctrl.qospolicy).toEqual($scope.model.qospolicy);
+ expect(ctrl.qospolicy).not.toEqual('2');
+ expect(ctrl.rule_types).toEqual(rules);
+ ctrl.onRuleTypeChange('dscp_mark');
+ expect(ctrl.onRuleTypeChange).toBeDefined();
+ expect(ctrl.directions).toEqual(directions);
+ expect(ctrl.ppsDirections).toEqual(ppsDirections);
+ // DSCP Mark
+ ctrl.onDSCPChange(dscp.model);
+ expect(ctrl.onDSCPChange).toBeDefined();
+ ctrl.onDSCPChange(ndscp.model);
+ expect(ctrl.onDSCPChange).toBeDefined();
+ // Minimum Bandwidth
+ ctrl.minBandwidth(minBwd.model);
+ expect(ctrl.minBandwidth).toBeDefined();
+ ctrl.minBandwidth(nminBwd.model);
+ expect(ctrl.minBandwidth).toBeDefined();
+ // Bandwidth Limit
+ ctrl.bwdLimit(bwdLmt.model);
+ expect(ctrl.bwdLimit).toBeDefined();
+ ctrl.bwdLimit(nbwdLmt.model);
+ expect(ctrl.nbwdLimit).not.toBeDefined();
+ // Minimum Packet Rate
+ ctrl.minPacketRate(minPckRt.model);
+ expect(ctrl.minPacketRate).toBeDefined();
+ ctrl.minPacketRate(nminPckRt.model);
+ expect(ctrl.minPacketRate).toBeDefined();
+ }));
+
+ });
+})();
diff --git a/openstack_dashboard/static/app/core/network_qos/actions/edit-rule.html b/openstack_dashboard/static/app/core/network_qos/actions/edit-rule.html
new file mode 100644
index 000000000..ce54412be
--- /dev/null
+++ b/openstack_dashboard/static/app/core/network_qos/actions/edit-rule.html
@@ -0,0 +1,106 @@
+<div ng-controller="horizon.app.core.network_qos.actions.EditQoSRuleController as ctrl" class="form-group">
+ <label class="control-label required">
+ <translate>QoS Policy ID</translate>
+ <span class="hz-icon-required fa fa-asterisk"></span>
+ </label>
+ <input class="form-control ng-pristine ng-untouched ng-valid" ng-value="ctrl.qospolicy" name="qospolicyid" readonly>
+ <label class="control-label required">
+ <translate>QoS Policy Name</translate>
+ <span class="hz-icon-required fa fa-asterisk"></span>
+ </label>
+ <input class="form-control ng-pristine ng-untouched ng-valid" ng-value="ctrl.qospolicyname" name="qospolicyname" readonly>
+ <label class="control-label required">
+ <translate>Rule to edit</translate>
+ <span class="hz-icon-required fa fa-asterisk"></span>
+ </label>
+ <select class="form-control switchable ng-pristine ng-untouched ng-valid"
+ ng-model="rule_type"
+ ng-options="option.val for option in ctrl.rule_types"
+ name="edit-rule"
+ ng-change="ctrl.onRuleTypeChange(rule_type)">
+ </select>
+ <div ng-show="rule_type.name === 'bandwidth_limit'">
+ <label class="control-label required">
+ <translate>Max bandwidth (in kbps)</translate>
+ <span class="hz-icon-required fa fa-asterisk"></span>
+ </label>
+ <input class="form-control ng-pristine ng-untouched ng-valid"
+ ng-model="bwd.maxkbps"
+ name="maxkbps"
+ ng-value="ctrl.maxkbps"
+ ng-change="ctrl.bwdLimit(bwd)">
+ <label class="control-label required">
+ <translate>Max Burst Size (in kbps)</translate>
+ </label>
+ <input class="form-control ng-pristine ng-untouched ng-valid"
+ ng-model="bwd.maxburstkbps"
+ name="maxburstkbps"
+ ng-value="ctrl.maxburstkbps"
+ ng-change="ctrl.bwdLimit(bwd)">
+ <label class="control-label required">
+ <translate>Direction</translate>
+ </label>
+ <select class="form-control switchable ng-pristine ng-untouched ng-valid"
+ ng-model="bwd.direction"
+ ng-init="ctrl.bwddirection"
+ ng-options="val as label for (val, label) in ctrl.directions"
+ name="direction"
+ ng-change="ctrl.bwdLimit(bwd)">
+ </select>
+ </div>
+ <div ng-show="rule_type.name === 'dscp_marking'">
+ <label class="control-label required">
+ <translate>DSCP Mark</translate>
+ <span class="hz-icon-required fa fa-asterisk"></span>
+ </label>
+ <input class="form-control ng-pristine ng-untouched ng-valid"
+ ng-model="dscpmark"
+ name="dscpmarking"
+ ng-value="ctrl.dscpmark"
+ placeholder="valid DSCP marks is:
+ 0, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 46, 48, 56"
+ ng-change="ctrl.onDSCPChange(dscpmark)">
+ </div>
+ <div ng-show="rule_type.name === 'minimum_bandwidth'">
+ <label class="control-label required">
+ <translate>Minimum bandwidth (in kbps)</translate>
+ <span class="hz-icon-required fa fa-asterisk"></span>
+ </label>
+ <input class="form-control ng-pristine ng-untouched ng-valid"
+ ng-model="mb.minkbps"
+ name="minkbps"
+ ng-value="ctrl.minkbps"
+ ng-change="ctrl.minBandwidth(mb)">
+ <label class="control-label required">
+ <translate>Direction</translate>
+ </label>
+ <select class="form-control switchable ng-pristine ng-untouched ng-valid"
+ ng-model="mb.direction"
+ ng-options="val as label for (val, label) in ctrl.directions"
+ name="direction"
+ ng-init="ctrl.minbwddirection"
+ ng-change="ctrl.minBandwidth(mb)">
+ </select>
+ </div>
+ <div ng-show="rule_type.name === 'minimum_packet_rate'">
+ <label class="control-label required">
+ <translate>Minimum packet rate (in kpps)</translate>
+ <span class="hz-icon-required fa fa-asterisk"></span>
+ </label>
+ <input class="form-control ng-pristine ng-untouched ng-valid"
+ ng-model="mpr.minkpps"
+ name="minkpps"
+ ng-value="ctrl.minkpps"
+ ng-change="ctrl.minPacketRate(mpr)">
+ <label class="control-label required">
+ <translate>Direction</translate>
+ </label>
+ <select class="form-control switchable ng-pristine ng-untouched ng-valid"
+ ng-model="mpr.direction"
+ ng-options="val as label for (val, label) in ctrl.ppsDirections"
+ name="direction"
+ ng-init="ctrl.minpckrtdirection"
+ ng-change="ctrl.minPacketRate(mpr)">
+ </select>
+ </div>
+ </div> \ No newline at end of file
diff --git a/openstack_dashboard/static/app/core/network_qos/actions/rule.description.html b/openstack_dashboard/static/app/core/network_qos/actions/rule.description.html
new file mode 100644
index 000000000..bc839e15c
--- /dev/null
+++ b/openstack_dashboard/static/app/core/network_qos/actions/rule.description.html
@@ -0,0 +1,18 @@
+<p translate>
+ Valid DSCP mark values are even numbers between 0 and 56,
+ except 2-6, 42, 44, and 50-54. The full list of valid DSCP marks is:
+ 0, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 46, 48, 56.
+</p>
+<p translate>
+ The maximum KBPS (kilobits per second) value.
+ If you specify this value, must be greater than 0 otherwise max_kbps will have no value.
+ <p translate>
+ The maximum burst size (in kilobits). Default is 0.
+ </p>
+</p>
+<p translate>
+ The minimum KBPS (kilobits per second) value which should be available for port.
+</p>
+<p translate>
+ The minimum kpps (kilo(1000) packets per second) value which should be available for port.
+</p> \ No newline at end of file
diff --git a/openstack_dashboard/static/app/core/network_qos/actions/workflow/delete-rule.workflow.service.js b/openstack_dashboard/static/app/core/network_qos/actions/workflow/delete-rule.workflow.service.js
new file mode 100644
index 000000000..73726ed65
--- /dev/null
+++ b/openstack_dashboard/static/app/core/network_qos/actions/workflow/delete-rule.workflow.service.js
@@ -0,0 +1,118 @@
+/* Liscensed 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.
+ */
+
+(function() {
+ 'use strict';
+
+ /**
+ * @ngdoc factory
+ * @name horizon.app.core.network_qos.actions.delete-rule.workflow.service
+ * @ngController
+ *
+ * @description
+ * Workflow for deleting rule to a network qos policy.
+ */
+
+ angular
+ .module('horizon.app.core.network_qos.actions')
+ .factory('horizon.app.core.network_qos.actions.deleteRuleWorkflow', deleteRuleWorkflow);
+
+ deleteRuleWorkflow.$inject = [
+ 'horizon.app.core.openstack-service-api.neutron'
+ ];
+
+ function deleteRuleWorkflow(neutronAPI) {
+
+ var workflow = {
+ init: init
+ };
+
+ function init(qospolicy) {
+ var schema = {
+ type: 'object',
+ properties: {
+ qospolicyname: {
+ title: gettext('QoS Policy Name'),
+ type: 'string',
+ readOnly: true
+ },
+ ruleid: {
+ title: gettext('Rule'),
+ type: 'string'
+ },
+ qospolicy: {
+ title: gettext('QoS Policy ID'),
+ type: 'string',
+ readOnly: true
+ }
+ },
+ required: ['ruleid']
+ };
+
+ var form = [
+ "qospolicy",
+ "qospolicyname",
+ {
+ key: "ruleid",
+ type: "select",
+ titleMap: []
+ }
+ ];
+
+ var model = {};
+
+ var config = {
+ schema: schema,
+ form: form,
+ model: model
+ };
+
+ neutronAPI.getQosPolicy(qospolicy.id).then(modifyPolicies);
+
+ function modifyPolicies(policies) {
+ var policyField = config.form[2];
+ angular.forEach(policies.data.rules, function(k) {
+ if (k.type === 'dscp_marking') {
+ this.push({
+ name: String(k.id + ' - ' + k.type + ' - dscpmark: ' + k.dscp_mark),
+ value: String(k.id)
+ });
+ }
+ else if (k.type === 'bandwidth_limit') {
+ this.push({
+ name: String(k.id + ' - ' + k.type + ' - maxkbps: ' + k.max_kbps +
+ ', maxburstkbps: ' + k.max_burst_kbps + ', ' + k.direction),
+ value: String(k.id)
+ });
+ }
+ else if (k.type === 'minimum_bandwidth') {
+ this.push({
+ name: String(k.id + ' - ' + k.type + ' - minkbps: ' +
+ k.min_kbps + ', ' + k.direction),
+ value: String(k.id)
+ });
+ }
+ else if (k.type === 'minimum_packet_rate') {
+ this.push({
+ name: String(k.id + ' - ' + k.type + ' - minkpps: ' +
+ k.min_kpps + ', ' + k.direction),
+ value: String(k.id)
+ });
+ }
+ }, policyField.titleMap);
+ }
+ return config;
+ }
+ return workflow;
+ }
+})();
diff --git a/openstack_dashboard/static/app/core/network_qos/actions/workflow/delete-rule.workflow.service.spec.js b/openstack_dashboard/static/app/core/network_qos/actions/workflow/delete-rule.workflow.service.spec.js
new file mode 100644
index 000000000..0792512d0
--- /dev/null
+++ b/openstack_dashboard/static/app/core/network_qos/actions/workflow/delete-rule.workflow.service.spec.js
@@ -0,0 +1,97 @@
+/*
+ * 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.
+ */
+
+(function() {
+ 'use strict';
+
+ describe('horizon.app.core.network_qos.actions.deleteRuleWorkflow.service', function() {
+
+ var $q, $scope, workflow, policies, neutronAPI;
+
+ beforeEach(module('horizon.framework'));
+ beforeEach(module('horizon.app.core'));
+ beforeEach(module('horizon.app.core.network_qos'));
+
+ beforeEach(inject(function($injector, _$rootScope_, _$q_) {
+ $q = _$q_;
+ $scope = _$rootScope_.$new();
+ neutronAPI = $injector.get('horizon.app.core.openstack-service-api.neutron');
+ workflow = $injector.get('horizon.app.core.network_qos.actions.deleteRuleWorkflow');
+ policies = {
+ "data": {
+ "created_at": "Z",
+ "description": "",
+ "id": "1",
+ "is_default": false,
+ "name": "qos_test",
+ "project_id": "5",
+ "revision_number": 1,
+ "rules": [
+ {
+ "direction": "egress",
+ "id": "1",
+ "max_burst_kbps": 1100,
+ "max_kbps": 1000,
+ "qos_policy_id": "2",
+ "type": "bandwidth_limit"
+ },
+ {
+ "dscp_mark": 0,
+ "id": "3",
+ "qos_policy_id": "2",
+ "type": "dscp_marking"
+ },
+ {
+ "direction": "egress",
+ "id": "6",
+ "min_kbps": 128,
+ "qos_policy_id": "2",
+ "type": "minimum_bandwidth"
+ },
+ {
+ "direction": "egress",
+ "id": "6",
+ "min_kbps": 1000,
+ "qos_policy_id": "2",
+ "type": "minimum_packet_rate"
+ }
+ ],
+ "shared": false,
+ "tags": [],
+ "tenant_id": "54",
+ "updated_at": "2021-09-15T07:38:49.000Z"
+ }
+ };
+ }));
+
+ function testInitWorkflow() {
+ var deferred = $q.defer();
+ spyOn(neutronAPI, 'getQosPolicy').and.returnValue(deferred.promise);
+ var config = workflow.init(policies.data);
+ deferred.resolve(policies);
+ neutronAPI.getQosPolicy(policies.data.id).then(workflow.modifyPolicies);
+ $scope.$apply();
+ expect(neutronAPI.getQosPolicy).toHaveBeenCalled();
+ expect(config.schema).toBeDefined();
+ expect(config.form).toBeDefined();
+ expect(config.model).toBeDefined();
+ return config;
+ }
+
+ it('should create workflow config for select rule for deleting', function() {
+ testInitWorkflow();
+ });
+
+ });
+})();
diff --git a/openstack_dashboard/static/app/core/network_qos/details/overview.controller.js b/openstack_dashboard/static/app/core/network_qos/details/overview.controller.js
index 542cf74de..30177d11f 100644
--- a/openstack_dashboard/static/app/core/network_qos/details/overview.controller.js
+++ b/openstack_dashboard/static/app/core/network_qos/details/overview.controller.js
@@ -34,7 +34,7 @@
var ctrl = this;
ctrl.resourceType = registry.getResourceType(qosResourceTypeCode);
- ctrl.tableConfig = {
+ ctrl.tableConfigBwd = {
selectAll: false,
expand: false,
trackId: 'id',
@@ -47,14 +47,66 @@
columns: [
{id: 'id', title: gettext('Rule ID'), priority: 1, sortDefault: true},
{id: 'type', title: gettext('Type'), priority: 1},
- {id: 'direction', title: gettext('Direction'), priority: 1},
{id: 'max_kbps', title: gettext('Max Kbps'), priority: 1},
{id: 'max_burst_kbps', title: gettext('Max Burst Kbits'), priority: 1},
- {id: 'min_kbps', title: gettext('Min Kbps'), priority: 1},
+ {id: 'direction', title: gettext('Direction'), priority: 1}
+ ]
+ };
+
+ ctrl.tableConfigDSCP = {
+ selectAll: false,
+ expand: false,
+ trackId: 'id',
+ /*
+ * getTableColumns here won't work as that will give back the
+ * columns for the policy, but here we need columns only for the
+ * policy rules, which is a (list of) dictionary(ies) in the
+ * policy dictionary.
+ */
+ columns: [
+ {id: 'id', title: gettext('Rule ID'), priority: 1, sortDefault: true},
+ {id: 'type', title: gettext('Type'), priority: 1},
{id: 'dscp_mark', title: gettext('DSCP Mark'), priority: 1}
]
};
+ ctrl.tableConfigMinBwd = {
+ selectAll: false,
+ expand: false,
+ trackId: 'id',
+ /*
+ * getTableColumns here won't work as that will give back the
+ * columns for the policy, but here we need columns only for the
+ * policy rules, which is a (list of) dictionary(ies) in the
+ * policy dictionary.
+ */
+ columns: [
+ {id: 'id', title: gettext('Rule ID'), priority: 1, sortDefault: true},
+ {id: 'type', title: gettext('Type'), priority: 1},
+ {id: 'min_kbps', title: gettext('Min Kbps'), priority: 1},
+ {id: 'direction', title: gettext('Direction'), priority: 1}
+
+ ]
+ };
+
+ ctrl.tableConfigMinPckRt = {
+ selectAll: false,
+ expand: false,
+ trackId: 'id',
+ /*
+ * getTableColumns here won't work as that will give back the
+ * columns for the policy, but here we need columns only for the
+ * policy rules, which is a (list of) dictionary(ies) in the
+ * policy dictionary.
+ */
+ columns: [
+ {id: 'id', title: gettext('Rule ID'), priority: 1, sortDefault: true},
+ {id: 'type', title: gettext('Type'), priority: 1},
+ {id: 'min_kpps', title: gettext('Min Kpps'), priority: 1},
+ {id: 'direction', title: gettext('Direction'), priority: 1},
+ ]
+ };
+
$scope.context.loadPromise.then(onGetPolicy);
function onGetPolicy(response) {
diff --git a/openstack_dashboard/static/app/core/network_qos/details/overview.html b/openstack_dashboard/static/app/core/network_qos/details/overview.html
index 55a111213..5733b7e0e 100644
--- a/openstack_dashboard/static/app/core/network_qos/details/overview.html
+++ b/openstack_dashboard/static/app/core/network_qos/details/overview.html
@@ -25,12 +25,43 @@
<div class="col-md-12 detail">
<h3 translate>Rules</h3>
<hr>
- <dl class="dl-horizontal">
+ <dl class="dl-horizontal" ng-repeat="rule in ctrl.policy.rules track by $index">
+ <div ng-if="rule.type === 'dscp_marking'">
+ <h3 translate>DSCP Rules</h3>
+ <hr>
<hz-dynamic-table
- config="ctrl.tableConfig"
- items="ctrl.policy.rules"
+ config="ctrl.tableConfigDSCP"
+ items="rule"
table="ctrl">
</hz-dynamic-table>
+ </div>
+ <div ng-if="rule.type === 'bandwidth_limit'">
+ <h3 translate>Bandwidth Rules</h3>
+ <hr>
+ <hz-dynamic-table
+ config="ctrl.tableConfigBwd"
+ items="rule"
+ table="ctrl">
+ </hz-dynamic-table>
+ </div>
+ <div ng-if="rule.type === 'minimum_bandwidth'">
+ <h3 translate>Minimum Bandwidth Rules</h3>
+ <hr>
+ <hz-dynamic-table
+ config="ctrl.tableConfigMinBwd"
+ items="rule"
+ table="ctrl">
+ </hz-dynamic-table>
+ </div>
+ <div ng-if="rule.type === 'minimum_packet_rate'">
+ <h3 translate>Minimum Packet Rules</h3>
+ <hr>
+ <hz-dynamic-table
+ config="ctrl.tableConfigMinPckRt"
+ items="rule"
+ table="ctrl">
+ </hz-dynamic-table>
+ </div>
</dl>
</div>
</div>
diff --git a/openstack_dashboard/static/app/core/openstack-service-api/neutron.service.js b/openstack_dashboard/static/app/core/openstack-service-api/neutron.service.js
index 504eaece1..e47432489 100644
--- a/openstack_dashboard/static/app/core/openstack-service-api/neutron.service.js
+++ b/openstack_dashboard/static/app/core/openstack-service-api/neutron.service.js
@@ -39,6 +39,10 @@
createSubnet: createSubnet,
createTrunk: createTrunk,
createNetworkQoSPolicy: createNetworkQoSPolicy,
+ createBandwidthLimitRule: createBandwidthLimitRule,
+ createDSCPMarkingRule: createDSCPMarkingRule,
+ createMinimumBandwidthRule: createMinimumBandwidthRule,
+ createMinimumPacketRateRule: createMinimumPacketRateRule,
deletePolicy: deletePolicy,
deleteTrunk: deleteTrunk,
getAgents: getAgents,
@@ -52,7 +56,15 @@
getTrunk: getTrunk,
getTrunks: getTrunks,
updateProjectQuota: updateProjectQuota,
- updateTrunk: updateTrunk
+ updateTrunk: updateTrunk,
+ deleteDSCPMarkingRule: deleteDSCPMarkingRule,
+ deleteBandwidthLimitRule: deleteBandwidthLimitRule,
+ deleteMinimumBandwidthRule: deleteMinimumBandwidthRule,
+ deleteMinimumPacketRateRule: deleteMinimumPacketRateRule,
+ updateMinimumBandwidthRule: updateMinimumBandwidthRule,
+ updateDSCPMarkingRule: updateDSCPMarkingRule,
+ updateBandwidthRule: updateBandwidthRule,
+ updateMinimumPacketRateRule: updateMinimumPacketRateRule
};
return service;
@@ -428,13 +440,13 @@
});
}
- /**
- * @name deletePolicy
- * @description
- * Delete a single neutron qos policy.
- * @param {string} policyId
- * Specifies the id of the policy to be deleted.
- */
+ /**
+ * @name deletePolicy
+ * @description
+ * Delete a single neutron qos policy.
+ * @param {string} policyId
+ * Specifies the id of the policy to be deleted.
+ */
function deletePolicy(policyId, suppressError) {
var promise = apiService.delete('/api/neutron/qos_policies/' + policyId + '/');
promise = suppressError ? promise : promise.error(function() {
@@ -443,6 +455,344 @@
});
return promise;
}
+
+ /**
+ * @name createBandwidthLimitRule
+ * @description
+ * Creates a bandwidth limit rule for a QoS policy
+ * @returns {Object} A bandwidth_limit_rule object on success.
+ *
+ * @param {Object} policyId
+ * This param is for qos policy.
+ *
+ * @param {Object} ruleId
+ * The bandwidth limit rule to create. Required.
+ *
+ * Example new bandwidth limit rule response object
+ * {
+ * "bandwidth_limit_rule": {
+ * "id": "5f126d84-551a-4dcf-bb01-0e9c0df0c793",
+ * "max_kbps": 10000,
+ * "max_burst_kbps": 0,
+ * "direction": "egress"
+ * }
+ * }
+ *
+ * Description of properties on the bandwidth limit rule object
+ *
+ * @property {integer} ruleId.max_kbps
+ * The maximum KBPS (kilobits per second) value.
+ * If you specify this value, must be greater than '0'
+ * otherwise max_kbps will have no value. Required.
+ *
+ * @property {integer} ruleId.max_burst_kbps
+ * The maximum burst size (in kilobits). Default is '0'. Optional.
+ *
+ * @property {string} ruleId.direction
+ * The direction of the traffic to which the QoS rule is applied,
+ * as seen from the point of view of the port.
+ * Valid values are egress and ingress. Default value is egress.
+ * Optional.
+ *
+ */
+ function createBandwidthLimitRule(policyId, ruleId) {
+ return apiService.post('/api/neutron/qos/policies/' + policyId +
+ '/bandwidth_limit_rules/', ruleId)
+ .error(function () {
+ toastService.add('error', gettext('Unable to add the bandwidthrule .'));
+ });
+ }
+
+ /**
+ * @name createDSCPMarkingRule
+ * @description
+ * Creates a DSCP marking rule for a QoS policy.
+ * @returns {Object} A dscp_marking_rule object on success.
+ *
+ * @param {Object} policyId
+ * This param is for qos policy.
+ *
+ * @param {Object} ruleId
+ * The dscp marking rule to create. Required.
+ *
+ * Example new dscp mark rule response object
+ * {
+ * "dscp_marking_rule": {
+ * "id": "5f126d84-551a-4dcf-bb01-0e9c0df0c794",
+ * "dscp_mark": 26
+ * }
+ * }
+ *
+ * Description of properties on the dscp marking rule object
+ *
+ * @property {integer} ruleId.dscp_mark
+ * The DSCP mark value. Required.
+ * Valid DSCP mark values are even numbers between 0 and 56,
+ * except 2-6, 42, 44, and 50-54. The full list of valid DSCP marks is:
+ * 0, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 46, 48, 56
+ *
+ */
+ function createDSCPMarkingRule(policyId, ruleId) {
+ return apiService.post('/api/neutron/qos/policies/' + policyId +
+ '/dscp_marking_rules/', ruleId)
+ .error(function () {
+ toastService.add('error', gettext('Unable to add the dscp_marking_rule .'));
+ });
+ }
+
+ /**
+ * @name createMinimumBandwidthRule
+ * @description
+ * Creates a minimum bandwidth rule for a QoS policy
+ * @returns {Object} A minimum_bandwidth_rule object on success.
+ *
+ * @param {Object} policyId
+ * This param is for qos policy.
+ *
+ * @param {Object} ruleId
+ * The minimum bandwidth rule to create. Required.
+ *
+ * Example new minimum bandwidth rule response object
+ * {
+ * "minimum_bandwidth_rule": {
+ * "id": "1eddf7af-0b4c-42c5-8ae1-390b32f1de08",
+ * "min_kbps": 10000,
+ * "direction": "egress"
+ * }
+ * }
+ *
+ * Description of properties on the minimum bandwidth rule object
+ *
+ * @property {integer} ruleId.min_kbps
+ * The minimum KBPS (kilobits per second) value which should be available for port.
+ * Required.
+ *
+ * @property {string} ruleId.direction
+ * The direction of the traffic to which the QoS rule is applied,
+ * as seen from the point of view of the port.
+ * Valid values are egress and ingress. Default value is egress.
+ * Optional.
+ *
+ */
+ function createMinimumBandwidthRule(policyId, ruleId) {
+ return apiService.post('/api/neutron/qos/policies/' + policyId +
+ '/minimum_bandwidth_rules/', ruleId)
+ .error(function () {
+ toastService.add('error', gettext('Unable to add the minimum_bandwidth_rule .'));
+ });
+ }
+
+ /**
+ * @name createMinimumPacketRateRule
+ * @description
+ * Creates a minimum packet rate rule for a QoS policy
+ * @returns {Object} A minimum_bandwidth_rule object on success.
+ *
+ * @param {Object} policyId
+ * This param is for qos policy.
+ *
+ * @param {Object} ruleId
+ * The minimum packet rate rule to create. Required.
+ *
+ * Example new minimum packet rate rule response object
+ * {
+ * "minimum_packet_rate_rule": {
+ * "id": "1eddf7af-0b4c-42c5-8ae1-390b32f1de08",
+ * "min_kpps": 10000,
+ * "direction": "egress"
+ * }
+ * }
+ *
+ * Description of properties on the minimum packet rate rule object
+ *
+ * @property {integer} ruleId.min_kbps
+ * The minimum kpps (kilo(1000) packets per second) value which should be available for port.
+ * Required.
+ *
+ * @property {string} ruleId.direction
+ * The direction of the traffic to which the QoS rule is applied,
+ * as seen from the point of view of the port.
+ * Valid values are egress and ingress. Default value is egress.
+ * Optional.
+ *
+ */
+ function createMinimumPacketRateRule(policyId, ruleId) {
+ return apiService.post('/api/neutron/qos/policies/' + policyId +
+ '/minimum_packet_rate_rules/', ruleId)
+ .error(function () {
+ toastService.add('error', gettext('Unable to add the minimum_packet_rate_rule.'));
+ });
+ }
+
+ /**
+ * @name updateBandwidthRule
+ * @description
+ * Update an existing bandwidth limit rule for a QoS policy.
+ * @returns {Object} A bandwidth_limit_rule object on success.
+ *
+ * @param {Object} policyId
+ * This param is for qos policy.
+ *
+ * @param {Object} ruleId
+ * This param is for rule.
+ *
+ * @param {Object} updateRuleId
+ * The bandwidth limit rule to update. Required.
+ *
+ */
+ function updateBandwidthRule(policyId, ruleId, updateRuleId) {
+ return apiService.patch('/api/neutron/qos/policies/' + policyId +
+ '/bandwidth_limit_rules/' + ruleId , updateRuleId)
+ .error(function () {
+ toastService.add('error', gettext('Unable to update the bandwidthrule.'));
+ });
+ }
+
+ /**
+ * @name updateDSCPMarkingRule
+ * @description
+ * Update an existing bandwidth limit rule for a QoS policy.
+ * @returns {Object} A bandwidth_limit_rule object on success.
+ *
+ * @param {Object} policyId
+ * This param is for qos policy.
+ *
+ * @param {Object} ruleId
+ * This param is for rule.
+ *
+ * @param {Object} updateRuleId
+ * The bandwidth limit rule to update. Required.
+ *
+ */
+ function updateDSCPMarkingRule(policyId, ruleId, updateRuleId) {
+ return apiService.patch('/api/neutron/qos/policies/' + policyId +
+ '/dscp_marking_rules/' + ruleId , updateRuleId)
+ .error(function () {
+ toastService.add('error', gettext('Unable to update the dscp marking rule.'));
+ });
+ }
+
+ /**
+ * @name updateMinimumBandwidthRule
+ * @description
+ * Update an existing minimum bandwidth rule for a QoS policy.
+ * @returns {Object} A minimum_bandwidth_rule object on success.
+ *
+ * @param {Object} policyId
+ * This param is for qos policy.
+ *
+ * @param {Object} ruleId
+ * This param is for rule.
+ *
+ * @param {Object} updateRuleId
+ * The minimum bandwidth limit rule to update. Required.
+ *
+ */
+ function updateMinimumBandwidthRule(policyId, ruleId, updateRuleId) {
+ return apiService.patch('/api/neutron/qos/policies/' + policyId +
+ '/minimum_bandwidth_rules/' + ruleId , updateRuleId)
+ .error(function () {
+ toastService.add('error', gettext('Unable to update the minimum bandwidth rule.'));
+ });
+ }
+
+ /**
+ * @name updateMinimumPacketRateRule
+ * @description
+ * Update an existing minimum packet rate limit rule for a QoS policy.
+ * @returns {Object} A minimum_packet_rate_rule object on success.
+ *
+ * @param {Object} policyId
+ * This param is for qos policy.
+ *
+ * @param {Object} ruleId
+ * This param is for rule.
+ *
+ * @param {Object} updateRuleId
+ * The minimum packet rate limit rule to update. Required.
+ *
+ */
+ function updateMinimumPacketRateRule(policyId, ruleId, updateRuleId) {
+ return apiService.patch('/api/neutron/qos/policies/' + policyId +
+ '/minimum_packet_rate_rules/' + ruleId , updateRuleId)
+ .error(function () {
+ toastService.add('error', gettext('Unable to update the minimum packet rate rule.'));
+ });
+ }
+
+ /**
+ * @name deleteBandwidthLimitRule
+ * @description
+ * Delete a single bandwidth limit rule.
+ *
+ * @param {string} policyId
+ * The ID of the QoS policy.
+ *
+ * @param {string} deleteruleId
+ * The ID of the QoS rule.
+ *
+ */
+ function deleteBandwidthLimitRule(policyId, deleteRuleId) {
+ return apiService.delete('/api/neutron/qos/policies/' + policyId +
+ '/bandwidth_limit_rules/' + deleteRuleId).error(function() {
+ toastService.add('error', gettext('Unable to delete the bandwidth_limit_rule.'));
+ });
+ }
+
+ /**
+ * @name deleteDSCPMarkingRule
+ * @description
+ * Delete a single dscp mark rule.
+ *
+ * @param {string} policyId
+ * The ID of the QoS policy.
+ *
+ * @param {string} deleteruleId
+ * The ID of the QoS rule.
+ */
+ function deleteDSCPMarkingRule(policyId, deleteRuleId) {
+ return apiService.delete('/api/neutron/qos/policies/' + policyId +
+ '/dscp_marking_rules/' + deleteRuleId).error(function() {
+ toastService.add('error', gettext('Unable to delete the dscp_marking_rule.'));
+ });
+ }
+
+ /**
+ * @name deleteMinimumBandwidthRule
+ * @description
+ * Delete a single minimum bandwidth rule.
+ *
+ * @param {string} policyId
+ * The ID of the QoS policy.
+ *
+ * @param {string} deleteruleId
+ * The ID of the QoS rule.
+ */
+ function deleteMinimumBandwidthRule(policyId, deleteRuleId) {
+ return apiService.delete('/api/neutron/qos/policies/' + policyId +
+ '/minimum_bandwidth_rules/' + deleteRuleId).error(function() {
+ toastService.add('error', gettext('Unable to delete the minimum_bandwidth_rule .'));
+ });
+ }
+
+ /**
+ * @name deleteMinimumPacketRateRule
+ * @description
+ * Delete a single minimum packet rate rule.
+ *
+ * @param {string} policyId
+ * The ID of the QoS policy.
+ *
+ * @param {string} deleteruleId
+ * The ID of the QoS rule.
+ */
+ function deleteMinimumPacketRateRule(policyId, deleteRuleId) {
+ return apiService.delete('/api/neutron/qos/policies/' + policyId +
+ '/minimum_packet_rate_rules/' + deleteRuleId).error(function() {
+ toastService.add('error', gettext('Unable to delete the minimum_packet_rate_rule .'));
+ });
+ }
+
// Trunks
/**
diff --git a/openstack_dashboard/static/app/core/openstack-service-api/neutron.service.spec.js b/openstack_dashboard/static/app/core/openstack-service-api/neutron.service.spec.js
index 918db157a..93fdd1f22 100644
--- a/openstack_dashboard/static/app/core/openstack-service-api/neutron.service.spec.js
+++ b/openstack_dashboard/static/app/core/openstack-service-api/neutron.service.spec.js
@@ -329,6 +329,114 @@
"testInput": [
63
]
+ },
+ {
+ "func": "createDSCPMarkingRule",
+ "method": "post",
+ "path": "/api/neutron/qos/policies/63/dscp_marking_rules/",
+ "data": {"dscp_marking_rule":{"dscp_mark":16}},
+ "error": "Unable to add the dscp_marking_rule .",
+ "testInput": [63,
+ {"dscp_marking_rule":{"dscp_mark": 16}}
+ ]
+ },
+ {
+ "func": "createBandwidthLimitRule",
+ "method": "post",
+ "path": "/api/neutron/qos/policies/63/bandwidth_limit_rules/",
+ "data": {"bandwidth_limit_rule": {"max_kbps": 10000}},
+ "error": "Unable to add the bandwidthrule .",
+ "testInput": [63,
+ {"bandwidth_limit_rule": {"max_kbps": 10000}}
+ ]
+ },
+ {
+ "func": "createMinimumBandwidthRule",
+ "method": "post",
+ "path": "/api/neutron/qos/policies/63/minimum_bandwidth_rules/",
+ "data": {"minimum_banwdiwth_rule": {"min_kbps": 1000, "direction": "egress"}},
+ "error": "Unable to add the minimum_bandwidth_rule .",
+ "testInput": [63,
+ {"minimum_banwdiwth_rule": {"min_kbps": 1000, "direction": "egress"}}
+ ]
+ },
+ {
+ "func": "createMinimumPacketRateRule",
+ "method": "post",
+ "path": "/api/neutron/qos/policies/63/minimum_packet_rate_rules/",
+ "data": {"minimum_packet_rate_rule": {"min_kpps": 1000, "direction": "ingress"}},
+ "error": "Unable to add the minimum_packet_rate_rule.",
+ "testInput": [63,
+ {"minimum_packet_rate_rule": {"min_kpps": 1000, "direction": "ingress"}}
+ ]
+ },
+ {
+ "func": "updateDSCPMarkingRule",
+ "method": "patch",
+ "path": "/api/neutron/qos/policies/63/dscp_marking_rules/1",
+ "data": {"dscp_marking_rule":{"dscp_mark":16}},
+ "error": "Unable to update the dscp marking rule.",
+ "testInput": [63, 1,
+ {"dscp_marking_rule":{"dscp_mark": 16}}
+ ]
+ },
+ {
+ "func": "updateBandwidthRule",
+ "method": "patch",
+ "path": "/api/neutron/qos/policies/63/bandwidth_limit_rules/1",
+ "data": {"bandwidth_limit_rule": {"max_kbps": "11000"}},
+ "error": "Unable to update the bandwidthrule.",
+ "testInput": [63, 1,
+ {"bandwidth_limit_rule": {"max_kbps": "11000"}}
+ ]
+ },
+ {
+ "func": "updateMinimumBandwidthRule",
+ "method": "patch",
+ "path": "/api/neutron/qos/policies/63/minimum_bandwidth_rules/1",
+ "data": {"minimum_bandwidth_rule": {"min_kbps": 1000, "direction": "ingress"}},
+ "error": "Unable to update the minimum bandwidth rule.",
+ "testInput": [63, 1,
+ {"minimum_bandwidth_rule": {"min_kbps": 1000, "direction": "ingress"}}
+ ]
+ },
+ {
+ "func": "updateMinimumPacketRateRule",
+ "method": "patch",
+ "path": "/api/neutron/qos/policies/63/minimum_packet_rate_rules/1",
+ "data": {"minimum_packet_rate_rule": {"min_kpps": 1000, "direction": "ingress"}},
+ "error": "Unable to update the minimum packet rate rule.",
+ "testInput": [63, 1,
+ {"minimum_packet_rate_rule": {"min_kpps": 1000, "direction": "ingress"}}
+ ]
+ },
+ {
+ "func": "deleteDSCPMarkingRule",
+ "method": "delete",
+ "path": "/api/neutron/qos/policies/63/dscp_marking_rules/1",
+ "error": "Unable to delete the dscp_marking_rule.",
+ "testInput": [63, 1]
+ },
+ {
+ "func": "deleteBandwidthLimitRule",
+ "method": "delete",
+ "path": "/api/neutron/qos/policies/63/bandwidth_limit_rules/1",
+ "error": "Unable to delete the bandwidth_limit_rule.",
+ "testInput": [63, 1]
+ },
+ {
+ "func": "deleteMinimumBandwidthRule",
+ "method": "delete",
+ "path": "/api/neutron/qos/policies/63/minimum_bandwidth_rules/1",
+ "error": "Unable to delete the minimum_bandwidth_rule .",
+ "testInput": [63, 1]
+ },
+ {
+ "func": "deleteMinimumPacketRateRule",
+ "method": "delete",
+ "path": "/api/neutron/qos/policies/63/minimum_packet_rate_rules/1",
+ "error": "Unable to delete the minimum_packet_rate_rule .",
+ "testInput": [63, 1]
}
];
diff --git a/openstack_dashboard/test/test_data/neutron_data.py b/openstack_dashboard/test/test_data/neutron_data.py
index ef2ec07e0..e902f74c7 100644
--- a/openstack_dashboard/test/test_data/neutron_data.py
+++ b/openstack_dashboard/test/test_data/neutron_data.py
@@ -45,6 +45,10 @@ def data(TEST):
TEST.neutron_quota_usages = utils.TestDataContainer()
TEST.ip_availability = utils.TestDataContainer()
TEST.qos_policies = utils.TestDataContainer()
+ TEST.dscp_mark_rule = utils.TestDataContainer()
+ TEST.bandwidth_limit_rule = utils.TestDataContainer()
+ TEST.minimum_bandwidth_rule = utils.TestDataContainer()
+ TEST.minimum_packet_rate_rule = utils.TestDataContainer()
TEST.rbac_policies = utils.TestDataContainer()
TEST.tp_ports = utils.TestDataContainer()
TEST.neutron_availability_zones = utils.TestDataContainer()
@@ -69,6 +73,10 @@ def data(TEST):
TEST.api_ip_availability = utils.TestDataContainer()
TEST.api_rbac_policies = utils.TestDataContainer()
TEST.api_qos_policies = utils.TestDataContainer()
+ TEST.api_dscp_mark_rule = utils.TestDataContainer()
+ TEST.api_bandwidth_limit_rule = utils.TestDataContainer()
+ TEST.api_minimum_bandwidth_rule = utils.TestDataContainer()
+ TEST.api_minimum_packet_rate_rule = utils.TestDataContainer()
TEST.api_tp_trunks = utils.TestDataContainer()
TEST.api_tp_ports = utils.TestDataContainer()
@@ -807,6 +815,49 @@ def data(TEST):
TEST.api_qos_policies.add(policy_dict1)
TEST.qos_policies.add(neutron.QoSPolicy(policy_dict1))
+ # qos rule - dscp mark
+ dscp_mark_rule_dict = {
+ "id": "5f126d84-551a-4dcf-bb01-0e9c0df0c794",
+ "dscp_mark": 26,
+ "tenant_id": "1"
+ }
+ TEST.api_dscp_mark_rule.add(dscp_mark_rule_dict)
+ TEST.dscp_mark_rule.add(neutron.DSCPMarkingRule(dscp_mark_rule_dict))
+
+ # qos rule - bandwidth limit
+ bandwidth_limit_rule = {
+ "id": "5f126d84-551a-4dcf-bb01-0e9c0df0c793",
+ "max_kbps": 10000,
+ "max_burst_kbps": 0,
+ "direction": "egress",
+ "tenant_id": "1"
+ }
+ TEST.api_bandwidth_limit_rule.add(bandwidth_limit_rule)
+ TEST.bandwidth_limit_rule.add(neutron.BandwidthLimitRule(
+ bandwidth_limit_rule))
+
+ # qos rule - minimum bandwidth
+ minimum_bandwidth_rule = {
+ "id": "1eddf7af-0b4c-42c5-8ae1-390b32f1de08",
+ "min_kbps": 10000,
+ "direction": "egress",
+ "tenant_id": "1"
+ }
+ TEST.api_minimum_bandwidth_rule.add(minimum_bandwidth_rule)
+ TEST.minimum_bandwidth_rule.add(neutron.MinimumBandwidthRule(
+ minimum_bandwidth_rule))
+
+ # qos rule - minimum packet rate
+ minimum_packet_rate_rule = {
+ "id": "1eddf7af-0b4c-42c5-8ae1-390b32f1de08",
+ "min_kpps": 10000,
+ "direction": "egress",
+ "tenant_id": "1"
+ }
+ TEST.api_minimum_packet_rate_rule.add(minimum_packet_rate_rule)
+ TEST.minimum_packet_rate_rule.add(neutron.MinimumPacketRateRule(
+ minimum_packet_rate_rule))
+
# rbac policies
rbac_policy_dict = {"project_id": "1",
"object_type": "network",
diff --git a/openstack_dashboard/test/unit/api/test_neutron.py b/openstack_dashboard/test/unit/api/test_neutron.py
index 9affe7f8b..fe22121a9 100644
--- a/openstack_dashboard/test/unit/api/test_neutron.py
+++ b/openstack_dashboard/test/unit/api/test_neutron.py
@@ -1120,6 +1120,265 @@ class NeutronApiTests(test.APIMockTestCase):
self.assertEqual(qos_policy['name'], ret_val.name)
neutronclient.create_qos_policy.assert_called_once_with(body=post_data)
+ @mock.patch.object(api.neutron, 'neutronclient')
+ def test_dscp_mark_rule_create(self, mock_neutronclient):
+ qos_policy = self.api_qos_policies.first()
+ dscp_mark_rule = self.api_dscp_mark_rule.first()
+ post_data = {'dscp_marking_rule': {
+ "dscp_mark": dscp_mark_rule["dscp_mark"],
+ "tenant_id": dscp_mark_rule["tenant_id"]}
+ }
+
+ neutronclient = mock_neutronclient.return_value
+
+ neutronclient.create_dscp_marking_rule.return_value = {
+ 'dscp_marking_rule': dscp_mark_rule
+ }
+
+ ret_val = api.neutron.dscp_marking_rule_create(
+ self.request,
+ policy_id=qos_policy['id'],
+ dscp_mark=dscp_mark_rule['dscp_mark'])
+
+ self.assertIsInstance(ret_val, api.neutron.DSCPMarkingRule)
+ self.assertEqual(dscp_mark_rule['dscp_mark'], ret_val.dscp_mark)
+ neutronclient.create_dscp_marking_rule.assert_called_once_with(
+ qos_policy['id'], post_data)
+
+ @mock.patch.object(api.neutron, 'neutronclient')
+ def test_dscp_mark_rule_update(self, mock_neutronclient):
+ qos_policy = self.api_qos_policies.first()
+ dscp_mark_rule = self.api_dscp_mark_rule.first()
+ dscp_mark_rule["dscp_mark"] = 28
+ post_data = {'dscp_marking_rule': {
+ "dscp_mark": 28}
+ }
+
+ neutronclient = mock_neutronclient.return_value
+
+ neutronclient.update_dscp_marking_rule.return_value = {
+ 'dscp_marking_rule': dscp_mark_rule
+ }
+
+ ret_val = api.neutron.dscp_marking_rule_update(
+ self.request,
+ policy_id=qos_policy['id'],
+ rule_id=dscp_mark_rule['id'],
+ dscp_mark=dscp_mark_rule['dscp_mark'])
+
+ self.assertIsInstance(ret_val, api.neutron.DSCPMarkingRule)
+ self.assertEqual(
+ dscp_mark_rule['dscp_mark'], ret_val.dscp_mark)
+ neutronclient.update_dscp_marking_rule.assert_called_once_with(
+ dscp_mark_rule['id'], qos_policy['id'], post_data)
+
+ @mock.patch.object(api.neutron, 'neutronclient')
+ def test_dscp_mark_rule_delete(self, mock_neutronclient):
+ qos_policy = self.api_qos_policies.first()
+ dscp_mark_rule = self.api_dscp_mark_rule.first()
+
+ neutronclient = mock_neutronclient.return_value
+
+ neutronclient.delete_dscp_marking_rule.return_value = None
+
+ api.neutron.dscp_marking_rule_delete(
+ self.request, qos_policy['id'], dscp_mark_rule['id'])
+
+ neutronclient.delete_dscp_marking_rule.assert_called_once_with(
+ dscp_mark_rule['id'], qos_policy['id'])
+
+ @mock.patch.object(api.neutron, 'neutronclient')
+ def test_bandwidth_limit_rule_create(self, mock_neutronclient):
+ qos_policy = self.api_qos_policies.first()
+ bwd_limit_rule = self.api_bandwidth_limit_rule.first()
+ post_data = {
+ 'bandwidth_limit_rule': {
+ "max_kbps": bwd_limit_rule["max_kbps"],
+ "tenant_id": bwd_limit_rule["tenant_id"]
+ }
+ }
+
+ neutronclient = mock_neutronclient.return_value
+
+ neutronclient.create_bandwidth_limit_rule.return_value = {
+ 'bandwidth_limit_rule': bwd_limit_rule}
+
+ ret_val = api.neutron.bandwidth_limit_rule_create(
+ self.request,
+ policy_id=qos_policy['id'],
+ max_kbps=bwd_limit_rule["max_kbps"])
+
+ self.assertIsInstance(ret_val, api.neutron.BandwidthLimitRule)
+ self.assertEqual(bwd_limit_rule["max_kbps"], ret_val.max_kbps)
+ neutronclient.create_bandwidth_limit_rule.assert_called_once_with(
+ qos_policy['id'], post_data)
+
+ @mock.patch.object(api.neutron, 'neutronclient')
+ def test_bandwidth_limit_rule_update(self, mock_neutronclient):
+ qos_policy = self.api_qos_policies.first()
+ bwd_limit_rule = self.api_bandwidth_limit_rule.first()
+ bwd_limit_rule["max_kbps"] = 20000
+ post_data = {
+ "bandwidth_limit_rule": {
+ "max_kbps": 20000
+ }
+ }
+
+ neutronclient = mock_neutronclient.return_value
+
+ neutronclient.update_bandwidth_limit_rule.return_value = {
+ 'bandwidth_limit_rule': bwd_limit_rule}
+
+ ret_val = api.neutron.bandwidth_limit_rule_update(
+ self.request,
+ policy_id=qos_policy['id'],
+ rule_id=bwd_limit_rule['id'],
+ max_kbps=bwd_limit_rule["max_kbps"])
+
+ self.assertIsInstance(ret_val, api.neutron.BandwidthLimitRule)
+ self.assertEqual(bwd_limit_rule["max_kbps"], ret_val.max_kbps)
+ neutronclient.update_bandwidth_limit_rule.assert_called_once_with(
+ bwd_limit_rule['id'], qos_policy['id'], post_data)
+
+ @mock.patch.object(api.neutron, 'neutronclient')
+ def test_bandwidth_limit_rule_delete(self, mock_neutronclient):
+ qos_policy = self.api_qos_policies.first()
+ bandwidth_limit_rule = self.api_bandwidth_limit_rule.first()
+
+ neutronclient = mock_neutronclient.return_value
+
+ neutronclient.delete_bandwidth_limit_rule.return_value = None
+
+ api.neutron.bandwidth_limit_rule_delete(
+ self.request, qos_policy['id'], bandwidth_limit_rule['id'])
+
+ neutronclient.delete_bandwidth_limit_rule.assert_called_once_with(
+ bandwidth_limit_rule['id'], qos_policy['id'])
+
+ @mock.patch.object(api.neutron, 'neutronclient')
+ def test_minimum_bandwidth_rule_create(self, mock_neutronclient):
+ qos_policy = self.api_qos_policies.first()
+ min_bwd_rule = self.api_minimum_bandwidth_rule.first()
+ post_data = {'minimum_bandwidth_rule': {
+ "min_kbps": min_bwd_rule["min_kbps"],
+ "tenant_id": min_bwd_rule["tenant_id"]}}
+
+ neutronclient = mock_neutronclient.return_value
+
+ neutronclient.create_minimum_bandwidth_rule.return_value = {
+ 'minimum_bandwidth_rule': min_bwd_rule}
+
+ ret_val = api.neutron.minimum_bandwidth_rule_create(
+ self.request,
+ policy_id=qos_policy['id'],
+ min_kbps=min_bwd_rule["min_kbps"])
+
+ self.assertIsInstance(ret_val, api.neutron.MinimumBandwidthRule)
+ self.assertEqual(min_bwd_rule["min_kbps"], ret_val.min_kbps)
+ neutronclient.create_minimum_bandwidth_rule.assert_called_once_with(
+ qos_policy['id'], post_data)
+
+ @mock.patch.object(api.neutron, 'neutronclient')
+ def test_minimum_bandwidth_rule_update(self, mock_neutronclient):
+ qos_policy = self.api_qos_policies.first()
+ min_bwd_rule = self.api_minimum_bandwidth_rule.first()
+ min_bwd_rule['min_kbps'] = 20000
+ post_data = {'minimum_bandwidth_rule': {
+ "min_kbps": 20000}}
+
+ neutronclient = mock_neutronclient.return_value
+
+ neutronclient.update_minimum_bandwidth_rule.return_value = {
+ 'minimum_bandwidth_rule': min_bwd_rule}
+
+ ret_val = api.neutron.minimum_bandwidth_rule_update(
+ self.request,
+ policy_id=qos_policy['id'],
+ rule_id=min_bwd_rule['id'],
+ min_kbps=min_bwd_rule["min_kbps"])
+
+ self.assertIsInstance(ret_val, api.neutron.MinimumBandwidthRule)
+ self.assertEqual(min_bwd_rule["min_kbps"], ret_val.min_kbps)
+ neutronclient.update_minimum_bandwidth_rule.assert_called_once_with(
+ min_bwd_rule['id'], qos_policy['id'], post_data)
+
+ @mock.patch.object(api.neutron, 'neutronclient')
+ def test_minimum_bandwidth_rule_delete(self, mock_neutronclient):
+ qos_policy = self.api_qos_policies.first()
+ min_bwd_rule = self.api_minimum_bandwidth_rule.first()
+
+ neutronclient = mock_neutronclient.return_value
+
+ neutronclient.delete_minimum_bandwidth_rule.return_value = None
+
+ api.neutron.minimum_bandwidth_rule_delete(
+ self.request, qos_policy['id'], min_bwd_rule['id'])
+
+ neutronclient.delete_minimum_bandwidth_rule.assert_called_once_with(
+ min_bwd_rule['id'], qos_policy['id'])
+
+ @mock.patch.object(api.neutron, 'neutronclient')
+ def test_minimum_packer_rate_rule_create(self, mock_neutronclient):
+ qos_policy = self.api_qos_policies.first()
+ min_pckt_rt_rule = self.api_minimum_packet_rate_rule.first()
+ post_data = {'minimum_packet_rate_rule': {
+ "min_kpps": min_pckt_rt_rule["min_kpps"],
+ "tenant_id": min_pckt_rt_rule["tenant_id"]}}
+
+ neutronclient = mock_neutronclient.return_value
+
+ neutronclient.create_minimum_packet_rate_rule.return_value = {
+ 'minimum_packet_rate_rule': min_pckt_rt_rule}
+
+ ret_val = api.neutron.minimum_packet_rate_rule_create(
+ self.request,
+ policy_id=qos_policy['id'],
+ min_kpps=min_pckt_rt_rule["min_kpps"])
+
+ self.assertIsInstance(ret_val, api.neutron.MinimumPacketRateRule)
+ self.assertEqual(min_pckt_rt_rule['min_kpps'], ret_val.min_kpps)
+ neutronclient.create_minimum_packet_rate_rule.assert_called_once_with(
+ qos_policy['id'], post_data)
+
+ @mock.patch.object(api.neutron, 'neutronclient')
+ def test_minimum_packer_rate_rule_update(self, mock_neutronclient):
+ qos_policy = self.api_qos_policies.first()
+ min_pckt_rt_rule = self.api_minimum_packet_rate_rule.first()
+ min_pckt_rt_rule['min_kpps'] = 11000
+ post_data = {'minimum_packet_rate_rule': {
+ "min_kpps": 11000}}
+
+ neutronclient = mock_neutronclient.return_value
+
+ neutronclient.update_minimum_packet_rate_rule.return_value = {
+ 'minimum_packet_rate_rule': min_pckt_rt_rule}
+
+ ret_val = api.neutron.minimum_packet_rate_rule_update(
+ self.request,
+ policy_id=qos_policy['id'],
+ rule_id=min_pckt_rt_rule['id'],
+ min_kpps=min_pckt_rt_rule["min_kpps"])
+
+ self.assertIsInstance(ret_val, api.neutron.MinimumPacketRateRule)
+ self.assertEqual(min_pckt_rt_rule["min_kpps"], ret_val.min_kpps)
+ neutronclient.update_minimum_packet_rate_rule.assert_called_once_with(
+ min_pckt_rt_rule['id'], qos_policy['id'], post_data)
+
+ @mock.patch.object(api.neutron, 'neutronclient')
+ def test_minimum_packet_rate_rule_delete(self, mock_neutronclient):
+ qos_policy = self.api_qos_policies.first()
+ min_pckt_rt_rule = self.api_minimum_packet_rate_rule.first()
+
+ neutronclient = mock_neutronclient.return_value
+
+ neutronclient.delete_minimum_packet_rate_rule.return_value = None
+
+ api.neutron.minimum_packet_rate_rule_delete(
+ self.request, qos_policy['id'], min_pckt_rt_rule['id'])
+
+ neutronclient.delete_minimum_packet_rate_rule.assert_called_once_with(
+ min_pckt_rt_rule['id'], qos_policy['id'])
+
class NeutronApiSecurityGroupTests(test.APIMockTestCase):
diff --git a/releasenotes/notes/network_qos_rules-cd103f9383b6cdf9.yaml b/releasenotes/notes/network_qos_rules-cd103f9383b6cdf9.yaml
new file mode 100644
index 000000000..ed8f350de
--- /dev/null
+++ b/releasenotes/notes/network_qos_rules-cd103f9383b6cdf9.yaml
@@ -0,0 +1,8 @@
+---
+features:
+ - |
+ Add Rules CRUD operations to the Network QoS Policy.
+
+ Added create, edit, and delete rules operation to the network qos policy.
+ Rules supported - Bandwidth-Limit, Minimum-Bandwidth, DSCP-Marking, and
+ Minimum-Packet-Rate.