Liron Ar has uploaded a new change for review. Change subject: core, restapi: wip: Introducing hot plug disk snapshot support ......................................................................
core, restapi: wip: Introducing hot plug disk snapshot support The following patch adds support to the following: *Hot-(un)plugging a disk snapshot. *Hot-(un)plugging to a vm which the disk isn't attached to. Note: When attempting to hotplug a disk to a vm which it isn't attached to, the operation would be executed in vdsm but won't be reflected in the engine as there is no VmDevice object. Usage example: http://SERVER:PORT/api/vms/GUID/snapshots/GUID/disks/GUID/hotplug http://SERVER:PORT/api/vms/GUID/snapshots/GUID/disks/GUID/hotunplug Current issues: *missing links Change-Id: Id1a265438dc5bc2d887a88a9be12641c721d9735 Signed-off-by: Liron Aravot <lara...@redhat.com> --- M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AbstractDiskVmCommand.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/DetachDiskFromVmCommand.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/HotPlugDiskToVmCommand.java M backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/UpdateVmDiskCommand.java M backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/HotPlugDiskToVmParameters.java M backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/DiskImageDAO.java M backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/DiskImageDAODbFacadeImpl.java M backend/manager/modules/restapi/interface/common/jaxrs/src/main/java/org/ovirt/engine/api/common/util/LinkHelper.java M backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/SnapshotDiskResource.java M backend/manager/modules/restapi/interface/definition/src/main/resources/rsdl_metadata.yaml M backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendSnapshotDiskResource.java M backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendSnapshotDisksResource.java M backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendSnapshotResource.java A backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendSnapshotDiskResourceTest.java M backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendSnapshotResourceTest.java M packaging/dbscripts/disk_images_sp.sql 16 files changed, 341 insertions(+), 49 deletions(-) git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/20/17420/1 diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AbstractDiskVmCommand.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AbstractDiskVmCommand.java index 2d96c2c..9714d1f 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AbstractDiskVmCommand.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/AbstractDiskVmCommand.java @@ -156,8 +156,8 @@ return true; } - protected boolean isDiskExist(Disk disk) { - if (disk == null || !isDiskExistInVm(disk)) { + protected boolean isDiskExist(Disk disk, boolean checkAttachedToVm) { + if (disk == null || (checkAttachedToVm && !isDiskExistInVm(disk))) { addCanDoActionMessage(VdcBllMessages.ACTION_TYPE_FAILED_DISK_NOT_EXIST); return false; } diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/DetachDiskFromVmCommand.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/DetachDiskFromVmCommand.java index cd83378..fdc95b6 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/DetachDiskFromVmCommand.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/DetachDiskFromVmCommand.java @@ -31,7 +31,7 @@ if (retValue) { disk = getDiskDao().get((Guid) getParameters().getEntityInfo().getId()); - retValue = isDiskExist(disk); + retValue = isDiskExist(disk, true); } if (retValue) { vmDevice = getVmDeviceDao().get(new VmDeviceId(disk.getId(), getVmId())); diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/HotPlugDiskToVmCommand.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/HotPlugDiskToVmCommand.java index f2cd9a2..0b24c82 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/HotPlugDiskToVmCommand.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/HotPlugDiskToVmCommand.java @@ -4,15 +4,19 @@ import java.util.List; import java.util.Map; +import org.ovirt.engine.core.bll.snapshots.SnapshotsValidator; import org.ovirt.engine.core.bll.utils.VmDeviceUtils; import org.ovirt.engine.core.common.AuditLogType; import org.ovirt.engine.core.common.action.HotPlugDiskToVmParameters; import org.ovirt.engine.core.common.businessentities.Disk; +import org.ovirt.engine.core.common.businessentities.Snapshot; import org.ovirt.engine.core.common.businessentities.VmDevice; +import org.ovirt.engine.core.common.businessentities.VmDeviceGeneralType; import org.ovirt.engine.core.common.businessentities.VmDeviceId; -import org.ovirt.engine.core.common.locks.LockingGroup; import org.ovirt.engine.core.common.errors.VdcBllMessages; +import org.ovirt.engine.core.common.locks.LockingGroup; import org.ovirt.engine.core.common.utils.Pair; +import org.ovirt.engine.core.common.utils.VmDeviceType; import org.ovirt.engine.core.common.vdscommands.VDSCommandType; import org.ovirt.engine.core.utils.transaction.TransactionMethod; import org.ovirt.engine.core.utils.transaction.TransactionSupport; @@ -22,7 +26,9 @@ public class HotPlugDiskToVmCommand<T extends HotPlugDiskToVmParameters> extends AbstractDiskVmCommand<T> { protected Disk disk; - private VmDevice oldVmDevice; + private Snapshot snapshot; + private VmDevice vmDeviceInfo; + boolean isDiskAttachedToTheVm = true; public HotPlugDiskToVmCommand(T parameters) { super(parameters); @@ -36,12 +42,12 @@ @Override protected boolean canDoAction() { - disk = getDiskDao().get(getParameters().getDiskId()); - - return - isVmExist() && + disk = loadDisk(); + SnapshotsValidator snapshotsValidator = getSnapshotsValidator(); + return isVmExist() && isVmInUpPausedDownStatus() && - isDiskExist(disk) && + (getParameters().getSnapshotId() == null || validate(snapshotsValidator.snapshotExists(getSnapshot()))) + && isDiskExist(disk, getParameters().isDiskShouldBeAttachedToTheVm()) && checkCanPerformPlugUnPlugDisk() && isVmNotInPreviewSnapshot(); } @@ -55,48 +61,82 @@ && isInterfaceSupportedForPlugUnPlug(disk); } if (returnValue) { - oldVmDevice = - getVmDeviceDao().get(new VmDeviceId(disk.getId(), getVmId())); - if (getPlugAction() == VDSCommandType.HotPlugDisk && oldVmDevice.getIsPlugged()) { - returnValue = false; - addCanDoActionMessage(VdcBllMessages.HOT_PLUG_DISK_IS_NOT_UNPLUGGED); - } - if (getPlugAction() == VDSCommandType.HotUnPlugDisk && !oldVmDevice.getIsPlugged()) { - returnValue = false; - addCanDoActionMessage(VdcBllMessages.HOT_UNPLUG_DISK_IS_NOT_PLUGGED); + prepareVmDeviceInfo(); + if (getParameters().isDiskShouldBeAttachedToTheVm()) { + if (getPlugAction() == VDSCommandType.HotPlugDisk && vmDeviceInfo.getIsPlugged()) { + returnValue = false; + addCanDoActionMessage(VdcBllMessages.HOT_PLUG_DISK_IS_NOT_UNPLUGGED); + } + if (getPlugAction() == VDSCommandType.HotUnPlugDisk && !vmDeviceInfo.getIsPlugged()) { + returnValue = false; + addCanDoActionMessage(VdcBllMessages.HOT_UNPLUG_DISK_IS_NOT_PLUGGED); + } } } return returnValue; + } + + private void prepareVmDeviceInfo() { + vmDeviceInfo = + getVmDeviceDao().get(new VmDeviceId(disk.getId(), getVmId())); + if (vmDeviceInfo == null && !getParameters().isDiskShouldBeAttachedToTheVm()) { + isDiskAttachedToTheVm = false; + vmDeviceInfo = createVmDevice(); + } + } + + protected VmDevice createVmDevice() { + return new VmDevice(new VmDeviceId(disk.getId(), getVmId()), + VmDeviceGeneralType.DISK, + VmDeviceType.DISK.getName(), + "", + 0, + null, + true, + true, + false, + "", + null); } protected VDSCommandType getPlugAction() { return VDSCommandType.HotPlugDisk; } + private Disk loadDisk() { + if (getParameters().getSnapshotId() == null) { + return getDiskDao().get(getParameters().getDiskId()); + } + return getDiskImageDao().getDiskSnapshotForVmSnapshot(getParameters().getDiskId(), + getParameters().getSnapshotId()); + } + @Override protected void executeVmCommand() { if (getVm().getStatus().isUpOrPaused()) { - performPlugCommand(getPlugAction(), disk, oldVmDevice); + performPlugCommand(getPlugAction(), disk, vmDeviceInfo); } - //Update boot order and isPlugged fields - final List<VmDevice> devices = VmDeviceUtils.updateBootOrderInVmDevice(getVm().getStaticData()); - for (VmDevice device:devices) { - if (device.getDeviceId().equals(oldVmDevice.getDeviceId())) { - device.setIsPlugged(!oldVmDevice.getIsPlugged()); - break; + if (isDiskAttachedToTheVm) { + // Update boot order and isPlugged fields + final List<VmDevice> devices = VmDeviceUtils.updateBootOrderInVmDevice(getVm().getStaticData()); + for (VmDevice device : devices) { + if (device.getDeviceId().equals(vmDeviceInfo.getDeviceId())) { + device.setIsPlugged(!vmDeviceInfo.getIsPlugged()); + break; + } } - } - TransactionSupport.executeInNewTransaction(new TransactionMethod<Void>() { - @Override - public Void runInTransaction() { - getVmStaticDAO().incrementDbGeneration(getVm().getId()); - getVmDeviceDao().updateAll("UpdateVmDeviceForHotPlugDisk", devices); - VmHandler.updateDisksFromDb(getVm()); - return null; - } - }); + TransactionSupport.executeInNewTransaction(new TransactionMethod<Void>() { + @Override + public Void runInTransaction() { + getVmStaticDAO().incrementDbGeneration(getVm().getId()); + getVmDeviceDao().updateAll("UpdateVmDeviceForHotPlugDisk", devices); + VmHandler.updateDisksFromDb(getVm()); + return null; + } + }); + } setSucceeded(true); } @@ -106,6 +146,13 @@ LockMessagesMatchUtil.makeLockingPair(LockingGroup.VM, VdcBllMessages.ACTION_TYPE_FAILED_OBJECT_LOCKED)); } + protected Snapshot getSnapshot() { + if (snapshot == null) { + snapshot = getSnapshotDao().get(getParameters().getSnapshotId()); + } + return snapshot; + } + @Override public AuditLogType getAuditLogTypeValue() { return getSucceeded() ? AuditLogType.USER_HOTPLUG_DISK : AuditLogType.USER_FAILED_HOTPLUG_DISK; diff --git a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/UpdateVmDiskCommand.java b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/UpdateVmDiskCommand.java index 97495fe..381f56b 100644 --- a/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/UpdateVmDiskCommand.java +++ b/backend/manager/modules/bll/src/main/java/org/ovirt/engine/core/bll/UpdateVmDiskCommand.java @@ -114,7 +114,7 @@ @Override protected boolean canDoAction() { - if (!isVmExist() || !isDiskExist(getOldDisk())) { + if (!isVmExist() || !isDiskExist(getOldDisk(), true)) { return false; } diff --git a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/HotPlugDiskToVmParameters.java b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/HotPlugDiskToVmParameters.java index 142b3a8..fa89ba8 100644 --- a/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/HotPlugDiskToVmParameters.java +++ b/backend/manager/modules/common/src/main/java/org/ovirt/engine/core/common/action/HotPlugDiskToVmParameters.java @@ -10,6 +10,9 @@ @NotNull private Guid diskId; + private Guid snapshotId; + private boolean performDbOperations = true; + private boolean diskShouldBeAttachedToTheVm = true; public HotPlugDiskToVmParameters(Guid vmId, Guid diskId) { super(vmId, null); @@ -26,4 +29,28 @@ public void setDiskId(Guid diskId) { this.diskId = diskId; } + + public Guid getSnapshotId() { + return snapshotId; + } + + public void setSnapshotId(Guid snapshotId) { + this.snapshotId = snapshotId; + } + + public boolean isPerformDbOperations() { + return performDbOperations; + } + + public void setPerformDbOperations(boolean performDbOperations) { + this.performDbOperations = performDbOperations; + } + + public boolean isDiskShouldBeAttachedToTheVm() { + return diskShouldBeAttachedToTheVm; + } + + public void setDiskShouldBeAttachedToTheVm(boolean diskShouldBeAttachedToTheVm) { + this.diskShouldBeAttachedToTheVm = diskShouldBeAttachedToTheVm; + } } diff --git a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/DiskImageDAO.java b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/DiskImageDAO.java index 3fc82ea..7023e3c 100644 --- a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/DiskImageDAO.java +++ b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/DiskImageDAO.java @@ -49,6 +49,17 @@ List<DiskImage> getAllSnapshotsForVmSnapshot(Guid id); /** + * Retrieves the disk image with the image information for the given vm snapshot id. + * + * @param diskId + * the disk id + * @param vmSnapshotId + * the snapshot id + * @return the list of snapshots + */ + DiskImage getDiskSnapshotForVmSnapshot(Guid diskId, Guid vmSnapshotId); + + /** * Retrieves all snapshots associated with the given image group. * * @param id diff --git a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/DiskImageDAODbFacadeImpl.java b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/DiskImageDAODbFacadeImpl.java index 4689ea3..11ef8e1 100644 --- a/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/DiskImageDAODbFacadeImpl.java +++ b/backend/manager/modules/dal/src/main/java/org/ovirt/engine/core/dao/DiskImageDAODbFacadeImpl.java @@ -70,6 +70,18 @@ } @Override + public DiskImage getDiskSnapshotForVmSnapshot(Guid diskId, Guid vmSnapshotId) { + MapSqlParameterSource parameterSource = getCustomMapSqlParameterSource() + .addValue("vm_snapshot_id", vmSnapshotId) + .addValue("image_group_id", diskId); + + return getCallsHandler().executeRead("GetDiskSnapshotForVmSnapshot", + DiskImageRowMapper.instance, + parameterSource); + } + + + @Override public List<DiskImage> getAllSnapshotsForImageGroup(Guid id) { MapSqlParameterSource parameterSource = getCustomMapSqlParameterSource() .addValue("image_group_id", id); diff --git a/backend/manager/modules/restapi/interface/common/jaxrs/src/main/java/org/ovirt/engine/api/common/util/LinkHelper.java b/backend/manager/modules/restapi/interface/common/jaxrs/src/main/java/org/ovirt/engine/api/common/util/LinkHelper.java index cd7eaa5..47af6b9 100644 --- a/backend/manager/modules/restapi/interface/common/jaxrs/src/main/java/org/ovirt/engine/api/common/util/LinkHelper.java +++ b/backend/manager/modules/restapi/interface/common/jaxrs/src/main/java/org/ovirt/engine/api/common/util/LinkHelper.java @@ -120,6 +120,8 @@ import org.ovirt.engine.api.resource.ReadOnlyDeviceResource; import org.ovirt.engine.api.resource.ReadOnlyDevicesResource; import org.ovirt.engine.api.resource.RolesResource; +import org.ovirt.engine.api.resource.SnapshotDiskResource; +import org.ovirt.engine.api.resource.SnapshotDisksResource; import org.ovirt.engine.api.resource.SnapshotResource; import org.ovirt.engine.api.resource.SnapshotsResource; import org.ovirt.engine.api.resource.StatisticResource; @@ -221,6 +223,7 @@ map = new ParentToCollectionMap(DiskResource.class, DisksResource.class); map.add(VmDiskResource.class, VmDisksResource.class, VM.class); map.add(TemplateDiskResource.class, TemplateDisksResource.class, Template.class); + map.add(SnapshotDiskResource.class, SnapshotDisksResource.class, Snapshot.class); map.add(DiskResource.class, DisksResource.class, StorageDomain.class); TYPES.put(Disk.class, map); diff --git a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/SnapshotDiskResource.java b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/SnapshotDiskResource.java index df7a5ad..4790649 100644 --- a/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/SnapshotDiskResource.java +++ b/backend/manager/modules/restapi/interface/definition/src/main/java/org/ovirt/engine/api/resource/SnapshotDiskResource.java @@ -1,16 +1,40 @@ package org.ovirt.engine.api.resource; +import javax.ws.rs.Consumes; import javax.ws.rs.GET; +import javax.ws.rs.POST; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; import javax.ws.rs.Produces; +import javax.ws.rs.core.Response; import org.jboss.resteasy.annotations.providers.jaxb.Formatted; +import org.ovirt.engine.api.model.Action; +import org.ovirt.engine.api.model.Actionable; import org.ovirt.engine.api.model.Disk; @Produces({ApiMediaType.APPLICATION_XML, ApiMediaType.APPLICATION_JSON, ApiMediaType.APPLICATION_X_YAML}) public interface SnapshotDiskResource { + @Path("{action: (hotplug|hotunplug)}/{oid}") + public ActionResource getActionSubresource(@PathParam("action")String action, @PathParam("oid")String oid); + @GET @Formatted public Disk get(); + @POST + @Formatted + @Actionable + @Path("hotplug") + @Consumes({ApiMediaType.APPLICATION_XML, ApiMediaType.APPLICATION_JSON, ApiMediaType.APPLICATION_X_YAML}) + public Response hotplug(Action action); + + @POST + @Formatted + @Actionable + @Path("hotunplug") + @Consumes({ApiMediaType.APPLICATION_XML, ApiMediaType.APPLICATION_JSON, ApiMediaType.APPLICATION_X_YAML}) + public Response hotunplug(Action action); + } diff --git a/backend/manager/modules/restapi/interface/definition/src/main/resources/rsdl_metadata.yaml b/backend/manager/modules/restapi/interface/definition/src/main/resources/rsdl_metadata.yaml index ed9529a..8451f57 100644 --- a/backend/manager/modules/restapi/interface/definition/src/main/resources/rsdl_metadata.yaml +++ b/backend/manager/modules/restapi/interface/definition/src/main/resources/rsdl_metadata.yaml @@ -710,6 +710,20 @@ signatures: [] urlparams: {} headers: {} +- name: /api/vms/{vm:id}/snapshots/{snapshot:id}/disks/{disk:id}/hotplug|rel=hotplug + request: + body: + parameterType: null + signatures: [] + urlparams: {} + headers: {} +- name: /api/vms/{vm:id}/snapshots/{snapshot:id}/disks/{disk:id}/hotunplug|rel=hotunplug + request: + body: + parameterType: null + signatures: [] + urlparams: {} + headers: {} - name: /api/vms/{vm:id}/snapshots/{snapshot:id}/nics|rel=get request: body: diff --git a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendSnapshotDiskResource.java b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendSnapshotDiskResource.java index ac6a353..1a765ec 100644 --- a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendSnapshotDiskResource.java +++ b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendSnapshotDiskResource.java @@ -1,29 +1,74 @@ package org.ovirt.engine.api.restapi.resource; import javax.ws.rs.WebApplicationException; - -import org.ovirt.engine.api.model.Disk; -import org.ovirt.engine.api.resource.SnapshotDiskResource; import javax.ws.rs.core.Response; -public class BackendSnapshotDiskResource implements SnapshotDiskResource { +import org.ovirt.engine.api.model.Action; +import org.ovirt.engine.api.model.Disk; +import org.ovirt.engine.api.model.VM; +import org.ovirt.engine.api.resource.ActionResource; +import org.ovirt.engine.api.resource.SnapshotDiskResource; +import org.ovirt.engine.core.common.action.HotPlugDiskToVmParameters; +import org.ovirt.engine.core.common.action.VdcActionType; +import org.ovirt.engine.core.common.interfaces.SearchType; +import org.ovirt.engine.core.compat.Guid; + +public class BackendSnapshotDiskResource extends AbstractBackendActionableResource<Disk, org.ovirt.engine.core.common.businessentities.Disk> implements SnapshotDiskResource { protected String diskId; protected BackendSnapshotDisksResource collection; public BackendSnapshotDiskResource(String diskId, BackendSnapshotDisksResource collection) { - super(); + super(diskId, Disk.class, org.ovirt.engine.core.common.businessentities.Disk.class, null); this.diskId = diskId; this.collection = collection; + } + + @Override + public ActionResource getActionSubresource(String action, String ids) { + return inject(new BackendActionResource(action, ids)); } @Override public Disk get() { for (Disk disk : collection.list().getDisks()) { if (disk.getId().equals(diskId)) { - return disk; + return addLinks(disk); } } throw new WebApplicationException(Response.status(Response.Status.NOT_FOUND).build()); } + + @Override + public Response hotplug(Action action) { + validateParameters(action, "vm.id|name"); + return doAction(VdcActionType.HotPlugDiskToVm, createHotPlugUnPlugParameters(action), action); + } + + @Override + public Response hotunplug(Action action) { + validateParameters(action, "vm.id|name"); + return doAction(VdcActionType.HotUnPlugDiskFromVm, createHotPlugUnPlugParameters(action), action); + } + + private Guid getVmId(VM vm) { + return vm.isSetId() + ? Guid.createGuidFromString(vm.getId()) + : getEntity(org.ovirt.engine.core.common.businessentities.StorageDomain.class, + SearchType.StorageDomain, + "Vm: name=" + vm.getName()).getId(); + } + + private HotPlugDiskToVmParameters createHotPlugUnPlugParameters(Action action) { + HotPlugDiskToVmParameters params = new HotPlugDiskToVmParameters(getVmId(action.getVm()), + Guid.createGuidFromString(diskId)); + params.setDiskShouldBeAttachedToTheVm(false); + params.setSnapshotId(collection.parent.guid); + return params; + } + + @Override + protected Disk doPopulate(Disk model, org.ovirt.engine.core.common.businessentities.Disk entity) { + return model; + } } diff --git a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendSnapshotDisksResource.java b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendSnapshotDisksResource.java index 401690f..3f0f65c 100644 --- a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendSnapshotDisksResource.java +++ b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendSnapshotDisksResource.java @@ -1,5 +1,8 @@ package org.ovirt.engine.api.restapi.resource; +import javax.ws.rs.core.Response; + +import org.ovirt.engine.api.model.Disk; import org.ovirt.engine.api.model.Disks; import org.ovirt.engine.api.resource.SnapshotDiskResource; import org.ovirt.engine.api.resource.SnapshotDisksResource; @@ -7,10 +10,13 @@ import org.ovirt.engine.core.common.businessentities.DiskImage; import org.ovirt.engine.core.common.businessentities.VM; -public class BackendSnapshotDisksResource extends BackendSnapshotElementsResource implements SnapshotDisksResource { +public class BackendSnapshotDisksResource extends AbstractBackendCollectionResource<Disk, org.ovirt.engine.core.common.businessentities.Disk> implements SnapshotDisksResource { - public BackendSnapshotDisksResource(BackendSnapshotResource parent, String vmId) { - super(parent, vmId); + protected BackendSnapshotResource parent; + + public BackendSnapshotDisksResource(BackendSnapshotResource parent) { + super(Disk.class, org.ovirt.engine.core.common.businessentities.Disk.class, null); + this.parent = parent; } @Override @@ -27,6 +33,16 @@ @Override public SnapshotDiskResource getDiskSubResource(String id) { - return new BackendSnapshotDiskResource(id, this); + return inject (new BackendSnapshotDiskResource(id, this)); + } + + @Override + protected Response performRemove(String id) { + throw new UnsupportedOperationException(); + } + + @Override + protected Disk doPopulate(Disk model, org.ovirt.engine.core.common.businessentities.Disk entity) { + return model; } } diff --git a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendSnapshotResource.java b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendSnapshotResource.java index 83fedfb..1f712b5 100644 --- a/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendSnapshotResource.java +++ b/backend/manager/modules/restapi/jaxrs/src/main/java/org/ovirt/engine/api/restapi/resource/BackendSnapshotResource.java @@ -126,7 +126,7 @@ } @Override public SnapshotDisksResource getSnapshotDisksResource() { - return new BackendSnapshotDisksResource(this, id); + return inject(new BackendSnapshotDisksResource(this)); } @Override public SnapshotNicsResource getSnapshotNicsResource() { diff --git a/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendSnapshotDiskResourceTest.java b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendSnapshotDiskResourceTest.java new file mode 100644 index 0000000..7f6573e --- /dev/null +++ b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendSnapshotDiskResourceTest.java @@ -0,0 +1,80 @@ +package org.ovirt.engine.api.restapi.resource; + +import javax.ws.rs.core.Response; + +import org.junit.Test; +import org.ovirt.engine.api.model.Action; +import org.ovirt.engine.api.model.CreationStatus; +import org.ovirt.engine.api.model.Disk; +import org.ovirt.engine.api.model.VM; +import org.ovirt.engine.core.common.action.HotPlugDiskToVmParameters; +import org.ovirt.engine.core.common.action.VdcActionType; +import org.ovirt.engine.core.compat.Guid; + + +public class BackendSnapshotDiskResourceTest + extends AbstractBackendSubResourceTest<Disk, org.ovirt.engine.core.common.businessentities.Disk, BackendSnapshotDiskResource> { + + protected static final Guid DISK_ID = GUIDS[0]; + private final static Guid VM_ID = GUIDS[1]; + private final static Guid SNAPSHOT_ID = GUIDS[2]; + + protected static BackendSnapshotDisksResource collection; + + public BackendSnapshotDiskResourceTest() { + super(new BackendSnapshotDiskResource(DISK_ID.toString(), getCollection())); + } + + protected static BackendSnapshotDisksResource getCollection() { + return new BackendSnapshotDisksResource(new BackendSnapshotResource(SNAPSHOT_ID.toString(), VM_ID, new BackendSnapshotsResource(VM_ID))); + } + + @Override + protected void init() { + super.init(); + initResource(resource.collection); + } + + + @Override + protected org.ovirt.engine.core.common.businessentities.Disk getEntity(int index) { + org.ovirt.engine.core.common.businessentities.Disk disk = control.createMock(org.ovirt.engine.core.common.businessentities.Disk.class); + return disk; + } + + @Test + public void testHotPlug() throws Exception { + setUriInfo(setUpActionExpectations(VdcActionType.HotPlugDiskToVm, + HotPlugDiskToVmParameters.class, + new String[] { "VmId", "SnapshotId", "DiskId" }, + new Object[] { VM_ID, SNAPSHOT_ID, DISK_ID}, + true, + true)); + Action action1 = new Action(); + action1.setVm(new VM()); + action1.getVm().setId(VM_ID.toString()); + Response response = resource.hotplug(action1); + assertEquals(200, response.getStatus()); + Action action = (Action)response.getEntity(); + assertTrue(action.isSetStatus()); + assertEquals(CreationStatus.COMPLETE.value(), action.getStatus().getState()); + } + + @Test + public void testHotUnPlug() throws Exception { + setUriInfo(setUpActionExpectations(VdcActionType.HotUnPlugDiskFromVm, + HotPlugDiskToVmParameters.class, + new String[] { "VmId", "SnapshotId", "DiskId" }, + new Object[] { VM_ID, SNAPSHOT_ID, DISK_ID}, + true, + true)); + Action action1 = new Action(); + action1.setVm(new VM()); + action1.getVm().setId(VM_ID.toString()); + Response response = resource.hotunplug(action1); + assertEquals(200, response.getStatus()); + Action action = (Action)response.getEntity(); + assertTrue(action.isSetStatus()); + assertEquals(CreationStatus.COMPLETE.value(), action.getStatus().getState()); + } +} diff --git a/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendSnapshotResourceTest.java b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendSnapshotResourceTest.java index 1d03d07..3601bac 100644 --- a/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendSnapshotResourceTest.java +++ b/backend/manager/modules/restapi/jaxrs/src/test/java/org/ovirt/engine/api/restapi/resource/BackendSnapshotResourceTest.java @@ -156,7 +156,7 @@ return setUpActionExpectations( VdcActionType.TryBackToAllSnapshotsOfVm, TryBackToAllSnapshotsOfVmParameters.class, - new String[] { "VmId", "DstSnapshotId" }, + new String[] { "VmId", "SnapshotId", "DiskId" }, new Object[] { VM_ID, SNAPSHOT_ID }, true, true, diff --git a/packaging/dbscripts/disk_images_sp.sql b/packaging/dbscripts/disk_images_sp.sql index 3266cd7..a259f98 100644 --- a/packaging/dbscripts/disk_images_sp.sql +++ b/packaging/dbscripts/disk_images_sp.sql @@ -127,6 +127,19 @@ +Create or replace FUNCTION GetDiskSnapshotForVmSnapshot(v_image_group_id UUID, v_vm_snapshot_id UUID) + RETURNS SETOF images_storage_domain_view + AS $procedure$ + BEGIN + RETURN QUERY SELECT * + FROM images_storage_domain_view images_storage_domain_view + WHERE image_group_id = v_image_group_id + AND vm_snapshot_id = v_vm_snapshot_id; + END; $procedure$ + LANGUAGE plpgsql; + + + Create or replace FUNCTION GetImagesWhichHaveNoDisk(v_vm_id UUID) RETURNS SETOF images_storage_domain_view AS $procedure$ -- To view, visit http://gerrit.ovirt.org/17420 To unsubscribe, visit http://gerrit.ovirt.org/settings Gerrit-MessageType: newchange Gerrit-Change-Id: Id1a265438dc5bc2d887a88a9be12641c721d9735 Gerrit-PatchSet: 1 Gerrit-Project: ovirt-engine Gerrit-Branch: master Gerrit-Owner: Liron Ar <lara...@redhat.com> _______________________________________________ Engine-patches mailing list Engine-patches@ovirt.org http://lists.ovirt.org/mailman/listinfo/engine-patches