-
Notifications
You must be signed in to change notification settings - Fork 17
ctdb: nodes list command, wait for ctdb option #128
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
dc3b01d
0e7e3c1
a55158a
78125f0
7f0c171
ba9a564
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -128,6 +128,9 @@ def _write_param(name: str, key: str) -> None: | |
fh.write(enc("\n")) | ||
fh.write(enc("[cluster]\n")) | ||
_write_param("recovery lock", "recovery_lock") | ||
if ctdb_params.get("nodes_cmd"): | ||
nodes_cmd = ctdb_params["nodes_cmd"] | ||
fh.write(enc(f"nodes list = !{nodes_cmd}")) | ||
fh.write(enc("\n")) | ||
fh.write(enc("[legacy]\n")) | ||
_write_param("realtime scheduling", "realtime_scheduling") | ||
|
@@ -481,16 +484,21 @@ def _node_update(cmeta: ClusterMeta, real_path: str) -> bool: | |
return True | ||
|
||
|
||
def cluster_meta_to_nodes(cmeta: ClusterMeta, real_path: str) -> None: | ||
def cluster_meta_to_nodes( | ||
cmeta: ClusterMeta, dest: typing.Union[str, typing.IO] | ||
) -> None: | ||
"""Write a nodes file based on the current content of the cluster | ||
metadata.""" | ||
with cmeta.open(locked=True) as cmo: | ||
json_data = cmo.load() | ||
nodes = json_data.get("nodes", []) | ||
_logger.info("Found node metadata: %r", nodes) | ||
ctdb_nodes = _cluster_meta_to_ctdb_nodes(nodes) | ||
_logger.info("Will write nodes: %s", ctdb_nodes) | ||
_save_nodes(real_path, ctdb_nodes) | ||
if isinstance(dest, str): | ||
_logger.info("Will write nodes: %s", ctdb_nodes) | ||
_save_nodes(dest, ctdb_nodes) | ||
else: | ||
write_nodes_file(dest, ctdb_nodes) | ||
|
||
|
||
def _cluster_meta_to_ctdb_nodes(nodes: list[dict]) -> list[str]: | ||
|
@@ -696,6 +704,42 @@ def check_nodestatus(cmd: samba_cmds.SambaCommand = samba_cmds.ctdb) -> None: | |
samba_cmds.execute(cmd_ctdb_check) | ||
|
||
|
||
def _read_command_pnn(cmd: samba_cmds.SambaCommand) -> typing.Optional[int]: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not a big fan of this mixed int-or-None return value. I would prefer a more explicit typing; something like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, sorry but I find your suggestion less idiomatic. Hope you don't mind. |
||
"""Run a ctdb command assuming it returns a pnn value. Return the pnn as an | ||
int on success, None on command failure. | ||
""" | ||
try: | ||
out = subprocess.check_output(list(cmd)) | ||
pnntxt = out.decode("utf8").strip() | ||
synarete marked this conversation as resolved.
Show resolved
Hide resolved
|
||
except subprocess.CalledProcessError as err: | ||
_logger.error(f"command {cmd!r} failed: {err!r}") | ||
return None | ||
except FileNotFoundError: | ||
_logger.error(f"ctdb command ({cmd!r}) not found") | ||
return None | ||
try: | ||
return int(pnntxt) | ||
except ValueError: | ||
_logger.debug(f"ctdb command wrote invalid pnn: {pnntxt!r}") | ||
return None | ||
|
||
|
||
def current_pnn() -> typing.Optional[int]: | ||
"""Run the `ctdb pnn` command. Returns the pnn value or None if the command | ||
fails. | ||
""" | ||
return _read_command_pnn(samba_cmds.ctdb["pnn"]) | ||
|
||
|
||
def leader_pnn() -> typing.Optional[int]: | ||
"""Run the `ctdb leader` (or equivalent) command. Returns the pnn value or | ||
None if the command fails. | ||
""" | ||
# recmaster command: <ctdb recmaster|leader> | ||
admin_cmd = samba_cmds.ctdb_leader_admin_cmd() | ||
return _read_command_pnn(samba_cmds.ctdb[admin_cmd]) | ||
|
||
|
||
class CLILeaderStatus: | ||
_isleader = False | ||
|
||
|
@@ -709,29 +753,10 @@ class CLILeaderLocator: | |
""" | ||
|
||
def __enter__(self) -> CLILeaderStatus: | ||
mypnn = recmaster = "" | ||
# mypnn = <ctdb pnn> | ||
pnn_cmd = samba_cmds.ctdb["pnn"] | ||
try: | ||
out = subprocess.check_output(list(pnn_cmd)) | ||
mypnn = out.decode("utf8").strip() | ||
except subprocess.CalledProcessError as err: | ||
_logger.error(f"command {pnn_cmd!r} failed: {err!r}") | ||
except FileNotFoundError: | ||
_logger.error(f"ctdb command ({pnn_cmd!r}) not found") | ||
# recmaster = <ctdb recmaster|leader> | ||
admin_cmd = samba_cmds.ctdb_leader_admin_cmd() | ||
recmaster_cmd = samba_cmds.ctdb[admin_cmd] | ||
try: | ||
out = subprocess.check_output(list(recmaster_cmd)) | ||
recmaster = out.decode("utf8").strip() | ||
except subprocess.CalledProcessError as err: | ||
_logger.error(f"command {recmaster_cmd!r} failed: {err!r}") | ||
except FileNotFoundError: | ||
_logger.error(f"ctdb command ({recmaster_cmd!r}) not found") | ||
|
||
mypnn = current_pnn() | ||
leader = leader_pnn() | ||
sts = CLILeaderStatus() | ||
sts._isleader = bool(mypnn) and mypnn == recmaster | ||
sts._isleader = mypnn is not None and mypnn == leader | ||
return sts | ||
|
||
def __exit__( | ||
|
Uh oh!
There was an error while loading. Please reload this page.