From 4e7ff84e2b347c74a81cf14f7802e32670645a37 Mon Sep 17 00:00:00 2001 From: Hamza El-Saawy Date: Thu, 2 Jul 2026 16:17:02 -0400 Subject: [PATCH] Add annotation for additional GCS args Add `io.microsoft.virtualmachine.lcow.extra-exec-command-args` annotation to allow specifying extra command line args for the GCS, without needing to plumb through need options and settings for each new flag added to the binary. Signed-off-by: Hamza El-Saawy --- internal/annotations/annotations.go | 3 +++ internal/builder/vm/lcow/kernel_args.go | 19 +++++++++++++------ internal/oci/uvm.go | 9 +++++++++ 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/internal/annotations/annotations.go b/internal/annotations/annotations.go index 1444dc8931..2d1daea08e 100644 --- a/internal/annotations/annotations.go +++ b/internal/annotations/annotations.go @@ -51,6 +51,9 @@ const ( // work to support multiple custom network routes per adapter in LCOW breaks existing // LCOW scenarios. Ideally, this annotation should be removed if no issues are found. NetworkingPolicyBasedRouting = "io.microsoft.virtualmachine.lcow.network.policybasedrouting" + + // ExtraLCOWExecArgs specifies additional args to pass to the command exec'd by the LCOW init. + ExtraLCOWExecArgs = "io.microsoft.virtualmachine.lcow.extra-exec-command-args" ) // WCOW uVM annotations. diff --git a/internal/builder/vm/lcow/kernel_args.go b/internal/builder/vm/lcow/kernel_args.go index 7f055356c9..d5822b73b8 100644 --- a/internal/builder/vm/lcow/kernel_args.go +++ b/internal/builder/vm/lcow/kernel_args.go @@ -27,7 +27,7 @@ func buildKernelArgs( kernelDirect bool, hasConsole bool, rootFsFile string, - LiveMigrationSupportEnabled bool, + liveMigrationSupportEnabled bool, ) (string, error) { log.G(ctx).WithField("rootFsFile", rootFsFile).Debug("buildKernelArgs: starting kernel arguments construction") @@ -82,7 +82,8 @@ func buildKernelArgs( args = append(args, "brd.rd_nr=0", "pmtmr=0") // 8. Init arguments (passed after "--" separator) - initArgs := buildInitArgs(ctx, opts, writableOverlayDirs, disableTimeSyncService, processDumpLocation, rootFsFile, hasConsole, LiveMigrationSupportEnabled) + initArgs := buildInitArgs(ctx, opts, annotations, + writableOverlayDirs, disableTimeSyncService, processDumpLocation, rootFsFile, hasConsole, liveMigrationSupportEnabled) args = append(args, "--", initArgs) result := strings.Join(args, " ") @@ -146,12 +147,13 @@ func buildConsoleArgs(hasConsole bool) []string { func buildInitArgs( ctx context.Context, opts *runhcsoptions.Options, + annotations map[string]string, writableOverlayDirs bool, disableTimeSyncService bool, processDumpLocation string, rootFsFile string, hasConsole bool, - LiveMigrationSupportEnabled bool, + liveMigrationSupportEnabled bool, ) string { log.G(ctx).WithFields(logrus.Fields{ "rootFsFile": rootFsFile, @@ -161,7 +163,7 @@ func buildInitArgs( entropyArgs := fmt.Sprintf("-e %d", vmutils.LinuxEntropyVsockPort) // Build GCS execution command - gcsCmd := buildGCSCommand(opts, disableTimeSyncService, processDumpLocation, LiveMigrationSupportEnabled) + gcsCmd := buildGCSCommand(opts, annotations, disableTimeSyncService, processDumpLocation, liveMigrationSupportEnabled) // Construct init arguments var initArgsList []string @@ -193,9 +195,10 @@ func buildInitArgs( // buildGCSCommand constructs the GCS (Guest Compute Service) command line. func buildGCSCommand( opts *runhcsoptions.Options, + annotations map[string]string, disableTimeSyncService bool, processDumpLocation string, - LiveMigrationSupportEnabled bool, + liveMigrationSupportEnabled bool, ) string { // Determine log level logLevel := "info" @@ -225,6 +228,10 @@ func buildGCSCommand( gcsParts = append(gcsParts, "-core-dump-location", processDumpLocation) } + if s := oci.ParseAnnotationsString(annotations, iannotations.ExtraLCOWExecArgs, ""); s != "" { + gcsParts = append(gcsParts, s) + } + gcsCmd := strings.Join(gcsParts, " ") // Live-migratable pods skip the /bin/vsockexec wrapper. The wrapper exists @@ -233,7 +240,7 @@ func buildGCSCommand( // does not run it for these pods. // Without a listener, vsockexec's outbound connect would block and stall guest init, // so we emit /bin/gcs directly instead. - if LiveMigrationSupportEnabled { + if liveMigrationSupportEnabled { return gcsCmd } diff --git a/internal/oci/uvm.go b/internal/oci/uvm.go index 3acf09ac42..a14b0afebe 100644 --- a/internal/oci/uvm.go +++ b/internal/oci/uvm.go @@ -146,6 +146,14 @@ func parseAnnotationsPreferredRootFSType(ctx context.Context, a map[string]strin return def } +// handleAnnotationBootFilesPath handles parsing annotations.BootFilesRootPath and setting +// implied options from the result. +func handleLCOWAnnotationExtraExecArgs(_ context.Context, a map[string]string, lopts *uvm.OptionsLCOW) { + if s := ParseAnnotationsString(a, iannotations.ExtraLCOWExecArgs, ""); s != "" { + lopts.ExecCommandLine += " " + s + } +} + // handleAnnotationBootFilesPath handles parsing annotations.BootFilesRootPath and setting // implied options from the result. func handleAnnotationBootFilesPath(ctx context.Context, a map[string]string, lopts *uvm.OptionsLCOW) { @@ -388,6 +396,7 @@ func SpecToUVMCreateOpts(ctx context.Context, s *specs.Spec, id, owner string) ( handleAnnotationPreferredRootFSType(ctx, s.Annotations, lopts) handleAnnotationKernelDirectBoot(ctx, s.Annotations, lopts) handleAnnotationFullyPhysicallyBacked(ctx, s.Annotations, lopts) + handleLCOWAnnotationExtraExecArgs(ctx, s.Annotations, lopts) // SecurityPolicy is very sensitive to other settings and will silently change those that are incompatible. // Eg VMPem device count, overridden kernel option cannot be respected.