def enable()

in AzureMonitorAgent/agent.py [0:0]


def enable():
    """
    Start the Azure Monitor Linux Agent Service
    This call will return non-zero or throw an exception if
    the settings provided are incomplete or incorrect.
    Note: enable operation times out from WAAgent at 5 minutes
    """

    public_settings, protected_settings = get_settings()

    exit_if_vm_not_supported('Enable')

    ensure = OrderedDict([
        ("azuremonitoragent", False),
        ("azuremonitoragentmgr", False)
    ])

    # Set traceFlags in publicSettings to enable mdsd tracing. For example, the EventIngest flag can be enabled via "traceFlags": "0x2"
    flags = ""
    if public_settings is not None and "traceFlags" in public_settings:
        flags = "-T {} ".format(public_settings.get("traceFlags"))

    # Use an Ordered Dictionary to ensure MDSD_OPTIONS (and other dependent variables) are written after their dependencies
    default_configs = OrderedDict([
        ("MDSD_CONFIG_DIR", "/etc/opt/microsoft/azuremonitoragent"),
        ("MDSD_LOG_DIR", "/var/opt/microsoft/azuremonitoragent/log"),
        ("MDSD_ROLE_PREFIX", "/run/azuremonitoragent/default"),
        ("MDSD_SPOOL_DIRECTORY", "/var/opt/microsoft/azuremonitoragent"),
        ("MDSD_OPTIONS", "\"{}-A -R -c /etc/opt/microsoft/azuremonitoragent/mdsd.xml -d -r $MDSD_ROLE_PREFIX -S $MDSD_SPOOL_DIRECTORY/eh -L $MDSD_SPOOL_DIRECTORY/events\"".format(flags)),
        ("MDSD_USE_LOCAL_PERSISTENCY", "true"),
        ("MDSD_TCMALLOC_RELEASE_FREQ_SEC", "1"),
        ("MONITORING_USE_GENEVA_CONFIG_SERVICE", "false"),
        ("ENABLE_MCS", "false")
    ])

    ssl_cert_var_name, ssl_cert_var_value = get_ssl_cert_info('Enable')
    default_configs[ssl_cert_var_name] = ssl_cert_var_value

    """
    Decide the mode and configuration. There are two supported configuration schema, mix-and-match between schemas is disallowed:
        Legacy:          allows one of [MCS, GCS single tenant, or GCS multi tenant ("Auto-Config")] modes
        Next-Generation: allows MCS, GCS multi tenant, or both
    """
    is_gcs_single_tenant = False
    GcsEnabled, McsEnabled = get_control_plane_mode()

    # Next-generation schema
    if public_settings is not None and (public_settings.get(GenevaConfigKey) or public_settings.get(AzureMonitorConfigKey)):

        geneva_configuration = public_settings.get(GenevaConfigKey)
        azure_monitor_configuration = public_settings.get(AzureMonitorConfigKey)

        # Check for mix-and match of next-generation and legacy schema content
        if len(public_settings) > 1 and ((geneva_configuration and not azure_monitor_configuration) or (azure_monitor_configuration and not geneva_configuration)):
            log_and_exit("Enable", MissingorInvalidParameterErrorCode, 'Mixing genevaConfiguration or azureMonitorConfiguration with other configuration schemas is not allowed')

        if geneva_configuration and geneva_configuration.get("enable") == True:
            hutil_log_info("Detected Geneva+ mode; azuremonitoragentmgr service will be started to handle Geneva tenants")
            ensure["azuremonitoragentmgr"] = True
            
        if azure_monitor_configuration and azure_monitor_configuration.get("enable") == True:
            hutil_log_info("Detected Azure Monitor+ mode; azuremonitoragent service will be started to handle Azure Monitor tenant")
            ensure["azuremonitoragent"] = True
            azure_monitor_public_settings = azure_monitor_configuration.get("configuration")
            azure_monitor_protected_settings = protected_settings.get(AzureMonitorConfigKey) if protected_settings is not None else None
            handle_mcs_config(azure_monitor_public_settings, azure_monitor_protected_settings, default_configs)

    # Legacy schema
    elif public_settings is not None and public_settings.get("GCS_AUTO_CONFIG") == True:
        hutil_log_info("Detected Auto-Config mode; azuremonitoragentmgr service will be started to handle Geneva tenants")
        ensure["azuremonitoragentmgr"] = True
                
    elif (protected_settings is None or len(protected_settings) == 0) or (public_settings is not None and "proxy" in public_settings and "mode" in public_settings.get("proxy") and public_settings.get("proxy").get("mode") == "application"):
        hutil_log_info("Detected Azure Monitor mode; azuremonitoragent service will be started to handle Azure Monitor configuration")
        ensure["azuremonitoragent"] = True
        handle_mcs_config(public_settings, protected_settings, default_configs)

    else:
        hutil_log_info("Detected Geneva mode; azuremonitoragent service will be started to handle Geneva configuration")
        ensure["azuremonitoragent"] = True
        is_gcs_single_tenant = True
        handle_gcs_config(public_settings, protected_settings, default_configs)
        
    # generate local syslog configuration files as in auto config syslog is not driven from DCR
    # Note that internally AMCS with geneva config path can be used in which case syslog should be handled same way as default 1P
    # generate local syslog configuration files as in 1P syslog is not driven from DCR
    if GcsEnabled:
        generate_localsyslog_configs(uses_gcs=True, uses_mcs=McsEnabled)

    config_file = "/etc/default/azuremonitoragent"
    temp_config_file = "/etc/default/azuremonitoragent_temp"

    try:
        if os.path.isfile(config_file):
            new_config = "\n".join(["export {0}={1}".format(key, value) for key, value in default_configs.items()]) + "\n"

            with open(temp_config_file, "w") as f:
                f.write(new_config)

            if not os.path.isfile(temp_config_file):
                log_and_exit("Enable", GenericErrorCode, "Error while updating environment variables in {0}".format(config_file))

            os.remove(config_file)
            os.rename(temp_config_file, config_file)            
        else:
            log_and_exit("Enable", GenericErrorCode, "Could not find the file {0}".format(config_file))
    except Exception as e:
        log_and_exit("Enable", GenericErrorCode, "Failed to add environment variables to {0}: {1}".format(config_file, e))

    if "ENABLE_MCS" in default_configs and default_configs["ENABLE_MCS"] == "true":
        # enable processes for Custom Logs
        ensure["azuremonitor-agentlauncher"] = True
        ensure["azuremonitor-coreagent"] = True
            
        # start the metrics, agent transform and syslog watchers only in 3P mode
        start_metrics_process()
        start_syslogconfig_process()
    elif ensure.get("azuremonitoragentmgr") or is_gcs_single_tenant:
        # In GCS scenarios, ensure that AMACoreAgent is running
        ensure["azuremonitor-coreagent"] = True

    hutil_log_info('Handler initiating onboarding.')

    if HUtilObject and HUtilObject.is_seq_smaller():
        # Either upgrade has just happened (in which case we need to start), or enable was called with no change to extension config
        hutil_log_info("Current sequence number, " + HUtilObject._context._seq_no + ", is not greater than the LKG sequence number. Starting service(s) only if it is not yet running.")
        operations = ["start", "enable"]
    else:
        # Either this is a clean install (in which case restart is effectively start), or extension config has changed
        hutil_log_info("Current sequence number, " + HUtilObject._context._seq_no + ", is greater than the LKG sequence number. Restarting service(s) to pick up the new config.")
        operations = ["restart", "enable"]

    output = ""

    # Ensure non-required services are not running; do not block if this step fails
    for service in [s for s in ensure.keys() if not ensure[s]]:
        exit_code, disable_output = run_command_and_log(get_service_command(service, "stop", "disable"))
        output += disable_output

    for service in [s for s in ensure.keys() if ensure[s]]:
        exit_code, enable_output = run_command_and_log(get_service_command(service, *operations))
        output += enable_output

        if exit_code != 0:
            status_command = get_service_command(service, "status")
            status_exit_code, status_output = run_command_and_log(status_command)

            if status_exit_code != 0:
                output += "Output of '{0}':\n{1}".format(status_command, status_output)
                return exit_code, output

    if platform.machine() != 'aarch64':
        if "ENABLE_MCS" in default_configs and default_configs["ENABLE_MCS"] == "true":
            # start/enable kql extension only in 3P mode and non aarch64
            kql_start_code, kql_output = run_command_and_log(get_service_command("azuremonitor-kqlextension", *operations))
            output += kql_output # do not block if kql start fails
            # start transformation config watcher process
            start_transformconfig_process()

    # Service(s) were successfully configured and started; increment sequence number
    HUtilObject.save_seq()

    return exit_code, output