diff --git a/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java b/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java index 384a41af4a0..03e822ebbe7 100755 --- a/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java +++ b/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java @@ -231,9 +231,7 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S } } - protected Answer copyFromS3ToNfs(CopyCommand cmd, DataTO srcData, S3TO s3, - - DataTO destData, NfsTO destImageStore) { + protected Answer copyFromS3ToNfs(CopyCommand cmd, DataTO srcData, S3TO s3, DataTO destData, NfsTO destImageStore) { final String storagePath = destImageStore.getUrl(); final String destPath = destData.getPath(); @@ -288,8 +286,8 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S return new CopyCmdAnswer(errMsg); } } - - + + protected Answer copySnapshotToTemplateFromNfsToNfsXenserver(CopyCommand cmd, SnapshotObjectTO srcData, NfsTO srcDataStore, TemplateObjectTO destData, NfsTO destDataStore) { String srcMountPoint = this.getRootDir(srcDataStore.getUrl()); String snapshotPath = srcData.getPath(); @@ -330,7 +328,7 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S loc.save(); TemplateObjectTO newTemplate = new TemplateObjectTO(); - newTemplate.setPath(destData.getPath() + File.separator + templateName); + newTemplate.setPath(destData.getPath() + File.separator + templateName); newTemplate.setFormat(ImageFormat.VHD); return new CopyCmdAnswer(newTemplate); } catch (ConfigurationException e) { @@ -346,16 +344,16 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S return new CopyCmdAnswer(errMsg); } - + protected Answer copySnapshotToTemplateFromNfsToNfs(CopyCommand cmd, SnapshotObjectTO srcData, NfsTO srcDataStore, TemplateObjectTO destData, NfsTO destDataStore) { - + if (srcData.getHypervisorType() == HypervisorType.XenServer) { return copySnapshotToTemplateFromNfsToNfsXenserver(cmd, srcData, srcDataStore, destData, destDataStore); } return new CopyCmdAnswer(""); } - + protected Answer createTemplateFromSnapshot(CopyCommand cmd) { DataTO srcData = cmd.getSrcTO(); DataTO destData = cmd.getDestTO(); @@ -366,7 +364,7 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S s_logger.debug("only support nfs storage as src, when create template from snapshot"); return Answer.createUnsupportedCommandAnswer(cmd); } - + if (destDataStore instanceof NfsTO){ return copySnapshotToTemplateFromNfsToNfs(cmd, (SnapshotObjectTO)srcData, (NfsTO)srcDataStore, (TemplateObjectTO)destData, (NfsTO)destDataStore); } @@ -380,12 +378,18 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S DataTO destData = cmd.getDestTO(); DataStoreTO srcDataStore = srcData.getDataStore(); DataStoreTO destDataStore = destData.getDataStore(); - + if (srcData.getObjectType() == DataObjectType.SNAPSHOT && destData.getObjectType() == DataObjectType.TEMPLATE) { return createTemplateFromSnapshot(cmd); } - + if (srcDataStore instanceof S3TO && destDataStore instanceof NfsTO && destDataStore.getRole() == DataStoreRole.ImageCache){ + S3TO s3 = (S3TO)srcDataStore; + NfsTO destImageStore = (NfsTO)destDataStore; + return this.copyFromS3ToNfs(cmd, srcData, s3, destData, destImageStore); + } + + return Answer.createUnsupportedCommandAnswer(cmd); } @@ -1729,7 +1733,7 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements S if (_configIpFirewallScr != null) { s_logger.info("_configIpFirewallScr found in " + _configIpFirewallScr); } - + createTemplateFromSnapshotXenScript = Script.findScript(getDefaultScriptsDir(), "create_privatetemplate_from_snapshot_xen.sh"); if (createTemplateFromSnapshotXenScript == null) { throw new ConfigurationException("create_privatetemplate_from_snapshot_xen.sh not found in " + getDefaultScriptsDir()); diff --git a/engine/api/src/org/apache/cloudstack/storage/datastore/db/ImageStoreDao.java b/engine/api/src/org/apache/cloudstack/storage/datastore/db/ImageStoreDao.java index 8d6acbdf011..bc6e0293d9b 100644 --- a/engine/api/src/org/apache/cloudstack/storage/datastore/db/ImageStoreDao.java +++ b/engine/api/src/org/apache/cloudstack/storage/datastore/db/ImageStoreDao.java @@ -30,5 +30,6 @@ public interface ImageStoreDao extends GenericDao { public ImageStoreVO findByName(String name); public List findByProvider(String provider); public List findByScope(ZoneScope scope); + public List findImageCacheByScope(ZoneScope scope); } diff --git a/engine/storage/cache/src/org/apache/cloudstack/storage/cache/manager/StorageCacheManagerImpl.java b/engine/storage/cache/src/org/apache/cloudstack/storage/cache/manager/StorageCacheManagerImpl.java index 1452e17a532..be1983e10eb 100644 --- a/engine/storage/cache/src/org/apache/cloudstack/storage/cache/manager/StorageCacheManagerImpl.java +++ b/engine/storage/cache/src/org/apache/cloudstack/storage/cache/manager/StorageCacheManagerImpl.java @@ -70,13 +70,13 @@ public class StorageCacheManagerImpl implements StorageCacheManager, Manager { @Override public void setName(String name) { // TODO Auto-generated method stub - + } @Override public void setConfigParams(Map params) { // TODO Auto-generated method stub - + } @Override @@ -94,7 +94,7 @@ public class StorageCacheManagerImpl implements StorageCacheManager, Manager { @Override public void setRunLevel(int level) { // TODO Auto-generated method stub - + } @Override @@ -113,9 +113,9 @@ public class StorageCacheManagerImpl implements StorageCacheManager, Manager { // TODO Auto-generated method stub return true; } - - + + private class CreateCacheObjectContext extends AsyncRpcConext { final AsyncCallFuture future; /** @@ -125,29 +125,34 @@ public class StorageCacheManagerImpl implements StorageCacheManager, Manager { super(callback); this.future = future; } - + } @Override public DataObject createCacheObject(DataObject data, Scope scope) { DataStore cacheStore = this.getCacheStorage(scope); DataObject objOnCacheStore = cacheStore.create(data); + AsyncCallFuture future = new AsyncCallFuture(); + /* CreateCacheObjectContext context = new CreateCacheObjectContext(null, future); - AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); + AsyncCallbackDispatcher caller = AsyncCallbackDispatcher.create(this); caller.setContext(context); - + caller.setCallback(future); + */ + CopyCommandResult result = null; try { objOnCacheStore.processEvent(Event.CreateOnlyRequested); - - dataMotionSvr.copyAsync(data, objOnCacheStore, caller); + + dataMotionSvr.copyAsync(data, objOnCacheStore, future); result = future.get(); - + if (result.isFailed()) { cacheStore.delete(data); } else { objOnCacheStore.processEvent(Event.OperationSuccessed, result.getAnswer()); + return objOnCacheStore; } } catch (InterruptedException e) { s_logger.debug("create cache storage failed: " + e.toString()); @@ -160,19 +165,19 @@ public class StorageCacheManagerImpl implements StorageCacheManager, Manager { cacheStore.delete(data); } } - + return null; } - + @Override public DataObject getCacheObject(DataObject data, Scope scope) { DataStore cacheStore = this.getCacheStorage(scope); DataObject objOnCacheStore = cacheStore.create(data); - + return objOnCacheStore; } - - protected Void createCacheObjectCallBack(AsyncCallbackDispatcher callback, + + protected Void createCacheObjectCallBack(AsyncCallbackDispatcher callback, CreateCacheObjectContext context) { AsyncCallFuture future = context.future; future.complete(callback.getResult()); diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/manager/ImageStoreProviderManagerImpl.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/manager/ImageStoreProviderManagerImpl.java index c14e2d91af6..a3dd930e1a8 100644 --- a/engine/storage/image/src/org/apache/cloudstack/storage/image/manager/ImageStoreProviderManagerImpl.java +++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/manager/ImageStoreProviderManagerImpl.java @@ -124,17 +124,13 @@ public class ImageStoreProviderManagerImpl implements ImageStoreProviderManager @Override public List listImageCacheStores(Scope scope) { - List imageStores = new ArrayList(); if (scope.getScopeType() != ScopeType.ZONE) { s_logger.debug("only support zone wide image cache stores"); - return imageStores; + return null; } - SearchCriteriaService sc = SearchCriteria2.create(ImageStoreVO.class); - sc.addAnd(sc.getEntity().getScope(), Op.EQ, ScopeType.ZONE); - sc.addAnd(sc.getEntity().getDataCenterId(), Op.EQ, scope.getScopeId()); - sc.addAnd(sc.getEntity().getRole(), Op.EQ, DataStoreRole.ImageCache); - List cacheStores = sc.list(); - for (ImageStoreVO store : cacheStores) { + List stores = dataStoreDao.findImageCacheByScope(new ZoneScope(scope.getScopeId())); + List imageStores = new ArrayList(); + for (ImageStoreVO store : stores) { imageStores.add(getImageStore(store.getId())); } return imageStores; diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/ImageStoreImpl.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/store/ImageStoreImpl.java index 638e1351947..5afe059616f 100644 --- a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/ImageStoreImpl.java +++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/store/ImageStoreImpl.java @@ -85,8 +85,7 @@ public class ImageStoreImpl implements ImageStoreEntity { @Override public DataStoreRole getRole() { - // TODO Auto-generated method stub - return DataStoreRole.Image; + return this.imageDataStoreVO.getRole(); } @Override public long getId() { diff --git a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java b/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java index 61a81255a3d..daf85681848 100644 --- a/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java +++ b/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java @@ -186,7 +186,7 @@ public class TemplateObject implements TemplateInfo { templEvent = TemplateEvent.OperationFailed; } - if (templEvent != null) { + if (templEvent != null && this.getDataStore().getRole() == DataStoreRole.Image) { this.stateTransit(templEvent); } } @@ -223,9 +223,11 @@ public class TemplateObject implements TemplateInfo { templateStoreRef.setDownloadPercent(100); templateStoreRef.setDownloadState(Status.DOWNLOADED); templateStoreDao.update(templateStoreRef.getId(), templateStoreRef); - VMTemplateVO templateVO = this.imageDao.findById(this.getId()); - templateVO.setFormat(newTemplate.getFormat()); - this.imageDao.update(templateVO.getId(), templateVO); + if (this.getDataStore().getRole() == DataStoreRole.Image) { + VMTemplateVO templateVO = this.imageDao.findById(this.getId()); + templateVO.setFormat(newTemplate.getFormat()); + this.imageDao.update(templateVO.getId(), templateVO); + } } TemplateEvent templEvent = null; @@ -239,7 +241,7 @@ public class TemplateObject implements TemplateInfo { templEvent = TemplateEvent.OperationFailed; } - if (templEvent != null) { + if (templEvent != null && this.getDataStore().getRole() == DataStoreRole.Image) { this.stateTransit(templEvent); } } diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/MockLocalNfsSecondaryStorageResource.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/MockLocalNfsSecondaryStorageResource.java index 0a460466036..d7a5d3fd1f5 100644 --- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/MockLocalNfsSecondaryStorageResource.java +++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/MockLocalNfsSecondaryStorageResource.java @@ -65,6 +65,11 @@ public class MockLocalNfsSecondaryStorageResource extends } + @Override + public String getRootDir(String secUrl){ + return "/mnt"; + } + @Override public Answer executeRequest(Command cmd) { if (cmd instanceof DownloadSystemTemplateCommand){ 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 index 5f29fde529e..8c4eae5cbf0 100644 --- 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 @@ -1,6 +1,5 @@ package org.apache.cloudstack.storage.test; -import java.util.Date; import java.util.HashMap; import java.util.Map; import java.util.UUID; @@ -12,11 +11,14 @@ 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.DataStoreProvider; import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector; +import org.apache.cloudstack.engine.subsystem.api.storage.StorageCacheManager; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateDataFactory; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService; import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService.TemplateApiResult; +import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope; import org.apache.cloudstack.framework.async.AsyncCallFuture; import org.apache.cloudstack.storage.LocalHostEndpoint; import org.apache.cloudstack.storage.MockLocalNfsSecondaryStorageResource; @@ -28,15 +30,14 @@ import org.mockito.Mockito; import org.springframework.test.context.ContextConfiguration; import org.testng.annotations.Test; import static org.testng.Assert.assertTrue; +import static org.testng.Assert.assertNotNull; import com.cloud.dc.DataCenterVO; import com.cloud.dc.DataCenter.NetworkType; import com.cloud.dc.dao.DataCenterDao; -import com.cloud.hypervisor.Hypervisor.HypervisorType; 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.ImageFormat; import com.cloud.storage.Storage.TemplateType; import com.cloud.storage.dao.VMTemplateDao; import com.cloud.storage.download.DownloadMonitorImpl; @@ -65,6 +66,8 @@ public class S3TemplateTest extends CloudStackTestNGBase { DownloadMonitorImpl downloadMonitor; @Inject ImageStoreHelper imageStoreHelper; + @Inject + StorageCacheManager cacheMgr; long dcId; long templateId; @@ -77,7 +80,6 @@ public class S3TemplateTest extends CloudStackTestNGBase { dc = dcDao.persist(dc); dcId = dc.getId(); - // add s3 image store Map sParams = new HashMap(); sParams.put("name", "test"); @@ -92,6 +94,17 @@ public class S3TemplateTest extends CloudStackTestNGBase { sDetails.put(ApiConstants.S3_END_POINT, this.getS3EndPoint()); this.imageStoreHelper.createImageStore(sParams, sDetails); + // add nfs cache storage + Map cParams = new HashMap(); + cParams.put("name", "testCache"); + cParams.put("protocol", "nfs"); + cParams.put("providerName", DataStoreProvider.NFS_IMAGE); + cParams.put("scope", ScopeType.ZONE); + cParams.put("role", DataStoreRole.ImageCache); + cParams.put("url", this.getSecondaryStorage()); + cParams.put("zoneId", dcId); + this.imageStoreHelper.createImageStore(cParams); + VMTemplateVO image = new VMTemplateVO(); image.setTemplateType(TemplateType.SYSTEM); @@ -119,9 +132,10 @@ public class S3TemplateTest extends CloudStackTestNGBase { ep.setResource(new MockLocalNfsSecondaryStorageResource()); Mockito.when(epSelector.select(Mockito.any(DataObject.class))).thenReturn(ep); Mockito.when(epSelector.select(Mockito.any(DataStore.class))).thenReturn(ep); + Mockito.when(epSelector.select(Mockito.any(DataObject.class), Mockito.any(DataObject.class))).thenReturn(ep); } - @Test + @Test(priority = 1) public void registerTemplate() { TemplateInfo template = templateFactory.getTemplate(templateId); DataStore store = dataStoreMgr.getImageStore(dcId); @@ -141,4 +155,11 @@ public class S3TemplateTest extends CloudStackTestNGBase { } } + @Test(priority = 2) + public void copyTemplateToCache() { + TemplateInfo template = templateFactory.getTemplate(templateId); + DataObject cacheObj = this.cacheMgr.createCacheObject(template, new ZoneScope(dcId)); + assertNotNull(cacheObj, "failed to create cache object"); + } + } 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 d0dfd55ff37..deb702f3571 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 @@ -48,18 +48,22 @@ public class ImageStoreHelper { return store; } store = new ImageStoreVO(); - store.setName((String)params.get("name")); store.setProtocol((String)params.get("protocol")); store.setProviderName((String)params.get("providerName")); store.setScope((ScopeType)params.get("scope")); + store.setDataCenterId((Long)params.get("zoneId")); String uuid = (String)params.get("uuid"); if (uuid != null) { store.setUuid(uuid); } else { store.setUuid(UUID.randomUUID().toString()); } + store.setName((String)params.get("name")); + if ( store.getName() == null ){ + store.setName(store.getUuid()); + } store.setUrl((String)params.get("url")); - store.setRole(DataStoreRole.getRole((String)params.get("role"))); + store.setRole((DataStoreRole)params.get("role")); store = imageStoreDao.persist(store); return store; } diff --git a/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageStoreDaoImpl.java b/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageStoreDaoImpl.java index 2300649bd86..06b286f5016 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageStoreDaoImpl.java +++ b/engine/storage/src/org/apache/cloudstack/storage/image/db/ImageStoreDaoImpl.java @@ -87,5 +87,13 @@ public class ImageStoreDaoImpl extends GenericDaoBase implem return listBy(sc); } + @Override + public List findImageCacheByScope(ZoneScope scope) { + SearchCriteria sc = createSearchCriteria(); + sc.addAnd("role", SearchCriteria.Op.EQ, DataStoreRole.ImageCache); + sc.addAnd("scope", SearchCriteria.Op.EQ, ScopeType.ZONE); + sc.addAnd("dcId", SearchCriteria.Op.EQ, scope.getScopeId()); + return listBy(sc); + } } 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 84c5ea53994..1865068ac55 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 @@ -126,7 +126,7 @@ public class CloudStackImageStoreDriverImpl implements ImageStoreDriver { public DataStoreTO getStoreTO(DataStore store) { ImageStoreImpl nfsStore = (ImageStoreImpl)store; NfsTO nfsTO = new NfsTO(); - nfsTO.setRole(DataStoreRole.Image); + nfsTO.setRole(store.getRole()); nfsTO.setUrl(nfsStore.getUri()); return nfsTO; }