Пример #1
0
def get_local_node_status(runner):
    try:
        cluster_status = ClusterState(get_cluster_status_dom(runner))
        node_name = get_local_node_name(runner)
    except PacemakerNotConnectedException:
        return {"offline": True}
    for node_status in cluster_status.node_section.nodes:
        if node_status.attrs.name == node_name:
            result = {
                "offline": False,
            }
            for attr in (
                    "id",
                    "name",
                    "type",
                    "online",
                    "standby",
                    "standby_onfail",
                    "maintenance",
                    "pending",
                    "unclean",
                    "shutdown",
                    "expected_up",
                    "is_dc",
                    "resources_running",
            ):
                result[attr] = getattr(node_status.attrs, attr)
            return result
    raise LibraryError(
        ReportItem.error(reports.messages.NodeNotFound(node_name)))
Пример #2
0
def verify(env, verbose=False):
    runner = env.cmd_runner()
    dummy_stdout, verify_stderr, verify_returncode = verify_cmd(
        runner,
        verbose=verbose,
    )

    #1) Do not even try to think about upgrading!
    #2) We do not need cib management in env (no need for push...).
    #So env.get_cib is not best choice here (there were considerations to
    #upgrade cib at all times inside env.get_cib). Go to a lower level here.
    if verify_returncode != 0:
        env.report_processor.append(reports.invalid_cib_content(verify_stderr))

        #Cib is sometimes loadable even if `crm_verify` fails (e.g. when
        #fencing topology is invalid). On the other hand cib with id duplication
        #is not loadable.
        #We try extra checks when cib is possible to load.
        cib_xml, dummy_stderr, returncode = get_cib_xml_cmd_results(runner)
        if returncode != 0:
            #can raise; raise LibraryError is better but in this case we prefer
            #be consistent with raising below
            env.report_processor.send()
    else:
        cib_xml = get_cib_xml(runner)

    cib = get_cib(cib_xml)
    fencing_topology.verify(
        env.report_processor, get_fencing_topology(cib), get_resources(cib),
        ClusterState(get_cluster_status_xml(runner)).node_section.nodes)
    #can raise
    env.report_processor.send()
Пример #3
0
 def get_status(self):
     return ClusterState("""
         <crm_mon version="2.0.3">
             <summary>
                 <stack type="corosync" />
                 <current_dc present="true" />
                 <last_update time="Wed Nov  6 13:45:41 2019" />
                 <last_change time="Wed Nov  6 10:42:54 2019"
                     user="******" client="crmd" origin="node1"
                 />
                 <nodes_configured number="2" />
                 <resources_configured number="0" disabled="0" blocked="0" />
                 <cluster_options stonith-enabled="true"
                     symmetric-cluster="true" no-quorum-policy="stop"
                     maintenance-mode="false"
                 />
             </summary>
             <nodes>
                 <node name="nodeA" id="1" online="true" standby="false"
                     standby_onfail="false" maintenance="false"
                     pending="false" unclean="false" shutdown="false"
                     expected_up="true" is_dc="true" resources_running="0"
                     type="member"
                 />
                 <node name="nodeB" id="2" online="true" standby="false"
                     standby_onfail="false" maintenance="false"
                     pending="false" unclean="false" shutdown="false"
                     expected_up="true" is_dc="false" resources_running="0"
                     type="member"
                 />
             </nodes>
         </crm_mon>
     """).node_section.nodes
Пример #4
0
def get_local_node_status(runner):
    try:
        cluster_status = ClusterState(get_cluster_status_xml(runner))
    except CrmMonErrorException:
        return {"offline": True}
    node_name = get_local_node_name(runner)
    for node_status in cluster_status.node_section.nodes:
        if node_status.attrs.name == node_name:
            result = {
                "offline": False,
            }
            for attr in (
                    'id',
                    'name',
                    'type',
                    'online',
                    'standby',
                    'standby_onfail',
                    'maintenance',
                    'pending',
                    'unclean',
                    'shutdown',
                    'expected_up',
                    'is_dc',
                    'resources_running',
            ):
                result[attr] = getattr(node_status.attrs, attr)
            return result
    raise LibraryError(reports.node_not_found(node_name))
