Updated Branches:
  refs/heads/javelin ed17281f0 -> 9410cd1f3

add deletevolume and createdata disk


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

Branch: refs/heads/javelin
Commit: 9410cd1f3ca1dabd1f66a20495cfb4c203c2d54e
Parents: ed17281
Author: Edison Su <[email protected]>
Authored: Thu Jan 3 18:55:55 2013 -0800
Committer: Edison Su <[email protected]>
Committed: Thu Jan 3 18:56:18 2013 -0800

----------------------------------------------------------------------
 api/src/com/cloud/storage/Volume.java              |    3 +-
 .../engine/subsystem/api/storage/VolumeInfo.java   |    1 +
 .../cloudstack/storage/test/volumeServiceTest.java |   19 +++-
 .../test/resource/storageContext.xml               |    1 +
 .../cloudstack/storage/command/CommandResult.java  |    2 +-
 .../storage/command/CreateVolumeAnswer.java        |    4 +
 .../storage/command/CreateVolumeCommand.java       |   10 +-
 .../cloudstack/storage/command/DeleteVolume.java   |   40 -------
 .../storage/command/DeleteVolumeCommand.java       |   44 +++++++
 .../storage/datastore/PrimaryDataStore.java        |    2 +-
 .../org/apache/cloudstack/storage/to/VolumeTO.java |    6 +
 .../storage/volume/VolumeEntityImpl.java           |   34 +++++-
 .../storage/datastore/DefaultPrimaryDataStore.java |    9 +-
 .../driver/DefaultPrimaryDataStoreDriverImpl.java  |   56 ++++------
 .../datastore/driver/PrimaryDataStoreDriver.java   |    2 +-
 .../storage/volume/VolumeManagerImpl.java          |   11 +-
 .../cloudstack/storage/volume/VolumeObject.java    |    5 +
 .../storage/volume/VolumeServiceImpl.java          |   46 +++++++-
 .../xen/resource/XenServerStorageResource.java     |   90 ++++++++++++++-
 .../driver/SolidfirePrimaryDataStoreDriver.java    |   11 +-
 20 files changed, 290 insertions(+), 106 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9410cd1f/api/src/com/cloud/storage/Volume.java
