From d3f406e9f6fe3c33228d0f384f986982640d2f43 Mon Sep 17 00:00:00 2001 From: Ashley Cui Date: Wed, 27 Apr 2022 16:56:48 -0400 Subject: podman system reset removed machines incorrectly podman system reset did not clean up machines fully, leaving some config files, and breaking machines. Now it removes all machines files fully. Signed-off-by: Ashley Cui --- cmd/podman/machine/init.go | 2 +- cmd/podman/machine/inspect.go | 2 +- cmd/podman/machine/list.go | 2 +- cmd/podman/machine/machine.go | 2 +- cmd/podman/machine/platform.go | 2 +- cmd/podman/machine/platform_windows.go | 2 +- cmd/podman/machine/rm.go | 2 +- cmd/podman/machine/set.go | 2 +- cmd/podman/machine/ssh.go | 2 +- cmd/podman/machine/start.go | 2 +- cmd/podman/machine/stop.go | 2 +- cmd/podman/system/reset.go | 10 +++- cmd/podman/system/reset_machine.go | 13 +++++ cmd/podman/system/reset_machine_unsupported.go | 8 +++ docs/source/markdown/podman-system-reset.1.md | 3 +- pkg/machine/config.go | 29 ++++++++-- pkg/machine/qemu/machine.go | 76 ++++++++++++++++++++++++++ pkg/machine/wsl/machine.go | 76 ++++++++++++++++++++++++++ test/e2e/system_reset_test.go | 7 +++ 19 files changed, 227 insertions(+), 17 deletions(-) create mode 100644 cmd/podman/system/reset_machine.go create mode 100644 cmd/podman/system/reset_machine_unsupported.go diff --git a/cmd/podman/machine/init.go b/cmd/podman/machine/init.go index 733266b85..6c31f3531 100644 --- a/cmd/podman/machine/init.go +++ b/cmd/podman/machine/init.go @@ -118,7 +118,7 @@ func initMachine(cmd *cobra.Command, args []string) error { vm machine.VM ) - provider := getSystemDefaultProvider() + provider := GetSystemDefaultProvider() initOpts.Name = defaultMachineName if len(args) > 0 { if len(args[0]) > maxMachineNameSize { diff --git a/cmd/podman/machine/inspect.go b/cmd/podman/machine/inspect.go index b8de8e4f4..4600a2b6d 100644 --- a/cmd/podman/machine/inspect.go +++ b/cmd/podman/machine/inspect.go @@ -51,7 +51,7 @@ func inspect(cmd *cobra.Command, args []string) error { args = append(args, defaultMachineName) } vms := make([]machine.InspectInfo, 0, len(args)) - provider := getSystemDefaultProvider() + provider := GetSystemDefaultProvider() for _, vmName := range args { vm, err := provider.LoadVMByName(vmName) if err != nil { diff --git a/cmd/podman/machine/list.go b/cmd/podman/machine/list.go index 861feee07..ef26b7886 100644 --- a/cmd/podman/machine/list.go +++ b/cmd/podman/machine/list.go @@ -84,7 +84,7 @@ func list(cmd *cobra.Command, args []string) error { listFlag.format = "{{.Name}}\n" } - provider := getSystemDefaultProvider() + provider := GetSystemDefaultProvider() listResponse, err = provider.List(opts) if err != nil { return errors.Wrap(err, "error listing vms") diff --git a/cmd/podman/machine/machine.go b/cmd/podman/machine/machine.go index cf7542389..553f1ef7a 100644 --- a/cmd/podman/machine/machine.go +++ b/cmd/podman/machine/machine.go @@ -64,7 +64,7 @@ func autocompleteMachine(cmd *cobra.Command, args []string, toComplete string) ( func getMachines(toComplete string) ([]string, cobra.ShellCompDirective) { suggestions := []string{} - provider := getSystemDefaultProvider() + provider := GetSystemDefaultProvider() machines, err := provider.List(machine.ListOptions{}) if err != nil { cobra.CompErrorln(err.Error()) diff --git a/cmd/podman/machine/platform.go b/cmd/podman/machine/platform.go index 77fec083e..5ba649a48 100644 --- a/cmd/podman/machine/platform.go +++ b/cmd/podman/machine/platform.go @@ -8,6 +8,6 @@ import ( "github.com/containers/podman/v4/pkg/machine/qemu" ) -func getSystemDefaultProvider() machine.Provider { +func GetSystemDefaultProvider() machine.Provider { return qemu.GetQemuProvider() } diff --git a/cmd/podman/machine/platform_windows.go b/cmd/podman/machine/platform_windows.go index 03978eda1..cdbc52459 100644 --- a/cmd/podman/machine/platform_windows.go +++ b/cmd/podman/machine/platform_windows.go @@ -5,6 +5,6 @@ import ( "github.com/containers/podman/v4/pkg/machine/wsl" ) -func getSystemDefaultProvider() machine.Provider { +func GetSystemDefaultProvider() machine.Provider { return wsl.GetWSLProvider() } diff --git a/cmd/podman/machine/rm.go b/cmd/podman/machine/rm.go index e678eb629..a6e66265c 100644 --- a/cmd/podman/machine/rm.go +++ b/cmd/podman/machine/rm.go @@ -61,7 +61,7 @@ func rm(_ *cobra.Command, args []string) error { vmName = args[0] } - provider := getSystemDefaultProvider() + provider := GetSystemDefaultProvider() vm, err = provider.LoadVMByName(vmName) if err != nil { return err diff --git a/cmd/podman/machine/set.go b/cmd/podman/machine/set.go index a994c981b..5777882da 100644 --- a/cmd/podman/machine/set.go +++ b/cmd/podman/machine/set.go @@ -83,7 +83,7 @@ func setMachine(cmd *cobra.Command, args []string) error { if len(args) > 0 && len(args[0]) > 0 { vmName = args[0] } - provider := getSystemDefaultProvider() + 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 e1175d632..4a86da67a 100644 --- a/cmd/podman/machine/ssh.go +++ b/cmd/podman/machine/ssh.go @@ -51,7 +51,7 @@ func ssh(cmd *cobra.Command, args []string) error { // Set the VM to default vmName := defaultMachineName - provider := getSystemDefaultProvider() + 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, diff --git a/cmd/podman/machine/start.go b/cmd/podman/machine/start.go index 2b0c8213d..c9b99e63b 100644 --- a/cmd/podman/machine/start.go +++ b/cmd/podman/machine/start.go @@ -42,7 +42,7 @@ func start(_ *cobra.Command, args []string) error { vmName = args[0] } - provider := getSystemDefaultProvider() + provider := GetSystemDefaultProvider() 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 dcb124dd4..993662792 100644 --- a/cmd/podman/machine/stop.go +++ b/cmd/podman/machine/stop.go @@ -41,7 +41,7 @@ func stop(cmd *cobra.Command, args []string) error { if len(args) > 0 && len(args[0]) > 0 { vmName = args[0] } - provider := getSystemDefaultProvider() + provider := GetSystemDefaultProvider() vm, err = provider.LoadVMByName(vmName) if err != nil { return err diff --git a/cmd/podman/system/reset.go b/cmd/podman/system/reset.go index 8f2e73375..176573bf6 100644 --- a/cmd/podman/system/reset.go +++ b/cmd/podman/system/reset.go @@ -61,7 +61,9 @@ func reset(cmd *cobra.Command, args []string) { - all pods - all images - all networks - - all build cache`) + - all build cache + - all machines`) + if len(listCtn) > 0 { fmt.Println(`WARNING! The following external containers will be purged:`) // print first 12 characters of ID and first configured name alias @@ -103,5 +105,11 @@ func reset(cmd *cobra.Command, args []string) { //nolint:gocritic os.Exit(define.ExecErrorCodeGeneric) } + + // Shutdown podman-machine and delete all machine files + if err := resetMachine(); err != nil { + logrus.Error(err) + } + os.Exit(0) } diff --git a/cmd/podman/system/reset_machine.go b/cmd/podman/system/reset_machine.go new file mode 100644 index 000000000..a07b4fb83 --- /dev/null +++ b/cmd/podman/system/reset_machine.go @@ -0,0 +1,13 @@ +//go:build (amd64 && !remote) || (arm64 && !remote) +// +build amd64,!remote arm64,!remote + +package system + +import ( + cmdMach "github.com/containers/podman/v4/cmd/podman/machine" +) + +func resetMachine() error { + provider := cmdMach.GetSystemDefaultProvider() + return provider.RemoveAndCleanMachines() +} diff --git a/cmd/podman/system/reset_machine_unsupported.go b/cmd/podman/system/reset_machine_unsupported.go new file mode 100644 index 000000000..e063cd089 --- /dev/null +++ b/cmd/podman/system/reset_machine_unsupported.go @@ -0,0 +1,8 @@ +//go:build !amd64 && !arm64 +// +build !amd64,!arm64 + +package system + +func resetMachine() error { + return nil +} diff --git a/docs/source/markdown/podman-system-reset.1.md b/docs/source/markdown/podman-system-reset.1.md index c463481e6..11ce11d07 100644 --- a/docs/source/markdown/podman-system-reset.1.md +++ b/docs/source/markdown/podman-system-reset.1.md @@ -7,7 +7,7 @@ podman\-system\-reset - Reset storage back to initial state **podman system reset** [*options*] ## DESCRIPTION -**podman system reset** removes all pods, containers, images, networks and volumes. +**podman system reset** removes all pods, containers, images, networks and volumes, and machines. This command must be run **before** changing any of the following fields in the `containers.conf` or `storage.conf` files: `driver`, `static_dir`, `tmp_dir` @@ -36,6 +36,7 @@ WARNING! This will remove: - all images - all networks - all build cache + - all machines Are you sure you want to continue? [y/N] y ``` diff --git a/pkg/machine/config.go b/pkg/machine/config.go index 9a0ce757a..d34776714 100644 --- a/pkg/machine/config.go +++ b/pkg/machine/config.go @@ -52,6 +52,7 @@ type Provider interface { List(opts ListOptions) ([]*ListResponse, error) IsValidVMName(name string) (bool, error) CheckExclusiveActiveVM() (bool, string, error) + RemoveAndCleanMachines() error } type RemoteConnectionType string @@ -170,11 +171,11 @@ func (rc RemoteConnectionType) MakeSSHURL(host, path, port, userName string) url // GetDataDir returns the filepath where vm images should // live for podman-machine. func GetDataDir(vmType string) (string, error) { - data, err := homedir.GetDataHome() + dataDirPrefix, err := DataDirPrefix() if err != nil { return "", err } - dataDir := filepath.Join(data, "containers", "podman", "machine", vmType) + dataDir := filepath.Join(dataDirPrefix, vmType) if _, err := os.Stat(dataDir); !os.IsNotExist(err) { return dataDir, nil } @@ -182,14 +183,24 @@ func GetDataDir(vmType string) (string, error) { return dataDir, mkdirErr } +// DataDirPrefix returns the path prefix for all machine data files +func DataDirPrefix() (string, error) { + data, err := homedir.GetDataHome() + if err != nil { + return "", err + } + dataDir := filepath.Join(data, "containers", "podman", "machine") + return dataDir, nil +} + // GetConfigDir returns the filepath to where configuration // files for podman-machine should live func GetConfDir(vmType string) (string, error) { - conf, err := homedir.GetConfigHome() + confDirPrefix, err := ConfDirPrefix() if err != nil { return "", err } - confDir := filepath.Join(conf, "containers", "podman", "machine", vmType) + confDir := filepath.Join(confDirPrefix, vmType) if _, err := os.Stat(confDir); !os.IsNotExist(err) { return confDir, nil } @@ -197,6 +208,16 @@ func GetConfDir(vmType string) (string, error) { return confDir, mkdirErr } +// ConfDirPrefix returns the path prefix for all machine config files +func ConfDirPrefix() (string, error) { + conf, err := homedir.GetConfigHome() + if err != nil { + return "", err + } + confDir := filepath.Join(conf, "containers", "podman", "machine") + return confDir, nil +} + // ResourceConfig describes physical attributes of the machine type ResourceConfig struct { // CPUs to be assigned to the VM diff --git a/pkg/machine/qemu/machine.go b/pkg/machine/qemu/machine.go index fe33e580c..6e36b0886 100644 --- a/pkg/machine/qemu/machine.go +++ b/pkg/machine/qemu/machine.go @@ -1544,3 +1544,79 @@ func (v *MachineVM) editCmdLine(flag string, value string) { v.CmdLine = append(v.CmdLine, []string{flag, value}...) } } + +// RemoveAndCleanMachines removes all machine and cleans up any other files associatied with podman machine +func (p *Provider) RemoveAndCleanMachines() error { + var ( + vm machine.VM + listResponse []*machine.ListResponse + opts machine.ListOptions + destroyOptions machine.RemoveOptions + ) + destroyOptions.Force = true + var prevErr error + + listResponse, err := p.List(opts) + if err != nil { + return err + } + + for _, mach := range listResponse { + vm, err = p.LoadVMByName(mach.Name) + if err != nil { + if prevErr != nil { + logrus.Error(prevErr) + } + prevErr = err + } + _, remove, err := vm.Remove(mach.Name, destroyOptions) + if err != nil { + if prevErr != nil { + logrus.Error(prevErr) + } + prevErr = err + } else { + if err := remove(); err != nil { + if prevErr != nil { + logrus.Error(prevErr) + } + prevErr = err + } + } + } + + // Clean leftover files in data dir + dataDir, err := machine.DataDirPrefix() + if err != nil { + if prevErr != nil { + logrus.Error(prevErr) + } + prevErr = err + } else { + err := os.RemoveAll(dataDir) + if err != nil { + if prevErr != nil { + logrus.Error(prevErr) + } + prevErr = err + } + } + + // Clean leftover files in conf dir + confDir, err := machine.ConfDirPrefix() + if err != nil { + if prevErr != nil { + logrus.Error(prevErr) + } + prevErr = err + } else { + err := os.RemoveAll(confDir) + if err != nil { + if prevErr != nil { + logrus.Error(prevErr) + } + prevErr = err + } + } + return prevErr +} diff --git a/pkg/machine/wsl/machine.go b/pkg/machine/wsl/machine.go index bc2ac7864..57fb36fc9 100644 --- a/pkg/machine/wsl/machine.go +++ b/pkg/machine/wsl/machine.go @@ -1442,3 +1442,79 @@ func (v *MachineVM) getResources() (resources machine.ResourceConfig) { resources.DiskSize = getDiskSize(v) return } + +// RemoveAndCleanMachines removes all machine and cleans up any other files associatied with podman machine +func (p *Provider) RemoveAndCleanMachines() error { + var ( + vm machine.VM + listResponse []*machine.ListResponse + opts machine.ListOptions + destroyOptions machine.RemoveOptions + ) + destroyOptions.Force = true + var prevErr error + + listResponse, err := p.List(opts) + if err != nil { + return err + } + + for _, mach := range listResponse { + vm, err = p.LoadVMByName(mach.Name) + if err != nil { + if prevErr != nil { + logrus.Error(prevErr) + } + prevErr = err + } + _, remove, err := vm.Remove(mach.Name, destroyOptions) + if err != nil { + if prevErr != nil { + logrus.Error(prevErr) + } + prevErr = err + } else { + if err := remove(); err != nil { + if prevErr != nil { + logrus.Error(prevErr) + } + prevErr = err + } + } + } + + // Clean leftover files in data dir + dataDir, err := machine.DataDirPrefix() + if err != nil { + if prevErr != nil { + logrus.Error(prevErr) + } + prevErr = err + } else { + err := os.RemoveAll(dataDir) + if err != nil { + if prevErr != nil { + logrus.Error(prevErr) + } + prevErr = err + } + } + + // Clean leftover files in conf dir + confDir, err := machine.ConfDirPrefix() + if err != nil { + if prevErr != nil { + logrus.Error(prevErr) + } + prevErr = err + } else { + err := os.RemoveAll(confDir) + if err != nil { + if prevErr != nil { + logrus.Error(prevErr) + } + prevErr = err + } + } + return prevErr +} diff --git a/test/e2e/system_reset_test.go b/test/e2e/system_reset_test.go index ec94bb819..28f2e25ca 100644 --- a/test/e2e/system_reset_test.go +++ b/test/e2e/system_reset_test.go @@ -89,5 +89,12 @@ var _ = Describe("podman system reset", func() { Expect(session).Should(Exit(0)) // default network should exists Expect(session.OutputToStringArray()).To(HaveLen(1)) + + // TODO: machine tests currently don't run outside of the machine test pkg + // no machines are created here to cleanup + session = podmanTest.Podman([]string{"machine", "list", "-q"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToStringArray()).To(BeEmpty()) }) }) -- cgit v1.2.3-54-g00ecf