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
This commit is contained in:
parent
e97ee8a972
commit
f21c7e2851
@ -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.
|
||||
|
@ -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):
|
||||
|
@ -1 +1 @@
|
||||
349b6fd605a6
|
||||
7d32f979895f
|
||||
|
@ -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))
|
@ -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__)
|
||||
|
58
neutron/extensions/netmtu_writable.py
Normal file
58
neutron/extensions/netmtu_writable.py
Normal file
@ -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]
|
@ -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',
|
||||
|
@ -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)
|
||||
|
@ -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"
|
||||
|
@ -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'
|
||||
|
@ -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)
|
||||
|
@ -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'
|
||||
},
|
||||
]
|
||||
}
|
||||
|
@ -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.
|
Loading…
Reference in New Issue
Block a user