diff --git a/pkg/cloudprovider/providers/vsphere/vsphere.go b/pkg/cloudprovider/providers/vsphere/vsphere.go index 6b14649b1d..60522b541a 100644 --- a/pkg/cloudprovider/providers/vsphere/vsphere.go +++ b/pkg/cloudprovider/providers/vsphere/vsphere.go @@ -20,7 +20,7 @@ import ( "errors" "fmt" "io" - "net" + "io/ioutil" "net/url" "path" "path/filepath" @@ -122,12 +122,17 @@ type VSphereConfig struct { WorkingDir string `gcfg:"working-dir"` // Soap round tripper count (retries = RoundTripper - 1) RoundTripperCount uint `gcfg:"soap-roundtrip-count"` + // VMUUID is the VM Instance UUID of virtual machine which can be retrieved from instanceUuid + // property in VmConfigInfo, or also set as vc.uuid in VMX file. + // If not set, will be fetched from the machine via sysfs (requires root) + VMUUID string `gcfg:"vm-uuid"` } Network struct { // PublicNetwork is name of the network the VMs are joined to. PublicNetwork string `gcfg:"public-network"` } + Disk struct { // SCSIControllerType defines SCSI controller to be used. SCSIControllerType string `dcfg:"scsicontrollertype"` @@ -201,14 +206,27 @@ func init() { // Returns the name of the VM on which this code is running. // Prerequisite: this code assumes VMWare vmtools or open-vm-tools to be installed in the VM. +// Will attempt to determine the machine's name via it's UUID in this precedence order, failing if neither have a UUID: +// * cloud config value VMUUID +// * sysfs entry func getVMName(client *govmomi.Client, cfg *VSphereConfig) (string, error) { - addrs, err := net.InterfaceAddrs() - if err != nil { - return "", err + var vmUUID string + + if cfg.Global.VMUUID != "" { + vmUUID = cfg.Global.VMUUID + } else { + // This needs root privileges on the host, and will fail otherwise. + vmUUIDbytes, err := ioutil.ReadFile("/sys/devices/virtual/dmi/id/product_uuid") + if err != nil { + return "", err + } + + vmUUID = string(vmUUIDbytes) + cfg.Global.VMUUID = vmUUID } - if len(addrs) == 0 { - return "", fmt.Errorf("unable to retrieve Instance ID") + if vmUUID == "" { + return "", fmt.Errorf("unable to determine machine ID from cloud configuration or sysfs") } // Create context @@ -227,28 +245,17 @@ func getVMName(client *govmomi.Client, cfg *VSphereConfig) (string, error) { s := object.NewSearchIndex(client.Client) - var svm object.Reference - for _, v := range addrs { - ip, _, err := net.ParseCIDR(v.String()) - if err != nil { - return "", fmt.Errorf("unable to parse cidr from ip") - } - - // Finds a virtual machine or host by IP address. - svm, err = s.FindByIp(ctx, dc, ip.String(), true) - if err == nil && svm != nil { - break - } - } - if svm == nil { - return "", fmt.Errorf("unable to retrieve vm reference from vSphere") - } - - var vm mo.VirtualMachine - err = s.Properties(ctx, svm.Reference(), []string{"name", "resourcePool"}, &vm) + svm, err := s.FindByUuid(ctx, dc, strings.ToLower(strings.TrimSpace(vmUUID)), true, nil) if err != nil { return "", err } + + var vm mo.VirtualMachine + err = s.Properties(ctx, svm.Reference(), []string{"name"}, &vm) + if err != nil { + return "", err + } + return vm.Name, nil } diff --git a/pkg/cloudprovider/providers/vsphere/vsphere_test.go b/pkg/cloudprovider/providers/vsphere/vsphere_test.go index b7bbdd7cc5..89903b639c 100644 --- a/pkg/cloudprovider/providers/vsphere/vsphere_test.go +++ b/pkg/cloudprovider/providers/vsphere/vsphere_test.go @@ -71,6 +71,7 @@ user = user password = password insecure-flag = true datacenter = us-west +vm-uuid = 1234 `)) if err != nil { t.Fatalf("Should succeed when a valid config is provided: %s", err) @@ -87,6 +88,10 @@ datacenter = us-west if cfg.Global.Datacenter != "us-west" { t.Errorf("incorrect datacenter: %s", cfg.Global.Datacenter) } + + if cfg.Global.VMUUID != "1234" { + t.Errorf("incorrect vm-uuid: %s", cfg.Global.VMUUID) + } } func TestNewVSphere(t *testing.T) {