Merge branch 'master' into feature/xoslib_test
diff --git a/xos/configurations/common/Dockerfile.common b/xos/configurations/common/Dockerfile.common
index 1f42c34..5329142 100644
--- a/xos/configurations/common/Dockerfile.common
+++ b/xos/configurations/common/Dockerfile.common
@@ -4,8 +4,8 @@
 # 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 
+# until there is a fix
+RUN ln -s -f /bin/true /usr/bin/chfn
 # XXX End workaround
 
 # Install.
@@ -23,12 +23,12 @@
     python-httplib2 \
     geoip-database \
     libgeoip1 \
-    wget \ 
-    curl \ 
+    wget \
+    curl \
     python-dev \
-    libyaml-dev \ 
-    pkg-config \ 
-    python-pycurl 
+    libyaml-dev \
+    pkg-config \
+    python-pycurl
 
 RUN pip install django==1.7
 RUN pip install djangorestframework==2.4.4
@@ -64,6 +64,7 @@
 RUN easy_install python_gflags
 RUN easy_install --upgrade httplib2
 RUN easy_install google_api_python_client
+RUN easy_install httplib2.ca_certs_locater
 
 # Install custom Ansible
 RUN DEBIAN_FRONTEND=noninteractive apt-get install -y python-crypto
@@ -97,7 +98,7 @@
 RUN DEBIAN_FRONTEND=noninteractive apt-get install -y supervisor
 ADD observer.conf /etc/supervisor/conf.d/
 
-# Get XOS 
+# Get XOS
 ADD xos /opt/xos
 
 # Initscript is broken in Ubuntu
diff --git a/xos/configurations/common/Makefile.cloudlab b/xos/configurations/common/Makefile.cloudlab
index 929bc14..5712765 100644
--- a/xos/configurations/common/Makefile.cloudlab
+++ b/xos/configurations/common/Makefile.cloudlab
@@ -1,4 +1,4 @@
-all: prereqs admin-openrc flat_name nodes_yaml public_key 
+all: prereqs admin-openrc flat_name nodes_yaml public_key private_key
 
 prereqs:
 	make -f Makefile.prereqs
@@ -7,7 +7,7 @@
 	sudo cat /root/setup/admin-openrc.sh > admin-openrc.sh
 
 flat_name:
-	sudo bash -c "source /root/setup/admin-openrc.sh ; neutron net-list" |grep flat|awk '{print $$4}' > flat_net_name
+	sudo bash -c "source /root/setup/admin-openrc.sh ; neutron net-list" |grep flat|awk '{printf "%s",$$4}' > flat_net_name
 
 nodes_yaml:
 	bash ./make-cloudlab-nodes-yaml.sh
@@ -15,6 +15,8 @@
 public_key: ~/.ssh/id_rsa.pub
 	cp ~/.ssh/id_rsa.pub .
 
+private_key: ~/.ssh/id_rsa
+	cp ~/.ssh/id_rsa .
+
 ~/.ssh/id_rsa.pub:
 	cat /dev/zero | ssh-keygen -q -N ""
-
diff --git a/xos/configurations/cord/Dockerfile.cord b/xos/configurations/cord/Dockerfile.cord
new file mode 100644
index 0000000..dad9895
--- /dev/null
+++ b/xos/configurations/cord/Dockerfile.cord
@@ -0,0 +1,13 @@
+RUN mkdir -p /root/setup
+ADD xos/configurations/common/admin-openrc.sh /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/observers/vcpe/supervisor/vcpe-observer.conf /etc/supervisor/conf.d/
+RUN sed -i 's/proxy_ssh=True/proxy_ssh=False/' /opt/xos/observers/vcpe/vcpe_observer_config
+
+CMD /usr/bin/make -C /opt/xos/configurations/cord -f Makefile.inside; /bin/bash
+
+#CMD ["/bin/bash"]
diff --git a/xos/configurations/cord/Makefile b/xos/configurations/cord/Makefile
new file mode 100644
index 0000000..40ff5a1
--- /dev/null
+++ b/xos/configurations/cord/Makefile
@@ -0,0 +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)
+
+test: common_cloudlab
+	echo "# Autogenerated -- do not edit" > Dockerfile
+	cat ../common/Dockerfile.common Dockerfile.cord >> Dockerfile
+	cd ../../..; sudo docker build -t xos -f xos/configurations/cord/Dockerfile .
+	sudo docker run -d --add-host="ctl:$(MYIP)" -p 9999:8000 xos
+	bash ../common/wait_for_xos.sh
+
+common_cloudlab:
+	make -C ../common -f Makefile.cloudlab
+
+stop:
+	sudo docker stop $(RUNNING_CONTAINER)
+
+showlogs:
+	sudo docker logs $(LAST_CONTAINER)
+
+enter:
+	sudo docker exec -t -i $(RUNNING_CONTAINER) bash
diff --git a/xos/configurations/cord/Makefile.inside b/xos/configurations/cord/Makefile.inside
new file mode 100644
index 0000000..a4bb5f1
--- /dev/null
+++ b/xos/configurations/cord/Makefile.inside
@@ -0,0 +1,10 @@
+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/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
+
+run_develserver:
+	cd /opt/xos; python manage.py runserver 0.0.0.0:8000 --insecure
diff --git a/xos/configurations/cord/README b/xos/configurations/cord/README
new file mode 100644
index 0000000..7c80c0f
--- /dev/null
+++ b/xos/configurations/cord/README
@@ -0,0 +1,4 @@
+This configuration configures XOS with the CORD services.  It is intended to be
+run on CloudLab, on the "ctl" node set up by the OpenStack profile.  It launches
+an XOS container on Cloudlab that runs the XOS develserver.  The container is
+left running in the background.
diff --git a/xos/configurations/cord/cord.yaml b/xos/configurations/cord/cord.yaml
new file mode 100644
index 0000000..56ab11d
--- /dev/null
+++ b/xos/configurations/cord/cord.yaml
@@ -0,0 +1,165 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+description: Setup CORD-related services -- vOLT, vCPE, vBNG.
+
+imports:
+   - custom_types/xos.yaml
+
+topology_template:
+  node_templates:
+    # CORD Services
+    service_volt:
+      type: tosca.nodes.Service
+      requirements:
+          - vcpe_tenant:
+              node: service_vcpe
+              relationship: tosca.relationships.TenantOfService
+      properties:
+          view_url: /admin/cord/voltservice/$id$/
+          kind: vOLT
+
+    Private:
+      type: tosca.nodes.NetworkTemplate
+
+    # networks required by vCPE
+    lan_network:

+      type: tosca.nodes.network.Network

+      properties:

+          ip_version: 4

+      requirements:

+          - network_template:

+              node: Private

+              relationship: tosca.relationships.UsesNetworkTemplate

+          - owner:

+              node: mysite_vcpe

+              relationship: tosca.relationships.MemberOfSlice

+          - connection:

+              node: mysite_vcpe

