From 653f1847336ff40ebfd54952db86e731fe2cadc6 Mon Sep 17 00:00:00 2001
From: Miguel Cantu <root@10-127-83-3.cook.book>
Date: Mon, 6 Apr 2015 14:39:11 +0000
Subject: [PATCH] Implement Ceilometer

This patch implements the implement-ceilometer blueprint.
It addes the necessary role/variables to deploy ceilometer
with a Mongodb backend. The Monogdb backend is assumed to
be up and configured and the playbooks only require a few
values to be set in user_variables to establish a connection.

Change-Id: I2164a1f27f632ce254cc2711ada2c449a9961fed
Implements: blueprint implement-ceilometer
---
 .../install-guide/configure-ceilometer.rst    | 137 +++++++
 .../conf.d/ceilometer.yml.aio                 |   9 +
 .../conf.d/ceilometer.yml.example             |  13 +
 etc/openstack_deploy/env.d/ceilometer.yml     |  68 ++++
 etc/openstack_deploy/user_group_vars.yml      |  16 +
 etc/openstack_deploy/user_secrets.yml         |   5 +
 etc/openstack_deploy/user_variables.yml       |  11 +
 .../repo_packages/openstack_services.yml      |   6 +
 playbooks/os-ceilometer-install.yml           |  74 ++++
 .../roles/os_ceilometer/CONTRIBUTING.rst      |  85 ++++
 playbooks/roles/os_ceilometer/LICENSE         | 202 ++++++++++
 playbooks/roles/os_ceilometer/README.rst      |  22 ++
 .../roles/os_ceilometer/defaults/main.yml     |  95 +++++
 .../roles/os_ceilometer/files/policy.json     |   7 +
 .../roles/os_ceilometer/handlers/main.yml     |  65 +++
 playbooks/roles/os_ceilometer/meta/main.yml   |  35 ++
 .../tasks/ceilometer_install.yml              |  42 ++
 .../tasks/ceilometer_post_install.yml         |  47 +++
 .../tasks/ceilometer_pre_install.yml          | 102 +++++
 .../tasks/ceilometer_service_add.yml          |  85 ++++
 .../tasks/ceilometer_service_setup.yml        |  30 ++
 .../tasks/ceilometer_upstart_common_init.yml  |  31 ++
 .../tasks/ceilometer_upstart_init.yml         |  91 +++++
 playbooks/roles/os_ceilometer/tasks/main.yml  |  23 ++
 .../os_ceilometer/templates/api_paste.ini.j2  |  17 +
 .../templates/ceilometer-upstart-init.j2      |  42 ++
 .../templates/ceilometer.conf.j2              |  51 +++
 .../templates/event_definitions.yaml.j2       | 369 ++++++++++++++++++
 .../templates/event_pipeline.yaml.j2          |  13 +
 .../os_ceilometer/templates/pipeline.yaml.j2  |  83 ++++
 .../roles/os_ceilometer/templates/sudoers.j2  |   3 +
 playbooks/roles/os_cinder/defaults/main.yml   |   3 +
 .../roles/os_cinder/templates/cinder.conf.j2  |   5 +
 playbooks/roles/os_glance/defaults/main.yml   |   4 +
 .../os_glance/templates/glance-api.conf.j2    |   6 +-
 .../templates/glance-registry.conf.j2         |   6 +
 playbooks/roles/os_heat/defaults/main.yml     |   3 +
 .../roles/os_heat/templates/heat.conf.j2      |   5 +
 playbooks/roles/os_nova/defaults/main.yml     |   3 +
 .../roles/os_nova/templates/nova.conf.j2      |   8 +
 playbooks/roles/os_swift/defaults/main.yml    |  11 +
 .../os_swift/tasks/swift_service_setup.yml    |  32 ++
 .../os_swift/templates/proxy-server.conf.j2   |  26 ++
 playbooks/setup-openstack.yml                 |   1 +
 playbooks/vars/configs/haproxy_config.yml     |   5 +
 scripts/bootstrap-aio.sh                      |  32 ++
 scripts/run-playbooks.sh                      |   9 +
 47 files changed, 2037 insertions(+), 1 deletion(-)
 create mode 100644 doc/source/install-guide/configure-ceilometer.rst
 create mode 100644 etc/openstack_deploy/conf.d/ceilometer.yml.aio
 create mode 100644 etc/openstack_deploy/conf.d/ceilometer.yml.example
 create mode 100644 etc/openstack_deploy/env.d/ceilometer.yml
 create mode 100644 playbooks/os-ceilometer-install.yml
 create mode 100644 playbooks/roles/os_ceilometer/CONTRIBUTING.rst
 create mode 100644 playbooks/roles/os_ceilometer/LICENSE
 create mode 100644 playbooks/roles/os_ceilometer/README.rst
 create mode 100644 playbooks/roles/os_ceilometer/defaults/main.yml
 create mode 100644 playbooks/roles/os_ceilometer/files/policy.json
 create mode 100644 playbooks/roles/os_ceilometer/handlers/main.yml
 create mode 100644 playbooks/roles/os_ceilometer/meta/main.yml
 create mode 100644 playbooks/roles/os_ceilometer/tasks/ceilometer_install.yml
 create mode 100644 playbooks/roles/os_ceilometer/tasks/ceilometer_post_install.yml
 create mode 100644 playbooks/roles/os_ceilometer/tasks/ceilometer_pre_install.yml
 create mode 100644 playbooks/roles/os_ceilometer/tasks/ceilometer_service_add.yml
 create mode 100644 playbooks/roles/os_ceilometer/tasks/ceilometer_service_setup.yml
 create mode 100644 playbooks/roles/os_ceilometer/tasks/ceilometer_upstart_common_init.yml
 create mode 100644 playbooks/roles/os_ceilometer/tasks/ceilometer_upstart_init.yml
 create mode 100644 playbooks/roles/os_ceilometer/tasks/main.yml
 create mode 100644 playbooks/roles/os_ceilometer/templates/api_paste.ini.j2
 create mode 100644 playbooks/roles/os_ceilometer/templates/ceilometer-upstart-init.j2
 create mode 100644 playbooks/roles/os_ceilometer/templates/ceilometer.conf.j2
 create mode 100644 playbooks/roles/os_ceilometer/templates/event_definitions.yaml.j2
 create mode 100644 playbooks/roles/os_ceilometer/templates/event_pipeline.yaml.j2
 create mode 100644 playbooks/roles/os_ceilometer/templates/pipeline.yaml.j2
 create mode 100644 playbooks/roles/os_ceilometer/templates/sudoers.j2

