cloudstack-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From edi...@apache.org
Subject [2/2] git commit: updated refs/heads/object_store to ac7be21
Date Wed, 08 May 2013 03:18:52 GMT
make create template from volume/snapshot work


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

Branch: refs/heads/object_store
Commit: 5aeca646ae18f620ea41ecbd8c1128aa1d1f30b2
Parents: ac1b75d
Author: Edison Su <sudison@gmail.com>
Authored: Tue May 7 17:46:10 2013 -0700
Committer: Edison Su <sudison@gmail.com>
Committed: Tue May 7 20:18:19 2013 -0700

----------------------------------------------------------------------
 .../resource/NfsSecondaryStorageResource.java      |  112 ++++++++++++--
 .../cloudstack/storage/to/SnapshotObjectTO.java    |   11 ++
 .../storage/motion/AncientDataMotionStrategy.java  |    2 +-
 .../storage/test/CloudStackTestNGBase.java         |    3 +
 .../cloudstack/storage/test/SnapshotTest.java      |   62 +++++++--
 .../cloudstack/storage/test/TemplateTest.java      |    2 +-
 .../apache/cloudstack/storage/test/VolumeTest.java |   51 +++++++
 .../storage/endpoint/DefaultEndPointSelector.java  |   19 ++-
 .../xen/resource/XenServerStorageResource.java     |   82 ++++++++++-
 .../create_privatetemplate_from_snapshot_xen.sh    |   98 +++++++++++++
 10 files changed, 404 insertions(+), 38 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/5aeca646/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java
----------------------------------------------------------------------
diff --git a/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java b/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java
index 48854df..e9ec839 100755
--- a/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java
+++ b/core/src/com/cloud/storage/resource/NfsSecondaryStorageResource.java
@@ -53,6 +53,7 @@ import org.apache.cloudstack.storage.command.CopyCommand;
 import org.apache.cloudstack.storage.command.DownloadCommand;
 import org.apache.cloudstack.storage.command.DownloadProgressCommand;
 import org.apache.cloudstack.storage.command.DownloadCommand.ResourceType;
+import org.apache.cloudstack.storage.to.SnapshotObjectTO;
 import org.apache.cloudstack.storage.to.TemplateObjectTO;
 import org.apache.commons.lang.StringUtils;
 import org.apache.log4j.Logger;
@@ -103,6 +104,7 @@ import com.cloud.agent.api.to.SwiftTO;
 import com.cloud.exception.InternalErrorException;
 import com.cloud.host.Host;
 import com.cloud.host.Host.Type;
+import com.cloud.hypervisor.Hypervisor.HypervisorType;
 import com.cloud.resource.ServerResourceBase;
 import com.cloud.storage.DataStoreRole;
 import com.cloud.storage.StorageLayer;
@@ -110,10 +112,14 @@ import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
 import com.cloud.storage.template.DownloadManager;
 import com.cloud.storage.template.DownloadManagerImpl;
 import com.cloud.storage.template.DownloadManagerImpl.ZfsPathParser;
+import com.cloud.storage.template.Processor.FormatInfo;
+import com.cloud.storage.template.Processor;
+import com.cloud.storage.template.QCOW2Processor;
 import com.cloud.storage.template.TemplateLocation;
 import com.cloud.storage.template.TemplateProp;
 import com.cloud.storage.template.UploadManager;
 import com.cloud.storage.template.UploadManagerImpl;
+import com.cloud.storage.template.VhdProcessor;
 import com.cloud.utils.NumbersUtil;
 import com.cloud.utils.S3Utils;
 import com.cloud.utils.S3Utils.FileNamingStrategy;
@@ -161,6 +167,7 @@ public class NfsSecondaryStorageResource extends ServerResourceBase implements
S
     final private String _parent = "/mnt/SecStorage";
     final private String _tmpltDir = "/var/cloudstack/template";
     final private String _tmpltpp = "template.properties";
