server,config: respect storage.max.volume.size and make it dynamic (#5857)

* server,config: respect storage.max.volume.size and make it dynamic

Fixes #5830

* fix test

* size change

* fix check

* server: donot include ISO size while checking volume sizes

* revert size check

* refactor

Signed-off-by: Abhishek Kumar <abhishek.mrt22@gmail.com>
Co-authored-by: sureshanaparti <12028987+sureshanaparti@users.noreply.github.com>
This commit is contained in:
Abhishek Kumar 2022-02-08 13:29:35 +05:30 committed by GitHub
parent eeaad0bfe7
commit af58284560
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 82 additions and 62 deletions

View File

@ -152,4 +152,6 @@ public interface VolumeApiService {
Volume destroyVolume(long volumeId, Account caller, boolean expunge, boolean forceExpunge);
Volume recoverVolume(long volumeId);
boolean validateVolumeSizeInBytes(long size);
}

View File

@ -75,6 +75,13 @@ public interface VolumeOrchestrationService {
true
);
ConfigKey<Long> MaxVolumeSize = new ConfigKey<Long>("Storage",
Long.class,
"storage.max.volume.size",
"2000",
"The maximum size for a volume (in GB).",
true);
VolumeInfo moveVolume(VolumeInfo volume, long destPoolDcId, Long destPoolPodId, Long destPoolClusterId, HypervisorType dataDiskHyperType)
throws ConcurrentOperationException, StorageUnavailableException;

View File

@ -18,10 +18,12 @@
*/
package org.apache.cloudstack.engine.orchestration;
import static com.cloud.storage.resource.StorageProcessor.REQUEST_TEMPLATE_RELOAD;
import static com.cloud.utils.NumbersUtil.toHumanReadableSize;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@ -35,14 +37,6 @@ import java.util.stream.Collectors;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import com.cloud.agent.api.to.DatadiskTO;
import com.cloud.utils.StringUtils;
import com.cloud.vm.SecondaryStorageVmVO;
import com.cloud.vm.UserVmDetailVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VmDetailConstants;
import com.cloud.vm.dao.SecondaryStorageVmDao;
import com.cloud.vm.dao.UserVmDetailsDao;
import org.apache.cloudstack.api.command.admin.vm.MigrateVMCmd;
import org.apache.cloudstack.api.command.admin.volume.MigrateVolumeCmdByAdmin;
import org.apache.cloudstack.api.command.user.volume.MigrateVolumeCmd;
@ -84,11 +78,12 @@ import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
import org.apache.log4j.Logger;
import com.cloud.agent.api.to.DataTO;
import com.cloud.agent.api.to.DatadiskTO;
import com.cloud.agent.api.to.DiskTO;
import com.cloud.agent.api.to.VirtualMachineTO;
import com.cloud.agent.manager.allocator.PodAllocator;
@ -139,6 +134,7 @@ import com.cloud.user.Account;
import com.cloud.user.ResourceLimitService;
import com.cloud.uservm.UserVm;
import com.cloud.utils.Pair;
import com.cloud.utils.StringUtils;
import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.db.DB;
import com.cloud.utils.db.EntityManager;
@ -150,21 +146,24 @@ import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.fsm.NoTransitionException;
import com.cloud.utils.fsm.StateMachine2;
import com.cloud.vm.DiskProfile;
import com.cloud.vm.SecondaryStorageVmVO;
import com.cloud.vm.UserVmCloneSettingVO;
import com.cloud.vm.UserVmDetailVO;
import com.cloud.vm.UserVmVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VirtualMachine.State;
import com.cloud.vm.VirtualMachineProfile;
import com.cloud.vm.VirtualMachineProfileImpl;
import com.cloud.vm.VmDetailConstants;
import com.cloud.vm.VmWorkAttachVolume;
import com.cloud.vm.VmWorkMigrateVolume;
import com.cloud.vm.VmWorkSerializer;
import com.cloud.vm.VmWorkTakeVolumeSnapshot;
import com.cloud.vm.dao.SecondaryStorageVmDao;
import com.cloud.vm.dao.UserVmCloneSettingDao;
import com.cloud.vm.dao.UserVmDao;
import static com.cloud.storage.resource.StorageProcessor.REQUEST_TEMPLATE_RELOAD;
import java.util.Date;
import com.cloud.vm.dao.UserVmDetailsDao;
public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrationService, Configurable {
@ -1749,8 +1748,6 @@ public class VolumeOrchestrator extends ManagerBase implements VolumeOrchestrati
return true;
}
public static final ConfigKey<Long> MaxVolumeSize = new ConfigKey<Long>(Long.class, "storage.max.volume.size", "Storage", "2000", "The maximum size for a volume (in GB).", true);
public static final ConfigKey<Boolean> RecreatableSystemVmEnabled = new ConfigKey<Boolean>(Boolean.class, "recreate.systemvm.enabled", "Advanced", "false",
"If true, will recreate system vm root disk whenever starting system vm", true);

View File

@ -16,6 +16,15 @@
// under the License.
package com.cloud.configuration;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.StringTokenizer;
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator;
import org.apache.cloudstack.framework.config.ConfigKey;
import com.cloud.agent.AgentManager;
import com.cloud.consoleproxy.ConsoleProxyManager;
import com.cloud.ha.HighAvailabilityManager;
@ -29,14 +38,6 @@ import com.cloud.storage.snapshot.SnapshotManager;
import com.cloud.template.TemplateManager;
import com.cloud.vm.UserVmManager;
import com.cloud.vm.snapshot.VMSnapshotManager;
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
import org.apache.cloudstack.engine.subsystem.api.storage.StoragePoolAllocator;
import org.apache.cloudstack.framework.config.ConfigKey;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.StringTokenizer;
/**
* @deprecated use the more dynamic ConfigKey
@ -144,7 +145,6 @@ public enum Config {
"60000",
"The interval (in milliseconds) when storage stats (per host) are retrieved from agents.",
null),
MaxVolumeSize("Storage", ManagementServer.class, Integer.class, "storage.max.volume.size", "2000", "The maximum size for a volume (in GB).", null),
StorageCacheReplacementLRUTimeInterval(
"Storage",
ManagementServer.class,

View File

@ -43,7 +43,6 @@ import java.util.Vector;
import javax.inject.Inject;
import javax.naming.ConfigurationException;
import com.googlecode.ipv6.IPv6Address;
import org.apache.cloudstack.acl.SecurityChecker;
import org.apache.cloudstack.affinity.AffinityGroup;
import org.apache.cloudstack.affinity.AffinityGroupService;
@ -85,6 +84,7 @@ import org.apache.cloudstack.config.ApiServiceConfiguration;
import org.apache.cloudstack.config.Configuration;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.engine.orchestration.service.NetworkOrchestrationService;
import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
import org.apache.cloudstack.framework.config.ConfigDepot;
@ -271,6 +271,7 @@ import com.google.common.base.MoreObjects;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import com.google.common.collect.Sets;
import com.googlecode.ipv6.IPv6Address;
public class ConfigurationManagerImpl extends ManagerBase implements ConfigurationManager, ConfigurationService, Configurable {
public static final Logger s_logger = Logger.getLogger(ConfigurationManagerImpl.class);
@ -422,7 +423,6 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
@Inject
protected DataCenterLinkLocalIpAddressDao _linkLocalIpAllocDao;
private int _maxVolumeSizeInGb = Integer.parseInt(Config.MaxVolumeSize.getDefaultValue());
private long _defaultPageSize = Long.parseLong(Config.DefaultPageSize.getDefaultValue());
private static final String DOMAIN_NAME_PATTERN = "^((?!-)[A-Za-z0-9-]{1,63}(?<!-)\\.)+[A-Za-z]{1,63}$";
protected Set<String> configValuesForValidation;
@ -478,9 +478,6 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
@Override
public boolean configure(final String name, final Map<String, Object> params) throws ConfigurationException {
final String maxVolumeSizeInGbString = _configDao.getValue(Config.MaxVolumeSize.key());
_maxVolumeSizeInGb = NumbersUtil.parseInt(maxVolumeSizeInGbString, Integer.parseInt(Config.MaxVolumeSize.getDefaultValue()));
final String defaultPageSizeString = _configDao.getValue(Config.DefaultPageSize.key());
_defaultPageSize = NumbersUtil.parseLong(defaultPageSizeString, Long.parseLong(Config.DefaultPageSize.getDefaultValue()));
@ -2943,6 +2940,10 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
if (rootDiskSizeInGiB != null && rootDiskSizeInGiB <= 0L) {
throw new InvalidParameterValueException(String.format("The Root disk size is of %s GB but it must be greater than 0.", rootDiskSizeInGiB));
} else if (rootDiskSizeInGiB != null) {
long maxVolumeSizeInGb = VolumeOrchestrationService.MaxVolumeSize.value();
if (rootDiskSizeInGiB > maxVolumeSizeInGb) {
throw new InvalidParameterValueException(String.format("The maximum size for a disk is %d GB.", maxVolumeSizeInGb));
}
long rootDiskSizeInBytes = rootDiskSizeInGiB * GiB_TO_BYTES;
offering.setDiskSize(rootDiskSizeInBytes);
}
@ -3264,10 +3265,11 @@ public class ConfigurationManagerImpl extends ManagerBase implements Configurati
Long iopsWriteRate, Long iopsWriteRateMax, Long iopsWriteRateMaxLength,
final Integer hypervisorSnapshotReserve, String cacheMode, final Map<String, String> details, final Long storagePolicyID) {
long diskSize = 0;// special case for custom disk offerings
long maxVolumeSizeInGb = VolumeOrchestrationService.MaxVolumeSize.value();
if (numGibibytes != null && numGibibytes <= 0) {
throw new InvalidParameterValueException("Please specify a disk size of at least 1 Gb.");
} else if (numGibibytes != null && numGibibytes > _maxVolumeSizeInGb) {
throw new InvalidParameterValueException("The maximum size for a disk is " + _maxVolumeSizeInGb + " Gb.");
throw new InvalidParameterValueException("Please specify a disk size of at least 1 GB.");
} else if (numGibibytes != null && numGibibytes > maxVolumeSizeInGb) {
throw new InvalidParameterValueException(String.format("The maximum size for a disk is %d GB.", maxVolumeSizeInGb));
}
final ProvisioningType typedProvisioningType = ProvisioningType.getProvisioningType(provisioningType);

View File

@ -311,7 +311,6 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
public static final ConfigKey<Boolean> AllowUserExpungeRecoverVolume = new ConfigKey<Boolean>("Advanced", Boolean.class, "allow.user.expunge.recover.volume", "true",
"Determines whether users can expunge or recover their volume", true, ConfigKey.Scope.Account);
private long _maxVolumeSizeInGb;
private final StateMachine2<Volume.State, Volume.Event, Volume> _volStateMachine;
private static final Set<Volume.State> STATES_VOLUME_CANNOT_BE_DESTROYED = new HashSet<>(Arrays.asList(Volume.State.Destroy, Volume.State.Expunging, Volume.State.Expunged, Volume.State.Allocated));
@ -730,9 +729,8 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
maxIops = diskOffering.getMaxIops();
}
if (!validateVolumeSizeRange(size)) {// convert size from mb to gb
// for validation
throw new InvalidParameterValueException("Invalid size for custom volume creation: " + size + " ,max volume size is:" + _maxVolumeSizeInGb);
if (!validateVolumeSizeInBytes(size)) {
throw new InvalidParameterValueException(String.format("Invalid size for custom volume creation: %s, max volume size is: %s GB", NumbersUtil.toReadableSize(size), VolumeOrchestrationService.MaxVolumeSize.value()));
}
}
@ -886,11 +884,13 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
});
}
public boolean validateVolumeSizeRange(long size) {
@Override
public boolean validateVolumeSizeInBytes(long size) {
long maxVolumeSize = VolumeOrchestrationService.MaxVolumeSize.value();
if (size < 0 || (size > 0 && size < (1024 * 1024 * 1024))) {
throw new InvalidParameterValueException("Please specify a size of at least 1 GB.");
} else if (size > (_maxVolumeSizeInGb * 1024 * 1024 * 1024)) {
throw new InvalidParameterValueException("Requested volume size is " + size + ", but the maximum size allowed is " + _maxVolumeSizeInGb + " GB.");
} else if (size > (maxVolumeSize * 1024 * 1024 * 1024)) {
throw new InvalidParameterValueException(String.format("Requested volume size is %s, but the maximum size allowed is %d GB.", NumbersUtil.toReadableSize(size), maxVolumeSize));
}
return true;
@ -1117,7 +1117,7 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
}
}
if (!validateVolumeSizeRange(newSize)) {
if (!validateVolumeSizeInBytes(newSize)) {
throw new InvalidParameterValueException("Requested size out of range");
}
@ -3534,8 +3534,6 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
@Override
public boolean configure(String name, Map<String, Object> params) {
String maxVolumeSizeInGbString = _configDao.getValue(Config.MaxVolumeSize.toString());
_maxVolumeSizeInGb = NumbersUtil.parseLong(maxVolumeSizeInGbString, 2000);
supportingDefaultHV = _hypervisorCapabilitiesDao.getHypervisorsWithDefaultEntries();
return true;
}

View File

@ -16,6 +16,7 @@
// under the License.
package com.cloud.vm;
import static com.cloud.configuration.ConfigurationManagerImpl.VM_USERDATA_MAX_LENGTH;
import static com.cloud.utils.NumbersUtil.toHumanReadableSize;
import java.io.IOException;
@ -26,6 +27,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
@ -50,8 +52,6 @@ import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import com.cloud.network.router.CommandSetupHelper;
import com.cloud.network.router.NetworkHelper;
import org.apache.cloudstack.acl.ControlledEntity;
import org.apache.cloudstack.acl.ControlledEntity.ACLType;
import org.apache.cloudstack.acl.SecurityChecker.AccessType;
@ -117,6 +117,7 @@ import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO;
import org.apache.cloudstack.utils.bytescale.ByteScaleUtils;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
@ -247,6 +248,8 @@ import com.cloud.network.dao.PhysicalNetworkDao;
import com.cloud.network.element.UserDataServiceProvider;
import com.cloud.network.guru.NetworkGuru;
import com.cloud.network.lb.LoadBalancingRulesManager;
import com.cloud.network.router.CommandSetupHelper;
import com.cloud.network.router.NetworkHelper;
import com.cloud.network.router.VpcVirtualNetworkApplianceManager;
import com.cloud.network.rules.FirewallManager;
import com.cloud.network.rules.FirewallRuleVO;
@ -355,10 +358,6 @@ import com.cloud.vm.dao.VMInstanceDao;
import com.cloud.vm.snapshot.VMSnapshotManager;
import com.cloud.vm.snapshot.VMSnapshotVO;
import com.cloud.vm.snapshot.dao.VMSnapshotDao;
import java.util.HashSet;
import org.apache.cloudstack.utils.bytescale.ByteScaleUtils;
import static com.cloud.configuration.ConfigurationManagerImpl.VM_USERDATA_MAX_LENGTH;
public class UserVmManagerImpl extends ManagerBase implements UserVmManager, VirtualMachineGuru, UserVmService, Configurable {
private static final Logger s_logger = Logger.getLogger(UserVmManagerImpl.class);
@ -3831,11 +3830,15 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
// check if account/domain is with in resource limits to create a new vm
boolean isIso = Storage.ImageFormat.ISO == template.getFormat();
long size = configureCustomRootDiskSize(customParameters, template, hypervisorType, offering);
long volumesSize = configureCustomRootDiskSize(customParameters, template, hypervisorType, offering);
if (diskOfferingId != null) {
long size = 0;
DiskOfferingVO diskOffering = _diskOfferingDao.findById(diskOfferingId);
if (diskOffering != null && diskOffering.isCustomized()) {
if (diskOffering == null) {
throw new InvalidParameterValueException("Specified disk offering cannot be found");
}
if (diskOffering.isCustomized()) {
if (diskSize == null) {
throw new InvalidParameterValueException("This disk offering requires a custom size specified");
}
@ -3845,16 +3848,19 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
throw new InvalidParameterValueException("VM Creation failed. Volume size: " + diskSize + "GB is out of allowed range. Max: " + customDiskOfferingMaxSize
+ " Min:" + customDiskOfferingMinSize);
}
size += diskSize * GiB_TO_BYTES;
size = diskSize * GiB_TO_BYTES;
} else {
size = diskOffering.getDiskSize();
}
size += _diskOfferingDao.findById(diskOfferingId).getDiskSize();
_volumeService.validateVolumeSizeInBytes(size);
volumesSize += size;
}
if (! VirtualMachineManager.ResourceCountRunningVMsonly.value()) {
resourceLimitCheck(owner, isDisplayVm, new Long(offering.getCpu()), new Long(offering.getRamSize()));
}
_resourceLimitMgr.checkResourceLimit(owner, ResourceType.volume, (isIso || diskOfferingId == null ? 1 : 2));
_resourceLimitMgr.checkResourceLimit(owner, ResourceType.primary_storage, size);
_resourceLimitMgr.checkResourceLimit(owner, ResourceType.primary_storage, volumesSize);
// verify security group ids
if (securityGroupIdList != null) {
@ -4177,6 +4183,7 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
DiskOfferingVO diskOffering = _diskOfferingDao.findById(serviceOffering.getId());
long rootDiskSizeInBytes = diskOffering.getDiskSize();
if (rootDiskSizeInBytes > 0) { //if the size at DiskOffering is not zero then the Service Offering had it configured, it holds priority over the User custom size
_volumeService.validateVolumeSizeInBytes(rootDiskSizeInBytes);
long rootDiskSizeInGiB = rootDiskSizeInBytes / GiB_TO_BYTES;
customParameters.put(VmDetailConstants.ROOT_DISK_SIZE, String.valueOf(rootDiskSizeInGiB));
return rootDiskSizeInBytes;
@ -4187,7 +4194,9 @@ public class UserVmManagerImpl extends ManagerBase implements UserVmManager, Vir
if (rootDiskSize <= 0) {
throw new InvalidParameterValueException("Root disk size should be a positive number.");
}
return rootDiskSize * GiB_TO_BYTES;
rootDiskSize *= GiB_TO_BYTES;
_volumeService.validateVolumeSizeInBytes(rootDiskSize);
return rootDiskSize;
} else {
// For baremetal, size can be 0 (zero)
Long templateSize = _templateDao.findById(template.getId()).getSize();

View File

@ -33,15 +33,6 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.cloud.configuration.Resource;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.storage.DiskOfferingVO;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.DiskOfferingDao;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.user.ResourceLimitService;
import com.cloud.user.dao.AccountDao;
import org.apache.cloudstack.api.BaseCmd.HTTPMethod;
import org.apache.cloudstack.api.command.user.vm.UpdateVMCmd;
import org.apache.cloudstack.api.command.user.volume.ResizeVolumeCmd;
@ -59,25 +50,35 @@ import org.mockito.Spy;
import org.mockito.junit.MockitoJUnitRunner;
import org.powermock.core.classloader.annotations.PrepareForTest;
import com.cloud.configuration.Resource;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.exception.InsufficientAddressCapacityException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.InvalidParameterValueException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.hypervisor.Hypervisor;
import com.cloud.network.NetworkModel;
import com.cloud.network.dao.NetworkDao;
import com.cloud.network.dao.NetworkVO;
import com.cloud.offering.ServiceOffering;
import com.cloud.service.ServiceOfferingVO;
import com.cloud.service.dao.ServiceOfferingDao;
import com.cloud.storage.DiskOfferingVO;
import com.cloud.storage.GuestOSVO;
import com.cloud.storage.Storage;
import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.VolumeApiService;
import com.cloud.storage.VolumeVO;
import com.cloud.storage.dao.DiskOfferingDao;
import com.cloud.storage.dao.GuestOSDao;
import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
import com.cloud.user.AccountVO;
import com.cloud.user.ResourceLimitService;
import com.cloud.user.UserVO;
import com.cloud.user.dao.AccountDao;
import com.cloud.uservm.UserVm;
import com.cloud.vm.dao.NicDao;
import com.cloud.vm.dao.UserVmDao;
@ -155,6 +156,9 @@ public class UserVmManagerImplTest {
@Mock
ResourceLimitService resourceLimitMgr;
@Mock
VolumeApiService volumeApiService;
private long vmId = 1l;
private static final long GiB_TO_BYTES = 1024 * 1024 * 1024;
@ -480,6 +484,7 @@ public class UserVmManagerImplTest {
Mockito.when(diskfferingVo.getDiskSize()).thenReturn(offeringRootDiskSize);
Mockito.when(volumeApiService.validateVolumeSizeInBytes(Mockito.anyLong())).thenReturn(true);
long rootDiskSize = userVmManagerImpl.configureCustomRootDiskSize(customParameters, template, Hypervisor.HypervisorType.KVM, offering);
Assert.assertEquals(expectedRootDiskSize, rootDiskSize);