Merge branch 'AddVPNService' of github.com:jermowery/xos into AddVPNService
diff --git a/containers/synchronizer/Dockerfile b/containers/synchronizer/Dockerfile
index 8557a4d..011e8dd 100644
--- a/containers/synchronizer/Dockerfile
+++ b/containers/synchronizer/Dockerfile
@@ -29,7 +29,7 @@
 # For Observer
 RUN mkdir -p /usr/local/share /bin /etc/ansible
 
-RUN cp /tmp/xos/containers/synchronizer/conf/ansible-hosts /etc/ansible/hosts
+COPY conf/ansible-hosts /etc/ansible/hosts
 
 ADD http://phantomjs.googlecode.com/files/phantomjs-1.7.0-linux-x86_64.tar.bz2 /usr/local/share/
 
@@ -43,6 +43,6 @@
 
 
 # Supervisor
-RUN cp /tmp/xos/containers/synchronizer/conf/synchronizer.conf /etc/supervisor/conf.d/
+COPY conf/synchronizer.conf /etc/supervisor/conf.d/
 
 CMD update-ca-certificates && /usr/bin/supervisord -c /etc/supervisor/conf.d/synchronizer.conf
diff --git a/containers/xos/Dockerfile b/containers/xos/Dockerfile
index dc9a638..c70085f 100644
--- a/containers/xos/Dockerfile
+++ b/containers/xos/Dockerfile
@@ -42,7 +42,7 @@
     django-crispy-forms \
     django-encrypted-fields \
     django-extensions \
-    django-filter \
+    django-filter==0.11.0 \
     django-geoposition \
     django-ipware \
     django_rest_swagger \
diff --git a/containers/xos/Dockerfile.devel b/containers/xos/Dockerfile.devel
new file mode 100644
index 0000000..fca77f4
--- /dev/null
+++ b/containers/xos/Dockerfile.devel
@@ -0,0 +1,94 @@
+FROM       python:2.7.11
+
+# 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 \
+    django==1.7 \
+    django-bitfield \
+    django-crispy-forms \
+    django-encrypted-fields \
+    django-extensions \
+    django-filter \
+    django-geoposition \
+    django-ipware \
+    django_rest_swagger \
+    django-suit==0.3a1 \
+    django-timezones \
+    djangorestframework==2.4.4 \
+    dnslib \
+    lxml \
+    markdown \
+    netaddr \
+    pyOpenSSL \
+    psycopg2 \
+    python-ceilometerclient \
+    python-dateutil \
+    python-keyczar \
+    pygraphviz \
+    pytz \
+    pyyaml \
+    requests
+
+RUN easy_install --upgrade httplib2
+
+RUN easy_install \
+    python_gflags \
+    google_api_python_client \
+    httplib2.ca_certs_locater
+
+ADD http://code.jquery.com/jquery-1.9.1.min.js /usr/local/lib/python2.7/site-packages/suit/static/suit/js/
+
+# Install XOS
+ADD xos /opt/xos
+RUN chmod +x /opt/xos/scripts/opencloud
+RUN /opt/xos/scripts/opencloud genkeys
+
+# install Tosca engine
+RUN chmod +x /opt/xos/tosca/run.py
+RUN bash /opt/xos/tosca/install_tosca.sh
+
+EXPOSE 8000
+
+# Set environment variables.
+ENV HOME /root
+ENV PYTHONPATH /usr/local/lib/python2.7/site-packages:/usr/lib/python2.7/dist-packages
+
+# Define working directory.
+WORKDIR /opt/xos
+
+# Define default command.
+CMD update-ca-certificates && python manage.py runserver 0.0.0.0:8000 --insecure
diff --git a/containers/xos/Dockerfile.templ b/containers/xos/Dockerfile.templ
index 216ceb5..4bb201e 100644
--- a/containers/xos/Dockerfile.templ
+++ b/containers/xos/Dockerfile.templ
@@ -43,7 +43,7 @@
     django-encrypted-fields \
     django_evolution \
     django-extensions \
-    django-filter \
+    django-filter==0.11.0 \
     django-geoposition \
     django-ipware \
     django_rest_swagger \
diff --git a/containers/xos/Makefile b/containers/xos/Makefile
index 833046b..4e0d40a 100644
--- a/containers/xos/Makefile
+++ b/containers/xos/Makefile
@@ -6,10 +6,13 @@
 NO_DOCKER_CACHE?=false
 
 .PHONY: build
-build: ; make -C ../../xos/configurations/common -f Makefile.cloudlab; docker build --no-cache=${NO_DOCKER_CACHE} --rm -t ${IMAGE_NAME} . 
+build: ; make -C ../../xos/configurations/common -f Makefile.cloudlab; docker build --no-cache=${NO_DOCKER_CACHE} --rm -t ${IMAGE_NAME} .
 
 .PHONY: custom
-custom: ; cat Dockerfile.templ | sed -e "s|XOS_GIT_REPO|${XOS_GIT_REPO}|g" -e "s|XOS_GIT_BRANCH|${XOS_GIT_BRANCH}|g" | docker build --no-cache=${NO_DOCKER_CACHE} -
+custom: ; cat Dockerfile.templ | sed -e "s|XOS_GIT_REPO|${XOS_GIT_REPO}|g" -e "s|XOS_GIT_BRANCH|${XOS_GIT_BRANCH}|g" | docker build --no-cache=${NO_DOCKER_CACHE} --rm -t ${IMAGE_NAME} -
+
+.PHONY: devel
+devel: ; cd ../..; ls; docker build -f containers/xos/Dockerfile.devel --no-cache=${NO_DOCKER_CACHE} --rm -t ${IMAGE_NAME} .
 
 .PHONY: run
 run: ; docker run -d --name ${CONTAINER_NAME} -p 80:8000 -v /usr/local/share/ca-certificates:/usr/local/share/ca-certificates:ro ${IMAGE_NAME}