Пример #5
0
def resource_refresh(
    runner: CommandRunner,
    resource: Optional[str] = None,
    node: Optional[str] = None,
    strict: bool = False,
    force: bool = False,
):
    if not force and not node and not resource:
        summary = ClusterState(get_cluster_status_xml(runner)).summary
        operations = summary.nodes.attrs.count * summary.resources.attrs.count
        if operations > __RESOURCE_REFRESH_OPERATION_COUNT_THRESHOLD:
            raise LibraryError(
                reports.resource_refresh_too_time_consuming(
                    __RESOURCE_REFRESH_OPERATION_COUNT_THRESHOLD))

    cmd = [__exec("crm_resource"), "--refresh"]
    if resource:
        cmd.extend(["--resource", resource])
    if node:
        cmd.extend(["--node", node])
    if strict:
        cmd.extend(["--force"])

    stdout, stderr, retval = runner.run(cmd)

    if retval != 0:
        raise LibraryError(
            reports.resource_refresh_error(join_multilines([stderr, stdout]),
                                           resource, node))
    # usefull output (what has been done) goes to stderr
    return join_multilines([stdout, stderr])
Пример #6
0
def add_level(lib_env,
              level,
              target_type,
              target_value,
              devices,
              force_device=False,
              force_node=False):
    """
    Validate and add a new fencing level

    LibraryError lib_env -- environment
    int|string level -- level (index) of the new fencing level
    constant target_type -- the new fencing level target value type
    mixed target_value -- the new fencing level target value
    Iterable devices -- list of stonith devices for the new fencing level
    bool force_device -- continue even if a stonith device does not exist
    bool force_node -- continue even if a node (target) does not exist
    """
    version_check = None
    if target_type == TARGET_TYPE_REGEXP:
        version_check = (2, 3, 0)
    elif target_type == TARGET_TYPE_ATTRIBUTE:
        version_check = (2, 4, 0)

    cib = lib_env.get_cib(version_check)
    cib_fencing_topology.add_level(
        lib_env.report_processor, get_fencing_topology(cib),
        get_resources(cib), level, target_type, target_value, devices,
        ClusterState(get_cluster_status_xml(
            lib_env.cmd_runner())).node_section.nodes, force_device,
        force_node)
    lib_env.report_processor.send()
    lib_env.push_cib()
Пример #7
0
    def test_refuse_invalid_document(self):
        self.covered_status.append_to_first_tag_name(
            'nodes', '<node without="required attributes" />')

        assert_raise_library_error(
            lambda: ClusterState(str(self.covered_status)),
            (severities.ERROR, report_codes.BAD_CLUSTER_STATE_FORMAT, {}))
Пример #8
0
    def setUp(self):
        self.node1 = etree.fromstring("""
            <node id="1" uname="name-test1" type="member" />
        """)
        self.node2 = etree.fromstring("""
            <node id="2" uname="name-test2" type="member" />
        """)
        self.nodes = etree.Element("nodes")
        self.nodes.append(self.node1)

        self.state = ClusterState("""
            <crm_mon version="1.1.15">
                <summary>
                    <current_dc present="true" />
                    <nodes_configured number="2" expected_votes="unknown" />
                    <resources_configured number="0" />
                </summary>
                <nodes>
                    <node name="name-test1" id="1" online="true" standby="false"
                        standby_onfail="false" maintenance="false"
                        pending="false" unclean="false" shutdown="false"
                        expected_up="true" is_dc="true" resources_running="0"
                        type="member"
                    />
                    <node name="name-test2" id="2" online="true" standby="false"
                        standby_onfail="false" maintenance="false"
                        pending="false" unclean="false" shutdown="false"
                        expected_up="true" is_dc="false" resources_running="0"
                        type="member"
                    />
                </nodes>
            </crm_mon>
        """).node_section.nodes
