Add support to regenerate port mac_address
Passing 'null' (None) as the mac address in a port update request causes the port's mac address to be re-generated using the base MAC address Neutron uses for VIFs. This change implementes a temporary lib api definition with a new converter that will generate valid mac if the data provided is None. APIImpact: Port mac_addr regenerated if None passed on update. Closes-Bug: #1768690 Change-Id: I7d04beea4810718c3b745de8ea97897b1323267e
This commit is contained in:
parent
9cb68ce777
commit
8f3a066b20
59
neutron/extensions/_port_mac_address_regenerate_lib.py
Normal file
59
neutron/extensions/_port_mac_address_regenerate_lib.py
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
TODO(hjensas): This module should be deleted once neutron-lib containing
|
||||||
|
Change-Id: Ibfcf179c2051d2bf47d4d1e62e8146cbee29fd64 is released.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from neutron_lib.api.definitions import port as port_def
|
||||||
|
from neutron_lib import constants
|
||||||
|
from neutron_lib.utils import net as net_utils
|
||||||
|
from oslo_config import cfg
|
||||||
|
|
||||||
|
|
||||||
|
def convert_to_mac_if_none(data):
|
||||||
|
"""Convert to a random mac address if data is None
|
||||||
|
|
||||||
|
:param data: The data value
|
||||||
|
:return: Random mac address if data is None, else return data.
|
||||||
|
"""
|
||||||
|
if data is None:
|
||||||
|
return net_utils.get_random_mac(cfg.CONF.base_mac.split(':'))
|
||||||
|
|
||||||
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
NAME = 'Neutron Port MAC address regenerate'
|
||||||
|
ALIAS = 'port-mac-address-regenerate'
|
||||||
|
DESCRIPTION = "Network port MAC address regenerate"
|
||||||
|
UPDATED_TIMESTAMP = "2018-05-03T10:00:00-00:00"
|
||||||
|
|
||||||
|
RESOURCE_ATTRIBUTE_MAP = {
|
||||||
|
port_def.COLLECTION_NAME: {
|
||||||
|
'mac_address': {'allow_post': True, 'allow_put': True,
|
||||||
|
'default': constants.ATTR_NOT_SPECIFIED,
|
||||||
|
'convert_to': convert_to_mac_if_none,
|
||||||
|
'validate': {'type:mac_address': None},
|
||||||
|
'enforce_policy': True,
|
||||||
|
'is_visible': True},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IS_SHIM_EXTENSION = False
|
||||||
|
IS_STANDARD_ATTR_EXTENSION = False
|
||||||
|
SUB_RESOURCE_ATTRIBUTE_MAP = {}
|
||||||
|
ACTION_MAP = {}
|
||||||
|
REQUIRED_EXTENSIONS = []
|
||||||
|
OPTIONAL_EXTENSIONS = []
|
||||||
|
ACTION_STATUS = {}
|
24
neutron/extensions/port_mac_address_regenerate.py
Normal file
24
neutron/extensions/port_mac_address_regenerate.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
# TODO(hjensas) When we have neutron-lib release, use it.
|
||||||
|
# from neutron_lib.api.definitions import port_mac_address_regenerate as apidef
|
||||||
|
|
||||||
|
from neutron.extensions import _port_mac_address_regenerate_lib as apidef
|
||||||
|
from neutron_lib.api import extensions as api_extensions
|
||||||
|
|
||||||
|
|
||||||
|
class Port_mac_address_regenerate(api_extensions.APIExtensionDescriptor):
|
||||||
|
"""Extension to support port MAC address regeneration"""
|
||||||
|
|
||||||
|
api_definition = apidef
|
@ -159,7 +159,8 @@ class Ml2Plugin(db_base_plugin_v2.NeutronDbPluginV2,
|
|||||||
"subnet-service-types",
|
"subnet-service-types",
|
||||||
"ip-substring-filtering",
|
"ip-substring-filtering",
|
||||||
"port-security-groups-filtering",
|
"port-security-groups-filtering",
|
||||||
"empty-string-filtering"]
|
"empty-string-filtering",
|
||||||
|
"port-mac-address-regenerate"]
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def supported_extension_aliases(self):
|
def supported_extension_aliases(self):
|
||||||
|
@ -40,6 +40,7 @@ NETWORK_API_EXTENSIONS+=",rbac-policies"
|
|||||||
NETWORK_API_EXTENSIONS+=",router"
|
NETWORK_API_EXTENSIONS+=",router"
|
||||||
NETWORK_API_EXTENSIONS+=",router_availability_zone"
|
NETWORK_API_EXTENSIONS+=",router_availability_zone"
|
||||||
NETWORK_API_EXTENSIONS+=",security-group"
|
NETWORK_API_EXTENSIONS+=",security-group"
|
||||||
|
NETWORK_API_EXTENSIONS+=",port-mac-address-regenerate"
|
||||||
NETWORK_API_EXTENSIONS+=",port-security-groups-filtering"
|
NETWORK_API_EXTENSIONS+=",port-security-groups-filtering"
|
||||||
NETWORK_API_EXTENSIONS+=",segment"
|
NETWORK_API_EXTENSIONS+=",segment"
|
||||||
NETWORK_API_EXTENSIONS+=",service-type"
|
NETWORK_API_EXTENSIONS+=",service-type"
|
||||||
|
@ -962,6 +962,29 @@ class TestMl2PortsV2(test_plugin.TestPortsV2, Ml2PluginV2TestCase):
|
|||||||
host_arg={portbindings.HOST_ID: HOST},
|
host_arg={portbindings.HOST_ID: HOST},
|
||||||
arg_list=(portbindings.HOST_ID,))
|
arg_list=(portbindings.HOST_ID,))
|
||||||
|
|
||||||
|
def test_update_port_regenerate_mac(self):
|
||||||
|
ctx = context.get_admin_context()
|
||||||
|
plugin = directory.get_plugin()
|
||||||
|
data = {'port': {'mac_address': None}}
|
||||||
|
with self.port() as port:
|
||||||
|
current_mac = port['port']['mac_address']
|
||||||
|
req = self.new_update_request('ports', data, port['port']['id'])
|
||||||
|
self.assertEqual(200, req.get_response(self.api).status_int)
|
||||||
|
new_mac = plugin.get_port(ctx, port['port']['id'])['mac_address']
|
||||||
|
self.assertNotEqual(current_mac, new_mac)
|
||||||
|
self.assertTrue(netaddr.valid_mac(new_mac))
|
||||||
|
|
||||||
|
def test_update_port_mac_does_not_change(self):
|
||||||
|
ctx = context.get_admin_context()
|
||||||
|
plugin = directory.get_plugin()
|
||||||
|
data = {'port': {'description': 'Port Description'}}
|
||||||
|
with self.port() as port:
|
||||||
|
current_mac = port['port']['mac_address']
|
||||||
|
req = self.new_update_request('ports', data, port['port']['id'])
|
||||||
|
self.assertEqual(200, req.get_response(self.api).status_int)
|
||||||
|
new_mac = plugin.get_port(ctx, port['port']['id'])['mac_address']
|
||||||
|
self.assertEqual(current_mac, new_mac)
|
||||||
|
|
||||||
def test_update_non_existent_port(self):
|
def test_update_non_existent_port(self):
|
||||||
ctx = context.get_admin_context()
|
ctx = context.get_admin_context()
|
||||||
plugin = directory.get_plugin()
|
plugin = directory.get_plugin()
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- |
|
||||||
|
Adds api extenstion ``port-mac-address-regenerate``. When passing
|
||||||
|
``'null'`` (``None``) as the ``mac_address`` on port update a converter
|
||||||
|
will generate a new mac address that will be assigned to the port.
|
||||||
|
`RFE: #1768690 <https://bugs.launchpad.net/neutron/+bug/1768690>`_.
|
Loading…
Reference in New Issue
Block a user