mirror of https://github.com/k3s-io/k3s
Fixes #40819
Start looking up the virtual machine by it's UUID in vSphere again. Looking up by IP address is problematic and can either not return a VM entirely, or could return the wrong VM. Retrieves the VM's UUID in one of two methods - either by a `vm-uuid` entry in the cloud config file on the VM, or via sysfs. The sysfs route requires root access, but restores the previous functionality. Multiple VMs in a vCenter cluster can share an IP address - for example, if you have multiple VM networks, but they're all isolated and use the same address range. Additionally, flannel network address ranges can overlap. vSphere seems to have a limitation of reporting no more than 16 interfaces from a virtual machine, so it's possible that the IP address list on a VM is completely untrustworthy anyhow - it can either be empty (because the 16 interfaces it found were veth interfaces with no IP address), or it can report the flannel IP.pull/6/head
parent
c26bd88620
commit
53a009302a
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
Loading…
Reference in New Issue