mirror of
https://github.com/apache/cloudstack.git
synced 2025-11-03 04:12:31 +01:00
add deletevolume and createdata disk
This commit is contained in:
parent
ed17281f0d
commit
9410cd1f3c
@ -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;
|
||||
|
||||
@ -42,4 +42,5 @@ public interface VolumeInfo {
|
||||
public Date getUpdatedDate();
|
||||
public String getOwner();
|
||||
public String getName();
|
||||
public boolean isAttachedVM();
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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" />
|
||||
|
||||
@ -23,7 +23,7 @@ public class CommandResult {
|
||||
private String result;
|
||||
|
||||
public CommandResult() {
|
||||
this.success = false;
|
||||
this.success = true;
|
||||
this.result = "";
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -18,17 +18,17 @@
|
||||
*/
|
||||
package org.apache.cloudstack.storage.command;
|
||||
|
||||
import org.apache.cloudstack.engine.subsystem.api.storage.VolumeInfo;
|
||||
import org.apache.cloudstack.storage.to.VolumeTO;
|
||||
|
||||
import com.cloud.agent.api.Command;
|
||||
|
||||
public class DeleteVolume extends Command {
|
||||
|
||||
public DeleteVolume(VolumeInfo volume) {
|
||||
|
||||
public class DeleteVolumeCommand extends Command implements StorageSubSystemCommand {
|
||||
private VolumeTO volume;
|
||||
public DeleteVolumeCommand(VolumeTO volume) {
|
||||
this.volume = volume;
|
||||
}
|
||||
|
||||
protected DeleteVolume() {
|
||||
protected DeleteVolumeCommand() {
|
||||
|
||||
}
|
||||
@Override
|
||||
@ -36,5 +36,9 @@ public class DeleteVolume extends Command {
|
||||
// TODO Auto-generated method stub
|
||||
return false;
|
||||
}
|
||||
|
||||
public VolumeTO getVolume() {
|
||||
return this.volume;
|
||||
}
|
||||
|
||||
}
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user