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 2012/12/21 04:06:38 UTC

git commit: finaly, finish download template to primary storage

Updated Branches:
  refs/heads/javelin 1d5019c3d -> ac88c16be


finaly, finish download template to primary storage


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

Branch: refs/heads/javelin
Commit: ac88c16be630a16880ae61b581a4eb9b598892a5
Parents: 1d5019c
Author: Edison Su <su...@gmail.com>
Authored: Thu Dec 20 19:05:47 2012 -0800
Committer: Edison Su <su...@gmail.com>
Committed: Thu Dec 20 19:06:02 2012 -0800

----------------------------------------------------------------------
 .../storage/test/DirectAgentManagerSimpleImpl.java |    7 +
 .../cloudstack/storage/test/DirectAgentTest.java   |    6 +-
 ...ockHostEndpointRpcServerDirectCallResource.java |   87 +++++++++++++++
 .../test/MockHypervsiorHostEndPointRpcServer.java  |   10 ++-
 .../cloudstack/storage/test/volumeServiceTest.java |    4 +-
 .../cloudstack/storage/HostEndpointRpcServer.java  |    3 +-
 .../cloudstack/storage/HypervisorHostEndPoint.java |   22 ++--
 .../storage/HypervsiorHostEndPointRpcServer.java   |   56 +++++++++-
 .../command/AttachPrimaryDataStoreAnswer.java      |   55 +++++++++
 .../storage/command/AttachPrimaryDataStoreCmd.java |   41 +++++++
 .../DefaultPrimaryDataStoreLifeCycleImpl.java      |   24 +++-
 .../xen/resource/CitrixResourceBase.java           |   26 ++--
 .../xen/resource/XenServerStorageResource.java     |   62 +++++++++-
 scripts/vm/hypervisor/xenserver/mockxcpplugin.py   |   66 +++++++++++
 scripts/vm/hypervisor/xenserver/storagePlugin      |   37 +++++--
 scripts/vm/hypervisor/xenserver/xcposs/patch       |    1 +
 16 files changed, 447 insertions(+), 60 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/ac88c16b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/DirectAgentManagerSimpleImpl.java
----------------------------------------------------------------------
diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/DirectAgentManagerSimpleImpl.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/DirectAgentManagerSimpleImpl.java
index 080e65b..6d09561 100644
--- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/DirectAgentManagerSimpleImpl.java
+++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/DirectAgentManagerSimpleImpl.java
@@ -31,12 +31,14 @@ import com.cloud.agent.Listener;
 import com.cloud.agent.StartupCommandProcessor;
 import com.cloud.agent.api.Answer;
 import com.cloud.agent.api.Command;
+import com.cloud.agent.api.SetupCommand;
 import com.cloud.agent.api.StartupCommand;
 import com.cloud.agent.manager.AgentAttache;
 import com.cloud.agent.manager.Commands;
 import com.cloud.exception.AgentUnavailableException;
 import com.cloud.exception.ConnectionException;
 import com.cloud.exception.OperationTimedoutException;
+import com.cloud.host.HostEnvironment;
 import com.cloud.host.HostVO;
 import com.cloud.host.Status.Event;
 import com.cloud.host.dao.HostDao;
@@ -100,6 +102,11 @@ public class DirectAgentManagerSimpleImpl implements AgentManager {
         } catch (ConfigurationException e) {
             logger.debug("Failed to load resource:" + e.toString());
         }
