Merged XOS master
diff --git a/Dockerfile b/Dockerfile
index 5d945a9..b69b7fd 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,4 @@
-FROM       ubuntu:14.04.2
+FROM       ubuntu:14.04.3
 MAINTAINER Andy Bavier <acb@cs.princeton.edu>
 
 # XXX Workaround for docker bug:
diff --git a/containers/observer/Dockerfile b/containers/observer/Dockerfile
new file mode 100644
index 0000000..7ec6592
--- /dev/null
+++ b/containers/observer/Dockerfile
@@ -0,0 +1,44 @@
+FROM       xos
+
+# Install custom Ansible
+RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y \
+    openssh-client \
+    python-crypto \
+    python-jinja2 \
+    python-paramiko \
+    python-yaml \
+    python-httplib2 \
+    supervisor
+
+RUN \
+    git clone -b release1.8.2 git://github.com/ansible/ansible.git /opt/ansible && \
+    git clone -b release1.8.2 git://github.com/ansible/ansible-modules-extras.git /opt/ansible/lib/ansible/modules/extras && \
+    git clone -b release1.8.2 git://github.com/ansible/ansible-modules-extras.git /opt/ansible/v2/ansible/modules/extras && \
+    git clone git://github.com/sb98052/ansible-modules-core.git /opt/ansible/lib/ansible/modules/core && \
+    git clone git://github.com/sb98052/ansible-modules-core.git /opt/ansible/v2/ansible/modules/core && \
+    # git clone uses cached copy, doesn't pick up latest
+    git -C /opt/ansible pull && \
+    git -C /opt/ansible/lib/ansible/modules/core pull && \
+    git -C /opt/ansible/v2/ansible/modules/core pull
+
+
+# For Observer
+RUN mkdir -p /usr/local/share /bin /etc/ansible
+
+RUN cp /tmp/xos/containers/observer/conf/ansible-hosts /etc/ansible/hosts
+
+ADD http://phantomjs.googlecode.com/files/phantomjs-1.7.0-linux-x86_64.tar.bz2 /usr/local/share/
+
+RUN git clone git://git.planet-lab.org/fofum.git /tmp/fofum && \
+    cd /tmp/fofum; python setup.py install && \
+    rm -rf /tmp/fofum && \
+    tar jxvf /usr/local/share/phantomjs-1.7.0-linux-x86_64.tar.bz2 -C /usr/local/share/ && \
+    rm -f /usr/local/share/phantomjs-1.7.0-linux-x86_64.tar.bz2 && \
+    ln -s /usr/local/share/phantomjs-1.7.0-linux-x86_64 /usr/local/share/phantomjs && \
+    ln -s /usr/local/share/phantomjs/bin/phantomjs /bin/phantomjs
+
+
+# Supervisor
+RUN cp /tmp/xos/containers/observer/conf/observer.conf /etc/supervisor/conf.d/
+
+CMD /usr/bin/supervisord -c /etc/supervisor/conf.d/observer.conf
diff --git a/containers/observer/Makefile b/containers/observer/Makefile
new file mode 100644
index 0000000..e7fedf5
--- /dev/null
+++ b/containers/observer/Makefile
@@ -0,0 +1,13 @@
+CONTAINER_NAME:=observer-server
+
+.PHONY: build
+build: ; docker build --rm -t observer .
+
+.PHONY: run
+run: ; docker run -d --name ${CONTAINER_NAME} observer
+
+.PHONY: stop
+stop: ; docker stop ${CONTAINER_NAME}
+
+.PHONY: rm
+rm: ; docker rm ${CONTAINER_NAME}
diff --git a/xos/configurations/opencloud/ansible-hosts b/containers/observer/conf/ansible-hosts
similarity index 100%
rename from xos/configurations/opencloud/ansible-hosts
rename to containers/observer/conf/ansible-hosts
diff --git a/containers/observer/conf/observer.conf b/containers/observer/conf/observer.conf
new file mode 100644
index 0000000..48f61dd
--- /dev/null
+++ b/containers/observer/conf/observer.conf
@@ -0,0 +1,9 @@
+[supervisord]
+logfile=/var/log/supervisord.log ; (main log file;default $CWD/supervisord.log)
+pidfile=/var/run/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
+nodaemon=true
+
+[program:observer]
+command=python /opt/xos/xos-observer.py
+stderr_logfile=/var/log/supervisor/observer.err.log
+stdout_logfile=/var/log/supervisor/observer.out.log
diff --git a/containers/postgresql/Dockerfile b/containers/postgresql/Dockerfile
new file mode 100644
index 0000000..4d4ebfd
--- /dev/null
+++ b/containers/postgresql/Dockerfile
@@ -0,0 +1,35 @@
+FROM ubuntu
+
+RUN apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys B97B0AFCAA1A47F044F244A07FCC7D46ACCC4CF8
+
+RUN echo "deb http://apt.postgresql.org/pub/repos/apt/ precise-pgdg main" > /etc/apt/sources.list.d/pgdg.list
+
+RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y --force-yes\
+    python-software-properties \
+    software-properties-common \
+    postgresql-9.3 \
+    postgresql-client-9.3 \
+    postgresql-contrib-9.3
+
+# Workaround for AUFS issue
+# https://github.com/docker/docker/issues/783#issuecomment-56013588
+RUN mkdir /etc/ssl/private-copy; mv /etc/ssl/private/* /etc/ssl/private-copy/; rm -r /etc/ssl/private; mv /etc/ssl/private-copy /etc/ssl/private; chmod -R 0700 /etc/ssl/private; chown -R postgres /etc/ssl/private
+
+USER postgres
+
+RUN /etc/init.d/postgresql start && \
+    psql --command "ALTER USER postgres WITH SUPERUSER PASSWORD 'password' " && \
+    psql --command "CREATE DATABASE xos"
+
+# Allow remote connections. 
+RUN echo "host all  all    0.0.0.0/0  md5" >> /etc/postgresql/9.3/main/pg_hba.conf
+RUN echo "host all  all    0.0.0.0/0  password" >> /etc/postgresql/9.3/main/pg_hba.conf
+
+RUN echo "listen_addresses='*'" >> /etc/postgresql/9.3/main/postgresql.conf
+
+# Expose the PostgreSQL port
+EXPOSE 5432
+
+VOLUME  ["/etc/postgresql", "/var/log/postgresql", "/var/lib/postgresql"]
+
+CMD ["/usr/lib/postgresql/9.3/bin/postgres", "-D", "/var/lib/postgresql/9.3/main", "-c", "config_file=/etc/postgresql/9.3/main/postgresql.conf"]
diff --git a/containers/postgresql/Makefile b/containers/postgresql/Makefile
new file mode 100644
index 0000000..327f661
--- /dev/null
+++ b/containers/postgresql/Makefile
@@ -0,0 +1,21 @@
+.PHONY: build
+build: ; docker build --rm -t postgres .
+
+.PHONY: run
+run: ; docker run -d -p 5432:5432 --name postgres-server postgres
+
+.PHONY: stop
+stop: ; docker stop postgres-server
+
+.PHONY: rm
+rm: ; docker rm postgres-server
+
+.PHONE: rmi
+rmi: ; docker rmi postgres
+
+.PHONY: backup
+backupvol: ; docker run --volumes-from postgres-server -v /backup:/backup postgres tar cvf /backup/backup-postgres.tar /var/lib/postgresql
+
+.PHONY: restore
+restorevol: ; docker run --volumes-from postgres-server -v /backup:/backup postgres cd /var/lib/postgresql && tar xvf /backup/backup-postgres.tar
+
diff --git a/containers/xos/Dockerfile b/containers/xos/Dockerfile
new file mode 100644
index 0000000..37bd55b
--- /dev/null
+++ b/containers/xos/Dockerfile
@@ -0,0 +1,88 @@
+FROM       ubuntu:14.04.3
+
+# XXX Workaround for docker bug:
+# https://github.com/docker/docker/issues/6345
+# Kernel 3.15 breaks docker, uss the line below as a workaround
+# until there is a fix
+RUN ln -s -f /bin/true /usr/bin/chfn
+# XXX End workaround
+
+# Install.
+RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y \
+    curl \
+    gcc \
+    geoip-database \
+    git \
+    graphviz \
+    graphviz-dev \
+    libgeoip1 \
+    libxslt1.1 \
+    libxslt1-dev \
+    libyaml-dev \
+    m4 \
+    pkg-config \
+    python-dev \
+    python-httplib2 \
+    python-pip \
+    python-psycopg2 \
+    python-pycurl \
+    python-setuptools \
+    tar \
+    wget \
+##### observer dependencies  
+    python-keystoneclient \
+    python-novaclient \
+    python-neutronclient \
+    python-glanceclient \
+    python-ceilometerclient
+
+RUN pip install -U \
+    django==1.7 \
+    django-bitfield \
+    django-crispy-forms \
+    django-encrypted-fields \
+    django_evolution \
+    django-extensions \
+    django-filter \
+    django-geoposition \
+    django-ipware \
+    django_rest_swagger \
+    django-suit \
+    django-timezones \
+    djangorestframework==2.4.4 \
+    dnslib \
+    google_api_python_client \
+    httplib2 \
+    httplib2.ca_certs_locater \
+    lxml \  
+    markdown \
+    netaddr \
+    python-dateutil \
+    python_gflags \
+    python-keyczar \
+    pygraphviz \
+    pytz \
+    pyyaml \
+    requests
+
+ADD http://code.jquery.com/jquery-1.9.1.min.js /usr/local/lib/python2.7/dist-packages/suit/static/suit/js/
+
+# Install XOS
+RUN git clone git://github.com/open-cloud/xos.git /tmp/xos && \
+    mv /tmp/xos/xos /opt/ && \
+    chmod +x /opt/xos/scripts/opencloud && \
+    /opt/xos/scripts/opencloud genkeys
+
+# install Tosca engine
+RUN bash /opt/xos/tosca/install_tosca.sh
+
+EXPOSE 8000
+
+# Set environment variables.
+ENV HOME /root
+
+# Define working directory.
+WORKDIR /root
+
+# Define default command.
+CMD python /opt/xos/manage.py runserver 0.0.0.0:8000 --insecure
diff --git a/containers/xos/Makefile b/containers/xos/Makefile
new file mode 100644
index 0000000..c71873e
--- /dev/null
+++ b/containers/xos/Makefile
@@ -0,0 +1,17 @@
+CONTAINER_NAME:=xos-server
+TOSCA_CONFIG_PATH:=/opt/xos/configurations/opencloud/opencloud.yaml
+
+.PHONY: build
+build: ; docker build --rm -t xos . && ./initdb
+
+.PHONY: run
+run: ; docker run -d --name ${CONTAINER_NAME} -p 80:8000 xos
+
+.PHONY: runtosca
+runtosca: ; docker exec -it ${CONTAINER_NAME} /usr/bin/python /opt/xos/tosca/run.py padmin@vicci.org ${TOSCA_CONFIG_PATH}
+
+.PHONY: stop
+stop: ; docker stop ${CONTAINER_NAME}
+
+.PHONY: rm
+rm: ; docker rm ${CONTAINER_NAME}
diff --git a/containers/xos/initdb b/containers/xos/initdb
new file mode 100755
index 0000000..bd020c5
--- /dev/null
+++ b/containers/xos/initdb
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+IMAGE_NAME=xos
+DB_HOST=$(wget http://ipinfo.io/ip -qO -)
+
+# configure db host
+docker run -it $IMAGE_NAME sed -i '0,/host/{s/host=localhost/host='$DB_HOST'/}' /opt/xos/xos_config
+CONTAINER_ID=$(docker ps -a | grep $IMAGE_NAME | head -1 |  awk '{print $1}')
+echo $CONTAINER_ID $IMAGE_NAME
+docker commit $CONTAINER_ID $IMAGE_NAME
+
+# init db schema
+docker run -it $IMAGE_NAME /opt/xos/scripts/opencloud makemigrations
+CONTAINER_ID=$(docker ps -a | grep $IMAGE_NAME | head -1 | awk '{print $1}')
+# run overrides the CMD specifed in the Dockerfile, so we re-set the CMD in the final commit"
+docker commit --change "CMD python /opt/xos/manage.py runserver 0.0.0.0:8000 --insecure" $CONTAINER_ID $IMAGE_NAME
diff --git a/docker-cp.sh b/docker-cp.sh
index 280a8d9..bec511d 100755
--- a/docker-cp.sh
+++ b/docker-cp.sh
@@ -5,4 +5,5 @@
 
 XOS=$( docker ps|grep "xos"|awk '{print $NF}' )
 FOLDER=`docker inspect -f   '{{.Id}}' $XOS`
-cp $1 /var/lib/docker/aufs/mnt/$FOLDER/$2
\ No newline at end of file
+#cp $1 /var/lib/docker/aufs/mnt/$FOLDER/$2
+docker cp $1 $XOS:$2
diff --git a/xos/apigen/hpc-api.template.py b/xos/apigen/hpc-api.template.py
index 291403a..301346b 100644
--- a/xos/apigen/hpc-api.template.py
+++ b/xos/apigen/hpc-api.template.py
@@ -37,7 +37,7 @@
 def get_hpc_REST_patterns():
     return patterns('',
         url(r'^hpcapi/$', hpc_api_root),
-    {% for object in generator.all %}
+    {% for object in generator.rest_models %}
         url(r'hpcapi/{{ object.rest_name }}/$', {{ object.camel }}List.as_view(), name='{{ object.singular }}-list'),
         url(r'hpcapi/{{ object.rest_name }}/(?P<pk>[a-zA-Z0-9\-]+)/$', {{ object.camel }}Detail.as_view(), name ='{{ object.singular }}-detail'),
     {% endfor %}
@@ -46,7 +46,7 @@
 @api_view(['GET'])
 def hpc_api_root(request, format=None):
     return Response({
-        {% for object in generator.all %}'{{ object.plural }}': reverse('{{ object }}-list', request=request, format=format),
+        {% for object in generator.rest_models %}'{{ object.plural }}': reverse('{{ object }}-list', request=request, format=format),
         {% endfor %}
     })
 
@@ -104,7 +104,7 @@
                    newModel = through(**{local_fieldName: obj, remote_fieldName: item})
                    newModel.save()
 
-{% for object in generator.all %}
+{% for object in generator.rest_models %}
 
 class {{ object.camel }}Serializer(serializers.HyperlinkedModelSerializer):
     id = IdField()
@@ -154,14 +154,14 @@
 {% endfor %}
 
 serializerLookUp = {
-{% for object in generator.all %}
+{% for object in generator.rest_models %}
                  {{ object.camel }}: {{ object.camel }}Serializer,
 {% endfor %}
                  None: None,
                 }
 
 # Based on core/views/*.py
-{% for object in generator.all %}
+{% for object in generator.rest_models %}
 
 class {{ object.camel }}List(XOSListCreateAPIView):
     queryset = {{ object.camel }}.objects.select_related().all()
diff --git a/xos/apigen/list.txt b/xos/apigen/list.txt
new file mode 100644
index 0000000..3e115e3
--- /dev/null
+++ b/xos/apigen/list.txt
@@ -0,0 +1,3 @@
+{% for o in generator.all %}
+{{ o.camel }}
+{% endfor %}
diff --git a/xos/apigen/modelgen b/xos/apigen/modelgen
index 7f740d1..63cf5b7 100644
--- a/xos/apigen/modelgen
+++ b/xos/apigen/modelgen
@@ -7,8 +7,7 @@
 import json
 import re
 from django.template import Context, Template
-
-blacklist = ['SingletonModel','PlCoreBase']
+from optparse import OptionParser
 
 # Django set up
 
@@ -16,6 +15,8 @@
 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "xos.settings")
 from django.db.models.fields.related import ForeignKey, ManyToManyField
 
+options = None
+
 def singular(foo, keys):
 	for k in keys:
 		if (foo==k+'es'):
@@ -40,7 +41,7 @@
 
             for classname in dir(models_module):
                     c = getattr(models_module, classname, None)
-                    if type(c)==type(PlCoreBase) and c.__name__ not in blacklist:
+                    if type(c)==type(PlCoreBase) and c.__name__ not in options.blacklist:
                             model_classes.append(c)
 
     return model_classes
@@ -90,6 +91,10 @@
 class Generator(dict):
 	def all(self):
 		return self.values()
+
+        def rest_models(self):
+                norest = [x.lower() for x in options.norest]
+                return [v for v in self.values() if not (str(v) in norest)]
 	
 	def regex(self, r):
 		filtered = filter(lambda o:re.match(r,str(o)), self.values())
@@ -122,6 +127,10 @@
 						cobj.multi = True
 						cobj.plural_name = related_name
 						refobj.refs.append(cobj)
+                                elif f.name.endswith("_ptr"):
+                                        # django inherited model, for example HPCService
+                                        # cause swagger and REST to break
+                                        pass
 				else:
 					obj.props.append(f.name)
 
@@ -144,9 +153,9 @@
                                 if (related_name.endswith("+")):
                                     continue
 
-				if (related_name!='+' and related_name.lower()!=str(obj).lower()):
-                                        #print "XXX2", obj, f, related_name, related_model_name, refobj.plural_name
+				if (related_name!='+') and related_model_name in self: # and related_name.lower()!=str(obj).lower()):
                                         refobj = self[related_model_name]
+                                        #print "XXX2", obj, f, related_name, related_model_name, refobj.plural_name
 					cobj = copy.deepcopy(refobj)
 					cobj.multi = True
 
@@ -154,22 +163,32 @@
 
 
 
-			
+
 def main():
-        if len(sys.argv)==3:
-            apps = [x.strip() for x in sys.argv[1].split(",")]
-            output = sys.argv[2]
-        elif len(sys.argv)==2:
-            apps = ["core"]
-            output = sys.argv[1]
-        else:
-	    print 'Usage: modelgen <output_template>'
-            print 'Alternative Usage: modelgen <app> <output_template>'
-	    exit(1)
+        global options
+        parser = OptionParser(usage="modelgen [options] <template_fn>", )
+
+        parser.add_option("-a", "--app", dest="apps",
+             help="list of applications to parse", metavar="APP", default=[], action="append")
+        parser.add_option("-b", "--blacklist", dest="blacklist",
+             help="add model name to blacklist", metavar="MODEL", default=["SingletonModel", "PlCoreBase"], action="append")
+        parser.add_option("-n", "--no-rest", dest="norest",
+             help="do not generate rest api for model", metavar="MODEL", default=["SingletonModel", "PlCoreBase"], action="append")
+
+        (options, args) = parser.parse_args(sys.argv[1:])
+
+        if not options.apps:
+            options.apps = ["core"]
+
+        if len(args)!=1:
+            print 'Usage: modelgen [options] <template_fn>'
+            exit(1)
+
+        output = args[0]
 
 	generator = Generator()
 
-	models = enum_classes(apps)
+	models = enum_classes(options.apps)
 
 	for m in models:
 		generator.add_object(m)
diff --git a/xos/ceilometer/models.py b/xos/ceilometer/models.py
index fbfecd3..a838c4e 100644
--- a/xos/ceilometer/models.py
+++ b/xos/ceilometer/models.py
@@ -41,12 +41,18 @@
     def save(self, *args, **kwargs):
         if not self.creator:
             if not getattr(self, "caller", None):
-                # caller must be set when creating a vCPE since it creates a slice
+                # caller must be set when creating a monitoring channel since it creates a slice
                 raise XOSProgrammingError("MonitoringChannel's self.caller was not set")
             self.creator = self.caller
             if not self.creator:
                 raise XOSProgrammingError("MonitoringChannel's self.creator was not set")
 
+        if self.pk is None:
+            #Allow only one monitoring channel per user
+            channel_count = sum ( [1 for channel in MonitoringChannel.objects.filter(kind=CEILOMETER_KIND) if (channel.creator == self.creator)] )
+            if channel_count > 0:
+                raise XOSValidationError("Already %s channels exist for user Can only create max 1 MonitoringChannel instance per user" % str(channel_count))
+
         super(MonitoringChannel, self).save(*args, **kwargs)
         model_policy_monitoring_channel(self.pk)
 
diff --git a/xos/configurations/bash/Dockerfile.bash b/xos/configurations/bash/Dockerfile.bash
index 2022392..a9c224d 100644
--- a/xos/configurations/bash/Dockerfile.bash
+++ b/xos/configurations/bash/Dockerfile.bash
@@ -1,8 +1,12 @@
 RUN mkdir -p /root/setup
 ADD xos/configurations/common/admin-openrc.sh /root/setup/
+ADD xos/configurations/common/controller_settings /root/setup/
 ADD xos/configurations/common/flat_net_name /root/setup/
 ADD xos/configurations/common/cloudlab-nodes.yaml /opt/xos/configurations/commmon/
 ADD xos/configurations/common/id_rsa.pub /root/setup/padmin_public_key
+ADD xos/configurations/common/node_key.pub /root/setup/node_key.pub
+ADD xos/configurations/common/node_key /root/setup/node_key
+ADD xos/configurations/common/ceilometer_url /root/setup/ceilometer_url
 
 CMD /usr/bin/make -C /opt/xos/configurations/bash -f Makefile.inside; /bin/bash
 
diff --git a/xos/configurations/common/Makefile.cloudlab b/xos/configurations/common/Makefile.cloudlab
index 5712765..43e7497 100644
--- a/xos/configurations/common/Makefile.cloudlab
+++ b/xos/configurations/common/Makefile.cloudlab
@@ -1,10 +1,15 @@
-all: prereqs admin-openrc flat_name nodes_yaml public_key private_key
+MYFLATLANIF:=$(shell netstat -i |grep "flat"|awk '{print $$1}' )
+MYFLATLANIP:=$(shell ifconfig $(MYFLATLANIF) | grep "inet addr" | awk -F: '{print $$2}' | awk '{print $$1}' )
+
+all: prereqs admin-openrc flat_name nodes_yaml public_key private_key ceilometer_url node_key
 
 prereqs:
 	make -f Makefile.prereqs
 
 admin-openrc:
 	sudo cat /root/setup/admin-openrc.sh > admin-openrc.sh
+	sudo cat /root/setup/settings > controller_settings
+	echo 'CONTROLLER_FLAT_LAN_IP=$(MYFLATLANIP)' >> controller_settings
 
 flat_name:
 	sudo bash -c "source /root/setup/admin-openrc.sh ; neutron net-list" |grep flat|awk '{printf "%s",$$4}' > flat_net_name
@@ -12,6 +17,9 @@
 nodes_yaml:
 	bash ./make-cloudlab-nodes-yaml.sh
 
+ceilometer_url:
+	echo http://`hostname -i`/xosmetering/ > ceilometer_url
+
 public_key: ~/.ssh/id_rsa.pub
 	cp ~/.ssh/id_rsa.pub .
 
@@ -20,3 +28,7 @@
 
 ~/.ssh/id_rsa.pub:
 	cat /dev/zero | ssh-keygen -q -N ""
+
+node_key:
+	sudo cat /root/setup/id_rsa > node_key
+	sudo cat /root/setup/id_rsa.pub > node_key.pub
diff --git a/xos/configurations/common/admin-openrc.sh b/xos/configurations/common/admin-openrc.sh
deleted file mode 100644
index e69de29..0000000
--- a/xos/configurations/common/admin-openrc.sh
+++ /dev/null
diff --git a/xos/configurations/common/cloudlab.yaml b/xos/configurations/common/cloudlab.yaml
index 807d931..a0beeeb 100644
--- a/xos/configurations/common/cloudlab.yaml
+++ b/xos/configurations/common/cloudlab.yaml
@@ -42,9 +42,13 @@
           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
diff --git a/xos/configurations/cord/Dockerfile.cord b/xos/configurations/cord/Dockerfile.cord
index a21c7d0..f7fdb65 100644
--- a/xos/configurations/cord/Dockerfile.cord
+++ b/xos/configurations/cord/Dockerfile.cord
@@ -1,16 +1,24 @@
 RUN mkdir -p /root/setup
 ADD xos/configurations/common/admin-openrc.sh /root/setup/
+ADD xos/configurations/common/controller_settings /root/setup/
 ADD xos/configurations/common/flat_net_name /root/setup/
 ADD xos/configurations/common/cloudlab-nodes.yaml /opt/xos/configurations/commmon/
 ADD xos/configurations/common/id_rsa.pub /root/setup/padmin_public_key
 ADD xos/configurations/common/id_rsa.pub /opt/xos/observers/vcpe/vcpe_public_key
 ADD xos/configurations/common/id_rsa /opt/xos/observers/vcpe/vcpe_private_key
+ADD xos/configurations/common/id_rsa.pub /opt/xos/observers/monitoring_channel/monitoring_channel_public_key
+ADD xos/configurations/common/id_rsa /opt/xos/observers/monitoring_channel/monitoring_channel_private_key
 ADD xos/configurations/common/id_rsa.pub /opt/xos/observers/onos/onos_key.pub
 ADD xos/configurations/common/id_rsa /opt/xos/observers/onos/onos_key
+ADD xos/configurations/common/node_key.pub /root/setup/node_key.pub
+ADD xos/configurations/common/node_key /root/setup/node_key
+ADD xos/configurations/common/ceilometer_url /root/setup/ceilometer_url
 ADD xos/observers/vcpe/supervisor/vcpe-observer.conf /etc/supervisor/conf.d/
 ADD xos/observers/vbng/supervisor/vbng-observer.conf /etc/supervisor/conf.d/
 ADD xos/observers/onos/supervisor/onos-observer.conf /etc/supervisor/conf.d/
+ADD xos/observers/monitoring_channel/supervisor/monitoring_channel_observer.conf /etc/supervisor/conf.d/
 RUN sed -i 's/proxy_ssh=True/proxy_ssh=False/' /opt/xos/observers/vcpe/vcpe_observer_config
+RUN sed -i 's/proxy_ssh=True/proxy_ssh=False/' /opt/xos/observers/monitoring_channel/monitoring_channel_observer_config
 
 CMD /usr/bin/make -C /opt/xos/configurations/cord -f Makefile.inside; /bin/bash
 
diff --git a/xos/configurations/cord/Makefile b/xos/configurations/cord/Makefile
index 40ff5a1..4c2e423 100644
--- a/xos/configurations/cord/Makefile
+++ b/xos/configurations/cord/Makefile
@@ -2,7 +2,7 @@
 RUNNING_CONTAINER:=$(shell sudo docker ps|grep "xos"|awk '{print $$NF}')
 LAST_CONTAINER=$(shell sudo docker ps -l -q)
 
-test: common_cloudlab
+test: common_cloudlab ceilometer_dashboard
 	echo "# Autogenerated -- do not edit" > Dockerfile
 	cat ../common/Dockerfile.common Dockerfile.cord >> Dockerfile
 	cd ../../..; sudo docker build -t xos -f xos/configurations/cord/Dockerfile .
@@ -12,6 +12,12 @@
 common_cloudlab:
 	make -C ../common -f Makefile.cloudlab
 
+ceilometer_dashboard:
+	#NOTE: The below dashboard install scripts assume 
+	#clouldlab openstack environment created using "OpenStack" profile
+	bash install_xos_ceilometer_dashboard.sh
+	bash install_ceilometer_vcpe_notification_listener.sh
+
 stop:
 	sudo docker stop $(RUNNING_CONTAINER)
 
diff --git a/xos/configurations/cord/Makefile.inside b/xos/configurations/cord/Makefile.inside
index a4bb5f1..c412f25 100644
--- a/xos/configurations/cord/Makefile.inside
+++ b/xos/configurations/cord/Makefile.inside
@@ -5,6 +5,7 @@
 	python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/cloudlab.yaml
 	python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/cloudlab-nodes.yaml
 	python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/cord/cord.yaml
+	python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/cord/ceilometer.yaml
 
 run_develserver:
 	cd /opt/xos; python manage.py runserver 0.0.0.0:8000 --insecure
diff --git a/xos/configurations/cord/README.md b/xos/configurations/cord/README.md
index efabcb2..4d64953 100644
--- a/xos/configurations/cord/README.md
+++ b/xos/configurations/cord/README.md
@@ -17,11 +17,11 @@
 and Open vSwitch (OvS) switches.  At a high level the dataplane looks like this:
 
 ```
-             olt                virtualbng
-             ----                 ----
-             ONOS                 ONOS
-              |                    |
-client ----> OvS ----> vCPE ----> OvS ----> Internet
+             olt                 virtualbng
+             ----                  ----
+             ONOS                  ONOS
+              |                     |
+client ----> CPqD ----> vCPE ----> OvS ----> Internet
          1         2          3         4
 ```
 
diff --git a/xos/configurations/cord/ceilometer.yaml b/xos/configurations/cord/ceilometer.yaml
new file mode 100644
index 0000000..73c18db
--- /dev/null
+++ b/xos/configurations/cord/ceilometer.yaml
@@ -0,0 +1,99 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: Setup CORD-related services -- vOLT, vCPE, vBNG.
+
+imports:
+   - custom_types/xos.yaml
+
+node_types:
+    tosca.nodes.CeilometerTenant:
+        derived_from: tosca.nodes.Root
+        description: >
+            CORD: A Tenant of the Ceilometer Service.
+        properties:
+            kind:
+                type: string
+                default: generic
+                description: Kind of tenant
+
+topology_template:
+  node_templates:
+    service_ceilometer:
+      type: tosca.nodes.Service
+      requirements:
+      properties:
+          view_url: /admin/ceilometer/ceilometerservice/$id$/
+          kind: ceilometer
+#          public_key: { get_artifact: [ SELF, pubkey, LOCAL_FILE] }
+#      artifacts:
+#          pubkey: /opt/xos/observers/vcpe/vcpe_public_key
+
+
+    Private:
+      type: tosca.nodes.NetworkTemplate
+
+    ceilometer_network:
+      type: tosca.nodes.network.Network.XOS

+      properties:

+          ip_version: 4

+          labels: ceilometer_client_access

+      requirements:

+          - network_template:

+              node: Private

+              relationship: tosca.relationships.UsesNetworkTemplate

+          - owner:

+              node: mysite_ceilometer

+              relationship: tosca.relationships.MemberOfSlice

+          - connection:

+              node: mysite_ceilometer

+              relationship: tosca.relationships.ConnectsToSlice
+
+    mysite:
+      type: tosca.nodes.Site
+
+    mysite_ceilometer:
+      description: Ceilometer Proxy Slice
+      type: tosca.nodes.Slice
+      requirements:
+          - ceilometer_service:
+              node: service_ceilometer
+              relationship: tosca.relationships.MemberOfService
+          - site:
+              node: mysite
+              relationship: tosca.relationships.MemberOfSite
+
+    my_ceilometer_tenant:
+      description: Ceilometer Service default Tenant
+      type: tosca.nodes.CeilometerTenant
+      requirements:
+          - provider_service:
+              node: service_ceilometer
+              relationship: tosca.relationships.MemberOfService
+       
+    Ceilometer:
+      type: tosca.nodes.DashboardView
+      properties:
+          url: { get_artifact: [ SELF, ceilometer_url, LOCAL_FILE] }
+      artifacts:
+          ceilometer_url: /root/setup/ceilometer_url
+
+    Tenant:
+      type: tosca.nodes.DashboardView
+      properties:
+          no-create: true
+          no-update: true
+          no-delete: true
+
+    padmin@vicci.org:
+      type: tosca.nodes.User
+      properties:
+          firstname: XOS
+          lastname: admin
+          is_admin: true
+      requirements:
+          - tenant_dashboard:
+              node: Tenant
+              relationship: tosca.relationships.UsesDashboard
+          - ceilometer_dashboard:
+              node: Ceilometer
+              relationship: tosca.relationships.UsesDashboard
diff --git a/xos/configurations/cord/ceilometer_vcpe_notification_agent.tar.gz b/xos/configurations/cord/ceilometer_vcpe_notification_agent.tar.gz
new file mode 100644
index 0000000..dcc6765
--- /dev/null
+++ b/xos/configurations/cord/ceilometer_vcpe_notification_agent.tar.gz
Binary files differ
diff --git a/xos/configurations/cord/cord.yaml b/xos/configurations/cord/cord.yaml
index 9d850b2..e9a6291 100644
--- a/xos/configurations/cord/cord.yaml
+++ b/xos/configurations/cord/cord.yaml
@@ -40,7 +40,7 @@
 # generate a URL from its IP address
 #          vbng_url: http://10.11.10.24:8181/onos/virtualbng/
 
-    service_ONOS:
+    service_ONOS_vBNG:
       type: tosca.nodes.ONOSService
       requirements:
       properties:
@@ -50,34 +50,46 @@
       artifacts:
           pubkey: /opt/xos/observers/onos/onos_key.pub
 
+#
+# To actually bring up the vBNG app
+# - Set up the dataplane using the ansible script
+# - Log into the vBNG ONOS and run 'devices' to get switch dpID
+# - Change the dpID values in vBNG ONOS app in XOS GUI
+# - (Synchronizer should copy the files to ONOS container immediately)
+# - Log into service_ONOS_vBNG VM and restart ONOS Docker container
+#   (Should roll this step into a Synchronizer)
+#
     vBNG_ONOS_app:
       type: tosca.nodes.ONOSvBNGApp
       requirements:
           - onos_tenant:
-              node: service_ONOS
+              node: service_ONOS_vBNG
               relationship: tosca.relationships.TenantOfService
           - vbng_service:
               node: service_vbng
               relationship: tosca.relationships.UsedByService
       properties:
           dependencies: org.onosproject.proxyarp, org.onosproject.virtualbng, org.onosproject.openflow, org.onosproject.fwd
-          config_addresses.json: >
+          config_network-cfg.json: >
             {
-                "addresses" : [
-                            {
-                                "dpid" : "00:00:00:00:00:00:00:a1",
-                                "port" : "1",
-                                "ips" : [10.0.1.253/24"],
-                                "mac" : "00:00:00:00:00:99"
-
-                            },
-                            {
-                                "dpid" : "00:00:00:00:00:00:00:a5",
-                                "port" : "2",
-                                "ips" : ["10.254.0.1/24"],
-                                "mac" : "00:00:00:00:00:98"
-                            }
-                ]
+              "ports" : {
+                "of:0000000000000001/1" : {
+                  "interfaces" : [
+                    {
+                      "ips"  : [ "10.0.1.253/24" ],
+                      "mac"  : "00:00:00:00:00:99"
+                    }
+                  ]
+                },
+                "of:0000000000000001/2" : {
+                  "interfaces" : [
+                    {
+                      "ips"  : [ "10.254.0.2/24" ],
+                      "mac"  : "00:00:00:00:00:98"
+                    }
+                  ]
+                }
+              }
             }
           config_virtualbng.json: >
             {
@@ -87,9 +99,34 @@
                 "nextHopIpAddress" : "10.254.0.1",
                 "publicFacingMac" : "00:00:00:00:00:66",
                 "xosIpAddress" : "10.11.10.1",
-                "xosRestPort" : "9999"
+                "xosRestPort" : "9999",
+                "hosts" : {
+                    "cp-1.devel.xos-pg0.clemson.cloudlab.us" : "of:0000000000000001/1",
+                    "cp-2.devel.xos-pg0.clemson.cloudlab.us" : "of:0000000000000001/1"
+                }
             }
 
+    service_ONOS_vOLT:
+      type: tosca.nodes.ONOSService
+      requirements:
+      properties:
+          kind: onos
+          view_url: /admin/onos/onosservice/$id$/
+          public_key: { get_artifact: [ SELF, pubkey, LOCAL_FILE] }
+      artifacts:
+          pubkey: /opt/xos/observers/onos/onos_key.pub
+
+    vOLT_ONOS_app:
+      type: tosca.nodes.ONOSvOLTApp
+      requirements:
+          - onos_tenant:
+              node: service_ONOS_vOLT
+              relationship: tosca.relationships.TenantOfService
+          - volt_service:
+              node: service_volt
+              relationship: tosca.relationships.UsedByService
+      properties:
+          dependencies: org.onosproject.olt
 
     # Network templates
     Private:
@@ -189,12 +226,23 @@
               node: mysite
               relationship: tosca.relationships.MemberOfSite
 
-    mysite_onos:
-      description: ONOS Controller Slice
+    mysite_onos_vbng:
+      description: ONOS Controller Slice for vBNG
       type: tosca.nodes.Slice
       requirements:
           - ONOS:
-              node: service_ONOS
+              node: service_ONOS_vBNG
+              relationship: tosca.relationships.MemberOfService
+          - site:
+              node: mysite
+              relationship: tosca.relationships.MemberOfSite
+
+    mysite_onos_volt:
+      description: ONOS Controller Slice for vOLT
+      type: tosca.nodes.Slice
+      requirements:
+          - ONOS:
+              node: service_ONOS_vOLT
               relationship: tosca.relationships.MemberOfService
           - site:
               node: mysite
@@ -217,7 +265,7 @@
               relationship: tosca.relationships.MemberOfSite
 
     mysite_clients:
-      description: slice for clients at the subscriber 
+      description: slice for clients at the subscriber
       type: tosca.nodes.Slice
       requirements:
           - site:
@@ -245,7 +293,7 @@
             version: 14.10
       requirements:
           - slice:
-                node: mysite_onos
+                node: mysite_onos_vbng
                 relationship: tosca.relationships.MemberOfSlice
 
     onos_app_2:
@@ -267,7 +315,7 @@
             version: 14.10
       requirements:
           - slice:
-                node: mysite_onos
+                node: mysite_onos_volt
                 relationship: tosca.relationships.MemberOfSlice
 
     # VM for running the OVS controlled by vBNG
diff --git a/xos/configurations/cord/dataplane/ansible.cfg b/xos/configurations/cord/dataplane/ansible.cfg
new file mode 100644
index 0000000..9100590
--- /dev/null
+++ b/xos/configurations/cord/dataplane/ansible.cfg
@@ -0,0 +1,4 @@
+[defaults]
+remote_user = ubuntu
+private_key_file = ~/.ssh/id_rsa
+host_key_checking = false
\ No newline at end of file
diff --git a/xos/configurations/cord/dataplane/dataplane.yaml b/xos/configurations/cord/dataplane/dataplane.yaml
new file mode 100644
index 0000000..4799515
--- /dev/null
+++ b/xos/configurations/cord/dataplane/dataplane.yaml
@@ -0,0 +1,100 @@
+---
+- hosts: switch_vbng
+  sudo: yes
+  vars:
+    controller_ip: "{{ hostvars['onos_vbng']['ansible_ssh_host'] }}"
+    controller_port: 6653
+    ovs_dpid: "0000000000000001"
+  tags:
+  - vbng
+  tasks:
+  - name: Fix /etc/hosts
+    lineinfile:
+      dest=/etc/hosts
+      regexp="127.0.0.1 localhost"
+      line="127.0.0.1 localhost {{ ansible_hostname }}"
+
+  - name: Install packages
+    apt: name={{ item }}
+      state=latest
+      update_cache=yes
+    with_items:
+    - openvswitch-switch
+    - python-netifaces
+
+  - name: Create br-vbng
+    openvswitch_bridge:
+      bridge=br-vbng
+      state=present
+
+  - name: Find wan_network interface
+    script: scripts/if_from_ip.py {{ wan_ip }}
+    register: wan_net
+
+  - name: Find public_network interface
+    script: scripts/if_from_ip.py {{ public_ip }}
+    register: public_net
+
+  - name: Hook up wan-network to br-vbng
+    openvswitch_port:
+      bridge=br-vbng
+      port={{ wan_net.stdout }}
+      state=present
+
+  - name: Hook up public-network to OvS
+    openvswitch_port:
+      bridge=br-vbng
+      port={{ public_net.stdout }}
+      state=present
+
+  - name: Change datapath ID of bridge to match config file
+    command: /usr/bin/ovs-vsctl set bridge br-vbng other-config:datapath-id={{ ovs_dpid }}
+
+  - name: Add controller to switch
+    command: /usr/bin/ovs-vsctl set-controller br-vbng tcp:{{ controller_ip }}:{{ controller_port }}
+
+- hosts: switch_volt
+  sudo: yes
+  vars:
+    controller_ip: "{{ hostvars['onos_volt']['ansible_ssh_host'] }}"
+    controller_port: 6653
+  tags:
+  - volt
+  tasks:
+
+  - name: Fix /etc/hosts
+    lineinfile:
+      dest=/etc/hosts
+      regexp="127.0.0.1 localhost"
+      line="127.0.0.1 localhost {{ ansible_hostname }}"
+
+  - name: Install packages
+    apt: name={{ item }} state=present update_cache=yes
+    with_items:
+    - git
+    - python-netifaces
+
+  - name: Checkout the Mininet repo
+    git: repo=https://github.com/mininet/mininet.git
+      dest=/tmp/mininet
+
+  - name: Install the CPqD switch using Mininet install script
+    shell: /tmp/mininet/util/install.sh -3f
+      creates=/usr/local/bin/ofdatapath
+    ignore_errors: true
+
+  - name: Find subscriber_network interface
+    script: scripts/if_from_ip.py {{ subscriber_ip }}
+    register: subscriber_net
+
+  - name: Find lan_network interface
+    script: scripts/if_from_ip.py {{ lan_ip }}
+    register: lan_net
+
+  - name: Run the datapath
+    command: /usr/local/bin/ofdatapath -i {{ subscriber_net.stdout_lines[0] }},{{ lan_net.stdout_lines[0] }} punix:/tmp/s1 -d 000000000001 --no-slicing -D -P
+      creates=/usr/local/var/run/ofdatapath.pid
+
+  - name: Run the control program
+    command: /usr/local/bin/ofprotocol unix:/tmp/s1 tcp:{{ controller_ip }}:{{ controller_port }} --fail=closed --listen=punix:/tmp/s1.listen -D -P
+      creates=/usr/local/var/run/ofprotocol.pid
diff --git a/xos/configurations/cord/dataplane/generate.sh b/xos/configurations/cord/dataplane/generate.sh
new file mode 100755
index 0000000..360ed67
--- /dev/null
+++ b/xos/configurations/cord/dataplane/generate.sh
@@ -0,0 +1,18 @@
+#!/bin/bash
+# set -x
+
+source ~/admin-openrc.sh
+
+get_ip () {
+    LABEL=$1
+    NETWORK=$2
+    nova list --all-tenants|grep $LABEL|sed "s/^.*$NETWORK=//g"|sed 's/; .*$//g'|awk '{print $1}'
+}
+
+cat <<EOF
+onos_vbng    ansible_ssh_host=$( get_ip mysite_onos_vbng flat-lan-1-net)
+switch_vbng  ansible_ssh_host=$( get_ip mysite_vbng flat-lan-1-net) wan_ip=$( get_ip mysite_vbng wan_network) public_ip=$( get_ip mysite_vbng tun0-net )
+
+onos_volt    ansible_ssh_host=$( get_ip mysite_onos_volt flat-lan-1-net)
+switch_volt  ansible_ssh_host=$( get_ip mysite_volt flat-lan-1-net) subscriber_ip=$( get_ip mysite_volt subscriber_network) lan_ip=$( get_ip mysite_volt lan_network) vcpe_lan_ip=$( get_ip mysite_vcpe lan_network)
+EOF
diff --git a/xos/configurations/cord/dataplane/scripts/if_from_ip.py b/xos/configurations/cord/dataplane/scripts/if_from_ip.py
new file mode 100644
index 0000000..be1da48
--- /dev/null
+++ b/xos/configurations/cord/dataplane/scripts/if_from_ip.py
@@ -0,0 +1,14 @@
+#!/usr/bin/python
+
+import sys
+import netifaces
+
+def main (argv):
+    addr = argv[0]
+    for iface in netifaces.interfaces():
+        addrs = netifaces.ifaddresses(iface)
+        if 2 in addrs and addrs[2][0]['addr'] == addr:
+            print iface
+    
+if __name__ == "__main__":
+    main(sys.argv[1:])
diff --git a/xos/configurations/cord/etc_xos_metering.tar.gz b/xos/configurations/cord/etc_xos_metering.tar.gz
new file mode 100644
index 0000000..53689db
--- /dev/null
+++ b/xos/configurations/cord/etc_xos_metering.tar.gz
Binary files differ
diff --git a/xos/configurations/cord/install_ceilometer_vcpe_notification_listener.sh b/xos/configurations/cord/install_ceilometer_vcpe_notification_listener.sh
new file mode 100755
index 0000000..50a4132
--- /dev/null
+++ b/xos/configurations/cord/install_ceilometer_vcpe_notification_listener.sh
@@ -0,0 +1,16 @@
+if [ -d /usr/lib/python2.7/dist-packages/ceilometer/network/ext_services ]; then
+    echo "Seems VCPE notification listeners are already enabled in ceilometer... so exiting gracefully..."
+    exit 0
+fi
+echo "Verifying if all the required files are present"
+if [ ! -f ceilometer_vcpe_notification_agent.tar.gz ];
+then
+    echo "File ceilometer_vcpe_notification_agent.tar.gz not found"
+    exit 1
+fi
+echo "Copying the ceilometer vcpe notification agent files /usr/lib/python2.7/dist-packages/ceilometer"
+tar -xzf ceilometer_vcpe_notification_agent.tar.gz
+sudo mv ceilometer/network/ext_services /usr/lib/python2.7/dist-packages/ceilometer/network/
+sudo mv ceilometer-2015.1.1.egg-info/entry_points.txt /usr/lib/python2.7/dist-packages/ceilometer-2015.1.1.egg-info/
+echo "Restarting ceilometer-agent-notification"
+sudo service ceilometer-agent-notification restart
diff --git a/xos/configurations/cord/install_xos_ceilometer_dashboard.sh b/xos/configurations/cord/install_xos_ceilometer_dashboard.sh
new file mode 100755
index 0000000..ed72f54
--- /dev/null
+++ b/xos/configurations/cord/install_xos_ceilometer_dashboard.sh
@@ -0,0 +1,25 @@
+if [ -d /usr/share/xos-metering ]; then
+    echo "Seems xos ceilometer dashboard is already installed... so exiting gracefully..."
+    exit 0
+fi
+echo "Verifying if all the required files are present"
+if [ ! -f xos_metering_dashboard.tar.gz ];
+then
+    echo "File xos_metering_dashboard.tar.gz not found"
+    exit 1
+fi
+if [ ! -f etc_xos_metering.tar.gz ];
+then
+    echo "File etc_xos_metering.tar.gz not found"
+    exit 1
+fi
+echo "Copying the xos ceilometer dashboard files /usr/share/ and /etc/apache2/"
+tar -xzf xos_metering_dashboard.tar.gz
+sudo mv xos-metering /usr/share/
+tar -xzf etc_xos_metering.tar.gz
+sudo mv xos-metering /etc/
+sudo mv apache2/conf-available/xos-metering.conf /etc/apache2/conf-available/
+cd /etc/apache2/conf-enabled/
+sudo ln -s ../conf-available/xos-metering.conf xos-metering.conf
+echo "Restarting apache2"
+sudo service apache2 restart
diff --git a/xos/configurations/cord/xos_metering_dashboard.tar.gz b/xos/configurations/cord/xos_metering_dashboard.tar.gz
new file mode 100644
index 0000000..648f91a
--- /dev/null
+++ b/xos/configurations/cord/xos_metering_dashboard.tar.gz
Binary files differ
diff --git a/xos/configurations/devel/Dockerfile.devel b/xos/configurations/devel/Dockerfile.devel
index e44891a..115b731 100644
--- a/xos/configurations/devel/Dockerfile.devel
+++ b/xos/configurations/devel/Dockerfile.devel
@@ -1,8 +1,12 @@
 RUN mkdir -p /root/setup
 ADD xos/configurations/common/admin-openrc.sh /root/setup/
+ADD xos/configurations/common/controller_settings /root/setup/
 ADD xos/configurations/common/flat_net_name /root/setup/
 ADD xos/configurations/common/cloudlab-nodes.yaml /opt/xos/configurations/commmon/
 ADD xos/configurations/common/id_rsa.pub /root/setup/padmin_public_key
+ADD xos/configurations/common/node_key.pub /root/setup/node_key.pub
+ADD xos/configurations/common/node_key /root/setup/node_key
+ADD xos/configurations/common/ceilometer_url /root/setup/ceilometer_url
 
 CMD /usr/bin/make -C /opt/xos/configurations/devel -f Makefile.inside; /bin/bash
 
diff --git a/xos/configurations/frontend/Makefile b/xos/configurations/frontend/Makefile
index e73c6ad..500e932 100644
--- a/xos/configurations/frontend/Makefile
+++ b/xos/configurations/frontend/Makefile
@@ -10,7 +10,7 @@
 	cat ../common/Dockerfile.common Dockerfile.frontend > Dockerfile
 	cd ../../..; sudo docker build -t xos -f xos/configurations/frontend/Dockerfile .
 	echo $(XOS_FOLDER)
-	sudo docker run -v $(XOS_FOLDER)/../../core/xoslib:/opt/xos/core/xoslib -p 9000:8000 --add-host="0.0.0.0:127.0.0.1" xos
+	sudo docker run -v $(XOS_FOLDER)/../../core/xoslib:/opt/xos/core/xoslib -p 9999:8000 --add-host="0.0.0.0:127.0.0.1" xos
 	#sudo docker run -d --add-host="0.0.0.0:$(MYIP)" -p 9999:8000 xos
 	bash ../common/wait_for_xos.sh
 	echo $(RUNNING_CONTAINER)
diff --git a/xos/configurations/opencloud/Dockerfile b/xos/configurations/opencloud/Dockerfile
deleted file mode 100644
index 5b09507..0000000
--- a/xos/configurations/opencloud/Dockerfile
+++ /dev/null
@@ -1,149 +0,0 @@
-FROM       ubuntu:14.04.2
-MAINTAINER Andy Bavier <acb@cs.princeton.edu>
-
-# Set environment variables.
-ENV HOME /root
-ENV TOSCA_CONFIG_PATH=/opt/xos/configurations/opencloud/opencloud.tosca
-
-# XXX Workaround for docker bug:
-# https://github.com/docker/docker/issues/6345
-# Kernel 3.15 breaks docker, uss the line below as a workaround
-# until there is a fix
-RUN ln -s -f /bin/true /usr/bin/chfn
-# XXX End workaround
-
-# Install.
-RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y \
-    git \
-    postgresql \
-    graphviz \
-    graphviz-dev \
-    libxslt1.1 \
-    libxslt1-dev \
-    tar \
-    gcc \
-    geoip-database \
-    libgeoip1 \
-    openssh-client \
-    wget \
-    curl \
-    python-dev \
-    libyaml-dev \
-    pkg-config \
-    supervisor \
-    python-crypto \
-    python-httplib2>=0.9.1 \
-    python-jinja2 \
-    python-paramiko \
-    python-pip \
-    python-psycopg2 \
-    python-pycurl \
-    python-setuptools \
-    python-yaml \
-    python-keystoneclient \
-    python-novaclient \
-    python-neutronclient \
-    python-glanceclient \
-    python-ceilometerclient
-
-RUN pip install \
-    django==1.7 \
-    djangorestframework==2.4.4 \
-    markdown  \ 
-    pyyaml \ 
-    django-filter \
-    lxml \
-    netaddr \
-    pytz \
-    django-timezones \
-    requests \
-    django-crispy-forms \
-    django-geoposition \
-    django-extensions \
-    django-suit \
-    django-bitfield \
-    django-ipware \
-    django-encrypted-fields \
-    django_rest_swagger \
-    python-keyczar \
-    pygraphviz \
-    dnslib
-
-RUN easy_install --upgrade httplib2
-
-RUN easy_install \
-    django_evolution \
-    python_gflags \
-    google_api_python_client \
-    httplib2.ca_certs_locater
-
-
-# Install custom Ansible
-RUN git clone -b release1.8.2 git://github.com/ansible/ansible.git /opt/ansible
-RUN git clone -b release1.8.2 git://github.com/ansible/ansible-modules-extras.git /opt/ansible/lib/ansible/modules/extras
-RUN git clone -b release1.8.2 git://github.com/ansible/ansible-modules-extras.git /opt/ansible/v2/ansible/modules/extras
-RUN git clone git://github.com/sb98052/ansible-modules-core.git /opt/ansible/lib/ansible/modules/core
-RUN git clone git://github.com/sb98052/ansible-modules-core.git /opt/ansible/v2/ansible/modules/core
-ADD ansible-hosts /etc/ansible/hosts
-
-ADD http://code.jquery.com/jquery-1.9.1.min.js /usr/local/lib/python2.7/dist-packages/suit/static/suit/js/
-
-# For Observer
-RUN git clone git://git.planet-lab.org/fofum.git /tmp/fofum
-RUN cd /tmp/fofum; python setup.py install
-RUN rm -rf /tmp/fofum
-
-RUN mkdir -p /usr/local/share /bin
-ADD http://phantomjs.googlecode.com/files/phantomjs-1.7.0-linux-x86_64.tar.bz2 /usr/local/share/
-RUN tar jxvf /usr/local/share/phantomjs-1.7.0-linux-x86_64.tar.bz2 -C /usr/local/share/
-RUN rm -f /usr/local/share/phantomjs-1.7.0-linux-x86_64.tar.bz2
-RUN ln -s /usr/local/share/phantomjs-1.7.0-linux-x86_64 /usr/local/share/phantomjs
-RUN ln -s /usr/local/share/phantomjs/bin/phantomjs /bin/phantomjs
-
-# Supervisor
-ADD observer.conf /etc/supervisor/conf.d/
-
-# Get XOS
-RUN git clone git://github.com/open-cloud/xos.git /tmp/xos && mv /tmp/xos/xos /opt/
-
-# Initscript is broken in Ubuntu
-#ADD observer-initscript /etc/init.d/xosobserver
-
-RUN chmod +x /opt/xos/scripts/opencloud
-RUN /opt/xos/scripts/opencloud genkeys
-
-# Workaround for AUFS issue
-# https://github.com/docker/docker/issues/783#issuecomment-56013588
-RUN mkdir /etc/ssl/private-copy; mv /etc/ssl/private/* /etc/ssl/private-copy/; rm -r /etc/ssl/private; mv /etc/ssl/private-copy /etc/ssl/private; chmod -R 0700 /etc/ssl/private; chown -R postgres /etc/ssl/private
-
-# Set postgres password to match default value in settings.py
-RUN service postgresql start; sudo -u postgres psql -c "alter user postgres with password 'password';"
-
-# Turn DEBUG on so that devel server will serve static files
-#    (not necessary if --insecure is passed to 'manage.py runserver')
-# RUN sed -i 's/DEBUG = False/DEBUG = True/' /opt/xos/xos/settings.py
-
-# Cruft to workaround problems with migrations, should go away...
-RUN /opt/xos/scripts/opencloud remigrate
-
-# git clone uses cached copy, doesn't pick up latest
-RUN git -C /opt/ansible pull
-RUN git -C /opt/ansible/lib/ansible/modules/core pull
-RUN git -C /opt/ansible/v2/ansible/modules/core pull
-
-# install Tosca engine
-RUN apt-get install -y m4
-RUN pip install python-dateutil
-RUN bash /opt/xos/tosca/install_tosca.sh
-
-EXPOSE 8000
-
-# Set environment variables.
-ENV HOME /root
-
-# Define working directory.
-WORKDIR /root
-
-# Define default command.
-#CMD ["/bin/bash"]
-CMD /opt/xos/scripts/docker_start_xos
diff --git a/xos/configurations/opencloud/Makefile b/xos/configurations/opencloud/Makefile
deleted file mode 100644
index 863f2b7..0000000
--- a/xos/configurations/opencloud/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-RUNNING_CONTAINER:=$(shell sudo docker ps|grep "opencloud_server"|awk '{print $$NF}')
-
-.PHONY: build
-build: ; docker build --rm -t opencloud .
-
-.PHONY: run
-run: ; docker run --rm  --name opencloud_server opencloud
-
-.PHONY: runtosca
-runtosca: ; docker exec -it $RUNNING_CONTAINER /usr/bin/python /opt/xos/tosca/run.py padmin@vicci.org $TOSCA_CONFIG_PATH
-
-.PHONY: stop
-stop: ; docker stop opencloud_server
-
-.PHONY: rmcontainer
-rmcontainer: ; docker rm opencloud_server
diff --git a/xos/configurations/opencloud/Makefile.inside b/xos/configurations/opencloud/Makefile.inside
deleted file mode 100644
index 43ad235..0000000
--- a/xos/configurations/opencloud/Makefile.inside
+++ /dev/null
@@ -1,2 +0,0 @@
-run_tosca:
-	python /opt/xos/tosca/run.py padmin@vicci.org opencloud.yaml
diff --git a/xos/configurations/opencloud/observer.conf b/xos/configurations/opencloud/observer.conf
deleted file mode 100644
index 92545eb..0000000
--- a/xos/configurations/opencloud/observer.conf
+++ /dev/null
@@ -1,2 +0,0 @@
-[program:observer]
-command=python /opt/xos/xos-observer.py
diff --git a/xos/configurations/opencloud/opencloud.yaml b/xos/configurations/opencloud/opencloud.yaml
index f6d33a2..15142a6 100644
--- a/xos/configurations/opencloud/opencloud.yaml
+++ b/xos/configurations/opencloud/opencloud.yaml
@@ -1,7 +1,6 @@
 tosca_definitions_version: tosca_simple_yaml_1_0
 
-description: >
-    * Adds OpenCloud Sites, Deployments, and Controllers.
+description: Adds OpenCloud Sites, Deployments, and Controllers.
 
 imports:
    - custom_types/xos.yaml
@@ -188,7 +187,7 @@
           admin_tenant: admin
           domain: Default
 
-   backbone-wdc:
+    backbone-wdc:
       type: tosca.nodes.Controller
       requirements:
           - deployment:
@@ -203,11 +202,26 @@
           admin_tenant: admin
           domain: Default
 
+    campus-arizona:
+      type: tosca.nodes.Controller
+      requirements:
+          - deployment:
+              node: campus
+              relationship: tosca.relationships.ControllerDeployment
+      properties:
+          backend_type: OpenStack
+          version: Juno
+          auth_url: http://localhost:35357/v2.0/
+          admin_user: admin
+          admin_password: admin
+          admin_tenant: admin
+          domain: Default
+
     campus-princeton:
       type: tosca.nodes.Controller
       requirements:
           - deployment:
-              node: backbone
+              node: campus
               relationship: tosca.relationships.ControllerDeployment
       properties:
           backend_type: OpenStack
@@ -222,7 +236,7 @@
       type: tosca.nodes.Controller
       requirements:
           - deployment:
-              node: backbone
+              node: campus
               relationship: tosca.relationships.ControllerDeployment
       properties:
           backend_type: OpenStack
@@ -237,7 +251,7 @@
       type: tosca.nodes.Controller
       requirements:
           - deployment:
-              node: backbone
+              node: campus
               relationship: tosca.relationships.ControllerDeployment
       properties:
           backend_type: OpenStack
@@ -252,7 +266,7 @@
       type: tosca.nodes.Controller
       requirements:
           - deployment:
-              node: backbone
+              node: campus
               relationship: tosca.relationships.ControllerDeployment
       properties:
           backend_type: OpenStack
@@ -267,7 +281,7 @@
       type: tosca.nodes.Controller
       requirements:
           - deployment:
-              node: backbone
+              node: campus
               relationship: tosca.relationships.ControllerDeployment
       properties:
           backend_type: OpenStack
@@ -282,7 +296,7 @@
       type: tosca.nodes.Controller
       requirements:
           - deployment:
-              node: backbone
+              node: campus
               relationship: tosca.relationships.ControllerDeployment
       properties:
           backend_type: OpenStack
@@ -297,7 +311,7 @@
       type: tosca.nodes.Controller
       requirements:
           - deployment:
-              node: backbone
+              node: campus
               relationship: tosca.relationships.ControllerDeployment
       properties:
           backend_type: OpenStack
@@ -363,7 +377,7 @@
                relationship: tosca.relationships.SiteDeployment
                requirements:
                    - controller:
-                       node: backbone-kas
+                       node: backbone-kan
                        relationship: tosca.relationships.UsesController
 
     i2-lax:
@@ -436,7 +450,7 @@
                        node: backbone-sng
                        relationship: tosca.relationships.UsesController
 
-   i2-wdc:
+    i2-wdc:
       type: tosca.nodes.Site
       properties:
           display_name: I2-wdc
@@ -567,7 +581,7 @@
       type: tosca.nodes.User
       requirements:
           - site:
-              node: campus_princeton
+              node: princeton
               relationship: tosca.relationships.MemberOfSite
       properties:
           is_admin: true
diff --git a/xos/cord/models.py b/xos/cord/models.py
index 26d7d24..67ffdc7 100644
--- a/xos/cord/models.py
+++ b/xos/cord/models.py
@@ -465,7 +465,7 @@
 
     sync_attributes = ("nat_ip", "nat_mac",
                        "lan_ip", "lan_mac",
-                       "wan_ip", "wan_mac",
+                       "wan_ip", "wan_mac", "wan_container_mac",
                        "private_ip", "private_mac",
                        "hpc_client_ip", "hpc_client_mac")
 
@@ -575,6 +575,12 @@
     def wan_mac(self):
         return self.addresses.get("wan", (None, None) )[1]
 
+    # Generate the MAC for the container interface connected to WAN
+    @property
+    def wan_container_mac(self):
+        (a, b, c, d) = self.wan_ip.split('.')
+        return "02:42:%02x:%02x:%02x:%02x" % (int(a), int(b), int(c), int(d))
+
     @property
     def private_ip(self):
         return self.addresses.get("private", (None, None) )[0]
diff --git a/xos/core/admin.py b/xos/core/admin.py
index a5b89be..a0cabd1 100644
--- a/xos/core/admin.py
+++ b/xos/core/admin.py
@@ -1372,6 +1372,39 @@
     #    obj.os_manager = OpenStackManager(auth=auth, caller=request.user)
     #    obj.delete()
 
+class ContainerPortInline(XOSTabularInline):
+    fields = ['backend_status_icon', 'network', 'container', 'ip', 'mac', 'segmentation_id']
+    readonly_fields = ("backend_status_icon", "ip", "mac", "segmentation_id")
+    model = Port
+    selflink_fieldname = "network"
+    extra = 0
+    verbose_name_plural = "Ports"
+    verbose_name = "Port"
+    suit_classes = 'suit-tab suit-tab-ports'
+
+class ContainerAdmin(XOSBaseAdmin):
+    fieldsets = [
+        ('Container Details', {'fields': ['backend_status_text', 'slice', 'node', 'docker_image', 'no_sync'], 'classes': ['suit-tab suit-tab-general'], })
+    ]
+    readonly_fields = ('backend_status_text', )
+    list_display = ['backend_status_icon', 'id']
+    list_display_links = ('backend_status_icon', 'id', )
+
+    suit_form_tabs =(('general', 'Container Details'), ('ports', 'Ports'))
+
+    inlines = [TagInline, ContainerPortInline]
+
+    def formfield_for_foreignkey(self, db_field, request, **kwargs):
+        if db_field.name == 'slice':
+            kwargs['queryset'] = Slice.select_by_user(request.user)
+
+        return super(ContainerAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
+
+    def queryset(self, request):
+        # admins can see all instances. Users can only see instances of
+        # the slices they belong to.
+        return Container.select_by_user(request.user)
+
 class UserCreationForm(forms.ModelForm):
     """A form for creating new users. Includes all the required
     fields, plus a repeated password."""
@@ -1727,7 +1760,7 @@
     readonly_fields = ('backend_status_icon', )
 
 class NetworkPortInline(XOSTabularInline):
-    fields = ['backend_status_icon', 'network', 'instance', 'ip', 'mac']
+    fields = ['backend_status_icon', 'network', 'instance', 'container', 'ip', 'mac']
     readonly_fields = ("backend_status_icon", "ip", "mac")
     model = Port
     selflink_fieldname = "instance"
@@ -2024,4 +2057,5 @@
     admin.site.register(TenantRoot, TenantRootAdmin)
     admin.site.register(TenantRootRole, TenantRootRoleAdmin)
     admin.site.register(TenantAttribute, TenantAttributeAdmin)
+    admin.site.register(Container, ContainerAdmin)
 
diff --git a/xos/core/models/__init__.py b/xos/core/models/__init__.py
index c380e9c..bc97dab 100644
--- a/xos/core/models/__init__.py
+++ b/xos/core/models/__init__.py
@@ -24,6 +24,7 @@
 from .node import Node
 from .slicetag import SliceTag
 from .instance import Instance
+from .container import Container
 from .reservation import ReservedResource
 from .reservation import Reservation
 from .network import Network, NetworkParameterType, NetworkParameter, Port, NetworkTemplate, Router, NetworkSlice, ControllerNetwork
diff --git a/xos/core/models/container.py b/xos/core/models/container.py
new file mode 100644
index 0000000..151b576
--- /dev/null
+++ b/xos/core/models/container.py
@@ -0,0 +1,83 @@
+import os
+from django.db import models
+from django.db.models import Q
+from django.core import exceptions
+from core.models import PlCoreBase,PlCoreBaseManager,PlCoreBaseDeletionManager
+from core.models.plcorebase import StrippedCharField
+from core.models import Image
+from core.models import Slice, SlicePrivilege
+from core.models import Node
+from core.models import Site
+from core.models import Deployment
+from core.models import Controller
+from core.models import User
+from core.models import Tag
+from core.models import Flavor
+from django.contrib.contenttypes import generic
+from xos.config import Config
+from monitor import driver as monitor
+from django.core.exceptions import PermissionDenied, ValidationError
+
+config = Config()
+
+
+# Create your models here.
+class Container(PlCoreBase):
+    name = StrippedCharField(max_length=200, help_text="Container name")
+    slice = models.ForeignKey(Slice, related_name='containers')
+    node = models.ForeignKey(Node, related_name='containers')
+    creator = models.ForeignKey(User, related_name='containers', blank=True, null=True)
+    docker_image = StrippedCharField(null=True, blank=True, max_length=200, help_text="name of docker container to instantiate")
+
+    def __unicode__(self):
+        return u'container-%s' % str(self.id)
+
+    def save(self, *args, **kwds):
+        if not self.name:
+            self.name = self.slice.name
+        if not self.creator and hasattr(self, 'caller'):
+            self.creator = self.caller
+        if not self.creator:
+            raise ValidationError('container has no creator')
+
+        if (self.slice.creator != self.creator):
+            # Check to make sure there's a slice_privilege for the user. If there
+            # isn't, then keystone will throw an exception inside the observer.
+            slice_privs = SlicePrivilege.objects.filter(slice=self.slice, user=self.creator)
+            if not slice_privs:
+                raise ValidationError('container creator has no privileges on slice')
+
+# XXX smbaker - disabled for now, was causing fault in tenant view create slice
+#        if not self.controllerNetwork.test_acl(slice=self.slice):
+#            raise exceptions.ValidationError("Deployment %s's ACL does not allow any of this slice %s's users" % (self.controllerNetwork.name, self.slice.name))
+
+        super(Container, self).save(*args, **kwds)
+
+    def can_update(self, user):
+        return True
+
+    @staticmethod
+    def select_by_user(user):
+        if user.is_admin:
+            qs = Container.objects.all()
+        else:
+            slices = Slice.select_by_user(user)
+            qs = Container.objects.filter(slice__in=slices)
+        return qs
+
+    def get_public_keys(self):
+        slice_memberships = SlicePrivilege.objects.filter(slice=self.slice)
+        pubkeys = set([sm.user.public_key for sm in slice_memberships if sm.user.public_key])
+
+        if self.creator.public_key:
+            pubkeys.add(self.creator.public_key)
+
+        if self.slice.creator.public_key:
+            pubkeys.add(self.slice.creator.public_key)
+
+        if self.slice.service and self.slice.service.public_key:
+            pubkeys.add(self.slice.service.public_key)
+
+        return pubkeys
+
+
diff --git a/xos/core/models/network.py b/xos/core/models/network.py
index 2bdf17f..48af5a6 100644
--- a/xos/core/models/network.py
+++ b/xos/core/models/network.py
@@ -2,7 +2,7 @@
 import socket
 import sys
 from django.db import models
-from core.models import PlCoreBase, Site, Slice, Instance, Controller
+from core.models import PlCoreBase, Site, Slice, Instance, Controller, Container
 from core.models import ControllerLinkManager,ControllerLinkDeletionManager
 from django.contrib.contenttypes.models import ContentType
 from django.contrib.contenttypes import generic
@@ -158,7 +158,7 @@
     router_id = models.CharField(null=True, blank=True, max_length=256, help_text="Quantum router id")
     subnet_id = models.CharField(null=True, blank=True, max_length=256, help_text="Quantum subnet id")
     subnet = models.CharField(max_length=32, blank=True)
-     
+
     class Meta:
         unique_together = ('network', 'controller')
         
@@ -211,9 +211,12 @@
 class Port(PlCoreBase):
     network = models.ForeignKey(Network,related_name='links')
     instance = models.ForeignKey(Instance, null=True, blank=True, related_name='ports')
+    container = models.ForeignKey(Container, null=True, blank=True, related_name='ports')
     ip = models.GenericIPAddressField(help_text="Instance ip address", blank=True, null=True)
     port_id = models.CharField(null=True, blank=True, max_length=256, help_text="Quantum port id")
     mac = models.CharField(null=True, blank=True, max_length=256, help_text="MAC address associated with this port")
+    #unattached = models.BooleanField(default=False, help_text="create this port even if no Instance is attached")
+    segmentation_id = models.CharField(null=True, blank=True, max_length=256, help_text="GRE segmentation id for port")
 
     class Meta:
         unique_together = ('network', 'instance')
diff --git a/xos/core/static/xos.css b/xos/core/static/xos.css
index 96ca8b1..33d05cb 100644
--- a/xos/core/static/xos.css
+++ b/xos/core/static/xos.css
@@ -1,4 +1,4 @@
-/*************************
+g/*************************
 colors:
     tab - active/focus color
     background-color: #105E9E !important;
@@ -483,7 +483,8 @@
 
 .login #content-main h1 {
 /*background: #EBF0F2;*/
