diff --git a/nova/network/linux_net.py b/nova/network/linux_net.py index 98e26474d133..d220df647d33 100644 --- a/nova/network/linux_net.py +++ b/nova/network/linux_net.py @@ -1382,9 +1382,8 @@ class LinuxBridgeInterfaceDriver(LinuxNetInterfaceDriver): # (danwent) the bridge will inherit this address, so we want to # make sure it is the value set from the NetworkManager if mac_address: - _execute('ip', 'link', 'set', interface, 'address', - mac_address, run_as_root=True, - check_exit_code=[0, 2, 254]) + nova.privsep.linux_net.set_device_macaddr( + interface, mac_address) nova.privsep.linux_net.set_device_enabled(interface) # NOTE(vish): set mtu every time to ensure that changes to mtu get # propagated @@ -1449,8 +1448,8 @@ class LinuxBridgeInterfaceDriver(LinuxNetInterfaceDriver): 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) + nova.privsep.linux_net.set_device_macaddr( + bridge, interface_mac) nova.privsep.linux_net.set_device_enabled(interface) @@ -1665,8 +1664,8 @@ class LinuxOVSInterfaceDriver(LinuxNetInterfaceDriver): 'external-ids:iface-status=active', '--', 'set', 'Interface', dev, 'external-ids:attached-mac=%s' % mac_address]) - _execute('ip', 'link', 'set', dev, 'address', mac_address, - run_as_root=True) + nova.privsep.linux_net.set_device_macaddr( + dev, mac_address) nova.privsep.linux_net.set_device_mtu(dev, network.get('mtu')) nova.privsep.linux_net.set_device_enabled(dev) if not gateway: diff --git a/nova/network/linux_utils.py b/nova/network/linux_utils.py index 96d6710a18ef..3c0c5a40372b 100644 --- a/nova/network/linux_utils.py +++ b/nova/network/linux_utils.py @@ -47,8 +47,7 @@ def create_tap_dev(dev, mac_address=None, multiqueue=False): # Second option: tunctl utils.execute('tunctl', '-b', '-t', dev, run_as_root=True) if mac_address: - utils.execute('ip', 'link', 'set', dev, 'address', mac_address, - run_as_root=True, check_exit_code=[0, 2, 254]) + nova.privsep.linux_net.set_device_macaddr(dev, mac_address) nova.privsep.linux_net.set_device_enabled(dev) @@ -59,20 +58,16 @@ def set_vf_interface_vlan(pci_addr, mac_addr, vlan=0): vf_num = pci_utils.get_vf_num_by_pci_address(pci_addr) # Set the VF's mac address and vlan - exit_code = [0, 2, 254] - port_state = 'up' if vlan > 0 else 'down' utils.execute('ip', 'link', 'set', pf_ifname, 'vf', vf_num, 'mac', mac_addr, 'vlan', vlan, run_as_root=True, - check_exit_code=exit_code) + check_exit_code=[0, 2, 254]) # Bring up/down the VF's interface # TODO(edand): The mac is assigned as a workaround for the following issue # https://bugzilla.redhat.com/show_bug.cgi?id=1372944 # once resolved it will be removed - utils.execute('ip', 'link', 'set', vf_ifname, - 'address', mac_addr, - port_state, - run_as_root=True, - check_exit_code=exit_code) + port_state = 'up' if vlan > 0 else 'down' + nova.privsep.linux_net.set_device_macaddr(vf_ifname, mac_addr, + port_state=port_state) diff --git a/nova/privsep/linux_net.py b/nova/privsep/linux_net.py index 2e8806b0460f..32b8686447f2 100644 --- a/nova/privsep/linux_net.py +++ b/nova/privsep/linux_net.py @@ -91,6 +91,16 @@ def set_device_enabled(dev): check_exit_code=[0, 2, 254]) +@nova.privsep.sys_admin_pctxt.entrypoint +def set_device_macaddr(dev, mac_addr, port_state=None): + if port_state: + processutils.execute('ip', 'link', 'set', dev, 'address', mac_addr, + port_state, check_exit_code=[0, 2, 254]) + else: + processutils.execute('ip', 'link', 'set', dev, 'address', mac_addr, + check_exit_code=[0, 2, 254]) + + @nova.privsep.sys_admin_pctxt.entrypoint def create_veth_pair(dev1_name, dev2_name, mtu=None): """Create a pair of veth devices with the specified names, diff --git a/nova/tests/functional/api_sample_tests/api_sample_base.py b/nova/tests/functional/api_sample_tests/api_sample_base.py index 43d3b9fe9f05..cdedd7425f90 100644 --- a/nova/tests/functional/api_sample_tests/api_sample_base.py +++ b/nova/tests/functional/api_sample_tests/api_sample_base.py @@ -126,6 +126,7 @@ class ApiSampleTestBaseV21(testscenarios.WithScenarios, self.stub_out('nova.privsep.linux_net.add_bridge', fake_noop) self.stub_out('nova.privsep.linux_net.set_device_mtu', fake_noop) self.stub_out('nova.privsep.linux_net.set_device_enabled', fake_noop) + self.stub_out('nova.privsep.linux_net.set_device_macaddr', fake_noop) def _setup_services(self): pass diff --git a/nova/tests/unit/network/test_linux_net.py b/nova/tests/unit/network/test_linux_net.py index 5158d6df2314..9cf534d3dcfc 100644 --- a/nova/tests/unit/network/test_linux_net.py +++ b/nova/tests/unit/network/test_linux_net.py @@ -1131,8 +1131,6 @@ class LinuxNetworkTestCase(test.NoDBTestCase): '_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', 'route', 'show', 'dev', 'eth0'), mock.call('ip', 'addr', 'show', 'dev', 'eth0', 'scope', 'global'), @@ -1142,9 +1140,11 @@ class LinuxNetworkTestCase(test.NoDBTestCase): mock.patch('nova.privsep.linux_net.device_exists', return_value=True), mock.patch('nova.privsep.linux_net.set_device_enabled'), + mock.patch('nova.privsep.linux_net.set_device_macaddr'), mock.patch.object(linux_net, '_execute', return_value=('', '')), mock.patch.object(netifaces, 'ifaddresses') - ) as (device_exists, device_enabled, _execute, ifaddresses): + ) as (device_exists, device_enabled, set_device_macaddr, + _execute, ifaddresses): ifaddresses.return_value = fake_ifaces driver = linux_net.LinuxBridgeInterfaceDriver() driver.ensure_bridge('bridge', 'eth0') @@ -1152,6 +1152,7 @@ class LinuxNetworkTestCase(test.NoDBTestCase): _execute.assert_has_calls(calls['_execute']) ifaddresses.assert_called_once_with('eth0') device_enabled.assert_called_once_with('eth0') + set_device_macaddr.assert_called_once_with('bridge', fake_mac) def test_ensure_bridge_brclt_addif_exception(self): def fake_execute(*cmd, **kwargs): @@ -1285,8 +1286,10 @@ class LinuxNetworkTestCase(test.NoDBTestCase): @mock.patch('nova.privsep.linux_net.device_exists', return_value=False) @mock.patch('nova.privsep.linux_net.set_device_mtu') @mock.patch('nova.privsep.linux_net.set_device_enabled') - def test_ensure_vlan(self, mock_set_enabled, mock_set_device_mtu, - mock_device_exists, mock_execute): + @mock.patch('nova.privsep.linux_net.set_device_macaddr') + def test_ensure_vlan(self, mock_set_macaddr, mock_set_enabled, + mock_set_device_mtu, mock_device_exists, + mock_execute): interface = linux_net.LinuxBridgeInterfaceDriver.ensure_vlan( 1, 'eth0', 'MAC', 'MTU', "vlan_name") self.assertEqual("vlan_name", interface) @@ -1295,13 +1298,12 @@ class LinuxNetworkTestCase(test.NoDBTestCase): expected_execute_args = [ mock.call('ip', 'link', 'add', 'link', 'eth0', 'name', 'vlan_name', 'type', 'vlan', 'id', 1, check_exit_code=[0, 2, 254], - run_as_root=True), - mock.call('ip', 'link', 'set', 'vlan_name', 'address', 'MAC', - check_exit_code=[0, 2, 254], run_as_root=True) + run_as_root=True) ] self.assertEqual(expected_execute_args, mock_execute.mock_calls) mock_set_device_mtu.assert_called_once_with('vlan_name', 'MTU') mock_set_enabled.assert_called_once_with('vlan_name') + mock_set_macaddr.assert_called_once_with('vlan_name', 'MAC') @mock.patch.object(linux_net, '_execute') @mock.patch('nova.privsep.linux_net.device_exists', return_value=True) diff --git a/nova/tests/unit/network/test_manager.py b/nova/tests/unit/network/test_manager.py index 2c821b3fff82..1c3be5756115 100644 --- a/nova/tests/unit/network/test_manager.py +++ b/nova/tests/unit/network/test_manager.py @@ -2839,8 +2839,9 @@ class AllocateTestCase(test.TestCase): @mock.patch('nova.privsep.linux_net.add_bridge', return_value=('', '')) @mock.patch('nova.privsep.linux_net.set_device_mtu') @mock.patch('nova.privsep.linux_net.set_device_enabled') - def test_allocate_for_instance(self, mock_set_enabeld, mock_set_mtu, - mock_add_bridge): + @mock.patch('nova.privsep.linux_net.set_device_macaddr') + def test_allocate_for_instance(self, mock_set_macaddr, mock_set_enabled, + mock_set_mtu, mock_add_bridge): address = "10.10.10.10" self.flags(auto_assign_floating_ip=True) @@ -2907,7 +2908,9 @@ class AllocateTestCase(test.TestCase): @mock.patch('nova.privsep.linux_net.add_bridge', return_value=('', '')) @mock.patch('nova.privsep.linux_net.set_device_mtu') @mock.patch('nova.privsep.linux_net.set_device_enabled') - def test_allocate_for_instance_with_mac(self, mock_enabled, mock_set_mtu, + @mock.patch('nova.privsep.linux_net.set_device_macaddr') + def test_allocate_for_instance_with_mac(self, mock_set_addr, + mock_enabled, mock_set_mtu, mock_add_bridge): available_macs = set(['ca:fe:de:ad:be:ef']) inst = db.instance_create(self.context, {'host': HOST, diff --git a/nova/tests/unit/network/test_utils.py b/nova/tests/unit/network/test_utils.py index d5bc97cf31b0..4baacd0f8985 100644 --- a/nova/tests/unit/network/test_utils.py +++ b/nova/tests/unit/network/test_utils.py @@ -44,17 +44,18 @@ class NetUtilsTestCase(test.NoDBTestCase): @mock.patch('nova.utils.execute') @mock.patch('nova.privsep.linux_net.set_device_enabled') - def test_create_tap_dev_mac(self, mock_enabled, mock_execute): + @mock.patch('nova.privsep.linux_net.set_device_macaddr') + def test_create_tap_dev_mac(self, mock_set_macaddr, mock_enabled, + mock_execute): net_utils.create_tap_dev('tap42', '00:11:22:33:44:55') mock_execute.assert_has_calls([ mock.call('ip', 'tuntap', 'add', 'tap42', 'mode', 'tap', - run_as_root=True, check_exit_code=[0, 2, 254]), - mock.call('ip', 'link', 'set', 'tap42', - 'address', '00:11:22:33:44:55', run_as_root=True, check_exit_code=[0, 2, 254]) ]) mock_enabled.assert_called_once_with('tap42') + mock_set_macaddr.assert_has_calls([ + mock.call('tap42', '00:11:22:33:44:55')]) @mock.patch('nova.utils.execute') @mock.patch('nova.privsep.linux_net.set_device_enabled') diff --git a/nova/tests/unit/virt/libvirt/test_vif.py b/nova/tests/unit/virt/libvirt/test_vif.py index 2e9c9e5dcb06..4b1fc2d46d1b 100644 --- a/nova/tests/unit/virt/libvirt/test_vif.py +++ b/nova/tests/unit/virt/libvirt/test_vif.py @@ -950,8 +950,9 @@ class LibvirtVifTestCase(test.NoDBTestCase): @mock.patch.object(utils, 'execute') @mock.patch.object(pci_utils, 'get_ifname_by_pci_address') @mock.patch.object(pci_utils, 'get_vf_num_by_pci_address', return_value=1) - def _test_hw_veb_op(self, op, vlan, mock_get_vf_num, mock_get_ifname, - mock_execute): + @mock.patch('nova.privsep.linux_net.set_device_macaddr') + def _test_hw_veb_op(self, op, vlan, mock_set_macaddr, mock_get_vf_num, + mock_get_ifname, mock_execute): mock_get_ifname.side_effect = ['eth1', 'eth13'] exit_code = [0, 2, 254] port_state = 'up' if vlan > 0 else 'down' @@ -967,18 +968,16 @@ class LibvirtVifTestCase(test.NoDBTestCase): self.vif_hw_veb_macvtap['address'], 'vlan', vlan, run_as_root=True, - check_exit_code=exit_code), - mock.call('ip', 'link', 'set', - 'eth13', 'address', - self.vif_hw_veb_macvtap['address'], - port_state, - run_as_root=True, - check_exit_code=exit_code)] + check_exit_code=exit_code)], + 'set_macaddr': [mock.call('eth13', + self.vif_hw_veb_macvtap['address'], + port_state=port_state)] } op(self.instance, self.vif_hw_veb_macvtap) mock_get_ifname.assert_has_calls(calls['get_ifname']) mock_get_vf_num.assert_has_calls(calls['get_vf_num']) mock_execute.assert_has_calls(calls['execute']) + mock_set_macaddr.assert_has_calls(calls['set_macaddr']) def test_plug_hw_veb(self): d = vif.LibvirtGenericVIFDriver() diff --git a/nova/tests/unit/virt/xenapi/test_xenapi.py b/nova/tests/unit/virt/xenapi/test_xenapi.py index 98eb3289d50d..8043b0c45b93 100644 --- a/nova/tests/unit/virt/xenapi/test_xenapi.py +++ b/nova/tests/unit/virt/xenapi/test_xenapi.py @@ -1138,8 +1138,10 @@ class XenAPIVMTestCase(stubs.XenAPITestBase, @mock.patch('nova.privsep.linux_net.add_bridge', return_value=('', '')) @mock.patch('nova.privsep.linux_net.set_device_mtu') @mock.patch('nova.privsep.linux_net.set_device_enabled') - def test_spawn_vlanmanager(self, mock_set_enabled, mock_set_mtu, - mock_add_bridge, mock_create_vifs): + @mock.patch('nova.privsep.linux_net.set_device_macaddr') + def test_spawn_vlanmanager(self, mock_set_macaddr, mock_set_enabled, + mock_set_mtu, mock_add_bridge, + mock_create_vifs): self.flags(network_manager='nova.network.manager.VlanManager', vlan_interface='fake0') # Reset network table