mounts: support mounting partitions

This allows us to map in a whole disk as a loopback device with parition
scanning rather than slicing up the disk and creating several loopback
devices. Something like this:

```
      - type: org.osbuild.copy
        inputs:
          tree:
            type: org.osbuild.tree
            origin: org.osbuild.pipeline
            references:
              - name:tree
        options:
          paths:
            - from: input://tree/
              to: mount://root/
        devices:
          efi:
            type: org.osbuild.loopback
            options:
              filename: disk.img
              start:
                mpp-format-int: '{image.layout[''EFI-SYSTEM''].start}'
              size:
                mpp-format-int: '{image.layout[''EFI-SYSTEM''].size}'
          boot:
            type: org.osbuild.loopback
            options:
              filename: disk.img
              start:
                mpp-format-int: '{image.layout[''boot''].start}'
              size:
                mpp-format-int: '{image.layout[''boot''].size}'
          root:
            type: org.osbuild.loopback
            options:
              filename: disk.img
              start:
                mpp-format-int: '{image.layout[''root''].start}'
              size:
                mpp-format-int: '{image.layout[''root''].size}'
        mounts:
          - name: root
            type: org.osbuild.xfs
            source: root
            target: /
          - name: boot
            type: org.osbuild.ext4
            source: boot
            target: /boot
          - name: efi
            type: org.osbuild.fat
            source: efi
            target: /boot/efi
```

now becomes a little more simple:

```
      - type: org.osbuild.copy
        inputs:
          tree:
            type: org.osbuild.tree
            origin: org.osbuild.pipeline
            references:
              - name:tree
        options:
          paths:
            - from: input://tree/
              to: mount://root/
        devices:
          disk:
            type: org.osbuild.loopback
            options:
              filename: disk.img
              partscan: true
        mounts:
          - name: root
            type: org.osbuild.xfs
            source: disk
            partition:
              mpp-format-int: '{image.layout[''root''].partnum}'
            target: /
          - name: boot
            type: org.osbuild.ext4
            source: disk
            partition:
              mpp-format-int: '{image.layout[''boot''].partnum}'
            target: /boot
          - name: efi
            type: org.osbuild.fat
            source: disk
            partition:
              mpp-format-int: '{image.layout[''EFI-SYSTEM''].partnum}'
            target: /boot/efi
```

Fixes https://github.com/osbuild/osbuild/issues/1495
This commit is contained in:
Dusty Mabe 2023-12-12 22:34:12 -05:00
parent f6d0a4a9ac
commit ce8408a9c6
12 changed files with 72 additions and 102 deletions

View file

@ -286,6 +286,7 @@ def load_mount(description: Dict, index: Index, stage: Stage):
raise ValueError(f"Duplicated mount '{name}'")
source = description.get("source")
partition = description.get("partition")
target = description.get("target")
options = description.get("options", {})
@ -296,7 +297,7 @@ def load_mount(description: Dict, index: Index, stage: Stage):
if not device:
raise ValueError(f"Unknown device '{source}' for mount '{name}'")
stage.add_mount(name, info, device, target, options)
stage.add_mount(name, info, device, partition, target, options)
def load_stage(description: Dict, index: Index, pipeline: Pipeline, manifest: Manifest, source_refs):

View file

@ -23,10 +23,11 @@ class Mount:
A single mount with its corresponding options
"""
def __init__(self, name, info, device, target, options: Dict):
def __init__(self, name, info, device, partition, target, options: Dict):
self.name = name
self.info = info
self.device = device
self.partition = partition
self.target = target
self.options = options
self.id = self.calc_id()
@ -71,6 +72,11 @@ class MountManager:
if relpath and os.path.exists(os.path.join('/dev', relpath)):
source = os.path.join('/dev', relpath)
# If the user specified a partition then the filesystem to
# mount is actually on a partition of the disk.
if source and mount.partition:
source = f"{source}p{mount.partition}"
root = os.fspath(self.root)
args = {

View file

@ -111,8 +111,8 @@ class Stage:
self.devices[name] = dev
return dev
def add_mount(self, name, info, device, target, options):
mount = Mount(name, info, device, target, options)
def add_mount(self, name, info, device, partition, target, options):
mount = Mount(name, info, device, partition, target, options)
self.mounts[name] = mount
return mount