diff --git a/api/src/com/cloud/agent/api/ModifyStoragePoolAnswer.java b/api/src/com/cloud/agent/api/ModifyStoragePoolAnswer.java index df77985248f..ed7043a8ec4 100644 --- a/api/src/com/cloud/agent/api/ModifyStoragePoolAnswer.java +++ b/api/src/com/cloud/agent/api/ModifyStoragePoolAnswer.java @@ -18,16 +18,16 @@ package com.cloud.agent.api; import java.util.Map; -import com.cloud.storage.template.TemplateInfo; +import com.cloud.storage.template.TemplateProp; public class ModifyStoragePoolAnswer extends Answer { StoragePoolInfo poolInfo; - Map templateInfo; + Map templateInfo; protected ModifyStoragePoolAnswer() { } - public ModifyStoragePoolAnswer(ModifyStoragePoolCommand cmd, long capacityBytes, long availableBytes, Map tInfo) { + public ModifyStoragePoolAnswer(ModifyStoragePoolCommand cmd, long capacityBytes, long availableBytes, Map tInfo) { super(cmd); this.result = true; this.poolInfo = new StoragePoolInfo(null, @@ -46,11 +46,11 @@ public class ModifyStoragePoolAnswer extends Answer { } - public Map getTemplateInfo() { + public Map getTemplateInfo() { return templateInfo; } - public void setTemplateInfo(Map templateInfo) { + public void setTemplateInfo(Map templateInfo) { this.templateInfo = templateInfo; } diff --git a/api/src/com/cloud/agent/api/StartupStorageCommand.java b/api/src/com/cloud/agent/api/StartupStorageCommand.java index 3c3b058ce39..52ed3ffdff3 100755 --- a/api/src/com/cloud/agent/api/StartupStorageCommand.java +++ b/api/src/com/cloud/agent/api/StartupStorageCommand.java @@ -22,13 +22,13 @@ import java.util.Map; import com.cloud.host.Host; import com.cloud.storage.Storage; import com.cloud.storage.Storage.StoragePoolType; -import com.cloud.storage.template.TemplateInfo; +import com.cloud.storage.template.TemplateProp; public class StartupStorageCommand extends StartupCommand { String parent; - Map templateInfo; + Map templateInfo; long totalSize; StoragePoolInfo poolInfo; Storage.StorageResourceType resourceType; @@ -40,7 +40,7 @@ public class StartupStorageCommand extends StartupCommand { super(Host.Type.Storage); } - public StartupStorageCommand(String parent, StoragePoolType fsType, long totalSize, Map info) { + public StartupStorageCommand(String parent, StoragePoolType fsType, long totalSize, Map info) { super(Host.Type.Storage); this.parent = parent; this.totalSize = totalSize; @@ -50,7 +50,7 @@ public class StartupStorageCommand extends StartupCommand { } - public StartupStorageCommand(String parent, StoragePoolType fsType, Map templateInfo, StoragePoolInfo poolInfo) { + public StartupStorageCommand(String parent, StoragePoolType fsType, Map templateInfo, StoragePoolInfo poolInfo) { super(Host.Type.Storage); this.parent = parent; this.templateInfo = templateInfo; @@ -79,11 +79,11 @@ public class StartupStorageCommand extends StartupCommand { return totalSize; } - public Map getTemplateInfo() { + public Map getTemplateInfo() { return templateInfo; } - public void setTemplateInfo(Map templateInfo) { + public void setTemplateInfo(Map templateInfo) { this.templateInfo = templateInfo; } diff --git a/api/src/com/cloud/agent/api/storage/ListTemplateAnswer.java b/api/src/com/cloud/agent/api/storage/ListTemplateAnswer.java index a4e2e255001..4155a632384 100644 --- a/api/src/com/cloud/agent/api/storage/ListTemplateAnswer.java +++ b/api/src/com/cloud/agent/api/storage/ListTemplateAnswer.java @@ -19,27 +19,27 @@ package com.cloud.agent.api.storage; import java.util.Map; import com.cloud.agent.api.Answer; -import com.cloud.storage.template.TemplateInfo; +import com.cloud.storage.template.TemplateProp; public class ListTemplateAnswer extends Answer { private String secUrl; - private Map templateInfos; + private Map templateInfos; public ListTemplateAnswer() { } - public ListTemplateAnswer(String secUrl, Map templateInfos) { + public ListTemplateAnswer(String secUrl, Map templateInfos) { super(null, true, "success"); this.setSecUrl(secUrl); this.templateInfos = templateInfos; } - public Map getTemplateInfo() { + public Map getTemplateInfo() { return templateInfos; } - public void setTemplateInfo(Map templateInfos) { + public void setTemplateInfo(Map templateInfos) { this.templateInfos = templateInfos; } diff --git a/api/src/com/cloud/agent/api/storage/ListVolumeAnswer.java b/api/src/com/cloud/agent/api/storage/ListVolumeAnswer.java index 6bbb2e82c33..31ea09b7d7c 100755 --- a/api/src/com/cloud/agent/api/storage/ListVolumeAnswer.java +++ b/api/src/com/cloud/agent/api/storage/ListVolumeAnswer.java @@ -19,27 +19,27 @@ package com.cloud.agent.api.storage; import java.util.Map; import com.cloud.agent.api.Answer; -import com.cloud.storage.template.TemplateInfo; +import com.cloud.storage.template.TemplateProp; public class ListVolumeAnswer extends Answer { private String secUrl; - private Map templateInfos; + private Map templateInfos; public ListVolumeAnswer() { } - public ListVolumeAnswer(String secUrl, Map templateInfos) { + public ListVolumeAnswer(String secUrl, Map templateInfos) { super(null, true, "success"); this.setSecUrl(secUrl); this.templateInfos = templateInfos; } - public Map getTemplateInfo() { + public Map getTemplateInfo() { return templateInfos; } - public void setTemplateInfo(Map templateInfos) { + public void setTemplateInfo(Map templateInfos) { this.templateInfos = templateInfos; } diff --git a/api/src/com/cloud/storage/template/TemplateInfo.java b/api/src/com/cloud/storage/template/TemplateProp.java similarity index 91% rename from api/src/com/cloud/storage/template/TemplateInfo.java rename to api/src/com/cloud/storage/template/TemplateProp.java index 6559d73b18d..0a2efc12e67 100644 --- a/api/src/com/cloud/storage/template/TemplateInfo.java +++ b/api/src/com/cloud/storage/template/TemplateProp.java @@ -16,7 +16,7 @@ // under the License. package com.cloud.storage.template; -public class TemplateInfo { +public class TemplateProp { String templateName; String installPath; long size; @@ -25,11 +25,11 @@ public class TemplateInfo { boolean isPublic; boolean isCorrupted; - protected TemplateInfo() { + protected TemplateProp() { } - public TemplateInfo(String templateName, String installPath, long size, long physicalSize, boolean isPublic, boolean isCorrupted) { + public TemplateProp(String templateName, String installPath, long size, long physicalSize, boolean isPublic, boolean isCorrupted) { this.templateName = templateName; this.installPath = installPath; this.size = size; @@ -38,7 +38,7 @@ public class TemplateInfo { this.isCorrupted = isCorrupted; } - public TemplateInfo(String templateName, String installPath, boolean isPublic, boolean isCorrupted) { + public TemplateProp(String templateName, String installPath, boolean isPublic, boolean isCorrupted) { this(templateName, installPath, 0, 0, isPublic, isCorrupted); } diff --git a/api/src/com/cloud/template/TemplateService.java b/api/src/com/cloud/template/TemplateApiService.java similarity index 98% rename from api/src/com/cloud/template/TemplateService.java rename to api/src/com/cloud/template/TemplateApiService.java index 7e831fb0055..50373fef651 100755 --- a/api/src/com/cloud/template/TemplateService.java +++ b/api/src/com/cloud/template/TemplateApiService.java @@ -36,7 +36,7 @@ import com.cloud.exception.StorageUnavailableException; import com.cloud.user.Account; import com.cloud.utils.exception.CloudRuntimeException; -public interface TemplateService { +public interface TemplateApiService { VirtualMachineTemplate registerTemplate(RegisterTemplateCmd cmd) throws URISyntaxException, ResourceAllocationException; diff --git a/api/src/org/apache/cloudstack/api/BaseCmd.java b/api/src/org/apache/cloudstack/api/BaseCmd.java index 78a2af36aa2..b845053e470 100644 --- a/api/src/org/apache/cloudstack/api/BaseCmd.java +++ b/api/src/org/apache/cloudstack/api/BaseCmd.java @@ -65,7 +65,7 @@ import com.cloud.storage.DataStoreProviderApiService; import com.cloud.storage.StorageService; import com.cloud.storage.VolumeApiService; import com.cloud.storage.snapshot.SnapshotService; -import com.cloud.template.TemplateService; +import com.cloud.template.TemplateApiService; import com.cloud.user.Account; import com.cloud.user.AccountService; import com.cloud.user.DomainService; @@ -106,7 +106,7 @@ public abstract class BaseCmd { @Inject public VolumeApiService _volumeService; @Inject public ResourceService _resourceService; @Inject public NetworkService _networkService; - @Inject public TemplateService _templateService; + @Inject public TemplateApiService _templateService; @Inject public SecurityGroupService _securityGroupService; @Inject public SnapshotService _snapshotService; @Inject public ConsoleProxyService _consoleProxyService; diff --git a/client/tomcatconf/applicationContext.xml.in b/client/tomcatconf/applicationContext.xml.in index 206afd3c8f3..7ad3bb50f9c 100644 --- a/client/tomcatconf/applicationContext.xml.in +++ b/client/tomcatconf/applicationContext.xml.in @@ -744,7 +744,7 @@ - + diff --git a/core/src/com/cloud/hypervisor/hyperv/resource/HypervResource.java b/core/src/com/cloud/hypervisor/hyperv/resource/HypervResource.java index 0f9b3dd9c6b..725f0cc1ae2 100755 --- a/core/src/com/cloud/hypervisor/hyperv/resource/HypervResource.java +++ b/core/src/com/cloud/hypervisor/hyperv/resource/HypervResource.java @@ -105,7 +105,7 @@ import com.cloud.resource.ServerResource; import com.cloud.resource.ServerResourceBase; import com.cloud.serializer.GsonHelper; import com.cloud.storage.Volume; -import com.cloud.storage.template.TemplateInfo; +import com.cloud.storage.template.TemplateProp; import com.cloud.utils.Pair; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.DiskProfile; @@ -765,7 +765,7 @@ public class HypervResource extends ServerResourceBase implements ServerResource try { StorageFilerTO pool = cmd.getPool(); s_logger.info("Primary storage pool details: " + pool.getHost() + " " + pool.getPath()); - Map tInfo = new HashMap(); + Map tInfo = new HashMap(); // FIXME: get the actual storage capacity and storage stats of CSV volume // by running powershell cmdlet. This hardcoding just for prototype. ModifyStoragePoolAnswer answer = new ModifyStoragePoolAnswer(cmd, diff --git a/core/src/com/cloud/storage/resource/CifsSecondaryStorageResource.java b/core/src/com/cloud/storage/resource/CifsSecondaryStorageResource.java index 285005a1c3a..435e0f713dc 100755 --- a/core/src/com/cloud/storage/resource/CifsSecondaryStorageResource.java +++ b/core/src/com/cloud/storage/resource/CifsSecondaryStorageResource.java @@ -60,7 +60,7 @@ import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.StorageLayer; import com.cloud.storage.template.DownloadManager; import com.cloud.storage.template.DownloadManagerImpl; -import com.cloud.storage.template.TemplateInfo; +import com.cloud.storage.template.TemplateProp; import com.cloud.storage.template.UploadManager; import com.cloud.storage.template.UploadManagerImpl; import com.cloud.utils.NumbersUtil; @@ -650,7 +650,7 @@ public class CifsSecondaryStorageResource extends ServerResourceBase implements return null; }*/ - final StartupStorageCommand cmd = new StartupStorageCommand(_parent, StoragePoolType.NetworkFilesystem, getTotalSize(), new HashMap()); + final StartupStorageCommand cmd = new StartupStorageCommand(_parent, StoragePoolType.NetworkFilesystem, getTotalSize(), new HashMap()); cmd.setResourceType(Storage.StorageResourceType.SECONDARY_STORAGE); cmd.setIqn(null); diff --git a/core/src/com/cloud/storage/resource/LocalSecondaryStorageResource.java b/core/src/com/cloud/storage/resource/LocalSecondaryStorageResource.java index c638c5d874e..89d0fe1836e 100644 --- a/core/src/com/cloud/storage/resource/LocalSecondaryStorageResource.java +++ b/core/src/com/cloud/storage/resource/LocalSecondaryStorageResource.java @@ -48,7 +48,7 @@ import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.StorageLayer; import com.cloud.storage.template.DownloadManager; import com.cloud.storage.template.DownloadManagerImpl; -import com.cloud.storage.template.TemplateInfo; +import com.cloud.storage.template.TemplateProp; import com.cloud.utils.component.ComponentContext; public class LocalSecondaryStorageResource extends ServerResourceBase implements SecondaryStorageResource { @@ -109,7 +109,7 @@ public class LocalSecondaryStorageResource extends ServerResourceBase implements private Answer execute(ListTemplateCommand cmd) { String root = getRootDir(); - Map templateInfos = _dlMgr.gatherTemplateInfo(root); + Map templateInfos = _dlMgr.gatherTemplateInfo(root); return new ListTemplateAnswer(cmd.getSecUrl(), templateInfos); } diff --git a/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java b/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java index e65cbe1312e..a8788c66b64 100755 --- a/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java +++ b/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java @@ -100,7 +100,7 @@ import com.cloud.storage.StorageLayer; import com.cloud.storage.template.DownloadManager; import com.cloud.storage.template.DownloadManagerImpl; import com.cloud.storage.template.DownloadManagerImpl.ZfsPathParser; -import com.cloud.storage.template.TemplateInfo; +import com.cloud.storage.template.TemplateProp; import com.cloud.storage.template.TemplateLocation; import com.cloud.storage.template.UploadManager; import com.cloud.storage.template.UploadManagerImpl; @@ -1073,12 +1073,12 @@ SecondaryStorageResource { } } - Map swiftListTemplate(SwiftTO swift) { + Map swiftListTemplate(SwiftTO swift) { String[] containers = swiftList(swift, "", ""); if (containers == null) { return null; } - Map tmpltInfos = new HashMap(); + Map tmpltInfos = new HashMap(); for( String container : containers) { if ( container.startsWith("T-")) { String ldir = _tmpltDir + "/" + UUID.randomUUID().toString(); @@ -1095,7 +1095,7 @@ SecondaryStorageResource { s_logger.warn("Unable to load template location " + ldir + " due to " + e.toString(), e); continue; } - TemplateInfo tInfo = loc.getTemplateInfo(); + TemplateProp tInfo = loc.getTemplateInfo(); tInfo.setInstallPath(container); tmpltInfos.put(tInfo.getTemplateName(), tInfo); loc.purge(); @@ -1111,11 +1111,11 @@ SecondaryStorageResource { return new Answer(cmd, true, null); } if (cmd.getSwift() != null) { - Map templateInfos = swiftListTemplate(cmd.getSwift()); + Map templateInfos = swiftListTemplate(cmd.getSwift()); return new ListTemplateAnswer(cmd.getSwift().toString(), templateInfos); } else { String root = getRootDir(cmd.getSecUrl()); - Map templateInfos = _dlMgr.gatherTemplateInfo(root); + Map templateInfos = _dlMgr.gatherTemplateInfo(root); return new ListTemplateAnswer(cmd.getSecUrl(), templateInfos); } } @@ -1126,7 +1126,7 @@ SecondaryStorageResource { } String root = getRootDir(cmd.getSecUrl()); - Map templateInfos = _dlMgr.gatherVolumeInfo(root); + Map templateInfos = _dlMgr.gatherVolumeInfo(root); return new ListVolumeAnswer(cmd.getSecUrl(), templateInfos); } diff --git a/core/src/com/cloud/storage/template/DownloadManager.java b/core/src/com/cloud/storage/template/DownloadManager.java index f4f8a0f17fa..82f4153f6e2 100644 --- a/core/src/com/cloud/storage/template/DownloadManager.java +++ b/core/src/com/cloud/storage/template/DownloadManager.java @@ -91,13 +91,13 @@ public interface DownloadManager extends Manager { /** * @return list of template info for installed templates */ - public Map gatherTemplateInfo(String templateDir); + public Map gatherTemplateInfo(String templateDir); /** /** * @return list of volume info for installed volumes */ - public Map gatherVolumeInfo(String volumeDir); + public Map gatherVolumeInfo(String volumeDir); } \ No newline at end of file diff --git a/core/src/com/cloud/storage/template/DownloadManagerImpl.java b/core/src/com/cloud/storage/template/DownloadManagerImpl.java index 22e78a081c1..db264c17bb1 100755 --- a/core/src/com/cloud/storage/template/DownloadManagerImpl.java +++ b/core/src/com/cloud/storage/template/DownloadManagerImpl.java @@ -717,8 +717,8 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager } @Override - public Map gatherTemplateInfo(String rootDir) { - Map result = new HashMap(); + public Map gatherTemplateInfo(String rootDir) { + Map result = new HashMap(); String templateDir = rootDir + File.separator + _templateDir; if (! _storage.exists(templateDir)) { @@ -741,7 +741,7 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager continue; } - TemplateInfo tInfo = loc.getTemplateInfo(); + TemplateProp tInfo = loc.getTemplateInfo(); if ((tInfo.size == tInfo.physicalSize) && (tInfo.installPath.endsWith(ImageFormat.OVA.getFileExtension()))) { try { @@ -774,8 +774,8 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager } @Override - public Map gatherVolumeInfo(String rootDir) { - Map result = new HashMap(); + public Map gatherVolumeInfo(String rootDir) { + Map result = new HashMap(); String volumeDir = rootDir + File.separator + _volumeDir; if (! _storage.exists(volumeDir)) { @@ -798,7 +798,7 @@ public class DownloadManagerImpl extends ManagerBase implements DownloadManager continue; } - TemplateInfo vInfo = loc.getTemplateInfo(); + TemplateProp vInfo = loc.getTemplateInfo(); if ((vInfo.size == vInfo.physicalSize) && (vInfo.installPath.endsWith(ImageFormat.OVA.getFileExtension()))) { try { diff --git a/core/src/com/cloud/storage/template/TemplateLocation.java b/core/src/com/cloud/storage/template/TemplateLocation.java index 58d023a4907..515b1f2343f 100644 --- a/core/src/com/cloud/storage/template/TemplateLocation.java +++ b/core/src/com/cloud/storage/template/TemplateLocation.java @@ -156,8 +156,8 @@ public class TemplateLocation { return true; } - public TemplateInfo getTemplateInfo() { - TemplateInfo tmplInfo = new TemplateInfo(); + public TemplateProp getTemplateInfo() { + TemplateProp tmplInfo = new TemplateProp(); tmplInfo.id = Long.parseLong(_props.getProperty("id")); tmplInfo.installPath = _templatePath + File.separator + _props.getProperty("filename"); if (_resourceType == ResourceType.VOLUME){ diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ImageService.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateService.java similarity index 86% rename from engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ImageService.java rename to engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateService.java index 119f3b1d32f..6bb58e0d4d6 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/ImageService.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateService.java @@ -20,10 +20,16 @@ package org.apache.cloudstack.engine.subsystem.api.storage; import org.apache.cloudstack.framework.async.AsyncCallFuture; -public interface ImageService { + + +import com.cloud.hypervisor.Hypervisor.HypervisorType; + +public interface TemplateService { AsyncCallFuture createTemplateAsync(TemplateInfo template, DataStore store); AsyncCallFuture createTemplateFromSnapshotAsync(SnapshotInfo snapshot, TemplateInfo template, DataStore store); AsyncCallFuture createTemplateFromVolumeAsync(VolumeInfo volume, TemplateInfo template, DataStore store); AsyncCallFuture deleteTemplateAsync(TemplateInfo template); - + + void handleSysTemplateDownload(HypervisorType hostHyper, Long dcId); + void handleTemplateSync(DataStore store); } diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeService.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeService.java index 102c47174b1..7175524c87e 100644 --- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeService.java +++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeService.java @@ -25,13 +25,13 @@ import com.cloud.exception.ConcurrentOperationException; public interface VolumeService { - + public class VolumeApiResult extends CommandResult { private final VolumeInfo volume; public VolumeApiResult(VolumeInfo volume) { this.volume = volume; } - + public VolumeInfo getVolume() { return this.volume; } @@ -39,16 +39,16 @@ public interface VolumeService { /** * Creates the volume based on the given criteria - * + * * @param cmd - * + * * @return the volume object */ AsyncCallFuture createVolumeAsync(VolumeInfo volume, DataStore store); /** * Delete volume - * + * * @param volumeId * @return * @throws ConcurrentOperationException @@ -56,12 +56,12 @@ public interface VolumeService { AsyncCallFuture expungeVolumeAsync(VolumeInfo volume); /** - * + * */ boolean cloneVolume(long volumeId, long baseVolId); /** - * + * */ AsyncCallFuture createVolumeFromSnapshot(VolumeInfo volume, DataStore store, SnapshotInfo snapshot); @@ -74,7 +74,9 @@ public interface VolumeService { boolean destroyVolume(long volumeId) throws ConcurrentOperationException; AsyncCallFuture registerVolume(VolumeInfo volume, DataStore store); - + AsyncCallFuture resize(VolumeInfo volume); + void handleVolumeSync(DataStore store); + } diff --git a/engine/api/src/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreDao.java b/engine/api/src/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreDao.java index 91ffdaa01c2..271ff41f08e 100644 --- a/engine/api/src/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreDao.java +++ b/engine/api/src/org/apache/cloudstack/storage/datastore/db/SnapshotDataStoreDao.java @@ -30,7 +30,5 @@ public interface SnapshotDataStoreDao extends GenericDao listByStoreId(long id); - public List listLiveByStoreId(long id); - public void deletePrimaryRecordsForStore(long id); } diff --git a/engine/api/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreDao.java b/engine/api/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreDao.java index 29c7859960b..f1fcdcc65d9 100644 --- a/engine/api/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreDao.java +++ b/engine/api/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreDao.java @@ -23,18 +23,20 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore; import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; +import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; import com.cloud.utils.db.GenericDao; import com.cloud.utils.fsm.StateDao; public interface TemplateDataStoreDao extends GenericDao, StateDao { - public List listByStoreId(long id); - public List listLiveByStoreId(long id); + public List listByStoreId(long id); public void deletePrimaryRecordsForStore(long id); List listByTemplateStoreStatus(long templateId, long storeId, State... states); + List listByTemplateStoreDownloadStatus(long templateId, long storeId, Status... status); + TemplateDataStoreVO findByStoreTemplate(long storeId, long templateId); } diff --git a/engine/api/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreVO.java b/engine/api/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreVO.java index 312fd119adc..d7c8443d71c 100755 --- a/engine/api/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreVO.java +++ b/engine/api/src/org/apache/cloudstack/storage/datastore/db/TemplateDataStoreVO.java @@ -291,6 +291,12 @@ public class TemplateDataStoreVO implements StateObject, public List listByStoreId(long id); - public List listLiveByStoreId(long id); - public void deletePrimaryRecordsForStore(long id); + + public VolumeDataStoreVO findByVolumeId(long volumeId); + + public VolumeDataStoreVO findByStoreVolume(long storeId, long volumeId); } diff --git a/engine/api/src/org/apache/cloudstack/storage/datastore/db/VolumeDataStoreVO.java b/engine/api/src/org/apache/cloudstack/storage/datastore/db/VolumeDataStoreVO.java index 185b12b52f1..a7134ea374c 100755 --- a/engine/api/src/org/apache/cloudstack/storage/datastore/db/VolumeDataStoreVO.java +++ b/engine/api/src/org/apache/cloudstack/storage/datastore/db/VolumeDataStoreVO.java @@ -203,14 +203,14 @@ public class VolumeDataStoreVO implements StateObject extends AsyncRpcConext { - final TemplateInfo srcTemplate; - final DataStore store; - final AsyncCallFuture future; - final DataObject templateOnStore; - - public CreateTemplateContext(AsyncCompletionCallback callback, TemplateInfo srcTemplate, - AsyncCallFuture future, - DataStore store, - DataObject templateOnStore - ) { - super(callback); - this.srcTemplate = srcTemplate; - this.future = future; - this.store = store; - this.templateOnStore = templateOnStore; - } - } - - @Override - public AsyncCallFuture createTemplateAsync( - TemplateInfo template, DataStore store) { - TemplateObject to = (TemplateObject) template; - AsyncCallFuture future = new AsyncCallFuture(); - // persist template_store_ref entry - DataObject templateOnStore = store.create(template); - // update template_store_ref state - templateOnStore.processEvent(ObjectInDataStoreStateMachine.Event.CreateOnlyRequested); - - CreateTemplateContext context = new CreateTemplateContext(null, - template, - future, - store, - templateOnStore - ); - AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); - caller.setCallback(caller.getTarget().createTemplateCallback(null, null)).setContext(context); - store.getDriver().createAsync(templateOnStore, caller); - return future; - } - - protected Void createTemplateCallback(AsyncCallbackDispatcher callback, - CreateTemplateContext context) { - TemplateObject template = (TemplateObject)context.srcTemplate; - AsyncCallFuture future = context.future; - CommandResult result = new CommandResult(); - DataObject templateOnStore = context.templateOnStore; - CreateCmdResult callbackResult = callback.getResult(); - if (callbackResult.isFailed()) { - try { - templateOnStore.processEvent(ObjectInDataStoreStateMachine.Event.OperationFailed); - template.stateTransit(TemplateEvent.OperationFailed); - } catch (NoTransitionException e) { - s_logger.debug("Failed to update template state", e); - } - result.setResult(callbackResult.getResult()); - future.complete(result); - return null; - } - - try { - templateOnStore.processEvent(ObjectInDataStoreStateMachine.Event.OperationSuccessed); - template.stateTransit(TemplateEvent.OperationSucceeded); - } catch (NoTransitionException e) { - s_logger.debug("Failed to transit state", e); - result.setResult(e.toString()); - future.complete(result); - return null; - } - - future.complete(result); - return null; - } - - @Override - public AsyncCallFuture deleteTemplateAsync( - TemplateInfo template) { - // TODO Auto-generated method stub - return null; - } - - @Override - public AsyncCallFuture createTemplateFromSnapshotAsync( - SnapshotInfo snapshot, TemplateInfo template, DataStore store) { - // TODO Auto-generated method stub - return null; - } - - @Override - public AsyncCallFuture createTemplateFromVolumeAsync( - VolumeInfo volume, TemplateInfo template, DataStore store) { - // TODO Auto-generated method stub - return null; - } -} diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateServiceImpl.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateServiceImpl.java new file mode 100644 index 00000000000..3dcb86b0939 --- /dev/null +++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/TemplateServiceImpl.java @@ -0,0 +1,481 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cloudstack.storage.image; + +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import javax.inject.Inject; + +import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult; +import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult; +import org.apache.cloudstack.engine.subsystem.api.storage.DataObject; +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.TemplateService; +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; +import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateEvent; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; +import com.cloud.storage.template.TemplateProp; +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.async.AsyncCallbackDispatcher; +import org.apache.cloudstack.framework.async.AsyncCompletionCallback; +import org.apache.cloudstack.framework.async.AsyncRpcConext; +import org.apache.cloudstack.storage.datastore.DataObjectManager; +import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager; +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.image.store.TemplateObject; +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import com.cloud.agent.AgentManager; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.storage.DeleteTemplateCommand; +import com.cloud.agent.api.storage.ListTemplateAnswer; +import com.cloud.agent.api.storage.ListTemplateCommand; +import com.cloud.alert.AlertManager; +import com.cloud.dc.DataCenterVO; +import com.cloud.dc.dao.ClusterDao; +import com.cloud.dc.dao.DataCenterDao; +import com.cloud.exception.AgentUnavailableException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.host.HostVO; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.storage.VMTemplateVO; +import com.cloud.storage.VMTemplateZoneVO; +import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; +import com.cloud.storage.dao.VMTemplateDao; +import com.cloud.storage.dao.VMTemplateZoneDao; +import com.cloud.storage.dao.VolumeDao; +import com.cloud.storage.download.DownloadMonitor; +import com.cloud.storage.secondary.SecondaryStorageVmManager; +import com.cloud.user.AccountManager; +import com.cloud.user.ResourceLimitService; +import com.cloud.utils.UriUtils; +import com.cloud.utils.fsm.NoTransitionException; +import com.cloud.vm.UserVmVO; +import com.cloud.vm.dao.UserVmDao; + +@Component +public class TemplateServiceImpl implements TemplateService { + private static final Logger s_logger = Logger.getLogger(TemplateServiceImpl.class); + @Inject + ObjectInDataStoreManager _objectInDataStoreMgr; + @Inject + DataObjectManager _dataObjectMgr; + @Inject + DataStoreManager _storeMgr; + @Inject + ResourceLimitService _resourceLimitMgr; + @Inject + AccountManager _accountMgr; + @Inject + AlertManager _alertMgr; + @Inject + VMTemplateDao _templateDao; + @Inject + TemplateDataStoreDao _vmTemplateStoreDao; + @Inject + VolumeDataStoreDao _volumeStoreDao; + @Inject + DownloadMonitor _dlMonitor; + @Inject + AgentManager _agentMgr; + @Inject + SecondaryStorageVmManager _ssvmMgr; + @Inject + DataCenterDao _dcDao = null; + @Inject + VMTemplateZoneDao _vmTemplateZoneDao; + @Inject + ClusterDao _clusterDao; + @Inject + UserVmDao _userVmDao; + @Inject + VolumeDao _volumeDao; + + + class CreateTemplateContext extends AsyncRpcConext { + final TemplateInfo srcTemplate; + final DataStore store; + final AsyncCallFuture future; + final DataObject templateOnStore; + + public CreateTemplateContext(AsyncCompletionCallback callback, TemplateInfo srcTemplate, + AsyncCallFuture future, + DataStore store, + DataObject templateOnStore + ) { + super(callback); + this.srcTemplate = srcTemplate; + this.future = future; + this.store = store; + this.templateOnStore = templateOnStore; + } + } + + @Override + public AsyncCallFuture createTemplateAsync( + TemplateInfo template, DataStore store) { + TemplateObject to = (TemplateObject) template; + AsyncCallFuture future = new AsyncCallFuture(); + // persist template_store_ref entry + DataObject templateOnStore = store.create(template); + // update template_store_ref state + templateOnStore.processEvent(ObjectInDataStoreStateMachine.Event.CreateOnlyRequested); + + CreateTemplateContext context = new CreateTemplateContext(null, + template, + future, + store, + templateOnStore + ); + AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); + caller.setCallback(caller.getTarget().createTemplateCallback(null, null)).setContext(context); + store.getDriver().createAsync(templateOnStore, caller); + return future; + } + + + @Override + public void handleSysTemplateDownload(HypervisorType hostHyper, Long dcId) { + Set toBeDownloaded = new HashSet(); + List ssHosts = this._storeMgr.getImageStoresByScope(new ZoneScope(dcId)); + if (ssHosts == null || ssHosts.isEmpty()){ + return; + } + + /*Download all the templates in zone with the same hypervisortype*/ + for ( DataStore ssHost : ssHosts) { + List rtngTmplts = _templateDao.listAllSystemVMTemplates(); + List defaultBuiltin = _templateDao.listDefaultBuiltinTemplates(); + + + for (VMTemplateVO rtngTmplt : rtngTmplts) { + if (rtngTmplt.getHypervisorType() == hostHyper) { + toBeDownloaded.add(rtngTmplt); + } + } + + for (VMTemplateVO builtinTmplt : defaultBuiltin) { + if (builtinTmplt.getHypervisorType() == hostHyper) { + toBeDownloaded.add(builtinTmplt); + } + } + + for (VMTemplateVO template: toBeDownloaded) { + TemplateDataStoreVO tmpltHost = _vmTemplateStoreDao.findByStoreTemplate(ssHost.getId(), template.getId()); + if (tmpltHost == null || tmpltHost.getState() != ObjectInDataStoreStateMachine.State.Ready) { + _dlMonitor.downloadTemplateToStorage(template, ssHost, null); + } + } + } + } + + + + + + @Override + public void handleTemplateSync(DataStore store) { + if (store == null) { + s_logger.warn("Huh? image store is null"); + return; + } + long storeId = store.getId(); + Long zoneId = store.getScope().getScopeId(); + + Map templateInfos = listTemplate(store); + if (templateInfos == null) { + return; + } + + Set toBeDownloaded = new HashSet(); + List allTemplates = null; + if (zoneId == null){ + // region wide store + allTemplates = _templateDao.listAll(); + } + else{ + // zone wide store + allTemplates = _templateDao.listAllInZone(zoneId); + } + List rtngTmplts = _templateDao.listAllSystemVMTemplates(); + List defaultBuiltin = _templateDao.listDefaultBuiltinTemplates(); + + if (rtngTmplts != null) { + for (VMTemplateVO rtngTmplt : rtngTmplts) { + if (!allTemplates.contains(rtngTmplt)) { + allTemplates.add(rtngTmplt); + } + } + } + + if (defaultBuiltin != null) { + for (VMTemplateVO builtinTmplt : defaultBuiltin) { + if (!allTemplates.contains(builtinTmplt)) { + allTemplates.add(builtinTmplt); + } + } + } + + toBeDownloaded.addAll(allTemplates); + + for (VMTemplateVO tmplt : allTemplates) { + String uniqueName = tmplt.getUniqueName(); + TemplateDataStoreVO tmpltStore = _vmTemplateStoreDao.findByStoreTemplate(storeId, tmplt.getId()); + if (templateInfos.containsKey(uniqueName)) { + TemplateProp tmpltInfo = templateInfos.remove(uniqueName); + toBeDownloaded.remove(tmplt); + if (tmpltStore != null) { + s_logger.info("Template Sync found " + uniqueName + " already in the template host table"); + if (tmpltStore.getDownloadState() != Status.DOWNLOADED) { + tmpltStore.setErrorString(""); + } + if (tmpltInfo.isCorrupted()) { + tmpltStore.setDownloadState(Status.DOWNLOAD_ERROR); + String msg = "Template " + tmplt.getName() + ":" + tmplt.getId() + " is corrupted on secondary storage " + tmpltStore.getId(); + tmpltStore.setErrorString(msg); + s_logger.info("msg"); + if (tmplt.getUrl() == null) { + msg = "Private Template (" + tmplt + ") with install path " + tmpltInfo.getInstallPath() + "is corrupted, please check in image store: " + tmpltStore.getDataStoreId(); + s_logger.warn(msg); + } else { + toBeDownloaded.add(tmplt); + } + + } else { + tmpltStore.setDownloadPercent(100); + tmpltStore.setDownloadState(Status.DOWNLOADED); + tmpltStore.setInstallPath(tmpltInfo.getInstallPath()); + tmpltStore.setSize(tmpltInfo.getSize()); + tmpltStore.setPhysicalSize(tmpltInfo.getPhysicalSize()); + tmpltStore.setLastUpdated(new Date()); + + if (tmpltInfo.getSize() > 0) { + long accountId = tmplt.getAccountId(); + try { + _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(accountId), + com.cloud.configuration.Resource.ResourceType.secondary_storage, + tmpltInfo.getSize() - UriUtils.getRemoteSize(tmplt.getUrl())); + } catch (ResourceAllocationException e) { + s_logger.warn(e.getMessage()); + _alertMgr.sendAlert(_alertMgr.ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED, zoneId, + null, e.getMessage(), e.getMessage()); + } finally { + _resourceLimitMgr.recalculateResourceCount(accountId, _accountMgr.getAccount(accountId).getDomainId(), + com.cloud.configuration.Resource.ResourceType.secondary_storage.getOrdinal()); + } + } + } + _vmTemplateStoreDao.update(tmpltStore.getId(), tmpltStore); + } else { + tmpltStore = new TemplateDataStoreVO(storeId, tmplt.getId(), new Date(), 100, Status.DOWNLOADED, null, null, null, tmpltInfo.getInstallPath(), tmplt.getUrl()); + tmpltStore.setSize(tmpltInfo.getSize()); + tmpltStore.setPhysicalSize(tmpltInfo.getPhysicalSize()); + _vmTemplateStoreDao.persist(tmpltStore); + this.associateTemplateToZone(tmplt.getId(), zoneId); + } + + continue; + } + if (tmpltStore != null && tmpltStore.getDownloadState() != Status.DOWNLOADED) { + s_logger.info("Template Sync did not find " + uniqueName + " ready on server " + storeId + ", will request download to start/resume shortly"); + + } else if (tmpltStore == null) { + s_logger.info("Template Sync did not find " + uniqueName + " on the server " + storeId + ", will request download shortly"); + TemplateDataStoreVO templtStore = new TemplateDataStoreVO(storeId, tmplt.getId(), new Date(), 0, Status.NOT_DOWNLOADED, null, null, null, null, tmplt.getUrl()); + _vmTemplateStoreDao.persist(templtStore); + this.associateTemplateToZone(tmplt.getId(), zoneId); + } + + } + + if (toBeDownloaded.size() > 0) { + /* Only download templates whose hypervirsor type is in the zone */ + List availHypers = _clusterDao.getAvailableHypervisorInZone(zoneId); + if (availHypers.isEmpty()) { + /* + * This is for cloudzone, local secondary storage resource + * started before cluster created + */ + availHypers.add(HypervisorType.KVM); + } + /* Baremetal need not to download any template */ + availHypers.remove(HypervisorType.BareMetal); + availHypers.add(HypervisorType.None); // bug 9809: resume ISO + // download. + for (VMTemplateVO tmplt : toBeDownloaded) { + if (tmplt.getUrl() == null) { // If url is null we can't + // initiate the download + continue; + } + // check if there is a record for this template in this store + TemplateDataStoreVO tmpltHost = _vmTemplateStoreDao.findByStoreTemplate(storeId, tmplt.getId()); + + // if this is private template, and there is no record for this + // template in this store, skip + if (!tmplt.isPublicTemplate() && !tmplt.isFeatured()) { + if (tmpltHost == null) { + continue; + } + } + if (availHypers.contains(tmplt.getHypervisorType())) { + if (tmpltHost != null ) { + continue; + } + s_logger.debug("Template " + tmplt.getName() + " needs to be downloaded to " + store.getName()); + //TODO: we should pass a callback here + _dlMonitor.downloadTemplateToStorage(tmplt, store, null); + } + } + } + + for (String uniqueName : templateInfos.keySet()) { + TemplateProp tInfo = templateInfos.get(uniqueName); + List userVmUsingIso = _userVmDao.listByIsoId(tInfo.getId()); + //check if there is any Vm using this ISO. + if (userVmUsingIso == null || userVmUsingIso.isEmpty()) { + DeleteTemplateCommand dtCommand = new DeleteTemplateCommand(store.getUri(), tInfo.getInstallPath()); + try { + HostVO ssAhost = _ssvmMgr.pickSsvmHost(store); + _agentMgr.sendToSecStorage(ssAhost, dtCommand, null); + } catch (AgentUnavailableException e) { + String err = "Failed to delete " + tInfo.getTemplateName() + " on secondary storage " + storeId + " which isn't in the database"; + s_logger.error(err); + return; + } + + String description = "Deleted template " + tInfo.getTemplateName() + " on secondary storage " + storeId + " since it isn't in the database"; + s_logger.info(description); + } + } + + } + + + // persist entry in template_zone_ref table. zoneId can be empty for region-wide image store, in that case, + // we will associate the template to all the zones. + private void associateTemplateToZone(long templateId, Long zoneId){ + List dcs = new ArrayList(); + if (zoneId != null ){ + dcs.add(zoneId); + } + else{ + List zones = _dcDao.listAll(); + for (DataCenterVO zone : zones){ + dcs.add(zone.getId()); + } + } + for (Long id : dcs) { + VMTemplateZoneVO tmpltZoneVO = _vmTemplateZoneDao.findByZoneTemplate(id, templateId); + if (tmpltZoneVO == null) { + tmpltZoneVO = new VMTemplateZoneVO(id, templateId, new Date()); + _vmTemplateZoneDao.persist(tmpltZoneVO); + } else { + tmpltZoneVO.setLastUpdated(new Date()); + _vmTemplateZoneDao.update(tmpltZoneVO.getId(), tmpltZoneVO); + } + } + } + + + private Map listTemplate(DataStore ssHost) { + ListTemplateCommand cmd = new ListTemplateCommand(ssHost.getUri()); + HostVO ssAhost = _ssvmMgr.pickSsvmHost(ssHost); + Answer answer = _agentMgr.sendToSecStorage(ssAhost, cmd); + if (answer != null && answer.getResult()) { + ListTemplateAnswer tanswer = (ListTemplateAnswer)answer; + return tanswer.getTemplateInfo(); + } else { + if (s_logger.isDebugEnabled()) { + s_logger.debug("can not list template for secondary storage host " + ssHost.getId()); + } + } + + return null; + } + + + protected Void createTemplateCallback(AsyncCallbackDispatcher callback, + CreateTemplateContext context) { + TemplateObject template = (TemplateObject)context.srcTemplate; + AsyncCallFuture future = context.future; + CommandResult result = new CommandResult(); + DataObject templateOnStore = context.templateOnStore; + CreateCmdResult callbackResult = callback.getResult(); + if (callbackResult.isFailed()) { + try { + templateOnStore.processEvent(ObjectInDataStoreStateMachine.Event.OperationFailed); + template.stateTransit(TemplateEvent.OperationFailed); + } catch (NoTransitionException e) { + s_logger.debug("Failed to update template state", e); + } + result.setResult(callbackResult.getResult()); + future.complete(result); + return null; + } + + try { + templateOnStore.processEvent(ObjectInDataStoreStateMachine.Event.OperationSuccessed); + template.stateTransit(TemplateEvent.OperationSucceeded); + } catch (NoTransitionException e) { + s_logger.debug("Failed to transit state", e); + result.setResult(e.toString()); + future.complete(result); + return null; + } + + future.complete(result); + return null; + } + + @Override + public AsyncCallFuture deleteTemplateAsync( + TemplateInfo template) { + // TODO Auto-generated method stub + return null; + } + + @Override + public AsyncCallFuture createTemplateFromSnapshotAsync( + SnapshotInfo snapshot, TemplateInfo template, DataStore store) { + // TODO Auto-generated method stub + return null; + } + + @Override + public AsyncCallFuture createTemplateFromVolumeAsync( + VolumeInfo volume, TemplateInfo template, DataStore store) { + // TODO Auto-generated method stub + return null; + } + + + +} diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/volumeServiceTest.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/volumeServiceTest.java index 293d7fb11c8..fcb89624dde 100644 --- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/volumeServiceTest.java +++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/volumeServiceTest.java @@ -39,7 +39,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProviderManag import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreRole; import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; 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.TemplateService; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo; @@ -86,7 +86,7 @@ public class volumeServiceTest extends CloudStackTestNGBase { //@Inject //ImageDataStoreProviderManager imageProviderMgr; @Inject - ImageService imageService; + TemplateService imageService; @Inject VolumeService volumeService; @Inject diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/db/SnapshotDataStoreDaoImpl.java b/engine/storage/src/org/apache/cloudstack/storage/image/db/SnapshotDataStoreDaoImpl.java index 6a6e04a52b3..c9ade1a7523 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/image/db/SnapshotDataStoreDaoImpl.java +++ b/engine/storage/src/org/apache/cloudstack/storage/image/db/SnapshotDataStoreDaoImpl.java @@ -42,21 +42,16 @@ public class SnapshotDataStoreDaoImpl extends GenericDaoBase updateStateSearch; private SearchBuilder storeSearch; - private SearchBuilder liveStoreSearch; @Override public boolean configure(String name, Map params) throws ConfigurationException { super.configure(name, params); - storeSearch = createSearchBuilder(); + storeSearch = createSearchBuilder(); storeSearch.and("store_id", storeSearch.entity().getDataStoreId(), SearchCriteria.Op.EQ); + storeSearch.and("destroyed", storeSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); storeSearch.done(); - liveStoreSearch = createSearchBuilder(); - liveStoreSearch.and("store_id", liveStoreSearch.entity().getDataStoreId(), SearchCriteria.Op.EQ); - liveStoreSearch.and("destroyed", liveStoreSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); - liveStoreSearch.done(); - updateStateSearch = this.createSearchBuilder(); updateStateSearch.and("id", updateStateSearch.entity().getId(), Op.EQ); updateStateSearch.and("state", updateStateSearch.entity().getState(), Op.EQ); @@ -102,17 +97,11 @@ public class SnapshotDataStoreDaoImpl extends GenericDaoBase 0; } + @Override public List listByStoreId(long id) { SearchCriteria sc = storeSearch.create(); sc.setParameters("store_id", id); - return listIncludingRemovedBy(sc); - } - - @Override - public List listLiveByStoreId(long id) { - SearchCriteria sc = liveStoreSearch.create(); - sc.setParameters("store_id", id); sc.setParameters("destroyed", false); return listIncludingRemovedBy(sc); } 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 a429dc961d6..e34a1aba885 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 @@ -30,6 +30,7 @@ import org.apache.log4j.Logger; import org.springframework.stereotype.Component; import com.cloud.storage.VMTemplateHostVO; +import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; @@ -42,23 +43,20 @@ public class TemplateDataStoreDaoImpl extends GenericDaoBase updateStateSearch; private SearchBuilder storeSearch; - private SearchBuilder liveStoreSearch; private SearchBuilder storeTemplateStateSearch; + private SearchBuilder storeTemplateDownloadStatusSearch; private SearchBuilder storeTemplateSearch; @Override public boolean configure(String name, Map params) throws ConfigurationException { super.configure(name, params); + storeSearch = createSearchBuilder(); storeSearch.and("store_id", storeSearch.entity().getDataStoreId(), SearchCriteria.Op.EQ); + storeSearch.and("destroyed", storeSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); storeSearch.done(); - liveStoreSearch = createSearchBuilder(); - liveStoreSearch.and("store_id", liveStoreSearch.entity().getDataStoreId(), SearchCriteria.Op.EQ); - liveStoreSearch.and("destroyed", liveStoreSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); - liveStoreSearch.done(); - updateStateSearch = this.createSearchBuilder(); updateStateSearch.and("id", updateStateSearch.entity().getId(), Op.EQ); updateStateSearch.and("state", updateStateSearch.entity().getState(), Op.EQ); @@ -72,6 +70,14 @@ public class TemplateDataStoreDaoImpl extends GenericDaoBase 0; } + @Override public List listByStoreId(long id) { SearchCriteria sc = storeSearch.create(); sc.setParameters("store_id", id); - return listIncludingRemovedBy(sc); - } - @Override - public List listLiveByStoreId(long id) { - SearchCriteria sc = liveStoreSearch.create(); - sc.setParameters("store_id", id); sc.setParameters("destroyed", false); return listIncludingRemovedBy(sc); } @@ -152,6 +153,17 @@ public class TemplateDataStoreDaoImpl extends GenericDaoBase listByTemplateStoreDownloadStatus(long templateId, long storeId, Status... status) { + SearchCriteria sc = storeTemplateStateSearch.create(); + sc.setParameters("template_id", templateId); + sc.setParameters("store_id", storeId); + sc.setParameters("downloadState", (Object[])status); + return search(sc, null); + } + @Override public TemplateDataStoreVO findByStoreTemplate(long storeId, long templateId) { SearchCriteria sc = storeTemplateSearch.create(); 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 9a93f980b27..dc6c2354952 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 @@ -31,6 +31,7 @@ import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreVO; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; +import com.cloud.storage.VolumeHostVO; import com.cloud.utils.db.GenericDaoBase; import com.cloud.utils.db.SearchBuilder; import com.cloud.utils.db.SearchCriteria; @@ -42,21 +43,30 @@ import com.cloud.utils.db.UpdateBuilder; public class VolumeDataStoreDaoImpl extends GenericDaoBase implements VolumeDataStoreDao { private static final Logger s_logger = Logger.getLogger(VolumeDataStoreDaoImpl.class); private SearchBuilder updateStateSearch; + private SearchBuilder volumeSearch; private SearchBuilder storeSearch; - private SearchBuilder liveStoreSearch; + private SearchBuilder storeVolumeSearch; @Override public boolean configure(String name, Map params) throws ConfigurationException { super.configure(name, params); + storeSearch = createSearchBuilder(); storeSearch.and("store_id", storeSearch.entity().getDataStoreId(), SearchCriteria.Op.EQ); + storeSearch.and("destroyed", storeSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); storeSearch.done(); - liveStoreSearch = createSearchBuilder(); - liveStoreSearch.and("store_id", liveStoreSearch.entity().getDataStoreId(), SearchCriteria.Op.EQ); - liveStoreSearch.and("destroyed", liveStoreSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); - liveStoreSearch.done(); + volumeSearch = createSearchBuilder(); + volumeSearch.and("volume_id", volumeSearch.entity().getVolumeId(), SearchCriteria.Op.EQ); + volumeSearch.and("destroyed", volumeSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); + volumeSearch.done(); + + storeVolumeSearch = createSearchBuilder(); + storeVolumeSearch.and("store_id", storeVolumeSearch.entity().getDataStoreId(), SearchCriteria.Op.EQ); + storeVolumeSearch.and("volume_id", storeVolumeSearch.entity().getVolumeId(), SearchCriteria.Op.EQ); + storeVolumeSearch.and("destroyed", storeVolumeSearch.entity().getDestroyed(), SearchCriteria.Op.EQ); + storeVolumeSearch.done(); updateStateSearch = this.createSearchBuilder(); updateStateSearch.and("id", updateStateSearch.entity().getId(), Op.EQ); @@ -102,16 +112,11 @@ public class VolumeDataStoreDaoImpl extends GenericDaoBase 0; } + @Override public List listByStoreId(long id) { SearchCriteria sc = storeSearch.create(); sc.setParameters("store_id", id); - return listIncludingRemovedBy(sc); - } - @Override - public List listLiveByStoreId(long id) { - SearchCriteria sc = liveStoreSearch.create(); - sc.setParameters("store_id", id); sc.setParameters("destroyed", false); return listIncludingRemovedBy(sc); } @@ -125,4 +130,23 @@ public class VolumeDataStoreDaoImpl extends GenericDaoBase sc = volumeSearch.create(); + sc.setParameters("volume_id", volumeId); + sc.setParameters("destroyed", false); + return findOneBy(sc); + } + @Override + public VolumeDataStoreVO findByStoreVolume(long storeId, long volumeId) { + SearchCriteria sc = storeVolumeSearch.create(); + sc.setParameters("store_id", storeId); + sc.setParameters("volume_id", volumeId); + sc.setParameters("destroyed", false); + return findOneBy(sc); + } + + } diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java index cde576b79f1..766d219261d 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java +++ b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java @@ -318,6 +318,10 @@ public class VolumeObject implements VolumeInfo { return this.payload; } + public VolumeVO getVolume(){ + return this.volumeVO; + } + @Override public HypervisorType getHypervisorType() { return this.volumeDao.getHypervisorType(this.volumeVO.getId()); diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java index 2b43adec71a..2da16c1178d 100644 --- a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java +++ b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java @@ -18,6 +18,11 @@ */ package org.apache.cloudstack.storage.volume; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.Map; + import javax.inject.Inject; import org.apache.cloudstack.engine.cloud.entity.api.VolumeEntity; @@ -41,19 +46,37 @@ import org.apache.cloudstack.storage.datastore.DataObjectManager; import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager; import org.apache.cloudstack.storage.datastore.PrimaryDataStore; import org.apache.cloudstack.storage.datastore.PrimaryDataStoreProviderManager; +import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreDao; +import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreVO; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; +import com.cloud.agent.AgentManager; +import com.cloud.agent.api.Answer; +import com.cloud.agent.api.storage.DeleteVolumeCommand; +import com.cloud.agent.api.storage.ListVolumeAnswer; +import com.cloud.agent.api.storage.ListVolumeCommand; +import com.cloud.alert.AlertManager; import com.cloud.configuration.Config; import com.cloud.configuration.dao.ConfigurationDao; +import com.cloud.exception.AgentUnavailableException; import com.cloud.exception.ConcurrentOperationException; +import com.cloud.exception.ResourceAllocationException; +import com.cloud.host.HostVO; import com.cloud.storage.StoragePool; import com.cloud.storage.Volume; +import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; import com.cloud.storage.Volume.Type; import com.cloud.storage.VolumeVO; import com.cloud.storage.dao.VolumeDao; +import com.cloud.storage.download.DownloadMonitor; +import com.cloud.storage.secondary.SecondaryStorageVmManager; import com.cloud.storage.snapshot.SnapshotManager; +import com.cloud.storage.template.TemplateProp; +import com.cloud.user.AccountManager; +import com.cloud.user.ResourceLimitService; import com.cloud.utils.NumbersUtil; +import com.cloud.utils.UriUtils; import com.cloud.utils.db.DB; import com.cloud.vm.VirtualMachine; import com.cloud.vm.dao.VMInstanceDao; @@ -77,13 +100,29 @@ public class VolumeServiceImpl implements VolumeService { @Inject VolumeDataFactory volFactory; @Inject SnapshotManager snapshotMgr; + @Inject + ResourceLimitService _resourceLimitMgr; + @Inject + DownloadMonitor _dlMonitor; + @Inject + AccountManager _accountMgr; + @Inject + AlertManager _alertMgr; @Inject VMInstanceDao vmDao; @Inject ConfigurationDao configDao; + @Inject + SecondaryStorageVmManager _ssvmMgr; + @Inject + AgentManager _agentMgr; + @Inject + VolumeDataStoreDao _volumeStoreDao; + @Inject + VolumeDao _volumeDao; public VolumeServiceImpl() { } - + private class CreateVolumeContext extends AsyncRpcConext { private DataObject volume; @@ -96,17 +135,17 @@ public class VolumeServiceImpl implements VolumeService { this.volume = volume; this.future = future; } - + public DataObject getVolume() { return this.volume; } - + public AsyncCallFuture getFuture() { return this.future; } - + } - + @Override public AsyncCallFuture createVolumeAsync(VolumeInfo volume, DataStore dataStore) { AsyncCallFuture future = new AsyncCallFuture(); @@ -117,11 +156,11 @@ public class VolumeServiceImpl implements VolumeService { AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); caller.setCallback(caller.getTarget().createVolumeCallback(null, null)) .setContext(context); - + dataStore.getDriver().createAsync(volumeOnStore, caller); return future; } - + protected Void createVolumeCallback(AsyncCallbackDispatcher callback, CreateVolumeContext context) { CreateCmdResult result = callback.getResult(); DataObject vo = context.getVolume(); @@ -139,7 +178,7 @@ public class VolumeServiceImpl implements VolumeService { context.getFuture().complete(volResult); return null; } - + private class DeleteVolumeContext extends AsyncRpcConext { private final VolumeObject volume; private AsyncCallFuture future; @@ -151,11 +190,11 @@ public class VolumeServiceImpl implements VolumeService { this.volume = volume; this.future = future; } - + public VolumeObject getVolume() { return this.volume; } - + public AsyncCallFuture getFuture() { return this.future; } @@ -171,7 +210,7 @@ public class VolumeServiceImpl implements VolumeService { future.complete(result); return future; } - + String vmName = null; VolumeVO vol = this.volDao.findById(volume.getId()); if (vol.getVolumeType() == Type.ROOT && vol.getInstanceId() != null) { @@ -194,19 +233,19 @@ public class VolumeServiceImpl implements VolumeService { return future; } VolumeObject vo = (VolumeObject)volume; - + volume.processEvent(Event.ExpungeRequested); - - + + DeleteVolumeContext context = new DeleteVolumeContext(null, vo, future); AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); caller.setCallback(caller.getTarget().deleteVolumeCallback(null, null)) .setContext(context); - + volume.getDataStore().getDriver().deleteAsync(volume, caller); return future; } - + public Void deleteVolumeCallback(AsyncCallbackDispatcher callback, DeleteVolumeContext context) { CommandResult result = callback.getResult(); VolumeObject vo = context.getVolume(); @@ -249,7 +288,7 @@ public class VolumeServiceImpl implements VolumeService { private final TemplateInfo srcTemplate; private final AsyncCallFuture future; final DataObject destObj; - public CreateBaseImageContext(AsyncCompletionCallback callback, VolumeInfo volume, PrimaryDataStore datastore, + public CreateBaseImageContext(AsyncCompletionCallback callback, VolumeInfo volume, PrimaryDataStore datastore, TemplateInfo srcTemplate, AsyncCallFuture future, DataObject destObj) { super(callback); @@ -259,11 +298,11 @@ public class VolumeServiceImpl implements VolumeService { this.srcTemplate = srcTemplate; this.destObj = destObj; } - + public VolumeInfo getVolume() { return this.volume; } - + public PrimaryDataStore getDataStore() { return this.dataStore; } @@ -271,13 +310,13 @@ public class VolumeServiceImpl implements VolumeService { public TemplateInfo getSrcTemplate() { return this.srcTemplate; } - + public AsyncCallFuture getFuture() { return this.future; } - + } - + static class CreateBaseImageResult extends CommandResult { final TemplateInfo template; public CreateBaseImageResult(TemplateInfo template) { @@ -285,7 +324,7 @@ public class VolumeServiceImpl implements VolumeService { this.template = template; } } - + private TemplateInfo waitForTemplateDownloaded(PrimaryDataStore store, TemplateInfo template) { int storagePoolMaxWaitSeconds = NumbersUtil.parseInt(configDao.getValue(Config.StoragePoolMaxWaitSeconds.key()), 3600); int sleepTime = 120; @@ -306,16 +345,16 @@ public class VolumeServiceImpl implements VolumeService { } @DB protected void createBaseImageAsync(VolumeInfo volume, PrimaryDataStore dataStore, TemplateInfo template, AsyncCallFuture future) { - + DataObject templateOnPrimaryStoreObj = dataStore.create(template); - CreateBaseImageContext context = new CreateBaseImageContext(null, volume, + CreateBaseImageContext context = new CreateBaseImageContext(null, volume, dataStore, template, future, templateOnPrimaryStoreObj); AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); caller.setCallback(caller.getTarget().copyBaseImageCallback(null, null)) .setContext(context); - + try { templateOnPrimaryStoreObj.processEvent(Event.CreateOnlyRequested); } catch (Exception e) { @@ -330,7 +369,7 @@ public class VolumeServiceImpl implements VolumeService { } } } - + try { motionSrv.copyAsync(template, templateOnPrimaryStoreObj, caller); } catch (Exception e) { @@ -342,12 +381,12 @@ public class VolumeServiceImpl implements VolumeService { } return; } - + @DB protected Void copyBaseImageCallback(AsyncCallbackDispatcher callback, CreateBaseImageContext context) { CopyCommandResult result = callback.getResult(); VolumeApiResult res = new VolumeApiResult(context.getVolume()); - + AsyncCallFuture future = context.getFuture(); DataObject templateOnPrimaryStoreObj = context.destObj; if (!result.isSuccess()) { @@ -356,18 +395,18 @@ public class VolumeServiceImpl implements VolumeService { future.complete(res); return null; } - + templateOnPrimaryStoreObj.processEvent(Event.OperationSuccessed); createVolumeFromBaseImageAsync(context.volume, templateOnPrimaryStoreObj, context.dataStore, future); return null; } - + private class CreateVolumeFromBaseImageContext extends AsyncRpcConext { private final VolumeObject vo; private final AsyncCallFuture future; private final DataStore primaryStore; private final DataObject templateOnStore; - public CreateVolumeFromBaseImageContext(AsyncCompletionCallback callback, VolumeObject vo, + public CreateVolumeFromBaseImageContext(AsyncCompletionCallback callback, VolumeObject vo, DataStore primaryStore, DataObject templateOnStore, AsyncCallFuture future) { @@ -377,13 +416,13 @@ public class VolumeServiceImpl implements VolumeService { this.primaryStore = primaryStore; this.templateOnStore = templateOnStore; } - + public AsyncCallFuture getFuture() { return this.future; } } - + @DB protected void createVolumeFromBaseImageAsync(VolumeInfo volume, DataObject templateOnPrimaryStore, PrimaryDataStore pd, AsyncCallFuture future) { VolumeObject vo = (VolumeObject)volume; @@ -398,23 +437,23 @@ public class VolumeServiceImpl implements VolumeService { motionSrv.copyAsync(context.templateOnStore, volumeOnPrimaryStorage, caller); return; } - + @DB public Void copyBaseImageCallBack(AsyncCallbackDispatcher callback, CreateVolumeFromBaseImageContext context) { VolumeObject vo = context.vo; CopyCommandResult result = callback.getResult(); VolumeApiResult volResult = new VolumeApiResult(vo); - + if (result.isSuccess()) { if (result.getPath() != null) { vo.setPath(result.getPath()); } - vo.processEvent(Event.OperationSuccessed); + vo.processEvent(Event.OperationSuccessed); } else { vo.processEvent(Event.OperationFailed); volResult.setResult(result.getResult()); } - + AsyncCallFuture future = context.getFuture(); future.complete(volResult); return null; @@ -427,12 +466,12 @@ public class VolumeServiceImpl implements VolumeService { TemplateInfo templateOnPrimaryStore = pd.getTemplate(template.getId()); AsyncCallFuture future = new AsyncCallFuture(); VolumeApiResult result = new VolumeApiResult(volume); - + if (templateOnPrimaryStore == null) { createBaseImageAsync(volume, pd, template, future); return future; } - + createVolumeFromBaseImageAsync(volume, templateOnPrimaryStore, pd, future); return future; } @@ -441,13 +480,13 @@ public class VolumeServiceImpl implements VolumeService { @DB public boolean destroyVolume(long volumeId) throws ConcurrentOperationException { - + VolumeInfo vol = this.volFactory.getVolume(volumeId); vol.processEvent(Event.DestroyRequested); this.snapshotMgr.deletePoliciesForVolume(volumeId); vol.processEvent(Event.OperationSuccessed); - + return true; } @@ -455,11 +494,11 @@ public class VolumeServiceImpl implements VolumeService { public AsyncCallFuture createVolumeFromSnapshot( VolumeInfo volume, DataStore store, SnapshotInfo snapshot) { AsyncCallFuture future = new AsyncCallFuture(); - + try { DataObject volumeOnStore = store.create(volume); volume.processEvent(Event.CreateOnlyRequested); - CreateVolumeFromBaseImageContext context = new CreateVolumeFromBaseImageContext(null, + CreateVolumeFromBaseImageContext context = new CreateVolumeFromBaseImageContext(null, (VolumeObject)volume, store, volumeOnStore, future); AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); caller.setCallback(caller.getTarget().createVolumeFromSnapshotCallback(null, null)) @@ -471,11 +510,11 @@ public class VolumeServiceImpl implements VolumeService { result.setResult(e.toString()); future.complete(result); } - + return future; } - - protected Void createVolumeFromSnapshotCallback(AsyncCallbackDispatcher callback, + + protected Void createVolumeFromSnapshotCallback(AsyncCallbackDispatcher callback, CreateVolumeFromBaseImageContext context) { CopyCommandResult result = callback.getResult(); VolumeInfo volume = context.vo; @@ -487,19 +526,19 @@ public class VolumeServiceImpl implements VolumeService { } else { event = Event.OperationSuccessed; } - + try { volume.processEvent(event); } catch (Exception e) { s_logger.debug("create volume from snapshot failed", e); apiResult.setResult(e.toString()); } - + AsyncCallFuture future = context.future; future.complete(apiResult); return null; } - + protected VolumeVO duplicateVolumeOnAnotherStorage(Volume volume, StoragePool pool) { Long lastPoolId = volume.getPoolId(); VolumeVO newVol = new VolumeVO(volume); @@ -511,7 +550,7 @@ public class VolumeServiceImpl implements VolumeService { newVol.setPodId(pool.getPodId()); return this.volDao.persist(newVol); } - + private class CopyVolumeContext extends AsyncRpcConext { final VolumeInfo srcVolume; @@ -529,7 +568,7 @@ public class VolumeServiceImpl implements VolumeService { this.destStore = destStore; this.future = future; } - + } @Override public AsyncCallFuture copyVolume(VolumeInfo srcVolume, @@ -540,7 +579,7 @@ public class VolumeServiceImpl implements VolumeService { if (!this.snapshotMgr.canOperateOnVolume(srcVolume)) { s_logger.debug( "There are snapshots creating on this volume, can not move this volume"); - + res.setResult("There are snapshots creating on this volume, can not move this volume"); future.complete(res); return future; @@ -551,7 +590,7 @@ public class VolumeServiceImpl implements VolumeService { destVolume.processEvent(Event.CreateOnlyRequested); srcVolume.processEvent(Event.CopyingRequested); - CopyVolumeContext context = new CopyVolumeContext(null, future, srcVolume, + CopyVolumeContext context = new CopyVolumeContext(null, future, srcVolume, destVolume, destStore); AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); @@ -565,7 +604,7 @@ public class VolumeServiceImpl implements VolumeService { } return future; } - + protected Void copyVolumeCallBack(AsyncCallbackDispatcher callback, CopyVolumeContext context) { VolumeInfo srcVolume = context.srcVolume; VolumeInfo destVolume = context.destVolume; @@ -593,13 +632,13 @@ public class VolumeServiceImpl implements VolumeService { res.setResult(e.toString()); future.complete(res); } - + return null; } - + @Override public AsyncCallFuture registerVolume(VolumeInfo volume, DataStore store) { - + AsyncCallFuture future = new AsyncCallFuture(); VolumeObject vo = (VolumeObject) volume; @@ -607,11 +646,11 @@ public class VolumeServiceImpl implements VolumeService { AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); caller.setCallback(caller.getTarget().registerVolumeCallback(null, null)) .setContext(context); - + dataObjectMgr.createAsync(volume, store, caller, true); return future; } - + protected Void registerVolumeCallback(AsyncCallbackDispatcher callback, CreateVolumeContext context) { CreateCmdResult result = callback.getResult(); VolumeObject vo = (VolumeObject)context.volume; @@ -624,7 +663,7 @@ public class VolumeServiceImpl implements VolumeService { context.future.complete(res); return null; } - + @Override public AsyncCallFuture resize(VolumeInfo volume) { @@ -645,12 +684,12 @@ public class VolumeServiceImpl implements VolumeService { volume.getDataStore().getDriver().resize(volume, caller); return future; } - + protected Void resizeVolumeCallback(AsyncCallbackDispatcher callback, CreateVolumeContext context) { CreateCmdResult result = callback.getResult(); AsyncCallFuture future = context.future; VolumeInfo volume = (VolumeInfo)context.volume; - + if (result.isFailed()) { try { volume.processEvent(Event.OperationFailed); @@ -662,7 +701,7 @@ public class VolumeServiceImpl implements VolumeService { future.complete(res); return null; } - + try { volume.processEvent(Event.OperationSuccessed); } catch(Exception e) { @@ -672,13 +711,137 @@ public class VolumeServiceImpl implements VolumeService { future.complete(res); return null; } - + VolumeApiResult res = new VolumeApiResult(volume); future.complete(res); - + return null; } - - + + @Override + public void handleVolumeSync(DataStore store) { + if (store == null) { + s_logger.warn("Huh? ssHost is null"); + return; + } + long storeId = store.getId(); + Long zoneId = store.getScope().getScopeId(); + + + Map volumeInfos = listVolume(store); + if (volumeInfos == null) { + return; + } + + List dbVolumes = _volumeStoreDao.listByStoreId(storeId); + List toBeDownloaded = new ArrayList(dbVolumes); + for (VolumeDataStoreVO volumeStore : dbVolumes){ + VolumeVO volume = _volumeDao.findById(volumeStore.getVolumeId()); + //Exists then don't download + if (volumeInfos.containsKey(volume.getId())){ + TemplateProp volInfo = volumeInfos.remove(volume.getId()); + toBeDownloaded.remove(volumeStore); + s_logger.info("Volume Sync found " + volume.getUuid() + " already in the volume image store table"); + if (volumeStore.getDownloadState() != Status.DOWNLOADED) { + volumeStore.setErrorString(""); + } + if (volInfo.isCorrupted()) { + volumeStore.setDownloadState(Status.DOWNLOAD_ERROR); + String msg = "Volume " + volume.getUuid() + " is corrupted on image store "; + volumeStore.setErrorString(msg); + s_logger.info("msg"); + if (volumeStore.getDownloadUrl() == null) { + msg = "Volume (" + volume.getUuid() + ") with install path " + volInfo.getInstallPath() + "is corrupted, please check in image store: " + volumeStore.getDataStoreId(); + s_logger.warn(msg); + } else { + toBeDownloaded.add(volumeStore); + } + + } else { // Put them in right status + volumeStore.setDownloadPercent(100); + volumeStore.setDownloadState(Status.DOWNLOADED); + volumeStore.setInstallPath(volInfo.getInstallPath()); + volumeStore.setSize(volInfo.getSize()); + volumeStore.setPhysicalSize(volInfo.getPhysicalSize()); + volumeStore.setLastUpdated(new Date()); + _volumeStoreDao.update(volumeStore.getId(), volumeStore); + + if (volume.getSize() == 0) { + // Set volume size in volumes table + volume.setSize(volInfo.getSize()); + _volumeDao.update(volumeStore.getVolumeId(), volume); + } + + if (volInfo.getSize() > 0) { + try { + String url = _volumeStoreDao.findByVolumeId(volume.getId()).getDownloadUrl(); + _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(volume.getAccountId()), + com.cloud.configuration.Resource.ResourceType.secondary_storage, + volInfo.getSize() - UriUtils.getRemoteSize(url)); + } catch (ResourceAllocationException e) { + s_logger.warn(e.getMessage()); + _alertMgr.sendAlert(_alertMgr.ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED, volume.getDataCenterId(), + volume.getPodId(), e.getMessage(), e.getMessage()); + } finally { + _resourceLimitMgr.recalculateResourceCount(volume.getAccountId(), volume.getDomainId(), + com.cloud.configuration.Resource.ResourceType.secondary_storage.getOrdinal()); + } + } + } + continue; + } + // Volume is not on secondary but we should download. + if (volumeStore.getDownloadState() != Status.DOWNLOADED) { + s_logger.info("Volume Sync did not find " + volume.getName() + " ready on image store " + storeId + ", will request download to start/resume shortly"); + toBeDownloaded.add(volumeStore); + } + } + + //Download volumes which haven't been downloaded yet. + if (toBeDownloaded.size() > 0) { + for (VolumeDataStoreVO volumeHost : toBeDownloaded) { + if (volumeHost.getDownloadUrl() == null) { // If url is null we can't initiate the download + continue; + } + s_logger.debug("Volume " + volumeHost.getVolumeId() + " needs to be downloaded to " + store.getName()); + //TODO: pass a callback later + _dlMonitor.downloadVolumeToStorage(_volumeDao.findById(volumeHost.getVolumeId()), store, volumeHost.getDownloadUrl(), volumeHost.getChecksum(), volumeHost.getFormat(), null); + } + } + + //Delete volumes which are not present on DB. + for (Long uniqueName : volumeInfos.keySet()) { + TemplateProp vInfo = volumeInfos.get(uniqueName); + DeleteVolumeCommand dtCommand = new DeleteVolumeCommand(store.getUri(), vInfo.getInstallPath()); + try { + HostVO ssAhost = _ssvmMgr.pickSsvmHost(store); + _agentMgr.sendToSecStorage(ssAhost, dtCommand, null); + } catch (AgentUnavailableException e) { + String err = "Failed to delete " + vInfo.getTemplateName() + " on image store " + storeId + " which isn't in the database"; + s_logger.error(err); + return; + } + + String description = "Deleted volume " + vInfo.getTemplateName() + " on image store " + storeId + " since it isn't in the database"; + s_logger.info(description); + } + + } + + private Map listVolume(DataStore store) { + ListVolumeCommand cmd = new ListVolumeCommand(store.getUri()); + HostVO ssAhost = _ssvmMgr.pickSsvmHost(store); + Answer answer = _agentMgr.sendToSecStorage(ssAhost, cmd); + if (answer != null && answer.getResult()) { + ListVolumeAnswer tanswer = (ListVolumeAnswer)answer; + return tanswer.getTemplateInfo(); + } else { + if (s_logger.isDebugEnabled()) { + s_logger.debug("Can not list volumes for image store " + store.getId()); + } + } + + return null; + } } diff --git a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java index 362e0a53e53..706c9ef5670 100755 --- a/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java +++ b/plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java @@ -215,7 +215,7 @@ import com.cloud.storage.Volume; import com.cloud.storage.template.Processor; import com.cloud.storage.template.Processor.FormatInfo; import com.cloud.storage.template.QCOW2Processor; -import com.cloud.storage.template.TemplateInfo; +import com.cloud.storage.template.TemplateProp; import com.cloud.storage.template.TemplateLocation; import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; @@ -2381,7 +2381,7 @@ ServerResource { return new Answer(cmd, false, " Failed to create storage pool"); } - Map tInfo = new HashMap(); + Map tInfo = new HashMap(); ModifyStoragePoolAnswer answer = new ModifyStoragePoolAnswer(cmd, storagepool.getCapacity(), storagepool.getUsed(), tInfo); diff --git a/plugins/hypervisors/ovm/src/com/cloud/ovm/hypervisor/OvmResourceBase.java b/plugins/hypervisors/ovm/src/com/cloud/ovm/hypervisor/OvmResourceBase.java index a626e31f458..7d8d90c7b61 100755 --- a/plugins/hypervisors/ovm/src/com/cloud/ovm/hypervisor/OvmResourceBase.java +++ b/plugins/hypervisors/ovm/src/com/cloud/ovm/hypervisor/OvmResourceBase.java @@ -114,7 +114,7 @@ import com.cloud.resource.hypervisor.HypervisorResource; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.Volume; -import com.cloud.storage.template.TemplateInfo; +import com.cloud.storage.template.TemplateProp; import com.cloud.template.VirtualMachineTemplate.BootloaderType; import com.cloud.utils.Pair; import com.cloud.utils.Ternary; @@ -458,7 +458,7 @@ public class OvmResourceBase implements ServerResource, HypervisorResource { setupHeartBeat(pool.getUuid()); OvmStoragePool.Details d = OvmStoragePool.getDetailsByUuid(_conn, pool.getUuid()); - Map tInfo = new HashMap(); + Map tInfo = new HashMap(); ModifyStoragePoolAnswer answer = new ModifyStoragePoolAnswer(cmd, d.totalSpace, d.freeSpace, tInfo); return answer; } catch (Exception e) { diff --git a/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockStorageManagerImpl.java b/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockStorageManagerImpl.java index a50dff6382c..ae7cf298e97 100644 --- a/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockStorageManagerImpl.java +++ b/plugins/hypervisors/simulator/src/com/cloud/agent/manager/MockStorageManagerImpl.java @@ -74,7 +74,7 @@ import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.VMTemplateStorageResourceAssoc; import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; -import com.cloud.storage.template.TemplateInfo; +import com.cloud.storage.template.TemplateProp; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.db.Transaction; import com.cloud.utils.exception.CloudRuntimeException; @@ -357,7 +357,7 @@ public class MockStorageManagerImpl extends ManagerBase implements MockStorageMa txn = Transaction.open(Transaction.CLOUD_DB); txn.close(); } - return new ModifyStoragePoolAnswer(cmd, storagePool.getCapacity(), 0, new HashMap()); + return new ModifyStoragePoolAnswer(cmd, storagePool.getCapacity(), 0, new HashMap()); } @Override @@ -398,7 +398,7 @@ public class MockStorageManagerImpl extends ManagerBase implements MockStorageMa txn = Transaction.open(Transaction.CLOUD_DB); txn.close(); } - return new ModifyStoragePoolAnswer(cmd, storagePool.getCapacity(), 0, new HashMap()); + return new ModifyStoragePoolAnswer(cmd, storagePool.getCapacity(), 0, new HashMap()); } @Override @@ -449,9 +449,9 @@ public class MockStorageManagerImpl extends ManagerBase implements MockStorageMa List volumes = _mockVolumeDao.findByStorageIdAndType(storage.getId(), MockVolumeType.VOLUME); - Map templateInfos = new HashMap(); + Map templateInfos = new HashMap(); for (MockVolumeVO volume : volumes) { - templateInfos.put(volume.getId(), new TemplateInfo(volume.getName(), volume.getPath() + templateInfos.put(volume.getId(), new TemplateProp(volume.getName(), volume.getPath() .replaceAll(storage.getMountPoint(), ""), volume.getSize(), volume.getSize(), true, false)); } txn.commit(); @@ -492,9 +492,9 @@ public class MockStorageManagerImpl extends ManagerBase implements MockStorageMa List templates = _mockVolumeDao.findByStorageIdAndType(storage.getId(), MockVolumeType.TEMPLATE); - Map templateInfos = new HashMap(); + Map templateInfos = new HashMap(); for (MockVolumeVO template : templates) { - templateInfos.put(template.getName(), new TemplateInfo(template.getName(), template.getPath() + templateInfos.put(template.getName(), new TemplateProp(template.getName(), template.getPath() .replaceAll(storage.getMountPoint(), ""), template.getSize(), template.getSize(), true, false)); } txn.commit(); diff --git a/plugins/hypervisors/simulator/src/com/cloud/resource/AgentRoutingResource.java b/plugins/hypervisors/simulator/src/com/cloud/resource/AgentRoutingResource.java index 46df50c2133..8a03c4b9598 100644 --- a/plugins/hypervisors/simulator/src/com/cloud/resource/AgentRoutingResource.java +++ b/plugins/hypervisors/simulator/src/com/cloud/resource/AgentRoutingResource.java @@ -51,7 +51,7 @@ import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.network.Networks.RouterPrivateIpStrategy; import com.cloud.simulator.MockVMVO; import com.cloud.storage.Storage.StorageResourceType; -import com.cloud.storage.template.TemplateInfo; +import com.cloud.storage.template.TemplateProp; import com.cloud.utils.Pair; import com.cloud.vm.VirtualMachine.State; @@ -168,7 +168,7 @@ public class AgentRoutingResource extends AgentStorageResource { } private StartupStorageCommand initializeLocalSR() { - Map tInfo = new HashMap(); + Map tInfo = new HashMap(); StoragePoolInfo poolInfo = _simMgr.getLocalStorage(hostGuid); diff --git a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java index 634827b6468..4079d0d65b5 100755 --- a/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java +++ b/plugins/hypervisors/vmware/src/com/cloud/hypervisor/vmware/resource/VmwareResource.java @@ -210,7 +210,7 @@ import com.cloud.storage.Storage; import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.Volume; import com.cloud.storage.resource.StoragePoolResource; -import com.cloud.storage.template.TemplateInfo; +import com.cloud.storage.template.TemplateProp; import com.cloud.utils.DateUtil; import com.cloud.utils.Pair; import com.cloud.utils.StringUtils; @@ -3137,7 +3137,7 @@ public class VmwareResource implements StoragePoolResource, ServerResource, Vmwa DatastoreSummary summary = new DatastoreMO(getServiceContext(), morDatastore).getSummary(); long capacity = summary.getCapacity(); long available = summary.getFreeSpace(); - Map tInfo = new HashMap(); + Map tInfo = new HashMap(); ModifyStoragePoolAnswer answer = new ModifyStoragePoolAnswer(cmd, capacity, available, tInfo); return answer; } catch (Throwable e) { diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java index c50f13ce7e5..046827d79b7 100644 --- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java +++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java @@ -233,7 +233,7 @@ import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.Volume; import com.cloud.storage.VolumeVO; -import com.cloud.storage.template.TemplateInfo; +import com.cloud.storage.template.TemplateProp; import com.cloud.template.VirtualMachineTemplate.BootloaderType; import com.cloud.utils.NumbersUtil; import com.cloud.utils.Pair; @@ -5287,7 +5287,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe s_logger.warn(msg); return new Answer(cmd, false, msg); } - Map tInfo = new HashMap(); + Map tInfo = new HashMap(); ModifyStoragePoolAnswer answer = new ModifyStoragePoolAnswer(cmd, capacity, available, tInfo); return answer; } catch (XenAPIException e) { diff --git a/plugins/storage/image/default/pom.xml b/plugins/storage/image/default/pom.xml index e84eab42941..d1b079d05e6 100644 --- a/plugins/storage/image/default/pom.xml +++ b/plugins/storage/image/default/pom.xml @@ -25,6 +25,16 @@ cloud-engine-storage-image ${project.version} + + org.apache.cloudstack + cloud-engine-storage-volume + ${project.version} + + + org.apache.cloudstack + cloud-engine-storage-snapshot + ${project.version} + mysql mysql-connector-java diff --git a/plugins/storage/image/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackImageStoreDriverImpl.java b/plugins/storage/image/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackImageStoreDriverImpl.java index d52af65279c..46c87b7c66d 100644 --- a/plugins/storage/image/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackImageStoreDriverImpl.java +++ b/plugins/storage/image/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackImageStoreDriverImpl.java @@ -35,6 +35,7 @@ import org.apache.cloudstack.framework.async.AsyncCompletionCallback; import org.apache.cloudstack.framework.async.AsyncRpcConext; import org.apache.cloudstack.storage.image.ImageStoreDriver; import org.apache.cloudstack.storage.image.store.TemplateObject; +import org.apache.cloudstack.storage.volume.VolumeObject; import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; @@ -118,11 +119,10 @@ public class CloudStackImageStoreDriverImpl implements ImageStoreDriver { TemplateObject tData = (TemplateObject)data; _downloadMonitor.downloadTemplateToStorage(tData.getImage(), tData.getDataStore(), callback); } else if (data.getType() == DataObjectType.VOLUME) { - VolumeVO vol = this.volumeDao.findById(data.getId()); - VolumeInfo volInfo = (VolumeInfo)data; + VolumeObject volInfo = (VolumeObject)data; RegisterVolumePayload payload = (RegisterVolumePayload)volInfo.getpayload(); - _downloadMonitor.downloadVolumeToStorage(vol, vol.getDataCenterId(), payload.getUrl(), - payload.getChecksum(), ImageFormat.valueOf(payload.getFormat().toUpperCase())); + _downloadMonitor.downloadVolumeToStorage(volInfo.getVolume(), volInfo.getDataStore(), payload.getUrl(), + payload.getChecksum(), ImageFormat.valueOf(payload.getFormat().toUpperCase()), callback); } CreateCmdResult result = new CreateCmdResult(null, null); diff --git a/plugins/storage/image/s3/pom.xml b/plugins/storage/image/s3/pom.xml index 7ab0d3e9301..7f5b9c4b333 100644 --- a/plugins/storage/image/s3/pom.xml +++ b/plugins/storage/image/s3/pom.xml @@ -32,6 +32,16 @@ cloud-engine-storage-image ${project.version} + + org.apache.cloudstack + cloud-engine-storage-volume + ${project.version} + + + org.apache.cloudstack + cloud-engine-storage-snapshot + ${project.version} + install diff --git a/plugins/storage/image/s3/src/org/apache/cloudstack/storage/datastore/driver/S3ImageStoreDriverImpl.java b/plugins/storage/image/s3/src/org/apache/cloudstack/storage/datastore/driver/S3ImageStoreDriverImpl.java index 0d84f589d83..50a82cc8793 100644 --- a/plugins/storage/image/s3/src/org/apache/cloudstack/storage/datastore/driver/S3ImageStoreDriverImpl.java +++ b/plugins/storage/image/s3/src/org/apache/cloudstack/storage/datastore/driver/S3ImageStoreDriverImpl.java @@ -35,6 +35,7 @@ import org.apache.cloudstack.framework.async.AsyncCompletionCallback; import org.apache.cloudstack.framework.async.AsyncRpcConext; import org.apache.cloudstack.storage.image.ImageStoreDriver; import org.apache.cloudstack.storage.image.store.TemplateObject; +import org.apache.cloudstack.storage.volume.VolumeObject; import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; @@ -118,11 +119,10 @@ public class S3ImageStoreDriverImpl implements ImageStoreDriver { TemplateObject tData = (TemplateObject)data; _downloadMonitor.downloadTemplateToStorage(tData.getImage(), tData.getDataStore(), callback); } else if (data.getType() == DataObjectType.VOLUME) { - VolumeVO vol = this.volumeDao.findById(data.getId()); - VolumeInfo volInfo = (VolumeInfo)data; + VolumeObject volInfo = (VolumeObject)data; RegisterVolumePayload payload = (RegisterVolumePayload)volInfo.getpayload(); - _downloadMonitor.downloadVolumeToStorage(vol, vol.getDataCenterId(), payload.getUrl(), - payload.getChecksum(), ImageFormat.valueOf(payload.getFormat().toUpperCase())); + _downloadMonitor.downloadVolumeToStorage(volInfo.getVolume(), volInfo.getDataStore(), payload.getUrl(), + payload.getChecksum(), ImageFormat.valueOf(payload.getFormat().toUpperCase()), callback); } CreateCmdResult result = new CreateCmdResult(null, null); diff --git a/plugins/storage/image/sample/pom.xml b/plugins/storage/image/sample/pom.xml index e4d5ac29ed8..d9eab9b45e5 100644 --- a/plugins/storage/image/sample/pom.xml +++ b/plugins/storage/image/sample/pom.xml @@ -25,6 +25,16 @@ cloud-engine-storage-image ${project.version} + + org.apache.cloudstack + cloud-engine-storage-volume + ${project.version} + + + org.apache.cloudstack + cloud-engine-storage-snapshot + ${project.version} + mysql mysql-connector-java diff --git a/plugins/storage/image/swift/pom.xml b/plugins/storage/image/swift/pom.xml index 27ebbe5c5e7..6254ccef6a6 100644 --- a/plugins/storage/image/swift/pom.xml +++ b/plugins/storage/image/swift/pom.xml @@ -25,6 +25,16 @@ cloud-engine-storage-image ${project.version} + + org.apache.cloudstack + cloud-engine-storage-volume + ${project.version} + + + org.apache.cloudstack + cloud-engine-storage-snapshot + ${project.version} + mysql mysql-connector-java diff --git a/plugins/storage/image/swift/src/org/apache/cloudstack/storage/datastore/driver/SwiftImageStoreDriverImpl.java b/plugins/storage/image/swift/src/org/apache/cloudstack/storage/datastore/driver/SwiftImageStoreDriverImpl.java index 36fd5fbbe0e..e539e5c6ba3 100644 --- a/plugins/storage/image/swift/src/org/apache/cloudstack/storage/datastore/driver/SwiftImageStoreDriverImpl.java +++ b/plugins/storage/image/swift/src/org/apache/cloudstack/storage/datastore/driver/SwiftImageStoreDriverImpl.java @@ -35,6 +35,7 @@ import org.apache.cloudstack.framework.async.AsyncCompletionCallback; import org.apache.cloudstack.framework.async.AsyncRpcConext; import org.apache.cloudstack.storage.image.ImageStoreDriver; import org.apache.cloudstack.storage.image.store.TemplateObject; +import org.apache.cloudstack.storage.volume.VolumeObject; import org.apache.log4j.Logger; import com.cloud.agent.AgentManager; @@ -118,11 +119,10 @@ public class SwiftImageStoreDriverImpl implements ImageStoreDriver { TemplateObject tData = (TemplateObject)data; _downloadMonitor.downloadTemplateToStorage(tData.getImage(), tData.getDataStore(), callback); } else if (data.getType() == DataObjectType.VOLUME) { - VolumeVO vol = this.volumeDao.findById(data.getId()); - VolumeInfo volInfo = (VolumeInfo)data; + VolumeObject volInfo = (VolumeObject)data; RegisterVolumePayload payload = (RegisterVolumePayload)volInfo.getpayload(); - _downloadMonitor.downloadVolumeToStorage(vol, vol.getDataCenterId(), payload.getUrl(), - payload.getChecksum(), ImageFormat.valueOf(payload.getFormat().toUpperCase())); + _downloadMonitor.downloadVolumeToStorage(volInfo.getVolume(), volInfo.getDataStore(), payload.getUrl(), + payload.getChecksum(), ImageFormat.valueOf(payload.getFormat().toUpperCase()), callback); } CreateCmdResult result = new CreateCmdResult(null, null); diff --git a/server/src/com/cloud/storage/StorageManagerImpl.java b/server/src/com/cloud/storage/StorageManagerImpl.java index 78b26bb69fd..3b1a768f0fe 100755 --- a/server/src/com/cloud/storage/StorageManagerImpl.java +++ b/server/src/com/cloud/storage/StorageManagerImpl.java @@ -1993,15 +1993,15 @@ public class StorageManagerImpl extends ManagerBase implements StorageManager, C _accountMgr.checkAccessAndSpecifyAuthority(UserContext.current().getCaller(), store.getDataCenterId()); // Verify that there are no live snapshot, template, volume on the image store to be deleted - List snapshots = _snapshotStoreDao.listLiveByStoreId(storeId); + List snapshots = _snapshotStoreDao.listByStoreId(storeId); if ( snapshots != null && snapshots.size() > 0 ){ throw new CloudRuntimeException("Cannot delete image store with active snapshots backup!"); } - List volumes = _volumeStoreDao.listLiveByStoreId(storeId); + List volumes = _volumeStoreDao.listByStoreId(storeId); if ( volumes != null && volumes.size() > 0 ){ throw new CloudRuntimeException("Cannot delete image store with active volumes backup!"); } - List templates = _templateStoreDao.listLiveByStoreId(storeId); + List templates = _templateStoreDao.listByStoreId(storeId); if ( templates != null && templates.size() > 0 ){ throw new CloudRuntimeException("Cannot delete image store with active templates backup!"); } diff --git a/server/src/com/cloud/storage/download/DownloadListener.java b/server/src/com/cloud/storage/download/DownloadListener.java index 8e979abdfd9..3eb223325cb 100755 --- a/server/src/com/cloud/storage/download/DownloadListener.java +++ b/server/src/com/cloud/storage/download/DownloadListener.java @@ -18,6 +18,7 @@ package com.cloud.storage.download; import java.util.Date; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Timer; import java.util.TimerTask; @@ -26,9 +27,15 @@ import javax.inject.Inject; import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult; 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.TemplateService; +import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; +import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService; +import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; import org.apache.cloudstack.framework.async.AsyncCompletionCallback; 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.log4j.Level; import org.apache.log4j.Logger; @@ -52,6 +59,8 @@ import com.cloud.exception.ConnectionException; import com.cloud.exception.ResourceAllocationException; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; +import com.cloud.hypervisor.Hypervisor.HypervisorType; +import com.cloud.resource.ResourceManager; import com.cloud.storage.Storage; import com.cloud.storage.StorageManager; import com.cloud.storage.VMTemplateHostVO; @@ -117,57 +126,68 @@ public class DownloadListener implements Listener { public static final String DOWNLOAD_ABANDONED=Status.ABANDONED.toString(); - private HostVO sserver; - private HostVO ssAgent; + private HostVO _sserver; + private HostVO _ssAgent; - private VMTemplateVO template; - private VolumeVO volume; - private boolean downloadActive = true; + private VMTemplateVO _template; + private VolumeVO _volume; + private boolean _downloadActive = true; - private VolumeHostDao volumeHostDao; + private VolumeHostDao _volumeHostDao; + private VolumeDataStoreDao _volumeStoreDao; private VolumeDao _volumeDao; private StorageManager _storageMgr; - private VMTemplateHostDao vmTemplateHostDao; + private VMTemplateHostDao _vmTemplateHostDao; private TemplateDataStoreDao _vmTemplateStoreDao; private VMTemplateDao _vmTemplateDao; private ResourceLimitService _resourceLimitMgr; private AccountManager _accountMgr; private AlertManager _alertMgr; - private final DownloadMonitorImpl downloadMonitor; + private final DownloadMonitorImpl _downloadMonitor; - private DownloadState currState; + private DownloadState _currState; - private DownloadCommand cmd; + private DownloadCommand _cmd; - private Timer timer; + private Timer _timer; - private StatusTask statusTask; - private TimeoutTask timeoutTask; - private Date lastUpdated = new Date(); - private String jobId; + private StatusTask _statusTask; + private TimeoutTask _timeoutTask; + private Date _lastUpdated = new Date(); + private String _jobId; - private final Map stateMap = new HashMap(); - private Long templateHostId; - private Long volumeHostId; + private final Map _stateMap = new HashMap(); + private Long _templateHostId; + private Long _volumeHostId; - private DataStore sstore; - private Long templateStoreId; - private AsyncCompletionCallback callback; + private DataStore _sstore; + private Long _templateStoreId; + private Long _volumeStoreId; + private AsyncCompletionCallback _callback; + + @Inject + private ResourceManager _resourceMgr; + @Inject + private TemplateService _imageSrv; + @Inject + private DataStoreManager _storeMgr; + @Inject + private VolumeService _volumeSrv; public DownloadListener(HostVO ssAgent, HostVO host, VMTemplateVO template, Timer _timer, VMTemplateHostDao dao, Long templHostId, DownloadMonitorImpl downloadMonitor, DownloadCommand cmd, VMTemplateDao templateDao, ResourceLimitService _resourceLimitMgr, AlertManager _alertMgr, AccountManager _accountMgr) { - this.ssAgent = ssAgent; - this.sserver = host; - this.template = template; - this.vmTemplateHostDao = dao; - this.downloadMonitor = downloadMonitor; - this.cmd = cmd; - this.templateHostId = templHostId; + this._ssAgent = ssAgent; + this._sserver = host; + this._template = template; + this._vmTemplateHostDao = dao; + this._downloadMonitor = downloadMonitor; + this._cmd = cmd; + this._templateHostId = templHostId; initStateMachine(); - this.currState=getState(Status.NOT_DOWNLOADED.toString()); - this.timer = _timer; - this.timeoutTask = new TimeoutTask(this); - this.timer.schedule(timeoutTask, 3*STATUS_POLL_INTERVAL); + this._currState=getState(Status.NOT_DOWNLOADED.toString()); + this._timer = _timer; + this._timeoutTask = new TimeoutTask(this); + this._timer.schedule(_timeoutTask, 3*STATUS_POLL_INTERVAL); this._vmTemplateDao = templateDao; this._resourceLimitMgr = _resourceLimitMgr; this._accountMgr = _accountMgr; @@ -177,63 +197,64 @@ public class DownloadListener implements Listener { // TODO: this constructor should be the one used for template only, remove other template constructor later public DownloadListener(HostVO ssAgent, DataStore store, VMTemplateVO template, Timer _timer, TemplateDataStoreDao dao, Long templStoreId, DownloadMonitorImpl downloadMonitor, DownloadCommand cmd, VMTemplateDao templateDao, ResourceLimitService _resourceLimitMgr, AlertManager _alertMgr, AccountManager _accountMgr, AsyncCompletionCallback callback) { - this.ssAgent = ssAgent; - this.sstore = store; - this.template = template; + this._ssAgent = ssAgent; + this._sstore = store; + this._template = template; this._vmTemplateStoreDao = dao; - this.downloadMonitor = downloadMonitor; - this.cmd = cmd; - this.templateStoreId = templStoreId; + this._downloadMonitor = downloadMonitor; + this._cmd = cmd; + this._templateStoreId = templStoreId; initStateMachine(); - this.currState=getState(Status.NOT_DOWNLOADED.toString()); - this.timer = _timer; - this.timeoutTask = new TimeoutTask(this); - this.timer.schedule(timeoutTask, 3*STATUS_POLL_INTERVAL); + this._currState=getState(Status.NOT_DOWNLOADED.toString()); + this._timer = _timer; + this._timeoutTask = new TimeoutTask(this); + this._timer.schedule(_timeoutTask, 3*STATUS_POLL_INTERVAL); this._vmTemplateDao = templateDao; this._resourceLimitMgr = _resourceLimitMgr; this._accountMgr = _accountMgr; this._alertMgr = _alertMgr; - this.callback = callback; + this._callback = callback; updateDatabase(Status.NOT_DOWNLOADED, ""); } - public DownloadListener(HostVO ssAgent, HostVO host, VolumeVO volume, Timer _timer, VolumeHostDao dao, Long volHostId, DownloadMonitorImpl downloadMonitor, DownloadCommand cmd, VolumeDao volumeDao, StorageManager storageMgr, ResourceLimitService _resourceLimitMgr, AlertManager _alertMgr, AccountManager _accountMgr) { - this.ssAgent = ssAgent; - this.sserver = host; - this.volume = volume; - this.volumeHostDao = dao; - this.downloadMonitor = downloadMonitor; - this.cmd = cmd; - this.volumeHostId = volHostId; + public DownloadListener(HostVO ssAgent, DataStore store, VolumeVO volume, Timer _timer, VolumeDataStoreDao dao, Long volStoreId, DownloadMonitorImpl downloadMonitor, DownloadCommand cmd, VolumeDao volumeDao, StorageManager storageMgr, ResourceLimitService _resourceLimitMgr, AlertManager _alertMgr, AccountManager _accountMgr, AsyncCompletionCallback callback) { + this._ssAgent = ssAgent; + this._sstore = store; + this._volume = volume; + this._volumeStoreDao = dao; + this._downloadMonitor = downloadMonitor; + this._cmd = cmd; + this._volumeStoreId = volStoreId; initStateMachine(); - this.currState=getState(Status.NOT_DOWNLOADED.toString()); - this.timer = _timer; - this.timeoutTask = new TimeoutTask(this); - this.timer.schedule(timeoutTask, 3*STATUS_POLL_INTERVAL); + this._currState=getState(Status.NOT_DOWNLOADED.toString()); + this._timer = _timer; + this._timeoutTask = new TimeoutTask(this); + this._timer.schedule(_timeoutTask, 3*STATUS_POLL_INTERVAL); this._volumeDao = volumeDao; this._storageMgr = storageMgr; this._resourceLimitMgr = _resourceLimitMgr; this._accountMgr = _accountMgr; this._alertMgr = _alertMgr; + this._callback = callback; updateDatabase(Status.NOT_DOWNLOADED, ""); } public void setCurrState(VMTemplateHostVO.Status currState) { - this.currState = getState(currState.toString()); + this._currState = getState(currState.toString()); } private void initStateMachine() { - stateMap.put(Status.NOT_DOWNLOADED.toString(), new NotDownloadedState(this)); - stateMap.put(Status.DOWNLOADED.toString(), new DownloadCompleteState(this)); - stateMap.put(Status.DOWNLOAD_ERROR.toString(), new DownloadErrorState(this)); - stateMap.put(Status.DOWNLOAD_IN_PROGRESS.toString(), new DownloadInProgressState(this)); - stateMap.put(Status.ABANDONED.toString(), new DownloadAbandonedState(this)); + _stateMap.put(Status.NOT_DOWNLOADED.toString(), new NotDownloadedState(this)); + _stateMap.put(Status.DOWNLOADED.toString(), new DownloadCompleteState(this)); + _stateMap.put(Status.DOWNLOAD_ERROR.toString(), new DownloadErrorState(this)); + _stateMap.put(Status.DOWNLOAD_IN_PROGRESS.toString(), new DownloadInProgressState(this)); + _stateMap.put(Status.ABANDONED.toString(), new DownloadAbandonedState(this)); } private DownloadState getState(String stateName) { - return stateMap.get(stateName); + return _stateMap.get(stateName); } public void sendCommand(RequestType reqType) { @@ -243,10 +264,10 @@ public class DownloadListener implements Listener { } try { DownloadProgressCommand dcmd = new DownloadProgressCommand(getCommand(), getJobId(), reqType); - if (template == null){ + if (_template == null){ dcmd.setResourceType(ResourceType.VOLUME); } - downloadMonitor.send(ssAgent.getId(), dcmd, this); + _downloadMonitor.send(_ssAgent.getId(), dcmd, this); } catch (AgentUnavailableException e) { s_logger.debug("Send command failed", e); setDisconnected(); @@ -264,63 +285,63 @@ public class DownloadListener implements Listener { } public void logDisconnect() { - if (template != null){ - s_logger.warn("Unable to monitor download progress of " + template.getName() + " at host " + sserver.getName()); + if (_template != null){ + s_logger.warn("Unable to monitor download progress of " + _template.getName() + " at host " + _sserver.getName()); }else { - s_logger.warn("Unable to monitor download progress of " + volume.getName() + " at host " + sserver.getName()); + s_logger.warn("Unable to monitor download progress of " + _volume.getName() + " at host " + _sserver.getName()); } } public synchronized void updateDatabase(Status state, String errorString) { - if (template != null){ - VMTemplateHostVO vo = vmTemplateHostDao.createForUpdate(); + if (_template != null){ + VMTemplateHostVO vo = _vmTemplateHostDao.createForUpdate(); vo.setDownloadState(state); vo.setLastUpdated(new Date()); vo.setErrorString(errorString); - vmTemplateHostDao.update(getTemplateHostId(), vo); + _vmTemplateHostDao.update(getTemplateHostId(), vo); }else { - VolumeHostVO vo = volumeHostDao.createForUpdate(); + VolumeHostVO vo = _volumeHostDao.createForUpdate(); vo.setDownloadState(state); vo.setLastUpdated(new Date()); vo.setErrorString(errorString); - volumeHostDao.update(getVolumeHostId(), vo); + _volumeHostDao.update(getVolumeHostId(), vo); } } public void log(String message, Level level) { - if (template != null){ - s_logger.log(level, message + ", template=" + template.getName() + " at host " + sserver.getName()); + if (_template != null){ + s_logger.log(level, message + ", template=" + _template.getName() + " at host " + _sserver.getName()); }else { - s_logger.log(level, message + ", volume=" + volume.getName() + " at host " + sserver.getName()); + s_logger.log(level, message + ", volume=" + _volume.getName() + " at host " + _sserver.getName()); } } private Long getTemplateHostId() { - if (templateHostId == null){ - VMTemplateHostVO templHost = vmTemplateHostDao.findByHostTemplate(sserver.getId(), template.getId()); - templateHostId = templHost.getId(); + if (_templateHostId == null){ + VMTemplateHostVO templHost = _vmTemplateHostDao.findByHostTemplate(_sserver.getId(), _template.getId()); + _templateHostId = templHost.getId(); } - return templateHostId; + return _templateHostId; } private Long getTemplateStoreId() { - if (templateStoreId == null){ - TemplateDataStoreVO templStore = _vmTemplateStoreDao.findByStoreTemplate(sstore.getId(), template.getId()); - templateStoreId = templStore.getId(); + if (_templateStoreId == null){ + TemplateDataStoreVO templStore = _vmTemplateStoreDao.findByStoreTemplate(_sstore.getId(), _template.getId()); + _templateStoreId = templStore.getId(); } - return templateStoreId; + return _templateStoreId; } private Long getVolumeHostId() { - if (volumeHostId == null){ - VolumeHostVO volHost = volumeHostDao.findByHostVolume(sserver.getId(), volume.getId()); - volumeHostId = volHost.getId(); + if (_volumeHostId == null){ + VolumeHostVO volHost = _volumeHostDao.findByHostVolume(_sserver.getId(), _volume.getId()); + _volumeHostId = volHost.getId(); } - return volumeHostId; + return _volumeHostId; } public DownloadListener(DownloadMonitorImpl monitor) { - downloadMonitor = monitor; + _downloadMonitor = monitor; } @@ -350,15 +371,15 @@ public class DownloadListener implements Listener { } private synchronized void transition(DownloadEvent event, Object evtObj) { - if (currState == null) { + if (_currState == null) { return; } - String prevName = currState.getName(); - String nextState = currState.handleEvent(event, evtObj); + String prevName = _currState.getName(); + String nextState = _currState.handleEvent(event, evtObj); if (nextState != null) { - currState = getState(nextState); - if (currState != null) { - currState.onEntry(prevName, event, evtObj); + _currState = getState(nextState); + if (_currState != null) { + _currState.onEntry(prevName, event, evtObj); } else { throw new CloudRuntimeException("Invalid next state: currState="+prevName+", evt="+event + ", next=" + nextState); } @@ -368,7 +389,7 @@ public class DownloadListener implements Listener { } public synchronized void updateDatabase(DownloadAnswer answer) { - if (template != null){ + if (_template != null){ TemplateDataStoreVO updateBuilder = _vmTemplateStoreDao.createForUpdate(); updateBuilder.setDownloadPercent(answer.getDownloadPct()); updateBuilder.setDownloadState(answer.getDownloadStatus()); @@ -380,40 +401,58 @@ public class DownloadListener implements Listener { updateBuilder.setSize(answer.getTemplateSize()); updateBuilder.setPhysicalSize(answer.getTemplatePhySicalSize()); + // only invoke callback when Download is completed or errored so that callback will update template_store_ref state column + Status dndStatus = answer.getDownloadStatus(); + // if (dndStatus == Status.DOWNLOAD_ERROR || dndStatus == Status.DOWNLOADED ){ + if ( _callback != null ){ + if (dndStatus == Status.DOWNLOAD_ERROR){ + CreateCmdResult result = new CreateCmdResult(null, null); + result.setSucess(false); + result.setResult("Download template failed"); + _callback.complete(result); + } else if (dndStatus == Status.DOWNLOADED){ + CreateCmdResult result = new CreateCmdResult(null, null); + _callback.complete(result); + } + } + else{ + // no callback specified, just update state here + if (dndStatus == Status.DOWNLOAD_ERROR){ + updateBuilder.setState(ObjectInDataStoreStateMachine.State.Failed); + } else if (dndStatus == Status.DOWNLOAD_IN_PROGRESS){ + updateBuilder.setState(ObjectInDataStoreStateMachine.State.Creating2); + } else if (dndStatus == Status.DOWNLOADED){ + updateBuilder.setState(ObjectInDataStoreStateMachine.State.Ready); + } + } + // } _vmTemplateStoreDao.update(getTemplateStoreId(), updateBuilder); if (answer.getCheckSum() != null) { VMTemplateVO templateDaoBuilder = _vmTemplateDao.createForUpdate(); templateDaoBuilder.setChecksum(answer.getCheckSum()); - _vmTemplateDao.update(template.getId(), templateDaoBuilder); + _vmTemplateDao.update(_template.getId(), templateDaoBuilder); } if (answer.getTemplateSize() > 0) { //long hostId = vmTemplateHostDao.findByTemplateId(template.getId()).getHostId(); - long accountId = template.getAccountId(); + long accountId = _template.getAccountId(); try { _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(accountId), com.cloud.configuration.Resource.ResourceType.secondary_storage, - answer.getTemplateSize() - UriUtils.getRemoteSize(template.getUrl())); + answer.getTemplateSize() - UriUtils.getRemoteSize(_template.getUrl())); } catch (ResourceAllocationException e) { s_logger.warn(e.getMessage()); - _alertMgr.sendAlert(_alertMgr.ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED, sserver.getDataCenterId(), + _alertMgr.sendAlert(_alertMgr.ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED, _sserver.getDataCenterId(), null, e.getMessage(), e.getMessage()); } finally { _resourceLimitMgr.recalculateResourceCount(accountId, _accountMgr.getAccount(accountId).getDomainId(), com.cloud.configuration.Resource.ResourceType.secondary_storage.getOrdinal()); } } - // only invoke callback when Download is completed or errored so that callback will update template_store_ref state column - Status dndStatus = answer.getDownloadStatus(); - if (dndStatus == Status.DOWNLOAD_ERROR || dndStatus == Status.DOWNLOADED ){ - if ( callback != null ){ - CreateCmdResult result = new CreateCmdResult(null, null); - callback.complete(result); - } - } + } else { - VolumeHostVO updateBuilder = volumeHostDao.createForUpdate(); + VolumeHostVO updateBuilder = _volumeHostDao.createForUpdate(); updateBuilder.setDownloadPercent(answer.getDownloadPct()); updateBuilder.setDownloadState(answer.getDownloadStatus()); updateBuilder.setLastUpdated(new Date()); @@ -424,25 +463,25 @@ public class DownloadListener implements Listener { updateBuilder.setSize(answer.getTemplateSize()); updateBuilder.setPhysicalSize(answer.getTemplatePhySicalSize()); - volumeHostDao.update(getVolumeHostId(), updateBuilder); + _volumeHostDao.update(getVolumeHostId(), updateBuilder); // Update volume size in Volume table. VolumeVO updateVolume = _volumeDao.createForUpdate(); updateVolume.setSize(answer.getTemplateSize()); - _volumeDao.update(volume.getId(), updateVolume); + _volumeDao.update(_volume.getId(), updateVolume); if (answer.getTemplateSize() > 0) { try { - String url = volumeHostDao.findByVolumeId(volume.getId()).getDownloadUrl(); - _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(volume.getAccountId()), + String url = _volumeHostDao.findByVolumeId(_volume.getId()).getDownloadUrl(); + _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(_volume.getAccountId()), com.cloud.configuration.Resource.ResourceType.secondary_storage, answer.getTemplateSize() - UriUtils.getRemoteSize(url)); } catch (ResourceAllocationException e) { s_logger.warn(e.getMessage()); - _alertMgr.sendAlert(_alertMgr.ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED, volume.getDataCenterId(), - volume.getPodId(), e.getMessage(), e.getMessage()); + _alertMgr.sendAlert(_alertMgr.ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED, _volume.getDataCenterId(), + _volume.getPodId(), e.getMessage(), e.getMessage()); } finally { - _resourceLimitMgr.recalculateResourceCount(volume.getAccountId(), volume.getDomainId(), + _resourceLimitMgr.recalculateResourceCount(_volume.getAccountId(), _volume.getDomainId(), com.cloud.configuration.Resource.ResourceType.secondary_storage.getOrdinal()); } } @@ -474,8 +513,12 @@ public class DownloadListener implements Listener { @Override public void processConnect(HostVO agent, StartupCommand cmd, boolean forRebalance) throws ConnectionException { if (cmd instanceof StartupRoutingCommand) { - - downloadMonitor.handleSysTemplateDownload(agent); + List hypers = _resourceMgr.listAvailHypervisorInZone(agent.getId(), agent.getDataCenterId()); + HypervisorType hostHyper = agent.getHypervisorType(); + if (hypers.contains(hostHyper)) { + return; + } + _imageSrv.handleSysTemplateDownload(hostHyper, agent.getDataCenterId()); } /* This can be removed since else if ( cmd instanceof StartupStorageCommand) { @@ -488,16 +531,20 @@ public class DownloadListener implements Listener { } }*/ else if ( cmd instanceof StartupSecondaryStorageCommand ) { - downloadMonitor.handleSync(agent.getDataCenterId()); + List imageStores = this._storeMgr.getImageStoresByScope(new ZoneScope(agent.getDataCenterId())); + for (DataStore store : imageStores){ + _volumeSrv.handleVolumeSync(store); + _imageSrv.handleTemplateSync(store); + } } } public void setCommand(DownloadCommand _cmd) { - this.cmd = _cmd; + this._cmd = _cmd; } public DownloadCommand getCommand() { - return cmd; + return _cmd; } @@ -506,63 +553,63 @@ public class DownloadListener implements Listener { } public void setJobId(String _jobId) { - this.jobId = _jobId; + this._jobId = _jobId; } public String getJobId() { - return jobId; + return _jobId; } public void scheduleStatusCheck(RequestType request) { - if (statusTask != null) statusTask.cancel(); + if (_statusTask != null) _statusTask.cancel(); - statusTask = new StatusTask(this, request); - timer.schedule(statusTask, STATUS_POLL_INTERVAL); + _statusTask = new StatusTask(this, request); + _timer.schedule(_statusTask, STATUS_POLL_INTERVAL); } public void scheduleTimeoutTask(long delay) { - if (timeoutTask != null) timeoutTask.cancel(); + if (_timeoutTask != null) _timeoutTask.cancel(); - timeoutTask = new TimeoutTask(this); - timer.schedule(timeoutTask, delay); + _timeoutTask = new TimeoutTask(this); + _timer.schedule(_timeoutTask, delay); if (s_logger.isDebugEnabled()) { log("Scheduling timeout at " + delay + " ms", Level.DEBUG); } } public void scheduleImmediateStatusCheck(RequestType request) { - if (statusTask != null) statusTask.cancel(); - statusTask = new StatusTask(this, request); - timer.schedule(statusTask, SMALL_DELAY); + if (_statusTask != null) _statusTask.cancel(); + _statusTask = new StatusTask(this, request); + _timer.schedule(_statusTask, SMALL_DELAY); } public boolean isDownloadActive() { - return downloadActive; + return _downloadActive; } public void cancelStatusTask() { - if (statusTask != null) statusTask.cancel(); + if (_statusTask != null) _statusTask.cancel(); } public Date getLastUpdated() { - return lastUpdated; + return _lastUpdated; } public void setLastUpdated() { - lastUpdated = new Date(); + _lastUpdated = new Date(); } public void setDownloadInactive(Status reason) { - downloadActive=false; - if (template != null){ - downloadMonitor.handleDownloadEvent(sserver, template, reason); + _downloadActive=false; + if (_template != null){ + _downloadMonitor.handleDownloadEvent(_sserver, _template, reason); }else { - downloadMonitor.handleDownloadEvent(sserver, volume, reason); + _downloadMonitor.handleDownloadEvent(_sserver, _volume, reason); } } public void cancelTimeoutTask() { - if (timeoutTask != null) timeoutTask.cancel(); + if (_timeoutTask != null) _timeoutTask.cancel(); } public void logDownloadStart() { diff --git a/server/src/com/cloud/storage/download/DownloadMonitor.java b/server/src/com/cloud/storage/download/DownloadMonitor.java index b20973352d5..b5a3f8592b9 100644 --- a/server/src/com/cloud/storage/download/DownloadMonitor.java +++ b/server/src/com/cloud/storage/download/DownloadMonitor.java @@ -16,8 +16,6 @@ // under the License. package com.cloud.storage.download; -import java.util.Map; - import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult; import org.apache.cloudstack.engine.subsystem.api.storage.DataStore; import org.apache.cloudstack.framework.async.AsyncCompletionCallback; @@ -28,7 +26,6 @@ import com.cloud.host.HostVO; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.VolumeVO; import com.cloud.storage.Storage.ImageFormat; -import com.cloud.storage.template.TemplateInfo; import com.cloud.utils.component.Manager; /** @@ -37,23 +34,17 @@ import com.cloud.utils.component.Manager; */ public interface DownloadMonitor extends Manager{ - public boolean downloadTemplateToStorage(VMTemplateVO template, DataStore store, AsyncCompletionCallback callback); + public void downloadTemplateToStorage(VMTemplateVO template, DataStore store, AsyncCompletionCallback callback); public void cancelAllDownloads(Long templateId); - public void handleTemplateSync(DataStore store); - public boolean copyTemplate(VMTemplateVO template, HostVO sourceServer, HostVO destServer) throws StorageUnavailableException; - void handleSysTemplateDownload(HostVO hostId); + //void addSystemVMTemplatesToHost(HostVO host, Map templateInfos); - void handleSync(Long dcId); + //public boolean downloadVolumeToStorage(VolumeVO volume, Long zoneId, String url, String checkSum, ImageFormat format); - void addSystemVMTemplatesToHost(HostVO host, Map templateInfos); - - boolean downloadVolumeToStorage(VolumeVO volume, Long zoneId, String url, String checkSum, ImageFormat format); - - void handleVolumeSync(HostVO ssHost); + public void downloadVolumeToStorage(VolumeVO volume, DataStore store, String url, String checkSum, ImageFormat format, AsyncCompletionCallback callback); } \ No newline at end of file diff --git a/server/src/com/cloud/storage/download/DownloadMonitorImpl.java b/server/src/com/cloud/storage/download/DownloadMonitorImpl.java index 82665e361a1..507d57531fe 100755 --- a/server/src/com/cloud/storage/download/DownloadMonitorImpl.java +++ b/server/src/com/cloud/storage/download/DownloadMonitorImpl.java @@ -18,12 +18,9 @@ package com.cloud.storage.download; import java.net.URI; import java.net.URISyntaxException; -import java.util.ArrayList; import java.util.Date; -import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.Timer; import java.util.concurrent.ConcurrentHashMap; @@ -33,19 +30,17 @@ import javax.inject.Inject; import org.apache.cloudstack.engine.subsystem.api.storage.CreateCmdResult; 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.ZoneScope; 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.log4j.Logger; import org.springframework.stereotype.Component; import com.cloud.agent.AgentManager; import com.cloud.agent.Listener; -import com.cloud.agent.api.Answer; import com.cloud.agent.api.Command; -import com.cloud.agent.api.storage.DeleteTemplateCommand; -import com.cloud.agent.api.storage.DeleteVolumeCommand; import com.cloud.agent.api.storage.DownloadCommand; import com.cloud.agent.api.storage.DownloadCommand.Proxy; @@ -53,16 +48,10 @@ import com.cloud.agent.api.storage.DownloadCommand.ResourceType; import com.cloud.agent.api.storage.DownloadProgressCommand.RequestType; import com.cloud.agent.api.storage.DownloadProgressCommand; -import com.cloud.agent.api.storage.ListTemplateAnswer; -import com.cloud.agent.api.storage.ListTemplateCommand; -import com.cloud.agent.api.storage.ListVolumeAnswer; -import com.cloud.agent.api.storage.ListVolumeCommand; - import com.cloud.agent.manager.Commands; import com.cloud.alert.AlertManager; import com.cloud.configuration.Config; import com.cloud.configuration.dao.ConfigurationDao; -import com.cloud.dc.DataCenterVO; import com.cloud.dc.dao.ClusterDao; import com.cloud.dc.dao.DataCenterDao; import com.cloud.event.EventTypes; @@ -70,9 +59,7 @@ import com.cloud.event.UsageEventUtils; import com.cloud.event.dao.UsageEventDao; import com.cloud.exception.AgentUnavailableException; import com.cloud.exception.InvalidParameterValueException; -import com.cloud.exception.ResourceAllocationException; import com.cloud.exception.StorageUnavailableException; -import com.cloud.host.Host; import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; @@ -80,12 +67,10 @@ import com.cloud.resource.ResourceManager; import com.cloud.storage.Storage.ImageFormat; import com.cloud.storage.StorageManager; -import com.cloud.storage.SwiftVO; import com.cloud.storage.VMTemplateHostVO; import com.cloud.storage.VMTemplateStorageResourceAssoc; import com.cloud.storage.VMTemplateVO; import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; -import com.cloud.storage.VMTemplateZoneVO; import com.cloud.storage.VolumeHostVO; import com.cloud.storage.VolumeVO; import com.cloud.storage.dao.StoragePoolHostDao; @@ -101,12 +86,10 @@ import com.cloud.storage.dao.VolumeHostDao; import com.cloud.storage.secondary.SecondaryStorageVmManager; import com.cloud.storage.swift.SwiftManager; import com.cloud.storage.template.TemplateConstants; -import com.cloud.storage.template.TemplateInfo; import com.cloud.template.TemplateManager; import com.cloud.user.Account; import com.cloud.user.AccountManager; import com.cloud.user.ResourceLimitService; -import com.cloud.utils.UriUtils; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.db.DB; import com.cloud.utils.db.JoinBuilder; @@ -117,14 +100,10 @@ import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.vm.SecondaryStorageVm; import com.cloud.vm.SecondaryStorageVmVO; import com.cloud.vm.UserVmManager; -import com.cloud.vm.UserVmVO; import com.cloud.vm.VirtualMachine.State; import com.cloud.vm.dao.SecondaryStorageVmDao; import com.cloud.vm.dao.UserVmDao; -import edu.emory.mathcs.backport.java.util.Collections; - -import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine; import org.apache.cloudstack.framework.async.AsyncCompletionCallback; @@ -152,6 +131,8 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor @Inject VolumeHostDao _volumeHostDao; @Inject + VolumeDataStoreDao _volumeStoreDao; + @Inject AlertManager _alertMgr; @Inject protected SwiftManager _swiftMgr; @@ -206,6 +187,7 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor final Map _listenerTemplateMap = new ConcurrentHashMap(); final Map _listenerMap = new ConcurrentHashMap(); final Map _listenerVolumeMap = new ConcurrentHashMap(); + final Map _listenerVolMap = new ConcurrentHashMap(); public void send(Long hostId, Command cmd, Listener listener) throws AgentUnavailableException { @@ -256,7 +238,7 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor public boolean isTemplateUpdateable(Long templateId, Long storeId) { List downloadsInProgress = - _vmTemplateStoreDao.listByTemplateStoreStatus(templateId, storeId, ObjectInDataStoreStateMachine.State.Creating, ObjectInDataStoreStateMachine.State.Creating2, ObjectInDataStoreStateMachine.State.Ready); + _vmTemplateStoreDao.listByTemplateStoreDownloadStatus(templateId, storeId, Status.DOWNLOAD_IN_PROGRESS, Status.DOWNLOADED ); return (downloadsInProgress.size() == 0); } @@ -370,7 +352,11 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor TemplateDataStoreVO vmTemplateStore = null; vmTemplateStore = _vmTemplateStoreDao.findByStoreTemplate(store.getId(), template.getId()); - // we should already persist one entry in template_store_ref table, so vmTemplateStore should not be null + if (vmTemplateStore == null) { + // This method can be invoked other places, for example, handleTemplateSync, in that case, vmTemplateStore may be null + vmTemplateStore = new TemplateDataStoreVO(store.getId(), template.getId(), new Date(), 0, VMTemplateStorageResourceAssoc.Status.NOT_DOWNLOADED, null, null, "jobid0000", null, template.getUrl()); + _vmTemplateStoreDao.persist(vmTemplateStore); + } else if ((vmTemplateStore.getJobId() != null) && (vmTemplateStore.getJobId().length() > 2)) { downloadJobExists = true; } @@ -420,42 +406,33 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor @Override - public boolean downloadTemplateToStorage(VMTemplateVO template, DataStore store, AsyncCompletionCallback callback) { + public void downloadTemplateToStorage(VMTemplateVO template, DataStore store, AsyncCompletionCallback callback) { long templateId = template.getId(); if (isTemplateUpdateable(templateId, store.getId())) { if ( template != null && template.getUrl() != null ){ initiateTemplateDownload(template, store, callback); } } - return true; } + @Override - public boolean downloadVolumeToStorage(VolumeVO volume, Long zoneId, String url, String checkSum, ImageFormat format) { - - List ssHosts = _ssvmMgr.listAllTypesSecondaryStorageHostsInOneZone(zoneId); - Collections.shuffle(ssHosts); - HostVO ssHost = ssHosts.get(0); - downloadVolumeToStorage(volume, ssHost, url, checkSum, format); - return true; - } - - private void downloadVolumeToStorage(VolumeVO volume, HostVO sserver, String url, String checkSum, ImageFormat format) { + public void downloadVolumeToStorage(VolumeVO volume, DataStore store, String url, String checkSum, ImageFormat format, AsyncCompletionCallback callback) { boolean downloadJobExists = false; - VolumeHostVO volumeHost = null; + VolumeDataStoreVO volumeHost = null; - volumeHost = _volumeHostDao.findByHostVolume(sserver.getId(), volume.getId()); + volumeHost = _volumeStoreDao.findByStoreVolume(store.getId(), volume.getId()); if (volumeHost == null) { - volumeHost = new VolumeHostVO(sserver.getId(), volume.getId(), sserver.getDataCenterId(), new Date(), 0, VMTemplateStorageResourceAssoc.Status.NOT_DOWNLOADED, null, null, + volumeHost = new VolumeDataStoreVO(store.getId(), volume.getId(), new Date(), 0, VMTemplateStorageResourceAssoc.Status.NOT_DOWNLOADED, null, null, "jobid0000", null, url, checkSum, format); - _volumeHostDao.persist(volumeHost); + _volumeStoreDao.persist(volumeHost); } else if ((volumeHost.getJobId() != null) && (volumeHost.getJobId().length() > 2)) { downloadJobExists = true; } Long maxVolumeSizeInBytes = getMaxVolumeSizeInBytes(); - String secUrl = sserver.getStorageUrl(); + String secUrl = store.getUri(); if(volumeHost != null) { start(); DownloadCommand dcmd = new DownloadCommand(secUrl, volume, maxVolumeSizeInBytes, checkSum, url, format); @@ -465,45 +442,35 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor dcmd.setResourceType(ResourceType.VOLUME); } - HostVO ssvm = _ssvmMgr.pickSsvmHost(sserver); - if( ssvm == null ) { - s_logger.warn("There is no secondary storage VM for secondary storage host " + sserver.getName()); + HostVO ssAhost = _ssvmMgr.pickSsvmHost(store); + if( ssAhost == null ) { + s_logger.warn("There is no secondary storage VM for image store " + store.getName()); return; } - DownloadListener dl = new DownloadListener(ssvm, sserver, volume, _timer, _volumeHostDao, volumeHost.getId(), - this, dcmd, _volumeDao, _storageMgr, _resourceLimitMgr, _alertMgr, _accountMgr); + DownloadListener dl = new DownloadListener(ssAhost, store, volume, _timer, _volumeStoreDao, volumeHost.getId(), + this, dcmd, _volumeDao, _storageMgr, _resourceLimitMgr, _alertMgr, _accountMgr, callback); if (downloadJobExists) { dl.setCurrState(volumeHost.getDownloadState()); } DownloadListener old = null; - synchronized (_listenerVolumeMap) { - old = _listenerVolumeMap.put(volumeHost, dl); + synchronized (_listenerVolMap) { + old = _listenerVolMap.put(volumeHost, dl); } if( old != null ) { old.abandon(); } try { - send(ssvm.getId(), dcmd, dl); + send(ssAhost.getId(), dcmd, dl); } catch (AgentUnavailableException e) { - s_logger.warn("Unable to start /resume download of volume " + volume.getName() + " to " + sserver.getName(), e); + s_logger.warn("Unable to start /resume download of volume " + volume.getName() + " to " + store.getName(), e); dl.setDisconnected(); dl.scheduleStatusCheck(RequestType.GET_OR_RESTART); } } } -/* - private void initiateTemplateDownload(Long templateId, DataStore store) { - VMTemplateVO template = _templateDao.findById(templateId); - if (template != null && (template.getUrl() != null)) { - //find all storage hosts and tell them to initiate download - downloadTemplateToStorage(template, store); - } - - } - */ @DB public void handleDownloadEvent(HostVO host, VMTemplateVO template, Status dnldStatus) { @@ -583,62 +550,18 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor txn.commit(); } - @Override - public void handleSysTemplateDownload(HostVO host) { - List hypers = _resourceMgr.listAvailHypervisorInZone(host.getId(), host.getDataCenterId()); - HypervisorType hostHyper = host.getHypervisorType(); - if (hypers.contains(hostHyper)) { - return; - } - - Set toBeDownloaded = new HashSet(); - List ssHosts = this.storeMgr.getImageStoresByScope(new ZoneScope(host.getDataCenterId())); - if (ssHosts == null || ssHosts.isEmpty()){ - return; - } - /* - List ssHosts = _resourceMgr.listAllUpAndEnabledHostsInOneZoneByType(Host.Type.SecondaryStorage, host.getDataCenterId()); - if (ssHosts == null || ssHosts.isEmpty()) { - return; - } - */ - /*Download all the templates in zone with the same hypervisortype*/ - for ( DataStore ssHost : ssHosts) { - List rtngTmplts = _templateDao.listAllSystemVMTemplates(); - List defaultBuiltin = _templateDao.listDefaultBuiltinTemplates(); - for (VMTemplateVO rtngTmplt : rtngTmplts) { - if (rtngTmplt.getHypervisorType() == hostHyper) { - toBeDownloaded.add(rtngTmplt); - } - } - - for (VMTemplateVO builtinTmplt : defaultBuiltin) { - if (builtinTmplt.getHypervisorType() == hostHyper) { - toBeDownloaded.add(builtinTmplt); - } - } - - for (VMTemplateVO template: toBeDownloaded) { - VMTemplateHostVO tmpltHost = _vmTemplateHostDao.findByHostTemplate(ssHost.getId(), template.getId()); - if (tmpltHost == null || tmpltHost.getDownloadState() != Status.DOWNLOADED) { - //TODO: pass callback here - initiateTemplateDownload(template, ssHost, null); - } - } - } - } - + /* @Override - public void addSystemVMTemplatesToHost(HostVO host, Map templateInfos){ + public void addSystemVMTemplatesToHost(HostVO host, Map templateInfos){ if ( templateInfos == null ) { return; } Long hostId = host.getId(); List rtngTmplts = _templateDao.listAllSystemVMTemplates(); for ( VMTemplateVO tmplt : rtngTmplts ) { - TemplateInfo tmpltInfo = templateInfos.get(tmplt.getUniqueName()); + TemplateProp tmpltInfo = templateInfos.get(tmplt.getUniqueName()); if ( tmpltInfo == null ) { continue; } @@ -651,354 +574,9 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor } } } + */ - @Override - public void handleSync(Long dcId) { - if (dcId != null) { - List ssHosts = _ssvmMgr.listSecondaryStorageHostsInOneZone(dcId); - for (HostVO ssHost : ssHosts) { - //handleTemplateSync(ssHost); - handleVolumeSync(ssHost); - } - } - List imageStores = this.storeMgr.getImageStoresByScope(new ZoneScope(dcId)); - for (DataStore store : imageStores){ - handleTemplateSync(store); - } - } - private Map listTemplate(DataStore ssHost) { - ListTemplateCommand cmd = new ListTemplateCommand(ssHost.getUri()); - HostVO ssAhost = _ssvmMgr.pickSsvmHost(ssHost); - Answer answer = _agentMgr.sendToSecStorage(ssAhost, cmd); - if (answer != null && answer.getResult()) { - ListTemplateAnswer tanswer = (ListTemplateAnswer)answer; - return tanswer.getTemplateInfo(); - } else { - if (s_logger.isDebugEnabled()) { - s_logger.debug("can not list template for secondary storage host " + ssHost.getId()); - } - } - - return null; - } - - private Map listVolume(HostVO ssHost) { - ListVolumeCommand cmd = new ListVolumeCommand(ssHost.getStorageUrl()); - Answer answer = _agentMgr.sendToSecStorage(ssHost, cmd); - if (answer != null && answer.getResult()) { - ListVolumeAnswer tanswer = (ListVolumeAnswer)answer; - return tanswer.getTemplateInfo(); - } else { - if (s_logger.isDebugEnabled()) { - s_logger.debug("Can not list volumes for secondary storage host " + ssHost.getId()); - } - } - - return null; - } - - private Map listTemplate(SwiftVO swift) { - if (swift == null) { - return null; - } - ListTemplateCommand cmd = new ListTemplateCommand(swift.toSwiftTO()); - Answer answer = _agentMgr.sendToSSVM(null, cmd); - if (answer != null && answer.getResult()) { - ListTemplateAnswer tanswer = (ListTemplateAnswer) answer; - return tanswer.getTemplateInfo(); - } else { - if (s_logger.isDebugEnabled()) { - s_logger.debug("can not list template for swift " + swift); - } - } - return null; - } - - @Override - public void handleVolumeSync(HostVO ssHost) { - if (ssHost == null) { - s_logger.warn("Huh? ssHost is null"); - return; - } - long sserverId = ssHost.getId(); - if (!(ssHost.getType() == Host.Type.SecondaryStorage || ssHost.getType() == Host.Type.LocalSecondaryStorage)) { - s_logger.warn("Huh? Agent id " + sserverId + " is not secondary storage host"); - return; - } - - Map volumeInfos = listVolume(ssHost); - if (volumeInfos == null) { - return; - } - - List dbVolumes = _volumeHostDao.listBySecStorage(sserverId); - List toBeDownloaded = new ArrayList(dbVolumes); - for (VolumeHostVO volumeHost : dbVolumes){ - VolumeVO volume = _volumeDao.findById(volumeHost.getVolumeId()); - //Exists then don't download - if (volumeInfos.containsKey(volume.getId())){ - TemplateInfo volInfo = volumeInfos.remove(volume.getId()); - toBeDownloaded.remove(volumeHost); - s_logger.info("Volume Sync found " + volume.getUuid() + " already in the volume host table"); - if (volumeHost.getDownloadState() != Status.DOWNLOADED) { - volumeHost.setErrorString(""); - } - if (volInfo.isCorrupted()) { - volumeHost.setDownloadState(Status.DOWNLOAD_ERROR); - String msg = "Volume " + volume.getUuid() + " is corrupted on secondary storage "; - volumeHost.setErrorString(msg); - s_logger.info("msg"); - if (volumeHost.getDownloadUrl() == null) { - msg = "Volume (" + volume.getUuid() + ") with install path " + volInfo.getInstallPath() + "is corrupted, please check in secondary storage: " + volumeHost.getHostId(); - s_logger.warn(msg); - } else { - toBeDownloaded.add(volumeHost); - } - - } else { // Put them in right status - volumeHost.setDownloadPercent(100); - volumeHost.setDownloadState(Status.DOWNLOADED); - volumeHost.setInstallPath(volInfo.getInstallPath()); - volumeHost.setSize(volInfo.getSize()); - volumeHost.setPhysicalSize(volInfo.getPhysicalSize()); - volumeHost.setLastUpdated(new Date()); - _volumeHostDao.update(volumeHost.getId(), volumeHost); - - if (volume.getSize() == 0) { - // Set volume size in volumes table - volume.setSize(volInfo.getSize()); - _volumeDao.update(volumeHost.getVolumeId(), volume); - } - - if (volInfo.getSize() > 0) { - try { - String url = _volumeHostDao.findByVolumeId(volume.getId()).getDownloadUrl(); - _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(volume.getAccountId()), - com.cloud.configuration.Resource.ResourceType.secondary_storage, - volInfo.getSize() - UriUtils.getRemoteSize(url)); - } catch (ResourceAllocationException e) { - s_logger.warn(e.getMessage()); - _alertMgr.sendAlert(_alertMgr.ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED, volume.getDataCenterId(), - volume.getPodId(), e.getMessage(), e.getMessage()); - } finally { - _resourceLimitMgr.recalculateResourceCount(volume.getAccountId(), volume.getDomainId(), - com.cloud.configuration.Resource.ResourceType.secondary_storage.getOrdinal()); - } - } - } - continue; - } - // Volume is not on secondary but we should download. - if (volumeHost.getDownloadState() != Status.DOWNLOADED) { - s_logger.info("Volume Sync did not find " + volume.getName() + " ready on server " + sserverId + ", will request download to start/resume shortly"); - toBeDownloaded.add(volumeHost); - } - } - - //Download volumes which haven't been downloaded yet. - if (toBeDownloaded.size() > 0) { - for (VolumeHostVO volumeHost : toBeDownloaded) { - if (volumeHost.getDownloadUrl() == null) { // If url is null we can't initiate the download - continue; - } - s_logger.debug("Volume " + volumeHost.getVolumeId() + " needs to be downloaded to " + ssHost.getName()); - downloadVolumeToStorage(_volumeDao.findById(volumeHost.getVolumeId()), ssHost, volumeHost.getDownloadUrl(), volumeHost.getChecksum(), volumeHost.getFormat()); - } - } - - //Delete volumes which are not present on DB. - for (Long uniqueName : volumeInfos.keySet()) { - TemplateInfo vInfo = volumeInfos.get(uniqueName); - DeleteVolumeCommand dtCommand = new DeleteVolumeCommand(ssHost.getStorageUrl(), vInfo.getInstallPath()); - try { - _agentMgr.sendToSecStorage(ssHost, dtCommand, null); - } catch (AgentUnavailableException e) { - String err = "Failed to delete " + vInfo.getTemplateName() + " on secondary storage " + sserverId + " which isn't in the database"; - s_logger.error(err); - return; - } - - String description = "Deleted volume " + vInfo.getTemplateName() + " on secondary storage " + sserverId + " since it isn't in the database"; - s_logger.info(description); - } - } - - @Override - public void handleTemplateSync(DataStore ssStore) { - if (ssStore == null) { - s_logger.warn("Huh? image store is null"); - return; - } - long storeId = ssStore.getId(); - Long zoneId = ssStore.getScope().getScopeId(); - - Map templateInfos = listTemplate(ssStore); - if (templateInfos == null) { - return; - } - - Set toBeDownloaded = new HashSet(); - List allTemplates = null; - if (zoneId == null){ - // region wide store - allTemplates = _templateDao.listAll(); - } - else{ - // zone wide store - allTemplates = _templateDao.listAllInZone(zoneId); - } - List rtngTmplts = _templateDao.listAllSystemVMTemplates(); - List defaultBuiltin = _templateDao.listDefaultBuiltinTemplates(); - - if (rtngTmplts != null) { - for (VMTemplateVO rtngTmplt : rtngTmplts) { - if (!allTemplates.contains(rtngTmplt)) { - allTemplates.add(rtngTmplt); - } - } - } - - if (defaultBuiltin != null) { - for (VMTemplateVO builtinTmplt : defaultBuiltin) { - if (!allTemplates.contains(builtinTmplt)) { - allTemplates.add(builtinTmplt); - } - } - } - - toBeDownloaded.addAll(allTemplates); - - for (VMTemplateVO tmplt : allTemplates) { - String uniqueName = tmplt.getUniqueName(); - TemplateDataStoreVO tmpltStore = _vmTemplateStoreDao.findByStoreTemplate(storeId, tmplt.getId()); - if (templateInfos.containsKey(uniqueName)) { - TemplateInfo tmpltInfo = templateInfos.remove(uniqueName); - toBeDownloaded.remove(tmplt); - if (tmpltStore != null) { - s_logger.info("Template Sync found " + uniqueName + " already in the template host table"); - if (tmpltStore.getDownloadState() != Status.DOWNLOADED) { - tmpltStore.setErrorString(""); - } - if (tmpltInfo.isCorrupted()) { - tmpltStore.setDownloadState(Status.DOWNLOAD_ERROR); - String msg = "Template " + tmplt.getName() + ":" + tmplt.getId() + " is corrupted on secondary storage " + tmpltStore.getId(); - tmpltStore.setErrorString(msg); - s_logger.info("msg"); - if (tmplt.getUrl() == null) { - msg = "Private Template (" + tmplt + ") with install path " + tmpltInfo.getInstallPath() + "is corrupted, please check in image store: " + tmpltStore.getDataStoreId(); - s_logger.warn(msg); - } else { - toBeDownloaded.add(tmplt); - } - - } else { - tmpltStore.setDownloadPercent(100); - tmpltStore.setDownloadState(Status.DOWNLOADED); - tmpltStore.setInstallPath(tmpltInfo.getInstallPath()); - tmpltStore.setSize(tmpltInfo.getSize()); - tmpltStore.setPhysicalSize(tmpltInfo.getPhysicalSize()); - tmpltStore.setLastUpdated(new Date()); - - if (tmpltInfo.getSize() > 0) { - long accountId = tmplt.getAccountId(); - try { - _resourceLimitMgr.checkResourceLimit(_accountMgr.getAccount(accountId), - com.cloud.configuration.Resource.ResourceType.secondary_storage, - tmpltInfo.getSize() - UriUtils.getRemoteSize(tmplt.getUrl())); - } catch (ResourceAllocationException e) { - s_logger.warn(e.getMessage()); - _alertMgr.sendAlert(_alertMgr.ALERT_TYPE_RESOURCE_LIMIT_EXCEEDED, zoneId, - null, e.getMessage(), e.getMessage()); - } finally { - _resourceLimitMgr.recalculateResourceCount(accountId, _accountMgr.getAccount(accountId).getDomainId(), - com.cloud.configuration.Resource.ResourceType.secondary_storage.getOrdinal()); - } - } - } - _vmTemplateStoreDao.update(tmpltStore.getId(), tmpltStore); - } else { - tmpltStore = new TemplateDataStoreVO(storeId, tmplt.getId(), new Date(), 100, Status.DOWNLOADED, null, null, null, tmpltInfo.getInstallPath(), tmplt.getUrl()); - tmpltStore.setSize(tmpltInfo.getSize()); - tmpltStore.setPhysicalSize(tmpltInfo.getPhysicalSize()); - _vmTemplateStoreDao.persist(tmpltStore); - this.associateTemplateToZone(tmplt.getId(), zoneId); - } - - continue; - } - if (tmpltStore != null && tmpltStore.getDownloadState() != Status.DOWNLOADED) { - s_logger.info("Template Sync did not find " + uniqueName + " ready on server " + storeId + ", will request download to start/resume shortly"); - - } else if (tmpltStore == null) { - s_logger.info("Template Sync did not find " + uniqueName + " on the server " + storeId + ", will request download shortly"); - TemplateDataStoreVO templtStore = new TemplateDataStoreVO(storeId, tmplt.getId(), new Date(), 0, Status.NOT_DOWNLOADED, null, null, null, null, tmplt.getUrl()); - _vmTemplateStoreDao.persist(templtStore); - this.associateTemplateToZone(tmplt.getId(), zoneId); - } - - } - - if (toBeDownloaded.size() > 0) { - /* Only download templates whose hypervirsor type is in the zone */ - List availHypers = _clusterDao.getAvailableHypervisorInZone(zoneId); - if (availHypers.isEmpty()) { - /* - * This is for cloudzone, local secondary storage resource - * started before cluster created - */ - availHypers.add(HypervisorType.KVM); - } - /* Baremetal need not to download any template */ - availHypers.remove(HypervisorType.BareMetal); - availHypers.add(HypervisorType.None); // bug 9809: resume ISO - // download. - for (VMTemplateVO tmplt : toBeDownloaded) { - if (tmplt.getUrl() == null) { // If url is null we can't - // initiate the download - continue; - } - // if this is private template, and there is no record for this - // template in this sHost, skip - if (!tmplt.isPublicTemplate() && !tmplt.isFeatured()) { - VMTemplateHostVO tmpltHost = _vmTemplateHostDao.findByHostTemplate(storeId, tmplt.getId()); - if (tmpltHost == null) { - continue; - } - } - if (availHypers.contains(tmplt.getHypervisorType())) { - if (_swiftMgr.isSwiftEnabled()) { - if (_swiftMgr.isTemplateInstalled(tmplt.getId())) { - continue; - } - } - s_logger.debug("Template " + tmplt.getName() + " needs to be downloaded to " + ssStore.getName()); - //TODO: we should pass a callback here - initiateTemplateDownload(tmplt, ssStore, null); - } - } - } - - for (String uniqueName : templateInfos.keySet()) { - TemplateInfo tInfo = templateInfos.get(uniqueName); - List userVmUsingIso = _userVmDao.listByIsoId(tInfo.getId()); - //check if there is any Vm using this ISO. - if (userVmUsingIso == null || userVmUsingIso.isEmpty()) { - DeleteTemplateCommand dtCommand = new DeleteTemplateCommand(ssStore.getUri(), tInfo.getInstallPath()); - try { - HostVO ssAhost = _ssvmMgr.pickSsvmHost(ssStore); - _agentMgr.sendToSecStorage(ssAhost, dtCommand, null); - } catch (AgentUnavailableException e) { - String err = "Failed to delete " + tInfo.getTemplateName() + " on secondary storage " + storeId + " which isn't in the database"; - s_logger.error(err); - return; - } - - String description = "Deleted template " + tInfo.getTemplateName() + " on secondary storage " + storeId + " since it isn't in the database"; - s_logger.info(description); - } - } - } @Override public void cancelAllDownloads(Long templateId) { @@ -1067,30 +645,6 @@ public class DownloadMonitorImpl extends ManagerBase implements DownloadMonitor } } - // persist entry in template_zone_ref table. zoneId can be empty for region-wide image store, in that case, - // we will associate the template to all the zones. - private void associateTemplateToZone(long templateId, Long zoneId){ - List dcs = new ArrayList(); - if (zoneId != null ){ - dcs.add(zoneId); - } - else{ - List zones = _dcDao.listAll(); - for (DataCenterVO zone : zones){ - dcs.add(zone.getId()); - } - } - for (Long id : dcs) { - VMTemplateZoneVO tmpltZoneVO = _vmTemplateZoneDao.findByZoneTemplate(id, templateId); - if (tmpltZoneVO == null) { - tmpltZoneVO = new VMTemplateZoneVO(id, templateId, new Date()); - _vmTemplateZoneDao.persist(tmpltZoneVO); - } else { - tmpltZoneVO.setLastUpdated(new Date()); - _vmTemplateZoneDao.update(tmpltZoneVO.getId(), tmpltZoneVO); - } - } - } } diff --git a/server/src/com/cloud/storage/resource/DummySecondaryStorageResource.java b/server/src/com/cloud/storage/resource/DummySecondaryStorageResource.java index 8f25514180c..02463d2f7dc 100644 --- a/server/src/com/cloud/storage/resource/DummySecondaryStorageResource.java +++ b/server/src/com/cloud/storage/resource/DummySecondaryStorageResource.java @@ -50,7 +50,7 @@ import com.cloud.storage.VMTemplateVO; import com.cloud.storage.Storage.StoragePoolType; import com.cloud.storage.dao.VMTemplateDao; import com.cloud.storage.template.TemplateConstants; -import com.cloud.storage.template.TemplateInfo; +import com.cloud.storage.template.TemplateProp; public class DummySecondaryStorageResource extends ServerResourceBase implements ServerResource { @@ -113,7 +113,7 @@ public class DummySecondaryStorageResource extends ServerResourceBase implements public StartupCommand[] initialize() { final StartupStorageCommand cmd = new StartupStorageCommand("dummy", StoragePoolType.NetworkFilesystem, 1024*1024*1024*100L, - new HashMap()); + new HashMap()); cmd.setResourceType(Storage.StorageResourceType.SECONDARY_STORAGE); cmd.setIqn(null); @@ -173,12 +173,12 @@ public class DummySecondaryStorageResource extends ServerResourceBase implements return _useServiceVm; } - public Map getDefaultSystemVmTemplateInfo() { + public Map getDefaultSystemVmTemplateInfo() { List tmplts = _tmpltDao.listAllSystemVMTemplates(); - Map tmpltInfo = new HashMap(); + Map tmpltInfo = new HashMap(); if (tmplts != null) { for (VMTemplateVO tmplt : tmplts) { - TemplateInfo routingInfo = new TemplateInfo(tmplt.getUniqueName(), TemplateConstants.DEFAULT_SYSTEM_VM_TEMPLATE_PATH + tmplt.getId() + File.separator, false, false); + TemplateProp routingInfo = new TemplateProp(tmplt.getUniqueName(), TemplateConstants.DEFAULT_SYSTEM_VM_TEMPLATE_PATH + tmplt.getId() + File.separator, false, false); tmpltInfo.put(tmplt.getUniqueName(), routingInfo); } } diff --git a/server/src/com/cloud/template/HypervisorTemplateAdapter.java b/server/src/com/cloud/template/HypervisorTemplateAdapter.java index 709288eca00..06cf6ac7fed 100755 --- a/server/src/com/cloud/template/HypervisorTemplateAdapter.java +++ b/server/src/com/cloud/template/HypervisorTemplateAdapter.java @@ -36,7 +36,7 @@ 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.TemplateService; import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; import org.apache.cloudstack.framework.async.AsyncCallFuture; import org.apache.log4j.Logger; @@ -75,7 +75,7 @@ public class HypervisorTemplateAdapter extends TemplateAdapterBase implements Te @Inject AgentManager _agentMgr; @Inject DataStoreManager storeMgr; - @Inject ImageService imageService; + @Inject TemplateService imageService; @Inject ImageDataFactory imageFactory; @Inject TemplateManager templateMgr; diff --git a/server/src/com/cloud/template/TemplateManager.java b/server/src/com/cloud/template/TemplateManager.java index 19ba3b52734..af5488076e6 100755 --- a/server/src/com/cloud/template/TemplateManager.java +++ b/server/src/com/cloud/template/TemplateManager.java @@ -35,7 +35,7 @@ import com.cloud.utils.Pair; /** * TemplateManager manages the templates stored on secondary storage. It is responsible for creating private/public templates. */ -public interface TemplateManager extends TemplateService{ +public interface TemplateManager extends TemplateApiService{ /** * Prepares a template for vm creation for a certain storage pool. diff --git a/server/src/com/cloud/template/TemplateManagerImpl.java b/server/src/com/cloud/template/TemplateManagerImpl.java index f4ad36e64ed..77c686073be 100755 --- a/server/src/com/cloud/template/TemplateManagerImpl.java +++ b/server/src/com/cloud/template/TemplateManagerImpl.java @@ -58,7 +58,7 @@ 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.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.TemplateInfo; @@ -187,8 +187,8 @@ import com.cloud.vm.dao.UserVmDao; import com.cloud.vm.dao.VMInstanceDao; @Component -@Local(value={TemplateManager.class, TemplateService.class}) -public class TemplateManagerImpl extends ManagerBase implements TemplateManager, TemplateService { +@Local(value={TemplateManager.class, TemplateApiService.class}) +public class TemplateManagerImpl extends ManagerBase implements TemplateManager, TemplateApiService { private final static Logger s_logger = Logger.getLogger(TemplateManagerImpl.class); @Inject VMTemplateDao _tmpltDao; @Inject VMTemplateHostDao _tmpltHostDao; @@ -246,7 +246,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager, @Inject SnapshotDataFactory snapshotFactory; @Inject - ImageService imageSvr; + TemplateService imageSvr; @Inject DataStoreManager dataStoreMgr; @Inject