diff --git a/doc/source/install-guide/configure-ceilometer.rst b/doc/source/install-guide/configure-ceilometer.rst
new file mode 100644
index 0000000000..f8abd7647b
--- /dev/null
+++ b/doc/source/install-guide/configure-ceilometer.rst
@@ -0,0 +1,137 @@
+`Home <index.html>`__ OpenStack Ansible Installation Guide
+
+Configuring the Ceilometer service (optional)
+---------------------------------------------
+
+The Telemetry module(Ceilometer) performs the following functions:
+
+  - Efficiently polls metering data related to OpenStack services.
+
+  - Collects event and metering data by monitoring notifications sent from services.
+
+  - Publishes collected data to various targets including data stores and message queues.
+
+  - Creates alarms when collected data breaks defined rules.
+
+Ceilometer on OSAD requires a monogodb backend to be configured prior to running the ceilometer playbooks. A connection string will then need to be given in the ``user_variables.yml`` file(See section Configuring User Data below).
+
+
+Setting up a Mongodb database for ceilometer
+############################################
+
+1. Install the MongoDB package:
+
+  .. code-block:: shell
+
+    apt-get install mongodb-server mongodb-clients python-pymongo
+
+2. Edit the ``/etc/mongodb.conf`` file and change the bind_ip to the management interface of the node your running this on.
+
+  .. code-block:: shell
+
+    bind_ip = 10.0.0.11
+
+3. Edit the ``/etc/mongodb.conf`` file and enable smallfiles
+
+  .. code-block:: shell
+
+    smallfiles = true
+
+4. Restart the mongodb service
+
+  .. code-block:: shell
+
+    service mongodb restart
+
+5. Create the ceilometer database
+
+  .. code-block:: shell
+
+        # mongo --host controller --eval '
+      db = db.getSiblingDB("ceilometer");
+      db.addUser({user: "ceilometer",
+      pwd: "CEILOMETER_DBPASS",
+      roles: [ "readWrite", "dbAdmin" ]})'
+
+    MongoDB shell version: 2.4.x
+    connecting to: controller:27017/test
+    {
+     "user" : "ceilometer",
+     "pwd" : "72f25aeee7ad4be52437d7cd3fc60f6f",
+     "roles" : [
+      "readWrite",
+      "dbAdmin"
+     ],
+     "_id" : ObjectId("5489c22270d7fad1ba631dc3")
+    }
+
+NOTE: The ``CEILOMETER_DBPASS`` must match the ``ceilometer_container_db_password`` in the ``/etc/openstack_deploy/user_secrets.yml`` file. This is how ansible knows how to configure the connection string within the ceilometer configuration files.
+
+Configuring the hosts
+#####################
+
+Ceilometer can be configured by specifying the ``metering-compute_hosts`` and ``metering-infra_hosts`` directives in the ``/etc/openstack_deploy/conf.d/ceilometer.yml`` file. Below is the example included in the ``etc/openstack_deploy/conf.d/ceilometer.yml.example`` file:
+
+.. code-block:: yaml
+
+    # The compute host that the ceilometer compute agent will be running on.
+    metering-compute_hosts:
+      compute1:
+        ip: 172.20.236.110
+
+    # The infra nodes that the central agents will be running on
+    metering-infra_hosts:
+      infra1:
+        ip: 172.20.236.111
+      infra2:
+        ip: 172.20.236.112
+      infra3:
+        ip: 172.20.236.113
+
+The ``metering-compute_hosts`` houses the ``ceilometer-agent-compute`` service. It runs on each compute node and pools for resource utilization statistics.
+The ``metering-infra_hosts`` houses serveral services:
+
+  - A central agent (ceilometer-agent-central): Runs on a central management server to poll for resource utilization statistics for resources not tied to instances or compute nodes. Multiple agents can be started to scale service horizontally.
+
+  - A notification agent (ceilometer-agent-notification): Runs on a central management server(s) and consumes messages from the message queue(s) to build event and metering data.
+
+  - A collector (ceilometer-collector): Runs on central management server(s) and dispatches collected telemetry data to a data store or external consumer without modification.
+
+  - An alarm evaluator (ceilometer-alarm-evaluator): Runs on one or more central management servers to determine when alarms fire due to the associated statistic trend crossing a threshold over a sliding time window.
+
+  - An alarm notifier (ceilometer-alarm-notifier): Runs on one or more central management servers to allow alarms to be set based on the threshold evaluation for a collection of samples.
+
+  - An API server (ceilometer-api): Runs on one or more central management servers to provide data access from the data store.
+
+
+Configuring the user data
+#########################
+In addtion to adding these hosts in the ``/etc/openstack_deploy/conf.d/ceilometer.yml`` file, other configurations must be specified in the ``/etc/openstack_deploy/user_variable.yml`` file. These configurations are listed below, along with a description:
+
+
+The type of database backend ceilometer will use. Currently only mongodb is supported:
+``ceilometer_db_type: mongodb``
+
+The IP address of the MonogoDB host:
+``ceilometer_db_ip: localhost``
+
+The port of the Mongodb service:
+``ceilometer_db_port: 27017``
+
+This configures swift to send notifications to the message bus:
+``swift_ceilometer_enabled: False``
+
+This configures heat to send notifications to the message bus:
+``heat_ceilometer_enabled: False``
+
+This configures cinder to send notifications to the message bus:
+``cinder_ceilometer_enabled: False``
+
+This configures glance to send notifications to the message bus:
+``glance_ceilometer_enabled: False``
+
+This configures nova to send notifications to the message bus:
+``nova_ceilometer_enabled: False``
+
+
+Once all of these steps are complete, you are ready to run the os-ceilometer-install.yml playbook! Or, if deploying a new stack, simply run setup-openstack.yml. The ceilometer playbooks will run as part of this playbook.
diff --git a/etc/openstack_deploy/conf.d/ceilometer.yml.aio b/etc/openstack_deploy/conf.d/ceilometer.yml.aio
new file mode 100644
index 0000000000..c49e492a7d
--- /dev/null
+++ b/etc/openstack_deploy/conf.d/ceilometer.yml.aio
@@ -0,0 +1,9 @@
+# The compute host that the ceilometer compute agent will be running on.
+metering-compute_hosts:
+  aio1:
+    ip: 172.29.236.100
+
+# The infra nodes that the central agents will be running on
+metering-infra_hosts:
+  aio1:
+    ip: 172.29.236.100
diff --git a/etc/openstack_deploy/conf.d/ceilometer.yml.example b/etc/openstack_deploy/conf.d/ceilometer.yml.example
new file mode 100644
index 0000000000..76d62a7707
--- /dev/null
+++ b/etc/openstack_deploy/conf.d/ceilometer.yml.example
@@ -0,0 +1,13 @@
+# The compute host that the ceilometer compute agent will be running on.
+metering-compute_hosts:
+  compute1:
+    ip: 172.20.236.110
+
+# The infra nodes that the central agents will be running on
+metering-infra_hosts:
+  infra1:
+    ip: 172.20.236.111
+  infra2:
+    ip: 172.20.236.112
+  infra3:
+    ip: 172.20.236.113
diff --git a/etc/openstack_deploy/env.d/ceilometer.yml b/etc/openstack_deploy/env.d/ceilometer.yml
new file mode 100644
index 0000000000..c4b052baa7
--- /dev/null
+++ b/etc/openstack_deploy/env.d/ceilometer.yml
@@ -0,0 +1,68 @@
+---
+component_skel:
+  ceilometer_agent_compute:
+    belongs_to:
+    - ceilometer_all
+  ceilometer_agent_central:
+    belongs_to:
+    - ceilometer_all
+  ceilometer_agent_notification:
+    belongs_to:
+    - ceilometer_all
+  ceilometer_collector:
+    belongs_to:
+    - ceilometer_all
+  ceilometer_alarm_evaluator:
+    belongs_to:
+    - ceilometer_all
+  ceilometer_alarm_notifier:
+    belongs_to:
+    - ceilometer_all
+  ceilometer_api:
+    belongs_to:
+    - ceilometer_all
+
+container_skel:
+  ceilometer_api_container:
+    belongs_to:
+      - metering-infra_containers
+    contains:
+      - ceilometer_agent_central
+      - ceilometer_agent_notification
+      - ceilometer_alarm_evaluator
+      - ceilometer_alarm_notifier
+      - ceilometer_api
+    properties:
+      service_name: ceilometer
+      container_release: trusty
+  ceilometer_collector_container:
+    belongs_to:
+      - metering-infra_containers
+    contains:
+      - ceilometer_collector
+    properties:
+      service_name: ceilometer
+      container_release: trusty
+  metering-compute_container:
+    belongs_to:
+    - metering-compute_containers
+    contains:
+    - ceilometer_agent_compute
+    properties:
+      is_metal: true
+      service_name: ceilometer
+      container_release: trusty
+
+physical_skel:
+  metering-compute_containers:
+    belongs_to:
+    - all_containers
+  metering-compute_hosts:
+    belongs_to:
+    - hosts
+  metering-infra_containers:
+    belongs_to:
+    - all_containers
+  metering-infra_hosts:
+    belongs_to:
+    - hosts
diff --git a/etc/openstack_deploy/user_group_vars.yml b/etc/openstack_deploy/user_group_vars.yml
index 97afd2151f..b76afdfe12 100644
--- a/etc/openstack_deploy/user_group_vars.yml
+++ b/etc/openstack_deploy/user_group_vars.yml
@@ -75,6 +75,15 @@ service_region: RegionOne
 #openstack_service_internaluri_proto: http
 
 
+## Ceilometer
+ceilometer_service_port: 8777
+ceilometer_service_proto: http
+ceilometer_service_user_name: ceilometer
+ceilometer_service_tenant_name: service
+ceilometer_service_adminuri: "{{ ceilometer_service_proto }}://{{ internal_lb_vip_address }}:{{ ceilometer_service_port }}"
+ceilometer_service_adminurl: "{{ ceilometer_service_adminuri }}/"
+ceilometer_service_region: "{{ service_region }}"
+
 ## Nova
 nova_service_port: 8774
 nova_service_proto: http
@@ -167,3 +176,10 @@ tempest_pip_instructions: >
   --extra-index-url https://pypi.python.org/simple
   --trusted-host pypi.python.org
   --trusted-host {{ openstack_upstream_domain }}
+
+## Swift
+swift_system_user_name: swift
+swift_system_group_name: swift
+swift_system_shell: /bin/bash
+swift_system_comment: swift system user
+swift_system_home_folder: "/var/lib/{{ swift_system_user_name }}"
diff --git a/etc/openstack_deploy/user_secrets.yml b/etc/openstack_deploy/user_secrets.yml
index 2ac1c522b4..719f15b451 100644
--- a/etc/openstack_deploy/user_secrets.yml
+++ b/etc/openstack_deploy/user_secrets.yml
@@ -33,6 +33,11 @@ keystone_auth_admin_token:
 keystone_auth_admin_password:
 keystone_service_password:
 
+## Ceilometer Options:
+ceilometer_container_db_password:
+ceilometer_service_password:
+ceilometer_telemetry_secret:
+
 ## Cinder Options
 cinder_container_mysql_password:
 cinder_service_password:
diff --git a/etc/openstack_deploy/user_variables.yml b/etc/openstack_deploy/user_variables.yml
index 9f6b12607a..9319e948f0 100644
--- a/etc/openstack_deploy/user_variables.yml
+++ b/etc/openstack_deploy/user_variables.yml
@@ -13,6 +13,17 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
+
+## Ceilometer Options
+ceilometer_db_type: mongodb
+ceilometer_db_ip: localhost
+ceilometer_db_port: 27017
+swift_ceilometer_enabled: False
+heat_ceilometer_enabled: False
+cinder_ceilometer_enabled: False
+glance_ceilometer_enabled: False
+nova_ceilometer_enabled: False
+
 ## Glance Options
 # Set default_store to "swift" if using Cloud Files or swift backend
 glance_default_store: file
diff --git a/playbooks/defaults/repo_packages/openstack_services.yml b/playbooks/defaults/repo_packages/openstack_services.yml
index 4ea5ac1240..6f6f9bed70 100644
--- a/playbooks/defaults/repo_packages/openstack_services.yml
+++ b/playbooks/defaults/repo_packages/openstack_services.yml
@@ -28,6 +28,12 @@
 ### Before this is shipped all of these services should have a tag set as the branch,
 ### or have a comment / reason attached to them as to why a tag can not work.
 
+## Ceilometer service
+ceilometer_git_repo: https://github.com/openstack/ceilometer
+ceilometer_git_install_branch: d9b04cd19c5ab853f8dafc67a7d493b01017b103 # HEAD of "master" as of 25.06.2015
+ceilometer_git_dest: "/opt/ceilometer_{{ceilometer_git_install_branch | replace('/', '_') }}"
+
+
 ## Cinder service
 cinder_git_repo: https://github.com/openstack/cinder
 cinder_git_install_branch: 648d544621ed101e6f5581a201efea585a08935a # HEAD of "master" as of 22.06.2015
diff --git a/playbooks/os-ceilometer-install.yml b/playbooks/os-ceilometer-install.yml
new file mode 100644
index 0000000000..7fb4a6c69c
--- /dev/null
+++ b/playbooks/os-ceilometer-install.yml
@@ -0,0 +1,74 @@
+---
+# Copyright 2014, Rackspace US, 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.
+
+- name: Install the ceilometer components
+  hosts: ceilometer_all
+  max_fail_percentage: 20
+  user: root
+  pre_tasks:
+    - name: Flush net cache
+      command: /usr/local/bin/lxc-system-manage flush-net-cache
+      delegate_to: "{{ physical_host }}"
+      tags:
+        - flush-net-cache
+    - name: Wait for container ssh
+      wait_for:
+        port: "22"
+        delay: 5
+        host: "{{ ansible_ssh_host }}"
+      delegate_to: "{{ physical_host }}"
+      tags:
+        - ceilometer-ssh-wait
+    - name: Sort the rabbitmq servers
+      dist_sort:
+        value_to_lookup: "{{ container_name }}"
+        ref_list: "{{ groups['ceilometer_all'] }}"
+        src_list: "{{ rabbitmq_servers }}"
+      register: servers
+    - name: Set rabbitmq servers
+      set_fact:
+        rabbitmq_servers: "{{ servers.sorted_list }}"
+    - name: Create log dir
+      file:
+        path: "{{ item.path }}"
+        state: directory
+      with_items:
+        - { path: "/openstack/log/{{ inventory_hostname }}-ceilometer" }
+      when: is_metal == true or is_metal == "True"
+      tags:
+        - ceilometer-logs
+        - ceilometer-log-dirs
+    - name: Create log aggregation links
+      file:
+        src: "{{ item.src }}"
+        dest: "{{ item.dest }}"
+        state: "{{ item.state }}"
+        force: "yes"
+      with_items:
+        - { src: "/openstack/log/{{ inventory_hostname }}-ceilometer", dest: "/var/log/ceilometer", state: "link" }
+      when: is_metal == true or is_metal == "True"
+      tags:
+        - ceilometer-logs
+  roles:
+    - { role: "os_ceilometer", tags: [ "os-ceilometer" ] }
+    - { role: "openstack_openrc", tags: [ "openstack-openrc" ] }
+    - role: "rsyslog_client"
+      rsyslog_client_log_dir: "/var/log/ceilometer"
+      rsyslog_client_config_name: "99-ceilometer-rsyslog-client.conf"
+      tags:
+        - "ceilometer-rsyslog-client"
+  vars:
+    ansible_hostname: "{{ container_name }}"
+    is_metal: "{{ properties.is_metal|default(false) }}"
diff --git a/playbooks/roles/os_ceilometer/CONTRIBUTING.rst b/playbooks/roles/os_ceilometer/CONTRIBUTING.rst
new file mode 100644
index 0000000000..eac8527aac
--- /dev/null
+++ b/playbooks/roles/os_ceilometer/CONTRIBUTING.rst
@@ -0,0 +1,85 @@
+OpenStack glance
+################
+:tags: openstack, glance, cloud, ansible
+:category: \*nix
+
+contributor guidelines
+^^^^^^^^^^^^^^^^^^^^^^
+
+Filing Bugs
+-----------
+
+Bugs should be filed on Launchpad, not GitHub: "https://bugs.launchpad.net/openstack-ansible"
+
+
+When submitting a bug, or working on a bug, please ensure the following criteria are met:
+    * The description clearly states or describes the original problem or root cause of the problem.
+    * Include historical information on how the problem was identified.
+    * Any relevant logs are included.
+    * The provided information should be totally self-contained. External access to web services/sites should not be needed.
+    * Steps to reproduce the problem if possible.
+
+
+Submitting Code
+---------------
+
+Changes to the project should be submitted for review via the Gerrit tool, following
+the workflow documented at: "http://docs.openstack.org/infra/manual/developers.html#development-workflow"
+
+Pull requests submitted through GitHub will be ignored and closed without regard.
+
+
+Extra
+-----
+
+Tags:
+    If it's a bug that needs fixing in a branch in addition to Master, add a '\<release\>-backport-potential' tag (eg ``juno-backport-potential``).  There are predefined tags that will autocomplete.
+
+Status:
+    Please leave this alone, it should be New till someone triages the issue.
+
+Importance:
+    Should only be touched if it is a Blocker/Gating issue. If it is, please set to High, and only use Critical if you have found a bug that can take down whole infrastructures.
+
+
+Style guide
+-----------
+
+When creating tasks and other roles for use in Ansible please create then using the YAML dictionary format.
+
+Example YAML dictionary format:
+    .. code-block:: yaml
+
+        - name: The name of the tasks
+          module_name:
+            thing1: "some-stuff"
+            thing2: "some-other-stuff"
+          tags:
+            - some-tag
+            - some-other-tag
+
+
+Example **NOT** in YAML dictionary format:
+    .. code-block:: yaml
+
+        - name: The name of the tasks
+          module_name: thing1="some-stuff" thing2="some-other-stuff"
+          tags:
+            - some-tag
+            - some-other-tag
+
+
+Usage of the ">" and "|" operators should be limited to Ansible conditionals and command modules such as the ansible ``shell`` module.
+
+
+Issues
+------
+
+When submitting an issue, or working on an issue please ensure the following criteria are met:
+    * The description clearly states or describes the original problem or root cause of the problem.
+    * Include historical information on how the problem was identified.
+    * Any relevant logs are included.
+    * If the issue is a bug that needs fixing in a branch other than Master, add the ‘backport potential’ tag TO THE ISSUE (not the PR).
+    * The provided information should be totally self-contained. External access to web services/sites should not be needed.
+    * If the issue is needed for a hotfix release, add the 'expedite' label.
+    * Steps to reproduce the problem if possible.
diff --git a/playbooks/roles/os_ceilometer/LICENSE b/playbooks/roles/os_ceilometer/LICENSE
new file mode 100644
index 0000000000..e06d208186
--- /dev/null
+++ b/playbooks/roles/os_ceilometer/LICENSE
@@ -0,0 +1,202 @@
+Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "{}"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright {yyyy} {name of copyright owner}
+
+   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.
+
diff --git a/playbooks/roles/os_ceilometer/README.rst b/playbooks/roles/os_ceilometer/README.rst
new file mode 100644
index 0000000000..c768cd2b91
--- /dev/null
+++ b/playbooks/roles/os_ceilometer/README.rst
@@ -0,0 +1,22 @@
+OpenStack ceilometer
+####################
+:tags: openstack, ceilometer, cloud, ansible
+:category: \*nix
+
+Role to install ceilometer and ceilometer registry.
+
+This role will install the following:
+    * ceilometer-api
+    * ceilometer-registry
+
+.. code-block:: yaml
+
+    - name: Install ceilometer server
+      hosts: ceilometer_all
+      user: root
+      roles:
+        - { role: "os_ceilometer", tags: [ "os-ceilometer" ] }
+      vars:
+        external_lb_vip_address: 172.16.24.1
+        internal_lb_vip_address: 192.168.0.1
+        galera_address: "{{ internal_lb_vip_address }}"
diff --git a/playbooks/roles/os_ceilometer/defaults/main.yml b/playbooks/roles/os_ceilometer/defaults/main.yml
new file mode 100644
index 0000000000..42724d1e8d
--- /dev/null
+++ b/playbooks/roles/os_ceilometer/defaults/main.yml
@@ -0,0 +1,95 @@
+---
+# Copyright 2014, Rackspace US, 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.
+
+# Defines that the role will be deployed on a host machine
+is_metal: true
+
+## Verbosity Options
+debug: False
+verbose: True
+
+## System info
+ceilometer_system_user_name: ceilometer
+ceilometer_system_group_name: ceilometer
+ceilometer_system_shell: /bin/false
+ceilometer_system_comment: ceilometer system user
+ceilometer_system_user_home: "/var/lib/{{ ceilometer_system_user_name }}"
+
+## DB info
+ceilometer_database_name: ceilometer
+ceilometer_database_user: ceilometer
+ceilometer_db_type: mongodb
+ceilometer_db_ip: localhost
+ceilometer_db_port: 27017
+ceilometer_connection_string: "{{ ceilometer_db_type }}://{{ ceilometer_database_user }}:{{ ceilometer_container_db_password }}@{{ ceilometer_db_ip }}:{{ ceilometer_db_port }}/{{ ceilometer_database_name }}"
+
+
+#Ceilometer services info
+ceilometer_role_name: admin
+ceilometer_api_host_address: 0.0.0.0
+ceilometer_api_service_port: 8777
+ceilometer_collector_program_name: ceilometer-collector
+ceilometer_compute_program_name: ceilometer-agent-compute
+ceilometer_alarm_notifier_program_name: ceilometer-alarm-notifier
+ceilometer_alarm_evaluator_program_name: ceilometer-alarm-evaluator
+ceilometer_api_program_name: ceilometer-api
+ceilometer_agent_notification_program_name: ceilometer-agent-notification
+ceilometer_agent_central_program_name: ceilometer-agent-central
+
+## Service Type and Data
+ceilometer_service_region: RegionOne
+ceilometer_service_name: ceilometer
+ceilometer_service_port: 8777
+ceilometer_service_proto: http
+ceilometer_service_type: metering
+ceilometer_service_description: "Ceilometer Service"
+ceilometer_service_user_name: ceilometer
+ceilometer_service_tenant_name: service
+ceilometer_service_project_name: service
+ceilometer_service_publicuri: "{{ ceilometer_service_proto }}://{{ external_lb_vip_address }}:{{ ceilometer_service_port }}"
+ceilometer_service_publicurl: "{{ ceilometer_service_publicuri }}"
+ceilometer_service_internaluri: "{{ ceilometer_service_proto }}://{{ internal_lb_vip_address }}:{{ ceilometer_service_port }}"
+ceilometer_service_internalurl: "{{ ceilometer_service_internaluri }}"
+ceilometer_service_adminuri: "{{ ceilometer_service_proto }}://{{ internal_lb_vip_address }}:{{ ceilometer_service_port }}"
+ceilometer_service_adminurl: "{{ ceilometer_service_adminuri }}"
+
+## Ceilometer config
+
+# Common apt packages
+ceilometer_apt_packages:
+  - rpcbind
+  - rsync
+  - git
+
+# Common pip packages
+ceilometer_pip_packages:
+  - ceilometer
+  - python-ceilometerclient
+  - ceilometermiddleware
+  - MySQL-python
+  - python-memcached
+  - pycrypto
+  - warlock
+  - pymongo
+
+## Service Names
+ceilometer_service_names:
+  - "ceilometer-api"
+  - "ceilometer-alarm-notifier"
+  - "ceilometer-alarm-evaluator"
+  - "ceilometer-collector"
+  - "ceilometer-agent-notification"
+  - "ceilometer-agent-central"
+  - "ceilometer-agent-compute"
diff --git a/playbooks/roles/os_ceilometer/files/policy.json b/playbooks/roles/os_ceilometer/files/policy.json
new file mode 100644
index 0000000000..2bcd03425a
--- /dev/null
+++ b/playbooks/roles/os_ceilometer/files/policy.json
@@ -0,0 +1,7 @@
+{
+    "context_is_admin": "role:admin",
+    "context_is_project": "project_id:%(target.project_id)s",
+    "context_is_owner": "user_id:%(target.user_id)s",
+    "segregation": "rule:context_is_admin",
+    "default": ""
+}
diff --git a/playbooks/roles/os_ceilometer/handlers/main.yml b/playbooks/roles/os_ceilometer/handlers/main.yml
new file mode 100644
index 0000000000..3c9d0bfa08
--- /dev/null
+++ b/playbooks/roles/os_ceilometer/handlers/main.yml
@@ -0,0 +1,65 @@
+---
+# Copyright 2014, Rackspace US, 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.
+
+- name: Restart ceilometer api
+  service:
+    name: "{{ ceilometer_api_program_name }}"
+    state: "restarted"
+    pattern: "{{ ceilometer_api_program_name }}"
+
+
+- name: Restart ceilometer collector
+  service:
+    name: "{{ ceilometer_collector_program_name }}"
+    state: "restarted"
+    pattern: "{{ ceilometer_collector_program_name }}"
+
+- name: Restart ceilometer compute
+  service:
+    name: "{{ ceilometer_compute_program_name }}"
+    state: "restarted"
+    pattern: "{{ ceilometer_compute_program_name }}"
+
+- name: Restart ceilometer alarm_notifier
+  service:
+    name: "{{ ceilometer_alarm_notifier_program_name }}"
+    state: "restarted"
+    pattern: "{{ ceilometer_alarm_notifier_program_name }}"
+
+- name: Restart ceilometer alarm_evaluator
+  service:
+    name: "{{ ceilometer_alarm_evaluator_program_name }}"
+    state: "restarted"
+    pattern: "{{ ceilometer_alarm_evaluator_program_name }}"
+
+- name: Restart ceilometer agent_notification
+  service:
+    name: "{{ ceilometer_agent_notification_program_name }}"
+    state: "restarted"
+    pattern: "{{ ceilometer_agent_notification_program_name }}"
+
+- name: Restart ceilometer agent_central
+  service:
+    name: "{{ ceilometer_agent_central_program_name }}"
+    state: "restarted"
+    pattern: "{{ ceilometer_agent_central_program_name }}"
+
+- name: Restart ceilometer services
+  service:
+    name: "{{ item }}"
+    state: "restarted"
+    pattern: "{{ item }}"
+  with_items: ceilometer_service_names
+  failed_when: false
diff --git a/playbooks/roles/os_ceilometer/meta/main.yml b/playbooks/roles/os_ceilometer/meta/main.yml
new file mode 100644
index 0000000000..c779d52457
--- /dev/null
+++ b/playbooks/roles/os_ceilometer/meta/main.yml
@@ -0,0 +1,35 @@
+---
+# Copyright 2014, Rackspace US, 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.
+
+galaxy_info:
+  author: rcbops
+  description: Installation and setup of ceilometer
+  company: Rackspace
+  license: Apache2
+  min_ansible_version: 1.6.6
+  platforms:
+    - name: Ubuntu
+      versions:
+        - trusty
+  categories:
+    - cloud
+    - python
+    - ceilometer
+    - development
+    - openstack
+dependencies:
+  - galera_client
+  - openstack_openrc
+  - pip_lock_down
diff --git a/playbooks/roles/os_ceilometer/tasks/ceilometer_install.yml b/playbooks/roles/os_ceilometer/tasks/ceilometer_install.yml
new file mode 100644
index 0000000000..d187505902
--- /dev/null
+++ b/playbooks/roles/os_ceilometer/tasks/ceilometer_install.yml
@@ -0,0 +1,42 @@
+---
+# Copyright 2014, Rackspace US, 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.
+
+- name: Install apt packages
+  apt:
+    pkg: "{{ item }}"
+    state: latest
+    update_cache: yes
+    cache_valid_time: 600
+  register: install_packages
+  until: install_packages|success
+  retries: 5
+  delay: 2
+  with_items: ceilometer_apt_packages
+  tags:
+    - ceilometer-apt-packages
+
+
+- name: Install pip packages
+  pip:
+    name: "{{ item }}"
+    state: present
+  register: install_packages
+  until: install_packages|success
+  retries: 5
+  delay: 2
+  with_items:
+    - "{{ ceilometer_pip_packages }}"
+  tags:
+    - ceilometer-pip-packages
diff --git a/playbooks/roles/os_ceilometer/tasks/ceilometer_post_install.yml b/playbooks/roles/os_ceilometer/tasks/ceilometer_post_install.yml
new file mode 100644
index 0000000000..2f929c857e
--- /dev/null
+++ b/playbooks/roles/os_ceilometer/tasks/ceilometer_post_install.yml
@@ -0,0 +1,47 @@
+---
+# Copyright 2014, Rackspace US, 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.
+
+- name: Copy ceilometer config
+  template:
+    src: "{{ item.src }}"
+    dest: "{{ item.dest }}"
+    owner: "{{ ceilometer_system_user_name }}"
+    group: "{{ ceilometer_system_group_name }}"
+  with_items:
+    - { src: "ceilometer.conf.j2", dest: "/etc/ceilometer/ceilometer.conf" }
+    - { src: "api_paste.ini.j2", dest: "/etc/ceilometer/api_paste.ini" }
+    - { src: "event_pipeline.yaml.j2", dest: "/etc/ceilometer/event_pipeline.yaml" }
+    - { src: "event_definitions.yaml.j2", dest: "/etc/ceilometer/event_definitions.yaml" }
+    - { src: "pipeline.yaml.j2", dest: "/etc/ceilometer/pipeline.yaml" }
+  notify: Restart ceilometer services
+  tags:
+    - ceilometer-config
+    - ceilometer-post-install
+
+- name: Apply updates to policy file
+  copy_updates:
+    content="{{ item.content }}"
+    updates="{{ item.policy_data }}"
+    dest="{{ item.dest }}"
+    owner="{{ ceilometer_system_user_name }}"
+    group="{{ ceilometer_system_group_name }}"
+    mode="{{ item.mode|default('0644') }}"
+  with_items:
+    - { content: "{{ lookup('file', 'policy.json') | b64encode }}", policy_data: "{{ ceilometer_policy_overrides|default('') }}", dest: "/etc/ceilometer/policy.json" }
+  notify:
+    - Restart ceilometer services
+  tags:
+    - ceilometer-config
+    - ceilometer-policy-update
diff --git a/playbooks/roles/os_ceilometer/tasks/ceilometer_pre_install.yml b/playbooks/roles/os_ceilometer/tasks/ceilometer_pre_install.yml
new file mode 100644
index 0000000000..cfde633c97
--- /dev/null
+++ b/playbooks/roles/os_ceilometer/tasks/ceilometer_pre_install.yml
@@ -0,0 +1,102 @@
+---
+# Copyright 2014, Rackspace US, 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.
+
+- name: Create the system group
+  group:
+    name: "{{ ceilometer_system_group_name }}"
+    state: "present"
+    system: "yes"
+  tags:
+    - ceilometer-group
+
+- name: Create the ceilometer system user
+  user:
+    name: "{{ ceilometer_system_user_name }}"
+    group: "{{ ceilometer_system_group_name }}"
+    comment: "{{ ceilometer_system_comment }}"
+    shell: "{{ ceilometer_system_shell }}"
+    system: "yes"
+    createhome: "yes"
+    home: "{{ ceilometer_system_user_home }}"
+  tags:
+    - ceilometer-user
+
+- name: Create the swift system user and add to ceilometer group
+  user:
+    name: "{{ swift_system_user_name }}"
+    group: "{{ ceilometer_system_group_name }}"
+    comment: "{{ swift_system_comment }}"
+    shell: "{{ swift_system_shell }}"
+    system: "yes"
+    createhome: "yes"
+    home: "{{ swift_system_home_folder }}"
+  tags:
+    - ceilometer-swift-user
+    - ceilometer-pre-install
+
+- name: Create ceilometer dir
+  file:
+    path: "{{ item.path }}"
+    state: directory
+    owner: "{{ item.owner|default(ceilometer_system_user_name) }}"
+    group: "{{ item.group|default(ceilometer_system_group_name) }}"
+    mode: "{{ item.mode|default('0755') }}"
+  with_items:
+    - { path: "/etc/ceilometer" }
+    - { path: "{{ ceilometer_system_user_home }}" }
+    - { path: "{{ ceilometer_system_user_home }}/.ssh", mode: "0700" }
+    - { path: "/var/cache/ceilometer", mode: "0700" }
+  tags:
+    - ceilometer-dirs
+
+- name: Test for log directory or link
+  shell: |
+    if [ -h "/var/log/ceilometer"  ]; then
+      chown -h {{ ceilometer_system_user_name }}:{{ ceilometer_system_group_name }} "/var/log/ceilometer"
+      chown -R {{ ceilometer_system_user_name }}:{{ ceilometer_system_group_name }} "$(readlink /var/log/ceilometer)"
+    else
+      exit 1
+    fi
+  register: log_dir
+  failed_when: false
+  changed_when: log_dir.rc != 0
+  tags:
+    - ceilometer-dirs
+    - ceilometer-logs
+
+- name: Create ceilometer log dir
+  file:
+    path: "{{ item.path }}"
+    state: directory
+    owner: "{{ item.owner|default(ceilometer_system_user_name) }}"
+    group: "{{ item.group|default(ceilometer_system_group_name) }}"
+    mode: "{{ item.mode|default('0755') }}"
+  with_items:
+    - { path: "/var/log/ceilometer" }
+  when: log_dir.rc != 0
+  tags:
+    - ceilometer-dirs
+    - ceilometer-logs
+
+- name: Drop sudoers file
+  template:
+    src: "sudoers.j2"
+    dest: "/etc/sudoers.d/{{ ceilometer_system_user_name }}_sudoers"
+    mode: "0440"
+    owner: "root"
+    group: "root"
+  tags:
+    - sudoers
+    - ceilometer-sudoers
diff --git a/playbooks/roles/os_ceilometer/tasks/ceilometer_service_add.yml b/playbooks/roles/os_ceilometer/tasks/ceilometer_service_add.yml
new file mode 100644
index 0000000000..d817a3cd0c
--- /dev/null
+++ b/playbooks/roles/os_ceilometer/tasks/ceilometer_service_add.yml
@@ -0,0 +1,85 @@
+---
+# Copyright 2014, Rackspace US, 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.
+
+- name: Ensure ceilometer service
+  keystone:
+    command: "ensure_service"
+    token: "{{ keystone_auth_admin_token }}"
+    endpoint: "{{ keystone_service_adminurl }}"
+    service_name: "{{ service_name }}"
+    service_type: "{{ service_type }}"
+    description: "{{ service_description }}"
+  register: add_service
+  until: add_service|success
+  retries: 5
+  delay: 2
+  tags:
+    - ceilometer-setup
+    - ceilometer-service-add
+
+- name: Ensure ceilometer user
+  keystone:
+    command: "ensure_user"
+    token: "{{ keystone_auth_admin_token }}"
+    endpoint: "{{ keystone_service_adminurl }}"
+    user_name: "{{ service_user_name }}"
+    tenant_name: "{{ service_tenant_name }}"
+    role_name: "{{ role_name }}"
+    password: "{{ ceilometer_service_password }}"
+  register: add_service
+  until: add_service|success
+  retries: 5
+  delay: 10
+  tags:
+    - ceilometer-setup
+    - ceilometer-service-add
+
+- name: Ensure ceilometer user to admin role
+  keystone:
+    command: "ensure_user_role"
+    token: "{{ keystone_auth_admin_token }}"
+    endpoint: "{{ keystone_service_adminurl }}"
+    user_name: "{{ ceilometer_service_user_name }}"
+    tenant_name: "{{ ceilometer_service_project_name }}"
+    role_name: "{{ ceilometer_role_name }}"
+  register: add_admin_role
+  until: add_admin_role|success
+  retries: 5
+  delay: 10
+  tags:
+    - ceilometer-api-setup
+    - ceilometer-service-add
+    - ceilometer-setup
+
+
+# Create an endpoint
+- name: Ensure ceilometer endpoint
+  keystone:
+    command: "ensure_endpoint"
+    token: "{{ keystone_auth_admin_token }}"
+    endpoint: "{{ keystone_service_adminurl }}"
+    region_name: "{{ service_region }}"
+    service_name: "{{ service_name }}"
+    service_type: "{{ service_type }}"
+    publicurl: "{{ service_publicurl }}"
+    adminurl: "{{ service_internalurl }}"
+    internalurl: "{{ service_adminurl }}"
+  register: add_service
+  until: add_service|success
+  retries: 5
+  delay: 10
+  tags:
+    - ceilometer-setup
+    - ceilometer-service-add
diff --git a/playbooks/roles/os_ceilometer/tasks/ceilometer_service_setup.yml b/playbooks/roles/os_ceilometer/tasks/ceilometer_service_setup.yml
new file mode 100644
index 0000000000..649a2e6df0
--- /dev/null
+++ b/playbooks/roles/os_ceilometer/tasks/ceilometer_service_setup.yml
@@ -0,0 +1,30 @@
+---
+# Copyright 2014, Rackspace US, 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.
+
+- include: ceilometer_service_add.yml
+  vars:
+    service_user_name: "{{ ceilometer_service_user_name }}"
+    service_tenant_name: "{{ ceilometer_service_tenant_name }}"
+    service_name: "{{ ceilometer_service_name }}"
+    service_type: "{{ ceilometer_service_type }}"
+    service_region: "{{ceilometer_service_region }}"
+    service_description: "{{ ceilometer_service_description }}"
+    service_password: "{{ ceilometer_service_password }}"
+    service_internalurl: "{{ ceilometer_service_internalurl }}"
+    service_publicurl: "{{ ceilometer_service_publicurl }}"
+    service_adminurl: "{{ ceilometer_service_adminurl }}"
+    role_name: "{{ ceilometer_role_name }}"
+  tags:
+    - ceilometer-add-service
diff --git a/playbooks/roles/os_ceilometer/tasks/ceilometer_upstart_common_init.yml b/playbooks/roles/os_ceilometer/tasks/ceilometer_upstart_common_init.yml
new file mode 100644
index 0000000000..e157fca77f
--- /dev/null
+++ b/playbooks/roles/os_ceilometer/tasks/ceilometer_upstart_common_init.yml
@@ -0,0 +1,31 @@
+- name: Place the init script
+  template:
+    src: "ceilometer-upstart-init.j2"
+    dest: "/etc/init/{{ program_name }}.conf"
+    mode: "0644"
+    owner: "root"
+    group: "root"
+  notify:
+    - Restart ceilometer services
+  tags:
+    - upstart-init
+    - ceilometer-init
+
+- name: Reload init scripts
+  shell: |
+    initctl reload-configuration
+  notify:
+    - Restart ceilometer services
+  tags:
+    - upstart-init
+    - ceilometer-init
+
+- name: Load service
+  service:
+    name: "{{ program_name }}"
+    enabled: "yes"
+  notify:
+    - Restart ceilometer services
+  tags:
+    - upstart-init
+    - ceilometer-init
diff --git a/playbooks/roles/os_ceilometer/tasks/ceilometer_upstart_init.yml b/playbooks/roles/os_ceilometer/tasks/ceilometer_upstart_init.yml
new file mode 100644
index 0000000000..69034f3ba8
--- /dev/null
+++ b/playbooks/roles/os_ceilometer/tasks/ceilometer_upstart_init.yml
@@ -0,0 +1,91 @@
+---
+# Copyright 2014, Rackspace US, 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.
+
+- include: ceilometer_upstart_common_init.yml
+  vars:
+    program_name: "{{ ceilometer_alarm_notifier_program_name }}"
+    service_name: "{{ ceilometer_service_name }}"
+    system_user: "{{ ceilometer_system_user_name }}"
+    system_group: "{{ ceilometer_system_group_name }}"
+    service_home: "{{ ceilometer_system_user_home }}"
+  when: inventory_hostname in groups['ceilometer_alarm_notifier']
+  tags:
+    - ceilometer-alarm-notifier-init
+
+- include: ceilometer_upstart_common_init.yml
+  vars:
+    program_name: "{{ ceilometer_alarm_evaluator_program_name }}"
+    service_name: "{{ ceilometer_service_name }}"
+    system_user: "{{ ceilometer_system_user_name }}"
+    system_group: "{{ ceilometer_system_group_name }}"
+    service_home: "{{ ceilometer_system_user_home }}"
+  when: inventory_hostname in groups['ceilometer_alarm_evaluator']
+  tags:
+    - ceilometer-alarm-evaluator-init
+
+- include: ceilometer_upstart_common_init.yml
+  vars:
+    program_name: "{{ ceilometer_api_program_name }}"
+    service_name: "{{ ceilometer_service_name }}"
+    system_user: "{{ ceilometer_system_user_name }}"
+    system_group: "{{ ceilometer_system_group_name }}"
+    service_home: "{{ ceilometer_system_user_home }}"
+  when: inventory_hostname in groups['ceilometer_api']
+  tags:
+    - ceilometer-api-init
+
+- include: ceilometer_upstart_common_init.yml
+  vars:
+    program_name: "{{ ceilometer_agent_notification_program_name }}"
+    service_name: "{{ ceilometer_service_name }}"
+    system_user: "{{ ceilometer_system_user_name }}"
+    system_group: "{{ ceilometer_system_group_name }}"
+    service_home: "{{ ceilometer_system_user_home }}"
+  when: inventory_hostname in groups['ceilometer_agent_notification']
+  tags:
+    - ceilometer-agent-notification-init
+
+- include: ceilometer_upstart_common_init.yml
+  vars:
+    program_name: "{{ ceilometer_agent_central_program_name }}"
+    service_name: "{{ ceilometer_service_name }}"
+    system_user: "{{ ceilometer_system_user_name }}"
+    system_group: "{{ ceilometer_system_group_name }}"
+    service_home: "{{ ceilometer_system_user_home }}"
+  when: inventory_hostname in groups['ceilometer_agent_central']
+  tags:
+    - ceilometer-agent-central
+
+- include: ceilometer_upstart_common_init.yml
+  vars:
+    program_name: "{{ ceilometer_collector_program_name }}"
+    service_name: "{{ ceilometer_service_name }}"
+    system_user: "{{ ceilometer_system_user_name }}"
+    system_group: "{{ ceilometer_system_group_name }}"
+    service_home: "{{ ceilometer_system_user_home }}"
+  when: inventory_hostname in groups['ceilometer_collector']
+  tags:
+    - ceilometer-collector-init
+
+- include: ceilometer_upstart_common_init.yml
+  vars:
+    program_name: "{{ ceilometer_compute_program_name }}"
+    service_name: "{{ ceilometer_service_name }}"
+    system_user: "{{ ceilometer_system_user_name }}"
+    system_group: "{{ ceilometer_system_group_name }}"
+    service_home: "{{ ceilometer_system_user_home }}"
+  when: inventory_hostname in groups['ceilometer_agent_compute']
+  tags:
+    - ceilometer-agent-compute-init
diff --git a/playbooks/roles/os_ceilometer/tasks/main.yml b/playbooks/roles/os_ceilometer/tasks/main.yml
new file mode 100644
index 0000000000..fa39a63e5a
--- /dev/null
+++ b/playbooks/roles/os_ceilometer/tasks/main.yml
@@ -0,0 +1,23 @@
+---
+# Copyright 2014, Rackspace US, 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.
+
+- include: ceilometer_pre_install.yml
+- include: ceilometer_install.yml
+- include: ceilometer_post_install.yml
+- include: ceilometer_upstart_init.yml
+
+- include: ceilometer_service_setup.yml
+  when: >
+    inventory_hostname == groups['ceilometer_api'][0]
diff --git a/playbooks/roles/os_ceilometer/templates/api_paste.ini.j2 b/playbooks/roles/os_ceilometer/templates/api_paste.ini.j2
new file mode 100644
index 0000000000..38a6a59a6d
--- /dev/null
+++ b/playbooks/roles/os_ceilometer/templates/api_paste.ini.j2
@@ -0,0 +1,17 @@
+# Ceilometer API WSGI Pipeline
+# Define the filters that make up the pipeline for processing WSGI requests
+# Note: This pipeline is PasteDeploy's term rather than Ceilometer's pipeline
+# used for processing samples
+
+# Remove authtoken from the pipeline if you don't want to use keystone authentication
+[pipeline:main]
+pipeline = request_id authtoken api-server
+
+[app:api-server]
+paste.app_factory = ceilometer.api.app:app_factory
+
+[filter:authtoken]
+paste.filter_factory = keystonemiddleware.auth_token:filter_factory
+
+[filter:request_id]
+paste.filter_factory = oslo.middleware:RequestId.factory
diff --git a/playbooks/roles/os_ceilometer/templates/ceilometer-upstart-init.j2 b/playbooks/roles/os_ceilometer/templates/ceilometer-upstart-init.j2
new file mode 100644
index 0000000000..9455552fd5
--- /dev/null
+++ b/playbooks/roles/os_ceilometer/templates/ceilometer-upstart-init.j2
@@ -0,0 +1,42 @@
+# {{ ansible_managed }}
+
+# vim:set ft=upstart ts=2 et:
+
+description "{{ program_name }}"
+author "Kevin Carter <kevin.carter@rackspace.com>"
+
+start on runlevel [2345]
+stop on runlelvel [016]
+
+respawn
+respawn limit 10 5
+
+# Set the RUNBIN environment variable
+env RUNBIN="/usr/local/bin/{{ program_name }}"
+
+# Change directory to service users home
+chdir "{{ service_home }}"
+
+# Pre start actions
+pre-start script
+  mkdir -p "/var/run/{{ program_name }}"
+  chown {{ system_user }}:{{ system_group }} "/var/run/{{ program_name }}"
+
+  mkdir -p "/var/lock/{{ program_name }}"
+  chown {{ system_user }}:{{ system_group }} "/var/lock/{{ program_name }}"
+end script
+
+# Post stop actions
+post-stop script
+  rm "/var/run/{{ program_name }}/{{ program_name }}.pid"
+end script
+
+# Run the start up job
+exec start-stop-daemon --start \
+                       --chuid {{ system_user }} \
+                       --make-pidfile \
+                       --pidfile /var/run/{{ program_name }}/{{ program_name }}.pid \
+                       --exec "{{ program_override|default('$RUNBIN') }}" \
+                       -- {{ program_config_options|default('') }} \
+                       --log-file=/var/log/{{ service_name }}/{{ program_name }}.log
+
diff --git a/playbooks/roles/os_ceilometer/templates/ceilometer.conf.j2 b/playbooks/roles/os_ceilometer/templates/ceilometer.conf.j2
new file mode 100644
index 0000000000..4d6c4217af
--- /dev/null
+++ b/playbooks/roles/os_ceilometer/templates/ceilometer.conf.j2
@@ -0,0 +1,51 @@
+#{{ ansible_managed}}
+
+[DEFAULT]
+auth_strategy = keystone
+collector_workers = 10
+notification_topics = notifications
+rpc_backend = rabbit
+
+[oslo_policy]
+policy_file = /etc/ceilometer/policy.json
+
+[oslo_messaging_rabbit]
+rpc_backend = rabbit
+rabbit_port = {{ rabbitmq_port }}
+rabbit_userid = {{ rabbitmq_userid }}
+rabbit_password = {{ rabbitmq_password }}
+rabbit_hosts = {{ rabbitmq_servers }}
+
+[api]
+port = 8777
+
+[database]
+metering_connection = {{ ceilometer_connection_string }}
+event_connection = {{ ceilometer_connection_string }}
+alarm_connection = {{ ceilometer_connection_string }}
+
+[keystone_authtoken]
+signing_dir = /var/cache/ceilometer
+identity_uri = {{ keystone_service_adminuri }}
+auth_uri = {{ keystone_service_internaluri }}
+auth_url = {{ keystone_service_adminuri }}
+admin_tenant_name = {{ ceilometer_service_tenant_name }}
+admin_user = {{ ceilometer_service_user_name }}
+admin_password = {{ ceilometer_service_password }}
+
+memcached_servers = {{ memcached_servers }}
+
+token_cache_time = 300
+revocation_cache_time = 60
+
+memcache_security_strategy = ENCRYPT
+memcache_secret_key = {{ memcached_encryption_key }}
+
+[publisher]
+telemetry_secret = {{ ceilometer_telemetry_secret }}
+
+[service_credentials]
+os_auth_url = {{ keystone_service_internalurl }}
+os_username = {{ ceilometer_service_user_name }}
+os_tenant_name = {{ ceilometer_service_tenant_name }}
+os_password = {{ ceilometer_service_password }}
diff --git a/playbooks/roles/os_ceilometer/templates/event_definitions.yaml.j2 b/playbooks/roles/os_ceilometer/templates/event_definitions.yaml.j2
new file mode 100644
index 0000000000..a5ab2e2c9d
--- /dev/null
+++ b/playbooks/roles/os_ceilometer/templates/event_definitions.yaml.j2
@@ -0,0 +1,369 @@
+---
+- event_type: compute.instance.*
+  traits: &instance_traits
+    tenant_id:
+      fields: payload.tenant_id
+    user_id:
+      fields: payload.user_id
+    instance_id:
+      fields: payload.instance_id
+    host:
+      fields: publisher_id
+      plugin:
+        name: split
+        parameters:
+          segment: 1
+          max_split: 1
+    service:
+      fields: publisher_id
+      plugin: split
+    memory_mb:
+      type: int
+      fields: payload.memory_mb
+    disk_gb:
+      type: int
+      fields: payload.disk_gb
+    root_gb:
+      type: int
+      fields: payload.root_gb
+    ephemeral_gb:
+      type: int
+      fields: payload.ephemeral_gb
+    vcpus:
+      type: int
+      fields: payload.vcpus
+    instance_type_id:
+      type: int
+      fields: payload.instance_type_id
+    instance_type:
+      fields: payload.instance_type
+    state:
+      fields: payload.state
+    os_architecture:
+      fields: payload.image_meta.'org.openstack__1__architecture'
+    os_version:
+      fields: payload.image_meta.'org.openstack__1__os_version'
+    os_distro:
+      fields: payload.image_meta.'org.openstack__1__os_distro'
+    launched_at:
+      type: datetime
+      fields: payload.launched_at
+    deleted_at:
+      type: datetime
+      fields: payload.deleted_at
+- event_type: compute.instance.exists
+  traits:
+    <<: *instance_traits
+    audit_period_beginning:
+      type: datetime
+      fields: payload.audit_period_beginning
+    audit_period_ending:
+      type: datetime
+      fields: payload.audit_period_ending
+- event_type: ['volume.exists', 'volume.create.*', 'volume.delete.*', 'volume.resize.*', 'volume.attach.*', 'volume.detach.*', 'volume.update.*', 'snapshot.exists', 'snapshot.create.*', 'snapshot.delete.*', 'snapshot.update.*']
+  traits: &cinder_traits
+    user_id:
+      fields: payload.user_id
+    project_id:
+      fields: payload.tenant_id
+    availability_zone:
+      fields: payload.availability_zone
+    display_name:
+      fields: payload.display_name
+    replication_status:
+      fields: payload.replication_status
+    status:
+      fields: payload.status
+    created_at:
+      fields: payload.created_at
+- event_type: ['volume.exists', 'volume.create.*', 'volume.delete.*', 'volume.resize.*', 'volume.attach.*', 'volume.detach.*', 'volume.update.*']
+  traits:
+    <<: *cinder_traits
+    resource_id:
+      fields: payload.volume_id
+    host:
+      fields: payload.host
+    size:
+      fields: payload.size
+    type:
+      fields: payload.volume_type
+    replication_status:
+      fields: payload.replication_status
+- event_type: ['snapshot.exists', 'snapshot.create.*', 'snapshot.delete.*', 'snapshot.update.*']
+  traits:
+    <<: *cinder_traits
+    resource_id:
+      fields: payload.snapshot_id
+    volume_id:
+      fields: payload.volume_id
+- event_type: ['image.update', 'image.upload', 'image.delete']
+  traits: &glance_crud
+    project_id:
+      fields: payload.owner
+    resource_id:
+      fields: payload.id
+    name:
+      fields: payload.name
+    status:
+      fields: payload.status
+    created_at:
+      fields: payload.created_at
+    user_id:
+      fields: payload.owner
+    deleted_at:
+      fields: payload.deleted_at
+    size:
+      fields: payload.size
+- event_type: image.send
+  traits: &glance_send
+    receiver_project:
+      fields: payload.receiver_tenant_id
+    receiver_user:
+      fields: payload.receiver_user_id
+    user_id:
+      fields: payload.owner_id
+    image_id:
+      fields: payload.image_id
+    destination_ip:
+      fields: payload.destination_ip
+    bytes_sent:
+      fields: payload.bytes_sent
+- event_type: orchestration.stack.*
+  traits: &orchestration_crud
+    project_id:
+      fields: payload.tenant_id
+    user_id:
+      fields: ['_context_trustor_user_id', '_context_user_id']
+    resource_id:
+      fields: payload.stack_identity
+- event_type: sahara.cluster.*
+  traits: &sahara_crud
+    project_id:
+      fields: payload.project_id
+    user_id:
+      fields: _context_user_id
+    resource_id:
+      fields: payload.cluster_id
+- event_type: ['identity.user.*', 'identity.project.*', 'identity.group.*', 'identity.role.*', 'identity.OS-TRUST:trust.*',
+               'identity.region.*', 'identity.service.*', 'identity.endpoint.*', 'identity.policy.*']
+  traits: &identity_crud
+    resource_id:
+      fields: payload.resource_info
+    initiator_id:
+      fields: payload.initiator.id
+    project_id:
+      fields: payload.initiator.project_id
+    domain_id:
+      fields: payload.initiator.domain_id
+- event_type: identity.role_assignment.*
+  traits: &identity_role_assignment
+    role:
+      fields: payload.role
+    group:
+      fields: payload.group
+    domain:
+      fields: payload.domain
+    user:
+      fields: payload.user
+    project:
+      fields: payload.project
+- event_type: identity.authenticate
+  traits: &identity_authenticate
+    typeURI:
+      fields: payload.typeURI
+    id:
+      fields: payload.id
+    action:
+      fields: payload.action
+    eventType:
+      fields: payload.eventType
+    eventTime:
+      fields: payload.eventTime
+    outcome:
+      fields: payload.outcome
+    initiator_typeURI:
+      fields: payload.initiator.typeURI
+    initiator_id:
+      fields: payload.initiator.id
+    initiator_name:
+      fields: payload.initiator.name
+    initiator_host_agent:
+      fields: payload.initiator.host.agent
+    initiator_host_addr:
+      fields: payload.initiator.host.address
+    target_typeURI:
+      fields: payload.target.typeURI
+    target_id:
+      fields: payload.target.id
+    observer_typeURI:
+      fields: payload.observer.typeURI
+    observer_id:
+      fields: payload.observer.id
+- event_type: objectstore.http.request
+  traits: &objectstore_request
+    typeURI:
+      fields: payload.typeURI
+    id:
+      fields: payload.id
+    action:
+      fields: payload.action
+    eventType:
+      fields: payload.eventType
+    eventTime:
+      fields: payload.eventTime
+    outcome:
+      fields: payload.outcome
+    initiator_typeURI:
+      fields: payload.initiator.typeURI
+    initiator_id:
+      fields: payload.initiator.id
+    initiator_project_id:
+      fields: payload.initiator.project_id
+    target_typeURI:
+      fields: payload.target.typeURI
+    target_id:
+      fields: payload.target.id
+    target_action:
+      fields: payload.target.action
+    target_metadata_path:
+      fields: payload.target.metadata.path
+    target_metadata_version:
+      fields: payload.target.metadata.version
+    target_metadata_container:
+      fields: payload.target.metadata.container
+    target_metadata_object:
+      fields: payload.target.metadata.object
+    observer_id:
+      fields: payload.observer.id
+- event_type: magnetodb.table.*
+  traits: &kv_store
+    resource_id:
+      fields: payload.table_uuid
+    user_id:
+      fields: _context_user_id
+    project_id:
+      fields: _context_tenant
+- event_type: ['network.*', 'subnet.*', 'port.*', 'router.*', 'floatingip.*', 'pool.*', 'vip.*', 'member.*', 'health_monitor.*', 'firewall.*', 'firewall_policy.*', 'firewall_rule.*', 'vpnservice.*', 'ipsecpolicy.*', 'ikepolicy.*', 'ipsec_site_connection.*']
+  traits: &network_traits
+    user_id:
+      fields: _context_user_id
+    project_id:
+      fields: _context_tenant_id
+- event_type: network.*
+  traits:
+    <<: *network_traits
+    resource_id:
+      fields: ['payload.network.id', 'payload.id']
+- event_type: subnet.*
+  traits:
+    <<: *network_traits
+    resource_id:
+      fields: ['payload.subnet.id', 'payload.id']
+- event_type: port.*
+  traits:
+    <<: *network_traits
+    resource_id:
+      fields: ['payload.port.id', 'payload.id']
+- event_type: router.*
+  traits:
+    <<: *network_traits
+    resource_id:
+      fields: ['payload.router.id', 'payload.id']
+- event_type: floatingip.*
+  traits:
+    <<: *network_traits
+    resource_id:
+      fields: ['payload.floatingip.id', 'payload.id']
+- event_type: pool.*
+  traits:
+    <<: *network_traits
+    resource_id:
+      fields: ['payload.pool.id', 'payload.id']
+- event_type: vip.*
+  traits:
+    <<: *network_traits
+    resource_id:
+      fields: ['payload.vip.id', 'payload.id']
+- event_type: member.*
+  traits:
+    <<: *network_traits
+    resource_id:
+      fields: ['payload.member.id', 'payload.id']
+- event_type: health_monitor.*
+  traits:
+    <<: *network_traits
+    resource_id:
+      fields: ['payload.health_monitor.id', 'payload.id']
+- event_type: firewall.*
+  traits:
+    <<: *network_traits
+    resource_id:
+      fields: ['payload.firewall.id', 'payload.id']
+- event_type: firewall_policy.*
+  traits:
+    <<: *network_traits
+    resource_id:
+      fields: ['payload.firewall_policy.id', 'payload.id']
+- event_type: firewall_rule.*
+  traits:
+    <<: *network_traits
+    resource_id:
+      fields: ['payload.firewall_rule.id', 'payload.id']
+- event_type: vpnservice.*
+  traits:
+    <<: *network_traits
+    resource_id:
+      fields: ['payload.vpnservice.id', 'payload.id']
+- event_type: ipsecpolicy.*
+  traits:
+    <<: *network_traits
+    resource_id:
+      fields: ['payload.ipsecpolicy.id', 'payload.id']
+- event_type: ikepolicy.*
+  traits:
+    <<: *network_traits
+    resource_id:
+      fields: ['payload.ikepolicy.id', 'payload.id']
+- event_type: ipsec_site_connection.*
+  traits:
+    <<: *network_traits
+    resource_id:
+      fields: ['payload.ipsec_site_connection.id', 'payload.id']
+- event_type: '*http.*'
+  traits: &http_audit
+    typeURI:
+      fields: payload.typeURI
+    eventType:
+      fields: payload.eventType
+    action:
+      fields: payload.action
+    outcome:
+      fields: payload.outcome
+    id:
+      fields: payload.id
+    eventTime:
+      fields: payload.eventTime
+    requestPath:
+      fields: payload.requestPath
+    observer_id:
+      fields: payload.observer.id
+    target_id:
+      fields: payload.target.id
+    target_typeURI:
+      fields: payload.target.typeURI
+    target_name:
+      fields: payload.target.name
+    initiator_typeURI:
+      fields: payload.initiator.typeURI
+    initiator_id:
+      fields: payload.initiator.id
+    initiator_name:
+      fields: payload.initiator.name
+    initiator_host_address:
+      fields: payload.initiator.host.address
+- event_type: '*http.response'
+  traits:
+    <<: *http_audit
+    reason_code:
+      fields: payload.reason.reasonCode
+
diff --git a/playbooks/roles/os_ceilometer/templates/event_pipeline.yaml.j2 b/playbooks/roles/os_ceilometer/templates/event_pipeline.yaml.j2
new file mode 100644
index 0000000000..d6c5e25695
--- /dev/null
+++ b/playbooks/roles/os_ceilometer/templates/event_pipeline.yaml.j2
@@ -0,0 +1,13 @@
+---
+sources:
+    - name: event_source
+      events:
+          - "*"
+      sinks:
+          - event_sink
+sinks:
+    - name: event_sink
+      transformers:
+      triggers:
+      publishers:
+          - direct://
diff --git a/playbooks/roles/os_ceilometer/templates/pipeline.yaml.j2 b/playbooks/roles/os_ceilometer/templates/pipeline.yaml.j2
new file mode 100644
index 0000000000..ca1086a725
--- /dev/null
+++ b/playbooks/roles/os_ceilometer/templates/pipeline.yaml.j2
@@ -0,0 +1,83 @@
+---
+sources:
+    - name: meter_source
+      interval: 600
+      meters:
+          - "*"
+      sinks:
+          - meter_sink
+    - name: cpu_source
+      interval: 600
+      meters:
+          - "cpu"
+      sinks:
+          - cpu_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:
+          - notifier://
+    - 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:
+          - notifier://
+    - 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:
+          - notifier://
+    - 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:
+          - notifier://
+
diff --git a/playbooks/roles/os_ceilometer/templates/sudoers.j2 b/playbooks/roles/os_ceilometer/templates/sudoers.j2
new file mode 100644
index 0000000000..36b562e454
--- /dev/null
+++ b/playbooks/roles/os_ceilometer/templates/sudoers.j2
@@ -0,0 +1,3 @@
+# {{ ansible_managed }}
+# Defaults:{{ ceilometer_system_user_name }}!requiretty
+{{ ceilometer_system_user_name }} ALL = (root) NOPASSWD: /usr/local/bin/{{ ceilometer_service_name }}-rootwrap
diff --git a/playbooks/roles/os_cinder/defaults/main.yml b/playbooks/roles/os_cinder/defaults/main.yml
index 3bdab2ddd7..5e211b04d6 100644
--- a/playbooks/roles/os_cinder/defaults/main.yml
+++ b/playbooks/roles/os_cinder/defaults/main.yml
@@ -16,6 +16,9 @@
 # Defines that the role will be deployed on a host machine
 is_metal: true
 
