2222
2323import javax .inject .Inject ;
2424
25+ import org .apache .cloudstack .engine .orchestration .service .VolumeOrchestrationService ;
2526import org .apache .cloudstack .engine .subsystem .api .storage .ChapInfo ;
2627import org .apache .cloudstack .engine .subsystem .api .storage .CopyCommandResult ;
2728import org .apache .cloudstack .engine .subsystem .api .storage .CreateCmdResult ;
3839import org .apache .cloudstack .engine .subsystem .api .storage .VolumeService ;
3940import org .apache .cloudstack .framework .async .AsyncCompletionCallback ;
4041import org .apache .cloudstack .framework .config .dao .ConfigurationDao ;
42+ import org .apache .cloudstack .resourcedetail .DiskOfferingDetailVO ;
43+ import org .apache .cloudstack .resourcedetail .dao .DiskOfferingDetailsDao ;
4144import org .apache .cloudstack .storage .RemoteHostEndPoint ;
4245import org .apache .cloudstack .storage .command .CommandResult ;
4346import org .apache .cloudstack .storage .command .CopyCommand ;
@@ -127,11 +130,15 @@ public class ScaleIOPrimaryDataStoreDriver implements PrimaryDataStoreDriver {
127130 @ Inject
128131 private ConfigurationDao configDao ;
129132 @ Inject
133+ private DiskOfferingDetailsDao diskOfferingDetailsDao ;
134+ @ Inject
130135 private HostDao hostDao ;
131136 @ Inject
132137 private VMInstanceDao vmInstanceDao ;
133138 @ Inject
134139 private VolumeService volumeService ;
140+ @ Inject
141+ private VolumeOrchestrationService volumeMgr ;
135142
136143 public ScaleIOPrimaryDataStoreDriver () {
137144
@@ -141,40 +148,47 @@ public ScaleIOGatewayClient getScaleIOClient(final Long storagePoolId) throws Ex
141148 return ScaleIOGatewayClientConnectionPool .getInstance ().getClient (storagePoolId , storagePoolDetailsDao );
142149 }
143150
151+ private boolean setVolumeLimitsOnSDC (VolumeVO volume , Host host , DataStore dataStore , Long iopsLimit , Long bandwidthLimitInKbps ) throws Exception {
152+ final String sdcId = getConnectedSdc (dataStore .getId (), host .getId ());
153+ if (StringUtils .isBlank (sdcId )) {
154+ alertHostSdcDisconnection (host );
155+ throw new CloudRuntimeException ("Unable to grant access to volume: " + volume .getId () + ", no Sdc connected with host ip: " + host .getPrivateIpAddress ());
156+ }
157+
158+ final ScaleIOGatewayClient client = getScaleIOClient (dataStore .getId ());
159+ return client .mapVolumeToSdcWithLimits (ScaleIOUtil .getVolumePath (volume .getPath ()), sdcId , iopsLimit , bandwidthLimitInKbps );
160+ }
161+
162+ private boolean setVolumeLimitsFromDetails (VolumeVO volume , Host host , DataStore dataStore ) throws Exception {
163+ Long bandwidthLimitInKbps = 0L ; // Unlimited
164+ // Check Bandwidth Limit parameter in volume details
165+ final VolumeDetailVO bandwidthVolumeDetail = volumeDetailsDao .findDetail (volume .getId (), Volume .BANDWIDTH_LIMIT_IN_MBPS );
166+ if (bandwidthVolumeDetail != null && bandwidthVolumeDetail .getValue () != null ) {
167+ bandwidthLimitInKbps = Long .parseLong (bandwidthVolumeDetail .getValue ()) * 1024 ;
168+ }
169+
170+ Long iopsLimit = 0L ; // Unlimited
171+ // Check IOPS Limit parameter in volume details, else try MaxIOPS
172+ final VolumeDetailVO iopsVolumeDetail = volumeDetailsDao .findDetail (volume .getId (), Volume .IOPS_LIMIT );
173+ if (iopsVolumeDetail != null && iopsVolumeDetail .getValue () != null ) {
174+ iopsLimit = Long .parseLong (iopsVolumeDetail .getValue ());
175+ } else if (volume .getMaxIops () != null ) {
176+ iopsLimit = volume .getMaxIops ();
177+ }
178+ if (iopsLimit > 0 && iopsLimit < ScaleIOUtil .MINIMUM_ALLOWED_IOPS_LIMIT ) {
179+ iopsLimit = ScaleIOUtil .MINIMUM_ALLOWED_IOPS_LIMIT ;
180+ }
181+
182+ return setVolumeLimitsOnSDC (volume , host , dataStore , iopsLimit , bandwidthLimitInKbps );
183+ }
184+
144185 @ Override
145186 public boolean grantAccess (DataObject dataObject , Host host , DataStore dataStore ) {
146187 try {
147188 if (DataObjectType .VOLUME .equals (dataObject .getType ())) {
148189 final VolumeVO volume = volumeDao .findById (dataObject .getId ());
149190 LOGGER .debug ("Granting access for PowerFlex volume: " + volume .getPath ());
150-
151- Long bandwidthLimitInKbps = Long .valueOf (0 ); // Unlimited
152- // Check Bandwidht Limit parameter in volume details
153- final VolumeDetailVO bandwidthVolumeDetail = volumeDetailsDao .findDetail (volume .getId (), Volume .BANDWIDTH_LIMIT_IN_MBPS );
154- if (bandwidthVolumeDetail != null && bandwidthVolumeDetail .getValue () != null ) {
155- bandwidthLimitInKbps = Long .parseLong (bandwidthVolumeDetail .getValue ()) * 1024 ;
156- }
157-
158- Long iopsLimit = Long .valueOf (0 ); // Unlimited
159- // Check IOPS Limit parameter in volume details, else try MaxIOPS
160- final VolumeDetailVO iopsVolumeDetail = volumeDetailsDao .findDetail (volume .getId (), Volume .IOPS_LIMIT );
161- if (iopsVolumeDetail != null && iopsVolumeDetail .getValue () != null ) {
162- iopsLimit = Long .parseLong (iopsVolumeDetail .getValue ());
163- } else if (volume .getMaxIops () != null ) {
164- iopsLimit = volume .getMaxIops ();
165- }
166- if (iopsLimit > 0 && iopsLimit < ScaleIOUtil .MINIMUM_ALLOWED_IOPS_LIMIT ) {
167- iopsLimit = ScaleIOUtil .MINIMUM_ALLOWED_IOPS_LIMIT ;
168- }
169-
170- final String sdcId = getConnectedSdc (dataStore .getId (), host .getId ());
171- if (StringUtils .isBlank (sdcId )) {
172- alertHostSdcDisconnection (host );
173- throw new CloudRuntimeException ("Unable to grant access to volume: " + dataObject .getId () + ", no Sdc connected with host ip: " + host .getPrivateIpAddress ());
174- }
175-
176- final ScaleIOGatewayClient client = getScaleIOClient (dataStore .getId ());
177- return client .mapVolumeToSdcWithLimits (ScaleIOUtil .getVolumePath (volume .getPath ()), sdcId , iopsLimit , bandwidthLimitInKbps );
191+ return setVolumeLimitsFromDetails (volume , host , dataStore );
178192 } else if (DataObjectType .TEMPLATE .equals (dataObject .getType ())) {
179193 final VMTemplateStoragePoolVO templatePoolRef = vmTemplatePoolDao .findByPoolTemplate (dataStore .getId (), dataObject .getId (), null );
180194 LOGGER .debug ("Granting access for PowerFlex template volume: " + templatePoolRef .getInstallPath ());
@@ -791,7 +805,15 @@ private Answer copyTemplateToVolume(DataObject srcData, DataObject destData, Hos
791805 LOGGER .error (errorMsg );
792806 answer = new Answer (cmd , false , errorMsg );
793807 } else {
794- answer = ep .sendMessage (cmd );
808+ VolumeVO volume = volumeDao .findById (destData .getId ());
809+ Host host = destHost != null ? destHost : hostDao .findById (ep .getId ());
810+ try {
811+ setVolumeLimitsOnSDC (volume , host , destData .getDataStore (), 0L , 0L );
812+ answer = ep .sendMessage (cmd );
813+ } catch (Exception e ) {
814+ LOGGER .error ("Failed to copy template to volume due to: " + e .getMessage (), e );
815+ answer = new Answer (cmd , false , e .getMessage ());
816+ }
795817 }
796818
797819 return answer ;
@@ -1181,7 +1203,7 @@ private void resizeVolume(VolumeInfo volumeInfo) {
11811203 ResizeVolumePayload payload = (ResizeVolumePayload )volumeInfo .getpayload ();
11821204 long newSizeInBytes = payload .newSize != null ? payload .newSize : volumeInfo .getSize ();
11831205 // Only increase size is allowed and size should be specified in granularity of 8 GB
1184- if (newSizeInBytes <= volumeInfo .getSize ()) {
1206+ if (newSizeInBytes < volumeInfo .getSize ()) {
11851207 throw new CloudRuntimeException ("Only increase size is allowed for volume: " + volumeInfo .getName ());
11861208 }
11871209
@@ -1210,6 +1232,20 @@ private void resizeVolume(VolumeInfo volumeInfo) {
12101232 }
12111233 }
12121234
1235+ Long newMaxIops = payload .newMaxIops != null ? payload .newMaxIops : volumeInfo .getMaxIops ();
1236+ long newBandwidthLimit = 0L ;
1237+ Long newDiskOfferingId = payload .newDiskOfferingId != null ? payload .newDiskOfferingId : volumeInfo .getDiskOfferingId ();
1238+ if (newDiskOfferingId != null ) {
1239+ DiskOfferingDetailVO bandwidthLimitDetail = diskOfferingDetailsDao .findDetail (newDiskOfferingId , Volume .BANDWIDTH_LIMIT_IN_MBPS );
1240+ if (bandwidthLimitDetail != null ) {
1241+ newBandwidthLimit = Long .parseLong (bandwidthLimitDetail .getValue ()) * 1024 ;
1242+ }
1243+ DiskOfferingDetailVO iopsLimitDetail = diskOfferingDetailsDao .findDetail (newDiskOfferingId , Volume .IOPS_LIMIT );
1244+ if (iopsLimitDetail != null ) {
1245+ newMaxIops = Long .parseLong (iopsLimitDetail .getValue ());
1246+ }
1247+ }
1248+
12131249 if (volumeInfo .getFormat ().equals (Storage .ImageFormat .QCOW2 ) || attachedRunning ) {
12141250 LOGGER .debug ("Volume needs to be resized at the hypervisor host" );
12151251
@@ -1229,9 +1265,8 @@ private void resizeVolume(VolumeInfo volumeInfo) {
12291265 volumeInfo .getPassphrase (), volumeInfo .getEncryptFormat ());
12301266
12311267 try {
1232- if (!attachedRunning ) {
1233- grantAccess (volumeInfo , ep , volumeInfo .getDataStore ());
1234- }
1268+ VolumeVO volume = volumeDao .findById (volumeInfo .getId ());
1269+ setVolumeLimitsOnSDC (volume , host , volumeInfo .getDataStore (), newMaxIops != null ? newMaxIops : 0L , newBandwidthLimit );
12351270 Answer answer = ep .sendMessage (resizeVolumeCommand );
12361271
12371272 if (!answer .getResult () && volumeInfo .getFormat ().equals (Storage .ImageFormat .QCOW2 )) {
@@ -1253,14 +1288,23 @@ private void resizeVolume(VolumeInfo volumeInfo) {
12531288 VolumeVO volume = volumeDao .findById (volumeInfo .getId ());
12541289 long oldVolumeSize = volume .getSize ();
12551290 volume .setSize (scaleIOVolume .getSizeInKb () * 1024 );
1291+ if (payload .newMinIops != null ) {
1292+ volume .setMinIops (payload .newMinIops );
1293+ }
1294+ if (payload .newMaxIops != null ) {
1295+ volume .setMaxIops (payload .newMaxIops );
1296+ }
12561297 volumeDao .update (volume .getId (), volume );
1298+ if (payload .newDiskOfferingId != null ) {
1299+ volumeMgr .saveVolumeDetails (payload .newDiskOfferingId , volume .getId ());
1300+ }
12571301
12581302 long capacityBytes = storagePool .getCapacityBytes ();
12591303 long usedBytes = storagePool .getUsedBytes ();
12601304
12611305 long newVolumeSize = volume .getSize ();
12621306 usedBytes += newVolumeSize - oldVolumeSize ;
1263- storagePool .setUsedBytes (usedBytes > capacityBytes ? capacityBytes : usedBytes );
1307+ storagePool .setUsedBytes (Math . min ( usedBytes , capacityBytes ) );
12641308 storagePoolDao .update (storagePoolId , storagePool );
12651309 } catch (Exception e ) {
12661310 String errMsg = "Unable to resize PowerFlex volume: " + volumeInfo .getId () + " due to " + e .getMessage ();
0 commit comments