Add Gnocchi and Panko support

- added ability to configure polling_interval
- added panko, gnocchi publishers
- added ability to disable publishers
- parametrized pipelines
- added possibility to create resources in gnocchi

Change-Id: Id0f934def308d005d93378516d03184fa5418a8c
Related-Prod: https://mirantis.jira.com/browse/PROD-17718
diff --git a/.kitchen.yml b/.kitchen.yml
index bb78fa4..fec26e7 100644
--- a/.kitchen.yml
+++ b/.kitchen.yml
@@ -75,6 +75,16 @@
             server:
               version: <%= ENV['OS_VERSION'] || 'pike' %>
 
+  - name: server_gnocchi_cluster
+    provisioner:
+      pillars-from-files:
+        ceilometer.sls: tests/pillar/server_gnocchi_cluster.sls
+      pillars:
+        release.sls:
+          ceilometer:
+            server:
+              version: <%= ENV['OS_VERSION'] || 'pike' %>
+
   - name: server_single
     provisioner:
       pillars-from-files:
@@ -111,6 +121,32 @@
               - release
               - ssl
 
+  - name: server_gnocchi_cluster_ssl
+    provisioner:
+      pillars-from-files:
+        ceilometer.sls: tests/pillar/server_gnocchi_cluster.sls
+      pillars:
+        release.sls:
+          ceilometer:
+            server:
+              version: <%= ENV['OS_VERSION'] || 'pike' %>
+        ssl.sls:
+          ceilometer:
+            server:
+              identity:
+                protocol: https
+              message_queue:
+                port: 5671
+                ssl:
+                  enabled: True
+        top.sls:
+          base:
+            "*":
+              - linux_repo_openstack
+              - ceilometer
+              - release
+              - ssl
+
   - name: agent_cluster_ssl
     provisioner:
       pillars-from-files:
diff --git a/.travis.yml b/.travis.yml
index f345b8f..7c4a0fa 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -24,18 +24,22 @@
     - PLATFORM=epcim/salt-formulas:saltstack-ubuntu-xenial-salt-2016.3 OS_VERSION=ocata SUITE=server_cluster
     - PLATFORM=epcim/salt-formulas:saltstack-ubuntu-xenial-salt-2016.3 OS_VERSION=ocata SUITE=server_single
     - PLATFORM=epcim/salt-formulas:saltstack-ubuntu-xenial-salt-2016.3 OS_VERSION=pike SUITE=server_cluster
+    - PLATFORM=epcim/salt-formulas:saltstack-ubuntu-xenial-salt-2016.3 OS_VERSION=pike SUITE=server_gnocchi_cluster
     - PLATFORM=epcim/salt-formulas:saltstack-ubuntu-xenial-salt-2016.3 OS_VERSION=pike SUITE=server_single
     - PLATFORM=epcim/salt-formulas:saltstack-ubuntu-xenial-salt-2016.3 OS_VERSION=pike SUITE=server_cluster_ssl
+    - PLATFORM=epcim/salt-formulas:saltstack-ubuntu-xenial-salt-2016.3 OS_VERSION=pike SUITE=server_gnocchi_cluster_ssl
     - PLATFORM=epcim/salt-formulas:saltstack-ubuntu-xenial-salt-2016.3 OS_VERSION=pike SUITE=agent_cluster_ssl
     - PLATFORM=epcim/salt-formulas:saltstack-ubuntu-xenial-salt-2017.7 OS_VERSION=ocata SUITE=agent_cluster
     - PLATFORM=epcim/salt-formulas:saltstack-ubuntu-xenial-salt-2017.7 OS_VERSION=ocata SUITE=agent_single
     - PLATFORM=epcim/salt-formulas:saltstack-ubuntu-xenial-salt-2017.7 OS_VERSION=pike SUITE=agent_cluster
     - PLATFORM=epcim/salt-formulas:saltstack-ubuntu-xenial-salt-2017.7 OS_VERSION=pike SUITE=agent_single
     - PLATFORM=epcim/salt-formulas:saltstack-ubuntu-xenial-salt-2017.7 OS_VERSION=ocata SUITE=server_cluster
