L3 Agent support for routers with HA and DVR
The main difference for DVR HA routers is where the VRRP/keepalived logic is run and which ports fall in the HA domain for DVR. Instead of running in the qrouter namespace, keepalived will run inside the snat-namespace. Therefore only snat ports will fall under the control of the HA domain. Partial-Bug: #1365473 Change-Id: If2962580397d39f72fd1fbbc1188a6958f00ff0c Co-Authored-By: Michael Smith <michael.smith6@hp.com> Co-Authored-By: Hardik Italia <hardik.italia@hp.com> Co-Authored-By: Adolfo Duarte <adolfo.duarte@hp.com> Co-Authored-By: John Schwarz <jschwarz@redhat.com>changes/93/196893/50
parent
44cc4b9a63
commit
f63366e615
@ -0,0 +1,129 @@
|
||||
# Copyright (c) 2015 Hewlett-Packard Development Company, L.P.
|
||||
# All Rights Reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
# not use this file except in compliance with the License. You may obtain
|
||||
# a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
from oslo_log import log as logging
|
||||
|
||||
from neutron.agent.l3.dvr_edge_router import DvrEdgeRouter
|
||||
from neutron.agent.l3 import dvr_snat_ns
|
||||
from neutron.agent.l3.ha_router import HaRouter
|
||||
from neutron.agent.l3.router_info import RouterInfo
|
||||
from neutron.common import constants as l3_constants
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class DvrEdgeHaRouter(DvrEdgeRouter, HaRouter):
|
||||
"""Router class which represents a centralized SNAT
|
||||
DVR router with HA capabilities.
|
||||
"""
|
||||
|
||||
def __init__(self, agent, host, *args, **kwargs):
|
||||
super(DvrEdgeHaRouter, self).__init__(agent, host,
|
||||
*args, **kwargs)
|
||||
self.enable_snat = None
|
||||
self.snat_ports = None
|
||||
|
||||
@property
|
||||
def ha_namespace(self):
|
||||
if self.snat_namespace:
|
||||
return self.snat_namespace.name
|
||||
return None
|
||||
|
||||
def internal_network_added(self, port):
|
||||
# Call RouterInfo's internal_network_added (Plugs the port, adds IP)
|
||||
RouterInfo.internal_network_added(self, port)
|
||||
|
||||
for subnet in port['subnets']:
|
||||
self._set_subnet_arp_info(subnet['id'])
|
||||
self._snat_redirect_add_from_port(port)
|
||||
|
||||
if not self.get_ex_gw_port() or not self._is_this_snat_host():
|
||||
return
|
||||
|
||||
sn_port = self.get_snat_port_for_internal_port(port)
|
||||
if not sn_port:
|
||||
return
|
||||
|
||||
self._plug_ha_router_port(
|
||||
sn_port,
|
||||
self._get_snat_int_device_name,
|
||||
dvr_snat_ns.SNAT_INT_DEV_PREFIX)
|
||||
|
||||
def external_gateway_added(self, ex_gw_port, interface_name):
|
||||
super(DvrEdgeHaRouter, self).external_gateway_added(
|
||||
ex_gw_port, interface_name)
|
||||
for port in self.get_snat_interfaces():
|
||||
snat_interface_name = self._get_snat_int_device_name(port['id'])
|
||||
self._disable_ipv6_addressing_on_interface(snat_interface_name)
|
||||
self._add_vips(
|
||||
self.get_snat_port_for_internal_port(port),
|
||||
snat_interface_name)
|
||||
|
||||
self._add_gateway_vip(ex_gw_port, interface_name)
|
||||
self._disable_ipv6_addressing_on_interface(interface_name)
|
||||
|
||||
def external_gateway_removed(self, ex_gw_port, interface_name):
|
||||
for port in self.snat_ports:
|
||||
snat_interface = self._get_snat_int_device_name(port['id'])
|
||||
self.driver.unplug(snat_interface,
|
||||
namespace=self.ha_namespace,
|
||||
prefix=l3_constants.SNAT_INT_DEV_PREFIX)
|
||||
self._clear_vips(snat_interface)
|
||||
super(DvrEdgeHaRouter, self)._external_gateway_removed(
|
||||
ex_gw_port, interface_name)
|
||||
self._clear_vips(interface_name)
|
||||
|
||||
def external_gateway_updated(self, ex_gw_port, interface_name):
|
||||
HaRouter.external_gateway_updated(self, ex_gw_port, interface_name)
|
||||
|
||||
def initialize(self, process_monitor):
|
||||
self._create_snat_namespace()
|
||||
super(DvrEdgeHaRouter, self).initialize(process_monitor)
|
||||
|
||||
def process(self, agent):
|
||||
super(DvrEdgeHaRouter, self).process(agent)
|
||||
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)
|
||||
|
||||
def _external_gateway_added(self, ex_gw_port, interface_name,
|
||||
ns_name, preserve_ips):
|
||||
self._plug_external_gateway(ex_gw_port, interface_name, ns_name)
|
||||
|
||||
def _is_this_snat_host(self):
|
||||
return (self.agent_conf.agent_mode
|
||||
== l3_constants.L3_AGENT_MODE_DVR_SNAT)
|
||||
|
||||
def _dvr_internal_network_removed(self, port):
|
||||
super(DvrEdgeHaRouter, self)._dvr_internal_network_removed(port)
|
||||
sn_port = self.get_snat_port_for_internal_port(port, self.snat_ports)
|
||||
if not sn_port:
|
||||
return
|
||||
self._clear_vips(self._get_snat_int_device_name(sn_port['id']))
|
||||
|
||||
def _plug_snat_port(self, port):
|
||||
"""Used by _create_dvr_gateway in DvrEdgeRouter."""
|
||||
interface_name = self._get_snat_int_device_name(port['id'])
|
||||
self.driver.plug(port['network_id'], port['id'],
|
||||
interface_name, port['mac_address'],
|
||||
namespace=self.snat_namespace.name,
|
||||
prefix=dvr_snat_ns.SNAT_INT_DEV_PREFIX)
|
||||
Loading…
Reference in New Issue