From 5d50c35ca5af0aa7b901c1bc0316b02b90e74e54 Mon Sep 17 00:00:00 2001 From: Ivar Lazzaro Date: Tue, 27 Feb 2018 20:06:34 -0800 Subject: [PATCH] [AIM] Make link update/delete transactional Also, make sure it doesn't break other networks' path update when one fails Change-Id: I3634f2686434697c51adf685a9373f853ba7f5ec (cherry picked from commit 8b7206a1ad757559b1d9864db8ad920d7503a385) --- .../drivers/apic_aim/mechanism_driver.py | 102 ++++++++++-------- 1 file changed, 59 insertions(+), 43 deletions(-) diff --git a/gbpservice/neutron/plugins/ml2plus/drivers/apic_aim/mechanism_driver.py b/gbpservice/neutron/plugins/ml2plus/drivers/apic_aim/mechanism_driver.py index 5820f5c4d..6ddf31909 100644 --- a/gbpservice/neutron/plugins/ml2plus/drivers/apic_aim/mechanism_driver.py +++ b/gbpservice/neutron/plugins/ml2plus/drivers/apic_aim/mechanism_driver.py @@ -1965,35 +1965,43 @@ class ApicMechanismDriver(api_plus.MechanismDriver, ', '.join([str(p) for p in (host, interface, mac, switch, module, port, pod_id, port_description)])) - if not switch: - self.delete_link(context, host, interface, mac, switch, module, - port) - return + with context.session.begin(subtransactions=True): + if not switch: + self.delete_link(context, host, interface, mac, switch, module, + port) + return - session = context.session - aim_ctx = aim_context.AimContext(db_session=session) - hlink = self.aim.get(aim_ctx, - aim_infra.HostLink(host_name=host, - interface_name=interface)) - if not hlink or hlink.path != port_description: - attrs = dict(interface_mac=mac, - switch_id=switch, module=module, port=port, - path=port_description, pod_id=pod_id) - if hlink: - old_path = hlink.path - hlink = self.aim.update(aim_ctx, hlink, **attrs) - else: - old_path = None - hlink = aim_infra.HostLink(host_name=host, - interface_name=interface, - **attrs) - hlink = self.aim.create(aim_ctx, hlink) - # Update static paths of all EPGs with ports on the host - nets_segs = self._get_non_opflex_segments_on_host(context, host) - for net, seg in nets_segs: - self._update_static_path_for_network(session, net, seg, - old_path=old_path, - new_path=hlink.path) + session = context.session + aim_ctx = aim_context.AimContext(db_session=session) + hlink = self.aim.get(aim_ctx, + aim_infra.HostLink(host_name=host, + interface_name=interface)) + if not hlink or hlink.path != port_description: + attrs = dict(interface_mac=mac, + switch_id=switch, module=module, port=port, + path=port_description, pod_id=pod_id) + if hlink: + old_path = hlink.path + hlink = self.aim.update(aim_ctx, hlink, **attrs) + else: + old_path = None + hlink = aim_infra.HostLink(host_name=host, + interface_name=interface, + **attrs) + hlink = self.aim.create(aim_ctx, hlink) + # Update static paths of all EPGs with ports on the host + nets_segs = self._get_non_opflex_segments_on_host(context, + host) + for net, seg in nets_segs: + try: + self._update_static_path_for_network( + session, net, seg, old_path=old_path, + new_path=hlink.path) + except Exception as e: + # If one fails don't affect all the others + LOG.error("Static path update on update_link has " + "failed for network %s: %s" % (net['id'], + e.message)) # Topology RPC method handler def delete_link(self, context, host, interface, mac, switch, module, port): @@ -2003,22 +2011,30 @@ class ApicMechanismDriver(api_plus.MechanismDriver, session = context.session aim_ctx = aim_context.AimContext(db_session=session) - hlink = self.aim.get(aim_ctx, - aim_infra.HostLink(host_name=host, - interface_name=interface)) - if not hlink: - return + with context.session.begin(subtransactions=True): + hlink = self.aim.get(aim_ctx, + aim_infra.HostLink(host_name=host, + interface_name=interface)) + if not hlink: + return - self.aim.delete(aim_ctx, hlink) - # if there are no more host-links for this host (multiple links may - # exist with VPC), update EPGs with ports on this host to remove - # the static path to this host - if not self.aim.find(aim_ctx, aim_infra.HostLink, host_name=host, - path=hlink.path): - nets_segs = self._get_non_opflex_segments_on_host(context, host) - for net, seg in nets_segs: - self._update_static_path_for_network(session, net, seg, - old_path=hlink.path) + self.aim.delete(aim_ctx, hlink) + # if there are no more host-links for this host (multiple links may + # exist with VPC), update EPGs with ports on this host to remove + # the static path to this host + if not self.aim.find(aim_ctx, aim_infra.HostLink, host_name=host, + path=hlink.path): + nets_segs = self._get_non_opflex_segments_on_host(context, + host) + for net, seg in nets_segs: + try: + self._update_static_path_for_network( + session, net, seg, old_path=hlink.path) + except Exception as e: + # If one fails don't affect all the others + LOG.error("Static path update on update_link has " + "failed for network %s: %s" % (net['id'], + e.message)) def _agent_bind_port(self, context, agent_type, bind_strategy): current = context.current