From 526dac467ba869284dd096c7a9e8251fb1bd4e85 Mon Sep 17 00:00:00 2001 From: Ryan Moats Date: Mon, 2 Nov 2015 13:30:26 -0600 Subject: [PATCH] Optimize router delete execution Optimize the execution of router delete in the L3 agent by not performing operations in the router namespace that will be removed as the last step of the workflow. Comparing the slopes of the least squares fit of delete execution time shows that this optimization decreases that slope by over half. Change-Id: Ic425ab1f8c3afe882c9deaa72a814ac0d2053f3b Signed-off-by: Ryan Moats Closes-Bug: 1512450 --- neutron/agent/l3/dvr_edge_ha_router.py | 9 +---- neutron/agent/l3/dvr_edge_router.py | 5 +++ neutron/agent/l3/dvr_local_router.py | 8 ++-- neutron/agent/l3/dvr_router_base.py | 4 +- neutron/agent/l3/ha_router.py | 4 +- neutron/agent/l3/router_info.py | 53 ++++++++++++++------------ neutron/agent/metadata/driver.py | 8 ---- 7 files changed, 44 insertions(+), 47 deletions(-) diff --git a/neutron/agent/l3/dvr_edge_ha_router.py b/neutron/agent/l3/dvr_edge_ha_router.py index 5e254d65dd8..ecd7a0e638f 100644 --- a/neutron/agent/l3/dvr_edge_ha_router.py +++ b/neutron/agent/l3/dvr_edge_ha_router.py @@ -92,16 +92,11 @@ class DvrEdgeHaRouter(DvrEdgeRouter, HaRouter): self._create_snat_namespace() super(DvrEdgeHaRouter, self).initialize(process_monitor) - def process(self, agent): - super(DvrEdgeHaRouter, self).process(agent) + def process(self, agent, delete=False): + super(DvrEdgeHaRouter, self).process(agent, delete) if self.ha_port: self.enable_keepalived() - def delete(self, agent): - super(DvrEdgeHaRouter, self).delete(agent) - if self.snat_namespace: - self.snat_namespace.delete() - def get_router_cidrs(self, device): return RouterInfo.get_router_cidrs(self, device) diff --git a/neutron/agent/l3/dvr_edge_router.py b/neutron/agent/l3/dvr_edge_router.py index 72534d35ca2..d2424096d13 100644 --- a/neutron/agent/l3/dvr_edge_router.py +++ b/neutron/agent/l3/dvr_edge_router.py @@ -186,3 +186,8 @@ class DvrEdgeRouter(dvr_local_router.DvrLocalRouter): ns_name = dvr_snat_ns.SnatNamespace.get_snat_ns_name(self.router['id']) super(DvrEdgeRouter, self).update_routing_table(operation, route, namespace=ns_name) + + def delete(self, agent): + super(DvrEdgeRouter, self).delete(agent) + if self.snat_namespace: + self.snat_namespace.delete() diff --git a/neutron/agent/l3/dvr_local_router.py b/neutron/agent/l3/dvr_local_router.py index f412f94bb4c..52bb49cca01 100644 --- a/neutron/agent/l3/dvr_local_router.py +++ b/neutron/agent/l3/dvr_local_router.py @@ -414,11 +414,11 @@ class DvrLocalRouter(dvr_router_base.DvrRouterBase): def _handle_router_snat_rules(self, ex_gw_port, interface_name): pass - def process_external(self, agent): + def process_external(self, agent, delete=False): ex_gw_port = self.get_ex_gw_port() if ex_gw_port: self.create_dvr_fip_interfaces(ex_gw_port) - super(DvrLocalRouter, self).process_external(agent) + super(DvrLocalRouter, self).process_external(agent, delete) def create_dvr_fip_interfaces(self, ex_gw_port): floating_ips = self.get_floating_ips() @@ -455,10 +455,10 @@ class DvrLocalRouter(dvr_router_base.DvrRouterBase): # configured self.agent.process_router_add(self) - def process(self, agent): + def process(self, agent, delete=False): ex_gw_port = self.get_ex_gw_port() if ex_gw_port: self.fip_ns = agent.get_fip_ns(ex_gw_port['network_id']) self.fip_ns.scan_fip_ports(self) - super(DvrLocalRouter, self).process(agent) + super(DvrLocalRouter, self).process(agent, delete) diff --git a/neutron/agent/l3/dvr_router_base.py b/neutron/agent/l3/dvr_router_base.py index 704be6ce6e0..ec519ef93fb 100644 --- a/neutron/agent/l3/dvr_router_base.py +++ b/neutron/agent/l3/dvr_router_base.py @@ -26,8 +26,8 @@ class DvrRouterBase(router.RouterInfo): self.agent = agent self.host = host - def process(self, agent): - super(DvrRouterBase, self).process(agent) + def process(self, agent, delete=False): + super(DvrRouterBase, self).process(agent, delete) # NOTE: Keep a copy of the interfaces around for when they are removed self.snat_ports = self.get_snat_interfaces() diff --git a/neutron/agent/l3/ha_router.py b/neutron/agent/l3/ha_router.py index d3ef8a68f3a..e0e96f86e91 100644 --- a/neutron/agent/l3/ha_router.py +++ b/neutron/agent/l3/ha_router.py @@ -385,8 +385,8 @@ class HaRouter(router.RouterInfo): self.ha_network_removed() self.disable_keepalived() - def process(self, agent): - super(HaRouter, self).process(agent) + def process(self, agent, delete=False): + super(HaRouter, self).process(agent, delete) if self.ha_port: self.enable_keepalived() diff --git a/neutron/agent/l3/router_info.py b/neutron/agent/l3/router_info.py index af3ae7c6e9b..e2c9907a84e 100644 --- a/neutron/agent/l3/router_info.py +++ b/neutron/agent/l3/router_info.py @@ -261,7 +261,7 @@ class RouterInfo(object): self.router['gw_port'] = None self.router[l3_constants.INTERFACE_KEY] = [] self.router[l3_constants.FLOATINGIP_KEY] = [] - self.process(agent) + self.process(agent, delete=True) self.disable_radvd() self.router_namespace.delete() @@ -646,31 +646,35 @@ class RouterInfo(object): self.iptables_manager, interface_name) - def process_external(self, agent): + def process_external(self, agent, delete=False): fip_statuses = {} - try: - with self.iptables_manager.defer_apply(): - ex_gw_port = self.get_ex_gw_port() - self._process_external_gateway(ex_gw_port, agent.pd) - if not ex_gw_port: - return + if not delete: + try: + with self.iptables_manager.defer_apply(): + ex_gw_port = self.get_ex_gw_port() + self._process_external_gateway(ex_gw_port, agent.pd) + if not ex_gw_port: + return - # Process SNAT/DNAT rules and addresses for floating IPs - self.process_snat_dnat_for_fip() + # Process SNAT/DNAT rules and addresses for floating IPs + self.process_snat_dnat_for_fip() - # Once NAT rules for floating IPs are safely in place - # configure their addresses on the external gateway port - interface_name = self.get_external_device_interface_name( - ex_gw_port) - fip_statuses = self.configure_fip_addresses(interface_name) + # Once NAT rules for floating IPs are safely in place + # configure their addresses on the external gateway port + interface_name = self.get_external_device_interface_name( + ex_gw_port) + fip_statuses = self.configure_fip_addresses(interface_name) - except (n_exc.FloatingIpSetupException, - n_exc.IpTablesApplyException): - # All floating IPs must be put in error state - LOG.exception(_LE("Failed to process floating IPs.")) - fip_statuses = self.put_fips_in_error_state() - finally: - self.update_fip_statuses(agent, fip_statuses) + except (n_exc.FloatingIpSetupException, + n_exc.IpTablesApplyException): + # All floating IPs must be put in error state + LOG.exception(_LE("Failed to process floating IPs.")) + fip_statuses = self.put_fips_in_error_state() + finally: + self.update_fip_statuses(agent, fip_statuses) + else: + ex_gw_port = self.get_ex_gw_port() + self._process_external_gateway(ex_gw_port, agent.pd) def update_fip_statuses(self, agent, fip_statuses): # Identify floating IPs which were disabled @@ -689,18 +693,19 @@ class RouterInfo(object): agent.context, self.router_id, fip_statuses) @common_utils.exception_logger() - def process(self, agent): + def process(self, agent, delete=False): """Process updates to this router This method is the point where the agent requests that updates be applied to this router. :param agent: Passes the agent in order to send RPC messages. + :param delete: Indicates whether this update is from a delete operation """ LOG.debug("process router updates") self._process_internal_ports(agent.pd) agent.pd.sync_router(self.router['id']) - self.process_external(agent) + self.process_external(agent, delete) # Process static routes for router self.routes_updated() diff --git a/neutron/agent/metadata/driver.py b/neutron/agent/metadata/driver.py index 16002d2c239..f25c28c5442 100644 --- a/neutron/agent/metadata/driver.py +++ b/neutron/agent/metadata/driver.py @@ -167,14 +167,6 @@ def after_router_added(resource, event, l3_agent, **kwargs): def before_router_removed(resource, event, l3_agent, **kwargs): router = kwargs['router'] proxy = l3_agent.metadata_driver - for c, r in proxy.metadata_filter_rules(proxy.metadata_port, - proxy.metadata_access_mark): - router.iptables_manager.ipv4['filter'].remove_rule(c, r) - for c, r in proxy.metadata_mangle_rules(proxy.metadata_access_mark): - router.iptables_manager.ipv4['mangle'].remove_rule(c, r) - for c, r in proxy.metadata_nat_rules(proxy.metadata_port): - router.iptables_manager.ipv4['nat'].remove_rule(c, r) - router.iptables_manager.apply() proxy.destroy_monitored_metadata_proxy(l3_agent.process_monitor, router.router['id'],