source: ogClient-Git/src/utils/fs.py

Last change on this file was eac9426, checked in by Jose M. Guisado <jguisado@…>, 2 years ago

utils: add fs.py

Adds utility module which wraps several mkfs.* calls as a subprocess.

The main utility function is mkfs(fs, disk, partition, label), which
subsequently calls the corresponding mkfs_*(partition_device) function.

mkfs() supports specifying a drive label where supported.

Other modules using fs.py should call mkfs() only.

  • Property mode set to 100644
File size: 4.5 KB
Line 
1#
2# Copyright (C) 2022 Soleta Networks <info@soleta.eu>
3#
4# This program is free software: you can redistribute it and/or modify it under
5# the terms of the GNU Affero General Public License as published by the
6# Free Software Foundation; either version 3 of the License, or
7# (at your option) any later version.
8
9import logging
10import os
11import subprocess
12import shlex
13
14from subprocess import DEVNULL, PIPE, STDOUT
15
16import psutil
17
18from src.utils.disk import get_partition_device
19
20
21def find_mountpoint(path):
22    """
23    Returns mountpoint of a given path
24    """
25    path = os.path.abspath(path)
26    while not os.path.ismount(path):
27        path = os.path.dirname(path)
28    return path
29
30
31def mount_mkdir(source, target):
32    """
33    Mounts and creates the mountpoint directory if it's not present.
34
35    Return True if mount is sucessful or if target is already a mountpoint.
36    """
37    if not os.path.exists(target):
38        os.mkdir(target)
39
40    if not os.path.ismount(target):
41        return mount(source, target)
42    else:
43        return True
44
45    return False
46
47
48def mount(source, target):
49    """
50    Mounts source into target directoru using mount(8).
51
52    Return true if exit code is 0. False otherwise.
53    """
54    cmd = f'mount {source} {target}'
55    proc = subprocess.run(cmd.split(), stderr=DEVNULL)
56
57    return not proc.returncode
58
59
60def umount(target):
61    """
62    Umounts target using umount(8).
63
64    Return true if exit code is 0. False otherwise.
65    """
66    cmd = f'umount {target}'
67    proc = subprocess.run(cmd.split(), stderr=DEVNULL)
68
69    return not proc.returncode
70
71
72def get_usedperc(mountpoint):
73    """
74    Returns percetage of used filesystem as decimal number.
75    """
76    try:
77        total, used, free, perc = psutil.disk_usage(mountpoint)
78    except FileNotFoundError:
79        return '0'
80    return str(perc)
81
82
83def ogReduceFs(disk, part):
84    """
85    Bash function 'ogReduceFs' wrapper
86    """
87    proc = subprocess.run(f'ogReduceFs {disk} {part}',
88                          shell=True, stdout=PIPE,
89                          encoding='utf-8')
90    if proc.returncode != 0:
91        logging.warn(f'ogReduceFS exited with non zero code: {proc.returncode}')
92    subprocess.run(f'ogUnmount {disk} {part}',
93                   shell=True)
94
95
96def ogExtendFs(disk, part):
97    """
98    Bash function 'ogExtendFs' wrapper
99    """
100    subprocess.run(f'ogMount {disk} {part}',
101                   shell=True)
102    proc = subprocess.run(f'ogExtendFs {disk} {part}',
103                          shell=True)
104    if proc.returncode != 0:
105        logging.warn(f'ogExtendFs exited with non zero code: {proc.returncode}')
106
107
108def mkfs(fs, disk, partition, label=None):
109    """
110    Install any supported filesystem. Target partition is specified a disk
111    number and partition number. This function uses utility functions to
112    translate disk and partition number into a partition device path.
113
114    If filesystem and partition are correct, calls the corresponding mkfs_*
115    function with the partition device path. If not, ValueError is raised.
116    """
117    logging.debug(f'mkfs({fs}, {disk}, {partition}, {label})')
118    fsdict = {
119        'ext4': mkfs_ext4,
120        'ntfs': mkfs_ntfs,
121        'fat32': mkfs_fat32,
122    }
123
124    if fs not in fsdict:
125        logging.warn(f'mkfs aborted, invalid target filesystem.')
126        raise ValueError('Invalid target filesystem')
127
128    try:
129        partdev = get_partition_device(disk, partition)
130    except ValueError as e:
131        logging.warn(f'mkfs aborted, invalid partition.')
132        raise e
133
134    fsdict[fs](partdev, label)
135
136
137def mkfs_ext4(partdev, label=None):
138    if label:
139        cmd = shlex.split(f'mkfs.ext4 -L {label} -F {partdev}')
140    else:
141        cmd = shlex.split(f'mkfs.ext4 -F {partdev}')
142    with open('/tmp/command.log', 'wb', 0) as logfile:
143        subprocess.run(cmd,
144                       stdout=logfile,
145                       stderr=STDOUT)
146
147
148def mkfs_ntfs(partdev, label=None):
149    if label:
150        cmd = shlex.split(f'mkfs.ntfs -f -L {label} {partdev}')
151    else:
152        cmd = shlex.split(f'mkfs.ntfs -f {partdev}')
153    with open('/tmp/command.log', 'wb', 0) as logfile:
154        subprocess.run(cmd,
155                       stdout=logfile,
156                       stderr=STDOUT)
157
158
159def mkfs_fat32(partdev, label=None):
160    if label:
161        cmd = shlex.split(f'mkfs.vfat -n {label} -F32 {partdev}')
162    else:
163        cmd = shlex.split(f'mkfs.vfat -F32 {partdev}')
164    with open('/tmp/command.log', 'wb', 0) as logfile:
165        subprocess.run(cmd,
166                       stdout=logfile,
167                       stderr=STDOUT)
Note: See TracBrowser for help on using the repository browser.