You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by ed...@apache.org on 2013/04/13 01:05:27 UTC

git commit: updated refs/heads/object_store to b81fa6d

Updated Branches:
  refs/heads/object_store bb6467271 -> b81fa6d9e


add copy template to cache store


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

Branch: refs/heads/object_store
Commit: b81fa6d9eaf096fedce9c6907e83c1770eac1584
Parents: bb64672
Author: Edison Su <su...@gmail.com>
Authored: Thu Apr 11 17:49:32 2013 -0700
Committer: Edison Su <su...@gmail.com>
Committed: Fri Apr 12 16:03:30 2013 -0700

----------------------------------------------------------------------
 .../agent/api/storage/AbstractDownloadCommand.java |    2 +-
 .../api/storage/PrimaryStorageDownloadCommand.java |    9 +
 .../engine/subsystem/api/storage/DataObject.java   |    4 +
 .../engine/subsystem/api/storage/DataStore.java    |    1 +
 .../subsystem/api/storage/DataStoreDriver.java     |    1 +
 .../engine/subsystem/api/storage/DataStoreTO.java  |   23 +++
 .../engine/subsystem/api/storage/DataTO.java       |   28 +++
 .../subsystem/api/storage/EndPointSelector.java    |   37 ++++
 .../engine/subsystem/api/storage/TemplateInfo.java |    1 +
 .../cache/manager/StorageCacheManagerImpl.java     |   64 ++++++-
 .../storage/motion/AncientDataMotionStrategy.java  |   30 +++-
 .../storage/image/store/ImageStoreImpl.java        |    6 +-
 .../storage/image/store/TemplateObject.java        |   48 +++--
 .../storage/test/ChildTestConfiguration.java       |    2 +-
 .../cloudstack/storage/test/volumeServiceTest.java |    2 +-
 .../storage/snapshot/SnapshotObject.java           |   14 ++
 .../apache/cloudstack/storage/command/CopyCmd.java |   39 +++-
 .../datastore/ObjectInDataStoreManager.java        |    2 +
 .../datastore/ObjectInDataStoreManagerImpl.java    |   26 ++-
 .../storage/endpoint/DefaultEndPointSelector.java  |    1 +
 .../storage/endpoint/EndPointSelector.java         |   40 ----
 .../apache/cloudstack/storage/to/ImageStoreTO.java |   20 ++-
 .../cloudstack/storage/to/PrimaryDataStoreTO.java  |    9 +-
 .../apache/cloudstack/storage/to/TemplateTO.java   |   27 +++-
 .../org/apache/cloudstack/storage/to/VolumeTO.java |    8 +-
 .../storage/datastore/PrimaryDataStoreImpl.java    |    6 +
 .../cloudstack/storage/volume/VolumeObject.java    |   20 ++-
 .../storage/volume/VolumeServiceImpl.java          |    4 +-
 .../xen/resource/XenServerStorageResource.java     |  149 +++++++++++++--
 .../driver/CloudStackImageStoreDriverImpl.java     |    6 +
 .../datastore/driver/S3ImageStoreDriverImpl.java   |    6 +
 .../driver/SampleImageStoreDriverImpl.java         |    8 +-
 .../driver/SwiftImageStoreDriverImpl.java          |    6 +
 .../CloudStackPrimaryDataStoreDriverImpl.java      |    6 +
 .../driver/SamplePrimaryDataStoreDriverImpl.java   |    8 +-
 .../SamplePrimaryDataStoreLifeCycleImpl.java       |    2 +-
 .../driver/SolidfirePrimaryDataStoreDriver.java    |    6 +
 .../com/cloud/template/TemplateManagerImpl.java    |    3 +-
 38 files changed, 563 insertions(+), 111 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b81fa6d9/api/src/com/cloud/agent/api/storage/AbstractDownloadCommand.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/agent/api/storage/AbstractDownloadCommand.java b/api/src/com/cloud/agent/api/storage/AbstractDownloadCommand.java
