diff --git a/nova/tests/unit/virt/libvirt/test_vif.py b/nova/tests/unit/virt/libvirt/test_vif.py index 841a3de3f5c8..90a91f49a74e 100644 --- a/nova/tests/unit/virt/libvirt/test_vif.py +++ b/nova/tests/unit/virt/libvirt/test_vif.py @@ -972,11 +972,14 @@ class LibvirtVifTestCase(test.NoDBTestCase): @mock.patch.object(pci_utils, 'get_vf_num_by_pci_address', return_value=1) @mock.patch('nova.privsep.linux_net.set_device_macaddr') @mock.patch('nova.privsep.linux_net.set_device_macaddr_and_vlan') - def test_unplug_hw_veb(self, mock_set_macaddr_and_vlan, - mock_set_macaddr, mock_get_vf_num, - mock_get_ifname): - d = vif.LibvirtGenericVIFDriver() + def _test_hw_veb_op(self, op, vlan, mock_set_macaddr_and_vlan, + mock_set_macaddr, mock_get_vf_num, + mock_get_ifname): mock_get_ifname.side_effect = ['eth1', 'eth13'] + vlan_id = int(vlan) + port_state = 'up' if vlan_id > 0 else 'down' + mac = ('00:00:00:00:00:00' if op.__name__ == 'unplug' + else self.vif_hw_veb_macvtap['address']) calls = { 'get_ifname': [mock.call(self.vif_hw_veb_macvtap['profile']['pci_slot'], @@ -984,17 +987,24 @@ class LibvirtVifTestCase(test.NoDBTestCase): mock.call(self.vif_hw_veb_macvtap['profile']['pci_slot'])], 'get_vf_num': [mock.call(self.vif_hw_veb_macvtap['profile']['pci_slot'])], - 'set_macaddr': [mock.call( - 'eth13', '00:00:00:00:00:00', port_state='down')] + 'set_macaddr': [mock.call('eth13', mac, port_state=port_state)] } - - d.unplug(self.instance, self.vif_hw_veb_macvtap) - + 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_set_macaddr.assert_has_calls(calls['set_macaddr']) mock_set_macaddr_and_vlan.assert_called_once_with( - 'eth1', 1, mock.ANY, 0) + 'eth1', 1, mock.ANY, vlan_id) + + def test_plug_hw_veb(self): + d = vif.LibvirtGenericVIFDriver() + details = self.vif_hw_veb_macvtap['details'] + vlan = details[network_model.VIF_DETAILS_VLAN] + self._test_hw_veb_op(d.plug, vlan) + + def test_unplug_hw_veb(self): + d = vif.LibvirtGenericVIFDriver() + self._test_hw_veb_op(d.unplug, 0) @mock.patch('nova.network.linux_net.set_vf_trusted') def test_plug_hw_veb_trusted(self, mset_vf_trusted): diff --git a/nova/virt/libvirt/vif.py b/nova/virt/libvirt/vif.py index 0c57fc2a5e49..d3a2a26dbab4 100644 --- a/nova/virt/libvirt/vif.py +++ b/nova/virt/libvirt/vif.py @@ -97,20 +97,20 @@ def is_vif_model_valid_for_virt(virt_type, vif_model): def set_vf_interface_vlan(pci_addr, mac_addr, vlan=0): + vlan_id = int(vlan) pf_ifname = pci_utils.get_ifname_by_pci_address(pci_addr, pf_interface=True) vf_ifname = pci_utils.get_ifname_by_pci_address(pci_addr) vf_num = pci_utils.get_vf_num_by_pci_address(pci_addr) nova.privsep.linux_net.set_device_macaddr_and_vlan( - pf_ifname, vf_num, mac_addr, vlan) + pf_ifname, vf_num, mac_addr, vlan_id) # 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=1415609 and should be removed - # once we bump the libvirt minimum to 3.2.0, as noted in - # https://bugzilla.redhat.com/show_bug.cgi?id=1372944 - port_state = 'up' if vlan > 0 else 'down' + # https://bugzilla.redhat.com/show_bug.cgi?id=1372944 + # once resolved it will be removed + port_state = 'up' if vlan_id > 0 else 'down' nova.privsep.linux_net.set_device_macaddr(vf_ifname, mac_addr, port_state=port_state) @@ -625,7 +625,20 @@ class LibvirtGenericVIFDriver(object): instance=instance) def plug_hw_veb(self, instance, vif): - if vif['vnic_type'] == network_model.VNIC_TYPE_DIRECT: + # TODO(adrianc): The piece of code for MACVTAP can be removed once: + # 1. neutron SR-IOV agent does not rely on the administrative mac + # as depicted in https://bugs.launchpad.net/neutron/+bug/1841067 + # 2. libvirt driver does not change mac address for macvtap VNICs + # or Alternatively does not rely on recreating libvirt's nodev + # name from the current mac address set on the netdevice. + # See: virt.libvrit.driver.LibvirtDriver._get_pcinet_info + if vif['vnic_type'] == network_model.VNIC_TYPE_MACVTAP: + set_vf_interface_vlan( + vif['profile']['pci_slot'], + mac_addr=vif['address'], + vlan=vif['details'][network_model.VIF_DETAILS_VLAN]) + + elif vif['vnic_type'] == network_model.VNIC_TYPE_DIRECT: trusted = strutils.bool_from_string( vif['profile'].get('trusted', "False")) if trusted: