-
Notifications
You must be signed in to change notification settings - Fork 164
/
Copy pathdomainmgrtypes.go
605 lines (535 loc) · 18.9 KB
/
domainmgrtypes.go
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
// Copyright (c) 2017 Zededa, Inc.
// SPDX-License-Identifier: Apache-2.0
package types
import (
"fmt"
"net"
"os"
"strconv"
"strings"
"time"
uuid "github.com/satori/go.uuid"
"github.com/google/go-cmp/cmp"
zconfig "github.com/lf-edge/eve-api/go/config"
"github.com/lf-edge/eve/pkg/kube/cnirpc"
"github.com/lf-edge/eve/pkg/pillar/base"
"github.com/lf-edge/eve/pkg/pillar/pubsub"
"github.com/lf-edge/eve/pkg/pillar/utils/cloudconfig"
)
// DomainConfig contains information DomainManager needs to boot and halt domains
// If the the version (in UUIDandVersion) changes then the domain needs to
// halted and booted?? NO, because an ACL change from ZedControl would bump
// the version. Who determines which changes require halt+reboot?
// Do we need an explicit interlock with ZedManager when a reboot
// is needed? For instance, ZedManager could remove the DomainConfig, what for
// DomainStatus to be deleted, then re-create the DomainConfig.
type DomainConfig struct {
UUIDandVersion UUIDandVersion
DisplayName string // Use as name for domU? DisplayName+version?
Activate bool // Actually start the domU as opposed to prepare
AppNum int // From networking; makes the name unique
VmConfig
DisableLogs bool
GPUConfig string
DiskConfigList []DiskConfig
VifList []VifConfig
IoAdapterList []IoAdapter
// KubeImageName: is the container image reference we pass to domainmgr to launch a native container
// in kubevirt eve
KubeImageName string
// if this node is the DNiD of the App
IsDNidNode bool
// XXX: to be deprecated, use CipherBlockStatus instead
CloudInitUserData *string `json:"pubsub-large-CloudInitUserData"` // base64-encoded
// CipherBlockStatus, for encrypted cloud-init data
CipherBlockStatus
// MetaDataType for select type of metadata service for app
MetaDataType MetaDataType
// Service flag indicates that we want to start app instance
// with options defined in org.mobyproject.config label of image provided by linuxkit
Service bool
// All changes to the cloud-init config are tracked using this version field -
// once the version is changed cloud-init tool restarts in a guest.
// See getCloudInitVersion() and createCloudInitISO() for details.
CloudInitVersion uint32
}
// MetaDataType of metadata service for app
// must match the values in the proto definition
type MetaDataType uint8
// types of metadata service for app if CloudInitUserData provided
const (
MetaDataDrive MetaDataType = iota + 0 // Default
MetaDataNone
MetaDataOpenStack
MetaDataDriveMultipart // Process multipart MIME for application
)
// String returns the string name
func (metaDataType MetaDataType) String() string {
switch metaDataType {
case MetaDataDrive:
return "MetaDataDrive"
case MetaDataNone:
return "MetaDataNone"
case MetaDataOpenStack:
return "MetaDataOpenStack"
case MetaDataDriveMultipart:
return "MetaDataDriveMultipart"
default:
return fmt.Sprintf("Unknown MetaDataType %d", metaDataType)
}
}
// The whole domain is considered as a container-based if the first disk
// has the 'CONTAINER' format.
func (config DomainConfig) IsOCIContainer() bool {
if len(config.DiskConfigList) > 0 &&
config.DiskConfigList[0].Format == zconfig.Format_CONTAINER {
return true
}
return false
}
// GetTaskName assigns a unique name to the task representing this domain
// FIXME: given config.UUIDandVersion.Version part not sure config.AppNum is needed for uniqueness
func (config DomainConfig) GetTaskName() string {
return config.UUIDandVersion.UUID.String() + "." +
config.UUIDandVersion.Version + "." +
strconv.Itoa(config.AppNum)
}
// DomainnameToUUID does the reverse of GetTaskName
func DomainnameToUUID(name string) (uuid.UUID, string, int, error) {
// FIXME: we can likely drop this altogether
if name == "Domain-0" {
return uuid.UUID{}, "", 0, nil
}
res := strings.Split(name, ".")
if len(res) != 3 {
return uuid.UUID{}, "", 0, fmt.Errorf("Unknown domainname format %s",
name)
}
id, err := uuid.FromString(res[0])
if err != nil {
return uuid.UUID{}, "", 0, fmt.Errorf("Bad UUID %s: %w",
res[0], err)
}
appNum, err := strconv.Atoi(res[2])
if err != nil {
return uuid.UUID{}, "", 0, fmt.Errorf("Bad appNum %s: %w",
res[2], err)
}
return id, res[1], appNum, nil
}
// Key returns domain UUID string
func (config DomainConfig) Key() string {
return config.UUIDandVersion.UUID.String()
}
// VirtualizationModeOrDefault sets the default to PV
func (config DomainConfig) VirtualizationModeOrDefault() VmMode {
switch config.VirtualizationMode {
case PV, HVM, FML, NOHYPER, LEGACY:
return config.VirtualizationMode
default:
return PV
}
}
// GetPVCNameFromVolumeKey gets the pvcName from volume key
func (status DiskStatus) GetPVCNameFromVolumeKey() (string, error) {
volumeIDAndGeneration := status.VolumeKey
generation := strings.Split(volumeIDAndGeneration, "#")
volUUID, err := uuid.FromString(generation[0])
if err != nil {
return "", fmt.Errorf("failed to parse volUUID: %w", err)
}
generationCounter, err := strconv.ParseInt(generation[1], 10, 64)
if err != nil {
return "", fmt.Errorf("failed to parse GenerationCounter: %w", err)
}
pvcName := fmt.Sprintf("%s-pvc-%d", volUUID, generationCounter)
return pvcName, nil
}
// LogCreate :
func (config DomainConfig) LogCreate(logBase *base.LogObject) {
logObject := base.NewLogObject(logBase, base.DomainConfigLogType, config.DisplayName,
config.UUIDandVersion.UUID, config.LogKey())
if logObject == nil {
return
}
logObject.CloneAndAddField("activate-bool", config.Activate).
AddField("enable-vnc-bool", config.EnableVnc).
AddField("enable-vnc-shim-vm-bool", config.EnableVncShimVM).
Noticef("domain config create")
}
// LogModify :
func (config DomainConfig) LogModify(logBase *base.LogObject, old interface{}) {
logObject := base.EnsureLogObject(logBase, base.DomainConfigLogType, config.DisplayName,
config.UUIDandVersion.UUID, config.LogKey())
oldConfig, ok := old.(DomainConfig)
if !ok {
logObject.Clone().Fatalf("LogModify: Old object interface passed is not of DomainConfig type")
}
if oldConfig.Activate != config.Activate ||
oldConfig.EnableVnc != config.EnableVnc ||
oldConfig.EnableVncShimVM != config.EnableVncShimVM {
logObject.CloneAndAddField("activate-bool", config.Activate).
AddField("enable-vnc-bool", config.EnableVnc).
AddField("enable-vnc-shim-vm-bool", config.EnableVncShimVM).
AddField("old-activate-bool", oldConfig.Activate).
AddField("old-enable-vnc-bool", oldConfig.EnableVnc).
AddField("old-enable-vnc-shim-vm-bool", oldConfig.EnableVncShimVM).
Noticef("domain config modify")
} else {
// XXX remove?
logObject.CloneAndAddField("diff", cmp.Diff(oldConfig, config)).
Noticef("domain config modify other change")
}
}
// LogDelete :
func (config DomainConfig) LogDelete(logBase *base.LogObject) {
logObject := base.EnsureLogObject(logBase, base.DomainConfigLogType, config.DisplayName,
config.UUIDandVersion.UUID, config.LogKey())
logObject.CloneAndAddField("activate-bool", config.Activate).
AddField("enable-vnc-bool", config.EnableVnc).
AddField("enable-vnc-shim-vm-bool", config.EnableVncShimVM).
Noticef("domain config delete")
base.DeleteLogObject(logBase, config.LogKey())
}
// LogKey :
func (config DomainConfig) LogKey() string {
return string(base.DomainConfigLogType) + "-" + config.Key()
}
// VmConfig, Some of these items can be overridden by matching Targets in
// StorageConfigList. For example, a Target of "kernel" means to set/override
// the Kernel attribute below.
//
// Keep in mind that the fields in this structure are considered
// so-called "fixed resources", which means that the virtual machine
// must be restarted before changes to the field will take effect.
type VmConfig struct {
Kernel string // default ""
Ramdisk string // default ""
Memory int // in kbytes; Rounded up to Mbytes for xen
MaxMem int // in kbytes; Default equal to 'Memory', so no ballooning for xen
VCpus int // default 1
MaxCpus int // default VCpus
RootDev string // default "/dev/xvda1"
ExtraArgs string // added to bootargs
BootLoader string // default ""
// For CPU pinning
CPUs []int // default nil, list of [1,2]
// Needed for device passthru
DeviceTree string // default ""; sets device_tree
// Example: device_tree="guest-gpio.dtb"
DtDev []string // default nil; sets dtdev
// Example, DtDev=["/smb/gpio@f7020000","/smb/gpio@f8013000"]
IRQs []int // default nil; sets irqs
// Example, IRQs=[88,86]
IOMem []string // default nil; sets iomem
// Example, IOMem=["0xf7020,1","0xf8013,1"]
VirtualizationMode VmMode
EnableVnc bool
VncDisplay uint32
VncPasswd string
CPUsPinned bool
VMMMaxMem int // in kbytes
EnableVncShimVM bool
// Enables enforcement of user-defined ordering for network interfaces.
EnforceNetworkInterfaceOrder bool
}
// VmMode is the type for the virtualization mode
type VmMode uint8
const (
PV VmMode = iota + 0 // Default
HVM
Filler
FML
NOHYPER
LEGACY
)
// Task represents any runnable entity on EVE
type Task interface {
Setup(DomainStatus, DomainConfig, *AssignableAdapters,
*ConfigItemValueMap, *os.File) error
VirtualTPMSetup(domainName string, wp *WatchdogParam) error
VirtualTPMTerminate(domainName string, wp *WatchdogParam) error
VirtualTPMTeardown(domainName string, wp *WatchdogParam) error
Create(string, string, *DomainConfig) (int, error)
Start(string) error
Stop(string, bool) error
Delete(string) error
Info(string) (int, SwState, error)
Cleanup(string) error
}
type DomainStatus struct {
UUIDandVersion UUIDandVersion
DisplayName string
State SwState // BOOTING and above?
Activated bool // XXX remove??
AppNum int // From networking; makes the name unique
PendingAdd bool
PendingModify bool
PendingDelete bool
DomainName string // Name of Xen domain
DomainId int
BootTime time.Time
DiskStatusList []DiskStatus
VifList []VifInfo
IoAdapterList []IoAdapter
DisableLogs bool
TriedCount int
// ErrorAndTime provides SetErrorNow() and ClearError()
ErrorAndTime
ConfigFailed bool
BootFailed bool
AdaptersFailed bool
OCIConfigDir string // folder holding an OCI Image config for this domain (empty string means no config)
EnvVariables map[string]string // List of environment variables to be set in container
WritableFiles []cloudconfig.WritableFile // List of files from CloudInit scripts to be created in container
VmConfig // From DomainConfig
Service bool
// VirtualTPM is a flag to signal the hypervisor implementation
// that vTPM is available for the domain.
VirtualTPM bool
// FmlCustomResolution is the custom resolution for FML mode,
// xxx: this should be moved to VmConfig
FmlCustomResolution string
// if this node is the DNiD of the App
IsDNidNode bool
// the device name is used for kube node name
// Need to pass in from domainmgr to hypervisor context commands
NodeName string
}
func (status DomainStatus) Key() string {
return status.UUIDandVersion.UUID.String()
}
func (status DomainStatus) Pending() bool {
return status.PendingAdd || status.PendingModify || status.PendingDelete
}
// VifInfoByVif looks up based on the name aka Vif
func (status DomainStatus) VifInfoByVif(vif string) *VifInfo {
for i := range status.VifList {
net := &status.VifList[i]
if net.Vif == vif {
return net
}
}
return nil
}
// LogCreate :
func (status DomainStatus) LogCreate(logBase *base.LogObject) {
logObject := base.NewLogObject(logBase, base.DomainStatusLogType, status.DisplayName,
status.UUIDandVersion.UUID, status.LogKey())
if logObject == nil {
return
}
logObject.CloneAndAddField("state", status.State.String()).
AddField("activated-bool", status.Activated).
Noticef("domain status create")
}
// LogModify :
func (status DomainStatus) LogModify(logBase *base.LogObject, old interface{}) {
logObject := base.EnsureLogObject(logBase, base.DomainStatusLogType, status.DisplayName,
status.UUIDandVersion.UUID, status.LogKey())
oldStatus, ok := old.(DomainStatus)
if !ok {
logObject.Clone().Fatalf("LogModify: Old object interface passed is not of DomainStatus type")
}
if oldStatus.State != status.State ||
oldStatus.Activated != status.Activated {
logObject.CloneAndAddField("state", status.State.String()).
AddField("activated-bool", status.Activated).
AddField("old-state", oldStatus.State.String()).
AddField("old-activated-bool", oldStatus.Activated).
Noticef("domain status modify")
} else {
// XXX remove?
logObject.CloneAndAddField("diff", cmp.Diff(oldStatus, status)).
Noticef("domain status modify other change")
}
if status.HasError() {
errAndTime := status.ErrorAndTime
logObject.CloneAndAddField("state", status.State.String()).
AddField("activated-bool", status.Activated).
AddField("error", errAndTime.Error).
AddField("error-time", errAndTime.ErrorTime).
Noticef("domain status modify")
}
}
// LogDelete :
func (status DomainStatus) LogDelete(logBase *base.LogObject) {
logObject := base.EnsureLogObject(logBase, base.DomainStatusLogType, status.DisplayName,
status.UUIDandVersion.UUID, status.LogKey())
logObject.CloneAndAddField("state", status.State.String()).
AddField("activated-bool", status.Activated).
Noticef("domain status delete")
base.DeleteLogObject(logBase, status.LogKey())
}
// LogKey :
func (status DomainStatus) LogKey() string {
return string(base.DomainStatusLogType) + "-" + status.Key()
}
// VlanInfo : applicable only for VIFs inside switch network instances.
type VlanInfo struct {
Start uint32
End uint32
IsTrunk bool
}
// VifConfig configure vif
type VifConfig struct {
Bridge string
Vif string
Mac net.HardwareAddr
MTU uint16
// PodVif is only valid in the Kubernetes mode.
PodVif PodVIF
// Interface order across both VIFs and directly attached network devices.
// Note that we cannot use attribute name "IntfOrder" here, otherwise it would
// overlap with IntfOrder from AppNetAdapterConfig inside AppNetAdapterStatus.
VifOrder uint32
}
// PodVIF : configuration parameters for VIF connecting Kubernetes pod with the host.
type PodVIF struct {
GuestIfName string
IPAM cnirpc.PodIPAMConfig
}
// VifInfo store info about vif
type VifInfo struct {
VifConfig
VifUsed string // Has -emu in name in Status if appropriate
}
// DomainManager will pass these to the xen xl config file
// The vdev is automatically assigned as xvd[x], where X is a, b, c etc,
// based on the order in the DiskList
// Note that vdev in general can be hd[x], xvd[x], sd[x] but here we only
// use xvd
type DiskConfig struct {
VolumeKey string
FileLocation string // Location of the volume
ReadOnly bool
Format zconfig.Format
MountDir string
DisplayName string
WWN string
Target zconfig.Target
CustomMeta string
}
type DiskStatus struct {
VolumeKey string
ReadOnly bool
FileLocation string // From DiskConfig
Format zconfig.Format
MountDir string
DisplayName string
Devtype string // XXX used internally by hypervisor; deprecate?
Vdev string // Allocated
WWN string
CustomMeta string
}
// DomainMetric carries CPU and memory usage. UUID=devUUID for the dom0/host metrics overhead
type DomainMetric struct {
UUIDandVersion UUIDandVersion
CPUTotalNs uint64 // Nanoseconds since Domain boot scaled by #CPUs
CPUScaled uint32 // The scale factor which was applied
AllocatedMB uint32
UsedMemory uint32 // in MB
MaxUsedMemory uint32 // in MB
AvailableMemory uint32 // in MB
UsedMemoryPercent float64
LastHeard time.Time
Activated bool
NodeName string // the name of the kubernetes node on which the app is currently running
}
// Key returns the key for pubsub
func (metric DomainMetric) Key() string {
return metric.UUIDandVersion.UUID.String()
}
// LogCreate :
func (metric DomainMetric) LogCreate(logBase *base.LogObject) {
logObject := base.NewLogObject(logBase, base.DomainMetricLogType, "",
metric.UUIDandVersion.UUID, metric.LogKey())
if logObject == nil {
return
}
logObject.Metricf("Domain metric create")
}
// LogModify :
func (metric DomainMetric) LogModify(logBase *base.LogObject, old interface{}) {
logObject := base.EnsureLogObject(logBase, base.DomainMetricLogType, "",
metric.UUIDandVersion.UUID, metric.LogKey())
oldMetric, ok := old.(DomainMetric)
if !ok {
logObject.Clone().Fatalf("LogModify: Old object interface passed is not of DomainMetric type")
}
// XXX remove? XXX huge?
logObject.CloneAndAddField("diff", cmp.Diff(oldMetric, metric)).
Metricf("Domain metric modify")
}
// LogDelete :
func (metric DomainMetric) LogDelete(logBase *base.LogObject) {
logObject := base.EnsureLogObject(logBase, base.DomainMetricLogType, "",
metric.UUIDandVersion.UUID, metric.LogKey())
logObject.Metricf("Domain metric delete")
base.DeleteLogObject(logBase, metric.LogKey())
}
// LogKey :
func (metric DomainMetric) LogKey() string {
return string(base.DomainMetricLogType) + "-" + metric.Key()
}
// HostMemory reports global stats. Published under "global" key
// Note that Ncpus is the set of physical CPUs which is different
// than the set of CPUs assigned to dom0
type HostMemory struct {
TotalMemoryMB uint64
FreeMemoryMB uint64
UsedEveMB uint64
KmemUsedEveMB uint64
Ncpus uint32
}
// Key returns the key for pubsub
func (hm HostMemory) Key() string {
return "global"
}
// LogCreate :
func (hm HostMemory) LogCreate(logBase *base.LogObject) {
logObject := base.NewLogObject(logBase, base.HostMemoryLogType, "",
nilUUID, hm.LogKey())
if logObject == nil {
return
}
logObject.Metricf("Host memory create")
}
// LogModify :
func (hm HostMemory) LogModify(logBase *base.LogObject, old interface{}) {
logObject := base.EnsureLogObject(logBase, base.HostMemoryLogType, "",
nilUUID, hm.LogKey())
oldHm, ok := old.(HostMemory)
if !ok {
logObject.Clone().Fatalf("LogModify: Old object interface passed is not of HostMemory type")
}
// XXX remove?
logObject.CloneAndAddField("diff", cmp.Diff(oldHm, hm)).
Metricf("Host memory modify")
}
// LogDelete :
func (hm HostMemory) LogDelete(logBase *base.LogObject) {
logObject := base.EnsureLogObject(logBase, base.HostMemoryLogType, "",
nilUUID, hm.LogKey())
logObject.Metricf("Host memory delete")
base.DeleteLogObject(logBase, hm.LogKey())
}
// LogKey :
func (hm HostMemory) LogKey() string {
return string(base.HostMemoryLogType) + "-" + hm.Key()
}
// Capabilities represents device information
type Capabilities struct {
HWAssistedVirtualization bool // VMX/SVM for amd64 or Arm virtualization extensions for arm64
IOVirtualization bool // I/O Virtualization support
CPUPinning bool // CPU Pinning support
UseVHost bool // vHost support
}
// WatchdogParam is used in some proc functions that have a timeout,
// to tell the watchdog agent is still alive.
type WatchdogParam struct {
Ps *pubsub.PubSub
AgentName string
WarnTime time.Duration
ErrTime time.Duration
}