This is an automated email from the ASF dual-hosted git repository.

gabriel pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cloudstack.git


The following commit(s) were added to refs/heads/master by this push:
     new 7c5eca9  Copy template to target KVM host if needed when migrating 
local <> local storage (#3154)
7c5eca9 is described below

commit 7c5eca94810c88a7e4a0849be1b1c23bf603e61b
Author: Gabriel Beims Bräscher <gabrasc...@gmail.com>
AuthorDate: Tue Feb 5 00:18:29 2019 -0200

    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
---
 .../java/com/cloud/storage/StorageManager.java     |   3 +
 .../storage/motion/AncientDataMotionStrategy.java  |   7 +-
 .../KvmNonManagedStorageDataMotionStrategy.java    |  97 ++++++++++++-
 .../motion/StorageSystemDataMotionStrategy.java    | 104 ++++++++------
 .../KvmNonManagedStorageSystemDataMotionTest.java  | 150 ++++++++++++++++++++-
 .../CloudStackPrimaryDataStoreDriverImpl.java      |   7 +-
 .../main/java/com/cloud/configuration/Config.java  |   8 --
 .../java/com/cloud/storage/StorageManagerImpl.java |   2 +-
 8 files changed, 316 insertions(+), 62 deletions(-)

diff --git 
a/engine/components-api/src/main/java/com/cloud/storage/StorageManager.java 
b/engine/components-api/src/main/java/com/cloud/storage/StorageManager.java
index c9c24d8..fd98101 100644
--- a/engine/components-api/src/main/java/com/cloud/storage/StorageManager.java
+++ b/engine/components-api/src/main/java/com/cloud/storage/StorageManager.java
@@ -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
diff --git 
a/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
 
b/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
index 9471fad..7b52645 100644
--- 
a/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
+++ 
b/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
@@ -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?";
diff --git 
a/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/KvmNonManagedStorageDataMotionStrategy.java
 
b/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/KvmNonManagedStorageDataMotionStrategy.java
index bb75a66..2cf236d 100644
--- 
a/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/KvmNonManagedStorageDataMotionStrategy.java
+++ 
b/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/KvmNonManagedStorageDataMotionStrategy.java
@@ -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);
+        }
+    }
 }
diff --git 
a/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategy.java
 
b/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategy.java
index adeb0d1..6bcaebe 100644
--- 
a/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategy.java
+++ 
b/engine/storage/datamotion/src/main/java/org/apache/cloudstack/storage/motion/StorageSystemDataMotionStrategy.java
@@ -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 : ";
diff --git 
a/engine/storage/datamotion/src/test/java/org/apache/cloudstack/storage/motion/KvmNonManagedStorageSystemDataMotionTest.java
 
b/engine/storage/datamotion/src/test/java/org/apache/cloudstack/storage/motion/KvmNonManagedStorageSystemDataMotionTest.java
index b344f83..c0d8ad3 100644
--- 
a/engine/storage/datamotion/src/test/java/org/apache/cloudstack/storage/motion/KvmNonManagedStorageSystemDataMotionTest.java
+++ 
b/engine/storage/datamotion/src/test/java/org/apache/cloudstack/storage/motion/KvmNonManagedStorageSystemDataMotionTest.java
@@ -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));
+    }
 }
diff --git 
a/plugins/storage/volume/default/src/main/java/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java
 
b/plugins/storage/volume/default/src/main/java/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java
index 96a03b7..4153ba1 100644
--- 
a/plugins/storage/volume/default/src/main/java/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java
+++ 
b/plugins/storage/volume/default/src/main/java/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java
@@ -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) {
diff --git a/server/src/main/java/com/cloud/configuration/Config.java 
b/server/src/main/java/com/cloud/configuration/Config.java
index eda34e5..d365ef0 100644
--- a/server/src/main/java/com/cloud/configuration/Config.java
+++ b/server/src/main/java/com/cloud/configuration/Config.java
@@ -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,
diff --git a/server/src/main/java/com/cloud/storage/StorageManagerImpl.java 
b/server/src/main/java/com/cloud/storage/StorageManagerImpl.java
index a299540..40ecb84 100644
--- a/server/src/main/java/com/cloud/storage/StorageManagerImpl.java
+++ b/server/src/main/java/com/cloud/storage/StorageManagerImpl.java
@@ -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

Reply via email to