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 + + } + }
