diff --git a/core/src/com/cloud/storage/resource/LocalNfsSecondaryStorageResource.java b/core/src/com/cloud/storage/resource/LocalNfsSecondaryStorageResource.java index 282074c850c..3b55e092c2e 100644 --- a/core/src/com/cloud/storage/resource/LocalNfsSecondaryStorageResource.java +++ b/core/src/com/cloud/storage/resource/LocalNfsSecondaryStorageResource.java @@ -23,6 +23,7 @@ import com.cloud.agent.api.to.NfsTO; import com.cloud.agent.api.to.S3TO; import com.cloud.agent.api.to.SwiftTO; import com.cloud.storage.VMTemplateStorageResourceAssoc.Status; +import com.cloud.storage.template.DownloadManagerImpl; import com.cloud.utils.S3Utils; import com.cloud.utils.UriUtils; import com.cloud.utils.exception.CloudRuntimeException; @@ -31,12 +32,17 @@ import com.cloud.utils.exception.CloudRuntimeException; public class LocalNfsSecondaryStorageResource extends NfsSecondaryStorageResource { + public LocalNfsSecondaryStorageResource(){ + _dlMgr = new DownloadManagerImpl(); + } + @Override public Answer executeRequest(Command cmd) { if (cmd instanceof DownloadSystemTemplateCommand){ return execute((DownloadSystemTemplateCommand)cmd); } else { - return Answer.createUnsupportedCommandAnswer(cmd); + //return Answer.createUnsupportedCommandAnswer(cmd); + return super.executeRequest(cmd); } } diff --git a/core/src/com/cloud/storage/template/TemplateConstants.java b/core/src/com/cloud/storage/template/TemplateConstants.java index 5c6de986c17..7b376648b7a 100644 --- a/core/src/com/cloud/storage/template/TemplateConstants.java +++ b/core/src/com/cloud/storage/template/TemplateConstants.java @@ -18,17 +18,18 @@ package com.cloud.storage.template; public final class TemplateConstants { public static final String DEFAULT_TMPLT_ROOT_DIR = "template"; + public static final String DEFAULT_SNAPSHOT_ROOT_DIR = "snapshots"; public static final String DEFAULT_VOLUME_ROOT_DIR = "volumes"; public static final String DEFAULT_TMPLT_FIRST_LEVEL_DIR = "tmpl/"; - + public static final String DEFAULT_SYSTEM_VM_TEMPLATE_PATH = "template/tmpl/1/"; - + public static final String DEFAULT_SYSTEM_VM_TMPLT_NAME = "routing"; - + public static final int DEFAULT_TMPLT_COPY_PORT = 80; public static final String DEFAULT_TMPLT_COPY_INTF = "eth2"; - + public static final String DEFAULT_SSL_CERT_DOMAIN = "realhostip.com"; public static final String DEFAULT_HTTP_AUTH_USER = "cloud"; - + } diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/CloudStackTestNGBase.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/CloudStackTestNGBase.java index 3e9ae482858..40267a70c8a 100644 --- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/CloudStackTestNGBase.java +++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/CloudStackTestNGBase.java @@ -37,35 +37,42 @@ public class CloudStackTestNGBase extends AbstractTestNGSpringContextTests { private String primaryStorageUrl; private String secondaryStorage; private Transaction txn; - + + private String s3AccessKey; + private String s3SecretKey; + private String s3EndPoint; + private String s3TemplateBucket; + private boolean s3UseHttps; + protected void injectMockito() { - + } - + @BeforeMethod(alwaysRun = true) protected void injectDB(Method testMethod) throws Exception { txn = Transaction.open(testMethod.getName()); } - + @Test protected void injectMockitoTest() { injectMockito(); } - + @AfterMethod(alwaysRun = true) protected void closeDB(Method testMethod) throws Exception { if (txn != null) { txn.close(); } } - + @BeforeMethod(alwaysRun = true) - @Parameters({"devcloud-host-uuid", "devcloud-host-gateway", "devcloud-host-cidr", - "devcloud-host-ip", "template-url", "devcloud-local-storage-uuid", - "primary-storage-want-to-add", "devcloud-secondary-storage"}) - protected void setup(String hostuuid, String gateway, String cidr, + @Parameters({"devcloud-host-uuid", "devcloud-host-gateway", "devcloud-host-cidr", + "devcloud-host-ip", "template-url", "devcloud-local-storage-uuid", + "primary-storage-want-to-add", "devcloud-secondary-storage", "s3-accesskey", "s3-secretkey", "s3-endpoint", "s3-template-bucket", "s3-usehttps"}) + protected void setup(String hostuuid, String gateway, String cidr, String hostIp, String templateUrl, String localStorageUuid, - String primaryStorage, String secondaryStorage) { + String primaryStorage, String secondaryStorage, String s3_accessKey, String s3_secretKey, String s3_endpoint, String s3_template_bucket, + String s3_usehttps) { this.hostGuid = hostuuid; this.hostGateway = gateway; this.hostCidr = cidr; @@ -74,32 +81,38 @@ public class CloudStackTestNGBase extends AbstractTestNGSpringContextTests { this.localStorageUuid = localStorageUuid; this.primaryStorageUrl = primaryStorage; this.setSecondaryStorage(secondaryStorage); + // set S3 parameters + this.s3AccessKey = s3_accessKey; + this.s3SecretKey = s3_secretKey; + this.s3EndPoint = s3_endpoint; + this.s3TemplateBucket = s3_template_bucket; + this.s3UseHttps = Boolean.parseBoolean(s3_usehttps); } - + protected String getHostGuid() { return this.hostGuid; } - + protected String getHostGateway() { return this.hostGateway; } - + protected String getHostCidr() { return this.hostCidr; } - + protected String getHostIp() { return this.hostIp; } - + protected String getTemplateUrl() { return this.templateUrl; } - + protected String getLocalStorageUuid() { return this.localStorageUuid; } - + protected String getPrimaryStorageUrl() { return this.primaryStorageUrl; } @@ -111,4 +124,27 @@ public class CloudStackTestNGBase extends AbstractTestNGSpringContextTests { public void setSecondaryStorage(String secondaryStorage) { this.secondaryStorage = secondaryStorage; } + + public String getS3AccessKey() { + return s3AccessKey; + } + + public String getS3SecretKey() { + return s3SecretKey; + } + + public String getS3EndPoint() { + return s3EndPoint; + } + + public String getS3TemplateBucket() { + return s3TemplateBucket; + } + + public boolean isS3UseHttps() { + return s3UseHttps; + } + + + } diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/S3TemplateTest.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/S3TemplateTest.java new file mode 100644 index 00000000000..4d4d037de30 --- /dev/null +++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/S3TemplateTest.java @@ -0,0 +1,135 @@ +package org.apache.cloudstack.storage.test; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.ExecutionException; + +import javax.inject.Inject; + +import org.apache.cloudstack.api.ApiConstants; +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.EndPointSelector; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService; +import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService.TemplateApiResult; +import org.apache.cloudstack.framework.async.AsyncCallFuture; +import org.apache.cloudstack.storage.LocalHostEndpoint; +import org.apache.cloudstack.storage.datastore.db.ImageStoreDao; +import org.apache.cloudstack.storage.datastore.db.ImageStoreDetailVO; +import org.apache.cloudstack.storage.datastore.db.ImageStoreVO; +import org.apache.cloudstack.storage.image.datastore.ImageStoreHelper; +import org.mockito.Mockito; +import org.springframework.test.context.ContextConfiguration; +import org.testng.annotations.Test; +import static org.testng.Assert.assertTrue; +import com.cloud.dc.DataCenterVO; +import com.cloud.dc.DataCenter.NetworkType; +import com.cloud.dc.dao.DataCenterDao; +import com.cloud.storage.DataStoreRole; +import com.cloud.storage.ScopeType; +import com.cloud.storage.Storage; +import com.cloud.storage.VMTemplateVO; +import com.cloud.storage.Storage.TemplateType; +import com.cloud.storage.dao.VMTemplateDao; +import com.cloud.storage.download.DownloadMonitorImpl; +import com.cloud.utils.component.ComponentContext; + +@ContextConfiguration(locations={"classpath:/storageContext.xml"}) + +public class S3TemplateTest extends CloudStackTestNGBase { + @Inject + DataCenterDao dcDao; + ImageStoreVO imageStore; + ImageStoreDetailVO imageStoreDetail; + @Inject + ImageStoreDao imageStoreDao; + @Inject + TemplateService templateSvr; + @Inject + VMTemplateDao templateDao; + @Inject + TemplateDataFactory templateFactory; + @Inject + DataStoreManager dataStoreMgr; + @Inject + EndPointSelector epSelector; + @Inject + DownloadMonitorImpl downloadMonitor; + @Inject + ImageStoreHelper imageStoreHelper; + long dcId; + long templateId; + + @Test(priority = -1) + public void setUp() { + ComponentContext.initComponentsLifeCycle(); + //create data center + DataCenterVO dc = new DataCenterVO(UUID.randomUUID().toString(), "test", "8.8.8.8", null, "10.0.0.1", null, "10.0.0.1/24", + null, null, NetworkType.Basic, null, null, true, true, null, null); + dc = dcDao.persist(dc); + dcId = dc.getId(); + + + // add s3 image store + Map sParams = new HashMap(); + sParams.put("name", "test"); + sParams.put("protocol", "http"); + sParams.put("providerName", "S3"); + sParams.put("scope", ScopeType.REGION); + sParams.put("role", DataStoreRole.Image); + Map sDetails = new HashMap(); + sDetails.put(ApiConstants.S3_ACCESS_KEY, this.getS3AccessKey()); + sDetails.put(ApiConstants.S3_SECRET_KEY, this.getS3SecretKey()); + sDetails.put(ApiConstants.S3_BUCKET_NAME, this.getS3TemplateBucket()); + sDetails.put(ApiConstants.S3_END_POINT, this.getS3EndPoint()); + this.imageStoreHelper.createImageStore(sParams, sDetails); + + VMTemplateVO image = new VMTemplateVO(); + image.setTemplateType(TemplateType.SYSTEM); + image.setUrl(this.getTemplateUrl()); + image.setUniqueName(UUID.randomUUID().toString()); + image.setName(UUID.randomUUID().toString()); + image.setPublicTemplate(false); + image.setFeatured(false); + image.setRequiresHvm(false); + image.setBits(64); + image.setFormat(Storage.ImageFormat.VHD); + image.setEnablePassword(false); + image.setEnableSshKey(false); + image.setGuestOSId(133); + image.setBootable(true); + image.setPrepopulate(true); + image.setCrossZones(true); + image.setExtractable(true); + image = templateDao.persist(image); + templateId = image.getId(); + + Mockito.when(epSelector.select(Mockito.any(DataObject.class))).thenReturn(new LocalHostEndpoint()); + Mockito.when(epSelector.select(Mockito.any(DataStore.class))).thenReturn(new LocalHostEndpoint()); + } + + @Test + public void registerTemplate() { + TemplateInfo template = templateFactory.getTemplate(templateId); + DataStore store = dataStoreMgr.getImageStore(dcId); + AsyncCallFuture future = new AsyncCallFuture(); + templateSvr.createTemplateAsync(template, store, future); + try { + TemplateApiResult result = future.get(); + assertTrue(result.isSuccess(), "failed to register template: " + result.getResult()); + } catch (InterruptedException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + assertTrue(false, e.getMessage()); + } catch (ExecutionException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + assertTrue(false, e.getMessage()); + } + } + +} diff --git a/engine/storage/integration-test/test/resource/s3_testng.xml b/engine/storage/integration-test/test/resource/s3_testng.xml new file mode 100644 index 00000000000..017cc9ba2f0 --- /dev/null +++ b/engine/storage/integration-test/test/resource/s3_testng.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/engine/storage/integration-test/test/resource/testng.xml b/engine/storage/integration-test/test/resource/testng.xml index e3d8cd1c86e..55f7edf1e0b 100644 --- a/engine/storage/integration-test/test/resource/testng.xml +++ b/engine/storage/integration-test/test/resource/testng.xml @@ -23,11 +23,12 @@ - + + diff --git a/engine/storage/src/org/apache/cloudstack/storage/LocalHostEndpoint.java b/engine/storage/src/org/apache/cloudstack/storage/LocalHostEndpoint.java index 7660cf9dadd..37e15356b73 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/LocalHostEndpoint.java +++ b/engine/storage/src/org/apache/cloudstack/storage/LocalHostEndpoint.java @@ -14,6 +14,7 @@ import com.cloud.agent.api.Command; import com.cloud.agent.api.storage.DownloadAnswer; import com.cloud.agent.api.storage.DownloadCommand; import com.cloud.resource.ServerResource; +import com.cloud.storage.VMTemplateStorageResourceAssoc; import com.cloud.storage.download.DownloadListener; import com.cloud.storage.resource.LocalNfsSecondaryStorageResource; import com.cloud.utils.component.ComponentContext; @@ -69,8 +70,13 @@ public class LocalHostEndpoint implements EndPoint { } @Override public void run() { - DownloadAnswer answer = (DownloadAnswer)sendMessage(cmd); - callback.complete(answer); + try { + DownloadAnswer answer = (DownloadAnswer) sendMessage(cmd); + callback.complete(answer); + } catch (Exception ex) { + DownloadAnswer fail = new DownloadAnswer("Error in handling DownloadCommand : " + ex.getMessage(), VMTemplateStorageResourceAssoc.Status.DOWNLOAD_ERROR); + callback.complete(fail); + } } } @Override diff --git a/engine/storage/src/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManagerImpl.java b/engine/storage/src/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManagerImpl.java index 4cf813918d1..1d891e53ddc 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManagerImpl.java +++ b/engine/storage/src/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManagerImpl.java @@ -46,6 +46,7 @@ import com.cloud.storage.dao.SnapshotDao; import com.cloud.storage.dao.VMTemplateDao; import com.cloud.storage.dao.VMTemplatePoolDao; import com.cloud.storage.dao.VolumeDao; +import com.cloud.storage.template.TemplateConstants; import com.cloud.utils.db.SearchCriteria.Op; import com.cloud.utils.db.SearchCriteria2; import com.cloud.utils.db.SearchCriteriaService; @@ -120,9 +121,7 @@ public class ObjectInDataStoreManagerImpl implements ObjectInDataStoreManager { TemplateDataStoreVO ts = new TemplateDataStoreVO(); ts.setTemplateId(obj.getId()); ts.setDataStoreId(dataStore.getId()); - if (dataStore.getRole() == DataStoreRole.ImageCache) { - ts.setInstallPath("template/tmpl/" + templateDao.findById(obj.getId()).getAccountId() + "/" + obj.getId()); - } + ts.setInstallPath(TemplateConstants.DEFAULT_TMPLT_ROOT_DIR + "/" + TemplateConstants.DEFAULT_TMPLT_FIRST_LEVEL_DIR + templateDao.findById(obj.getId()).getAccountId() + "/" + obj.getId()); ts.setState(ObjectInDataStoreStateMachine.State.Allocated); ts = templateDataStoreDao.persist(ts); break; @@ -131,9 +130,7 @@ public class ObjectInDataStoreManagerImpl implements ObjectInDataStoreManager { ss.setSnapshotId(obj.getId()); ss.setDataStoreId(dataStore.getId()); ss.setRole(dataStore.getRole()); - if (dataStore.getRole() == DataStoreRole.ImageCache) { - ss.setInstallPath("/snapshots/" + snapshotDao.findById(obj.getId()).getAccountId() + "/" + obj.getId()); - } + ss.setInstallPath(TemplateConstants.DEFAULT_SNAPSHOT_ROOT_DIR + "/" + snapshotDao.findById(obj.getId()).getAccountId() + "/" + obj.getId()); ss.setState(ObjectInDataStoreStateMachine.State.Allocated); ss = snapshotDataStoreDao.persist(ss); break; @@ -141,9 +138,7 @@ public class ObjectInDataStoreManagerImpl implements ObjectInDataStoreManager { VolumeDataStoreVO vs = new VolumeDataStoreVO(); vs.setVolumeId(obj.getId()); vs.setDataStoreId(dataStore.getId()); - if (dataStore.getRole() == DataStoreRole.ImageCache) { - vs.setInstallPath("/volumes/" + volumeDao.findById(obj.getId()).getAccountId() + "/" + obj.getId()); - } + vs.setInstallPath(TemplateConstants.DEFAULT_VOLUME_ROOT_DIR + "/" + volumeDao.findById(obj.getId()).getAccountId() + "/" + obj.getId()); vs.setState(ObjectInDataStoreStateMachine.State.Allocated); vs = volumeDataStoreDao.persist(vs); break; diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageStoreHelper.java b/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageStoreHelper.java index f43bc4093f3..fe6e94f2853 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageStoreHelper.java +++ b/engine/storage/src/org/apache/cloudstack/storage/image/datastore/ImageStoreHelper.java @@ -20,6 +20,7 @@ package org.apache.cloudstack.storage.image.datastore; import java.util.Iterator; import java.util.Map; +import java.util.UUID; import javax.inject.Inject; @@ -51,7 +52,12 @@ public class ImageStoreHelper { store.setProtocol((String)params.get("protocol")); store.setProviderName((String)params.get("providerName")); store.setScope((ScopeType)params.get("scope")); - store.setUuid((String)params.get("uuid")); + String uuid = (String)params.get("uuid"); + if (uuid != null) { + store.setUuid(uuid); + } else { + store.setUuid(UUID.randomUUID().toString()); + } store.setUrl((String)params.get("url")); store.setRole(DataStoreRole.getRole((String)params.get("role"))); store = imageStoreDao.persist(store); @@ -69,7 +75,12 @@ public class ImageStoreHelper { store.setProviderName((String)params.get("providerName")); store.setScope((ScopeType)params.get("scope")); store.setDataCenterId((Long)params.get("zoneId")); - store.setUuid((String)params.get("uuid")); + String uuid = (String)params.get("uuid"); + if (uuid != null) { + store.setUuid(uuid); + } else { + store.setUuid(UUID.randomUUID().toString()); + } store.setUrl((String)params.get("url")); store.setRole((DataStoreRole)params.get("role")); store = imageStoreDao.persist(store); 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 8e1511c0b9e..c2e4c9c27bd 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 @@ -154,18 +154,11 @@ public class CloudStackImageStoreDriverImpl implements ImageStoreDriver { } } - private class createObjectContext extends AsyncRpcConext { - final DataObject data; - public createObjectContext(AsyncCompletionCallback callback, DataObject data) { - super(callback); - this.data = data; - } - } @Override public void createAsync(DataObject data, AsyncCompletionCallback callback) { - createObjectContext context = new createObjectContext(callback, data); + CreateContext context = new CreateContext(callback, data); AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); caller.setContext(context); @@ -184,7 +177,7 @@ public class CloudStackImageStoreDriverImpl implements ImageStoreDriver { } protected Void createAsyncCallback(AsyncCallbackDispatcher callback, - createObjectContext context) { + CreateContext context) { DownloadAnswer answer = callback.getResult(); DataObject obj = context.data; DataStore store = obj.getDataStore(); 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 384e7f010e3..31e2fdd6d58 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 @@ -18,6 +18,7 @@ */ package org.apache.cloudstack.storage.datastore.driver; +import java.util.Date; import java.util.List; import java.util.Map; import java.util.Set; @@ -35,6 +36,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.engine.subsystem.api.storage.DataTO; import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector; +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.db.ImageStoreDetailsDao; @@ -54,6 +56,7 @@ import com.cloud.agent.api.Answer; import com.cloud.agent.api.DeleteSnapshotBackupCommand; import com.cloud.agent.api.storage.DeleteTemplateCommand; import com.cloud.agent.api.storage.DeleteVolumeCommand; +import com.cloud.agent.api.storage.DownloadAnswer; import com.cloud.agent.api.to.DataStoreTO; import com.cloud.agent.api.to.S3TO; import com.cloud.agent.api.to.SwiftTO; @@ -136,10 +139,10 @@ public class S3ImageStoreDriverImpl implements ImageStoreDriver { details.get(ApiConstants.S3_SECRET_KEY), details.get(ApiConstants.S3_END_POINT), details.get(ApiConstants.S3_BUCKET_NAME), - Boolean.parseBoolean(details.get(ApiConstants.S3_HTTPS_FLAG)), - Integer.valueOf(details.get(ApiConstants.S3_CONNECTION_TIMEOUT)), - Integer.valueOf(details.get(ApiConstants.S3_MAX_ERROR_RETRY)), - Integer.valueOf(details.get(ApiConstants.S3_SOCKET_TIMEOUT)), + details.get(ApiConstants.S3_HTTPS_FLAG) == null ? false : Boolean.parseBoolean(details.get(ApiConstants.S3_HTTPS_FLAG)), + details.get(ApiConstants.S3_CONNECTION_TIMEOUT) == null ? null : Integer.valueOf(details.get(ApiConstants.S3_CONNECTION_TIMEOUT)), + details.get(ApiConstants.S3_MAX_ERROR_RETRY) == null ? null : Integer.valueOf(details.get(ApiConstants.S3_MAX_ERROR_RETRY)), + details.get(ApiConstants.S3_SOCKET_TIMEOUT) == null ? null : Integer.valueOf(details.get(ApiConstants.S3_SOCKET_TIMEOUT)), imgStore.getCreated()); } @@ -167,22 +170,26 @@ public class S3ImageStoreDriverImpl implements ImageStoreDriver { @Override public void createAsync(DataObject data, AsyncCompletionCallback callback) { + + CreateContext context = new CreateContext(callback, data); + AsyncCallbackDispatcher caller = + AsyncCallbackDispatcher.create(this); + caller.setContext(context); + caller.setCallback(caller.getTarget().createAsyncCallback(null, null)); + + if (data.getType() == DataObjectType.TEMPLATE) { TemplateObject tData = (TemplateObject)data; - _downloadMonitor.downloadTemplateToStorage(tData, tData.getDataStore(), null); + _downloadMonitor.downloadTemplateToStorage(tData, tData.getDataStore(), caller); } else if (data.getType() == DataObjectType.VOLUME) { VolumeObject volInfo = (VolumeObject)data; RegisterVolumePayload payload = (RegisterVolumePayload)volInfo.getpayload(); _downloadMonitor.downloadVolumeToStorage(volInfo, volInfo.getDataStore(), payload.getUrl(), - payload.getChecksum(), ImageFormat.valueOf(payload.getFormat().toUpperCase()), null); + payload.getChecksum(), ImageFormat.valueOf(payload.getFormat().toUpperCase()), caller); } - - CreateCmdResult result = new CreateCmdResult(null, null); - callback.complete(result); } private void deleteVolume(DataObject data, AsyncCompletionCallback callback) { - // TODO Auto-generated method stub VolumeVO vol = volumeDao.findById(data.getId()); if (s_logger.isDebugEnabled()) { s_logger.debug("Expunging " + vol); @@ -219,6 +226,48 @@ public class S3ImageStoreDriverImpl implements ImageStoreDriver { } } + + protected Void createAsyncCallback(AsyncCallbackDispatcher callback, + CreateContext context) { + DownloadAnswer answer = callback.getResult(); + DataObject obj = context.data; + DataStore store = obj.getDataStore(); + + TemplateDataStoreVO updateBuilder = _templateStoreDao.createForUpdate(); + updateBuilder.setDownloadPercent(answer.getDownloadPct()); + updateBuilder.setDownloadState(answer.getDownloadStatus()); + updateBuilder.setLastUpdated(new Date()); + updateBuilder.setErrorString(answer.getErrorString()); + updateBuilder.setJobId(answer.getJobId()); + updateBuilder.setLocalDownloadPath(answer.getDownloadPath()); + updateBuilder.setInstallPath(answer.getInstallPath()); + updateBuilder.setSize(answer.getTemplateSize()); + updateBuilder.setPhysicalSize(answer.getTemplatePhySicalSize()); + _templateStoreDao.update(store.getId(), updateBuilder); + + AsyncCompletionCallback caller = context.getParentCallback(); + + if (answer.getDownloadStatus() == VMTemplateStorageResourceAssoc.Status.DOWNLOAD_ERROR || + answer.getDownloadStatus() == VMTemplateStorageResourceAssoc.Status.ABANDONED || + answer.getDownloadStatus() == VMTemplateStorageResourceAssoc.Status.UNKNOWN) { + CreateCmdResult result = new CreateCmdResult(null, null); + result.setSucess(false); + result.setResult(answer.getErrorString()); + caller.complete(result); + } else if (answer.getDownloadStatus() == VMTemplateStorageResourceAssoc.Status.DOWNLOADED) { + if (answer.getCheckSum() != null) { + VMTemplateVO templateDaoBuilder = templateDao.createForUpdate(); + templateDaoBuilder.setChecksum(answer.getCheckSum()); + templateDao.update(obj.getId(), templateDaoBuilder); + } + + + CreateCmdResult result = new CreateCmdResult(null, null); + caller.complete(result); + } + return null; + } + private void deleteTemplate(DataObject data, AsyncCompletionCallback callback) { TemplateObject templateObj = (TemplateObject) data; VMTemplateVO template = templateObj.getImage(); 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 aa0f3755dd4..4f83d4b30a7 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 @@ -18,6 +18,7 @@ */ package org.apache.cloudstack.storage.datastore.driver; +import java.util.Date; import java.util.List; import java.util.Map; import java.util.Set; @@ -35,6 +36,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreManager; import org.apache.cloudstack.engine.subsystem.api.storage.DataTO; import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint; import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector; +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.db.ImageStoreDetailsDao; @@ -54,6 +56,7 @@ import com.cloud.agent.api.Answer; import com.cloud.agent.api.DeleteSnapshotBackupCommand; import com.cloud.agent.api.storage.DeleteTemplateCommand; import com.cloud.agent.api.storage.DeleteVolumeCommand; +import com.cloud.agent.api.storage.DownloadAnswer; import com.cloud.agent.api.to.DataStoreTO; import com.cloud.agent.api.to.S3TO; import com.cloud.agent.api.to.SwiftTO; @@ -161,18 +164,63 @@ public class SwiftImageStoreDriverImpl implements ImageStoreDriver { @Override public void createAsync(DataObject data, AsyncCompletionCallback callback) { + CreateContext context = new CreateContext(callback, data); + AsyncCallbackDispatcher caller = + AsyncCallbackDispatcher.create(this); + caller.setContext(context); + caller.setCallback(caller.getTarget().createAsyncCallback(null, null)); + + if (data.getType() == DataObjectType.TEMPLATE) { TemplateObject tData = (TemplateObject)data; - _downloadMonitor.downloadTemplateToStorage(tData, tData.getDataStore(), null); + _downloadMonitor.downloadTemplateToStorage(tData, tData.getDataStore(), caller); } else if (data.getType() == DataObjectType.VOLUME) { VolumeObject volInfo = (VolumeObject)data; RegisterVolumePayload payload = (RegisterVolumePayload)volInfo.getpayload(); _downloadMonitor.downloadVolumeToStorage(volInfo, volInfo.getDataStore(), payload.getUrl(), - payload.getChecksum(), ImageFormat.valueOf(payload.getFormat().toUpperCase()), null); + payload.getChecksum(), ImageFormat.valueOf(payload.getFormat().toUpperCase()), caller); } + } - CreateCmdResult result = new CreateCmdResult(null, null); - callback.complete(result); + protected Void createAsyncCallback(AsyncCallbackDispatcher callback, + CreateContext context) { + DownloadAnswer answer = callback.getResult(); + DataObject obj = context.data; + DataStore store = obj.getDataStore(); + + TemplateDataStoreVO updateBuilder = _templateStoreDao.createForUpdate(); + updateBuilder.setDownloadPercent(answer.getDownloadPct()); + updateBuilder.setDownloadState(answer.getDownloadStatus()); + updateBuilder.setLastUpdated(new Date()); + updateBuilder.setErrorString(answer.getErrorString()); + updateBuilder.setJobId(answer.getJobId()); + updateBuilder.setLocalDownloadPath(answer.getDownloadPath()); + updateBuilder.setInstallPath(answer.getInstallPath()); + updateBuilder.setSize(answer.getTemplateSize()); + updateBuilder.setPhysicalSize(answer.getTemplatePhySicalSize()); + _templateStoreDao.update(store.getId(), updateBuilder); + + AsyncCompletionCallback caller = context.getParentCallback(); + + if (answer.getDownloadStatus() == VMTemplateStorageResourceAssoc.Status.DOWNLOAD_ERROR || + answer.getDownloadStatus() == VMTemplateStorageResourceAssoc.Status.ABANDONED || + answer.getDownloadStatus() == VMTemplateStorageResourceAssoc.Status.UNKNOWN) { + CreateCmdResult result = new CreateCmdResult(null, null); + result.setSucess(false); + result.setResult(answer.getErrorString()); + caller.complete(result); + } else if (answer.getDownloadStatus() == VMTemplateStorageResourceAssoc.Status.DOWNLOADED) { + if (answer.getCheckSum() != null) { + VMTemplateVO templateDaoBuilder = templateDao.createForUpdate(); + templateDaoBuilder.setChecksum(answer.getCheckSum()); + templateDao.update(obj.getId(), templateDaoBuilder); + } + + + CreateCmdResult result = new CreateCmdResult(null, null); + caller.complete(result); + } + return null; } private void deleteVolume(DataObject data, AsyncCompletionCallback callback) { diff --git a/server/src/com/cloud/storage/download/DownloadListener.java b/server/src/com/cloud/storage/download/DownloadListener.java index a3f5bffd496..af5d771aef1 100755 --- a/server/src/com/cloud/storage/download/DownloadListener.java +++ b/server/src/com/cloud/storage/download/DownloadListener.java @@ -258,7 +258,9 @@ public class DownloadListener implements Listener { } public void callback(DownloadAnswer answer) { - this._callback.complete(answer); + if ( _callback != null ){ + this._callback.complete(answer); + } } @Override