You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ko...@apache.org on 2015/01/16 13:34:35 UTC

git commit: updated refs/heads/volume-upload to 053c160

Repository: cloudstack
Updated Branches:
  refs/heads/volume-upload 1bf405873 -> 053c160b0


volume upload: management server polling and upload status from agent
MS polling logic to query status for templates that are uploaded


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/053c160b
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/053c160b
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/053c160b

Branch: refs/heads/volume-upload
Commit: 053c160b0fb5ba537d56c6d460998c2231904439
Parents: 1bf4058
Author: Koushik Das <ko...@apache.org>
Authored: Fri Jan 16 18:03:36 2015 +0530
Committer: Koushik Das <ko...@apache.org>
Committed: Fri Jan 16 18:03:36 2015 +0530

----------------------------------------------------------------------
 .../cloud/template/VirtualMachineTemplate.java  | 38 +++++++-
 .../src/com/cloud/storage/VMTemplateVO.java     |  3 +
 .../com/cloud/storage/dao/VMTemplateDao.java    |  4 +-
 .../cloud/storage/dao/VMTemplateDaoImpl.java    | 72 +++++++++++++++
 .../datastore/db/TemplateDataStoreDao.java      |  3 +
 .../storage/image/store/TemplateObject.java     | 20 ++++-
 .../storage/image/TemplateEntityImpl.java       | 17 ++++
 .../image/db/TemplateDataStoreDaoImpl.java      | 19 +++-
 .../image/db/VolumeDataStoreDaoImpl.java        |  4 +-
 .../storage/ImageStoreUploadMonitorImpl.java    | 92 ++++++++++++++++++++
 10 files changed, 264 insertions(+), 8 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/053c160b/api/src/com/cloud/template/VirtualMachineTemplate.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/template/VirtualMachineTemplate.java b/api/src/com/cloud/template/VirtualMachineTemplate.java
index 599212b..39229e5 100755
--- a/api/src/com/cloud/template/VirtualMachineTemplate.java
+++ b/api/src/com/cloud/template/VirtualMachineTemplate.java
@@ -26,10 +26,37 @@ import org.apache.cloudstack.api.InternalIdentity;
 import com.cloud.hypervisor.Hypervisor.HypervisorType;
 import com.cloud.storage.Storage.ImageFormat;
 import com.cloud.storage.Storage.TemplateType;
+import com.cloud.utils.fsm.StateMachine2;
+import com.cloud.utils.fsm.StateObject;
 
