diff --git a/nova_powervm/tests/virt/powervm/test_vif.py b/nova_powervm/tests/virt/powervm/test_vif.py index ffc04ad5..10f304e4 100644 --- a/nova_powervm/tests/virt/powervm/test_vif.py +++ b/nova_powervm/tests/virt/powervm/test_vif.py @@ -18,6 +18,7 @@ import mock from nova import exception from nova.network import model +from nova.network.neutronv2 import api as netapi from nova import test from oslo_config import cfg from pypowervm import exceptions as pvm_ex @@ -39,6 +40,16 @@ def cna(mac): return nic +class FakeNetworkAPI(object): + def __init__(self, physnet): + self.physical_network = physnet + + def get(self, context, netid): + physnet = mock.MagicMock() + physnet.physical_network = self.physical_network + return physnet + + class TestVifFunctions(test.TestCase): def setUp(self): @@ -312,19 +323,115 @@ class TestVifSriovDriver(test.TestCase): self.inst = mock.MagicMock() self.drv = vif.PvmVnicSriovVifDriver(self.adpt, 'host_uuid', self.inst) - def test_plug_no_pports(self): + @mock.patch('pypowervm.wrappers.managed_system.System.get') + def test_plug_no_pports(self, mock_sysget): """Raise when plug is called with a network with no physical ports.""" + sriov_adaps = [ + mock.Mock(phys_ports=[ + mock.Mock(loc_code='loc1', label='foo'), + mock.Mock(loc_code='loc2', label='')]), + mock.Mock(phys_ports=[ + mock.Mock(loc_code='loc3', label='bar'), + mock.Mock(loc_code='loc4', label='foo')])] + sys = mock.Mock(asio_config=mock.Mock(sriov_adapters=sriov_adaps)) + mock_sysget.return_value = [sys] self.assertRaises(exception.VirtualInterfacePlugException, self.drv.plug, FakeDirectVif('net2', pports=[]), 1) + @mock.patch('pypowervm.wrappers.iocard.VNIC.bld') + @mock.patch('nova_powervm.virt.powervm.vm.get_pvm_uuid') + @mock.patch('pypowervm.tasks.sriov.set_vnic_back_devs') + @mock.patch('pypowervm.wrappers.managed_system.System.get') + def test_plug_no_physnet(self, mock_sysget, mock_back_devs, mock_pvm_uuid, + mock_vnic_bld): + slot = 10 + pports = ['port1', 'port2'] + sriov_adaps = [ + mock.Mock(phys_ports=[ + mock.Mock(loc_code='port11', label='default'), + mock.Mock(loc_code='port3', label='data1')]), + mock.Mock(phys_ports=[ + mock.Mock(loc_code='port4', label='data2'), + mock.Mock(loc_code='port22', label='default')])] + sys = mock.Mock(asio_config=mock.Mock(sriov_adapters=sriov_adaps)) + mock_sysget.return_value = [sys] + netapi.API = mock.Mock(return_value=FakeNetworkAPI('default')) + self.drv.plug(FakeDirectVif('', pports=pports), slot) + # Ensure back devs are created with pports from sriov_adaps and + # not with what pports passed into plug method + mock_back_devs.assert_called_once_with( + mock_vnic_bld.return_value, ['port11', 'port22'], redundancy=3, + capacity=None, check_port_status=True, + sys_w=sys) + + @mock.patch('pypowervm.wrappers.iocard.VNIC.bld') + @mock.patch('nova_powervm.virt.powervm.vm.get_pvm_uuid') + @mock.patch('pypowervm.tasks.sriov.set_vnic_back_devs') + @mock.patch('pypowervm.wrappers.managed_system.System.get') + def test_plug_no_matching_pports(self, mock_sysget, mock_back_devs, + mock_pvm_uuid, mock_vnic_bld): + slot = 10 + pports = ['port1', 'port2'] + sriov_adaps = [ + mock.Mock(phys_ports=[ + mock.Mock(loc_code='port1', label='data1'), + mock.Mock(loc_code='port3', label='data1')]), + mock.Mock(phys_ports=[ + mock.Mock(loc_code='port4', label='data2'), + mock.Mock(loc_code='port2', label='data2')])] + sys = mock.Mock(asio_config=mock.Mock(sriov_adapters=sriov_adaps)) + mock_sysget.return_value = [sys] + netapi.API = mock.Mock(return_value=FakeNetworkAPI('default')) + # Ensure Plug exception is raised when there are no matching pports + # for physical network of corresponding neutron network + self.assertRaises(exception.VirtualInterfacePlugException, + self.drv.plug, + FakeDirectVif('default', pports=pports), slot) + + @mock.patch('pypowervm.wrappers.iocard.VNIC.bld') + @mock.patch('nova_powervm.virt.powervm.vm.get_pvm_uuid') + @mock.patch('pypowervm.tasks.sriov.set_vnic_back_devs') + @mock.patch('pypowervm.wrappers.managed_system.System.get') + def test_plug_bad_pports(self, mock_sysget, mock_back_devs, mock_pvm_uuid, + mock_vnic_bld): + slot = 10 + pports = ['bad1', 'bad2'] + sriov_adaps = [ + mock.Mock(phys_ports=[ + mock.Mock(loc_code='port1', label='default'), + mock.Mock(loc_code='port3', label='data1')]), + mock.Mock(phys_ports=[ + mock.Mock(loc_code='port4', label='data2'), + mock.Mock(loc_code='port2', label='default')])] + sys = mock.Mock(asio_config=mock.Mock(sriov_adapters=sriov_adaps)) + mock_sysget.return_value = [sys] + netapi.API = mock.Mock(return_value=FakeNetworkAPI('default')) + self.drv.plug(FakeDirectVif('', pports=pports), slot) + # Ensure back devs are created with correct pports belonging to same + # physical network corresonding to neutron network + mock_back_devs.assert_called_once_with( + mock_vnic_bld.return_value, ['port1', 'port2'], redundancy=3, + capacity=None, check_port_status=True, + sys_w=sys) + + @mock.patch('pypowervm.wrappers.managed_system.System.get') @mock.patch('pypowervm.util.sanitize_mac_for_api') @mock.patch('pypowervm.wrappers.iocard.VNIC.bld') @mock.patch('pypowervm.tasks.sriov.set_vnic_back_devs') @mock.patch('nova_powervm.virt.powervm.vm.get_pvm_uuid') def test_plug(self, mock_pvm_uuid, mock_back_devs, mock_vnic_bld, - mock_san_mac): + mock_san_mac, mock_sysget): slot = 10 pports = ['port1', 'port2'] + sriov_adaps = [ + mock.Mock(phys_ports=[ + mock.Mock(loc_code='port1', label='default'), + mock.Mock(loc_code='port3', label='data1')]), + mock.Mock(phys_ports=[ + mock.Mock(loc_code='port4', label='data2'), + mock.Mock(loc_code='port2', label='default')])] + sys = mock.Mock(asio_config=mock.Mock(sriov_adapters=sriov_adaps)) + mock_sysget.return_value = [sys] self.drv.plug(FakeDirectVif('default', pports=pports), slot) mock_san_mac.assert_called_once_with('ab:ab:ab:ab:ab:ab') @@ -334,7 +441,8 @@ class TestVifSriovDriver(test.TestCase): allowed_macs='NONE') mock_back_devs.assert_called_once_with( mock_vnic_bld.return_value, ['port1', 'port2'], redundancy=3, - capacity=None, check_port_status=True) + capacity=None, check_port_status=True, + sys_w=sys) mock_pvm_uuid.assert_called_once_with(self.drv.instance) mock_vnic_bld.return_value.create.assert_called_once_with( parent_type=pvm_lpar.LPAR, parent_uuid=mock_pvm_uuid.return_value) @@ -353,7 +461,8 @@ class TestVifSriovDriver(test.TestCase): allowed_macs='NONE') mock_back_devs.assert_called_once_with( mock_vnic_bld.return_value, ['port1', 'port2'], - redundancy=3, capacity=0.08, check_port_status=True) + redundancy=3, capacity=0.08, check_port_status=True, + sys_w=sys) mock_pvm_uuid.assert_called_once_with(self.drv.instance) mock_vnic_bld.return_value.create.assert_called_once_with( parent_type=pvm_lpar.LPAR, parent_uuid=mock_pvm_uuid.return_value) diff --git a/nova_powervm/virt/powervm/vif.py b/nova_powervm/virt/powervm/vif.py index 6e032888..bf50f395 100644 --- a/nova_powervm/virt/powervm/vif.py +++ b/nova_powervm/virt/powervm/vif.py @@ -17,7 +17,9 @@ import abc import six +from nova import context as ctx from nova import exception +from nova import network as net_api from nova.network import linux_net from nova.network import model as network_model from nova import utils @@ -616,12 +618,30 @@ class PvmVnicSriovVifDriver(PvmVifDriver): return None physnet = vif.get_physical_network() + if not physnet: + # Get physnet from neutron network if not present in vif + # TODO(svenkat): This section of code will be eliminated in + # pike release. Design will be in place to fix any vif + # that has physical_network missing. The fix will be in + # compute startup code. + net_id = vif['network']['id'] + admin_context = ctx.get_admin_context() + napi = net_api.API() + network = napi.get(admin_context, net_id) + physnet = network.physical_network + LOG.debug("Plugging vNIC SR-IOV vif for physical network " "'%(physnet)s' into instance %(inst)s.", - {'physnet': physnet, 'inst': self.instance.name}) + {'physnet': physnet, 'inst': self.instance.name}, + instance=self.instance) + + # Get the msys + msys = pvm_ms.System.get(self.adapter)[0] + # Physical ports for the given port label + pports_w = sriovtask.find_pports_for_portlabel(physnet, self.adapter, + msys) + pports = [pport.loc_code for pport in pports_w] - # Physical ports for the given physical network - pports = vif['details']['physical_ports'] if not pports: raise exception.VirtualInterfacePlugException( _("Unable to find SR-IOV physical ports for physical " @@ -645,7 +665,8 @@ class PvmVnicSriovVifDriver(PvmVifDriver): allowed_vlans=pvm_util.VLANList.NONE, allowed_macs=pvm_util.MACList.NONE) - sriovtask.set_vnic_back_devs(vnic, pports, redundancy=redundancy, + sriovtask.set_vnic_back_devs(vnic, pports, sys_w=msys, + redundancy=redundancy, capacity=capacity, check_port_status=True) return vnic.create(parent_type=pvm_lpar.LPAR,