+# Enable/Disable Ceilometer
+cinder_ceilometer_enabled: False
+
 cinder_storage_availability_zone: nova
 cinder_default_availability_zone: "{{ cinder_storage_availability_zone }}"
 
diff --git a/playbooks/roles/os_cinder/templates/cinder.conf.j2 b/playbooks/roles/os_cinder/templates/cinder.conf.j2
index 5a13b2b746..e94c470689 100644
--- a/playbooks/roles/os_cinder/templates/cinder.conf.j2
+++ b/playbooks/roles/os_cinder/templates/cinder.conf.j2
@@ -78,6 +78,11 @@ default_volume_type = {{ cinder_default_volume_type }}
 {% if cinder_backends is defined %}
 enabled_backends={% for backend in cinder_backends|dictsort %}{{ backend.0 }}{% if not loop.last %},{% endif %}{% endfor %}
 
+#Ceilometer configurations
+{% if cinder_ceilometer_enabled %}
+notification_driver = cinder.openstack.common.notifier.rpc_notifier
+{% endif %}
+
 # All given backend(s)
 {% for backend_section in cinder_backends|dictsort %}
 [{{ backend_section.0 }}]
diff --git a/playbooks/roles/os_glance/defaults/main.yml b/playbooks/roles/os_glance/defaults/main.yml
index eec4923a37..cc60b68454 100644
--- a/playbooks/roles/os_glance/defaults/main.yml
+++ b/playbooks/roles/os_glance/defaults/main.yml
@@ -16,6 +16,9 @@
 # Defines that the role will be deployed on a host machine
 is_metal: true
 
