WIP: CORD-1017 Dockerization of monitoring service components

Change-Id: I9f120450d838285b9a21fd8a3470fd3f694738a8
diff --git a/xos/synchronizer/ceilometer/dockerized_ceilometer_service/README.md b/xos/synchronizer/ceilometer/dockerized_ceilometer_service/README.md
new file mode 100644
index 0000000..ec42acc
--- /dev/null
+++ b/xos/synchronizer/ceilometer/dockerized_ceilometer_service/README.md
@@ -0,0 +1,49 @@
+# dockerized-monitoring service
+
+NOTE: This is a WIP activity and not completed yet
+
+The target of this activity is to containarize all the components that constitute CORD Monitoring service
+
+Following are the various modules in CORD Monitoring service
+
+Infrastructure components:
+- Rabbitmq
+- Kafka & Zookeeper
+- MongoDB
+- KeyStone
+- MySQL DB for KeyStone
+CORD specific/extended components:
+- Ceilometer-notification-agent
+- Ceilometer-api
+- CORD Publish/Subscribe module on top of Ceilometer data
+
+The plan is to leverage publicly available containers for all the infrastructure components as much as possible.
+However, in our exploration, we found that public offcial docker images are not available for many of the above components.
+Instead, there are private docker images available, but there is a risk associated in terms of maintenance and support for such images
+For CORD specific components, we need to create the docker container ourselves.
+
+Below are the steps to create custom VM images with all the above necessary containers to be used by XOS (TODO: Create Ansible script for the same and refer to it)
+1. Create ubuntu 14.04 based VM
+2. Install Docker: wget -qO- https://get.docker.com/ | sh
+3. Add user to docker group: sudo usermod -aG docker $USER
+4. Install docker-compose
+5. docker pull rabbitmq:3-management
+6. docker pull spotify/kafka
+7. docker pull mongo:3.4
+8. docker pull srikanthvavila/ceilometer-agent-notification
+9. docker pull srikanthvavila/cord-publish-subscribe
+10. copy dockerized_ceilometer_service/docker-compose.yml file (Pending: The IP addresses need to be parameterized so that they can be provided when the VM is actually booted)
+
+
+While instantiating monitoring service in CORD:
+1. Ensure the IP addresses are updated with the VM's fabric interface IP address
+2. docker-compose up -d
+
+
+PENDING:
+1. Build ceilometer-api container the same way ceilometer-agent-notification is built
+2. Explore availability of docker container for MySQL DB 
+3. Explore availability of Keystone docker container (Explore https://github.com/int32bit/docker-keystone)
+4. Configuration of MySQL DB and Keystone to allow ceilometer-api to provide its services
+5. Currently spotify/kafka container embeds the zookeeper service also. Explore availability of container image for kafka and zookeeper such that kafka can be scaled independently (Explore https://github.com/wurstmeister/kafka-docker)
+6. Explore if MongoDB can be replaced with Gnocchi component and update ceilometer-agent-notification/Dockerfile to do corresponding Gnocchi related configurations. Once migration to Gnocchi is completed, ceilometer-api conatiner is not needed, instead Gnocchi API will be used 
diff --git a/xos/synchronizer/ceilometer/dockerized_ceilometer_service/ceilometer-agent-notification/Dockerfile.ceilo-agent-notification b/xos/synchronizer/ceilometer/dockerized_ceilometer_service/ceilometer-agent-notification/Dockerfile.ceilo-agent-notification
new file mode 100644
index 0000000..f8bc8bc
--- /dev/null
+++ b/xos/synchronizer/ceilometer/dockerized_ceilometer_service/ceilometer-agent-notification/Dockerfile.ceilo-agent-notification
@@ -0,0 +1,48 @@
+# Dockerfile.ceilo-agent-notification: docker file for building srikanthvavila/ceilometer-agent-notification container
+# It is built on top of srikanthvavila/ceilometer-base container
+
+FROM srikanthvavila/ceilometer-base
+LABEL maintainer "Open Networking Lab"
+
+ADD start-ceilo-agent-notification.sh /usr/bin/start-ceilo-agent-notification.sh
+RUN chmod +x /usr/bin/start-ceilo-agent-notification.sh
+#ADD ceilo-agent-notification.conf /etc/supervisor/conf.d/
+
+#CORD Monitoring service specific changes
+#Clone cord monitoring repository
+RUN git clone https://github.com/opencord/monitoring.git /opt/cord/monitoring/
+#Copy CORD specific ceilometer plugins to this container.
+RUN cp -r /opt/cord/monitoring/xos/synchronizer/ceilometer/ceilometer-plugins/network/ext_services /usr/local/lib/python2.7/dist-packages/ceilometer/network/ 
+#Copy the script that updates ceilometer entry_points.txt to load the above CORD specific plugins
+ADD load-ceilo-plugins.sh /usr/bin/load-ceilo-plugins.sh
+#Copy CORD specific pipeline.yaml file to this container.
+ADD pipeline.yaml /etc/ceilometer/pipeline.yaml
+#Copy the script that updates pipeline with other publishers (like kafka...etc) at run time based on the user inputs
+ADD update-pipeline.sh /usr/bin/update-pipeline.sh
+#Install kafka-python
+RUN pip install kafka-python
+#Add ceilometer kafka broker patch.
+#There is a bug in ceilometer/publisher/kafka_broker.py that causes inconsistent kafka publishing behavior
+#The patch is pulled from ceilometer master branch: https://review.openstack.org/#/c/392637/5/ceilometer/publisher/kafka_broker.py
+#On top of that patch, a minor change is done in _send() method to make it work with mitaka code base
+COPY ceilometer_kafka_patch/kafka_broker.py /usr/local/lib/python2.7/dist-packages/ceilometer/publisher/
+
+RUN echo "#!/bin/bash" > /usr/bin/create-mongo-user-db.sh
+RUN echo "if [ ! -z \"\$USE_MONGODB\" ]; then mongo --host mongodb --eval 'db = db.getSiblingDB(\"ceilometer\"); db.createUser({user: \"ceilometer\", pwd: \"password\", roles: [ \"readWrite\", \"dbAdmin\" ]})'; fi" >> /usr/bin/create-mongo-user-db.sh 
+RUN chmod +x /usr/bin/create-mongo-user-db.sh
+
+RUN echo "#!/bin/bash" > /usr/bin/config-ceilometer-mongo.sh
+RUN echo "if [ ! -z \"\$USE_MONGODB\" ]; then sed -r -i \"s,[#]*(metering_connection) = (.*),metering_connection = mongodb://ceilometer:password@mongodb:27017/ceilometer,g\" /etc/ceilometer/ceilometer.conf; fi" >> /usr/bin/config-ceilometer-mongo.sh
+RUN echo "if [ ! -z \"\$USE_MONGODB\" ]; then sed -r -i \"s,[#]*(event_connection) = (.*),event_connection = mongodb://ceilometer:password@mongodb:27017/ceilometer,g\" /etc/ceilometer/ceilometer.conf; fi" >> /usr/bin/config-ceilometer-mongo.sh
+RUN chmod +x /usr/bin/config-ceilometer-mongo.sh
+
+#Create a script that runs all the needed shell scripts when the container is started
+RUN echo "#!/bin/bash" > /usr/bin/deploy-ceilo-agent-notification
+RUN echo "bash /usr/bin/create-mongo-user-db.sh" >> /usr/bin/deploy-ceilo-agent-notification
+RUN echo "bash /usr/bin/load-ceilo-plugins.sh" >> /usr/bin/deploy-ceilo-agent-notification
+RUN echo "bash /usr/bin/update-pipeline.sh" >> /usr/bin/deploy-ceilo-agent-notification
+RUN echo "bash /usr/bin/config-ceilometer-mongo.sh" >> /usr/bin/deploy-ceilo-agent-notification
+RUN echo "/usr/bin/start-ceilo-agent-notification.sh" >> /usr/bin/deploy-ceilo-agent-notification
+RUN chmod +x /usr/bin/deploy-ceilo-agent-notification
+
+CMD ["/usr/bin/deploy-ceilo-agent-notification"]
diff --git a/xos/synchronizer/ceilometer/dockerized_ceilometer_service/ceilometer-agent-notification/ceilometer_kafka_patch/kafka_broker.py b/xos/synchronizer/ceilometer/dockerized_ceilometer_service/ceilometer-agent-notification/ceilometer_kafka_patch/kafka_broker.py
new file mode 100644
index 0000000..2ceaa33
--- /dev/null
+++ b/xos/synchronizer/ceilometer/dockerized_ceilometer_service/ceilometer-agent-notification/ceilometer_kafka_patch/kafka_broker.py
@@ -0,0 +1,100 @@
+#
+# Copyright 2015 Cisco Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+import kafka
+from oslo_log import log
+from oslo_serialization import jsonutils
+from oslo_utils import netutils
+from six.moves.urllib import parse as urlparse
+
+from ceilometer.i18n import _LE
+from ceilometer.publisher import messaging
+
+LOG = log.getLogger(__name__)
+
+
+class KafkaBrokerPublisher(messaging.MessagingPublisher):
+    """Publish metering data to kafka broker.
+
+    The ip address and port number of kafka broker should be configured in
+    ceilometer pipeline configuration file. If an ip address is not specified,
+    this kafka publisher will not publish any meters.
+
+    To enable this publisher, add the following section to the
+    /etc/ceilometer/pipeline.yaml file or simply add it to an existing
+    pipeline::
+
+        meter:
+            - name: meter_kafka
+            interval: 600
+            counters:
+                - "*"
+            transformers:
+            sinks:
+                - kafka_sink
+        sinks:
+            - name: kafka_sink
+            transformers:
+            publishers:
+                - kafka://[kafka_broker_ip]:[kafka_broker_port]?topic=[topic]
+
+    Kafka topic name and broker's port are required for this publisher to work
+    properly. If topic parameter is missing, this kafka publisher publish
+    metering data under a topic name, 'ceilometer'. If the port number is not
+    specified, this Kafka Publisher will use 9092 as the broker's port.
+    This publisher has transmit options such as queue, drop, and retry. These
+    options are specified using policy field of URL parameter. When queue
+    option could be selected, local queue length can be determined using
+    max_queue_length field as well. When the transfer fails with retry
+    option, try to resend the data as many times as specified in max_retry
+    field. If max_retry is not specified, default the number of retry is 100.
+    """
+
+    def __init__(self, parsed_url):
+        super(KafkaBrokerPublisher, self).__init__(parsed_url)
+        options = urlparse.parse_qs(parsed_url.query)
+
+        self._producer = None
+        self._host, self._port = netutils.parse_host_port(
+            parsed_url.netloc, default_port=9092)
+        self._topic = options.get('topic', ['ceilometer'])[-1]
+        self.max_retry = int(options.get('max_retry', [100])[-1])
+
+    def _ensure_connection(self):
+        if self._producer:
+            return
+
+        try:
+            self._producer = kafka.KafkaProducer(
+                bootstrap_servers=["%s:%s" % (self._host, self._port)])
+        except kafka.errors.KafkaError as e:
+            LOG.exception(_LE("Failed to connect to Kafka service: %s"), e)
+            raise messaging.DeliveryFailure('Kafka Client is not available, '
+                                            'please restart Kafka client')
+        except Exception as e:
+            LOG.exception(_LE("Failed to connect to Kafka service: %s"), e)
+            raise messaging.DeliveryFailure('Kafka Client is not available, '
+                                            'please restart Kafka client')
+
+    def _send(self, context, event_type, data):
+        self._ensure_connection()
+        # TODO(sileht): don't split the payload into multiple network
+        # message ... but how to do that without breaking consuming
+        # application...
+        try:
+            for d in data:
+                self._producer.send(self._topic, jsonutils.dumps(d))
+        except Exception as e:
+            messaging.raise_delivery_failure(e)
diff --git a/xos/synchronizer/ceilometer/dockerized_ceilometer_service/ceilometer-agent-notification/load-ceilo-plugins.sh b/xos/synchronizer/ceilometer/dockerized_ceilometer_service/ceilometer-agent-notification/load-ceilo-plugins.sh
new file mode 100644
index 0000000..0f5cce4
--- /dev/null
+++ b/xos/synchronizer/ceilometer/dockerized_ceilometer_service/ceilometer-agent-notification/load-ceilo-plugins.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+declare -a plugins=("vcpe= ceilometer.network.ext_services.vcpe.notifications:VCPENotification"
+"vcpe.compute.stats= ceilometer.network.ext_services.vcpe.notifications:VCPEComputeStatistics"
+"vcpe.dns.cache.size=ceilometer.network.ext_services.vcpe.notifications:VCPEDNSCacheSize"
+"vcpe.dns.total_instered_entries=ceilometer.network.ext_services.vcpe.notifications:VCPEDNSTotalInsertedEntries"
+"vcpe.dns.replaced_unexpired_entries= ceilometer.network.ext_services.vcpe.notifications:VCPEDNSReplacedUnexpiredEntries"
+"vcpe.dns.queries_answered_locally= ceilometer.network.ext_services.vcpe.notifications:VCPEDNSQueriesAnsweredLocally"
+"vcpe.dns.queries_forwarded= ceilometer.network.ext_services.vcpe.notifications:VCPEDNSQueriesForwarded"
+"vcpe.dns.server.queries_sent= ceilometer.network.ext_services.vcpe.notifications:VCPEDNSServerQueriesSent"
+"vcpe.dns.server.queries_failed= ceilometer.network.ext_services.vcpe.notifications:VCPEDNSServerQueriesFailed"
+"volt.device= ceilometer.network.ext_services.volt.notifications:VOLTDeviceNotification"
+"volt.device.subscribers= ceilometer.network.ext_services.volt.notifications:VOLTDeviceSubscriberNotification"
+"infra=ceilometer.network.ext_services.openstack_infra.notifications:OPENSTACK_INFRANotification"
+"cord=ceilometer.network.ext_services.cord.notifications:CORDNotificationBase"
+"broadview.bst.device=ceilometer.network.ext_services.broadview.notifications:BroadViewNotificationBase")
+
+section='ceilometer.notification'
+for line in "${plugins[@]}"
+do
+   sed -i -e '/\['$section'\]/{;:a;n;/^$/!ba;i\'"$line"'' -e '}' /usr/local/lib/python2.7/dist-packages/ceilometer*egg*/entry_points.txt
+done
+
diff --git a/xos/synchronizer/ceilometer/dockerized_ceilometer_service/ceilometer-agent-notification/pipeline.yaml b/xos/synchronizer/ceilometer/dockerized_ceilometer_service/ceilometer-agent-notification/pipeline.yaml
new file mode 100644
index 0000000..df39046
--- /dev/null
+++ b/xos/synchronizer/ceilometer/dockerized_ceilometer_service/ceilometer-agent-notification/pipeline.yaml
@@ -0,0 +1,92 @@
+---
+sources:
+    - name: meter_source
+      interval: 600
+      meters:
+          - "*"
+      sinks:
+          - meter_sink
+    - name: cpu_source
+      interval: 600
+      meters:
+          - "cpu"
+      sinks:
+          - cpu_sink
+          - cpu_delta_sink
+    - name: disk_source
+      interval: 600
+      meters:
+          - "disk.read.bytes"
+          - "disk.read.requests"
+          - "disk.write.bytes"
+          - "disk.write.requests"
+          - "disk.device.read.bytes"
+          - "disk.device.read.requests"
+          - "disk.device.write.bytes"
+          - "disk.device.write.requests"
+      sinks:
+          - disk_sink
+    - name: network_source
+      interval: 600
+      meters:
+          - "network.incoming.bytes"
+          - "network.incoming.packets"
+          - "network.outgoing.bytes"
+          - "network.outgoing.packets"
+      sinks:
+          - network_sink
+sinks:
+    - name: meter_sink
+      transformers:
+      publishers:
+          - direct://
+    - name: cpu_sink
+      transformers:
+          - name: "rate_of_change"
+            parameters:
+                target:
+                    name: "cpu_util"
+                    unit: "%"
+                    type: "gauge"
+                    scale: "100.0 / (10**9 * (resource_metadata.cpu_number or 1))"
+      publishers:
+          - direct://
+    - name: cpu_delta_sink
+      transformers:
+          - name: "delta"
+            parameters:
+                target:
+                    name: "cpu.delta"
+                growth_only: True
+      publishers:
+          - direct://
+    - name: disk_sink
+      transformers:
+          - name: "rate_of_change"
+            parameters:
+                source:
+                    map_from:
+                        name: "(disk\\.device|disk)\\.(read|write)\\.(bytes|requests)"
+                        unit: "(B|request)"
+                target:
+                    map_to:
+                        name: "\\1.\\2.\\3.rate"
+                        unit: "\\1/s"
+                    type: "gauge"
+      publishers:
+          - direct://
+    - name: network_sink
+      transformers:
+          - name: "rate_of_change"
+            parameters:
+                source:
+                   map_from:
+                       name: "network\\.(incoming|outgoing)\\.(bytes|packets)"
+                       unit: "(B|packet)"
+                target:
+                    map_to:
+                        name: "network.\\1.\\2.rate"
+                        unit: "\\1/s"
+                    type: "gauge"
+      publishers:
+          - direct://
diff --git a/xos/synchronizer/ceilometer/dockerized_ceilometer_service/ceilometer-agent-notification/start-ceilo-agent-notification.sh b/xos/synchronizer/ceilometer/dockerized_ceilometer_service/ceilometer-agent-notification/start-ceilo-agent-notification.sh
new file mode 100644
index 0000000..3f57a8d
--- /dev/null
+++ b/xos/synchronizer/ceilometer/dockerized_ceilometer_service/ceilometer-agent-notification/start-ceilo-agent-notification.sh
@@ -0,0 +1,17 @@
+#!/bin/sh
+
+if [ ! -z "$RABBIT_TRANSPORT_URL" ]; then
+   sed -r -i "s,[#]*(transport_url) = (.*),\1 = $RABBIT_TRANSPORT_URL,g" /etc/ceilometer/ceilometer.conf
+fi
+if [ ! -z "$RABBIT_HOST" ]; then
+   sed -r -i "s/[#]*(rabbit_host) = (.*)/\1 = $RABBIT_HOST/g" /etc/ceilometer/ceilometer.conf
+fi
+if [ ! -z "$RABBIT_USER" ]; then
+   sed -r -i "s/[#]*(rabbit_userid) = (.*)/\1 = $RABBIT_USER/g" /etc/ceilometer/ceilometer.conf
+fi
+if [ ! -z "$RABBIT_PASS" ]; then
+   sed -r -i "s/[#]*(rabbit_password) = (.*)/\1 = $RABBIT_PASS/g" /etc/ceilometer/ceilometer.conf
+fi
+
+#Run ceilometer-agent-notification
+/usr/local/bin/ceilometer-agent-notification
diff --git a/xos/synchronizer/ceilometer/dockerized_ceilometer_service/ceilometer-agent-notification/update-pipeline.sh b/xos/synchronizer/ceilometer/dockerized_ceilometer_service/ceilometer-agent-notification/update-pipeline.sh
new file mode 100644
index 0000000..6c3e7dd
--- /dev/null
+++ b/xos/synchronizer/ceilometer/dockerized_ceilometer_service/ceilometer-agent-notification/update-pipeline.sh
@@ -0,0 +1,6 @@
+#!/bin/sh
+
+#Insert specified kafka url AFTER the match text
+if [ ! -z "$KAFKA_PUBLISHER_URL" ]; then
+   sed -i "/publishers:/a \ \ \ \ \ \ \ \ \ \ - $KAFKA_PUBLISHER_URL" /etc/ceilometer/pipeline.yaml
+fi
diff --git a/xos/synchronizer/ceilometer/dockerized_ceilometer_service/ceilometer-base/.Dockerfile.ceilo-base.swp b/xos/synchronizer/ceilometer/dockerized_ceilometer_service/ceilometer-base/.Dockerfile.ceilo-base.swp
new file mode 100644
index 0000000..d2a16b3
--- /dev/null
+++ b/xos/synchronizer/ceilometer/dockerized_ceilometer_service/ceilometer-base/.Dockerfile.ceilo-base.swp
Binary files differ
diff --git a/xos/synchronizer/ceilometer/dockerized_ceilometer_service/ceilometer-base/Dockerfile.ceilo-base b/xos/synchronizer/ceilometer/dockerized_ceilometer_service/ceilometer-base/Dockerfile.ceilo-base
new file mode 100644
index 0000000..f70e7c9
--- /dev/null
+++ b/xos/synchronizer/ceilometer/dockerized_ceilometer_service/ceilometer-base/Dockerfile.ceilo-base
@@ -0,0 +1,48 @@
+# Dockerfile.ceilo-base: docker file for srikanthvavila/ceilometer-base
+# This image isn't used directly, but installs the prereqs for the other ceilometer images
+# Build this docker container before building other ceilometer containers
+# Build command: `pushd ceilometer-base;docker build -f Dockerfile.ceilo-base -t srikanthvavila/ceilometer-base
+# TODO: Remove srikanthvavila and use some official OpenCORD tag for all these containers
+FROM ubuntu:14.04.5
+LABEL maintainer "Open Networking Lab"
+
+# Install.
+RUN \
+  sed -i 's/# \(.*multiverse$\)/\1/g' /etc/apt/sources.list && \
+  apt-get update && \
+  apt-get -y upgrade && \
+  apt-get install -y build-essential && \
+  apt-get install -y software-properties-common && \
+  apt-get install -y byobu curl git htop man unzip vim wget supervisor python-dev python-pip libpq-dev && \
+  rm -rf /var/lib/apt/lists/*
+
+RUN pip install tox==1.6.1
+RUN pip install 'oslo.config<2.0.0'
+RUN pip install 'oslo.service'
+RUN pip install 'oslo.messaging'
+RUN pip install 'retrying'
+RUN pip install 'tooz'
+RUN pip install 'jsonpath-rw-ext'
+RUN pip install 'oslo.db'
+RUN pip install 'oslo.reports'
+RUN pip install 'python-keystoneclient'
+
+#Clone Ceilometer
+RUN git clone -b stable/mitaka https://github.com/openstack/ceilometer.git /opt/stack/ceilometer/
+
+WORKDIR /opt/stack/ceilometer
+RUN python setup.py install
+RUN mkdir -p /etc/ceilometer
+RUN tox -egenconfig
+RUN cp /opt/stack/ceilometer/etc/ceilometer/*.json /etc/ceilometer
+RUN cp /opt/stack/ceilometer/etc/ceilometer/*.yaml /etc/ceilometer
+RUN cp /opt/stack/ceilometer/etc/ceilometer/ceilometer.conf /etc/ceilometer/ceilometer.conf
+
+# Install Mongo shell utilities.
+RUN \
+  apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 0C49F3730359A14518585931BC711F9BA15703C6 && \
+  echo "deb [ arch=amd64 ] http://repo.mongodb.org/apt/ubuntu trusty/mongodb-org/3.4 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.4.list && \
+  apt-get update && \
+  apt-get install -y mongodb-org-shell
+
+RUN pip install 'pymongo'
diff --git a/xos/synchronizer/ceilometer/dockerized_ceilometer_service/cord-publish-subscribe/Dockerfile.publish-subscribe b/xos/synchronizer/ceilometer/dockerized_ceilometer_service/cord-publish-subscribe/Dockerfile.publish-subscribe
new file mode 100644
index 0000000..de840df
--- /dev/null
+++ b/xos/synchronizer/ceilometer/dockerized_ceilometer_service/cord-publish-subscribe/Dockerfile.publish-subscribe
@@ -0,0 +1,31 @@
+FROM ubuntu:14.04.5
+LABEL maintainer "Open Networking Lab"
+
+# Install.
+RUN \
+  sed -i 's/# \(.*multiverse$\)/\1/g' /etc/apt/sources.list && \
+  apt-get update && \
+  apt-get -y upgrade && \
+  apt-get install -y curl git python-dev python-pip
+
+RUN pip install msgpack-python
+RUN pip install oslo.utils
+RUN pip install oslo.config
+RUN pip install netifaces
+RUN pip install Babel
+RUN pip install Flask
+RUN pip install kafka-python
+RUN pip install wrapt
+
+#Clone cord monitoring repository
+RUN git clone https://github.com/opencord/monitoring.git /opt/cord/monitoring/
+
+WORKDIR /opt/cord/monitoring/xos/synchronizer/ceilometer/ceilometer_pub_sub/
+RUN chmod +x sub_main.py
+
+RUN echo "#!/bin/sh" > deploy-cord-publish-subscribe
+RUN echo "if [ ! -z \"\$KAFKA_URL\" ]; then sed -r -i \"s,^(target) = (.*),target = \$KAFKA_URL,g\" pub_sub.conf; fi" >> deploy-cord-publish-subscribe 
+RUN echo "python sub_main.py" >> deploy-cord-publish-subscribe 
+RUN chmod +x deploy-cord-publish-subscribe
+
+CMD ["./deploy-cord-publish-subscribe"]
diff --git a/xos/synchronizer/ceilometer/dockerized_ceilometer_service/docker-compose.yml b/xos/synchronizer/ceilometer/dockerized_ceilometer_service/docker-compose.yml
new file mode 100644
index 0000000..955bf28
--- /dev/null
+++ b/xos/synchronizer/ceilometer/dockerized_ceilometer_service/docker-compose.yml
@@ -0,0 +1,56 @@
+# Docker-compose for CORD Monitoring Service
+#TODO: The IP addresses in this file need to be parameterized and set when the monitoring service is instantiated through XOS synchronizer
+
+rabbit1:
+  image: "rabbitmq:3-management"
+  hostname: "rabbit1"
+  environment:
+    RABBITMQ_ERLANG_COOKIE: "SWQOKODSQALRPCLNMEQG"
+    RABBITMQ_DEFAULT_USER: "openstack"
+    RABBITMQ_DEFAULT_PASS: "password"
+    RABBITMQ_DEFAULT_VHOST: "/"
+  ports:
+    - "15672:15672"
+    - "5672:5672"
+  labels:
+    NAME: "rabbitmq1"
+
+mongodb1:
+  image: "mongo:3.4"
+  ports:
+    - "27017:27017"
+  labels:
+    NAME: "mongodb1"
+
+kafka1:
+  image: "spotify/kafka"
+  hostname: "kafka1"
+  ports:
+    - "2181:2181"
+    - "9092:9092"
+  environment:
+    ADVERTISED_HOST: "10.0.5.5"
+    ADVERTISED_PORT: "9092"
+  labels:
+    NAME: "kafka1"
+
+ceilo-notification1:
+  image: "srikanthvavila/ceilometer-agent-notification"
+  labels:
+    NAME: "ceilometer-agent-notification"
+  links:
+    - rabbit1
+    - mongodb1:mongodb
+  environment:
+    RABBIT_TRANSPORT_URL: rabbit://openstack:password@rabbit1:5672//
+    KAFKA_PUBLISHER_URL: kafka://10.0.5.5:9092/topic=ceilometer
+    USE_MONGODB: 1
+
+cord-publish-subscribe:
+  image: "srikanthvavila/cord-publish-subscribe"
+  ports:
+    - "4455:4455"
+  labels:
+    NAME: "cord-publish-subscribe"
+  environment:
+    KAFKA_URL: kafka://10.0.5.5:9092/topic=ceilometer