@@ -210,17 +210,6 @@ def make_stream_hash(src, dest):
210
210
outf .write (hashlib .sha256 (buf ).hexdigest () + '\n ' )
211
211
212
212
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
-
224
213
def generate_iso ():
225
214
# convention for kernel and initramfs names
226
215
kernel_img = 'vmlinuz'
@@ -284,7 +273,13 @@ def generate_iso():
284
273
with open (stamppath , 'w' ) as fh :
285
274
fh .write (args .build + '\n ' )
286
275
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.
288
283
with open (os .path .join (tmpisoimages , ignition_img ), 'wb' ) as fdst :
289
284
fdst .write (bytes (ignition_img_size ))
290
285
@@ -353,7 +348,6 @@ def generate_iso():
353
348
kargs = ' ' .join (kargs_array )
354
349
print (f'Substituting ISO kernel arguments: { kargs } ' )
355
350
356
- files_with_karg_embed_areas = {}
357
351
kargs_json = {'files' : []}
358
352
cmdline = ''
359
353
karg_embed_area_length = 0
@@ -386,26 +380,21 @@ def generate_iso():
386
380
raise Exception (f'Default cmdline is different: "{ cmdline } " != "{ file_kargs } "' )
387
381
388
382
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 ()
390
383
kargs_json ['files' ].append ({
391
384
'path' : os .path .join (dir_suffix , filename ),
392
385
'offset' : karg_area_start .start (),
393
386
})
394
387
if karg_embed_area_length == 0 :
395
388
karg_embed_area_length = length
396
389
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' ] } " )
398
391
with open (dstfile , 'w' ) as fh :
399
392
fh .write (buf )
400
393
shutil .copystat (srcfile , dstfile )
401
394
print (f'{ srcfile } -> { dstfile } ' )
402
395
403
- if len ( files_with_karg_embed_areas ) > 0 :
396
+ if karg_embed_area_length > 0 :
404
397
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 )
409
398
kargs_json .update (
410
399
size = karg_embed_area_length ,
411
400
default = cmdline .strip (),
610
599
if os .path .exists (os .path .join (tmpisoroot , f ['path' ]))]
611
600
kargs_json ['files' ].sort (key = lambda f : f ['path' ])
612
601
if kargs_json ['files' ]:
602
+ # Store the location of "karg embed areas" for use by
603
+ # `coreos-installer iso kargs modify`
613
604
with open (os .path .join (tmpisocoreos , kargs_file ), 'w' ) as fh :
614
605
json .dump (kargs_json , fh , indent = 2 , sort_keys = True )
615
606
fh .write ('\n ' )
@@ -661,77 +652,6 @@ boot
661
652
run_verbose (genisoargs_minimal )
662
653
if basearch == "x86_64" :
663
654
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
-
735
655
# this consumes the minimal image
736
656
run_verbose (['coreos-installer' , 'pack' , 'minimal-iso' ,
737
657
tmpisofile , f'{ tmpisofile } .minimal' , "--consume" ])
0 commit comments