@@ -1165,41 +1165,47 @@ func (vs *VSphere) DisksAreAttached(nodeVolumes map[k8stypes.NodeName][]string)
1165
1165
func (vs * VSphere ) CreateVolume (volumeOptions * vclib.VolumeOptions ) (canonicalVolumePath string , err error ) {
1166
1166
klog .V (1 ).Infof ("Starting to create a vSphere volume with volumeOptions: %+v" , volumeOptions )
1167
1167
createVolumeInternal := func (volumeOptions * vclib.VolumeOptions ) (canonicalVolumePath string , err error ) {
1168
- var datastore string
1168
+ var datastoreInfo * vclib. DatastoreInfo
1169
1169
var dsList []* vclib.DatastoreInfo
1170
- // If datastore not specified, then use default datastore
1171
- if volumeOptions .Datastore == "" {
1172
- datastore = vs .cfg .Workspace .DefaultDatastore
1173
- } else {
1174
- datastore = volumeOptions .Datastore
1175
- }
1176
- datastore = strings .TrimSpace (datastore )
1170
+
1177
1171
// Create context
1178
1172
ctx , cancel := context .WithCancel (context .Background ())
1179
1173
defer cancel ()
1180
1174
vsi , err := vs .getVSphereInstanceForServer (vs .cfg .Workspace .VCenterIP , ctx )
1181
1175
if err != nil {
1182
1176
return "" , err
1183
1177
}
1184
- dc , err := vclib .GetDatacenter (ctx , vsi .conn , vs .cfg .Workspace .Datacenter )
1178
+ // If datastore not specified, then use default datastore
1179
+ datastoreName := strings .TrimSpace (volumeOptions .Datastore )
1180
+ if datastoreName == "" {
1181
+ datastoreName = strings .TrimSpace (vs .cfg .Workspace .DefaultDatastore )
1182
+ }
1183
+ // The given datastoreName may be present in more than one datacenter
1184
+ candidateDatastoreInfos , err := vs .FindDatastoreByName (ctx , datastoreName )
1185
1185
if err != nil {
1186
1186
return "" , err
1187
1187
}
1188
+ // Each of the datastores found is a candidate for Volume creation.
1189
+ // One of these will be selected based on given policy and/or zone.
1190
+ candidateDatastores := make (map [string ]* vclib.DatastoreInfo )
1191
+ for _ , dsInfo := range candidateDatastoreInfos {
1192
+ candidateDatastores [dsInfo .Info .Url ] = dsInfo
1193
+ }
1194
+
1188
1195
var vmOptions * vclib.VMOptions
1189
1196
if volumeOptions .VSANStorageProfileData != "" || volumeOptions .StoragePolicyName != "" {
1190
1197
// If datastore and zone are specified, first validate if the datastore is in the provided zone.
1191
1198
if len (volumeOptions .Zone ) != 0 && volumeOptions .Datastore != "" {
1192
1199
klog .V (4 ).Infof ("Specified zone : %s, datastore : %s" , volumeOptions .Zone , volumeOptions .Datastore )
1193
- dsList , err = getDatastoresForZone (ctx , dc , vs .nodeManager , volumeOptions .Zone )
1200
+ dsList , err = getDatastoresForZone (ctx , vs .nodeManager , volumeOptions .Zone )
1194
1201
if err != nil {
1195
1202
return "" , err
1196
1203
}
1197
1204
1198
1205
// Validate if the datastore provided belongs to the zone. If not, fail the operation.
1199
1206
found := false
1200
1207
for _ , ds := range dsList {
1201
- if ds .Info .Name == volumeOptions .Datastore {
1202
- found = true
1208
+ if datastoreInfo , found = candidateDatastores [ds .Info .Url ]; found {
1203
1209
break
1204
1210
}
1205
1211
}
@@ -1221,19 +1227,14 @@ func (vs *VSphere) CreateVolume(volumeOptions *vclib.VolumeOptions) (canonicalVo
1221
1227
cleanUpRoutineInitialized = true
1222
1228
}
1223
1229
cleanUpRoutineInitLock .Unlock ()
1224
- vmOptions , err = vs .setVMOptions (ctx , dc , vs .cfg .Workspace .ResourcePoolPath )
1225
- if err != nil {
1226
- klog .Errorf ("Failed to set VM options requires to create a vsphere volume. err: %+v" , err )
1227
- return "" , err
1228
- }
1229
1230
}
1230
1231
if volumeOptions .StoragePolicyName != "" && volumeOptions .Datastore == "" {
1231
1232
if len (volumeOptions .Zone ) == 0 {
1232
1233
klog .V (4 ).Infof ("Selecting a shared datastore as per the storage policy %s" , volumeOptions .StoragePolicyName )
1233
- datastore , err = getPbmCompatibleDatastore (ctx , dc , volumeOptions .StoragePolicyName , vs .nodeManager )
1234
+ datastoreInfo , err = getPbmCompatibleDatastore (ctx , vsi . conn . Client , volumeOptions .StoragePolicyName , vs .nodeManager )
1234
1235
} else {
1235
1236
// If zone is specified, first get the datastores in the zone.
1236
- dsList , err = getDatastoresForZone (ctx , dc , vs .nodeManager , volumeOptions .Zone )
1237
+ dsList , err = getDatastoresForZone (ctx , vs .nodeManager , volumeOptions .Zone )
1237
1238
1238
1239
if err != nil {
1239
1240
klog .Errorf ("Failed to find a shared datastore matching zone %s. err: %+v" , volumeOptions .Zone , err )
@@ -1249,18 +1250,18 @@ func (vs *VSphere) CreateVolume(volumeOptions *vclib.VolumeOptions) (canonicalVo
1249
1250
klog .V (4 ).Infof ("Specified zone : %s. Picking a datastore as per the storage policy %s among the zoned datastores : %s" , volumeOptions .Zone ,
1250
1251
volumeOptions .StoragePolicyName , dsList )
1251
1252
// Among the compatible datastores, select the one based on the maximum free space.
1252
- datastore , err = getPbmCompatibleZonedDatastore (ctx , dc , volumeOptions .StoragePolicyName , dsList )
1253
+ datastoreInfo , err = getPbmCompatibleZonedDatastore (ctx , vsi . conn . Client , volumeOptions .StoragePolicyName , dsList )
1253
1254
}
1254
- klog .V (1 ).Infof ("Datastore selected as per policy : %s" , datastore )
1255
1255
if err != nil {
1256
1256
klog .Errorf ("Failed to get pbm compatible datastore with storagePolicy: %s. err: %+v" , volumeOptions .StoragePolicyName , err )
1257
1257
return "" , err
1258
1258
}
1259
+ klog .V (1 ).Infof ("Datastore selected as per policy : %s" , datastoreInfo .Info .Name )
1259
1260
} else {
1260
1261
// If zone is specified, pick the datastore in the zone with maximum free space within the zone.
1261
1262
if volumeOptions .Datastore == "" && len (volumeOptions .Zone ) != 0 {
1262
1263
klog .V (4 ).Infof ("Specified zone : %s" , volumeOptions .Zone )
1263
- dsList , err = getDatastoresForZone (ctx , dc , vs .nodeManager , volumeOptions .Zone )
1264
+ dsList , err = getDatastoresForZone (ctx , vs .nodeManager , volumeOptions .Zone )
1264
1265
1265
1266
if err != nil {
1266
1267
klog .Errorf ("Failed to find a shared datastore matching zone %s. err: %+v" , volumeOptions .Zone , err )
@@ -1273,40 +1274,40 @@ func (vs *VSphere) CreateVolume(volumeOptions *vclib.VolumeOptions) (canonicalVo
1273
1274
return "" , err
1274
1275
}
1275
1276
1276
- datastore , err = getMostFreeDatastoreName (ctx , nil , dsList )
1277
+ datastoreInfo , err = getMostFreeDatastore (ctx , nil , dsList )
1277
1278
if err != nil {
1278
1279
klog .Errorf ("Failed to get shared datastore: %+v" , err )
1279
1280
return "" , err
1280
1281
}
1281
- klog .V (1 ).Infof ("Specified zone : %s. Selected datastore : %s" , volumeOptions .StoragePolicyName , datastore )
1282
+ klog .V (1 ).Infof ("Specified zone : %s. Selected datastore : %s" , volumeOptions .Zone , datastoreInfo . Info . Name )
1282
1283
} else {
1283
1284
var sharedDsList []* vclib.DatastoreInfo
1284
1285
var err error
1285
1286
if len (volumeOptions .Zone ) == 0 {
1286
1287
// If zone is not provided, get the shared datastore across all node VMs.
1287
- klog .V (4 ).Infof ("Validating if datastore %s is shared across all node VMs" , datastore )
1288
- sharedDsList , err = getSharedDatastoresInK8SCluster (ctx , dc , vs .nodeManager )
1288
+ klog .V (4 ).Infof ("Validating if datastore %s is shared across all node VMs" , datastoreName )
1289
+ sharedDsList , err = getSharedDatastoresInK8SCluster (ctx , vs .nodeManager )
1289
1290
if err != nil {
1290
1291
klog .Errorf ("Failed to get shared datastore: %+v" , err )
1291
1292
return "" , err
1292
1293
}
1293
1294
// Prepare error msg to be used later, if required.
1294
- err = fmt .Errorf ("The specified datastore %s is not a shared datastore across node VMs" , datastore )
1295
+ err = fmt .Errorf ("The specified datastore %s is not a shared datastore across node VMs" , datastoreName )
1295
1296
} else {
1296
1297
// If zone is provided, get the shared datastores in that zone.
1297
- klog .V (4 ).Infof ("Validating if datastore %s is in zone %s " , datastore , volumeOptions .Zone )
1298
- sharedDsList , err = getDatastoresForZone (ctx , dc , vs .nodeManager , volumeOptions .Zone )
1298
+ klog .V (4 ).Infof ("Validating if datastore %s is in zone %s " , datastoreName , volumeOptions .Zone )
1299
+ sharedDsList , err = getDatastoresForZone (ctx , vs .nodeManager , volumeOptions .Zone )
1299
1300
if err != nil {
1300
1301
klog .Errorf ("Failed to find a shared datastore matching zone %s. err: %+v" , volumeOptions .Zone , err )
1301
1302
return "" , err
1302
1303
}
1303
1304
// Prepare error msg to be used later, if required.
1304
- err = fmt .Errorf ("The specified datastore %s does not match the provided zones : %s" , datastore , volumeOptions .Zone )
1305
+ err = fmt .Errorf ("The specified datastore %s does not match the provided zones : %s" , datastoreName , volumeOptions .Zone )
1305
1306
}
1306
1307
found := false
1307
1308
// Check if the selected datastore belongs to the list of shared datastores computed.
1308
1309
for _ , sharedDs := range sharedDsList {
1309
- if datastore == sharedDs .Info .Name {
1310
+ if datastoreInfo , found = candidateDatastores [ sharedDs .Info .Url ]; found {
1310
1311
klog .V (4 ).Infof ("Datastore validation succeeded" )
1311
1312
found = true
1312
1313
break
@@ -1318,11 +1319,19 @@ func (vs *VSphere) CreateVolume(volumeOptions *vclib.VolumeOptions) (canonicalVo
1318
1319
}
1319
1320
}
1320
1321
}
1321
- ds , err := dc .GetDatastoreByName (ctx , datastore )
1322
+
1323
+ // if datastoreInfo is still not determined, it is an error condition
1324
+ if datastoreInfo == nil {
1325
+ klog .Errorf ("Ambigous datastore name %s, cannot be found among: %v" , datastoreName , candidateDatastoreInfos )
1326
+ return "" , fmt .Errorf ("Ambigous datastore name %s" , datastoreName )
1327
+ }
1328
+ ds := datastoreInfo .Datastore
1329
+ volumeOptions .Datastore = datastoreInfo .Info .Name
1330
+ vmOptions , err = vs .setVMOptions (ctx , vsi .conn , ds )
1322
1331
if err != nil {
1332
+ klog .Errorf ("Failed to set VM options required to create a vsphere volume. err: %+v" , err )
1323
1333
return "" , err
1324
1334
}
1325
- volumeOptions .Datastore = datastore
1326
1335
kubeVolsPath := filepath .Clean (ds .Path (VolDir )) + "/"
1327
1336
err = ds .CreateDirectory (ctx , kubeVolsPath , false )
1328
1337
if err != nil && err != vclib .ErrFileAlreadyExist {
@@ -1337,18 +1346,18 @@ func (vs *VSphere) CreateVolume(volumeOptions *vclib.VolumeOptions) (canonicalVo
1337
1346
}
1338
1347
volumePath , err = disk .Create (ctx , ds )
1339
1348
if err != nil {
1340
- klog .Errorf ("Failed to create a vsphere volume with volumeOptions: %+v on datastore: %s. err: %+v" , volumeOptions , datastore , err )
1349
+ klog .Errorf ("Failed to create a vsphere volume with volumeOptions: %+v on datastore: %s. err: %+v" , volumeOptions , ds , err )
1341
1350
return "" , err
1342
1351
}
1343
1352
// Get the canonical path for the volume path.
1344
- canonicalVolumePath , err = getcanonicalVolumePath (ctx , dc , volumePath )
1353
+ canonicalVolumePath , err = getcanonicalVolumePath (ctx , datastoreInfo . Datacenter , volumePath )
1345
1354
if err != nil {
1346
- klog .Errorf ("Failed to get canonical vsphere volume path for volume: %s with volumeOptions: %+v on datastore: %s. err: %+v" , volumePath , volumeOptions , datastore , err )
1355
+ klog .Errorf ("Failed to get canonical vsphere volume path for volume: %s with volumeOptions: %+v on datastore: %s. err: %+v" , volumePath , volumeOptions , ds , err )
1347
1356
return "" , err
1348
1357
}
1349
- if filepath .Base (datastore ) != datastore {
1358
+ if filepath .Base (datastoreName ) != datastoreName {
1350
1359
// If datastore is within cluster, add cluster path to the volumePath
1351
- canonicalVolumePath = strings .Replace (canonicalVolumePath , filepath .Base (datastore ), datastore , 1 )
1360
+ canonicalVolumePath = strings .Replace (canonicalVolumePath , filepath .Base (datastoreName ), datastoreName , 1 )
1352
1361
}
1353
1362
return canonicalVolumePath , nil
1354
1363
}
@@ -1577,12 +1586,29 @@ func (vs *VSphere) GetVolumeLabels(volumePath string) (map[string]string, error)
1577
1586
return nil , nil
1578
1587
}
1579
1588
1589
+ // Find the datastore on which this volume resides
1580
1590
datastorePathObj , err := vclib .GetDatastorePathObjFromVMDiskPath (volumePath )
1581
1591
if err != nil {
1582
1592
klog .Errorf ("Failed to get datastore for volume: %v: %+v" , volumePath , err )
1583
1593
return nil , err
1584
1594
}
1585
- dsZones , err := vs .GetZonesForDatastore (ctx , datastorePathObj .Datastore )
1595
+ dsInfos , err := vs .FindDatastoreByName (ctx , datastorePathObj .Datastore )
1596
+ if err != nil {
1597
+ klog .Errorf ("Failed to get datastore by name: %v: %+v" , datastorePathObj .Datastore , err )
1598
+ return nil , err
1599
+ }
1600
+ var datastore * vclib.Datastore
1601
+ for _ , dsInfo := range dsInfos {
1602
+ if dsInfo .Datastore .Exists (ctx , datastorePathObj .Path ) {
1603
+ datastore = dsInfo .Datastore
1604
+ }
1605
+ }
1606
+ if datastore == nil {
1607
+ klog .Errorf ("Could not find %s among %v" , volumePath , dsInfos )
1608
+ return nil , fmt .Errorf ("Could not find the datastore for volume: %s" , volumePath )
1609
+ }
1610
+
1611
+ dsZones , err := vs .GetZonesForDatastore (ctx , datastore )
1586
1612
if err != nil {
1587
1613
klog .Errorf ("Failed to get zones for datastore %v: %+v" , datastorePathObj .Datastore , err )
1588
1614
return nil , err
@@ -1620,25 +1646,16 @@ func (vs *VSphere) collapseZonesInRegion(ctx context.Context, zones []cloudprovi
1620
1646
}
1621
1647
1622
1648
// GetZonesForDatastore returns all the zones from which this datastore is visible
1623
- func (vs * VSphere ) GetZonesForDatastore (ctx context.Context , datastore string ) ([]cloudprovider.Zone , error ) {
1649
+ func (vs * VSphere ) GetZonesForDatastore (ctx context.Context , datastore * vclib. Datastore ) ([]cloudprovider.Zone , error ) {
1624
1650
vsi , err := vs .getVSphereInstanceForServer (vs .cfg .Workspace .VCenterIP , ctx )
1625
1651
if err != nil {
1626
1652
klog .Errorf ("Failed to get vSphere instance: %+v" , err )
1627
1653
return nil , err
1628
1654
}
1629
- dc , err := vclib .GetDatacenter (ctx , vsi .conn , vs .cfg .Workspace .Datacenter )
1630
- if err != nil {
1631
- klog .Errorf ("Failed to get datacenter: %+v" , err )
1632
- return nil , err
1633
- }
1655
+
1634
1656
// get the hosts mounted on this datastore
1635
1657
// datastore -> ["host-1", "host-2", "host-3", ...]
1636
- ds , err := dc .GetDatastoreByName (ctx , datastore )
1637
- if err != nil {
1638
- klog .Errorf ("Failed to get datastore by name: %v: %+v" , datastore , err )
1639
- return nil , err
1640
- }
1641
- dsHosts , err := ds .GetDatastoreHostMounts (ctx )
1658
+ dsHosts , err := datastore .GetDatastoreHostMounts (ctx )
1642
1659
if err != nil {
1643
1660
klog .Errorf ("Failed to get datastore host mounts for %v: %+v" , datastore , err )
1644
1661
return nil , err
0 commit comments