-background: url("open-cloud-login-themed-light.png") no-repeat scroll 40% center / 89% auto rgba(235, 240, 242, 0);
+/*background: url("open-cloud-login-themed-light.png") no-repeat scroll 40% center / 89% auto rgba(235, 240, 242, 0);*/
+background: url("cord_logo_3.png") no-repeat scroll 40% center / 89% auto rgba(235, 240, 242, 0);
 /*background-position: 40%;*/
 height: 55px;
 background-repeat: no-repeat;
diff --git a/xos/core/xoslib/spec/views/contentprovider.test.js b/xos/core/xoslib/spec/views/contentprovider.test.js
index e522534..7b64ae8 100644
--- a/xos/core/xoslib/spec/views/contentprovider.test.js
+++ b/xos/core/xoslib/spec/views/contentprovider.test.js
@@ -2,13 +2,18 @@
 
 describe('The Content Provider SPA', () => {
 
-  var scope, element, isolatedScope, httpBackend, mockLocation;
+  var scope, element, isolatedScope, httpBackend, mockLocation, httpProvider;
+
+  var token = 'fakeToken';
 
   // injecting main module
   beforeEach(module('xos.contentProviderApp'));
 
   beforeEach(function(){
-    module(function($provide){
+    module(function($provide, $httpProvider){
+
+      httpProvider = $httpProvider;
+
       // mocking routeParams to pass 1 as id
       $provide.provider('$routeParams', function(){
         /* eslint-disable no-invalid-this*/
@@ -17,6 +22,15 @@
         };
         /* eslint-enable no-invalid-this*/
       });
+
+      //mock $cookie to return a fake xoscsrftoken
+      $provide.service('$cookies', function(){
+        /* eslint-disable no-invalid-this*/
+        this.get = () => {
+          return token;
+        };
+        /* eslint-enable no-invalid-this*/
+      });
     });
   });
 
@@ -30,6 +44,25 @@
     $httpBackend.whenDELETE('/hpcapi/contentproviders/1/?no_hyperlinks=1').respond();
   }));
 
+  it('should set the $http interceptor', () => {
+    expect(httpProvider.interceptors).toContain('SetCSRFToken');
+  });
+
+  it('should add no_hyperlink param', inject(($http, $httpBackend) => {
+    $http.get('www.example.com');
+    $httpBackend.expectGET('www.example.com?no_hyperlinks=1').respond(200);
+    $httpBackend.flush();
+  }));
+
+  it('should set token in the headers', inject(($http, $httpBackend) => {
+    $http.post('http://example.com');
+    $httpBackend.expectPOST('http://example.com?no_hyperlinks=1', undefined, function(headers){
+      // if this condition is false the httpBackend expectation fail
+      return headers['X-CSRFToken'] === token;
+    }).respond(200, {name: 'example'});
+    httpBackend.flush();
+  }));
+
   describe('the action directive', () => {
     beforeEach(inject(function($compile, $rootScope){
       scope = $rootScope.$new();
diff --git a/xos/core/xoslib/static/js/xoslib/xos-backbone.js b/xos/core/xoslib/static/js/xoslib/xos-backbone.js
index 61f51b4..04d5fb7 100644
--- a/xos/core/xoslib/static/js/xoslib/xos-backbone.js
+++ b/xos/core/xoslib/static/js/xoslib/xos-backbone.js
@@ -893,8 +893,10 @@
         var _sync = Backbone.sync;
         Backbone.sync = function(method, model, options){
             options.beforeSend = function(xhr){
-                var token = getCookie("csrftoken");
-                xhr.setRequestHeader('X-CSRFToken', token);
+                // var token = getCookie("csrftoken");
+                // xhr.setRequestHeader('X-CSRFToken', token);
+                var xosToken = getCookie('xoscsrftoken');
+                xhr.setRequestHeader('X-CSRFToken', xosToken);
             };
             return _sync(method, model, options);
         };
diff --git a/xos/core/xoslib/xos-builder/.gitignore b/xos/core/xoslib/xos-builder/.gitignore
index 5157e54..bccda71 100644
--- a/xos/core/xoslib/xos-builder/.gitignore
+++ b/xos/core/xoslib/xos-builder/.gitignore
@@ -1,3 +1,5 @@
 dist/
 src/vendor
-.tmp
\ No newline at end of file
+.tmp
+node_modules
+npm-debug.log
\ No newline at end of file
diff --git a/xos/core/xoslib/xos-builder/README.md b/xos/core/xoslib/xos-builder/README.md
new file mode 100644
index 0000000..7e15de6
--- /dev/null
+++ b/xos/core/xoslib/xos-builder/README.md
@@ -0,0 +1,46 @@
+# XOS Lib Helper
+
+This library should help you while developing with:
+
+#### Serve
+- Install Bower deps
+- Load js files (from args folder)
+- Load html templates (from args folder)
+- Compile ES6
+- Compile Scss
+- Compile template using `ng2html`
+- Watch source folder
+- Livereload
+- Generate a basic index.html in a `dist` folder under `args` folder loading files
+
+#### Build
+- Install Bower deps
+- Load js files (from args folder)
+- Load html templates (from args folder)
+- Compile ES6
+- Compile Scss
+- Compile template using `ng2html`
+- Minify Js & Css
+- Prefix Css
+- Cicle trough `bower.json` and diff it with base `bower.json` to exclude already loaded modules (eg: angular) [Optional]
+- Move `dist` under xos folder
+
+## App Structure
+
+App Name
+â””- src
+   ├ js
+   ├ templates
+   ├ bower_components
+   â”” dist
+
+Angular apps should be saved under `xoslib/source` and builded apps should be moved under `xoslib/static/js`. 
+
+Two files should be generated, `appname_main.js` and `appname_vendor.js`, these file should be included into `xoslib/dashboards/appname.html` (tbd if this file has to be automatically generated during the build)
+
+## Advantages
+
+- Faster development with common tool
+- Standard build for community developer
+- Minified files
+
diff --git a/xos/core/xoslib/xos-builder/xos-builder.js b/xos/core/xoslib/xos-builder/xos-builder.js
new file mode 100755
index 0000000..d6adfe5
--- /dev/null
+++ b/xos/core/xoslib/xos-builder/xos-builder.js
@@ -0,0 +1,20 @@
+#! /usr/bin/env node
+'use strict';
+
+const assert = require('assert');
+const chalk = require('chalk');
+
+const args = process.argv.slice(2);
+
+const error = chalk.white.bgRed;
+const success = chalk.white.bgGreen;
+
+const task = args[0];
+if(!task){
+  console.log(error('A task should be defined'))
+  process.exit(1);
+}
+
+console.log(success('Build Started for'));
+
+console.log(process.argv);
diff --git a/xos/nginx/xos.conf b/xos/nginx/xos.conf
index 9b5d996..64d9d5e 100644
--- a/xos/nginx/xos.conf
+++ b/xos/nginx/xos.conf
@@ -6,8 +6,9 @@
 
 
 server {
-    listen 80;
-    server_name 128.112.139.48;
+    listen   80;
+    listen   [::]:80 default ipv6only=on; ## listen for ipv6
+    server_name 127.0.0.1;
 
     location /static/ {
         alias /opt/xos/core/static/;
diff --git a/xos/observers/onos/steps/sync_onosapp.yaml b/xos/observers/onos/steps/sync_onosapp.yaml
index 2c5eb0f..ad3718c 100644
--- a/xos/observers/onos/steps/sync_onosapp.yaml
+++ b/xos/observers/onos/steps/sync_onosapp.yaml
@@ -11,39 +11,44 @@
   tasks:
 
   - name: Config file directory
-    file:

-      path=/home/ubuntu/{{ appname }}/

-      state=directory

-

-  - name: Copy over configuration files

-    copy:

-      src={{ files_dir }}/{{ '{{' }} item {{ '}}' }}

-      dest=/home/ubuntu/{{ appname }}/{{ '{{' }} item {{ '}}' }}

-    with_items:

-        {% for config_fn in config_fns %}

+    file:
+      path=/home/ubuntu/{{ appname }}/
+      state=directory
+
+{% if config_fns %}
+  - name: Copy over configuration files
+    copy:
+      src={{ files_dir }}/{{ '{{' }} item {{ '}}' }}
+      dest=/home/ubuntu/{{ appname }}/{{ '{{' }} item {{ '}}' }}
+    with_items:
+        {% for config_fn in config_fns %}
         - {{ config_fn }}
-        {% endfor %}

-

-  - name: Copy config files into container

-    shell: docker cp {{ appname }}/{{ '{{' }} item {{ '}}' }} {{ ONOS_container }}:/root/onos/config/

-    sudo: yes

-    with_items:

-        {% for config_fn in config_fns %}

+        {% endfor %}
+
+  - name: Make sure config directory exists
+    shell: docker exec {{ ONOS_container }} mkdir -p /root/onos/config/
+    sudo: yes
+
+  - name: Copy config files into container
+    shell: docker cp {{ appname }}/{{ '{{' }} item {{ '}}' }} {{ ONOS_container }}:/root/onos/config/
+    sudo: yes
+    with_items:
+        {% for config_fn in config_fns %}
         - {{ config_fn }}
-        {% endfor %}

-

-  # Don't know how to check for this condition, just wait

-  - name: Wait for ONOS to install the apps

-    wait_for: timeout=15

-

-  - name: Add dependencies to ONOS

-    uri:

-      url: http://localhost:8181/onos/v1/applications/{{ '{{' }} item {{ '}}' }}/active

-      method: POST

-      user: karaf

-      password: karaf

-    with_items:

-        {% for dependency in dependencies %}

+        {% endfor %}
+{% endif %}
+
+  # Don't know how to check for this condition, just wait
+  - name: Wait for ONOS to install the apps
+    wait_for: timeout=15
+
+  - name: Add dependencies to ONOS
+    uri:
+      url: http://localhost:8181/onos/v1/applications/{{ '{{' }} item {{ '}}' }}/active
+      method: POST
+      user: karaf
+      password: karaf
+    with_items:
+        {% for dependency in dependencies %}
         - {{ dependency }}
-        {% endfor %}

-

+        {% endfor %}
diff --git a/xos/observers/vbng/steps/sync_vbngtenant.py b/xos/observers/vbng/steps/sync_vbngtenant.py
index b603ed6..1347e2f 100644
--- a/xos/observers/vbng/steps/sync_vbngtenant.py
+++ b/xos/observers/vbng/steps/sync_vbngtenant.py
@@ -100,11 +100,11 @@
         if not vcpe.wan_ip:
             self.defer_sync(o, "does not have a WAN IP yet")
 
-        if not vcpe.wan_mac:
-            # this should never happen; WAN MAC is computed from WAN IP
-            self.defer_sync(o, "does not have a WAN MAC yet")
+        if not vcpe.wan_container_mac:
+            # this should never happen; container MAC is computed from WAN IP
+            self.defer_sync(o, "does not have a WAN container MAC yet")
 
-        return (vcpe.wan_ip, vcpe.wan_mac, vcpe.instance.node.name)
+        return (vcpe.wan_ip, vcpe.wan_container_mac, vcpe.instance.node.name)
 
     def sync_record(self, o):
         logger.info("sync'ing VBNGTenant %s" % str(o))
diff --git a/xos/observers/vcpe/steps/sync_vcpetenant.yaml b/xos/observers/vcpe/steps/sync_vcpetenant.yaml
index b485c0f..b5a112a 100644
--- a/xos/observers/vcpe/steps/sync_vcpetenant.yaml
+++ b/xos/observers/vcpe/steps/sync_vcpetenant.yaml
@@ -31,6 +31,8 @@
       lan_mac: {{ lan_mac }}
       wan_ip: {{ wan_ip }}
       wan_mac: {{ wan_mac }}
+      wan_container_mac: {{ wan_container_mac }}
+      wan_next_hop: 10.0.1.253   # FIX ME
       private_ip: {{ private_ip }}
       private_mac: {{ private_mac }}
       hpc_client_ip: {{ hpc_client_ip }}
diff --git a/xos/observers/vcpe/templates/start-vcpe.sh.j2 b/xos/observers/vcpe/templates/start-vcpe.sh.j2
index 7e714de..a3533fa 100755
--- a/xos/observers/vcpe/templates/start-vcpe.sh.j2
+++ b/xos/observers/vcpe/templates/start-vcpe.sh.j2
@@ -5,11 +5,6 @@
     ifconfig|grep $MAC| awk '{print $1}'|grep -v '\.'
 }
 
-function generate_mac_from_ip {
-    IP=$1
-    printf "02:42:%02x:%02x:%02x:%02x\n" `echo $IP|awk -F '.' '{print $1, $2, $3, $4}'`
-}
-
 iptables -L > /dev/null
 ip6tables -L > /dev/null
 
@@ -25,9 +20,8 @@
 fi
 
 # Set up networking via pipework
-WAN_CONTAINER_MAC=$( generate_mac_from_ip {{ wan_ip }} )
 WAN_IFACE=$( mac_to_iface {{ wan_mac }} )
-docker exec $VCPE ifconfig eth0 >> /dev/null || pipework $WAN_IFACE -i eth0 $VCPE {{ wan_ip }}/17@192.168.128.1 $WAN_CONTAINER_MAC
+docker exec $VCPE ifconfig eth0 >> /dev/null || pipework $WAN_IFACE -i eth0 $VCPE {{ wan_ip }}/24@{{ wan_next_hop }} {{ wan_container_mac }}
 
 LAN_IFACE=$( mac_to_iface {{ lan_mac }} )
 docker exec $VCPE ifconfig eth1 >> /dev/null || pipework $LAN_IFACE -i eth1 $VCPE 192.168.0.1/24 @{{ vlan_ids[0] }}
diff --git a/xos/observers/vcpe/vcpe_stats_notifier.py b/xos/observers/vcpe/vcpe_stats_notifier.py
index f4bb923..d726e3c 100644
--- a/xos/observers/vcpe/vcpe_stats_notifier.py
+++ b/xos/observers/vcpe/vcpe_stats_notifier.py
@@ -14,7 +14,11 @@
 level=logging.INFO
 logger=logging.getLogger('vcpe_stats_notifier')
 logger.setLevel(level)
+# create formatter
+formatter = logging.Formatter("%(asctime)s;%(levelname)s;%(message)s")
 handler=logging.handlers.RotatingFileHandler(logfile,maxBytes=1000000, backupCount=1)
+# add formatter to handler
+handler.setFormatter(formatter)
 logger.addHandler(handler)
 
 def extract_dns_stats_from_all_vcpes():
@@ -105,6 +109,9 @@
 def publish_cpe_stats():
      global producer
      global keystone_tenant_id, keystone_user_id, cpe_publisher_id
+
+     logger.debug('publish_cpe_stats invoked')
+
      cpe_container_stats = extract_dns_stats_from_all_vcpes()
 
      for k,v in cpe_container_stats.iteritems():
@@ -119,6 +126,8 @@
                             }
                 }
           producer.publish(msg)
+          logger.debug('Publishing vcpe event: %s', msg)
+
           if 'cache_size' in v:
                msg = {'event_type': 'vcpe.dns.cache.size', 
                       'message_id':six.text_type(uuid.uuid4()),
@@ -132,6 +141,8 @@
                                  }
                      }
                producer.publish(msg)
+               logger.debug('Publishing vcpe.dns.cache.size event: %s', msg)
+
           if 'total_inserted_entries' in v:
                msg = {'event_type': 'vcpe.dns.total_inserted_entries', 
                       'message_id':six.text_type(uuid.uuid4()),
@@ -145,6 +156,8 @@
                                  }
                      }
                producer.publish(msg)
+               logger.debug('Publishing vcpe.dns.total_inserted_entries event: %s', msg)
+
           if 'replaced_unexpired_entries' in v:
                msg = {'event_type': 'vcpe.dns.replaced_unexpired_entries', 
                       'message_id':six.text_type(uuid.uuid4()),
@@ -158,6 +171,7 @@
                                  }
                      }
                producer.publish(msg)
+               logger.debug('Publishing vcpe.dns.replaced_unexpired_entries event: %s', msg)
 
           if 'queries_forwarded' in v:
                msg = {'event_type': 'vcpe.dns.queries_forwarded', 
@@ -172,6 +186,7 @@
                                  }
                      }
                producer.publish(msg)
