mirror of https://github.com/apache/cloudstack.git
add create volume
This commit is contained in:
parent
a4e0c4f012
commit
5d1e97e407
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,9 @@ public class CommandResult {
|
|||
|
||||
public void setResult(String result) {
|
||||
this.result = result;
|
||||
if (result != null) {
|
||||
this.success = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue