monasca-agent/monasca_setup/detection/plugins/congestion.py
Fouad Benamrane 08ac1308b8 Add network congestion detection to monasca
To allow monasca detecting network congestion, we add a new agent plugin for monasca-agent
module based on Explicit Congestion Notification (ECN) tos bits. The agent will create a
map between the number of Congestion Encountered(CE) packets/bytes and the source ip address
responsible of the congestion. The source could be a compute or (if activated) a set of VMs
deployed in a compute. First, we ensure that ECN marking is enabled for both edges. Second,
we check ecn.packets and ecn.bytes and calculate ecn.cong.rate associated to each source of
congestion. Last, the agent sends the three metrics and their timestamp to monasca API for
any further processing and keeps the metric counters into a cache file. This piece of
information could be used to trigger a new kind of performance alarm in monasca threshold.

Change-Id: I98405524588582065c7825ca511c489d59826cda
Task: 5750
Story: 2001234
2017-12-01 17:20:30 +01:00

101 lines
3.8 KiB
Python

# Copyright 2017 OrangeLabs
import ConfigParser
import logging
from monasca_agent.common.psutil_wrapper import psutil
import monasca_setup.agent_config
import monasca_setup.detection
import os
log = logging.getLogger(__name__)
# Directory to use for metric caches
cache_dir = "/dev/shm"
# Enable vm congestion check
enable_vm = True
# Ensure that ECN marking is enabled
enable_ecn = True
# Smoothing factor used to compute ecn congestion rate
s_factor = 0.1
# Period of time in second to collect metrics
collect_period = 30
# Acceptable arguments
acceptable_args = ['username', 'password', 'project_name',
'auth_url', 'cache_dir', 'enable_vm', 'enable_ecn',
'region_name', 's_factor', 'collect_period']
class Congestion(monasca_setup.detection.Plugin):
"""Configures congestion detection plugin."""
def _detect(self):
"""Run detection, set self.available True if the service is
detected.
"""
self.available = True
# Start with plugin-specific configuration parameters
# Try to detect the location of the Nova configuration file.
# Walk through the list of processes, searching for 'nova-compute'
# process with 'nova.conf' inside one of the parameters
nova_conf = None
for proc in psutil.process_iter():
try:
cmd = proc.as_dict(['cmdline'])['cmdline']
if (len(cmd) > 2 and 'python' in cmd[0] and
'nova-compute' in cmd[1]):
conf_indexes = [cmd.index(y)
for y in cmd if 'nova.conf' in y]
if not conf_indexes:
continue
param = conf_indexes[0]
if '=' in cmd[param]:
nova_conf = cmd[param].split('=')[1]
else:
nova_conf = cmd[param]
except (IOError, psutil.NoSuchProcess):
# Process has already terminated, ignore
continue
if (nova_conf is not None and os.path.isfile(nova_conf)):
self.available = True
self.nova_conf = nova_conf
def build_config(self):
"""Build the config as a Plugins object and return. """
config = monasca_setup.agent_config.Plugins()
log.info("Configuring congestion plugin")
nova_cfg = ConfigParser.SafeConfigParser()
log.info("\tUsing nova configuration file {0}".format(self.nova_conf))
nova_cfg.read(self.nova_conf)
# Which configuration options are needed for the plugin YAML?
# Use a dict so that they can be renamed later if necessary
cfg_needed = {
'username': 'username', 'password': 'password',
'project_name': 'project_name'}
cfg_section = 'keystone_authtoken'
region_name_sec = 'neutron'
init_config = {
'cache_dir': cache_dir,
'enable_vm': enable_vm,
'enable_ecn': enable_ecn,
's_factor': s_factor,
'collect_period': collect_period}
for option in cfg_needed:
init_config[option] = nova_cfg.get(
cfg_section, cfg_needed[option])
init_config['region_name'] = nova_cfg.get(
region_name_sec, 'region_name')
# Create an identity URI (again, slightly different for Devstack)
if nova_cfg.has_option(cfg_section, 'auth_url'):
init_config['auth_url'] = nova_cfg.get(cfg_section, 'auth_url')
else:
init_config['auth_url'] = nova_cfg.get(
cfg_section, 'identity_uri')
config = monasca_setup.agent_config.Plugins()
config['congestion'] = {
'init_config': init_config, 'instances': []}
return config
def dependencies_installed(self):
return True