From 3e7ed2c42c4170212110ed28289eb1e006227f70 Mon Sep 17 00:00:00 2001
From: zhubingbing <1392607554@qq.com>
Date: Mon, 7 Nov 2016 07:32:04 +0000
Subject: [PATCH] add panko role

Change-Id: I515fdcdf6093e9e59dbbdc97221d23ed7f4e0a3d
Partially-Implements: blueprint add-panko-ansible-role
---
 ansible/group_vars/all.yml                    | 13 ++++
 ansible/inventory/all-in-one                  |  7 ++
 ansible/inventory/multinode                   |  7 ++
 .../ceilometer/templates/ceilometer.conf.j2   |  9 ++-
 ansible/roles/common/tasks/config.yml         |  2 +
 .../templates/cron-logrotate-panko.conf.j2    |  3 +
 ansible/roles/common/templates/cron.json.j2   |  1 +
 .../roles/common/templates/heka-panko.toml.j2 | 13 ++++
 ansible/roles/common/templates/heka.json.j2   |  7 ++
 .../roles/haproxy/templates/haproxy.cfg.j2    | 19 +++++
 ansible/roles/panko/defaults/main.yml         | 31 ++++++++
 ansible/roles/panko/meta/main.yml             |  3 +
 ansible/roles/panko/tasks/bootstrap.yml       | 70 +++++++++++++++++++
 .../roles/panko/tasks/bootstrap_service.yml   | 21 ++++++
 ansible/roles/panko/tasks/config.yml          | 51 ++++++++++++++
 ansible/roles/panko/tasks/deploy.yml          | 12 ++++
 ansible/roles/panko/tasks/main.yml            |  2 +
 ansible/roles/panko/tasks/pull.yml            |  7 ++
 ansible/roles/panko/tasks/reconfigure.yml     | 64 +++++++++++++++++
 ansible/roles/panko/tasks/register.yml        | 40 +++++++++++
 ansible/roles/panko/tasks/start.yml           | 12 ++++
 ansible/roles/panko/tasks/upgrade.yml         |  6 ++
 .../roles/panko/templates/panko-api.json.j2   | 33 +++++++++
 ansible/roles/panko/templates/panko.conf.j2   | 28 ++++++++
 .../roles/panko/templates/wsgi-panko.conf.j2  | 17 +++++
 ansible/site.yml                              |  8 +++
 etc/kolla/globals.yml                         |  8 +++
 etc/kolla/passwords.yml                       |  3 +
 .../add-panko-role-b76b2b3b1f758e21.yaml      |  3 +
 29 files changed, 499 insertions(+), 1 deletion(-)
 create mode 100644 ansible/roles/common/templates/cron-logrotate-panko.conf.j2
 create mode 100644 ansible/roles/common/templates/heka-panko.toml.j2
 create mode 100644 ansible/roles/panko/defaults/main.yml
 create mode 100644 ansible/roles/panko/meta/main.yml
 create mode 100644 ansible/roles/panko/tasks/bootstrap.yml
 create mode 100644 ansible/roles/panko/tasks/bootstrap_service.yml
 create mode 100644 ansible/roles/panko/tasks/config.yml
 create mode 100644 ansible/roles/panko/tasks/deploy.yml
 create mode 100644 ansible/roles/panko/tasks/main.yml
 create mode 100644 ansible/roles/panko/tasks/pull.yml
 create mode 100644 ansible/roles/panko/tasks/reconfigure.yml
 create mode 100644 ansible/roles/panko/tasks/register.yml
 create mode 100644 ansible/roles/panko/tasks/start.yml
 create mode 100644 ansible/roles/panko/tasks/upgrade.yml
 create mode 100644 ansible/roles/panko/templates/panko-api.json.j2
 create mode 100644 ansible/roles/panko/templates/panko.conf.j2
 create mode 100644 ansible/roles/panko/templates/wsgi-panko.conf.j2
 create mode 100644 releasenotes/notes/add-panko-role-b76b2b3b1f758e21.yaml

diff --git a/ansible/group_vars/all.yml b/ansible/group_vars/all.yml
index b49b776da3..7febc28cf7 100644
--- a/ansible/group_vars/all.yml
+++ b/ansible/group_vars/all.yml
@@ -133,6 +133,8 @@ mariadb_wsrep_port: "4567"
 mariadb_ist_port: "4568"
 mariadb_sst_port: "4444"
 
+panko_api_port: "8977"
+
 rabbitmq_port: "5672"
 rabbitmq_management_port: "15672"
 rabbitmq_cluster_port: "25672"
@@ -291,6 +293,7 @@ enable_neutron_lbaas: "no"
 enable_neutron_qos: "no"
 enable_neutron_agent_ha: "no"
 enable_octavia: "no"
