Merge branch 'master' of github.com:open-cloud/xos
diff --git a/xos/configurations/common/base.yaml b/xos/configurations/common/base.yaml
index 3638dd9..3f13c94 100644
--- a/xos/configurations/common/base.yaml
+++ b/xos/configurations/common/base.yaml
@@ -20,6 +20,12 @@
          disk_format: QCOW2
          container_format: BARE
 
+    trusty-server-multi-nic-docker:
+      type: tosca.nodes.Image
+      properties:
+         disk_format: QCOW2
+         container_format: BARE
+
     MyDeployment:
       type: tosca.nodes.Deployment
       properties:
@@ -28,6 +34,9 @@
           - image:
               node: trusty-server-multi-nic
               relationship: tosca.relationships.SupportsImage
+          - image:
+              node: trusty-server-multi-nic-docker
+              relationship: tosca.relationships.SupportsImage
 
     CloudLab:
       type: tosca.nodes.Controller
diff --git a/xos/configurations/cord/ceilometer.yaml b/xos/configurations/cord/ceilometer.yaml
index 6fcd132..f8192fb 100644
--- a/xos/configurations/cord/ceilometer.yaml
+++ b/xos/configurations/cord/ceilometer.yaml
@@ -161,6 +161,9 @@
     trusty-server-multi-nic:
       type: tosca.nodes.Image
 
+    trusty-server-multi-nic-docker:
+      type: tosca.nodes.Image
+
     mysite_ceilometer:
       description: Ceilometer Proxy Slice
       type: tosca.nodes.Slice
@@ -172,7 +175,7 @@
               node: mysite
               relationship: tosca.relationships.MemberOfSite
           - default_image:
-                node: trusty-server-multi-nic
+                node: trusty-server-multi-nic-docker
                 relationship: tosca.relationships.DefaultImage
       properties:
           default_flavor: m1.small
diff --git a/xos/configurations/vtn/Makefile b/xos/configurations/vtn/Makefile
index 2746f31..1315b39 100644
--- a/xos/configurations/vtn/Makefile
+++ b/xos/configurations/vtn/Makefile
@@ -8,6 +8,7 @@
 xos: vtn_network_cfg_json
 	sudo MYIP=$(MYIP) docker-compose up -d
 	bash ../common/wait_for_xos.sh
+	sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/fixtures.yaml
 	sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/base.yaml
 	sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/nodes.yaml
 	sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/vtn/vtn.yaml
diff --git a/xos/configurations/vtn/cord-vtn-vsg.yaml b/xos/configurations/vtn/cord-vtn-vsg.yaml
new file mode 100644
index 0000000..bcb6847
--- /dev/null
+++ b/xos/configurations/vtn/cord-vtn-vsg.yaml
@@ -0,0 +1,172 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: Just enough Tosca to get the vSG slice running on VTN-Cloudlab
+
+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: 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/
+
+    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: 432
+        requirements:
+            - provider_service:
+                node: service_volt
+                relationship: tosca.relationships.MemberOfService
+            - subscriber:
+                node: My House
+                relationship: tosca.relationships.BelongsToSubscriber
diff --git a/xos/configurations/vtn/docker-compose.yml b/xos/configurations/vtn/docker-compose.yml
index e7bb6b1..7fb68f1 100644
--- a/xos/configurations/vtn/docker-compose.yml
+++ b/xos/configurations/vtn/docker-compose.yml
@@ -21,7 +21,7 @@
 
 xos_synchronizer_onos:
     image: xosproject/xos-synchronizer-openstack
-    command: bash -c "python /opt/xos/synchronizers/onos/onos-observer.py -C /opt/xos/synchronizers/onos/onos_observer_config"
+    command: bash -c "python /opt/xos/synchronizers/onos/onos-synchronizer.py -C /opt/xos/synchronizers/onos/onos_synchronizer_config"
     labels:
         org.xosproject.kind: synchronizer
         org.xosproject.target: onos
diff --git a/xos/core/models/service.py b/xos/core/models/service.py
index 1a1b6ef..6ece1b3 100644
--- a/xos/core/models/service.py
+++ b/xos/core/models/service.py
@@ -661,12 +661,15 @@
                 instance = self.pick_least_loaded_instance_in_slice(slices)
 
             if not instance:
-                flavors = Flavor.objects.filter(name="m1.small")
-                if not flavors:
-                    raise XOSConfigurationError("No m1.small flavor")
-
                 slice = self.provider_service.slices.all()[0]
 
