podman

Форк
0
325 строк · 6.7 Кб
1
package config
2

3
import (
4
	"encoding/json"
5
	"fmt"
6
)
7

8
// The technique for json (de)serialization was explained here:
9
// http://gregtrowbridge.com/golang-json-serialization-with-interfaces/
10

11
type vmComponentKind string
12

13
const (
14
	// Bootloader kinds
15
	efiBootloader   vmComponentKind = "efiBootloader"
16
	linuxBootloader vmComponentKind = "linuxBootloader"
17

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"
29
)
30

31
type jsonKind struct {
32
	Kind vmComponentKind `json:"kind"`
33
}
34

35
func kind(k vmComponentKind) jsonKind {
36
	return jsonKind{Kind: k}
37
}
38

39
func unmarshalBootloader(rawMsg json.RawMessage) (Bootloader, error) {
40
	var (
41
		kind       jsonKind
42
		bootloader Bootloader
43
		err        error
44
	)
45
	if err := json.Unmarshal(rawMsg, &kind); err != nil {
46
		return nil, err
47
	}
48
	switch kind.Kind {
49
	case efiBootloader:
50
		var efi EFIBootloader
51
		err = json.Unmarshal(rawMsg, &efi)
52
		if err == nil {
53
			bootloader = &efi
54
		}
55
	case linuxBootloader:
56
		var linux LinuxBootloader
57
		err = json.Unmarshal(rawMsg, &linux)
58
		if err == nil {
59
			bootloader = &linux
60
		}
61
	default:
62
		err = fmt.Errorf("unknown 'kind' field: '%s'", kind)
63
	}
64

65
	return bootloader, err
66
}
67

68
func unmarshalDevices(rawMsg json.RawMessage) ([]VirtioDevice, error) {
69
	var (
70
		rawDevices []*json.RawMessage
71
		devices    []VirtioDevice
72
	)
73

74
	err := json.Unmarshal(rawMsg, &rawDevices)
75
	if err != nil {
76
		return nil, err
77
	}
78

79
	for _, msg := range rawDevices {
80
		dev, err := unmarshalDevice(*msg)
81
		if err != nil {
82
			return nil, err
83
		}
84
		devices = append(devices, dev)
85
	}
86

87
	return devices, nil
88
}
89

90
func unmarshalDevice(rawMsg json.RawMessage) (VirtioDevice, error) {
91
	var (
92
		kind jsonKind
93
		dev  VirtioDevice
94
		err  error
95
	)
96
	if err := json.Unmarshal(rawMsg, &kind); err != nil {
97
		return nil, err
98
	}
99
	switch kind.Kind {
100
	case vfNet:
101
		var newDevice VirtioNet
102
		err = json.Unmarshal(rawMsg, &newDevice)
103
		dev = &newDevice
104
	case vfVsock:
105
		var newDevice VirtioVsock
106
		err = json.Unmarshal(rawMsg, &newDevice)
107
		dev = &newDevice
108
	case vfBlk:
109
		var newDevice VirtioBlk
110
		err = json.Unmarshal(rawMsg, &newDevice)
111
		dev = &newDevice
112
	case vfFs:
113
		var newDevice VirtioFs
114
		err = json.Unmarshal(rawMsg, &newDevice)
115
		dev = &newDevice
116
	case rosetta:
117
		var newDevice RosettaShare
118
		err = json.Unmarshal(rawMsg, &newDevice)
119
		dev = &newDevice
120
	case vfRng:
121
		var newDevice VirtioRng
122
		err = json.Unmarshal(rawMsg, &newDevice)
123
		dev = &newDevice
124
	case vfSerial:
125
		var newDevice VirtioSerial
126
		err = json.Unmarshal(rawMsg, &newDevice)
127
		dev = &newDevice
128
	case vfGpu:
129
		var newDevice VirtioGPU
130
		err = json.Unmarshal(rawMsg, &newDevice)
131
		dev = &newDevice
132
	case vfInput:
133
		var newDevice VirtioInput
134
		err = json.Unmarshal(rawMsg, &newDevice)
135
		dev = &newDevice
136
	case usbMassStorage:
137
		var newDevice USBMassStorage
138
		err = json.Unmarshal(rawMsg, &newDevice)
139
		dev = &newDevice
140
	default:
141
		err = fmt.Errorf("unknown 'kind' field: '%s'", kind)
142
	}
143

144
	if err != nil {
145
		return nil, err
146
	}
147
	return dev, nil
148
}
149

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 {
154
	var (
155
		err   error
156
		input map[string]*json.RawMessage
157
	)
158

159
	if err := json.Unmarshal(b, &input); err != nil {
160
		return err
161
	}
162

163
	for idx, rawMsg := range input {
164
		if rawMsg == nil {
165
			continue
166
		}
167
		switch idx {
168
		case "vcpus":
169
			err = json.Unmarshal(*rawMsg, &vm.Vcpus)
170
		case "memoryBytes":
171
			err = json.Unmarshal(*rawMsg, &vm.MemoryBytes)
172
		case "bootloader":
173
			var bootloader Bootloader
174
			bootloader, err = unmarshalBootloader(*rawMsg)
175
			if err == nil {
176
				vm.Bootloader = bootloader
177
			}
178
		case "timesync":
179
			err = json.Unmarshal(*rawMsg, &vm.Timesync)
180
		case "devices":
181
			var devices []VirtioDevice
182
			devices, err = unmarshalDevices(*rawMsg)
183
			if err == nil {
184
				vm.Devices = devices
185
			}
186
		}
187

188
		if err != nil {
189
			return err
190
		}
191
	}
192
	return nil
193
}
194