+# Enable/Disable Ceilometer
+glance_ceilometer_enabled: False
+
 ## Verbosity Options
 debug: False
 verbose: True
@@ -31,6 +34,7 @@ glance_system_user_home: "/var/lib/{{ glance_system_user_name }}"
 
 glance_flavor: "keystone+cachemanagement"
 glance_registry_host: "{{ internal_lb_vip_address }}"
+glance_ceilometer_notification_driver: messagingv2
 glance_notification_driver: noop
 glance_rpc_backend: glance.openstack.common.rpc.impl_kombu
 glance_default_store: file
diff --git a/playbooks/roles/os_glance/templates/glance-api.conf.j2 b/playbooks/roles/os_glance/templates/glance-api.conf.j2
index b86127c85b..17bcf9d559 100644
--- a/playbooks/roles/os_glance/templates/glance-api.conf.j2
+++ b/playbooks/roles/os_glance/templates/glance-api.conf.j2
@@ -25,8 +25,12 @@ enable_v1_registry = {{ glance_enable_v1_registry }}
 enable_v2_api = {{ glance_enable_v2_api }}
 enable_v2_registry = {{ glance_enable_v2_registry }}
 
+{% if glance_ceilometer_enabled %}
+notification_driver = {{ glance_ceilometer_notification_driver }}
+{% else %}
 notification_driver = {{ glance_notification_driver }}
