Merge pull request #118 from davidkbainbridge/docker-changes

Docker changes
diff --git a/containers/README.md b/containers/README.md
new file mode 100644
index 0000000..0bdc74b
--- /dev/null
+++ b/containers/README.md
@@ -0,0 +1,77 @@
+# XOS Docker Images
+
+## Introduction
+
+ XOS is comprised of 3 core services:
+
+  * A database backend (postgres)
+  * A webserver front end (django)
+  * A synchronizer daemon that interacts with the openstack backend.
+
+We have created separate dockerfiles for each of these services, making it
+easier to build the services independently and also deploy and run them in
+isolated environments.
+
+#### Database Container
+
+To build and run the database container:
+
+```
+$ cd postgres; make build && make run
+```
+
+#### XOS Container
+
+To build and run the xos webserver container:
+
+```
+$ cd xos; make build && make run
+```
+
+You should now be able to access the login page by visiting
+`http://localhost:80` and log in using the default `paadmin@vicci.org` account
+with password `letmein`. It may be helpful to bootstrap xos with some sample
+data; deployment, controllers, sites, slices, etc. You can get started by
+loading tosca configuration for the opencloud demo dataset:
+
+```
+$ cd xos; make runtosca
+```
+
+Or you can create you own tosca configuraton file and customize the dataset
+however you want. You can all load your own tosca configuration by setting the
+`TOSCA_CONFIG_PATH` environment variable before executing the make command:
+
+```
+$ cd xos; TOSCA_CONFIG_PATH=/path/to/tosca/config.yaml make runtosca
+```
+
+#### Synchronizer Container
+
+The Synchronizer shares many of the same dependencies as the xos container. The
+synchronizer container takes advantage of this by building itself on top of the
+xos image. This means you must build the xos image before building the
+synchronizer image. The XOS and synchronizer containers can run on separate
+hosts, but you must build the xos image on the host that you plan to run the
+synchronizer container. Assuming you have already built the xos container,
+executing the following will build and run the synchronizer container:
+
+```
+$ cd synchronizer; make build && make run
+```
+
+#### Solution Compose File ![](https://img.shields.io/badge/compose-beta-red.svg)
+
+[Docker Compose](https://docs.docker.com/compose/) is a tool for defining and
+running multi-container Docker applications. With Compose, you use a Compose
+file to configure your application’s services. Then, using a single command, you
+create, start, scale, and manage all the services from your configuration.
+
+Included is a compose file in *YAML* format with content defined by the [Docker
+Compose Format](https://docs.docker.com/compose/compose-file/). With the compose
+file a complete XOS solution based on docker containers can be instantiated
+using a single command. To start the instance you can use the command:
+
+```
+$ docker-compose -f xos-compose.yml up -d
+```
diff --git a/containers/postgresql/Makefile b/containers/postgresql/Makefile
index 327f661..38f159c 100644
--- a/containers/postgresql/Makefile
+++ b/containers/postgresql/Makefile
@@ -1,21 +1,25 @@
+IMAGE_NAME:=xosproject/xos-postgress
+CONTAINER_NAME:=xos-db-postgress
+NO_DOCKER_CACHE?=false
+
 .PHONY: build
-build: ; docker build --rm -t postgres .
+build: ; docker build --no-cache=${NO_DOCKER_CACHE} --rm -t ${IMAGE_NAME} .
 
 .PHONY: run
-run: ; docker run -d -p 5432:5432 --name postgres-server postgres
+run: ; docker run -d -p 5432:5432 --name ${CONTAINER_NAME} ${IMAGE_NAME}
 
 .PHONY: stop
-stop: ; docker stop postgres-server
+stop: ; docker stop ${CONTAINER_NAME}
 
 .PHONY: rm
-rm: ; docker rm postgres-server
+rm: ; docker rm ${CONTAINER_NAME}
 
 .PHONE: rmi
-rmi: ; docker rmi postgres
+rmi: ; docker rmi ${IMAGE_NAME}
 
 .PHONY: backup
-backupvol: ; docker run --volumes-from postgres-server -v /backup:/backup postgres tar cvf /backup/backup-postgres.tar /var/lib/postgresql
+backupvol: ; docker run --volumes-from ${CONTAINER_NAME} -v /backup:/backup postgres tar cvf /backup/backup-postgres.tar /var/lib/postgresql
 
 .PHONY: restore
-restorevol: ; docker run --volumes-from postgres-server -v /backup:/backup postgres cd /var/lib/postgresql && tar xvf /backup/backup-postgres.tar
+restorevol: ; docker run --volumes-from ${CONTAINER_NAME} -v /backup:/backup postgres cd /var/lib/postgresql && tar xvf /backup/backup-postgres.tar
 
diff --git a/containers/synchronizer/Dockerfile b/containers/synchronizer/Dockerfile
index 44b058e..f9d79ae 100644
--- a/containers/synchronizer/Dockerfile
+++ b/containers/synchronizer/Dockerfile
@@ -1,4 +1,4 @@
-FROM       xos
+FROM       xosproject/xos
 
 # Install custom Ansible
 RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y \
diff --git a/containers/synchronizer/Makefile b/containers/synchronizer/Makefile
index 14520d9..8620438 100644
--- a/containers/synchronizer/Makefile
+++ b/containers/synchronizer/Makefile
@@ -1,10 +1,12 @@
-CONTAINER_NAME:=synchronizer-server
+IMAGE_NAME:=xosproject/xos-synchronizer-openstack
+CONTAINER_NAME:=xos-synchronizer
+NO_DOCKER_CACHE?=false
 
 .PHONY: build
-build: ; docker build --rm -t synchronizer .
+build: ; docker build --no-cache=${NO_DOCKER_CACHE} --rm -t ${IMAGE_NAME} .
 
 .PHONY: run
-run: ; docker run -d --name ${CONTAINER_NAME} synchronizer
+run: ; docker run -d --name ${CONTAINER_NAME} ${IMAGE_NAME}
 
 .PHONY: stop
 stop: ; docker stop ${CONTAINER_NAME}
diff --git a/containers/xos-compose.yml b/containers/xos-compose.yml
new file mode 100644
index 0000000..27a3b5a
--- /dev/null
+++ b/containers/xos-compose.yml
@@ -0,0 +1,25 @@
+xos_db:
+    image: xosproject/xos-postgress
+    expose:
+        - "5432"
+
+xos_synchronizer_openstack:
+    image: xosproject/xos-synchronizer-openstack
+    labels:
+        org.xosproject.kind: synchronizer
+        org.xosproject.target: openstack
+
+# 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:
+        - "8000:8000"
+    links:
+        - xos_db
diff --git a/containers/xos/Dockerfile.templ b/containers/xos/Dockerfile.templ
new file mode 100644
index 0000000..e669692
--- /dev/null
+++ b/containers/xos/Dockerfile.templ
@@ -0,0 +1,88 @@
+FROM       ubuntu:14.04.3
+
+# XXX Workaround for docker bug:
+# https://github.com/docker/docker/issues/6345
+# Kernel 3.15 breaks docker, uss the line below as a workaround
+# until there is a fix
+RUN ln -s -f /bin/true /usr/bin/chfn
+# XXX End workaround
+
+# Install.
+RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y \
+    curl \
+    gcc \
+    geoip-database \
+    git \
+    graphviz \
+    graphviz-dev \
+    libgeoip1 \
+    libxslt1.1 \
+    libxslt1-dev \
+    libyaml-dev \
+    m4 \
+    pkg-config \
+    python-dev \
+    python-httplib2 \
+    python-pip \
+    python-psycopg2 \
+    python-pycurl \
+    python-setuptools \
+    tar \
+    wget \
+##### observer dependencies  
+    python-keystoneclient \
+    python-novaclient \
+    python-neutronclient \
+    python-glanceclient \
+    python-ceilometerclient
+
+RUN pip install -U \
+    django==1.7 \
+    django-bitfield \
+    django-crispy-forms \
+    django-encrypted-fields \
+    django_evolution \
+    django-extensions \
+    django-filter \
+    django-geoposition \
+    django-ipware \
+    django_rest_swagger \
+    django-suit \
+    django-timezones \
+    djangorestframework==2.4.4 \
+    dnslib \
+    google_api_python_client \
+    httplib2 \
+    httplib2.ca_certs_locater \
+    lxml \  
+    markdown \
+    netaddr \
+    python-dateutil \
+    python_gflags \
+    python-keyczar \
+    pygraphviz \
+    pytz \
+    pyyaml \
+    requests
+
+ADD http://code.jquery.com/jquery-1.9.1.min.js /usr/local/lib/python2.7/dist-packages/suit/static/suit/js/
+
+# Install XOS
+RUN git clone XOS_GIT_REPO -b XOS_GIT_BRANCH /tmp/xos && \
+    mv /tmp/xos/xos /opt/ && \
+    chmod +x /opt/xos/scripts/opencloud && \
+    /opt/xos/scripts/opencloud genkeys
+
+# install Tosca engine
+RUN bash /opt/xos/tosca/install_tosca.sh
+
+EXPOSE 8000
+
+# Set environment variables.
+ENV HOME /root
+
+# Define working directory.
+WORKDIR /root
+
+# Define default command.
+CMD python /opt/xos/manage.py runserver 0.0.0.0:8000 --insecure
diff --git a/containers/xos/Makefile b/containers/xos/Makefile
index c71873e..367f0ec 100644
--- a/containers/xos/Makefile
+++ b/containers/xos/Makefile
@@ -1,11 +1,18 @@
 CONTAINER_NAME:=xos-server
+IMAGE_NAME:=xosproject/xos
 TOSCA_CONFIG_PATH:=/opt/xos/configurations/opencloud/opencloud.yaml
+XOS_GIT_REPO?=git://github.com/open-cloud/xos.git
+XOS_GIT_BRANCH?=master
+NO_DOCKER_CACHE?=false
 
 .PHONY: build
-build: ; docker build --rm -t xos . && ./initdb
+build: ; 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} -
 
 .PHONY: run
-run: ; docker run -d --name ${CONTAINER_NAME} -p 80:8000 xos
+run: ; docker run -d --name ${CONTAINER_NAME} -p 80:8000 ${IMAGE_NAME}
 
 .PHONY: runtosca
 runtosca: ; docker exec -it ${CONTAINER_NAME} /usr/bin/python /opt/xos/tosca/run.py padmin@vicci.org ${TOSCA_CONFIG_PATH}
diff --git a/containers/xos/initdb b/containers/xos/initdb
index bd020c5..41e0a9a 100755
--- a/containers/xos/initdb
+++ b/containers/xos/initdb
@@ -1,16 +1,17 @@
 #!/bin/bash
 
-IMAGE_NAME=xos
+IMAGE_NAME=xosproject/xos
+CONTAINER_NAME=xos_build_helper_$$
 DB_HOST=$(wget http://ipinfo.io/ip -qO -)
 
 # configure db host
-docker run -it $IMAGE_NAME sed -i '0,/host/{s/host=localhost/host='$DB_HOST'/}' /opt/xos/xos_config
-CONTAINER_ID=$(docker ps -a | grep $IMAGE_NAME | head -1 |  awk '{print $1}')
-echo $CONTAINER_ID $IMAGE_NAME
-docker commit $CONTAINER_ID $IMAGE_NAME
+docker run -it --name=$CONTAINER_NAME $IMAGE_NAME sed -i '0,/host/{s/host=localhost/host='$DB_HOST'/}' /opt/xos/xos_config
+docker commit $CONTAINER_NAME $IMAGE_NAME
+docker rm $CONTAINER_NAME
 
 # init db schema
-docker run -it $IMAGE_NAME /opt/xos/scripts/opencloud makemigrations
-CONTAINER_ID=$(docker ps -a | grep $IMAGE_NAME | head -1 | awk '{print $1}')
+docker run -it --name=$CONTAINER_NAME $IMAGE_NAME /opt/xos/scripts/opencloud makemigrations
 # run overrides the CMD specifed in the Dockerfile, so we re-set the CMD in the final commit"
-docker commit --change "CMD python /opt/xos/manage.py runserver 0.0.0.0:8000 --insecure" $CONTAINER_ID $IMAGE_NAME
+echo docker commit --change="CMD python /opt/xos/manage.py runserver 0.0.0.0:8000 --insecure" $CONTAINER_NAME $IMAGE_NAME
+docker commit --change="CMD python /opt/xos/manage.py runserver 0.0.0.0:8000 --insecure" $CONTAINER_NAME $IMAGE_NAME
+docker rm $CONTAINER_NAME
diff --git a/xos/manage.py b/xos/manage.py
index 0ddd014..5d09794 100644
--- a/xos/manage.py
+++ b/xos/manage.py
@@ -7,6 +7,10 @@
 
     from django.core.management import execute_from_command_line
 
+    if "--makemigrations" in sys.argv:
+        os.system("/opt/xos/scripts/opencloud makemigrations")
+        sys.argv.remove("--makemigrations")
+
     if "--nomodelpolicy" in sys.argv:
         import model_policy
         model_policy.EnableModelPolicy(False)
diff --git a/xos/xos/settings.py b/xos/xos/settings.py
index fc2ad2f..4c0f779 100644
--- a/xos/xos/settings.py
+++ b/xos/xos/settings.py
@@ -1,15 +1,36 @@
 from django.conf.global_settings import TEMPLATE_CONTEXT_PROCESSORS as TCP
 from django import VERSION as DJANGO_VERSION
 import socket
+import os
+from urlparse import urlparse
 
 # Django settings for XOS.
 from config import Config
+from config import set_override
 config = Config()
 
+# Override the config from the environment. This is used leverage the LINK
+# capability of docker. It would be far better to use DNS and that can be
+# done in environments like kubernetes. Look for environment variables that
+# match the link pattern and set the appropriate overeides. It is expected
+# that the set of overrides will be expanded with need
+def overrideDbSettings(v):
+    parsed = urlparse(v)
+    config.db_host = parsed.hostname
+    config.db_port = parsed.port
+
+env_to_config_dict = {
+    "XOS_DB_PORT" : overrideDbSettings
+}
+
+for key, ofunc in env_to_config_dict.items():
+    if key in os.environ:
+        ofunc(os.environ[key])
+
 GEOIP_PATH = "/usr/share/GeoIP"
 XOS_DIR = "/opt/xos"
- 
-DEBUG = False 
+
+DEBUG = False
 TEMPLATE_DEBUG = DEBUG
 
 ADMINS = (
@@ -29,7 +50,7 @@
         'USER': config.db_user,
         'PASSWORD': config.db_password,
         'HOST': config.db_host,                      # Empty for localhost through domain sockets or '127.0.0.1' for localhost through TCP.
-        'PORT': '',                      # Set to empty string for default.
+        'PORT': config.db_port,                      # Set to empty string for default.
     }
 }
 
@@ -132,7 +153,7 @@
     # Always use forward slashes, even on Windows.
     # Don't forget to use absolute paths, not relative paths.
     XOS_DIR + "/templates",
-    XOS_DIR + "/core/xoslib/templates",    
+    XOS_DIR + "/core/xoslib/templates",
 )
 
 INSTALLED_APPS = (
@@ -170,7 +191,7 @@
     INSTALLED_APPS[INSTALLED_APPS.index('django.contrib.admin')] = 'django.contrib.admin.apps.SimpleAdminConfig'
     INSTALLED_APPS = tuple(INSTALLED_APPS)
 
-# Added for django-suit form 
+# Added for django-suit form
 TEMPLATE_CONTEXT_PROCESSORS = TCP + (
     'django.core.context_processors.request',
     'core.context_processors.xos',
@@ -196,7 +217,7 @@
     # 'MENU_OPEN_FIRST_CHILD': True, # Default True
     'MENU_EXCLUDE': (
          'auth.group',
-         'auth', 
+         'auth',
          'core.network',
          'core.instance',
          'core.node',
@@ -284,4 +305,3 @@
 
 # prevents warnings on django 1.7
 TEST_RUNNER = 'django.test.runner.DiscoverRunner'
-