+    private String createTemplateFromSnapshotXenScript;
 
     @Override
     public void disconnected() {
@@ -280,35 +287,103 @@ 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();
+        int index = snapshotPath.lastIndexOf("/");
+        String snapshotName = snapshotPath.substring(index + 1);
+        if (!snapshotName.startsWith("VHD-") && !snapshotName.endsWith(".vhd")) {
+            snapshotName = snapshotName + ".vhd";
+        }
+        snapshotPath = snapshotPath.substring(0, index);
+        snapshotPath = srcMountPoint + snapshotPath;
+        String destMountPoint = this.getRootDir(destDataStore.getUrl());
+        String destPath = destMountPoint + destData.getPath();
 
-    protected Answer copyFromSwiftToNfs(CopyCommand cmd, DataTO srcData, SwiftTO srcImageStore,
+        String errMsg = null;
+        try {
+            this._storage.mkdir(destPath);
+
+            String templateUuid = UUID.randomUUID().toString();
+            String templateName = templateUuid + ".vhd";
+            Script command = new Script(this.createTemplateFromSnapshotXenScript, cmd.getWait(),
s_logger);
+            command.add("-p", snapshotPath);
+            command.add("-s", snapshotName);
+            command.add("-n", templateName);
+            command.add("-t", destPath);
+            command.execute();
+
+            Map<String, Object> params = new HashMap<String, Object>();
+            params.put(StorageLayer.InstanceConfigKey, _storage);
+            Processor processor = new VhdProcessor();
+
+            processor.configure("Vhd Processor", params);
+            FormatInfo info = processor.process(destPath, null,
+                    templateUuid);
+
+            TemplateLocation loc = new TemplateLocation(_storage, destPath);
+            loc.create(1, true, templateName);
+            loc.addFormat(info);
+            loc.save();
+
+            TemplateObjectTO newTemplate = new TemplateObjectTO();
+            newTemplate.setPath(destData.getPath() + File.separator + templateUuid); 
+            return new CopyCmdAnswer(newTemplate);
+        } catch (ConfigurationException e) {
+            s_logger.debug("Failed to create template from snapshot: " + e.toString());
+            errMsg = e.toString();
+        } catch (InternalErrorException e) {
+            s_logger.debug("Failed to create template from snapshot: " + e.toString());
+            errMsg = e.toString();
+        } catch (IOException e) {
+            s_logger.debug("Failed to create template from snapshot: " + e.toString());
+            errMsg = e.toString();
+        }
 
-    DataTO destData, NfsTO destImageStore) {
-        return Answer.createUnsupportedCommandAnswer(cmd);
+        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);
+        }
 
