You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ah...@apache.org on 2013/06/25 01:52:12 UTC

[36/50] [abbrv] merge is complete

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/7b7db056/server/src/com/cloud/template/TemplateManagerImpl.java
----------------------------------------------------------------------
diff --cc server/src/com/cloud/template/TemplateManagerImpl.java
index 3317fa1,273614c..2528b54
--- a/server/src/com/cloud/template/TemplateManagerImpl.java
+++ b/server/src/com/cloud/template/TemplateManagerImpl.java
@@@ -16,13 -16,12 +16,8 @@@
  // under the License.
  package com.cloud.template;
  
--import java.net.Inet6Address;
--import java.net.InetAddress;
--import java.net.URI;
  import java.net.URISyntaxException;
--import java.net.UnknownHostException;
  import java.util.ArrayList;
- import java.util.Collections;
  import java.util.Date;
  import java.util.List;
  import java.util.Map;
@@@ -31,15 -29,13 +25,17 @@@ import java.util.UUID
  import java.util.concurrent.ExecutionException;
  import java.util.concurrent.ExecutorService;
  import java.util.concurrent.Executors;
- import java.util.concurrent.ScheduledExecutorService;
- import java.util.concurrent.TimeUnit;
 +
  import javax.ejb.Local;
  import javax.inject.Inject;
  import javax.naming.ConfigurationException;
  
++import org.apache.log4j.Logger;
++import org.springframework.stereotype.Component;
++
  import org.apache.cloudstack.acl.SecurityChecker.AccessType;
  import org.apache.cloudstack.api.BaseListTemplateOrIsoPermissionsCmd;
+ import org.apache.cloudstack.api.BaseUpdateTemplateOrIsoCmd;
  import org.apache.cloudstack.api.BaseUpdateTemplateOrIsoPermissionsCmd;
  import org.apache.cloudstack.api.command.user.iso.DeleteIsoCmd;
  import org.apache.cloudstack.api.command.user.iso.ExtractIsoCmd;
@@@ -52,40 -49,53 +49,47 @@@ import org.apache.cloudstack.api.comman
  import org.apache.cloudstack.api.command.user.template.ExtractTemplateCmd;
  import org.apache.cloudstack.api.command.user.template.ListTemplatePermissionsCmd;
  import org.apache.cloudstack.api.command.user.template.RegisterTemplateCmd;
+ import org.apache.cloudstack.api.command.user.template.UpdateTemplateCmd;
  import org.apache.cloudstack.api.command.user.template.UpdateTemplatePermissionsCmd;
 +import org.apache.cloudstack.context.CallContext;
- import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult;
  import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
  import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager;
- import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreRole;
- import org.apache.cloudstack.engine.subsystem.api.storage.ImageDataFactory;
- import org.apache.cloudstack.engine.subsystem.api.storage.ImageService;
+ import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
+ import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
+ import org.apache.cloudstack.engine.subsystem.api.storage.Scope;
 -import org.apache.cloudstack.engine.subsystem.api.storage.StorageCacheManager;
 -import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory;
 -import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService;
  import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory;
  import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
++import org.apache.cloudstack.engine.subsystem.api.storage.StorageCacheManager;
++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.TemplateService;
+ import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService.TemplateApiResult;
  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.ZoneScope;
  import org.apache.cloudstack.framework.async.AsyncCallFuture;
 +import org.apache.cloudstack.framework.jobs.AsyncJobManager;
- import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO;
+ import org.apache.cloudstack.storage.command.AttachCommand;
+ import org.apache.cloudstack.storage.command.CommandResult;
 -import org.apache.cloudstack.storage.command.CopyCommand;
+ import org.apache.cloudstack.storage.command.DettachCommand;
+ import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
  import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
  import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
- import org.apache.log4j.Logger;
- import org.springframework.stereotype.Component;
+ import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
+ import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreVO;
+ import org.apache.cloudstack.storage.image.datastore.ImageStoreEntity;
 -import org.apache.log4j.Logger;
 -import org.springframework.stereotype.Component;
  
 -import com.amazonaws.services.s3.model.CannedAccessControlList;
  import com.cloud.agent.AgentManager;
  import com.cloud.agent.api.Answer;
- import com.cloud.agent.api.AttachIsoCommand;
+ import com.cloud.agent.api.Command;
  import com.cloud.agent.api.ComputeChecksumCommand;
- import com.cloud.agent.api.DownloadTemplateFromSwiftToSecondaryStorageCommand;
- import com.cloud.agent.api.UploadTemplateToSwiftFromSecondaryStorageCommand;
 -
  import com.cloud.agent.api.storage.DestroyCommand;
- import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
- import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
- import com.cloud.agent.api.to.SwiftTO;
- 
+ import com.cloud.agent.api.to.DataTO;
+ import com.cloud.agent.api.to.DiskTO;
+ import com.cloud.agent.api.to.NfsTO;
 -import com.cloud.agent.api.to.S3TO;
  import com.cloud.api.ApiDBUtils;
+ import com.cloud.api.query.dao.UserVmJoinDao;
+ import com.cloud.api.query.vo.UserVmJoinVO;
 -import com.cloud.async.AsyncJobManager;
 -import com.cloud.async.AsyncJobVO;
  import com.cloud.configuration.Config;
  import com.cloud.configuration.Resource.ResourceType;
  import com.cloud.configuration.dao.ConfigurationDao;
@@@ -104,7 -114,7 +108,6 @@@ import com.cloud.exception.InvalidParam
  import com.cloud.exception.PermissionDeniedException;
  import com.cloud.exception.ResourceAllocationException;
  import com.cloud.exception.StorageUnavailableException;
- import com.cloud.host.Host;
 -import com.cloud.exception.UnsupportedServiceException;
  import com.cloud.host.HostVO;
  import com.cloud.host.dao.HostDao;
  import com.cloud.hypervisor.Hypervisor;
@@@ -112,34 -122,34 +115,29 @@@ import com.cloud.hypervisor.Hypervisor.
  import com.cloud.hypervisor.HypervisorGuruManager;
  import com.cloud.projects.Project;
  import com.cloud.projects.ProjectManager;
--
  import com.cloud.resource.ResourceManager;
  import com.cloud.server.ConfigurationServer;
++import com.cloud.storage.DataStoreRole;
  import com.cloud.storage.GuestOSVO;
  import com.cloud.storage.LaunchPermissionVO;
++import com.cloud.storage.ScopeType;
  import com.cloud.storage.Snapshot;
  import com.cloud.storage.SnapshotVO;
  import com.cloud.storage.Storage;
--
  import com.cloud.storage.Storage.ImageFormat;
  import com.cloud.storage.Storage.TemplateType;
 -import com.cloud.storage.DataStoreRole;
 -import com.cloud.storage.ScopeType;
  import com.cloud.storage.StorageManager;
  import com.cloud.storage.StoragePool;
  import com.cloud.storage.StoragePoolHostVO;
  import com.cloud.storage.StoragePoolStatus;
  import com.cloud.storage.TemplateProfile;
  import com.cloud.storage.Upload;
--import com.cloud.storage.Upload.Type;
- 
- import com.cloud.storage.UploadVO;
 -import com.cloud.storage.VMTemplateZoneVO;
 -
 -import com.cloud.storage.UploadVO;
  import com.cloud.storage.VMTemplateHostVO;
  import com.cloud.storage.VMTemplateStoragePoolVO;
  import com.cloud.storage.VMTemplateStorageResourceAssoc;
  import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
- import com.cloud.storage.VMTemplateSwiftVO;
  import com.cloud.storage.VMTemplateVO;
 +import com.cloud.storage.VMTemplateZoneVO;
  import com.cloud.storage.Volume;
  import com.cloud.storage.VolumeManager;
  import com.cloud.storage.VolumeVO;
@@@ -157,12 -166,10 +154,9 @@@ import com.cloud.storage.dao.VMTemplate
  import com.cloud.storage.dao.VMTemplateZoneDao;
  import com.cloud.storage.dao.VolumeDao;
  import com.cloud.storage.download.DownloadMonitor;
- import com.cloud.storage.s3.S3Manager;
  import com.cloud.storage.secondary.SecondaryStorageVmManager;
- import com.cloud.storage.swift.SwiftManager;
  import com.cloud.storage.upload.UploadMonitor;
  import com.cloud.template.TemplateAdapter.TemplateAdapterType;
--
  import com.cloud.user.Account;
  import com.cloud.user.AccountManager;
  import com.cloud.user.AccountService;
@@@ -173,12 -181,14 +167,14 @@@ import com.cloud.user.dao.AccountDao
  import com.cloud.user.dao.UserAccountDao;
  import com.cloud.user.dao.UserDao;
  import com.cloud.uservm.UserVm;
+ import com.cloud.utils.EnumUtils;
  import com.cloud.utils.NumbersUtil;
  import com.cloud.utils.Pair;
  import com.cloud.utils.component.AdapterBase;
  import com.cloud.utils.component.ManagerBase;
  import com.cloud.utils.concurrency.NamedThreadFactory;
--import com.cloud.utils.db.*;
++import com.cloud.utils.db.DB;
++import com.cloud.utils.db.Transaction;
  import com.cloud.utils.exception.CloudRuntimeException;
  import com.cloud.vm.UserVmManager;
  import com.cloud.vm.UserVmVO;
@@@ -230,105 -258,121 +244,121 @@@ public class TemplateManagerImpl extend
      @Inject
      protected GuestOSDao _guestOSDao;
      long _routerTemplateId = -1;
-     @Inject StorageManager _storageMgr;
-     @Inject AsyncJobManager _asyncMgr;
-     @Inject UserVmManager _vmMgr;
-     @Inject UsageEventDao _usageEventDao;
-     @Inject HypervisorGuruManager _hvGuruMgr;
-     @Inject AccountService _accountService;
-     @Inject ResourceLimitService _resourceLimitMgr;
-     @Inject SecondaryStorageVmManager _ssvmMgr;
-     @Inject LaunchPermissionDao _launchPermissionDao;
-     @Inject ProjectManager _projectMgr;
      @Inject
-     VolumeDataFactory volFactory;
+     StorageManager _storageMgr;
+     @Inject
+     AsyncJobManager _asyncMgr;
+     @Inject
+     UserVmManager _vmMgr;
      @Inject
-     ImageDataFactory tmplFactory;
+     UsageEventDao _usageEventDao;
      @Inject
-     SnapshotDataFactory snapshotFactory;
+     HypervisorGuruManager _hvGuruMgr;
      @Inject
-     ImageService imageSvr;
+     AccountService _accountService;
      @Inject
-     DataStoreManager dataStoreMgr;
+     ResourceLimitService _resourceLimitMgr;
+     @Inject
+     SecondaryStorageVmManager _ssvmMgr;
+     @Inject
+     LaunchPermissionDao _launchPermissionDao;
+     @Inject
+     ProjectManager _projectMgr;
+     @Inject
+     VolumeDataFactory _volFactory;
+     @Inject
+     TemplateDataFactory _tmplFactory;
+     @Inject
+     SnapshotDataFactory _snapshotFactory;
+     @Inject
+     TemplateService _tmpltSvr;
+     @Inject
+     DataStoreManager _dataStoreMgr;
      @Inject
      protected ResourceManager _resourceMgr;
-     @Inject VolumeManager volumeMgr;
-     @Inject VMTemplateHostDao templateHostDao;
      @Inject
-     ConfigurationServer _configServer;
+     VolumeManager _volumeMgr;
+     @Inject
+     ImageStoreDao _imageStoreDao;
+     @Inject
+     EndPointSelector _epSelector;
+     @Inject
+     UserVmJoinDao _userVmJoinDao;
  
+     @Inject
+     ConfigurationServer _configServer;
 -
 +    
      int _primaryStorageDownloadWait;
-     protected SearchBuilder<VMTemplateHostVO> HostTemplateStatesSearch;
-     
      int _storagePoolMaxWaitSeconds = 3600;
      boolean _disableExtraction = false;
      ExecutorService _preloadExecutor;
  
      @Inject
      protected List<TemplateAdapter> _adapters;
 -
 +    
+     @Inject
+     StorageCacheManager cacheMgr;
+     @Inject
+     EndPointSelector selector;
+ 
      private TemplateAdapter getAdapter(HypervisorType type) {
 -        TemplateAdapter adapter = null;
 -        if (type == HypervisorType.BareMetal) {
 -            adapter = AdapterBase.getAdapterByName(_adapters, TemplateAdapterType.BareMetal.getName());
 -        } else {
 -            // see HypervisorTemplateAdapter
 -            adapter = AdapterBase.getAdapterByName(_adapters, TemplateAdapterType.Hypervisor.getName());
 -        }
 -
 -        if (adapter == null) {
 -            throw new CloudRuntimeException("Cannot find template adapter for " + type.toString());
 -        }
 -
 -        return adapter;
 +    	TemplateAdapter adapter = null;
 +    	if (type == HypervisorType.BareMetal) {
 +    		adapter = AdapterBase.getAdapterByName(_adapters, TemplateAdapterType.BareMetal.getName());
 +    	} else {
 +    		// see HypervisorTemplateAdapter
 +    		adapter =  AdapterBase.getAdapterByName(_adapters, TemplateAdapterType.Hypervisor.getName());
 +    	}
 +    	
 +    	if (adapter == null) {
 +    		throw new CloudRuntimeException("Cannot find template adapter for " + type.toString());
 +    	}
 +    	
 +    	return adapter;
      }
 -
 +    
      @Override
      @ActionEvent(eventType = EventTypes.EVENT_ISO_CREATE, eventDescription = "creating iso")
