OpenrelikWorkerCommon.MountUtils.BlockDevice (openrelik_worker_common v0.1.0)

Copy Markdown View Source

Provides functionality to map a disk image file to block devices (loop or nbd) and mount them (openrelik_worker_common.mount_utils.BlockDevice).

The default minimum partition size that gets mounted is 100 MB (104_857_600 bytes).

Summary

Functions

Extracts device and partition information using lsblk -ba -J.

Detaches the block device (qemu-nbd --disconnect for NBD devices or losetup --detach for loop devices).

Mounts an EWF image (.E01 / .EX01) using ewfmount and returns {updated_bd, raw_image_path}.

Unmounts an EWF FUSE mount and removes its mount directory.

Finds and locks a free NBD device (/dev/nbd0../dev/nbd10) in Redis until unlocked or timeout.

Analyses the file system type of a block device or partition using blkid.

Returns the hostname from the NODENAME environment variable or OS hostname.

Generates a mount path under bd.mountroot respecting bd.max_mountpath_size.

Decides if a partition should be processed (size >= min_partition_size and supported fs type).

Returns true if devname points to a block device containing a supported filesystem type.

Default Redis lock timeout in seconds (21600, 6 hours).

Maps bd.image_path to a loopback device using losetup.

Default maximum mount path character length (500).

Default maximum NBD device index (10).

Default minimum partition size in bytes (100 MB).

Mounts a disk or one or more partitions on a mountpoint.

Maps a QCOW image file to an NBD device using qemu-nbd and probes partitions with fdisk.

Initializes a %BlockDevice{} struct.

Parses partition information from bd.blkdeviceinfo.

Checks if the nbd kernel module is loaded or if /dev/nbd* devices exist.

Checks if required CLI tools (lsblk, blkid, mount, qemu-nbd, sudo, fdisk, ntfsinfo) are available on PATH.

Sets up the BlockDevice instance: checks if the image exists, verifies required tools, configures the block device (ewfmount, qemu-nbd, or losetup), queries lsblk, and scans available partitions.

Unmounts all mounted file systems, detaches the block device, unmounts any EWF FUSE mount, and releases any Redis lock.

Unmounts all registered mountpoints and removes their directories.

Types

cmd_result()

@type cmd_result() :: %{
  returncode: integer(),
  stdout: String.t() | nil,
  stderr: String.t() | nil
}

t()

@type t() :: %OpenrelikWorkerCommon.MountUtils.BlockDevice{
  blkdevice: String.t() | nil,
  blkdeviceinfo: map() | nil,
  ewf_mount_path: String.t() | nil,
  image_path: String.t(),
  max_mountpath_size: pos_integer(),
  min_partition_size: non_neg_integer(),
  mountpoints: [String.t()],
  mountroot: String.t(),
  opts: keyword(),
  original_image_path: String.t(),
  partitions: [String.t()],
  redis_client: term(),
  redis_lock: OpenrelikWorkerCommon.MountUtils.RedisLock.t() | nil,
  redis_url: String.t(),
  supported_ewftypes: [String.t()],
  supported_fstypes: [String.t()],
  supported_qcowtypes: [String.t()]
}

Functions

blkinfo(bd)

@spec blkinfo(t()) :: map()

Extracts device and partition information using lsblk -ba -J.

detach_device(bd)

@spec detach_device(t()) :: t()

Detaches the block device (qemu-nbd --disconnect for NBD devices or losetup --detach for loop devices).

ewfmount(bd)

@spec ewfmount(t()) :: String.t()

Mounts an EWF image (.E01 / .EX01) using ewfmount and returns {updated_bd, raw_image_path}.

ewfumount(bd)

@spec ewfumount(t()) :: t()

Unmounts an EWF FUSE mount and removes its mount directory.

get_free_nbd_device(bd)

@spec get_free_nbd_device(t()) :: {t(), String.t()}

