#!/usr/bin/env python3 import json import socket import sys PROTOCOL_VERSION = 1 VALID_OCF_RCS = {0, 1, 7, 8} def main(): if len(sys.argv) != 5: raise SystemExit(11) socket_path = sys.argv[1] resource = sys.argv[2] transport_failure = int(sys.argv[3]) protocol_failure = int(sys.argv[4]) request = { "protocol_version": PROTOCOL_VERSION, "action": "monitor", "resource": resource, } try: sock = socket.socket( socket.AF_UNIX, socket.SOCK_STREAM, ) sock.settimeout(2.0) try: sock.connect(socket_path) sock.sendall( json.dumps(request).encode("utf-8") + b"\n" ) raw = b"" while b"\n" not in raw: chunk = sock.recv(65536) if not chunk: break raw += chunk finally: sock.close() except ( socket.timeout, ConnectionError, OSError, ): raise SystemExit(transport_failure) # A connection was established. From this point onward, absence of a # valid response is a protocol/result failure rather than transport loss. if not raw: raise SystemExit(protocol_failure) try: obj = json.loads( raw.decode("utf-8").strip() ) except ( UnicodeDecodeError, json.JSONDecodeError, ): raise SystemExit(protocol_failure) if not isinstance(obj, dict): raise SystemExit(protocol_failure) if obj.get("protocol_version") != PROTOCOL_VERSION: raise SystemExit(protocol_failure) if obj.get("ok") is not True: raise SystemExit(protocol_failure) if obj.get("resource") != resource: raise SystemExit(protocol_failure) if obj.get("action") != "monitor": raise SystemExit(protocol_failure) result = obj.get("result") if not isinstance(result, dict): raise SystemExit(protocol_failure) ha = result.get("ha") if not isinstance(ha, dict): raise SystemExit(protocol_failure) try: ocf_rc = int(ha.get("ocf_rc")) except ( TypeError, ValueError, ): raise SystemExit(protocol_failure) if ocf_rc not in VALID_OCF_RCS: raise SystemExit(protocol_failure) receiver = result.get("wal_receiver") or {} if not isinstance(receiver, dict): raise SystemExit(protocol_failure) payload = "|".join([ str(ocf_rc), str(ha.get("health", "unknown")), str(ha.get("ha_role", "unknown")), str(ha.get("state", "unknown")), str( ha.get( "promotion_eligible", "unknown", ) ).lower(), str(result.get("role", "unknown")), str( result.get( "streaming", "unknown", ) ).lower(), str(receiver.get("slot_name") or ""), str(receiver.get("sender_host") or ""), ]) print(payload) if __name__ == "__main__": main()