From 803defbe509af1902a1fdc2ed7f41b49ebd241f6 Mon Sep 17 00:00:00 2001
From: "Jason T. Greene" <jason@stacksmash.com>
Date: Fri, 12 Nov 2021 00:10:58 -0600
Subject: Introduce Windows WSL implementation of podman machine

[NO NEW TESTS NEEDED] for now

Signed-off-by: Jason Greene <jason.greene@redhat.com>
---
 cmd/podman/machine/init.go                | 48 ++++++++++++++++++++++---------
 cmd/podman/machine/list.go                | 23 +++++++++------
 cmd/podman/machine/machine.go             |  6 ++--
 cmd/podman/machine/machine_unsupported.go |  2 +-
 cmd/podman/machine/platform.go            | 12 ++++++++
 cmd/podman/machine/platform_windows.go    | 10 +++++++
 cmd/podman/machine/rm.go                  | 15 ++++------
 cmd/podman/machine/ssh.go                 | 29 +++++++------------
 cmd/podman/machine/start.go               | 22 +++++++-------
 cmd/podman/machine/stop.go                | 15 ++++------
 10 files changed, 109 insertions(+), 73 deletions(-)
 create mode 100644 cmd/podman/machine/platform.go
 create mode 100644 cmd/podman/machine/platform_windows.go

(limited to 'cmd')

diff --git a/cmd/podman/machine/init.go b/cmd/podman/machine/init.go
index bee6844df..14e87c201 100644
--- a/cmd/podman/machine/init.go
+++ b/cmd/podman/machine/init.go
@@ -1,4 +1,4 @@
-// +build amd64,!windows arm64,!windows
+// +build amd64 arm64
 
 package machine
 
@@ -8,7 +8,6 @@ import (
 	"github.com/containers/common/pkg/completion"
 	"github.com/containers/podman/v3/cmd/podman/registry"
 	"github.com/containers/podman/v3/pkg/machine"
-	"github.com/containers/podman/v3/pkg/machine/qemu"
 	"github.com/pkg/errors"
 	"github.com/spf13/cobra"
 )
@@ -38,6 +37,8 @@ func init() {
 	})
 	flags := initCmd.Flags()
 	cfg := registry.PodmanConfig()
+	initOpts.Username = cfg.Config.Machine.User
+
 	cpusFlagName := "cpus"
 	flags.Uint64Var(
 		&initOpts.CPUS,
@@ -76,6 +77,13 @@ func init() {
 	flags.StringVar(&initOpts.TimeZone, timezoneFlagName, defaultTz, "Set timezone")
 	_ = initCmd.RegisterFlagCompletionFunc(timezoneFlagName, completion.AutocompleteDefault)
 
+	flags.BoolVar(
+		&initOpts.ReExec,
+		"reexec", false,
+		"process was rexeced",
+	)
+	flags.MarkHidden("reexec")
+
 	ImagePathFlagName := "image-path"
 	flags.StringVar(&initOpts.ImagePath, ImagePathFlagName, cfg.Machine.Image, "Path to qcow image")
 	_ = initCmd.RegisterFlagCompletionFunc(ImagePathFlagName, completion.AutocompleteDefault)
@@ -88,33 +96,47 @@ func init() {
 // TODO should we allow for a users to append to the qemu cmdline?
 func initMachine(cmd *cobra.Command, args []string) error {
 	var (
-		vm     machine.VM
-		vmType string
-		err    error
+		vm  machine.VM
+		err error
 	)
+
+	provider := getSystemDefaultProvider()
 	initOpts.Name = defaultMachineName
 	if len(args) > 0 {
 		initOpts.Name = args[0]
 	}
-	switch vmType {
-	default: // qemu is the default
-		if _, err := qemu.LoadVMByName(initOpts.Name); err == nil {
-			return errors.Wrap(machine.ErrVMAlreadyExists, initOpts.Name)
-		}
-		vm, err = qemu.NewMachine(initOpts)
+	if _, err := provider.LoadVMByName(initOpts.Name); err == nil {
+		return errors.Wrap(machine.ErrVMAlreadyExists, initOpts.Name)
 	}
+
+	vm, err = provider.NewMachine(initOpts)
 	if err != nil {
 		return err
 	}
-	err = vm.Init(initOpts)
-	if err != nil {
+
+	if finished, err := vm.Init(initOpts); err != nil || !finished {
+		// Finished = true,  err  = nil  -  Success! Log a message with further instructions
+		// Finished = false, err  = nil  -  The installation is partially complete and podman should
+		//                                  exit gracefully with no error and no success message.
+		//                                  Examples:
+		//                                  - a user has chosen to perform their own reboot
+		//                                  - reexec for limited admin operations, returning to parent
+		// Finished = *,     err != nil  -  Exit with an error message
+
 		return err
 	}
+	fmt.Println("Machine init complete")
 	if now {
 		err = vm.Start(initOpts.Name, machine.StartOptions{})
 		if err == nil {
 			fmt.Printf("Machine %q started successfully\n", initOpts.Name)
 		}
+	} else {
+		extra := ""
+		if initOpts.Name != defaultMachineName {
+			extra = " " + initOpts.Name
+		}
+		fmt.Printf("To start your machine run:\n\n\tpodman machine start%s\n\n", extra)
 	}
 	return err
 }
diff --git a/cmd/podman/machine/list.go b/cmd/podman/machine/list.go
index 774ab4fd0..858d87401 100644
--- a/cmd/podman/machine/list.go
+++ b/cmd/podman/machine/list.go
@@ -1,4 +1,5 @@
-// +build amd64,!windows arm64,!windows
+//go:build amd64 || arm64
+// +build amd64 arm64
 
 package machine
 
@@ -16,7 +17,6 @@ import (
 	"github.com/containers/podman/v3/cmd/podman/registry"
 	"github.com/containers/podman/v3/cmd/podman/validate"
 	"github.com/containers/podman/v3/pkg/machine"
-	"github.com/containers/podman/v3/pkg/machine/qemu"
 	"github.com/docker/go-units"
 	"github.com/pkg/errors"
 	"github.com/spf13/cobra"
@@ -69,9 +69,14 @@ func init() {
 }
 
 func list(cmd *cobra.Command, args []string) error {
-	var opts machine.ListOptions
-	// We only have qemu VM's for now
-	listResponse, err := qemu.List(opts)
+	var (
+		opts         machine.ListOptions
+		listResponse []*machine.ListResponse
+		err          error
+	)
+
+	provider := getSystemDefaultProvider()
+	listResponse, err = provider.List(opts)
 	if err != nil {
 		return errors.Wrap(err, "error listing vms")
 	}
@@ -182,8 +187,8 @@ func toMachineFormat(vms []*machine.ListResponse) ([]*machineReporter, error) {
 		response.Stream = streamName(vm.Stream)
 		response.VMType = vm.VMType
 		response.CPUs = vm.CPUs
-		response.Memory = strUint(vm.Memory * units.MiB)
-		response.DiskSize = strUint(vm.DiskSize * units.GiB)
+		response.Memory = strUint(vm.Memory)
+		response.DiskSize = strUint(vm.DiskSize)
 
 		machineResponses = append(machineResponses, response)
 	}
@@ -214,8 +219,8 @@ func toHumanFormat(vms []*machine.ListResponse) ([]*machineReporter, error) {
 		response.Created = units.HumanDuration(time.Since(vm.CreatedAt)) + " ago"
 		response.VMType = vm.VMType
 		response.CPUs = vm.CPUs
-		response.Memory = units.HumanSize(float64(vm.Memory) * units.MiB)
-		response.DiskSize = units.HumanSize(float64(vm.DiskSize) * units.GiB)
+		response.Memory = units.HumanSize(float64(vm.Memory))
+		response.DiskSize = units.HumanSize(float64(vm.DiskSize))
 
 		humanResponses = append(humanResponses, response)
 	}
diff --git a/cmd/podman/machine/machine.go b/cmd/podman/machine/machine.go
index 8ff9055f0..22ffbbee7 100644
--- a/cmd/podman/machine/machine.go
+++ b/cmd/podman/machine/machine.go
@@ -1,4 +1,4 @@
-// +build amd64,!windows arm64,!windows
+// +build amd64 arm64
 
 package machine
 
@@ -8,7 +8,6 @@ import (
 	"github.com/containers/podman/v3/cmd/podman/registry"
 	"github.com/containers/podman/v3/cmd/podman/validate"
 	"github.com/containers/podman/v3/pkg/machine"
-	"github.com/containers/podman/v3/pkg/machine/qemu"
 	"github.com/spf13/cobra"
 )
 
@@ -51,7 +50,8 @@ func autocompleteMachine(cmd *cobra.Command, args []string, toComplete string) (
 
 func getMachines(toComplete string) ([]string, cobra.ShellCompDirective) {
 	suggestions := []string{}
-	machines, err := qemu.List(machine.ListOptions{})
+	provider := getSystemDefaultProvider()
+	machines, err := provider.List(machine.ListOptions{})
 	if err != nil {
 		cobra.CompErrorln(err.Error())
 		return nil, cobra.ShellCompDirectiveNoFileComp
diff --git a/cmd/podman/machine/machine_unsupported.go b/cmd/podman/machine/machine_unsupported.go
index f8392694a..2f4189446 100644
--- a/cmd/podman/machine/machine_unsupported.go
+++ b/cmd/podman/machine/machine_unsupported.go
@@ -1,4 +1,4 @@
-// +build !amd64 amd64,windows
+// +build !amd64,!arm64
 
 package machine
 
diff --git a/cmd/podman/machine/platform.go b/cmd/podman/machine/platform.go
new file mode 100644
index 000000000..fc3186205
--- /dev/null
+++ b/cmd/podman/machine/platform.go
@@ -0,0 +1,12 @@
+// +build amd64,!windows arm64,!windows
+
+package machine
+
+import (
+	"github.com/containers/podman/v3/pkg/machine"
+	"github.com/containers/podman/v3/pkg/machine/qemu"
+)
+
+func getSystemDefaultProvider() machine.Provider {
+	return qemu.GetQemuProvider()
+}
diff --git a/cmd/podman/machine/platform_windows.go b/cmd/podman/machine/platform_windows.go
new file mode 100644
index 000000000..a4a35e712
--- /dev/null
+++ b/cmd/podman/machine/platform_windows.go
@@ -0,0 +1,10 @@
+package machine
+
+import (
+	"github.com/containers/podman/v3/pkg/machine"
+	"github.com/containers/podman/v3/pkg/machine/wsl"
+)
+
+func getSystemDefaultProvider() machine.Provider {
+	return wsl.GetWSLProvider()
+}
diff --git a/cmd/podman/machine/rm.go b/cmd/podman/machine/rm.go
index c17399c78..c58e74a42 100644
--- a/cmd/podman/machine/rm.go
+++ b/cmd/podman/machine/rm.go
@@ -1,4 +1,4 @@
-// +build amd64,!windows arm64,!windows
+// +build amd64 arm64
 
 package machine
 
@@ -10,7 +10,6 @@ import (
 
 	"github.com/containers/podman/v3/cmd/podman/registry"
 	"github.com/containers/podman/v3/pkg/machine"
-	"github.com/containers/podman/v3/pkg/machine/qemu"
 	"github.com/spf13/cobra"
 )
 
@@ -52,18 +51,16 @@ func init() {
 
 func rm(cmd *cobra.Command, args []string) error {
 	var (
-		err    error
-		vm     machine.VM
-		vmType string
+		err error
+		vm  machine.VM
 	)
 	vmName := defaultMachineName
 	if len(args) > 0 && len(args[0]) > 0 {
 		vmName = args[0]
 	}
-	switch vmType {
-	default:
-		vm, err = qemu.LoadVMByName(vmName)
-	}
+
+	provider := getSystemDefaultProvider()
+	vm, err = provider.LoadVMByName(vmName)
 	if err != nil {
 		return err
 	}
diff --git a/cmd/podman/machine/ssh.go b/cmd/podman/machine/ssh.go
index da0a09338..5ef34afc6 100644
--- a/cmd/podman/machine/ssh.go
+++ b/cmd/podman/machine/ssh.go
@@ -1,4 +1,4 @@
-// +build amd64,!windows arm64,!windows
+// +build amd64 arm64
 
 package machine
 
@@ -9,7 +9,6 @@ import (
 	"github.com/containers/common/pkg/config"
 	"github.com/containers/podman/v3/cmd/podman/registry"
 	"github.com/containers/podman/v3/pkg/machine"
-	"github.com/containers/podman/v3/pkg/machine/qemu"
 	"github.com/pkg/errors"
 	"github.com/spf13/cobra"
 )
@@ -47,27 +46,24 @@ func ssh(cmd *cobra.Command, args []string) error {
 		err     error
 		validVM bool
 		vm      machine.VM
-		vmType  string
 	)
 
 	// Set the VM to default
 	vmName := defaultMachineName
+	provider := getSystemDefaultProvider()
 
 	// If len is greater than 0, it means we may have been
 	// provided the VM name.  If so, we check.  The VM name,
 	// if provided, must be in args[0].
 	if len(args) > 0 {
-		switch vmType {
-		default:
-			validVM, err = qemu.IsValidVMName(args[0])
-			if err != nil {
-				return err
-			}
-			if validVM {
-				vmName = args[0]
-			} else {
-				sshOpts.Args = append(sshOpts.Args, args[0])
-			}
+		validVM, err = provider.IsValidVMName(args[0])
+		if err != nil {
+			return err
+		}
+		if validVM {
+			vmName = args[0]
+		} else {
+			sshOpts.Args = append(sshOpts.Args, args[0])
 		}
 	}
 
@@ -88,10 +84,7 @@ func ssh(cmd *cobra.Command, args []string) error {
 		}
 	}
 
-	switch vmType {
-	default:
-		vm, err = qemu.LoadVMByName(vmName)
-	}
+	vm, err = provider.LoadVMByName(vmName)
 	if err != nil {
 		return errors.Wrapf(err, "vm %s not found", vmName)
 	}
diff --git a/cmd/podman/machine/start.go b/cmd/podman/machine/start.go
index 4ae31e6de..9c9c24f64 100644
--- a/cmd/podman/machine/start.go
+++ b/cmd/podman/machine/start.go
@@ -1,4 +1,4 @@
-// +build amd64,!windows arm64,!windows
+// +build amd64 arm64
 
 package machine
 
@@ -7,7 +7,6 @@ import (
 
 	"github.com/containers/podman/v3/cmd/podman/registry"
 	"github.com/containers/podman/v3/pkg/machine"
-	"github.com/containers/podman/v3/pkg/machine/qemu"
 	"github.com/pkg/errors"
 	"github.com/spf13/cobra"
 )
@@ -33,30 +32,31 @@ func init() {
 
 func start(cmd *cobra.Command, args []string) error {
 	var (
-		err    error
-		vm     machine.VM
-		vmType string
+		err error
+		vm  machine.VM
 	)
 	vmName := defaultMachineName
 	if len(args) > 0 && len(args[0]) > 0 {
 		vmName = args[0]
 	}
 
-	// We only have qemu VM's for now
-	active, activeName, err := qemu.CheckActiveVM()
+	provider := getSystemDefaultProvider()
+	vm, err = provider.LoadVMByName(vmName)
 	if err != nil {
 		return err
 	}
+
+	active, activeName, cerr := provider.CheckExclusiveActiveVM()
+	if cerr != nil {
+		return cerr
+	}
 	if active {
 		if vmName == activeName {
 			return errors.Wrapf(machine.ErrVMAlreadyRunning, "cannot start VM %s", vmName)
 		}
 		return errors.Wrapf(machine.ErrMultipleActiveVM, "cannot start VM %s. VM %s is currently running", vmName, activeName)
 	}
-	switch vmType {
-	default:
-		vm, err = qemu.LoadVMByName(vmName)
-	}
+	vm, err = provider.LoadVMByName(vmName)
 	if err != nil {
 		return err
 	}
diff --git a/cmd/podman/machine/stop.go b/cmd/podman/machine/stop.go
index 75666f734..17969298b 100644
--- a/cmd/podman/machine/stop.go
+++ b/cmd/podman/machine/stop.go
@@ -1,4 +1,5 @@
-// +build amd64,!windows arm64,!windows
+//go:build amd64 || arm64
+// +build amd64 arm64
 
 package machine
 
@@ -7,7 +8,6 @@ import (
 
 	"github.com/containers/podman/v3/cmd/podman/registry"
 	"github.com/containers/podman/v3/pkg/machine"
-	"github.com/containers/podman/v3/pkg/machine/qemu"
 	"github.com/spf13/cobra"
 )
 
@@ -33,18 +33,15 @@ func init() {
 // TODO  Name shouldn't be required, need to create a default vm
 func stop(cmd *cobra.Command, args []string) error {
 	var (
-		err    error
-		vm     machine.VM
-		vmType string
+		err error
+		vm  machine.VM
 	)
 	vmName := defaultMachineName
 	if len(args) > 0 && len(args[0]) > 0 {
 		vmName = args[0]
 	}
-	switch vmType {
-	default:
-		vm, err = qemu.LoadVMByName(vmName)
-	}
+	provider := getSystemDefaultProvider()
+	vm, err = provider.LoadVMByName(vmName)
 	if err != nil {
 		return err
 	}
-- 
cgit v1.2.3-54-g00ecf