Skip to content

Commit

Permalink
Update uvmboot WCOW, remove globals
Browse files Browse the repository at this point in the history
Update WCOW uvmboot command to work, and make functionality more inline
with LCOW's. Specifically, add the `fwd-std*` and `output-handling` flags,
and share them, along with the `exec` flag definition, between the two.

Add a `no-cmd` flag to skip prepending `cmd /c` to the exec command and
allow passing in a command line exactly.

Fix naming conflicts, where `c` was either a `*cli.Context` or `*cmd.Cmd`,
the former is now consistently `cCtx` (which matches usage elsewhere).
Rename `cmd` variables to prevent overshadowing module import.

Replace global variables with calls to `cCtx.*` flag-access functions to
avoid global (mutatable) state.

Signed-off-by: Hamza El-Saawy <[email protected]>
  • Loading branch information
helsaawy committed Sep 16, 2024
1 parent 3156992 commit 1f05483
Show file tree
Hide file tree
Showing 3 changed files with 286 additions and 190 deletions.
142 changes: 55 additions & 87 deletions internal/tools/uvmboot/lcow.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,9 @@ const (
consolePipeArgName = "console-pipe"
kernelDirectArgName = "kernel-direct"
kernelFileArgName = "kernel-file"
forwardStdoutArgName = "fwd-stdout"
forwardStderrArgName = "fwd-stderr"
outputHandlingArgName = "output-handling"
kernelArgsArgName = "kernel-args"
rootFSTypeArgName = "root-fs-type"
disableTimeSyncArgName = "disable-time-sync"
vpMemMaxCountArgName = "vpmem-max-count"
vpMemMaxSizeArgName = "vpmem-max-size"
scsiMountsArgName = "mount-scsi"
Expand All @@ -37,15 +35,12 @@ const (
securityPolicyEnforcerArgName = "security-policy-enforcer"
)

var (
lcowUseTerminal bool
lcowDisableTimeSync bool
)

var lcowCommand = cli.Command{
Name: "lcow",
Usage: "Boot an LCOW UVM",
Flags: []cli.Flag{
CustomHelpTemplate: cli.CommandHelpTemplate + "EXAMPLES:\n" +
` .\uvmboot.exe -gcs lcow -boot-files-path "C:\ContainerPlat\LinuxBootFiles" -root-fs-type vhd -t -exec "/bin/bash"`,
Flags: append(commonUVMFlags,
cli.StringFlag{
Name: kernelArgsArgName,
Value: "",
Expand Down Expand Up @@ -76,9 +71,8 @@ var lcowCommand = cli.Command{
Usage: "The kernel `file` to use; either 'kernel' or 'vmlinux'. (default: 'kernel')",
},
cli.BoolFlag{
Name: "disable-time-sync",
Usage: "Disable the time synchronization service",
Destination: &lcowDisableTimeSync,
Name: disableTimeSyncArgName,
Usage: "Disable the time synchronization service",
},
cli.StringFlag{
Name: securityPolicyArgName,
Expand All @@ -93,31 +87,10 @@ var lcowCommand = cli.Command{
Name: securityHardwareFlag,
Usage: "Use VMGS file to run on secure hardware. ('root-fs-type' must be set to 'none')",
},
cli.StringFlag{
Name: execCommandLineArgName,
Usage: "Command to execute in the UVM.",
},
cli.BoolFlag{
Name: forwardStdoutArgName,
Usage: "Whether stdout from the process in the UVM should be forwarded",
},
cli.BoolFlag{
Name: forwardStderrArgName,
Usage: "Whether stderr from the process in the UVM should be forwarded",
},
cli.StringFlag{
Name: outputHandlingArgName,
Usage: "Controls how output from UVM is handled. Use 'stdout' to print all output to stdout",
},
cli.StringFlag{
Name: consolePipeArgName,
Usage: "Named pipe for serial console output (which will be enabled)",
},
cli.BoolFlag{
Name: "tty,t",
Usage: "create the process in the UVM with a TTY enabled",
Destination: &lcowUseTerminal,
},
cli.StringSliceFlag{
Name: scsiMountsArgName,
Usage: "List of VHDs to SCSI mount into the UVM. Use repeat instances to add multiple. " +
Expand All @@ -134,58 +107,53 @@ var lcowCommand = cli.Command{
Name: vpmemMountsArgName,
Usage: "List of VHDs to VPMem mount into the UVM. Use repeat instances to add multiple. ",
},
},
Action: func(c *cli.Context) error {
runMany(c, func(id string) error {
),
Action: func(cCtx *cli.Context) error {
runMany(cCtx, func(id string) error {
ctx := context.Background()

options, err := createLCOWOptions(ctx, c, id)
options, err := createLCOWOptions(ctx, cCtx, id)
if err != nil {
return err
}

return runLCOW(ctx, options, c)
return runLCOW(ctx, cCtx, options)
})

return nil
},
}

func init() {
lcowCommand.CustomHelpTemplate = cli.CommandHelpTemplate + "EXAMPLES:\n" +
`.\uvmboot.exe -gcs lcow -boot-files-path "C:\ContainerPlat\LinuxBootFiles" -root-fs-type vhd -t -exec "/bin/bash"`
}

func createLCOWOptions(ctx context.Context, c *cli.Context, id string) (*uvm.OptionsLCOW, error) {
func createLCOWOptions(ctx context.Context, cCtx *cli.Context, id string) (*uvm.OptionsLCOW, error) {
options := uvm.NewDefaultOptionsLCOW(id, "")
setGlobalOptions(c, options.Options)
setGlobalOptions(cCtx, options.Options)

// boot
if c.IsSet(bootFilesPathArgName) {
options.UpdateBootFilesPath(ctx, c.String(bootFilesPathArgName))
if cCtx.IsSet(bootFilesPathArgName) {
options.UpdateBootFilesPath(ctx, cCtx.String(bootFilesPathArgName))
}

// kernel
if c.IsSet(kernelDirectArgName) {
options.KernelDirect = c.Bool(kernelDirectArgName)
if cCtx.IsSet(kernelDirectArgName) {
options.KernelDirect = cCtx.Bool(kernelDirectArgName)
}
if c.IsSet(kernelFileArgName) {
switch strings.ToLower(c.String(kernelFileArgName)) {
if cCtx.IsSet(kernelFileArgName) {
switch strings.ToLower(cCtx.String(kernelFileArgName)) {
case uvm.KernelFile:
options.KernelFile = uvm.KernelFile
case uvm.UncompressedKernelFile:
options.KernelFile = uvm.UncompressedKernelFile
default:
return nil, unrecognizedError(c.String(kernelFileArgName), kernelFileArgName)
return nil, unrecognizedError(cCtx.String(kernelFileArgName), kernelFileArgName)
}
}
if c.IsSet(kernelArgsArgName) {
options.KernelBootOptions = c.String(kernelArgsArgName)
if cCtx.IsSet(kernelArgsArgName) {
options.KernelBootOptions = cCtx.String(kernelArgsArgName)
}

// rootfs
if c.IsSet(rootFSTypeArgName) {
switch strings.ToLower(c.String(rootFSTypeArgName)) {
if cCtx.IsSet(rootFSTypeArgName) {
switch strings.ToLower(cCtx.String(rootFSTypeArgName)) {
case "initrd":
options.RootFSFile = uvm.InitrdFile
options.PreferredRootFSType = uvm.PreferredRootFSTypeInitRd
Expand All @@ -196,59 +164,59 @@ func createLCOWOptions(ctx context.Context, c *cli.Context, id string) (*uvm.Opt
options.RootFSFile = ""
options.PreferredRootFSType = uvm.PreferredRootFSTypeNA
default:
return nil, unrecognizedError(c.String(rootFSTypeArgName), rootFSTypeArgName)
return nil, unrecognizedError(cCtx.String(rootFSTypeArgName), rootFSTypeArgName)
}
}

if c.IsSet(vpMemMaxCountArgName) {
options.VPMemDeviceCount = uint32(c.Uint(vpMemMaxCountArgName))
if cCtx.IsSet(vpMemMaxCountArgName) {
options.VPMemDeviceCount = uint32(cCtx.Uint(vpMemMaxCountArgName))
}
if c.IsSet(vpMemMaxSizeArgName) {
options.VPMemSizeBytes = c.Uint64(vpMemMaxSizeArgName) * memory.MiB // convert from MB to bytes
if cCtx.IsSet(vpMemMaxSizeArgName) {
options.VPMemSizeBytes = cCtx.Uint64(vpMemMaxSizeArgName) * memory.MiB // convert from MB to bytes
}

// GCS
options.UseGuestConnection = useGCS
if !useGCS {
if c.IsSet(execCommandLineArgName) {
options.ExecCommandLine = c.String(execCommandLineArgName)
options.UseGuestConnection = cCtx.GlobalBool(useGCSArgName)
if !options.UseGuestConnection {
if cCtx.IsSet(execCommandLineArgName) {
options.ExecCommandLine = cCtx.String(execCommandLineArgName)
}
if c.IsSet(forwardStdoutArgName) {
options.ForwardStdout = c.Bool(forwardStdoutArgName)
if cCtx.IsSet(forwardStdoutArgName) {
options.ForwardStdout = cCtx.Bool(forwardStdoutArgName)
}
if c.IsSet(forwardStderrArgName) {
options.ForwardStderr = c.Bool(forwardStderrArgName)
if cCtx.IsSet(forwardStderrArgName) {
options.ForwardStderr = cCtx.Bool(forwardStderrArgName)
}
if c.IsSet(outputHandlingArgName) {
switch strings.ToLower(c.String(outputHandlingArgName)) {
if cCtx.IsSet(outputHandlingArgName) {
switch strings.ToLower(cCtx.String(outputHandlingArgName)) {
case "stdout":
options.OutputHandlerCreator = func(*uvm.Options) uvm.OutputHandler {
return func(r io.Reader) {
_, _ = io.Copy(os.Stdout, r)
}
}
default:
return nil, unrecognizedError(c.String(outputHandlingArgName), outputHandlingArgName)
return nil, unrecognizedError(cCtx.String(outputHandlingArgName), outputHandlingArgName)
}
}
}
if c.IsSet(consolePipeArgName) {
options.ConsolePipe = c.String(consolePipeArgName)
if cCtx.IsSet(consolePipeArgName) {
options.ConsolePipe = cCtx.String(consolePipeArgName)
}

// general settings
if lcowDisableTimeSync {
options.DisableTimeSyncService = true
if cCtx.IsSet(disableTimeSyncArgName) {
options.DisableTimeSyncService = cCtx.Bool(disableTimeSyncArgName)
}

// empty policy string defaults to open door
if c.IsSet(securityPolicyArgName) {
options.SecurityPolicy = c.String(securityPolicyArgName)
if cCtx.IsSet(securityPolicyArgName) {
options.SecurityPolicy = cCtx.String(securityPolicyArgName)
}
if c.IsSet(securityPolicyEnforcerArgName) {
options.SecurityPolicyEnforcer = c.String(securityPolicyEnforcerArgName)
if cCtx.IsSet(securityPolicyEnforcerArgName) {
options.SecurityPolicyEnforcer = cCtx.String(securityPolicyEnforcerArgName)
}
if c.IsSet(securityHardwareFlag) {
if cCtx.IsSet(securityHardwareFlag) {
options.GuestStateFile = uvm.GuestStateFile
options.SecurityPolicyEnabled = true
options.AllowOvercommit = false
Expand All @@ -257,7 +225,7 @@ func createLCOWOptions(ctx context.Context, c *cli.Context, id string) (*uvm.Opt
return options, nil
}

func runLCOW(ctx context.Context, options *uvm.OptionsLCOW, c *cli.Context) error {
func runLCOW(ctx context.Context, cCtx *cli.Context, options *uvm.OptionsLCOW) error {
vm, err := uvm.CreateLCOW(ctx, options)
if err != nil {
return err
Expand All @@ -270,20 +238,20 @@ func runLCOW(ctx context.Context, options *uvm.OptionsLCOW, c *cli.Context) erro
return err
}

if err := mountSCSI(ctx, c, vm); err != nil {
if err := mountSCSI(ctx, cCtx, vm); err != nil {
return err
}

if err := shareFiles(ctx, c, vm); err != nil {
if err := shareFiles(ctx, cCtx, vm); err != nil {
return err
}

if err := mountVPMem(ctx, c, vm); err != nil {
if err := mountVPMem(ctx, cCtx, vm); err != nil {
return err
}

if options.UseGuestConnection {
if err := execViaGCS(ctx, vm, c); err != nil {
if err := execViaGCS(ctx, vm, cCtx); err != nil {
return err
}
_ = vm.Terminate(ctx)
Expand All @@ -298,7 +266,7 @@ func runLCOW(ctx context.Context, options *uvm.OptionsLCOW, c *cli.Context) erro
func execViaGCS(ctx context.Context, vm *uvm.UtilityVM, cCtx *cli.Context) error {
c := cmd.CommandContext(ctx, vm, "sh", "-c", cCtx.String(execCommandLineArgName))
c.Log = log.L.Dup()
if lcowUseTerminal {
if cCtx.Bool(useTerminalArgName) {
c.Spec.Terminal = true
c.Stdin = os.Stdin
c.Stdout = os.Stdout
Expand Down
Loading

0 comments on commit 1f05483

Please sign in to comment.