+enable_panko: "no"
 enable_rally: "no"
 enable_sahara: "no"
 enable_searchlight: "no"
@@ -372,6 +375,16 @@ glance_backend_ceph: "{{ enable_ceph }}"
 # Valid options are [ mongodb, mysql, gnocchi ]
 ceilometer_database_type: "mongodb"
 
+# Valid options are [ mongodb, gnocchi, panko ]
+ceilometer_event_type: "mongodb"
+
+
+########################
+### Panko options
+########################
+# Valid options are [ mongodb, mysql ]
+panko_database_type: "mysql"
+
 
 #################
 # Gnocchi options
diff --git a/ansible/inventory/all-in-one b/ansible/inventory/all-in-one
index a90fb922b3..8ed05384b8 100644
--- a/ansible/inventory/all-in-one
+++ b/ansible/inventory/all-in-one
@@ -114,6 +114,9 @@ control
 [manila:children]
 control
 
+[panko:children]
+control
+
 [gnocchi:children]
 control
 
@@ -367,6 +370,10 @@ aodh
 [aodh-notifier:children]
 aodh
 
+# Panko
+[panko-api:children]
+panko
+
 # Gnocchi
 [gnocchi-api:children]
 gnocchi
diff --git a/ansible/inventory/multinode b/ansible/inventory/multinode
index fca4335215..699dafe614 100644
--- a/ansible/inventory/multinode
+++ b/ansible/inventory/multinode
@@ -139,6 +139,9 @@ control
 [congress:children]
 control
 
+[panko:children]
+control
+
 [gnocchi:children]
 control
 
@@ -406,6 +409,10 @@ congress
 [congress-policy-engine:children]
 congress
 
+# Panko
+[panko-api:children]
+panko
+
 # Gnocchi
 [gnocchi-api:children]
 gnocchi
diff --git a/ansible/roles/ceilometer/templates/ceilometer.conf.j2 b/ansible/roles/ceilometer/templates/ceilometer.conf.j2
index 0d33a09e02..1be311b04e 100644
--- a/ansible/roles/ceilometer/templates/ceilometer.conf.j2
+++ b/ansible/roles/ceilometer/templates/ceilometer.conf.j2
@@ -5,9 +5,16 @@ log_dir = /var/log/kolla/ceilometer
 
 transport_url = rabbit://{% for host in groups['rabbitmq'] %}{{ rabbitmq_user }}:{{ rabbitmq_password }}@{{ hostvars[host]['ansible_' + hostvars[host]['api_interface']]['ipv4']['address'] }}:{{ rabbitmq_port }}{% if not loop.last %},{% endif %}{% endfor %}
 
+{% if ceilometer_event_type == "mongodb" %}
+event_dispatchers = database
+{% elif ceilometer_event_type == "gnocchi" %}
+event_dispatchers = gnocchi
+{% elif ceilometer_event_type == "panko" %}
+event_dispatchers = panko
+{% endif %}
+
 {% if ceilometer_database_type == 'gnocchi' %}
 meter_dispatchers = gnocchi
-event_dispatchers = gnocchi
 {% endif %}
 
 [api]
diff --git a/ansible/roles/common/tasks/config.yml b/ansible/roles/common/tasks/config.yml
index f2dd09d5d4..8d020513dd 100644
--- a/ansible/roles/common/tasks/config.yml
+++ b/ansible/roles/common/tasks/config.yml
@@ -37,6 +37,7 @@
     - { name: "keepalived", enabled: "{{ enable_haproxy }}" }
     - { name: "keystone", enabled: "{{ enable_keystone }}" }
     - { name: "mariadb", enabled: "{{ enable_mariadb }}" }
+    - { name: "panko", enabled: "{{ enable_panko }}" }
     - { name: "openstack", enabled: "yes" }
     - { name: "rabbitmq", enabled: "{{ enable_rabbitmq }}" }
     - { name: "swift-account-auditor", src: "swift", enabled: "{{ enable_swift }}" }
@@ -95,6 +96,7 @@
     - { name: "neutron", enabled: "{{ enable_neutron }}" }
     - { name: "nova", enabled: "{{ enable_nova }}" }
     - { name: "octavia", enabled: "{{ enable_octavia }}" }
+    - { name: "panko", enabled: "{{ enable_panko }}" }
     - { name: "rabbitmq", enabled: "{{ enable_rabbitmq }}" }
     - { name: "sahara", enabled: "{{ enable_sahara }}" }
     - { name: "searchlight", enabled: "{{ enable_searchlight }}" }
