metropolis: use new OS image format for install
This switches the USB and SSH installation methods to the new OS image
format based on OCI artifacts.
When stored on disk, the new format consists of a directory containing
an OCI layout, instead of a single file. This means that all steps which
copy or upload an image now need to handle a tree of files.
Change-Id: I526d32f5c50bd74f513f785118768a56b2655fa0
Reviewed-on: https://review.monogon.dev/c/monogon/+/4090
Reviewed-by: Tim Windelschmidt <tim@monogon.tech>
Tested-by: Jenkins CI
diff --git a/metropolis/cli/metroctl/BUILD.bazel b/metropolis/cli/metroctl/BUILD.bazel
index 8829be4..e1d724b 100644
--- a/metropolis/cli/metroctl/BUILD.bazel
+++ b/metropolis/cli/metroctl/BUILD.bazel
@@ -50,6 +50,7 @@
"//osbase/logtree",
"//osbase/logtree/proto",
"//osbase/net/sshtakeover",
+ "//osbase/oci",
"//osbase/structfs",
"//version",
"@com_github_adrg_xdg//:xdg",
@@ -78,7 +79,7 @@
"//conditions:default": [
"//metropolis/cli/takeover",
"//metropolis/installer:kernel",
- "//metropolis/node:bundle",
+ "//metropolis/node:oci_image",
],
}),
embed = [":metroctl_lib"],
diff --git a/metropolis/cli/metroctl/cmd_install.go b/metropolis/cli/metroctl/cmd_install.go
index 1b9b8cb..3fd4802 100644
--- a/metropolis/cli/metroctl/cmd_install.go
+++ b/metropolis/cli/metroctl/cmd_install.go
@@ -36,7 +36,7 @@
var bootstrap = installCmd.PersistentFlags().Bool("bootstrap", false, "Create a bootstrap installer image.")
var bootstrapTPMMode = flagdefs.TPMModePflag(installCmd.PersistentFlags(), "bootstrap-tpm-mode", cpb.ClusterConfiguration_TPM_MODE_REQUIRED, "TPM mode to set on cluster")
var bootstrapStorageSecurityPolicy = flagdefs.StorageSecurityPolicyPflag(installCmd.PersistentFlags(), "bootstrap-storage-security", cpb.ClusterConfiguration_STORAGE_SECURITY_POLICY_NEEDS_ENCRYPTION_AND_AUTHENTICATION, "Storage security policy to set on cluster")
-var bundlePath = installCmd.PersistentFlags().StringP("bundle", "b", "", "Path to the Metropolis bundle to be installed")
+var imagePath = installCmd.PersistentFlags().StringP("image", "", "", "Path to the OCI layout directory containing the Metropolis OS image to be installed")
var nodeParamPath = installCmd.PersistentFlags().String("node-params", "", "Path to the metropolis.proto.api.NodeParameters prototext file (advanced usage only)")
func makeNodeParams() (*api.NodeParameters, error) {
@@ -109,19 +109,26 @@
return params, nil
}
-func external(name, datafilePath string, flag *string) (structfs.Blob, error) {
+func external(name, datafilePath string, flag *string) (string, error) {
if flag == nil || *flag == "" {
rPath, err := runfiles.Rlocation(datafilePath)
if err != nil {
- return nil, fmt.Errorf("no %s specified", name)
+ return "", fmt.Errorf("no %s specified", name)
}
- return structfs.OSPathBlob(rPath)
+ return rPath, nil
}
- f, err := structfs.OSPathBlob(*flag)
+ return *flag, nil
+}
+
+func externalFile(name, datafilePath string, flag *string) (structfs.Blob, error) {
+ path, err := external(name, datafilePath, flag)
+ if err != nil {
+ return nil, err
+ }
+ f, err := structfs.OSPathBlob(path)
if err != nil {
return nil, fmt.Errorf("failed to open specified %s: %w", name, err)
}
-
return f, nil
}
diff --git a/metropolis/cli/metroctl/cmd_install_ssh.go b/metropolis/cli/metroctl/cmd_install_ssh.go
index b52c353..3dec0d4 100644
--- a/metropolis/cli/metroctl/cmd_install_ssh.go
+++ b/metropolis/cli/metroctl/cmd_install_ssh.go
@@ -24,6 +24,7 @@
"google.golang.org/protobuf/proto"
"source.monogon.dev/osbase/net/sshtakeover"
+ "source.monogon.dev/osbase/oci"
)
// progressbarUpdater wraps a [progressbar.ProgressBar] with an improved
@@ -93,7 +94,7 @@
var sshCmd = &cobra.Command{
Use: "ssh --disk=<disk> <target>",
Short: "Installs Metropolis on a Linux system accessible via SSH.",
- Example: "metroctl install --bundle=metropolis-v0.1.zip --takeover=takeover ssh --disk=nvme0n1 root@ssh-enabled-server.example",
+ Example: "metroctl install --image=metropolis-v0.1 --takeover=takeover ssh --disk=nvme0n1 root@ssh-enabled-server.example",
Args: cobra.ExactArgs(1), // One positional argument: the target
RunE: func(cmd *cobra.Command, args []string) error {
user, address, err := parseSSHAddr(args[0])
@@ -185,22 +186,36 @@
}
const takeoverTargetPath = "/root/takeover"
- const bundleTargetPath = "/root/bundle.zip"
- bundle, err := external("bundle", "_main/metropolis/node/bundle.zip", bundlePath)
+ const imageTargetPath = "/root/osimage"
+
+ imagePathResolved, err := external("image", "_main/metropolis/node/oci_image", imagePath)
if err != nil {
return err
}
+ image, err := oci.ReadLayout(imagePathResolved)
+ if err != nil {
+ return fmt.Errorf("failed to read OS image: %w", err)
+ }
+ imageLayout, err := oci.CreateLayout(image)
+ if err != nil {
+ return fmt.Errorf("failed to read OS image: %w", err)
+ }
takeoverPath, err := cmd.Flags().GetString("takeover")
if err != nil {
return err
}
- takeover, err := external("takeover", "_main/metropolis/cli/takeover/takeover_bin_/takeover_bin", &takeoverPath)
+ takeover, err := externalFile("takeover", "_main/metropolis/cli/takeover/takeover_bin_/takeover_bin", &takeoverPath)
if err != nil {
return err
}
log.Println("Uploading files to target host.")
- totalSize := takeover.Size() + bundle.Size()
+ totalSize := takeover.Size()
+ for _, entry := range imageLayout.Walk() {
+ if entry.Mode.IsRegular() {
+ totalSize += entry.Content.Size()
+ }
+ }
barUpdater := startProgressbarUpdater(progressbar.DefaultBytes(totalSize))
defer barUpdater.stop()
conn.SetProgress(barUpdater.add)
@@ -215,14 +230,9 @@
return fmt.Errorf("error while uploading %q: %w", takeoverTargetPath, err)
}
- bundleContent, err := bundle.Open()
+ err = conn.UploadTree(ctx, imageTargetPath, imageLayout)
if err != nil {
- return err
- }
- err = conn.Upload(ctx, bundleTargetPath, bundleContent)
- bundleContent.Close()
- if err != nil {
- return fmt.Errorf("error while uploading %q: %w", bundleTargetPath, err)
+ return fmt.Errorf("error while uploading OS image: %w", err)
}
barUpdater.stop()
diff --git a/metropolis/cli/metroctl/cmd_install_usb.go b/metropolis/cli/metroctl/cmd_install_usb.go
index 38c1501..4453ed7 100644
--- a/metropolis/cli/metroctl/cmd_install_usb.go
+++ b/metropolis/cli/metroctl/cmd_install_usb.go
@@ -11,12 +11,13 @@
"github.com/spf13/cobra"
"source.monogon.dev/metropolis/cli/metroctl/core"
+ "source.monogon.dev/osbase/oci"
)
var genusbCmd = &cobra.Command{
Use: "genusb target",
Short: "Generates a Metropolis installer disk or image.",
- Example: "metroctl install --bundle=metropolis-v0.1.zip genusb /dev/sdx",
+ Example: "metroctl install --image=metropolis-v0.1 genusb /dev/sdx",
Args: PrintUsageOnWrongArgs(cobra.ExactArgs(1)), // One positional argument: the target
RunE: func(cmd *cobra.Command, args []string) error {
params, err := makeNodeParams()
@@ -29,20 +30,24 @@
return err
}
- installer, err := external("installer", "_main/metropolis/installer/kernel.efi", &installerPath)
+ installer, err := externalFile("installer", "_main/metropolis/installer/kernel.efi", &installerPath)
if err != nil {
return err
}
- bundle, err := external("bundle", "_main/metropolis/node/bundle.zip", bundlePath)
+ imagePathResolved, err := external("image", "_main/metropolis/node/oci_image", imagePath)
if err != nil {
return err
}
+ image, err := oci.ReadLayout(imagePathResolved)
+ if err != nil {
+ return fmt.Errorf("failed to read OS image: %w", err)
+ }
installerImageArgs := core.MakeInstallerImageArgs{
TargetPath: args[0],
Installer: installer,
NodeParams: params,
- Bundle: bundle,
+ Image: image,
}
log.Printf("Generating installer image (this can take a while, see issues/92).")
diff --git a/metropolis/cli/metroctl/core/BUILD.bazel b/metropolis/cli/metroctl/core/BUILD.bazel
index 73527d5..cd95ac1 100644
--- a/metropolis/cli/metroctl/core/BUILD.bazel
+++ b/metropolis/cli/metroctl/core/BUILD.bazel
@@ -21,6 +21,7 @@
"//osbase/blockdev",
"//osbase/fat32",
"//osbase/gpt",
+ "//osbase/oci",
"//osbase/structfs",
"@io_k8s_client_go//pkg/apis/clientauthentication/v1:clientauthentication",
"@io_k8s_client_go//tools/clientcmd",
diff --git a/metropolis/cli/metroctl/core/install.go b/metropolis/cli/metroctl/core/install.go
index 5d43a89..92e8303 100644
--- a/metropolis/cli/metroctl/core/install.go
+++ b/metropolis/cli/metroctl/core/install.go
@@ -15,6 +15,7 @@
"source.monogon.dev/osbase/blockdev"
"source.monogon.dev/osbase/fat32"
"source.monogon.dev/osbase/gpt"
+ "source.monogon.dev/osbase/oci"
"source.monogon.dev/osbase/structfs"
)
@@ -28,13 +29,13 @@
// Optional NodeParameters to be embedded for use by the installer.
NodeParams *api.NodeParameters
- // Optional Reader for a Metropolis bundle for use by the installer.
- Bundle structfs.Blob
+ // Optional OS image for use by the installer.
+ Image *oci.Image
}
// MakeInstallerImage generates an installer disk image containing a Table
// partition table and a single FAT32 partition with an installer and optionally
-// with a bundle and/or Node Parameters.
+// with an OS image and/or Node Parameters.
func MakeInstallerImage(args MakeInstallerImageArgs) error {
if args.Installer == nil {
return errors.New("installer is mandatory")
@@ -58,8 +59,12 @@
return err
}
}
- if args.Bundle != nil {
- if err := espRoot.PlaceFile("metropolis-installer/bundle.bin", args.Bundle); err != nil {
+ if args.Image != nil {
+ imageLayout, err := oci.CreateLayout(args.Image)
+ if err != nil {
+ return err
+ }
+ if err := espRoot.PlaceDir("metropolis-installer/osimage", imageLayout); err != nil {
return err
}
}
diff --git a/metropolis/cli/takeover/BUILD.bazel b/metropolis/cli/takeover/BUILD.bazel
index c262164..c0b16f4 100644
--- a/metropolis/cli/takeover/BUILD.bazel
+++ b/metropolis/cli/takeover/BUILD.bazel
@@ -40,6 +40,8 @@
"//osbase/kexec",
"//osbase/net/dump",
"//osbase/net/proto",
+ "//osbase/oci",
+ "//osbase/oci/osimage",
"//osbase/structfs",
"//osbase/supervisor",
"@com_github_cavaliergopher_cpio//:cpio",
diff --git a/metropolis/cli/takeover/e2e/BUILD.bazel b/metropolis/cli/takeover/e2e/BUILD.bazel
index ae4810b..d951ad8 100644
--- a/metropolis/cli/takeover/e2e/BUILD.bazel
+++ b/metropolis/cli/takeover/e2e/BUILD.bazel
@@ -6,13 +6,13 @@
data = [
"//metropolis/cli/metroctl:metroctl_lite",
"//metropolis/cli/takeover",
- "//metropolis/installer/test/testos:testos_bundle",
+ "//metropolis/installer/test/testos:testos_image",
"//third_party/edk2:OVMF_CODE.fd",
"//third_party/edk2:OVMF_VARS.fd",
"@debian_11_cloudimage//file",
],
x_defs = {
- "xBundleFilePath": "$(rlocationpath //metropolis/installer/test/testos:testos_bundle )",
+ "xImagePath": "$(rlocationpath //metropolis/installer/test/testos:testos_image )",
"xOvmfVarsPath": "$(rlocationpath //third_party/edk2:OVMF_VARS.fd )",
"xOvmfCodePath": "$(rlocationpath //third_party/edk2:OVMF_CODE.fd )",
"xCloudImagePath": "$(rlocationpath @debian_11_cloudimage//file )",
diff --git a/metropolis/cli/takeover/e2e/main_test.go b/metropolis/cli/takeover/e2e/main_test.go
index afce515..d357d8a 100644
--- a/metropolis/cli/takeover/e2e/main_test.go
+++ b/metropolis/cli/takeover/e2e/main_test.go
@@ -32,7 +32,7 @@
// These are filled by bazel at linking time with the canonical path of
// their corresponding file. Inside the init function we resolve it
// with the rules_go runfiles package to the real path.
- xBundleFilePath string
+ xImagePath string
xOvmfVarsPath string
xOvmfCodePath string
xCloudImagePath string
@@ -44,7 +44,7 @@
var err error
for _, path := range []*string{
&xCloudImagePath, &xOvmfVarsPath, &xOvmfCodePath,
- &xTakeoverPath, &xBundleFilePath, &xMetroctlPath,
+ &xTakeoverPath, &xImagePath, &xMetroctlPath,
} {
*path, err = runfiles.Rlocation(*path)
if err != nil {
@@ -203,7 +203,7 @@
"--bootstrap",
"--cluster", "cluster.internal",
"--takeover", xTakeoverPath,
- "--bundle", xBundleFilePath,
+ "--image", xImagePath,
}
installCmd := exec.Command(xMetroctlPath, installArgs...)
installCmd.Env = append(installCmd.Environ(), fmt.Sprintf("SSH_AUTH_SOCK=%s", sshAuthSock))
diff --git a/metropolis/cli/takeover/install.go b/metropolis/cli/takeover/install.go
index 2b76095..5bea9e9 100644
--- a/metropolis/cli/takeover/install.go
+++ b/metropolis/cli/takeover/install.go
@@ -4,7 +4,6 @@
package main
import (
- "archive/zip"
_ "embed"
"fmt"
"os"
@@ -14,30 +13,14 @@
"source.monogon.dev/osbase/blockdev"
"source.monogon.dev/osbase/build/mkimage/osimage"
"source.monogon.dev/osbase/efivarfs"
+ "source.monogon.dev/osbase/oci"
+ ociosimage "source.monogon.dev/osbase/oci/osimage"
"source.monogon.dev/osbase/structfs"
)
//go:embed metropolis/node/core/abloader/abloader.efi
var abloader []byte
-// zipBlob looks up a file in a [zip.Reader] and adapts it to [structfs.Blob].
-func zipBlob(reader *zip.Reader, name string) (zipFileBlob, error) {
- for _, file := range reader.File {
- if file.Name == name {
- return zipFileBlob{file}, nil
- }
- }
- return zipFileBlob{}, fmt.Errorf("file %q not found", name)
-}
-
-type zipFileBlob struct {
- *zip.File
-}
-
-func (f zipFileBlob) Size() int64 {
- return int64(f.File.UncompressedSize64)
-}
-
// EnvInstallTarget environment variable which tells the takeover binary where
// to install to
const EnvInstallTarget = "TAKEOVER_INSTALL_TARGET"
@@ -54,22 +37,12 @@
return err
}
- bundleRaw, err := os.Open("/bundle.zip")
+ image, err := oci.ReadLayout("/osimage")
if err != nil {
- return err
+ return fmt.Errorf("failed to read OS image: %w", err)
}
- bundleStat, err := bundleRaw.Stat()
- if err != nil {
- return err
- }
-
- bundle, err := zip.NewReader(bundleRaw, bundleStat.Size())
- if err != nil {
- return fmt.Errorf("failed to open node bundle: %w", err)
- }
-
- installParams, err := setupOSImageParams(bundle, metropolisSpecRaw, os.Getenv(EnvInstallTarget))
+ installParams, err := setupOSImageParams(image, metropolisSpecRaw, os.Getenv(EnvInstallTarget))
if err != nil {
return err
}
@@ -89,20 +62,24 @@
return nil
}
-func setupOSImageParams(bundle *zip.Reader, metropolisSpecRaw []byte, installTarget string) (*osimage.Params, error) {
+func setupOSImageParams(image *oci.Image, metropolisSpecRaw []byte, installTarget string) (*osimage.Params, error) {
rootDev, err := blockdev.Open(filepath.Join("/dev", installTarget))
if err != nil {
return nil, fmt.Errorf("failed to open root device: %w", err)
}
- efiPayload, err := zipBlob(bundle, "kernel_efi.efi")
+ osImage, err := ociosimage.Read(image)
if err != nil {
- return nil, fmt.Errorf("invalid bundle: %w", err)
+ return nil, fmt.Errorf("failed to read OS image: %w", err)
}
- systemImage, err := zipBlob(bundle, "verity_rootfs.img")
+ efiPayload, err := osImage.Payload("kernel.efi")
if err != nil {
- return nil, fmt.Errorf("invalid bundle: %w", err)
+ return nil, fmt.Errorf("cannot open EFI payload in OS image: %w", err)
+ }
+ systemImage, err := osImage.Payload("system")
+ if err != nil {
+ return nil, fmt.Errorf("cannot open system image in OS image: %w", err)
}
return &osimage.Params{
diff --git a/metropolis/cli/takeover/takeover.go b/metropolis/cli/takeover/takeover.go
index 07c44de..b8ace66 100644
--- a/metropolis/cli/takeover/takeover.go
+++ b/metropolis/cli/takeover/takeover.go
@@ -4,7 +4,6 @@
package main
import (
- "archive/zip"
_ "embed"
"fmt"
"io"
@@ -23,6 +22,7 @@
"source.monogon.dev/osbase/build/mkimage/osimage"
"source.monogon.dev/osbase/kexec"
netdump "source.monogon.dev/osbase/net/dump"
+ "source.monogon.dev/osbase/oci"
"source.monogon.dev/osbase/structfs"
)
@@ -94,19 +94,9 @@
return nil, err
}
- bundleBlob, err := structfs.OSPathBlob(filepath.Join(filepath.Dir(currPath), "bundle.zip"))
+ image, err := oci.ReadLayout(filepath.Join(filepath.Dir(currPath), "osimage"))
if err != nil {
- return nil, err
- }
-
- bundleRaw, err := bundleBlob.Open()
- if err != nil {
- return nil, err
- }
- defer bundleRaw.Close()
- bundle, err := zip.NewReader(bundleRaw.(io.ReaderAt), bundleBlob.Size())
- if err != nil {
- return nil, fmt.Errorf("failed to open node bundle: %w", err)
+ return nil, fmt.Errorf("failed to read OS image: %w", err)
}
// Dump the current network configuration
@@ -140,7 +130,7 @@
return nil, fmt.Errorf("failed marshaling: %w", err)
}
- oParams, err := setupOSImageParams(bundle, nodeParamsRaw, target)
+ oParams, err := setupOSImageParams(image, nodeParamsRaw, target)
if err != nil {
return nil, err
}
@@ -170,15 +160,19 @@
return nil, fmt.Errorf("failed to write initramfs into memory-backed file: %w", err)
}
- // Append this executable, the bundle and node params to initramfs
+ // Append this executable, node params and OS image to initramfs.
self, err := structfs.OSPathBlob("/proc/self/exe")
if err != nil {
return nil, err
}
+ imageLayout, err := oci.CreateLayout(image)
+ if err != nil {
+ return nil, err
+ }
root := structfs.Tree{
structfs.File("init", self, structfs.WithPerm(0o755)),
structfs.File("params.pb", structfs.Bytes(nodeParamsRaw)),
- structfs.File("bundle.zip", bundleBlob),
+ structfs.Dir("osimage", imageLayout),
}
compressedW, err := zstd.NewWriter(initramfsFile, zstd.WithEncoderLevel(1))
if err != nil {
diff --git a/metropolis/installer/BUILD.bazel b/metropolis/installer/BUILD.bazel
index fe80669..27eb5a5 100644
--- a/metropolis/installer/BUILD.bazel
+++ b/metropolis/installer/BUILD.bazel
@@ -16,6 +16,8 @@
"//osbase/bringup",
"//osbase/build/mkimage/osimage",
"//osbase/efivarfs",
+ "//osbase/oci",
+ "//osbase/oci/osimage",
"//osbase/structfs",
"//osbase/supervisor",
"//osbase/sysfs",
diff --git a/metropolis/installer/main.go b/metropolis/installer/main.go
index 216f99c..2ba2142 100644
--- a/metropolis/installer/main.go
+++ b/metropolis/installer/main.go
@@ -2,12 +2,11 @@
// SPDX-License-Identifier: Apache-2.0
// Installer creates a Metropolis image at a suitable block device based on the
-// installer bundle present in the installation medium's ESP, after which it
-// reboots. It's meant to be used as an init process.
+// OS image present in the installation medium's ESP, after which it reboots.
+// It's meant to be used as an init process.
package main
import (
- "archive/zip"
"context"
_ "embed"
"errors"
@@ -23,6 +22,8 @@
"source.monogon.dev/osbase/bringup"
"source.monogon.dev/osbase/build/mkimage/osimage"
"source.monogon.dev/osbase/efivarfs"
+ "source.monogon.dev/osbase/oci"
+ ociosimage "source.monogon.dev/osbase/oci/osimage"
"source.monogon.dev/osbase/structfs"
"source.monogon.dev/osbase/supervisor"
"source.monogon.dev/osbase/sysfs"
@@ -103,24 +104,6 @@
return suitable, nil
}
-// zipBlob looks up a file in a [zip.Reader] and adapts it to [structfs.Blob].
-func zipBlob(reader *zip.Reader, name string) (zipFileBlob, error) {
- for _, file := range reader.File {
- if file.Name == name {
- return zipFileBlob{file}, nil
- }
- }
- return zipFileBlob{}, fmt.Errorf("file %q not found", name)
-}
-
-type zipFileBlob struct {
- *zip.File
-}
-
-func (f zipFileBlob) Size() int64 {
- return int64(f.File.UncompressedSize64)
-}
-
func main() {
bringup.Runnable(installerRunnable).Run()
}
@@ -159,7 +142,7 @@
}
}
espPath := filepath.Join("/dev", espDev)
- // Mount the installer partition. The installer bundle will be read from it.
+ // Mount the installer partition. The OS image will be read from it.
if err := mountInstallerESP(espPath); err != nil {
return fmt.Errorf("while mounting the installer ESP: %w", err)
}
@@ -169,19 +152,22 @@
return fmt.Errorf("failed to open node parameters from ESP: %w", err)
}
- // TODO(lorenz): Replace with proper bundles
- bundle, err := zip.OpenReader("/installer/metropolis-installer/bundle.bin")
+ ociImage, err := oci.ReadLayout("/installer/metropolis-installer/osimage")
if err != nil {
- return fmt.Errorf("failed to open node bundle from ESP: %w", err)
+ return fmt.Errorf("failed to read OS image from ESP: %w", err)
}
- defer bundle.Close()
- efiPayload, err := zipBlob(&bundle.Reader, "kernel_efi.efi")
+ osImage, err := ociosimage.Read(ociImage)
if err != nil {
- return fmt.Errorf("cannot open EFI payload in bundle: %w", err)
+ return fmt.Errorf("failed to read OS image from ESP: %w", err)
}
- systemImage, err := zipBlob(&bundle.Reader, "verity_rootfs.img")
+
+ efiPayload, err := osImage.Payload("kernel.efi")
if err != nil {
- return fmt.Errorf("cannot open system image in bundle: %w", err)
+ return fmt.Errorf("cannot open EFI payload in OS image: %w", err)
+ }
+ systemImage, err := osImage.Payload("system")
+ if err != nil {
+ return fmt.Errorf("cannot open system image in OS image: %w", err)
}
// Build the osimage parameters.
diff --git a/metropolis/installer/test/BUILD.bazel b/metropolis/installer/test/BUILD.bazel
index 7b7828d..903f46e 100644
--- a/metropolis/installer/test/BUILD.bazel
+++ b/metropolis/installer/test/BUILD.bazel
@@ -7,7 +7,7 @@
srcs = ["run_test.go"],
data = [
":kernel",
- "//metropolis/installer/test/testos:testos_bundle",
+ "//metropolis/installer/test/testos:testos_image",
"//third_party/edk2:OVMF_CODE.fd",
"//third_party/edk2:OVMF_VARS.fd",
],
@@ -17,13 +17,14 @@
"xOvmfVarsPath": "$(rlocationpath //third_party/edk2:OVMF_VARS.fd )",
"xOvmfCodePath": "$(rlocationpath //third_party/edk2:OVMF_CODE.fd )",
"xInstallerPath": "$(rlocationpath :kernel )",
- "xBundlePath": "$(rlocationpath //metropolis/installer/test/testos:testos_bundle )",
+ "xImagePath": "$(rlocationpath //metropolis/installer/test/testos:testos_image )",
},
deps = [
"//metropolis/cli/metroctl/core",
"//metropolis/proto/api",
"//osbase/build/mkimage/osimage",
"//osbase/cmd",
+ "//osbase/oci",
"//osbase/structfs",
"@com_github_diskfs_go_diskfs//:go-diskfs",
"@com_github_diskfs_go_diskfs//disk",
diff --git a/metropolis/installer/test/run_test.go b/metropolis/installer/test/run_test.go
index cd87852..925e758 100644
--- a/metropolis/installer/test/run_test.go
+++ b/metropolis/installer/test/run_test.go
@@ -26,6 +26,7 @@
mctl "source.monogon.dev/metropolis/cli/metroctl/core"
"source.monogon.dev/osbase/build/mkimage/osimage"
"source.monogon.dev/osbase/cmd"
+ "source.monogon.dev/osbase/oci"
"source.monogon.dev/osbase/structfs"
)
@@ -36,14 +37,14 @@
xOvmfCodePath string
xOvmfVarsPath string
xInstallerPath string
- xBundlePath string
+ xImagePath string
)
func init() {
var err error
for _, path := range []*string{
&xOvmfCodePath, &xOvmfVarsPath,
- &xInstallerPath, &xBundlePath,
+ &xInstallerPath, &xImagePath,
} {
*path, err = runfiles.Rlocation(*path)
if err != nil {
@@ -139,7 +140,7 @@
log.Fatal(err)
}
- bundle, err := structfs.OSPathBlob(xBundlePath)
+ image, err := oci.ReadLayout(xImagePath)
if err != nil {
log.Fatal(err)
}
@@ -148,7 +149,7 @@
Installer: installer,
TargetPath: installerImage,
NodeParams: &api.NodeParameters{},
- Bundle: bundle,
+ Image: image,
}
if err := mctl.MakeInstallerImage(iargs); err != nil {
log.Fatalf("Couldn't create the installer image at %q: %v", installerImage, err)
diff --git a/metropolis/installer/test/testos/BUILD.bazel b/metropolis/installer/test/testos/BUILD.bazel
index c8f1c3f..e8d8700 100644
--- a/metropolis/installer/test/testos/BUILD.bazel
+++ b/metropolis/installer/test/testos/BUILD.bazel
@@ -1,6 +1,7 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
load("@rules_pkg//:pkg.bzl", "pkg_zip")
load("//osbase/build/mkerofs:def.bzl", "erofs_image")
+load("//osbase/build/mkoci:def.bzl", "oci_os_image")
load("//osbase/build/mkpayload:def.bzl", "efi_unified_kernel_image")
load("//osbase/build/mkverity:def.bzl", "verity_image")
@@ -35,6 +36,15 @@
visibility = ["//visibility:public"],
)
+oci_os_image(
+ name = "testos_image",
+ srcs = {
+ "system": ":verity_rootfs",
+ "kernel.efi": ":kernel_efi",
+ },
+ visibility = ["//visibility:public"],
+)
+
go_library(
name = "testos_lib",
srcs = ["main.go"],
diff --git a/metropolis/node/BUILD.bazel b/metropolis/node/BUILD.bazel
index 04a3049..231456a 100644
--- a/metropolis/node/BUILD.bazel
+++ b/metropolis/node/BUILD.bazel
@@ -4,6 +4,7 @@
load("//osbase/build/genosrelease:defs.bzl", "os_release")
load("//osbase/build/mkerofs:def.bzl", "erofs_image")
load("//osbase/build/mkimage:def.bzl", "node_image")
+load("//osbase/build/mkoci:def.bzl", "oci_os_image")
load("//osbase/build/mkpayload:def.bzl", "efi_unified_kernel_image")
load("//osbase/build/mkverity:def.bzl", "verity_image")
@@ -121,6 +122,15 @@
verity = ":verity_rootfs",
)
+oci_os_image(
+ name = "oci_image",
+ srcs = {
+ "system": ":verity_rootfs",
+ "kernel.efi": ":kernel_efi",
+ },
+ visibility = ["//visibility:public"],
+)
+
# An intermediary "bundle" format until we finalize the actual bundle format. This is NOT stable until migrated
# to the actual bundle format.
# TODO(lorenz): Replace this