Add support for LVM and RAID to mount-all-volumes
* Renamed get_mounted_data to get_mounted_volumes * Report data is now a dict for better clarity * Widened report hoping that LVM names will fit (they probably wont) * This fixes #38
This commit is contained in:
parent
e6b7cc602b
commit
24df753a40
2 changed files with 70 additions and 57 deletions
|
|
@ -170,93 +170,106 @@ def is_valid_wim_file(item):
|
||||||
print_log('WARNING: Image "{}" damaged.'.format(item.name))
|
print_log('WARNING: Image "{}" damaged.'.format(item.name))
|
||||||
return valid
|
return valid
|
||||||
|
|
||||||
def get_mounted_data():
|
def get_mounted_volumes():
|
||||||
"""Get mounted volumes, returns dict."""
|
"""Get mounted volumes, returns dict."""
|
||||||
cmd = [
|
cmd = [
|
||||||
'findmnt', '-J', '-b', '-i',
|
'findmnt', '-J', '-b', '-i',
|
||||||
't', (
|
'-t', (
|
||||||
'autofs,binfmt_misc,cgroup,cgroup2,configfs,debugfs,devpts,devtmpfs,'
|
'autofs,binfmt_misc,bpf,cgroup,cgroup2,configfs,debugfs,devpts,devtmpfs,'
|
||||||
'hugetlbfs,mqueue,proc,pstore,securityfs,sysfs,tmpfs'
|
'hugetlbfs,mqueue,proc,pstore,securityfs,sysfs,tmpfs'
|
||||||
),
|
),
|
||||||
'-o', 'SOURCE,TARGET,FSTYPE,LABEL,SIZE,AVAIL,USED']
|
'-o', 'SOURCE,TARGET,FSTYPE,LABEL,SIZE,AVAIL,USED']
|
||||||
result = run_program(cmd)
|
result = run_program(cmd)
|
||||||
json_data = json.loads(result.stdout.decode())
|
json_data = json.loads(result.stdout.decode())
|
||||||
mounted_data = []
|
mounted_volumes = []
|
||||||
for item in json_data.get('filesystems', []):
|
for item in json_data.get('filesystems', []):
|
||||||
mounted_data.append(item)
|
mounted_volumes.append(item)
|
||||||
mounted_data.extend(item.get('children', []))
|
mounted_volumes.extend(item.get('children', []))
|
||||||
return {item['source']: item for item in mounted_data}
|
return {item['source']: item for item in mounted_volumes}
|
||||||
|
|
||||||
def mount_all_volumes():
|
def mount_all_volumes():
|
||||||
"""Mount all attached devices with recognized filesystems."""
|
"""Mount all detected filesystems."""
|
||||||
report = []
|
report = {}
|
||||||
|
|
||||||
# Get list of block devices
|
# Get list of block devices
|
||||||
cmd = ['lsblk', '-J', '-o', 'NAME,FSTYPE,LABEL,UUID,PARTTYPE,TYPE,SIZE']
|
cmd = [
|
||||||
|
'lsblk', '-J', '-p',
|
||||||
|
'-o', 'NAME,FSTYPE,LABEL,UUID,PARTTYPE,TYPE,SIZE']
|
||||||
result = run_program(cmd)
|
result = run_program(cmd)
|
||||||
json_data = json.loads(result.stdout.decode())
|
json_data = json.loads(result.stdout.decode())
|
||||||
devs = json_data.get('blockdevices', [])
|
devs = json_data.get('blockdevices', [])
|
||||||
|
|
||||||
# Get list of mounted devices
|
# Get list of volumes
|
||||||
mounted_data = get_mounted_data()
|
volumes = {}
|
||||||
mounted_list = [m['source'] for m in mounted_data.values()]
|
|
||||||
|
|
||||||
# Loop over devices
|
|
||||||
for dev in devs:
|
for dev in devs:
|
||||||
dev_path = '/dev/{}'.format(dev['name'])
|
|
||||||
if re.search(r'^(loop|sr)', dev['name'], re.IGNORECASE):
|
|
||||||
# Skip loopback devices and optical media
|
|
||||||
report.append([dev_path, 'Skipped'])
|
|
||||||
continue
|
|
||||||
for child in dev.get('children', []):
|
for child in dev.get('children', []):
|
||||||
child_path = '/dev/{}'.format(child['name'])
|
volumes.update({child['name']: child})
|
||||||
if child_path in mounted_list:
|
for grandchild in child.get('children', []):
|
||||||
report.append([child_path, 'Already Mounted'])
|
volumes.update({grandchild['name']: grandchild})
|
||||||
else:
|
|
||||||
try:
|
# Get list of mounted volumes
|
||||||
run_program(['udevil', 'mount', '-o', 'ro', child_path])
|
mounted_volumes = get_mounted_volumes()
|
||||||
report.append([child_path, 'CS'])
|
|
||||||
except subprocess.CalledProcessError:
|
|
||||||
report.append([child_path, 'NS'])
|
|
||||||
|
|
||||||
# Update list of mounted devices
|
# Loop over volumes
|
||||||
mounted_data = get_mounted_data()
|
for vol_path, vol_data in volumes.items():
|
||||||
mounted_list = [m['source'] for m in mounted_data.values()]
|
vol_data['show_data'] = {
|
||||||
|
'message': vol_path.replace('/dev/mapper/', ''),
|
||||||
# Update report lines for show_data()
|
'data': None,
|
||||||
for line in report:
|
}
|
||||||
_path = line[0]
|
if re.search(r'^loop\d', vol_path, re.IGNORECASE):
|
||||||
_result = line[1]
|
# Skip loopback devices
|
||||||
info = {'message': '{}:'.format(_path)}
|
vol_data['show_data']['data'] = 'Skipped'
|
||||||
if _path in mounted_list:
|
vol_data['show_data']['warning'] = True
|
||||||
info['data'] = 'Mounted on {}'.format(
|
report[vol_path] = vol_data
|
||||||
mounted_data[_path]['target'])
|
elif 'children' in vol_data:
|
||||||
info['data'] = '{:40} ({} used, {} free)'.format(
|
# Skip LVM/RAID partitions (the real volume is mounted separately)
|
||||||
info['data'],
|
vol_data['show_data']['data'] = vol_data.get('fstype', 'UNKNOWN')
|
||||||
human_readable_size(mounted_data[_path]['used']),
|
if vol_data.get('label', None):
|
||||||
human_readable_size(mounted_data[_path]['avail']))
|
vol_data['show_data']['data'] += ' "{}"'.format(vol_data['label'])
|
||||||
if _result == 'Already Mounted':
|
vol_data['show_data']['info'] = True
|
||||||
info['warning'] = True
|
report[vol_path] = vol_data
|
||||||
elif _result == 'Skipped':
|
|
||||||
info['data'] = 'Skipped'
|
|
||||||
info['warning'] = True
|
|
||||||
else:
|
else:
|
||||||
info['data'] = 'Failed to mount'
|
if vol_path in mounted_volumes:
|
||||||
info['error'] = True
|
vol_data['show_data']['warning'] = True
|
||||||
line.append(info)
|
else:
|
||||||
|
# Mount volume
|
||||||
|
try:
|
||||||
|
run_program(['udevil', 'mount', '-o', 'ro', vol_path])
|
||||||
|
except subprocess.CalledProcessError:
|
||||||
|
vol_data['show_data']['data'] = 'Failed to mount'
|
||||||
|
vol_data['show_data']['error'] = True
|
||||||
|
# Update mounted_volumes data
|
||||||
|
mounted_volumes = get_mounted_volumes()
|
||||||
|
|
||||||
|
# Format pretty result string
|
||||||
|
if vol_data['show_data']['data'] != 'Failed to mount':
|
||||||
|
size_used = human_readable_size(
|
||||||
|
mounted_volumes[vol_path]['used'])
|
||||||
|
size_avail = human_readable_size(
|
||||||
|
mounted_volumes[vol_path]['avail'])
|
||||||
|
vol_data['show_data']['data'] = 'Mounted on {}'.format(
|
||||||
|
mounted_volumes[vol_path]['target'])
|
||||||
|
vol_data['show_data']['data'] = '{:40} ({} used, {} free)'.format(
|
||||||
|
vol_data['show_data']['data'],
|
||||||
|
size_used,
|
||||||
|
size_avail)
|
||||||
|
|
||||||
|
# Update report
|
||||||
|
report[vol_path] = vol_data
|
||||||
|
|
||||||
return report
|
return report
|
||||||
|
|
||||||
def mount_backup_shares(read_write=False):
|
def mount_backup_shares(read_write=False):
|
||||||
"""Mount the backup shares unless labeled as already mounted."""
|
"""Mount the backup shares unless labeled as already mounted."""
|
||||||
if psutil.LINUX:
|
if psutil.LINUX:
|
||||||
mounted_data = get_mounted_data()
|
mounted_volumes = get_mounted_volumes()
|
||||||
for server in BACKUP_SERVERS:
|
for server in BACKUP_SERVERS:
|
||||||
if psutil.LINUX:
|
if psutil.LINUX:
|
||||||
# Update mounted status
|
# Update mounted status
|
||||||
source = '//{IP}/{Share}'.format(**server)
|
source = '//{IP}/{Share}'.format(**server)
|
||||||
dest = '/Backups/{Name}'.format(**server)
|
dest = '/Backups/{Name}'.format(**server)
|
||||||
mounted_str = '(Already) Mounted {}'.format(dest)
|
mounted_str = '(Already) Mounted {}'.format(dest)
|
||||||
data = mounted_data.get(source, {})
|
data = mounted_volumes.get(source, {})
|
||||||
if dest == data.get('target', ''):
|
if dest == data.get('target', ''):
|
||||||
server['Mounted'] = True
|
server['Mounted'] = True
|
||||||
elif psutil.WINDOWS:
|
elif psutil.WINDOWS:
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,8 @@ if __name__ == '__main__':
|
||||||
|
|
||||||
# Print report
|
# Print report
|
||||||
print_info('\nResults')
|
print_info('\nResults')
|
||||||
for line in report:
|
for vol_name, vol_data in sorted(report.items()):
|
||||||
show_data(indent=4, width=16, **line[-1])
|
show_data(indent=4, width=20, **vol_data['show_data'])
|
||||||
|
|
||||||
# Done
|
# Done
|
||||||
print_standard('\nDone.')
|
print_standard('\nDone.')
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue