Пример #1
0
 def _process_response(self, response):
     report = response_to_report_item(response)
     target = response.request.target
     if report is None:
         try:
             parsed_response = json.loads(response.data)
             # If the node is offline, we only get the "offline" key. Asking
             # for any other in that case results in KeyError which is not
             # what we want.
             if (
                 parsed_response.get("pending", True)
                 or
                 not parsed_response.get("online", False)
             ):
                 self._not_yet_started_target_list.append(target)
                 return
             report = reports.cluster_start_success(target.label)
         except (json.JSONDecodeError, KeyError):
             report = reports.invalid_response_format(target.label)
     else:
         if not response.was_connected:
             self._not_yet_started_target_list.append(target)
             report = response_to_report_item(
                 response, severity=ReportItemSeverity.WARNING
             )
     self._report(report)
Пример #2
0
 def _process_response(self, response):
     report = response_to_report_item(response)
     if report is None:
         self._online_target_list.append(response.request.target)
         return
     if not response.was_connected:
         report = (ReportItem.warning(
             reports.messages.OmittingNode(response.request.target.label))
                   if self._ignore_offline_targets else
                   response_to_report_item(
                       response, forceable=report_codes.SKIP_OFFLINE_NODES))
     self._report(report)
Пример #3
0
 def _process_response(self, response):
     report = response_to_report_item(response)
     if report is None:
         self._online_target_list.append(response.request.target)
         return
     if not response.was_connected:
         report = (
             reports.omitting_node(response.request.target.label)
             if self._ignore_offline_targets
             else response_to_report_item(
                 response, forceable=report_codes.SKIP_OFFLINE_NODES
             )
         )
     self._report(report)
Пример #4
0
 def _process_response(self, response):
     report = response_to_report_item(
         response, severity=ReportItemSeverity.WARNING
     )
     node = response.request.target.label
     if report is not None:
         self._has_failure = True
         self._report(report)
         return self._get_next_list()
     if response.data.strip() == "Cannot initialize CMAP service":
         # corosync is not running on the node, this is OK
         return self._get_next_list()
     try:
         quorum_status = corosync_live.QuorumStatus.from_string(
             response.data
         )
         if not quorum_status.is_quorate:
             return self._get_next_list()
         self._quorum_status = quorum_status
     except corosync_live.QuorumStatusParsingException as e:
         self._has_failure = True
         self._report(
             reports.corosync_quorum_get_status_error(
                 e.reason,
                 node=node,
                 severity=ReportItemSeverity.WARNING,
             )
         )
         return self._get_next_list()
     return []
Пример #5
0
    def _process_response(self, response):
        report = response_to_report_item(response,
                                         severity=ReportItemSeverity.WARNING)
        node = response.request.target.label
        if report is not None:
            self.__has_failures = True
            self._report(report)
            return self._get_next_list()
        try:
            output = json.loads(response.data)
            if output["code"] == "reloaded":
                self.__was_successful = True
                self._report(reports.corosync_config_reloaded(node))
                return

            if output["code"] == "not_running":
                self._report(reports.corosync_config_reload_not_possible(node))
            else:
                self.__has_failures = True
                self._report(
                    reports.corosync_config_reload_error(
                        output["message"],
                        node=node,
                        severity=ReportItemSeverity.WARNING,
                    ))
        except (ValueError, LookupError):
            self._report(
                reports.invalid_response_format(
                    node,
                    severity=ReportItemSeverity.WARNING,
                ))

        return self._get_next_list()
Пример #6
0
 def _get_response_report(self, response):
     return response_to_report_item(
         response,
         severity=self._failure_severity,
         forceable=self._failure_forceable,
         report_pcsd_too_old_on_404=self._report_pcsd_too_old_on_404,
     )
Пример #7
0
    def _process_response(self, response):
        report = response_to_report_item(
            response, severity=ReportItemSeverity.WARNING
        )
        node = response.request.target.label
        if report is not None:
            self.__has_failures = True
            self._report(report)
            return self._get_next_list()
        try:
            output = json.loads(response.data)
            if output["code"] == "reloaded":
                self.__was_successful = True
                self._report(reports.corosync_config_reloaded(node))
                return []

            if output["code"] == "not_running":
                self._report(reports.corosync_config_reload_not_possible(node))
            else:
                self.__has_failures = True
                self._report(reports.corosync_config_reload_error(
                    output["message"],
                    node=node,
                    severity=ReportItemSeverity.WARNING,
                ))
        except (ValueError, LookupError):
            self.__has_failures = True
            self._report(reports.invalid_response_format(
                node,
                severity=ReportItemSeverity.WARNING,
            ))

        return self._get_next_list()
