Skip to content

Commit e99b98e

Browse files
sandeeplocharlaLocharla, Sandeep
andauthored
feature/CSTACKEX-65: Aggregate selection logic for creating ONTAP Volume in StoragePool creation workflow (#24)
* CSTACKEX-65: Aggregate selection logic based on available space for ONTAP Volume creation --------- Co-authored-by: Locharla, Sandeep <Sandeep.Locharla@netapp.com>
1 parent 2c61e76 commit e99b98e

File tree

1 file changed

+53
-22
lines changed
  • plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/service

1 file changed

+53
-22
lines changed

plugins/storage/volume/ontap/src/main/java/org/apache/cloudstack/storage/service/StorageStrategy.java

Lines changed: 53 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -124,31 +124,14 @@ public boolean connect() {
124124
s_logger.error("iSCSI protocol is not enabled on SVM " + svmName);
125125
throw new CloudRuntimeException("iSCSI protocol is not enabled on SVM " + svmName);
126126
}
127-
// TODO: Implement logic to select appropriate aggregate based on storage requirements
127+
128128
List<Aggregate> aggrs = svm.getAggregates();
129129
if (aggrs == null || aggrs.isEmpty()) {
130130
s_logger.error("No aggregates are assigned to SVM " + svmName);
131131
throw new CloudRuntimeException("No aggregates are assigned to SVM " + svmName);
132132
}
133-
// Set the aggregates which are according to the storage requirements
134-
for (Aggregate aggr : aggrs) {
135-
s_logger.debug("Found aggregate: " + aggr.getName() + " with UUID: " + aggr.getUuid());
136-
Aggregate aggrResp = aggregateFeignClient.getAggregateByUUID(authHeader, aggr.getUuid());
137-
if (!Objects.equals(aggrResp.getState(), Aggregate.StateEnum.ONLINE)) {
138-
s_logger.warn("Aggregate " + aggr.getName() + " is not in online state. Skipping this aggregate.");
139-
continue;
140-
} else if (aggrResp.getSpace() == null || aggrResp.getAvailableBlockStorageSpace() == null ||
141-
aggrResp.getAvailableBlockStorageSpace() <= storage.getSize().doubleValue()) {
142-
s_logger.warn("Aggregate " + aggr.getName() + " does not have sufficient available space. Skipping this aggregate.");
143-
continue;
144-
}
145-
s_logger.info("Selected aggregate: " + aggr.getName() + " for volume operations.");
146-
this.aggregates = List.of(aggr);
147-
}
148-
if (this.aggregates == null || this.aggregates.isEmpty()) {
149-
s_logger.error("No suitable aggregates found on SVM " + svmName + " for volume creation.");
150-
throw new CloudRuntimeException("No suitable aggregates found on SVM " + svmName + " for volume creation.");
151-
}
133+
134+
this.aggregates = aggrs;
152135
s_logger.info("Successfully connected to ONTAP cluster and validated ONTAP details provided");
153136
} catch (Exception e) {
154137
throw new CloudRuntimeException("Failed to connect to ONTAP cluster: " + e.getMessage(), e);
@@ -175,6 +158,10 @@ public Volume createStorageVolume(String volumeName, Long size) {
175158
s_logger.error("No aggregates available to create volume on SVM " + svmName);
176159
throw new CloudRuntimeException("No aggregates available to create volume on SVM " + svmName);
177160
}
161+
if (size == null || size <= 0) {
162+
throw new CloudRuntimeException("Invalid volume size provided: " + size);
163+
}
164+
178165
// Get the AuthHeader
179166
String authHeader = Utility.generateAuthHeader(storage.getUsername(), storage.getPassword());
180167

@@ -187,9 +174,53 @@ public Volume createStorageVolume(String volumeName, Long size) {
187174

188175
volumeRequest.setName(volumeName);
189176
volumeRequest.setSvm(svm);
177+
178+
// Pick the best aggregate for this specific request (largest available, online, and sufficient space).
179+
long maxAvailableAggregateSpaceBytes = -1L;
180+
Aggregate aggrChosen = null;
181+
for (Aggregate aggr : aggregates) {
182+
s_logger.debug("Found aggregate: " + aggr.getName() + " with UUID: " + aggr.getUuid());
183+
Aggregate aggrResp = aggregateFeignClient.getAggregateByUUID(authHeader, aggr.getUuid());
184+
185+
if (aggrResp == null) {
186+
s_logger.warn("Aggregate details response is null for aggregate " + aggr.getName() + ". Skipping.");
187+
continue;
188+
}
189+
190+
if (!Objects.equals(aggrResp.getState(), Aggregate.StateEnum.ONLINE)) {
191+
s_logger.warn("Aggregate " + aggr.getName() + " is not in online state. Skipping this aggregate.");
192+
continue;
193+
}
194+
195+
if (aggrResp.getSpace() == null || aggrResp.getAvailableBlockStorageSpace() == null) {
196+
s_logger.warn("Aggregate " + aggr.getName() + " does not have space information. Skipping this aggregate.");
197+
continue;
198+
}
199+
200+
final long availableBytes = aggrResp.getAvailableBlockStorageSpace().longValue();
201+
s_logger.debug("Aggregate " + aggr.getName() + " available bytes=" + availableBytes + ", requested=" + size);
202+
203+
if (availableBytes <= size) {
204+
s_logger.warn("Aggregate " + aggr.getName() + " does not have sufficient available space. Required=" +
205+
size + " bytes, available=" + availableBytes + " bytes. Skipping this aggregate.");
206+
continue;
207+
}
208+
209+
if (availableBytes > maxAvailableAggregateSpaceBytes) {
210+
maxAvailableAggregateSpaceBytes = availableBytes;
211+
aggrChosen = aggr;
212+
}
213+
}
214+
215+
if (aggrChosen == null) {
216+
s_logger.error("No suitable aggregates found on SVM " + svmName + " for volume creation.");
217+
throw new CloudRuntimeException("No suitable aggregates found on SVM " + svmName + " for volume operations.");
218+
}
219+
s_logger.info("Selected aggregate: " + aggrChosen.getName() + " for volume operations.");
220+
190221
Aggregate aggr = new Aggregate();
191-
aggr.setName(aggregates.get(0).getName());
192-
aggr.setUuid(aggregates.get(0).getUuid());
222+
aggr.setName(aggrChosen.getName());
223+
aggr.setUuid(aggrChosen.getUuid());
193224
volumeRequest.setAggregates(List.of(aggr));
194225
volumeRequest.setSize(size);
195226
volumeRequest.setNas(nas);

0 commit comments

Comments
 (0)