diff --git a/docker/centos/binary/barbican/start.sh b/docker/centos/binary/barbican/start.sh
deleted file mode 100755
index 673aa43393695908fd94605790d2dea2f73beafb..0000000000000000000000000000000000000000
--- a/docker/centos/binary/barbican/start.sh
+++ /dev/null
@@ -1,81 +0,0 @@
-#!/bin/bash
-
-set -e
-
-: ${BARBICAN_DB_USER:=barbican}
-: ${BARBICAN_DB_NAME:=barbican}
-: ${KEYSTONE_AUTH_PROTOCOL:=http}
-: ${BARBICAN_KEYSTONE_USER:=barbican}
-: ${ADMIN_TENANT_NAME:=admin}
-
-if ! [ "$BARBICAN_DB_PASSWORD" ]; then
-        BARBICAN_DB_PASSWORD=$(openssl rand -hex 15)
-        export BARBICAN_DB_PASSWORD
-fi
-
-check_required_vars KEYSTONE_ADMIN_TOKEN KEYSTONE_ADMIN_SERVICE_HOST \
-                    KEYSTONE_ADMIN_SERVICE_PORT BARBICAN_ADMIN_PASSWORD
-fail_unless_db
-fail_unless_os_service_running keystone
-
-mysql -h ${MARIADB_SERVICE_HOST} -u root -p"${DB_ROOT_PASSWORD}" mysql <<EOF
-CREATE DATABASE IF NOT EXISTS ${BARBICAN_DB_NAME};
-GRANT ALL PRIVILEGES ON barbican.* TO
-    '${BARBICAN_DB_USER}'@'%' IDENTIFIED BY '${BARBICAN_DB_PASSWORD}'
-EOF
-
-# config file setup
-crudini --set /etc/barbican/barbican-api.conf \
-    DEFAULT \
-    sql_connection \
-    "mysql://${BARBICAN_DB_USER}:${BARBICAN_DB_PASSWORD}@${MARIADB_SERVICE_HOST}/${BARBICAN_DB_NAME}"
-crudini --set /etc/barbican/barbican-api.conf \
-    DEFAULT \
-    log_dir \
-    "/var/log/barbican/"
-crudini --set /etc/barbican/barbican-api.conf \
-    DEFAULT \
-    log_file \
-    "/var/log/barbican/barbican.log"
-crudini --set /etc/barbican/barbican-api-paste.ini \
-    pipeline:barbican_api \
-    pipeline \
-    "keystone_authtoken context apiapp"
-crudini --set /etc/barbican/barbican-api-paste.ini \
-    filter:keystone_authtoken \
-    auth_host \
-    ${KEYSTONE_ADMIN_SERVICE_HOST}
-crudini --set /etc/barbican/barbican-api-paste.ini \
-    filter:keystone_authtoken \
-    auth_port \
-    ${KEYSTONE_ADMIN_SERVICE_PORT}
-crudini --set /etc/barbican/barbican-api-paste.ini \
-    filter:keystone_authtoken \
-    auth_protocol \
-    ${KEYSTONE_AUTH_PROTOCOL}
-crudini --set /etc/barbican/barbican-api-paste.ini \
-    filter:keystone_authtoken \
-    admin_tenant_name \
-    ${ADMIN_TENANT_NAME}
-crudini --set /etc/barbican/barbican-api-paste.ini \
-    filter:keystone_authtoken \
-    admin_user \
-    ${BARBICAN_KEYSTONE_USER}
-crudini --set /etc/barbican/barbican-api-paste.ini \
-    filter:keystone_authtoken \
-    admin_password \
-    ${BARBICAN_KEYSTONE_USER}
-
-# create the required keystone entities for barbican
-export SERVICE_TOKEN="${KEYSTONE_ADMIN_TOKEN}"
-export SERVICE_ENDPOINT="${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}/v2.0"
-
-keystone user-get ${BARBICAN_KEYSTONE_USER} > /dev/null 2>&1 || /bin/keystone user-create --name ${BARBICAN_KEYSTONE_USER} --pass ${BARBICAN_ADMIN_PASSWORD}
-
-keystone role-get observer > /dev/null 2>&1 || /bin/keystone role-create --name observer
-keystone role-get creator > /dev/null 2>&1 || /bin/keystone role-create --name creator
-
-keystone user-get ${BARBICAN_KEYSTONE_USER} > /dev/null 2>&1 || /bin/keystone user-role-add --user ${BARBICAN_KEYSTONE_USER} --role admin --tenant ${ADMIN_TENANT_NAME}
-
-# launch Barbican using uwsgi
-exec uwsgi --master --emperor /etc/barbican/vassals
diff --git a/docker/centos/binary/barbican/start.sh b/docker/centos/binary/barbican/start.sh
new file mode 120000
index 0000000000000000000000000000000000000000..fbb47be02d0717cbe31f849c18e4706fc2cbb41f
--- /dev/null
+++ b/docker/centos/binary/barbican/start.sh
@@ -0,0 +1 @@
+../../../common/barbican/start.sh
\ No newline at end of file
diff --git a/docker/centos/binary/base/kolla-common.sh b/docker/centos/binary/base/kolla-common.sh
index 380efbc3d71be8cfa47c37c5fd938c575de7126e..c265c62f7ae70d3fa72661782afc0be3affc49c8 120000
--- a/docker/centos/binary/base/kolla-common.sh
+++ b/docker/centos/binary/base/kolla-common.sh
@@ -1 +1 @@
-../../../common/kolla-common.sh
\ No newline at end of file
+../../../common/base/kolla-common.sh
\ No newline at end of file
diff --git a/docker/centos/binary/base/service_hosts.sh b/docker/centos/binary/base/service_hosts.sh
index 777b7334d593d689000f2f04ff473ad4545f1c41..06e0454405c1ccd8bfa27a6827cfed4af862b84f 120000
--- a/docker/centos/binary/base/service_hosts.sh
+++ b/docker/centos/binary/base/service_hosts.sh
@@ -1 +1 @@
-../../../common/service_hosts.sh
\ No newline at end of file
+../../../common/base/service_hosts.sh
\ No newline at end of file
diff --git a/docker/centos/binary/ceilometer/ceilometer-alarm/start.sh b/docker/centos/binary/ceilometer/ceilometer-alarm/start.sh
deleted file mode 100644
index 7470ae608f0762b48968a933ed3911f42fbf56b9..0000000000000000000000000000000000000000
--- a/docker/centos/binary/ceilometer/ceilometer-alarm/start.sh
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/bash
-
-set -e
-
-. /opt/kolla/kolla-common.sh
-. /opt/kolla/config-ceilometer.sh
-
-
-exec /usr/bin/ceilometer-alarm-evaluator &
-exec /usr/bin/ceilometer-alarm-notifier
diff --git a/docker/centos/binary/ceilometer/ceilometer-alarm/start.sh b/docker/centos/binary/ceilometer/ceilometer-alarm/start.sh
new file mode 120000
index 0000000000000000000000000000000000000000..ed3ac528d4f721cc8b11d91173619ba484ac3f2f
--- /dev/null
+++ b/docker/centos/binary/ceilometer/ceilometer-alarm/start.sh
@@ -0,0 +1 @@
+../../../../common/ceilometer/ceilometer-alarm/start.sh
\ No newline at end of file
diff --git a/docker/centos/binary/ceilometer/ceilometer-api/start.sh b/docker/centos/binary/ceilometer/ceilometer-api/start.sh
deleted file mode 100644
index f081c9f84de535b688bd5a6b43ab0782b3185eeb..0000000000000000000000000000000000000000
--- a/docker/centos/binary/ceilometer/ceilometer-api/start.sh
+++ /dev/null
@@ -1,51 +0,0 @@
-#!/bin/bash
-
-set -e
-
-. /opt/kolla/kolla-common.sh
-. /opt/kolla/config-ceilometer.sh
-
-check_required_vars CEILOMETER_DB_USER CEILOMETER_DB_NAME \
-                    CEILOMETER_DB_PASSWORD KEYSTONE_ADMIN_TOKEN \
-                    KEYSTONE_AUTH_PROTOCOL KEYSTONE_ADMIN_SERVICE_HOST \
-                    KEYSTONE_ADMIN_SERVICE_PORT ADMIN_TENANT_NAME \
-                    CEILOMETER_KEYSTONE_USER CEILOMETER_ADMIN_PASSWORD \
-                    CEILOMETER_API_SERVICE_HOST PUBLIC_IP
-
-fail_unless_os_service_running keystone
-fail_unless_db
-
-#TODO(pkilambi): Add mongodb support
-
-mysql -h ${MARIADB_SERVICE_HOST} -u root -p${DB_ROOT_PASSWORD} mysql <<EOF
-CREATE DATABASE IF NOT EXISTS ${CEILOMETER_DB_NAME} DEFAULT CHARACTER SET utf8;
-GRANT ALL PRIVILEGES ON ${CEILOMETER_DB_NAME}.* TO
-       '${CEILOMETER_DB_USER}'@'%' IDENTIFIED BY '${CEILOMETER_DB_PASSWORD}'
-
-EOF
-
-
-export SERVICE_TOKEN="${KEYSTONE_ADMIN_TOKEN}"
-export SERVICE_ENDPOINT="${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}/v2.0"
-
-
-crux user-create -n ${CEILOMETER_KEYSTONE_USER} \
-    -p ${CEILOMETER_ADMIN_PASSWORD} \
-    -t ${ADMIN_TENANT_NAME} \
-    -r admin
-
-crux service-create -n ${CEILOMETER_KEYSTONE_USER} -t metering \
-    -d "Ceilometer Telemetry Service"
-
-crux endpoint-create i--remove-all -n ${CEILOMETER_KEYSTONE_USER} -t metering \
-    -I "${KEYSTONE_AUTH_PROTOCOL}://${CEILOMETER_API_SERVICE_HOST}:8777" \
-    -P "${KEYSTONE_AUTH_PROTOCOL}://${PUBLIC_IP}:8777" \
-    -A "${KEYSTONE_AUTH_PROTOCOL}://${CEILOMETER_API_SERVICE_HOST}:8777"
-
-cfg=/etc/ceilometer/ceilometer.conf
-crudini --set $cfg \
-    DEFAULT connection
-    "mysql://${CEILOMETER_DB_USER}:${CEILOMETER_DB_PASSWORD}@${MARIADB_SERVICE_HOST}/${CEILOMETER_DB_NAME}"
-
-
-exec /usr/bin/ceilometer-api
diff --git a/docker/centos/binary/ceilometer/ceilometer-api/start.sh b/docker/centos/binary/ceilometer/ceilometer-api/start.sh
new file mode 120000
index 0000000000000000000000000000000000000000..7acfa2cba6e19e8e859f4e4ffbb021c4ada51401
--- /dev/null
+++ b/docker/centos/binary/ceilometer/ceilometer-api/start.sh
@@ -0,0 +1 @@
+../../../../common/ceilometer/ceilometer-api/start.sh
\ No newline at end of file
diff --git a/docker/centos/binary/ceilometer/ceilometer-base/config-ceilometer.sh b/docker/centos/binary/ceilometer/ceilometer-base/config-ceilometer.sh
deleted file mode 100644
index a2316dcd1d42162c7c2b51a421a489b804f349ab..0000000000000000000000000000000000000000
--- a/docker/centos/binary/ceilometer/ceilometer-base/config-ceilometer.sh
+++ /dev/null
@@ -1,71 +0,0 @@
-#!/bin/bash
-
-set -e
-. /opt/kolla/kolla-common.sh
-
-: ${CEILOMETER_DB_USER:=ceilometer}
-: ${CEILOMETER_DB_NAME:=ceilometer}
-: ${KEYSTONE_AUTH_PROTOCOL:=http}
-: ${CEILOMETER_KEYSTONE_USER:=admin}
-: ${CEILOMETER_ADMIN_PASSWORD:=kolla}
-: ${ADMIN_TENANT_NAME:=admin}
-: ${METERING_SECRET:=ceilometer}
-: ${RABBIT_PASSWORD:=guest}
-
-check_required_vars KEYSTONE_ADMIN_TOKEN KEYSTONE_ADMIN_SERVICE_HOST \
-                    KEYSTONE_ADMIN_SERVICE_PORT KEYSTONE_PUBLIC_SERVICE_HOST \
-dump_vars
-
-cat > /openrc <<EOF
-export SERVICE_TOKEN="${KEYSTONE_ADMIN_TOKEN}"
-export SERVICE_ENDPOINT="${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}/v2.0"
-EOF
-
-
-cfg=/etc/ceilometer/ceilometer.conf
-
-crudini --set $cfg \
-    DEFAULT rpc_backend rabbit
-crudini --set $cfg \
-    DEFAULT rabbit_host ${RABBITMQ_SERVICE_HOST}
-crudini --set $cfg \
-    DEFAULT rabbit_password ${RABBIT_PASSWORD}
-
-crudini --set $cfg \
-    keystone_authtoken \
-    auth_uri \
-    "http://${KEYSTONE_PUBLIC_SERVICE_HOST}:5000/"
-crudini --set $cfg \
-    keystone_authtoken \
-    admin_tenant_name \
-    "${ADMIN_TENANT_NAME}"
-crudini --set $cfg \
-    keystone_authtoken \
-    admin_user \
-    "${CEILOMETER_KEYSTONE_USER}"
-crudini --set $cfg \
-    keystone_authtoken \
-    admin_password \
-    ${CEILOMETER_ADMIN_PASSWORD}
-
-crudini --set $cfg \
-    service_credentials \
-    os_auth_url \
-    ${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_PUBLIC_SERVICE_HOST}:5000/
-crudini --set $cfg \
-    service_credentials \
-    os_username \
-    ceilometer
-crudini --set $cfg \
-    service_credentials \
-    os_tenant_name \
-    service
-crudini --set $cfg \
-    service_credentials \
-    os_password \
-    ${CEILOMETER_ADMIN_PASSWORD}
-
-crudini --set $cfg \
-    publisher
-    metering_secret
-    ${METERING_SECRET}
diff --git a/docker/centos/binary/ceilometer/ceilometer-base/config-ceilometer.sh b/docker/centos/binary/ceilometer/ceilometer-base/config-ceilometer.sh
new file mode 120000
index 0000000000000000000000000000000000000000..63215435d5a6d6c8dcd4da80feeacb4df506c9d6
--- /dev/null
+++ b/docker/centos/binary/ceilometer/ceilometer-base/config-ceilometer.sh
@@ -0,0 +1 @@
+../../../../common/ceilometer/ceilometer-base/config-ceilometer.sh
\ No newline at end of file
diff --git a/docker/centos/binary/ceilometer/ceilometer-central/start.sh b/docker/centos/binary/ceilometer/ceilometer-central/start.sh
deleted file mode 100644
index 76f9a1fc2c14a6f93f218a487985ef61df0455b0..0000000000000000000000000000000000000000
--- a/docker/centos/binary/ceilometer/ceilometer-central/start.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/bash
-
-. /opt/kolla/kolla-common.sh
-. /opt/kolla/config-ceilometer.sh
-
-check_required_vars KEYSTONE_ADMIN_TOKEN KEYSTONE_AUTH_PROTOCOL \
-                    KEYSTONE_ADMIN_SERVICE_HOST KEYSTONE_ADMIN_SERVICE_PORT
-
-fail_unless_os_service_running keystone
-
-export SERVICE_TOKEN="${KEYSTONE_ADMIN_TOKEN}"
-export SERVICE_ENDPOINT="${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}/v2.0"
-
-exec /usr/bin/ceilometer-agent-central
diff --git a/docker/centos/binary/ceilometer/ceilometer-central/start.sh b/docker/centos/binary/ceilometer/ceilometer-central/start.sh
new file mode 120000
index 0000000000000000000000000000000000000000..8df383cd16874e524b98cd47d3bdaa19da114833
--- /dev/null
+++ b/docker/centos/binary/ceilometer/ceilometer-central/start.sh
@@ -0,0 +1 @@
+../../../../common/ceilometer/ceilometer-central/start.sh
\ No newline at end of file
diff --git a/docker/centos/binary/ceilometer/ceilometer-collector/start.sh b/docker/centos/binary/ceilometer/ceilometer-collector/start.sh
deleted file mode 100644
index 1ed4c9e7d0122e8eb4b2e31e8ee579f1f408dd56..0000000000000000000000000000000000000000
--- a/docker/centos/binary/ceilometer/ceilometer-collector/start.sh
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/bash
-
-set -e
-
-. /opt/kolla/kolla-common.sh
-. /opt/kolla/config-ceilometer.sh
-
-
-exec /usr/bin/ceilometer-collector
diff --git a/docker/centos/binary/ceilometer/ceilometer-collector/start.sh b/docker/centos/binary/ceilometer/ceilometer-collector/start.sh
new file mode 120000
index 0000000000000000000000000000000000000000..bea2eb09c1c3d6ab02d524767436de7f3a50d15d
--- /dev/null
+++ b/docker/centos/binary/ceilometer/ceilometer-collector/start.sh
@@ -0,0 +1 @@
+../../../../common/ceilometer/ceilometer-collector/start.sh
\ No newline at end of file
diff --git a/docker/centos/binary/ceilometer/ceilometer-compute/start.sh b/docker/centos/binary/ceilometer/ceilometer-compute/start.sh
deleted file mode 100644
index f4fc30baeea96849943a9d2b287d5aa22951961b..0000000000000000000000000000000000000000
--- a/docker/centos/binary/ceilometer/ceilometer-compute/start.sh
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/bin/bash
-
-. /opt/kolla/kolla-common.sh
-. /opt/kolla/config-ceilometer.sh
-
-
-check_required_vars KEYSTONE_ADMIN_TOKEN RABBITMQ_SERVICE_HOST RABBIT_PASSWORD
-
-fail_unless_os_service_running keystone
-
-# Nova conf settings
-crudini --set /etc/nova/nova.conf DEFAULT instance_usage_audit True
-crudini --set /etc/nova/nova.conf DEFAULT instance_usage_audit_period hour
-crudini --set /etc/nova/nova.conf DEFAULT notify_on_state_change vm_and_task_state
-crudini --set /etc/nova/nova.conf DEFAULT notification_driver nova.openstack.common.notifier.rpc_notifier
-crudini --set /etc/nova/nova.conf DEFAULT notification_driver ceilometer.compute.nova_notifier
-
-#ceilometer settings
-cfg=/etc/ceilometer/ceilometer.conf
-crudini --set $cfg publisher_rpc metering_secret ${KEYSTONE_ADMIN_TOKEN}
-crudini --set $cfg rabbit_host ${RABBITMQ_SERVICE_HOST}
-crudini --set $cfg rabbit_password ${RABBIT_PASSWORD}
-
-
-exec /usr/bin/ceilometer-agent-compute
diff --git a/docker/centos/binary/ceilometer/ceilometer-compute/start.sh b/docker/centos/binary/ceilometer/ceilometer-compute/start.sh
new file mode 120000
index 0000000000000000000000000000000000000000..1118b9552d2f4c63cc113985251927cbdd52388b
--- /dev/null
+++ b/docker/centos/binary/ceilometer/ceilometer-compute/start.sh
@@ -0,0 +1 @@
+../../../../common/ceilometer/ceilometer-compute/start.sh
\ No newline at end of file
diff --git a/docker/centos/binary/ceilometer/ceilometer-notification/start.sh b/docker/centos/binary/ceilometer/ceilometer-notification/start.sh
deleted file mode 100644
index 9397345497a0efc8db57bba0e0b2ddd2decd504b..0000000000000000000000000000000000000000
--- a/docker/centos/binary/ceilometer/ceilometer-notification/start.sh
+++ /dev/null
@@ -1,9 +0,0 @@
-#!/bin/bash
-
-set -e
-
-. /opt/kolla/kolla-common.sh
-. /opt/kolla/config-ceilometer.sh
-
-
-exec /usr/bin/ceilometer-agent-notification
diff --git a/docker/centos/binary/ceilometer/ceilometer-notification/start.sh b/docker/centos/binary/ceilometer/ceilometer-notification/start.sh
new file mode 120000
index 0000000000000000000000000000000000000000..8e6d4e3374a39131c1c2c3765edd0a8a6da4b88c
--- /dev/null
+++ b/docker/centos/binary/ceilometer/ceilometer-notification/start.sh
@@ -0,0 +1 @@
+../../../../common/ceilometer/ceilometer-notification/start.sh
\ No newline at end of file
diff --git a/docker/centos/binary/cinder-app/cinder-api/check.sh b/docker/centos/binary/cinder-app/cinder-api/check.sh
deleted file mode 100755
index 57b88f56694ebad5ba42d874746ecdac4977bfd4..0000000000000000000000000000000000000000
--- a/docker/centos/binary/cinder-app/cinder-api/check.sh
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/bin/sh
-
-RES=0
-
-. /openrc
-if ! keystone token-get > /dev/null; then
-    echo "ERROR: keystone token-get failed" >&2
-    RES=1
-else
-    if ! cinder list > /dev/null; then
-        echo "ERROR: cinder list failed" >&2
-        RES=1
-    fi
-fi
-
-exit $RES
diff --git a/docker/centos/binary/cinder-app/cinder-api/check.sh b/docker/centos/binary/cinder-app/cinder-api/check.sh
new file mode 120000
index 0000000000000000000000000000000000000000..829110b45879c8f2538a7189c3d7b8684ddec94c
--- /dev/null
+++ b/docker/centos/binary/cinder-app/cinder-api/check.sh
@@ -0,0 +1 @@
+../../../../common/cinder-app/cinder-api/check.sh
\ No newline at end of file
diff --git a/docker/centos/binary/cinder-app/cinder-api/start.sh b/docker/centos/binary/cinder-app/cinder-api/start.sh
deleted file mode 100755
index 28293ac6cc4f3f1fa714a28b4ff91d56782b3ab0..0000000000000000000000000000000000000000
--- a/docker/centos/binary/cinder-app/cinder-api/start.sh
+++ /dev/null
@@ -1,73 +0,0 @@
-#!/bin/bash
-
-set -e
-
-. /opt/kolla/kolla-common.sh
-. /opt/kolla/config-cinder.sh
-
-check_required_vars KEYSTONE_ADMIN_TOKEN KEYSTONE_ADMIN_SERVICE_HOST \
-                    ADMIN_TENANT_NAME PUBLIC_IP CINDER_API_SERVICE_HOST \
-                    KEYSTONE_AUTH_PROTOCOL KEYSTONE_ADMIN_SERVICE_PORT \
-                    CINDER_KEYSTONE_USER CINDER_KEYSTONE_PASSWORD \
-                    CINDER_API_LOG_FILE CINDER_API_SERVICE_LISTEN \
-                    CINDER_API_SERVICE_PORT CINDER_API_SERVICE_LISTEN
-
-fail_unless_os_service_running keystone
-
-cfg=/etc/cinder/cinder.conf
-
-# Set the auth credentials
-export SERVICE_TOKEN="${KEYSTONE_ADMIN_TOKEN}"
-export SERVICE_ENDPOINT="${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}/v2.0"
-
-# Create Keystone User
-crux user-create --update \
-    -n "${CINDER_KEYSTONE_USER}" \
-    -p "${CINDER_KEYSTONE_PASSWORD}" \
-    -t "${ADMIN_TENANT_NAME}" \
-    -r admin
-
-# Configure Keystone
-crux endpoint-create --remove-all \
-    -n cinder \
-    -t volume \
-    -P "http://${CINDER_API_SERVICE_HOST}:${CINDER_API_SERVICE_PORT}/v1/\$(tenant_id)s" \
-    -A "http://${CINDER_API_SERVICE_HOST}:${CINDER_API_SERVICE_PORT}/v1/\$(tenant_id)s" \
-    -I "http://${CINDER_API_SERVICE_HOST}:${CINDER_API_SERVICE_PORT}/v1/\$(tenant_id)s"
-
-crux endpoint-create --remove-all \
-    -n cinderv2 \
-    -t volumev2 \
-    -P "http://${CINDER_API_SERVICE_HOST}:${CINDER_API_SERVICE_PORT}/v2/\$(tenant_id)s" \
-    -A "http://${CINDER_API_SERVICE_HOST}:${CINDER_API_SERVICE_PORT}/v2/\$(tenant_id)s" \
-    -I "http://${CINDER_API_SERVICE_HOST}:${CINDER_API_SERVICE_PORT}/v2/\$(tenant_id)s"
-
-# Logging
-crudini --set $cfg \
-        DEFAULT \
-        log_file \
-        "${CINDER_API_LOG_FILE}"
-
-# API Configuration
-crudini --set $cfg \
-        DEFAULT \
-        osapi_volume_listen \
-        "${CINDER_API_SERVICE_LISTEN}"
-
-crudini --set $cfg \
-        DEFAULT \
-        osapi_volume_listen_port \
-        "${CINDER_API_SERVICE_PORT}"
-
-crudini --set $cfg \
-        DEFAULT \
-        enable_v1_api \
-        "true"
-
-crudini --set $cfg \
-        DEFAULT \
-        enable_v2_api \
-        "true"
-
-echo "Starting cinder-api"
-exec /usr/bin/cinder-api --config-file $cfg
diff --git a/docker/centos/binary/cinder-app/cinder-api/start.sh b/docker/centos/binary/cinder-app/cinder-api/start.sh
new file mode 120000
index 0000000000000000000000000000000000000000..33182c78cf4d9d81636581407f2598e262d64e7f
--- /dev/null
+++ b/docker/centos/binary/cinder-app/cinder-api/start.sh
@@ -0,0 +1 @@
+../../../../common/cinder-app/cinder-api/start.sh
\ No newline at end of file
diff --git a/docker/centos/binary/cinder-app/cinder-backup/start.sh b/docker/centos/binary/cinder-app/cinder-backup/start.sh
deleted file mode 100755
index 5dff79b3566634c76180065cbdea8ab583e3d819..0000000000000000000000000000000000000000
--- a/docker/centos/binary/cinder-app/cinder-backup/start.sh
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/bin/bash
-
-set -e
-
-. /opt/kolla/kolla-common.sh
-. /opt/kolla/config-cinder.sh
-
-check_required_vars CINDER_BACKUP_DRIVER CINDER_BACKUP_MANAGER \
-                    CINDER_BACKUP_API_CLASS CINDER_BACKUP_NAME_TEMPLATE
-
-cfg=/etc/cinder/cinder.conf
-
-# volume backup configuration
-crudini --set $cfg \
-        DEFAULT \
-        backup_driver \
-        "${CINDER_BACKUP_DRIVER}"
-crudini --set $cfg \
-        DEFAULT \
-        backup_topic \
-        "cinder-backup"
-crudini --set $cfg \
-        DEFAULT \
-        backup_manager \
-        "${CINDER_BACKUP_MANAGER}"
-crudini --set $cfg \
-        DEFAULT \
-        backup_api_class \
-        "${CINDER_BACKUP_API_CLASS}"
-crudini --set $cfg \
-        DEFAULT \
-        backup_name_template \
-        "${CINDER_BACKUP_NAME_TEMPLATE}"
-
-echo "Starting cinder-backup"
-exec /usr/bin/cinder-backup --config-file $cfg
diff --git a/docker/centos/binary/cinder-app/cinder-backup/start.sh b/docker/centos/binary/cinder-app/cinder-backup/start.sh
new file mode 120000
index 0000000000000000000000000000000000000000..c21a17f09aaa1fcae06041ac5fc353fcf2f5693a
--- /dev/null
+++ b/docker/centos/binary/cinder-app/cinder-backup/start.sh
@@ -0,0 +1 @@
+../../../../common/cinder-app/cinder-backup/start.sh
\ No newline at end of file
diff --git a/docker/centos/binary/cinder-app/cinder-base/config-cinder.sh b/docker/centos/binary/cinder-app/cinder-base/config-cinder.sh
deleted file mode 100644
index f82cb5510c97bf0b35e76773b07216f5dabe4f78..0000000000000000000000000000000000000000
--- a/docker/centos/binary/cinder-app/cinder-base/config-cinder.sh
+++ /dev/null
@@ -1,132 +0,0 @@
-#!/bin/sh
-
-set -e
-
-. /opt/kolla/kolla-common.sh
-
-check_required_vars CINDER_DB_PASSWORD CINDER_KEYSTONE_PASSWORD \
-                    KEYSTONE_PUBLIC_SERVICE_HOST RABBITMQ_SERVICE_HOST \
-                    GLANCE_API_SERVICE_HOST MARIADB_SERVICE_HOST \
-                    RABBITMQ_SERVICE_HOST RABBITMQ_SERVICE_PORT \
-                    RABBIT_USERID RABBIT_PASSWORD GLANCE_API_SERVICE_HOST \
-                    GLANCE_API_SERVICE_PORT ADMIN_TENANT_NAME \
-                    CINDER_DB_NAME CINDER_DB_USER CINDER_KEYSTONE_USER \
-                    PUBLIC_IP KEYSTONE_AUTH_PROTOCOL CINDER_LOG_DIR
-
-dump_vars
-
-cat > /openrc <<EOF
-export OS_AUTH_URL="${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_PUBLIC_SERVICE_HOST}:${KEYSTONE_PUBLIC_SERVICE_PORT}/v2.0"
-export OS_USERNAME="${CINDER_KEYSTONE_USER}"
-export OS_PASSWORD="${CINDER_KEYSTONE_PASSWORD}"
-export OS_TENANT_NAME="${ADMIN_TENANT_NAME}"
-EOF
-
-cfg=/etc/cinder/cinder.conf
-
-# Logging
-crudini --set $cfg \
-        DEFAULT \
-        log_dir \
-        "${CINDER_LOG_DIR}"
-crudini --set $cfg \
-        DEFAULT \
-        verbose \
-        "${VERBOSE_LOGGING}"
-crudini --set $cfg \
-        DEFAULT \
-        debug \
-        "${DEBUG_LOGGING}"
-
-# backend
-crudini --set $cfg \
-        DEFAULT \
-        rpc_backend \
-        "cinder.openstack.common.rpc.impl_kombu"
-
-# rabbit
-crudini --set $cfg \
-        DEFAULT \
-        rabbit_host \
-        "${RABBITMQ_SERVICE_HOST}"
-crudini --set $cfg \
-        DEFAULT \
-        rabbit_port \
-        "${RABBITMQ_SERVICE_PORT}"
-crudini --set $cfg \
-        DEFAULT \
-        rabbit_hosts \
-        "${RABBITMQ_SERVICE_HOST}:${RABBITMQ_SERVICE_PORT}"
-crudini --set $cfg \
-        DEFAULT \
-        rabbit_userid \
-        "${RABBIT_USERID}"
-crudini --set $cfg \
-        DEFAULT \
-        rabbit_password \
-        "${RABBIT_PASSWORD}"
-crudini --set /etc/cinder/cinder.conf \
-        DEFAULT \
-        rabbit_virtual_host \
-        "/"
-crudini --set /etc/cinder/cinder.conf \
-        DEFAULT \
-        rabbit_ha_queues \
-        "False"
-
-# control_exchange
-crudini --set /etc/cinder/cinder.conf \
-        DEFAULT \
-        control_exchange \
-        "openstack"
-
-# glance
-crudini --set $cfg \
-        DEFAULT \
-        glance_host \
-        "${GLANCE_API_SERVICE_HOST}"
-crudini --set $cfg \
-        DEFAULT \
-        glance_port \
-        "${GLANCE_API_SERVICE_PORT}"
-
-# database
-crudini --set $cfg \
-        database \
-        connection \
-        "mysql://${CINDER_DB_USER}:${CINDER_DB_PASSWORD}@${MARIADB_SERVICE_HOST}/${CINDER_DB_NAME}"
-
-# keystone
-crudini --set $cfg \
-        DEFAULT \
-        auth_strategy \
-        "keystone"
-crudini --del $cfg \
-        keystone_authtoken \
-        auth_protocol
-crudini --del $cfg \
-        keystone_authtoken \
-        auth_host
-crudini --del $cfg \
-        keystone_authtoken \
-        auth_port
-crudini --set $cfg \
-        keystone_authtoken \
-        auth_uri \
-        "${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_PUBLIC_SERVICE_HOST}:${KEYSTONE_PUBLIC_SERVICE_PORT}/v2.0"
-crudini --set $cfg \
-        keystone_authtoken \
-        identity_uri \
-        "${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}"
-crudini --set $cfg \
-        keystone_authtoken \
-        admin_tenant_name \
-        "${ADMIN_TENANT_NAME}"
-crudini --set $cfg \
-        keystone_authtoken \
-        admin_user \
-        "${CINDER_KEYSTONE_USER}"
-crudini --set $cfg \
-        keystone_authtoken \
-        admin_password \
-        "${CINDER_KEYSTONE_PASSWORD}"
diff --git a/docker/centos/binary/cinder-app/cinder-base/config-cinder.sh b/docker/centos/binary/cinder-app/cinder-base/config-cinder.sh
new file mode 120000
index 0000000000000000000000000000000000000000..22722c185b10d5f171b5a2fd3ba72c6be77c247c
--- /dev/null
+++ b/docker/centos/binary/cinder-app/cinder-base/config-cinder.sh
@@ -0,0 +1 @@
+../../../../common/cinder-app/cinder-base/config-cinder.sh
\ No newline at end of file
diff --git a/docker/centos/binary/cinder-app/cinder-scheduler/start.sh b/docker/centos/binary/cinder-app/cinder-scheduler/start.sh
deleted file mode 100755
index 93efeb4062a02628f932a808730307b1f31d7a1a..0000000000000000000000000000000000000000
--- a/docker/centos/binary/cinder-app/cinder-scheduler/start.sh
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/bin/bash
-
-set -e
-
-. /opt/kolla/kolla-common.sh
-. /opt/kolla/config-cinder.sh
-
-fail_unless_db
-
-check_required_vars MARIADB_SERVICE_HOST DB_ROOT_PASSWORD \
-                    CINDER_DB_NAME CINDER_DB_USER CINDER_DB_PASSWORD \
-                    CINDER_SCHEDULER_LOG_FILE INIT_CINDER_DB
-
-cfg=/etc/cinder/cinder.conf
-
-if [ "${INIT_CINDER_DB}" == "true" ]; then
-    mysql -h ${MARIADB_SERVICE_HOST} -u root -p${DB_ROOT_PASSWORD} mysql <<EOF
-CREATE DATABASE IF NOT EXISTS ${CINDER_DB_NAME};
-GRANT ALL PRIVILEGES ON ${CINDER_DB_NAME}.* TO
-'${CINDER_DB_USER}'@'%' IDENTIFIED BY '${CINDER_DB_PASSWORD}'
-EOF
-
-    su -s /bin/sh -c "cinder-manage db sync" cinder
-fi
-
-crudini --set $cfg \
-    DEFAULT \
-    log_file \
-    "${CINDER_SCHEDULER_LOG_FILE}"
-
-echo "Starting cinder-scheduler"
-exec /usr/bin/cinder-scheduler --config-file $cfg
diff --git a/docker/centos/binary/cinder-app/cinder-scheduler/start.sh b/docker/centos/binary/cinder-app/cinder-scheduler/start.sh
new file mode 120000
index 0000000000000000000000000000000000000000..a91c95ebda3c6dad71b13c0f8a7c0d22e9d69c76
--- /dev/null
+++ b/docker/centos/binary/cinder-app/cinder-scheduler/start.sh
@@ -0,0 +1 @@
+../../../../common/cinder-app/cinder-scheduler/start.sh
\ No newline at end of file
diff --git a/docker/centos/binary/cinder-app/cinder-volume/start.sh b/docker/centos/binary/cinder-app/cinder-volume/start.sh
deleted file mode 100755
index db29e75deb41e111a4da98498a92a9e7f1c2d07c..0000000000000000000000000000000000000000
--- a/docker/centos/binary/cinder-app/cinder-volume/start.sh
+++ /dev/null
@@ -1,75 +0,0 @@
-#!/bin/bash
-
-set -e
-
-. /opt/kolla/kolla-common.sh
-. /opt/kolla/config-cinder.sh
-. /opt/kolla/volume-group-create.sh
-
-check_required_vars CINDER_VOLUME_API_LISTEN ISCSI_HELPER ISCSI_IP_ADDRESS \
-                    CINDER_VOLUME_GROUP CINDER_LVM_LO_VOLUME_SIZE \
-                    CINDER_VOLUME_BACKEND_NAME CINDER_VOLUME_DRIVER \
-                    CINDER_ENABLED_BACKEND CINDER_VOLUME_LOG_FILE
-
-cfg=/etc/cinder/cinder.conf
-
-# Logging
-crudini --set $cfg \
-    DEFAULT \
-    log_file \
-    "${CINDER_VOLUME_LOG_FILE}"
-
-# IP address on which OpenStack Volume API listens
-crudini --set $cfg \
-    DEFAULT \
-    osapi_volume_listen \
-    "${CINDER_VOLUME_API_LISTEN}"
-
-# The IP address that the iSCSI daemon is listening on
-crudini --set $cfg \
-    DEFAULT \
-    iscsi_ip_address \
-    "${ISCSI_IP_ADDRESS}"
-
-# Set to false when using loopback devices (testing)
-crudini --set $cfg \
-    DEFAULT \
-    secure_delete \
-    "false"
-
-crudini --set $cfg \
-    DEFAULT \
-    enabled_backends \
-    "${CINDER_ENABLED_BACKEND}"
-
-crudini --set $cfg \
-    lvm57 \
-    iscsi_helper \
-    "${ISCSI_HELPER}"
-
-crudini --set $cfg \
-    lvm57 \
-    volume_group \
-    "${CINDER_VOLUME_GROUP}"
-
-crudini --set $cfg \
-    lvm57 \
-    volume_driver \
-    "${CINDER_VOLUME_DRIVER}"
-
-crudini --set $cfg \
-    lvm57 \
-    iscsi_ip_address \
-    "${ISCSI_IP_ADDRESS}"
-
-crudini --set $cfg \
-    lvm57 \
-    volume_backend_name \
-    "${CINDER_VOLUME_BACKEND_NAME}"
-
-sed -i 's/udev_sync = 1/udev_sync = 0/' /etc/lvm/lvm.conf
-sed -i 's/udev_rules = 1/udev_rules = 0/' /etc/lvm/lvm.conf
-sed -i 's/use_lvmetad = 1/use_lvmetad = 0/' /etc/lvm/lvm.conf
-
-echo "Starting cinder-volume"
-exec /usr/bin/cinder-volume --config-file /etc/cinder/cinder.conf
diff --git a/docker/centos/binary/cinder-app/cinder-volume/start.sh b/docker/centos/binary/cinder-app/cinder-volume/start.sh
new file mode 120000
index 0000000000000000000000000000000000000000..f79df7c4706a33058e512bb8f00b0bdf1e9d203a
--- /dev/null
+++ b/docker/centos/binary/cinder-app/cinder-volume/start.sh
@@ -0,0 +1 @@
+../../../../common/cinder-app/cinder-volume/start.sh
\ No newline at end of file
diff --git a/docker/centos/binary/cinder-app/cinder-volume/volume-group-create.sh b/docker/centos/binary/cinder-app/cinder-volume/volume-group-create.sh
deleted file mode 100755
index 908d987b0d91e59723da8e362c1f6f8f149a0031..0000000000000000000000000000000000000000
--- a/docker/centos/binary/cinder-app/cinder-volume/volume-group-create.sh
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/bin/bash
-
-# The script will create the cinder-volume volume group that will
-# allow cinder to create volumes from a backing file.
-# This is based off devstack.
-set -e
-
-backing_file=/opt/data/cinder_volume
-
-check_required_vars CINDER_LVM_LO_VOLUME_SIZE CINDER_VOLUME_GROUP
-
-if ! vgs ${CINDER_VOLUME_GROUP}; then
-    [[ ! -f $backing_file ]] && truncate -s ${CINDER_LVM_LO_VOLUMES_SIZE} $backing_file
-    vg_dev=`losetup -f --show $backing_file`
-    if ! vgs ${CINDER_VOLUME_GROUP}; then
-        vgcreate ${CINDER_VOLUME_GROUP} $vg_dev
-    fi
-fi
-
-# Remove iscsi targets
-cinder-rtstool get-targets | xargs -rn 1 cinder-rtstool delete
-
diff --git a/docker/centos/binary/cinder-app/cinder-volume/volume-group-create.sh b/docker/centos/binary/cinder-app/cinder-volume/volume-group-create.sh
new file mode 120000
index 0000000000000000000000000000000000000000..eeeca7063e63d473944014e54f0075ed2d0dedc4
--- /dev/null
+++ b/docker/centos/binary/cinder-app/cinder-volume/volume-group-create.sh
@@ -0,0 +1 @@
+../../../../common/cinder-app/cinder-volume/volume-group-create.sh
\ No newline at end of file
diff --git a/docker/centos/binary/designate/designate-api/start.sh b/docker/centos/binary/designate/designate-api/start.sh
deleted file mode 100755
index aae50ea8f1b6a22aaae67e6171b77f35547f8a2f..0000000000000000000000000000000000000000
--- a/docker/centos/binary/designate/designate-api/start.sh
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/bin/bash
-set -e
-
-. /opt/kolla/kolla-common.sh
-. /opt/kolla/config-designate.sh
-
-CONF=/etc/designate/designate.conf
-
-check_required_vars KEYSTONE_ADMIN_TOKEN KEYSTONE_ADMIN_SERVICE_HOST \
-                    DESIGNATE_KEYSTONE_USER DESIGNATE_KEYSTONE_PASSWORD \
-                    KEYSTONE_AUTH_PROTOCOL ADMIN_TENANT_NAME \
-                    DESIGNATE_API_SERVICE_HOST DESIGNATE_API_SERVICE_PORT \
-                    KEYSTONE_ADMIN_SERVICE_PORT
-
-export SERVICE_TOKEN="${KEYSTONE_ADMIN_TOKEN}"
-export SERVICE_ENDPOINT="${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}/v2.0"
-
-fail_unless_os_service_running keystone
-
-crux user-create \
-    -n ${DESIGNATE_KEYSTONE_USER} \
-    -p ${DESIGNATE_KEYSTONE_PASSWORD} \
-    -t ${ADMIN_TENANT_NAME} \
-    -r admin
-
-crux endpoint-create \
-    --remove-all \
-    -n ${DESIGNATE_KEYSTONE_USER} \
-    -t dns \
-    -I "${KEYSTONE_AUTH_PROTOCOL}://${DESIGNATE_API_SERVICE_HOST}:${DESIGNATE_API_SERVICE_PORT}/v1" \
-    -P "${KEYSTONE_AUTH_PROTOCOL}://${DESIGNATE_API_SERVICE_HOST}:${DESIGNATE_API_SERVICE_PORT}/v1" \
-    -A "${KEYSTONE_AUTH_PROTOCOL}://${DESIGNATE_API_SERVICE_HOST}:${DESIGNATE_API_SERVICE_PORT}/v1"
-
-crudini --set $CONF service:api api_paste_config "/usr/share/designate/api-paste.ini"
-crudini --set $CONF service:api api_port "${DESIGNATE_API_SERVICE_PORT}"
-
-exec /usr/bin/designate-api
diff --git a/docker/centos/binary/designate/designate-api/start.sh b/docker/centos/binary/designate/designate-api/start.sh
new file mode 120000
index 0000000000000000000000000000000000000000..f96fe1a342ccf1e21a3176eea442e7dc06c12be6
--- /dev/null
+++ b/docker/centos/binary/designate/designate-api/start.sh
@@ -0,0 +1 @@
+../../../../common/designate/designate-api/start.sh
\ No newline at end of file
diff --git a/docker/centos/binary/designate/designate-backend-bind9/start.sh b/docker/centos/binary/designate/designate-backend-bind9/start.sh
deleted file mode 100755
index 90d2de676bef4e1e4457beaa3486ebf2909e3166..0000000000000000000000000000000000000000
--- a/docker/centos/binary/designate/designate-backend-bind9/start.sh
+++ /dev/null
@@ -1,60 +0,0 @@
-#!/bin/bash
-set -e
-
-. /opt/kolla/kolla-common.sh
-
-check_required_vars DESIGNATE_MASTERNS DESIGNATE_SLAVENS DESIGNATE_BIND9_RNDC_KEY \
-                    DESIGNATE_ALLOW_RECURSION
-
-NAMEDCFG=/etc/named.conf
-
-# /var/named is coming from a VOLUME definition but at first boot it needs to
-# be populated from the original container since else it would be missing some
-# Bind9 core files. These files have been saved during the build phase.
-
-if [ ! -f /var/named/named.ca ]; then
-    cp -pr /opt/kolla/var-named/* /var/named/
-fi
-
-# When rndc adds a new domain, bind adds the call in an nzf file in this
-# directory.
-chmod 770 /var/named
-chown root:named /var/named
-
-# Default Bind9 behavior is to enable recursion, disable if wanted.
-if [ "${DESIGNATE_ALLOW_RECURSION}" == "false" ]; then
-    sed -i -r "s/(recursion) yes/\1 no/" $NAMEDCFG
-fi
-
-sed -i -r "/listen-on port 53/d" $NAMEDCFG
-sed -i -r "/listen-on-v6/d" $NAMEDCFG
-sed -i -r "s,/\* Path to ISC DLV key \*/,allow-new-zones yes;," $NAMEDCFG
-sed -i -r "/allow-query .+;/d" $NAMEDCFG
-
-if ! grep -q rndc-key /etc/named.conf; then
-    cat >> /etc/named.conf <<EOF
-include "/etc/rndc.key";
-controls {
-    inet ${DESIGNATE_SLAVENS} allow { ${DESIGNATE_MASTERNS}; } keys { "rndc-key"; };
-};
-EOF
-fi
-
-cat > /etc/rndc.key <<EOF
-key "rndc-key" {
-    algorithm hmac-md5;
-    secret "${DESIGNATE_BIND9_RNDC_KEY}";
-};
-EOF
-cat > /etc/rndc.conf <<EOF
-options {
-    default-key "rndc-key";
-    default-server 127.0.0.1;
-    default-port 953;
-};
-EOF
-cat /etc/rndc.key >> /etc/rndc.conf
-chown named /etc/rndc.key
-
-# Launch and keep in the foreground.
-exec /usr/sbin/named -u named -g
diff --git a/docker/centos/binary/designate/designate-backend-bind9/start.sh b/docker/centos/binary/designate/designate-backend-bind9/start.sh
new file mode 120000
index 0000000000000000000000000000000000000000..918411fa1a46eb9b875d7f44f985d7284958e3a5
--- /dev/null
+++ b/docker/centos/binary/designate/designate-backend-bind9/start.sh
@@ -0,0 +1 @@
+../../../../common/designate/designate-backend-bind9/start.sh
\ No newline at end of file
diff --git a/docker/centos/binary/designate/designate-base/config-designate.sh b/docker/centos/binary/designate/designate-base/config-designate.sh
deleted file mode 100755
index 6edfd1bd24971c61f2b9480b351d9b9201cf2b2f..0000000000000000000000000000000000000000
--- a/docker/centos/binary/designate/designate-base/config-designate.sh
+++ /dev/null
@@ -1,79 +0,0 @@
-#!/bin/bash
-
-set -e
-
-. /opt/kolla/kolla-common.sh
-
-get_or_create_domain() {
-    local DOMAIN_NAME=$1
-
-    DOMAIN_ID=$(designate domain-create --name $DOMAIN_NAME | awk '/id/ { print $4; }')
-    # Searching domain if not created
-    if [ -z $DOMAIN_ID ]; then
-        DOMAIN_ID=$(designate domain-list | awk "/$DOMAIN_NAME/ { print \$2; }")
-    fi
-    # Fail if domain still don't exist
-    if [ -z $DOMAIN_ID ]; then
-        echo "Creating domain failed" 1>&2
-        exit 1
-    fi
-
-    echo $DOMAIN_ID
-}
-
-check_required_vars DESIGNATE_DB_PASSWORD DESIGNATE_KEYSTONE_PASSWORD \
-                    KEYSTONE_PUBLIC_SERVICE_HOST RABBITMQ_SERVICE_HOST \
-                    DESIGNATE_BIND9_RNDC_KEY DESIGNATE_BACKEND \
-                    KEYSTONE_PUBLIC_SERVICE_PORT DESIGNATE_KEYSTONE_USER \
-                    RABBIT_USERID RABBIT_PASSWORD DESIGNATE_DB_USER \
-                    DESIGNATE_DB_NAME KEYSTONE_AUTH_PROTOCOL \
-                    KEYSTONE_ADMIN_SERVICE_HOST KEYSTONE_ADMIN_SERVICE_PORT \
-                    DEBUG_LOGGING DESIGNATE_POOLMAN_POOLID
-
-fail_unless_db
-dump_vars
-
-cat > /openrc <<EOF
-export OS_AUTH_URL="http://${KEYSTONE_PUBLIC_SERVICE_HOST}:${KEYSTONE_PUBLIC_SERVICE_PORT}/v2.0"
-export OS_USERNAME="${DESIGNATE_KEYSTONE_USER}"
-export OS_PASSWORD="${DESIGNATE_KEYSTONE_PASSWORD}"
-export OS_TENANT_NAME="${ADMIN_TENANT_NAME}"
-EOF
-
-conf=/etc/designate/designate.conf
-
-# Regular configuration.
-crudini --set $conf DEFAULT log_file ""
-crudini --set $conf DEFAULT use_stderr "True"
-crudini --set $conf DEFAULT debug "${DEBUG_LOGGING}"
-crudini --set $conf DEFAULT rpc_backend "designate.openstack.common.rpc.impl_kombu"
-
-crudini --set $conf oslo_messaging_rabbit rabbit_host "${RABBITMQ_SERVICE_HOST}"
-crudini --set $conf oslo_messaging_rabbit rabbit_userid "${RABBIT_USERID}"
-crudini --set $conf oslo_messaging_rabbit rabbit_password "${RABBIT_PASSWORD}"
-
-crudini --set $conf storage:sqlalchemy connection "mysql://${DESIGNATE_DB_USER}:${DESIGNATE_DB_PASSWORD}@${MARIADB_SERVICE_HOST}/${DESIGNATE_DB_NAME}"
-
-crudini --set $conf service:api auth_strategy "keystone"
-crudini --set $conf service:api api_host "${PUBLIC_IP}"
-
-# Eventhough this is a central-scoped item, it's used in other Designate
-# components as well. Thus it should be configured here, from designate-base.
-crudini --set $conf service:central default_pool_id "${DESIGNATE_POOLMAN_POOLID}"
-
-crudini --set $conf keystone_authtoken identity_uri "${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}"
-crudini --set $conf keystone_authtoken auth_uri "${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_PUBLIC_SERVICE_HOST}:${KEYSTONE_PUBLIC_SERVICE_PORT}/v2.0"
-crudini --set $conf keystone_authtoken admin_tenant_name "${ADMIN_TENANT_NAME}"
-crudini --set $conf keystone_authtoken admin_user "${DESIGNATE_KEYSTONE_USER}"
-crudini --set $conf keystone_authtoken admin_password "${DESIGNATE_KEYSTONE_PASSWORD}"
-
-if [ "${DESIGNATE_BACKEND}" == "bind9" ]; then
-    # Configure a key for RNDC so it can connect with Bind9 to create/delete
-    # zones.
-    cat > /etc/rndc.key <<EOF
-key "rndc-key" {
-    algorithm hmac-md5;
-    secret "${DESIGNATE_BIND9_RNDC_KEY}";
-};
-EOF
-fi
diff --git a/docker/centos/binary/designate/designate-base/config-designate.sh b/docker/centos/binary/designate/designate-base/config-designate.sh
new file mode 120000
index 0000000000000000000000000000000000000000..77aa738de25ecb7ff4610c9801611438c2b0d154
--- /dev/null
+++ b/docker/centos/binary/designate/designate-base/config-designate.sh
@@ -0,0 +1 @@
+../../../../common/designate/designate-base/config-designate.sh
\ No newline at end of file
diff --git a/docker/centos/binary/designate/designate-central/start.sh b/docker/centos/binary/designate/designate-central/start.sh
deleted file mode 100755
index fef7e235327d82491a8bbf11fe92781a9133fa8e..0000000000000000000000000000000000000000
--- a/docker/centos/binary/designate/designate-central/start.sh
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/bash
-set -e
-
-. /opt/kolla/kolla-common.sh
-. /opt/kolla/config-designate.sh
-
-check_required_vars MARIADB_SERVICE_HOST DB_ROOT_PASSWORD DESIGNATE_DB_NAME \
-                    DESIGNATE_DB_USER DESIGNATE_DB_PASSWORD DESIGNATE_INITDB
-
-fail_unless_db
-
-CONF=/etc/designate/designate.conf
-
-if [ "${DESIGNATE_INITDB}" == "true" ]; then
-    echo "Configuring database"
-    mysql -h ${MARIADB_SERVICE_HOST} -u root -p"${DB_ROOT_PASSWORD}" mysql <<EOF
-CREATE DATABASE IF NOT EXISTS ${DESIGNATE_DB_NAME};
-GRANT ALL PRIVILEGES ON ${DESIGNATE_DB_NAME}.* TO '${DESIGNATE_DB_USER}'@'%' IDENTIFIED BY '${DESIGNATE_DB_PASSWORD}'
-EOF
-
-    designate-manage database sync
-fi
-
-exec /usr/bin/designate-central
diff --git a/docker/centos/binary/designate/designate-central/start.sh b/docker/centos/binary/designate/designate-central/start.sh
new file mode 120000
index 0000000000000000000000000000000000000000..9e0a8c484abaf9c9b7ef17f0deac9c317005074d
--- /dev/null
+++ b/docker/centos/binary/designate/designate-central/start.sh
@@ -0,0 +1 @@
+../../../../common/designate/designate-central/start.sh
\ No newline at end of file
diff --git a/docker/centos/binary/designate/designate-mdns/start.sh b/docker/centos/binary/designate/designate-mdns/start.sh
deleted file mode 100755
index a3e5df2747db943a1bec999c4f180446a3bffb7c..0000000000000000000000000000000000000000
--- a/docker/centos/binary/designate/designate-mdns/start.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-set -e
-
-. /opt/kolla/kolla-common.sh
-. /opt/kolla/config-designate.sh
-
-check_required_vars DESIGNATE_MASTERNS DESIGNATE_MDNS_PORT
-
-CONF=/etc/designate/designate.conf
-
-crudini --set $CONF service:mdns workers "1"
-crudini --set $CONF service:mdns host "${DESIGNATE_MASTERNS}"
-crudini --set $CONF service:mdns port "${DESIGNATE_MDNS_PORT}"
-crudini --set $CONF service:mdns tcp_backlog "100"
-crudini --set $CONF service:mdns all_tcp "False"
-
-exec /usr/bin/designate-mdns
diff --git a/docker/centos/binary/designate/designate-mdns/start.sh b/docker/centos/binary/designate/designate-mdns/start.sh
new file mode 120000
index 0000000000000000000000000000000000000000..f7bf747fc5b452b89ab5751545e015b4afbf7bdc
--- /dev/null
+++ b/docker/centos/binary/designate/designate-mdns/start.sh
@@ -0,0 +1 @@
+../../../../common/designate/designate-mdns/start.sh
\ No newline at end of file
diff --git a/docker/centos/binary/designate/designate-poolmanager/start.sh b/docker/centos/binary/designate/designate-poolmanager/start.sh
deleted file mode 100755
index f5222b3f46751cc1c26191056696696146edeeda..0000000000000000000000000000000000000000
--- a/docker/centos/binary/designate/designate-poolmanager/start.sh
+++ /dev/null
@@ -1,54 +0,0 @@
-#!/bin/bash
-set -e
-
-. /opt/kolla/kolla-common.sh
-. /opt/kolla/config-designate.sh
-
-check_required_vars DESIGNATE_MASTERNS DESIGNATE_BACKEND DESIGNATE_SLAVENS \
-                    DESIGNATE_MDNS_PORT DESIGNATE_DNS_PORT DESIGNATE_POOLMAN_POOLID \
-                    DESIGNATE_POOLMAN_TARGETS DESIGNATE_POOLMAN_NSS \
-                    DESIGNATE_POOLMAN_POOLID
-
-CONF=/etc/designate/designate.conf
-
-if [ "${DESIGNATE_BACKEND}" == "bind9" ]; then
-    TYPE="bind9"
-    OPTIONS="rndc_host: ${DESIGNATE_SLAVENS}, rndc_key_file: /etc/rndc.key"
-else
-    echo Unsupported backend: ${DESIGNATE_BACKEND}
-    exit
-fi
-
-crudini --set $CONF service:pool_manager workers "1"
-crudini --set $CONF service:pool_manager enable_recovery_timer "False"
-crudini --set $CONF service:pool_manager periodic_recovery_interval "120"
-crudini --set $CONF service:pool_manager enable_sync_timer "True"
-crudini --set $CONF service:pool_manager periodic_sync_interval "1800"
-crudini --set $CONF service:pool_manager poll_max_retries "10"
-crudini --set $CONF service:pool_manager poll_delay "5"
-crudini --set $CONF service:pool_manager poll_retry_interval "15"
-crudini --set $CONF service:pool_manager pool_id "${DESIGNATE_POOLMAN_POOLID}"
-crudini --set $CONF service:pool_manager cache_driver "noop"
-
-# TODO: use this to use memcached
-#crudini --set $CONF service:pool_manager cache_driver memcache
-#crudini --set $CONF service:pool_manager memcached_servers ${MEMCACHED_HOST}
-
-# Specify the id of the pool managed through pool_manager. Central gets
-# configured with this pool_id as well.
-crudini --set $CONF service:pool_manager pool_id "${DESIGNATE_POOLMAN_POOLID}"
-
-crudini --set $CONF pool:${DESIGNATE_POOLMAN_POOLID} nameservers "${DESIGNATE_POOLMAN_NSS}"
-crudini --set $CONF pool:${DESIGNATE_POOLMAN_POOLID} targets "${DESIGNATE_POOLMAN_TARGETS}"
-
-crudini --set $CONF pool_target:${DESIGNATE_POOLMAN_TARGETS} type "${TYPE}"
-crudini --set $CONF pool_target:${DESIGNATE_POOLMAN_TARGETS} options "${OPTIONS}"
-# This is the mdns container, which is the master nameserver.
-crudini --set $CONF pool_target:${DESIGNATE_POOLMAN_TARGETS} masters "${DESIGNATE_MASTERNS}:${DESIGNATE_MDNS_PORT}"
-crudini --set $CONF pool_target:${DESIGNATE_POOLMAN_TARGETS} host "${DESIGNATE_MASTERNS}"
-crudini --set $CONF pool_target:${DESIGNATE_POOLMAN_TARGETS} port "${DESIGNATE_DNS_PORT}"
-
-crudini --set $CONF pool_nameserver:${DESIGNATE_POOLMAN_NSS} host "${DESIGNATE_MASTERNS}"
-crudini --set $CONF pool_nameserver:${DESIGNATE_POOLMAN_NSS} port "${DESIGNATE_DNS_PORT}"
-
-exec /usr/bin/designate-pool-manager
diff --git a/docker/centos/binary/designate/designate-poolmanager/start.sh b/docker/centos/binary/designate/designate-poolmanager/start.sh
new file mode 120000
index 0000000000000000000000000000000000000000..cc428b4fe4b91db92f363d9a9f4abb66fc733282
--- /dev/null
+++ b/docker/centos/binary/designate/designate-poolmanager/start.sh
@@ -0,0 +1 @@
+../../../../common/designate/designate-poolmanager/start.sh
\ No newline at end of file
diff --git a/docker/centos/binary/galera/config-galera.sh b/docker/centos/binary/galera/config-galera.sh
deleted file mode 100755
index f0ab542e15344897084c4d666861734a80005c6e..0000000000000000000000000000000000000000
--- a/docker/centos/binary/galera/config-galera.sh
+++ /dev/null
@@ -1,94 +0,0 @@
-#!/bin/bash
-
-. /opt/kolla/kolla-common.sh
-
-check_required_vars DB_CLUSTER_BIND_ADDRESS DB_CLUSTER_NAME DB_CLUSTER_NODES \
-                    DB_ROOT_PASSWORD DB_CLUSTER_WSREP_METHOD
-
-CFG=/etc/my.cnf.d/server.cnf
-DB_CLUSTER_INIT_SQL=/tmp/mysql-first-time.sql
-
-function configure_files {
-    crudini --set $CFG mariadb bind-address "${DB_CLUSTER_BIND_ADDRESS}"
-    crudini --set $CFG mariadb binlog_format "ROW"
-    crudini --set $CFG mariadb character-set-server "utf8"
-    crudini --set $CFG mariadb collation-server "utf8_general_ci"
-    crudini --set $CFG mariadb datadir "/var/lib/mysql"
-    crudini --set $CFG mariadb default-storage-engine "innodb"
-    crudini --set $CFG mariadb init-connect "'SET NAMES utf8'"
-    crudini --set $CFG mariadb innodb_autoinc_lock_mode "2"
-    crudini --set $CFG mariadb innodb_file_per_table 1
-    crudini --set $CFG mariadb innodb_flush_log_at_trx_commit "2"
-    crudini --set $CFG mariadb innodb_locks_unsafe_for_binlog "1"
-    crudini --set $CFG mariadb innodb_log_file_size "100M"
-    crudini --set $CFG mariadb query_cache_size "0"
-    crudini --set $CFG mariadb query_cache_type "0"
-    crudini --set $CFG mariadb wsrep_cluster_address "gcomm://${DB_CLUSTER_NODES}"
-    crudini --set $CFG mariadb wsrep_cluster_name "${DB_CLUSTER_NAME}"
-    crudini --set $CFG mariadb wsrep_provider "/usr/lib64/galera/libgalera_smm.so"
-    crudini --set $CFG mariadb wsrep_sst_auth "'root:${DB_ROOT_PASSWORD}'"
-    crudini --set $CFG mariadb wsrep_sst_method "${DB_CLUSTER_WSREP_METHOD}"
-}
-
-function bootstrap_database() {
-    mysqld_safe &
-    # Waiting for deamon
-    sleep 10
-    expect -c '
-    set timeout 10
-    spawn mysql_secure_installation
-    expect "Enter current password for root (enter for none):"
-    send "\r"
-    expect "Set root password?"
-    send "y\r"
-    expect "New password:"
-    send "'"${DB_ROOT_PASSWORD}"'\r"
-    expect "Re-enter new password:"
-    send "'"${DB_ROOT_PASSWORD}"'\r"
-    expect "Remove anonymous users?"
-    send "y\r"
-    expect "Disallow root login remotely?"
-    send "n\r"
-    expect "Remove test database and access to it?"
-    send "y\r"
-    expect "Reload privilege tables now?"
-    send "y\r"
-    expect eof'
-    mysqladmin -p"${DB_ROOT_PASSWORD}" shutdown
-}
-
-function configure_db {
-    bootstrap_database
-
-    echo "GRANT ALL ON *.* TO 'root'@'%' IDENTIFIED BY '$DB_ROOT_PASSWORD' ;" > $DB_CLUSTER_INIT_SQL
-
-    if [ "$MARIADB_DATABASE" ]; then
-        echo "CREATE DATABASE IF NOT EXISTS $MARIADB_DATABASE ;" >> $DB_CLUSTER_INIT_SQL
-    fi
-
-    if [ "$MARIADB_USER" -a "$MARIADB_PASSWORD" ]; then
-        echo "CREATE USER '$MARIADB_USER'@'%' IDENTIFIED BY '$MARIADB_PASSWORD' ;" >> $DB_CLUSTER_INIT_SQL
-
-        if [ "$MARIADB_DATABASE" ]; then
-            echo "GRANT ALL ON $MARIADB_DATABASE.* TO '$MARIADB_USER'@'%' ;" >> $DB_CLUSTER_INIT_SQL
-        fi
-    fi
-
-    echo "FLUSH PRIVILEGES" >> $DB_CLUSTER_INIT_SQL
-}
-
-function populate_db {
-    if [[ $(ls /var/lib/mysql) == "" ]]; then
-        echo "POPULATING NEW DB"
-        mysql_install_db
-        chown -R mysql /var/lib/mysql
-    else
-        echo "DB ALREADY EXISTS"
-    fi
-}
-
-function prepare_db {
-    populate_db
-    configure_db
-    configure_files
-}
diff --git a/docker/centos/binary/galera/config-galera.sh b/docker/centos/binary/galera/config-galera.sh
new file mode 120000
index 0000000000000000000000000000000000000000..f6782bb871765345e3ca337b78e00e6460bd820b
--- /dev/null
+++ b/docker/centos/binary/galera/config-galera.sh
@@ -0,0 +1 @@
+../../../common/galera/config-galera.sh
\ No newline at end of file
diff --git a/docker/centos/binary/galera/start.sh b/docker/centos/binary/galera/start.sh
deleted file mode 100755
index 9288b77cc74a376fd2050816d49deadd56772d77..0000000000000000000000000000000000000000
--- a/docker/centos/binary/galera/start.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/bash
-
-. /opt/kolla/kolla-common.sh
-. /opt/kolla/config-galera.sh
-
-check_required_vars DB_CLUSTER_INIT_DB
-prepare_db
-
-if [[ "${DB_CLUSTER_INIT_DB}" == "true" ]] && ! [[ -a /var/lib/mysql/cluster.exists ]]; then
-    DB_CLUSTER_IS_MASTER_NODE="--wsrep-new-cluster"
-    touch /var/lib/mysql/cluster.exists
-fi
-
-mysqld_safe --init-file=$DB_CLUSTER_INIT_SQL $DB_CLUSTER_IS_MASTER_NODE
\ No newline at end of file
diff --git a/docker/centos/binary/galera/start.sh b/docker/centos/binary/galera/start.sh
new file mode 120000
index 0000000000000000000000000000000000000000..1fa9a143dbb068c5b297b12c60184a78335a78a7
--- /dev/null
+++ b/docker/centos/binary/galera/start.sh
@@ -0,0 +1 @@
+../../../common/galera/start.sh
\ No newline at end of file
diff --git a/docker/centos/binary/glance/glance-api/check.sh b/docker/centos/binary/glance/glance-api/check.sh
deleted file mode 100755
index f97ef70f46ffef79a4dbd27403819c3a1932d7a1..0000000000000000000000000000000000000000
--- a/docker/centos/binary/glance/glance-api/check.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-
-RES=0
-
-. /openrc
-if ! keystone token-get > /dev/null; then
-    echo "ERROR: keystone token-get failed" >&2
-    RES=1
-else
-    if ! glance image-list > /dev/null; then
-        echo "ERROR: glance image-list failed" >&2
-        RES=1
-    fi
-fi
-
-exit $RES
-
diff --git a/docker/centos/binary/glance/glance-api/check.sh b/docker/centos/binary/glance/glance-api/check.sh
new file mode 120000
index 0000000000000000000000000000000000000000..73dd5e25370a414626cc8590d00f06ed6de586cc
--- /dev/null
+++ b/docker/centos/binary/glance/glance-api/check.sh
@@ -0,0 +1 @@
+../../../../common/glance/glance-api/check.sh
\ No newline at end of file
diff --git a/docker/centos/binary/glance/glance-api/start.sh b/docker/centos/binary/glance/glance-api/start.sh
deleted file mode 100755
index c546333f44d01e84881234ab5aee9319bae176d5..0000000000000000000000000000000000000000
--- a/docker/centos/binary/glance/glance-api/start.sh
+++ /dev/null
@@ -1,52 +0,0 @@
-#!/bin/bash
-
-set -e
-
-. /opt/kolla/kolla-common.sh
-. /opt/kolla/config-glance.sh
-: ${GLANCE_API_SERVICE_HOST:=$PUBLIC_IP}
-
-check_required_vars KEYSTONE_ADMIN_TOKEN KEYSTONE_ADMIN_SERVICE_HOST \
-                    GLANCE_KEYSTONE_USER GLANCE_KEYSTONE_PASSWORD \
-                    ADMIN_TENANT_NAME GLANCE_API_SERVICE_HOST \
-                    PUBLIC_IP
-
-fail_unless_os_service_running keystone
-
-export SERVICE_TOKEN="${KEYSTONE_ADMIN_TOKEN}"
-export SERVICE_ENDPOINT="${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}/v2.0"
-
-crux user-create --update \
-    -n "${GLANCE_KEYSTONE_USER}" \
-    -p "${GLANCE_KEYSTONE_PASSWORD}" \
-    -t "${ADMIN_TENANT_NAME}" \
-    -r admin
-
-crux endpoint-create --remove-all \
-    -n glance -t image \
-    -I "http://${GLANCE_API_SERVICE_HOST}:9292" \
-    -P "http://${PUBLIC_IP}:9292" \
-    -A "http://${GLANCE_API_SERVICE_HOST}:9292"
-
-# turn on notification sending by glance
-crudini --set /etc/glance/glance-api.conf \
-    DEFAULT \
-    notification_driver \
-    "messaging"
-
-crudini --set /etc/glance/glance-api.conf \
-    DEFAULT \
-    rabbit_host \
-    "${RABBITMQ_SERVICE_HOST}"
-
-crudini --set /etc/glance/glance-api.conf \
-    DEFAULT \
-    registry_host \
-    "${GLANCE_REGISTRY_SERVICE_HOST}"
-
-crudini --set /etc/glance/glance-api.conf \
-    DEFAULT \
-    debug \
-    "True"
-
-exec /usr/bin/glance-api
diff --git a/docker/centos/binary/glance/glance-api/start.sh b/docker/centos/binary/glance/glance-api/start.sh
new file mode 120000
index 0000000000000000000000000000000000000000..6740e1fe92d7ed051c1fb61229b3709afe364989
--- /dev/null
+++ b/docker/centos/binary/glance/glance-api/start.sh
@@ -0,0 +1 @@
+../../../../common/glance/glance-api/start.sh
\ No newline at end of file
diff --git a/docker/centos/binary/glance/glance-base/config-glance.sh b/docker/centos/binary/glance/glance-base/config-glance.sh
deleted file mode 100644
index 97d076c11652dff140f775caeafad9c69a25ba96..0000000000000000000000000000000000000000
--- a/docker/centos/binary/glance/glance-base/config-glance.sh
+++ /dev/null
@@ -1,63 +0,0 @@
-#!/bin/bash
-
-set -e
-
-. /opt/kolla/kolla-common.sh
-
-: ${ADMIN_TENANT_NAME:=admin}
-: ${GLANCE_DB_NAME:=glance}
-: ${GLANCE_DB_USER:=glance}
-: ${GLANCE_KEYSTONE_USER:=glance}
-: ${KEYSTONE_AUTH_PROTOCOL:=http}
-: ${PUBLIC_IP:=$GLANCE_API_PORT_9292_TCP_ADDR}
-
-check_required_vars GLANCE_DB_PASSWORD GLANCE_KEYSTONE_PASSWORD
-dump_vars
-
-cat > /openrc <<EOF
-export OS_AUTH_URL="http://${KEYSTONE_PUBLIC_SERVICE_HOST}:5000/v2.0"
-export OS_USERNAME="${GLANCE_KEYSTONE_USER}"
-export OS_PASSWORD="${GLANCE_KEYSTONE_PASSWORD}"
-export OS_TENANT_NAME="${ADMIN_TENANT_NAME}"
-EOF
-
-for cfg in /etc/glance/glance-api.conf /etc/glance/glance-registry.conf; do
-    crudini --set $cfg \
-        DEFAULT \
-        log_file \
-        ""
-
-    for option in auth_protocol auth_host auth_port; do
-        crudini --del $cfg \
-            keystone_authtoken \
-            $option
-    done
-
-    crudini --set $cfg \
-        keystone_authtoken \
-        auth_uri \
-        "http://${KEYSTONE_PUBLIC_SERVICE_HOST}:5000/"
-    crudini --set $cfg \
-        keystone_authtoken \
-        admin_tenant_name \
-        "${ADMIN_TENANT_NAME}"
-    crudini --set $cfg \
-        keystone_authtoken \
-        admin_user \
-        "${GLANCE_KEYSTONE_USER}"
-    crudini --set $cfg \
-        keystone_authtoken \
-        admin_password \
-        "${GLANCE_KEYSTONE_PASSWORD}"
-
-    crudini --set $cfg \
-        paste_deploy \
-        flavor \
-        keystone
-
-    crudini --set $cfg \
-        database \
-        connection \
-        "mysql://${GLANCE_DB_USER}:${GLANCE_DB_PASSWORD}@${MARIADB_SERVICE_HOST}/${GLANCE_DB_NAME}"
-done
-
diff --git a/docker/centos/binary/glance/glance-base/config-glance.sh b/docker/centos/binary/glance/glance-base/config-glance.sh
new file mode 120000
index 0000000000000000000000000000000000000000..d5c26f0b84e89c476ca5e7a7eaac01e99691f23e
--- /dev/null
+++ b/docker/centos/binary/glance/glance-base/config-glance.sh
@@ -0,0 +1 @@
+../../../../common/glance/glance-base/config-glance.sh
\ No newline at end of file
diff --git a/docker/centos/binary/glance/glance-registry/start.sh b/docker/centos/binary/glance/glance-registry/start.sh
deleted file mode 100755
index 5f590fb1ccd5d979ba075aa5dc5bcacf7d1d2745..0000000000000000000000000000000000000000
--- a/docker/centos/binary/glance/glance-registry/start.sh
+++ /dev/null
@@ -1,21 +0,0 @@
-#!/bin/bash
-
-set -e
-
-. /opt/kolla/kolla-common.sh
-. /opt/kolla/config-glance.sh
-
-check_required_vars GLANCE_DB_NAME GLANCE_DB_USER GLANCE_DB_PASSWORD
-# lets wait for the DB to be available
-wait_for 25 1 check_for_db
-
-mysql -h ${MARIADB_SERVICE_HOST} -u root -p${DB_ROOT_PASSWORD} mysql <<EOF
-CREATE DATABASE IF NOT EXISTS ${GLANCE_DB_NAME} DEFAULT CHARACTER SET utf8;
-GRANT ALL PRIVILEGES ON ${GLANCE_DB_NAME}.* TO
-       '${GLANCE_DB_USER}'@'%' IDENTIFIED BY '${GLANCE_DB_PASSWORD}'
-
-EOF
-
-/usr/bin/glance-manage db_sync
-
-exec /usr/bin/glance-registry
diff --git a/docker/centos/binary/glance/glance-registry/start.sh b/docker/centos/binary/glance/glance-registry/start.sh
new file mode 120000
index 0000000000000000000000000000000000000000..1295cdc3140a523560c371c2786734f163333d75
--- /dev/null
+++ b/docker/centos/binary/glance/glance-registry/start.sh
@@ -0,0 +1 @@
+../../../../common/glance/glance-registry/start.sh
\ No newline at end of file
diff --git a/docker/centos/binary/hautoproxy/haproxy.cfg.tmpl b/docker/centos/binary/hautoproxy/haproxy.cfg.tmpl
deleted file mode 100644
index cd1174b21966fcf5fc0e4d4da7514f973079b402..0000000000000000000000000000000000000000
--- a/docker/centos/binary/hautoproxy/haproxy.cfg.tmpl
+++ /dev/null
@@ -1,26 +0,0 @@
-global
-    daemon
-    maxconn 4096
-    pidfile /var/run/haproxy.pid
-
-defaults
-    mode tcp
-    timeout connect 5s
-    timeout client 1m
-    timeout server 1m
-    option redispatch
-    balance roundrobin
-
-listen stats :1936
-    mode http
-    stats enable
-    stats hide-version
-    #stats realm Haproxy\ Statistics
-    stats uri /
-    #stats auth Username:Password
-
-{% for service in services %}
-listen {{ service.service_name }}
-    bind 127.0.0.1:{{service.local_port}}
-    server {{ service.remote_name }} {{ service.remote_addr }}:{{ service.remote_port}} check inter 2s rise 3 fall 2
-{% endfor %}
diff --git a/docker/centos/binary/hautoproxy/haproxy.cfg.tmpl b/docker/centos/binary/hautoproxy/haproxy.cfg.tmpl
new file mode 120000
index 0000000000000000000000000000000000000000..dc3f45c31a243af13316f3ed8d892f34441caf9a
--- /dev/null
+++ b/docker/centos/binary/hautoproxy/haproxy.cfg.tmpl
@@ -0,0 +1 @@
+../../../common/hautoproxy/haproxy.cfg.tmpl
\ No newline at end of file
diff --git a/docker/centos/binary/hautoproxy/start.py b/docker/centos/binary/hautoproxy/start.py
deleted file mode 100755
index 877b22157b8dcd205b65fd7ff44d35894bc85033..0000000000000000000000000000000000000000
--- a/docker/centos/binary/hautoproxy/start.py
+++ /dev/null
@@ -1,65 +0,0 @@
-#!/usr/bin/python
-
-'''This script configures and starts a local haproxy instances, bound to
-127.0.0.1, that forwards connections all of the discovered
-docker/kubernetes environment variables.'''
-
-import argparse
-import os
-import sys
-from jinja2 import Environment, FileSystemLoader
-import re
-import urlparse
-
-re_url = re.compile(
-    '^(?P<name>.*)_PORT_(?P<port>\d+)_(?P<proto>(UDP|TCP))$')
-
-def parse_args():
-    p = argparse.ArgumentParser()
-    p.add_argument('--output', '-o',
-                   default='/etc/haproxy/haproxy.cfg')
-    p.add_argument('--no-start', '-n',
-                   action='store_true')
-    p.add_argument('--template-dir', '-t',
-                   default='/etc/haproxy/templates')
-    return p.parse_args()
-
-def discover_services():
-    services = []
-    for k in os.environ:
-        mo = re_url.match(k)
-
-        if mo:
-            parts = urlparse.urlparse(os.environ[k])
-            remote_host,remote_port = parts.netloc.split(':')
-            service_name = '%(name)s-%(port)s' % mo.groupdict()
-
-            services.append({
-                'remote_name': mo.group('name'),
-                'remote_addr': remote_host,
-                'remote_port': remote_port,
-                'remote_proto': parts.scheme,
-                'local_port': mo.group('port'),
-                'service_name': service_name,
-            })
-
-    return services
-
-def main():
-    args = parse_args()
-    services = discover_services()
-
-    env = Environment(loader=FileSystemLoader(['.',
-                                               args.template_dir]))
-    template = env.get_template('haproxy.cfg.tmpl')
-    with open(args.output, 'w') as fd:
-        fd.write(template.render(services=services))
-
-    if args.no_start:
-        return
-
-    os.execlp('haproxy', 'haproxy', '-f', args.output, '-db')
-
-if __name__ == '__main__':
-    main()
-
diff --git a/docker/centos/binary/hautoproxy/start.py b/docker/centos/binary/hautoproxy/start.py
new file mode 120000
index 0000000000000000000000000000000000000000..f89efa2f89a1d4ae508364fff13738e02b0d1fd5
--- /dev/null
+++ b/docker/centos/binary/hautoproxy/start.py
@@ -0,0 +1 @@
+../../../common/hautoproxy/start.py
\ No newline at end of file
diff --git a/docker/centos/binary/heat/heat-api-cfn/check.sh b/docker/centos/binary/heat/heat-api-cfn/check.sh
deleted file mode 100755
index ee03dc6d23e3488433ffda423f567aabda4f9e73..0000000000000000000000000000000000000000
--- a/docker/centos/binary/heat/heat-api-cfn/check.sh
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/bin/bash
-
-RES=0
-
-. /openrc
-if ! keystone token-get > /dev/null; then
-    echo "ERROR: keystone token-get failed" >&2
-    RES=1
-else
-    if ! heat stack-list > /dev/null; then
-        echo "ERROR: heat stack-list failed" >&2
-        RES=1
-    fi
-fi
-
-exit $RES
diff --git a/docker/centos/binary/heat/heat-api-cfn/check.sh b/docker/centos/binary/heat/heat-api-cfn/check.sh
new file mode 120000
index 0000000000000000000000000000000000000000..68fce28bf145f1852ade1f54ba29a7f68bae73a1
--- /dev/null
+++ b/docker/centos/binary/heat/heat-api-cfn/check.sh
@@ -0,0 +1 @@
+../../../../common/heat/heat-api-cfn/check.sh
\ No newline at end of file
diff --git a/docker/centos/binary/heat/heat-api-cfn/start.sh b/docker/centos/binary/heat/heat-api-cfn/start.sh
deleted file mode 100755
index bcd72250b46dd4aba22490428f0f9e060fa35453..0000000000000000000000000000000000000000
--- a/docker/centos/binary/heat/heat-api-cfn/start.sh
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/bin/bash
-set -e
-
-. /opt/kolla/kolla-common.sh
-. /opt/kolla/config-heat.sh
-
-check_required_vars KEYSTONE_ADMIN_TOKEN KEYSTONE_ADMIN_SERVICE_HOST \
-                    HEAT_CFN_KEYSTONE_USER HEAT_CFN_KEYSTONE_PASSWORD \
-                    KEYSTONE_AUTH_PROTOCOL KEYSTONE_ADMIN_SERVICE_PORT \
-                    ADMIN_TENANT_NAME HEAT_API_CFN_SERVICE_HOST \
-                    HEAT_API_CFN_SERVICE_PORT
-
-fail_unless_os_service_running keystone
-
-export SERVICE_TOKEN="${KEYSTONE_ADMIN_TOKEN}"
-export SERVICE_ENDPOINT="${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}/v2.0"
-
-crux user-create -n ${HEAT_CFN_KEYSTONE_USER} \
-    -p ${HEAT_CFN_KEYSTONE_PASSWORD} \
-    -t ${ADMIN_TENANT_NAME} \
-    -r admin
-
-crux endpoint-create --remove-all -n ${HEAT_CFN_KEYSTONE_USER} -t cloudformation \
-    -I "${KEYSTONE_AUTH_PROTOCOL}://${HEAT_API_CFN_SERVICE_HOST}:${HEAT_API_CFN_SERVICE_PORT}/v1" \
-    -P "${KEYSTONE_AUTH_PROTOCOL}://${HEAT_API_CFN_SERVICE_HOST}:${HEAT_API_CFN_SERVICE_PORT}/v1" \
-    -A "${KEYSTONE_AUTH_PROTOCOL}://${HEAT_API_CFN_SERVICE_HOST}:${HEAT_API_CFN_SERVICE_PORT}/v1"
-
-exec /usr/bin/heat-api-cfn
diff --git a/docker/centos/binary/heat/heat-api-cfn/start.sh b/docker/centos/binary/heat/heat-api-cfn/start.sh
new file mode 120000
index 0000000000000000000000000000000000000000..a71201d4b03c2b9a6428e71de358a811be9a8db7
--- /dev/null
+++ b/docker/centos/binary/heat/heat-api-cfn/start.sh
@@ -0,0 +1 @@
+../../../../common/heat/heat-api-cfn/start.sh
\ No newline at end of file
diff --git a/docker/centos/binary/heat/heat-api/check.sh b/docker/centos/binary/heat/heat-api/check.sh
deleted file mode 100755
index ee03dc6d23e3488433ffda423f567aabda4f9e73..0000000000000000000000000000000000000000
--- a/docker/centos/binary/heat/heat-api/check.sh
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/bin/bash
-
-RES=0
-
-. /openrc
-if ! keystone token-get > /dev/null; then
-    echo "ERROR: keystone token-get failed" >&2
-    RES=1
-else
-    if ! heat stack-list > /dev/null; then
-        echo "ERROR: heat stack-list failed" >&2
-        RES=1
-    fi
-fi
-
-exit $RES
diff --git a/docker/centos/binary/heat/heat-api/check.sh b/docker/centos/binary/heat/heat-api/check.sh
new file mode 120000
index 0000000000000000000000000000000000000000..1e72d2e2c1ad91af162327cd174772ab04e38e1f
--- /dev/null
+++ b/docker/centos/binary/heat/heat-api/check.sh
@@ -0,0 +1 @@
+../../../../common/heat/heat-api/check.sh
\ No newline at end of file
diff --git a/docker/centos/binary/heat/heat-api/start.sh b/docker/centos/binary/heat/heat-api/start.sh
deleted file mode 100755
index b57aaa710b880d444e680b9520f71112b9a94f35..0000000000000000000000000000000000000000
--- a/docker/centos/binary/heat/heat-api/start.sh
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/bin/bash
-set -e
-
-. /opt/kolla/kolla-common.sh
-. /opt/kolla/config-heat.sh
-
-check_required_vars KEYSTONE_ADMIN_TOKEN KEYSTONE_ADMIN_SERVICE_HOST \
-                    HEAT_KEYSTONE_USER HEAT_KEYSTONE_PASSWORD \
-                    KEYSTONE_AUTH_PROTOCOL ADMIN_TENANT_NAME \
-                    HEAT_API_SERVICE_HOST PUBLIC_IP
-
-fail_unless_os_service_running keystone
-
-export SERVICE_TOKEN="${KEYSTONE_ADMIN_TOKEN}"
-export SERVICE_ENDPOINT="${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:35357/v2.0"
-crux user-create -n ${HEAT_KEYSTONE_USER} \
-    -p ${HEAT_KEYSTONE_PASSWORD} \
-    -t ${ADMIN_TENANT_NAME} \
-    -r admin
-
-crux endpoint-create --remove-all -n ${HEAT_KEYSTONE_USER} -t orchestration \
-    -I "${KEYSTONE_AUTH_PROTOCOL}://${HEAT_API_SERVICE_HOST}:8004/v1/%(tenant_id)s" \
-    -P "${KEYSTONE_AUTH_PROTOCOL}://${PUBLIC_IP}:8004/v1/%(tenant_id)s" \
-    -A "${KEYSTONE_AUTH_PROTOCOL}://${HEAT_API_SERVICE_HOST}:8004/v1/%(tenant_id)s"
-
-# will use crux after https://github.com/larsks/crux/issues/1 is implemented
-openstack role list --os-token="${KEYSTONE_ADMIN_TOKEN}" --os-url $SERVICE_ENDPOINT -f csv | tail -n +2 | awk -F, '{print $2}' | grep heat_stack_user || keystone role-create --name heat_stack_user
-
-exec /usr/bin/heat-api
diff --git a/docker/centos/binary/heat/heat-api/start.sh b/docker/centos/binary/heat/heat-api/start.sh
new file mode 120000
index 0000000000000000000000000000000000000000..cf3eb022cd27cef106f16da3818171d098064dcb
--- /dev/null
+++ b/docker/centos/binary/heat/heat-api/start.sh
@@ -0,0 +1 @@
+../../../../common/heat/heat-api/start.sh
\ No newline at end of file
diff --git a/docker/centos/binary/heat/heat-base/config-heat.sh b/docker/centos/binary/heat/heat-base/config-heat.sh
deleted file mode 100755
index 74b2718a4b71bc31479dfd43a2f1cf1748ccebe3..0000000000000000000000000000000000000000
--- a/docker/centos/binary/heat/heat-base/config-heat.sh
+++ /dev/null
@@ -1,67 +0,0 @@
-#!/bin/bash
-
-set -e
-
-. /opt/kolla/kolla-common.sh
-
-: ${ADMIN_TENANT_NAME:=admin}
-: ${HEAT_DB_NAME:=heat}
-: ${HEAT_DB_USER:=heat}
-: ${HEAT_KEYSTONE_USER:=heat}
-: ${HEAT_CFN_KEYSTONE_USER:=heat_cfn}
-: ${KEYSTONE_AUTH_PROTOCOL:=http}
-: ${PUBLIC_IP:=$HEAT_API_PORT_8004_TCP_ADDR}
-: ${RABBIT_USER:=guest}
-: ${RABBIT_PASSWORD:=guest}
-
-check_required_vars HEAT_DB_PASSWORD HEAT_KEYSTONE_PASSWORD \
-                    KEYSTONE_PUBLIC_SERVICE_HOST RABBITMQ_SERVICE_HOST
-
-fail_unless_db
-dump_vars
-
-cat > /openrc <<EOF
-export OS_AUTH_URL="http://${KEYSTONE_PUBLIC_SERVICE_HOST}:5000/v2.0"
-export OS_USERNAME="${HEAT_KEYSTONE_USER}"
-export OS_PASSWORD="${HEAT_KEYSTONE_PASSWORD}"
-export OS_TENANT_NAME="${ADMIN_TENANT_NAME}"
-EOF
-
-crudini --set /etc/heat/heat.conf DEFAULT log_file \
-    ""
-crudini --set /etc/heat/heat.conf DEFAULT use_stderr \
-    true
-crudini --set /etc/heat/heat.conf DEFAULT rpc_backend \
-    heat.openstack.common.rpc.impl_kombu
-crudini --set /etc/heat/heat.conf DEFAULT rabbit_host \
-    "${RABBITMQ_SERVICE_HOST}"
-crudini --set /etc/heat/heat.conf DEFAULT rabbit_userid \
-    "${RABBIT_USER}"
-crudini --set /etc/heat/heat.conf DEFAULT rabbit_password \
-    "${RABBIT_PASSWORD}"
-
-crudini --set /etc/heat/heat.conf database connection \
-    mysql://${HEAT_DB_USER}:${HEAT_DB_PASSWORD}@${MARIADB_SERVICE_HOST}/${HEAT_DB_NAME}
-
-crudini --set /etc/heat/heat.conf keystone_authtoken auth_protocol \
-    "${KEYSTONE_AUTH_PROTOCOL}"
-crudini --set /etc/heat/heat.conf keystone_authtoken auth_host \
-    "${KEYSTONE_PUBLIC_SERVICE_HOST}"
-crudini --set /etc/heat/heat.conf keystone_authtoken auth_port \
-    "${KEYSTONE_PUBLIC_SERVICE_PORT}"
-crudini --set /etc/heat/heat.conf keystone_authtoken auth_uri \
-    "${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_PUBLIC_SERVICE_HOST}:${KEYSTONE_PUBLIC_SERVICE_PORT}/v2.0"
-crudini --set /etc/heat/heat.conf  keystone_authtoken admin_tenant_name \
-    "${ADMIN_TENANT_NAME}"
-crudini --set /etc/heat/heat.conf keystone_authtoken admin_user \
-    "${HEAT_KEYSTONE_USER}"
-crudini --set /etc/heat/heat.conf keystone_authtoken admin_password \
-    "${HEAT_KEYSTONE_PASSWORD}"
-
-crudini --set /etc/heat/heat.conf ec2authtoken auth_uri \
-    "${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_PUBLIC_SERVICE_HOST}:${KEYSTONE_PUBLIC_SERVICE_PORT}/v2.0"
-
-crudini --set /etc/heat/heat.conf DEFAULT heat_metadata_server_url \
-    http://${HEAT_API_CFN_URL_HOST}:${HEAT_API_CFN_SERVICE_PORT}
-crudini --set /etc/heat/heat.conf DEFAULT heat_waitcondition_server_url \
-    http://${HEAT_API_CFN_URL_HOST}:${HEAT_API_CFN_SERVICE_PORT}/v1/waitcondition
diff --git a/docker/centos/binary/heat/heat-base/config-heat.sh b/docker/centos/binary/heat/heat-base/config-heat.sh
new file mode 120000
index 0000000000000000000000000000000000000000..8b4e89797881f26bf1108cabea59004dafc29e87
--- /dev/null
+++ b/docker/centos/binary/heat/heat-base/config-heat.sh
@@ -0,0 +1 @@
+../../../../common/heat/heat-base/config-heat.sh
\ No newline at end of file
diff --git a/docker/centos/binary/heat/heat-engine/start.sh b/docker/centos/binary/heat/heat-engine/start.sh
deleted file mode 100755
index 2dfc78e9280323de3ad4650e7b0e65c10f1f34c7..0000000000000000000000000000000000000000
--- a/docker/centos/binary/heat/heat-engine/start.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-
-. /opt/kolla/kolla-common.sh
-. /opt/kolla/config-heat.sh
-
-check_required_vars HEAT_DB_NAME HEAT_DB_USER HEAT_DB_PASSWORD
-fail_unless_db
-
-mysql -h ${MARIADB_SERVICE_HOST} -u root -p${DB_ROOT_PASSWORD} mysql <<EOF
-CREATE DATABASE IF NOT EXISTS ${HEAT_DB_NAME} DEFAULT CHARACTER SET utf8;
-GRANT ALL PRIVILEGES ON ${HEAT_DB_NAME}.* TO
-    '${HEAT_DB_USER}'@'%' IDENTIFIED BY '${HEAT_DB_PASSWORD}'
-EOF
-
-/usr/bin/heat-manage db_sync
-
-exec /usr/bin/heat-engine
diff --git a/docker/centos/binary/heat/heat-engine/start.sh b/docker/centos/binary/heat/heat-engine/start.sh
new file mode 120000
index 0000000000000000000000000000000000000000..d660bc5d116a4647d67b51a689a1837f56d6d44a
--- /dev/null
+++ b/docker/centos/binary/heat/heat-engine/start.sh
@@ -0,0 +1 @@
+../../../../common/heat/heat-engine/start.sh
\ No newline at end of file
diff --git a/docker/centos/binary/horizon/start.sh b/docker/centos/binary/horizon/start.sh
deleted file mode 100755
index 4e720bb879a8fd57f62e387d809274892ae561f4..0000000000000000000000000000000000000000
--- a/docker/centos/binary/horizon/start.sh
+++ /dev/null
@@ -1,36 +0,0 @@
-#!/bin/bash
-set -e
-
-: ${HORIZON_KEYSTONE_USER:=horizon}
-
-. /opt/kolla/kolla-common.sh
-
-fail_unless_os_service_running keystone
-fail_unless_os_service_running glance
-fail_unless_os_service_running nova
-
-export SERVICE_TOKEN="${KEYSTONE_ADMIN_TOKEN}"
-export SERVICE_ENDPOINT="${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:35357/v2.0"
-
-cfg=/etc/openstack-dashboard/local_settings
-httpdcfg=/etc/httpd/conf.d/openstack-dashboard.conf
-
-sed -ri 's/ALLOWED_HOSTS = \['\''horizon.example.com'\'', '\''localhost'\''\]/ALLOWED_HOSTS = \['\''*'\'', \]/' /etc/openstack-dashboard/local_settings
-
-sed -ri 's/OPENSTACK_KEYSTONE_URL = \"http:\/\/%s:5000\/v2.0\" % OPENSTACK_HOST/OPENSTACK_KEYSTONE_URL = \"http:\/\/'"$KEYSTONE_PUBLIC_SERVICE_HOST"':5000\/v2.0\"/' /etc/openstack-dashboard/local_settings
-
-sed -ri 's/OPENSTACK_HOST = \"127.0.0.1\"/OPENSTACK_HOST = \"'"$KEYSTONE_PUBLIC_SERVICE_HOST"'\" /' /etc/openstack-dashboard/local_settings
-
-# Make sure we launch horizon using the default value for WEBROOT, which is
-# '/'.
-sed -ri '/^WEBROOT =.+/d' $cfg
-sed -ri 's,^(WSGIScriptAlias) /dashboard (/usr/share/openstack-dashboard/openstack_dashboard/wsgi/django.wsgi),\1 / \2,' $httpdcfg
-sed -ri 's,^(Alias /dashboard)(/static /usr/share/openstack-dashboard/static),Alias \2,' $httpdcfg
-
-# This step is required because of:
-# https://bugzilla.redhat.com/show_bug.cgi?id=1220070
-# Running this in the Dockerfile didn't fix the HTTP/500 as a result of the
-# missing compress action.
-python /usr/share/openstack-dashboard/manage.py compress
-
-/usr/sbin/httpd -DFOREGROUND
diff --git a/docker/centos/binary/horizon/start.sh b/docker/centos/binary/horizon/start.sh
new file mode 120000
index 0000000000000000000000000000000000000000..3c793e4f9bace9a85d7108284e117b603a3d521d
--- /dev/null
+++ b/docker/centos/binary/horizon/start.sh
@@ -0,0 +1 @@
+../../../common/horizon/start.sh
\ No newline at end of file
diff --git a/docker/centos/binary/keystone/check.sh b/docker/centos/binary/keystone/check.sh
deleted file mode 100755
index ca484478485d9624c43b6832cf626051ac420c50..0000000000000000000000000000000000000000
--- a/docker/centos/binary/keystone/check.sh
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/bin/bash
-
-RES=0
-
-. /openrc
-if ! keystone token-get > /dev/null; then
-    echo "ERROR: keystone token-get failed" >&2
-    RES=1
-fi
-
-exit $RES
-
diff --git a/docker/centos/binary/keystone/check.sh b/docker/centos/binary/keystone/check.sh
new file mode 120000
index 0000000000000000000000000000000000000000..fe8e7608c02a7e75fe42c99ce5f2bffc89b89c41
--- /dev/null
+++ b/docker/centos/binary/keystone/check.sh
@@ -0,0 +1 @@
+../../../common/keystone/check.sh
\ No newline at end of file
diff --git a/docker/centos/binary/keystone/start.sh b/docker/centos/binary/keystone/start.sh
deleted file mode 100755
index 6dfebe06058b269b692ffa9ccffeed136ed90b86..0000000000000000000000000000000000000000
--- a/docker/centos/binary/keystone/start.sh
+++ /dev/null
@@ -1,162 +0,0 @@
-#!/bin/bash
-
-set -e
-
-# Run Kolla common script
-echo "Running the kolla-common script"
-. /opt/kolla/kolla-common.sh
-
-# Credentials, token, etc..
-: ${ADMIN_USER:=admin}
-: ${ADMIN_USER_PASSWORD:=password}
-: ${ADMIN_TENANT_NAME:=admin}
-: ${KEYSTONE_USER:=keystone}
-: ${KEYSTONE_ADMIN_PASSWORD:=password}
-: ${KEYSTONE_ADMIN_TOKEN:=changeme}
-# DB Settings
-: ${INIT_DB:=true}
-: ${KEYSTONE_DB_NAME:=keystone}
-: ${KEYSTONE_DB_USER:=keystone}
-: ${DB_ROOT_PASSWORD:=password}
-: ${MARIADB_SERVICE_HOST:=$PUBLIC_IP}
-: ${KEYSTONE_DB_PASSWORD:=password}
-# Service Addresses/Ports/Version
-: ${KEYSTONE_PUBLIC_SERVICE_HOST:=$PUBLIC_IP}
-: ${KEYSTONE_ADMIN_SERVICE_HOST:=$PUBLIC_IP}
-: ${KEYSTONE_PUBLIC_SERVICE_PORT:=5000}
-: ${KEYSTONE_ADMIN_SERVICE_PORT:=35357}
-: ${KEYSTONE_API_VERSION:=2.0}
-# Logging
-: ${LOG_FILE:=/var/log/keystone/keystone.log}
-: ${VERBOSE_LOGGING:=true}
-: ${DEBUG_LOGGING:=false}
-: ${USE_STDERR:=false}
-# Token provider, driver, etc..
-: ${TOKEN_PROVIDER:=uuid}
-: ${TOKEN_DRIVER:=sql}
-
-## Check DB connectivity and required variables
-echo "Checking connectivity to the DB"
-fail_unless_db
-echo "Checking for required variables"
-check_required_vars KEYSTONE_ADMIN_TOKEN KEYSTONE_DB_PASSWORD \
-                    KEYSTONE_ADMIN_PASSWORD ADMIN_TENANT_NAME \
-                    KEYSTONE_PUBLIC_SERVICE_HOST KEYSTONE_ADMIN_SERVICE_HOST \
-                    PUBLIC_IP
-dump_vars
-
-# Setup the Keystone DB
-echo "Setting up Keystone DB"
-mysql -h ${MARIADB_SERVICE_HOST} -u root -p"${DB_ROOT_PASSWORD}" mysql <<EOF
-CREATE DATABASE IF NOT EXISTS ${KEYSTONE_DB_NAME};
-GRANT ALL PRIVILEGES ON ${KEYSTONE_DB_NAME}.* TO
-    '${KEYSTONE_DB_USER}'@'%' IDENTIFIED BY '${KEYSTONE_DB_PASSWORD}'
-EOF
-
-# File path and name used by crudini tool
-cfg=/etc/keystone/keystone.conf
-
-# Token Configuration
-echo "Configuring keystone.conf"
-crudini --set $cfg \
-    DEFAULT \
-    admin_token \
-    "${KEYSTONE_ADMIN_TOKEN}"
-
-# Database Configuration
-crudini --set $cfg \
-    database \
-    connection \
-    "mysql://${KEYSTONE_DB_USER}:${KEYSTONE_DB_PASSWORD}@${MARIADB_SERVICE_HOST}/${KEYSTONE_DB_NAME}"
-
-# Logging
-crudini --del $cfg \
-    DEFAULT \
-    log_dir
-crudini --set $cfg \
-    DEFAULT \
-    log_file \
-    ${LOG_FILE}
-crudini --set $cfg \
-    DEFAULT \
-    verbose \
-    ${VERBOSE_LOGGING}
-crudini --set $cfg \
-    DEFAULT \
-    debug \
-    ${DEBUG_LOGGING}
-crudini --set $cfg \
-    DEFAULT \
-    use_stderr \
-    ${USE_STDERR}
-
-# Token Management
-crudini --set $cfg \
-    token \
-    provider \
-    keystone.token.providers."${TOKEN_PROVIDER}".Provider
-crudini --set $cfg \
-    token \
-    driver \
-    keystone.token.persistence.backends."${TOKEN_DRIVER}".Token
-crudini --set $cfg \
-    revoke \
-    driver \
-    keystone.contrib.revoke.backends."${TOKEN_DRIVER}".Revoke
-
-# Setup the openrc auth file
-cat > /openrc <<EOF
-export OS_AUTH_URL=http://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}/v${KEYSTONE_API_VERSION}
-export OS_USERNAME=${KEYSTONE_USER}
-export OS_PASSWORD=${KEYSTONE_ADMIN_PASSWORD}
-export OS_TENANT_NAME=${ADMIN_TENANT_NAME}
-EOF
-
-# Run PKI Setup script
-echo "Setting up PKI"
-/usr/bin/keystone-manage pki_setup --keystone-user keystone --keystone-group keystone
-
-# Fix permissions
-chown -R keystone:keystone /var/log/keystone
-chown -R keystone:keystone /etc/keystone/ssl
-chmod -R o-rwx /etc/keystone/ssl
-
-# Initialize the Keystone DB
-echo "Initializing Keystone DB"
-if [ "${INIT_DB}" == "true" ] ; then
-    su -s /bin/bash -c "keystone-manage db_sync" keystone
-fi
-
-# Start Keystone
-echo "Starting Keystone"
-/usr/bin/keystone-all &
-PID=$!
-
-# Export Keystone service environment variables
-export SERVICE_TOKEN="${KEYSTONE_ADMIN_TOKEN}"
-export SERVICE_ENDPOINT="http://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}/v${KEYSTONE_API_VERSION}"
-
-# Check to make sure the service is running
-echo "Verifying Keystone is running"
-while ! curl -o /dev/null -s --fail ${SERVICE_ENDPOINT}; do
-    echo "waiting for Keystone @ ${SERVICE_ENDPOINT}"
-    sleep 1;
-done
-echo "keystone is active @ ${SERVICE_ENDPOINT}"
-
-# Create Keystone tenant, user, role, service and endpoints
-echo "Creating Keystone tenant, user, role, service and endpoints"
-crux user-create --update \
-    -n ${ADMIN_USER} -p "${ADMIN_USER_PASSWORD}" \
-    -t ${ADMIN_TENANT_NAME} -r admin
-crux user-create --update \
-    -n ${KEYSTONE_USER} -p "${KEYSTONE_ADMIN_PASSWORD}" \
-    -t ${ADMIN_TENANT_NAME} -r admin
-crux endpoint-create --remove-all \
-    -n keystone -t identity \
-    -I "http://${KEYSTONE_PUBLIC_SERVICE_HOST}:${KEYSTONE_PUBLIC_SERVICE_PORT}/v${KEYSTONE_API_VERSION}" \
-    -A "http://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}/v${KEYSTONE_API_VERSION}" \
-    -P "http://${KEYSTONE_PUBLIC_SERVICE_HOST}:${KEYSTONE_PUBLIC_SERVICE_PORT}/v${KEYSTONE_API_VERSION}"
-
-# Wait on all jobs to exit before proceeding (see man wait)
-wait
diff --git a/docker/centos/binary/keystone/start.sh b/docker/centos/binary/keystone/start.sh
new file mode 120000
index 0000000000000000000000000000000000000000..ae34844eaba6ef4cb9a99fa6c751879566f138a7
--- /dev/null
+++ b/docker/centos/binary/keystone/start.sh
@@ -0,0 +1 @@
+../../../common/keystone/start.sh
\ No newline at end of file
diff --git a/docker/centos/binary/magnum/magnum-api/check.sh b/docker/centos/binary/magnum/magnum-api/check.sh
deleted file mode 100755
index ee03dc6d23e3488433ffda423f567aabda4f9e73..0000000000000000000000000000000000000000
--- a/docker/centos/binary/magnum/magnum-api/check.sh
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/bin/bash
-
-RES=0
-
-. /openrc
-if ! keystone token-get > /dev/null; then
-    echo "ERROR: keystone token-get failed" >&2
-    RES=1
-else
-    if ! heat stack-list > /dev/null; then
-        echo "ERROR: heat stack-list failed" >&2
-        RES=1
-    fi
-fi
-
-exit $RES
diff --git a/docker/centos/binary/magnum/magnum-api/check.sh b/docker/centos/binary/magnum/magnum-api/check.sh
new file mode 120000
index 0000000000000000000000000000000000000000..7464ba29601de9c6a8ec9df0e5b7392b3c6ab5d5
--- /dev/null
+++ b/docker/centos/binary/magnum/magnum-api/check.sh
@@ -0,0 +1 @@
+../../../../common/magnum/magnum-api/check.sh
\ No newline at end of file
diff --git a/docker/centos/binary/magnum/magnum-api/start.sh b/docker/centos/binary/magnum/magnum-api/start.sh
deleted file mode 100755
index 00a51b3cdfa31b34cc9afecdd3c8e2399f269c21..0000000000000000000000000000000000000000
--- a/docker/centos/binary/magnum/magnum-api/start.sh
+++ /dev/null
@@ -1,27 +0,0 @@
-#!/bin/bash
-set -e
-
-. /opt/kolla/kolla-common.sh
-. /opt/kolla/config-magnum.sh
-
-check_required_vars KEYSTONE_ADMIN_TOKEN KEYSTONE_ADMIN_SERVICE_HOST \
-                    MAGNUM_KEYSTONE_USER MAGNUM_KEYSTONE_PASSWORD \
-                    KEYSTONE_AUTH_PROTOCOL ADMIN_TENANT_NAME \
-                    MAGNUM_API_SERVICE_HOST KEYSTONE_ADMIN_SERVICE_PORT \
-                    MAGNUM_API_SERVICE_PORT
-
-fail_unless_os_service_running keystone
-
-export SERVICE_TOKEN="${KEYSTONE_ADMIN_TOKEN}"
-export SERVICE_ENDPOINT="${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}/v2.0"
-crux user-create -n ${MAGNUM_KEYSTONE_USER} \
-    -p ${MAGNUM_KEYSTONE_PASSWORD} \
-    -t ${ADMIN_TENANT_NAME} \
-    -r admin
-
-crux endpoint-create --remove-all -n ${MAGNUM_KEYSTONE_USER} -t container \
-    -I "${KEYSTONE_AUTH_PROTOCOL}://${MAGNUM_API_SERVICE_HOST}:${MAGNUM_API_SERVICE_PORT}/v1" \
-    -P "${KEYSTONE_AUTH_PROTOCOL}://${MAGNUM_API_SERVICE_HOST}:${MAGNUM_API_SERVICE_PORT}/v1" \
-    -A "${KEYSTONE_AUTH_PROTOCOL}://${MAGNUM_API_SERVICE_HOST}:${MAGNUM_API_SERVICE_PORT}/v1"
-
-exec /usr/bin/magnum-api
diff --git a/docker/centos/binary/magnum/magnum-api/start.sh b/docker/centos/binary/magnum/magnum-api/start.sh
new file mode 120000
index 0000000000000000000000000000000000000000..58cc9e37c943aa2c54d3b72d3d1aedc453ccf439
--- /dev/null
+++ b/docker/centos/binary/magnum/magnum-api/start.sh
@@ -0,0 +1 @@
+../../../../common/magnum/magnum-api/start.sh
\ No newline at end of file
diff --git a/docker/centos/binary/magnum/magnum-base/config-magnum.sh b/docker/centos/binary/magnum/magnum-base/config-magnum.sh
deleted file mode 100755
index 03599d359eb2c874e298443c891e7d7155225234..0000000000000000000000000000000000000000
--- a/docker/centos/binary/magnum/magnum-base/config-magnum.sh
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/bin/bash
-
-set -e
-
-. /opt/kolla/kolla-common.sh
-
-check_required_vars MAGNUM_DB_PASSWORD MAGNUM_KEYSTONE_PASSWORD \
-                    KEYSTONE_PUBLIC_SERVICE_HOST KEYSTONE_PUBLIC_SERVICE_PORT \
-                    MAGNUM_KEYSTONE_USER ADMIN_TENANT_NAME \
-                    MAGNUM_DB_USER MAGNUM_DB_NAME KEYSTONE_AUTH_PROTOCOL \
-                    KEYSTONE_PUBLIC_SERVICE_PORT RABBITMQ_SERVICE_HOST \
-                    VERBOSE_LOGGING DEBUG_LOGGING
-
-fail_unless_db
-dump_vars
-
-cat > /openrc <<EOF
-export OS_AUTH_URL="http://${KEYSTONE_PUBLIC_SERVICE_HOST}:${KEYSTONE_PUBLIC_SERVICE_PORT}/v2.0"
-export OS_USERNAME="${MAGNUM_KEYSTONE_USER}"
-export OS_PASSWORD="${MAGNUM_KEYSTONE_PASSWORD}"
-export OS_TENANT_NAME="${ADMIN_TENANT_NAME}"
-EOF
-
-cfg=/etc/magnum/magnum.conf
-
-crudini --set $cfg DEFAULT log_file ""
-crudini --set $cfg DEFAULT verbose "${VERBOSE_LOGGING}"
-crudini --set $cfg DEFAULT debug "${DEBUG_LOGGING}"
-crudini --set $cfg DEFAULT use_stderr true
-crudini --set $cfg DEFAULT rpc_backend magnum.openstack.common.rpc.impl_kombu
-crudini --set $cfg DEFAULT admin_user admin
-crudini --set $cfg oslo_messaging_rabbit rabbit_host ${RABBITMQ_SERVICE_HOST}
-crudini --set $cfg oslo_messaging_rabbit rabbit_userid ${RABBIT_USER}
-crudini --set $cfg oslo_messaging_rabbit rabbit_password ${RABBIT_PASSWORD}
-crudini --set $cfg database connection \
-    mysql://${MAGNUM_DB_USER}:${MAGNUM_DB_PASSWORD}@${MARIADB_SERVICE_HOST}/${MAGNUM_DB_NAME}
-crudini --set $cfg keystone_authtoken auth_protocol "${KEYSTONE_AUTH_PROTOCOL}"
-crudini --set $cfg keystone_authtoken auth_host "${KEYSTONE_PUBLIC_SERVICE_HOST}"
-crudini --set $cfg keystone_authtoken auth_port "${KEYSTONE_PUBLIC_SERVICE_PORT}"
-crudini --set $cfg keystone_authtoken auth_uri \
-    "${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_PUBLIC_SERVICE_HOST}:${KEYSTONE_PUBLIC_SERVICE_PORT}/v2.0"
-crudini --set $cfg  keystone_authtoken admin_tenant_name "${ADMIN_TENANT_NAME}"
-crudini --set $cfg keystone_authtoken admin_user "${MAGNUM_KEYSTONE_USER}"
-crudini --set $cfg keystone_authtoken admin_password \
-    "${MAGNUM_KEYSTONE_PASSWORD}"
-crudini --set $cfg api host ${MAGNUM_API_SERVICE_HOST}
diff --git a/docker/centos/binary/magnum/magnum-base/config-magnum.sh b/docker/centos/binary/magnum/magnum-base/config-magnum.sh
new file mode 120000
index 0000000000000000000000000000000000000000..473c0be8e294bc669c0879085ae0610e2653b8f7
--- /dev/null
+++ b/docker/centos/binary/magnum/magnum-base/config-magnum.sh
@@ -0,0 +1 @@
+../../../../common/magnum/magnum-base/config-magnum.sh
\ No newline at end of file
diff --git a/docker/centos/binary/magnum/magnum-conductor/start.sh b/docker/centos/binary/magnum/magnum-conductor/start.sh
deleted file mode 100755
index 4cf1291a393c92d093d18497e0ca0c7b334b0c85..0000000000000000000000000000000000000000
--- a/docker/centos/binary/magnum/magnum-conductor/start.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-
-. /opt/kolla/kolla-common.sh
-. /opt/kolla/config-magnum.sh
-
-check_required_vars MAGNUM_DB_NAME MAGNUM_DB_USER MAGNUM_DB_PASSWORD
-fail_unless_db
-
-mysql -h ${MARIADB_SERVICE_HOST} -u root -p${DB_ROOT_PASSWORD} mysql <<EOF
-CREATE DATABASE IF NOT EXISTS ${MAGNUM_DB_NAME} DEFAULT CHARACTER SET utf8;
-GRANT ALL PRIVILEGES ON ${MAGNUM_DB_NAME}.* TO
-    '${MAGNUM_DB_USER}'@'%' IDENTIFIED BY '${MAGNUM_DB_PASSWORD}'
-EOF
-
-/usr/bin/magnum-db-manage upgrade
-
-exec /usr/bin/magnum-conductor
diff --git a/docker/centos/binary/magnum/magnum-conductor/start.sh b/docker/centos/binary/magnum/magnum-conductor/start.sh
new file mode 120000
index 0000000000000000000000000000000000000000..6818630367bc573c35f6bbebb4031ccbd139695f
--- /dev/null
+++ b/docker/centos/binary/magnum/magnum-conductor/start.sh
@@ -0,0 +1 @@
+../../../../common/magnum/magnum-conductor/start.sh
\ No newline at end of file
diff --git a/docker/centos/binary/mariadb-app/config-mysql.sh b/docker/centos/binary/mariadb-app/config-mysql.sh
deleted file mode 100755
index b11939b8bbaccf0d040b18d4ef9b3af21dfa582a..0000000000000000000000000000000000000000
--- a/docker/centos/binary/mariadb-app/config-mysql.sh
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/bash
-
-. /opt/kolla/kolla-common.sh
-
-: ${BIND_ADDRESS:=$PUBLIC_IP}
-: ${DB_ROOT_PASSWORD:=$DB_ROOT_PASSWORD}
-: ${DEFAULT_STORAGE_ENGINE:=innodb}
-: ${COLLATION_SERVER:=utf8_general_ci}
-: ${INIT_CONNECT:=SET NAMES utf8}
-: ${CHAR_SET_SERVER:=utf8}
-: ${INNODB_FILE_PER_TABLE:=true}
-: ${DATADIR:=/var/lib/mysql}
-: ${TEMP_FILE:='/tmp/mysql-first-time.sql'}
-
-server_cnf=/etc/my.cnf.d/server.cnf
-
-crudini --set $server_cnf mysqld bind-address $BIND_ADDRESS
-crudini --set $server_cnf mysqld default-storage-engine $DEFAULT_STORAGE_ENGINE
-crudini --set $server_cnf mysqld collation-server $COLLATION_SERVER
-crudini --set $server_cnf mysqld init-connect "'${INIT_CONNECT}'"
-crudini --set $server_cnf mysqld character-set-server $CHAR_SET_SERVER
-if [ "${INNODB_FILE_PER_TABLE}" == "true" ] || ["${INNODB_FILE_PER_TABLE}" == "True" ] ; then
-    crudini --set $server_cnf mysqld innodb_file_per_table 1
-fi
diff --git a/docker/centos/binary/mariadb-app/config-mysql.sh b/docker/centos/binary/mariadb-app/config-mysql.sh
new file mode 120000
index 0000000000000000000000000000000000000000..17341e4151783cd944eaaa490d67800b2c36c49a
--- /dev/null
+++ b/docker/centos/binary/mariadb-app/config-mysql.sh
@@ -0,0 +1 @@
+../../../common/mariadb-app/config-mysql.sh
\ No newline at end of file
diff --git a/docker/centos/binary/neutron/neutron-agents/check-scripts/check-dhcp-agent.sh b/docker/centos/binary/neutron/neutron-agents/check-scripts/check-dhcp-agent.sh
deleted file mode 100755
index 7dda736efbc890074d58bead1d612667551f1b3c..0000000000000000000000000000000000000000
--- a/docker/centos/binary/neutron/neutron-agents/check-scripts/check-dhcp-agent.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/bash
-
-RES=0
-
-check=$(/usr/bin/neutron agent-list | awk '/ DHCP / {print $9}')
-error="ERROR: Neutron DHCP Agent is not alive."
-
-if [[ $check != ":-)" ]]; then
-    echo $error >&2
-    RES=1
-fi
-
-exit $RES
diff --git a/docker/centos/binary/neutron/neutron-agents/check-scripts/check-dhcp-agent.sh b/docker/centos/binary/neutron/neutron-agents/check-scripts/check-dhcp-agent.sh
new file mode 120000
index 0000000000000000000000000000000000000000..fcce4f251e32fffa32950a7f3a4288c49db5333e
--- /dev/null
+++ b/docker/centos/binary/neutron/neutron-agents/check-scripts/check-dhcp-agent.sh
@@ -0,0 +1 @@
+../../../../../common/neutron/neutron-agents/check-scripts/check-dhcp-agent.sh
\ No newline at end of file
diff --git a/docker/centos/binary/neutron/neutron-agents/check-scripts/check-l3-agent.sh b/docker/centos/binary/neutron/neutron-agents/check-scripts/check-l3-agent.sh
deleted file mode 100755
index d32c1e272f8d138a8f342f8204cb7476cdd4b6ba..0000000000000000000000000000000000000000
--- a/docker/centos/binary/neutron/neutron-agents/check-scripts/check-l3-agent.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/bash
-
-RES=0
-
-check=$(/usr/bin/neutron agent-list | awk '/ L3 / {print $9}')
-error="ERROR: Neutron L3 Agent is not alive."
-
-if [[ $check != ":-)" ]]; then
-    echo $error >&2
-    RES=1
-fi
-
-exit $RES
diff --git a/docker/centos/binary/neutron/neutron-agents/check-scripts/check-l3-agent.sh b/docker/centos/binary/neutron/neutron-agents/check-scripts/check-l3-agent.sh
new file mode 120000
index 0000000000000000000000000000000000000000..3975d06b633ebad538f603c17e58369af637fc1f
--- /dev/null
+++ b/docker/centos/binary/neutron/neutron-agents/check-scripts/check-l3-agent.sh
@@ -0,0 +1 @@
+../../../../../common/neutron/neutron-agents/check-scripts/check-l3-agent.sh
\ No newline at end of file
diff --git a/docker/centos/binary/neutron/neutron-agents/check-scripts/check-linuxbridge-agent.sh b/docker/centos/binary/neutron/neutron-agents/check-scripts/check-linuxbridge-agent.sh
deleted file mode 100755
index 4485fc1ec915bda80e5fa0cdf47cf7a23eb52a44..0000000000000000000000000000000000000000
--- a/docker/centos/binary/neutron/neutron-agents/check-scripts/check-linuxbridge-agent.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/bash
-
-RES=0
-
-check=$(/usr/bin/neutron agent-list | awk '/ Linux / {print $10}')
-error="ERROR: Neutron Linux Bridge agent is not alive."
-
-if [[ $check != ":-)" ]]; then
-    echo $error >&2
-    RES=1
-fi
-
-exit $RES
diff --git a/docker/centos/binary/neutron/neutron-agents/check-scripts/check-linuxbridge-agent.sh b/docker/centos/binary/neutron/neutron-agents/check-scripts/check-linuxbridge-agent.sh
new file mode 120000
index 0000000000000000000000000000000000000000..8f26a18febbe74f9dc402c078ed0d661c2217b09
--- /dev/null
+++ b/docker/centos/binary/neutron/neutron-agents/check-scripts/check-linuxbridge-agent.sh
@@ -0,0 +1 @@
+../../../../../common/neutron/neutron-agents/check-scripts/check-linuxbridge-agent.sh
\ No newline at end of file
diff --git a/docker/centos/binary/neutron/neutron-agents/check-scripts/check-metadata-agent.sh b/docker/centos/binary/neutron/neutron-agents/check-scripts/check-metadata-agent.sh
deleted file mode 100755
index fd1c6812b4c29190c12a6a5f4357a7a33cf321f1..0000000000000000000000000000000000000000
--- a/docker/centos/binary/neutron/neutron-agents/check-scripts/check-metadata-agent.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/bash
-
-RES=0
-
-check=$(/usr/bin/neutron agent-list | awk '/ Metadata / {print $9}')
-error="ERROR: Neutron Metadata Agent is not alive."
-
-if [[ $check != ":-)" ]]; then
-    echo $error >&2
-    RES=1
-fi
-
-exit $RES
diff --git a/docker/centos/binary/neutron/neutron-agents/check-scripts/check-metadata-agent.sh b/docker/centos/binary/neutron/neutron-agents/check-scripts/check-metadata-agent.sh
new file mode 120000
index 0000000000000000000000000000000000000000..aabb2a9eef1a61b70d21277e010ce71eb6a8df8b
--- /dev/null
+++ b/docker/centos/binary/neutron/neutron-agents/check-scripts/check-metadata-agent.sh
@@ -0,0 +1 @@
+../../../../../common/neutron/neutron-agents/check-scripts/check-metadata-agent.sh
\ No newline at end of file
diff --git a/docker/centos/binary/neutron/neutron-agents/config-scripts/config-dhcp-agent.sh b/docker/centos/binary/neutron/neutron-agents/config-scripts/config-dhcp-agent.sh
deleted file mode 100755
index db71678b1dc81882bb56cd312973cc6cdbd4dc4e..0000000000000000000000000000000000000000
--- a/docker/centos/binary/neutron/neutron-agents/config-scripts/config-dhcp-agent.sh
+++ /dev/null
@@ -1,88 +0,0 @@
-#!/bin/bash
-
-set -e
-
-. /opt/kolla/config-neutron.sh
-. /opt/kolla/config-sudoers.sh
-
-: ${DHCP_DRIVER:=neutron.agent.linux.dhcp.Dnsmasq}
-: ${USE_NAMESPACES:=true}
-: ${DELETE_NAMESPACES:=true}
-: ${DNSMASQ_CONFIG_FILE:=/etc/neutron/dnsmasq/dnsmasq-neutron.conf}
-: ${ROOT_HELPER:=sudo neutron-rootwrap /etc/neutron/rootwrap.conf}
-
-mkdir -p $(dirname $DNSMASQ_CONFIG_FILE)
-
-check_required_vars VERBOSE_LOGGING DEBUG_LOGGING MECHANISM_DRIVERS \
-                    DHCP_DRIVER USE_NAMESPACES DELETE_NAMESPACES \
-                    NEUTRON_LOG_DIR DNSMASQ_CONFIG_FILE \
-
-cfg=/etc/neutron/dhcp_agent.ini
-neutron_conf=/etc/neutron/neutron.conf
-
-# Workaround bug in dhclient in cirros images which does not correctly
-# handle setting checksums of packets when using hardware with checksum
-# offloading.  See:
-# https://www.rdoproject.org/forum/discussion/567/packstack-allinone-grizzly-cirros-image-cannot-get-a-dhcp-address-when-a-centos-image-can/p1
-
-/usr/sbin/iptables -A POSTROUTING -t mangle -p udp --dport bootpc \
-    -j CHECKSUM --checksum-fill
-
-if [[ ${MECHANISM_DRIVERS} =~ linuxbridge ]]; then
-    interface_driver="neutron.agent.linux.interface.BridgeInterfaceDriver"
-elif [[ ${MECHANISM_DRIVERS} == "openvswitch" ]]; then
-    interface_driver="neutron.agent.linux.interface.OVSInterfaceDriver"
-fi
-
-# Logging
-crudini --set $neutron_conf \
-    DEFAULT \
-    log_file \
-    "${NEUTRON_DHCP_AGENT_LOG_FILE}"
-
-# Configure dhcp_agent.ini
-crudini --set $cfg \
-    DEFAULT \
-    verbose \
-    "${VERBOSE_LOGGING}"
-crudini --set $cfg \
-    DEFAULT \
-    debug \
-    "${DEBUG_LOGGING}"
-crudini --set $cfg \
-    DEFAULT \
-    interface_driver \
-    "$interface_driver"
-crudini --set $cfg \
-    DEFAULT \
-    dhcp_driver \
-    "${DHCP_DRIVER}"
-crudini --set $cfg \
-    DEFAULT \
-    use_namespaces \
-    "${USE_NAMESPACES}"
-crudini --set $cfg \
-    DEFAULT \
-    delete_namespaces \
-    "${DELETE_NAMESPACES}"
-crudini --set $cfg \
-    DEFAULT \
-    dnsmasq_config_file \
-    "${DNSMASQ_CONFIG_FILE}"
-crudini --set $cfg \
-    DEFAULT \
-    root_helper \
-    "${ROOT_HELPER}"
-
-cat > ${DNSMASQ_CONFIG_FILE} <<EOF
-dhcp-option-force=26,1450
-log-facility=${NEUTRON_LOG_DIR}/neutron-dnsmasq.log
-EOF
-
-# Remove any existing qdhcp namespaces
-ip netns list | grep qdhcp | while read -r line ; do
-    ip netns delete $line
-done
-
-# Start DHCP Agent
-exec /usr/bin/neutron-dhcp-agent --config-file /etc/neutron/neutron.conf --config-file /etc/neutron/dhcp_agent.ini --config-dir /etc/neutron
diff --git a/docker/centos/binary/neutron/neutron-agents/config-scripts/config-dhcp-agent.sh b/docker/centos/binary/neutron/neutron-agents/config-scripts/config-dhcp-agent.sh
new file mode 120000
index 0000000000000000000000000000000000000000..8ef8dec068833c01f6efa3684cfdb470473baa56
--- /dev/null
+++ b/docker/centos/binary/neutron/neutron-agents/config-scripts/config-dhcp-agent.sh
@@ -0,0 +1 @@
+../../../../../common/neutron/neutron-agents/config-scripts/config-dhcp-agent.sh
\ No newline at end of file
diff --git a/docker/centos/binary/neutron/neutron-agents/config-scripts/config-l3-agent.sh b/docker/centos/binary/neutron/neutron-agents/config-scripts/config-l3-agent.sh
deleted file mode 100755
index 761d07685e946993c4f660ed79901063546d3696..0000000000000000000000000000000000000000
--- a/docker/centos/binary/neutron/neutron-agents/config-scripts/config-l3-agent.sh
+++ /dev/null
@@ -1,85 +0,0 @@
-#!/bin/bash
-
-set -e
-
-. /opt/kolla/config-neutron.sh
-. /opt/kolla/config-sudoers.sh
-
-: ${USE_NAMESPACES:=true}
-
-check_required_vars VERBOSE_LOGGING DEBUG_LOGGING
-
-cfg=/etc/neutron/l3_agent.ini
-neutron_conf=/etc/neutron/neutron.conf
-
-# Logging
-crudini --set $neutron_conf \
-    DEFAULT \
-    log_file \
-    "${NEUTRON_L3_AGENT_LOG_FILE}"
-
-# Configure l3_agent.ini
-crudini --set $cfg \
-    DEFAULT \
-    verbose \
-    "${VERBOSE_LOGGING}"
-crudini --set $cfg \
-    DEFAULT \
-    debug \
-    "${DEBUG_LOGGING}"
-if [[ "${MECHANISM_DRIVERS}" =~ linuxbridge ]] ; then
-    crudini --set $cfg \
-        DEFAULT \
-        interface_driver \
-        "neutron.agent.linux.interface.BridgeInterfaceDriver"
-    crudini --set $cfg \
-        DEFAULT \
-        gateway_external_network_id \
-        ""
-    crudini --set $cfg \
-        DEFAULT \
-        external_network_bridge \
-        ""
-elif [[ "${MECHANISM_DRIVERS}" =~ .*openvswitch* ]] ; then
-    crudini --set $cfg \
-        DEFAULT \
-        interface_driver \
-        "neutron.agent.linux.interface.OVSInterfaceDriver"
-    crudini --set $cfg \
-        DEFAULT \
-        gateway_external_network_id \
-        "${NEUTRON_FLAT_NETWORK_BRIDGE}"
-    crudini --set $cfg \
-        DEFAULT \
-        external_network_bridge \
-        "${NEUTRON_FLAT_NETWORK_BRIDGE}"
-fi
-
-crudini --set $cfg \
-    DEFAULT \
-    use_namespaces \
-    "${USE_NAMESPACES}"
-
-if [ "${USE_NAMESPACES}" == "false" ] ; then
-    source /openrc
-    # Create router if it does not exist
-    /usr/bin/neutron router-list | grep admin-router || /usr/bin/neutron router-create admin-router
-    # Set router-id
-    crudini --set $cfg \
-        DEFAULT \
-        router_id \
-        "$(/usr/bin/neutron router-list | awk '/ admin-router / {print $2}')"
-elif [ "${USE_NAMESPACES}" == "true" ] ; then
-    crudini --set $cfg \
-        DEFAULT \
-        router_delete_namespaces \
-        "true"
-fi
-
-# Remove any existing qrouter namespaces
-ip netns list | grep qrouter | while read -r line ; do
-    ip netns delete $line
-done
-
-# Start L3 Agent
-exec /usr/bin/neutron-l3-agent --config-file /etc/neutron/neutron.conf --config-file /etc/neutron/l3_agent.ini --config-file /etc/neutron/fwaas_driver.ini --config-dir /etc/neutron
diff --git a/docker/centos/binary/neutron/neutron-agents/config-scripts/config-l3-agent.sh b/docker/centos/binary/neutron/neutron-agents/config-scripts/config-l3-agent.sh
new file mode 120000
index 0000000000000000000000000000000000000000..d92fe01ecf802dc7b3ceab6a59bc5475593d0a8f
--- /dev/null
+++ b/docker/centos/binary/neutron/neutron-agents/config-scripts/config-l3-agent.sh
@@ -0,0 +1 @@
+../../../../../common/neutron/neutron-agents/config-scripts/config-l3-agent.sh
\ No newline at end of file
diff --git a/docker/centos/binary/neutron/neutron-agents/config-scripts/config-linuxbridge-agent.sh b/docker/centos/binary/neutron/neutron-agents/config-scripts/config-linuxbridge-agent.sh
deleted file mode 100755
index bd8f90194be4f04ef98c81ae1974adf10c94e877..0000000000000000000000000000000000000000
--- a/docker/centos/binary/neutron/neutron-agents/config-scripts/config-linuxbridge-agent.sh
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/bin/bash
-
-set -e
-
-. /opt/kolla/config-neutron.sh
-. /opt/kolla/config-sudoers.sh
-
-: ${NEUTRON_FLAT_NETWORK_NAME:=physnet1}
-: ${NEUTRON_FLAT_NETWORK_INTERFACE:=eth1}
-
-check_required_vars PUBLIC_IP NEUTRON_FLAT_NETWORK_NAME \
-                    NEUTRON_FLAT_NETWORK_INTERFACE
-
-cfg=/etc/neutron/plugins/ml2/ml2_conf.ini
-
-# Configure ml2_conf.ini
-if [[ ${TYPE_DRIVERS} =~ vxlan ]]; then
-    crudini --set $cfg \
-        vxlan \
-        local_ip \
-        "${PUBLIC_IP}"
-fi
-
-crudini --set $cfg \
-    linux_bridge \
-    physical_interface_mappings \
-    "${NEUTRON_FLAT_NETWORK_NAME}:${NEUTRON_FLAT_NETWORK_INTERFACE}"
-
-exec /usr/bin/neutron-linuxbridge-agent --config-file /etc/neutron/neutron.conf --config-file /etc/neutron/plugins/ml2/ml2_conf.ini --config-dir /etc/neutron
diff --git a/docker/centos/binary/neutron/neutron-agents/config-scripts/config-linuxbridge-agent.sh b/docker/centos/binary/neutron/neutron-agents/config-scripts/config-linuxbridge-agent.sh
new file mode 120000
index 0000000000000000000000000000000000000000..0736ca3caeb61b254f4e2268ad45fa355abb97be
--- /dev/null
+++ b/docker/centos/binary/neutron/neutron-agents/config-scripts/config-linuxbridge-agent.sh
@@ -0,0 +1 @@
+../../../../../common/neutron/neutron-agents/config-scripts/config-linuxbridge-agent.sh
\ No newline at end of file
diff --git a/docker/centos/binary/neutron/neutron-agents/config-scripts/config-metadata-agent.sh b/docker/centos/binary/neutron/neutron-agents/config-scripts/config-metadata-agent.sh
deleted file mode 100755
index d1eef341c11141cb4cd4cbc5831004451e740b07..0000000000000000000000000000000000000000
--- a/docker/centos/binary/neutron/neutron-agents/config-scripts/config-metadata-agent.sh
+++ /dev/null
@@ -1,74 +0,0 @@
-#!/bin/bash
-
-set -e
-
-. /opt/kolla/config-neutron.sh
-. /opt/kolla/config-sudoers.sh
-
-: ${KEYSTONE_REGION:=RegionOne}
-: ${ENDPOINT_TYPE:=adminURL}
-: ${NEUTRON_SHARED_SECRET:=sharedsecret}
-
-check_required_vars VERBOSE_LOGGING DEBUG_LOGGING KEYSTONE_AUTH_PROTOCOL \
-                    KEYSTONE_PUBLIC_SERVICE_HOST ADMIN_TENANT_NAME \
-                    NEUTRON_KEYSTONE_USER NEUTRON_KEYSTONE_PASSWORD \
-                    NEUTRON_SHARED_SECRET NOVA_METADATA_API_SERVICE_HOST \
-                    NOVA_METADATA_API_SERVICE_PORT
-
-cfg=/etc/neutron/metadata_agent.ini
-neutron_conf=/etc/neutron/neutron.conf
-
-# Logging
-crudini --set $neutron_conf \
-        DEFAULT \
-        log_file \
-        "${NEUTRON_METADATA_AGENT_LOG_FILE}"
-
-# Configure metadata_agent.ini
-crudini --set $cfg \
-        DEFAULT \
-        verbose \
-        "${VERBOSE_LOGGING}"
-crudini --set $cfg \
-        DEFAULT \
-        debug \
-        "${DEBUG_LOGGING}"
-crudini --set $cfg \
-        DEFAULT \
-        auth_region \
-        "${KEYSTONE_REGION}"
-crudini --set $cfg \
-        DEFAULT \
-        endpoint_type \
-        "${ENDPOINT_TYPE}"
-crudini --set $cfg \
-        DEFAULT \
-        auth_url \
-        "${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_PUBLIC_SERVICE_HOST}:${KEYSTONE_PUBLIC_SERVICE_PORT}/v2.0"
-crudini --set $cfg \
-        DEFAULT \
-        admin_tenant_name \
-        "${ADMIN_TENANT_NAME}"
-crudini --set $cfg \
-        DEFAULT \
-        admin_user \
-        "${NEUTRON_KEYSTONE_USER}"
-crudini --set $cfg \
-        DEFAULT \
-        admin_password \
-        "${NEUTRON_KEYSTONE_PASSWORD}"
-crudini --set $cfg \
-        DEFAULT \
-        nova_metadata_ip \
-        "${NOVA_METADATA_API_SERVICE_HOST}"
-crudini --set $cfg \
-        DEFAULT \
-        nova_metadata_port \
-        "${NOVA_METADATA_API_SERVICE_PORT}"
-crudini --set $cfg \
-        DEFAULT \
-        metadata_proxy_shared_secret \
-        "${NEUTRON_SHARED_SECRET}"
-
-# Start Metadata Agent
-exec /usr/bin/neutron-metadata-agent --config-file /etc/neutron/neutron.conf --config-file /etc/neutron/metadata_agent.ini --config-dir /etc/neutron
diff --git a/docker/centos/binary/neutron/neutron-agents/config-scripts/config-metadata-agent.sh b/docker/centos/binary/neutron/neutron-agents/config-scripts/config-metadata-agent.sh
new file mode 120000
index 0000000000000000000000000000000000000000..7e9c1b299ed84875b6c82384585b9f771331e96a
--- /dev/null
+++ b/docker/centos/binary/neutron/neutron-agents/config-scripts/config-metadata-agent.sh
@@ -0,0 +1 @@
+../../../../../common/neutron/neutron-agents/config-scripts/config-metadata-agent.sh
\ No newline at end of file
diff --git a/docker/centos/binary/neutron/neutron-agents/config-scripts/config-sudoers.sh b/docker/centos/binary/neutron/neutron-agents/config-scripts/config-sudoers.sh
deleted file mode 100755
index 0e02226db80b73838863bb80119b59a4d5c11d27..0000000000000000000000000000000000000000
--- a/docker/centos/binary/neutron/neutron-agents/config-scripts/config-sudoers.sh
+++ /dev/null
@@ -1,12 +0,0 @@
-#!/bin/bash
-
-# Neutron uses rootwrap which requires a tty for sudo.
-# Since the container is running in daemon mode, a tty
-# is not present and requiretty must be commented out.
-if [ ! -f /var/run/sudo-modified ]; then
-    chmod 0640 /etc/sudoers
-    sed -i '/Defaults    requiretty/s/^/#/' /etc/sudoers
-    chmod 0440 /etc/sudoers
-fi
-
-touch /var/run/sudo-modified
diff --git a/docker/centos/binary/neutron/neutron-agents/config-scripts/config-sudoers.sh b/docker/centos/binary/neutron/neutron-agents/config-scripts/config-sudoers.sh
new file mode 120000
index 0000000000000000000000000000000000000000..3ecc0c8235672eb4e29db5279710256bb5986673
--- /dev/null
+++ b/docker/centos/binary/neutron/neutron-agents/config-scripts/config-sudoers.sh
@@ -0,0 +1 @@
+../../../../../common/neutron/neutron-agents/config-scripts/config-sudoers.sh
\ No newline at end of file
diff --git a/docker/centos/binary/neutron/neutron-agents/fwaas_driver.ini b/docker/centos/binary/neutron/neutron-agents/fwaas_driver.ini
deleted file mode 100644
index 41f761abf1a7f12650badb5c2c92f03da1b08892..0000000000000000000000000000000000000000
--- a/docker/centos/binary/neutron/neutron-agents/fwaas_driver.ini
+++ /dev/null
@@ -1,3 +0,0 @@
-[fwaas]
-#driver = neutron.services.firewall.drivers.linux.iptables_fwaas.IptablesFwaasDriver
-#enabled = True
diff --git a/docker/centos/binary/neutron/neutron-agents/fwaas_driver.ini b/docker/centos/binary/neutron/neutron-agents/fwaas_driver.ini
new file mode 120000
index 0000000000000000000000000000000000000000..84e47b1c26bbe685017d8f780d7232911de12b74
--- /dev/null
+++ b/docker/centos/binary/neutron/neutron-agents/fwaas_driver.ini
@@ -0,0 +1 @@
+../../../../common/neutron/neutron-agents/fwaas_driver.ini
\ No newline at end of file
diff --git a/docker/centos/binary/neutron/neutron-agents/supervisord.conf b/docker/centos/binary/neutron/neutron-agents/supervisord.conf
deleted file mode 100644
index 7455cb3d7e652bb416909a757548b5e1735190b1..0000000000000000000000000000000000000000
--- a/docker/centos/binary/neutron/neutron-agents/supervisord.conf
+++ /dev/null
@@ -1,53 +0,0 @@
-[unix_http_server]
-file = /var/run/supervisor.sock
-
-[inet_http_server]
-port = 127.0.0.1:9001
-
-[supervisord]
-nodaemon=true
-logfile = /var/log/supervisor/supervisord.log
-logfile_maxbytes = 200KB
-logfile_backups = 1
-pidfile = /var/run/supervisord.pid
-childlogdir = /var/log/supervisor
-
-[rpcinterface:supervisor]
-supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
-
-[supervisorctl]
-serverurl = unix:///var/run/supervisor.sock
-
-[program:neutron-linuxbridge-agent]
-command=/opt/kolla/neutron/config-linuxbridge-agent.sh
-priority=30
-startsec=10
-stderr_events_enabled=true
-stdout_events_enabled=true
-
-[program:neutron-dhcp-agent]
-command=/opt/kolla/neutron/config-dhcp-agent.sh
-priority=40
-startsec=10
-stderr_events_enabled=true
-stdout_events_enabled=true
-
-[program:neutron-metadata-agent]
-command=/opt/kolla/neutron/config-metadata-agent.sh
-priority=40 
-startsec=10
-stderr_events_enabled=true
-stdout_events_enabled=true
-
-[program:neutron-l3-agent]
-command=/opt/kolla/neutron/config-l3-agent.sh
-priority=40
-startsec=10
-stderr_events_enabled=true
-stdout_events_enabled=true
-
-[eventlistener:stdout]
-command = supervisor_stdout
-buffer_size = 100
-events = PROCESS_LOG
-result_handler = supervisor_stdout:event_handler
diff --git a/docker/centos/binary/neutron/neutron-agents/supervisord.conf b/docker/centos/binary/neutron/neutron-agents/supervisord.conf
new file mode 120000
index 0000000000000000000000000000000000000000..a7f24cb777691c1ba8a46fecb5330b6de1f5c545
--- /dev/null
+++ b/docker/centos/binary/neutron/neutron-agents/supervisord.conf
@@ -0,0 +1 @@
+../../../../common/neutron/neutron-agents/supervisord.conf
\ No newline at end of file
diff --git a/docker/centos/binary/neutron/neutron-base/config-neutron.sh b/docker/centos/binary/neutron/neutron-base/config-neutron.sh
deleted file mode 100644
index 0155651052aa75edd3854456d80268835ea070d4..0000000000000000000000000000000000000000
--- a/docker/centos/binary/neutron/neutron-base/config-neutron.sh
+++ /dev/null
@@ -1,210 +0,0 @@
-#!/bin/bash
-
-set -e
-
-. /opt/kolla/kolla-common.sh
-
-# Database
-: ${NEUTRON_DB_NAME:=neutron}
-: ${NEUTRON_DB_USER:=neutron}
-: ${NEUTRON_DB_PASSWORD:=password}
-# Keystone
-: ${ADMIN_TENANT_NAME:=admin}
-: ${NEUTRON_KEYSTONE_USER:=neutron}
-: ${NEUTRON_KEYSTONE_PASSWORD:=password}
-: ${KEYSTONE_AUTH_PROTOCOL:=http}
-: ${KEYSTONE_ADMIN_SERVICE_HOST:=127.0.0.1}
-: ${KEYSTONE_PUBLIC_SERVICE_HOST:=127.0.0.1}
-: ${KEYSTONE_ADMIN_SERVICE_PORT:=35357}
-: ${KEYSTONE_PUBLIC_SERVICE_PORT:=5000}
-: ${KEYSTONE_REGION:=RegionOne}
-# RabbitMQ
-: ${RABBIT_HOST:=$RABBITMQ_SERVICE_HOST}
-: ${RABBIT_USER:=guest}
-: ${RABBIT_PASSWORD:=guest}
-# Logging
-: ${VERBOSE_LOGGING:=true}
-: ${DEBUG_LOGGING:=false}
-# Networking
-: ${NEUTRON_FLAT_NETWORK_NAME:=physnet1}
-# Paste configuration file
-: ${API_PASTE_CONFIG:=/usr/share/neutron/api-paste.ini}
-
-check_required_vars NEUTRON_KEYSTONE_PASSWORD NEUTRON_API_PASTE_CONFIG \
-                    KEYSTONE_PUBLIC_SERVICE_HOST RABBITMQ_SERVICE_HOST
-
-core_cfg=/etc/neutron/neutron.conf
-ml2_cfg=/etc/neutron/plugins/ml2/ml2_conf.ini
-
-# Logging
-crudini --set $core_cfg \
-        DEFAULT \
-        log_dir \
-        "${NEUTRON_LOG_DIR}"
-crudini --set $core_cfg \
-        DEFAULT \
-        verbose \
-        "${VERBOSE_LOGGING}"
-crudini --set $core_cfg \
-        DEFAULT \
-        debug \
-        "${DEBUG_LOGGING}"
-
-# Paste config
-crudini --set $core_cfg \
-        DEFAULT \
-        api_paste_config \
-        "${NEUTRON_API_PASTE_CONFIG}"
-
-# Rabbit
-crudini --set $core_cfg \
-        DEFAULT \
-        rabbit_host \
-        "${RABBIT_HOST}"
-crudini --set $core_cfg \
-        DEFAULT \
-        rabbit_userid \
-        "${RABBIT_USER}"
-crudini --set $core_cfg \
-        DEFAULT \
-        rabbit_password \
-        "${RABBIT_PASSWORD}"
-
-# Locking
-crudini --set $core_cfg \
-        DEFAULT \
-        lock_path \
-        "/var/lock/neutron"
-
-# Keystone
-crudini --set $core_cfg \
-        DEFAULT \
-        auth_strategy \
-        "keystone"
-crudini --set $core_cfg \
-        keystone_authtoken \
-        auth_uri \
-        "${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_PUBLIC_SERVICE_HOST}:${KEYSTONE_PUBLIC_SERVICE_PORT}/v2.0"
-crudini --set $core_cfg \
-        keystone_authtoken \
-        identity_uri \
-        "${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}"
-crudini --set $core_cfg \
-        keystone_authtoken \
-        admin_tenant_name \
-        "${ADMIN_TENANT_NAME}"
-crudini --set $core_cfg \
-        keystone_authtoken \
-        admin_user \
-        "${NEUTRON_KEYSTONE_USER}"
-crudini --set $core_cfg \
-        keystone_authtoken \
-        admin_password \
-        "${NEUTRON_KEYSTONE_PASSWORD}"
-
-# Rootwrap
-crudini --set $core_cfg \
-        agent \
-        root_helper \
-        "sudo neutron-rootwrap /etc/neutron/rootwrap.conf"
-
-# neutron.conf ml2 configuration
-crudini --set $core_cfg \
-        DEFAULT \
-        core_plugin \
-        "neutron.plugins.ml2.plugin.Ml2Plugin"
-crudini --set $core_cfg \
-        DEFAULT \
-        service_plugins \
-        "neutron.services.l3_router.l3_router_plugin.L3RouterPlugin"
-crudini --set $core_cfg \
-        DEFAULT \
-        allow_overlapping_ips \
-        "True"
-
-# Configure ml2_conf.ini
-crudini --set $ml2_cfg \
-        ml2 \
-        type_drivers \
-        "${TYPE_DRIVERS}"
-crudini --set $ml2_cfg \
-        ml2 \
-        tenant_network_types \
-        "${TENANT_NETWORK_TYPES}"
-crudini --set $ml2_cfg \
-        ml2 \
-        mechanism_drivers \
-        "${MECHANISM_DRIVERS}"
-
-if [[ ${TYPE_DRIVERS} =~ .*flat.* ]]; then
-    crudini --set $ml2_cfg \
-        ml2_type_flat \
-        flat_networks \
-        ${NEUTRON_FLAT_NETWORK_NAME}
-fi
-
-if [[ ${TYPE_DRIVERS} =~ .*vxlan.* ]]; then
-    crudini --set $ml2_cfg \
-        ml2_type_vxlan \
-        vxlan_group \
-        ""
-    crudini --set $ml2_cfg \
-        ml2_type_vxlan \
-        vni_ranges \
-        "1:1000"
-    crudini --set $ml2_cfg \
-        vxlan \
-        enable_vxlan \
-        "True"
-    crudini --set $ml2_cfg \
-        vxlan \
-        vxlan_group \
-        ""
-    crudini --set $ml2_cfg \
-        vxlan \
-        l2_population \
-        "True"
-    crudini --set $ml2_cfg \
-        agent \
-        tunnel_types \
-        "vxlan"
-    crudini --set $ml2_cfg \
-        agent \
-        vxlan_udp_port \
-        "4789"
-    crudini --set $core_cfg \
-        DEFAULT \
-        network_device_mtu \
-        "1450"
-fi
-
-crudini --set $ml2_cfg \
-    l2pop \
-    agent_boot_time \
-    "180"
-crudini --set $ml2_cfg \
-    securitygroup \
-    enable_security_group \
-    "True"
-crudini --set $ml2_cfg \
-    securitygroup \
-    enable_ipset \
-    "True"
-
-if [[ ${MECHANISM_DRIVERS} =~ linuxbridge ]]; then
-    firewall_driver="neutron.agent.linux.iptables_firewall.IptablesFirewallDriver"
-elif [[ ${MECHANISM_DRIVERS} == "openvswitch" ]]; then
-    firewall_driver="neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver"
-fi
-
-crudini --set $ml2_cfg \
-    securitygroup \
-    firewall_driver \
-    "$firewall_driver"
-
-cat > /openrc <<EOF
-export OS_AUTH_URL="http://${KEYSTONE_PUBLIC_SERVICE_HOST}:${KEYSTONE_PUBLIC_SERVICE_PORT}/v2.0"
-export OS_USERNAME="${NEUTRON_KEYSTONE_USER}"
-export OS_PASSWORD="${NEUTRON_KEYSTONE_PASSWORD}"
-export OS_TENANT_NAME="${ADMIN_TENANT_NAME}"
-EOF
diff --git a/docker/centos/binary/neutron/neutron-base/config-neutron.sh b/docker/centos/binary/neutron/neutron-base/config-neutron.sh
new file mode 120000
index 0000000000000000000000000000000000000000..0de59812307a0680d549b75cba3dfd2bdbff79dc
--- /dev/null
+++ b/docker/centos/binary/neutron/neutron-base/config-neutron.sh
@@ -0,0 +1 @@
+../../../../common/neutron/neutron-base/config-neutron.sh
\ No newline at end of file
diff --git a/docker/centos/binary/neutron/neutron-server/check.sh b/docker/centos/binary/neutron/neutron-server/check.sh
deleted file mode 100755
index 4e9aa623c60bbdd43ce2622e1ab930102d0ce9af..0000000000000000000000000000000000000000
--- a/docker/centos/binary/neutron/neutron-server/check.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-
-RES=0
-
-. /openrc
-if ! keystone token-get > /dev/null; then
-    echo "ERROR: keystone token-get failed" >&2
-    RES=1
-else
-    if ! neutron ext-list > /dev/null; then
-        echo "ERROR: neutron ext-list failed" >&2
-        RES=1
-    fi
-fi
-
-exit $RES
-
diff --git a/docker/centos/binary/neutron/neutron-server/check.sh b/docker/centos/binary/neutron/neutron-server/check.sh
new file mode 120000
index 0000000000000000000000000000000000000000..00193661632e7bd5ab509ba575eae0aba8986936
--- /dev/null
+++ b/docker/centos/binary/neutron/neutron-server/check.sh
@@ -0,0 +1 @@
+../../../../common/neutron/neutron-server/check.sh
\ No newline at end of file
diff --git a/docker/centos/binary/neutron/neutron-server/start.sh b/docker/centos/binary/neutron/neutron-server/start.sh
deleted file mode 100755
index fb971083f583422f5f1e21b57ad259098f969f74..0000000000000000000000000000000000000000
--- a/docker/centos/binary/neutron/neutron-server/start.sh
+++ /dev/null
@@ -1,98 +0,0 @@
-#!/bin/bash
-
-set -e
-
-. /opt/kolla/config-neutron.sh
-
-: ${NEUTRON_FLAT_NETWORK_NAME:=physnet1}
-: ${NEUTRON_FLAT_NETWORK_INTERFACE:=eth1}
-
-check_required_vars KEYSTONE_ADMIN_TOKEN KEYSTONE_ADMIN_SERVICE_HOST \
-                    KEYSTONE_AUTH_PROTOCOL NOVA_API_SERVICE_HOST \
-                    NOVA_KEYSTONE_USER NOVA_KEYSTONE_PASSWORD \
-                    NEUTRON_DB_NAME NEUTRON_DB_USER NEUTRON_DB_PASSWORD \
-                    NEUTRON_KEYSTONE_USER NEUTRON_KEYSTONE_PASSWORD \
-                    ADMIN_TENANT_NAME NEUTRON_SERVER_SERVICE_HOST \
-                    PUBLIC_IP NEUTRON_DB_PASSWORD
-fail_unless_os_service_running keystone
-fail_unless_db
-
-mysql -h ${MARIADB_SERVICE_HOST} -u root -p${DB_ROOT_PASSWORD} mysql <<EOF
-CREATE DATABASE IF NOT EXISTS ${NEUTRON_DB_NAME} DEFAULT CHARACTER SET utf8;
-GRANT ALL PRIVILEGES ON ${NEUTRON_DB_NAME}.* TO
-       '${NEUTRON_DB_USER}'@'%' IDENTIFIED BY '${NEUTRON_DB_PASSWORD}'
-
-EOF
-
-export SERVICE_TOKEN="${KEYSTONE_ADMIN_TOKEN}"
-export SERVICE_ENDPOINT="${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}/v2.0"
-
-# Configure Keystone Service Catalog
-crux user-create -n "${NEUTRON_KEYSTONE_USER}" \
-    -p "${NEUTRON_KEYSTONE_PASSWORD}" \
-    -t "${ADMIN_TENANT_NAME}" \
-    -r admin
-
-crux endpoint-create -n neutron -t network \
-    -I "${KEYSTONE_AUTH_PROTOCOL}://${NEUTRON_SERVER_SERVICE_HOST}:${NEUTRON_SERVER_SERVICE_PORT}" \
-    -P "${KEYSTONE_AUTH_PROTOCOL}://${NEUTRON_SERVER_SERVICE_HOST}:${NEUTRON_SERVER_SERVICE_PORT}" \
-    -A "${KEYSTONE_AUTH_PROTOCOL}://${NEUTRON_SERVER_SERVICE_HOST}:${NEUTRON_SERVER_SERVICE_PORT}"
-
-core_cfg=/etc/neutron/neutron.conf
-ml2_cfg=/etc/neutron/plugins/ml2/ml2_conf.ini
-
-# Logging
-crudini --set /etc/neutron/neutron.conf \
-        DEFAULT \
-        log_file \
-        "${NEUTRON_SERVER_LOG_FILE}"
-
-# Database
-crudini --set $core_cfg \
-        database \
-        connection \
-        "mysql://${NEUTRON_DB_USER}:${NEUTRON_DB_PASSWORD}@${MARIADB_SERVICE_HOST}/${NEUTRON_DB_NAME}"
-# Nova
-crudini --set $core_cfg \
-        DEFAULT \
-        notify_nova_on_port_status_changes \
-        "True"
-crudini --set $core_cfg \
-        DEFAULT \
-        notify_nova_on_port_data_changes \
-        "True"
-crudini --set $core_cfg \
-        DEFAULT \
-        nova_url \
-        "http://${NOVA_API_SERVICE_HOST}:${NOVA_API_SERVICE_PORT}/v2"
-crudini --set $core_cfg \
-        DEFAULT \
-        nova_admin_auth_url \
-        "${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}/v2.0"
-crudini --set $core_cfg \
-        DEFAULT \
-        nova_region_name \
-        "${KEYSTONE_REGION}"
-crudini --set $core_cfg \
-        DEFAULT \
-        nova_admin_username \
-        "${NOVA_KEYSTONE_USER}"
-crudini --set $core_cfg \
-        DEFAULT \
-        nova_admin_tenant_id \
-        "$(keystone tenant-list | grep $ADMIN_TENANT_NAME | awk '{print $2;}')"
-crudini --set $core_cfg \
-        DEFAULT \
-        nova_admin_password \
-        "${NOVA_KEYSTONE_PASSWORD}"
-
-if [[ ${MECHANISM_DRIVERS} =~ linuxbridge ]]; then
-    crudini --set $ml2_cfg \
-        linux_bridge \
-        physical_interface_mappings \
-        "${NEUTRON_FLAT_NETWORK_NAME}:${NEUTRON_FLAT_NETWORK_INTERFACE}"
-fi
-
-su -s /bin/bash -c "neutron-db-manage --config-file /etc/neutron/neutron.conf --config-file /etc/neutron/plugins/ml2/ml2_conf.ini upgrade head" neutron
-
-exec /usr/bin/neutron-server --config-file /etc/neutron/neutron.conf --config-file /etc/neutron/plugins/ml2/ml2_conf.ini
diff --git a/docker/centos/binary/neutron/neutron-server/start.sh b/docker/centos/binary/neutron/neutron-server/start.sh
new file mode 120000
index 0000000000000000000000000000000000000000..a11ea7703f47bcc998e91cfee582ce6cbff39255
--- /dev/null
+++ b/docker/centos/binary/neutron/neutron-server/start.sh
@@ -0,0 +1 @@
+../../../../common/neutron/neutron-server/start.sh
\ No newline at end of file
diff --git a/docker/centos/binary/nova-base/config-nova.sh b/docker/centos/binary/nova-base/config-nova.sh
deleted file mode 100755
index 8789a14a54e0ba02386fb90b0843ad34d2f900c5..0000000000000000000000000000000000000000
--- a/docker/centos/binary/nova-base/config-nova.sh
+++ /dev/null
@@ -1,137 +0,0 @@
-#!/bin/bash
-
-. /opt/kolla/kolla-common.sh
-
-: ${NOVA_DB_USER:=nova}
-: ${NOVA_DB_NAME:=nova}
-: ${NOVA_KEYSTONE_USER:=admin}
-: ${NOVA_KEYSTONE_PASSWORD:=kolla}
-: ${ADMIN_TENANT_NAME:=admin}
-: ${RABBIT_USERID:=guest}
-: ${RABBIT_PASSWORD:=guest}
-: ${NETWORK_MANAGER:=nova}
-: ${FLAT_NETWORK:=eth1}
-: ${PUBLIC_NETWORK:=eth0}
-: ${ENABLED_APIS:=ec2,osapi_compute,metadata}
-: ${METADATA_HOST:=$PUBLIC_IP}
-: ${NEUTRON_SHARED_SECRET:=sharedsecret}
-
-check_required_vars KEYSTONE_ADMIN_TOKEN NOVA_DB_PASSWORD \
-                    RABBITMQ_SERVICE_HOST GLANCE_API_SERVICE_HOST \
-                    KEYSTONE_PUBLIC_SERVICE_HOST PUBLIC_IP \
-                    PUBLIC_INTERFACE FLAT_INTERFACE DEBUG_LOGGING \
-                    VERBOSE_LOGGING
-
-cfg=/etc/nova/nova.conf
-
-crudini --set $cfg DEFAULT amqp_durable_queues False
-crudini --set $cfg DEFAULT rabbit_host ${RABBITMQ_SERVICE_HOST}
-crudini --set $cfg DEFAULT rabbit_port 5672
-crudini --set $cfg DEFAULT rabbit_hosts ${RABBITMQ_SERVICE_HOST}:5672
-crudini --set $cfg DEFAULT rabbit_use_ssl False
-crudini --set $cfg DEFAULT rabbit_userid ${RABBIT_USERID}
-crudini --set $cfg DEFAULT rabbit_password "${RABBIT_PASSWORD}"
-crudini --set $cfg DEFAULT rabbit_virtual_host /
-crudini --set $cfg DEFAULT rabbit_ha_queues False
-crudini --set $cfg DEFAULT rpc_backend nova.openstack.common.rpc.impl_kombu
-crudini --set $cfg DEFAULT enabled_apis ${ENABLED_APIS}
-crudini --set $cfg DEFAULT ec2_listen 0.0.0.0
-crudini --set $cfg DEFAULT osapi_compute_listen 0.0.0.0
-crudini --set $cfg DEFAULT osapi_compute_workers 8
-crudini --set $cfg DEFAULT metadata_host ${METADATA_HOST}
-crudini --set $cfg DEFAULT metadata_listen 0.0.0.0
-crudini --set $cfg DEFAULT metadata_workers 8
-crudini --set $cfg DEFAULT service_down_time 60
-crudini --set $cfg DEFAULT rootwrap_config /etc/nova/rootwrap.conf
-crudini --set $cfg DEFAULT auth_strategy keystone
-crudini --set $cfg DEFAULT use_forwarded_for False
-crudini --set $cfg DEFAULT glance_api_servers ${GLANCE_API_SERVICE_HOST}:9292
-crudini --set $cfg DEFAULT cpu_allocation_ratio 16.0
-crudini --set $cfg DEFAULT ram_allocation_ratio 1.5
-crudini --set $cfg DEFAULT scheduler_default_filters RetryFilter,AvailabilityZoneFilter,RamFilter,ComputeFilter,ComputeCapabilitiesFilter,ImagePropertiesFilter,CoreFilter
-crudini --set $cfg DEFAULT compute_driver nova.virt.libvirt.LibvirtDriver
-crudini --set $cfg DEFAULT vif_plugging_is_fatal True
-crudini --set $cfg DEFAULT vif_plugging_timeout 300
-crudini --set $cfg DEFAULT volume_api_class nova.volume.cinder.API
-crudini --set $cfg DEFAULT image_service nova.image.glance.GlanceImageService
-crudini --set $cfg DEFAULT osapi_volume_listen 0.0.0.0
-crudini --set $cfg DEFAULT instances_path /var/lib/nova/instances
-crudini --set $cfg DEFAULT lock_path /var/lib/nova/lock
-
-# This is not created by openstack-nova packaging
-mkdir -p /var/lib/nova/lock
-
-# configure logging
-crudini --set $cfg DEFAULT log_dir "${NOVA_LOG_DIR}"
-crudini --set $cfg DEFAULT debug "${DEBUG_LOGGING}"
-crudini --set $cfg DEFAULT verbose "${VERBOSE_LOGGING}"
-
-crudini --set $cfg DEFAULT admin_token "${KEYSTONE_ADMIN_TOKEN}"
-
-crudini --set $cfg conductor workers 8
-
-if [ "${NETWORK_MANAGER}" == "nova" ] ; then
-    crudini --set $cfg DEFAULT network_manager nova.network.manager.FlatDHCPManager
-    crudini --set $cfg DEFAULT firewall_driver nova.virt.libvirt.firewall.IptablesFirewallDriver
-    crudini --set $cfg DEFAULT network_size 254
-    crudini --set $cfg DEFAULT allow_same_net_traffic False
-    crudini --set $cfg DEFAULT multi_host True
-    crudini --set $cfg DEFAULT send_arp_for_ha True
-    crudini --set $cfg DEFAULT share_dhcp_address True
-    crudini --set $cfg DEFAULT force_dhcp_release True
-    crudini --set $cfg DEFAULT flat_interface $FLAT_INTERFACE
-    crudini --set $cfg DEFAULT flat_network_bridge br100
-    crudini --set $cfg DEFAULT public_interface $PUBLIC_INTERFACE
-elif [ "${NETWORK_MANAGER}" == "neutron" ] ; then
-    check_required_vars NEUTRON_SHARED_SECRET
-    crudini --set $cfg neutron service_metadata_proxy True
-    crudini --set $cfg neutron metadata_proxy_shared_secret ${NEUTRON_SHARED_SECRET}
-    crudini --set $cfg DEFAULT neutron_default_tenant_id default
-    crudini --set $cfg DEFAULT network_api_class nova.network.neutronv2.api.API
-    crudini --set $cfg DEFAULT security_group_api neutron
-    if [[ "${MECHANISM_DRIVERS}" =~ linuxbridge ]] ; then
-        crudini --set $cfg DEFAULT linuxnet_interface_driver nova.network.linux_net.NeutronLinuxBridgeInterfaceDriver
-    elif [[ "${MECHANISM_DRIVERS}" =~ openvswitch ]] ; then
-        crudini --set $cfg DEFAULT linuxnet_interface_driver nova.network.linux_net.LinuxOVSInterfaceDriver
-    fi
-    crudini --set $cfg DEFAULT libvirt_vif_driver nova.virt.libvirt.vif.LibvirtGenericVIFDriver
-    crudini --set $cfg DEFAULT firewall_driver nova.virt.firewall.NoopFirewallDriver
-    crudini --set $cfg neutron url http://${NEUTRON_SERVER_SERVICE_HOST}:${NEUTRON_SERVER_SERVICE_PORT}
-    crudini --set $cfg neutron auth_strategy keystone
-    crudini --set $cfg neutron admin_auth_url ${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}/v2.0
-    crudini --set $cfg neutron admin_tenant_name ${ADMIN_TENANT_NAME}
-    crudini --set $cfg neutron admin_username ${NEUTRON_KEYSTONE_USER}
-    crudini --set $cfg neutron admin_password ${NEUTRON_KEYSTONE_PASSWORD}
-else
-    echo "Incorrect NETWORK_MANAGER ${NETWORK_MANAGER}. Supported options are nova and neutron."
-    exit 1
-fi
-
-# disabled pending answers to http://lists.openstack.org/pipermail/openstack/2014-October/009997.html
-#for option in auth_protocol auth_host auth_port; do
-#    crudini --del $cfg \
-#        keystone_authtoken \
-#        $option
-#done
-
-crudini --set $cfg keystone_authtoken auth_uri "http://${KEYSTONE_PUBLIC_SERVICE_HOST}:5000/"
-crudini --set $cfg keystone_authtoken auth_protocol http
-crudini --set $cfg keystone_authtoken auth_host ${KEYSTONE_PUBLIC_SERVICE_HOST}
-crudini --set $cfg keystone_authtoken auth_port 5000
-
-crudini --set $cfg keystone_authtoken admin_user ${NOVA_KEYSTONE_USER}
-crudini --set $cfg keystone_authtoken admin_password "${NOVA_KEYSTONE_PASSWORD}"
-crudini --set $cfg keystone_authtoken admin_tenant_name ${ADMIN_TENANT_NAME}
-
-cat > /openrc <<EOF
-export OS_AUTH_URL="http://${KEYSTONE_PUBLIC_SERVICE_HOST}:5000/v2.0"
-export OS_USERNAME="${NOVA_KEYSTONE_USER}"
-export OS_PASSWORD="${NOVA_KEYSTONE_PASSWORD}"
-export OS_TENANT_NAME="${ADMIN_TENANT_NAME}"
-EOF
-
-# Configure database connection
-crudini --set $cfg \
-    database \
-    connection \
-    "mysql://${NOVA_DB_USER}:${NOVA_DB_PASSWORD}@${MARIADB_SERVICE_HOST}/${NOVA_DB_NAME}"
diff --git a/docker/centos/binary/nova-base/config-nova.sh b/docker/centos/binary/nova-base/config-nova.sh
new file mode 120000
index 0000000000000000000000000000000000000000..32efe60563f09a2bdde533e16f696c166e6ae351
--- /dev/null
+++ b/docker/centos/binary/nova-base/config-nova.sh
@@ -0,0 +1 @@
+../../../common/nova-base/config-nova.sh
\ No newline at end of file
diff --git a/docker/centos/binary/nova-compute/nova-compute/config-nova-compute.sh b/docker/centos/binary/nova-compute/nova-compute/config-nova-compute.sh
deleted file mode 100755
index 9a2c125724650c5eb44b4757a0def4ad7c9df9e9..0000000000000000000000000000000000000000
--- a/docker/centos/binary/nova-compute/nova-compute/config-nova-compute.sh
+++ /dev/null
@@ -1,28 +0,0 @@
-#!/bin/bash
-
-. /opt/kolla/kolla-common.sh
-. /opt/kolla/config-nova.sh
-
-cfg=/etc/nova/nova.conf
-
-check_required_vars NOVA_VNCSERVER_PROXYCLIENT_ADDRESS NOVA_NOVNC_PROXY_PORT \
-                    NOVA_NOVNC_BASE_ADDRESS
-
-# Configures novnc to listen on all interfaces and instructs nova-compute to
-# announce PROXYCLIENT_IP to the nova-vncproxy. Clients like Horizon will
-# connect with this address.
-# As such, NOVA_VNCSERVER_PROXYCLIENT_ADDRESS is unique per compute node.
-crudini --set $cfg DEFAULT vnc_enabled "True"
-crudini --set $cfg DEFAULT vncserver_listen "0.0.0.0"
-crudini --set $cfg DEFAULT vncserver_proxyclient_address "${NOVA_VNCSERVER_PROXYCLIENT_ADDRESS}"
-crudini --set $cfg DEFAULT novncproxy_base_url "http://${NOVA_NOVNC_BASE_ADDRESS}:${NOVA_NOVNC_PROXY_PORT}/vnc_auto.html"
-
-# configure logging
-crudini --set $cfg DEFAULT log_file "${NOVA_COMPUTE_LOG_FILE}"
-
-# set qmeu emulation if no hardware acceleration found
-if [[ `egrep -c '(vmx|svm)' /proc/cpuinfo` == 0 ]]; then
-    crudini --set $cfg libvirt virt_type qemu
-fi
-
-mkdir -p /var/lib/nova/instances
diff --git a/docker/centos/binary/nova-compute/nova-compute/config-nova-compute.sh b/docker/centos/binary/nova-compute/nova-compute/config-nova-compute.sh
new file mode 120000
index 0000000000000000000000000000000000000000..0f3c1216cf1a443c1481098604970d8b08a26db1
--- /dev/null
+++ b/docker/centos/binary/nova-compute/nova-compute/config-nova-compute.sh
@@ -0,0 +1 @@
+../../../../common/nova-compute/nova-compute/config-nova-compute.sh
\ No newline at end of file
diff --git a/docker/centos/binary/nova-compute/nova-compute/start.sh b/docker/centos/binary/nova-compute/nova-compute/start.sh
deleted file mode 100755
index ce3d0c0c377d1ff66c0d26a52f2814725d05f1a4..0000000000000000000000000000000000000000
--- a/docker/centos/binary/nova-compute/nova-compute/start.sh
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/bash
-
-set -e
-
-. /opt/kolla/config-nova-compute.sh
-
-sleep 6
-
-echo "Starting nova-compute."
-exec /usr/bin/nova-compute --config-file /etc/nova/nova.conf
diff --git a/docker/centos/binary/nova-compute/nova-compute/start.sh b/docker/centos/binary/nova-compute/nova-compute/start.sh
new file mode 120000
index 0000000000000000000000000000000000000000..ef5d32f18a21c140c33d91a75c376fb10c853afe
--- /dev/null
+++ b/docker/centos/binary/nova-compute/nova-compute/start.sh
@@ -0,0 +1 @@
+../../../../common/nova-compute/nova-compute/start.sh
\ No newline at end of file
diff --git a/docker/centos/binary/nova-compute/nova-libvirt/start.sh b/docker/centos/binary/nova-compute/nova-libvirt/start.sh
deleted file mode 100755
index bdbe882b8d1433bd14340a233a15a05887ed2129..0000000000000000000000000000000000000000
--- a/docker/centos/binary/nova-compute/nova-libvirt/start.sh
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/bin/bash
-
-if [[ $(cat /proc/cpuinfo | grep vmx) ]]; then
-    modprobe kvm_intel
-elif [[ $(cat /proc/cpuinfo | grep svm) ]]; then
-    modprobe kvm_amd
-else
-    echo "WARNING: Your hardware does not support hardware virtualization -" \
-        "using qemu software virtualization instead"
-fi
-
-modprobe ip6_tables ip_tables ebtable_nat
-
-# If libvirt is not installed on the host permissions need to be set
-# If running in qemu, we don't need to set anything as /dev/kvm won't exist
-if [[ -c /dev/kvm ]]; then
-    chmod 660 /dev/kvm
-    chown root:kvm /dev/kvm
-fi
-
-echo "Starting libvirtd."
-exec /usr/sbin/libvirtd
diff --git a/docker/centos/binary/nova-compute/nova-libvirt/start.sh b/docker/centos/binary/nova-compute/nova-libvirt/start.sh
new file mode 120000
index 0000000000000000000000000000000000000000..eac90997893da07ef4f135fc02a77c4ce611436e
--- /dev/null
+++ b/docker/centos/binary/nova-compute/nova-libvirt/start.sh
@@ -0,0 +1 @@
+../../../../common/nova-compute/nova-libvirt/start.sh
\ No newline at end of file
diff --git a/docker/centos/binary/nova-compute/nova-network/config-nova-network.sh b/docker/centos/binary/nova-compute/nova-network/config-nova-network.sh
deleted file mode 100755
index 6976d3a20871f27713e30d7cfece401fb5a72f29..0000000000000000000000000000000000000000
--- a/docker/centos/binary/nova-compute/nova-network/config-nova-network.sh
+++ /dev/null
@@ -1,30 +0,0 @@
-#!/bin/bash
-
-. /opt/kolla/config-nova.sh
-
-cfg=/etc/nova/nova.conf
-
-# configure logging
-crudini --set $cfg DEFAULT log_file "${NOVA_NETWORK_LOG_FILE}"
-
-# Configure eth1 as a physcial interface for nova flat network
-cat > /etc/sysconfig/network-scripts/ifcfg-$FLAT_INTERFACE <<EOF
-DEVICE="$FLAT_INTERFACE"
-BOOTPROTO="none"
-ONBOOT="yes"
-TYPE="Ethernet"
-EOF
-
-/usr/sbin/ifup $FLAT_INTERFACE
-
-cfg=/etc/nova/nova.conf
-
-crudini --set $cfg DEFAULT network_manager nova.network.manager.FlatDHCPManager
-crudini --set $cfg DEFAULT firewall_driver nova.virt.libvirt.firewall.IptablesFirewallDriver
-crudini --set $cfg DEFAULT network_size 254
-crudini --set $cfg DEFAULT allow_same_net_traffic False
-crudini --set $cfg DEFAULT multi_host True
-crudini --set $cfg DEFAULT send_arp_for_ha True
-crudini --set $cfg DEFAULT share_dhcp_address True
-crudini --set $cfg DEFAULT force_dhcp_release True
-crudini --set $cfg DEFAULT flat_network_bridge br100
diff --git a/docker/centos/binary/nova-compute/nova-network/config-nova-network.sh b/docker/centos/binary/nova-compute/nova-network/config-nova-network.sh
new file mode 120000
index 0000000000000000000000000000000000000000..ed1af588e0412dddfcc3b93f13f8e7d4863d8fdd
--- /dev/null
+++ b/docker/centos/binary/nova-compute/nova-network/config-nova-network.sh
@@ -0,0 +1 @@
+../../../../common/nova-compute/nova-network/config-nova-network.sh
\ No newline at end of file
diff --git a/docker/centos/binary/nova-compute/nova-network/start.sh b/docker/centos/binary/nova-compute/nova-network/start.sh
deleted file mode 100755
index 92381b720f582f0b48af2155904613edc92e31df..0000000000000000000000000000000000000000
--- a/docker/centos/binary/nova-compute/nova-network/start.sh
+++ /dev/null
@@ -1,8 +0,0 @@
-#!/bin/bash
-
-set -e
-
-. /opt/kolla/config-nova-network.sh
-
-# Start nova-network
-exec /usr/bin/nova-network --config-file /etc/nova/nova.conf
diff --git a/docker/centos/binary/nova-compute/nova-network/start.sh b/docker/centos/binary/nova-compute/nova-network/start.sh
new file mode 120000
index 0000000000000000000000000000000000000000..f2bec197912f60d29fae5d05050aebd81c0d59b6
--- /dev/null
+++ b/docker/centos/binary/nova-compute/nova-network/start.sh
@@ -0,0 +1 @@
+../../../../common/nova-compute/nova-network/start.sh
\ No newline at end of file
diff --git a/docker/centos/binary/nova-controller/nova-api/check.sh b/docker/centos/binary/nova-controller/nova-api/check.sh
deleted file mode 100755
index b250682d803aed91be45efd89f5ff493ce754402..0000000000000000000000000000000000000000
--- a/docker/centos/binary/nova-controller/nova-api/check.sh
+++ /dev/null
@@ -1,17 +0,0 @@
-#!/bin/bash
-
-RES=0
-
-. /openrc
-if ! keystone token-get > /dev/null; then
-    echo "ERROR: keystone token-get failed" >&2
-    RES=1
-else
-    if ! nova list > /dev/null; then
-        echo "ERROR: nova list failed" >&2
-        RES=1
-    fi
-fi
-
-exit $RES
-
diff --git a/docker/centos/binary/nova-controller/nova-api/check.sh b/docker/centos/binary/nova-controller/nova-api/check.sh
new file mode 120000
index 0000000000000000000000000000000000000000..2a047038e49dd6f39d793790e145d3a264c2d8f4
--- /dev/null
+++ b/docker/centos/binary/nova-controller/nova-api/check.sh
@@ -0,0 +1 @@
+../../../../common/nova-controller/nova-api/check.sh
\ No newline at end of file
diff --git a/docker/centos/binary/nova-controller/nova-api/start.sh b/docker/centos/binary/nova-controller/nova-api/start.sh
deleted file mode 100755
index 7928370a46324521bc85bb6d0cde7800f8b22e22..0000000000000000000000000000000000000000
--- a/docker/centos/binary/nova-controller/nova-api/start.sh
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/bin/bash
-
-set -e
-
-. /opt/kolla/config-nova.sh
-
-check_required_vars KEYSTONE_ADMIN_TOKEN KEYSTONE_ADMIN_SERVICE_HOST \
-                    NOVA_KEYSTONE_USER NOVA_KEYSTONE_PASSWORD \
-                    ADMIN_TENANT_NAME NOVA_API_SERVICE_HOST \
-                    NOVA_EC2_API_SERVICE_HOST PUBLIC_IP NOVA_DB_NAME
-fail_unless_os_service_running keystone
-fail_unless_db $NOVA_DB_NAME
-
-export SERVICE_TOKEN="${KEYSTONE_ADMIN_TOKEN}"
-export SERVICE_ENDPOINT="http://${KEYSTONE_ADMIN_SERVICE_HOST}:35357/v2.0"
-
-cfg=/etc/nova/nova.conf
-
-# configure logging
-crudini --set $cfg DEFAULT log_file "${NOVA_API_LOG_FILE}"
-
-crux user-create --update \
-    -n "${NOVA_KEYSTONE_USER}" \
-    -p "${NOVA_KEYSTONE_PASSWORD}" \
-    -t "${ADMIN_TENANT_NAME}" \
-    -r admin
-
-crux endpoint-create --remove-all \
-    -n ec2 -t ec2 \
-    -I "http://${NOVA_EC2_API_SERVICE_HOST}:8773/services/Cloud" \
-    -P "http://${PUBLIC_IP}:8773/services/Cloud" \
-    -A "http://${NOVA_EC2_API_SERVICE_HOST}:8773/services/Admin"
-
-crux endpoint-create --remove-all \
-    -n nova -t compute \
-    -I "http://${NOVA_API_SERVICE_HOST}:8774/v2/\$(tenant_id)s" \
-    -P "http://${PUBLIC_IP}:8774/v2/\$(tenant_id)s" \
-    -A "http://${NOVA_API_SERVICE_HOST}:8774/v2/\$(tenant_id)s"
-
-crux endpoint-create --remove-all \
-    -n novav3 -t computev3 \
-    -I "http://${NOVA_API_SERVICE_HOST}:8774/v3" \
-    -P "http://${PUBLIC_IP}:8774/v3" \
-    -A "http://${NOVA_API_SERVICE_HOST}:8774/v3"
-
-exec /usr/bin/nova-api --config-file /etc/nova/nova.conf
diff --git a/docker/centos/binary/nova-controller/nova-api/start.sh b/docker/centos/binary/nova-controller/nova-api/start.sh
new file mode 120000
index 0000000000000000000000000000000000000000..7613d713aa003bd8993fe2032c7776a78177ae2d
--- /dev/null
+++ b/docker/centos/binary/nova-controller/nova-api/start.sh
@@ -0,0 +1 @@
+../../../../common/nova-controller/nova-api/start.sh
\ No newline at end of file
diff --git a/docker/centos/binary/nova-controller/nova-conductor/start.sh b/docker/centos/binary/nova-controller/nova-conductor/start.sh
deleted file mode 100755
index 575e7ff6ccf14c45ad2172273b9a2fc6e327e35e..0000000000000000000000000000000000000000
--- a/docker/centos/binary/nova-controller/nova-conductor/start.sh
+++ /dev/null
@@ -1,23 +0,0 @@
-#!/bin/bash
-
-set -e
-
-. /opt/kolla/config-nova.sh
-
-check_required_vars NOVA_DB_NAME NOVA_DB_USER NOVA_DB_PASSWORD
-fail_unless_db
-
-cfg=/etc/nova/nova.conf
-
-# configure logging
-crudini --set $cfg DEFAULT log_file "${NOVA_CONDUCTOR_LOG_FILE}"
-
-mysql -h ${MARIADB_SERVICE_HOST} -u root -p${DB_ROOT_PASSWORD} mysql <<EOF
-CREATE DATABASE IF NOT EXISTS ${NOVA_DB_NAME};
-GRANT ALL PRIVILEGES ON ${NOVA_DB_NAME}.* TO
-	'${NOVA_DB_USER}'@'%' IDENTIFIED BY '${NOVA_DB_PASSWORD}'
-EOF
-
-nova-manage db sync
-
-exec /usr/bin/nova-conductor --config-file /etc/nova/nova.conf
diff --git a/docker/centos/binary/nova-controller/nova-conductor/start.sh b/docker/centos/binary/nova-controller/nova-conductor/start.sh
new file mode 120000
index 0000000000000000000000000000000000000000..2b0dc28f8cd56be9a234e52376dfaaa78d571955
--- /dev/null
+++ b/docker/centos/binary/nova-controller/nova-conductor/start.sh
@@ -0,0 +1 @@
+../../../../common/nova-controller/nova-conductor/start.sh
\ No newline at end of file
diff --git a/docker/centos/binary/nova-controller/nova-consoleauth/start.sh b/docker/centos/binary/nova-controller/nova-consoleauth/start.sh
deleted file mode 100755
index a1b0864ac3253e1132f31c216aa1031c0b02609f..0000000000000000000000000000000000000000
--- a/docker/centos/binary/nova-controller/nova-consoleauth/start.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/bash
-set -e
-
-. /opt/kolla/config-nova.sh
-
-cfg=/etc/nova/nova.conf
-
-crudini --set $cfg DEFAULT log_file "${NOVA_CONSOLEAUTH_LOG_FILE}"
-
-echo Starting nova-consoleauth
-exec /usr/bin/nova-consoleauth
diff --git a/docker/centos/binary/nova-controller/nova-consoleauth/start.sh b/docker/centos/binary/nova-controller/nova-consoleauth/start.sh
new file mode 120000
index 0000000000000000000000000000000000000000..0821b3c38120100c1eea50a3b7dd4a7bdb510d5a
--- /dev/null
+++ b/docker/centos/binary/nova-controller/nova-consoleauth/start.sh
@@ -0,0 +1 @@
+../../../../common/nova-controller/nova-consoleauth/start.sh
\ No newline at end of file
diff --git a/docker/centos/binary/nova-controller/nova-novncproxy/start.sh b/docker/centos/binary/nova-controller/nova-novncproxy/start.sh
deleted file mode 100755
index 9edafbca340fa5fff8aa09d24b9dd87f9e0f7da9..0000000000000000000000000000000000000000
--- a/docker/centos/binary/nova-controller/nova-novncproxy/start.sh
+++ /dev/null
@@ -1,22 +0,0 @@
-#!/bin/bash
-set -e
-. /opt/kolla/kolla-common.sh
-
-cfg=/etc/nova/nova.conf
-
-check_required_vars PUBLIC_IP NOVA_NOVNC_PROXY_SERVICE_HOST NOVA_NOVNC_PROXY_PORT \
-                    NOVA_NOVNC_BASE_ADDRESS NOVA_VNCSERVER_LISTEN_ADDRESS \
-                    NOVA_VNCSERVER_PROXYCLIENT_ADDRESS
-
-crudini --set $cfg DEFAULT log_file "${NOVA_NOVNCPROXY_LOG_FILE}"
-
-# Listen on all interfaces on port $NOVA_NOVNC_PROXY_PORT for incoming novnc
-# requests.
-# The base_url is given to clients to connect to, like Horizon, so this could
-# very well be fancy DNS name.
-echo Configuring VNC...
-crudini --set $cfg DEFAULT vncserver_listen "${NOVA_VNCSERVER_LISTEN_ADDRESS}"
-crudini --set $cfg DEFAULT vncserver_proxyclient_address "${NOVA_VNCSERVER_PROXYCLIENT_ADDRESS}"
-
-echo Starting nova-novncproxy
-exec /usr/bin/nova-novncproxy
diff --git a/docker/centos/binary/nova-controller/nova-novncproxy/start.sh b/docker/centos/binary/nova-controller/nova-novncproxy/start.sh
new file mode 120000
index 0000000000000000000000000000000000000000..80b6459a44c772d1053255ebfff66b6d2e99b88e
--- /dev/null
+++ b/docker/centos/binary/nova-controller/nova-novncproxy/start.sh
@@ -0,0 +1 @@
+../../../../common/nova-controller/nova-novncproxy/start.sh
\ No newline at end of file
diff --git a/docker/centos/binary/nova-controller/nova-scheduler/start.sh b/docker/centos/binary/nova-controller/nova-scheduler/start.sh
deleted file mode 100755
index 504c049edc6c4721adf5caa12f495fb6b4d34138..0000000000000000000000000000000000000000
--- a/docker/centos/binary/nova-controller/nova-scheduler/start.sh
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/bash
-
-set -e
-
-. /opt/kolla/config-nova.sh
-
-check_required_vars NOVA_DB_NAME
-fail_unless_db $NOVA_DB_NAME
-
-cfg=/etc/nova/nova.conf
-
-# configure logging
-crudini --set $cfg DEFAULT log_file "${NOVA_SCHEDULER_LOG_FILE}"
-
-exec /usr/bin/nova-scheduler --config-file /etc/nova/nova.conf
diff --git a/docker/centos/binary/nova-controller/nova-scheduler/start.sh b/docker/centos/binary/nova-controller/nova-scheduler/start.sh
new file mode 120000
index 0000000000000000000000000000000000000000..a72115139b970e4bd808bba87bcd4f56d43a375a
--- /dev/null
+++ b/docker/centos/binary/nova-controller/nova-scheduler/start.sh
@@ -0,0 +1 @@
+../../../../common/nova-controller/nova-scheduler/start.sh
\ No newline at end of file
diff --git a/docker/centos/binary/rabbitmq/rabbitmq-env.conf b/docker/centos/binary/rabbitmq/rabbitmq-env.conf
deleted file mode 100644
index e76f18f0b1bee9a48a8149059e5c63644f50848b..0000000000000000000000000000000000000000
--- a/docker/centos/binary/rabbitmq/rabbitmq-env.conf
+++ /dev/null
@@ -1,2 +0,0 @@
-RABBITMQ_NODENAME=@RABBITMQ_NODENAME@
-RABBITMQ_LOG_BASE=@RABBITMQ_LOG_BASE@
diff --git a/docker/centos/binary/rabbitmq/rabbitmq-env.conf b/docker/centos/binary/rabbitmq/rabbitmq-env.conf
new file mode 120000
index 0000000000000000000000000000000000000000..af9f8525e942e601d96c3de6df0070895f75cc6d
--- /dev/null
+++ b/docker/centos/binary/rabbitmq/rabbitmq-env.conf
@@ -0,0 +1 @@
+../../../common/rabbitmq/rabbitmq-env.conf
\ No newline at end of file
diff --git a/docker/centos/binary/rabbitmq/rabbitmq.config b/docker/centos/binary/rabbitmq/rabbitmq.config
deleted file mode 100644
index 15a47eba18ddf5ffce27941e54b51103e6f5212a..0000000000000000000000000000000000000000
--- a/docker/centos/binary/rabbitmq/rabbitmq.config
+++ /dev/null
@@ -1,11 +0,0 @@
-[
-  {rabbit, [
-    {default_user, <<"@RABBITMQ_USER@">>},
-    {default_pass, <<"@RABBITMQ_PASS@">>}
-  ]},
-  {kernel, [
-    
-  ]}
-].
-% EOF
-
diff --git a/docker/centos/binary/rabbitmq/rabbitmq.config b/docker/centos/binary/rabbitmq/rabbitmq.config
new file mode 120000
index 0000000000000000000000000000000000000000..cfb088507e381b1d82608675f3501f43f7be7dee
--- /dev/null
+++ b/docker/centos/binary/rabbitmq/rabbitmq.config
@@ -0,0 +1 @@
+../../../common/rabbitmq/rabbitmq.config
\ No newline at end of file
diff --git a/docker/centos/binary/rabbitmq/start.sh b/docker/centos/binary/rabbitmq/start.sh
deleted file mode 100755
index f70c3486689b23692653bf50982ad024e2debbeb..0000000000000000000000000000000000000000
--- a/docker/centos/binary/rabbitmq/start.sh
+++ /dev/null
@@ -1,24 +0,0 @@
-#!/bin/bash
-
-set -e
-
-: ${RABBITMQ_USER:=guest}
-: ${RABBITMQ_PASS:=guest}
-: ${RABBITMQ_NODENAME:=rabbit}
-: ${RABBITMQ_LOG_BASE:=/var/log/rabbitmq}
-
-sed -i '
-    s|@RABBITMQ_USER@|'"$RABBITMQ_USER"'|g
-    s|@RABBITMQ_PASS@|'"$RABBITMQ_PASS"'|g
-' /etc/rabbitmq/rabbitmq.config
-
-sed -i '
-    s|@RABBITMQ_NODENAME@|'"$RABBITMQ_NODENAME"'|g
-    s|@RABBITMQ_LOG_BASE@|'"$RABBITMQ_LOG_BASE"'|g
-' /etc/rabbitmq/rabbitmq-env.conf
-
-# work around:
-#   https://bugs.launchpad.net/ubuntu/+source/rabbitmq-server/+bug/653405
-echo "${RABBITMQ_SERVICE_HOST} `/usr/bin/hostname -s`" > /etc/hosts
-
-exec /usr/sbin/rabbitmq-server
diff --git a/docker/centos/binary/rabbitmq/start.sh b/docker/centos/binary/rabbitmq/start.sh
new file mode 120000
index 0000000000000000000000000000000000000000..035f55e267c70eebbd8d0db7b259beb91f85f96b
--- /dev/null
+++ b/docker/centos/binary/rabbitmq/start.sh
@@ -0,0 +1 @@
+../../../common/rabbitmq/start.sh
\ No newline at end of file
diff --git a/docker/centos/binary/swift/swift-account/start.sh b/docker/centos/binary/swift/swift-account/start.sh
deleted file mode 100644
index bf86830f98d0d82fbe09b708c3d1cbf3464f9ef4..0000000000000000000000000000000000000000
--- a/docker/centos/binary/swift/swift-account/start.sh
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/bin/bash
-
-: ${SWIFT_DB_USER:=swift}
-: ${SWIFT_DB_NAME:=swift}
-: ${KEYSTONE_AUTH_PROTOCOL:=http}
-: ${SWIFT_KEYSTONE_USER:=swift}
-: ${ADMIN_TENANT_NAME:=admin}
-
-check_required_vars KEYSTONE_ADMIN_TOKEN KEYSTONE_ADMIN_SERVICE_HOST \
-                    SWIFT_ADMIN_PASSWORD
-fail_unless_db
-fail_unless_os_service_running keystone
-
-if ! [ "$SWIFT_DB_PASSWORD" ]; then
-    SWIFT_DB_PASSWORD=$(openssl rand -hex 15)
-    export SWIFT_DB_PASSWORD
-fi
-
-sh /opt/swift/config-swift.sh account-server
-
-mysql -h ${MARIADB_SERVICE_HOST} -u root -p${DB_ROOT_PASSWORD} mysql <<EOF
-CREATE DATABASE IF NOT EXISTS ${SWIFT_DB_NAME};
-GRANT ALL PRIVILEGES ON swift* TO
-'${SWIFT_DB_USER}'@'%' IDENTIFIED BY '${SWIFT_DB_PASSWORD}'
-EOF
-
-export SERVICE_TOKEN="${KEYSTONE_ADMIN_TOKEN}"
-export SERVICE_ENDPOINT="${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:35357/v2.0"
-
-/bin/keystone user-create --name ${SWIFT_KEYSTONE_USER} --pass ${SWIFT_ADMIN_PASSWORD}
-/bin/keystone role-create --name ${SWIFT_KEYSTONE_USER}
-/bin/keystone user-role-add --user ${SWIFT_KEYSTONE_USER} --role admin --tenant ${ADMIN_TENANT_NAME}
-
-exec /usr/bin/swift-engine
diff --git a/docker/centos/binary/swift/swift-account/start.sh b/docker/centos/binary/swift/swift-account/start.sh
new file mode 120000
index 0000000000000000000000000000000000000000..f9e76aa5ba027499286f12fd8ef1f4c875ad6d14
--- /dev/null
+++ b/docker/centos/binary/swift/swift-account/start.sh
@@ -0,0 +1 @@
+../../../../common/swift/swift-account/start.sh
\ No newline at end of file
diff --git a/docker/centos/binary/swift/swift-container/start.sh b/docker/centos/binary/swift/swift-container/start.sh
deleted file mode 100644
index 42d4ccf35531a6fb10c1d7306c892910a4ced49e..0000000000000000000000000000000000000000
--- a/docker/centos/binary/swift/swift-container/start.sh
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/bin/bash
-
-: ${SWIFT_DB_USER:=swift}
-: ${SWIFT_DB_NAME:=swift}
-: ${KEYSTONE_AUTH_PROTOCOL:=http}
-: ${SWIFT_KEYSTONE_USER:=swift}
-: ${ADMIN_TENANT_NAME:=admin}
-
-check_required_vars KEYSTONE_ADMIN_TOKEN KEYSTONE_ADMIN_SERVICE_HOST \
-                    SWIFT_ADMIN_PASSWORD
-fail_unless_db
-fail_unless_os_service_running keystone
-
-if ! [ "$SWIFT_DB_PASSWORD" ]; then
-    SWIFT_DB_PASSWORD=$(openssl rand -hex 15)
-    export SWIFT_DB_PASSWORD
-fi
-
-sh /opt/swift/config-swift.sh container
-
-mysql -h ${MARIADB_SERVICE_HOST} -u root -p${DB_ROOT_PASSWORD} mysql <<EOF
-CREATE DATABASE IF NOT EXISTS ${SWIFT_DB_NAME};
-GRANT ALL PRIVILEGES ON swift* TO
-'${SWIFT_DB_USER}'@'%' IDENTIFIED BY '${SWIFT_DB_PASSWORD}'
-EOF
-
-export SERVICE_TOKEN="${KEYSTONE_ADMIN_TOKEN}"
-export SERVICE_ENDPOINT="${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:35357/v2.0"
-
-/bin/keystone user-create --name ${SWIFT_KEYSTONE_USER} --pass ${SWIFT_ADMIN_PASSWORD}
-/bin/keystone role-create --name ${SWIFT_KEYSTONE_USER}
-/bin/keystone user-role-add --user ${SWIFT_KEYSTONE_USER} --role admin --tenant ${ADMIN_TENANT_NAME}
-
-exec /usr/bin/swift-container-server
diff --git a/docker/centos/binary/swift/swift-container/start.sh b/docker/centos/binary/swift/swift-container/start.sh
new file mode 120000
index 0000000000000000000000000000000000000000..dc3c88490bc312eafd199fd3bd93134fa9b3ca98
--- /dev/null
+++ b/docker/centos/binary/swift/swift-container/start.sh
@@ -0,0 +1 @@
+../../../../common/swift/swift-container/start.sh
\ No newline at end of file
diff --git a/docker/centos/binary/swift/swift-object/start.sh b/docker/centos/binary/swift/swift-object/start.sh
deleted file mode 100644
index 7ed97536e757761df6de4f040a88119c212053b8..0000000000000000000000000000000000000000
--- a/docker/centos/binary/swift/swift-object/start.sh
+++ /dev/null
@@ -1,34 +0,0 @@
-#!/bin/bash
-
-: ${SWIFT_DB_USER:=swift}
-: ${SWIFT_DB_NAME:=swift}
-: ${KEYSTONE_AUTH_PROTOCOL:=http}
-: ${SWIFT_KEYSTONE_USER:=swift}
-: ${ADMIN_TENANT_NAME:=admin}
-
-check_required_vars KEYSTONE_ADMIN_TOKEN KEYSTONE_ADMIN_SERVICE_HOST \
-                    SWIFT_ADMIN_PASSWORD
-fail_unless_db
-fail_unless_os_service_running keystone
-
-if ! [ "$SWIFT_DB_PASSWORD" ]; then
-    SWIFT_DB_PASSWORD=$(openssl rand -hex 15)
-    export SWIFT_DB_PASSWORD
-fi
-
-sh /opt/swift/config-swift.sh engine
-
-mysql -h ${MARIADB_SERVICE_HOST} -u root -p${DB_ROOT_PASSWORD} mysql <<EOF
-CREATE DATABASE IF NOT EXISTS ${SWIFT_DB_NAME};
-GRANT ALL PRIVILEGES ON swift* TO
-'${SWIFT_DB_USER}'@'%' IDENTIFIED BY '${SWIFT_DB_PASSWORD}'
-EOF
-
-export SERVICE_TOKEN="${KEYSTONE_ADMIN_TOKEN}"
-export SERVICE_ENDPOINT="${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:35357/v2.0"
-
-/bin/keystone user-create --name ${SWIFT_KEYSTONE_USER} --pass ${SWIFT_ADMIN_PASSWORD}
-/bin/keystone role-create --name ${SWIFT_KEYSTONE_USER}
-/bin/keystone user-role-add --user ${SWIFT_KEYSTONE_USER} --role admin --tenant ${ADMIN_TENANT_NAME}
-
-exec /usr/bin/swift-object-server
diff --git a/docker/centos/binary/swift/swift-object/start.sh b/docker/centos/binary/swift/swift-object/start.sh
new file mode 120000
index 0000000000000000000000000000000000000000..690be2540edb8a25bdb245dd439a5400acc3d766
--- /dev/null
+++ b/docker/centos/binary/swift/swift-object/start.sh
@@ -0,0 +1 @@
+../../../../common/swift/swift-object/start.sh
\ No newline at end of file
diff --git a/docker/centos/binary/swift/swift-proxy-server/start.sh b/docker/centos/binary/swift/swift-proxy-server/start.sh
deleted file mode 100644
index 3f387d187e4926b81c5747d861e677645cdf21a6..0000000000000000000000000000000000000000
--- a/docker/centos/binary/swift/swift-proxy-server/start.sh
+++ /dev/null
@@ -1,5 +0,0 @@
-#!/bin/bash
-
-sh /opt/swift/config-swift.sh proxy
-
-exec /usr/bin/swift-proxy-server
diff --git a/docker/centos/binary/swift/swift-proxy-server/start.sh b/docker/centos/binary/swift/swift-proxy-server/start.sh
new file mode 120000
index 0000000000000000000000000000000000000000..6a5581a46c9b15d794d51f27efaf3e2255fd7379
--- /dev/null
+++ b/docker/centos/binary/swift/swift-proxy-server/start.sh
@@ -0,0 +1 @@
+../../../../common/swift/swift-proxy-server/start.sh
\ No newline at end of file
diff --git a/docker/centos/binary/zaqar/check.sh b/docker/centos/binary/zaqar/check.sh
deleted file mode 100755
index 4b3cdbb464930b0d2a5ce30e637aaa3ac9b9c4ab..0000000000000000000000000000000000000000
--- a/docker/centos/binary/zaqar/check.sh
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/bash
-
-status=$(curl -s -w "%{http_code}" -o /dev/null http://localhost:8888/v1/queues)
-
-if [[ $status -ne 200 && $status -ne 204 ]]; then
-    echo "ERROR($status): queue list failed"
-    exit $status
-fi
-
-exit 0
diff --git a/docker/centos/binary/zaqar/check.sh b/docker/centos/binary/zaqar/check.sh
new file mode 120000
index 0000000000000000000000000000000000000000..48c775659effde469d9c042e2614211101bec407
--- /dev/null
+++ b/docker/centos/binary/zaqar/check.sh
@@ -0,0 +1 @@
+../../../common/zaqar/check.sh
\ No newline at end of file
diff --git a/docker/centos/binary/zaqar/start.sh b/docker/centos/binary/zaqar/start.sh
deleted file mode 100755
index 6c68fccf22e0d941bd10b5e9bd776ab83172e07a..0000000000000000000000000000000000000000
--- a/docker/centos/binary/zaqar/start.sh
+++ /dev/null
@@ -1,64 +0,0 @@
-#!/bin/sh
-
-set -e
-
-. /opt/kolla/kolla-common.sh
-
-: ${ADMIN_TENANT_NAME:=admin}
-: ${ZAQAR_KEYSTONE_USER:=zaqar}
-: ${KEYSTONE_AUTH_PROTOCOL:=http}
-
-check_required_vars ZAQAR_KEYSTONE_PASSWORD ZAQAR_SERVER_SERVICE_HOST \
-                    KEYSTONE_ADMIN_SERVICE_HOST KEYSTONE_ADMIN_TOKEN \
-                    PUBLIC_IP
-dump_vars
-
-#check_for_mongodb
-check_for_keystone
-
-cat > /openrc <<EOF
-export OS_AUTH_URL="http://${KEYSTONE_PUBLIC_SERVICE_HOST}:5000/v2.0"
-export OS_USERNAME="${ZAQAR_KEYSTONE_USER}"
-export OS_PASSWORD="${ZAQAR_KEYSTONE_PASSWORD}"
-export OS_TENANT_NAME="${ADMIN_TENANT_NAME}"
-EOF
-
-cfg=/etc/zaqar/zaqar.conf
-
-crudini --set $cfg DEFAULT log_file \
-    ""
-crudini --set $cfg DEFAULT use_stderr \
-    true
-
-crudini --set $cfg drivers storage \
-    sqlite
-
-crudini --set $cfg keystone_authtoken admin_password \
-    "${ZAQAR_KEYSTONE_PASSWORD}"
-crudini --set $cfg keystone_authtoken admin_user \
-    "${ZAQAR_KEYSTONE_USER}"
-crudini --set $cfg  keystone_authtoken admin_tenant_name \
-    "${ADMIN_TENANT_NAME}"
-crudini --set $cfg keystone_authtoken auth_uri \
-    "${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_PUBLIC_SERVICE_HOST}:5000/v2.0"
-crudini --set $cfg keystone_authtoken auth_protocol \
-    "${KEYSTONE_AUTH_PROTOCOL}"
-crudini --set $cfg keystone_authtoken auth_host \
-    "${KEYSTONE_PUBLIC_SERVICE_HOST}"
-crudini --set $cfg keystone_authtoken auth_port \
-    5000
-
-
-export SERVICE_TOKEN="${KEYSTONE_ADMIN_TOKEN}"
-export SERVICE_ENDPOINT="${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:35357/v2.0"
-crux user-create -n ${ZAQAR_KEYSTONE_USER} \
-    -p ${ZAQAR_KEYSTONE_PASSWORD} \
-    -t ${ADMIN_TENANT_NAME} \
-    -r admin
-
-crux endpoint-create --remove-all -n ${ZAQAR_KEYSTONE_USER} -t messaging \
-    -I "${KEYSTONE_AUTH_PROTOCOL}://${ZAQAR_SERVER_SERVICE_HOST}:8888" \
-    -P "${KEYSTONE_AUTH_PROTOCOL}://${PUBLIC_IP}:8888" \
-    -A "${KEYSTONE_AUTH_PROTOCOL}://${ZAQAR_SERVER_SERVICE_HOST}:8888"
-
-exec /usr/bin/zaqar-server
diff --git a/docker/centos/binary/zaqar/start.sh b/docker/centos/binary/zaqar/start.sh
new file mode 120000
index 0000000000000000000000000000000000000000..48134a04428cc67396785bf29573884406ea72c0
--- /dev/null
+++ b/docker/centos/binary/zaqar/start.sh
@@ -0,0 +1 @@
+../../../common/zaqar/start.sh
\ No newline at end of file
diff --git a/docker/common/barbican/start.sh b/docker/common/barbican/start.sh
new file mode 100755
index 0000000000000000000000000000000000000000..673aa43393695908fd94605790d2dea2f73beafb
--- /dev/null
+++ b/docker/common/barbican/start.sh
@@ -0,0 +1,81 @@
+#!/bin/bash
+
+set -e
+
+: ${BARBICAN_DB_USER:=barbican}
+: ${BARBICAN_DB_NAME:=barbican}
+: ${KEYSTONE_AUTH_PROTOCOL:=http}
+: ${BARBICAN_KEYSTONE_USER:=barbican}
+: ${ADMIN_TENANT_NAME:=admin}
+
+if ! [ "$BARBICAN_DB_PASSWORD" ]; then
+        BARBICAN_DB_PASSWORD=$(openssl rand -hex 15)
+        export BARBICAN_DB_PASSWORD
+fi
+
+check_required_vars KEYSTONE_ADMIN_TOKEN KEYSTONE_ADMIN_SERVICE_HOST \
+                    KEYSTONE_ADMIN_SERVICE_PORT BARBICAN_ADMIN_PASSWORD
+fail_unless_db
+fail_unless_os_service_running keystone
+
+mysql -h ${MARIADB_SERVICE_HOST} -u root -p"${DB_ROOT_PASSWORD}" mysql <<EOF
+CREATE DATABASE IF NOT EXISTS ${BARBICAN_DB_NAME};
+GRANT ALL PRIVILEGES ON barbican.* TO
+    '${BARBICAN_DB_USER}'@'%' IDENTIFIED BY '${BARBICAN_DB_PASSWORD}'
+EOF
+
+# config file setup
+crudini --set /etc/barbican/barbican-api.conf \
+    DEFAULT \
+    sql_connection \
+    "mysql://${BARBICAN_DB_USER}:${BARBICAN_DB_PASSWORD}@${MARIADB_SERVICE_HOST}/${BARBICAN_DB_NAME}"
+crudini --set /etc/barbican/barbican-api.conf \
+    DEFAULT \
+    log_dir \
+    "/var/log/barbican/"
+crudini --set /etc/barbican/barbican-api.conf \
+    DEFAULT \
+    log_file \
+    "/var/log/barbican/barbican.log"
+crudini --set /etc/barbican/barbican-api-paste.ini \
+    pipeline:barbican_api \
+    pipeline \
+    "keystone_authtoken context apiapp"
+crudini --set /etc/barbican/barbican-api-paste.ini \
+    filter:keystone_authtoken \
+    auth_host \
+    ${KEYSTONE_ADMIN_SERVICE_HOST}
+crudini --set /etc/barbican/barbican-api-paste.ini \
+    filter:keystone_authtoken \
+    auth_port \
+    ${KEYSTONE_ADMIN_SERVICE_PORT}
+crudini --set /etc/barbican/barbican-api-paste.ini \
+    filter:keystone_authtoken \
+    auth_protocol \
+    ${KEYSTONE_AUTH_PROTOCOL}
+crudini --set /etc/barbican/barbican-api-paste.ini \
+    filter:keystone_authtoken \
+    admin_tenant_name \
+    ${ADMIN_TENANT_NAME}
+crudini --set /etc/barbican/barbican-api-paste.ini \
+    filter:keystone_authtoken \
+    admin_user \
+    ${BARBICAN_KEYSTONE_USER}
+crudini --set /etc/barbican/barbican-api-paste.ini \
+    filter:keystone_authtoken \
+    admin_password \
+    ${BARBICAN_KEYSTONE_USER}
+
+# create the required keystone entities for barbican
+export SERVICE_TOKEN="${KEYSTONE_ADMIN_TOKEN}"
+export SERVICE_ENDPOINT="${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}/v2.0"
+
+keystone user-get ${BARBICAN_KEYSTONE_USER} > /dev/null 2>&1 || /bin/keystone user-create --name ${BARBICAN_KEYSTONE_USER} --pass ${BARBICAN_ADMIN_PASSWORD}
+
+keystone role-get observer > /dev/null 2>&1 || /bin/keystone role-create --name observer
+keystone role-get creator > /dev/null 2>&1 || /bin/keystone role-create --name creator
+
+keystone user-get ${BARBICAN_KEYSTONE_USER} > /dev/null 2>&1 || /bin/keystone user-role-add --user ${BARBICAN_KEYSTONE_USER} --role admin --tenant ${ADMIN_TENANT_NAME}
+
+# launch Barbican using uwsgi
+exec uwsgi --master --emperor /etc/barbican/vassals
diff --git a/docker/common/kolla-common.sh b/docker/common/base/kolla-common.sh
similarity index 100%
rename from docker/common/kolla-common.sh
rename to docker/common/base/kolla-common.sh
diff --git a/docker/common/service_hosts.sh b/docker/common/base/service_hosts.sh
similarity index 100%
rename from docker/common/service_hosts.sh
rename to docker/common/base/service_hosts.sh
diff --git a/docker/common/ceilometer/ceilometer-alarm/start.sh b/docker/common/ceilometer/ceilometer-alarm/start.sh
new file mode 100644
index 0000000000000000000000000000000000000000..7470ae608f0762b48968a933ed3911f42fbf56b9
--- /dev/null
+++ b/docker/common/ceilometer/ceilometer-alarm/start.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+set -e
+
+. /opt/kolla/kolla-common.sh
+. /opt/kolla/config-ceilometer.sh
+
+
+exec /usr/bin/ceilometer-alarm-evaluator &
+exec /usr/bin/ceilometer-alarm-notifier
diff --git a/docker/common/ceilometer/ceilometer-api/start.sh b/docker/common/ceilometer/ceilometer-api/start.sh
new file mode 100644
index 0000000000000000000000000000000000000000..f081c9f84de535b688bd5a6b43ab0782b3185eeb
--- /dev/null
+++ b/docker/common/ceilometer/ceilometer-api/start.sh
@@ -0,0 +1,51 @@
+#!/bin/bash
+
+set -e
+
+. /opt/kolla/kolla-common.sh
+. /opt/kolla/config-ceilometer.sh
+
+check_required_vars CEILOMETER_DB_USER CEILOMETER_DB_NAME \
+                    CEILOMETER_DB_PASSWORD KEYSTONE_ADMIN_TOKEN \
+                    KEYSTONE_AUTH_PROTOCOL KEYSTONE_ADMIN_SERVICE_HOST \
+                    KEYSTONE_ADMIN_SERVICE_PORT ADMIN_TENANT_NAME \
+                    CEILOMETER_KEYSTONE_USER CEILOMETER_ADMIN_PASSWORD \
+                    CEILOMETER_API_SERVICE_HOST PUBLIC_IP
+
+fail_unless_os_service_running keystone
+fail_unless_db
+
+#TODO(pkilambi): Add mongodb support
+
+mysql -h ${MARIADB_SERVICE_HOST} -u root -p${DB_ROOT_PASSWORD} mysql <<EOF
+CREATE DATABASE IF NOT EXISTS ${CEILOMETER_DB_NAME} DEFAULT CHARACTER SET utf8;
+GRANT ALL PRIVILEGES ON ${CEILOMETER_DB_NAME}.* TO
+       '${CEILOMETER_DB_USER}'@'%' IDENTIFIED BY '${CEILOMETER_DB_PASSWORD}'
+
+EOF
+
+
+export SERVICE_TOKEN="${KEYSTONE_ADMIN_TOKEN}"
+export SERVICE_ENDPOINT="${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}/v2.0"
+
+
+crux user-create -n ${CEILOMETER_KEYSTONE_USER} \
+    -p ${CEILOMETER_ADMIN_PASSWORD} \
+    -t ${ADMIN_TENANT_NAME} \
+    -r admin
+
+crux service-create -n ${CEILOMETER_KEYSTONE_USER} -t metering \
+    -d "Ceilometer Telemetry Service"
+
+crux endpoint-create i--remove-all -n ${CEILOMETER_KEYSTONE_USER} -t metering \
+    -I "${KEYSTONE_AUTH_PROTOCOL}://${CEILOMETER_API_SERVICE_HOST}:8777" \
+    -P "${KEYSTONE_AUTH_PROTOCOL}://${PUBLIC_IP}:8777" \
+    -A "${KEYSTONE_AUTH_PROTOCOL}://${CEILOMETER_API_SERVICE_HOST}:8777"
+
+cfg=/etc/ceilometer/ceilometer.conf
+crudini --set $cfg \
+    DEFAULT connection
+    "mysql://${CEILOMETER_DB_USER}:${CEILOMETER_DB_PASSWORD}@${MARIADB_SERVICE_HOST}/${CEILOMETER_DB_NAME}"
+
+
+exec /usr/bin/ceilometer-api
diff --git a/docker/common/ceilometer/ceilometer-base/config-ceilometer.sh b/docker/common/ceilometer/ceilometer-base/config-ceilometer.sh
new file mode 100644
index 0000000000000000000000000000000000000000..a2316dcd1d42162c7c2b51a421a489b804f349ab
--- /dev/null
+++ b/docker/common/ceilometer/ceilometer-base/config-ceilometer.sh
@@ -0,0 +1,71 @@
+#!/bin/bash
+
+set -e
+. /opt/kolla/kolla-common.sh
+
+: ${CEILOMETER_DB_USER:=ceilometer}
+: ${CEILOMETER_DB_NAME:=ceilometer}
+: ${KEYSTONE_AUTH_PROTOCOL:=http}
+: ${CEILOMETER_KEYSTONE_USER:=admin}
+: ${CEILOMETER_ADMIN_PASSWORD:=kolla}
+: ${ADMIN_TENANT_NAME:=admin}
+: ${METERING_SECRET:=ceilometer}
+: ${RABBIT_PASSWORD:=guest}
+
+check_required_vars KEYSTONE_ADMIN_TOKEN KEYSTONE_ADMIN_SERVICE_HOST \
+                    KEYSTONE_ADMIN_SERVICE_PORT KEYSTONE_PUBLIC_SERVICE_HOST \
+dump_vars
+
+cat > /openrc <<EOF
+export SERVICE_TOKEN="${KEYSTONE_ADMIN_TOKEN}"
+export SERVICE_ENDPOINT="${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}/v2.0"
+EOF
+
+
+cfg=/etc/ceilometer/ceilometer.conf
+
+crudini --set $cfg \
+    DEFAULT rpc_backend rabbit
+crudini --set $cfg \
+    DEFAULT rabbit_host ${RABBITMQ_SERVICE_HOST}
+crudini --set $cfg \
+    DEFAULT rabbit_password ${RABBIT_PASSWORD}
+
+crudini --set $cfg \
+    keystone_authtoken \
+    auth_uri \
+    "http://${KEYSTONE_PUBLIC_SERVICE_HOST}:5000/"
+crudini --set $cfg \
+    keystone_authtoken \
+    admin_tenant_name \
+    "${ADMIN_TENANT_NAME}"
+crudini --set $cfg \
+    keystone_authtoken \
+    admin_user \
+    "${CEILOMETER_KEYSTONE_USER}"
+crudini --set $cfg \
+    keystone_authtoken \
+    admin_password \
+    ${CEILOMETER_ADMIN_PASSWORD}
+
+crudini --set $cfg \
+    service_credentials \
+    os_auth_url \
+    ${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_PUBLIC_SERVICE_HOST}:5000/
+crudini --set $cfg \
+    service_credentials \
+    os_username \
+    ceilometer
+crudini --set $cfg \
+    service_credentials \
+    os_tenant_name \
+    service
+crudini --set $cfg \
+    service_credentials \
+    os_password \
+    ${CEILOMETER_ADMIN_PASSWORD}
+
+crudini --set $cfg \
+    publisher
+    metering_secret
+    ${METERING_SECRET}
diff --git a/docker/common/ceilometer/ceilometer-central/start.sh b/docker/common/ceilometer/ceilometer-central/start.sh
new file mode 100644
index 0000000000000000000000000000000000000000..76f9a1fc2c14a6f93f218a487985ef61df0455b0
--- /dev/null
+++ b/docker/common/ceilometer/ceilometer-central/start.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+
+. /opt/kolla/kolla-common.sh
+. /opt/kolla/config-ceilometer.sh
+
+check_required_vars KEYSTONE_ADMIN_TOKEN KEYSTONE_AUTH_PROTOCOL \
+                    KEYSTONE_ADMIN_SERVICE_HOST KEYSTONE_ADMIN_SERVICE_PORT
+
+fail_unless_os_service_running keystone
+
+export SERVICE_TOKEN="${KEYSTONE_ADMIN_TOKEN}"
+export SERVICE_ENDPOINT="${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}/v2.0"
+
+exec /usr/bin/ceilometer-agent-central
diff --git a/docker/common/ceilometer/ceilometer-collector/start.sh b/docker/common/ceilometer/ceilometer-collector/start.sh
new file mode 100644
index 0000000000000000000000000000000000000000..1ed4c9e7d0122e8eb4b2e31e8ee579f1f408dd56
--- /dev/null
+++ b/docker/common/ceilometer/ceilometer-collector/start.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+set -e
+
+. /opt/kolla/kolla-common.sh
+. /opt/kolla/config-ceilometer.sh
+
+
+exec /usr/bin/ceilometer-collector
diff --git a/docker/common/ceilometer/ceilometer-compute/start.sh b/docker/common/ceilometer/ceilometer-compute/start.sh
new file mode 100644
index 0000000000000000000000000000000000000000..f4fc30baeea96849943a9d2b287d5aa22951961b
--- /dev/null
+++ b/docker/common/ceilometer/ceilometer-compute/start.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+. /opt/kolla/kolla-common.sh
+. /opt/kolla/config-ceilometer.sh
+
+
+check_required_vars KEYSTONE_ADMIN_TOKEN RABBITMQ_SERVICE_HOST RABBIT_PASSWORD
+
+fail_unless_os_service_running keystone
+
+# Nova conf settings
+crudini --set /etc/nova/nova.conf DEFAULT instance_usage_audit True
+crudini --set /etc/nova/nova.conf DEFAULT instance_usage_audit_period hour
+crudini --set /etc/nova/nova.conf DEFAULT notify_on_state_change vm_and_task_state
+crudini --set /etc/nova/nova.conf DEFAULT notification_driver nova.openstack.common.notifier.rpc_notifier
+crudini --set /etc/nova/nova.conf DEFAULT notification_driver ceilometer.compute.nova_notifier
+
+#ceilometer settings
+cfg=/etc/ceilometer/ceilometer.conf
+crudini --set $cfg publisher_rpc metering_secret ${KEYSTONE_ADMIN_TOKEN}
+crudini --set $cfg rabbit_host ${RABBITMQ_SERVICE_HOST}
+crudini --set $cfg rabbit_password ${RABBIT_PASSWORD}
+
+
+exec /usr/bin/ceilometer-agent-compute
diff --git a/docker/common/ceilometer/ceilometer-notification/start.sh b/docker/common/ceilometer/ceilometer-notification/start.sh
new file mode 100644
index 0000000000000000000000000000000000000000..9397345497a0efc8db57bba0e0b2ddd2decd504b
--- /dev/null
+++ b/docker/common/ceilometer/ceilometer-notification/start.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+set -e
+
+. /opt/kolla/kolla-common.sh
+. /opt/kolla/config-ceilometer.sh
+
+
+exec /usr/bin/ceilometer-agent-notification
diff --git a/docker/common/cinder-app/cinder-api/check.sh b/docker/common/cinder-app/cinder-api/check.sh
new file mode 100755
index 0000000000000000000000000000000000000000..57b88f56694ebad5ba42d874746ecdac4977bfd4
--- /dev/null
+++ b/docker/common/cinder-app/cinder-api/check.sh
@@ -0,0 +1,16 @@
+#!/bin/sh
+
+RES=0
+
+. /openrc
+if ! keystone token-get > /dev/null; then
+    echo "ERROR: keystone token-get failed" >&2
+    RES=1
+else
+    if ! cinder list > /dev/null; then
+        echo "ERROR: cinder list failed" >&2
+        RES=1
+    fi
+fi
+
+exit $RES
diff --git a/docker/common/cinder-app/cinder-api/start.sh b/docker/common/cinder-app/cinder-api/start.sh
new file mode 100755
index 0000000000000000000000000000000000000000..28293ac6cc4f3f1fa714a28b4ff91d56782b3ab0
--- /dev/null
+++ b/docker/common/cinder-app/cinder-api/start.sh
@@ -0,0 +1,73 @@
+#!/bin/bash
+
+set -e
+
+. /opt/kolla/kolla-common.sh
+. /opt/kolla/config-cinder.sh
+
+check_required_vars KEYSTONE_ADMIN_TOKEN KEYSTONE_ADMIN_SERVICE_HOST \
+                    ADMIN_TENANT_NAME PUBLIC_IP CINDER_API_SERVICE_HOST \
+                    KEYSTONE_AUTH_PROTOCOL KEYSTONE_ADMIN_SERVICE_PORT \
+                    CINDER_KEYSTONE_USER CINDER_KEYSTONE_PASSWORD \
+                    CINDER_API_LOG_FILE CINDER_API_SERVICE_LISTEN \
+                    CINDER_API_SERVICE_PORT CINDER_API_SERVICE_LISTEN
+
+fail_unless_os_service_running keystone
+
+cfg=/etc/cinder/cinder.conf
+
+# Set the auth credentials
+export SERVICE_TOKEN="${KEYSTONE_ADMIN_TOKEN}"
+export SERVICE_ENDPOINT="${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}/v2.0"
+
+# Create Keystone User
+crux user-create --update \
+    -n "${CINDER_KEYSTONE_USER}" \
+    -p "${CINDER_KEYSTONE_PASSWORD}" \
+    -t "${ADMIN_TENANT_NAME}" \
+    -r admin
+
+# Configure Keystone
+crux endpoint-create --remove-all \
+    -n cinder \
+    -t volume \
+    -P "http://${CINDER_API_SERVICE_HOST}:${CINDER_API_SERVICE_PORT}/v1/\$(tenant_id)s" \
+    -A "http://${CINDER_API_SERVICE_HOST}:${CINDER_API_SERVICE_PORT}/v1/\$(tenant_id)s" \
+    -I "http://${CINDER_API_SERVICE_HOST}:${CINDER_API_SERVICE_PORT}/v1/\$(tenant_id)s"
+
+crux endpoint-create --remove-all \
+    -n cinderv2 \
+    -t volumev2 \
+    -P "http://${CINDER_API_SERVICE_HOST}:${CINDER_API_SERVICE_PORT}/v2/\$(tenant_id)s" \
+    -A "http://${CINDER_API_SERVICE_HOST}:${CINDER_API_SERVICE_PORT}/v2/\$(tenant_id)s" \
+    -I "http://${CINDER_API_SERVICE_HOST}:${CINDER_API_SERVICE_PORT}/v2/\$(tenant_id)s"
+
+# Logging
+crudini --set $cfg \
+        DEFAULT \
+        log_file \
+        "${CINDER_API_LOG_FILE}"
+
+# API Configuration
+crudini --set $cfg \
+        DEFAULT \
+        osapi_volume_listen \
+        "${CINDER_API_SERVICE_LISTEN}"
+
+crudini --set $cfg \
+        DEFAULT \
+        osapi_volume_listen_port \
+        "${CINDER_API_SERVICE_PORT}"
+
+crudini --set $cfg \
+        DEFAULT \
+        enable_v1_api \
+        "true"
+
+crudini --set $cfg \
+        DEFAULT \
+        enable_v2_api \
+        "true"
+
+echo "Starting cinder-api"
+exec /usr/bin/cinder-api --config-file $cfg
diff --git a/docker/common/cinder-app/cinder-backup/start.sh b/docker/common/cinder-app/cinder-backup/start.sh
new file mode 100755
index 0000000000000000000000000000000000000000..5dff79b3566634c76180065cbdea8ab583e3d819
--- /dev/null
+++ b/docker/common/cinder-app/cinder-backup/start.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+
+set -e
+
+. /opt/kolla/kolla-common.sh
+. /opt/kolla/config-cinder.sh
+
+check_required_vars CINDER_BACKUP_DRIVER CINDER_BACKUP_MANAGER \
+                    CINDER_BACKUP_API_CLASS CINDER_BACKUP_NAME_TEMPLATE
+
+cfg=/etc/cinder/cinder.conf
+
+# volume backup configuration
+crudini --set $cfg \
+        DEFAULT \
+        backup_driver \
+        "${CINDER_BACKUP_DRIVER}"
+crudini --set $cfg \
+        DEFAULT \
+        backup_topic \
+        "cinder-backup"
+crudini --set $cfg \
+        DEFAULT \
+        backup_manager \
+        "${CINDER_BACKUP_MANAGER}"
+crudini --set $cfg \
+        DEFAULT \
+        backup_api_class \
+        "${CINDER_BACKUP_API_CLASS}"
+crudini --set $cfg \
+        DEFAULT \
+        backup_name_template \
+        "${CINDER_BACKUP_NAME_TEMPLATE}"
+
+echo "Starting cinder-backup"
+exec /usr/bin/cinder-backup --config-file $cfg
diff --git a/docker/common/cinder-app/cinder-base/config-cinder.sh b/docker/common/cinder-app/cinder-base/config-cinder.sh
new file mode 100644
index 0000000000000000000000000000000000000000..f82cb5510c97bf0b35e76773b07216f5dabe4f78
--- /dev/null
+++ b/docker/common/cinder-app/cinder-base/config-cinder.sh
@@ -0,0 +1,132 @@
+#!/bin/sh
+
+set -e
+
+. /opt/kolla/kolla-common.sh
+
+check_required_vars CINDER_DB_PASSWORD CINDER_KEYSTONE_PASSWORD \
+                    KEYSTONE_PUBLIC_SERVICE_HOST RABBITMQ_SERVICE_HOST \
+                    GLANCE_API_SERVICE_HOST MARIADB_SERVICE_HOST \
+                    RABBITMQ_SERVICE_HOST RABBITMQ_SERVICE_PORT \
+                    RABBIT_USERID RABBIT_PASSWORD GLANCE_API_SERVICE_HOST \
+                    GLANCE_API_SERVICE_PORT ADMIN_TENANT_NAME \
+                    CINDER_DB_NAME CINDER_DB_USER CINDER_KEYSTONE_USER \
+                    PUBLIC_IP KEYSTONE_AUTH_PROTOCOL CINDER_LOG_DIR
+
+dump_vars
+
+cat > /openrc <<EOF
+export OS_AUTH_URL="${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_PUBLIC_SERVICE_HOST}:${KEYSTONE_PUBLIC_SERVICE_PORT}/v2.0"
+export OS_USERNAME="${CINDER_KEYSTONE_USER}"
+export OS_PASSWORD="${CINDER_KEYSTONE_PASSWORD}"
+export OS_TENANT_NAME="${ADMIN_TENANT_NAME}"
+EOF
+
+cfg=/etc/cinder/cinder.conf
+
+# Logging
+crudini --set $cfg \
+        DEFAULT \
+        log_dir \
+        "${CINDER_LOG_DIR}"
+crudini --set $cfg \
+        DEFAULT \
+        verbose \
+        "${VERBOSE_LOGGING}"
+crudini --set $cfg \
+        DEFAULT \
+        debug \
+        "${DEBUG_LOGGING}"
+
+# backend
+crudini --set $cfg \
+        DEFAULT \
+        rpc_backend \
+        "cinder.openstack.common.rpc.impl_kombu"
+
+# rabbit
+crudini --set $cfg \
+        DEFAULT \
+        rabbit_host \
+        "${RABBITMQ_SERVICE_HOST}"
+crudini --set $cfg \
+        DEFAULT \
+        rabbit_port \
+        "${RABBITMQ_SERVICE_PORT}"
+crudini --set $cfg \
+        DEFAULT \
+        rabbit_hosts \
+        "${RABBITMQ_SERVICE_HOST}:${RABBITMQ_SERVICE_PORT}"
+crudini --set $cfg \
+        DEFAULT \
+        rabbit_userid \
+        "${RABBIT_USERID}"
+crudini --set $cfg \
+        DEFAULT \
+        rabbit_password \
+        "${RABBIT_PASSWORD}"
+crudini --set /etc/cinder/cinder.conf \
+        DEFAULT \
+        rabbit_virtual_host \
+        "/"
+crudini --set /etc/cinder/cinder.conf \
+        DEFAULT \
+        rabbit_ha_queues \
+        "False"
+
+# control_exchange
+crudini --set /etc/cinder/cinder.conf \
+        DEFAULT \
+        control_exchange \
+        "openstack"
+
+# glance
+crudini --set $cfg \
+        DEFAULT \
+        glance_host \
+        "${GLANCE_API_SERVICE_HOST}"
+crudini --set $cfg \
+        DEFAULT \
+        glance_port \
+        "${GLANCE_API_SERVICE_PORT}"
+
+# database
+crudini --set $cfg \
+        database \
+        connection \
+        "mysql://${CINDER_DB_USER}:${CINDER_DB_PASSWORD}@${MARIADB_SERVICE_HOST}/${CINDER_DB_NAME}"
+
+# keystone
+crudini --set $cfg \
+        DEFAULT \
+        auth_strategy \
+        "keystone"
+crudini --del $cfg \
+        keystone_authtoken \
+        auth_protocol
+crudini --del $cfg \
+        keystone_authtoken \
+        auth_host
+crudini --del $cfg \
+        keystone_authtoken \
+        auth_port
+crudini --set $cfg \
+        keystone_authtoken \
+        auth_uri \
+        "${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_PUBLIC_SERVICE_HOST}:${KEYSTONE_PUBLIC_SERVICE_PORT}/v2.0"
+crudini --set $cfg \
+        keystone_authtoken \
+        identity_uri \
+        "${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}"
+crudini --set $cfg \
+        keystone_authtoken \
+        admin_tenant_name \
+        "${ADMIN_TENANT_NAME}"
+crudini --set $cfg \
+        keystone_authtoken \
+        admin_user \
+        "${CINDER_KEYSTONE_USER}"
+crudini --set $cfg \
+        keystone_authtoken \
+        admin_password \
+        "${CINDER_KEYSTONE_PASSWORD}"
diff --git a/docker/common/cinder-app/cinder-scheduler/start.sh b/docker/common/cinder-app/cinder-scheduler/start.sh
new file mode 100755
index 0000000000000000000000000000000000000000..93efeb4062a02628f932a808730307b1f31d7a1a
--- /dev/null
+++ b/docker/common/cinder-app/cinder-scheduler/start.sh
@@ -0,0 +1,32 @@
+#!/bin/bash
+
+set -e
+
+. /opt/kolla/kolla-common.sh
+. /opt/kolla/config-cinder.sh
+
+fail_unless_db
+
+check_required_vars MARIADB_SERVICE_HOST DB_ROOT_PASSWORD \
+                    CINDER_DB_NAME CINDER_DB_USER CINDER_DB_PASSWORD \
+                    CINDER_SCHEDULER_LOG_FILE INIT_CINDER_DB
+
+cfg=/etc/cinder/cinder.conf
+
+if [ "${INIT_CINDER_DB}" == "true" ]; then
+    mysql -h ${MARIADB_SERVICE_HOST} -u root -p${DB_ROOT_PASSWORD} mysql <<EOF
+CREATE DATABASE IF NOT EXISTS ${CINDER_DB_NAME};
+GRANT ALL PRIVILEGES ON ${CINDER_DB_NAME}.* TO
+'${CINDER_DB_USER}'@'%' IDENTIFIED BY '${CINDER_DB_PASSWORD}'
+EOF
+
+    su -s /bin/sh -c "cinder-manage db sync" cinder
+fi
+
+crudini --set $cfg \
+    DEFAULT \
+    log_file \
+    "${CINDER_SCHEDULER_LOG_FILE}"
+
+echo "Starting cinder-scheduler"
+exec /usr/bin/cinder-scheduler --config-file $cfg
diff --git a/docker/common/cinder-app/cinder-volume/start.sh b/docker/common/cinder-app/cinder-volume/start.sh
new file mode 100755
index 0000000000000000000000000000000000000000..db29e75deb41e111a4da98498a92a9e7f1c2d07c
--- /dev/null
+++ b/docker/common/cinder-app/cinder-volume/start.sh
@@ -0,0 +1,75 @@
+#!/bin/bash
+
+set -e
+
+. /opt/kolla/kolla-common.sh
+. /opt/kolla/config-cinder.sh
+. /opt/kolla/volume-group-create.sh
+
+check_required_vars CINDER_VOLUME_API_LISTEN ISCSI_HELPER ISCSI_IP_ADDRESS \
+                    CINDER_VOLUME_GROUP CINDER_LVM_LO_VOLUME_SIZE \
+                    CINDER_VOLUME_BACKEND_NAME CINDER_VOLUME_DRIVER \
+                    CINDER_ENABLED_BACKEND CINDER_VOLUME_LOG_FILE
+
+cfg=/etc/cinder/cinder.conf
+
+# Logging
+crudini --set $cfg \
+    DEFAULT \
+    log_file \
+    "${CINDER_VOLUME_LOG_FILE}"
+
+# IP address on which OpenStack Volume API listens
+crudini --set $cfg \
+    DEFAULT \
+    osapi_volume_listen \
+    "${CINDER_VOLUME_API_LISTEN}"
+
+# The IP address that the iSCSI daemon is listening on
+crudini --set $cfg \
+    DEFAULT \
+    iscsi_ip_address \
+    "${ISCSI_IP_ADDRESS}"
+
+# Set to false when using loopback devices (testing)
+crudini --set $cfg \
+    DEFAULT \
+    secure_delete \
+    "false"
+
+crudini --set $cfg \
+    DEFAULT \
+    enabled_backends \
+    "${CINDER_ENABLED_BACKEND}"
+
+crudini --set $cfg \
+    lvm57 \
+    iscsi_helper \
+    "${ISCSI_HELPER}"
+
+crudini --set $cfg \
+    lvm57 \
+    volume_group \
+    "${CINDER_VOLUME_GROUP}"
+
+crudini --set $cfg \
+    lvm57 \
+    volume_driver \
+    "${CINDER_VOLUME_DRIVER}"
+
+crudini --set $cfg \
+    lvm57 \
+    iscsi_ip_address \
+    "${ISCSI_IP_ADDRESS}"
+
+crudini --set $cfg \
+    lvm57 \
+    volume_backend_name \
+    "${CINDER_VOLUME_BACKEND_NAME}"
+
+sed -i 's/udev_sync = 1/udev_sync = 0/' /etc/lvm/lvm.conf
+sed -i 's/udev_rules = 1/udev_rules = 0/' /etc/lvm/lvm.conf
+sed -i 's/use_lvmetad = 1/use_lvmetad = 0/' /etc/lvm/lvm.conf
+
+echo "Starting cinder-volume"
+exec /usr/bin/cinder-volume --config-file /etc/cinder/cinder.conf
diff --git a/docker/common/cinder-app/cinder-volume/volume-group-create.sh b/docker/common/cinder-app/cinder-volume/volume-group-create.sh
new file mode 100755
index 0000000000000000000000000000000000000000..908d987b0d91e59723da8e362c1f6f8f149a0031
--- /dev/null
+++ b/docker/common/cinder-app/cinder-volume/volume-group-create.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+
+# The script will create the cinder-volume volume group that will
+# allow cinder to create volumes from a backing file.
+# This is based off devstack.
+set -e
+
+backing_file=/opt/data/cinder_volume
+
+check_required_vars CINDER_LVM_LO_VOLUME_SIZE CINDER_VOLUME_GROUP
+
+if ! vgs ${CINDER_VOLUME_GROUP}; then
+    [[ ! -f $backing_file ]] && truncate -s ${CINDER_LVM_LO_VOLUMES_SIZE} $backing_file
+    vg_dev=`losetup -f --show $backing_file`
+    if ! vgs ${CINDER_VOLUME_GROUP}; then
+        vgcreate ${CINDER_VOLUME_GROUP} $vg_dev
+    fi
+fi
+
+# Remove iscsi targets
+cinder-rtstool get-targets | xargs -rn 1 cinder-rtstool delete
+
diff --git a/docker/common/designate/designate-api/start.sh b/docker/common/designate/designate-api/start.sh
new file mode 100755
index 0000000000000000000000000000000000000000..aae50ea8f1b6a22aaae67e6171b77f35547f8a2f
--- /dev/null
+++ b/docker/common/designate/designate-api/start.sh
@@ -0,0 +1,37 @@
+#!/bin/bash
+set -e
+
+. /opt/kolla/kolla-common.sh
+. /opt/kolla/config-designate.sh
+
+CONF=/etc/designate/designate.conf
+
+check_required_vars KEYSTONE_ADMIN_TOKEN KEYSTONE_ADMIN_SERVICE_HOST \
+                    DESIGNATE_KEYSTONE_USER DESIGNATE_KEYSTONE_PASSWORD \
+                    KEYSTONE_AUTH_PROTOCOL ADMIN_TENANT_NAME \
+                    DESIGNATE_API_SERVICE_HOST DESIGNATE_API_SERVICE_PORT \
+                    KEYSTONE_ADMIN_SERVICE_PORT
+
+export SERVICE_TOKEN="${KEYSTONE_ADMIN_TOKEN}"
+export SERVICE_ENDPOINT="${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}/v2.0"
+
+fail_unless_os_service_running keystone
+
+crux user-create \
+    -n ${DESIGNATE_KEYSTONE_USER} \
+    -p ${DESIGNATE_KEYSTONE_PASSWORD} \
+    -t ${ADMIN_TENANT_NAME} \
+    -r admin
+
+crux endpoint-create \
+    --remove-all \
+    -n ${DESIGNATE_KEYSTONE_USER} \
+    -t dns \
+    -I "${KEYSTONE_AUTH_PROTOCOL}://${DESIGNATE_API_SERVICE_HOST}:${DESIGNATE_API_SERVICE_PORT}/v1" \
+    -P "${KEYSTONE_AUTH_PROTOCOL}://${DESIGNATE_API_SERVICE_HOST}:${DESIGNATE_API_SERVICE_PORT}/v1" \
+    -A "${KEYSTONE_AUTH_PROTOCOL}://${DESIGNATE_API_SERVICE_HOST}:${DESIGNATE_API_SERVICE_PORT}/v1"
+
+crudini --set $CONF service:api api_paste_config "/usr/share/designate/api-paste.ini"
+crudini --set $CONF service:api api_port "${DESIGNATE_API_SERVICE_PORT}"
+
+exec /usr/bin/designate-api
diff --git a/docker/common/designate/designate-backend-bind9/start.sh b/docker/common/designate/designate-backend-bind9/start.sh
new file mode 100755
index 0000000000000000000000000000000000000000..90d2de676bef4e1e4457beaa3486ebf2909e3166
--- /dev/null
+++ b/docker/common/designate/designate-backend-bind9/start.sh
@@ -0,0 +1,60 @@
+#!/bin/bash
+set -e
+
+. /opt/kolla/kolla-common.sh
+
+check_required_vars DESIGNATE_MASTERNS DESIGNATE_SLAVENS DESIGNATE_BIND9_RNDC_KEY \
+                    DESIGNATE_ALLOW_RECURSION
+
+NAMEDCFG=/etc/named.conf
+
+# /var/named is coming from a VOLUME definition but at first boot it needs to
+# be populated from the original container since else it would be missing some
+# Bind9 core files. These files have been saved during the build phase.
+
+if [ ! -f /var/named/named.ca ]; then
+    cp -pr /opt/kolla/var-named/* /var/named/
+fi
+
+# When rndc adds a new domain, bind adds the call in an nzf file in this
+# directory.
+chmod 770 /var/named
+chown root:named /var/named
+
+# Default Bind9 behavior is to enable recursion, disable if wanted.
+if [ "${DESIGNATE_ALLOW_RECURSION}" == "false" ]; then
+    sed -i -r "s/(recursion) yes/\1 no/" $NAMEDCFG
+fi
+
+sed -i -r "/listen-on port 53/d" $NAMEDCFG
+sed -i -r "/listen-on-v6/d" $NAMEDCFG
+sed -i -r "s,/\* Path to ISC DLV key \*/,allow-new-zones yes;," $NAMEDCFG
+sed -i -r "/allow-query .+;/d" $NAMEDCFG
+
+if ! grep -q rndc-key /etc/named.conf; then
+    cat >> /etc/named.conf <<EOF
+include "/etc/rndc.key";
+controls {
+    inet ${DESIGNATE_SLAVENS} allow { ${DESIGNATE_MASTERNS}; } keys { "rndc-key"; };
+};
+EOF
+fi
+
+cat > /etc/rndc.key <<EOF
+key "rndc-key" {
+    algorithm hmac-md5;
+    secret "${DESIGNATE_BIND9_RNDC_KEY}";
+};
+EOF
+cat > /etc/rndc.conf <<EOF
+options {
+    default-key "rndc-key";
+    default-server 127.0.0.1;
+    default-port 953;
+};
+EOF
+cat /etc/rndc.key >> /etc/rndc.conf
+chown named /etc/rndc.key
+
+# Launch and keep in the foreground.
+exec /usr/sbin/named -u named -g
diff --git a/docker/common/designate/designate-base/config-designate.sh b/docker/common/designate/designate-base/config-designate.sh
new file mode 100755
index 0000000000000000000000000000000000000000..5a31401eec9b71dfe7a930ddfe649d25a4f2ae8a
--- /dev/null
+++ b/docker/common/designate/designate-base/config-designate.sh
@@ -0,0 +1,62 @@
+#!/bin/bash
+
+set -e
+
+. /opt/kolla/kolla-common.sh
+
+check_required_vars DESIGNATE_DB_PASSWORD DESIGNATE_KEYSTONE_PASSWORD \
+                    KEYSTONE_PUBLIC_SERVICE_HOST RABBITMQ_SERVICE_HOST \
+                    DESIGNATE_BIND9_RNDC_KEY DESIGNATE_BACKEND \
+                    KEYSTONE_PUBLIC_SERVICE_PORT DESIGNATE_KEYSTONE_USER \
+                    RABBIT_USERID RABBIT_PASSWORD DESIGNATE_DB_USER \
+                    DESIGNATE_DB_NAME KEYSTONE_AUTH_PROTOCOL \
+                    KEYSTONE_ADMIN_SERVICE_HOST KEYSTONE_ADMIN_SERVICE_PORT \
+                    DEBUG_LOGGING DESIGNATE_POOLMAN_POOLID
+
+fail_unless_db
+dump_vars
+
+cat > /openrc <<EOF
+export OS_AUTH_URL="http://${KEYSTONE_PUBLIC_SERVICE_HOST}:${KEYSTONE_PUBLIC_SERVICE_PORT}/v2.0"
+export OS_USERNAME="${DESIGNATE_KEYSTONE_USER}"
+export OS_PASSWORD="${DESIGNATE_KEYSTONE_PASSWORD}"
+export OS_TENANT_NAME="${ADMIN_TENANT_NAME}"
+EOF
+
+conf=/etc/designate/designate.conf
+
+# Regular configuration.
+crudini --set $conf DEFAULT log_file ""
+crudini --set $conf DEFAULT use_stderr "True"
+crudini --set $conf DEFAULT debug "${DEBUG_LOGGING}"
+crudini --set $conf DEFAULT rpc_backend "designate.openstack.common.rpc.impl_kombu"
+
+crudini --set $conf oslo_messaging_rabbit rabbit_host "${RABBITMQ_SERVICE_HOST}"
+crudini --set $conf oslo_messaging_rabbit rabbit_userid "${RABBIT_USERID}"
+crudini --set $conf oslo_messaging_rabbit rabbit_password "${RABBIT_PASSWORD}"
+
+crudini --set $conf storage:sqlalchemy connection "mysql://${DESIGNATE_DB_USER}:${DESIGNATE_DB_PASSWORD}@${MARIADB_SERVICE_HOST}/${DESIGNATE_DB_NAME}"
+
+crudini --set $conf service:api auth_strategy "keystone"
+crudini --set $conf service:api api_host "${PUBLIC_IP}"
+
+# Eventhough this is a central-scoped item, it's used in other Designate
+# components as well. Thus it should be configured here, from designate-base.
+crudini --set $conf service:central default_pool_id "${DESIGNATE_POOLMAN_POOLID}"
+
+crudini --set $conf keystone_authtoken identity_uri "${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}"
+crudini --set $conf keystone_authtoken auth_uri "${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_PUBLIC_SERVICE_HOST}:${KEYSTONE_PUBLIC_SERVICE_PORT}/v2.0"
+crudini --set $conf keystone_authtoken admin_tenant_name "${ADMIN_TENANT_NAME}"
+crudini --set $conf keystone_authtoken admin_user "${DESIGNATE_KEYSTONE_USER}"
+crudini --set $conf keystone_authtoken admin_password "${DESIGNATE_KEYSTONE_PASSWORD}"
+
+if [ "${DESIGNATE_BACKEND}" == "bind9" ]; then
+    # Configure a key for RNDC so it can connect with Bind9 to create/delete
+    # zones.
+    cat > /etc/rndc.key <<EOF
+key "rndc-key" {
+    algorithm hmac-md5;
+    secret "${DESIGNATE_BIND9_RNDC_KEY}";
+};
+EOF
+fi
diff --git a/docker/common/designate/designate-central/start.sh b/docker/common/designate/designate-central/start.sh
new file mode 100755
index 0000000000000000000000000000000000000000..fef7e235327d82491a8bbf11fe92781a9133fa8e
--- /dev/null
+++ b/docker/common/designate/designate-central/start.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+set -e
+
+. /opt/kolla/kolla-common.sh
+. /opt/kolla/config-designate.sh
+
+check_required_vars MARIADB_SERVICE_HOST DB_ROOT_PASSWORD DESIGNATE_DB_NAME \
+                    DESIGNATE_DB_USER DESIGNATE_DB_PASSWORD DESIGNATE_INITDB
+
+fail_unless_db
+
+CONF=/etc/designate/designate.conf
+
+if [ "${DESIGNATE_INITDB}" == "true" ]; then
+    echo "Configuring database"
+    mysql -h ${MARIADB_SERVICE_HOST} -u root -p"${DB_ROOT_PASSWORD}" mysql <<EOF
+CREATE DATABASE IF NOT EXISTS ${DESIGNATE_DB_NAME};
+GRANT ALL PRIVILEGES ON ${DESIGNATE_DB_NAME}.* TO '${DESIGNATE_DB_USER}'@'%' IDENTIFIED BY '${DESIGNATE_DB_PASSWORD}'
+EOF
+
+    designate-manage database sync
+fi
+
+exec /usr/bin/designate-central
diff --git a/docker/common/designate/designate-mdns/start.sh b/docker/common/designate/designate-mdns/start.sh
new file mode 100755
index 0000000000000000000000000000000000000000..a3e5df2747db943a1bec999c4f180446a3bffb7c
--- /dev/null
+++ b/docker/common/designate/designate-mdns/start.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+set -e
+
+. /opt/kolla/kolla-common.sh
+. /opt/kolla/config-designate.sh
+
+check_required_vars DESIGNATE_MASTERNS DESIGNATE_MDNS_PORT
+
+CONF=/etc/designate/designate.conf
+
+crudini --set $CONF service:mdns workers "1"
+crudini --set $CONF service:mdns host "${DESIGNATE_MASTERNS}"
+crudini --set $CONF service:mdns port "${DESIGNATE_MDNS_PORT}"
+crudini --set $CONF service:mdns tcp_backlog "100"
+crudini --set $CONF service:mdns all_tcp "False"
+
+exec /usr/bin/designate-mdns
diff --git a/docker/common/designate/designate-poolmanager/start.sh b/docker/common/designate/designate-poolmanager/start.sh
new file mode 100755
index 0000000000000000000000000000000000000000..f5222b3f46751cc1c26191056696696146edeeda
--- /dev/null
+++ b/docker/common/designate/designate-poolmanager/start.sh
@@ -0,0 +1,54 @@
+#!/bin/bash
+set -e
+
+. /opt/kolla/kolla-common.sh
+. /opt/kolla/config-designate.sh
+
+check_required_vars DESIGNATE_MASTERNS DESIGNATE_BACKEND DESIGNATE_SLAVENS \
+                    DESIGNATE_MDNS_PORT DESIGNATE_DNS_PORT DESIGNATE_POOLMAN_POOLID \
+                    DESIGNATE_POOLMAN_TARGETS DESIGNATE_POOLMAN_NSS \
+                    DESIGNATE_POOLMAN_POOLID
+
+CONF=/etc/designate/designate.conf
+
+if [ "${DESIGNATE_BACKEND}" == "bind9" ]; then
+    TYPE="bind9"
+    OPTIONS="rndc_host: ${DESIGNATE_SLAVENS}, rndc_key_file: /etc/rndc.key"
+else
+    echo Unsupported backend: ${DESIGNATE_BACKEND}
+    exit
+fi
+
+crudini --set $CONF service:pool_manager workers "1"
+crudini --set $CONF service:pool_manager enable_recovery_timer "False"
+crudini --set $CONF service:pool_manager periodic_recovery_interval "120"
+crudini --set $CONF service:pool_manager enable_sync_timer "True"
+crudini --set $CONF service:pool_manager periodic_sync_interval "1800"
+crudini --set $CONF service:pool_manager poll_max_retries "10"
+crudini --set $CONF service:pool_manager poll_delay "5"
+crudini --set $CONF service:pool_manager poll_retry_interval "15"
+crudini --set $CONF service:pool_manager pool_id "${DESIGNATE_POOLMAN_POOLID}"
+crudini --set $CONF service:pool_manager cache_driver "noop"
+
+# TODO: use this to use memcached
+#crudini --set $CONF service:pool_manager cache_driver memcache
+#crudini --set $CONF service:pool_manager memcached_servers ${MEMCACHED_HOST}
+
+# Specify the id of the pool managed through pool_manager. Central gets
+# configured with this pool_id as well.
+crudini --set $CONF service:pool_manager pool_id "${DESIGNATE_POOLMAN_POOLID}"
+
+crudini --set $CONF pool:${DESIGNATE_POOLMAN_POOLID} nameservers "${DESIGNATE_POOLMAN_NSS}"
+crudini --set $CONF pool:${DESIGNATE_POOLMAN_POOLID} targets "${DESIGNATE_POOLMAN_TARGETS}"
+
+crudini --set $CONF pool_target:${DESIGNATE_POOLMAN_TARGETS} type "${TYPE}"
+crudini --set $CONF pool_target:${DESIGNATE_POOLMAN_TARGETS} options "${OPTIONS}"
+# This is the mdns container, which is the master nameserver.
+crudini --set $CONF pool_target:${DESIGNATE_POOLMAN_TARGETS} masters "${DESIGNATE_MASTERNS}:${DESIGNATE_MDNS_PORT}"
+crudini --set $CONF pool_target:${DESIGNATE_POOLMAN_TARGETS} host "${DESIGNATE_MASTERNS}"
+crudini --set $CONF pool_target:${DESIGNATE_POOLMAN_TARGETS} port "${DESIGNATE_DNS_PORT}"
+
+crudini --set $CONF pool_nameserver:${DESIGNATE_POOLMAN_NSS} host "${DESIGNATE_MASTERNS}"
+crudini --set $CONF pool_nameserver:${DESIGNATE_POOLMAN_NSS} port "${DESIGNATE_DNS_PORT}"
+
+exec /usr/bin/designate-pool-manager
diff --git a/docker/common/galera/config-galera.sh b/docker/common/galera/config-galera.sh
new file mode 100755
index 0000000000000000000000000000000000000000..f0ab542e15344897084c4d666861734a80005c6e
--- /dev/null
+++ b/docker/common/galera/config-galera.sh
@@ -0,0 +1,94 @@
+#!/bin/bash
+
+. /opt/kolla/kolla-common.sh
+
+check_required_vars DB_CLUSTER_BIND_ADDRESS DB_CLUSTER_NAME DB_CLUSTER_NODES \
+                    DB_ROOT_PASSWORD DB_CLUSTER_WSREP_METHOD
+
+CFG=/etc/my.cnf.d/server.cnf
+DB_CLUSTER_INIT_SQL=/tmp/mysql-first-time.sql
+
+function configure_files {
+    crudini --set $CFG mariadb bind-address "${DB_CLUSTER_BIND_ADDRESS}"
+    crudini --set $CFG mariadb binlog_format "ROW"
+    crudini --set $CFG mariadb character-set-server "utf8"
+    crudini --set $CFG mariadb collation-server "utf8_general_ci"
+    crudini --set $CFG mariadb datadir "/var/lib/mysql"
+    crudini --set $CFG mariadb default-storage-engine "innodb"
+    crudini --set $CFG mariadb init-connect "'SET NAMES utf8'"
+    crudini --set $CFG mariadb innodb_autoinc_lock_mode "2"
+    crudini --set $CFG mariadb innodb_file_per_table 1
+    crudini --set $CFG mariadb innodb_flush_log_at_trx_commit "2"
+    crudini --set $CFG mariadb innodb_locks_unsafe_for_binlog "1"
+    crudini --set $CFG mariadb innodb_log_file_size "100M"
+    crudini --set $CFG mariadb query_cache_size "0"
+    crudini --set $CFG mariadb query_cache_type "0"
+    crudini --set $CFG mariadb wsrep_cluster_address "gcomm://${DB_CLUSTER_NODES}"
+    crudini --set $CFG mariadb wsrep_cluster_name "${DB_CLUSTER_NAME}"
+    crudini --set $CFG mariadb wsrep_provider "/usr/lib64/galera/libgalera_smm.so"
+    crudini --set $CFG mariadb wsrep_sst_auth "'root:${DB_ROOT_PASSWORD}'"
+    crudini --set $CFG mariadb wsrep_sst_method "${DB_CLUSTER_WSREP_METHOD}"
+}
+
+function bootstrap_database() {
+    mysqld_safe &
+    # Waiting for deamon
+    sleep 10
+    expect -c '
+    set timeout 10
+    spawn mysql_secure_installation
+    expect "Enter current password for root (enter for none):"
+    send "\r"
+    expect "Set root password?"
+    send "y\r"
+    expect "New password:"
+    send "'"${DB_ROOT_PASSWORD}"'\r"
+    expect "Re-enter new password:"
+    send "'"${DB_ROOT_PASSWORD}"'\r"
+    expect "Remove anonymous users?"
+    send "y\r"
+    expect "Disallow root login remotely?"
+    send "n\r"
+    expect "Remove test database and access to it?"
+    send "y\r"
+    expect "Reload privilege tables now?"
+    send "y\r"
+    expect eof'
+    mysqladmin -p"${DB_ROOT_PASSWORD}" shutdown
+}
+
+function configure_db {
+    bootstrap_database
+
+    echo "GRANT ALL ON *.* TO 'root'@'%' IDENTIFIED BY '$DB_ROOT_PASSWORD' ;" > $DB_CLUSTER_INIT_SQL
+
+    if [ "$MARIADB_DATABASE" ]; then
+        echo "CREATE DATABASE IF NOT EXISTS $MARIADB_DATABASE ;" >> $DB_CLUSTER_INIT_SQL
+    fi
+
+    if [ "$MARIADB_USER" -a "$MARIADB_PASSWORD" ]; then
+        echo "CREATE USER '$MARIADB_USER'@'%' IDENTIFIED BY '$MARIADB_PASSWORD' ;" >> $DB_CLUSTER_INIT_SQL
+
+        if [ "$MARIADB_DATABASE" ]; then
+            echo "GRANT ALL ON $MARIADB_DATABASE.* TO '$MARIADB_USER'@'%' ;" >> $DB_CLUSTER_INIT_SQL
+        fi
+    fi
+
+    echo "FLUSH PRIVILEGES" >> $DB_CLUSTER_INIT_SQL
+}
+
+function populate_db {
+    if [[ $(ls /var/lib/mysql) == "" ]]; then
+        echo "POPULATING NEW DB"
+        mysql_install_db
+        chown -R mysql /var/lib/mysql
+    else
+        echo "DB ALREADY EXISTS"
+    fi
+}
+
+function prepare_db {
+    populate_db
+    configure_db
+    configure_files
+}
diff --git a/docker/common/galera/start.sh b/docker/common/galera/start.sh
new file mode 100755
index 0000000000000000000000000000000000000000..9288b77cc74a376fd2050816d49deadd56772d77
--- /dev/null
+++ b/docker/common/galera/start.sh
@@ -0,0 +1,14 @@
+#!/bin/bash
+
+. /opt/kolla/kolla-common.sh
+. /opt/kolla/config-galera.sh
+
+check_required_vars DB_CLUSTER_INIT_DB
+prepare_db
+
+if [[ "${DB_CLUSTER_INIT_DB}" == "true" ]] && ! [[ -a /var/lib/mysql/cluster.exists ]]; then
+    DB_CLUSTER_IS_MASTER_NODE="--wsrep-new-cluster"
+    touch /var/lib/mysql/cluster.exists
+fi
+
+mysqld_safe --init-file=$DB_CLUSTER_INIT_SQL $DB_CLUSTER_IS_MASTER_NODE
\ No newline at end of file
diff --git a/docker/common/glance/glance-api/check.sh b/docker/common/glance/glance-api/check.sh
new file mode 100755
index 0000000000000000000000000000000000000000..f97ef70f46ffef79a4dbd27403819c3a1932d7a1
--- /dev/null
+++ b/docker/common/glance/glance-api/check.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+RES=0
+
+. /openrc
+if ! keystone token-get > /dev/null; then
+    echo "ERROR: keystone token-get failed" >&2
+    RES=1
+else
+    if ! glance image-list > /dev/null; then
+        echo "ERROR: glance image-list failed" >&2
+        RES=1
+    fi
+fi
+
+exit $RES
+
diff --git a/docker/common/glance/glance-api/start.sh b/docker/common/glance/glance-api/start.sh
new file mode 100755
index 0000000000000000000000000000000000000000..c546333f44d01e84881234ab5aee9319bae176d5
--- /dev/null
+++ b/docker/common/glance/glance-api/start.sh
@@ -0,0 +1,52 @@
+#!/bin/bash
+
+set -e
+
+. /opt/kolla/kolla-common.sh
+. /opt/kolla/config-glance.sh
+: ${GLANCE_API_SERVICE_HOST:=$PUBLIC_IP}
+
+check_required_vars KEYSTONE_ADMIN_TOKEN KEYSTONE_ADMIN_SERVICE_HOST \
+                    GLANCE_KEYSTONE_USER GLANCE_KEYSTONE_PASSWORD \
+                    ADMIN_TENANT_NAME GLANCE_API_SERVICE_HOST \
+                    PUBLIC_IP
+
+fail_unless_os_service_running keystone
+
+export SERVICE_TOKEN="${KEYSTONE_ADMIN_TOKEN}"
+export SERVICE_ENDPOINT="${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}/v2.0"
+
+crux user-create --update \
+    -n "${GLANCE_KEYSTONE_USER}" \
+    -p "${GLANCE_KEYSTONE_PASSWORD}" \
+    -t "${ADMIN_TENANT_NAME}" \
+    -r admin
+
+crux endpoint-create --remove-all \
+    -n glance -t image \
+    -I "http://${GLANCE_API_SERVICE_HOST}:9292" \
+    -P "http://${PUBLIC_IP}:9292" \
+    -A "http://${GLANCE_API_SERVICE_HOST}:9292"
+
+# turn on notification sending by glance
+crudini --set /etc/glance/glance-api.conf \
+    DEFAULT \
+    notification_driver \
+    "messaging"
+
+crudini --set /etc/glance/glance-api.conf \
+    DEFAULT \
+    rabbit_host \
+    "${RABBITMQ_SERVICE_HOST}"
+
+crudini --set /etc/glance/glance-api.conf \
+    DEFAULT \
+    registry_host \
+    "${GLANCE_REGISTRY_SERVICE_HOST}"
+
+crudini --set /etc/glance/glance-api.conf \
+    DEFAULT \
+    debug \
+    "True"
+
+exec /usr/bin/glance-api
diff --git a/docker/common/glance/glance-base/config-glance.sh b/docker/common/glance/glance-base/config-glance.sh
new file mode 100644
index 0000000000000000000000000000000000000000..97d076c11652dff140f775caeafad9c69a25ba96
--- /dev/null
+++ b/docker/common/glance/glance-base/config-glance.sh
@@ -0,0 +1,63 @@
+#!/bin/bash
+
+set -e
+
+. /opt/kolla/kolla-common.sh
+
+: ${ADMIN_TENANT_NAME:=admin}
+: ${GLANCE_DB_NAME:=glance}
+: ${GLANCE_DB_USER:=glance}
+: ${GLANCE_KEYSTONE_USER:=glance}
+: ${KEYSTONE_AUTH_PROTOCOL:=http}
+: ${PUBLIC_IP:=$GLANCE_API_PORT_9292_TCP_ADDR}
+
+check_required_vars GLANCE_DB_PASSWORD GLANCE_KEYSTONE_PASSWORD
+dump_vars
+
+cat > /openrc <<EOF
+export OS_AUTH_URL="http://${KEYSTONE_PUBLIC_SERVICE_HOST}:5000/v2.0"
+export OS_USERNAME="${GLANCE_KEYSTONE_USER}"
+export OS_PASSWORD="${GLANCE_KEYSTONE_PASSWORD}"
+export OS_TENANT_NAME="${ADMIN_TENANT_NAME}"
+EOF
+
+for cfg in /etc/glance/glance-api.conf /etc/glance/glance-registry.conf; do
+    crudini --set $cfg \
+        DEFAULT \
+        log_file \
+        ""
+
+    for option in auth_protocol auth_host auth_port; do
+        crudini --del $cfg \
+            keystone_authtoken \
+            $option
+    done
+
+    crudini --set $cfg \
+        keystone_authtoken \
+        auth_uri \
+        "http://${KEYSTONE_PUBLIC_SERVICE_HOST}:5000/"
+    crudini --set $cfg \
+        keystone_authtoken \
+        admin_tenant_name \
+        "${ADMIN_TENANT_NAME}"
+    crudini --set $cfg \
+        keystone_authtoken \
+        admin_user \
+        "${GLANCE_KEYSTONE_USER}"
+    crudini --set $cfg \
+        keystone_authtoken \
+        admin_password \
+        "${GLANCE_KEYSTONE_PASSWORD}"
+
+    crudini --set $cfg \
+        paste_deploy \
+        flavor \
+        keystone
+
+    crudini --set $cfg \
+        database \
+        connection \
+        "mysql://${GLANCE_DB_USER}:${GLANCE_DB_PASSWORD}@${MARIADB_SERVICE_HOST}/${GLANCE_DB_NAME}"
+done
+
diff --git a/docker/common/glance/glance-registry/start.sh b/docker/common/glance/glance-registry/start.sh
new file mode 100755
index 0000000000000000000000000000000000000000..5f590fb1ccd5d979ba075aa5dc5bcacf7d1d2745
--- /dev/null
+++ b/docker/common/glance/glance-registry/start.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+
+set -e
+
+. /opt/kolla/kolla-common.sh
+. /opt/kolla/config-glance.sh
+
+check_required_vars GLANCE_DB_NAME GLANCE_DB_USER GLANCE_DB_PASSWORD
+# lets wait for the DB to be available
+wait_for 25 1 check_for_db
+
+mysql -h ${MARIADB_SERVICE_HOST} -u root -p${DB_ROOT_PASSWORD} mysql <<EOF
+CREATE DATABASE IF NOT EXISTS ${GLANCE_DB_NAME} DEFAULT CHARACTER SET utf8;
+GRANT ALL PRIVILEGES ON ${GLANCE_DB_NAME}.* TO
+       '${GLANCE_DB_USER}'@'%' IDENTIFIED BY '${GLANCE_DB_PASSWORD}'
+
+EOF
+
+/usr/bin/glance-manage db_sync
+
+exec /usr/bin/glance-registry
diff --git a/docker/common/hautoproxy/haproxy.cfg.tmpl b/docker/common/hautoproxy/haproxy.cfg.tmpl
new file mode 100644
index 0000000000000000000000000000000000000000..cd1174b21966fcf5fc0e4d4da7514f973079b402
--- /dev/null
+++ b/docker/common/hautoproxy/haproxy.cfg.tmpl
@@ -0,0 +1,26 @@
+global
+    daemon
+    maxconn 4096
+    pidfile /var/run/haproxy.pid
+
+defaults
+    mode tcp
+    timeout connect 5s
+    timeout client 1m
+    timeout server 1m
+    option redispatch
+    balance roundrobin
+
+listen stats :1936
+    mode http
+    stats enable
+    stats hide-version
+    #stats realm Haproxy\ Statistics
+    stats uri /
+    #stats auth Username:Password
+
+{% for service in services %}
+listen {{ service.service_name }}
+    bind 127.0.0.1:{{service.local_port}}
+    server {{ service.remote_name }} {{ service.remote_addr }}:{{ service.remote_port}} check inter 2s rise 3 fall 2
+{% endfor %}
diff --git a/docker/common/hautoproxy/start.py b/docker/common/hautoproxy/start.py
new file mode 100755
index 0000000000000000000000000000000000000000..877b22157b8dcd205b65fd7ff44d35894bc85033
--- /dev/null
+++ b/docker/common/hautoproxy/start.py
@@ -0,0 +1,65 @@
+#!/usr/bin/python
+
+'''This script configures and starts a local haproxy instances, bound to
+127.0.0.1, that forwards connections all of the discovered
+docker/kubernetes environment variables.'''
+
+import argparse
+import os
+import sys
+from jinja2 import Environment, FileSystemLoader
+import re
+import urlparse
+
+re_url = re.compile(
+    '^(?P<name>.*)_PORT_(?P<port>\d+)_(?P<proto>(UDP|TCP))$')
+
+def parse_args():
+    p = argparse.ArgumentParser()
+    p.add_argument('--output', '-o',
+                   default='/etc/haproxy/haproxy.cfg')
+    p.add_argument('--no-start', '-n',
+                   action='store_true')
+    p.add_argument('--template-dir', '-t',
+                   default='/etc/haproxy/templates')
+    return p.parse_args()
+
+def discover_services():
+    services = []
+    for k in os.environ:
+        mo = re_url.match(k)
+
+        if mo:
+            parts = urlparse.urlparse(os.environ[k])
+            remote_host,remote_port = parts.netloc.split(':')
+            service_name = '%(name)s-%(port)s' % mo.groupdict()
+
+            services.append({
+                'remote_name': mo.group('name'),
+                'remote_addr': remote_host,
+                'remote_port': remote_port,
+                'remote_proto': parts.scheme,
+                'local_port': mo.group('port'),
+                'service_name': service_name,
+            })
+
+    return services
+
+def main():
+    args = parse_args()
+    services = discover_services()
+
+    env = Environment(loader=FileSystemLoader(['.',
+                                               args.template_dir]))
+    template = env.get_template('haproxy.cfg.tmpl')
+    with open(args.output, 'w') as fd:
+        fd.write(template.render(services=services))
+
+    if args.no_start:
+        return
+
+    os.execlp('haproxy', 'haproxy', '-f', args.output, '-db')
+
+if __name__ == '__main__':
+    main()
+
diff --git a/docker/common/heat/heat-api-cfn/check.sh b/docker/common/heat/heat-api-cfn/check.sh
new file mode 100755
index 0000000000000000000000000000000000000000..ee03dc6d23e3488433ffda423f567aabda4f9e73
--- /dev/null
+++ b/docker/common/heat/heat-api-cfn/check.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+RES=0
+
+. /openrc
+if ! keystone token-get > /dev/null; then
+    echo "ERROR: keystone token-get failed" >&2
+    RES=1
+else
+    if ! heat stack-list > /dev/null; then
+        echo "ERROR: heat stack-list failed" >&2
+        RES=1
+    fi
+fi
+
+exit $RES
diff --git a/docker/common/heat/heat-api-cfn/start.sh b/docker/common/heat/heat-api-cfn/start.sh
new file mode 100755
index 0000000000000000000000000000000000000000..bcd72250b46dd4aba22490428f0f9e060fa35453
--- /dev/null
+++ b/docker/common/heat/heat-api-cfn/start.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+set -e
+
+. /opt/kolla/kolla-common.sh
+. /opt/kolla/config-heat.sh
+
+check_required_vars KEYSTONE_ADMIN_TOKEN KEYSTONE_ADMIN_SERVICE_HOST \
+                    HEAT_CFN_KEYSTONE_USER HEAT_CFN_KEYSTONE_PASSWORD \
+                    KEYSTONE_AUTH_PROTOCOL KEYSTONE_ADMIN_SERVICE_PORT \
+                    ADMIN_TENANT_NAME HEAT_API_CFN_SERVICE_HOST \
+                    HEAT_API_CFN_SERVICE_PORT
+
+fail_unless_os_service_running keystone
+
+export SERVICE_TOKEN="${KEYSTONE_ADMIN_TOKEN}"
+export SERVICE_ENDPOINT="${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}/v2.0"
+
+crux user-create -n ${HEAT_CFN_KEYSTONE_USER} \
+    -p ${HEAT_CFN_KEYSTONE_PASSWORD} \
+    -t ${ADMIN_TENANT_NAME} \
+    -r admin
+
+crux endpoint-create --remove-all -n ${HEAT_CFN_KEYSTONE_USER} -t cloudformation \
+    -I "${KEYSTONE_AUTH_PROTOCOL}://${HEAT_API_CFN_SERVICE_HOST}:${HEAT_API_CFN_SERVICE_PORT}/v1" \
+    -P "${KEYSTONE_AUTH_PROTOCOL}://${HEAT_API_CFN_SERVICE_HOST}:${HEAT_API_CFN_SERVICE_PORT}/v1" \
+    -A "${KEYSTONE_AUTH_PROTOCOL}://${HEAT_API_CFN_SERVICE_HOST}:${HEAT_API_CFN_SERVICE_PORT}/v1"
+
+exec /usr/bin/heat-api-cfn
diff --git a/docker/common/heat/heat-api/check.sh b/docker/common/heat/heat-api/check.sh
new file mode 100755
index 0000000000000000000000000000000000000000..ee03dc6d23e3488433ffda423f567aabda4f9e73
--- /dev/null
+++ b/docker/common/heat/heat-api/check.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+RES=0
+
+. /openrc
+if ! keystone token-get > /dev/null; then
+    echo "ERROR: keystone token-get failed" >&2
+    RES=1
+else
+    if ! heat stack-list > /dev/null; then
+        echo "ERROR: heat stack-list failed" >&2
+        RES=1
+    fi
+fi
+
+exit $RES
diff --git a/docker/common/heat/heat-api/start.sh b/docker/common/heat/heat-api/start.sh
new file mode 100755
index 0000000000000000000000000000000000000000..b57aaa710b880d444e680b9520f71112b9a94f35
--- /dev/null
+++ b/docker/common/heat/heat-api/start.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+set -e
+
+. /opt/kolla/kolla-common.sh
+. /opt/kolla/config-heat.sh
+
+check_required_vars KEYSTONE_ADMIN_TOKEN KEYSTONE_ADMIN_SERVICE_HOST \
+                    HEAT_KEYSTONE_USER HEAT_KEYSTONE_PASSWORD \
+                    KEYSTONE_AUTH_PROTOCOL ADMIN_TENANT_NAME \
+                    HEAT_API_SERVICE_HOST PUBLIC_IP
+
+fail_unless_os_service_running keystone
+
+export SERVICE_TOKEN="${KEYSTONE_ADMIN_TOKEN}"
+export SERVICE_ENDPOINT="${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:35357/v2.0"
+crux user-create -n ${HEAT_KEYSTONE_USER} \
+    -p ${HEAT_KEYSTONE_PASSWORD} \
+    -t ${ADMIN_TENANT_NAME} \
+    -r admin
+
+crux endpoint-create --remove-all -n ${HEAT_KEYSTONE_USER} -t orchestration \
+    -I "${KEYSTONE_AUTH_PROTOCOL}://${HEAT_API_SERVICE_HOST}:8004/v1/%(tenant_id)s" \
+    -P "${KEYSTONE_AUTH_PROTOCOL}://${PUBLIC_IP}:8004/v1/%(tenant_id)s" \
+    -A "${KEYSTONE_AUTH_PROTOCOL}://${HEAT_API_SERVICE_HOST}:8004/v1/%(tenant_id)s"
+
+# will use crux after https://github.com/larsks/crux/issues/1 is implemented
+openstack role list --os-token="${KEYSTONE_ADMIN_TOKEN}" --os-url $SERVICE_ENDPOINT -f csv | tail -n +2 | awk -F, '{print $2}' | grep heat_stack_user || keystone role-create --name heat_stack_user
+
+exec /usr/bin/heat-api
diff --git a/docker/common/heat/heat-base/config-heat.sh b/docker/common/heat/heat-base/config-heat.sh
new file mode 100755
index 0000000000000000000000000000000000000000..74b2718a4b71bc31479dfd43a2f1cf1748ccebe3
--- /dev/null
+++ b/docker/common/heat/heat-base/config-heat.sh
@@ -0,0 +1,67 @@
+#!/bin/bash
+
+set -e
+
+. /opt/kolla/kolla-common.sh
+
+: ${ADMIN_TENANT_NAME:=admin}
+: ${HEAT_DB_NAME:=heat}
+: ${HEAT_DB_USER:=heat}
+: ${HEAT_KEYSTONE_USER:=heat}
+: ${HEAT_CFN_KEYSTONE_USER:=heat_cfn}
+: ${KEYSTONE_AUTH_PROTOCOL:=http}
+: ${PUBLIC_IP:=$HEAT_API_PORT_8004_TCP_ADDR}
+: ${RABBIT_USER:=guest}
+: ${RABBIT_PASSWORD:=guest}
+
+check_required_vars HEAT_DB_PASSWORD HEAT_KEYSTONE_PASSWORD \
+                    KEYSTONE_PUBLIC_SERVICE_HOST RABBITMQ_SERVICE_HOST
+
+fail_unless_db
+dump_vars
+
+cat > /openrc <<EOF
+export OS_AUTH_URL="http://${KEYSTONE_PUBLIC_SERVICE_HOST}:5000/v2.0"
+export OS_USERNAME="${HEAT_KEYSTONE_USER}"
+export OS_PASSWORD="${HEAT_KEYSTONE_PASSWORD}"
+export OS_TENANT_NAME="${ADMIN_TENANT_NAME}"
+EOF
+
+crudini --set /etc/heat/heat.conf DEFAULT log_file \
+    ""
+crudini --set /etc/heat/heat.conf DEFAULT use_stderr \
+    true
+crudini --set /etc/heat/heat.conf DEFAULT rpc_backend \
+    heat.openstack.common.rpc.impl_kombu
+crudini --set /etc/heat/heat.conf DEFAULT rabbit_host \
+    "${RABBITMQ_SERVICE_HOST}"
+crudini --set /etc/heat/heat.conf DEFAULT rabbit_userid \
+    "${RABBIT_USER}"
+crudini --set /etc/heat/heat.conf DEFAULT rabbit_password \
+    "${RABBIT_PASSWORD}"
+
+crudini --set /etc/heat/heat.conf database connection \
+    mysql://${HEAT_DB_USER}:${HEAT_DB_PASSWORD}@${MARIADB_SERVICE_HOST}/${HEAT_DB_NAME}
+
+crudini --set /etc/heat/heat.conf keystone_authtoken auth_protocol \
+    "${KEYSTONE_AUTH_PROTOCOL}"
+crudini --set /etc/heat/heat.conf keystone_authtoken auth_host \
+    "${KEYSTONE_PUBLIC_SERVICE_HOST}"
+crudini --set /etc/heat/heat.conf keystone_authtoken auth_port \
+    "${KEYSTONE_PUBLIC_SERVICE_PORT}"
+crudini --set /etc/heat/heat.conf keystone_authtoken auth_uri \
+    "${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_PUBLIC_SERVICE_HOST}:${KEYSTONE_PUBLIC_SERVICE_PORT}/v2.0"
+crudini --set /etc/heat/heat.conf  keystone_authtoken admin_tenant_name \
+    "${ADMIN_TENANT_NAME}"
+crudini --set /etc/heat/heat.conf keystone_authtoken admin_user \
+    "${HEAT_KEYSTONE_USER}"
+crudini --set /etc/heat/heat.conf keystone_authtoken admin_password \
+    "${HEAT_KEYSTONE_PASSWORD}"
+
+crudini --set /etc/heat/heat.conf ec2authtoken auth_uri \
+    "${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_PUBLIC_SERVICE_HOST}:${KEYSTONE_PUBLIC_SERVICE_PORT}/v2.0"
+
+crudini --set /etc/heat/heat.conf DEFAULT heat_metadata_server_url \
+    http://${HEAT_API_CFN_URL_HOST}:${HEAT_API_CFN_SERVICE_PORT}
+crudini --set /etc/heat/heat.conf DEFAULT heat_waitcondition_server_url \
+    http://${HEAT_API_CFN_URL_HOST}:${HEAT_API_CFN_SERVICE_PORT}/v1/waitcondition
diff --git a/docker/common/heat/heat-engine/start.sh b/docker/common/heat/heat-engine/start.sh
new file mode 100755
index 0000000000000000000000000000000000000000..2dfc78e9280323de3ad4650e7b0e65c10f1f34c7
--- /dev/null
+++ b/docker/common/heat/heat-engine/start.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+. /opt/kolla/kolla-common.sh
+. /opt/kolla/config-heat.sh
+
+check_required_vars HEAT_DB_NAME HEAT_DB_USER HEAT_DB_PASSWORD
+fail_unless_db
+
+mysql -h ${MARIADB_SERVICE_HOST} -u root -p${DB_ROOT_PASSWORD} mysql <<EOF
+CREATE DATABASE IF NOT EXISTS ${HEAT_DB_NAME} DEFAULT CHARACTER SET utf8;
+GRANT ALL PRIVILEGES ON ${HEAT_DB_NAME}.* TO
+    '${HEAT_DB_USER}'@'%' IDENTIFIED BY '${HEAT_DB_PASSWORD}'
+EOF
+
+/usr/bin/heat-manage db_sync
+
+exec /usr/bin/heat-engine
diff --git a/docker/common/horizon/start.sh b/docker/common/horizon/start.sh
new file mode 100755
index 0000000000000000000000000000000000000000..4e720bb879a8fd57f62e387d809274892ae561f4
--- /dev/null
+++ b/docker/common/horizon/start.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+set -e
+
+: ${HORIZON_KEYSTONE_USER:=horizon}
+
+. /opt/kolla/kolla-common.sh
+
+fail_unless_os_service_running keystone
+fail_unless_os_service_running glance
+fail_unless_os_service_running nova
+
+export SERVICE_TOKEN="${KEYSTONE_ADMIN_TOKEN}"
+export SERVICE_ENDPOINT="${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:35357/v2.0"
+
+cfg=/etc/openstack-dashboard/local_settings
+httpdcfg=/etc/httpd/conf.d/openstack-dashboard.conf
+
+sed -ri 's/ALLOWED_HOSTS = \['\''horizon.example.com'\'', '\''localhost'\''\]/ALLOWED_HOSTS = \['\''*'\'', \]/' /etc/openstack-dashboard/local_settings
+
+sed -ri 's/OPENSTACK_KEYSTONE_URL = \"http:\/\/%s:5000\/v2.0\" % OPENSTACK_HOST/OPENSTACK_KEYSTONE_URL = \"http:\/\/'"$KEYSTONE_PUBLIC_SERVICE_HOST"':5000\/v2.0\"/' /etc/openstack-dashboard/local_settings
+
+sed -ri 's/OPENSTACK_HOST = \"127.0.0.1\"/OPENSTACK_HOST = \"'"$KEYSTONE_PUBLIC_SERVICE_HOST"'\" /' /etc/openstack-dashboard/local_settings
+
+# Make sure we launch horizon using the default value for WEBROOT, which is
+# '/'.
+sed -ri '/^WEBROOT =.+/d' $cfg
+sed -ri 's,^(WSGIScriptAlias) /dashboard (/usr/share/openstack-dashboard/openstack_dashboard/wsgi/django.wsgi),\1 / \2,' $httpdcfg
+sed -ri 's,^(Alias /dashboard)(/static /usr/share/openstack-dashboard/static),Alias \2,' $httpdcfg
+
+# This step is required because of:
+# https://bugzilla.redhat.com/show_bug.cgi?id=1220070
+# Running this in the Dockerfile didn't fix the HTTP/500 as a result of the
+# missing compress action.
+python /usr/share/openstack-dashboard/manage.py compress
+
+/usr/sbin/httpd -DFOREGROUND
diff --git a/docker/common/keystone/check.sh b/docker/common/keystone/check.sh
new file mode 100755
index 0000000000000000000000000000000000000000..ca484478485d9624c43b6832cf626051ac420c50
--- /dev/null
+++ b/docker/common/keystone/check.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+RES=0
+
+. /openrc
+if ! keystone token-get > /dev/null; then
+    echo "ERROR: keystone token-get failed" >&2
+    RES=1
+fi
+
+exit $RES
+
diff --git a/docker/common/keystone/start.sh b/docker/common/keystone/start.sh
new file mode 100755
index 0000000000000000000000000000000000000000..6dfebe06058b269b692ffa9ccffeed136ed90b86
--- /dev/null
+++ b/docker/common/keystone/start.sh
@@ -0,0 +1,162 @@
+#!/bin/bash
+
+set -e
+
+# Run Kolla common script
+echo "Running the kolla-common script"
+. /opt/kolla/kolla-common.sh
+
+# Credentials, token, etc..
+: ${ADMIN_USER:=admin}
+: ${ADMIN_USER_PASSWORD:=password}
+: ${ADMIN_TENANT_NAME:=admin}
+: ${KEYSTONE_USER:=keystone}
+: ${KEYSTONE_ADMIN_PASSWORD:=password}
+: ${KEYSTONE_ADMIN_TOKEN:=changeme}
+# DB Settings
+: ${INIT_DB:=true}
+: ${KEYSTONE_DB_NAME:=keystone}
+: ${KEYSTONE_DB_USER:=keystone}
+: ${DB_ROOT_PASSWORD:=password}
+: ${MARIADB_SERVICE_HOST:=$PUBLIC_IP}
+: ${KEYSTONE_DB_PASSWORD:=password}
+# Service Addresses/Ports/Version
+: ${KEYSTONE_PUBLIC_SERVICE_HOST:=$PUBLIC_IP}
+: ${KEYSTONE_ADMIN_SERVICE_HOST:=$PUBLIC_IP}
+: ${KEYSTONE_PUBLIC_SERVICE_PORT:=5000}
+: ${KEYSTONE_ADMIN_SERVICE_PORT:=35357}
+: ${KEYSTONE_API_VERSION:=2.0}
+# Logging
+: ${LOG_FILE:=/var/log/keystone/keystone.log}
+: ${VERBOSE_LOGGING:=true}
+: ${DEBUG_LOGGING:=false}
+: ${USE_STDERR:=false}
+# Token provider, driver, etc..
+: ${TOKEN_PROVIDER:=uuid}
+: ${TOKEN_DRIVER:=sql}
+
+## Check DB connectivity and required variables
+echo "Checking connectivity to the DB"
+fail_unless_db
+echo "Checking for required variables"
+check_required_vars KEYSTONE_ADMIN_TOKEN KEYSTONE_DB_PASSWORD \
+                    KEYSTONE_ADMIN_PASSWORD ADMIN_TENANT_NAME \
+                    KEYSTONE_PUBLIC_SERVICE_HOST KEYSTONE_ADMIN_SERVICE_HOST \
+                    PUBLIC_IP
+dump_vars
+
+# Setup the Keystone DB
+echo "Setting up Keystone DB"
+mysql -h ${MARIADB_SERVICE_HOST} -u root -p"${DB_ROOT_PASSWORD}" mysql <<EOF
+CREATE DATABASE IF NOT EXISTS ${KEYSTONE_DB_NAME};
+GRANT ALL PRIVILEGES ON ${KEYSTONE_DB_NAME}.* TO
+    '${KEYSTONE_DB_USER}'@'%' IDENTIFIED BY '${KEYSTONE_DB_PASSWORD}'
+EOF
+
+# File path and name used by crudini tool
+cfg=/etc/keystone/keystone.conf
+
+# Token Configuration
+echo "Configuring keystone.conf"
+crudini --set $cfg \
+    DEFAULT \
+    admin_token \
+    "${KEYSTONE_ADMIN_TOKEN}"
+
+# Database Configuration
+crudini --set $cfg \
+    database \
+    connection \
+    "mysql://${KEYSTONE_DB_USER}:${KEYSTONE_DB_PASSWORD}@${MARIADB_SERVICE_HOST}/${KEYSTONE_DB_NAME}"
+
+# Logging
+crudini --del $cfg \
+    DEFAULT \
+    log_dir
+crudini --set $cfg \
+    DEFAULT \
+    log_file \
+    ${LOG_FILE}
+crudini --set $cfg \
+    DEFAULT \
+    verbose \
+    ${VERBOSE_LOGGING}
+crudini --set $cfg \
+    DEFAULT \
+    debug \
+    ${DEBUG_LOGGING}
+crudini --set $cfg \
+    DEFAULT \
+    use_stderr \
+    ${USE_STDERR}
+
+# Token Management
+crudini --set $cfg \
+    token \
+    provider \
+    keystone.token.providers."${TOKEN_PROVIDER}".Provider
+crudini --set $cfg \
+    token \
+    driver \
+    keystone.token.persistence.backends."${TOKEN_DRIVER}".Token
+crudini --set $cfg \
+    revoke \
+    driver \
+    keystone.contrib.revoke.backends."${TOKEN_DRIVER}".Revoke
+
+# Setup the openrc auth file
+cat > /openrc <<EOF
+export OS_AUTH_URL=http://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}/v${KEYSTONE_API_VERSION}
+export OS_USERNAME=${KEYSTONE_USER}
+export OS_PASSWORD=${KEYSTONE_ADMIN_PASSWORD}
+export OS_TENANT_NAME=${ADMIN_TENANT_NAME}
+EOF
+
+# Run PKI Setup script
+echo "Setting up PKI"
+/usr/bin/keystone-manage pki_setup --keystone-user keystone --keystone-group keystone
+
+# Fix permissions
+chown -R keystone:keystone /var/log/keystone
+chown -R keystone:keystone /etc/keystone/ssl
+chmod -R o-rwx /etc/keystone/ssl
+
+# Initialize the Keystone DB
+echo "Initializing Keystone DB"
+if [ "${INIT_DB}" == "true" ] ; then
+    su -s /bin/bash -c "keystone-manage db_sync" keystone
+fi
+
+# Start Keystone
+echo "Starting Keystone"
+/usr/bin/keystone-all &
+PID=$!
+
+# Export Keystone service environment variables
+export SERVICE_TOKEN="${KEYSTONE_ADMIN_TOKEN}"
+export SERVICE_ENDPOINT="http://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}/v${KEYSTONE_API_VERSION}"
+
+# Check to make sure the service is running
+echo "Verifying Keystone is running"
+while ! curl -o /dev/null -s --fail ${SERVICE_ENDPOINT}; do
+    echo "waiting for Keystone @ ${SERVICE_ENDPOINT}"
+    sleep 1;
+done
+echo "keystone is active @ ${SERVICE_ENDPOINT}"
+
+# Create Keystone tenant, user, role, service and endpoints
+echo "Creating Keystone tenant, user, role, service and endpoints"
+crux user-create --update \
+    -n ${ADMIN_USER} -p "${ADMIN_USER_PASSWORD}" \
+    -t ${ADMIN_TENANT_NAME} -r admin
+crux user-create --update \
+    -n ${KEYSTONE_USER} -p "${KEYSTONE_ADMIN_PASSWORD}" \
+    -t ${ADMIN_TENANT_NAME} -r admin
+crux endpoint-create --remove-all \
+    -n keystone -t identity \
+    -I "http://${KEYSTONE_PUBLIC_SERVICE_HOST}:${KEYSTONE_PUBLIC_SERVICE_PORT}/v${KEYSTONE_API_VERSION}" \
+    -A "http://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}/v${KEYSTONE_API_VERSION}" \
+    -P "http://${KEYSTONE_PUBLIC_SERVICE_HOST}:${KEYSTONE_PUBLIC_SERVICE_PORT}/v${KEYSTONE_API_VERSION}"
+
+# Wait on all jobs to exit before proceeding (see man wait)
+wait
diff --git a/docker/common/magnum/magnum-api/check.sh b/docker/common/magnum/magnum-api/check.sh
new file mode 100755
index 0000000000000000000000000000000000000000..ee03dc6d23e3488433ffda423f567aabda4f9e73
--- /dev/null
+++ b/docker/common/magnum/magnum-api/check.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+RES=0
+
+. /openrc
+if ! keystone token-get > /dev/null; then
+    echo "ERROR: keystone token-get failed" >&2
+    RES=1
+else
+    if ! heat stack-list > /dev/null; then
+        echo "ERROR: heat stack-list failed" >&2
+        RES=1
+    fi
+fi
+
+exit $RES
diff --git a/docker/common/magnum/magnum-api/start.sh b/docker/common/magnum/magnum-api/start.sh
new file mode 100755
index 0000000000000000000000000000000000000000..00a51b3cdfa31b34cc9afecdd3c8e2399f269c21
--- /dev/null
+++ b/docker/common/magnum/magnum-api/start.sh
@@ -0,0 +1,27 @@
+#!/bin/bash
+set -e
+
+. /opt/kolla/kolla-common.sh
+. /opt/kolla/config-magnum.sh
+
+check_required_vars KEYSTONE_ADMIN_TOKEN KEYSTONE_ADMIN_SERVICE_HOST \
+                    MAGNUM_KEYSTONE_USER MAGNUM_KEYSTONE_PASSWORD \
+                    KEYSTONE_AUTH_PROTOCOL ADMIN_TENANT_NAME \
+                    MAGNUM_API_SERVICE_HOST KEYSTONE_ADMIN_SERVICE_PORT \
+                    MAGNUM_API_SERVICE_PORT
+
+fail_unless_os_service_running keystone
+
+export SERVICE_TOKEN="${KEYSTONE_ADMIN_TOKEN}"
+export SERVICE_ENDPOINT="${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}/v2.0"
+crux user-create -n ${MAGNUM_KEYSTONE_USER} \
+    -p ${MAGNUM_KEYSTONE_PASSWORD} \
+    -t ${ADMIN_TENANT_NAME} \
+    -r admin
+
+crux endpoint-create --remove-all -n ${MAGNUM_KEYSTONE_USER} -t container \
+    -I "${KEYSTONE_AUTH_PROTOCOL}://${MAGNUM_API_SERVICE_HOST}:${MAGNUM_API_SERVICE_PORT}/v1" \
+    -P "${KEYSTONE_AUTH_PROTOCOL}://${MAGNUM_API_SERVICE_HOST}:${MAGNUM_API_SERVICE_PORT}/v1" \
+    -A "${KEYSTONE_AUTH_PROTOCOL}://${MAGNUM_API_SERVICE_HOST}:${MAGNUM_API_SERVICE_PORT}/v1"
+
+exec /usr/bin/magnum-api
diff --git a/docker/common/magnum/magnum-base/config-magnum.sh b/docker/common/magnum/magnum-base/config-magnum.sh
new file mode 100755
index 0000000000000000000000000000000000000000..03599d359eb2c874e298443c891e7d7155225234
--- /dev/null
+++ b/docker/common/magnum/magnum-base/config-magnum.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+
+set -e
+
+. /opt/kolla/kolla-common.sh
+
+check_required_vars MAGNUM_DB_PASSWORD MAGNUM_KEYSTONE_PASSWORD \
+                    KEYSTONE_PUBLIC_SERVICE_HOST KEYSTONE_PUBLIC_SERVICE_PORT \
+                    MAGNUM_KEYSTONE_USER ADMIN_TENANT_NAME \
+                    MAGNUM_DB_USER MAGNUM_DB_NAME KEYSTONE_AUTH_PROTOCOL \
+                    KEYSTONE_PUBLIC_SERVICE_PORT RABBITMQ_SERVICE_HOST \
+                    VERBOSE_LOGGING DEBUG_LOGGING
+
+fail_unless_db
+dump_vars
+
+cat > /openrc <<EOF
+export OS_AUTH_URL="http://${KEYSTONE_PUBLIC_SERVICE_HOST}:${KEYSTONE_PUBLIC_SERVICE_PORT}/v2.0"
+export OS_USERNAME="${MAGNUM_KEYSTONE_USER}"
+export OS_PASSWORD="${MAGNUM_KEYSTONE_PASSWORD}"
+export OS_TENANT_NAME="${ADMIN_TENANT_NAME}"
+EOF
+
+cfg=/etc/magnum/magnum.conf
+
+crudini --set $cfg DEFAULT log_file ""
+crudini --set $cfg DEFAULT verbose "${VERBOSE_LOGGING}"
+crudini --set $cfg DEFAULT debug "${DEBUG_LOGGING}"
+crudini --set $cfg DEFAULT use_stderr true
+crudini --set $cfg DEFAULT rpc_backend magnum.openstack.common.rpc.impl_kombu
+crudini --set $cfg DEFAULT admin_user admin
+crudini --set $cfg oslo_messaging_rabbit rabbit_host ${RABBITMQ_SERVICE_HOST}
+crudini --set $cfg oslo_messaging_rabbit rabbit_userid ${RABBIT_USER}
+crudini --set $cfg oslo_messaging_rabbit rabbit_password ${RABBIT_PASSWORD}
+crudini --set $cfg database connection \
+    mysql://${MAGNUM_DB_USER}:${MAGNUM_DB_PASSWORD}@${MARIADB_SERVICE_HOST}/${MAGNUM_DB_NAME}
+crudini --set $cfg keystone_authtoken auth_protocol "${KEYSTONE_AUTH_PROTOCOL}"
+crudini --set $cfg keystone_authtoken auth_host "${KEYSTONE_PUBLIC_SERVICE_HOST}"
+crudini --set $cfg keystone_authtoken auth_port "${KEYSTONE_PUBLIC_SERVICE_PORT}"
+crudini --set $cfg keystone_authtoken auth_uri \
+    "${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_PUBLIC_SERVICE_HOST}:${KEYSTONE_PUBLIC_SERVICE_PORT}/v2.0"
+crudini --set $cfg  keystone_authtoken admin_tenant_name "${ADMIN_TENANT_NAME}"
+crudini --set $cfg keystone_authtoken admin_user "${MAGNUM_KEYSTONE_USER}"
+crudini --set $cfg keystone_authtoken admin_password \
+    "${MAGNUM_KEYSTONE_PASSWORD}"
+crudini --set $cfg api host ${MAGNUM_API_SERVICE_HOST}
diff --git a/docker/common/magnum/magnum-conductor/start.sh b/docker/common/magnum/magnum-conductor/start.sh
new file mode 100755
index 0000000000000000000000000000000000000000..4cf1291a393c92d093d18497e0ca0c7b334b0c85
--- /dev/null
+++ b/docker/common/magnum/magnum-conductor/start.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+. /opt/kolla/kolla-common.sh
+. /opt/kolla/config-magnum.sh
+
+check_required_vars MAGNUM_DB_NAME MAGNUM_DB_USER MAGNUM_DB_PASSWORD
+fail_unless_db
+
+mysql -h ${MARIADB_SERVICE_HOST} -u root -p${DB_ROOT_PASSWORD} mysql <<EOF
+CREATE DATABASE IF NOT EXISTS ${MAGNUM_DB_NAME} DEFAULT CHARACTER SET utf8;
+GRANT ALL PRIVILEGES ON ${MAGNUM_DB_NAME}.* TO
+    '${MAGNUM_DB_USER}'@'%' IDENTIFIED BY '${MAGNUM_DB_PASSWORD}'
+EOF
+
+/usr/bin/magnum-db-manage upgrade
+
+exec /usr/bin/magnum-conductor
diff --git a/docker/common/mariadb-app/config-mysql.sh b/docker/common/mariadb-app/config-mysql.sh
new file mode 100755
index 0000000000000000000000000000000000000000..b11939b8bbaccf0d040b18d4ef9b3af21dfa582a
--- /dev/null
+++ b/docker/common/mariadb-app/config-mysql.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+. /opt/kolla/kolla-common.sh
+
+: ${BIND_ADDRESS:=$PUBLIC_IP}
+: ${DB_ROOT_PASSWORD:=$DB_ROOT_PASSWORD}
+: ${DEFAULT_STORAGE_ENGINE:=innodb}
+: ${COLLATION_SERVER:=utf8_general_ci}
+: ${INIT_CONNECT:=SET NAMES utf8}
+: ${CHAR_SET_SERVER:=utf8}
+: ${INNODB_FILE_PER_TABLE:=true}
+: ${DATADIR:=/var/lib/mysql}
+: ${TEMP_FILE:='/tmp/mysql-first-time.sql'}
+
+server_cnf=/etc/my.cnf.d/server.cnf
+
+crudini --set $server_cnf mysqld bind-address $BIND_ADDRESS
+crudini --set $server_cnf mysqld default-storage-engine $DEFAULT_STORAGE_ENGINE
+crudini --set $server_cnf mysqld collation-server $COLLATION_SERVER
+crudini --set $server_cnf mysqld init-connect "'${INIT_CONNECT}'"
+crudini --set $server_cnf mysqld character-set-server $CHAR_SET_SERVER
+if [ "${INNODB_FILE_PER_TABLE}" == "true" ] || ["${INNODB_FILE_PER_TABLE}" == "True" ] ; then
+    crudini --set $server_cnf mysqld innodb_file_per_table 1
+fi
diff --git a/docker/centos/binary/mariadb-app/mysql-entrypoint.sh b/docker/common/mariadb-app/mysql-entrypoint.sh
similarity index 93%
rename from docker/centos/binary/mariadb-app/mysql-entrypoint.sh
rename to docker/common/mariadb-app/mysql-entrypoint.sh
index 6dece43cadab165fe3a6079bc351e5cc843a05d5..aa04a84b0a6a61fe5ddff057388ffff4ba038c15 100755
--- a/docker/centos/binary/mariadb-app/mysql-entrypoint.sh
+++ b/docker/common/mariadb-app/mysql-entrypoint.sh
@@ -32,7 +32,7 @@ EOSQL
     fi
 
     if [ "$MARIADB_USER" -a "$MARIADB_PASSWORD" ]; then
-        echo "CREATE USER '$MARIADB_USER'@'%' IDENTIFIED BY '$MARIADB_PASSWORD' ;" >> "$TEMP_FILE"
+       echo "CREATE USER '$MARIADB_USER'@'%' IDENTIFIED BY '$MARIADB_PASSWORD' ;" >> "$TEMP_FILE"
 
         if [ "$MARIADB_DATABASE" ]; then
             echo "GRANT ALL ON $MARIADB_DATABASE.* TO '$MARIADB_USER'@'%' ;" >> "$TEMP_FILE"
diff --git a/docker/common/neutron/neutron-agents/check-scripts/check-dhcp-agent.sh b/docker/common/neutron/neutron-agents/check-scripts/check-dhcp-agent.sh
new file mode 100755
index 0000000000000000000000000000000000000000..7dda736efbc890074d58bead1d612667551f1b3c
--- /dev/null
+++ b/docker/common/neutron/neutron-agents/check-scripts/check-dhcp-agent.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+RES=0
+
+check=$(/usr/bin/neutron agent-list | awk '/ DHCP / {print $9}')
+error="ERROR: Neutron DHCP Agent is not alive."
+
+if [[ $check != ":-)" ]]; then
+    echo $error >&2
+    RES=1
+fi
+
+exit $RES
diff --git a/docker/common/neutron/neutron-agents/check-scripts/check-l3-agent.sh b/docker/common/neutron/neutron-agents/check-scripts/check-l3-agent.sh
new file mode 100755
index 0000000000000000000000000000000000000000..d32c1e272f8d138a8f342f8204cb7476cdd4b6ba
--- /dev/null
+++ b/docker/common/neutron/neutron-agents/check-scripts/check-l3-agent.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+RES=0
+
+check=$(/usr/bin/neutron agent-list | awk '/ L3 / {print $9}')
+error="ERROR: Neutron L3 Agent is not alive."
+
+if [[ $check != ":-)" ]]; then
+    echo $error >&2
+    RES=1
+fi
+
+exit $RES
diff --git a/docker/common/neutron/neutron-agents/check-scripts/check-linuxbridge-agent.sh b/docker/common/neutron/neutron-agents/check-scripts/check-linuxbridge-agent.sh
new file mode 100755
index 0000000000000000000000000000000000000000..4485fc1ec915bda80e5fa0cdf47cf7a23eb52a44
--- /dev/null
+++ b/docker/common/neutron/neutron-agents/check-scripts/check-linuxbridge-agent.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+RES=0
+
+check=$(/usr/bin/neutron agent-list | awk '/ Linux / {print $10}')
+error="ERROR: Neutron Linux Bridge agent is not alive."
+
+if [[ $check != ":-)" ]]; then
+    echo $error >&2
+    RES=1
+fi
+
+exit $RES
diff --git a/docker/common/neutron/neutron-agents/check-scripts/check-metadata-agent.sh b/docker/common/neutron/neutron-agents/check-scripts/check-metadata-agent.sh
new file mode 100755
index 0000000000000000000000000000000000000000..fd1c6812b4c29190c12a6a5f4357a7a33cf321f1
--- /dev/null
+++ b/docker/common/neutron/neutron-agents/check-scripts/check-metadata-agent.sh
@@ -0,0 +1,13 @@
+#!/bin/bash
+
+RES=0
+
+check=$(/usr/bin/neutron agent-list | awk '/ Metadata / {print $9}')
+error="ERROR: Neutron Metadata Agent is not alive."
+
+if [[ $check != ":-)" ]]; then
+    echo $error >&2
+    RES=1
+fi
+
+exit $RES
diff --git a/docker/common/neutron/neutron-agents/config-scripts/config-dhcp-agent.sh b/docker/common/neutron/neutron-agents/config-scripts/config-dhcp-agent.sh
new file mode 100755
index 0000000000000000000000000000000000000000..db71678b1dc81882bb56cd312973cc6cdbd4dc4e
--- /dev/null
+++ b/docker/common/neutron/neutron-agents/config-scripts/config-dhcp-agent.sh
@@ -0,0 +1,88 @@
+#!/bin/bash
+
+set -e
+
+. /opt/kolla/config-neutron.sh
+. /opt/kolla/config-sudoers.sh
+
+: ${DHCP_DRIVER:=neutron.agent.linux.dhcp.Dnsmasq}
+: ${USE_NAMESPACES:=true}
+: ${DELETE_NAMESPACES:=true}
+: ${DNSMASQ_CONFIG_FILE:=/etc/neutron/dnsmasq/dnsmasq-neutron.conf}
+: ${ROOT_HELPER:=sudo neutron-rootwrap /etc/neutron/rootwrap.conf}
+
+mkdir -p $(dirname $DNSMASQ_CONFIG_FILE)
+
+check_required_vars VERBOSE_LOGGING DEBUG_LOGGING MECHANISM_DRIVERS \
+                    DHCP_DRIVER USE_NAMESPACES DELETE_NAMESPACES \
+                    NEUTRON_LOG_DIR DNSMASQ_CONFIG_FILE \
+
+cfg=/etc/neutron/dhcp_agent.ini
+neutron_conf=/etc/neutron/neutron.conf
+
+# Workaround bug in dhclient in cirros images which does not correctly
+# handle setting checksums of packets when using hardware with checksum
+# offloading.  See:
+# https://www.rdoproject.org/forum/discussion/567/packstack-allinone-grizzly-cirros-image-cannot-get-a-dhcp-address-when-a-centos-image-can/p1
+
+/usr/sbin/iptables -A POSTROUTING -t mangle -p udp --dport bootpc \
+    -j CHECKSUM --checksum-fill
+
+if [[ ${MECHANISM_DRIVERS} =~ linuxbridge ]]; then
+    interface_driver="neutron.agent.linux.interface.BridgeInterfaceDriver"
+elif [[ ${MECHANISM_DRIVERS} == "openvswitch" ]]; then
+    interface_driver="neutron.agent.linux.interface.OVSInterfaceDriver"
+fi
+
+# Logging
+crudini --set $neutron_conf \
+    DEFAULT \
+    log_file \
+    "${NEUTRON_DHCP_AGENT_LOG_FILE}"
+
+# Configure dhcp_agent.ini
+crudini --set $cfg \
+    DEFAULT \
+    verbose \
+    "${VERBOSE_LOGGING}"
+crudini --set $cfg \
+    DEFAULT \
+    debug \
+    "${DEBUG_LOGGING}"
+crudini --set $cfg \
+    DEFAULT \
+    interface_driver \
+    "$interface_driver"
+crudini --set $cfg \
+    DEFAULT \
+    dhcp_driver \
+    "${DHCP_DRIVER}"
+crudini --set $cfg \
+    DEFAULT \
+    use_namespaces \
+    "${USE_NAMESPACES}"
+crudini --set $cfg \
+    DEFAULT \
+    delete_namespaces \
+    "${DELETE_NAMESPACES}"
+crudini --set $cfg \
+    DEFAULT \
+    dnsmasq_config_file \
+    "${DNSMASQ_CONFIG_FILE}"
+crudini --set $cfg \
+    DEFAULT \
+    root_helper \
+    "${ROOT_HELPER}"
+
+cat > ${DNSMASQ_CONFIG_FILE} <<EOF
+dhcp-option-force=26,1450
+log-facility=${NEUTRON_LOG_DIR}/neutron-dnsmasq.log
+EOF
+
+# Remove any existing qdhcp namespaces
+ip netns list | grep qdhcp | while read -r line ; do
+    ip netns delete $line
+done
+
+# Start DHCP Agent
+exec /usr/bin/neutron-dhcp-agent --config-file /etc/neutron/neutron.conf --config-file /etc/neutron/dhcp_agent.ini --config-dir /etc/neutron
diff --git a/docker/common/neutron/neutron-agents/config-scripts/config-l3-agent.sh b/docker/common/neutron/neutron-agents/config-scripts/config-l3-agent.sh
new file mode 100755
index 0000000000000000000000000000000000000000..761d07685e946993c4f660ed79901063546d3696
--- /dev/null
+++ b/docker/common/neutron/neutron-agents/config-scripts/config-l3-agent.sh
@@ -0,0 +1,85 @@
+#!/bin/bash
+
+set -e
+
+. /opt/kolla/config-neutron.sh
+. /opt/kolla/config-sudoers.sh
+
+: ${USE_NAMESPACES:=true}
+
+check_required_vars VERBOSE_LOGGING DEBUG_LOGGING
+
+cfg=/etc/neutron/l3_agent.ini
+neutron_conf=/etc/neutron/neutron.conf
+
+# Logging
+crudini --set $neutron_conf \
+    DEFAULT \
+    log_file \
+    "${NEUTRON_L3_AGENT_LOG_FILE}"
+
+# Configure l3_agent.ini
+crudini --set $cfg \
+    DEFAULT \
+    verbose \
+    "${VERBOSE_LOGGING}"
+crudini --set $cfg \
+    DEFAULT \
+    debug \
+    "${DEBUG_LOGGING}"
+if [[ "${MECHANISM_DRIVERS}" =~ linuxbridge ]] ; then
+    crudini --set $cfg \
+        DEFAULT \
+        interface_driver \
+        "neutron.agent.linux.interface.BridgeInterfaceDriver"
+    crudini --set $cfg \
+        DEFAULT \
+        gateway_external_network_id \
+        ""
+    crudini --set $cfg \
+        DEFAULT \
+        external_network_bridge \
+        ""
+elif [[ "${MECHANISM_DRIVERS}" =~ .*openvswitch* ]] ; then
+    crudini --set $cfg \
+        DEFAULT \
+        interface_driver \
+        "neutron.agent.linux.interface.OVSInterfaceDriver"
+    crudini --set $cfg \
+        DEFAULT \
+        gateway_external_network_id \
+        "${NEUTRON_FLAT_NETWORK_BRIDGE}"
+    crudini --set $cfg \
+        DEFAULT \
+        external_network_bridge \
+        "${NEUTRON_FLAT_NETWORK_BRIDGE}"
+fi
+
+crudini --set $cfg \
+    DEFAULT \
+    use_namespaces \
+    "${USE_NAMESPACES}"
+
+if [ "${USE_NAMESPACES}" == "false" ] ; then
+    source /openrc
+    # Create router if it does not exist
+    /usr/bin/neutron router-list | grep admin-router || /usr/bin/neutron router-create admin-router
+    # Set router-id
+    crudini --set $cfg \
+        DEFAULT \
+        router_id \
+        "$(/usr/bin/neutron router-list | awk '/ admin-router / {print $2}')"
+elif [ "${USE_NAMESPACES}" == "true" ] ; then
+    crudini --set $cfg \
+        DEFAULT \
+        router_delete_namespaces \
+        "true"
+fi
+
+# Remove any existing qrouter namespaces
+ip netns list | grep qrouter | while read -r line ; do
+    ip netns delete $line
+done
+
+# Start L3 Agent
+exec /usr/bin/neutron-l3-agent --config-file /etc/neutron/neutron.conf --config-file /etc/neutron/l3_agent.ini --config-file /etc/neutron/fwaas_driver.ini --config-dir /etc/neutron
diff --git a/docker/common/neutron/neutron-agents/config-scripts/config-linuxbridge-agent.sh b/docker/common/neutron/neutron-agents/config-scripts/config-linuxbridge-agent.sh
new file mode 100755
index 0000000000000000000000000000000000000000..bd8f90194be4f04ef98c81ae1974adf10c94e877
--- /dev/null
+++ b/docker/common/neutron/neutron-agents/config-scripts/config-linuxbridge-agent.sh
@@ -0,0 +1,29 @@
+#!/bin/bash
+
+set -e
+
+. /opt/kolla/config-neutron.sh
+. /opt/kolla/config-sudoers.sh
+
+: ${NEUTRON_FLAT_NETWORK_NAME:=physnet1}
+: ${NEUTRON_FLAT_NETWORK_INTERFACE:=eth1}
+
+check_required_vars PUBLIC_IP NEUTRON_FLAT_NETWORK_NAME \
+                    NEUTRON_FLAT_NETWORK_INTERFACE
+
+cfg=/etc/neutron/plugins/ml2/ml2_conf.ini
+
+# Configure ml2_conf.ini
+if [[ ${TYPE_DRIVERS} =~ vxlan ]]; then
+    crudini --set $cfg \
+        vxlan \
+        local_ip \
+        "${PUBLIC_IP}"
+fi
+
+crudini --set $cfg \
+    linux_bridge \
+    physical_interface_mappings \
+    "${NEUTRON_FLAT_NETWORK_NAME}:${NEUTRON_FLAT_NETWORK_INTERFACE}"
+
+exec /usr/bin/neutron-linuxbridge-agent --config-file /etc/neutron/neutron.conf --config-file /etc/neutron/plugins/ml2/ml2_conf.ini --config-dir /etc/neutron
diff --git a/docker/common/neutron/neutron-agents/config-scripts/config-metadata-agent.sh b/docker/common/neutron/neutron-agents/config-scripts/config-metadata-agent.sh
new file mode 100755
index 0000000000000000000000000000000000000000..d1eef341c11141cb4cd4cbc5831004451e740b07
--- /dev/null
+++ b/docker/common/neutron/neutron-agents/config-scripts/config-metadata-agent.sh
@@ -0,0 +1,74 @@
+#!/bin/bash
+
+set -e
+
+. /opt/kolla/config-neutron.sh
+. /opt/kolla/config-sudoers.sh
+
+: ${KEYSTONE_REGION:=RegionOne}
+: ${ENDPOINT_TYPE:=adminURL}
+: ${NEUTRON_SHARED_SECRET:=sharedsecret}
+
+check_required_vars VERBOSE_LOGGING DEBUG_LOGGING KEYSTONE_AUTH_PROTOCOL \
+                    KEYSTONE_PUBLIC_SERVICE_HOST ADMIN_TENANT_NAME \
+                    NEUTRON_KEYSTONE_USER NEUTRON_KEYSTONE_PASSWORD \
+                    NEUTRON_SHARED_SECRET NOVA_METADATA_API_SERVICE_HOST \
+                    NOVA_METADATA_API_SERVICE_PORT
+
+cfg=/etc/neutron/metadata_agent.ini
+neutron_conf=/etc/neutron/neutron.conf
+
+# Logging
+crudini --set $neutron_conf \
+        DEFAULT \
+        log_file \
+        "${NEUTRON_METADATA_AGENT_LOG_FILE}"
+
+# Configure metadata_agent.ini
+crudini --set $cfg \
+        DEFAULT \
+        verbose \
+        "${VERBOSE_LOGGING}"
+crudini --set $cfg \
+        DEFAULT \
+        debug \
+        "${DEBUG_LOGGING}"
+crudini --set $cfg \
+        DEFAULT \
+        auth_region \
+        "${KEYSTONE_REGION}"
+crudini --set $cfg \
+        DEFAULT \
+        endpoint_type \
+        "${ENDPOINT_TYPE}"
+crudini --set $cfg \
+        DEFAULT \
+        auth_url \
+        "${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_PUBLIC_SERVICE_HOST}:${KEYSTONE_PUBLIC_SERVICE_PORT}/v2.0"
+crudini --set $cfg \
+        DEFAULT \
+        admin_tenant_name \
+        "${ADMIN_TENANT_NAME}"
+crudini --set $cfg \
+        DEFAULT \
+        admin_user \
+        "${NEUTRON_KEYSTONE_USER}"
+crudini --set $cfg \
+        DEFAULT \
+        admin_password \
+        "${NEUTRON_KEYSTONE_PASSWORD}"
+crudini --set $cfg \
+        DEFAULT \
+        nova_metadata_ip \
+        "${NOVA_METADATA_API_SERVICE_HOST}"
+crudini --set $cfg \
+        DEFAULT \
+        nova_metadata_port \
+        "${NOVA_METADATA_API_SERVICE_PORT}"
+crudini --set $cfg \
+        DEFAULT \
+        metadata_proxy_shared_secret \
+        "${NEUTRON_SHARED_SECRET}"
+
+# Start Metadata Agent
+exec /usr/bin/neutron-metadata-agent --config-file /etc/neutron/neutron.conf --config-file /etc/neutron/metadata_agent.ini --config-dir /etc/neutron
diff --git a/docker/common/neutron/neutron-agents/config-scripts/config-sudoers.sh b/docker/common/neutron/neutron-agents/config-scripts/config-sudoers.sh
new file mode 100755
index 0000000000000000000000000000000000000000..0e02226db80b73838863bb80119b59a4d5c11d27
--- /dev/null
+++ b/docker/common/neutron/neutron-agents/config-scripts/config-sudoers.sh
@@ -0,0 +1,12 @@
+#!/bin/bash
+
+# Neutron uses rootwrap which requires a tty for sudo.
+# Since the container is running in daemon mode, a tty
+# is not present and requiretty must be commented out.
+if [ ! -f /var/run/sudo-modified ]; then
+    chmod 0640 /etc/sudoers
+    sed -i '/Defaults    requiretty/s/^/#/' /etc/sudoers
+    chmod 0440 /etc/sudoers
+fi
+
+touch /var/run/sudo-modified
diff --git a/docker/common/neutron/neutron-agents/fwaas_driver.ini b/docker/common/neutron/neutron-agents/fwaas_driver.ini
new file mode 100644
index 0000000000000000000000000000000000000000..41f761abf1a7f12650badb5c2c92f03da1b08892
--- /dev/null
+++ b/docker/common/neutron/neutron-agents/fwaas_driver.ini
@@ -0,0 +1,3 @@
+[fwaas]
+#driver = neutron.services.firewall.drivers.linux.iptables_fwaas.IptablesFwaasDriver
+#enabled = True
diff --git a/docker/common/neutron/neutron-agents/supervisord.conf b/docker/common/neutron/neutron-agents/supervisord.conf
new file mode 100644
index 0000000000000000000000000000000000000000..7455cb3d7e652bb416909a757548b5e1735190b1
--- /dev/null
+++ b/docker/common/neutron/neutron-agents/supervisord.conf
@@ -0,0 +1,53 @@
+[unix_http_server]
+file = /var/run/supervisor.sock
+
+[inet_http_server]
+port = 127.0.0.1:9001
+
+[supervisord]
+nodaemon=true
+logfile = /var/log/supervisor/supervisord.log
+logfile_maxbytes = 200KB
+logfile_backups = 1
+pidfile = /var/run/supervisord.pid
+childlogdir = /var/log/supervisor
+
+[rpcinterface:supervisor]
+supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
+
+[supervisorctl]
+serverurl = unix:///var/run/supervisor.sock
+
+[program:neutron-linuxbridge-agent]
+command=/opt/kolla/neutron/config-linuxbridge-agent.sh
+priority=30
+startsec=10
+stderr_events_enabled=true
+stdout_events_enabled=true
+
+[program:neutron-dhcp-agent]
+command=/opt/kolla/neutron/config-dhcp-agent.sh
+priority=40
+startsec=10
+stderr_events_enabled=true
+stdout_events_enabled=true
+
+[program:neutron-metadata-agent]
+command=/opt/kolla/neutron/config-metadata-agent.sh
+priority=40 
+startsec=10
+stderr_events_enabled=true
+stdout_events_enabled=true
+
+[program:neutron-l3-agent]
+command=/opt/kolla/neutron/config-l3-agent.sh
+priority=40
+startsec=10
+stderr_events_enabled=true
+stdout_events_enabled=true
+
+[eventlistener:stdout]
+command = supervisor_stdout
+buffer_size = 100
+events = PROCESS_LOG
+result_handler = supervisor_stdout:event_handler
diff --git a/docker/common/neutron/neutron-base/config-neutron.sh b/docker/common/neutron/neutron-base/config-neutron.sh
new file mode 100644
index 0000000000000000000000000000000000000000..0155651052aa75edd3854456d80268835ea070d4
--- /dev/null
+++ b/docker/common/neutron/neutron-base/config-neutron.sh
@@ -0,0 +1,210 @@
+#!/bin/bash
+
+set -e
+
+. /opt/kolla/kolla-common.sh
+
+# Database
+: ${NEUTRON_DB_NAME:=neutron}
+: ${NEUTRON_DB_USER:=neutron}
+: ${NEUTRON_DB_PASSWORD:=password}
+# Keystone
+: ${ADMIN_TENANT_NAME:=admin}
+: ${NEUTRON_KEYSTONE_USER:=neutron}
+: ${NEUTRON_KEYSTONE_PASSWORD:=password}
+: ${KEYSTONE_AUTH_PROTOCOL:=http}
+: ${KEYSTONE_ADMIN_SERVICE_HOST:=127.0.0.1}
+: ${KEYSTONE_PUBLIC_SERVICE_HOST:=127.0.0.1}
+: ${KEYSTONE_ADMIN_SERVICE_PORT:=35357}
+: ${KEYSTONE_PUBLIC_SERVICE_PORT:=5000}
+: ${KEYSTONE_REGION:=RegionOne}
+# RabbitMQ
+: ${RABBIT_HOST:=$RABBITMQ_SERVICE_HOST}
+: ${RABBIT_USER:=guest}
+: ${RABBIT_PASSWORD:=guest}
+# Logging
+: ${VERBOSE_LOGGING:=true}
+: ${DEBUG_LOGGING:=false}
+# Networking
+: ${NEUTRON_FLAT_NETWORK_NAME:=physnet1}
+# Paste configuration file
+: ${API_PASTE_CONFIG:=/usr/share/neutron/api-paste.ini}
+
+check_required_vars NEUTRON_KEYSTONE_PASSWORD NEUTRON_API_PASTE_CONFIG \
+                    KEYSTONE_PUBLIC_SERVICE_HOST RABBITMQ_SERVICE_HOST
+
+core_cfg=/etc/neutron/neutron.conf
+ml2_cfg=/etc/neutron/plugins/ml2/ml2_conf.ini
+
+# Logging
+crudini --set $core_cfg \
+        DEFAULT \
+        log_dir \
+        "${NEUTRON_LOG_DIR}"
+crudini --set $core_cfg \
+        DEFAULT \
+        verbose \
+        "${VERBOSE_LOGGING}"
+crudini --set $core_cfg \
+        DEFAULT \
+        debug \
+        "${DEBUG_LOGGING}"
+
+# Paste config
+crudini --set $core_cfg \
+        DEFAULT \
+        api_paste_config \
+        "${NEUTRON_API_PASTE_CONFIG}"
+
+# Rabbit
+crudini --set $core_cfg \
+        DEFAULT \
+        rabbit_host \
+        "${RABBIT_HOST}"
+crudini --set $core_cfg \
+        DEFAULT \
+        rabbit_userid \
+        "${RABBIT_USER}"
+crudini --set $core_cfg \
+        DEFAULT \
+        rabbit_password \
+        "${RABBIT_PASSWORD}"
+
+# Locking
+crudini --set $core_cfg \
+        DEFAULT \
+        lock_path \
+        "/var/lock/neutron"
+
+# Keystone
+crudini --set $core_cfg \
+        DEFAULT \
+        auth_strategy \
+        "keystone"
+crudini --set $core_cfg \
+        keystone_authtoken \
+        auth_uri \
+        "${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_PUBLIC_SERVICE_HOST}:${KEYSTONE_PUBLIC_SERVICE_PORT}/v2.0"
+crudini --set $core_cfg \
+        keystone_authtoken \
+        identity_uri \
+        "${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}"
+crudini --set $core_cfg \
+        keystone_authtoken \
+        admin_tenant_name \
+        "${ADMIN_TENANT_NAME}"
+crudini --set $core_cfg \
+        keystone_authtoken \
+        admin_user \
+        "${NEUTRON_KEYSTONE_USER}"
+crudini --set $core_cfg \
+        keystone_authtoken \
+        admin_password \
+        "${NEUTRON_KEYSTONE_PASSWORD}"
+
+# Rootwrap
+crudini --set $core_cfg \
+        agent \
+        root_helper \
+        "sudo neutron-rootwrap /etc/neutron/rootwrap.conf"
+
+# neutron.conf ml2 configuration
+crudini --set $core_cfg \
+        DEFAULT \
+        core_plugin \
+        "neutron.plugins.ml2.plugin.Ml2Plugin"
+crudini --set $core_cfg \
+        DEFAULT \
+        service_plugins \
+        "neutron.services.l3_router.l3_router_plugin.L3RouterPlugin"
+crudini --set $core_cfg \
+        DEFAULT \
+        allow_overlapping_ips \
+        "True"
+
+# Configure ml2_conf.ini
+crudini --set $ml2_cfg \
+        ml2 \
+        type_drivers \
+        "${TYPE_DRIVERS}"
+crudini --set $ml2_cfg \
+        ml2 \
+        tenant_network_types \
+        "${TENANT_NETWORK_TYPES}"
+crudini --set $ml2_cfg \
+        ml2 \
+        mechanism_drivers \
+        "${MECHANISM_DRIVERS}"
+
+if [[ ${TYPE_DRIVERS} =~ .*flat.* ]]; then
+    crudini --set $ml2_cfg \
+        ml2_type_flat \
+        flat_networks \
+        ${NEUTRON_FLAT_NETWORK_NAME}
+fi
+
+if [[ ${TYPE_DRIVERS} =~ .*vxlan.* ]]; then
+    crudini --set $ml2_cfg \
+        ml2_type_vxlan \
+        vxlan_group \
+        ""
+    crudini --set $ml2_cfg \
+        ml2_type_vxlan \
+        vni_ranges \
+        "1:1000"
+    crudini --set $ml2_cfg \
+        vxlan \
+        enable_vxlan \
+        "True"
+    crudini --set $ml2_cfg \
+        vxlan \
+        vxlan_group \
+        ""
+    crudini --set $ml2_cfg \
+        vxlan \
+        l2_population \
+        "True"
+    crudini --set $ml2_cfg \
+        agent \
+        tunnel_types \
+        "vxlan"
+    crudini --set $ml2_cfg \
+        agent \
+        vxlan_udp_port \
+        "4789"
+    crudini --set $core_cfg \
+        DEFAULT \
+        network_device_mtu \
+        "1450"
+fi
+
+crudini --set $ml2_cfg \
+    l2pop \
+    agent_boot_time \
+    "180"
+crudini --set $ml2_cfg \
+    securitygroup \
+    enable_security_group \
+    "True"
+crudini --set $ml2_cfg \
+    securitygroup \
+    enable_ipset \
+    "True"
+
+if [[ ${MECHANISM_DRIVERS} =~ linuxbridge ]]; then
+    firewall_driver="neutron.agent.linux.iptables_firewall.IptablesFirewallDriver"
+elif [[ ${MECHANISM_DRIVERS} == "openvswitch" ]]; then
+    firewall_driver="neutron.agent.linux.iptables_firewall.OVSHybridIptablesFirewallDriver"
+fi
+
+crudini --set $ml2_cfg \
+    securitygroup \
+    firewall_driver \
+    "$firewall_driver"
+
+cat > /openrc <<EOF
+export OS_AUTH_URL="http://${KEYSTONE_PUBLIC_SERVICE_HOST}:${KEYSTONE_PUBLIC_SERVICE_PORT}/v2.0"
+export OS_USERNAME="${NEUTRON_KEYSTONE_USER}"
+export OS_PASSWORD="${NEUTRON_KEYSTONE_PASSWORD}"
+export OS_TENANT_NAME="${ADMIN_TENANT_NAME}"
+EOF
diff --git a/docker/common/neutron/neutron-server/check.sh b/docker/common/neutron/neutron-server/check.sh
new file mode 100755
index 0000000000000000000000000000000000000000..4e9aa623c60bbdd43ce2622e1ab930102d0ce9af
--- /dev/null
+++ b/docker/common/neutron/neutron-server/check.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+RES=0
+
+. /openrc
+if ! keystone token-get > /dev/null; then
+    echo "ERROR: keystone token-get failed" >&2
+    RES=1
+else
+    if ! neutron ext-list > /dev/null; then
+        echo "ERROR: neutron ext-list failed" >&2
+        RES=1
+    fi
+fi
+
+exit $RES
+
diff --git a/docker/common/neutron/neutron-server/start.sh b/docker/common/neutron/neutron-server/start.sh
new file mode 100755
index 0000000000000000000000000000000000000000..fb971083f583422f5f1e21b57ad259098f969f74
--- /dev/null
+++ b/docker/common/neutron/neutron-server/start.sh
@@ -0,0 +1,98 @@
+#!/bin/bash
+
+set -e
+
+. /opt/kolla/config-neutron.sh
+
+: ${NEUTRON_FLAT_NETWORK_NAME:=physnet1}
+: ${NEUTRON_FLAT_NETWORK_INTERFACE:=eth1}
+
+check_required_vars KEYSTONE_ADMIN_TOKEN KEYSTONE_ADMIN_SERVICE_HOST \
+                    KEYSTONE_AUTH_PROTOCOL NOVA_API_SERVICE_HOST \
+                    NOVA_KEYSTONE_USER NOVA_KEYSTONE_PASSWORD \
+                    NEUTRON_DB_NAME NEUTRON_DB_USER NEUTRON_DB_PASSWORD \
+                    NEUTRON_KEYSTONE_USER NEUTRON_KEYSTONE_PASSWORD \
+                    ADMIN_TENANT_NAME NEUTRON_SERVER_SERVICE_HOST \
+                    PUBLIC_IP NEUTRON_DB_PASSWORD
+fail_unless_os_service_running keystone
+fail_unless_db
+
+mysql -h ${MARIADB_SERVICE_HOST} -u root -p${DB_ROOT_PASSWORD} mysql <<EOF
+CREATE DATABASE IF NOT EXISTS ${NEUTRON_DB_NAME} DEFAULT CHARACTER SET utf8;
+GRANT ALL PRIVILEGES ON ${NEUTRON_DB_NAME}.* TO
+       '${NEUTRON_DB_USER}'@'%' IDENTIFIED BY '${NEUTRON_DB_PASSWORD}'
+
+EOF
+
+export SERVICE_TOKEN="${KEYSTONE_ADMIN_TOKEN}"
+export SERVICE_ENDPOINT="${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}/v2.0"
+
+# Configure Keystone Service Catalog
+crux user-create -n "${NEUTRON_KEYSTONE_USER}" \
+    -p "${NEUTRON_KEYSTONE_PASSWORD}" \
+    -t "${ADMIN_TENANT_NAME}" \
+    -r admin
+
+crux endpoint-create -n neutron -t network \
+    -I "${KEYSTONE_AUTH_PROTOCOL}://${NEUTRON_SERVER_SERVICE_HOST}:${NEUTRON_SERVER_SERVICE_PORT}" \
+    -P "${KEYSTONE_AUTH_PROTOCOL}://${NEUTRON_SERVER_SERVICE_HOST}:${NEUTRON_SERVER_SERVICE_PORT}" \
+    -A "${KEYSTONE_AUTH_PROTOCOL}://${NEUTRON_SERVER_SERVICE_HOST}:${NEUTRON_SERVER_SERVICE_PORT}"
+
+core_cfg=/etc/neutron/neutron.conf
+ml2_cfg=/etc/neutron/plugins/ml2/ml2_conf.ini
+
+# Logging
+crudini --set /etc/neutron/neutron.conf \
+        DEFAULT \
+        log_file \
+        "${NEUTRON_SERVER_LOG_FILE}"
+
+# Database
+crudini --set $core_cfg \
+        database \
+        connection \
+        "mysql://${NEUTRON_DB_USER}:${NEUTRON_DB_PASSWORD}@${MARIADB_SERVICE_HOST}/${NEUTRON_DB_NAME}"
+# Nova
+crudini --set $core_cfg \
+        DEFAULT \
+        notify_nova_on_port_status_changes \
+        "True"
+crudini --set $core_cfg \
+        DEFAULT \
+        notify_nova_on_port_data_changes \
+        "True"
+crudini --set $core_cfg \
+        DEFAULT \
+        nova_url \
+        "http://${NOVA_API_SERVICE_HOST}:${NOVA_API_SERVICE_PORT}/v2"
+crudini --set $core_cfg \
+        DEFAULT \
+        nova_admin_auth_url \
+        "${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}/v2.0"
+crudini --set $core_cfg \
+        DEFAULT \
+        nova_region_name \
+        "${KEYSTONE_REGION}"
+crudini --set $core_cfg \
+        DEFAULT \
+        nova_admin_username \
+        "${NOVA_KEYSTONE_USER}"
+crudini --set $core_cfg \
+        DEFAULT \
+        nova_admin_tenant_id \
+        "$(keystone tenant-list | grep $ADMIN_TENANT_NAME | awk '{print $2;}')"
+crudini --set $core_cfg \
+        DEFAULT \
+        nova_admin_password \
+        "${NOVA_KEYSTONE_PASSWORD}"
+
+if [[ ${MECHANISM_DRIVERS} =~ linuxbridge ]]; then
+    crudini --set $ml2_cfg \
+        linux_bridge \
+        physical_interface_mappings \
+        "${NEUTRON_FLAT_NETWORK_NAME}:${NEUTRON_FLAT_NETWORK_INTERFACE}"
+fi
+
+su -s /bin/bash -c "neutron-db-manage --config-file /etc/neutron/neutron.conf --config-file /etc/neutron/plugins/ml2/ml2_conf.ini upgrade head" neutron
+
+exec /usr/bin/neutron-server --config-file /etc/neutron/neutron.conf --config-file /etc/neutron/plugins/ml2/ml2_conf.ini
diff --git a/docker/common/nova-base/config-nova.sh b/docker/common/nova-base/config-nova.sh
new file mode 100755
index 0000000000000000000000000000000000000000..8789a14a54e0ba02386fb90b0843ad34d2f900c5
--- /dev/null
+++ b/docker/common/nova-base/config-nova.sh
@@ -0,0 +1,137 @@
+#!/bin/bash
+
+. /opt/kolla/kolla-common.sh
+
+: ${NOVA_DB_USER:=nova}
+: ${NOVA_DB_NAME:=nova}
+: ${NOVA_KEYSTONE_USER:=admin}
+: ${NOVA_KEYSTONE_PASSWORD:=kolla}
+: ${ADMIN_TENANT_NAME:=admin}
+: ${RABBIT_USERID:=guest}
+: ${RABBIT_PASSWORD:=guest}
+: ${NETWORK_MANAGER:=nova}
+: ${FLAT_NETWORK:=eth1}
+: ${PUBLIC_NETWORK:=eth0}
+: ${ENABLED_APIS:=ec2,osapi_compute,metadata}
+: ${METADATA_HOST:=$PUBLIC_IP}
+: ${NEUTRON_SHARED_SECRET:=sharedsecret}
+
+check_required_vars KEYSTONE_ADMIN_TOKEN NOVA_DB_PASSWORD \
+                    RABBITMQ_SERVICE_HOST GLANCE_API_SERVICE_HOST \
+                    KEYSTONE_PUBLIC_SERVICE_HOST PUBLIC_IP \
+                    PUBLIC_INTERFACE FLAT_INTERFACE DEBUG_LOGGING \
+                    VERBOSE_LOGGING
+
+cfg=/etc/nova/nova.conf
+
+crudini --set $cfg DEFAULT amqp_durable_queues False
+crudini --set $cfg DEFAULT rabbit_host ${RABBITMQ_SERVICE_HOST}
+crudini --set $cfg DEFAULT rabbit_port 5672
+crudini --set $cfg DEFAULT rabbit_hosts ${RABBITMQ_SERVICE_HOST}:5672
+crudini --set $cfg DEFAULT rabbit_use_ssl False
+crudini --set $cfg DEFAULT rabbit_userid ${RABBIT_USERID}
+crudini --set $cfg DEFAULT rabbit_password "${RABBIT_PASSWORD}"
+crudini --set $cfg DEFAULT rabbit_virtual_host /
+crudini --set $cfg DEFAULT rabbit_ha_queues False
+crudini --set $cfg DEFAULT rpc_backend nova.openstack.common.rpc.impl_kombu
+crudini --set $cfg DEFAULT enabled_apis ${ENABLED_APIS}
+crudini --set $cfg DEFAULT ec2_listen 0.0.0.0
+crudini --set $cfg DEFAULT osapi_compute_listen 0.0.0.0
+crudini --set $cfg DEFAULT osapi_compute_workers 8
+crudini --set $cfg DEFAULT metadata_host ${METADATA_HOST}
+crudini --set $cfg DEFAULT metadata_listen 0.0.0.0
+crudini --set $cfg DEFAULT metadata_workers 8
+crudini --set $cfg DEFAULT service_down_time 60
+crudini --set $cfg DEFAULT rootwrap_config /etc/nova/rootwrap.conf
+crudini --set $cfg DEFAULT auth_strategy keystone
+crudini --set $cfg DEFAULT use_forwarded_for False
+crudini --set $cfg DEFAULT glance_api_servers ${GLANCE_API_SERVICE_HOST}:9292
+crudini --set $cfg DEFAULT cpu_allocation_ratio 16.0
+crudini --set $cfg DEFAULT ram_allocation_ratio 1.5
+crudini --set $cfg DEFAULT scheduler_default_filters RetryFilter,AvailabilityZoneFilter,RamFilter,ComputeFilter,ComputeCapabilitiesFilter,ImagePropertiesFilter,CoreFilter
+crudini --set $cfg DEFAULT compute_driver nova.virt.libvirt.LibvirtDriver
+crudini --set $cfg DEFAULT vif_plugging_is_fatal True
+crudini --set $cfg DEFAULT vif_plugging_timeout 300
+crudini --set $cfg DEFAULT volume_api_class nova.volume.cinder.API
+crudini --set $cfg DEFAULT image_service nova.image.glance.GlanceImageService
+crudini --set $cfg DEFAULT osapi_volume_listen 0.0.0.0
+crudini --set $cfg DEFAULT instances_path /var/lib/nova/instances
+crudini --set $cfg DEFAULT lock_path /var/lib/nova/lock
+
+# This is not created by openstack-nova packaging
+mkdir -p /var/lib/nova/lock
+
+# configure logging
+crudini --set $cfg DEFAULT log_dir "${NOVA_LOG_DIR}"
+crudini --set $cfg DEFAULT debug "${DEBUG_LOGGING}"
+crudini --set $cfg DEFAULT verbose "${VERBOSE_LOGGING}"
+
+crudini --set $cfg DEFAULT admin_token "${KEYSTONE_ADMIN_TOKEN}"
+
+crudini --set $cfg conductor workers 8
+
+if [ "${NETWORK_MANAGER}" == "nova" ] ; then
+    crudini --set $cfg DEFAULT network_manager nova.network.manager.FlatDHCPManager
+    crudini --set $cfg DEFAULT firewall_driver nova.virt.libvirt.firewall.IptablesFirewallDriver
+    crudini --set $cfg DEFAULT network_size 254
+    crudini --set $cfg DEFAULT allow_same_net_traffic False
+    crudini --set $cfg DEFAULT multi_host True
+    crudini --set $cfg DEFAULT send_arp_for_ha True
+    crudini --set $cfg DEFAULT share_dhcp_address True
+    crudini --set $cfg DEFAULT force_dhcp_release True
+    crudini --set $cfg DEFAULT flat_interface $FLAT_INTERFACE
+    crudini --set $cfg DEFAULT flat_network_bridge br100
+    crudini --set $cfg DEFAULT public_interface $PUBLIC_INTERFACE
+elif [ "${NETWORK_MANAGER}" == "neutron" ] ; then
+    check_required_vars NEUTRON_SHARED_SECRET
+    crudini --set $cfg neutron service_metadata_proxy True
+    crudini --set $cfg neutron metadata_proxy_shared_secret ${NEUTRON_SHARED_SECRET}
+    crudini --set $cfg DEFAULT neutron_default_tenant_id default
+    crudini --set $cfg DEFAULT network_api_class nova.network.neutronv2.api.API
+    crudini --set $cfg DEFAULT security_group_api neutron
+    if [[ "${MECHANISM_DRIVERS}" =~ linuxbridge ]] ; then
+        crudini --set $cfg DEFAULT linuxnet_interface_driver nova.network.linux_net.NeutronLinuxBridgeInterfaceDriver
+    elif [[ "${MECHANISM_DRIVERS}" =~ openvswitch ]] ; then
+        crudini --set $cfg DEFAULT linuxnet_interface_driver nova.network.linux_net.LinuxOVSInterfaceDriver
+    fi
+    crudini --set $cfg DEFAULT libvirt_vif_driver nova.virt.libvirt.vif.LibvirtGenericVIFDriver
+    crudini --set $cfg DEFAULT firewall_driver nova.virt.firewall.NoopFirewallDriver
+    crudini --set $cfg neutron url http://${NEUTRON_SERVER_SERVICE_HOST}:${NEUTRON_SERVER_SERVICE_PORT}
+    crudini --set $cfg neutron auth_strategy keystone
+    crudini --set $cfg neutron admin_auth_url ${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:${KEYSTONE_ADMIN_SERVICE_PORT}/v2.0
+    crudini --set $cfg neutron admin_tenant_name ${ADMIN_TENANT_NAME}
+    crudini --set $cfg neutron admin_username ${NEUTRON_KEYSTONE_USER}
+    crudini --set $cfg neutron admin_password ${NEUTRON_KEYSTONE_PASSWORD}
+else
+    echo "Incorrect NETWORK_MANAGER ${NETWORK_MANAGER}. Supported options are nova and neutron."
+    exit 1
+fi
+
+# disabled pending answers to http://lists.openstack.org/pipermail/openstack/2014-October/009997.html
+#for option in auth_protocol auth_host auth_port; do
+#    crudini --del $cfg \
+#        keystone_authtoken \
+#        $option
+#done
+
+crudini --set $cfg keystone_authtoken auth_uri "http://${KEYSTONE_PUBLIC_SERVICE_HOST}:5000/"
+crudini --set $cfg keystone_authtoken auth_protocol http
+crudini --set $cfg keystone_authtoken auth_host ${KEYSTONE_PUBLIC_SERVICE_HOST}
+crudini --set $cfg keystone_authtoken auth_port 5000
+
+crudini --set $cfg keystone_authtoken admin_user ${NOVA_KEYSTONE_USER}
+crudini --set $cfg keystone_authtoken admin_password "${NOVA_KEYSTONE_PASSWORD}"
+crudini --set $cfg keystone_authtoken admin_tenant_name ${ADMIN_TENANT_NAME}
+
+cat > /openrc <<EOF
+export OS_AUTH_URL="http://${KEYSTONE_PUBLIC_SERVICE_HOST}:5000/v2.0"
+export OS_USERNAME="${NOVA_KEYSTONE_USER}"
+export OS_PASSWORD="${NOVA_KEYSTONE_PASSWORD}"
+export OS_TENANT_NAME="${ADMIN_TENANT_NAME}"
+EOF
+
+# Configure database connection
+crudini --set $cfg \
+    database \
+    connection \
+    "mysql://${NOVA_DB_USER}:${NOVA_DB_PASSWORD}@${MARIADB_SERVICE_HOST}/${NOVA_DB_NAME}"
diff --git a/docker/common/nova-compute/nova-compute/config-nova-compute.sh b/docker/common/nova-compute/nova-compute/config-nova-compute.sh
new file mode 100755
index 0000000000000000000000000000000000000000..9a2c125724650c5eb44b4757a0def4ad7c9df9e9
--- /dev/null
+++ b/docker/common/nova-compute/nova-compute/config-nova-compute.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+. /opt/kolla/kolla-common.sh
+. /opt/kolla/config-nova.sh
+
+cfg=/etc/nova/nova.conf
+
+check_required_vars NOVA_VNCSERVER_PROXYCLIENT_ADDRESS NOVA_NOVNC_PROXY_PORT \
+                    NOVA_NOVNC_BASE_ADDRESS
+
+# Configures novnc to listen on all interfaces and instructs nova-compute to
+# announce PROXYCLIENT_IP to the nova-vncproxy. Clients like Horizon will
+# connect with this address.
+# As such, NOVA_VNCSERVER_PROXYCLIENT_ADDRESS is unique per compute node.
+crudini --set $cfg DEFAULT vnc_enabled "True"
+crudini --set $cfg DEFAULT vncserver_listen "0.0.0.0"
+crudini --set $cfg DEFAULT vncserver_proxyclient_address "${NOVA_VNCSERVER_PROXYCLIENT_ADDRESS}"
+crudini --set $cfg DEFAULT novncproxy_base_url "http://${NOVA_NOVNC_BASE_ADDRESS}:${NOVA_NOVNC_PROXY_PORT}/vnc_auto.html"
+
+# configure logging
+crudini --set $cfg DEFAULT log_file "${NOVA_COMPUTE_LOG_FILE}"
+
+# set qmeu emulation if no hardware acceleration found
+if [[ `egrep -c '(vmx|svm)' /proc/cpuinfo` == 0 ]]; then
+    crudini --set $cfg libvirt virt_type qemu
+fi
+
+mkdir -p /var/lib/nova/instances
diff --git a/docker/common/nova-compute/nova-compute/start.sh b/docker/common/nova-compute/nova-compute/start.sh
new file mode 100755
index 0000000000000000000000000000000000000000..ce3d0c0c377d1ff66c0d26a52f2814725d05f1a4
--- /dev/null
+++ b/docker/common/nova-compute/nova-compute/start.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+set -e
+
+. /opt/kolla/config-nova-compute.sh
+
+sleep 6
+
+echo "Starting nova-compute."
+exec /usr/bin/nova-compute --config-file /etc/nova/nova.conf
diff --git a/docker/common/nova-compute/nova-libvirt/start.sh b/docker/common/nova-compute/nova-libvirt/start.sh
new file mode 100755
index 0000000000000000000000000000000000000000..bdbe882b8d1433bd14340a233a15a05887ed2129
--- /dev/null
+++ b/docker/common/nova-compute/nova-libvirt/start.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+
+if [[ $(cat /proc/cpuinfo | grep vmx) ]]; then
+    modprobe kvm_intel
+elif [[ $(cat /proc/cpuinfo | grep svm) ]]; then
+    modprobe kvm_amd
+else
+    echo "WARNING: Your hardware does not support hardware virtualization -" \
+        "using qemu software virtualization instead"
+fi
+
+modprobe ip6_tables ip_tables ebtable_nat
+
+# If libvirt is not installed on the host permissions need to be set
+# If running in qemu, we don't need to set anything as /dev/kvm won't exist
+if [[ -c /dev/kvm ]]; then
+    chmod 660 /dev/kvm
+    chown root:kvm /dev/kvm
+fi
+
+echo "Starting libvirtd."
+exec /usr/sbin/libvirtd
diff --git a/docker/common/nova-compute/nova-network/config-nova-network.sh b/docker/common/nova-compute/nova-network/config-nova-network.sh
new file mode 100755
index 0000000000000000000000000000000000000000..6976d3a20871f27713e30d7cfece401fb5a72f29
--- /dev/null
+++ b/docker/common/nova-compute/nova-network/config-nova-network.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+. /opt/kolla/config-nova.sh
+
+cfg=/etc/nova/nova.conf
+
+# configure logging
+crudini --set $cfg DEFAULT log_file "${NOVA_NETWORK_LOG_FILE}"
+
+# Configure eth1 as a physcial interface for nova flat network
+cat > /etc/sysconfig/network-scripts/ifcfg-$FLAT_INTERFACE <<EOF
+DEVICE="$FLAT_INTERFACE"
+BOOTPROTO="none"
+ONBOOT="yes"
+TYPE="Ethernet"
+EOF
+
+/usr/sbin/ifup $FLAT_INTERFACE
+
+cfg=/etc/nova/nova.conf
+
+crudini --set $cfg DEFAULT network_manager nova.network.manager.FlatDHCPManager
+crudini --set $cfg DEFAULT firewall_driver nova.virt.libvirt.firewall.IptablesFirewallDriver
+crudini --set $cfg DEFAULT network_size 254
+crudini --set $cfg DEFAULT allow_same_net_traffic False
+crudini --set $cfg DEFAULT multi_host True
+crudini --set $cfg DEFAULT send_arp_for_ha True
+crudini --set $cfg DEFAULT share_dhcp_address True
+crudini --set $cfg DEFAULT force_dhcp_release True
+crudini --set $cfg DEFAULT flat_network_bridge br100
diff --git a/docker/common/nova-compute/nova-network/start.sh b/docker/common/nova-compute/nova-network/start.sh
new file mode 100755
index 0000000000000000000000000000000000000000..92381b720f582f0b48af2155904613edc92e31df
--- /dev/null
+++ b/docker/common/nova-compute/nova-network/start.sh
@@ -0,0 +1,8 @@
+#!/bin/bash
+
+set -e
+
+. /opt/kolla/config-nova-network.sh
+
+# Start nova-network
+exec /usr/bin/nova-network --config-file /etc/nova/nova.conf
diff --git a/docker/common/nova-controller/nova-api/check.sh b/docker/common/nova-controller/nova-api/check.sh
new file mode 100755
index 0000000000000000000000000000000000000000..b250682d803aed91be45efd89f5ff493ce754402
--- /dev/null
+++ b/docker/common/nova-controller/nova-api/check.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+RES=0
+
+. /openrc
+if ! keystone token-get > /dev/null; then
+    echo "ERROR: keystone token-get failed" >&2
+    RES=1
+else
+    if ! nova list > /dev/null; then
+        echo "ERROR: nova list failed" >&2
+        RES=1
+    fi
+fi
+
+exit $RES
+
diff --git a/docker/common/nova-controller/nova-api/start.sh b/docker/common/nova-controller/nova-api/start.sh
new file mode 100755
index 0000000000000000000000000000000000000000..7928370a46324521bc85bb6d0cde7800f8b22e22
--- /dev/null
+++ b/docker/common/nova-controller/nova-api/start.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+
+set -e
+
+. /opt/kolla/config-nova.sh
+
+check_required_vars KEYSTONE_ADMIN_TOKEN KEYSTONE_ADMIN_SERVICE_HOST \
+                    NOVA_KEYSTONE_USER NOVA_KEYSTONE_PASSWORD \
+                    ADMIN_TENANT_NAME NOVA_API_SERVICE_HOST \
+                    NOVA_EC2_API_SERVICE_HOST PUBLIC_IP NOVA_DB_NAME
+fail_unless_os_service_running keystone
+fail_unless_db $NOVA_DB_NAME
+
+export SERVICE_TOKEN="${KEYSTONE_ADMIN_TOKEN}"
+export SERVICE_ENDPOINT="http://${KEYSTONE_ADMIN_SERVICE_HOST}:35357/v2.0"
+
+cfg=/etc/nova/nova.conf
+
+# configure logging
+crudini --set $cfg DEFAULT log_file "${NOVA_API_LOG_FILE}"
+
+crux user-create --update \
+    -n "${NOVA_KEYSTONE_USER}" \
+    -p "${NOVA_KEYSTONE_PASSWORD}" \
+    -t "${ADMIN_TENANT_NAME}" \
+    -r admin
+
+crux endpoint-create --remove-all \
+    -n ec2 -t ec2 \
+    -I "http://${NOVA_EC2_API_SERVICE_HOST}:8773/services/Cloud" \
+    -P "http://${PUBLIC_IP}:8773/services/Cloud" \
+    -A "http://${NOVA_EC2_API_SERVICE_HOST}:8773/services/Admin"
+
+crux endpoint-create --remove-all \
+    -n nova -t compute \
+    -I "http://${NOVA_API_SERVICE_HOST}:8774/v2/\$(tenant_id)s" \
+    -P "http://${PUBLIC_IP}:8774/v2/\$(tenant_id)s" \
+    -A "http://${NOVA_API_SERVICE_HOST}:8774/v2/\$(tenant_id)s"
+
+crux endpoint-create --remove-all \
+    -n novav3 -t computev3 \
+    -I "http://${NOVA_API_SERVICE_HOST}:8774/v3" \
+    -P "http://${PUBLIC_IP}:8774/v3" \
+    -A "http://${NOVA_API_SERVICE_HOST}:8774/v3"
+
+exec /usr/bin/nova-api --config-file /etc/nova/nova.conf
diff --git a/docker/common/nova-controller/nova-conductor/start.sh b/docker/common/nova-controller/nova-conductor/start.sh
new file mode 100755
index 0000000000000000000000000000000000000000..575e7ff6ccf14c45ad2172273b9a2fc6e327e35e
--- /dev/null
+++ b/docker/common/nova-controller/nova-conductor/start.sh
@@ -0,0 +1,23 @@
+#!/bin/bash
+
+set -e
+
+. /opt/kolla/config-nova.sh
+
+check_required_vars NOVA_DB_NAME NOVA_DB_USER NOVA_DB_PASSWORD
+fail_unless_db
+
+cfg=/etc/nova/nova.conf
+
+# configure logging
+crudini --set $cfg DEFAULT log_file "${NOVA_CONDUCTOR_LOG_FILE}"
+
+mysql -h ${MARIADB_SERVICE_HOST} -u root -p${DB_ROOT_PASSWORD} mysql <<EOF
+CREATE DATABASE IF NOT EXISTS ${NOVA_DB_NAME};
+GRANT ALL PRIVILEGES ON ${NOVA_DB_NAME}.* TO
+	'${NOVA_DB_USER}'@'%' IDENTIFIED BY '${NOVA_DB_PASSWORD}'
+EOF
+
+nova-manage db sync
+
+exec /usr/bin/nova-conductor --config-file /etc/nova/nova.conf
diff --git a/docker/common/nova-controller/nova-consoleauth/start.sh b/docker/common/nova-controller/nova-consoleauth/start.sh
new file mode 100755
index 0000000000000000000000000000000000000000..a1b0864ac3253e1132f31c216aa1031c0b02609f
--- /dev/null
+++ b/docker/common/nova-controller/nova-consoleauth/start.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+set -e
+
+. /opt/kolla/config-nova.sh
+
+cfg=/etc/nova/nova.conf
+
+crudini --set $cfg DEFAULT log_file "${NOVA_CONSOLEAUTH_LOG_FILE}"
+
+echo Starting nova-consoleauth
+exec /usr/bin/nova-consoleauth
diff --git a/docker/common/nova-controller/nova-novncproxy/start.sh b/docker/common/nova-controller/nova-novncproxy/start.sh
new file mode 100755
index 0000000000000000000000000000000000000000..9edafbca340fa5fff8aa09d24b9dd87f9e0f7da9
--- /dev/null
+++ b/docker/common/nova-controller/nova-novncproxy/start.sh
@@ -0,0 +1,22 @@
+#!/bin/bash
+set -e
+. /opt/kolla/kolla-common.sh
+
+cfg=/etc/nova/nova.conf
+
+check_required_vars PUBLIC_IP NOVA_NOVNC_PROXY_SERVICE_HOST NOVA_NOVNC_PROXY_PORT \
+                    NOVA_NOVNC_BASE_ADDRESS NOVA_VNCSERVER_LISTEN_ADDRESS \
+                    NOVA_VNCSERVER_PROXYCLIENT_ADDRESS
+
+crudini --set $cfg DEFAULT log_file "${NOVA_NOVNCPROXY_LOG_FILE}"
+
+# Listen on all interfaces on port $NOVA_NOVNC_PROXY_PORT for incoming novnc
+# requests.
+# The base_url is given to clients to connect to, like Horizon, so this could
+# very well be fancy DNS name.
+echo Configuring VNC...
+crudini --set $cfg DEFAULT vncserver_listen "${NOVA_VNCSERVER_LISTEN_ADDRESS}"
+crudini --set $cfg DEFAULT vncserver_proxyclient_address "${NOVA_VNCSERVER_PROXYCLIENT_ADDRESS}"
+
+echo Starting nova-novncproxy
+exec /usr/bin/nova-novncproxy
diff --git a/docker/common/nova-controller/nova-scheduler/start.sh b/docker/common/nova-controller/nova-scheduler/start.sh
new file mode 100755
index 0000000000000000000000000000000000000000..504c049edc6c4721adf5caa12f495fb6b4d34138
--- /dev/null
+++ b/docker/common/nova-controller/nova-scheduler/start.sh
@@ -0,0 +1,15 @@
+#!/bin/bash
+
+set -e
+
+. /opt/kolla/config-nova.sh
+
+check_required_vars NOVA_DB_NAME
+fail_unless_db $NOVA_DB_NAME
+
+cfg=/etc/nova/nova.conf
+
+# configure logging
+crudini --set $cfg DEFAULT log_file "${NOVA_SCHEDULER_LOG_FILE}"
+
+exec /usr/bin/nova-scheduler --config-file /etc/nova/nova.conf
diff --git a/docker/common/rabbitmq/rabbitmq-env.conf b/docker/common/rabbitmq/rabbitmq-env.conf
new file mode 100644
index 0000000000000000000000000000000000000000..e76f18f0b1bee9a48a8149059e5c63644f50848b
--- /dev/null
+++ b/docker/common/rabbitmq/rabbitmq-env.conf
@@ -0,0 +1,2 @@
+RABBITMQ_NODENAME=@RABBITMQ_NODENAME@
+RABBITMQ_LOG_BASE=@RABBITMQ_LOG_BASE@
diff --git a/docker/common/rabbitmq/rabbitmq.config b/docker/common/rabbitmq/rabbitmq.config
new file mode 100644
index 0000000000000000000000000000000000000000..15a47eba18ddf5ffce27941e54b51103e6f5212a
--- /dev/null
+++ b/docker/common/rabbitmq/rabbitmq.config
@@ -0,0 +1,11 @@
+[
+  {rabbit, [
+    {default_user, <<"@RABBITMQ_USER@">>},
+    {default_pass, <<"@RABBITMQ_PASS@">>}
+  ]},
+  {kernel, [
+    
+  ]}
+].
+% EOF
+
diff --git a/docker/common/rabbitmq/start.sh b/docker/common/rabbitmq/start.sh
new file mode 100755
index 0000000000000000000000000000000000000000..f70c3486689b23692653bf50982ad024e2debbeb
--- /dev/null
+++ b/docker/common/rabbitmq/start.sh
@@ -0,0 +1,24 @@
+#!/bin/bash
+
+set -e
+
+: ${RABBITMQ_USER:=guest}
+: ${RABBITMQ_PASS:=guest}
+: ${RABBITMQ_NODENAME:=rabbit}
+: ${RABBITMQ_LOG_BASE:=/var/log/rabbitmq}
+
+sed -i '
+    s|@RABBITMQ_USER@|'"$RABBITMQ_USER"'|g
+    s|@RABBITMQ_PASS@|'"$RABBITMQ_PASS"'|g
+' /etc/rabbitmq/rabbitmq.config
+
+sed -i '
+    s|@RABBITMQ_NODENAME@|'"$RABBITMQ_NODENAME"'|g
+    s|@RABBITMQ_LOG_BASE@|'"$RABBITMQ_LOG_BASE"'|g
+' /etc/rabbitmq/rabbitmq-env.conf
+
+# work around:
+#   https://bugs.launchpad.net/ubuntu/+source/rabbitmq-server/+bug/653405
+echo "${RABBITMQ_SERVICE_HOST} `/usr/bin/hostname -s`" > /etc/hosts
+
+exec /usr/sbin/rabbitmq-server
diff --git a/docker/common/swift/swift-account/start.sh b/docker/common/swift/swift-account/start.sh
new file mode 100644
index 0000000000000000000000000000000000000000..bf86830f98d0d82fbe09b708c3d1cbf3464f9ef4
--- /dev/null
+++ b/docker/common/swift/swift-account/start.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+
+: ${SWIFT_DB_USER:=swift}
+: ${SWIFT_DB_NAME:=swift}
+: ${KEYSTONE_AUTH_PROTOCOL:=http}
+: ${SWIFT_KEYSTONE_USER:=swift}
+: ${ADMIN_TENANT_NAME:=admin}
+
+check_required_vars KEYSTONE_ADMIN_TOKEN KEYSTONE_ADMIN_SERVICE_HOST \
+                    SWIFT_ADMIN_PASSWORD
+fail_unless_db
+fail_unless_os_service_running keystone
+
+if ! [ "$SWIFT_DB_PASSWORD" ]; then
+    SWIFT_DB_PASSWORD=$(openssl rand -hex 15)
+    export SWIFT_DB_PASSWORD
+fi
+
+sh /opt/swift/config-swift.sh account-server
+
+mysql -h ${MARIADB_SERVICE_HOST} -u root -p${DB_ROOT_PASSWORD} mysql <<EOF
+CREATE DATABASE IF NOT EXISTS ${SWIFT_DB_NAME};
+GRANT ALL PRIVILEGES ON swift* TO
+'${SWIFT_DB_USER}'@'%' IDENTIFIED BY '${SWIFT_DB_PASSWORD}'
+EOF
+
+export SERVICE_TOKEN="${KEYSTONE_ADMIN_TOKEN}"
+export SERVICE_ENDPOINT="${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:35357/v2.0"
+
+/bin/keystone user-create --name ${SWIFT_KEYSTONE_USER} --pass ${SWIFT_ADMIN_PASSWORD}
+/bin/keystone role-create --name ${SWIFT_KEYSTONE_USER}
+/bin/keystone user-role-add --user ${SWIFT_KEYSTONE_USER} --role admin --tenant ${ADMIN_TENANT_NAME}
+
+exec /usr/bin/swift-engine
diff --git a/docker/common/swift/swift-container/start.sh b/docker/common/swift/swift-container/start.sh
new file mode 100644
index 0000000000000000000000000000000000000000..42d4ccf35531a6fb10c1d7306c892910a4ced49e
--- /dev/null
+++ b/docker/common/swift/swift-container/start.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+
+: ${SWIFT_DB_USER:=swift}
+: ${SWIFT_DB_NAME:=swift}
+: ${KEYSTONE_AUTH_PROTOCOL:=http}
+: ${SWIFT_KEYSTONE_USER:=swift}
+: ${ADMIN_TENANT_NAME:=admin}
+
+check_required_vars KEYSTONE_ADMIN_TOKEN KEYSTONE_ADMIN_SERVICE_HOST \
+                    SWIFT_ADMIN_PASSWORD
+fail_unless_db
+fail_unless_os_service_running keystone
+
+if ! [ "$SWIFT_DB_PASSWORD" ]; then
+    SWIFT_DB_PASSWORD=$(openssl rand -hex 15)
+    export SWIFT_DB_PASSWORD
+fi
+
+sh /opt/swift/config-swift.sh container
+
+mysql -h ${MARIADB_SERVICE_HOST} -u root -p${DB_ROOT_PASSWORD} mysql <<EOF
+CREATE DATABASE IF NOT EXISTS ${SWIFT_DB_NAME};
+GRANT ALL PRIVILEGES ON swift* TO
+'${SWIFT_DB_USER}'@'%' IDENTIFIED BY '${SWIFT_DB_PASSWORD}'
+EOF
+
+export SERVICE_TOKEN="${KEYSTONE_ADMIN_TOKEN}"
+export SERVICE_ENDPOINT="${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:35357/v2.0"
+
+/bin/keystone user-create --name ${SWIFT_KEYSTONE_USER} --pass ${SWIFT_ADMIN_PASSWORD}
+/bin/keystone role-create --name ${SWIFT_KEYSTONE_USER}
+/bin/keystone user-role-add --user ${SWIFT_KEYSTONE_USER} --role admin --tenant ${ADMIN_TENANT_NAME}
+
+exec /usr/bin/swift-container-server
diff --git a/docker/common/swift/swift-object/start.sh b/docker/common/swift/swift-object/start.sh
new file mode 100644
index 0000000000000000000000000000000000000000..7ed97536e757761df6de4f040a88119c212053b8
--- /dev/null
+++ b/docker/common/swift/swift-object/start.sh
@@ -0,0 +1,34 @@
+#!/bin/bash
+
+: ${SWIFT_DB_USER:=swift}
+: ${SWIFT_DB_NAME:=swift}
+: ${KEYSTONE_AUTH_PROTOCOL:=http}
+: ${SWIFT_KEYSTONE_USER:=swift}
+: ${ADMIN_TENANT_NAME:=admin}
+
+check_required_vars KEYSTONE_ADMIN_TOKEN KEYSTONE_ADMIN_SERVICE_HOST \
+                    SWIFT_ADMIN_PASSWORD
+fail_unless_db
+fail_unless_os_service_running keystone
+
+if ! [ "$SWIFT_DB_PASSWORD" ]; then
+    SWIFT_DB_PASSWORD=$(openssl rand -hex 15)
+    export SWIFT_DB_PASSWORD
+fi
+
+sh /opt/swift/config-swift.sh engine
+
+mysql -h ${MARIADB_SERVICE_HOST} -u root -p${DB_ROOT_PASSWORD} mysql <<EOF
+CREATE DATABASE IF NOT EXISTS ${SWIFT_DB_NAME};
+GRANT ALL PRIVILEGES ON swift* TO
+'${SWIFT_DB_USER}'@'%' IDENTIFIED BY '${SWIFT_DB_PASSWORD}'
+EOF
+
+export SERVICE_TOKEN="${KEYSTONE_ADMIN_TOKEN}"
+export SERVICE_ENDPOINT="${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:35357/v2.0"
+
+/bin/keystone user-create --name ${SWIFT_KEYSTONE_USER} --pass ${SWIFT_ADMIN_PASSWORD}
+/bin/keystone role-create --name ${SWIFT_KEYSTONE_USER}
+/bin/keystone user-role-add --user ${SWIFT_KEYSTONE_USER} --role admin --tenant ${ADMIN_TENANT_NAME}
+
+exec /usr/bin/swift-object-server
diff --git a/docker/common/swift/swift-proxy-server/start.sh b/docker/common/swift/swift-proxy-server/start.sh
new file mode 100644
index 0000000000000000000000000000000000000000..3f387d187e4926b81c5747d861e677645cdf21a6
--- /dev/null
+++ b/docker/common/swift/swift-proxy-server/start.sh
@@ -0,0 +1,5 @@
+#!/bin/bash
+
+sh /opt/swift/config-swift.sh proxy
+
+exec /usr/bin/swift-proxy-server
diff --git a/docker/common/zaqar/check.sh b/docker/common/zaqar/check.sh
new file mode 100755
index 0000000000000000000000000000000000000000..4b3cdbb464930b0d2a5ce30e637aaa3ac9b9c4ab
--- /dev/null
+++ b/docker/common/zaqar/check.sh
@@ -0,0 +1,10 @@
+#!/bin/bash
+
+status=$(curl -s -w "%{http_code}" -o /dev/null http://localhost:8888/v1/queues)
+
+if [[ $status -ne 200 && $status -ne 204 ]]; then
+    echo "ERROR($status): queue list failed"
+    exit $status
+fi
+
+exit 0
diff --git a/docker/common/zaqar/start.sh b/docker/common/zaqar/start.sh
new file mode 100755
index 0000000000000000000000000000000000000000..6c68fccf22e0d941bd10b5e9bd776ab83172e07a
--- /dev/null
+++ b/docker/common/zaqar/start.sh
@@ -0,0 +1,64 @@
+#!/bin/sh
+
+set -e
+
+. /opt/kolla/kolla-common.sh
+
+: ${ADMIN_TENANT_NAME:=admin}
+: ${ZAQAR_KEYSTONE_USER:=zaqar}
+: ${KEYSTONE_AUTH_PROTOCOL:=http}
+
+check_required_vars ZAQAR_KEYSTONE_PASSWORD ZAQAR_SERVER_SERVICE_HOST \
+                    KEYSTONE_ADMIN_SERVICE_HOST KEYSTONE_ADMIN_TOKEN \
+                    PUBLIC_IP
+dump_vars
+
+#check_for_mongodb
+check_for_keystone
+
+cat > /openrc <<EOF
+export OS_AUTH_URL="http://${KEYSTONE_PUBLIC_SERVICE_HOST}:5000/v2.0"
+export OS_USERNAME="${ZAQAR_KEYSTONE_USER}"
+export OS_PASSWORD="${ZAQAR_KEYSTONE_PASSWORD}"
+export OS_TENANT_NAME="${ADMIN_TENANT_NAME}"
+EOF
+
+cfg=/etc/zaqar/zaqar.conf
+
+crudini --set $cfg DEFAULT log_file \
+    ""
+crudini --set $cfg DEFAULT use_stderr \
+    true
+
+crudini --set $cfg drivers storage \
+    sqlite
+
+crudini --set $cfg keystone_authtoken admin_password \
+    "${ZAQAR_KEYSTONE_PASSWORD}"
+crudini --set $cfg keystone_authtoken admin_user \
+    "${ZAQAR_KEYSTONE_USER}"
+crudini --set $cfg  keystone_authtoken admin_tenant_name \
+    "${ADMIN_TENANT_NAME}"
+crudini --set $cfg keystone_authtoken auth_uri \
+    "${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_PUBLIC_SERVICE_HOST}:5000/v2.0"
+crudini --set $cfg keystone_authtoken auth_protocol \
+    "${KEYSTONE_AUTH_PROTOCOL}"
+crudini --set $cfg keystone_authtoken auth_host \
+    "${KEYSTONE_PUBLIC_SERVICE_HOST}"
+crudini --set $cfg keystone_authtoken auth_port \
+    5000
+
+
+export SERVICE_TOKEN="${KEYSTONE_ADMIN_TOKEN}"
+export SERVICE_ENDPOINT="${KEYSTONE_AUTH_PROTOCOL}://${KEYSTONE_ADMIN_SERVICE_HOST}:35357/v2.0"
+crux user-create -n ${ZAQAR_KEYSTONE_USER} \
+    -p ${ZAQAR_KEYSTONE_PASSWORD} \
+    -t ${ADMIN_TENANT_NAME} \
+    -r admin
+
+crux endpoint-create --remove-all -n ${ZAQAR_KEYSTONE_USER} -t messaging \
+    -I "${KEYSTONE_AUTH_PROTOCOL}://${ZAQAR_SERVER_SERVICE_HOST}:8888" \
+    -P "${KEYSTONE_AUTH_PROTOCOL}://${PUBLIC_IP}:8888" \
+    -A "${KEYSTONE_AUTH_PROTOCOL}://${ZAQAR_SERVER_SERVICE_HOST}:8888"
+
+exec /usr/bin/zaqar-server
diff --git a/docker/fedora/binary/base/kolla-common.sh b/docker/fedora/binary/base/kolla-common.sh
index 380efbc3d71be8cfa47c37c5fd938c575de7126e..c265c62f7ae70d3fa72661782afc0be3affc49c8 120000
--- a/docker/fedora/binary/base/kolla-common.sh
+++ b/docker/fedora/binary/base/kolla-common.sh
@@ -1 +1 @@
-../../../common/kolla-common.sh
\ No newline at end of file
+../../../common/base/kolla-common.sh
\ No newline at end of file
diff --git a/docker/fedora/binary/base/service_hosts.sh b/docker/fedora/binary/base/service_hosts.sh
index 777b7334d593d689000f2f04ff473ad4545f1c41..06e0454405c1ccd8bfa27a6827cfed4af862b84f 120000
--- a/docker/fedora/binary/base/service_hosts.sh
+++ b/docker/fedora/binary/base/service_hosts.sh
@@ -1 +1 @@
-../../../common/service_hosts.sh
\ No newline at end of file
+../../../common/base/service_hosts.sh
\ No newline at end of file
diff --git a/docker/rhel/binary/base/kolla-common.sh b/docker/rhel/binary/base/kolla-common.sh
index 380efbc3d71be8cfa47c37c5fd938c575de7126e..c265c62f7ae70d3fa72661782afc0be3affc49c8 120000
--- a/docker/rhel/binary/base/kolla-common.sh
+++ b/docker/rhel/binary/base/kolla-common.sh
@@ -1 +1 @@
-../../../common/kolla-common.sh
\ No newline at end of file
+../../../common/base/kolla-common.sh
\ No newline at end of file
diff --git a/docker/rhel/binary/base/service_hosts.sh b/docker/rhel/binary/base/service_hosts.sh
index 777b7334d593d689000f2f04ff473ad4545f1c41..06e0454405c1ccd8bfa27a6827cfed4af862b84f 120000
--- a/docker/rhel/binary/base/service_hosts.sh
+++ b/docker/rhel/binary/base/service_hosts.sh
@@ -1 +1 @@
-../../../common/service_hosts.sh
\ No newline at end of file
+../../../common/base/service_hosts.sh
\ No newline at end of file