Пример #8
0
 def _process_response(self, response):
     report_item = response_to_report_item(
         response, severity=reports.ReportItemSeverity.WARNING)
     node = response.request.target.label
     if report_item is not None:
         self._has_failure = True
         self._report(report_item)
         return self._get_next_list()
     if response.data.strip() == "Cannot initialize CMAP service":
         # corosync is not running on the node, this is OK
         return self._get_next_list()
     try:
         quorum_status = corosync_live.QuorumStatus.from_string(
             response.data)
         if not quorum_status.is_quorate:
             return self._get_next_list()
         self._quorum_status = quorum_status
     except corosync_live.QuorumStatusParsingException as e:
         self._has_failure = True
         self._report(
             ReportItem.warning(
                 reports.messages.CorosyncQuorumGetStatusError(
                     e.reason,
                     node=node,
                 )))
         return self._get_next_list()
     return []
Пример #9
0
 def _process_response(self, response):
     report = response_to_report_item(response)
     if report:
         self._report(report)
         return
     report_list = []
     node_label = response.request.target.label
     try:
         data = json.loads(response.data)
         if not data["sbd"]["installed"]:
             report_list.append(reports.sbd_not_installed(node_label))
         if not data["watchdog"]["exist"]:
             report_list.append(
                 reports.watchdog_not_found(node_label,
                                            data["watchdog"]["path"]))
         for device in data.get("device_list", []):
             if not device["exist"]:
                 report_list.append(
                     reports.sbd_device_does_not_exist(
                         device["path"], node_label))
             elif not device["block_device"]:
                 report_list.append(
                     reports.sbd_device_is_not_block_device(
                         device["path"], node_label))
             # TODO maybe we can check whenever device is initialized by sbd (by
             # running 'sbd -d <dev> dump;')
     except (ValueError, KeyError, TypeError):
         report_list.append(reports.invalid_response_format(node_label))
     if report_list:
         self._report_list(report_list)
     else:
         self._report(
             reports.sbd_check_success(response.request.target.label))
Пример #10
0
 def _process_response(self, response):
     report_item = response_to_report_item(
         response, severity=ReportItemSeverity.WARNING)
     if report_item is None:
         self._on_success()
         return []
     self._report(report_item)
     return self._get_next_list()
Пример #11
0
    def _get_response_report(self, response):
        """
        Convert specified response to report item. Returns None if the response
        has no failures.

        Response response -- a response to be converted
        """
        return response_to_report_item(response)
Пример #12
0
 def test_code_other(self):
     assert_report_item_equal(
         lib.response_to_report_item(self.fixture_response_connected(500)),
         (severity.ERROR, report_codes.NODE_COMMUNICATION_ERROR, {
             "node": self.host,
             "command": self.request,
             "reason": "HTTP error: 500"
         }, None))
Пример #13
0
 def test_code_403(self):
     assert_report_item_equal(
         lib.response_to_report_item(self.fixture_response_connected(403)),
         (severity.ERROR,
          report_codes.NODE_COMMUNICATION_ERROR_PERMISSION_DENIED, {
              "node": self.host,
              "command": self.request,
              "reason": "HTTP error: 403"
          }, None))
Пример #14
0
    def _get_response_report(self, response):
        # pylint: disable=no-self-use
        """
        Convert specified response to report item. Returns None if the response
        has no failures.

        Response response -- a response to be converted
        """
        return response_to_report_item(response)
Пример #15
0
 def test_code_404(self):
     assert_report_item_equal(
         lib.response_to_report_item(self.fixture_response_connected(404)),
         (severity.ERROR,
          report_codes.NODE_COMMUNICATION_ERROR_UNSUPPORTED_COMMAND, {
              "node": self.host,
              "command": self.request,
              "reason": "HTTP error: 404"
          }, None))
