Exemple #1
0
 def test_unfence_failure_unknown_command(self):
     self.config_cib()
     self.config.corosync_conf.load_content(
         corosync_conf_fixture(self.existing_corosync_nodes))
     self.config.http.corosync.get_corosync_online_targets(
         node_labels=self.existing_nodes)
     communication_list = [
         dict(
             label=node,
             raw_data=json.dumps(self.get_raw_data(node)),
         ) for node in self.existing_nodes
     ]
     communication_list[2]["response_code"] = 404
     communication_list[2]["output"] = json.dumps(
         dto.to_dict(
             communication.dto.InternalCommunicationResultDto(
                 status=communication.const.COM_STATUS_UNKNOWN_CMD,
                 status_msg=("Unknown command '/api/v1/unknown/v2'"),
                 report_list=[],
                 data=None,
             )))
     self.unfence_config(communication_list=communication_list)
     self.env_assist.assert_raise_library_error(self.command())
     self.env_assist.assert_reports([
         fixture.error(
             reports.codes.PCSD_VERSION_TOO_OLD,
             node=self.existing_nodes[2],
         ),
     ])
Exemple #2
0
def get_config(env: LibraryEnvironment) -> Mapping[str, Any]:
    """
    Return local disaster recovery config

    env -- LibraryEnvironment
    """
    report_processor = env.report_processor
    report_list, dr_config = _load_dr_config(env.get_dr_env().config)
    report_processor.report_list(report_list)
    if report_processor.has_errors:
        raise LibraryError()

    return dto.to_dict(
        DrConfigDto(
            local_site=DrConfigSiteDto(
                site_role=dr_config.local_role,
                node_list=[],
            ),
            remote_site_list=[
                DrConfigSiteDto(
                    site_role=site.role,
                    node_list=[
                        DrConfigNodeDto(name=name)
                        for name in site.node_name_list
                    ],
                ) for site in dr_config.get_remote_site_list()
            ],
        ))
Exemple #3
0
 def test_all(self):
     stdout, retval = self.pcs_runner.run(
         ["resource", "config", "--output-format=json"]
     )
     self.assertEqual(retval, 0)
     expected = ListCibResourcesDto(
         primitives=[
             resources_dto.PRIMITIVE_R1,
             resources_dto.PRIMITIVE_R7,
             resources_dto.PRIMITIVE_R5,
             resources_dto.STONITH_S1,
             resources_dto.PRIMITIVE_R2,
             resources_dto.PRIMITIVE_R3,
             resources_dto.PRIMITIVE_R4,
             resources_dto.PRIMITIVE_R6,
         ],
         clones=[
             resources_dto.CLONE_G1,
             resources_dto.CLONE_R6,
         ],
         groups=[
             resources_dto.GROUP_G2,
             resources_dto.GROUP_G1,
         ],
         bundles=[
             resources_dto.BUNDLE_B1,
             resources_dto.BUNDLE_B2,
         ],
     )
     self.assertEqual(json.loads(stdout), to_dict(expected))
 def test_unfence_failure_agent_script_failed(self):
     self.config_cib()
     self.config.corosync_conf.load_content(
         corosync_conf_fixture(self.existing_corosync_nodes))
     self.config.http.corosync.get_corosync_online_targets(
         node_labels=self.existing_nodes)
     communication_list = [
         dict(
             label=node,
             raw_data=json.dumps(self.get_raw_data(node)),
         ) for node in self.existing_nodes
     ]
     communication_list[1]["output"] = json.dumps(
         dto.to_dict(
             communication.dto.InternalCommunicationResultDto(
                 status=communication.const.COM_STATUS_ERROR,
                 status_msg="error",
                 report_list=[
                     reports.ReportItem.error(
                         reports.messages.StonithUnfencingFailed(
                             "errB")).to_dto()
                 ],
                 data=None,
             )))
     self.unfence_config(communication_list=communication_list)
     self.env_assist.assert_raise_library_error(self.command())
     self.env_assist.assert_reports([
         fixture.error(
             reports.codes.STONITH_UNFENCING_FAILED,
             reason="errB",
             context=reports.dto.ReportItemContextDto(
                 node=self.existing_nodes[1], ),
         ),
     ])
