Fixing flake8 errors now that tox is working again
Change-Id: Id34991711c57f20922f003928008143032723af3
This commit is contained in:
parent
d108a0f4ab
commit
1ded0b7b1c
|
@ -143,7 +143,7 @@ class Check(util.Dimensions):
|
||||||
[(timestamp, value, hostname, device_name)]
|
[(timestamp, value, hostname, device_name)]
|
||||||
else:
|
else:
|
||||||
raise exceptions.CheckException("%s must be either gauge or counter, skipping sample at %s" %
|
raise exceptions.CheckException("%s must be either gauge or counter, skipping sample at %s" %
|
||||||
(metric, time.ctime(timestamp)))
|
(metric, time.ctime(timestamp)))
|
||||||
|
|
||||||
if self.is_gauge(metric):
|
if self.is_gauge(metric):
|
||||||
# store[metric][dimensions] = (ts, val) - only 1 value allowed
|
# store[metric][dimensions] = (ts, val) - only 1 value allowed
|
||||||
|
@ -636,32 +636,3 @@ class AgentCheck(util.Dimensions):
|
||||||
return val
|
return val
|
||||||
else:
|
else:
|
||||||
return cast(val)
|
return cast(val)
|
||||||
|
|
||||||
|
|
||||||
def run_check(name, path=None):
|
|
||||||
import tests.common
|
|
||||||
|
|
||||||
# Read the config file
|
|
||||||
config = Config()
|
|
||||||
confd_path = path or os.path.join(config.get_confd_path(),
|
|
||||||
'{0}.yaml'.format(name))
|
|
||||||
|
|
||||||
try:
|
|
||||||
f = open(confd_path)
|
|
||||||
except IOError:
|
|
||||||
raise Exception('Unable to open configuration at %s' % confd_path)
|
|
||||||
|
|
||||||
config_str = f.read()
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
# Run the check
|
|
||||||
check, instances = tests.common.get_check(name, config_str)
|
|
||||||
if not instances:
|
|
||||||
raise Exception('YAML configuration returned no instances.')
|
|
||||||
for instance in instances:
|
|
||||||
check.check(instance)
|
|
||||||
if check.has_events():
|
|
||||||
print("Events:\n")
|
|
||||||
pprint.pprint(check.get_events(), indent=4)
|
|
||||||
print("Metrics:\n")
|
|
||||||
pprint.pprint(check.get_metrics(), indent=4)
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
# Core modules
|
# Core modules
|
||||||
import logging
|
import logging
|
||||||
import socket
|
import socket
|
||||||
import system.win32 as w32
|
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import monasca_agent.common.check_status as check_status
|
import monasca_agent.common.check_status as check_status
|
||||||
import monasca_agent.common.metrics as metrics
|
import monasca_agent.common.metrics as metrics
|
||||||
import monasca_agent.common.util as util
|
import monasca_agent.common.util as util
|
||||||
|
import system.win32 as w32
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
|
@ -74,8 +74,7 @@ class PoolWorker(threading.Thread):
|
||||||
|
|
||||||
class Pool(object):
|
class Pool(object):
|
||||||
|
|
||||||
"""
|
"""The Pool class represents a pool of worker threads.
|
||||||
The Pool class represents a pool of worker threads.
|
|
||||||
|
|
||||||
It has methods which allows tasks to be offloaded to the
|
It has methods which allows tasks to be offloaded to the
|
||||||
worker processes in a few different ways.
|
worker processes in a few different ways.
|
||||||
|
|
|
@ -170,6 +170,7 @@ class ServicesCheck(monasca_agent.collector.checks.AgentCheck):
|
||||||
|
|
||||||
def _check(self, instance):
|
def _check(self, instance):
|
||||||
"""This function should be implemented by inherited classes.
|
"""This function should be implemented by inherited classes.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
|
|
|
@ -5,16 +5,20 @@ import urllib2
|
||||||
import urlparse
|
import urlparse
|
||||||
|
|
||||||
# project
|
# project
|
||||||
import monasca_agent.common.util as util
|
|
||||||
import monasca_agent.collector.checks as checks
|
import monasca_agent.collector.checks as checks
|
||||||
|
import monasca_agent.collector.checks.services_checks as services_checks
|
||||||
import monasca_agent.collector.checks.utils as utils
|
import monasca_agent.collector.checks.utils as utils
|
||||||
|
import monasca_agent.common.util as util
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Apache(checks.AgentCheck):
|
class Apache(checks.AgentCheck):
|
||||||
"""Tracks basic connection/requests/workers metrics
|
"""Tracks basic connection/requests/workers metrics
|
||||||
|
|
||||||
See http://httpd.apache.org/docs/2.2/mod/mod_status.html for more details
|
See http://httpd.apache.org/docs/2.2/mod/mod_status.html for more details
|
||||||
"""
|
"""
|
||||||
|
|
||||||
GAUGES = {'IdleWorkers': 'apache.performance.idle_worker_count',
|
GAUGES = {'IdleWorkers': 'apache.performance.idle_worker_count',
|
||||||
'BusyWorkers': 'apache.performance.busy_worker_count',
|
'BusyWorkers': 'apache.performance.busy_worker_count',
|
||||||
'CPULoad': 'apache.performance.cpu_load_perc',
|
'CPULoad': 'apache.performance.cpu_load_perc',
|
||||||
|
@ -54,9 +58,9 @@ class Apache(checks.AgentCheck):
|
||||||
apache_host = socket.gethostname()
|
apache_host = socket.gethostname()
|
||||||
|
|
||||||
dimensions = self._set_dimensions({'apache_host': apache_host,
|
dimensions = self._set_dimensions({'apache_host': apache_host,
|
||||||
'apache_port': apache_port,
|
'apache_port': apache_port,
|
||||||
'service': 'apache',
|
'service': 'apache',
|
||||||
'component': 'apache'},
|
'component': 'apache'},
|
||||||
instance)
|
instance)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -77,7 +81,7 @@ class Apache(checks.AgentCheck):
|
||||||
# Loop through and extract the numerical values
|
# Loop through and extract the numerical values
|
||||||
for line in response.split('\n'):
|
for line in response.split('\n'):
|
||||||
values = line.split(': ')
|
values = line.split(': ')
|
||||||
if len(values) == 2: # match
|
if len(values) == 2: # match
|
||||||
metric, value = values
|
metric, value = values
|
||||||
try:
|
try:
|
||||||
value = float(value)
|
value = float(value)
|
||||||
|
|
|
@ -32,7 +32,6 @@ class CheckMK(AgentCheck):
|
||||||
def __init__(self, name, init_config, agent_config, instances=None):
|
def __init__(self, name, init_config, agent_config, instances=None):
|
||||||
AgentCheck.__init__(self, name, init_config, agent_config, instances)
|
AgentCheck.__init__(self, name, init_config, agent_config, instances)
|
||||||
|
|
||||||
|
|
||||||
def check(self, instance):
|
def check(self, instance):
|
||||||
"""Run check_mk_agent and process the '<<<local>>>' results.
|
"""Run check_mk_agent and process the '<<<local>>>' results.
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import json
|
import json
|
||||||
import urllib2
|
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
import urllib2
|
||||||
|
|
||||||
from monasca_agent.collector.checks import AgentCheck
|
from monasca_agent.collector.checks import AgentCheck
|
||||||
from monasca_agent.collector.checks.utils import add_basic_auth
|
from monasca_agent.collector.checks.utils import add_basic_auth
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import psutil
|
|
||||||
import logging
|
import logging
|
||||||
|
import psutil
|
||||||
|
|
||||||
import monasca_agent.collector.checks as checks
|
import monasca_agent.collector.checks as checks
|
||||||
|
|
||||||
|
@ -18,9 +18,9 @@ class Cpu(checks.AgentCheck):
|
||||||
dimensions = self._set_dimensions(None, instance)
|
dimensions = self._set_dimensions(None, instance)
|
||||||
|
|
||||||
if instance is not None:
|
if instance is not None:
|
||||||
send_rollup_stats = instance.get("send_rollup_stats", False)
|
send_rollup_stats = instance.get("send_rollup_stats", False)
|
||||||
else:
|
else:
|
||||||
send_rollup_stats = False
|
send_rollup_stats = False
|
||||||
|
|
||||||
cpu_stats = psutil.cpu_times_percent(percpu=False)
|
cpu_stats = psutil.cpu_times_percent(percpu=False)
|
||||||
num_of_metrics = self._format_results(cpu_stats.user + cpu_stats.nice,
|
num_of_metrics = self._format_results(cpu_stats.user + cpu_stats.nice,
|
||||||
|
@ -34,7 +34,6 @@ class Cpu(checks.AgentCheck):
|
||||||
num_of_metrics += 1
|
num_of_metrics += 1
|
||||||
log.debug('Collected {0} cpu metrics'.format(num_of_metrics))
|
log.debug('Collected {0} cpu metrics'.format(num_of_metrics))
|
||||||
|
|
||||||
|
|
||||||
def _format_results(self, us, sy, wa, idle, st, dimensions):
|
def _format_results(self, us, sy, wa, idle, st, dimensions):
|
||||||
data = {'cpu.user_perc': us,
|
data = {'cpu.user_perc': us,
|
||||||
'cpu.system_perc': sy,
|
'cpu.system_perc': sy,
|
||||||
|
|
|
@ -16,8 +16,7 @@ class Crash(checks.AgentCheck):
|
||||||
log.debug('crash dir: %s', self.crash_dir)
|
log.debug('crash dir: %s', self.crash_dir)
|
||||||
|
|
||||||
def check(self, instance):
|
def check(self, instance):
|
||||||
"""
|
"""Capture crash dump statistics
|
||||||
Capture crash dump statistics
|
|
||||||
"""
|
"""
|
||||||
dimensions = self._set_dimensions(None, instance)
|
dimensions = self._set_dimensions(None, instance)
|
||||||
dump_count = 0
|
dump_count = 0
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
from fnmatch import fnmatch
|
from fnmatch import fnmatch
|
||||||
from os import stat
|
|
||||||
from os import walk
|
|
||||||
from os.path import abspath
|
from os.path import abspath
|
||||||
from os.path import exists
|
from os.path import exists
|
||||||
from os.path import join
|
from os.path import join
|
||||||
|
from os import stat
|
||||||
|
from os import walk
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from monasca_agent.collector.checks import AgentCheck
|
from monasca_agent.collector.checks import AgentCheck
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import psutil
|
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import psutil
|
||||||
|
import re
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -22,14 +23,14 @@ class Disk(checks.AgentCheck):
|
||||||
if instance is not None:
|
if instance is not None:
|
||||||
use_mount = instance.get("use_mount", True)
|
use_mount = instance.get("use_mount", True)
|
||||||
send_io_stats = instance.get("send_io_stats", True)
|
send_io_stats = instance.get("send_io_stats", True)
|
||||||
send_rollup_stats = instance.get("send_rollup_stats", False)
|
send_rollup_stats = instance.get("send_rollup_stats", False)
|
||||||
# If we filter devices, get the list.
|
# If we filter devices, get the list.
|
||||||
device_blacklist_re = self._get_re_exclusions(instance)
|
device_blacklist_re = self._get_re_exclusions(instance)
|
||||||
fs_types_to_ignore = self._get_fs_exclusions(instance)
|
fs_types_to_ignore = self._get_fs_exclusions(instance)
|
||||||
else:
|
else:
|
||||||
use_mount = True
|
use_mount = True
|
||||||
send_io_stats = True
|
send_io_stats = True
|
||||||
send_rollup_stats = False
|
send_rollup_stats = False
|
||||||
device_blacklist_re = None
|
device_blacklist_re = None
|
||||||
fs_types_to_ignore = []
|
fs_types_to_ignore = []
|
||||||
|
|
||||||
|
@ -41,8 +42,8 @@ class Disk(checks.AgentCheck):
|
||||||
total_used = 0
|
total_used = 0
|
||||||
for partition in partitions:
|
for partition in partitions:
|
||||||
if partition.fstype not in fs_types_to_ignore \
|
if partition.fstype not in fs_types_to_ignore \
|
||||||
or (device_blacklist_re \
|
or (device_blacklist_re
|
||||||
and not device_blacklist_re.match(partition.device)):
|
and not device_blacklist_re.match(partition.device)):
|
||||||
device_name = self._get_device_name(partition.device)
|
device_name = self._get_device_name(partition.device)
|
||||||
disk_usage = psutil.disk_usage(partition.mountpoint)
|
disk_usage = psutil.disk_usage(partition.mountpoint)
|
||||||
total_capacity += disk_usage.total
|
total_capacity += disk_usage.total
|
||||||
|
@ -80,14 +81,13 @@ class Disk(checks.AgentCheck):
|
||||||
|
|
||||||
if send_rollup_stats:
|
if send_rollup_stats:
|
||||||
self.gauge("disk.total_space_mb",
|
self.gauge("disk.total_space_mb",
|
||||||
total_capacity/1048576,
|
total_capacity / 1048576,
|
||||||
dimensions=rollup_dimensions)
|
dimensions=rollup_dimensions)
|
||||||
self.gauge("disk.total_used_space_mb",
|
self.gauge("disk.total_used_space_mb",
|
||||||
total_used/1048576,
|
total_used / 1048576,
|
||||||
dimensions=rollup_dimensions)
|
dimensions=rollup_dimensions)
|
||||||
log.debug('Collected 2 rolled-up disk usage metrics')
|
log.debug('Collected 2 rolled-up disk usage metrics')
|
||||||
|
|
||||||
|
|
||||||
def _get_re_exclusions(self, instance):
|
def _get_re_exclusions(self, instance):
|
||||||
"""Parse device blacklist regular expression"""
|
"""Parse device blacklist regular expression"""
|
||||||
filter = None
|
filter = None
|
||||||
|
@ -95,7 +95,7 @@ class Disk(checks.AgentCheck):
|
||||||
filter_device_re = instance.get('device_blacklist_re', None)
|
filter_device_re = instance.get('device_blacklist_re', None)
|
||||||
if filter_device_re:
|
if filter_device_re:
|
||||||
filter = re.compile(filter_device_re)
|
filter = re.compile(filter_device_re)
|
||||||
except re.error as err:
|
except re.error:
|
||||||
log.error('Error processing regular expression {0}'.format(filter_device_re))
|
log.error('Error processing regular expression {0}'.format(filter_device_re))
|
||||||
|
|
||||||
return filter
|
return filter
|
||||||
|
|
|
@ -3,8 +3,8 @@ import json
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import socket
|
import socket
|
||||||
import urllib2
|
|
||||||
import urllib
|
import urllib
|
||||||
|
import urllib2
|
||||||
from urlparse import urlsplit
|
from urlparse import urlsplit
|
||||||
|
|
||||||
from monasca_agent.collector.checks import AgentCheck
|
from monasca_agent.collector.checks import AgentCheck
|
||||||
|
|
|
@ -206,7 +206,6 @@ class ElasticSearch(AgentCheck):
|
||||||
self.STATS_URL = "/_cluster/nodes/stats?all=true"
|
self.STATS_URL = "/_cluster/nodes/stats?all=true"
|
||||||
self.NODES_URL = "/_cluster/nodes?network=true"
|
self.NODES_URL = "/_cluster/nodes?network=true"
|
||||||
|
|
||||||
|
|
||||||
additional_metrics = {
|
additional_metrics = {
|
||||||
"elasticsearch.cache.field.evictions": ("gauge", "indices.cache.field_evictions"),
|
"elasticsearch.cache.field.evictions": ("gauge", "indices.cache.field_evictions"),
|
||||||
"elasticsearch.cache.field.size": ("gauge", "indices.cache.field_size_in_bytes"),
|
"elasticsearch.cache.field.size": ("gauge", "indices.cache.field_size_in_bytes"),
|
||||||
|
|
|
@ -232,8 +232,7 @@ class HAProxy(AgentCheck):
|
||||||
# Store this host status so we can check against it later
|
# Store this host status so we can check against it later
|
||||||
self.host_status[url][key] = data['status']
|
self.host_status[url][key] = data['status']
|
||||||
|
|
||||||
@staticmethod
|
def _create_event(self, status, hostname, lastchg, service_name):
|
||||||
def _create_event(status, hostname, lastchg, service_name):
|
|
||||||
if status == "DOWN":
|
if status == "DOWN":
|
||||||
alert_type = "error"
|
alert_type = "error"
|
||||||
title = "HAProxy %s front-end reported %s %s" % (service_name, hostname, status)
|
title = "HAProxy %s front-end reported %s %s" % (service_name, hostname, status)
|
||||||
|
|
|
@ -12,8 +12,9 @@ from httplib2 import httplib
|
||||||
from httplib2 import HttpLib2Error
|
from httplib2 import HttpLib2Error
|
||||||
|
|
||||||
import monasca_agent.collector.checks.services_checks as services_checks
|
import monasca_agent.collector.checks.services_checks as services_checks
|
||||||
import monasca_agent.common.keystone as keystone
|
|
||||||
import monasca_agent.common.config as cfg
|
import monasca_agent.common.config as cfg
|
||||||
|
import monasca_agent.common.keystone as keystone
|
||||||
|
|
||||||
|
|
||||||
class HTTPCheck(services_checks.ServicesCheck):
|
class HTTPCheck(services_checks.ServicesCheck):
|
||||||
|
|
||||||
|
|
|
@ -84,7 +84,7 @@ class IIS(AgentCheck):
|
||||||
if iis_site.Name == '_Total':
|
if iis_site.Name == '_Total':
|
||||||
dimensions.pop('site', None)
|
dimensions.pop('site', None)
|
||||||
else:
|
else:
|
||||||
dimensions.update({'site': iis_site.Name})
|
dimensions.update({'site': iis_site.Name})
|
||||||
|
|
||||||
for metric, mtype, wmi_val in self.METRICS:
|
for metric, mtype, wmi_val in self.METRICS:
|
||||||
if not hasattr(iis_site, wmi_val):
|
if not hasattr(iis_site, wmi_val):
|
||||||
|
|
|
@ -14,7 +14,7 @@ log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class KafkaConnection(object):
|
class KafkaConnection(object):
|
||||||
""" A simple context manager for kafka connections """
|
"""A simple context manager for kafka connections """
|
||||||
|
|
||||||
def __init__(self, connect_str):
|
def __init__(self, connect_str):
|
||||||
self.connect_str = connect_str
|
self.connect_str = connect_str
|
||||||
|
@ -31,13 +31,13 @@ class KafkaConnection(object):
|
||||||
|
|
||||||
|
|
||||||
class KafkaCheck(checks.AgentCheck):
|
class KafkaCheck(checks.AgentCheck):
|
||||||
""" Checks the configured kafka instance reporting the consumption lag
|
"""Checks the configured kafka instance reporting the consumption lag
|
||||||
for each partition per topic in each consumer group. If full_output
|
for each partition per topic in each consumer group. If full_output
|
||||||
is set also reports broker offsets and the current consumer offset.
|
is set also reports broker offsets and the current consumer offset.
|
||||||
Works on Kafka version >= 0.8.1.1
|
Works on Kafka version >= 0.8.1.1
|
||||||
"""
|
"""
|
||||||
def _validate_consumer_groups(self, val):
|
def _validate_consumer_groups(self, val):
|
||||||
""" Private config validation/marshalling functions
|
"""Private config validation/marshalling functions
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
consumer_group, topic_partitions = val.items()[0]
|
consumer_group, topic_partitions = val.items()[0]
|
||||||
|
|
|
@ -24,8 +24,8 @@ import yaml
|
||||||
from calendar import timegm
|
from calendar import timegm
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from distutils.version import LooseVersion
|
from distutils.version import LooseVersion
|
||||||
from monasca_agent.collector.virt import inspector
|
|
||||||
from monasca_agent.collector.checks import AgentCheck
|
from monasca_agent.collector.checks import AgentCheck
|
||||||
|
from monasca_agent.collector.virt import inspector
|
||||||
|
|
||||||
|
|
||||||
class LibvirtCheck(AgentCheck):
|
class LibvirtCheck(AgentCheck):
|
||||||
|
@ -93,8 +93,8 @@ class LibvirtCheck(AgentCheck):
|
||||||
try:
|
try:
|
||||||
with open(self.instance_cache_file, 'w') as cache_yaml:
|
with open(self.instance_cache_file, 'w') as cache_yaml:
|
||||||
yaml.safe_dump(id_cache, cache_yaml)
|
yaml.safe_dump(id_cache, cache_yaml)
|
||||||
if stat.S_IMODE(os.stat(self.instance_cache_file).st_mode) != 0600:
|
if stat.S_IMODE(os.stat(self.instance_cache_file).st_mode) != 0o600:
|
||||||
os.chmod(self.instance_cache_file, 0600)
|
os.chmod(self.instance_cache_file, 0o600)
|
||||||
except IOError as e:
|
except IOError as e:
|
||||||
self.log.error("Cannot write to {0}: {1}".format(self.instance_cache_file, e))
|
self.log.error("Cannot write to {0}: {1}".format(self.instance_cache_file, e))
|
||||||
|
|
||||||
|
@ -139,8 +139,8 @@ class LibvirtCheck(AgentCheck):
|
||||||
try:
|
try:
|
||||||
with open(self.metric_cache_file, 'w') as cache_yaml:
|
with open(self.metric_cache_file, 'w') as cache_yaml:
|
||||||
yaml.safe_dump(metric_cache, cache_yaml)
|
yaml.safe_dump(metric_cache, cache_yaml)
|
||||||
if stat.S_IMODE(os.stat(self.metric_cache_file).st_mode) != 0600:
|
if stat.S_IMODE(os.stat(self.metric_cache_file).st_mode) != 0o600:
|
||||||
os.chmod(self.metric_cache_file, 0600)
|
os.chmod(self.metric_cache_file, 0o600)
|
||||||
except IOError as e:
|
except IOError as e:
|
||||||
self.log.error("Cannot write to {0}: {1}".format(self.metric_cache_file, e))
|
self.log.error("Cannot write to {0}: {1}".format(self.metric_cache_file, e))
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import psutil
|
|
||||||
import logging
|
import logging
|
||||||
|
import psutil
|
||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import sys
|
||||||
|
|
||||||
import monasca_agent.collector.checks as checks
|
import monasca_agent.collector.checks as checks
|
||||||
import monasca_agent.common.util as util
|
import monasca_agent.common.util as util
|
||||||
|
@ -36,7 +37,7 @@ class Load(checks.AgentCheck):
|
||||||
# Get output from uptime
|
# Get output from uptime
|
||||||
try:
|
try:
|
||||||
uptime = subprocess.Popen(['uptime'],
|
uptime = subprocess.Popen(['uptime'],
|
||||||
stdout=sp.PIPE,
|
stdout=subprocess.PIPE,
|
||||||
close_fds=True).communicate()[0]
|
close_fds=True).communicate()[0]
|
||||||
except Exception:
|
except Exception:
|
||||||
log.exception('Cannot extract load using uptime')
|
log.exception('Cannot extract load using uptime')
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import psutil
|
|
||||||
import logging
|
import logging
|
||||||
|
import psutil
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -21,25 +21,25 @@ class Memory(checks.AgentCheck):
|
||||||
swap_info = psutil.swap_memory()
|
swap_info = psutil.swap_memory()
|
||||||
|
|
||||||
self.gauge('mem.total_mb',
|
self.gauge('mem.total_mb',
|
||||||
int(mem_info.total/1048576),
|
int(mem_info.total / 1048576),
|
||||||
dimensions=dimensions)
|
dimensions=dimensions)
|
||||||
self.gauge('mem.free_mb',
|
self.gauge('mem.free_mb',
|
||||||
int(mem_info.free/1048576),
|
int(mem_info.free / 1048576),
|
||||||
dimensions=dimensions)
|
dimensions=dimensions)
|
||||||
self.gauge('mem.usable_mb',
|
self.gauge('mem.usable_mb',
|
||||||
int(mem_info.available/1048576),
|
int(mem_info.available / 1048576),
|
||||||
dimensions=dimensions)
|
dimensions=dimensions)
|
||||||
self.gauge('mem.usable_perc',
|
self.gauge('mem.usable_perc',
|
||||||
float(100 - mem_info.percent),
|
float(100 - mem_info.percent),
|
||||||
dimensions=dimensions)
|
dimensions=dimensions)
|
||||||
self.gauge('mem.swap_total_mb',
|
self.gauge('mem.swap_total_mb',
|
||||||
int(swap_info.total/1048576),
|
int(swap_info.total / 1048576),
|
||||||
dimensions=dimensions)
|
dimensions=dimensions)
|
||||||
self.gauge('mem.swap_used_mb',
|
self.gauge('mem.swap_used_mb',
|
||||||
int(swap_info.used/1048576),
|
int(swap_info.used / 1048576),
|
||||||
dimensions=dimensions)
|
dimensions=dimensions)
|
||||||
self.gauge('mem.swap_free_mb',
|
self.gauge('mem.swap_free_mb',
|
||||||
int(swap_info.free/1048576),
|
int(swap_info.free / 1048576),
|
||||||
dimensions=dimensions)
|
dimensions=dimensions)
|
||||||
self.gauge('mem.swap_free_perc',
|
self.gauge('mem.swap_free_perc',
|
||||||
float(100 - swap_info.percent),
|
float(100 - swap_info.percent),
|
||||||
|
@ -48,20 +48,20 @@ class Memory(checks.AgentCheck):
|
||||||
count = 8
|
count = 8
|
||||||
if 'buffers' in mem_info:
|
if 'buffers' in mem_info:
|
||||||
self.gauge('mem.used_buffers',
|
self.gauge('mem.used_buffers',
|
||||||
int(mem_info.buffers/1048576),
|
int(mem_info.buffers / 1048576),
|
||||||
dimensions=dimensions)
|
dimensions=dimensions)
|
||||||
count +=1
|
count += 1
|
||||||
|
|
||||||
if 'cached' in mem_info:
|
if 'cached' in mem_info:
|
||||||
self.gauge('mem.used_cache',
|
self.gauge('mem.used_cache',
|
||||||
int(mem_info.cached/1048576),
|
int(mem_info.cached / 1048576),
|
||||||
dimensions=dimensions)
|
dimensions=dimensions)
|
||||||
count +=1
|
count += 1
|
||||||
|
|
||||||
if 'shared' in mem_info:
|
if 'shared' in mem_info:
|
||||||
self.gauge('mem.used_shared',
|
self.gauge('mem.used_shared',
|
||||||
int(mem_info.shared/1048576),
|
int(mem_info.shared / 1048576),
|
||||||
dimensions=dimensions)
|
dimensions=dimensions)
|
||||||
count +=1
|
count += 1
|
||||||
|
|
||||||
log.debug('Collected {0} memory metrics'.format(count))
|
log.debug('Collected {0} memory metrics'.format(count))
|
||||||
|
|
|
@ -11,7 +11,8 @@ import socket
|
||||||
import subprocess
|
import subprocess
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from monasca_agent.collector.checks.services_checks import ServicesCheck, Status
|
from monasca_agent.collector.checks.services_checks import ServicesCheck
|
||||||
|
from monasca_agent.collector.checks.services_checks import Status
|
||||||
|
|
||||||
|
|
||||||
class WrapNagios(ServicesCheck):
|
class WrapNagios(ServicesCheck):
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# stdlib
|
# stdlib
|
||||||
import logging
|
import logging
|
||||||
import re
|
|
||||||
import psutil
|
import psutil
|
||||||
|
import re
|
||||||
|
|
||||||
# project
|
# project
|
||||||
import monasca_agent.collector.checks as checks
|
import monasca_agent.collector.checks as checks
|
||||||
|
@ -32,7 +32,6 @@ class Network(checks.AgentCheck):
|
||||||
exclude_iface_re = None
|
exclude_iface_re = None
|
||||||
|
|
||||||
nics = psutil.net_io_counters(pernic=True)
|
nics = psutil.net_io_counters(pernic=True)
|
||||||
count = 0
|
|
||||||
for nic_name in nics.keys():
|
for nic_name in nics.keys():
|
||||||
if self._is_nic_monitored(nic_name, excluded_ifaces, exclude_iface_re):
|
if self._is_nic_monitored(nic_name, excluded_ifaces, exclude_iface_re):
|
||||||
nic = nics[nic_name]
|
nic = nics[nic_name]
|
||||||
|
|
|
@ -9,14 +9,14 @@ DEFAULT_PORT = "ntp"
|
||||||
|
|
||||||
|
|
||||||
class NtpCheck(AgentCheck):
|
class NtpCheck(AgentCheck):
|
||||||
""" Uses ntplib to grab a metric for the ntp offset
|
"""Uses ntplib to grab a metric for the ntp offset
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def check(self, instance):
|
def check(self, instance):
|
||||||
dimensions = self._set_dimensions(None, instance)
|
dimensions = self._set_dimensions(None, instance)
|
||||||
req_args = {
|
req_args = {
|
||||||
'host': instance.get('host', DEFAULT_HOST),
|
'host': instance.get('host', DEFAULT_HOST),
|
||||||
'port': instance.get('port', DEFAULT_PORT),
|
'port': instance.get('port', DEFAULT_PORT),
|
||||||
'version': int(instance.get('version', DEFAULT_NTP_VERSION)),
|
'version': int(instance.get('version', DEFAULT_NTP_VERSION)),
|
||||||
'timeout': float(instance.get('timeout', DEFAULT_TIMEOUT)),
|
'timeout': float(instance.get('timeout', DEFAULT_TIMEOUT)),
|
||||||
}
|
}
|
||||||
|
@ -32,4 +32,3 @@ class NtpCheck(AgentCheck):
|
||||||
# case the agent host's clock is messed up.
|
# case the agent host's clock is messed up.
|
||||||
ntp_ts = ntp_stats.recv_time
|
ntp_ts = ntp_stats.recv_time
|
||||||
self.gauge('ntp.offset', ntp_offset, timestamp=ntp_ts, dimensions=dimensions)
|
self.gauge('ntp.offset', ntp_offset, timestamp=ntp_ts, dimensions=dimensions)
|
||||||
|
|
||||||
|
|
|
@ -140,8 +140,8 @@ class ProcessCheck(checks.AgentCheck):
|
||||||
except psutil.AccessDenied:
|
except psutil.AccessDenied:
|
||||||
got_denied = True
|
got_denied = True
|
||||||
|
|
||||||
rss += float(mem.rss/1048576)
|
rss += float(mem.rss / 1048576)
|
||||||
vms += float(mem.vms/1048576)
|
vms += float(mem.vms / 1048576)
|
||||||
thr += p.get_num_threads()
|
thr += p.get_num_threads()
|
||||||
cpu += p.get_cpu_percent(cpu_check_interval)
|
cpu += p.get_cpu_percent(cpu_check_interval)
|
||||||
|
|
||||||
|
@ -151,8 +151,8 @@ class ProcessCheck(checks.AgentCheck):
|
||||||
io_counters = p.get_io_counters()
|
io_counters = p.get_io_counters()
|
||||||
read_count += io_counters.read_count
|
read_count += io_counters.read_count
|
||||||
write_count += io_counters.write_count
|
write_count += io_counters.write_count
|
||||||
read_kbytes += float(io_counters.read_bytes/1024)
|
read_kbytes += float(io_counters.read_bytes / 1024)
|
||||||
write_kbytes += float(io_counters.write_bytes/1024)
|
write_kbytes += float(io_counters.write_bytes / 1024)
|
||||||
except psutil.AccessDenied:
|
except psutil.AccessDenied:
|
||||||
self.log.debug('monasca-agent user does not have ' +
|
self.log.debug('monasca-agent user does not have ' +
|
||||||
'access to I/O counters for process' +
|
'access to I/O counters for process' +
|
||||||
|
|
|
@ -194,10 +194,10 @@ class RabbitMQ(checks.AgentCheck):
|
||||||
|
|
||||||
# No queues/node are specified. We will process every queue/node if it's under the limit
|
# No queues/node are specified. We will process every queue/node if it's under the limit
|
||||||
else:
|
else:
|
||||||
# Monasca does not support events at this time.
|
# Monasca does not support events at this time.
|
||||||
# if len(data) > ALERT_THRESHOLD * max_detailed:
|
# if len(data) > ALERT_THRESHOLD * max_detailed:
|
||||||
# # Post a message on the dogweb stream to warn
|
# # Post a message on the dogweb stream to warn
|
||||||
# self.alert(base_url, max_detailed, len(data), object_type)
|
# self.alert(base_url, max_detailed, len(data), object_type)
|
||||||
|
|
||||||
if len(data) > max_detailed:
|
if len(data) > max_detailed:
|
||||||
# Display a warning in the info page
|
# Display a warning in the info page
|
||||||
|
@ -226,7 +226,7 @@ class RabbitMQ(checks.AgentCheck):
|
||||||
root = root.get(path, {})
|
root = root.get(path, {})
|
||||||
|
|
||||||
value = root.get(keys[-1], None)
|
value = root.get(keys[-1], None)
|
||||||
if value == None:
|
if value is None:
|
||||||
value = 0.0
|
value = 0.0
|
||||||
try:
|
try:
|
||||||
self.log.debug("Collected data for %s: metric name: %s: value: %f dimensions: %s" % (object_type, metric_name, float(value), str(dimensions)))
|
self.log.debug("Collected data for %s: metric name: %s: value: %f dimensions: %s" % (object_type, metric_name, float(value), str(dimensions)))
|
||||||
|
|
|
@ -29,19 +29,18 @@ def run_command(command, input=None):
|
||||||
stdout,
|
stdout,
|
||||||
stderr))
|
stderr))
|
||||||
return errcode, stdout, stderr
|
return errcode, stdout, stderr
|
||||||
except Exception as e:
|
except Exception:
|
||||||
log.error("Failure while executing command - {0}".format(command))
|
log.error("Failure while executing command - {0}".format(command))
|
||||||
|
|
||||||
|
|
||||||
def process_command(command):
|
def process_command(command):
|
||||||
"""
|
"""Runs the command and returns json output
|
||||||
Runs the command and returns json output
|
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
errcode, stdout, stderr = run_command(command)
|
errcode, stdout, stderr = run_command(command)
|
||||||
json_output = json.loads(stdout)
|
json_output = json.loads(stdout)
|
||||||
return json_output
|
return json_output
|
||||||
except Exception as e:
|
except Exception:
|
||||||
log.error('Failure while processing output - {0}'.format(stdout))
|
log.error('Failure while processing output - {0}'.format(stdout))
|
||||||
|
|
||||||
|
|
||||||
|
@ -50,11 +49,9 @@ class SwiftDiags(checks.AgentCheck):
|
||||||
super(SwiftDiags, self).__init__(name, init_config, agent_config)
|
super(SwiftDiags, self).__init__(name, init_config, agent_config)
|
||||||
|
|
||||||
def check(self, instance):
|
def check(self, instance):
|
||||||
"""
|
"""Get swift checks and propagate.
|
||||||
Get swift checks and propagate.
|
The checks are part of HP swift-diags package and checks are
|
||||||
The checks are part of HP swift-diags package and checks are
|
are run only if the package exists.
|
||||||
are run only if the package exists.
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if not (os.path.exists(DIAG_COMMAND) and
|
if not (os.path.exists(DIAG_COMMAND) and
|
||||||
os.path.exists(CHECKER_COMMAND)):
|
os.path.exists(CHECKER_COMMAND)):
|
||||||
|
|
|
@ -116,9 +116,9 @@ class Zookeeper(AgentCheck):
|
||||||
# Latency min/avg/max: -10/0/20007
|
# Latency min/avg/max: -10/0/20007
|
||||||
_, value = buf.readline().split(':')
|
_, value = buf.readline().split(':')
|
||||||
l_min, l_avg, l_max = [int(v) for v in value.strip().split('/')]
|
l_min, l_avg, l_max = [int(v) for v in value.strip().split('/')]
|
||||||
metrics.append(('zookeeper.min_latency_sec', float(l_min)/1000))
|
metrics.append(('zookeeper.min_latency_sec', float(l_min) / 1000))
|
||||||
metrics.append(('zookeeper.avg_latency_sec', float(l_avg)/1000))
|
metrics.append(('zookeeper.avg_latency_sec', float(l_avg) / 1000))
|
||||||
metrics.append(('zookeeper.max_latency_sec', float(l_max)/1000))
|
metrics.append(('zookeeper.max_latency_sec', float(l_max) / 1000))
|
||||||
|
|
||||||
# Received: 101032173
|
# Received: 101032173
|
||||||
_, value = buf.readline().split(':')
|
_, value = buf.readline().split(':')
|
||||||
|
|
|
@ -20,7 +20,7 @@ import monasca_agent.common.util as util
|
||||||
|
|
||||||
# set up logging before importing any other components
|
# set up logging before importing any other components
|
||||||
util.initialize_logging('collector')
|
util.initialize_logging('collector')
|
||||||
os.umask(022)
|
os.umask(0o22)
|
||||||
|
|
||||||
# Check we're not using an old version of Python. We need 2.4 above because
|
# Check we're not using an old version of Python. We need 2.4 above because
|
||||||
# some modules (like subprocess) were only introduced in 2.4.
|
# some modules (like subprocess) were only introduced in 2.4.
|
||||||
|
@ -264,7 +264,6 @@ def main():
|
||||||
run_check(check)
|
run_check(check)
|
||||||
|
|
||||||
elif 'configcheck' == command or 'configtest' == command:
|
elif 'configcheck' == command or 'configtest' == command:
|
||||||
osname = util.get_os()
|
|
||||||
all_valid = True
|
all_valid = True
|
||||||
paths = util.Paths()
|
paths = util.Paths()
|
||||||
for conf_path in glob.glob(os.path.join(paths.get_confd_path(), "*.yaml")):
|
for conf_path in glob.glob(os.path.join(paths.get_confd_path(), "*.yaml")):
|
||||||
|
@ -317,6 +316,7 @@ def main():
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
def run_check(check):
|
def run_check(check):
|
||||||
|
|
||||||
is_multi_threaded = False
|
is_multi_threaded = False
|
||||||
|
|
|
@ -20,7 +20,7 @@ from monasca_agent.collector.virt.hyperv import utilsv2
|
||||||
from monasca_agent.collector.virt import inspector as virt_inspector
|
from monasca_agent.collector.virt import inspector as virt_inspector
|
||||||
|
|
||||||
|
|
||||||
def instance_name(instance):
|
def get_instance_name(instance):
|
||||||
"""Shortcut to get instance name."""
|
"""Shortcut to get instance name."""
|
||||||
return getattr(instance, 'OS-EXT-SRV-ATTR:instance_name', None)
|
return getattr(instance, 'OS-EXT-SRV-ATTR:instance_name', None)
|
||||||
|
|
||||||
|
|
|
@ -279,5 +279,5 @@ def get_hypervisor_inspector():
|
||||||
cfg.CONF.hypervisor_inspector,
|
cfg.CONF.hypervisor_inspector,
|
||||||
invoke_on_load=True)
|
invoke_on_load=True)
|
||||||
return mgr.driver
|
return mgr.driver
|
||||||
except ImportError as e:
|
except ImportError:
|
||||||
return Inspector()
|
return Inspector()
|
||||||
|
|
|
@ -90,7 +90,7 @@ class VsphereInspector(virt_inspector.Inspector):
|
||||||
vm_moid = self._ops.get_vm_moid(instance.id)
|
vm_moid = self._ops.get_vm_moid(instance.id)
|
||||||
if vm_moid is None:
|
if vm_moid is None:
|
||||||
raise virt_inspector.InstanceNotFoundException(
|
raise virt_inspector.InstanceNotFoundException(
|
||||||
_('VM %s not found in VMware Vsphere') % instance.id)
|
'VM %s not found in VMware Vsphere' % instance.id)
|
||||||
cpu_util_counter_id = self._ops.get_perf_counter_id(
|
cpu_util_counter_id = self._ops.get_perf_counter_id(
|
||||||
VC_AVERAGE_CPU_CONSUMED_CNTR)
|
VC_AVERAGE_CPU_CONSUMED_CNTR)
|
||||||
cpu_util = self._ops.query_vm_aggregate_stats(
|
cpu_util = self._ops.query_vm_aggregate_stats(
|
||||||
|
@ -107,7 +107,7 @@ class VsphereInspector(virt_inspector.Inspector):
|
||||||
vm_moid = self._ops.get_vm_moid(instance.id)
|
vm_moid = self._ops.get_vm_moid(instance.id)
|
||||||
if not vm_moid:
|
if not vm_moid:
|
||||||
raise virt_inspector.InstanceNotFoundException(
|
raise virt_inspector.InstanceNotFoundException(
|
||||||
_('VM %s not found in VMware Vsphere') % instance.id)
|
'VM %s not found in VMware Vsphere' % instance.id)
|
||||||
|
|
||||||
vnic_stats = {}
|
vnic_stats = {}
|
||||||
vnic_ids = set()
|
vnic_ids = set()
|
||||||
|
@ -139,7 +139,7 @@ class VsphereInspector(virt_inspector.Inspector):
|
||||||
vm_moid = self._ops.get_vm_moid(instance.id)
|
vm_moid = self._ops.get_vm_moid(instance.id)
|
||||||
if vm_moid is None:
|
if vm_moid is None:
|
||||||
raise virt_inspector.InstanceNotFoundException(
|
raise virt_inspector.InstanceNotFoundException(
|
||||||
_('VM %s not found in VMware Vsphere') % instance.id)
|
'VM %s not found in VMware Vsphere' % instance.id)
|
||||||
mem_counter_id = self._ops.get_perf_counter_id(
|
mem_counter_id = self._ops.get_perf_counter_id(
|
||||||
VC_AVERAGE_MEMORY_CONSUMED_CNTR)
|
VC_AVERAGE_MEMORY_CONSUMED_CNTR)
|
||||||
memory = self._ops.query_vm_aggregate_stats(
|
memory = self._ops.query_vm_aggregate_stats(
|
||||||
|
@ -152,7 +152,7 @@ class VsphereInspector(virt_inspector.Inspector):
|
||||||
vm_moid = self._ops.get_vm_moid(instance.id)
|
vm_moid = self._ops.get_vm_moid(instance.id)
|
||||||
if not vm_moid:
|
if not vm_moid:
|
||||||
raise virt_inspector.InstanceNotFoundException(
|
raise virt_inspector.InstanceNotFoundException(
|
||||||
_('VM %s not found in VMware Vsphere') % instance.id)
|
'VM %s not found in VMware Vsphere' % instance.id)
|
||||||
|
|
||||||
disk_stats = {}
|
disk_stats = {}
|
||||||
disk_ids = set()
|
disk_ids = set()
|
||||||
|
|
|
@ -57,23 +57,23 @@ class XenapiException(virt_inspector.InspectorException):
|
||||||
|
|
||||||
def get_api_session():
|
def get_api_session():
|
||||||
if not api:
|
if not api:
|
||||||
raise ImportError(_('XenAPI not installed'))
|
raise ImportError('XenAPI not installed')
|
||||||
|
|
||||||
url = CONF.xenapi.connection_url
|
url = CONF.xenapi.connection_url
|
||||||
username = CONF.xenapi.connection_username
|
username = CONF.xenapi.connection_username
|
||||||
password = CONF.xenapi.connection_password
|
password = CONF.xenapi.connection_password
|
||||||
if not url or password is None:
|
if not url or password is None:
|
||||||
raise XenapiException(_('Must specify connection_url, and '
|
raise XenapiException('Must specify connection_url, and '
|
||||||
'connection_password to use'))
|
'connection_password to use')
|
||||||
|
|
||||||
exception = api.Failure(_("Unable to log in to XenAPI "
|
exception = api.Failure("Unable to log in to XenAPI "
|
||||||
"(is the Dom0 disk full?)"))
|
"(is the Dom0 disk full?)")
|
||||||
try:
|
try:
|
||||||
session = api.Session(url)
|
session = api.Session(url)
|
||||||
with timeout.Timeout(CONF.xenapi.login_timeout, exception):
|
with timeout.Timeout(CONF.xenapi.login_timeout, exception):
|
||||||
session.login_with_password(username, password)
|
session.login_with_password(username, password)
|
||||||
except api.Failure as e:
|
except api.Failure as e:
|
||||||
msg = _("Could not connect to XenAPI: %s") % e.details[0]
|
msg = "Could not connect to XenAPI: %s" % e.details[0]
|
||||||
raise XenapiException(msg)
|
raise XenapiException(msg)
|
||||||
return session
|
return session
|
||||||
|
|
||||||
|
@ -96,10 +96,10 @@ class XenapiInspector(virt_inspector.Inspector):
|
||||||
n = len(vm_refs)
|
n = len(vm_refs)
|
||||||
if n == 0:
|
if n == 0:
|
||||||
raise virt_inspector.InstanceNotFoundException(
|
raise virt_inspector.InstanceNotFoundException(
|
||||||
_('VM %s not found in XenServer') % instance_name)
|
'VM %s not found in XenServer' % instance_name)
|
||||||
elif n > 1:
|
elif n > 1:
|
||||||
raise XenapiException(
|
raise XenapiException(
|
||||||
_('Multiple VM %s found in XenServer') % instance_name)
|
'Multiple VM %s found in XenServer' % instance_name)
|
||||||
else:
|
else:
|
||||||
return vm_refs[0]
|
return vm_refs[0]
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ class XenapiInspector(virt_inspector.Inspector):
|
||||||
vcpus_number = metrics_rec['VCPUs_number']
|
vcpus_number = metrics_rec['VCPUs_number']
|
||||||
vcpus_utils = metrics_rec['VCPUs_utilisation']
|
vcpus_utils = metrics_rec['VCPUs_utilisation']
|
||||||
if len(vcpus_utils) == 0:
|
if len(vcpus_utils) == 0:
|
||||||
msg = _("Could not get VM %s CPU Utilization") % instance_name
|
msg = "Could not get VM %s CPU Utilization" % instance_name
|
||||||
raise XenapiException(msg)
|
raise XenapiException(msg)
|
||||||
|
|
||||||
utils = 0.0
|
utils = 0.0
|
||||||
|
|
|
@ -34,10 +34,7 @@ class InvalidDimensionValue(Exception):
|
||||||
|
|
||||||
|
|
||||||
class MetricsAggregator(object):
|
class MetricsAggregator(object):
|
||||||
|
"""A metric aggregator class."""
|
||||||
"""
|
|
||||||
A metric aggregator class.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, hostname, recent_point_threshold=None):
|
def __init__(self, hostname, recent_point_threshold=None):
|
||||||
self.events = []
|
self.events = []
|
||||||
|
@ -63,10 +60,8 @@ class MetricsAggregator(object):
|
||||||
priority=None,
|
priority=None,
|
||||||
dimensions=None,
|
dimensions=None,
|
||||||
hostname=None):
|
hostname=None):
|
||||||
event = {
|
event = {'msg_title': title,
|
||||||
'msg_title': title,
|
'msg_text': text}
|
||||||
'msg_text': text,
|
|
||||||
}
|
|
||||||
if date_happened is not None:
|
if date_happened is not None:
|
||||||
event['timestamp'] = date_happened
|
event['timestamp'] = date_happened
|
||||||
else:
|
else:
|
||||||
|
@ -97,7 +92,7 @@ class MetricsAggregator(object):
|
||||||
for context, metric in self.metrics.items():
|
for context, metric in self.metrics.items():
|
||||||
try:
|
try:
|
||||||
metrics.extend(metric.flush(timestamp))
|
metrics.extend(metric.flush(timestamp))
|
||||||
except Exception as e:
|
except Exception:
|
||||||
log.exception('Error flushing {0} metrics.'.format(metric.name))
|
log.exception('Error flushing {0} metrics.'.format(metric.name))
|
||||||
|
|
||||||
# Log a warning regarding metrics with old timestamps being submitted
|
# Log a warning regarding metrics with old timestamps being submitted
|
||||||
|
@ -126,9 +121,9 @@ class MetricsAggregator(object):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def formatter(metric, value, timestamp, dimensions, hostname, delegated_tenant=None,
|
def formatter(metric, value, timestamp, dimensions, hostname, delegated_tenant=None,
|
||||||
device_name=None, metric_type=None, value_meta=None):
|
device_name=None, metric_type=None, value_meta=None):
|
||||||
""" Formats metrics, put them into a Measurement class
|
"""Formats metrics, put them into a Measurement class
|
||||||
(metric, timestamp, value, {"dimensions": {"name1": "value1", "name2": "value2"}, ...})
|
(metric, timestamp, value, {"dimensions": {"name1": "value1", "name2": "value2"}, ...})
|
||||||
dimensions should be a dictionary
|
dimensions should be a dictionary
|
||||||
"""
|
"""
|
||||||
if 'hostname' not in dimensions and hostname:
|
if 'hostname' not in dimensions and hostname:
|
||||||
dimensions.update({'hostname': hostname})
|
dimensions.update({'hostname': hostname})
|
||||||
|
|
|
@ -31,6 +31,7 @@ NTP_OFFSET_THRESHOLD = 600
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Stylizer(object):
|
class Stylizer(object):
|
||||||
|
|
||||||
STYLES = {
|
STYLES = {
|
||||||
|
@ -58,7 +59,7 @@ class Stylizer(object):
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def stylize(cls, text, *styles):
|
def stylize(cls, text, *styles):
|
||||||
""" stylize the text. """
|
"""stylize the text. """
|
||||||
if not cls.ENABLED:
|
if not cls.ENABLED:
|
||||||
return text
|
return text
|
||||||
# don't bother about escaping, not that complicated.
|
# don't bother about escaping, not that complicated.
|
||||||
|
@ -102,9 +103,7 @@ def get_ntp_info():
|
||||||
|
|
||||||
|
|
||||||
class AgentStatus(object):
|
class AgentStatus(object):
|
||||||
|
"""A small class used to load and save status messages to the filesystem.
|
||||||
"""
|
|
||||||
A small class used to load and save status messages to the filesystem.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
NAME = None
|
NAME = None
|
||||||
|
@ -497,8 +496,6 @@ class CollectorStatus(AgentStatus):
|
||||||
check_status['error'] = es.error
|
check_status['error'] = es.error
|
||||||
status_info['emitter'].append(check_status)
|
status_info['emitter'].append(check_status)
|
||||||
|
|
||||||
osname = config.get_os()
|
|
||||||
|
|
||||||
paths = util.Paths()
|
paths = util.Paths()
|
||||||
try:
|
try:
|
||||||
status_info['confd_path'] = paths.get_confd_path()
|
status_info['confd_path'] = paths.get_confd_path()
|
||||||
|
|
|
@ -9,6 +9,7 @@ try:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from yaml import Loader
|
from yaml import Loader
|
||||||
|
|
||||||
|
from monasca_agent.common.exceptions import PathNotFound
|
||||||
import monasca_agent.common.singleton as singleton
|
import monasca_agent.common.singleton as singleton
|
||||||
|
|
||||||
DEFAULT_CONFIG_FILE = '/etc/monasca/agent/agent.yaml'
|
DEFAULT_CONFIG_FILE = '/etc/monasca/agent/agent.yaml'
|
||||||
|
@ -17,10 +18,11 @@ LOGGING_MAX_BYTES = 5 * 1024 * 1024
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Config(object):
|
class Config(object):
|
||||||
# Make this a singleton class so we don't get the config every time
|
# Make this a singleton class so we don't get the config every time
|
||||||
# the class is created
|
# the class is created
|
||||||
__metaclass__ = singleton.Singleton
|
six.add_metaclass(singleton.Singleton)
|
||||||
|
|
||||||
def __init__(self, configFile=None):
|
def __init__(self, configFile=None):
|
||||||
if configFile is not None:
|
if configFile is not None:
|
||||||
|
@ -146,10 +148,10 @@ def main():
|
||||||
api_config = configuration.get_config('Api')
|
api_config = configuration.get_config('Api')
|
||||||
statsd_config = configuration.get_config('Statsd')
|
statsd_config = configuration.get_config('Statsd')
|
||||||
logging_config = configuration.get_config('Logging')
|
logging_config = configuration.get_config('Logging')
|
||||||
print "Main Configuration: \n {0}".format(config)
|
print("Main Configuration: \n {0}".format(config))
|
||||||
print "\nApi Configuration: \n {0}".format(api_config)
|
print("\nApi Configuration: \n {0}".format(api_config))
|
||||||
print "\nStatsd Configuration: \n {0}".format(statsd_config)
|
print("\nStatsd Configuration: \n {0}".format(statsd_config))
|
||||||
print "\nLogging Configuration: \n {0}".format(logging_config)
|
print("\nLogging Configuration: \n {0}".format(logging_config))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
@ -12,29 +12,28 @@
|
||||||
|
|
||||||
# Core modules
|
# Core modules
|
||||||
import atexit
|
import atexit
|
||||||
|
import errno
|
||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
|
import signal
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
import logging
|
|
||||||
import errno
|
|
||||||
import signal
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class AgentSupervisor(object):
|
class AgentSupervisor(object):
|
||||||
|
"""A simple supervisor to keep a restart a child on expected auto-restarts
|
||||||
''' A simple supervisor to keep a restart a child on expected auto-restarts
|
"""
|
||||||
'''
|
|
||||||
RESTART_EXIT_STATUS = 5
|
RESTART_EXIT_STATUS = 5
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def start(cls, parent_func, child_func=None):
|
def start(cls, parent_func, child_func=None):
|
||||||
''' `parent_func` is a function that's called every time the child
|
"""`parent_func` is a function that's called every time the child
|
||||||
process dies.
|
process dies.
|
||||||
`child_func` is a function that should be run by the forked child
|
`child_func` is a function that should be run by the forked child
|
||||||
that will auto-restart with the RESTART_EXIT_STATUS.
|
that will auto-restart with the RESTART_EXIT_STATUS.
|
||||||
'''
|
"""
|
||||||
|
|
||||||
# Allow the child process to die on SIGTERM
|
# Allow the child process to die on SIGTERM
|
||||||
signal.signal(signal.SIGTERM, cls._handle_sigterm)
|
signal.signal(signal.SIGTERM, cls._handle_sigterm)
|
||||||
|
@ -70,9 +69,7 @@ class AgentSupervisor(object):
|
||||||
|
|
||||||
|
|
||||||
class Daemon(object):
|
class Daemon(object):
|
||||||
|
"""A generic daemon class.
|
||||||
"""
|
|
||||||
A generic daemon class.
|
|
||||||
|
|
||||||
Usage: subclass the Daemon class and override the run() method
|
Usage: subclass the Daemon class and override the run() method
|
||||||
"""
|
"""
|
||||||
|
@ -86,8 +83,7 @@ class Daemon(object):
|
||||||
self.pidfile = pidfile
|
self.pidfile = pidfile
|
||||||
|
|
||||||
def daemonize(self):
|
def daemonize(self):
|
||||||
"""
|
"""Do the UNIX double-fork magic, see Stevens' "Advanced
|
||||||
Do the UNIX double-fork magic, see Stevens' "Advanced
|
|
||||||
Programming in the UNIX Environment" for details (ISBN 0201563177)
|
Programming in the UNIX Environment" for details (ISBN 0201563177)
|
||||||
http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16
|
http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16
|
||||||
"""
|
"""
|
||||||
|
@ -208,22 +204,19 @@ class Daemon(object):
|
||||||
self.start()
|
self.start()
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
"""
|
"""You should override this method when you subclass Daemon.
|
||||||
You should override this method when you subclass Daemon. It will be called after the process has been
|
It will be called after the process has been daemonized by start() or restart().
|
||||||
daemonized by start() or restart().
|
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def info(self):
|
def info(self):
|
||||||
"""
|
"""You should override this method when you subclass Daemon.
|
||||||
You should override this method when you subclass Daemon. It will be
|
It will be called to provide information about the status of the process
|
||||||
called to provide information about the status of the process
|
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def status(self):
|
def status(self):
|
||||||
"""
|
"""Get the status of the daemon. Exits with 0 if running, 1 if not.
|
||||||
Get the status of the daemon. Exits with 0 if running, 1 if not.
|
|
||||||
"""
|
"""
|
||||||
pid = self.pid()
|
pid = self.pid()
|
||||||
|
|
||||||
|
|
|
@ -12,3 +12,7 @@ class CheckException(Exception):
|
||||||
|
|
||||||
class NaN(CheckException):
|
class NaN(CheckException):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class PathNotFound(Exception):
|
||||||
|
pass
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import logging
|
import logging
|
||||||
|
import six
|
||||||
|
|
||||||
from monascaclient import ksclient
|
from monascaclient import ksclient
|
||||||
|
|
||||||
|
@ -10,7 +11,7 @@ log = logging.getLogger(__name__)
|
||||||
class Keystone(object):
|
class Keystone(object):
|
||||||
# Make this a singleton class so we don't get the token every time
|
# Make this a singleton class so we don't get the token every time
|
||||||
# the class is created
|
# the class is created
|
||||||
__metaclass__ = singleton.Singleton
|
six.add_metaclass(singleton.Singleton)
|
||||||
|
|
||||||
def __init__(self, config):
|
def __init__(self, config):
|
||||||
self.config = config
|
self.config = config
|
||||||
|
|
|
@ -4,7 +4,8 @@ from collections import namedtuple
|
||||||
import logging
|
import logging
|
||||||
from time import time
|
from time import time
|
||||||
|
|
||||||
from monasca_agent.common.exceptions import Infinity, UnknownValue
|
from monasca_agent.common.exceptions import Infinity
|
||||||
|
from monasca_agent.common.exceptions import UnknownValue
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
@ -30,24 +31,21 @@ class MetricTypes(object):
|
||||||
|
|
||||||
|
|
||||||
class Metric(object):
|
class Metric(object):
|
||||||
|
"""A base metric class that accepts points, slices them into time intervals
|
||||||
"""
|
and performs roll-ups within those intervals.
|
||||||
A base metric class that accepts points, slices them into time intervals
|
|
||||||
and performs roll-ups within those intervals.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def sample(self, value, sample_rate, timestamp=None):
|
def sample(self, value, sample_rate, timestamp=None):
|
||||||
""" Add a point to the given metric. """
|
"""Add a point to the given metric. """
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
def flush(self, timestamp):
|
def flush(self, timestamp):
|
||||||
""" Flush all metrics up to the given timestamp. """
|
"""Flush all metrics up to the given timestamp. """
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
class Gauge(Metric):
|
class Gauge(Metric):
|
||||||
|
"""A metric that tracks a value at particular points in time. """
|
||||||
""" A metric that tracks a value at particular points in time. """
|
|
||||||
|
|
||||||
def __init__(self, formatter, name, dimensions,
|
def __init__(self, formatter, name, dimensions,
|
||||||
hostname, device_name, delegated_tenant=None,
|
hostname, device_name, delegated_tenant=None,
|
||||||
|
@ -87,8 +85,7 @@ class Gauge(Metric):
|
||||||
|
|
||||||
|
|
||||||
class Counter(Metric):
|
class Counter(Metric):
|
||||||
|
"""A metric that tracks a counter value. """
|
||||||
""" A metric that tracks a counter value. """
|
|
||||||
|
|
||||||
def __init__(self, formatter, name, dimensions,
|
def __init__(self, formatter, name, dimensions,
|
||||||
hostname, device_name, delegated_tenant=None,
|
hostname, device_name, delegated_tenant=None,
|
||||||
|
@ -107,9 +104,9 @@ class Counter(Metric):
|
||||||
|
|
||||||
def sample(self, value, sample_rate, timestamp=None):
|
def sample(self, value, sample_rate, timestamp=None):
|
||||||
try:
|
try:
|
||||||
self.value += value * int(1 / sample_rate)
|
self.value += value * int(1 / sample_rate)
|
||||||
except TypeError:
|
except TypeError:
|
||||||
log.error("metric {} value {} sample_rate {}".format(self.name, value, sample_rate))
|
log.error("metric {} value {} sample_rate {}".format(self.name, value, sample_rate))
|
||||||
|
|
||||||
def flush(self, timestamp):
|
def flush(self, timestamp):
|
||||||
if self.value is not None:
|
if self.value is not None:
|
||||||
|
@ -129,8 +126,7 @@ class Counter(Metric):
|
||||||
|
|
||||||
|
|
||||||
class Histogram(Metric):
|
class Histogram(Metric):
|
||||||
|
"""A metric to track the distribution of a set of values. """
|
||||||
""" A metric to track the distribution of a set of values. """
|
|
||||||
|
|
||||||
def __init__(self, formatter, name, dimensions,
|
def __init__(self, formatter, name, dimensions,
|
||||||
hostname, device_name, delegated_tenant=None,
|
hostname, device_name, delegated_tenant=None,
|
||||||
|
@ -173,15 +169,15 @@ class Histogram(Metric):
|
||||||
]
|
]
|
||||||
|
|
||||||
metrics.extend(self.formatter(hostname=self.hostname,
|
metrics.extend(self.formatter(hostname=self.hostname,
|
||||||
device_name=self.device_name,
|
device_name=self.device_name,
|
||||||
dimensions=self.dimensions,
|
dimensions=self.dimensions,
|
||||||
delegated_tenant=self.delegated_tenant,
|
delegated_tenant=self.delegated_tenant,
|
||||||
metric='%s.%s' % (self.name, suffix),
|
metric='%s.%s' % (self.name, suffix),
|
||||||
value=value,
|
value=value,
|
||||||
timestamp=timestamp,
|
timestamp=timestamp,
|
||||||
metric_type=metric_type,
|
metric_type=metric_type,
|
||||||
value_meta=self.value_meta
|
value_meta=self.value_meta
|
||||||
) for suffix, value, metric_type in metric_aggrs)
|
) for suffix, value, metric_type in metric_aggrs)
|
||||||
|
|
||||||
for p in self.percentiles:
|
for p in self.percentiles:
|
||||||
val = self.samples[int(round(p * length - 1))]
|
val = self.samples[int(round(p * length - 1))]
|
||||||
|
@ -202,8 +198,7 @@ class Histogram(Metric):
|
||||||
|
|
||||||
|
|
||||||
class Set(Metric):
|
class Set(Metric):
|
||||||
|
"""A metric to track the number of unique elements in a set. """
|
||||||
""" A metric to track the number of unique elements in a set. """
|
|
||||||
|
|
||||||
def __init__(self, formatter, name, dimensions,
|
def __init__(self, formatter, name, dimensions,
|
||||||
hostname, device_name, delegated_tenant=None,
|
hostname, device_name, delegated_tenant=None,
|
||||||
|
@ -224,7 +219,6 @@ class Set(Metric):
|
||||||
self.values.add(value)
|
self.values.add(value)
|
||||||
|
|
||||||
def flush(self, timestamp):
|
def flush(self, timestamp):
|
||||||
metrics = []
|
|
||||||
if not self.values:
|
if not self.values:
|
||||||
return []
|
return []
|
||||||
else:
|
else:
|
||||||
|
@ -243,8 +237,7 @@ class Set(Metric):
|
||||||
|
|
||||||
|
|
||||||
class Rate(Metric):
|
class Rate(Metric):
|
||||||
|
"""Track the rate of metrics over each flush interval """
|
||||||
""" Track the rate of metrics over each flush interval """
|
|
||||||
|
|
||||||
def __init__(self, formatter, name, dimensions,
|
def __init__(self, formatter, name, dimensions,
|
||||||
hostname, device_name, delegated_tenant=None,
|
hostname, device_name, delegated_tenant=None,
|
||||||
|
|
|
@ -3,7 +3,7 @@ class Singleton(type):
|
||||||
super(Singleton, cls).__init__(name, bases, dict)
|
super(Singleton, cls).__init__(name, bases, dict)
|
||||||
cls.instance = None
|
cls.instance = None
|
||||||
|
|
||||||
def __call__(cls,*args,**kw):
|
def __call__(cls, *args, **kw):
|
||||||
if cls.instance is None:
|
if cls.instance is None:
|
||||||
cls.instance = super(Singleton, cls).__call__(*args, **kw)
|
cls.instance = super(Singleton, cls).__call__(*args, **kw)
|
||||||
return cls.instance
|
return cls.instance
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import inspect
|
|
||||||
import imp
|
|
||||||
import itertools
|
|
||||||
import glob
|
import glob
|
||||||
import math
|
|
||||||
import hashlib
|
import hashlib
|
||||||
|
import imp
|
||||||
|
import inspect
|
||||||
|
import itertools
|
||||||
|
import math
|
||||||
import optparse
|
import optparse
|
||||||
import os
|
import os
|
||||||
import platform
|
import platform
|
||||||
|
@ -23,7 +23,8 @@ log = logging.getLogger(__name__)
|
||||||
|
|
||||||
# Tornado
|
# Tornado
|
||||||
try:
|
try:
|
||||||
from tornado import ioloop, version_info as tornado_version
|
from tornado import ioloop
|
||||||
|
from tornado import version_info as tornado_version
|
||||||
except ImportError:
|
except ImportError:
|
||||||
# We are likely running the agent without the forwarder and tornado is not installed
|
# We are likely running the agent without the forwarder and tornado is not installed
|
||||||
# Generate a warning
|
# Generate a warning
|
||||||
|
@ -37,10 +38,7 @@ LOGGING_MAX_BYTES = 5 * 1024 * 1024
|
||||||
NumericTypes = (float, int, long)
|
NumericTypes = (float, int, long)
|
||||||
|
|
||||||
import monasca_agent.common.config as configuration
|
import monasca_agent.common.config as configuration
|
||||||
|
from monasca_agent.common.exceptions import PathNotFound
|
||||||
|
|
||||||
class PathNotFound(Exception):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class Watchdog(object):
|
class Watchdog(object):
|
||||||
|
@ -88,8 +86,7 @@ class Watchdog(object):
|
||||||
|
|
||||||
|
|
||||||
class PidFile(object):
|
class PidFile(object):
|
||||||
|
"""A small helper class for pidfiles. """
|
||||||
""" A small helper class for pidfiles. """
|
|
||||||
|
|
||||||
PID_DIR = '/var/run/monasca-agent'
|
PID_DIR = '/var/run/monasca-agent'
|
||||||
|
|
||||||
|
@ -147,9 +144,7 @@ class PidFile(object):
|
||||||
|
|
||||||
|
|
||||||
class LaconicFilter(logging.Filter):
|
class LaconicFilter(logging.Filter):
|
||||||
|
"""Filters messages, only print them once while keeping memory under control
|
||||||
"""
|
|
||||||
Filters messages, only print them once while keeping memory under control
|
|
||||||
"""
|
"""
|
||||||
LACONIC_MEM_LIMIT = 1024
|
LACONIC_MEM_LIMIT = 1024
|
||||||
|
|
||||||
|
@ -177,8 +172,7 @@ class LaconicFilter(logging.Filter):
|
||||||
|
|
||||||
|
|
||||||
class Timer(object):
|
class Timer(object):
|
||||||
|
"""Helper class """
|
||||||
""" Helper class """
|
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.start()
|
self.start()
|
||||||
|
@ -203,9 +197,7 @@ class Timer(object):
|
||||||
|
|
||||||
|
|
||||||
class Platform(object):
|
class Platform(object):
|
||||||
|
"""Return information about the given platform.
|
||||||
"""
|
|
||||||
Return information about the given platform.
|
|
||||||
"""
|
"""
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def is_darwin(name=None):
|
def is_darwin(name=None):
|
||||||
|
@ -224,7 +216,7 @@ class Platform(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def is_bsd(name=None):
|
def is_bsd(name=None):
|
||||||
""" Return true if this is a BSD like operating system. """
|
"""Return true if this is a BSD like operating system. """
|
||||||
name = name or sys.platform
|
name = name or sys.platform
|
||||||
return Platform.is_darwin(name) or Platform.is_freebsd(name)
|
return Platform.is_darwin(name) or Platform.is_freebsd(name)
|
||||||
|
|
||||||
|
@ -235,7 +227,7 @@ class Platform(object):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def is_unix(name=None):
|
def is_unix(name=None):
|
||||||
""" Return true if the platform is a unix, False otherwise. """
|
"""Return true if the platform is a unix, False otherwise. """
|
||||||
name = name or sys.platform
|
name = name or sys.platform
|
||||||
return (Platform.is_darwin()
|
return (Platform.is_darwin()
|
||||||
or Platform.is_linux()
|
or Platform.is_linux()
|
||||||
|
@ -249,11 +241,9 @@ class Platform(object):
|
||||||
|
|
||||||
|
|
||||||
class Dimensions(object):
|
class Dimensions(object):
|
||||||
|
"""Class to update the default dimensions.
|
||||||
|
"""
|
||||||
|
|
||||||
"""
|
|
||||||
Class to update the default dimensions.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, agent_config):
|
def __init__(self, agent_config):
|
||||||
self.agent_config = agent_config
|
self.agent_config = agent_config
|
||||||
|
|
||||||
|
@ -276,9 +266,7 @@ class Dimensions(object):
|
||||||
|
|
||||||
|
|
||||||
class Paths(object):
|
class Paths(object):
|
||||||
|
"""Return information about system paths.
|
||||||
"""
|
|
||||||
Return information about system paths.
|
|
||||||
"""
|
"""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.osname = get_os()
|
self.osname = get_os()
|
||||||
|
@ -316,27 +304,27 @@ class Paths(object):
|
||||||
raise PathNotFound(path)
|
raise PathNotFound(path)
|
||||||
|
|
||||||
def _windows_confd_path(self):
|
def _windows_confd_path(self):
|
||||||
common_data = _windows_commondata_path()
|
common_data = self._windows_commondata_path()
|
||||||
path = os.path.join(common_data, 'Datadog', 'conf.d')
|
path = os.path.join(common_data, 'Datadog', 'conf.d')
|
||||||
if os.path.exists(path):
|
if os.path.exists(path):
|
||||||
return path
|
return path
|
||||||
raise PathNotFound(path)
|
raise PathNotFound(path)
|
||||||
|
|
||||||
def get_checksd_path(self):
|
def get_checksd_path(self):
|
||||||
if self.osname == 'windows':
|
if self.osname == 'windows':
|
||||||
return self._windows_checksd_path()
|
return self._windows_checksd_path()
|
||||||
else:
|
else:
|
||||||
return self._unix_checksd_path()
|
return self._unix_checksd_path()
|
||||||
|
|
||||||
def _unix_checksd_path(self):
|
def _unix_checksd_path(self):
|
||||||
# Unix only will look up based on the current directory
|
# Unix only will look up based on the current directory
|
||||||
# because checks_d will hang with the other python modules
|
# because checks_d will hang with the other python modules
|
||||||
cur_path = os.path.dirname(os.path.realpath(__file__))
|
cur_path = os.path.dirname(os.path.realpath(__file__))
|
||||||
checksd_path = os.path.join(cur_path, '../collector/checks_d')
|
checksd_path = os.path.join(cur_path, '../collector/checks_d')
|
||||||
|
|
||||||
if os.path.exists(checksd_path):
|
if os.path.exists(checksd_path):
|
||||||
return checksd_path
|
return checksd_path
|
||||||
raise PathNotFound(checksd_path)
|
raise PathNotFound(checksd_path)
|
||||||
|
|
||||||
def _windows_checksd_path(self):
|
def _windows_checksd_path(self):
|
||||||
if hasattr(sys, 'frozen'):
|
if hasattr(sys, 'frozen'):
|
||||||
|
@ -357,7 +345,8 @@ class Paths(object):
|
||||||
how-do-i-find-the-windows-common-application-data-folder-using-python
|
how-do-i-find-the-windows-common-application-data-folder-using-python
|
||||||
"""
|
"""
|
||||||
import ctypes
|
import ctypes
|
||||||
from ctypes import wintypes, windll
|
from ctypes import windll
|
||||||
|
from ctypes import wintypes
|
||||||
|
|
||||||
_SHGetFolderPath = windll.shell32.SHGetFolderPathW
|
_SHGetFolderPath = windll.shell32.SHGetFolderPathW
|
||||||
_SHGetFolderPath.argtypes = [wintypes.HWND,
|
_SHGetFolderPath.argtypes = [wintypes.HWND,
|
||||||
|
@ -385,6 +374,7 @@ class Paths(object):
|
||||||
log.info("Windows certificate path: %s" % crt_path)
|
log.info("Windows certificate path: %s" % crt_path)
|
||||||
tornado.simple_httpclient._DEFAULT_CA_CERTS = crt_path
|
tornado.simple_httpclient._DEFAULT_CA_CERTS = crt_path
|
||||||
|
|
||||||
|
|
||||||
def plural(count):
|
def plural(count):
|
||||||
if count == 1:
|
if count == 1:
|
||||||
return ""
|
return ""
|
||||||
|
@ -488,9 +478,8 @@ def is_valid_hostname(hostname):
|
||||||
|
|
||||||
|
|
||||||
def get_hostname():
|
def get_hostname():
|
||||||
"""
|
"""Get the canonical host name this agent should identify as. This is
|
||||||
Get the canonical host name this agent should identify as. This is
|
the authoritative source of the host name for the agent.
|
||||||
the authoritative source of the host name for the agent.
|
|
||||||
|
|
||||||
Tries, in order:
|
Tries, in order:
|
||||||
|
|
||||||
|
@ -558,9 +547,11 @@ def get_parsed_args():
|
||||||
|
|
||||||
|
|
||||||
def load_check_directory():
|
def load_check_directory():
|
||||||
''' Return the initialized checks from checks_d, and a mapping of checks that failed to
|
"""Return the initialized checks from checks_d, and a mapping of checks that failed to
|
||||||
initialize. Only checks that have a configuration
|
initialize. Only checks that have a configuration
|
||||||
file in conf.d will be returned. '''
|
file in conf.d will be returned.
|
||||||
|
"""
|
||||||
|
|
||||||
from monasca_agent.collector.checks import AgentCheck
|
from monasca_agent.collector.checks import AgentCheck
|
||||||
|
|
||||||
config = configuration.Config()
|
config = configuration.Config()
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import collections
|
import collections
|
||||||
import copy
|
import copy
|
||||||
import logging
|
import logging
|
||||||
import time
|
|
||||||
import random
|
import random
|
||||||
|
import time
|
||||||
|
|
||||||
import monascaclient.client
|
|
||||||
import monasca_agent.common.keystone as keystone
|
import monasca_agent.common.keystone as keystone
|
||||||
|
import monascaclient.client
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -22,9 +22,7 @@ class MonascaAPI(object):
|
||||||
MAX_BACKOFF = 60 # seconds
|
MAX_BACKOFF = 60 # seconds
|
||||||
|
|
||||||
def __init__(self, config):
|
def __init__(self, config):
|
||||||
"""
|
"""Initialize Mon api client connection."""
|
||||||
Initialize Mon api client connection.
|
|
||||||
"""
|
|
||||||
self.config = config
|
self.config = config
|
||||||
self.url = config['url']
|
self.url = config['url']
|
||||||
self.api_version = '2_0'
|
self.api_version = '2_0'
|
||||||
|
|
|
@ -6,11 +6,11 @@
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Standard imports
|
# Standard imports
|
||||||
import socket
|
import datetime
|
||||||
import logging
|
import logging
|
||||||
import signal
|
import signal
|
||||||
|
import socket
|
||||||
import sys
|
import sys
|
||||||
import datetime
|
|
||||||
|
|
||||||
# set up logging before importing any other components
|
# set up logging before importing any other components
|
||||||
import monasca_agent.common.util as util
|
import monasca_agent.common.util as util
|
||||||
|
@ -18,19 +18,19 @@ import monasca_agent.common.util as util
|
||||||
util.initialize_logging('forwarder')
|
util.initialize_logging('forwarder')
|
||||||
|
|
||||||
import os
|
import os
|
||||||
os.umask(022)
|
os.umask(0o22)
|
||||||
|
|
||||||
# Tornado
|
# Tornado
|
||||||
|
import tornado.escape
|
||||||
import tornado.httpclient
|
import tornado.httpclient
|
||||||
import tornado.httpserver
|
import tornado.httpserver
|
||||||
import tornado.ioloop
|
import tornado.ioloop
|
||||||
import tornado.web
|
|
||||||
import tornado.escape
|
|
||||||
import tornado.options
|
import tornado.options
|
||||||
|
import tornado.web
|
||||||
|
|
||||||
# agent import
|
# agent import
|
||||||
import monasca_agent.common.config as cfg
|
|
||||||
import monasca_agent.common.check_status as check_status
|
import monasca_agent.common.check_status as check_status
|
||||||
|
import monasca_agent.common.config as cfg
|
||||||
import monasca_agent.common.metrics as metrics
|
import monasca_agent.common.metrics as metrics
|
||||||
import monasca_agent.common.util as util
|
import monasca_agent.common.util as util
|
||||||
import monasca_agent.forwarder.api.monasca_api as mon
|
import monasca_agent.forwarder.api.monasca_api as mon
|
||||||
|
@ -102,7 +102,7 @@ class Forwarder(tornado.web.Application):
|
||||||
use_simple_http_client=False):
|
use_simple_http_client=False):
|
||||||
self._port = int(port)
|
self._port = int(port)
|
||||||
self._agent_config = agent_config
|
self._agent_config = agent_config
|
||||||
self.flush_interval = (int(agent_config.get('check_freq'))/2) * 1000
|
self.flush_interval = (int(agent_config.get('check_freq')) / 2) * 1000
|
||||||
self._metrics = {}
|
self._metrics = {}
|
||||||
transaction.MetricTransaction.set_application(self)
|
transaction.MetricTransaction.set_application(self)
|
||||||
transaction.MetricTransaction.set_endpoints(mon.MonascaAPI(agent_config))
|
transaction.MetricTransaction.set_endpoints(mon.MonascaAPI(agent_config))
|
||||||
|
@ -132,9 +132,10 @@ class Forwarder(tornado.web.Application):
|
||||||
|
|
||||||
# todo why is the tornado logging method overridden? Perhaps ditch this.
|
# todo why is the tornado logging method overridden? Perhaps ditch this.
|
||||||
def log_request(self, handler):
|
def log_request(self, handler):
|
||||||
""" Override the tornado logging method.
|
"""Override the tornado logging method.
|
||||||
If everything goes well, log level is DEBUG.
|
If everything goes well, log level is DEBUG.
|
||||||
Otherwise it's WARNING or ERROR depending on the response code. """
|
Otherwise it's WARNING or ERROR depending on the response code.
|
||||||
|
"""
|
||||||
if handler.get_status() < 400:
|
if handler.get_status() < 400:
|
||||||
log_method = log.debug
|
log_method = log.debug
|
||||||
elif handler.get_status() < 500:
|
elif handler.get_status() < 500:
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
# stdlib
|
# stdlib
|
||||||
import sys
|
from datetime import datetime
|
||||||
import time
|
from datetime import timedelta
|
||||||
from datetime import datetime, timedelta
|
|
||||||
import logging
|
import logging
|
||||||
from operator import attrgetter
|
from operator import attrgetter
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
|
||||||
# project
|
# project
|
||||||
import monasca_agent.common.check_status as check_status
|
import monasca_agent.common.check_status as check_status
|
||||||
|
@ -116,9 +117,9 @@ class MetricTransaction(Transaction):
|
||||||
|
|
||||||
|
|
||||||
class TransactionManager(util.Dimensions):
|
class TransactionManager(util.Dimensions):
|
||||||
|
|
||||||
"""Holds any transaction derived object list and make sure they
|
"""Holds any transaction derived object list and make sure they
|
||||||
are all commited, without exceeding parameters (throttling, memory consumption) """
|
are all commited, without exceeding parameters (throttling, memory consumption)
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self, max_wait_for_replay, max_queue_size, throttling_delay, agent_config):
|
def __init__(self, max_wait_for_replay, max_queue_size, throttling_delay, agent_config):
|
||||||
super(TransactionManager, self).__init__(agent_config)
|
super(TransactionManager, self).__init__(agent_config)
|
||||||
|
|
|
@ -27,7 +27,7 @@ log = logging.getLogger('statsd')
|
||||||
|
|
||||||
|
|
||||||
class MonascaStatsd(object):
|
class MonascaStatsd(object):
|
||||||
""" This class is the monasca_statsd daemon. """
|
"""This class is the monasca_statsd daemon. """
|
||||||
|
|
||||||
def __init__(self, config_path):
|
def __init__(self, config_path):
|
||||||
config = cfg.Config()
|
config = cfg.Config()
|
||||||
|
@ -86,7 +86,7 @@ class MonascaStatsd(object):
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
""" The main entry point for the unix version of monasca_statsd. """
|
"""The main entry point for the unix version of monasca_statsd. """
|
||||||
parser = argparse.ArgumentParser(description='Monasca statsd - statsd server supporting metric dimensions')
|
parser = argparse.ArgumentParser(description='Monasca statsd - statsd server supporting metric dimensions')
|
||||||
parser.add_argument('--config', '-c',
|
parser.add_argument('--config', '-c',
|
||||||
help="Location for an alternate config rather than using the default config location.")
|
help="Location for an alternate config rather than using the default config location.")
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
import monasca_agent.common.check_status as check_status
|
import monasca_agent.common.check_status as check_status
|
||||||
import monasca_agent.common.emitter as emitter
|
import monasca_agent.common.emitter as emitter
|
||||||
import monasca_agent.common.util as util
|
import monasca_agent.common.util as util
|
||||||
|
@ -18,8 +19,7 @@ EVENT_CHUNK_SIZE = 50
|
||||||
|
|
||||||
|
|
||||||
class Reporter(threading.Thread):
|
class Reporter(threading.Thread):
|
||||||
"""
|
"""The reporter periodically sends the aggregated metrics to the
|
||||||
The reporter periodically sends the aggregated metrics to the
|
|
||||||
server.
|
server.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
|
@ -21,10 +21,7 @@ metric_class = {
|
||||||
|
|
||||||
|
|
||||||
class Server(object):
|
class Server(object):
|
||||||
|
"""A statsd udp server."""
|
||||||
"""
|
|
||||||
A statsd udp server.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, aggregator, host, port, forward_to_host=None, forward_to_port=None):
|
def __init__(self, aggregator, host, port, forward_to_host=None, forward_to_port=None):
|
||||||
self.host = host
|
self.host = host
|
||||||
|
@ -162,7 +159,7 @@ class Server(object):
|
||||||
name, value, metric_class[mtype], dimensions=dimensions, sample_rate=sample_rate)
|
name, value, metric_class[mtype], dimensions=dimensions, sample_rate=sample_rate)
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
""" Run the server. """
|
"""Run the server."""
|
||||||
# Bind to the UDP socket.
|
# Bind to the UDP socket.
|
||||||
# IPv4 only
|
# IPv4 only
|
||||||
open_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
open_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
|
|
|
@ -1,27 +1,30 @@
|
||||||
# set up logging before importing any other components
|
# set up logging before importing any other components
|
||||||
|
from collector import modules
|
||||||
from config import initialize_logging
|
from config import initialize_logging
|
||||||
from monasca_agent.pup import pup
|
from monasca_agent.pup import pup
|
||||||
from collector import modules
|
|
||||||
from monasca_agent.statsd import daemon
|
from monasca_agent.statsd import daemon
|
||||||
|
|
||||||
initialize_logging('collector')
|
initialize_logging('collector')
|
||||||
|
|
||||||
import win32serviceutil
|
|
||||||
import win32service
|
|
||||||
import win32event
|
|
||||||
import sys
|
|
||||||
import logging
|
import logging
|
||||||
import time
|
|
||||||
import multiprocessing
|
import multiprocessing
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import win32event
|
||||||
|
import win32service
|
||||||
|
import win32serviceutil
|
||||||
|
|
||||||
from optparse import Values
|
|
||||||
from collector.checks.collector import Collector
|
from collector.checks.collector import Collector
|
||||||
from emitter import http_emitter
|
|
||||||
from ddagent import Application
|
|
||||||
from win32.common import handle_exe_click
|
|
||||||
from collector.jmxfetch import JMXFetch
|
from collector.jmxfetch import JMXFetch
|
||||||
|
from ddagent import Application
|
||||||
|
from emitter import http_emitter
|
||||||
|
from optparse import Values
|
||||||
|
from win32.common import handle_exe_click
|
||||||
|
|
||||||
from monasca_agent.common.config import get_config, load_check_directory, set_win32_cert_path
|
from monasca_agent.common.config import get_config
|
||||||
|
from monasca_agent.common.config import load_check_directory
|
||||||
|
from monasca_agent.common.config import set_win32_cert_path
|
||||||
|
from monasca_agent.statsd.daemon import MonascaStatsd
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
RESTART_INTERVAL = 24 * 60 * 60 # Defaults to 1 day
|
RESTART_INTERVAL = 24 * 60 * 60 # Defaults to 1 day
|
||||||
|
|
|
@ -2,9 +2,10 @@ import ctypes
|
||||||
|
|
||||||
|
|
||||||
def handle_exe_click(name):
|
def handle_exe_click(name):
|
||||||
''' When the executables are clicked directly in the UI, we must let the
|
"""When the executables are clicked directly in the UI, we must let the
|
||||||
user know that they have to install the program as a service instead of
|
user know that they have to install the program as a service instead of
|
||||||
running it directly. '''
|
running it directly.
|
||||||
|
"""
|
||||||
message = """To use %(name)s, you must install it as a service.
|
message = """To use %(name)s, you must install it as a service.
|
||||||
|
|
||||||
To install %(name)s as a service, you must run the following in the console:
|
To install %(name)s as a service, you must run the following in the console:
|
||||||
|
|
|
@ -3,34 +3,54 @@
|
||||||
# Licensed under the terms of the CECILL License
|
# Licensed under the terms of the CECILL License
|
||||||
# Modified for Datadog
|
# Modified for Datadog
|
||||||
|
|
||||||
import yaml
|
|
||||||
try:
|
try:
|
||||||
from yaml import CLoader as Loader
|
from yaml import CLoader as Loader
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from yaml import Loader
|
from yaml import Loader
|
||||||
import sys
|
|
||||||
import os
|
import os
|
||||||
import os.path as osp
|
import os.path as osp
|
||||||
|
import sys
|
||||||
|
import threading as thread
|
||||||
import webbrowser
|
import webbrowser
|
||||||
import thread # To manage the windows process asynchronously
|
import yaml
|
||||||
|
|
||||||
import win32serviceutil
|
|
||||||
import win32service
|
import win32service
|
||||||
|
import win32serviceutil
|
||||||
|
|
||||||
# GUI Imports
|
# GUI Imports
|
||||||
from guidata.qt.QtCore import SIGNAL, Qt, QSize, QPoint, QTimer
|
from guidata.qt.QtCore import QPoint
|
||||||
from guidata.qt.QtGui import QInputDialog, QWidget, QFont, QLabel, QGroupBox, QHBoxLayout, QSystemTrayIcon
|
from guidata.qt.QtCore import QSize
|
||||||
from guidata.qt.QtGui import QVBoxLayout, QPushButton, QSplitter, QListWidget, QMenu, QMessageBox
|
from guidata.qt.QtCore import Qt
|
||||||
|
from guidata.qt.QtCore import QTimer
|
||||||
|
from guidata.qt.QtCore import SIGNAL
|
||||||
|
|
||||||
from guidata.configtools import get_icon, get_family, MONOSPACE
|
from guidata.qt.QtGui import QFont
|
||||||
|
from guidata.qt.QtGui import QGroupBox
|
||||||
|
from guidata.qt.QtGui import QHBoxLayout
|
||||||
|
from guidata.qt.QtGui import QInputDialog
|
||||||
|
from guidata.qt.QtGui import QLabel
|
||||||
|
from guidata.qt.QtGui import QListWidget
|
||||||
|
from guidata.qt.QtGui import QMenu
|
||||||
|
from guidata.qt.QtGui import QMessageBox
|
||||||
|
from guidata.qt.QtGui import QPushButton
|
||||||
|
from guidata.qt.QtGui import QSplitter
|
||||||
|
from guidata.qt.QtGui import QSystemTrayIcon
|
||||||
|
from guidata.qt.QtGui import QVBoxLayout
|
||||||
|
from guidata.qt.QtGui import QWidget
|
||||||
|
|
||||||
|
from guidata.configtools import get_family
|
||||||
|
from guidata.configtools import get_icon
|
||||||
|
from guidata.configtools import MONOSPACE
|
||||||
from guidata.qthelpers import get_std_icon
|
from guidata.qthelpers import get_std_icon
|
||||||
from spyderlib.widgets.sourcecode.codeeditor import CodeEditor
|
from spyderlib.widgets.sourcecode.codeeditor import CodeEditor
|
||||||
|
|
||||||
|
|
||||||
# Datadog
|
# Datadog
|
||||||
from common.util import get_os
|
from common.util import get_os
|
||||||
from config import (get_confd_path, get_config_path, get_config,
|
from config import _windows_commondata_path
|
||||||
_windows_commondata_path)
|
from config import get_confd_path
|
||||||
|
from config import get_config
|
||||||
|
from config import get_config_path
|
||||||
|
|
||||||
EXCLUDED_WINDOWS_CHECKS = [
|
EXCLUDED_WINDOWS_CHECKS = [
|
||||||
'cacti', 'directory', 'gearmand',
|
'cacti', 'directory', 'gearmand',
|
||||||
|
|
|
@ -58,7 +58,7 @@ def merge_by_name(first, second):
|
||||||
|
|
||||||
|
|
||||||
def read_plugin_config_from_disk(config_dir, plugin_name):
|
def read_plugin_config_from_disk(config_dir, plugin_name):
|
||||||
""" Reads from the Agent on disk configuration the config for a specific plugin
|
"""Reads from the Agent on disk configuration the config for a specific plugin
|
||||||
:param config_dir: Monasca Agent configuration directory
|
:param config_dir: Monasca Agent configuration directory
|
||||||
:param plugin_name: The name of the check plugin
|
:param plugin_name: The name of the check plugin
|
||||||
:return: Dictionary of parsed yaml content
|
:return: Dictionary of parsed yaml content
|
||||||
|
@ -72,7 +72,7 @@ def read_plugin_config_from_disk(config_dir, plugin_name):
|
||||||
|
|
||||||
|
|
||||||
def save_plugin_config(config_dir, plugin_name, user, conf):
|
def save_plugin_config(config_dir, plugin_name, user, conf):
|
||||||
""" Writes configuration for plugin_name to disk in the config_dir
|
"""Writes configuration for plugin_name to disk in the config_dir
|
||||||
:param config_dir: Monasca Agent configuration directory
|
:param config_dir: Monasca Agent configuration directory
|
||||||
:param plugin_name: The name of the check plugin
|
:param plugin_name: The name of the check plugin
|
||||||
:param user: The username Monasca-agent will run as
|
:param user: The username Monasca-agent will run as
|
||||||
|
@ -88,5 +88,5 @@ def save_plugin_config(config_dir, plugin_name, user, conf):
|
||||||
allow_unicode=True,
|
allow_unicode=True,
|
||||||
default_flow_style=False))
|
default_flow_style=False))
|
||||||
gid = pwd.getpwnam(user).pw_gid
|
gid = pwd.getpwnam(user).pw_gid
|
||||||
os.chmod(config_path, 0640)
|
os.chmod(config_path, 0o640)
|
||||||
os.chown(config_path, 0, gid)
|
os.chown(config_path, 0, gid)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
from args_plugin import ArgsPlugin
|
||||||
from plugin import Plugin
|
from plugin import Plugin
|
||||||
|
from service_plugin import ServicePlugin
|
||||||
from utils import find_process_cmdline
|
from utils import find_process_cmdline
|
||||||
from utils import find_process_name
|
from utils import find_process_name
|
||||||
from utils import watch_process
|
|
||||||
from utils import service_api_check
|
from utils import service_api_check
|
||||||
from args_plugin import ArgsPlugin
|
from utils import watch_process
|
||||||
from service_plugin import ServicePlugin
|
|
||||||
|
|
|
@ -7,11 +7,10 @@ log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class ArgsPlugin(Plugin):
|
class ArgsPlugin(Plugin):
|
||||||
""" Base plugin for detection plugins that take arguments for configuration rather than do detection."""
|
"""Base plugin for detection plugins that take arguments for configuration rather than do detection."""
|
||||||
|
|
||||||
def _build_instance(self, arg_list):
|
def _build_instance(self, arg_list):
|
||||||
""" If a value for each arg in the arg_list was specified build it into an instance dictionary. Also check
|
"""If a value for each arg in the arg_list was specified build it into an instance dictionary. Also check for dimensions and add if they were specified.
|
||||||
for dimensions and add if they were specified.
|
|
||||||
:param arg_list: Arguments to include
|
:param arg_list: Arguments to include
|
||||||
:return: instance dictionary
|
:return: instance dictionary
|
||||||
"""
|
"""
|
||||||
|
@ -24,7 +23,7 @@ class ArgsPlugin(Plugin):
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
def _check_required_args(self, arg_list):
|
def _check_required_args(self, arg_list):
|
||||||
""" Check that the required args were specified
|
"""Check that the required args were specified
|
||||||
:param arg_list: A list of arguments to verify were specified
|
:param arg_list: A list of arguments to verify were specified
|
||||||
:return: True if the required args exist false otherwise
|
:return: True if the required args exist false otherwise
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
|
|
||||||
Detection classes should be platform independent
|
Detection classes should be platform independent
|
||||||
"""
|
"""
|
||||||
import sys
|
|
||||||
import logging
|
import logging
|
||||||
|
import sys
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -39,8 +39,8 @@ class Plugin(object):
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def build_config_with_name(self):
|
def build_config_with_name(self):
|
||||||
""" Builds the config and then adds a field 'built_by' to each instance in the config.
|
"""Builds the config and then adds a field 'built_by' to each instance in the config.
|
||||||
built_by is set to the plugin name
|
built_by is set to the plugin name
|
||||||
:return: An agent_config.Plugins object
|
:return: An agent_config.Plugins object
|
||||||
"""
|
"""
|
||||||
conf = self.build_config()
|
conf = self.build_config()
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
|
|
|
@ -102,11 +102,11 @@ class Apache(monasca_setup.detection.Plugin):
|
||||||
log.info("\tSuccessfully setup Apache plugin.")
|
log.info("\tSuccessfully setup Apache plugin.")
|
||||||
else:
|
else:
|
||||||
log.warn('Unable to access the Apache server-status URL;' + error_msg)
|
log.warn('Unable to access the Apache server-status URL;' + error_msg)
|
||||||
except urllib2.URLError, e:
|
except urllib2.URLError as e:
|
||||||
log.error('\tError {0} received when accessing url {1}.'.format(e.reason, apache_url) +
|
log.error('\tError {0} received when accessing url {1}.'.format(e.reason, apache_url) +
|
||||||
'\n\tPlease ensure the Apache web server is running and your configuration ' +
|
'\n\tPlease ensure the Apache web server is running and your configuration ' +
|
||||||
'information in /root/.apache.cnf is correct.' + error_msg)
|
'information in /root/.apache.cnf is correct.' + error_msg)
|
||||||
except urllib2.HTTPError, e:
|
except urllib2.HTTPError as e:
|
||||||
log.error('\tError code {0} received when accessing {1}'.format(e.code, apache_url) + error_msg)
|
log.error('\tError code {0} received when accessing {1}'.format(e.code, apache_url) + error_msg)
|
||||||
else:
|
else:
|
||||||
log.error('\tThe dependencies for Apache Web Server are not installed or unavailable.' + error_msg)
|
log.error('\tThe dependencies for Apache Web Server are not installed or unavailable.' + error_msg)
|
||||||
|
|
|
@ -12,7 +12,7 @@ class Cinder(monasca_setup.detection.ServicePlugin):
|
||||||
'overwrite': overwrite,
|
'overwrite': overwrite,
|
||||||
'service_name': 'block-storage',
|
'service_name': 'block-storage',
|
||||||
'process_names': ['cinder-volume', 'cinder-scheduler',
|
'process_names': ['cinder-volume', 'cinder-scheduler',
|
||||||
'cinder-api','cinder-backup'],
|
'cinder-api', 'cinder-backup'],
|
||||||
'service_api_url': 'http://localhost:8776/v2.0',
|
'service_api_url': 'http://localhost:8776/v2.0',
|
||||||
'search_pattern': '.*version=1.*'
|
'search_pattern': '.*version=1.*'
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,14 +8,12 @@ log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class Crash(Plugin):
|
class Crash(Plugin):
|
||||||
"""
|
"""Detect if kdump is installed and enabled and setup configuration to
|
||||||
Detect if kdump is installed and enabled and setup configuration to
|
monitor for crash dumps.
|
||||||
monitor for crash dumps.
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def _detect(self):
|
def _detect(self):
|
||||||
"""
|
"""Run detection, set self.available True if a crash kernel is loaded.
|
||||||
Run detection, set self.available True if a crash kernel is loaded.
|
|
||||||
"""
|
"""
|
||||||
loaded = '/sys/kernel/kexec_crash_loaded'
|
loaded = '/sys/kernel/kexec_crash_loaded'
|
||||||
if os.path.isfile(loaded):
|
if os.path.isfile(loaded):
|
||||||
|
@ -24,8 +22,7 @@ class Crash(Plugin):
|
||||||
self.available = True
|
self.available = True
|
||||||
|
|
||||||
def build_config(self):
|
def build_config(self):
|
||||||
"""
|
"""Build the config as a Plugin object and return it.
|
||||||
Build the config as a Plugin object and return it.
|
|
||||||
"""
|
"""
|
||||||
log.info('\tEnabling the Monasca crash dump healthcheck')
|
log.info('\tEnabling the Monasca crash dump healthcheck')
|
||||||
config = agent_config.Plugins()
|
config = agent_config.Plugins()
|
||||||
|
|
|
@ -64,7 +64,7 @@ class HAProxy(monasca_setup.detection.Plugin):
|
||||||
instance_config['username'] = user
|
instance_config['username'] = user
|
||||||
if password is not None:
|
if password is not None:
|
||||||
instance_config['password'] = password
|
instance_config['password'] = password
|
||||||
config['haproxy'] = {'init_config': None, 'instances': [ instance_config ]}
|
config['haproxy'] = {'init_config': None, 'instances': [instance_config]}
|
||||||
|
|
||||||
return config
|
return config
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ class Heat(monasca_setup.detection.ServicePlugin):
|
||||||
'process_names': ['heat-api', 'heat-api-cfn',
|
'process_names': ['heat-api', 'heat-api-cfn',
|
||||||
'heat-api-cloudwatch', 'heat-engine'],
|
'heat-api-cloudwatch', 'heat-engine'],
|
||||||
'service_api_url': 'http://localhost:8004',
|
'service_api_url': 'http://localhost:8004',
|
||||||
'search_pattern' : '.*200 OK.*',
|
'search_pattern': '.*200 OK.*',
|
||||||
}
|
}
|
||||||
|
|
||||||
super(Heat, self).__init__(service_params)
|
super(Heat, self).__init__(service_params)
|
||||||
|
|
|
@ -7,16 +7,16 @@ log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class HostAlive(monasca_setup.detection.ArgsPlugin):
|
class HostAlive(monasca_setup.detection.ArgsPlugin):
|
||||||
""" Setup an host_alive check according to the passed in args.
|
"""Setup an host_alive check according to the passed in args.
|
||||||
Despite being a detection plugin, this plugin does no detection and
|
Despite being a detection plugin, this plugin does no detection and
|
||||||
will be a NOOP without arguments. Expects two space-separated
|
will be a NOOP without arguments. Expects two space-separated
|
||||||
arguments, 'hostname' and 'type,' where the former is a comma-separated
|
arguments, 'hostname' and 'type,' where the former is a comma-separated
|
||||||
list of hosts, and the latter can be either 'ssh' or 'ping'.
|
list of hosts, and the latter can be either 'ssh' or 'ping'.
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
monasca-setup -d hostalive -a "hostname=remotebox type=ping"
|
monasca-setup -d hostalive -a "hostname=remotebox type=ping"
|
||||||
|
|
||||||
monasca-setup -d hostalive -a "hostname=remotebox,remotebox2 type=ssh"
|
monasca-setup -d hostalive -a "hostname=remotebox,remotebox2 type=ssh"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def _detect(self):
|
def _detect(self):
|
||||||
|
|
|
@ -8,10 +8,10 @@ log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class HttpCheck(monasca_setup.detection.ArgsPlugin):
|
class HttpCheck(monasca_setup.detection.ArgsPlugin):
|
||||||
""" Setup an http_check according to the passed in args.
|
"""Setup an http_check according to the passed in args.
|
||||||
Despite being a detection plugin this plugin does no detection and will be a noop without arguments.
|
Despite being a detection plugin this plugin does no detection and will be a noop without arguments.
|
||||||
Expects space seperated arguments, the required argument is url. Optional parameters include:
|
Expects space seperated arguments, the required argument is url. Optional parameters include:
|
||||||
disable_ssl_validation and match_pattern.
|
disable_ssl_validation and match_pattern.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def _detect(self):
|
def _detect(self):
|
||||||
|
|
|
@ -1,12 +1,17 @@
|
||||||
import logging
|
import logging
|
||||||
import re
|
import re
|
||||||
from subprocess import CalledProcessError, STDOUT
|
from subprocess import CalledProcessError
|
||||||
|
from subprocess import STDOUT
|
||||||
|
|
||||||
from monasca_setup.detection import Plugin, find_process_cmdline, watch_process
|
|
||||||
from monasca_setup.detection.utils import find_addr_listening_on_port
|
|
||||||
from monasca_setup.detection.utils import check_output
|
|
||||||
from monasca_setup import agent_config
|
from monasca_setup import agent_config
|
||||||
|
|
||||||
|
from monasca_setup.detection import find_process_cmdline
|
||||||
|
from monasca_setup.detection import Plugin
|
||||||
|
from monasca_setup.detection import watch_process
|
||||||
|
|
||||||
|
from monasca_setup.detection.utils import check_output
|
||||||
|
from monasca_setup.detection.utils import find_addr_listening_on_port
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
@ -67,8 +72,8 @@ class Kafka(Plugin):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _find_zookeeper_url():
|
def _find_zookeeper_url():
|
||||||
""" Pull the zookeeper url the kafka config.
|
"""Pull the zookeeper url the kafka config.
|
||||||
:return: Zookeeper url
|
:return: Zookeeper url
|
||||||
"""
|
"""
|
||||||
zk_connect = re.compile('zookeeper.connect=(.*)')
|
zk_connect = re.compile('zookeeper.connect=(.*)')
|
||||||
try:
|
try:
|
||||||
|
@ -84,9 +89,9 @@ class Kafka(Plugin):
|
||||||
return match.group(1).split(',')[0] # Only use the first zk url
|
return match.group(1).split(',')[0] # Only use the first zk url
|
||||||
|
|
||||||
def _ls_zookeeper(self, path):
|
def _ls_zookeeper(self, path):
|
||||||
""" Do a ls on the given zookeeper path.
|
"""Do a ls on the given zookeeper path.
|
||||||
I am using the local command line kafka rather than kazoo because it doesn't make sense to
|
I am using the local command line kafka rather than kazoo because it doesn't make sense to
|
||||||
have kazoo as a dependency only for detection.
|
have kazoo as a dependency only for detection.
|
||||||
"""
|
"""
|
||||||
zk_shell = ['/opt/kafka/bin/zookeeper-shell.sh', self.zk_url, 'ls', path]
|
zk_shell = ['/opt/kafka/bin/zookeeper-shell.sh', self.zk_url, 'ls', path]
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
|
import ConfigParser
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import ConfigParser
|
|
||||||
import monasca_setup.detection
|
|
||||||
import monasca_setup.agent_config
|
import monasca_setup.agent_config
|
||||||
|
import monasca_setup.detection
|
||||||
|
|
||||||
from distutils.version import LooseVersion
|
from distutils.version import LooseVersion
|
||||||
|
|
||||||
|
@ -101,9 +102,9 @@ class Libvirt(monasca_setup.detection.Plugin):
|
||||||
|
|
||||||
def dependencies_installed(self):
|
def dependencies_installed(self):
|
||||||
try:
|
try:
|
||||||
|
import novaclient
|
||||||
import time
|
import time
|
||||||
import yaml
|
import yaml
|
||||||
import novaclient
|
|
||||||
# novaclient module versions were renamed in version 2.22
|
# novaclient module versions were renamed in version 2.22
|
||||||
if novaclient.__version__ < LooseVersion("2.22"):
|
if novaclient.__version__ < LooseVersion("2.22"):
|
||||||
import novaclient.v1_1.client
|
import novaclient.v1_1.client
|
||||||
|
|
|
@ -37,7 +37,6 @@ class MKLivestatus(monasca_setup.detection.Plugin):
|
||||||
"""Search common Nagios/Icinga config file locations for mk_livestatus
|
"""Search common Nagios/Icinga config file locations for mk_livestatus
|
||||||
broker module socket path
|
broker module socket path
|
||||||
"""
|
"""
|
||||||
socket_path = None
|
|
||||||
# Search likely Nagios/Icinga config file locations
|
# Search likely Nagios/Icinga config file locations
|
||||||
for cfg_file in nagios_cfg_files:
|
for cfg_file in nagios_cfg_files:
|
||||||
if os.path.isfile(cfg_file):
|
if os.path.isfile(cfg_file):
|
||||||
|
|
|
@ -9,7 +9,8 @@ import yaml
|
||||||
|
|
||||||
import monasca_setup.agent_config
|
import monasca_setup.agent_config
|
||||||
import monasca_setup.detection
|
import monasca_setup.detection
|
||||||
from monasca_setup.detection import find_process_cmdline, watch_process
|
from monasca_setup.detection import find_process_cmdline
|
||||||
|
from monasca_setup.detection import watch_process
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
@ -38,7 +39,6 @@ class MonAPI(monasca_setup.detection.Plugin):
|
||||||
def build_config(self):
|
def build_config(self):
|
||||||
"""Build the config as a Plugins object and return."""
|
"""Build the config as a Plugins object and return."""
|
||||||
log.info("\tEnabling the Monasca api healthcheck")
|
log.info("\tEnabling the Monasca api healthcheck")
|
||||||
admin_port = self.api_config['server']['adminConnectors'][0]['port']
|
|
||||||
config = monasca_setup.agent_config.Plugins()
|
config = monasca_setup.agent_config.Plugins()
|
||||||
config.merge(dropwizard_health_check('monitoring', 'api', 'http://localhost:8081/healthcheck'))
|
config.merge(dropwizard_health_check('monitoring', 'api', 'http://localhost:8081/healthcheck'))
|
||||||
|
|
||||||
|
|
|
@ -38,8 +38,8 @@ class MySQL(monasca_setup.detection.Plugin):
|
||||||
# Attempt login, requires either an empty root password from localhost
|
# Attempt login, requires either an empty root password from localhost
|
||||||
# or relying on a configured /root/.my.cnf
|
# or relying on a configured /root/.my.cnf
|
||||||
if self.dependencies_installed(): # ensures MySQLdb is available
|
if self.dependencies_installed(): # ensures MySQLdb is available
|
||||||
import MySQLdb
|
|
||||||
import _mysql_exceptions
|
import _mysql_exceptions
|
||||||
|
import MySQLdb
|
||||||
try:
|
try:
|
||||||
MySQLdb.connect(read_default_file=mysql_conf)
|
MySQLdb.connect(read_default_file=mysql_conf)
|
||||||
except _mysql_exceptions.MySQLError:
|
except _mysql_exceptions.MySQLError:
|
||||||
|
|
|
@ -13,7 +13,7 @@ class Ovsvapp(monasca_setup.detection.ServicePlugin):
|
||||||
'template_dir': template_dir,
|
'template_dir': template_dir,
|
||||||
'overwrite': overwrite,
|
'overwrite': overwrite,
|
||||||
'service_name': 'OVSvApp-ServiceVM',
|
'service_name': 'OVSvApp-ServiceVM',
|
||||||
'process_names': ['neutron-ovsvapp-agent', 'ovsdb-server','ovs-vswitchd'],
|
'process_names': ['neutron-ovsvapp-agent', 'ovsdb-server', 'ovs-vswitchd'],
|
||||||
'service_api_url': '',
|
'service_api_url': '',
|
||||||
'search_pattern': ''
|
'search_pattern': ''
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ class Postfix(monasca_setup.detection.Plugin):
|
||||||
"""
|
"""
|
||||||
if monasca_setup.detection.find_process_cmdline('postfix') is not None:
|
if monasca_setup.detection.find_process_cmdline('postfix') is not None:
|
||||||
# Test for sudo access
|
# Test for sudo access
|
||||||
# TODO: don't hardcode the user. Need to get it from the arguments to monasca_setup
|
# TODO(craig): don't hardcode the user. Need to get it from the arguments to monasca_setup
|
||||||
test_sudo = os.system('sudo -l -U mon-agent find /var/spool/postfix/incoming -type f > /dev/null')
|
test_sudo = os.system('sudo -l -U mon-agent find /var/spool/postfix/incoming -type f > /dev/null')
|
||||||
if test_sudo != 0:
|
if test_sudo != 0:
|
||||||
log.info("Postfix found but the required sudo access is not configured.\n\t" +
|
log.info("Postfix found but the required sudo access is not configured.\n\t" +
|
||||||
|
|
|
@ -41,7 +41,7 @@ class RabbitMQ(monasca_setup.detection.Plugin):
|
||||||
self.available = True
|
self.available = True
|
||||||
|
|
||||||
def _get_config(self):
|
def _get_config(self):
|
||||||
""" Set the configuration to be used for connecting to rabbitmq
|
"""Set the configuration to be used for connecting to rabbitmq
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
# Set defaults and read config or use arguments
|
# Set defaults and read config or use arguments
|
||||||
|
@ -63,7 +63,7 @@ class RabbitMQ(monasca_setup.detection.Plugin):
|
||||||
self.exchanges = self.args.get('exchanges')
|
self.exchanges = self.args.get('exchanges')
|
||||||
|
|
||||||
def _login_test(self):
|
def _login_test(self):
|
||||||
""" Attempt to log into the rabbitmq admin api to verify credentials.
|
"""Attempt to log into the rabbitmq admin api to verify credentials.
|
||||||
:return: bool status of the test
|
:return: bool status of the test
|
||||||
"""
|
"""
|
||||||
url = self.api_url + '/aliveness-test/%2F'
|
url = self.api_url + '/aliveness-test/%2F'
|
||||||
|
@ -84,7 +84,7 @@ class RabbitMQ(monasca_setup.detection.Plugin):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _read_config(self, config_file):
|
def _read_config(self, config_file):
|
||||||
""" Read the configuration setting member variables as appropriate.
|
"""Read the configuration setting member variables as appropriate.
|
||||||
:param config_file: The filename of the configuration to read and parse
|
:param config_file: The filename of the configuration to read and parse
|
||||||
"""
|
"""
|
||||||
# Read the rabbitmq config file to extract the needed variables.
|
# Read the rabbitmq config file to extract the needed variables.
|
||||||
|
|
|
@ -2,8 +2,8 @@ import logging
|
||||||
import os
|
import os
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
from monasca_setup.detection import Plugin
|
|
||||||
from monasca_setup import agent_config
|
from monasca_setup import agent_config
|
||||||
|
from monasca_setup.detection import Plugin
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
|
@ -62,8 +62,8 @@ class ServicePlugin(Plugin):
|
||||||
host, port = parsed.netloc.split(':')
|
host, port = parsed.netloc.split(':')
|
||||||
listening = []
|
listening = []
|
||||||
for connection in psutil.net_connections():
|
for connection in psutil.net_connections():
|
||||||
if connection.status == psutil.CONN_LISTEN and connection.laddr[1] == int(port):
|
if connection.status == psutil.CONN_LISTEN and connection.laddr[1] == int(port):
|
||||||
listening.append(connection.laddr[0])
|
listening.append(connection.laddr[0])
|
||||||
|
|
||||||
if len(listening) > 0:
|
if len(listening) > 0:
|
||||||
# If not listening on localhost or ips then use another local ip
|
# If not listening on localhost or ips then use another local ip
|
||||||
|
@ -75,7 +75,7 @@ class ServicePlugin(Plugin):
|
||||||
# Setup an active http_status check on the API
|
# Setup an active http_status check on the API
|
||||||
log.info("\tConfiguring an http_check for the {0} API.".format(self.service_name))
|
log.info("\tConfiguring an http_check for the {0} API.".format(self.service_name))
|
||||||
config.merge(service_api_check(self.service_name + '-api', api_url,
|
config.merge(service_api_check(self.service_name + '-api', api_url,
|
||||||
self.search_pattern, self.service_name))
|
self.search_pattern, self.service_name))
|
||||||
else:
|
else:
|
||||||
log.info("\tNo process found listening on {0} ".format(port) +
|
log.info("\tNo process found listening on {0} ".format(port) +
|
||||||
"skipping setup of http_check for the {0} API." .format(self.service_name))
|
"skipping setup of http_check for the {0} API." .format(self.service_name))
|
||||||
|
|
|
@ -2,7 +2,9 @@
|
||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
import subprocess
|
import subprocess
|
||||||
from subprocess import Popen, PIPE, CalledProcessError
|
from subprocess import CalledProcessError
|
||||||
|
from subprocess import PIPE
|
||||||
|
from subprocess import Popen
|
||||||
|
|
||||||
import psutil
|
import psutil
|
||||||
|
|
||||||
|
|
|
@ -89,7 +89,7 @@ def main(argv=None):
|
||||||
|
|
||||||
|
|
||||||
def base_configuration(args):
|
def base_configuration(args):
|
||||||
""" Write out the primary Agent configuration and setup the service.
|
"""Write out the primary Agent configuration and setup the service.
|
||||||
:param args: Arguments from the command line
|
:param args: Arguments from the command line
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
|
@ -203,7 +203,7 @@ def parse_arguments(parser):
|
||||||
|
|
||||||
|
|
||||||
def plugin_detection(plugins, template_dir, detection_args, skip_failed=True):
|
def plugin_detection(plugins, template_dir, detection_args, skip_failed=True):
|
||||||
""" Runs the detection step for each plugin in the list and returns the complete detected agent config.
|
"""Runs the detection step for each plugin in the list and returns the complete detected agent config.
|
||||||
:param plugins: A list of detection plugin classes
|
:param plugins: A list of detection plugin classes
|
||||||
:param template_dir: Location of plugin configuration templates
|
:param template_dir: Location of plugin configuration templates
|
||||||
:param detection_args: Arguments passed to each detection plugin
|
:param detection_args: Arguments passed to each detection plugin
|
||||||
|
@ -228,8 +228,8 @@ def plugin_detection(plugins, template_dir, detection_args, skip_failed=True):
|
||||||
|
|
||||||
|
|
||||||
def remove_config(args, plugin_names):
|
def remove_config(args, plugin_names):
|
||||||
""" Parse all configuration removing any configuration built by plugins in plugin_names
|
"""Parse all configuration removing any configuration built by plugins in plugin_names
|
||||||
Note there is no concept of overwrite for removal.
|
Note there is no concept of overwrite for removal.
|
||||||
:param args: specified arguments
|
:param args: specified arguments
|
||||||
:param plugin_names: A list of the plugin names to remove from the config
|
:param plugin_names: A list of the plugin names to remove from the config
|
||||||
:return: True if changes, false otherwise
|
:return: True if changes, false otherwise
|
||||||
|
|
|
@ -9,8 +9,8 @@ log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def detect_init(*args, **kwargs):
|
def detect_init(*args, **kwargs):
|
||||||
""" Detect the service manager running on this box
|
"""Detect the service manager running on this box
|
||||||
args/kwargs match those of service.Service
|
args/kwargs match those of service.Service
|
||||||
:return: The apropriate Service object for this system
|
:return: The apropriate Service object for this system
|
||||||
"""
|
"""
|
||||||
detected_os = platform.system()
|
detected_os = platform.system()
|
||||||
|
@ -29,7 +29,7 @@ def detect_init(*args, **kwargs):
|
||||||
|
|
||||||
|
|
||||||
def detect_linux_init(*args, **kwargs):
|
def detect_linux_init(*args, **kwargs):
|
||||||
""" Detect which of the linux inits is running
|
"""Detect which of the linux inits is running
|
||||||
:return: Return a valid Linux service manager object
|
:return: Return a valid Linux service manager object
|
||||||
"""
|
"""
|
||||||
with open('/proc/1/comm', 'r') as init_proc:
|
with open('/proc/1/comm', 'r') as init_proc:
|
||||||
|
|
|
@ -13,10 +13,10 @@ log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class LinuxInit(service.Service):
|
class LinuxInit(service.Service):
|
||||||
""" Parent class for all Linux based init systems.
|
"""Parent class for all Linux based init systems.
|
||||||
"""
|
"""
|
||||||
def enable(self):
|
def enable(self):
|
||||||
""" Does user/group directory creation.
|
"""Does user/group directory creation.
|
||||||
"""
|
"""
|
||||||
# Create user/group if needed
|
# Create user/group if needed
|
||||||
try:
|
try:
|
||||||
|
@ -29,7 +29,7 @@ class LinuxInit(service.Service):
|
||||||
# todo log dir is hardcoded
|
# todo log dir is hardcoded
|
||||||
for path in (self.log_dir, self.config_dir, '%s/conf.d' % self.config_dir):
|
for path in (self.log_dir, self.config_dir, '%s/conf.d' % self.config_dir):
|
||||||
if not os.path.exists(path):
|
if not os.path.exists(path):
|
||||||
os.makedirs(path, 0755)
|
os.makedirs(path, 0o755)
|
||||||
os.chown(path, 0, user.pw_gid)
|
os.chown(path, 0, user.pw_gid)
|
||||||
# the log dir needs to be writable by the user
|
# the log dir needs to be writable by the user
|
||||||
os.chown(self.log_dir, user.pw_uid, user.pw_gid)
|
os.chown(self.log_dir, user.pw_uid, user.pw_gid)
|
||||||
|
@ -66,7 +66,7 @@ class Systemd(LinuxInit):
|
||||||
service_script.write(template.read().format(prefix=self.prefix_dir, monasca_user=self.username,
|
service_script.write(template.read().format(prefix=self.prefix_dir, monasca_user=self.username,
|
||||||
config_dir=self.config_dir))
|
config_dir=self.config_dir))
|
||||||
os.chown(init_path, 0, 0)
|
os.chown(init_path, 0, 0)
|
||||||
os.chmod(init_path, 0644)
|
os.chmod(init_path, 0o644)
|
||||||
|
|
||||||
# Enable the service
|
# Enable the service
|
||||||
subprocess.check_call(['systemctl', 'daemon-reload'])
|
subprocess.check_call(['systemctl', 'daemon-reload'])
|
||||||
|
@ -128,7 +128,7 @@ class SysV(LinuxInit):
|
||||||
conf.write(template.read().format(prefix=self.prefix_dir, monasca_user=self.username,
|
conf.write(template.read().format(prefix=self.prefix_dir, monasca_user=self.username,
|
||||||
config_dir=self.config_dir))
|
config_dir=self.config_dir))
|
||||||
os.chown(self.init_script, 0, 0)
|
os.chown(self.init_script, 0, 0)
|
||||||
os.chmod(self.init_script, 0755)
|
os.chmod(self.init_script, 0o755)
|
||||||
|
|
||||||
for runlevel in ['2', '3', '4', '5']:
|
for runlevel in ['2', '3', '4', '5']:
|
||||||
link_path = '/etc/rc%s.d/S10monasca-agent' % runlevel
|
link_path = '/etc/rc%s.d/S10monasca-agent' % runlevel
|
||||||
|
|
|
@ -12,7 +12,7 @@ log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def discover_plugins(custom_path):
|
def discover_plugins(custom_path):
|
||||||
""" Find and import all detection plugins. It will look in detection/plugins dir of the code as well as custom_path
|
"""Find and import all detection plugins. It will look in detection/plugins dir of the code as well as custom_path
|
||||||
|
|
||||||
:param custom_path: An additional path to search for detection plugins
|
:param custom_path: An additional path to search for detection plugins
|
||||||
:return: A list of imported detection plugin classes.
|
:return: A list of imported detection plugin classes.
|
||||||
|
@ -44,10 +44,9 @@ def discover_plugins(custom_path):
|
||||||
|
|
||||||
|
|
||||||
def select_plugins(plugin_names, plugin_list):
|
def select_plugins(plugin_names, plugin_list):
|
||||||
"""
|
""":param plugin_names: A list of names
|
||||||
:param plugin_names: A list of names
|
:param plugin_list: A list of detection plugins classes
|
||||||
:param plugin_list: A list of detection plugins classes
|
:return: Returns a list of plugins from plugin_list that match plugin_names
|
||||||
:return: Returns a list of plugins from plugin_list that match plugin_names
|
|
||||||
"""
|
"""
|
||||||
lower_plugins = [p.lower() for p in plugin_names]
|
lower_plugins = [p.lower() for p in plugin_names]
|
||||||
plugins = []
|
plugins = []
|
||||||
|
@ -64,8 +63,8 @@ def select_plugins(plugin_names, plugin_list):
|
||||||
|
|
||||||
|
|
||||||
def write_template(template_path, out_path, variables, group, is_yaml=False):
|
def write_template(template_path, out_path, variables, group, is_yaml=False):
|
||||||
""" Write a file using a simple python string template.
|
"""Write a file using a simple python string template.
|
||||||
Assumes 640 for the permissions and root:group for ownership.
|
Assumes 640 for the permissions and root:group for ownership.
|
||||||
:param template_path: Location of the Template to use
|
:param template_path: Location of the Template to use
|
||||||
:param out_path: Location of the file to write
|
:param out_path: Location of the file to write
|
||||||
:param variables: dictionary with key/value pairs to use in writing the template
|
:param variables: dictionary with key/value pairs to use in writing the template
|
||||||
|
@ -85,4 +84,4 @@ def write_template(template_path, out_path, variables, group, is_yaml=False):
|
||||||
else:
|
else:
|
||||||
conf.write(contents)
|
conf.write(contents)
|
||||||
os.chown(out_path, 0, group)
|
os.chown(out_path, 0, group)
|
||||||
os.chmod(out_path, 0640)
|
os.chmod(out_path, 0o640)
|
||||||
|
|
|
@ -1,2 +1,3 @@
|
||||||
hacking>=0.9.2,<0.10
|
hacking>=0.10.2
|
||||||
|
flake8>=2.2.4
|
||||||
nose==1.3.0
|
nose==1.3.0
|
||||||
|
|
7
tox.ini
7
tox.ini
|
@ -21,11 +21,14 @@ commands = {posargs}
|
||||||
|
|
||||||
[flake8]
|
[flake8]
|
||||||
max-line-length = 120
|
max-line-length = 120
|
||||||
|
max-complexity = 30
|
||||||
# TODO: ignored checks should be enabled in the future
|
# TODO: ignored checks should be enabled in the future
|
||||||
# E501 Line length > 80 characters
|
# E501 Line length > 80 characters
|
||||||
# F401 module imported but unused
|
# F401 module imported but unused
|
||||||
# H302 import only modules
|
# H302 import only modules
|
||||||
# H904 Wrap long lines in parentheses instead of a backslash (DEPRECATED)
|
# H904 Wrap long lines in parentheses instead of a backslash (DEPRECATED)
|
||||||
ignore = E501, F401, H302, H904,
|
# H405 Multiline docstring separated by empty line
|
||||||
|
# H105 Don't use author tags
|
||||||
|
ignore = E501,F401,H302,H904,H803,H405,H105
|
||||||
show-source = True
|
show-source = True
|
||||||
exclude=.venv,.git,.tox,dist,*egg,build
|
exclude=.venv,.git,.tox,dist,*egg,build,tests
|
||||||
|
|
Loading…
Reference in New Issue