Пример #16
0
 def test_code_400(self):
     assert_report_item_equal(
         lib.response_to_report_item(self.fixture_response_connected(400)),
         (severity.ERROR,
          report_codes.NODE_COMMUNICATION_COMMAND_UNSUCCESSFUL, {
              "node": self.host,
              "command": self.request,
              "reason": self.data.decode("utf-8")
          }, None))
Пример #17
0
 def _process_response(self, response):
     report = response_to_report_item(
         response, severity=ReportItemSeverity.WARNING
     )
     if report is None:
         self._on_success()
         return []
     self._report(report)
     return self._get_next_list()
Пример #18
0
 def _process_response(self, response):
     report = response_to_report_item(response,
                                      severity=ReportItemSeverity.WARNING)
     node_label = response.request.target.label
     if report is None:
         self._report(reports.cluster_destroy_success(node_label))
     else:
         self._report(report)
         self._unreachable_nodes.append(node_label)
Пример #19
0
 def test_timedouted(self):
     response = self.fixture_response_not_connected(
         pycurl.E_OPERATION_TIMEOUTED, "err")
     assert_report_item_equal(
         lib.response_to_report_item(response),
         (severity.ERROR, report_codes.NODE_COMMUNICATION_ERROR_TIMED_OUT, {
             "node": self.host,
             "command": self.request,
             "reason": "err"
         }, None))
Пример #20
0
 def _process_response(self, response):
     report_item = response_to_report_item(
         response, severity=ReportItemSeverity.WARNING)
     if report_item is not None:
         self.__has_failures = True
         self._report(report_item)
         return self._get_next_list()
     self.__corosync_conf = response.data
     self.__was_successful = True
     return []
Пример #21
0
 def _process_response(self, response):
     report = response_to_report_item(
         response, severity=ReportItemSeverity.WARNING
     )
     node_label = response.request.target.label
     if report is None:
         self._report(reports.cluster_destroy_success(node_label))
     else:
         self._report(report)
         self._unreachable_nodes.append(node_label)
Пример #22
0
 def test_unable_to_connect(self):
     response = self.fixture_response_not_connected(pycurl.E_SEND_ERROR,
                                                    "err")
     assert_report_item_equal(
         lib.response_to_report_item(response),
         (severity.ERROR,
          report_codes.NODE_COMMUNICATION_ERROR_UNABLE_TO_CONNECT, {
              "node": self.host,
              "command": self.request,
              "reason": "err"
          }, None))
Пример #23
0
 def _process_response(self, response):
     report_item = response_to_report_item(
         response, severity=reports.ReportItemSeverity.WARNING)
     node_label = response.request.target.label
     if report_item is None:
         self._report(
             ReportItem.info(
                 reports.messages.ClusterDestroySuccess(node_label)))
     else:
         self._report(report_item)
         self._unreachable_nodes.append(node_label)
Пример #24
0
 def _process_response(self, response):
     report = response_to_report_item(response,
                                      severity=ReportItemSeverity.INFO)
     host_name = response.request.target.label
     if report is None:
         report = reports.host_already_authorized(host_name)
     else:
         # If we cannot connect it may be because a node's address and / or
         # port is not correct. Since these are part of authentication info
         # we tell we're not authorized.
         self._not_authorized_host_name_list.append(host_name)
     self._report(report)
Пример #25
0
 def _process_response(self, response):
     report = response_to_report_item(
         response, severity=ReportItemSeverity.INFO
     )
     host_name = response.request.target.label
     if report is None:
         report = reports.host_already_authorized(host_name)
     else:
         # If we cannot connect it may be because a node's address and / or
         # port is not correct. Since these are part of authentication info
         # we tell we're not authorized.
         self._not_authorized_host_name_list.append(host_name)
     self._report(report)
Пример #26
0
 def _process_response(self, response):
     report = response_to_report_item(response)
     target = response.request.target
     if report is None:
         try:
             parsed_response = json.loads(response.data)
             # If the node is offline, we only get the "offline" key. Asking
             # for any other in that case results in KeyError which is not
             # what we want.
             if (parsed_response.get("pending", True)
                     or not parsed_response.get("online", False)):
                 self._not_yet_started_target_list.append(target)
                 return
             report = reports.cluster_start_success(target.label)
         except (json.JSONDecodeError, KeyError):
             report = reports.invalid_response_format(target.label)
     else:
         if not response.was_connected:
             self._not_yet_started_target_list.append(target)
             report = response_to_report_item(
                 response, severity=ReportItemSeverity.WARNING)
     self._report(report)
Пример #27
0
 def test_code_404(self):
     assert_report_item_equal(
         lib.response_to_report_item(self.fixture_response_connected(404)),
         (
             severity.ERROR,
             report_codes.NODE_COMMUNICATION_ERROR_UNSUPPORTED_COMMAND,
             {
                 "node": self.host,
                 "command": self.request,
                 "reason": "HTTP error: 404"
             },
             None
         )
     )
Пример #28
0
 def test_code_403(self):
     assert_report_item_equal(
         lib.response_to_report_item(self.fixture_response_connected(403)),
         (
             severity.ERROR,
             report_codes.NODE_COMMUNICATION_ERROR_PERMISSION_DENIED,
             {
                 "node": self.host,
                 "command": self.request,
                 "reason": "HTTP error: 403"
             },
             None
         )
     )
Пример #29
0
 def test_code_400(self):
     assert_report_item_equal(
         lib.response_to_report_item(self.fixture_response_connected(400)),
         (
             severity.ERROR,
             report_codes.NODE_COMMUNICATION_COMMAND_UNSUCCESSFUL,
             {
                 "node": self.host,
                 "command": self.request,
                 "reason": self.data.decode("utf-8")
             },
             None
         )
     )
Пример #30
0
 def test_code_401(self):
     assert_report_item_equal(
         lib.response_to_report_item(self.fixture_response_connected(401)),
         (
             severity.ERROR,
             report_codes.NODE_COMMUNICATION_ERROR_NOT_AUTHORIZED,
             {
                 "node": self.host,
                 "command": self.request,
                 "reason": "HTTP error: 401",
             },
             None,
         ),
     )
Пример #31
0
    def _process_response(self, response):
        report_item = response_to_report_item(response)
        if report_item:
            self._report(report_item)
            return
        report_list = []
        node_label = response.request.target.label
        try:
            data = json.loads(response.data)
            if not data["sbd"]["installed"]:
                report_list.append(
                    ReportItem.error(
                        reports.messages.SbdNotInstalled(node_label)))
            if "watchdog" in data:
                if data["watchdog"]["exist"]:
                    if not data["watchdog"].get("is_supported", True):
                        report_list.append(
                            ReportItem.error(
                                reports.messages.SbdWatchdogNotSupported(
                                    node_label, data["watchdog"]["path"])))
                else:
                    report_list.append(
                        ReportItem.error(
                            reports.messages.WatchdogNotFound(
                                node_label, data["watchdog"]["path"])))

            for device in data.get("device_list", []):
                if not device["exist"]:
                    report_list.append(
                        ReportItem.error(
                            reports.messages.SbdDeviceDoesNotExist(
                                device["path"], node_label)))
                elif not device["block_device"]:
                    report_list.append(
                        ReportItem.error(
                            reports.messages.SbdDeviceIsNotBlockDevice(
                                device["path"], node_label)))
                # TODO maybe we can check whenever device is initialized by sbd
                # (by running 'sbd -d <dev> dump;')
        except (ValueError, KeyError, TypeError):
            report_list.append(
                ReportItem.error(
                    reports.messages.InvalidResponseFormat(node_label)))
        if report_list:
            self._report_list(report_list)
        else:
            self._report(
                ReportItem.info(
                    reports.messages.SbdCheckSuccess(
                        response.request.target.label)))
Пример #32
0
 def test_code_other(self):
     assert_report_item_equal(
         lib.response_to_report_item(self.fixture_response_connected(500)),
         (
             severity.ERROR,
             report_codes.NODE_COMMUNICATION_ERROR,
             {
                 "node": self.host,
                 "command": self.request,
                 "reason": "HTTP error: 500"
             },
             None
         )
     )