Exemple #5
0
 def test_simple_order(self):
     resources_members = ["order-d1-d2-mandatory"]
     resources = {
         "d1": self.primitive_fixture("d1", resources_members),
         "d2": self.primitive_fixture("d2", resources_members),
     }
     relations = {
         "order-d1-d2-mandatory":
         RelationEntityDto(
             "order-d1-d2-mandatory",
             ResourceRelationType.ORDER,
             members=["d1", "d2"],
             metadata={
                 "id": "order-d1-d2-mandatory",
                 "first": "d1",
                 "first-action": "start",
                 "then": "d2",
                 "then-action": "start",
                 "kind": "Mandatory",
             },
         ),
     }
     expected = dict(
         relation_entity=dto.to_dict(resources["d2"]),
         is_leaf=False,
         members=[
             dict(
                 relation_entity=dto.to_dict(
                     relations["order-d1-d2-mandatory"]),
                 is_leaf=False,
                 members=[
                     dict(
                         relation_entity=dto.to_dict(resources["d1"]),
                         is_leaf=False,
                         members=[],
                     )
                 ],
             )
         ],
     )
     self.assertEqual(
         expected,
         dto.to_dict(
             lib.ResourceRelationTreeBuilder(
                 resources, relations).get_tree("d2").to_dto()),
     )
Exemple #6
0
def main() -> None:
    # pylint: disable=broad-except
    argv = sys.argv[1:]
    if argv:
        _exit(
            communication.const.COM_STATUS_INPUT_ERROR,
            status_msg="No arguments allowed",
        )

    utils.subprocess_setup()
    logging.basicConfig()

    try:
        input_dto = dto.from_dict(
            communication.dto.InternalCommunicationRequestDto,
            json.load(sys.stdin),
        )
        cli_env = get_cli_env(input_dto.options)
        lib = Library(cli_env, utils.get_middleware_factory())
        if input_dto.cmd not in SUPPORTED_COMMANDS:
            _exit(
                communication.const.COM_STATUS_UNKNOWN_CMD,
                status_msg=f"Unknown command '{input_dto.cmd}'",
            )
        for sub_cmd in input_dto.cmd.split("."):
            lib = getattr(lib, sub_cmd)
        output_data = lib(**input_dto.cmd_data)  # type: ignore
        _exit(
            communication.const.COM_STATUS_SUCCESS,
            report_list=cli_env.report_processor.processed_items,
            data=(
                dto.to_dict(output_data)
                if isinstance(output_data, dto.DataTransferObject)
                else output_data
            ),
        )
    except LibraryError as e:
        _exit(
            communication.const.COM_STATUS_ERROR,
            report_list=(
                cli_env.report_processor.processed_items + list(e.args)
            ),
            data=e.output,
        )
    except json.JSONDecodeError as e:
        _exit(
            communication.const.COM_STATUS_INPUT_ERROR,
            status_msg=f"Unable to parse input data: {e.msg}",
        )
    except DaciteError as e:
        _exit(
            communication.const.COM_STATUS_INPUT_ERROR,
            status_msg=str(e),
        )
    except Exception as e:
        # TODO: maybe add traceback?
        _exit(communication.const.COM_STATUS_EXCEPTION, status_msg=str(e))
Exemple #7
0
 def test_unfence_failure_unable_to_connect(self):
     self._unfence_failure_common_calls()
     self.config.http.corosync.get_corosync_online_targets(
         node_labels=self.existing_nodes)
     self.config.http.scsi.unfence_node(
         DEVICES_2,
         communication_list=[
             dict(
                 label=self.existing_nodes[0],
                 raw_data=json.dumps(
                     dict(devices=DEVICES_2, node=self.existing_nodes[0])),
                 was_connected=False,
                 error_msg="errA",
             ),
             dict(
                 label=self.existing_nodes[1],
                 raw_data=json.dumps(
                     dict(devices=DEVICES_2, node=self.existing_nodes[1])),
                 output=json.dumps(
                     dto.to_dict(
                         communication.dto.InternalCommunicationResultDto(
                             status=communication.const.COM_STATUS_ERROR,
                             status_msg="error",
                             report_list=[
                                 reports.ReportItem.error(
                                     reports.messages.
                                     StonithUnfencingFailed(
                                         "errB")).to_dto()
                             ],
                             data=None,
                         ))),
             ),
             dict(
                 label=self.existing_nodes[2],
                 raw_data=json.dumps(
                     dict(devices=DEVICES_2, node=self.existing_nodes[2])),
             ),
         ],
     )
     self.env_assist.assert_raise_library_error(
         lambda: stonith.update_scsi_devices(self.env_assist.get_env(),
                                             SCSI_STONITH_ID, DEVICES_2), )
     self.env_assist.assert_reports([
         fixture.error(
             reports.codes.NODE_COMMUNICATION_ERROR_UNABLE_TO_CONNECT,
             node=self.existing_nodes[0],
             command="api/v1/scsi-unfence-node/v1",
             reason="errA",
         ),
         fixture.error(
             reports.codes.STONITH_UNFENCING_FAILED,
             reason="errB",
             context=reports.dto.ReportItemContextDto(
                 node=self.existing_nodes[1], ),
         ),
     ])
Exemple #8
0
 def test_unfence_failure_unknown_command(self):
     self._unfence_failure_common_calls()
     self.config.http.corosync.get_corosync_online_targets(
         node_labels=self.existing_nodes
     )
     communication_list = [
         dict(
             label=node,
             raw_data=json.dumps(
                 dict(
                     node=node,
                     original_devices=DEVICES_1,
                     updated_devices=DEVICES_2,
                 )
             ),
         )
         for node in self.existing_nodes[0:2]
     ]
     communication_list.append(
         dict(
             label=self.existing_nodes[2],
             response_code=404,
             raw_data=json.dumps(
                 dict(
                     node=self.existing_nodes[2],
                     original_devices=DEVICES_1,
                     updated_devices=DEVICES_2,
                 )
             ),
             output=json.dumps(
                 dto.to_dict(
                     communication.dto.InternalCommunicationResultDto(
                         status=communication.const.COM_STATUS_UNKNOWN_CMD,
                         status_msg=(
                             "Unknown command '/api/v1/scsi-unfence-node/v2'"
                         ),
                         report_list=[],
                         data=None,
                     )
                 )
             ),
         ),
     )
     self.config.http.scsi.unfence_node(
         communication_list=communication_list
     )
     self.env_assist.assert_raise_library_error(self.command())
     self.env_assist.assert_reports(
         [
             fixture.error(
                 reports.codes.PCSD_VERSION_TOO_OLD,
                 node=self.existing_nodes[2],
             ),
         ]
     )
Exemple #9
0
 def test_simple_in_group(self):
     resources_members = ["outer:g1"]
     resources = {
         "d1": self.primitive_fixture("d1", resources_members),
         "d2": self.primitive_fixture("d2", resources_members),
         "g1": RelationEntityDto("g1", "group", ["inner:g1"], {"id": "g1"}),
     }
     relations = {
         "inner:g1":
         RelationEntityDto(
             "inner:g1",
             ResourceRelationType.INNER_RESOURCES,
             ["d1", "d2"],
             {"id": "g1"},
         ),
         "outer:g1":
         RelationEntityDto(
             "outer:g1",
             ResourceRelationType.OUTER_RESOURCE,
             ["g1"],
             {"id": "g1"},
         ),
     }
     expected = dict(
         relation_entity=dto.to_dict(resources["d1"]),
         is_leaf=False,
         members=[
             dict(
                 relation_entity=dto.to_dict(relations["outer:g1"]),
                 is_leaf=False,
                 members=[
                     dict(
                         relation_entity=dto.to_dict(resources["g1"]),
                         is_leaf=False,
                         members=[
                             dict(
                                 relation_entity=dto.to_dict(
                                     relations["inner:g1"]),
                                 is_leaf=False,
                                 members=[
                                     dict(
                                         relation_entity=dto.to_dict(
                                             resources["d2"]),
                                         is_leaf=False,
                                         members=[],
                                     ),
                                 ],
                             ),
                         ],
                     ),
                 ],
             ),
         ],
     )
     self.assertEqual(
         expected,
         dto.to_dict(
             lib.ResourceRelationTreeBuilder(
                 resources, relations).get_tree("d1").to_dto()),
     )
Exemple #10
0
    def unfence_node_mpath(
        self,
        node_key_map,
        original_devices=(),
        updated_devices=(),
        node_labels=None,
        communication_list=None,
        name="http.scsi.unfence_node",
    ):
        """
        Create a calls for node unfencing

        dict node_key_map -- map of node name to its registration key
        list original_devices -- list of scsi devices before an update
        list updated_devices -- list of scsi devices after an update
        list node_labels -- create success responses from these nodes
        list communication_list -- use these custom responses
        string name -- the key of this call
        """
        if (node_labels is None
                and communication_list is None) or (node_labels
                                                    and communication_list):
            raise AssertionError(
                "Exactly one of 'node_labels', 'communication_list' "
                "must be specified")

        if node_labels:
            communication_list = [
                dict(
                    label=node,
                    raw_data=json.dumps(
                        dict(
                            key=node_key_map[node],
                            original_devices=original_devices,
                            updated_devices=updated_devices,
                        )),
                ) for node in node_labels
            ]
        place_communication(
            self.__calls,
            name,
            communication_list,
            action="api/v1/scsi-unfence-node-mpath/v1",
            output=json.dumps(
                to_dict(
                    communication.dto.InternalCommunicationResultDto(
                        status=communication.const.COM_STATUS_SUCCESS,
                        status_msg=None,
                        report_list=[],
                        data=None,
                    ))),
        )
Exemple #11
0
def _action_dto_to_dict(
    dto: AgentActionDto,
    new_role_names_supported: bool,
) -> Dict[str, str]:
    result = dict(
        filter(
            lambda item: item[0] != "deph" and item[1] not in (None, ""),
            to_dict(dto).items(),
        ))
    if "role" in result:
        result["role"] = pacemaker.role.get_value_for_cib(
            result["role"], new_role_names_supported)
    return result
Exemple #12
0
def describe_agent(
    lib_env: LibraryEnvironment, agent_name: str
) -> Dict[str, Any]:
    """
    Get agent's description (metadata) in a structure

    agent_name -- name of the agent (not containing "stonith:" prefix)
    """
    agent = resource_agent.find_valid_stonith_agent_by_name(
        lib_env.report_processor,
        lib_env.cmd_runner(),
        agent_name,
        absent_agent_supported=False,
    )
    return to_dict(agent.get_full_info())
Exemple #13
0
 def test_get_specified(self):
     stdout, retval = self.pcs_runner.run(
         ["stonith", "config", "--output-format=json", "S1"],
         ignore_stderr=True,
     )
     self.assertEqual(retval, 0)
     expected = ListCibResourcesDto(
         primitives=[
             resources_dto.STONITH_S1,
         ],
         clones=[],
         groups=[],
         bundles=[],
     )
     self.assertEqual(json.loads(stdout), to_dict(expected))
Exemple #14
0
def _exit(
    status: communication.types.CommunicationResultStatus,
    status_msg: Optional[str] = None,
    report_list: Optional[ReportItemList] = None,
    data: Any = None,
) -> None:
    json.dump(
        dto.to_dict(
            communication.dto.InternalCommunicationResultDto(
                status,
                status_msg,
                [report.to_dto() for report in (report_list or [])],
                data,
            )),
        sys.stdout,
    )
    sys.exit(0)
Exemple #15
0
 def test_get_multiple(self):
     stdout, retval = self.pcs_runner.run(
         ["resource", "config", "--output-format=json", "G1-clone", "R1"]
     )
     self.assertEqual(retval, 0)
     expected = ListCibResourcesDto(
         primitives=[
             resources_dto.PRIMITIVE_R1,
             resources_dto.PRIMITIVE_R2,
             resources_dto.PRIMITIVE_R3,
             resources_dto.PRIMITIVE_R4,
         ],
         clones=[resources_dto.CLONE_G1],
         groups=[resources_dto.GROUP_G1],
         bundles=[],
     )
     self.assertEqual(json.loads(stdout), to_dict(expected))
