add container_wan_ip to allowed-address-fields of neutron port
diff --git a/xos/synchronizers/vtn/steps/sync_port_addresses.py b/xos/synchronizers/vtn/steps/sync_port_addresses.py
new file mode 100644
index 0000000..2c41b3f
--- /dev/null
+++ b/xos/synchronizers/vtn/steps/sync_port_addresses.py
@@ -0,0 +1,118 @@
+import os
+import requests
+import socket
+import sys
+import base64
+from django.db.models import F, Q
+from xos.config import Config
+from synchronizers.base.syncstep import SyncStep
+from core.models import Service, Port, Controller
+from core.models.service import COARSE_KIND
+from services.cord.models import VSGTenant
+from services.cord.models import Tenant
+from xos.logger import Logger, logging
+from requests.auth import HTTPBasicAuth
+
+# hpclibrary will be in steps/..
+parentdir = os.path.join(os.path.dirname(__file__),"..")
+sys.path.insert(0,parentdir)
+
+logger = Logger(level=logging.INFO)
+
+# XXX should save and load this
+glo_saved_vtn_maps = []
+
+class SyncPortAddresses(SyncStep):
+    requested_interval = 0 # 3600
+    provides=[Port]
+    observes=Port
+
+    def __init__(self, **args):
+        SyncStep.__init__(self, **args)
+
+    def call(self, **args):
+        global glo_saved_vtn_maps
+
+        logger.info("sync'ing vsg tenant to port addresses")
+
+        # build up a dictionary of port-->[wan_addrs] mappings
+        port_addrs = {}
+        for vsg in VSGTenant.get_tenant_objects().all():
+            if not vsg.instance:
+                logger.info("skipping vsg %s because it has no instance" % vsg)
+
+            wan_ip = vsg.wan_container_ip
+            if not wan_ip:
+                logger.info("skipping vsg %s because it has no wan_container_ip" % vsg)
+
+            lan_network = vsg.get_lan_network(vsg.instance)
+            if not lan_network:
+                logger.info("skipping vsg %s because it has no lan_network" % vsg)
+
+            lan_port = Port.objects.filter(instance = vsg.instance, network=lan_network)
+            if not lan_port:
+                logger.info("skipping vsg %s because it has no lan_port" % vsg)
+            lan_port = lan_port[0]
+
+            if not lan_port.port_id:
+                logger.info("skipping vsg %s because its lan_port has no port_id" % vsg)
+
+            if not (lan_port.pk in port_addrs):
+                port_addrs[lan_port.pk] = []
+            addrs = port_addrs[lan_port.pk]
+            if not wan_ip in addrs:
+                 addrs.append(wan_ip)
+
+        # Get all ports in all controllers
+        ports_by_id = {}
+        for controller in Controller.objects.all():
+            if not controller.admin_tenant:
+                logger.info("controller %s has no admin_tenant" % controller)
+                continue
+            try:
+                driver = self.driver.admin_driver(controller = controller)
+                ports = driver.shell.quantum.list_ports()["ports"]
+            except:
+                logger.log_exc("failed to get ports from controller %s" % controller)
+                continue
+
+            for port in ports:
+                ports_by_id[port["id"]] = port
+
+        for port_pk in port_addrs.keys():
+            port = Port.objects.get(pk=port_pk)
+            addrs = port_addrs[port_pk]
+            neutron_port = ports_by_id.get(port.port_id,None)
+            if not neutron_port:
+                logger.log_info("failed to get neutron port for port %s" % port)
+
+            changed = False
+
+            # delete addresses in neutron that don't exist in XOS
+            aaps = neutron_port.get("allowed_address_pairs", [])
+            for aap in aaps[:]:
+                if not aap["ip_address"] in addrs:
+                    logger.info("removing address %s from port %s" % (aap["ip_address"], port))
+                    aaps.remove(aap)
+                    changed = True
+
+            aaps_addrs = [x["ip_address"] for x in aaps]
+
+            # add addresses in XOS that don't exist in neutron
+            for addr in addrs:
+                if not addr in aaps_addrs:
+                    logger.info("adding address %s to port %s" % (addr, port))
+                    aaps.append( {"ip_address": addr} )
+                    aaps_addrs.append(addr)
+                    changed = True
+
+            if changed:
+                logger.info("updating port %s" % port)
+                driver.shell.quantum.update_port(port.port_id, {"port": {"allowed_address_pairs": aaps}})
+
+
+
+
+
+
+