From f21c7e2851bc99b424bdc5322dcd0e3dee7ee5a3 Mon Sep 17 00:00:00 2001 From: Ihar Hrachyshka Date: Mon, 7 Aug 2017 10:18:11 -0700 Subject: [PATCH] Allow to set/modify network mtu This patch adds ``net-mtu-writable`` API extension that allows to write to network ``mtu`` attribute. The patch also adds support for the extension to ml2, as well as covers the feature with unit and tempest tests. Agent side implementation of the feature is moved into a separate patch to ease review. DocImpact: neutron controller now supports ``net-mtu-writable`` API extension. APIImpact: new ``net-mtu-writable`` API extension was added. Related-Bug: #1671634 Change-Id: Ib232796562edd8fa69ec06b0cc5cb752c1467add --- doc/source/admin/config-mtu.rst | 8 +- neutron/db/db_base_plugin_v2.py | 32 ++-- .../alembic_migrations/versions/EXPAND_HEAD | 2 +- .../7d32f979895f_add_mtu_for_networks.py | 38 +++++ neutron/db/models_v2.py | 3 + neutron/extensions/netmtu_writable.py | 58 ++++++++ neutron/objects/network.py | 4 - neutron/plugins/ml2/plugin.py | 138 +++++++++++++----- .../tests/contrib/hooks/api_all_extensions | 1 + neutron/tests/tempest/api/test_networks.py | 31 ++++ .../tests/unit/db/test_db_base_plugin_v2.py | 1 + neutron/tests/unit/plugins/ml2/test_plugin.py | 40 ++--- ...itable-api-extension-f7038f85f3494a74.yaml | 17 +++ 13 files changed, 301 insertions(+), 72 deletions(-) create mode 100644 neutron/db/migration/alembic_migrations/versions/pike/expand/7d32f979895f_add_mtu_for_networks.py create mode 100644 neutron/extensions/netmtu_writable.py create mode 100644 releasenotes/notes/add-net-mtu-writable-api-extension-f7038f85f3494a74.yaml diff --git a/doc/source/admin/config-mtu.rst b/doc/source/admin/config-mtu.rst index 47486692504..0059eaa7661 100644 --- a/doc/source/admin/config-mtu.rst +++ b/doc/source/admin/config-mtu.rst @@ -29,10 +29,10 @@ architectures should avoid cases 2 and 3. .. note:: - You can trigger MTU recalculation for existing networks by changing the - MTU configuration and restarting the ``neutron-server`` service. - However, propagating MTU calculations to the data plane may require - users to delete and recreate ports on the network. + After you adjust MTU configuration options in ``neutron.conf`` and + ``ml2_conf.ini``, you should update ``mtu`` attribute for all existing + networks that need a new MTU. (Network MTU update is available for all core + plugins that implement the ``net-mtu-writable`` API extension.) When using the Open vSwitch or Linux bridge drivers, new MTU calculations will be propogated automatically after restarting the ``l3-agent`` service. diff --git a/neutron/db/db_base_plugin_v2.py b/neutron/db/db_base_plugin_v2.py index df4982138b3..d51fe717055 100644 --- a/neutron/db/db_base_plugin_v2.py +++ b/neutron/db/db_base_plugin_v2.py @@ -379,6 +379,7 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon, args = {'tenant_id': n['tenant_id'], 'id': n.get('id') or uuidutils.generate_uuid(), 'name': n['name'], + 'mtu': n.get('mtu'), 'admin_state_up': n['admin_state_up'], 'status': n.get('status', constants.NET_STATUS_ACTIVE), 'description': n.get('description')} @@ -465,21 +466,34 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon, network = self._get_network(context, id) return self._make_network_dict(network, fields, context=context) + @db_api.retry_if_session_inactive() + def _get_networks(self, context, filters=None, fields=None, + sorts=None, limit=None, marker=None, + page_reverse=False): + marker_obj = ndb_utils.get_marker_obj(self, context, 'network', + limit, marker) + return model_query.get_collection( + context, models_v2.Network, + # if caller needs postprocessing, it should implement it explicitly + dict_func=None, + filters=filters, fields=fields, + sorts=sorts, + limit=limit, + marker_obj=marker_obj, + page_reverse=page_reverse) + @db_api.retry_if_session_inactive() def get_networks(self, context, filters=None, fields=None, sorts=None, limit=None, marker=None, page_reverse=False): - marker_obj = ndb_utils.get_marker_obj(self, context, 'network', - limit, marker) make_network_dict = functools.partial(self._make_network_dict, context=context) - return model_query.get_collection(context, models_v2.Network, - make_network_dict, - filters=filters, fields=fields, - sorts=sorts, - limit=limit, - marker_obj=marker_obj, - page_reverse=page_reverse) + return [ + make_network_dict(net, fields) + for net in self._get_networks( + context, filters=filters, fields=fields, sorts=sorts, + limit=limit, marker=marker, page_reverse=page_reverse) + ] @db_api.retry_if_session_inactive() def get_networks_count(self, context, filters=None): diff --git a/neutron/db/migration/alembic_migrations/versions/EXPAND_HEAD b/neutron/db/migration/alembic_migrations/versions/EXPAND_HEAD index 17a4ac0d323..902d5a3396c 100644 --- a/neutron/db/migration/alembic_migrations/versions/EXPAND_HEAD +++ b/neutron/db/migration/alembic_migrations/versions/EXPAND_HEAD @@ -1 +1 @@ -349b6fd605a6 +7d32f979895f diff --git a/neutron/db/migration/alembic_migrations/versions/pike/expand/7d32f979895f_add_mtu_for_networks.py b/neutron/db/migration/alembic_migrations/versions/pike/expand/7d32f979895f_add_mtu_for_networks.py new file mode 100644 index 00000000000..fc9c202c04b --- /dev/null +++ b/neutron/db/migration/alembic_migrations/versions/pike/expand/7d32f979895f_add_mtu_for_networks.py @@ -0,0 +1,38 @@ +# 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. +# + +"""add mtu for networks + +Revision ID: 7d32f979895f +Revises: c8c222d42aa9 +Create Date: 2017-07-13 19:25:29.204547 + +""" + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = '7d32f979895f' +down_revision = '349b6fd605a6' + +# require the migration rule that dropped the mtu column in the past +depends_on = ('b67e765a3524',) + + +def upgrade(): + op.add_column('networks', + sa.Column('mtu', + sa.Integer(), + nullable=True)) diff --git a/neutron/db/models_v2.py b/neutron/db/models_v2.py index 4906d015ef1..6863cc3b267 100644 --- a/neutron/db/models_v2.py +++ b/neutron/db/models_v2.py @@ -267,6 +267,9 @@ class Network(standard_attr.HasStandardAttributes, model_base.BASEV2, lazy='subquery', cascade='all, delete, delete-orphan') availability_zone_hints = sa.Column(sa.String(255)) + # TODO(ihrachys) provide data migration path to fill in mtus for existing + # networks in Queens when all controllers run Pike+ code + mtu = sa.Column(sa.Integer, nullable=True) dhcp_agents = orm.relationship( 'Agent', lazy='subquery', viewonly=True, secondary=ndab_model.NetworkDhcpAgentBinding.__table__) diff --git a/neutron/extensions/netmtu_writable.py b/neutron/extensions/netmtu_writable.py new file mode 100644 index 00000000000..2a7641accdd --- /dev/null +++ b/neutron/extensions/netmtu_writable.py @@ -0,0 +1,58 @@ +# 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 import converters +from neutron_lib.api.definitions import network +from neutron_lib.api.definitions import network_mtu +from neutron_lib.api import extensions + + +#TODO(ihrachys) migrate api definition to neutron-lib + +MTU = 'mtu' + +RESOURCE_ATTRIBUTE_MAP = { + network.COLLECTION_NAME: { + MTU: {'allow_post': True, 'allow_put': True, 'is_visible': True, + 'validate': {'type:non_negative': None}, 'default': 0, + 'convert_to': converters.convert_to_int}, + }, +} + + +class Netmtu_writable(extensions.ExtensionDescriptor): + """Extension class supporting writable network MTU.""" + + @classmethod + def get_name(cls): + return 'Network MTU (writable)' + + @classmethod + def get_alias(cls): + return 'net-mtu-writable' + + @classmethod + def get_description(cls): + return 'Provides a writable MTU attribute for a network resource.' + + @classmethod + def get_updated(cls): + return '2017-07-12T00:00:00-00:00' + + def get_extended_resources(self, version): + if version == "2.0": + return RESOURCE_ATTRIBUTE_MAP + else: + return {} + + def get_required_extensions(self): + return [network_mtu.ALIAS] diff --git a/neutron/objects/network.py b/neutron/objects/network.py index b52c8fb9689..d9d3c40fc68 100644 --- a/neutron/objects/network.py +++ b/neutron/objects/network.py @@ -186,10 +186,6 @@ class Network(rbac_db.NeutronRbacObject): synthetic_fields = [ 'dns_domain', - # MTU is not stored in the database any more, it's a synthetic field - # that may be used by plugins to provide a canonical representation for - # the resource - 'mtu', 'qos_policy_id', 'security', 'segments', diff --git a/neutron/plugins/ml2/plugin.py b/neutron/plugins/ml2/plugin.py index a4f22d42cdf..29a40c781d0 100644 --- a/neutron/plugins/ml2/plugin.py +++ b/neutron/plugins/ml2/plugin.py @@ -19,7 +19,6 @@ from neutron_lib.api.definitions import network as net_def from neutron_lib.api.definitions import port as port_def from neutron_lib.api.definitions import port_security as psec from neutron_lib.api.definitions import portbindings -from neutron_lib.api.definitions import provider_net from neutron_lib.api.definitions import subnet as subnet_def from neutron_lib.api import validators from neutron_lib.callbacks import events @@ -77,9 +76,10 @@ from neutron.db import subnet_service_type_db_models as service_type_db from neutron.db import vlantransparent_db from neutron.extensions import allowedaddresspairs as addr_pair from neutron.extensions import availability_zone as az_ext -from neutron.extensions import multiprovidernet as mpnet +from neutron.extensions import netmtu_writable as mtu_ext from neutron.extensions import providernet as provider from neutron.extensions import vlantransparent +from neutron.plugins.common import utils as p_utils from neutron.plugins.ml2.common import exceptions as ml2_exc from neutron.plugins.ml2 import config # noqa from neutron.plugins.ml2 import db @@ -146,7 +146,8 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, "dhcp_agent_scheduler", "multi-provider", "allowed-address-pairs", "extra_dhcp_opt", "subnet_allocation", - "net-mtu", "vlan-transparent", + "net-mtu", "net-mtu-writable", + "vlan-transparent", "address-scope", "availability_zone", "network_availability_zone", @@ -724,14 +725,16 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, self._delete_objects(context, resource, to_delete) return objects - def _get_network_mtu(self, network): + def _get_network_mtu(self, network_db, validate=True): mtus = [] try: - segments = network[mpnet.SEGMENTS] + segments = network_db['segments'] except KeyError: - segments = [network] + segments = [network_db] for s in segments: - segment_type = s[provider_net.NETWORK_TYPE] + segment_type = s.get('network_type') + if segment_type is None: + continue try: type_driver = self.type_manager.drivers[segment_type].obj except KeyError: @@ -742,7 +745,7 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, # a bad setup, it's better to be safe than sorry here. Also, # several unit tests use non-existent driver types that may # trigger the exception here. - if segment_type and s[provider_net.SEGMENTATION_ID]: + if segment_type and s['segmentation_id']: LOG.warning( _LW("Failed to determine MTU for segment " "%(segment_type)s:%(segment_id)s; network " @@ -750,18 +753,29 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, "accurate"), { 'segment_type': segment_type, - 'segment_id': s[provider_net.SEGMENTATION_ID], - 'network_id': network['id'], + 'segment_id': s['segmentation_id'], + 'network_id': network_db['id'], } ) else: - mtu = type_driver.get_mtu(s[provider_net.PHYSICAL_NETWORK]) + mtu = type_driver.get_mtu(s['physical_network']) # Some drivers, like 'local', may return None; the assumption # then is that for the segment type, MTU has no meaning or # unlimited, and so we should then ignore those values. if mtu: mtus.append(mtu) - return min(mtus) if mtus else 0 + + max_mtu = min(mtus) if mtus else p_utils.get_deployment_physnet_mtu() + net_mtu = network_db.get('mtu') + + if validate: + # validate that requested mtu conforms to allocated segments + if net_mtu and max_mtu and max_mtu < net_mtu: + msg = _("Requested MTU is too big, maximum is %d") % max_mtu + raise exc.InvalidInput(error_message=msg) + + # if mtu is not set in database, use the maximum possible + return net_mtu or max_mtu def _before_create_network(self, context, network): net_data = network[net_def.RESOURCE_NAME] @@ -773,23 +787,29 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, tenant_id = net_data['tenant_id'] with db_api.context_manager.writer.using(context): net_db = self.create_network_db(context, network) - result = self._make_network_dict(net_db, process_extensions=False, - context=context) - self.extension_manager.process_create_network(context, net_data, - result) - self._process_l3_create(context, result, net_data) - net_data['id'] = result['id'] + net_data['id'] = net_db.id self.type_manager.create_network_segments(context, net_data, tenant_id) + net_db.mtu = self._get_network_mtu(net_db) + + result = self._make_network_dict(net_db, process_extensions=False, + context=context) + + self.extension_manager.process_create_network( + context, + # NOTE(ihrachys) extensions expect no id in the dict + {k: v for k, v in net_data.items() if k != 'id'}, + result) + + self._process_l3_create(context, result, net_data) self.type_manager.extend_network_dict_provider(context, result) + # Update the transparent vlan if configured if utils.is_extension_supported(self, 'vlan-transparent'): vlt = vlantransparent.get_vlan_transparent(net_data) net_db['vlan_transparent'] = vlt result['vlan_transparent'] = vlt - result[api.MTU] = self._get_network_mtu(result) - if az_ext.AZ_HINTS in net_data: self.validate_availability_zones(context, 'network', net_data[az_ext.AZ_HINTS]) @@ -853,6 +873,17 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, # Expire the db_network in current transaction, so that the join # relationship can be updated. context.session.expire(db_network) + + if ( + mtu_ext.MTU in net_data or + # NOTE(ihrachys) mtu may be null for existing networks, + # calculate and update it as needed; the conditional can be + # removed in Queens when we populate all mtu attributes and + # enforce it's not nullable on database level + db_network.mtu is None): + db_network.mtu = self._get_network_mtu(db_network, + validate=False) + updated_network = self._make_network_dict( db_network, context=context) self.type_manager.extend_network_dict_provider( @@ -889,27 +920,42 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, @db_api.retry_if_session_inactive() def get_network(self, context, id, fields=None): - with db_api.context_manager.reader.using(context): - result = super(Ml2Plugin, self).get_network(context, id, None) - self.type_manager.extend_network_dict_provider(context, result) - result[api.MTU] = self._get_network_mtu(result) + # NOTE(ihrachys) use writer manager to be able to update mtu + # TODO(ihrachys) remove in Queens+ when mtu is not nullable + with db_api.context_manager.writer.using(context): + net_db = self._get_network(context, id) - return db_utils.resource_fields(result, fields) + # NOTE(ihrachys) pre Pike networks may have null mtus; update them + # in database if needed + # TODO(ihrachys) remove in Queens+ when mtu is not nullable + if net_db.mtu is None: + net_db.mtu = self._get_network_mtu(net_db, validate=False) + + net_data = self._make_network_dict(net_db, context=context) + self.type_manager.extend_network_dict_provider(context, net_data) + + return db_utils.resource_fields(net_data, fields) @db_api.retry_if_session_inactive() def get_networks(self, context, filters=None, fields=None, sorts=None, limit=None, marker=None, page_reverse=False): - with db_api.context_manager.reader.using(context): - nets = super(Ml2Plugin, - self).get_networks(context, filters, None, sorts, - limit, marker, page_reverse) - self.type_manager.extend_networks_dict_provider(context, nets) + # NOTE(ihrachys) use writer manager to be able to update mtu + # TODO(ihrachys) remove in Queens when mtu is not nullable + with db_api.context_manager.writer.using(context): + nets_db = super(Ml2Plugin, self)._get_networks( + context, filters, None, sorts, limit, marker, page_reverse) - nets = self._filter_nets_provider(context, nets, filters) - - for net in nets: - net[api.MTU] = self._get_network_mtu(net) + # NOTE(ihrachys) pre Pike networks may have null mtus; update them + # in database if needed + # TODO(ihrachys) remove in Queens+ when mtu is not nullable + net_data = [] + for net in nets_db: + if net.mtu is None: + net.mtu = self._get_network_mtu(net, validate=False) + net_data.append(self._make_network_dict(net, context=context)) + self.type_manager.extend_networks_dict_provider(context, net_data) + nets = self._filter_nets_provider(context, net_data, filters) return [db_utils.resource_fields(net, fields) for net in nets] def get_network_contexts(self, context, network_ids): @@ -970,11 +1016,17 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, with db_api.context_manager.writer.using(context): result, net_db, ipam_sub = self._create_subnet_precommit( context, subnet) + + # NOTE(ihrachys) pre Pike networks may have null mtus; update them + # in database if needed + # TODO(ihrachys) remove in Queens+ when mtu is not nullable + if net_db['mtu'] is None: + net_db['mtu'] = self._get_network_mtu(net_db, validate=False) + self.extension_manager.process_create_subnet( context, subnet[subnet_def.RESOURCE_NAME], result) network = self._make_network_dict(net_db, context=context) self.type_manager.extend_network_dict_provider(context, network) - network[api.MTU] = self._get_network_mtu(network) mech_context = driver_context.SubnetContext(self, context, result, network) self.mechanism_manager.create_subnet_precommit(mech_context) @@ -1513,7 +1565,10 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, @db_api.retry_if_session_inactive(context_var_name='plugin_context') def get_bound_port_context(self, plugin_context, port_id, host=None, cached_networks=None): - with db_api.context_manager.reader.using(plugin_context) as session: + # NOTE(ihrachys) use writer manager to be able to update mtu when + # fetching network + # TODO(ihrachys) remove in Queens+ when mtu is not nullable + with db_api.context_manager.writer.using(plugin_context) as session: try: port_db = (session.query(models_v2.Port). enable_eagerloads(False). @@ -1566,7 +1621,10 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, @db_api.retry_if_session_inactive(context_var_name='plugin_context') def get_bound_ports_contexts(self, plugin_context, dev_ids, host=None): result = {} - with db_api.context_manager.reader.using(plugin_context): + # NOTE(ihrachys) use writer manager to be able to update mtu when + # fetching network + # TODO(ihrachys) remove in Queens+ when mtu is not nullable + with db_api.context_manager.writer.using(plugin_context): dev_to_full_pids = db.partial_port_ids_to_full_ids( plugin_context, dev_ids) # get all port objects for IDs @@ -1816,6 +1874,12 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2, elif event == events.PRECOMMIT_DELETE: self.type_manager.release_network_segment(context, segment) + # change in segments could affect resulting network mtu, so let's + # recalculate it + network_db = self._get_network(context, network_id) + network_db.mtu = self._get_network_mtu(network_db) + network_db.save(session=context.session) + try: self._notify_mechanism_driver_for_segment_change( event, context, network_id) diff --git a/neutron/tests/contrib/hooks/api_all_extensions b/neutron/tests/contrib/hooks/api_all_extensions index 29f31f444b4..c9075a32ac4 100644 --- a/neutron/tests/contrib/hooks/api_all_extensions +++ b/neutron/tests/contrib/hooks/api_all_extensions @@ -21,6 +21,7 @@ NETWORK_API_EXTENSIONS+=",l3_agent_scheduler" NETWORK_API_EXTENSIONS+=",metering" NETWORK_API_EXTENSIONS+=",multi-provider" NETWORK_API_EXTENSIONS+=",net-mtu" +NETWORK_API_EXTENSIONS+=",net-mtu-writable" NETWORK_API_EXTENSIONS+=",network-ip-availability" NETWORK_API_EXTENSIONS+=",network_availability_zone" NETWORK_API_EXTENSIONS+=",pagination" diff --git a/neutron/tests/tempest/api/test_networks.py b/neutron/tests/tempest/api/test_networks.py index 0b395696ffc..b350068e03d 100644 --- a/neutron/tests/tempest/api/test_networks.py +++ b/neutron/tests/tempest/api/test_networks.py @@ -15,8 +15,10 @@ from tempest.lib import decorators from tempest import test +import testtools from neutron.tests.tempest.api import base +from neutron.tests.tempest import config class NetworksTestJSON(base.BaseNetworkTest): @@ -129,6 +131,35 @@ class NetworksTestJSON(base.BaseNetworkTest): _check_list_networks_fields(['project_id', 'tenant_id'], True, True) +# TODO(ihrachys): check that bad mtu is not allowed; current API extension +# definition doesn't enforce values +# TODO(ihrachys): check that new segment reservation updates mtu, once +# https://review.openstack.org/#/c/353115/ is merged +class NetworksMtuTestJSON(base.BaseNetworkTest): + required_extensions = ['net-mtu', 'net-mtu-writable'] + + @decorators.idempotent_id('c79dbf94-ee26-420f-a56f-382aaccb1a41') + def test_create_network_custom_mtu(self): + # 68 should be supported by all implementations, as per api-ref + network = self.create_network(mtu=68) + body = self.client.show_network(network['id'])['network'] + self.assertEqual(68, body['mtu']) + + @decorators.idempotent_id('2d35d49d-9d16-465c-92c7-4768eb717688') + @testtools.skipUnless(config.CONF.network_feature_enabled.ipv6, + 'IPv6 is not enabled') + def test_update_network_custom_mtu(self): + # 68 should be supported by all implementations, as per api-ref + network = self.create_network(mtu=68) + body = self.client.show_network(network['id'])['network'] + self.assertEqual(68, body['mtu']) + + # 1280 should be supported by all ipv6 compliant implementations + self.client.update_network(network['id'], mtu=1280) + body = self.client.show_network(network['id'])['network'] + self.assertEqual(1280, body['mtu']) + + class NetworksSearchCriteriaTest(base.BaseSearchCriteriaTest): resource = 'network' 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 f9e52b03111..294eecbdece 100644 --- a/neutron/tests/unit/db/test_db_base_plugin_v2.py +++ b/neutron/tests/unit/db/test_db_base_plugin_v2.py @@ -6150,6 +6150,7 @@ class DbModelMixin(object): "admin_state_up=True, " "vlan_transparent=None, " "availability_zone_hints=None, " + "mtu=None, " "standard_attr_id=None}>") final_exp = exp_start_with + exp_middle + exp_end_with self.assertEqual(final_exp, actual_repr_output) diff --git a/neutron/tests/unit/plugins/ml2/test_plugin.py b/neutron/tests/unit/plugins/ml2/test_plugin.py index 7b34b62a8a3..28f2e359f1a 100644 --- a/neutron/tests/unit/plugins/ml2/test_plugin.py +++ b/neutron/tests/unit/plugins/ml2/test_plugin.py @@ -1367,8 +1367,8 @@ class Test_GetNetworkMtu(Ml2PluginV2TestCase): plugin.type_manager.drivers['driver1'].obj = mock_type_driver net = { 'name': 'net1', - pnet.NETWORK_TYPE: 'driver1', - pnet.PHYSICAL_NETWORK: 'physnet1', + 'network_type': 'driver1', + 'physical_network': 'physnet1', } plugin._get_network_mtu(net) mock_type_driver.get_mtu.assert_called_once_with('physnet1') @@ -1380,6 +1380,12 @@ class Test_GetNetworkMtu(Ml2PluginV2TestCase): def get_mtu(self, physical_network=None): return mtu + def validate_provider_segment(self, segment): + pass + + def is_partial_segment(self, segment): + return False + driver_mock = mock.Mock() driver_mock.obj = FakeDriver() plugin.type_manager.drivers[driver] = driver_mock @@ -1392,8 +1398,8 @@ class Test_GetNetworkMtu(Ml2PluginV2TestCase): 'name': 'net1', mpnet.SEGMENTS: [ { - pnet.NETWORK_TYPE: 'driver1', - pnet.PHYSICAL_NETWORK: 'physnet1' + 'network_type': 'driver1', + 'physical_network': 'physnet1' }, ] } @@ -1408,12 +1414,12 @@ class Test_GetNetworkMtu(Ml2PluginV2TestCase): 'name': 'net1', mpnet.SEGMENTS: [ { - pnet.NETWORK_TYPE: 'driver1', - pnet.PHYSICAL_NETWORK: 'physnet1' + 'network_type': 'driver1', + 'physical_network': 'physnet1' }, { - pnet.NETWORK_TYPE: 'driver2', - pnet.PHYSICAL_NETWORK: 'physnet2' + 'network_type': 'driver2', + 'physical_network': 'physnet2' }, ] } @@ -1425,8 +1431,8 @@ class Test_GetNetworkMtu(Ml2PluginV2TestCase): net = { 'name': 'net1', - pnet.NETWORK_TYPE: 'driver1', - pnet.PHYSICAL_NETWORK: 'physnet1', + 'network_type': 'driver1', + 'physical_network': 'physnet1', } self.assertEqual(1400, plugin._get_network_mtu(net)) @@ -1436,10 +1442,10 @@ class Test_GetNetworkMtu(Ml2PluginV2TestCase): net = { 'name': 'net1', - pnet.NETWORK_TYPE: 'driver1', - pnet.PHYSICAL_NETWORK: 'physnet1', + 'network_type': 'driver1', + 'physical_network': 'physnet1', } - self.assertEqual(0, plugin._get_network_mtu(net)) + self.assertEqual(1500, plugin._get_network_mtu(net)) def test_unknown_segment_type_ignored(self): plugin = directory.get_plugin() @@ -1450,12 +1456,12 @@ class Test_GetNetworkMtu(Ml2PluginV2TestCase): 'name': 'net1', mpnet.SEGMENTS: [ { - pnet.NETWORK_TYPE: 'driver1', - pnet.PHYSICAL_NETWORK: 'physnet1' + 'network_type': 'driver1', + 'physical_network': 'physnet1' }, { - pnet.NETWORK_TYPE: 'driver2', - pnet.PHYSICAL_NETWORK: 'physnet2' + 'network_type': 'driver2', + 'physical_network': 'physnet2' }, ] } diff --git a/releasenotes/notes/add-net-mtu-writable-api-extension-f7038f85f3494a74.yaml b/releasenotes/notes/add-net-mtu-writable-api-extension-f7038f85f3494a74.yaml new file mode 100644 index 00000000000..495f44b7004 --- /dev/null +++ b/releasenotes/notes/add-net-mtu-writable-api-extension-f7038f85f3494a74.yaml @@ -0,0 +1,17 @@ +--- +features: + - | + The new ``net-mtu-writable`` extension API definition has been added. The + new extension indicates that the network ``mtu`` attribute is writeable. + Plugins supporting the new extension are expected to also support + ``net-mtu``. The first plugin that gets support for the new extension is + ``ml2``. +other: + - | + Changing MTU configuration options (``global_physnet_mtu``, + ``physical_network_mtus``, and ``path_mtu``) and restarting + ``neutron-serer`` no longer affects existing networks' MTUs. Nevertheless, + new networks will use new option values for MTU calculation. To reflect + configuration changes for existing networks, one may use the new + ``net-mtu-writable`` API extension to update ``mtu`` attribute for those + networks.