Пример #9
0
 def test_resources_count(self):
     with open(rc("crm_mon.minimal.xml")) as crm_mon_file:
         crm_mon_xml = crm_mon_file.read()
     self.assertEqual(
         0,
         ClusterState(
             complete_state(crm_mon_xml)).summary.resources.attrs.count,
     )
Пример #10
0
def cib_runner_nodes(lib_env: LibraryEnvironment, wait: WaitType):
    wait_timeout = lib_env.ensure_wait_satisfiable(wait)
    yield (
        lib_env.get_cib(),
        lib_env.cmd_runner(),
        ClusterState(lib_env.get_cluster_state()).node_section.nodes,
    )
    lib_env.push_cib(wait_timeout=wait_timeout)
Пример #11
0
    def test_refuse_invalid_document(self, mock_validate):
        mock_validate.side_effect = etree.DocumentInvalid("some error")
        self.covered_status.append_to_first_tag_name(
            "nodes", '<node without="required attributes" />')

        assert_raise_library_error(
            lambda: ClusterState(str(self.covered_status)),
            (severities.ERROR, report_codes.BAD_CLUSTER_STATE_FORMAT, {}),
        )
Пример #12
0
def cib_runner_nodes(lib_env, wait):
    lib_env.ensure_wait_satisfiable(wait)
    runner = lib_env.cmd_runner()

    state_nodes = ClusterState(
        get_cluster_status_xml(runner)).node_section.nodes

    yield (lib_env.get_cib(), runner, state_nodes)
    lib_env.push_cib(wait=wait)
Пример #13
0
 def test_can_get_node_names(self):
     self.covered_status.append_to_first_tag_name(
         'nodes',
         self.fixture_node_string(name='node1', id='1'),
         self.fixture_node_string(name='node2', id='2'),
     )
     xml = str(self.covered_status)
     self.assertEqual(
         ['node1', 'node2'],
         [node.attrs.name for node in ClusterState(xml).node_section.nodes])
Пример #14
0
 def test_can_get_node_names(self):
     self.covered_status.append_to_first_tag_name(
         "nodes",
         self.fixture_node_string(name="node1", id="1"),
         self.fixture_node_string(name="node2", id="2"),
     )
     xml = str(self.covered_status)
     self.assertEqual(
         ["node1", "node2"],
         [node.attrs.name for node in ClusterState(xml).node_section.nodes],
     )
Пример #15
0
 def test_can_filter_out_remote_nodes(self):
     self.covered_status.append_to_first_tag_name(
         'nodes',
         self.fixture_node_string(name='node1', id='1'),
         self.fixture_node_string(name='node2', type='remote', id='2'),
     )
     xml = str(self.covered_status)
     self.assertEqual(['node1'], [
         node.attrs.name for node in ClusterState(xml).node_section.nodes
         if node.attrs.type != 'remote'
     ])
Пример #16
0
 def get_status(self):
     with open(rc("crm_mon.minimal.xml")) as crm_mon_file:
         crm_mon_xml = crm_mon_file.read()
     return ClusterState(
         fixture_crm_mon.complete_state(
             crm_mon_xml,
             nodes_xml="""
             <nodes>
                 <node name="nodeA" id="1" is_dc="true" />
                 <node name="nodeB" id="2" />
             </nodes>
         """,
         )).node_section.nodes
Пример #17
0
def verify(lib_env):
    """
    Check if all cluster nodes and stonith devices used in fencing levels exist

    LibraryError lib_env -- environment
    """
    cib = lib_env.get_cib()
    cib_fencing_topology.verify(
        lib_env.report_processor, get_fencing_topology(cib),
        get_resources(cib),
        ClusterState(get_cluster_status_xml(
            lib_env.cmd_runner())).node_section.nodes)
    lib_env.report_processor.send()