-public interface VirtualMachineTemplate extends ControlledEntity, Identity, InternalIdentity {
+public interface VirtualMachineTemplate extends ControlledEntity, Identity, InternalIdentity, StateObject<VirtualMachineTemplate.State> {
     enum State {
-        Active, Inactive;
+        Active,
+        Inactive,
+        NotUploaded,
+        UploadInProgress,
+        UploadError,
+        UploadAbandoned;
+
+        public static StateMachine2<State, Event, VirtualMachineTemplate> getStateMachine() {
+            return s_fsm;
+        }
+
+        private final static StateMachine2<State, Event, VirtualMachineTemplate> s_fsm = new StateMachine2<State, Event, VirtualMachineTemplate>();
+        static {
+            s_fsm.addTransition(new StateMachine2.Transition<State, Event>(NotUploaded, Event.OperationTimeout, UploadAbandoned, null));
+            s_fsm.addTransition(new StateMachine2.Transition<State, Event>(NotUploaded, Event.UploadRequested, UploadInProgress, null));
+            s_fsm.addTransition(new StateMachine2.Transition<State, Event>(UploadInProgress, Event.OperationSucceeded, Active, null));
+            s_fsm.addTransition(new StateMachine2.Transition<State, Event>(UploadInProgress, Event.OperationFailed, UploadError, null));
+            s_fsm.addTransition(new StateMachine2.Transition<State, Event>(UploadInProgress, Event.OperationTimeout, UploadError, null));
+        }
+    }
+
+    enum Event {
+        OperationFailed,
+        OperationSucceeded,
+        UploadRequested,
+        OperationTimeout;
     }
 
     public static enum BootloaderType {
@@ -47,6 +74,7 @@ public interface VirtualMachineTemplate extends ControlledEntity, Identity, Inte
         all // all templates (only usable by admins)
     }
 
+    @Override
     State getState();
 
     boolean isFeatured();
@@ -100,4 +128,10 @@ public interface VirtualMachineTemplate extends ControlledEntity, Identity, Inte
     Map getDetails();
 
     boolean isDynamicallyScalable();
+
+    long getUpdatedCount();
+
+    void incrUpdatedCount();
+
+    Date getUpdated();
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/053c160b/engine/schema/src/com/cloud/storage/VMTemplateVO.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/storage/VMTemplateVO.java b/engine/schema/src/com/cloud/storage/VMTemplateVO.java
index d44de22..dd2b35a 100755
--- a/engine/schema/src/com/cloud/storage/VMTemplateVO.java
+++ b/engine/schema/src/com/cloud/storage/VMTemplateVO.java
@@ -582,10 +582,12 @@ public class VMTemplateVO implements VirtualMachineTemplate {
         return size;
     }
 
+    @Override
     public long getUpdatedCount() {
         return updatedCount;
     }
 
+    @Override
     public void incrUpdatedCount() {
         updatedCount++;
     }
@@ -594,6 +596,7 @@ public class VMTemplateVO implements VirtualMachineTemplate {
         updatedCount--;
     }
 
+    @Override
     public Date getUpdated() {
         return updated;
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/053c160b/engine/schema/src/com/cloud/storage/dao/VMTemplateDao.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/storage/dao/VMTemplateDao.java b/engine/schema/src/com/cloud/storage/dao/VMTemplateDao.java
index 2b815d8..a3adffc 100755
--- a/engine/schema/src/com/cloud/storage/dao/VMTemplateDao.java
+++ b/engine/schema/src/com/cloud/storage/dao/VMTemplateDao.java
@@ -21,12 +21,14 @@ import java.util.Map;
 
 import com.cloud.hypervisor.Hypervisor.HypervisorType;
 import com.cloud.storage.VMTemplateVO;
+import com.cloud.template.VirtualMachineTemplate;
 import com.cloud.utils.db.GenericDao;
+import com.cloud.utils.fsm.StateDao;
 
 /*
  * Data Access Object for vm_templates table
  */
-public interface VMTemplateDao extends GenericDao<VMTemplateVO, Long> {
+public interface VMTemplateDao extends GenericDao<VMTemplateVO, Long>, StateDao<VirtualMachineTemplate.State, VirtualMachineTemplate.Event, VirtualMachineTemplate> {
 
     public List<VMTemplateVO> listByPublic();
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/053c160b/engine/schema/src/com/cloud/storage/dao/VMTemplateDaoImpl.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/com/cloud/storage/dao/VMTemplateDaoImpl.java b/engine/schema/src/com/cloud/storage/dao/VMTemplateDaoImpl.java
index 401a4a2..90196a8 100755
--- a/engine/schema/src/com/cloud/storage/dao/VMTemplateDaoImpl.java
+++ b/engine/schema/src/com/cloud/storage/dao/VMTemplateDaoImpl.java
@@ -59,6 +59,7 @@ import com.cloud.utils.db.SearchBuilder;
 import com.cloud.utils.db.SearchCriteria;
 import com.cloud.utils.db.SearchCriteria.Func;
 import com.cloud.utils.db.TransactionLegacy;
+import com.cloud.utils.db.UpdateBuilder;
 import com.cloud.utils.exception.CloudRuntimeException;
 
 @Component
@@ -104,6 +105,7 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
     private SearchBuilder<VMTemplateVO> UserIsoSearch;
     private GenericSearchBuilder<VMTemplateVO, Long> CountTemplatesByAccount;
     // private SearchBuilder<VMTemplateVO> updateStateSearch;
+    private SearchBuilder<VMTemplateVO> AllFieldsSearch;
 
     @Inject
     ResourceTagDao _tagsDao;
@@ -393,6 +395,16 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
         //        updateStateSearch.and("updatedCount", updateStateSearch.entity().getUpdatedCount(), Op.EQ);
         //        updateStateSearch.done();
 
+        AllFieldsSearch = createSearchBuilder();
+        AllFieldsSearch.and("state", AllFieldsSearch.entity().getState(), SearchCriteria.Op.EQ);
+        AllFieldsSearch.and("accountId", AllFieldsSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
+        AllFieldsSearch.and("id", AllFieldsSearch.entity().getId(), SearchCriteria.Op.EQ);
+        AllFieldsSearch.and("destroyed", AllFieldsSearch.entity().getState(), SearchCriteria.Op.EQ);
+        AllFieldsSearch.and("notDestroyed", AllFieldsSearch.entity().getState(), SearchCriteria.Op.NEQ);
+        AllFieldsSearch.and("updatedCount", AllFieldsSearch.entity().getUpdatedCount(), SearchCriteria.Op.EQ);
+        AllFieldsSearch.and("name", AllFieldsSearch.entity().getName(), SearchCriteria.Op.EQ);
+        AllFieldsSearch.done();
+
         return result;
     }
 
@@ -1000,4 +1012,64 @@ public class VMTemplateDaoImpl extends GenericDaoBase<VMTemplateVO, Long> implem
      * return templateZonePairList; }
      */
 
+    @Override
+    public boolean updateState(
+            com.cloud.template.VirtualMachineTemplate.State currentState,
+            com.cloud.template.VirtualMachineTemplate.Event event,
+            com.cloud.template.VirtualMachineTemplate.State nextState,
+            VirtualMachineTemplate vo, Object data) {
+
+        Long oldUpdated = vo.getUpdatedCount();
+        Date oldUpdatedTime = vo.getUpdated();
+
+        SearchCriteria<VMTemplateVO> sc = AllFieldsSearch.create();
+        sc.setParameters("id", vo.getId());
+        sc.setParameters("state", currentState);
+        sc.setParameters("updatedCount", vo.getUpdatedCount());
+
+        vo.incrUpdatedCount();
+
+        UpdateBuilder builder = getUpdateBuilder(vo);
+        builder.set(vo, "state", nextState);
+        builder.set(vo, "updated", new Date());
+
+        int rows = update((VMTemplateVO)vo, sc);
+        if (rows == 0 && s_logger.isDebugEnabled()) {
+            VMTemplateVO dbTemplate = findByIdIncludingRemoved(vo.getId());
+            if (dbTemplate != null) {
+                StringBuilder str = new StringBuilder("Unable to update ").append(vo.toString());
+                str.append(": DB Data={id=")
+                    .append(dbTemplate.getId())
+                    .append("; state=")
+                    .append(dbTemplate.getState())
+                    .append("; updatecount=")
+                    .append(dbTemplate.getUpdatedCount())
+                    .append(";updatedTime=")
+                    .append(dbTemplate.getUpdated());
+                str.append(": New Data={id=")
+                    .append(vo.getId())
+                    .append("; state=")
+                    .append(nextState)
+                    .append("; event=")
+                    .append(event)
+                    .append("; updatecount=")
+                    .append(vo.getUpdatedCount())
+                    .append("; updatedTime=")
+                    .append(vo.getUpdated());
+                str.append(": stale Data={id=")
+                    .append(vo.getId())
+                    .append("; state=")
+                    .append(currentState)
+                    .append("; event=")
+                    .append(event)
+                    .append("; updatecount=")
+                    .append(oldUpdated)
+                    .append("; updatedTime=")
+                    .append(oldUpdatedTime);
+            } else {
+                s_logger.debug("Unable to update template: id=" + vo.getId() + ", as no such template exists in the database anymore");
+            }
+        }
+        return rows > 0;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/053c160b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreDao.java
----------------------------------------------------------------------
diff --git a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreDao.java b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreDao.java
index 9f8bccd..4da779c 100644
--- a/engine/schema/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreDao.java
+++ b/engine/schema/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreDao.java
@@ -25,6 +25,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreState
 import com.cloud.storage.DataStoreRole;
 import com.cloud.storage.VMTemplateStorageResourceAssoc;
 import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
+import com.cloud.template.VirtualMachineTemplate;
 import com.cloud.utils.db.GenericDao;
 import com.cloud.utils.fsm.StateDao;
 
@@ -80,4 +81,6 @@ public interface TemplateDataStoreDao extends GenericDao<TemplateDataStoreVO, Lo
     void removeByTemplateStore(long templateId, long imageStoreId);
 
     void expireDnldUrlsForZone(Long dcId);
+
+    List<TemplateDataStoreVO> listByTemplateState(VirtualMachineTemplate.State... states);
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/053c160b/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java
----------------------------------------------------------------------
diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java
index e4b04de..197caa7 100644
--- a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java
+++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java
@@ -28,7 +28,6 @@ import org.apache.log4j.Logger;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
 import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
-import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
 import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStore;
 import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
 import org.apache.cloudstack.storage.command.CopyCmdAnswer;
@@ -166,7 +165,7 @@ public class TemplateObject implements TemplateInfo {
     }
 
     @Override
-    public void processEvent(Event event) {
+    public void processEvent(org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event event) {
         try {
             objectInStoreMgr.update(this, event);
         } catch (NoTransitionException e) {
@@ -459,4 +458,21 @@ public class TemplateObject implements TemplateInfo {
     public Class<?> getEntityType() {
         return VirtualMachineTemplate.class;
     }
+
+    @Override
+    public long getUpdatedCount() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public void incrUpdatedCount() {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public Date getUpdated() {
+        // TODO Auto-generated method stub
+        return null;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/053c160b/engine/storage/src/org/apache/cloudstack/storage/image/TemplateEntityImpl.java
----------------------------------------------------------------------
diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/TemplateEntityImpl.java b/engine/storage/src/org/apache/cloudstack/storage/image/TemplateEntityImpl.java
index c1aa8c2..db752fe 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/image/TemplateEntityImpl.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/image/TemplateEntityImpl.java
@@ -290,4 +290,21 @@ public class TemplateEntityImpl implements TemplateEntity {
     public Class<?> getEntityType() {
         return VirtualMachineTemplate.class;
     }
+
+    @Override
+    public long getUpdatedCount() {
+        // TODO Auto-generated method stub
+        return 0;
+    }
+
+    @Override
+    public void incrUpdatedCount() {
+        // TODO Auto-generated method stub
+    }
+
+    @Override
+    public Date getUpdated() {
+        // TODO Auto-generated method stub
+        return null;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/053c160b/engine/storage/src/org/apache/cloudstack/storage/image/db/TemplateDataStoreDaoImpl.java
----------------------------------------------------------------------
diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/db/TemplateDataStoreDaoImpl.java b/engine/storage/src/org/apache/cloudstack/storage/image/db/TemplateDataStoreDaoImpl.java
index dad0b6d..1c3f485 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/image/db/TemplateDataStoreDaoImpl.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/image/db/TemplateDataStoreDaoImpl.java
@@ -28,7 +28,6 @@ import javax.naming.ConfigurationException;
 
 import org.apache.log4j.Logger;
 import org.springframework.stereotype.Component;
-
 import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
@@ -45,7 +44,9 @@ import com.cloud.storage.Storage.TemplateType;
 import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
 import com.cloud.storage.VMTemplateVO;
 import com.cloud.storage.dao.VMTemplateDao;
+import com.cloud.template.VirtualMachineTemplate;
 import com.cloud.utils.db.GenericDaoBase;
+import com.cloud.utils.db.JoinBuilder.JoinType;
 import com.cloud.utils.db.SearchBuilder;
 import com.cloud.utils.db.SearchCriteria;
 import com.cloud.utils.db.SearchCriteria.Op;
@@ -65,6 +66,8 @@ public class TemplateDataStoreDaoImpl extends GenericDaoBase<TemplateDataStoreVO
     private SearchBuilder<TemplateDataStoreVO> storeTemplateStateSearch;
     private SearchBuilder<TemplateDataStoreVO> storeTemplateDownloadStatusSearch;
     private SearchBuilder<TemplateDataStoreVO> downloadTemplateSearch;
+    private SearchBuilder<TemplateDataStoreVO> uploadTemplateStateSearch;
+    private SearchBuilder<VMTemplateVO> templateOnlySearch;
     private static final String EXPIRE_DOWNLOAD_URLS_FOR_ZONE = "update template_store_ref set download_url_created=? where store_id in (select id from image_store where data_center_id=?)";
 
     @Inject
@@ -139,6 +142,13 @@ public class TemplateDataStoreDaoImpl extends GenericDaoBase<TemplateDataStoreVO
         downloadTemplateSearch.and("destroyed", downloadTemplateSearch.entity().getDestroyed(), SearchCriteria.Op.EQ);
         downloadTemplateSearch.done();
 
+        templateOnlySearch = _tmpltDao.createSearchBuilder();
+        templateOnlySearch.and("states", templateOnlySearch.entity().getState(), SearchCriteria.Op.IN);
+        uploadTemplateStateSearch = createSearchBuilder();
+        uploadTemplateStateSearch.join("templateOnlySearch", templateOnlySearch, templateOnlySearch.entity().getId(), uploadTemplateStateSearch.entity().getTemplateId(), JoinType.LEFT);
+        uploadTemplateStateSearch.and("destroyed", uploadTemplateStateSearch.entity().getDestroyed(), SearchCriteria.Op.EQ);
+        uploadTemplateStateSearch.done();
+
         return true;
     }
 
@@ -531,4 +541,11 @@ public class TemplateDataStoreDaoImpl extends GenericDaoBase<TemplateDataStoreVO
 
     }
 
+    @Override
+    public List<TemplateDataStoreVO> listByTemplateState(VirtualMachineTemplate.State... states) {
+        SearchCriteria<TemplateDataStoreVO> sc = uploadTemplateStateSearch.create();
+        sc.setJoinParameters("templateOnlySearch", "states", (Object[])states);
+        sc.setParameters("destroyed", false);
+        return listIncludingRemovedBy(sc);
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/053c160b/engine/storage/src/org/apache/cloudstack/storage/image/db/VolumeDataStoreDaoImpl.java
----------------------------------------------------------------------
diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/db/VolumeDataStoreDaoImpl.java b/engine/storage/src/org/apache/cloudstack/storage/image/db/VolumeDataStoreDaoImpl.java
index 117e622..f3163ee 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/image/db/VolumeDataStoreDaoImpl.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/image/db/VolumeDataStoreDaoImpl.java
@@ -110,7 +110,7 @@ public class VolumeDataStoreDaoImpl extends GenericDaoBase<VolumeDataStoreVO, Lo
         uploadVolumeSearch.done();
 
         volumeOnlySearch = volumeDao.createSearchBuilder();
-        volumeOnlySearch.and("state", volumeOnlySearch.entity().getState(), Op.IN);
+        volumeOnlySearch.and("states", volumeOnlySearch.entity().getState(), Op.IN);
         uploadVolumeStateSearch = createSearchBuilder();
         uploadVolumeStateSearch.join("volumeOnlySearch", volumeOnlySearch, volumeOnlySearch.entity().getId(), uploadVolumeStateSearch.entity().getVolumeId(), JoinType.LEFT);
         uploadVolumeStateSearch.and("destroyed", uploadVolumeStateSearch.entity().getDestroyed(), SearchCriteria.Op.EQ);
@@ -322,7 +322,7 @@ public class VolumeDataStoreDaoImpl extends GenericDaoBase<VolumeDataStoreVO, Lo
     @Override
     public List<VolumeDataStoreVO> listByVolumeState(Volume.State... states) {
         SearchCriteria<VolumeDataStoreVO> sc = uploadVolumeStateSearch.create();
-        sc.setJoinParameters("volumeOnlySearch", "state", (Object[])states);
+        sc.setJoinParameters("volumeOnlySearch", "states", (Object[])states);
         sc.setParameters("destroyed", false);
         return listIncludingRemovedBy(sc);
     }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/053c160b/server/src/com/cloud/storage/ImageStoreUploadMonitorImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/storage/ImageStoreUploadMonitorImpl.java b/server/src/com/cloud/storage/ImageStoreUploadMonitorImpl.java
index 6defb89..63642f0 100755
--- a/server/src/com/cloud/storage/ImageStoreUploadMonitorImpl.java
+++ b/server/src/com/cloud/storage/ImageStoreUploadMonitorImpl.java
@@ -38,6 +38,8 @@ import org.apache.cloudstack.managed.context.ManagedContextRunnable;
 import org.apache.cloudstack.storage.command.UploadStatusAnswer;
 import org.apache.cloudstack.storage.command.UploadStatusCommand;
 import org.apache.cloudstack.storage.command.UploadStatusCommand.EntityType;
+import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
+import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO;
 import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreDao;
 import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreVO;
 import org.apache.cloudstack.utils.identity.ManagementServerNode;
@@ -53,7 +55,9 @@ import com.cloud.host.Host;
 import com.cloud.host.Status;
 import com.cloud.host.dao.HostDao;
 import com.cloud.storage.Volume.Event;
+import com.cloud.storage.dao.VMTemplateDao;
 import com.cloud.storage.dao.VolumeDao;
+import com.cloud.template.VirtualMachineTemplate;
 import com.cloud.utils.component.ManagerBase;
 import com.cloud.utils.concurrency.NamedThreadFactory;
 import com.cloud.utils.db.Transaction;
@@ -76,6 +80,10 @@ public class ImageStoreUploadMonitorImpl extends ManagerBase implements ImageSto
     @Inject
     private VolumeDataStoreDao _volumeDataStoreDao;
     @Inject
+    private VMTemplateDao _templateDao;
+    @Inject
+    private TemplateDataStoreDao _templateDataStoreDao;
+    @Inject
     private HostDao _hostDao;
     @Inject
     private EndPointSelector _epSelector;
@@ -189,6 +197,32 @@ public class ImageStoreUploadMonitorImpl extends ManagerBase implements ImageSto
                     handleVolumeStatusResponse((UploadStatusAnswer)answer, volume, volumeDataStore);
                 }
             }
+
+            // Handle for template upload as well
+            List<TemplateDataStoreVO> templateDataStores = _templateDataStoreDao.listByTemplateState(VirtualMachineTemplate.State.NotUploaded, VirtualMachineTemplate.State.UploadInProgress);
+            for (TemplateDataStoreVO templateDataStore : templateDataStores) {
+                DataStore dataStore = storeMgr.getDataStore(templateDataStore.getDataStoreId(), DataStoreRole.Image);
+                EndPoint ep = _epSelector.select(dataStore, templateDataStore.getExtractUrl());
+                if (ep == null) {
+                    s_logger.warn("There is no secondary storage VM for image store " + dataStore.getName());
+                    continue;
+                }
+                VMTemplateVO template = _templateDao.findById(templateDataStore.getTemplateId());
+                if (template == null) {
+                    s_logger.warn("Template with id " + templateDataStore.getTemplateId() + " not found");
+                    continue;
+                }
+                Host host = _hostDao.findById(ep.getId());
+                if (host != null && host.getManagementServerId() != null && _nodeId == host.getManagementServerId().longValue()) {
+                    UploadStatusCommand cmd = new UploadStatusCommand(template.getId(), EntityType.Template);
+                    Answer answer = ep.sendMessage(cmd);
+                    if (answer == null || !(answer instanceof UploadStatusAnswer)) {
+                        s_logger.warn("No or invalid answer corresponding to UploadStatusCommand for template " + templateDataStore.getTemplateId());
+                        continue;
+                    }
+                    handleTemplateStatusResponse((UploadStatusAnswer)answer, template, templateDataStore);
+                }
+            }
         }
 
         private void handleVolumeStatusResponse(final UploadStatusAnswer answer, final VolumeVO volume, final VolumeDataStoreVO volumeDataStore) {
@@ -248,6 +282,64 @@ public class ImageStoreUploadMonitorImpl extends ManagerBase implements ImageSto
                 }
             });
         }
+
+        private void handleTemplateStatusResponse(final UploadStatusAnswer answer, final VMTemplateVO template, final TemplateDataStoreVO templateDataStore) {
+            final StateMachine2<VirtualMachineTemplate.State, VirtualMachineTemplate.Event, VirtualMachineTemplate> stateMachine = VirtualMachineTemplate.State.getStateMachine();
+            Transaction.execute(new TransactionCallbackNoReturn() {
+                @Override
+                public void doInTransactionWithoutResult(TransactionStatus status) {
+                    VMTemplateVO tmpTemplate = _templateDao.findById(template.getId());
+                    TemplateDataStoreVO tmpTemplateDataStore = _templateDataStoreDao.findById(templateDataStore.getId());
+                    try {
+                        switch (answer.getStatus()) {
+                        case COMPLETED:
+                            tmpTemplateDataStore.setDownloadState(VMTemplateStorageResourceAssoc.Status.UPLOADED);
+                            stateMachine.transitTo(tmpTemplate, VirtualMachineTemplate.Event.OperationSucceeded, null, _templateDao);
+                            if (s_logger.isDebugEnabled()) {
+                                s_logger.debug("Template " + tmpTemplate.getUuid() + " uploaded successfully");
+                            }
+                            break;
+                        case IN_PROGRESS:
+                            if (tmpTemplate.getState() == VirtualMachineTemplate.State.NotUploaded) {
+                                tmpTemplateDataStore.setDownloadState(VMTemplateStorageResourceAssoc.Status.UPLOAD_IN_PROGRESS);
+                                stateMachine.transitTo(tmpTemplate, VirtualMachineTemplate.Event.UploadRequested, null, _templateDao);
+                            } else if (tmpTemplate.getState() == VirtualMachineTemplate.State.UploadInProgress) { // check for timeout
+                                if (System.currentTimeMillis() - tmpTemplateDataStore.getCreated().getTime() > _uploadOperationTimeout) {
+                                    tmpTemplateDataStore.setDownloadState(VMTemplateStorageResourceAssoc.Status.UPLOAD_ERROR);
+                                    stateMachine.transitTo(tmpTemplate, VirtualMachineTemplate.Event.OperationFailed, null, _templateDao);
+                                    if (s_logger.isDebugEnabled()) {
+                                        s_logger.debug("Template " + tmpTemplate.getUuid() + " failed to upload due to operation timed out");
+                                    }
+                                }
+                            }
+                            break;
+                        case ERROR:
+                            tmpTemplateDataStore.setDownloadState(VMTemplateStorageResourceAssoc.Status.UPLOAD_ERROR);
+                            stateMachine.transitTo(tmpTemplate, VirtualMachineTemplate.Event.OperationFailed, null, _templateDao);
+                            if (s_logger.isDebugEnabled()) {
+                                s_logger.debug("Template " + tmpTemplate.getUuid() + " failed to upload. Error details: " + answer.getDetails());
+                            }
+                            break;
+                        case UNKNOWN:
+                            if (tmpTemplate.getState() == VirtualMachineTemplate.State.NotUploaded) { // check for timeout
+                                if (System.currentTimeMillis() - tmpTemplateDataStore.getCreated().getTime() > _uploadOperationTimeout) {
+                                    tmpTemplateDataStore.setDownloadState(VMTemplateStorageResourceAssoc.Status.ABANDONED);
+                                    stateMachine.transitTo(tmpTemplate, VirtualMachineTemplate.Event.OperationTimeout, null, _templateDao);
+                                    if (s_logger.isDebugEnabled()) {
+                                        s_logger.debug("Template " + tmpTemplate.getUuid() + " failed to upload due to operation timed out");
+                                    }
+                                }
+                            }
+                            break;
+                        }
+                        _templateDataStoreDao.update(tmpTemplateDataStore.getId(), tmpTemplateDataStore);
+                    } catch (NoTransitionException e) {
+                        s_logger.error("Unexpected error " + e.getMessage());
+                    }
+                }
+            });
+        }
+
     }
 
     @Override