From 0390ada97c01031e675caf43b5028bb311331865 Mon Sep 17 00:00:00 2001 From: Bence Romsics Date: Wed, 28 Dec 2022 15:58:17 +0100 Subject: [PATCH] port-hints: api extension api extension db model db migration ovo (including changes affecting push rpc) extension driver policies To enable this: * neutron-db-manage upgrade 6f1145bff34c * ml2_conf.ini: [ml2] extension_drivers += port_hints This patch also bumps neutron-lib requirement to 3.5.0. Change-Id: I80816618285d742775bc0534510c0f874f84ed2e Partial-Bug: #1990842 Related-Change (spec): https://review.opendev.org/c/openstack/neutron-specs/+/862133 Related-Change (n-lib api-def): https://review.opendev.org/c/openstack/neutron-lib/+/870080 --- neutron/conf/policies/port.py | 23 +++++ .../2023.2/expand/6f1145bff34c_port_hints.py | 45 ++++++++++ .../alembic_migrations/versions/EXPAND_HEAD | 2 +- neutron/db/models/port_hints.py | 35 ++++++++ neutron/db/port_hints_db.py | 53 ++++++++++++ neutron/extensions/port_hints.py | 20 +++++ neutron/objects/port/extensions/port_hints.py | 53 ++++++++++++ neutron/objects/ports.py | 9 +- neutron/plugins/ml2/extensions/port_hints.py | 45 ++++++++++ neutron/tests/unit/conf/policies/test_port.py | 60 +++++++++++++ .../tests/unit/db/test_db_base_plugin_v2.py | 2 +- .../tests/unit/extensions/test_port_hints.py | 85 +++++++++++++++++++ .../port/extensions/test_port_hints.py | 33 +++++++ neutron/tests/unit/objects/test_objects.py | 3 +- neutron/tests/unit/objects/test_ports.py | 6 ++ requirements.txt | 2 +- setup.cfg | 1 + 17 files changed, 472 insertions(+), 5 deletions(-) create mode 100644 neutron/db/migration/alembic_migrations/versions/2023.2/expand/6f1145bff34c_port_hints.py create mode 100644 neutron/db/models/port_hints.py create mode 100644 neutron/db/port_hints_db.py create mode 100644 neutron/extensions/port_hints.py create mode 100644 neutron/objects/port/extensions/port_hints.py create mode 100644 neutron/plugins/ml2/extensions/port_hints.py create mode 100644 neutron/tests/unit/extensions/test_port_hints.py create mode 100644 neutron/tests/unit/objects/port/extensions/test_port_hints.py diff --git a/neutron/conf/policies/port.py b/neutron/conf/policies/port.py index 5783f080bbe..bce04da941c 100644 --- a/neutron/conf/policies/port.py +++ b/neutron/conf/policies/port.py @@ -270,6 +270,15 @@ rules = [ deprecated_reason=DEPRECATED_REASON, deprecated_since=versionutils.deprecated.WALLABY) ), + policy.DocumentedRuleDefault( + name='create_port:hints', + check_str=base.ADMIN, + scope_types=['project'], + description=( + 'Specify ``hints`` attribute when creating a port' + ), + operations=ACTION_POST, + ), policy.DocumentedRuleDefault( name='get_port', @@ -350,6 +359,13 @@ rules = [ deprecated_reason=DEPRECATED_REASON, deprecated_since=versionutils.deprecated.WALLABY) ), + policy.DocumentedRuleDefault( + name='get_port:hints', + check_str=base.ADMIN, + scope_types=['project'], + description='Get ``hints`` attribute of a port', + operations=ACTION_GET, + ), # TODO(amotoki): Add get_port:binding:vnic_type # TODO(amotoki): Add get_port:binding:data_plane_status @@ -592,6 +608,13 @@ rules = [ deprecated_reason=DEPRECATED_REASON, deprecated_since=versionutils.deprecated.WALLABY) ), + policy.DocumentedRuleDefault( + name='update_port:hints', + check_str=base.ADMIN, + scope_types=['project'], + description='Update ``hints`` attribute of a port', + operations=ACTION_PUT, + ), policy.DocumentedRuleDefault( name='delete_port', diff --git a/neutron/db/migration/alembic_migrations/versions/2023.2/expand/6f1145bff34c_port_hints.py b/neutron/db/migration/alembic_migrations/versions/2023.2/expand/6f1145bff34c_port_hints.py new file mode 100644 index 00000000000..b82d3de9566 --- /dev/null +++ b/neutron/db/migration/alembic_migrations/versions/2023.2/expand/6f1145bff34c_port_hints.py @@ -0,0 +1,45 @@ +# Copyright 2023 OpenStack Foundation +# +# 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.db import constants as db_const +import sqlalchemy as sa + + +"""port_hints + +Revision ID: 6f1145bff34c +Revises: 93f394357a27 +Create Date: 2023-01-01 00:00:00.000000 + +""" + +# revision identifiers, used by Alembic. +revision = '6f1145bff34c' +down_revision = '93f394357a27' + + +def upgrade(): + op.create_table( + 'porthints', + sa.Column( + 'port_id', + sa.String(length=db_const.UUID_FIELD_SIZE), + sa.ForeignKey('ports.id', ondelete='CASCADE'), + primary_key=True), + sa.Column('hints', + sa.String(4095), + nullable=False), + ) diff --git a/neutron/db/migration/alembic_migrations/versions/EXPAND_HEAD b/neutron/db/migration/alembic_migrations/versions/EXPAND_HEAD index 88323e719ea..8e31a8bd562 100644 --- a/neutron/db/migration/alembic_migrations/versions/EXPAND_HEAD +++ b/neutron/db/migration/alembic_migrations/versions/EXPAND_HEAD @@ -1 +1 @@ -93f394357a27 +6f1145bff34c diff --git a/neutron/db/models/port_hints.py b/neutron/db/models/port_hints.py new file mode 100644 index 00000000000..8ef171bba5a --- /dev/null +++ b/neutron/db/models/port_hints.py @@ -0,0 +1,35 @@ +# Copyright 2023 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.db import constants as db_const +from neutron_lib.db import model_base +import sqlalchemy as sa + +from neutron.db import models_v2 + + +class PortHints(model_base.BASEV2): + __tablename__ = 'porthints' + port_id = sa.Column( + sa.String(db_const.UUID_FIELD_SIZE), + sa.ForeignKey('ports.id', ondelete='CASCADE'), + primary_key=True) + hints = sa.Column('hints', sa.String(length=4095), nullable=False) + port = sa.orm.relationship( + models_v2.Port, + load_on_pending=True, + backref=sa.orm.backref( + 'hints', uselist=False, cascade='delete', lazy='subquery')) + + revises_on_change = ('port', ) diff --git a/neutron/db/port_hints_db.py b/neutron/db/port_hints_db.py new file mode 100644 index 00000000000..0b45b413fbd --- /dev/null +++ b/neutron/db/port_hints_db.py @@ -0,0 +1,53 @@ +# Copyright 2023 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 port_hints as phints_def +from oslo_serialization import jsonutils + +from neutron.objects.port.extensions import port_hints as phints_obj + + +class PortHintsMixin(object): + """Mixin class to add hints to a port""" + + def _process_create_port(self, context, data, result): + if not data.get(phints_def.HINTS): + result[phints_def.HINTS] = None + return + + obj = phints_obj.PortHints( + context, port_id=result['id'], + hints=data[phints_def.HINTS]) + obj.create() + result[phints_def.HINTS] = data[phints_def.HINTS] + + def _process_update_port(self, context, data, result): + obj = phints_obj.PortHints.get_object( + context, port_id=result['id']) + + if obj: + if data[phints_def.HINTS]: + obj.hints = data[phints_def.HINTS] + obj.update() + else: + obj.delete() + result[phints_def.HINTS] = data[phints_def.HINTS] + else: + self._process_create_port(context, data, result) + + def _extend_port_dict(self, port_db, result): + if port_db.hints: + result[phints_def.HINTS] = jsonutils.loads(port_db.hints.hints) + else: + result[phints_def.HINTS] = None diff --git a/neutron/extensions/port_hints.py b/neutron/extensions/port_hints.py new file mode 100644 index 00000000000..74e9e6007c8 --- /dev/null +++ b/neutron/extensions/port_hints.py @@ -0,0 +1,20 @@ +# Copyright 2023 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 port_hints as phints_def +from neutron_lib.api import extensions as api_extensions + + +class Port_hints(api_extensions.APIExtensionDescriptor): + api_definition = phints_def diff --git a/neutron/objects/port/extensions/port_hints.py b/neutron/objects/port/extensions/port_hints.py new file mode 100644 index 00000000000..a9fd1c793f0 --- /dev/null +++ b/neutron/objects/port/extensions/port_hints.py @@ -0,0 +1,53 @@ +# Copyright 2023 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.objects import common_types + +from neutron.db.models import port_hints +from neutron.objects import base + + +@base.NeutronObjectRegistry.register +class PortHints(base.NeutronDbObject): + # Version 1.0: Initial version + VERSION = '1.0' + + db_model = port_hints.PortHints + + primary_keys = ['port_id'] + + fields = { + 'port_id': common_types.UUIDField(), + 'hints': common_types.DictOfMiscValuesField(), + } + + foreign_keys = {'Port': {'port_id': 'id'}} + + @classmethod + def modify_fields_to_db(cls, fields): + result = super(PortHints, cls).modify_fields_to_db(fields) + if 'hints' in result: + # dump field into string, set '' if empty '{}' or None + result['hints'] = ( + cls.filter_to_json_str(result['hints'], default='')) + return result + + @classmethod + def modify_fields_from_db(cls, db_obj): + fields = super(PortHints, cls).modify_fields_from_db(db_obj) + if 'hints' in fields: + # load string from DB into dict, set None if hints is '' + fields['hints'] = ( + cls.load_json_from_str(fields['hints'])) + return fields diff --git a/neutron/objects/ports.py b/neutron/objects/ports.py index 462d86944c2..e9fd61b38e3 100644 --- a/neutron/objects/ports.py +++ b/neutron/objects/ports.py @@ -336,7 +336,8 @@ class Port(base.NeutronDbObject): # Version 1.5: Added qos_network_policy_id field # Version 1.6: Added numa_affinity_policy field # Version 1.7: Added port_device field - VERSION = '1.7' + # Version 1.8: Added hints field + VERSION = '1.8' db_model = models_v2.Port @@ -370,6 +371,9 @@ class Port(base.NeutronDbObject): 'fixed_ips': obj_fields.ListOfObjectsField( 'IPAllocation', nullable=True ), + 'hints': obj_fields.ObjectField( + 'PortHints', nullable=True + ), # TODO(ihrachys): consider converting to boolean 'security': obj_fields.ObjectField( 'PortSecurity', nullable=True @@ -407,6 +411,7 @@ class Port(base.NeutronDbObject): 'distributed_bindings', 'dns', 'fixed_ips', + 'hints', 'numa_affinity_policy', 'qos_policy_id', 'qos_network_policy_id', @@ -610,6 +615,8 @@ class Port(base.NeutronDbObject): primitive.pop('numa_affinity_policy', None) if _target_version < (1, 7): primitive.pop('device_profile', None) + if _target_version < (1, 8): + primitive.pop('hints', None) @classmethod @db_api.CONTEXT_READER diff --git a/neutron/plugins/ml2/extensions/port_hints.py b/neutron/plugins/ml2/extensions/port_hints.py new file mode 100644 index 00000000000..1e4ba654f4e --- /dev/null +++ b/neutron/plugins/ml2/extensions/port_hints.py @@ -0,0 +1,45 @@ +# Copyright 2023 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 port_hints as phints_def +from neutron_lib.plugins.ml2 import api +from oslo_log import log as logging + +from neutron.db import port_hints_db + + +LOG = logging.getLogger(__name__) + + +class PortHintsExtensionDriver( + api.ExtensionDriver, port_hints_db.PortHintsMixin): + + _supported_extension_alias = phints_def.ALIAS + + def initialize(self): + LOG.info('PortHintsExtensionDriver initialization complete') + + @property + def extension_alias(self): + return self._supported_extension_alias + + def process_create_port(self, context, data, result): + self._process_create_port(context, data, result) + + def process_update_port(self, context, data, result): + if phints_def.HINTS in data: + self._process_update_port(context, data, result) + + def extend_port_dict(self, session, port_db, result): + self._extend_port_dict(port_db, result) diff --git a/neutron/tests/unit/conf/policies/test_port.py b/neutron/tests/unit/conf/policies/test_port.py index c50d3feb107..8248960abbf 100644 --- a/neutron/tests/unit/conf/policies/test_port.py +++ b/neutron/tests/unit/conf/policies/test_port.py @@ -532,6 +532,16 @@ class AdminTests(PortAPITestCase): 'create_port:allowed_address_pairs:ip_address', self.alt_target)) + def test_create_port_with_hints(self): + self.assertTrue( + policy.enforce(self.context, + 'create_port:hints', + self.target)) + self.assertTrue( + policy.enforce(self.context, + 'create_port:hints', + self.alt_target)) + def test_get_port(self): self.assertTrue( policy.enforce(self.context, 'get_port', self.target)) @@ -578,6 +588,14 @@ class AdminTests(PortAPITestCase): policy.enforce( self.context, 'get_port:resource_request', self.alt_target)) + def test_get_port_hints(self): + self.assertTrue( + policy.enforce( + self.context, 'get_port:hints', self.target)) + self.assertTrue( + policy.enforce( + self.context, 'get_port:hints', self.alt_target)) + def test_update_port(self): self.assertTrue( policy.enforce(self.context, 'update_port', self.target)) @@ -701,6 +719,16 @@ class AdminTests(PortAPITestCase): 'update_port:data_plane_status', self.alt_target)) + def test_update_port_hints(self): + self.assertTrue( + policy.enforce(self.context, + 'update_port:hints', + self.target)) + self.assertTrue( + policy.enforce(self.context, + 'update_port:hints', + self.alt_target)) + def test_delete_port(self): self.assertTrue( policy.enforce(self.context, 'delete_port', self.target)) @@ -850,6 +878,18 @@ class ProjectMemberTests(AdminTests): self.context, 'create_port:allowed_address_pairs:ip_address', self.alt_target) + def test_create_port_with_hints(self): + self.assertRaises( + base_policy.PolicyNotAuthorized, + policy.enforce, + self.context, 'create_port:hints', + self.target) + self.assertRaises( + base_policy.PolicyNotAuthorized, + policy.enforce, + self.context, 'create_port:hints', + self.alt_target) + def test_get_port(self): self.assertTrue( policy.enforce(self.context, 'get_port', self.target)) @@ -907,6 +947,16 @@ class ProjectMemberTests(AdminTests): policy.enforce, self.context, 'get_port:resource_request', self.alt_target) + def test_get_port_hints(self): + self.assertRaises( + base_policy.PolicyNotAuthorized, + policy.enforce, self.context, 'get_port:hints', + self.target) + self.assertRaises( + base_policy.PolicyNotAuthorized, + policy.enforce, self.context, 'get_port:hints', + self.alt_target) + def test_update_port(self): self.assertTrue( policy.enforce(self.context, 'update_port', self.target)) @@ -1053,6 +1103,16 @@ class ProjectMemberTests(AdminTests): policy.enforce, self.context, 'update_port:data_plane_status', self.alt_target) + def test_update_port_hints(self): + self.assertRaises( + base_policy.PolicyNotAuthorized, + policy.enforce, + self.context, 'update_port:hints', self.target) + self.assertRaises( + base_policy.PolicyNotAuthorized, + policy.enforce, + self.context, 'update_port:hints', self.alt_target) + def test_delete_port(self): self.assertTrue( policy.enforce(self.context, 'delete_port', self.target)) diff --git a/neutron/tests/unit/db/test_db_base_plugin_v2.py b/neutron/tests/unit/db/test_db_base_plugin_v2.py index c4a1dce9aef..eb80348fbb3 100644 --- a/neutron/tests/unit/db/test_db_base_plugin_v2.py +++ b/neutron/tests/unit/db/test_db_base_plugin_v2.py @@ -517,7 +517,7 @@ class NeutronDbPluginV2TestCase(testlib_api.WebTestCase): 'mac_address', 'name', 'fixed_ips', 'tenant_id', 'device_owner', 'security_groups', 'propagate_uplink_status', 'numa_affinity_policy', - 'device_profile') + (arg_list or ())): + 'device_profile', 'hints') + (arg_list or ())): # Arg must be present if arg in kwargs: data['port'][arg] = kwargs[arg] diff --git a/neutron/tests/unit/extensions/test_port_hints.py b/neutron/tests/unit/extensions/test_port_hints.py new file mode 100644 index 00000000000..9aa9fb1462c --- /dev/null +++ b/neutron/tests/unit/extensions/test_port_hints.py @@ -0,0 +1,85 @@ +# Copyright 2023 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. + +import ddt +from neutron_lib.api.definitions import port_hints as phints_def +from neutron_lib.db import api as db_api + +from neutron.db import db_base_plugin_v2 +from neutron.db import port_hints_db as phints_db +from neutron.tests.unit.db import test_db_base_plugin_v2 + +HINTS_LIST = [ + None, + {'openvswitch': {'other_config': {'tx-steering': 'hash'}}}, +] + + +class PortHintsExtensionTestPlugin( + db_base_plugin_v2.NeutronDbPluginV2, + phints_db.PortHintsMixin): + """Test plugin to mixin the port hints extension.""" + + supported_extension_aliases = [phints_def.ALIAS] + + def create_port(self, context, port): + with db_api.CONTEXT_WRITER.using(context): + new_port = super(PortHintsExtensionTestPlugin, + self).create_port(context, port) + self._process_create_port(context, port['port'], new_port) + return new_port + + def update_port(self, context, id, port): + with db_api.CONTEXT_WRITER.using(context): + updated_port = super( + PortHintsExtensionTestPlugin, + self).update_port(context, id, port) + self._process_update_port(context, port['port'], updated_port) + return updated_port + + +@ddt.ddt +class PortHintsExtensionTestCase( + test_db_base_plugin_v2.NeutronDbPluginV2TestCase): + """Test API extension port-hints attributes.""" + + def setUp(self, *args): + plugin = ('neutron.tests.unit.extensions.test_port_hints.' + 'PortHintsExtensionTestPlugin') + super(PortHintsExtensionTestCase, self).setUp(plugin=plugin) + + def _create_and_check_port_hints(self, hints): + keys = [('name', 'name_1'), + ('admin_state_up', True), + ('status', self.port_create_status), + ('hints', hints)] + with self.port(is_admin=True, name='name_1', hints=hints) as port: + for k, v in keys: + self.assertEqual(v, port['port'][k]) + return port + + def _update_and_check_port_hints(self, port, hints): + data = {'port': {'hints': hints}} + req = self.new_update_request( + 'ports', data, port['port']['id'], as_admin=True) + res = self.deserialize(self.fmt, req.get_response(self.api)) + self.assertEqual( + hints, res['port']['hints']) + + @ddt.data(*HINTS_LIST) + def test_create_and_update_port_hints( + self, hints): + port = self._create_and_check_port_hints(hints) + for new_hints in HINTS_LIST: + self._update_and_check_port_hints(port, new_hints) diff --git a/neutron/tests/unit/objects/port/extensions/test_port_hints.py b/neutron/tests/unit/objects/port/extensions/test_port_hints.py new file mode 100644 index 00000000000..2efd985388c --- /dev/null +++ b/neutron/tests/unit/objects/port/extensions/test_port_hints.py @@ -0,0 +1,33 @@ +# Copyright 2023 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.objects.port.extensions import port_hints +from neutron.tests.unit.objects import test_base as obj_test_base +from neutron.tests.unit import testlib_api + + +class PortHintsIfaceObjectTestCase(obj_test_base.BaseObjectIfaceTestCase): + + _test_class = port_hints.PortHints + + +class PortHintsDbObjectTestCase( + obj_test_base.BaseDbObjectTestCase, testlib_api.SqlTestCase): + + _test_class = port_hints.PortHints + + def setUp(self): + super(PortHintsDbObjectTestCase, self).setUp() + self.update_obj_fields( + {'port_id': lambda: self._create_test_port_id()}) diff --git a/neutron/tests/unit/objects/test_objects.py b/neutron/tests/unit/objects/test_objects.py index d6a431e1085..d198bae2b74 100644 --- a/neutron/tests/unit/objects/test_objects.py +++ b/neutron/tests/unit/objects/test_objects.py @@ -73,8 +73,9 @@ object_data = { 'NetworkSegment': '1.0-57b7f2960971e3b95ded20cbc59244a8', 'NetworkSegmentRange': '1.0-bdec1fffc9058ea676089b1f2f2b3cf3', 'NetworkSubnetLock': '1.0-140de39d4b86ae346dc3d70b885bea53', - 'Port': '1.7-d8c1cfe42cfa3719a5d810eeab79e006', + 'Port': '1.8-1aa850ab5529128de07e82c6fb75fcb5', 'PortDeviceProfile': '1.0-b98c7083cc3e93d176fd7a91ae13af32', + 'PortHints': '1.0-9ebf6e12fa427809476a92c7432352b8', 'PortNumaAffinityPolicy': '1.0-38fcea43e7bfb2536461f3d053c43aa3', 'PortBinding': '1.0-3306deeaa6deb01e33af06777d48d578', 'PortBindingLevel': '1.1-50d47f63218f87581b6cd9a62db574e5', diff --git a/neutron/tests/unit/objects/test_ports.py b/neutron/tests/unit/objects/test_ports.py index b01fb998ed0..f38077d8d01 100644 --- a/neutron/tests/unit/objects/test_ports.py +++ b/neutron/tests/unit/objects/test_ports.py @@ -529,6 +529,12 @@ class PortDbObjectTestCase(obj_test_base.BaseDbObjectTestCase, self.assertNotIn('device_profile', port_v1_6['versioned_object.data']) + def test_v1_8_to_v1_7_drops_hints(self): + port_new = self._create_test_port() + port_v1_7 = port_new.obj_to_primitive(target_version='1.7') + self.assertNotIn('hints', + port_v1_7['versioned_object.data']) + def test_get_ports_ids_by_security_groups_except_router(self): sg_id = self._create_test_security_group_id() filter_owner = constants.ROUTER_INTERFACE_OWNERS_SNAT diff --git a/requirements.txt b/requirements.txt index 2b2d62fbb9c..73796c43eb1 100644 --- a/requirements.txt +++ b/requirements.txt @@ -20,7 +20,7 @@ Jinja2>=2.10 # BSD License (3 clause) keystonemiddleware>=5.1.0 # Apache-2.0 netaddr>=0.7.18 # BSD netifaces>=0.10.4 # MIT -neutron-lib>=3.4.0 # Apache-2.0 +neutron-lib>=3.5.0 # Apache-2.0 python-neutronclient>=7.8.0 # Apache-2.0 tenacity>=6.0.0 # Apache-2.0 SQLAlchemy>=1.4.23 # MIT diff --git a/setup.cfg b/setup.cfg index da9e0c09498..66edcd4575e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -125,6 +125,7 @@ neutron.ml2.extension_drivers = tag_ports_during_bulk_creation = neutron.plugins.ml2.extensions.tag_ports_during_bulk_creation:TagPortsDuringBulkCreationExtensionDriver subnet_dns_publish_fixed_ip = neutron.plugins.ml2.extensions.subnet_dns_publish_fixed_ip:SubnetDNSPublishFixedIPExtensionDriver dns_domain_keywords = neutron.plugins.ml2.extensions.dns_domain_keywords:DnsDomainKeywordsExtensionDriver + port_hints = neutron.plugins.ml2.extensions.port_hints:PortHintsExtensionDriver neutron.ipam_drivers = fake = neutron.tests.unit.ipam.fake_driver:FakeDriver internal = neutron.ipam.drivers.neutrondb_ipam.driver:NeutronDbPool