Source code for insights.parsers.pcs_status

"""
PCSStatus - command ``pcs status``
==================================

This module provides the classs ``PCSStatus`` which processes
``/usr/sbin/pcs status`` command output. Typical output of the ``pcs status``
command looks like::

    Cluster name: mycluster
    Last updated: Thu Dec  1 02:33:50 2016		Last change: Wed Aug  3 03:47:11 2016 by root via cibadmin on nodea.example.com
    Stack: corosync
    Current DC: nodea.example.com (version 1.1.13-10.el7-44eb2dd) - partition WITHOUT quorum
    3 nodes and 3 resources configured

    Online: [ nodea.example.com ]
    OFFLINE: [ nodeb.example.com nodec.example.com ]

    Full list of resources:
        myfence	(stonith:fence_xvm):	Stopped
        Resource Group: myweb
            webVIP	(ocf::heartbeat:IPaddr2):	Stopped
            webserver	(ocf::heartbeat:apache):	Stopped
    PCSD Status:
        nodea.example.com: Online
        nodeb.example.com: Offline
        nodec.example.com: Offline
    Daemon Status:
        corosync: active/enabled
        pacemaker: active/enabled
        pcsd: active/enabled

The class ``PCSStatus`` has one attribute ``nodes`` whick is a list containing all
node names that from ``PCSD Status`` section.


Examples:

    >>> pcsstatus_content = '''
    ... Cluster name: openstack
    ... Last updated: Fri Oct 14 15:45:32 2016
    ... Last change: Thu Oct 13 20:02:27 2016
    ... Stack: corosync
    ... Current DC: myhost15 (1) - partition with quorum
    ... Version: 1.1.12-a14efad
    ... 3 Nodes configured
    ... 143 Resources configured
    ... online: [ myhost15 myhost16 myhost17 ]
    ... Full list of resources:
    ... stonith-ipmilan-10.24.221.172	(stonith:fence_ipmilan):	Started myhost15
    ... stonith-ipmilan-10.24.221.171	(stonith:fence_ipmilan):	Started myhost16
    ... stonith-ipmilan-10.24.221.173	(stonith:fence_ipmilan):	Started myhost15
    ... PCSD Status:
    ...     myhost15: Online
    ...     myhost17: Online
    ...     myhost16: Online
    ... Daemon Status:
    ...    corosync: active/enabled
    ...    pacemaker: active/enabled
    ...    pcsd: active/enabled
    ... '''.strip()
    >>> from insights.tests import context_wrap
    >>> shared = {PCSStatus: PCSStatus(context_wrap(pcsstatus_content))}
    >>> pcsstatus_info = shared[PCSStatus]
    >>> pcsstatus_info.get("Cluster name")
    'openstack'
    >>> pcsstatus_info.get("Stack")
    'corosync'
    >>> pcsstatus_info.get("Nodes configured")
    '3'
    >>> pcsstatus_info.get("Resources configured")
    '143'
    >>> pcsstatus_info.nodes
    ['myhost15', 'myhost17', 'myhost16']
    >>> len(pcsstatus_info.get("Full list of resources"))
    3
"""
from insights import parser, CommandParser
from insights.specs import Specs


[docs] @parser(Specs.pcs_status) class PCSStatus(CommandParser, dict): """Class to process the output of ``pcs status`` command. Sample Output:: { "Resources configured": "143", "PCSD Status": [ "myhost15: Online", "myhost17: Online", "myhost16: Online" ], "Current DC": "myhost15 (1) - partition with quorum", "Full list of resources": [ "stonith-ipmilan-10.24.221.172\t(stonith:fence_ipmilan):\tStarted myhost15", "stonith-ipmilan-10.24.221.171\t(stonith:fence_ipmilan):\tStarted myhost16", "stonith-ipmilan-10.24.221.173\t(stonith:fence_ipmilan):\tStarted myhost15", ], "Daemon Status": [ "corosync: active/enabled", "pacemaker: active/enabled", "pcsd: active/enabled" ], "Nodes configured": "3", "Online": "[ myhost15 myhost16 myhost17 ]", "Cluster name": "openstack", "Stack": "corosync" } Attributes: nodes (list): A list containing all node names according "PCSD Status" section """
[docs] def parse_content(self, content): self.nodes = [] self.bad_nodes = [] # according this file https://github.com/ClusterLabs/pacemaker/blob/d078ca4a9ac72fc96073a215da2eed48939536f5/tools/crm_mon.c key_oneline = ( "Cluster name", "Stack", "Current DC", "Online", "RemoteOnline", "OFFLINE", "RemoteOFFLINE", "GuestOnline") key_nextline_titles = ( "Full list of resources", "Full List of Resources", "Failed Actions", "Failed Resource Actions", "Failed Fencing Actions", "PCSD Status", "Daemon Status", "Migration Summary", "Fencing History", "Node List", "Node Attributes", "Tickets" ) # pacemaker changes some prefix after version 1.0 and 2.0 key_nextline_alias = { "Full List of Resources": "Full list of resources", "Failed Resource Actions": "Failed Actions", # "Failed Actions" was renamed to "Failed Resource Actions" at https://github.com/ClusterLabs/pacemaker/pull/1521 } key_nextline_start = 0 multiple_lines = [] for line in content: if line.startswith("WARNING:"): if "WARNING" in self: self["WARNING"].append(line.strip()) else: self["WARNING"] = [line.strip()] continue if (line.startswith("RemoteNode") or line.startswith("GuestNode") or (line.startswith("Node") and not line.startswith('Node List'))): linesplit = line.split() bad_node = {} bad_node['name'] = linesplit[1][0:-1] bad_node['status'] = line.split(':')[1][1:] self.bad_nodes.append(bad_node) if line.startswith(key_nextline_titles): key_nextline_start = 1 multiple_lines = [] attr_name = line.split(":")[0].strip() self[key_nextline_alias.get(attr_name, attr_name)] = multiple_lines continue if key_nextline_start == 0: line = line.strip('* ') linesplit = line.split() if line.startswith(key_oneline): key, value = line.split(":", 1) self[key.strip()] = value.strip() elif "nodes configured" in line.lower(): self["Nodes configured"] = linesplit[0] elif any(item in line.lower() for item in ["resources configured", "resource instance configured", "resource instances configured"]): if "and" in line: # 3 nodes and 3 resources configured self['Nodes configured'] = linesplit[0] self["Resources configured"] = linesplit[3] else: self["Resources configured"] = linesplit[0] else: # key_nextline_start > 0 if line.strip(): multiple_lines.append(line.strip()) pcsd_status = self.get("PCSD Status") if pcsd_status: # According "PCSD Status" to get node list for line in pcsd_status: if line.count(':') > 1: self.nodes.extend([item.split(':')[0] for item in line.split() if ':' in item]) else: self.nodes.append(line.split(":")[0].strip())
@property def data(self): # to keep compatibility with old usage, please use itselt directly. return self