Пример #33
0
    def _process_response(self, response):
        report_item = response_to_report_item(
            response, severity=ReportItemSeverity.WARNING)
        if report_item is not None:
            self._report(report_item)
            return self._get_next_list()

        node = response.request.target.label
        try:
            output = json.loads(response.data)
            if output["status"] == "success":
                self._was_successful = True
                self._cluster_status = output["data"]
                return []
            if output["status_msg"]:
                self._report(
                    ReportItem.error(
                        reports.messages.NodeCommunicationCommandUnsuccessful(
                            node,
                            response.request.action,
                            output["status_msg"],
                        )))
            # TODO Node name should be added to each received report item and
            # those modified report itemss should be reported. That, however,
            # requires reports overhaul which would add possibility to add a
            # node name to any report item. Also, infos and warnings should not
            # be ignored.
            if output["report_list"]:
                for report_data in output["report_list"]:
                    if (report_data["severity"] == ReportItemSeverity.ERROR
                            and report_data["report_text"]):
                        # pylint: disable=line-too-long
                        self._report(
                            ReportItem.error(
                                reports.messages.
                                NodeCommunicationCommandUnsuccessful(
                                    node,
                                    response.request.action,
                                    report_data["report_text"],
                                )))
        except (ValueError, LookupError, TypeError):
            self._report(
                ReportItem.warning(
                    reports.messages.InvalidResponseFormat(node)))

        return self._get_next_list()
Пример #34
0
 def test_timedouted(self):
     response = self.fixture_response_not_connected(
         pycurl.E_OPERATION_TIMEOUTED, "err"
     )
     assert_report_item_equal(
         lib.response_to_report_item(response),
         (
             severity.ERROR,
             report_codes.NODE_COMMUNICATION_ERROR_TIMED_OUT,
             {
                 "node": self.host,
                 "command": self.request,
                 "reason": "err"
             },
             None
         )
     )
Пример #35
0
 def test_unable_to_connect(self):
     response = self.fixture_response_not_connected(
         pycurl.E_SEND_ERROR, "err"
     )
     assert_report_item_equal(
         lib.response_to_report_item(response),
         (
             severity.ERROR,
             report_codes.NODE_COMMUNICATION_ERROR_UNABLE_TO_CONNECT,
             {
                 "node": self.host,
                 "command": self.request,
                 "reason": "err"
             },
             None
         )
     )
Пример #36
0
 def _process_response(self, response):
     report_item = response_to_report_item(
         response, severity=ReportItemSeverity.WARNING)
     node_label = response.request.target.label
     if report_item is not None:
         if not response.was_connected:
             self._report(report_item)
         self._report(
             ReportItem.warning(
                 reports.messages.UnableToGetSbdConfig(node_label, "")))
         return
     self._config_list.append({
         "node":
         node_label,
         "config":
         environment_file_to_dict(response.data),
     })
     self._successful_target_list.append(node_label)
Пример #37
0
 def _process_response(self, response):
     report = response_to_report_item(response,
                                      severity=ReportItemSeverity.WARNING)
     node_label = response.request.target.label
     if report is not None:
         if not response.was_connected:
             self._report(report)
         self._report(
             reports.unable_to_get_sbd_config(node_label, "",
                                              ReportItemSeverity.WARNING))
         return
     self._config_list.append({
         "node":
         node_label,
         "config":
         environment_file_to_dict(response.data)
     })
     self._successful_target_list.append(node_label)
Пример #38
0
 def _process_response(self, response):
     report = response_to_report_item(
         response, severity=ReportItemSeverity.WARNING
     )
     node_label = response.request.target.label
     if report is not None:
         if not response.was_connected:
             self._report(report)
         self._report(
             reports.unable_to_get_sbd_config(
                 node_label, "", ReportItemSeverity.WARNING
             )
         )
         return
     self._config_list.append({
         "node": node_label,
         "config": environment_file_to_dict(response.data)
     })
     self._successful_target_list.append(node_label)
Пример #39
0
 def _process_response(self, response):
     report = response_to_report_item(response,
                                      severity=ReportItemSeverity.WARNING)
     node_label = response.request.target.label
     if report is not None:
         self._report_list([
             report,
             #reason is in previous report item, warning is there implicit
             reports.unable_to_get_sbd_status(node_label, "")
         ])
         return
     try:
         self._status_list.append({
             "node": node_label,
             "status": json.loads(response.data)["sbd"]
         })
         self._successful_target_list.append(node_label)
     except (ValueError, KeyError) as e:
         self._report(reports.unable_to_get_sbd_status(node_label, str(e)))
