# vim: tabstop=10 shiftwidth=4 softtabstop=4 # # 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. import netaddr from neutron.common import rpc as n_rpc from neutron import manager from neutron.openstack.common import log as logging from neutron.openstack.common import rpc from neutron.openstack.common.rpc import proxy from neutron.plugins.common import constants from neutron.services.vpn.common import topics from neutron.services.vpn import service_drivers LOG = logging.getLogger(__name__) IPSEC = 'ipsec' BASE_IPSEC_VERSION = '1.0' class IPsecVpnDriverCallBack(object): """Callback for IPSecVpnDriver rpc.""" # history # 1.0 Initial version RPC_API_VERSION = BASE_IPSEC_VERSION def __init__(self, driver): self.driver = driver def create_rpc_dispatcher(self): return n_rpc.PluginRpcDispatcher([self]) def get_vpn_services_on_host(self, context, host=None): """Retuns the vpnservices on the host.""" plugin = self.driver.service_plugin vpnservices = plugin._get_agent_hosting_vpn_services( context, host) return [self.driver._make_vpnservice_dict(vpnservice) for vpnservice in vpnservices] def update_status(self, context, status): """Update status of vpnservices.""" plugin = self.driver.service_plugin plugin.update_status_by_agent(context, status) class IPsecVpnAgentApi(proxy.RpcProxy): """Agent RPC API for IPsecVPNAgent.""" RPC_API_VERSION = BASE_IPSEC_VERSION def _agent_notification(self, context, method, router_id, version=None): """Notify update for the agent. This method will find where is the router, and dispatch notification for the agent. """ adminContext = context.is_admin and context or context.elevated() plugin = manager.NeutronManager.get_service_plugins().get( constants.L3_ROUTER_NAT) if not version: version = self.RPC_API_VERSION l3_agents = plugin.get_l3_agents_hosting_routers( adminContext, [router_id], admin_state_up=True, active=True) for l3_agent in l3_agents: LOG.debug(_('Notify agent at %(topic)s.%(host)s the message ' '%(method)s'), {'topic': topics.IPSEC_AGENT_TOPIC, 'host': l3_agent.host, 'method': method}) self.cast( context, self.make_msg(method), version=version, topic='%s.%s' % (topics.IPSEC_AGENT_TOPIC, l3_agent.host)) def vpnservice_updated(self, context, router_id): """Send update event of vpnservices.""" method = 'vpnservice_updated' self._agent_notification(context, method, router_id) class IPsecVPNDriver(service_drivers.VpnDriver): """VPN Service Driver class for IPsec.""" def __init__(self, service_plugin): self.callbacks = IPsecVpnDriverCallBack(self) self.service_plugin = service_plugin self.conn = rpc.create_connection(new=True) self.conn.create_consumer( topics.IPSEC_DRIVER_TOPIC, self.callbacks.create_rpc_dispatcher(), fanout=False) self.conn.consume_in_thread() self.agent_rpc = IPsecVpnAgentApi( topics.IPSEC_AGENT_TOPIC, BASE_IPSEC_VERSION) @property def service_type(self): return IPSEC def create_ipsec_site_connection(self, context, ipsec_site_connection): vpnservice = self.service_plugin._get_vpnservice( context, ipsec_site_connection['vpnservice_id']) self.agent_rpc.vpnservice_updated(context, vpnservice['router_id']) def update_ipsec_site_connection( self, context, old_ipsec_site_connection, ipsec_site_connection): vpnservice = self.service_plugin._get_vpnservice( context, ipsec_site_connection['vpnservice_id']) self.agent_rpc.vpnservice_updated(context, vpnservice['router_id']) def delete_ipsec_site_connection(self, context, ipsec_site_connection): vpnservice = self.service_plugin._get_vpnservice( context, ipsec_site_connection['vpnservice_id']) self.agent_rpc.vpnservice_updated(context, vpnservice['router_id']) def create_ikepolicy(self, context, ikepolicy): pass def delete_ikepolicy(self, context, ikepolicy): pass def update_ikepolicy(self, context, old_ikepolicy, ikepolicy): pass def create_ipsecpolicy(self, context, ipsecpolicy): pass def delete_ipsecpolicy(self, context, ipsecpolicy): pass def update_ipsecpolicy(self, context, old_ipsec_policy, ipsecpolicy): pass def create_vpnservice(self, context, vpnservice): pass def update_vpnservice(self, context, old_vpnservice, vpnservice): self.agent_rpc.vpnservice_updated(context, vpnservice['router_id']) def delete_vpnservice(self, context, vpnservice): self.agent_rpc.vpnservice_updated(context, vpnservice['router_id']) def _make_vpnservice_dict(self, vpnservice): """Convert vpnservice information for vpn agent. also converting parameter name for vpn agent driver """ vpnservice_dict = dict(vpnservice) vpnservice_dict['ipsec_site_connections'] = [] vpnservice_dict['subnet'] = dict( vpnservice.subnet) vpnservice_dict['external_ip'] = vpnservice.router.gw_port[ 'fixed_ips'][0]['ip_address'] for ipsec_site_connection in vpnservice.ipsec_site_connections: ipsec_site_connection_dict = dict(ipsec_site_connection) try: netaddr.IPAddress(ipsec_site_connection['peer_id']) except netaddr.core.AddrFormatError: ipsec_site_connection['peer_id'] = ( '@' + ipsec_site_connection['peer_id']) ipsec_site_connection_dict['ikepolicy'] = dict( ipsec_site_connection.ikepolicy) ipsec_site_connection_dict['ipsecpolicy'] = dict( ipsec_site_connection.ipsecpolicy) vpnservice_dict['ipsec_site_connections'].append( ipsec_site_connection_dict) peer_cidrs = [ peer_cidr.cidr for peer_cidr in ipsec_site_connection.peer_cidrs] ipsec_site_connection_dict['peer_cidrs'] = peer_cidrs return vpnservice_dict