:py:mod:`dissect.vmfs.lvm` ========================== .. py:module:: dissect.vmfs.lvm Module Contents --------------- Classes ~~~~~~~ .. autoapisummary:: dissect.vmfs.lvm.LVM dissect.vmfs.lvm.Device dissect.vmfs.lvm.Volume dissect.vmfs.lvm.VolumeStream .. py:class:: LVM(fh: BinaryIO | Device | list[BinaryIO] | list[Device]) VMFS LVM implementation, supports LVM5 and LVM6. VMFS LVM is a logical volume manager that allows multiple physical devices to be combined into a single logical volume. Technically LVM supports multiple logical volumes, in fact LVM3 started with supporting 1024, later versions decreased it to 512. LVM6 only allows 1. In practice only one logical volume is ever used. Provide this class with file-like objects for all devices that make up the LVM, then access the :attr:`~LVM.volumes` attribute to get a list of logical volumes. A :class:`Volume` can be opened for reading by calling :meth:`Volume.open`. :param fh: A file-like object or a list of file-like objects that constitute an LVM. .. py:attribute:: devices :type: list[Device] :value: [] List of :class:`Device` objects that make up the LVM. .. py:attribute:: volumes :type: list[Volume] :value: [] List of :class:`Volume` objects that are in the LVM. .. py:method:: __repr__() -> str .. py:class:: Device(fh: BinaryIO) VMFS LVM device implementation. Represents a single device in the LVM. LVM devices contain metadata that describes itself, the logical volumes and physical extents it contains. The metadata roughly looks like the following pseudo-structure: .. code-block:: c struct LVM_DeviceHeader { LVM_DevMetadata devMeta; LVM_VolTableEntry volTable[LVM_MAX_VOLUMES_PER_DEV]; char reserved[LVM_RESERVED_SIZE]; LVM_SDTableEntry sdTable[FS_PLIST_DEF_MAX_PARTITIONS]; uint8 peBitmap[LVM_PE_BITMAP_SIZE]; LVM_PETableEntry peTable[LVM_PES_PER_BITMAP]; }; On versions prior to LVM6, it looks like the structure sizes are largely respected when calculating offsets to other tables. However, since LVM6 a specific field in ``LVM_DevMetadata`` is often used for this calculation. Because the real name of this field is unknown, we have decided to call it ``mdAlignment`` within this project, since it appears to be used in a similar way as in VMFS. The device metadata (``devMeta``) starts at a fixed offset (``0x00100000``), but since LVM6 may reference extended metadata at other offsets. The volume table (``volTable``) starts after ``devMeta``, which is ``0x00100000 + LVM_SIZEOF_LVM_DEVMETA``, where ``LVM_SIZEOF_LVM_DEVMETA`` is either ``512`` or since LVM6 the value of the ``mdAlignment`` field in the ``LVM_DevMetadata`` structure. Since LVM5 (I could not find evidence that LVM4 exists) there exists a ``sdTable``, which is a table of device names, that starts at the end of the volume table. The ``peBitmap`` is a bitmap that describes which entries in the ``peTable`` are used, and starts at the end of the ``volTable``/``sdTable``. The ``peTable`` is a table of physical extents, which starts at the end of the ``peBitmap``. A pair of ``peBitmap`` and ``peTable`` repeats for ``numPEs`` times. The device metadata ``LVM_DevMetadata`` contains information about the device, including some identifiers and number of volumes and physical extents. There are also timestamps when the device was created and last modified. The volume descriptor ``LVM_VolDescriptor`` contains information about the logical volume, specific to that device. The ``LVM_VolMetadata`` structure contains metadata that is shared across all devices in the volume, but other fields in the descriptor are specific to that device (such as the first and last physical extent on that device). The "SD table" (storage device? SCSI disk?) is a table of device names that are part of the volume, which is only present in LVM5 and later, and only on the first device in the LVM (internally referred to as "devZero"). The physical extent descriptors (``LVM_PEDescriptor``) contain information about the physical extents on the device, including the logical offset, physical offset and length of the extent, as well as a reference to the volume it belongs to. A device can have multiple physical extents, and the logical volume is constructed from these physical extents across all devices in the LVM. There can only be a maximum of 8 physical extent map/table pairs per metadata region (so 8 maps and 64k table entries). If more are needed, the device metadata will reference extended metadata regions, which are similarly laid out, but with a different offset. The extended metadata regions are linked together by the ``nextOffset`` field in the ``LVM_ExtDevMetadata`` structure. :param fh: A file-like object of a LVM device. .. py:attribute:: fh .. py:attribute:: metadata .. py:attribute:: ext_metadata :value: [] .. py:attribute:: major_version .. py:attribute:: minor_version .. py:attribute:: uuid .. py:attribute:: size .. py:attribute:: volumes .. py:method:: __repr__() -> str .. py:class:: Volume(uuid: str, snap_id: int, devices: list[Device]) Logical volume in a VMFS LVM. Represents a logical volume that is constructed from one or more devices. :param uuid: The UUID of the volume. :param snap_id: The snapshot ID of the volume. :param devices: A list of :class:`Device` objects that make up the volume. Must contain at least one device. .. py:attribute:: uuid .. py:attribute:: snap_id .. py:attribute:: devices .. py:attribute:: size .. py:attribute:: generation .. py:attribute:: state .. py:attribute:: name .. py:attribute:: creation_ts .. py:attribute:: dataruns .. py:method:: __repr__() -> str .. py:method:: is_valid() -> bool Check if the volume is valid and can be opened for reading. .. py:method:: open() -> VolumeStream Open a read-only stream for the volume. .. py:class:: VolumeStream(volume: Volume) Bases: :py:obj:`dissect.util.stream.AlignedStream` Read-only stream that allows reading from VMFS LVM volumes. :param volume: The :class:`Volume` to provide a stream for. .. py:attribute:: volume .. py:attribute:: runs