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
This commit is contained in:
zitptan 2021-08-17 14:37:00 +05:30 committed by elajkat
parent 12bb9fe518
commit aa83752f20
26 changed files with 3259 additions and 14 deletions

View File

@ -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(

View File

@ -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)

View File

@ -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);
@ -55,6 +61,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',

View File

@ -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);

View File

@ -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;
}
}
})();

View File

@ -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'
);
});
});
})();

View File

@ -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';
};
}
})();

View File

@ -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();
}));
});
})();

View File

@ -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>

View File

@ -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;
}
}
})();

View File

@ -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.'
);
});
});
})();

View File

@ -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;
}
}
})();

View File

@ -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.'
);
});
});
})();

View File

@ -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;
};
}
})();

View File

@ -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();
}));
});
})();

View File

@ -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>

View File

@ -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>

View File

@ -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;
}
})();

View File

@ -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();
});
});
})();

View File

@ -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) {

View File

@ -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>

View File

@ -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
/**

View File

@ -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]
}
];

View File

@ -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",

View File

@ -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):

View File

@ -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.