add create volume
Project: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/commit/5d1e97e4 Tree: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/tree/5d1e97e4 Diff: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/diff/5d1e97e4 Branch: refs/heads/javelin Commit: 5d1e97e407144c1ef2ca1afde66763f96558ed3f Parents: a4e0c4f Author: Edison Su <sudi...@gmail.com> Authored: Wed Jan 2 17:32:38 2013 -0800 Committer: Edison Su <sudi...@gmail.com> Committed: Wed Jan 2 17:32:54 2013 -0800 ---------------------------------------------------------------------- .../engine/cloud/entity/api/VolumeEntity.java | 1 + .../cloudstack/storage/command/CommandResult.java | 3 + .../storage/command/CreateVolumeCommand.java | 2 +- .../storage/datastore/PrimaryDataStore.java | 2 +- .../storage/volume/VolumeEntityImpl.java | 31 ++++++++++- .../cloudstack/storage/volume/VolumeService.java | 16 +++++- .../storage/datastore/DefaultPrimaryDataStore.java | 12 ++-- .../driver/DefaultPrimaryDataStoreDriverImpl.java | 45 ++++++++++++-- .../datastore/driver/PrimaryDataStoreDriver.java | 2 +- .../storage/volume/VolumeServiceImpl.java | 45 ++++++++++++--- .../driver/SolidfirePrimaryDataStoreDriver.java | 2 +- 11 files changed, 133 insertions(+), 28 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5d1e97e4/engine/api/src/org/apache/cloudstack/engine/cloud/entity/api/VolumeEntity.java ---------------------------------------------------------------------- diff --git a/engine/api/src/org/apache/cloudstack/engine/cloud/entity/api/VolumeEntity.java b/engine/api/src/org/apache/cloudstack/engine/cloud/entity/api/VolumeEntity.java index 4f883c0..47fb638 100755 --- a/engine/api/src/org/apache/cloudstack/engine/cloud/entity/api/VolumeEntity.java +++ b/engine/api/src/org/apache/cloudstack/engine/cloud/entity/api/VolumeEntity.java @@ -83,4 +83,5 @@ public interface VolumeEntity extends CloudStackEntity { StorageEntity getDataStore(); boolean createVolumeFromTemplate(long dataStoreId, VolumeDiskType diskType, TemplateEntity template); + boolean createVolume(long dataStoreId, VolumeDiskType diskType); } http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5d1e97e4/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 5fe8a7e..998f35d 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/command/CommandResult.java +++ b/engine/storage/src/org/apache/cloudstack/storage/command/CommandResult.java @@ -41,6 +41,9 @@ public class CommandResult { public void setResult(String result) { this.result = result; + if (result != null) { + this.success = false; + } } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5d1e97e4/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 3d8880f..e42d265 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/command/CreateVolumeCommand.java +++ b/engine/storage/src/org/apache/cloudstack/storage/command/CreateVolumeCommand.java @@ -22,7 +22,7 @@ import org.apache.cloudstack.storage.to.VolumeTO; import com.cloud.agent.api.Command; -public class CreateVolumeCommand extends Command { +public class CreateVolumeCommand extends Command implements StorageSubSystemCommand { protected VolumeTO volumeInfo; public CreateVolumeCommand(VolumeTO volumeInfo) { http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5d1e97e4/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 a945e28..fca9791 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/datastore/PrimaryDataStore.java +++ b/engine/storage/src/org/apache/cloudstack/storage/datastore/PrimaryDataStore.java @@ -38,7 +38,7 @@ public interface PrimaryDataStore extends PrimaryDataStoreInfo { boolean deleteVolume(VolumeInfo volume); - VolumeInfo createVolume(VolumeInfo vo, VolumeDiskType diskType); + void createVolumeAsync(VolumeInfo vo, VolumeDiskType diskType, AsyncCompletionCallback<CommandResult> callback); VolumeInfo createVoluemFromBaseImage(VolumeInfo volume, TemplateOnPrimaryDataStoreInfo templateStore); http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5d1e97e4/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 8883e8e..5449534 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/volume/VolumeEntityImpl.java +++ b/engine/storage/src/org/apache/cloudstack/storage/volume/VolumeEntityImpl.java @@ -35,12 +35,14 @@ import org.apache.cloudstack.framework.async.AsyncCompletionCallback; import org.apache.cloudstack.storage.datastore.PrimaryDataStoreEntityImpl; import org.apache.cloudstack.storage.image.TemplateEntityImpl; import org.apache.cloudstack.storage.image.TemplateInfo; +import org.apache.cloudstack.storage.volume.VolumeService.VolumeApiResult; import com.cloud.utils.exception.CloudRuntimeException; public class VolumeEntityImpl implements VolumeEntity { private VolumeInfo volumeInfo; private final VolumeService vs; + private VolumeApiResult result; protected VolumeEntityImpl() { this.vs = null; @@ -217,11 +219,38 @@ public class VolumeEntityImpl implements VolumeEntity { } - public Object createVolumeFromTemplateAsyncCallback(AsyncCompletionCallback<VolumeInfo> callback, Object context) { + private Void createVolumeFromTemplateAsyncCallback(AsyncCompletionCallback<VolumeInfo> callback, Object context) { synchronized (volumeInfo) { volumeInfo.notify(); } return null; } + @Override + public boolean createVolume(long dataStoreId, VolumeDiskType diskType) { + AsyncCallbackDispatcher<VolumeEntityImpl> caller = AsyncCallbackDispatcher.create(this); + caller.setCallback(caller.getTarget().createVolumeCallback(null, null)); + vs.createVolumeAsync(volumeInfo, dataStoreId, diskType, caller); + try { + synchronized (volumeInfo) { + volumeInfo.wait(); + } + if (result.isSuccess()) { + return true; + } else { + throw new CloudRuntimeException("Failed to create volume:" + result.getResult()); + } + } catch (InterruptedException e) { + throw new CloudRuntimeException("wait volume info failed", e); + } + } + + private Void createVolumeCallback(AsyncCallbackDispatcher<VolumeApiResult> callback, Object context) { + synchronized (volumeInfo) { + this.result = callback.getResult(); + volumeInfo.notify(); + } + return null; + } + } http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5d1e97e4/engine/storage/src/org/apache/cloudstack/storage/volume/VolumeService.java ---------------------------------------------------------------------- diff --git a/engine/storage/src/org/apache/cloudstack/storage/volume/VolumeService.java b/engine/storage/src/org/apache/cloudstack/storage/volume/VolumeService.java index 716c260..fcf6f98 100644 --- a/engine/storage/src/org/apache/cloudstack/storage/volume/VolumeService.java +++ b/engine/storage/src/org/apache/cloudstack/storage/volume/VolumeService.java @@ -24,9 +24,21 @@ import org.apache.cloudstack.engine.subsystem.api.storage.disktype.VolumeDiskTyp import org.apache.cloudstack.engine.subsystem.api.storage.type.VolumeType; import org.apache.cloudstack.framework.async.AsyncCompletionCallback; import org.apache.cloudstack.storage.EndPoint; +import org.apache.cloudstack.storage.command.CommandResult; import org.apache.cloudstack.storage.image.TemplateInfo; public interface VolumeService { + + public class VolumeApiResult extends CommandResult { + private final VolumeInfo volume; + public VolumeApiResult(VolumeInfo volume) { + this.volume = volume; + } + + public VolumeInfo getVolume() { + return this.volume; + } + } /** * */ @@ -39,7 +51,7 @@ public interface VolumeService { * * @return the volume object */ - VolumeInfo createVolume(VolumeInfo volume, long dataStoreId, VolumeDiskType diskType); + void createVolumeAsync(VolumeInfo volume, long dataStoreId, VolumeDiskType diskType, AsyncCompletionCallback<VolumeApiResult> callback); /** * Delete volume @@ -75,5 +87,5 @@ public interface VolumeService { VolumeEntity getVolumeEntity(long volumeId); void createVolumeFromTemplateAsync(VolumeInfo volume, long dataStoreId, VolumeDiskType diskType, TemplateInfo template, - AsyncCompletionCallback<VolumeInfo> callback); + AsyncCompletionCallback<VolumeApiResult> callback); } http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5d1e97e4/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 13b6f4a..3d3ce68 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 @@ -34,6 +34,8 @@ import com.cloud.host.HostVO; import com.cloud.host.dao.HostDao; import com.cloud.hypervisor.Hypervisor.HypervisorType; import com.cloud.utils.component.ComponentInject; +import com.cloud.utils.exception.CloudRuntimeException; + import edu.emory.mathcs.backport.java.util.Collections; public class DefaultPrimaryDataStore implements PrimaryDataStore { @@ -155,8 +157,7 @@ public class DefaultPrimaryDataStore implements PrimaryDataStore { @Override public boolean isVolumeDiskTypeSupported(VolumeDiskType diskType) { - // TODO Auto-generated method stub - return false; + return true; } @Override @@ -170,14 +171,13 @@ public class DefaultPrimaryDataStore implements PrimaryDataStore { } @Override - public VolumeObject createVolume(VolumeInfo vi, VolumeDiskType diskType) { + public void createVolumeAsync(VolumeInfo vi, VolumeDiskType diskType, AsyncCompletionCallback<CommandResult> callback) { if (!isVolumeDiskTypeSupported(diskType)) { - return null; + throw new CloudRuntimeException("disk type " + diskType + " is not supported"); } VolumeObject vo = (VolumeObject) vi; vo.setVolumeDiskType(diskType); - this.driver.createVolume(vo); - return vo; + this.driver.createVolumeAsync(vo, callback); } @Override http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5d1e97e4/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 9506d7c..e88d707 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 @@ -41,18 +41,49 @@ public class DefaultPrimaryDataStoreDriverImpl implements PrimaryDataStoreDriver this.dataStore = dataStore; } + private class CreateVolumeContext<T> extends AsyncRpcConext<T> { + private final VolumeObject volume; + /** + * @param callback + */ + public CreateVolumeContext(AsyncCompletionCallback<T> callback, VolumeObject volume) { + super(callback); + this.volume = volume; + } + + public VolumeObject getVolume() { + return this.volume; + } + + } + @Override - public boolean createVolume(VolumeObject vol) { - // The default driver will send createvolume command to one of hosts - // which can access its datastore + public void createVolumeAsync(VolumeObject vol, AsyncCompletionCallback<CommandResult> callback) { List<EndPoint> endPoints = vol.getDataStore().getEndPoints(); + EndPoint ep = endPoints.get(0); VolumeInfo volInfo = vol; CreateVolumeCommand createCmd = new CreateVolumeCommand(this.dataStore.getVolumeTO(volInfo)); - Answer answer = sendOutCommand(createCmd, endPoints); + + CreateVolumeContext<CommandResult> context = new CreateVolumeContext<CommandResult>(callback, vol); + AsyncCallbackDispatcher<DefaultPrimaryDataStoreDriverImpl> caller = AsyncCallbackDispatcher.create(this); + caller.setContext(context) + .setCallback(caller.getTarget().createVolumeAsyncCallback(null, null)); - CreateVolumeAnswer volAnswer = (CreateVolumeAnswer) answer; - vol.setPath(volAnswer.getVolumeUuid()); - return true; + ep.sendMessageAsync(createCmd, caller); + } + + protected Void createVolumeAsyncCallback(AsyncCallbackDispatcher<DefaultPrimaryDataStoreDriverImpl> callback, CreateVolumeContext<CommandResult> context) { + CommandResult result = new CommandResult(); + CreateVolumeAnswer volAnswer = (CreateVolumeAnswer) callback.getResult(); + if (volAnswer.getResult()) { + VolumeObject volume = context.getVolume(); + volume.setPath(volAnswer.getVolumeUuid()); + } else { + result.setResult(volAnswer.getDetails()); + } + + context.getParentCallback().complete(result); + return null; } @Override http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5d1e97e4/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 04694aa..96e629e 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 @@ -10,7 +10,7 @@ import org.apache.cloudstack.storage.volume.TemplateOnPrimaryDataStoreInfo; import org.apache.cloudstack.storage.volume.VolumeObject; public interface PrimaryDataStoreDriver { - boolean createVolume(VolumeObject vol); + void createVolumeAsync(VolumeObject vol, AsyncCompletionCallback<CommandResult> callback); void createVolumeFromBaseImageAsync(VolumeObject volume, TemplateOnPrimaryDataStoreInfo template, AsyncCompletionCallback<CommandResult> callback); http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5d1e97e4/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 b5687fd..d5d2681 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 @@ -59,28 +59,58 @@ public class VolumeServiceImpl implements VolumeService { public VolumeServiceImpl() { } + private class CreateVolumeContext<T> extends AsyncRpcConext<T> { + + private VolumeObject volume; + /** + * @param callback + */ + public CreateVolumeContext(AsyncCompletionCallback<T> callback, VolumeObject volume) { + super(callback); + this.volume = volume; + } + + public VolumeObject getVolume() { + return this.volume; + } + + } + @Override - public VolumeInfo createVolume(VolumeInfo volume, long dataStoreId, VolumeDiskType diskType) { + public void createVolumeAsync(VolumeInfo volume, long dataStoreId, VolumeDiskType diskType, AsyncCompletionCallback<VolumeApiResult> callback) { PrimaryDataStore dataStore = dataStoreMgr.getPrimaryDataStore(dataStoreId); if (dataStore == null) { throw new CloudRuntimeException("Can't find dataStoreId: " + dataStoreId); } if (dataStore.exists(volume)) { - return volume; + throw new CloudRuntimeException("Volume: " + volume.getId() + " already exists on primary data store: " + dataStoreId); } VolumeObject vo = (VolumeObject) volume; vo.stateTransit(Volume.Event.CreateRequested); - try { - VolumeInfo vi = dataStore.createVolume(vo, diskType); + CreateVolumeContext<VolumeApiResult> context = new CreateVolumeContext<VolumeApiResult>(callback, vo); + AsyncCallbackDispatcher<VolumeServiceImpl> caller = AsyncCallbackDispatcher.create(this); + caller.setCallback(caller.getTarget().createVolumeCallback(null, null)) + .setContext(context); + + dataStore.createVolumeAsync(vo, diskType, caller); + } + + protected Void createVolumeCallback(AsyncCallbackDispatcher<VolumeServiceImpl> callback, CreateVolumeContext<VolumeApiResult> context) { + CommandResult result = callback.getResult(); + VolumeObject vo = context.getVolume(); + VolumeApiResult volResult = new VolumeApiResult(vo); + if (result.isSuccess()) { vo.stateTransit(Volume.Event.OperationSucceeded); - return vi; - } catch (Exception e) { + } else { vo.stateTransit(Volume.Event.OperationFailed); - throw new CloudRuntimeException(e.toString()); + volResult.setResult(result.getResult()); } + + context.getParentCallback().complete(volResult); + return null; } @DB @@ -240,7 +270,6 @@ public class VolumeServiceImpl implements VolumeService { } AsyncCompletionCallback<VolumeInfo> parentCall = context.getParentCallback(); - parentCall.complete(vo); return null; } http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/5d1e97e4/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 d2d229b..a891ffe 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 @@ -12,7 +12,7 @@ import org.apache.cloudstack.storage.volume.VolumeObject; public class SolidfirePrimaryDataStoreDriver implements PrimaryDataStoreDriver { @Override - public boolean createVolume(VolumeObject vol) { + public boolean createVolumeAsync(VolumeObject vol) { // TODO Auto-generated method stub return false; }