Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Automated cherry pick of #40892 #41219

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
51 changes: 29 additions & 22 deletions pkg/cloudprovider/providers/vsphere/vsphere.go
Expand Up @@ -20,7 +20,7 @@ import (
"errors"
"fmt"
"io"
"net"
"io/ioutil"
"net/url"
"path"
"path/filepath"
Expand Down Expand Up @@ -97,12 +97,17 @@ type VSphereConfig struct {
Datastore string `gcfg:"datastore"`
// WorkingDir is path where VMs can be found.
WorkingDir string `gcfg:"working-dir"`
// 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"`
Expand Down Expand Up @@ -158,14 +163,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(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
Expand All @@ -191,28 +209,17 @@ func getVMName(cfg *VSphereConfig) (string, error) {

s := object.NewSearchIndex(c.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")
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", "resourcePool"}, &vm)
err = s.Properties(ctx, svm.Reference(), []string{"name"}, &vm)
if err != nil {
return "", err
}

return vm.Name, nil
}

Expand Down
5 changes: 5 additions & 0 deletions pkg/cloudprovider/providers/vsphere/vsphere_test.go
Expand Up @@ -69,6 +69,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)
Expand All @@ -85,6 +86,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) {
Expand Down