1
# Copyright 2014 OpenStack Foundation.
4
# Licensed under the Apache License, Version 2.0 (the "License"); you may
5
# not use this file except in compliance with the License. You may obtain
6
# a copy of the License at
8
# http://www.apache.org/licenses/LICENSE-2.0
10
# Unless required by applicable law or agreed to in writing, software
11
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13
# License for the specific language governing permissions and limitations
16
from oslo.config import cfg
17
from oslo.utils import importutils
19
from neutron import context as n_context
20
from neutron.openstack.common import log as logging
21
from neutron.services import advanced_service
22
from neutron.services import provider_configuration as provconfig
24
from neutron_vpnaas.extensions import vpnaas
26
LOG = logging.getLogger(__name__)
28
DEVICE_DRIVERS = 'device_drivers'
31
class VPNService(advanced_service.AdvancedService):
32
"""VPN Service observer."""
34
def __init__(self, l3_agent):
35
"""Creates a VPN Service instance with context.
37
DO NOT CALL THIS DIRECTLY! Use the instance() class method to Creates
38
a singleton instance of the service.
40
self.context = n_context.get_admin_context_without_session()
41
super(VPNService, self).__init__(l3_agent)
43
def load_device_drivers(self, host):
44
"""Loads one or more device drivers for VPNaaS."""
46
for device_driver in cfg.CONF.vpnagent.vpn_device_driver:
47
device_driver = provconfig.get_provider_driver_class(
48
device_driver, DEVICE_DRIVERS)
50
self.devices.append(importutils.import_object(device_driver,
53
LOG.debug('Loaded VPNaaS device driver: %s', device_driver)
55
raise vpnaas.DeviceDriverImportError(
56
device_driver=device_driver)
59
# Overridden handlers for L3 agent events.
60
def after_router_added(self, ri):
61
"""Create the router and sync for each loaded device driver."""
62
for device in self.devices:
63
device.create_router(ri.router_id)
64
device.sync(self.context, [ri.router])
66
def after_router_removed(self, ri):
67
"""Remove the router from each loaded device driver."""
68
for device in self.devices:
69
device.destroy_router(ri.router_id)
71
def after_router_updated(self, ri):
72
"""Perform a sync on each loaded device driver."""
73
for device in self.devices:
74
device.sync(self.context, [ri.router])
76
# Device driver methods calling back to L3 agent
77
def get_namespace(self, router_id):
78
"""Get namespace of router.
81
:returns: namespace string.
82
Note if the router is not exist, this function
85
router_info = self.l3_agent.router_info.get(router_id)
88
# Added for handling the distributed Routers within SNAT namespace
89
if router_info.router['distributed']:
90
#return self.get_snat_ns_name(router_id)
91
return self.l3_agent.get_snat_ns_name(router_id)
93
return router_info.ns_name
95
def get_router_based_iptables_manager(self, router_info):
96
"""Returns router based iptables manager
98
In DVR routers the IPsec VPN service should run inside
99
the snat namespace. So the iptables manager used for
100
snat namespace is different from the iptables manager
101
used for the qr namespace in a non dvr based router.
103
This function will check the router type and then will
104
return the right iptables manager. If DVR enabled router
105
it will return the snat_iptables_manager otherwise it will
106
return the legacy iptables_manager.
108
if router_info.router['distributed']:
109
return router_info.snat_iptables_manager
111
return router_info.iptables_manager
113
def add_nat_rule(self, router_id, chain, rule, top=False):
114
"""Add nat rule in namespace.
116
:param router_id: router_id
117
:param chain: a string of chain name
118
:param rule: a string of rule
119
:param top: if top is true, the rule
120
will be placed on the top of chain
121
Note if there is no rotuer, this method do nothing
123
router_info = self.l3_agent.router_info.get(router_id)
126
iptables_manager = self.get_router_based_iptables_manager(router_info)
127
iptables_manager.ipv4['nat'].add_rule(chain, rule, top=top)
129
def remove_nat_rule(self, router_id, chain, rule, top=False):
130
"""Remove nat rule in namespace.
132
:param router_id: router_id
133
:param chain: a string of chain name
134
:param rule: a string of rule
136
needed to have same argument with add_nat_rule
138
router_info = self.l3_agent.router_info.get(router_id)
141
iptables_manager = self.get_router_based_iptables_manager(router_info)
142
iptables_manager.ipv4['nat'].remove_rule(chain, rule, top=top)
144
def iptables_apply(self, router_id):
147
:param router_id: router_id
148
This method do nothing if there is no router
150
router_info = self.l3_agent.router_info.get(router_id)
153
iptables_manager = self.get_router_based_iptables_manager(router_info)
154
iptables_manager.apply()