summaryrefslogtreecommitdiff
path: root/cmd/podman/machine/create.go
blob: 35f0677adb775e36c84fc6763e12bff6ab574f69 (plain)
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
package machine

import (
	"fmt"
	"strings"

	"github.com/containers/common/pkg/completion"
	"github.com/containers/podman/v3/cmd/podman/registry"
	"github.com/containers/podman/v3/pkg/domain/entities"
	"github.com/pkg/errors"
	"github.com/spf13/cobra"
)

var (
	createCmd = &cobra.Command{
		Use:               "create [options] NAME",
		Short:             "Create a vm",
		Long:              "Create a virtual machine for Podman to run on. Virtual machines are used to run Podman on Macs. ",
		RunE:              create,
		Args:              cobra.ExactArgs(1),
		Example:           `podman machine create myvm`,
		ValidArgsFunction: completion.AutocompleteNone,
	}
)

type CreateCLIOptions struct {
	CPUS       uint64
	Memory     uint64
	KernelPath string
	Devices    []string
}

var (
	createOpts = CreateCLIOptions{}
)

func init() {
	registry.Commands = append(registry.Commands, registry.CliCommand{
		Mode:    []entities.EngineMode{entities.ABIMode, entities.TunnelMode},
		Command: createCmd,
		Parent:  machineCmd,
	})
	flags := createCmd.Flags()

	cpusFlagName := "cpus"
	flags.Uint64Var(
		&createOpts.CPUS,
		cpusFlagName, 0,
		"Number of CPUs. The default is 0.000 which means no limit",
	)
	_ = createCmd.RegisterFlagCompletionFunc(cpusFlagName, completion.AutocompleteNone)

	memoryFlagName := "memory"
	flags.Uint64VarP(
		&createOpts.Memory,
		memoryFlagName, "m", 0,
		"Memory (in MB)",
	)
	_ = createCmd.RegisterFlagCompletionFunc(memoryFlagName, completion.AutocompleteNone)

	kernelPathFlagName := "kernel-path"
	flags.StringVar(
		&createOpts.KernelPath,
		kernelPathFlagName, "",
		"Kernel path",
	)
	_ = createCmd.RegisterFlagCompletionFunc(kernelPathFlagName, completion.AutocompleteNone)

	deviceFlagName := "device"
	flags.StringSliceVar(
		&createOpts.Devices,
		deviceFlagName, []string{},
		"Add a device",
	)
	_ = createCmd.RegisterFlagCompletionFunc(deviceFlagName, completion.AutocompleteDefault)
}

func create(cmd *cobra.Command, args []string) error {
	vmOpts := CreateOptions{
		CPUS:       createOpts.CPUS,
		Memory:     createOpts.Memory,
		KernelPath: createOpts.KernelPath,
	}

	if cmd.Flags().Changed("device") {
		devices, err := cmd.Flags().GetStringSlice("device")
		if err != nil {
			return err
		}
		vmOpts.Devices, err = parseDevices(devices)
		if err != nil {
			return err
		}
	}

	test := new(TestVM)
	test.Create(args[0], vmOpts)

	return nil
}

func parseDevices(devices []string) ([]VMDevices, error) {
	vmDevices := make([]VMDevices, 0, len(devices))

	for _, dev := range devices {
		split := strings.Split(dev, ":")

		if len(split) == 1 {
			vmDevices = append(vmDevices, VMDevices{
				Path:     split[0],
				ReadOnly: false,
			})
		} else if len(split) == 2 {
			var readonly bool

			switch split[1] {
			case "ro", "readonly":
				readonly = true
			default:
				return nil, errors.New(fmt.Sprintf("Invalid readonly value: %s", dev))
			}

			vmDevices = append(vmDevices, VMDevices{
				Path:     split[0],
				ReadOnly: readonly,
			})
		} else {
			return nil, errors.New(fmt.Sprintf("Invalid device format: %s", dev))
		}
	}
	return vmDevices, nil
}