mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
Copy template to target KVM host if needed when migrating local <> local storage (#3154)
* Migrate template to target host if needed. Fix KVM VM local storage live migration by migrating its template to the target host if needed. * Address reviewer and add method that updates the DB template reference * Remove deprecated Config.PrimaryStorageDownloadWait * Code formating of @Inject to follow checkstyle
This commit is contained in:
parent
3f17671449
commit
7c5eca9481
@ -101,6 +101,9 @@ public interface StorageManager extends StorageService {
|
||||
ConfigKey.Scope.Cluster,
|
||||
null);
|
||||
|
||||
ConfigKey<Integer> PRIMARY_STORAGE_DOWNLOAD_WAIT = new ConfigKey<Integer>("Storage", Integer.class, "primary.storage.download.wait", "10800",
|
||||
"In second, timeout for download template to primary storage", false);
|
||||
|
||||
/**
|
||||
* Returns a comma separated list of tags for the specified storage pool
|
||||
* @param poolId
|
||||
|
||||
@ -62,6 +62,7 @@ import com.cloud.configuration.Config;
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.hypervisor.Hypervisor;
|
||||
import com.cloud.storage.DataStoreRole;
|
||||
import com.cloud.storage.StorageManager;
|
||||
import com.cloud.storage.Storage.StoragePoolType;
|
||||
import com.cloud.storage.StoragePool;
|
||||
import com.cloud.storage.VolumeVO;
|
||||
@ -145,8 +146,7 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
|
||||
}
|
||||
|
||||
protected Answer copyObject(DataObject srcData, DataObject destData, Host destHost) {
|
||||
String value = configDao.getValue(Config.PrimaryStorageDownloadWait.toString());
|
||||
int _primaryStorageDownloadWait = NumbersUtil.parseInt(value, Integer.parseInt(Config.PrimaryStorageDownloadWait.getDefaultValue()));
|
||||
int primaryStorageDownloadWait = StorageManager.PRIMARY_STORAGE_DOWNLOAD_WAIT.value();
|
||||
Answer answer = null;
|
||||
DataObject cacheData = null;
|
||||
DataObject srcForCopy = srcData;
|
||||
@ -156,7 +156,8 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
|
||||
srcForCopy = cacheData = cacheMgr.createCacheObject(srcData, destScope);
|
||||
}
|
||||
|
||||
CopyCommand cmd = new CopyCommand(srcForCopy.getTO(), addFullCloneFlagOnVMwareDest(destData.getTO()), _primaryStorageDownloadWait, VirtualMachineManager.ExecuteInSequence.value());
|
||||
CopyCommand cmd = new CopyCommand(srcForCopy.getTO(), addFullCloneFlagOnVMwareDest(destData.getTO()), primaryStorageDownloadWait,
|
||||
VirtualMachineManager.ExecuteInSequence.value());
|
||||
EndPoint ep = destHost != null ? RemoteHostEndPoint.getHypervisorHostEndPoint(destHost) : selector.select(srcForCopy, destData);
|
||||
if (ep == null) {
|
||||
String errMsg = "No remote endpoint to send command, check if host or ssvm is down?";
|
||||
|
||||
@ -29,7 +29,13 @@ import org.apache.cloudstack.engine.subsystem.api.storage.StrategyPriority;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
|
||||
import org.apache.cloudstack.storage.command.CopyCommand;
|
||||
import org.apache.cloudstack.storage.datastore.DataStoreManagerImpl;
|
||||
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
|
||||
import org.apache.cloudstack.storage.to.TemplateObjectTO;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.MigrateCommand;
|
||||
@ -37,14 +43,22 @@ import com.cloud.agent.api.MigrateCommand.MigrateDiskInfo;
|
||||
import com.cloud.agent.api.storage.CreateAnswer;
|
||||
import com.cloud.agent.api.storage.CreateCommand;
|
||||
import com.cloud.agent.api.to.VirtualMachineTO;
|
||||
import com.cloud.exception.AgentUnavailableException;
|
||||
import com.cloud.exception.OperationTimedoutException;
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.storage.DataStoreRole;
|
||||
import com.cloud.storage.DiskOfferingVO;
|
||||
import com.cloud.storage.Storage.StoragePoolType;
|
||||
import com.cloud.storage.StorageManager;
|
||||
import com.cloud.storage.StoragePool;
|
||||
import com.cloud.storage.VMTemplateStoragePoolVO;
|
||||
import com.cloud.storage.VMTemplateStorageResourceAssoc;
|
||||
import com.cloud.storage.VolumeVO;
|
||||
import com.cloud.storage.dao.VMTemplatePoolDao;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.vm.DiskProfile;
|
||||
import com.cloud.vm.VirtualMachineManager;
|
||||
|
||||
/**
|
||||
* Extends {@link StorageSystemDataMotionStrategy}, allowing KVM hosts to migrate VMs with the ROOT volume on a non managed local storage pool.
|
||||
@ -54,6 +68,14 @@ public class KvmNonManagedStorageDataMotionStrategy extends StorageSystemDataMot
|
||||
|
||||
@Inject
|
||||
private TemplateDataFactory templateDataFactory;
|
||||
@Inject
|
||||
private VMTemplatePoolDao vmTemplatePoolDao;
|
||||
@Inject
|
||||
private DataStoreManagerImpl dataStoreManagerImpl;
|
||||
@Inject
|
||||
private VirtualMachineManager virtualMachineManager;
|
||||
|
||||
private static final Logger LOGGER = Logger.getLogger(KvmNonManagedStorageDataMotionStrategy.class);
|
||||
|
||||
/**
|
||||
* Uses the canHandle from the Super class {@link StorageSystemDataMotionStrategy}. If the storage pool is of file and the internalCanHandle from {@link StorageSystemDataMotionStrategy} CANT_HANDLE, returns the StrategyPriority.HYPERVISOR strategy priority. otherwise returns CANT_HANDLE.
|
||||
@ -95,7 +117,7 @@ public class KvmNonManagedStorageDataMotionStrategy extends StorageSystemDataMot
|
||||
String templateUuid = getTemplateUuid(destVolumeInfo.getTemplateId());
|
||||
CreateCommand rootImageProvisioningCommand = new CreateCommand(diskProfile, templateUuid, destStoragePool, true);
|
||||
|
||||
Answer rootImageProvisioningAnswer = _agentMgr.easySend(destHost.getId(), rootImageProvisioningCommand);
|
||||
Answer rootImageProvisioningAnswer = agentManager.easySend(destHost.getId(), rootImageProvisioningCommand);
|
||||
|
||||
if (rootImageProvisioningAnswer == null) {
|
||||
throw new CloudRuntimeException(String.format("Migration with storage of vm [%s] failed while provisioning root image", vmTO.getName()));
|
||||
@ -140,4 +162,77 @@ public class KvmNonManagedStorageDataMotionStrategy extends StorageSystemDataMot
|
||||
protected boolean shouldMigrateVolume(StoragePoolVO sourceStoragePool, Host destHost, StoragePoolVO destStoragePool) {
|
||||
return sourceStoragePool.getPoolType() == StoragePoolType.Filesystem;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the template is not on the target primary storage then it copies the template.
|
||||
*/
|
||||
@Override
|
||||
protected void copyTemplateToTargetFilesystemStorageIfNeeded(VolumeInfo srcVolumeInfo, StoragePool srcStoragePool, DataStore destDataStore, StoragePool destStoragePool,
|
||||
Host destHost) {
|
||||
VMTemplateStoragePoolVO sourceVolumeTemplateStoragePoolVO = vmTemplatePoolDao.findByPoolTemplate(destStoragePool.getId(), srcVolumeInfo.getTemplateId());
|
||||
if (sourceVolumeTemplateStoragePoolVO == null && destStoragePool.getPoolType() == StoragePoolType.Filesystem) {
|
||||
DataStore sourceTemplateDataStore = dataStoreManagerImpl.getImageStore(srcVolumeInfo.getDataCenterId());
|
||||
TemplateInfo sourceTemplateInfo = templateDataFactory.getTemplate(srcVolumeInfo.getTemplateId(), sourceTemplateDataStore);
|
||||
TemplateObjectTO sourceTemplate = new TemplateObjectTO(sourceTemplateInfo);
|
||||
|
||||
LOGGER.debug(String.format("Could not find template [id=%s, name=%s] on the storage pool [id=%s]; copying the template to the target storage pool.",
|
||||
srcVolumeInfo.getTemplateId(), sourceTemplateInfo.getName(), destDataStore.getId()));
|
||||
|
||||
TemplateInfo destTemplateInfo = templateDataFactory.getTemplate(srcVolumeInfo.getTemplateId(), destDataStore);
|
||||
final TemplateObjectTO destTemplate = new TemplateObjectTO(destTemplateInfo);
|
||||
Answer copyCommandAnswer = sendCopyCommand(destHost, sourceTemplate, destTemplate, destDataStore);
|
||||
|
||||
if (copyCommandAnswer != null && copyCommandAnswer.getResult()) {
|
||||
updateTemplateReferenceIfSuccessfulCopy(srcVolumeInfo, srcStoragePool, destTemplateInfo, destDataStore);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the template reference on table "template_spool_ref" (VMTemplateStoragePoolVO).
|
||||
*/
|
||||
protected void updateTemplateReferenceIfSuccessfulCopy(VolumeInfo srcVolumeInfo, StoragePool srcStoragePool, TemplateInfo destTemplateInfo, DataStore destDataStore) {
|
||||
VMTemplateStoragePoolVO srcVolumeTemplateStoragePoolVO = vmTemplatePoolDao.findByPoolTemplate(srcStoragePool.getId(), srcVolumeInfo.getTemplateId());
|
||||
VMTemplateStoragePoolVO destVolumeTemplateStoragePoolVO = new VMTemplateStoragePoolVO(destDataStore.getId(), srcVolumeInfo.getTemplateId());
|
||||
destVolumeTemplateStoragePoolVO.setDownloadPercent(100);
|
||||
destVolumeTemplateStoragePoolVO.setDownloadState(VMTemplateStorageResourceAssoc.Status.DOWNLOADED);
|
||||
destVolumeTemplateStoragePoolVO.setState(ObjectInDataStoreStateMachine.State.Ready);
|
||||
destVolumeTemplateStoragePoolVO.setTemplateSize(srcVolumeTemplateStoragePoolVO.getTemplateSize());
|
||||
destVolumeTemplateStoragePoolVO.setLocalDownloadPath(destTemplateInfo.getUuid());
|
||||
destVolumeTemplateStoragePoolVO.setInstallPath(destTemplateInfo.getUuid());
|
||||
vmTemplatePoolDao.persist(destVolumeTemplateStoragePoolVO);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the CopyCommand to migrate the template to the dest host.
|
||||
*/
|
||||
protected Answer sendCopyCommand(Host destHost, TemplateObjectTO sourceTemplate, TemplateObjectTO destTemplate, DataStore destDataStore) {
|
||||
boolean executeInSequence = virtualMachineManager.getExecuteInSequence(HypervisorType.KVM);
|
||||
CopyCommand copyCommand = new CopyCommand(sourceTemplate, destTemplate, StorageManager.PRIMARY_STORAGE_DOWNLOAD_WAIT.value(), executeInSequence);
|
||||
try {
|
||||
Answer copyCommandAnswer = agentManager.send(destHost.getId(), copyCommand);
|
||||
logInCaseOfTemplateCopyFailure(copyCommandAnswer, sourceTemplate, destDataStore);
|
||||
return copyCommandAnswer;
|
||||
} catch (AgentUnavailableException | OperationTimedoutException e) {
|
||||
throw new CloudRuntimeException(generateFailToCopyTemplateMessage(sourceTemplate, destDataStore), e);
|
||||
}
|
||||
}
|
||||
|
||||
private String generateFailToCopyTemplateMessage(TemplateObjectTO sourceTemplate, DataStore destDataStore) {
|
||||
return String.format("Failed to copy template [id=%s, name=%s] to the primary storage pool [id=%s].", sourceTemplate.getId(),
|
||||
sourceTemplate.getName(), destDataStore.getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs in debug mode the copy command failure if the CopyCommand Answer has result as false.
|
||||
*/
|
||||
protected void logInCaseOfTemplateCopyFailure(Answer copyCommandAnswer, TemplateObjectTO sourceTemplate, DataStore destDataStore) {
|
||||
if (copyCommandAnswer != null && !copyCommandAnswer.getResult()) {
|
||||
String failureDetails = StringUtils.EMPTY;
|
||||
if (copyCommandAnswer.getDetails() != null) {
|
||||
failureDetails = " Details: " + copyCommandAnswer.getDetails();
|
||||
}
|
||||
LOGGER.error(generateFailToCopyTemplateMessage(sourceTemplate, destDataStore) + failureDetails);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -112,7 +112,6 @@ import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
|
||||
import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
|
||||
import org.apache.cloudstack.storage.to.VolumeObjectTO;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.apache.commons.lang.math.NumberUtils;
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import org.springframework.stereotype.Component;
|
||||
@ -138,28 +137,45 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
||||
private static final String OPERATION_NOT_SUPPORTED = "This operation is not supported.";
|
||||
|
||||
@Inject
|
||||
protected AgentManager _agentMgr;
|
||||
@Inject private ConfigurationDao _configDao;
|
||||
@Inject private DataStoreManager dataStoreMgr;
|
||||
protected AgentManager agentManager;
|
||||
@Inject
|
||||
private ConfigurationDao _configDao;
|
||||
@Inject
|
||||
private DataStoreManager dataStoreMgr;
|
||||
@Inject
|
||||
protected DiskOfferingDao _diskOfferingDao;
|
||||
@Inject private GuestOSCategoryDao _guestOsCategoryDao;
|
||||
@Inject private GuestOSDao _guestOsDao;
|
||||
@Inject private ClusterDao clusterDao;
|
||||
@Inject private HostDao _hostDao;
|
||||
@Inject
|
||||
private GuestOSCategoryDao _guestOsCategoryDao;
|
||||
@Inject
|
||||
private GuestOSDao _guestOsDao;
|
||||
@Inject
|
||||
private ClusterDao clusterDao;
|
||||
@Inject
|
||||
private HostDao _hostDao;
|
||||
@Inject
|
||||
protected PrimaryDataStoreDao _storagePoolDao;
|
||||
@Inject private SnapshotDao _snapshotDao;
|
||||
@Inject private SnapshotDataStoreDao _snapshotDataStoreDao;
|
||||
@Inject private SnapshotDetailsDao _snapshotDetailsDao;
|
||||
@Inject private VMInstanceDao _vmDao;
|
||||
@Inject private VMTemplateDao _vmTemplateDao;
|
||||
@Inject private VolumeDao _volumeDao;
|
||||
@Inject private VolumeDataFactory _volumeDataFactory;
|
||||
@Inject private VolumeDetailsDao volumeDetailsDao;
|
||||
@Inject private VolumeService _volumeService;
|
||||
@Inject private StorageCacheManager cacheMgr;
|
||||
@Inject private EndPointSelector selector;
|
||||
@Inject
|
||||
private SnapshotDao _snapshotDao;
|
||||
@Inject
|
||||
private SnapshotDataStoreDao _snapshotDataStoreDao;
|
||||
@Inject
|
||||
private SnapshotDetailsDao _snapshotDetailsDao;
|
||||
@Inject
|
||||
private VMInstanceDao _vmDao;
|
||||
@Inject
|
||||
private VMTemplateDao _vmTemplateDao;
|
||||
@Inject
|
||||
private VolumeDao _volumeDao;
|
||||
@Inject
|
||||
private VolumeDataFactory _volumeDataFactory;
|
||||
@Inject
|
||||
private VolumeDetailsDao volumeDetailsDao;
|
||||
@Inject
|
||||
private VolumeService _volumeService;
|
||||
@Inject
|
||||
private StorageCacheManager cacheMgr;
|
||||
@Inject
|
||||
private EndPointSelector selector;
|
||||
|
||||
@Override
|
||||
public StrategyPriority canHandle(DataObject srcData, DataObject destData) {
|
||||
@ -926,8 +942,7 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
||||
}
|
||||
}
|
||||
|
||||
String value = _configDao.getValue(Config.PrimaryStorageDownloadWait.toString());
|
||||
int primaryStorageDownloadWait = NumbersUtil.parseInt(value, Integer.parseInt(Config.PrimaryStorageDownloadWait.getDefaultValue()));
|
||||
int primaryStorageDownloadWait = StorageManager.PRIMARY_STORAGE_DOWNLOAD_WAIT.value();
|
||||
CopyCommand copyCommand = new CopyCommand(snapshotInfo.getTO(), destOnStore.getTO(), primaryStorageDownloadWait,
|
||||
VirtualMachineManager.ExecuteInSequence.value());
|
||||
|
||||
@ -953,7 +968,7 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
||||
|
||||
copyCommand.setOptions(srcDetails);
|
||||
|
||||
copyCmdAnswer = (CopyCmdAnswer)_agentMgr.send(hostVO.getId(), copyCommand);
|
||||
copyCmdAnswer = (CopyCmdAnswer)agentManager.send(hostVO.getId(), copyCommand);
|
||||
|
||||
if (!copyCmdAnswer.getResult()) {
|
||||
errMsg = copyCmdAnswer.getDetails();
|
||||
@ -1101,8 +1116,7 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
||||
verifyCopyCmdAnswer(copyCmdAnswer, snapshotInfo);
|
||||
}
|
||||
|
||||
String value = _configDao.getValue(Config.PrimaryStorageDownloadWait.toString());
|
||||
int primaryStorageDownloadWait = NumbersUtil.parseInt(value, Integer.parseInt(Config.PrimaryStorageDownloadWait.getDefaultValue()));
|
||||
int primaryStorageDownloadWait = StorageManager.PRIMARY_STORAGE_DOWNLOAD_WAIT.value();
|
||||
|
||||
CopyCommand copyCommand = new CopyCommand(snapshotInfo.getTO(), volumeInfo.getTO(), primaryStorageDownloadWait,
|
||||
VirtualMachineManager.ExecuteInSequence.value());
|
||||
@ -1120,7 +1134,7 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
||||
|
||||
copyCommand.setOptions(srcDetails);
|
||||
|
||||
copyCmdAnswer = (CopyCmdAnswer)_agentMgr.send(hostVO.getId(), copyCommand);
|
||||
copyCmdAnswer = (CopyCmdAnswer)agentManager.send(hostVO.getId(), copyCommand);
|
||||
|
||||
if (!copyCmdAnswer.getResult()) {
|
||||
errMsg = copyCmdAnswer.getDetails();
|
||||
@ -1594,8 +1608,7 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
||||
}
|
||||
|
||||
private CopyCmdAnswer copyImageToVolume(DataObject srcDataObject, VolumeInfo destVolumeInfo, HostVO hostVO) {
|
||||
String value = _configDao.getValue(Config.PrimaryStorageDownloadWait.toString());
|
||||
int primaryStorageDownloadWait = NumbersUtil.parseInt(value, Integer.parseInt(Config.PrimaryStorageDownloadWait.getDefaultValue()));
|
||||
int primaryStorageDownloadWait = StorageManager.PRIMARY_STORAGE_DOWNLOAD_WAIT.value();
|
||||
|
||||
CopyCommand copyCommand = new CopyCommand(srcDataObject.getTO(), destVolumeInfo.getTO(), primaryStorageDownloadWait,
|
||||
VirtualMachineManager.ExecuteInSequence.value());
|
||||
@ -1609,7 +1622,7 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
||||
|
||||
copyCommand.setOptions2(destDetails);
|
||||
|
||||
copyCmdAnswer = (CopyCmdAnswer)_agentMgr.send(hostVO.getId(), copyCommand);
|
||||
copyCmdAnswer = (CopyCmdAnswer)agentManager.send(hostVO.getId(), copyCommand);
|
||||
}
|
||||
catch (CloudRuntimeException | AgentUnavailableException | OperationTimedoutException ex) {
|
||||
String msg = "Failed to copy image : ";
|
||||
@ -1724,6 +1737,8 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
||||
continue;
|
||||
}
|
||||
|
||||
copyTemplateToTargetFilesystemStorageIfNeeded(srcVolumeInfo, sourceStoragePool, destDataStore, destStoragePool, destHost);
|
||||
|
||||
VolumeVO destVolume = duplicateVolumeOnAnotherStorage(srcVolume, destStoragePool);
|
||||
VolumeInfo destVolumeInfo = _volumeDataFactory.getVolume(destVolume.getId(), destDataStore);
|
||||
|
||||
@ -1763,7 +1778,7 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
||||
PrepareForMigrationCommand pfmc = new PrepareForMigrationCommand(vmTO);
|
||||
|
||||
try {
|
||||
Answer pfma = _agentMgr.send(destHost.getId(), pfmc);
|
||||
Answer pfma = agentManager.send(destHost.getId(), pfmc);
|
||||
|
||||
if (pfma == null || !pfma.getResult()) {
|
||||
String details = pfma != null ? pfma.getDetails() : "null answer returned";
|
||||
@ -1791,7 +1806,7 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
||||
|
||||
migrateCommand.setAutoConvergence(kvmAutoConvergence);
|
||||
|
||||
MigrateAnswer migrateAnswer = (MigrateAnswer)_agentMgr.send(srcHost.getId(), migrateCommand);
|
||||
MigrateAnswer migrateAnswer = (MigrateAnswer)agentManager.send(srcHost.getId(), migrateCommand);
|
||||
|
||||
boolean success = migrateAnswer != null && migrateAnswer.getResult();
|
||||
|
||||
@ -1859,6 +1874,15 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
||||
volume.setPath(volume.get_iScsiName());
|
||||
}
|
||||
|
||||
/**
|
||||
* For this strategy it is not necessary to copy the template before migrating the VM.
|
||||
* However, classes that extend this one may need to copy the template to the target storage pool before migrating the VM.
|
||||
*/
|
||||
protected void copyTemplateToTargetFilesystemStorageIfNeeded(VolumeInfo srcVolumeInfo, StoragePool srcStoragePool, DataStore destDataStore, StoragePool destStoragePool,
|
||||
Host destHost) {
|
||||
// This method is used by classes that extend this one
|
||||
}
|
||||
|
||||
private void handlePostMigration(boolean success, Map<VolumeInfo, VolumeInfo> srcVolumeInfoToDestVolumeInfo, VirtualMachineTO vmTO, Host destHost) {
|
||||
if (!success) {
|
||||
try {
|
||||
@ -1866,7 +1890,7 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
||||
|
||||
pfmc.setRollback(true);
|
||||
|
||||
Answer pfma = _agentMgr.send(destHost.getId(), pfmc);
|
||||
Answer pfma = agentManager.send(destHost.getId(), pfmc);
|
||||
|
||||
if (pfma == null || !pfma.getResult()) {
|
||||
String details = pfma != null ? pfma.getDetails() : "null answer returned";
|
||||
@ -2007,7 +2031,7 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
||||
}
|
||||
|
||||
private List<String> sendModifyTargetsCommand(ModifyTargetsCommand cmd, long hostId) {
|
||||
ModifyTargetsAnswer modifyTargetsAnswer = (ModifyTargetsAnswer)_agentMgr.easySend(hostId, cmd);
|
||||
ModifyTargetsAnswer modifyTargetsAnswer = (ModifyTargetsAnswer)agentManager.easySend(hostId, cmd);
|
||||
|
||||
if (modifyTargetsAnswer == null) {
|
||||
throw new CloudRuntimeException("Unable to get an answer to the modify targets command");
|
||||
@ -2109,8 +2133,7 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
||||
HostVO hostVO = getHost(volumeInfo.getDataCenterId(), HypervisorType.KVM, false);
|
||||
DataStore srcDataStore = volumeInfo.getDataStore();
|
||||
|
||||
String value = _configDao.getValue(Config.PrimaryStorageDownloadWait.toString());
|
||||
int primaryStorageDownloadWait = NumberUtils.toInt(value, Integer.parseInt(Config.PrimaryStorageDownloadWait.getDefaultValue()));
|
||||
int primaryStorageDownloadWait = StorageManager.PRIMARY_STORAGE_DOWNLOAD_WAIT.value();
|
||||
|
||||
CopyCommand copyCommand = new CopyCommand(volumeInfo.getTO(), templateInfo.getTO(), primaryStorageDownloadWait, VirtualMachineManager.ExecuteInSequence.value());
|
||||
|
||||
@ -2125,7 +2148,7 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
||||
|
||||
copyCommand.setOptions(srcDetails);
|
||||
|
||||
copyCmdAnswer = (CopyCmdAnswer)_agentMgr.send(hostVO.getId(), copyCommand);
|
||||
copyCmdAnswer = (CopyCmdAnswer)agentManager.send(hostVO.getId(), copyCommand);
|
||||
|
||||
if (!copyCmdAnswer.getResult()) {
|
||||
errMsg = copyCmdAnswer.getDetails();
|
||||
@ -2389,7 +2412,7 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
||||
try {
|
||||
_volumeService.grantAccess(dataObj, hostVO, dataStore);
|
||||
|
||||
answer = (ResignatureAnswer)_agentMgr.send(hostVO.getId(), command);
|
||||
answer = (ResignatureAnswer)agentManager.send(hostVO.getId(), command);
|
||||
}
|
||||
catch (CloudRuntimeException | AgentUnavailableException | OperationTimedoutException ex) {
|
||||
keepGrantedAccess = false;
|
||||
@ -2466,7 +2489,7 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
||||
|
||||
_volumeService.grantAccess(destVolumeInfo, hostVO, destVolumeInfo.getDataStore());
|
||||
|
||||
MigrateVolumeAnswer migrateVolumeAnswer = (MigrateVolumeAnswer)_agentMgr.send(hostVO.getId(), migrateVolumeCommand);
|
||||
MigrateVolumeAnswer migrateVolumeAnswer = (MigrateVolumeAnswer)agentManager.send(hostVO.getId(), migrateVolumeCommand);
|
||||
|
||||
if (migrateVolumeAnswer == null || !migrateVolumeAnswer.getResult()) {
|
||||
if (migrateVolumeAnswer != null && !StringUtils.isEmpty(migrateVolumeAnswer.getDetails())) {
|
||||
@ -2534,7 +2557,7 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
||||
_volumeService.grantAccess(srcVolumeInfo, hostVO, srcVolumeInfo.getDataStore());
|
||||
}
|
||||
|
||||
CopyVolumeAnswer copyVolumeAnswer = (CopyVolumeAnswer)_agentMgr.send(hostVO.getId(), copyVolumeCommand);
|
||||
CopyVolumeAnswer copyVolumeAnswer = (CopyVolumeAnswer)agentManager.send(hostVO.getId(), copyVolumeCommand);
|
||||
|
||||
if (copyVolumeAnswer == null || !copyVolumeAnswer.getResult()) {
|
||||
if (copyVolumeAnswer != null && !StringUtils.isEmpty(copyVolumeAnswer.getDetails())) {
|
||||
@ -2592,8 +2615,7 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
||||
private CopyCmdAnswer performCopyOfVdi(VolumeInfo volumeInfo, SnapshotInfo snapshotInfo, HostVO hostVO) {
|
||||
Snapshot.LocationType locationType = snapshotInfo.getLocationType();
|
||||
|
||||
String value = _configDao.getValue(Config.PrimaryStorageDownloadWait.toString());
|
||||
int primaryStorageDownloadWait = NumbersUtil.parseInt(value, Integer.parseInt(Config.PrimaryStorageDownloadWait.getDefaultValue()));
|
||||
int primaryStorageDownloadWait = StorageManager.PRIMARY_STORAGE_DOWNLOAD_WAIT.value();
|
||||
|
||||
DataObject srcData = snapshotInfo;
|
||||
CopyCmdAnswer copyCmdAnswer = null;
|
||||
@ -2623,7 +2645,7 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
||||
|
||||
copyCommand.setOptions2(destDetails);
|
||||
|
||||
copyCmdAnswer = (CopyCmdAnswer)_agentMgr.send(hostVO.getId(), copyCommand);
|
||||
copyCmdAnswer = (CopyCmdAnswer)agentManager.send(hostVO.getId(), copyCommand);
|
||||
}
|
||||
catch (CloudRuntimeException | AgentUnavailableException | OperationTimedoutException ex) {
|
||||
String msg = "Failed to perform VDI copy : ";
|
||||
|
||||
@ -25,14 +25,22 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.StrategyPriority;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
|
||||
import org.apache.cloudstack.storage.command.CopyCommand;
|
||||
import org.apache.cloudstack.storage.datastore.DataStoreManagerImpl;
|
||||
import org.apache.cloudstack.storage.datastore.PrimaryDataStoreImpl;
|
||||
import org.apache.cloudstack.storage.datastore.db.ImageStoreVO;
|
||||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
|
||||
import org.apache.cloudstack.storage.image.datastore.ImageStoreEntity;
|
||||
import org.apache.cloudstack.storage.image.store.ImageStoreImpl;
|
||||
import org.apache.cloudstack.storage.to.TemplateObjectTO;
|
||||
import org.apache.cloudstack.storage.volume.VolumeObject;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InOrder;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
@ -40,37 +48,52 @@ import org.mockito.Spy;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
import com.cloud.agent.AgentManager;
|
||||
import com.cloud.agent.api.Answer;
|
||||
import com.cloud.agent.api.MigrateCommand;
|
||||
import com.cloud.agent.api.storage.CreateAnswer;
|
||||
import com.cloud.agent.api.storage.CreateCommand;
|
||||
import com.cloud.agent.api.to.VirtualMachineTO;
|
||||
import com.cloud.agent.api.to.VolumeTO;
|
||||
import com.cloud.exception.AgentUnavailableException;
|
||||
import com.cloud.exception.CloudException;
|
||||
import com.cloud.exception.OperationTimedoutException;
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.host.HostVO;
|
||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||
import com.cloud.storage.DataStoreRole;
|
||||
import com.cloud.storage.DiskOfferingVO;
|
||||
import com.cloud.storage.Storage;
|
||||
import com.cloud.storage.StoragePool;
|
||||
import com.cloud.storage.VMTemplateStoragePoolVO;
|
||||
import com.cloud.storage.Storage.ImageFormat;
|
||||
import com.cloud.storage.Storage.StoragePoolType;
|
||||
import com.cloud.storage.Volume;
|
||||
import com.cloud.storage.VolumeVO;
|
||||
import com.cloud.storage.dao.DiskOfferingDao;
|
||||
import com.cloud.storage.dao.VMTemplatePoolDao;
|
||||
import com.cloud.utils.exception.CloudRuntimeException;
|
||||
import com.cloud.vm.DiskProfile;
|
||||
import com.cloud.vm.VirtualMachineManager;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class KvmNonManagedStorageSystemDataMotionTest {
|
||||
|
||||
@Mock
|
||||
private PrimaryDataStoreDao primaryDataStoreDao;
|
||||
|
||||
@Mock
|
||||
private TemplateDataFactory templateDataFactory;
|
||||
|
||||
@Mock
|
||||
private AgentManager agentManager;
|
||||
|
||||
@Mock
|
||||
private DiskOfferingDao diskOfferingDao;
|
||||
@Mock
|
||||
private VirtualMachineManager virtualMachineManager;
|
||||
@Mock
|
||||
private VMTemplatePoolDao vmTemplatePoolDao;
|
||||
@Mock
|
||||
private DataStoreManagerImpl dataStoreManagerImpl;
|
||||
@Mock
|
||||
private VolumeDataFactory volumeDataFactory;
|
||||
|
||||
@Spy
|
||||
@InjectMocks
|
||||
@ -253,4 +276,125 @@ public class KvmNonManagedStorageSystemDataMotionTest {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sendCopyCommandTest() throws AgentUnavailableException, OperationTimedoutException {
|
||||
configureAndTestSendCommandTest(null);
|
||||
}
|
||||
|
||||
@Test(expected = CloudRuntimeException.class)
|
||||
public void sendCopyCommandTestThrowAgentUnavailableException() throws AgentUnavailableException, OperationTimedoutException {
|
||||
configureAndTestSendCommandTest(AgentUnavailableException.class);
|
||||
}
|
||||
|
||||
@Test(expected = CloudRuntimeException.class)
|
||||
public void sendCopyCommandTestThrowOperationTimedoutException() throws AgentUnavailableException, OperationTimedoutException {
|
||||
configureAndTestSendCommandTest(OperationTimedoutException.class);
|
||||
}
|
||||
|
||||
private void configureAndTestSendCommandTest(Class<? extends CloudException> exception) throws AgentUnavailableException, OperationTimedoutException {
|
||||
Host destHost = new HostVO("guid");
|
||||
TemplateObjectTO sourceTemplate = new TemplateObjectTO();
|
||||
sourceTemplate.setName("name");
|
||||
sourceTemplate.setId(0l);
|
||||
TemplateObjectTO destTemplate = new TemplateObjectTO();
|
||||
ImageStoreVO dataStoreVO = Mockito.mock(ImageStoreVO.class);
|
||||
Mockito.when(dataStoreVO.getId()).thenReturn(0l);
|
||||
|
||||
ImageStoreEntity destDataStore = Mockito.mock(ImageStoreImpl.class);
|
||||
Mockito.doReturn(0l).when(destDataStore).getId();
|
||||
|
||||
Answer copyCommandAnswer = Mockito.mock(Answer.class);
|
||||
|
||||
if (exception == null) {
|
||||
Mockito.doReturn(copyCommandAnswer).when(agentManager).send(Mockito.anyLong(), Mockito.any(CopyCommand.class));
|
||||
} else {
|
||||
Mockito.doThrow(exception).when(agentManager).send(Mockito.anyLong(), Mockito.any(CopyCommand.class));
|
||||
}
|
||||
|
||||
Mockito.doNothing().when(kvmNonManagedStorageDataMotionStrategy).logInCaseOfTemplateCopyFailure(Mockito.any(Answer.class), Mockito.any(TemplateObjectTO.class),
|
||||
Mockito.any(DataStore.class));
|
||||
|
||||
kvmNonManagedStorageDataMotionStrategy.sendCopyCommand(destHost, sourceTemplate, destTemplate, destDataStore);
|
||||
|
||||
InOrder verifyInOrder = Mockito.inOrder(virtualMachineManager, agentManager, kvmNonManagedStorageDataMotionStrategy);
|
||||
|
||||
verifyInOrder.verify(virtualMachineManager).getExecuteInSequence(HypervisorType.KVM);
|
||||
verifyInOrder.verify(agentManager).send(Mockito.anyLong(), Mockito.any(CopyCommand.class));
|
||||
verifyInOrder.verify(kvmNonManagedStorageDataMotionStrategy).logInCaseOfTemplateCopyFailure(Mockito.any(Answer.class), Mockito.any(TemplateObjectTO.class),
|
||||
Mockito.any(DataStore.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void copyTemplateToTargetStorageIfNeededTestTemplateAlreadyOnTargetHost() throws AgentUnavailableException, OperationTimedoutException {
|
||||
Answer copyCommandAnswer = Mockito.mock(Answer.class);
|
||||
Mockito.when(copyCommandAnswer.getResult()).thenReturn(true);
|
||||
configureAndTestcopyTemplateToTargetStorageIfNeeded(new VMTemplateStoragePoolVO(0l, 0l), StoragePoolType.Filesystem, 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void migrateTemplateToTargetStorageIfNeededTestTemplateNotOnTargetHost() throws AgentUnavailableException, OperationTimedoutException {
|
||||
configureAndTestcopyTemplateToTargetStorageIfNeeded(null, StoragePoolType.Filesystem, 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void migrateTemplateToTargetStorageIfNeededTestNonDesiredStoragePoolType() throws AgentUnavailableException, OperationTimedoutException {
|
||||
StoragePoolType[] storagePoolTypeArray = StoragePoolType.values();
|
||||
for (int i = 0; i < storagePoolTypeArray.length; i++) {
|
||||
if (storagePoolTypeArray[i] == StoragePoolType.Filesystem) {
|
||||
continue;
|
||||
}
|
||||
configureAndTestcopyTemplateToTargetStorageIfNeeded(new VMTemplateStoragePoolVO(0l, 0l), storagePoolTypeArray[i], 0);
|
||||
}
|
||||
}
|
||||
|
||||
private void configureAndTestcopyTemplateToTargetStorageIfNeeded(VMTemplateStoragePoolVO vmTemplateStoragePoolVO, StoragePoolType storagePoolType, int times) {
|
||||
DataStore destDataStore = Mockito.mock(DataStore.class);
|
||||
Host destHost = Mockito.mock(Host.class);
|
||||
|
||||
VolumeInfo srcVolumeInfo = Mockito.mock(VolumeInfo.class);
|
||||
Mockito.when(srcVolumeInfo.getTemplateId()).thenReturn(0l);
|
||||
|
||||
StoragePool srcStoragePool = Mockito.mock(StoragePool.class);
|
||||
|
||||
VolumeInfo destVolumeInfo = Mockito.mock(VolumeInfo.class);
|
||||
Mockito.when(volumeDataFactory.getVolume(Mockito.anyLong(), Mockito.any(DataStore.class))).thenReturn(destVolumeInfo);
|
||||
|
||||
StoragePool destStoragePool = Mockito.mock(StoragePool.class);
|
||||
Mockito.when(destStoragePool.getId()).thenReturn(0l);
|
||||
Mockito.when(destStoragePool.getPoolType()).thenReturn(storagePoolType);
|
||||
|
||||
DataStore sourceTemplateDataStore = Mockito.mock(DataStore.class);
|
||||
Mockito.when(sourceTemplateDataStore.getName()).thenReturn("sourceTemplateName");
|
||||
|
||||
TemplateInfo sourceTemplateInfo = Mockito.mock(TemplateInfo.class);
|
||||
Mockito.when(sourceTemplateInfo.getInstallPath()).thenReturn("installPath");
|
||||
Mockito.when(sourceTemplateInfo.getUuid()).thenReturn("uuid");
|
||||
Mockito.when(sourceTemplateInfo.getId()).thenReturn(0l);
|
||||
Mockito.when(sourceTemplateInfo.getUrl()).thenReturn("url");
|
||||
Mockito.when(sourceTemplateInfo.getDisplayText()).thenReturn("display text");
|
||||
Mockito.when(sourceTemplateInfo.getChecksum()).thenReturn("checksum");
|
||||
Mockito.when(sourceTemplateInfo.isRequiresHvm()).thenReturn(true);
|
||||
Mockito.when(sourceTemplateInfo.getAccountId()).thenReturn(0l);
|
||||
Mockito.when(sourceTemplateInfo.getUniqueName()).thenReturn("unique name");
|
||||
Mockito.when(sourceTemplateInfo.getFormat()).thenReturn(ImageFormat.QCOW2);
|
||||
Mockito.when(sourceTemplateInfo.getSize()).thenReturn(0l);
|
||||
Mockito.when(sourceTemplateInfo.getHypervisorType()).thenReturn(HypervisorType.KVM);
|
||||
|
||||
Mockito.when(vmTemplatePoolDao.findByPoolTemplate(Mockito.anyLong(), Mockito.anyLong())).thenReturn(vmTemplateStoragePoolVO);
|
||||
Mockito.when(dataStoreManagerImpl.getImageStore(Mockito.anyLong())).thenReturn(sourceTemplateDataStore);
|
||||
Mockito.when(templateDataFactory.getTemplate(Mockito.anyLong(), Mockito.eq(sourceTemplateDataStore))).thenReturn(sourceTemplateInfo);
|
||||
Mockito.when(templateDataFactory.getTemplate(Mockito.anyLong(), Mockito.eq(destDataStore))).thenReturn(sourceTemplateInfo);
|
||||
kvmNonManagedStorageDataMotionStrategy.copyTemplateToTargetFilesystemStorageIfNeeded(srcVolumeInfo, srcStoragePool, destDataStore, destStoragePool, destHost);
|
||||
Mockito.doNothing().when(kvmNonManagedStorageDataMotionStrategy).updateTemplateReferenceIfSuccessfulCopy(Mockito.any(VolumeInfo.class), Mockito.any(StoragePool.class),
|
||||
Mockito.any(TemplateInfo.class), Mockito.any(DataStore.class));
|
||||
|
||||
InOrder verifyInOrder = Mockito.inOrder(vmTemplatePoolDao, dataStoreManagerImpl, templateDataFactory, kvmNonManagedStorageDataMotionStrategy);
|
||||
verifyInOrder.verify(vmTemplatePoolDao, Mockito.times(1)).findByPoolTemplate(Mockito.anyLong(), Mockito.anyLong());
|
||||
verifyInOrder.verify(dataStoreManagerImpl, Mockito.times(times)).getImageStore(Mockito.anyLong());
|
||||
verifyInOrder.verify(templateDataFactory, Mockito.times(times)).getTemplate(Mockito.anyLong(), Mockito.eq(sourceTemplateDataStore));
|
||||
verifyInOrder.verify(templateDataFactory, Mockito.times(times)).getTemplate(Mockito.anyLong(), Mockito.eq(destDataStore));
|
||||
verifyInOrder.verify(kvmNonManagedStorageDataMotionStrategy, Mockito.times(times)).sendCopyCommand(Mockito.eq(destHost), Mockito.any(TemplateObjectTO.class),
|
||||
Mockito.any(TemplateObjectTO.class), Mockito.eq(destDataStore));
|
||||
}
|
||||
}
|
||||
|
||||
@ -61,7 +61,6 @@ import com.cloud.agent.api.to.DataObjectType;
|
||||
import com.cloud.agent.api.to.DataStoreTO;
|
||||
import com.cloud.agent.api.to.DataTO;
|
||||
import com.cloud.agent.api.to.StorageFilerTO;
|
||||
import com.cloud.configuration.Config;
|
||||
import com.cloud.exception.StorageUnavailableException;
|
||||
import com.cloud.host.Host;
|
||||
import com.cloud.host.dao.HostDao;
|
||||
@ -77,7 +76,6 @@ import com.cloud.storage.dao.VMTemplateDao;
|
||||
import com.cloud.storage.dao.VolumeDao;
|
||||
import com.cloud.storage.snapshot.SnapshotManager;
|
||||
import com.cloud.template.TemplateManager;
|
||||
import com.cloud.utils.NumbersUtil;
|
||||
import com.cloud.vm.dao.VMInstanceDao;
|
||||
|
||||
public class CloudStackPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver {
|
||||
@ -256,13 +254,12 @@ public class CloudStackPrimaryDataStoreDriverImpl implements PrimaryDataStoreDri
|
||||
callback.complete(result);
|
||||
} else if (srcdata.getType() == DataObjectType.TEMPLATE && destData.getType() == DataObjectType.VOLUME) {
|
||||
//For CLVM, we need to pass template on secondary storage to hypervisor
|
||||
String value = configDao.getValue(Config.PrimaryStorageDownloadWait.toString());
|
||||
int _primaryStorageDownloadWait = NumbersUtil.parseInt(value, Integer.parseInt(Config.PrimaryStorageDownloadWait.getDefaultValue()));
|
||||
int primaryStorageDownloadWait = StorageManager.PRIMARY_STORAGE_DOWNLOAD_WAIT.value();
|
||||
StoragePoolVO storagePoolVO = primaryStoreDao.findById(store.getId());
|
||||
DataStore imageStore = templateManager.getImageStore(storagePoolVO.getDataCenterId(), srcdata.getId());
|
||||
DataObject srcData = templateDataFactory.getTemplate(srcdata.getId(), imageStore);
|
||||
|
||||
CopyCommand cmd = new CopyCommand(srcData.getTO(), destData.getTO(), _primaryStorageDownloadWait, true);
|
||||
CopyCommand cmd = new CopyCommand(srcData.getTO(), destData.getTO(), primaryStorageDownloadWait, true);
|
||||
EndPoint ep = epSelector.select(srcData, destData);
|
||||
Answer answer = null;
|
||||
if (ep == null) {
|
||||
|
||||
@ -187,14 +187,6 @@ public enum Config {
|
||||
"3600",
|
||||
"Timeout (in seconds) to synchronize storage pool operations.",
|
||||
null),
|
||||
PrimaryStorageDownloadWait(
|
||||
"Storage",
|
||||
TemplateManager.class,
|
||||
Integer.class,
|
||||
"primary.storage.download.wait",
|
||||
"10800",
|
||||
"In second, timeout for download template to primary storage",
|
||||
null),
|
||||
CreateVolumeFromSnapshotWait(
|
||||
"Storage",
|
||||
StorageManager.class,
|
||||
|
||||
@ -2489,7 +2489,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
|
||||
@Override
|
||||
public ConfigKey<?>[] getConfigKeys() {
|
||||
return new ConfigKey<?>[] { StorageCleanupInterval, StorageCleanupDelay, StorageCleanupEnabled, TemplateCleanupEnabled,
|
||||
KvmStorageOfflineMigrationWait, KvmStorageOnlineMigrationWait, MaxNumberOfManagedClusteredFileSystems };
|
||||
KvmStorageOfflineMigrationWait, KvmStorageOnlineMigrationWait, MaxNumberOfManagedClusteredFileSystems, PRIMARY_STORAGE_DOWNLOAD_WAIT};
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user