diff --git a/ansible/roles/common/templates/cron-logrotate-panko.conf.j2 b/ansible/roles/common/templates/cron-logrotate-panko.conf.j2
new file mode 100644
index 0000000000..dd3894cc25
--- /dev/null
+++ b/ansible/roles/common/templates/cron-logrotate-panko.conf.j2
@@ -0,0 +1,3 @@
+"/var/log/kolla/panko/*.log"
+{
+}
diff --git a/ansible/roles/common/templates/cron.json.j2 b/ansible/roles/common/templates/cron.json.j2
index adc437a489..2112f99ddd 100644
--- a/ansible/roles/common/templates/cron.json.j2
+++ b/ansible/roles/common/templates/cron.json.j2
@@ -22,6 +22,7 @@
     ( 'murano', enable_murano ),
     ( 'neutron', enable_neutron ),
     ( 'nova', enable_nova ),
+    ( 'panko', enable_panko ),
     ( 'rabbitmq', enable_rabbitmq ),
     ( 'sahara', enable_sahara ),
     ( 'searchlight', enable_searchlight ),
diff --git a/ansible/roles/common/templates/heka-panko.toml.j2 b/ansible/roles/common/templates/heka-panko.toml.j2
new file mode 100644
index 0000000000..367db41813
--- /dev/null
+++ b/ansible/roles/common/templates/heka-panko.toml.j2
@@ -0,0 +1,13 @@
+[panko_apache_log_decoder]
+type = "SandboxDecoder"
+filename = "lua_decoders/os_panko_apache_log.lua"
+    [panko_apache_log_decoder.config]
+    apache_log_pattern = '%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b %D \"%{Referer}i\" \"%{User-Agent}i\"'
+
+[panko_apache_logstreamer_input]
+type = "LogstreamerInput"
+decoder = "panko_apache_log_decoder"
+log_directory = "/var/log/kolla"
+file_match = 'panko/panko-apache-(?P<Service>.+)-access\.log\.?(?P<Seq>\d*)$'
+priority = ["^Seq"]
+differentiator = ["panko-apache-", "Service"]
diff --git a/ansible/roles/common/templates/heka.json.j2 b/ansible/roles/common/templates/heka.json.j2
index 87ea5e4ced..f7b583f86b 100644
--- a/ansible/roles/common/templates/heka.json.j2
+++ b/ansible/roles/common/templates/heka.json.j2
@@ -91,6 +91,13 @@
             "perm": "0600",
             "optional": {{ (not enable_mariadb | bool) | string | lower }}
         },