Пример #18
0
def verify(lib_env: LibraryEnvironment):
    """
    Check if all cluster nodes and stonith devices used in fencing levels exist

    LibraryEnvironment lib_env -- environment
    """
    cib = lib_env.get_cib()
    lib_env.report_processor.report_list(
        cib_fencing_topology.verify(
            get_fencing_topology(cib),
            get_resources(cib),
            ClusterState(lib_env.get_cluster_state()).node_section.nodes,
        ))
    if lib_env.report_processor.has_errors:
        raise LibraryError()
Пример #19
0
 def test_can_filter_out_remote_nodes(self):
     self.covered_status.append_to_first_tag_name(
         "nodes",
         self.fixture_node_string(name="node1", id="1"),
         self.fixture_node_string(name="node2", type="remote", id="2"),
     )
     xml = str(self.covered_status)
     self.assertEqual(
         ["node1"],
         [
             node.attrs.name
             for node in ClusterState(xml).node_section.nodes
             if node.attrs.type != "remote"
         ],
     )
Пример #20
0
 def test_can_get_node_names(self):
     with open(rc("crm_mon.minimal.xml")) as crm_mon_file:
         crm_mon_xml = crm_mon_file.read()
     state_dom = complete_state(
         crm_mon_xml,
         nodes_xml="""
             <nodes>
                 <node name="node1" id="1" />
                 <node name="node2" id="2" />
             </nodes>
         """,
     )
     self.assertEqual(
         ["node1", "node2"],
         [
             node.attrs.name
             for node in ClusterState(state_dom).node_section.nodes
         ],
     )
Пример #21
0
def add_level(
    lib_env: LibraryEnvironment,
    level,
    target_type,
    target_value,
    devices,
    force_device=False,
    force_node=False,
):
    """
    Validate and add a new fencing level

    LibraryEnvironment lib_env -- environment
    int|string level -- level (index) of the new fencing level
    constant target_type -- the new fencing level target value type
    mixed target_value -- the new fencing level target value
    Iterable devices -- list of stonith devices for the new fencing level
    bool force_device -- continue even if a stonith device does not exist
    bool force_node -- continue even if a node (target) does not exist
    """
    cib = lib_env.get_cib()
    cib_fencing_topology.add_level(
        lib_env.report_processor,
        get_fencing_topology(cib),
        get_resources(cib),
        level,
        target_type,
        target_value,
        devices,
        ClusterState(lib_env.get_cluster_state()).node_section.nodes,
        force_device,
        force_node,
    )
    if lib_env.report_processor.has_errors:
        raise LibraryError()
    lib_env.push_cib()
Пример #22
0
 def get_status(self):
     return ClusterState("""
         <crm_mon version="1.1.15">
             <summary>
                 <current_dc present="true" />
                 <nodes_configured number="2" expected_votes="unknown" />
                 <resources_configured number="0" />
             </summary>
             <nodes>
                 <node name="nodeA" id="1" online="true" standby="false"
                     standby_onfail="false" maintenance="false"
                     pending="false" unclean="false" shutdown="false"
                     expected_up="true" is_dc="true" resources_running="0"
                     type="member"
                 />
                 <node name="nodeB" id="2" online="true" standby="false"
                     standby_onfail="false" maintenance="false"
                     pending="false" unclean="false" shutdown="false"
                     expected_up="true" is_dc="false" resources_running="0"
                     type="member"
                 />
             </nodes>
         </crm_mon>
     """).node_section.nodes
