net: explicitly set mac on linux bridge
The default behavior on a linux bridge is to use the lowest mac of all attached interface. This isn't a problem when the bridge is first set up, because the bridged interface is the only interface attached. But, when instance interfaces are attached, there is a chance a lower mac could be assigned and the bridge will switch macs. This patch always sets the mac on the bridge to the mac of the bridged interface. Change-Id: Ibf5333516a4c5487a3ee7c662e07028789bdd286 Closes-bug: #1488686
This commit is contained in:
parent
3f26a62007
commit
33fba48726
|
@ -24,6 +24,7 @@ import re
|
|||
import time
|
||||
|
||||
import netaddr
|
||||
import netifaces
|
||||
from oslo_concurrency import processutils
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
|
@ -1613,10 +1614,6 @@ class LinuxBridgeInterfaceDriver(LinuxNetInterfaceDriver):
|
|||
_execute('brctl', 'setfd', bridge, 0, run_as_root=True)
|
||||
# _execute('brctl setageing %s 10' % bridge, run_as_root=True)
|
||||
_execute('brctl', 'stp', bridge, 'off', run_as_root=True)
|
||||
# (danwent) bridge device MAC address can't be set directly.
|
||||
# instead it inherits the MAC address of the first device on the
|
||||
# bridge, which will either be the vlan interface, or a
|
||||
# physical NIC.
|
||||
_execute('ip', 'link', 'set', bridge, 'up', run_as_root=True)
|
||||
|
||||
if interface:
|
||||
|
@ -1629,6 +1626,18 @@ class LinuxBridgeInterfaceDriver(LinuxNetInterfaceDriver):
|
|||
msg = _('Failed to add interface: %s') % err
|
||||
raise exception.NovaException(msg)
|
||||
|
||||
# NOTE(apmelton): Linux bridge's default behavior is to use the
|
||||
# lowest mac of all plugged interfaces. This isn't a problem when
|
||||
# it is first created and the only interface is the bridged
|
||||
# interface. But, as instance interfaces are plugged, there is a
|
||||
# chance for the mac to change. So, set it here so that it won't
|
||||
# change in the future.
|
||||
if not CONF.fake_network:
|
||||
interface_addrs = netifaces.ifaddresses(interface)
|
||||
interface_mac = interface_addrs[netifaces.AF_LINK][0]['addr']
|
||||
_execute('ip', 'link', 'set', bridge, 'address', interface_mac,
|
||||
run_as_root=True)
|
||||
|
||||
out, err = _execute('ip', 'link', 'set', interface, 'up',
|
||||
check_exit_code=False, run_as_root=True)
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ import time
|
|||
|
||||
import mock
|
||||
from mox3 import mox
|
||||
import netifaces
|
||||
from oslo_concurrency import processutils
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
|
@ -1127,11 +1128,20 @@ class LinuxNetworkTestCase(test.NoDBTestCase):
|
|||
self._test_add_metadata_forward_rule(expected)
|
||||
|
||||
def test_ensure_bridge_brings_up_interface(self):
|
||||
# We have to bypass the CONF.fake_network check so that netifaces
|
||||
# is actually called.
|
||||
self.flags(fake_network=False)
|
||||
fake_mac = 'aa:bb:cc:00:11:22'
|
||||
fake_ifaces = {
|
||||
netifaces.AF_LINK: [{'addr': fake_mac}]
|
||||
}
|
||||
calls = {
|
||||
'device_exists': [mock.call('bridge')],
|
||||
'_execute': [
|
||||
mock.call('brctl', 'addif', 'bridge', 'eth0',
|
||||
run_as_root=True, check_exit_code=False),
|
||||
mock.call('ip', 'link', 'set', 'bridge', 'address', fake_mac,
|
||||
run_as_root=True),
|
||||
mock.call('ip', 'link', 'set', 'eth0', 'up',
|
||||
run_as_root=True, check_exit_code=False),
|
||||
mock.call('ip', 'route', 'show', 'dev', 'eth0'),
|
||||
|
@ -1141,12 +1151,15 @@ class LinuxNetworkTestCase(test.NoDBTestCase):
|
|||
}
|
||||
with contextlib.nested(
|
||||
mock.patch.object(linux_net, 'device_exists', return_value=True),
|
||||
mock.patch.object(linux_net, '_execute', return_value=('', ''))
|
||||
) as (device_exists, _execute):
|
||||
mock.patch.object(linux_net, '_execute', return_value=('', '')),
|
||||
mock.patch.object(netifaces, 'ifaddresses')
|
||||
) as (device_exists, _execute, ifaddresses):
|
||||
ifaddresses.return_value = fake_ifaces
|
||||
driver = linux_net.LinuxBridgeInterfaceDriver()
|
||||
driver.ensure_bridge('bridge', 'eth0')
|
||||
device_exists.assert_has_calls(calls['device_exists'])
|
||||
_execute.assert_has_calls(calls['_execute'])
|
||||
ifaddresses.assert_called_once_with('eth0')
|
||||
|
||||
def test_ensure_bridge_brclt_addif_exception(self):
|
||||
def fake_execute(*cmd, **kwargs):
|
||||
|
|
Loading…
Reference in New Issue