Add API extension for QoS minimum pps rule
This patch implements support for CRUD operations for QoS minimum packet rate, for example: DELETE /qos/policies/$POLICY_ID/minimum_packet_rate_rules/$RULE_ID Placement or dataplane enforcement is not implemented yet. Partial-Bug: #1922237 See-Also: https://review.opendev.org/785236 Change-Id: Ie994bdab62bab33737f25287e568519c782dea9a
This commit is contained in:
parent
1d450dbddc
commit
56044db26d
@ -38,24 +38,28 @@ QoS supported rule types are now available as ``VALID_RULE_TYPES`` in `QoS rule
|
||||
|
||||
* minimum_bandwidth: Minimum bandwidth constraints on certain types of traffic.
|
||||
|
||||
* minimum_packet_rate: Minimum packet rate constraints on certain types of traffic.
|
||||
|
||||
|
||||
Any QoS driver can claim support for some QoS rule types
|
||||
by providing a driver property called
|
||||
``supported_rules``, the QoS driver manager will recalculate rule types
|
||||
dynamically that the QoS driver supports.
|
||||
dynamically that the QoS driver supports. In the most simple case, the
|
||||
property can be represented by a simple Python list defined on the class.
|
||||
|
||||
The following table shows the Networking back ends, QoS supported rules, and
|
||||
traffic directions (from the VM point of view).
|
||||
|
||||
.. table:: **Networking back ends, supported rules, and traffic direction**
|
||||
|
||||
==================== ======================= ======================= =================== ===================
|
||||
Rule \\ back end Open vSwitch SR-IOV Linux bridge OVN
|
||||
==================== ======================= ======================= =================== ===================
|
||||
Bandwidth limit Egress \\ Ingress Egress (1) Egress \\ Ingress Egress \\ Ingress
|
||||
Minimum bandwidth Egress \\ Ingress (2) Egress \\ Ingress (2) - -
|
||||
DSCP marking Egress - Egress Egress
|
||||
==================== ======================= ======================= =================== ===================
|
||||
==================== ============================= ======================= =================== ===================
|
||||
Rule \\ back end Open vSwitch SR-IOV Linux bridge OVN
|
||||
==================== ============================= ======================= =================== ===================
|
||||
Bandwidth limit Egress \\ Ingress Egress (1) Egress \\ Ingress Egress \\ Ingress
|
||||
Minimum bandwidth Egress \\ Ingress (2) Egress \\ Ingress (2) - -
|
||||
Minimum packet rate - - - -
|
||||
DSCP marking Egress - Egress Egress
|
||||
==================== ============================= ======================= =================== ===================
|
||||
|
||||
.. note::
|
||||
|
||||
@ -78,8 +82,14 @@ traffic directions (from the VM point of view).
|
||||
(1) Since Newton
|
||||
(2) Since Stein
|
||||
|
||||
In the most simple case, the property can be represented by a simple Python
|
||||
list defined on the class.
|
||||
.. table:: **Neutron backends, supported directions and enforcement types for Minimum Packet Rate rule**
|
||||
|
||||
============================ ==================== ==================== ============== =====
|
||||
Enforcement type \ Backend Open vSwitch SR-IOV Linux Bridge OVN
|
||||
============================ ==================== ==================== ============== =====
|
||||
Dataplane - - - -
|
||||
Placement - - - -
|
||||
============================ ==================== ==================== ============== =====
|
||||
|
||||
For an ml2 plug-in, the list of supported QoS rule types and parameters is
|
||||
defined as a common subset of rules supported by all active mechanism drivers.
|
||||
@ -328,6 +338,15 @@ To enable minimum bandwidth rule:
|
||||
"delete_policy_minimum_bandwidth_rule": "rule:regular_user",
|
||||
"update_policy_minimum_bandwidth_rule": "rule:regular_user",
|
||||
|
||||
To enable minimum packet rate rule:
|
||||
|
||||
.. code-block:: none
|
||||
|
||||
"get_policy_minimum_packet_rate_rule": "rule:regular_user",
|
||||
"create_policy_minimum_packet_rate_rule": "rule:regular_user",
|
||||
"delete_policy_minimum_packet_rate_rule": "rule:regular_user",
|
||||
"update_policy_minimum_packet_rate_rule": "rule:regular_user",
|
||||
|
||||
User workflow
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
|
@ -151,6 +151,8 @@ From database point of view, following objects are defined in schema:
|
||||
bits for egress traffic.
|
||||
* QosMinimumBandwidthRule: defines the rule that creates a minimum bandwidth
|
||||
constraint.
|
||||
* QosMinimumPacketRateRule: defines the rule that creates a minimum packet rate
|
||||
constraint.
|
||||
|
||||
All database models are defined under:
|
||||
|
||||
@ -176,6 +178,9 @@ For QoS, the following neutron objects are implemented:
|
||||
characterized by a min_kbps parameter. This rule has also a direction
|
||||
parameter to set the traffic direction, from the instance point of view. The
|
||||
only direction now implemented is egress.
|
||||
* QosMinimumPacketRateRule: defines the minimum assured packet rate rule type,
|
||||
characterized by a min_kpps parameter. This rule has also a direction
|
||||
parameter to set the traffic direction, from the instance point of view.
|
||||
|
||||
Those are defined in:
|
||||
|
||||
|
@ -79,6 +79,13 @@ def build_resource_info(plural_mappings, resource_map, which_service,
|
||||
for collection_name in resource_map:
|
||||
resource_name = plural_mappings[collection_name]
|
||||
params = resource_map.get(collection_name, {})
|
||||
# If SUB_RESOURCE_ATTRIBUTE_MAP was passed in as a resource_map, we
|
||||
# need special handling for it. SUB_RESOURCE_ATTRIBUTE_MAP must have
|
||||
# a 'parent' and 'parameters' keys. 'parameters' key is going to
|
||||
# contain sub-resources that are being extended.
|
||||
parent = params.get('parent')
|
||||
params = params['parameters'] if params.get('parameters') else params
|
||||
|
||||
if translate_name:
|
||||
collection_name = collection_name.replace('_', '-')
|
||||
if register_quota:
|
||||
@ -89,12 +96,14 @@ def build_resource_info(plural_mappings, resource_map, which_service,
|
||||
member_actions=member_actions,
|
||||
allow_bulk=allow_bulk,
|
||||
allow_pagination=True,
|
||||
allow_sorting=True)
|
||||
allow_sorting=True,
|
||||
parent=parent)
|
||||
resource = extensions.ResourceExtension(
|
||||
collection_name,
|
||||
controller,
|
||||
path_prefix=path_prefix,
|
||||
member_actions=member_actions,
|
||||
attr_map=params)
|
||||
attr_map=params,
|
||||
parent=parent)
|
||||
resources.append(resource)
|
||||
return resources
|
||||
|
@ -343,6 +343,61 @@ rules = [
|
||||
deprecated_reason=DEPRECATED_REASON,
|
||||
deprecated_since=versionutils.deprecated.WALLABY)
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name='get_policy_minimum_packet_rate_rule',
|
||||
check_str=base.SYSTEM_OR_PROJECT_READER,
|
||||
scope_types=['system', 'project'],
|
||||
description='Get a QoS minimum packet rate rule',
|
||||
operations=[
|
||||
{
|
||||
'method': 'GET',
|
||||
'path': '/qos/policies/{policy_id}/minimum_packet_rate_rules',
|
||||
},
|
||||
{
|
||||
'method': 'GET',
|
||||
'path': ('/qos/policies/{policy_id}/'
|
||||
'minimum_packet_rate_rules/{rule_id}'),
|
||||
},
|
||||
],
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name='create_policy_minimum_packet_rate_rule',
|
||||
check_str=base.SYSTEM_ADMIN,
|
||||
scope_types=['system'],
|
||||
description='Create a QoS minimum packet rate rule',
|
||||
operations=[
|
||||
{
|
||||
'method': 'POST',
|
||||
'path': '/qos/policies/{policy_id}/minimum_packet_rate_rules',
|
||||
},
|
||||
],
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name='update_policy_minimum_packet_rate_rule',
|
||||
check_str=base.SYSTEM_ADMIN,
|
||||
scope_types=['system'],
|
||||
description='Update a QoS minimum packet rate rule',
|
||||
operations=[
|
||||
{
|
||||
'method': 'PUT',
|
||||
'path': ('/qos/policies/{policy_id}/'
|
||||
'minimum_packet_rate_rules/{rule_id}'),
|
||||
},
|
||||
],
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name='delete_policy_minimum_packet_rate_rule',
|
||||
check_str=base.SYSTEM_ADMIN,
|
||||
scope_types=['system'],
|
||||
description='Delete a QoS minimum packet rate rule',
|
||||
operations=[
|
||||
{
|
||||
'method': 'DELETE',
|
||||
'path': ('/qos/policies/{policy_id}/'
|
||||
'minimum_packet_rate_rules/{rule_id}'),
|
||||
},
|
||||
],
|
||||
),
|
||||
policy.DocumentedRuleDefault(
|
||||
name='get_alias_bandwidth_limit_rule',
|
||||
check_str='rule:get_policy_bandwidth_limit_rule',
|
||||
|
@ -1 +1 @@
|
||||
1bb3393de75d
|
||||
c181bb1d89e4
|
||||
|
@ -0,0 +1,56 @@
|
||||
# Copyright (c) 2021 Ericsson Software Technology
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
|
||||
from alembic import op
|
||||
from neutron_lib import constants as n_const
|
||||
from neutron_lib.db import constants as db_const
|
||||
import sqlalchemy as sa
|
||||
|
||||
from neutron.db import migration
|
||||
|
||||
|
||||
"""qos_minimum_packet_rate_rules
|
||||
|
||||
Revision ID: c181bb1d89e4
|
||||
Revises: 1bb3393de75d
|
||||
Create Date: 2021-07-09 15:47:46.826903
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'c181bb1d89e4'
|
||||
down_revision = '1bb3393de75d'
|
||||
|
||||
# milestone identifier, used by neutron-db-manage
|
||||
neutron_milestone = [migration.YOGA]
|
||||
|
||||
|
||||
def upgrade():
|
||||
op.create_table(
|
||||
'qos_minimum_packet_rate_rules',
|
||||
sa.Column('id', sa.String(db_const.UUID_FIELD_SIZE),
|
||||
primary_key=True),
|
||||
sa.Column('qos_policy_id', sa.String(db_const.UUID_FIELD_SIZE),
|
||||
sa.ForeignKey('qos_policies.id', ondelete='CASCADE'),
|
||||
index=True),
|
||||
sa.Column('min_kpps', sa.Integer(), nullable=False),
|
||||
sa.Column('direction',
|
||||
sa.Enum(*n_const.VALID_DIRECTIONS_AND_ANY,
|
||||
name="qos_minimum_packet_rate_rules_directions"),
|
||||
nullable=False,
|
||||
server_default=n_const.EGRESS_DIRECTION),
|
||||
sa.UniqueConstraint('qos_policy_id', 'direction',
|
||||
name='qos_minimum_packet_rate_rules0qos_policy_id0direction')
|
||||
)
|
@ -218,3 +218,27 @@ class QosPacketRateLimitRule(model_base.HasId, model_base.BASEV2):
|
||||
name="qos_packet_rate_limit_rules0qos_policy_id0direction"),
|
||||
model_base.BASEV2.__table_args__
|
||||
)
|
||||
|
||||
|
||||
class QosMinimumPacketRateRule(model_base.HasId, model_base.BASEV2):
|
||||
__tablename__ = 'qos_minimum_packet_rate_rules'
|
||||
qos_policy_id = sa.Column(sa.String(db_const.UUID_FIELD_SIZE),
|
||||
sa.ForeignKey('qos_policies.id',
|
||||
ondelete='CASCADE'),
|
||||
index=True)
|
||||
min_kpps = sa.Column(sa.Integer(), nullable=False)
|
||||
direction = sa.Column(
|
||||
sa.Enum(*constants.VALID_DIRECTIONS_AND_ANY,
|
||||
name='qos_minimum_packet_rate_rules_directions'),
|
||||
nullable=False,
|
||||
default=constants.EGRESS_DIRECTION,
|
||||
server_default=constants.EGRESS_DIRECTION)
|
||||
revises_on_change = ('qos_policy', )
|
||||
qos_policy = sa.orm.relationship(QosPolicy, load_on_pending=True)
|
||||
|
||||
__table_args__ = (
|
||||
sa.UniqueConstraint(
|
||||
qos_policy_id, direction,
|
||||
name='qos_minimum_packet_rate_rules0qos_policy_id0direction'),
|
||||
model_base.BASEV2.__table_args__
|
||||
)
|
||||
|
@ -88,6 +88,7 @@ class QoSPluginBase(service_base.ServicePluginBase, metaclass=abc.ABCMeta):
|
||||
'bandwidth_limit': rule_object.QosBandwidthLimitRule,
|
||||
'dscp_marking': rule_object.QosDscpMarkingRule,
|
||||
'minimum_bandwidth': rule_object.QosMinimumBandwidthRule,
|
||||
'minimum_packet_rate': rule_object.QosMinimumPacketRateRule,
|
||||
'packet_rate_limit': rule_object.QosPacketRateLimitRule,
|
||||
}
|
||||
|
||||
|
35
neutron/extensions/qos_pps_minimum_rule.py
Normal file
35
neutron/extensions/qos_pps_minimum_rule.py
Normal file
@ -0,0 +1,35 @@
|
||||
# Copyright (c) 2021 Ericsson Software Technology
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from neutron_lib.api.definitions import qos_pps_minimum_rule as apidef
|
||||
from neutron_lib.api import extensions as api_extensions
|
||||
from neutron_lib.plugins import constants as nl_pl_const
|
||||
|
||||
from neutron.api.v2 import resource_helper
|
||||
|
||||
|
||||
class Qos_pps_minimum_rule(api_extensions.APIExtensionDescriptor):
|
||||
api_definition = apidef
|
||||
|
||||
@classmethod
|
||||
def get_resources(cls):
|
||||
plural_mappings = resource_helper.build_plural_mappings(
|
||||
{}, apidef.SUB_RESOURCE_ATTRIBUTE_MAP)
|
||||
|
||||
return resource_helper.build_resource_info(
|
||||
plural_mappings,
|
||||
apidef.SUB_RESOURCE_ATTRIBUTE_MAP,
|
||||
nl_pl_const.QOS,
|
||||
translate_name=True,
|
||||
allow_bulk=True)
|
@ -67,7 +67,8 @@ class QosPolicy(rbac_db.NeutronRbacObject):
|
||||
# Version 1.7: Added floating IP bindings
|
||||
# Version 1.8: Added router gateway QoS policy bindings
|
||||
# Version 1.9: Added QosPacketRateLimitRule
|
||||
VERSION = '1.9'
|
||||
# Version 1.10: Added QosMinimumPacketRateRule
|
||||
VERSION = '1.10'
|
||||
|
||||
# required by RbacNeutronMetaclass
|
||||
rbac_db_cls = QosPolicyRBAC
|
||||
@ -391,6 +392,8 @@ class QosPolicy(rbac_db.NeutronRbacObject):
|
||||
]
|
||||
if _target_version >= (1, 9):
|
||||
names.append(rule_obj_impl.QosPacketRateLimitRule.obj_name())
|
||||
if _target_version >= (1, 10):
|
||||
names.append(rule_obj_impl.QosMinimumPacketRuleRule.obj_name())
|
||||
if 'rules' in primitive and names:
|
||||
primitive['rules'] = filter_rules(names, primitive['rules'])
|
||||
|
||||
|
@ -13,9 +13,12 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from neutron_lib import constants as n_consts
|
||||
from neutron_lib.exceptions import qos as qos_exc
|
||||
from neutron_lib.services.qos import constants as qos_consts
|
||||
|
||||
from neutron.services.qos import constants as qos_constants
|
||||
|
||||
|
||||
def check_bandwidth_rule_conflict(policy, rule_data):
|
||||
"""Implementation of the QoS Rule checker.
|
||||
@ -65,3 +68,33 @@ def check_rules_conflict(policy, rule_obj):
|
||||
new_rule_type=rule_obj.rule_type,
|
||||
rule_id=rule.id,
|
||||
policy_id=policy.id)
|
||||
|
||||
|
||||
def check_min_pps_rule_conflict(policy, rule_obj):
|
||||
"""Implementation of the QoS Rule checker.
|
||||
|
||||
This function checks if the new QoS minimum packet rate rule to be
|
||||
associated with the policy doesn't conflict with the existing rules.
|
||||
Raises an exception if conflict is identified.
|
||||
"""
|
||||
if (getattr(rule_obj, "rule_type", None) !=
|
||||
qos_constants.RULE_TYPE_MINIMUM_PACKET_RATE):
|
||||
return
|
||||
for rule in policy.rules:
|
||||
if rule.rule_type == qos_constants.RULE_TYPE_MINIMUM_PACKET_RATE:
|
||||
# Just like in check_rules_conflict(), we need to avoid raising
|
||||
# exception when compared rules have got same ID.
|
||||
if rule.id == getattr(rule_obj, "id", None):
|
||||
continue
|
||||
# Check if we are mixing directionless and direction-oriented QoS
|
||||
# minimum packet rate rules
|
||||
if getattr(rule_obj, "direction", None) and (
|
||||
(rule_obj.direction == n_consts.ANY_DIRECTION and
|
||||
rule.direction in n_consts.VALID_DIRECTIONS) or
|
||||
(rule_obj.direction in n_consts.VALID_DIRECTIONS and
|
||||
rule.direction == n_consts.ANY_DIRECTION)):
|
||||
raise qos_exc.QoSRuleParameterConflict(
|
||||
rule_value=rule_obj.direction,
|
||||
policy_id=policy["id"],
|
||||
existing_rule=rule.rule_type,
|
||||
existing_value=rule.direction)
|
||||
|
@ -52,11 +52,12 @@ class QosRule(base.NeutronDbObject, metaclass=abc.ABCMeta):
|
||||
# 1.2: Added QosMinimumBandwidthRule
|
||||
# 1.3: Added direction for BandwidthLimitRule
|
||||
# 1.4: Added PacketRateLimitRule
|
||||
# 1.5: Added QosMinimumPacketRateRule
|
||||
#
|
||||
# NOTE(mangelajo): versions need to be handled from the top QosRule object
|
||||
# because it's the only reference QosPolicy can make
|
||||
# to them via obj_relationships version map
|
||||
VERSION = '1.4'
|
||||
VERSION = '1.5'
|
||||
|
||||
fields = {
|
||||
'id': common_types.UUIDField(),
|
||||
@ -186,3 +187,18 @@ class QosPacketRateLimitRule(QosRule):
|
||||
duplicates_compare_fields = ['direction']
|
||||
|
||||
rule_type = qos_constants.RULE_TYPE_PACKET_RATE_LIMIT
|
||||
|
||||
|
||||
@base.NeutronObjectRegistry.register
|
||||
class QosMinimumPacketRateRule(QosRule):
|
||||
|
||||
db_model = qos_db_model.QosMinimumPacketRateRule
|
||||
|
||||
fields = {
|
||||
'min_kpps': obj_fields.IntegerField(nullable=False),
|
||||
'direction': common_types.FlowDirectionAndAnyEnumField(),
|
||||
}
|
||||
|
||||
duplicates_compare_fields = ['direction']
|
||||
|
||||
rule_type = qos_constants.RULE_TYPE_MINIMUM_PACKET_RATE
|
||||
|
@ -34,7 +34,8 @@ class QosRuleType(base.NeutronObject):
|
||||
# Version 1.2: Added QosMinimumBandwidthRule
|
||||
# Version 1.3: Added drivers field
|
||||
# Version 1.4: Added QosPacketRateLimitRule
|
||||
VERSION = '1.4'
|
||||
# Version 1.5: Added QosMinimumPacketRateRule
|
||||
VERSION = '1.5'
|
||||
|
||||
fields = {
|
||||
'type': RuleTypeField(),
|
||||
|
@ -19,6 +19,7 @@ from neutron_lib.services.qos import constants as qos_consts
|
||||
# to neutron-lib after neutron has the new rule.
|
||||
# Add qos rule packet rate limit
|
||||
RULE_TYPE_PACKET_RATE_LIMIT = 'packet_rate_limit'
|
||||
RULE_TYPE_MINIMUM_PACKET_RATE = 'minimum_packet_rate'
|
||||
# NOTE(przszc): Ensure that there are no duplicates in the list. Order of the
|
||||
# items in the list must be stable, as QosRuleType OVO hash value depends on
|
||||
# it.
|
||||
@ -26,5 +27,7 @@ RULE_TYPE_PACKET_RATE_LIMIT = 'packet_rate_limit'
|
||||
# from the list below.
|
||||
VALID_RULE_TYPES = (qos_consts.VALID_RULE_TYPES +
|
||||
([RULE_TYPE_PACKET_RATE_LIMIT] if RULE_TYPE_PACKET_RATE_LIMIT not in
|
||||
qos_consts.VALID_RULE_TYPES else []) +
|
||||
([RULE_TYPE_MINIMUM_PACKET_RATE] if RULE_TYPE_MINIMUM_PACKET_RATE not in
|
||||
qos_consts.VALID_RULE_TYPES else [])
|
||||
)
|
||||
|
@ -22,6 +22,7 @@ from neutron_lib.api.definitions import qos_bw_limit_direction
|
||||
from neutron_lib.api.definitions import qos_bw_minimum_ingress
|
||||
from neutron_lib.api.definitions import qos_default
|
||||
from neutron_lib.api.definitions import qos_port_network_policy
|
||||
from neutron_lib.api.definitions import qos_pps_minimum_rule
|
||||
from neutron_lib.api.definitions import qos_pps_rule
|
||||
from neutron_lib.api.definitions import qos_rule_type_details
|
||||
from neutron_lib.api.definitions import qos_rules_alias
|
||||
@ -51,6 +52,7 @@ from neutron.objects.qos import policy as policy_object
|
||||
from neutron.objects.qos import qos_policy_validator as checker
|
||||
from neutron.objects.qos import rule as rule_object
|
||||
from neutron.objects.qos import rule_type as rule_type_object
|
||||
from neutron.services.qos import constants as qos_constants
|
||||
from neutron.services.qos.drivers import manager
|
||||
|
||||
|
||||
@ -75,6 +77,7 @@ class QoSPlugin(qos.QoSPluginBase):
|
||||
qos_rules_alias.ALIAS,
|
||||
qos_port_network_policy.ALIAS,
|
||||
qos_pps_rule.ALIAS,
|
||||
qos_pps_minimum_rule.ALIAS,
|
||||
]
|
||||
|
||||
__native_pagination_support = True
|
||||
@ -410,7 +413,7 @@ class QoSPlugin(qos.QoSPluginBase):
|
||||
raise qos_exc.QosRuleNotSupportedByNetwork(
|
||||
rule_type=rule.rule_type, network_id=network_id)
|
||||
|
||||
def reject_min_bw_rule_updates(self, context, policy):
|
||||
def reject_rule_update_for_bound_port(self, context, policy):
|
||||
ports = self._get_ports_with_policy(context, policy)
|
||||
for port in ports:
|
||||
# NOTE(bence romsics): In some cases the presence of
|
||||
@ -582,12 +585,15 @@ class QoSPlugin(qos.QoSPluginBase):
|
||||
policy = policy_object.QosPolicy.get_policy_obj(context, policy_id)
|
||||
checker.check_bandwidth_rule_conflict(policy, rule_data)
|
||||
rule = rule_cls(context, qos_policy_id=policy_id, **rule_data)
|
||||
checker.check_min_pps_rule_conflict(policy, rule)
|
||||
checker.check_rules_conflict(policy, rule)
|
||||
rule.create()
|
||||
policy.obj_load_attr('rules')
|
||||
self.validate_policy(context, policy)
|
||||
if rule.rule_type == qos_consts.RULE_TYPE_MINIMUM_BANDWIDTH:
|
||||
self.reject_min_bw_rule_updates(context, policy)
|
||||
if rule.rule_type in (
|
||||
qos_consts.RULE_TYPE_MINIMUM_BANDWIDTH,
|
||||
qos_constants.RULE_TYPE_MINIMUM_PACKET_RATE):
|
||||
self.reject_rule_update_for_bound_port(context, policy)
|
||||
self.driver_manager.call(qos_consts.UPDATE_POLICY_PRECOMMIT,
|
||||
context, policy)
|
||||
|
||||
@ -623,12 +629,15 @@ class QoSPlugin(qos.QoSPluginBase):
|
||||
checker.check_bandwidth_rule_conflict(policy, rule_data)
|
||||
rule = policy.get_rule_by_id(rule_id)
|
||||
rule.update_fields(rule_data, reset_changes=True)
|
||||
checker.check_min_pps_rule_conflict(policy, rule)
|
||||
checker.check_rules_conflict(policy, rule)
|
||||
rule.update()
|
||||
policy.obj_load_attr('rules')
|
||||
self.validate_policy(context, policy)
|
||||
if rule.rule_type == qos_consts.RULE_TYPE_MINIMUM_BANDWIDTH:
|
||||
self.reject_min_bw_rule_updates(context, policy)
|
||||
if rule.rule_type in (
|
||||
qos_consts.RULE_TYPE_MINIMUM_BANDWIDTH,
|
||||
qos_constants.RULE_TYPE_MINIMUM_PACKET_RATE):
|
||||
self.reject_rule_update_for_bound_port(context, policy)
|
||||
self.driver_manager.call(qos_consts.UPDATE_POLICY_PRECOMMIT,
|
||||
context, policy)
|
||||
|
||||
@ -687,8 +696,10 @@ class QoSPlugin(qos.QoSPluginBase):
|
||||
rule = policy.get_rule_by_id(rule_id)
|
||||
rule.delete()
|
||||
policy.obj_load_attr('rules')
|
||||
if rule.rule_type == qos_consts.RULE_TYPE_MINIMUM_BANDWIDTH:
|
||||
self.reject_min_bw_rule_updates(context, policy)
|
||||
if rule.rule_type in (
|
||||
qos_consts.RULE_TYPE_MINIMUM_BANDWIDTH,
|
||||
qos_constants.RULE_TYPE_MINIMUM_PACKET_RATE):
|
||||
self.reject_rule_update_for_bound_port(context, policy)
|
||||
self.driver_manager.call(qos_consts.UPDATE_POLICY_PRECOMMIT,
|
||||
context, policy)
|
||||
|
||||
|
@ -233,6 +233,10 @@ def get_random_flow_direction():
|
||||
return random.choice(constants.VALID_DIRECTIONS)
|
||||
|
||||
|
||||
def get_random_flow_direction_or_any():
|
||||
return random.choice(constants.VALID_DIRECTIONS_AND_ANY)
|
||||
|
||||
|
||||
def get_random_ha_states():
|
||||
return random.choice(constants.VALID_HA_STATES)
|
||||
|
||||
|
@ -1002,3 +1002,172 @@ class ProjectReaderQosMinimumBandwidthRuleTests(
|
||||
def setUp(self):
|
||||
super(ProjectReaderQosMinimumBandwidthRuleTests, self).setUp()
|
||||
self.context = self.project_reader_ctx
|
||||
|
||||
|
||||
class SystemAdminQosMinimumPacketRateRuleTests(QosRulesAPITestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(SystemAdminQosMinimumPacketRateRuleTests, self).setUp()
|
||||
self.context = self.system_admin_ctx
|
||||
|
||||
def test_get_policy_minimum_packet_rate_rule(self):
|
||||
self.assertTrue(
|
||||
policy.enforce(self.context,
|
||||
'get_policy_minimum_packet_rate_rule',
|
||||
self.target))
|
||||
self.assertTrue(
|
||||
policy.enforce(self.context,
|
||||
'get_policy_minimum_packet_rate_rule',
|
||||
self.alt_target))
|
||||
|
||||
def test_create_policy_minimum_packet_rate_rule(self):
|
||||
self.assertTrue(
|
||||
policy.enforce(self.context,
|
||||
'create_policy_minimum_packet_rate_rule',
|
||||
self.target))
|
||||
self.assertTrue(
|
||||
policy.enforce(self.context,
|
||||
'create_policy_minimum_packet_rate_rule',
|
||||
self.alt_target))
|
||||
|
||||
def test_update_policy_minimum_packet_rate_rule(self):
|
||||
self.assertTrue(
|
||||
policy.enforce(self.context,
|
||||
'update_policy_minimum_packet_rate_rule',
|
||||
self.target))
|
||||
self.assertTrue(
|
||||
policy.enforce(self.context,
|
||||
'update_policy_minimum_packet_rate_rule',
|
||||
self.alt_target))
|
||||
|
||||
def test_delete_policy_minimum_packet_rate_rule(self):
|
||||
self.assertTrue(
|
||||
policy.enforce(self.context,
|
||||
'delete_policy_minimum_packet_rate_rule',
|
||||
self.target))
|
||||
self.assertTrue(
|
||||
policy.enforce(self.context,
|
||||
'delete_policy_minimum_packet_rate_rule',
|
||||
self.alt_target))
|
||||
|
||||
|
||||
class SystemMemberQosMinimumPacketRateRuleTests(
|
||||
SystemAdminQosMinimumPacketRateRuleTests):
|
||||
|
||||
def setUp(self):
|
||||
super(SystemMemberQosMinimumPacketRateRuleTests, self).setUp()
|
||||
self.context = self.system_member_ctx
|
||||
|
||||
def test_create_policy_minimum_packet_rate_rule(self):
|
||||
self.assertRaises(
|
||||
base_policy.PolicyNotAuthorized,
|
||||
policy.enforce,
|
||||
self.context, 'create_policy_minimum_packet_rate_rule',
|
||||
self.target)
|
||||
self.assertRaises(
|
||||
base_policy.PolicyNotAuthorized,
|
||||
policy.enforce,
|
||||
self.context, 'create_policy_minimum_packet_rate_rule',
|
||||
self.alt_target)
|
||||
|
||||
def test_update_policy_minimum_packet_rate_rule(self):
|
||||
self.assertRaises(
|
||||
base_policy.PolicyNotAuthorized,
|
||||
policy.enforce,
|
||||
self.context, 'update_policy_minimum_packet_rate_rule',
|
||||
self.target)
|
||||
self.assertRaises(
|
||||
base_policy.PolicyNotAuthorized,
|
||||
policy.enforce,
|
||||
self.context, 'update_policy_minimum_packet_rate_rule',
|
||||
self.alt_target)
|
||||
|
||||
def test_delete_policy_minimum_packet_rate_rule(self):
|
||||
self.assertRaises(
|
||||
base_policy.PolicyNotAuthorized,
|
||||
policy.enforce,
|
||||
self.context, 'delete_policy_minimum_packet_rate_rule',
|
||||
self.target)
|
||||
self.assertRaises(
|
||||
base_policy.PolicyNotAuthorized,
|
||||
policy.enforce,
|
||||
self.context, 'delete_policy_minimum_packet_rate_rule',
|
||||
self.alt_target)
|
||||
|
||||
|
||||
class SystemReaderQosMinimumPacketRateRuleTests(
|
||||
SystemMemberQosMinimumPacketRateRuleTests):
|
||||
|
||||
def setUp(self):
|
||||
super(SystemReaderQosMinimumPacketRateRuleTests, self).setUp()
|
||||
self.context = self.system_reader_ctx
|
||||
|
||||
|
||||
class ProjectAdminQosMinimumPacketRateRuleTests(QosRulesAPITestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(ProjectAdminQosMinimumPacketRateRuleTests, self).setUp()
|
||||
self.context = self.project_admin_ctx
|
||||
|
||||
def test_get_policy_minimum_packet_rate_rule(self):
|
||||
self.assertTrue(
|
||||
policy.enforce(self.context,
|
||||
'get_policy_minimum_packet_rate_rule',
|
||||
self.target))
|
||||
self.assertRaises(
|
||||
base_policy.PolicyNotAuthorized,
|
||||
policy.enforce,
|
||||
self.context, 'get_policy_minimum_packet_rate_rule',
|
||||
self.alt_target)
|
||||
|
||||
def test_create_policy_minimum_packet_rate_rule(self):
|
||||
self.assertRaises(
|
||||
base_policy.PolicyNotAuthorized,
|
||||
policy.enforce,
|
||||
self.context, 'create_policy_minimum_packet_rate_rule',
|
||||
self.target)
|
||||
self.assertRaises(
|
||||
base_policy.PolicyNotAuthorized,
|
||||
policy.enforce,
|
||||
self.context, 'create_policy_minimum_packet_rate_rule',
|
||||
self.alt_target)
|
||||
|
||||
def test_update_policy_minimum_packet_rate_rule(self):
|
||||
self.assertRaises(
|
||||
base_policy.PolicyNotAuthorized,
|
||||
policy.enforce,
|
||||
self.context, 'update_policy_minimum_packet_rate_rule',
|
||||
self.target)
|
||||
self.assertRaises(
|
||||
base_policy.PolicyNotAuthorized,
|
||||
policy.enforce,
|
||||
self.context, 'update_policy_minimum_packet_rate_rule',
|
||||
self.alt_target)
|
||||
|
||||
def test_delete_policy_minimum_packet_rate_rule(self):
|
||||
self.assertRaises(
|
||||
base_policy.PolicyNotAuthorized,
|
||||
policy.enforce,
|
||||
self.context, 'delete_policy_minimum_packet_rate_rule',
|
||||
self.target)
|
||||
self.assertRaises(
|
||||
base_policy.PolicyNotAuthorized,
|
||||
policy.enforce,
|
||||
self.context, 'delete_policy_minimum_packet_rate_rule',
|
||||
self.alt_target)
|
||||
|
||||
|
||||
class ProjectMemberQosMinimumPacketRateRuleTests(
|
||||
ProjectAdminQosMinimumPacketRateRuleTests):
|
||||
|
||||
def setUp(self):
|
||||
super(ProjectMemberQosMinimumPacketRateRuleTests, self).setUp()
|
||||
self.context = self.project_member_ctx
|
||||
|
||||
|
||||
class ProjectReaderQosMinimumPacketRateRuleTests(
|
||||
ProjectMemberQosMinimumPacketRateRuleTests):
|
||||
|
||||
def setUp(self):
|
||||
super(ProjectReaderQosMinimumPacketRateRuleTests, self).setUp()
|
||||
self.context = self.project_reader_ctx
|
||||
|
@ -35,6 +35,7 @@ RULE_OBJ_CLS = {
|
||||
qos_consts.RULE_TYPE_DSCP_MARKING: rule.QosDscpMarkingRule,
|
||||
qos_consts.RULE_TYPE_MINIMUM_BANDWIDTH: rule.QosMinimumBandwidthRule,
|
||||
q_consts.RULE_TYPE_PACKET_RATE_LIMIT: rule.QosPacketRateLimitRule,
|
||||
q_consts.RULE_TYPE_MINIMUM_PACKET_RATE: rule.QosMinimumPacketRateRule,
|
||||
}
|
||||
|
||||
|
||||
@ -101,6 +102,10 @@ class QosPolicyObjectTestCase(test_base.BaseObjectIfaceTestCase):
|
||||
self.get_random_db_fields(rule.QosMinimumBandwidthRule)
|
||||
for _ in range(3)]
|
||||
|
||||
self.db_qos_minimum_packet_rate_rules = [
|
||||
self.get_random_db_fields(rule.QosMinimumPacketRateRule)
|
||||
for _ in range(3)]
|
||||
|
||||
self.model_map.update({
|
||||
self._test_class.db_model: self.db_objs,
|
||||
binding.QosPolicyPortBinding.db_model: [],
|
||||
@ -108,7 +113,9 @@ class QosPolicyObjectTestCase(test_base.BaseObjectIfaceTestCase):
|
||||
rule.QosBandwidthLimitRule.db_model: self.db_qos_bandwidth_rules,
|
||||
rule.QosDscpMarkingRule.db_model: self.db_qos_dscp_rules,
|
||||
rule.QosMinimumBandwidthRule.db_model:
|
||||
self.db_qos_minimum_bandwidth_rules})
|
||||
self.db_qos_minimum_bandwidth_rules,
|
||||
rule.QosMinimumPacketRateRule:
|
||||
self.db_qos_minimum_packet_rate_rules})
|
||||
|
||||
# TODO(ihrachys): stop overriding those test cases, instead base test cases
|
||||
# should be expanded if there are missing bits there to support QoS objects
|
||||
@ -179,7 +186,8 @@ class QosPolicyDbObjectTestCase(test_base.BaseDbObjectTestCase,
|
||||
if (obj_cls.rule_type in [
|
||||
qos_consts.RULE_TYPE_BANDWIDTH_LIMIT,
|
||||
qos_consts.RULE_TYPE_MINIMUM_BANDWIDTH,
|
||||
q_consts.RULE_TYPE_PACKET_RATE_LIMIT] and
|
||||
q_consts.RULE_TYPE_PACKET_RATE_LIMIT,
|
||||
q_consts.RULE_TYPE_MINIMUM_PACKET_RATE] and
|
||||
bwlimit_direction is not None):
|
||||
rule_fields['direction'] = bwlimit_direction
|
||||
rule_obj = obj_cls(self.context, **rule_fields)
|
||||
@ -481,6 +489,22 @@ class QosPolicyDbObjectTestCase(test_base.BaseDbObjectTestCase,
|
||||
self.assertIn(rule_objs[2], policy_obj_v1_8.rules)
|
||||
self.assertNotIn(rule_objs[3], policy_obj_v1_8.rules)
|
||||
|
||||
def test_object_version_degradation_less_than_1_10(self):
|
||||
policy_obj, rule_objs = self._create_test_policy_with_rules(
|
||||
[qos_consts.RULE_TYPE_BANDWIDTH_LIMIT,
|
||||
qos_consts.RULE_TYPE_DSCP_MARKING,
|
||||
qos_consts.RULE_TYPE_MINIMUM_BANDWIDTH,
|
||||
q_consts.RULE_TYPE_PACKET_RATE_LIMIT,
|
||||
q_consts.RULE_TYPE_MINIMUM_PACKET_RATE], reload_rules=True,
|
||||
bwlimit_direction=lib_consts.INGRESS_DIRECTION)
|
||||
policy_obj_v1_9 = self._policy_through_version(policy_obj, '1.9')
|
||||
|
||||
self.assertIn(rule_objs[0], policy_obj_v1_9.rules)
|
||||
self.assertIn(rule_objs[1], policy_obj_v1_9.rules)
|
||||
self.assertIn(rule_objs[2], policy_obj_v1_9.rules)
|
||||
self.assertIn(rule_objs[3], policy_obj_v1_9.rules)
|
||||
self.assertNotIn(rule_objs[4], policy_obj_v1_9.rules)
|
||||
|
||||
@mock.patch.object(policy.QosPolicy, 'unset_default')
|
||||
def test_filter_by_shared(self, *mocks):
|
||||
project_id = uuidutils.generate_uuid()
|
||||
|
@ -290,3 +290,54 @@ class QosPacketRateLimitRuleDbObjectTestCase(test_base.BaseDbObjectTestCase,
|
||||
id=generated_qos_policy_id,
|
||||
project_id=uuidutils.generate_uuid())
|
||||
policy_obj.create()
|
||||
|
||||
|
||||
class QosMinimumPacketRateRuleObjectTestCase(
|
||||
test_base.BaseObjectIfaceTestCase):
|
||||
|
||||
_test_class = rule.QosMinimumPacketRateRule
|
||||
|
||||
def test_to_dict_returns_type(self):
|
||||
obj = rule.QosMinimumPacketRateRule(self.context, **self.db_objs[0])
|
||||
dict_ = obj.to_dict()
|
||||
self.assertEqual(qos_constants.RULE_TYPE_MINIMUM_PACKET_RATE,
|
||||
dict_['type'])
|
||||
|
||||
def test_duplicate_rules(self):
|
||||
policy_id = uuidutils.generate_uuid()
|
||||
ingress_rule_1 = rule.QosMinimumPacketRateRule(
|
||||
self.context, qos_policy_id=policy_id,
|
||||
min_kpps=1000, direction=constants.INGRESS_DIRECTION)
|
||||
ingress_rule_2 = rule.QosMinimumPacketRateRule(
|
||||
self.context, qos_policy_id=policy_id,
|
||||
min_kpps=2000, direction=constants.INGRESS_DIRECTION)
|
||||
egress_rule = rule.QosMinimumPacketRateRule(
|
||||
self.context, qos_policy_id=policy_id,
|
||||
min_kpps=1000, direction=constants.EGRESS_DIRECTION)
|
||||
directionless_rule = rule.QosMinimumPacketRateRule(
|
||||
self.context, qos_policy_id=policy_id,
|
||||
min_kpps=1000, direction=constants.ANY_DIRECTION)
|
||||
min_bw_rule = rule.QosMinimumBandwidthRule(
|
||||
self.context, qos_policy_id=policy_id,
|
||||
min_kbps=1000, direction=constants.INGRESS_DIRECTION)
|
||||
self.assertTrue(ingress_rule_1.duplicates(ingress_rule_2))
|
||||
self.assertFalse(ingress_rule_1.duplicates(egress_rule))
|
||||
self.assertFalse(ingress_rule_1.duplicates(directionless_rule))
|
||||
self.assertFalse(ingress_rule_1.duplicates(min_bw_rule))
|
||||
|
||||
|
||||
class QosMinimumPacketRateRuleDbObjectTestCase(test_base.BaseDbObjectTestCase,
|
||||
testlib_api.SqlTestCase):
|
||||
|
||||
_test_class = rule.QosMinimumPacketRateRule
|
||||
|
||||
def setUp(self):
|
||||
super(QosMinimumPacketRateRuleDbObjectTestCase, self).setUp()
|
||||
# Prepare policy to be able to insert a rule
|
||||
for obj in self.db_objs:
|
||||
generated_qos_policy_id = obj['qos_policy_id']
|
||||
policy_obj = policy.QosPolicy(
|
||||
self.context,
|
||||
id=generated_qos_policy_id,
|
||||
project_id=uuidutils.generate_uuid())
|
||||
policy_obj.create()
|
||||
|
@ -511,6 +511,8 @@ FIELD_TYPE_VALUE_GENERATOR_MAP = {
|
||||
common_types.EtherTypeEnumField: tools.get_random_ether_type,
|
||||
common_types.FloatingIPStatusEnumField: tools.get_random_floatingip_status,
|
||||
common_types.FlowDirectionEnumField: tools.get_random_flow_direction,
|
||||
common_types.FlowDirectionAndAnyEnumField:
|
||||
tools.get_random_flow_direction_or_any,
|
||||
common_types.HARouterEnumField: tools.get_random_ha_states,
|
||||
common_types.IpamAllocationStatusEnumField: tools.get_random_ipam_status,
|
||||
common_types.IPNetworkField: lib_test_tools.get_random_ip_network,
|
||||
|
@ -82,14 +82,15 @@ object_data = {
|
||||
'PortUplinkStatusPropagation': '1.1-f0a4ca451a941910376c33616dea5de2',
|
||||
'ProviderResourceAssociation': '1.0-05ab2d5a3017e5ce9dd381328f285f34',
|
||||
'ProvisioningBlock': '1.0-c19d6d05bfa8143533471c1296066125',
|
||||
'QosBandwidthLimitRule': '1.4-51b662b12a8d1dfa89288d826c6d26d3',
|
||||
'QosDscpMarkingRule': '1.4-0313c6554b34fd10c753cb63d638256c',
|
||||
'QosMinimumBandwidthRule': '1.4-314c3419f4799067cc31cc319080adff',
|
||||
'QosPacketRateLimitRule': '1.4-18411fa95f54602b8c8a5da2d3194b31',
|
||||
'QosBandwidthLimitRule': '1.5-51b662b12a8d1dfa89288d826c6d26d3',
|
||||
'QosDscpMarkingRule': '1.5-0313c6554b34fd10c753cb63d638256c',
|
||||
'QosMinimumBandwidthRule': '1.5-314c3419f4799067cc31cc319080adff',
|
||||
'QosMinimumPacketRateRule': '1.5-d0516c55aa2f310a2646c7d243cb8620',
|
||||
'QosPacketRateLimitRule': '1.5-18411fa95f54602b8c8a5da2d3194b31',
|
||||
'QosPolicyRBAC': '1.1-192845c5ed0718e1c54fac36936fcd7d',
|
||||
'QosRuleType': '1.4-a5b870dfa6f510a91f5cb0216873064e',
|
||||
'QosRuleType': '1.5-56b25ec81e27aa5c8238b8c43e88aed6',
|
||||
'QosRuleTypeDriver': '1.0-7d8cb9f0ef661ac03700eae97118e3db',
|
||||
'QosPolicy': '1.9-4adb0cde3102c10d8970ec9487fd7fe7',
|
||||
'QosPolicy': '1.10-4adb0cde3102c10d8970ec9487fd7fe7',
|
||||
'QosPolicyDefault': '1.0-59e5060eedb1f06dd0935a244d27d11c',
|
||||
'QosPolicyFloatingIPBinding': '1.0-5625df4205a18778cd6aa40f99be024e',
|
||||
'QosPolicyRouterGatewayIPBinding': '1.0-da064fbfe5ee18c950b905b483bf59e3',
|
||||
|
@ -103,7 +103,12 @@ class TestQosPlugin(base.BaseQosTestCase):
|
||||
'packet_rate_limit_rule': {
|
||||
'id': uuidutils.generate_uuid(),
|
||||
'max_kpps': 20,
|
||||
'max_burst_kpps': 130}}
|
||||
'max_burst_kpps': 130},
|
||||
'minimum_packet_rate_rule': {
|
||||
'id': uuidutils.generate_uuid(),
|
||||
'min_kpps': 10,
|
||||
'direction': 'any'},
|
||||
}
|
||||
|
||||
self.policy = policy_object.QosPolicy(
|
||||
self.ctxt, **self.policy_data['policy'])
|
||||
@ -114,12 +119,15 @@ class TestQosPlugin(base.BaseQosTestCase):
|
||||
self.dscp_rule = rule_object.QosDscpMarkingRule(
|
||||
self.ctxt, **self.rule_data['dscp_marking_rule'])
|
||||
|
||||
self.min_rule = rule_object.QosMinimumBandwidthRule(
|
||||
self.min_bw_rule = rule_object.QosMinimumBandwidthRule(
|
||||
self.ctxt, **self.rule_data['minimum_bandwidth_rule'])
|
||||
|
||||
self.pps_rule = rule_object.QosPacketRateLimitRule(
|
||||
self.ctxt, **self.rule_data['packet_rate_limit_rule'])
|
||||
|
||||
self.min_pps_rule = rule_object.QosMinimumPacketRateRule(
|
||||
self.ctxt, **self.rule_data['minimum_packet_rate_rule'])
|
||||
|
||||
def _validate_driver_params(self, method_name, ctxt):
|
||||
call_args = self.qos_plugin.driver_manager.call.call_args[0]
|
||||
self.assertTrue(self.qos_plugin.driver_manager.call.called)
|
||||
@ -158,8 +166,8 @@ class TestQosPlugin(base.BaseQosTestCase):
|
||||
port_res, self.port)
|
||||
|
||||
def test__extend_port_resource_request_min_bw_rule(self):
|
||||
self.min_rule.direction = lib_constants.EGRESS_DIRECTION
|
||||
port = self._create_and_extend_port([self.min_rule])
|
||||
self.min_bw_rule.direction = lib_constants.EGRESS_DIRECTION
|
||||
port = self._create_and_extend_port([self.min_bw_rule])
|
||||
|
||||
self.assertEqual(
|
||||
['CUSTOM_PHYSNET_PUBLIC', 'CUSTOM_VNIC_TYPE_NORMAL'],
|
||||
@ -171,16 +179,17 @@ class TestQosPlugin(base.BaseQosTestCase):
|
||||
)
|
||||
|
||||
def test__extend_port_resource_request_mixed_rules(self):
|
||||
self.min_rule.direction = lib_constants.EGRESS_DIRECTION
|
||||
self.min_bw_rule.direction = lib_constants.EGRESS_DIRECTION
|
||||
|
||||
min_rule_ingress_data = {
|
||||
min_bw_rule_ingress_data = {
|
||||
'id': uuidutils.generate_uuid(),
|
||||
'min_kbps': 20,
|
||||
'direction': lib_constants.INGRESS_DIRECTION}
|
||||
min_rule_ingress = rule_object.QosMinimumBandwidthRule(
|
||||
self.ctxt, **min_rule_ingress_data)
|
||||
min_bw_rule_ingress = rule_object.QosMinimumBandwidthRule(
|
||||
self.ctxt, **min_bw_rule_ingress_data)
|
||||
|
||||
port = self._create_and_extend_port([self.min_rule, min_rule_ingress])
|
||||
port = self._create_and_extend_port(
|
||||
[self.min_bw_rule, min_bw_rule_ingress])
|
||||
self.assertEqual(
|
||||
['CUSTOM_PHYSNET_PUBLIC', 'CUSTOM_VNIC_TYPE_NORMAL'],
|
||||
port['resource_request']['required']
|
||||
@ -199,9 +208,9 @@ class TestQosPlugin(base.BaseQosTestCase):
|
||||
self.assertIsNone(port.get('resource_request'))
|
||||
|
||||
def test__extend_port_resource_request_non_provider_net(self):
|
||||
self.min_rule.direction = lib_constants.EGRESS_DIRECTION
|
||||
self.min_bw_rule.direction = lib_constants.EGRESS_DIRECTION
|
||||
|
||||
port = self._create_and_extend_port([self.min_rule],
|
||||
port = self._create_and_extend_port([self.min_bw_rule],
|
||||
physical_network=None)
|
||||
self.assertIsNone(port.get('resource_request'))
|
||||
|
||||
@ -211,10 +220,10 @@ class TestQosPlugin(base.BaseQosTestCase):
|
||||
self.assertIsNone(port.get('resource_request'))
|
||||
|
||||
def test__extend_port_resource_request_inherited_policy(self):
|
||||
self.min_rule.direction = lib_constants.EGRESS_DIRECTION
|
||||
self.min_rule.qos_policy_id = self.policy.id
|
||||
self.min_bw_rule.direction = lib_constants.EGRESS_DIRECTION
|
||||
self.min_bw_rule.qos_policy_id = self.policy.id
|
||||
|
||||
port = self._create_and_extend_port([self.min_rule],
|
||||
port = self._create_and_extend_port([self.min_bw_rule],
|
||||
has_net_qos_policy=True)
|
||||
self.assertEqual(
|
||||
['CUSTOM_PHYSNET_PUBLIC', 'CUSTOM_VNIC_TYPE_NORMAL'],
|
||||
@ -413,7 +422,7 @@ class TestQosPlugin(base.BaseQosTestCase):
|
||||
|
||||
def test_create_min_bw_rule_on_bound_port(self):
|
||||
policy = self._get_policy()
|
||||
policy.rules = [self.min_rule]
|
||||
policy.rules = [self.min_bw_rule]
|
||||
segment = network_object.NetworkSegment(
|
||||
physical_network='fake physnet')
|
||||
net = network_object.Network(
|
||||
@ -441,7 +450,7 @@ class TestQosPlugin(base.BaseQosTestCase):
|
||||
|
||||
def test_create_min_bw_rule_on_unbound_port(self):
|
||||
policy = self._get_policy()
|
||||
policy.rules = [self.min_rule]
|
||||
policy.rules = [self.min_bw_rule]
|
||||
segment = network_object.NetworkSegment(
|
||||
physical_network='fake physnet')
|
||||
net = network_object.Network(
|
||||
@ -574,9 +583,12 @@ class TestQosPlugin(base.BaseQosTestCase):
|
||||
mock_manager.attach_mock(mock_qos_rule_create, 'create')
|
||||
mock_manager.attach_mock(self.qos_plugin.driver_manager, 'driver')
|
||||
mock_manager.reset_mock()
|
||||
with mock.patch(
|
||||
'neutron.objects.qos.qos_policy_validator'
|
||||
'.check_bandwidth_rule_conflict', return_value=None):
|
||||
with mock.patch('neutron.objects.qos.qos_policy_validator'
|
||||
'.check_bandwidth_rule_conflict',
|
||||
return_value=None), \
|
||||
mock.patch(
|
||||
'neutron.objects.qos.qos_policy_validator'
|
||||
'.check_min_pps_rule_conflict', return_value=None):
|
||||
self.qos_plugin.create_policy_bandwidth_limit_rule(
|
||||
self.ctxt, self.policy.id, self.rule_data)
|
||||
self._validate_driver_params('update_policy', self.ctxt)
|
||||
@ -603,7 +615,7 @@ class TestQosPlugin(base.BaseQosTestCase):
|
||||
|
||||
def test_create_policy_rule_check_rule_max_more_than_min(self):
|
||||
_policy = self._get_policy()
|
||||
setattr(_policy, "rules", [self.min_rule])
|
||||
setattr(_policy, "rules", [self.min_bw_rule])
|
||||
with mock.patch('neutron.objects.qos.policy.QosPolicy.get_object',
|
||||
return_value=_policy) as mock_qos_get_obj:
|
||||
self.qos_plugin.create_policy_bandwidth_limit_rule(
|
||||
@ -615,7 +627,7 @@ class TestQosPlugin(base.BaseQosTestCase):
|
||||
def test_create_policy_rule_check_rule_bwlimit_less_than_minbw(self):
|
||||
_policy = self._get_policy()
|
||||
self.rule_data['bandwidth_limit_rule']['max_kbps'] = 1
|
||||
setattr(_policy, "rules", [self.min_rule])
|
||||
setattr(_policy, "rules", [self.min_bw_rule])
|
||||
with mock.patch('neutron.objects.qos.policy.QosPolicy.get_object',
|
||||
return_value=_policy) as mock_qos_get_obj:
|
||||
self.assertRaises(qos_exc.QoSRuleParameterConflict,
|
||||
@ -690,13 +702,13 @@ class TestQosPlugin(base.BaseQosTestCase):
|
||||
self.mock_qos_load_attr.assert_called_once_with('rules')
|
||||
self._validate_driver_params('update_policy', self.ctxt)
|
||||
|
||||
rules = [self.rule, self.min_rule]
|
||||
rules = [self.rule, self.min_bw_rule]
|
||||
setattr(_policy, "rules", rules)
|
||||
self.mock_qos_load_attr.reset_mock()
|
||||
with mock.patch('neutron.objects.qos.policy.QosPolicy.get_object',
|
||||
return_value=_policy):
|
||||
self.qos_plugin.update_policy_minimum_bandwidth_rule(
|
||||
self.ctxt, self.min_rule.id,
|
||||
self.ctxt, self.min_bw_rule.id,
|
||||
self.policy.id, self.rule_data)
|
||||
self.mock_qos_load_attr.assert_called_once_with('rules')
|
||||
self._validate_driver_params('update_policy', self.ctxt)
|
||||
@ -716,16 +728,17 @@ class TestQosPlugin(base.BaseQosTestCase):
|
||||
self.assertRaises(
|
||||
qos_exc.QoSRuleParameterConflict,
|
||||
self.qos_plugin.update_policy_minimum_bandwidth_rule,
|
||||
self.ctxt, self.min_rule.id,
|
||||
self.ctxt, self.min_bw_rule.id,
|
||||
self.policy.id, self.rule_data)
|
||||
|
||||
def test_update_policy_rule_check_rule_minbw_gr_than_bwlimit(self):
|
||||
_policy = self._get_policy()
|
||||
setattr(_policy, "rules", [self.min_rule])
|
||||
setattr(_policy, "rules", [self.min_bw_rule])
|
||||
with mock.patch('neutron.objects.qos.policy.QosPolicy.get_object',
|
||||
return_value=_policy):
|
||||
self.qos_plugin.update_policy_minimum_bandwidth_rule(
|
||||
self.ctxt, self.min_rule.id, self.policy.id, self.rule_data)
|
||||
self.ctxt, self.min_bw_rule.id, self.policy.id,
|
||||
self.rule_data)
|
||||
self.mock_qos_load_attr.assert_called_once_with('rules')
|
||||
self._validate_driver_params('update_policy', self.ctxt)
|
||||
self.rule_data['bandwidth_limit_rule']['max_kbps'] = 1
|
||||
@ -1260,6 +1273,314 @@ class TestQosPlugin(base.BaseQosTestCase):
|
||||
self.qos_plugin.get_rule_type,
|
||||
self.ctxt, qos_constants.RULE_TYPE_PACKET_RATE_LIMIT)
|
||||
|
||||
def test_create_min_pps_rule_on_bound_port(self):
|
||||
_policy = self._get_policy()
|
||||
setattr(_policy, "rules", [self.min_pps_rule])
|
||||
segment = network_object.NetworkSegment(
|
||||
physical_network='fake physnet')
|
||||
net = network_object.Network(
|
||||
self.ctxt,
|
||||
segments=[segment])
|
||||
port = ports_object.Port(
|
||||
self.ctxt,
|
||||
id=uuidutils.generate_uuid(),
|
||||
network_id=uuidutils.generate_uuid(),
|
||||
device_owner='compute:fake-zone')
|
||||
with mock.patch(
|
||||
'neutron.objects.qos.policy.QosPolicy.get_object',
|
||||
return_value=_policy), \
|
||||
mock.patch(
|
||||
'neutron.objects.network.Network.get_object',
|
||||
return_value=net), \
|
||||
mock.patch.object(
|
||||
self.qos_plugin,
|
||||
'_get_ports_with_policy',
|
||||
return_value=[port]):
|
||||
self.assertRaises(
|
||||
NotImplementedError,
|
||||
self.qos_plugin.create_policy_minimum_packet_rate_rule,
|
||||
self.ctxt, _policy.id, self.rule_data)
|
||||
|
||||
def test_create_min_pps_rule_on_unbound_port(self):
|
||||
_policy = self._get_policy()
|
||||
setattr(_policy, "rules", [self.min_pps_rule])
|
||||
segment = network_object.NetworkSegment(
|
||||
physical_network='fake physnet')
|
||||
net = network_object.Network(
|
||||
self.ctxt,
|
||||
segments=[segment])
|
||||
port = ports_object.Port(
|
||||
self.ctxt,
|
||||
id=uuidutils.generate_uuid(),
|
||||
network_id=uuidutils.generate_uuid(),
|
||||
device_owner='')
|
||||
with mock.patch(
|
||||
'neutron.objects.qos.policy.QosPolicy.get_object',
|
||||
return_value=_policy), \
|
||||
mock.patch(
|
||||
'neutron.objects.network.Network.get_object',
|
||||
return_value=net), \
|
||||
mock.patch.object(
|
||||
self.qos_plugin,
|
||||
'_get_ports_with_policy',
|
||||
return_value=[port]):
|
||||
try:
|
||||
self.qos_plugin.create_policy_minimum_packet_rate_rule(
|
||||
self.ctxt, _policy.id, self.rule_data)
|
||||
except NotImplementedError:
|
||||
self.fail()
|
||||
|
||||
def test_create_policy_rule_check_rule_min_pps_direction_conflict(self):
|
||||
_policy = self._get_policy()
|
||||
self.rule_data['minimum_packet_rate_rule']['direction'] = 'any'
|
||||
setattr(_policy, "rules", [self.min_pps_rule])
|
||||
rules = [
|
||||
{
|
||||
'minimum_packet_rate_rule': {
|
||||
'id': uuidutils.generate_uuid(),
|
||||
'min_kpps': 10,
|
||||
'direction': 'ingress'
|
||||
}
|
||||
},
|
||||
{
|
||||
'minimum_packet_rate_rule': {
|
||||
'id': uuidutils.generate_uuid(),
|
||||
'min_kpps': 10,
|
||||
'direction': 'egress'
|
||||
}
|
||||
},
|
||||
]
|
||||
for new_rule_data in rules:
|
||||
with mock.patch('neutron.objects.qos.policy.QosPolicy.get_object',
|
||||
return_value=_policy) as mock_qos_get_obj:
|
||||
self.assertRaises(qos_exc.QoSRuleParameterConflict,
|
||||
self.qos_plugin.create_policy_minimum_packet_rate_rule,
|
||||
self.ctxt, self.policy.id, new_rule_data)
|
||||
mock_qos_get_obj.assert_called_once_with(self.ctxt,
|
||||
id=_policy.id)
|
||||
|
||||
for rule_data in rules:
|
||||
min_pps_rule = rule_object.QosMinimumPacketRateRule(
|
||||
self.ctxt, **rule_data['minimum_packet_rate_rule'])
|
||||
setattr(_policy, "rules", [min_pps_rule])
|
||||
with mock.patch('neutron.objects.qos.policy.QosPolicy.get_object',
|
||||
return_value=_policy) as mock_qos_get_obj:
|
||||
self.assertRaises(qos_exc.QoSRuleParameterConflict,
|
||||
self.qos_plugin.create_policy_minimum_packet_rate_rule,
|
||||
self.ctxt, self.policy.id, self.rule_data)
|
||||
mock_qos_get_obj.assert_called_once_with(self.ctxt,
|
||||
id=_policy.id)
|
||||
|
||||
def test_create_policy_min_pps_rule(self):
|
||||
_policy = self._get_policy()
|
||||
setattr(_policy, "rules", [self.min_pps_rule])
|
||||
with mock.patch('neutron.objects.qos.policy.QosPolicy.get_object',
|
||||
return_value=_policy):
|
||||
self.qos_plugin.create_policy_minimum_packet_rate_rule(
|
||||
self.ctxt, self.policy.id, self.rule_data)
|
||||
self._validate_driver_params('update_policy', self.ctxt)
|
||||
|
||||
def test_create_policy_min_pps_rule_duplicates(self):
|
||||
_policy = self._get_policy()
|
||||
setattr(_policy, "rules", [self.min_pps_rule])
|
||||
new_rule_data = {
|
||||
'minimum_packet_rate_rule': {
|
||||
'id': uuidutils.generate_uuid(),
|
||||
'min_kpps': 1234,
|
||||
'direction': self.min_pps_rule.direction,
|
||||
},
|
||||
}
|
||||
|
||||
with mock.patch('neutron.objects.qos.policy.QosPolicy.get_object',
|
||||
return_value=_policy) as mock_qos_get_obj:
|
||||
self.assertRaises(
|
||||
qos_exc.QoSRulesConflict,
|
||||
self.qos_plugin.create_policy_minimum_packet_rate_rule,
|
||||
self.ctxt, _policy.id, new_rule_data)
|
||||
mock_qos_get_obj.assert_called_once_with(self.ctxt, id=_policy.id)
|
||||
|
||||
def test_create_policy_min_pps_rule_for_nonexistent_policy(self):
|
||||
with mock.patch('neutron.objects.qos.policy.QosPolicy.get_object',
|
||||
return_value=None):
|
||||
self.assertRaises(
|
||||
qos_exc.QosPolicyNotFound,
|
||||
self.qos_plugin.create_policy_minimum_packet_rate_rule,
|
||||
self.ctxt, self.policy.id, self.rule_data)
|
||||
|
||||
def test_update_policy_min_pps_rule(self):
|
||||
_policy = self._get_policy()
|
||||
setattr(_policy, "rules", [self.min_pps_rule])
|
||||
with mock.patch('neutron.objects.qos.policy.QosPolicy.get_object',
|
||||
return_value=_policy):
|
||||
self.qos_plugin.update_policy_minimum_packet_rate_rule(
|
||||
self.ctxt, self.min_pps_rule.id, self.policy.id,
|
||||
self.rule_data)
|
||||
self._validate_driver_params('update_policy', self.ctxt)
|
||||
|
||||
def test_update_policy_rule_check_rule_min_pps_direction_conflict(self):
|
||||
_policy = self._get_policy()
|
||||
rules_data = [
|
||||
{
|
||||
'minimum_packet_rate_rule': {
|
||||
'id': uuidutils.generate_uuid(),
|
||||
'min_kpps': 10,
|
||||
'direction': 'ingress'
|
||||
}
|
||||
},
|
||||
{
|
||||
'minimum_packet_rate_rule': {
|
||||
'id': uuidutils.generate_uuid(),
|
||||
'min_kpps': 10,
|
||||
'direction': 'egress'
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
self.rule_data['minimum_packet_rate_rule']['direction'] = 'any'
|
||||
for rule_data in rules_data:
|
||||
rules = [
|
||||
rule_object.QosMinimumPacketRateRule(
|
||||
self.ctxt, **rules_data[0]['minimum_packet_rate_rule']),
|
||||
rule_object.QosMinimumPacketRateRule(
|
||||
self.ctxt, **rules_data[1]['minimum_packet_rate_rule']),
|
||||
]
|
||||
setattr(_policy, 'rules', rules)
|
||||
with mock.patch('neutron.objects.qos.policy.QosPolicy.get_object',
|
||||
return_value=_policy) as mock_qos_get_obj:
|
||||
self.assertRaises(qos_exc.QoSRuleParameterConflict,
|
||||
self.qos_plugin.update_policy_minimum_packet_rate_rule,
|
||||
self.ctxt, rule_data['minimum_packet_rate_rule']['id'],
|
||||
self.policy.id, self.rule_data)
|
||||
mock_qos_get_obj.assert_called_once_with(self.ctxt,
|
||||
id=_policy.id)
|
||||
|
||||
def test_update_policy_min_pps_rule_bad_policy(self):
|
||||
_policy = self._get_policy()
|
||||
setattr(_policy, "rules", [])
|
||||
with mock.patch('neutron.objects.qos.policy.QosPolicy.get_object',
|
||||
return_value=_policy):
|
||||
self.assertRaises(
|
||||
qos_exc.QosRuleNotFound,
|
||||
self.qos_plugin.update_policy_minimum_packet_rate_rule,
|
||||
self.ctxt, self.min_pps_rule.id, self.policy.id,
|
||||
self.rule_data)
|
||||
|
||||
def test_update_policy_min_pps_rule_for_nonexistent_policy(self):
|
||||
with mock.patch('neutron.objects.qos.policy.QosPolicy.get_object',
|
||||
return_value=None):
|
||||
self.assertRaises(
|
||||
qos_exc.QosPolicyNotFound,
|
||||
self.qos_plugin.update_policy_minimum_packet_rate_rule,
|
||||
self.ctxt, self.min_pps_rule.id, self.policy.id,
|
||||
self.rule_data)
|
||||
|
||||
def test_delete_policy_min_pps_rule(self):
|
||||
_policy = self._get_policy()
|
||||
setattr(_policy, "rules", [self.min_pps_rule])
|
||||
with mock.patch('neutron.objects.qos.policy.QosPolicy.get_object',
|
||||
return_value=_policy):
|
||||
self.qos_plugin.delete_policy_minimum_packet_rate_rule(
|
||||
self.ctxt, self.min_pps_rule.id, self.policy.id)
|
||||
self._validate_driver_params('update_policy', self.ctxt)
|
||||
|
||||
def test_delete_policy_min_pps_rule_bad_policy(self):
|
||||
_policy = self._get_policy()
|
||||
setattr(_policy, "rules", [])
|
||||
with mock.patch('neutron.objects.qos.policy.QosPolicy.get_object',
|
||||
return_value=_policy):
|
||||
self.assertRaises(
|
||||
qos_exc.QosRuleNotFound,
|
||||
self.qos_plugin.delete_policy_minimum_packet_rate_rule,
|
||||
self.ctxt, self.min_pps_rule.id, _policy.id)
|
||||
|
||||
def test_delete_policy_min_pps_rule_for_nonexistent_policy(self):
|
||||
with mock.patch('neutron.objects.qos.policy.QosPolicy.get_object',
|
||||
return_value=None):
|
||||
self.assertRaises(
|
||||
qos_exc.QosPolicyNotFound,
|
||||
self.qos_plugin.delete_policy_minimum_packet_rate_rule,
|
||||
self.ctxt, self.min_pps_rule.id, self.policy.id)
|
||||
|
||||
def test_get_policy_min_pps_rule(self):
|
||||
with mock.patch('neutron.objects.qos.policy.QosPolicy.get_object',
|
||||
return_value=self.policy):
|
||||
with mock.patch('neutron.objects.qos.rule.'
|
||||
'QosMinimumPacketRateRule.'
|
||||
'get_object') as get_object_mock:
|
||||
self.qos_plugin.get_policy_minimum_packet_rate_rule(
|
||||
self.ctxt, self.min_pps_rule.id, self.policy.id)
|
||||
get_object_mock.assert_called_once_with(
|
||||
self.ctxt, id=self.min_pps_rule.id)
|
||||
|
||||
def test_get_policy_min_pps_rules_for_policy(self):
|
||||
with mock.patch('neutron.objects.qos.policy.QosPolicy.get_object',
|
||||
return_value=self.policy):
|
||||
with mock.patch('neutron.objects.qos.rule.'
|
||||
'QosMinimumPacketRateRule.'
|
||||
'get_objects') as get_objects_mock:
|
||||
self.qos_plugin.get_policy_minimum_packet_rate_rules(
|
||||
self.ctxt, self.policy.id)
|
||||
get_objects_mock.assert_called_once_with(
|
||||
self.ctxt, _pager=mock.ANY, qos_policy_id=self.policy.id)
|
||||
|
||||
def test_get_policy_min_pps_rules_for_policy_with_filters(self):
|
||||
with mock.patch('neutron.objects.qos.policy.QosPolicy.get_object',
|
||||
return_value=self.policy):
|
||||
with mock.patch('neutron.objects.qos.rule.'
|
||||
'QosMinimumPacketRateRule.'
|
||||
'get_objects') as get_objects_mock:
|
||||
filters = {'filter': 'filter_id'}
|
||||
self.qos_plugin.get_policy_minimum_packet_rate_rules(
|
||||
self.ctxt, self.policy.id, filters=filters)
|
||||
get_objects_mock.assert_called_once_with(
|
||||
self.ctxt, _pager=mock.ANY,
|
||||
qos_policy_id=self.policy.id,
|
||||
filter='filter_id')
|
||||
|
||||
def test_get_policy_min_pps_rule_for_nonexistent_policy(self):
|
||||
with mock.patch('neutron.objects.qos.policy.QosPolicy.get_object',
|
||||
return_value=None):
|
||||
self.assertRaises(
|
||||
qos_exc.QosPolicyNotFound,
|
||||
self.qos_plugin.get_policy_minimum_packet_rate_rule,
|
||||
self.ctxt, self.min_pps_rule.id, self.policy.id)
|
||||
|
||||
def test_get_policy_min_pps_rules_for_nonexistent_policy(self):
|
||||
with mock.patch('neutron.objects.qos.policy.QosPolicy.get_object',
|
||||
return_value=None):
|
||||
self.assertRaises(
|
||||
qos_exc.QosPolicyNotFound,
|
||||
self.qos_plugin.get_policy_minimum_packet_rate_rules,
|
||||
self.ctxt, self.policy.id)
|
||||
|
||||
def test_get_min_pps_rule_type(self):
|
||||
admin_ctxt = context.get_admin_context()
|
||||
drivers_details = [{
|
||||
'name': 'fake-driver',
|
||||
'supported_parameters': [{
|
||||
'parameter_name': 'min_kpps',
|
||||
'parameter_type': lib_constants.VALUES_TYPE_RANGE,
|
||||
'parameter_range': {'start': 0, 'end': 100}
|
||||
}]
|
||||
}]
|
||||
with mock.patch.object(
|
||||
qos_plugin.QoSPlugin, "supported_rule_type_details",
|
||||
return_value=drivers_details
|
||||
):
|
||||
rule_type_details = self.qos_plugin.get_rule_type(
|
||||
admin_ctxt, qos_constants.RULE_TYPE_MINIMUM_PACKET_RATE)
|
||||
self.assertEqual(
|
||||
qos_constants.RULE_TYPE_MINIMUM_PACKET_RATE,
|
||||
rule_type_details['type'])
|
||||
self.assertEqual(
|
||||
drivers_details, rule_type_details['drivers'])
|
||||
|
||||
def test_get_min_pps_rule_type_as_user(self):
|
||||
self.assertRaises(
|
||||
lib_exc.NotAuthorized,
|
||||
self.qos_plugin.get_rule_type,
|
||||
self.ctxt, qos_constants.RULE_TYPE_MINIMUM_PACKET_RATE)
|
||||
|
||||
|
||||
class QoSRuleAliasTestExtensionManager(object):
|
||||
|
||||
|
@ -0,0 +1,5 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Added new API extension to QoS service plugin to support CRUD operations
|
||||
for minimum packet rate rule in Neutron server.
|
@ -235,6 +235,7 @@ neutron.objects =
|
||||
QosBandwidthLimitRule = neutron.objects.qos.rule:QosBandwidthLimitRule
|
||||
QosDscpMarkingRule = neutron.objects.qos.rule:QosDscpMarkingRule
|
||||
QosMinimumBandwidthRule = neutron.objects.qos.rule:QosMinimumBandwidthRule
|
||||
QosMinimumPacketRateRule = neutron.objects.qos.rule:QosMinimumPacketRateRule
|
||||
QosPacketRateLimitRule = neutron.objects.qos.rule:QosPacketRateLimitRule
|
||||
QosPolicy = neutron.objects.qos.policy:QosPolicy
|
||||
QosPolicyDefault = neutron.objects.qos.policy:QosPolicyDefault
|
||||
|
Loading…
Reference in New Issue
Block a user