+                flavor = slice.default_flavor
+                if not flavor:
+                    flavors = Flavor.objects.filter(name="m1.small")
+                    if not flavors:
+                        raise XOSConfigurationError("No m1.small flavor")
+                    flavor = flavors[0]
+
                 if slice.default_isolation == "container_vm":
                     (node, parent) = ContainerVmScheduler(slice).pick()
                 else:
@@ -677,7 +680,7 @@
                                 image = self.image,
                                 creator = self.creator,
                                 deployment = node.site_deployment.deployment,
-                                flavor = flavors[0],
+                                flavor = flavor,
                                 isolation = slice.default_isolation,
                                 parent = parent)
                 self.save_instance(instance)
diff --git a/xos/services/ceilometer/models.py b/xos/services/ceilometer/models.py
index 42734de..2684097 100644
--- a/xos/services/ceilometer/models.py
+++ b/xos/services/ceilometer/models.py
@@ -35,6 +35,10 @@
         proxy = True
 
     KIND = CEILOMETER_KIND
+    LOOK_FOR_IMAGES=[ "trusty-server-multi-nic-docker", # CloudLab
+                      "trusty-server-multi-nic",
+                    ]
+
 
     sync_attributes = ("private_ip", "private_mac",
                        "ceilometer_ip", "ceilometer_mac",
diff --git a/xos/services/cord/admin.py b/xos/services/cord/admin.py
index 5cf6b29..71cae5f 100644
--- a/xos/services/cord/admin.py
+++ b/xos/services/cord/admin.py
@@ -163,6 +163,7 @@
     creator = forms.ModelChoiceField(queryset=User.objects.all())
     instance = forms.ModelChoiceField(queryset=Instance.objects.all(),required=False)
     last_ansible_hash = forms.CharField(required=False)
+    wan_container_ip = forms.CharField(required=False)
 
     def __init__(self,*args,**kwargs):
         super (VSGTenantForm,self ).__init__(*args,**kwargs)
@@ -174,6 +175,7 @@
             self.fields['creator'].initial = self.instance.creator
             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
         if (not self.instance) or (not self.instance.pk):
             # default fields for an 'add' form
             self.fields['kind'].initial = VCPE_KIND
@@ -194,7 +196,7 @@
     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',
-                                     'bbs_account', 'creator', 'instance', 'last_ansible_hash'],
+                                     'wan_container_ip', 'bbs_account', 'creator', 'instance', 'last_ansible_hash'],
                           'classes':['suit-tab suit-tab-general']})]
     readonly_fields = ('backend_status_text', 'service_specific_attribute', 'bbs_account')
     form = VSGTenantForm
diff --git a/xos/services/cord/models.py b/xos/services/cord/models.py
index 6d26048..2f29d81 100644
--- a/xos/services/cord/models.py
+++ b/xos/services/cord/models.py
@@ -1,5 +1,5 @@
 from django.db import models
-from core.models import Service, PlCoreBase, Slice, Instance, Tenant, TenantWithContainer, Node, Image, User, Flavor, Subscriber, NetworkParameter, NetworkParameterType, Port
+from core.models import Service, PlCoreBase, Slice, Instance, Tenant, TenantWithContainer, Node, Image, User, Flavor, Subscriber, NetworkParameter, NetworkParameterType, Port, AddressPool
 from core.models.plcorebase import StrippedCharField
 import os
 from django.db import models, transaction
@@ -10,6 +10,7 @@
 from core.models.service import LeastLoadedNodeScheduler
 import traceback
 from xos.exceptions import *
+from xos.config import Config
 
 class ConfigurationError(Exception):
     pass
@@ -19,6 +20,8 @@
 VBNG_KIND = "vBNG"
 CORD_SUBSCRIBER_KIND = "CordSubscriberRoot"
 
+CORD_USE_VTN = getattr(Config(), "networking_use_vtn", False)
+
 # -------------------------------------------
 # CordSubscriberRoot
 # -------------------------------------------
@@ -453,7 +456,8 @@
 
     sync_attributes = ("nat_ip", "nat_mac",
                        "lan_ip", "lan_mac",
-                       "wan_ip", "wan_mac", "wan_container_mac",
+                       "wan_ip", "wan_mac",
+                       "wan_container_ip", "wan_container_mac",
                        "private_ip", "private_mac",
                        "hpc_client_ip", "hpc_client_mac")
 
@@ -461,7 +465,8 @@
                           "container_id": None,
                           "users": [],
                           "bbs_account": None,
-                          "last_ansible_hash": None}
+                          "last_ansible_hash": None,
+                          "wan_container_ip": None}
 
     def __init__(self, *args, **kwargs):
         super(VSGTenant, self).__init__(*args, **kwargs)