-{% if glance_notification_driver == "messaging" %}
+{% endif %}
+{% if glance_notification_driver == "messaging" or (glance_ceilometer_notification_driver == "messagingv2" and glance_ceilometer_enabled) %}
 ##### RPC MESSAGING OPTIONS #####
 rpc_backend = {{ glance_rpc_backend }}
 rabbit_hosts = {{ rabbitmq_servers }}
diff --git a/playbooks/roles/os_glance/templates/glance-registry.conf.j2 b/playbooks/roles/os_glance/templates/glance-registry.conf.j2
index 66ce65cbe5..91420877da 100644
--- a/playbooks/roles/os_glance/templates/glance-registry.conf.j2
+++ b/playbooks/roles/os_glance/templates/glance-registry.conf.j2
@@ -16,6 +16,12 @@ backlog = 4096
 workers = {{ glance_registry_workers | default(api_threads) }}
 api_limit_max = 1000
 limit_param_default = 25
+{% if glance_ceilometer_enabled %}
+notification_driver = {{ glance_notification_driver }}
+rpc_backend = {{ glance_rpc_backend }}
+rabbit_hosts = {{ rabbitmq_servers }}
+rabbit_password = {{ rabbitmq_password }}
+{% endif %}
 
 [database]
 connection = mysql://{{ glance_galera_user }}:{{ glance_container_mysql_password }}@{{ glance_galera_address }}/{{ glance_galera_database }}?charset=utf8
