diff --git a/cmd/podman/machine/reset.go b/cmd/podman/machine/reset.go index 8c2f01e19a..9b76f97a86 100644 --- a/cmd/podman/machine/reset.go +++ b/cmd/podman/machine/reset.go @@ -7,14 +7,14 @@ import ( "fmt" "os" "strings" + "text/tabwriter" "github.com/containers/common/pkg/completion" "github.com/containers/podman/v5/cmd/podman/registry" "github.com/containers/podman/v5/cmd/podman/validate" "github.com/containers/podman/v5/pkg/machine" - "github.com/containers/podman/v5/pkg/machine/env" + provider2 "github.com/containers/podman/v5/pkg/machine/provider" "github.com/containers/podman/v5/pkg/machine/shim" - "github.com/containers/podman/v5/pkg/machine/vmconfigs" "github.com/spf13/cobra" ) @@ -23,7 +23,6 @@ var ( Use: "reset [options]", Short: "Remove all machines", Long: "Remove all machines, configurations, data, and cached images", - PersistentPreRunE: machinePreRunE, RunE: reset, Args: validate.NoArgs, Example: `podman machine reset`, @@ -51,21 +50,19 @@ func reset(_ *cobra.Command, _ []string) error { err error ) - dirs, err := env.GetMachineDirs(provider.VMType()) - if err != nil { - return err - } - - // TODO we could consider saying we get a list of vms but can proceed - // to just delete all local disk dirs, etc. Maybe a --proceed? - mcs, err := vmconfigs.LoadMachinesInDir(dirs) + providers, err := provider2.GetAll(resetOptions.Force) if err != nil { return err } if !resetOptions.Force { - vms := vmNamesFromMcs(mcs) - resetConfirmationMessage(vms) + listResponse, err := shim.List(providers, machine.ListOptions{}) + if err != nil { + return err + } + + resetConfirmationMessage(listResponse) + reader := bufio.NewReader(os.Stdin) fmt.Print("\nAre you sure you want to continue? [y/N] ") answer, err := reader.ReadString('\n') @@ -76,24 +73,18 @@ func reset(_ *cobra.Command, _ []string) error { return nil } } - - // resetErr can be nil or a multi-error - return shim.Reset(dirs, provider, mcs) + return shim.Reset(providers, resetOptions) } -func resetConfirmationMessage(vms []string) { +func resetConfirmationMessage(listResponse []*machine.ListResponse) { fmt.Println("Warning: this command will delete all existing Podman machines") fmt.Println("and all of the configuration and data directories for Podman machines") fmt.Printf("\nThe following machine(s) will be deleted:\n\n") - for _, msg := range vms { - fmt.Printf("%s\n", msg) - } -} + w := tabwriter.NewWriter(os.Stdout, 0, 0, 3, ' ', 0) + fmt.Fprintln(w, "NAME\tPROVIDER") -func vmNamesFromMcs(mcs map[string]*vmconfigs.MachineConfig) []string { - keys := make([]string, 0, len(mcs)) - for k := range mcs { - keys = append(keys, k) + for _, m := range listResponse { + fmt.Fprintf(w, "%s\t%s\n", m.Name, m.VMType) } - return keys + w.Flush() } diff --git a/pkg/machine/provider/platform.go b/pkg/machine/provider/platform.go index 2eb40072e1..40cf79053a 100644 --- a/pkg/machine/provider/platform.go +++ b/pkg/machine/provider/platform.go @@ -38,6 +38,10 @@ func Get() (vmconfigs.VMProvider, error) { } } +func GetAll(_ bool) ([]vmconfigs.VMProvider, error) { + return []vmconfigs.VMProvider{new(qemu.QEMUStubber)}, nil +} + // SupportedProviders returns the providers that are supported on the host operating system func SupportedProviders() []define.VMType { return []define.VMType{define.QemuVirt} diff --git a/pkg/machine/provider/platform_darwin.go b/pkg/machine/provider/platform_darwin.go index c868957b24..0c76421546 100644 --- a/pkg/machine/provider/platform_darwin.go +++ b/pkg/machine/provider/platform_darwin.go @@ -42,6 +42,13 @@ func Get() (vmconfigs.VMProvider, error) { } } +func GetAll(_ bool) ([]vmconfigs.VMProvider, error) { + return []vmconfigs.VMProvider{ + new(applehv.AppleHVStubber), + new(libkrun.LibKrunStubber), + }, nil +} + // SupportedProviders returns the providers that are supported on the host operating system func SupportedProviders() []define.VMType { supported := []define.VMType{define.AppleHvVirt} diff --git a/pkg/machine/provider/platform_windows.go b/pkg/machine/provider/platform_windows.go index f6a4577b24..772693669d 100644 --- a/pkg/machine/provider/platform_windows.go +++ b/pkg/machine/provider/platform_windows.go @@ -43,6 +43,18 @@ func Get() (vmconfigs.VMProvider, error) { } } +func GetAll(force bool) ([]vmconfigs.VMProvider, error) { + providers := []vmconfigs.VMProvider{ + new(wsl.WSLStubber), + } + if !wsl.HasAdminRights() && !force { + logrus.Warn("managing hyperv machines require admin authority.") + } else { + providers = append(providers, new(hyperv.HyperVStubber)) + } + return providers, nil +} + // SupportedProviders returns the providers that are supported on the host operating system func SupportedProviders() []define.VMType { return []define.VMType{define.HyperVVirt, define.WSLVirt} diff --git a/pkg/machine/shim/host.go b/pkg/machine/shim/host.go index a0d3a4252b..35ae43b991 100644 --- a/pkg/machine/shim/host.go +++ b/pkg/machine/shim/host.go @@ -636,38 +636,61 @@ func confirmationMessage(files []string) { } } -func Reset(dirs *machineDefine.MachineDirs, mp vmconfigs.VMProvider, mcs map[string]*vmconfigs.MachineConfig) error { +func Reset(mps []vmconfigs.VMProvider, opts machine.ResetOptions) error { var resetErrors *multierror.Error - for _, mc := range mcs { - err := Stop(mc, mp, dirs, true) - if err != nil { - resetErrors = multierror.Append(resetErrors, err) - } - _, genericRm, err := mc.Remove(false, false) - if err != nil { - resetErrors = multierror.Append(resetErrors, err) - } - _, providerRm, err := mp.Remove(mc) - if err != nil { - resetErrors = multierror.Append(resetErrors, err) - } + removeDirs := []*machineDefine.MachineDirs{} - if err := genericRm(); err != nil { + for _, p := range mps { + d, err := env.GetMachineDirs(p.VMType()) + if err != nil { resetErrors = multierror.Append(resetErrors, err) + continue } - if err := providerRm(); err != nil { + mcs, err := vmconfigs.LoadMachinesInDir(d) + if err != nil { resetErrors = multierror.Append(resetErrors, err) + continue + } + removeDirs = append(removeDirs, d) + + for _, mc := range mcs { + err := Stop(mc, p, d, true) + if err != nil { + resetErrors = multierror.Append(resetErrors, err) + } + _, genericRm, err := mc.Remove(false, false) + if err != nil { + resetErrors = multierror.Append(resetErrors, err) + } + _, providerRm, err := p.Remove(mc) + if err != nil { + resetErrors = multierror.Append(resetErrors, err) + } + + if err := genericRm(); err != nil { + resetErrors = multierror.Append(resetErrors, err) + } + if err := providerRm(); err != nil { + resetErrors = multierror.Append(resetErrors, err) + } } } // Delete the various directories + // We do this after all the provider rm's, since providers may still share the base machine dir. // Note: we cannot delete the machine run dir blindly like this because // other things live there like the podman.socket and so forth. - - // in linux this ~/.local/share/containers/podman/machine - dataDirErr := utils.GuardedRemoveAll(filepath.Dir(dirs.DataDir.GetPath())) - // in linux this ~/.config/containers/podman/machine - confDirErr := utils.GuardedRemoveAll(filepath.Dir(dirs.ConfigDir.GetPath())) - resetErrors = multierror.Append(resetErrors, confDirErr, dataDirErr) + for _, dir := range removeDirs { + // in linux this ~/.local/share/containers/podman/machine + dataDirErr := utils.GuardedRemoveAll(filepath.Dir(dir.DataDir.GetPath())) + if !errors.Is(dataDirErr, os.ErrNotExist) { + resetErrors = multierror.Append(resetErrors, dataDirErr) + } + // in linux this ~/.config/containers/podman/machine + confDirErr := utils.GuardedRemoveAll(filepath.Dir(dir.ConfigDir.GetPath())) + if !errors.Is(confDirErr, os.ErrNotExist) { + resetErrors = multierror.Append(resetErrors, confDirErr) + } + } return resetErrors.ErrorOrNil() }