Add network QoS inheritance to floating IP
Added information of the floating IP network QoS policy to the ``FloatingIP`` OVO. The view-only parameter added allows to check the network QoS policy in the floating IP object. This patch does not implement any change in the L3 code (OVS or OVN). This patch does not change any existing behaviour. NOTE: bump neutron-lib version Depends-On: https://review.opendev.org/c/openstack/neutron-lib/+/817936 Partial-Bug: #1950454 Change-Id: I9d7bb54b14fb983161fdf51c96b6fda107db4fe6
This commit is contained in:
parent
6a73a362c5
commit
42cfa055c2
@ -26,11 +26,12 @@ class FloatingQoSDbMixin(object):
|
||||
@staticmethod
|
||||
@resource_extend.extends([l3_apidef.FLOATINGIPS])
|
||||
def _extend_extra_fip_dict(fip_res, fip_db):
|
||||
if fip_db.get('qos_policy_binding'):
|
||||
fip_res[qos_consts.QOS_POLICY_ID] = (
|
||||
fip_db.qos_policy_binding.policy_id)
|
||||
else:
|
||||
fip_res[qos_consts.QOS_POLICY_ID] = None
|
||||
qos_id = (fip_db.qos_policy_binding.policy_id if
|
||||
fip_db.qos_policy_binding else None)
|
||||
fip_res[qos_consts.QOS_POLICY_ID] = qos_id
|
||||
qos_id = (fip_db.qos_network_policy_binding.policy_id if
|
||||
fip_db.qos_network_policy_binding else None)
|
||||
fip_res[qos_consts.QOS_NETWORK_POLICY_ID] = qos_id
|
||||
return fip_res
|
||||
|
||||
def _create_fip_qos_db(self, context, fip_id, policy_id):
|
||||
|
@ -61,6 +61,14 @@ class QosNetworkPolicyBinding(model_base.BASEV2):
|
||||
backref=sa.orm.backref('qos_network_policy_binding', uselist=False,
|
||||
lazy='joined'),
|
||||
sync_backref=False, viewonly=True)
|
||||
floatingip = sa.orm.relationship(
|
||||
l3.FloatingIP,
|
||||
primaryjoin=('QosNetworkPolicyBinding.network_id == '
|
||||
'FloatingIP.floating_network_id'),
|
||||
foreign_keys=network_id,
|
||||
backref=sa.orm.backref('qos_network_policy_binding', uselist=False,
|
||||
lazy='joined'),
|
||||
sync_backref=False, viewonly=True)
|
||||
|
||||
|
||||
class QosFIPPolicyBinding(model_base.BASEV2):
|
||||
|
20
neutron/extensions/qos_fip_network_policy.py
Normal file
20
neutron/extensions/qos_fip_network_policy.py
Normal file
@ -0,0 +1,20 @@
|
||||
# Copyright (c) 2021 Red Hat, Inc.
|
||||
#
|
||||
# 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_fip_network_policy
|
||||
from neutron_lib.api import extensions as api_extensions
|
||||
|
||||
|
||||
class Qos_fip_network_policy(api_extensions.APIExtensionDescriptor):
|
||||
api_definition = qos_fip_network_policy
|
@ -235,7 +235,8 @@ class Router(base.NeutronDbObject):
|
||||
class FloatingIP(base.NeutronDbObject):
|
||||
# Version 1.0: Initial version
|
||||
# Version 1.1: Added qos_policy_id field
|
||||
VERSION = '1.1'
|
||||
# Version 1.2: Added qos_network_policy_id field
|
||||
VERSION = '1.2'
|
||||
|
||||
db_model = l3.FloatingIP
|
||||
|
||||
@ -248,6 +249,8 @@ class FloatingIP(base.NeutronDbObject):
|
||||
'fixed_port_id': common_types.UUIDField(nullable=True),
|
||||
'fixed_ip_address': obj_fields.IPAddressField(nullable=True),
|
||||
'qos_policy_id': common_types.UUIDField(nullable=True, default=None),
|
||||
'qos_network_policy_id': common_types.UUIDField(nullable=True,
|
||||
default=None),
|
||||
'router_id': common_types.UUIDField(nullable=True),
|
||||
'last_known_router_id': common_types.UUIDField(nullable=True),
|
||||
'status': common_types.FloatingIPStatusEnumField(nullable=True),
|
||||
@ -257,6 +260,7 @@ class FloatingIP(base.NeutronDbObject):
|
||||
'floating_network_id', 'floating_port_id']
|
||||
synthetic_fields = ['dns',
|
||||
'qos_policy_id',
|
||||
'qos_network_policy_id',
|
||||
]
|
||||
|
||||
@classmethod
|
||||
@ -314,13 +318,18 @@ class FloatingIP(base.NeutronDbObject):
|
||||
if db_obj.get('qos_policy_binding'):
|
||||
self.qos_policy_id = db_obj.qos_policy_binding.policy_id
|
||||
fields_to_change.append('qos_policy_id')
|
||||
|
||||
if db_obj.get('qos_network_policy_binding'):
|
||||
self.qos_network_policy_id = (
|
||||
db_obj.qos_network_policy_binding.policy_id)
|
||||
fields_to_change.append('qos_network_policy_binding')
|
||||
self.obj_reset_changes(fields_to_change)
|
||||
|
||||
def obj_make_compatible(self, primitive, target_version):
|
||||
_target_version = versionutils.convert_version_to_tuple(target_version)
|
||||
if _target_version < (1, 1):
|
||||
primitive.pop('qos_policy_id', None)
|
||||
if _target_version < (1, 2):
|
||||
primitive.pop('qos_network_policy_id', None)
|
||||
|
||||
@classmethod
|
||||
def get_scoped_floating_ips(cls, context, router_ids):
|
||||
|
@ -2746,8 +2746,9 @@ class L3NatTestCaseBase(L3NatTestCaseMixin):
|
||||
port_id=port_id,
|
||||
router_id=router_id)
|
||||
skip = ('description', 'dns_domain', 'dns_name',
|
||||
'port_details', 'qos_policy_id', 'revision_number',
|
||||
'status', 'standard_attr_id')
|
||||
'port_details', 'qos_network_policy_id',
|
||||
'qos_policy_id', 'revision_number', 'status',
|
||||
'standard_attr_id')
|
||||
for k in skip:
|
||||
payload.states[0].pop(k, None)
|
||||
payload.states[1].pop(k, None)
|
||||
@ -2793,8 +2794,9 @@ class L3NatTestCaseBase(L3NatTestCaseMixin):
|
||||
port_id=None,
|
||||
router_id=None)
|
||||
skip = ('description', 'dns_domain', 'dns_name',
|
||||
'port_details', 'qos_policy_id', 'revision_number',
|
||||
'status', 'standard_attr_id')
|
||||
'port_details', 'qos_network_policy_id',
|
||||
'qos_policy_id', 'revision_number', 'status',
|
||||
'standard_attr_id')
|
||||
for k in skip:
|
||||
payload.states[0].pop(k, None)
|
||||
payload.states[1].pop(k, None)
|
||||
@ -2839,8 +2841,9 @@ class L3NatTestCaseBase(L3NatTestCaseMixin):
|
||||
port_id=None,
|
||||
router_id=None)
|
||||
skip = ('description', 'dns_domain', 'dns_name',
|
||||
'port_details', 'qos_policy_id', 'revision_number',
|
||||
'status', 'standard_attr_id')
|
||||
'port_details', 'qos_network_policy_id',
|
||||
'qos_policy_id', 'revision_number', 'status',
|
||||
'standard_attr_id')
|
||||
for k in skip:
|
||||
payload.states[0].pop(k, None)
|
||||
payload.states[1].pop(k, None)
|
||||
|
@ -205,6 +205,20 @@ class FakeStandardAttribute(object):
|
||||
self.revision_number = revision_number
|
||||
|
||||
|
||||
class FakeQosNetworkPolicyBinding(object):
|
||||
|
||||
def __init__(self, policy_id=mock.ANY, network_id=mock.ANY):
|
||||
self.policy_id = policy_id
|
||||
self.network_id = network_id
|
||||
|
||||
|
||||
class FakeQosFIPPolicyBinding(object):
|
||||
|
||||
def __init__(self, policy_id=mock.ANY, fip_id=mock.ANY):
|
||||
self.policy_id = policy_id
|
||||
self.fip_id = fip_id
|
||||
|
||||
|
||||
class FakeResource(dict):
|
||||
|
||||
def __init__(self, manager=None, info=None, loaded=False, methods=None):
|
||||
@ -688,6 +702,8 @@ class FakeFloatingIp(object):
|
||||
'dns_name': '',
|
||||
'project_id': '',
|
||||
'standard_attr': FakeStandardAttribute(),
|
||||
'qos_policy_binding': FakeQosFIPPolicyBinding(),
|
||||
'qos_network_policy_binding': FakeQosNetworkPolicyBinding(),
|
||||
}
|
||||
|
||||
# Overwrite default attributes.
|
||||
|
@ -46,7 +46,7 @@ object_data = {
|
||||
'FlatAllocation': '1.0-bf666f24f4642b047eeca62311fbcb41',
|
||||
'Flavor': '1.0-82194de5c9aafce08e8527bb7977f5c6',
|
||||
'FlavorServiceProfileBinding': '1.0-a2c8731e16cefdac4571f80abf1f8930',
|
||||
'FloatingIP': '1.1-595514f8e992849cfc67981d1fd6614e',
|
||||
'FloatingIP': '1.2-fb6675ea98d2a37e5883dc5962ec401c',
|
||||
'FloatingIPDNS': '1.0-ee3db848500fa1825235f701828c06d5',
|
||||
'GeneveAllocation': '1.0-d5f76e8eac60a778914d61dd8e23e90f',
|
||||
'GeneveEndpoint': '1.0-040f026996b5952e2ae4ccd40ac61ca6',
|
||||
|
@ -12,9 +12,12 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from unittest import mock
|
||||
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from neutron.objects.qos import binding as qos_binding
|
||||
from neutron.objects.qos import policy
|
||||
from neutron.objects import router
|
||||
from neutron.tests.unit.objects import test_base as obj_test_base
|
||||
from neutron.tests.unit import testlib_api
|
||||
@ -201,11 +204,36 @@ class FloatingIPDbObjectTestCase(obj_test_base.BaseDbObjectTestCase,
|
||||
self.context, fip_id=fip_id)
|
||||
self.assertEqual([], qos_fip_binding)
|
||||
|
||||
@mock.patch.object(policy.QosPolicy, 'unset_default')
|
||||
def test_qos_network_policy_id(self, *mocks):
|
||||
policy_obj = policy.QosPolicy(self.context)
|
||||
policy_obj.create()
|
||||
|
||||
obj = self._make_object(self.obj_fields[0])
|
||||
obj.create()
|
||||
obj = router.FloatingIP.get_object(self.context, id=obj.id)
|
||||
self.assertIsNone(obj.qos_network_policy_id)
|
||||
self.assertIsNone(obj.qos_policy_id)
|
||||
|
||||
network = self._create_test_network(qos_policy_id=policy_obj.id)
|
||||
self.update_obj_fields({'floating_network_id': network.id})
|
||||
obj = self._make_object(self.obj_fields[1])
|
||||
obj.create()
|
||||
obj = router.FloatingIP.get_object(self.context, id=obj.id)
|
||||
self.assertEqual(policy_obj.id, obj.qos_network_policy_id)
|
||||
self.assertIsNone(obj.qos_policy_id)
|
||||
|
||||
def test_v1_1_to_v1_0_drops_qos_policy_id(self):
|
||||
obj = self._make_object(self.obj_fields[0])
|
||||
obj_v1_0 = obj.obj_to_primitive(target_version='1.0')
|
||||
self.assertNotIn('qos_policy_id', obj_v1_0['versioned_object.data'])
|
||||
|
||||
def test_v1_2_to_v1_1_drops_qos_network_policy_id(self):
|
||||
obj = self._make_object(self.obj_fields[0])
|
||||
obj_v1_1 = obj.obj_to_primitive(target_version='1.1')
|
||||
self.assertNotIn('qos_network_policy_id',
|
||||
obj_v1_1['versioned_object.data'])
|
||||
|
||||
|
||||
class DvrFipGatewayPortAgentBindingTestCase(
|
||||
obj_test_base.BaseObjectIfaceTestCase):
|
||||
|
Loading…
Reference in New Issue
Block a user