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

@ -21,6 +21,10 @@ SCHEMA_2 = """
"source": {
"type": "string"
},
"partition": {
"description": "If the source device has partitions, the partition number, starting at one",
"type": "number"
},
"target": {
"type": "string"
},

View file

@ -21,6 +21,10 @@ SCHEMA_2 = """
"source": {
"type": "string"
},
"partition": {
"description": "If the source device has partitions, the partition number, starting at one",
"type": "number"
},
"target": {
"type": "string"
},

View file

@ -24,6 +24,10 @@ SCHEMA_2 = """
"target": {
"type": "string"
},
"partition": {
"description": "If the source device has partitions, the partition number, starting at one",
"type": "number"
},
"options": {
"type": "object",
"additionalProperties": false,

View file

@ -21,6 +21,9 @@ SCHEMA_2 = """
"source": {
"type": "string"
},
"partition": {
"type": "number"
},
"target": {
"type": "string"
},

View file

@ -24,6 +24,10 @@ SCHEMA_2 = """
"target": {
"type": "string"
},
"partition": {
"description": "If the source device has partitions, the partition number, starting at one",
"type": "number"
},
"options": {
"type": "object",
"additionalProperties": false,

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

View file

@ -82,6 +82,9 @@
"target": {
"type": "string"
},
"partition": {
"type": "number"
},
"options": {
"type": "object",
"additionalProperties": true

View file

@ -682,28 +682,11 @@
]
},
"devices": {
"efi": {
"disk": {
"type": "org.osbuild.loopback",
"options": {
"filename": "disk.img",
"start": 4096,
"size": 260096
}
},
"boot": {
"type": "org.osbuild.loopback",
"options": {
"filename": "disk.img",
"start": 264192,
"size": 786432
}
},
"root": {
"type": "org.osbuild.loopback",
"options": {
"filename": "disk.img",
"start": 1050624,
"size": 4194304
"partscan": true
}
}
},
@ -711,19 +694,22 @@
{
"name": "root",
"type": "org.osbuild.xfs",
"source": "root",
"source": "disk",
"partition": 4,
"target": "/"
},
{
"name": "boot",
"type": "org.osbuild.ext4",
"source": "boot",
"source": "disk",
"partition": 3,
"target": "/boot"
},
{
"name": "efi",
"type": "org.osbuild.fat",
"source": "efi",
"source": "disk",
"partition": 2,
"target": "/boot/efi"
}
]
@ -884,30 +870,11 @@
]
},
"devices": {
"efi": {
"disk": {
"type": "org.osbuild.loopback",
"options": {
"filename": "disk.img",
"start": 512,
"size": 32512,
"sector-size": 4096
}
},
"boot": {
"type": "org.osbuild.loopback",
"options": {
"filename": "disk.img",
"start": 33024,
"size": 98304,
"sector-size": 4096
}
},
"root": {
"type": "org.osbuild.loopback",
"options": {
"filename": "disk.img",
"start": 131328,
"size": 524288,
"partscan": true,
"sector-size": 4096
}
}
@ -916,19 +883,22 @@
{
"name": "root",
"type": "org.osbuild.xfs",
"source": "root",
"source": "disk",
"partition": 4,
"target": "/"
},
{
"name": "boot",
"type": "org.osbuild.ext4",
"source": "boot",
"source": "disk",
"partition": 3,
"target": "/boot"
},
{
"name": "efi",
"type": "org.osbuild.fat",
"source": "efi",
"source": "disk",
"partition": 2,
"target": "/boot/efi"
}
]

View file

@ -207,42 +207,29 @@ pipelines:
- from: input://tree/
to: mount://root/
devices:
efi:
disk:
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}'
partscan: true
mounts:
- name: root
type: org.osbuild.xfs
source: root
source: disk
partition:
mpp-format-int: '{image.layout[''root''].partnum}'
target: /
- name: boot
type: org.osbuild.ext4
source: boot
source: disk
partition:
mpp-format-int: '{image.layout[''boot''].partnum}'
target: /boot
- name: efi
type: org.osbuild.fat
source: efi
source: disk
partition:
mpp-format-int: '{image.layout[''EFI-SYSTEM''].partnum}'
target: /boot/efi
- type: org.osbuild.grub2.inst
options:
@ -339,48 +326,31 @@ pipelines:
- from: input://tree/
to: mount://root/
devices:
efi:
disk:
type: org.osbuild.loopback
options:
filename: disk.img
start:
mpp-format-int: '{image4k.layout[''EFI-SYSTEM''].start}'
size:
mpp-format-int: '{image4k.layout[''EFI-SYSTEM''].size}'
sector-size:
mpp-format-int: "{four_k_sector_size}"
boot:
type: org.osbuild.loopback
options:
filename: disk.img
start:
mpp-format-int: '{image4k.layout[''boot''].start}'
size:
mpp-format-int: '{image4k.layout[''boot''].size}'
sector-size:
mpp-format-int: "{four_k_sector_size}"
root:
type: org.osbuild.loopback
options:
filename: disk.img
start:
mpp-format-int: '{image4k.layout[''root''].start}'
size:
mpp-format-int: '{image4k.layout[''root''].size}'
partscan: true
sector-size:
mpp-format-int: "{four_k_sector_size}"
mounts:
- name: root
type: org.osbuild.xfs
source: root
source: disk
partition:
mpp-format-int: '{image4k.layout[''root''].partnum}'
target: /
- name: boot
type: org.osbuild.ext4
source: boot
source: disk
partition:
mpp-format-int: '{image4k.layout[''boot''].partnum}'
target: /boot
- name: efi
type: org.osbuild.fat
source: efi
source: disk
partition:
mpp-format-int: '{image4k.layout[''EFI-SYSTEM''].partnum}'
target: /boot/efi
- name: raw-metal-image
build: name:build

View file

@ -107,6 +107,7 @@ def mount(mgr, devpath, tree, size, mountpoint, options):
lpath,
index.get_module_info("Mount", "org.osbuild.fat"),
dev,
None,
"/",
options
)