diff --git a/xos/configurations/bash/Dockerfile.bash b/xos/configurations/bash/Dockerfile.bash
deleted file mode 100644
index fc7177b..0000000
--- a/xos/configurations/bash/Dockerfile.bash
+++ /dev/null
@@ -1,13 +0,0 @@
-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/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
-
-#CMD ["/bin/bash"]
diff --git a/xos/configurations/bash/Makefile b/xos/configurations/bash/Makefile
deleted file mode 100644
index a668a55..0000000
--- a/xos/configurations/bash/Makefile
+++ /dev/null
@@ -1,11 +0,0 @@
-MYIP:=$(shell hostname -i)
-
-test: common_cloudlab
-	rm ../../xos_configuration/*
-	cp ../common/xos_common_config ../../xos_configuration/
-	cat ../common/Dockerfile.common Dockerfile.bash > Dockerfile
-	cd ../../..; sudo docker build -t xos -f xos/configurations/bash/Dockerfile .
-	sudo docker run -i --tty --add-host="ctl:$(MYIP)" -p 9999:8000 xos
-
-common_cloudlab:
-	make -C ../common -f Makefile.cloudlab
diff --git a/xos/configurations/bash/Makefile.inside b/xos/configurations/bash/Makefile.inside
deleted file mode 100644
index 4ec8328..0000000
--- a/xos/configurations/bash/Makefile.inside
+++ /dev/null
@@ -1,7 +0,0 @@
-all: setup_xos
-
-setup_xos:
-	bash /opt/xos/scripts/docker_setup_xos
-	python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/fixtures.yaml
-	python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/base.yaml
-	python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/nodes.yaml
diff --git a/xos/configurations/bash/README b/xos/configurations/bash/README
deleted file mode 100644
index 83322a0..0000000
--- a/xos/configurations/bash/README
+++ /dev/null
@@ -1,5 +0,0 @@
-This configuration launches XOS on Cloudlab, leaving the user in an interactive bash session.
-
-The django UI is not started automatically. To start it, execute the following commands from the bash session:
-   cd /opt/xos
-   scripts/opencloud runserver
diff --git a/xos/configurations/common/Dockerfile.common b/xos/configurations/common/Dockerfile.common
index e2c4bbb..8bfd813 100644
--- a/xos/configurations/common/Dockerfile.common
+++ b/xos/configurations/common/Dockerfile.common
@@ -35,7 +35,7 @@
 RUN pip install djangorestframework==2.4.4
 RUN pip install markdown  # Markdown support for the browseable API.
 RUN pip install pyyaml    # YAML content-type support.
-RUN pip install django-filter  # Filtering support
+RUN pip install django-filter==0.11.0  # Filtering support
 RUN pip install lxml  # XML manipulation library
 RUN pip install netaddr # IP Addr library
 RUN pip install pytz
diff --git a/xos/configurations/common/Makefile.cloudlab b/xos/configurations/common/Makefile.cloudlab
index 4646fd6..7ab8a54 100644
--- a/xos/configurations/common/Makefile.cloudlab
+++ b/xos/configurations/common/Makefile.cloudlab
@@ -3,36 +3,39 @@
 $(error MYFLATLANIF is empty)
 endif
 MYFLATLANIP:=$(shell ifconfig $(MYFLATLANIF) | grep "inet addr" | awk -F: '{print $$2}' | awk '{print $$1}' )
+SETUPDIR:=../setup
 
-all: prereqs admin-openrc flat_name nodes_yaml public_key private_key ceilometer_url node_key
+all: prereqs admin-openrc flat_name nodes_yaml public_key private_key ceilometer_url other_keys
 
 prereqs:
 	make -f Makefile.prereqs
+	mkdir -p $(SETUPDIR)
 
 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
+	sudo cat /root/setup/admin-openrc.sh > $(SETUPDIR)/admin-openrc.sh
+	sudo cat /root/setup/settings > $(SETUPDIR)/controller_settings
+	echo 'CONTROLLER_FLAT_LAN_IP=$(MYFLATLANIP)' >> $(SETUPDIR)/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
-	[ -s flat_net_name ] # throw error if flat_net_name is empty
+	bash -c "source $(SETUPDIR)/admin-openrc.sh ; neutron net-list" |grep flat|awk '{printf "%s",$$4}' > $(SETUPDIR)/flat_net_name
+	[ -s $(SETUPDIR)/flat_net_name ] # throw error if flat_net_name is empty
 
 nodes_yaml:
-	bash ./make-nodes-yaml.sh
+	export SETUPDIR=$(SETUPDIR); bash ./make-nodes-yaml.sh 
 
 ceilometer_url:
-	echo http://`hostname -i`/xosmetering/ > ceilometer_url
+	echo http://`hostname -i`/xosmetering/ > $(SETUPDIR)/ceilometer_url
 
 public_key: ~/.ssh/id_rsa.pub
-	cp ~/.ssh/id_rsa.pub .
+	cp ~/.ssh/id_rsa.pub $(SETUPDIR)
 
 private_key: ~/.ssh/id_rsa
-	cp ~/.ssh/id_rsa .
+	cp ~/.ssh/id_rsa $(SETUPDIR)
 
 ~/.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
+other_keys: public_key private_key
+	sudo cat /root/setup/id_rsa > $(SETUPDIR)/node_key
+	sudo cat /root/setup/id_rsa.pub > $(SETUPDIR)/node_key.pub
+	sudo cp $(SETUPDIR)/id_rsa.pub $(SETUPDIR)/padmin_public_key
diff --git a/xos/configurations/common/Makefile.devstack b/xos/configurations/common/Makefile.devstack
index f969b3d..2764b28 100644
--- a/xos/configurations/common/Makefile.devstack
+++ b/xos/configurations/common/Makefile.devstack
@@ -1,38 +1,40 @@
 # This shouldn't be hardcoded
 DEVSTACK_ROOT:=~/devstack
+SETUPDIR:=../setup
 
 all: prereqs admin-openrc flat_name nodes_yaml public_key private_key ceilometer_url node_key net_fix
 
 prereqs:
 	make -f Makefile.prereqs
 	sudo pip install httpie --upgrade
+	mkdir -p $(SETUPDIR)
 
 admin-openrc:
-	bash ./devstack-creds.sh $(DEVSTACK_ROOT) > admin-openrc.sh
-	touch controller_settings
+	bash ./devstack-creds.sh $(DEVSTACK_ROOT) > $(SETUPDIR)/admin-openrc.sh
+	touch $(SETUPDIR)/controller_settings
 
 flat_name:
-	echo private|tr -d '\n' > flat_net_name
+	echo private|tr -d '\n' > $(SETUPDIR)/flat_net_name
 	bash -c "source admin-openrc.sh; openstack network set --share private"
 
 nodes_yaml:
-	bash ./make-nodes-yaml.sh
+	bash ./make-nodes-yaml.sh > $(SETUPDIR)/nodes.yaml
 
 ceilometer_url:
-	echo http://`hostname -i`/xosmetering/ > ceilometer_url
+	echo http://`hostname -i`/xosmetering/ > $(SETUPDIR)/ceilometer_url
 
 public_key: ~/.ssh/id_rsa.pub
-	cp ~/.ssh/id_rsa.pub .
+	cp ~/.ssh/id_rsa.pub $(SETUPDIR)
 
 private_key: ~/.ssh/id_rsa
-	cp ~/.ssh/id_rsa .
+	cp ~/.ssh/id_rsa $(SETUPDIR)
 
 ~/.ssh/id_rsa.pub:
 	cat /dev/zero | ssh-keygen -q -N ""
 
 node_key:
-	sudo cat ~/.ssh/id_rsa > node_key
-	sudo cat ~/.ssh/id_rsa.pub > node_key.pub
+	sudo cat ~/.ssh/id_rsa > $(SETUPDIR)/node_key
+	sudo cat ~/.ssh/id_rsa.pub > $(SETUPDIR)/node_key.pub
 
 net_fix:
 	sudo devstack/net-fix.sh
diff --git a/xos/configurations/common/Makefile.opencloud b/xos/configurations/common/Makefile.opencloud
index 8bc5b93..8cf9f29 100644
--- a/xos/configurations/common/Makefile.opencloud
+++ b/xos/configurations/common/Makefile.opencloud
@@ -1,36 +1,40 @@
-MYFLATLANIP:=$(shell hostname -i)
+MYFLATLANIF:=$(shell netstat -i |grep "flat"|awk '{print $$1}' )
+MYFLATLANIP:=$(shell ifconfig $(MYFLATLANIF) | grep "inet addr" | awk -F: '{print $$2}' | awk '{print $$1}' )
+SETUPDIR:=../setup
 
-all: prereqs admin-openrc flat_name nodes_yaml public_key private_key ceilometer_url node_key images
+all: prereqs admin-openrc flat_name nodes_yaml public_key private_key ceilometer_url node_key
 
 prereqs:
 	make -f Makefile.prereqs
+	mkdir -p $(SETUPDIR)
 
 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
+	sudo cat /root/setup/admin-openrc.sh > $(SETUPDIR)/admin-openrc.sh
+	sudo cat /root/setup/settings > $(SETUPDIR)/controller_settings
+	echo 'CONTROLLER_FLAT_LAN_IP=$(MYFLATLANIP)' >> $(SETUPDIR)/controller_settings
 
 flat_name:
-	echo nat-net|tr -d '\n' > flat_net_name
+	sudo bash -c "source /root/setup/admin-openrc.sh ; neutron net-list" |grep flat|awk '{printf "%s",$$4}' > $(SETUPDIR)/flat_net_name
+	[ -s $(SETUPDIR)/flat_net_name ] # throw error if flat_net_name is empty
 
 nodes_yaml:
-	bash ./make-nodes-yaml.sh
+	bash ./make-nodes-yaml.sh > $(SETUPDIR)/nodes.yaml
 
 ceilometer_url:
-	echo http://`hostname -i`/xosmetering/ > ceilometer_url
+	echo http://`hostname -i`/xosmetering/ > $(SETUPDIR)/ceilometer_url
 
 public_key: ~/.ssh/id_rsa.pub
-	cp ~/.ssh/id_rsa.pub .
+	cp ~/.ssh/id_rsa.pub $(SETUPDIR)
 
 private_key: ~/.ssh/id_rsa
-	cp ~/.ssh/id_rsa .
+	cp ~/.ssh/id_rsa $(SETUPDIR)
 
 ~/.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
+	sudo cat /root/setup/id_rsa > $(SETUPDIR)/node_key
+	sudo cat /root/setup/id_rsa.pub > $(SETUPDIR)/node_key.pub
 
 images:
 	source admin-openrc.sh; glance image-show trusty-server-multi-nic || glance image-create --name trusty-server-multi-nic --disk-format qcow2 --file /proj/xos-PG0/acb/images/trusty-server-multi-nic.img --container-format bare
diff --git a/xos/configurations/common/Makefile.prereqs b/xos/configurations/common/Makefile.prereqs
index 0325224..fce51be 100644
--- a/xos/configurations/common/Makefile.prereqs
+++ b/xos/configurations/common/Makefile.prereqs
@@ -3,11 +3,14 @@
 ifeq ($(UBUNTU),0)
 
 # ******************* apt-based distros ***************************
-prereqs: /usr/bin/http docker
+prereqs: /usr/bin/http docker /usr/bin/curl /usr/local/bin/docker-compose
 
-/usr/bin/http: 
+/usr/bin/http:
 	sudo apt-get -y install httpie
 
+/usr/bin/curl:
+	sudo apt-get -y install curl
+
 docker:
 	which docker > /dev/null || wget -qO- https://get.docker.com/ | sh
 	sudo usermod -aG docker $(shell whoami)
@@ -18,11 +21,11 @@
 
 # (untested / work-in-progress)
 
-prereqs: /usr/bin/pip /usr/bin/http docker
+prereqs: /usr/bin/pip /usr/bin/http docker /usr/local/bin/docker-compose
 
 /usr/bin/pip:
 	curl "https://bootstrap.pypa.io/get-pip.py" -o "get-pip.py"
-	sudo python ./get-pip.py     
+	sudo python ./get-pip.py
 
 docker:
 	which docker > /dev/null || wget -qO- https://get.docker.com/ | sh
@@ -32,3 +35,7 @@
 	sudo pip install httpie
 
 endif
+
+/usr/local/bin/docker-compose:
+	sudo bash -c "curl -L https://github.com/docker/compose/releases/download/1.5.2/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose"
+	sudo chmod +x /usr/local/bin/docker-compose
diff --git a/xos/configurations/common/base.yaml b/xos/configurations/common/base.yaml
index 6b6ae34..3638dd9 100644
--- a/xos/configurations/common/base.yaml
+++ b/xos/configurations/common/base.yaml
@@ -29,7 +29,7 @@
               node: trusty-server-multi-nic
               relationship: tosca.relationships.SupportsImage
 
-    Backend:
+    CloudLab:
       type: tosca.nodes.Controller
       requirements:
           - deployment:
@@ -61,7 +61,7 @@
                relationship: tosca.relationships.SiteDeployment
                requirements:
                    - controller:
-                       node: Backend
+                       node: CloudLab
                        relationship: tosca.relationships.UsesController
 
     Public shared IPv4:
diff --git a/xos/configurations/common/make-nodes-yaml.sh b/xos/configurations/common/make-nodes-yaml.sh
index eafab4a..1c0003a 100644
--- a/xos/configurations/common/make-nodes-yaml.sh
+++ b/xos/configurations/common/make-nodes-yaml.sh
@@ -1,4 +1,4 @@
-FN=nodes.yaml
+FN=$SETUPDIR/nodes.yaml
 
 rm -f $FN
 
@@ -18,7 +18,7 @@
         type: tosca.nodes.Site
 EOF
 
-NODES=$( bash -c "source ./admin-openrc.sh ; nova hypervisor-list" |grep enabled|awk '{print $4}' )
+NODES=$( bash -c "source $SETUPDIR/admin-openrc.sh ; nova hypervisor-list" |grep enabled|awk '{print $4}' )
 I=0
 for NODE in $NODES; do
     echo $NODE
diff --git a/xos/configurations/common/xos_common_config b/xos/configurations/common/xos_common_config
index df30b54..b06098e 100644
--- a/xos/configurations/common/xos_common_config
+++ b/xos/configurations/common/xos_common_config
@@ -33,7 +33,7 @@
 
 [observer]
 pretend=False
-backoff_disabled=False
+backoff_disabled=True
 images_directory=/opt/xos/images
 dependency_graph=/opt/xos/model-deps
 logfile=/var/log/xos_backend.log
diff --git a/xos/configurations/cord/Makefile b/xos/configurations/cord/Makefile
index 0dc7a73..c95d9dd 100644
--- a/xos/configurations/cord/Makefile
+++ b/xos/configurations/cord/Makefile
@@ -1,20 +1,25 @@
+SETUPDIR:=../setup
 MYIP:=$(shell hostname -i)
-RUNNING_CONTAINER:=$(shell sudo docker ps|grep "xos"|awk '{print $$NF}')
-LAST_CONTAINER=$(shell sudo docker ps -l -q)
 
-cord: common_cloudlab ceilometer_dashboard virtualbng_json vtn_network_cfg_json
-	if [ -a ../../xos_configuration/* ]; then rm ../../xos_configuration/*; fi
-	echo "# Autogenerated -- do not edit" > Dockerfile
-	cat ../common/Dockerfile.common Dockerfile.cord >> Dockerfile
-	cp ../common/xos_common_config ../../xos_configuration/
-	cp ./xos_cord_config ../../xos_configuration/
-	cd ../../..; sudo docker build -t xos -f xos/configurations/cord/Dockerfile .
-	sudo docker run -d --add-host="ctl:$(MYIP)" -p 9999:8000 xos
+cloudlab: common_cloudlab cord
+
+devstack: upgrade_pkgs common_devstack devstack_net_fix cord
+
+cord: ceilometer_dashboard virtualbng_json vtn_network_cfg_json
+	sudo MYIP=$(MYIP) docker-compose up -d
 	bash ../common/wait_for_xos.sh
+	sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/fixtures.yaml
+	sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/base.yaml
+	sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/nodes.yaml
+	sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/cord/cord.yaml
+	sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/cord/ceilometer.yaml
 
 common_cloudlab:
 	make -C ../common -f Makefile.cloudlab
 
+common_devstack:
+	make -C ../common -f Makefile.devstack
+
 ceilometer_dashboard:
 	#NOTE: The below dashboard install scripts assume
 	#clouldlab openstack environment created using "OpenStack" profile
@@ -22,19 +27,22 @@
 	bash install_ceilometer_patch.sh
 
 virtualbng_json:
-	bash make-virtualbng-json.sh
+	export SETUPDIR=$(SETUPDIR); bash make-virtualbng-json.sh
 
 vtn_network_cfg_json:
-	bash make-vtn-networkconfig-json.sh
+	export SETUPDIR=$(SETUPDIR); bash make-vtn-networkconfig-json.sh
 
 stop:
-	sudo docker stop $(RUNNING_CONTAINER)
+	sudo MYIP=$(MYIP) docker-compose stop
+
+rm:
+	sudo MYIP=$(MYIP) docker-compose rm
 
 showlogs:
-	sudo docker logs $(LAST_CONTAINER)
+	sudo MYIP=$(MYIP) docker-compose logs
 
-enter:
-	sudo docker exec -t -i $(RUNNING_CONTAINER) bash
+ps:
+	sudo MYIP=$(MYIP) docker-compose ps
 
 dataplane: etc_hosts
 	cd dataplane; ./gen-inventory.sh > hosts
@@ -55,7 +63,14 @@
 	# reboot the vBNG ONOS
 	cd dataplane; ansible -i hosts onos_vbng -m shell -s -a "docker restart ONOS"
 
-cleanup:
+cleanup: stop rm
 	cd dataplane; ./cleanup.sh
-	bash -c "source ../common/admin-openrc.sh; nova list --all-tenants; neutron net-list"
-	echo "Don't forget to clean up containers"
+	bash -c "source ../setup/admin-openrc.sh; nova list --all-tenants; neutron net-list"
+	echo "Don't forget to clean up vCPE containers"
+
+devstack_net_fix:
+	sudo ../common/devstack/net-fix.sh
+	sudo bash -c "source ../setup/admin-openrc.sh; neutron subnet-update private-subnet --dns-nameservers list=true 8.8.8.8 8.8.4.4"
+
+upgrade_pkgs:
+	sudo pip install httpie --upgrade
diff --git a/xos/configurations/cord/README-VTN.md b/xos/configurations/cord/README-VTN.md
index 9827b0e..38fc2b4 100644
--- a/xos/configurations/cord/README-VTN.md
+++ b/xos/configurations/cord/README-VTN.md
@@ -41,35 +41,26 @@
     emacs /usr/local/lib/python2.7/dist-packages/networking_onos/plugins/ml2/driver.py
         hard-code self.onos_path and self.onos_auth
     
-Compute node that has the ONOS Container
+Compute nodes and nm nodes:
 
-    # we need NAT rule so the neutron vtn plugin can talk to onos
-    # change 172.17.0.2 to the IP address for the ONOS container (use "docker inspect")
-    iptables -t nat -A PREROUTING -i br-ex -p tcp --dport 8101 -j DNAT --to-destination 172.17.0.2
-    iptables -t nat -A PREROUTING -i br-ex -p tcp --dport 8181 -j DNAT --to-destination 172.17.0.2
-    iptables -t nat -A PREROUTING -i br-ex -p tcp --dport 6653 -j DNAT --to-destination 172.17.0.2
-    
-Compute nodes (all of them):
-
-    systemctl stop neutron-plugin-openvswitch-agent
-    emacs /usr/share/openvswitch/scripts/ovs-ctl
-        update settings as per vtn docs to make port 6640 visible
-    service openvswitch-switch restart
-    ovs-vsctl del-br br-int
-
-nm node:
-
-    # neutron-dhcp-agent causes VTN app to throw port errors, because XOS uses --no-gateway
-    systemctl stop neutron-dhcp-agent.service 
+    cd xos/configurations/cord/dataplane
+    ./generate-bm.sh > hosts-bm
+    ansible-playbook -i hosts-bm dataplane-vtn.yaml
+    # the playbook will:
+    #  1) turn off neutron openvswitch-agent
+    #  2) set openvswitch to listen on port 6641
+    #  3) restart openvswitch
+    #  4) delete any existing br-int bridge
+    #  5) [nm only] turn off neutron-dhcp-agent
 
 VTN doesn't seem to like cloudlab's networks (flat-net-1, ext-net, etc). You might have to delete them all. I've placed a script in xos/scripts/ called destroy-all-networks.sh that will automate tearing down all of cloudlab's neutron networks.
 
 For development, I suggest using the bash configuration (remember to start the ONOS observer manually) so that 
 there aren't a bunch of preexisting Neutron networks and nova instances to get in the way. 
 
-Problems:
-* If you have more than one compute node, then the node that isn't running ONOS VTN will report as incomplete in VTN. This is because the openvswitch is trying to contact VTN on 172.17.0.2:6653. 
-
 Notes:
+* I've configured the OpenvSwitch switches to use port 6641 instead of port 6640. This is because the VTN app listens on 6640
+itself, and since we're running it in docker 'host' networking mode now, it would conflict with an Openvswitch that was
+also listening on 6640.
 * Adding use_vtn=True to the [networking] section in the XOS config file has two effects: 1) it sets the gateway in sync_controller_networks, and 2) it disables automatic creation of nat-net for new slices. This is because VTN will fail if there is no gateway on a network, and because we don't have nat-net under the VTN configuration.
 * When using of-vfctl to look at flow rules, if you get a protocol error, try "ovs-ofctl show -O OpenFlow13 br-int "
diff --git a/xos/configurations/cord/dataplane/cleanup.sh b/xos/configurations/cord/dataplane/cleanup.sh
index 721f054..9860de7 100755
--- a/xos/configurations/cord/dataplane/cleanup.sh
+++ b/xos/configurations/cord/dataplane/cleanup.sh
@@ -13,7 +13,7 @@
   neutron net-delete $NETWORK
 }
 
-source ../../common/admin-openrc.sh
+source ../../setup/admin-openrc.sh
 
 echo "Deleting VMs"
 # Delete all VMs
diff --git a/xos/configurations/cord/dataplane/dataplane-vtn.yaml b/xos/configurations/cord/dataplane/dataplane-vtn.yaml
new file mode 100644
index 0000000..f6561b5
--- /dev/null
+++ b/xos/configurations/cord/dataplane/dataplane-vtn.yaml
@@ -0,0 +1,31 @@
+---
+- hosts: baremetal:nm
+
+  user: root
+  sudo: no
+  tasks:
+  - name: stop neutron openvswitch agent
+    service: name=neutron-plugin-openvswitch-agent state=stopped
+
+  - name: Update openvswitch config
+    lineinfile:
+      dest=/usr/share/openvswitch/scripts/ovs-ctl
+      insertafter="set ovsdb-server.*DB_FILE.*"
+      regexp=".*set.*--remote=ptcp.*"
+      line="        set \"$@\" --remote=ptcp:6641"
+      state=present
+
+  - name: Restart openvswitch
+    service: name=openvswitch-switch state=restarted
+
+  - name: Delete br-int
+    shell: ovs-vsctl show | grep -i br-int > /dev/null && ovs-vsctl del-br br-int
+    ignore_errors: yes
+
+- hosts: nm
+
+  user: root
+  sudo: no
+  tasks:
+  - name: stop neutron dhcp agent
+    service: name=neutron-dhcp-agent state=stopped
diff --git a/xos/configurations/cord/dataplane/gen-etc-hosts.sh b/xos/configurations/cord/dataplane/gen-etc-hosts.sh
index ce98731..6c07ef9 100755
--- a/xos/configurations/cord/dataplane/gen-etc-hosts.sh
+++ b/xos/configurations/cord/dataplane/gen-etc-hosts.sh
@@ -1,7 +1,7 @@
 #!/bin/bash
 # set -x
 
-source ../../common/admin-openrc.sh
+source ../../setup/admin-openrc.sh
 
 get_ip () {
     LABEL=$1
diff --git a/xos/configurations/cord/dataplane/gen-inventory.sh b/xos/configurations/cord/dataplane/gen-inventory.sh
index 590376d..74a5ac8 100755
--- a/xos/configurations/cord/dataplane/gen-inventory.sh
+++ b/xos/configurations/cord/dataplane/gen-inventory.sh
@@ -1,7 +1,7 @@
 #!/bin/bash
 # set -x
 
-source ../../common/admin-openrc.sh
+source ../../setup/admin-openrc.sh
 
 get_ip () {
     LABEL=$1
diff --git a/xos/configurations/cord/dataplane/generate-bm.sh b/xos/configurations/cord/dataplane/generate-bm.sh
index 25f6fa5..f9b8787 100755
--- a/xos/configurations/cord/dataplane/generate-bm.sh
+++ b/xos/configurations/cord/dataplane/generate-bm.sh
@@ -1,4 +1,4 @@
-source ../../common/admin-openrc.sh
+source ../../setup/admin-openrc.sh
 
 get_ip () {
     LABEL=$1
@@ -9,7 +9,7 @@
 GRENAMES=()
 BM_IPS=()
 
-NODES=`sudo bash -c "source /root/setup/admin-openrc.sh ; nova hypervisor-list" |grep cloudlab|awk '{print $4}'`
+NODES=`sudo bash -c "source ../../setup/admin-openrc.sh ; nova hypervisor-list" |grep enabled|awk '{print $4}'`
 I=1
 for NODE in $NODES; do
     BM_SSH_IP=`getent hosts $NODE | awk '{ print $1 }'`
@@ -29,9 +29,16 @@
 
 echo switch_volt ansible_ssh_host=$( get_ip mysite_volt flat-lan-1-net) grenames=\"$GRE_NAMES\" bm_ips=\"$BM_IPS\"
 
+NM=`grep "^nm" /root/setup/fqdn.map | awk '{ print $2 }'`
+echo "nm1 ansible_ssh_host=$NM ansible_ssh_private_key_file=/root/.ssh/id_rsa"
+
 echo "[baremetal]"
 I=1
 for NODE in $NODES; do
     echo bm$I
     I=$((I+1))
 done
+
+# now for the network management node
+echo "[nm]"
+echo "nm1"
diff --git a/xos/configurations/cord/docker-compose.yml b/xos/configurations/cord/docker-compose.yml
new file mode 100644
index 0000000..e09dc1a
--- /dev/null
+++ b/xos/configurations/cord/docker-compose.yml
@@ -0,0 +1,95 @@
+xos_db:
+    image: xosproject/xos-postgres
+    expose:
+        - "5432"
+
+xos_synchronizer_openstack:
+    command: bash -c "sleep 120 ; python /opt/xos/xos-observer.py"
+    image: xosproject/xos-synchronizer-openstack
+    labels:
+        org.xosproject.kind: synchronizer
+        org.xosproject.target: openstack
+    links:
+        - xos_db
+    extra_hosts:
+        - ctl:${MYIP}
+    volumes:
+        - ../common/xos_common_config:/opt/xos/xos_configuration/xos_common_config:ro
+        - ./xos_cord_config:/opt/xos/xos_configuration/xos_cord_config:ro
+        - ../setup:/root/setup:ro
+
+xos_synchronizer_onos:
+    image: xosproject/xos-synchronizer-openstack
+    command: bash -c "sleep 120 ; python /opt/xos/observers/onos/onos-observer.py -C /opt/xos/observers/onos/onos_observer_config"
+    labels:
+        org.xosproject.kind: synchronizer
+        org.xosproject.target: onos
+    links:
+        - xos_db
+    extra_hosts:
+        - ctl:${MYIP}
+    volumes:
+        - ../setup/id_rsa:/opt/xos/observers/onos/onos_key:ro  # private key
+
+xos_synchronizer_vcpe:
+    image: xosproject/xos-synchronizer-openstack
+    #command: /usr/bin/supervisord -c /opt/xos/observers/vcpe/supervisor/vcpe-observer.conf
+    command: bash -c "sleep 120 ; python /opt/xos/observers/vcpe/vcpe-observer.py -C /opt/xos/observers/vcpe/vcpe_observer_config"
+    labels:
+        org.xosproject.kind: synchronizer
+        org.xosproject.target: vcpe
+    links:
+        - xos_db
+    extra_hosts:
+        - ctl:${MYIP}
+    volumes:
+        - ../setup/id_rsa:/opt/xos/observers/vcpe/vcpe_private_key:ro  # private key
+        - ../setup:/root/setup:ro
+        
+xos_synchronizer_vbng:
+    image: xosproject/xos-synchronizer-openstack
+    command: bash -c "sleep 120 ; python /opt/xos/observers/vbng/vbng-observer.py -C /opt/xos/observers/vbng/vbng_observer_config"
+    labels:
+        org.xosproject.kind: synchronizer
+        org.xosproject.target: vbng
+    links:
+        - xos_db
+    extra_hosts:
+        - ctl:${MYIP}
+
+xos_synchronizer_monitoring_channel:
+    image: xosproject/xos-synchronizer-openstack
+    #command: /usr/bin/supervisord -c /opt/xos/observers/monitoring_channel/supervisor/monitoring_channel_observer.conf
+    command: bash -c "sleep 120 ; python /opt/xos/observers/monitoring_channel/monitoring_channel_observer.py -C /opt/xos/observers/monitoring_channel/monitoring_channel_observer_config"
+    labels:
+        org.xosproject.kind: synchronizer
+        org.xosproject.target: monitoring_channel
+    links:
+        - xos_db
+    extra_hosts:
+        - ctl:${MYIP}
+    volumes:
+        - ../setup/id_rsa:/opt/xos/observers/monitoring_channel/monitoring_channel_private_key:ro  # private key
+
+
+# FUTURE
+#xos_swarm_synchronizer:
+#    image: xosproject/xos-swarm-synchronizer
+#    labels:
+#        org.xosproject.kind: synchronizer
+#        org.xosproject.target: swarm
+
+xos:
+    image: xosproject/xos
+    command: python /opt/xos/manage.py runserver 0.0.0.0:8000 --insecure --makemigrations
+    ports:
+        - "9999:8000"
+    links:
+        - xos_db
+    volumes:
+      - ../setup:/root/setup:ro
+      - ../common/xos_common_config:/opt/xos/xos_configuration/xos_common_config:ro
+      - ./xos_cord_config:/opt/xos/xos_configuration/xos_cord_config:ro
+      - ../setup/id_rsa.pub:/opt/xos/observers/onos/onos_key.pub:ro
+      - ../setup/id_rsa.pub:/opt/xos/observers/vcpe/vcpe_public_key:ro
+      - ../setup/id_rsa.pub:/opt/xos/observers/monitoring_channel/monitoring_channel_public_key:ro
diff --git a/xos/configurations/cord/make-virtualbng-json.sh b/xos/configurations/cord/make-virtualbng-json.sh
index 2d6501d..8eb971b 100644
--- a/xos/configurations/cord/make-virtualbng-json.sh
+++ b/xos/configurations/cord/make-virtualbng-json.sh
@@ -1,4 +1,4 @@
-FN=virtualbng.json
+FN=$SETUPDIR/virtualbng.json
 
 rm -f $FN
 
@@ -14,7 +14,7 @@
     "hosts" : {
 EOF
 
-NODES=$( sudo bash -c "source /root/setup/admin-openrc.sh ; nova hypervisor-list" |grep enabled|awk '{print $4}' )
+NODES=$( sudo bash -c "source $SETUPDIR/admin-openrc.sh ; nova hypervisor-list" |grep enabled|awk '{print $4}' )
 
 NODECOUNT=0
 for NODE in $NODES; do
diff --git a/xos/configurations/cord/make-vtn-networkconfig-json.sh b/xos/configurations/cord/make-vtn-networkconfig-json.sh
index 918674a..c4506cc 100755
--- a/xos/configurations/cord/make-vtn-networkconfig-json.sh
+++ b/xos/configurations/cord/make-vtn-networkconfig-json.sh
@@ -1,4 +1,4 @@
-FN=vtn-network-cfg.json
+FN=$SETUPDIR/vtn-network-cfg.json
 
 rm -f $FN
 
@@ -10,7 +10,7 @@
                 "nodes" : [
 EOF
 
-NODES=$( sudo bash -c "source /root/setup/admin-openrc.sh ; nova hypervisor-list" |grep cloudlab|awk '{print $4}' )
+NODES=$( sudo bash -c "source $SETUPDIR/admin-openrc.sh ; nova hypervisor-list" |grep enabled|awk '{print $4}' )
 
 NODECOUNT=0
 for NODE in $NODES; do
@@ -27,7 +27,7 @@
                     {
                       "hostname": "$NODE",
                       "ovsdbIp": "$NODEIP",
-                      "ovsdbPort": "6640",
+                      "ovsdbPort": "6641",
                       "bridgeId": "of:000000000000000$I"
 EOF
     if [[ "$I" -lt "$NODECOUNT" ]]; then
@@ -38,7 +38,7 @@
 done
 
 # get the openstack admin password and username
-source /root/setup/admin-openrc.sh
+source $SETUPDIR/admin-openrc.sh
 
 HOSTNAME=`hostname`
 NEUTRONIP=`getent hosts $HOSTNAME | awk '{ print $1 }'`
@@ -46,7 +46,7 @@
 
 cat >> $FN <<EOF
                 ]
-            }

+            }
         },
         "org.onosproject.openstackswitching" : {
             "openstackswitching" : {
diff --git a/xos/configurations/devel/Dockerfile.devel b/xos/configurations/devel/Dockerfile.devel
deleted file mode 100644
index 8cb8953..0000000
--- a/xos/configurations/devel/Dockerfile.devel
+++ /dev/null
@@ -1,15 +0,0 @@
-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/nodes.yaml /opt/xos/configurations/commmon/
-ADD xos/configurations/common/id_rsa.pub /root/setup/padmin_public_key
-ADD xos/configurations/common/id_rsa /opt/xos/observers/helloworldservice_complete/helloworldservice_private_key
-ADD xos/configurations/common/id_rsa /opt/xos/observers/vpn/vpn_private_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
-
-#CMD ["/bin/bash"]
diff --git a/xos/configurations/devel/Makefile b/xos/configurations/devel/Makefile
index 60a4cdd..5112311 100644
--- a/xos/configurations/devel/Makefile
+++ b/xos/configurations/devel/Makefile
@@ -1,21 +1,14 @@
 MYIP:=$(shell hostname -i)
-RUNNING_CONTAINER:=$(shell sudo docker ps|grep "xos"|awk '{print $$NF}')
-LAST_CONTAINER=$(shell sudo docker ps -l -q)
 
 cloudlab: common_cloudlab xos
 
-devstack: common_devstack xos
-
-opencloud: common_opencloud xos
+devstack: upgrade_pkgs common_devstack devstack_net_fix xos
 
 xos:
-	if [ -a ../../xos_configuration/* ]; then rm ../../xos_configuration/*; fi
-	cp ../common/xos_common_config ../../xos_configuration/
-	echo "# Autogenerated -- do not edit" > Dockerfile
-	cat ../common/Dockerfile.common Dockerfile.devel >> Dockerfile
-	cd ../../..; sudo docker build -t xosproject/xos-devel -f xos/configurations/devel/Dockerfile .
-	sudo docker run -d --add-host="ctl:$(MYIP)" -p 9999:8000 xosproject/xos-devel
+	sudo MYIP=$(MYIP) docker-compose up -d
 	bash ../common/wait_for_xos.sh
+	sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/base.yaml
+	sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/nodes.yaml
 
 common_cloudlab:
 	make -C ../common -f Makefile.cloudlab
@@ -23,20 +16,27 @@
 common_devstack:
 	make -C ../common -f Makefile.devstack
 
-common_opencloud:
-	make -C ../common -f Makefile.opencloud
-
 stop:
-	sudo docker stop $(RUNNING_CONTAINER)
+	sudo MYIP=$(MYIP) docker-compose stop
 
 showlogs:
-	sudo docker logs $(LAST_CONTAINER)
+	sudo MYIP=$(MYIP) docker-compose logs
 
-enter:
-	sudo docker exec -t -i $(RUNNING_CONTAINER) bash
+rm: stop
+	sudo MYIP=$(MYIP) docker-compose rm
 
-clean:
-	/proj/xos-PG0/acb/cleanup.sh
-	sudo docker stop $(docker ps -a -q)
-	sudo docker rm $(docker ps -a -q)
-	sudo docker rmi $(docker images -f "dangling=true" -q)
+ps:
+	sudo MYIP=$(MYIP) docker-compose ps
+
+enter-xos:
+	sudo docker exec -it devel_xos_1 bash
+
+enter-synchronizer:
+	sudo docker exec -it devel_xos_synchronizer_openstack_1 bash
+
+devstack_net_fix:
+	sudo ../common/devstack/net-fix.sh
+	sudo bash -c "source ../setup/admin-openrc.sh; neutron subnet-update private-subnet --dns-nameservers list=true 8.8.8.8 8.8.4.4"
+
+upgrade_pkgs:
+	sudo pip install httpie --upgrade
diff --git a/xos/configurations/devel/Makefile.inside b/xos/configurations/devel/Makefile.inside
deleted file mode 100644
index fb9433c..0000000
--- a/xos/configurations/devel/Makefile.inside
+++ /dev/null
@@ -1,9 +0,0 @@
-all: setup_xos run_develserver
-
-setup_xos:
-	bash /opt/xos/scripts/docker_setup_xos
-	python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/base.yaml
-	python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/nodes.yaml
-
-run_develserver:
-	cd /opt/xos; python manage.py runserver 0.0.0.0:8000 --insecure
diff --git a/xos/configurations/devel/README.md b/xos/configurations/devel/README.md
index d877a39..2361396 100644
--- a/xos/configurations/devel/README.md
+++ b/xos/configurations/devel/README.md
@@ -1,8 +1,8 @@
 # XOS development environment
 
 This configuration can be used to do basic end-to-end development of XOS.  It launches
-an XOS container, runs the XOS develserver, and configures XOS to talk to an OpenStack
-backend.  
+XOS in three Docker containers (development GUI, Synchronizer, database) and configures XOS
+to talk to an OpenStack backend.  *docker-compose* is used to manage the containers.
 
 ## How to run it
 
@@ -56,3 +56,19 @@
 Note that there are some issues with the networking setup in this configuration:
 VMs do not have a working DNS configuration in `/etc/resolv.conf`.  If you fix this
 manually then everything should work.
+
+## Docker Helpers
+
+Stop the containers: `make stop`
+
+Restart the containers: `make stop; make [cloudlab|devstack]`
+
+Delete the containers and relaunch them: `make rm; make [cloudlab|devstack]`
+
+View logs: `make showlogs`
+
+See what containers are running: `make ps`
+
+Open a shell on the XOS container: `make enter-xos`
+
+Open a shell on the Synchronizer container: `make enter-synchronizer`
diff --git a/xos/configurations/devel/docker-compose.yml b/xos/configurations/devel/docker-compose.yml
new file mode 100644
index 0000000..66f6702
--- /dev/null
+++ b/xos/configurations/devel/docker-compose.yml
@@ -0,0 +1,35 @@
+xos_db:
+    image: xosproject/xos-postgres
+    expose:
+        - "5432"
+
+xos_synchronizer_openstack:
+    image: xosproject/xos-synchronizer-openstack
+    command: bash -c "sleep 120; python /opt/xos/xos-observer.py"
+    labels:
+        org.xosproject.kind: synchronizer
+        org.xosproject.target: openstack
+    links:
+        - xos_db
+    extra_hosts:
+        - ctl:${MYIP}
+    volumes:
+        - ../common/xos_common_config:/opt/xos/xos_configuration/xos_common_config:ro
+
+# FUTURE
+#xos_swarm_synchronizer:
+#    image: xosproject/xos-swarm-synchronizer
+#    labels:
+#        org.xosproject.kind: synchronizer
+#        org.xosproject.target: swarm
+
+xos:
+    image: xosproject/xos
+    command: python /opt/xos/manage.py runserver 0.0.0.0:8000 --insecure --makemigrations
+    ports:
+        - "9999:8000"
+    links:
+        - xos_db
+    volumes:
+      - ../setup:/root/setup:ro
+      - ../common/xos_common_config:/opt/xos/xos_configuration/xos_common_config:ro
diff --git a/xos/configurations/frontend/Dockerfile.frontend b/xos/configurations/frontend/Dockerfile.frontend
deleted file mode 100644
index 8372fbf..0000000
--- a/xos/configurations/frontend/Dockerfile.frontend
+++ /dev/null
@@ -1,13 +0,0 @@
-
-###############################################################################
-########################## START FRONTEND TASKS ###############################
-###############################################################################
-
-RUN mkdir -p /root/setup
-
-RUN echo "autostart=false" >> /etc/supervisor/conf.d/observer.conf
-
-# TODO
-# - Enter /opt/xos/core/xoslib and run npm install
-
-CMD /usr/bin/make -C /opt/xos/configurations/frontend -f Makefile.inside
diff --git a/xos/configurations/frontend/Makefile b/xos/configurations/frontend/Makefile
index 96b0779..c061bc1 100644
--- a/xos/configurations/frontend/Makefile
+++ b/xos/configurations/frontend/Makefile
@@ -1,37 +1,22 @@
 MYIP:=$(shell hostname -i)
-RUNNING_CONTAINER=$(shell sudo docker ps|grep "xos"|awk '{print $$NF}')
-LAST_CONTAINER=$(shell sudo docker ps -l -q)
-XOS_FOLDER=$(shell pwd)
-
-all: frontend
 
 frontend:
-	if [ -a ../../xos_configuration/* ]; then rm ../../xos_configuration/*; fi
-	sudo apt-get -y install httpie
-	cat ../common/Dockerfile.common Dockerfile.frontend > Dockerfile
-	cp ../common/xos_common_config ../../xos_configuration/
-	cd ../../..; sudo docker build -t xos -f xos/configurations/frontend/Dockerfile .
-	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 make -f ../common/Makefile.prereq
+	sudo docker-compose up -d
 	bash ../common/wait_for_xos.sh
-	echo $(RUNNING_CONTAINER)
-
-interactive:
-	if [ -a ../../xos_configuration/* ]; then rm ../../xos_configuration/*; fi
-	cat ../common/Dockerfile.common Dockerfile.frontend > Dockerfile
-	cp ../common/xos_common_config ../../xos_configuration/
-	#cp ../cord/xos_cord_config ../../xos_configuration/
-	cd ../../..; sudo docker build -t xos -f xos/configurations/frontend/Dockerfile .
-	echo "Inside the container run: /usr/bin/make -C /opt/xos/configurations/frontend -f Makefile.inside"
-	sudo docker run -it -v $(shell pwd)/../..:/opt/xos -p 9999:8000 --add-host="0.0.0.0:127.0.0.1" xos
+	sudo docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/frontend/sample.yaml
 
 stop:
-	sudo docker stop $(RUNNING_CONTAINER)
-
-start:
-	sudo docker start $(LAST_CONTAINER)
+	sudo docker-compose stop
 
 showlogs:
-	sudo docker logs $(LAST_CONTAINER)
+	sudo docker-compose logs
 
-enter:
-	sudo docker exec -t -i $(RUNNING_CONTAINER) bash
+rm: stop
+	sudo docker-compose rm
+
+ps:
+	sudo docker-compose ps
+
+enter-xos:
+	sudo docker exec -ti frontend_xos_1 bash
diff --git a/xos/configurations/frontend/Makefile.inside b/xos/configurations/frontend/Makefile.inside
deleted file mode 100644
index 48046b2..0000000
--- a/xos/configurations/frontend/Makefile.inside
+++ /dev/null
@@ -1,12 +0,0 @@
-all: setup_xos run_develserver
-
-setup_xos:
-	chmod +x /opt/xos/scripts/opencloud;
-	/opt/xos/scripts/opencloud genkeys;
-#	/opt/xos/scripts/opencloud remigrate;
-	bash /opt/xos/tosca/install_tosca.sh;
-	bash /opt/xos/scripts/docker_setup_xos
-	python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/frontend/sample.yaml
-
-run_develserver:
-	cd /opt/xos; python manage.py runserver 0.0.0.0:8000 --insecure
diff --git a/xos/configurations/frontend/README.md b/xos/configurations/frontend/README.md
index db3c99f..1cf244d 100644
--- a/xos/configurations/frontend/README.md
+++ b/xos/configurations/frontend/README.md
@@ -1,11 +1,7 @@
 # XOS UI Development
 
-This configuration launches an XOS container on Cloudlab that runs the XOS develserver. The container is left running
-in the backgorund.
-
-The observer is not started, and there is no openstack backend connected for XOS. 
-
-This configuration is intended for developing the XOS GUI. 
+This configuration launches the XOS GUI and database in separate containers
+using docker-compose.  The Synchronizer is not started and there is no openstack backend connected for XOS.  This configuration is intended for developing the XOS GUI.
 
 ## Getting Started
 
@@ -14,20 +10,27 @@
 
 You'll be able to visit XOS at `0.0.0.0:9000` and the `xos/core/xoslib` folder is shared with the container. This means that any update to that folder is automatically reported in the container.
 
->If you need to work on the Django application there is an alternative command to setup your config. Using `make interactive` instead of `make` an interactive container will be set up and the whole `xos` folder is shared.
->
-> _NOTE: once the container has started, be sure to isse `CMD /usr/bin/make -C /opt/xos/configurations/frontend -f Makefile.inside` command. Please be carefull and do not commit migrations, private keys or other autogenerated files. 
+If you need to work on the Django application itself, comment out the "sleep" command
+for the `xos` container in docker-compose.yml and run `make`.  Once the containers are
+up then type `make enter` to enter the running container.
+
+> _NOTE:
+> Please be careful and do not commit migrations, private keys or other autogenerated files._
 
 ### Docker Helpers
 
-Stop the container: `make stop`
+Stop the containers: `make stop`
 
-Restart (without rebuilding): `make start`
+Restart the containers: `make stop; make`
 
-Open a container shell: `make enter`
+Delete the containers and relaunch them: `make rm; make`
 
 View logs: `make showlogs`
 
+See what containers are running: `make ps`
+
+Open a shell on the XOS container: `make enter-xos`
+
 ## Docs
 
 You can find a Swagger documentation for endpoint at: `http://0.0.0.0:9000/docs/`
@@ -48,6 +51,5 @@
 
 This project is following [Google JavaScript Style Guide](https://google.github.io/styleguide/javascriptguide.xml). To contribute please install [Eslint](http://eslint.org/) in your editor and run `npm run eslint` before commit.
 
-> _NOTE_
+> _NOTE_:
 > Many of the already present file were not Style compliant. Linting for them has been disabled as it was to time consuming fix all of them. If **you are going to work** on that files, please **start fixing style issues**, and then **remove the `/* eslint-disable */`** comment
-
diff --git a/xos/configurations/frontend/docker-compose.yml b/xos/configurations/frontend/docker-compose.yml
new file mode 100644
index 0000000..2779deb
--- /dev/null
+++ b/xos/configurations/frontend/docker-compose.yml
@@ -0,0 +1,23 @@
+xos_db:
+    image: xosproject/xos-postgres
+    expose:
+        - "5432"
+
+# FUTURE
+#xos_swarm_synchronizer:
+#    image: xosproject/xos-swarm-synchronizer
+#    labels:
+#        org.xosproject.kind: synchronizer
+#        org.xosproject.target: swarm
+
+xos:
+    image: xosproject/xos
+    command: python /opt/xos/manage.py runserver 0.0.0.0:8000 --insecure --makemigrations
+    #command: sleep 86400    # For interactive session
+    ports:
+        - "9999:8000"
+    links:
+        - xos_db
+    volumes:
+      - ../common/xos_common_config:/opt/xos/xos_configuration/xos_common_config:ro
+      - ../../core/xoslib:/opt/xos/core/xoslib:ro
diff --git a/xos/configurations/test/Dockerfile.test b/xos/configurations/test/Dockerfile.test
deleted file mode 100644
index 5c2c717..0000000
--- a/xos/configurations/test/Dockerfile.test
+++ /dev/null
@@ -1,10 +0,0 @@
-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/nodes.yaml /opt/xos/configurations/commmon/
-ADD xos/configurations/common/id_rsa.pub /root/setup/padmin_public_key
-
-CMD ["/usr/bin/make", "-C", "/opt/xos/configurations/test", "-f", "Makefile.inside"]
-
-#CMD ["/bin/bash"]
diff --git a/xos/configurations/test/Makefile b/xos/configurations/test/Makefile
index 75143fa..a79e322 100644
--- a/xos/configurations/test/Makefile
+++ b/xos/configurations/test/Makefile
@@ -1,11 +1,38 @@
 MYIP:=$(shell hostname -i)
 
-test: common_cloudlab
-	if [ -a ../../xos_configuration/* ]; then rm ../../xos_configuration/*; fi
-	cat ../common/Dockerfile.common Dockerfile.test > Dockerfile
-	cd ../../..; sudo docker build -t xos -f xos/configurations/test/Dockerfile .
-	# sudo docker run -d --add-host="ctl:$(MYIP)" -p 9999:8000 xos
-	sudo docker run -i --tty --add-host="ctl:$(MYIP)" -p 9999:8000 xos
+cloudlab: common_cloudlab xos
+
+devstack: upgrade_pkgs common_devstack devstack_net_fix xos
+
+xos:
+	sudo MYIP=$(MYIP) docker-compose up -d
+	bash ../common/wait_for_xos.sh
+	sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/base.yaml
+	sudo MYIP=$(MYIP) docker-compose run xos python /opt/xos/tosca/run.py padmin@vicci.org /root/setup/nodes.yaml
+	sudo MYIP=$(MYIP) docker-compose run xos bash -c "cd /opt/xos/tosca/tests; python ./alltests.py"
+	sudo MYIP=$(MYIP) docker-compose run xos bash -c "cd /opt/xos/tosca/tests; python ./allObserverTests.py"
 
 common_cloudlab:
 	make -C ../common -f Makefile.cloudlab
+
+common_devstack:
+	make -C ../common -f Makefile.devstack
+
+stop:
+	sudo MYIP=$(MYIP) docker-compose stop
+
+showlogs:
+	sudo MYIP=$(MYIP) docker-compose logs
+
+rm: stop
+	sudo MYIP=$(MYIP) docker-compose rm
+
+ps:
+	sudo MYIP=$(MYIP) docker-compose ps
+
+devstack_net_fix:
+	sudo ../common/devstack/net-fix.sh
+	sudo bash -c "source ../setup/admin-openrc.sh; neutron subnet-update private-subnet --dns-nameservers list=true 8.8.8.8 8.8.4.4"
+
+upgrade_pkgs:
+	sudo pip install httpie --upgrade
diff --git a/xos/configurations/test/Makefile.inside b/xos/configurations/test/Makefile.inside
deleted file mode 100644
index 168f671..0000000
--- a/xos/configurations/test/Makefile.inside
+++ /dev/null
@@ -1,13 +0,0 @@
-all: setup_xos run_tests
-
-setup_xos:
-	bash /opt/xos/scripts/docker_setup_xos
-	python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/base.yaml
-	python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/nodes.yaml
-	echo sleeping 30 seconds
-	sleep 30
-
-run_tests:
-	supervisorctl stop observer
-	cd /opt/xos/tosca/tests; python ./alltests.py
-	cd /opt/xos/tosca/tests; python ./allObserverTests.py
diff --git a/xos/configurations/test/docker-compose.yml b/xos/configurations/test/docker-compose.yml
new file mode 100644
index 0000000..91cd4e3
--- /dev/null
+++ b/xos/configurations/test/docker-compose.yml
@@ -0,0 +1,24 @@
+xos_db:
+    image: xosproject/xos-postgres
+    expose:
+        - "5432"
+
+# FUTURE
+#xos_swarm_synchronizer:
+#    image: xosproject/xos-swarm-synchronizer
+#    labels:
+#        org.xosproject.kind: synchronizer
+#        org.xosproject.target: swarm
+
+xos:
+    image: xosproject/xos-synchronizer-openstack  # Because we test the observer too
+    command: python /opt/xos/manage.py runserver 0.0.0.0:8000 --insecure --makemigrations
+    ports:
+        - "9999:8000"
+    links:
+        - xos_db
+    extra_hosts:
+        - ctl:${MYIP}
+    volumes:
+      - ../setup:/root/setup:ro
+      - ../common/xos_common_config:/opt/xos/xos_configuration/xos_common_config:ro
diff --git a/xos/observers/onos/scripts/dockerip.sh b/xos/observers/onos/scripts/dockerip.sh
index 4bf355d..732c3fe 100644
--- a/xos/observers/onos/scripts/dockerip.sh
+++ b/xos/observers/onos/scripts/dockerip.sh
@@ -1,4 +1,9 @@
-#!/bin/sh
+#!/bin/bash
 
-docker inspect --format '{{ .NetworkSettings.IPAddress }}' $1 | tr -d '\n' | tr -d '\r'
+MODE=`docker inspect --format '{{ .HostConfig.NetworkMode }}' $1  | tr -d '\n' | tr -d '\r'`
+if [[ "$MODE" == "host" ]]; then
+    echo -n "127.0.0.1"
+else
+    docker inspect --format '{{ .NetworkSettings.IPAddress }}' $1 | tr -d '\n' | tr -d '\r'
+fi
 
diff --git a/xos/observers/onos/steps/sync_onosapp.py b/xos/observers/onos/steps/sync_onosapp.py
index 0feb2e5..cfe1041 100644
--- a/xos/observers/onos/steps/sync_onosapp.py
+++ b/xos/observers/onos/steps/sync_onosapp.py
@@ -1,6 +1,7 @@
 import hashlib
 import os
 import socket
+import socket
 import sys
 import base64
 import time
@@ -73,6 +74,19 @@
 
         return os.path.join(step_dir, "..", "files", str(self.get_onos_service(o).id), o.name)
 
+    def get_cluster_configuration(self, o):
+        instance = self.get_instance(o)
+        if not instance:
+           raise "No instance for ONOS App"
+        node_ips = [socket.gethostbyname(instance.node.name)]
+
+        ipPrefix = ".".join(node_ips[0].split(".")[:3]) + ".*"
+        result = '{ "nodes": ['
+        result = result + ",".join(['{ "ip": "%s"}' % ip for ip in node_ips])
+        result = result + '], "ipPrefix": "%s"}' % ipPrefix
+        return result
+
+
     def write_configs(self, o):
         o.config_fns = []
         o.rest_configs = []
@@ -86,7 +100,23 @@
         attrs = o.provider_service.serviceattribute_dict
         attrs.update(o.tenantattribute_dict)
 
-        for (name, value) in attrs.items():
+        ordered_attrs = attrs.keys()
+
+        o.early_rest_configs=[]
+        if ("cordvtn" in o.dependencies):
+            # For VTN, since it's running in a docker host container, we need
+            # to make sure it configures the cluster using the right ip addresses.
+            # NOTE: rest_onos/v1/cluster/configuration/ will reboot the cluster and
+            #   must go first.
+            name="rest_onos/v1/cluster/configuration/"
+            value= self.get_cluster_configuration(o)
+            fn = name[5:].replace("/","_")
+            endpoint = name[5:]
+            file(os.path.join(o.files_dir, fn),"w").write(" " +value)
+            o.early_rest_configs.append( {"endpoint": endpoint, "fn": fn} )
+
+        for name in attrs.keys():
+            value = attrs[name]
             if name.startswith("config_"):
                 fn = name[7:] # .replace("_json",".json")
                 o.config_fns.append(fn)
@@ -114,6 +144,7 @@
         fields["nat_ip"] = instance.get_ssh_ip()
         fields["config_fns"] = o.config_fns
         fields["rest_configs"] = o.rest_configs
+        fields["early_rest_configs"] = o.early_rest_configs
         if o.dependencies:
             fields["dependencies"] = [x.strip() for x in o.dependencies.split(",")]
         else:
diff --git a/xos/observers/onos/steps/sync_onosapp.yaml b/xos/observers/onos/steps/sync_onosapp.yaml
index 496fad0..a03368b 100644
--- a/xos/observers/onos/steps/sync_onosapp.yaml
+++ b/xos/observers/onos/steps/sync_onosapp.yaml
@@ -14,6 +14,13 @@
          body: "{{ '{{' }} lookup('file', '{{ files_dir }}/{{ rest_config.fn }}') {{ '}}' }}"
 {% endfor %}
 {% endif %}
+{% if early_rest_configs %}
+    early_rest_configs:
+{% for early_rest_config in early_rest_configs %}
+       - endpoint: {{ early_rest_config.endpoint }}
+         body: "{{ '{{' }} lookup('file', '{{ files_dir }}/{{ early_rest_config.fn }}') {{ '}}' }}"
+{% endfor %}
+{% endif %}
 
   tasks:
 
@@ -63,6 +70,22 @@
   - name: Wait for ONOS to install the apps
     wait_for: timeout=15
 
+{% if early_rest_configs %}
+  - name: Add ONOS early configuration values
+    uri:
+      url: http://{{ '{{' }} onosaddr.stdout {{ '}}' }}:8181/{{ '{{' }} item.endpoint {{ '}}' }}
+      body: "{{ '{{' }} item.body {{ '}}' }}"
+      body_format: raw
+      method: POST
+      user: karaf
+      password: karaf
+    with_items: "early_rest_configs"
+
+  # Don't know how to check for this condition, just wait
+  - name: Wait for ONOS to restart
+    wait_for: timeout=15
+{% endif %}
+
 {% if dependencies %}
   - name: Add dependencies to ONOS
     uri:
diff --git a/xos/observers/onos/supervisor/onos-observer.conf b/xos/observers/onos/supervisor/onos-observer.conf
index 16afa8c..36e00d9 100644
--- a/xos/observers/onos/supervisor/onos-observer.conf
+++ b/xos/observers/onos/supervisor/onos-observer.conf
@@ -1,2 +1,9 @@
-[program:onos-observer]
+[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:synchronizer]
 command=python /opt/xos/observers/onos/onos-observer.py -C /opt/xos/observers/onos/onos_observer_config
+stderr_logfile=/var/log/supervisor/synchronizer.err.log
+stdout_logfile=/var/log/supervisor/synchronizer.out.log
diff --git a/xos/tosca/samples/vtn.yaml b/xos/tosca/samples/vtn.yaml
index 38db047..4683b70 100644
--- a/xos/tosca/samples/vtn.yaml
+++ b/xos/tosca/samples/vtn.yaml
@@ -56,7 +56,7 @@
               node: docker-onos
               relationship: tosca.relationships.UsesImage
       properties:
-          network: bridged
+          network: host
           default_isolation: container
 
     # Virtual machines