blob: 02e8df690770d73972cd42fca3126020b5337b6b [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
14
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
35 logger.info("sync'ing vsg tenant to port addresses")
36
37 # build up a dictionary of port-->[wan_addrs] mappings
38 port_addrs = {}
39 for vsg in VSGTenant.get_tenant_objects().all():
40 if not vsg.instance:
41 logger.info("skipping vsg %s because it has no instance" % vsg)
42
43 wan_ip = vsg.wan_container_ip
44 if not wan_ip:
45 logger.info("skipping vsg %s because it has no wan_container_ip" % vsg)
46
47 wan_mac = vsg.wan_container_mac
48 if not wan_mac:
49 logger.info("skipping vsg %s because it has no wan_container_mac" % vsg)
50
51 lan_network = vsg.get_lan_network(vsg.instance)
52 if not lan_network:
53 logger.info("skipping vsg %s because it has no lan_network" % vsg)
54
55 lan_port = Port.objects.filter(instance = vsg.instance, network=lan_network)
56 if not lan_port:
57 logger.info("skipping vsg %s because it has no lan_port" % vsg)
58 lan_port = lan_port[0]
59
60 if not lan_port.port_id:
61 logger.info("skipping vsg %s because its lan_port has no port_id" % vsg)
62
63 if not (lan_port.pk in port_addrs):
64 port_addrs[lan_port.pk] = []
65 entry = {"mac_address": wan_mac, "ip_address": wan_ip}
66 addr_pairs = port_addrs[lan_port.pk]
67 if not entry in addr_pairs:
68 addr_pairs.append(entry)
69
70 # now do the VM_WAN_IP from the instance
71 if vsg.instance:
72 wan_vm_ip = vsg.wan_vm_ip
73 wan_vm_mac = vsg.wan_vm_mac
74 entry = {"mac_address": wan_vm_mac, "ip_address": wan_vm_ip}
75 if not entry in addr_pairs:
76 addr_pairs.append(entry)
77
78 # Get all ports in all controllers
79 ports_by_id = {}
80 for controller in Controller.objects.all():
81 if not controller.admin_tenant:
82 logger.info("controller %s has no admin_tenant" % controller)
83 continue
84 try:
85 driver = self.driver.admin_driver(controller = controller)
Zack Williamsabe24da2016-06-27 13:09:00 -070086 # FIXME: after LTS merge, use neutron (new name) instead of quantum (old name)
87 # the following if is a workaround
88 if hasattr( driver.shell, "neutron"):
89 ports = driver.shell.neutron.list_ports()["ports"]
90 else:
91 ports = driver.shell.quantum.list_ports()["ports"]
Scott Bakerc3ce3e72016-06-20 17:35:19 -070092 except:
93 logger.log_exc("failed to get ports from controller %s" % controller)
94 continue
95
96 for port in ports:
97 ports_by_id[port["id"]] = port
98
99 for port_pk in port_addrs.keys():
100 port = Port.objects.get(pk=port_pk)
101 addr_pairs = port_addrs[port_pk]
102 neutron_port = ports_by_id.get(port.port_id,None)
103 if not neutron_port:
104 logger.info("failed to get neutron port for port %s" % port)
105 continue
106
107 ips = [x["ip_address"] for x in addr_pairs]
108
109 changed = False
110
111 # delete addresses in neutron that don't exist in XOS
112 aaps = neutron_port.get("allowed_address_pairs", [])
113 for aap in aaps[:]:
114 if not aap["ip_address"] in ips:
115 logger.info("removing address %s from port %s" % (aap["ip_address"], port))
116 aaps.remove(aap)
117 changed = True
118
119 aaps_ips = [x["ip_address"] for x in aaps]
120
121 # add addresses in XOS that don't exist in neutron
122 for addr in addr_pairs:
123 if not addr["ip_address"] in aaps_ips:
124 logger.info("adding address %s to port %s" % (addr, port))
125 aaps.append( addr )
126 aaps_ips.append(addr["ip_address"])
127 changed = True
128
129 if changed:
130 logger.info("updating port %s" % port)
Zack Williamsabe24da2016-06-27 13:09:00 -0700131 # FIXME: See FIXME above, remove after LTS merge
132 if hasattr( driver.shell, "neutron"):
133 driver.shell.neutron.update_port(port.port_id, {"port": {"allowed_address_pairs": aaps}})
134 else:
135 driver.shell.quantum.update_port(port.port_id, {"port": {"allowed_address_pairs": aaps}})
Scott Bakerc3ce3e72016-06-20 17:35:19 -0700136