neutron-vpnaas/neutron/services/vpn/agent.py
Carl Baldwin 29c7d39a65 Refactor _process_routers to handle a single router
The method _process_routers no longer handles multiple routers.  The
only caller of this method would construct a list of exactly one
router in order to make the call.  This made the for loop unnecessary.
The method's logic is too heavy for its current purpose.  This commit
removes much of the weight.

The use of the sets in this method is also no longer necessary.  It
became clear that all of it boiled down to "if the router is not
compatible with with this agent but it is known in router_info from
before then we need to remove it."  This is an exceptional condition
that shouldn't be handled in this method so I raise an exception and
handle it in process_router_update where other router removal is
handled.  Logging was added for this exceptional condition.

The eventlet pool was also obsolete.  It was used to spawn two methods
and there was a waitall at the end.  The other refactoring made it
clear that the two spawns were mutually exclusive.  There was only one
thread spawned for any given invocation of the method and the eventlet
pool is overkill.

Change-Id: Ibeac591b08565d10b2a9730e25a54f2cd11fc2bc
Closes-Bug: #1378398
2014-10-09 18:51:13 +00:00

147 lines
4.9 KiB
Python

# Copyright 2013, Nachi Ueno, NTT I3, Inc.
# 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.config import cfg
from neutron.agent import l3_agent
from neutron.extensions import vpnaas
from neutron.openstack.common import importutils
vpn_agent_opts = [
cfg.MultiStrOpt(
'vpn_device_driver',
default=['neutron.services.vpn.device_drivers.'
'ipsec.OpenSwanDriver'],
help=_("The vpn device drivers Neutron will use")),
]
cfg.CONF.register_opts(vpn_agent_opts, 'vpnagent')
class VPNAgent(l3_agent.L3NATAgentWithStateReport):
"""VPNAgent class which can handle vpn service drivers."""
def __init__(self, host, conf=None):
super(VPNAgent, self).__init__(host=host, conf=conf)
self.setup_device_drivers(host)
def setup_device_drivers(self, host):
"""Setting up device drivers.
:param host: hostname. This is needed for rpc
Each devices will stays as processes.
They will communicate with
server side service plugin using rpc with
device specific rpc topic.
:returns: None
"""
device_drivers = cfg.CONF.vpnagent.vpn_device_driver
self.devices = []
for device_driver in device_drivers:
try:
self.devices.append(
importutils.import_object(device_driver, self, host))
except ImportError:
raise vpnaas.DeviceDriverImportError(
device_driver=device_driver)
def get_namespace(self, router_id):
"""Get namespace of router.
:router_id: router_id
:returns: namespace string.
Note if the router is not exist, this function
returns None
"""
router_info = self.router_info.get(router_id)
if not router_info:
return
return router_info.ns_name
def add_nat_rule(self, router_id, chain, rule, top=False):
"""Add nat rule in namespace.
:param router_id: router_id
:param chain: a string of chain name
:param rule: a string of rule
:param top: if top is true, the rule
will be placed on the top of chain
Note if there is no rotuer, this method do nothing
"""
router_info = self.router_info.get(router_id)
if not router_info:
return
router_info.iptables_manager.ipv4['nat'].add_rule(
chain, rule, top=top)
def remove_nat_rule(self, router_id, chain, rule, top=False):
"""Remove nat rule in namespace.
:param router_id: router_id
:param chain: a string of chain name
:param rule: a string of rule
:param top: unused
needed to have same argument with add_nat_rule
"""
router_info = self.router_info.get(router_id)
if not router_info:
return
router_info.iptables_manager.ipv4['nat'].remove_rule(
chain, rule, top=top)
def iptables_apply(self, router_id):
"""Apply IPtables.
:param router_id: router_id
This method do nothing if there is no router
"""
router_info = self.router_info.get(router_id)
if not router_info:
return
router_info.iptables_manager.apply()
def _router_added(self, router_id, router):
"""Router added event.
This method overwrites parent class method.
:param router_id: id of added router
:param router: dict of rotuer
"""
super(VPNAgent, self)._router_added(router_id, router)
for device in self.devices:
device.create_router(router_id)
def _router_removed(self, router_id):
"""Router removed event.
This method overwrites parent class method.
:param router_id: id of removed router
"""
super(VPNAgent, self)._router_removed(router_id)
for device in self.devices:
device.destroy_router(router_id)
def _process_router_if_compatible(self, router):
"""Router sync event.
This method overwrites parent class method.
:param router: a router
"""
super(VPNAgent, self)._process_router_if_compatible(router)
for device in self.devices:
device.sync(self.context, [router])
def main():
l3_agent.main(
manager='neutron.services.vpn.agent.VPNAgent')