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

Reply via email to