Merge branch 'master' of github.com:open-cloud/xos
diff --git a/xos/api/examples/util.sh b/xos/api/examples/util.sh
index b3d3060..648b32c 100644
--- a/xos/api/examples/util.sh
+++ b/xos/api/examples/util.sh
@@ -41,7 +41,7 @@
     fi
     ID=`echo $JSON | python -c "import json,sys; print json.load(sys.stdin)['related'].get('vsg_id','')"`
     if [[ $ID == "" ]]; then
-        echo "there is no volt for this subscriber" >&2
+        echo "there is no vsg for this subscriber" >&2
         exit -1
     fi
 
diff --git a/xos/api/import_methods.py b/xos/api/import_methods.py
index 1b5e3ca..3702f8a 100644
--- a/xos/api/import_methods.py
+++ b/xos/api/import_methods.py
@@ -30,7 +30,16 @@
 
 def import_module_by_dotted_name(name):
     print "import", name
-    module = __import__(name)
+    try:
+        module = __import__(name)
+    except:
+        # django will eat the exception, and then fail later with
+        #  'conflicting models in application'
+        # when it tries to import the module a second time.
+        print "exception in import_model_by_dotted_name"
+        import traceback
+        traceback.print_exc()
+        raise
     for part in name.split(".")[1:]:
         module = getattr(module, part)
     return module
diff --git a/xos/api/service/vtn.py b/xos/api/service/vtn.py
new file mode 100644
index 0000000..6b02616
--- /dev/null
+++ b/xos/api/service/vtn.py
@@ -0,0 +1,96 @@
+from rest_framework.decorators import api_view
+from rest_framework.response import Response
+from rest_framework.reverse import reverse
+from rest_framework import serializers
+from rest_framework import generics
+from rest_framework import viewsets
+from rest_framework.decorators import detail_route, list_route
+from rest_framework.views import APIView
+from core.models import *
+from services.vtn.models import VTNService
+from django.forms import widgets
+from django.conf.urls import patterns, url
+from api.xosapi_helpers import PlusModelSerializer, XOSViewSet, ReadOnlyField
+from django.shortcuts import get_object_or_404
+from xos.apibase import XOSListCreateAPIView, XOSRetrieveUpdateDestroyAPIView, XOSPermissionDenied
+from xos.exceptions import *
+import json
+import subprocess
+
+class VTNServiceSerializer(PlusModelSerializer):
+    id = ReadOnlyField()
+
+    privateGatewayMac = serializers.CharField(required=False)
+    localManagementIp = serializers.CharField(required=False)
+    ovsdbPort = serializers.IntegerField(required=False)
+    sshPort = serializers.IntegerField(required=False)
+    sshUser = serializers.CharField(required=False)
+    sshKeyFile = serializers.CharField(required=False)
+    mgmtSubnetBits = serializers.IntegerField(required=False)
+    xosEndpoint = serializers.CharField(required=False)
+    xosUser = serializers.CharField(required=False)
+    xosPassword = serializers.CharField(required=False)
+
+
+    humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
+    class Meta:
+        model = VTNService
+        fields = ('humanReadableName', 'id', 'privateGatewayMac', 'localManagementIp', 'ovsdbPort', 'sshPort', 'sshUser', 'sshKeyFile',
+                  'mgmtSubnetBits', 'xosEndpoint', 'xosUser', 'xosPassword')
+
+    def getHumanReadableName(self, obj):
+        return obj.__unicode__()
+
+class VTNViewSet(XOSViewSet):
+    base_name = "vtn"
+    method_name = "vtn"
+    method_kind = "viewset"
+
+    # these are just because ViewSet needs some queryset and model, even if we don't use the
+    # default endpoints
+    queryset = VTNService.get_service_objects().all()
+    model = VTNService
+    serializer_class = VTNServiceSerializer
+
+    @classmethod
+    def get_urlpatterns(self, api_path="^"):
+        patterns = []
+
+        patterns.append( self.detail_url("services/$", {"get": "get_services"}, "services") )
+        patterns.append( self.detail_url("services_names/$", {"get": "get_services_names"}, "services") )
+        patterns.append( self.detail_url("services/(?P<service>[a-zA-Z0-9\-_]+)/$", {"get": "get_service"}, "get_service") )
+
+        # Not as RESTful as it could be, but maintain these endpoints for compability
+        patterns.append( self.list_url("services/$", {"get": "get_services"}, "rootvtn_services") )
+        patterns.append( self.list_url("services_names/$", {"get": "get_services_names"}, "rootvtn_services") )
+        patterns.append( self.list_url("services/(?P<service>[a-zA-Z0-9\-_]+)/$", {"get": "get_service"}, "rootvtn_get_service") )
+
+        patterns = patterns + super(VTNViewSet,self).get_urlpatterns(api_path)
+
+        return patterns
+
+    def get_services_names(self, request, pk=None):
+        result = {}
+        for service in Service.objects.all():
+           for id in service.get_vtn_src_names():
+               dependencies = service.get_vtn_dependencies_names()
+               if dependencies:
+                   result[id] = dependencies
+        return Response(result)
+
+    def get_services(self, request, pk=None):
+        result = {}
+        for service in Service.objects.all():
+           for id in service.get_vtn_src_ids():
+               dependencies = service.get_vtn_dependencies_ids()
+               if dependencies:
+                   result[id] = dependencies
+        return Response(result)
+
+    def get_service(self, request, pk=None, service=None):
+        for xos_service in Service.objects.all():
+            if service in xos_service.get_vtn_src_ids():
+                return Response(xos_service.get_vtn_dependencies_ids())
+        return Response([])
+
+
diff --git a/xos/api/tenant/cord/vsg.py b/xos/api/tenant/cord/vsg.py
new file mode 100644
index 0000000..6807e98
--- /dev/null
+++ b/xos/api/tenant/cord/vsg.py
@@ -0,0 +1,62 @@
+from rest_framework.decorators import api_view
+from rest_framework.response import Response
+from rest_framework.reverse import reverse
+from rest_framework import serializers
+from rest_framework import generics
+from rest_framework import status
+from core.models import *
+from django.forms import widgets
+from services.cord.models import VSGTenant, VSGService, CordSubscriberRoot
+from xos.apibase import XOSListCreateAPIView, XOSRetrieveUpdateDestroyAPIView, XOSPermissionDenied
+from api.xosapi_helpers import PlusModelSerializer, XOSViewSet, ReadOnlyField
+
+def get_default_vsg_service():
+    vsg_services = VSGService.get_service_objects().all()
+    if vsg_services:
+        return vsg_services[0].id
+    return None
+
+class VSGTenantForAPI(VSGTenant):
+    class Meta:
+        proxy = True
+        app_label = "cord"
+
+    @property
+    def related(self):
+        related = {}
+        if self.instance:
+            related["instance_id"] = self.instance.id
+        return related
+
+class VSGTenantSerializer(PlusModelSerializer):
+    id = ReadOnlyField()
+    wan_container_ip = serializers.CharField()
+    wan_container_mac = ReadOnlyField()
+    related = serializers.DictField(required=False)
+
+    humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
+    class Meta:
+        model = VSGTenantForAPI
+        fields = ('humanReadableName', 'id', 'wan_container_ip', 'wan_container_mac', 'related' )
+
+    def getHumanReadableName(self, obj):
+        return obj.__unicode__()
+
+class VSGTenantViewSet(XOSViewSet):
+    base_name = "vsg"
+    method_name = "vsg"
+    method_kind = "viewset"
+    queryset = VSGTenantForAPI.get_tenant_objects().all()
+    serializer_class = VSGTenantSerializer
+
+    @classmethod
+    def get_urlpatterns(self, api_path="^"):
+        patterns = super(VSGTenantViewSet, self).get_urlpatterns(api_path=api_path)
+
+        return patterns
+
+
+
+
+
+
diff --git a/xos/api/utility/__init__.py b/xos/api/utility/__init__.py
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/xos/api/utility/__init__.py
@@ -0,0 +1 @@
+
diff --git a/xos/api/utility/loginview.py b/xos/api/utility/loginview.py
new file mode 100644
index 0000000..2dc79c6
--- /dev/null
+++ b/xos/api/utility/loginview.py
@@ -0,0 +1,101 @@
+from rest_framework.decorators import api_view
+from rest_framework.response import Response
+from rest_framework.reverse import reverse
+from rest_framework import serializers
+from rest_framework import generics
+from rest_framework.views import APIView
+from core.models import *
+from services.hpc.models import *
+from services.requestrouter.models import *
+from django.forms import widgets
+from django.core.exceptions import PermissionDenied
+from django.contrib.contenttypes.models import ContentType
+import json
+import socket
+import time
+import django.middleware.csrf
+from xos.exceptions import *
+from django.contrib.sessions.backends.db import SessionStore
+from django.contrib.sessions.models import Session
+from django.contrib.auth import authenticate
+
+def date_handler(obj):
+    return obj.isoformat() if hasattr(obj, 'isoformat') else obj
+
+def serialize_user(model):
+    serialized = model_to_dict(model)
+    del serialized['timezone']
+    del serialized['password']
+    return json.dumps(serialized, default=date_handler)
+
+class LoginView(APIView):
+    method_kind = "list"
+    method_name = "login"
+
+    def do_login(self, request, username, password):
+        if not username:
+            raise XOSMissingField("No username specified")
+
+        if not password:
+            raise XOSMissingField("No password specified")
+
+        u=authenticate(username=username, password=password)
+        if not u:
+            raise PermissionDenied("Failed to authenticate user %s" % username)
+
+        auth = {"username": username, "password": password}
+        request.session["auth"] = auth
+        request.session['_auth_user_id'] = u.pk
+        request.session['_auth_user_backend'] = u.backend
+        request.session.save()
+
+        return Response({
+            "xoscsrftoken": django.middleware.csrf.get_token(request),
+            "xossessionid": request.session.session_key,
+            "user": serialize_user(u)
+        })
+
+    def get(self, request, format=None):
+        username = request.GET.get("username", None)
+        password = request.GET.get("password", None)
+
+        return self.do_login(request, username, password)
+
+    def post(self, request, format=None):
+        username = request.data.get("username", None)
+        password = request.data.get("password", None)
+
+        return self.do_login(request, username, password)
+
+class LogoutView(APIView):
+    method_kind = "list"
+    method_name = "logout"
+
+    def do_logout(self, request, sessionid):
+        if not sessionid:
+            raise XOSMissingField("No xossessionid specified")
+
+        # Make sure the session exists. This prevents us from accidentally
+        # creating empty sessions with SessionStore()
+        session = Session.objects.filter(session_key=sessionid)
+        if not session:
+            # session doesn't exist
+            raise PermissionDenied("Session does not exist")
+
+        session = SessionStore(session_key=sessionid)
+        if "auth" in session:
+            del session["auth"]
+            session.save()
+        if "_auth_user_id" in session:
+            del session["_auth_user_id"]
+            session.save()
+
+        return Response("Logged Out")
+
+    def get(self, request, format=None):
+        sessionid = request.GET.get("xossessionid", None)
+        return self.do_logout(request, sessionid)
+
+    def post(self, request, format=None):
+        sessionid = request.data.get("xossessionid", None)
+        return self.do_logout(request, sessionid)
\ No newline at end of file
diff --git a/xos/configurations/acord/Makefile b/xos/configurations/acord/Makefile
index b5b93fa..cfa04f8 100644
--- a/xos/configurations/acord/Makefile
+++ b/xos/configurations/acord/Makefile
@@ -8,8 +8,9 @@
 cord: 
 	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 none /opt/xos/configurations/common/fixtures.yaml
