Scott Baker | c3ce3e7 | 2016-06-20 17:35:19 -0700 | [diff] [blame] | 1 | import os |
| 2 | import requests |
| 3 | import socket |
| 4 | import sys |
| 5 | import base64 |
Scott Baker | c3ce3e7 | 2016-06-20 17:35:19 -0700 | [diff] [blame] | 6 | from xos.config import Config |
Scott Baker | 61b41a9 | 2017-03-14 13:04:57 -0700 | [diff] [blame] | 7 | from synchronizers.new_base.syncstep import SyncStep |
| 8 | from synchronizers.new_base.modelaccessor import * |
Scott Baker | c3ce3e7 | 2016-06-20 17:35:19 -0700 | [diff] [blame] | 9 | from xos.logger import Logger, logging |
Scott Baker | c3ce3e7 | 2016-06-20 17:35:19 -0700 | [diff] [blame] | 10 | |
| 11 | logger = Logger(level=logging.INFO) |
| 12 | |
Scott Baker | 08a4df3 | 2017-03-15 14:13:59 -0700 | [diff] [blame] | 13 | # TODO: This file seems obsolete -- evaluate for deletion. |
| 14 | |
Scott Baker | c3ce3e7 | 2016-06-20 17:35:19 -0700 | [diff] [blame] | 15 | # XXX should save and load this |
| 16 | glo_saved_vtn_maps = [] |
| 17 | |
| 18 | class SyncPortAddresses(SyncStep): |
| 19 | requested_interval = 0 # 3600 |
| 20 | provides=[Port] |
| 21 | observes=Port |
| 22 | |
| 23 | def __init__(self, **args): |
| 24 | SyncStep.__init__(self, **args) |
| 25 | |
| 26 | def call(self, **args): |
| 27 | global glo_saved_vtn_maps |
| 28 | |
Scott Baker | 61b41a9 | 2017-03-14 13:04:57 -0700 | [diff] [blame] | 29 | vtn_service = VTNService.objects.all() |
Scott Baker | 855a9df | 2016-09-09 09:23:50 -0700 | [diff] [blame] | 30 | if not vtn_service: |
| 31 | raise Exception("SyncPortAddresses: No VTN Service") |
| 32 | vtn_service = vtn_service[0] |
| 33 | if vtn_service.vtnAPIVersion >= 2: |
| 34 | logger.info("skipping SyncPortAddresses due to VTN API Version") |
| 35 | return |
Scott Baker | cdbb71e | 2016-10-26 15:50:03 -0700 | [diff] [blame] | 36 | else: |
| 37 | raise Exception("VTN API Version 1 is no longer supported by VTN Synchronizer") |
Scott Baker | 855a9df | 2016-09-09 09:23:50 -0700 | [diff] [blame] | 38 | |
Scott Baker | c3ce3e7 | 2016-06-20 17:35:19 -0700 | [diff] [blame] | 39 | # build up a dictionary of port-->[wan_addrs] mappings |
| 40 | port_addrs = {} |
Andy Bavier | 5901263 | 2016-09-14 08:41:56 -0400 | [diff] [blame] | 41 | try: |
| 42 | from services.vsg.models import VSGTenant |
Scott Baker | c3ce3e7 | 2016-06-20 17:35:19 -0700 | [diff] [blame] | 43 | |
Andy Bavier | 5901263 | 2016-09-14 08:41:56 -0400 | [diff] [blame] | 44 | logger.info("sync'ing vsg tenant to port addresses") |
Scott Baker | c3ce3e7 | 2016-06-20 17:35:19 -0700 | [diff] [blame] | 45 | |
Scott Baker | 61b41a9 | 2017-03-14 13:04:57 -0700 | [diff] [blame] | 46 | for vsg in VSGTenant.objects.all(): |
Andy Bavier | 5901263 | 2016-09-14 08:41:56 -0400 | [diff] [blame] | 47 | if not vsg.instance: |
| 48 | logger.info("skipping vsg %s because it has no instance" % vsg) |
Scott Baker | c3ce3e7 | 2016-06-20 17:35:19 -0700 | [diff] [blame] | 49 | |
Andy Bavier | 5901263 | 2016-09-14 08:41:56 -0400 | [diff] [blame] | 50 | wan_ip = vsg.wan_container_ip |
| 51 | if not wan_ip: |
| 52 | logger.info("skipping vsg %s because it has no wan_container_ip" % vsg) |
Scott Baker | c3ce3e7 | 2016-06-20 17:35:19 -0700 | [diff] [blame] | 53 | |
Andy Bavier | 5901263 | 2016-09-14 08:41:56 -0400 | [diff] [blame] | 54 | wan_mac = vsg.wan_container_mac |
| 55 | if not wan_mac: |
| 56 | logger.info("skipping vsg %s because it has no wan_container_mac" % vsg) |
Scott Baker | c3ce3e7 | 2016-06-20 17:35:19 -0700 | [diff] [blame] | 57 | |
Andy Bavier | 5901263 | 2016-09-14 08:41:56 -0400 | [diff] [blame] | 58 | lan_network = vsg.get_lan_network(vsg.instance) |
| 59 | if not lan_network: |
| 60 | logger.info("skipping vsg %s because it has no lan_network" % vsg) |
Scott Baker | c3ce3e7 | 2016-06-20 17:35:19 -0700 | [diff] [blame] | 61 | |
Andy Bavier | 5901263 | 2016-09-14 08:41:56 -0400 | [diff] [blame] | 62 | lan_port = Port.objects.filter(instance = vsg.instance, network=lan_network) |
| 63 | if not lan_port: |
| 64 | logger.info("skipping vsg %s because it has no lan_port" % vsg) |
| 65 | lan_port = lan_port[0] |
Scott Baker | c3ce3e7 | 2016-06-20 17:35:19 -0700 | [diff] [blame] | 66 | |
Andy Bavier | 5901263 | 2016-09-14 08:41:56 -0400 | [diff] [blame] | 67 | if not lan_port.port_id: |
| 68 | logger.info("skipping vsg %s because its lan_port has no port_id" % vsg) |
| 69 | |
| 70 | if not (lan_port.pk in port_addrs): |
| 71 | port_addrs[lan_port.pk] = [] |
| 72 | entry = {"mac_address": wan_mac, "ip_address": wan_ip} |
| 73 | addr_pairs = port_addrs[lan_port.pk] |
Scott Baker | c3ce3e7 | 2016-06-20 17:35:19 -0700 | [diff] [blame] | 74 | if not entry in addr_pairs: |
| 75 | addr_pairs.append(entry) |
| 76 | |
Andy Bavier | 5901263 | 2016-09-14 08:41:56 -0400 | [diff] [blame] | 77 | # now do the VM_WAN_IP from the instance |
| 78 | if vsg.instance: |
| 79 | wan_vm_ip = vsg.wan_vm_ip |
| 80 | wan_vm_mac = vsg.wan_vm_mac |
| 81 | entry = {"mac_address": wan_vm_mac, "ip_address": wan_vm_ip} |
| 82 | if not entry in addr_pairs: |
| 83 | addr_pairs.append(entry) |
| 84 | except: |
| 85 | logger.info("No VSG service present") |
| 86 | |
Scott Baker | c3ce3e7 | 2016-06-20 17:35:19 -0700 | [diff] [blame] | 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 Williams | abe24da | 2016-06-27 13:09:00 -0700 | [diff] [blame] | 95 | # 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 Baker | c3ce3e7 | 2016-06-20 17:35:19 -0700 | [diff] [blame] | 101 | 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 Williams | abe24da | 2016-06-27 13:09:00 -0700 | [diff] [blame] | 140 | # 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 Baker | c3ce3e7 | 2016-06-20 17:35:19 -0700 | [diff] [blame] | 145 | |