+               logger.debug('Publishing vcpe.dns.queries_forwarded event: %s', msg)
 
           if 'queries_answered_locally' in v:
                msg = {'event_type': 'vcpe.dns.queries_answered_locally', 
@@ -186,6 +201,7 @@
                                  }
                      }
                producer.publish(msg)
+               logger.debug('Publishing vcpe.dns.queries_answered_locally event: %s', msg)
 
           if 'server_stats' in v:
                for server in v['server_stats']:
@@ -202,6 +218,7 @@
                                      }
                          }
                    producer.publish(msg)
+                   logger.debug('Publishing vcpe.dns.server.queries_sent event: %s', msg)
 
                    msg = {'event_type': 'vcpe.dns.server.queries_failed', 
                           'message_id':six.text_type(uuid.uuid4()),
@@ -216,6 +233,7 @@
                                      }
                          }
                    producer.publish(msg)
+                   logger.debug('Publishing vcpe.dns.server.queries_failed event: %s', msg)
 
 def periodic_publish():
      publish_cpe_stats()
diff --git a/xos/openstack_observer/ansible.py b/xos/openstack_observer/ansible.py
index ee110c9..94b09bd 100644
--- a/xos/openstack_observer/ansible.py
+++ b/xos/openstack_observer/ansible.py
@@ -144,16 +144,21 @@
     return ok_results
 
 def run_template_ssh(name, opts, path='', expected_num=None):
