Skip to content

Commit fe187c3

Browse files
ravanellidustymabe
authored andcommitted
osbuild: Add Live ISO/PXE build support
This backports and takes advantage of the new org.osbuild.coreos.live-artifacts.mono stage. Signed-off-by: Renata Ravanelli <[email protected]>
1 parent 1c55085 commit fe187c3

14 files changed

+1257
-2
lines changed

build.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,11 @@ patch_osbuild() {
177177
/usr/lib/coreos-assembler/0002-parsing-treat-locations-without-scheme-as-belonging-.patch \
178178
/usr/lib/coreos-assembler/0003-org.osbuild.selinux-support-operating-on-mounts.patch \
179179
/usr/lib/coreos-assembler/0004-org.osbuild.selinux-support-for-specifying-where-fil.patch \
180+
/usr/lib/coreos-assembler/0001-osbuild-remoteloop-add-more-loop-device-options.patch \
181+
/usr/lib/coreos-assembler/0002-osbuild-loop-make-the-loop-device-if-missing.patch \
182+
/usr/lib/coreos-assembler/0003-util-osrelease.py-improve-whitespace-and-quote-strip.patch \
183+
/usr/lib/coreos-assembler/0004-util-chroot-Add-support-for-custom-directory-bind-mo.patch \
184+
/usr/lib/coreos-assembler/0005-stages-add-coreos.live-artifacts.mono-stage.patch \
180185
| patch -d /usr/lib/osbuild -p1
181186

182187
# And then move the files back; supermin appliance creation will need it back
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
From 9edf8572ad4797033e7342c308ac617aa284f3ae Mon Sep 17 00:00:00 2001
2+
From: Dusty Mabe <[email protected]>
3+
Date: Fri, 22 Nov 2024 19:02:57 -0500
4+
Subject: [PATCH 1/5] osbuild/remoteloop: add more loop device options
5+
6+
This adds lock, partscan, read_only, sector_size to _create_device()
7+
similar to make_loop() from devices/org.osbuild.loopback.
8+
---
9+
osbuild/remoteloop.py | 42 +++++++++++++++++++++++++++++++++++++-----
10+
1 file changed, 37 insertions(+), 5 deletions(-)
11+
12+
diff --git a/osbuild/remoteloop.py b/osbuild/remoteloop.py
13+
index 0544e0be..0fd2cfc0 100644
14+
--- a/osbuild/remoteloop.py
15+
+++ b/osbuild/remoteloop.py
16+
@@ -41,8 +41,23 @@ class LoopServer(api.BaseAPI):
17+
self.devs = []
18+
self.ctl = loop.LoopControl()
19+
20+
- def _create_device(self, fd, dir_fd, offset=None, sizelimit=None):
21+
- lo = self.ctl.loop_for_fd(fd, offset=offset, sizelimit=sizelimit, autoclear=True)
22+
+ def _create_device(
23+
+ self,
24+
+ fd,
25+
+ dir_fd,
26+
+ offset=None,
27+
+ sizelimit=None,
28+
+ lock=False,
29+
+ partscan=False,
30+
+ read_only=False,
31+
+ sector_size=512):
32+
+ lo = self.ctl.loop_for_fd(fd, lock=lock,
33+
+ offset=offset,
34+
+ sizelimit=sizelimit,
35+
+ blocksize=sector_size,
36+
+ partscan=partscan,
37+
+ read_only=read_only,
38+
+ autoclear=True)
39+
lo.mknod(dir_fd)
40+
# Pin the Loop objects so they are only released when the LoopServer
41+
# is destroyed.
42+
@@ -54,8 +69,12 @@ class LoopServer(api.BaseAPI):
43+
dir_fd = fds[msg["dir_fd"]]
44+
offset = msg.get("offset")
45+
sizelimit = msg.get("sizelimit")
46+
+ lock = msg.get("lock", False)
47+
+ partscan = msg.get("partscan", False)
48+
+ read_only = msg.get("read_only", False)
49+
+ sector_size = msg.get("sector_size", 512)
50+
51+
- devname = self._create_device(fd, dir_fd, offset, sizelimit)
52+
+ devname = self._create_device(fd, dir_fd, offset, sizelimit, lock, partscan, read_only, sector_size)
53+
sock.send({"devname": devname})
54+
55+
def _cleanup(self):
56+
@@ -75,11 +94,20 @@ class LoopClient:
57+
self.client.close()
58+
59+
@contextlib.contextmanager
60+
- def device(self, filename, offset=None, sizelimit=None):
61+
+ def device(
62+
+ self,
63+
+ filename,
64+
+ offset=None,
65+
+ sizelimit=None,
66+
+ lock=False,
67+
+ partscan=False,
68+
+ read_only=False,
69+
+ sector_size=512):
70+
req = {}
71+
fds = []
72+
73+
- fd = os.open(filename, os.O_RDWR)
74+
+ flags = os.O_RDONLY if read_only else os.O_RDWR
75+
+ fd = os.open(filename, flags)
76+
dir_fd = os.open("/dev", os.O_DIRECTORY)
77+
78+
fds.append(fd)
79+
@@ -91,6 +119,10 @@ class LoopClient:
80+
req["offset"] = offset
81+
if sizelimit:
82+
req["sizelimit"] = sizelimit
83+
+ req["lock"] = lock
84+
+ req["partscan"] = partscan
85+
+ req["read_only"] = read_only
86+
+ req["sector_size"] = sector_size
87+
88+
self.client.send(req, fds=fds)
89+
os.close(dir_fd)
90+
--
91+
2.47.0
92+
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
From 4f09c4d4c1ad2026346a98e63f0e13155d0f0487 Mon Sep 17 00:00:00 2001
2+
From: Dusty Mabe <[email protected]>
3+
Date: Mon, 25 Nov 2024 16:29:10 -0500
4+
Subject: [PATCH 2/5] osbuild/loop: make the loop device if missing
5+
6+
A few times during development I saw an error where the loop
7+
device wasn't getting created. Maybe it was some weird state
8+
issue with my system (i.e. loopback devices are global), or
9+
maybe not. Either way maybe it won't hurt to create it if
10+
it doesn't exist.
11+
---
12+
osbuild/loop.py | 6 ++++++
13+
1 file changed, 6 insertions(+)
14+
15+
diff --git a/osbuild/loop.py b/osbuild/loop.py
16+
index ec6d3619..b768af22 100644
17+
--- a/osbuild/loop.py
18+
+++ b/osbuild/loop.py
19+
@@ -126,6 +126,12 @@ class Loop:
20+
if not dir_fd:
21+
dir_fd = os.open("/dev", os.O_DIRECTORY)
22+
stack.callback(lambda: os.close(dir_fd))
23+
+ # If the loopdev didn't show up for some reason let's
24+
+ # create it manually
25+
+ try:
26+
+ os.stat(self.devname, dir_fd=dir_fd)
27+
+ except FileNotFoundError:
28+
+ self.mknod(dir_fd)
29+
self.fd = os.open(self.devname, os.O_RDWR, dir_fd=dir_fd)
30+
31+
info = os.stat(self.fd)
32+
--
33+
2.47.0
34+
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
From a835c409a19a9c72b5e669a70664ea960d873704 Mon Sep 17 00:00:00 2001
2+
From: Renata Ravanelli <[email protected]>
3+
Date: Tue, 12 Nov 2024 15:12:52 -0300
4+
Subject: [PATCH 3/5] util/osrelease.py: improve whitespace and quote stripping
5+
6+
- Enhanced the value stripping logic in osrelease parsing
7+
to handle leading and trailing spaces, newlines, tabs,
8+
and both single and double quotes.
9+
- This ensures cleaner and more accurate key-value assignments.
10+
11+
Signed-off-by: Renata Ravanelli <[email protected]>
12+
(cherry picked from commit 066f1ea89fbda6e886a5d88119586c0f09b0a234)
13+
---
14+
osbuild/util/osrelease.py | 2 +-
15+
1 file changed, 1 insertion(+), 1 deletion(-)
16+
17+
diff --git a/osbuild/util/osrelease.py b/osbuild/util/osrelease.py
18+
index b8d56e73..a2b61d26 100644
19+
--- a/osbuild/util/osrelease.py
20+
+++ b/osbuild/util/osrelease.py
21+
@@ -33,7 +33,7 @@ def parse_files(*paths):
22+
if line[0] == "#":
23+
continue
24+
key, value = line.split("=", 1)
25+
- osrelease[key] = value.strip('"')
26+
+ osrelease[key] = value.strip(" \n\t'\"")
27+
28+
return osrelease
29+
30+
--
31+
2.47.0
32+
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
From c367e6506ed9d4c674795ccc2da7a850c367398e Mon Sep 17 00:00:00 2001
2+
From: Renata Ravanelli <[email protected]>
3+
Date: Thu, 31 Oct 2024 14:13:50 -0300
4+
Subject: [PATCH 4/5] util/chroot: Add support for custom directory bind mounts
5+
6+
- Add optional bind_mounts parameter to __init__ method;
7+
- Enhanced methods to accept an optional `bind_mounts`.
8+
This allows for more flexible for configurations when setting
9+
up bind mounts.
10+
11+
Signed-off-by: Renata Ravanelli <[email protected]>
12+
(cherry picked from commit 9b5fbadee6b170455d62c57eb315e20d57173110)
13+
---
14+
osbuild/util/chroot.py | 15 ++++++++++++++-
15+
1 file changed, 14 insertions(+), 1 deletion(-)
16+
17+
diff --git a/osbuild/util/chroot.py b/osbuild/util/chroot.py
18+
index da14bf44..11245bbd 100644
19+
--- a/osbuild/util/chroot.py
20+
+++ b/osbuild/util/chroot.py
21+
@@ -12,8 +12,9 @@ class Chroot:
22+
This mounts /proc, /dev, and /sys.
23+
"""
24+
25+
- def __init__(self, root: str):
26+
+ def __init__(self, root: str, bind_mounts=None):
27+
self.root = root
28+
+ self._bind_mounts = bind_mounts or []
29+
30+
def __enter__(self):
31+
for d in ["/proc", "/dev", "/sys"]:
32+
@@ -33,6 +34,13 @@ class Chroot:
33+
"sysfs", f"{self.root}/sys"],
34+
check=True)
35+
36+
+ for d in self._bind_mounts:
37+
+ target_path = os.path.join(self.root, d.lstrip("/"))
38+
+ if not os.path.exists(target_path):
39+
+ print(f"Making missing chroot directory: {d}")
40+
+ os.makedirs(target_path)
41+
+ subprocess.run(["mount", "--rbind", d, target_path], check=True)
42+
+
43+
return self
44+
45+
def __exit__(self, exc_type, exc_value, tracebk):
46+
@@ -43,6 +51,11 @@ class Chroot:
47+
if failed_umounts:
48+
print(f"Error unmounting paths from chroot: {failed_umounts}")
49+
50+
+ for d in self._bind_mounts[::-1]:
51+
+ target_path = os.path.join(self.root, d.lstrip("/"))
52+
+ if subprocess.run(["umount", "--lazy", target_path], check=False).returncode != 0:
53+
+ print(f"Error unmounting paths from chroot: {d}")
54+
+
55+
def run(self, cmd, **kwargs):
56+
cmd = ["chroot", self.root] + cmd
57+
# pylint: disable=subprocess-run-check
58+
--
59+
2.47.0
60+

0 commit comments

Comments
 (0)