+              relationship: tosca.relationships.ConnectsToSlice
+
+    wan_network:
+      type: tosca.nodes.network.Network
+      properties:
+          ip_version: 4
+      requirements:
+          - network_template:
+              node: Private
+              relationship: tosca.relationships.UsesNetworkTemplate
+          - owner:
+              node: mysite_vcpe
+              relationship: tosca.relationships.MemberOfSlice
+          - connection:
+              node: mysite_vcpe
+              relationship: tosca.relationships.ConnectsToSlice
+
+    hpc_client_network:
+      type: tosca.nodes.network.Network
+      properties:
+          ip_version: 4
+      requirements:
+          - network_template:
+              node: Private
+              relationship: tosca.relationships.UsesNetworkTemplate
+          - owner:
+              node: mysite_vcpe
+              relationship: tosca.relationships.MemberOfSlice
+          - connection:
+              node: mysite_vcpe
+              relationship: tosca.relationships.ConnectsToSlice
+
+    service_vcpe:
+      type: tosca.nodes.VCPEService
+      requirements:
+          - vbng_tenant:
+              node: service_vbng
+              relationship: tosca.relationships.TenantOfService
+      properties:
+          view_url: /admin/cord/vcpeservice/$id$/
+          backend_network_label: hpc_client
+          public_key: { get_artifact: [ SELF, pubkey, LOCAL_FILE] }
+      artifacts:
+          pubkey: /opt/xos/observers/vcpe/vcpe_public_key
+
+    service_vbng:
+      type: tosca.nodes.VBNGService
+      properties:
+          view_url: /admin/cord/vbngservice/$id$/
+          vbng_url: http://10.0.3.136:8181/onos/virtualbng/
+
+    mysite:
+      type: tosca.nodes.Site
+
+    mysite_vcpe:
+      description: vCPE Controller Slice
+      type: tosca.nodes.Slice
+      requirements:
+          - vcpe_service:
+              node: service_vcpe
+              relationship: tosca.relationships.MemberOfService
+          - site:
+              node: mysite
+              relationship: tosca.relationships.MemberOfSite
+
+    # Now let's add a subscriber
+
+    My House:
+       type: tosca.nodes.CORDSubscriber
+       properties:
+           service_specific_id: 1234
+           firewall_enable: false
+           cdn_enable: false
+           url_filter_enable: false
+           url_filter_level: R
+
+    Mom's PC:
+       type: tosca.nodes.CORDUser
+       properties:
+           mac: 010203040506
+           level: PG_13
+       requirements:
+           - household:
+               node: My House
+               relationship: tosca.relationships.SubscriberDevice
+
+    Dad's PC:
+       type: tosca.nodes.CORDUser
+       properties:
+           mac: 90E2Ba82F975
+           level: PG_13
+       requirements:
+           - household:
+               node: My House
+               relationship: tosca.relationships.SubscriberDevice
+
+    Jack's Laptop:
+       type: tosca.nodes.CORDUser
+       properties:
+           mac: 685B359D91D5
+           level: PG_13
+       requirements:
+           - household:
+               node: My House
+               relationship: tosca.relationships.SubscriberDevice
+
+    Jill's Laptop:
+       type: tosca.nodes.CORDUser
+       properties:
+           mac: 34363BC9B6A6
+           level: PG_13
+       requirements:
+           - household:
+               node: My House
+               relationship: tosca.relationships.SubscriberDevice
+
+    My Volt:
+        type: tosca.nodes.VOLTTenant
+        properties:
+            service_specific_id: 1234
+            vlan_id: 4321
+        requirements:
+            - provider_service:
+                node: service_volt
+                relationship: tosca.relationships.MemberOfService
+            - subscriber:
+                node: My House
+                relationship: tosca.relationships.BelongsToSubscriber
diff --git a/xos/configurations/devel/Makefile b/xos/configurations/devel/Makefile
index 90dabcc..3ce188b 100644
--- a/xos/configurations/devel/Makefile
+++ b/xos/configurations/devel/Makefile
@@ -6,7 +6,7 @@
 	echo "# Autogenerated -- do not edit" > Dockerfile
 	cat ../common/Dockerfile.common Dockerfile.devel >> Dockerfile
 	cd ../../..; sudo docker build -t xos -f xos/configurations/devel/Dockerfile .
-	sudo docker run -d --add-host="0.0.0.0:$(MYIP)" -p 9999:8000 xos
+	sudo docker run -d --add-host="ctl:$(MYIP)" -p 9999:8000 xos
 	bash ../common/wait_for_xos.sh
 
 common_cloudlab:
diff --git a/xos/configurations/kilo-install/Dockerfile b/xos/configurations/kilo-install/Dockerfile
new file mode 100644
index 0000000..f0ced90
--- /dev/null
+++ b/xos/configurations/kilo-install/Dockerfile
@@ -0,0 +1,154 @@
+# Autogenerated -- do not edit
+FROM       ubuntu:14.04.2
+MAINTAINER Andy Bavier <acb@cs.princeton.edu>
+
+# 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 apt-get update && apt-get install -y \
+    git \
+    postgresql \
+    python-psycopg2 \
+    graphviz \
+    graphviz-dev \
+    libxslt1.1 \
+    libxslt1-dev \
+    python-pip \
+    tar \
+    gcc \
+    python-httplib2 \
+    geoip-database \
+    libgeoip1 \
+    wget \ 
+    curl \ 
+    python-dev \
+    libyaml-dev \ 
+    pkg-config \ 
+    python-pycurl 
+
+RUN pip install django==1.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 lxml  # XML manipulation library
+RUN pip install netaddr # IP Addr library
+RUN pip install pytz
+RUN pip install django-timezones
+RUN pip install requests
+RUN pip install django-crispy-forms
+RUN pip install django-geoposition
+RUN pip install django-extensions
+RUN pip install django-suit
+RUN pip install django-bitfield
+RUN pip install django-ipware
+RUN pip install django-encrypted-fields
+RUN pip install python-keyczar
+RUN pip install pygraphviz
+RUN pip install dnslib
+
+RUN DEBIAN_FRONTEND=noninteractive apt-get install -y python-keystoneclient
+RUN DEBIAN_FRONTEND=noninteractive apt-get install -y python-novaclient
+RUN DEBIAN_FRONTEND=noninteractive apt-get install -y python-neutronclient
+RUN DEBIAN_FRONTEND=noninteractive apt-get install -y python-glanceclient
+RUN DEBIAN_FRONTEND=noninteractive apt-get install -y python-ceilometerclient
+
+RUN pip install django_rest_swagger
+
+RUN DEBIAN_FRONTEND=noninteractive apt-get install -y python-setuptools
+RUN easy_install django_evolution
+RUN easy_install python_gflags
+RUN easy_install --upgrade httplib2
+RUN easy_install google_api_python_client
+RUN easy_install httplib2.ca_certs_locater
+
+# Install custom Ansible
+RUN DEBIAN_FRONTEND=noninteractive apt-get install -y python-crypto
+RUN DEBIAN_FRONTEND=noninteractive apt-get install -y python-yaml
+RUN DEBIAN_FRONTEND=noninteractive apt-get install -y openssh-client
+RUN DEBIAN_FRONTEND=noninteractive apt-get install -y python-paramiko
+RUN DEBIAN_FRONTEND=noninteractive apt-get install -y python-jinja2
+RUN DEBIAN_FRONTEND=noninteractive apt-get install -y python-httplib2
+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
+RUN DEBIAN_FRONTEND=noninteractive apt-get install -y supervisor
+ADD observer.conf /etc/supervisor/conf.d/
+
+# Get XOS 
+ADD xos /opt/xos
+
+# 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
+RUN mkdir -p /root/setup
+ADD xos/configurations/common/admin-openrc.sh /root/setup/
+RUN bash -c 'echo "nat-net" > /root/setup/flat_net_name'
+ADD xos/configurations/common/cloudlab-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/kilo-install -f Makefile.inside; /bin/bash
+
+#CMD ["/bin/bash"]
diff --git a/xos/configurations/kilo-install/Dockerfile.kilo-install b/xos/configurations/kilo-install/Dockerfile.kilo-install
new file mode 100644
index 0000000..fabfcd8
--- /dev/null
+++ b/xos/configurations/kilo-install/Dockerfile.kilo-install
@@ -0,0 +1,8 @@
+RUN mkdir -p /root/setup
+ADD xos/configurations/common/admin-openrc.sh /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
+
+CMD /usr/bin/make -C /opt/xos/configurations/kilo-install -f Makefile.inside; /bin/bash
+
+#CMD ["/bin/bash"]
diff --git a/xos/configurations/kilo-install/Makefile b/xos/configurations/kilo-install/Makefile
new file mode 100644
index 0000000..108df7a
--- /dev/null
+++ b/xos/configurations/kilo-install/Makefile
@@ -0,0 +1,38 @@
+MYIP:=$(shell hostname -i)
+RUNNING_CONTAINER:=$(shell sudo docker ps|grep "xos"|awk '{print $$NF}')
+LAST_CONTAINER=$(shell sudo docker ps -l -q)
+
+# For installing XOS on a node that is not the OpenStack head node
+MGMT_SUBNET="192.168.122.0/24"
+HEAD_NODE_IP="130.127.133.61"
+
+test: common_cloudlab images
+	echo "# Autogenerated -- do not edit" > Dockerfile
+	cat ../common/Dockerfile.common Dockerfile.kilo-install >> Dockerfile
+	cd ../../..; sudo docker build -t xos -f xos/configurations/kilo-install/Dockerfile .
+	sudo docker run -d -p 9999:8000 -v /usr/local/share/ca-certificates:/usr/local/share/ca-certificates:ro  xos
+	bash ../common/wait_for_xos.sh
+
+common_cloudlab:
+	make -C ../common -f Makefile.cloudlab
+
+stop:
+	sudo docker stop $(RUNNING_CONTAINER)
+
+showlogs:
+	sudo docker logs $(LAST_CONTAINER)
+
+enter:
+	sudo docker exec -t -i $(RUNNING_CONTAINER) bash
+
+images:
+	sudo bash -c "source /root/setup/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"
+
+remote_head_node:
+	sudo iptables -t nat -A OUTPUT -p tcp -d $MGMT_SUBNET -j DNAT --to-destination $HEAD_NODE_IP
+	sudo iptables -t nat -A PREROUTING -p tcp -d $MGMT_SUBNET -j DNAT --to-destination $HEAD_NODE_IP
diff --git a/xos/configurations/kilo-install/Makefile.inside b/xos/configurations/kilo-install/Makefile.inside
new file mode 100644
index 0000000..c49841a
--- /dev/null
+++ b/xos/configurations/kilo-install/Makefile.inside
@@ -0,0 +1,12 @@
+all: setup_xos update_certificates run_develserver
+
+setup_xos:
+	bash /opt/xos/scripts/docker_setup_xos
+	python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/kilo-install/cloudlab.yaml
+	python /opt/xos/tosca/run.py padmin@vicci.org /opt/xos/configurations/common/cloudlab-nodes.yaml
+
+update_certificates:
+	update-ca-certificates
+
+run_develserver:
+	cd /opt/xos; python manage.py runserver 0.0.0.0:8000 --insecure
diff --git a/xos/configurations/kilo-install/README b/xos/configurations/kilo-install/README
new file mode 100644
index 0000000..2ff7549
--- /dev/null
+++ b/xos/configurations/kilo-install/README
@@ -0,0 +1,8 @@
+This configuration is based on the "devel" configuration for CloudLab.  It is
+meant to work with an OpenStack Kilo cluster installed on CloudLab using the
+procedure documented here:
+
+https://github.com/andybavier/opencloud-cluster-setup
+
+It launches an XOS container on Cloudlab that runs the XOS develserver. The
+container is left running in the background.
diff --git a/xos/configurations/kilo-install/cloudlab.yaml b/xos/configurations/kilo-install/cloudlab.yaml
new file mode 100644
index 0000000..f92442c
--- /dev/null
+++ b/xos/configurations/kilo-install/cloudlab.yaml
@@ -0,0 +1,76 @@
+tosca_definitions_version: tosca_simple_yaml_1_0
+
+# Note:
+#   assumes the following have been created and filled with appropriate data:
+#       /root/setup/admin_openrc
+#       /root/setup/flat_net_name
+#       /root/setup/padmin_public_key
+
+description: >
+    * Adds OpenCloud Sites, Deployments, and Controllers.
+
+imports:
+   - custom_types/xos.yaml
+
+topology_template:
+  node_templates:
+    trusty-server-multi-nic:
+      type: tosca.nodes.Image
+      properties:
+         disk_format: QCOW2
+         container_format: BARE
+
+    MyDeployment:
+      type: tosca.nodes.Deployment
+      properties:
+          flavors: m1.large, m1.medium, m1.small
+      requirements:
+          - image:
+              node: trusty-server-multi-nic
+              relationship: tosca.relationships.SupportsImage
+
+    CloudLab:
+      type: tosca.nodes.Controller
+      requirements:
+          - deployment:
+              node: MyDeployment
+              relationship: tosca.relationships.ControllerDeployment
+      properties:
+          backend_type: OpenStack
+          version: Juno
+          auth_url: { get_script_env: [ SELF, adminrc, OS_AUTH_URL, LOCAL_FILE] }
+          admin_user: { get_script_env: [ SELF, adminrc, OS_USERNAME, LOCAL_FILE] }
+          admin_password: { get_script_env: [ SELF, adminrc, OS_PASSWORD, LOCAL_FILE] }
+          admin_tenant: { get_script_env: [ SELF, adminrc, OS_TENANT_NAME, LOCAL_FILE] }
+          domain: Default
+      artifacts:
+          adminrc: /root/setup/admin-openrc.sh
+
+    mysite:
+      type: tosca.nodes.Site
+      properties:
+          display_name: MySite
+          site_url: http://opencloud.us/
+      requirements:
+          - deployment:
+               node: MyDeployment
+               relationship: tosca.relationships.SiteDeployment
+               requirements:
+                   - controller:
+                       node: CloudLab
+                       relationship: tosca.relationships.UsesController
+
+    padmin@vicci.org:
+      type: tosca.nodes.User
+      requirements:
+          - site:
+              node: mysite
+              relationship: tosca.relationships.MemberOfSite
+      properties:
+          public_key: { get_artifact: [ SELF, pubkey, LOCAL_FILE ] }
+          is_admin: true
+          is_active: true
+          firstname: XOS
+          lastname: admin
+      artifacts:
+          pubkey: /root/setup/padmin_public_key
diff --git a/xos/core/fixtures/initial_data.json b/xos/core/fixtures/initial_data.json
index 213245c..86658bb 100644
--- a/xos/core/fixtures/initial_data.json
+++ b/xos/core/fixtures/initial_data.json
@@ -334,7 +334,7 @@
         "translation": "none",
         "backend_status": "0 - Provisioning in progress",
         "shared_network_name": null,
-        "controller_kind": "none",
+        "controller_kind": null,
         "enacted": null
     },
     "model": "core.networktemplate",
@@ -356,7 +356,7 @@
         "translation": "NAT",
         "backend_status": "0 - Provisioning in progress",
         "shared_network_name": "nat-net",
-        "controller_kind": "none",
+        "controller_kind": null,
         "enacted": null
     },
     "model": "core.networktemplate",
@@ -378,7 +378,7 @@
         "translation": "none",
         "backend_status": "0 - Provisioning in progress",
         "shared_network_name": "ext-net",
-        "controller_kind": "none",
+        "controller_kind": null,
         "enacted": null
     },
     "model": "core.networktemplate",
diff --git a/xos/core/models/controlleruser.py b/xos/core/models/controlleruser.py
index 6b11b24..1031e12 100644
--- a/xos/core/models/controlleruser.py
+++ b/xos/core/models/controlleruser.py
@@ -26,7 +26,7 @@
         if user.is_admin:
             qs = ControllerUser.objects.all()
         else:
-            users = Users.select_by_user(user)
+            users = User.select_by_user(user)
             qs = ControllerUser.objects.filter(user__in=users)
         return qs
 
diff --git a/xos/core/models/flavor.py b/xos/core/models/flavor.py
index 3d6b9bb..8251eb1 100644
--- a/xos/core/models/flavor.py
+++ b/xos/core/models/flavor.py
@@ -18,6 +18,10 @@
         app_label = "core"
         ordering = ('order', 'name')
 
+    def __init__(self, *args, **kwargs):
+        super(Flavor, self).__init__(*args, **kwargs)
+        self.no_sync=True
+
     def __unicode__(self):  return u'%s' % (self.name)
 
 """ FlavorParameterType and FlavorParameter are below for completeness sake,
diff --git a/xos/core/models/network.py b/xos/core/models/network.py
index fe60fce..2bdf17f 100644
--- a/xos/core/models/network.py
+++ b/xos/core/models/network.py
@@ -7,6 +7,7 @@
 from django.contrib.contenttypes.models import ContentType
 from django.contrib.contenttypes import generic
 from django.core.exceptions import ValidationError
+from django.db.models import Q
 
 # If true, then IP addresses will be allocated by the model. If false, then
 # we will assume the observer handles it.
@@ -203,7 +204,8 @@
             qs = NetworkSlice.objects.all()
         else:
             slice_ids = [s.id for s in Slice.select_by_user(user)]
-            qs = NetworkSlice.objects.filter(id__in=slice_ids)
+            network_ids = [network.id for network in Network.select_by_user(user)]
+            qs = NetworkSlice.objects.filter(Q(slice__in=slice_ids) | Q(network__in=network_ids))
         return qs
 
 class Port(PlCoreBase):
@@ -246,8 +248,11 @@
         if user.is_admin:
             qs = Port.objects.all()
         else:
-            instance_ids = [s.id for s in Port.select_by_user(user)]
-            qs = Port.objects.filter(id__in=instance_ids)
+            instances = Instance.select_by_user(user)
+            instance_ids = [instance.id for instance in instances]
+            networks = Network.select_by_user(user)
+            network_ids = [network.id for network in networks]
+            qs = Port.objects.filter(Q(instance__in=instance_ids) | Q(network__in=network_ids))
         return qs
 
 class Router(PlCoreBase):
diff --git a/xos/core/models/site.py b/xos/core/models/site.py
index 42855a9..26ff191 100644
--- a/xos/core/models/site.py
+++ b/xos/core/models/site.py
@@ -168,6 +168,9 @@
     #    given a default of 'allow site <site_of_creator>'
     accessControl = models.TextField(max_length=200, blank=False, null=False, default="allow all",
                                      help_text="Access control list that specifies which sites/users may use nodes in this deployment")
+    def __init__(self, *args, **kwargs):
+        super(Deployment, self).__init__(*args, **kwargs)
+        self.no_sync=True
 
     def get_acl(self):
         return AccessControlList(self.accessControl)
@@ -261,7 +264,10 @@
     admin_tenant = StrippedCharField(max_length=200, null=True, blank=True, help_text="Name of the tenant the admin user belongs to")
     domain = StrippedCharField(max_length=200, null=True, blank=True, help_text="Name of the domain this controller belongs to")
     deployment = models.ForeignKey(Deployment,related_name='controllerdeployments')
-   
+
+    def __init__(self, *args, **kwargs):
+        super(Controller, self).__init__(*args, **kwargs)
+        self.no_sync=True
 
     def __unicode__(self):  return u'%s %s %s' % (self.name, self.backend_type, self.version)
 
diff --git a/xos/core/xoslib/methods/cordsubscriber.py b/xos/core/xoslib/methods/cordsubscriber.py
index ea8da80..c26ac54 100644
--- a/xos/core/xoslib/methods/cordsubscriber.py
+++ b/xos/core/xoslib/methods/cordsubscriber.py
@@ -392,10 +392,18 @@
 
         return Response( {"vbng_mapping": mappings} )
 
+class CordDebugIdSerializer(serializers.ModelSerializer, PlusSerializerMixin):
+    # Swagger is failing because CordDebugViewSet has neither a model nor
+    # a serializer_class. Stuck this in here as a placeholder for now.
+    id = ReadOnlyField()
+    class Meta:
+        model = CordSubscriber
+
 class CordDebugViewSet(XOSViewSet):
     base_name = "cord_debug"
     method_name = "rs/cord_debug"
     method_kind = "viewset"
+    serializer_class = CordDebugIdSerializer
 
     @classmethod
     def get_urlpatterns(self):
diff --git a/xos/observers/hello_world/run.sh b/xos/observers/hello_world/run.sh
index f77d751..1107a7a 100755
--- a/xos/observers/hello_world/run.sh
+++ b/xos/observers/hello_world/run.sh
@@ -3,4 +3,4 @@
 #fi
 
 export XOS_DIR=/opt/xos
-python hpc-observer.py  -C $XOS_DIR/observers/hpc/hpc_observer_config
+python helloworld-observer.py  -C $XOS_DIR/observers/hello_world/helloworld_config
diff --git a/xos/openstack/client.py b/xos/openstack/client.py
index 4962e06..c500204 100644
--- a/xos/openstack/client.py
+++ b/xos/openstack/client.py
@@ -36,7 +36,7 @@
     return opts
 
 class Client:
-    def __init__(self, username=None, password=None, tenant=None, url=None, token=None, endpoint=None, controller=None, admin=True, *args, **kwds):
+    def __init__(self, username=None, password=None, tenant=None, url=None, token=None, endpoint=None, controller=None, cacert=None, admin=True, *args, **kwds):
        
         self.has_openstack = has_openstack
         self.url = controller.auth_url
@@ -62,6 +62,8 @@
         if endpoint:
             self.endpoint = endpoint
 
+        self.cacert = cacert
+
         #if '@' in self.username:
         #    self.username = self.username[:self.username.index('@')]
 
@@ -157,7 +159,8 @@
             self.client = quantum_client.Client(username=self.username,
                                                 password=self.password,
                                                 tenant_name=self.tenant,
-                                                auth_url=self.url)
+                                                auth_url=self.url,
+                                                ca_cert=self.cacert)
     @require_enabled
     def connect(self, *args, **kwds):
         self.__init__(*args, **kwds)
diff --git a/xos/tosca/custom_types/xos.m4 b/xos/tosca/custom_types/xos.m4
index 1a5bee1..81d1333 100644
--- a/xos/tosca/custom_types/xos.m4
+++ b/xos/tosca/custom_types/xos.m4
@@ -8,11 +8,11 @@
             no-delete:
                 type: boolean
                 default: false
-                description: do not allow Tosca to delete this object
+                description: Do not allow Tosca to delete this object
             no-create:
                 type: boolean
                 default: false
-                description: do not allow Tosca to create this object)
+                description: Do not allow Tosca to create this object)
 # Service
 define(xos_base_service_caps,
             scalable:
@@ -23,24 +23,30 @@
             kind:
                 type: string
                 default: generic
+                description: Type of service.
             view_url:
                 type: string
                 required: false
+                description: URL to follow when icon is clicked in the Service Directory.
             icon_url:
                 type: string
                 required: false
+                description: ICON to display in the Service Directory.
             enabled:
                 type: boolean
                 default: true
             published:
                 type: boolean
                 default: true
+                description: If True then display this Service in the Service Directory.
             public_key:
                 type: string
                 required: false
+                description: Public key to install into Instances to allows Services to SSH into them.
             versionNumber:
                 type: string
-                required: false)
+                required: false
+                description: Version number of Service.)
 # Subscriber
 define(xos_base_subscriber_caps,
             subscriber:
@@ -49,16 +55,20 @@
             kind:
                 type: string
                 default: generic
+                description: Kind of subscriber
             service_specific_id:
                 type: string
-                required: false)
+                required: false
+                description: Service specific ID, opaque to XOS but meaningful to service)
 define(xos_base_tenant_props,
             kind:
                 type: string
                 default: generic
+                description: Kind of tenant
             service_specific_id:
                 type: string
-                required: false)
+                required: false
+                description: Service specific ID, opaque to XOS but meaningful to service)
 
 # end m4 macros
 #
@@ -67,12 +77,17 @@
 node_types:
     tosca.nodes.Service:
         derived_from: tosca.nodes.Root
+        description: >
+            An XOS Service object. Services may be listed in the Service
+            directory and may be linked together via Tenancy Relationships.
         capabilities:
             xos_base_service_caps
         properties:
             xos_base_service_props
 
     tosca.nodes.VCPEService:
+        description: >
+            CORD: The vCPE Service.
         derived_from: tosca.nodes.Root
         capabilities:
             xos_base_service_caps
@@ -81,9 +96,12 @@
             backend_network_label:
                 type: string
                 required: false
+                description: Label that matches network used to connect HPC and BBS services.
 
     tosca.nodes.VBNGService:
         derived_from: tosca.nodes.Root
+        description: >
+            CORD: The vBNG Service.
         capabilities:
             xos_base_service_caps
         properties:
@@ -91,9 +109,12 @@
             vbng_url:
                 type: string
                 required: false
+                description: URL of REST API endpoint for vBNG Service.
 
     tosca.nodes.CDNService:
         derived_from: tosca.nodes.Root
+        description: >
+            Content Delivery Network Service. Includes Request Routing and Hypercache.
         capabilities:
             xos_base_service_caps
         properties:
@@ -101,6 +122,7 @@
 
     tosca.nodes.Subscriber:
         derived_from: tosca.nodes.Root
+        description: XOS subscriber base class.
         capabilities:
             xos_base_subscriber_caps
         properties:
@@ -108,6 +130,10 @@
 
     tosca.nodes.CORDSubscriber:
         derived_from: tosca.nodes.Root
+        description: >
+            CORD: Subscriber. The Subscriber object contains all of the settings
+            for a CORD household. For example, it contains parental control
+            filter settings.
         capabilities:
             xos_base_subscriber_caps
         properties:
@@ -115,37 +141,57 @@
             firewall_enable:
                 type: boolean
                 default: false
+                description: If True, then firewalling is enabled.
             url_filter_enable:
                 type: boolean
                 default: false
+                description: If True, then parental controls are enabled.
             url_filter_level:
                 type: string
                 default: PG
+                description: The default URL filter level for the household.
             cdn_enable:
                 type: boolean
                 default: true
+                description: If True, then the CDN is enabled.
 
     tosca.nodes.CORDUser:
         derived_from: tosca.nodes.Root
+        description: >
+            CORD: User. The CORD user represents an individual device beloning
+            to the CORD Subscriber. Each device may have its own parental
+            controls.
+        capabilities:
+            device:
+                type: tosca.capabilities.xos.Device
         properties:
             level:
                 type: string
                 default: PG_13
+                description: Parental control level for this device.
             mac:
                 type: string
                 required: true
+                description: MAC address for this device.
 
     tosca.nodes.VOLTTenant:
         derived_from: tosca.nodes.Root
+        description: >
+            CORD: A Tenant of the vOLT Service. Each Tenant is tied to a
+            specific vlan_id.
         properties:
             xos_base_tenant_props
             vlan_id:
                 type: string
                 required: false
+                description: vlan_id for connection to subscriber household.
 
     tosca.nodes.User:
         derived_from: tosca.nodes.Root
 
+        description: >
+            An XOS User record. Users are able to login and use the XOS GUI.
+
         capabilities:
             user:
                 type: tosca.capabilities.xos.User
@@ -157,31 +203,43 @@
             firstname:
                 type: string
                 required: true
+                description: First name of User.
             lastname:
                 type: string
                 required: true
+                description: Last name of User.
             phone:
                 type: string
                 required: false
+                description: Phone number of User.
             user_url:
                 type: string
                 required: false
+                description: URL to User web page.
             public_key:
                 type: string
                 required: false
+                description: Public key that will be installed in Instances.
             is_active:
                 type: boolean
                 default: true
+                description: If True, the user may log in.
             is_admin:
                 type: boolean
                 default: false
+                description: If True, the user has root admin privileges.
             login_page:
                 type: string
                 required: false
+                description: Indicates what page the user should go to on login.
 
     tosca.nodes.NetworkTemplate:
         derived_from: tosca.nodes.Root
 
+        description: >
+            An XOS network template. Network templates contain settings associated
+            with a particular class of network.
+
         capabilities:
             network_template:
                 type: tosca.capabilities.xos.NetworkTemplate
@@ -190,21 +248,27 @@
             visibility:
                 type: string
                 default: private
+                description: Indicates whether network is publicly routable.
             translation:
                 type: string
                 default: none
+                description: Indicates whether network uses address translation.
             shared_network_name:
                 type: string
                 required: false
+                description: Attaches this template to a specific OpenStack network.
             shared_network_id:
                 type: string
                 required: false
+                description: Attaches this template to a specific OpenStack network.
             topology_kind:
                 type: string
                 default: BigSwitch
+                description: Describes the topology of the network.
             controller_kind:
                 type: string
                 required: false
+                description: Indicates the type of controller that the network is connected to.
 
     tosca.nodes.network.Network.XOS:
           # Due to bug? in implementation, we have to copy everything from
@@ -212,7 +276,8 @@
           # using derived_from.
           derived_from: tosca.nodes.Root
           description: >

-            The TOSCA Network node represents a simple, logical network service.

+            This is a variant of the TOSCA Network object that includes additional

+            XOS-specific properties.

           properties:

             ip_version:

               type: integer

@@ -280,41 +345,27 @@
             ports:

                 type: string
                 required: false
+                description: >
+                    A comma-separated list of protocols and ports. For example,
+                    "tcp/123, tcp/456-459, udp/111"
             labels:
                 type: string
                 required: false
+                description: A comma-separated list of labels for this network.
             permit_all_slices:
                 type: boolean
                 # In the data model, this is defaulted to false. However, to
                 # preserve Tosca semantics, we default it to true instead.
                 default: true
+                description: If True, then any slice may be attached to this network.
           capabilities:
             link:

               type: tosca.capabilities.network.Linkable
 
-#    tosca.nodes.XOSNetwork:
-#        derived_from: tosca.nodes.Root
-#
-#        capabilities:
-#            network:
-#                type: tosca.capabilities.xos.Network
-#
-#        properties:
-#            ports:
-#                type: string
-#                required: false
-#            labels:
-#                type: string
-#                required: false
-#            permit_all_slices:
-#                type: boolean
-#                default: false
-#            permitted_slices:
-#                type: string
-#                required: false
-
     tosca.nodes.Deployment:
         derived_from: tosca.nodes.Root
+        description: >
+            An XOS Deployment.
         capabilities:
             deployment:
                 type: tosca.capabilities.xos.Deployment
@@ -323,12 +374,16 @@
             accessControl:
                 type: string
                 default: allow all
+                description: ACL that describes who may use this deployment.
             flavors:
                 type: string
                 required: false
+                description: Comma-separated list of flavors that this deployment supports.
 
     tosca.nodes.Image:
         derived_from: tosca.nodes.Root
+        description: >
+            An XOS Operating System Image.
         capabilities:
             image:
                 type: tosca.capabilities.xos.Image
@@ -336,15 +391,21 @@
             disk_format:
                 type: string
                 required: false
+                description: Glance disk format.
             container_format:
                 type: string
                 required: false
+                description: Glance container format.
             path:
                 type: string
                 required: false
+                description: Path to Image file inside XOS docker container.
 
     tosca.nodes.Controller:
         derived_from: tosca.nodes.Root
+        description: >
+            An XOS controller. Controllers serve as the interface between
+            XOS and services such as OpenStack.
         capabilities:
             controller:
                 type: tosca.capabilities.xos.Controller
@@ -352,27 +413,36 @@
             backend_type:
                 type: string
                 required: false
+                description: Type of backend.
             version:
                 type: string
                 required: false
+                description: Version of backend.
             auth_url:
                 type: string
                 required: false
+                description: Keystone auth_url.
             admin_user:
                 type: string
                 required: false
+                description: Keystone username.
             admin_password:
                 type: string
                 required: false
+                description: Keystone password.
             admin_tenant:
                 type: string
                 required: false
+                description: Tenant associated with admin account.
             domain:
                 type: string
                 required: false
+                description: OpenStack domain (or "Default")
 
     tosca.nodes.Site:
         derived_from: tosca.nodes.Root
+        description: >
+            An XOS Site. Sites are containers for Users and/or Nodes.
         capabilities:
             site:
                 type: tosca.capabilities.xos.Site
@@ -380,19 +450,22 @@
              display_name:
                  type: string
                  required: false
-                 description: name of the site
+                 description: Name of the site.
              site_url:
                  type: string
                  required: false
+                 description: URL of site web page.
              enabled:
                  type: boolean
                  default: true
              hosts_nodes:
                  type: boolean
                  default: true
+                 description: If True, then this site hosts nodes where Instances may be instantiated.
              hosts_users:
                  type: boolean
                  default: true
+                 description: If True, then this site hosts users who may use XOS.
              is_public:
                  type: boolean
                  default: true
@@ -400,7 +473,10 @@
 
     tosca.nodes.Slice:
         derived_from: tosca.nodes.Root
-        capability:
+        description: >
+            An XOS Slice. A slice is a collection of instances that share
+            common attributes.
+        capabilities:
             slice:
                 type: tosca.capabilities.xos.Slice
         properties:
@@ -410,15 +486,21 @@
             description:
                 type: string
                 required: false
+                description: Description of this slice.
             slice_url:
                 type: string
                 required: false
+                description: URL to web page that describes slice.
             max_instances:
                 type: integer
                 default: 10
+                description: Quota of instances that this slice may create.
 
     tosca.nodes.Node:
         derived_from: tosca.nodes.Root
+        description: >
+            An XOS Node. Nodes are physical machines that host virtual machines
+            and/or containers.
         capability:
             node:
                 type: tosca.capabilities.xos.Node
@@ -465,6 +547,7 @@
 
     tosca.relationships.ConnectsToSlice:
         derived_from: tosca.relationships.Root
+        valid_target_types: [ tosca.capabilities.xos.Slice ]
 
     #    tosca.relationships.OwnsNetwork:
     #        derived_from: tosca.relationships.Root
@@ -476,25 +559,27 @@
 
     tosca.relationships.AdminPrivilege:
         derived_from: tosca.relationships.Root
-        valid_target_types: [ tosca.capabilities.xos.Slice, tosca.capabiltys.xos.Site ]
+        valid_target_types: [ tosca.capabilities.xos.Slice, tosca.capabilities.xos.Site ]
 
     tosca.relationships.AccessPrivilege:
         derived_from: tosca.relationships.Root
-        valid_target_types: [ tosca.capabilities.xos.Slice, tosca.capabiltys.xos.Site ]
+        valid_target_types: [ tosca.capabilities.xos.Slice, tosca.capabilities.xos.Site ]
 
     tosca.relationships.PIPrivilege:
         derived_from: tosca.relationships.Root
-        valid_target_types: [ tosca.capabiltys.xos.Site ]
+        valid_target_types: [ tosca.capabilities.xos.Site ]
 
     tosca.relationships.TechPrivilege:
         derived_from: tosca.relationships.Root
-        valid_target_types: [ tosca.capabiltys.xos.Site ]
+        valid_target_types: [ tosca.capabilities.xos.Site ]
 
     tosca.relationships.SubscriberDevice:
         derived_from: tosca.relationships.Root
+        valid_target_types: [ tosca.capabilities.xos.Subscriber ]
 
     tosca.relationships.BelongsToSubscriber:
         derived_from: tosca.relationships.Root
+        valid_target_types: [ tosca.capabilities.xos.Subscriber ]
 
     tosca.capabilities.xos.Service:
         derived_from: tosca.capabilities.Root
@@ -532,6 +617,10 @@
         derived_from: tosca.capabilities.Root
         description: An XOS Subscriber
 
+    tosca.capabilities.xos.Device:
+        derived_from: tosca.capabilities.Root
+        description: A device belonging to an XOS subscriber
+
     tosca.capabilities.xos.Node:
         derived_from: tosca.capabilities.Root
         description: An XOS Node
diff --git a/xos/tosca/custom_types/xos.yaml b/xos/tosca/custom_types/xos.yaml
index 96c03fa..9e25754 100644
--- a/xos/tosca/custom_types/xos.yaml
+++ b/xos/tosca/custom_types/xos.yaml
@@ -20,6 +20,9 @@
 node_types:
     tosca.nodes.Service:
         derived_from: tosca.nodes.Root
+        description: >
+            An XOS Service object. Services may be listed in the Service
+            directory and may be linked together via Tenancy Relationships.
         capabilities:
             scalable:
                 type: tosca.capabilities.Scalable
@@ -29,26 +32,34 @@
             kind:
                 type: string
                 default: generic
+                description: Type of service.
             view_url:
                 type: string
                 required: false
+                description: URL to follow when icon is clicked in the Service Directory.
             icon_url:
                 type: string
                 required: false
+                description: ICON to display in the Service Directory.
             enabled:
                 type: boolean
                 default: true
             published:
                 type: boolean
                 default: true
+                description: If True then display this Service in the Service Directory.
             public_key:
                 type: string
                 required: false
+                description: Public key to install into Instances to allows Services to SSH into them.
             versionNumber:
                 type: string
                 required: false
+                description: Version number of Service.
 
     tosca.nodes.VCPEService:
+        description: >
+            CORD: The vCPE Service.
         derived_from: tosca.nodes.Root
         capabilities:
             scalable:
@@ -59,30 +70,39 @@
             kind:
                 type: string
                 default: generic
+                description: Type of service.
             view_url:
                 type: string
                 required: false
+                description: URL to follow when icon is clicked in the Service Directory.
             icon_url:
                 type: string
                 required: false
+                description: ICON to display in the Service Directory.
             enabled:
                 type: boolean
                 default: true
             published:
                 type: boolean
                 default: true
+                description: If True then display this Service in the Service Directory.
             public_key:
                 type: string
                 required: false
+                description: Public key to install into Instances to allows Services to SSH into them.
             versionNumber:
                 type: string
                 required: false
+                description: Version number of Service.
             backend_network_label:
                 type: string
                 required: false
+                description: Label that matches network used to connect HPC and BBS services.
 
     tosca.nodes.VBNGService:
         derived_from: tosca.nodes.Root
+        description: >
+            CORD: The vBNG Service.
         capabilities:
             scalable:
                 type: tosca.capabilities.Scalable
@@ -92,30 +112,39 @@
             kind:
                 type: string
                 default: generic
+                description: Type of service.
             view_url:
                 type: string
                 required: false
+                description: URL to follow when icon is clicked in the Service Directory.
             icon_url:
                 type: string
                 required: false
+                description: ICON to display in the Service Directory.
             enabled:
                 type: boolean
                 default: true
             published:
                 type: boolean
                 default: true
+                description: If True then display this Service in the Service Directory.
             public_key:
                 type: string
                 required: false
+                description: Public key to install into Instances to allows Services to SSH into them.
             versionNumber:
                 type: string
                 required: false
+                description: Version number of Service.
             vbng_url:
                 type: string
                 required: false
+                description: URL of REST API endpoint for vBNG Service.
 
     tosca.nodes.CDNService:
         derived_from: tosca.nodes.Root
+        description: >
+            Content Delivery Network Service. Includes Request Routing and Hypercache.
         capabilities:
             scalable:
                 type: tosca.capabilities.Scalable
@@ -125,27 +154,34 @@
             kind:
                 type: string
                 default: generic
+                description: Type of service.
             view_url:
                 type: string
                 required: false
+                description: URL to follow when icon is clicked in the Service Directory.
             icon_url:
                 type: string
                 required: false
+                description: ICON to display in the Service Directory.
             enabled:
                 type: boolean
                 default: true
             published:
                 type: boolean
                 default: true
+                description: If True then display this Service in the Service Directory.
             public_key:
                 type: string
                 required: false
+                description: Public key to install into Instances to allows Services to SSH into them.
             versionNumber:
                 type: string
                 required: false
+                description: Version number of Service.
 
     tosca.nodes.Subscriber:
         derived_from: tosca.nodes.Root
+        description: XOS subscriber base class.
         capabilities:
             subscriber:
                 type: tosca.capabilities.xos.Subscriber
@@ -153,12 +189,18 @@
             kind:
                 type: string
                 default: generic
+                description: Kind of subscriber
             service_specific_id:
                 type: string
                 required: false
+                description: Service specific ID
 
     tosca.nodes.CORDSubscriber:
         derived_from: tosca.nodes.Root
+        description: >
+            CORD: Subscriber. The Subscriber object contains all of the settings
+            for a CORD household. For example, it contains parental control
+            filter settings.
         capabilities:
             subscriber:
                 type: tosca.capabilities.xos.Subscriber
@@ -166,48 +208,72 @@
             kind:
                 type: string
                 default: generic
+                description: Kind of subscriber
             service_specific_id:
                 type: string
                 required: false
+                description: Service specific ID
             firewall_enable:
                 type: boolean
                 default: false
+                description: If True, then firewalling is enabled.
             url_filter_enable:
                 type: boolean
                 default: false
+                description: If True, then parental controls are enabled.
             url_filter_level:
                 type: string
                 default: PG
+                description: The default URL filter level for the household.
             cdn_enable:
                 type: boolean
                 default: true
+                description: If True, then the CDN is enabled.
 
     tosca.nodes.CORDUser:
         derived_from: tosca.nodes.Root
+        description: >
+            CORD: User. The CORD user represents an individual device beloning
+            to the CORD Subscriber. Each device may have its own parental
+            controls.
+        capabilities:
+            device:
+                type: tosca.capabilities.xos.Device
         properties:
             level:
                 type: string
                 default: PG_13
+                description: Parental control level for this device.
             mac:
                 type: string
                 required: true
+                description: MAC address for this device.
 
     tosca.nodes.VOLTTenant:
         derived_from: tosca.nodes.Root
+        description: >
+            CORD: A Tenant of the vOLT Service. Each Tenant is tied to a
+            specific vlan_id.
         properties:
             kind:
                 type: string
                 default: generic
+                description: Kind of tenant
             service_specific_id:
                 type: string
                 required: false
+                description: Service specific ID
             vlan_id:
                 type: string
                 required: false
+                description: vlan_id for connection to subscriber household.
 
     tosca.nodes.User:
         derived_from: tosca.nodes.Root
 
+        description: >
+            An XOS User record. Users are able to login and use the XOS GUI.
+
         capabilities:
             user:
                 type: tosca.capabilities.xos.User
@@ -219,31 +285,43 @@
             firstname:
                 type: string
                 required: true
+                description: First name of User.
             lastname:
                 type: string
                 required: true
+                description: Last name of User.
             phone:
                 type: string
                 required: false
+                description: Phone number of User.
             user_url:
                 type: string
                 required: false
+                description: URL to User web page.
             public_key:
                 type: string
                 required: false
+                description: Public key that will be installed in Instances.
             is_active:
                 type: boolean
                 default: true
+                description: If True, the user may log in.
             is_admin:
                 type: boolean
                 default: false
+                description: If True, the user has root admin privileges.
             login_page:
                 type: string
                 required: false
+                description: Indicates what page the user should go to on login.
 
     tosca.nodes.NetworkTemplate:
         derived_from: tosca.nodes.Root
 
+        description: >
+            An XOS network template. Network templates contain settings associated
+            with a particular class of network.
+
         capabilities:
             network_template:
                 type: tosca.capabilities.xos.NetworkTemplate
@@ -252,21 +330,27 @@
             visibility:
                 type: string
                 default: private
+                description: Indicates whether network is publicly routable.
             translation:
                 type: string
                 default: none
+                description: Indicates whether network uses address translation.
             shared_network_name:
                 type: string
                 required: false
+                description: Attaches this template to a specific OpenStack network.
             shared_network_id:
                 type: string
                 required: false
+                description: Attaches this template to a specific OpenStack network.
             topology_kind:
                 type: string
                 default: BigSwitch
+                description: Describes the topology of the network.
             controller_kind:
                 type: string
                 required: false
+                description: Indicates the type of controller that the network is connected to.
 
     tosca.nodes.network.Network.XOS:
           # Due to bug? in implementation, we have to copy everything from
@@ -274,7 +358,8 @@
           # using derived_from.
           derived_from: tosca.nodes.Root
           description: >

-            The TOSCA Network node represents a simple, logical network service.

+            This is a variant of the TOSCA Network object that includes additional

+            XOS-specific properties.

           properties:

             ip_version:

               type: integer

@@ -342,41 +427,27 @@
             ports:

                 type: string
                 required: false
+                description: >
+                    A comma-separated list of protocols and ports. For example,
+                    "tcp/123, tcp/456-459, udp/111"
             labels:
                 type: string
                 required: false
+                description: A comma-separated list of labels for this network.
             permit_all_slices:
                 type: boolean
                 # In the data model, this is defaulted to false. However, to
                 # preserve Tosca semantics, we default it to true instead.
                 default: true
+                description: If True, then any slice may be attached to this network.
           capabilities:
             link:

               type: tosca.capabilities.network.Linkable
 
-#    tosca.nodes.XOSNetwork:
-#        derived_from: tosca.nodes.Root
-#
-#        capabilities:
-#            network:
-#                type: tosca.capabilities.xos.Network
-#
-#        properties:
-#            ports:
-#                type: string
-#                required: false
-#            labels:
-#                type: string
-#                required: false
-#            permit_all_slices:
-#                type: boolean
-#                default: false
-#            permitted_slices:
-#                type: string
-#                required: false
-
     tosca.nodes.Deployment:
         derived_from: tosca.nodes.Root
+        description: >
+            An XOS Deployment.
         capabilities:
             deployment:
                 type: tosca.capabilities.xos.Deployment
@@ -384,20 +455,24 @@
             no-delete:
                 type: boolean
                 default: false
-                description: do not allow Tosca to delete this object
+                description: Do not allow Tosca to delete this object
             no-create:
                 type: boolean
                 default: false
-                description: do not allow Tosca to create this object
+                description: Do not allow Tosca to create this object
             accessControl:
                 type: string
                 default: allow all
+                description: ACL that describes who may use this deployment.
             flavors:
                 type: string
                 required: false
+                description: Comma-separated list of flavors that this deployment supports.
 
     tosca.nodes.Image:
         derived_from: tosca.nodes.Root
+        description: >
+            An XOS Operating System Image.
         capabilities:
             image:
                 type: tosca.capabilities.xos.Image
@@ -405,15 +480,21 @@
             disk_format:
                 type: string
                 required: false
+                description: Glance disk format.
             container_format:
                 type: string
                 required: false
+                description: Glance container format.
             path:
                 type: string
                 required: false
+                description: Path to Image file inside XOS docker container.
 
     tosca.nodes.Controller:
         derived_from: tosca.nodes.Root
+        description: >
+            An XOS controller. Controllers serve as the interface between
+            XOS and services such as OpenStack.
         capabilities:
             controller:
                 type: tosca.capabilities.xos.Controller
@@ -421,27 +502,36 @@
             backend_type:
                 type: string
                 required: false
+                description: Type of backend.
             version:
                 type: string
                 required: false
+                description: Version of backend.
             auth_url:
                 type: string
                 required: false
+                description: Keystone auth_url.
             admin_user:
                 type: string
                 required: false
+                description: Keystone username.
             admin_password:
                 type: string
                 required: false
+                description: Keystone password.
             admin_tenant:
                 type: string
                 required: false
+                description: Tenant associated with admin account.
             domain:
                 type: string
                 required: false
+                description: OpenStack domain (or "Default")
 
     tosca.nodes.Site:
         derived_from: tosca.nodes.Root
+        description: >
+            An XOS Site. Sites are containers for Users and/or Nodes.
         capabilities:
             site:
                 type: tosca.capabilities.xos.Site
@@ -449,19 +539,22 @@
              display_name:
                  type: string
                  required: false
-                 description: name of the site
+                 description: Name of the site.
              site_url:
                  type: string
                  required: false
+                 description: URL of site web page.
              enabled:
                  type: boolean
                  default: true
              hosts_nodes:
                  type: boolean
                  default: true
+                 description: If True, then this site hosts nodes where Instances may be instantiated.
              hosts_users:
                  type: boolean
                  default: true
+                 description: If True, then this site hosts users who may use XOS.
              is_public:
                  type: boolean
                  default: true
@@ -469,7 +562,10 @@
 
     tosca.nodes.Slice:
         derived_from: tosca.nodes.Root
-        capability:
+        description: >
+            An XOS Slice. A slice is a collection of instances that share
+            common attributes.
+        capabilities:
             slice:
                 type: tosca.capabilities.xos.Slice
         properties:
@@ -479,15 +575,21 @@
             description:
                 type: string
                 required: false
+                description: Description of this slice.
             slice_url:
                 type: string
                 required: false
+                description: URL to web page that describes slice.
             max_instances:
                 type: integer
                 default: 10
+                description: Quota of instances that this slice may create.
 
     tosca.nodes.Node:
         derived_from: tosca.nodes.Root
+        description: >
+            An XOS Node. Nodes are physical machines that host virtual machines
+            and/or containers.
         capability:
             node:
                 type: tosca.capabilities.xos.Node
@@ -534,6 +636,7 @@
 
     tosca.relationships.ConnectsToSlice:
         derived_from: tosca.relationships.Root
+        valid_target_types: [ tosca.capabilities.xos.Slice ]
 
     #    tosca.relationships.OwnsNetwork:
     #        derived_from: tosca.relationships.Root
@@ -545,25 +648,27 @@
 
     tosca.relationships.AdminPrivilege:
         derived_from: tosca.relationships.Root
-        valid_target_types: [ tosca.capabilities.xos.Slice, tosca.capabiltys.xos.Site ]
+        valid_target_types: [ tosca.capabilities.xos.Slice, tosca.capabilities.xos.Site ]
 
     tosca.relationships.AccessPrivilege:
         derived_from: tosca.relationships.Root
-        valid_target_types: [ tosca.capabilities.xos.Slice, tosca.capabiltys.xos.Site ]
+        valid_target_types: [ tosca.capabilities.xos.Slice, tosca.capabilities.xos.Site ]
 
     tosca.relationships.PIPrivilege:
         derived_from: tosca.relationships.Root
-        valid_target_types: [ tosca.capabiltys.xos.Site ]
+        valid_target_types: [ tosca.capabilities.xos.Site ]
 
     tosca.relationships.TechPrivilege:
         derived_from: tosca.relationships.Root
-        valid_target_types: [ tosca.capabiltys.xos.Site ]
+        valid_target_types: [ tosca.capabilities.xos.Site ]
 
     tosca.relationships.SubscriberDevice:
         derived_from: tosca.relationships.Root
+        valid_target_types: [ tosca.capabilities.xos.Subscriber ]
 
     tosca.relationships.BelongsToSubscriber:
         derived_from: tosca.relationships.Root
+        valid_target_types: [ tosca.capabilities.xos.Subscriber ]
 
     tosca.capabilities.xos.Service:
         derived_from: tosca.capabilities.Root
@@ -601,6 +706,10 @@
         derived_from: tosca.capabilities.Root
         description: An XOS Subscriber
 
+    tosca.capabilities.xos.Device:
+        derived_from: tosca.capabilities.Root
+        description: A device belonging to an XOS subscriber
+
     tosca.capabilities.xos.Node:
         derived_from: tosca.capabilities.Root
         description: An XOS Node
diff --git a/xos/tosca/definitions/TOSCA_definition_1_0.yaml b/xos/tosca/definitions/TOSCA_definition_1_0.yaml
index c21f0bc..97a8c44 100644
--- a/xos/tosca/definitions/TOSCA_definition_1_0.yaml
+++ b/xos/tosca/definitions/TOSCA_definition_1_0.yaml
@@ -1,4 +1,4 @@
-#    Licensed under the Apache License, Version 2.0 (the "License"); you may
+#    Licensed under the Apache License, Version 2.0 (the "License"); you may
 #    not use this file except in compliance with the License. You may obtain
 #    a copy of the License at
 #
@@ -47,6 +47,11 @@
 
 tosca.nodes.Compute:
   derived_from: tosca.nodes.Root
+  description: >
+    The TOSCA Compute node represents one or more real or virtual processors
+    of software applications or services along with other essential local
+    resources.  Collectively, the resources the compute node represents can
+    logically be viewed as a (real or virtual) server.
   attributes:
     private_address:
       type: string
diff --git a/xos/tosca/doctemplates/html/node_type.html b/xos/tosca/doctemplates/html/node_type.html
new file mode 100644
index 0000000..95e8b7b
--- /dev/null
+++ b/xos/tosca/doctemplates/html/node_type.html
@@ -0,0 +1,46 @@
+<hr>
+<h2 id="{{ node_type.node_type_name }}">{{ node_type.node_type_name }}</h2>
+<blockquote>
+
+<h3>Description:</h3>
+{% if node_type.description %}
+  <blockquote>
+  {{ node_type.description }}
+  </blockquote>
+{% endif %}
+
+<h3>Capabilities:</h3>
+{% if node_type.capabilities %}
+  <blockquote>
+  <table class="properties">
+  <tr><th>name</th><th>type</th></tr>
+  {% for capname,cap in node_type.capabilities.iteritems() %}
+     <tr><td>{{ capname }}</td><td>{{ cap.type }}</td></tr>
+  {% endfor %}
+  </table>
+  </blockquote>
+{% endif %}
+
+<h3>Properties:</h3>
+{% if node_type.properties %}
+  <blockquote>
+  <table class="properties">
+  <tr><th>name</th><th>required</th><th>type</th><th>default</th></tr>
+  {% for propname,prop in node_type.properties.iteritems() %}
+     <tr><td>{{ propname }}</td>
+         <td>{{ prop.required }}</td>
+         <td>{{ prop.type }}</td>
+         <td>{{ prop.default }}</td>
+     </tr>
+     {% if prop.description %}
+     <tr><td colspan=4 class="helptext" style="apadding-left: 30px;">{{ prop.description }}</td></tr>
+     {% endif %}
+  {% endfor %}
+  </table>
+  </blockquote>
+{% endif %}
+
+</blockquote>
+
+
+
diff --git a/xos/tosca/doctemplates/html/toscadoctemplate.html b/xos/tosca/doctemplates/html/toscadoctemplate.html
new file mode 100644
index 0000000..8568d33
--- /dev/null
+++ b/xos/tosca/doctemplates/html/toscadoctemplate.html
@@ -0,0 +1,80 @@
+<html><head>
+<title>XOS TOSCA Reference</title>
+
+<style>
+.properties {
+  border-collapse: collapse;
+}
+.properties td, .properties th {
+  border: 1px solid black;
+  padding: 3px 7px 2px 7px;
+}
+.properties th {
+  font-size: 1.1em;
+  padding-top: 5px;
+  padding-bottom: 4px;
+  oldbackground-color: #A7C942;
+  background-color: #2d6ca2;
+  color: #ffffff;
+}
+.helptext {
+  padding-left: 30px !important;
+  color: rgb(153, 153, 153);
+}
+</style>
+
+</head>
+<body>
+
+<h1>XOS TOSCA Reference</h1>
+
+<p>This documentation is autogenerated from the XOS Tosca custom_types
+specification (xos/tosca/custom_types/xos.m4).
+
+Table of Contents:
+<ul>
+<li>Node Types
+<ul>
+{% for node_type in node_types %}
+  {% if node_type.node_type_kind == "node" %}
+    <li><a href="#{{ node_type.node_type_name }}">{{ node_type.node_type_name }}</a></li>
+  {% endif %}
+{% endfor %}
+</li>
+</ul>
+<li><a href="#xos_relationships">Relationships</a></li>
+<li><a href="#xos_capabilities">Capabilities</a></li>
+</ul>
+
+{% for node_type in node_types %}
+  {% if node_type.node_type_kind == "node" %}
+    {% include 'node_type.html' %}
+  {% endif %}
+{% endfor %}
+
+<h3 id="xos_relationships">XOS Relationships</h3>
+<blockquote>
+<table class="properties">
+<tr><th>name</th><th>target_types</th></tr>
+{% for node_type in node_types %}
+  {% if node_type.node_type_kind == "relationship" %}
+      <tr><td>{{ node_type.node_type_name }}</td><td>{{ node_type.valid_target_types|join(', ') }}</td></tr>
+  {% endif %}
+{% endfor %}
+</table>
+</blockquote>
+
+<h3 id="xos_capabilities">XOS Capabilities</h3>
+<blockquote>
+<table class="properties">
+<tr><th>name</th></tr>
+{% for node_type in node_types %}
+  {% if node_type.node_type_kind == "capability" %}
+      <tr><td>{{ node_type.node_type_name }}</td></tr>
+  {% endif %}
+{% endfor %}
+</table>
+</blockquote>
+
+</body>
+</html>
diff --git a/xos/tosca/makedocs.py b/xos/tosca/makedocs.py
new file mode 100644
index 0000000..6a9e959
--- /dev/null
+++ b/xos/tosca/makedocs.py
@@ -0,0 +1,65 @@
+import jinja2
+import os
+import sys
+import yaml
+import pdb
+
+# add the parent directory to sys.path
+import os,sys,inspect
+currentdir = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
+parentdir = os.path.dirname(currentdir)
+sys.path.append(parentdir)
+
+# a bit of a hack for developing -- run m4 to generate xos.yaml from xos.m4
+os.system("m4 %s/custom_types/xos.m4 > %s/custom_types/xos.yaml" % (currentdir, currentdir))
+
+"""
+{'derived_from': 'tosca.nodes.Root', 'capabilities': {'scalable': {'type': 'tosca.capabilities.Scalable'},
+'service': {'type': 'tosca.capabilities.xos.Service'}}, 'properties': {'icon_url': {'required': False,
+'type': 'string'}, 'public_key': {'required': False, 'type': 'string'}, 'kind': {'default': 'generic',
+'type': 'string'}, 'published': {'default': True, 'type': 'boolean'}, 'view_url': {'required': False, 'type': 'string'}, 'enabled': {'default': True, 'type': 'boolean'}, 'versionNumber': {'required': False, 'type': 'string'}}}
+"""
+
+class ToscaDocumenter(object):
+    def __init__(self, fn="./custom_types/xos.yaml", templatedir="./doctemplates/html", templatename="toscadoctemplate.html", destfn="tosca_reference.html"):
+        self.env = jinja2.Environment(loader=jinja2.FileSystemLoader(templatedir))
+
+        self.node_types = {}
+        self.root_types = yaml.load(file("definitions/TOSCA_definition_1_0.yaml").read())
+        for x in self.root_types.keys():
+            if x in ["tosca.nodes.Compute", "tosca.nodes.network.Network"]:
+                self.node_types[x] = self.root_types[x]
+
+        self.custom_types = yaml.load(file(fn).read())
+        self.node_types.update(self.custom_types.get("node_types"))
+
+        self.destfn = destfn
+        self.templatename = templatename
+
+    def run(self):
+        node_types=[]
+        for k in sorted(self.node_types.keys()):
+            nt = self.node_types[k]
+            nt["node_type_name"] = k
+
+            derived_from = nt.get("derived_from","")
+
+            if derived_from.startswith("tosca.nodes"):
+                nt["node_type_kind"] = "node"
+            elif derived_from.startswith("tosca.capabilities"):
+                nt["node_type_kind"] = "capability"
+            elif derived_from.startswith("tosca.relationships"):
+                nt["node_type_kind"] = "relationship"
+
+            node_types.append(nt)
+
+        template = self.env.get_template(self.templatename)
+
+        self.destf = open(self.destfn,"w")
+        self.destf.write(template.render(node_types=node_types))
+
+def main():
+    ToscaDocumenter().run()
+
+if __name__=="__main__":
+    main()