Exemple #16
0
def operation_dto_to_legacy_dict(
    operation: CibResourceOperationDto,
    defaults: Mapping[str, Any],
) -> ResourceOperationOut:
    operation_dict = dict(defaults)
    operation_dict.update({
        key: value
        for key, value in to_dict(operation).items()
        if key in ("name", "timeout", "interval", "role")
    })
    operation_dict["start-delay"] = operation.start_delay
    operation_dict["OCF_CHECK_LEVEL"] = None
    for nvset in operation.instance_attributes:
        for nvpair in nvset.nvpairs:
            if nvpair.name == "OCF_CHECK_LEVEL":
                operation_dict["OCF_CHECK_LEVEL"] = nvpair.value
    return operation_dict
Exemple #17
0
def _agent_metadata_to_dict(agent: ResourceAgentMetadata,
                            describe: bool = False) -> Dict[str, str]:
    agent_dto = agent.to_dto()
    agent_dict = to_dict(agent_dto)
    del agent_dict["name"]
    agent_dict["name"] = agent.name.full_name
    agent_dict["standard"] = agent.name.standard
    agent_dict["provider"] = agent.name.provider
    agent_dict["type"] = agent.name.type

    agent_dict["actions"] = [
        action_to_operation(action, keep_extra_keys=True)
        for action in agent_dto.actions
    ]
    agent_dict["default_actions"] = (complete_operations_options(
        get_default_operations(agent, keep_extra_keys=True))
                                     if describe else [])
    return agent_dict
Exemple #18
0
    def unfence_node(
        self,
        devices,
        node_labels=None,
        communication_list=None,
        name="http.scsi.unfence_node",
    ):
        """
        Create a calls for node unfencing

        list devices -- list of scsi devices
        list node_labels -- create success responses from these nodes
        list communication_list -- use these custom responses
        string name -- the key of this call
        """
        if (node_labels is None
                and communication_list is None) or (node_labels
                                                    and communication_list):
            raise AssertionError(
                "Exactly one of 'node_labels', 'communication_list' "
                "must be specified")

        if node_labels:
            communication_list = [
                dict(
                    label=node,
                    raw_data=json.dumps(dict(devices=devices, node=node)),
                ) for node in node_labels
            ]
        place_communication(
            self.__calls,
            name,
            communication_list,
            action="api/v1/scsi-unfence-node/v1",
            output=json.dumps(
                to_dict(
                    communication.dto.InternalCommunicationResultDto(
                        status=communication.const.COM_STATUS_SUCCESS,
                        status_msg=None,
                        report_list=[],
                        data=None,
                    ))),
        )
Exemple #19
0
def _agent_metadata_to_dict(agent: ResourceAgentMetadata,
                            describe: bool = False) -> Dict[str, str]:
    agent_dto = agent.to_dto()
    agent_dict = to_dict(agent_dto)
    del agent_dict["name"]
    agent_dict["name"] = agent.name.full_name
    agent_dict["standard"] = agent.name.standard
    agent_dict["provider"] = agent.name.provider
    agent_dict["type"] = agent.name.type

    agent_dict["actions"] = [
        _action_to_operation(action) for action in agent_dto.actions
    ]
    operations_defaults = {
        OCF_CHECK_LEVEL_INSTANCE_ATTRIBUTE_NAME: None,
        "automatic": False,
        "on_target": False,
    }
    agent_dict["default_actions"] = ([
        operation_dto_to_legacy_dict(op, operations_defaults)
        for op in get_default_operations(agent)
    ] if describe else [])
    return agent_dict
Exemple #20
0
def action_to_operation(action: ResourceAgentActionDto,
                        keep_extra_keys: bool = False) -> ResourceOperationOut:
    """
    Transform agent action data to CIB operation data
    """
    # This function bridges new agent framework, which provides data in
    # dataclasses, to old resource create code and transforms new data
    # structures to a format expected by the old code. When resource create is
    # overhauled, this fuction is expected to be removed.
    operation = {}
    for key, value in to_dict(action).items():
        if key == "depth":
            # "None" values are not put to CIB, so this keeps the key in place
            # while making sure it's not put in CIB. I'm not sure why depth ==
            # 0 is treated like this, but I keep it in place so the behavior is
            # the same as it has been for a long time. If pcs starts using
            # depth / OCF_CHECK_LEVEL or there is other demand for it, consider
            # changing this so value of "0" is put in CIB.
            operation["OCF_CHECK_LEVEL"] = None if value == "0" else value
        elif key == "start_delay":
            operation["start-delay"] = value
        elif key in OPERATION_ATTRIBUTES or keep_extra_keys:
            operation[key] = value
    return operation
Exemple #21
0
 def setUp(self):
     self.lib_call = mock.Mock()
     self.lib = mock.Mock(spec_set=["resource"])
     self.lib.resource = mock.Mock(spec_set=["get_resource_relations_tree"])
     self.lib.resource.get_resource_relations_tree = self.lib_call
     self.lib_call.return_value = dto.to_dict(
         ResourceRelationDto(
             RelationEntityDto(
                 "d1",
                 ResourceRelationType.RSC_PRIMITIVE,
                 [],
                 {
                     "class": "ocf",
                     "provider": "pacemaker",
                     "type": "Dummy",
                 },
             ),
             [
                 ResourceRelationDto(
                     RelationEntityDto(
                         "order1",
                         ResourceRelationType.ORDER,
                         [],
                         {
                             "first-action": "start",
                             "first": "d1",
                             "then-action": "start",
                             "then": "d2",
                             "kind": "Mandatory",
                             "symmetrical": "true",
                         },
                     ),
                     [
                         ResourceRelationDto(
                             RelationEntityDto(
                                 "d2",
                                 ResourceRelationType.RSC_PRIMITIVE,
                                 [],
                                 {
                                     "class": "ocf",
                                     "provider": "heartbeat",
                                     "type": "Dummy",
                                 },
                             ),
                             [],
                             False,
                         ),
                     ],
                     False,
                 ),
                 ResourceRelationDto(
                     RelationEntityDto(
                         "inner:g1",
                         ResourceRelationType.INNER_RESOURCES,
                         [],
                         {},
                     ),
                     [
                         ResourceRelationDto(
                             RelationEntityDto(
                                 "g1", ResourceRelationType.RSC_GROUP, [],
                                 {}),
                             [],
                             True,
                         ),
                     ],
                     False,
                 ),
             ],
             False,
         ))
Exemple #22
0
 def test_order_loop(self):
     resources_members = ["order-d1-d2-mandatory", "order-d2-d1-mandatory"]
     resources = {
         "d1": self.primitive_fixture("d1", resources_members),
         "d2": self.primitive_fixture("d2", resources_members),
     }
     order_fixture = lambda r1, r2: RelationEntityDto(
         f"order-{r1}-{r2}-mandatory",
         ResourceRelationType.ORDER,
         members=[r1, r2],
         metadata={
             "id": f"order-{r1}-{r2}-mandatory",
             "first": r1,
             "first-action": "start",
             "then": r2,
             "then-action": "start",
             "kind": "Mandatory",
         },
     )
     relations = {
         "order-d1-d2-mandatory": order_fixture("d1", "d2"),
         "order-d2-d1-mandatory": order_fixture("d2", "d1"),
     }
     expected = dict(
         relation_entity=dto.to_dict(resources["d1"]),
         is_leaf=False,
         members=[
             dict(
                 relation_entity=dto.to_dict(
                     relations["order-d1-d2-mandatory"]),
                 is_leaf=False,
                 members=[
                     dict(
                         relation_entity=dto.to_dict(resources["d2"]),
                         is_leaf=False,
                         members=[
                             dict(
                                 relation_entity=dto.to_dict(
                                     relations["order-d2-d1-mandatory"]),
                                 is_leaf=True,
                                 members=[],
                             ),
                         ],
                     ),
                 ],
             ),
             dict(
                 relation_entity=dto.to_dict(
                     relations["order-d2-d1-mandatory"]),
                 is_leaf=False,
                 members=[
                     dict(
                         relation_entity=dto.to_dict(resources["d2"]),
                         is_leaf=True,
                         members=[],
                     ),
                 ],
             ),
         ],
     )
     self.assertEqual(
         expected,
         dto.to_dict(
             lib.ResourceRelationTreeBuilder(
                 resources, relations).get_tree("d1").to_dto()),
     )