+    - PLATFORM=epcim/salt-formulas:saltstack-ubuntu-xenial-salt-2017.7 OS_VERSION=pike SUITE=server_gnocchi_cluster
     - PLATFORM=epcim/salt-formulas:saltstack-ubuntu-xenial-salt-2017.7 OS_VERSION=ocata SUITE=server_single
     - PLATFORM=epcim/salt-formulas:saltstack-ubuntu-xenial-salt-2017.7 OS_VERSION=pike SUITE=server_cluster
     - PLATFORM=epcim/salt-formulas:saltstack-ubuntu-xenial-salt-2017.7 OS_VERSION=pike SUITE=server_single
     - PLATFORM=epcim/salt-formulas:saltstack-ubuntu-xenial-salt-2017.7 OS_VERSION=pike SUITE=server_cluster_ssl
+    - PLATFORM=epcim/salt-formulas:saltstack-ubuntu-xenial-salt-2017.7 OS_VERSION=pike SUITE=server_gnocchi_cluster_ssl
     - PLATFORM=epcim/salt-formulas:saltstack-ubuntu-xenial-salt-2017.7 OS_VERSION=pike SUITE=agent_cluster_ssl
 
 before_script:
diff --git a/ceilometer/agent.sls b/ceilometer/agent.sls
index c4c5ffa..661da46 100644
--- a/ceilometer/agent.sls
+++ b/ceilometer/agent.sls
@@ -61,7 +61,7 @@
 
 {%- for publisher_name, publisher in agent.get('publisher', {}).items() %}
 
-{%- if publisher_name != "default" %}
+{%- if publisher_name not in ['default', 'gnocchi', 'panko'] %}
 
 ceilometer_publisher_{{ publisher_name }}_pkg:
   pkg.latest:
@@ -79,7 +79,7 @@
   - require:
     - pkg: ceilometer_agent_packages
 
-{%- if agent.version != "kilo" %}
+{%- if agent.version != 'kilo' %}
 
 ceilometer_agent_event_pipeline:
   file.managed:
@@ -115,6 +115,21 @@
 {%- endif %}
 {%- endif %}
 
