Merge pull request #30935 from vipulsabhaya/vsphere_zones

Automatic merge from submit-queue

Make a vSphere cluster the failure_zone

vSphere cloud provider returns the FailureZone as Cluster, if the VM belongs to a ResourcePool under a Cluster. 

fixes: #30933

* Currently the vSphere cloud provider treats Datacenter as the failure
  Zone.  This doesn't necessarily work since in the current implemention
  Kubernetes nodes cannot span Datacenters.
* This change introduces Clusters as the failure zone, while treating
  Datacenters as Regions
* Also updated tests for Zones
This commit is contained in:
Kubernetes Submit Queue 2016-09-05 18:57:45 -07:00 committed by GitHub
commit 2977d03bfe
2 changed files with 47 additions and 15 deletions

View File

@ -73,6 +73,8 @@ type VSphere struct {
cfg *VSphereConfig cfg *VSphereConfig
// InstanceID of the server where this VSphere object is instantiated. // InstanceID of the server where this VSphere object is instantiated.
localInstanceID string localInstanceID string
// Cluster that VirtualMachine belongs to
clusterName string
} }
type VSphereConfig struct { type VSphereConfig struct {
@ -148,17 +150,17 @@ func init() {
}) })
} }
// Returns the name of the VM on which this code is running. // Returns the name of the VM and its Cluster on which this code is running.
// This is done by searching for the name of virtual machine by current IP. // This is done by searching for the name of virtual machine by current IP.
// Prerequisite: this code assumes VMWare vmtools or open-vm-tools to be installed in the VM. // Prerequisite: this code assumes VMWare vmtools or open-vm-tools to be installed in the VM.
func readInstanceID(cfg *VSphereConfig) (string, error) { func readInstance(cfg *VSphereConfig) (string, string, error) {
addrs, err := net.InterfaceAddrs() addrs, err := net.InterfaceAddrs()
if err != nil { if err != nil {
return "", err return "", "", err
} }
if len(addrs) == 0 { if len(addrs) == 0 {
return "", fmt.Errorf("unable to retrieve Instance ID") return "", "", fmt.Errorf("unable to retrieve Instance ID")
} }
// Create context // Create context
@ -168,7 +170,7 @@ func readInstanceID(cfg *VSphereConfig) (string, error) {
// Create vSphere client // Create vSphere client
c, err := vsphereLogin(cfg, ctx) c, err := vsphereLogin(cfg, ctx)
if err != nil { if err != nil {
return "", err return "", "", err
} }
defer c.Logout(ctx) defer c.Logout(ctx)
@ -178,7 +180,7 @@ func readInstanceID(cfg *VSphereConfig) (string, error) {
// Fetch and set data center // Fetch and set data center
dc, err := f.Datacenter(ctx, cfg.Global.Datacenter) dc, err := f.Datacenter(ctx, cfg.Global.Datacenter)
if err != nil { if err != nil {
return "", err return "", "", err
} }
f.SetDatacenter(dc) f.SetDatacenter(dc)
@ -188,7 +190,7 @@ func readInstanceID(cfg *VSphereConfig) (string, error) {
for _, v := range addrs { for _, v := range addrs {
ip, _, err := net.ParseCIDR(v.String()) ip, _, err := net.ParseCIDR(v.String())
if err != nil { if err != nil {
return "", fmt.Errorf("unable to parse cidr from ip") return "", "", fmt.Errorf("unable to parse cidr from ip")
} }
// Finds a virtual machine or host by IP address. // Finds a virtual machine or host by IP address.
@ -198,19 +200,37 @@ func readInstanceID(cfg *VSphereConfig) (string, error) {
} }
} }
if svm == nil { if svm == nil {
return "", fmt.Errorf("unable to retrieve vm reference from vSphere") return "", "", fmt.Errorf("unable to retrieve vm reference from vSphere")
} }
var vm mo.VirtualMachine var vm mo.VirtualMachine
err = s.Properties(ctx, svm.Reference(), []string{"name"}, &vm) err = s.Properties(ctx, svm.Reference(), []string{"name", "resourcePool"}, &vm)
if err != nil { if err != nil {
return "", err return "", "", err
} }
return vm.Name, nil
var cluster string
if vm.ResourcePool != nil {
// Extract the Cluster Name if VM belongs to a ResourcePool
var rp mo.ResourcePool
err = s.Properties(ctx, *vm.ResourcePool, []string{"parent"}, &rp)
if err == nil {
var ccr mo.ClusterComputeResource
err = s.Properties(ctx, *rp.Parent, []string{"name"}, &ccr)
if err == nil {
cluster = ccr.Name
} else {
glog.Warningf("VM %s, does not belong to a vSphere Cluster, will not have FailureDomain label", vm.Name)
}
} else {
glog.Warningf("VM %s, does not belong to a vSphere Cluster, will not have FailureDomain label", vm.Name)
}
}
return vm.Name, cluster, nil
} }
func newVSphere(cfg VSphereConfig) (*VSphere, error) { func newVSphere(cfg VSphereConfig) (*VSphere, error) {
id, err := readInstanceID(&cfg) id, cluster, err := readInstance(&cfg)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -227,6 +247,7 @@ func newVSphere(cfg VSphereConfig) (*VSphere, error) {
vs := VSphere{ vs := VSphere{
cfg: &cfg, cfg: &cfg,
localInstanceID: id, localInstanceID: id,
clusterName: cluster,
} }
return &vs, nil return &vs, nil
} }
@ -520,9 +541,14 @@ func (vs *VSphere) Zones() (cloudprovider.Zones, bool) {
} }
func (vs *VSphere) GetZone() (cloudprovider.Zone, error) { func (vs *VSphere) GetZone() (cloudprovider.Zone, error) {
glog.V(4).Infof("Current zone is %v", vs.cfg.Global.Datacenter) glog.V(4).Infof("Current datacenter is %v, cluster is %v", vs.cfg.Global.Datacenter, vs.clusterName)
return cloudprovider.Zone{Region: vs.cfg.Global.Datacenter}, nil // The clusterName is determined from the VirtualMachine ManagedObjectReference during init
// If the VM is not created within a Cluster, this will return empty-string
return cloudprovider.Zone{
Region: vs.cfg.Global.Datacenter,
FailureDomain: vs.clusterName,
}, nil
} }
// Routes returns a false since the interface is not supported for vSphere. // Routes returns a false since the interface is not supported for vSphere.

View File

@ -126,10 +126,12 @@ func TestVSphereLogin(t *testing.T) {
func TestZones(t *testing.T) { func TestZones(t *testing.T) {
cfg := VSphereConfig{} cfg := VSphereConfig{}
cfg.Global.Datacenter = "myDatacenter" cfg.Global.Datacenter = "myDatacenter"
failureZone := "myCluster"
// Create vSphere configuration object // Create vSphere configuration object
vs := VSphere{ vs := VSphere{
cfg: &cfg, cfg: &cfg,
clusterName: failureZone,
} }
z, ok := vs.Zones() z, ok := vs.Zones()
@ -145,6 +147,10 @@ func TestZones(t *testing.T) {
if zone.Region != vs.cfg.Global.Datacenter { if zone.Region != vs.cfg.Global.Datacenter {
t.Fatalf("GetZone() returned wrong region (%s)", zone.Region) t.Fatalf("GetZone() returned wrong region (%s)", zone.Region)
} }
if zone.FailureDomain != failureZone {
t.Fatalf("GetZone() returned wrong Failure Zone (%s)", zone.FailureDomain)
}
} }
func TestInstances(t *testing.T) { func TestInstances(t *testing.T) {