Skip to content

Commit

Permalink
r/virtual_machine: Fix template UUID lookup for older vSphere versions
Browse files Browse the repository at this point in the history
Historically, the FindByUuid method under SearchIndex did not support
looking up VMs marked as template. However, at some point in time, this
was changed (possibly vSphere 6.5, based on bug reports), and any
mention of the UUID search not supporting templates was removed from the
API documentation, without a mention of when support for templates was
introduced. Since this is the method that we use to look up both VMs and
templates, this means that templates have not been functional for
vSphere <= 6.0 users since the resource was re-written in 1.0.

There has been a workaround in that the source template is just
converted back to virtual machine, but this update fixes it so that on
versions of vSphere older than 6.5, we fall back to using ContainerView
with a filter on the UUID. This works for all versions of vSphere. We
keep FindByUuid for 6.5 as it may possibly be more direct path.
  • Loading branch information
vancluever committed Jan 29, 2018
1 parent a4bccbf commit 18c73ab
Showing 1 changed file with 79 additions and 8 deletions.
87 changes: 79 additions & 8 deletions vsphere/internal/helper/virtualmachine/virtual_machine_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,26 @@ import (
"github.com/terraform-providers/terraform-provider-vsphere/vsphere/internal/helper/folder"
"github.com/terraform-providers/terraform-provider-vsphere/vsphere/internal/helper/provider"
"github.com/terraform-providers/terraform-provider-vsphere/vsphere/internal/helper/structure"
"github.com/terraform-providers/terraform-provider-vsphere/vsphere/internal/helper/viapi"
"github.com/vmware/govmomi"
"github.com/vmware/govmomi/find"
"github.com/vmware/govmomi/object"
"github.com/vmware/govmomi/property"
"github.com/vmware/govmomi/view"
"github.com/vmware/govmomi/vim25/mo"
"github.com/vmware/govmomi/vim25/types"
)

var errGuestShutdownTimeout = errors.New("the VM did not power off within the specified amount of time")

// vmUUIDSearchIndexVersion denotes the minimum version we use the SearchIndex
// VM UUID search for. All versions lower than this use ContainerView to find
// the VM.
var vmUUIDSearchUseContainerVersion = viapi.VSphereVersion{
Major: 6,
Minor: 5,
}

// UUIDNotFoundError is an error type that is returned when a
// virtual machine could not be found by UUID.
type UUIDNotFoundError struct {
Expand All @@ -43,17 +53,20 @@ func newUUIDNotFoundError(s string) *UUIDNotFoundError {
// FromUUID locates a virtualMachine by its UUID.
func FromUUID(client *govmomi.Client, uuid string) (*object.VirtualMachine, error) {
log.Printf("[DEBUG] Locating virtual machine with UUID %q", uuid)
search := object.NewSearchIndex(client.Client)

ctx, cancel := context.WithTimeout(context.Background(), provider.DefaultAPITimeout)
defer cancel()
result, err := search.FindByUuid(ctx, nil, uuid, true, structure.BoolPtr(false))
if err != nil {
return nil, err
var result object.Reference
var err error
version := viapi.ParseVersionFromClient(client)
expected := vmUUIDSearchUseContainerVersion
expected.Product = version.Product
if version.Older(expected) {
result, err = virtualMachineFromContainerView(client, uuid)
} else {
result, err = virtualMachineFromSearchIndex(client, uuid)
}

if result == nil {
return nil, newUUIDNotFoundError(fmt.Sprintf("virtual machine with UUID %q not found", uuid))
if err != nil {
return nil, err
}

// We need to filter our object through finder to ensure that the
Expand All @@ -75,6 +88,64 @@ func FromUUID(client *govmomi.Client, uuid string) (*object.VirtualMachine, erro
return vm.(*object.VirtualMachine), nil
}

// virtualMachineFromSearchIndex gets the virtual machine reference via the
// SearchIndex MO and is the method used to fetch UUIDs on newer versions of
// vSphere.
func virtualMachineFromSearchIndex(client *govmomi.Client, uuid string) (object.Reference, error) {
log.Printf("[DEBUG] Using SearchIndex to look up UUID %q", uuid)
search := object.NewSearchIndex(client.Client)
ctx, cancel := context.WithTimeout(context.Background(), provider.DefaultAPITimeout)
defer cancel()
result, err := search.FindByUuid(ctx, nil, uuid, true, structure.BoolPtr(false))
if err != nil {
return nil, err
}

if result == nil {
return nil, newUUIDNotFoundError(fmt.Sprintf("virtual machine with UUID %q not found", uuid))
}

return result, nil
}

// virtualMachineFromContainerView is a compatability method that is
// used when the version of vSphere is too old to support using SearchIndex's
// FindByUuid method correctly. This is mainly to facilitate the ability to use
// FromUUID to find both templates in addition to virtual machines, which
// historically was not supported by FindByUuid.
func virtualMachineFromContainerView(client *govmomi.Client, uuid string) (object.Reference, error) {
log.Printf("[DEBUG] Using ContainerView to look up UUID %q", uuid)
m := view.NewManager(client.Client)

vctx, vcancel := context.WithTimeout(context.Background(), provider.DefaultAPITimeout)
defer vcancel()
v, err := m.CreateContainerView(vctx, client.ServiceContent.RootFolder, []string{"VirtualMachine"}, true)
if err != nil {
return nil, err
}

defer func() {
dctx, dcancel := context.WithTimeout(context.Background(), provider.DefaultAPITimeout)
defer dcancel()
v.Destroy(dctx)
}()

var vms []mo.VirtualMachine
err = v.RetrieveWithFilter(vctx, []string{"VirtualMachine"}, []string{"summary"}, &vms, property.Filter{"config.uuid": uuid})
if err != nil {
return nil, err
}

switch {
case len(vms) < 1:
return nil, newUUIDNotFoundError(fmt.Sprintf("virtual machine with UUID %q not found", uuid))
case len(vms) > 1:
return nil, fmt.Errorf("multiple virtual machines with UUID %q found", uuid)
}

return object.NewReference(client.Client, vms[0].Self), nil
}

// FromMOID locates a virtualMachine by its managed
// object reference ID.
func FromMOID(client *govmomi.Client, id string) (*object.VirtualMachine, error) {
Expand Down

0 comments on commit 18c73ab

Please # to comment.