Example #1
0
    def run(
        self,
        env, resource_id, node=None, master=False, lifetime=None, wait=False
    ):
        # validate
        env.ensure_wait_satisfiable(wait) # raises on error

        report_list = []
        resource_el = resource.common.find_one_resource_and_report(
            get_resources(env.get_cib()),
            resource_id,
            report_list,
        )
        if resource_el is not None:
            report_list.extend(self._validate(resource_el, master))
        env.report_processor.process_list(report_list) # raises on error

        # get current status for wait processing
        if wait is not False:
            resource_running_on_before = get_resource_state(
                env.get_cluster_state(),
                resource_id
            )

        # run the action
        stdout, stderr, retval = self._run_action(
            env.cmd_runner(), resource_id, node=node, master=master,
            lifetime=lifetime
        )
        if retval != 0:
            if (
                f"Resource '{resource_id}' not moved: active in 0 locations"
                in
                stderr
            ):
                raise LibraryError(
                    self._report_action_stopped_resource(resource_id)
                )
            raise LibraryError(
                self._report_action_pcmk_error(resource_id, stdout, stderr)
            )
        env.report_processor.process(
            self._report_action_pcmk_success(resource_id, stdout, stderr)
        )

        # process wait
        if wait is not False:
            wait_for_idle(env.cmd_runner(), env.get_wait_timeout(wait))
            resource_running_on_after = get_resource_state(
                env.get_cluster_state(),
                resource_id
            )
            env.report_processor.process(
                self._report_wait_result(
                    resource_id,
                    node,
                    resource_running_on_before,
                    resource_running_on_after,
                )
            )
Example #2
0
    def run(self,
            env,
            resource_id,
            node=None,
            master=False,
            lifetime=None,
            wait=False):
        # validate
        env.ensure_wait_satisfiable(wait)  # raises on error

        report_list = []
        resource_el = resource.common.find_one_resource_and_report(
            get_resources(env.get_cib()),
            resource_id,
            report_list,
        )
        if resource_el is not None:
            report_list.extend(self._validate(resource_el, master))
        env.report_processor.process_list(report_list)  # raises on error

        # get current status for wait processing
        if wait is not False:
            resource_running_on_before = get_resource_state(
                env.get_cluster_state(), resource_id)

        # run the action
        stdout, stderr, retval = self._run_action(env.cmd_runner(),
                                                  resource_id,
                                                  node=node,
                                                  master=master,
                                                  lifetime=lifetime)
        if retval != 0:
            if (f"Resource '{resource_id}' not moved: active in 0 locations"
                    in stderr):
                raise LibraryError(
                    self._report_action_stopped_resource(resource_id))
            raise LibraryError(
                self._report_action_pcmk_error(resource_id, stdout, stderr))
        env.report_processor.process(
            self._report_action_pcmk_success(resource_id, stdout, stderr))

        # process wait
        if wait is not False:
            wait_for_idle(env.cmd_runner(), env.get_wait_timeout(wait))
            resource_running_on_after = get_resource_state(
                env.get_cluster_state(), resource_id)
            env.report_processor.process(
                self._report_wait_result(
                    resource_id,
                    node,
                    resource_running_on_before,
                    resource_running_on_after,
                ))
Example #3
0
def update_scsi_devices_without_restart(
    runner: CommandRunner,
    cluster_state: _Element,
    resource_el: _Element,
    id_provider: IdProvider,
    devices_list: Iterable[str],
) -> None:
    """
    Update scsi devices without restart of stonith resource or other resources.

    runner -- command runner instance
    cluster_state -- status of the cluster
    resource_el -- resource element being updated
    id_provider -- elements' ids generator
    device_list -- list of updated scsi devices
    """
    resource_id = resource_el.get("id", "")
    roles_with_nodes = get_resource_state(cluster_state, resource_id)
    if "Started" not in roles_with_nodes:
        raise LibraryError(
            ReportItem.error(
                reports.messages.StonithRestartlessUpdateUnableToPerform(
                    f"resource '{resource_id}' is not running on any node",
                    reason_type=reports.const.
                    STONITH_RESTARTLESS_UPDATE_UNABLE_TO_PERFORM_REASON_NOT_RUNNING,
                )))
    if len(roles_with_nodes["Started"]) != 1:
        # TODO: do we want to be able update cloned fence_scsi? Or just case
        # when it's running on more than 1 node? It is possible but we need to
        # update more lrm_rsc_op elements
        raise LibraryError(
            ReportItem.error(
                reports.messages.StonithRestartlessUpdateUnableToPerform(
                    f"resource '{resource_id}' is running on more than 1 node")
            ))
    node_name = roles_with_nodes["Started"][0]

    new_instance_attrs = {"devices": ",".join(sorted(devices_list))}
    arrange_first_instance_attributes(resource_el, new_instance_attrs,
                                      id_provider)

    lrm_rsc_op_start_list = _get_lrm_rsc_op_elements(get_root(resource_el),
                                                     resource_id, node_name,
                                                     "start")
    if len(lrm_rsc_op_start_list) == 1:
        _update_digest_attrs_in_lrm_rsc_op(
            lrm_rsc_op_start_list[0],
            get_resource_digests(
                runner,
                resource_id,
                node_name,
                new_instance_attrs,
            ),
        )
    else:
        raise LibraryError(
            ReportItem.error(
                reports.messages.StonithRestartlessUpdateUnableToPerform(
                    "lrm_rsc_op element for start operation was not found")))

    monitor_attrs_list = _get_monitor_attrs(resource_el)
    lrm_rsc_op_monitor_list = _get_lrm_rsc_op_elements(get_root(resource_el),
                                                       resource_id, node_name,
                                                       "monitor")
    if len(lrm_rsc_op_monitor_list) != len(monitor_attrs_list):
        raise LibraryError(
            ReportItem.error(
                reports.messages.StonithRestartlessUpdateUnableToPerform(
                    ("number of lrm_rsc_op and op elements for monitor "
                     "operation differs"))))

    for monitor_attrs in monitor_attrs_list:
        lrm_rsc_op_list = _get_lrm_rsc_op_elements(
            get_root(resource_el),
            resource_id,
            node_name,
            "monitor",
            monitor_attrs["interval"],
        )
        if len(lrm_rsc_op_list) == 1:
            _update_digest_attrs_in_lrm_rsc_op(
                lrm_rsc_op_list[0],
                get_resource_digests(
                    runner,
                    resource_id,
                    node_name,
                    new_instance_attrs,
                    crm_meta_attributes=monitor_attrs,
                ),
            )
        else:
            raise LibraryError(
                ReportItem.error(
                    reports.messages.StonithRestartlessUpdateUnableToPerform(
                        ("monitor lrm_rsc_op element for resource "
                         f"'{resource_id}', node '{node_name}' and interval "
                         f"'{monitor_attrs['interval']}' not found"))))