Fix corner case in failure assigning MAC to SR-IOV NIC
Sometimes due to NIC driver incorrect behavior, VFs might be
missing in 'ip link show' output. This may lead to a VM boot
failure as agent will just skip such missing devices.
Make the agent do a resync in case a newly added device
'disappears' during processing, which should cause a MAC to
get assigned.
Co-authored-by: Oleg Bondarev <obondarev@mirantis.com>
Change-Id: I148b5a025fc388821fd1269d02908cc8ce1882fe
Closes-bug: #1784484
(cherry picked from commit eea5aaac4f
)
This commit is contained in:
parent
1cd4b8ed5a
commit
9574da1a3d
|
@ -289,6 +289,7 @@ class SriovNicSwitchAgent(object):
|
||||||
|
|
||||||
devices_up = set()
|
devices_up = set()
|
||||||
devices_down = set()
|
devices_down = set()
|
||||||
|
resync = False
|
||||||
for device_details in devices_details_list:
|
for device_details in devices_details_list:
|
||||||
device = device_details['device']
|
device = device_details['device']
|
||||||
LOG.debug("Port with MAC address %s is added", device)
|
LOG.debug("Port with MAC address %s is added", device)
|
||||||
|
@ -307,6 +308,8 @@ class SriovNicSwitchAgent(object):
|
||||||
devices_up.add(device)
|
devices_up.add(device)
|
||||||
else:
|
else:
|
||||||
devices_down.add(device)
|
devices_down.add(device)
|
||||||
|
else:
|
||||||
|
resync = True
|
||||||
self._update_network_ports(device_details['network_id'],
|
self._update_network_ports(device_details['network_id'],
|
||||||
port_id,
|
port_id,
|
||||||
(device, profile.get('pci_slot')))
|
(device, profile.get('pci_slot')))
|
||||||
|
@ -319,7 +322,7 @@ class SriovNicSwitchAgent(object):
|
||||||
devices_down,
|
devices_down,
|
||||||
self.agent_id,
|
self.agent_id,
|
||||||
self.conf.host)
|
self.conf.host)
|
||||||
return False
|
return resync
|
||||||
|
|
||||||
def treat_devices_removed(self, devices):
|
def treat_devices_removed(self, devices):
|
||||||
resync = False
|
resync = False
|
||||||
|
|
|
@ -449,6 +449,15 @@ class TestSriovAgent(base.BaseTestCase):
|
||||||
self.assertFalse(agent.treat_device('aa:bb:cc:dd:ee:ff', '1:2:3:0',
|
self.assertFalse(agent.treat_device('aa:bb:cc:dd:ee:ff', '1:2:3:0',
|
||||||
admin_state_up=True))
|
admin_state_up=True))
|
||||||
|
|
||||||
|
def test_treat_device_no_device_found(self):
|
||||||
|
agent = self.agent
|
||||||
|
agent.plugin_rpc = mock.Mock()
|
||||||
|
agent.eswitch_mgr = mock.Mock()
|
||||||
|
agent.eswitch_mgr.device_exists.return_value = False
|
||||||
|
|
||||||
|
self.assertFalse(agent.treat_device('aa:bb:cc:dd:ee:ff', '1:2:3:0',
|
||||||
|
admin_state_up=True))
|
||||||
|
|
||||||
def test_treat_devices_added_updated_admin_state_up_false(self):
|
def test_treat_devices_added_updated_admin_state_up_false(self):
|
||||||
agent = self.agent
|
agent = self.agent
|
||||||
mock_details = {'device': 'aa:bb:cc:dd:ee:ff',
|
mock_details = {'device': 'aa:bb:cc:dd:ee:ff',
|
||||||
|
@ -474,6 +483,26 @@ class TestSriovAgent(base.BaseTestCase):
|
||||||
mock.ANY,
|
mock.ANY,
|
||||||
mock.ANY)
|
mock.ANY)
|
||||||
|
|
||||||
|
def test_treat_devices_added_updated_no_device_found(self):
|
||||||
|
agent = self.agent
|
||||||
|
mock_details = {'device': 'aa:bb:cc:dd:ee:ff',
|
||||||
|
'port_id': 'port123',
|
||||||
|
'network_id': 'net123',
|
||||||
|
'admin_state_up': True,
|
||||||
|
'network_type': 'vlan',
|
||||||
|
'segmentation_id': 100,
|
||||||
|
'profile': {'pci_slot': '1:2:3.0'},
|
||||||
|
'physical_network': 'physnet1'}
|
||||||
|
agent.plugin_rpc = mock.Mock()
|
||||||
|
agent.plugin_rpc.get_devices_details_list.return_value = [mock_details]
|
||||||
|
agent.remove_port_binding = mock.Mock()
|
||||||
|
agent.eswitch_mgr = mock.Mock()
|
||||||
|
agent.eswitch_mgr.device_exists.return_value = False
|
||||||
|
resync_needed = agent.treat_devices_added_updated(
|
||||||
|
set(['aa:bb:cc:dd:ee:ff']))
|
||||||
|
self.assertTrue(resync_needed)
|
||||||
|
self.assertFalse(agent.plugin_rpc.update_device_up.called)
|
||||||
|
|
||||||
def test_update_and_clean_network_ports(self):
|
def test_update_and_clean_network_ports(self):
|
||||||
network_id1 = 'network_id1'
|
network_id1 = 'network_id1'
|
||||||
network_id2 = 'network_id2'
|
network_id2 = 'network_id2'
|
||||||
|
|
Loading…
Reference in New Issue