blob: 57de70bb61c2260c92277e7df9f2c2d51fb41fa3 [file] [log] [blame]
Scott Bakerc3ce3e72016-06-20 17:35:19 -07001import os
2import requests
3import socket
4import sys
5import base64
Scott Bakerc3ce3e72016-06-20 17:35:19 -07006from xos.config import Config
Scott Baker61b41a92017-03-14 13:04:57 -07007from synchronizers.new_base.syncstep import SyncStep
8from synchronizers.new_base.modelaccessor import *
Scott Bakerc3ce3e72016-06-20 17:35:19 -07009from xos.logger import Logger, logging
Scott Bakerc3ce3e72016-06-20 17:35:19 -070010
11logger = Logger(level=logging.INFO)
12
13# XXX should save and load this
14glo_saved_vtn_maps = []
15
16class SyncPortAddresses(SyncStep):
17 requested_interval = 0 # 3600
18 provides=[Port]
19 observes=Port
20
21 def __init__(self, **args):
22 SyncStep.__init__(self, **args)
23
24 def call(self, **args):
25 global glo_saved_vtn_maps
26
Scott Baker61b41a92017-03-14 13:04:57 -070027 vtn_service = VTNService.objects.all()
Scott Baker855a9df2016-09-09 09:23:50 -070028 if not vtn_service:
29 raise Exception("SyncPortAddresses: No VTN Service")
30 vtn_service = vtn_service[0]
31 if vtn_service.vtnAPIVersion >= 2:
32 logger.info("skipping SyncPortAddresses due to VTN API Version")
33 return
Scott Bakercdbb71e2016-10-26 15:50:03 -070034 else:
35 raise Exception("VTN API Version 1 is no longer supported by VTN Synchronizer")
Scott Baker855a9df2016-09-09 09:23:50 -070036
Scott Bakerc3ce3e72016-06-20 17:35:19 -070037 # build up a dictionary of port-->[wan_addrs] mappings
38 port_addrs = {}
Andy Bavier59012632016-09-14 08:41:56 -040039 try:
40 from services.vsg.models import VSGTenant
Scott Bakerc3ce3e72016-06-20 17:35:19 -070041
Andy Bavier59012632016-09-14 08:41:56 -040042 logger.info("sync'ing vsg tenant to port addresses")
Scott Bakerc3ce3e72016-06-20 17:35:19 -070043
Scott Baker61b41a92017-03-14 13:04:57 -070044 for vsg in VSGTenant.objects.all():
Andy Bavier59012632016-09-14 08:41:56 -040045 if not vsg.instance:
46 logger.info("skipping vsg %s because it has no instance" % vsg)
Scott Bakerc3ce3e72016-06-20 17:35:19 -070047
Andy Bavier59012632016-09-14 08:41:56 -040048 wan_ip = vsg.wan_container_ip
49 if not wan_ip:
50 logger.info("skipping vsg %s because it has no wan_container_ip" % vsg)
Scott Bakerc3ce3e72016-06-20 17:35:19 -070051
Andy Bavier59012632016-09-14 08:41:56 -040052 wan_mac = vsg.wan_container_mac
53 if not wan_mac:
54 logger.info("skipping vsg %s because it has no wan_container_mac" % vsg)
Scott Bakerc3ce3e72016-06-20 17:35:19 -070055
Andy Bavier59012632016-09-14 08:41:56 -040056 lan_network = vsg.get_lan_network(vsg.instance)
57 if not lan_network:
58 logger.info("skipping vsg %s because it has no lan_network" % vsg)
Scott Bakerc3ce3e72016-06-20 17:35:19 -070059
Andy Bavier59012632016-09-14 08:41:56 -040060 lan_port = Port.objects.filter(instance = vsg.instance, network=lan_network)
61 if not lan_port:
62 logger.info("skipping vsg %s because it has no lan_port" % vsg)
63 lan_port = lan_port[0]
Scott Bakerc3ce3e72016-06-20 17:35:19 -070064
Andy Bavier59012632016-09-14 08:41:56 -040065 if not lan_port.port_id:
66 logger.info("skipping vsg %s because its lan_port has no port_id" % vsg)
67
68 if not (lan_port.pk in port_addrs):
69 port_addrs[lan_port.pk] = []
70 entry = {"mac_address": wan_mac, "ip_address": wan_ip}
71 addr_pairs = port_addrs[lan_port.pk]
Scott Bakerc3ce3e72016-06-20 17:35:19 -070072 if not entry in addr_pairs:
73 addr_pairs.append(entry)
74
Andy Bavier59012632016-09-14 08:41:56 -040075 # now do the VM_WAN_IP from the instance
76 if vsg.instance:
77 wan_vm_ip = vsg.wan_vm_ip
78 wan_vm_mac = vsg.wan_vm_mac
79 entry = {"mac_address": wan_vm_mac, "ip_address": wan_vm_ip}
80 if not entry in addr_pairs:
81 addr_pairs.append(entry)
82 except:
83 logger.info("No VSG service present")
84
Scott Bakerc3ce3e72016-06-20 17:35:19 -070085 # Get all ports in all controllers
86 ports_by_id = {}
87 for controller in Controller.objects.all():
88 if not controller.admin_tenant:
89 logger.info("controller %s has no admin_tenant" % controller)
90 continue
91 try:
92 driver = self.driver.admin_driver(controller = controller)
Zack Williamsabe24da2016-06-27 13:09:00 -070093 # FIXME: after LTS merge, use neutron (new name) instead of quantum (old name)
94 # the following if is a workaround
95 if hasattr( driver.shell, "neutron"):
96 ports = driver.shell.neutron.list_ports()["ports"]
97 else:
98 ports = driver.shell.quantum.list_ports()["ports"]
Scott Bakerc3ce3e72016-06-20 17:35:19 -070099 except:
100 logger.log_exc("failed to get ports from controller %s" % controller)
101 continue
102
103 for port in ports:
104 ports_by_id[port["id"]] = port
105
106 for port_pk in port_addrs.keys():
107 port = Port.objects.get(pk=port_pk)
108 addr_pairs = port_addrs[port_pk]
109 neutron_port = ports_by_id.get(port.port_id,None)
110 if not neutron_port:
111 logger.info("failed to get neutron port for port %s" % port)
112 continue
113
114 ips = [x["ip_address"] for x in addr_pairs]
115
116 changed = False
117
118 # delete addresses in neutron that don't exist in XOS
119 aaps = neutron_port.get("allowed_address_pairs", [])
120 for aap in aaps[:]:
121 if not aap["ip_address"] in ips:
122 logger.info("removing address %s from port %s" % (aap["ip_address"], port))
123 aaps.remove(aap)
124 changed = True
125
126 aaps_ips = [x["ip_address"] for x in aaps]
127
128 # add addresses in XOS that don't exist in neutron
129 for addr in addr_pairs:
130 if not addr["ip_address"] in aaps_ips:
131 logger.info("adding address %s to port %s" % (addr, port))
132 aaps.append( addr )
133 aaps_ips.append(addr["ip_address"])
134 changed = True
135
136 if changed:
137 logger.info("updating port %s" % port)
Zack Williamsabe24da2016-06-27 13:09:00 -0700138 # FIXME: See FIXME above, remove after LTS merge
139 if hasattr( driver.shell, "neutron"):
140 driver.shell.neutron.update_port(port.port_id, {"port": {"allowed_address_pairs": aaps}})
141 else:
142 driver.shell.quantum.update_port(port.port_id, {"port": {"allowed_address_pairs": aaps}})
Scott Bakerc3ce3e72016-06-20 17:35:19 -0700143