Merge branch 'ceilometer_devstack' of https://github.com/open-cloud/xos into ceilometer_devstack
diff --git a/xos/configurations/common/make-nodes-yaml.sh b/xos/configurations/common/make-nodes-yaml.sh
index 74b8d0b..65e16bb 100644
--- a/xos/configurations/common/make-nodes-yaml.sh
+++ b/xos/configurations/common/make-nodes-yaml.sh
@@ -18,7 +18,7 @@
         type: tosca.nodes.Site
 EOF
 
-NODES=$( bash -c "source $SETUPDIR/admin-openrc.sh ; nova hypervisor-list" |grep -v ID|grep -v +|awk '{print $4}' )
+NODES=$( bash -c "source $SETUPDIR/admin-openrc.sh ; nova host-list" |grep compute|awk '{print $2}' )
 I=0
 for NODE in $NODES; do
     echo $NODE
diff --git a/xos/configurations/common/xos_common_config b/xos/configurations/common/xos_common_config
index f7b335e..76ba747 100644
--- a/xos/configurations/common/xos_common_config
+++ b/xos/configurations/common/xos_common_config
@@ -37,6 +37,7 @@
 images_directory=/opt/xos/images
 dependency_graph=/opt/xos/model-deps
 logfile=/var/log/xos_backend.log
+save_ansible_output=True
 
 [gui]
 disable_minidashboard=True
diff --git a/xos/configurations/cord-pod/Makefile b/xos/configurations/cord-pod/Makefile
index 1be4a80..606f106 100644
--- a/xos/configurations/cord-pod/Makefile
+++ b/xos/configurations/cord-pod/Makefile
@@ -1,12 +1,18 @@
 .PHONY: xos
-xos: nodes.yaml images.yaml vtn_network_cfg_json
+xos: nodes.yaml images.yaml vtn_network_cfg_json virtualbng_json
 	sudo docker-compose up -d
 	../common/wait_for_xos_port.sh 80
 	sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/setup.yaml
 	sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/nodes.yaml
 	sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/images.yaml
+
+vtn:
 	sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/vtn-external.yaml
-	sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/cord/vtn.yaml
+
+cord:
+	sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/mgmt-net.yaml
+	sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/fixtures.yaml
+	sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/cord-vtn-vsg.yaml
 
 nodes.yaml:
 	export SETUPDIR=.; bash ../common/make-nodes-yaml.sh
@@ -14,6 +20,9 @@
 images.yaml:
 	export SETUPDIR=.; bash ../common/make-images-yaml.sh
 
+virtualbng_json:
+	export SETUPDIR=.; bash ./make-virtualbng-json.sh
+
 vtn_network_cfg_json:
 	export SETUPDIR=.; bash ./make-vtn-networkconfig-json.sh
 
diff --git a/xos/configurations/cord-pod/NOTES.txt b/xos/configurations/cord-pod/NOTES.txt
index d0ecf36..d832f2b 100644
--- a/xos/configurations/cord-pod/NOTES.txt
+++ b/xos/configurations/cord-pod/NOTES.txt
@@ -12,27 +12,26 @@
   - mgmtbr on head nodes
   - dnsmasq on head1 using cord config file
 * Install OpenStack using the openstack-cluster-install repo
-  TO ADD:
-  - Create XOS VM
-  - Install git, make, OpenStack clients
-  - Check out XOS inside VM
-  - Copy admin-openrc.sh and id_rsa* to correct location
-* Add trusty-server-multi-nic image to OpenStack
 
 VTN
-* Install Docker on the head node
-* Edit /etc/default/docker so that it points to mgmtbr
-* Create onos-cord Docker container
-  # docker ...
+* onos-cord VM is created by openstack-cluster-install
+* Bring up ONOS
+  # cd cord; docker-compose up -d
+* On each compute node it's necessary perform a few manual steps (FIX ME)
+  - Disable neutron-plugin-openvswitch-agent. As root:
+    # service neutron-plugin-openvswitch-agent stop
+    # echo manual > /etc/init/neutron-plugin-openvswitch-agent.override
+  - Clean up OVS: delete br-int and any other bridges
+  - Listen for connections from VTN:
+    # ovs-appctl -t ovsdb-server ovsdb-server/add-remote ptcp:6641
 
 XOS
-* Create xos Docker containers attached to mgmtbr
-  # docker ...
+* xos VM is created by openstack-cluster-install
+  - requirements listed above should already be satisfied by install
+* cd xos/xos/configurations/cord-pod
 * Bring up XOS cord-pod configuration
-
-
-
-
-
-Test VTN
-* Try to create a network: neutron net-create testnet
+  # make
+  # make vtn
+  # make cord
+* Login to XOS at http://xos
+  - padmin@vicci.org / letmein
diff --git a/xos/configurations/cord-pod/README.md b/xos/configurations/cord-pod/README.md
index 0fcdb13..c6511f7 100644
--- a/xos/configurations/cord-pod/README.md
+++ b/xos/configurations/cord-pod/README.md
@@ -1,77 +1,79 @@
-# XOS Docker Images
+# XOS Configuration for CORD development POD
 
 ## Introduction
 