Пример #23
0
def nodes_status(lib, argv, modifiers):
    """
    Options:
      * -f - CIB file - for config subcommand and not for both or corosync
      * --corosync_conf - only for config subcommand

    NOTE: modifiers check is in subcommand
    """
    del lib
    if len(argv) == 1 and (argv[0] == "config"):
        modifiers.ensure_only_supported("-f", "--corosync_conf")
        if utils.hasCorosyncConf():
            corosync_nodes, report_list = get_existing_nodes_names(
                utils.get_corosync_conf_facade())
            if report_list:
                process_library_reports(report_list)
        else:
            corosync_nodes = []
        try:
            pacemaker_nodes = sorted([
                node.attrs.name for node in ClusterState(
                    get_cluster_status_dom(
                        utils.cmd_runner())).node_section.nodes
                if node.attrs.type != "remote"
            ])
        except LibraryError as e:
            process_library_reports(e.args)
        print("Corosync Nodes:")
        if corosync_nodes:
            print(" " + " ".join(corosync_nodes))
        print("Pacemaker Nodes:")
        if pacemaker_nodes:
            print(" " + " ".join(pacemaker_nodes))

        return

    if len(argv) == 1 and (argv[0] == "corosync" or argv[0] == "both"):
        modifiers.ensure_only_supported()
        all_nodes, report_list = get_existing_nodes_names(
            utils.get_corosync_conf_facade())
        if report_list:
            process_library_reports(report_list)
        online_nodes = utils.getCorosyncActiveNodes()
        offline_nodes = []
        for node in all_nodes:
            if node not in online_nodes:
                offline_nodes.append(node)

        online_nodes.sort()
        offline_nodes.sort()
        print("Corosync Nodes:")
        print(" ".join([" Online:"] + online_nodes))
        print(" ".join([" Offline:"] + offline_nodes))
        if argv[0] != "both":
            sys.exit(0)

    modifiers.ensure_only_supported("-f")
    info_dom = utils.getClusterState()

    nodes = info_dom.getElementsByTagName("nodes")
    if nodes.length == 0:
        utils.err("No nodes section found")

    onlinenodes = []
    offlinenodes = []
    standbynodes = []
    standbynodes_with_resources = []
    maintenancenodes = []
    remote_onlinenodes = []
    remote_offlinenodes = []
    remote_standbynodes = []
    remote_standbynodes_with_resources = []
    remote_maintenancenodes = []
    for node in nodes[0].getElementsByTagName("node"):
        node_name = node.getAttribute("name")
        node_remote = node.getAttribute("type") == "remote"
        if node.getAttribute("online") == "true":
            if node.getAttribute("standby") == "true":
                is_running_resources = (node.getAttribute("resources_running")
                                        != "0")
                if node_remote:
                    if is_running_resources:
                        remote_standbynodes_with_resources.append(node_name)
                    else:
                        remote_standbynodes.append(node_name)
                else:
                    if is_running_resources:
                        standbynodes_with_resources.append(node_name)
                    else:
                        standbynodes.append(node_name)
            if node.getAttribute("maintenance") == "true":
                if node_remote:
                    remote_maintenancenodes.append(node_name)
                else:
                    maintenancenodes.append(node_name)
            if (node.getAttribute("standby") == "false"
                    and node.getAttribute("maintenance") == "false"):
                if node_remote:
                    remote_onlinenodes.append(node_name)
                else:
                    onlinenodes.append(node_name)
        else:
            if node_remote:
                remote_offlinenodes.append(node_name)
            else:
                offlinenodes.append(node_name)

    print("Pacemaker Nodes:")
    print(" ".join([" Online:"] + onlinenodes))
    print(" ".join([" Standby:"] + standbynodes))
    print(" ".join([" Standby with resource(s) running:"] +
                   standbynodes_with_resources))
    print(" ".join([" Maintenance:"] + maintenancenodes))
    print(" ".join([" Offline:"] + offlinenodes))

    print("Pacemaker Remote Nodes:")
    print(" ".join([" Online:"] + remote_onlinenodes))
    print(" ".join([" Standby:"] + remote_standbynodes))
    print(" ".join([" Standby with resource(s) running:"] +
                   remote_standbynodes_with_resources))
    print(" ".join([" Maintenance:"] + remote_maintenancenodes))
    print(" ".join([" Offline:"] + remote_offlinenodes))
