Skip to content

Commit 99ce834

Browse files
committed
buildextend-live: drop legacy embed headers
coreos-installer now knows how to locate ignition.img and kargs.json directly in the ISO 9660 filesystem, so we don't need the custom coreiso+ and coreKarg headers anymore.
1 parent 189d179 commit 99ce834

File tree

1 file changed

+11
-91
lines changed

1 file changed

+11
-91
lines changed

src/cmd-buildextend-live

Lines changed: 11 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -210,17 +210,6 @@ def make_stream_hash(src, dest):
210210
outf.write(hashlib.sha256(buf).hexdigest() + '\n')
211211

212212

213-
def file_offset_in_iso(isoinfo, filename):
214-
# -rw-rw-r-- 1 1750 1750 553961457 Sep 18 2019 [ 4733 00] filename
215-
# match the logical block number ^^^^ ||
216-
# file type, always 00 ^^
217-
matches = list(re.finditer(r'\[\s*([0-9]+) 00\]\s+{}\s*$'.format(filename),
218-
isoinfo, re.MULTILINE))
219-
if len(matches) != 1:
220-
raise Exception('Found {} copies of {}'.format(len(matches), filename))
221-
return int(matches[0].group(1)) * 2048 # assume 2 KB per logical block
222-
223-
224213
def generate_iso():
225214
# convention for kernel and initramfs names
226215
kernel_img = 'vmlinuz'
@@ -284,7 +273,13 @@ def generate_iso():
284273
with open(stamppath, 'w') as fh:
285274
fh.write(args.build + '\n')
286275

287-
# Add placeholder for Ignition CPIO file
276+
# Add placeholder for Ignition CPIO file. This allows an external tool,
277+
# `coreos-installer iso ignition embed`, to modify an existing ISO image
278+
# to embed a user's custom Ignition config. The tool wraps the Ignition
279+
# config in a cpio.xz and write it directly into this file in the ISO
280+
# image. The cpio.xz will be read into the initramfs filesystem at
281+
# runtime and the Ignition Dracut module will ensure that the config is
282+
# moved where Ignition will see it.
288283
with open(os.path.join(tmpisoimages, ignition_img), 'wb') as fdst:
289284
fdst.write(bytes(ignition_img_size))
290285

@@ -353,7 +348,6 @@ def generate_iso():
353348
kargs = ' '.join(kargs_array)
354349
print(f'Substituting ISO kernel arguments: {kargs}')
355350

356-
files_with_karg_embed_areas = {}
357351
kargs_json = {'files': []}
358352
cmdline = ''
359353
karg_embed_area_length = 0
@@ -386,26 +380,21 @@ def generate_iso():
386380
raise Exception(f'Default cmdline is different: "{cmdline}" != "{file_kargs}"')
387381

388382
length = karg_area_end.start() + len(karg_area_end[1]) - karg_area_start.start()
389-
files_with_karg_embed_areas[dstfile] = karg_area_start.start()
390383
kargs_json['files'].append({
391384
'path': os.path.join(dir_suffix, filename),
392385
'offset': karg_area_start.start(),
393386
})
394387
if karg_embed_area_length == 0:
395388
karg_embed_area_length = length
396389
elif length != karg_embed_area_length:
397-
raise Exception(f"Karg embed areas of varying length {list(files_with_karg_embed_areas)}")
390+
raise Exception(f"Karg embed areas of varying length {kargs_json['files']}")
398391
with open(dstfile, 'w') as fh:
399392
fh.write(buf)
400393
shutil.copystat(srcfile, dstfile)
401394
print(f'{srcfile} -> {dstfile}')
402395

