blob: b3a78377ccb73d5d817327747227b5c207304e2d [file] [log] [blame]
Scott Bakerc3ce3e72016-06-20 17:35:19 -07001import os
2import requests
3import socket
4import sys
5import base64
6from django.db.models import F, Q
7from xos.config import Config
8from synchronizers.base.syncstep import SyncStep
9from core.models import Service, Port, Controller, Tag, Tenant
10from core.models.service import COARSE_KIND
Scott Bakerc3ce3e72016-06-20 17:35:19 -070011from xos.logger import Logger, logging
12from requests.auth import HTTPBasicAuth
Scott Baker855a9df2016-09-09 09:23:50 -070013from services.vtn.models import VTNService
Scott Bakerc3ce3e72016-06-20 17:35:19 -070014
15# hpclibrary will be in steps/..
16parentdir = os.path.join(os.path.dirname(__file__),"..")
17sys.path.insert(0,parentdir)
18
19logger = Logger(level=logging.INFO)
20
21# XXX should save and load this
22glo_saved_vtn_maps = []
23
24class SyncPortAddresses(SyncStep):
25 requested_interval = 0 # 3600
26 provides=[Port]
27 observes=Port
28
29 def __init__(self, **args):
30 SyncStep.__init__(self, **args)
31
32 def call(self, **args):
33 global glo_saved_vtn_maps
34
Scott Baker855a9df2016-09-09 09:23:50 -070035 vtn_service = VTNService.get_service_objects().all()
36 if not vtn_service:
37 raise Exception("SyncPortAddresses: No VTN Service")
38 vtn_service = vtn_service[0]
39 if vtn_service.vtnAPIVersion >= 2:
40 logger.info("skipping SyncPortAddresses due to VTN API Version")
41 return
Scott Bakercdbb71e2016-10-26 15:50:03 -070042 else:
43 raise Exception("VTN API Version 1 is no longer supported by VTN Synchronizer")
Scott Baker855a9df2016-09-09 09:23:50 -070044
Scott Bakerc3ce3e72016-06-20 17:35:19 -070045 # build up a dictionary of port-->[wan_addrs] mappings
46 port_addrs = {}
Andy Bavier59012632016-09-14 08:41:56 -040047 try:
48 from services.vsg.models import VSGTenant
Scott Bakerc3ce3e72016-06-20 17:35:19 -070049
Andy Bavier59012632016-09-14 08:41:56 -040050 logger.info("sync'ing vsg tenant to port addresses")
Scott Bakerc3ce3e72016-06-20 17:35:19 -070051
Andy Bavier59012632016-09-14 08:41:56 -040052 for vsg in VSGTenant.get_tenant_objects().all():
53 if not vsg.instance:
54 logger.info("skipping vsg %s because it has no instance" % vsg)
Scott Bakerc3ce3e72016-06-20 17:35:19 -070055
Andy Bavier59012632016-09-14 08:41:56 -040056 wan_ip = vsg.wan_container_ip
57 if not wan_ip:
58 logger.info("skipping vsg %s because it has no wan_container_ip" % vsg)
Scott Bakerc3ce3e72016-06-20 17:35:19 -070059
Andy Bavier59012632016-09-14 08:41:56 -040060 wan_mac = vsg.wan_container_mac
61 if not wan_mac:
62 logger.info("skipping vsg %s because it has no wan_container_mac" % vsg)
Scott Bakerc3ce3e72016-06-20 17:35:19 -070063
Andy Bavier59012632016-09-14 08:41:56 -040064 lan_network = vsg.get_lan_network(vsg.instance)
65 if not lan_network:
66 logger.info("skipping vsg %s because it has no lan_network" % vsg)
Scott Bakerc3ce3e72016-06-20 17:35:19 -070067
Andy Bavier59012632016-09-14 08:41:56 -040068 lan_port = Port.objects.filter(instance = vsg.instance, network=lan_network)
69 if not lan_port:
70 logger.info("skipping vsg %s because it has no lan_port" % vsg)
71 lan_port = lan_port[0]
Scott Bakerc3ce3e72016-06-20 17:35:19 -070072
Andy Bavier59012632016-09-14 08:41:56 -040073 if not lan_port.port_id:
74 logger.info("skipping vsg %s because its lan_port has no port_id" % vsg)
75
76 if not (lan_port.pk in port_addrs):
77 port_addrs[lan_port.pk] = []
78 entry = {"mac_address": wan_mac, "ip_address": wan_ip}
79 addr_pairs = port_addrs[lan_port.pk]
Scott Bakerc3ce3e72016-06-20 17:35:19 -070080 if not entry in addr_pairs:
81 addr_pairs.append(entry)
82
Andy Bavier59012632016-09-14 08:41:56 -040083 # now do the VM_WAN_IP from the instance
84 if vsg.instance:
85 wan_vm_ip = vsg.wan_vm_ip
86 wan_vm_mac = vsg.wan_vm_mac
87 entry = {"mac_address": wan_vm_mac, "ip_address": wan_vm_ip}
88 if not entry in addr_pairs:
89 addr_pairs.append(entry)
90 except:
91 logger.info("No VSG service present")
92
Scott Bakerc3ce3e72016-06-20 17:35:19 -070093 # Get all ports in all controllers
94 ports_by_id = {}
95 for controller in Controller.objects.all():
96 if not controller.admin_tenant:
97 logger.info("controller %s has no admin_tenant" % controller)
98 continue
99 try:
100 driver = self.driver.admin_driver(controller = controller)
Zack Williamsabe24da2016-06-27 13:09:00 -0700101 # FIXME: after LTS merge, use neutron (new name) instead of quantum (old name)
102 # the following if is a workaround
103 if hasattr( driver.shell, "neutron"):
104 ports = driver.shell.neutron.list_ports()["ports"]
105 else:
106 ports = driver.shell.quantum.list_ports()["ports"]
Scott Bakerc3ce3e72016-06-20 17:35:19 -0700107 except:
108 logger.log_exc("failed to get ports from controller %s" % controller)
109 continue
110
111 for port in ports:
112 ports_by_id[port["id"]] = port
113
114 for port_pk in port_addrs.keys():
115 port = Port.objects.get(pk=port_pk)
116 addr_pairs = port_addrs[port_pk]
117 neutron_port = ports_by_id.get(port.port_id,None)
118 if not neutron_port:
119 logger.info("failed to get neutron port for port %s" % port)
120 continue
121
122 ips = [x["ip_address"] for x in addr_pairs]
123
124 changed = False
125
126 # delete addresses in neutron that don't exist in XOS
127 aaps = neutron_port.get("allowed_address_pairs", [])
128 for aap in aaps[:]:
129 if not aap["ip_address"] in ips:
130 logger.info("removing address %s from port %s" % (aap["ip_address"], port))
131 aaps.remove(aap)
132 changed = True
133
134 aaps_ips = [x["ip_address"] for x in aaps]
135
136 # add addresses in XOS that don't exist in neutron
137 for addr in addr_pairs:
138 if not addr["ip_address"] in aaps_ips:
139 logger.info("adding address %s to port %s" % (addr, port))
140 aaps.append( addr )
141 aaps_ips.append(addr["ip_address"])
142 changed = True
143
144 if changed:
145 logger.info("updating port %s" % port)
Zack Williamsabe24da2016-06-27 13:09:00 -0700146 # FIXME: See FIXME above, remove after LTS merge
147 if hasattr( driver.shell, "neutron"):
148 driver.shell.neutron.update_port(port.port_id, {"port": {"allowed_address_pairs": aaps}})
149 else:
150 driver.shell.quantum.update_port(port.port_id, {"port": {"allowed_address_pairs": aaps}})
Scott Bakerc3ce3e72016-06-20 17:35:19 -0700151