----------------------------------------------------------------------
diff --git a/api/src/com/cloud/storage/Volume.java 
b/api/src/com/cloud/storage/Volume.java
index f54dfef..18edbc3 100755
--- a/api/src/com/cloud/storage/Volume.java
+++ b/api/src/com/cloud/storage/Volume.java
@@ -35,7 +35,8 @@ public interface Volume extends ControlledEntity, BasedOn, 
StateObject<Volume.St
         Migrating("The volume is migrating to other storage pool"),
         Snapshotting("There is a snapshot created on this volume, not backed 
up to secondary storage yet"),
         Expunging("The volume is being expunging"),
-        Destroy("The volume is destroyed, and can't be recovered."),        
+        Destroy("The volume is destroyed, and can't be recovered."), 
+        Destroying("The volume is destroying, and can't be recovered."),  
         UploadOp ("The volume upload operation is in progress or in short the 
volume is on secondary storage");            
 
         String _description;

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9410cd1f/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeInfo.java
----------------------------------------------------------------------
diff --git 
a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeInfo.java
 
b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeInfo.java
index 00e8eb0..4adc1a8 100644
--- 
a/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeInfo.java
+++ 
b/engine/api/src/org/apache/cloudstack/engine/subsystem/api/storage/VolumeInfo.java
@@ -42,4 +42,5 @@ public interface VolumeInfo {
        public Date getUpdatedDate();
        public String getOwner();
        public String getName();
+       public boolean isAttachedVM();
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9410cd1f/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 110c328..cb915c2 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
@@ -125,6 +125,7 @@ public class volumeServiceTest extends CloudStackTestNGBase 
{
        Long podId;
        HostVO host;
        String primaryName = "my primary data store";
+       PrimaryDataStoreInfo primaryStore;
        
     @Test(priority = -1)
        public void setUp() {
@@ -270,21 +271,29 @@ public class volumeServiceTest extends 
CloudStackTestNGBase {
                }
        }
 
-       private VolumeVO createVolume(long templateId, long dataStoreId) {
+       private VolumeVO createVolume(Long templateId, long dataStoreId) {
                VolumeVO volume = new VolumeVO(1000, new RootDisk().toString(), 
UUID.randomUUID().toString(), templateId);
                volume.setPoolId(dataStoreId);
                volume = volumeDao.persist(volume);
                return volume;
-
        }
 
        @Test(priority=2)
        public void createVolumeFromTemplate() {
                TemplateEntity te = createTemplate();
-               PrimaryDataStoreInfo dataStoreInfo = createPrimaryDataStore();
-               VolumeVO volume = createVolume(te.getId(), 
dataStoreInfo.getId());
+               primaryStore = createPrimaryDataStore();
+               VolumeVO volume = createVolume(te.getId(), 
primaryStore.getId());
                VolumeEntity ve = volumeService.getVolumeEntity(volume.getId());
-               ve.createVolumeFromTemplate(dataStoreInfo.getId(), new VHD(), 
te);
+               ve.createVolumeFromTemplate(primaryStore.getId(), new VHD(), 
te);
+               ve.destroy();
+       }
+       
+       @Test(priority=3) 
+       public void createDataDisk() {
+           VolumeVO volume = createVolume(null, primaryStore.getId());
+           VolumeEntity ve = volumeService.getVolumeEntity(volume.getId());
+           ve.createVolume(primaryStore.getId(), new VHD());
+           ve.destroy();
        }
        
        //@Test(priority=3)

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9410cd1f/engine/storage/integration-test/test/resource/storageContext.xml
----------------------------------------------------------------------
diff --git a/engine/storage/integration-test/test/resource/storageContext.xml 
b/engine/storage/integration-test/test/resource/storageContext.xml
index 0b99ba1..f5e343e 100644
--- a/engine/storage/integration-test/test/resource/storageContext.xml
+++ b/engine/storage/integration-test/test/resource/storageContext.xml
@@ -17,6 +17,7 @@
   <context:component-scan base-package="com.cloud.utils.component" />
   <context:component-scan base-package="com.cloud.host.dao" />
   <context:component-scan base-package="com.cloud.dc.dao" />
+  <context:component-scan base-package="com.cloud.cluster.agentlb.dao" />
  
    <context:component-scan base-package=" com.cloud.upgrade.dao" />
   <tx:annotation-driven transaction-manager="transactionManager" />

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9410cd1f/engine/storage/src/org/apache/cloudstack/storage/command/CommandResult.java
----------------------------------------------------------------------
diff --git 
a/engine/storage/src/org/apache/cloudstack/storage/command/CommandResult.java 
b/engine/storage/src/org/apache/cloudstack/storage/command/CommandResult.java
index 998f35d..d152863 100644
--- 
a/engine/storage/src/org/apache/cloudstack/storage/command/CommandResult.java
+++ 
b/engine/storage/src/org/apache/cloudstack/storage/command/CommandResult.java
@@ -23,7 +23,7 @@ public class CommandResult {
     private String result;
     
     public CommandResult() {
-        this.success = false;
+        this.success = true;
         this.result = "";
     }
     

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9410cd1f/engine/storage/src/org/apache/cloudstack/storage/command/CreateVolumeAnswer.java
----------------------------------------------------------------------
diff --git 
a/engine/storage/src/org/apache/cloudstack/storage/command/CreateVolumeAnswer.java
 
b/engine/storage/src/org/apache/cloudstack/storage/command/CreateVolumeAnswer.java
index cfed00c..42674de 100644
--- 
a/engine/storage/src/org/apache/cloudstack/storage/command/CreateVolumeAnswer.java
+++ 
b/engine/storage/src/org/apache/cloudstack/storage/command/CreateVolumeAnswer.java
@@ -32,6 +32,10 @@ public class CreateVolumeAnswer extends Answer {
         super(cmd);
         this.volumeUuid = volumeUuid;
     }
+    
+    public CreateVolumeAnswer(Command cmd, boolean status, String result) {
+        super(cmd, status, result);
+    }
 
     public String getVolumeUuid() {
         return this.volumeUuid;

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9410cd1f/engine/storage/src/org/apache/cloudstack/storage/command/CreateVolumeCommand.java
----------------------------------------------------------------------
diff --git 
a/engine/storage/src/org/apache/cloudstack/storage/command/CreateVolumeCommand.java
 
b/engine/storage/src/org/apache/cloudstack/storage/command/CreateVolumeCommand.java
index e42d265..c44970e 100644
--- 
a/engine/storage/src/org/apache/cloudstack/storage/command/CreateVolumeCommand.java
+++ 
b/engine/storage/src/org/apache/cloudstack/storage/command/CreateVolumeCommand.java
@@ -23,11 +23,11 @@ import org.apache.cloudstack.storage.to.VolumeTO;
 import com.cloud.agent.api.Command;
 
 public class CreateVolumeCommand extends Command implements 
StorageSubSystemCommand {
-    protected VolumeTO volumeInfo;
+    protected VolumeTO volumeTO;
 
-    public CreateVolumeCommand(VolumeTO volumeInfo) {
+    public CreateVolumeCommand(VolumeTO volumeTO) {
         super();
-        this.volumeInfo = volumeInfo;
+        this.volumeTO = volumeTO;
     }
 
     protected CreateVolumeCommand() {
@@ -39,5 +39,9 @@ public class CreateVolumeCommand extends Command implements 
StorageSubSystemComm
         // TODO Auto-generated method stub
         return false;
     }
+    
+    public VolumeTO getVolume() {
+        return this.volumeTO;
+    }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9410cd1f/engine/storage/src/org/apache/cloudstack/storage/command/DeleteVolume.java
----------------------------------------------------------------------
diff --git 
a/engine/storage/src/org/apache/cloudstack/storage/command/DeleteVolume.java 
b/engine/storage/src/org/apache/cloudstack/storage/command/DeleteVolume.java
deleted file mode 100644
index 755d7f8..0000000
--- a/engine/storage/src/org/apache/cloudstack/storage/command/DeleteVolume.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.command;
-
-import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
-
-import com.cloud.agent.api.Command;
-
-public class DeleteVolume extends Command {
-
-    public DeleteVolume(VolumeInfo volume) {
-        
-    }
-    
-    protected DeleteVolume() {
-        
-    }
-    @Override
-    public boolean executeInSequence() {
-        // TODO Auto-generated method stub
-        return false;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9410cd1f/engine/storage/src/org/apache/cloudstack/storage/command/DeleteVolumeCommand.java
----------------------------------------------------------------------
diff --git 
a/engine/storage/src/org/apache/cloudstack/storage/command/DeleteVolumeCommand.java
 
b/engine/storage/src/org/apache/cloudstack/storage/command/DeleteVolumeCommand.java
new file mode 100644
index 0000000..a30a83b
--- /dev/null
+++ 
b/engine/storage/src/org/apache/cloudstack/storage/command/DeleteVolumeCommand.java
@@ -0,0 +1,44 @@
+/*
+ * 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.storage.to.VolumeTO;
+
+import com.cloud.agent.api.Command;
+
+public class DeleteVolumeCommand extends Command implements 
StorageSubSystemCommand {
+    private VolumeTO volume;
+    public DeleteVolumeCommand(VolumeTO volume) {
+        this.volume = volume;
+    }
+    
+    protected DeleteVolumeCommand() {
+        
+    }
+    @Override
+    public boolean executeInSequence() {
+        // TODO Auto-generated method stub
+        return false;
+    }
+    
+    public VolumeTO getVolume() {
+        return this.volume;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9410cd1f/engine/storage/src/org/apache/cloudstack/storage/datastore/PrimaryDataStore.java
----------------------------------------------------------------------
diff --git 
a/engine/storage/src/org/apache/cloudstack/storage/datastore/PrimaryDataStore.java
 
b/engine/storage/src/org/apache/cloudstack/storage/datastore/PrimaryDataStore.java
index fca9791..51c8696 100644
--- 
a/engine/storage/src/org/apache/cloudstack/storage/datastore/PrimaryDataStore.java
+++ 
b/engine/storage/src/org/apache/cloudstack/storage/datastore/PrimaryDataStore.java
@@ -36,7 +36,7 @@ public interface PrimaryDataStore extends 
PrimaryDataStoreInfo {
 
     List<VolumeInfo> getVolumes();
 
-    boolean deleteVolume(VolumeInfo volume);
+    void deleteVolumeAsync(VolumeInfo volume, 
AsyncCompletionCallback<CommandResult> callback);
 
     void createVolumeAsync(VolumeInfo vo, VolumeDiskType diskType, 
AsyncCompletionCallback<CommandResult> callback);
 

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9410cd1f/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 6b8ab75..8ec117c 100644
--- a/engine/storage/src/org/apache/cloudstack/storage/to/VolumeTO.java
+++ b/engine/storage/src/org/apache/cloudstack/storage/to/VolumeTO.java
@@ -11,6 +11,7 @@ public class VolumeTO {
     private final VolumeDiskType diskType;
     private PrimaryDataStoreTO dataStore;
     private final String name;
+    private final long size;
     public VolumeTO(VolumeInfo volume) {
         this.uuid = volume.getUuid();
         this.path = volume.getPath();
@@ -22,6 +23,7 @@ public class VolumeTO {
             this.dataStore = null;
         }
         this.name = volume.getName();
+        this.size = volume.getSize();
     }
     
     public String getUuid() {
@@ -51,4 +53,8 @@ public class VolumeTO {
     public String getName() {
         return this.name;
     }
+    
+    public long getSize() {
+        return this.size;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9410cd1f/engine/storage/src/org/apache/cloudstack/storage/volume/VolumeEntityImpl.java
----------------------------------------------------------------------
diff --git 
a/engine/storage/src/org/apache/cloudstack/storage/volume/VolumeEntityImpl.java 
b/engine/storage/src/org/apache/cloudstack/storage/volume/VolumeEntityImpl.java
index c3bdf4e..f3e07e7 100644
--- 
a/engine/storage/src/org/apache/cloudstack/storage/volume/VolumeEntityImpl.java
+++ 
b/engine/storage/src/org/apache/cloudstack/storage/volume/VolumeEntityImpl.java
@@ -146,10 +146,6 @@ public class VolumeEntityImpl implements VolumeEntity {
 
     }
 
-    @Override
-    public void destroy() {
-        //vs.deleteVolume(volumeInfo);
-    }
 
     @Override
     public long getSize() {
@@ -190,7 +186,7 @@ public class VolumeEntityImpl implements VolumeEntity {
     }
     
    
-    private Void 
createVolumeFromTemplateAsyncCallback(AsyncCallbackDispatcher<VolumeEntityImpl, 
VolumeInfo> callback, Object context) {
+    public Object 
createVolumeFromTemplateAsyncCallback(AsyncCallbackDispatcher<VolumeEntityImpl, 
VolumeInfo> callback, Object context) {
         synchronized (volumeInfo) {
             volumeInfo.notify();
         }
@@ -216,7 +212,33 @@ public class VolumeEntityImpl implements VolumeEntity {
         }
     }
     
-    private Void createVolumeCallback(AsyncCallbackDispatcher<VolumeApiResult, 
VolumeApiResult> callback, Object context) {
+    public Void createVolumeCallback(AsyncCallbackDispatcher<VolumeApiResult, 
VolumeApiResult> callback, Object context) {
+        synchronized (volumeInfo) {
+            this.result = callback.getResult();
+            volumeInfo.notify();
+        }
+        return null;
+    }
+    
+
+    @Override
+    public void destroy() {
+        AsyncCallbackDispatcher<VolumeEntityImpl, VolumeApiResult> caller = 
AsyncCallbackDispatcher.create(this);
+        caller.setCallback(caller.getTarget().destroyCallback(null, null));
+        vs.deleteVolumeAsync(volumeInfo, caller);
+        try {
+            synchronized (volumeInfo) {
+                volumeInfo.wait();
+            }
+            if (!result.isSuccess()) {
+                throw new CloudRuntimeException("Failed to create volume:" + 
result.getResult());
+            }
+        } catch (InterruptedException e) {
+           throw new CloudRuntimeException("wait volume info failed", e);
+        }
+    }
+    
+    public Void destroyCallback(AsyncCallbackDispatcher<VolumeApiResult, 
VolumeApiResult> callback, Object context) {
         synchronized (volumeInfo) {
             this.result = callback.getResult();
             volumeInfo.notify();

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9410cd1f/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/DefaultPrimaryDataStore.java
----------------------------------------------------------------------
diff --git 
a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/DefaultPrimaryDataStore.java
 
b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/DefaultPrimaryDataStore.java
index 3d3ce68..571f227 100644
--- 
a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/DefaultPrimaryDataStore.java
+++ 
b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/DefaultPrimaryDataStore.java
@@ -111,8 +111,13 @@ public class DefaultPrimaryDataStore implements 
PrimaryDataStore {
     }
 
     @Override
-    public boolean deleteVolume(VolumeInfo volume) {
-        return this.driver.deleteVolume((VolumeObject)volume);
+    public void deleteVolumeAsync(VolumeInfo volume, 
AsyncCompletionCallback<CommandResult> callback) {
+        CommandResult result = new CommandResult();
+        if (volume.isAttachedVM()) {
+            result.setResult("Can't delete volume: " + volume.getId() + ", if 
it's attached to a VM");
+            callback.complete(result);
+        }
+        this.driver.deleteVolumeAsync((VolumeObject)volume, callback);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9410cd1f/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/driver/DefaultPrimaryDataStoreDriverImpl.java
----------------------------------------------------------------------
diff --git 
a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/driver/DefaultPrimaryDataStoreDriverImpl.java
 
b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/driver/DefaultPrimaryDataStoreDriverImpl.java
index 88eeca2..5567037 100644
--- 
a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/driver/DefaultPrimaryDataStoreDriverImpl.java
+++ 
b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/driver/DefaultPrimaryDataStoreDriverImpl.java
@@ -12,7 +12,7 @@ import org.apache.cloudstack.storage.command.CommandResult;
 import org.apache.cloudstack.storage.command.CreateVolumeAnswer;
 import org.apache.cloudstack.storage.command.CreateVolumeCommand;
 import org.apache.cloudstack.storage.command.CreateVolumeFromBaseImageCommand;
-import org.apache.cloudstack.storage.command.DeleteVolume;
+import org.apache.cloudstack.storage.command.DeleteVolumeCommand;
 import org.apache.cloudstack.storage.datastore.PrimaryDataStore;
 import org.apache.cloudstack.storage.to.ImageOnPrimayDataStoreTO;
 import org.apache.cloudstack.storage.to.VolumeTO;
@@ -72,7 +72,7 @@ public class DefaultPrimaryDataStoreDriverImpl implements 
PrimaryDataStoreDriver
         ep.sendMessageAsync(createCmd, caller);
     }
     
-    protected Void 
createVolumeAsyncCallback(AsyncCallbackDispatcher<DefaultPrimaryDataStoreDriverImpl,
 Answer> callback, CreateVolumeContext<CommandResult> context) {
+    public Void 
createVolumeAsyncCallback(AsyncCallbackDispatcher<DefaultPrimaryDataStoreDriverImpl,
 Answer> callback, CreateVolumeContext<CommandResult> context) {
         CommandResult result = new CommandResult();
         CreateVolumeAnswer volAnswer = (CreateVolumeAnswer) 
callback.getResult();
         if (volAnswer.getResult()) {
@@ -85,14 +85,27 @@ public class DefaultPrimaryDataStoreDriverImpl implements 
PrimaryDataStoreDriver
         context.getParentCallback().complete(result);
         return null;
     }
-
+  
     @Override
-    public boolean deleteVolume(VolumeObject vo) {
-        DeleteVolume cmd = new DeleteVolume((VolumeInfo)vo);
+    public void deleteVolumeAsync(VolumeObject vo, 
AsyncCompletionCallback<CommandResult> callback) {
+        DeleteVolumeCommand cmd = new 
DeleteVolumeCommand(this.dataStore.getVolumeTO(vo));
         List<EndPoint> endPoints = vo.getDataStore().getEndPoints();
-        sendOutCommand(cmd, endPoints);
-
-        return true;
+        EndPoint ep = endPoints.get(0);
+        AsyncRpcConext<CommandResult> context = new 
AsyncRpcConext<CommandResult>(callback);
+        AsyncCallbackDispatcher<DefaultPrimaryDataStoreDriverImpl, Answer> 
caller = AsyncCallbackDispatcher.create(this);
+        caller.setCallback(caller.getTarget().deleteVolumeCallback(null, null))
+            .setContext(context);
+        ep.sendMessageAsync(cmd, caller);
+    }
+    
+    public Void 
deleteVolumeCallback(AsyncCallbackDispatcher<DefaultPrimaryDataStoreDriverImpl, 
Answer> callback, AsyncRpcConext<CommandResult> context) {
+        CommandResult result = new CommandResult();
+        Answer answer = callback.getResult();
+        if (!answer.getResult()) {
+            result.setResult(answer.getDetails());
+        }
+        context.getParentCallback().complete(result);
+        return null;
     }
 
     @Override
@@ -106,33 +119,6 @@ public class DefaultPrimaryDataStoreDriverImpl implements 
PrimaryDataStoreDriver
         // TODO Auto-generated method stub
         return true;
     }
-
-    protected Answer sendOutCommand(Command cmd, List<EndPoint> endPoints) {
-        Answer answer = null;
-        int retries = 3;
-        int i = 0;
-        for (EndPoint ep : endPoints) {
-            answer = ep.sendMessage(cmd);
-            if (answer == null || answer.getDetails() != null) {
-                if (i < retries) {
-                    s_logger.debug("create volume failed, retrying: " + i);
-                }
-                i++;
-            } else {
-                break;
-            }
-        }
-        
-        if (answer == null || answer.getDetails() != null) {
-            if (answer == null) {
-                throw new CloudRuntimeException("Failed to created volume");
-            } else {
-                throw new CloudRuntimeException(answer.getDetails());
-            }
-        }
-        
-        return answer;
-    }
     
     private class CreateVolumeFromBaseImageContext<T> extends 
AsyncRpcConext<T> {
         private final VolumeObject volume;

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9410cd1f/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/driver/PrimaryDataStoreDriver.java
----------------------------------------------------------------------
diff --git 
a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/driver/PrimaryDataStoreDriver.java
 
b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/driver/PrimaryDataStoreDriver.java
index 96e629e..eca7d79 100644
--- 
a/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/driver/PrimaryDataStoreDriver.java
+++ 
b/engine/storage/volume/src/org/apache/cloudstack/storage/datastore/driver/PrimaryDataStoreDriver.java
@@ -14,7 +14,7 @@ public interface PrimaryDataStoreDriver {
 
     void createVolumeFromBaseImageAsync(VolumeObject volume, 
TemplateOnPrimaryDataStoreInfo template, AsyncCompletionCallback<CommandResult> 
callback);
 
-    boolean deleteVolume(VolumeObject vo);
+    void deleteVolumeAsync(VolumeObject vo, 
AsyncCompletionCallback<CommandResult> callback);
 
     String grantAccess(VolumeObject vol, EndPoint ep);
 

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9410cd1f/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeManagerImpl.java
----------------------------------------------------------------------
diff --git 
a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeManagerImpl.java
 
b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeManagerImpl.java
index 76f0b03..98c6b69 100644
--- 
a/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeManagerImpl.java
+++ 
b/engine/storage/volume/src/org/apache/cloudstack/storage/volume/VolumeManagerImpl.java
@@ -54,18 +54,18 @@ public class VolumeManagerImpl implements VolumeManager {
     
     private void initStateMachine() {
             s_fsm.addTransition(Volume.State.Allocated, Event.CreateRequested, 
Volume.State.Creating);
-            s_fsm.addTransition(Volume.State.Allocated, 
Event.DestroyRequested, Volume.State.Destroy);
+            s_fsm.addTransition(Volume.State.Allocated, 
Event.DestroyRequested, Volume.State.Destroying);
             s_fsm.addTransition(Volume.State.Creating, Event.OperationRetry, 
Volume.State.Creating);
             s_fsm.addTransition(Volume.State.Creating, Event.OperationFailed, 
Volume.State.Allocated);
             s_fsm.addTransition(Volume.State.Creating, 
Event.OperationSucceeded, Volume.State.Ready);
-            s_fsm.addTransition(Volume.State.Creating, Event.DestroyRequested, 
Volume.State.Destroy);
+            s_fsm.addTransition(Volume.State.Creating, Event.DestroyRequested, 
Volume.State.Destroying);
             s_fsm.addTransition(Volume.State.Creating, Event.CreateRequested, 
Volume.State.Creating);            
             s_fsm.addTransition(Volume.State.Allocated, Event.UploadRequested, 
Volume.State.UploadOp);
             s_fsm.addTransition(Volume.State.UploadOp, Event.CopyRequested, 
Volume.State.Creating);// CopyRequested for volume from sec to primary storage  
          
             s_fsm.addTransition(Volume.State.Creating, Event.CopySucceeded, 
Volume.State.Ready);
             s_fsm.addTransition(Volume.State.Creating, Event.CopyFailed, 
Volume.State.UploadOp);// Copying volume from sec to primary failed.  
-            s_fsm.addTransition(Volume.State.UploadOp, Event.DestroyRequested, 
Volume.State.Destroy);
-            s_fsm.addTransition(Volume.State.Ready, Event.DestroyRequested, 
Volume.State.Destroy);
+            s_fsm.addTransition(Volume.State.UploadOp, Event.DestroyRequested, 
Volume.State.Destroying);
+            s_fsm.addTransition(Volume.State.Ready, Event.DestroyRequested, 
Volume.State.Destroying);
             s_fsm.addTransition(Volume.State.Destroy, 
Event.ExpungingRequested, Volume.State.Expunging);
             s_fsm.addTransition(Volume.State.Ready, Event.SnapshotRequested, 
Volume.State.Snapshotting);
             s_fsm.addTransition(Volume.State.Snapshotting, 
Event.OperationSucceeded, Volume.State.Ready);
@@ -74,6 +74,9 @@ public class VolumeManagerImpl implements VolumeManager {
             s_fsm.addTransition(Volume.State.Migrating, 
Event.OperationSucceeded, Volume.State.Ready);
             s_fsm.addTransition(Volume.State.Migrating, Event.OperationFailed, 
Volume.State.Ready);
             s_fsm.addTransition(Volume.State.Destroy, 
Event.OperationSucceeded, Volume.State.Destroy);
+            s_fsm.addTransition(Volume.State.Destroying, 
Event.OperationSucceeded, Volume.State.Destroy);
+            s_fsm.addTransition(Volume.State.Destroying, 
Event.OperationFailed, Volume.State.Destroying);
+            s_fsm.addTransition(Volume.State.Destroying, 
Event.DestroyRequested, Volume.State.Destroying);
     }
     
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9410cd1f/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 b8c7631..a1eeb65 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
@@ -158,4 +158,9 @@ public class VolumeObject implements VolumeInfo {
     public String getName() {
         return this.volumeVO.getName();
     }
+
+    @Override
+    public boolean isAttachedVM() {
+        return (this.volumeVO.getInstanceId() == null) ? false : true;
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9410cd1f/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 815033a..445e6b3 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
@@ -98,7 +98,7 @@ public class VolumeServiceImpl implements VolumeService {
         dataStore.createVolumeAsync(vo, diskType, caller);
     }
     
-    protected Void 
createVolumeCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CommandResult> 
callback, CreateVolumeContext<VolumeApiResult> context) {
+    public Void 
createVolumeCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CommandResult> 
callback, CreateVolumeContext<VolumeApiResult> context) {
         CommandResult result = callback.getResult();
         VolumeObject vo = context.getVolume();
         VolumeApiResult volResult = new VolumeApiResult(vo);
@@ -112,11 +112,55 @@ public class VolumeServiceImpl implements VolumeService {
         context.getParentCallback().complete(volResult);
         return null;
     }
+    
+    private class DeleteVolumeContext<T> extends AsyncRpcConext<T> {
+        private final VolumeObject volume;
+        /**
+         * @param callback
+         */
+        public DeleteVolumeContext(AsyncCompletionCallback<T> callback, 
VolumeObject volume) {
+            super(callback);
+            this.volume = volume;
+        }
+        
+        public VolumeObject getVolume() {
+            return this.volume;
+        }
+    }
 
     @DB
     @Override
     public void deleteVolumeAsync(VolumeInfo volume, 
AsyncCompletionCallback<VolumeApiResult> callback) {
+        VolumeObject vo = (VolumeObject)volume;
+        PrimaryDataStore dataStore = vo.getDataStore();
+        vo.stateTransit(Volume.Event.DestroyRequested);
+        if (dataStore == null) {
+            vo.stateTransit(Volume.Event.OperationSucceeded);
+            volDao.remove(vo.getId());
+            return;
+        }
+        
+        DeleteVolumeContext<VolumeApiResult> context = new 
DeleteVolumeContext<VolumeApiResult>(callback, vo);
+        AsyncCallbackDispatcher<VolumeServiceImpl, CommandResult> caller = 
AsyncCallbackDispatcher.create(this);
+        caller.setCallback(caller.getTarget().deleteVolumeCallback(null, null))
+            .setContext(context);
         
+        dataStore.deleteVolumeAsync(volume, caller);
+    }
+    
+    public Void 
deleteVolumeCallback(AsyncCallbackDispatcher<VolumeServiceImpl, CommandResult> 
callback, DeleteVolumeContext<VolumeApiResult> context) {
+        CommandResult result = callback.getResult();
+        VolumeObject vo = context.getVolume();
+        VolumeApiResult apiResult = new VolumeApiResult(vo);
+        if (result.isSuccess()) {
+            vo.stateTransit(Volume.Event.OperationSucceeded);
+            volDao.remove(vo.getId());
+        } else {
+            vo.stateTransit(Volume.Event.OperationFailed);
+            apiResult.setResult(result.getResult());
+        }
+        context.getParentCallback().complete(apiResult);
+        return null;
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9410cd1f/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 031d0e0..7322e02 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
@@ -34,7 +34,9 @@ import 
org.apache.cloudstack.storage.command.CopyTemplateToPrimaryStorageCmd;
 import 
org.apache.cloudstack.storage.command.CopyTemplateToPrimaryStorageAnswer;
 import org.apache.cloudstack.storage.command.CreatePrimaryDataStoreCmd;
 import org.apache.cloudstack.storage.command.CreateVolumeAnswer;
+import org.apache.cloudstack.storage.command.CreateVolumeCommand;
 import org.apache.cloudstack.storage.command.CreateVolumeFromBaseImageCommand;
+import org.apache.cloudstack.storage.command.DeleteVolumeCommand;
 import org.apache.cloudstack.storage.command.StorageSubSystemCommand;
 import org.apache.cloudstack.storage.datastore.protocol.DataStoreProtocol;
 import org.apache.cloudstack.storage.to.ImageDataStoreTO;
@@ -72,6 +74,7 @@ import com.xensource.xenapi.PBD;
 import com.xensource.xenapi.Pool;
 import com.xensource.xenapi.SR;
 import com.xensource.xenapi.Types;
+import com.xensource.xenapi.VBD;
 import com.xensource.xenapi.Types.BadServerResponse;
 import com.xensource.xenapi.Types.XenAPIException;
 import com.xensource.xenapi.VDI;
@@ -93,11 +96,96 @@ public class XenServerStorageResource {
             return execute((CreatePrimaryDataStoreCmd) command);
         } else if (command instanceof CreateVolumeFromBaseImageCommand) {
             return execute((CreateVolumeFromBaseImageCommand)command);
+        } else if (command instanceof CreateVolumeCommand) {
+            return execute((CreateVolumeCommand) command);
+        } else if (command instanceof DeleteVolumeCommand) {
+            return execute((DeleteVolumeCommand)command);
         }
         return new Answer((Command)command, false, "not implemented yet"); 
     }
     
-    public Answer execute(CreateVolumeFromBaseImageCommand cmd) {
+    protected SR getSRByNameLabel(Connection conn, String nameLabel) throws 
BadServerResponse, XenAPIException, XmlRpcException {
+        Set<SR> srs = SR.getByNameLabel(conn, nameLabel);
+        if (srs.size() != 1) {
+            throw new CloudRuntimeException("storage uuid: " + nameLabel + " 
is not unique");
+        }
+        SR poolsr = srs.iterator().next();
+        return poolsr;
+    }
+    
+    protected VDI createVdi(Connection conn, String vdiName, SR sr, long size) 
throws BadServerResponse, XenAPIException, XmlRpcException {
+        VDI.Record vdir = new VDI.Record();
+        vdir.nameLabel = vdiName;
+        vdir.SR = sr;
+        vdir.type = Types.VdiType.USER;
+
+        vdir.virtualSize = size;
+        VDI vdi = VDI.create(conn, vdir);
+        return vdi;
+    }
+    
+    protected void deleteVDI(Connection conn, VDI vdi) throws 
BadServerResponse, XenAPIException, XmlRpcException {
+        vdi.destroy(conn);
+    }
+    
+    protected CreateVolumeAnswer execute(CreateVolumeCommand cmd) {
+        VolumeTO volume = cmd.getVolume();
+        PrimaryDataStoreTO primaryDataStore = volume.getDataStore();
+        Connection conn = hypervisorResource.getConnection();
+        VDI vdi = null;
+        boolean result = false;
+        String errorMsg = null;
+        try {
+            SR primaryDataStoreSR = getSRByNameLabel(conn, 
primaryDataStore.getUuid());
+            vdi = createVdi(conn, volume.getName(), primaryDataStoreSR, 
volume.getSize());
+            VDI.Record record = vdi.getRecord(conn);
+            result = true;
+            return new CreateVolumeAnswer(cmd, record.uuid);
+        } catch (BadServerResponse e) {
+            s_logger.debug("Failed to create volume", e);
+            errorMsg = e.toString();
+        } catch (XenAPIException e) {
+            s_logger.debug("Failed to create volume", e);
+            errorMsg = e.toString();
+        } catch (XmlRpcException e) {
+            s_logger.debug("Failed to create volume", e);
+            errorMsg = e.toString();
+        } finally {
+            if (!result && vdi != null) {
+                try {
+                    deleteVDI(conn, vdi);
+                } catch (Exception e) {
+                    s_logger.debug("Faled to delete vdi: " + vdi.toString());
+                }
+            }
+        }
+        
+        return new CreateVolumeAnswer(cmd, false, errorMsg);
+    }
+    
+    protected Answer execute(DeleteVolumeCommand cmd) {
+        VolumeTO volume = cmd.getVolume();
+        Connection conn = hypervisorResource.getConnection();
+        String errorMsg = null;
+        try {
+            VDI vdi = VDI.getByUuid(conn, volume.getUuid());
+            deleteVDI(conn, vdi);
+            return new Answer(cmd);
+        } catch (BadServerResponse e) {
+            s_logger.debug("Failed to delete volume", e);
+            errorMsg = e.toString();
+        } catch (XenAPIException e) {
+            s_logger.debug("Failed to delete volume", e);
+            errorMsg = e.toString();
+        } catch (XmlRpcException e) {
+            s_logger.debug("Failed to delete volume", e);
+            errorMsg = e.toString();
+        }
+        
+        return new Answer(cmd, false, errorMsg);
+    }
+    
+    protected Answer execute(CreateVolumeFromBaseImageCommand cmd) {
         VolumeTO volume = cmd.getVolume();
         ImageOnPrimayDataStoreTO baseImage = cmd.getImage();
         Connection conn = hypervisorResource.getConnection();

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/9410cd1f/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 54d12c9..afee8b0 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
@@ -11,11 +11,6 @@ import org.apache.cloudstack.storage.volume.VolumeObject;
 
 public class SolidfirePrimaryDataStoreDriver implements PrimaryDataStoreDriver 
{
 
-       @Override
-       public boolean deleteVolume(VolumeObject vo) {
-               // TODO Auto-generated method stub
-               return false;
-       }
 
        @Override
        public String grantAccess(VolumeObject vol, EndPoint ep) {
@@ -77,4 +72,10 @@ public class SolidfirePrimaryDataStoreDriver implements 
PrimaryDataStoreDriver {
         
     }
 
+    @Override
+    public void deleteVolumeAsync(VolumeObject vo, 
AsyncCompletionCallback<CommandResult> callback) {
+        // TODO Auto-generated method stub
+        
+    }
+
 }

Reply via email to