8
// The technique for json (de)serialization was explained here:
9
// http://gregtrowbridge.com/golang-json-serialization-with-interfaces/
11
type vmComponentKind string
15
efiBootloader vmComponentKind = "efiBootloader"
16
linuxBootloader vmComponentKind = "linuxBootloader"
18
// VirtIO device kinds
19
vfNet vmComponentKind = "virtionet"
20
vfVsock vmComponentKind = "virtiosock"
21
vfBlk vmComponentKind = "virtioblk"
22
vfFs vmComponentKind = "virtiofs"
23
vfRng vmComponentKind = "virtiorng"
24
vfSerial vmComponentKind = "virtioserial"
25
vfGpu vmComponentKind = "virtiogpu"
26
vfInput vmComponentKind = "virtioinput"
27
usbMassStorage vmComponentKind = "usbmassstorage"
28
rosetta vmComponentKind = "rosetta"
32
Kind vmComponentKind `json:"kind"`
35
func kind(k vmComponentKind) jsonKind {
36
return jsonKind{Kind: k}
39
func unmarshalBootloader(rawMsg json.RawMessage) (Bootloader, error) {
45
if err := json.Unmarshal(rawMsg, &kind); err != nil {
51
err = json.Unmarshal(rawMsg, &efi)
56
var linux LinuxBootloader
57
err = json.Unmarshal(rawMsg, &linux)
62
err = fmt.Errorf("unknown 'kind' field: '%s'", kind)
65
return bootloader, err
68
func unmarshalDevices(rawMsg json.RawMessage) ([]VirtioDevice, error) {
70
rawDevices []*json.RawMessage
71
devices []VirtioDevice
74
err := json.Unmarshal(rawMsg, &rawDevices)
79
for _, msg := range rawDevices {
80
dev, err := unmarshalDevice(*msg)
84
devices = append(devices, dev)
90
func unmarshalDevice(rawMsg json.RawMessage) (VirtioDevice, error) {
96
if err := json.Unmarshal(rawMsg, &kind); err != nil {
101
var newDevice VirtioNet
102
err = json.Unmarshal(rawMsg, &newDevice)
105
var newDevice VirtioVsock
106
err = json.Unmarshal(rawMsg, &newDevice)
109
var newDevice VirtioBlk
110
err = json.Unmarshal(rawMsg, &newDevice)
113
var newDevice VirtioFs
114
err = json.Unmarshal(rawMsg, &newDevice)
117
var newDevice RosettaShare
118
err = json.Unmarshal(rawMsg, &newDevice)
121
var newDevice VirtioRng
122
err = json.Unmarshal(rawMsg, &newDevice)
125
var newDevice VirtioSerial
126
err = json.Unmarshal(rawMsg, &newDevice)
129
var newDevice VirtioGPU
130
err = json.Unmarshal(rawMsg, &newDevice)
133
var newDevice VirtioInput
134
err = json.Unmarshal(rawMsg, &newDevice)
137
var newDevice USBMassStorage
138
err = json.Unmarshal(rawMsg, &newDevice)
141
err = fmt.Errorf("unknown 'kind' field: '%s'", kind)
150
// UnmarshalJSON is a custom deserializer for VirtualMachine. The custom work
151
// is needed because VirtualMachine uses interfaces in its struct and JSON cannot
152
// determine which implementation of the interface to deserialize to.
153
func (vm *VirtualMachine) UnmarshalJSON(b []byte) error {
156
input map[string]*json.RawMessage
159
if err := json.Unmarshal(b, &input); err != nil {
163
for idx, rawMsg := range input {
169
err = json.Unmarshal(*rawMsg, &vm.Vcpus)
171
err = json.Unmarshal(*rawMsg, &vm.MemoryBytes)
173
var bootloader Bootloader
174
bootloader, err = unmarshalBootloader(*rawMsg)
176
vm.Bootloader = bootloader
179
err = json.Unmarshal(*rawMsg, &vm.Timesync)
181
var devices []VirtioDevice
182
devices, err = unmarshalDevices(*rawMsg)
195
func (bootloader *EFIBootloader) MarshalJSON() ([]byte, error) {
196
type blWithKind struct {
200
return json.Marshal(blWithKind{
201
jsonKind: kind(efiBootloader),
202
EFIBootloader: *bootloader,
206
func (bootloader *LinuxBootloader) MarshalJSON() ([]byte, error) {
207
type blWithKind struct {
211
return json.Marshal(blWithKind{
212
jsonKind: kind(linuxBootloader),
213
LinuxBootloader: *bootloader,
217
func (dev *VirtioNet) MarshalJSON() ([]byte, error) {
218
type devWithKind struct {
222
return json.Marshal(devWithKind{
223
jsonKind: kind(vfNet),
228
func (dev *VirtioVsock) MarshalJSON() ([]byte, error) {
229
type devWithKind struct {
233
return json.Marshal(devWithKind{
234
jsonKind: kind(vfVsock),
239
func (dev *VirtioBlk) MarshalJSON() ([]byte, error) {
240
type devWithKind struct {
244
return json.Marshal(devWithKind{
245
jsonKind: kind(vfBlk),
250
func (dev *VirtioFs) MarshalJSON() ([]byte, error) {
251
type devWithKind struct {
255
return json.Marshal(devWithKind{
256
jsonKind: kind(vfFs),
261
func (dev *RosettaShare) MarshalJSON() ([]byte, error) {
262
type devWithKind struct {
266
return json.Marshal(devWithKind{
267
jsonKind: kind(rosetta),
272
func (dev *VirtioRng) MarshalJSON() ([]byte, error) {
273
type devWithKind struct {
277
return json.Marshal(devWithKind{
278
jsonKind: kind(vfRng),
283
func (dev *VirtioSerial) MarshalJSON() ([]byte, error) {
284
type devWithKind struct {
288
return json.Marshal(devWithKind{
289
jsonKind: kind(vfSerial),
294
func (dev *VirtioGPU) MarshalJSON() ([]byte, error) {
295
type devWithKind struct {
299
return json.Marshal(devWithKind{
300
jsonKind: kind(vfGpu),
305
func (dev *VirtioInput) MarshalJSON() ([]byte, error) {
306
type devWithKind struct {
310
return json.Marshal(devWithKind{
311
jsonKind: kind(vfInput),
316
func (dev *USBMassStorage) MarshalJSON() ([]byte, error) {
317
type devWithKind struct {
321
return json.Marshal(devWithKind{
322
jsonKind: kind(usbMassStorage),
323
USBMassStorage: *dev,