Use OpenStack API to collect the status of Neutron agents
This change uses the Neutron API to get the status of the Neutron agents instead of querying the MySQL database. Change-Id: I60fa2386a887e9dac2fe4f1234d225ad6402bf2d Partial-Bug: #1546188
This commit is contained in:
parent
e60e187f32
commit
bcdedbf1aa
|
@ -364,16 +364,6 @@ if $influxdb_mode != 'disabled' {
|
|||
password => $nova['db_password'],
|
||||
}
|
||||
|
||||
unless $contrail {
|
||||
lma_collector::collectd::dbi_services { 'neutron':
|
||||
username => 'neutron',
|
||||
dbname => 'neutron',
|
||||
password => $neutron['database']['passwd'],
|
||||
report_interval => 15,
|
||||
downtime_factor => 4,
|
||||
}
|
||||
}
|
||||
|
||||
class { 'lma_collector::collectd::haproxy':
|
||||
socket => $haproxy_socket,
|
||||
# Ignore internal stats ('Stats' for 6.1, 'stats' for 7.0) and lma proxies
|
||||
|
|
|
@ -191,26 +191,40 @@ class CollectdPlugin(base.Base):
|
|||
|
||||
where 'state' can be 'up', 'down' or 'disabled'
|
||||
"""
|
||||
ost_services_r = self.get(service, 'os-services')
|
||||
|
||||
if service == 'neutron':
|
||||
endpoint = 'v2.0/agents'
|
||||
entry = 'agents'
|
||||
else:
|
||||
endpoint = 'os-services'
|
||||
entry = 'services'
|
||||
|
||||
ost_services_r = self.get(service, endpoint)
|
||||
r_status = ost_services_r.status_code
|
||||
try:
|
||||
r_json = ost_services_r.json()
|
||||
except ValueError:
|
||||
r_json = {}
|
||||
|
||||
if r_status == 200 and 'services' in r_json:
|
||||
for val in r_json['services']:
|
||||
if r_status == 200 and entry in r_json:
|
||||
for val in r_json[entry]:
|
||||
data = {'host': val['host'], 'service': val['binary']}
|
||||
|
||||
if val['status'] == 'disabled':
|
||||
data['state'] = 'disabled'
|
||||
elif val['state'] == 'up' or val['state'] == 'down':
|
||||
data['state'] = val['state']
|
||||
if service == 'neutron':
|
||||
if not val['admin_state_up']:
|
||||
data['state'] = 'disabled'
|
||||
else:
|
||||
data['state'] = 'up' if val['alive'] else 'down'
|
||||
else:
|
||||
msg = "Unknown state for {} workers:{}".format(
|
||||
service, val['state'])
|
||||
self.logger.warning(msg)
|
||||
continue
|
||||
if val['status'] == 'disabled':
|
||||
data['state'] = 'disabled'
|
||||
elif val['state'] == 'up' or val['state'] == 'down':
|
||||
data['state'] = val['state']
|
||||
else:
|
||||
msg = "Unknown state for {} workers:{}".format(
|
||||
service, val['state'])
|
||||
self.logger.warning(msg)
|
||||
continue
|
||||
|
||||
yield data
|
||||
else:
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
#
|
||||
# Collectd plugin for getting resource statistics from Neutron
|
||||
import collectd
|
||||
from collections import Counter
|
||||
from collections import defaultdict
|
||||
import re
|
||||
|
||||
import base
|
||||
import collectd_openstack as openstack
|
||||
|
@ -26,6 +29,7 @@ INTERVAL = openstack.INTERVAL
|
|||
class NeutronStatsPlugin(openstack.CollectdPlugin):
|
||||
""" Class to report the statistics on Neutron service.
|
||||
|
||||
state of agents
|
||||
number of networks broken down by status
|
||||
number of subnets
|
||||
number of ports broken down by owner and status
|
||||
|
@ -33,8 +37,13 @@ class NeutronStatsPlugin(openstack.CollectdPlugin):
|
|||
number of floating IP addresses broken down by free/associated
|
||||
"""
|
||||
|
||||
neutron_re = re.compile('^neutron-')
|
||||
agent_re = re.compile('-agent$')
|
||||
states = {'up': 0, 'down': 1, 'disabled': 2}
|
||||
|
||||
@base.read_callback_wrapper
|
||||
def read_callback(self):
|
||||
|
||||
def groupby_network(x):
|
||||
return "networks.%s" % x.get('status', 'unknown').lower()
|
||||
|
||||
|
@ -60,6 +69,29 @@ class NeutronStatsPlugin(openstack.CollectdPlugin):
|
|||
status = 'free'
|
||||
return "floatingips.%s" % status
|
||||
|
||||
# Get information of the state per agent
|
||||
# State can be up or down
|
||||
aggregated_agents = defaultdict(Counter)
|
||||
|
||||
for agent in self.iter_workers('neutron'):
|
||||
host = agent['host'].split('.')[0]
|
||||
service = self.agent_re.sub(
|
||||
'', self.neutron_re.sub('', agent['service']))
|
||||
state = agent['state']
|
||||
|
||||
aggregated_agents[service][state] += 1
|
||||
self.dispatch_value('neutron_agent',
|
||||
self.states[state],
|
||||
{'host': host,
|
||||
'service': service,
|
||||
'state': state})
|
||||
|
||||
for service in aggregated_agents:
|
||||
for state in self.states:
|
||||
self.dispatch_value('neutron_agents',
|
||||
aggregated_agents[service][state],
|
||||
{'service': service, 'state': state})
|
||||
|
||||
# Networks
|
||||
networks = self.get_objects('neutron', 'networks', api_version='v2.0')
|
||||
status = self.count_objects_group_by(networks,
|
||||
|
@ -97,14 +129,14 @@ class NeutronStatsPlugin(openstack.CollectdPlugin):
|
|||
self.dispatch_value(s, nb)
|
||||
self.dispatch_value('floatingips', len(floatingips))
|
||||
|
||||
def dispatch_value(self, name, value):
|
||||
def dispatch_value(self, name, value, meta=None):
|
||||
v = collectd.Values(
|
||||
plugin=PLUGIN_NAME, # metric source
|
||||
type='gauge',
|
||||
type_instance=name,
|
||||
interval=INTERVAL,
|
||||
# w/a for https://github.com/collectd/collectd/issues/716
|
||||
meta={'0': True},
|
||||
meta=meta or {'0': True},
|
||||
values=[value]
|
||||
)
|
||||
v.dispatch()
|
||||
|
|
|
@ -39,19 +39,6 @@ function replace_dot_by_sep (str)
|
|||
return string.gsub(str, '%.', sep)
|
||||
end
|
||||
|
||||
function split_service_and_state_and_hostname(str)
|
||||
-- Possible values:
|
||||
-- services.compute.down.node-1.test.domain.local
|
||||
-- services.scheduler.up
|
||||
-- agents.dhcp.down.node-44
|
||||
-- agents.dhcp.up
|
||||
-- services.scheduler.disabled.rbd:volumes
|
||||
local service, state, hostname = string.match(str, '^%w+%.([%w-]+)%.([%w-]+)%.?(.-)$')
|
||||
-- remove domain part of the hostname or nil if string is empty
|
||||
hostname = string.match(hostname, '^([^.]+)')
|
||||
return replace_dot_by_sep(service), state, hostname
|
||||
end
|
||||
|
||||
function process_message ()
|
||||
local ok, samples = pcall(cjson.decode, read_message("Payload"))
|
||||
if not ok then
|
||||
|
@ -266,6 +253,15 @@ function process_message ()
|
|||
skip_it = true
|
||||
elseif sample['type_instance'] == 'subnets' then
|
||||
msg['Fields']['name'] = 'openstack' .. sep .. 'neutron' .. sep .. 'subnets'
|
||||
elseif sample['type_instance'] == 'neutron_agents' or
|
||||
sample['type_instance'] == 'neutron_agent' then
|
||||
msg['Fields']['name'] = 'openstack_' .. sample['type_instance']
|
||||
msg['Fields']['tag_fields'] = { 'service', 'state' }
|
||||
msg['Fields']['service'] = sample['meta']['service']
|
||||
msg['Fields']['state'] = sample['meta']['state']
|
||||
if sample['type_instance'] == 'neutron_agent' then
|
||||
msg['Fields']['hostname'] = sample['meta']['host']
|
||||
end
|
||||
elseif string.match(sample['type_instance'], '^ports') then
|
||||
local resource, owner, state = string.match(sample['type_instance'], '^([^.]+)%.([^.]+)%.(.+)$')
|
||||
msg['Fields']['name'] = 'openstack' .. sep .. 'neutron' .. sep .. replace_dot_by_sep(resource)
|
||||
|
@ -331,17 +327,6 @@ function process_message ()
|
|||
msg['Fields'][additional_tag] = sample['type_instance']
|
||||
end
|
||||
end
|
||||
elseif metric_source == 'dbi' and sample['plugin_instance'] == 'agents_neutron' then
|
||||
local service, state, hostname = split_service_and_state_and_hostname(sample['type_instance'])
|
||||
if hostname then
|
||||
msg['Fields']['name'] = 'openstack' .. sep .. 'neutron' .. sep .. 'agent'
|
||||
msg['Fields']['hostname'] = hostname
|
||||
else
|
||||
msg['Fields']['name'] = 'openstack' .. sep .. 'neutron' .. sep .. 'agents'
|
||||
end
|
||||
msg['Fields']['tag_fields'] = { 'service', 'state' }
|
||||
msg['Fields']['service'] = service
|
||||
msg['Fields']['state'] = state
|
||||
elseif metric_source == 'pacemaker_resource' then
|
||||
msg['Fields']['name'] = 'pacemaker_local_resource_active'
|
||||
msg['Fields']['tag_fields'] = { 'resource' }
|
||||
|
|
Loading…
Reference in New Issue