summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/pyparted.py66
1 files changed, 66 insertions, 0 deletions
diff --git a/tools/pyparted.py b/tools/pyparted.py
new file mode 100644
index 0000000..492e032
--- /dev/null
+++ b/tools/pyparted.py
@@ -0,0 +1,66 @@
+import logging
+
+from . import log
+
+__all__ = ["list_partitions"]
+
+L = logging.getLogger(__name__)
+
+try:
+ import parted # type: ignore
+except ModuleNotFoundError:
+ L.error(
+ "You need to install the following packages:\n"
+ "sudo apt install python3-dev libparted-dev pkg-config\n"
+ "pip3 install pyparted"
+ )
+ raise
+
+SUPPORTED_FS_TYPES = ["ext2", "ext3", "ext4", "xfs", "btrfs", "vfat", "ntfs"]
+
+
+@log
+def list_partitions(path):
+ """Find all partitions with a filesystem or a LVM volume system in a RAW
+ image file using `pyparted`.
+
+ See also:
+ https://github.com/dcantrell/pyparted
+
+ Args:
+ path (str): Path to the RAW image file.
+
+ Returns:
+ List of partitions. For example:
+ [{'nr': 1, 'type': 'ext4', 'offset': 1048576, 'size': 1073741824},
+ {'nr': 2, 'type': 'btrfs', 'offset': 1074790400, 'size': 20400046080}]
+ """
+ try:
+ device = parted.getDevice(path)
+ except Exception as e:
+ L.error("failed to get device from %s: %r", path, e)
+ return []
+
+ try:
+ disk = parted.Disk(device)
+ except Exception as e:
+ L.error("failed to read disk from %s: %r", path, e)
+ return []
+
+ ret = []
+ for part in disk.partitions:
+ if part.fileSystem and part.fileSystem.type in SUPPORTED_FS_TYPES:
+ part_type = part.fileSystem.type
+ elif part.getFlag(parted.PARTITION_LVM):
+ part_type = "lvm"
+ else:
+ continue
+
+ ret.append({
+ "nr": part.number,
+ "type": part_type,
+ "offset": part.geometry.start * device.sectorSize, # in bytes
+ "size": part.geometry.length * device.sectorSize # in bytes
+ })
+
+ return ret