diff --git a/neutron/db/db_base_plugin_common.py b/neutron/db/db_base_plugin_common.py index fc45df97856..36c427cc96d 100644 --- a/neutron/db/db_base_plugin_common.py +++ b/neutron/db/db_base_plugin_common.py @@ -15,6 +15,8 @@ import functools +import six + 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 subnet as subnet_def @@ -88,8 +90,9 @@ class DbBasePluginCommon(common_db_mixin.CommonDbMixin): """ @staticmethod - def _generate_mac(): - return net.get_random_mac(cfg.CONF.base_mac.split(':')) + def _generate_macs(mac_count=1): + mac_maker = net.random_mac_generator(cfg.CONF.base_mac.split(':')) + return [six.next(mac_maker) for x in range(mac_count)] @db_api.CONTEXT_READER def _is_mac_in_use(self, context, network_id, mac_address): diff --git a/neutron/db/db_base_plugin_v2.py b/neutron/db/db_base_plugin_v2.py index 97a76f64ef1..1136bdd96e4 100644 --- a/neutron/db/db_base_plugin_v2.py +++ b/neutron/db/db_base_plugin_v2.py @@ -1274,7 +1274,7 @@ class NeutronDbPluginV2(db_base_plugin_common.DbBasePluginCommon, raise exc.MacAddressInUse(net_id=port_data['network_id'], mac=mac_address) else: - mac_address = self._generate_mac() + mac_address = self._generate_macs()[0] db_port = models_v2.Port(mac_address=mac_address, **port_data) context.session.add(db_port) return db_port diff --git a/neutron/tests/common/net_helpers.py b/neutron/tests/common/net_helpers.py index 92adb110b36..5c383d98f1b 100644 --- a/neutron/tests/common/net_helpers.py +++ b/neutron/tests/common/net_helpers.py @@ -41,7 +41,7 @@ from neutron.agent.linux import iptables_firewall from neutron.agent.linux import utils from neutron.common import utils as common_utils from neutron.conf.agent import common as config -from neutron.db import db_base_plugin_common +from neutron.db import db_base_plugin_common as db_base from neutron.plugins.ml2.drivers.linuxbridge.agent import \ linuxbridge_neutron_agent as linuxbridge_agent from neutron.tests.common import base as common_base @@ -687,8 +687,8 @@ class PortFixture(fixtures.Fixture): super(PortFixture, self).__init__() self.bridge = bridge self.namespace = namespace - self.mac = ( - mac or db_base_plugin_common.DbBasePluginCommon._generate_mac()) + self.mac = (mac or + db_base.DbBasePluginCommon._generate_macs()[0]) self.port_id = port_id or uuidutils.generate_uuid() @abc.abstractmethod 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 613d3b343e2..c8c0bf8f53f 100644 --- a/neutron/tests/unit/db/test_db_base_plugin_v2.py +++ b/neutron/tests/unit/db/test_db_base_plugin_v2.py @@ -1782,8 +1782,8 @@ fixed_ips=ip_address%%3D%s&fixed_ips=ip_address%%3D%s&fixed_ips=subnet_id%%3D%s # simulate duplicate mac generation to make sure DBDuplicate is retried responses = ['12:34:56:78:00:00', '12:34:56:78:00:00', '12:34:56:78:00:01'] - with mock.patch.object(net, 'get_random_mac', - side_effect=responses) as grand_mac: + with mock.patch.object(net, 'random_mac_generator', + return_value=itertools.cycle(responses)) as grand_mac: with self.subnet() as s: with self.port(subnet=s) as p1, self.port(subnet=s) as p2: self.assertEqual('12:34:56:78:00:00', diff --git a/neutron/tests/unit/plugins/ml2/test_db.py b/neutron/tests/unit/plugins/ml2/test_db.py index 89c65fcb956..241b4ef6f5d 100644 --- a/neutron/tests/unit/plugins/ml2/test_db.py +++ b/neutron/tests/unit/plugins/ml2/test_db.py @@ -13,6 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +import re import warnings import mock @@ -50,7 +51,7 @@ class Ml2DBTestCase(testlib_api.SqlTestCase): network_obj.Network(self.ctx, id=network_id).create() def _setup_neutron_port(self, network_id, port_id): - mac_address = db_base_plugin_v2.NeutronDbPluginV2._generate_mac() + mac_address = db_base_plugin_v2.NeutronDbPluginV2._generate_macs()[0] port = port_obj.Port(self.ctx, id=port_id, network_id=network_id, @@ -287,6 +288,18 @@ class Ml2DBTestCase(testlib_api.SqlTestCase): port['mac_address']) self.assertEqual(port_id, observed_port.id) + def test_generating_multiple_mac_addresses(self): + mac_regex = "^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$" + + macs = db_base_plugin_v2.NeutronDbPluginV2._generate_macs() + self.assertEqual(1, len(macs)) + self.assertIsNotNone(re.search(mac_regex, macs[0])) + + macs = db_base_plugin_v2.NeutronDbPluginV2._generate_macs(5) + self.assertEqual(5, len(macs)) + for mac in macs: + self.assertIsNotNone(re.search(mac_regex, mac)) + class Ml2DvrDBTestCase(testlib_api.SqlTestCase): @@ -301,7 +314,7 @@ class Ml2DvrDBTestCase(testlib_api.SqlTestCase): ports = [] for port_id in port_ids: mac_address = (db_base_plugin_v2.NeutronDbPluginV2. - _generate_mac()) + _generate_macs()[0]) port = port_obj.Port(self.ctx, id=port_id, network_id=network_id,