orphan disk search update

This commit is contained in:
David Schroeder
2026-09-22 22:35:01 -05:00
parent e34f9d832e
commit e262260358
4 changed files with 53 additions and 6 deletions
+25 -5
View File
@@ -2,6 +2,7 @@
"""Read-only Proxmox storage/reference inventory; no third-party dependencies."""
import argparse
import csv
from datetime import datetime
import json
import math
from pathlib import Path
@@ -198,17 +199,36 @@ def render(rows, warnings, coverage):
def export_csv(path, rows):
destination = Path(path).expanduser()
folder = destination.is_dir() or str(path).endswith('/')
if folder:
destination.mkdir(parents=True, exist_ok=True)
destination /= datetime.now().strftime('tapm-orphan-disks-%Y-%m-%d-%H%M%S.csv')
elif destination.suffix.lower() != '.csv':
destination = Path(str(destination) + '.csv')
# Exclusive creation avoids overwriting existing files, including symlink targets.
with open(path, 'x', newline='') as handle:
base = destination
suffix = 0
while True:
try:
handle = destination.open('x', newline='')
break
except FileExistsError:
if not folder:
raise
suffix += 1
destination = base.with_name(f'{base.stem}-{suffix}.csv')
with handle:
writer = csv.DictWriter(handle, fieldnames=FIELDS + ['disk_size'])
writer.writeheader()
for row in rows:
writer.writerow(dict(row, disk_size=format_size(row['size_bytes'], row.get('size_is_approximate', False))))
return destination
def main():
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('--csv', metavar='PATH', help='export to a new CSV file')
parser.add_argument('--csv', metavar='PATH', help='export to a CSV file or folder (.csv is added if missing)')
parser.add_argument('--interactive', action='store_true', help='offer CSV export after the report')
# The TAPM preloader pads its forwarded arguments with empty strings.
args = parser.parse_args([arg for arg in sys.argv[1:] if arg])
@@ -217,10 +237,10 @@ def main():
render(rows, warnings, coverage)
destination = args.csv
if args.interactive and sys.stdin.isatty() and not destination:
destination = input('\nCSV export path (Enter to skip): ').strip()
destination = input('\nCSV export file or folder (Enter to skip): ').strip()
if destination:
export_csv(destination, rows)
print('CSV saved: ' + destination)
destination = export_csv(destination, rows)
print(f'CSV saved: {destination}')
return 2 if warnings else 0
except (OSError, RuntimeError, ValueError, subprocess.TimeoutExpired) as exc:
print(f'Disk report failed: {exc}', file=sys.stderr)