Collect OpenStack notifications
This change enables the LMA collector to receive OpenStack notifications and store them into ElasticSearch. Note that we configure an additional notification topic ('lma_notifications') instead of high-jacking the topic used by Ceilometer ('notifications'). This adds a new checkbox option in the UI to enable/disable the notification collection (default value: disabled). Change-Id: Ie934c244e7cf58f58487ed903aeb94af2e2e0495
This commit is contained in:
parent
23cae82af0
commit
2300b2f8cb
|
@ -0,0 +1,27 @@
|
|||
define heka::input::amqp (
|
||||
$ensure = present,
|
||||
$config_dir,
|
||||
$decoder,
|
||||
$user,
|
||||
$password,
|
||||
$host,
|
||||
$exchange,
|
||||
$exchange_durability = false,
|
||||
$exchange_auto_delete = false,
|
||||
$queue_auto_delete = true,
|
||||
$exchange_type = "topic",
|
||||
$queue,
|
||||
$routing_key = "*",
|
||||
) {
|
||||
|
||||
include heka::params
|
||||
|
||||
file { "${config_dir}/amqp-${title}.toml":
|
||||
ensure => $ensure,
|
||||
content => template('heka/input/amqp.toml.erb'),
|
||||
mode => '0600',
|
||||
owner => $heka::params::user,
|
||||
group => $heka::params::user,
|
||||
require => File[$config_dir],
|
||||
}
|
||||
}
|
|
@ -5,6 +5,6 @@ filename = "<%= @filename %>"
|
|||
<% if @config.size() > 0 %>
|
||||
[<%= @title %>_decoder.config]
|
||||
<% @config.each do |k,v| %>
|
||||
<%= k %> = '<%= v %>'
|
||||
<%= k %> = <%= v.is_a?(String) ? "'#{v}'" : v %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
[<%= @title %>_amqp]
|
||||
type = "AMQPInput"
|
||||
url = "amqp://<%= @user %>:<%= @password %>@<%= @host %>/"
|
||||
exchange = "<%= @exchange %>"
|
||||
exchange_type = "<%= @exchange_type %>"
|
||||
exchange_durability = <%= @exchange_durability %>
|
||||
exchange_auto_delete = <%= @exchange_auto_delete %>
|
||||
queue_auto_delete = <%= @queue_auto_delete %>
|
||||
queue = "<%= @queue %>"
|
||||
routing_key = "<%= @routing_key %>"
|
||||
decoder = "<%= @decoder %>_decoder"
|
||||
splitter = "NullSplitter"
|
|
@ -24,6 +24,30 @@ local msg = {
|
|||
Fields = nil
|
||||
}
|
||||
|
||||
-- Mapping table from event_type prefixes to notification loggers
|
||||
local logger_map = {
|
||||
--cinder
|
||||
volume = 'cinder',
|
||||
-- glance
|
||||
image = 'glance',
|
||||
-- heat
|
||||
orchestration = 'heat',
|
||||
-- keystone
|
||||
identity = 'keystone',
|
||||
-- nova
|
||||
compute = 'nova',
|
||||
scheduler = 'nova',
|
||||
keypair = 'nova',
|
||||
-- neutron
|
||||
floatingip = 'neutron',
|
||||
security_group = 'neutron',
|
||||
security_group_rule = 'neutron',
|
||||
network = 'neutron',
|
||||
port = 'neutron',
|
||||
router = 'neutron',
|
||||
subnet = 'neutron',
|
||||
}
|
||||
|
||||
-- Mapping table between the attributes in the notification's payload and the
|
||||
-- fields in the Heka message
|
||||
local payload_fields = {
|
||||
|
@ -78,7 +102,6 @@ local transform_functions = {
|
|||
volume_id = normalize_uuid,
|
||||
}
|
||||
|
||||
local service = read_config("service") or error("'service' configuration must be specified")
|
||||
local include_full_notification = read_config("include_full_notification") or false
|
||||
|
||||
function process_message ()
|
||||
|
@ -95,7 +118,7 @@ function process_message ()
|
|||
end
|
||||
|
||||
msg.Fields = {}
|
||||
msg.Logger = service
|
||||
msg.Logger = logger_map[string.match(notif.event_type, '([^.]+)')]
|
||||
msg.Severity = utils.label_to_severity_map[notif.priority]
|
||||
msg.Timestamp = patt.Timestamp:match(notif.timestamp)
|
||||
msg.Fields.publisher, msg.Hostname = string.match(notif.publisher_id, '([^.]+)%.([%w_-]+)')
|
||||
|
|
|
@ -17,7 +17,7 @@ class lma_collector::elasticsearch (
|
|||
config_dir => $lma_collector::params::config_dir,
|
||||
server => $server,
|
||||
port => $port,
|
||||
message_matcher => "Type == 'log'",
|
||||
message_matcher => "Type == 'log' || Type == 'notification'",
|
||||
require => Heka::Encoder::Es_json['elasticsearch'],
|
||||
notify => Service[$lma_collector::params::service_name],
|
||||
}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
class lma_collector::notifications::cinder (
|
||||
$topics = [],
|
||||
$driver = $lma_collector::params::notification_driver,
|
||||
) inherits lma_collector::params {
|
||||
|
||||
validate_array($topics)
|
||||
|
||||
include cinder::params
|
||||
|
||||
cinder_config {
|
||||
'DEFAULT/notification_topics': value => join($topics, ','),
|
||||
notify => Service[$::cinder::params::volume_service],
|
||||
}
|
||||
cinder_config {
|
||||
'DEFAULT/notification_driver': value => $driver,
|
||||
notify => Service[$::cinder::params::volume_service],
|
||||
}
|
||||
|
||||
service { $::cinder::params::volume_service:
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
class lma_collector::notifications::compute (
|
||||
$topics = [],
|
||||
$driver = $lma_collector::params::notification_driver,
|
||||
) inherits lma_collector::params {
|
||||
validate_array($topics)
|
||||
|
||||
include nova::params
|
||||
|
||||
nova_config {
|
||||
'DEFAULT/notification_topics': value => join($topics, ','),
|
||||
notify => Service[$::nova::params::compute_service_name],
|
||||
}
|
||||
nova_config {
|
||||
'DEFAULT/notification_driver': value => $driver,
|
||||
notify => Service[$::nova::params::compute_service_name],
|
||||
}
|
||||
|
||||
service { $::nova::params::compute_service_name:
|
||||
}
|
||||
}
|
|
@ -0,0 +1,182 @@
|
|||
class lma_collector::notifications::controller (
|
||||
$host = $lma_collector::params::rabbitmq_host,
|
||||
$user = $lma_collector::params::rabbitmq_user,
|
||||
$password = $lma_collector::params::rabbitmq_password,
|
||||
$driver = $lma_collector::params::notification_driver,
|
||||
$topics = [],
|
||||
) inherits lma_collector::params {
|
||||
|
||||
validate_array($topics)
|
||||
$notification_topics = join($topics, ',')
|
||||
|
||||
# We need to pick one exchange and we settled on 'nova'. The default
|
||||
# exchange ("") doesn't work because Heka would fail to create the queue in
|
||||
# case it doesn't exist yet.
|
||||
$exchange = 'nova'
|
||||
|
||||
heka::decoder::sandbox { 'notification':
|
||||
config_dir => $lma_collector::params::config_dir,
|
||||
filename => "${lma_collector::plugins_dir}/decoders/notification.lua" ,
|
||||
config => {
|
||||
include_full_notification => false
|
||||
},
|
||||
notify => Service[$lma_collector::params::service_name],
|
||||
}
|
||||
|
||||
heka::input::amqp { 'openstack_info':
|
||||
config_dir => $lma_collector::params::config_dir,
|
||||
decoder => 'notification',
|
||||
user => $user,
|
||||
password => $password,
|
||||
host => $host,
|
||||
exchange => $exchange,
|
||||
exchange_durability => false,
|
||||
exchange_auto_delete => false,
|
||||
queue_auto_delete => false,
|
||||
exchange_type => "topic",
|
||||
queue => "${lma_collector::params::lma_topic}.info",
|
||||
routing_key => "${lma_collector::params::lma_topic}.info",
|
||||
notify => Service[$lma_collector::params::service_name],
|
||||
}
|
||||
|
||||
heka::input::amqp { 'openstack_error':
|
||||
config_dir => $lma_collector::params::config_dir,
|
||||
decoder => 'notification',
|
||||
user => $user,
|
||||
password => $password,
|
||||
host => $host,
|
||||
exchange => $exchange,
|
||||
exchange_durability => false,
|
||||
exchange_auto_delete => false,
|
||||
queue_auto_delete => false,
|
||||
exchange_type => "topic",
|
||||
queue => "${lma_collector::params::lma_topic}.error",
|
||||
routing_key => "${lma_collector::params::lma_topic}.error",
|
||||
notify => Service[$lma_collector::params::service_name],
|
||||
}
|
||||
|
||||
heka::input::amqp { 'openstack_warn':
|
||||
config_dir => $lma_collector::params::config_dir,
|
||||
decoder => 'notification',
|
||||
user => $user,
|
||||
password => $password,
|
||||
host => $host,
|
||||
exchange => $exchange,
|
||||
exchange_durability => false,
|
||||
exchange_auto_delete => false,
|
||||
queue_auto_delete => false,
|
||||
exchange_type => "topic",
|
||||
queue => "${lma_collector::params::lma_topic}.warn",
|
||||
routing_key => "${lma_collector::params::lma_topic}.warn",
|
||||
notify => Service[$lma_collector::params::service_name],
|
||||
}
|
||||
|
||||
# Nova
|
||||
include nova::params
|
||||
|
||||
nova_config {
|
||||
'DEFAULT/notification_topics': value => $notification_topics,
|
||||
notify => Service[$::nova::params::api_service_name, $::nova::params::conductor_service_name, $::nova::params::scheduler_service_name],
|
||||
}
|
||||
nova_config {
|
||||
'DEFAULT/notification_driver': value => $driver,
|
||||
notify => Service[$::nova::params::api_service_name, $::nova::params::conductor_service_name, $::nova::params::scheduler_service_name],
|
||||
}
|
||||
|
||||
service { [$::nova::params::api_service_name, $::nova::params::conductor_service_name, $::nova::params::scheduler_service_name]:
|
||||
}
|
||||
|
||||
# Cinder
|
||||
include cinder::params
|
||||
|
||||
cinder_config {
|
||||
'DEFAULT/notification_topics': value => $notification_topics,
|
||||
notify => Service[$::cinder::params::api_service, $::cinder::params::scheduler_service],
|
||||
}
|
||||
cinder_config {
|
||||
'DEFAULT/notification_driver': value => $driver,
|
||||
notify => Service[$::cinder::params::api_service, $::cinder::params::scheduler_service],
|
||||
}
|
||||
|
||||
service { [$::cinder::params::api_service, $::cinder::params::scheduler_service]:
|
||||
}
|
||||
|
||||
# Keystone
|
||||
include keystone::params
|
||||
|
||||
keystone_config {
|
||||
'DEFAULT/notification_topics': value => $notification_topics,
|
||||
notify => Service[$::keystone::params::service_name],
|
||||
}
|
||||
keystone_config {
|
||||
'DEFAULT/notification_driver': value => $driver,
|
||||
notify => Service[$::keystone::params::service_name],
|
||||
}
|
||||
|
||||
service { $::keystone::params::service_name:
|
||||
}
|
||||
|
||||
# Neutron
|
||||
include neutron::params
|
||||
|
||||
neutron_config {
|
||||
'DEFAULT/notification_topics': value => $notification_topics,
|
||||
notify => Service[$::neutron::params::server_service],
|
||||
}
|
||||
neutron_config {
|
||||
'DEFAULT/notification_driver': value => $driver,
|
||||
notify => Service[$::neutron::params::server_service],
|
||||
}
|
||||
|
||||
service { $::neutron::params::server_service:
|
||||
}
|
||||
|
||||
# Glance
|
||||
include glance::params
|
||||
|
||||
# Default value is 'image.localhost' for Glance
|
||||
$glance_publisher_id = "image.${::hostname}"
|
||||
|
||||
glance_api_config {
|
||||
'DEFAULT/notification_topics': value => $notification_topics,
|
||||
notify => Service[$::glance::params::api_service_name],
|
||||
}
|
||||
glance_api_config {
|
||||
'DEFAULT/notification_driver': value => $driver,
|
||||
notify => Service[$::glance::params::api_service_name],
|
||||
}
|
||||
glance_api_config {
|
||||
'DEFAULT/default_publisher_id': value => $glance_publisher_id,
|
||||
notify => Service[$::glance::params::api_service_name],
|
||||
}
|
||||
glance_registry_config {
|
||||
'DEFAULT/notification_topics': value => $notification_topics,
|
||||
notify => Service[$::glance::params::registry_service_name],
|
||||
}
|
||||
glance_registry_config {
|
||||
'DEFAULT/notification_driver': value => $driver,
|
||||
notify => Service[$::glance::params::registry_service_name],
|
||||
}
|
||||
glance_registry_config {
|
||||
'DEFAULT/default_publisher_id': value => $glance_publisher_id,
|
||||
notify => Service[$::glance::params::registry_service_name],
|
||||
}
|
||||
|
||||
service { [$::glance::params::api_service_name, $::glance::params::registry_service_name]:
|
||||
}
|
||||
|
||||
# Heat
|
||||
include heat::params
|
||||
|
||||
heat_config {
|
||||
'DEFAULT/notification_topics': value => $notification_topics,
|
||||
notify => Service[$::heat::params::api_service_name, $::heat::params::engine_service_name],
|
||||
}
|
||||
heat_config {
|
||||
'DEFAULT/notification_driver': value => $driver,
|
||||
notify => Service[$::heat::params::api_service_name, $::heat::params::engine_service_name],
|
||||
}
|
||||
|
||||
service { [$::heat::params::api_service_name, $::heat::params::engine_service_name]:
|
||||
}
|
||||
}
|
|
@ -25,6 +25,10 @@ class lma_collector::params {
|
|||
$rabbitmq_host = false
|
||||
$rabbitmq_user = ''
|
||||
$rabbitmq_password = ''
|
||||
$rabbitmq_exchange = ''
|
||||
$lma_topic = 'lma_notifications'
|
||||
$openstack_topic = 'notifications'
|
||||
$notification_driver = 'messaging'
|
||||
|
||||
$elasticsearch_server = false
|
||||
$elasticsearch_port = '9200'
|
||||
|
|
|
@ -1,28 +1,19 @@
|
|||
# TODO(spasquier): replace by Hiera when testing with 6.1
|
||||
$fuel_settings = parseyaml(file('/etc/astute.yaml'))
|
||||
|
||||
$deployment_mode = $fuel_settings['deployment_mode']
|
||||
if $deployment_mode == 'multinode' {
|
||||
$controller_role = 'controller'
|
||||
}
|
||||
elsif $deployment_mode =~ /^ha/ {
|
||||
$controller_role = 'primary-controller'
|
||||
}
|
||||
else {
|
||||
fail("'${deployment_mode} is not a supported deployment mode")
|
||||
}
|
||||
# TODO(spasquier): fail if Neutron isn't used
|
||||
|
||||
# TODO: verify that we're running Neutron
|
||||
include lma_collector::params
|
||||
|
||||
$deployment_mode = $fuel_settings['deployment_mode']
|
||||
|
||||
$roles = node_roles($fuel_settings['nodes'], $fuel_settings['uid'])
|
||||
$is_primary_controller = member($roles, $controller_role)
|
||||
$is_controller = member($roles, 'controller')
|
||||
|
||||
if $fuel_settings['rabbit']['user'] {
|
||||
$rabbitmq_user = $fuel_settings['rabbit']['user']
|
||||
}
|
||||
else {
|
||||
$rabbitmq_user = 'nova'
|
||||
}
|
||||
$roles_map = {}
|
||||
$roles_map['primary-controller'] = member($roles, 'primary-controller')
|
||||
$roles_map['controller'] = member($roles, 'controller')
|
||||
$roles_map['compute'] = member($roles, 'compute')
|
||||
$roles_map['cinder'] = member($roles, 'cinder')
|
||||
$roles_map['ceph-osd'] = member($roles, 'ceph-osd')
|
||||
|
||||
$tags = {
|
||||
deployment_id => $fuel_settings['deployment_id'],
|
||||
|
@ -40,32 +31,69 @@ else {
|
|||
$additional_tags = {}
|
||||
}
|
||||
|
||||
class lma_common {
|
||||
class { 'lma_collector':
|
||||
tags => merge($tags, $additional_tags)
|
||||
}
|
||||
|
||||
class { 'lma_collector::logs::system': }
|
||||
|
||||
class { 'lma_collector::logs::openstack': }
|
||||
|
||||
class { 'lma_collector::logs::monitor': }
|
||||
$enable_notifications = $fuel_settings['lma_collector']['enable_notifications']
|
||||
if $fuel_settings['ceilometer']['enabled'] {
|
||||
$notification_topics = [$lma_collector::params::openstack_topic, $lma_collector::params::lma_topic]
|
||||
}
|
||||
else {
|
||||
$notification_topics = [$lma_collector::params::lma_topic]
|
||||
}
|
||||
|
||||
class lma_controller {
|
||||
# Resources shared by all roles
|
||||
class { 'lma_collector':
|
||||
tags => merge($tags, $additional_tags)
|
||||
}
|
||||
|
||||
class { 'lma_collector::logs::system': }
|
||||
|
||||
class { 'lma_collector::logs::openstack': }
|
||||
|
||||
class { 'lma_collector::logs::monitor': }
|
||||
|
||||
# Controller
|
||||
if ($roles_map['primary-controller'] or $roles_map['controller']) {
|
||||
# Logs
|
||||
class { 'lma_collector::logs::mysql': }
|
||||
|
||||
class { 'lma_collector::logs::rabbitmq': }
|
||||
|
||||
class { 'lma_collector::logs::pacemaker': }
|
||||
if $deployment_mode =~ /^ha/ {
|
||||
class { 'lma_collector::logs::pacemaker': }
|
||||
}
|
||||
|
||||
# Notifications
|
||||
if $fuel_settings['rabbit']['user'] {
|
||||
$rabbitmq_user = $fuel_settings['rabbit']['user']
|
||||
}
|
||||
else {
|
||||
$rabbitmq_user = 'nova'
|
||||
}
|
||||
|
||||
if $enable_notifications {
|
||||
class { 'lma_collector::notifications::controller':
|
||||
host => $fuel_settings['management_vip'],
|
||||
user => $rabbitmq_user,
|
||||
password => $fuel_settings['rabbit']['password'],
|
||||
topics => $notification_topics,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class { 'lma_common': }
|
||||
|
||||
if ($is_primary_controller or $is_controller) {
|
||||
class { 'lma_controller': }
|
||||
# Compute
|
||||
if $roles_map['compute'] and $enable_notifications {
|
||||
class { 'lma_collector::notifications::compute':
|
||||
topics => $notification_topics,
|
||||
}
|
||||
}
|
||||
|
||||
# Cinder
|
||||
if $roles_map['cinder'] and $enable_notifications {
|
||||
class { 'lma_collector::notifications::cinder':
|
||||
topics => $notification_topics,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$elasticsearch_mode = $fuel_settings['lma_collector']['elasticsearch_mode']
|
||||
case $elasticsearch_mode {
|
||||
'remote': {
|
||||
|
|
|
@ -44,3 +44,9 @@ attributes:
|
|||
regex:
|
||||
source: '^[a-zA-Z\d][a-zA-Z\d_\-.]+$'
|
||||
error: "Invalid address or name"
|
||||
|
||||
enable_notifications:
|
||||
type: "checkbox"
|
||||
weight: 50
|
||||
value: false
|
||||
label: "Collect OpenStack notifications"
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
#!/bin/bash
|
||||
set -eux
|
||||
shopt -s extglob
|
||||
|
||||
ROOT="$(dirname `readlink -f $0`)"
|
||||
MODULES="${ROOT}"/deployment_scripts/puppet/modules
|
||||
MODULES_DIR="${ROOT}"/deployment_scripts/puppet/modules
|
||||
MODULES='@(stdlib|openstack|inifile|glance|nova|heat|neutron|keystone|cinder)'
|
||||
RPM_REPO="${ROOT}"/repositories/centos/
|
||||
DEB_REPO="${ROOT}"/repositories/ubuntu/
|
||||
HEKA_VERSION="0.9.0"
|
||||
|
@ -11,12 +13,12 @@ FUEL_LIB_SHA1="b977b77b7e1fca1f38e701373601e9fe3430eaee"
|
|||
FUEL_LIB_TARBALL_URL="https://github.com/stackforge/fuel-library/tarball/${FUEL_LIB_SHA1}"
|
||||
|
||||
# Clean-up first
|
||||
rm -rf ${MODULES}/{stdlib,openstack}/
|
||||
rm -rf ${MODULES_DIR}/{cinder,glance,heat,inifile,keystone,neutron,nova,openstack,stdlib}
|
||||
|
||||
wget -qO - https://github.com/mozilla-services/heka/releases/download/v${HEKA_VERSION}/heka_${HEKA_VERSION}_amd64.deb > ${DEB_REPO}/heka_${HEKA_VERSION}_amd64.deb
|
||||
wget -qO - https://github.com/mozilla-services/heka/releases/download/v${HEKA_VERSION}/heka-${HEKA_VERSION//./_}-linux-amd64.rpm > ${RPM_REPO}/heka-${HEKA_VERSION//./_}-linux-amd64.rpm
|
||||
|
||||
# Include dependent manifests from fuel-library
|
||||
wget -qO- "${FUEL_LIB_TARBALL_URL}" | \
|
||||
tar -C "${MODULES}" --strip-components=3 -zxvf - \
|
||||
stackforge-fuel-library-${FUEL_LIB_SHA1:0:7}/deployment/puppet/{stdlib,keystone,openstack}
|
||||
tar -C "${MODULES_DIR}" --strip-components=3 -zxvf - \
|
||||
stackforge-fuel-library-${FUEL_LIB_SHA1:0:7}/deployment/puppet/{cinder,glance,heat,inifile,keystone,neutron,nova,openstack,stdlib}
|
||||
|
|
Loading…
Reference in New Issue