forked from linuxkit/linuxkit
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathprovider_vmware.go
137 lines (112 loc) · 3.35 KB
/
provider_vmware.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
//go:build linux && 386 && amd64
package main
import (
"compress/gzip"
"encoding/base64"
"fmt"
"io/ioutil"
"path"
"strings"
log "github.com/sirupsen/logrus"
"github.com/vmware/vmw-guestinfo/rpcvmx"
"github.com/vmware/vmw-guestinfo/vmcheck"
)
const (
guestMetaData = "guestinfo.metadata"
guestUserData = "guestinfo.userdata"
guestVendorData = "guestinfo.vendordata"
)
// ProviderVMware implements the Provider interface for VMware guestinfo api
type ProviderVMware struct{}
// NewVMware returns a new VMware Provider
func NewVMware() *ProviderVMware {
return &ProviderVMware{}
}
// String returns provider name
func (p *ProviderVMware) String() string {
return "VMWARE"
}
// Probe checks if we are running on VMware and either userdata or metadata is set
func (p *ProviderVMware) Probe() bool {
isVM, err := vmcheck.IsVirtualWorld()
if err != nil || !isVM {
return false
}
md, merr := vmwareGet(guestMetaData)
ud, uerr := vmwareGet(guestUserData)
return ((merr == nil) && len(md) > 1 && string(md) != "---") || ((uerr == nil) && len(ud) > 1 && string(ud) != "---")
}
// Extract gets the host specific metadata, generic userdata and if set vendordata
// This function returns error if it fails to write metadata or vendordata to disk
func (p *ProviderVMware) Extract() ([]byte, error) {
// Get vendor data, if empty do not fail
vendorData, err := vmwareGet(guestVendorData)
if err != nil {
log.Debugf("VMWare: Failed to get vendordata: %v", err)
} else {
err = ioutil.WriteFile(path.Join(ConfigPath, "vendordata"), vendorData, 0644)
if err != nil {
log.Debugf("VMWare: Failed to write vendordata: %v", err)
}
}
// Get metadata
metaData, err := vmwareGet(guestMetaData)
if err != nil {
log.Printf("VMWare: Failed to get metadata: %v", err)
} else {
err = ioutil.WriteFile(path.Join(ConfigPath, "metadata"), metaData, 0644)
if err != nil {
return nil, fmt.Errorf("VMWare: Failed to write metadata: %s", err)
}
}
// Get userdata
userData, err := vmwareGet(guestUserData)
if err != nil {
log.Printf("VMware: Failed to get userdata: %v", err)
// This is not an error
return nil, nil
}
return userData, nil
}
// vmwareGet gets and extracts the guestinfo data
func vmwareGet(name string) ([]byte, error) {
config := rpcvmx.NewConfig()
// get the gusest info value
out, err := config.String(name, "")
if err != nil {
log.Debugf("Getting guest info %s failed: error %s", name, err)
return nil, err
}
enc, err := config.String(name+".encoding", "")
if err != nil {
log.Debugf("Getting guest info %s.encoding failed: error %s", name, err)
return nil, err
}
switch strings.TrimSuffix(enc, "\n") {
case " ":
return []byte(strings.TrimSuffix(out, "\n")), nil
case "base64":
r := base64.NewDecoder(base64.StdEncoding, strings.NewReader(out))
dst, err := ioutil.ReadAll(r)
if err != nil {
log.Debugf("Decoding base64 of '%s' failed %v", name, err)
return nil, err
}
return dst, nil
case "gzip+base64":
r := base64.NewDecoder(base64.StdEncoding, strings.NewReader(out))
zr, err := gzip.NewReader(r)
if err != nil {
log.Debugf("New gzip reader from '%s' failed %v", name, err)
return nil, err
}
dst, err := ioutil.ReadAll(zr)
if err != nil {
log.Debugf("Read '%s' failed %v", name, err)
return nil, err
}
return dst, nil
default:
return nil, fmt.Errorf("Unknown encoding %s", string(enc))
}
}