Exemple #23
0
 def test_simple_order_set(self):
     res_list = ("d1", "d2", "d3", "d4", "d5", "d6")
     resources_members = ["pcs_rsc_order_set_1"]
     resources = {
         _id: self.primitive_fixture(_id, resources_members)
         for _id in res_list
     }
     relations = {
         "pcs_rsc_order_set_1":
         RelationEntityDto(
             "pcs_rsc_order_set_1",
             ResourceRelationType.ORDER_SET,
             members=["d1", "d2", "d3", "d4", "d5", "d6"],
             metadata={
                 "id":
                 "pcs_rsc_order_set_1",
                 "sets": [
                     {
                         "id": "pcs_rsc_set_1",
                         "metadata": {
                             "id": "pcs_rsc_set_1",
                             "sequential": "true",
                             "require-all": "true",
                             "action": "start",
                         },
                         "members": ["d1", "d3", "d2"],
                     },
                     {
                         "id": "pcs_rsc_set_2",
                         "metadata": {
                             "id": "pcs_rsc_set_2",
                             "sequential": "false",
                             "require-all": "false",
                             "action": "stop",
                         },
                         "members": ["d6", "d5", "d4"],
                     },
                 ],
                 "kind":
                 "Serialize",
                 "symmetrical":
                 "true",
             },
         ),
     }
     get_res = lambda _id: dict(
         relation_entity=dto.to_dict(resources[_id]),
         is_leaf=False,
         members=[],
     )
     expected = dict(
         relation_entity=dto.to_dict(resources["d5"]),
         is_leaf=False,
         members=[
             dict(
                 relation_entity=dto.to_dict(
                     relations["pcs_rsc_order_set_1"]),
                 is_leaf=False,
                 members=[
                     get_res(_id) for _id in ("d1", "d2", "d3", "d4", "d6")
                 ],
             )
         ],
     )
     self.assertEqual(
         expected,
         dto.to_dict(
             lib.ResourceRelationTreeBuilder(
                 resources, relations).get_tree("d5").to_dto()),
     )
Exemple #24
0
 def test_simple_to_dict(self):
     self.assertEqual(to_dict(self.simple_dto), self.simple_dict)