403-
if len(files_with_karg_embed_areas) > 0:
396+
if karg_embed_area_length > 0:
404397
assert(karg_embed_area_length > len(cmdline))
405-
with open(os.path.join(tmpisoroot, '.cmdline'), 'w') as fh:
406-
fh.write('#' * karg_embed_area_length)
407-
fh.seek(0)
408-
fh.write(cmdline)
409398
kargs_json.update(
410399
size=karg_embed_area_length,
411400
default=cmdline.strip(),
@@ -610,6 +599,8 @@ boot
610599
if os.path.exists(os.path.join(tmpisoroot, f['path']))]
611600
kargs_json['files'].sort(key=lambda f: f['path'])
612601
if kargs_json['files']:
602+
# Store the location of "karg embed areas" for use by
603+
# `coreos-installer iso kargs modify`
613604
with open(os.path.join(tmpisocoreos, kargs_file), 'w') as fh:
614605
json.dump(kargs_json, fh, indent=2, sort_keys=True)
615606
fh.write('\n')
@@ -661,77 +652,6 @@ boot
661652
run_verbose(genisoargs_minimal)
662653
if basearch == "x86_64":
663654
run_verbose(['/usr/bin/isohybrid', '--uefi', f'{tmpisofile}.minimal'])
664-
665-
isoinfo = run_verbose(['isoinfo', '-lR', '-i', tmpisofile],
666-
stdout=subprocess.PIPE, text=True).stdout
667-
668-
# We've already created a file in the ISO with ignition_img_size
669-
# bytes of zeroes. Find the byte offset of that file within the ISO
670-
# image and write it into a custom header at the end of the ISO 9660
671-
# System Area, which is 32 KB at the start of the image "reserved for
672-
# system use". The System Area usually contains partition tables and
673-
# the like, and we're assuming that none of our platforms use the last
674-
# 24 bytes of it.
675-
#
676-
# This allows an external tool, `coreos-installer iso embed`, to modify
677-
# an existing ISO image to embed a user's custom Ignition config.
678-
# The tool wraps the Ignition config in a cpio.gz and uses our header
679-
# to write it directly into the ISO image. The cpio.gz will be read
680-
# into the initramfs filesystem at runtime and the Ignition Dracut module
681-
# will ensure that the config is moved where Ignition will see it.
682-
#
683-
# Skip on s390x because that platform uses an embedded El Torito image
684-
# with its own copy of the initramfs.
685-
#
686-
# Recently, we also play a similar trick for injecting kernel arguments: we
687-
# store the location of "karg embed areas" at the end of the System Area
688-
# (in the 72 bytes before the 24 bytes for the initrd info). This is then
689-
# picked up by `coreos-installer iso embed-kargs`.
690-
if basearch != "s390x":
691-
# size of System Area section at start of ISO9660 images
692-
ISO_SYSTEM_AREA_SIZE = 32768
693-
694-
# number of karg files we allow for in the format
695-
MAX_KARG_FILES = 6
696-
697-
# prune out karg files which don't exist anymore
698-
files_with_karg_embed_areas = {k: v for (k, v) in
699-
files_with_karg_embed_areas.items() if
700-
os.path.exists(k)}
701-
702-
assert len(files_with_karg_embed_areas) <= MAX_KARG_FILES
703-
704-
# these can really never change without ratcheting on the
705-
# coreos-installer side first
706-
INITRDFMT = '<8s2Q'
707-
assert struct.calcsize(INITRDFMT) == 24
708-
KARGSFMT = f"<8s{MAX_KARG_FILES+1+1}Q" # +1 for area length and +1 for offset to default read-only '.cmdline'
709-
assert struct.calcsize(KARGSFMT) == 72
710-
711-
# Start of the Ignition padding within the ISO
712-
offset = file_offset_in_iso(isoinfo, ignition_img)
713-
with open(tmpisofile, 'r+b') as isofh:
714-
# Verify that the calculated byte range is empty
715-
isofh.seek(offset)
716-
if isofh.read(ignition_img_size) != bytes(ignition_img_size):
717-
raise Exception(f'ISO image {ignition_img_size} bytes at {offset} are not zero')
718-
719-
# Write header at the end of the System Area
720-
isofh.seek(ISO_SYSTEM_AREA_SIZE - (struct.calcsize(INITRDFMT) +
721-
struct.calcsize(KARGSFMT)))
722-
723-
offsets = [0] * (MAX_KARG_FILES + 1) # +1 for offset to default
724-
# This is ours default read-only '.cmdline' file, which is used for `coreos-installer iso kargs reset ISO`
725-
offsets[0] = file_offset_in_iso(isoinfo, '.cmdline')
726-
727-
for i, fn in enumerate(files_with_karg_embed_areas):
728-
offset_in_file = files_with_karg_embed_areas[fn]
729-
offsets[i + 1] = file_offset_in_iso(isoinfo, os.path.basename(fn)) + offset_in_file
730-
isofh.write(struct.pack(KARGSFMT, b'coreKarg', karg_embed_area_length, *offsets))
731-
# Magic number + offset + length
732-
isofh.write(struct.pack(INITRDFMT, b'coreiso+', offset, ignition_img_size))
733-
print(f'Embedded {ignition_img_size} bytes Ignition config space at {offset}')
734-
735655
# this consumes the minimal image
736656
run_verbose(['coreos-installer', 'pack', 'minimal-iso',
737657
tmpisofile, f'{tmpisofile}.minimal', "--consume"])

0 commit comments

Comments
 (0)