OpenStack-Neutron-VPNaaS-代码
目前juno只支持ipsec的vpn 但是其实稍微修改代码pptp/openvpn/gre也都是可以支持的,下面看看vpn服务的代码流程:
默认我们创建好了ide策略、ipsec策略和vpn服务,因为这几个都是直接在数据库中添加记录,不实际做其他事情
下面看看创建一个连接的代码
路径: neutron/services/vpn/plugin.py
类:VPNPluginDb
方法:create_ipsec_site_connection
这个方法会首先创建数据库的ipsec_site_connection记录
def create_ipsec_site_connection(self, context, ipsec_site_connection): ipsec_site_connection = super( VPNDriverPlugin, self).create_ipsec_site_connection( context, ipsec_site_connection)# 1.创建数据库记录 driver = self._get_driver_for_ipsec_site_connection( context, ipsec_site_connection) # 2.获取driver,在配置文件配置的,这里是ipsec driver.create_ipsec_site_connection(context, ipsec_site_connection) #3.调用vpn_service类中的方法开始底层的操作 return ipsec_site_connection
1.
路径:neutron/db/vpn/vpn_db.py
类:VPNPluginDb
方法:create_ipsec_site_connection
这个方法里面会根据ipsec_site_connection来获取vpn服务的id,ike策略id,ipsec策略id
从而得到数据中对应的vpn服务,ide策略,ipsec策略的数据记录,最后创建ipsec_site_connection数据库记录
3.
路径: neutron/services/vpn/service_drivers/ipsec.py
类:VPNPluginDb
方法:create_ipsec_site_connection
调用rpc方法vpnservice_updated
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'])
路径: neutron/services/vpn/device_drivers/ipsec.py
类:IPsecDriver
方法:vpnservice_updated,该方法调用sync方法
def sync(self, context, routers): vpnservices = self.agent_rpc.get_vpn_services_on_host( context, self.host)#获取数据库中有关vpn的记录列表 router_ids = [vpnservice['router_id'] for vpnservice in vpnservices] # Ensure the ipsec process is enabled for vpnservice in vpnservices: process = self.ensure_process(vpnservice['router_id'], vpnservice=vpnservice) #创建openswan进程,初始化文件和目录,数据库字段过滤等等 self._update_nat(vpnservice, self.agent.add_nat_rule) #在路由空间中创建nat规则 process.update() #启动openswan进程 # Delete any IPSec processes that are # associated with routers, but are not running the VPN service. for router in routers: #We are using router id as process_id process_id = router['id'] if process_id not in router_ids: process = self.ensure_process(process_id) self.destroy_router(process_id) # Delete any IPSec processes running # VPN that do not have an associated router. process_ids = [process_id for process_id in self.processes if process_id not in router_ids] for process_id in process_ids: self.destroy_router(process_id) self.report_status(context)
启动openswan进程
def update(self): """Update Status based on vpnservice configuration.""" if self.vpnservice and not self.vpnservice['admin_state_up']: self.disable() else: self.enable() if plugin_utils.in_pending_status(self.vpnservice['status']): self.updated_pending_status = True self.vpnservice['status'] = self.status for ipsec_site_conn in self.vpnservice['ipsec_site_connections']: if plugin_utils.in_pending_status(ipsec_site_conn['status']): conn_id = ipsec_site_conn['id'] conn_status = self.connection_status.get(conn_id) if not conn_status: continue conn_status['updated_pending_status'] = True ipsec_site_conn['status'] = conn_status['status']
enable中调用start方法
def start(self): """Start the process. Note: if there is not namespace yet, just do nothing, and wait next event. """ if not self.namespace: return virtual_private = self._virtual_privates() self.clear_pid() #这里需要清空对应目录中的pid文件,不然会报错 #start pluto IKE keying daemon
#启动IKE守护进程 self._execute([self.binary, 'pluto', '--ctlbase', self.pid_path, '--ipsecdir', self.ipsecd_dir, #'--use-netkey', '--uniqueids', '--nat_traversal', '--secretsfile', self.secrets_file, '--virtual_private', virtual_private ]) #add connections for ipsec_site_conn in self.vpnservice['ipsec_site_connections']: nexthop = self._get_nexthop(ipsec_site_conn['peer_address']) self._execute([self.binary, 'addconn', '--ctlbase', '%s.ctl' % self.pid_path, # '--defaultroutenexthop', nexthop, '--config', self.config_file, ipsec_site_conn['id'] ]) #TODO(nati) fix this when openswan is fixed #Due to openswan bug, this command always exit with 3 #start whack ipsec keying daemon self._execute([self.binary, 'whack', '--ctlbase', self.pid_path, '--listen', ], check_exit_code=False) for ipsec_site_conn in self.vpnservice['ipsec_site_connections']: if not ipsec_site_conn['initiator'] == 'start': continue #initiate ipsec connection self._execute([self.binary, 'whack', '--ctlbase', self.pid_path, '--name', ipsec_site_conn['id'], '--asynchronous', '--initiate' ])