-     public VirtualMachineTemplate registerIso(RegisterIsoCmd cmd) throws ResourceAllocationException{
+     public VirtualMachineTemplate registerIso(RegisterIsoCmd cmd) throws ResourceAllocationException {
 -        TemplateAdapter adapter = getAdapter(HypervisorType.None);
 -        TemplateProfile profile = adapter.prepare(cmd);
 -        VMTemplateVO template = adapter.create(profile);
 -
 +    	TemplateAdapter adapter = getAdapter(HypervisorType.None);
-     	TemplateProfile profile = adapter.prepare(cmd);    	
++    	TemplateProfile profile = adapter.prepare(cmd);
 +    	VMTemplateVO template = adapter.create(profile);
 +    	
-     	if (template != null){
+         if (template != null) {
 -            return template;
 +        	return template;
-         }else {
+         } else {
 -            throw new CloudRuntimeException("Failed to create ISO");
 +        	throw new CloudRuntimeException("Failed to create ISO");
          }
      }
  
      @Override
      @ActionEvent(eventType = EventTypes.EVENT_TEMPLATE_CREATE, eventDescription = "creating template")
-     public VirtualMachineTemplate registerTemplate(RegisterTemplateCmd cmd) throws URISyntaxException, ResourceAllocationException{
-         if(cmd.getTemplateTag() != null){
+     public VirtualMachineTemplate registerTemplate(RegisterTemplateCmd cmd) throws URISyntaxException, ResourceAllocationException {
+         if (cmd.getTemplateTag() != null) {
 -            Account account = UserContext.current().getCaller();
 +            Account account = CallContext.current().getCallingAccount();
-             if(!_accountService.isRootAdmin(account.getType())){
+             if (!_accountService.isRootAdmin(account.getType())) {
                  throw new PermissionDeniedException("Parameter templatetag can only be specified by a Root Admin, permission denied");
              }
          }
 -
 -        TemplateAdapter adapter = getAdapter(HypervisorType.getType(cmd.getHypervisor()));
 -        TemplateProfile profile = adapter.prepare(cmd);
 -        VMTemplateVO template = adapter.create(profile);
 -
 +        
 +    	TemplateAdapter adapter = getAdapter(HypervisorType.getType(cmd.getHypervisor()));
 +    	TemplateProfile profile = adapter.prepare(cmd);
 +    	VMTemplateVO template = adapter.create(profile);
 +    	
-     	if (template != null){
+         if (template != null) {
 -            return template;
 +        	return template;
-         }else {
+         } else {
 -            throw new CloudRuntimeException("Failed to create a template");
 +        	throw new CloudRuntimeException("Failed to create a template");
          }
      }
 -
 +    
      @Override
      public DataStore getImageStore(String storeUuid, Long zoneId) {
          DataStore imageStore = null;
          if (storeUuid != null) {
-             imageStore = this.dataStoreMgr.getDataStore(storeUuid, DataStoreRole.Image);
 -            imageStore = this._dataStoreMgr.getDataStore(storeUuid, DataStoreRole.Image);
++            imageStore = _dataStoreMgr.getDataStore(storeUuid, DataStoreRole.Image);
          } else {
-             List<DataStore> stores = this.dataStoreMgr.getImageStores(new ZoneScope(zoneId));
 -            List<DataStore> stores = this._dataStoreMgr.getImageStoresByScope(new ZoneScope(zoneId));
++            List<DataStore> stores = _dataStoreMgr.getImageStoresByScope(new ZoneScope(zoneId));
              if (stores.size() > 1) {
                  throw new CloudRuntimeException("multiple image stores, don't know which one to use");
              }
@@@ -340,27 -384,21 +370,21 @@@
  
      @Override
      @ActionEvent(eventType = EventTypes.EVENT_ISO_EXTRACT, eventDescription = "extracting ISO", async = true)
-     public Long extract(ExtractIsoCmd cmd) {
-         Account account = CallContext.current().getCallingAccount();
+     public String extract(ExtractIsoCmd cmd) {
 -        Account account = UserContext.current().getCaller();
++    Account account = CallContext.current().getCallingAccount();
          Long templateId = cmd.getId();
          Long zoneId = cmd.getZoneId();
          String url = cmd.getUrl();
          String mode = cmd.getMode();
          Long eventId = cmd.getStartEventId();
 -
 +        
-         // FIXME: async job needs fixing
-         Long uploadId = extract(account, templateId, url, zoneId, mode, eventId, true, null, _asyncMgr);
-         if (uploadId != null){
-         	return uploadId;
-         }else {
-         	throw new CloudRuntimeException("Failed to extract the iso");
-         }
+         return extract(account, templateId, url, zoneId, mode, eventId, true);
      }
  
      @Override
      @ActionEvent(eventType = EventTypes.EVENT_TEMPLATE_EXTRACT, eventDescription = "extracting template", async = true)
-     public Long extract(ExtractTemplateCmd cmd) {
-         Account caller = CallContext.current().getCallingAccount();
+     public String extract(ExtractTemplateCmd cmd) {
 -        Account caller = UserContext.current().getCaller();
++    Account caller = CallContext.current().getCallingAccount();
          Long templateId = cmd.getId();
          Long zoneId = cmd.getZoneId();
          String url = cmd.getUrl();
@@@ -374,52 -412,48 +398,48 @@@
          TemplateAdapter adapter = getAdapter(template.getHypervisorType());
          TemplateProfile profile = adapter.prepareExtractTemplate(cmd);
  
-         // FIXME: async job needs fixing
-         Long uploadId = extract(caller, templateId, url, zoneId, mode, eventId, false, null, _asyncMgr);
-         if (uploadId != null){
-         	return uploadId;
-         }else {
-         	throw new CloudRuntimeException("Failed to extract the teamplate");
-         }
+         return extract(caller, templateId, url, zoneId, mode, eventId, false);
      }
 -
 +    
      @Override
      public VirtualMachineTemplate prepareTemplate(long templateId, long zoneId) {
 -
 -        VMTemplateVO vmTemplate = _tmpltDao.findById(templateId);
 +    	
 +    	VMTemplateVO vmTemplate = _tmpltDao.findById(templateId);
-     	if(vmTemplate == null)
+         if (vmTemplate == null)
 -            throw new InvalidParameterValueException("Unable to find template id=" + templateId);
 -
 -        _accountMgr.checkAccess(UserContext.current().getCaller(), AccessType.ModifyEntry, true, vmTemplate);
 -
 -        prepareTemplateInAllStoragePools(vmTemplate, zoneId);
 -        return vmTemplate;
 +    		throw new InvalidParameterValueException("Unable to find template id=" + templateId);
 +    	
 +    	_accountMgr.checkAccess(CallContext.current().getCallingAccount(), AccessType.ModifyEntry, true, vmTemplate);
 +    	
 +    	prepareTemplateInAllStoragePools(vmTemplate, zoneId);
 +    	return vmTemplate;
      }
  
-     private Long extract(Account caller, Long templateId, String url, Long zoneId, String mode, Long eventId, boolean isISO, AsyncJobVO job, AsyncJobManager mgr) {
+     private String extract(Account caller, Long templateId, String url, Long zoneId, String mode, Long eventId, boolean isISO) {
          String desc = Upload.Type.TEMPLATE.toString();
          if (isISO) {
              desc = Upload.Type.ISO.toString();
          }
-         eventId = eventId == null ? 0:eventId;
+         eventId = eventId == null ? 0 : eventId;
 -
 +        
          if (!_accountMgr.isRootAdmin(caller.getType()) && _disableExtraction) {
              throw new PermissionDeniedException("Extraction has been disabled by admin");
          }
 -
 +        
          VMTemplateVO template = _tmpltDao.findById(templateId);
          if (template == null || template.getRemoved() != null) {
-             throw new InvalidParameterValueException("Unable to find " +desc+ " with id " + templateId);
+             throw new InvalidParameterValueException("Unable to find " + desc + " with id " + templateId);
          }
 -
 +        
-         if (template.getTemplateType() ==  Storage.TemplateType.SYSTEM){
-             throw new InvalidParameterValueException("Unable to extract the " + desc + " " + template.getName() + " as it is a default System template");
-         } else if (template.getTemplateType() ==  Storage.TemplateType.PERHOST){
-             throw new InvalidParameterValueException("Unable to extract the " + desc + " " + template.getName() + " as it resides on host and not on SSVM");
+         if (template.getTemplateType() == Storage.TemplateType.SYSTEM) {
+             throw new InvalidParameterValueException("Unable to extract the " + desc + " " + template.getName()
+                     + " as it is a default System template");
+         } else if (template.getTemplateType() == Storage.TemplateType.PERHOST) {
+             throw new InvalidParameterValueException("Unable to extract the " + desc + " " + template.getName()
+                     + " as it resides on host and not on SSVM");
          }
 -
 +        
          if (isISO) {
-             if (template.getFormat() != ImageFormat.ISO ){
+             if (template.getFormat() != ImageFormat.ISO) {
                  throw new InvalidParameterValueException("Unsupported format, could not extract the ISO");
              }
          } else {
@@@ -427,493 -461,180 +447,180 @@@
                  throw new InvalidParameterValueException("Unsupported format, could not extract the template");
              }
          }
 -
 +        
- 		if (zoneId == null && _swiftMgr.isSwiftEnabled()) {
-             zoneId = _swiftMgr.chooseZoneForTmpltExtract(templateId);
-         }
- 
-         if (zoneId == null && _s3Mgr.isS3Enabled()) {
-             zoneId = _s3Mgr.chooseZoneForTemplateExtract(template);
-         }
- 
-         if (_dcDao.findById(zoneId) == null) {
+         if (zoneId != null && _dcDao.findById(zoneId) == null) {
              throw new IllegalArgumentException("Please specify a valid zone.");
          }
 -
 +        
          if (!_accountMgr.isRootAdmin(caller.getType()) && !template.isExtractable()) {
              throw new InvalidParameterValueException("Unable to extract template id=" + templateId + " as it's not extractable");
          }
 -
 +        
          _accountMgr.checkAccess(caller, AccessType.ModifyEntry, true, template);
 -
 -        List<DataStore> ssStores = this._dataStoreMgr.getImageStoresByScope(new ZoneScope(zoneId));
 +        
-         List<HostVO> sservers = getSecondaryStorageHosts(zoneId);
- 
-         VMTemplateHostVO tmpltHostRef = null;
-         if (sservers != null) {
-             for(HostVO secondaryStorageHost: sservers){
-                 tmpltHostRef = _tmpltHostDao.findByHostTemplate(secondaryStorageHost.getId(), templateId);
-                 if (tmpltHostRef != null){
-                     if (tmpltHostRef.getDownloadState() != com.cloud.storage.VMTemplateStorageResourceAssoc.Status.DOWNLOADED) {
-                         tmpltHostRef = null;
-                     }
-                     else {
++        List<DataStore> ssStores = _dataStoreMgr.getImageStoresByScope(new ZoneScope(zoneId));
+ 
+         TemplateDataStoreVO tmpltStoreRef = null;
+         ImageStoreEntity tmpltStore = null;
+         if (ssStores != null) {
+             for (DataStore store : ssStores) {
 -                tmpltStoreRef = this._tmplStoreDao.findByStoreTemplate(store.getId(), templateId);
++                tmpltStoreRef = _tmplStoreDao.findByStoreTemplate(store.getId(), templateId);
+                 if (tmpltStoreRef != null) {
+                     if (tmpltStoreRef.getDownloadState() == com.cloud.storage.VMTemplateStorageResourceAssoc.Status.DOWNLOADED) {
+                         tmpltStore = (ImageStoreEntity) store;
                          break;
                      }
                  }
              }
          }
 -
 +        
-         if (tmpltHostRef == null && _swiftMgr.isSwiftEnabled()) {
-             SwiftTO swift = _swiftMgr.getSwiftTO(templateId);
-             if (swift != null && sservers != null) {
-                 downloadTemplateFromSwiftToSecondaryStorage(zoneId, templateId);
-             }
-         } else if (tmpltHostRef == null && _s3Mgr.isS3Enabled()) {
-             if (sservers != null) {
-                 _s3Mgr.downloadTemplateFromS3ToSecondaryStorage(zoneId,
-                         templateId, _primaryStorageDownloadWait);
-             }
-         }
- 
-         if (tmpltHostRef == null) {
+         if (tmpltStoreRef == null) {
              throw new InvalidParameterValueException("The " + desc + " has not been downloaded ");
          }
 -
 +        
-         Upload.Mode extractMode;
-         if (mode == null || (!mode.equalsIgnoreCase(Upload.Mode.FTP_UPLOAD.toString()) && !mode.equalsIgnoreCase(Upload.Mode.HTTP_DOWNLOAD.toString())) ){
-             throw new InvalidParameterValueException("Please specify a valid extract Mode. Supported modes: "+ Upload.Mode.FTP_UPLOAD + ", " + Upload.Mode.HTTP_DOWNLOAD);
-         } else {
-             extractMode = mode.equalsIgnoreCase(Upload.Mode.FTP_UPLOAD.toString()) ? Upload.Mode.FTP_UPLOAD : Upload.Mode.HTTP_DOWNLOAD;
-         }
-         
-         if (extractMode == Upload.Mode.FTP_UPLOAD){
-             URI uri = null;
-             try {
-                 uri = new URI(url);
-                 if ((uri.getScheme() == null) || (!uri.getScheme().equalsIgnoreCase("ftp") )) {
-                    throw new InvalidParameterValueException("Unsupported scheme for url: " + url);
-                 }
-             } catch (Exception ex) {
-                 throw new InvalidParameterValueException("Invalid url given: " + url);
-             }
-     
-             String host = uri.getHost();
-             try {
-                 InetAddress hostAddr = InetAddress.getByName(host);
-                 if (hostAddr.isAnyLocalAddress() || hostAddr.isLinkLocalAddress() || hostAddr.isLoopbackAddress() || hostAddr.isMulticastAddress() ) {
-                     throw new InvalidParameterValueException("Illegal host specified in url");
-                 }
-                 if (hostAddr instanceof Inet6Address) {
-                     throw new InvalidParameterValueException("IPV6 addresses not supported (" + hostAddr.getHostAddress() + ")");
-                 }
-             } catch (UnknownHostException uhe) {
-                 throw new InvalidParameterValueException("Unable to resolve " + host);
-             }
-                     
-             if (_uploadMonitor.isTypeUploadInProgress(templateId, isISO ? Type.ISO : Type.TEMPLATE) ){
-                 throw new IllegalArgumentException(template.getName() + " upload is in progress. Please wait for some time to schedule another upload for the same"); 
-             }
-         
-             return _uploadMonitor.extractTemplate(template, url, tmpltHostRef, zoneId, eventId, job.getId(), mgr);            
-         }
-         
-         UploadVO vo = _uploadMonitor.createEntityDownloadURL(template, tmpltHostRef, zoneId, eventId);
-         if (vo != null){                                  
-             return vo.getId();
-         }else{
-             return null;
-         }
+         return tmpltStore.createEntityExtractUrl(tmpltStoreRef.getInstallPath(), template.getFormat());
      }
 -
 +    
      public void prepareTemplateInAllStoragePools(final VMTemplateVO template, long zoneId) {
 -        List<StoragePoolVO> pools = _poolDao.listByStatus(StoragePoolStatus.Up);
 +    	List<StoragePoolVO> pools = _poolDao.listByStatus(StoragePoolStatus.Up);
-     	for(final StoragePoolVO pool : pools) {
-     		if(pool.getDataCenterId() == zoneId) {
+         for (final StoragePoolVO pool : pools) {
+             if (pool.getDataCenterId() == zoneId) {
 -                s_logger.info("Schedule to preload template " + template.getId() + " into primary storage " + pool.getId());
 -                this._preloadExecutor.execute(new Runnable() {
 +    			s_logger.info("Schedule to preload template " + template.getId() + " into primary storage " + pool.getId());
- 	    		this._preloadExecutor.execute(new Runnable() {
++	    		_preloadExecutor.execute(new Runnable() {
+                     @Override
 -                    public void run() {
 -                        try {
 -                            reallyRun();
 +	    			public void run() {
 +	    				try {
 +	    					reallyRun();
- 	    				} catch(Throwable e) {
+                         } catch (Throwable e) {
 -                            s_logger.warn("Unexpected exception ", e);
 -                        }
 -                    }
 -
 -                    private void reallyRun() {
 -                        s_logger.info("Start to preload template " + template.getId() + " into primary storage " + pool.getId());
 +	    					s_logger.warn("Unexpected exception ", e);
 +	    				}
 +	    			}
 +	    			
 +	    			private void reallyRun() {
 +	        			s_logger.info("Start to preload template " + template.getId() + " into primary storage " + pool.getId());
- 	        			StoragePool pol = (StoragePool)dataStoreMgr.getPrimaryDataStore(pool.getId());
+                         StoragePool pol = (StoragePool) _dataStoreMgr.getPrimaryDataStore(pool.getId());
 -                        prepareTemplateForCreate(template, pol);
 -                        s_logger.info("End of preloading template " + template.getId() + " into primary storage " + pool.getId());
 -                    }
 -                });
 -            } else {
 +	        			prepareTemplateForCreate(template, pol);
 +	        			s_logger.info("End of preloading template " + template.getId() + " into primary storage " + pool.getId());
 +	    			}
 +	    		});
 +    		} else {
-     			s_logger.info("Skip loading template " + template.getId() + " into primary storage " + pool.getId() + " as pool zone " + pool.getDataCenterId() + " is ");
-     		}
-     	}
-     }
-     
-     String downloadTemplateFromSwiftToSecondaryStorage(long dcId, long templateId){
-         VMTemplateVO template = _tmpltDao.findById(templateId);
-         if ( template == null ) {
-             String errMsg = " Can not find template " + templateId;
-             s_logger.warn(errMsg);
-             return errMsg;
-         }
-         VMTemplateSwiftVO tmpltSwift = _swiftMgr.findByTmpltId(templateId);
-         if ( tmpltSwift == null ) {
-             String errMsg = " Template " + templateId + " doesn't exist in swift";
-             s_logger.warn(errMsg);
-             return errMsg;
-         }
-         SwiftTO swift = _swiftMgr.getSwiftTO(tmpltSwift.getSwiftId());
-         if ( swift == null ) {
-             String errMsg = " Swift " + tmpltSwift.getSwiftId() + " doesn't exit ?";
-             s_logger.warn(errMsg);
-             return errMsg;
-         }
- 
-         HostVO secHost = _ssvmMgr.findSecondaryStorageHost(dcId);
-         if ( secHost == null ) {
-             String errMsg = "Can not find secondary storage in data center " + dcId;
-             s_logger.warn(errMsg);
-             return errMsg;
-         }
- 
-         DownloadTemplateFromSwiftToSecondaryStorageCommand cmd = new DownloadTemplateFromSwiftToSecondaryStorageCommand(swift, secHost.getName(), dcId, template.getAccountId(), templateId,
-                 tmpltSwift.getPath(), _primaryStorageDownloadWait);
-         try {
-             Answer answer = _agentMgr.sendToSSVM(dcId, cmd);
-             if (answer == null || !answer.getResult()) {
-                 String errMsg = "Failed to download template from Swift to secondary storage due to " + (answer == null ? "answer is null" : answer.getDetails());
-                 s_logger.warn(errMsg);
-                 throw new CloudRuntimeException(errMsg);
-             }
-             String installPath = "template/tmpl/" + template.getAccountId() + "/" + template.getId() + "/" + tmpltSwift.getPath();
-             VMTemplateHostVO tmpltHost = new VMTemplateHostVO(secHost.getId(), templateId, new Date(), 100, Status.DOWNLOADED, null, null, null, installPath, template.getUrl());
-             tmpltHost.setSize(tmpltSwift.getSize());
-             tmpltHost.setPhysicalSize(tmpltSwift.getPhysicalSize());
-             _tmpltHostDao.persist(tmpltHost);
-         } catch (Exception e) {
-             String errMsg = "Failed to download template from Swift to secondary storage due to " + e.toString();
-             s_logger.warn(errMsg);
-             throw new CloudRuntimeException(errMsg);
-         }
-         return null;
-     }
- 
-     String uploadTemplateToSwiftFromSecondaryStorage(VMTemplateHostVO templateHostRef) {
-         Long templateId = templateHostRef.getTemplateId();
-         VMTemplateVO template = _tmpltDao.findById(templateId);
-         if (template == null) {
-             String errMsg = " Can not find template " + templateId;
-             s_logger.warn(errMsg);
-             return errMsg;
-         }
- 
-         if (template.getTemplateType() == TemplateType.PERHOST) {
-             return null;
-         }
- 
-         SwiftTO swift = _swiftMgr.getSwiftTO();
-         if (swift == null) {
-             String errMsg = " There is no Swift in this setup ";
-             s_logger.warn(errMsg);
-             return errMsg;
-         }
- 
-         HostVO secHost = _hostDao.findById(templateHostRef.getHostId());
-         if (secHost == null) {
-             String errMsg = "Can not find secondary storage " + templateHostRef.getHostId();
-             s_logger.warn(errMsg);
-             return errMsg;
-         }
- 
-         UploadTemplateToSwiftFromSecondaryStorageCommand cmd = new UploadTemplateToSwiftFromSecondaryStorageCommand(swift, secHost.getName(), secHost.getDataCenterId(), template.getAccountId(),
-                 templateId, _primaryStorageDownloadWait);
-         Answer answer = null;
-         try {
-             answer = _agentMgr.sendToSSVM(secHost.getDataCenterId(), cmd);
-             if (answer == null || !answer.getResult()) {
-                 if (template.getTemplateType() != TemplateType.SYSTEM) {
-                     String errMsg = "Failed to upload template " + templateId + " to Swift from secondary storage due to " + ((answer == null) ? "null" : answer.getDetails());
-                     s_logger.warn(errMsg);
-                     throw new CloudRuntimeException(errMsg);
+                 s_logger.info("Skip loading template " + template.getId() + " into primary storage " + pool.getId() + " as pool zone "
+                         + pool.getDataCenterId() + " is ");
 -            }
 +                }
-                 return null;
-             }
-             String path = templateHostRef.getInstallPath();
-             int index = path.lastIndexOf('/');
-             path = path.substring(index + 1);
-             VMTemplateSwiftVO tmpltSwift = new VMTemplateSwiftVO(swift.getId(), templateHostRef.getTemplateId(), new Date(), path, templateHostRef.getSize(), templateHostRef.getPhysicalSize());
-             _tmpltSwiftDao.persist(tmpltSwift);
-             _swiftMgr.propagateTemplateOnAllZones(templateHostRef.getTemplateId());
-         } catch (Exception e) {
-             String errMsg = "Failed to upload template " + templateId + " to Swift from secondary storage due to " + e.toString();
-             s_logger.warn(errMsg);
-             throw new CloudRuntimeException(errMsg);
          }
-         return null;
      }
  
-     @Override @DB
+     @Override
+     @DB
      public VMTemplateStoragePoolVO prepareTemplateForCreate(VMTemplateVO templ, StoragePool pool) {
 -        VMTemplateVO template = _tmpltDao.findById(templ.getId(), true);
 -
 +    	VMTemplateVO template = _tmpltDao.findById(templ.getId(), true);
 +    	
          long poolId = pool.getId();
          long templateId = template.getId();
-         long dcId = pool.getDataCenterId();
          VMTemplateStoragePoolVO templateStoragePoolRef = null;
-         VMTemplateHostVO templateHostRef = null;
-         long templateStoragePoolRefId;
-         String origUrl = null;
+         TemplateDataStoreVO templateStoreRef = null;
 -
 +        
          templateStoragePoolRef = _tmpltPoolDao.findByPoolTemplate(poolId, templateId);
          if (templateStoragePoolRef != null) {
 -            templateStoragePoolRef.setMarkedForGC(false);
 +        	templateStoragePoolRef.setMarkedForGC(false);
              _tmpltPoolDao.update(templateStoragePoolRef.getId(), templateStoragePoolRef);
 -
 +            
              if (templateStoragePoolRef.getDownloadState() == Status.DOWNLOADED) {
 -                if (s_logger.isDebugEnabled()) {
 -                    s_logger.debug("Template " + templateId + " has already been downloaded to pool " + poolId);
 -                }
 -
 -                return templateStoragePoolRef;
 -            }
 -        }
 -
 -        templateStoreRef = this._tmplStoreDao.findByTemplateZoneDownloadStatus(templateId, pool.getDataCenterId(),
 +	            if (s_logger.isDebugEnabled()) {
 +	                s_logger.debug("Template " + templateId + " has already been downloaded to pool " + poolId);
 +	            }
 +	            
 +	            return templateStoragePoolRef;
 +	        }
 +        }
 +        
-         templateHostRef = findVmTemplateHost(templateId, pool);
-         
-         if (templateHostRef == null || templateHostRef.getDownloadState() != Status.DOWNLOADED) {
-             String result = downloadTemplateFromSwiftToSecondaryStorage(dcId, templateId);
-             if (result != null) {
-                 s_logger.error("Unable to find a secondary storage host who has completely downloaded the template.");
-                 return null;
-             }
-             result = _s3Mgr.downloadTemplateFromS3ToSecondaryStorage(dcId,
-                     templateId, _primaryStorageDownloadWait);
-             if (result != null) {
-                 s_logger.error("Unable to find a secondary storage host who has completely downloaded the template.");
-                 return null;
-             }
-             templateHostRef = findVmTemplateHost(templateId, pool);
-             if (templateHostRef == null || templateHostRef.getDownloadState() != Status.DOWNLOADED) {
++        templateStoreRef = _tmplStoreDao.findByTemplateZoneDownloadStatus(templateId, pool.getDataCenterId(),
+                 VMTemplateStorageResourceAssoc.Status.DOWNLOADED);
+         if (templateStoreRef == null) {
 -            s_logger.error("Unable to find a secondary storage host who has completely downloaded the template.");
 -            return null;
 -        }
 -
 +                s_logger.error("Unable to find a secondary storage host who has completely downloaded the template.");
 +                return null;
 +            }
-         }
 +        
-         HostVO sh = _hostDao.findById(templateHostRef.getHostId());
-         origUrl = sh.getStorageUrl();
-         if (origUrl == null) {
-             throw new CloudRuntimeException("Unable to find the orig.url from host " + sh.toString());
+         List<StoragePoolHostVO> vos = _poolHostDao.listByHostStatus(poolId, com.cloud.host.Status.Up);
+         if (vos == null || vos.isEmpty()) {
+             throw new CloudRuntimeException("Cannot download " + templateId + " to poolId " + poolId
+                     + " since there is no host in the Up state connected to this pool");
          }
 -
 +        
          if (templateStoragePoolRef == null) {
              if (s_logger.isDebugEnabled()) {
                  s_logger.debug("Downloading template " + templateId + " to pool " + poolId);
              }
-             templateStoragePoolRef = new VMTemplateStoragePoolVO(poolId, templateId);
-             try {
-                 templateStoragePoolRef = _tmpltPoolDao.persist(templateStoragePoolRef);
-                 templateStoragePoolRefId =  templateStoragePoolRef.getId();
-                 
-             } catch (Exception e) {
-                 s_logger.debug("Assuming we're in a race condition: " + e.getMessage());
-                 templateStoragePoolRef = _tmpltPoolDao.findByPoolTemplate(poolId, templateId);
-                 if (templateStoragePoolRef == null) {
-                     throw new CloudRuntimeException("Unable to persist a reference for pool " + poolId + " and template " + templateId);
-                 }
-                 templateStoragePoolRefId = templateStoragePoolRef.getId();
-             }
-         } else {
-             templateStoragePoolRefId = templateStoragePoolRef.getId();
-         }
-         
-         List<StoragePoolHostVO> vos = _poolHostDao.listByHostStatus(poolId, com.cloud.host.Status.Up);
-         if (vos == null || vos.isEmpty()){
-         	 throw new CloudRuntimeException("Cannot download " + templateId + " to poolId " + poolId + " since there is no host in the Up state connected to this pool");            
-         }                
-         
-         templateStoragePoolRef = _tmpltPoolDao.acquireInLockTable(templateStoragePoolRefId, _storagePoolMaxWaitSeconds);
-         if (templateStoragePoolRef == null) {
-             throw new CloudRuntimeException("Unable to acquire lock on VMTemplateStoragePool: " + templateStoragePoolRefId);
-         }
 -            DataStore srcSecStore = this._dataStoreMgr.getDataStore(templateStoreRef.getDataStoreId(), DataStoreRole.Image);
 -            TemplateInfo srcTemplate = this._tmplFactory.getTemplate(templateId, srcSecStore);
++            DataStore srcSecStore = _dataStoreMgr.getDataStore(templateStoreRef.getDataStoreId(), DataStoreRole.Image);
++            TemplateInfo srcTemplate = _tmplFactory.getTemplate(templateId, srcSecStore);
  
 -            AsyncCallFuture<TemplateApiResult> future = this._tmpltSvr.prepareTemplateOnPrimary(srcTemplate, pool);
 -            try {
++            AsyncCallFuture<TemplateApiResult> future = _tmpltSvr.prepareTemplateOnPrimary(srcTemplate, pool);
 +        try {
-             if (templateStoragePoolRef.getDownloadState() == Status.DOWNLOADED) {
-                 return templateStoragePoolRef;
-             }
-             String url = origUrl + "/" + templateHostRef.getInstallPath();
-             PrimaryStorageDownloadCommand dcmd = new PrimaryStorageDownloadCommand(template.getUniqueName(), url, template.getFormat(), 
-                    template.getAccountId(), pool, _primaryStorageDownloadWait);
-             HostVO secondaryStorageHost = _hostDao.findById(templateHostRef.getHostId());
-             assert(secondaryStorageHost != null);
-             dcmd.setSecondaryStorageUrl(secondaryStorageHost.getStorageUrl());
-             // TODO temporary hacking, hard-coded to NFS primary data store
-             dcmd.setPrimaryStorageUrl("nfs://" + pool.getHostAddress() + pool.getPath());
-             
-             for (int retry = 0; retry < 2; retry ++){
-             	Collections.shuffle(vos); // Shuffling to pick a random host in the vm deployment retries
-             	StoragePoolHostVO vo = vos.get(0);
- 	            if (s_logger.isDebugEnabled()) {
- 	                s_logger.debug("Downloading " + templateId + " via " + vo.getHostId());
- 	            }
- 	        	dcmd.setLocalPath(vo.getLocalPath());
- 	        	// set 120 min timeout for this command
- 	        	
- 	        	PrimaryStorageDownloadAnswer answer = (PrimaryStorageDownloadAnswer)_agentMgr.easySend(
- 	                   _hvGuruMgr.getGuruProcessedCommandTargetHost(vo.getHostId(), dcmd), dcmd);
- 	            if (answer != null && answer.getResult() ) {
- 	        		templateStoragePoolRef.setDownloadPercent(100);
- 	        		templateStoragePoolRef.setDownloadState(Status.DOWNLOADED);
- 	        		templateStoragePoolRef.setLocalDownloadPath(answer.getInstallPath());
- 	        		templateStoragePoolRef.setInstallPath(answer.getInstallPath());
- 	        		templateStoragePoolRef.setTemplateSize(answer.getTemplateSize());
- 	        		_tmpltPoolDao.update(templateStoragePoolRef.getId(), templateStoragePoolRef);
- 	        		if (s_logger.isDebugEnabled()) {
- 	        			s_logger.debug("Template " + templateId + " is downloaded via " + vo.getHostId());
- 	        		}
- 	        		return templateStoragePoolRef;
- 	            } else {
- 	                if (s_logger.isDebugEnabled()) {
- 	                    s_logger.debug("Template " + templateId + " download to pool " + vo.getPoolId() + " failed due to " + (answer!=null?answer.getDetails():"return null"));                }
- 	            }
-             }
-         } finally {
-             _tmpltPoolDao.releaseFromLockTable(templateStoragePoolRefId);
-         }
-         if (s_logger.isDebugEnabled()) {
-             s_logger.debug("Template " + templateId + " is not found on and can not be downloaded to pool " + poolId);
-         }
+                 TemplateApiResult result = future.get();
+                 if (result.isFailed()) {
+                     s_logger.debug("prepare template failed:" + result.getResult());
 -                    return null;
 -                }
 -
 +        return null;
 +    }
 +    
-     
-     
-     
-     @Override
-     public VMTemplateHostVO findVmTemplateHost(long templateId,
-             StoragePool pool) {
-         long dcId = pool.getDataCenterId();
-         Long podId = pool.getPodId();
- 
-         List<HostVO> secHosts = _ssvmMgr
-                 .listSecondaryStorageHostsInOneZone(dcId);
- 
- 
-         if (secHosts.size() == 1) {
-             VMTemplateHostVO templateHostVO = this._tmpltHostDao
-                     .findByHostTemplate(secHosts.get(0).getId(), templateId);
-             return templateHostVO;
-         }
-         if (podId != null) {
-             List<VMTemplateHostVO> templHosts = this._tmpltHostDao
-                     .listByTemplateStatus(templateId, dcId, podId,
-                             VMTemplateStorageResourceAssoc.Status.DOWNLOADED);
-             if (templHosts != null && !templHosts.isEmpty()) {
-                 Collections.shuffle(templHosts);
-                 return templHosts.get(0);
-             }
+                 return _tmpltPoolDao.findByPoolTemplate(poolId, templateId);
+             } catch (Exception ex) {
+                 s_logger.debug("failed to copy template from image store:" + srcSecStore.getName() + " to primary storage");
 -            }
 +        }
-         List<VMTemplateHostVO> templHosts = this._tmpltHostDao
-                 .listByTemplateStatus(templateId, dcId,
-                         VMTemplateStorageResourceAssoc.Status.DOWNLOADED);
-         if (templHosts != null && !templHosts.isEmpty()) {
-             Collections.shuffle(templHosts);
-             return templHosts.get(0);
          }
+ 
          return null;
      }
 -
 +    
      @Override
-     public String getChecksum(Long hostId, String templatePath) {
-         HostVO ssHost = _hostDao.findById(hostId);
-         Host.Type type = ssHost.getType();
-         if (type != Host.Type.SecondaryStorage
-                 && type != Host.Type.LocalSecondaryStorage) {
-             return null;
-         }
-         String secUrl = ssHost.getStorageUrl();
-         Answer answer;
-         answer = _agentMgr.sendToSecStorage(ssHost, new ComputeChecksumCommand(
-                 secUrl, templatePath));
+     public String getChecksum(DataStore store, String templatePath) {
+         EndPoint ep = _epSelector.select(store);
+         ComputeChecksumCommand cmd = new ComputeChecksumCommand(store.getTO(), templatePath);
+         Answer answer = ep.sendMessage(cmd);
          if (answer != null && answer.getResult()) {
              return answer.getDetails();
          }
          return null;
      }
 -
 +    
      @Override
      @DB
-     public VMTemplateHostVO prepareISOForCreate(VMTemplateVO template, StoragePool pool) {
-         template = _tmpltDao.findById(template.getId(), true);
- 
-         long poolId = pool.getId();
-         long templateId = template.getId();
-         long dcId = pool.getDataCenterId();
-         VMTemplateStoragePoolVO templateStoragePoolRef = null;
-         VMTemplateHostVO templateHostRef = null;
-         long templateStoragePoolRefId;
-         String origUrl = null;
- 
-         templateHostRef = findVmTemplateHost(templateId, pool);
- 
-         if (templateHostRef == null || templateHostRef.getDownloadState() != Status.DOWNLOADED) {
-             String result = downloadTemplateFromSwiftToSecondaryStorage(dcId, templateId);
-             if (result != null) {
-                 s_logger.error("Unable to find a secondary storage host who has completely downloaded the template.");
-                 return null;
-             }
-             result = _s3Mgr.downloadTemplateFromS3ToSecondaryStorage(dcId,
-                     templateId, _primaryStorageDownloadWait);
-             if (result != null) {
-                 s_logger.error("Unable to find a secondary storage host who has completely downloaded the template.");
-                 return null;
-             }
-             templateHostRef = findVmTemplateHost(templateId, pool);
-             if (templateHostRef == null || templateHostRef.getDownloadState() != Status.DOWNLOADED) {
-                 s_logger.error("Unable to find a secondary storage host who has completely downloaded the template.");
-                 return null;
-             }
-         }
-         return templateHostRef;
-     }
- 
-     @Override
-     @DB
      public boolean resetTemplateDownloadStateOnPool(long templateStoragePoolRefId) {
-     	// have to use the same lock that prepareTemplateForCreate use to maintain state consistency
+         // have to use the same lock that prepareTemplateForCreate use to
+         // maintain state consistency
 -        VMTemplateStoragePoolVO templateStoragePoolRef = _tmpltPoolDao.acquireInLockTable(templateStoragePoolRefId, 1200);
 -
 +    	VMTemplateStoragePoolVO templateStoragePoolRef = _tmpltPoolDao.acquireInLockTable(templateStoragePoolRefId, 1200);
 +    	
          if (templateStoragePoolRef == null) {
 -            s_logger.warn("resetTemplateDownloadStateOnPool failed - unable to lock TemplateStorgePoolRef " + templateStoragePoolRefId);
 +        	s_logger.warn("resetTemplateDownloadStateOnPool failed - unable to lock TemplateStorgePoolRef " + templateStoragePoolRefId);
              return false;
          }
 -
 +        
          try {
 -            templateStoragePoolRef.setDownloadState(VMTemplateStorageResourceAssoc.Status.NOT_DOWNLOADED);
 -            _tmpltPoolDao.update(templateStoragePoolRefId, templateStoragePoolRef);
 +        	templateStoragePoolRef.setDownloadState(VMTemplateStorageResourceAssoc.Status.NOT_DOWNLOADED);
 +        	_tmpltPoolDao.update(templateStoragePoolRefId, templateStoragePoolRef);
          } finally {
              _tmpltPoolDao.releaseFromLockTable(templateStoragePoolRefId);
          }
 -
 +        
          return true;
      }
 -
 +    
      @Override
      @DB
-     public boolean copy(long userId, VMTemplateVO template, HostVO srcSecHost, DataCenterVO srcZone, DataCenterVO dstZone) throws StorageUnavailableException, ResourceAllocationException {
-         List<HostVO> dstSecHosts = _ssvmMgr.listSecondaryStorageHostsInOneZone(dstZone.getId());
+     public boolean copy(long userId, VMTemplateVO template, DataStore srcSecStore, DataCenterVO dstZone) throws StorageUnavailableException,
+             ResourceAllocationException {
          long tmpltId = template.getId();
          long dstZoneId = dstZone.getId();
-         if (dstSecHosts == null || dstSecHosts.isEmpty() ) {
-             throw new StorageUnavailableException("Destination zone is not ready", DataCenter.class, dstZone.getId());
+         // find all eligible image stores for the destination zone
 -        List<DataStore> dstSecStores = this._dataStoreMgr.getImageStoresByScope(new ZoneScope(dstZoneId));
++        List<DataStore> dstSecStores = _dataStoreMgr.getImageStoresByScope(new ZoneScope(dstZoneId));
+         if (dstSecStores == null || dstSecStores.isEmpty()) {
+             throw new StorageUnavailableException("Destination zone is not ready, no image store associated", DataCenter.class, dstZone.getId());
          }
          AccountVO account = _accountDao.findById(template.getAccountId());
-         VMTemplateHostVO srcTmpltHost = _tmpltHostDao.findByHostTemplate(srcSecHost.getId(), tmpltId);
+         // find the size of the template to be copied
 -        TemplateDataStoreVO srcTmpltStore = this._tmplStoreDao.findByStoreTemplate(srcSecStore.getId(), tmpltId);
++        TemplateDataStoreVO srcTmpltStore = _tmplStoreDao.findByStoreTemplate(srcSecStore.getId(), tmpltId);
  
          _resourceLimitMgr.checkResourceLimit(account, ResourceType.template);
-         _resourceLimitMgr.checkResourceLimit(account, ResourceType.secondary_storage, new Long(srcTmpltHost.getSize()));
+         _resourceLimitMgr.checkResourceLimit(account, ResourceType.secondary_storage, new Long(srcTmpltStore.getSize()));
  
          // Event details
          String copyEventType;
@@@ -929,70 -650,49 +636,49 @@@
          Transaction txn = Transaction.currentTxn();
          txn.start();
  
-         for ( HostVO dstSecHost : dstSecHosts ) {
-             VMTemplateHostVO dstTmpltHost = null;
-             try {
-             	dstTmpltHost = _tmpltHostDao.findByHostTemplate(dstSecHost.getId(), tmpltId, true);
-             	if (dstTmpltHost != null) {
-             		dstTmpltHost = _tmpltHostDao.lockRow(dstTmpltHost.getId(), true);
-             		if (dstTmpltHost != null && dstTmpltHost.getDownloadState() == Status.DOWNLOADED) {
-             			if (dstTmpltHost.getDestroyed() == false)  {
-             				return true;
-             			} else {
-             				dstTmpltHost.setDestroyed(false);
-             				_tmpltHostDao.update(dstTmpltHost.getId(), dstTmpltHost);
-             				
-             				return true;
-             			}
-             		} else if (dstTmpltHost != null && dstTmpltHost.getDownloadState() == Status.DOWNLOAD_ERROR){
-             			if (dstTmpltHost.getDestroyed() == true)  {
-             				dstTmpltHost.setDestroyed(false);
-             				dstTmpltHost.setDownloadState(Status.NOT_DOWNLOADED);
-             				dstTmpltHost.setDownloadPercent(0);
-             				dstTmpltHost.setCopy(true);
-             				dstTmpltHost.setErrorString("");
-             				dstTmpltHost.setJobId(null);
-             				_tmpltHostDao.update(dstTmpltHost.getId(), dstTmpltHost);
 -        TemplateInfo srcTemplate = this._tmplFactory.getTemplate(template.getId(), srcSecStore);
++        TemplateInfo srcTemplate = _tmplFactory.getTemplate(template.getId(), srcSecStore);
+         // Copy will just find one eligible image store for the destination zone
+         // and copy template there, not propagate to all image stores
+         // for that zone
+         for (DataStore dstSecStore : dstSecStores) {
 -            TemplateDataStoreVO dstTmpltStore = this._tmplStoreDao.findByStoreTemplate(dstSecStore.getId(), tmpltId);
++            TemplateDataStoreVO dstTmpltStore = _tmplStoreDao.findByStoreTemplate(dstSecStore.getId(), tmpltId);
+             if (dstTmpltStore != null && dstTmpltStore.getDownloadState() == Status.DOWNLOADED) {
+                 return true; // already downloaded on this image store
 -            }
 +            			}
-             		}
-             	}
-             } finally {
-             	txn.commit();
+ 
 -            AsyncCallFuture<TemplateApiResult> future = this._tmpltSvr.copyTemplate(srcTemplate, dstSecStore);
++            AsyncCallFuture<TemplateApiResult> future = _tmpltSvr.copyTemplate(srcTemplate, dstSecStore);
+             try {
+                 TemplateApiResult result = future.get();
+                 if (result.isFailed()) {
+                     s_logger.debug("copy template failed for image store " + dstSecStore.getName() + ":" + result.getResult());
+                     continue; // try next image store
 -                }
 +            }
  
-             if(_downloadMonitor.copyTemplate(template, srcSecHost, dstSecHost) ) {
                  _tmpltDao.addTemplateToZone(template, dstZoneId);
 -
 +            	
-             	if(account.getId() != Account.ACCOUNT_ID_SYSTEM){
-                     UsageEventUtils.publishUsageEvent(copyEventType, account.getId(), dstZoneId, tmpltId, null, null, null, srcTmpltHost.getSize(),
+                 if (account.getId() != Account.ACCOUNT_ID_SYSTEM) {
+                     UsageEventUtils.publishUsageEvent(copyEventType, account.getId(), dstZoneId, tmpltId, null, null, null, srcTmpltStore.getSize(),
                              template.getClass().getName(), template.getUuid());
 -                }
 -                return true;
 +            	}
 +            	return true;
+             } catch (Exception ex) {
+                 s_logger.debug("failed to copy template to image store:" + dstSecStore.getName() + " ,will try next one");
              }
          }
          return false;
-     }
 -
 +  
+     }
 -
 +    
      @Override
      @ActionEvent(eventType = EventTypes.EVENT_TEMPLATE_COPY, eventDescription = "copying template", async = true)
      public VirtualMachineTemplate copyTemplate(CopyTemplateCmd cmd) throws StorageUnavailableException, ResourceAllocationException {
 -        Long templateId = cmd.getId();
 -        Long userId = UserContext.current().getCallerUserId();
 -        Long sourceZoneId = cmd.getSourceZoneId();
 -        Long destZoneId = cmd.getDestinationZoneId();
 -        Account caller = UserContext.current().getCaller();
 -
 +    	Long templateId = cmd.getId();
 +    	Long userId = CallContext.current().getCallingUserId();
 +    	Long sourceZoneId = cmd.getSourceZoneId();
 +    	Long destZoneId = cmd.getDestinationZoneId();
 +    	Account caller = CallContext.current().getCallingAccount();
 +        
-         if (_swiftMgr.isSwiftEnabled()) {
-             throw new CloudRuntimeException("copytemplate API is disabled in Swift setup, templates in Swift can be accessed by all Zones");
-         }
- 
-         if (_s3Mgr.isS3Enabled()) {
-             throw new CloudRuntimeException(
-                     "copytemplate API is disabled in S3 setup -- S3 templates are accessible in all zones.");
-         }
- 
-         //Verify parameters
+         // Verify parameters
          if (sourceZoneId.equals(destZoneId)) {
              throw new InvalidParameterValueException("Please specify different source and destination zones.");
          }
@@@ -1011,80 -711,85 +697,85 @@@
          if (template == null || template.getRemoved() != null) {
              throw new InvalidParameterValueException("Unable to find template with id");
          }
 -
 +      
-         HostVO dstSecHost = getSecondaryStorageHost(destZoneId, templateId);
-         if ( dstSecHost != null ) {
-             s_logger.debug("There is template " + templateId + " in secondary storage " + dstSecHost.getId() + " in zone " + destZoneId + " , don't need to copy");
+         DataStore dstSecStore = getImageStore(destZoneId, templateId);
+         if (dstSecStore != null) {
+             s_logger.debug("There is template " + templateId + " in secondary storage " + dstSecStore.getName() + " in zone " + destZoneId
+                     + " , don't need to copy");
              return template;
          }
 -
 +        
-         HostVO srcSecHost = getSecondaryStorageHost(sourceZoneId, templateId);
-         if ( srcSecHost == null ) {
-             throw new InvalidParameterValueException("There is no template " + templateId + " in zone " + sourceZoneId );
+         DataStore srcSecStore = getImageStore(sourceZoneId, templateId);
+         if (srcSecStore == null) {
+             throw new InvalidParameterValueException("There is no template " + templateId + " in zone " + sourceZoneId);
+         }
+         if (srcSecStore.getScope().getScopeType() == ScopeType.REGION) {
+             s_logger.debug("Template " + templateId + " is in region-wide secondary storage " + dstSecStore.getName() + " , don't need to copy");
+             return template;
          }
 -
 +       
          _accountMgr.checkAccess(caller, AccessType.ModifyEntry, true, template);
 -
 +        
-         boolean success = copy(userId, template, srcSecHost, sourceZone, dstZone);
+         boolean success = copy(userId, template, srcSecStore, dstZone);
 -
 +        
-     	if (success){
+         if (success) {
 -            return template;
 +        	return template;
-         }else {
+         } else {
 -            throw new CloudRuntimeException("Failed to copy template");
 +        	throw new CloudRuntimeException("Failed to copy template");
          }
      }
  
      @Override
      public boolean delete(long userId, long templateId, Long zoneId) {
 -        VMTemplateVO template = _tmpltDao.findById(templateId);
 -        if (template == null || template.getRemoved() != null) {
 -            throw new InvalidParameterValueException("Please specify a valid template.");
 -        }
 -
 -        TemplateAdapter adapter = getAdapter(template.getHypervisorType());
 -        return adapter.delete(new TemplateProfile(userId, template, zoneId));
 +    	VMTemplateVO template = _tmpltDao.findById(templateId);
 +    	if (template == null || template.getRemoved() != null) {
 +    		throw new InvalidParameterValueException("Please specify a valid template.");
 +    	}
 +    	
 +    	TemplateAdapter adapter = getAdapter(template.getHypervisorType());
 +    	return adapter.delete(new TemplateProfile(userId, template, zoneId));
      }
 -
 +    
      @Override
      public List<VMTemplateStoragePoolVO> getUnusedTemplatesInPool(StoragePoolVO pool) {
 -        List<VMTemplateStoragePoolVO> unusedTemplatesInPool = new ArrayList<VMTemplateStoragePoolVO>();
 -        List<VMTemplateStoragePoolVO> allTemplatesInPool = _tmpltPoolDao.listByPoolId(pool.getId());
 -
 -        for (VMTemplateStoragePoolVO templatePoolVO : allTemplatesInPool) {
 -            VMTemplateVO template = _tmpltDao.findByIdIncludingRemoved(templatePoolVO.getTemplateId());
 -
 -            // If this is a routing template, consider it in use
 -            if (template.getTemplateType() == TemplateType.SYSTEM) {
 -                continue;
 -            }
 -
 +		List<VMTemplateStoragePoolVO> unusedTemplatesInPool = new ArrayList<VMTemplateStoragePoolVO>();
 +		List<VMTemplateStoragePoolVO> allTemplatesInPool = _tmpltPoolDao.listByPoolId(pool.getId());
 +		
 +		for (VMTemplateStoragePoolVO templatePoolVO : allTemplatesInPool) {
- 			VMTemplateVO template = _tmpltDao.findByIdIncludingRemoved(templatePoolVO.getTemplateId());			
++			VMTemplateVO template = _tmpltDao.findByIdIncludingRemoved(templatePoolVO.getTemplateId());
 +		
 +			// If this is a routing template, consider it in use
 +			if (template.getTemplateType() == TemplateType.SYSTEM) {
 +				continue;
 +			}
 +			
- 			// If the template is not yet downloaded to the pool, consider it in use
+             // If the template is not yet downloaded to the pool, consider it in
+             // use
 -            if (templatePoolVO.getDownloadState() != Status.DOWNLOADED) {
 -                continue;
 -            }
 +			if (templatePoolVO.getDownloadState() != Status.DOWNLOADED) {
 +				continue;
 +			}
  
 -            if (template.getFormat() != ImageFormat.ISO && !_volumeDao.isAnyVolumeActivelyUsingTemplateOnPool(template.getId(), pool.getId())) {
 +			if (template.getFormat() != ImageFormat.ISO && !_volumeDao.isAnyVolumeActivelyUsingTemplateOnPool(template.getId(), pool.getId())) {
                  unusedTemplatesInPool.add(templatePoolVO);
 -            }
 -        }
 -
 -        return unusedTemplatesInPool;
 -    }
 -
 +			}
 +		}
 +		
 +		return unusedTemplatesInPool;
 +	}
 +    
      @Override
      public void evictTemplateFromStoragePool(VMTemplateStoragePoolVO templatePoolVO) {
-         StoragePool pool = (StoragePool)this.dataStoreMgr.getPrimaryDataStore(templatePoolVO.getPoolId());
 -        StoragePool pool = (StoragePool) this._dataStoreMgr.getPrimaryDataStore(templatePoolVO.getPoolId());
 -        VMTemplateVO template = _tmpltDao.findByIdIncludingRemoved(templatePoolVO.getTemplateId());
 -
 -        if (s_logger.isDebugEnabled()) {
 -            s_logger.debug("Evicting " + templatePoolVO);
 -        }
 -        DestroyCommand cmd = new DestroyCommand(pool, templatePoolVO);
 -
++        StoragePool pool = (StoragePool) _dataStoreMgr.getPrimaryDataStore(templatePoolVO.getPoolId());
 +		VMTemplateVO template = _tmpltDao.findByIdIncludingRemoved(templatePoolVO.getTemplateId());
 +		
- 		
 +		if (s_logger.isDebugEnabled()) {
 +		    s_logger.debug("Evicting " + templatePoolVO);
 +		}
 +		DestroyCommand cmd = new DestroyCommand(pool, templatePoolVO);
 +		
          try {
              Answer answer = _storageMgr.sendToPool(pool, cmd);
 -
 +		
              if (answer != null && answer.getResult()) {
                  // Remove the templatePoolVO
                  if (_tmpltPoolDao.remove(templatePoolVO.getId())) {
@@@ -1094,94 -799,14 +785,14 @@@
                  s_logger.info("Will retry evicte template: " + template.getName() + " from storage pool: " + pool.getName());
              }
          } catch (StorageUnavailableException e) {
-             s_logger.info("Storage is unavailable currently.  Will retry evicte template: " + template.getName() + " from storage pool: " + pool.getName());
+             s_logger.info("Storage is unavailable currently.  Will retry evicte template: " + template.getName() + " from storage pool: "
+                     + pool.getName());
          }
  
 -    }
 -
 +	}
 +    
-     void swiftTemplateSync() {
-         GlobalLock swiftTemplateSyncLock = GlobalLock.getInternLock("templatemgr.swiftTemplateSync");
-         try {
-             if (!_swiftMgr.isSwiftEnabled()) {
-                 return;
-             }
-             List<HypervisorType> hypers = _clusterDao.getAvailableHypervisorInZone(null);
-             List<VMTemplateVO> templates = _tmpltDao.listByHypervisorType(hypers);
-             List<Long> templateIds = new ArrayList<Long>();
-             for (VMTemplateVO template : templates) {
-                 if (template.getTemplateType() != TemplateType.PERHOST) {
-                     templateIds.add(template.getId());
-                 }
-             }
-             List<VMTemplateSwiftVO> templtSwiftRefs = _tmpltSwiftDao.listAll();
-             for (VMTemplateSwiftVO templtSwiftRef : templtSwiftRefs) {
-                 templateIds.remove((Long) templtSwiftRef.getTemplateId());
-             }
-             if (templateIds.size() < 1) {
-                 return;
-             }
-             if (swiftTemplateSyncLock.lock(3)) {
-                 try {
-                     List<VMTemplateHostVO> templtHostRefs = _tmpltHostDao.listByState(VMTemplateHostVO.Status.DOWNLOADED);
-                     for (VMTemplateHostVO templtHostRef : templtHostRefs) {
-                         if (templtHostRef.getDestroyed()) {
-                             continue;
-                         }
-                         if (!templateIds.contains(templtHostRef.getTemplateId())) {
-                             continue;
-                         }
-                         try {
-                             uploadTemplateToSwiftFromSecondaryStorage(templtHostRef);
-                         } catch (Exception e) {
-                             s_logger.debug("failed to upload template " + templtHostRef.getTemplateId() + " to Swift due to " + e.toString());
-                         }
-                     }
-                 } catch (Throwable e) {
-                     s_logger.error("Problem with sync swift template due to " + e.toString(), e);
-                 } finally {
-                     swiftTemplateSyncLock.unlock();
-                 }
-             }
-         } catch (Throwable e) {
-             s_logger.error("Problem with sync swift template due to " + e.toString(), e);
-         } finally {
-             swiftTemplateSyncLock.releaseRef();
-         }
-     }
- 
-     private Runnable getSwiftTemplateSyncTask() {
-         return new Runnable() {
-             @Override
-             public void run() {
-                 if (s_logger.isDebugEnabled()) {
-                     s_logger.trace("Start Swift Template sync at" + (new Date()));
-                 }
-                 swiftTemplateSync();
-                 if (s_logger.isTraceEnabled()) {
-                     s_logger.trace("Finish Swift Template sync at" + (new Date()));
-                 }
-             }
-         };
-     }
- 
      @Override
      public boolean start() {
-         _swiftTemplateSyncExecutor.scheduleAtFixedRate(getSwiftTemplateSyncTask(), 60, 60, TimeUnit.SECONDS);
- 
-         if (_s3TemplateSyncExecutor != null) {
- 
-             final int initialDelay = 60;
-             final int period = 60;
- 
-             _s3TemplateSyncExecutor.scheduleAtFixedRate(new S3SyncTask(
-                     this._tmpltDao, this._s3Mgr), initialDelay, period,
-                     TimeUnit.SECONDS);
-             s_logger.info(String.format("Started S3 sync task to execute "
-                     + "execute every %1$s after an initial delay of %2$s.",
-                     period, initialDelay));
- 
-         }
- 
          return true;
      }
  
@@@ -1205,31 -824,11 +810,11 @@@
          String value = _configDao.getValue(Config.PrimaryStorageDownloadWait.toString());
          _primaryStorageDownloadWait = NumbersUtil.parseInt(value, Integer.parseInt(Config.PrimaryStorageDownloadWait.getDefaultValue()));
  
 -        String disableExtraction = _configDao.getValue(Config.DisableExtraction.toString());
 -        _disableExtraction = (disableExtraction == null) ? false : Boolean.parseBoolean(disableExtraction);
 +        String disableExtraction =  _configDao.getValue(Config.DisableExtraction.toString());
 +        _disableExtraction  = (disableExtraction == null) ? false : Boolean.parseBoolean(disableExtraction);
  
-         HostTemplateStatesSearch = _tmpltHostDao.createSearchBuilder();
-         HostTemplateStatesSearch.and("id", HostTemplateStatesSearch.entity().getTemplateId(), SearchCriteria.Op.EQ);
-         HostTemplateStatesSearch.and("state", HostTemplateStatesSearch.entity().getDownloadState(), SearchCriteria.Op.EQ);
-         
-         SearchBuilder<HostVO> HostSearch = _hostDao.createSearchBuilder();
-         HostSearch.and("dcId", HostSearch.entity().getDataCenterId(), SearchCriteria.Op.EQ);
-         
-         HostTemplateStatesSearch.join("host", HostSearch, HostSearch.entity().getId(), HostTemplateStatesSearch.entity().getHostId(), JoinBuilder.JoinType.INNER);
-         HostSearch.done();
-         HostTemplateStatesSearch.done();
-         
          _storagePoolMaxWaitSeconds = NumbersUtil.parseInt(_configDao.getValue(Config.StoragePoolMaxWaitSeconds.key()), 3600);
          _preloadExecutor = Executors.newFixedThreadPool(8, new NamedThreadFactory("Template-Preloader"));
-         _swiftTemplateSyncExecutor = Executors.newScheduledThreadPool(1, new NamedThreadFactory("swift-template-sync-Executor"));
- 
-         if (_s3Mgr.isS3Enabled()) {
-             _s3TemplateSyncExecutor = Executors
-                     .newSingleThreadScheduledExecutor(new NamedThreadFactory(
-                             "s3-template-sync"));
-         } else {
-             s_logger.info("S3 secondary storage synchronization is disabled.");
-         }
  
          return true;
      }
@@@ -1237,52 -836,73 +822,73 @@@
      protected TemplateManagerImpl() {
      }
  
 -    @Override
 -    public boolean templateIsDeleteable(VMTemplateHostVO templateHostRef) {
 -        VMTemplateVO template = _tmpltDao.findByIdIncludingRemoved(templateHostRef.getTemplateId());
 -        long templateId = template.getId();
 -        HostVO secondaryStorageHost = _hostDao.findById(templateHostRef.getHostId());
 -        long zoneId = secondaryStorageHost.getDataCenterId();
 -        DataCenterVO zone = _dcDao.findById(zoneId);
 +	@Override
 +	public boolean templateIsDeleteable(VMTemplateHostVO templateHostRef) {
 +	    VMTemplateVO template = _tmpltDao.findByIdIncludingRemoved(templateHostRef.getTemplateId());
 +	    long templateId = template.getId();
 +	    HostVO secondaryStorageHost = _hostDao.findById(templateHostRef.getHostId());
 +	    long zoneId = secondaryStorageHost.getDataCenterId();
 +	    DataCenterVO zone = _dcDao.findById(zoneId);
  
- 	    // Check if there are VMs running in the template host ref's zone that use the template
+         // Check if there are VMs running in the template host ref's zone that
+         // use the template
 -        List<VMInstanceVO> nonExpungedVms = _vmInstanceDao.listNonExpungedByZoneAndTemplate(zoneId, templateId);
 +	    List<VMInstanceVO> nonExpungedVms = _vmInstanceDao.listNonExpungedByZoneAndTemplate(zoneId, templateId);
  
 -        if (!nonExpungedVms.isEmpty()) {
 +	    if (!nonExpungedVms.isEmpty()) {
- 	        s_logger.debug("Template " + template.getName() + " in zone " + zone.getName() + " is not deleteable because there are non-expunged VMs deployed from this template.");
+             s_logger.debug("Template " + template.getName() + " in zone " + zone.getName()
+                     + " is not deleteable because there are non-expunged VMs deployed from this template.");
 -            return false;
 -        }
 -        List<UserVmVO> userVmUsingIso = _userVmDao.listByIsoId(templateId);
 +	        return false;
 +	    }
 +	    List<UserVmVO> userVmUsingIso = _userVmDao.listByIsoId(templateId);
- 	    //check if there is any VM using this ISO.
+         // check if there is any VM using this ISO.
 -        if (!userVmUsingIso.isEmpty()) {
 +	    if (!userVmUsingIso.isEmpty()) {
- 	        s_logger.debug("ISO " + template.getName() + " in zone " + zone.getName() + " is not deleteable because it is attached to " + userVmUsingIso.size() + " VMs");
+             s_logger.debug("ISO " + template.getName() + " in zone " + zone.getName() + " is not deleteable because it is attached to "
+                     + userVmUsingIso.size() + " VMs");
 -            return false;
 -        }
 +	        return false;
 +	    }
- 	    // Check if there are any snapshots for the template in the template host ref's zone
+         // Check if there are any snapshots for the template in the template
+         // host ref's zone
 -        List<VolumeVO> volumes = _volumeDao.findByTemplateAndZone(templateId, zoneId);
 -        for (VolumeVO volume : volumes) {
 -            List<SnapshotVO> snapshots = _snapshotDao.listByVolumeIdVersion(volume.getId(), "2.1");
 -            if (!snapshots.isEmpty()) {
 +	    List<VolumeVO> volumes = _volumeDao.findByTemplateAndZone(templateId, zoneId);
 +	    for (VolumeVO volume : volumes) {
 +	        List<SnapshotVO> snapshots = _snapshotDao.listByVolumeIdVersion(volume.getId(), "2.1");
 +	        if (!snapshots.isEmpty()) {
- 	            s_logger.debug("Template " + template.getName() + " in zone " + zone.getName() + " is not deleteable because there are 2.1 snapshots using this template.");
+                 s_logger.debug("Template " + template.getName() + " in zone " + zone.getName()
+                         + " is not deleteable because there are 2.1 snapshots using this template.");
 -                return false;
 -            }
 -        }
 +	            return false;
 +	        }
 +	    }
  
 -        return true;
 -    }
 +	    return true;
 +	}
  
 -    @Override
 +	@Override
+     public boolean templateIsDeleteable(long templateId) {
+         List<UserVmJoinVO> userVmUsingIso = _userVmJoinDao.listActiveByIsoId(templateId);
+         // check if there is any Vm using this ISO. We only need to check the
+         // case where templateId is an ISO since
+         // VM can be launched from ISO in secondary storage, while template will
+         // always be copied to
+         // primary storage before deploying VM.
+         if (!userVmUsingIso.isEmpty()) {
+             s_logger.debug("ISO " + templateId + " is not deleteable because it is attached to " + userVmUsingIso.size() + " VMs");
+             return false;
+         }
+ 
+         return true;
+     }
+ 
+     @Override
      @ActionEvent(eventType = EventTypes.EVENT_ISO_DETACH, eventDescription = "detaching ISO", async = true)
 -    public boolean detachIso(long vmId) {
 -        Account caller = UserContext.current().getCaller();
 -        Long userId = UserContext.current().getCallerUserId();
 -
 +	public boolean detachIso(long vmId)  {
 +        Account caller = CallContext.current().getCallingAccount();
 +        Long userId = CallContext.current().getCallingUserId();
 +        
          // Verify input parameters
          UserVmVO vmInstanceCheck = _userVmDao.findById(vmId);
          if (vmInstanceCheck == null) {
-             throw new InvalidParameterValueException ("Unable to find a virtual machine with id " + vmId);
+             throw new InvalidParameterValueException("Unable to find a virtual machine with id " + vmId);
          }
 -
 +        
          UserVm userVM = _userVmDao.findById(vmId);
          if (userVM == null) {
              throw new InvalidParameterValueException("Please specify a valid VM.");
@@@ -1294,69 -914,93 +900,93 @@@
          if (isoId == null) {
              throw new InvalidParameterValueException("The specified VM has no ISO attached to it.");
          }
 -        UserContext.current().setEventDetails("Vm Id: " + vmId + " ISO Id: " + isoId);
 -
 +    	CallContext.current().setEventDetails("Vm Id: " +vmId+ " ISO Id: "+isoId);
 +        
          State vmState = userVM.getState();
          if (vmState != State.Running && vmState != State.Stopped) {
 -            throw new InvalidParameterValueException("Please specify a VM that is either Stopped or Running.");
 +        	throw new InvalidParameterValueException("Please specify a VM that is either Stopped or Running.");
          }
  
-         boolean result = attachISOToVM(vmId, userId, isoId, false); //attach=false => detach
-         if (result){
+         boolean result = attachISOToVM(vmId, userId, isoId, false); // attach=false
+                                                                     // => detach
+         if (result) {
 -            return result;
 +        	return result;
-         }else {
+         } else {
 -            throw new CloudRuntimeException("Failed to detach iso");
 +        	throw new CloudRuntimeException("Failed to detach iso");
-         }        
+         }
 -    }
 -
 -    @Override
 +	}
 +	
 +	@Override
      @ActionEvent(eventType = EventTypes.EVENT_ISO_ATTACH, eventDescription = "attaching ISO", async = true)
 -    public boolean attachIso(long isoId, long vmId) {
 -        Account caller = UserContext.current().getCaller();
 -        Long userId = UserContext.current().getCallerUserId();
 -
 -        // Verify input parameters
 -        UserVmVO vm = _userVmDao.findById(vmId);
 -        if (vm == null) {
 +	public boolean attachIso(long isoId, long vmId) {
 +        Account caller = CallContext.current().getCallingAccount();
 +        Long userId = CallContext.current().getCallingUserId();
 +        
 +    	// Verify input parameters
 +    	UserVmVO vm = _userVmDao.findById(vmId);
 +    	if (vm == null) {
              throw new InvalidParameterValueException("Unable to find a virtual machine with id " + vmId);
          }
 -
 -        VMTemplateVO iso = _tmpltDao.findById(isoId);
 -        if (iso == null || iso.getRemoved() != null) {
 +    	
 +    	VMTemplateVO iso = _tmpltDao.findById(isoId);
 +    	if (iso == null || iso.getRemoved() != null) {
              throw new InvalidParameterValueException("Unable to find an ISO with id " + isoId);
 -        }
 -
 +    	}
 +    	
-     	//check permissions
-     	//check if caller has access to VM and ISO 
-     	//and also check if the VM's owner has access to the ISO.
+         // check permissions
+         // check if caller has access to VM and ISO
+         // and also check if the VM's owner has access to the ISO.
 -
 -        _accountMgr.checkAccess(caller, null, false, iso, vm);
 -
 -        Account vmOwner = _accountDao.findById(vm.getAccountId());
 -        _accountMgr.checkAccess(vmOwner, null, false, iso, vm);
 -
 +    	
 +    	_accountMgr.checkAccess(caller, null, false, iso, vm);
 +    	
 +    	Account vmOwner = _accountDao.findById(vm.getAccountId());
 +    	_accountMgr.checkAccess(vmOwner, null, false, iso, vm);
 +    	
          State vmState = vm.getState();
          if (vmState != State.Running && vmState != State.Stopped) {
 -            throw new InvalidParameterValueException("Please specify a VM that is either Stopped or Running.");
 +        	throw new InvalidParameterValueException("Please specify a VM that is either Stopped or Running.");
          }
 -
 +        
-         if ("xen-pv-drv-iso".equals(iso.getDisplayText()) && vm.getHypervisorType() != Hypervisor.HypervisorType.XenServer){
+         if ("xen-pv-drv-iso".equals(iso.getDisplayText()) && vm.getHypervisorType() != Hypervisor.HypervisorType.XenServer) {
 -            throw new InvalidParameterValueException("Cannot attach Xenserver PV drivers to incompatible hypervisor " + vm.getHypervisorType());
 +        	throw new InvalidParameterValueException("Cannot attach Xenserver PV drivers to incompatible hypervisor " + vm.getHypervisorType());
          }
 -
 +        
-         if("vmware-tools.iso".equals(iso.getName()) && vm.getHypervisorType() != Hypervisor.HypervisorType.VMware) {
+         if ("vmware-tools.iso".equals(iso.getName()) && vm.getHypervisorType() != Hypervisor.HypervisorType.VMware) {
 -            throw new InvalidParameterValueException("Cannot attach VMware tools drivers to incompatible hypervisor " + vm.getHypervisorType());
 +        	throw new InvalidParameterValueException("Cannot attach VMware tools drivers to incompatible hypervisor " + vm.getHypervisorType());
          }
          boolean result = attachISOToVM(vmId, userId, isoId, true);
-         if (result){
+         if (result) {
 -            return result;
 +        	return result;
-         }else {
+         } else {
 -            throw new CloudRuntimeException("Failed to attach iso");
 +        	throw new CloudRuntimeException("Failed to attach iso");
          }
 -    }
 -
 +	}
 +	
+     // for ISO, we need to consider whether to copy to cache storage or not if it is not on NFS, since our hypervisor resource always assumes that they are in NFS
+     @Override
+     public TemplateInfo prepareIso(long isoId, long dcId){
 -        TemplateInfo tmplt = this._tmplFactory.getTemplate(isoId, DataStoreRole.Image, dcId);
++        TemplateInfo tmplt = _tmplFactory.getTemplate(isoId, DataStoreRole.Image, dcId);
+         if (tmplt == null || tmplt.getFormat() != ImageFormat.ISO ) {
+             s_logger.warn("ISO: " + isoId + " does not exist in vm_template table");
+             return null;
+         }
+ 
+         if (tmplt.getDataStore() != null && !(tmplt.getDataStore().getTO() instanceof NfsTO)) {
+             // if it is s3, need to download into cache storage first
+             Scope destScope = new ZoneScope(dcId);
+             TemplateInfo cacheData = (TemplateInfo) cacheMgr.createCacheObject(tmplt, destScope);
+             if (cacheData == null) {
+                 s_logger.error("Failed in copy iso from S3 to cache storage");
+                 return null;
+             }
+             return cacheData;
+         } else{
+             return tmplt;
+         }
+     }
+ 
      private boolean attachISOToVM(long vmId, long isoId, boolean attach) {
--        UserVmVO vm = this._userVmDao.findById(vmId);
++        UserVmVO vm = _userVmDao.findById(vmId);
  
          if (vm == null) {
              return false;
@@@ -1401,22 -1032,22 +1018,22 @@@
      }
  
      private boolean attachISOToVM(long vmId, long userId, long isoId, boolean attach) {
 -        UserVmVO vm = _userVmDao.findById(vmId);
 -        VMTemplateVO iso = _tmpltDao.findById(isoId);
 +    	UserVmVO vm = _userVmDao.findById(vmId);
 +    	VMTemplateVO iso = _tmpltDao.findById(isoId);
  
          boolean success = attachISOToVM(vmId, isoId, attach);
-         if ( success && attach) {
+         if (success && attach) {
 -            vm.setIsoId(iso.getId());
 +             vm.setIsoId(iso.getId());
              _userVmDao.update(vmId, vm);
-         } 
-         if ( success && !attach ) {
+         }
+         if (success && !attach) {
              vm.setIsoId(null);
              _userVmDao.update(vmId, vm);
-         }    
+         }
          return success;
      }
 -
 -    @Override
 +	
 +	@Override
      @ActionEvent(eventType = EventTypes.EVENT_TEMPLATE_DELETE, eventDescription = "deleting template", async = true)
      public boolean deleteTemplate(DeleteTemplateCmd cmd) {
          Long templateId = cmd.getId();
@@@ -1426,100 -1057,68 +1043,68 @@@
          if (template == null) {
              throw new InvalidParameterValueException("unable to find template with id " + templateId);
          }
 -
 +        
          _accountMgr.checkAccess(caller, AccessType.ModifyEntry, true, template);
 +    	
 +    	if (template.getFormat() == ImageFormat.ISO) {
 +    		throw new InvalidParameterValueException("Please specify a valid template.");
 +    	}
-         if (cmd.getZoneId() == null && _swiftMgr.isSwiftEnabled()) {
-             _swiftMgr.deleteTemplate(cmd);
-         }
-         if (cmd.getZoneId() == null && _s3Mgr.isS3Enabled()) {
-             _s3Mgr.deleteTemplate(cmd.getId(), caller.getAccountId());
-         }
  
 -        if (template.getFormat() == ImageFormat.ISO) {
 -            throw new InvalidParameterValueException("Please specify a valid template.");
 -        }
 -
 -        TemplateAdapter adapter = getAdapter(template.getHypervisorType());
 -        TemplateProfile profile = adapter.prepareDelete(cmd);
 +    	TemplateAdapter adapter = getAdapter(template.getHypervisorType());
 +    	TemplateProfile profile = adapter.prepareDelete(cmd);
-     	boolean result = adapter.delete(profile);
-     	
-     	if (result){
-             if (cmd.getZoneId() == null
-                     && (_swiftMgr.isSwiftEnabled() || _s3Mgr.isS3Enabled())) {
-                 List<VMTemplateZoneVO> templateZones = _tmpltZoneDao
-                         .listByZoneTemplate(null, templateId);
-                 if (templateZones != null) {
-                     for (VMTemplateZoneVO templateZone : templateZones) {
-                         _tmpltZoneDao.remove(templateZone.getId());
-                     }
-                 }
-             }
-     		return true;
-     	}else{
-     		throw new CloudRuntimeException("Failed to delete template");
-     	}
+         return adapter.delete(profile);
 -    }
 -
 -    @Override
 +	}
 +	
 +	@Override
      @ActionEvent(eventType = EventTypes.EVENT_ISO_DELETE, eventDescription = "deleting iso", async = true)
      public boolean deleteIso(DeleteIsoCmd cmd) {
          Long templateId = cmd.getId();
 -        Account caller = UserContext.current().getCaller();
 +        Account caller = CallContext.current().getCallingAccount();
          Long zoneId = cmd.getZoneId();
 -
 +        
-         VirtualMachineTemplate template = getTemplate(templateId);;
+         VirtualMachineTemplate template = getTemplate(templateId);
+         ;
          if (template == null) {
              throw new InvalidParameterValueException("unable to find iso with id " + templateId);
          }
 -
 +        
          _accountMgr.checkAccess(caller, AccessType.ModifyEntry, true, template);
 -
 -        if (template.getFormat() != ImageFormat.ISO) {
 -            throw new InvalidParameterValueException("Please specify a valid iso.");
 -        }
 +         	
 +    	if (template.getFormat() != ImageFormat.ISO) {
 +    		throw new InvalidParameterValueException("Please specify a valid iso.");
 +    	}
-         if (cmd.getZoneId() == null && _swiftMgr.isSwiftEnabled()) {
-             _swiftMgr.deleteIso(cmd);
-     	}
-

<TRUNCATED>