forked from dmacvicar/terraform-provider-libvirt
-
Notifications
You must be signed in to change notification settings - Fork 0
/
utils_domain_def.go
157 lines (135 loc) · 4.11 KB
/
utils_domain_def.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
package libvirt
import (
"encoding/xml"
"fmt"
"log"
"strings"
libvirt "github.com/digitalocean/go-libvirt"
"libvirt.org/go/libvirtxml"
)
func getGuestForArchType(caps libvirtxml.Caps, arch string, virttype string) (libvirtxml.CapsGuest, error) {
for _, guest := range caps.Guests {
log.Printf("[TRACE] Checking for %s/%s against %s/%s\n", arch, virttype, guest.Arch.Name, guest.OSType)
if guest.Arch.Name == arch && guest.OSType == virttype {
log.Printf("[DEBUG] Found %d machines in guest for %s/%s", len(guest.Arch.Machines), arch, virttype)
return guest, nil
}
}
return libvirtxml.CapsGuest{}, fmt.Errorf("[DEBUG] Could not find any guests for architecure type %s/%s", virttype, arch)
}
func lookupMachine(machines []libvirtxml.CapsGuestMachine, targetmachine string) string {
for _, machine := range machines {
if machine.Name == targetmachine {
if machine.Canonical != "" {
return machine.Canonical
}
return machine.Name
}
}
return ""
}
func getCanonicalMachineName(caps libvirtxml.Caps, arch string, virttype string, targetmachine string) (string, error) {
guest, err := getGuestForArchType(caps, arch, virttype)
if err != nil {
return "", err
}
/* Machine entries can be in the guest.Arch.Machines level as well as
under each guest.Arch.Domains[].Machines */
name := lookupMachine(guest.Arch.Machines, targetmachine)
if name != "" {
return name, nil
}
for _, domain := range guest.Arch.Domains {
name := lookupMachine(domain.Machines, targetmachine)
if name != "" {
return name, nil
}
}
return "", fmt.Errorf("[WARN] Cannot find machine type %s for %s/%s in %v", targetmachine, virttype, arch, caps)
}
func getOriginalMachineName(caps libvirtxml.Caps, arch string, virttype string, targetmachine string) (string, error) {
guest, err := getGuestForArchType(caps, arch, virttype)
if err != nil {
return "", err
}
for _, machine := range guest.Arch.Machines {
if machine.Canonical != "" && machine.Canonical == targetmachine {
return machine.Name, nil
}
}
return targetmachine, nil // There wasn't a canonical mapping to this
}
// as kernal args allow duplicate keys, we use a list of maps
// we jump to a next map as soon as we find a duplicate
// key
func splitKernelCmdLine(cmdLine string) ([]map[string]string, error) {
var cmdLines []map[string]string
if len(cmdLine) == 0 {
return cmdLines, nil
}
currCmdLine := make(map[string]string)
keylessCmdLineArgs := []string{}
argVals := strings.Split(cmdLine, " ")
for _, argVal := range argVals {
if !strings.Contains(argVal, "=") {
// keyless cmd line (eg: nosplash)
keylessCmdLineArgs = append(keylessCmdLineArgs, argVal)
continue
}
kv := strings.SplitN(argVal, "=", 2)
k, v := kv[0], kv[1]
// if the key is duplicate, start a new map
if _, ok := currCmdLine[k]; ok {
cmdLines = append(cmdLines, currCmdLine)
currCmdLine = make(map[string]string)
}
currCmdLine[k] = v
}
if len(currCmdLine) > 0 {
cmdLines = append(cmdLines, currCmdLine)
}
if len(keylessCmdLineArgs) > 0 {
cl := make(map[string]string)
cl["_"] = strings.Join(keylessCmdLineArgs, " ")
cmdLines = append(cmdLines, cl)
}
return cmdLines, nil
}
func getHostArchitecture(virConn *libvirt.Libvirt) (string, error) {
type HostCapabilities struct {
XMLName xml.Name `xml:"capabilities"`
Host struct {
XMLName xml.Name `xml:"host"`
CPU struct {
XMLName xml.Name `xml:"cpu"`
Arch string `xml:"arch"`
}
}
}
info, err := virConn.Capabilities()
if err != nil {
return "", err
}
capabilities := HostCapabilities{}
err = xml.Unmarshal([]byte(info), &capabilities)
if err != nil {
return "", err
}
return capabilities.Host.CPU.Arch, nil
}
//
func getHostCapabilities(virConn *libvirt.Libvirt) (libvirtxml.Caps, error) {
// We should perhaps think of storing this on the connect object
// on first call to avoid the back and forth
caps := libvirtxml.Caps{}
capsXML, err := virConn.Capabilities()
if err != nil {
return caps, err
}
err = xml.Unmarshal([]byte(capsXML), &caps)
if err != nil {
return caps, err
}
log.Printf("[TRACE] Capabilities of host \n %+v", caps)
return caps, nil
}