-    protected Answer execute(CopyCommand cmd) {
+        return new CopyCmdAnswer("");
+    }
+    
+    protected Answer createTemplateFromSnapshot(CopyCommand cmd) {
         DataTO srcData = cmd.getSrcTO();
         DataTO destData = cmd.getDestTO();
         DataStoreTO srcDataStore = srcData.getDataStore();
         DataStoreTO destDataStore = destData.getDataStore();
-
-        if (srcDataStore.getRole() == DataStoreRole.Image && destDataStore.getRole()
== DataStoreRole.ImageCache) {
-
-            if (!(destDataStore instanceof NfsTO)) {
-                s_logger.debug("only support nfs as cache storage");
+        if (srcDataStore.getRole() == DataStoreRole.Image || srcDataStore.getRole() == DataStoreRole.ImageCache)
{
+            if (!(srcDataStore instanceof NfsTO)) {
+                s_logger.debug("only support nfs storage as src, when create template from
snapshot");
                 return Answer.createUnsupportedCommandAnswer(cmd);
             }
-
-            if (srcDataStore instanceof S3TO) {
-                return copyFromS3ToNfs(cmd, srcData, (S3TO) srcDataStore, destData, (NfsTO)
destDataStore);
-            } else if (srcDataStore instanceof SwiftTO) {
-                return copyFromSwiftToNfs(cmd, srcData, (SwiftTO) srcDataStore, destData,
(NfsTO) destDataStore);
-            } else {
-                return Answer.createUnsupportedCommandAnswer(cmd);
+        
+            if (destDataStore instanceof NfsTO){
+                return copySnapshotToTemplateFromNfsToNfs(cmd, (SnapshotObjectTO)srcData,
(NfsTO)srcDataStore, (TemplateObjectTO)destData, (NfsTO)destDataStore);
             }
 
         }
+        return new CopyCmdAnswer("");
+    }
+
+    protected Answer execute(CopyCommand cmd) {
+        DataTO srcData = cmd.getSrcTO();
+        DataTO destData = cmd.getDestTO();
+        DataStoreTO srcDataStore = srcData.getDataStore();
+        DataStoreTO destDataStore = destData.getDataStore();
+        
+        if (srcData.getObjectType() == DataObjectType.SNAPSHOT && destData.getObjectType()
== DataObjectType.TEMPLATE) {
+            return createTemplateFromSnapshot(cmd);
+        }
+
+     
         return Answer.createUnsupportedCommandAnswer(cmd);
     }
 
@@ -1652,6 +1727,11 @@ 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());
+        }
 
         _role = (String) params.get("role");
         if (_role == null)

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/5aeca646/engine/api/src/org/apache/cloudstack/storage/to/SnapshotObjectTO.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/storage/to/SnapshotObjectTO.java b/engine/api/src/org/apache/cloudstack/storage/to/SnapshotObjectTO.java
index 6d98045..ed4cbe1 100644
--- a/engine/api/src/org/apache/cloudstack/storage/to/SnapshotObjectTO.java
+++ b/engine/api/src/org/apache/cloudstack/storage/to/SnapshotObjectTO.java
@@ -5,6 +5,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
 import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
 
 import com.cloud.agent.api.to.DataStoreTO;
+import com.cloud.hypervisor.Hypervisor.HypervisorType;
 
 public class SnapshotObjectTO implements DataTO {
 	private String path;
@@ -13,6 +14,7 @@ public class SnapshotObjectTO implements DataTO {
 	private DataStoreTO dataStore;
 	private String vmName;
 	private String name;
+	private HypervisorType hypervisorType;
 	private long id;
 	
 	public SnapshotObjectTO() {
@@ -29,6 +31,7 @@ public class SnapshotObjectTO implements DataTO {
 	    }
 	    this.dataStore = snapshot.getDataStore().getTO();
 	    this.setName(snapshot.getName());
+	    this.hypervisorType = snapshot.getHypervisorType();
 	}
 	
 	@Override
@@ -89,4 +92,12 @@ public class SnapshotObjectTO implements DataTO {
     public void setName(String name) {
         this.name = name;
     }
+
+    public HypervisorType getHypervisorType() {
+        return hypervisorType;
+    }
+
+    public void setHypervisorType(HypervisorType hypervisorType) {
+        this.hypervisorType = hypervisorType;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/5aeca646/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
----------------------------------------------------------------------
diff --git a/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
b/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
index db3971c..560c34f 100644
--- a/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
+++ b/engine/storage/datamotion/src/org/apache/cloudstack/storage/motion/AncientDataMotionStrategy.java
@@ -327,7 +327,7 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
                         .parseInt(Config.CreatePrivateTemplateFromSnapshotWait
                                 .getDefaultValue()));
 
-        if (srcData.getDataStore().getRole() != DataStoreRole.ImageCache && destData.getDataStore().getRole()
!= DataStoreRole.ImageCache) {
+        if (needCacheStorage(srcData, destData)) {
             SnapshotInfo snapshot = (SnapshotInfo)srcData;
             srcData = cacheSnapshotChain(snapshot);
         }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/5aeca646/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/CloudStackTestNGBase.java
----------------------------------------------------------------------
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 8bf14f6..77b6ec3 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
@@ -94,6 +94,9 @@ public class CloudStackTestNGBase extends AbstractTestNGSpringContextTests
{
         this.s3TemplateBucket = s3_template_bucket;
         this.s3UseHttps = Boolean.parseBoolean(s3_usehttps);
         this.scriptPath = scriptPath;
+        if (this.scriptPath != null) {
+            System.setProperty("paths.script", this.getScriptPath());
+        }
     }
 
     protected String getHostGuid() {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/5aeca646/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/SnapshotTest.java
----------------------------------------------------------------------
diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/SnapshotTest.java
b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/SnapshotTest.java
index 203f762..9dc6854 100644
--- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/SnapshotTest.java
+++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/SnapshotTest.java
@@ -29,6 +29,7 @@ import javax.inject.Inject;
 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.DataStoreProviderManager;
 import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
 import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory;
@@ -45,6 +46,8 @@ import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreState
 import org.apache.cloudstack.engine.subsystem.api.storage.VolumeService.VolumeApiResult;
 import org.apache.cloudstack.engine.subsystem.api.storage.type.RootDisk;
 import org.apache.cloudstack.framework.async.AsyncCallFuture;
+import org.apache.cloudstack.storage.LocalHostEndpoint;
+import org.apache.cloudstack.storage.MockLocalNfsSecondaryStorageResource;
 import org.apache.cloudstack.storage.RemoteHostEndPoint;
 import org.apache.cloudstack.storage.command.CopyCmdAnswer;
 import org.apache.cloudstack.storage.datastore.db.ImageStoreDao;
@@ -144,6 +147,7 @@ public class SnapshotTest extends CloudStackTestNGBase {
     SnapshotDao snapshotDao;
     @Inject
     EndPointSelector epSelector;
+
     long primaryStoreId;
     VMTemplateVO image;
     String imageStoreName = "testImageStore";
@@ -196,7 +200,7 @@ public class SnapshotTest extends CloudStackTestNGBase {
             imageStore = new ImageStoreVO();
             imageStore.setName(imageStoreName);
             imageStore.setDataCenterId(dcId);
-            imageStore.setProviderName("CloudStack ImageStore Provider");
+            imageStore.setProviderName(DataStoreProvider.NFS_IMAGE);
             imageStore.setRole(DataStoreRole.Image);
             imageStore.setUrl(this.getSecondaryStorage());
             imageStore.setUuid(UUID.randomUUID().toString());
@@ -301,7 +305,7 @@ public class SnapshotTest extends CloudStackTestNGBase {
             pool.setPoolType(StoragePoolType.NetworkFilesystem);
             pool.setPodId(podId);
             pool.setScope(ScopeType.CLUSTER);
-            pool.setStorageProviderName("cloudstack primary data store provider");
+            pool.setStorageProviderName(DataStoreProvider.DEFAULT_PRIMARY);
             pool = this.primaryStoreDao.persist(pool);
             DataStore store = this.dataStoreMgr.getPrimaryDataStore(pool.getId());
             return store;
@@ -359,15 +363,49 @@ public class SnapshotTest extends CloudStackTestNGBase {
             }
         }
     }
-
-    //@Test
-    public void testCreateDataDisk() {
-        DataStore primaryStore = createPrimaryDataStore();
-        primaryStoreId = primaryStore.getId();
-        primaryStore = this.dataStoreMgr.getPrimaryDataStore(primaryStoreId);
-        VolumeVO volume = createVolume(null, primaryStore.getId());
-        VolumeInfo volInfo = this.volFactory.getVolume(volume.getId());
-        this.volumeService.createVolumeAsync(volInfo, primaryStore);
+    
+    private VMTemplateVO createTemplateInDb() {
+        image = new VMTemplateVO();
+        image.setTemplateType(TemplateType.USER);
+      
+        image.setUniqueName(UUID.randomUUID().toString());
+        image.setName(UUID.randomUUID().toString());
+        image.setPublicTemplate(true);
+        image.setFeatured(true);
+        image.setRequiresHvm(true);
+        image.setBits(64);
+        image.setFormat(Storage.ImageFormat.VHD);
+        image.setEnablePassword(true);
+        image.setEnableSshKey(true);
+        image.setGuestOSId(1);
+        image.setBootable(true);
+        image.setPrepopulate(true);
+        image.setCrossZones(true);
+        image.setExtractable(true);
+        image = imageDataDao.persist(image);
+        return image;
+    }
+    
+    @Test
+    public void createTemplateFromSnapshot() {
+        VolumeInfo vol = createCopyBaseImage();
+        SnapshotVO snapshotVO = createSnapshotInDb(vol);
+        SnapshotInfo snapshot = this.snapshotFactory.getSnapshot(snapshotVO.getId(), vol.getDataStore());
+        boolean result = false;
+        for (SnapshotStrategy strategy : this.snapshotStrategies) {
+            if (strategy.canHandle(snapshot)) {
+                snapshot = strategy.takeSnapshot(snapshot);
+                result = true;
+            }
+        }
+        
+        AssertJUnit.assertTrue(result);
+        LocalHostEndpoint ep = new LocalHostEndpoint();
+        ep.setResource(new MockLocalNfsSecondaryStorageResource());
+        Mockito.when(epSelector.select(Mockito.any(DataObject.class), Mockito.any(DataObject.class))).thenReturn(ep);
+        VMTemplateVO templateVO = createTemplateInDb();
+        TemplateInfo tmpl = this.templateFactory.getTemplate(templateVO.getId());
+        DataStore imageStore = this.dataStoreMgr.getImageStore(this.dcId);
+        this.imageService.createTemplateFromSnapshotAsync(snapshot, tmpl, imageStore);
     }
-
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/5aeca646/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/TemplateTest.java
----------------------------------------------------------------------
diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/TemplateTest.java
b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/TemplateTest.java
index 3ef1b54..294d4b5 100644
--- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/TemplateTest.java
+++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/TemplateTest.java
@@ -68,7 +68,7 @@ public class TemplateTest extends CloudStackTestNGBase {
 	@Test(priority = -1)
 	public void setUp() {
 		ComponentContext.initComponentsLifeCycle();
-	      System.setProperty("paths.script", this.getScriptPath());
+	     
 		//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);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/5aeca646/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/VolumeTest.java
----------------------------------------------------------------------
diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/VolumeTest.java
b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/VolumeTest.java
index 0171545..a354959 100644
--- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/VolumeTest.java
+++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/VolumeTest.java
@@ -379,4 +379,55 @@ public class VolumeTest extends CloudStackTestNGBase {
         }
         
     }
+    
+    private VMTemplateVO createTemplateInDb() {
+        image = new VMTemplateVO();
+        image.setTemplateType(TemplateType.USER);
+      
+        image.setUniqueName(UUID.randomUUID().toString());
+        image.setName(UUID.randomUUID().toString());
+        image.setPublicTemplate(true);
+        image.setFeatured(true);
+        image.setRequiresHvm(true);
+        image.setBits(64);
+        image.setFormat(Storage.ImageFormat.VHD);
+        image.setEnablePassword(true);
+        image.setEnableSshKey(true);
+        image.setGuestOSId(1);
+        image.setBootable(true);
+        image.setPrepopulate(true);
+        image.setCrossZones(true);
+        image.setExtractable(true);
+        image = imageDataDao.persist(image);
+        return image;
+    }
+    
+    @Test
+    public void testCreateTemplateFromVolume() {
+        DataStore primaryStore = createPrimaryDataStore();
+        primaryStoreId = primaryStore.getId();
+        primaryStore = this.dataStoreMgr.getPrimaryDataStore(primaryStoreId);
+        VolumeVO volume = createVolume(null, primaryStore.getId());
+        VolumeInfo volInfo = this.volFactory.getVolume(volume.getId());
+        AsyncCallFuture<VolumeApiResult> future = this.volumeService.createVolumeAsync(volInfo,
primaryStore);
+        try {
+            VolumeApiResult result = future.get();
+            
+            AssertJUnit.assertTrue(result.isSuccess());
+            volInfo = result.getVolume();
+            VMTemplateVO templateVO = createTemplateInDb();
+            TemplateInfo tmpl = this.templateFactory.getTemplate(templateVO.getId());
+            DataStore imageStore = this.dataStoreMgr.getImageStore(this.dcId);
+            
+            this.imageService.createTemplateFromVolumeAsync(volInfo, tmpl, imageStore);
+        } catch (InterruptedException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        } catch (ExecutionException e) {
+            // TODO Auto-generated catch block
+            e.printStackTrace();
+        }
+        
+        
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/5aeca646/engine/storage/src/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java
----------------------------------------------------------------------
diff --git a/engine/storage/src/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java
b/engine/storage/src/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java
index 5b22301..54059f2 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java
@@ -83,6 +83,16 @@ public class DefaultEndPointSelector implements EndPointSelector {
         	  return false;
           }
     }
+    
+    protected boolean moveBetweenImages(DataStore srcStore, DataStore destStore) {
+        DataStoreRole srcRole = srcStore.getRole();
+        DataStoreRole destRole = destStore.getRole();
+        if (srcRole == DataStoreRole.Image && destRole == DataStoreRole.Image) {
+            return true;
+        } else {
+            return false;
+        }
+  }
 
     @DB
     protected EndPoint findEndPointInScope(Scope scope, String sqlBase) {
@@ -162,12 +172,11 @@ public class DefaultEndPointSelector implements EndPointSelector {
         if (moveBetweenPrimaryImage(srcStore, destStore)) {
             return findEndPointForImageMove(srcStore, destStore);
         } else if (moveBetweenCacheAndImage(srcStore, destStore)) {
-        	EndPoint ep = findEndPointForImageMove(srcStore, destStore);
-        	if (ep == null) {
-        		//if there is no ssvm agent running, use mgt server
-        		ep = new LocalHostEndpoint();
-        	}
+        	EndPoint ep = findEndpointForImageStorage(destStore);
         	return ep;
+        } else if (moveBetweenImages(srcStore, destStore)) {
+            EndPoint ep = findEndpointForImageStorage(destStore);
+            return ep;
         }
         // TODO Auto-generated method stub
         return null;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/5aeca646/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageResource.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageResource.java
b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageResource.java
index ab01c72..fc3a0dd 100644
--- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageResource.java
+++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/XenServerStorageResource.java
@@ -70,6 +70,7 @@ import com.cloud.agent.api.ManageSnapshotAnswer;
 import com.cloud.agent.api.ManageSnapshotCommand;
 import com.cloud.agent.api.storage.CopyVolumeAnswer;
 import com.cloud.agent.api.storage.CreateAnswer;
+import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer;
 import com.cloud.agent.api.storage.DeleteVolumeCommand;
 import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
 import com.cloud.agent.api.to.DataStoreTO;
@@ -81,6 +82,7 @@ import com.cloud.agent.api.to.VolumeTO;
 import com.cloud.exception.InternalErrorException;
 import com.cloud.hypervisor.xen.resource.CitrixResourceBase.SRType;
 import com.cloud.storage.DataStoreRole;
+import com.cloud.storage.Storage.ImageFormat;
 import com.cloud.utils.S3Utils;
 import com.cloud.utils.StringUtils;
 import com.cloud.utils.exception.CloudRuntimeException;
@@ -1200,7 +1202,7 @@ public class XenServerStorageResource {
             destroySnapshotOnPrimaryStorageExceptThis(conn, volumeUuid, snapshotUuid);
 
             SnapshotObjectTO newSnapshot = new SnapshotObjectTO();
-            newSnapshot.setPath(snapshotBackupUuid);
+            newSnapshot.setPath(folder + File.separator + snapshotBackupUuid);
             if (fullbackup) {
                 newSnapshot.setParentSnapshotPath(null);
             } else {
@@ -1217,6 +1219,76 @@ public class XenServerStorageResource {
 
         return new CopyCmdAnswer(details);
     }
+    
+    protected CopyCmdAnswer createTemplateFromVolume(DataTO srcData, DataTO destData, int
wait) {
+        Connection conn = this.hypervisorResource.getConnection();
+        VolumeObjectTO volume = (VolumeObjectTO)srcData;
+        TemplateObjectTO template = (TemplateObjectTO)destData;
+        NfsTO destStore = (NfsTO)destData.getDataStore();
+        
+        String secondaryStoragePoolURL = destStore.getUrl();
+        String volumeUUID = volume.getPath();
+       
+        String userSpecifiedName = template.getName();
+      
+     
+        String details = null;
+        SR tmpltSR = null;
+        boolean result = false;
+        String secondaryStorageMountPath = null;
+        String installPath = null;
+        try {
+            URI uri = new URI(secondaryStoragePoolURL);
+            secondaryStorageMountPath = uri.getHost() + ":" + uri.getPath();
+            installPath = template.getPath();
+            if( !this.hypervisorResource.createSecondaryStorageFolder(conn, secondaryStorageMountPath,
installPath)) {
+                details = " Filed to create folder " + installPath + " in secondary storage";
+                s_logger.warn(details);
+                return new CopyCmdAnswer(details);
+            }
+
+            VDI vol = getVDIbyUuid(conn, volumeUUID);
+            // create template SR
+            URI tmpltURI = new URI(secondaryStoragePoolURL + "/" + installPath);
+            tmpltSR = this.hypervisorResource.createNfsSRbyURI(conn, tmpltURI, false);
+
+            // copy volume to template SR
+            VDI tmpltVDI = this.hypervisorResource.cloudVDIcopy(conn, vol, tmpltSR, wait);
+            // scan makes XenServer pick up VDI physicalSize
+            tmpltSR.scan(conn);
+            if (userSpecifiedName != null) {
+                tmpltVDI.setNameLabel(conn, userSpecifiedName);
+            }
+
+            String tmpltUUID = tmpltVDI.getUuid(conn);
+            String tmpltFilename = tmpltUUID + ".vhd";
+            long virtualSize = tmpltVDI.getVirtualSize(conn);
+            long physicalSize = tmpltVDI.getPhysicalUtilisation(conn);
+            // create the template.properties file
+            String templatePath = secondaryStorageMountPath + "/" + installPath;
+            result = this.hypervisorResource.postCreatePrivateTemplate(conn, templatePath,
tmpltFilename, tmpltUUID, userSpecifiedName, null, physicalSize, virtualSize, template.getId());
+            if (!result) {
+                throw new CloudRuntimeException("Could not create the template.properties
file on secondary storage dir: " + tmpltURI);
+            }
+            installPath = installPath + "/" + tmpltFilename;
+            this.hypervisorResource.removeSR(conn, tmpltSR);
+            tmpltSR = null;
+            TemplateObjectTO newTemplate = new TemplateObjectTO();
+            newTemplate.setPath(installPath);
+            CopyCmdAnswer answer = new CopyCmdAnswer(newTemplate);
+            return answer;
+        } catch (Exception e) {
+            if (tmpltSR != null) {
+                this.hypervisorResource.removeSR(conn, tmpltSR);
+            }
+            if ( secondaryStorageMountPath != null) {
+                this.hypervisorResource.deleteSecondaryStorageFolder(conn, secondaryStorageMountPath,
installPath);
+            }
+            details = "Creating template from volume " + volumeUUID + " failed due to " +
e.toString();
+            s_logger.error(details, e);
+        }
+        return new CopyCmdAnswer(details);
+    }
 
     protected Answer execute(CopyCommand cmd) {
         DataTO srcData = cmd.getSrcTO();
@@ -1235,11 +1307,15 @@ public class XenServerStorageResource {
         } else if (srcData.getObjectType() == DataObjectType.TEMPLATE && srcDataStore.getRole()
== DataStoreRole.Primary && destDataStore.getRole() == DataStoreRole.Primary) {
             //clone template to a volume
             return cloneVolumeFromBaseTemplate(srcData, destData);
-        } else if (srcData.getObjectType() == DataObjectType.VOLUME && srcData.getDataStore().getRole()
== DataStoreRole.ImageCache) {
+        } else if (srcData.getObjectType() == DataObjectType.VOLUME && (srcData.getDataStore().getRole()
== DataStoreRole.ImageCache || srcDataStore.getRole() == DataStoreRole.Image)) {
             //copy volume from image cache to primary
             return copyVolumeFromImageCacheToPrimary(srcData, destData, cmd.getWait());
         } else if (srcData.getObjectType() == DataObjectType.VOLUME && srcData.getDataStore().getRole()
== DataStoreRole.Primary) {
-            return copyVolumeFromPrimaryToSecondary(srcData, destData, cmd.getWait());
+            if (destData.getObjectType() == DataObjectType.VOLUME) {
+                return copyVolumeFromPrimaryToSecondary(srcData, destData, cmd.getWait());
+            } else if (destData.getObjectType() == DataObjectType.TEMPLATE) {
+                return createTemplateFromVolume(srcData, destData, cmd.getWait());
+            }
         } else if (srcData.getObjectType() == DataObjectType.SNAPSHOT && srcData.getDataStore().getRole()
== DataStoreRole.Primary) {
             DataTO cacheData = cmd.getCacheTO();
             return backupSnasphot(srcData, destData, cacheData, cmd.getWait());

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/5aeca646/scripts/storage/secondary/create_privatetemplate_from_snapshot_xen.sh
----------------------------------------------------------------------
diff --git a/scripts/storage/secondary/create_privatetemplate_from_snapshot_xen.sh b/scripts/storage/secondary/create_privatetemplate_from_snapshot_xen.sh
new file mode 100755
index 0000000..309bcbd
--- /dev/null
+++ b/scripts/storage/secondary/create_privatetemplate_from_snapshot_xen.sh
@@ -0,0 +1,98 @@
+#!/bin/bash
+# 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.
+
+#set -x
+ 
+usage() {
+  printf "Usage: %s -t [template path] -n [template name] -s [snapshot name] -p [snapshot
path] \n" $(basename $0) 
+}
+
+snapshotPath=
+snapshotName=
+templatePath=
+templateName=
+while getopts ':s:n:t:p:' OPTION
+do
+  case $OPTION in
+  t)	tflag=1
+		templatePath="$OPTARG"
+		;;
+  n)	nflag=1
+		templateName="$OPTARG"
+		;;
+  s)	sflag=1
+                snapshotName="$OPTARG"
+		;;
+  p)	pflag=1
+                snapshotPath="$OPTARG"
+		;;
+  ?)	usage
+		exit 2
+		;;
+  esac
+done
+
+if [ "$sflag$nflag$tflag$pflag" != "1111" ]
+then
+  usage
+  exit 1
+fi
+
+VHDUTIL="/bin/vhd-util"
+desvhd=$templatePath/$templateName
+srcvhd=$snapshotPath/$snapshotName
+
+copyvhd()
+{
+  local desvhd=$1
+  local srcvhd=$2
+  local parent=
+  parent=`$VHDUTIL query -p -n $srcvhd`
+  if [ $? -ne 0 ]; then
+    echo "30#failed to query $srcvhd"
+    exit 2
+  fi
+  if [[ "${parent}"  =~ " no parent" ]]; then
+    dd if=$srcvhd of=$desvhd bs=2M     
+    if [ $? -ne 0 ]; then
+      echo "31#failed to dd $srcvhd to $desvhd"
+      rm -rf $desvhd > /dev/null
+      exit 0
+    fi
+  else
+    copyvhd $desvhd $parent
+    $VHDUTIL coalesce -p $desvhd -n $srcvhd
+    if [ $? -ne 0 ]; then
+      echo "32#failed to coalesce  $desvhd to $srcvhd"
+      rm -rf $desvhd > /dev/null
+      exit 0
+    fi
+  fi
+}
+
+copyvhd $desvhd $srcvhd
+imgsize=$(ls -l $desvhd| awk -F" " '{print $5}')
+propertyFile=/$templatePath/template.properties
+touch $propertyFile
+echo -n "" > $propertyFile
+
+echo "filename=$templateName" > $propertyFile
+echo "hvm=$hvm" >> $propertyFile
+echo "size=$imgsize" >> $propertyFile
+
+exit 0


Mime
View raw message