+	sudo docker-compose run xos python /opt/xos/tosca/run.py none /opt/xos/configurations/common/mydeployment.yaml
+	sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/cloudlab-openstack.yaml
 	sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/nodes.yaml
 
 acord: cord
diff --git a/xos/configurations/common/cloudlab-openstack.yaml b/xos/configurations/common/cloudlab-openstack.yaml
new file mode 100644
index 0000000..969f84c
--- /dev/null
+++ b/xos/configurations/common/cloudlab-openstack.yaml
@@ -0,0 +1,89 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+# Note:
+#   assumes mydeployment.yaml has already been run, and the following exist:
+#       MyDeployment
+#       mysite
+#       padmin@vicci.org
+#       Public Shared IPv4
+#   assumes the following have been created and filled with appropriate data:
+#       /root/setup/admin_openrc
+#       /root/setup/flat_net_name
+#       /root/setup/padmin_public_key
+
+description: >
+    * Adds OpenCloud Sites, Deployments, and Controllers.
+
+imports:
+   - custom_types/xos.yaml
+
+topology_template:
+  node_templates:
+    trusty-server-multi-nic:
+      type: tosca.nodes.Image
+      properties:
+         disk_format: QCOW2
+         container_format: BARE
+
+    MyDeployment:
+      type: tosca.nodes.Deployment
+      properties:
+          no-create: True
+          no-delete: True
+      requirements:
+          - image:
+              node: trusty-server-multi-nic
+              relationship: tosca.relationships.SupportsImage
+
+    CloudLab:
+      type: tosca.nodes.Controller
+      requirements:
+          - deployment:
+              node: MyDeployment
+              relationship: tosca.relationships.ControllerDeployment
+      properties:
+          backend_type: OpenStack
+          version: Kilo
+          auth_url: { get_script_env: [ SELF, adminrc, OS_AUTH_URL, LOCAL_FILE] }
+          admin_user: { get_script_env: [ SELF, adminrc, OS_USERNAME, LOCAL_FILE] }
+          admin_password: { get_script_env: [ SELF, adminrc, OS_PASSWORD, LOCAL_FILE] }
+          admin_tenant: { get_script_env: [ SELF, adminrc, OS_TENANT_NAME, LOCAL_FILE] }
+          rabbit_user: { get_script_env: [ SELF, controller_settings, RABBIT_USER, LOCAL_FILE] }
+          rabbit_password: { get_script_env: [ SELF, controller_settings, RABBIT_PASS, LOCAL_FILE] }
+          rabbit_host: { get_script_env: [ SELF, controller_settings, CONTROLLER_FLAT_LAN_IP, LOCAL_FILE] }
+          domain: Default
+      artifacts:
+          adminrc: /root/setup/admin-openrc.sh
+          controller_settings: /root/setup/controller_settings
+
+    mysite:
+      type: tosca.nodes.Site
+      properties:
+          no-create: True
+          no-delete: True
+      requirements:
+          - deployment:
+               node: MyDeployment
+               relationship: tosca.relationships.SiteDeployment
+               requirements:
+                   - controller:
+                       node: CloudLab
+                       relationship: tosca.relationships.UsesController
+
+    Public shared IPv4:
+      type: tosca.nodes.NetworkTemplate
+      properties:
+          no-create: True
+          no-delete: True
+          shared_network_name: { get_artifact: [ SELF, flat_net_name, LOCAL_FILE] }
+      artifacts:
+          flat_net_name: /root/setup/flat_net_name
+
+    padmin@vicci.org:
+      type: tosca.nodes.User
+      properties:
+          no-create: True
+          no-delete: True
+          public_key: { get_artifact: [ SELF, pubkey, LOCAL_FILE ] }
+      artifacts:
+          pubkey: /root/setup/padmin_public_key
diff --git a/xos/configurations/common/fixtures.yaml b/xos/configurations/common/fixtures.yaml
index 6419211..6d9c0e8 100644
--- a/xos/configurations/common/fixtures.yaml
+++ b/xos/configurations/common/fixtures.yaml
@@ -7,6 +7,11 @@
 
 topology_template:
   node_templates:
+
+# -----------------------------------------------------------------------------
+# Network Parameter Types
+# -----------------------------------------------------------------------------
+
     s_tag:
       type: tosca.nodes.NetworkParameterType
 
@@ -24,3 +29,97 @@
 
     neutron_port_name:
       type: tosca.nodes.NetworkParameterType
+
+# ----------------------------------------------------------------------------
+# Roles
+# ----------------------------------------------------------------------------
+
+    siterole#admin:
+      type: tosca.nodes.SiteRole
+
+    siterole#pi:
+      type: tosca.nodes.SiteRole
+
+    siterole#tech:
+      type: tosca.nodes.SiteRole
+
+    tenantrole#admin:
+      type: tosca.nodes.TenantRole
+
+    tenantrole#access:
+      type: tosca.nodes.TenantRole
+
+    deploymentrole#admin:
+      type: tosca.nodes.DeploymentRole
+
+    slicerole#admin:
+      type: tosca.nodes.SliceRole
+
+    slicerole#access:
+      type: tosca.nodes.SliceRole
+
+# -----------------------------------------------------------------------------
+# Flavors
+# -----------------------------------------------------------------------------
+
+    m1.small:
+      type: tosca.nodes.Flavor
+
+    m1.medium:
+      type: tosca.nodes.Flavor
+
+    m1.large:
+      type: tosca.nodes.Flavor
+
+# -----------------------------------------------------------------------------
+# Dashboard Views
+# -----------------------------------------------------------------------------
+
+    xsh:
+      type: tosca.nodes.DashboardView
+      properties:
+          url: template:xsh
+
+    Customize:
+      type: tosca.nodes.DashboardView
+      properties:
+          url: template:customize
+
+    Tenant:
+      type: tosca.nodes.DashboardView
+      properties:
+          url: template:xosTenant
+
+    Developer:
+      type: tosca.nodes.DashboardView
+      properties:
+          url: template:xosDeveloper_datatables
+
+# -----------------------------------------------------------------------------
+# Network Templates
+# -----------------------------------------------------------------------------
+
+    Private:
+      type: tosca.nodes.NetworkTemplate
+      properties:
+          visibility: private
+          translation: none
+
+    Public shared IPv4:
+      type: tosca.nodes.NetworkTemplate
+      properties:
+          visibility: private
+          translation: NAT
+          shared_network_name: nat-net
+
+    Public dedicated IPv4:
+      type: tosca.nodes.NetworkTemplate
+      properties:
+          visibility: public
+          translation: none
+          shared_network_name: ext-net
+
+
+
+
+
diff --git a/xos/configurations/common/mydeployment.yaml b/xos/configurations/common/mydeployment.yaml
index 9d2c951..66bb75d 100644
--- a/xos/configurations/common/mydeployment.yaml
+++ b/xos/configurations/common/mydeployment.yaml
@@ -38,13 +38,16 @@
                node: MyDeployment
                relationship: tosca.relationships.SiteDeployment
 
-    # Include the Tenant view so we can make it a default of padmin@vicci.org
+    # Attach the Tenant view to the MyDeployment deployment
     Tenant:
       type: tosca.nodes.DashboardView
       properties:
           no-create: true
-          no-update: true
           no-delete: true
+      requirements:
+          - deployment:
+              node: MyDeployment
+              relationship: tosca.relationships.SupportsDeployment
 
     padmin@vicci.org:
       type: tosca.nodes.User
@@ -62,3 +65,5 @@
               node: Tenant
               relationship: tosca.relationships.UsesDashboard
 
+
+
diff --git a/xos/configurations/cord-deprecated/Makefile b/xos/configurations/cord-deprecated/Makefile
index 1e53e79..184f2d5 100644
--- a/xos/configurations/cord-deprecated/Makefile
+++ b/xos/configurations/cord-deprecated/Makefile
@@ -8,8 +8,9 @@
 cord: virtualbng_json 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 none /opt/xos/configurations/common/fixtures.yaml
+	sudo docker-compose run xos python /opt/xos/tosca/run.py none /opt/xos/configurations/common/mydeployment.yaml
+	sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/cloudlab-openstack.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/cord/cord.yaml
 
diff --git a/xos/configurations/cord-pod/Makefile b/xos/configurations/cord-pod/Makefile
index f1111b4..ce1baf8 100644
--- a/xos/configurations/cord-pod/Makefile
+++ b/xos/configurations/cord-pod/Makefile
@@ -2,17 +2,17 @@
 xos: nodes.yaml images.yaml
 	sudo docker-compose up -d
 	../common/wait_for_xos_port.sh 80
+	sudo docker-compose run xos python /opt/xos/tosca/run.py none /opt/xos/configurations/common/fixtures.yaml
 	sudo docker-compose run xos python /opt/xos/tosca/run.py none /opt/xos/configurations/common/mydeployment.yaml
 	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:
+vtn: vtn-external.yaml
 	sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/vtn-external.yaml
 
-cord: virtualbng_json
+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
 
 exampleservice:
@@ -27,6 +27,9 @@
 images.yaml:
 	export SETUPDIR=.; bash ../common/make-images-yaml.sh
 
+vtn-external.yaml:
+	export SETUPDIR=.; bash ./make-vtn-external-yaml.sh
+
 virtualbng_json:
 	export SETUPDIR=.; bash ./make-virtualbng-json.sh
 
diff --git a/xos/configurations/cord-pod/README.md b/xos/configurations/cord-pod/README.md
index 871bd30..d5051c9 100644
--- a/xos/configurations/cord-pod/README.md
+++ b/xos/configurations/cord-pod/README.md
@@ -31,7 +31,7 @@
 To set up 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.  If you're just getting started with CORD, it's probably best to begin with the 
+repository.  If you're just getting started with CORD, it's probably best to begin with the
 single-node CORD test environment to familiarize yourself with the overall setup.
 
 **NOTE: In order to use the cord-pod configuration, you must set up OpenStack using the above recipe.**
@@ -73,15 +73,15 @@
 ubuntu@xos:~$ cd xos/xos/configurations/cord-pod
 ```
 
-Next, check that the following files exist in this directory:
+Next, check that the following files exist in this directory
+(they will have been put there for you by the cluster installation scripts):
 
  * *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
 
-They will have been put there for you by the cluster installation scripts.
-
-XOS can then be brought up for CORD by running a few `make` commands:
+XOS can then be brought up for CORD by running a few `make` commands.
+First, run:
 
 ```
 ubuntu@xos:~/xos/xos/configurations/cord-pod$ make
@@ -93,37 +93,56 @@
 being sync'ed with OpenStack.  Log into the GUI and select *Users*
 at left.  Make sure there is a green check next to `padmin@vicci.org`.
 
