ML2: Change port status only when it's bound to the host
Currently, nothing prevents the port status to be changed to BUILD state when get_device_details() is sent by a host that doesn't own the port. In some cases the port might stay in BUILD state. This could happen during a live-migration, or for multi-hosted ports such as HA ports. This commit allows the port status modification only if the port is bound to the host that is asking for it. Closes-Bug: #1439857 Closes-Bug: #1438040 Closes-Bug: #1416933 Change-Id: I9b3673f453abbafaaa4f78542fcfebe8dc93f2bb
This commit is contained in:
parent
c48ba4c7b0
commit
9b53b82ce7
|
@ -96,13 +96,14 @@ class RpcCallbacks(type_tunnel.TunnelRpcCallbackMixin):
|
||||||
'vif_type': port[portbindings.VIF_TYPE]})
|
'vif_type': port[portbindings.VIF_TYPE]})
|
||||||
return {'device': device}
|
return {'device': device}
|
||||||
|
|
||||||
new_status = (q_const.PORT_STATUS_BUILD if port['admin_state_up']
|
if (not host or host == port_context.host):
|
||||||
else q_const.PORT_STATUS_DOWN)
|
new_status = (q_const.PORT_STATUS_BUILD if port['admin_state_up']
|
||||||
if port['status'] != new_status:
|
else q_const.PORT_STATUS_DOWN)
|
||||||
plugin.update_port_status(rpc_context,
|
if port['status'] != new_status:
|
||||||
port_id,
|
plugin.update_port_status(rpc_context,
|
||||||
new_status,
|
port_id,
|
||||||
host)
|
new_status,
|
||||||
|
host)
|
||||||
|
|
||||||
entry = {'device': device,
|
entry = {'device': device,
|
||||||
'network_id': port['network_id'],
|
'network_id': port['network_id'],
|
||||||
|
|
|
@ -88,6 +88,7 @@ class RpcCallbacksTestCase(base.BaseTestCase):
|
||||||
def test_get_device_details_port_status_equal_new_status(self):
|
def test_get_device_details_port_status_equal_new_status(self):
|
||||||
port = collections.defaultdict(lambda: 'fake')
|
port = collections.defaultdict(lambda: 'fake')
|
||||||
self.plugin.get_bound_port_context().current = port
|
self.plugin.get_bound_port_context().current = port
|
||||||
|
self.plugin.port_bound_to_host = mock.MagicMock(return_value=True)
|
||||||
for admin_state_up in (True, False):
|
for admin_state_up in (True, False):
|
||||||
new_status = (constants.PORT_STATUS_BUILD if admin_state_up
|
new_status = (constants.PORT_STATUS_BUILD if admin_state_up
|
||||||
else constants.PORT_STATUS_DOWN)
|
else constants.PORT_STATUS_DOWN)
|
||||||
|
@ -98,8 +99,7 @@ class RpcCallbacksTestCase(base.BaseTestCase):
|
||||||
port['admin_state_up'] = admin_state_up
|
port['admin_state_up'] = admin_state_up
|
||||||
port['status'] = status
|
port['status'] = status
|
||||||
self.plugin.update_port_status.reset_mock()
|
self.plugin.update_port_status.reset_mock()
|
||||||
self.callbacks.get_device_details('fake_context',
|
self.callbacks.get_device_details('fake_context')
|
||||||
host='fake_host')
|
|
||||||
self.assertEqual(status == new_status,
|
self.assertEqual(status == new_status,
|
||||||
not self.plugin.update_port_status.called)
|
not self.plugin.update_port_status.called)
|
||||||
|
|
||||||
|
@ -113,6 +113,24 @@ class RpcCallbacksTestCase(base.BaseTestCase):
|
||||||
cached_networks=cached_networks)
|
cached_networks=cached_networks)
|
||||||
self.assertTrue('fake_port' in cached_networks)
|
self.assertTrue('fake_port' in cached_networks)
|
||||||
|
|
||||||
|
def test_get_device_details_wrong_host(self):
|
||||||
|
port = collections.defaultdict(lambda: 'fake')
|
||||||
|
port_context = self.plugin.get_bound_port_context()
|
||||||
|
port_context.current = port
|
||||||
|
port_context.host = 'fake'
|
||||||
|
self.plugin.update_port_status.reset_mock()
|
||||||
|
self.callbacks.get_device_details('fake_context',
|
||||||
|
host='fake_host')
|
||||||
|
self.assertFalse(self.plugin.update_port_status.called)
|
||||||
|
|
||||||
|
def test_get_device_details_port_no_host(self):
|
||||||
|
port = collections.defaultdict(lambda: 'fake')
|
||||||
|
port_context = self.plugin.get_bound_port_context()
|
||||||
|
port_context.current = port
|
||||||
|
self.plugin.update_port_status.reset_mock()
|
||||||
|
self.callbacks.get_device_details('fake_context')
|
||||||
|
self.assertTrue(self.plugin.update_port_status.called)
|
||||||
|
|
||||||
def test_get_devices_details_list(self):
|
def test_get_devices_details_list(self):
|
||||||
devices = [1, 2, 3, 4, 5]
|
devices = [1, 2, 3, 4, 5]
|
||||||
kwargs = {'host': 'fake_host', 'agent_id': 'fake_agent_id'}
|
kwargs = {'host': 'fake_host', 'agent_id': 'fake_agent_id'}
|
||||||
|
|
Loading…
Reference in New Issue