def collect_ext_status(self, ext): self.logger.verbose("Collect extension status") seq_no, ext_status_file = self.get_status_file_path(ext) if seq_no == -1: return None ext_status = ExtensionStatus(seq_no=seq_no) try: data_str = fileutil.read_file(ext_status_file) data = json.loads(data_str) parse_ext_status(ext_status, data) except IOError as e: ext_status.message = u"Failed to get status file {0}".format(e) ext_status.code = -1 ext_status.status = "error" except ExtensionError as e: ext_status.message = u"Malformed status file {0}".format(e) ext_status.code = e.code ext_status.status = "error" except ValueError as e: ext_status.message = u"Malformed status file {0}".format(e) ext_status.code = -1 ext_status.status = "error" return ext_status
def test_parse_extension_status_with_empty_status(self): """ Parse a status report for a successful execution of an extension. """ # Validating empty status case s = '''[]''' ext_status = ExtensionStatus(seq_no=0) parse_ext_status(ext_status, json.loads(s)) self.assertEqual(None, ext_status.code) self.assertEqual(None, ext_status.configurationAppliedTime) self.assertEqual(None, ext_status.message) self.assertEqual(None, ext_status.operation) self.assertEqual(None, ext_status.status) self.assertEqual(0, ext_status.sequenceNumber) self.assertEqual(0, len(ext_status.substatusList)) # Validating None case ext_status = ExtensionStatus(seq_no=0) parse_ext_status(ext_status, None) self.assertEqual(None, ext_status.code) self.assertEqual(None, ext_status.configurationAppliedTime) self.assertEqual(None, ext_status.message) self.assertEqual(None, ext_status.operation) self.assertEqual(None, ext_status.status) self.assertEqual(0, ext_status.sequenceNumber) self.assertEqual(0, len(ext_status.substatusList))
def collect_ext_status(self, ext): self.logger.verbose("Collect extension status") seq_no = self.get_largest_seq_no() if seq_no == -1: return None status_dir = self.get_status_dir() ext_status_file = "{0}.status".format(seq_no) ext_status_file = os.path.join(status_dir, ext_status_file) ext_status = ExtensionStatus(seq_no=seq_no) try: data_str = fileutil.read_file(ext_status_file) data = json.loads(data_str) parse_ext_status(ext_status, data) except IOError as e: ext_status.message = u"Failed to get status file {0}".format(e) ext_status.code = -1 ext_status.status = "error" except (ExtensionError, ValueError) as e: ext_status.message = u"Malformed status file {0}".format(e) ext_status.code = -1 ext_status.status = "error" return ext_status
def test_parse_extension_status01(self): """ Parse a status report for a failed execution of an extension. The extension returned a bad status/status of failed. The agent should handle this gracefully, and convert all unknown status/status values into an error. """ s = '''[{ "status": { "status": "failed", "formattedMessage": { "lang": "en-US", "message": "Enable failed: Failed with error: commandToExecute is empty or invalid ..." }, "operation": "Enable", "code": "0", "name": "Microsoft.OSTCExtensions.CustomScriptForLinux" }, "version": "1.0", "timestampUTC": "2018-04-20T20:50:22Z" }]''' ext_status = ExtensionStatus(seq_no=0) parse_ext_status(ext_status, json.loads(s)) self.assertEqual('0', ext_status.code) self.assertEqual(None, ext_status.configurationAppliedTime) self.assertEqual( 'Enable failed: Failed with error: commandToExecute is empty or invalid ...', ext_status.message) self.assertEqual('Enable', ext_status.operation) self.assertEqual('error', ext_status.status) self.assertEqual(0, ext_status.sequenceNumber) self.assertEqual(0, len(ext_status.substatusList))
def test_parse_extension_status00(self): """ Parse a status report for a successful execution of an extension. """ s = '''[{ "status": { "status": "success", "formattedMessage": { "lang": "en-US", "message": "Command is finished." }, "operation": "Daemon", "code": "0", "name": "Microsoft.OSTCExtensions.CustomScriptForLinux" }, "version": "1.0", "timestampUTC": "2018-04-20T21:20:24Z" } ]''' ext_status = ExtensionStatus(seq_no=0) parse_ext_status(ext_status, json.loads(s)) self.assertEqual('0', ext_status.code) self.assertEqual(None, ext_status.configurationAppliedTime) self.assertEqual('Command is finished.', ext_status.message) self.assertEqual('Daemon', ext_status.operation) self.assertEqual('success', ext_status.status) self.assertEqual(0, ext_status.sequenceNumber) self.assertEqual(0, len(ext_status.substatusList))
def test_parse_ext_status_should_parse_missing_substatus_as_empty(self): status = '''[{ "status": { "status": "success", "formattedMessage": { "lang": "en-US", "message": "Command is finished." }, "operation": "Enable", "code": "0", "name": "Microsoft.OSTCExtensions.CustomScriptForLinux" }, "version": "1.0", "timestampUTC": "2018-04-20T21:20:24Z" } ]''' extension_status = ExtensionStatus(seq_no=0) parse_ext_status(extension_status, json.loads(status)) self.assertTrue(isinstance(extension_status.substatusList, list), 'substatus was not parsed correctly') self.assertEqual(0, len(extension_status.substatusList))
def collect_ext_status(self, ext): self.logger.verbose("Collect extension status") seq_no = self.get_largest_seq_no() if seq_no == -1: return None status_dir = self.get_status_dir() ext_status_file = "{0}.status".format(seq_no) ext_status_file = os.path.join(status_dir, ext_status_file) ext_status = ExtensionStatus(seq_no=seq_no) try: data_str = fileutil.read_file(ext_status_file) data = json.loads(data_str) parse_ext_status(ext_status, data) except IOError as e: ext_status.message = u"Failed to get status file {0}".format(e) ext_status.code = -1 ext_status.status = "error" except (ExtensionError, ValueError) as e: ext_status.message = u"Malformed status file {0}".format(e) ext_status.code = -1 ext_status.status = "error" return ext_status
def test_parse_ext_status_should_raise_on_non_array(self): status = json.loads(''' {{ "status": {{ "status": "transitioning", "operation": "Enabling Handler", "code": 0, "name": "Microsoft.Azure.RecoveryServices.SiteRecovery.Linux" }}, "version": 1.0, "timestampUTC": "2020-01-14T15:04:43Z", "longText": "{0}" }}'''.format("*" * 5 * 1024)) with self.assertRaises(ExtensionStatusError) as context_manager: parse_ext_status(ExtensionStatus(seq_no=0), status) error_message = str(context_manager.exception) self.assertIn("The extension status must be an array", error_message) self.assertTrue(0 < len(error_message) - 64 < 4096, "The error message should not be much longer than 4K characters: [{0}]".format(error_message))
def collect_ext_status(self, ext): # see github issue 1116 self.logger.verbose("Collect extension status") seq_no, ext_status_file = self.get_status_file_path() if seq_no == -1: return None ext_status = ExtensionStatus(seq_no=seq_no) try: data_str = fileutil.read_file(ext_status_file) data = json.loads(data_str) parse_ext_status(ext_status, data) except IOError as e: ext_status.message = u"Failed to get status file {0}".format(e) ext_status.code = -1 ext_status.status = "error" except (ExtensionError, ValueError) as e: ext_status.message = u"Malformed status file {0}".format(e) ext_status.code = -1 ext_status.status = "error" return ext_status
def test_add_extension_observation(self): handler_status = ExtHandlerStatus() handler_status.name = "Name" handler_status.version = "1.0" handler_status.code = 0 handler_status.status = "Unresponsive" healthObserver = ExtensionHealthObserver() healthObserver.add_extension_observation(handler_status, []) # validate that 2 observations were made - one for the handler version, and one for the handler being in a failed state self.assertEqual(2, len(healthObserver.partial_observations)) self.assertEqual( ExtensionHealthObserver.CONTEXT_OBSERVATION + handler_status.name, healthObserver.partial_observations[0].name) self.assertEqual(handler_status.version, healthObserver.partial_observations[0].value) self.assertEqual(True, healthObserver.partial_observations[0].is_healthy) # unhealthy handler self.assertEqual(handler_status.name, healthObserver.partial_observations[1].name) self.assertEqual(False, healthObserver.partial_observations[1].is_healthy) handler_status.status = "Ready" healthObserver = ExtensionHealthObserver() healthObserver.add_extension_observation(handler_status, []) # validate that 2 observations were made - one for the handler version, and one for the handler being in a failed state self.assertEqual(2, len(healthObserver.partial_observations)) self.assertEqual( ExtensionHealthObserver.CONTEXT_OBSERVATION + handler_status.name, healthObserver.partial_observations[0].name) self.assertEqual(handler_status.version, healthObserver.partial_observations[0].value) self.assertEqual(True, healthObserver.partial_observations[0].is_healthy) # healthy handler self.assertEqual(handler_status.name, healthObserver.partial_observations[1].name) self.assertEqual(True, healthObserver.partial_observations[1].is_healthy) # add in an extension status ext_status = ExtensionStatus(seq_no=0) ext_status.status = "Error" ext_status.code = 0 healthObserver = ExtensionHealthObserver() healthObserver.add_extension_observation(handler_status, [ext_status]) # validate that 3 observations were made - one for the handler version, and one for the handler being in a success state, and one for # the extension self.assertEqual(3, len(healthObserver.partial_observations)) # unhealthy extension self.assertEqual( handler_status.name + ExtensionHealthObserver.STATUS_SUFFIX, healthObserver.partial_observations[2].name) self.assertEqual(False, healthObserver.partial_observations[2].is_healthy) ext_status.status = "Succeeded" healthObserver = ExtensionHealthObserver() healthObserver.add_extension_observation(handler_status, [ext_status]) # validate that 3 observations were made - one for the handler version, and one for the handler being in a success state, and one for # the extension self.assertEqual(3, len(healthObserver.partial_observations)) # healthy extension self.assertEqual( handler_status.name + ExtensionHealthObserver.STATUS_SUFFIX, healthObserver.partial_observations[2].name) self.assertEqual(True, healthObserver.partial_observations[2].is_healthy) substatus = ExtensionSubStatus() substatus.code = 0 substatus.status = "Error" ext_status.substatusList.append(substatus) healthObserver = ExtensionHealthObserver() healthObserver.add_extension_observation(handler_status, [ext_status]) # validate that 4 observations were made - one for the handler version, and one for the handler being in a success state, and one for # the extension self.assertEqual(4, len(healthObserver.partial_observations)) # unhealthy extension substatus self.assertEqual( handler_status.name + ExtensionHealthObserver.SUBSTATUS_SUFFIX, healthObserver.partial_observations[3].name) self.assertEqual(False, healthObserver.partial_observations[3].is_healthy) substatus.status = "Succeeded" ext_status.substatusList.append(substatus) healthObserver = ExtensionHealthObserver() healthObserver.add_extension_observation(handler_status, [ext_status]) # validate that 4 observations were made - one for the handler version, and one for the handler being in a success state, and one for # the extension self.assertEqual(4, len(healthObserver.partial_observations)) # unhealthy extension substatus self.assertEqual( handler_status.name + ExtensionHealthObserver.SUBSTATUS_SUFFIX, healthObserver.partial_observations[3].name) self.assertEqual(True, healthObserver.partial_observations[3].is_healthy)