Prepare clean Sargo images and validated storage inventories
Keep internal documents out of system images while retaining license notices and package versions. Generate boot mappings from a bounded storage inventory, and allow long SSH diagnostics. Hardware boot qualification remains pending.
This commit is contained in:
parent
a15c2915dc
commit
9b606ed5f3
7 changed files with 193 additions and 4 deletions
55
tundra/tools/inventory-storage.py
Normal file
55
tundra/tools/inventory-storage.py
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
#!/usr/bin/env python3
|
||||
# SPDX-License-Identifier: MPL-2.0
|
||||
"""Inventory an existing Sargo ext4/LVM mount without changing any storage."""
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import stat
|
||||
import subprocess
|
||||
|
||||
from storage_layout import mount_table
|
||||
|
||||
|
||||
def command(*args):
|
||||
return subprocess.check_output(args, text=True, timeout=15,
|
||||
env={**os.environ, 'PATH': '/usr/sbin:/usr/bin:/sbin:/bin', 'LC_ALL': 'C'}).strip()
|
||||
|
||||
|
||||
def inventory(mountpoint):
|
||||
device = Path('/dev/mmcblk0p72')
|
||||
if not stat.S_ISBLK(device.stat().st_mode):
|
||||
raise ValueError('Sargo userdata block device is missing')
|
||||
label = command('blkid', '-s', 'PARTLABEL', '-o', 'value', str(device))
|
||||
if label != 'userdata':
|
||||
raise ValueError('Unexpected partition label')
|
||||
mounted = json.loads(command('findmnt', '--json', '--mountpoint', mountpoint,
|
||||
'--output', 'SOURCE,FSTYPE'))['filesystems']
|
||||
if len(mounted) != 1 or mounted[0]['fstype'] != 'ext4':
|
||||
raise ValueError('Expected one existing ext4 mount')
|
||||
source = mounted[0]['source']
|
||||
if not source.startswith('/dev/mapper/'):
|
||||
raise ValueError('Only the existing single-extent LVM layout is supported')
|
||||
table = command('dmsetup', 'table', source)
|
||||
with device.open('rb', buffering=0) as stream:
|
||||
first = stream.read(1048576)
|
||||
if len(first) != 1048576:
|
||||
raise ValueError('Cannot read userdata identity')
|
||||
layout = {
|
||||
'schema': 2, 'device': str(device), 'partitionLabel': label,
|
||||
'filesystem': mounted[0]['fstype'], 'table': table,
|
||||
'backingDevice': Path('/sys/class/block/mmcblk0p72/dev').read_text().strip(),
|
||||
'size': int(command('blockdev', '--getsize64', str(device))),
|
||||
'firstMiBSha256': hashlib.sha256(first).hexdigest(),
|
||||
}
|
||||
mount_table(layout)
|
||||
return layout
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--mountpoint', required=True,
|
||||
help='Existing root mount, or /reference/installed under Tundra')
|
||||
args = parser.parse_args()
|
||||
print(json.dumps(inventory(args.mountpoint), indent=2))
|
||||
Loading…
Reference in a new issue