diff --git a/playbooks/roles/os_heat/defaults/main.yml b/playbooks/roles/os_heat/defaults/main.yml
index 10edc2faeb..e1ff320c2a 100644
--- a/playbooks/roles/os_heat/defaults/main.yml
+++ b/playbooks/roles/os_heat/defaults/main.yml
@@ -19,6 +19,9 @@
 # Defines that the role will be deployed on a host machine
 is_metal: true
 
+# Enable/Disable Ceilometer
+heat_ceilometer_enabled: False
+
 ## Verbosity Options
 debug: False
 verbose: True
diff --git a/playbooks/roles/os_heat/templates/heat.conf.j2 b/playbooks/roles/os_heat/templates/heat.conf.j2
index 7d63e3d918..6facd278f4 100644
--- a/playbooks/roles/os_heat/templates/heat.conf.j2
+++ b/playbooks/roles/os_heat/templates/heat.conf.j2
@@ -27,6 +27,11 @@ rpc_backend = {{ heat_rpc_backend }}
 ## Plugin dirs
 plugin_dirs = {{ heat_plugin_dirs | join(',') }}
 
+# Ceilometer options
+{% if heat_ceilometer_enabled %}
+notification_driver = heat.openstack.common.notifier.rpc_notifier
+{% endif %}
+
 
 [clients]
 endpoint_type = {{ heat_clients_endpoint }}
diff --git a/playbooks/roles/os_nova/defaults/main.yml b/playbooks/roles/os_nova/defaults/main.yml
index 1092575e4d..6a6a28aa76 100644
--- a/playbooks/roles/os_nova/defaults/main.yml
+++ b/playbooks/roles/os_nova/defaults/main.yml
@@ -16,6 +16,9 @@
 # Defines that the role will be deployed on a host machine
 is_metal: true
 
+# Enable/Disable ceilometer configurations
+nova_ceilometer_enabled: False
+
 ## Verbosity Options
 debug: False
 verbose: True
diff --git a/playbooks/roles/os_nova/templates/nova.conf.j2 b/playbooks/roles/os_nova/templates/nova.conf.j2
index e3d8b5d9bb..8ac145e4a7 100644
--- a/playbooks/roles/os_nova/templates/nova.conf.j2
+++ b/playbooks/roles/os_nova/templates/nova.conf.j2
@@ -100,6 +100,14 @@ max_age = {{ nova_max_age }}
 # Common
 memcached_servers = {{ memcached_servers }}
 
+# Ceilometer notification configurations
+{% if nova_ceilometer_enabled %}
+instance_usage_audit = True
+instance_usage_audit_period = hour
+notify_on_state_change = vm_and_task_state
+notification_driver = messagingv2
+{% endif %}
+
 # Cinder
 [cinder]
 catalog_info = volume:cinder:internalURL
diff --git a/playbooks/roles/os_swift/defaults/main.yml b/playbooks/roles/os_swift/defaults/main.yml
index 5152ac0693..f0a7581ca1 100644
--- a/playbooks/roles/os_swift/defaults/main.yml
+++ b/playbooks/roles/os_swift/defaults/main.yml
@@ -16,6 +16,9 @@
 # Defines that the role will be deployed on a host machine
 is_metal: true
 
+# Enable/Disable Ceilometer
+swift_ceilometer_enabled: False
+
 ## Verbosity Options
 debug: False
 verbose: True
@@ -73,6 +76,13 @@ swift_allow_versions: True
 # This will allow all users to create containers and upload to swift if set to True
 swift_allow_all_users: False
 
+## Swift ceilometer variables
+swift_reselleradmin_role: ResellerAdmin
+
+## Swift Auth
+swift_service_admin_tenant_name: "service"
+swift_service_admin_username: "swift"
+
 swift_account_server_program_config_options: /etc/swift/account-server/account-server.conf
 swift_account_replicator_program_config_options: /etc/swift/account-server/account-server-replicator.conf
 
@@ -114,6 +124,7 @@ swift_proxy_server_program_config_options: /etc/swift/proxy-server/proxy-server.
 # swift_proxy_server_workers: 16
 
 swift_pip_packages:
+  - ceilometermiddleware
   - dnspython
   - ecdsa
   - keystonemiddleware