+        HostEnvironment env = new HostEnvironment();
+        SetupCommand cmd = new SetupCommand(env);
+        cmd.setNeedSetup(true);
+        
+        resource.executeRequest(cmd);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/ac88c16b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/DirectAgentTest.java
----------------------------------------------------------------------
diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/DirectAgentTest.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/DirectAgentTest.java
index 2f5e7ae..072535b 100644
--- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/DirectAgentTest.java
+++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/DirectAgentTest.java
@@ -69,7 +69,7 @@ public class DirectAgentTest {
     private long dcId;
     private long clusterId;
     private long hostId;
-    private String hostGuid = "759ee4c9-a15a-297b-67c6-ac267d8aa429";
+    private String hostGuid = "9d4c9db8-32f7-25c3-0435-eab4bf3adcea";
     @Before
     public void setUp() {
         HostVO host = hostDao.findByGuid(hostGuid);
@@ -102,7 +102,7 @@ public class DirectAgentTest {
         host.setName("devcloud xen host");
         host.setType(Host.Type.Routing);
         host.setHypervisorType(HypervisorType.XenServer);
-        host.setPrivateIpAddress("192.168.56.2");
+        host.setPrivateIpAddress("192.168.56.10");
         host.setDataCenterId(dc.getId());
         host.setVersion("6.0.1");
         host.setAvailable(true);
@@ -133,7 +133,7 @@ public class DirectAgentTest {
     public void testDownloadTemplate() {
         ImageOnPrimayDataStoreTO image = Mockito.mock(ImageOnPrimayDataStoreTO.class);
         PrimaryDataStoreTO primaryStore = Mockito.mock(PrimaryDataStoreTO.class);
-        Mockito.when(primaryStore.getUuid()).thenReturn("cd10cac1-4772-92e5-5da6-c2bc16b1ce1b");
+        Mockito.when(primaryStore.getUuid()).thenReturn("9f3f9262-3f77-09cc-2df7-0d8475676260");
         Mockito.when(image.getPrimaryDataStore()).thenReturn(primaryStore);
         
         ImageDataStoreTO imageStore = Mockito.mock(ImageDataStoreTO.class);

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/ac88c16b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockHostEndpointRpcServerDirectCallResource.java
----------------------------------------------------------------------
diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockHostEndpointRpcServerDirectCallResource.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockHostEndpointRpcServerDirectCallResource.java
new file mode 100644
index 0000000..f2272ce
--- /dev/null
+++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockHostEndpointRpcServerDirectCallResource.java
@@ -0,0 +1,87 @@
+/*
+ * 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.test;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+
+import javax.inject.Inject;
+
+
+import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
+
+import org.apache.cloudstack.storage.HostEndpointRpcServer;
+import org.apache.cloudstack.storage.HypervisorHostEndPoint;
+
+import org.apache.log4j.Logger;
+
+import com.cloud.agent.AgentManager;
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.Command;
+import com.cloud.exception.AgentUnavailableException;
+import com.cloud.exception.OperationTimedoutException;
+
+
+public class MockHostEndpointRpcServerDirectCallResource implements HostEndpointRpcServer {
+    private static final Logger s_logger = Logger.getLogger(MockHostEndpointRpcServerDirectCallResource.class);
+    private ScheduledExecutorService executor;
+    @Inject
+    AgentManager agentMgr;
+    public MockHostEndpointRpcServerDirectCallResource() {
+        executor = Executors.newScheduledThreadPool(10);
+    }
+    protected class MockRpcCallBack implements Runnable {
+        private final Command cmd;
+        private final long hostId;
+        private final AsyncCompletionCallback<Answer> callback; 
+        public MockRpcCallBack(long hostId, Command cmd, final AsyncCompletionCallback<Answer> callback) {
+            this.cmd = cmd;
+            this.callback = callback;
+            this.hostId = hostId;
+        }
+        @Override
+        public void run() {
+            try {
+                Answer answer = agentMgr.send(hostId, cmd);
+                callback.complete(answer);
+            } catch (Exception e) {
+                s_logger.debug("send command failed:" + e.toString());
+            }
+        }
+        
+    }
+    
+    public void sendCommandAsync(HypervisorHostEndPoint host, final Command command, final AsyncCompletionCallback<Answer> callback) {
+        executor.schedule(new MockRpcCallBack(host.getHostId(), command, callback), 10, TimeUnit.SECONDS);
+    }
+
+    @Override
+    public Answer sendCommand(HypervisorHostEndPoint host, Command command) {
+        Answer answer;
+        try {
+            answer = agentMgr.send(host.getHostId(), command);
+            return answer;
+        } catch (AgentUnavailableException e) {
+           return null;
+        } catch (OperationTimedoutException e) {
+           return null;
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/ac88c16b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockHypervsiorHostEndPointRpcServer.java
----------------------------------------------------------------------
diff --git a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockHypervsiorHostEndPointRpcServer.java b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockHypervsiorHostEndPointRpcServer.java
index 35b5bb1..6c5ee19 100644
--- a/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockHypervsiorHostEndPointRpcServer.java
+++ b/engine/storage/integration-test/test/org/apache/cloudstack/storage/test/MockHypervsiorHostEndPointRpcServer.java
@@ -25,6 +25,7 @@ import java.util.concurrent.TimeUnit;
 
 import org.apache.cloudstack.framework.async.AsyncCompletionCallback;
 import org.apache.cloudstack.storage.HostEndpointRpcServer;
+import org.apache.cloudstack.storage.HypervisorHostEndPoint;
 import org.apache.cloudstack.storage.command.CopyTemplateToPrimaryStorageCmd;
 import org.apache.cloudstack.storage.command.CopyTemplateToPrimaryStorageAnswer;
 import org.apache.cloudstack.storage.command.CreateVolumeAnswer;
@@ -63,7 +64,14 @@ public class MockHypervsiorHostEndPointRpcServer implements HostEndpointRpcServe
         }
         
     }
-    public void sendCommandAsync(String host, final Command command, final AsyncCompletionCallback<Answer> callback) {
+    
+    public void sendCommandAsync(HypervisorHostEndPoint host, final Command command, final AsyncCompletionCallback<Answer> callback) {
         executor.schedule(new MockRpcCallBack(command, callback), 10, TimeUnit.SECONDS);
     }
+    
+    @Override
+    public Answer sendCommand(HypervisorHostEndPoint host, Command command) {
+        // TODO Auto-generated method stub
+        return null;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/ac88c16b/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 59a7554..238de2b 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
@@ -158,7 +158,7 @@ public class volumeServiceTest {
 		HostVO host = new HostVO(UUID.randomUUID().toString());
 		host.setName("devcloud xen host");
 		host.setType(Host.Type.Routing);
-		host.setPrivateIpAddress("192.168.56.2");
+		host.setPrivateIpAddress("192.168.56.10");
 		host.setDataCenterId(dc.getId());
 		host.setVersion("6.0.1");
 		host.setAvailable(true);
@@ -237,7 +237,7 @@ public class volumeServiceTest {
 			PrimaryDataStoreProvider provider = primaryDataStoreProviderMgr.getDataStoreProvider("default primary data store provider");
 
 			Map<String, String> params = new HashMap<String, String>();
-			params.put("url", "nfs://test/test");
+			params.put("url", "nfs://localhost/primarynfs");
 			params.put("dcId", dcId.toString());
 			params.put("clusterId", clusterId.toString());
 			params.put("name", "my primary data store");

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/ac88c16b/engine/storage/src/org/apache/cloudstack/storage/HostEndpointRpcServer.java
----------------------------------------------------------------------
diff --git a/engine/storage/src/org/apache/cloudstack/storage/HostEndpointRpcServer.java b/engine/storage/src/org/apache/cloudstack/storage/HostEndpointRpcServer.java
index 25ebc7f..a316223 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/HostEndpointRpcServer.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/HostEndpointRpcServer.java
@@ -24,5 +24,6 @@ import com.cloud.agent.api.Answer;
 import com.cloud.agent.api.Command;
 
 public interface HostEndpointRpcServer {
-    void sendCommandAsync(String host, final Command command, final AsyncCompletionCallback<Answer> callback);
+    void sendCommandAsync(HypervisorHostEndPoint ep, final Command command, final AsyncCompletionCallback<Answer> callback);
+    Answer sendCommand(HypervisorHostEndPoint ep, final Command command);
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/ac88c16b/engine/storage/src/org/apache/cloudstack/storage/HypervisorHostEndPoint.java
----------------------------------------------------------------------
diff --git a/engine/storage/src/org/apache/cloudstack/storage/HypervisorHostEndPoint.java b/engine/storage/src/org/apache/cloudstack/storage/HypervisorHostEndPoint.java
index 7e5387d..a2e9ea9 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/HypervisorHostEndPoint.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/HypervisorHostEndPoint.java
@@ -42,24 +42,22 @@ public class HypervisorHostEndPoint implements EndPoint {
         this.hostId = hostId;
         this.hostAddress = hostAddress;
     }
+    
+    public String getHostAddr() {
+        return this.hostAddress;
+    }
+    
+    public long getHostId() {
+        return this.hostId;
+    }
 
     @Override
     public Answer sendMessage(Command cmd) {
-        Answer answer = null;
-        try {
-            answer = agentMgr.send(hostId, cmd);
-        } catch (AgentUnavailableException e) {
-            s_logger.debug("Unable to send command:" + cmd + ", due to: " + e.toString());
-        } catch (OperationTimedoutException e) {
-            s_logger.debug("Unable to send command:" + cmd + ", due to: " + e.toString());
-        } catch (Exception e) {
-            s_logger.debug("Unable to send command:" + cmd + ", due to: " + e.toString());
-        }
-        return answer;
+        return rpcServer.sendCommand(this, cmd);
     }
     
     @Override
     public void sendMessageAsync(Command cmd, AsyncCompletionCallback<Answer> callback) {
-        rpcServer.sendCommandAsync(this.hostAddress, cmd, callback);
+        rpcServer.sendCommandAsync(this, cmd, callback);
     }
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/ac88c16b/engine/storage/src/org/apache/cloudstack/storage/HypervsiorHostEndPointRpcServer.java
----------------------------------------------------------------------
diff --git a/engine/storage/src/org/apache/cloudstack/storage/HypervsiorHostEndPointRpcServer.java b/engine/storage/src/org/apache/cloudstack/storage/HypervsiorHostEndPointRpcServer.java
index de7b386..0975869 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/HypervsiorHostEndPointRpcServer.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/HypervsiorHostEndPointRpcServer.java
@@ -20,19 +20,23 @@ package org.apache.cloudstack.storage;
 
 import javax.inject.Inject;
 
+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.framework.rpc.RpcCallbackListener;
 import org.apache.cloudstack.framework.rpc.RpcException;
 import org.apache.cloudstack.framework.rpc.RpcProvider;
 import org.apache.cloudstack.framework.rpc.RpcServiceDispatcher;
+import org.apache.log4j.Logger;
 import org.springframework.stereotype.Component;
 
 import com.cloud.agent.api.Answer;
 import com.cloud.agent.api.Command;
+import com.cloud.utils.exception.CloudRuntimeException;
 
 @Component
 public class HypervsiorHostEndPointRpcServer implements HostEndpointRpcServer {
-    
+    private static final Logger s_logger = Logger.getLogger(HypervsiorHostEndPointRpcServer.class);
     private RpcProvider _rpcProvider;
     @Inject
     public HypervsiorHostEndPointRpcServer(RpcProvider rpcProvider) {
@@ -41,8 +45,8 @@ public class HypervsiorHostEndPointRpcServer implements HostEndpointRpcServer {
     }
     
     @Override
-    public void sendCommandAsync(String host, final Command command, final AsyncCompletionCallback<Answer> callback) {
-        _rpcProvider.newCall(host).addCallbackListener(new RpcCallbackListener<Answer>() {
+    public void sendCommandAsync(HypervisorHostEndPoint host, final Command command, final AsyncCompletionCallback<Answer> callback) {
+        _rpcProvider.newCall(host.getHostAddr()).addCallbackListener(new RpcCallbackListener<Answer>() {
             @Override
             public void onSuccess(Answer result) {
                 callback.complete(result);
@@ -55,4 +59,50 @@ public class HypervsiorHostEndPointRpcServer implements HostEndpointRpcServer {
             }
         }).apply();
     }
+    
+    private class SendCommandContext<T> extends AsyncRpcConext<T> {
+        private T answer;
+       
+        public SendCommandContext(AsyncCompletionCallback<T> callback) {
+            super(callback);
+        }
+        
+        public void setAnswer(T answer) {
+            this.answer = answer;
+        }
+        
+        public T getAnswer() {
+            return this.answer;
+        }
+        
+    }
+
+    @Override
+    public Answer sendCommand(HypervisorHostEndPoint host, Command command) {
+        SendCommandContext<Answer> context = new SendCommandContext<Answer>(null);
+        AsyncCallbackDispatcher<HypervsiorHostEndPointRpcServer> caller = AsyncCallbackDispatcher.create(this);
+        caller.setCallback(caller.getTarget().sendCommandCallback(null, null))
+        .setContext(context);
+        
+        this.sendCommandAsync(host, command, caller);
+        
+        synchronized (context) {
+            try {
+                context.wait();
+            } catch (InterruptedException e) {
+                s_logger.debug(e.toString());
+                throw new CloudRuntimeException("wait on context is interrupted", e);
+            }
+        }
+        
+        return context.getAnswer();
+    }
+    
+    protected Object sendCommandCallback(AsyncCallbackDispatcher<HypervsiorHostEndPointRpcServer> callback, SendCommandContext<Answer> context) {
+        context.setAnswer((Answer)callback.getResult());
+        synchronized(context) {
+            context.notify();
+        }
+        return null;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/ac88c16b/engine/storage/src/org/apache/cloudstack/storage/command/AttachPrimaryDataStoreAnswer.java
----------------------------------------------------------------------
diff --git a/engine/storage/src/org/apache/cloudstack/storage/command/AttachPrimaryDataStoreAnswer.java b/engine/storage/src/org/apache/cloudstack/storage/command/AttachPrimaryDataStoreAnswer.java
new file mode 100644
index 0000000..cd15030
--- /dev/null
+++ b/engine/storage/src/org/apache/cloudstack/storage/command/AttachPrimaryDataStoreAnswer.java
@@ -0,0 +1,55 @@
+/*
+ * 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.command;
+
+import com.cloud.agent.api.Answer;
+import com.cloud.agent.api.Command;
+
+public class AttachPrimaryDataStoreAnswer extends Answer {
+    private String uuid;
+    private long capacity;
+    private long avail;
+    public AttachPrimaryDataStoreAnswer(Command cmd) {
+        super(cmd);
+    }
+    
+    public void setUuid(String uuid) {
+        this.uuid = uuid;
+    }
+    
+    public String getUuid() {
+        return this.uuid;
+    }
+    
+    public void setCapacity(long capacity) {
+        this.capacity = capacity;
+    }
+    
+    public long getCapacity() {
+        return this.capacity;
+    }
+    
+    public void setAvailable(long avail) {
+        this.avail = avail;
+    }
+    
+    public long getAvailable() {
+        return this.avail;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/ac88c16b/engine/storage/src/org/apache/cloudstack/storage/command/AttachPrimaryDataStoreCmd.java
----------------------------------------------------------------------
diff --git a/engine/storage/src/org/apache/cloudstack/storage/command/AttachPrimaryDataStoreCmd.java b/engine/storage/src/org/apache/cloudstack/storage/command/AttachPrimaryDataStoreCmd.java
new file mode 100644
index 0000000..53400a3
--- /dev/null
+++ b/engine/storage/src/org/apache/cloudstack/storage/command/AttachPrimaryDataStoreCmd.java
@@ -0,0 +1,41 @@
+/*
+ * 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.command;
+
+import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo;
+import org.apache.cloudstack.storage.to.PrimaryDataStoreTO;
+
+import com.cloud.agent.api.Command;
+
+public class AttachPrimaryDataStoreCmd extends Command implements StorageSubSystemCommand {
+    private final PrimaryDataStoreTO dataStore;
+    public AttachPrimaryDataStoreCmd(PrimaryDataStoreInfo dataStore) {
+        this.dataStore = new PrimaryDataStoreTO(dataStore);
+    }
+    
+    public PrimaryDataStoreTO getDataStore() {
+        return this.dataStore;
+    }
+
+    @Override
+    public boolean executeInSequence() {
+        // TODO Auto-generated method stub
+        return false;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/ac88c16b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/lifecycle/DefaultPrimaryDataStoreLifeCycleImpl.java
----------------------------------------------------------------------
diff --git a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/lifecycle/DefaultPrimaryDataStoreLifeCycleImpl.java b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/lifecycle/DefaultPrimaryDataStoreLifeCycleImpl.java
index dc304a1..7f55797 100644
--- a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/lifecycle/DefaultPrimaryDataStoreLifeCycleImpl.java
+++ b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/lifecycle/DefaultPrimaryDataStoreLifeCycleImpl.java
@@ -23,12 +23,15 @@ import java.util.Map;
 import org.apache.cloudstack.engine.subsystem.api.storage.ClusterScope;
 import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreInfo;
 import org.apache.cloudstack.engine.subsystem.api.storage.PrimaryDataStoreLifeCycle;
+import org.apache.cloudstack.storage.EndPoint;
+import org.apache.cloudstack.storage.command.AttachPrimaryDataStoreCmd;
 import org.apache.cloudstack.storage.datastore.DataStoreStatus;
+import org.apache.cloudstack.storage.datastore.PrimaryDataStore;
 import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
 import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreVO;
 
 public class DefaultPrimaryDataStoreLifeCycleImpl implements PrimaryDataStoreLifeCycle {
-    protected PrimaryDataStoreInfo dataStore;
+    protected PrimaryDataStore dataStore;
     protected PrimaryDataStoreDao dataStoreDao;
     public DefaultPrimaryDataStoreLifeCycleImpl(PrimaryDataStoreDao dataStoreDao) {
         this.dataStoreDao = dataStoreDao;
@@ -36,7 +39,7 @@ public class DefaultPrimaryDataStoreLifeCycleImpl implements PrimaryDataStoreLif
     
     @Override
     public void setDataStore(PrimaryDataStoreInfo dataStore) {
-        this.dataStore = dataStore;
+        this.dataStore = (PrimaryDataStore)dataStore;
     }
     
     @Override
@@ -50,11 +53,18 @@ public class DefaultPrimaryDataStoreLifeCycleImpl implements PrimaryDataStoreLif
 
     @Override
     public boolean attachCluster(ClusterScope scope) {
-        PrimaryDataStoreVO dataStore = dataStoreDao.findById(this.dataStore.getId());
-        dataStore.setDataCenterId(scope.getZoneId());
-        dataStore.setPodId(scope.getPodId());
-        dataStore.setClusterId(scope.getScopeId());
-        dataStoreDao.update(this.dataStore.getId(), dataStore);
+        PrimaryDataStoreVO dataStoreVO = dataStoreDao.findById(this.dataStore.getId());
+        dataStoreVO.setDataCenterId(scope.getZoneId());
+        dataStoreVO.setPodId(scope.getPodId());
+        dataStoreVO.setClusterId(scope.getScopeId());
+        dataStoreVO.setStatus(DataStoreStatus.Up);
+        dataStoreDao.update(dataStoreVO.getId(), dataStoreVO);
+        
+        //send down createStoragePool command to all the hosts in the cluster
+        AttachPrimaryDataStoreCmd cmd = new AttachPrimaryDataStoreCmd(this.dataStore);
+        for (EndPoint ep : dataStore.getEndPoints()) {
+            ep.sendMessage(cmd);
+        }
         return false;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/ac88c16b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
----------------------------------------------------------------------
diff --git a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
index 611913a..9cd1bf6 100644
--- a/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
+++ b/plugins/hypervisors/xen/src/com/cloud/hypervisor/xen/resource/CitrixResourceBase.java
@@ -5042,7 +5042,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
         boolean add = cmd.getAdd();
         if( add ) {
             try {
-                SR sr = getStorageRepository(conn, pool);
+                SR sr = getStorageRepository(conn, pool.getUuid());
                 setupHeartbeatSr(conn, sr, false);
                 long capacity = sr.getPhysicalSize(conn);
                 long available = capacity - sr.getPhysicalUtilisation(conn);
@@ -5065,7 +5065,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
             }
         } else {
             try {
-                SR sr = getStorageRepository(conn, pool);
+                SR sr = getStorageRepository(conn, pool.getUuid());
                 String srUuid = sr.getUuid(conn);
                 String result = callHostPluginPremium(conn, "setup_heartbeat_file", "host", _host.uuid, "sr", srUuid, "add", "false");
                 if (result == null || !result.split("#")[1].equals("0")) {
@@ -5330,7 +5330,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
         Connection conn = getConnection();
         StorageFilerTO poolTO = cmd.getPool();
         try {
-            SR sr = getStorageRepository(conn, poolTO);
+            SR sr = getStorageRepository(conn, poolTO.getUuid());
             removeSR(conn, sr);
             Answer answer = new Answer(cmd, true, "success");
             return answer;
@@ -5587,7 +5587,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
         DiskProfile dskch = cmd.getDiskCharacteristics();
         VDI vdi = null;
         try {
-            SR poolSr = getStorageRepository(conn, pool);
+            SR poolSr = getStorageRepository(conn, pool.getUuid());
             if (cmd.getTemplateUrl() != null) {
                 VDI tmpltvdi = null;
                 
@@ -5973,7 +5973,7 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
             String remoteVolumesMountPath = uri.getHost() + ":" + uri.getPath() + "/volumes/";
             String volumeFolder = String.valueOf(cmd.getVolumeId()) + "/";
             String mountpoint = remoteVolumesMountPath + volumeFolder;
-            SR primaryStoragePool = getStorageRepository(conn, poolTO);
+            SR primaryStoragePool = getStorageRepository(conn, poolTO.getUuid());
             String srUuid = primaryStoragePool.getUuid(conn);
             if (toSecondaryStorage) {
                 // Create the volume folder
@@ -6685,30 +6685,30 @@ public abstract class CitrixResourceBase implements ServerResource, HypervisorRe
         }
     }
 
-    protected SR getStorageRepository(Connection conn, StorageFilerTO pool) {
+    protected SR getStorageRepository(Connection conn, String uuid) {
         Set<SR> srs;
         try {
-            srs = SR.getByNameLabel(conn, pool.getUuid());
+            srs = SR.getByNameLabel(conn, uuid);
         } catch (XenAPIException e) {
-            throw new CloudRuntimeException("Unable to get SR " + pool.getUuid() + " due to " + e.toString(), e);
+            throw new CloudRuntimeException("Unable to get SR " + uuid + " due to " + e.toString(), e);
         } catch (Exception e) {
-            throw new CloudRuntimeException("Unable to get SR " + pool.getUuid() + " due to " + e.getMessage(), e);
+            throw new CloudRuntimeException("Unable to get SR " + uuid + " due to " + e.getMessage(), e);
         }
 
         if (srs.size() > 1) {
-            throw new CloudRuntimeException("More than one storage repository was found for pool with uuid: " + pool.getUuid());
+            throw new CloudRuntimeException("More than one storage repository was found for pool with uuid: " + uuid);
         } else if (srs.size() == 1) {
             SR sr = srs.iterator().next();
             if (s_logger.isDebugEnabled()) {
-                s_logger.debug("SR retrieved for " + pool.getId());
+                s_logger.debug("SR retrieved for " + uuid);
             }
 
             if (checkSR(conn, sr)) {
                 return sr;
             }
-            throw new CloudRuntimeException("SR check failed for storage pool: " + pool.getUuid() + "on host:" + _host.uuid);
+            throw new CloudRuntimeException("SR check failed for storage pool: " + uuid + "on host:" + _host.uuid);
         } else {
-            throw new CloudRuntimeException("Can not see storage pool: " + pool.getUuid() + " from on host:" + _host.uuid);
+            throw new CloudRuntimeException("Can not see storage pool: " + uuid + " from on host:" + _host.uuid);
         }
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/ac88c16b/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 8789bb7..f47b080 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,6 +28,8 @@ import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
 
+import org.apache.cloudstack.storage.command.AttachPrimaryDataStoreAnswer;
+import org.apache.cloudstack.storage.command.AttachPrimaryDataStoreCmd;
 import org.apache.cloudstack.storage.command.CopyTemplateToPrimaryStorageCmd;
 import org.apache.cloudstack.storage.command.CopyTemplateToPrimaryStorageAnswer;
 import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
@@ -51,7 +53,10 @@ import org.apache.xmlrpc.XmlRpcException;
 
 import com.cloud.agent.api.Answer;
 import com.cloud.agent.api.Command;
+import com.cloud.agent.api.ModifyStoragePoolAnswer;
 import com.cloud.agent.api.storage.PrimaryStorageDownloadAnswer;
+import com.cloud.agent.api.to.StorageFilerTO;
+import com.cloud.storage.template.TemplateInfo;
 import com.cloud.utils.exception.CloudRuntimeException;
 import com.xensource.xenapi.Connection;
 import com.xensource.xenapi.PBD;
@@ -72,11 +77,25 @@ public class XenServerStorageResource {
     public Answer handleStorageCommands(StorageSubSystemCommand command) {
         if (command instanceof CopyTemplateToPrimaryStorageCmd) {
             return this.execute((CopyTemplateToPrimaryStorageCmd)command);
+        } else if (command instanceof AttachPrimaryDataStoreCmd) {
+            return this.execute((AttachPrimaryDataStoreCmd)command);
         }
         return new Answer((Command)command, false, "not implemented yet"); 
     }
     
-    private long getTemplateSize(String url) {
+    private long getTemplateSize(Connection conn, String url) {
+        String size = hypervisorResource.callHostPlugin(conn, "storagePlugin", "getTemplateSize", "srcUrl", url);
+        if (size == "" || size == null) {
+            throw new CloudRuntimeException("Can't get template size");
+        }
+        
+        try {
+            return Long.parseLong(size);
+        } catch (NumberFormatException e) {
+            throw new CloudRuntimeException("Failed to get template lenght", e);
+        }
+        
+        /*
         HttpHead method = new HttpHead(url);
         DefaultHttpClient client = new DefaultHttpClient();
         try {
@@ -93,7 +112,7 @@ public class XenServerStorageResource {
             throw new CloudRuntimeException("Failed to get template lenght", e);
         } catch (NumberFormatException e) {
             throw new CloudRuntimeException("Failed to get template lenght", e);
-        }
+        }*/
     }
     
     private void downloadHttpToLocalFile(String destFilePath, String url) {
@@ -143,17 +162,17 @@ public class XenServerStorageResource {
         boolean result = false;
         try {
             
-            Set<SR> srs = SR.getByNameLabel(conn, primaryStoreUuid);
-            if (srs.size() != 1) {
+            SR sr = SR.getByUuid(conn, primaryStoreUuid);
+            if (sr == null) {
                 throw new CloudRuntimeException("storage uuid: " + primaryStoreUuid + " is not unique");
             }
-            poolsr = srs.iterator().next();
+            poolsr = sr;
             VDI.Record vdir = new VDI.Record();
             vdir.nameLabel = "Base-Image-" + UUID.randomUUID().toString();
             vdir.SR = poolsr;
             vdir.type = Types.VdiType.USER;
             
-            vdir.virtualSize = getTemplateSize(template.getPath());
+            vdir.virtualSize = getTemplateSize(conn, template.getPath());
             vdi = VDI.create(conn, vdir);
             
             vdir = vdi.getRecord(conn);
@@ -172,7 +191,7 @@ public class XenServerStorageResource {
             String vdiPath = pbdLocation + "/" + vdiLocation + ".vhd";
             //download a url into vdipath
             //downloadHttpToLocalFile(vdiPath, template.getPath());
-            hypervisorResource.callHostPlugin(conn, "vmopsStorage", "downloadTemplateFromUrl", "destPath", vdiPath, "srcUrl", template.getPath());
+            hypervisorResource.callHostPlugin(conn, "storagePlugin", "downloadTemplateFromUrl", "destPath", vdiPath, "srcUrl", template.getPath());
             result = true;
             return new CopyTemplateToPrimaryStorageAnswer(cmd, vdi.getUuid(conn));
         } catch (BadServerResponse e) {
@@ -199,6 +218,35 @@ public class XenServerStorageResource {
         return new Answer(cmd, false, "Failed to download template");
     }
     
+    protected Answer execute(AttachPrimaryDataStoreCmd cmd) {
+        PrimaryDataStoreTO dataStore = cmd.getDataStore();
+        Connection conn = hypervisorResource.getConnection();
+        try {
+            SR sr = hypervisorResource.getStorageRepository(conn, dataStore.getUuid());
+            hypervisorResource.setupHeartbeatSr(conn, sr, false);
+            long capacity = sr.getPhysicalSize(conn);
+            long available = capacity - sr.getPhysicalUtilisation(conn);
+            if (capacity == -1) {
+                String msg = "Pool capacity is -1! pool: ";
+                s_logger.warn(msg);
+                return new Answer(cmd, false, msg);
+            }
+            AttachPrimaryDataStoreAnswer answer = new AttachPrimaryDataStoreAnswer(cmd);
+            answer.setCapacity(capacity);
+            answer.setUuid(sr.getUuid(conn));
+            answer.setAvailable(available);
+            return answer;
+        } catch (XenAPIException e) {
+            String msg = "AttachPrimaryDataStoreCmd add XenAPIException:" + e.toString();
+            s_logger.warn(msg, e);
+            return new Answer(cmd, false, msg);
+        } catch (Exception e) {
+            String msg = "AttachPrimaryDataStoreCmd failed:" + e.getMessage();
+            s_logger.warn(msg, e);
+            return new Answer(cmd, false, msg);
+        }
+    }
+    
     protected Answer execute(CopyTemplateToPrimaryStorageCmd cmd) {
         ImageOnPrimayDataStoreTO imageTO = cmd.getImage();
         TemplateTO template = imageTO.getTemplate();

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/ac88c16b/scripts/vm/hypervisor/xenserver/mockxcpplugin.py
----------------------------------------------------------------------
diff --git a/scripts/vm/hypervisor/xenserver/mockxcpplugin.py b/scripts/vm/hypervisor/xenserver/mockxcpplugin.py
new file mode 100644
index 0000000..0de24ca
--- /dev/null
+++ b/scripts/vm/hypervisor/xenserver/mockxcpplugin.py
@@ -0,0 +1,66 @@
+#!/usr/bin/python
+# 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.
+
+# This is for test purpose, to test xcp plugin
+
+import sys
+import XenAPI
+import os.path
+import traceback
+import socket
+def getHost():
+    hostname = socket.gethostname()
+    url = "http://localhost"
+    session = XenAPI.Session(url)
+    session.xenapi.login_with_password("root", "password")
+    host = session.xenapi.host
+    hosts = session.xenapi.host.get_by_name_label(hostname)
+    if len(hosts) != 1:
+        print "can't find host:" + hostname
+        sys.exit(1)
+    localhost = hosts[0]
+    return [host, localhost]
+
+def callPlugin(pluginName, func, params):
+    hostPair = getHost()
+    host = hostPair[0]
+    localhost = hostPair[1]
+    return host.call_plugin(localhost, pluginName, func, params)
+
+def main():
+    if len(sys.argv) < 3:
+        print "args: pluginName funcName params"
+        sys.exit(1)
+
+    pluginName = sys.argv[1]
+    funcName = sys.argv[2]
+
+    paramList = sys.argv[3:]
+    if (len(paramList) % 2) != 0:
+        print "params must be name/value pair"
+        sys.exit(2)
+    params = {}
+    pos = 0;
+    for i in range(len(paramList) / 2):
+        params[str(paramList[pos])] = str(paramList[pos+1])
+        pos = pos + 2
+    print "call: " + pluginName + " " + funcName + ", with params: " + str(params)
+    print "return: " +  callPlugin(pluginName, funcName, params)
+
+if __name__ == "__main__":
+    main()

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/ac88c16b/scripts/vm/hypervisor/xenserver/storagePlugin
----------------------------------------------------------------------
diff --git a/scripts/vm/hypervisor/xenserver/storagePlugin b/scripts/vm/hypervisor/xenserver/storagePlugin
index df1c340..7cb6e35 100755
--- a/scripts/vm/hypervisor/xenserver/storagePlugin
+++ b/scripts/vm/hypervisor/xenserver/storagePlugin
@@ -22,24 +22,23 @@
 
 import os, sys, time
 import XenAPIPlugin
-sys.path.extend(["/opt/xensource/sm/", "/usr/local/sbin/", "/sbin/"])
+sys.path.extend(["/usr/lib/xcp/sm/", "/usr/local/sbin/", "/sbin/"])
+import util
 import base64
-import hostvmstats
 import socket
 import stat
 import tempfile
-import util
 import subprocess
 import zlib
 import urllib2
-from util import CommandException
+import traceback
 
 def echo(fn):
     def wrapped(*v, **k):
         name = fn.__name__
-        util.SMlog("#### VMOPS enter  %s ####" % name )
+        util.SMlog("#### xen plugin enter  %s ####" % name )
         res = fn(*v, **k)
-        util.SMlog("#### VMOPS exit  %s ####" % name )
+        util.SMlog("#### xen plugin exit  %s ####" % name )
         return res
     return wrapped
 
@@ -47,10 +46,26 @@ def echo(fn):
 def downloadTemplateFromUrl(session, args):
     destPath = args["destPath"]
     srcUrl = args["srcUrl"]
-    template = urllib2.urlopen(srcUrl)
-    destFile = open(destPath, "wb")
-    destFile.write(template.read())
-    destFile.close()
+    try:
+        template = urllib2.urlopen(srcUrl)
+        destFile = open(destPath, "wb")
+        destFile.write(template.read())
+        destFile.close()
+        return "success"
+    except:
+        util.SMlog("exception: " + str(sys.exc_info()))
+        return ""
     
+@echo
+def getTemplateSize(session, args):
+   srcUrl = args["srcUrl"]
+   try:
+       template = urllib2.urlopen(srcUrl)
+       headers = template.info()
+       return str(headers["Content-Length"])
+   except:
+       return ""
 if __name__ == "__main__":
-    XenAPIPlugin.dispatch({"downloadTemplateFromUrl": downloadTemplateFromUrl})
+    XenAPIPlugin.dispatch({"downloadTemplateFromUrl": downloadTemplateFromUrl
+                           ,"getTemplateSize": getTemplateSize
+                          })

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/ac88c16b/scripts/vm/hypervisor/xenserver/xcposs/patch
----------------------------------------------------------------------
diff --git a/scripts/vm/hypervisor/xenserver/xcposs/patch b/scripts/vm/hypervisor/xenserver/xcposs/patch
index 2ab9421..1b615b7 100644
--- a/scripts/vm/hypervisor/xenserver/xcposs/patch
+++ b/scripts/vm/hypervisor/xenserver/xcposs/patch
@@ -64,3 +64,4 @@ cloud-prepare-upgrade.sh=..,0755,/usr/lib/xcp/bin
 getRouterStatus.sh=../../../../network/domr/,0755,/usr/lib/xcp/bin
 bumpUpPriority.sh=../../../../network/domr/,0755,/usr/lib/xcp/bin
 getDomRVersion.sh=../../../../network/domr/,0755,/usr/lib/xcp/bin
+storagePlugin=.,0755,/usr/lib/xcp/plugins