13
type VirtualMachine struct {
14
Vcpus uint `json:"vcpus"`
15
MemoryBytes uint64 `json:"memoryBytes"`
16
Bootloader Bootloader `json:"bootloader"`
17
Devices []VirtioDevice `json:"devices,omitempty"`
18
Timesync *TimeSync `json:"timesync,omitempty"`
29
type VMComponent interface {
30
FromOptions([]option) error
31
ToCmdLine() ([]string, error)
37
func NewVirtualMachine(vcpus uint, memoryBytes uint64, bootloader Bootloader) *VirtualMachine {
38
return &VirtualMachine{
40
MemoryBytes: memoryBytes,
41
Bootloader: bootloader,
49
func (vm *VirtualMachine) ToCmdLine() ([]string, error) {
54
args = append(args, "--cpus", strconv.FormatUint(uint64(vm.Vcpus), 10))
56
if vm.MemoryBytes != 0 {
57
args = append(args, "--memory", strconv.FormatUint(vm.MemoryBytes, 10))
60
if vm.Bootloader == nil {
61
return nil, fmt.Errorf("missing bootloader configuration")
63
bootloaderArgs, err := vm.Bootloader.ToCmdLine()
67
args = append(args, bootloaderArgs...)
69
for _, dev := range vm.Devices {
70
devArgs, err := dev.ToCmdLine()
74
args = append(args, devArgs...)
80
func (vm *VirtualMachine) extraFiles() []*os.File {
81
extraFiles := []*os.File{}
82
for _, dev := range vm.Devices {
83
virtioNet, ok := dev.(*VirtioNet)
87
if virtioNet.Socket != nil {
88
extraFiles = append(extraFiles, virtioNet.Socket)
98
func (vm *VirtualMachine) Cmd(vfkitPath string) (*exec.Cmd, error) {
99
args, err := vm.ToCmdLine()
104
cmd := exec.Command(vfkitPath, args...)
105
cmd.ExtraFiles = vm.extraFiles()
110
func (vm *VirtualMachine) AddDevicesFromCmdLine(cmdlineOpts []string) error {
111
for _, deviceOpts := range cmdlineOpts {
112
dev, err := deviceFromCmdLine(deviceOpts)
116
vm.Devices = append(vm.Devices, dev)
121
func (vm *VirtualMachine) VirtioGPUDevices() []*VirtioGPU {
122
gpuDevs := []*VirtioGPU{}
123
for _, dev := range vm.Devices {
124
if gpuDev, isVirtioGPU := dev.(*VirtioGPU); isVirtioGPU {
125
gpuDevs = append(gpuDevs, gpuDev)
132
func (vm *VirtualMachine) VirtioVsockDevices() []*VirtioVsock {
133
vsockDevs := []*VirtioVsock{}
134
for _, dev := range vm.Devices {
135
if vsockDev, isVirtioVsock := dev.(*VirtioVsock); isVirtioVsock {
136
vsockDevs = append(vsockDevs, vsockDev)
145
func (vm *VirtualMachine) AddDevice(dev VirtioDevice) error {
146
vm.Devices = append(vm.Devices, dev)
151
func (vm *VirtualMachine) AddTimeSyncFromCmdLine(cmdlineOpts string) error {
152
if cmdlineOpts == "" {
155
timesync, err := timesyncFromCmdLine(cmdlineOpts)
159
vm.Timesync = timesync
164
func (vm *VirtualMachine) TimeSync() *TimeSync {
168
func TimeSyncNew(vsockPort uint) (VMComponent, error) {
170
VsockPort: vsockPort,
174
func (ts *TimeSync) ToCmdLine() ([]string, error) {
176
if ts.VsockPort != 0 {
177
args = append(args, fmt.Sprintf("vsockPort=%d", ts.VsockPort))
179
return []string{"--timesync", strings.Join(args, ",")}, nil
182
func (ts *TimeSync) FromOptions(options []option) error {
183
for _, option := range options {
186
vsockPort, err := strconv.ParseUint(option.value, 10, 64)
190
ts.VsockPort = uint(vsockPort)
192
return fmt.Errorf("unknown option for timesync parameter: %s", option.key)
196
if ts.VsockPort == 0 {
197
return fmt.Errorf("missing 'vsockPort' option for timesync parameter")
203
func timesyncFromCmdLine(optsStr string) (*TimeSync, error) {
204
var timesync TimeSync
206
optsStrv := strings.Split(optsStr, ",")
207
options := strvToOptions(optsStrv)
209
if err := timesync.FromOptions(options); err != nil {
213
return ×ync, nil