diff --git a/playbooks/roles/os_swift/tasks/swift_service_setup.yml b/playbooks/roles/os_swift/tasks/swift_service_setup.yml
index 08ef02ce66..88a58e3ff3 100644
--- a/playbooks/roles/os_swift/tasks/swift_service_setup.yml
+++ b/playbooks/roles/os_swift/tasks/swift_service_setup.yml
@@ -99,6 +99,38 @@
     - swift-service-add
     - swift-setup
 
+- name: "Create keystone role for ResellerAdmin"
+  keystone:
+    command: "ensure_role"
+    token: "{{ keystone_auth_admin_token }}"
+    endpoint: "{{ keystone_service_adminurl }}"
+    role_name: "ResellerAdmin"
+  register: add_role
+  until: add_role|success
+  retries: 5
+  delay: 10
+  when: swift_ceilometer_enabled
+  tags:
+    - swift-ceilometer-setup
+    - swift-ceilometer-role
+
+- name: "Add ResellerAdmin role to the service tenant and ceilometer user"
+  keystone:
+    command: "ensure_user_role"
+    token: "{{ keystone_auth_admin_token }}"
+    endpoint: "{{ keystone_service_adminurl }}"
+    user_name: "{{ ceilometer_service_user_name }}"
+    tenant_name: "{{ ceilometer_service_tenant_name }}"
+    role_name: "{{ swift_reselleradmin_role }}"
+  register: ensure_role
+  until: ensure_role|success
+  retries: 5
+  delay: 10
+  when: swift_ceilometer_enabled
+  tags:
+    - swift-ceilometer-setup
+    - swift-ceilometer-role
+
 - name: "Add swiftoperator role to swift-dispersion user"
   keystone:
     command: "ensure_user_role"
diff --git a/playbooks/roles/os_swift/templates/proxy-server.conf.j2 b/playbooks/roles/os_swift/templates/proxy-server.conf.j2
index af34dc3f65..4046c36afb 100644
--- a/playbooks/roles/os_swift/templates/proxy-server.conf.j2
+++ b/playbooks/roles/os_swift/templates/proxy-server.conf.j2
@@ -13,10 +13,18 @@ log_facility = LOG_LOCAL1
 
 [pipeline:main]
 {% if swift_authtoken_active %}
+{% if swift_ceilometer_enabled %}
+pipeline = catch_errors gatekeeper healthcheck proxy-logging ceilometer cache container_sync bulk tempurl ratelimit authtoken keystoneauth container-quotas account-quotas slo dlo proxy-server
+{% else %}
 pipeline = catch_errors gatekeeper healthcheck proxy-logging cache container_sync bulk tempurl ratelimit authtoken keystoneauth container-quotas account-quotas slo dlo proxy-logging proxy-server
+{% endif %}
+{% else %}
+{% if swift_ceilometer_enabled %}
+pipeline = catch_errors gatekeeper healthcheck proxy-logging ceilometer cache container_sync bulk tempurl ratelimit tempauth container-quotas account-quotas slo dlo proxy-server
 {% else %}
 pipeline = catch_errors gatekeeper healthcheck proxy-logging cache container_sync bulk tempurl ratelimit tempauth container-quotas account-quotas slo dlo proxy-logging proxy-server
 {% endif %}
+{% endif %}
 [app:proxy-server]
 use = egg:swift#proxy
 log_facility = LOG_LOCAL1
@@ -60,10 +68,18 @@ delay_auth_decision = {{ swift_delay_auth_decision }}
 [filter:keystoneauth]
 use = egg:swift#keystoneauth
 {% if swift_allow_all_users is defined and swift_allow_all_users == True %}
+{% if swift_ceilometer_enabled %}
+operator_roles = admin, swiftoperator, _member_, ResellerAdmin
+{% else %}
 operator_roles = admin, swiftoperator, _member_
+{% endif %}
+{% else %}
+{% if swift_ceilometer_enabled %}
+operator_roles = admin, swiftoperator, ResellerAdmin
 {% else %}
 operator_roles = admin, swiftoperator
 {% endif %}
+{% endif %}
 # The reseller admin role has the ability to create and delete accounts
 reseller_admin_role = reseller_admin
 
@@ -128,3 +144,13 @@ use = egg:swift#container_sync
 
 [filter:xprofile]
 use = egg:swift#xprofile
+
+{% if swift_ceilometer_enabled %}
+[filter:ceilometer]
+paste.filter_factory = ceilometermiddleware.swift:filter_factory
+control_exchange = swift
+driver = messagingv2
+url = rabbit://openstack:{{ rabbitmq_password }}@{{ groups['rabbitmq_all'][0] }}
+topic = notifications
+log_level = WARN
+{% endif %}
diff --git a/playbooks/setup-openstack.yml b/playbooks/setup-openstack.yml
index 3f9e4e282b..1cb0d47075 100644
--- a/playbooks/setup-openstack.yml
+++ b/playbooks/setup-openstack.yml
@@ -20,4 +20,5 @@
 - include: os-nova-install.yml
 - include: os-neutron-install.yml
 - include: os-heat-install.yml
+- include: os-ceilometer-install.yml
 - include: os-horizon-install.yml
diff --git a/playbooks/vars/configs/haproxy_config.yml b/playbooks/vars/configs/haproxy_config.yml
index beef6e7bd7..a32d722e53 100644
--- a/playbooks/vars/configs/haproxy_config.yml
+++ b/playbooks/vars/configs/haproxy_config.yml
@@ -154,3 +154,8 @@ haproxy_service_configs:
       haproxy_port: 8181
       haproxy_backend_port: 8181
       haproxy_balance_type: http
+  - service:
+      haproxy_service_name: ceilometer_api
+      haproxy_backend_nodes: "{{ groups['ceilometer_api_container'] }}"
+      haproxy_port: 8777
+      haproxy_balance_type: http
diff --git a/scripts/bootstrap-aio.sh b/scripts/bootstrap-aio.sh
index a2c1b96b91..7d07d61fff 100755
--- a/scripts/bootstrap-aio.sh
+++ b/scripts/bootstrap-aio.sh
@@ -23,6 +23,7 @@ DEFAULT_PASSWORD=$(tr -dc 'a-zA-Z0-9' < /dev/urandom | head -c 32)
 export ADMIN_PASSWORD=${ADMIN_PASSWORD:-$DEFAULT_PASSWORD}
 export SERVICE_REGION=${SERVICE_REGION:-"RegionOne"}
 export DEPLOY_SWIFT=${DEPLOY_SWIFT:-"yes"}
+export DEPLOY_CEILOMETER=${DEPLOY_CEILOMETER:-"yes"}
 export GET_PIP_URL=${GET_PIP_URL:-"https://bootstrap.pypa.io/get-pip.py"}
 export PUBLIC_INTERFACE=${PUBLIC_INTERFACE:-$(ip route show | awk '/default/ { print $NF }')}
 export PUBLIC_ADDRESS=${PUBLIC_ADDRESS:-$(ip -o -4 addr show dev ${PUBLIC_INTERFACE} | awk -F '[ /]+' '/global/ {print $4}')}
@@ -293,6 +294,37 @@ scripts/pw-token-gen.py --file /etc/openstack_deploy/user_secrets.yml
 sed -i "s/keystone_auth_admin_password:.*/keystone_auth_admin_password: ${ADMIN_PASSWORD}/" /etc/openstack_deploy/user_secrets.yml
 sed -i "s/external_lb_vip_address:.*/external_lb_vip_address: ${PUBLIC_ADDRESS}/" /etc/openstack_deploy/openstack_user_config.yml
 
+if [ ${DEPLOY_CEILOMETER} ]; then
+  # Install mongodb on the aio1 host
+  apt-get install mongodb-server mongodb-clients python-pymongo -y
+  # Change bind_ip to management ip
+  sed -i "s/^bind_ip.*/bind_ip = 172.29.236.100/" /etc/mongodb.conf
+  # Asserting smallfiles key
+  sed -i "s/^smallfiles.*/smallfiles = true/" /etc/mongodb.conf
+  service mongodb restart
+  # Giving the service a second..
+  sleep 5
+  #Adding the ceilometer database
+  mongo --host 172.29.236.100 --eval '
+    db = db.getSiblingDB("ceilometer");
+    db.addUser({user: "ceilometer",
+    pwd: "ceilometer",
+    roles: [ "readWrite", "dbAdmin" ]})'
+
+  # change the generated passwords for mongodb access
+  sed -i "s/ceilometer_container_db_password:.*/ceilometer_container_db_password: ceilometer/" /etc/openstack_deploy/user_secrets.yml
+  # Change the ceilometer user variables necessary for deployment
+  sed -i "s/ceilometer_db_ip:.*/ceilometer_db_ip: \"\{\{ hostvars\['aio1'\]\['ansible_ssh_host'\] \}\}\"/" /etc/openstack_deploy/user_variables.yml
+  # Enable ceilometer for all other openstack services
+  if [ ${DEPLOY_SWIFT} ]; then
+    sed -i "s/swift_ceilometer_enabled:.*/swift_ceilometer_enabled: True/" /etc/openstack_deploy/user_variables.yml
+  fi
+  sed -i "s/heat_ceilometer_enabled:.*/heat_ceilometer_enabled: True/" /etc/openstack_deploy/user_variables.yml
+  sed -i "s/cinder_ceilometer_enabled:.*/cinder_ceilometer_enabled: True/" /etc/openstack_deploy/user_variables.yml
+  sed -i "s/glance_ceilometer_enabled:.*/glance_ceilometer_enabled: True/" /etc/openstack_deploy/user_variables.yml
+  sed -i "s/nova_ceilometer_enabled:.*/nova_ceilometer_enabled: True/" /etc/openstack_deploy/user_variables.yml
+fi
+
 # Service region set
 echo "service_region: ${SERVICE_REGION}" | tee -a /etc/openstack_deploy/user_variables.yml
 
diff --git a/scripts/run-playbooks.sh b/scripts/run-playbooks.sh
index 83700c467f..aa87a2cdf7 100755
--- a/scripts/run-playbooks.sh
+++ b/scripts/run-playbooks.sh
@@ -24,6 +24,7 @@ DEPLOY_INFRASTRUCTURE=${DEPLOY_INFRASTRUCTURE:-"yes"}
 DEPLOY_LOGGING=${DEPLOY_LOGGING:-"yes"}
 DEPLOY_OPENSTACK=${DEPLOY_OPENSTACK:-"yes"}
 DEPLOY_SWIFT=${DEPLOY_SWIFT:-"yes"}
+DEPLOY_CEILOMETER=${DEPLOY_CEILOMETER:-"yes"}
 DEPLOY_TEMPEST=${DEPLOY_TEMPEST:-"no"}
 
 
@@ -95,6 +96,14 @@ pushd "playbooks"
     install_bits os-horizon-install.yml
   fi
 
+  # If ceilometer is deployed, it must be run before
+  # swift, since the swift playbooks will make reference
+  # to the ceilometer user when applying the reselleradmin
+  # role
+  if [ "${DEPLOY_CEILOMETER}" == "yes" ]; then
+    install_bits os-ceilometer-install.yml
+  fi
+
   if [ "${DEPLOY_SWIFT}" == "yes" ]; then
     if [ "${DEPLOY_OPENSTACK}" == "no" ]; then
       # When os install is no, make sure we still have keystone for use in swift.