Пример #40
0
 def _process_response(self, response):
     report = response_to_report_item(
         response, severity=ReportItemSeverity.WARNING
     )
     node_label = response.request.target.label
     if report is not None:
         self._report_list([
             report,
             #reason is in previous report item, warning is there implicit
             reports.unable_to_get_sbd_status(node_label, "")
         ])
         return
     try:
         self._status_list.append({
             "node": node_label,
             "status": json.loads(response.data)["sbd"]
         })
         self._successful_target_list.append(node_label)
     except (ValueError, KeyError) as e:
         self._report(reports.unable_to_get_sbd_status(node_label, str(e)))
Пример #41
0
    def _process_response(self, response):
        report = response_to_report_item(response)
        if report:
            self._report(report)
            return
        report_list = []
        node_label = response.request.target.label
        try:
            data = json.loads(response.data)
            if not data["sbd"]["installed"]:
                report_list.append(reports.sbd_not_installed(node_label))
            if "watchdog" in data:
                if data["watchdog"]["exist"]:
                    if not data["watchdog"].get("is_supported", True):
                        report_list.append(reports.sbd_watchdog_not_supported(
                            node_label, data["watchdog"]["path"]
                        ))
                else:
                    report_list.append(reports.watchdog_not_found(
                        node_label, data["watchdog"]["path"]
                    ))

            for device in data.get("device_list", []):
                if not device["exist"]:
                    report_list.append(reports.sbd_device_does_not_exist(
                        device["path"], node_label
                    ))
                elif not device["block_device"]:
                    report_list.append(reports.sbd_device_is_not_block_device(
                        device["path"], node_label
                    ))
                # TODO maybe we can check whenever device is initialized by sbd
                # (by running 'sbd -d <dev> dump;')
        except (ValueError, KeyError, TypeError):
            report_list.append(reports.invalid_response_format(node_label))
        if report_list:
            self._report_list(report_list)
        else:
            self._report(
                reports.sbd_check_success(response.request.target.label)
            )
Пример #42
0
Файл: scsi.py Проект: vvidic/pcs
    def _process_response(self, response):
        report_item = response_to_report_item(response,
                                              report_pcsd_too_old_on_404=True)
        if report_item:
            self._report(report_item)
            return
        node_label = response.request.target.label
        try:
            result = from_dict(InternalCommunicationResultDto,
                               json.loads(response.data))
            context = reports.ReportItemContext(node_label)
            self._report_list([
                reports.report_dto_to_item(report, context)
                for report in result.report_list
            ])
            if result.status == const.COM_STATUS_SUCCESS:
                self._on_success()

        except (json.JSONDecodeError, DaciteError):
            self._report(
                reports.ReportItem.error(
                    reports.messages.InvalidResponseFormat(node_label)))
Пример #43
0
    def _process_response(self, response):
        report_item = response_to_report_item(
            response, severity=ReportItemSeverity.WARNING)
        node = response.request.target.label
        if report_item is not None:
            self.__has_failures = True
            self._report(report_item)
            return self._get_next_list()
        try:
            output = json.loads(response.data)
            if output["code"] == "reloaded":
                self.__was_successful = True
                self._report(
                    ReportItem.info(
                        reports.messages.CorosyncConfigReloaded(node)))
                return []

            if output["code"] == "not_running":
                self._report(
                    ReportItem.warning(
                        reports.messages.CorosyncConfigReloadNotPossible(
                            node)))
            else:
                self.__has_failures = True
                self._report(
                    ReportItem.warning(
                        reports.messages.CorosyncConfigReloadError(
                            output["message"],
                            node=node,
                        )))
        except (ValueError, LookupError):
            self.__has_failures = True
            self._report(
                ReportItem.warning(
                    reports.messages.InvalidResponseFormat(node)))

        return self._get_next_list()
Пример #44
0
 def test_code_200(self):
     self.assertIsNone(
         lib.response_to_report_item(self.fixture_response_connected(200)))
Пример #45
0
 def test_code_200(self):
     self.assertIsNone(
         lib.response_to_report_item(self.fixture_response_connected(200))
     )
Пример #46
0
 def _get_response_report(self, response):
     return response_to_report_item(
         response,
         severity=self._failure_severity,
         forceable=self._failure_forceable,
     )
Пример #47
0
 def _process_response(self, response):
     report = response_to_report_item(response)
     if report is None:
         return
     self._report(report)
     return self._get_next_list()
Пример #48
0
 def _get_response_report(self, response):
     return response_to_report_item(
         response,
         severity=self._failure_severity,
         forceable=self._failure_forceable,
     )