[mic][iso] Added the ability to customize an existing mic-generated iso.#8785
Conversation
bfaf011 to
973a1a0
Compare
| }() | ||
|
|
||
| // estimate the new disk size | ||
| safeDiskSizeMB, err := getDiskSizeEstimateInMBs(squashMountDir, 2 /*safety factor*/) |
There was a problem hiding this comment.
Why is the safety factor so large? Being off by an order of magnitude suggests that something is wrong.
There was a problem hiding this comment.
I've changed it to 1.5. It's hard to estimate the size without some more calculations. I'm trying to err on the safe side.
There was a problem hiding this comment.
btw:
I've found out that du returns the total size of disk blocks used. It does not just add the exact size of each file. So, du will return 4k for 2 byte file, for example. This makes me think we can lower the safety factor, since choosing a block size that's not 4k is not common. Open to suggestions here...
a9c121d to
5f4ee0c
Compare
|
|
||
| // define a disk layout with a boot partition and a rootfs partition | ||
| var maxDiskSizeMB imagecustomizerapi.DiskSize | ||
| maxDiskSizeMB = imagecustomizerapi.DiskSize(safeDiskSizeMB * 1024 * 1024) |
There was a problem hiding this comment.
Add the ESP partition to the disk's max size?
There was a problem hiding this comment.
It's already included since the squashfs has both partitions included.
| err := ic.isoBuilder.createWriteableImageFromSquashfs(ic.buildDir, ic.rawImageFile) | ||
| if err != nil { | ||
| return fmt.Errorf("failed to create writeable image:\n%w", err) | ||
| } |
There was a problem hiding this comment.
Should ic.isoBuilder be deleted here? When customizeOSPartitions is true, ic.isoBuilder isn't used after this point.
There was a problem hiding this comment.
It actually needs to survive post this point...
isoBuilder has populated its internal state with all the relevant artifacts. That state can be used to regenerate the iso again without re-building any of these artifacts.
I've moved isoBuild out of the parameter structure so that it's not a side effect anymore. It's now returned from convertInputImageToWriteableFormat and is fed into convertWriteableFormatToOutputImage.
There was a problem hiding this comment.
But you create a new copy of the LiveOSIsoBuilder type in the createLiveOSIsoImage function. So, surely the resources being held by ic.isoBuilder aren't needed?
There was a problem hiding this comment.
I see you're point. You're right. I think we can make that decision right here.
pending.
There was a problem hiding this comment.
I've found a flow where we do need the input iso builder object even when we're re-creating the squashfs. So, I need to keep it around.
Basically, when doing iso->iso creation, even if we re-create the squashfs (boot + rootfs), we still need the original iso state to determine what extra files the user has packed into it (in a previous customization), and copy them unto the new iso as well.
| While converting the input full disk image into a LiveOS ISO involves copying | ||
| The Azure Linux Image Customizer can customize an input image and package the | ||
| output as a LiveOS iso image. The input image can be a full disk image | ||
| (vhd/vhdx/qcow2/raw) or another LiveOS iso image. The LiveOS iso output format |
There was a problem hiding this comment.
does it have to be LiveOS iso only? what will happen if a regular iso is used?
There was a problem hiding this comment.
Correct, the input iso has to an image previously generated by mic. If the input iso does not have the same exact names and location of bits as the one generated by mic, customization will fail.
There was a problem hiding this comment.
[we need to locate bootloaders, kernel, initrd, rootfs, grub.cfg in specific locations and with specific names]
|
|
||
| switch config.OS.ResetBootLoaderType { | ||
| case imagecustomizerapi.ResetBootLoaderTypeHard: | ||
| if config.Storage == nil { |
There was a problem hiding this comment.
I thought storage is not necessary to resetBootLoaderType but the other way around is mandated (where resetBootLoaderType is a must when storage is specified), is that not the case anymore?
| // the total size of a collection of files is multiplied by the | ||
| // expansionSafetyFactor to estimate a disk size sufficient to hold those | ||
| // files. | ||
| expansionSafetyFactor = 1.5 |
There was a problem hiding this comment.
curious - is this based of anything specific or just a buffered estimate?
There was a problem hiding this comment.
not based on anything specific - just a buffered estimate.
I've found out that du returns the total size of disk blocks used. It does not just add the exact size of each file. So, du will return 4k for 2 byte file, for example. This makes me think we can lower the safety factor, since choosing a block size that's not 4k is not common. Open to suggestions here...
| err := ic.isoBuilder.createWriteableImageFromSquashfs(ic.buildDir, ic.rawImageFile) | ||
| if err != nil { | ||
| return fmt.Errorf("failed to create writeable image:\n%w", err) | ||
| } |
There was a problem hiding this comment.
But you create a new copy of the LiveOSIsoBuilder type in the createLiveOSIsoImage function. So, surely the resources being held by ic.isoBuilder aren't needed?
d711e63 to
74c3a4c
Compare
|
|
||
| inputIsoArtifacts, err := createIsoBuilderFromIsoImage(ic.buildDir, ic.buildDirAbs, ic.inputImageFile) | ||
| if err != nil { | ||
| var cleanUpError error |
There was a problem hiding this comment.
This cleanup should occur in createIsoBuilderFromIsoImage, not in the caller of createIsoBuilderFromIsoImage.
It might be helpful to create a createIsoBuilderFromIsoImageHelper function that handles all the initialization logic. Then have the createIsoBuilderFromIsoImage call the createIsoBuilderFromIsoImageHelper function and call the cleanup logic if createIsoBuilderFromIsoImageHelper fails.
There was a problem hiding this comment.
makes sense. I've moved isobuilder.cleanUp() into createIsoBuilderFromIsoImage() and set it such that it gets called only if there's an error. This 'only if' avoid having to add the call to each error handling in the rest of createIsoBuilderFromIsoImage() (and I think we can do without the helper function).
func someFunc() (err error ) {
x := &SomeType{}
defer func() { if err != nil {x.cleanUp} }()
err = anotherFunc()
if err != nil { return err } // -> this invokes the clean-up code.
return nil // -> this does not invoke the clean-up code.
}
| // However, there are no customizations, and the input is an iso, we | ||
| // should just return - but call out any command line switches that might | ||
| // have requested unsupported changes. | ||
| if !ic.customizeOSPartitions && ic.inputImageFormat == ".iso" { |
There was a problem hiding this comment.
Should we also error out if the input is an ISO and the config has a .storage value?
There was a problem hiding this comment.
if .storage is defined, that will enable the usual mic flow - i.e.
- input is an iso
- because one of storage, os, scripts nodes is defined:
- input iso is converted to a writeable disk with a boot partition + a rootfs partition
- storage configuration is processed as usual
- we create an iso from the final state of the writeable disk
So, while it should just work, we can still disable it since the value of repartitioning is not there. All partitions get collapsed into the squashfs anyway (the same argument for vhd(x)/qcow -> iso actually - but users can use storage to move content from other partitions to the boot/rootfs. So, we shouldn't disable this scenario for vhdx(x)/qcow->iso).
I think it makes sense to disable since there's no point of having it.
Merge Checklist
All boxes should be checked before merging the PR (just tick any boxes which don't apply to this PR)
*-staticsubpackages, etc.) have had theirReleasetag incremented../cgmanifest.json,./toolkit/scripts/toolchain/cgmanifest.json,.github/workflows/cgmanifest.json)./SPECS/LICENSES-AND-NOTICES/data/licenses.json,./SPECS/LICENSES-AND-NOTICES/LICENSES-MAP.md,./SPECS/LICENSES-AND-NOTICES/LICENSE-EXCEPTIONS.PHOTON)*.signatures.jsonfilessudo make go-tidy-allandsudo make go-test-coveragepassSummary
This PR allows MIC to take a mic-generated LiveOS iso and customize it.
Customization spans both the squashfs os image as well as the iso file system.
Change Log
Does this affect the toolchain?
NO
Associated issues
Links to CVEs
Test Methodology