components/openstack/neutron/files/services/vpn/device_drivers/solaris_ipsec.py
changeset 6378 9d70f1e25eba
parent 5630 dff517d5c829
child 6848 8e252a37ed0d
equal deleted inserted replaced
6377:12498e4ad8f9 6378:9d70f1e25eba
   221                 vpn_tunnels.append(ifname)
   221                 vpn_tunnels.append(ifname)
   222 
   222 
   223     return vpn_tunnels
   223     return vpn_tunnels
   224 
   224 
   225 
   225 
   226 def disable_services():
   226 def disable_smf_services():
   227     """Disable IPsec Policy/IKE smf(5) services using rad(1).
   227     """Disable IPsec Policy/IKE smf(5) services using rad(1).
   228     """
   228     """
   229     ike_svc = "network/ipsec/ike"
   229     ike_svc = "network/ipsec/ike"
   230     ipsec_svc = "network/ipsec/policy"
   230     ipsec_svc = "network/ipsec/policy"
   231     global restarting
   231     global restarting
   279         # configured or not. The easiest way to determine if VPNaaS is
   279         # configured or not. The easiest way to determine if VPNaaS is
   280         # configured is to check if there are any IP tunnels configured.
   280         # configured is to check if there are any IP tunnels configured.
   281         ifs = get_vpn_interfaces()
   281         ifs = get_vpn_interfaces()
   282         if ifs:
   282         if ifs:
   283             whack_ike_rules()
   283             whack_ike_rules()
   284             disable_services()
   284             disable_smf_services()
   285             delete_tunnels(ifs, False)
   285             delete_tunnels(ifs, False)
   286 
   286 
   287 
   287 
   288 def whack_ike_rules():
   288 def whack_ike_rules():
   289         cmd = ['/usr/bin/pfexec', '/usr/sbin/ikeadm', '-n', 'dump', 'rule']
   289         cmd = ['/usr/bin/pfexec', '/usr/sbin/ikeadm', '-n', 'dump', 'rule']
   446         self.ipsec_svc = "network/ipsec/policy"
   446         self.ipsec_svc = "network/ipsec/policy"
   447         self.packet_logging = cfg.CONF.solaris.packet_logging
   447         self.packet_logging = cfg.CONF.solaris.packet_logging
   448         self.logging_level = cfg.CONF.solaris.logger_level
   448         self.logging_level = cfg.CONF.solaris.logger_level
   449         self.generate_config(vpnservice)
   449         self.generate_config(vpnservice)
   450         self.dump_config()
   450         self.dump_config()
   451         LOG.info("Configuring vpn-service: %s." % vpnservice)
   451         LOG.debug("Configuring router: %s" % process_id)
       
   452         LOG.debug("Configuring vpn-service: %s." % vpnservice)
   452 
   453 
   453     def dump_config(self):
   454     def dump_config(self):
   454         if not self.vpnservice:
   455         if not self.vpnservice:
   455             LOG.warn("No VPNs configured.")
   456             LOG.info("No VPNs configured.")
   456             return
   457             return
   457 
   458 
   458         connections = self.vpnservice['ipsec_site_connections']
   459         connections = self.vpnservice['ipsec_site_connections']
   459         LOG.warn("New VPN configuration:")
   460         LOG.info("New VPN configuration:")
   460         for site in connections:
   461         for site in connections:
   461             LOG.info("Site ID: \"%s\"" % site['id'])
   462             LOG.info("Site ID: \"%s\"" % site['id'])
   462             LOG.info("\tTenant ID: \"%s\"" % site['tenant_id'])
   463             LOG.info("\tTenant ID: \"%s\"" % site['tenant_id'])
   463             LOG.info("\tIKE policy ID: \"%s\"" % site['ikepolicy_id'])
   464             LOG.info("\tIKE policy ID: \"%s\"" % site['ikepolicy_id'])
   464             LOG.info("\tIPsec policy ID: \"%s\"" % site['ipsecpolicy_id'])
   465             LOG.info("\tIPsec policy ID: \"%s\"" % site['ipsecpolicy_id'])
   468             LOG.info("\tStatus: \"%s\"" % site['status'])
   469             LOG.info("\tStatus: \"%s\"" % site['status'])
   469 
   470 
   470     def translate_dialect(self):
   471     def translate_dialect(self):
   471         if not self.vpnservice:
   472         if not self.vpnservice:
   472             return
   473             return
   473         LOG.warn("Generating Solaris IKE/IPsec config files.")
   474         LOG.info("Generating Solaris IKE/IPsec config files.")
   474         for ipsec_site_conn in self.vpnservice['ipsec_site_connections']:
   475         for ipsec_site_conn in self.vpnservice['ipsec_site_connections']:
   475             self._dialect(ipsec_site_conn, 'initiator')
   476             self._dialect(ipsec_site_conn, 'initiator')
   476             self._dialect(ipsec_site_conn['ikepolicy'], 'ike_version')
   477             self._dialect(ipsec_site_conn['ikepolicy'], 'ike_version')
   477             for key in ['encryption_algorithm', 'auth_algorithm', 'pfs']:
   478             for key in ['encryption_algorithm', 'auth_algorithm', 'pfs']:
   478                 self._dialect(ipsec_site_conn['ikepolicy'], key)
   479                 self._dialect(ipsec_site_conn['ikepolicy'], key)
   524 
   525 
   525     def gen_config_content(self, template_file, vpnservice):
   526     def gen_config_content(self, template_file, vpnservice):
   526         """Generate IPsec configuration files using templates.
   527         """Generate IPsec configuration files using templates.
   527         """
   528         """
   528         template = _get_template(template_file)
   529         template = _get_template(template_file)
   529 
       
   530         return template.render(
   530         return template.render(
   531             {'vpnservice': vpnservice,
   531             {'vpnservice': vpnservice,
   532              'state_path': cfg.CONF.state_path})
   532              'state_path': cfg.CONF.state_path})
   533 
   533 
   534     @abc.abstractmethod
   534     @abc.abstractmethod
   552                 The l3_agent is being shutdown.
   552                 The l3_agent is being shutdown.
   553         """
   553         """
   554         LOG.debug("Getting status of IKE daemon")
   554         LOG.debug("Getting status of IKE daemon")
   555         global being_shutdown
   555         global being_shutdown
   556         if being_shutdown:
   556         if being_shutdown:
   557             LOG.warn("VPNaaS being shutdown")
   557             LOG.info("VPNaaS being shutdown")
   558             return False
   558             return False
   559 
   559 
   560         # IKE is running. Update status of all connections
   560         # IKE is running. Update status of all connections
   561         # IKE knows about.
   561         # IKE knows about.
   562         self.get_connection_status()
   562         self.get_connection_status()
   628            it back again.
   628            it back again.
   629 
   629 
   630            This should be revisited if we support more than one router.
   630            This should be revisited if we support more than one router.
   631         """
   631         """
   632         if not self.vpnservice:
   632         if not self.vpnservice:
   633             LOG.warn("No VPNs configured.")
   633             LOG.info("No VPNs configured.")
   634             return
   634             return
   635 
   635 
   636         status_changed_vpn_services = []
   636         status_changed_vpn_services = []
   637         new_status = self.copy_process_status(self)
   637         new_status = self.copy_process_status(self)
   638         LOG.info("Marking all site connections %s" % new_state)
   638         LOG.info("Marking all site connections %s" % new_state)
   639         for conn in new_status[IPSEC_CONNS]:
   639         for conn in new_status[IPSEC_CONNS]:
   640             new_status[IPSEC_CONNS][conn] = {
   640             new_status[IPSEC_CONNS][conn] = {
   641                 'status': new_state,
   641                 'status': new_state,
   642                 'updated_pending_status': True
   642                 'updated_pending_status': True
   643             }
   643             }
   644         status_changed_vpn_services.append(new_status)
   644             status_changed_vpn_services.append(new_status)
       
   645 
   645         self.agent_rpc.update_status(
   646         self.agent_rpc.update_status(
   646             self.context,
   647             self.context,
   647             status_changed_vpn_services)
   648             status_changed_vpn_services)
   648 
   649 
   649     def get_connection_status(self):
   650     def get_connection_status(self):
   655         LOG.debug("Getting Connection Status")
   656         LOG.debug("Getting Connection Status")
   656         global being_shutdown
   657         global being_shutdown
   657         global restarting
   658         global restarting
   658 
   659 
   659         if not self.vpnservice:
   660         if not self.vpnservice:
   660             LOG.warn("No VPNs configured.")
   661             LOG.info("No VPNs configured.")
   661             return True
   662             return True
   662 
   663 
   663         if restarting:
   664         if restarting:
   664             LOG.warn("IKE restarting")
   665             LOG.info("IKE restarting")
   665             return True
   666             return True
   666         self.ike_was_running = self.ike_running
   667         self.ike_was_running = self.ike_running
   667         if not self.get_status():
   668         if not self.get_status():
   668             if being_shutdown:
   669             if being_shutdown:
   669                 self.ikeadm_fails = 0
   670                 self.ikeadm_fails = 0
   670             else:
   671             else:
   671                 LOG.warn("IKE daemon is not running.")
   672                 LOG.info("IKE daemon is not running.")
   672                 self.ikeadm_fails += 1
   673                 self.ikeadm_fails += 1
   673             if self.ikeadm_fails > self.ikeadm_maxfails:
   674             if self.ikeadm_fails > self.ikeadm_maxfails:
   674                 LOG.warn("IKE daemon still not running, something's wrong.")
   675                 LOG.info("IKE daemon still not running, something's wrong.")
   675                 restarting = True
   676                 restarting = True
   676                 being_shutdown = True
   677                 being_shutdown = True
   677                 self.mark_connections(constants.DOWN)
   678                 self.mark_connections(constants.DOWN)
   678                 restarting = False
   679                 restarting = False
   679                 being_shutdown = False
   680                 being_shutdown = False
   681                 self.ike_running = False
   682                 self.ike_running = False
   682 
   683 
   683             return False
   684             return False
   684 
   685 
   685         if self.ike_running and not self.ike_was_running:
   686         if self.ike_running and not self.ike_was_running:
   686             LOG.warn("IKE daemon has been restarted")
   687             LOG.info("IKE daemon has been restarted")
   687             self.mark_connections(constants.ACTIVE)
   688             self.mark_connections(constants.ACTIVE)
   688             return True
   689             return True
   689         for connection_id in self.connection_ids:
   690         for connection_id in self.connection_ids:
   690             if not self.connection_status.get(connection_id):
   691             if not self.connection_status.get(connection_id):
   691                 self.connection_status[connection_id] = {
   692                 self.connection_status[connection_id] = {
   748 
   749 
   749        Solaris commands mentioned above are called directly using pfexec(1).
   750        Solaris commands mentioned above are called directly using pfexec(1).
   750     """
   751     """
   751     def __init__(self, conf, process_id,
   752     def __init__(self, conf, process_id,
   752                  vpnservice, namespace):
   753                  vpnservice, namespace):
   753         LOG.warn("Configuring IPsec/IKE")
   754         LOG.info("Configuring IPsec/IKE")
   754         super(SolarisIPsecProcess, self).__init__(
   755         super(SolarisIPsecProcess, self).__init__(
   755             conf, process_id,
   756             conf, process_id,
   756             vpnservice, namespace)
   757             vpnservice, namespace)
   757         self.secrets_file = os.path.join(
   758         self.secrets_file = os.path.join(
   758             self.etc_dir, 'secret/ike.preshared')
   759             self.etc_dir, 'secret/ike.preshared')
   808         self.generate_config_file(
   809         self.generate_config_file(
   809             'ike/ikev2.preshared',
   810             'ike/ikev2.preshared',
   810             self.conf.solaris.ikev2_secret_template,
   811             self.conf.solaris.ikev2_secret_template,
   811             self.vpnservice)
   812             self.vpnservice)
   812 
   813 
       
   814     def start_ipsec(self):
       
   815         self.service_setprops()
       
   816         self.enable_smf_services()
       
   817 
   813     def add_tunnels(self):
   818     def add_tunnels(self):
   814         """Add tunnel interfaces using dladm(1m) and
   819         """Add tunnel interfaces using dladm(1m) and
   815            ipadm(1m).
   820            ipadm(1m).
   816 
   821 
   817         """
   822         """
   845             try:
   850             try:
   846                 stdout, stderr = processutils.execute(*cmd)
   851                 stdout, stderr = processutils.execute(*cmd)
   847             except processutils.ProcessExecutionError as stderr:
   852             except processutils.ProcessExecutionError as stderr:
   848                 m = re.search('object already exists', str(stderr))
   853                 m = re.search('object already exists', str(stderr))
   849                 if m:
   854                 if m:
   850                     LOG.warn("Tunnel with Outer IP: %s -> %s, Inner: "
   855                     LOG.info("Tunnel with Outer IP: %s -> %s, Inner: "
   851                              "%s -> %s already exists."
   856                              "%s -> %s already exists."
   852                              % (o_local, o_remote, i_local, i_remote))
   857                              % (o_local, o_remote, i_local, i_remote))
   853                 else:
   858                 else:
   854                     LOG.warn("Error adding tunnel - Outer IP: %s -> %s,"
   859                     LOG.info("Error adding tunnel - Outer IP: %s -> %s,"
   855                              "Inner: %s -> %s"
   860                              "Inner: %s -> %s"
   856                              % (o_local, o_remote, i_local, i_remote))
   861                              % (o_local, o_remote, i_local, i_remote))
   857                     LOG.warn("\"%s\"" % stderr)
   862                     LOG.info("\"%s\"" % stderr)
   858                     self.badboys.append(site)
   863                     self.badboys.append(site)
   859                     continue
   864                     continue
   860 
   865 
   861             LOG.info(
   866             LOG.info(
   862                 "Added tunnel - Outer IP: %s -> %s, Inner: %s -> %s"
   867                 "Added tunnel - Outer IP: %s -> %s, Inner: %s -> %s"
   865             cmd = ['/usr/bin/pfexec', 'ipadm', 'create-ip', '-t', tun_name]
   870             cmd = ['/usr/bin/pfexec', 'ipadm', 'create-ip', '-t', tun_name]
   866             try:
   871             try:
   867                 stdout, stderr = processutils.execute(*cmd)
   872                 stdout, stderr = processutils.execute(*cmd)
   868             except processutils.ProcessExecutionError as stderr:
   873             except processutils.ProcessExecutionError as stderr:
   869                 if re.search('Interface already exists', str(stderr)):
   874                 if re.search('Interface already exists', str(stderr)):
   870                     LOG.warn("Tunnel interface: '%s' already exists." %
   875                     LOG.info("Tunnel interface: '%s' already exists." %
   871                              tun_name)
   876                              tun_name)
   872                 else:
   877                 else:
   873                     LOG.warn("Error creating tunnel")
   878                     LOG.info("Error creating tunnel")
   874                     LOG.warn("\"%s\"" % stderr)
   879                     LOG.info("\"%s\"" % stderr)
   875                     self.badboys.append(site)
   880                     self.badboys.append(site)
   876                     continue
   881                     continue
   877             cmd = ['/usr/bin/pfexec', 'ipadm', 'create-addr', '-t',  '-T',
   882             cmd = ['/usr/bin/pfexec', 'ipadm', 'create-addr', '-t',  '-T',
   878                    'static', '-a', "local=%s,remote=%s" % (i_local, i_remote),
   883                    'static', '-a', "local=%s,remote=%s" % (i_local, i_remote),
   879                    tun_name]
   884                    tun_name]
   880             try:
   885             try:
   881                 stdout, stderr = processutils.execute(*cmd)
   886                 stdout, stderr = processutils.execute(*cmd)
   882             except processutils.ProcessExecutionError as stderr:
   887             except processutils.ProcessExecutionError as stderr:
   883                 LOG.warn("Error creating tunnel")
   888                 LOG.info("Error creating tunnel")
   884                 LOG.warn("\"%s\"" % stderr)
   889                 LOG.info("\"%s\"" % stderr)
   885                 self.badboys.append(site)
   890                 self.badboys.append(site)
   886                 continue
   891                 continue
   887 
   892 
   888             cmd = ['/usr/bin/pfexec', 'route', '-n', 'add', 'net', peer_cidr,
   893             cmd = ['/usr/bin/pfexec', 'route', '-n', 'add', 'net', peer_cidr,
   889                    i_remote]
   894                    i_remote]
   891             try:
   896             try:
   892                 stdout, stderr = processutils.execute(*cmd)
   897                 stdout, stderr = processutils.execute(*cmd)
   893             except processutils.ProcessExecutionError as stderr:
   898             except processutils.ProcessExecutionError as stderr:
   894                 m = re.search('entry exists', str(stderr))
   899                 m = re.search('entry exists', str(stderr))
   895                 if m:
   900                 if m:
   896                     LOG.warn("Route already exists.")
   901                     LOG.info("Route already exists.")
   897                 else:
   902                 else:
   898                     LOG.warn("Error adding route.")
   903                     LOG.info("Error adding route.")
   899                     self.badboys.append(site)
   904                     self.badboys.append(site)
   900                     continue
   905                     continue
   901 
   906 
   902             # Now for some Policy Based Routing (PBR) voodoo. When a Neutron
   907             # Now for some Policy Based Routing (PBR) voodoo. When a Neutron
   903             # subnet is added to a Neutron router, it adds a PBR rule that
   908             # subnet is added to a Neutron router, it adds a PBR rule that
   941                             addrobj_addr.startswith('l3i')):
   946                             addrobj_addr.startswith('l3i')):
   942                         addrobj = addrobj_addr.split(':')[0]
   947                         addrobj = addrobj_addr.split(':')[0]
   943                         ifname = addrobj.split('/')[0]
   948                         ifname = addrobj.split('/')[0]
   944                         break
   949                         break
   945             if not ifname:
   950             if not ifname:
   946                 LOG.warn("Failed to find IP interface corresponding to "
   951                 LOG.info("Failed to find IP interface corresponding to "
   947                          "VPN subnet: %s. Skipping bypass rule for '%s'" %
   952                          "VPN subnet: %s. Skipping bypass rule for '%s'" %
   948                          (subnet['cidr'], tun_name))
   953                          (subnet['cidr'], tun_name))
   949                 continue
   954                 continue
   950 
   955 
   951             label = 'vpn_%s_%s' % (ifname, peer_cidr.replace('/', '_'))
   956             label = 'vpn_%s_%s' % (ifname, peer_cidr.replace('/', '_'))
   996         LOG.debug("Looking for IPsec site connections.")
  1001         LOG.debug("Looking for IPsec site connections.")
   997         cmd = ['/usr/bin/pfexec', '/usr/sbin/ikeadm', '-n', 'dump', 'rule']
  1002         cmd = ['/usr/bin/pfexec', '/usr/sbin/ikeadm', '-n', 'dump', 'rule']
   998         try:
  1003         try:
   999             status, stderr = processutils.execute(*cmd)
  1004             status, stderr = processutils.execute(*cmd)
  1000         except processutils.ProcessExecutionError as stderr:
  1005         except processutils.ProcessExecutionError as stderr:
  1001             LOG.warn("IKE daemon does not appear to be running.")
  1006             LOG.info("IKE daemon does not appear to be running.")
  1002             LOG.debug("\"%s\"" % stderr)
  1007             LOG.debug("\"%s\"" % stderr)
  1003             return False
  1008             return False
  1004 
  1009 
  1005         self.ikeadm_fails = 0
  1010         self.ikeadm_fails = 0
  1006         self.connection_ids = []
  1011         self.connection_ids = []
  1020         """Restart VPNaaS.
  1025         """Restart VPNaaS.
  1021            Some optimization possible here, a restart does not
  1026            Some optimization possible here, a restart does not
  1022            require property setting. If we are not running, we
  1027            require property setting. If we are not running, we
  1023            don't need to disable stuff. See self.start(), self.stop()
  1028            don't need to disable stuff. See self.start(), self.stop()
  1024         """
  1029         """
  1025         LOG.warn("Restarting VPNaaS")
  1030         LOG.info("Restarting VPNaaS")
  1026         self.stop()
  1031         self.stop()
  1027         self.start()
  1032         self.start()
  1028         return
  1033         return
  1029 
  1034 
  1030     def start(self):
  1035     def start(self):
  1031         """Start VPNaaS.
  1036         """Start VPNaaS.
  1032         """
  1037         """
  1033         LOG.warn("Start")
  1038         LOG.info("Start")
  1034         if not self.vpnservice:
  1039         if not self.vpnservice:
  1035             LOG.warn("No VPNs configured.")
  1040             LOG.info("No VPNs configured.")
  1036             return
  1041             return
  1037 
  1042 
  1038         LOG.warn("Starting VPNaaS")
  1043         LOG.info("Starting VPNaaS")
  1039         self.ensure_configs()
  1044         self.ensure_configs()
  1040         self.service_setprops()
       
  1041         self.enable_services()
       
  1042         self.add_tunnels()
  1045         self.add_tunnels()
  1043 
  1046 
  1044     def stop(self):
  1047     def stop(self):
  1045         self.connection_status = {}
  1048         self.connection_status = {}
  1046 
  1049 
  1047         self.get_status()
  1050         self.get_status()
  1048         self.flush_sas()
  1051         self.flush_sas()
  1049         self.mark_connections(constants.DOWN)
  1052         self.mark_connections(constants.DOWN)
  1050         LOG.debug("Disable IPsec policy and IKE SMF(5) services")
  1053         LOG.debug("Disable IPsec policy and IKE SMF(5) services")
  1051         disable_services()
  1054         disable_smf_services()
  1052 
  1055 
  1053     def flush_sas(self):
  1056     def flush_sas(self):
  1054         """Flush IPsec SAs, this should be done with rad(1) eventually.
  1057         """Flush IPsec SAs, this should be done with rad(1) eventually.
  1055            For disable ignore any errors.
  1058            For disable ignore any errors.
  1056         """
  1059         """
  1117                                    [self.logging_level])
  1120                                    [self.logging_level])
  1118             instance.refresh()
  1121             instance.refresh()
  1119 
  1122 
  1120         rad_connection.close()
  1123         rad_connection.close()
  1121 
  1124 
  1122     def enable_services(self):
  1125     def enable_smf_services(self):
  1123         """Enable IPsec Policy/IKE smf(5) services using rad(1).
  1126         """Enable IPsec Policy/IKE smf(5) services using rad(1).
  1124         """
  1127         """
  1125         LOG.info("Enabling IPsec policy.")
  1128         LOG.info("Enabling IPsec policy.")
  1126         rad_connection = rad.connect.connect_unix()
  1129         rad_connection = rad.connect.connect_unix()
  1127         instance = rad_connection.get_object(
  1130         instance = rad_connection.get_object(
  1136             rad.client.ADRGlobPattern({'service': self.ike_svc,
  1139             rad.client.ADRGlobPattern({'service': self.ike_svc,
  1137                                        'instance': self.ike_version}))
  1140                                        'instance': self.ike_version}))
  1138         instance.enable(True)
  1141         instance.enable(True)
  1139 
  1142 
  1140         if self.packet_logging:
  1143         if self.packet_logging:
  1141             LOG.warn("Enabling IPsec packet logger.")
  1144             LOG.info("Enabling IPsec packet logger.")
  1142             instance = rad_connection.get_object(
  1145             instance = rad_connection.get_object(
  1143                 smfb.Instance(),
  1146                 smfb.Instance(),
  1144                 rad.client.ADRGlobPattern({'service': self.ipsec_svc,
  1147                 rad.client.ADRGlobPattern({'service': self.ipsec_svc,
  1145                                            'instance': 'logger'}))
  1148                                            'instance': 'logger'}))
  1146             instance.enable(True)
  1149             instance.enable(True)
  1294                 LOG.info(
  1297                 LOG.info(
  1295                     "Status of router ID: \"%s\" has changed." % process.id)
  1298                     "Status of router ID: \"%s\" has changed." % process.id)
  1296                 new_status = self.copy_process_status(process)
  1299                 new_status = self.copy_process_status(process)
  1297 
  1300 
  1298                 if not self.check_connection_cache(process, new_status):
  1301                 if not self.check_connection_cache(process, new_status):
  1299                     LOG.debug("Connection Cache stale.")
  1302                     LOG.debug("Connection Cache has been updated.")
  1300 
  1303 
  1301                 status_changed_vpn_services.append(new_status)
  1304                 status_changed_vpn_services.append(new_status)
       
  1305 
       
  1306                 self.unset_updated_pending_status(process)
       
  1307                 self.unset_cache_status(process)
  1302                 self.process_status_cache[process.id] = (
  1308                 self.process_status_cache[process.id] = (
  1303                     self.copy_process_status(process))
  1309                     self.copy_process_status(process))
  1304                 self.unset_updated_pending_status(process)
       
  1305 
  1310 
  1306         if status_changed_vpn_services:
  1311         if status_changed_vpn_services:
  1307             LOG.warn("Updating VPN Site status in database.")
  1312             LOG.info("Status of VPN services have changed %s" %
       
  1313                      status_changed_vpn_services)
  1308             self.agent_rpc.update_status(context, status_changed_vpn_services)
  1314             self.agent_rpc.update_status(context, status_changed_vpn_services)
  1309 
  1315 
  1310     @lockutils.synchronized('vpn-agent', 'neutron-')
  1316     @lockutils.synchronized('vpn-agent', 'neutron-')
  1311     @abc.abstractmethod
  1317     @abc.abstractmethod
  1312     def create_process(self, process_id, vpnservice, namespace):
  1318     def create_process(self, process_id, vpnservice, namespace):
  1314 
  1320 
  1315     def enable_vpn(self, process_id, vpnservice=None):
  1321     def enable_vpn(self, process_id, vpnservice=None):
  1316         """Configure IPsec, IKE, tunnels on this router.
  1322         """Configure IPsec, IKE, tunnels on this router.
  1317         """
  1323         """
  1318         LOG.info("Configuring VPNaaS on router: \"%s\"" % process_id)
  1324         LOG.info("Configuring VPNaaS on router: \"%s\"" % process_id)
       
  1325         if not vpnservice:
       
  1326             LOG.info("No VPNs configured")
       
  1327             return
       
  1328 
  1319         process = self.processes.get(process_id)
  1329         process = self.processes.get(process_id)
  1320         if not process or not process.namespace:
  1330         if not process or not process.namespace:
  1321             namespace = ""
  1331             namespace = ""
  1322             process = self.create_process(
  1332             process = self.create_process(
  1323                 process_id,
  1333                 process_id,
  1324                 vpnservice,
  1334                 vpnservice,
  1325                 namespace)
  1335                 namespace)
  1326             self.processes[process_id] = process
  1336             self.processes[process_id] = process
  1327         elif vpnservice:
  1337         elif vpnservice:
  1328             process.generate_config(vpnservice)
  1338             process.generate_config(vpnservice)
       
  1339 
  1329         return process
  1340         return process
  1330 
  1341 
  1331     def create_router(self, process_id):
  1342     def create_router(self, process_id):
  1332         """"Handling create router event.
  1343         """"Handling create router event.
  1333         """
  1344         """
  1368            process.status *calls* active.
  1379            process.status *calls* active.
  1369            There is a lot of debug here, because if this function fails
  1380            There is a lot of debug here, because if this function fails
  1370            nothing gets updated.
  1381            nothing gets updated.
  1371         """
  1382         """
  1372         if process.updated_pending_status:
  1383         if process.updated_pending_status:
  1373             LOG.debug("updated_pending_status: True")
  1384             LOG.debug("Status of VPN services have changed")
  1374             return True
  1385             return True
       
  1386 
  1375         if process.status != previous_status['status']:
  1387         if process.status != previous_status['status']:
  1376             LOG.debug("Current Router status != Previous status")
  1388             LOG.debug("Current Router status != Previous status")
       
  1389             LOG.debug("%s/%s" % (process.status, previous_status['status']))
  1377             return True
  1390             return True
  1378         ps = previous_status['ipsec_site_connections']
  1391         ps = previous_status['ipsec_site_connections']
  1379         if process.connection_status != ps:
  1392         if process.connection_status != ps:
  1380             LOG.debug("Current VPN status != Previous status")
  1393             LOG.debug("Current VPN status != Previous status")
       
  1394             LOG.debug("%s/%s" % (process.connection_status, ps))
  1381             return True
  1395             return True
  1382 
  1396 
  1383         found_previous_connection = False
  1397         found_previous_connection = False
  1384 
  1398 
  1385         ps = previous_status['ipsec_site_connections']
  1399         ps = previous_status['ipsec_site_connections']
  1389                        ps[ipsec_site_conn]['updated_pending_status']))
  1403                        ps[ipsec_site_conn]['updated_pending_status']))
  1390             found_previous_connection = False
  1404             found_previous_connection = False
  1391 
  1405 
  1392             for new_ipsec_site_conn in process.connection_ids:
  1406             for new_ipsec_site_conn in process.connection_ids:
  1393                 if ipsec_site_conn == new_ipsec_site_conn:
  1407                 if ipsec_site_conn == new_ipsec_site_conn:
  1394                     LOG.debug("Found entry for ID: '%s'" %
  1408                     LOG.debug("Found existing entry for ID: '%s'" %
  1395                               new_ipsec_site_conn)
  1409                               new_ipsec_site_conn)
  1396                     found_previous_connection = True
  1410                     found_previous_connection = True
  1397             if not found_previous_connection:
  1411             if not found_previous_connection:
  1398                 LOG.debug("Unable to find entry for ID: '%s'" %
  1412                 LOG.debug("Unable to find existing entry for ID: '%s'" %
  1399                           ipsec_site_conn)
  1413                           ipsec_site_conn)
       
  1414                 ps[ipsec_site_conn]['status'] = constants.DOWN
       
  1415                 ps[ipsec_site_conn]['updated_pending_status'] = True
  1400                 return True
  1416                 return True
  1401             continue
  1417             continue
  1402 
  1418 
  1403         return False
  1419         return False
       
  1420 
       
  1421     def unset_cache_status(self, process):
       
  1422         self.process_status_cache[process.id]['updated_pending_status'] = False
       
  1423         cache = self.process_status_cache[process.id]
       
  1424         for pending in cache['ipsec_site_connections'].values():
       
  1425             pending['updated_pending_status'] = False
  1404 
  1426 
  1405     def unset_updated_pending_status(self, process):
  1427     def unset_updated_pending_status(self, process):
  1406         process.updated_pending_status = False
  1428         process.updated_pending_status = False
  1407         for connection_status in process.connection_status.values():
  1429         for connection_status in process.connection_status.values():
       
  1430             LOG.debug("Unset Pending Status %s" % connection_status)
  1408             connection_status['updated_pending_status'] = False
  1431             connection_status['updated_pending_status'] = False
  1409 
  1432 
  1410     def copy_process_status(self, process):
  1433     def copy_process_status(self, process):
  1411         return {
  1434         return {
  1412             'id': process.vpnservice['id'],
  1435             'id': process.vpnservice['id'],
  1431         if process_id in self.process_status_cache:
  1454         if process_id in self.process_status_cache:
  1432             LOG.debug(
  1455             LOG.debug(
  1433                 "Checking connection cache of router ID: \"%s\"" % process_id)
  1456                 "Checking connection cache of router ID: \"%s\"" % process_id)
  1434             stale_entries = []
  1457             stale_entries = []
  1435             cache = self.process_status_cache[process_id]
  1458             cache = self.process_status_cache[process_id]
       
  1459             if not cache[IPSEC_CONNS]:
       
  1460                 LOG.debug("No cache")
       
  1461                 return False
       
  1462 
  1436             for site_conn in cache[IPSEC_CONNS]:
  1463             for site_conn in cache[IPSEC_CONNS]:
  1437                 status = cache[IPSEC_CONNS][site_conn]['status']
  1464                 status = cache[IPSEC_CONNS][site_conn]['status']
  1438                 LOG.debug(
  1465                 LOG.debug(
  1439                     "Cache has [%s] entry for site ID: \"%s\""
  1466                     "Cache has [%s] entry for site ID: \"%s\""
  1440                     % (status, site_conn))
  1467                     % (status, site_conn))
  1441                 if site_conn not in process.connection_ids:
  1468                 if site_conn not in process.connection_ids:
  1442                     LOG.warn(
  1469                     LOG.info(
  1443                         "Site connection \"%s\" appears to have been deleted."
  1470                         "Site connection \"%s\" appears to have been deleted."
  1444                         % site_conn)
  1471                         % site_conn)
  1445                     return_value = False
  1472                     return_value = False
  1446                     new_status[IPSEC_CONNS][site_conn] = {
  1473                     new_status[IPSEC_CONNS][site_conn] = {
  1447                         'status': constants.DOWN,
  1474                         'status': constants.DOWN,
  1448                         'updated_pending_status': True
  1475                         'updated_pending_status': True
  1449                     }
  1476                     }
  1450                     stale_entries.append(site_conn)
  1477                     stale_entries.append(site_conn)
  1451 
  1478 
  1452             for badboy in stale_entries:
  1479             if stale_entries:
  1453                 cache[IPSEC_CONNS].pop(badboy)
  1480                 for badboy in stale_entries:
  1454 
  1481                     LOG.debug("Remove stale entry from connection cache: %s" %
  1455             return return_value
  1482                               badboy)
       
  1483                     cache[IPSEC_CONNS].pop(badboy)
       
  1484 
       
  1485         return return_value
  1456 
  1486 
  1457     @lockutils.synchronized('vpn-agent', 'neutron-')
  1487     @lockutils.synchronized('vpn-agent', 'neutron-')
  1458     def sync(self, context, routers):
  1488     def sync(self, context, routers):
  1459         """Sync is called by the server side of neutron.
  1489         """Sync is called by the server side of neutron.
  1460            This will be called whenever new configuration is
  1490            This will be called whenever new configuration is
  1526               vpn_0_site_2/v4 static    ok   -- 192.168.90.1->192.168.100.1
  1556               vpn_0_site_2/v4 static    ok   -- 192.168.90.1->192.168.100.1
  1527               vpn_0_site_2/v4a static   ok   -- 192.168.90.1->192.168.101.1
  1557               vpn_0_site_2/v4a static   ok   -- 192.168.90.1->192.168.101.1
  1528               vpn_0_site_2/v4b static   ok   -- 192.168.80.1->192.168.100.1
  1558               vpn_0_site_2/v4b static   ok   -- 192.168.80.1->192.168.100.1
  1529               vpn_0_site_2/v4c static   ok   -- 192.168.80.1->192.168.101.1
  1559               vpn_0_site_2/v4c static   ok   -- 192.168.80.1->192.168.101.1
  1530         """
  1560         """
  1531         LOG.warn("Neutron: Syncing VPN configuration.")
       
  1532         try:
  1561         try:
       
  1562             LOG.info("Getting VPN configuration from neutron")
  1533             vpnservices = self.agent_rpc.get_vpn_services_on_host(
  1563             vpnservices = self.agent_rpc.get_vpn_services_on_host(
  1534                 context, self.host)
  1564                 context, self.host)
  1535         except:
  1565         except:
  1536             LOG.warn("No VPN")
  1566             LOG.info("VPNaaS not enabled.")
  1537             return
  1567             return
  1538 
  1568 
  1539         router_ids = [vpnservice['router_id'] for vpnservice in vpnservices]
  1569         router_ids = [vpnservice['router_id'] for vpnservice in vpnservices]
  1540         global existing_tunnels
  1570         global existing_tunnels
  1541         delete_tunnels(existing_tunnels)
  1571         delete_tunnels(existing_tunnels)
       
  1572         whack_ike_rules()
  1542         existing_tunnels = []
  1573         existing_tunnels = []
  1543 
       
  1544         # This is a list of one or more vpn-service objects.
       
  1545         vpnservices = self.agent_rpc.get_vpn_services_on_host(
       
  1546             context, self.host)
       
  1547 
  1574 
  1548         # Remove old configuration files.
  1575         # Remove old configuration files.
  1549         try:
  1576         try:
  1550             shutil.rmtree(os.path.join(cfg.CONF.solaris.config_base_dir,
  1577             shutil.rmtree(os.path.join(cfg.CONF.solaris.config_base_dir,
  1551                           vpnservice['router_id']))
  1578                           vpnservice['router_id']))
  1555         # Add tunnel_id's
  1582         # Add tunnel_id's
  1556         local_ips = {}
  1583         local_ips = {}
  1557         remote_ips = {}
  1584         remote_ips = {}
  1558         vpn_cnt = 0
  1585         vpn_cnt = 0
  1559         site_cnt = 0
  1586         site_cnt = 0
       
  1587 
       
  1588         # If there are no vpn-services defined, we can bail out here.
       
  1589         # But we still need to check and delete any sub-processes that
       
  1590         # may have been created last time sync() was called.
       
  1591         if not vpnservices:
       
  1592             LOG.info("No VPNs configured")
       
  1593             for process in self.processes:
       
  1594                 del process
       
  1595             self.process_status_cache['process_id'] = {}
       
  1596             self.processes = {}
       
  1597             disable_smf_services()
       
  1598             return
  1560 
  1599 
  1561         for vpnservice in vpnservices:
  1600         for vpnservice in vpnservices:
  1562             ex_ip = vpnservice['external_ip']
  1601             ex_ip = vpnservice['external_ip']
  1563             l_id = local_ips.get(ex_ip)
  1602             l_id = local_ips.get(ex_ip)
  1564 
  1603 
  1582                           (tun_name, vpnservice['id']))
  1621                           (tun_name, vpnservice['id']))
  1583                 # Next time we restart, these tunnels will be removed.
  1622                 # Next time we restart, these tunnels will be removed.
  1584                 if tun_name not in existing_tunnels:
  1623                 if tun_name not in existing_tunnels:
  1585                     existing_tunnels.append(tun_name)
  1624                     existing_tunnels.append(tun_name)
  1586 
  1625 
       
  1626         new_vpnservice_status = []
       
  1627 
  1587         for vpnservice in vpnservices:
  1628         for vpnservice in vpnservices:
  1588             process = self.enable_vpn(
  1629             process = self.enable_vpn(
  1589                 vpnservice['router_id'], vpnservice=vpnservice)
  1630                 vpnservice['router_id'], vpnservice=vpnservice)
  1590 
  1631             self.vpnservice = vpnservice
  1591             process.update()
  1632             process.update()
  1592 
  1633             new_status = {
  1593         for router in routers:
  1634                 'id': vpnservice['id'],
  1594             # We are using router id as process_id
  1635                 'status': constants.ACTIVE,
  1595             process_id = router['id']
  1636                 'updated_pending_status': True,
  1596             if process_id not in router_ids:
  1637                 'ipsec_site_connections': {}
  1597                 process = self.enable_vpn(process_id)
  1638             }
  1598                 self.destroy_router(process_id)
  1639             new_vpnservice_status.append(new_status)
  1599 
  1640 
  1600         process_ids = [process_id
  1641         LOG.debug("Updating status of all vpnservices: %s" %
  1601                        for process_id in self.processes
  1642                   new_vpnservice_status)
  1602                        if process_id not in router_ids]
  1643         self.agent_rpc.update_status(
  1603         for process_id in process_ids:
  1644             self.context, new_vpnservice_status)
  1604             LOG.info("Deleting VPNaaS on router: \"%s\"" % process_id)
  1645 
  1605             self.destroy_router(process_id)
  1646         # Call start routine that sets up tunnels and
       
  1647         # enables smf(5) services.
       
  1648         process.start_ipsec()
  1606 
  1649 
  1607 
  1650 
  1608 class SolarisIPsecDriver(IPsecDriver):
  1651 class SolarisIPsecDriver(IPsecDriver):
  1609     def create_process(self, process_id, vpnservice, namespace):
  1652     def create_process(self, process_id, vpnservice, namespace):
  1610         LOG.debug("SolarisIPsec Driver loaded.")
  1653         LOG.debug("SolarisIPsec Driver loaded.")