Merge "Allow the other nic to allocate VMs post PCI-PT VM creation." into stable/newton

This commit is contained in:
Jenkins 2017-03-11 02:19:49 +00:00 committed by Gerrit Code Review
commit 8cbcd74336
3 changed files with 126 additions and 6 deletions

View File

@ -62,6 +62,10 @@ class PciOsWrapper(object):
vf_list.append((pci_slot, vf_index))
return vf_list
@classmethod
def pf_device_exists(cls, dev_name):
return os.path.isdir(cls.DEVICE_PATH % dev_name)
@classmethod
def is_assigned_vf(cls, dev_name, vf_index, ip_link_show_output):
"""Check if VF is assigned.
@ -75,12 +79,19 @@ class PciOsWrapper(object):
@param vf_index: vf index
@param ip_link_show_output: 'ip link show' output
"""
if not cls.pf_device_exists(dev_name):
# If the root PCI path does not exist, then the VF cannot
# actually have been allocated and there is no way we can
# manage it.
return False
path = cls.PCI_PATH % (dev_name, vf_index)
try:
ifname_list = os.listdir(path)
except OSError:
# PCI_PATH does not exist means that the DIRECT VF assigend
# PCI_PATH does not exist means that the DIRECT VF assigned
return True
# Note(moshele) kernel < 3.13 doesn't create symbolic link
@ -351,6 +362,26 @@ class ESwitchManager(object):
embedded_switch.set_device_spoofcheck(pci_slot,
enabled)
def _process_emb_switch_map(self, phys_net, dev_name, exclude_devices):
"""Process emb_switch_map
@param phys_net: physical network
@param dev_name: device name
@param exclude_devices: PCI devices to ignore.
"""
emb_switches = self.emb_switches_map.get(phys_net, [])
for switch in emb_switches:
if switch.dev_name == dev_name:
if not PciOsWrapper.pf_device_exists(dev_name):
# If the device is given to the VM as PCI-PT
# then delete the respective emb_switch from map
self.emb_switches_map.get(phys_net).remove(switch)
return
# We don't know about this device at the moment, so add to the map.
if PciOsWrapper.pf_device_exists(dev_name):
self._create_emb_switch(phys_net, dev_name,
exclude_devices.get(dev_name, set()))
def discover_devices(self, device_mappings, exclude_devices):
"""Discover which Virtual functions to manage.
@ -362,8 +393,8 @@ class ESwitchManager(object):
exclude_devices = {}
for phys_net, dev_names in six.iteritems(device_mappings):
for dev_name in dev_names:
self._create_emb_switch(phys_net, dev_name,
exclude_devices.get(dev_name, set()))
self._process_emb_switch_map(phys_net, dev_name,
exclude_devices)
def _create_emb_switch(self, phys_net, dev_name, exclude_devices):
embedded_switch = EmbSwitch(phys_net, dev_name, exclude_devices)

View File

@ -113,6 +113,8 @@ class SriovNicSwitchAgent(object):
self.polling_interval = polling_interval
self.network_ports = collections.defaultdict(list)
self.conf = cfg.CONF
self.device_mappings = physical_devices_mappings
self.exclude_devices = exclude_devices
self.setup_eswitch_mgr(physical_devices_mappings,
exclude_devices)
@ -376,6 +378,8 @@ class SriovNicSwitchAgent(object):
updated_devices_copy = self.updated_devices
self.updated_devices = set()
try:
self.eswitch_mgr.discover_devices(self.device_mappings,
self.exclude_devices)
device_info = self.scan_devices(devices, updated_devices_copy)
if self._device_info_has_changes(device_info):
LOG.debug("Agent loop found changes! %s", device_info)

View File

@ -41,6 +41,9 @@ class TestCreateESwitchManager(base.BaseTestCase):
"eswitch_manager.PciOsWrapper.scan_vf_devices",
side_effect=exc.InvalidDeviceError(
dev_name="p6p1", reason="device" " not found")),\
mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
"eswitch_manager.PciOsWrapper.pf_device_exists",
return_value=True), \
mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
"eswitch_manager.PciOsWrapper.is_assigned_vf",
return_value=True):
@ -55,6 +58,9 @@ class TestCreateESwitchManager(base.BaseTestCase):
with mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
"eswitch_manager.PciOsWrapper.scan_vf_devices",
return_value=self.SCANNED_DEVICES),\
mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
"eswitch_manager.PciOsWrapper.pf_device_exists",
return_value=True), \
mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
"eswitch_manager.PciOsWrapper.is_assigned_vf",
return_value=True):
@ -91,11 +97,36 @@ class TestESwitchManagerApi(base.BaseTestCase):
with mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
"eswitch_manager.PciOsWrapper.scan_vf_devices",
return_value=self.SCANNED_DEVICES), \
mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
"eswitch_manager.PciOsWrapper.pf_device_exists",
return_value=True), \
mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
"eswitch_manager.PciOsWrapper.is_assigned_vf",
return_value=True):
eswitch_mgr.discover_devices(device_mappings, None)
def test_discover_devices_with_device(self):
device_mappings = {'physnet1': ['p6p1', 'p6p2']}
with mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
"eswitch_manager.PciOsWrapper.pf_device_exists",
return_value=True), \
mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
"eswitch_manager.ESwitchManager._create_emb_switch",
) as emb_switch:
self.eswitch_mgr.discover_devices(device_mappings, None)
self.assertTrue(emb_switch.called)
def test_discover_devices_without_device(self):
device_mappings = {'physnet1': ['p6p1', 'p6p2']}
with mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
"eswitch_manager.PciOsWrapper.pf_device_exists",
return_value=False), \
mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
"eswitch_manager.ESwitchManager._create_emb_switch",
) as emb_switch:
self.eswitch_mgr.discover_devices(device_mappings, None)
self.assertFalse(emb_switch.called)
def test_get_assigned_devices_info(self):
with mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
"eswitch_manager.EmbSwitch.get_assigned_devices_info",
@ -248,6 +279,36 @@ class TestESwitchManagerApi(base.BaseTestCase):
'device_mac': self.WRONG_MAC})
self.assertFalse(result)
def test_process_emb_switch_without_device(self):
device_mappings = {'physnet1': ['p6p1', 'p6p2']}
phys_net = 'physnet1'
dev_name = 'p6p1'
self._set_eswitch_manager(self.eswitch_mgr, device_mappings)
with mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
"eswitch_manager.PciOsWrapper.pf_device_exists",
return_value=False), \
mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
"eswitch_manager.ESwitchManager._create_emb_switch",
) as emb_switch:
self.eswitch_mgr._process_emb_switch_map(phys_net,
dev_name, {})
self.assertFalse(emb_switch.called)
def test_process_emb_switch_with_device(self):
device_mappings = {'physnet1': ['p6p1', 'p6p2']}
phys_net = 'physnet1'
dev_name = 'p6p3'
self._set_eswitch_manager(self.eswitch_mgr, device_mappings)
with mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
"eswitch_manager.PciOsWrapper.pf_device_exists",
return_value=True), \
mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
"eswitch_manager.ESwitchManager._create_emb_switch",
) as emb_switch:
self.eswitch_mgr._process_emb_switch_map(phys_net,
dev_name, {})
self.assertTrue(emb_switch.called)
def _test_clear_rate(self, rate_type, pci_slot, passed, mac_address):
with mock.patch('neutron.plugins.ml2.drivers.mech_sriov.agent.'
'eswitch_manager.EmbSwitch.set_device_rate') \
@ -257,7 +318,10 @@ class TestESwitchManagerApi(base.BaseTestCase):
return_value=mac_address), \
mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
"pci_lib.PciDeviceIPWrapper.link_show",
return_value=''):
return_value=''), \
mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
"eswitch_manager.PciOsWrapper.pf_device_exists",
return_value=True):
self.eswitch_mgr.clear_rate(pci_slot, rate_type)
if passed:
set_rate_mock.assert_called_once_with(pci_slot, rate_type, 0)
@ -557,9 +621,13 @@ class TestPciOsWrapper(base.BaseTestCase):
@mock.patch("os.listdir", side_effect=OSError())
def test_is_assigned_vf_true(self, *args):
self.assertTrue(esm.PciOsWrapper.is_assigned_vf(
self.DEV_NAME, self.VF_INDEX, ''))
with mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
"eswitch_manager.PciOsWrapper.pf_device_exists",
return_value=True):
self.assertTrue(esm.PciOsWrapper.is_assigned_vf(
self.DEV_NAME, self.VF_INDEX, ''))
@mock.patch("os.path.exists", return_value=True)
@mock.patch("os.listdir", return_value=[DEV_NAME, "eth1"])
@mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent.pci_lib."
"PciDeviceIPWrapper.is_macvtap_assigned", return_value=False)
@ -567,6 +635,7 @@ class TestPciOsWrapper(base.BaseTestCase):
self.assertFalse(esm.PciOsWrapper.is_assigned_vf(
self.DEV_NAME, self.VF_INDEX, ''))
@mock.patch("os.path.exists", return_value=True)
@mock.patch("os.listdir", return_value=["eth0", "eth1"])
@mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent.pci_lib."
"PciDeviceIPWrapper.is_macvtap_assigned", return_value=True)
@ -575,6 +644,7 @@ class TestPciOsWrapper(base.BaseTestCase):
esm.PciOsWrapper.is_assigned_vf(self.DEV_NAME, self.VF_INDEX, '')
mock_is_macvtap_assigned.called_with(self.VF_INDEX, "eth0")
@mock.patch("os.path.exists", return_value=True)
@mock.patch("os.listdir", side_effect=OSError())
@mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent.pci_lib."
"PciDeviceIPWrapper.is_macvtap_assigned")
@ -582,3 +652,18 @@ class TestPciOsWrapper(base.BaseTestCase):
self, mock_is_macvtap_assigned, *args):
esm.PciOsWrapper.is_assigned_vf(self.DEV_NAME, self.VF_INDEX, '')
self.assertFalse(mock_is_macvtap_assigned.called)
@mock.patch("os.path.exists", return_value=False)
@mock.patch("os.listdir", return_value=["eth0", "eth1"])
def test_is_assigned_vf_pf_disappeared(self, list_dir_mock, *args):
self.assertFalse(esm.PciOsWrapper.is_assigned_vf(
self.DEV_NAME, self.VF_INDEX, ''))
self.assertFalse(list_dir_mock.called)
def test_pf_device_exists_with_no_dir(self):
with mock.patch("os.path.isdir", return_value=False):
self.assertFalse(esm.PciOsWrapper.pf_device_exists('p6p1'))
def test_pf_device_exists_with_dir(self):
with mock.patch("os.path.isdir", return_value=True):
self.assertTrue(esm.PciOsWrapper.pf_device_exists('p6p1'))