add create volume

This commit is contained in:
Edison Su 2013-01-02 17:32:38 -08:00
parent a4e0c4f012
commit 5d1e97e407
11 changed files with 133 additions and 28 deletions

View File

@ -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);
}

View File

@ -41,6 +41,9 @@ public class CommandResult {
public void setResult(String result) {
this.result = result;
if (result != null) {
this.success = false;
}
}
}

View File

@ -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) {

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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;
}

View File

@ -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;
}