147 lines
3.1 KiB
Python
Executable File
147 lines
3.1 KiB
Python
Executable File
#!/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()
|