-Next, you may need to edit `vtn-external.yml` so that `rest_hostname:`
-points to the host where ONOS should run the VTN app.  Then run:
+> If you are **not** building the single-node development POD, the next
+> step is to create and edit the VTN configuration.  Run `make vtn-external.yaml`
+> then edit the `vtn-external.yml` TOSCA file.  The `rest_hostname:`
+> field points to the host where ONOS should run the VTN app.  The
+> fields in the `service_vtn` and the objects of type `tosca.nodes.Tag`
+> correspond to the VTN fields listed
+> on [the CORD VTN page on the ONOS Wiki](https://wiki.onosproject.org/display/ONOS/CORD+VTN),
+> under the **ONOS Settings** heading; refer there for the fields'
+> meanings.  
+
+Then run:
 
 ```
 ubuntu@xos:~/xos/xos/configurations/cord-pod$ make vtn
 ```
 The above step configures the ONOS VTN app by generating a configuration
-and pushing it to ONOS.  **If you are not setting up the single-node development POD**, you will 
-need to modify the generated configuration via the XOS GUI. (The defaults
-should be OK for the single-node POD.)  For more information
-about how to configure VTN, see [this page on the ONOS Wiki](https://wiki.onosproject.org/display/ONOS/CORD+VTN),
-under the **ONOS Settings** heading.   
+and pushing it to ONOS.  You are able to see and modify the configuration
+via the GUI as follows:
 
-* To see the generated configuration, go to http://xos/admin/onos/onosapp/, select
+* To see the generated configuration, go to *http://xos/admin/onos/onosapp/*, select
 *VTN_ONOS_app*, then the *Attributes* tab, and look for the
 `rest_onos/v1/network/configuration/` attribute.  
 
-* To change `privateGatewayMac`, `localManagementIp`, `ovsdbPort`, `sshPort`, 
-`sshUser` or `sshKeyFile` in the generated configuration, select *Services* at 
-left in the XOS GUI, then *service_vtn*.  Modify these fields under *VTN Service Details*
-and then select *Save*.
-
-* To change `bridgeId`, `dataPlaneIntf`, or `dataPlaneIp` for a particular compute node, go to
-http://xos/admin/core/node/, select a node, then select the *Tags* tab.  Modify the appropriate tag
-and then select *Save*.
+* To change the VTN configuration, modify the fields of the VTN Service object
+and the Tag objects associated with Nodes.  Don't forget to select *Save*.
 
 * After modifying the above fields, delete the `rest_onos/v1/network/configuration/` attribute
 in the *ONOS_VTN_app* and select *Save*.  The attribute will be regenerated using the new information.
 
-Finally modify `cord-vtn-vsg.yml` and change `addresses_vsg` so that it contains the IP address block,
-gateway IP, and gateway MAC of the fabric.  (Again, the defaults are fine for the single-node POD.)
+* Alternatively, if you want to load your own VTN configuration manually, you can delete the
+`autogenerate` attribute from the *ONOS_VTN_app*, edit the configuration in the
+`rest_onos/v1/network/configuration/` attribute, and select *Save*.
+
+Before proceeding, check that the VTN app is controlling Open vSwitch on the compute nodes.  Log
+into ONOS and run the `cordvtn-nodes` command:
+
+```
+$ ssh -p 8101 karaf@onos-cord   # password is karaf
+onos> cordvtn-nodes
+hostname=nova-compute, hostMgmtIp=192.168.122.177/24, dpIp=192.168.199.1/24, br-int=of:0000000000000001, dpIntf=veth1, init=COMPLETE
+Total 1 nodes
+```
+The important part is the `init=COMPLETE` at the end.  If you do not see this, refer to
+[the CORD VTN page on the ONOS Wiki](https://wiki.onosproject.org/display/ONOS/CORD+VTN) for
+help fixing the problem.  This must be working to bring up VMs on the POD.
+
+> If you are **not** building the single-node development POD, modify `cord-vtn-vsg.yml` 
+> and change `addresses_vsg` so that it contains the IP address block,
+> gateway IP, and gateway MAC of the CORD fabric.  
+
 Then run:
 
 ```
diff --git a/xos/configurations/cord-pod/make-vtn-external-yaml.sh b/xos/configurations/cord-pod/make-vtn-external-yaml.sh
new file mode 100644
index 0000000..c623394
--- /dev/null
+++ b/xos/configurations/cord-pod/make-vtn-external-yaml.sh
@@ -0,0 +1,107 @@
+FN=$SETUPDIR/vtn-external.yaml
+
+rm -f $FN
+
+cat >> $FN <<EOF
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+imports:
+   - custom_types/xos.yaml
+
+description: autogenerated node tags file for VTN configuration
+
+topology_template:
+  node_templates:
+
+    service_ONOS_CORD:
+      type: tosca.nodes.ONOSService
+      requirements:
+      properties:
+          kind: onos
+          view_url: /admin/onos/onosservice/$id$/
+          no_container: true
+          rest_hostname: onos-cord
+
+    service_vtn:
+      type: tosca.nodes.VTNService
+      properties:
+          view_url: /admin/vtn/vtnservice/$id$/
+          privateGatewayMac: 00:00:00:00:00:01
+          localManagementIp: 172.27.0.1/24
+          ovsdbPort: 6641
+          sshUser: root
+          sshKeyFile: /root/node_key
+          sshPort: 22
+          xosEndpoint: http://xos/
+          xosUser: padmin@vicci.org
+          xosPassword: letmein
+
+EOF
+
+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
+    cat >> $FN <<EOF
+    $NODE:
+      type: tosca.nodes.Node
+
+    # VTN bridgeId field for node $NODE
+    ${NODE}_bridgeId_tag:
+      type: tosca.nodes.Tag
+      properties:
+          name: bridgeId
+          value: of:0000000000000001
+      requirements:
+          - target:
+              node: $NODE
+              relationship: tosca.relationships.TagsObject
+          - service:
+              node: service_ONOS_CORD
+              relationship: tosca.relationships.MemberOfService
+
+    # VTN dataPlaneIntf field for node $NODE
+    ${NODE}_dataPlaneIntf_tag:
+      type: tosca.nodes.Tag
+      properties:
+          name: dataPlaneIntf
+          value: veth1
+      requirements:
+          - target:
+              node: $NODE
+              relationship: tosca.relationships.TagsObject
+          - service:
+              node: service_ONOS_CORD
+              relationship: tosca.relationships.MemberOfService
+
+    # VTN dataPlaneIp field for node $NODE
+    ${NODE}_dataPlaneIp_tag:
+      type: tosca.nodes.Tag
+      properties:
+          name: dataPlaneIp
+          value: 10.168.0.253/24
+      requirements:
+          - target:
+              node: $NODE
+              relationship: tosca.relationships.TagsObject
+          - service:
+              node: service_ONOS_CORD
+              relationship: tosca.relationships.MemberOfService
+
+EOF
+done
+
+cat >> $FN <<EOF
+    VTN_ONOS_app:
+      type: tosca.nodes.ONOSVTNApp
+      requirements:
+          - onos_tenant:
+              node: service_ONOS_CORD
+              relationship: tosca.relationships.TenantOfService
+          - vtn_service:
+              node: service_vtn
+              relationship: tosca.relationships.UsedByService
+      properties:
+          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
+          autogenerate: vtn-network-cfg
+EOF
\ No newline at end of file
diff --git a/xos/configurations/cord-pod/vtn-external.yaml b/xos/configurations/cord-pod/vtn-external.yaml
deleted file mode 100644
index 51cca08..0000000
--- a/xos/configurations/cord-pod/vtn-external.yaml
+++ /dev/null
@@ -1,36 +0,0 @@
-tosca_definitions_version: tosca_simple_yaml_1_0
-
-description: Set up ONOS VTN app
-
-imports:
-   - custom_types/xos.yaml
-
-topology_template:
-  node_templates:
-
-    service_ONOS_CORD:
-      type: tosca.nodes.ONOSService
-      requirements:
-      properties:
-          kind: onos
-          view_url: /admin/onos/onosservice/$id$/
-          no_container: true
-          rest_hostname: onos-cord
-
-    VTN_ONOS_app:
-      type: tosca.nodes.ONOSVTNApp
-      requirements:
-          - onos_tenant:
-              node: service_ONOS_CORD
-              relationship: tosca.relationships.TenantOfService
-          - vtn_service:
-              node: service_vtn
-              relationship: tosca.relationships.UsedByService
-      properties:
-          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
-          autogenerate: vtn-network-cfg
-
-    service_vtn:
-      type: tosca.nodes.VTNService
-      properties:
-          view_url: /admin/vtn/vtnservice/$id$/
diff --git a/xos/configurations/devel/Makefile b/xos/configurations/devel/Makefile
index 1e650f3..e55f38b 100644
--- a/xos/configurations/devel/Makefile
+++ b/xos/configurations/devel/Makefile
@@ -7,7 +7,9 @@
 xos:
 	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/base.yaml
+	sudo docker-compose run xos python /opt/xos/tosca/run.py none /opt/xos/configurations/common/fixtures.yaml
+	sudo docker-compose run xos python /opt/xos/tosca/run.py none /opt/xos/configurations/common/mydeployment.yaml
+	sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/cloudlab-openstack.yaml
 	sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/nodes.yaml
 
 containers:
diff --git a/xos/configurations/frontend/Makefile b/xos/configurations/frontend/Makefile
index 27b0044..09c714b 100644
--- a/xos/configurations/frontend/Makefile
+++ b/xos/configurations/frontend/Makefile
@@ -4,6 +4,7 @@
 	sudo make -f ../common/Makefile.prereqs
 	sudo docker-compose up -d
 	bash ../common/wait_for_xos.sh
+	sudo docker-compose run xos python /opt/xos/tosca/run.py none /opt/xos/configurations/common/fixtures.yaml
 	sudo docker-compose run xos python /opt/xos/tosca/run.py none /opt/xos/configurations/common/mydeployment.yaml
 	sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/frontend/sample.yaml
 
@@ -29,7 +30,6 @@
 	sudo docker exec frontend_xos_1 touch /opt/xos/xos/settings.py
 
 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/Makefile b/xos/configurations/opencloud/Makefile
index aef4946..03168ed 100644
--- a/xos/configurations/opencloud/Makefile
+++ b/xos/configurations/opencloud/Makefile
@@ -1,6 +1,7 @@
 xos:
 	sudo docker-compose up -d
 	bash ./wait_for_xos.sh
+	sudo docker-compose run xos python /opt/xos/tosca/run.py none /opt/xos/configurations/common/fixtures.yaml
 	sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/opencloud/opencloud.yaml
 
 containers:
diff --git a/xos/configurations/openvpn/Makefile b/xos/configurations/openvpn/Makefile
index f71f638..aa6f2d5 100644
--- a/xos/configurations/openvpn/Makefile
+++ b/xos/configurations/openvpn/Makefile
@@ -5,7 +5,9 @@
 xos:
 	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/base.yaml
+	sudo docker-compose run xos python /opt/xos/tosca/run.py none /opt/xos/configurations/common/fixtures.yaml
+	sudo docker-compose run xos python /opt/xos/tosca/run.py none /opt/xos/configurations/common/mydeployment.yaml
+	sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/cloudlab-openstack.yaml
 	sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/nodes.yaml
 
 frontend:
diff --git a/xos/configurations/syndicate/Makefile b/xos/configurations/syndicate/Makefile
index eb8050e..3b29ee5 100644
--- a/xos/configurations/syndicate/Makefile
+++ b/xos/configurations/syndicate/Makefile
@@ -7,7 +7,9 @@
 xos: syndicate_config
 	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/base.yaml
+	sudo docker-compose run xos python /opt/xos/tosca/run.py none /opt/xos/configurations/common/fixtures.yaml
+	sudo docker-compose run xos python /opt/xos/tosca/run.py none /opt/xos/configurations/common/mydeployment.yaml
+	sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/cloudlab-openstack.yaml
 	sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/nodes.yaml
 
 containers:
diff --git a/xos/configurations/test-standalone/Makefile b/xos/configurations/test-standalone/Makefile
index 4956607..3ef5848 100644
--- a/xos/configurations/test-standalone/Makefile
+++ b/xos/configurations/test-standalone/Makefile
@@ -29,10 +29,9 @@
 	sudo docker exec teststandalone_xos_db_1 psql -U postgres -d xos -c "SELECT truncate_tables('postgres');"
 	sudo docker exec teststandalone_xos_db_1 psql -U postgres -d xos -c "SELECT setval('core_tenant_id_seq', 1)"
 	sudo docker-compose run xos python /opt/xos/manage.py --noobserver --nomodelpolicy loaddata /opt/xos/core/fixtures/core_initial_data.json
+	sudo docker-compose run xos python /opt/xos/tosca/run.py none /opt/xos/configurations/common/fixtures.yaml
 	sudo docker-compose run xos python /opt/xos/tosca/run.py none /opt/xos/configurations/common/mydeployment.yaml
 	sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/frontend/sample.yaml
-	sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/fixtures.yaml
-
 
 
 test: restore-initial-db-status
diff --git a/xos/configurations/test/Makefile b/xos/configurations/test/Makefile
index adf349a..d4e54fd 100644
--- a/xos/configurations/test/Makefile
+++ b/xos/configurations/test/Makefile
@@ -7,7 +7,9 @@
 xos:
 	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/base.yaml
+	sudo docker-compose run xos python /opt/xos/tosca/run.py none /opt/xos/configurations/common/fixtures.yaml
+	sudo docker-compose run xos python /opt/xos/tosca/run.py none /opt/xos/configurations/common/mydeployment.yaml
+	sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/cloudlab-openstack.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 bash -c "cd /opt/xos/tosca/tests; python ./alltests.py"
 	sudo MYIP=$(MYIP) docker-compose run xos bash -c "cd /opt/xos/tosca/tests; python ./allObserverTests.py"
diff --git a/xos/core/fixtures/core_initial_data.json b/xos/core/fixtures/core_initial_data.json
index db5bd10..01ff999 100644
--- a/xos/core/fixtures/core_initial_data.json
+++ b/xos/core/fixtures/core_initial_data.json
@@ -1,159 +1,6 @@
 [
 {
     "fields": {
-        "updated": "2015-02-17T22:06:38.620Z",
-        "policed": null,
-        "created": "2015-02-17T22:06:38.620Z",
-        "deleted": false,
-        "backend_register": "{}",
-        "role": "admin",
-        "backend_status": "0 - Provisioning in progress",
-        "enacted": null
-    },
-    "model": "core.siterole",
-    "pk": 1
-},
-{
-    "fields": {
-        "updated": "2015-02-17T22:06:38.670Z",
-        "policed": null,
-        "created": "2015-02-17T22:06:38.669Z",
-        "deleted": false,
-        "backend_register": "{}",
-        "role": "pi",
-        "backend_status": "0 - Provisioning in progress",
-        "enacted": null
-    },
-    "model": "core.siterole",
-    "pk": 2
-},
-{
-    "fields": {
-        "updated": "2015-02-17T22:06:38.731Z",
-        "policed": null,
-        "created": "2015-02-17T22:06:38.730Z",
-        "deleted": false,
-        "backend_register": "{}",
-        "role": "tech",
-        "backend_status": "0 - Provisioning in progress",
-        "enacted": null
-    },
-    "model": "core.siterole",
-    "pk": 3
-},
-{
-    "fields": {

-        "updated": "2015-02-17T22:06:38.620Z",

-        "policed": null,

-        "created": "2015-02-17T22:06:38.620Z",

-        "deleted": false,

-        "backend_register": "{}",

-        "role": "admin",

-        "backend_status": "0 - Provisioning in progress",

-        "enacted": null

-    },

-    "model": "core.tenantrole",

-    "pk": 1

-},

-{

-    "fields": {

-        "updated": "2015-02-17T22:06:38.620Z",

-        "policed": null,

-        "created": "2015-02-17T22:06:38.620Z",

-        "deleted": false,

-        "backend_register": "{}",

-        "role": "access",

-        "backend_status": "0 - Provisioning in progress",

-        "enacted": null

-    },

-    "model": "core.tenantrole",

-    "pk": 2

-},
-{
-    "fields": {
-        "updated": "2015-02-17T22:06:38.894Z",
-        "policed": null,
-        "created": "2015-02-17T22:06:38.894Z",
-        "deleted": false,
-        "backend_register": "{}",
-        "role": "admin",
-        "backend_status": "0 - Provisioning in progress",
-        "enacted": null
-    },
-    "model": "core.deploymentrole",
-    "pk": 1
-},
-{
-    "fields": {
-        "updated": "2015-02-17T22:06:38.953Z",
-        "policed": null,
-        "created": "2015-02-17T22:06:38.953Z",
-        "deleted": false,
-        "deployments": [],
-        "enabled": true,
-        "name": "xsh",
-        "backend_register": "{}",
-        "url": "template:xsh",
-        "backend_status": "0 - Provisioning in progress",
-        "enacted": null
-    },
-    "model": "core.dashboardview",
-    "pk": 1
-},
-{
-    "fields": {
-        "updated": "2015-02-17T22:06:39.011Z",
-        "policed": null,
-        "created": "2015-02-17T22:06:39.011Z",
-        "deleted": false,
-        "deployments": [],
-        "enabled": true,
-        "name": "Customize",
-        "backend_register": "{}",
-        "url": "template:customize",
-        "backend_status": "0 - Provisioning in progress",
-        "enacted": null
-    },
-    "model": "core.dashboardview",
-    "pk": 2
-},
-{
-    "fields": {
-        "updated": "2015-02-17T22:06:39.244Z",
-        "policed": null,
-        "created": "2015-02-17T22:06:39.069Z",
-        "deleted": false,
-        "deployments": [
-        ],
-        "enabled": true,
-        "name": "Tenant",
-        "backend_register": "{}",
-        "url": "template:xosTenant",
-        "backend_status": "0 - Provisioning in progress",
-        "enacted": null
-    },
-    "model": "core.dashboardview",
-    "pk": 3
-},
-{
-    "fields": {
-        "updated": "2015-02-17T22:06:39.302Z",
-        "policed": null,
-        "created": "2015-02-17T22:06:39.302Z",
-        "deleted": false,
-        "deployments": [],
-        "enabled": true,
-        "name": "Developer",
-        "backend_register": "{}",
-        "url": "template:xosDeveloper_datatables",
-        "backend_status": "0 - Provisioning in progress",
-        "enacted": null
-    },
-    "model": "core.dashboardview",
-    "pk": 4
-},
-{
-    "fields": {
         "updated": "2015-02-17T22:06:39.361Z",
         "membershipFee": 0,
         "policed": null,
@@ -171,159 +18,5 @@
     },
     "model": "core.serviceclass",
     "pk": 1
-},
-{
-    "fields": {
-        "updated": "2015-02-17T22:06:38.236Z",
-        "policed": null,
-        "created": "2015-02-17T22:06:38.095Z",
-        "deleted": false,
-        "deployments": [
-        ],
-        "description": null,
-        "name": "m1.small",
-        "backend_register": "{}",
-        "default": false,
-        "flavor": "m1.small",
-        "backend_status": "0 - Provisioning in progress",
-        "order": 0,
-        "enacted": null
-    },
-    "model": "core.flavor",
-    "pk": 1
-},
-{
-    "fields": {
-        "updated": "2015-02-17T22:06:38.394Z",
-        "policed": null,
-        "created": "2015-02-17T22:06:38.287Z",
-        "deleted": false,
-        "deployments": [
-        ],
-        "description": null,
-        "name": "m1.medium",
-        "backend_register": "{}",
-        "default": false,
-        "flavor": "m1.medium",
-        "backend_status": "0 - Provisioning in progress",
-        "order": 0,
-        "enacted": null
-    },
-    "model": "core.flavor",
-    "pk": 2
-},
-{
-    "fields": {
-        "updated": "2015-02-17T22:06:38.561Z",
-        "policed": null,
-        "created": "2015-02-17T22:06:38.445Z",
-        "deleted": false,
-        "deployments": [
-        ],
-        "description": null,
-        "name": "m1.large",
-        "backend_register": "{}",
-        "default": false,
-        "flavor": "m1.large",
-        "backend_status": "0 - Provisioning in progress",
-        "order": 0,
-        "enacted": null
-    },
-    "model": "core.flavor",
-    "pk": 3
-},
-{
-    "fields": {
-        "updated": "2015-02-17T22:06:38.778Z",
-        "policed": null,
-        "created": "2015-02-17T22:06:38.778Z",
-        "deleted": false,
-        "backend_register": "{}",
-        "role": "admin",
-        "backend_status": "0 - Provisioning in progress",
-        "enacted": null
-    },
-    "model": "core.slicerole",
-    "pk": 1
-},
-{
-    "fields": {
-        "updated": "2015-02-17T22:06:38.836Z",
-        "policed": null,
-        "created": "2015-02-17T22:06:38.836Z",
-        "deleted": false,
-        "backend_register": "{}",
-        "role": "access",
-        "backend_status": "0 - Provisioning in progress",
-        "enacted": null
-    },
-    "model": "core.slicerole",
-    "pk": 2
-},
-{
-    "fields": {
-        "shared_network_id": null,
-        "updated": "2015-02-17T22:06:39.419Z",
-        "policed": null,
-        "created": "2015-02-17T22:06:39.419Z",
-        "deleted": false,
-        "description": "A private virtual network",
-        "visibility": "private",
-        "name": "Private",
-        "backend_register": "{}",
-        "topology_kind": "bigswitch",
-        "guaranteed_bandwidth": 0,
-        "translation": "none",
-        "backend_status": "0 - Provisioning in progress",
-        "shared_network_name": null,
-        "controller_kind": null,
-        "enacted": null
-    },
-    "model": "core.networktemplate",
-    "pk": 1
-},
-{
-    "fields": {
-        "shared_network_id": null,
-        "updated": "2015-02-17T22:06:39.477Z",
-        "policed": null,
-        "created": "2015-02-17T22:06:39.477Z",
-        "deleted": false,
-        "description": "Connect a instance to the public network",
-        "visibility": "private",
-        "name": "Public shared IPv4",
-        "backend_register": "{}",
-        "topology_kind": "bigswitch",
-        "guaranteed_bandwidth": 0,
-        "translation": "NAT",
-        "backend_status": "0 - Provisioning in progress",
-        "shared_network_name": "nat-net",
-        "controller_kind": null,
-        "enacted": null
-    },
-    "model": "core.networktemplate",
-    "pk": 2
-},
-{
-    "fields": {
-        "shared_network_id": null,
-        "updated": "2015-02-17T22:06:39.536Z",
-        "policed": null,
-        "created": "2015-02-17T22:06:39.536Z",
-        "deleted": false,
-        "description": "Connect a instance to the public network",
-        "visibility": "public",
-        "name": "Public dedicated IPv4",
-        "backend_register": "{}",
-        "topology_kind": "bigswitch",
-        "guaranteed_bandwidth": 0,
-        "translation": "none",
-        "backend_status": "0 - Provisioning in progress",
-        "shared_network_name": "ext-net",
-        "controller_kind": null,
-        "enacted": null
-    },
-    "model": "core.networktemplate",
-    "pk": 3
 }
 ]
diff --git a/xos/core/models/plcorebase.py b/xos/core/models/plcorebase.py
index c8c25a7..060570d 100644
--- a/xos/core/models/plcorebase.py
+++ b/xos/core/models/plcorebase.py
@@ -2,6 +2,7 @@
 import json
 import os
 import sys
+import threading
 from django import db
 from django.db import models
 from django.forms.models import model_to_dict
@@ -198,7 +199,7 @@
     # default values for created and updated are only there to keep evolution
     # from failing.
     created = models.DateTimeField(auto_now_add=True, default=timezone.now)
-    updated = models.DateTimeField(auto_now=True, default=timezone.now)
+    updated = models.DateTimeField(default=timezone.now)
     enacted = models.DateTimeField(null=True, blank=True, default=None)
     policed = models.DateTimeField(null=True, blank=True, default=None)
 
@@ -270,6 +271,9 @@
                 if not (field in ["backend_register", "backend_status", "deleted", "enacted", "updated"]):
                     ignore_composite_key_check=False
 
+        if 'synchronizer' not in threading.current_thread().name:
+            self.updated = datetime.datetime.now()
+
         super(PlCoreBase, self).save(*args, **kwargs)
 
         # This is a no-op if observer_disabled is set
diff --git a/xos/core/xoslib/methods/loginview.py b/xos/core/xoslib/methods/loginview.py
old mode 100755
new mode 100644
index 69ee289..2dc79c6
--- a/xos/core/xoslib/methods/loginview.py
+++ b/xos/core/xoslib/methods/loginview.py
@@ -62,8 +62,8 @@
         return self.do_login(request, username, password)
 
     def post(self, request, format=None):
-        username = request.DATA.get("username", None)
-        password = request.DATA.get("password", None)
+        username = request.data.get("username", None)
+        password = request.data.get("password", None)
 
         return self.do_login(request, username, password)
 
@@ -97,5 +97,5 @@
         return self.do_logout(request, sessionid)
 
     def post(self, request, format=None):
-        sessionid = request.DATA.get("xossessionid", None)
+        sessionid = request.data.get("xossessionid", None)
         return self.do_logout(request, sessionid)
\ No newline at end of file
diff --git a/xos/core/xoslib/methods/vtn.py b/xos/core/xoslib/methods/vtn.py
index 1a2af53..c9dbf3a 100644
--- a/xos/core/xoslib/methods/vtn.py
+++ b/xos/core/xoslib/methods/vtn.py
@@ -57,7 +57,8 @@
         for xos_service in Service.objects.all():
             if service in xos_service.get_vtn_src_ids():
                 return Response(xos_service.get_vtn_dependencies_ids())
-        raise DoesNotExist()
+        return Response([])
+        # raise DoesNotExist()
 
     def list(self, request):
         raise Exception("Not Implemented")
diff --git a/xos/services/vtn/admin.py b/xos/services/vtn/admin.py
index c64e054..03ff5cd 100644
--- a/xos/services/vtn/admin.py
+++ b/xos/services/vtn/admin.py
@@ -29,6 +29,9 @@
     sshUser = forms.CharField(required=False)
     sshKeyFile = forms.CharField(required=False)
     mgmtSubnetBits = forms.CharField(required=False)
+    xosEndpoint = forms.CharField(required=False)
+    xosUser = forms.CharField(required=False)
+    xosPassword = forms.CharField(required=False)
 
     def __init__(self,*args,**kwargs):
         super (VTNServiceForm,self ).__init__(*args,**kwargs)
@@ -40,6 +43,9 @@
             self.fields['sshUser'].initial = self.instance.sshUser
             self.fields['sshKeyFile'].initial = self.instance.sshKeyFile
             self.fields['mgmtSubnetBits'].initial = self.instance.mgmtSubnetBits
+            self.fields['xosEndpoint'].initial = self.instance.xosEndpoint
+            self.fields['xosUser'].initial = self.instance.xosUser
+            self.fields['xosPassword'].initial = self.instance.xosPassword
 
     def save(self, commit=True):
         self.instance.privateGatewayMac = self.cleaned_data.get("privateGatewayMac")
@@ -49,6 +55,9 @@
         self.instance.sshUser = self.cleaned_data.get("sshUser")
         self.instance.sshKeyFile = self.cleaned_data.get("sshKeyFile")
         self.instance.mgmtSubnetBits = self.cleaned_data.get("mgmtSubnetBits")
+        self.instance.xosEndpoint = self.cleaned_data.get("xosEndpoint")
+        self.instance.xosUser = self.cleaned_data.get("xosUser")
+        self.instance.xosPassword = self.cleaned_data.get("xosPassword")
         return super(VTNServiceForm, self).save(commit=commit)
 
     class Meta:
@@ -62,7 +71,7 @@
     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",
-                                    'privateGatewayMac', 'localManagementIp', 'ovsdbPort', 'sshPort', 'sshUser', 'sshKeyFile', 'mgmtSubnetBits' ], 'classes':['suit-tab suit-tab-general']})]
+                                    'privateGatewayMac', 'localManagementIp', 'ovsdbPort', 'sshPort', 'sshUser', 'sshKeyFile', 'mgmtSubnetBits', 'xosEndpoint', 'xosUser', 'xosPassword' ], 'classes':['suit-tab suit-tab-general']})]
     readonly_fields = ('backend_status_text', )
     inlines = [SliceInline,ServiceAttrAsTabInline,ServicePrivilegeInline]
 
@@ -84,4 +93,3 @@
         return VTNService.get_service_objects_by_user(request.user)
 
 admin.site.register(VTNService, VTNServiceAdmin)
-
diff --git a/xos/services/vtn/models.py b/xos/services/vtn/models.py
index cb254d7..52b1633 100644
--- a/xos/services/vtn/models.py
+++ b/xos/services/vtn/models.py
@@ -37,8 +37,10 @@
                           ("sshUser", "root"),
                           ("sshKeyFile", "/root/node_key") ,
                           ("mgmtSubnetBits", "24"),
+                          ("xosEndpoint", "http://xos/"),
+                          ("xosUser", "padmin@vicci.org"),
+                          ("xosPassword", "letmein"),
 
                          )
 
 VTNService.setup_simple_attributes()
-
diff --git a/xos/synchronizers/base/backend.py b/xos/synchronizers/base/backend.py
index 5f11d46..d7307fa 100644
--- a/xos/synchronizers/base/backend.py
+++ b/xos/synchronizers/base/backend.py
@@ -15,7 +15,7 @@
     def run(self):
         # start the openstack observer
         observer = XOSObserver()
-        observer_thread = threading.Thread(target=observer.run)
+        observer_thread = threading.Thread(target=observer.run,name='synchronizer')
         observer_thread.start()
 
         # start model policies thread
diff --git a/xos/synchronizers/base/event_loop.py b/xos/synchronizers/base/event_loop.py
index f224380..4f7d436 100644
--- a/xos/synchronizers/base/event_loop.py
+++ b/xos/synchronizers/base/event_loop.py
@@ -521,7 +521,12 @@
 
                         loop_end = time.time()
 
-                        diag = Diag.objects.filter(name=Config().observer_name).first()
+                        try:
+                            observer_name = Config().observer_name
+                        except:
+                            observer_name = ''
+
+                        diag = Diag.objects.filter(name=observer_name).first()
                         if (diag):
                             br_str = diag.backend_register
                             br = json.loads(br_str)
diff --git a/xos/synchronizers/onos/steps/sync_onosapp.py b/xos/synchronizers/onos/steps/sync_onosapp.py
index 1233ad7..7b80641 100644
--- a/xos/synchronizers/onos/steps/sync_onosapp.py
+++ b/xos/synchronizers/onos/steps/sync_onosapp.py
@@ -118,18 +118,9 @@
                 raise Exception("Controller user object for %s does not exist" % instance.creator)
             return cuser.kuser_id
 
-
-    def node_tag_default(self, o, node, tagname, default):
+    def get_node_tag(self, o, node, tagname):
         tags = Tag.select_by_content_object(node).filter(name=tagname)
-        if tags:
-            value = tags[0].value
-        else:
-            value = default
-            logger.info("node %s: saving default value %s for tag %s" % (node.name, value, tagname))
-            service = self.get_onos_service(o)
-            tag = Tag(service=service, content_object=node, name=tagname, value=value)
-            tag.save()
-        return value
+        return tags[0].value
 
     # Scan attrs for attribute name
     # If it's not present, save it as a TenantAttribute
@@ -153,6 +144,9 @@
         sshUser = None
         sshKeyFile = None
         mgmtSubnetBits = None
+        xosEndpoint = None
+        xosUser = None
+        xosPassword = None
 
         # VTN-specific configuration from the VTN Service
         vtns = VTNService.get_service_objects().all()
@@ -165,6 +159,9 @@
             sshUser = vtn.sshUser
             sshKeyFile = vtn.sshKeyFile
             mgmtSubnetBits = vtn.mgmtSubnetBits
+            xosEndpoint = vtn.xosEndpoint
+            xosUser = vtn.xosUser
+            xosPassword = vtn.xosPassword
 
         # OpenStack endpoints and credentials
         keystone_server = "http://keystone:5000/v2.0/"
@@ -196,6 +193,11 @@
                             "user": user_name,
                             "password": password
                         },
+                        "xos": {
+                            "endpoint": xosEndpoint,
+                            "user": xosUser,
+                            "password": xosPassword
+                        },
                         "publicGateways": [],
                         "nodes" : []
                     }
@@ -209,10 +211,9 @@
             nodeip = socket.gethostbyname(node.name)
 
             try:
-                bridgeId = self.node_tag_default(o, node, "bridgeId", "of:0000000000000001")
-                dataPlaneIntf = self.node_tag_default(o, node, "dataPlaneIntf", "veth1")
-                # This should be generated from the AddressPool if not present
-                dataPlaneIp = self.node_tag_default(o, node, "dataPlaneIp", "192.168.199.1/24")
+                bridgeId = self.get_node_tag(o, node, "bridgeId")
+                dataPlaneIntf = self.get_node_tag(o, node, "dataPlaneIntf")
+                dataPlaneIp = self.get_node_tag(o, node, "dataPlaneIp")
             except:
                 logger.error("not adding node %s to the VTN configuration" % node.name)
                 continue
diff --git a/xos/synchronizers/vtr/steps/sync_vtrtenant.py b/xos/synchronizers/vtr/steps/sync_vtrtenant.py
index 8debadf..c66f19c 100644
--- a/xos/synchronizers/vtr/steps/sync_vtrtenant.py
+++ b/xos/synchronizers/vtr/steps/sync_vtrtenant.py
@@ -95,9 +95,9 @@
 
         # add in the sync_attributes that come from the vSG object
         # this will be wan_ip, wan_mac, wan_container_ip, wan_container_mac, ...
-        if o.target and o.target.volt and o.target.volt.vsg:
-            for attribute_name in o.target.volt.vsg.sync_attributes:
-                fields[attribute_name] = getattr(o.target.volt.vsg, attribute_name)
+        if o.target and o.target.volt and o.target.volt.vcpe:
+            for attribute_name in o.target.volt.vcpe.sync_attributes:
+                fields[attribute_name] = getattr(o.target.volt.vcpe, attribute_name)
 
         # add in the sync_attributes that come from the SubscriberRoot object
         if o.target and hasattr(o.target, "sync_attributes"):
diff --git a/xos/tosca/custom_types/xos.m4 b/xos/tosca/custom_types/xos.m4
index c114652..32eefa4 100644
--- a/xos/tosca/custom_types/xos.m4
+++ b/xos/tosca/custom_types/xos.m4
@@ -282,6 +282,16 @@
             mgmtSubnetBits:
                 type: string
                 required: false
+            xosEndpoint:
+                type: string
+                required: false
+            xosUser:
+                type: string
+                required: false
+            xosPassword:
+                type: string
+                required: false
+
 
     tosca.nodes.CDNService:
         derived_from: tosca.nodes.Root
@@ -385,16 +395,17 @@
                 type: tosca.capabilities.xos.User
 
         properties:
+            xos_base_props
             password:
                 type: string
                 required: false
             firstname:
                 type: string
-                required: true
+                required: false
                 description: First name of User.
             lastname:
                 type: string
-                required: true
+                required: false
                 description: Last name of User.
             phone:
                 type: string
@@ -410,11 +421,13 @@
                 description: Public key that will be installed in Instances.
             is_active:
                 type: boolean
-                default: true
+                required: false
+                #default: true
                 description: If True, the user may log in.
             is_admin:
                 type: boolean
-                default: false
+                required: false
+                #default: false
                 description: If True, the user has root admin privileges.
             login_page:
                 type: string
@@ -428,6 +441,9 @@
             An XOS network parameter type. May be applied to Networks and/or
             Ports.
 
+        properties:
+            xos_base_props
+
         capabilities:
             network_parameter_type:
                 type: tosca.capabilities.xos.NetworkParameterType
@@ -444,13 +460,14 @@
                 type: tosca.capabilities.xos.NetworkTemplate
 
         properties:
+            xos_base_props
             visibility:
                 type: string
-                default: private
+                required: false
                 description: Indicates whether network is publicly routable.
             translation:
                 type: string
-                default: none
+                required: false
                 description: Indicates whether network uses address translation.
             shared_network_name:
                 type: string
@@ -462,7 +479,7 @@
                 description: Attaches this template to a specific OpenStack network.
             topology_kind:
                 type: string
-                default: BigSwitch
+                required: false
                 description: Describes the topology of the network.
             controller_kind:
                 type: string
@@ -792,6 +809,46 @@
             flavor:
                 type: tosca.capabilities.xos.Flavor
 
+    tosca.nodes.SiteRole:
+        derived_from: tosca.nodes.Root
+        description: >
+            An XOS Site Role.
+        properties:
+            xos_base_props
+        capabilities:
+            siterole:
+                type: tosca.capabilities.xos.SiteRole
+
+    tosca.nodes.SliceRole:
+        derived_from: tosca.nodes.Root
+        description: >
+            An XOS Slice Role.
+        properties:
+            xos_base_props
+        capabilities:
+            slicerole:
+                type: tosca.capabilities.xos.SliceRole
+
+    tosca.nodes.TenantRole:
+        derived_from: tosca.nodes.Root
+        description: >
+            An XOS Tenant Role.
+        properties:
+            xos_base_props
+        capabilities:
+            tenantrole:
+                type: tosca.capabilities.xos.TenantRole
+
+    tosca.nodes.DeploymentRole:
+        derived_from: tosca.nodes.Root
+        description: >
+            An XOS Deployment Role.
+        properties:
+            xos_base_props
+        capabilities:
+            deploymentrole:
+                type: tosca.capabilities.xos.DeploymentRole
+
     tosca.nodes.DashboardView:
         derived_from: tosca.nodes.Root
         description: >
@@ -809,6 +866,21 @@
                 required: false
                 description: URL to the dashboard
 
+    tosca.nodes.Tag:
+        derived_from: tosca.nodes.Root
+        description: >
+            An XOS Tag
+        properties:
+            xos_base_props
+            name:
+                type: string
+                required: true
+                descrption: name of tag
+            value:
+                type: string
+                required: false
+                descrption: value of tag
+
     tosca.nodes.Compute.Container:
       derived_from: tosca.nodes.Compute
       description: >
@@ -945,6 +1017,9 @@
     tosca.relationships.DependsOn:
         derived_from: tosca.relationships.Root
 
+    tosca.relationships.TagsObject:
+        derived_from: tosca.relationships.Root
+
     tosca.capabilities.xos.Service:
         derived_from: tosca.capabilities.Root
         description: An XOS Service
@@ -997,6 +1072,22 @@
         derived_from: tosca.capabilities.Root
         description: An XOS Flavor
 
+    tosca.capabilities.xos.DeploymentRole:
+        derived_from: tosca.capabilities.Root
+        description: An XOS DeploymentRole
+
+    tosca.capabilities.xos.SliceRole:
+        derived_from: tosca.capabilities.Root
+        description: An XOS SliceRole
+
+    tosca.capabilities.xos.SiteRole:
+        derived_from: tosca.capabilities.Root
+        description: An XOS SiteRole
+
+    tosca.capabilities.xos.TenantRole:
+        derived_from: tosca.capabilities.Root
+        description: An XOS TenantRole
+
     tosca.capabilities.xos.Image:
         derived_from: tosca.capabilities.Root
         description: An XOS Image
diff --git a/xos/tosca/custom_types/xos.yaml b/xos/tosca/custom_types/xos.yaml
index a89641c..8102d1c 100644
--- a/xos/tosca/custom_types/xos.yaml
+++ b/xos/tosca/custom_types/xos.yaml
@@ -516,6 +516,15 @@
             mgmtSubnetBits:
                 type: string
                 required: false
+            xosEndpoint:
+                type: string
+                required: false
+            xosUser:
+                type: string
+                required: false
+            xosPassword:
+                type: string
+                required: false
 
     tosca.nodes.CDNService:
         derived_from: tosca.nodes.Root
@@ -730,16 +739,28 @@
                 type: tosca.capabilities.xos.User
 
         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
             password:
                 type: string
                 required: false
             firstname:
                 type: string
-                required: true
+                required: false
                 description: First name of User.
             lastname:
                 type: string
-                required: true
+                required: false
                 description: Last name of User.
             phone:
                 type: string
@@ -755,11 +776,13 @@
                 description: Public key that will be installed in Instances.
             is_active:
                 type: boolean
-                default: true
+                required: false
+                #default: true
                 description: If True, the user may log in.
             is_admin:
                 type: boolean
-                default: false
+                required: false
+                #default: false
                 description: If True, the user has root admin privileges.
             login_page:
                 type: string
@@ -773,6 +796,20 @@
             An XOS network parameter type. May be applied to Networks and/or
             Ports.
 
+        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
+
         capabilities:
             network_parameter_type:
                 type: tosca.capabilities.xos.NetworkParameterType
@@ -789,13 +826,25 @@
                 type: tosca.capabilities.xos.NetworkTemplate
 
         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
             visibility:
                 type: string
-                default: private
+                required: false
                 description: Indicates whether network is publicly routable.
             translation:
                 type: string
-                default: none
+                required: false
                 description: Indicates whether network uses address translation.
             shared_network_name:
                 type: string
@@ -807,7 +856,7 @@
                 description: Attaches this template to a specific OpenStack network.
             topology_kind:
                 type: string
-                default: BigSwitch
+                required: false
                 description: Describes the topology of the network.
             controller_kind:
                 type: string
@@ -1236,6 +1285,90 @@
             flavor:
                 type: tosca.capabilities.xos.Flavor
 
+    tosca.nodes.SiteRole:
+        derived_from: tosca.nodes.Root
+        description: >
+            An XOS Site Role.
+        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
+        capabilities:
+            siterole:
+                type: tosca.capabilities.xos.SiteRole
+
+    tosca.nodes.SliceRole:
+        derived_from: tosca.nodes.Root
+        description: >
+            An XOS Slice Role.
+        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
+        capabilities:
+            slicerole:
+                type: tosca.capabilities.xos.SliceRole
+
+    tosca.nodes.TenantRole:
+        derived_from: tosca.nodes.Root
+        description: >
+            An XOS Tenant Role.
+        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
+        capabilities:
+            tenantrole:
+                type: tosca.capabilities.xos.TenantRole
+
+    tosca.nodes.DeploymentRole:
+        derived_from: tosca.nodes.Root
+        description: >
+            An XOS Deployment Role.
+        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
+        capabilities:
+            deploymentrole:
+                type: tosca.capabilities.xos.DeploymentRole
+
     tosca.nodes.DashboardView:
         derived_from: tosca.nodes.Root
         description: >
@@ -1264,6 +1397,32 @@
                 required: false
                 description: URL to the dashboard
 
+    tosca.nodes.Tag:
+        derived_from: tosca.nodes.Root
+        description: >
+            An XOS Tag
+        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
+            name:
+                type: string
+                required: true
+                descrption: name of tag
+            value:
+                type: string
+                required: false
+                descrption: value of tag
+
     tosca.nodes.Compute.Container:
       derived_from: tosca.nodes.Compute
       description: >
@@ -1400,6 +1559,9 @@
     tosca.relationships.DependsOn:
         derived_from: tosca.relationships.Root
 
+    tosca.relationships.TagsObject:
+        derived_from: tosca.relationships.Root
+
     tosca.capabilities.xos.Service:
         derived_from: tosca.capabilities.Root
         description: An XOS Service
@@ -1452,6 +1614,22 @@
         derived_from: tosca.capabilities.Root
         description: An XOS Flavor
 
+    tosca.capabilities.xos.DeploymentRole:
+        derived_from: tosca.capabilities.Root
+        description: An XOS DeploymentRole
+
+    tosca.capabilities.xos.SliceRole:
+        derived_from: tosca.capabilities.Root
+        description: An XOS SliceRole
+
+    tosca.capabilities.xos.SiteRole:
+        derived_from: tosca.capabilities.Root
+        description: An XOS SiteRole
+
+    tosca.capabilities.xos.TenantRole:
+        derived_from: tosca.capabilities.Root
+        description: An XOS TenantRole
+
     tosca.capabilities.xos.Image:
         derived_from: tosca.capabilities.Root
         description: An XOS Image
diff --git a/xos/tosca/resources/CORDUser.py b/xos/tosca/resources/CORDUser.py
index 566e205..705a895 100644
--- a/xos/tosca/resources/CORDUser.py
+++ b/xos/tosca/resources/CORDUser.py
@@ -28,12 +28,12 @@
         if not sub:
            return []
         for user in sub.users:
-            if user["name"] == self.nodetemplate.name:
+            if user["name"] == self.obj_name:
                 result.append(user)
         return result
 
     def get_xos_args(self):
-        args = {"name": self.nodetemplate.name,
+        args = {"name": self.obj_name,
                 "level": self.get_property("level"),
                 "mac": self.get_property("mac")}
         return args
@@ -46,7 +46,7 @@
         sub.create_user(**xos_args)
         sub.save()
 
-        self.info("Created CORDUser %s for Subscriber %s" % (self.nodetemplate.name, sub.name))
+        self.info("Created CORDUser %s for Subscriber %s" % (self.obj_name, sub.name))
 
     def update(self, obj):
         pass
diff --git a/xos/tosca/resources/cdnprefix.py b/xos/tosca/resources/cdnprefix.py
index 5faaca8..8daf7fb 100644
--- a/xos/tosca/resources/cdnprefix.py
+++ b/xos/tosca/resources/cdnprefix.py
@@ -16,7 +16,7 @@
     copyin_props = []
 
     def get_xos_args(self):
-        args = {"prefix": self.nodetemplate.name}
+        args = {"prefix": self.obj_name}
 
         cp_name = self.get_requirement("tosca.relationships.MemberOfContentProvider")
         if cp_name:
diff --git a/xos/tosca/resources/compute.py b/xos/tosca/resources/compute.py
index 37ba390..2af010a 100644
--- a/xos/tosca/resources/compute.py
+++ b/xos/tosca/resources/compute.py
@@ -39,7 +39,7 @@
         nodetemplate = self.nodetemplate
 
         if not name:
-            name = nodetemplate.name
+            name = self.obj_name
 
         args = {"name": name}
 
@@ -105,7 +105,7 @@
         if scalable:
             default_instances = scalable.get("default_instances",1)
             for i in range(0, default_instances):
-                name = "%s-%d" % (self.nodetemplate.name, i)
+                name = "%s-%d" % (self.obj_name, i)
                 existing_instances = Instance.objects.filter(name=name)
                 if existing_instances:
                     self.info("%s %s already exists" % (self.xos_model.__name__, name))
@@ -121,7 +121,7 @@
             existing_instances = []
             max_instances = scalable.get("max_instances",1)
             for i in range(0, max_instances):
-                name = "%s-%d" % (self.nodetemplate.name, i)
+                name = "%s-%d" % (self.obj_name, i)
                 existing_instances = existing_instances + list(Instance.objects.filter(name=name))
             return existing_instances
         else:
diff --git a/xos/tosca/resources/contentprovider.py b/xos/tosca/resources/contentprovider.py
index 06ca02e..66742ea 100644
--- a/xos/tosca/resources/contentprovider.py
+++ b/xos/tosca/resources/contentprovider.py
@@ -17,7 +17,7 @@
     def get_xos_args(self):
         sp_name = self.get_requirement("tosca.relationships.MemberOfServiceProvider", throw_exception=True)
         sp = self.get_xos_object(ServiceProvider, name=sp_name)
-        return {"name": self.nodetemplate.name,
+        return {"name": self.obj_name,
                 "serviceProvider": sp}
 
     def can_delete(self, obj):
diff --git a/xos/tosca/resources/dashboardview.py b/xos/tosca/resources/dashboardview.py
index 9f7687c..3bce58d 100644
--- a/xos/tosca/resources/dashboardview.py
+++ b/xos/tosca/resources/dashboardview.py
@@ -17,6 +17,14 @@
     def get_xos_args(self):
         return super(XOSDashboardView, self).get_xos_args()
 
+    def postprocess(self, obj):
+        for deployment_name in self.get_requirements("tosca.relationships.SupportsDeployment"):
+            deployment = self.get_xos_object(Deployment, deployment_name)
+            if not deployment in obj.deployments.all():
+                print "attaching dashboardview %s to deployment %s" % (obj, deployment)
+                obj.deployments.add(deployment)
+                obj.save()
+
     def can_delete(self, obj):
         return super(XOSDashboardView, self).can_delete(obj)
 
diff --git a/xos/tosca/resources/deploymentrole.py b/xos/tosca/resources/deploymentrole.py
new file mode 100644
index 0000000..4339026
--- /dev/null
+++ b/xos/tosca/resources/deploymentrole.py
@@ -0,0 +1,29 @@
+# note: this module named xossite.py instead of site.py due to conflict with
+#    /usr/lib/python2.7/site.py
+
+import os
+import pdb
+import sys
+import tempfile
+sys.path.append("/opt/tosca")
+from translator.toscalib.tosca_template import ToscaTemplate
+
+from core.models import User, Deployment, DeploymentRole
+
+from xosresource import XOSResource
+
+class XOSDeploymentRole(XOSResource):
+    provides = "tosca.nodes.DeploymentRole"
+    xos_model = DeploymentRole
+    name_field = "role"
+
+    def get_xos_args(self):
+        args = super(XOSDeploymentRole, self).get_xos_args()
+
+        return args
+
+    def delete(self, obj):
+        super(XOSDeploymentRole, self).delete(obj)
+
+
+
diff --git a/xos/tosca/resources/node.py b/xos/tosca/resources/node.py
index 99e756f..128aaed 100644
--- a/xos/tosca/resources/node.py
+++ b/xos/tosca/resources/node.py
@@ -14,7 +14,7 @@
     xos_model = Node
 
     def get_xos_args(self):
-        args = {"name": self.nodetemplate.name}
+        args = {"name": self.obj_name}
 
         site = None
         siteName = self.get_requirement("tosca.relationships.MemberOfSite", throw_exception=False)
@@ -44,9 +44,6 @@
             obj.save()
 
     def create(self):
-        nodetemplate = self.nodetemplate
-        sliceName = nodetemplate.name
-
         xos_args = self.get_xos_args()
 
         if not xos_args.get("site", None):
diff --git a/xos/tosca/resources/onosapp.py b/xos/tosca/resources/onosapp.py
index 72511b3..dccc8db 100644
--- a/xos/tosca/resources/onosapp.py
+++ b/xos/tosca/resources/onosapp.py
@@ -33,7 +33,7 @@
 
     def get_existing_objs(self):
         objs = ONOSApp.get_tenant_objects().all()
-        objs = [x for x in objs if x.name == self.nodetemplate.name]
+        objs = [x for x in objs if x.name == self.obj_name]
         return objs
 
     def set_tenant_attr(self, obj, prop_name, value):
diff --git a/xos/tosca/resources/originserver.py b/xos/tosca/resources/originserver.py
index 196ce2e..46cf87e 100644
--- a/xos/tosca/resources/originserver.py
+++ b/xos/tosca/resources/originserver.py
@@ -15,18 +15,18 @@
     name_field = "url"
     copyin_props = []
 
-    def nodetemplate_name_to_url(self):
-        url = self.nodetemplate.name
+    def obj_name_to_url(self):
+        url = self.obj_name
         if url.startswith("http_"):
             url = url[5:]
         return url
 
     def get_existing_objs(self):
-        url = self.nodetemplate_name_to_url()
+        url = self.obj_name_to_url()
         return self.xos_model.objects.filter(**{self.name_field: url})
 
     def get_xos_args(self):
-        url = self.nodetemplate_name_to_url()
+        url = self.obj_name_to_url()
         cp_name = self.get_requirement("tosca.relationships.MemberOfContentProvider", throw_exception=True)
         cp = self.get_xos_object(ContentProvider, name=cp_name)
         return {"url": url,
diff --git a/xos/tosca/resources/serviceprovider.py b/xos/tosca/resources/serviceprovider.py
index 8faec6c..2c9a167 100644
--- a/xos/tosca/resources/serviceprovider.py
+++ b/xos/tosca/resources/serviceprovider.py
@@ -17,7 +17,7 @@
     def get_xos_args(self):
         hpc_service_name = self.get_requirement("tosca.relationships.MemberOfService", throw_exception=True)
         hpc_service = self.get_xos_object(HpcService, name=hpc_service_name)
-        return {"name": self.nodetemplate.name,
+        return {"name": self.obj_name,
                 "hpcService": hpc_service}
 
     def can_delete(self, obj):
diff --git a/xos/tosca/resources/siterole.py b/xos/tosca/resources/siterole.py
new file mode 100644
index 0000000..abb1f0d
--- /dev/null
+++ b/xos/tosca/resources/siterole.py
@@ -0,0 +1,29 @@
+# note: this module named xossite.py instead of site.py due to conflict with
+#    /usr/lib/python2.7/site.py
+
+import os
+import pdb
+import sys
+import tempfile
+sys.path.append("/opt/tosca")
+from translator.toscalib.tosca_template import ToscaTemplate
+
+from core.models import User, Deployment, SiteRole
+
+from xosresource import XOSResource
+
+class XOSSiteRole(XOSResource):
+    provides = "tosca.nodes.SiteRole"
+    xos_model = SiteRole
+    name_field = "role"
+
+    def get_xos_args(self):
+        args = super(XOSSiteRole, self).get_xos_args()
+
+        return args
+
+    def delete(self, obj):
+        super(XOSSiteRole, self).delete(obj)
+
+
+
diff --git a/xos/tosca/resources/slice.py b/xos/tosca/resources/slice.py
index 22978a2..0add5ac 100644
--- a/xos/tosca/resources/slice.py
+++ b/xos/tosca/resources/slice.py
@@ -50,19 +50,6 @@
                     ("tosca.relationships.PIPrivilege", "pi"), ("tosca.relationships.TechPrivilege", "tech") )
         self.postprocess_privileges(SliceRole, SlicePrivilege, rolemap, obj, "slice")
 
-    def create(self):
-        nodetemplate = self.nodetemplate
-        sliceName = nodetemplate.name
-
-        xos_args = self.get_xos_args()
-        slice = Slice(**xos_args)
-        slice.caller = self.user
-        slice.save()
-
-        self.postprocess(slice)
-
-        self.info("Created Slice '%s' on Site '%s'" % (str(slice), str(slice.site)))
-
     def delete(self, obj):
         if obj.instances.exists():
             self.info("Slice %s has active instances; skipping delete" % obj.name)
diff --git a/xos/tosca/resources/slicerole.py b/xos/tosca/resources/slicerole.py
new file mode 100644
index 0000000..fc7d3f1
--- /dev/null
+++ b/xos/tosca/resources/slicerole.py
@@ -0,0 +1,29 @@
+# note: this module named xossite.py instead of site.py due to conflict with
+#    /usr/lib/python2.7/site.py
+
+import os
+import pdb
+import sys
+import tempfile
+sys.path.append("/opt/tosca")
+from translator.toscalib.tosca_template import ToscaTemplate
+
+from core.models import User, Deployment, SliceRole
+
+from xosresource import XOSResource
+
+class XOSSliceRole(XOSResource):
+    provides = "tosca.nodes.SliceRole"
+    xos_model = SliceRole
+    name_field = "role"
+
+    def get_xos_args(self):
+        args = super(XOSSliceRole, self).get_xos_args()
+
+        return args
+
+    def delete(self, obj):
+        super(XOSSliceRole, self).delete(obj)
+
+
+
diff --git a/xos/tosca/resources/tag.py b/xos/tosca/resources/tag.py
new file mode 100644
index 0000000..001cba8
--- /dev/null
+++ b/xos/tosca/resources/tag.py
@@ -0,0 +1,57 @@
+import importlib
+import os
+import sys
+import tempfile
+sys.path.append("/opt/tosca")
+from translator.toscalib.tosca_template import ToscaTemplate
+from django.contrib.contenttypes.models import ContentType
+
+from core.models import Tag, Service
+
+from xosresource import XOSResource
+
+class XOSTag(XOSResource):
+    provides = "tosca.nodes.Tag"
+    xos_model = Tag
+    name_field = None
+    copyin_props = ("name", "value")
+
+    def get_xos_args(self, throw_exception=True):
+        args = super(XOSTag, self).get_xos_args()
+
+        # Find the Tosca object that this Tag is pointing to, and return its
+        # content_type and object_id, which will be used in the GenericForeignKey
+        # django relation.
+
+        target_name = self.get_requirement("tosca.relationships.TagsObject", throw_exception=throw_exception)
+        if target_name:
+            target_model = self.engine.name_to_xos_model(self.user, target_name)
+            args["content_type"] = ContentType.objects.get_for_model(target_model)
+            args["object_id"] = target_model.id
+
+        service_name = self.get_requirement("tosca.relationships.MemberOfService", throw_exception=throw_exception)
+        if service_name:
+            args["service"] = self.get_xos_object(Service, name=service_name)
+
+        # To uniquely identify a Tag, we must know the object that it is attached
+        # to as well as the name of the Tag.
+
+        if ("content_type" not in args) or ("object_id" not in args) or ("name" not in args):
+           if throw_exception:
+               raise Exception("Tag must specify TagsObject requirement and Name property")
+
+        return args
+
+    def get_existing_objs(self):
+        args = self.get_xos_args(throw_exception=True)
+
+        return Tag.objects.filter(content_type=args["content_type"],
+                                  object_id=args["object_id"],
+                                  name=args["name"])
+
+    def postprocess(self, obj):
+        pass
+
+    def can_delete(self, obj):
+        return super(XOSTag, self).can_delete(obj)
+
diff --git a/xos/tosca/resources/tenantrole.py b/xos/tosca/resources/tenantrole.py
new file mode 100644
index 0000000..316a5a3
--- /dev/null
+++ b/xos/tosca/resources/tenantrole.py
@@ -0,0 +1,29 @@
+# note: this module named xossite.py instead of site.py due to conflict with
+#    /usr/lib/python2.7/site.py
+
+import os
+import pdb
+import sys
+import tempfile
+sys.path.append("/opt/tosca")
+from translator.toscalib.tosca_template import ToscaTemplate
+
+from core.models import User, Deployment, TenantRole
+
+from xosresource import XOSResource
+
+class XOSTenantRole(XOSResource):
+    provides = "tosca.nodes.TenantRole"
+    xos_model = TenantRole
+    name_field = "role"
+
+    def get_xos_args(self):
+        args = super(XOSTenantRole, self).get_xos_args()
+
+        return args
+
+    def delete(self, obj):
+        super(XOSTenantRole, self).delete(obj)
+
+
+
diff --git a/xos/tosca/resources/user.py b/xos/tosca/resources/user.py
index 8587c89..55c0423 100644
--- a/xos/tosca/resources/user.py
+++ b/xos/tosca/resources/user.py
@@ -25,7 +25,7 @@
         return args
 
     def get_existing_objs(self):
-        return self.xos_model.objects.filter(email = self.nodetemplate.name)
+        return self.xos_model.objects.filter(email = self.obj_name)
 
     def postprocess(self, obj):
         rolemap = ( ("tosca.relationships.AdminPrivilege", "admin"), ("tosca.relationships.AccessPrivilege", "access"),
@@ -62,12 +62,12 @@
                         udv.save()
 
     def create(self):
-        nodetemplate = self.nodetemplate
-
         xos_args = self.get_xos_args()
 
         if not xos_args.get("site",None):
              raise Exception("Site name must be specified when creating user")
+        if ("firstname" not in xos_args) or ("lastname" not in xos_args):
+             raise Exception("firstname and lastname must be specified when creating user")
 
         user = User(**xos_args)
         user.save()
diff --git a/xos/tosca/resources/vtnservice.py b/xos/tosca/resources/vtnservice.py
index f0940d6..2a5738f 100644
--- a/xos/tosca/resources/vtnservice.py
+++ b/xos/tosca/resources/vtnservice.py
@@ -12,5 +12,4 @@
 class XOSVTNService(XOSService):
     provides = "tosca.nodes.VTNService"
     xos_model = VTNService
-    copyin_props = ["view_url", "icon_url", "enabled", "published", "public_key", "versionNumber", 'privateGatewayMac', 'localManagementIp', 'ovsdbPort', 'sshPort', 'sshUser', 'sshKeyFile', 'mgmtSubnetBits']
-
+    copyin_props = ["view_url", "icon_url", "enabled", "published", "public_key", "versionNumber", 'privateGatewayMac', 'localManagementIp', 'ovsdbPort', 'sshPort', 'sshUser', 'sshKeyFile', 'mgmtSubnetBits', 'xosEndpoint', 'xosUser', 'xosPassword']
diff --git a/xos/tosca/resources/xosresource.py b/xos/tosca/resources/xosresource.py
index 7a6c194..e70cfa9 100644
--- a/xos/tosca/resources/xosresource.py
+++ b/xos/tosca/resources/xosresource.py
@@ -19,6 +19,17 @@
         self.nodetemplate = nodetemplate
         self.engine = engine
 
+    @property
+    def full_name(self):
+        return self.nodetemplate.name
+
+    @property
+    def obj_name(self):
+        if "#" in self.nodetemplate.name:
+            return self.nodetemplate.name.split("#",1)[1]
+        else:
+            return self.nodetemplate.name
+
     def get_all_required_node_names(self):
         results = []
         for reqs in self.nodetemplate.requirements:
@@ -38,7 +49,7 @@
                     results.append(v["node"])
 
         if (not results) and throw_exception:
-            raise Exception("Failed to find requirement in %s using relationship %s" % (self.nodetemplate.name, relationship_name))
+            raise Exception("Failed to find requirement in %s using relationship %s" % (self.full_name, relationship_name))
 
         return results
 
@@ -75,7 +86,7 @@
         return objs[0]
 
     def get_existing_objs(self):
-        return self.xos_model.objects.filter(**{self.name_field: self.nodetemplate.name})
+        return self.xos_model.objects.filter(**{self.name_field: self.obj_name})
 
     def get_model_class_name(self):
         return self.xos_model.__name__
@@ -84,19 +95,19 @@
         existing_objs = self.get_existing_objs()
         if existing_objs:
             if self.get_property_default("no-update", False):
-                self.info("%s %s already exists. Skipping update due to 'no-update' property" % (self.get_model_class_name(), self.nodetemplate.name))
+                self.info("%s:%s (%s) already exists. Skipping update due to 'no-update' property" % (self.get_model_class_name(), self.obj_name, self.full_name))
             else:
-                self.info("%s %s already exists" % (self.get_model_class_name(), self.nodetemplate.name))
+                self.info("%s:%s (%s) already exists" % (self.get_model_class_name(), self.obj_name, self.full_name))
                 self.update(existing_objs[0])
         else:
             if self.get_property_default("no-create", False):
-                self.info("%s %s does not exist, but 'no-create' is specified" % (self.get_model_class_name(), self.nodetemplate.name))
+                self.info("%s:%s (%s) does not exist, but 'no-create' is specified" % (self.get_model_class_name(), self.obj_name, self.full_name))
             else:
                 self.create()
 
     def can_delete(self, obj):
         if self.get_property_default("no-delete",False):
-            self.info("%s %s is marked 'no-delete'. Skipping delete." % (self.get_model_class_name(), self.nodetemplate.name))
+            self.info("%s:%s %s is marked 'no-delete'. Skipping delete." % (self.get_model_class_name(), self.obj_name, self.full_name))
             return False
         return True
 
@@ -170,7 +181,7 @@
         args = {}
 
         if self.name_field:
-            args[self.name_field] = self.nodetemplate.name
+            args[self.name_field] = self.obj_name
 
         # copy simple string properties from the template into the arguments
         for prop in self.copyin_props:
diff --git a/xos/tosca/resources/xossite.py b/xos/tosca/resources/xossite.py
index 616e397..9b03bc5 100644
--- a/xos/tosca/resources/xossite.py
+++ b/xos/tosca/resources/xossite.py
@@ -19,9 +19,9 @@
     def get_xos_args(self):
         display_name = self.get_property("display_name")
         if not display_name:
-            display_name = self.nodetemplate.name
+            display_name = self.obj_name
 
-        args = {"login_base": self.nodetemplate.name,
+        args = {"login_base": self.obj_name,
                 "name": display_name}
 
         # copy simple string properties from the template into the arguments
@@ -33,7 +33,7 @@
         return args
 
     def get_existing_objs(self):
-        return self.xos_model.objects.filter(login_base = self.nodetemplate.name)
+        return self.xos_model.objects.filter(login_base = self.obj_name)
 
     def postprocess(self, obj):
         results = []
@@ -68,20 +68,6 @@
                         sitedep.save()
                         self.info("Created SiteDeployment from %s to %s" % (str(obj), str(deployment)))
 
-    def create(self):
-        nodetemplate = self.nodetemplate
-        siteName = nodetemplate.name
-
-        xos_args = self.get_xos_args()
-
-        site = Site(**xos_args)
-        site.caller = self.user
-        site.save()
-
-        self.postprocess(site)
-
-        self.info("Created Site '%s'" % (str(site), ))
-
     def delete(self, obj):
         if obj.slices.exists():
             self.info("Site %s has active slices; skipping delete" % obj.name)
diff --git a/xos/tosca/samples/slicetag.yaml b/xos/tosca/samples/slicetag.yaml
new file mode 100644
index 0000000..ec064e3
--- /dev/null
+++ b/xos/tosca/samples/slicetag.yaml
@@ -0,0 +1,35 @@
+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:
+    mysite_vsg:
+      type: tosca.nodes.Slice
+      properties:
+          no-create: True
+          no-delete: True
+          no-update: True
+
+    service_vsg:
+      type: tosca.nodes.Service
+      properties:
+          no-create: True
+          no-delete: True
+          no-update: True
+
+    mysite_vsg_foobar_tag:
+      type: tosca.nodes.Tag
+      properties:
+          name: foobar
+          value: xyz
+      requirements:
+          - target:
+              node: mysite_vsg
+              relationship: tosca.relationships.TagsObject
+          - service:
+              node: service_vsg
+              relationship: tosca.relationships.MemberOfService