Exemple #25
0
def status_all_sites_plaintext(
    env: LibraryEnvironment,
    hide_inactive_resources: bool = False,
    verbose: bool = False,
) -> List[Mapping[str, Any]]:
    """
    Return local site's and all remote sites' status as plaintext

    env -- LibraryEnvironment
    hide_inactive_resources -- if True, do not display non-running resources
    verbose -- if True, display more info
    """

    # The command does not provide an option to skip offline / unreacheable /
    # misbehaving nodes.
    # The point of such skipping is to stop a command if it is unable to make
    # changes on all nodes. The user can then decide to proceed anyway and
    # make changes on the skipped nodes later manually.
    # This command only reads from nodes so it automatically asks other nodes
    # if one is offline / misbehaving.
    class SiteData():
        def __init__(
            self,
            local: bool,
            role: DrRole,
            target_list: Iterable[RequestTarget],
        ) -> None:
            self.local = local
            self.role = role
            self.target_list = target_list
            self.status_loaded = False
            self.status_plaintext = ""

    if env.ghost_file_codes:
        raise LibraryError(
            reports.live_environment_required(env.ghost_file_codes))

    report_processor = env.report_processor
    report_list, dr_config = _load_dr_config(env.get_dr_env().config)
    report_processor.report_list(report_list)
    if report_processor.has_errors:
        raise LibraryError()

    site_data_list = []
    target_factory = env.get_node_target_factory()

    # get local nodes
    local_nodes, report_list = get_existing_nodes_names(
        env.get_corosync_conf())
    report_processor.report_list(report_list)
    report_list, local_targets = target_factory.get_target_list_with_reports(
        local_nodes,
        skip_non_existing=True,
    )
    report_processor.report_list(report_list)
    site_data_list.append(SiteData(True, dr_config.local_role, local_targets))

    # get remote sites' nodes
    for conf_remote_site in dr_config.get_remote_site_list():
        report_list, remote_targets = (
            target_factory.get_target_list_with_reports(
                conf_remote_site.node_name_list,
                skip_non_existing=True,
            ))
        report_processor.report_list(report_list)
        site_data_list.append(
            SiteData(False, conf_remote_site.role, remote_targets))
    if report_processor.has_errors:
        raise LibraryError()

    # get all statuses
    for site_data in site_data_list:
        com_cmd = GetFullClusterStatusPlaintext(
            report_processor,
            hide_inactive_resources=hide_inactive_resources,
            verbose=verbose,
        )
        com_cmd.set_targets(site_data.target_list)
        site_data.status_loaded, site_data.status_plaintext = run_com_cmd(
            env.get_node_communicator(), com_cmd)

    return [
        dto.to_dict(
            DrSiteStatusDto(
                local_site=site_data.local,
                site_role=site_data.role,
                status_plaintext=site_data.status_plaintext,
                status_successfully_obtained=site_data.status_loaded,
            )) for site_data in site_data_list
    ]
Exemple #26
0
 def test_any_is_dict(self):
     dto = DtoWithAny("a", {1: "1", 2: "2"})
     self.assertEqual(dict(field_a="a", field_b={
         1: "1",
         2: "2"
     }), to_dict(dto))
Exemple #27
0
 def test_nested_to_dict(self):
     self.assertEqual(to_dict(self.nested_dto), self.nested_dict)
Exemple #28
0
 def assert_dto_equal(self, expected, actual):
     self.assertEqual(dto.to_dict(expected), dto.to_dict(actual))
Exemple #29
0
 def test_any_is_list(self):
     dto = DtoWithAny("a", [1, 2])
     self.assertEqual(dict(field_a="a", field_b=[1, 2]), to_dict(dto))
Exemple #30
0
 def test_unfence_failure_agent_script_failed(self):
     self._unfence_failure_common_calls()
     self.config.http.corosync.get_corosync_online_targets(
         node_labels=self.existing_nodes
     )
     self.config.http.scsi.unfence_node(
         communication_list=[
             dict(
                 label=self.existing_nodes[0],
                 raw_data=json.dumps(
                     dict(
                         node=self.existing_nodes[0],
                         original_devices=DEVICES_1,
                         updated_devices=DEVICES_2,
                     )
                 ),
             ),
             dict(
                 label=self.existing_nodes[1],
                 raw_data=json.dumps(
                     dict(
                         node=self.existing_nodes[1],
                         original_devices=DEVICES_1,
                         updated_devices=DEVICES_2,
                     )
                 ),
                 output=json.dumps(
                     dto.to_dict(
                         communication.dto.InternalCommunicationResultDto(
                             status=communication.const.COM_STATUS_ERROR,
                             status_msg="error",
                             report_list=[
                                 reports.ReportItem.error(
                                     reports.messages.StonithUnfencingFailed(
                                         "errB"
                                     )
                                 ).to_dto()
                             ],
                             data=None,
                         )
                     )
                 ),
             ),
             dict(
                 label=self.existing_nodes[2],
                 raw_data=json.dumps(
                     dict(
                         node=self.existing_nodes[2],
                         original_devices=DEVICES_1,
                         updated_devices=DEVICES_2,
                     )
                 ),
             ),
         ],
     )
     self.env_assist.assert_raise_library_error(self.command())
     self.env_assist.assert_reports(
         [
             fixture.error(
                 reports.codes.STONITH_UNFENCING_FAILED,
                 reason="errB",
                 context=reports.dto.ReportItemContextDto(
                     node=self.existing_nodes[1],
                 ),
             ),
         ]
     )