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,
|
ConfigKey.Scope.Cluster,
|
||||||
null);
|
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
|
* Returns a comma separated list of tags for the specified storage pool
|
||||||
* @param poolId
|
* @param poolId
|
||||||
|
|||||||
@ -62,6 +62,7 @@ import com.cloud.configuration.Config;
|
|||||||
import com.cloud.host.Host;
|
import com.cloud.host.Host;
|
||||||
import com.cloud.hypervisor.Hypervisor;
|
import com.cloud.hypervisor.Hypervisor;
|
||||||
import com.cloud.storage.DataStoreRole;
|
import com.cloud.storage.DataStoreRole;
|
||||||
|
import com.cloud.storage.StorageManager;
|
||||||
import com.cloud.storage.Storage.StoragePoolType;
|
import com.cloud.storage.Storage.StoragePoolType;
|
||||||
import com.cloud.storage.StoragePool;
|
import com.cloud.storage.StoragePool;
|
||||||
import com.cloud.storage.VolumeVO;
|
import com.cloud.storage.VolumeVO;
|
||||||
@ -145,8 +146,7 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected Answer copyObject(DataObject srcData, DataObject destData, Host destHost) {
|
protected Answer copyObject(DataObject srcData, DataObject destData, Host destHost) {
|
||||||
String value = configDao.getValue(Config.PrimaryStorageDownloadWait.toString());
|
int primaryStorageDownloadWait = StorageManager.PRIMARY_STORAGE_DOWNLOAD_WAIT.value();
|
||||||
int _primaryStorageDownloadWait = NumbersUtil.parseInt(value, Integer.parseInt(Config.PrimaryStorageDownloadWait.getDefaultValue()));
|
|
||||||
Answer answer = null;
|
Answer answer = null;
|
||||||
DataObject cacheData = null;
|
DataObject cacheData = null;
|
||||||
DataObject srcForCopy = srcData;
|
DataObject srcForCopy = srcData;
|
||||||
@ -156,7 +156,8 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
|
|||||||
srcForCopy = cacheData = cacheMgr.createCacheObject(srcData, destScope);
|
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);
|
EndPoint ep = destHost != null ? RemoteHostEndPoint.getHypervisorHostEndPoint(destHost) : selector.select(srcForCopy, destData);
|
||||||
if (ep == null) {
|
if (ep == null) {
|
||||||
String errMsg = "No remote endpoint to send command, check if host or ssvm is down?";
|
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.TemplateDataFactory;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
|
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.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.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.Answer;
|
||||||
import com.cloud.agent.api.MigrateCommand;
|
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.CreateAnswer;
|
||||||
import com.cloud.agent.api.storage.CreateCommand;
|
import com.cloud.agent.api.storage.CreateCommand;
|
||||||
import com.cloud.agent.api.to.VirtualMachineTO;
|
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.host.Host;
|
||||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||||
import com.cloud.storage.DataStoreRole;
|
import com.cloud.storage.DataStoreRole;
|
||||||
import com.cloud.storage.DiskOfferingVO;
|
import com.cloud.storage.DiskOfferingVO;
|
||||||
import com.cloud.storage.Storage.StoragePoolType;
|
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.VolumeVO;
|
||||||
|
import com.cloud.storage.dao.VMTemplatePoolDao;
|
||||||
import com.cloud.utils.exception.CloudRuntimeException;
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
import com.cloud.vm.DiskProfile;
|
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.
|
* 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
|
@Inject
|
||||||
private TemplateDataFactory templateDataFactory;
|
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.
|
* 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());
|
String templateUuid = getTemplateUuid(destVolumeInfo.getTemplateId());
|
||||||
CreateCommand rootImageProvisioningCommand = new CreateCommand(diskProfile, templateUuid, destStoragePool, true);
|
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) {
|
if (rootImageProvisioningAnswer == null) {
|
||||||
throw new CloudRuntimeException(String.format("Migration with storage of vm [%s] failed while provisioning root image", vmTO.getName()));
|
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) {
|
protected boolean shouldMigrateVolume(StoragePoolVO sourceStoragePool, Host destHost, StoragePoolVO destStoragePool) {
|
||||||
return sourceStoragePool.getPoolType() == StoragePoolType.Filesystem;
|
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.PrimaryDataStoreTO;
|
||||||
import org.apache.cloudstack.storage.to.VolumeObjectTO;
|
import org.apache.cloudstack.storage.to.VolumeObjectTO;
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.apache.commons.lang.math.NumberUtils;
|
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import org.springframework.stereotype.Component;
|
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.";
|
private static final String OPERATION_NOT_SUPPORTED = "This operation is not supported.";
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
protected AgentManager _agentMgr;
|
protected AgentManager agentManager;
|
||||||
@Inject private ConfigurationDao _configDao;
|
@Inject
|
||||||
@Inject private DataStoreManager dataStoreMgr;
|
private ConfigurationDao _configDao;
|
||||||
|
@Inject
|
||||||
|
private DataStoreManager dataStoreMgr;
|
||||||
@Inject
|
@Inject
|
||||||
protected DiskOfferingDao _diskOfferingDao;
|
protected DiskOfferingDao _diskOfferingDao;
|
||||||
@Inject private GuestOSCategoryDao _guestOsCategoryDao;
|
@Inject
|
||||||
@Inject private GuestOSDao _guestOsDao;
|
private GuestOSCategoryDao _guestOsCategoryDao;
|
||||||
@Inject private ClusterDao clusterDao;
|
@Inject
|
||||||
@Inject private HostDao _hostDao;
|
private GuestOSDao _guestOsDao;
|
||||||
|
@Inject
|
||||||
|
private ClusterDao clusterDao;
|
||||||
|
@Inject
|
||||||
|
private HostDao _hostDao;
|
||||||
@Inject
|
@Inject
|
||||||
protected PrimaryDataStoreDao _storagePoolDao;
|
protected PrimaryDataStoreDao _storagePoolDao;
|
||||||
@Inject private SnapshotDao _snapshotDao;
|
@Inject
|
||||||
@Inject private SnapshotDataStoreDao _snapshotDataStoreDao;
|
private SnapshotDao _snapshotDao;
|
||||||
@Inject private SnapshotDetailsDao _snapshotDetailsDao;
|
@Inject
|
||||||
@Inject private VMInstanceDao _vmDao;
|
private SnapshotDataStoreDao _snapshotDataStoreDao;
|
||||||
@Inject private VMTemplateDao _vmTemplateDao;
|
@Inject
|
||||||
@Inject private VolumeDao _volumeDao;
|
private SnapshotDetailsDao _snapshotDetailsDao;
|
||||||
@Inject private VolumeDataFactory _volumeDataFactory;
|
@Inject
|
||||||
@Inject private VolumeDetailsDao volumeDetailsDao;
|
private VMInstanceDao _vmDao;
|
||||||
@Inject private VolumeService _volumeService;
|
@Inject
|
||||||
@Inject private StorageCacheManager cacheMgr;
|
private VMTemplateDao _vmTemplateDao;
|
||||||
@Inject private EndPointSelector selector;
|
@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
|
@Override
|
||||||
public StrategyPriority canHandle(DataObject srcData, DataObject destData) {
|
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 = StorageManager.PRIMARY_STORAGE_DOWNLOAD_WAIT.value();
|
||||||
int primaryStorageDownloadWait = NumbersUtil.parseInt(value, Integer.parseInt(Config.PrimaryStorageDownloadWait.getDefaultValue()));
|
|
||||||
CopyCommand copyCommand = new CopyCommand(snapshotInfo.getTO(), destOnStore.getTO(), primaryStorageDownloadWait,
|
CopyCommand copyCommand = new CopyCommand(snapshotInfo.getTO(), destOnStore.getTO(), primaryStorageDownloadWait,
|
||||||
VirtualMachineManager.ExecuteInSequence.value());
|
VirtualMachineManager.ExecuteInSequence.value());
|
||||||
|
|
||||||
@ -953,7 +968,7 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
|||||||
|
|
||||||
copyCommand.setOptions(srcDetails);
|
copyCommand.setOptions(srcDetails);
|
||||||
|
|
||||||
copyCmdAnswer = (CopyCmdAnswer)_agentMgr.send(hostVO.getId(), copyCommand);
|
copyCmdAnswer = (CopyCmdAnswer)agentManager.send(hostVO.getId(), copyCommand);
|
||||||
|
|
||||||
if (!copyCmdAnswer.getResult()) {
|
if (!copyCmdAnswer.getResult()) {
|
||||||
errMsg = copyCmdAnswer.getDetails();
|
errMsg = copyCmdAnswer.getDetails();
|
||||||
@ -1101,8 +1116,7 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
|||||||
verifyCopyCmdAnswer(copyCmdAnswer, snapshotInfo);
|
verifyCopyCmdAnswer(copyCmdAnswer, snapshotInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
String value = _configDao.getValue(Config.PrimaryStorageDownloadWait.toString());
|
int primaryStorageDownloadWait = StorageManager.PRIMARY_STORAGE_DOWNLOAD_WAIT.value();
|
||||||
int primaryStorageDownloadWait = NumbersUtil.parseInt(value, Integer.parseInt(Config.PrimaryStorageDownloadWait.getDefaultValue()));
|
|
||||||
|
|
||||||
CopyCommand copyCommand = new CopyCommand(snapshotInfo.getTO(), volumeInfo.getTO(), primaryStorageDownloadWait,
|
CopyCommand copyCommand = new CopyCommand(snapshotInfo.getTO(), volumeInfo.getTO(), primaryStorageDownloadWait,
|
||||||
VirtualMachineManager.ExecuteInSequence.value());
|
VirtualMachineManager.ExecuteInSequence.value());
|
||||||
@ -1120,7 +1134,7 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
|||||||
|
|
||||||
copyCommand.setOptions(srcDetails);
|
copyCommand.setOptions(srcDetails);
|
||||||
|
|
||||||
copyCmdAnswer = (CopyCmdAnswer)_agentMgr.send(hostVO.getId(), copyCommand);
|
copyCmdAnswer = (CopyCmdAnswer)agentManager.send(hostVO.getId(), copyCommand);
|
||||||
|
|
||||||
if (!copyCmdAnswer.getResult()) {
|
if (!copyCmdAnswer.getResult()) {
|
||||||
errMsg = copyCmdAnswer.getDetails();
|
errMsg = copyCmdAnswer.getDetails();
|
||||||
@ -1594,8 +1608,7 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private CopyCmdAnswer copyImageToVolume(DataObject srcDataObject, VolumeInfo destVolumeInfo, HostVO hostVO) {
|
private CopyCmdAnswer copyImageToVolume(DataObject srcDataObject, VolumeInfo destVolumeInfo, HostVO hostVO) {
|
||||||
String value = _configDao.getValue(Config.PrimaryStorageDownloadWait.toString());
|
int primaryStorageDownloadWait = StorageManager.PRIMARY_STORAGE_DOWNLOAD_WAIT.value();
|
||||||
int primaryStorageDownloadWait = NumbersUtil.parseInt(value, Integer.parseInt(Config.PrimaryStorageDownloadWait.getDefaultValue()));
|
|
||||||
|
|
||||||
CopyCommand copyCommand = new CopyCommand(srcDataObject.getTO(), destVolumeInfo.getTO(), primaryStorageDownloadWait,
|
CopyCommand copyCommand = new CopyCommand(srcDataObject.getTO(), destVolumeInfo.getTO(), primaryStorageDownloadWait,
|
||||||
VirtualMachineManager.ExecuteInSequence.value());
|
VirtualMachineManager.ExecuteInSequence.value());
|
||||||
@ -1609,7 +1622,7 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
|||||||
|
|
||||||
copyCommand.setOptions2(destDetails);
|
copyCommand.setOptions2(destDetails);
|
||||||
|
|
||||||
copyCmdAnswer = (CopyCmdAnswer)_agentMgr.send(hostVO.getId(), copyCommand);
|
copyCmdAnswer = (CopyCmdAnswer)agentManager.send(hostVO.getId(), copyCommand);
|
||||||
}
|
}
|
||||||
catch (CloudRuntimeException | AgentUnavailableException | OperationTimedoutException ex) {
|
catch (CloudRuntimeException | AgentUnavailableException | OperationTimedoutException ex) {
|
||||||
String msg = "Failed to copy image : ";
|
String msg = "Failed to copy image : ";
|
||||||
@ -1724,6 +1737,8 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
copyTemplateToTargetFilesystemStorageIfNeeded(srcVolumeInfo, sourceStoragePool, destDataStore, destStoragePool, destHost);
|
||||||
|
|
||||||
VolumeVO destVolume = duplicateVolumeOnAnotherStorage(srcVolume, destStoragePool);
|
VolumeVO destVolume = duplicateVolumeOnAnotherStorage(srcVolume, destStoragePool);
|
||||||
VolumeInfo destVolumeInfo = _volumeDataFactory.getVolume(destVolume.getId(), destDataStore);
|
VolumeInfo destVolumeInfo = _volumeDataFactory.getVolume(destVolume.getId(), destDataStore);
|
||||||
|
|
||||||
@ -1763,7 +1778,7 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
|||||||
PrepareForMigrationCommand pfmc = new PrepareForMigrationCommand(vmTO);
|
PrepareForMigrationCommand pfmc = new PrepareForMigrationCommand(vmTO);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Answer pfma = _agentMgr.send(destHost.getId(), pfmc);
|
Answer pfma = agentManager.send(destHost.getId(), pfmc);
|
||||||
|
|
||||||
if (pfma == null || !pfma.getResult()) {
|
if (pfma == null || !pfma.getResult()) {
|
||||||
String details = pfma != null ? pfma.getDetails() : "null answer returned";
|
String details = pfma != null ? pfma.getDetails() : "null answer returned";
|
||||||
@ -1791,7 +1806,7 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
|||||||
|
|
||||||
migrateCommand.setAutoConvergence(kvmAutoConvergence);
|
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();
|
boolean success = migrateAnswer != null && migrateAnswer.getResult();
|
||||||
|
|
||||||
@ -1859,6 +1874,15 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
|||||||
volume.setPath(volume.get_iScsiName());
|
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) {
|
private void handlePostMigration(boolean success, Map<VolumeInfo, VolumeInfo> srcVolumeInfoToDestVolumeInfo, VirtualMachineTO vmTO, Host destHost) {
|
||||||
if (!success) {
|
if (!success) {
|
||||||
try {
|
try {
|
||||||
@ -1866,7 +1890,7 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
|||||||
|
|
||||||
pfmc.setRollback(true);
|
pfmc.setRollback(true);
|
||||||
|
|
||||||
Answer pfma = _agentMgr.send(destHost.getId(), pfmc);
|
Answer pfma = agentManager.send(destHost.getId(), pfmc);
|
||||||
|
|
||||||
if (pfma == null || !pfma.getResult()) {
|
if (pfma == null || !pfma.getResult()) {
|
||||||
String details = pfma != null ? pfma.getDetails() : "null answer returned";
|
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) {
|
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) {
|
if (modifyTargetsAnswer == null) {
|
||||||
throw new CloudRuntimeException("Unable to get an answer to the modify targets command");
|
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);
|
HostVO hostVO = getHost(volumeInfo.getDataCenterId(), HypervisorType.KVM, false);
|
||||||
DataStore srcDataStore = volumeInfo.getDataStore();
|
DataStore srcDataStore = volumeInfo.getDataStore();
|
||||||
|
|
||||||
String value = _configDao.getValue(Config.PrimaryStorageDownloadWait.toString());
|
int primaryStorageDownloadWait = StorageManager.PRIMARY_STORAGE_DOWNLOAD_WAIT.value();
|
||||||
int primaryStorageDownloadWait = NumberUtils.toInt(value, Integer.parseInt(Config.PrimaryStorageDownloadWait.getDefaultValue()));
|
|
||||||
|
|
||||||
CopyCommand copyCommand = new CopyCommand(volumeInfo.getTO(), templateInfo.getTO(), primaryStorageDownloadWait, VirtualMachineManager.ExecuteInSequence.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);
|
copyCommand.setOptions(srcDetails);
|
||||||
|
|
||||||
copyCmdAnswer = (CopyCmdAnswer)_agentMgr.send(hostVO.getId(), copyCommand);
|
copyCmdAnswer = (CopyCmdAnswer)agentManager.send(hostVO.getId(), copyCommand);
|
||||||
|
|
||||||
if (!copyCmdAnswer.getResult()) {
|
if (!copyCmdAnswer.getResult()) {
|
||||||
errMsg = copyCmdAnswer.getDetails();
|
errMsg = copyCmdAnswer.getDetails();
|
||||||
@ -2389,7 +2412,7 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
|||||||
try {
|
try {
|
||||||
_volumeService.grantAccess(dataObj, hostVO, dataStore);
|
_volumeService.grantAccess(dataObj, hostVO, dataStore);
|
||||||
|
|
||||||
answer = (ResignatureAnswer)_agentMgr.send(hostVO.getId(), command);
|
answer = (ResignatureAnswer)agentManager.send(hostVO.getId(), command);
|
||||||
}
|
}
|
||||||
catch (CloudRuntimeException | AgentUnavailableException | OperationTimedoutException ex) {
|
catch (CloudRuntimeException | AgentUnavailableException | OperationTimedoutException ex) {
|
||||||
keepGrantedAccess = false;
|
keepGrantedAccess = false;
|
||||||
@ -2466,7 +2489,7 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
|||||||
|
|
||||||
_volumeService.grantAccess(destVolumeInfo, hostVO, destVolumeInfo.getDataStore());
|
_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 || !migrateVolumeAnswer.getResult()) {
|
||||||
if (migrateVolumeAnswer != null && !StringUtils.isEmpty(migrateVolumeAnswer.getDetails())) {
|
if (migrateVolumeAnswer != null && !StringUtils.isEmpty(migrateVolumeAnswer.getDetails())) {
|
||||||
@ -2534,7 +2557,7 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
|||||||
_volumeService.grantAccess(srcVolumeInfo, hostVO, srcVolumeInfo.getDataStore());
|
_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 || !copyVolumeAnswer.getResult()) {
|
||||||
if (copyVolumeAnswer != null && !StringUtils.isEmpty(copyVolumeAnswer.getDetails())) {
|
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) {
|
private CopyCmdAnswer performCopyOfVdi(VolumeInfo volumeInfo, SnapshotInfo snapshotInfo, HostVO hostVO) {
|
||||||
Snapshot.LocationType locationType = snapshotInfo.getLocationType();
|
Snapshot.LocationType locationType = snapshotInfo.getLocationType();
|
||||||
|
|
||||||
String value = _configDao.getValue(Config.PrimaryStorageDownloadWait.toString());
|
int primaryStorageDownloadWait = StorageManager.PRIMARY_STORAGE_DOWNLOAD_WAIT.value();
|
||||||
int primaryStorageDownloadWait = NumbersUtil.parseInt(value, Integer.parseInt(Config.PrimaryStorageDownloadWait.getDefaultValue()));
|
|
||||||
|
|
||||||
DataObject srcData = snapshotInfo;
|
DataObject srcData = snapshotInfo;
|
||||||
CopyCmdAnswer copyCmdAnswer = null;
|
CopyCmdAnswer copyCmdAnswer = null;
|
||||||
@ -2623,7 +2645,7 @@ public class StorageSystemDataMotionStrategy implements DataMotionStrategy {
|
|||||||
|
|
||||||
copyCommand.setOptions2(destDetails);
|
copyCommand.setOptions2(destDetails);
|
||||||
|
|
||||||
copyCmdAnswer = (CopyCmdAnswer)_agentMgr.send(hostVO.getId(), copyCommand);
|
copyCmdAnswer = (CopyCmdAnswer)agentManager.send(hostVO.getId(), copyCommand);
|
||||||
}
|
}
|
||||||
catch (CloudRuntimeException | AgentUnavailableException | OperationTimedoutException ex) {
|
catch (CloudRuntimeException | AgentUnavailableException | OperationTimedoutException ex) {
|
||||||
String msg = "Failed to perform VDI copy : ";
|
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.StrategyPriority;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory;
|
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.TemplateInfo;
|
||||||
|
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
|
||||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
|
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.PrimaryDataStoreImpl;
|
||||||
|
import org.apache.cloudstack.storage.datastore.db.ImageStoreVO;
|
||||||
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
|
||||||
import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
|
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.apache.cloudstack.storage.volume.VolumeObject;
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.InOrder;
|
||||||
import org.mockito.InjectMocks;
|
import org.mockito.InjectMocks;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.Mockito;
|
import org.mockito.Mockito;
|
||||||
@ -40,37 +48,52 @@ import org.mockito.Spy;
|
|||||||
import org.mockito.runners.MockitoJUnitRunner;
|
import org.mockito.runners.MockitoJUnitRunner;
|
||||||
|
|
||||||
import com.cloud.agent.AgentManager;
|
import com.cloud.agent.AgentManager;
|
||||||
|
import com.cloud.agent.api.Answer;
|
||||||
import com.cloud.agent.api.MigrateCommand;
|
import com.cloud.agent.api.MigrateCommand;
|
||||||
import com.cloud.agent.api.storage.CreateAnswer;
|
import com.cloud.agent.api.storage.CreateAnswer;
|
||||||
import com.cloud.agent.api.storage.CreateCommand;
|
import com.cloud.agent.api.storage.CreateCommand;
|
||||||
import com.cloud.agent.api.to.VirtualMachineTO;
|
import com.cloud.agent.api.to.VirtualMachineTO;
|
||||||
import com.cloud.agent.api.to.VolumeTO;
|
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.host.HostVO;
|
||||||
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
import com.cloud.hypervisor.Hypervisor.HypervisorType;
|
||||||
import com.cloud.storage.DataStoreRole;
|
import com.cloud.storage.DataStoreRole;
|
||||||
import com.cloud.storage.DiskOfferingVO;
|
import com.cloud.storage.DiskOfferingVO;
|
||||||
import com.cloud.storage.Storage;
|
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.Storage.StoragePoolType;
|
||||||
import com.cloud.storage.Volume;
|
import com.cloud.storage.Volume;
|
||||||
import com.cloud.storage.VolumeVO;
|
import com.cloud.storage.VolumeVO;
|
||||||
import com.cloud.storage.dao.DiskOfferingDao;
|
import com.cloud.storage.dao.DiskOfferingDao;
|
||||||
|
import com.cloud.storage.dao.VMTemplatePoolDao;
|
||||||
import com.cloud.utils.exception.CloudRuntimeException;
|
import com.cloud.utils.exception.CloudRuntimeException;
|
||||||
import com.cloud.vm.DiskProfile;
|
import com.cloud.vm.DiskProfile;
|
||||||
|
import com.cloud.vm.VirtualMachineManager;
|
||||||
|
|
||||||
@RunWith(MockitoJUnitRunner.class)
|
@RunWith(MockitoJUnitRunner.class)
|
||||||
public class KvmNonManagedStorageSystemDataMotionTest {
|
public class KvmNonManagedStorageSystemDataMotionTest {
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private PrimaryDataStoreDao primaryDataStoreDao;
|
private PrimaryDataStoreDao primaryDataStoreDao;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private TemplateDataFactory templateDataFactory;
|
private TemplateDataFactory templateDataFactory;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private AgentManager agentManager;
|
private AgentManager agentManager;
|
||||||
|
|
||||||
@Mock
|
@Mock
|
||||||
private DiskOfferingDao diskOfferingDao;
|
private DiskOfferingDao diskOfferingDao;
|
||||||
|
@Mock
|
||||||
|
private VirtualMachineManager virtualMachineManager;
|
||||||
|
@Mock
|
||||||
|
private VMTemplatePoolDao vmTemplatePoolDao;
|
||||||
|
@Mock
|
||||||
|
private DataStoreManagerImpl dataStoreManagerImpl;
|
||||||
|
@Mock
|
||||||
|
private VolumeDataFactory volumeDataFactory;
|
||||||
|
|
||||||
@Spy
|
@Spy
|
||||||
@InjectMocks
|
@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.DataStoreTO;
|
||||||
import com.cloud.agent.api.to.DataTO;
|
import com.cloud.agent.api.to.DataTO;
|
||||||
import com.cloud.agent.api.to.StorageFilerTO;
|
import com.cloud.agent.api.to.StorageFilerTO;
|
||||||
import com.cloud.configuration.Config;
|
|
||||||
import com.cloud.exception.StorageUnavailableException;
|
import com.cloud.exception.StorageUnavailableException;
|
||||||
import com.cloud.host.Host;
|
import com.cloud.host.Host;
|
||||||
import com.cloud.host.dao.HostDao;
|
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.dao.VolumeDao;
|
||||||
import com.cloud.storage.snapshot.SnapshotManager;
|
import com.cloud.storage.snapshot.SnapshotManager;
|
||||||
import com.cloud.template.TemplateManager;
|
import com.cloud.template.TemplateManager;
|
||||||
import com.cloud.utils.NumbersUtil;
|
|
||||||
import com.cloud.vm.dao.VMInstanceDao;
|
import com.cloud.vm.dao.VMInstanceDao;
|
||||||
|
|
||||||
public class CloudStackPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver {
|
public class CloudStackPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver {
|
||||||
@ -256,13 +254,12 @@ public class CloudStackPrimaryDataStoreDriverImpl implements PrimaryDataStoreDri
|
|||||||
callback.complete(result);
|
callback.complete(result);
|
||||||
} else if (srcdata.getType() == DataObjectType.TEMPLATE && destData.getType() == DataObjectType.VOLUME) {
|
} else if (srcdata.getType() == DataObjectType.TEMPLATE && destData.getType() == DataObjectType.VOLUME) {
|
||||||
//For CLVM, we need to pass template on secondary storage to hypervisor
|
//For CLVM, we need to pass template on secondary storage to hypervisor
|
||||||
String value = configDao.getValue(Config.PrimaryStorageDownloadWait.toString());
|
int primaryStorageDownloadWait = StorageManager.PRIMARY_STORAGE_DOWNLOAD_WAIT.value();
|
||||||
int _primaryStorageDownloadWait = NumbersUtil.parseInt(value, Integer.parseInt(Config.PrimaryStorageDownloadWait.getDefaultValue()));
|
|
||||||
StoragePoolVO storagePoolVO = primaryStoreDao.findById(store.getId());
|
StoragePoolVO storagePoolVO = primaryStoreDao.findById(store.getId());
|
||||||
DataStore imageStore = templateManager.getImageStore(storagePoolVO.getDataCenterId(), srcdata.getId());
|
DataStore imageStore = templateManager.getImageStore(storagePoolVO.getDataCenterId(), srcdata.getId());
|
||||||
DataObject srcData = templateDataFactory.getTemplate(srcdata.getId(), imageStore);
|
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);
|
EndPoint ep = epSelector.select(srcData, destData);
|
||||||
Answer answer = null;
|
Answer answer = null;
|
||||||
if (ep == null) {
|
if (ep == null) {
|
||||||
|
|||||||
@ -187,14 +187,6 @@ public enum Config {
|
|||||||
"3600",
|
"3600",
|
||||||
"Timeout (in seconds) to synchronize storage pool operations.",
|
"Timeout (in seconds) to synchronize storage pool operations.",
|
||||||
null),
|
null),
|
||||||
PrimaryStorageDownloadWait(
|
|
||||||
"Storage",
|
|
||||||
TemplateManager.class,
|
|
||||||
Integer.class,
|
|
||||||
"primary.storage.download.wait",
|
|
||||||
"10800",
|
|
||||||
"In second, timeout for download template to primary storage",
|
|
||||||
null),
|
|
||||||
CreateVolumeFromSnapshotWait(
|
CreateVolumeFromSnapshotWait(
|
||||||
"Storage",
|
"Storage",
|
||||||
StorageManager.class,
|
StorageManager.class,
|
||||||
|
|||||||
@ -2489,7 +2489,7 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C
|
|||||||
@Override
|
@Override
|
||||||
public ConfigKey<?>[] getConfigKeys() {
|
public ConfigKey<?>[] getConfigKeys() {
|
||||||
return new ConfigKey<?>[] { StorageCleanupInterval, StorageCleanupDelay, StorageCleanupEnabled, TemplateCleanupEnabled,
|
return new ConfigKey<?>[] { StorageCleanupInterval, StorageCleanupDelay, StorageCleanupEnabled, TemplateCleanupEnabled,
|
||||||
KvmStorageOfflineMigrationWait, KvmStorageOnlineMigrationWait, MaxNumberOfManagedClusteredFileSystems };
|
KvmStorageOfflineMigrationWait, KvmStorageOnlineMigrationWait, MaxNumberOfManagedClusteredFileSystems, PRIMARY_STORAGE_DOWNLOAD_WAIT};
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user