Make a vSphere cluster the failure_zone

* 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:
Vipul Sabhaya 2016-08-18 11:09:57 -07:00 committed by Vipul Sabhaya
parent 1b0bc9421f
commit 808f18439d
2 changed files with 47 additions and 15 deletions

View File

@ -72,6 +72,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 {
@ -126,17 +128,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
@ -146,7 +148,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)
@ -156,7 +158,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)
@ -166,7 +168,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.
@ -176,19 +178,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
}
@ -205,6 +225,7 @@ func newVSphere(cfg VSphereConfig) (*VSphere, error) {
vs := VSphere{
cfg: &cfg,
localInstanceID: id,
clusterName: cluster,
}
return &vs, nil
}
@ -498,9 +519,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) {