diff --git a/cmd/podman/machine/cp.go b/cmd/podman/machine/cp.go index 7d730ad13b1..a1435570276 100644 --- a/cmd/podman/machine/cp.go +++ b/cmd/podman/machine/cp.go @@ -14,7 +14,7 @@ import ( "github.com/containers/podman/v6/pkg/copy" "github.com/containers/podman/v6/pkg/machine" "github.com/containers/podman/v6/pkg/machine/define" - "github.com/containers/podman/v6/pkg/machine/env" + "github.com/containers/podman/v6/pkg/machine/shim" "github.com/containers/podman/v6/pkg/machine/vmconfigs" "github.com/containers/podman/v6/pkg/specgen" "github.com/spf13/cobra" @@ -78,12 +78,16 @@ func cp(_ *cobra.Command, args []string) error { destPath = args[1] } - mc, err := resolveMachine(srcMachine, destMachine) + vmName, err := resolveMachineName(srcMachine, destMachine) + if err != nil { + return err + } + mc, vmProvider, err := shim.VMExists(vmName) if err != nil { return err } - state, err := provider.State(mc, false) + state, err := vmProvider.State(mc, false) if err != nil { return err } @@ -135,25 +139,18 @@ func localhostSSHCopy(opts *cpOptions) error { return cmd.Run() } -func resolveMachine(srcMachine, destMachine string) (*vmconfigs.MachineConfig, error) { +func resolveMachineName(srcMachine, destMachine string) (string, error) { if len(srcMachine) > 0 && len(destMachine) > 0 { - return nil, errors.New("copying between two machines is unsupported") + return "", errors.New("copying between two machines is unsupported") } if len(srcMachine) == 0 && len(destMachine) == 0 { - return nil, errors.New("a machine name must prefix either the source path or destination path") - } - - dirs, err := env.GetMachineDirs(provider.VMType()) - if err != nil { - return nil, err + return "", errors.New("a machine name must prefix either the source path or destination path") } - name := destMachine if len(srcMachine) > 0 { cpOpts.IsSrc = true name = srcMachine } - - return vmconfigs.LoadMachineByName(name, dirs) + return name, nil } diff --git a/cmd/podman/machine/init.go b/cmd/podman/machine/init.go index fd0f9804942..6bf03d9eaf7 100644 --- a/cmd/podman/machine/init.go +++ b/cmd/podman/machine/init.go @@ -12,7 +12,6 @@ import ( "github.com/containers/podman/v6/libpod/events" "github.com/containers/podman/v6/pkg/machine/define" "github.com/containers/podman/v6/pkg/machine/shim" - "github.com/containers/podman/v6/pkg/machine/vmconfigs" "github.com/shirou/gopsutil/v4/mem" "github.com/sirupsen/logrus" "github.com/spf13/cobra" @@ -184,14 +183,20 @@ func initMachine(cmd *cobra.Command, args []string) error { } // Check if machine already exists - _, exists, err := shim.VMExists(initOpts.Name, []vmconfigs.VMProvider{provider}) - if err != nil { + var errNotExists *define.ErrVMDoesNotExist + _, _, err := shim.VMExists(initOpts.Name) + // errors.As checks for nil so safe to use. + if !errors.As(err, &errNotExists) { return err } - // machine exists, return error + // Check if something on the hypervisor exists with the same name + exists, err := shim.VMExistsOnHyperVisor(initOpts.Name) + if err != nil { + return err + } if exists { - return fmt.Errorf("%s: %w", initOpts.Name, define.ErrVMAlreadyExists) + return fmt.Errorf("%s already exists on hypervisor", initOpts.Name) } // check if a system connection already exists diff --git a/cmd/podman/machine/inspect.go b/cmd/podman/machine/inspect.go index 403ec17384a..b83b26ba274 100644 --- a/cmd/podman/machine/inspect.go +++ b/cmd/podman/machine/inspect.go @@ -10,7 +10,7 @@ import ( "github.com/containers/podman/v6/cmd/podman/utils" "github.com/containers/podman/v6/pkg/machine" "github.com/containers/podman/v6/pkg/machine/env" - "github.com/containers/podman/v6/pkg/machine/vmconfigs" + "github.com/containers/podman/v6/pkg/machine/shim" "github.com/spf13/cobra" "go.podman.io/common/pkg/report" ) @@ -48,33 +48,34 @@ func inspect(cmd *cobra.Command, args []string) error { var ( errs utils.OutputErrors ) - dirs, err := env.GetMachineDirs(provider.VMType()) - if err != nil { - return err - } if len(args) < 1 { args = append(args, defaultMachineName) } vms := make([]machine.InspectInfo, 0, len(args)) for _, name := range args { - mc, err := vmconfigs.LoadMachineByName(name, dirs) + mc, vmProvider, err := shim.VMExists(name) if err != nil { errs = append(errs, err) continue } - state, err := provider.State(mc, false) + dirs, err := env.GetMachineDirs(provider.VMType()) + if err != nil { + return err + } + + state, err := vmProvider.State(mc, false) if err != nil { return err } - podmanSocket, podmanPipe, err := mc.ConnectionInfo(provider.VMType()) + podmanSocket, podmanPipe, err := mc.ConnectionInfo(vmProvider.VMType()) if err != nil { return err } - rosetta, err := provider.GetRosetta(mc) + rosetta, err := vmProvider.GetRosetta(mc) if err != nil { return err } @@ -91,7 +92,7 @@ func inspect(cmd *cobra.Command, args []string) error { Resources: mc.Resources, SSHConfig: mc.SSH, State: state, - UserModeNetworking: provider.UserModeNetworkEnabled(mc), + UserModeNetworking: vmProvider.UserModeNetworkEnabled(mc), Rootful: mc.HostUser.Rootful, Rosetta: rosetta, } diff --git a/cmd/podman/machine/list.go b/cmd/podman/machine/list.go index f33bf942fcb..b25ff0530b4 100644 --- a/cmd/podman/machine/list.go +++ b/cmd/podman/machine/list.go @@ -17,7 +17,6 @@ import ( "github.com/containers/podman/v6/pkg/machine" provider2 "github.com/containers/podman/v6/pkg/machine/provider" "github.com/containers/podman/v6/pkg/machine/shim" - "github.com/containers/podman/v6/pkg/machine/vmconfigs" "github.com/docker/go-units" "github.com/spf13/cobra" "go.podman.io/common/pkg/completion" @@ -44,10 +43,9 @@ var ( ) type listFlagType struct { - format string - noHeading bool - quiet bool - allProviders bool + format string + noHeading bool + quiet bool } func init() { @@ -62,7 +60,6 @@ func init() { _ = lsCmd.RegisterFlagCompletionFunc(formatFlagName, common.AutocompleteFormat(&entities.ListReporter{})) flags.BoolVarP(&listFlag.noHeading, "noheading", "n", false, "Do not print headers") flags.BoolVarP(&listFlag.quiet, "quiet", "q", false, "Show only machine names") - flags.BoolVar(&listFlag.allProviders, "all-providers", false, "Show machines from all providers") } func list(cmd *cobra.Command, _ []string) error { @@ -70,17 +67,7 @@ func list(cmd *cobra.Command, _ []string) error { opts machine.ListOptions err error ) - var providers []vmconfigs.VMProvider - if listFlag.allProviders { - providers = provider2.GetAll() - } else { - provider, err = provider2.Get() - if err != nil { - return err - } - providers = []vmconfigs.VMProvider{provider} - } - + providers := provider2.GetAll() listResponse, err := shim.List(providers, opts) if err != nil { return err diff --git a/cmd/podman/machine/machine.go b/cmd/podman/machine/machine.go index 48ed1ede87e..bf96602d70f 100644 --- a/cmd/podman/machine/machine.go +++ b/cmd/podman/machine/machine.go @@ -42,6 +42,7 @@ var ( ) var ( + // TODO This needs to be deleted! provider vmconfigs.VMProvider ) diff --git a/cmd/podman/machine/os/apply.go b/cmd/podman/machine/os/apply.go index 0e23c2b83f3..80111fa3c94 100644 --- a/cmd/podman/machine/os/apply.go +++ b/cmd/podman/machine/os/apply.go @@ -8,7 +8,6 @@ import ( "github.com/containers/podman/v6/cmd/podman/registry" "github.com/containers/podman/v6/cmd/podman/validate" "github.com/containers/podman/v6/pkg/machine/os" - provider2 "github.com/containers/podman/v6/pkg/machine/provider" "github.com/spf13/cobra" ) @@ -49,11 +48,7 @@ func apply(_ *cobra.Command, args []string) error { Restart: restart, } - provider, err := provider2.Get() - if err != nil { - return err - } - osManager, err := NewOSManager(managerOpts, provider) + osManager, err := NewOSManager(managerOpts) if err != nil { return err } diff --git a/cmd/podman/machine/os/manager.go b/cmd/podman/machine/os/manager.go index 9f6ad57fedb..1fa47a94768 100644 --- a/cmd/podman/machine/os/manager.go +++ b/cmd/podman/machine/os/manager.go @@ -9,10 +9,8 @@ import ( "strings" "github.com/containers/podman/v6/pkg/machine/define" - "github.com/containers/podman/v6/pkg/machine/env" pkgOS "github.com/containers/podman/v6/pkg/machine/os" - "github.com/containers/podman/v6/pkg/machine/provider" - "github.com/containers/podman/v6/pkg/machine/vmconfigs" + "github.com/containers/podman/v6/pkg/machine/shim" machineconfig "go.podman.io/common/pkg/machine" ) @@ -23,53 +21,43 @@ type ManagerOpts struct { } // NewOSManager creates a new OSManager depending on the mode of the call -func NewOSManager(opts ManagerOpts, p vmconfigs.VMProvider) (pkgOS.Manager, error) { +func NewOSManager(opts ManagerOpts) (pkgOS.Manager, error) { // If a VM name is specified, then we know that we are not inside a // Podman VM, but rather outside of it. if machineconfig.IsPodmanMachine() && opts.VMName == "" { return guestOSManager() } - return machineOSManager(opts, p) -} - -// guestOSManager returns an OSmanager for inside-VM operations -func guestOSManager() (pkgOS.Manager, error) { - dist := GetDistribution() - switch { - case dist.Name == "fedora" && dist.Variant == "coreos": - return &pkgOS.OSTree{}, nil - default: - return nil, errors.New("unsupported OS") - } -} -// machineOSManager returns an os manager that manages outside the VM. -func machineOSManager(opts ManagerOpts, _ vmconfigs.VMProvider) (pkgOS.Manager, error) { - vmName := opts.VMName + // Set to the default name if no VM was provided if opts.VMName == "" { - vmName = define.DefaultMachineName + opts.VMName = define.DefaultMachineName } - p, err := provider.Get() - if err != nil { - return nil, err - } - dirs, err := env.GetMachineDirs(p.VMType()) - if err != nil { - return nil, err - } - mc, err := vmconfigs.LoadMachineByName(vmName, dirs) + + mc, vmProvider, err := shim.VMExists(opts.VMName) if err != nil { return nil, err } + return &pkgOS.MachineOS{ VM: mc, - Provider: p, + Provider: vmProvider, Args: opts.CLIArgs, - VMName: vmName, + VMName: opts.VMName, Restart: opts.Restart, }, nil } +// guestOSManager returns an OSmanager for inside-VM operations +func guestOSManager() (pkgOS.Manager, error) { + dist := GetDistribution() + switch { + case dist.Name == "fedora" && dist.Variant == "coreos": + return &pkgOS.OSTree{}, nil + default: + return nil, errors.New("unsupported OS") + } +} + type Distribution struct { Name string Variant string diff --git a/cmd/podman/machine/rm.go b/cmd/podman/machine/rm.go index a243da534b4..c6ced6fcf7c 100644 --- a/cmd/podman/machine/rm.go +++ b/cmd/podman/machine/rm.go @@ -6,9 +6,7 @@ import ( "github.com/containers/podman/v6/cmd/podman/registry" "github.com/containers/podman/v6/libpod/events" "github.com/containers/podman/v6/pkg/machine" - "github.com/containers/podman/v6/pkg/machine/env" "github.com/containers/podman/v6/pkg/machine/shim" - "github.com/containers/podman/v6/pkg/machine/vmconfigs" "github.com/spf13/cobra" ) @@ -55,17 +53,12 @@ func rm(_ *cobra.Command, args []string) error { vmName = args[0] } - dirs, err := env.GetMachineDirs(provider.VMType()) + mc, vmProvider, err := shim.VMExists(vmName) if err != nil { return err } - mc, err := vmconfigs.LoadMachineByName(vmName, dirs) - if err != nil { - return err - } - - if err := shim.Remove(mc, provider, dirs, destroyOptions); err != nil { + if err := shim.Remove(mc, vmProvider, destroyOptions); err != nil { return err } newMachineEvent(events.Remove, events.Event{Name: vmName}) diff --git a/cmd/podman/machine/set.go b/cmd/podman/machine/set.go index 8211a343a5e..ecfae810ae8 100644 --- a/cmd/podman/machine/set.go +++ b/cmd/podman/machine/set.go @@ -5,9 +5,7 @@ package machine import ( "github.com/containers/podman/v6/cmd/podman/registry" "github.com/containers/podman/v6/pkg/machine/define" - "github.com/containers/podman/v6/pkg/machine/env" "github.com/containers/podman/v6/pkg/machine/shim" - "github.com/containers/podman/v6/pkg/machine/vmconfigs" "github.com/spf13/cobra" "go.podman.io/common/pkg/completion" "go.podman.io/common/pkg/strongunits" @@ -93,12 +91,7 @@ func setMachine(cmd *cobra.Command, args []string) error { vmName = args[0] } - dirs, err := env.GetMachineDirs(provider.VMType()) - if err != nil { - return err - } - - mc, err := vmconfigs.LoadMachineByName(vmName, dirs) + mc, vmProvider, err := shim.VMExists(vmName) if err != nil { return err } @@ -129,5 +122,5 @@ func setMachine(cmd *cobra.Command, args []string) error { // At this point, we have the known changed information, etc // Walk through changes to the providers if they need them - return shim.Set(mc, provider, setOpts) + return shim.Set(mc, vmProvider, setOpts) } diff --git a/cmd/podman/machine/ssh.go b/cmd/podman/machine/ssh.go index 909d39aa541..66beaeb0722 100644 --- a/cmd/podman/machine/ssh.go +++ b/cmd/podman/machine/ssh.go @@ -3,14 +3,14 @@ package machine import ( + "errors" "fmt" - "github.com/containers/podman/v6/pkg/machine/define" - "github.com/containers/podman/v6/pkg/machine/env" - "github.com/containers/podman/v6/cmd/podman/registry" "github.com/containers/podman/v6/cmd/podman/utils" "github.com/containers/podman/v6/pkg/machine" + "github.com/containers/podman/v6/pkg/machine/define" + "github.com/containers/podman/v6/pkg/machine/shim" "github.com/containers/podman/v6/pkg/machine/vmconfigs" "github.com/spf13/cobra" "go.podman.io/common/pkg/completion" @@ -45,20 +45,14 @@ func init() { _ = sshCmd.RegisterFlagCompletionFunc(usernameFlagName, completion.AutocompleteNone) } -// TODO Remember that this changed upstream and needs to updated as such! - func ssh(_ *cobra.Command, args []string) error { var ( - err error - mc *vmconfigs.MachineConfig - validVM bool + err error + exists bool + mc *vmconfigs.MachineConfig + vmProvider vmconfigs.VMProvider ) - dirs, err := env.GetMachineDirs(provider.VMType()) - if err != nil { - return err - } - // Set the VM to default vmName := defaultMachineName // If len is greater than 0, it means we may have been @@ -68,23 +62,22 @@ func ssh(_ *cobra.Command, args []string) error { // note: previous incantations of this up by a specific name // and errors were ignored. this error is not ignored because // it implies podman cannot read its machine files, which is bad - machines, err := vmconfigs.LoadMachinesInDir(dirs) + mc, vmProvider, err = shim.VMExists(args[0]) if err != nil { return err } - - mc, validVM = machines[args[0]] - if validVM { + if errors.Is(err, &define.ErrVMDoesNotExist{}) { vmName = args[0] } else { sshOpts.Args = append(sshOpts.Args, args[0]) } + exists = true } // If len is greater than 1, it means we might have been // given a vmname and args or just args if len(args) > 1 { - if validVM { + if exists { sshOpts.Args = args[1:] } else { sshOpts.Args = args @@ -93,13 +86,12 @@ func ssh(_ *cobra.Command, args []string) error { // If the machine config was not loaded earlier, we load it now if mc == nil { - mc, err = vmconfigs.LoadMachineByName(vmName, dirs) + mc, vmProvider, err = shim.VMExists(vmName) if err != nil { - return fmt.Errorf("vm %s not found: %w", vmName, err) + return err } } - - state, err := provider.State(mc, false) + state, err := vmProvider.State(mc, false) if err != nil { return err } diff --git a/cmd/podman/machine/start.go b/cmd/podman/machine/start.go index f7c88dc8802..824acbff69b 100644 --- a/cmd/podman/machine/start.go +++ b/cmd/podman/machine/start.go @@ -8,9 +8,7 @@ import ( "github.com/containers/podman/v6/cmd/podman/registry" "github.com/containers/podman/v6/libpod/events" "github.com/containers/podman/v6/pkg/machine" - "github.com/containers/podman/v6/pkg/machine/env" "github.com/containers/podman/v6/pkg/machine/shim" - "github.com/containers/podman/v6/pkg/machine/vmconfigs" "github.com/spf13/cobra" ) @@ -54,11 +52,7 @@ func start(_ *cobra.Command, args []string) error { vmName = args[0] } - dirs, err := env.GetMachineDirs(provider.VMType()) - if err != nil { - return err - } - mc, err := vmconfigs.LoadMachineByName(vmName, dirs) + mc, vmProvider, err := shim.VMExists(vmName) if err != nil { return err } @@ -67,7 +61,7 @@ func start(_ *cobra.Command, args []string) error { fmt.Printf("Starting machine %q\n", vmName) } - if err := shim.Start(mc, provider, dirs, startOpts); err != nil { + if err := shim.Start(mc, vmProvider, startOpts); err != nil { return err } fmt.Printf("Machine %q started successfully\n", vmName) diff --git a/cmd/podman/machine/stop.go b/cmd/podman/machine/stop.go index 87db79df8cf..144f5e9cfec 100644 --- a/cmd/podman/machine/stop.go +++ b/cmd/podman/machine/stop.go @@ -7,9 +7,7 @@ import ( "github.com/containers/podman/v6/cmd/podman/registry" "github.com/containers/podman/v6/libpod/events" - "github.com/containers/podman/v6/pkg/machine/env" "github.com/containers/podman/v6/pkg/machine/shim" - "github.com/containers/podman/v6/pkg/machine/vmconfigs" "github.com/spf13/cobra" ) @@ -44,16 +42,12 @@ func stop(_ *cobra.Command, args []string) error { vmName = args[0] } - dirs, err := env.GetMachineDirs(provider.VMType()) - if err != nil { - return err - } - mc, err := vmconfigs.LoadMachineByName(vmName, dirs) + mc, vmProvider, err := shim.VMExists(vmName) if err != nil { return err } - if err := shim.Stop(mc, provider, dirs, false); err != nil { + if err := shim.Stop(mc, vmProvider, false); err != nil { return err } diff --git a/cmd/podman/system/reset_machine.go b/cmd/podman/system/reset_machine.go index 6d2c313fe17..6eed7fa3378 100644 --- a/cmd/podman/system/reset_machine.go +++ b/cmd/podman/system/reset_machine.go @@ -42,7 +42,7 @@ func resetMachine() error { } if state == define.Running { - if err := shim.Stop(mc, provider, dirs, true); err != nil { + if err := shim.Stop(mc, provider, true); err != nil { logrus.Errorf("unable to stop running machine %s: %q", mc.Name, err) } } diff --git a/docs/source/markdown/podman-machine-list.1.md.in b/docs/source/markdown/podman-machine-list.1.md.in index a850666cd75..e2439270636 100644 --- a/docs/source/markdown/podman-machine-list.1.md.in +++ b/docs/source/markdown/podman-machine-list.1.md.in @@ -26,10 +26,6 @@ environment variable while the machines are running can lead to unexpected behav ## OPTIONS -#### **--all-providers** - -Show machines from all providers - #### **--format**=*format* Change the default output format. This can be of a supported type like 'json' diff --git a/pkg/machine/define/errors.go b/pkg/machine/define/errors.go index e5703591869..f42a92fa8f0 100644 --- a/pkg/machine/define/errors.go +++ b/pkg/machine/define/errors.go @@ -7,12 +7,19 @@ import ( var ( ErrWrongState = errors.New("VM in wrong state to perform action") - ErrVMAlreadyExists = errors.New("VM already exists") ErrNotImplemented = errors.New("functionality not implemented") ErrInitRelaunchAttempt = errors.New("stopping execution: 'init' relaunched with --reexec flag to reinitialize the VM") ErrRebootInitiated = errors.New("system reboot initiated") ) +type ErrVMAlreadyExists struct { + Name string +} + +func (err *ErrVMAlreadyExists) Error() string { + return fmt.Sprintf("machine %q already exists", err.Name) +} + type ErrVMRunningCannotDestroyed struct { Name string } diff --git a/pkg/machine/e2e/list_test.go b/pkg/machine/e2e/list_test.go index 6551c6157e7..c967d9fa4f7 100644 --- a/pkg/machine/e2e/list_test.go +++ b/pkg/machine/e2e/list_test.go @@ -185,7 +185,7 @@ var _ = Describe("podman machine list", func() { Expect(listSession.outputToString()).To(Equal("2GiB 11GiB")) }) It("list machine from all providers", func() { - skipIfVmtype(define.QemuVirt, "linux only has one provider") + Skip("This test will be changed for when --provider is added to init") // create machine on other provider currprovider := os.Getenv("CONTAINERS_MACHINE_PROVIDER") diff --git a/pkg/machine/os/machine_os.go b/pkg/machine/os/machine_os.go index 13a44ebebef..0f7b7177424 100644 --- a/pkg/machine/os/machine_os.go +++ b/pkg/machine/os/machine_os.go @@ -6,7 +6,6 @@ import ( "fmt" "github.com/containers/podman/v6/pkg/machine" - "github.com/containers/podman/v6/pkg/machine/env" "github.com/containers/podman/v6/pkg/machine/shim" "github.com/containers/podman/v6/pkg/machine/vmconfigs" ) @@ -28,16 +27,11 @@ func (m *MachineOS) Apply(image string, _ ApplyOptions) error { return err } - dirs, err := env.GetMachineDirs(m.Provider.VMType()) - if err != nil { - return err - } - if m.Restart { - if err := shim.Stop(m.VM, m.Provider, dirs, false); err != nil { + if err := shim.Stop(m.VM, m.Provider, false); err != nil { return err } - if err := shim.Start(m.VM, m.Provider, dirs, machine.StartOptions{NoInfo: true}); err != nil { + if err := shim.Start(m.VM, m.Provider, machine.StartOptions{NoInfo: true}); err != nil { return err } fmt.Printf("Machine %q restarted successfully\n", m.VMName) diff --git a/pkg/machine/shim/host.go b/pkg/machine/shim/host.go index 089fdb19c19..3d399e52fd2 100644 --- a/pkg/machine/shim/host.go +++ b/pkg/machine/shim/host.go @@ -32,42 +32,35 @@ import ( // List is done at the host level to allow for a *possible* future where // more than one provider is used func List(vmstubbers []vmconfigs.VMProvider, _ machine.ListOptions) ([]*machine.ListResponse, error) { - var lrs []*machine.ListResponse - - for _, s := range vmstubbers { - dirs, err := env.GetMachineDirs(s.VMType()) - if err != nil { - return nil, err - } - mcs, err := vmconfigs.LoadMachinesInDir(dirs) + lrs := make([]*machine.ListResponse, 0) + mcs, err := getMCsOverProviders(vmstubbers) + if err != nil { + return nil, err + } + for name, mc := range mcs { + state, err := mc.Provider.State(mc.MachineConfig, false) if err != nil { return nil, err } - for name, mc := range mcs { - state, err := s.State(mc, false) - if err != nil { - return nil, err - } - lr := machine.ListResponse{ - Name: name, - CreatedAt: mc.Created, - LastUp: mc.LastUp, - Running: state == machineDefine.Running, - Starting: mc.Starting, - VMType: s.VMType().String(), - CPUs: mc.Resources.CPUs, - Memory: mc.Resources.Memory, - Swap: mc.Swap, - DiskSize: mc.Resources.DiskSize, - Port: mc.SSH.Port, - RemoteUsername: mc.SSH.RemoteUsername, - IdentityPath: mc.SSH.IdentityPath, - UserModeNetworking: s.UserModeNetworkEnabled(mc), - } - lrs = append(lrs, &lr) - } + lr := machine.ListResponse{ + Name: name, + CreatedAt: mc.Created, + LastUp: mc.LastUp, + Running: state == machineDefine.Running, + Starting: mc.Starting, + VMType: mc.Provider.VMType().String(), + CPUs: mc.Resources.CPUs, + Memory: mc.Resources.Memory, + Swap: mc.Swap, + DiskSize: mc.Resources.DiskSize, + Port: mc.SSH.Port, + RemoteUsername: mc.SSH.RemoteUsername, + IdentityPath: mc.SSH.IdentityPath, + UserModeNetworking: mc.Provider.UserModeNetworkEnabled(mc.MachineConfig), + } + + lrs = append(lrs, &lr) } - return lrs, nil } @@ -300,27 +293,37 @@ func Init(opts machineDefine.InitOptions, mp vmconfigs.VMProvider) error { return mc.Write() } +type MultiProvider []vmconfigs.VMProvider + // VMExists looks across given providers for a machine's existence. returns the actual config and found bool -func VMExists(name string, vmstubbers []vmconfigs.VMProvider) (*vmconfigs.MachineConfig, bool, error) { +func VMExists(name string) (*vmconfigs.MachineConfig, vmconfigs.VMProvider, error) { // Look on disk first - mcs, err := getMCsOverProviders(vmstubbers) + mcs, err := getMCsOverProviders(provider.GetAll()) if err != nil { - return nil, false, err + return nil, nil, err } if mc, found := mcs[name]; found { - return mc.MachineConfig, true, nil + vmType := mc.Provider + return mc.MachineConfig, vmType, nil } - // Check with the provider hypervisor - for _, vmstubber := range vmstubbers { - exists, err := vmstubber.Exists(name) + + return nil, nil, &machineDefine.ErrVMDoesNotExist{Name: name} +} + +// VMExistsOnHyperVisor actually checks the managing hypervisor (like WSL, HyperV) +// to make sure a VM with the same name does not happen to exist. +func VMExistsOnHyperVisor(name string) (bool, error) { + providers := provider.GetAll() + for _, p := range providers { + exists, err := p.Exists(name) if err != nil { - return nil, false, err + return false, err } if exists { - return nil, true, fmt.Errorf("vm %q already exists on hypervisor", name) + return true, nil } } - return nil, false, nil + return false, nil } // checkExclusiveActiveVM checks if any of the machines are already running @@ -356,8 +359,8 @@ func checkExclusiveActiveVM(currentProvider vmconfigs.VMProvider, mc *vmconfigs. } type knownMachineConfig struct { - Provider vmconfigs.VMProvider - MachineConfig *vmconfigs.MachineConfig + Provider vmconfigs.VMProvider + *vmconfigs.MachineConfig } // getMCsOverProviders loads machineconfigs from a config dir derived from the "provider". it returns only what is known on @@ -373,15 +376,9 @@ func getMCsOverProviders(vmstubbers []vmconfigs.VMProvider) (map[string]knownMac if err != nil { return nil, err } - // TODO When we get to golang-1.20+ we can replace the following with maps.Copy - // maps.Copy(mcs, stubberMCs) - // iterate known mcs and add the stubbers for mcName, mc := range stubberMCs { if _, ok := mcs[mcName]; !ok { - mcs[mcName] = knownMachineConfig{ - Provider: stubber, - MachineConfig: mc, - } + mcs[mcName] = knownMachineConfig{Provider: stubber, MachineConfig: mc} } } } @@ -389,7 +386,11 @@ func getMCsOverProviders(vmstubbers []vmconfigs.VMProvider) (map[string]knownMac } // Stop stops the machine as well as supporting binaries/processes -func Stop(mc *vmconfigs.MachineConfig, mp vmconfigs.VMProvider, dirs *machineDefine.MachineDirs, hardStop bool) error { +func Stop(mc *vmconfigs.MachineConfig, mp vmconfigs.VMProvider, hardStop bool) error { + dirs, err := env.GetMachineDirs(mp.VMType()) + if err != nil { + return err + } // state is checked here instead of earlier because stopping a stopped vm is not considered // an error. so putting in one place instead of sprinkling all over. mc.Lock() @@ -445,11 +446,15 @@ func stopLocked(mc *vmconfigs.MachineConfig, mp vmconfigs.VMProvider, dirs *mach return mc.Write() } -func Start(mc *vmconfigs.MachineConfig, mp vmconfigs.VMProvider, dirs *machineDefine.MachineDirs, opts machine.StartOptions) error { +func Start(mc *vmconfigs.MachineConfig, mp vmconfigs.VMProvider, opts machine.StartOptions) error { defaultBackoff := 500 * time.Millisecond maxBackoffs := 6 signalChanClosed := false + dirs, err := env.GetMachineDirs(mp.VMType()) + if err != nil { + return err + } mc.Lock() defer mc.Unlock() if err := mc.Refresh(); err != nil { @@ -672,7 +677,11 @@ func Set(mc *vmconfigs.MachineConfig, mp vmconfigs.VMProvider, opts machineDefin return mc.Write() } -func Remove(mc *vmconfigs.MachineConfig, mp vmconfigs.VMProvider, dirs *machineDefine.MachineDirs, opts machine.RemoveOptions) error { +func Remove(mc *vmconfigs.MachineConfig, mp vmconfigs.VMProvider, opts machine.RemoveOptions) error { + dirs, err := env.GetMachineDirs(mp.VMType()) + if err != nil { + return err + } mc.Lock() defer mc.Unlock() if err := mc.Refresh(); err != nil { @@ -776,7 +785,7 @@ func Reset(mps []vmconfigs.VMProvider, _ machine.ResetOptions) error { } for _, mc := range mcs { - err := Stop(mc, p, d, true) + err := Stop(mc, p, true) if err != nil { resetErrors = multierror.Append(resetErrors, err) } diff --git a/pkg/machine/vmconfigs/machine.go b/pkg/machine/vmconfigs/machine.go index 41d66c9f2d2..d80291d1c92 100644 --- a/pkg/machine/vmconfigs/machine.go +++ b/pkg/machine/vmconfigs/machine.go @@ -59,7 +59,7 @@ func NewMachineConfig(opts define.InitOptions, dirs *define.MachineDirs, sshIden // Given that we are locked now and check again that the config file does not exists, // if it does it means the VM was already created and we should error. if err := fileutils.Exists(cf.Path); err == nil { - return nil, fmt.Errorf("%s: %w", opts.Name, define.ErrVMAlreadyExists) + return nil, &define.ErrVMAlreadyExists{Name: opts.Name} } if vmtype != define.QemuVirt && len(opts.USBs) > 0 {