blob: 0ff7d6783caebd66e612a3a57429e34f4a1d5cb6 [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
11from services.vsg.models import VSGTenant
12from xos.logger import Logger, logging
13from requests.auth import HTTPBasicAuth
Scott Baker855a9df2016-09-09 09:23:50 -070014from services.vtn.models import VTNService
Scott Bakerc3ce3e72016-06-20 17:35:19 -070015
16# hpclibrary will be in steps/..
17parentdir = os.path.join(os.path.dirname(__file__),"..")
18sys.path.insert(0,parentdir)
19
20logger = Logger(level=logging.INFO)
21
22# XXX should save and load this
23glo_saved_vtn_maps = []
24
25class SyncPortAddresses(SyncStep):
26 requested_interval = 0 # 3600
27 provides=[Port]
28 observes=Port
29
30 def __init__(self, **args):
31 SyncStep.__init__(self, **args)
32
33 def call(self, **args):
34 global glo_saved_vtn_maps
35
Scott Baker855a9df2016-09-09 09:23:50 -070036 vtn_service = VTNService.get_service_objects().all()
37 if not vtn_service:
38 raise Exception("SyncPortAddresses: No VTN Service")
39 vtn_service = vtn_service[0]
40 if vtn_service.vtnAPIVersion >= 2:
41 logger.info("skipping SyncPortAddresses due to VTN API Version")
42 return
43
Scott Bakerc3ce3e72016-06-20 17:35:19 -070044 logger.info("sync'ing vsg tenant to port addresses")
45
46 # build up a dictionary of port-->[wan_addrs] mappings
47 port_addrs = {}
48 for vsg in VSGTenant.get_tenant_objects().all():
49 if not vsg.instance:
50 logger.info("skipping vsg %s because it has no instance" % vsg)
51
52 wan_ip = vsg.wan_container_ip
53 if not wan_ip:
54 logger.info("skipping vsg %s because it has no wan_container_ip" % vsg)
55
56 wan_mac = vsg.wan_container_mac
57 if not wan_mac:
58 logger.info("skipping vsg %s because it has no wan_container_mac" % vsg)
59
60 lan_network = vsg.get_lan_network(vsg.instance)
61 if not lan_network:
62 logger.info("skipping vsg %s because it has no lan_network" % vsg)
63
64 lan_port = Port.objects.filter(instance = vsg.instance, network=lan_network)
65 if not lan_port:
66 logger.info("skipping vsg %s because it has no lan_port" % vsg)
67 lan_port = lan_port[0]
68
69 if not lan_port.port_id:
70 logger.info("skipping vsg %s because its lan_port has no port_id" % vsg)
71
72 if not (lan_port.pk in port_addrs):
73 port_addrs[lan_port.pk] = []
74 entry = {"mac_address": wan_mac, "ip_address": wan_ip}
75 addr_pairs = port_addrs[lan_port.pk]
76 if not entry in addr_pairs:
77 addr_pairs.append(entry)
78
79 # now do the VM_WAN_IP from the instance
80 if vsg.instance:
81 wan_vm_ip = vsg.wan_vm_ip
82 wan_vm_mac = vsg.wan_vm_mac
83 entry = {"mac_address": wan_vm_mac, "ip_address": wan_vm_ip}
84 if not entry in addr_pairs:
85 addr_pairs.append(entry)
86
87 # Get all ports in all controllers
88 ports_by_id = {}
89 for controller in Controller.objects.all():
90 if not controller.admin_tenant:
91 logger.info("controller %s has no admin_tenant" % controller)
92 continue
93 try:
94 driver = self.driver.admin_driver(controller = controller)
Zack Williamsabe24da2016-06-27 13:09:00 -070095 # FIXME: after LTS merge, use neutron (new name) instead of quantum (old name)
96 # the following if is a workaround
97 if hasattr( driver.shell, "neutron"):
98 ports = driver.shell.neutron.list_ports()["ports"]
99 else:
100 ports = driver.shell.quantum.list_ports()["ports"]
Scott Bakerc3ce3e72016-06-20 17:35:19 -0700101 except:
102 logger.log_exc("failed to get ports from controller %s" % controller)
103 continue
104
105 for port in ports:
106 ports_by_id[port["id"]] = port
107
108 for port_pk in port_addrs.keys():
109 port = Port.objects.get(pk=port_pk)
110 addr_pairs = port_addrs[port_pk]
111 neutron_port = ports_by_id.get(port.port_id,None)
112 if not neutron_port:
113 logger.info("failed to get neutron port for port %s" % port)
114 continue
115
116 ips = [x["ip_address"] for x in addr_pairs]
117
118 changed = False
119
120 # delete addresses in neutron that don't exist in XOS
121 aaps = neutron_port.get("allowed_address_pairs", [])
122 for aap in aaps[:]:
123 if not aap["ip_address"] in ips:
124 logger.info("removing address %s from port %s" % (aap["ip_address"], port))
125 aaps.remove(aap)
126 changed = True
127
128 aaps_ips = [x["ip_address"] for x in aaps]
129
130 # add addresses in XOS that don't exist in neutron
131 for addr in addr_pairs:
132 if not addr["ip_address"] in aaps_ips:
133 logger.info("adding address %s to port %s" % (addr, port))
134 aaps.append( addr )
135 aaps_ips.append(addr["ip_address"])
136 changed = True
137
138 if changed:
139 logger.info("updating port %s" % port)
Zack Williamsabe24da2016-06-27 13:09:00 -0700140 # FIXME: See FIXME above, remove after LTS merge
141 if hasattr( driver.shell, "neutron"):
142 driver.shell.neutron.update_port(port.port_id, {"port": {"allowed_address_pairs": aaps}})
143 else:
144 driver.shell.quantum.update_port(port.port_id, {"port": {"allowed_address_pairs": aaps}})
Scott Bakerc3ce3e72016-06-20 17:35:19 -0700145