@@ -544,6 +549,10 @@
                 addresses["hpc_client"] = (ns.ip, ns.mac)
         return addresses
 
+    # ------------------------------------------------------------------------
+    # The following IP addresses all come from the VM
+    # Note: They might not be useful for the VTN-vSG
+
     @property
     def nat_ip(self):
         return self.addresses.get("nat", (None,None) )[0]
@@ -568,10 +577,33 @@
     def wan_mac(self):
         return self.addresses.get("wan", (None, None) )[1]
 
+    # end of VM IP address stubs
+    # ------------------------------------------------------------------------
+
+    @property
+    def wan_container_ip(self):
+        if CORD_USE_VTN:
+            # When using VTN, wan_container_ip is stored and maintained inside
+            # of the vSG object.
+            return self.get_attribute("wan_container_ip", self.default_attributes["wan_container_ip"])
+        else:
+            # When not using VTN, wan_container_ip is the same as wan_ip.
+            # XXX Is this broken for multiple-containers-per-VM?
+            return self.wan_ip
+
+    @wan_container_ip.setter
+    def wan_container_ip(self, value):
+        if CORD_USE_VTN:
+            self.set_attribute("wan_container_ip", value)
+        else:
+            raise Exception("wan_container_ip.setter called on non-VTN CORD")
+
     # Generate the MAC for the container interface connected to WAN
     @property
     def wan_container_mac(self):
-        (a, b, c, d) = self.wan_ip.split('.')
+        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))
 
     @property
@@ -721,6 +753,25 @@
                 self.bbs_account = None
                 super(VSGTenant, self).save()
 
+    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.")
+
+                self.wan_container_ip = addr
+
+    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.wan_container_ip = None
+
     def find_or_make_port(self, instance, network, **kwargs):
         port = Port.objects.filter(instance=instance, network=network)
         if port:
@@ -731,10 +782,14 @@
         return port
 
     def get_lan_network(self, instance):
-        # TODO: for VTN, pick the access network
-
         slice = self.provider_service.slices.all()[0]
-        lan_networks = [x for x in slice.networks.all() if "lan" in x.name]
+        if CORD_USE_VTN:
+            # there should only be one network private network, and its template should not be the management template
+            lan_networks = [x for x in slice.networks.all() if x.template.visibility=="private" and (not "management" in x.template.name)]
+            if len(lan_networks)>1:
+                raise XOSProgrammingError("The vSG slice should only have one non-management private network")
+        else:
+            lan_networks = [x for x in slice.networks.all() if "lan" in x.name]
         if not lan_networks:
             raise XOSProgrammingError("No lan_network")
         return lan_networks[0]
@@ -786,14 +841,11 @@
 
         super(VSGTenant, self).save(*args, **kwargs)
         model_policy_vcpe(self.pk)
-        #self.manage_instance()
-        #self.manage_vbng()
-        #self.manage_bbs_account()
-        #self.cleanup_orphans()
 
     def delete(self, *args, **kwargs):
         self.cleanup_vbng()
         self.cleanup_container()
+        self.cleanup_wan_container_ip()
         super(VSGTenant, self).delete(*args, **kwargs)
 
 def model_policy_vcpe(pk):
@@ -803,6 +855,7 @@
         if not vcpe:
             return
         vcpe = vcpe[0]
+        vcpe.manage_wan_container_ip()
         vcpe.manage_container()
         vcpe.manage_vbng()
         vcpe.manage_bbs_account()
diff --git a/xos/synchronizers/monitoring_channel/steps/sync_monitoringchannel.yaml b/xos/synchronizers/monitoring_channel/steps/sync_monitoringchannel.yaml
index 6cda511..c868be9 100644
--- a/xos/synchronizers/monitoring_channel/steps/sync_monitoringchannel.yaml
+++ b/xos/synchronizers/monitoring_channel/steps/sync_monitoringchannel.yaml
@@ -32,24 +32,24 @@
      - remove container
 {% else %}
 {% if full_setup %}
-  - name: Docker repository
-    copy: src=/opt/xos/synchronizers/monitoring_channel/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: Docker repository
+#    copy: src=/opt/xos/synchronizers/monitoring_channel/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
@@ -85,6 +85,32 @@
      - remove container
      - start monitoring-channel
 
