diff --git a/sambacc/commands/ctdb.py b/sambacc/commands/ctdb.py index 6fe6fff..2734621 100644 --- a/sambacc/commands/ctdb.py +++ b/sambacc/commands/ctdb.py @@ -62,6 +62,10 @@ def _ctdb_migrate_args(parser: argparse.ArgumentParser) -> None: default=ctdb.DB_DIR, help="Specify where CTDB database files will be written.", ) + parser.add_argument( + "--archive", + help="Move converted TDB files to an archive dir.", + ) def _ctdb_general_node_args(parser: argparse.ArgumentParser) -> None: @@ -250,6 +254,8 @@ def ctdb_migrate(ctx: Context) -> None: """Migrate standard samba databases to CTDB databases.""" _ctdb_ok() ctdb.migrate_tdb(ctx.instance_config, ctx.cli.dest_dir) + if ctx.cli.archive: + ctdb.archive_tdb(ctx.instance_config, ctx.cli.archive) def _lookup_hostname(hostname): @@ -328,7 +334,18 @@ def ctdb_manage_nodes(ctx: Context) -> None: waiter.wait() -@commands.command(name="ctdb-must-have-node", arg_func=_ctdb_general_node_args) +def _ctdb_must_have_node_args(parser: argparse.ArgumentParser) -> None: + _ctdb_general_node_args(parser) + parser.add_argument( + "--write-nodes", + action="store_true", + help="Specify node by IP", + ) + + +@commands.command( + name="ctdb-must-have-node", arg_func=_ctdb_must_have_node_args +) def ctdb_must_have_node(ctx: Context) -> None: """Block until the current node is present in the ctdb nodes file.""" _ctdb_ok() @@ -341,6 +358,11 @@ def ctdb_must_have_node(ctx: Context) -> None: cmeta=np.cluster_meta(), pnn=expected_pnn, ): - return + break _logger.info("node not yet ready") waiter.wait() + if ctx.cli.write_nodes: + _logger.info("Writing nodes file") + ctdb.cluster_meta_to_nodes( + np.cluster_meta(), real_path=np.persistent_path + ) diff --git a/sambacc/ctdb.py b/sambacc/ctdb.py index 741eb9f..bfb2a0a 100644 --- a/sambacc/ctdb.py +++ b/sambacc/ctdb.py @@ -483,6 +483,26 @@ def _node_update(cmeta: ClusterMeta, real_path: str) -> bool: return True +def cluster_meta_to_nodes(cmeta: ClusterMeta, real_path: str) -> 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) + pnn_max = max(n["pnn"] for n in nodes) + 1 # pnn is zero indexed + ctdb_nodes: list[str] = [""] * pnn_max + for entry in nodes: + pnn = entry["pnn"] + expected_line = _entry_to_node(ctdb_nodes, entry) + ctdb_nodes[pnn] = expected_line + _logger.info("Will write nodes: %s", ctdb_nodes) + with open(real_path, "w") as nffh: + write_nodes_file(nffh, ctdb_nodes) + nffh.flush() + os.fsync(nffh) + + def ensure_ctdbd_etc_files( etc_path: str = ETC_DIR, src_path: str = SHARE_DIR ) -> None: @@ -566,6 +586,23 @@ def _convert_tdb_file(tdb_path: str, dest_dir: str, pnn: int = 0) -> None: subprocess.check_call(list(cmd)) +def archive_tdb(iconfig: config.InstanceConfig, dest_dir: str) -> None: + """Arhive TDB files into a given directory.""" + # TODO: these paths should be based on our instance config, not hard coded + try: + os.mkdir(dest_dir) + _logger.debug("dest_dir: %r created", dest_dir) + except FileExistsError: + _logger.debug("dest_dir: %r already exists", dest_dir) + for tdbfile in _SRC_TDB_FILES: + for parent in _SRC_TDB_DIRS: + tdb_path = os.path.join(parent, tdbfile) + if _has_tdb_file(tdb_path): + dest_path = os.path.join(dest_dir, tdbfile) + _logger.info("archiving: %r -> %r", tdb_path, dest_path) + os.rename(tdb_path, dest_path) + + def check_nodestatus(cmd: samba_cmds.SambaCommand = samba_cmds.ctdb) -> None: cmd_ctdb_check = cmd["nodestatus"] samba_cmds.execute(cmd_ctdb_check)