Пример #24
0
def nodes_status(argv):
    if len(argv) == 1 and (argv[0] == "config"):
        if utils.hasCorosyncConf():
            corosync_nodes = utils.get_corosync_conf_facade().get_nodes_names()
        else:
            corosync_nodes = []
        try:
            pacemaker_nodes = sorted([
                node.attrs.name for node in ClusterState(
                    utils.getClusterStateXml()).node_section.nodes
                if node.attrs.type != 'remote'
            ])
        except LibraryError as e:
            utils.process_library_reports(e.args)
        print("Corosync Nodes:")
        if corosync_nodes:
            print(" " + " ".join(corosync_nodes))
        print("Pacemaker Nodes:")
        if pacemaker_nodes:
            print(" " + " ".join(pacemaker_nodes))

        return

    if len(argv) == 1 and (argv[0] == "corosync" or argv[0] == "both"):
        all_nodes = utils.get_corosync_conf_facade().get_nodes_names()
        online_nodes = utils.getCorosyncActiveNodes()
        offline_nodes = []
        for node in all_nodes:
            if node not in online_nodes:
                offline_nodes.append(node)

        online_nodes.sort()
        offline_nodes.sort()
        print("Corosync Nodes:")
        print(" ".join([" Online:"] + online_nodes))
        print(" ".join([" Offline:"] + offline_nodes))
        if argv[0] != "both":
            sys.exit(0)

    info_dom = utils.getClusterState()

    nodes = info_dom.getElementsByTagName("nodes")
    if nodes.length == 0:
        utils.err("No nodes section found")

    onlinenodes = []
    offlinenodes = []
    standbynodes = []
    maintenancenodes = []
    remote_onlinenodes = []
    remote_offlinenodes = []
    remote_standbynodes = []
    remote_maintenancenodes = []
    for node in nodes[0].getElementsByTagName("node"):
        node_name = node.getAttribute("name")
        node_remote = node.getAttribute("type") == "remote"
        if node.getAttribute("online") == "true":
            if node.getAttribute("standby") == "true":
                if node_remote:
                    remote_standbynodes.append(node_name)
                else:
                    standbynodes.append(node_name)
            elif node.getAttribute("maintenance") == "true":
                if node_remote:
                    remote_maintenancenodes.append(node_name)
                else:
                    maintenancenodes.append(node_name)
            else:
                if node_remote:
                    remote_onlinenodes.append(node_name)
                else:
                    onlinenodes.append(node_name)
        else:
            if node_remote:
                remote_offlinenodes.append(node_name)
            else:
                offlinenodes.append(node_name)

    print("Pacemaker Nodes:")
    print(" ".join([" Online:"] + onlinenodes))
    print(" ".join([" Standby:"] + standbynodes))
    print(" ".join([" Maintenance:"] + maintenancenodes))
    print(" ".join([" Offline:"] + offlinenodes))

    print("Pacemaker Remote Nodes:")
    print(" ".join([" Online:"] + remote_onlinenodes))
    print(" ".join([" Standby:"] + remote_standbynodes))
    print(" ".join([" Maintenance:"] + remote_maintenancenodes))
    print(" ".join([" Offline:"] + remote_offlinenodes))
Пример #25
0
 def test_refuse_invalid_xml(self):
     assert_raise_library_error(
         lambda: ClusterState('invalid xml'),
         (severities.ERROR, report_codes.BAD_CLUSTER_STATE_FORMAT, {}))
Пример #26
0
 def test_minimal_crm_mon_is_valid(self):
     ClusterState(str(self.covered_status))
Пример #27
0
 def test_resources_count(self):
     xml = str(self.covered_status)
     self.assertEqual(0, ClusterState(xml).summary.resources.attrs.count)