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
// InstanceID of the server where this VSphere object is instantiated.
localInstanceID string
// Cluster that VirtualMachine belongs to
clusterName string
}
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.
// 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()
if err != nil {
return "", err
return "", "", err
}
if len(addrs) == 0 {
return "", fmt.Errorf("unable to retrieve Instance ID")
return "", "", fmt.Errorf("unable to retrieve Instance ID")
}
// Create context
@ -168,7 +170,7 @@ func readInstanceID(cfg *VSphereConfig) (string, error) {
// Create vSphere client
c, err := vsphereLogin(cfg, ctx)
if err != nil {
return "", err
return "", "", err
}
defer c.Logout(ctx)
@ -178,7 +180,7 @@ func readInstanceID(cfg *VSphereConfig) (string, error) {
// Fetch and set data center
dc, err := f.Datacenter(ctx, cfg.Global.Datacenter)
if err != nil {
return "", err
return "", "", err
}
f.SetDatacenter(dc)
@ -188,7 +190,7 @@ func readInstanceID(cfg *VSphereConfig) (string, error) {
for _, v := range addrs {
ip, _, err := net.ParseCIDR(v.String())
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.
@ -198,19 +200,37 @@ func readInstanceID(cfg *VSphereConfig) (string, error) {
}
}
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
err = s.Properties(ctx, svm.Reference(), []string{"name"}, &vm)
err = s.Properties(ctx, svm.Reference(), []string{"name", "resourcePool"}, &vm)
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) {
id, err := readInstanceID(&cfg)
id, cluster, err := readInstance(&cfg)
if err != nil {
return nil, err
}
@ -227,6 +247,7 @@ func newVSphere(cfg VSphereConfig) (*VSphere, error) {
vs := VSphere{
cfg: &cfg,
localInstanceID: id,
clusterName: cluster,
}
return &vs, nil
}
@ -520,9 +541,14 @@ func (vs *VSphere) Zones() (cloudprovider.Zones, bool) {
}
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.

View File

@ -126,10 +126,12 @@ func TestVSphereLogin(t *testing.T) {
func TestZones(t *testing.T) {
cfg := VSphereConfig{}
cfg.Global.Datacenter = "myDatacenter"
failureZone := "myCluster"
// Create vSphere configuration object
vs := VSphere{
cfg: &cfg,
cfg: &cfg,
clusterName: failureZone,
}
z, ok := vs.Zones()
@ -145,6 +147,10 @@ func TestZones(t *testing.T) {
if zone.Region != vs.cfg.Global.Datacenter {
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) {