195
func (bootloader *EFIBootloader) MarshalJSON() ([]byte, error) {
196
	type blWithKind struct {
197
		jsonKind
198
		EFIBootloader
199
	}
200
	return json.Marshal(blWithKind{
201
		jsonKind:      kind(efiBootloader),
202
		EFIBootloader: *bootloader,
203
	})
204
}
205

206
func (bootloader *LinuxBootloader) MarshalJSON() ([]byte, error) {
207
	type blWithKind struct {
208
		jsonKind
209
		LinuxBootloader
210
	}
211
	return json.Marshal(blWithKind{
212
		jsonKind:        kind(linuxBootloader),
213
		LinuxBootloader: *bootloader,
214
	})
215
}
216

217
func (dev *VirtioNet) MarshalJSON() ([]byte, error) {
218
	type devWithKind struct {
219
		jsonKind
220
		VirtioNet
221
	}
222
	return json.Marshal(devWithKind{
223
		jsonKind:  kind(vfNet),
224
		VirtioNet: *dev,
225
	})
226
}
227

228
func (dev *VirtioVsock) MarshalJSON() ([]byte, error) {
229
	type devWithKind struct {
230
		jsonKind
231
		VirtioVsock
232
	}
233
	return json.Marshal(devWithKind{
234
		jsonKind:    kind(vfVsock),
235
		VirtioVsock: *dev,
236
	})
237
}
238

239
func (dev *VirtioBlk) MarshalJSON() ([]byte, error) {
240
	type devWithKind struct {
241
		jsonKind
242
		VirtioBlk
243
	}
244
	return json.Marshal(devWithKind{
245
		jsonKind:  kind(vfBlk),
246
		VirtioBlk: *dev,
247
	})
248
}
249

250
func (dev *VirtioFs) MarshalJSON() ([]byte, error) {
251
	type devWithKind struct {
252
		jsonKind
253
		VirtioFs
254
	}
255
	return json.Marshal(devWithKind{
256
		jsonKind: kind(vfFs),
257
		VirtioFs: *dev,
258
	})
259
}
260

261
func (dev *RosettaShare) MarshalJSON() ([]byte, error) {
262
	type devWithKind struct {
263
		jsonKind
264
		RosettaShare
265
	}
266
	return json.Marshal(devWithKind{
267
		jsonKind:     kind(rosetta),
268
		RosettaShare: *dev,
269
	})
270
}
271

272
func (dev *VirtioRng) MarshalJSON() ([]byte, error) {
273
	type devWithKind struct {
274
		jsonKind
275
		VirtioRng
276
	}
277
	return json.Marshal(devWithKind{
278
		jsonKind:  kind(vfRng),
279
		VirtioRng: *dev,
280
	})
281
}
282

283
func (dev *VirtioSerial) MarshalJSON() ([]byte, error) {
284
	type devWithKind struct {
285
		jsonKind
286
		VirtioSerial
287
	}
288
	return json.Marshal(devWithKind{
289
		jsonKind:     kind(vfSerial),
290
		VirtioSerial: *dev,
291
	})
292
}
293

294
func (dev *VirtioGPU) MarshalJSON() ([]byte, error) {
295
	type devWithKind struct {
296
		jsonKind
297
		VirtioGPU
298
	}
299
	return json.Marshal(devWithKind{
300
		jsonKind:  kind(vfGpu),
301
		VirtioGPU: *dev,
302
	})
303
}
304

305
func (dev *VirtioInput) MarshalJSON() ([]byte, error) {
306
	type devWithKind struct {
307
		jsonKind
308
		VirtioInput
309
	}
310
	return json.Marshal(devWithKind{
311
		jsonKind:    kind(vfInput),
312
		VirtioInput: *dev,
313
	})
314
}
315

316
func (dev *USBMassStorage) MarshalJSON() ([]byte, error) {
317
	type devWithKind struct {
318
		jsonKind
319
		USBMassStorage
320
	}
321
	return json.Marshal(devWithKind{
322
		jsonKind:       kind(usbMassStorage),
323
		USBMassStorage: *dev,
324
	})
325
}
326

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.