Fix CORE→SCALE compatibility for SMB and NFS share payloads
Strip CORE-only SMB share field (vuid) and NFS share fields (paths, alldirs, quiet) that are rejected by the SCALE API. Convert CORE's NFS paths list to the single path string SCALE expects. Also include NFS paths in dry-run dataset existence checks. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -539,16 +539,33 @@ def list_archive_and_exit(tar_path: str) -> None:
|
||||
|
||||
# Read-only / server-generated fields that must NOT be sent on create/update
|
||||
_SMB_SHARE_READONLY = frozenset({"id", "locked"})
|
||||
_NFS_SHARE_READONLY = frozenset({"id", "locked"})
|
||||
_SMB_CONFIG_READONLY = frozenset({"id", "server_sid"})
|
||||
|
||||
# CORE SMB share fields that do not exist in the SCALE API
|
||||
_SMB_SHARE_CORE_EXTRAS = frozenset({
|
||||
"vuid", # server-generated Time Machine UUID; SCALE sets this automatically
|
||||
})
|
||||
|
||||
# CORE NFS share fields that do not exist in the SCALE API
|
||||
_NFS_SHARE_CORE_EXTRAS = frozenset({
|
||||
"paths", # CORE uses a list; SCALE uses a single "path" string (converted below)
|
||||
"alldirs", # removed in SCALE
|
||||
"quiet", # removed in SCALE
|
||||
})
|
||||
|
||||
|
||||
def _smb_share_payload(share: dict) -> dict:
|
||||
return {k: v for k, v in share.items() if k not in _SMB_SHARE_READONLY}
|
||||
exclude = _SMB_SHARE_READONLY | _SMB_SHARE_CORE_EXTRAS
|
||||
return {k: v for k, v in share.items() if k not in exclude}
|
||||
|
||||
|
||||
def _nfs_share_payload(share: dict) -> dict:
|
||||
return {k: v for k, v in share.items() if k not in _NFS_SHARE_READONLY}
|
||||
payload = {k: v for k, v in share.items()
|
||||
if k not in {"id", "locked"} | _NFS_SHARE_CORE_EXTRAS}
|
||||
# CORE stores export paths as a list under "paths"; SCALE expects a single "path" string.
|
||||
if "path" not in payload and share.get("paths"):
|
||||
payload["path"] = share["paths"][0]
|
||||
return payload
|
||||
|
||||
|
||||
def _smb_config_payload(config: dict) -> dict:
|
||||
@@ -952,7 +969,10 @@ async def migrate_nfs_shares(
|
||||
log.info(" Destination has %d existing NFS share(s).", len(existing_paths))
|
||||
|
||||
for share in shares:
|
||||
path = share.get("path", "").rstrip("/")
|
||||
# CORE archives store paths as a list; SCALE uses a single string.
|
||||
core_paths = share.get("paths") or []
|
||||
path = (share.get("path") or (core_paths[0] if core_paths else "")).rstrip("/")
|
||||
all_paths = [p.rstrip("/") for p in (core_paths if core_paths else ([path] if path else []))]
|
||||
log.info("── NFS export %r", path)
|
||||
|
||||
if path in existing_paths:
|
||||
@@ -966,8 +986,7 @@ async def migrate_nfs_shares(
|
||||
if dry_run:
|
||||
log.info(" [DRY RUN] would create NFS export for %r", path)
|
||||
summary.nfs_created += 1
|
||||
if path:
|
||||
summary.paths_to_create.append(path)
|
||||
summary.paths_to_create.extend(all_paths)
|
||||
continue
|
||||
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user