Skip to content

Commit aa68e69

Browse files
xtrusiakatonalala
authored andcommitted
Checking pci_slot to avoid changing staus to BUILD forever
Currently when sriov agent is enabled and migrating a non-sriov instance, non-sriov port status is frequently set to BUILD instead of ACTIVE. This is because the 'binding_activate' function in sriov-nic-agent sets it BUILD with get_device_details_from_port_id(as it calls _get_new_status). This patch checks network_ports in binding_activate and skip binding port if it is not sriov port Closes-Bug: #2072154 Change-Id: I2d7702e17c75c96ca2f29749dccab77cb2f4bcf4 (cherry picked from commit a311606) (cherry picked from commit 27eee0b)
1 parent 4bc77ee commit aa68e69

File tree

2 files changed

+62
-10
lines changed

2 files changed

+62
-10
lines changed

neutron/plugins/ml2/drivers/mech_sriov/agent/sriov_nic_agent.py

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -112,17 +112,39 @@ def network_update(self, context, **kwargs):
112112
def binding_activate(self, context, **kwargs):
113113
if kwargs.get('host') != self.agent.conf.host:
114114
return
115-
LOG.debug("binding activate for port %s", kwargs.get('port_id'))
116-
device_details = self.agent.get_device_details_from_port_id(
117-
kwargs.get('port_id'))
118-
mac = device_details.get('mac_address')
119-
binding_profile = device_details.get('profile')
120-
if binding_profile:
121-
pci_slot = binding_profile.get('pci_slot')
122-
self.agent.activated_bindings.add((mac, pci_slot))
115+
116+
port_id = kwargs.get('port_id')
117+
118+
def _is_port_id_in_network(network_port, port_id):
119+
for network_id, ports in network_port.items():
120+
for port in ports:
121+
if port['port_id'] == port_id:
122+
return True
123+
return False
124+
125+
is_port_id_sriov = _is_port_id_in_network(
126+
self.agent.network_ports, port_id
127+
)
128+
129+
if is_port_id_sriov:
130+
LOG.debug("binding activate for port %s", port_id)
131+
device_details = self.agent.get_device_details_from_port_id(
132+
port_id)
133+
mac = device_details.get('mac_address')
134+
binding_profile = device_details.get('profile')
135+
if binding_profile:
136+
pci_slot = binding_profile.get('pci_slot')
137+
self.agent.activated_bindings.add((mac, pci_slot))
138+
else:
139+
LOG.warning(
140+
"binding_profile not found for port %s.",
141+
port_id
142+
)
123143
else:
124-
LOG.warning("binding_profile not found for port %s.",
125-
kwargs.get('port_id'))
144+
LOG.warning(
145+
"This port is not SRIOV, skip binding for port %s.",
146+
port_id
147+
)
126148

127149
def binding_deactivate(self, context, **kwargs):
128150
if kwargs.get('host') != self.agent.conf.host:

neutron/tests/unit/plugins/ml2/drivers/mech_sriov/agent/test_sriov_nic_agent.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
# See the License for the specific language governing permissions and
1414
# limitations under the License.
1515

16+
import collections
1617
import copy
1718
from unittest import mock
1819

@@ -460,6 +461,7 @@ def __init__(self):
460461
self.activated_bindings = set()
461462
self.conf = mock.Mock()
462463
self.conf.host = 'host1'
464+
self.network_ports = collections.defaultdict(list)
463465

464466

465467
class TestSriovNicSwitchRpcCallbacks(base.BaseTestCase):
@@ -528,6 +530,12 @@ def test_binding_activate(self):
528530
}
529531
kwargs = self._create_fake_bindings(fake_port, self.agent.conf.host)
530532
kwargs['context'] = self.context
533+
534+
self.agent.network_ports['network_id'].append({
535+
'port_id': fake_port['id'],
536+
'device': 'fake_device'
537+
})
538+
531539
self.sriov_rpc_callback.binding_activate(**kwargs)
532540
# Assert agent.activated_binding set contains the new binding
533541
self.assertIn((fake_port['mac_address'],
@@ -538,10 +546,32 @@ def test_binding_activate_no_host(self):
538546
fake_port = self._create_fake_port()
539547
kwargs = self._create_fake_bindings(fake_port, 'other-host')
540548
kwargs['context'] = self.context
549+
550+
self.agent.network_ports[self.agent.conf.host].append({
551+
'port_id': fake_port['id'],
552+
'device': 'fake_device'
553+
})
554+
541555
self.sriov_rpc_callback.binding_activate(**kwargs)
542556
# Assert no bindings were added
543557
self.assertEqual(set(), self.agent.activated_bindings)
544558

559+
def test_binding_activate_port_not_in_network(self):
560+
fake_port = self._create_fake_port()
561+
kwargs = self._create_fake_bindings(fake_port, self.agent.conf.host)
562+
kwargs['context'] = self.context
563+
564+
self.agent.network_ports['network_id'] = []
565+
566+
with mock.patch.object(sriov_nic_agent.LOG,
567+
'warning') as mock_warning:
568+
self.sriov_rpc_callback.binding_activate(**kwargs)
569+
# Check that the warning message was logged
570+
expected_msg = (
571+
"This port is not SRIOV, skip binding for port %s."
572+
)
573+
mock_warning.assert_called_once_with(expected_msg, fake_port['id'])
574+
545575
def test_binding_deactivate(self):
546576
# binding_deactivate() basically does nothing
547577
# call it with both the agent's host and other host to cover

0 commit comments

Comments
 (0)