def main()

in src/setup.py [0:0]


def main():
    CMD = namedtuple("cmd", "cmd, msg")
    COLLECTD_INFO = get_collectd_info()
    STOP_COLLECTD_CMD = CMD("pkill collectd", "Stopping collectd process")
    START_COLLECTD_CMD = CMD(COLLECTD_INFO.exec_path, "Starting collectd process")
    DOWNLOAD_PLUGIN_CMD = CMD("curl -sL https://github.com/" + GITHUB_USER_NAME + "/collectd-cloudwatch/tarball/" + GITHUB_REPO_BRANCH + " > " + TAR_FILE, "Downloading plugin")
    UNTAR_PLUGIN_CMD = CMD("tar zxf " + TAR_FILE, "Extracting plugin")
    COPY_CMD = "\cp -rf {source} {target}"
    COPY_PLUGIN_CMD = CMD(COPY_CMD.format(source=NEW_PLUGIN_FILES, target=CollectdInfo.PLUGINS_DIR), "Moving to collectd plugins directory")
    COPY_PLUGIN_INCLUDE_FILE_CMD = CMD(COPY_CMD.format(source=PLUGIN_INCLUDE_CONFIGURATION, target="/etc/"), "Copying CloudWatch plugin include file")
    COPY_RECOMMENDED_COLLECTD_CONFIG_CMD = CMD(COPY_CMD.format(source=RECOMMENDED_COLLECTD_CONFIGURATION, target=COLLECTD_INFO.config_path), "Replacing collectd configuration")
    BACKUP_COLLECTD_CONFIG_CMD = CMD(COPY_CMD.format(source=COLLECTD_INFO.config_path, target=COLLECTD_INFO.config_path + "." + time.strftime(TIMESTAMP_FORMAT)),
                                 "Creating backup of the original configuration")
    REPLACE_WHITELIST_CMD = CMD(COPY_CMD.format(source=RECOMMENDED_WHITELIST, target=DEFAULT_PLUGIN_CONFIGURATION_DIR), "Replacing whitelist configuration")

    parser = argparse.ArgumentParser(
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
        description='Script for custom installation process for collectd AWS CloudWatch plugin'
    )
    parser.add_argument(
        '-I', '--non_interactive', required=False,
        help='Non interactive mode',
        default=False, action='store_true'
    )
    parser.add_argument(
        '-H', '--host_name', required=False,
        help='Manual override for EC2 Instance ID and Host information propagated by collectd',
        metavar='HOST_NAME', default=None
    )
    parser.add_argument(
        '-r', '--region', required=False,
        help='Manual override for region used to publish metrics',
        metavar='REGION', default=None
    )
    parser.add_argument(
        '-n', '--proxy_name', required=False,
        help='Proxy server name',
        metavar='NAME', default=None
    )
    parser.add_argument(
        '-p', '--proxy_port', required=False,
        help='Proxy server port',
        metavar='PORT', default=None
    )
    parser.add_argument(
        '-e', '--enable_high_resolution_metrics', required=False,
        help='Enable high resolution metrics',
        default=False, action='store_true'
    )
    parser.add_argument(
        '-f', '--flush_interval', required=False,
        help='Flush interval (in seconds)',
        metavar='FLUSH_INTERVAL', default=None
    )
    parser.add_argument(
        '-a', '--access_key', required=False,
        help='AWS IAM user access key',
        metavar='ACCESS_KEY', default=None
    )
    parser.add_argument(
        '-s', '--secret_key', required=False,
        help='AWS IAM user secret key',
        metavar='SECRET_KEY', default=None
    )
    parser.add_argument(
        '-P', '--creds_path', required=False,
        help='Absolute path to AWS credentials file',
        metavar='CREDENTIALS_PATH', default=None
    )
    parser.add_argument(
        '-m', '--installation_method', required=False,
        help='Choose how to install CloudWatch plugin in collectd',
        choices=['recommended', 'add', 'not_modify'],
        metavar='recommended|add|not_modify', default=None
    )
    parser.add_argument(
        '-g', '--push_asg', required=False,
        help='Include the Auto-Scaling Group name as a metric dimension:',
        default=False, action='store_true'
    )
    parser.add_argument(
        '-c', '--push_constant', required=False,
        help='Include the FixedDimension as a metric dimension',
        default=None, action='store_true'
    )
    parser.add_argument(
        '-v', '--dimension_value', required=False,
        help='FixedDimension value',
        metavar='DIMENSION_VALUE', default=None
    )
    parser.add_argument(
        '-d', '--debug', default=False,
        action='store_true', help='Provides verbose logging of metrics emitted to CloudWatch'
    )
    parser.add_argument(
        '-D', '--debug_setup', default=False,
        action='store_true', help='Provides verbose logging during setup process'
    )
    args = parser.parse_args()

    if args.proxy_port is None and args.proxy_name or args.proxy_port and args.proxy_name is None:
        parser.error('To enable proxy, use both --proxy_name and --proxy_port ')

    if args.access_key is None and args.secret_key or args.access_key and args.secret_key is None:
        parser.error('For IAM credentials, use both --secret_key and --access_key')

    if args.push_constant is None and args.dimension_value:
        parser.error('To include the FixedDimension as a metric dimension, '
                     'use both --push_constant and --dimension_value')

    if args.creds_path and args.secret_key is None and args.access_key is None:
        parser.error('Credential path (--creds_path) used only with --secret_key and --access_key arguments')

    non_interactive = args.non_interactive
    host = args.host_name
    region = args.region
    proxy_name = args.proxy_name
    proxy_port = args.proxy_port
    enable_high_resolution_metrics = args.enable_high_resolution_metrics
    flush_interval = args.flush_interval
    access_key = args.access_key
    secret_key = args.secret_key
    creds_path = args.creds_path
    installation_method = args.installation_method
    push_asg = args.push_asg
    push_constant = args.push_constant
    dimension_value = args.dimension_value
    debug_setup = args.debug_setup
    debug = args.debug

    def install_plugin():
        try:
            # "python-pip", "python-setuptools" will pull in the python2.6 runtime 
            # Since python with version >= 2.7 should install pip and setuptools by default, we 
            # can ignore the system dependencies
            if not ( is_pip_installed() and is_setupTools_installed() ):
                install_packages(["python-pip", "python-setuptools"])
            install_python_packages(PYTHON_DEPENDENCIES)
            create_directory_structure()
            chdir(TEMP_DIRECTORY)
            _run_command(DOWNLOAD_PLUGIN_CMD, shell=True, exit_on_failure=True)
            _run_command(UNTAR_PLUGIN_CMD, exit_on_failure=True)
            _run_command(COPY_PLUGIN_CMD, shell=True, exit_on_failure=True)
            supply_config()
            restart_collectd()
        finally:
            remove_temp_dir()

    def create_directory_structure():
        try:
            make_dirs(TEMP_DIRECTORY)
            make_dirs(CollectdInfo.PLUGINS_DIR)
        except IOError:
            raise InstallationFailedException("Cannot create required directories.")

    def supply_config():
        if COLLECTD_INFO.is_supported_version():
            _run_command(COPY_PLUGIN_INCLUDE_FILE_CMD, shell=True)
            config = PluginConfig()
            _prepare_plugin_config(config)
            if config.use_recommended_collectd_config:
                _copy_recommended_configs()
            elif config.only_add_plugin:
                _inject_plugin_configuration()
            else:
                print Color.yellow("Please find instructions for the manual configuration of the plugin in the readme.md file.")
        else:
            raise InstallationFailedException("The minimum supported version of collectd is " + CollectdInfo.MIN_SUPPORTED_VERSION + \
                                              ", and your version is " + COLLECTD_INFO.version + \
                                              ". You need to upgrade collectd before proceeding with the plugin installation.")

    def _prepare_plugin_config(plugin_config):
        metadata_reader = MetadataReader()
        InteractiveConfigurator(plugin_config, metadata_reader, COLLECTD_INFO,
                                non_interactive, region, host, proxy_name,
                                proxy_port, enable_high_resolution_metrics,
                                flush_interval, access_key, secret_key,
                                creds_path, installation_method, push_asg,
                                push_constant, dimension_value, debug_setup,
                                debug).run()
        PluginConfigWriter(plugin_config).write()

    def _inject_plugin_configuration():
        if _is_cloudwatch_plugin_configured():
            print Color.yellow("CloudWatch collectd plugin is already configured in the existing collectd.conf file.")
        elif _can_safely_add_python_plugin():
            with open(COLLECTD_INFO.config_path, "a") as config:
                config.write(PLUGIN_CONFIGURATION_INCLUDE_LINE)
        else:
            print Color.yellow("Cannot add CloudWatch collectd plugin automatically to the existing collectd configuration.\n"
                               "Plugin must be configured manually, please find instructions in readme.md file.")

    def _copy_recommended_configs():
        _run_command(BACKUP_COLLECTD_CONFIG_CMD)
        _run_command(COPY_RECOMMENDED_COLLECTD_CONFIG_CMD, shell=True)
        _run_command(REPLACE_WHITELIST_CMD, shell=True)

    def _can_safely_add_python_plugin():
        configs = [COLLECTD_INFO.config_path]
        configs += _find_custom_includes(COLLECTD_INFO.config_path)
        return not any(_is_python_plugin_configured(config) for config in configs)

    def _is_cloudwatch_plugin_configured():
        with open(COLLECTD_INFO.config_path) as config:
            return bool(CLOUD_WATCH_COLLECTD_DETECTION_REGEX.findall(config.read()))

    def _find_custom_includes(config_path):
        with open(config_path) as config:
            return COLLECTD_CONFIG_INCLUDE_REGEX.findall(config.read())

    def _is_python_plugin_configured(config_path):
        with open(config_path) as config:
            return bool(COLLECTD_PYTHON_PLUGIN_CONFIGURATION_REGEX.findall(config.read()))

    def restart_collectd():
        _run_command(STOP_COLLECTD_CMD)
        _run_command(START_COLLECTD_CMD, exit_on_failure=True)

    def remove_temp_dir():
        shutil.rmtree(TEMP_DIRECTORY, ignore_errors=True)

    def _run_command(command, exit_on_failure=False, shell=False):
        Command(command.cmd, command.msg, shell=shell, exit_on_failure=exit_on_failure).run()

    install_plugin()