1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
|
//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/spf13/cobra"
)
var (
initCmd = &cobra.Command{
Use: "init [options] [NAME]",
Short: "Initialize a virtual machine",
Long: "initialize a virtual machine ",
PersistentPreRunE: rootlessOnly,
RunE: initMachine,
Args: cobra.MaximumNArgs(1),
Example: `podman machine init myvm`,
ValidArgsFunction: completion.AutocompleteNone,
}
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()
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")
UsernameFlagName := "username"
flags.StringVar(&initOpts.Username, UsernameFlagName, cfg.Machine.User, "Username used in qcow image")
_ = initCmd.RegisterFlagCompletionFunc(UsernameFlagName, completion.AutocompleteDefault)
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")
}
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 fmt.Errorf("machine name %q must be %d characters or less", args[0], maxMachineNameSize)
}
initOpts.Name = args[0]
}
if _, err := provider.LoadVMByName(initOpts.Name); err == nil {
return fmt.Errorf("%s: %w", initOpts.Name, machine.ErrVMAlreadyExists)
}
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 {
return start(cmd, args)
}
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
}
|