-    instance_id = opts["instance_id"]
     instance_name = opts["instance_name"]
     hostname = opts["hostname"]
     private_key = opts["private_key"]
-    nat_ip = opts["nat_ip"]
-
-    try:
-        proxy_ssh = Config().observer_proxy_ssh
-    except:
-        proxy_ssh = True
+    baremetal_ssh = opts.get("baremetal_ssh",False)
+    if baremetal_ssh:
+        # no instance_id or nat_ip for baremetal
+        # we never proxy to baremetal
+        proxy_ssh = False
+    else:
+        instance_id = opts["instance_id"]
+        nat_ip = opts["nat_ip"]
+        try:
+            proxy_ssh = Config().observer_proxy_ssh
+        except:
+            proxy_ssh = True
 
     (opts, fqp) = get_playbook_fn(opts, path)
     private_key_pathname = fqp + ".key"
@@ -177,7 +182,7 @@
 
     f = open(hosts_pathname, "w")
     f.write("[%s]\n" % instance_name)
-    if proxy_ssh:
+    if proxy_ssh or baremetal_ssh:
         f.write("%s ansible_ssh_private_key_file=%s\n" % (hostname, private_key_pathname))
     else:
         # acb: Login user is hardcoded, this is not great
diff --git a/xos/openstack_observer/steps/sync_container.py b/xos/openstack_observer/steps/sync_container.py
new file mode 100644
index 0000000..de4a2ce
--- /dev/null
+++ b/xos/openstack_observer/steps/sync_container.py
@@ -0,0 +1,122 @@
+import hashlib
+import os
+import socket
+import sys
+import base64
+import time
+from django.db.models import F, Q
+from xos.config import Config
+from observer.syncstep import SyncStep
+from observer.ansible import run_template_ssh
+from core.models import Service, Slice, Container
+from services.onos.models import ONOSService, ONOSApp
+from util.logger import Logger, logging
+
+# hpclibrary will be in steps/..
+parentdir = os.path.join(os.path.dirname(__file__),"..")
+sys.path.insert(0,parentdir)
+
+logger = Logger(level=logging.INFO)
+
+class SyncContainer(SyncStep):
+    provides=[Container]
+    observes=Container
+    requested_interval=0
+    template_name = "sync_container.yaml"
+
+    def __init__(self, *args, **kwargs):
+        super(SyncContainer, self).__init__(*args, **kwargs)
+
+#    def fetch_pending(self, deleted):
+#        if (not deleted):
+#            objs = ONOSService.get_service_objects().filter(Q(enacted__lt=F('updated')) | Q(enacted=None),Q(lazy_blocked=False))
+#        else:
+#            objs = ONOSService.get_deleted_service_objects()
+#
+#        return objs
+
+    def get_node(self,o):
+        return o.node
+
+    def get_node_key(self, node):
+        return "/root/setup/node_key"
+        #return "/opt/xos/node-key"
+
+    def get_instance_port(self, container_port):
+        print container_port
+        print container_port.network
+        for p in container_port.network.links.all():
+            if (p.instance) and (p.instance.node == container_port.container.node) and (p.mac):
+                return p
+        return None
+
+    def get_ports(self, o):
+        i=0
+        ports = []
+        for port in o.ports.all():
+            if not port.mac:
+                raise Exception("Port on network %s is not yet ready" % port.network.name)
+
+            pd={}
+            pd["device"] = "eth%d" % i
+            pd["mac"] = port.mac
+            pd["ip"] = port.ip
+
+            instance_port = self.get_instance_port(port)
+            if not instance_port:
+                raise Exception("No instance on slice for port on network %s" % port.network.name)
+
+            pd["snoop_instance_mac"] = instance_port.mac
+            pd["snoop_instance_id"] = instance_port.instance.instance_id
+
+            ports.append(pd)
+        return ports
+
+    def get_extra_attributes(self, o):
+        fields={}
+        fields["ansible_tag"] = "container-%s" % str(o.id)
+        fields["baremetal_ssh"] = True
+        fields["instance_name"] = "rootcontext"
+        fields["container_name"] = "%s-%s" % (o.slice.name, str(o.id))
+        fields["docker_image"] = o.docker_image
+        fields["username"] = "root"
+        fields["ports"] = self.get_ports(o)
+        return fields
+
+    def sync_fields(self, o, fields):
+        self.run_playbook(o, fields)
+
+    def sync_record(self, o):
+        logger.info("sync'ing object %s" % str(o))
+
+        node = self.get_node(o)
+        node_key_name = self.get_node_key(node)
+
+        if not os.path.exists(node_key_name):
+            raise Exception("Node key %s does not exist" % node_key_name)
+
+        node_key = file(node_key_name).read()
+
+        fields = { "hostname": node.name,
+                   "private_key": node_key,
+                 }
+
+        # If 'o' defines a 'sync_attributes' list, then we'll copy those
+        # attributes into the Ansible recipe's field list automatically.
+        if hasattr(o, "sync_attributes"):
+            for attribute_name in o.sync_attributes:
+                fields[attribute_name] = getattr(o, attribute_name)
+
+        fields.update(self.get_extra_attributes(o))
+
+        self.sync_fields(o, fields)
+
+        o.save()
+
+    def run_playbook(self, o, fields):
+        tStart = time.time()
+        run_template_ssh(self.template_name, fields, path="container")
+        logger.info("playbook execution time %d" % int(time.time()-tStart))
+
+    def delete_record(self, m):
+        pass
diff --git a/xos/openstack_observer/steps/sync_container.yaml b/xos/openstack_observer/steps/sync_container.yaml
new file mode 100644
index 0000000..a707d0b
--- /dev/null
+++ b/xos/openstack_observer/steps/sync_container.yaml
@@ -0,0 +1,91 @@
+---
+- hosts: {{ instance_name }}
+  gather_facts: False
+  connection: ssh
+  user: {{ username }}
+  sudo: yes
+
+  vars:
+    container_name: {{ container_name }}
+    docker_image: {{ docker_image }}
+    ports:
+    {% for port in ports %}
+       - device: {{ port.device }}
+         mac: {{ port.mac }}
+         ip: {{ port.ip }}
+         snoop_instance_mac: {{ port.snoop_instance_mac }}
+         snoop_instance_id: {{ port.snoop_instance_id }}
+    {% endfor %}
+
+  tasks:
+
+#  - name: Fix /etc/hosts
+#    lineinfile:
+#      dest=/etc/hosts
+#      regexp="127.0.0.1 localhost"
+#      line="127.0.0.1 localhost {{ instance_hostname }}"
+
+  - name: Add repo key
+    apt_key:
+      keyserver=hkp://pgp.mit.edu:80
+      id=58118E89F3A912897C070ADBF76221572C52609D
+
+  - name: Install Docker repo
+    apt_repository:
+      repo="deb https://apt.dockerproject.org/repo ubuntu-trusty main"
+      state=present
+
+  - name: Install Docker
+    apt:
+      name={{ '{{' }} item {{ '}}' }}
+      state=latest
+      update_cache=yes
+    with_items:
+    - docker-engine
+    - python-pip
+    - python-httplib2
+
+  # Something is installing a requests library that is incompative with pip, and
+  # will cause this recipe to fail next time it tries to run pip. Only the one
+  # in /usr/local/lib is bad. There's still a good one in /usr/lib
+  - name: check if bad requests library installed
+    stat: path=/usr/local/lib/python2.7/dist-packages/requests
+    register: bad_requests
+
+  - name: remove bad request library
+    shell: mv /usr/local/lib/python2.7/dist-packages/requests /usr/local/lib/python2.7/dist-packages/requests-bad
+    when: bad_requests.stat.exists == True
+
+  - name: Install docker-py
+    pip:
+      name=docker-py
+      state=latest
+
+  - name: install Pipework
+    get_url: url=https://raw.githubusercontent.com/jpetazzo/pipework/master/pipework
+       dest=/usr/local/bin/pipework
+       mode=0755
+
+#  - name: Start Container
+#    docker:
+#      docker_api_version: "1.18"
+#      name: {{ container_name }}
+#      # was: reloaded
+#      state: running
+#      image: {{ docker_image }}
+
+  - name: container upstart
+    template: src=/opt/xos/openstack_observer/templates/container.conf.j2 dest=/etc/init/container-{{ container_name }}.conf
+
+  - name: container systemd
+    template: src=/opt/xos/openstack_observer/templates/container.service.j2 dest=/lib/systemd/system/container-{{ container_name }}.service
+
+  - name: container startup script
+    template: src=/opt/xos/openstack_observer/templates/start-container.sh.j2 dest=/usr/local/sbin/start-container-{{ container_name }}.sh mode=0755
+
+  - name: restart systemd
+    shell: systemctl daemon-reload
+
+  - name: Make sure container is running
+    service: name=container-{{ container_name }} state=started
+
diff --git a/xos/openstack_observer/steps/sync_ports.py b/xos/openstack_observer/steps/sync_ports.py
index 967bef9..7b20d29 100644
--- a/xos/openstack_observer/steps/sync_ports.py
+++ b/xos/openstack_observer/steps/sync_ports.py
@@ -144,9 +144,14 @@
 
         # For ports that were created by the user, find that ones
         # that don't have neutron ports, and create them.