- XOS is comprised of 3 core services:
+This directory holds files that are used to configure a development POD for
+CORD.  For more information on the CORD project, check out
+[the CORD website](http://cord.onosproject.org/).
+
+XOS is composed of several core services:
 
   * A database backend (postgres)
   * A webserver front end (django)
-  * A synchronizer daemon that interacts with the openstack backend.
+  * A synchronizer daemon that interacts with the openstack backend
+  * A synchronizer for each configured XOS service
 
-We have created separate dockerfiles for each of these services, making it
-easier to build the services independently and also deploy and run them in
-isolated environments.
+Each service runs in a separate Docker container.  The containers are built
+automatically by [Docker Hub](https://hub.docker.com/u/xosproject/) using
+the HEAD of the XOS repository.
 
-#### Database Container
+## How to bring up CORD
 
-To build the database container:
+Installing a CORD POD requires three steps:
+ 1. Installing OpenStack on a cluster
+ 2. Setting up the ONOS VTN app and configuring OVS on the nova-compute nodes to be
+    controlled by VTN
+ 3. Bringing up XOS with the CORD services
 
+### Installing OpenStack
+
+Follow the instructions in the [README.md](https://github.com/open-cloud/openstack-cluster-setup/blob/master/README.md)
+file of the [open-cloud/openstack-cluster-setup](https://github.com/open-cloud/openstack-cluster-setup/)
+repository.
+
+### Setting up ONOS VTN
+
+The OpenStack installer above creates a VM called *onos-cord* on the head node.
+To bring up ONOS in this VM, log into the head node and run:
 ```
-$ cd postgresql; make build
+$ ssh ubuntu@onos-cord
+ubuntu@onos-cord:~$ cd cord; sudo docker-compose up -d
 ```
 
-#### XOS Container
-
-To build the XOS webserver container:
-
+Currently it's also necessary to do some manual configuration on each compute
+node.  As root do the following:
+ 1. Disable neutron-plugin-openvswitch-agent, if running:
 ```
-$ cd xos; make build
+$ service neutron-plugin-openvswitch-agent stop
+$ echo manual > /etc/init/neutron-plugin-openvswitch-agent.override
+```
+ 2. Delete *br-int* and all other bridges from OVS
+ 3. Configure OVS to listen for connections from VTN:
+```
+$ ovs-appctl -t ovsdb-server ovsdb-server/add-remote ptcp:6641
 ```
 
-#### Synchronizer Container
+### Bringing up XOS
 
-The Synchronizer shares many of the same dependencies as the XOS container. The
-synchronizer container takes advantage of this by building itself on top of the
-XOS image. This means you must build the XOS image before building the
-synchronizer image.  Assuming you have already built the XOS container,
-executing the following will build the Synchronizer container:
-
+The OpenStack installer above creates a VM called *xos* on the head node.
+To bring up XOS in this VM, first log into the head node and run:
 ```
-$ cd synchronizer; make build
+$ ssh ubuntu@xos
+ubuntu@xos:~$ cd xos/xos/configurations/cord-pod
 ```
 
-#### Solution Compose File
+Next, put the following files in this directory:
 
-[Docker Compose](https://docs.docker.com/compose/) is a tool for defining and
-running multi-container Docker applications. With Compose, you use a Compose
-file to configure your application’s services. Then, using a single command, you
-create, start, scale, and manage all the services from your configuration.
+ * *admin-openrc.sh*: Admin credentials for your OpenStack cloud
+ * *id_rsa[.pub]*: A keypair that will be used by the various services
+ * *node_key*: A private key that allows root login to the compute nodes
 
-Included is a compose file in *YAML* format with content defined by the [Docker
-Compose Format](https://docs.docker.com/compose/compose-file/). With the compose
-file a complete XOS solution based on Docker containers can be instantiated
-using a single command. To start the instance you can use the command:
-
+Then XOS can be brought up for CORD by running a few 'make' commands:
 ```
-$ docker-compose up -d
+ubuntu@xos:~/xos/xos/configurations/cord-pod$ make
+ubuntu@xos:~/xos/xos/configurations/cord-pod$ make vtn
+ubuntu@xos:~/xos/xos/configurations/cord-pod$ make cord
 ```
 
-You should now be able to access the login page by visiting
-`http://localhost:8000` and log in using the default `padmin@vicci.org` account
-with password `letmein`.
-
-#### Configuring XOS for OpenStack
-
-If you have your own OpenStack cluster, and you would like to configure XOS to
-control it, copy the `admin-openrc.sh` credentials file for your cluster to
-this directory.  Make sure that OpenStack commands work from the local machine
-using the credentials, e.g., `source ./admin-openrc.sh; nova list`.  Then run:
-
-```
-$ make
-```
-
-XOS will be launched (the Makefile will run the `docker-compose up -d` command
-for you) and configured with the nodes and images available in your
-OpenStack cloud.  You can then log in to XOS as described above and start creating
-slices and instances.
+After the first 'make' command above, you will be able to login to XOS at
+*http://xos/* using username/password `padmin@vicci.org/letmein`.
diff --git a/xos/configurations/cord-pod/cord-vtn-vsg.yaml b/xos/configurations/cord-pod/cord-vtn-vsg.yaml
new file mode 100644
index 0000000..d9fda9b
--- /dev/null
+++ b/xos/configurations/cord-pod/cord-vtn-vsg.yaml
@@ -0,0 +1,175 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: Just enough Tosca to get the vSG slice running on the CORD POD
+
+imports:
+   - custom_types/xos.yaml
+
+topology_template:
+  node_templates:
+    # CORD Services
+    service_volt:
+      type: tosca.nodes.Service
+      requirements:
+          - vsg_tenant:
+              node: service_vsg
+              relationship: tosca.relationships.TenantOfService
+      properties:
+          view_url: /admin/cord/voltservice/$id$/
+          kind: vOLT
+
+    public_addresses:
+      type: tosca.nodes.AddressPool
+      properties:
+          addresses: 207.141.192.128/27
+
+    service_vsg:
+      type: tosca.nodes.VSGService
+      requirements:
+          - vbng_tenant:
+              node: service_vbng
+              relationship: tosca.relationships.TenantOfService
+      properties:
+          view_url: /admin/cord/vsgservice/$id$/
+          backend_network_label: hpc_client
+          public_key: { get_artifact: [ SELF, pubkey, LOCAL_FILE] }
+          private_key_fn: /opt/xos/synchronizers/vcpe/vcpe_private_key
+          wan_container_gateway_ip: 207.141.192.158
+          wan_container_gateway_mac: a4:23:05:34:56:78
+          wan_container_netbits: 27
+      artifacts:
+          pubkey: /opt/xos/synchronizers/vcpe/vcpe_public_key
+
+    service_vbng:
+      type: tosca.nodes.VBNGService
+      properties:
+          view_url: /admin/cord/vbngservice/$id$/
+# if unspecified, vbng observer will look for an ONOSApp Tenant and
+# generate a URL from its IP address
+#          vbng_url: http://10.11.10.24:8181/onos/virtualbng/
+
+    Private:
+      type: tosca.nodes.NetworkTemplate
+
+    management:
+      type: tosca.nodes.network.Network.XOS
+      properties:
+          no-create: true
+          no-delete: true
+          no-update: true
+
+    mysite:
+      type: tosca.nodes.Site
+
+    # Networks required by the CORD setup
+    mysite_vsg-access:
+      type: tosca.nodes.network.Network
+      properties:
+          ip_version: 4
+      requirements:
+          - network_template:
+              node: Private
+              relationship: tosca.relationships.UsesNetworkTemplate
+          - owner:
+              node: mysite_vsg
+              relationship: tosca.relationships.MemberOfSlice
+          - connection:
+              node: mysite_vsg
+              relationship: tosca.relationships.ConnectsToSlice
+
+    # CORD Slices
+    mysite_vsg:
+      description: vSG Controller Slice
+      type: tosca.nodes.Slice
+      properties:
+          network: noauto
+      requirements:
+          - vsg_service:
+              node: service_vsg
+              relationship: tosca.relationships.MemberOfService
+          - site:
+              node: mysite
+              relationship: tosca.relationships.MemberOfSite
+          - management:
+              node: management
+              relationship: tosca.relationships.ConnectsToNetwork
+
+    # Let's add a user who can be administrator of the household
+    johndoe@myhouse.com:
+      type: tosca.nodes.User
+      properties:
+          password: letmein
+          firstname: john
+          lastname: doe
+      requirements:
+          - site:
+              node: mysite
+              relationship: tosca.relationships.MemberOfSite
+
+    # A subscriber
+    My House:
+       type: tosca.nodes.CORDSubscriber
+       properties:
+           service_specific_id: 123
+           firewall_enable: false
+           cdn_enable: false
+           url_filter_enable: false
+           url_filter_level: R
+       requirements:
+          - house_admin:
+              node: johndoe@myhouse.com
+              relationship: tosca.relationships.AdminPrivilege
+
+    Mom's PC:
+       type: tosca.nodes.CORDUser
+       properties:
+           mac: 01:02:03:04:05:06
+           level: PG_13
+       requirements:
+           - household:
+               node: My House
+               relationship: tosca.relationships.SubscriberDevice
+
+    Dad's PC:
+       type: tosca.nodes.CORDUser
+       properties:
+           mac: 90:E2:BA:82:F9:75
+           level: PG_13
+       requirements:
+           - household:
+               node: My House
+               relationship: tosca.relationships.SubscriberDevice
+
+    Jack's Laptop:
+       type: tosca.nodes.CORDUser
+       properties:
+           mac: 68:5B:35:9D:91:D5
+           level: PG_13
+       requirements:
+           - household:
+               node: My House
+               relationship: tosca.relationships.SubscriberDevice
+
+    Jill's Laptop:
+       type: tosca.nodes.CORDUser
+       properties:
+           mac: 34:36:3B:C9:B6:A6
+           level: PG_13
+       requirements:
+           - household:
+               node: My House
+               relationship: tosca.relationships.SubscriberDevice
+
+    My Volt:
+        type: tosca.nodes.VOLTTenant
+        properties:
+            service_specific_id: 123
+            s_tag: 222
+            c_tag: 111
+        requirements:
+            - provider_service:
+                node: service_volt
+                relationship: tosca.relationships.MemberOfService
+            - subscriber:
+                node: My House
+                relationship: tosca.relationships.BelongsToSubscriber
diff --git a/xos/configurations/cord-pod/cord.yaml b/xos/configurations/cord-pod/cord.yaml
deleted file mode 100644
index c2d2fc8..0000000
--- a/xos/configurations/cord-pod/cord.yaml
+++ /dev/null
@@ -1,288 +0,0 @@
-tosca_definitions_version: tosca_simple_yaml_1_0
-
-description: Setup CORD-related services -- vOLT, vCPE, vBNG.
-
-imports:
-   - custom_types/xos.yaml
-
-topology_template:
-  node_templates:
-    # CORD Services
-    service_volt:
-      type: tosca.nodes.Service
-      requirements:
-          - vsg_tenant:
-              node: service_vsg
-              relationship: tosca.relationships.TenantOfService
-          - lan_network:
-              node: lan_network
-              relationship: tosca.relationships.UsesNetwork
-          - wan_network:
-              node: wan_network
-              relationship: tosca.relationships.UsesNetwork
-      properties:
-          view_url: /admin/cord/voltservice/$id$/
-          kind: vOLT
-
-    public_addresses:
-      type: tosca.nodes.AddressPool
-      properties:
-          addresses: 10.123.0.0/24 10.124.0.0/24
-
-    service_vsg:
-      type: tosca.nodes.VSGService
-      requirements:
-          - vbng_tenant:
-              node: service_vbng
-              relationship: tosca.relationships.TenantOfService
-      properties:
-          view_url: /admin/cord/vsgservice/$id$/
-          backend_network_label: hpc_client
-          public_key: { get_artifact: [ SELF, pubkey, LOCAL_FILE] }
-          private_key_fn: /opt/xos/synchronizers/vcpe/vcpe_private_key
-      artifacts:
-          pubkey: /opt/xos/synchronizers/vcpe/vcpe_public_key
-
-    service_vbng:
-      type: tosca.nodes.VBNGService
-      properties:
-          view_url: /admin/cord/vbngservice/$id$/
-# if unspecified, vbng observer will look for an ONOSApp Tenant and
-# generate a URL from its IP address
-#          vbng_url: http://10.11.10.24:8181/onos/virtualbng/
-
-    service_ONOS_vBNG:
-      type: tosca.nodes.ONOSService
-      requirements:
-      properties:
-          kind: onos
-          view_url: /admin/onos/onosservice/$id$/
-          no_container: true
-          rest_hostname: onos-cord
-
-#
-# To actually bring up the vBNG app
-# - Set up the dataplane using the ansible script
-# - Log into the vBNG ONOS and run 'devices' to get switch dpID
-# - Change the dpID values in vBNG ONOS app in XOS GUI
-# - (Synchronizer should copy the files to ONOS container immediately)
-# - Log into service_ONOS_vBNG VM and restart ONOS Docker container
-#   (Should roll this step into a Synchronizer)
-#f
-    vBNG_ONOS_app:
-      type: tosca.nodes.ONOSvBNGApp
-      requirements:
-          - onos_tenant:
-              node: service_ONOS_vBNG
-              relationship: tosca.relationships.TenantOfService
-          - vbng_service:
-              node: service_vbng
-              relationship: tosca.relationships.UsedByService
-      properties:
-          dependencies: org.onosproject.proxyarp, org.onosproject.virtualbng, org.onosproject.openflow, org.onosproject.fwd
-          config_network-cfg.json: >
-            {
-              "ports" : {
-                "of:0000000000000001/1" : {
-                  "interfaces" : [
-                    {
-                      "ips"  : [ "10.0.1.253/24" ],
-                      "mac"  : "00:00:00:00:00:99"
-                    }
-                  ]
-                },
-                "of:0000000000000001/2" : {
-                  "interfaces" : [
-                    {
-                      "ips"  : [ "10.254.0.2/24" ],
-                      "mac"  : "00:00:00:00:00:98"
-                    }
-                  ]
-                }
-              }
-            }
-          config_virtualbng.json: { get_artifact: [ SELF, virtualbng_json, LOCAL_FILE] }
-      artifacts:
-          virtualbng_json: /root/setup/virtualbng.json
-
-    service_ONOS_vOLT:
-      type: tosca.nodes.ONOSService
-      requirements:
-      properties:
-          kind: onos
-          view_url: /admin/onos/onosservice/$id$/
-          no_container: true
-          rest_hostname: onos-cord
-          rest_onos/v1/network/configuration/: >
-            {
-              "devices" : {
-                "of:0000000000000001" : {
-                  "accessDevice" : {
-                    "uplink" : "2",
-                    "vlan"   : "222",
-                    "defaultVlan" : "1"
-                  },
-                  "basic" : {
-                    "driver" : "pmc-olt"
-                  }
-                }
-              }
-            }
-
-
-    vOLT_ONOS_app:
-      type: tosca.nodes.ONOSvOLTApp
-      requirements:
-          - onos_tenant:
-              node: service_ONOS_vOLT
-              relationship: tosca.relationships.TenantOfService
-          - volt_service:
-              node: service_volt
-              relationship: tosca.relationships.UsedByService
-      properties:
-          install_dependencies: onos-ext-notifier-1.0-SNAPSHOT.oar, onos-ext-volt-event-publisher-1.0-SNAPSHOT.oar
-          dependencies: org.onosproject.openflow-base, org.onosproject.olt, org.ciena.onos.ext_notifier, org.ciena.onos.volt_event_publisher
-          component_config: >
-             {
-                "org.ciena.onos.ext_notifier.KafkaNotificationBridge":{
-                   "rabbit.user": "<rabbit_user>",
-                   "rabbit.password": "<rabbit_password>",
-                   "rabbit.host": "<rabbit_host>",
-                   "publish.kafka": "false",
-                   "publish.rabbit": "true",
-                   "volt.events.rabbit.topic": "notifications.info",
-                   "volt.events.rabbit.exchange": "voltlistener",
-                   "volt.events.opaque.info": "{project_id: <keystone_tenant_id>, user_id: <keystone_user_id>}",
-                   "publish.volt.events": "true"
-                }
-             }
-#          config_network-cfg.json: >
-#            {
-#              "devices" : {
-#                "of:0000000000000001" : {
-#                  "accessDevice" : {
-#                    "uplink" : "2",
-#                    "vlan"   : "222",
-#                    "defaultVlan" : "1"
-#                  },
-#                  "basic" : {
-#                    "driver" : "default"
-#                  }
-#                }
-#              }
-#            }
-
-    # Network templates
-    Private:
-      type: tosca.nodes.NetworkTemplate
-
-    mysite:
-      type: tosca.nodes.Site
-
-    # CORD Slices
-    mysite_vsg:
-      description: vSG Controller Slice
-      type: tosca.nodes.Slice
-      requirements:
-          - vsg_service:
-              node: service_vsg
-              relationship: tosca.relationships.MemberOfService
-          - site:
-              node: mysite
-              relationship: tosca.relationships.MemberOfSite
-          - vsg_docker_image:
-              node: docker-vsg
-              relationship: tosca.relationships.UsesImage
-#      properties:
-#          default_isolation: container
-
-    # docker image for vSG containers
-    docker-vsg:
-      # TODO: need to attach this to mydeployment
-      type: tosca.nodes.Image
-      properties:
-        kind: container
-        container_format: na
-        disk_format: na
-        path: andybavier/docker-vcpe
-        tag: develop
-
-    # Let's add a user who can be administrator of the household
-    johndoe@myhouse.com:
-      type: tosca.nodes.User
-      properties:
-          password: letmein
-          firstname: john
-          lastname: doe
-      requirements:
-          - site:
-              node: mysite
-              relationship: tosca.relationships.MemberOfSite
-
-    # A subscriber
-    My House:
-       type: tosca.nodes.CORDSubscriber
-       properties:
-           service_specific_id: 123
-           firewall_enable: false
-           cdn_enable: false
-           url_filter_enable: false
-           url_filter_level: R
-       requirements:
-          - house_admin:
-              node: johndoe@myhouse.com
-              relationship: tosca.relationships.AdminPrivilege
-
-    Mom's PC:
-       type: tosca.nodes.CORDUser
-       properties:
-           mac: 01:02:03:04:05:06
-           level: PG_13
-       requirements:
-           - household:
-               node: My House
-               relationship: tosca.relationships.SubscriberDevice
-
-    Dad's PC:
-       type: tosca.nodes.CORDUser
-       properties:
-           mac: 90:E2:BA:82:F9:75
-           level: PG_13
-       requirements:
-           - household:
-               node: My House
-               relationship: tosca.relationships.SubscriberDevice
-
-    Jack's Laptop:
-       type: tosca.nodes.CORDUser
-       properties:
-           mac: 68:5B:35:9D:91:D5
-           level: PG_13
-       requirements:
-           - household:
-               node: My House
-               relationship: tosca.relationships.SubscriberDevice
-
-    Jill's Laptop:
-       type: tosca.nodes.CORDUser
-       properties:
-           mac: 34:36:3B:C9:B6:A6
-           level: PG_13
-       requirements:
-           - household:
-               node: My House
-               relationship: tosca.relationships.SubscriberDevice
-
-    My Volt:
-        type: tosca.nodes.VOLTTenant
-        properties:
-            service_specific_id: 123
-            s_tag: 222
-            c_tag: 432
-        requirements:
-            - provider_service:
-                node: service_volt
-                relationship: tosca.relationships.MemberOfService
-            - subscriber:
-                node: My House
-                relationship: tosca.relationships.BelongsToSubscriber
diff --git a/xos/configurations/cord-pod/docker-compose.yml b/xos/configurations/cord-pod/docker-compose.yml
index 6ea8c13..6f442af 100644
--- a/xos/configurations/cord-pod/docker-compose.yml
+++ b/xos/configurations/cord-pod/docker-compose.yml
@@ -13,9 +13,10 @@
         - xos_db
     volumes:
         - ../common/xos_common_config:/opt/xos/xos_configuration/xos_common_config:ro
-	- ../cord//xos_cord_config:/opt/xos/xos_configuration/xos_cord_config:ro
+        - ../cord//xos_cord_config:/opt/xos/xos_configuration/xos_cord_config:ro
         - .:/root/setup:ro
         - ../vtn/files/xos_vtn_config:/opt/xos/xos_configuration/xos_vtn_config:ro
+        - ./images:/opt/xos/images:ro
 
 xos_synchronizer_onos:
     image: xosproject/xos-synchronizer-openstack
@@ -29,17 +30,28 @@
         - .:/root/setup:ro
         - ./id_rsa:/opt/xos/synchronizers/onos/onos_key:ro  # private key
 
-#xos_synchronizer_vcpe:
-#    image: xosproject/xos-synchronizer-openstack
-#    command: bash -c "sleep 120; python /opt/xos/synchronizers/vcpe/vcpe-synchronizer.py -C /root/setup/files/vcpe_synchronizer_config"
-#    labels:
-#        org.xosproject.kind: synchronizer
-#        org.xosproject.target: vcpe
-#    links:
-#        - xos_db
-#    volumes:
-#        - .:/root/setup:ro
-#        - ./id_rsa:/opt/xos/synchronizers/vcpe/vcpe_private_key:ro  # private key
+xos_synchronizer_vcpe:
+    image: xosproject/xos-synchronizer-openstack
+    command: bash -c "sleep 120; cp /root/setup/node_key /opt/xos/synchronizers/vcpe/; chmod 0600 /opt/xos/synchronizers/vcpe/node_key; python /opt/xos/synchronizers/vcpe/vcpe-synchronizer.py -C /root/setup/files/vcpe_synchronizer_config"
+    labels:
+        org.xosproject.kind: synchronizer
+        org.xosproject.target: vcpe
+    links:
+        - xos_db
+    volumes:
+        - .:/root/setup:ro
+        - ./id_rsa:/opt/xos/synchronizers/vcpe/vcpe_private_key:ro  # private key
+
+xos_synchronizer_vtn:
+    image: xosproject/xos-synchronizer-openstack
+    command: bash -c "sleep 120; python /opt/xos/synchronizers/vtn/vtn-synchronizer.py -C /opt/xos/synchronizers/vtn/vtn_synchronizer_config"
+    labels:
+        org.xosproject.kind: synchronizer
+        org.xosproject.target: vtn
+    links:
+        - xos_db
+    volumes:
+        - .:/root/setup:ro
 
 #xos_synchronizer_vbng:
 #    image: xosproject/xos-synchronizer-openstack
@@ -74,3 +86,4 @@
         - ../cord/xos_cord_config:/opt/xos/xos_configuration/xos_cord_config:ro
         - ../vtn/files/xos_vtn_config:/opt/xos/xos_configuration/xos_vtn_config:ro
         - ./id_rsa.pub:/opt/xos/synchronizers/onos/onos_key.pub:ro
+        - ./id_rsa.pub:/opt/xos/synchronizers/vcpe/vcpe_public_key:ro
diff --git a/xos/configurations/cord-pod/files/vcpe_synchronizer_config b/xos/configurations/cord-pod/files/vcpe_synchronizer_config
index 6ace486..46ee0c3 100644
--- a/xos/configurations/cord-pod/files/vcpe_synchronizer_config
+++ b/xos/configurations/cord-pod/files/vcpe_synchronizer_config
@@ -34,10 +34,13 @@
 backoff_disabled=True
 save_ansible_output=True
 # set proxy_ssh to false on cloudlab
+full_setup=True
 proxy_ssh=True
 proxy_ssh_key=/root/setup/node_key
 proxy_ssh_user=root
-full_setup=True
+
+[networking]
+use_vtn=True
 
 [feefie]
 client_id='vicci_dev_central'
diff --git a/xos/configurations/cord-pod/images/README.md b/xos/configurations/cord-pod/images/README.md
new file mode 100644
index 0000000..aca55a9
--- /dev/null
+++ b/xos/configurations/cord-pod/images/README.md
@@ -0,0 +1,5 @@
+# VM images for XOS
+
+Any Cloud image files placed in this directory (with suffix .img) will be automatically
+imported by XOS and added to Glance (OpenStack's image repository).  For instance, the image
+`trusty-server-multi-nic.img` will be imported with name `trusty-server-multi-nic`.
diff --git a/xos/configurations/cord-pod/make-virtualbng-json.sh b/xos/configurations/cord-pod/make-virtualbng-json.sh
new file mode 100644
index 0000000..993643c
--- /dev/null
+++ b/xos/configurations/cord-pod/make-virtualbng-json.sh
@@ -0,0 +1,38 @@
+FN=$SETUPDIR/virtualbng.json
+
+rm -f $FN
+
+cat >> $FN <<EOF
+{
+    "localPublicIpPrefixes" : [
+        "10.254.0.128/25"
+    ],
+    "nextHopIpAddress" : "10.254.0.1",
+    "publicFacingMac" : "00:00:00:00:00:66",
+    "xosIpAddress" : "10.11.10.1",
+    "xosRestPort" : "9999",
+    "hosts" : {
+EOF
+
+NODES=$( sudo bash -c "source $SETUPDIR/admin-openrc.sh ; nova hypervisor-list" |grep -v ID|grep -v +|awk '{print $4}' )
+
+NODECOUNT=0
+for NODE in $NODES; do
+    ((NODECOUNT++))
+done
+
+I=0
+for NODE in $NODES; do
+    echo $NODE
+    ((I++))
+    if [[ "$I" -lt "$NODECOUNT" ]]; then
+        echo "      \"$NODE\" : \"of:0000000000000001/1\"," >> $FN
+    else
+        echo "      \"$NODE\" : \"of:0000000000000001/1\"" >> $FN
+    fi
+done
+
+cat >> $FN <<EOF
+    }
+}
+EOF
diff --git a/xos/configurations/cord-pod/make-vtn-networkconfig-json.sh b/xos/configurations/cord-pod/make-vtn-networkconfig-json.sh
index 309df5e..5239267 100755
--- a/xos/configurations/cord-pod/make-vtn-networkconfig-json.sh
+++ b/xos/configurations/cord-pod/make-vtn-networkconfig-json.sh
@@ -9,12 +9,18 @@
     "apps" : {
         "org.onosproject.cordvtn" : {
             "cordvtn" : {
-                "gatewayMac" : "00:00:00:00:00:01",
-                "localManagementIp": "10.90.0.147/24",
+                "privateGatewayMac" : "00:00:00:00:00:01",
+                "localManagementIp": "172.27.0.1/24",
                 "ovsdbPort": "6641",
                 "sshPort": "22",
                 "sshUser": "root",
                 "sshKeyFile": "/root/node_key",
+                "publicGateways": [
+                    {
+                        "gatewayIp": "207.141.192.158",
+                        "gatewayMac": "a4:23:05:34:56:78"
+                    }
+                ],
                 "nodes" : [
 EOF
 
@@ -37,7 +43,7 @@
 
     PHYPORT=mlx0
     # How to set LOCALIP?
-    LOCALIP=10.0.2.1
+    LOCALIPNET="192.168.199"
 
     ((I++))
     cat >> $FN <<EOF
@@ -46,7 +52,7 @@
                       "hostManagementIp": "$NODEIP/24",
                       "bridgeId": "of:000000000000000$I",
                       "dataPlaneIntf": "$PHYPORT",
-                      "dataPlaneIp": "$LOCALIP/24"
+                      "dataPlaneIp": "$LOCALIPNET.$I/24"
 EOF
     if [[ "$I" -lt "$NODECOUNT" ]]; then
         echo "                    }," >> $FN
diff --git a/xos/configurations/cord-pod/mgmt-net.yaml b/xos/configurations/cord-pod/mgmt-net.yaml
new file mode 100644
index 0000000..2bd0173
--- /dev/null
+++ b/xos/configurations/cord-pod/mgmt-net.yaml
@@ -0,0 +1,40 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: Set up management network for CORD POD
+imports:
+   - custom_types/xos.yaml
+
+topology_template:
+  node_templates:
+
+    management_template:
+      type: tosca.nodes.NetworkTemplate
+      properties:
+          visibility: private
+          translation: none
+
+    management:
+      type: tosca.nodes.network.Network
+      properties:
+          ip_version: 4
+          cidr: 172.27.0.0/24
+      requirements:
+          - network_template:
+              node: management_template
+              relationship: tosca.relationships.UsesNetworkTemplate
+          - owner:
+              node: mysite_management
+              relationship: tosca.relationships.MemberOfSlice
+
+    mysite:
+      type: tosca.nodes.Site
+
+    mysite_management:
+      description: This slice exists solely to own the management network
+      type: tosca.nodes.Slice
+      properties:
+          network: noauto
+      requirements:
+          - site:
+              node: mysite
+              relationship: tosca.relationships.MemberOfSite
diff --git a/xos/configurations/cord-pod/vtn-external.yaml b/xos/configurations/cord-pod/vtn-external.yaml
index eed1d1c..0aaee67 100644
--- a/xos/configurations/cord-pod/vtn-external.yaml
+++ b/xos/configurations/cord-pod/vtn-external.yaml
@@ -1,12 +1,13 @@
 tosca_definitions_version: tosca_simple_yaml_1_0
 
-description: Setup CORD-related services -- vOLT, vCPE, vBNG.
+description: Set up ONOS VTN app
 
 imports:
    - custom_types/xos.yaml
 
 topology_template:
   node_templates:
+
     service_ONOS_VTN:
       type: tosca.nodes.ONOSService
       requirements:
@@ -23,7 +24,7 @@
               node: service_ONOS_VTN
               relationship: tosca.relationships.TenantOfService
       properties:
-          dependencies: org.onosproject.drivers, org.onosproject.drivers.ovsdb, org.onosproject.lldpprovider, org.onosproject.openflow-base, org.onosproject.ovsdb-base, org.onosproject.dhcp, org.onosproject.openstackswitching, org.onosproject.cordvtn
+          dependencies: org.onosproject.drivers, org.onosproject.drivers.ovsdb, org.onosproject.openflow-base, org.onosproject.ovsdb-base, org.onosproject.dhcp, org.onosproject.cordvtn, org.onosproject.olt, org.onosproject.igmp, org.onosproject.cordmcast
           rest_onos/v1/network/configuration/: { get_artifact: [ SELF, vtn_network_cfg_json, LOCAL_FILE ] }
       artifacts:
           vtn_network_cfg_json: /root/setup/vtn-network-cfg.json
diff --git a/xos/configurations/cord/README-VTN.md b/xos/configurations/cord/README-VTN.md
index 2d9b7aa..b3c0c61 100644
--- a/xos/configurations/cord/README-VTN.md
+++ b/xos/configurations/cord/README-VTN.md
@@ -1,4 +1,4 @@
-vtn notes:
+# vtn notes:
 
 see also: https://github.com/hyunsun/documentations/wiki/Neutron-ONOS-Integration-for-CORD-VTN#onos-setup
 
@@ -15,7 +15,7 @@
         use_vtn=True
     supervisorctl restart observer
 
-ctl node:
+### ctl node:
 
     # set ONOS_VTN_HOSTNAME to the host where the VTN container was installed
     ONOS_VTN_HOSTNAME="cp-2.smbaker-xos5.xos-pg0.clemson.cloudlab.us"
@@ -30,7 +30,7 @@
     # not still an issue lurking...
     cat > /usr/local/etc/neutron/plugins/ml2/conf_onos.ini <<EOF
     [onos]
-    url_path = http://$ONOS_VTN_HOSTNAME:8181/onos/openstackswitching
+    url_path = http://$ONOS_VTN_HOSTNAME:8181/onos/cordvtn
     username = karaf
     password = karaf
     EOF
@@ -41,7 +41,7 @@
     # files. Maybe it can be restarted using systemctl instead...
     /usr/bin/neutron-server --config-file /etc/neutron/neutron.conf --config-file /etc/neutron/plugins/ml2/ml2_conf.ini --config-file /usr/local/etc/neutron/plugins/ml2/conf_onos.ini
 
-Compute nodes and nm nodes:
+### Compute nodes and nm nodes:
 
     cd xos/configurations/cord/dataplane
     ./generate-bm.sh > hosts-bm
@@ -55,22 +55,14 @@
 
 Additional compute node stuff:
 
-Br-flat-lan-1 needs to be deleted, since VTN will be attaching br-int directly to the eth device that br-flat-lan-1 was using. Additionally, we need to assign an IP address to br-int (sounds like Hyunsun is working on having VTN do that for us). Adding the route was not in Hyunsun's instructions, but I found I had to do it in order to get the compute nodes to talk to one another.
+I've been deleting any existing unused bridges. Not sure if it's necesary.
 
     ovs-vsctl del-br br-tun
     ovs-vsctl del-br br-flat-lan-1
-    ip addr add <addr-that-was-assinged-to-flat-lan-1> dev br-int
-    ip link set br-int up
-    ip route add <network-that-was-assigned-to-flat-lan-1>/24 dev br-int
-    
-To get the management network working, we need to create management network template, slice, and network. configurations/cord/vtn.yaml will do this for you. Then add a connection to the management network for any slice that needs management connectivity. Note the subnet that gets assigned to the management network. Management-gateway-ip is the .1 address on the subnet. On the compute node:
 
-    ip addr add <management-gateway-ip>/24 dev br-int
+To get the management network working, we need to create management network template, slice, and network. configurations/cord/vtn.yaml will do this for you. Then add a connection to the management network for any slice that needs management connectivity.
     
-For development, I suggest using the bash configuration (remember to start the ONOS observer manually) so that 
-there aren't a bunch of preexisting Neutron networks and nova instances to get in the way. 
-
-Notes:
+### Notes:
 * I've configured the OpenvSwitch switches to use port 6641 instead of port 6640. This is because the VTN app listens on 6640
 itself, and since we're running it in docker 'host' networking mode now, it would conflict with an Openvswitch that was
 also listening on 6640.
@@ -79,7 +71,7 @@
 * Note that the VTN Synchronizer isn't started automatically. It's only use for inter-Service connectivity, so no need to mess with it until intra-Slice connectivity is working first. 
 * Note that the VTN Synchronizer won't connect non-access networks. Any network templates you want VTN to connect must have Access set to "Direct" or "Indirect". 
 
-There is no management network yet, so no way to SSH into the slices. I've been setting up a VNC tunnel, like this:
+In case management network isn't working, you can use a VNC tunnel, like this:
 
     # on compute node, run the following and note the IP address and port number
     virsh vncdisplay <instance-id>
@@ -92,13 +84,13 @@
 
 Then open a VNC session to the local port on your local machine. You'll have a console on the Instance. The username is "Ubuntu" and the password can be obtained from your cloudlab experiment description
 
-Things that can be tested:
+### Things that can be tested:
 
 * Create an Instance, it should have a Private network, and there should be a tap attached from the instance to br-int
 * Two Instances in the same Slice can talk to one another. They can be on the same machine or different machines.
 * Two Slices can talk to one another if the slices are associated with Services and those Services have a Tenancy relationship between them. Note that 1) The VTN Synchronizer must be running, 2) There must be a Private network with Access=[Direct|Indirect], and 3) The connectivity is unidirectional, from subscriber service to provider service.
 
-Testing service composition
+### Testing service composition
 
 1. Change the private network template's 'Access' field from None to Direct
 2. Create a Service, Service-A
@@ -113,3 +105,47 @@
 11. You should see the pings arrive and responses sent out. Note that the ping responses will not reach Slice-1, since VTN traffic is unidirectional.
 12. Delete the Tenancy relation you created in Step #7. The ping traffic should no longer appear in the tcpdump.
 
+### Getting external connectivity working on cloudlab
+
+On head node:
+
+    ovs-vsctl del-br br-flat-lan-1
+    ifconfig eth2 10.123.0.1
+    iptables --table nat --append POSTROUTING --out-interface br-ex -j MASQUERADE
+    arp -s 10.123.0.3 fa:16:3e:ea:11:0a
+    
+Substitute for your installation:
+
+    10.123.0.3 = wan_ip of vSG
+    10.123.0.1 = wan gateway
+    fa:16:3e:ea:11:0a = wan_mac of vSG
+    00:8c:fa:5b:09:d8 = wan_mac of gateway
+    
+### Setting up a test-client
+
+Before setting up VTN, create a bridge and attach it to the dataplane device on each compute node:
+
+    brctl addbr br-inject
+    brctl addif br-inject eth3   # substitute dataplane eth device here, may be different on each compute node
+    ip link set br-inject up
+    ip link set dev br-inject promisc on
+    
+Then update the network-config attribute of the VTN ONOS App in XOS to use a dataplaneIntf of br-inject instead of the eth device. Bring up VTN and a VSG. WAN connectivity and everything else should be working fine. 
+
+Add a new slice, mysite_client, and make sure to give it both a private and a management network. Bring up an instance on the same node as the vSG you want to test. On the compute node, run the following:
+
+    $MAC=<make-up-some-mac>
+    $INSTANCE=<instance-id>
+    virsh attach-interface --domain $INSTANCE --type bridge --source br-inject --model virtio --mac $MAC --config --live
+    
+Log into the vSG via the management interface. Inside of the vSG run the following:
+
+    STAG=<your s-tag here>
+    CTAG=<your c-tag here>
+    ip link add link eth2 eth2.$STAG type vlan id $STAG
+    ip link add link eth2.$STAG eth2.$STAG.$CTAG type vlan id $CTAG
+    ip link set eth2.$STAG up
+    ip link set eth2.$STAG.$CTAG up
+    ip addr add 192.168.0.2/24 dev eth2.$STAG.$CTAG
+    ip route del default
+    ip route add default via 192.168.0.1
diff --git a/xos/configurations/cord/cord.yaml b/xos/configurations/cord/cord.yaml
index ec2cd6f..07d4b68 100644
--- a/xos/configurations/cord/cord.yaml
+++ b/xos/configurations/cord/cord.yaml
@@ -24,6 +24,7 @@
           view_url: /admin/cord/voltservice/$id$/
           kind: vOLT
 
+    # set a pool of addresses that we can hand out for the VSG Wan.
     public_addresses:
       type: tosca.nodes.AddressPool
       properties:
diff --git a/xos/configurations/cord/dataplane/cleanup.sh b/xos/configurations/cord/dataplane/cleanup.sh
index 9860de7..120454d 100755
--- a/xos/configurations/cord/dataplane/cleanup.sh
+++ b/xos/configurations/cord/dataplane/cleanup.sh
@@ -26,8 +26,11 @@
 echo "Waiting 5 seconds..."
 sleep 5
 
+cleanup_network lan_network
 cleanup_network wan_network
 cleanup_network mysite_vcpe-private
+cleanup_network mysite_vsg-access
+cleanup_network management
 
 echo "Deleting networks"
 # Delete all networks beginning with mysite_
@@ -42,3 +45,5 @@
 neutron net-delete public_network || true
 neutron net-delete hpc_client_network || true
 neutron net-delete ceilometer_network || true
+neutron net-delete management || true
+neutron net-delete mysite_vsg-access || true
diff --git a/xos/configurations/cord/make-vtn-networkconfig-json.sh b/xos/configurations/cord/make-vtn-networkconfig-json.sh
index 8a8b233..2cccd65 100644
--- a/xos/configurations/cord/make-vtn-networkconfig-json.sh
+++ b/xos/configurations/cord/make-vtn-networkconfig-json.sh
@@ -9,12 +9,18 @@
     "apps" : {
         "org.onosproject.cordvtn" : {
             "cordvtn" : {
-                "gatewayMac" : "00:00:00:00:00:01",
+                "privateGatewayMac" : "00:00:00:00:00:01",
                 "localManagementIp": "172.27.0.1/24",
                 "ovsdbPort": "6641",
                 "sshPort": "22",
                 "sshUser": "root",
                 "sshKeyFile": "/root/node_key",
+                "publicGateways": [
+                    {
+                        "gatewayIp": "10.123.0.1",
+                        "gatewayMac": "00:8c:fa:5b:09:d8"
+                    }
+                ],
                 "nodes" : [
 EOF
 
diff --git a/xos/configurations/frontend/Makefile b/xos/configurations/frontend/Makefile
index aad475d..5c0ce0e 100644
--- a/xos/configurations/frontend/Makefile
+++ b/xos/configurations/frontend/Makefile
@@ -25,6 +25,7 @@
 	sudo docker exec -ti frontend_xos_1 bash
 
 mock-cord:
+	sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/fixtures.yaml
 	sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/frontend/mocks/cord.yaml
 	sudo docker exec frontend_xos_1 cp /opt/xos/configurations/cord/xos_cord_config /opt/xos/xos_configuration/
 	sudo docker exec frontend_xos_1 touch /opt/xos/xos/settings.py
diff --git a/xos/configurations/opencloud/cdn-syndicate-content.yaml b/xos/configurations/opencloud/cdn-syndicate-content.yaml
new file mode 100644
index 0000000..06dc623
--- /dev/null
+++ b/xos/configurations/opencloud/cdn-syndicate-content.yaml
@@ -0,0 +1,52 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: Template for deploying a single server with predefined properties.
+
+imports:
+   - custom_types/xos.yaml
+   - custom_types/cdn.yaml
+
+topology_template:
+  node_templates:
+    HyperCache:
+      type: tosca.nodes.CDNService
+      properties:
+          # HyperCache service must already exist before running this recipe
+          no-create: true
+          no-delete: true
+          no-update: true
+
+    # Setup the Syndicate Devel Service Provider
+
+    main_service_provider:
+        type: tosca.nodes.ServiceProvider
+        requirements:
+           - hpc_service:
+                 node: HyperCache
+                 relationship: tosca.relationships.MemberOfService
+
+    syndicate_devel:
+        type: tosca.nodes.ContentProvider

+        requirements:

+            - service_provider:

+                  node: main_service_provider

+                  relationship: tosca.relationships.MemberOfServiceProvider
+
+#    http_node2.cs.arizona.edu:
+#        type: tosca.nodes.OriginServer

+#        requirements:

+#             - content_provider:

+#                   node: syndicate_devel

+#                   relationship: tosca.relationships.MemberOfContentProvider
+
+    syndicate-devel.opencloud.us:
+        type: tosca.nodes.CDNPrefix

+        requirements:

+             - content_provider:

+                   node: syndicate_devel

+                   relationship: tosca.relationships.MemberOfContentProvider

+

+#             - default_origin_server:

+#                   node: http_node2.cs.arizona.edu

+#                   relationship: tosca.relationships.DefaultOriginServer
+
diff --git a/xos/configurations/opencloud/docker-compose.yml b/xos/configurations/opencloud/docker-compose.yml
index 3813dee..b44c828 100644
--- a/xos/configurations/opencloud/docker-compose.yml
+++ b/xos/configurations/opencloud/docker-compose.yml
@@ -16,6 +16,7 @@
         - ../common/xos_common_config:/opt/xos/xos_configuration/xos_common_config:ro
         - /usr/local/share/ca-certificates:/usr/local/share/ca-certificates:ro
         - ./files/xos_opencloud_config:/opt/xos/xos_configuration/xos_opencloud_config:ro
+        - ./images:/opt/xos/images:ro
 
 xos_synchronizer_hpc:
     image: xosproject/xos-synchronizer-openstack
diff --git a/xos/configurations/test/README b/xos/configurations/test/README.md
similarity index 86%
rename from xos/configurations/test/README
rename to xos/configurations/test/README.md
index 31f7786..37af594 100644
--- a/xos/configurations/test/README
+++ b/xos/configurations/test/README.md
@@ -1,2 +1,4 @@
+#CORD Test Configuration
+
 This configuration launches the XOS container on cloudlab and runs a test suite. The test results will be printed to
 the console, and then the docker container will exit. 
diff --git a/xos/configurations/vtn/cord-vtn-vsg.yaml b/xos/configurations/vtn/cord-vtn-vsg.yaml
index bcb6847..1b26bba 100644
--- a/xos/configurations/vtn/cord-vtn-vsg.yaml
+++ b/xos/configurations/vtn/cord-vtn-vsg.yaml
@@ -34,6 +34,10 @@
           backend_network_label: hpc_client
           public_key: { get_artifact: [ SELF, pubkey, LOCAL_FILE] }
           private_key_fn: /opt/xos/synchronizers/vcpe/vcpe_private_key
+          wan_container_gateway_ip: 10.123.0.1
+          wan_container_gateway_mac: 00:8c:fa:5b:09:d8
+          wan_container_netbits: 24
+          dns_servers: 8.8.8.8, 8.8.4.4
       artifacts:
           pubkey: /opt/xos/synchronizers/vcpe/vcpe_public_key
 
diff --git a/xos/configurations/vtn/docker-compose.yml b/xos/configurations/vtn/docker-compose.yml
index 7fb68f1..0fa718b 100644
--- a/xos/configurations/vtn/docker-compose.yml
+++ b/xos/configurations/vtn/docker-compose.yml
@@ -42,7 +42,7 @@
 
 xos:
     image: xosproject/xos
-    command: python /opt/xos/manage.py runserver 0.0.0.0:8000 --insecure --makemigrations
+    command: bash -c "python /opt/xos/manage.py runserver 0.0.0.0:8000 --insecure --makemigrations"
     ports:
         - "9999:8000"
     links:
diff --git a/xos/configurations/vtn/vtn.yaml b/xos/configurations/vtn/vtn.yaml
index 9b36852..3928ba1 100644
--- a/xos/configurations/vtn/vtn.yaml
+++ b/xos/configurations/vtn/vtn.yaml
@@ -58,7 +58,7 @@
               node: service_ONOS_VTN
               relationship: tosca.relationships.TenantOfService
       properties:
-          dependencies: org.onosproject.drivers, org.onosproject.drivers.ovsdb, org.onosproject.lldpprovider, org.onosproject.openflow-base, org.onosproject.ovsdb-base, org.onosproject.dhcp, org.onosproject.openstackswitching, org.onosproject.cordvtn
+          dependencies: org.onosproject.drivers, org.onosproject.drivers.ovsdb, org.onosproject.lldpprovider, org.onosproject.openflow-base, org.onosproject.ovsdb-base, org.onosproject.dhcp, org.onosproject.cordvtn
           rest_onos/v1/network/configuration/: { get_artifact: [ SELF, vtn_network_cfg_json, LOCAL_FILE ] }
       artifacts:
           vtn_network_cfg_json: /root/setup/vtn-network-cfg.json
diff --git a/xos/core/admin.py b/xos/core/admin.py
index c6e3e93..28d99fd 100644
--- a/xos/core/admin.py
+++ b/xos/core/admin.py
@@ -1256,7 +1256,7 @@
                ]
     readonly_fields = ('backend_status_text', )
 
-    suit_form_tabs =(('general','Image Details'),('instances','Instances'),('imagedeployments','Deployments'), ('controllerimages', 'Controllers'))
+    suit_form_tabs =(('general','Image Details'),('instances','Instances'),('imagedeployments','Deployments'), ('admin-only', 'Admin-Only'))
 
     inlines = [InstanceInline, ControllerImagesInline]
 
@@ -1898,7 +1898,7 @@
     suit_form_tabs = (('general','Network Template Details'), ('netparams', 'Parameters') )
 
 class PortAdmin(XOSBaseAdmin):
-    list_display = ("backend_status_icon", "name", "id", "ip")
+    list_display = ("backend_status_icon", "id", "ip")
     list_display_links = ('backend_status_icon', 'id')
     readonly_fields = ("subnet", )
     inlines = [NetworkParameterInline]
diff --git a/xos/core/models/network.py b/xos/core/models/network.py
index 0dc6d4a..80ee9ba 100644
--- a/xos/core/models/network.py
+++ b/xos/core/models/network.py
@@ -259,6 +259,7 @@
     ip = models.GenericIPAddressField(help_text="Instance ip address", blank=True, null=True)
     port_id = models.CharField(null=True, blank=True, max_length=256, help_text="Neutron port id")
     mac = models.CharField(null=True, blank=True, max_length=256, help_text="MAC address associated with this port")
+    xos_created = models.BooleanField(default=False) # True if XOS created this port in Neutron, False if port created by Neutron and observed by XOS
 
     class Meta:
         unique_together = ('network', 'instance')
@@ -348,20 +349,32 @@
         with transaction.atomic():
             ap = AddressPool.objects.get(pk=self.pk)
             if ap.addresses:
-                addresses = ap.addresses or ""
-                parts = addresses.split()
-                addr = parts.pop(0)
-                ap.addresses = " ".join(parts)
-
-                inuse = ap.inuse or ""
-                parts = inuse.split()
-                if not (addr in parts):
-                    parts.insert(0,addr)
-                    ap.inuse = " ".join(parts)
-
-                ap.save()
+                avail_ips = ap.addresses.split()
             else:
-                addr = None
+                avail_ips = []
+
+            if ap.inuse:
+                inuse_ips = ap.inuse.split()
+            else:
+                inuse_ips = []
+
+            while avail_ips:
+                addr = avail_ips.pop(0)
+
+                if addr in inuse_ips:
+                    # This may have happened if someone re-ran the tosca
+                    # recipe and 'refilled' the AddressPool while some addresses
+                    # were still in use.
+                    continue
+
+                inuse_ips.insert(0,addr)
+
+                ap.inuse = " ".join(inuse_ips)
+                ap.addresses = " ".join(avail_ips)
+                ap.save()
+                return addr
+
+            addr = None
         return addr
 
     def put_address(self, addr):
diff --git a/xos/core/models/tag.py b/xos/core/models/tag.py
index d774800..76a4e2e 100644
--- a/xos/core/models/tag.py
+++ b/xos/core/models/tag.py
@@ -27,6 +27,10 @@
     def can_update(self, user):
         return user.can_update_root()
 
+    @classmethod
+    def select_by_content_object(cls, obj):
+        return cls.objects.filter(content_type=ContentType.objects.get_for_model(obj), object_id=obj.id)
+
     @staticmethod
     def select_by_user(user):
         return Tag.objects.all()
diff --git a/xos/core/xoslib/methods/ceilometerview.py b/xos/core/xoslib/methods/ceilometerview.py
index 5f99b61..9e46aa7 100644
--- a/xos/core/xoslib/methods/ceilometerview.py
+++ b/xos/core/xoslib/methods/ceilometerview.py
@@ -1246,8 +1246,13 @@
                 query = make_query(tenant_id=meter["project_id"],resource_id=meter["resource_id"])
                 if additional_query:
                     query = query + additional_query
-                statistics = statistic_list(request, meter["name"],
+                try:
+                    statistics = statistic_list(request, meter["name"],
                                         ceilometer_url=tenant_ceilometer_url, query=query, period=3600*24)
+                except Exception as e:
+                    logger.error('Exception during statistics query for meter %(meter)s and reason:%(reason)s' % {'meter':meter["name"], 'reason':str(e)})
+                    statistics = None
+
                 if not statistics:
                     continue
                 statistic = statistics[-1]
@@ -1398,8 +1403,13 @@
                     query = make_query(tenant_id=meter["project_id"],resource_id=meter["resource_id"])
                     if additional_query:
                         query = query + additional_query
-                    statistics = statistic_list(request, meter["name"],
+                    try:
+                        statistics = statistic_list(request, meter["name"],
                                             ceilometer_url=tenant_ceilometer_url, query=query, period=3600*24)
+                    except Exception as e:
+                        logger.error('Exception during statistics query for meter %(meter)s and reason:%(reason)s' % {'meter':meter["name"], 'reason':str(e)})
+                        statistics = None
+
                     if not statistics:
                         continue
                     statistic = statistics[-1]
diff --git a/xos/model_autodeletion.py b/xos/model_autodeletion.py
index 2bfc48c..6eaf63c 100644
--- a/xos/model_autodeletion.py
+++ b/xos/model_autodeletion.py
@@ -1 +1 @@
-ephemeral_models = ['ReservedResource','Instance','Image','Network','Port','Tag','SitePrivilege','SliceMembership','SliceTag','Reservation','Slice']
+ephemeral_models = ['ReservedResource','Instance','Image','Network','Tag','SitePrivilege','SliceMembership','SliceTag','Reservation','Slice']
diff --git a/xos/services/cord/admin.py b/xos/services/cord/admin.py
index 71cae5f..76b505c 100644
--- a/xos/services/cord/admin.py
+++ b/xos/services/cord/admin.py
@@ -104,6 +104,10 @@
     bbs_server = forms.CharField(required=False)
     backend_network_label = forms.CharField(required=False)
     bbs_slice = forms.ModelChoiceField(queryset=Slice.objects.all(), required=False)
+    wan_container_gateway_ip = forms.CharField(required=False)
+    wan_container_gateway_mac = forms.CharField(required=False)
+    wan_container_netbits = forms.CharField(required=False)
+    dns_servers = forms.CharField(required=False)
 
     def __init__(self,*args,**kwargs):
         super (VSGServiceForm,self ).__init__(*args,**kwargs)
@@ -113,6 +117,10 @@
             self.fields['bbs_server'].initial = self.instance.bbs_server
             self.fields['backend_network_label'].initial = self.instance.backend_network_label
             self.fields['bbs_slice'].initial = self.instance.bbs_slice
+            self.fields['wan_container_gateway_ip'].initial = self.instance.wan_container_gateway_ip
+            self.fields['wan_container_gateway_mac'].initial = self.instance.wan_container_gateway_mac
+            self.fields['wan_container_netbits'].initial = self.instance.wan_container_netbits
+            self.fields['dns_servers'].initial = self.instance.dns_servers
 
     def save(self, commit=True):
         self.instance.bbs_api_hostname = self.cleaned_data.get("bbs_api_hostname")
@@ -120,6 +128,10 @@
         self.instance.bbs_server = self.cleaned_data.get("bbs_server")
         self.instance.backend_network_label = self.cleaned_data.get("backend_network_label")
         self.instance.bbs_slice = self.cleaned_data.get("bbs_slice")
+        self.instance.wan_container_gateway_ip = self.cleaned_data.get("wan_container_gateway_ip")
+        self.instance.wan_container_gateway_mac = self.cleaned_data.get("wan_container_gateway_mac")
+        self.instance.wan_container_netbits = self.cleaned_data.get("wan_container_netbits")
+        self.instance.dns_servers = self.cleaned_data.get("dns_servers")
         return super(VSGServiceForm, self).save(commit=commit)
 
     class Meta:
@@ -127,14 +139,16 @@
 
 class VSGServiceAdmin(ReadOnlyAwareAdmin):
     model = VSGService
-    verbose_name = "vCPE Service"
-    verbose_name_plural = "vCPE Service"
+    verbose_name = "vSG Service"
+    verbose_name_plural = "vSG Service"
     list_display = ("backend_status_icon", "name", "enabled")
     list_display_links = ('backend_status_icon', 'name', )
     fieldsets = [(None,             {'fields': ['backend_status_text', 'name','enabled','versionNumber', 'description', "view_url", "icon_url", "service_specific_attribute",],
                                      'classes':['suit-tab suit-tab-general']}),
                  ("backend config", {'fields': [ "backend_network_label", "bbs_api_hostname", "bbs_api_port", "bbs_server", "bbs_slice"],
-                                     'classes':['suit-tab suit-tab-backend']}) ]
+                                     'classes':['suit-tab suit-tab-backend']}),
+                 ("vSG config", {'fields': [ "wan_container_gateway_ip", "wan_container_gateway_mac", "wan_container_netbits", "dns_servers"],
+                                     'classes':['suit-tab suit-tab-vsg']}) ]
     readonly_fields = ('backend_status_text', "service_specific_attribute")
     inlines = [SliceInline,ServiceAttrAsTabInline,ServicePrivilegeInline]
     form = VSGServiceForm
@@ -145,6 +159,7 @@
 
     suit_form_tabs =(('general', 'Service Details'),
         ('backend', 'Backend Config'),
+        ('vsg', 'vSG Config'),
         ('administration', 'Administration'),
         #('tools', 'Tools'),
         ('slices','Slices'),
@@ -164,6 +179,7 @@
     instance = forms.ModelChoiceField(queryset=Instance.objects.all(),required=False)
     last_ansible_hash = forms.CharField(required=False)
     wan_container_ip = forms.CharField(required=False)
+    wan_container_mac = forms.CharField(required=False)
 
     def __init__(self,*args,**kwargs):
         super (VSGTenantForm,self ).__init__(*args,**kwargs)
@@ -176,6 +192,7 @@
             self.fields['instance'].initial = self.instance.instance
             self.fields['last_ansible_hash'].initial = self.instance.last_ansible_hash
             self.fields['wan_container_ip'].initial = self.instance.wan_container_ip
+            self.fields['wan_container_mac'].initial = self.instance.wan_container_mac
         if (not self.instance) or (not self.instance.pk):
             # default fields for an 'add' form
             self.fields['kind'].initial = VCPE_KIND
@@ -196,9 +213,9 @@
     list_display = ('backend_status_icon', 'id', 'subscriber_tenant' )
     list_display_links = ('backend_status_icon', 'id')
     fieldsets = [ (None, {'fields': ['backend_status_text', 'kind', 'provider_service', 'subscriber_tenant', 'service_specific_id', # 'service_specific_attribute',
-                                     'wan_container_ip', 'bbs_account', 'creator', 'instance', 'last_ansible_hash'],
+                                     'wan_container_ip', 'wan_container_mac', 'bbs_account', 'creator', 'instance', 'last_ansible_hash'],
                           'classes':['suit-tab suit-tab-general']})]
-    readonly_fields = ('backend_status_text', 'service_specific_attribute', 'bbs_account')
+    readonly_fields = ('backend_status_text', 'service_specific_attribute', 'bbs_account', 'wan_container_ip', 'wan_container_mac')
     form = VSGTenantForm
 
     suit_form_tabs = (('general','Details'),)
diff --git a/xos/services/cord/models.py b/xos/services/cord/models.py
index 2f29d81..37ee78e 100644
--- a/xos/services/cord/models.py
+++ b/xos/services/cord/models.py
@@ -399,7 +399,11 @@
     simple_attributes = ( ("bbs_api_hostname", None),
                           ("bbs_api_port", None),
                           ("bbs_server", None),
-                          ("backend_network_label", "hpc_client"), )
+                          ("backend_network_label", "hpc_client"),
+                          ("wan_container_gateway_ip", ""),
+                          ("wan_container_gateway_mac", ""),
+                          ("wan_container_netbits", "24"),
+                          ("dns_servers", "8.8.8.8") )
 
     def __init__(self, *args, **kwargs):
         super(VSGService, self).__init__(*args, **kwargs)
@@ -598,13 +602,16 @@
         else:
             raise Exception("wan_container_ip.setter called on non-VTN CORD")
 
+    def ip_to_mac(self, ip):
+        (a, b, c, d) = ip.split('.')
+        return "02:42:%02x:%02x:%02x:%02x" % (int(a), int(b), int(c), int(d))
+
     # Generate the MAC for the container interface connected to WAN
     @property
     def wan_container_mac(self):
         if not self.wan_container_ip:
             return None
-        (a, b, c, d) = self.wan_container_ip.split('.')
-        return "02:42:%02x:%02x:%02x:%02x" % (int(a), int(b), int(c), int(d))
+        return self.ip_to_mac(self.wan_container_ip)
 
     @property
     def private_ip(self):
@@ -727,6 +734,10 @@
         if not self.volt:
             raise XOSConfigurationError("This vCPE container has no volt")
 
+        if self.instance:
+            # We're good.
+            return
+
         instance = self.find_or_make_instance_for_s_tag(self.volt.s_tag)
         self.instance = instance
         super(TenantWithContainer, self).save()
@@ -753,23 +764,31 @@
                 self.bbs_account = None
                 super(VSGTenant, self).save()
 
+    def get_wan_address_from_pool(self):
+        ap = AddressPool.objects.filter(name="public_addresses")
+        if not ap:
+            raise Exception("AddressPool 'public_addresses' does not exist. Please configure it.")
+        ap = ap[0]
+
+        addr = ap.get_address()
+        if not addr:
+            raise Exception("AddressPool 'public_addresses' has run out of addresses.")
+        return addr
+
+    def put_wan_address_to_pool(self, addr):
+        AddressPool.objects.filter(name="public_addresses")[0].put_address(addr)
+
     def manage_wan_container_ip(self):
         if CORD_USE_VTN:
             if not self.wan_container_ip:
-                ap = AddressPool.objects.filter(name="public_addresses")
-                if not ap:
-                    raise Exception("AddressPool 'public_addresses' does not exist. Please configure it.")
-                ap = ap[0]
-
-                addr = ap.get_address()
-                if not addr:
-                    raise Exception("AddressPool 'public_addresses' has run out of addresses.")
+                addr = self.get_wan_address_from_pool()
 
                 self.wan_container_ip = addr
+                super(TenantWithContainer, self).save()
 
     def cleanup_wan_container_ip(self):
         if CORD_USE_VTN and self.wan_container_ip:
-            AddressPool.objects.filter(name="public_addresses")[0].put_address(self.wan_container_ip)
+            self.put_wan_address_to_pool(self.wan_container_ip)
             self.wan_container_ip = None
 
     def find_or_make_port(self, instance, network, **kwargs):
@@ -830,6 +849,15 @@
                     tag = Tag(service=self.provider_service, content_object=instance, name="s_tag", value=self.volt.s_tag)
                     tag.save()
 
+            # VTN-CORD needs a WAN address for the VM, so that the VM can
+            # be configured.
+            if CORD_USE_VTN:
+                tags = Tag.select_by_content_object(instance).filter(name="vm_wan_addr")
+                if not tags:
+                    address = self.get_wan_address_from_pool()
+                    tag = Tag(service=self.provider_service, content_object=instance, name="vm_wan_addr", value="%s,%s,%s" % ("public_addresses", address, self.ip_to_mac(address)))
+                    tag.save()
+
     def save(self, *args, **kwargs):
         if not self.creator:
             if not getattr(self, "caller", None):
diff --git a/xos/synchronizers/base/SyncInstanceUsingAnsible.py b/xos/synchronizers/base/SyncInstanceUsingAnsible.py
index a2109ad..04b98df 100644
--- a/xos/synchronizers/base/SyncInstanceUsingAnsible.py
+++ b/xos/synchronizers/base/SyncInstanceUsingAnsible.py
@@ -147,9 +147,9 @@
 
         fields.update({"keystone_tenant_id": cslice.tenant_id,
                        "keystone_user_id": cuser.kuser_id,
-                       "rabbit_user": instance.controller.rabbit_user,
-                       "rabbit_password": instance.controller.rabbit_password,
-                       "rabbit_host": instance.controller.rabbit_host})
+                       "rabbit_user": getattr(instance.controller,"rabbit_user", None),
+                       "rabbit_password": getattr(instance.controller, "rabbit_password", None),
+                       "rabbit_host": getattr(instance.controller, "rabbit_host", None)})
 
         return fields
 
diff --git a/xos/synchronizers/base/event_loop.py b/xos/synchronizers/base/event_loop.py
index 6cfc9f6..c1b9cda 100644
--- a/xos/synchronizers/base/event_loop.py
+++ b/xos/synchronizers/base/event_loop.py
@@ -421,7 +421,7 @@
 				except Exception,e:
                         		self.consolePrint(bcolors.FAIL + "Model step %r failed" % (sync_step.__name__) + bcolors.ENDC)
 					logger.error('Model step %r failed. This seems like a misconfiguration or bug: %r. This error will not be relayed to the user!' % (sync_step.__name__, e))
-					logger.log_exc(e)
+					logger.log_exc("Exception in sync step")
 					self.failed_steps.append(S)
 					my_status = STEP_STATUS_KO
 			else:
diff --git a/xos/synchronizers/openstack/event_loop.py b/xos/synchronizers/openstack/event_loop.py
index 3a14511..db78f07 100644
--- a/xos/synchronizers/openstack/event_loop.py
+++ b/xos/synchronizers/openstack/event_loop.py
@@ -421,7 +421,7 @@
 				except Exception,e:
                         		self.consolePrint(bcolors.FAIL + "Model step %r failed" % (sync_step.__name__) + bcolors.ENDC)
 					logger.error('Model step %r failed. This seems like a misconfiguration or bug: %r. This error will not be relayed to the user!' % (sync_step.__name__, e))
-					logger.log_exc(e)
+					logger.log_exc("Exception in sync step")
 					self.failed_steps.append(S)
 					my_status = STEP_STATUS_KO
 			else:
diff --git a/xos/synchronizers/openstack/steps/sync_ports.py b/xos/synchronizers/openstack/steps/sync_ports.py
index 3289ece..4f6ce14 100644
--- a/xos/synchronizers/openstack/steps/sync_ports.py
+++ b/xos/synchronizers/openstack/steps/sync_ports.py
@@ -16,8 +16,35 @@
     #     has, and then work backward from each port's network-id to determine
     #     which Network is associated from the port.
 
-    def call(self, **args):
-        logger.info("sync'ing network instances")
+    def call(self, failed=[], deletion=False):
+        if deletion:
+            self.delete_ports()
+        else:
+            self.sync_ports()
+
+    def get_driver(self, port):
+        # We need to use a client driver that specifies the tenant
+        # of the destination instance. Nova-compute will not connect
+        # ports to instances if the port's tenant does not match
+        # the instance's tenant.
+
+        # A bunch of stuff to compensate for OpenStackDriver.client_driveR()
+        # not being in working condition.
+        from openstack.client import OpenStackClient
+        from openstack.driver import OpenStackDriver
+        controller = port.instance.node.site_deployment.controller
+        slice = port.instance.slice
+        caller = port.network.owner.creator
+        auth = {'username': caller.email,
+                'password': caller.remote_password,
+                'tenant': slice.name}
+        client = OpenStackClient(controller=controller, **auth) # cacert=self.config.nova_ca_ssl_cert,
+        driver = OpenStackDriver(client=client)
+
+        return driver
+
+    def sync_ports(self):
+        logger.info("sync'ing Ports [delete=False]")
 
         ports = Port.objects.all()
         ports_by_id = {}
@@ -164,21 +191,7 @@
                     logger.info("deferring port %s because controllerNetwork does not have a port-id yet" % port)
                     continue
                 try:
-                    # We need to use a client driver that specifies the tenant
-                    # of the destination instance. Nova-compute will not connect
-                    # ports to instances if the port's tenant does not match
-                    # the instance's tenant.
-
-                    # A bunch of stuff to compensate for OpenStackDriver.client_driveR()
-                    # not being in working condition.
-                    from openstack.client import OpenStackClient
-                    from openstack.driver import OpenStackDriver
-                    caller = port.network.owner.creator
-                    auth = {'username': caller.email,
-                            'password': caller.remote_password,
-                            'tenant': slice.name}
-                    client = OpenStackClient(controller=controller, **auth) # cacert=self.config.nova_ca_ssl_cert,
-                    driver = OpenStackDriver(client=client)
+                    driver = self.get_driver(port)
 
                     args = {"network_id": cn.net_id}
                     neutron_port_name = port.get_parameters().get("neutron_port_name", None)
@@ -190,12 +203,28 @@
                     if neutron_port["fixed_ips"]:
                         port.ip = neutron_port["fixed_ips"][0]["ip_address"]
                     port.mac = neutron_port["mac_address"]
+                    port.xos_created = True
+                    logger.info("created neutron port %s for %s" % (port.port_id, port))
                 except:
                     logger.log_exc("failed to create neutron port for %s" % port)
                     continue
                 port.save()
 
-    def delete_record(self, network_instance):
-        # Nothing to do, this is an OpenCloud object
-        pass
+    def delete_ports(self):
+        logger.info("sync'ing Ports [delete=True]")
+        for port in Port.deleted_objects.all():
+            self.delete_record(port)
+
+    def delete_record(self, port):
+        if port.xos_created and port.port_id:
+            logger.info("calling openstack to destroy port %s" % port.port_id)
+            try:
+                driver = self.get_driver(port)
+                driver.shell.quantum.delete_port(port.port_id)
+            except:
+                logger.log_exc("failed to delete port %s from neutron" % port.port_id)
+                return
+
+        logger.info("Purging port %s" % port)
+        port.delete(purge=True)
 
diff --git a/xos/synchronizers/vcpe/run-vtn.sh b/xos/synchronizers/vcpe/run-vtn.sh
new file mode 100755
index 0000000..c4c3b00
--- /dev/null
+++ b/xos/synchronizers/vcpe/run-vtn.sh
@@ -0,0 +1,8 @@
+#if [[ ! -e ./vcpe-observer.py ]]; then
+#    ln -s ../../xos-observer.py vcpe-observer.py
+#fi
+
+export XOS_DIR=/opt/xos
+cp /root/setup/node_key $XOS_DIR/synchronizers/vcpe/node_key
+chmod 0600 $XOS_DIR/synchronizers/vcpe/node_key
+python vcpe-synchronizer.py  -C $XOS_DIR/synchronizers/vcpe/vtn_vcpe_synchronizer_config
diff --git a/xos/synchronizers/vcpe/steps/sync_vcpetenant.py b/xos/synchronizers/vcpe/steps/sync_vcpetenant.py
index bbb3ad5..5e48837 100644
--- a/xos/synchronizers/vcpe/steps/sync_vcpetenant.py
+++ b/xos/synchronizers/vcpe/steps/sync_vcpetenant.py
@@ -9,7 +9,7 @@
 from synchronizers.base.syncstep import SyncStep
 from synchronizers.base.ansible import run_template_ssh
 from synchronizers.base.SyncInstanceUsingAnsible import SyncInstanceUsingAnsible
-from core.models import Service, Slice
+from core.models import Service, Slice, Tag
 from services.cord.models import VSGService, VSGTenant, VOLTTenant
 from services.hpc.models import HpcService, CDNPrefix
 from xos.logger import Logger, logging
@@ -25,6 +25,8 @@
 PARENTAL_MECHANISM="dnsmasq"
 ENABLE_QUICK_UPDATE=False
 
+CORD_USE_VTN = getattr(Config(), "networking_use_vtn", False)
+
 class SyncVSGTenant(SyncInstanceUsingAnsible):
     provides=[VSGTenant]
     observes=VSGTenant
@@ -137,6 +139,19 @@
                     if mac:
                         safe_macs.append(mac)
 
+        wan_vm_ip=""
+        wan_vm_mac=""
+        tags = Tag.select_by_content_object(o.instance).filter(name="vm_wan_addr")
+        if tags:
+            parts=tags[0].value.split(",")
+            if len(parts)!=3:
+                raise Exception("vm_wan_addr tag is malformed: %s" % value)
+            wan_vm_ip = parts[1]
+            wan_vm_mac = parts[2]
+        else:
+            if CORD_USE_VTN:
+                raise Exception("no vm_wan_addr tag for instance %s" % o.instance)
+
         fields = {"vlan_ids": vlan_ids,   # XXX remove this
                 "s_tags": s_tags,
                 "c_tags": c_tags,
@@ -145,7 +160,13 @@
                 "bbs_addrs": bbs_addrs,
                 "full_setup": full_setup,
                 "isolation": o.instance.isolation,
-                "safe_browsing_macs": safe_macs}
+                "wan_container_gateway_mac": vcpe_service.wan_container_gateway_mac,
+                "wan_container_gateway_ip": vcpe_service.wan_container_gateway_ip,
+                "wan_container_netbits": vcpe_service.wan_container_netbits,
+                "wan_vm_mac": wan_vm_mac,
+                "wan_vm_ip": wan_vm_ip,
+                "safe_browsing_macs": safe_macs,
+                "dns_servers": [x.strip() for x in vcpe_service.dns_servers.split(",")] }
 
         # add in the sync_attributes that come from the SubscriberRoot object
 
@@ -227,7 +248,10 @@
             if o.instance.isolation in ["container", "container_vm"]:
                 super(SyncVSGTenant, self).run_playbook(o, fields, "sync_vcpetenant_new.yaml")
             else:
-                super(SyncVSGTenant, self).run_playbook(o, fields)
+                if CORD_USE_VTN:
+                    super(SyncVSGTenant, self).run_playbook(o, fields, template_name="sync_vcpetenant_vtn.yaml")
+                else:
+                    super(SyncVSGTenant, self).run_playbook(o, fields)
 
         o.last_ansible_hash = ansible_hash
 
diff --git a/xos/synchronizers/vcpe/steps/sync_vcpetenant.yaml b/xos/synchronizers/vcpe/steps/sync_vcpetenant.yaml
index d887547..585f68a 100644
--- a/xos/synchronizers/vcpe/steps/sync_vcpetenant.yaml
+++ b/xos/synchronizers/vcpe/steps/sync_vcpetenant.yaml
@@ -33,6 +33,10 @@
         {% for bbs_addr in bbs_addrs %}
         - {{ bbs_addr }}
         {% endfor %}
+      dns_servers:
+        {% for dns_server in dns_servers %}
+        - {{ dns_server }}
+        {% endfor %}
       nat_ip: {{ nat_ip }}
       nat_mac: {{ nat_mac }}
       lan_ip: {{ lan_ip }}
diff --git a/xos/synchronizers/vcpe/steps/sync_vcpetenant_new.yaml b/xos/synchronizers/vcpe/steps/sync_vcpetenant_new.yaml
index 59047c1..071c30a 100644
--- a/xos/synchronizers/vcpe/steps/sync_vcpetenant_new.yaml
+++ b/xos/synchronizers/vcpe/steps/sync_vcpetenant_new.yaml
@@ -34,6 +34,10 @@
         {% for bbs_addr in bbs_addrs %}
         - {{ bbs_addr }}
         {% endfor %}
+      dns_servers:
+        {% for dns_server in dns_servers %}
+        - {{ dns_server }}
+        {% endfor %}
       nat_ip: {{ nat_ip }}
       nat_mac: {{ nat_mac }}
       lan_ip: {{ lan_ip }}
diff --git a/xos/synchronizers/vcpe/steps/sync_vcpetenant_vtn.yaml b/xos/synchronizers/vcpe/steps/sync_vcpetenant_vtn.yaml
new file mode 100644
index 0000000..819dcc5
--- /dev/null
+++ b/xos/synchronizers/vcpe/steps/sync_vcpetenant_vtn.yaml
@@ -0,0 +1,217 @@
+---
+- hosts: {{ instance_name }}
+  gather_facts: False
+  connection: ssh
+  user: ubuntu
+  sudo: yes
+  vars:
+      cdn_enable: {{ cdn_enable }}
+      dnsdemux_ip: {{ dnsdemux_ip }}
+      firewall_enable: {{ firewall_enable }}
+      url_filter_enable: {{ url_filter_enable }}
+      vlan_ids:
+        {% for vlan_id in vlan_ids %}
+        - {{ vlan_id }}
+        {% endfor %}
+      c_tags:
+        {% for c_tag in c_tags %}
+        - {{ c_tag }}
+        {% endfor %}
+      s_tags:
+        {% for s_tag in s_tags %}
+        - {{ s_tag }}
+        {% endfor %}
+      firewall_rules:
+        {% for firewall_rule in firewall_rules.split("\n") %}
+        - {{ firewall_rule }}
+        {% endfor %}
+      cdn_prefixes:
+        {% for prefix in cdn_prefixes %}
+        - {{ prefix }}
+        {% endfor %}
+      bbs_addrs:
+        {% for bbs_addr in bbs_addrs %}
+        - {{ bbs_addr }}
+        {% endfor %}
+      dns_servers:
+        {% for dns_server in dns_servers %}
+        - {{ dns_server }}
+        {% endfor %}
+      nat_ip: {{ nat_ip }}
+      nat_mac: {{ nat_mac }}
+      lan_ip: {{ lan_ip }}
+      lan_mac: {{ lan_mac }}
+      wan_ip: {{ wan_ip }}
+      wan_mac: {{ wan_mac }}
+      wan_container_ip: {{ wan_container_ip }}
+      wan_container_netbits: {{ wan_container_netbits }}
+      wan_container_mac: {{ wan_container_mac }}
+      wan_container_gateway_ip: {{ wan_container_gateway_ip }}
+      wan_vm_ip: {{ wan_vm_ip }}
+      wan_vm_mac: {{ wan_vm_mac }}
+      wan_next_hop: 10.0.1.253   # FIX ME
+      private_ip: {{ private_ip }}
+      private_mac: {{ private_mac }}
+      hpc_client_ip: {{ hpc_client_ip }}
+      hpc_client_mac: {{ hpc_client_mac }}
+      keystone_tenant_id: {{ keystone_tenant_id }}
+      keystone_user_id: {{ keystone_user_id }}
+      rabbit_user: {{ rabbit_user }}
+      rabbit_password: {{ rabbit_password }}
+      rabbit_host: {{ rabbit_host }}
+      safe_browsing:
+        {% for mac in safe_browsing_macs %}
+        - {{ mac }}
+        {% endfor %}
+
+  tasks:
+  - name: Check to see if network is setup
+    stat: path=/root/network_is_setup
+    register: network_is_setup
+
+  - name: Add eth0.500
+    shell: "{{ '{{' }} item {{ '}}' }}"
+    with_items:
+      - ip link del link eth0 eth0.500 || true
+      - brctl delbr br-wan || true
+      - ip link add link eth0 eth0.500 type vlan id 500
+      - ifconfig eth0.500 up
+      - ifconfig eth0.500 0.0.0.0
+      - ifconfig eth0.500 hw ether {{ wan_vm_mac }}
+      - ip addr add {{ wan_vm_ip }}/{{ wan_container_netbits }} dev eth0.500
+      - ip link set eth0.500 up
+      - ip route del default || true
+      - ip route add default via {{ wan_container_gateway_ip }}
+    when: network_is_setup.stat.exists == False
+
+  - name: install bridge-utils
+    apt: name=bridge-utils state=present
+
+  - name: now redo everything using a bridge
+    shell: "{{ '{{' }} item {{ '}}' }}"
+    with_items:
+       - ip link del link eth0 eth0.500
+       - ip link add link eth0 eth0.500 type vlan id 500
+       - ip link set eth0.500 up
+       - brctl delbr br-wan || true
+       - brctl addbr br-wan
+       - brctl addif br-wan eth0.500
+       - ifconfig br-wan hw ether {{ wan_vm_mac }}
+       - ip addr add {{ wan_vm_ip }}/{{ wan_container_netbits }} dev br-wan
+       - ip link set br-wan up
+       - ip route del default || true
+       - ip route add default via {{ wan_container_gateway_ip }}
+       - ip link set dev br-wan promisc on
+    when: network_is_setup.stat.exists == False
+
+  - name: Remember that the network is setup, so we never do the above again
+    shell: touch /root/network_is_setup
+
+{% if full_setup %}
+  - name: Docker repository
+    copy: src=/opt/xos/synchronizers/vcpe/files/docker.list
+      dest=/etc/apt/sources.list.d/docker.list
+
+  - name: Import the repository key
+    apt_key: keyserver=keyserver.ubuntu.com id=36A1D7869245C8950F966E92D8576A8BA88D21E9
+
+  - name: install Docker
+    apt: name=lxc-docker state=present update_cache=yes
+
+  - name: install python-setuptools
+    apt: name=python-setuptools state=present
+
+  - name: install pip
+    easy_install: name=pip
+
+  - name: install docker-py
+    pip: name=docker-py version=0.5.3
+
+  - name: install Pipework
+    get_url: url=https://raw.githubusercontent.com/jpetazzo/pipework/master/pipework
+       dest=/usr/local/bin/pipework
+       mode=0755
+
+  - name: make sure /etc/dnsmasq.d exists
+    file: path=/etc/dnsmasq.d state=directory owner=root group=root
+
+  - name: Disable resolvconf service
+    shell: service resolvconf stop
+    shell: echo manual > /etc/init/resolvconf.override
+    shell: rm -f /etc/resolv.conf
+
+  - name: Install resolv.conf
+    copy: src=/opt/xos/synchronizers/vcpe/files/vm-resolv.conf
+      dest=/etc/resolv.conf
+
+  - name: Verify if vcpe_stats_notifier ([] is to avoid capturing the shell process) cron job is already running
+    shell: pgrep -f [v]cpe_stats_notifier | wc -l
+    register: cron_job_pids_count
+
+#  - name: DEBUG
+#    debug: var=cron_job_pids_count.stdout
+
+#  - name: make sure ~/bin exists
+#    file: path=~/bin state=directory owner=root group=root
+#    when: cron_job_pids_count.stdout == "0"
+
+#  - name: Copy cron job to destination
+#    copy: src=/opt/xos/synchronizers/vcpe/vcpe_stats_notifier.py
+#      dest=/usr/local/sbin/vcpe_stats_notifier.py
+#    when: cron_job_pids_count.stdout == "0"
+
+#  - name: install python-kombu
+#    apt: name=python-kombu state=present
+#    when: cron_job_pids_count.stdout == "0"
+
+#  - name: Initiate vcpe_stats_notifier cron job
+#    command: sudo python /usr/local/sbin/vcpe_stats_notifier.py --keystone_tenant_id={{ keystone_tenant_id }} --keystone_user_id={{ keystone_user_id }} --rabbit_user={{ rabbit_user }} --rabbit_password={{ rabbit_password }} --rabbit_host={{ rabbit_host }} --vcpeservice_rabbit_exchange='vcpeservice'
+#    async: 9999999999999999
+#    poll: 0
+#    when: cron_job_pids_count.stdout == "0"
+{% endif %}
+
+  - name: vCPE upstart
+    template: src=/opt/xos/synchronizers/vcpe/templates/vcpe.conf.j2 dest=/etc/init/vcpe-{{ s_tags[0] }}-{{ c_tags[0] }}.conf
+
+  - name: vCPE startup script
+    template: src=/opt/xos/synchronizers/vcpe/templates/start-vcpe-vtn.sh.j2 dest=/usr/local/sbin/start-vcpe-{{ s_tags[0] }}-{{ c_tags[0] }}.sh mode=0755
+    notify:
+#    - restart vcpe
+     - stop vcpe
+     - remove container
+     - start vcpe
+
+  - name: create /etc/vcpe-{{ s_tags[0] }}-{{ c_tags[0] }}/dnsmasq.d
+    file: path=/etc/vcpe-{{ s_tags[0] }}-{{ c_tags[0] }}/dnsmasq.d state=directory owner=root group=root
+
+  - name: vCPE basic dnsmasq config
+    copy: src=/opt/xos/synchronizers/vcpe/files/vcpe.dnsmasq dest=/etc/vcpe-{{ s_tags[0] }}-{{ c_tags[0] }}/dnsmasq.d/vcpe.conf owner=root group=root
+    notify:
+    - restart dnsmasq
+
+  - name: dnsmasq config
+    template: src=/opt/xos/synchronizers/vcpe/templates/dnsmasq_servers.j2 dest=/etc/vcpe-{{ s_tags[0] }}-{{ c_tags[0] }}/dnsmasq.d/servers.conf owner=root group=root
+    notify:
+    - restart dnsmasq
+
+  - name: Make sure vCPE service is running
+    service: name=vcpe-{{ s_tags[0] }}-{{ c_tags[0] }} state=started
+
+  handlers:
+  # Dnsmasq is automatically restarted in the container
+  - name: restart dnsmasq
+    shell: docker exec vcpe-{{ s_tags[0] }}-{{ c_tags[0] }} killall dnsmasq
+
+  - name: restart vcpe
+    shell: service vcpe-{{ s_tags[0] }}-{{ c_tags[0] }} stop; sleep 1; service vcpe-{{ s_tags[0] }}-{{ c_tags[0] }} start
+
+  - name: stop vcpe
+    service: name=vcpe-{{ s_tags[0] }}-{{ c_tags[0] }} state=stopped
+
+  - name: remove container
+    docker: name=vcpe-{{ s_tags[0] }}-{{ c_tags[0] }} state=absent image=docker-vcpe
+
+  - name: start vcpe
+    service: name=vcpe-{{ s_tags[0] }}-{{ c_tags[0] }} state=started
+
diff --git a/xos/synchronizers/vcpe/templates/dnsmasq_servers.j2 b/xos/synchronizers/vcpe/templates/dnsmasq_servers.j2
index c89c762..3682cdf 100644
--- a/xos/synchronizers/vcpe/templates/dnsmasq_servers.j2
+++ b/xos/synchronizers/vcpe/templates/dnsmasq_servers.j2
@@ -10,5 +10,7 @@
 {% endif %}
 
 # use google's DNS service
-server=8.8.8.8
-server=8.8.4.4
+{% for dns_server in dns_servers %}
+server={{ dns_server }}
+{% endfor %}
+
diff --git a/xos/synchronizers/vcpe/templates/start-vcpe-vtn.sh.j2 b/xos/synchronizers/vcpe/templates/start-vcpe-vtn.sh.j2
new file mode 100644
index 0000000..bf46515
--- /dev/null
+++ b/xos/synchronizers/vcpe/templates/start-vcpe-vtn.sh.j2
@@ -0,0 +1,47 @@
+#!/bin/bash
+
+function mac_to_iface {
+    MAC=$1
+    ifconfig|grep $MAC| awk '{print $1}'|grep -v '\.'
+}
+
+iptables -L > /dev/null
+ip6tables -L > /dev/null
+
+STAG={{ s_tags[0] }}
+CTAG={{ c_tags[0] }}
+VCPE=vcpe-$STAG-$CTAG
+
+docker inspect $VCPE > /dev/null 2>&1
+if [ "$?" == 1 ]
+then
+    docker pull andybavier/docker-vcpe
+    docker run -d --name=$VCPE --privileged=true --net=none -v /etc/$VCPE/dnsmasq.d:/etc/dnsmasq.d andybavier/docker-vcpe
+else
+    docker start $VCPE
+fi
+
+# Set up networking via pipework
+WAN_IFACE=br-wan
+docker exec $VCPE ifconfig eth0 >> /dev/null || pipework $WAN_IFACE -i eth0 $VCPE {{ wan_container_ip }}/{{ wan_container_netbits }}@{{ wan_container_gateway_ip }} {{ wan_container_mac }}
+
+LAN_IFACE=eth0
+ifconfig $LAN_IFACE >> /dev/null
+if [ "$?" == 0 ]
+then
+    ifconfig $LAN_IFACE.$STAG >> /dev/null || ip link add link $LAN_IFACE name $LAN_IFACE.$STAG type vlan id $STAG
+    ifconfig $LAN_IFACE.$STAG up
+    docker exec $VCPE ifconfig eth1 >> /dev/null || pipework $LAN_IFACE.$STAG -i eth1 $VCPE 192.168.0.1/24 @$CTAG
+fi
+
+#HPC_IFACE=$( mac_to_iface {{ hpc_client_mac }} )
+#docker exec $VCPE ifconfig eth2 >> /dev/null || pipework $HPC_IFACE -i eth2 $VCPE {{ hpc_client_ip }}/24
+
+# Make sure VM's eth0 (hpc_client) has no IP address
+#ifconfig $HPC_IFACE 0.0.0.0
+
+# Now can start up dnsmasq
+docker exec $VCPE service dnsmasq start
+
+# Attach to container
+docker start -a $VCPE
diff --git a/xos/synchronizers/vcpe/vtn_vcpe_synchronizer_config b/xos/synchronizers/vcpe/vtn_vcpe_synchronizer_config
new file mode 100644
index 0000000..e92786b
--- /dev/null
+++ b/xos/synchronizers/vcpe/vtn_vcpe_synchronizer_config
@@ -0,0 +1,47 @@
+
+[plc]
+name=plc
+deployment=VICCI
+
+[db]
+name=xos
+user=postgres
+password=password
+host=localhost
+port=5432
+
+[api]
+host=128.112.171.237
+port=8000
+ssl_key=None
+ssl_cert=None
+ca_ssl_cert=None
+ratelimit_enabled=0
+omf_enabled=0
+mail_support_address=support@localhost
+nova_enabled=True
+
+[observer]
+name=vcpe
+dependency_graph=/opt/xos/synchronizers/vcpe/model-deps
+steps_dir=/opt/xos/synchronizers/vcpe/steps
+sys_dir=/opt/xos/synchronizers/vcpe/sys
+deleters_dir=/opt/xos/synchronizers/vcpe/deleters
+log_file=console
+#/var/log/hpc.log
+driver=None
+pretend=False
+backoff_disabled=True
+save_ansible_output=True
+# set proxy_ssh to false on cloudlab
+full_setup=True
+proxy_ssh=True
+proxy_ssh_key=/opt/xos/synchronizers/vcpe/node_key
+proxy_ssh_user=root
+
+[networking]
+use_vtn=True
+
+[feefie]
+client_id='vicci_dev_central'
+user_id='pl'
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..6b48911
--- /dev/null
+++ b/xos/synchronizers/vtn/steps/sync_port_addresses.py
@@ -0,0 +1,137 @@
+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, Tag
+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)
+
+            wan_mac = vsg.wan_container_mac
+            if not wan_mac:
+                logger.info("skipping vsg %s because it has no wan_container_mac" % 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] = []
+            entry = {"mac_address": wan_mac, "ip_address": wan_ip}
+            addr_pairs = port_addrs[lan_port.pk]
+            if not entry in addr_pairs:
+                 addr_pairs.append(entry)
+
+            # now do the VM_WAN_IP from the instance
+            if vsg.instance:
+                tags=Tag.select_by_content_object(vsg.instance).filter(name="vm_wan_addr")
+                if tags:
+                    parts=tags[0].value.split(",")
+                    if len(parts)!=3:
+                        raise Exception("vm_wan_addr tag is malformed: %s" % value)
+                    entry = {"mac_address": parts[2], "ip_address": parts[1]}
+                    if not entry in addr_pairs:
+                        addr_pairs.append(entry)
+
+        # 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)
+            addr_pairs = port_addrs[port_pk]
+            neutron_port = ports_by_id.get(port.port_id,None)
+            if not neutron_port:
+                logger.info("failed to get neutron port for port %s" % port)
+                continue
+
+            ips = [x["ip_address"] for x in addr_pairs]
+
+            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 ips:
+                    logger.info("removing address %s from port %s" % (aap["ip_address"], port))
+                    aaps.remove(aap)
+                    changed = True
+
+            aaps_ips = [x["ip_address"] for x in aaps]
+
+            # add addresses in XOS that don't exist in neutron
+            for addr in addr_pairs:
+                if not addr["ip_address"] in aaps_ips:
+                    logger.info("adding address %s to port %s" % (addr, port))
+                    aaps.append( addr )
+                    aaps_ips.append(addr["ip_address"])
+                    changed = True
+
+            if changed:
+                logger.info("updating port %s" % port)
+                driver.shell.quantum.update_port(port.port_id, {"port": {"allowed_address_pairs": aaps}})
+
+
+
+
+
+
+
diff --git a/xos/synchronizers/vtn/vtn_synchronizer_config b/xos/synchronizers/vtn/vtn_synchronizer_config
index 302a096..d931839 100644
--- a/xos/synchronizers/vtn/vtn_synchronizer_config
+++ b/xos/synchronizers/vtn/vtn_synchronizer_config
@@ -29,10 +29,16 @@
 deleters_dir=/opt/xos/synchronizers/vtn/deleters
 log_file=console
 #/var/log/hpc.log
-driver=None
+driver=openstack
 pretend=False
 backoff_disabled=True
 
+[nova]
+ca_ssl_cert=/etc/ssl/certs/ca-certificates.crt
+
 [feefie]
 client_id='vicci_dev_central'
 user_id='pl'
+
+[networking]
+use_vtn=True
diff --git a/xos/tests/README.md b/xos/tests/README.md
new file mode 100644
index 0000000..f3ddad5
--- /dev/null
+++ b/xos/tests/README.md
@@ -0,0 +1,5 @@
+# CORD Tests
+
+The files in this directory are obsolete. The plan is for this
+directory to hold tests in the furture. There are also tests in
+the form of TOSCA specifications in `../configurations/tests`.
diff --git a/xos/tools/apigen/modelgen b/xos/tools/apigen/modelgen
index 72cce08..414540d 100644
--- a/xos/tools/apigen/modelgen
+++ b/xos/tools/apigen/modelgen
@@ -17,6 +17,7 @@
 
 options = None
 
+
 def singular(foo, keys):
 	for k in keys:
 		if (foo==k+'es'):
@@ -28,8 +29,11 @@
 g = globals()
 
 def enum_classes(apps):
+    global app_map
+    app_map = {}
     model_classes = []
     for app in apps:
+            orig_app=app
             app = app + ".models"
             models_module = __import__(app)
             for part in app.split(".")[1:]:
@@ -37,12 +41,15 @@
                     break
                 models_module = getattr(models_module,part)
 
+            global PlCoreBase
             PlCoreBase = getattr(models_module,"PlCoreBase")
 
             for classname in dir(models_module):
                     c = getattr(models_module, classname, None)
                     if type(c)==type(PlCoreBase) and c.__name__ not in options.blacklist:
                             model_classes.append(c)
+                            app_map[c.__name__]=orig_app
+
 
     return model_classes
 
@@ -53,6 +60,8 @@
 	def __init__(self, m):
 		self.model = m
 		self.props = []
+		self.fields = []
+		self.field_dict = []
 		self.refs = []
 		self.plural_name = None
 
@@ -101,11 +110,19 @@
 		return filtered
 
 	def add_object(self, o):
+                global app_map
 		obj = GenObj(o)
 		fields = o._meta.fields
+                try:
+                    obj.app = app_map[o.__name__]
+                except KeyError:
+                    print "KeyError: %r"%o.__name__
+                    pdb.set_trace()
 		self[str(obj).lower()]=obj
 
 	def compute_links(self):
+                base_props = [f.name for f in PlCoreBase._meta.fields]
+
 		for obj in self.values():
 			#if (str(obj)=='network'):
 			#	pdb.set_trace()
@@ -132,7 +149,11 @@
                                         # cause swagger and REST to break
                                         pass
 				else:
-					obj.props.append(f.name)
+                                        f.type = f.__class__.__name__
+
+                                        if (f.name not in base_props):
+                                            obj.fields.append(f) 
+                                        obj.props.append(f.name)
 
 			m2m = obj.model._meta.many_to_many
 			for f in m2m:
diff --git a/xos/tosca/custom_types/xos.m4 b/xos/tosca/custom_types/xos.m4
index 2f5b537..15e9710 100644
--- a/xos/tosca/custom_types/xos.m4
+++ b/xos/tosca/custom_types/xos.m4
@@ -218,6 +218,18 @@
                 type: string
                 required: false
                 description: Label that matches network used to connect HPC and BBS services.
+            wan_container_gateway_ip:
+                type: string
+                required: false
+            wan_container_gateway_mac:
+                type: string
+                required: false
+            wan_container_netbits:
+                type: string
+                required: false
+            dns_servers:
+                type: string
+                required: false
 
     tosca.nodes.VBNGService:
         derived_from: tosca.nodes.Root
diff --git a/xos/tosca/custom_types/xos.yaml b/xos/tosca/custom_types/xos.yaml
index d466180..88b3388 100644
--- a/xos/tosca/custom_types/xos.yaml
+++ b/xos/tosca/custom_types/xos.yaml
@@ -320,6 +320,18 @@
                 type: string
                 required: false
                 description: Label that matches network used to connect HPC and BBS services.
+            wan_container_gateway_ip:
+                type: string
+                required: false
+            wan_container_gateway_mac:
+                type: string
+                required: false
+            wan_container_netbits:
+                type: string
+                required: false
+            dns_servers:
+                type: string
+                required: false
 
     tosca.nodes.VBNGService:
         derived_from: tosca.nodes.Root
diff --git a/xos/tosca/resources/vcpeservice.py b/xos/tosca/resources/vcpeservice.py
index 5c478ac..5c7b2a7 100644
--- a/xos/tosca/resources/vcpeservice.py
+++ b/xos/tosca/resources/vcpeservice.py
@@ -12,5 +12,8 @@
 class XOSVsgService(XOSService):
     provides = "tosca.nodes.VSGService"
     xos_model = VSGService
-    copyin_props = ["view_url", "icon_url", "enabled", "published", "public_key", "private_key_fn", "versionNumber", "backend_network_label"]
+    copyin_props = ["view_url", "icon_url", "enabled", "published", "public_key",
+                    "private_key_fn", "versionNumber", "backend_network_label",
+                    "wan_container_gateway_ip", "wan_container_gateway_mac",
+                    "wan_container_netbits", "dns_servers"]
 
diff --git a/xos/xos/settings.py b/xos/xos/settings.py
index c8b0b07..8764b80 100644
--- a/xos/xos/settings.py
+++ b/xos/xos/settings.py
@@ -209,13 +209,23 @@
         }
     },
     'handlers': {
+        'file': {
+            'level': 'DEBUG',
+            'class': 'logging.FileHandler',
+            'filename': '/var/log/django_debug.log',
+        },
         'mail_admins': {
             'level': 'ERROR',
             'filters': ['require_debug_false'],
             'class': 'django.utils.log.AdminEmailHandler'
-        }
+        },
     },
     'loggers': {
+        'django': {
+            'handlers': ['file'],
+            'level': 'DEBUG',
+            'propagate': True,
+        },
         'django.request': {
             'handlers': ['mail_admins'],
             'level': 'ERROR',