Skip to content

[mic][iso] Added the ability to customize an existing mic-generated iso.#8785

Merged
gmileka merged 11 commits into
3.0-devfrom
gmileka/iso-customize-iso-2
May 7, 2024
Merged

[mic][iso] Added the ability to customize an existing mic-generated iso.#8785
gmileka merged 11 commits into
3.0-devfrom
gmileka/iso-customize-iso-2

Conversation

@gmileka

@gmileka gmileka commented Apr 12, 2024

Copy link
Copy Markdown
Merge Checklist

All boxes should be checked before merging the PR (just tick any boxes which don't apply to this PR)

  • The toolchain has been rebuilt successfully (or no changes were made to it)
  • The toolchain/worker package manifests are up-to-date
  • Any updated packages successfully build (or no packages were changed)
  • Packages depending on static components modified in this PR (Golang, *-static subpackages, etc.) have had their Release tag incremented.
  • Package tests (%check section) have been verified with RUN_CHECK=y for existing SPEC files, or added to new SPEC files
  • All package sources are available
  • cgmanifest files are up-to-date and sorted (./cgmanifest.json, ./toolkit/scripts/toolchain/cgmanifest.json, .github/workflows/cgmanifest.json)
  • LICENSE-MAP files are up-to-date (./SPECS/LICENSES-AND-NOTICES/data/licenses.json, ./SPECS/LICENSES-AND-NOTICES/LICENSES-MAP.md, ./SPECS/LICENSES-AND-NOTICES/LICENSE-EXCEPTIONS.PHOTON)
  • All source files have up-to-date hashes in the *.signatures.json files
  • sudo make go-tidy-all and sudo make go-test-coverage pass
  • Documentation has been updated to match any changes to the build system
  • Ready to merge

Summary

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
  • none
Test Methodology
  • Created the following flavors and ensured they all boot successfully and we can log-in with mic/ci credentials:
    • vhdx->vhdx
      • os customizations
    • vhdx->iso
      • os with ci customizations + iso customizations {additional files + kernel params }
      • os customizations + iso with ci customizations {additional files + kernel params }
        • iso {from previous step} -> iso
          • iso customization
          • os customization
          • both os and iso customization

@gmileka gmileka force-pushed the gmileka/iso-customize-iso-2 branch 2 times, most recently from bfaf011 to 973a1a0 Compare April 17, 2024 03:28
@gmileka gmileka changed the title Gmileka/iso customize iso 2 [mic][iso] Added the ability to customie an existing mic-generated iso. Apr 17, 2024
@gmileka gmileka marked this pull request as ready for review April 18, 2024 00:07
@gmileka gmileka requested a review from a team as a code owner April 18, 2024 00:07
Comment thread toolkit/tools/imagecustomizer/docs/iso.md Outdated
Comment thread toolkit/tools/imagecustomizer/docs/iso.md Outdated
Comment thread toolkit/tools/pkg/imagecustomizerlib/customizeutils.go
Comment thread toolkit/tools/pkg/imagecustomizerlib/imagecustomizer.go Outdated
Comment thread toolkit/tools/pkg/imagecustomizerlib/imagecustomizer.go Outdated
Comment thread toolkit/tools/pkg/imagecustomizerlib/liveosisobuilder.go Outdated
Comment thread toolkit/tools/pkg/imagecustomizerlib/liveosisobuilder.go Outdated
Comment thread toolkit/tools/pkg/imagecustomizerlib/liveosisobuilder.go Outdated
}()

// estimate the new disk size
safeDiskSizeMB, err := getDiskSizeEstimateInMBs(squashMountDir, 2 /*safety factor*/)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is the safety factor so large? Being off by an order of magnitude suggests that something is wrong.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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...

Comment thread toolkit/tools/pkg/imagecustomizerlib/liveosisobuilder.go Outdated
@gmileka gmileka force-pushed the gmileka/iso-customize-iso-2 branch 2 times, most recently from a9c121d to 5f4ee0c Compare April 18, 2024 20:58
Comment thread toolkit/tools/pkg/imagecustomizerlib/liveosisobuilder.go Outdated
Comment thread toolkit/tools/pkg/imagecustomizerlib/liveosisobuilder.go Outdated
Comment thread toolkit/tools/pkg/imagecustomizerlib/liveosisobuilder.go Outdated

// define a disk layout with a boot partition and a rootfs partition
var maxDiskSizeMB imagecustomizerapi.DiskSize
maxDiskSizeMB = imagecustomizerapi.DiskSize(safeDiskSizeMB * 1024 * 1024)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add the ESP partition to the disk's max size?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's already included since the squashfs has both partitions included.

