Merge "Reduce IP link show calls for SR-IOV scan loop"

This commit is contained in:
Jenkins 2017-01-06 17:54:03 +00:00 committed by Gerrit Code Review
commit 499f3c6d56
4 changed files with 56 additions and 40 deletions

View File

@ -63,7 +63,7 @@ class PciOsWrapper(object):
return vf_list
@classmethod
def is_assigned_vf(cls, dev_name, vf_index):
def is_assigned_vf(cls, dev_name, vf_index, ip_link_show_output):
"""Check if VF is assigned.
Checks if a given vf index of a given device name is assigned
@ -73,6 +73,7 @@ class PciOsWrapper(object):
Macvtap VF: macvtap@<vf interface> interface exists in ip link show
@param dev_name: pf network device name
@param vf_index: vf index
@param ip_link_show_output: 'ip link show' output
"""
path = cls.PCI_PATH % (dev_name, vf_index)
@ -86,7 +87,8 @@ class PciOsWrapper(object):
# for macvtap interface. Therefore we workaround it
# by parsing ip link show and checking if macvtap interface exists
for ifname in ifname_list:
if pci_lib.PciDeviceIPWrapper.is_macvtap_assigned(ifname):
if pci_lib.PciDeviceIPWrapper.is_macvtap_assigned(
ifname, ip_link_show_output):
return True
return False
@ -138,8 +140,9 @@ class EmbSwitch(object):
"""
vf_to_pci_slot_mapping = {}
assigned_devices_info = []
ls = self.pci_dev_wrapper.link_show()
for pci_slot, vf_index in self.pci_slot_map.items():
if not PciOsWrapper.is_assigned_vf(self.dev_name, vf_index):
if not PciOsWrapper.is_assigned_vf(self.dev_name, vf_index, ls):
continue
vf_to_pci_slot_mapping[vf_index] = pci_slot
if vf_to_pci_slot_mapping:
@ -230,7 +233,8 @@ class EmbSwitch(object):
vf_index = self.pci_slot_map.get(pci_slot)
mac = None
if vf_index is not None:
if PciOsWrapper.is_assigned_vf(self.dev_name, vf_index):
ls = pci_lib.PciDeviceIPWrapper.link_show()
if PciOsWrapper.is_assigned_vf(self.dev_name, vf_index, ls):
macs = self.pci_dev_wrapper.get_assigned_macs([vf_index])
mac = macs.get(vf_index)
return mac

View File

@ -186,22 +186,26 @@ class PciDeviceIPWrapper(ip_lib.IPWrapper):
return vf_details
@classmethod
def is_macvtap_assigned(cls, ifname):
def link_show(cls):
try:
out = cls._execute([], "link", ("show", ), run_as_root=True)
except Exception as e:
LOG.error(_LE("Failed executing ip command: %s"), e)
raise exc.IpCommandError(reason=e)
return out
@classmethod
def is_macvtap_assigned(cls, ifname, ip_link_show_output):
"""Check if vf has macvtap interface assigned
Parses the output of ip link show command and checks
if macvtap[0-9]+@<vf interface> regex matches the
output.
@param ifname: vf interface name
@param ip_link_show_output: 'ip link show' result to parse
@return: True on match otherwise False
"""
try:
out = cls._execute([], "link", ("show", ), run_as_root=True)
except Exception as e:
LOG.error(_LE("Failed executing ip command: %s"), e)
raise exc.IpCommandError(reason=e)
for line in out.splitlines():
for line in ip_link_show_output.splitlines():
pattern_match = cls.MACVTAP_REG_EX.match(line)
if pattern_match:
if ifname == pattern_match.group('vf_interface'):

View File

@ -99,7 +99,10 @@ class TestESwitchManagerApi(base.BaseTestCase):
def test_get_assigned_devices_info(self):
with mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
"eswitch_manager.EmbSwitch.get_assigned_devices_info",
return_value=[(self.ASSIGNED_MAC, self.PCI_SLOT)]):
return_value=[(self.ASSIGNED_MAC, self.PCI_SLOT)]),\
mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
"pci_lib.PciDeviceIPWrapper.link_show",
return_value=''):
result = self.eswitch_mgr.get_assigned_devices_info()
self.assertIn(self.ASSIGNED_MAC, list(result)[0])
self.assertIn(self.PCI_SLOT, list(result)[0])
@ -267,7 +270,10 @@ class TestESwitchManagerApi(base.BaseTestCase):
as set_rate_mock, \
mock.patch('neutron.plugins.ml2.drivers.mech_sriov.agent.'
'pci_lib.PciDeviceIPWrapper.get_assigned_macs',
return_value=mac_address):
return_value=mac_address), \
mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
"pci_lib.PciDeviceIPWrapper.link_show",
return_value=''):
self.eswitch_mgr._clear_rate(pci_slot, rate_type)
if passed:
set_rate_mock.assert_called_once_with(pci_slot, rate_type, 0)
@ -335,7 +341,10 @@ class TestEmbSwitch(base.BaseTestCase):
return_value={0: self.ASSIGNED_MAC}),\
mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
"eswitch_manager.PciOsWrapper.is_assigned_vf",
return_value=True):
return_value=True), \
mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
"pci_lib.PciDeviceIPWrapper.link_show",
return_value=''):
result = emb_switch.get_assigned_devices_info()
self.assertIn(self.ASSIGNED_MAC, list(result)[0])
self.assertIn(self.PCI_SLOT, list(result)[0])
@ -350,7 +359,10 @@ class TestEmbSwitch(base.BaseTestCase):
return_value=self.VF_TO_MAC_MAPPING),\
mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
"eswitch_manager.PciOsWrapper.is_assigned_vf",
return_value=True):
return_value=True),\
mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
"pci_lib.PciDeviceIPWrapper.link_show",
return_value=''):
devices_info = emb_switch.get_assigned_devices_info()
for device_info in devices_info:
mac = device_info[0]
@ -361,7 +373,10 @@ class TestEmbSwitch(base.BaseTestCase):
def test_get_assigned_devices_empty(self):
with mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
"eswitch_manager.PciOsWrapper.is_assigned_vf",
return_value=False):
return_value=False), \
mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
"pci_lib.PciDeviceIPWrapper.link_show",
return_value=''):
result = self.emb_switch.get_assigned_devices_info()
self.assertFalse(result)
@ -478,7 +493,10 @@ class TestEmbSwitch(base.BaseTestCase):
return_value={0: self.ASSIGNED_MAC}),\
mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
"eswitch_manager.PciOsWrapper.is_assigned_vf",
return_value=True):
return_value=True),\
mock.patch("neutron.plugins.ml2.drivers.mech_sriov.agent."
"pci_lib.PciDeviceIPWrapper.link_show",
return_value=''):
result = self.emb_switch.get_pci_device(self.PCI_SLOT)
self.assertEqual(self.ASSIGNED_MAC, result)
@ -556,21 +574,21 @@ 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))
self.DEV_NAME, self.VF_INDEX, ''))
@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)
def test_is_assigned_vf_false(self, *args):
self.assertFalse(esm.PciOsWrapper.is_assigned_vf(
self.DEV_NAME, self.VF_INDEX))
self.DEV_NAME, self.VF_INDEX, ''))
@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)
def test_is_assigned_vf_macvtap(
self, mock_is_macvtap_assigned, *args):
esm.PciOsWrapper.is_assigned_vf(self.DEV_NAME, self.VF_INDEX)
esm.PciOsWrapper.is_assigned_vf(self.DEV_NAME, self.VF_INDEX, '')
mock_is_macvtap_assigned.called_with(self.VF_INDEX, "eth0")
@mock.patch("os.listdir", side_effect=OSError())
@ -578,5 +596,5 @@ class TestPciOsWrapper(base.BaseTestCase):
"PciDeviceIPWrapper.is_macvtap_assigned")
def test_is_assigned_vf_macvtap_failure(
self, mock_is_macvtap_assigned, *args):
esm.PciOsWrapper.is_assigned_vf(self.DEV_NAME, self.VF_INDEX)
esm.PciOsWrapper.is_assigned_vf(self.DEV_NAME, self.VF_INDEX, '')
self.assertFalse(mock_is_macvtap_assigned.called)

View File

@ -176,30 +176,20 @@ class TestPciLib(base.BaseTestCase):
state=True)
def test_is_macvtap_assigned(self):
with mock.patch.object(pci_lib.PciDeviceIPWrapper,
"_execute") as mock_exec:
mock_exec.return_value = self.IP_LINK_SHOW_WITH_MACVTAP
self.assertTrue(
pci_lib.PciDeviceIPWrapper.is_macvtap_assigned('enp129s0f1'))
self.assertTrue(pci_lib.PciDeviceIPWrapper.is_macvtap_assigned(
'enp129s0f1', self.IP_LINK_SHOW_WITH_MACVTAP))
def test_is_macvtap_assigned_interface_with_underscore(self):
with mock.patch.object(pci_lib.PciDeviceIPWrapper,
"_execute") as mock_exec:
mock_exec.return_value = self.IP_LINK_SHOW_WITH_MACVTAP2
self.assertTrue(
pci_lib.PciDeviceIPWrapper.is_macvtap_assigned('p1p2_1'))
self.assertTrue(pci_lib.PciDeviceIPWrapper.is_macvtap_assigned(
'p1p2_1', self.IP_LINK_SHOW_WITH_MACVTAP2))
def test_is_macvtap_assigned_not_assigned(self):
with mock.patch.object(pci_lib.PciDeviceIPWrapper,
"_execute") as mock_exec:
mock_exec.return_value = self.IP_LINK_SHOW_WITH_MACVTAP
self.assertFalse(
pci_lib.PciDeviceIPWrapper.is_macvtap_assigned('enp129s0f2'))
self.assertFalse(pci_lib.PciDeviceIPWrapper.is_macvtap_assigned(
'enp129s0f2', self.IP_LINK_SHOW_WITH_MACVTAP))
def test_is_macvtap_assigned_failed(self):
def test_link_show_command_failed(self):
with mock.patch.object(pci_lib.PciDeviceIPWrapper,
"_execute") as mock_exec:
mock_exec.side_effect = Exception()
self.assertRaises(exc.IpCommandError,
pci_lib.PciDeviceIPWrapper.is_macvtap_assigned,
'enp129s0f3')
pci_lib.PciDeviceIPWrapper.link_show)