Skip to content

Commit

Permalink
Add telemetrySupported field to environmentSettings (#140)
Browse files Browse the repository at this point in the history
  • Loading branch information
benank authored Jun 15, 2022
1 parent 698f4fa commit 6dc345e
Show file tree
Hide file tree
Showing 26 changed files with 189 additions and 268 deletions.
7 changes: 4 additions & 3 deletions src/core/src/bootstrap/Bootstrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ def __init__(self, argv, capture_stdout=True):
self.current_env = self.get_current_env()
self.argv = argv
self.auto_assessment_only = bool(self.get_value_from_argv(self.argv, Constants.ARG_AUTO_ASSESS_ONLY, "False") == "True")
self.log_file_path, self.real_record_path, self.events_folder = self.get_path_to_log_files_and_telemetry_dir(argv, self.auto_assessment_only)
self.log_file_path, self.real_record_path, self.events_folder, self.telemetry_supported = self.get_path_to_log_files_and_telemetry_dir(argv, self.auto_assessment_only)
self.recorder_enabled, self.emulator_enabled = self.get_recorder_emulator_flags(argv)

# Container initialization
print("Building bootstrap container configuration...")
self.configuration_factory = ConfigurationFactory(self.log_file_path, self.real_record_path, self.recorder_enabled, self.emulator_enabled, self.events_folder)
self.configuration_factory = ConfigurationFactory(self.log_file_path, self.real_record_path, self.recorder_enabled, self.emulator_enabled, self.events_folder, self.telemetry_supported)
self.container = Container()
self.container.build(self.configuration_factory.get_bootstrap_configuration(self.current_env))

Expand Down Expand Up @@ -73,7 +73,8 @@ def get_path_to_log_files_and_telemetry_dir(self, argv, auto_assessment_only):
log_file_path = os.path.join(log_folder, str(sequence_number) + exec_demarcator + ".core.log")
real_rec_path = os.path.join(log_folder, str(sequence_number) + exec_demarcator + ".core.rec")
events_folder = environment_settings[Constants.EnvSettings.EVENTS_FOLDER] # can throw exception and that's okay (since we can't recover from this)
return log_file_path, real_rec_path, events_folder
telemetry_supported = environment_settings[Constants.EnvSettings.TELEMETRY_SUPPORTED]
return log_file_path, real_rec_path, events_folder, telemetry_supported

def reset_auto_assessment_log_file_if_needed(self):
""" Deletes the auto assessment log file when needed to prevent excessive growth """
Expand Down
13 changes: 7 additions & 6 deletions src/core/src/bootstrap/ConfigurationFactory.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,14 @@ class ConfigurationFactory(object):
""" Class for generating module definitions. Configuration is list of key value pairs. Please DON'T change key name.
DI container relies on the key name to find and resolve dependencies. If you do need change it, please make sure to
update the key name in all places that reference it. """
def __init__(self, log_file_path, real_record_path, recorder_enabled, emulator_enabled, events_folder):
def __init__(self, log_file_path, real_record_path, recorder_enabled, emulator_enabled, events_folder, telemetry_supported):
self.vm_cloud_type = self.get_vm_cloud_type()
self.lifecycle_manager_component = self.get_lifecycle_manager_component(self.vm_cloud_type)

self.bootstrap_configurations = {
'prod_config': self.new_bootstrap_configuration(Constants.PROD, log_file_path, real_record_path, recorder_enabled, emulator_enabled, events_folder),
'dev_config': self.new_bootstrap_configuration(Constants.DEV, log_file_path, real_record_path, recorder_enabled, emulator_enabled, events_folder),
'test_config': self.new_bootstrap_configuration(Constants.TEST, log_file_path, real_record_path, recorder_enabled, emulator_enabled, events_folder)
'prod_config': self.new_bootstrap_configuration(Constants.PROD, log_file_path, real_record_path, recorder_enabled, emulator_enabled, events_folder, telemetry_supported),
'dev_config': self.new_bootstrap_configuration(Constants.DEV, log_file_path, real_record_path, recorder_enabled, emulator_enabled, events_folder, telemetry_supported),
'test_config': self.new_bootstrap_configuration(Constants.TEST, log_file_path, real_record_path, recorder_enabled, emulator_enabled, events_folder, telemetry_supported)
}

self.configurations = {
Expand Down Expand Up @@ -123,7 +123,7 @@ def get_configuration(self, env, package_manager_name):

# region - Configuration Builders
@staticmethod
def new_bootstrap_configuration(config_env, log_file_path, real_record_path, recorder_enabled, emulator_enabled, events_folder):
def new_bootstrap_configuration(config_env, log_file_path, real_record_path, recorder_enabled, emulator_enabled, events_folder, telemetry_supported):
""" Core configuration definition. """
configuration = {
'config_env': config_env,
Expand Down Expand Up @@ -155,7 +155,8 @@ def new_bootstrap_configuration(config_env, log_file_path, real_record_path, rec
'component': TelemetryWriter,
'component_args': ['env_layer', 'composite_logger'],
'component_kwargs': {
'events_folder_path': events_folder
'events_folder_path': events_folder,
'telemetry_supported': telemetry_supported
}
},
}
Expand Down
12 changes: 3 additions & 9 deletions src/core/src/bootstrap/Constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class EnvSettings(EnumBackport):
CONFIG_FOLDER = "configFolder"
STATUS_FOLDER = "statusFolder"
EVENTS_FOLDER = "eventsFolder"
TELEMETRY_SUPPORTED = "telemetrySupported"

class ConfigSettings(EnumBackport):
OPERATION = 'operation'
Expand Down Expand Up @@ -246,8 +247,6 @@ class PatchOperationErrorCodes(EnumBackport):
TELEMETRY_EVENT_COUNTER_MSG_SIZE_LIMIT_IN_CHARS = 15 # buffer for telemetry event counter text added at the end of every message sent to telemetry
TELEMETRY_MAX_EVENT_COUNT_THROTTLE = 60
TELEMETRY_MAX_TIME_IN_SECONDS_FOR_EVENT_COUNT_THROTTLE = 60
AZURE_GUEST_AGENT_EXTENSION_SUPPORTED_FEATURES_ENV_VAR = 'AZURE_GUEST_AGENT_EXTENSION_SUPPORTED_FEATURES'
TELEMETRY_EXTENSION_PIPELINE_SUPPORTED_KEY = 'ExtensionTelemetryPipeline'

# Telemetry Event Level
class TelemetryEventLevel(EnumBackport):
Expand All @@ -265,8 +264,8 @@ class TelemetryTaskName(EnumBackport):
EXEC = "Core.Exec" # mainline execution triggered from handler
AUTO_ASSESSMENT = "Core.AutoAssessment" # auto-assessment triggered from scheduler

TELEMETRY_AT_AGENT_NOT_COMPATIBLE_ERROR_MSG = "Unsupported older Azure Linux Agent version. To resolve: http://aka.ms/UpdateLinuxAgent"
TELEMETRY_AT_AGENT_COMPATIBLE_MSG = "Minimum Azure Linux Agent version prerequisite met"
TELEMETRY_NOT_COMPATIBLE_ERROR_MSG = "Unsupported older Azure Linux Agent version. To resolve: http://aka.ms/UpdateLinuxAgent"
TELEMETRY_COMPATIBLE_MSG = "Minimum Azure Linux Agent version prerequisite met"

UTC_DATETIME_FORMAT = "%Y-%m-%dT%H:%M:%SZ"

Expand All @@ -276,8 +275,3 @@ class EnvLayer(EnumBackport):
PRIVILEGED_OP_REBOOT = PRIVILEGED_OP_MARKER + "Reboot_Exception"
PRIVILEGED_OP_EXIT = PRIVILEGED_OP_MARKER + "Exit_"

# These are numbers instead of strings like extension because they are customer facing in the error message diagnostics
class AgentEnvVarStatusCode(EnumBackport):
AGENT_ENABLED = 0
FAILED_TO_GET_AGENT_SUPPORTED_FEATURES = 1
FAILED_TO_GET_TELEMETRY_KEY = 2
12 changes: 6 additions & 6 deletions src/core/src/core_logic/ConfigurePatchingProcessor.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def start_configure_patching(self):
""" Start configure patching """
try:
self.status_handler.set_current_operation(Constants.CONFIGURE_PATCHING)
self.__raise_if_agent_incompatible()
self.__raise_if_telemetry_unsupported()
self.composite_logger.log('\nStarting configure patching...')

self.__report_consolidated_configure_patch_status(status=Constants.STATUS_TRANSITIONING)
Expand Down Expand Up @@ -136,12 +136,12 @@ def __report_consolidated_configure_patch_status(self, status=Constants.STATUS_T
automatic_os_patch_state=self.current_auto_os_patch_state,
auto_assessment_state=self.current_auto_assessment_state)

def __raise_if_agent_incompatible(self):
def __raise_if_telemetry_unsupported(self):
if self.lifecycle_manager.get_vm_cloud_type() == Constants.VMCloudType.ARC and self.execution_config.operation not in [Constants.ASSESSMENT, Constants.INSTALLATION]:
self.composite_logger.log("Skipping agent compatibility check for Arc cloud type when operation is not manual")
self.composite_logger.log("Skipping telemetry compatibility check for Arc cloud type when operation is not manual")
return
if not self.telemetry_writer.is_agent_compatible():
error_msg = "{0} [{1}]".format(Constants.TELEMETRY_AT_AGENT_NOT_COMPATIBLE_ERROR_MSG, self.telemetry_writer.get_telemetry_diagnostics())
if not self.telemetry_writer.is_telemetry_supported():
error_msg = "{0}".format(Constants.TELEMETRY_NOT_COMPATIBLE_ERROR_MSG)
raise Exception(error_msg)

self.composite_logger.log("{0} [{1}]".format(Constants.TELEMETRY_AT_AGENT_COMPATIBLE_MSG, self.telemetry_writer.get_telemetry_diagnostics()))
self.composite_logger.log("{0}".format(Constants.TELEMETRY_COMPATIBLE_MSG))
1 change: 1 addition & 0 deletions src/core/src/core_logic/ExecutionConfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ def __init__(self, env_layer, composite_logger, execution_parameters):
self.config_folder = self.environment_settings[Constants.EnvSettings.CONFIG_FOLDER]
self.status_folder = self.environment_settings[Constants.EnvSettings.STATUS_FOLDER]
self.events_folder = self.environment_settings[Constants.EnvSettings.EVENTS_FOLDER]
self.telemetry_supported = self.environment_settings[Constants.EnvSettings.TELEMETRY_SUPPORTED]

# Config Settings
self.composite_logger.log_debug(" - Parsing configuration settings... [ConfigSettings={0}]".format(str(self.config_settings)))
Expand Down
12 changes: 6 additions & 6 deletions src/core/src/core_logic/PatchAssessor.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def __init__(self, env_layer, execution_config, composite_logger, telemetry_writ
def start_assessment(self):
""" Start a patch assessment """
self.status_handler.set_current_operation(Constants.ASSESSMENT)
self.raise_if_agent_incompatible()
self.raise_if_telemetry_unsupported()

self.composite_logger.log('\nStarting patch assessment...')

Expand Down Expand Up @@ -79,15 +79,15 @@ def start_assessment(self):
self.composite_logger.log("\nPatch assessment completed.\n")
return True

def raise_if_agent_incompatible(self):
def raise_if_telemetry_unsupported(self):
if self.lifecycle_manager.get_vm_cloud_type() == Constants.VMCloudType.ARC and self.execution_config.operation not in [Constants.ASSESSMENT, Constants.INSTALLATION]:
self.composite_logger.log("Skipping agent compatibility check for Arc cloud type when operation is not manual")
self.composite_logger.log("Skipping telemetry compatibility check for Arc cloud type when operation is not manual")
return
if not self.telemetry_writer.is_agent_compatible():
error_msg = "{0} [{1}]".format(Constants.TELEMETRY_AT_AGENT_NOT_COMPATIBLE_ERROR_MSG, self.telemetry_writer.get_telemetry_diagnostics())
if not self.telemetry_writer.is_telemetry_supported():
error_msg = "{0}".format(Constants.TELEMETRY_NOT_COMPATIBLE_ERROR_MSG)
self.composite_logger.log_error(error_msg)
self.status_handler.set_assessment_substatus_json(status=Constants.STATUS_ERROR)
raise Exception(error_msg)

self.composite_logger.log("{0} [{1}]".format(Constants.TELEMETRY_AT_AGENT_COMPATIBLE_MSG, self.telemetry_writer.get_telemetry_diagnostics()))
self.composite_logger.log("{0}".format(Constants.TELEMETRY_COMPATIBLE_MSG))

12 changes: 6 additions & 6 deletions src/core/src/core_logic/PatchInstaller.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ def __init__(self, env_layer, execution_config, composite_logger, telemetry_writ
def start_installation(self, simulate=False):
""" Kick off a patch installation run """
self.status_handler.set_current_operation(Constants.INSTALLATION)
self.raise_if_agent_incompatible()
self.raise_if_telemetry_unsupported()

self.composite_logger.log('\nStarting patch installation...')

Expand Down Expand Up @@ -98,16 +98,16 @@ def start_installation(self, simulate=False):

return overall_patch_installation_successful

def raise_if_agent_incompatible(self):
def raise_if_telemetry_unsupported(self):
if self.lifecycle_manager.get_vm_cloud_type() == Constants.VMCloudType.ARC and self.execution_config.operation not in [Constants.ASSESSMENT, Constants.INSTALLATION]:
self.composite_logger.log("Skipping agent compatibility check for Arc cloud type when operation is not manual")
self.composite_logger.log("Skipping telemetry compatibility check for Arc cloud type when operation is not manual")
return
if not self.telemetry_writer.is_agent_compatible():
error_msg = "{0} [{1}]".format(Constants.TELEMETRY_AT_AGENT_NOT_COMPATIBLE_ERROR_MSG, self.telemetry_writer.get_telemetry_diagnostics())
if not self.telemetry_writer.is_telemetry_supported():
error_msg = "{0}".format(Constants.TELEMETRY_NOT_COMPATIBLE_ERROR_MSG)
self.composite_logger.log_error(error_msg)
raise Exception(error_msg)

self.composite_logger.log("{0} [{1}]".format(Constants.TELEMETRY_AT_AGENT_COMPATIBLE_MSG, self.telemetry_writer.get_telemetry_diagnostics()))
self.composite_logger.log("{0}".format(Constants.TELEMETRY_COMPATIBLE_MSG))

def install_updates(self, maintenance_window, package_manager, simulate=False):
"""wrapper function of installing updates"""
Expand Down
9 changes: 1 addition & 8 deletions src/core/src/service_interfaces/StatusHandler.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,6 @@ def __init__(self, env_layer, execution_config, composite_logger, telemetry_writ

self.__current_operation = None

# If an error message is any of these strings, it ignores the length limit (STATUS_ERROR_MSG_SIZE_LIMIT_IN_CHARACTERS)
self.__ignore_error_message_restriction_compliance_strings = [Constants.TELEMETRY_AT_AGENT_NOT_COMPATIBLE_ERROR_MSG]

# Update patch metadata summary in status for auto patching installation requests, to be reported to healthstore
if (execution_config.maintenance_run_id is not None or execution_config.health_store_id is not None) and execution_config.operation.lower() == Constants.INSTALLATION.lower():
if self.__installation_reboot_status != Constants.RebootStatus.STARTED:
Expand Down Expand Up @@ -718,11 +715,7 @@ def __ensure_error_message_restriction_compliance(self, full_message):
""" Removes line breaks, tabs and restricts message to a character limit """
message_size_limit = Constants.STATUS_ERROR_MSG_SIZE_LIMIT_IN_CHARACTERS
formatted_message = re.sub(r"\s+", " ", str(full_message))
ignore_message_restriction = any(ignore_string in formatted_message for ignore_string in self.__ignore_error_message_restriction_compliance_strings)
if ignore_message_restriction is False:
return formatted_message[:message_size_limit - 3] + '...' if len(formatted_message) > message_size_limit else formatted_message
else:
return formatted_message
return formatted_message[:message_size_limit - 3] + '...' if len(formatted_message) > message_size_limit else formatted_message

@staticmethod
def __try_add_error(error_list, detail):
Expand Down
Loading

0 comments on commit 6dc345e

Please sign in to comment.