+{# Starting Pike switch to polling.yaml to handle meters polling as recommended in upstream #}
+{%- if agent.version not in ['liberty', 'juno', 'kilo', 'mitaka', 'newton', 'ocata'] and agent.polling is defined %}
+
+ceilometer_agent_polling:
+  file.managed:
+  - name: /etc/ceilometer/polling.yaml
+  - source: salt://ceilometer/files/{{ agent.version }}/polling.yaml
+  - template: jinja
+  - require:
+    - pkg: ceilometer_agent_packages
+  - watch_in:
+    - service: ceilometer_agent_services
+
+{%- endif %}
+
 ceilometer_agent_services:
   service.running:
   - names: {{ agent.services }}
diff --git a/ceilometer/files/pike/ceilometer-server.conf.Debian b/ceilometer/files/pike/ceilometer-server.conf.Debian
index 41cc4c4..054c981 100644
--- a/ceilometer/files/pike/ceilometer-server.conf.Debian
+++ b/ceilometer/files/pike/ceilometer-server.conf.Debian
@@ -14,7 +14,6 @@
 log_config_append=/etc/ceilometer/logging.conf
 {%- endif %}
 
-
 {%- if server.message_queue.rpc_thread_pool_size is defined %}
 executor_thread_pool_size = {{ server.message_queue.rpc_thread_pool_size }}
 {%- endif %}
@@ -114,6 +113,27 @@
 {%- endif %}
 {%- endif %}
 
+
+{%- if server.get('publisher', {}).get('gnocchi', {}).get('enabled', False) %}
+[dispatcher_gnocchi]
+
+{%- if server.publisher.gnocchi.filter_project is defined %}
+filter_project = {{ server.publisher.gnocchi.filter_project }}
+{%- endif %}
+
+{%- if server.publisher.gnocchi.archive_policy is defined %}
+archive_policy = {{ server.publisher.gnocchi.archive_policy }}
+{%- endif %}
+
+{%- if server.publisher.gnocchi.resources_definition_file is defined %}
+resources_definition_file = {{ server.publisher.gnocchi.resources_definition_file }}
+{%- endif %}
+
+{%- if server.publisher.gnocchi.request_timeout is defined %}
+request_timeout = {{ server.publisher.gnocchi.request_timeout }}
+{%- endif %}
+{%- endif %}
+
 [keystone_authtoken]
 
 auth_type = password
diff --git a/ceilometer/files/pike/event_pipeline.yaml b/ceilometer/files/pike/event_pipeline.yaml
index 8f025fc..936b52c 100644
--- a/ceilometer/files/pike/event_pipeline.yaml
+++ b/ceilometer/files/pike/event_pipeline.yaml
@@ -1,3 +1,20 @@
+{%- from "ceilometer/map.jinja" import server with context %}
+{%- from "ceilometer/map.jinja" import agent with context %}
+{%- if server.get('enabled', False) %}
+{%- set publisher = server.publisher %}
+{%- else %}
+{%- set publisher = agent.publisher %}
+{%- endif %}
+{%- set publisher_lst = [] %}
+{%- for k, v in publisher.items() %}
+{%- if v.get('enabled', False) and v.get('publish_event', False) %}
+{%- if k == 'default' %}
+{%- do publisher_lst.append( '- direct://' ) %}
+{%- else %}
+{%- do publisher_lst.append( '- ' + v.url ) %}
+{%- endif %}
+{%- endif %}
+{%- endfor %}
 ---
 sources:
     - name: event_source
@@ -9,4 +26,4 @@
     - name: event_sink
       transformers:
       publishers:
-          - direct://
\ No newline at end of file
+          {{ '\n'.join(publisher_lst) }}
diff --git a/ceilometer/files/pike/gnocchi_resources.yaml b/ceilometer/files/pike/gnocchi_resources.yaml
new file mode 100644
index 0000000..a92ce7d
--- /dev/null
+++ b/ceilometer/files/pike/gnocchi_resources.yaml
@@ -0,0 +1,298 @@
+---
+
+resources:
+  - resource_type: identity
+    metrics:
+      - 'identity.authenticate.success'
+      - 'identity.authenticate.pending'
+      - 'identity.authenticate.failure'
+      - 'identity.user.created'
+      - 'identity.user.deleted'
+      - 'identity.user.updated'
+      - 'identity.group.created'
+      - 'identity.group.deleted'
+      - 'identity.group.updated'
+      - 'identity.role.created'
+      - 'identity.role.deleted'
+      - 'identity.role.updated'
+      - 'identity.project.created'
+      - 'identity.project.deleted'
+      - 'identity.project.updated'
+      - 'identity.trust.created'
+      - 'identity.trust.deleted'
+      - 'identity.role_assignment.created'
+      - 'identity.role_assignment.deleted'
+
+  - resource_type: ceph_account
+    metrics:
+      - 'radosgw.objects'
+      - 'radosgw.objects.size'
+      - 'radosgw.objects.containers'
+      - 'radosgw.api.request'
+      - 'radosgw.containers.objects'
+      - 'radosgw.containers.objects.size'
+
+  - resource_type: instance
+    metrics:
+      - 'memory'
+      - 'memory.usage'
+      - 'memory.resident'
+      - 'memory.swap.in'
+      - 'memory.swap.out'
+      - 'memory.bandwidth.total'
+      - 'memory.bandwidth.local'
+      - 'vcpus'
+      - 'cpu'
+      - 'cpu.delta'
+      - 'cpu_util'
+      - 'cpu_l3_cache'
+      - 'disk.root.size'
+      - 'disk.ephemeral.size'
+      - 'disk.read.requests'
+      - 'disk.read.requests.rate'
+      - 'disk.write.requests'
+      - 'disk.write.requests.rate'
+      - 'disk.read.bytes'
+      - 'disk.read.bytes.rate'
+      - 'disk.write.bytes'
+      - 'disk.write.bytes.rate'
+      - 'disk.latency'
+      - 'disk.iops'
+      - 'disk.capacity'
+      - 'disk.allocation'
+      - 'disk.usage'
+      - 'compute.instance.booting.time'
+      - 'perf.cpu.cycles'
+      - 'perf.instructions'
+      - 'perf.cache.references'
+      - 'perf.cache.misses'
+    attributes:
+      host: resource_metadata.(instance_host|host)
+      image_ref: resource_metadata.image_ref
+      display_name: resource_metadata.display_name
+      flavor_id: resource_metadata.(instance_flavor_id|(flavor.id)|flavor_id)
+      flavor_name: resource_metadata.(instance_type|(flavor.name)|flavor_name)
+      server_group: resource_metadata.user_metadata.server_group
+    event_delete: compute.instance.delete.start
+    event_attributes:
+      id: instance_id
+    event_associated_resources:
+      instance_network_interface: '{"=": {"instance_id": "%s"}}'
+      instance_disk: '{"=": {"instance_id": "%s"}}'
+
+  - resource_type: instance_network_interface
+    metrics:
+      - 'network.outgoing.packets.rate'
+      - 'network.incoming.packets.rate'
+      - 'network.outgoing.packets'
+      - 'network.incoming.packets'
+      - 'network.outgoing.packets.drop'
+      - 'network.incoming.packets.drop'
+      - 'network.outgoing.packets.error'
+      - 'network.incoming.packets.error'
+      - 'network.outgoing.bytes.rate'
+      - 'network.incoming.bytes.rate'
+      - 'network.outgoing.bytes'
+      - 'network.incoming.bytes'
+    attributes:
+      name: resource_metadata.vnic_name
+      instance_id: resource_metadata.instance_id
+
+  - resource_type: instance_disk
+    metrics:
+      - 'disk.device.read.requests'
+      - 'disk.device.read.requests.rate'
+      - 'disk.device.write.requests'
+      - 'disk.device.write.requests.rate'
+      - 'disk.device.read.bytes'
+      - 'disk.device.read.bytes.rate'
+      - 'disk.device.write.bytes'
+      - 'disk.device.write.bytes.rate'
+      - 'disk.device.latency'
+      - 'disk.device.iops'
+      - 'disk.device.capacity'
+      - 'disk.device.allocation'
+      - 'disk.device.usage'
+    attributes:
+      name: resource_metadata.disk_name
+      instance_id: resource_metadata.instance_id
+
+  - resource_type: image
+    metrics:
+      - 'image.size'
+      - 'image.download'
+      - 'image.serve'
+    attributes:
+      name: resource_metadata.name
+      container_format: resource_metadata.container_format
+      disk_format: resource_metadata.disk_format
+    event_delete: image.delete
+    event_attributes:
+      id: resource_id
+
+  - resource_type: ipmi
+    metrics:
+      - 'hardware.ipmi.node.power'
+      - 'hardware.ipmi.node.temperature'
+      - 'hardware.ipmi.node.inlet_temperature'
+      - 'hardware.ipmi.node.outlet_temperature'
+      - 'hardware.ipmi.node.fan'
+      - 'hardware.ipmi.node.current'
+      - 'hardware.ipmi.node.voltage'
+      - 'hardware.ipmi.node.airflow'
+      - 'hardware.ipmi.node.cups'
+      - 'hardware.ipmi.node.cpu_util'
+      - 'hardware.ipmi.node.mem_util'
+      - 'hardware.ipmi.node.io_util'
+
+  - resource_type: network
+    metrics:
+      - 'bandwidth'
+      - 'ip.floating'
+    event_delete: floatingip.delete.end
+    event_attributes:
+      id: resource_id
+
+  - resource_type: stack
+    metrics:
+      - 'stack.create'
+      - 'stack.update'
+      - 'stack.delete'
+      - 'stack.resume'
+      - 'stack.suspend'
+
+  - resource_type: swift_account
+    metrics:
+      - 'storage.objects.incoming.bytes'
+      - 'storage.objects.outgoing.bytes'
+      - 'storage.api.request'
+      - 'storage.objects.size'
+      - 'storage.objects'
+      - 'storage.objects.containers'
+      - 'storage.containers.objects'
+      - 'storage.containers.objects.size'
+
+  - resource_type: volume
+    metrics:
+      - 'volume'
+      - 'volume.size'
+      - 'snapshot.size'
+      - 'volume.snapshot.size'
+      - 'volume.backup.size'
+    attributes:
+      display_name: resource_metadata.(display_name|name)
+      volume_type: resource_metadata.volume_type
+    event_delete: volume.delete.start
+    event_attributes:
+      id: resource_id
+
+  - resource_type: host
+    metrics:
+      - 'hardware.cpu.load.1min'
+      - 'hardware.cpu.load.5min'
+      - 'hardware.cpu.load.15min'
+      - 'hardware.cpu.util'
+      - 'hardware.memory.total'
+      - 'hardware.memory.used'
+      - 'hardware.memory.swap.total'
+      - 'hardware.memory.swap.avail'
+      - 'hardware.memory.buffer'
+      - 'hardware.memory.cached'
+      - 'hardware.network.ip.outgoing.datagrams'
+      - 'hardware.network.ip.incoming.datagrams'
+      - 'hardware.system_stats.cpu.idle'
+      - 'hardware.system_stats.io.outgoing.blocks'
+      - 'hardware.system_stats.io.incoming.blocks'
+    attributes:
+      host_name: resource_metadata.resource_url
+
+  - resource_type: host_disk
+    metrics:
+      - 'hardware.disk.size.total'
+      - 'hardware.disk.size.used'
+    attributes:
+      host_name: resource_metadata.resource_url
+      device_name: resource_metadata.device
+
+  - resource_type: host_network_interface
+    metrics:
+      - 'hardware.network.incoming.bytes'
+      - 'hardware.network.outgoing.bytes'
+      - 'hardware.network.outgoing.errors'
+    attributes:
+      host_name: resource_metadata.resource_url
+      device_name: resource_metadata.name
+
+  - resource_type: nova_compute
+    metrics:
+      - 'compute.node.cpu.frequency'
+      - 'compute.node.cpu.idle.percent'
+      - 'compute.node.cpu.idle.time'
+      - 'compute.node.cpu.iowait.percent'
+      - 'compute.node.cpu.iowait.time'
+      - 'compute.node.cpu.kernel.percent'
+      - 'compute.node.cpu.kernel.time'
+      - 'compute.node.cpu.percent'
+      - 'compute.node.cpu.user.percent'
+      - 'compute.node.cpu.user.time'
+    attributes:
+      host_name: resource_metadata.host
+
+  - resource_type: manila_share
+    metrics:
+      - 'manila.share.size'
+    attributes:
+      name: resource_metadata.name
+      host: resource_metadata.host
+      status: resource_metadata.status
+      availability_zone: resource_metadata.availability_zone
+      protocol: resource_metadata.protocol
+
+  - resource_type: switch
+    metrics:
+      - 'switch'
+      - 'switch.ports'
+    attributes:
+      controller: resource_metadata.controller
+
+  - resource_type: switch_port
+    metrics:
+      - 'switch.port'
+      - 'switch.port.uptime'
+      - 'switch.port.receive.packets'
+      - 'switch.port.transmit.packets'
+      - 'switch.port.receive.bytes'
+      - 'switch.port.transmit.bytes'
+      - 'switch.port.receive.drops'
+      - 'switch.port.transmit.drops'
+      - 'switch.port.receive.errors'
+      - 'switch.port.transmit.errors'
+      - 'switch.port.receive.frame_error'
+      - 'switch.port.receive.overrun_error'
+      - 'switch.port.receive.crc_error'
+      - 'switch.port.collision.count'
+    attributes:
+      switch: resource_metadata.switch
+      port_number_on_switch: resource_metadata.port_number_on_switch
+      neutron_port_id: resource_metadata.neutron_port_id
+      controller: resource_metadata.controller
+
+  - resource_type: port
+    metrics:
+      - 'port'
+      - 'port.uptime'
+      - 'port.receive.packets'
+      - 'port.transmit.packets'
+      - 'port.receive.bytes'
+      - 'port.transmit.bytes'
+      - 'port.receive.drops'
+      - 'port.receive.errors'
+    attributes:
+      controller: resource_metadata.controller
+
+  - resource_type: switch_table
+    metrics:
+      - 'switch.table.active.entries'
+    attributes:
+      controller: resource_metadata.controller
+      switch: resource_metadata.switch
diff --git a/ceilometer/files/pike/pipeline.yaml b/ceilometer/files/pike/pipeline.yaml
index 4bf2f6c..77512de 100644
--- a/ceilometer/files/pike/pipeline.yaml
+++ b/ceilometer/files/pike/pipeline.yaml
@@ -5,23 +5,104 @@
 {%- else %}
 {%- set publisher = agent.publisher %}
 {%- endif %}
+{%- set publisher_lst = [] %}
+{%- for k, v in publisher.items() %}
+{%- if v.get('enabled', False) and v.get('publish_metric', False) %}
+{%- if k == 'default' %}
+{%- do publisher_lst.append( '- notifier://' ) %}
+{%- elif k == 'graphite' %}
+{%- do publisher_lst.append( '- graphite://' + v.host + ':' + v.port ) %}
+{%- else %}
+{%- do publisher_lst.append( '- ' + v.url ) %}
+{%- endif %}
+{%- endif %}
+{%- endfor %}
 ---
 sources:
     - name: meter_source
-      interval: 60
       meters:
           - "*"
       sinks:
           - meter_sink
+    - name: cpu_source
+      meters:
+          - "cpu"
+      sinks:
+          - cpu_sink
+          - cpu_delta_sink
+    - name: disk_source
+      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
+      meters:
+          - "network.incoming.bytes"
+          - "network.incoming.packets"
+          - "network.outgoing.bytes"
+          - "network.outgoing.packets"
+      sinks:
+          - network_sink
 sinks:
     - name: meter_sink
       transformers:
       publishers:
-          {%- for publisher_name, publisher in publisher.items() %}
-          {%- if publisher_name == 'default' %}
-          - notifier://
-          {%- endif %}
-          {%- if publisher_name == 'graphite' %}
-          - graphite://{{ publisher.host }}:{{ publisher.port }}
-          {%- endif %}
-          {%- endfor %}
\ No newline at end of file
+          {{ '\n'.join(publisher_lst) }}
+    - name: cpu_sink
+      transformers:
+          - name: "rate_of_change"
+            parameters:
+                target:
+                    name: "cpu_util"
+                    unit: "%"
+                    type: "gauge"
+                    max: 100
+                    scale: "100.0 / (10**9 * (resource_metadata.cpu_number or 1))"
+      publishers:
+          {{ '\n'.join(publisher_lst) }}
+    - name: cpu_delta_sink
+      transformers:
+          - name: "delta"
+            parameters:
+                target:
+                    name: "cpu.delta"
+                growth_only: True
+      publishers:
+          {{ '\n'.join(publisher_lst) }}
+    - 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:
+          {{ '\n'.join(publisher_lst) }}
+    - 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:
+          {{ '\n'.join(publisher_lst) }}
diff --git a/ceilometer/files/pike/polling.yaml b/ceilometer/files/pike/polling.yaml
new file mode 100644
index 0000000..48a51c4
--- /dev/null
+++ b/ceilometer/files/pike/polling.yaml
@@ -0,0 +1,11 @@
+{%- from "ceilometer/map.jinja" import agent with context %}
+---
+sources:
+{%- for source_name, source in agent.polling.sources.items() %}
+    - name: {{ source_name }}
+      interval: {{ source.get('interval', 300) }}
+      meters:
+        {%- for meter in source.meters %}
+        - "{{ meter }}"
+        {%- endfor %}
+{%- endfor %}
diff --git a/ceilometer/server.sls b/ceilometer/server.sls
index a6a6373..8c5a683 100644
--- a/ceilometer/server.sls
+++ b/ceilometer/server.sls
@@ -113,7 +113,7 @@
 
 {%- for publisher_name, publisher in server.get('publisher', {}).items() %}
 
-{%- if publisher_name != "default" %}
+{%- if publisher_name not in ['default', 'gnocchi', 'panko'] %}
 
 ceilometer_publisher_{{ publisher_name }}_pkg:
   pkg.latest:
@@ -121,6 +121,35 @@
 
 {%- endif %}
 
+{%- if publisher_name == 'gnocchi' and publisher.enabled == true %}
+
+ceilometer_gnocchiclient_pkg:
+  pkg.latest:
+    - name: python-gnocchiclient
+
+{%- if publisher.create_resources %}
+
+ceilometer_server_gnocchi_resources:
+  file.managed:
+  - name: /etc/ceilometer/gnocchi_resources.yaml
+  - source: salt://ceilometer/files/{{ server.version }}/gnocchi_resources.yaml
+  - template: jinja
+  - require:
+    - pkg: ceilometer_server_packages
+    - pkg: ceilometer_gnocchiclient_pkg
+
+ceilometer_upgrade:
+  cmd.run:
+    - name: ceilometer-upgrade --skip-metering-database
+    {%- if grains.get('noservices') %}
+    - onlyif: /bin/false
+    {%- endif %}
+    - onchanges:
+      - ceilometer_server_gnocchi_resources
+
+{%- endif %}
+{%- endif %}
+
 {%- endfor %}
 
 /etc/ceilometer/pipeline.yaml:
diff --git a/metadata/service/agent/cluster.yml b/metadata/service/agent/cluster.yml
index c2ec588..2132fe1 100644
--- a/metadata/service/agent/cluster.yml
+++ b/metadata/service/agent/cluster.yml
@@ -15,6 +15,9 @@
       secret: ${_param:ceilometer_secret_key}
       publisher:
         default:
+          enabled: true
+          publish_event: true
+          publish_metric: true
       identity:
         engine: keystone
         host: ${_param:cluster_vip_address}
diff --git a/metadata/service/agent/single.yml b/metadata/service/agent/single.yml
index 63d0312..1f1fca2 100644
--- a/metadata/service/agent/single.yml
+++ b/metadata/service/agent/single.yml
@@ -15,6 +15,9 @@
       secret: ${_param:ceilometer_secret_key}
       publisher:
         default:
+          enabled: true
+          publish_event: true
+          publish_metric: true
       identity:
         engine: keystone
         host: ${_param:cluster_vip_address}
diff --git a/metadata/service/server/cluster.yml b/metadata/service/server/cluster.yml
index 44d1655..33df2b4 100644
--- a/metadata/service/server/cluster.yml
+++ b/metadata/service/server/cluster.yml
@@ -17,6 +17,9 @@
       ttl: 86400
       publisher:
         default:
+          enabled: true
+          publish_event: true
+          publish_metric: true
       bind:
         host: ${_param:cluster_local_address}
         port: 8777
diff --git a/metadata/service/server/publisher/gnocchi.yml b/metadata/service/server/publisher/gnocchi.yml
new file mode 100644
index 0000000..4850143
--- /dev/null
+++ b/metadata/service/server/publisher/gnocchi.yml
@@ -0,0 +1,15 @@
+parameters:
+  _param:
+     ceilometer_create_gnocchi_resources: false
+     ceilometer_gnocchi_filter_project: service
+     ceilometer_gnocchi_archive_policy: medium
+  ceilometer:
+    server:
+      publisher:
+        gnocchi:
+          enabled: true
+          url: gnocchi://
+          publish_metric: true
+          archive_policy: ${_param:ceilometer_gnocchi_archive_policy}
+          filter_project: ${_param:ceilometer_gnocchi_filter_project}
+          create_resources: ${_param:ceilometer_create_gnocchi_resources}
diff --git a/metadata/service/server/publisher/panko.yml b/metadata/service/server/publisher/panko.yml
new file mode 100644
index 0000000..4c9960c
--- /dev/null
+++ b/metadata/service/server/publisher/panko.yml
@@ -0,0 +1,8 @@
+parameters:
+  ceilometer:
+    server:
+      publisher:
+        panko:
+          enabled: true
+          url: panko://
+          publish_event: true
diff --git a/metadata/service/server/single.yml b/metadata/service/server/single.yml
index 05d617b..5c5ddf8 100644
--- a/metadata/service/server/single.yml
+++ b/metadata/service/server/single.yml
@@ -16,6 +16,9 @@
       ttl: 86400
       publisher:
         default:
+          enabled: true
+          publish_event: true
+          publish_metric: true
       bind:
         host: ${_param:single_address}
         port: 8777
diff --git a/tests/pillar/agent_cluster.sls b/tests/pillar/agent_cluster.sls
index 46f3401..75d87ab 100644
--- a/tests/pillar/agent_cluster.sls
+++ b/tests/pillar/agent_cluster.sls
@@ -1,5 +1,16 @@
 ceilometer:
   agent:
+    polling:
+      sources:
+        my_pollsters:
+          meters:
+            - "test_meter1"
+            - "regex_meters*"
+          interval: 30
+        all_pollsters:
+          meters:
+            - "*"
+          interval: 100
     debug: true
     region: RegionOne
     enabled: true
@@ -7,6 +18,7 @@
     secret: password
     publisher:
       default:
+        enabled: true
     identity:
       engine: keystone
       host: 127.0.0.1
diff --git a/tests/pillar/agent_single.sls b/tests/pillar/agent_single.sls
index 4072fd4..300e747 100644
--- a/tests/pillar/agent_single.sls
+++ b/tests/pillar/agent_single.sls
@@ -7,6 +7,7 @@
     secret: password
     publisher:
       default:
+        enabled: true
     identity:
       engine: keystone
       host: 127.0.0.1
diff --git a/tests/pillar/server_cluster.sls b/tests/pillar/server_cluster.sls
index 93f4d02..7a6c50d 100644
--- a/tests/pillar/server_cluster.sls
+++ b/tests/pillar/server_cluster.sls
@@ -9,6 +9,7 @@
     ttl: 86400
     publisher:
       default:
+        enabled: true
     bind:
       host: 127.0.0.1
       port: 8777
diff --git a/tests/pillar/server_gnocchi_cluster.sls b/tests/pillar/server_gnocchi_cluster.sls
new file mode 100644
index 0000000..9cdbc31
--- /dev/null
+++ b/tests/pillar/server_gnocchi_cluster.sls
@@ -0,0 +1,45 @@
+ceilometer:
+  server:
+    debug: true
+    region: RegionOne
+    enabled: true
+    version: pike
+    cluster: true
+    secret: password
+    ttl: 86400
+    publisher:
+      default:
+        enabled: false
+      gnocchi:
+        enabled: true
+        url: gnocchi://
+        publish_metric: true
+        archive_policy: high
+        filter_project: project
+        create_resources: true
+        resources_definition_file: gnocchi_resources.yaml
+        request_timeout: 11.0
+    bind:
+      host: 127.0.0.1
+      port: 8777
+    identity:
+      engine: keystone
+      host: 127.0.0.1
+      port: 35357
+      tenant: service
+      user: ceilometer
+      password: password
+      endpoint_type: internalURL
+    message_queue:
+      engine: rabbitmq
+      members:
+      - host: 127.0.0.1
+      - host: 127.0.0.1
+      - host: 127.0.0.1
+      user: openstack
+      password: password
+      virtual_host: '/openstack'
+      # Workaround for https://bugs.launchpad.net/ceilometer/+bug/1337715
+      rpc_thread_pool_size: 5
+    database:
+      engine: gnocchi
diff --git a/tests/pillar/server_single.sls b/tests/pillar/server_single.sls
index f2fa5c4..26f5653 100644
--- a/tests/pillar/server_single.sls
+++ b/tests/pillar/server_single.sls
@@ -8,6 +8,7 @@
     ttl: 86400
     publisher:
       default:
+        enabled: true
     bind:
       host: 127.0.0.1
       port: 8777