mirror of
https://github.com/containers/podman.git
synced 2025-11-30 18:18:18 +08:00
* Use vfkit command line assembly * Inject ignition file into guest using http over vsock * Ready notification through use of vsock [NO NEW TESTS NEEDED] Signed-off-by: Brent Baude <bbaude@redhat.com>
310 lines
6.4 KiB
Go
310 lines
6.4 KiB
Go
package config
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
)
|
|
|
|
// The technique for json (de)serialization was explained here:
|
|
// http://gregtrowbridge.com/golang-json-serialization-with-interfaces/
|
|
|
|
type vmComponentKind string
|
|
|
|
const (
|
|
// Bootloader kinds
|
|
efiBootloader vmComponentKind = "efiBootloader"
|
|
linuxBootloader vmComponentKind = "linuxBootloader"
|
|
|
|
// VirtIO device kinds
|
|
vfNet vmComponentKind = "virtionet"
|
|
vfVsock vmComponentKind = "virtiosock"
|
|
vfBlk vmComponentKind = "virtioblk"
|
|
vfFs vmComponentKind = "virtiofs"
|
|
vfRng vmComponentKind = "virtiorng"
|
|
vfSerial vmComponentKind = "virtioserial"
|
|
vfGpu vmComponentKind = "virtiogpu"
|
|
vfInput vmComponentKind = "virtioinput"
|
|
usbMassStorage vmComponentKind = "usbmassstorage"
|
|
)
|
|
|
|
type jsonKind struct {
|
|
Kind vmComponentKind `json:"kind"`
|
|
}
|
|
|
|
func kind(k vmComponentKind) jsonKind {
|
|
return jsonKind{Kind: k}
|
|
}
|
|
|
|
func unmarshalBootloader(rawMsg json.RawMessage) (Bootloader, error) {
|
|
var (
|
|
kind jsonKind
|
|
bootloader Bootloader
|
|
err error
|
|
)
|
|
if err := json.Unmarshal(rawMsg, &kind); err != nil {
|
|
return nil, err
|
|
}
|
|
switch kind.Kind {
|
|
case efiBootloader:
|
|
var efi EFIBootloader
|
|
err = json.Unmarshal(rawMsg, &efi)
|
|
if err == nil {
|
|
bootloader = &efi
|
|
}
|
|
case linuxBootloader:
|
|
var linux LinuxBootloader
|
|
err = json.Unmarshal(rawMsg, &linux)
|
|
if err == nil {
|
|
bootloader = &linux
|
|
}
|
|
default:
|
|
err = fmt.Errorf("unknown 'kind' field: '%s'", kind)
|
|
}
|
|
|
|
return bootloader, err
|
|
}
|
|
|
|
func unmarshalDevices(rawMsg json.RawMessage) ([]VirtioDevice, error) {
|
|
var (
|
|
rawDevices []*json.RawMessage
|
|
devices []VirtioDevice
|
|
)
|
|
|
|
err := json.Unmarshal(rawMsg, &rawDevices)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for _, msg := range rawDevices {
|
|
dev, err := unmarshalDevice(*msg)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
devices = append(devices, dev)
|
|
}
|
|
|
|
return devices, nil
|
|
}
|
|
|
|
func unmarshalDevice(rawMsg json.RawMessage) (VirtioDevice, error) {
|
|
var (
|
|
kind jsonKind
|
|
dev VirtioDevice
|
|
err error
|
|
)
|
|
if err := json.Unmarshal(rawMsg, &kind); err != nil {
|
|
return nil, err
|
|
}
|
|
switch kind.Kind {
|
|
case vfNet:
|
|
var newDevice VirtioNet
|
|
err = json.Unmarshal(rawMsg, &newDevice)
|
|
dev = &newDevice
|
|
case vfVsock:
|
|
var newDevice VirtioVsock
|
|
err = json.Unmarshal(rawMsg, &newDevice)
|
|
dev = &newDevice
|
|
case vfBlk:
|
|
var newDevice VirtioBlk
|
|
err = json.Unmarshal(rawMsg, &newDevice)
|
|
dev = &newDevice
|
|
case vfFs:
|
|
var newDevice VirtioFs
|
|
err = json.Unmarshal(rawMsg, &newDevice)
|
|
dev = &newDevice
|
|
case vfRng:
|
|
var newDevice VirtioRng
|
|
err = json.Unmarshal(rawMsg, &newDevice)
|
|
dev = &newDevice
|
|
case vfSerial:
|
|
var newDevice VirtioSerial
|
|
err = json.Unmarshal(rawMsg, &newDevice)
|
|
dev = &newDevice
|
|
case vfGpu:
|
|
var newDevice VirtioGPU
|
|
err = json.Unmarshal(rawMsg, &newDevice)
|
|
dev = &newDevice
|
|
case vfInput:
|
|
var newDevice VirtioInput
|
|
err = json.Unmarshal(rawMsg, &newDevice)
|
|
dev = &newDevice
|
|
case usbMassStorage:
|
|
var newDevice USBMassStorage
|
|
err = json.Unmarshal(rawMsg, &newDevice)
|
|
dev = &newDevice
|
|
default:
|
|
err = fmt.Errorf("unknown 'kind' field: '%s'", kind)
|
|
}
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return dev, nil
|
|
}
|
|
|
|
// UnmarshalJSON is a custom deserializer for VirtualMachine. The custom work
|
|
// is needed because VirtualMachine uses interfaces in its struct and JSON cannot
|
|
// determine which implementation of the interface to deserialize to.
|
|
func (vm *VirtualMachine) UnmarshalJSON(b []byte) error {
|
|
var (
|
|
err error
|
|
input map[string]*json.RawMessage
|
|
)
|
|
|
|
if err := json.Unmarshal(b, &input); err != nil {
|
|
return err
|
|
}
|
|
|
|
for idx, rawMsg := range input {
|
|
if rawMsg == nil {
|
|
continue
|
|
}
|
|
switch idx {
|
|
case "vcpus":
|
|
err = json.Unmarshal(*rawMsg, &vm.Vcpus)
|
|
case "memoryBytes":
|
|
err = json.Unmarshal(*rawMsg, &vm.MemoryBytes)
|
|
case "bootloader":
|
|
var bootloader Bootloader
|
|
bootloader, err = unmarshalBootloader(*rawMsg)
|
|
if err == nil {
|
|
vm.Bootloader = bootloader
|
|
}
|
|
case "timesync":
|
|
err = json.Unmarshal(*rawMsg, &vm.Timesync)
|
|
case "devices":
|
|
var devices []VirtioDevice
|
|
devices, err = unmarshalDevices(*rawMsg)
|
|
if err == nil {
|
|
vm.Devices = devices
|
|
}
|
|
}
|
|
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (bootloader *EFIBootloader) MarshalJSON() ([]byte, error) {
|
|
type blWithKind struct {
|
|
jsonKind
|
|
EFIBootloader
|
|
}
|
|
return json.Marshal(blWithKind{
|
|
jsonKind: kind(efiBootloader),
|
|
EFIBootloader: *bootloader,
|
|
})
|
|
}
|
|
|
|
func (bootloader *LinuxBootloader) MarshalJSON() ([]byte, error) {
|
|
type blWithKind struct {
|
|
jsonKind
|
|
LinuxBootloader
|
|
}
|
|
return json.Marshal(blWithKind{
|
|
jsonKind: kind(linuxBootloader),
|
|
LinuxBootloader: *bootloader,
|
|
})
|
|
}
|
|
|
|
func (dev *VirtioNet) MarshalJSON() ([]byte, error) {
|
|
type devWithKind struct {
|
|
jsonKind
|
|
VirtioNet
|
|
}
|
|
return json.Marshal(devWithKind{
|
|
jsonKind: kind(vfNet),
|
|
VirtioNet: *dev,
|
|
})
|
|
}
|
|
|
|
func (dev *VirtioVsock) MarshalJSON() ([]byte, error) {
|
|
type devWithKind struct {
|
|
jsonKind
|
|
VirtioVsock
|
|
}
|
|
return json.Marshal(devWithKind{
|
|
jsonKind: kind(vfVsock),
|
|
VirtioVsock: *dev,
|
|
})
|
|
}
|
|
|
|
func (dev *VirtioBlk) MarshalJSON() ([]byte, error) {
|
|
type devWithKind struct {
|
|
jsonKind
|
|
VirtioBlk
|
|
}
|
|
return json.Marshal(devWithKind{
|
|
jsonKind: kind(vfBlk),
|
|
VirtioBlk: *dev,
|
|
})
|
|
}
|
|
|
|
func (dev *VirtioFs) MarshalJSON() ([]byte, error) {
|
|
type devWithKind struct {
|
|
jsonKind
|
|
VirtioFs
|
|
}
|
|
return json.Marshal(devWithKind{
|
|
jsonKind: kind(vfFs),
|
|
VirtioFs: *dev,
|
|
})
|
|
}
|
|
|
|
func (dev *VirtioRng) MarshalJSON() ([]byte, error) {
|
|
type devWithKind struct {
|
|
jsonKind
|
|
VirtioRng
|
|
}
|
|
return json.Marshal(devWithKind{
|
|
jsonKind: kind(vfRng),
|
|
VirtioRng: *dev,
|
|
})
|
|
}
|
|
|
|
func (dev *VirtioSerial) MarshalJSON() ([]byte, error) {
|
|
type devWithKind struct {
|
|
jsonKind
|
|
VirtioSerial
|
|
}
|
|
return json.Marshal(devWithKind{
|
|
jsonKind: kind(vfSerial),
|
|
VirtioSerial: *dev,
|
|
})
|
|
}
|
|
|
|
func (dev *VirtioGPU) MarshalJSON() ([]byte, error) {
|
|
type devWithKind struct {
|
|
jsonKind
|
|
VirtioGPU
|
|
}
|
|
return json.Marshal(devWithKind{
|
|
jsonKind: kind(vfGpu),
|
|
VirtioGPU: *dev,
|
|
})
|
|
}
|
|
|
|
func (dev *VirtioInput) MarshalJSON() ([]byte, error) {
|
|
type devWithKind struct {
|
|
jsonKind
|
|
VirtioInput
|
|
}
|
|
return json.Marshal(devWithKind{
|
|
jsonKind: kind(vfInput),
|
|
VirtioInput: *dev,
|
|
})
|
|
}
|
|
|
|
func (dev *USBMassStorage) MarshalJSON() ([]byte, error) {
|
|
type devWithKind struct {
|
|
jsonKind
|
|
USBMassStorage
|
|
}
|
|
return json.Marshal(devWithKind{
|
|
jsonKind: kind(usbMassStorage),
|
|
USBMassStorage: *dev,
|
|
})
|
|
}
|