+        {
+            "source": "{{ container_config_directory }}/heka-panko.toml",
+            "dest": "/etc/heka/heka-panko.toml",
+            "owner": "heka",
+            "perm": "0600",
+            "optional": {{ (not enable_panko | bool) | string | lower }}
+        },
         {
             "source": "{{ container_config_directory }}/heka-keystone.toml",
             "dest": "/etc/heka/heka-keystone.toml",
diff --git a/ansible/roles/haproxy/templates/haproxy.cfg.j2 b/ansible/roles/haproxy/templates/haproxy.cfg.j2
index 9d1d54883b..7a4a4fcc14 100644
--- a/ansible/roles/haproxy/templates/haproxy.cfg.j2
+++ b/ansible/roles/haproxy/templates/haproxy.cfg.j2
@@ -274,6 +274,25 @@ listen octavia_api_external
 {% endif %}
 {% endif %}
 
+{% if enable_panko | bool %}
+listen panko_api
+  bind {{ kolla_internal_vip_address }}:{{ panko_api_port }}
+  http-request del-header X-Forwarded-Proto
+{% for host in groups['panko-api'] %}
+  server {{ hostvars[host]['ansible_hostname'] }} {{ hostvars[host]['ansible_' + hostvars[host]['api_interface']]['ipv4']['address'] }}:{{ panko_api_port }} check inter 2000 rise 2 fall 5
+{% endfor %}
+{% if haproxy_enable_external_vip | bool %}
+
+listen panko_api_external
+  bind {{ kolla_external_vip_address }}:{{ panko_api_port }} {{ tls_bind_info }}
+  http-request del-header X-Forwarded-Proto
+  http-request set-header X-Forwarded-Proto https if { ssl_fc }
+{% for host in groups['panko-api'] %}
+  server {{ hostvars[host]['ansible_hostname'] }} {{ hostvars[host]['ansible_' + hostvars[host]['api_interface']]['ipv4']['address'] }}:{{ panko_api_port }} check inter 2000 rise 2 fall 5
+{% endfor %}
+{% endif %}
+{% endif %}
+
 {% if enable_heat | bool %}
 listen heat_api
   bind {{ kolla_internal_vip_address }}:{{ heat_api_port }}
diff --git a/ansible/roles/panko/defaults/main.yml b/ansible/roles/panko/defaults/main.yml
new file mode 100644
index 0000000000..4986300410
--- /dev/null
+++ b/ansible/roles/panko/defaults/main.yml
@@ -0,0 +1,31 @@
+---
+project_name: "panko"
+
+####################
+# Database
+####################
+panko_database_name: "panko"
+panko_database_user: "panko"
+panko_database_port: "{{ mongodb_port if panko_database_type == 'mongodb' else database_port }}"
+panko_database_mongodb_address: "{% for host in groups['mongodb'] %}{{ hostvars[host]['ansible_' + hostvars[host]['api_interface']]['ipv4']['address'] }}:{{ pankor_database_port }}{% if not loop.last %},{% endif %}{% endfor %}"
+panko_database_mysql_address: "{{ kolla_internal_fqdn }}"
+
+####################
+# Docker
+####################
+panko_api_image: "{{ docker_registry ~ '/' if docker_registry else '' }}{{ docker_namespace }}/{{ kolla_base_distro }}-{{ kolla_install_type }}-panko-api"
+panko_api_tag: "{{ openstack_release }}"
+panko_api_image_full: "{{ panko_api_image }}:{{ panko_api_tag }}"
+
+####################
+# OpenStack
+####################
+panko_admin_endpoint: "{{ admin_protocol }}://{{ kolla_internal_fqdn }}:{{ panko_api_port }}"
+panko_internal_endpoint: "{{ internal_protocol }}://{{ kolla_internal_fqdn }}:{{ panko_api_port }}"
+panko_public_endpoint: "{{ public_protocol }}://{{ kolla_external_fqdn }}:{{ panko_api_port }}"
+
+panko_logging_debug: "{{ openstack_logging_debug }}"
+
+panko_keystone_user: "panko"
+
+openstack_panko_auth: "{'auth_url':'{{ openstack_auth.auth_url }}','username':'{{ openstack_auth.username }}','password':'{{ openstack_auth.password }}','project_name':'{{ openstack_auth.project_name }}','domain_name':'default'}"
diff --git a/ansible/roles/panko/meta/main.yml b/ansible/roles/panko/meta/main.yml
new file mode 100644
index 0000000000..6b4fff8fef
--- /dev/null
+++ b/ansible/roles/panko/meta/main.yml
@@ -0,0 +1,3 @@
+---
+dependencies:
+  - { role: common }
diff --git a/ansible/roles/panko/tasks/bootstrap.yml b/ansible/roles/panko/tasks/bootstrap.yml
new file mode 100644
index 0000000000..2548a80fa3
--- /dev/null
+++ b/ansible/roles/panko/tasks/bootstrap.yml
@@ -0,0 +1,70 @@
+---
+- name: Creating Panko MongoDB database
+  command: docker exec -t mongodb mongo --host {{ panko_database_mongodb_address }} --eval 'db = db.getSiblingDB("{{ panko_database_name }}"); db.createUser({user':' "{{ panko_database_user }}", pwd':' "{{ panko_database_password}}", roles':' [ "readWrite", "dbAdmin" ]})'
+  register: mongodb_panko_database
+  run_once: true
+  failed_when:
+    - "'already' not in mongodb_panko_database.stdout"
+    - mongodb_panko_database.stdout.split()[4] != 'connecting'
+  delegate_to: "{{ groups['mongodb'][0] }}"
+  when:
+    - panko_database_type == "mongodb"
+
+- name: Checking Panko mysql database
+  command: docker exec -t kolla_toolbox /usr/bin/ansible localhost
+    -m mysql_db
+    -a "login_host='{{ panko_database_mysql_address }}'
+        login_port='{{ panko_database_port }}'
+        login_user='{{ panko_database_user }}'
+        login_password='{{ panko_database_password }}'
+        name='{{ panko_database_name }}'"
+  register: mysql_access
+  failed_when: False
+  changed_when: False
+  run_once: True
+  when:
+    - panko_database_type == "mysql"
+
+- name: Creating panko mysql database
+  command: docker exec -t kolla_toolbox /usr/bin/ansible localhost
+    -m mysql_db
+    -a "login_host='{{ panko_database_mysql_address }}'
+        login_port='{{ panko_database_port }}'
+        login_user='{{ database_user }}'
+        login_password='{{ database_password }}'
+        name='{{ panko_database_name }}'"
+  register: mysql_panko_database
+  changed_when: "{{ mysql_panko_database.stdout.find('localhost | SUCCESS => ') != -1 and
+                    (mysql_panko_database.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed }}"
+  failed_when: mysql_panko_database.stdout.split()[2] != 'SUCCESS'
+  run_once: True
+  delegate_to: "{{ groups['panko-api'][0] }}"
+  when:
+    - panko_database_type == "mysql"
+    - "'FAILED' in mysql_access.stdout"
+
+- name: Creating panko database user and setting permissions
+  command: docker exec -t kolla_toolbox /usr/bin/ansible localhost
+    -m mysql_user
+    -a "login_host='{{ panko_database_mysql_address }}'
+        login_port='{{ panko_database_port }}'
+        login_user='{{ database_user }}'
+        login_password='{{ database_password }}'
+        name='{{ panko_database_name }}'
+        password='{{ panko_database_password }}'
+        host='%'
+        priv='{{ panko_database_name }}.*:ALL'
+        append_privs='yes'"
+  register: database_user_create
+  changed_when: "{{ database_user_create.stdout.find('localhost | SUCCESS => ') != -1 and
+                    (database_user_create.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed }}"
+  failed_when: database_user_create.stdout.split()[2] != 'SUCCESS'
+  run_once: True
+  delegate_to: "{{ groups['panko-api'][0] }}"
+  when:
+    - panko_database_type == "mysql"
+    - "'FAILED' in mysql_access.stdout"
+
+ - include: bootstrap_service.yml
+   when: ((panko_database_type == "mongodb" and mongodb_panko_database.changed)
+            or panko_database_type == "mysql" and mysql_panko_database.changed)
diff --git a/ansible/roles/panko/tasks/bootstrap_service.yml b/ansible/roles/panko/tasks/bootstrap_service.yml
new file mode 100644
index 0000000000..9ac8bab2e7
--- /dev/null
+++ b/ansible/roles/panko/tasks/bootstrap_service.yml
@@ -0,0 +1,21 @@
+---
+- name: Running panko bootstrap container
+  kolla_docker:
+    action: "start_container"
+    common_options: "{{ docker_common_options }}"
+    detach: False
+    environment:
+      KOLLA_BOOTSTRAP:
+      KOLLA_CONFIG_STRATEGY: "{{ config_strategy }}"
+      PANKO_DATABASE_TYPE: "{{ panko_database_type }}"
+    image: "{{ panko_api_image_full }}"
+    labels:
+      BOOTSTRAP:
+    name: "bootstrap_panko"
+    restart_policy: "never"
+    volumes:
+      - "{{ node_config_directory }}/panko-api/:{{ container_config_directory }}/:ro"
+      - "/etc/localtime:/etc/localtime:ro"
+      - "kolla_logs:/var/log/kolla/"
+  run_once: True
+  delegate_to: "{{ groups['panko-api'][0] }}"
diff --git a/ansible/roles/panko/tasks/config.yml b/ansible/roles/panko/tasks/config.yml
new file mode 100644
index 0000000000..71d608d4b7
--- /dev/null
+++ b/ansible/roles/panko/tasks/config.yml
@@ -0,0 +1,51 @@
+---
+- name: Ensuring config directories exist
+  file:
+    path: "{{ node_config_directory }}/{{ item }}"
+    state: "directory"
+    recurse: yes
+  with_items:
+    - "panko-api"
+
+- name: Copying over config.json files for services
+  template:
+    src: "{{ item }}.json.j2"
+    dest: "{{ node_config_directory }}/{{ item }}/config.json"
+  with_items:
+    - "panko-api"
+
+- name: Copying over panko.conf
+  merge_configs:
+    vars:
+      service_name: "{{ item }}"
+    sources:
+      - "{{ role_path }}/templates/panko.conf.j2"
+      - "{{ node_custom_config }}/global.conf"
+      - "{{ node_custom_config }}/database.conf"
+      - "{{ node_custom_config }}/messaging.conf"
+      - "{{ node_custom_config }}/panko.conf"
+      - "{{ node_custom_config }}/panko/{{ item }}.conf"
+      - "{{ node_custom_config }}/panko/{{ inventory_hostname }}/{{ item }}.conf"
+    dest: "{{ node_config_directory }}/{{ item }}/panko.conf"
+  with_items:
+    - "panko-api"
+
+- name: Copying over wsgi-panko files for services
+  template:
+    src: "wsgi-panko.conf.j2"
+    dest: "{{ node_config_directory }}/{{ item }}/wsgi-panko.conf"
+  with_items:
+    - "panko-api"
+
+- name: Check if policies shall be overwritten
+  local_action: stat path="{{ node_custom_config }}/panko/policy.json"
+  register: panko_policy
+
+- name: Copying over existing policy.json
+  template:
+    src: "{{ node_custom_config }}/panko/policy.json"
+    dest: "{{ node_config_directory }}/{{ item }}/policy.json"
+  with_items:
+    - "panko-api"
+  when:
+    panko_policy.stat.exists
diff --git a/ansible/roles/panko/tasks/deploy.yml b/ansible/roles/panko/tasks/deploy.yml
new file mode 100644
index 0000000000..063a4691cd
--- /dev/null
+++ b/ansible/roles/panko/tasks/deploy.yml
@@ -0,0 +1,12 @@
+---
+- include: register.yml
+  when: inventory_hostname in groups['panko-api']
+
+- include: config.yml
+  when: inventory_hostname in groups['panko-api']
+
+- include: bootstrap.yml
+  when: inventory_hostname in groups['panko-api']
+
+- include: start.yml
+  when: inventory_hostname in groups['panko-api']
diff --git a/ansible/roles/panko/tasks/main.yml b/ansible/roles/panko/tasks/main.yml
new file mode 100644
index 0000000000..b017e8b4ad
--- /dev/null
+++ b/ansible/roles/panko/tasks/main.yml
@@ -0,0 +1,2 @@
+---
+- include: "{{ action }}.yml"
diff --git a/ansible/roles/panko/tasks/pull.yml b/ansible/roles/panko/tasks/pull.yml
new file mode 100644
index 0000000000..cacd7e794e
--- /dev/null
+++ b/ansible/roles/panko/tasks/pull.yml
@@ -0,0 +1,7 @@
+---
+- name: Pulling panko-api image
+  kolla_docker:
+    action: "pull_image"
+    common_options: "{{ docker_common_options }}"
+    image: "{{ panko_api_image_full }}"
+  when: inventory_hostname in groups['panko-api']
diff --git a/ansible/roles/panko/tasks/reconfigure.yml b/ansible/roles/panko/tasks/reconfigure.yml
new file mode 100644
index 0000000000..d58756d0d1
--- /dev/null
+++ b/ansible/roles/panko/tasks/reconfigure.yml
@@ -0,0 +1,64 @@
+---
+- name: Ensuring the containers up
+  kolla_docker:
+    name: "{{ item.name }}"
+    action: "get_container_state"
+  register: container_state
+  failed_when: container_state.Running == false
+  when: inventory_hostname in groups[item.group]
+  with_items:
+    - { name: panko_api, group: panko-api }
+
+- include: config.yml
+
+- name: Check the configs
+  command: docker exec {{ item.name }} /usr/local/bin/kolla_set_configs --check
+  changed_when: false
+  failed_when: false
+  register: check_results
+  when: inventory_hostname in groups[item.group]
+  with_items:
+    - { name: panko_api, group: panko-api }
+
+# NOTE(jeffrey4l): when config_strategy == 'COPY_ALWAYS'
+# and container env['KOLLA_CONFIG_STRATEGY'] == 'COPY_ONCE',
+# just remove the container and start again
+- name: Containers config strategy
+  kolla_docker:
+    name: "{{ item.name }}"
+    action: "get_container_env"
+  register: container_envs
+  when: inventory_hostname in groups[item.group]
+  with_items:
+    - { name: panko_api, group: panko-api }
+
+- name: Remove the containers
+  kolla_docker:
+    name: "{{ item[0]['name'] }}"
+    action: "remove_container"
+  register: remove_containers
+  when:
+    - inventory_hostname in groups[item[0]['group']]
+    - config_strategy == "COPY_ONCE" or item[1]['KOLLA_CONFIG_STRATEGY'] == 'COPY_ONCE'
+    - item[2]['rc'] == 1
+  with_together:
+    - [{ name: panko_api, group: panko-api }]
+    - "{{ container_envs.results }}"
+    - "{{ check_results.results }}"
+
+- include: start.yml
+  when: remove_containers.changed
+
+- name: Restart containers
+  kolla_docker:
+    name: "{{ item[0]['name'] }}"
+    action: "restart_container"
+  when:
+    - inventory_hostname in groups[item[0]['group']]
+    - config_strategy == 'COPY_ALWAYS'
+    - item[1]['KOLLA_CONFIG_STRATEGY'] != 'COPY_ONCE'
+    - item[2]['rc'] == 1
+  with_together:
+    - [{ name: panko_api, group: panko-api }]
+    - "{{ container_envs.results }}"
+    - "{{ check_results.results }}"
diff --git a/ansible/roles/panko/tasks/register.yml b/ansible/roles/panko/tasks/register.yml
new file mode 100644
index 0000000000..34b14a47be
--- /dev/null
+++ b/ansible/roles/panko/tasks/register.yml
@@ -0,0 +1,40 @@
+---
+- name: Creating the panko service and endpoint
+  command: docker exec -t kolla_toolbox /usr/bin/ansible localhost
+    -m kolla_keystone_service
+    -a "service_name=panko
+        service_type=event
+        description='Panko Service'
+        endpoint_region={{ openstack_region_name }}
+        url='{{ item.url }}'
+        interface='{{ item.interface }}'
+        region_name={{ openstack_region_name }}
+        auth={{ '{{ openstack_panko_auth }}' }}"
+    -e "{'openstack_panko_auth':{{ openstack_panko_auth }}}"
+  register: panko_endpoint
+  changed_when: "{{ panko_endpoint.stdout.find('localhost | SUCCESS => ') != -1 and (panko_endpoint.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed }}"
+  until: panko_endpoint.stdout.split()[2] == 'SUCCESS'
+  retries: 10
+  delay: 5
+  run_once: True
+  with_items:
+    - {'interface': 'admin', 'url': '{{ panko_admin_endpoint }}'}
+    - {'interface': 'internal', 'url': '{{ panko_internal_endpoint }}'}
+    - {'interface': 'public', 'url': '{{ panko_public_endpoint }}'}
+
+- name: Creating the panko project, user, and role
+  command: docker exec -t kolla_toolbox /usr/bin/ansible localhost
+    -m kolla_keystone_user
+    -a "project=service
+        user=panko
+        password={{ panko_keystone_password }}
+        role=admin
+        region_name={{ openstack_region_name }}
+        auth={{ '{{ openstack_panko_auth }}' }}"
+    -e "{'openstack_panko_auth':{{ openstack_panko_auth }}}"
+  register: panko_user
+  changed_when: "{{ panko_user.stdout.find('localhost | SUCCESS => ') != -1 and (panko_user.stdout.split('localhost | SUCCESS => ')[1]|from_json).changed }}"
+  until: panko_user.stdout.split()[2] == 'SUCCESS'
+  retries: 10
+  delay: 5
+  run_once: True
diff --git a/ansible/roles/panko/tasks/start.yml b/ansible/roles/panko/tasks/start.yml
new file mode 100644
index 0000000000..12f9b0efe8
--- /dev/null
+++ b/ansible/roles/panko/tasks/start.yml
@@ -0,0 +1,12 @@
+---
+- name: Starting panko-api container
+  kolla_docker:
+    action: "start_container"
+    common_options: "{{ docker_common_options }}"
+    image: "{{ panko_api_image_full }}"
+    name: "panko_api"
+    volumes:
+      - "{{ node_config_directory }}/panko-api/:{{ container_config_directory }}/:ro"
+      - "/etc/localtime:/etc/localtime:ro"
+      - "kolla_logs:/var/log/kolla/"
+  when: inventory_hostname in groups['panko-api']
diff --git a/ansible/roles/panko/tasks/upgrade.yml b/ansible/roles/panko/tasks/upgrade.yml
new file mode 100644
index 0000000000..308053080c
--- /dev/null
+++ b/ansible/roles/panko/tasks/upgrade.yml
@@ -0,0 +1,6 @@
+---
+- include: config.yml
+
+- include: bootstrap_service.yml
+
+- include: start.yml
diff --git a/ansible/roles/panko/templates/panko-api.json.j2 b/ansible/roles/panko/templates/panko-api.json.j2
new file mode 100644
index 0000000000..9331ca2083
--- /dev/null
+++ b/ansible/roles/panko/templates/panko-api.json.j2
@@ -0,0 +1,33 @@
+{% set panko_cmd = 'apache2' if kolla_base_distro in ['ubuntu', 'debian'] else 'httpd' %}
+{% set panko_dir = 'apache2/conf-enabled' if kolla_base_distro in ['ubuntu', 'debian'] else 'httpd/conf.d' %}
+{
+    "command": "{{ panko_cmd }} -DFOREGROUND",
+    "config_files": [
+        {
+            "source": "{{ container_config_directory }}/panko.conf",
+            "dest": "/etc/panko/panko.conf",
+            "owner": "panko",
+            "perm": "0600"
+        },
+        {
+            "source": "{{ container_config_directory }}/policy.json",
+            "dest": "/etc/panko/policy.json",
+            "owner": "panko",
+            "perm": "0600",
+            "optional": true
+        },
+        {
+            "source": "{{ container_config_directory }}/wsgi-panko.conf",
+            "dest": "/etc/{{ panko_dir }}/wsgi-panko.conf",
+            "owner": "panko",
+            "perm": "0640"
+        }
+    ],
+    "permissions": [
+        {
+            "path": "/var/log/kolla/panko",
+            "owner": "panko:panko",
+            "recurse": true
+        }
+    ]
+}
diff --git a/ansible/roles/panko/templates/panko.conf.j2 b/ansible/roles/panko/templates/panko.conf.j2
new file mode 100644
index 0000000000..74e2157c6f
--- /dev/null
+++ b/ansible/roles/panko/templates/panko.conf.j2
@@ -0,0 +1,28 @@
+#jinja2: trim_blocks: False
+[DEFAULT]
+log_dir = /var/log/kolla/panko
+debug = {{ panko_logging_debug }}
+
+[database]
+{% if panko_database_type == "mongodb" %}
+event_connection = mongodb://{{ panko_database_user }}:{{ panko_database_password }}@{{ panko_database_mongodb_address }}/{{ panko_database_name }}
+metering_connection = mongodb://{{ panko_database_user }}:{{ panko_database_password }}@{{ panko_database_mongodb_address }}/{{ panko_database_name }}
+{% elif panko_database_type == "mysql" %}
+event_connection = mysql+pymysql://{{ panko_database_user }}:{{ panko_database_password }}@{{ panko_database_mysql_address }}:{{ panko_database_port }}/{{ panko_database_name }}
+metering_connection = mysql+pymysql://{{ panko_database_user }}:{{ panko_database_password }}@{{ panko_database_mysql_address }}:{{ panko_database_port }}/{{ panko_database_name }}
+{% endif %}
+
+
+[keystone_authtoken]
+auth_uri = {{ internal_protocol }}://{{ kolla_internal_fqdn }}:{{ keystone_public_port }}
+project_domain_name = Default
+project_name = service
+user_domain_name = Default
+username = {{ panko_keystone_user }}
+password = {{ panko_keystone_password }}
+auth_url = {{ admin_protocol }}://{{ kolla_internal_fqdn }}:{{ keystone_admin_port }}
+auth_type = password
+
+memcache_security_strategy = ENCRYPT
+memcache_secret_key = {{ memcache_secret_key }}
+memcached_servers = {% for host in groups['memcached'] %}{{ hostvars[host]['ansible_' + hostvars[host]['api_interface']]['ipv4']['address'] }}:{{ memcached_port }}{% if not loop.last %},{% endif %}{% endfor %}
diff --git a/ansible/roles/panko/templates/wsgi-panko.conf.j2 b/ansible/roles/panko/templates/wsgi-panko.conf.j2
new file mode 100644
index 0000000000..e9128b959f
--- /dev/null
+++ b/ansible/roles/panko/templates/wsgi-panko.conf.j2
@@ -0,0 +1,17 @@
+{% set python_path = '/usr/lib/python2.7/site-packages' if kolla_install_type == 'binary' else '/var/lib/kolla/venv/lib/python2.7/site-packages' %}
+Listen {{ hostvars[inventory_hostname]['ansible_' + api_interface]['ipv4']['address'] }}:{{ panko_api_port }}
+
+<VirtualHost *:{{ panko_api_port }}>
+
+  ErrorLog "/var/log/kolla/panko/panko-api-error.log"
+  CustomLog "/var/log/kolla/panko/panko-api-access.log" combined
+  WSGIApplicationGroup %{GLOBAL}
+  WSGIDaemonProcess panko group=panko processes={{ openstack_service_workers }} threads=1 user=panko python-path={{ python_path }}
+  WSGIProcessGroup panko
+  WSGIScriptAlias / "{{ python_path }}/panko/api/app.wsgi"
+
+  <Directory "{{ python_path }}/panko/api">
+        Require all granted
+  </Directory>
+
+</VirtualHost>
diff --git a/ansible/site.yml b/ansible/site.yml
index 91b9ab44b7..0a9f5dab5b 100644
--- a/ansible/site.yml
+++ b/ansible/site.yml
@@ -207,6 +207,14 @@
         tags: nova,
         when: enable_nova | bool }
 
