Bind daemon to local Pacemaker node identity
This commit is contained in:
@@ -20,6 +20,7 @@ registry = None
|
|||||||
pacemaker_resource_id = None
|
pacemaker_resource_id = None
|
||||||
pacemaker_peer_uid = None
|
pacemaker_peer_uid = None
|
||||||
pacemaker_peer_gid = None
|
pacemaker_peer_gid = None
|
||||||
|
pacemaker_node_name = None
|
||||||
|
|
||||||
PROTOCOL_VERSION = 1
|
PROTOCOL_VERSION = 1
|
||||||
|
|
||||||
@@ -68,6 +69,38 @@ def load_pacemaker_resource_binding(
|
|||||||
return resource_id
|
return resource_id
|
||||||
|
|
||||||
|
|
||||||
|
def load_pacemaker_node_name(environ=None):
|
||||||
|
"""
|
||||||
|
Load the Pacemaker node represented by this daemon instance.
|
||||||
|
|
||||||
|
The daemon is local to one PostgreSQL instance. This identity is not
|
||||||
|
used for routing; it is used to validate promotion and demotion context.
|
||||||
|
"""
|
||||||
|
if environ is None:
|
||||||
|
environ = os.environ
|
||||||
|
|
||||||
|
raw_node_name = environ.get("PACEMAKER_NODE_NAME")
|
||||||
|
|
||||||
|
if raw_node_name is None:
|
||||||
|
raise RegistryError(
|
||||||
|
"PACEMAKER_NODE_NAME is not configured"
|
||||||
|
)
|
||||||
|
|
||||||
|
node_name = raw_node_name.strip().lower()
|
||||||
|
|
||||||
|
if not node_name:
|
||||||
|
raise RegistryError(
|
||||||
|
"PACEMAKER_NODE_NAME is empty"
|
||||||
|
)
|
||||||
|
|
||||||
|
if any(char.isspace() for char in node_name):
|
||||||
|
raise RegistryError(
|
||||||
|
"PACEMAKER_NODE_NAME must not contain whitespace"
|
||||||
|
)
|
||||||
|
|
||||||
|
return node_name
|
||||||
|
|
||||||
|
|
||||||
def load_pacemaker_peer_authorization(
|
def load_pacemaker_peer_authorization(
|
||||||
environ=None,
|
environ=None,
|
||||||
):
|
):
|
||||||
@@ -163,6 +196,7 @@ def handle_request(
|
|||||||
"pacemaker_resource": (
|
"pacemaker_resource": (
|
||||||
pacemaker_resource_id
|
pacemaker_resource_id
|
||||||
),
|
),
|
||||||
|
"pacemaker_node": pacemaker_node_name,
|
||||||
})
|
})
|
||||||
|
|
||||||
if action == "registry.list":
|
if action == "registry.list":
|
||||||
@@ -171,6 +205,7 @@ def handle_request(
|
|||||||
"pacemaker_resource": (
|
"pacemaker_resource": (
|
||||||
pacemaker_resource_id
|
pacemaker_resource_id
|
||||||
),
|
),
|
||||||
|
"pacemaker_node": pacemaker_node_name,
|
||||||
"resources": registry.list_resources(),
|
"resources": registry.list_resources(),
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -263,6 +298,7 @@ def serve():
|
|||||||
global pacemaker_resource_id
|
global pacemaker_resource_id
|
||||||
global pacemaker_peer_uid
|
global pacemaker_peer_uid
|
||||||
global pacemaker_peer_gid
|
global pacemaker_peer_gid
|
||||||
|
global pacemaker_node_name
|
||||||
|
|
||||||
registry = Registry()
|
registry = Registry()
|
||||||
pacemaker_resource_id = (
|
pacemaker_resource_id = (
|
||||||
@@ -272,6 +308,7 @@ def serve():
|
|||||||
pacemaker_peer_uid,
|
pacemaker_peer_uid,
|
||||||
pacemaker_peer_gid,
|
pacemaker_peer_gid,
|
||||||
) = load_pacemaker_peer_authorization()
|
) = load_pacemaker_peer_authorization()
|
||||||
|
pacemaker_node_name = load_pacemaker_node_name()
|
||||||
|
|
||||||
socket_directory = os.path.dirname(
|
socket_directory = os.path.dirname(
|
||||||
SOCKET_PATH
|
SOCKET_PATH
|
||||||
@@ -321,6 +358,12 @@ def serve():
|
|||||||
flush=True,
|
flush=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
print(
|
||||||
|
"Pacemaker node identity: "
|
||||||
|
+ pacemaker_node_name,
|
||||||
|
flush=True,
|
||||||
|
)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
while True:
|
while True:
|
||||||
conn, _ = server_socket.accept()
|
conn, _ = server_socket.accept()
|
||||||
|
|||||||
Executable
+70
@@ -0,0 +1,70 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import sys
|
||||||
|
|
||||||
|
sys.path.insert(0, "daemon")
|
||||||
|
|
||||||
|
import server
|
||||||
|
from registry import RegistryError
|
||||||
|
|
||||||
|
|
||||||
|
def require(condition, message):
|
||||||
|
if not condition:
|
||||||
|
raise SystemExit("FAIL: " + message)
|
||||||
|
|
||||||
|
|
||||||
|
def require_error(environment, message):
|
||||||
|
try:
|
||||||
|
server.load_pacemaker_node_name(environment)
|
||||||
|
except RegistryError:
|
||||||
|
return
|
||||||
|
|
||||||
|
raise SystemExit("FAIL: " + message)
|
||||||
|
|
||||||
|
|
||||||
|
print("===== PACEMAKER NODE IDENTITY =====")
|
||||||
|
|
||||||
|
require_error(
|
||||||
|
{},
|
||||||
|
"missing node identity was accepted",
|
||||||
|
)
|
||||||
|
print("missing_identity rejected")
|
||||||
|
|
||||||
|
require_error(
|
||||||
|
{"PACEMAKER_NODE_NAME": " "},
|
||||||
|
"empty node identity was accepted",
|
||||||
|
)
|
||||||
|
print("empty_identity rejected")
|
||||||
|
|
||||||
|
require_error(
|
||||||
|
{"PACEMAKER_NODE_NAME": "david prodesk"},
|
||||||
|
"whitespace node identity was accepted",
|
||||||
|
)
|
||||||
|
print("whitespace_identity rejected")
|
||||||
|
|
||||||
|
node_name = server.load_pacemaker_node_name({
|
||||||
|
"PACEMAKER_NODE_NAME": " DAVID-PRODESK ",
|
||||||
|
})
|
||||||
|
|
||||||
|
require(
|
||||||
|
node_name == "david-prodesk",
|
||||||
|
"node identity was not normalized",
|
||||||
|
)
|
||||||
|
print("valid_identity normalized")
|
||||||
|
|
||||||
|
server.pacemaker_node_name = node_name
|
||||||
|
|
||||||
|
ping = server.protocol_response({
|
||||||
|
"ok": True,
|
||||||
|
"daemon": "managed-containerd",
|
||||||
|
"pacemaker_node": server.pacemaker_node_name,
|
||||||
|
})
|
||||||
|
|
||||||
|
require(
|
||||||
|
ping["pacemaker_node"] == "david-prodesk",
|
||||||
|
"node identity was not reportable",
|
||||||
|
)
|
||||||
|
|
||||||
|
print("reported_identity accepted")
|
||||||
|
print()
|
||||||
|
print("NODE_IDENTITY_TEST_PASS=1")
|
||||||
Reference in New Issue
Block a user