Finds and locks a free NBD device (/dev/nbd0../dev/nbd10) in Redis until unlocked or timeout.

Returns {updated_bd, devname} (or devname when called via _get_free_nbd_device override).

get_fstype(bd, devname)

@spec get_fstype(t(), String.t()) :: String.t()

Analyses the file system type of a block device or partition using blkid.

get_hostname(bd \\ nil)

@spec get_hostname(t() | nil) :: String.t()

Returns the hostname from the NODENAME environment variable or OS hostname.

get_mount_path(bd)

@spec get_mount_path(t()) :: String.t()

Generates a mount path under bd.mountroot respecting bd.max_mountpath_size.

is_important_partition(bd, partition)

@spec is_important_partition(t(), map()) :: boolean()

Decides if a partition should be processed (size >= min_partition_size and supported fs type).

is_supported_fs(bd, devname)

@spec is_supported_fs(t(), String.t()) :: boolean()

Returns true if devname points to a block device containing a supported filesystem type.

lock_timeout_seconds()

@spec lock_timeout_seconds() :: pos_integer()

Default Redis lock timeout in seconds (21600, 6 hours).

losetup(bd)

@spec losetup(t()) :: String.t()

Maps bd.image_path to a loopback device using losetup.

max_mountpath_size()

@spec max_mountpath_size() :: pos_integer()

Default maximum mount path character length (500).

max_nbd_devices()

@spec max_nbd_devices() :: pos_integer()

Default maximum NBD device index (10).

min_partition_size_bytes()

@spec min_partition_size_bytes() :: pos_integer()

Default minimum partition size in bytes (100 MB).

mount(bd, partition_name_or_opts \\ "")

@spec mount(t(), String.t() | keyword()) :: {t(), [String.t()]}

Mounts a disk or one or more partitions on a mountpoint.

Returns {updated_bd, mountpoints}.

nbdsetup(bd)

@spec nbdsetup(t()) :: String.t()

Maps a QCOW image file to an NBD device using qemu-nbd and probes partitions with fdisk.

new(image_path, opts \\ [])

@spec new(String.t(), keyword()) :: t()

Initializes a %BlockDevice{} struct.

Options

  • :min_partition_size - Minimum partition size in bytes (default 104_857_600).
  • :max_mountpath_size - Maximum root mount path length (default 500).
  • :mountroot - Root directory for mount points (default "/mnt").
  • :redis_url - Redis URL override (default System.get_env("REDIS_URL") || "redis://localhost:6379/0").
  • :redis_client - Optional pre-configured Redis client or mock client map.

parse_partitions(bd)

@spec parse_partitions(t()) :: [String.t()]

Parses partition information from bd.blkdeviceinfo.

required_modules_loaded(bd \\ nil)

@spec required_modules_loaded(t() | nil) :: :ok

Checks if the nbd kernel module is loaded or if /dev/nbd* devices exist.

required_tools_available(bd \\ nil)

@spec required_tools_available(t() | nil) :: boolean()

Checks if required CLI tools (lsblk, blkid, mount, qemu-nbd, sudo, fdisk, ntfsinfo) are available on PATH.

select_partitions_to_mount(bd, partition_name \\ "")

@spec select_partitions_to_mount(t(), String.t()) :: [String.t()]

Selects partitions to mount.

setup(bd)

@spec setup(t()) :: t()

Sets up the BlockDevice instance: checks if the image exists, verifies required tools, configures the block device (ewfmount, qemu-nbd, or losetup), queries lsblk, and scans available partitions.

If an error occurs during setup, any partially attached block device, EWF mount, or Redis lock is automatically cleaned up before re-raising the original RuntimeError.

umount(bd)

@spec umount(t()) :: t()

Unmounts all mounted file systems, detaches the block device, unmounts any EWF FUSE mount, and releases any Redis lock.

umount_all(bd)

@spec umount_all(t()) :: t()

Unmounts all registered mountpoints and removes their directories.