Update to debug paths

This commit is contained in:
2026-03-03 13:57:52 -05:00
parent 3adb11487f
commit 0a42cb572f

View File

@@ -50,6 +50,7 @@ from __future__ import annotations
import argparse
import asyncio
import contextlib
import json
import logging
import ssl
@@ -154,34 +155,53 @@ class Summary:
_CANDIDATES: dict[str, list[str]] = {
"smb_shares": [
# SCALE 24.04+ combined plugin file; shares are under "sharing_smb_query"
"ixdiagnose/plugins/smb/smb_info.json",
# Older SCALE layouts
"ixdiagnose/plugins/SMB/sharing.smb.query.json",
"ixdiagnose/plugins/Sharing/sharing.smb.query.json",
"ixdiagnose/SMB/sharing.smb.query.json",
# CORE / freenas-debug
"freenas-debug/sharing/smb.json",
"sharing/smb.json",
"middleware/sharing.smb.query.json",
],
"nfs_shares": [
# SCALE 24.04+ combined plugin file; shares are under "sharing_nfs_query"
"ixdiagnose/plugins/nfs/nfs_config.json",
# Older SCALE layouts
"ixdiagnose/plugins/NFS/sharing.nfs.query.json",
"ixdiagnose/plugins/Sharing/sharing.nfs.query.json",
"ixdiagnose/NFS/sharing.nfs.query.json",
# CORE / freenas-debug
"freenas-debug/sharing/nfs.json",
"sharing/nfs.json",
"middleware/sharing.nfs.query.json",
],
"smb_config": [
# SCALE 24.04+ combined plugin file; config is under "smb_config"
"ixdiagnose/plugins/smb/smb_info.json",
# Older SCALE layouts
"ixdiagnose/plugins/SMB/smb.config.json",
"ixdiagnose/SMB/smb.config.json",
# CORE / freenas-debug
"freenas-debug/SMB/smb_config.json",
"middleware/smb.config.json",
],
}
# When a candidate file bundles multiple datasets, pull out the right sub-key.
_KEY_WITHIN_FILE: dict[str, str] = {
"smb_shares": "sharing_smb_query",
"nfs_shares": "sharing_nfs_query",
"smb_config": "smb_config",
}
# Keyword fragments for heuristic fallback scan
_KEYWORDS: dict[str, list[str]] = {
"smb_shares": ["sharing.smb", "smb_share", "sharing/smb"],
"nfs_shares": ["sharing.nfs", "nfs_share", "sharing/nfs"],
"smb_config": ["smb.config", "smb_config"],
"smb_shares": ["sharing.smb", "smb_share", "sharing/smb", "smb_info"],
"nfs_shares": ["sharing.nfs", "nfs_share", "sharing/nfs", "nfs_config"],
"smb_config": ["smb.config", "smb_config", "smb_info"],
}
@@ -203,6 +223,20 @@ def _read_json(tf: tarfile.TarFile, info: tarfile.TarInfo) -> Optional[Any]:
return None
def _extract_subkey(raw: Any, data_type: str) -> Optional[Any]:
"""
When a JSON file bundles multiple datasets, pull out the sub-key that
corresponds to data_type (e.g. "sharing_smb_query" from smb_info.json).
Falls back to the raw value when no sub-key mapping exists.
"""
if not isinstance(raw, dict):
return raw
key = _KEY_WITHIN_FILE.get(data_type)
if key and key in raw:
return raw[key]
return raw
def _find_data(
tf: tarfile.TarFile,
members: dict[str, tarfile.TarInfo],
@@ -222,7 +256,8 @@ def _find_data(
info = member
break
if info is not None:
result = _read_json(tf, info)
raw = _read_json(tf, info)
result = _extract_subkey(raw, data_type)
if result is not None:
log.info(" %-12s%s", data_type, info.name)
return result
@@ -234,7 +269,8 @@ def _find_data(
if not path.lower().endswith(".json"):
continue
if any(kw in path.lower() for kw in keywords):
result = _read_json(tf, members[path])
raw = _read_json(tf, members[path])
result = _extract_subkey(raw, data_type)
if result is not None:
log.info(" %-12s%s (heuristic)", data_type, path)
return result
@@ -242,6 +278,36 @@ def _find_data(
return None
@contextlib.contextmanager
def _open_source_tar(tar_path: str):
"""
Open the archive that actually contains the ixdiagnose data.
TrueNAS HA debug bundles (25.04+) wrap each node's ixdiagnose snapshot
in a separate .txz inside the outer .tgz. We prefer the member whose
name includes '_active'; if none is labelled that way we fall back to the
first .txz found. Single-node (non-HA) bundles are used directly.
"""
with tarfile.open(tar_path, "r:*") as outer:
txz_members = [
m for m in outer.getmembers()
if m.name.lower().endswith(".txz") and m.isfile()
]
if not txz_members:
yield outer
return
# HA bundle pick the active node's inner archive
active = next(
(m for m in txz_members if "_active" in m.name.lower()),
txz_members[0],
)
log.info(" HA bundle detected; reading inner archive: %s", active.name)
fh = outer.extractfile(active)
with tarfile.open(fileobj=fh, mode="r:*") as inner:
yield inner
def parse_archive(tar_path: str) -> dict[str, Any]:
"""
Extract SMB shares, NFS shares, and SMB config from the debug archive.
@@ -255,7 +321,7 @@ def parse_archive(tar_path: str) -> dict[str, Any]:
}
try:
with tarfile.open(tar_path, "r:*") as tf:
with _open_source_tar(tar_path) as tf:
members = _members_map(tf)
log.info(" Archive contains %d total entries.", len(members))
@@ -297,7 +363,7 @@ def list_archive_and_exit(tar_path: str) -> None:
"""
print(f"\nJSON files in archive: {tar_path}\n")
try:
with tarfile.open(tar_path, "r:*") as tf:
with _open_source_tar(tar_path) as tf:
json_members = sorted(
(m for m in tf.getmembers() if m.name.endswith(".json")),
key=lambda m: m.name,