+#  - name: Start monitoring-channel container
+#    docker:
+#      docker_api_version: "1.18"
+#      name: monitoring-channel-{{ unique_id }}
+#      # was: reloaded
+#      state: running
+#      image: srikanthvavila/monitoring-channel
+#      expose:
+#      - 8000
+#      ports:
+#      - "{{ ceilometer_port }}:8000"
+#      volumes:
+#      - /usr/local/share/monitoring-channel-{{ unique_id }}_ceilometer_proxy_config:/usr/local/share/ceilometer_proxy_config
+#
+#  - name: Get Docker IP
+#    #TODO: copy dockerip.sh to monitoring service synchronizer
+#    script: /opt/xos/synchronizers/onos/scripts/dockerip.sh monitoring-channel-{{ unique_id }}
+#    register: dockerip
+#
+#  - name: Wait for Monitoring channel to come up
+#    wait_for:
+#      host={{ '{{' }} dockerip.stdout {{ '}}' }}
+#      port={{ '{{' }} item {{ '}}' }}
+#      state=present
+#    with_items:
+#    - {{ ceilometer_port }}
 # These are samples, not necessary for correct function of demo
 
   - name: Make sure Monitoring channel service is running
diff --git a/xos/synchronizers/monitoring_channel/templates/start-monitoring-channel.sh.j2 b/xos/synchronizers/monitoring_channel/templates/start-monitoring-channel.sh.j2
index f56c247..ea5b639 100755
--- a/xos/synchronizers/monitoring_channel/templates/start-monitoring-channel.sh.j2
+++ b/xos/synchronizers/monitoring_channel/templates/start-monitoring-channel.sh.j2
@@ -22,7 +22,12 @@
 then
     #sudo docker build -t monitoring-channel -f Dockerfile.monitoring_channel .
     sudo docker pull srikanthvavila/monitoring-channel
+if [ -z "$HEADNODEFLATLANIP" ] || [ "$HEADNODEFLATLANIP" == "None" ]
+then
+    docker run -d --name=$MONITORING_CHANNEL --privileged=true -p $HOST_FORWARDING_PORT_FOR_CEILOMETER:8000 srikanthvavila/monitoring-channel
+else
     docker run -d --name=$MONITORING_CHANNEL --add-host="ctl:$HEADNODEFLATLANIP" --privileged=true -p $HOST_FORWARDING_PORT_FOR_CEILOMETER:8000 srikanthvavila/monitoring-channel
+fi
 else
     docker start $MONITORING_CHANNEL
 fi
diff --git a/xos/synchronizers/openstack/steps/sync_instances.py b/xos/synchronizers/openstack/steps/sync_instances.py
index 73624a3..884bcf5 100644
--- a/xos/synchronizers/openstack/steps/sync_instances.py
+++ b/xos/synchronizers/openstack/steps/sync_instances.py
@@ -34,8 +34,7 @@
             userdata += '  - %s\n' % key
         return userdata
 
-    def sort_controller_networks(self, nets):
-        nets = list(nets)
+    def sort_nics(self, nics):
         result = []
 
         # Enforce VTN's network order requirement. The access network must be
@@ -43,23 +42,27 @@
         # into the second slot.
 
         # move the private and/or access network to the first spot
-        for net in nets[:]:
-            tem = net.network.template
-            if (tem.visibility == "private") and (tem.translation=="none") and ("management" not in tem.name):
-                result.append(net)
-                nets.remove(net)
+        for nic in nics[:]:
+            network=nic.get("network", None)
+            if network:
+                tem = network.template
+                if (tem.visibility == "private") and (tem.translation=="none") and ("management" not in tem.name):
+                    result.append(nic)
+                    nics.remove(nic)
 
         # move the management network to the second spot
-        for net in nets[:]:
-            tem = net.network.template
-            if (tem.visibility == "private") and (tem.translation=="none") and ("management" in tem.name):
-                if len(result)!=1:
-                    raise Exception("Management network needs to be inserted in slot 1, but there are %d private nets" % len(result))
-                result.append(net)
-                nets.remove(net)
+        for net in nics[:]:
+            network=nic.get("network", None)
+            if network:
+                tem = network.template
+                if (tem.visibility == "private") and (tem.translation=="none") and ("management" in tem.name):
+                    if len(result)!=1:
+                        raise Exception("Management network needs to be inserted in slot 1, but there are %d private nics" % len(result))
+                    result.append(nic)
+                    nics.remove(nic)
 
         # add everything else. For VTN there probably shouldn't be any more.
-        result.extend(nets)
+        result.extend(nics)
 
         return result
 
@@ -84,29 +87,30 @@
         if instance.slice.service and instance.slice.service.public_key:
             pubkeys.add(instance.slice.service.public_key)
 
+        nics=[]
+
         # handle ports the were created by the user
         port_ids=[]
         for port in Port.objects.filter(instance=instance):
             if not port.port_id:
                 raise DeferredException("Instance %s waiting on port %s" % (instance, port))
