This repository has been archived by the owner on Feb 27, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 18
/
migrate.go
130 lines (119 loc) · 3.46 KB
/
migrate.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
package vm
import "encoding/json"
// A migration upgrades machine definition from one version to the next
// these will be chained to ensure machine definitions are fully migrated.
//
// If migration fails, method should return nil.
var migrations = []func(map[string]interface{}) map[string]interface{}{
// Note: Array index must match with the version the function migrates from.
// All migrations must migrate to the next version, this way we only
// have to write one migration when we change the format.
migrate0to1,
// As a final step after migrations we validate against current schema and
// return nil, if it's not valid.
func(def map[string]interface{}) map[string]interface{} {
if MachineSchema.Validate(def) != nil {
return nil
}
return def
},
}
// MigrateMachineDefinition takes a machine definition and migrates it to the
// latest format version, and returns nil, if format is not supported.
func MigrateMachineDefinition(definition interface{}) interface{} {
def, ok := definition.(map[string]interface{})
if !ok {
return nil
}
version := 0 // default version from before we specified version numbers
if v, ok := def["version"]; ok {
if ver, ok := v.(float64); ok {
version = int(ver)
} else {
return nil
}
}
for i := version; i < len(migrations) && def != nil; i++ {
// Normalizing JSON
raw, _ := json.Marshal(def)
def = nil
if len(raw) == 0 || json.Unmarshal(raw, &def) != nil {
return nil
}
// Execution migration step
def = migrations[i](def)
}
return def
}
// Migrate version 0 -> version 1
func migrate0to1(def map[string]interface{}) map[string]interface{} {
// Note: version 0 did not carry a version number.
// machineV0 is an old machine definition no longer in use
type machineV0 struct {
UUID string `json:"uuid"`
Memory int `json:"memory,omitempty"`
CPU struct {
Threads int `json:"threads,omitempty"`
Cores int `json:"cores,omitempty"`
Sockets int `json:"sockets,omitempty"`
} `json:"cpu"`
Network struct {
Device string `json:"device"`
MAC string `json:"mac"`
} `json:"network"`
Keyboard struct {
Layout string `json:"layout"`
} `json:"keyboard"`
Sound *struct {
Device string `json:"device"`
Controller string `json:"controller"`
} `json:"sound,omitempty"`
}
// Parse JSON
raw, _ := json.Marshal(def)
var m machineV0
if len(raw) == 0 || json.Unmarshal(raw, &m) != nil {
return nil
}
// Construct sound definition
sound := "none"
if m.Sound != nil {
sound = m.Sound.Device
if m.Sound.Controller != "pci" {
sound += "/" + m.Sound.Controller
}
}
// Create result
result := map[string]interface{}{
"version": 1,
"uuid": m.UUID,
"chipset": "pc-i440fx-2.8",
"cpu": "host",
"threads": 1, // always default to 1
"flags": []interface{}{},
"usb": "nec-usb-xhci",
"network": "e1000",
"mac": m.Network.MAC,
"storage": "virtio-blk-pci",
"graphics": "vmware-svga",
"sound": sound,
"keyboard": "usb-kbd",
"keyboardLayout": m.Keyboard.Layout,
"mouse": "usb-mouse",
"tablet": "none",
}
// Add threads, cores, sockets, and memory if specified
if m.CPU.Threads != 0 {
result["threads"] = m.CPU.Threads
}
if m.CPU.Cores != 0 {
result["cores"] = m.CPU.Cores
}
if m.CPU.Sockets != 0 {
result["sockets"] = m.CPU.Sockets
}
if m.Memory != 0 {
result["memory"] = m.Memory
}
return result
}