diff --git a/neutron/common/ovn/extensions.py b/neutron/common/ovn/extensions.py index f68878c1540..0cd9e753e53 100644 --- a/neutron/common/ovn/extensions.py +++ b/neutron/common/ovn/extensions.py @@ -32,6 +32,7 @@ from neutron_lib.api.definitions import network_availability_zone from neutron_lib.api.definitions import network_ip_availability from neutron_lib.api.definitions import network_mtu from neutron_lib.api.definitions import pagination +from neutron_lib.api.definitions import port_numa_affinity_policy from neutron_lib.api.definitions import port_resource_request from neutron_lib.api.definitions import port_security from neutron_lib.api.definitions import portbindings @@ -82,6 +83,7 @@ ML2_SUPPORTED_API_EXTENSIONS = [ network_mtu.ALIAS, network_availability_zone.ALIAS, network_ip_availability.ALIAS, + port_numa_affinity_policy.ALIAS, port_security.ALIAS, provider_net.ALIAS, port_resource_request.ALIAS, diff --git a/neutron/db/migration/alembic_migrations/versions/EXPAND_HEAD b/neutron/db/migration/alembic_migrations/versions/EXPAND_HEAD index e0c729daf42..c23b25bebb7 100644 --- a/neutron/db/migration/alembic_migrations/versions/EXPAND_HEAD +++ b/neutron/db/migration/alembic_migrations/versions/EXPAND_HEAD @@ -1 +1 @@ -I38991de2b4 +532aa95457e2 diff --git a/neutron/db/migration/alembic_migrations/versions/wallaby/expand/532aa95457e2_port_numa_affinity_policy.py b/neutron/db/migration/alembic_migrations/versions/wallaby/expand/532aa95457e2_port_numa_affinity_policy.py new file mode 100644 index 00000000000..6f73b61147d --- /dev/null +++ b/neutron/db/migration/alembic_migrations/versions/wallaby/expand/532aa95457e2_port_numa_affinity_policy.py @@ -0,0 +1,44 @@ +# Copyright 2020 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 import constants as n_const +from neutron_lib.db import constants as db_const +import sqlalchemy as sa + + +"""port_numa_affinity_policy + +Revision ID: 532aa95457e2 +Revises: I38991de2b4 +Create Date: 2020-07-10 14:59:18.868245 + +""" + +# revision identifiers, used by Alembic. +revision = '532aa95457e2' +down_revision = 'I38991de2b4' + + +def upgrade(): + op.create_table('portnumaaffinitypolicies', + sa.Column('port_id', + sa.String(length=db_const.UUID_FIELD_SIZE), + sa.ForeignKey('ports.id', ondelete='CASCADE'), + primary_key=True), + sa.Column('numa_affinity_policy', + sa.Enum(*n_const.PORT_NUMA_POLICIES, + name='numa_affinity_policy')) + ) diff --git a/neutron/db/models/port_numa_affinity_policy.py b/neutron/db/models/port_numa_affinity_policy.py new file mode 100644 index 00000000000..e695d79713c --- /dev/null +++ b/neutron/db/models/port_numa_affinity_policy.py @@ -0,0 +1,36 @@ +# Copyright 2020 Red Hat, Inc. +# All Rights Reserved. +# +# 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 import constants as n_const +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 PortNumaAffinityPolicy(model_base.BASEV2): + __tablename__ = 'portnumaaffinitypolicies' + port_id = sa.Column(sa.String(db_const.UUID_FIELD_SIZE), + sa.ForeignKey('ports.id', ondelete='CASCADE'), + primary_key=True) + numa_affinity_policy = sa.Column(sa.Enum(*n_const.PORT_NUMA_POLICIES, + name='numa_affinity_policy')) + port = sa.orm.relationship( + models_v2.Port, load_on_pending=True, + backref=sa.orm.backref('numa_affinity_policy', uselist=False, + cascade='delete', lazy='joined')) + + revises_on_change = ('port', ) diff --git a/neutron/db/port_numa_affinity_policy_db.py b/neutron/db/port_numa_affinity_policy_db.py new file mode 100644 index 00000000000..4a457852a2b --- /dev/null +++ b/neutron/db/port_numa_affinity_policy_db.py @@ -0,0 +1,67 @@ +# Copyright (c) 2020 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 port_numa_affinity_policy as pnap +from neutron_lib.api.definitions import portbindings +from neutron_lib import exceptions as n_exc + +from neutron.objects.port.extensions import port_numa_affinity_policy as \ + pnap_obj + + +class PortNumaAffinityPolicyDbMixin(object): + """Mixin class to add NUMA affinity policy to a port""" + + def _process_create_port(self, context, data, result): + if not data.get(pnap.NUMA_AFFINITY_POLICY): + result[pnap.NUMA_AFFINITY_POLICY] = None + return + + obj = pnap_obj.PortNumaAffinityPolicy( + context, port_id=result['id'], + numa_affinity_policy=data[pnap.NUMA_AFFINITY_POLICY]) + obj.create() + result[pnap.NUMA_AFFINITY_POLICY] = data[pnap.NUMA_AFFINITY_POLICY] + + def _process_update_port(self, context, data, result): + if pnap.NUMA_AFFINITY_POLICY not in data: + return + + if (result[portbindings.VIF_TYPE] not in + portbindings.VIF_UNPLUGGED_TYPES): + raise n_exc.PortBoundNUMAAffinityPolicy( + port_id=result['id'], host_id=result[portbindings.HOST_ID], + numa_affinity_policy=data[pnap.NUMA_AFFINITY_POLICY]) + + obj = pnap_obj.PortNumaAffinityPolicy.get_object(context, + port_id=result['id']) + + if data[pnap.NUMA_AFFINITY_POLICY]: + if not obj: + return self._process_create_port(context, data, result) + obj.update_fields( + {pnap.NUMA_AFFINITY_POLICY: data[pnap.NUMA_AFFINITY_POLICY]}) + obj.update() + else: + if obj: + obj.delete() + + result[pnap.NUMA_AFFINITY_POLICY] = data[pnap.NUMA_AFFINITY_POLICY] + + def _extend_port_dict(self, port_db, result): + if port_db.numa_affinity_policy: + result[pnap.NUMA_AFFINITY_POLICY] = ( + port_db.numa_affinity_policy.numa_affinity_policy) + else: + result[pnap.NUMA_AFFINITY_POLICY] = None diff --git a/neutron/extensions/port_numa_affinity_policy.py b/neutron/extensions/port_numa_affinity_policy.py new file mode 100644 index 00000000000..23ddd31c6c5 --- /dev/null +++ b/neutron/extensions/port_numa_affinity_policy.py @@ -0,0 +1,20 @@ +# Copyright (c) 2020 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 port_numa_affinity_policy +from neutron_lib.api import extensions as api_extensions + + +class Port_numa_affinity_policy(api_extensions.APIExtensionDescriptor): + api_definition = port_numa_affinity_policy diff --git a/neutron/objects/port/extensions/port_numa_affinity_policy.py b/neutron/objects/port/extensions/port_numa_affinity_policy.py new file mode 100644 index 00000000000..8e40e4b3557 --- /dev/null +++ b/neutron/objects/port/extensions/port_numa_affinity_policy.py @@ -0,0 +1,44 @@ +# Copyright (c) 2020 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 import constants as lib_constants +from neutron_lib.objects import common_types +from oslo_versionedobjects import fields as obj_fields + +from neutron.db.models import port_numa_affinity_policy +from neutron.objects import base + + +# TODO(ralonsoh): move to neutron_lib.objects.common_types +class NumaAffinityPoliciesEnumField(obj_fields.AutoTypedField): + AUTO_TYPE = obj_fields.Enum(valid_values=lib_constants.PORT_NUMA_POLICIES) + + +@base.NeutronObjectRegistry.register +class PortNumaAffinityPolicy(base.NeutronDbObject): + # Version 1.0: Initial version + VERSION = '1.0' + + db_model = port_numa_affinity_policy.PortNumaAffinityPolicy + + primary_keys = ['port_id'] + + new_facade = True + + fields = { + 'port_id': common_types.UUIDField(), + 'numa_affinity_policy': NumaAffinityPoliciesEnumField(), + } + + foreign_keys = {'Port': {'port_id': 'id'}} diff --git a/neutron/objects/ports.py b/neutron/objects/ports.py index 7cba7deef3c..0cd7e39638d 100644 --- a/neutron/objects/ports.py +++ b/neutron/objects/ports.py @@ -273,7 +273,8 @@ class Port(base.NeutronDbObject): # Version 1.3: distributed_binding -> distributed_bindings # Version 1.4: Attribute binding becomes ListOfObjectsField # Version 1.5: Added qos_network_policy_id field - VERSION = '1.5' + # Version 1.6: Added numa_affinity_policy field + VERSION = '1.6' db_model = models_v2.Port @@ -323,6 +324,7 @@ class Port(base.NeutronDbObject): 'binding_levels': obj_fields.ListOfObjectsField( 'PortBindingLevel', nullable=True ), + 'numa_affinity_policy': obj_fields.StringField(nullable=True), # TODO(ihrachys): consider adding a 'dns_assignment' fully synthetic # field in later object iterations @@ -341,6 +343,7 @@ class Port(base.NeutronDbObject): 'distributed_bindings', 'dns', 'fixed_ips', + 'numa_affinity_policy', 'qos_policy_id', 'qos_network_policy_id', 'security', @@ -501,6 +504,11 @@ class Port(base.NeutronDbObject): db_obj.qos_network_policy_binding.policy_id) fields_to_change.append('qos_network_policy_binding') + if db_obj.get('numa_affinity_policy'): + self.numa_affinity_policy = ( + db_obj.numa_affinity_policy.numa_affinity_policy) + fields_to_change.append('numa_affinity_policy') + self.obj_reset_changes(fields_to_change) def obj_make_compatible(self, primitive, target_version): @@ -529,6 +537,8 @@ class Port(base.NeutronDbObject): break if _target_version < (1, 5): primitive.pop('qos_network_policy_id', None) + if _target_version < (1, 6): + primitive.pop('numa_affinity_policy', None) @classmethod def get_ports_by_router_and_network(cls, context, router_id, owner, diff --git a/neutron/plugins/ml2/extensions/port_numa_affinity_policy.py b/neutron/plugins/ml2/extensions/port_numa_affinity_policy.py new file mode 100644 index 00000000000..ee160880ef9 --- /dev/null +++ b/neutron/plugins/ml2/extensions/port_numa_affinity_policy.py @@ -0,0 +1,47 @@ +# Copyright 2020 Red Hat, Inc. +# All Rights Reserved. +# +# 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_numa_affinity_policy as pnap +from neutron_lib.plugins.ml2 import api +from oslo_log import log as logging + +from neutron.db import port_numa_affinity_policy_db + + +LOG = logging.getLogger(__name__) + + +class PortNumaAffinityPolicyExtensionDriver( + api.ExtensionDriver, + port_numa_affinity_policy_db.PortNumaAffinityPolicyDbMixin): + + _supported_extension_alias = pnap.ALIAS + + def initialize(self): + LOG.info('PortNumaAffinityPolicyExtensionDriver 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): + 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/plugins/ml2/plugin.py b/neutron/plugins/ml2/plugin.py index ab642c501d1..09a29b31824 100644 --- a/neutron/plugins/ml2/plugin.py +++ b/neutron/plugins/ml2/plugin.py @@ -40,6 +40,7 @@ from neutron_lib.api.definitions import network_mtu as mtu_apidef from neutron_lib.api.definitions import network_mtu_writable as mtuw_apidef from neutron_lib.api.definitions import port as port_def from neutron_lib.api.definitions import port_mac_address_regenerate +from neutron_lib.api.definitions import port_numa_affinity_policy as pnap_def from neutron_lib.api.definitions import port_security as psec from neutron_lib.api.definitions import portbindings from neutron_lib.api.definitions import portbindings_extended as pbe_ext @@ -213,7 +214,9 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, subnet_onboard_def.ALIAS, subnetpool_prefix_ops_def.ALIAS, stateful_security_group.ALIAS, - addrgrp_def.ALIAS] + addrgrp_def.ALIAS, + pnap_def.ALIAS, + ] # List of agent types for which all binding_failed ports should try to be # rebound when agent revive @@ -378,12 +381,11 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, ] def _check_mac_update_allowed(self, orig_port, port, binding): - unplugged_types = (portbindings.VIF_TYPE_BINDING_FAILED, - portbindings.VIF_TYPE_UNBOUND) new_mac = port.get('mac_address') mac_change = (new_mac is not None and orig_port['mac_address'] != new_mac) - if (mac_change and binding.vif_type not in unplugged_types): + if (mac_change and binding.vif_type not in + portbindings.VIF_UNPLUGGED_TYPES): raise exc.PortBound(port_id=orig_port['id'], vif_type=binding.vif_type, old_mac=orig_port['mac_address'], diff --git a/neutron/tests/contrib/hooks/api_all_extensions b/neutron/tests/contrib/hooks/api_all_extensions index a80c49bf900..01646bb1538 100644 --- a/neutron/tests/contrib/hooks/api_all_extensions +++ b/neutron/tests/contrib/hooks/api_all_extensions @@ -53,6 +53,7 @@ NETWORK_API_EXTENSIONS+=",router-admin-state-down-before-update" NETWORK_API_EXTENSIONS+=",router_availability_zone" NETWORK_API_EXTENSIONS+=",security-group" NETWORK_API_EXTENSIONS+=",port-mac-address-regenerate" +NETWORK_API_EXTENSIONS+=",port-numa-affinity-policy" NETWORK_API_EXTENSIONS+=",port-security-groups-filtering" NETWORK_API_EXTENSIONS+=",segment" NETWORK_API_EXTENSIONS+=",segments-peer-subnet-host-routes" diff --git a/neutron/tests/tools.py b/neutron/tests/tools.py index 069fadf9c8b..d92874b1bab 100644 --- a/neutron/tests/tools.py +++ b/neutron/tests/tools.py @@ -266,3 +266,7 @@ def get_random_ipv6_mode(): def get_random_security_event(): return random.choice(log_const.LOG_EVENTS) + + +def get_random_port_numa_affinity_policy(): + return random.choice(constants.PORT_NUMA_POLICIES) 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 10746ffbeb7..83a04724e98 100644 --- a/neutron/tests/unit/db/test_db_base_plugin_v2.py +++ b/neutron/tests/unit/db/test_db_base_plugin_v2.py @@ -450,7 +450,7 @@ class NeutronDbPluginV2TestCase(testlib_api.WebTestCase): for arg in (('admin_state_up', 'device_id', 'mac_address', 'name', 'fixed_ips', 'tenant_id', 'device_owner', 'security_groups', - 'propagate_uplink_status') + + 'propagate_uplink_status', 'numa_affinity_policy') + (arg_list or ())): # Arg must be present if arg in kwargs: diff --git a/neutron/tests/unit/extensions/test_port_numa_affinity_policy.py b/neutron/tests/unit/extensions/test_port_numa_affinity_policy.py new file mode 100644 index 00000000000..308fc1d7865 --- /dev/null +++ b/neutron/tests/unit/extensions/test_port_numa_affinity_policy.py @@ -0,0 +1,85 @@ +# Copyright (c) 2020 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. + +import ddt +from neutron_lib.api.definitions import port_numa_affinity_policy as apidef +from neutron_lib.api.definitions import portbindings +from neutron_lib import constants + +from neutron.db import db_base_plugin_v2 +from neutron.db import port_numa_affinity_policy_db as pnap_db +from neutron.tests.unit.db import test_db_base_plugin_v2 + + +class PortNumaAffinityPolicyExtensionExtensionTestPlugin( + db_base_plugin_v2.NeutronDbPluginV2, + pnap_db.PortNumaAffinityPolicyDbMixin): + """Test plugin to mixin the port NUMA affinity policy extension.""" + + supported_extension_aliases = [apidef.ALIAS] + + def create_port(self, context, port): + with context.session.begin(subtransactions=True): + new_port = super( + PortNumaAffinityPolicyExtensionExtensionTestPlugin, + 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 context.session.begin(subtransactions=True): + updated_port = super( + PortNumaAffinityPolicyExtensionExtensionTestPlugin, + self).update_port(context, id, port) + updated_port[portbindings.VIF_TYPE] = portbindings.VIF_TYPE_UNBOUND + self._process_update_port(context, port['port'], updated_port) + return updated_port + + +@ddt.ddt +class PortNumaAffinityPolicyExtensionExtensionTestCase( + test_db_base_plugin_v2.NeutronDbPluginV2TestCase): + """Test API extension numa_affinity_policy attributes.""" + + def setUp(self, *args): + plugin = ('neutron.tests.unit.extensions.test_port_numa_affinity_' + 'policy.PortNumaAffinityPolicyExtensionExtensionTestPlugin') + super(PortNumaAffinityPolicyExtensionExtensionTestCase, + self).setUp(plugin=plugin) + + def _create_and_check_port_nap(self, numa_affinity_policy): + name = 'numa_affinity_policy' + keys = [('name', name), ('admin_state_up', True), + ('status', self.port_create_status), + ('numa_affinity_policy', numa_affinity_policy)] + with self.port(name=name, + numa_affinity_policy=numa_affinity_policy) as port: + for k, v in keys: + self.assertEqual(v, port['port'][k]) + return port + + def _update_and_check_port_nap(self, port, numa_affinity_policy): + data = {'port': {'numa_affinity_policy': numa_affinity_policy}} + req = self.new_update_request('ports', data, + port['port']['id']) + res = self.deserialize(self.fmt, req.get_response(self.api)) + self.assertEqual(numa_affinity_policy, + res['port']['numa_affinity_policy']) + + @ddt.data(*constants.PORT_NUMA_POLICIES, None) + def test_create_and_update_port_numa_affinity_policy(self, + numa_affinity_policy): + port = self._create_and_check_port_nap(numa_affinity_policy) + for new_nap in (*constants.PORT_NUMA_POLICIES, None): + self._update_and_check_port_nap(port, new_nap) diff --git a/neutron/tests/unit/objects/port/extensions/test_port_numa_affinity_policy.py b/neutron/tests/unit/objects/port/extensions/test_port_numa_affinity_policy.py new file mode 100644 index 00000000000..4e7474bc6b1 --- /dev/null +++ b/neutron/tests/unit/objects/port/extensions/test_port_numa_affinity_policy.py @@ -0,0 +1,38 @@ +# Copyright (c) 2020 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 import constants + +from neutron.objects.port.extensions import port_numa_affinity_policy +from neutron.tests.unit.objects import test_base as obj_test_base +from neutron.tests.unit import testlib_api + + +class PortNumaAffinityPolicyIfaceObjectTestCase( + obj_test_base.BaseObjectIfaceTestCase): + + _test_class = port_numa_affinity_policy.PortNumaAffinityPolicy + + +class PortNumaAffinityPolicyDbObjectTestCase( + obj_test_base.BaseDbObjectTestCase, + testlib_api.SqlTestCase): + + _test_class = port_numa_affinity_policy.PortNumaAffinityPolicy + + def setUp(self): + super(PortNumaAffinityPolicyDbObjectTestCase, self).setUp() + self.update_obj_fields( + {'port_id': lambda: self._create_test_port_id(), + 'numa_affinity_policy': constants.PORT_NUMA_POLICY_PREFERRED}) diff --git a/neutron/tests/unit/objects/test_base.py b/neutron/tests/unit/objects/test_base.py index c66ce654c29..32957d83154 100644 --- a/neutron/tests/unit/objects/test_base.py +++ b/neutron/tests/unit/objects/test_base.py @@ -44,6 +44,7 @@ from neutron.objects import base from neutron.objects.db import api as obj_db_api from neutron.objects import flavor from neutron.objects import network as net_obj +from neutron.objects.port.extensions import port_numa_affinity_policy from neutron.objects import ports from neutron.objects.qos import policy as qos_policy from neutron.objects import rbac_db @@ -541,6 +542,8 @@ FIELD_TYPE_VALUE_GENERATOR_MAP = { obj_fields.ListOfStringsField: tools.get_random_string_list, obj_fields.ObjectField: lambda: None, obj_fields.StringField: lambda: helpers.get_random_string(10), + port_numa_affinity_policy.NumaAffinityPoliciesEnumField: + tools.get_random_port_numa_affinity_policy, } diff --git a/neutron/tests/unit/objects/test_objects.py b/neutron/tests/unit/objects/test_objects.py index 9aa814ea524..4ccbd5455f8 100644 --- a/neutron/tests/unit/objects/test_objects.py +++ b/neutron/tests/unit/objects/test_objects.py @@ -69,7 +69,8 @@ object_data = { 'NetworkSegment': '1.0-57b7f2960971e3b95ded20cbc59244a8', 'NetworkSegmentRange': '1.0-bdec1fffc9058ea676089b1f2f2b3cf3', 'NetworkSubnetLock': '1.0-140de39d4b86ae346dc3d70b885bea53', - 'Port': '1.5-98f35183d876c9beb188f4bf44d4d886', + 'Port': '1.6-c9a1ecc035181aeb0af76eb395c09ac0', + 'PortNumaAffinityPolicy': '1.0-38fcea43e7bfb2536461f3d053c43aa3', 'PortBinding': '1.0-3306deeaa6deb01e33af06777d48d578', 'PortBindingLevel': '1.1-50d47f63218f87581b6cd9a62db574e5', 'PortDataPlaneStatus': '1.0-25be74bda46c749653a10357676c0ab2', diff --git a/neutron/tests/unit/objects/test_ports.py b/neutron/tests/unit/objects/test_ports.py index a6a1180fd0a..6d8f0803858 100644 --- a/neutron/tests/unit/objects/test_ports.py +++ b/neutron/tests/unit/objects/test_ports.py @@ -482,6 +482,12 @@ class PortDbObjectTestCase(obj_test_base.BaseDbObjectTestCase, self.assertNotIn('qos_network_policy_id', port_v1_4['versioned_object.data']) + def test_v1_6_to_v1_5_drops_numa_affinity_policy(self): + port_new = self._create_test_port() + port_v1_5 = port_new.obj_to_primitive(target_version='1.5') + self.assertNotIn('numa_affinity_policy', + port_v1_5['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/setup.cfg b/setup.cfg index d24a88a6740..38c4a48846e 100644 --- a/setup.cfg +++ b/setup.cfg @@ -113,6 +113,7 @@ neutron.ml2.extension_drivers = dns = neutron.plugins.ml2.extensions.dns_integration:DNSExtensionDriverML2 data_plane_status = neutron.plugins.ml2.extensions.data_plane_status:DataPlaneStatusExtensionDriver dns_domain_ports = neutron.plugins.ml2.extensions.dns_integration:DNSDomainPortsExtensionDriver + port_numa_affinity_policy = neutron.plugins.ml2.extensions.port_numa_affinity_policy:PortNumaAffinityPolicyExtensionDriver uplink_status_propagation = neutron.plugins.ml2.extensions.uplink_status_propagation:UplinkStatusPropagationExtensionDriver 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