-        for port in Port.objects.filter(port_id__isnull=True, instance__isnull=False):
-            #logger.info("XXX working on port %s" % port)
-            controller = port.instance.node.site_deployment.controller
+        for port in Port.objects.filter(Q(port_id__isnull=True), Q(instance__isnull=False) | Q(container__isnull=False)):
+            logger.info("XXX working on port %s" % port)
+            if port.instance:
+                controller = port.instance.node.site_deployment.controller
+                slice = port.instance.slice
+            else:
+                controller = port.container.node.site_deployment.controller
+                slice = port.container.slice
             if controller:
                 cn=port.network.controllernetworks.filter(controller=controller)
                 if not cn:
@@ -174,7 +179,7 @@
                     caller = port.network.owner.creator
                     auth = {'username': caller.email,
                             'password': caller.remote_password,
-                            'tenant': port.instance.slice.name} # port.network.owner.name}
+                            'tenant': slice.name}
                     client = OpenStackClient(controller=controller, **auth) # cacert=self.config.nova_ca_ssl_cert,
                     driver = OpenStackDriver(client=client)
 
@@ -183,6 +188,10 @@
                     if neutron_port["fixed_ips"]:
                         port.ip = neutron_port["fixed_ips"][0]["ip_address"]
                     port.mac = neutron_port["mac_address"]
+
+                    neutron_network = driver.shell.quantum.list_networks(cn.net_id)["networks"][0]
+                    if "provider:segmentation_id" in neutron_network:
+                        port.segmentation_id = neutron_network["provider:segmentation_id"]
                 except:
                     logger.log_exc("failed to create neutron port for %s" % port)
                     continue
diff --git a/xos/openstack_observer/templates/container.conf.j2 b/xos/openstack_observer/templates/container.conf.j2
new file mode 100644
index 0000000..d3ef42d
--- /dev/null
+++ b/xos/openstack_observer/templates/container.conf.j2
@@ -0,0 +1,11 @@
+# Upstart script for container
+description "container"
+author "smbaker@gmail.com"
+start on filesystem and started docker
+stop on runlevel [!2345]
+respawn
+
+script
+  /usr/local/sbin/start-container-{{ container_name }}.sh
+end script
+
diff --git a/xos/openstack_observer/templates/container.service.j2 b/xos/openstack_observer/templates/container.service.j2
new file mode 100644
index 0000000..9e2b83c
--- /dev/null
+++ b/xos/openstack_observer/templates/container.service.j2
@@ -0,0 +1,9 @@
+[Unit]
+Description={{ container_name }}
+After=docker.service
+
+[Service]
+ExecStart=/bin/bash -c "/usr/local/sbin/start-container-{{ container_name }}.sh"
+
+[Install]
+WantedBy=multi-user.target
diff --git a/xos/openstack_observer/templates/start-container.sh.j2 b/xos/openstack_observer/templates/start-container.sh.j2
new file mode 100644
index 0000000..5656992
--- /dev/null
+++ b/xos/openstack_observer/templates/start-container.sh.j2
@@ -0,0 +1,44 @@
+#!/bin/bash
+
+iptables -L > /dev/null
+ip6tables -L > /dev/null
+
+CONTAINER={{ container_name }}
+IMAGE={{ docker_image }}
+
+docker inspect $CONTAINER > /dev/null 2>&1
+if [ "$?" == 1 ]
+then
+    docker pull $IMAGE
+    docker run -d --name=$CONTAINER --privileged=true --net=none $IMAGE
+else
+    docker start $CONTAINER
+fi
+
+{% if ports %}
+{% for port in ports %}
+IP="{{ port.ip }}"
+MAC="{{ port.mac }}"
+DEVICE="{{ port.device }}"

+INSTANCE_MAC="{{ port.snoop_instance_mac }}"
+INSTANCE_ID="{{ port.snoop_instance_id }}"
+INSTANCE_TAP=`virsh domiflist $INSTANCE_ID | grep -i $INSTANCE_MAC | awk '{print $1}'`
+INSTANCE_TAP=${INSTANCE_TAP:3}
+VLAN_ID=`ovs-vsctl show | grep -i -A 1 port.*$INSTANCE_TAP | grep -i tag | awk '{print $2}'`
+TAP="con`echo $CONTAINER_$DEVICE|md5sum|awk '{print $1}'`"
+TAP=${TAP:0:12}
+echo im=$INSTANCE_MAC ii=$INSTANCE_ID it=$INSTANCE_TAP vlan=$VLAN_ID tap=$TAP con=$CONTAINER dev=$DEVICE mac=$MAC
+ovs-vsctl show | grep -i $TAP
+if [[ $? == 1 ]]; then
+    echo creating tap
+    ovs-vsctl add-port br-int $TAP tag=$VLAN_ID -- set interface $TAP type=internal
+else
+    echo tap exists
+fi
+
+docker exec $CONTAINER ifconfig $DEVICE >> /dev/null || pipework $TAP -i $DEVICE $CONTAINER $IP/24 $MAC
+{% endfor %}
+{% endif %}
+
+# Attach to container
+# docker start -a $CONTAINER
diff --git a/xos/scripts/opencloud b/xos/scripts/opencloud
index b936ce3..189a673 100755
--- a/xos/scripts/opencloud
+++ b/xos/scripts/opencloud
@@ -136,11 +136,8 @@
     fi
 }
 
