mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
CLOUDSTACK-4744: enhanced root admin API updateVolume with state/storageId parameters as a part of "Better control over first party objects" feature.
Also fixed existing bugs for the API: * corrected action event to be VOLUME.UPDATE (was VOLUME.ATTACH) * all parameters to update, should be optional - fixed that. If nothing is specified, the db object will remain with its original fields
This commit is contained in:
parent
b998fba4da
commit
43770e0cb2
@ -188,6 +188,8 @@ public class EventTypes {
|
|||||||
public static final String EVENT_VOLUME_DETAIL_UPDATE = "VOLUME.DETAIL.UPDATE";
|
public static final String EVENT_VOLUME_DETAIL_UPDATE = "VOLUME.DETAIL.UPDATE";
|
||||||
public static final String EVENT_VOLUME_DETAIL_ADD = "VOLUME.DETAIL.ADD";
|
public static final String EVENT_VOLUME_DETAIL_ADD = "VOLUME.DETAIL.ADD";
|
||||||
public static final String EVENT_VOLUME_DETAIL_REMOVE = "VOLUME.DETAIL.REMOVE";
|
public static final String EVENT_VOLUME_DETAIL_REMOVE = "VOLUME.DETAIL.REMOVE";
|
||||||
|
public static final String EVENT_VOLUME_UPDATE = "VOLUME.UPDATE";
|
||||||
|
|
||||||
|
|
||||||
// Domains
|
// Domains
|
||||||
public static final String EVENT_DOMAIN_CREATE = "DOMAIN.CREATE";
|
public static final String EVENT_DOMAIN_CREATE = "DOMAIN.CREATE";
|
||||||
|
|||||||
@ -84,7 +84,7 @@ public interface VolumeApiService {
|
|||||||
|
|
||||||
Snapshot allocSnapshot(Long volumeId, Long policyId)
|
Snapshot allocSnapshot(Long volumeId, Long policyId)
|
||||||
throws ResourceAllocationException;
|
throws ResourceAllocationException;
|
||||||
Volume updateVolume(UpdateVolumeCmd updateVolumeCmd);
|
Volume updateVolume(long volumeId, String path, String state, Long storageId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts the volume to a particular location.
|
* Extracts the volume to a particular location.
|
||||||
|
|||||||
@ -23,15 +23,14 @@ import org.apache.cloudstack.api.ApiErrorCode;
|
|||||||
import org.apache.cloudstack.api.BaseAsyncCmd;
|
import org.apache.cloudstack.api.BaseAsyncCmd;
|
||||||
import org.apache.cloudstack.api.Parameter;
|
import org.apache.cloudstack.api.Parameter;
|
||||||
import org.apache.cloudstack.api.ServerApiException;
|
import org.apache.cloudstack.api.ServerApiException;
|
||||||
import org.apache.cloudstack.api.response.UserVmResponse;
|
import org.apache.cloudstack.api.response.StoragePoolResponse;
|
||||||
import org.apache.cloudstack.api.response.VolumeResponse;
|
import org.apache.cloudstack.api.response.VolumeResponse;
|
||||||
import org.apache.cloudstack.context.CallContext;
|
import org.apache.cloudstack.context.CallContext;
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import com.cloud.event.EventTypes;
|
import com.cloud.event.EventTypes;
|
||||||
|
import com.cloud.exception.InvalidParameterValueException;
|
||||||
import com.cloud.storage.Volume;
|
import com.cloud.storage.Volume;
|
||||||
import com.cloud.user.Account;
|
|
||||||
|
|
||||||
@APICommand(name = "updateVolume", description="Updates the volume.", responseObject=VolumeResponse.class)
|
@APICommand(name = "updateVolume", description="Updates the volume.", responseObject=VolumeResponse.class)
|
||||||
public class UpdateVolumeCmd extends BaseAsyncCmd {
|
public class UpdateVolumeCmd extends BaseAsyncCmd {
|
||||||
@ -42,13 +41,18 @@ public class UpdateVolumeCmd extends BaseAsyncCmd {
|
|||||||
//////////////// API parameters /////////////////////
|
//////////////// API parameters /////////////////////
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
|
|
||||||
@Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType=VolumeResponse.class,
|
@Parameter(name=ApiConstants.ID, type=CommandType.UUID, entityType=VolumeResponse.class, description="the ID of the disk volume")
|
||||||
required=true, description="the ID of the disk volume")
|
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
@Parameter(name=ApiConstants.PATH, type=CommandType.STRING,
|
@Parameter(name=ApiConstants.PATH, type=CommandType.STRING, description="The path of the volume")
|
||||||
required=true, description="the path of the volume")
|
|
||||||
private String path;
|
private String path;
|
||||||
|
|
||||||
|
@Parameter(name=ApiConstants.STORAGE_ID, type=CommandType.UUID, entityType=StoragePoolResponse.class,
|
||||||
|
description="Destination storage pool UUID for the volume", since="4.3")
|
||||||
|
private Long storageId;
|
||||||
|
|
||||||
|
@Parameter(name=ApiConstants.STATE, type=CommandType.STRING, description="The state of the volume", since="4.3")
|
||||||
|
private String state;
|
||||||
|
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
/////////////////// Accessors ///////////////////////
|
/////////////////// Accessors ///////////////////////
|
||||||
@ -61,6 +65,15 @@ public class UpdateVolumeCmd extends BaseAsyncCmd {
|
|||||||
public Long getId() {
|
public Long getId() {
|
||||||
return id;
|
return id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Long getStorageId() {
|
||||||
|
return storageId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getState() {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
/////////////// API Implementation///////////////////
|
/////////////// API Implementation///////////////////
|
||||||
@ -83,25 +96,37 @@ public class UpdateVolumeCmd extends BaseAsyncCmd {
|
|||||||
public long getEntityOwnerId() {
|
public long getEntityOwnerId() {
|
||||||
Volume volume = _responseGenerator.findVolumeById(getId());
|
Volume volume = _responseGenerator.findVolumeById(getId());
|
||||||
if (volume == null) {
|
if (volume == null) {
|
||||||
return Account.ACCOUNT_ID_SYSTEM; // bad id given, parent this command to SYSTEM so ERROR events are tracked
|
throw new InvalidParameterValueException("Invalid volume id was provided");
|
||||||
}
|
}
|
||||||
return volume.getAccountId();
|
return volume.getAccountId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getEventType() {
|
public String getEventType() {
|
||||||
return EventTypes.EVENT_VOLUME_ATTACH;
|
return EventTypes.EVENT_VOLUME_UPDATE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getEventDescription() {
|
public String getEventDescription() {
|
||||||
return "adding detail to the volume: " + getId();
|
StringBuffer desc = new StringBuffer();
|
||||||
|
desc.append(" with");
|
||||||
|
if (getPath() != null) {
|
||||||
|
desc.append(" path " + getPath());
|
||||||
|
}
|
||||||
|
if (getStorageId() != null) {
|
||||||
|
desc.append(", storage id " + getStorageId());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (getState() != null) {
|
||||||
|
desc.append(", state " + getState());
|
||||||
|
}
|
||||||
|
return "Updating volume: " + getId() + desc.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(){
|
public void execute(){
|
||||||
CallContext.current().setEventDetails("Volume Id: "+getId());
|
CallContext.current().setEventDetails("Volume Id: "+getId());
|
||||||
Volume result = _volumeService.updateVolume(this);
|
Volume result = _volumeService.updateVolume(getId(), getPath(), getState(), getStorageId());
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
VolumeResponse response = _responseGenerator.createVolumeResponse(result);
|
VolumeResponse response = _responseGenerator.createVolumeResponse(result);
|
||||||
response.setResponseName(getCommandName());
|
response.setResponseName(getCommandName());
|
||||||
|
|||||||
@ -35,6 +35,7 @@ import javax.persistence.Transient;
|
|||||||
import com.cloud.storage.Storage.StoragePoolType;
|
import com.cloud.storage.Storage.StoragePoolType;
|
||||||
import com.cloud.utils.NumbersUtil;
|
import com.cloud.utils.NumbersUtil;
|
||||||
import com.cloud.utils.db.GenericDao;
|
import com.cloud.utils.db.GenericDao;
|
||||||
|
import com.cloud.vm.VirtualMachine.State;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "volumes")
|
@Table(name = "volumes")
|
||||||
@ -573,4 +574,10 @@ public class VolumeVO implements Volume {
|
|||||||
public void setIsoId(long isoId) {
|
public void setIsoId(long isoId) {
|
||||||
this.isoId =isoId;
|
this.isoId =isoId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// don't use this directly, use volume state machine instead
|
||||||
|
// This method is used by UpdateVolume as a part of "Better control over first class objects in CS"
|
||||||
|
public void setState(State state) {
|
||||||
|
this.state = state;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,8 +25,6 @@ import java.util.concurrent.ExecutionException;
|
|||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import org.apache.log4j.Logger;
|
|
||||||
|
|
||||||
import org.apache.cloudstack.api.BaseCmd;
|
import org.apache.cloudstack.api.BaseCmd;
|
||||||
import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd;
|
import org.apache.cloudstack.api.command.user.volume.AttachVolumeCmd;
|
||||||
import org.apache.cloudstack.api.command.user.volume.CreateVolumeCmd;
|
import org.apache.cloudstack.api.command.user.volume.CreateVolumeCmd;
|
||||||
@ -34,7 +32,6 @@ import org.apache.cloudstack.api.command.user.volume.DetachVolumeCmd;
|
|||||||
import org.apache.cloudstack.api.command.user.volume.ExtractVolumeCmd;
|
import org.apache.cloudstack.api.command.user.volume.ExtractVolumeCmd;
|
||||||
import org.apache.cloudstack.api.command.user.volume.MigrateVolumeCmd;
|
import org.apache.cloudstack.api.command.user.volume.MigrateVolumeCmd;
|
||||||
import org.apache.cloudstack.api.command.user.volume.ResizeVolumeCmd;
|
import org.apache.cloudstack.api.command.user.volume.ResizeVolumeCmd;
|
||||||
import org.apache.cloudstack.api.command.user.volume.UpdateVolumeCmd;
|
|
||||||
import org.apache.cloudstack.api.command.user.volume.UploadVolumeCmd;
|
import org.apache.cloudstack.api.command.user.volume.UploadVolumeCmd;
|
||||||
import org.apache.cloudstack.context.CallContext;
|
import org.apache.cloudstack.context.CallContext;
|
||||||
import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
|
import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
|
||||||
@ -67,6 +64,7 @@ import org.apache.cloudstack.storage.datastore.db.TemplateDataStoreDao;
|
|||||||
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreDao;
|
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreDao;
|
||||||
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreVO;
|
import org.apache.cloudstack.storage.datastore.db.VolumeDataStoreVO;
|
||||||
import org.apache.cloudstack.storage.image.datastore.ImageStoreEntity;
|
import org.apache.cloudstack.storage.image.datastore.ImageStoreEntity;
|
||||||
|
import org.apache.log4j.Logger;
|
||||||
|
|
||||||
import com.cloud.agent.AgentManager;
|
import com.cloud.agent.AgentManager;
|
||||||
import com.cloud.agent.api.Answer;
|
import com.cloud.agent.api.Answer;
|
||||||
@ -1108,16 +1106,32 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Volume updateVolume(UpdateVolumeCmd cmd) {
|
@ActionEvent(eventType = EventTypes.EVENT_VOLUME_UPDATE, eventDescription = "updating volume", async = true)
|
||||||
Long volumeId = cmd.getId();
|
public Volume updateVolume(long volumeId, String path, String state, Long storageId) {
|
||||||
String path = cmd.getPath();
|
VolumeVO volume = _volumeDao.findById(volumeId);
|
||||||
|
|
||||||
if (path == null) {
|
if (path != null) {
|
||||||
throw new InvalidParameterValueException("Failed to update the volume as path was null");
|
volume.setPath(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
VolumeVO volume = ApiDBUtils.findVolumeById(volumeId);
|
if (state != null) {
|
||||||
volume.setPath(path);
|
try {
|
||||||
|
Volume.State volumeState = Volume.State.valueOf(state);
|
||||||
|
volume.setState(volumeState);
|
||||||
|
}
|
||||||
|
catch(IllegalArgumentException ex) {
|
||||||
|
throw new InvalidParameterValueException("Invalid volume state specified");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (storageId != null) {
|
||||||
|
StoragePool pool = _storagePoolDao.findById(storageId);
|
||||||
|
if (pool.getDataCenterId() != volume.getDataCenterId()) {
|
||||||
|
throw new InvalidParameterValueException("Invalid storageId specified; refers to the pool outside of the volume's zone");
|
||||||
|
}
|
||||||
|
volume.setPoolId(pool.getId());
|
||||||
|
}
|
||||||
|
|
||||||
_volumeDao.update(volumeId, volume);
|
_volumeDao.update(volumeId, volume);
|
||||||
|
|
||||||
return volume;
|
return volume;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user