From ce8408a9c6cd4e1137b9da9546f0af287829784f Mon Sep 17 00:00:00 2001 From: Dusty Mabe Date: Tue, 12 Dec 2023 22:34:12 -0500 Subject: [PATCH] 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 --- mounts/org.osbuild.btrfs | 4 + mounts/org.osbuild.ext4 | 4 + mounts/org.osbuild.fat | 4 + mounts/org.osbuild.noop | 3 + mounts/org.osbuild.xfs | 4 + osbuild/formats/v2.py | 3 +- osbuild/mounts.py | 8 +- osbuild/pipeline.py | 4 +- schemas/osbuild2.json | 3 + .../manifests/fedora-coreos-container.json | 62 ++++------------ .../fedora-coreos-container.mpp.yaml | 74 ++++++------------- test/run/test_mount.py | 1 + 12 files changed, 72 insertions(+), 102 deletions(-) diff --git a/mounts/org.osbuild.btrfs b/mounts/org.osbuild.btrfs index 4a5bff9f..a2b862a3 100755 --- a/mounts/org.osbuild.btrfs +++ b/mounts/org.osbuild.btrfs @@ -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" }, diff --git a/mounts/org.osbuild.ext4 b/mounts/org.osbuild.ext4 index 74eb58bf..333f807f 100755 --- a/mounts/org.osbuild.ext4 +++ b/mounts/org.osbuild.ext4 @@ -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" }, diff --git a/mounts/org.osbuild.fat b/mounts/org.osbuild.fat index 6ea54f61..37c966e1 100755 --- a/mounts/org.osbuild.fat +++ b/mounts/org.osbuild.fat @@ -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, diff --git a/mounts/org.osbuild.noop b/mounts/org.osbuild.noop index 0dea2814..7f81c36d 100755 --- a/mounts/org.osbuild.noop +++ b/mounts/org.osbuild.noop @@ -21,6 +21,9 @@ SCHEMA_2 = """ "source": { "type": "string" }, + "partition": { + "type": "number" + }, "target": { "type": "string" }, diff --git a/mounts/org.osbuild.xfs b/mounts/org.osbuild.xfs index 1e294325..6bc34eaf 100755 --- a/mounts/org.osbuild.xfs +++ b/mounts/org.osbuild.xfs @@ -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, diff --git a/osbuild/formats/v2.py b/osbuild/formats/v2.py index c0366d5e..4ce5ae6d 100644 --- a/osbuild/formats/v2.py +++ b/osbuild/formats/v2.py @@ -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): diff --git a/osbuild/mounts.py b/osbuild/mounts.py index 76a143cc..2cd33095 100644 --- a/osbuild/mounts.py +++ b/osbuild/mounts.py @@ -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 = { diff --git a/osbuild/pipeline.py b/osbuild/pipeline.py index 92b50dcf..a450d791 100644 --- a/osbuild/pipeline.py +++ b/osbuild/pipeline.py @@ -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 diff --git a/schemas/osbuild2.json b/schemas/osbuild2.json index 96795c53..562fb777 100644 --- a/schemas/osbuild2.json +++ b/schemas/osbuild2.json @@ -82,6 +82,9 @@ "target": { "type": "string" }, + "partition": { + "type": "number" + }, "options": { "type": "object", "additionalProperties": true diff --git a/test/data/manifests/fedora-coreos-container.json b/test/data/manifests/fedora-coreos-container.json index f307a33c..e253a61e 100644 --- a/test/data/manifests/fedora-coreos-container.json +++ b/test/data/manifests/fedora-coreos-container.json @@ -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" } ] diff --git a/test/data/manifests/fedora-coreos-container.mpp.yaml b/test/data/manifests/fedora-coreos-container.mpp.yaml index b07d5816..aefda0d9 100644 --- a/test/data/manifests/fedora-coreos-container.mpp.yaml +++ b/test/data/manifests/fedora-coreos-container.mpp.yaml @@ -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 diff --git a/test/run/test_mount.py b/test/run/test_mount.py index 005ad299..2a741f00 100755 --- a/test/run/test_mount.py +++ b/test/run/test_mount.py @@ -107,6 +107,7 @@ def mount(mgr, devpath, tree, size, mountpoint, options): lpath, index.get_module_info("Mount", "org.osbuild.fat"), dev, + None, "/", options )