+- name: Apply role panko
+  hosts: panko-api
+  serial: '{{ serial|default("0") }}'
+  roles:
+    - { role: panko,
+        tags: panko,
+        when: enable_panko | bool }
+
 - name: Apply role kuryr
   hosts:
     - compute
diff --git a/etc/kolla/globals.yml b/etc/kolla/globals.yml
index 51397d6bad..91b5d23afa 100644
--- a/etc/kolla/globals.yml
+++ b/etc/kolla/globals.yml
@@ -203,6 +203,14 @@ kolla_internal_vip_address: "10.10.10.254"
 # Valid options are [ mongodb, mysql, gnocchi ]
 #ceilometer_database_type: "mongodb"
 
+# Valid options are [ mongodb, gnocchi, panko ]
+#ceilometer_event_type: "mongodb"
+
+#######################
+## Panko options
+#######################
+# Valid options are [ mongodb, mysql ]
+#panko_database_type: "mysql"
 
 #######################
 # Gnocchi options
diff --git a/etc/kolla/passwords.yml b/etc/kolla/passwords.yml
index 7aea8a1830..be1f36a918 100644
--- a/etc/kolla/passwords.yml
+++ b/etc/kolla/passwords.yml
@@ -55,6 +55,9 @@ cinder_keystone_password:
 cloudkitty_database_password:
 cloudkitty_keystone_password:
 
+panko_database_password:
+panko_keystone_password:
+
 sahara_database_password:
 sahara_keystone_password:
 
diff --git a/releasenotes/notes/add-panko-role-b76b2b3b1f758e21.yaml b/releasenotes/notes/add-panko-role-b76b2b3b1f758e21.yaml
new file mode 100644
index 0000000000..02b573f2cc
--- /dev/null
+++ b/releasenotes/notes/add-panko-role-b76b2b3b1f758e21.yaml
@@ -0,0 +1,3 @@
+---
+features:
+  - Add Panko role, Panko is a component of the Telemetry project