예제 #1
0
    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
예제 #2
0
    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))
예제 #3
0
    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
예제 #4
0
    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))
예제 #5
0
    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))
예제 #7
0
    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
예제 #8
0
    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))
예제 #9
0
    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
예제 #10
0
    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)