-
Notifications
You must be signed in to change notification settings - Fork 445
/
data_source_vsphere_virtual_machine.go
288 lines (269 loc) · 9.84 KB
/
data_source_vsphere_virtual_machine.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
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package vsphere
import (
"fmt"
"log"
"path"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
"github.com/hashicorp/terraform-provider-vsphere/vsphere/internal/helper/folder"
"github.com/hashicorp/terraform-provider-vsphere/vsphere/internal/helper/structure"
"github.com/hashicorp/terraform-provider-vsphere/vsphere/internal/helper/virtualmachine"
"github.com/hashicorp/terraform-provider-vsphere/vsphere/internal/virtualdevice"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/vim25/types"
)
func dataSourceVSphereVirtualMachine() *schema.Resource {
s := map[string]*schema.Schema{
"datacenter_id": {
Type: schema.TypeString,
Description: "The managed object ID of the datacenter the virtual machine is in. This is not required when using ESXi directly, or if there is only one datacenter in your infrastructure.",
Optional: true,
},
"folder": {
Type: schema.TypeString,
Optional: true,
Description: "The name of the folder the virtual machine is in. Allows distinguishing virtual machines with the same name in different folder paths",
StateFunc: folder.NormalizePath,
ConflictsWith: []string{"uuid", "moid"},
},
"scsi_controller_scan_count": {
Type: schema.TypeInt,
Description: "The number of SCSI controllers to scan for disk sizes and controller types on.",
Optional: true,
Default: 1,
},
"sata_controller_scan_count": {
Type: schema.TypeInt,
Description: "The number of SATA controllers to scan for disk sizes and controller types on.",
Optional: true,
Default: 0,
},
"ide_controller_scan_count": {
Type: schema.TypeInt,
Description: "The number of IDE controllers to scan for disk sizes and controller types on.",
Optional: true,
Default: 2,
},
"scsi_type": {
Type: schema.TypeString,
Computed: true,
Description: "The common SCSI bus type of all controllers on the virtual machine.",
},
"scsi_bus_sharing": {
Type: schema.TypeString,
Computed: true,
Description: "Mode for sharing the SCSI bus.",
},
"disks": {
Type: schema.TypeList,
Description: "Select configuration attributes from the disks on this virtual machine, sorted by bus and unit number.",
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"size": {
Type: schema.TypeInt,
Computed: true,
},
"eagerly_scrub": {
Type: schema.TypeBool,
Computed: true,
},
"thin_provisioned": {
Type: schema.TypeBool,
Computed: true,
},
"label": {
Type: schema.TypeString,
Computed: true,
},
"unit_number": {
Type: schema.TypeInt,
Computed: true,
},
},
},
},
"network_interface_types": {
Type: schema.TypeList,
Description: "The types of network interfaces found on the virtual machine, sorted by unit number.",
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"network_interfaces": {
Type: schema.TypeList,
Description: "The types of network interfaces found on the virtual machine, sorted by unit number.",
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"adapter_type": {
Type: schema.TypeString,
Computed: true,
},
"physical_function": {
Type: schema.TypeString,
Computed: true,
Description: "The ID of the Physical SR-IOV NIC to attach to, e.g. '0000:d8:00.0'",
},
"bandwidth_limit": {
Type: schema.TypeInt,
Optional: true,
Default: -1,
Description: "The upper bandwidth limit of this network interface, in Mbits/sec.",
ValidateFunc: validation.IntAtLeast(-1),
},
"bandwidth_reservation": {
Type: schema.TypeInt,
Optional: true,
Default: 0,
Description: "The bandwidth reservation of this network interface, in Mbits/sec.",
ValidateFunc: validation.IntAtLeast(0),
},
"bandwidth_share_level": {
Type: schema.TypeString,
Optional: true,
Default: string(types.SharesLevelNormal),
Description: "The bandwidth share allocation level for this interface. Can be one of low, normal, high, or custom.",
ValidateFunc: validation.StringInSlice(sharesLevelAllowedValues, false),
},
"bandwidth_share_count": {
Type: schema.TypeInt,
Optional: true,
Computed: true,
Description: "The share count for this network interface when the share level is custom.",
ValidateFunc: validation.IntAtLeast(0),
},
"mac_address": {
Type: schema.TypeString,
Computed: true,
},
"network_id": {
Type: schema.TypeString,
Computed: true,
},
},
},
},
"default_ip_address": {
Type: schema.TypeString,
Computed: true,
Description: "The default IP address.",
},
"guest_ip_addresses": {
Type: schema.TypeList,
Description: "The current list of IP addresses on this virtual machine.",
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"instance_uuid": {
Type: schema.TypeString,
Computed: true,
Description: "Instance UUID of this virtual machine.",
},
}
// Merge the VirtualMachineConfig structure so that we can include the number of
// include the number of cpus, memory, firmware, disks, etc.
structure.MergeSchema(s, schemaVirtualMachineConfigSpec())
// make name/uuid/moid Optional/AtLeastOneOf
s["name"].Required = false
s["name"].Optional = true
s["name"].AtLeastOneOf = []string{"name", "uuid", "moid"}
s["uuid"].Required = false
s["uuid"].Optional = true
s["uuid"].AtLeastOneOf = []string{"name", "uuid", "moid"}
s["moid"].Required = false
s["moid"].Optional = true
s["moid"].AtLeastOneOf = []string{"name", "uuid", "moid"}
// Now that the schema has been composed and merged, we can attach our reader and
// return the resource back to our host process.
return &schema.Resource{
Read: dataSourceVSphereVirtualMachineRead,
Schema: s,
}
}
func dataSourceVSphereVirtualMachineRead(d *schema.ResourceData, meta interface{}) error {
client := meta.(*Client).vimClient
uuid := d.Get("uuid").(string)
moid := d.Get("moid").(string)
name := d.Get("name").(string)
folderName := d.Get("folder").(string)
var vm *object.VirtualMachine
var err error
if uuid != "" {
log.Printf("[DEBUG] Looking for VM or template by UUID %q", uuid)
vm, err = virtualmachine.FromUUID(client, uuid)
} else if moid != "" {
log.Printf("[DEBUG] Looking for VM or template by MOID %q", moid)
vm, err = virtualmachine.FromMOID(client, moid)
} else {
log.Printf("[DEBUG] Looking for VM or template by name/path %q", name)
var dc *object.Datacenter
if dcID, ok := d.GetOk("datacenter_id"); ok {
dc, err = datacenterFromID(client, dcID.(string))
if err != nil {
return fmt.Errorf("cannot locate datacenter: %s", err)
}
log.Printf("[DEBUG] Datacenter for VM/template search: %s", dc.InventoryPath)
}
searchPath := name
if len(folderName) > 0 {
searchPath = path.Join(folderName, name)
}
vm, err = virtualmachine.FromPath(client, searchPath, dc)
}
if err != nil {
return fmt.Errorf("error fetching virtual machine: %s", err)
}
// Set the managed object id.
d.Set("moid", vm.Reference().Value)
props, err := virtualmachine.Properties(vm)
if err != nil {
return fmt.Errorf("error fetching virtual machine properties: %s", err)
}
if props.Config == nil {
return fmt.Errorf("no configuration returned for virtual machine %q", vm.InventoryPath)
}
if props.Config.Uuid == "" {
return fmt.Errorf("virtual machine %q does not have a UUID", vm.InventoryPath)
}
// Read general VM config info
if err := flattenVirtualMachineConfigInfo(d, props.Config, client); err != nil {
return fmt.Errorf("error reading virtual machine configuration: %s", err)
}
d.SetId(props.Config.Uuid)
_ = d.Set("guest_id", props.Config.GuestId)
_ = d.Set("alternate_guest_name", props.Config.AlternateGuestName)
_ = d.Set("scsi_type", virtualdevice.ReadSCSIBusType(object.VirtualDeviceList(props.Config.Hardware.Device), d.Get("scsi_controller_scan_count").(int)))
_ = d.Set("scsi_bus_sharing", virtualdevice.ReadSCSIBusSharing(object.VirtualDeviceList(props.Config.Hardware.Device), d.Get("scsi_controller_scan_count").(int)))
_ = d.Set("firmware", props.Config.Firmware)
_ = d.Set("instance_uuid", props.Config.InstanceUuid)
disks, err := virtualdevice.ReadDiskAttrsForDataSource(object.VirtualDeviceList(props.Config.Hardware.Device), d)
if err != nil {
return fmt.Errorf("error reading disk sizes: %s", err)
}
nics, err := virtualdevice.ReadNetworkInterfaceTypes(object.VirtualDeviceList(props.Config.Hardware.Device))
if err != nil {
return fmt.Errorf("error reading network interface types: %s", err)
}
networkInterfaces, err := virtualdevice.ReadNetworkInterfaces(object.VirtualDeviceList(props.Config.Hardware.Device))
if err != nil {
return fmt.Errorf("error reading network interfaces: %s", err)
}
if err := d.Set("disks", disks); err != nil {
return fmt.Errorf("error setting disk sizes: %s", err)
}
if err := d.Set("network_interface_types", nics); err != nil {
return fmt.Errorf("error setting network interface types: %s", err)
}
if err := d.Set("network_interfaces", networkInterfaces); err != nil {
return fmt.Errorf("error setting network interfaces: %s", err)
}
if props.Guest != nil {
if err := buildAndSelectGuestIPs(d, *props.Guest); err != nil {
return fmt.Errorf("error setting guest IP addresses: %s", err)
}
}
log.Printf("[DEBUG] VM search for %q completed successfully (UUID %q)", name, props.Config.Uuid)
return nil
}