index 04b3d43..248a419 100644
--- a/api/src/com/cloud/agent/api/storage/AbstractDownloadCommand.java
+++ b/api/src/com/cloud/agent/api/storage/AbstractDownloadCommand.java
@@ -28,7 +28,7 @@ public abstract class AbstractDownloadCommand extends ssCommand {
     protected AbstractDownloadCommand() {
     }
 
-    protected AbstractDownloadCommand(String name, String url, ImageFormat format, long accountId) {
+    protected AbstractDownloadCommand(String name, String url, ImageFormat format, Long accountId) {
     	assert(url != null);
     	url = url.replace('\\', '/');
 

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b81fa6d9/api/src/com/cloud/agent/api/storage/PrimaryStorageDownloadCommand.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/agent/api/storage/PrimaryStorageDownloadCommand.java b/api/src/com/cloud/agent/api/storage/PrimaryStorageDownloadCommand.java
index 8d955bb..b0d0fdf 100644
--- a/api/src/com/cloud/agent/api/storage/PrimaryStorageDownloadCommand.java
+++ b/api/src/com/cloud/agent/api/storage/PrimaryStorageDownloadCommand.java
@@ -34,7 +34,16 @@ public class PrimaryStorageDownloadCommand extends AbstractDownloadCommand {
 	String primaryStorageUrl;
 
     protected PrimaryStorageDownloadCommand() {
+        
 	}
+    
+    public PrimaryStorageDownloadCommand(String url, StoragePool pool, int wait) {
+        super(null, url, null, null);
+        this.poolId = pool.getId();
+        this.poolUuid = pool.getUuid();
+        this.primaryPool = new StorageFilerTO(pool);
+        setWait(wait);
+    }
 
     public PrimaryStorageDownloadCommand(String name, String url, ImageFormat format, long accountId, StoragePool pool, int wait) {
         super(name, url, format, accountId);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b81fa6d9/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataObject.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataObject.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataObject.java
index 0827cf6..9bb14c7 100644
--- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataObject.java
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataObject.java
@@ -20,13 +20,17 @@ package org.apache.cloudstack.engine.subsystem.api.storage;
 
 import org.apache.cloudstack.engine.subsystem.api.storage.disktype.DiskFormat;
 
+import com.cloud.agent.api.Answer;
+
 public interface DataObject {
     public long getId();
     public String getUri();
+    public DataTO getTO();
     public DataStore getDataStore();
     public Long getSize();
     public DataObjectType getType();
     public DiskFormat getFormat();
     public String getUuid();
     public void processEvent(ObjectInDataStoreStateMachine.Event event);
+    public void processEvent(ObjectInDataStoreStateMachine.Event event, Answer answer);
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b81fa6d9/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStore.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStore.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStore.java
index 10f869c..d20167b 100644
--- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStore.java
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStore.java
@@ -26,4 +26,5 @@ public interface DataStore {
     String getName();
     DataObject create(DataObject obj);
     boolean delete(DataObject obj);
+    DataStoreTO getTO();
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b81fa6d9/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreDriver.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreDriver.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreDriver.java
index cf5759b..f79d349 100644
--- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreDriver.java
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreDriver.java
@@ -31,4 +31,5 @@ public interface DataStoreDriver {
     public void copyAsync(DataObject srcdata, DataObject destData, AsyncCompletionCallback<CopyCommandResult> callback);
     public boolean canCopy(DataObject srcData, DataObject destData);
     public void resize(DataObject data, AsyncCompletionCallback<CreateCmdResult> callback);
+    public DataTO getTO(DataObject data);
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b81fa6d9/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreTO.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreTO.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreTO.java
new file mode 100644
index 0000000..5886bde
--- /dev/null
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataStoreTO.java
@@ -0,0 +1,23 @@
+/*
+ * 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.engine.subsystem.api.storage;
+
+public interface DataStoreTO {
+    public DataStoreRole getRole();
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b81fa6d9/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataTO.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataTO.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataTO.java
new file mode 100644
index 0000000..cd43745
--- /dev/null
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/DataTO.java
@@ -0,0 +1,28 @@
+/*
+ * 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.engine.subsystem.api.storage;
+
+public interface DataTO {
+    public DataObjectType getObjectType();
+    public DataStoreTO getDataStore();
+    /**
+     * @return
+     */
+    String getPath();
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b81fa6d9/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/EndPointSelector.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/EndPointSelector.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/EndPointSelector.java
new file mode 100644
index 0000000..fe3a1b7
--- /dev/null
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/EndPointSelector.java
@@ -0,0 +1,37 @@
+/*
+ * 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.engine.subsystem.api.storage;
+
+import java.util.List;
+
+
+public interface EndPointSelector {
+    public EndPoint select(DataObject srcData, DataObject destData);
+
+    /**
+     * @param object
+     * @return
+     */
+    EndPoint select(DataObject object);
+    /**
+     * @param store
+     * @return
+     */
+    List<EndPoint> selectAll(DataStore store);
+}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b81fa6d9/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateInfo.java
----------------------------------------------------------------------
diff --git a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateInfo.java b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateInfo.java
index 8e03503..99de1da 100644
--- a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateInfo.java
+++ b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/TemplateInfo.java
@@ -19,4 +19,5 @@
 package org.apache.cloudstack.engine.subsystem.api.storage;
 
 public interface TemplateInfo extends DataObject {
+    public String getUniqueName();
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b81fa6d9/engine/storage/cache/src/org/apache/cloudstack/storage/cache/manager/StorageCacheManagerImpl.java
----------------------------------------------------------------------
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 f943ed4..c51ce6e 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
@@ -20,20 +20,30 @@ package org.apache.cloudstack.storage.cache.manager;
 
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.ExecutionException;
 
 import javax.inject.Inject;
 import javax.naming.ConfigurationException;
 
+import org.apache.cloudstack.engine.subsystem.api.storage.CommandResult;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataMotionService;
 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.ObjectInDataStoreStateMachine.Event;
 import org.apache.cloudstack.engine.subsystem.api.storage.Scope;
 import org.apache.cloudstack.engine.subsystem.api.storage.StorageCacheManager;
+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.cache.allocator.StorageCacheAllocator;
+import org.apache.log4j.Logger;
 
 import com.cloud.utils.component.Manager;
 
 public class StorageCacheManagerImpl implements StorageCacheManager, Manager {
+    private static final Logger s_logger = Logger
+            .getLogger(StorageCacheManagerImpl.class);
     @Inject
     List<StorageCacheAllocator> storageCacheAllocator;
     @Inject
@@ -101,14 +111,62 @@ public class StorageCacheManagerImpl implements StorageCacheManager, Manager {
         // TODO Auto-generated method stub
         return true;
     }
+    
+
+    
+    private class CreateCacheObjectContext<T> extends AsyncRpcConext<T> {
+        final AsyncCallFuture<CommandResult> future;
+        /**
+         * @param callback
+         */
+        public CreateCacheObjectContext(AsyncCompletionCallback<T> callback, AsyncCallFuture<CommandResult> future) {
+            super(callback);
+            this.future = future;
+        }
+        
+    }
 
 	@Override
 	public DataObject createCacheObject(DataObject data, Scope scope) {
 		DataStore cacheStore = this.getCacheStorage(scope);
 		DataObject objOnCacheStore = cacheStore.create(data);
-		//AsyncCallFuture<>
-		//dataMotionSvr.copyAsync(data, objOnCacheStore, callback);
-		// TODO Auto-generated method stub
+		AsyncCallFuture<CommandResult> future = new AsyncCallFuture<CommandResult>();
+		CreateCacheObjectContext<CommandResult> context = new CreateCacheObjectContext<CommandResult>(null, future);
+		AsyncCallbackDispatcher<StorageCacheManagerImpl, CommandResult> caller = AsyncCallbackDispatcher.create(this); 
+		caller.setContext(context);
+		
+		
+		CommandResult result = null;
+		try {
+		    objOnCacheStore.processEvent(Event.CreateOnlyRequested);
+		    
+		    dataMotionSvr.copyAsync(data, objOnCacheStore, caller);
+		    result = future.get();
+		    
+		    if (result.isFailed()) {
+		        cacheStore.delete(data);
+		    } else {
+		        objOnCacheStore.processEvent(Event.OperationSuccessed);
+		    }
+        } catch (InterruptedException e) {
+            s_logger.debug("create cache storage failed: " + e.toString());
+        } catch (ExecutionException e) {
+            s_logger.debug("create cache storage failed: " + e.toString());
+        } catch (Exception e) {
+            s_logger.debug("create cache storage failed: " + e.toString());
+        } finally {
+            if (result == null) {
+                cacheStore.delete(data);
+            }
+        }
+		
 		return null;
 	}
+	
+	protected Void createCacheObjectCallBack(AsyncCallbackDispatcher<StorageCacheManagerImpl, CommandResult> callback, 
+	        CreateCacheObjectContext<CommandResult> context) {
+	    AsyncCallFuture<CommandResult> future = context.future;
+	    future.complete(callback.getResult());
+	    return null;
+	}
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b81fa6d9/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 1d164cd..efc2f99 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
@@ -29,9 +29,13 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
 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.EndPoint;
+import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
 import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
+import org.apache.cloudstack.engine.subsystem.api.storage.StorageCacheManager;
 import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
 import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
+import org.apache.cloudstack.storage.command.CopyCmd;
 import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
 import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
 import org.apache.log4j.Logger;
@@ -51,6 +55,8 @@ import com.cloud.agent.api.storage.CopyVolumeCommand;
 import com.cloud.agent.api.storage.CreateAnswer;
 import com.cloud.agent.api.storage.CreateCommand;
 import com.cloud.agent.api.storage.CreatePrivateTemplateAnswer;
+import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
+import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
 import com.cloud.agent.api.to.S3TO;
 import com.cloud.agent.api.to.StorageFilerTO;
 import com.cloud.agent.api.to.SwiftTO;
@@ -93,6 +99,8 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
     private static final Logger s_logger = Logger
             .getLogger(AncientDataMotionStrategy.class);
     @Inject
+    EndPointSelector selector;
+    @Inject
     TemplateManager templateMgr;
     @Inject
     VolumeHostDao volumeHostDao;
@@ -124,6 +132,8 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
     private SwiftManager _swiftMgr;
     @Inject 
     private S3Manager _s3Mgr;
+    @Inject
+    StorageCacheManager cacheMgr;
 
     @Override
     public boolean canHandle(DataObject srcData, DataObject destData) {
@@ -178,10 +188,22 @@ public class AncientDataMotionStrategy implements DataMotionStrategy {
     }
 
     private Answer copyTemplate(DataObject srcData, DataObject destData) {
-        VMTemplateVO template = this.templateDao.findById(srcData.getId());
-        templateMgr.prepareTemplateForCreate(template,
-                (StoragePool) destData.getDataStore());
-        return null;
+        String value = configDao.getValue(Config.PrimaryStorageDownloadWait.toString());
+        int _primaryStorageDownloadWait = NumbersUtil.parseInt(value, Integer.parseInt(Config.PrimaryStorageDownloadWait.getDefaultValue()));
+        if (srcData.getDataStore().getRole() != DataStoreRole.ImageCache && destData.getDataStore().getRole() != DataStoreRole.ImageCache) {
+            //need to copy it to image cache store
+            DataObject cacheData = cacheMgr.createCacheObject(srcData, destData.getDataStore().getScope());
+            CopyCmd cmd = new CopyCmd(cacheData.getTO(), destData.getTO(), _primaryStorageDownloadWait);
+            EndPoint ep = selector.select(cacheData, destData);
+            Answer answer = ep.sendMessage(cmd);
+            return answer;
+        } else {
+            //handle copy it to cache store
+            CopyCmd cmd = new CopyCmd(srcData.getTO(), destData.getTO(), _primaryStorageDownloadWait);
+            EndPoint ep = selector.select(srcData, destData);
+            Answer answer = ep.sendMessage(cmd);
+            return answer;
+        }
     }
 
     protected Answer copyFromSnapshot(DataObject snapObj, DataObject volObj) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b81fa6d9/engine/storage/image/src/org/apache/cloudstack/storage/image/store/ImageStoreImpl.java
----------------------------------------------------------------------
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 7e143cb..4cd70ca 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
@@ -25,6 +25,7 @@ import javax.inject.Inject;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataObject;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreDriver;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreRole;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreTO;
 import org.apache.cloudstack.engine.subsystem.api.storage.ImageStoreProvider;
 import org.apache.cloudstack.engine.subsystem.api.storage.Scope;
 import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
@@ -164,7 +165,10 @@ public class ImageStoreImpl implements ImageStoreEntity {
         return imageDataStoreVO.getProtocol();
     }
 
-
+    @Override
+    public DataStoreTO getTO() {
+        return null;
+    }
 
 
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b81fa6d9/engine/storage/image/src/org/apache/cloudstack/storage/image/store/TemplateObject.java
----------------------------------------------------------------------
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 b6c2004..2025d27 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
@@ -23,6 +23,7 @@ import javax.inject.Inject;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
 import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
 import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
 import org.apache.cloudstack.engine.subsystem.api.storage.TemplateEvent;
@@ -30,15 +31,16 @@ import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
 import org.apache.cloudstack.engine.subsystem.api.storage.disktype.DiskFormat;
 import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager;
 import org.apache.cloudstack.storage.image.manager.ImageDataManager;
+import org.apache.cloudstack.storage.to.TemplateTO;
 import org.apache.log4j.Logger;
 
+import com.cloud.agent.api.Answer;
 import com.cloud.storage.VMTemplateVO;
 import com.cloud.storage.dao.VMTemplateDao;
 import com.cloud.storage.dao.VMTemplatePoolDao;
 import com.cloud.utils.component.ComponentContext;
 import com.cloud.utils.exception.CloudRuntimeException;
 import com.cloud.utils.fsm.NoTransitionException;
-import com.cloud.utils.storage.encoding.EncodingType;
 
 public class TemplateObject implements TemplateInfo {
     private static final Logger s_logger = Logger
@@ -83,6 +85,11 @@ public class TemplateObject implements TemplateInfo {
     public DataStore getDataStore() {
         return this.dataStore;
     }
+    
+    @Override
+    public String getUniqueName() {
+        return this.imageVO.getUniqueName();
+    }
 
     @Override
     public long getId() {
@@ -101,22 +108,7 @@ public class TemplateObject implements TemplateInfo {
             return image.getUrl();
         } else {
             DataObjectInStore obj = ojbectInStoreMgr.findObject(this, this.dataStore);
-            StringBuilder builder = new StringBuilder();
-            if (obj.getState() == ObjectInDataStoreStateMachine.State.Ready
-                    || obj.getState() == ObjectInDataStoreStateMachine.State.Copying) {
-
-                builder.append(this.dataStore.getUri());
-                builder.append("&" + EncodingType.OBJTYPE + "=" + DataObjectType.TEMPLATE);
-                builder.append("&" + EncodingType.PATH + "=" + obj.getInstallPath());
-                builder.append("&" + EncodingType.SIZE + "=" + image.getSize());
-                return builder.toString();
-            } else {
-                builder.append(this.dataStore.getUri());
-                builder.append("&" + EncodingType.OBJTYPE + "=" + DataObjectType.TEMPLATE);
-                builder.append("&" + EncodingType.SIZE + "=" + image.getSize());
-                builder.append("&" + EncodingType.PATH + "=" + image.getUrl());
-                return builder.toString();
-            }
+           return obj.getInstallPath();
         }
     }
 
@@ -174,10 +166,30 @@ public class TemplateObject implements TemplateInfo {
     @Override
     public void processEvent(Event event) {
         try {
-            ojbectInStoreMgr.update(this, event);
+            ojbectInStoreMgr.update(this, event, null);
         } catch (NoTransitionException e) {
             s_logger.debug("failed to update state", e);
             throw new CloudRuntimeException("Failed to update state" + e.toString());
         }
     }
+    
+    @Override
+    public void processEvent(ObjectInDataStoreStateMachine.Event event, Answer answer) {
+        try {
+            ojbectInStoreMgr.update(this, event, answer);
+        } catch (NoTransitionException e) {
+            s_logger.debug("failed to update state", e);
+            throw new CloudRuntimeException("Failed to update state" + e.toString());
+        }
+    }
+    
+    @Override
+    public DataTO getTO() {
+        DataTO to = this.dataStore.getDriver().getTO(this);
+        if (to == null) {
+            to = new TemplateTO(this);
+        }
+        
+        return to;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b81fa6d9/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/ChildTestConfiguration.java
----------------------------------------------------------------------
diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/ChildTestConfiguration.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/ChildTestConfiguration.java
index a063bdd..4b8dbb8 100644
--- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/ChildTestConfiguration.java
+++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/ChildTestConfiguration.java
@@ -20,9 +20,9 @@ import java.io.IOException;
 
 import org.apache.cloudstack.acl.APIChecker;
 import org.apache.cloudstack.engine.service.api.OrchestrationService;
+import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
 import org.apache.cloudstack.framework.rpc.RpcProvider;
 import org.apache.cloudstack.storage.HostEndpointRpcServer;
-import org.apache.cloudstack.storage.endpoint.EndPointSelector;
 import org.apache.cloudstack.storage.test.ChildTestConfiguration.Library;
 import org.mockito.Mockito;
 import org.springframework.context.annotation.Bean;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b81fa6d9/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/volumeServiceTest.java
----------------------------------------------------------------------
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 fcb8962..ca64105 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
@@ -38,6 +38,7 @@ 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.DataStoreRole;
 import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
+import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
 import org.apache.cloudstack.engine.subsystem.api.storage.ImageDataFactory;
 import org.apache.cloudstack.engine.subsystem.api.storage.TemplateService;
 import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
@@ -50,7 +51,6 @@ import org.apache.cloudstack.framework.async.AsyncCallFuture;
 import org.apache.cloudstack.storage.HypervisorHostEndPoint;
 import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
 import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
-import org.apache.cloudstack.storage.endpoint.EndPointSelector;
 import org.apache.cloudstack.storage.volume.db.VolumeDao2;
 import org.apache.cloudstack.storage.volume.db.VolumeVO;
 import org.mockito.Mockito;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b81fa6d9/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java
----------------------------------------------------------------------
diff --git a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java
index d10dc77..b8a7760 100644
--- a/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java
+++ b/engine/storage/snapshot/src/org/apache/cloudstack/storage/snapshot/SnapshotObject.java
@@ -24,6 +24,7 @@ import javax.inject.Inject;
 
 import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
 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.VolumeDataFactory;
@@ -32,6 +33,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.disktype.DiskFormat;
 import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager;
 import org.apache.log4j.Logger;
 
+import com.cloud.agent.api.Answer;
 import com.cloud.hypervisor.Hypervisor.HypervisorType;
 import com.cloud.storage.Snapshot;
 import com.cloud.storage.SnapshotVO;
@@ -220,4 +222,16 @@ public class SnapshotObject implements SnapshotInfo {
 	public String getBackupSnapshotId() {
 		return this.snapshot.getBackupSnapshotId();
 	}
+
+    @Override
+    public DataTO getTO() {
+        // TODO Auto-generated method stub
+        return null;
+    }
+
+    @Override
+    public void processEvent(org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event event, Answer answer) {
+        // TODO Auto-generated method stub
+        
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b81fa6d9/engine/storage/src/org/apache/cloudstack/storage/command/CopyCmd.java
----------------------------------------------------------------------
diff --git a/engine/storage/src/org/apache/cloudstack/storage/command/CopyCmd.java b/engine/storage/src/org/apache/cloudstack/storage/command/CopyCmd.java
index 10478ef..9cb225b 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/command/CopyCmd.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/command/CopyCmd.java
@@ -16,30 +16,47 @@
 // under the License.
 package org.apache.cloudstack.storage.command;
 
+import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
+
 import com.cloud.agent.api.Command;
 
 public class CopyCmd extends Command implements StorageSubSystemCommand {
-    private String srcUri;
-    private String destUri;
+    private DataTO srcTO;
+    private DataTO destTO;
+    private int timeout;
+
+    /**
+     * @return the timeout
+     */
+    public int getTimeout() {
+        return timeout;
+    }
+
+    /**
+     * @param timeout the timeout to set
+     */
+    public void setTimeout(int timeout) {
+        this.timeout = timeout;
+    }
 
-    public CopyCmd(String srcUri, String destUri) {
+    public CopyCmd(DataTO srcUri, DataTO destUri, int timeout) {
         super();
-        this.srcUri = srcUri;
-        this.destUri = destUri;
+        this.srcTO = srcUri;
+        this.destTO = destUri;
+        this.timeout = timeout;
     }
     
-    public String getDestUri() {
-        return this.destUri;
+    public DataTO getDestTO() {
+        return this.destTO;
     }
     
-    public String getSrcUri() {
-        return this.srcUri;
+    public DataTO getSrcTO() {
+        return this.srcTO;
     }
 
     @Override
     public boolean executeInSequence() {
-        // TODO Auto-generated method stub
-        return false;
+        return true;
     }
 
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b81fa6d9/engine/storage/src/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManager.java
----------------------------------------------------------------------
diff --git a/engine/storage/src/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManager.java b/engine/storage/src/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManager.java
index cb27c02..2632143 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManager.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManager.java
@@ -23,11 +23,13 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreRole;
 import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event;
 
+import com.cloud.agent.api.Answer;
 import com.cloud.utils.fsm.NoTransitionException;
 
 public interface ObjectInDataStoreManager {
     public DataObject create(DataObject template, DataStore dataStore);
     public DataObject get(DataObject dataObj, DataStore store);
+    public boolean update(DataObject vo, Event event, Answer answer) throws NoTransitionException;
     public boolean update(DataObject vo, Event event) throws NoTransitionException;
     DataObjectInStore findObject(long objId, DataObjectType type,
             long dataStoreId, DataStoreRole role);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b81fa6d9/engine/storage/src/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManagerImpl.java
----------------------------------------------------------------------
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 ac96c5f..632860d 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManagerImpl.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/datastore/ObjectInDataStoreManagerImpl.java
@@ -29,6 +29,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreState
 import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.State;
 import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotDataFactory;
 import org.apache.cloudstack.engine.subsystem.api.storage.VolumeDataFactory;
+import org.apache.cloudstack.storage.command.CopyCmdAnswer;
 import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreDao;
 import org.apache.cloudstack.storage.datastore.db.SnapshotDataStoreVO;
 import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
@@ -40,7 +41,9 @@ import org.apache.cloudstack.storage.db.ObjectInDataStoreVO;
 import org.apache.log4j.Logger;
 import org.springframework.stereotype.Component;
 
+import com.cloud.agent.api.Answer;
 import com.cloud.storage.VMTemplateStoragePoolVO;
+import com.cloud.storage.VMTemplateStorageResourceAssoc.Status;
 import com.cloud.storage.dao.VMTemplatePoolDao;
 import com.cloud.utils.db.SearchCriteria;
 import com.cloud.utils.db.SearchCriteria.Op;
@@ -148,7 +151,7 @@ public class ObjectInDataStoreManagerImpl implements ObjectInDataStoreManager {
     }
 
     @Override
-    public boolean update(DataObject data, Event event)
+    public boolean update(DataObject data, Event event, Answer answer)
             throws NoTransitionException {
         DataObjectInStore obj = this.findObject(data, data.getDataStore());
         if (obj == null) {
@@ -167,11 +170,21 @@ public class ObjectInDataStoreManagerImpl implements ObjectInDataStoreManager {
                 this.stateMachines.transitTo(obj, event, null, volumeDataStoreDao);
             }
         } else if (data.getType() == DataObjectType.TEMPLATE && data.getDataStore().getRole() == DataStoreRole.Primary) {
+            if (answer != null && answer instanceof CopyCmdAnswer) {
+                CopyCmdAnswer cpyAnswer = (CopyCmdAnswer)answer;
+                VMTemplateStoragePoolVO templatePoolRef = templatePoolDao.findByPoolTemplate(data.getDataStore().getId(), data.getId());
+                templatePoolRef.setDownloadPercent(100);
+                templatePoolRef.setDownloadState(Status.DOWNLOADED);
+                templatePoolRef.setLocalDownloadPath(cpyAnswer.getPath());
+                templatePoolRef.setInstallPath(cpyAnswer.getPath());
+                templatePoolDao.update(templatePoolRef.getId(), templatePoolRef);
+            }
             try {
-            this.stateMachines.transitTo(obj, event, null,
-                    templatePoolDao);
+                obj = this.findObject(data, data.getDataStore());
+                this.stateMachines.transitTo(obj, event, null,
+                        templatePoolDao);
             } catch (NoTransitionException e) {
-                    throw e;
+                throw e;
             }
         } else {
             throw new CloudRuntimeException("Invalid data or store type: " + data.getType() + " " + data.getDataStore().getRole());
@@ -254,4 +267,9 @@ public class ObjectInDataStoreManagerImpl implements ObjectInDataStoreManager {
         return store;
     }
 
+    @Override
+    public boolean update(DataObject vo, Event event) throws NoTransitionException {
+       return this.update(vo, event, null);
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b81fa6d9/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 772a8f2..ab5c552 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/endpoint/DefaultEndPointSelector.java
@@ -30,6 +30,7 @@ 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.DataStoreRole;
 import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
+import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
 import org.apache.cloudstack.engine.subsystem.api.storage.Scope;
 import org.apache.cloudstack.engine.subsystem.api.storage.disktype.DiskFormat;
 import org.apache.cloudstack.storage.HypervisorHostEndPoint;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b81fa6d9/engine/storage/src/org/apache/cloudstack/storage/endpoint/EndPointSelector.java
----------------------------------------------------------------------
diff --git a/engine/storage/src/org/apache/cloudstack/storage/endpoint/EndPointSelector.java b/engine/storage/src/org/apache/cloudstack/storage/endpoint/EndPointSelector.java
deleted file mode 100644
index 6910eb6..0000000
--- a/engine/storage/src/org/apache/cloudstack/storage/endpoint/EndPointSelector.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * 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.endpoint;
-
-import java.util.List;
-
-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.EndPoint;
-
-public interface EndPointSelector {
-    public EndPoint select(DataObject srcData, DataObject destData);
-
-    /**
-     * @param object
-     * @return
-     */
-    EndPoint select(DataObject object);
-    /**
-     * @param store
-     * @return
-     */
-    List<EndPoint> selectAll(DataStore store);
-}

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b81fa6d9/engine/storage/src/org/apache/cloudstack/storage/to/ImageStoreTO.java
----------------------------------------------------------------------
diff --git a/engine/storage/src/org/apache/cloudstack/storage/to/ImageStoreTO.java b/engine/storage/src/org/apache/cloudstack/storage/to/ImageStoreTO.java
index eb6d088..5224e2e 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/to/ImageStoreTO.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/to/ImageStoreTO.java
@@ -16,14 +16,20 @@
 // under the License.
 package org.apache.cloudstack.storage.to;
 
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreRole;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreTO;
 import org.apache.cloudstack.storage.image.datastore.ImageStoreInfo;
 
-public class ImageStoreTO {
+public class ImageStoreTO implements DataStoreTO {
     private final String type;
     private final String uri;
+    private final String providerName;
+    private final DataStoreRole role;
     public ImageStoreTO(ImageStoreInfo dataStore) {
         this.type = dataStore.getType();
         this.uri = dataStore.getUri();
+        this.providerName = null;
+        this.role = dataStore.getRole();
     }
     
     public String getType() {
@@ -33,4 +39,16 @@ public class ImageStoreTO {
     public String getUri() {
         return this.uri;
     }
+
+    /**
+     * @return the providerName
+     */
+    public String getProviderName() {
+        return providerName;
+    }
+
+    @Override
+    public DataStoreRole getRole() {
+        return this.role;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b81fa6d9/engine/storage/src/org/apache/cloudstack/storage/to/PrimaryDataStoreTO.java
----------------------------------------------------------------------
diff --git a/engine/storage/src/org/apache/cloudstack/storage/to/PrimaryDataStoreTO.java b/engine/storage/src/org/apache/cloudstack/storage/to/PrimaryDataStoreTO.java
index aa47e8f..b410dd6 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/to/PrimaryDataStoreTO.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/to/PrimaryDataStoreTO.java
@@ -16,9 +16,11 @@
 // under the License.
 package org.apache.cloudstack.storage.to;
 
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreRole;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreTO;
 import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo;
 
-public class PrimaryDataStoreTO {
+public class PrimaryDataStoreTO implements DataStoreTO {
     private final String uuid;
     private final String name;
     private  String type;
@@ -45,4 +47,9 @@ public class PrimaryDataStoreTO {
     public String getType() {
         return this.type;
     }
+
+    @Override
+    public DataStoreRole getRole() {
+        return DataStoreRole.Primary;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b81fa6d9/engine/storage/src/org/apache/cloudstack/storage/to/TemplateTO.java
----------------------------------------------------------------------
diff --git a/engine/storage/src/org/apache/cloudstack/storage/to/TemplateTO.java b/engine/storage/src/org/apache/cloudstack/storage/to/TemplateTO.java
index d7b146b..f54c2c7 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/to/TemplateTO.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/to/TemplateTO.java
@@ -16,23 +16,29 @@
 // under the License.
 package org.apache.cloudstack.storage.to;
 
+import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreTO;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
 import org.apache.cloudstack.engine.subsystem.api.storage.TemplateInfo;
 import org.apache.cloudstack.engine.subsystem.api.storage.disktype.DiskFormat;
 import org.apache.cloudstack.storage.image.datastore.ImageStoreInfo;
 
-public class TemplateTO {
+public class TemplateTO implements DataTO {
     private final String path;
     private final String uuid;
     private  DiskFormat diskType;
     private final ImageStoreTO imageDataStore;
+    private final String name;
 
     public TemplateTO(TemplateInfo template) {
-        this.path = null;
+        this.path = template.getUri();
         this.uuid = template.getUuid();
         //this.diskType = template.getDiskType();
         this.imageDataStore = new ImageStoreTO((ImageStoreInfo)template.getDataStore());
+        this.name = template.getUniqueName();
     }
     
+    @Override
     public String getPath() {
         return this.path;
     }
@@ -48,4 +54,21 @@ public class TemplateTO {
     public ImageStoreTO getImageDataStore() {
         return this.imageDataStore;
     }
+
+    @Override
+    public DataObjectType getObjectType() {
+        return DataObjectType.TEMPLATE;
+    }
+
+    @Override
+    public DataStoreTO getDataStore() {
+        return (DataStoreTO)this.imageDataStore;
+    }
+
+    /**
+     * @return the name
+     */
+    public String getName() {
+        return name;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b81fa6d9/engine/storage/src/org/apache/cloudstack/storage/to/VolumeTO.java
----------------------------------------------------------------------
diff --git a/engine/storage/src/org/apache/cloudstack/storage/to/VolumeTO.java b/engine/storage/src/org/apache/cloudstack/storage/to/VolumeTO.java
index c65b652..162ff38 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/to/VolumeTO.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/to/VolumeTO.java
@@ -16,12 +16,14 @@
 // under the License.
 package org.apache.cloudstack.storage.to;
 
+import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
 import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo;
 import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
 import org.apache.cloudstack.engine.subsystem.api.storage.disktype.DiskFormat;
 import org.apache.cloudstack.engine.subsystem.api.storage.type.VolumeType;
 
-public class VolumeTO {
+public class VolumeTO implements DataTO {
     private final String uuid;
     private final String path;
     private  VolumeType volumeType;
@@ -74,4 +76,8 @@ public class VolumeTO {
     public long getSize() {
         return this.size;
     }
+    
+    public DataObjectType getObjectType() {
+        return DataObjectType.VOLUME;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b81fa6d9/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreImpl.java
----------------------------------------------------------------------
diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreImpl.java b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreImpl.java
index 3266eaf..836f9d4 100644
--- a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreImpl.java
+++ b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/PrimaryDataStoreImpl.java
@@ -29,6 +29,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreDriver;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreProvider;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreRole;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreTO;
 import org.apache.cloudstack.engine.subsystem.api.storage.HostScope;
 import org.apache.cloudstack.engine.subsystem.api.storage.ImageDataFactory;
 import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
@@ -340,4 +341,9 @@ public class PrimaryDataStoreImpl implements PrimaryDataStore {
     public String getStorageProviderName() {
         return this.pdsv.getStorageProviderName();
     }
+    
+    @Override
+    public DataStoreTO getTO() {
+        return null;
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b81fa6d9/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeObject.java
----------------------------------------------------------------------
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 766d219..c2fb0cb 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
@@ -24,12 +24,15 @@ import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectInStore;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreRole;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
 import org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine;
 import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
 import org.apache.cloudstack.engine.subsystem.api.storage.disktype.DiskFormat;
 import org.apache.cloudstack.storage.datastore.ObjectInDataStoreManager;
+import org.apache.cloudstack.storage.to.VolumeTO;
 import org.apache.log4j.Logger;
 
+import com.cloud.agent.api.Answer;
 import com.cloud.hypervisor.Hypervisor.HypervisorType;
 import com.cloud.storage.Volume;
 import com.cloud.storage.VolumeVO;
@@ -162,7 +165,7 @@ public class VolumeObject implements VolumeInfo {
         try {
             Volume.Event volEvent = null;
             if (this.dataStore.getRole() == DataStoreRole.Image) {
-                ojbectInStoreMgr.update(this, event);
+                ojbectInStoreMgr.update(this, event, null);
                 if (event == ObjectInDataStoreStateMachine.Event.CreateRequested) {
                     volEvent = Volume.Event.UploadRequested;
                 } else if (event == ObjectInDataStoreStateMachine.Event.OperationSuccessed) {
@@ -331,4 +334,19 @@ public class VolumeObject implements VolumeInfo {
 	public Long getLastPoolId() {
 		return this.volumeVO.getLastPoolId();
 	}
+
+    @Override
+    public DataTO getTO() {
+        DataTO to = this.getDataStore().getDriver().getTO(this);
+        if (to == null) {
+            to = new VolumeTO(this);
+        }
+        return to;
+    }
+
+    @Override
+    public void processEvent(org.apache.cloudstack.engine.subsystem.api.storage.ObjectInDataStoreStateMachine.Event event, Answer answer) {
+        // TODO Auto-generated method stub
+        
+    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b81fa6d9/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeServiceImpl.java
----------------------------------------------------------------------
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 2da16c1..d017f4f 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
@@ -428,7 +428,7 @@ public class VolumeServiceImpl implements VolumeService {
         VolumeObject vo = (VolumeObject)volume;
         CreateVolumeFromBaseImageContext<VolumeApiResult> context = new CreateVolumeFromBaseImageContext<VolumeApiResult>(null, vo, pd, templateOnPrimaryStore, future);
         AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> caller =  AsyncCallbackDispatcher.create(this);
-        caller.setCallback(caller.getTarget().copyBaseImageCallBack(null, null))
+        caller.setCallback(caller.getTarget().createVolumeFromBaseImageCallBack(null, null))
         .setContext(context);
 
         DataObject volumeOnPrimaryStorage = pd.create(volume);
@@ -439,7 +439,7 @@ public class VolumeServiceImpl implements VolumeService {
     }
 
     @DB
-    public Void copyBaseImageCallBack(AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> callback, CreateVolumeFromBaseImageContext<VolumeApiResult> context) {
+    protected Void createVolumeFromBaseImageCallBack(AsyncCallbackDispatcher<VolumeServiceImpl, CopyCommandResult> callback, CreateVolumeFromBaseImageContext<VolumeApiResult> context) {
         VolumeObject vo = context.vo;
         CopyCommandResult result = callback.getResult();
         VolumeApiResult volResult = new VolumeApiResult(vo);

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b81fa6d9/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 9c29149..70c992f 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
@@ -28,7 +28,12 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.UUID;
 
+import org.apache.cloudstack.engine.subsystem.api.storage.DataObjectType;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreRole;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataStoreTO;
+import org.apache.cloudstack.engine.subsystem.api.storage.DataTO;
 import org.apache.cloudstack.storage.command.AttachPrimaryDataStoreAnswer;
 import org.apache.cloudstack.storage.command.AttachPrimaryDataStoreCmd;
 import org.apache.cloudstack.storage.command.CopyCmd;
@@ -40,6 +45,9 @@ import org.apache.cloudstack.storage.command.CreateVolumeFromBaseImageCommand;
 import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
 import org.apache.cloudstack.storage.datastore.protocol.DataStoreProtocol;
 import org.apache.cloudstack.storage.to.ImageOnPrimayDataStoreTO;
+import org.apache.cloudstack.storage.to.ImageStoreTO;
+import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
+import org.apache.cloudstack.storage.to.TemplateTO;
 import org.apache.cloudstack.storage.to.VolumeTO;
 import org.apache.http.HttpEntity;
 import org.apache.http.HttpResponse;
@@ -52,6 +60,8 @@ import org.apache.xmlrpc.XmlRpcException;
 import com.cloud.agent.api.Answer;
 import com.cloud.agent.api.Command;
 import com.cloud.agent.api.storage.DeleteVolumeCommand;
+import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
+import com.cloud.agent.api.storage.PrimaryStorageDownloadCommand;
 import com.cloud.hypervisor.xen.resource.CitrixResourceBase.SRType;
 import com.cloud.utils.exception.CloudRuntimeException;
 import com.cloud.utils.storage.encoding.DecodedDataObject;
@@ -601,21 +611,134 @@ public class XenServerStorageResource {
         }
     }
     
-    protected Answer execute(CopyCmd cmd) {
-        DecodedDataObject srcObj = null;
-        DecodedDataObject destObj = null;
+    private boolean IsISCSI(String type) {
+        return SRType.LVMOHBA.equals(type) || SRType.LVMOISCSI.equals(type) || SRType.LVM.equals(type) ;
+    }
+    
+    private String copy_vhd_from_secondarystorage(Connection conn, String mountpoint, String sruuid, int wait) {
+        String nameLabel = "cloud-" + UUID.randomUUID().toString();
+        String results = hypervisorResource.callHostPluginAsync(conn, "vmopspremium", "copy_vhd_from_secondarystorage",
+                wait, "mountpoint", mountpoint, "sruuid", sruuid, "namelabel", nameLabel);
+        String errMsg = null;
+        if (results == null || results.isEmpty()) {
+            errMsg = "copy_vhd_from_secondarystorage return null";
+        } else {
+            String[] tmp = results.split("#");
+            String status = tmp[0];
+            if (status.equals("0")) {
+                return tmp[1];
+            } else {
+                errMsg = tmp[1];
+            }
+        }
+        String source = mountpoint.substring(mountpoint.lastIndexOf('/') + 1);
+        if( hypervisorResource.killCopyProcess(conn, source) ) {
+            destroyVDIbyNameLabel(conn, nameLabel);
+        }
+        s_logger.warn(errMsg);
+        throw new CloudRuntimeException(errMsg);
+    }
+    
+    private void destroyVDIbyNameLabel(Connection conn, String nameLabel) {
         try {
-            srcObj = Decoder.decode(cmd.getSrcUri());
-            destObj = Decoder.decode(cmd.getDestUri());
-        } catch (URISyntaxException e) {
-            return new Answer(cmd, false, e.toString());
+            Set<VDI> vdis = VDI.getByNameLabel(conn, nameLabel);
+            if ( vdis.size() != 1 ) {
+                s_logger.warn("destoryVDIbyNameLabel failed due to there are " + vdis.size() + " VDIs with name " + nameLabel);
+                return;
+            }
+            for (VDI vdi : vdis) {
+                try {
+                    vdi.destroy(conn);
+                } catch (Exception e) {
+                }
+            }
+        } catch (Exception e){
         }
-       
+    }
+    
+    protected VDI getVDIbyUuid(Connection conn, String uuid) {
+        try {
+            return VDI.getByUuid(conn, uuid);
+        } catch (Exception e) {
+            String msg = "Catch Exception " + e.getClass().getName() + " :VDI getByUuid for uuid: " + uuid + " failed due to " + e.toString();
+            s_logger.debug(msg);
+            throw new CloudRuntimeException(msg, e);
+        }
+    }
+    
+    protected String getVhdParent(Connection conn, String primaryStorageSRUuid, String snapshotUuid, Boolean isISCSI) {
+        String parentUuid = hypervisorResource.callHostPlugin(conn, "vmopsSnapshot", "getVhdParent", "primaryStorageSRUuid", primaryStorageSRUuid,
+                "snapshotUuid", snapshotUuid, "isISCSI", isISCSI.toString());
+
+        if (parentUuid == null || parentUuid.isEmpty() || parentUuid.equalsIgnoreCase("None")) {
+            s_logger.debug("Unable to get parent of VHD " + snapshotUuid + " in SR " + primaryStorageSRUuid);
+            // errString is already logged.
+            return null;
+        }
+        return parentUuid;
+    }
+    
+    protected PrimaryStorageDownloadAnswer copyTemplateToPrimaryStorage(DataTO srcData, DataTO destData, int wait) {
+        DataStoreTO srcStore = srcData.getDataStore();
+        try {
+            if (srcStore.getRole() == DataStoreRole.ImageCache && srcData.getObjectType() == DataObjectType.TEMPLATE) {
+                ImageStoreTO srcImageStore = (ImageStoreTO)srcStore;
+                TemplateTO srcTemplate = (TemplateTO)srcData;
+                String storeUrl = srcImageStore.getUri();
+                if (!storeUrl.startsWith("nfs")) {
+                    return new PrimaryStorageDownloadAnswer("only nfs image cache store supported");
+                }
+                String tmplpath = storeUrl + ":" + srcData.getPath();
+                PrimaryDataStoreTO destStore = (PrimaryDataStoreTO)destData.getDataStore();
+                String poolName = destStore.getUuid();
+                Connection conn = hypervisorResource.getConnection();
+
+                SR poolsr = null;
+                Set<SR> srs = SR.getByNameLabel(conn, poolName);
+                if (srs.size() != 1) {
+                    String msg = "There are " + srs.size() + " SRs with same name: " + poolName;
+                    s_logger.warn(msg);
+                    return new PrimaryStorageDownloadAnswer(msg);
+                } else {
+                    poolsr = srs.iterator().next();
+                }
+                String pUuid = poolsr.getUuid(conn);
+                boolean isISCSI = IsISCSI(poolsr.getType(conn));
+                String uuid = copy_vhd_from_secondarystorage(conn, tmplpath, pUuid, wait);
+                VDI tmpl = getVDIbyUuid(conn, uuid);
+                VDI snapshotvdi = tmpl.snapshot(conn, new HashMap<String, String>());
+                String snapshotUuid = snapshotvdi.getUuid(conn);
+                snapshotvdi.setNameLabel(conn, "Template " + srcTemplate.getName());
+                String parentuuid = getVhdParent(conn, pUuid, snapshotUuid, isISCSI);
+                VDI parent = getVDIbyUuid(conn, parentuuid);
+                Long phySize = parent.getPhysicalUtilisation(conn);
+                tmpl.destroy(conn);
+                poolsr.scan(conn);
+                try{
+                    Thread.sleep(5000);
+                } catch (Exception e) {
+                }
+                return new PrimaryStorageDownloadAnswer(snapshotvdi.getUuid(conn), phySize);
+            } 
+        }catch (Exception e) {
+            String msg = "Catch Exception " + e.getClass().getName() + " for template + " + " due to " + e.toString();
+            s_logger.warn(msg, e);
+            return new PrimaryStorageDownloadAnswer(msg);
+        }
+        return new PrimaryStorageDownloadAnswer("not implemented yet");
+    }
+ 
+    
+    protected Answer execute(CopyCmd cmd) {
+        DataTO srcData = cmd.getSrcTO();
+        DataTO destData = cmd.getDestTO();
         
-        if (srcObj.getPath().startsWith("http")) {
-            return directDownloadHttpTemplate(cmd, srcObj, destObj);
-        } else {
-            return new Answer(cmd, false, "not implemented yet");
+        if (srcData.getObjectType() == DataObjectType.TEMPLATE && destData.getDataStore().getRole() == DataStoreRole.Primary) {
+            //copy template to primary storage
+            return copyTemplateToPrimaryStorage(srcData, destData, cmd.getTimeout());
+        }
+        
+        return new Answer(cmd, false, "not implemented yet");
             /*
         String tmplturl = cmd.getUrl();
         String poolName = cmd.getPoolUuid();
@@ -657,6 +780,4 @@ public class XenServerStorageResource {
             return new PrimaryStorageDownloadAnswer(msg);
         }*/
         }
-        
-    }
 }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b81fa6d9/plugins/storage/image/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackImageStoreDriverImpl.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 46c87b7..692aded 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
@@ -29,6 +29,7 @@ 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.DataObjectType;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
+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.VolumeInfo;
 import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
@@ -91,6 +92,11 @@ public class CloudStackImageStoreDriverImpl implements ImageStoreDriver {
         // TODO Auto-generated method stub
         return null;
     }
+    
+    @Override
+    public DataTO getTO(DataObject data) {
+        return null;
+    }
 
     @Override
     public boolean revokeAccess(DataObject data, EndPoint ep) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b81fa6d9/plugins/storage/image/s3/src/org/apache/cloudstack/storage/datastore/driver/S3ImageStoreDriverImpl.java
----------------------------------------------------------------------
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 50a82cc..c5574d3 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
@@ -29,6 +29,7 @@ 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.DataObjectType;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
+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.VolumeInfo;
 import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
@@ -91,6 +92,11 @@ public class S3ImageStoreDriverImpl implements ImageStoreDriver {
         // TODO Auto-generated method stub
         return null;
     }
+    
+    @Override
+    public DataTO getTO(DataObject data) {
+        return null;
+    }
 
     @Override
     public boolean revokeAccess(DataObject data, EndPoint ep) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b81fa6d9/plugins/storage/image/sample/src/org/apache/cloudstack/storage/datastore/driver/SampleImageStoreDriverImpl.java
----------------------------------------------------------------------
diff --git a/plugins/storage/image/sample/src/org/apache/cloudstack/storage/datastore/driver/SampleImageStoreDriverImpl.java b/plugins/storage/image/sample/src/org/apache/cloudstack/storage/datastore/driver/SampleImageStoreDriverImpl.java
index dc2e58c..4d53520 100644
--- a/plugins/storage/image/sample/src/org/apache/cloudstack/storage/datastore/driver/SampleImageStoreDriverImpl.java
+++ b/plugins/storage/image/sample/src/org/apache/cloudstack/storage/datastore/driver/SampleImageStoreDriverImpl.java
@@ -28,11 +28,12 @@ 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.DataObjectType;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
+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.AsyncCompletionCallback;
 import org.apache.cloudstack.storage.command.CreateObjectAnswer;
 import org.apache.cloudstack.storage.command.CreateObjectCommand;
-import org.apache.cloudstack.storage.endpoint.EndPointSelector;
 import org.apache.cloudstack.storage.image.ImageStoreDriver;
 
 import com.cloud.storage.dao.VMTemplateDao;
@@ -45,6 +46,11 @@ public class SampleImageStoreDriverImpl implements ImageStoreDriver {
     VMTemplateDao imageDataDao;
     public SampleImageStoreDriverImpl() {
     }
+    
+    @Override
+    public DataTO getTO(DataObject data) {
+        return null;
+    }
 
     @Override
     public String grantAccess(DataObject data, EndPoint ep) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b81fa6d9/plugins/storage/image/swift/src/org/apache/cloudstack/storage/datastore/driver/SwiftImageStoreDriverImpl.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 e539e5c..8504de9 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
@@ -29,6 +29,7 @@ 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.DataObjectType;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
+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.VolumeInfo;
 import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
@@ -91,6 +92,11 @@ public class SwiftImageStoreDriverImpl implements ImageStoreDriver {
         // TODO Auto-generated method stub
         return null;
     }
+    
+    @Override
+    public DataTO getTO(DataObject data) {
+        return null;
+    }
 
     @Override
     public boolean revokeAccess(DataObject data, EndPoint ep) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b81fa6d9/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java
----------------------------------------------------------------------
diff --git a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java
index 0486902..412647f 100644
--- a/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java
+++ b/plugins/storage/volume/default/src/org/apache/cloudstack/storage/datastore/driver/CloudStackPrimaryDataStoreDriverImpl.java
@@ -28,6 +28,7 @@ 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.DataObjectType;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
+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.PrimaryDataStoreDriver;
 import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
@@ -90,6 +91,11 @@ public class CloudStackPrimaryDataStoreDriverImpl implements PrimaryDataStoreDri
 		// TODO Auto-generated method stub
 		return null;
 	}
+	
+	@Override
+    public DataTO getTO(DataObject data) {
+        return null;
+    }
 
 	@Override
 	public boolean revokeAccess(DataObject data, EndPoint ep) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b81fa6d9/plugins/storage/volume/sample/src/org/apache/cloudstack/storage/datastore/driver/SamplePrimaryDataStoreDriverImpl.java
----------------------------------------------------------------------
diff --git a/plugins/storage/volume/sample/src/org/apache/cloudstack/storage/datastore/driver/SamplePrimaryDataStoreDriverImpl.java b/plugins/storage/volume/sample/src/org/apache/cloudstack/storage/datastore/driver/SamplePrimaryDataStoreDriverImpl.java
index 67e9843..99b16eb 100644
--- a/plugins/storage/volume/sample/src/org/apache/cloudstack/storage/datastore/driver/SamplePrimaryDataStoreDriverImpl.java
+++ b/plugins/storage/volume/sample/src/org/apache/cloudstack/storage/datastore/driver/SamplePrimaryDataStoreDriverImpl.java
@@ -26,7 +26,9 @@ import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
 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.DataTO;
 import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
+import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
 import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver;
 import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
 import org.apache.cloudstack.framework.async.AsyncCallbackDispatcher;
@@ -36,7 +38,6 @@ import org.apache.cloudstack.storage.command.CreateObjectAnswer;
 import org.apache.cloudstack.storage.command.CreateObjectCommand;
 import org.apache.cloudstack.storage.command.DeleteCommand;
 import org.apache.cloudstack.storage.datastore.DataObjectManager;
-import org.apache.cloudstack.storage.endpoint.EndPointSelector;
 import org.apache.log4j.Logger;
 
 import com.cloud.agent.api.Answer;
@@ -58,6 +59,11 @@ public class SamplePrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver
         
     }
     
+    @Override
+    public DataTO getTO(DataObject data) {
+        return null;
+    }
+    
     private class CreateVolumeContext<T> extends AsyncRpcConext<T> {
         private final DataObject volume;
         /**

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b81fa6d9/plugins/storage/volume/sample/src/org/apache/cloudstack/storage/datastore/lifecycle/SamplePrimaryDataStoreLifeCycleImpl.java
----------------------------------------------------------------------
diff --git a/plugins/storage/volume/sample/src/org/apache/cloudstack/storage/datastore/lifecycle/SamplePrimaryDataStoreLifeCycleImpl.java b/plugins/storage/volume/sample/src/org/apache/cloudstack/storage/datastore/lifecycle/SamplePrimaryDataStoreLifeCycleImpl.java
index 15bf8c1..ddd64e5 100644
--- a/plugins/storage/volume/sample/src/org/apache/cloudstack/storage/datastore/lifecycle/SamplePrimaryDataStoreLifeCycleImpl.java
+++ b/plugins/storage/volume/sample/src/org/apache/cloudstack/storage/datastore/lifecycle/SamplePrimaryDataStoreLifeCycleImpl.java
@@ -26,6 +26,7 @@ import javax.inject.Inject;
 import org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope;
 import org.apache.cloudstack.engine.subsystem.api.storage.DataStore;
 import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
+import org.apache.cloudstack.engine.subsystem.api.storage.EndPointSelector;
 import org.apache.cloudstack.engine.subsystem.api.storage.HostScope;
 import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreLifeCycle;
 import org.apache.cloudstack.engine.subsystem.api.storage.ZoneScope;
@@ -34,7 +35,6 @@ import org.apache.cloudstack.storage.command.CreatePrimaryDataStoreCmd;
 import org.apache.cloudstack.storage.datastore.PrimaryDataStoreProviderManager;
 import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
 import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
-import org.apache.cloudstack.storage.endpoint.EndPointSelector;
 import org.apache.cloudstack.storage.volume.datastore.PrimaryDataStoreHelper;
 
 import com.cloud.agent.api.StoragePoolInfo;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b81fa6d9/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidfirePrimaryDataStoreDriver.java
----------------------------------------------------------------------
diff --git a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidfirePrimaryDataStoreDriver.java b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidfirePrimaryDataStoreDriver.java
index f31126c..3916773 100644
--- a/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidfirePrimaryDataStoreDriver.java
+++ b/plugins/storage/volume/solidfire/src/org/apache/cloudstack/storage/datastore/driver/SolidfirePrimaryDataStoreDriver.java
@@ -23,6 +23,7 @@ import org.apache.cloudstack.engine.subsystem.api.storage.CopyCommandResult;
 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.DataTO;
 import org.apache.cloudstack.engine.subsystem.api.storage.EndPoint;
 import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreDriver;
 import org.apache.cloudstack.engine.subsystem.api.storage.SnapshotInfo;
@@ -35,6 +36,11 @@ public class SolidfirePrimaryDataStoreDriver implements PrimaryDataStoreDriver {
         // TODO Auto-generated method stub
         return null;
     }
+    
+    @Override
+    public DataTO getTO(DataObject data) {
+        return null;
+    }
 
     @Override
     public boolean revokeAccess(DataObject data, EndPoint ep) {

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/b81fa6d9/server/src/com/cloud/template/TemplateManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/template/TemplateManagerImpl.java b/server/src/com/cloud/template/TemplateManagerImpl.java
index 77c6860..aabdaf9 100755
--- a/server/src/com/cloud/template/TemplateManagerImpl.java
+++ b/server/src/com/cloud/template/TemplateManagerImpl.java
@@ -739,8 +739,7 @@ public class TemplateManagerImpl extends ManagerBase implements TemplateManager,
             HostVO secondaryStorageHost = _hostDao.findById(templateHostRef.getHostId());
             assert(secondaryStorageHost != null);
             dcmd.setSecondaryStorageUrl(secondaryStorageHost.getStorageUrl());
-            // TODO temporary hacking, hard-coded to NFS primary data store
-            dcmd.setPrimaryStorageUrl("nfs://" + pool.getHostAddress() + pool.getPath());
+     
             
             for (int retry = 0; retry < 2; retry ++){
             	Collections.shuffle(vos); // Shuffling to pick a random host in the vm deployment retries