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