Use only 'binding:host_id' to detect port migration

The existing code fails to detect a port migration if the port status
is in 'DOWN' state. With this patch, detection of a port migration
relies only on change in 'binding:host_id'.
This patch also fixes failure of deleting a network due to orphan port
in the arista_provisioned_vms database by deleting all entries from the
table if they exist.

Change-Id: I4faa8c9aafc39dce9e0773fcf2ff4836b86080dd
changes/60/466960/2
Nader Lahouti 6 years ago
parent 357444b2ac
commit 30333342f2

@ -209,12 +209,10 @@ class AristaDriver(driver_api.MechanismDriver):
with self.eos_sync_lock:
if db_lib.is_network_provisioned(tenant_id, network_id):
if db_lib.are_ports_attached_to_network(network_id):
LOG.info(_LI('Network %s can not be deleted as it '
'has ports attached to it'), network_id)
raise ml2_exc.MechanismDriverError(
method='delete_network_precommit')
else:
db_lib.forget_network_segment(tenant_id, network_id)
db_lib.forget_all_ports_for_network(network_id)
LOG.info(_LI('Deleting all ports on network %s'),
network_id)
db_lib.forget_network_segment(tenant_id, network_id)
def delete_network_postcommit(self, context):
"""Send network delete request to Arista HW."""
@ -223,9 +221,9 @@ class AristaDriver(driver_api.MechanismDriver):
if not self.rpc.hpb_supported():
# Hierarchical port binding is not supported by CVX, only
# send the request if network type is VLAN.
if(segments and
if (segments and
segments[0][driver_api.NETWORK_TYPE] != p_const.TYPE_VLAN):
# If networtk type is not VLAN, do nothing
# If network type is not VLAN, do nothing
return
# No need to pass segments info when calling delete_network as
# HPB is not supported.
@ -450,15 +448,11 @@ class AristaDriver(driver_api.MechanismDriver):
"""
orig_port = context.original
orig_host = context.original_host
orig_status = context.original_status
new_status = context.status
new_host = context.host
new_port = context.current
port_id = orig_port['id']
if (new_host != orig_host and
orig_status == n_const.PORT_STATUS_ACTIVE and
new_status == n_const.PORT_STATUS_DOWN):
if new_host and orig_host and new_host != orig_host:
LOG.debug("Handling port migration for: %s " % orig_port)
network_id = orig_port['network_id']
tenant_id = orig_port['tenant_id'] or INTERNAL_TENANT_ID
@ -484,14 +478,9 @@ class AristaDriver(driver_api.MechanismDriver):
"""
orig_port = context.original
orig_host = context.original_host
orig_status = context.original_status
new_status = context.status
new_host = context.host
if (new_host != orig_host and
orig_status == n_const.PORT_STATUS_ACTIVE and
new_status == n_const.PORT_STATUS_DOWN):
if new_host and orig_host and new_host != orig_host:
self._try_to_release_dynamic_segment(context, migration=True)
# Handling migration case.
@ -503,7 +492,7 @@ class AristaDriver(driver_api.MechanismDriver):
# Ensure that we use tenant Id for the network owner
tenant_id = self._network_owner_tenant(context, network_id,
tenant_id)
for binding_level in context._original_binding_levels:
for binding_level in context._original_binding_levels or []:
if self._network_provisioned(
tenant_id, network_id,
segment_id=binding_level.segment_id):
@ -768,7 +757,7 @@ class AristaDriver(driver_api.MechanismDriver):
port_id = port['id']
host_id = context.host
with self.eos_sync_lock:
if db_lib.is_port_provisioned(port_id):
if db_lib.is_port_provisioned(port_id, host_id):
db_lib.forget_port(port_id, host_id)
def delete_port_postcommit(self, context):
@ -788,8 +777,8 @@ class AristaDriver(driver_api.MechanismDriver):
pretty_log("delete_port_postcommit:", port)
# If this port is the last one using dynamic segmentation id,
# and the segmentaion id was alloated by this driver, it needs
# to be releaed.
# and the segmentation id was allocated by this driver, it needs
# to be released.
self._try_to_release_dynamic_segment(context)
with self.eos_sync_lock:

@ -455,7 +455,7 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
port_id = port_context.current['id']
expected_calls = [
mock.call.is_port_provisioned(port_id),
mock.call.is_port_provisioned(port_id, port_context.host),
mock.call.forget_port(port_id, port_context.host),
]
@ -484,7 +484,7 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
port_id = port_context.current['id']
expected_calls += [
mock.call.is_port_provisioned(port_id),
mock.call.is_port_provisioned(port_id, port_context.host),
mock.call.forget_port(port_id, port_context.host),
]
@ -616,7 +616,6 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
vm_id,
network_context)
host_id = port_context.current['binding:host_id']
port_context.original['binding:host_id'] = 'ubuntu0'
port_id = port_context.current['id']
network = {'tenant_id': tenant_id}
@ -657,7 +656,6 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
vm_id,
network_context)
host_id = port_context.current['binding:host_id']
port_context.original['binding:host_id'] = 'ubuntu0'
port_id = port_context.current['id']
# Force the check to return port found, but, network was not found
@ -678,8 +676,6 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
mock.call.is_network_provisioned(tenant_id, network_id,
segmentation_id, segment_id),
mock.call.is_port_provisioned(port_id, None),
mock.call.update_port(vm_id, host_id, port_id,
network_id, tenant_id)
]
mechanism_arista.db_lib.assert_has_calls(expected_calls)
@ -702,7 +698,6 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
# Port does not contain a tenant
port_context.current['tenant_id'] = None
host_id = port_context.current['binding:host_id']
port_context.original['binding:host_id'] = 'ubuntu0'
port_id = port_context.current['id']
# Force the check to return port and network were found
@ -784,8 +779,7 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
device_id = port['device_id']
device_owner = port['device_owner']
host_id = port['binding:host_id']
orig_host_id = 'ubuntu0'
port_context.original['binding:host_id'] = orig_host_id
orig_host_id = port_context.original_host
port_id = port['id']
port_name = port['name']
vnic_type = port['binding:vnic_type']
@ -806,16 +800,6 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
mock.call.create_network_segments(tenant_id, network_id,
network_name,
segments),
mock.call.is_network_provisioned(tenant_id, network_id, None,
None),
mock.call.unplug_port_from_network(device_id, 'compute',
orig_host_id, port_id,
network_id, tenant_id,
None, vnic_type,
switch_bindings=profile),
mock.call.remove_security_group(None, profile),
mock.call.num_nets_provisioned(tenant_id),
mock.call.num_vms_provisioned(tenant_id),
mock.call.plug_port_into_network(device_id, host_id, port_id,
network_id, tenant_id,
port_name, device_owner, None,
@ -858,8 +842,7 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
device_id = port['device_id']
device_owner = port['device_owner']
host_id = port['binding:host_id']
orig_host_id = 'ubuntu0'
port_context.original['binding:host_id'] = orig_host_id
orig_host_id = port_context.original_host
port_id = port['id']
port_name = port['name']
network_name = network_context.current['name']
@ -876,17 +859,6 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
mock.call.create_network_segments(INTERNAL_TENANT_ID, network_id,
network_name,
segments),
mock.call.is_network_provisioned(INTERNAL_TENANT_ID, network_id,
None, None),
mock.call.unplug_port_from_network(device_id, 'compute',
orig_host_id,
port_id, network_id,
INTERNAL_TENANT_ID,
None, vnic_type,
switch_bindings=profile),
mock.call.remove_security_group(None, profile),
mock.call.num_nets_provisioned(INTERNAL_TENANT_ID),
mock.call.num_vms_provisioned(INTERNAL_TENANT_ID),
mock.call.plug_port_into_network(device_id, host_id, port_id,
network_id, INTERNAL_TENANT_ID,
port_name, device_owner, None,
@ -1070,10 +1042,7 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
self.drv.update_port_precommit(context)
expected_calls = [
mock.call.is_network_provisioned(tenant_id, network_id,
segmentation_id,
segment_id),
mock.call.is_port_provisioned(port_id, None),
mock.call.is_port_provisioned(port_id, old_host),
mock.call.update_port(new_device_id,
new_host, port_id,
network_id, tenant_id)
@ -1239,17 +1208,19 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
context.current['binding:host_id'] = new_host
context.current['status'] = 'DOWN'
physnet = dict(physnet='default')
self.fake_rpc.get_physical_network.return_value = physnet
context._original_binding_levels = context._binding_levels
mechanism_arista.db_lib.reset_mock()
self.drv.update_port_postcommit(context)
expected_calls = [
mock.call.is_port_provisioned(port_id, None),
mock.call.is_network_provisioned(tenant_id, network_id,
None, None),
mock.call.is_network_provisioned(tenant_id, network_id,
segmentation_id,
None),
mock.call.hpb_supported(),
expected_calls = []
expected_calls.extend(
mock.call.is_network_provisioned(tenant_id, network_id, None,
binding_level.segment_id)
for binding_level in context._original_binding_levels)
expected_calls += [
mock.call.is_network_provisioned(tenant_id, network_id,
None, None),
mock.call.unplug_port_from_network(reserved_device,
@ -1262,14 +1233,6 @@ class AristaDriverTestCase(testlib_api.SqlTestCase):
mock.call.remove_security_group(None, profile),
mock.call.num_nets_provisioned(tenant_id),
mock.call.num_vms_provisioned(tenant_id),
mock.call.plug_port_into_network(new_device_id,
new_host,
port_id, network_id,
tenant_id, port_name,
n_const.DEVICE_OWNER_DHCP,
None, None, vnic_type,
segments=[],
switch_bindings=profile),
]
mechanism_arista.db_lib.assert_has_calls(expected_calls)

Loading…
Cancel
Save