Skip to content

Commit 92f5d8f

Browse files
elainezhao1liulanze
authored andcommitted
Add osPackages field in metadata for COSI 1.1 (#257)
<!-- Description: Please provide a summary of the changes and the motivation behind them. --> --- This is P1 for COSI 1.1 support (bootloader related will be P2) changes: - updated doc (referenced from trident cosi 1.1 revision doc) - updated metadata to include the new field - updated couple field names (verityConfig, FileSystem) to match the updated cosi 1.1 schema tested locally ![image](https://github.com/user-attachments/assets/4cbfaed1-4d83-475a-a37b-542bf6339491) ### **Checklist** - [ ] Tests added/updated - [x] Documentation updated (if needed) - [x] Code conforms to style guidelines
1 parent 4f709fb commit 92f5d8f

7 files changed

Lines changed: 234 additions & 136 deletions

File tree

docs/imagecustomizer/api/cosi.md

Lines changed: 145 additions & 98 deletions
Large diffs are not rendered by default.

toolkit/tools/pkg/imagecustomizerlib/cosicommon.go

Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,18 @@ import (
1010
"path"
1111
"path/filepath"
1212
"runtime"
13+
"strings"
1314

1415
"github.com/microsoft/azurelinux/toolkit/tools/imagegen/diskutils"
1516
"github.com/microsoft/azurelinux/toolkit/tools/internal/logger"
1617
"github.com/microsoft/azurelinux/toolkit/tools/internal/safeloopback"
18+
"github.com/microsoft/azurelinux/toolkit/tools/internal/shell"
1719
)
1820

1921
type ImageBuildData struct {
2022
Source string
2123
KnownInfo outputPartitionMetadata
22-
Metadata *Image
24+
Metadata *FileSystem
2325
VeritySource string
2426
}
2527

@@ -48,7 +50,7 @@ func convertToCosi(ic *ImageCustomizerParameters) error {
4850
}
4951

5052
err = buildCosiFile(outputDir, ic.outputImageFile, partitionMetadataOutput, ic.verityMetadata,
51-
ic.partUuidToFstabEntry, ic.imageUuidStr, ic.osRelease)
53+
ic.partUuidToFstabEntry, ic.imageUuidStr, ic.osRelease, ic.osPackages)
5254
if err != nil {
5355
return fmt.Errorf("failed to build COSI file:\n%w", err)
5456
}
@@ -65,7 +67,7 @@ func convertToCosi(ic *ImageCustomizerParameters) error {
6567

6668
func buildCosiFile(sourceDir string, outputFile string, partitions []outputPartitionMetadata,
6769
verityMetadata []verityDeviceMetadata, partUuidToFstabEntry map[string]diskutils.FstabEntry,
68-
imageUuidStr string, osRelease string,
70+
imageUuidStr string, osRelease string, osPackages []OsPackage,
6971
) error {
7072
// Pre-compute a map for quick lookup of partition metadata by UUID
7173
partUuidToMetadata := make(map[string]outputPartitionMetadata)
@@ -94,7 +96,7 @@ func buildCosiFile(sourceDir string, outputFile string, partitions []outputParti
9496
continue
9597
}
9698

97-
metadataImage := Image{
99+
metadataImage := FileSystem{
98100
Image: ImageFile{
99101
Path: path.Join("images", partition.PartitionFilename),
100102
UncompressedSize: partition.UncompressedSize,
@@ -119,7 +121,7 @@ func buildCosiFile(sourceDir string, outputFile string, partitions []outputParti
119121
return fmt.Errorf("missing metadata for hash partition UUID:\n%s", verity.hashPartUuid)
120122
}
121123

122-
metadataImage.Verity = &Verity{
124+
metadataImage.Verity = &VerityConfig{
123125
Roothash: verity.rootHash,
124126
Image: ImageFile{
125127
Path: path.Join("images", hashPartition.PartitionFilename),
@@ -147,11 +149,12 @@ func buildCosiFile(sourceDir string, outputFile string, partitions []outputParti
147149
}
148150

149151
metadata := MetadataJson{
150-
Version: "1.0",
151-
OsArch: getArchitectureForCosi(),
152-
Id: imageUuidStr,
153-
Images: make([]Image, len(imageData)),
154-
OsRelease: osRelease,
152+
Version: "1.0",
153+
OsArch: getArchitectureForCosi(),
154+
Id: imageUuidStr,
155+
Images: make([]FileSystem, len(imageData)),
156+
OsRelease: osRelease,
157+
OsPackages: osPackages,
155158
}
156159

157160
// Copy updated metadata
@@ -282,7 +285,7 @@ func populateMetadata(data *ImageBuildData) error {
282285
return nil
283286
}
284287

285-
func populateVerityMetadata(source string, verity *Verity) error {
288+
func populateVerityMetadata(source string, verity *VerityConfig) error {
286289
if source == "" && verity == nil {
287290
return nil
288291
}
@@ -304,3 +307,35 @@ func getArchitectureForCosi() string {
304307
}
305308
return runtime.GOARCH
306309
}
310+
311+
func getAllPackagesFromChroot(imageConnection *ImageConnection) ([]OsPackage, error) {
312+
var out string
313+
err := imageConnection.Chroot().UnsafeRun(func() error {
314+
var err error
315+
out, _, err = shell.Execute(
316+
"rpm", "-qa", "--queryformat", "%{NAME} %{VERSION} %{RELEASE} %{ARCH}\n",
317+
)
318+
return err
319+
})
320+
if err != nil {
321+
return nil, fmt.Errorf("failed to get RPM output from chroot:\n%w", err)
322+
}
323+
324+
lines := strings.Split(strings.TrimSpace(out), "\n")
325+
var packages []OsPackage
326+
for _, line := range lines {
327+
parts := strings.Fields(line)
328+
if len(parts) != 4 {
329+
return nil, fmt.Errorf("malformed RPM line encountered while parsing installed RPMs for COSI: %q", line)
330+
}
331+
packages = append(packages, OsPackage{
332+
Name: parts[0],
333+
Version: parts[1],
334+
Release: parts[2],
335+
Arch: parts[3],
336+
})
337+
}
338+
339+
return packages, nil
340+
341+
}
Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,24 @@
11
package imagecustomizerlib
22

33
type MetadataJson struct {
4-
Version string `json:"version"`
5-
OsArch string `json:"osArch"`
6-
Images []Image `json:"images"`
7-
OsRelease string `json:"osRelease"`
8-
Id string `json:"id"`
4+
Version string `json:"version"`
5+
OsArch string `json:"osArch"`
6+
Images []FileSystem `json:"images"`
7+
OsRelease string `json:"osRelease"`
8+
Id string `json:"id"`
9+
OsPackages []OsPackage `json:"osPackages"`
910
}
1011

11-
type Image struct {
12-
Image ImageFile `json:"image"`
13-
MountPoint string `json:"mountPoint"`
14-
FsType string `json:"fsType"`
15-
FsUuid string `json:"fsUuid"`
16-
PartType string `json:"partType"`
17-
Verity *Verity `json:"verity"`
12+
type FileSystem struct {
13+
Image ImageFile `json:"image"`
14+
MountPoint string `json:"mountPoint"`
15+
FsType string `json:"fsType"`
16+
FsUuid string `json:"fsUuid"`
17+
PartType string `json:"partType"`
18+
Verity *VerityConfig `json:"verity"`
1819
}
1920

20-
type Verity struct {
21+
type VerityConfig struct {
2122
Image ImageFile `json:"image"`
2223
Roothash string `json:"roothash"`
2324
}
@@ -28,3 +29,10 @@ type ImageFile struct {
2829
UncompressedSize uint64 `json:"uncompressedSize"`
2930
Sha384 string `json:"sha384"`
3031
}
32+
33+
type OsPackage struct {
34+
Name string `json:"name"`
35+
Version string `json:"version"`
36+
Release string `json:"release"`
37+
Arch string `json:"arch"`
38+
}

toolkit/tools/pkg/imagecustomizerlib/customizepartitionsfilecopy.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import (
1616
func customizePartitionsUsingFileCopy(buildDir string, baseConfigPath string, config *imagecustomizerapi.Config,
1717
buildImageFile string, newBuildImageFile string,
1818
) (map[string]string, error) {
19-
existingImageConnection, _, _, err := connectToExistingImage(buildImageFile, buildDir, "imageroot", false)
19+
existingImageConnection, _, _, _, err := connectToExistingImage(buildImageFile, buildDir, "imageroot", false)
2020
if err != nil {
2121
return nil, err
2222
}

toolkit/tools/pkg/imagecustomizerlib/imagecustomizer.go

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ type ImageCustomizerParameters struct {
8484

8585
partUuidToFstabEntry map[string]diskutils.FstabEntry
8686
osRelease string
87+
osPackages []OsPackage
8788
}
8889

8990
type verityDeviceMetadata struct {
@@ -464,7 +465,7 @@ func customizeOSContents(ic *ImageCustomizerParameters) error {
464465
}
465466

466467
// Customize the raw image file.
467-
partUuidToFstabEntry, baseImageVerityMetadata, osRelease, err := customizeImageHelper(ic.buildDirAbs, ic.configPath,
468+
partUuidToFstabEntry, baseImageVerityMetadata, osRelease, osPackages, err := customizeImageHelper(ic.buildDirAbs, ic.configPath,
468469
ic.config, ic.rawImageFile, ic.rpmsSources, ic.useBaseImageRpmRepos, partitionsCustomized, ic.imageUuidStr, ic.packageSnapshotTime)
469470
if err != nil {
470471
return err
@@ -482,6 +483,7 @@ func customizeOSContents(ic *ImageCustomizerParameters) error {
482483
ic.partUuidToFstabEntry = partUuidToFstabEntry
483484
ic.baseImageVerityMetadata = baseImageVerityMetadata
484485
ic.osRelease = osRelease
486+
ic.osPackages = osPackages
485487

486488
// For COSI, always shrink the filesystems.
487489
shrinkPartitions := ic.outputImageFormat == imagecustomizerapi.ImageFormatTypeCosi
@@ -854,20 +856,20 @@ func validateOutput(baseConfigPath string, output imagecustomizerapi.Output, out
854856
func customizeImageHelper(buildDir string, baseConfigPath string, config *imagecustomizerapi.Config,
855857
rawImageFile string, rpmsSources []string, useBaseImageRpmRepos bool, partitionsCustomized bool,
856858
imageUuidStr string, packageSnapshotTime string,
857-
) (map[string]diskutils.FstabEntry, []verityDeviceMetadata, string, error) {
859+
) (map[string]diskutils.FstabEntry, []verityDeviceMetadata, string, []OsPackage, error) {
858860
logger.Log.Debugf("Customizing OS")
859861

860-
imageConnection, partUuidToFstabEntry, baseImageVerityMetadata, err := connectToExistingImage(rawImageFile,
862+
imageConnection, partUuidToFstabEntry, baseImageVerityMetadata, osPackages, err := connectToExistingImage(rawImageFile,
861863
buildDir, "imageroot", true)
862864
if err != nil {
863-
return nil, nil, "", err
865+
return nil, nil, "", nil, err
864866
}
865867
defer imageConnection.Close()
866868

867869
// Extract OS release info from rootfs for COSI
868870
osRelease, err := extractOSRelease(imageConnection)
869871
if err != nil {
870-
return nil, nil, "", fmt.Errorf("failed to extract OS release from rootfs partition:\n%w", err)
872+
return nil, nil, "", nil, fmt.Errorf("failed to extract OS release from rootfs partition:\n%w", err)
871873
}
872874

873875
imageConnection.Chroot().UnsafeRun(func() error {
@@ -879,7 +881,7 @@ func customizeImageHelper(buildDir string, baseConfigPath string, config *imagec
879881

880882
err = validateVerityMountPaths(imageConnection, config, partUuidToFstabEntry)
881883
if err != nil {
882-
return nil, nil, "", fmt.Errorf("verity validation failed:\n%w", err)
884+
return nil, nil, "", nil, fmt.Errorf("verity validation failed:\n%w", err)
883885
}
884886

885887
// Do the actual customizations.
@@ -891,15 +893,15 @@ func customizeImageHelper(buildDir string, baseConfigPath string, config *imagec
891893
warnOnLowFreeSpace(buildDir, imageConnection)
892894

893895
if err != nil {
894-
return nil, nil, "", err
896+
return nil, nil, "", nil, err
895897
}
896898

897899
err = imageConnection.CleanClose()
898900
if err != nil {
899-
return nil, nil, "", err
901+
return nil, nil, "", nil, err
900902
}
901903

902-
return partUuidToFstabEntry, baseImageVerityMetadata, osRelease, nil
904+
return partUuidToFstabEntry, baseImageVerityMetadata, osRelease, osPackages, nil
903905
}
904906

905907
func shrinkFilesystemsHelper(buildImageFile string) error {

toolkit/tools/pkg/imagecustomizerlib/imageutils.go

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,22 @@ import (
2121
type installOSFunc func(imageChroot *safechroot.Chroot) error
2222

2323
func connectToExistingImage(imageFilePath string, buildDir string, chrootDirName string, includeDefaultMounts bool,
24-
) (*ImageConnection, map[string]diskutils.FstabEntry, []verityDeviceMetadata, error) {
24+
) (*ImageConnection, map[string]diskutils.FstabEntry, []verityDeviceMetadata, []OsPackage, error) {
2525
imageConnection := NewImageConnection()
2626

2727
partUuidToMountPath, verityMetadata, err := connectToExistingImageHelper(imageConnection, imageFilePath, buildDir,
2828
chrootDirName, includeDefaultMounts)
2929
if err != nil {
3030
imageConnection.Close()
31-
return nil, nil, nil, err
31+
return nil, nil, nil, nil, err
3232
}
33-
return imageConnection, partUuidToMountPath, verityMetadata, nil
33+
34+
packages, err := getAllPackagesFromChroot(imageConnection)
35+
if err != nil {
36+
return nil, nil, nil, nil, err
37+
}
38+
39+
return imageConnection, partUuidToMountPath, verityMetadata, packages, nil
3440
}
3541

3642
func connectToExistingImageHelper(imageConnection *ImageConnection, imageFilePath string,

toolkit/tools/pkg/imagecustomizerlib/liveosisobuilder.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ func createLiveOSFromRawHelper(buildDir, baseConfigPath string, inputArtifactsSt
178178
}()
179179

180180
logger.Log.Debugf("Connecting to raw image (%s)", rawImageFile)
181-
rawImageConnection, _, _, err := connectToExistingImage(rawImageFile, isoBuildDir, "readonly-rootfs-mount", false /*includeDefaultMounts*/)
181+
rawImageConnection, _, _, _, err := connectToExistingImage(rawImageFile, isoBuildDir, "readonly-rootfs-mount", false /*includeDefaultMounts*/)
182182
if err != nil {
183183
return err
184184
}

0 commit comments

Comments
 (0)