Migration scenario, SR-IOV vif contains source physical ports
This is not a bug, this is related to future work to support migration for SR-IOV VMs. In migration scenarios, SR-IOV plug mechanism receives vif and it proceeds to create vNIC. This fails due to physical ports mismatch. As there are no physical ports matching with location codes in incoming vif, no backing device could be created. This is due to the fact that rebuild logic in nova compute, retrieves vif details from nova instance and feeds it to plug mechanism. Though neutron SR-IOV mechanism driver provides new and valid physical ports corresponding to destination host, it is ignored. A fix is needed in SR-IOV plug mechanism to retrieve appropriate SR_IOV physical ports that corresponds to related physical network (from related neutron network) and consume. There are two parts to this fix. One is related to physical_network. If there are no physical network in incoming vif detail, it is retreived using network id. Refer to https://bugs.launchpad.net/networking-powervm/+bug/1651129 for a fix on networking-powervm to avoid this moving forward. Second part is to retrieve physical ports from the environment using physical_network against port label attribute. Change-Id: Ic511314095472da21c3a5588d77955c939b7e0f1
This commit is contained in:
parent
eedae5b0d4
commit
ef98898379
@ -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)
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user