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 <rmoats@us.ibm.com>
Closes-Bug: 1512450
This commit is contained in:
Ryan Moats 2015-11-02 13:30:26 -06:00
parent 830c2e30fd
commit 526dac467b
7 changed files with 44 additions and 47 deletions

View File

@ -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)

View File

@ -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()

View File

@ -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)

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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'],