Пример #1
0
def main(argv=None):
    parser = argparse.ArgumentParser(description='Configure and setup the agent. In a full run it will detect running' +
                                                 ' daemons then configure and start the agent.',
                                     formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    args = parse_arguments(parser)

    if args.verbose:
        logging.basicConfig(level=logging.DEBUG, format="%(levelname)s: %(message)s")
    else:
        logging.basicConfig(level=logging.INFO, format="%(levelname)s: %(message)s")

    if args.dry_run:
        log.info("Running in dry run mode, no changes will be made only reported")

    # Detect and if possibly enable the agent service
    agent_service = detect_init(PREFIX_DIR, args.config_dir, args.log_dir, args.template_dir, username=args.user)

    # Skip base setup if only installing plugins or running specific detection
    # plugins
    if not args.install_plugins_only and args.detection_plugins is None:
        if not args.skip_enable:
            agent_service.enable()

        # Verify required options
        if args.username is None or args.password is None or args.keystone_url is None:
            log.error('Username, password and keystone_url are required when running full configuration.')
            parser.print_help()
            sys.exit(1)
        base_configuration(args)

    # Collect the set of detection plugins to run
    detected_plugins = utils.discover_plugins(CUSTOM_PLUGIN_PATH)
    if args.system_only:
        from detection.plugins.system import System
        plugins = [System]
    elif args.detection_plugins is not None:
        plugins = utils.select_plugins(args.detection_plugins, detected_plugins)
    else:
        plugins = detected_plugins
    plugin_names = [p.__name__ for p in plugins]

    if args.remove:  # Remove entries for each plugin from the various plugin config files
        changes = remove_config(args, plugin_names)
    else:
        # Run detection for all the plugins, halting on any failures if plugins were specified in the arguments
        detected_config = plugin_detection(plugins, args.template_dir, args.detection_args,
                                           skip_failed=(args.detection_plugins is None))
        if detected_config is None:
            return 1  # Indicates detection problem, skip remaining steps and give non-zero exit code

        changes = modify_config(args, detected_config)

    # Don't restart if only doing detection plugins and no changes found
    if args.detection_plugins is not None and not changes:
        log.info('No changes found for plugins {0}, skipping restart of Monasca Agent'.format(plugin_names))
        return 0
    elif args.dry_run:
        log.info('Running in dry mode, skipping changes and restart of Monasca Agent')
        return 0

    # Now that the config is built, start the service
    if args.install_plugins_only:
        log.info('Command line option install_plugins_only set, skipping '
                 'service (re)start.')
    else:
        try:
            agent_service.start(restart=True)
        except subprocess.CalledProcessError:
            log.error('The service did not startup correctly see %s' % args.log_dir)
Пример #2
0
def main(argv=None):
    parser = argparse.ArgumentParser(
        description=
        'Configure and setup the agent. In a full run it will detect running' +
        ' daemons then configure and start the agent.',
        formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    args = parse_arguments(parser)

    if args.verbose:
        logging.basicConfig(level=logging.DEBUG,
                            format="%(levelname)s: %(message)s")
    else:
        logging.basicConfig(level=logging.INFO,
                            format="%(levelname)s: %(message)s")

    if args.dry_run:
        log.info(
            "Running in dry run mode, no changes will be made only reported")

    # Detect and if possibly enable the agent service
    agent_service = detect_init(PREFIX_DIR,
                                args.config_dir,
                                args.log_dir,
                                args.template_dir,
                                username=args.user)

    # Skip base setup if only installing plugins or running specific detection
    # plugins
    if not args.install_plugins_only and args.detection_plugins is None:
        if not args.skip_enable:
            agent_service.enable()

        # Verify required options
        if args.username is None or args.password is None or args.keystone_url is None:
            log.error(
                'Username, password and keystone_url are required when running full configuration.'
            )
            parser.print_help()
            sys.exit(1)
        base_configuration(args)

    # Collect the set of detection plugins to run
    detected_plugins = utils.discover_plugins(CUSTOM_PLUGIN_PATH)
    if args.system_only:
        from detection.plugins.system import System
        plugins = [System]
    elif args.detection_plugins is not None:
        plugins = utils.select_plugins(args.detection_plugins,
                                       detected_plugins)
    elif args.skip_detection_plugins is not None:
        plugins = utils.select_plugins(args.skip_detection_plugins,
                                       detected_plugins,
                                       skip=True)
    else:
        plugins = detected_plugins
    plugin_names = [p.__name__ for p in plugins]

    if args.remove:  # Remove entries for each plugin from the various plugin config files
        changes = remove_config(args, plugin_names)
    else:
        # Run detection for all the plugins, halting on any failures if plugins were specified in the arguments
        detected_config = plugin_detection(
            plugins,
            args.template_dir,
            args.detection_args,
            skip_failed=(args.detection_plugins is None))
        if detected_config is None:
            return 1  # Indicates detection problem, skip remaining steps and give non-zero exit code

        changes = modify_config(args, detected_config)

    # Don't restart if only doing detection plugins and no changes found
    if args.detection_plugins is not None and not changes:
        log.info(
            'No changes found for plugins {0}, skipping restart of Monasca Agent'
            .format(plugin_names))
        return 0
    elif args.dry_run:
        log.info(
            'Running in dry mode, skipping changes and restart of Monasca Agent'
        )
        return 0

    # Now that the config is built, start the service
    if args.install_plugins_only:
        log.info('Command line option install_plugins_only set, skipping '
                 'service (re)start.')
    else:
        try:
            agent_service.start(restart=True)
        except subprocess.CalledProcessError:
            log.error('The service did not startup correctly see %s' %
                      args.log_dir)
Пример #3
0
def main(argv=None):
    parser = argparse.ArgumentParser(description='Configure and setup the agent. In a full run it will detect running' +
                                                 ' daemons then configure and start the agent.',
                                     formatter_class=argparse.ArgumentDefaultsHelpFormatter)
    parser.add_argument(
        '-u', '--username', help="Username used for keystone authentication. Required for basic configuration.")
    parser.add_argument(
        '-p', '--password', help="Password used for keystone authentication. Required for basic configuration.")
    parser.add_argument('--keystone_url', help="Keystone url. Required for basic configuration.")
    parser.add_argument('--project_name', help="Project name for keystone authentication", default='')
    parser.add_argument('--project_domain_id', help="Project domain id for keystone authentication", default='')
    parser.add_argument('--project_domain_name', help="Project domain name for keystone authentication", default='')
    parser.add_argument('--project_id', help="Keystone project id  for keystone authentication", default='')
    parser.add_argument('--monasca_url', help="Monasca API url, if not defined the url is pulled from keystone",
                        default='')
    parser.add_argument('--system_only', help="Setup the service but only configure the base config and system " +
                                              "metrics (cpu, disk, load, memory, network).",
                        action="store_true", default=False)
    parser.add_argument('-d', '--detection_plugins', nargs='*',
                        help="Skip base config and service setup and only configure this space separated list. " +
                             "This assumes the base config has already run.")
    parser.add_argument('-a', '--detection_args', help="A string of arguments that will be passed to detection " +
                                                       "plugins. Only certain detection plugins use arguments.")
    parser.add_argument('--check_frequency', help="How often to run metric collection in seconds", type=int, default=30)
    parser.add_argument('--dimensions', help="Additional dimensions to set for all metrics. A comma seperated list " +
                                             "of name/value pairs, 'name:value,name2:value2'")
    parser.add_argument('--ca_file', help="Sets the path to the ca certs file if using certificates. " +
                                          "Required only if insecure is set to False", default='')
    parser.add_argument('--insecure', help="Set whether certificates are used for Keystone authentication",
                        default=False)
    parser.add_argument('--config_dir', help="Configuration directory", default='/etc/monasca/agent')
    parser.add_argument('--log_dir', help="monasca-agent log directory", default='/var/log/monasca/agent')
    parser.add_argument('--log_level', help="monasca-agent logging level (ERROR, WARNING, INFO, DEBUG)", required=False,
                        default='WARN')
    parser.add_argument( '--template_dir', help="Alternative template directory",
                         default=os.path.join(PREFIX_DIR, 'share/monasca/agent'))
    parser.add_argument('--overwrite',
                        help="Overwrite existing plugin configuration. " +
                             "The default is to merge. agent.yaml is always overwritten.",
                        action="store_true")
    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")
    parser.add_argument('--user', help="User name to run monasca-agent as", default='mon-agent')
    parser.add_argument('-s', '--service', help="Service this node is associated with, added as a dimension.")
    parser.add_argument('--amplifier', help="Integer for the number of additional measurements to create. " +
                                            "Additional measurements contain the 'amplifier' dimension. " +
                                            "Useful for load testing; not for production use.", default=0)
    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 and if possibly enable the agent service
    agent_service = detect_init(PREFIX_DIR, args.config_dir, args.log_dir, args.template_dir, username=args.user)

    if args.detection_plugins is None:  # Skip base setup if running specific detection plugins
        # Verify required options
        if args.username is None or args.password is None or args.keystone_url is None:
            log.error('Username, password and keystone_url are required when running full configuration.')
            parser.print_help()
            sys.exit(1)
        if not args.skip_enable:
            agent_service.enable()

        gid = pwd.getpwnam(args.user).pw_gid
        # Write the main agent.yaml - Note this is always overwritten
        log.info('Configuring base Agent settings.')
        dimensions = {}
        # Join service in with the dimensions
        if args.service:
            dimensions.update({'service': args.service})
        if args.dimensions:
            dimensions.update(dict(item.strip().split(":") for item in args.dimensions.split(",")))

        args.dimensions = dict((name, value) for (name, value) in dimensions.iteritems())
        write_template(os.path.join(args.template_dir, 'agent.yaml.template'),
                       os.path.join(args.config_dir, 'agent.yaml'),
                       {'args': args, 'hostname': socket.getfqdn()},
                       gid,
                       is_yaml=True)

        # Write the supervisor.conf
        write_template(os.path.join(args.template_dir, 'supervisor.conf.template'),
                       os.path.join(args.config_dir, 'supervisor.conf'),
                       {'prefix': PREFIX_DIR, 'log_dir': args.log_dir, 'monasca_user': args.user},
                       gid)

    # Run through detection and config building for the plugins
    plugin_config = agent_config.Plugins()
    detected_plugins = find_plugins(CUSTOM_PLUGIN_PATH)
    if args.system_only:
        from detection.plugins.system import System
        plugins = [System]
    elif args.detection_plugins is not None:
        lower_plugins = [p.lower() for p in args.detection_plugins]
        plugins = []
        for plugin in detected_plugins:
            if plugin.__name__.lower() in lower_plugins:
                plugins.append(plugin)

        if len(plugins) != len(args.detection_plugins):
            plugin_names = [p.__name__ for p in detected_plugins]
            log.warn("Not all plugins found, discovered plugins {0}\nAvailable plugins{1}".format(plugins,
                                                                                                  plugin_names))
    else:
        plugins = detected_plugins

    for detect_class in plugins:
        detect = detect_class(args.template_dir, args.overwrite, args.detection_args)
        if detect.available:
            log.info('Configuring {0}'.format(detect.name))
            new_config = detect.build_config()
            if new_config is not None:
                plugin_config.merge(new_config)
        elif args.detection_plugins is not None:  # Give a warning on failed detection when a plugin is called out
            log.warn('Failed detection of plugin {0}.'.format(detect.name) +
                     "\n\tPossible causes: Service not found or missing arguments.")

    # todo add option to install dependencies

    # Write out the plugin config
    changes = False
    # The gid is created on service activation which we assume has happened before this step or before running with -d
    gid = pwd.getpwnam(args.user).pw_gid
    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
        config_path = os.path.join(args.config_dir, 'conf.d', key + '.yaml')
        # merge old and new config, new has precedence
        if (not args.overwrite) and os.path.exists(config_path):
            with open(config_path, 'r') as config_file:
                old_config = yaml.load(config_file.read())
            if old_config is not None:
                agent_config.merge_by_name(value['instances'], old_config['instances'])
                # Sort before compare, if instances have no name the sort will fail making order changes significant
                try:
                    value['instances'].sort(key=lambda k: k['name'])
                    old_config['instances'].sort(key=lambda k: k['name'])
                except Exception:
                    pass
                if value == old_config:  # Don't write config if no change
                    continue
        with open(config_path, 'w') as config_file:
            changes = True
            os.chmod(config_path, 0640)
            os.chown(config_path, 0, gid)
            config_file.write(yaml.safe_dump(value,
                                             encoding='utf-8',
                                             allow_unicode=True,
                                             default_flow_style=False))

    # Don't restart if only doing detection plugins and no changes found
    if args.detection_plugins is not None and not changes:
        plugin_names = [p.__name__ for p in plugins]
        log.info('No changes found for plugins {0}, skipping restart of Monasca Agent'.format(plugin_names))
        return 0

    # Now that the config is built, start the service
    try:
        agent_service.start(restart=True)
    except subprocess.CalledProcessError:
        log.error('The service did not startup correctly see %s' % args.log_dir)