-function remigrate {
-    if db_exists; then
-        dropdb
-    fi
-    rm -rf /opt/xos/*/migrations
+function makemigrations {
+    rm -rf /opt/xos/*/migrations /opt/xos/services/*/migrations
     python ./manage.py makemigrations core
     python ./manage.py makemigrations hpc
     python ./manage.py makemigrations requestrouter
@@ -151,6 +148,13 @@
     #python ./manage.py makemigrations servcomp
 }
 
+function remigrate {
+    if db_exists; then
+        dropdb
+    fi
+    makemigrations
+}
+
 COMMAND=$1
 
 if [ "$COMMAND" = "initdb" ]; then
@@ -226,3 +230,7 @@
    createdb
    syncdb
 fi
+if [ "$COMMAND" = "makemigrations" ]; then
+   makemigrations
+   syncdb
+fi
diff --git a/xos/templates/admin/base.html b/xos/templates/admin/base.html
index d29456a..a7cc0c4 100644
--- a/xos/templates/admin/base.html
+++ b/xos/templates/admin/base.html
@@ -6,6 +6,7 @@
   <link rel="stylesheet" type="text/css" href="{% static 'suit/bootstrap/css/bootstrap.min.css' %}" media="all"/>
   <link rel="stylesheet" type="text/css" href="{% static 'suit/css/suit.css' %}" media="all">
   <link rel="stylesheet" type="text/css" href="{% static 'xos.css' %}" media="all">
+  <link rel="stylesheet" type="text/css" href="{% static 'cord.css' %}" media="all">
   {% if XOS_BRANDING_CSS %}
       <link rel="stylesheet" type="text/css" href="{{ XOS_BRANDING_CSS }}">
   {% endif %}
@@ -43,7 +44,7 @@
     <div id="container">
 
       {% block logo %}
-      <a href="{% url 'admin:index' %}"><h1 id="site-name"><img class="logo" height="70" width="259" src="{% static 'open-cloud-login-themed-light.png' %}"/></h1></a>
+      <a href="{% url 'admin:index' %}"><h1 id="site-name"><img class="logo" height="70" width="259" src="{% static 'cord_logo_3.png' %}"/></h1></a>
       {% endblock %}
       {% block header %}
         {% if not is_popup %}
diff --git a/xos/templates/admin/dashboard/customize.html b/xos/templates/admin/dashboard/customize.html
index d2e8a20..eb92b21 100644
--- a/xos/templates/admin/dashboard/customize.html
+++ b/xos/templates/admin/dashboard/customize.html
@@ -1,39 +1,50 @@
-<form>
+<div class="row-fluid">

+    <div class="span12 text-right">

+        <a href="core/dashboardview/add/" class="btn btn-success">

+            <i class="icon icon-plus"></i> Add

+        </a>

+    </div>

+</div>

+<form>

     <div class="customize_row">

-    <div class="customize_column">

-    <div>Available Dashboard Views</div>

-    <select name="selectfrom" id="select-from" multiple size="5">

-        {% for cp in unusedDashboards %}

-           <option value="{{ cp }}">{{ cp }}</option>
-        {% endfor %}

-    </select>

-    </div>

-    <div class="customize_column">

-    <br>

-    <div class="btn btn-success" id="customize-btn-add">Add &raquo;</div><br><br>

-    <div class="btn btn-success" id="customize-btn-remove">&laquo; Remove</div>

-    </div>

-    <div class="customize_column">

-    <div>Selected Dashboard Views</div>

-    <select name="selectto" id="select-to" multiple size="5">

-        {% for cp in dashboards %}

-           <option value="{{ cp }}">{{ cp }}</option>
-        {% endfor %}

-    </select>

-    <br>

-    <div class="btn btn-high btn-info" id="customize-btn-save">Save</div>

-    <div style="display: none" id="customize-msg-saving">Saving...</div>

-    </div>

-    <div class="customize_column">

-    <br>

-    <div class="btn btn-success" id="customize-btn-up">Up</div><br><br>

-    <div class="btn btn-success" id="customize-btn-down">Down</div>

-    </div>

+        <div class="customize_column">

+            <div>Available Dashboard Views</div>

+            <select name="selectfrom" id="select-from" multiple size="5">

+                {% for cp in unusedDashboards %}

+                <option value="{{ cp }}">{{ cp }}</option>

+                {% endfor %}

+            </select>

+        </div>

+        <div class="customize_column">

+            <br>

+            <div class="btn btn-success" id="customize-btn-add">Add &raquo;</div>

+            <br>

+            <br>

+            <div class="btn btn-success" id="customize-btn-remove">&laquo; Remove</div>

+        </div>

+        <div class="customize_column">

+            <div>Selected Dashboard Views</div>

+            <select name="selectto" id="select-to" multiple size="5">

+                {% for cp in dashboards %}

+                <option value="{{ cp }}">{{ cp }}</option>

+                {% endfor %}

+            </select>

+            <br>

+            <div class="btn btn-high btn-info" id="customize-btn-save">Save</div>

+            <div style="display: none" id="customize-msg-saving">Saving...</div>

+        </div>

+        <div class="customize_column">

+            <br>

+            <div class="btn btn-success" id="customize-btn-up">Up</div>

+            <br>

+            <br>

+            <div class="btn btn-success" id="customize-btn-down">Down</div>

+        </div>

     </div>

 </form>

-
-<script>
-$(document).ready(function() {
+

+<script>

+$(document).ready(function() {

     $('#customize-btn-add').click(function(){

         $('#select-from option:selected').each( function() {

                 $('#select-to').append("<option value='"+$(this).val()+"'>"+$(this).text()+"</option>");

@@ -71,23 +82,22 @@
          var items=[];

          $("#select-to option").each(function() { items.push($(this).val()); });

          $.ajax({

-                url: '/customize/',
-                dataType: 'json',
-                data: {
-                        dashboards: items.join(","),
-  		        csrfmiddlewaretoken: "{{ csrf_token }}" // < here
-                },
-                type: 'POST',
-                error: function (jqXHR, textStatus, errorThrown) {
-                    errorDialog("Error", textStatus + " " + jqXHR.responseText);
-                    $("#customize-btn-save").show();
-                    $("#customize-msg-saving").hide();
-                },
-                success: function () {
-                        location.reload();
-                }
+                url: '/customize/',

+                dataType: 'json',

+                data: {

+                        dashboards: items.join(","),

+                csrfmiddlewaretoken: "{{ csrf_token }}" // < here

+                },

+                type: 'POST',

+                error: function (jqXHR, textStatus, errorThrown) {

+                    errorDialog("Error", textStatus + " " + jqXHR.responseText);

+                    $("#customize-btn-save").show();

+                    $("#customize-msg-saving").hide();

+                },

+                success: function () {

+                        location.reload();

+                }

         });

-    });
-});
-</script>
-
+    });

+});

+</script>
\ No newline at end of file
diff --git a/xos/tosca/custom_types/xos.m4 b/xos/tosca/custom_types/xos.m4
index 055817d..a661af7 100644
--- a/xos/tosca/custom_types/xos.m4
+++ b/xos/tosca/custom_types/xos.m4
@@ -120,6 +120,9 @@
             config_addresses.json:
                 type: string
                 required: false
+            config_network-cfg.json:
+                type: string
+                required: false
             config_virtualbng.json:
                 type: string
                 required: false
@@ -488,6 +491,18 @@
                 type: string
                 required: false
                 description: OpenStack domain (or "Default")
+            rabbit_host:
+                type: string
+                required: false
+                description: Rabbit host
+            rabbit_user:
+                type: string
+                required: false
+                description: Rabbit user
+            rabbit_password:
+                type: string
+                required: false
+                description: Rabbit password
 
     tosca.nodes.Site:
         derived_from: tosca.nodes.Root
@@ -559,6 +574,23 @@
             node:
                 type: tosca.capabilities.xos.Node
 
+    tosca.nodes.DashboardView:
+        derived_from: tosca.nodes.Root
+        description: >
+            An XOS Dashboard View
+        capabilities:
+            dashboardview:
+                type: tosca.capabilities.xos.DashboardView
+        properties:
+            xos_base_props
+            enabled:
+                type: boolean
+                default: true
+            url:
+                type: string
+                required: false
+                description: URL to the dashboard
+
     tosca.relationships.MemberOfSlice:
         derived_from: tosca.relationships.Root
         valid_target_types: [ tosca.capabilities.xos.Slice ]
@@ -639,6 +671,10 @@
         derived_from: tosca.relationships.Root
         valid_target_types: [ tosca.capabilities.xos.Subscriber ]
 
+    tosca.relationships.UsesDashboard:
+        derived_from: tosca.relationships.Root
+        valid_target_types: [ tosca.capabilities.xos.DashboardView ]
+
     tosca.capabilities.xos.Service:
         derived_from: tosca.capabilities.Root
         description: An XOS Service
@@ -687,3 +723,6 @@
         derived_from: tosca.capabilities.Root
         description: An XOS Image
 
+    tosca.capabilities.xos.DashboardView:
+        derived_from: tosca.capabilities.Root
+        description: An XOS DashboardView
diff --git a/xos/tosca/custom_types/xos.yaml b/xos/tosca/custom_types/xos.yaml
index 409e86b..9170ecf 100644
--- a/xos/tosca/custom_types/xos.yaml
+++ b/xos/tosca/custom_types/xos.yaml
@@ -131,6 +131,9 @@
             config_addresses.json:
                 type: string
                 required: false
+            config_network-cfg.json:
+                type: string
+                required: false
             config_virtualbng.json:
                 type: string
                 required: false
@@ -638,6 +641,18 @@
                 type: string
                 required: false
                 description: OpenStack domain (or "Default")
+            rabbit_host:
+                type: string
+                required: false
+                description: Rabbit host
+            rabbit_user:
+                type: string
+                required: false
+                description: Rabbit user
+            rabbit_password:
+                type: string
+                required: false
+                description: Rabbit password
 
     tosca.nodes.Site:
         derived_from: tosca.nodes.Root
@@ -742,6 +757,34 @@
             node:
                 type: tosca.capabilities.xos.Node
 
+    tosca.nodes.DashboardView:
+        derived_from: tosca.nodes.Root
+        description: >
+            An XOS Dashboard View
+        capabilities:
+            dashboardview:
+                type: tosca.capabilities.xos.DashboardView
+        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
+            enabled:
+                type: boolean
+                default: true
+            url:
+                type: string
+                required: false
+                description: URL to the dashboard
+
     tosca.relationships.MemberOfSlice:
         derived_from: tosca.relationships.Root
         valid_target_types: [ tosca.capabilities.xos.Slice ]
@@ -822,6 +865,10 @@
         derived_from: tosca.relationships.Root
         valid_target_types: [ tosca.capabilities.xos.Subscriber ]
 
+    tosca.relationships.UsesDashboard:
+        derived_from: tosca.relationships.Root
+        valid_target_types: [ tosca.capabilities.xos.DashboardView ]
+
     tosca.capabilities.xos.Service:
         derived_from: tosca.capabilities.Root
         description: An XOS Service
@@ -870,3 +917,6 @@
         derived_from: tosca.capabilities.Root
         description: An XOS Image
 
+    tosca.capabilities.xos.DashboardView:
+        derived_from: tosca.capabilities.Root
+        description: An XOS DashboardView
diff --git a/xos/tosca/resources/ceilometertenant.py b/xos/tosca/resources/ceilometertenant.py
new file mode 100644
index 0000000..6599f33
--- /dev/null
+++ b/xos/tosca/resources/ceilometertenant.py
@@ -0,0 +1,39 @@
+import os
+import pdb
+import sys
+import tempfile
+sys.path.append("/opt/tosca")
+from translator.toscalib.tosca_template import ToscaTemplate
+import pdb
+
+from ceilometer.models import MonitoringChannel, CeilometerService
+
+from xosresource import XOSResource
+
+class XOSCeilometerTenant(XOSResource):
+    provides = "tosca.nodes.CeilometerTenant"
+    xos_model = MonitoringChannel
+    name_field = None
+
+    def get_xos_args(self, throw_exception=True):
+        args = super(XOSCeilometerTenant, self).get_xos_args()
+
+        provider_name = self.get_requirement("tosca.relationships.MemberOfService", throw_exception=throw_exception)
+        if provider_name:
+            args["provider_service"] = self.get_xos_object(CeilometerService, throw_exception=throw_exception, name=provider_name)
+
+        return args
+
+    def get_existing_objs(self):
+        args = self.get_xos_args(throw_exception=False)
+        provider_service = args.get("provider", None)
+        if provider_service:
+            return [ self.get_xos_object(provider_service=provider_service) ]
+        return []
+
+    def postprocess(self, obj):
+        pass
+
+    def can_delete(self, obj):
+        return super(XOSCeilometerTenant, self).can_delete(obj)
+
diff --git a/xos/tosca/resources/controller.py b/xos/tosca/resources/controller.py
index 9a20ea5..2aa208c 100644
--- a/xos/tosca/resources/controller.py
+++ b/xos/tosca/resources/controller.py
@@ -15,7 +15,7 @@
 class XOSController(XOSResource):
     provides = "tosca.nodes.Controller"
     xos_model = Controller
-    copyin_props = ["backend_type", "version", "auth_url", "admin_user", "admin_password", "admin_tenant", "domain"]
+    copyin_props = ["backend_type", "version", "auth_url", "admin_user", "admin_password", "admin_tenant", "domain", "rabbit_host", "rabbit_user", "rabbit_password"]
 
     def get_xos_args(self):
         args = super(XOSController, self).get_xos_args()
diff --git a/xos/tosca/resources/dashboardview.py b/xos/tosca/resources/dashboardview.py
new file mode 100644
index 0000000..9f7687c
--- /dev/null
+++ b/xos/tosca/resources/dashboardview.py
@@ -0,0 +1,23 @@
+import os
+import pdb
+import sys
+import tempfile
+sys.path.append("/opt/tosca")
+from translator.toscalib.tosca_template import ToscaTemplate
+
+from core.models import DashboardView, Site, Deployment, SiteDeployment
+
+from xosresource import XOSResource
+
+class XOSDashboardView(XOSResource):
+    provides = "tosca.nodes.DashboardView"
+    xos_model = DashboardView
+    copyin_props = ["url","enabled"]
+
+    def get_xos_args(self):
+        return super(XOSDashboardView, self).get_xos_args()
+
+    def can_delete(self, obj):
+        return super(XOSDashboardView, self).can_delete(obj)
+
+
diff --git a/xos/tosca/resources/user.py b/xos/tosca/resources/user.py
index 53323c5..724bc3d 100644
--- a/xos/tosca/resources/user.py
+++ b/xos/tosca/resources/user.py
@@ -5,7 +5,7 @@
 sys.path.append("/opt/tosca")
 from translator.toscalib.tosca_template import ToscaTemplate
 
-from core.models import User, Site, SiteRole, SliceRole, SlicePrivilege, SitePrivilege
+from core.models import User, Site, SiteRole, SliceRole, SlicePrivilege, SitePrivilege, DashboardView, UserDashboardView
 
 from xosresource import XOSResource
 
@@ -46,6 +46,21 @@
                         sp.save()
                         self.info("Added site privilege on %s role %s for %s" % (str(dest), str(role), str(obj)))
 
+        dashboard_order = 10
+        for reqs in self.nodetemplate.requirements:
+            for (k,v) in reqs.items():
+                if (v["relationship"] == "tosca.relationships.UsesDashboard"):
+                    dashboard_name = v["node"]
+                    dashboard = self.get_xos_object(DashboardView, name=dashboard_name)
+
+                    udvs = UserDashboardView.objects.filter(user=obj, dashboardView=dashboard)
+                    if not udvs:
+                        self.info("Adding UserDashboardView from %s to %s" % (obj, dashboard))
+
+                        udv = UserDashboardView(user=obj, dashboardView=dashboard, order=dashboard_order)
+                        dashboard_order += 10
+                        udv.save()
+
     def create(self):
         nodetemplate = self.nodetemplate
 
diff --git a/xos/tosca/samples/dashboardview.yaml b/xos/tosca/samples/dashboardview.yaml
new file mode 100644
index 0000000..2a358f2
--- /dev/null
+++ b/xos/tosca/samples/dashboardview.yaml
@@ -0,0 +1,34 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: Dashboard View
+
+imports:
+   - custom_types/xos.yaml
+
+topology_template:
+  node_templates:
+    Ceilometer:
+      type: tosca.nodes.DashboardView
+      properties:
+          url: http:/xosmetering/
+
+    Tenant:
+      type: tosca.nodes.DashboardView
+      properties:
+          no-create: true
+          no-update: true
+          no-delete: true
+
+    padmin@vicci.org:
+      type: tosca.nodes.User
+      properties:
+          firstname: XOS
+          lastname: admin
+          is_admin: true
+      requirements:
+          - tenant_dashboard:
+              node: Tenant
+              relationship: tosca.relationships.UsesDashboard
+          - ceilometer_dashboard:
+              node: Ceilometer
+              relationship: tosca.relationships.UsesDashboard
diff --git a/xos/tosca/samples/new_site_deploy_slice.yaml b/xos/tosca/samples/new_site_deploy_slice.yaml
index 6ccadc1..5e36bcb 100644
--- a/xos/tosca/samples/new_site_deploy_slice.yaml
+++ b/xos/tosca/samples/new_site_deploy_slice.yaml
@@ -27,6 +27,9 @@
            admin_password: letmeout
            admin_tenant: 12345678
            domain: mydomain
+           rabbit_host: rabhost
+           rabbit_user: rabuser
+           rabbit_password: rabpw
 
     newsite:
       type: tosca.nodes.Site
diff --git a/xos/uwsgi/xos.ini b/xos/uwsgi/xos.ini
index da7f7dd..63eb6b2 100644
--- a/xos/uwsgi/xos.ini
+++ b/xos/uwsgi/xos.ini
@@ -2,17 +2,17 @@
 chdir = /opt/xos
 module = xos.wsgi:application
 env = DJANGO_SETTINGS_MODULE=xos.settings
-socket = /var/run/uwsgi/xos.sock
+socket = /var/run/uwsgi.xos.sock
 socket = 127.0.0.1:9001
-http = 128.112.139.48:9002
+http = 127.0.0.1:9002
 stats = 127.0.0.1:9003
 workers = 3
 master = true
 processes = 8
-uid = uwsgi
-gid = webserver 
+uid = root
+gid = root
 harakiri = 20
-daemonize=/var/log/uwsgi/xos.log 
+daemonize=/var/log/uwsgi.xos.log 
 static-map = /static=/var/www/xos/static
-pidfile = /var/run/uwsgi/uwsgi.pid
+pidfile = /var/run/uwsgi.xos.pid
 buffer-size = 8192
diff --git a/xos/xos/hpcapi.py b/xos/xos/hpcapi.py
index 389238e..9de4989 100644
--- a/xos/xos/hpcapi.py
+++ b/xos/xos/hpcapi.py
@@ -38,9 +38,6 @@
     return patterns('',
         url(r'^hpcapi/$', hpc_api_root),
     
-        url(r'hpcapi/services/$', ServiceList.as_view(), name='service-list'),
-        url(r'hpcapi/services/(?P<pk>[a-zA-Z0-9\-]+)/$', ServiceDetail.as_view(), name ='service-detail'),
-    
         url(r'hpcapi/hpchealthchecks/$', HpcHealthCheckList.as_view(), name='hpchealthcheck-list'),
         url(r'hpcapi/hpchealthchecks/(?P<pk>[a-zA-Z0-9\-]+)/$', HpcHealthCheckDetail.as_view(), name ='hpchealthcheck-detail'),
     
@@ -53,9 +50,6 @@
         url(r'hpcapi/cdnprefixs/$', CDNPrefixList.as_view(), name='cdnprefix-list'),
         url(r'hpcapi/cdnprefixs/(?P<pk>[a-zA-Z0-9\-]+)/$', CDNPrefixDetail.as_view(), name ='cdnprefix-detail'),
     
-        url(r'hpcapi/users/$', UserList.as_view(), name='user-list'),
-        url(r'hpcapi/users/(?P<pk>[a-zA-Z0-9\-]+)/$', UserDetail.as_view(), name ='user-detail'),
-    
         url(r'hpcapi/serviceproviders/$', ServiceProviderList.as_view(), name='serviceprovider-list'),
         url(r'hpcapi/serviceproviders/(?P<pk>[a-zA-Z0-9\-]+)/$', ServiceProviderDetail.as_view(), name ='serviceprovider-detail'),
     
@@ -73,12 +67,10 @@
 @api_view(['GET'])
 def hpc_api_root(request, format=None):
     return Response({
-        'services': reverse('service-list', request=request, format=format),
         'hpchealthchecks': reverse('hpchealthcheck-list', request=request, format=format),
         'hpcservices': reverse('hpcservice-list', request=request, format=format),
         'originservers': reverse('originserver-list', request=request, format=format),
         'cdnprefixs': reverse('cdnprefix-list', request=request, format=format),
-        'users': reverse('user-list', request=request, format=format),
         'serviceproviders': reverse('serviceprovider-list', request=request, format=format),
         'contentproviders': reverse('contentprovider-list', request=request, format=format),
         'accessmaps': reverse('accessmap-list', request=request, format=format),
@@ -142,41 +134,6 @@
 
 
 
-class ServiceSerializer(serializers.HyperlinkedModelSerializer):
-    id = IdField()
-    
-    humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
-    validators = serializers.SerializerMethodField("getValidators")
-    def getHumanReadableName(self, obj):
-        return str(obj)
-    def getValidators(self, obj):
-        try:
-            return obj.getValidators()
-        except:
-            return None
-    class Meta:
-        model = Service
-        fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','policed','backend_register','backend_status','deleted','write_protect','lazy_blocked','no_sync','description','enabled','kind','name','versionNumber','published','view_url','icon_url','public_key','service_specific_id','service_specific_attribute',)
-
-class ServiceIdSerializer(XOSModelSerializer):
-    id = IdField()
-    
-    humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
-    validators = serializers.SerializerMethodField("getValidators")
-    def getHumanReadableName(self, obj):
-        return str(obj)
-    def getValidators(self, obj):
-        try:
-            return obj.getValidators()
-        except:
-            return None
-    class Meta:
-        model = Service
-        fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','policed','backend_register','backend_status','deleted','write_protect','lazy_blocked','no_sync','description','enabled','kind','name','versionNumber','published','view_url','icon_url','public_key','service_specific_id','service_specific_attribute',)
-
-
-
-
 class HpcHealthCheckSerializer(serializers.HyperlinkedModelSerializer):
     id = IdField()
     
@@ -226,7 +183,7 @@
             return None
     class Meta:
         model = HpcService
-        fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','policed','backend_register','backend_status','deleted','write_protect','lazy_blocked','no_sync','description','enabled','kind','name','versionNumber','published','view_url','icon_url','public_key','service_specific_id','service_specific_attribute','service_ptr','cmi_hostname','hpc_port80','watcher_hpc_network','watcher_dnsdemux_network','watcher_dnsredir_network',)
+        fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','policed','backend_register','backend_status','deleted','write_protect','lazy_blocked','no_sync','description','enabled','kind','name','versionNumber','published','view_url','icon_url','public_key','service_specific_id','service_specific_attribute','cmi_hostname','hpc_port80','watcher_hpc_network','watcher_dnsdemux_network','watcher_dnsredir_network',)
 
 class HpcServiceIdSerializer(XOSModelSerializer):
     id = IdField()
@@ -242,7 +199,7 @@
             return None
     class Meta:
         model = HpcService
-        fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','policed','backend_register','backend_status','deleted','write_protect','lazy_blocked','no_sync','description','enabled','kind','name','versionNumber','published','view_url','icon_url','public_key','service_specific_id','service_specific_attribute','service_ptr','cmi_hostname','hpc_port80','watcher_hpc_network','watcher_dnsdemux_network','watcher_dnsredir_network',)
+        fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','policed','backend_register','backend_status','deleted','write_protect','lazy_blocked','no_sync','description','enabled','kind','name','versionNumber','published','view_url','icon_url','public_key','service_specific_id','service_specific_attribute','cmi_hostname','hpc_port80','watcher_hpc_network','watcher_dnsdemux_network','watcher_dnsredir_network',)
 
 
 
@@ -317,49 +274,6 @@
 
 
 
-class UserSerializer(serializers.HyperlinkedModelSerializer):
-    id = IdField()
-    
-    
-    contentproviders = serializers.HyperlinkedRelatedField(many=True, read_only=True, view_name='contentprovider-detail')
-    
-    
-    humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
-    validators = serializers.SerializerMethodField("getValidators")
-    def getHumanReadableName(self, obj):
-        return str(obj)
-    def getValidators(self, obj):
-        try:
-            return obj.getValidators()
-        except:
-            return None
-    class Meta:
-        model = User
-        fields = ('humanReadableName', 'validators', 'id','password','last_login','email','username','firstname','lastname','phone','user_url','site','public_key','is_active','is_admin','is_staff','is_readonly','is_registering','is_appuser','login_page','created','updated','enacted','policed','backend_status','deleted','write_protect','timezone','contentproviders',)
-
-class UserIdSerializer(XOSModelSerializer):
-    id = IdField()
-    
-    
-    contentproviders = serializers.PrimaryKeyRelatedField(many=True,  queryset = ContentProvider.objects.all())
-    
-    
-    humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
-    validators = serializers.SerializerMethodField("getValidators")
-    def getHumanReadableName(self, obj):
-        return str(obj)
-    def getValidators(self, obj):
-        try:
-            return obj.getValidators()
-        except:
-            return None
-    class Meta:
-        model = User
-        fields = ('humanReadableName', 'validators', 'id','password','last_login','email','username','firstname','lastname','phone','user_url','site','public_key','is_active','is_admin','is_staff','is_readonly','is_registering','is_appuser','login_page','created','updated','enacted','policed','backend_status','deleted','write_protect','timezone','contentproviders',)
-
-
-
-
 class ServiceProviderSerializer(serializers.HyperlinkedModelSerializer):
     id = IdField()
     
@@ -398,21 +312,9 @@
 class ContentProviderSerializer(serializers.HyperlinkedModelSerializer):
     id = IdField()
     
-    humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
-    validators = serializers.SerializerMethodField("getValidators")
-    def getHumanReadableName(self, obj):
-        return str(obj)
-    def getValidators(self, obj):
-        try:
-            return obj.getValidators()
-        except:
-            return None
-    class Meta:
-        model = ContentProvider
-        fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','policed','backend_register','backend_status','deleted','write_protect','lazy_blocked','no_sync','content_provider_id','name','enabled','description','serviceProvider',)
-
-class ContentProviderIdSerializer(XOSModelSerializer):
-    id = IdField()
+    
+    users = serializers.HyperlinkedRelatedField(many=True, read_only=True, view_name='user-detail')
+    
     
     humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
     validators = serializers.SerializerMethodField("getValidators")
@@ -425,7 +327,27 @@
             return None
     class Meta:
         model = ContentProvider
-        fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','policed','backend_register','backend_status','deleted','write_protect','lazy_blocked','no_sync','content_provider_id','name','enabled','description','serviceProvider',)
+        fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','policed','backend_register','backend_status','deleted','write_protect','lazy_blocked','no_sync','content_provider_id','name','enabled','description','serviceProvider','users',)
+
+class ContentProviderIdSerializer(XOSModelSerializer):
+    id = IdField()
+    
+    
+    users = serializers.PrimaryKeyRelatedField(many=True,  queryset = User.objects.all())
+    
+    
+    humanReadableName = serializers.SerializerMethodField("getHumanReadableName")
+    validators = serializers.SerializerMethodField("getValidators")
+    def getHumanReadableName(self, obj):
+        return str(obj)
+    def getValidators(self, obj):
+        try:
+            return obj.getValidators()
+        except:
+            return None
+    class Meta:
+        model = ContentProvider
+        fields = ('humanReadableName', 'validators', 'id','created','updated','enacted','policed','backend_register','backend_status','deleted','write_protect','lazy_blocked','no_sync','content_provider_id','name','enabled','description','serviceProvider','users',)
 
 
 
@@ -502,8 +424,6 @@
 
 serializerLookUp = {
 
-                 Service: ServiceSerializer,
-
                  HpcHealthCheck: HpcHealthCheckSerializer,
 
                  HpcService: HpcServiceSerializer,
@@ -512,8 +432,6 @@
 
                  CDNPrefix: CDNPrefixSerializer,
 
-                 User: UserSerializer,
-
                  ServiceProvider: ServiceProviderSerializer,
 
                  ContentProvider: ContentProviderSerializer,
@@ -528,53 +446,6 @@
 # Based on core/views/*.py
 
 
-class ServiceList(XOSListCreateAPIView):
-    queryset = Service.objects.select_related().all()
-    serializer_class = ServiceSerializer
-    id_serializer_class = ServiceIdSerializer
-    filter_backends = (filters.DjangoFilterBackend,)
-    filter_fields = ('id','created','updated','enacted','policed','backend_register','backend_status','deleted','write_protect','lazy_blocked','no_sync','description','enabled','kind','name','versionNumber','published','view_url','icon_url','public_key','service_specific_id','service_specific_attribute',)
-
-    def get_serializer_class(self):
-        no_hyperlinks=False
-        if hasattr(self.request,"QUERY_PARAMS"):
-            no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
-        if (no_hyperlinks):
-            return self.id_serializer_class
-        else:
-            return self.serializer_class
-
-    def get_queryset(self):
-        if (not self.request.user.is_authenticated()):
-            raise XOSNotAuthenticated()
-        return Service.select_by_user(self.request.user)
-
-
-class ServiceDetail(XOSRetrieveUpdateDestroyAPIView):
-    queryset = Service.objects.select_related().all()
-    serializer_class = ServiceSerializer
-    id_serializer_class = ServiceIdSerializer
-
-    def get_serializer_class(self):
-        no_hyperlinks=False
-        if hasattr(self.request,"QUERY_PARAMS"):
-            no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
-        if (no_hyperlinks):
-            return self.id_serializer_class
-        else:
-            return self.serializer_class
-
-    def get_queryset(self):
-        if (not self.request.user.is_authenticated()):
-            raise XOSNotAuthenticated()
-        return Service.select_by_user(self.request.user)
-
-    # update() is handled by XOSRetrieveUpdateDestroyAPIView
-
-    # destroy() is handled by XOSRetrieveUpdateDestroyAPIView
-
-
-
 class HpcHealthCheckList(XOSListCreateAPIView):
     queryset = HpcHealthCheck.objects.select_related().all()
     serializer_class = HpcHealthCheckSerializer
@@ -627,7 +498,7 @@
     serializer_class = HpcServiceSerializer
     id_serializer_class = HpcServiceIdSerializer
     filter_backends = (filters.DjangoFilterBackend,)
-    filter_fields = ('id','created','updated','enacted','policed','backend_register','backend_status','deleted','write_protect','lazy_blocked','no_sync','description','enabled','kind','name','versionNumber','published','view_url','icon_url','public_key','service_specific_id','service_specific_attribute','service_ptr','cmi_hostname','hpc_port80','watcher_hpc_network','watcher_dnsdemux_network','watcher_dnsredir_network',)
+    filter_fields = ('id','created','updated','enacted','policed','backend_register','backend_status','deleted','write_protect','lazy_blocked','no_sync','description','enabled','kind','name','versionNumber','published','view_url','icon_url','public_key','service_specific_id','service_specific_attribute','cmi_hostname','hpc_port80','watcher_hpc_network','watcher_dnsdemux_network','watcher_dnsredir_network',)
 
     def get_serializer_class(self):
         no_hyperlinks=False
@@ -763,53 +634,6 @@
 
 
 
-class UserList(XOSListCreateAPIView):
-    queryset = User.objects.select_related().all()
-    serializer_class = UserSerializer
-    id_serializer_class = UserIdSerializer
-    filter_backends = (filters.DjangoFilterBackend,)
-    filter_fields = ('id','password','last_login','email','username','firstname','lastname','phone','user_url','site','public_key','is_active','is_admin','is_staff','is_readonly','is_registering','is_appuser','login_page','created','updated','enacted','policed','backend_status','deleted','write_protect','timezone','contentproviders',)
-
-    def get_serializer_class(self):
-        no_hyperlinks=False
-        if hasattr(self.request,"QUERY_PARAMS"):
-            no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
-        if (no_hyperlinks):
-            return self.id_serializer_class
-        else:
-            return self.serializer_class
-
-    def get_queryset(self):
-        if (not self.request.user.is_authenticated()):
-            raise XOSNotAuthenticated()
-        return User.select_by_user(self.request.user)
-
-
-class UserDetail(XOSRetrieveUpdateDestroyAPIView):
-    queryset = User.objects.select_related().all()
-    serializer_class = UserSerializer
-    id_serializer_class = UserIdSerializer
-
-    def get_serializer_class(self):
-        no_hyperlinks=False
-        if hasattr(self.request,"QUERY_PARAMS"):
-            no_hyperlinks = self.request.QUERY_PARAMS.get('no_hyperlinks', False)
-        if (no_hyperlinks):
-            return self.id_serializer_class
-        else:
-            return self.serializer_class
-
-    def get_queryset(self):
-        if (not self.request.user.is_authenticated()):
-            raise XOSNotAuthenticated()
-        return User.select_by_user(self.request.user)
-
-    # update() is handled by XOSRetrieveUpdateDestroyAPIView
-
-    # destroy() is handled by XOSRetrieveUpdateDestroyAPIView
-
-
-
 class ServiceProviderList(XOSListCreateAPIView):
     queryset = ServiceProvider.objects.select_related().all()
     serializer_class = ServiceProviderSerializer
@@ -862,7 +686,7 @@
     serializer_class = ContentProviderSerializer
     id_serializer_class = ContentProviderIdSerializer
     filter_backends = (filters.DjangoFilterBackend,)
-    filter_fields = ('id','created','updated','enacted','policed','backend_register','backend_status','deleted','write_protect','lazy_blocked','no_sync','content_provider_id','name','enabled','description','serviceProvider',)
+    filter_fields = ('id','created','updated','enacted','policed','backend_register','backend_status','deleted','write_protect','lazy_blocked','no_sync','content_provider_id','name','enabled','description','serviceProvider','users',)
 
     def get_serializer_class(self):
         no_hyperlinks=False
diff --git a/xos/xos/settings.py b/xos/xos/settings.py
index e660352..3e64d15 100644
--- a/xos/xos/settings.py
+++ b/xos/xos/settings.py
@@ -120,6 +120,12 @@
 
 # Python dotted path to the WSGI application used by Django's runserver.
 WSGI_APPLICATION = 'xos.wsgi.application'
+# Default: 'csrftoken'
+CSRF_COOKIE_NAME = 'xoscsrftoken'
+# Default: 'django_language'
+LANGUAGE_COOKIE_NAME = 'xos_django_language'
+# Default: 'sessionid'
+SESSION_COOKIE_NAME = 'xossessionid'
 
 TEMPLATE_DIRS = (
     # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".