132 lines
6.3 KiB
Python
Raw Normal View History

#!/usr/bin/env python
""" Detect running daemons then configure and start the agent.
"""
import argparse
import logging
import os
2014-06-09 11:07:26 -06:00
import pwd
import socket
import subprocess
import sys
import yaml
2014-06-30 17:24:27 -06:00
from monagent.common.keystone import Keystone
import agent_config
2014-06-30 17:24:27 -06:00
from detection.plugins import kafka, mon, mysql, network, zookeeper, nova, glance, cinder, neutron, swift, ceilometer, keystone
from service import sysv
# List of all detection plugins to run
2014-06-13 21:13:04 -06:00
DETECTION_PLUGINS = [kafka.Kafka, mon.MonAPI, mon.MonPersister, mon.MonThresh, mysql.MySQL,
2014-06-30 17:24:27 -06:00
network.Network, nova.Nova, cinder.Cinder, swift.Swift, glance.Glance,
ceilometer.Ceilometer, neutron.Neutron, keystone.Keystone, zookeeper.Zookeeper]
# Map OS to service type
OS_SERVICE_MAP = {'linux': sysv.SysV}
log = logging.getLogger(__name__)
def main(argv=None):
2014-06-09 12:20:03 -06:00
parser = argparse.ArgumentParser(description='Detect running daemons then configure and start the agent.',
formatter_class=argparse.ArgumentDefaultsHelpFormatter)
parser.add_argument('-u', '--username', help="Keystone username used to post metrics", required=True)
parser.add_argument('-p', '--password', help="Keystone password used to post metrics", required=True)
parser.add_argument('--project_name', help="Keystone project/tenant name", required=True)
parser.add_argument('-s', '--service', help="Service this node is associated with.", required=True)
parser.add_argument('--keystone_url', help="Keystone url", required=True)
parser.add_argument('--mon_url', help="Mon API url", required=True)
2014-06-09 12:16:05 -06:00
parser.add_argument('--config_dir', help="Configuration directory", default='/etc/mon-agent')
parser.add_argument('--log_dir', help="mon-agent log directory", default='/var/log/mon-agent')
parser.add_argument('--template_dir', help="Alternative template directory", default='/usr/local/share/mon/agent')
parser.add_argument('--headless', help="Run in a non-interactive mode", action="store_true")
parser.add_argument('--overwrite',
help="Overwrite existing plugin configuration." +
"The default is to merge. Agent.conf is always overwritten.",
action="store_true")
2014-06-09 12:16:05 -06:00
parser.add_argument('--skip_enable', help="By default the service is enabled," +
" which requires the script run as root. Set this to skip that step.",
action="store_true")
2014-06-09 11:07:26 -06:00
parser.add_argument('--user', help="User name to run mon-agent as", default='mon-agent')
parser.add_argument('-v', '--verbose', help="Verbose Output", action="store_true")
args = parser.parse_args()
if args.verbose:
logging.basicConfig(level=logging.DEBUG, format="%(levelname)s: %(message)s")
else:
logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s")
# Detect os
detected_os = 'linux' # todo add detection
2014-06-10 12:47:30 -06:00
# Service enable, includes setup of users/config directories so must be done before configuration
2014-06-09 11:07:26 -06:00
agent_service = OS_SERVICE_MAP[detected_os](os.path.join(args.template_dir, 'mon-agent.init'), args.config_dir,
2014-06-09 12:16:05 -06:00
args.log_dir, username=args.user)
2014-06-10 09:39:47 -06:00
if not args.skip_enable:
2014-06-09 12:16:05 -06:00
agent_service.enable()
2014-06-10 12:47:30 -06:00
gid = pwd.getpwnam(args.user).pw_gid
# Write the main agent.conf - Note this is always overwritten
log.info('Configuring base Agent settings.')
2014-06-10 12:47:30 -06:00
agent_conf_path = os.path.join(args.config_dir, 'agent.conf')
with open(os.path.join(args.template_dir, 'agent.conf.template'), 'r') as agent_template:
2014-06-10 12:47:30 -06:00
with open(agent_conf_path, 'w') as agent_conf:
agent_conf.write(agent_template.read().format(args=args, hostname=socket.gethostname()))
2014-06-10 12:47:30 -06:00
os.chown(agent_conf_path, 0, gid)
os.chmod(agent_conf_path, 0640)
# Link the supervisor.conf
supervisor_path = os.path.join(args.config_dir, 'supervisor.conf')
if os.path.exists(supervisor_path):
os.remove(supervisor_path)
os.symlink(os.path.join(args.template_dir, 'supervisor.conf'), supervisor_path)
2014-06-30 17:24:27 -06:00
# Create the keystone object to use for alarm creation
token = None
try:
keystone = Keystone(args.keystone_url,
args.username,
args.password,
args.project_name)
token = keystone.get_token()
except:
log.exception('Unable to get Keystone Token, skipping alarm configuration...')
# Run through detection and config building for the plugins
plugin_config = agent_config.Plugins()
for detect_class in DETECTION_PLUGINS:
detect = detect_class(args.template_dir, args.overwrite)
if detect.available:
log.info('Configuring {0}'.format(detect.name))
new_config = detect.build_config()
plugin_config.merge(new_config)
2014-06-30 17:24:27 -06:00
if token and args.mon_url:
if not detect.configure_alarms(args.mon_url, token):
log.warn('Unable to configure alarms for {0}'.format(detect.name))
#todo add option to install dependencies
# Write out the plugin config
for key, value in plugin_config.iteritems():
# todo if overwrite is set I should either warn or just delete any config files not in the new config
# todo add the ability to show a diff before overwriting or merging config
config_path = os.path.join(args.config_dir, 'conf.d', key + '.yaml')
if (not args.overwrite) and os.path.exists(config_path): # merge old and new config, new has precedence
with open(config_path, 'r') as config_file:
old_config = yaml.load(config_file.read())
if old_config is not None:
2014-06-10 15:45:56 -06:00
agent_config.deep_merge(old_config, value)
value = old_config
with open(config_path, 'w') as config_file:
2014-06-09 11:07:26 -06:00
os.chmod(config_path, 0640)
2014-06-10 12:47:30 -06:00
os.chown(config_path, 0, gid)
config_file.write(yaml.dump(value))
# Now that the config is build start the service
try:
agent_service.start(restart=True)
except subprocess.CalledProcessError:
2014-06-09 12:16:05 -06:00
log.error('The service did not startup correctly see %s' % args.log_dir)
if __name__ == "__main__":
2014-06-30 17:24:27 -06:00
sys.exit(main())