Use any host that mounts the datastore to create Volume

Also, This change makes zone to work per datacenter and cleans up dummy vms. There can be multiple datastores found for a given name. The datastore name is unique only within a datacenter. So this commit returns a list of datastores for a given datastore name in FindDatastoreByName() method. The calles are responsible to handle or find the right datastore to use among those returned.
parent d1c99590
...@@ -32,6 +32,7 @@ go_library( ...@@ -32,6 +32,7 @@ go_library(
"//staging/src/k8s.io/cloud-provider:go_default_library", "//staging/src/k8s.io/cloud-provider:go_default_library",
"//staging/src/k8s.io/cloud-provider/node/helpers:go_default_library", "//staging/src/k8s.io/cloud-provider/node/helpers:go_default_library",
"//staging/src/k8s.io/cloud-provider/volume/helpers:go_default_library", "//staging/src/k8s.io/cloud-provider/volume/helpers:go_default_library",
"//vendor/github.com/vmware/govmomi/find:go_default_library",
"//vendor/github.com/vmware/govmomi/object:go_default_library", "//vendor/github.com/vmware/govmomi/object:go_default_library",
"//vendor/github.com/vmware/govmomi/property:go_default_library", "//vendor/github.com/vmware/govmomi/property:go_default_library",
"//vendor/github.com/vmware/govmomi/vapi/rest:go_default_library", "//vendor/github.com/vmware/govmomi/vapi/rest:go_default_library",
......
...@@ -39,6 +39,11 @@ type NodeInfo struct { ...@@ -39,6 +39,11 @@ type NodeInfo struct {
zone *cloudprovider.Zone zone *cloudprovider.Zone
} }
func (n NodeInfo) String() string {
return fmt.Sprintf("{datacenter: %v, vm: %v, vcServer: %s, vmUUID: %s, zone: %v}",
*n.dataCenter, n.vm.Reference(), n.vcServer, n.vmUUID, *n.zone)
}
type NodeManager struct { type NodeManager struct {
// TODO: replace map with concurrent map when k8s supports go v1.9 // TODO: replace map with concurrent map when k8s supports go v1.9
......
...@@ -52,6 +52,7 @@ const ( ...@@ -52,6 +52,7 @@ const (
DatacenterType = "Datacenter" DatacenterType = "Datacenter"
ClusterComputeResourceType = "ClusterComputeResource" ClusterComputeResourceType = "ClusterComputeResource"
HostSystemType = "HostSystem" HostSystemType = "HostSystem"
NameProperty = "name"
) )
// Test Constants // Test Constants
......
...@@ -187,6 +187,28 @@ func (dc *Datacenter) GetDatastoreByName(ctx context.Context, name string) (*Dat ...@@ -187,6 +187,28 @@ func (dc *Datacenter) GetDatastoreByName(ctx context.Context, name string) (*Dat
return &datastore, nil return &datastore, nil
} }
// GetDatastoreInfoByName gets the Datastore object for the given datastore name
func (dc *Datacenter) GetDatastoreInfoByName(ctx context.Context, name string) (*DatastoreInfo, error) {
finder := getFinder(dc)
ds, err := finder.Datastore(ctx, name)
if err != nil {
klog.Errorf("Failed while searching for datastore: %s. err: %+v", name, err)
return nil, err
}
datastore := Datastore{ds, dc}
var dsMo mo.Datastore
pc := property.DefaultCollector(dc.Client())
properties := []string{DatastoreInfoProperty}
err = pc.RetrieveOne(ctx, ds.Reference(), properties, &dsMo)
if err != nil {
klog.Errorf("Failed to get Datastore managed objects from datastore reference."+
" dsRef: %+v, err: %+v", ds.Reference(), err)
return nil, err
}
klog.V(9).Infof("Result dsMo: %+v", dsMo)
return &DatastoreInfo{Datastore: &datastore, Info: dsMo.Info.GetDatastoreInfo()}, nil
}
// GetResourcePool gets the resource pool for the given path // GetResourcePool gets the resource pool for the given path
func (dc *Datacenter) GetResourcePool(ctx context.Context, resourcePoolPath string) (*object.ResourcePool, error) { func (dc *Datacenter) GetResourcePool(ctx context.Context, resourcePoolPath string) (*object.ResourcePool, error) {
finder := getFinder(dc) finder := getFinder(dc)
......
...@@ -96,8 +96,14 @@ func (ds *Datastore) GetDatastoreHostMounts(ctx context.Context) ([]types.Manage ...@@ -96,8 +96,14 @@ func (ds *Datastore) GetDatastoreHostMounts(ctx context.Context) ([]types.Manage
return nil, err return nil, err
} }
hosts := make([]types.ManagedObjectReference, len(dsMo.Host)) hosts := make([]types.ManagedObjectReference, len(dsMo.Host))
for _, dsHostMount := range dsMo.Host { for i, dsHostMount := range dsMo.Host {
hosts = append(hosts, dsHostMount.Key) hosts[i] = dsHostMount.Key
} }
return hosts, nil return hosts, nil
} }
// Exists returns whether the given file exists in this datastore
func (ds *Datastore) Exists(ctx context.Context, file string) bool {
_, err := ds.Datastore.Stat(ctx, file)
return err == nil
}
...@@ -211,7 +211,7 @@ func (vmdisk vmDiskManager) createDummyVM(ctx context.Context, datacenter *vclib ...@@ -211,7 +211,7 @@ func (vmdisk vmDiskManager) createDummyVM(ctx context.Context, datacenter *vclib
} }
// CleanUpDummyVMs deletes stale dummyVM's // CleanUpDummyVMs deletes stale dummyVM's
func CleanUpDummyVMs(ctx context.Context, folder *vclib.Folder, dc *vclib.Datacenter) error { func CleanUpDummyVMs(ctx context.Context, folder *vclib.Folder) error {
vmList, err := folder.GetVirtualMachines(ctx) vmList, err := folder.GetVirtualMachines(ctx)
if err != nil { if err != nil {
klog.V(4).Infof("Failed to get virtual machines in the kubernetes cluster: %s, err: %+v", folder.InventoryPath, err) klog.V(4).Infof("Failed to get virtual machines in the kubernetes cluster: %s, err: %+v", folder.InventoryPath, err)
...@@ -230,7 +230,7 @@ func CleanUpDummyVMs(ctx context.Context, folder *vclib.Folder, dc *vclib.Datace ...@@ -230,7 +230,7 @@ func CleanUpDummyVMs(ctx context.Context, folder *vclib.Folder, dc *vclib.Datace
continue continue
} }
if strings.HasPrefix(vmName, vclib.DummyVMPrefixName) { if strings.HasPrefix(vmName, vclib.DummyVMPrefixName) {
vmObj := vclib.VirtualMachine{VirtualMachine: object.NewVirtualMachine(dc.Client(), vm.Reference()), Datacenter: dc} vmObj := vclib.VirtualMachine{VirtualMachine: object.NewVirtualMachine(folder.Client(), vm.Reference())}
dummyVMList = append(dummyVMList, &vmObj) dummyVMList = append(dummyVMList, &vmObj)
} }
} }
......
...@@ -85,7 +85,7 @@ func (pbmClient *PbmClient) IsDatastoreCompatible(ctx context.Context, storagePo ...@@ -85,7 +85,7 @@ func (pbmClient *PbmClient) IsDatastoreCompatible(ctx context.Context, storagePo
// GetCompatibleDatastores filters and returns compatible list of datastores for given storage policy id // GetCompatibleDatastores filters and returns compatible list of datastores for given storage policy id
// For Non Compatible Datastores, fault message with the Datastore Name is also returned // For Non Compatible Datastores, fault message with the Datastore Name is also returned
func (pbmClient *PbmClient) GetCompatibleDatastores(ctx context.Context, dc *Datacenter, storagePolicyID string, datastores []*DatastoreInfo) ([]*DatastoreInfo, string, error) { func (pbmClient *PbmClient) GetCompatibleDatastores(ctx context.Context, storagePolicyID string, datastores []*DatastoreInfo) ([]*DatastoreInfo, string, error) {
var ( var (
dsMorNameMap = getDsMorNameMap(ctx, datastores) dsMorNameMap = getDsMorNameMap(ctx, datastores)
localizedMessagesForNotCompatibleDatastores = "" localizedMessagesForNotCompatibleDatastores = ""
......
...@@ -235,7 +235,7 @@ func (vm *VirtualMachine) GetAllAccessibleDatastores(ctx context.Context) ([]*Da ...@@ -235,7 +235,7 @@ func (vm *VirtualMachine) GetAllAccessibleDatastores(ctx context.Context) ([]*Da
var dsMoList []mo.Datastore var dsMoList []mo.Datastore
pc := property.DefaultCollector(vm.Client()) pc := property.DefaultCollector(vm.Client())
properties := []string{DatastoreInfoProperty} properties := []string{DatastoreInfoProperty, NameProperty}
err = pc.Retrieve(ctx, dsRefList, properties, &dsMoList) err = pc.Retrieve(ctx, dsRefList, properties, &dsMoList)
if err != nil { if err != nil {
klog.Errorf("Failed to get Datastore managed objects from datastore objects."+ klog.Errorf("Failed to get Datastore managed objects from datastore objects."+
...@@ -243,12 +243,19 @@ func (vm *VirtualMachine) GetAllAccessibleDatastores(ctx context.Context) ([]*Da ...@@ -243,12 +243,19 @@ func (vm *VirtualMachine) GetAllAccessibleDatastores(ctx context.Context) ([]*Da
return nil, err return nil, err
} }
klog.V(9).Infof("Result dsMoList: %+v", dsMoList) klog.V(9).Infof("Result dsMoList: %+v", dsMoList)
finder := getFinder(vm.Datacenter)
var dsObjList []*DatastoreInfo var dsObjList []*DatastoreInfo
for _, dsMo := range dsMoList { for _, dsMo := range dsMoList {
// use the finder so that InventoryPath is set correctly in ds
ds, err := finder.Datastore(ctx, dsMo.Name)
if err != nil {
klog.Errorf("Failed finding datastore: %s. err: %+v", dsMo.Name, err)
return nil, err
}
datastore := Datastore{ds, vm.Datacenter}
dsObjList = append(dsObjList, dsObjList = append(dsObjList,
&DatastoreInfo{ &DatastoreInfo{
&Datastore{object.NewDatastore(vm.Client(), dsMo.Reference()), &datastore,
vm.Datacenter},
dsMo.Info.GetDatastoreInfo()}) dsMo.Info.GetDatastoreInfo()})
} }
return dsObjList, nil return dsObjList, nil
......
...@@ -70,7 +70,7 @@ var _ = utils.SIGDescribe("Volume Provisioning on Datastore [Feature:vsphere]", ...@@ -70,7 +70,7 @@ var _ = utils.SIGDescribe("Volume Provisioning on Datastore [Feature:vsphere]",
scParameters[DiskFormat] = ThinDisk scParameters[DiskFormat] = ThinDisk
err := invokeInvalidDatastoreTestNeg(client, namespace, scParameters) err := invokeInvalidDatastoreTestNeg(client, namespace, scParameters)
Expect(err).To(HaveOccurred()) Expect(err).To(HaveOccurred())
errorMsg := `Failed to provision volume with StorageClass \"` + DatastoreSCName + `\": The specified datastore ` + InvalidDatastore + ` is not a shared datastore across node VMs` errorMsg := `Failed to provision volume with StorageClass \"` + DatastoreSCName + `\": Datastore ` + InvalidDatastore + ` not found`
if !strings.Contains(err.Error(), errorMsg) { if !strings.Contains(err.Error(), errorMsg) {
Expect(err).NotTo(HaveOccurred(), errorMsg) Expect(err).NotTo(HaveOccurred(), errorMsg)
} }
......
...@@ -176,6 +176,13 @@ var _ = utils.SIGDescribe("Zone Support", func() { ...@@ -176,6 +176,13 @@ var _ = utils.SIGDescribe("Zone Support", func() {
verifyPVCAndPodCreationSucceeds(client, namespace, scParameters, zones) verifyPVCAndPodCreationSucceeds(client, namespace, scParameters, zones)
}) })
It("Verify a pod is created on a non-Workspace zone and attached to a dynamically created PV, based on the allowed zones and storage policy specified in storage class", func() {
By(fmt.Sprintf("Creating storage class with zone :%s and storage policy :%s", zoneB, compatPolicy))
scParameters[SpbmStoragePolicy] = compatPolicy
zones = append(zones, zoneB)
verifyPVCAndPodCreationSucceeds(client, namespace, scParameters, zones)
})
It("Verify PVC creation with incompatible storagePolicy and zone combination specified in storage class fails", func() { It("Verify PVC creation with incompatible storagePolicy and zone combination specified in storage class fails", func() {
By(fmt.Sprintf("Creating storage class with zone :%s and storage policy :%s", zoneA, nonCompatPolicy)) By(fmt.Sprintf("Creating storage class with zone :%s and storage policy :%s", zoneA, nonCompatPolicy))
scParameters[SpbmStoragePolicy] = nonCompatPolicy scParameters[SpbmStoragePolicy] = nonCompatPolicy
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment