From 98ec8201970c0b37eced3e9ab600b5125adbf7bc Mon Sep 17 00:00:00 2001 From: Erik Schamper <1254028+Schamper@users.noreply.github.com> Date: Tue, 26 Sep 2023 13:49:20 +0200 Subject: [PATCH] Update LVM volume system to reflect library update (#371) --- dissect/target/volumes/lvm.py | 43 +++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/dissect/target/volumes/lvm.py b/dissect/target/volumes/lvm.py index faa7184af..aee52b5b6 100644 --- a/dissect/target/volumes/lvm.py +++ b/dissect/target/volumes/lvm.py @@ -1,3 +1,4 @@ +import logging from collections import defaultdict from typing import BinaryIO, Iterator, Union @@ -5,6 +6,20 @@ from dissect.target.volume import LogicalVolumeSystem, Volume +log = logging.getLogger(__name__) + +OPEN_TYPES = ( + "linear", + "striped", + "mirror", + "thin", +) + +KNOWN_SKIP_TYPES = ( + "snapshot", + "thin-pool", +) + class LvmVolumeSystem(LogicalVolumeSystem): def __init__(self, fh: Union[BinaryIO, list[BinaryIO]], *args, **kwargs): @@ -19,13 +34,10 @@ def open_all(cls, volumes: list[BinaryIO]) -> Iterator[LogicalVolumeSystem]: if not cls.detect_volume(vol): continue - pv = lvm.PhysicalVolume(vol) - if pv.has_metadata(): - try: - m = pv.read_metadata() - except Exception: - continue - lvm_pvs[m.vg.name].append(pv) + dev = lvm.LVM2Device(vol) + if metadata := dev.metadata: + vg_name = next(key for key, value in metadata.items() if isinstance(value, dict)) + lvm_pvs[vg_name].append(dev) for pvs in lvm_pvs.values(): try: @@ -47,8 +59,19 @@ def _detect_volume(fh: BinaryIO) -> bool: return b"LABELONE" in buf def _volumes(self) -> Iterator[Volume]: - for num, lv in enumerate(self.lvm.volume_group.logical_volumes): + num = 1 + + for lv_name, lv in self.lvm.volume_group.logical_volumes.items(): + if lv.type not in OPEN_TYPES: + if lv.type not in KNOWN_SKIP_TYPES: + log.debug("Skipping unsupported LVM logical volume type: %s (%s)", lv.type, lv) + continue + # When composing a vg-lv name, LVM2 replaces hyphens with double hyphens in the vg and lv names # Emulate that here for the volume name - name = f"{lv.vg.name.replace('-', '--')}-{lv.metadata.name.replace('-', '--')}" - yield Volume(lv, num + 1, None, lv.size, None, name, raw=lv, vs=self) + name = f"{lv.vg.name.replace('-', '--')}-{lv_name.replace('-', '--')}" + + fh = lv.open() + yield Volume(fh, num, None, fh.size, None, name, raw=lv, vs=self) + + num += 1