-            port_ids.append(port.port_id)
+            nics.append({"kind": "port", "value": port.port_id, "network": port.network})
 
         # we want to exclude from 'nics' any network that already has a Port
         existing_port_networks = [port.network for network in Port.objects.filter(instance=instance)]
 
-        nics = []
         networks = [ns.network for ns in NetworkSlice.objects.filter(slice=instance.slice) if ns.network not in existing_port_networks]
         controller_networks = ControllerNetwork.objects.filter(network__in=networks,
                                                                 controller=instance.node.site_deployment.controller)
 
-        controller_networks = self.sort_controller_networks(controller_networks)
+        #controller_networks = self.sort_controller_networks(controller_networks)
         for controller_network in controller_networks:
             # Lenient exception - causes slow backoff
             if controller_network.network.template.visibility == 'private' and \
                controller_network.network.template.translation == 'none':
                    if not controller_network.net_id:
                         raise DeferredException("Instance %s Private Network %s has no id; Try again later" % (instance, controller_network.network.name))
-                   nics.append(controller_network.net_id)
+                   nics.append({"kind": "net", "value": controller_network.net_id, "network": controller_network.network})
 
         # now include network template
         network_templates = [network.template.shared_network_name for network in networks \
@@ -117,12 +121,14 @@
         nets = driver.shell.quantum.list_networks()['networks']
         for net in nets:
             if net['name'] in network_templates:
-                nics.append(net['id'])
+                nics.append({"kind": "net", "value": net['id'], "network": None})
 
         if (not nics):
             for net in nets:
                 if net['name']=='public':
-                    nics.append(net['id'])
+                    nics.append({"kind": "net", "value": net['id'], "network": None})
+
+        nics = self.sort_nics(nics)
 
         image_name = None
         controller_images = instance.image.controllerimages.filter(controller=instance.node.site_deployment.controller)
diff --git a/xos/synchronizers/openstack/steps/sync_instances.yaml b/xos/synchronizers/openstack/steps/sync_instances.yaml
index a61e5cf..3e7182a 100644
--- a/xos/synchronizers/openstack/steps/sync_instances.yaml
+++ b/xos/synchronizers/openstack/steps/sync_instances.yaml
@@ -19,11 +19,8 @@
       user_data: "{{ user_data }}"
       config_drive: yes
       nics:
-      {% for net in nics %}
-          - net-id: {{ net }}
-      {% endfor %}
-      {% for port in ports %}
-          - port-id: {{ port }}
+      {% for nic in nics %}
+          - {{ nic.kind }}-id: {{ nic.value }}
       {% endfor %}
 
       {% if meta %}
diff --git a/xos/tosca/custom_types/xos.m4 b/xos/tosca/custom_types/xos.m4
index c9cea49..2f5b537 100644
--- a/xos/tosca/custom_types/xos.m4
+++ b/xos/tosca/custom_types/xos.m4
@@ -421,6 +421,7 @@
             This is a variant of the TOSCA Network object that includes additional

             XOS-specific properties.

           properties:

+            xos_base_props

             ip_version:

               type: integer

               required: no

diff --git a/xos/tosca/custom_types/xos.yaml b/xos/tosca/custom_types/xos.yaml
index ce8a1ac..d466180 100644
--- a/xos/tosca/custom_types/xos.yaml
+++ b/xos/tosca/custom_types/xos.yaml
@@ -634,6 +634,18 @@
             This is a variant of the TOSCA Network object that includes additional

             XOS-specific properties.

           properties:

+            no-delete:
+                type: boolean
+                default: false
+                description: Do not allow Tosca to delete this object
+            no-create:
+                type: boolean
+                default: false
+                description: Do not allow Tosca to create this object
+            no-update:
+                type: boolean
+                default: false
+                description: Do not allow Tosca to update this object

             ip_version:

               type: integer

               required: no

diff --git a/xos/tosca/resources/slice.py b/xos/tosca/resources/slice.py
index 7dcbd59..48e5eb0 100644
--- a/xos/tosca/resources/slice.py
+++ b/xos/tosca/resources/slice.py
@@ -12,7 +12,7 @@
 class XOSSlice(XOSResource):
     provides = "tosca.nodes.Slice"
     xos_model = Slice
-    copyin_props = ["enabled", "description", "slice_url", "max_instances", "default_isolation", "network", "exposed_ports"]
+    copyin_props = ["enabled", "description", "slice_url", "max_instances", "default_isolation", "default_flavor", "network", "exposed_ports"]
 
     def get_xos_args(self):
         args = super(XOSSlice, self).get_xos_args()