Comment thread toolkit/tools/pkg/imagecustomizerlib/liveosisobuilder.go Outdated
Comment thread toolkit/tools/pkg/imagecustomizerlib/liveosisobuilder.go Outdated
Comment thread toolkit/tools/pkg/imagecustomizerlib/liveosisobuilder.go Outdated
Comment thread toolkit/tools/pkg/imagecustomizerlib/liveosisobuilder.go Outdated
Comment thread toolkit/tools/pkg/imagecustomizerlib/liveosisobuilder.go Outdated
err := ic.isoBuilder.createWriteableImageFromSquashfs(ic.buildDir, ic.rawImageFile)
if err != nil {
return fmt.Errorf("failed to create writeable image:\n%w", err)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should ic.isoBuilder be deleted here? When customizeOSPartitions is true, ic.isoBuilder isn't used after this point.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see you're point. You're right. I think we can make that decision right here.
pending.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@gmileka gmileka changed the title [mic][iso] Added the ability to customie an existing mic-generated iso. [mic][iso] Added the ability to customize an existing mic-generated iso. May 1, 2024
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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

does it have to be LiveOS iso only? what will happen if a regular iso is used?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[we need to locate bootloaders, kernel, initrd, rootfs, grub.cfg in specific locations and with specific names]

Comment thread toolkit/tools/imagecustomizer/docs/iso.md Outdated

switch config.OS.ResetBootLoaderType {
case imagecustomizerapi.ResetBootLoaderTypeHard:
if config.Storage == nil {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

Comment thread toolkit/tools/pkg/imagecustomizerlib/imagecustomizer.go Outdated
Comment thread toolkit/tools/pkg/imagecustomizerlib/imagecustomizer.go
Comment thread toolkit/tools/pkg/imagecustomizerlib/imagecustomizer.go Outdated
// 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

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

curious - is this based of anything specific or just a buffered estimate?

@gmileka gmileka May 4, 2024

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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...

Comment thread toolkit/tools/pkg/imagecustomizerlib/imagecustomizer.go Outdated
Comment thread toolkit/tools/pkg/imagecustomizerlib/imagecustomizer.go
Comment thread toolkit/tools/pkg/imagecustomizerlib/imagecustomizer.go
Comment thread toolkit/tools/pkg/imagecustomizerlib/imagecustomizer.go Outdated
Comment thread toolkit/tools/pkg/imagecustomizerlib/liveosisobuilder.go Outdated
Comment thread toolkit/tools/pkg/imagecustomizerlib/imagecustomizer.go Outdated
Comment thread toolkit/tools/pkg/imagecustomizerlib/imagecustomizer.go Outdated
err := ic.isoBuilder.createWriteableImageFromSquashfs(ic.buildDir, ic.rawImageFile)
if err != nil {
return fmt.Errorf("failed to create writeable image:\n%w", err)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?

@gmileka gmileka force-pushed the gmileka/iso-customize-iso-2 branch from d711e63 to 74c3a4c Compare May 4, 2024 05:54
Comment thread toolkit/tools/pkg/imagecustomizerlib/imagecustomizer.go Outdated
Comment thread toolkit/tools/pkg/imagecustomizerlib/imagecustomizer.go Outdated

inputIsoArtifacts, err := createIsoBuilderFromIsoImage(ic.buildDir, ic.buildDirAbs, ic.inputImageFile)
if err != nil {
var cleanUpError error

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.
}

Comment thread toolkit/tools/pkg/imagecustomizerlib/imagecustomizer.go Outdated
Comment thread toolkit/tools/pkg/imagecustomizerlib/imagecustomizer.go Outdated
Comment thread toolkit/tools/pkg/imagecustomizerlib/imagecustomizer.go
Comment thread toolkit/tools/pkg/imagecustomizerlib/liveosisobuilder.go Outdated
Comment thread toolkit/tools/pkg/imagecustomizerlib/liveosisobuilder.go Outdated
// 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" {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we also error out if the input is an ISO and the config has a .storage value?

@gmileka gmileka May 6, 2024

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread toolkit/tools/pkg/imagecustomizerlib/imagecustomizer.go Outdated
Comment thread toolkit/tools/pkg/imagecustomizerlib/imagecustomizer.go Outdated
@gmileka gmileka merged commit b847ba5 into 3.0-dev May 7, 2024
@gmileka gmileka deleted the gmileka/iso-customize-iso-2 branch May 7, 2024 00:20
Xiaohong-Deng pushed a commit to Xiaohong-Deng/azurelinux that referenced this pull request Nov 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants