spiegel_podman/cmd/podman/machine/init.go
Ashley Cui d3f406e9f6 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 <acui@redhat.com>
2022-05-04 18:06:23 +00:00

166 lines
5.2 KiB
Go

//go:build amd64 || arm64
// +build amd64 arm64
package machine
import (
"fmt"
"os"
"github.com/containers/common/pkg/completion"
"github.com/containers/podman/v4/cmd/podman/registry"
"github.com/containers/podman/v4/libpod/events"
"github.com/containers/podman/v4/pkg/machine"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)
var (
initCmd = &cobra.Command{
Use: "init [options] [NAME]",
Short: "Initialize a virtual machine",
Long: "initialize a virtual machine ",
RunE: initMachine,
Args: cobra.MaximumNArgs(1),
Example: `podman machine init myvm`,
ValidArgsFunction: completion.AutocompleteNone,
}
)
var (
initOpts = machine.InitOptions{}
defaultMachineName = machine.DefaultMachineName
now bool
)
// maxMachineNameSize is set to thirty to limit huge machine names primarily
// because macos has a much smaller file size limit.
const maxMachineNameSize = 30
func init() {
registry.Commands = append(registry.Commands, registry.CliCommand{
Command: initCmd,
Parent: machineCmd,
})
flags := initCmd.Flags()
cfg := registry.PodmanConfig()
initOpts.Username = cfg.Config.Machine.User
cpusFlagName := "cpus"
flags.Uint64Var(
&initOpts.CPUS,
cpusFlagName, cfg.Machine.CPUs,
"Number of CPUs",
)
_ = initCmd.RegisterFlagCompletionFunc(cpusFlagName, completion.AutocompleteNone)
diskSizeFlagName := "disk-size"
flags.Uint64Var(
&initOpts.DiskSize,
diskSizeFlagName, cfg.Machine.DiskSize,
"Disk size in GB",
)
_ = initCmd.RegisterFlagCompletionFunc(diskSizeFlagName, completion.AutocompleteNone)
memoryFlagName := "memory"
flags.Uint64VarP(
&initOpts.Memory,
memoryFlagName, "m", cfg.Machine.Memory,
"Memory in MB",
)
_ = initCmd.RegisterFlagCompletionFunc(memoryFlagName, completion.AutocompleteNone)
flags.BoolVar(
&now,
"now", false,
"Start machine now",
)
timezoneFlagName := "timezone"
defaultTz := cfg.TZ()
if len(defaultTz) < 1 {
defaultTz = "local"
}
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)
VolumeFlagName := "volume"
flags.StringArrayVarP(&initOpts.Volumes, VolumeFlagName, "v", cfg.Machine.Volumes, "Volumes to mount, source:target")
_ = initCmd.RegisterFlagCompletionFunc(VolumeFlagName, completion.AutocompleteDefault)
VolumeDriverFlagName := "volume-driver"
flags.StringVar(&initOpts.VolumeDriver, VolumeDriverFlagName, "", "Optional volume driver")
_ = initCmd.RegisterFlagCompletionFunc(VolumeDriverFlagName, completion.AutocompleteDefault)
IgnitionPathFlagName := "ignition-path"
flags.StringVar(&initOpts.IgnitionPath, IgnitionPathFlagName, "", "Path to ignition file")
_ = initCmd.RegisterFlagCompletionFunc(IgnitionPathFlagName, completion.AutocompleteDefault)
rootfulFlagName := "rootful"
flags.BoolVar(&initOpts.Rootful, rootfulFlagName, false, "Whether this machine should prefer rootful container execution")
}
// TODO should we allow for a users to append to the qemu cmdline?
func initMachine(cmd *cobra.Command, args []string) error {
var (
err error
vm machine.VM
)
provider := GetSystemDefaultProvider()
initOpts.Name = defaultMachineName
if len(args) > 0 {
if len(args[0]) > maxMachineNameSize {
return errors.New("machine name must be 30 characters or less")
}
initOpts.Name = args[0]
}
if _, err := provider.LoadVMByName(initOpts.Name); err == nil {
return errors.Wrap(machine.ErrVMAlreadyExists, initOpts.Name)
}
for idx, vol := range initOpts.Volumes {
initOpts.Volumes[idx] = os.ExpandEnv(vol)
}
vm, err = provider.NewMachine(initOpts)
if err != nil {
return err
}
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
}
newMachineEvent(events.Init, events.Event{Name: initOpts.Name})
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)
newMachineEvent(events.Start, events.Event{Name: 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
}