CLOUDSTACK-1453: support restore for VM created from ISO
This is to support restore a vm to a new/currently_attached ISO.
In the restorevm API we have an optional parameter templateId to restore the vm 
to the new template/ISO ID.


Project: http://git-wip-us.apache.org/repos/asf/cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/cloudstack/commit/a34e577d
Tree: http://git-wip-us.apache.org/repos/asf/cloudstack/tree/a34e577d
Diff: http://git-wip-us.apache.org/repos/asf/cloudstack/diff/a34e577d

Branch: refs/heads/vmware-storage-motion
Commit: a34e577d1be5a25d7eb884147212ab51786b55e2
Parents: 23baacb
Author: Harikrishna Patnala <[email protected]>
Authored: Fri May 24 16:38:55 2013 +0530
Committer: Koushik Das <[email protected]>
Committed: Fri May 24 16:41:03 2013 +0530

----------------------------------------------------------------------
 .../api/command/user/vm/RestoreVMCmd.java          |    5 +-
 server/src/com/cloud/vm/UserVmManagerImpl.java     |   43 +++++++++++----
 server/test/com/cloud/vm/UserVmManagerTest.java    |   42 +++++++++++++--
 3 files changed, 74 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a34e577d/api/src/org/apache/cloudstack/api/command/user/vm/RestoreVMCmd.java
----------------------------------------------------------------------
diff --git 
a/api/src/org/apache/cloudstack/api/command/user/vm/RestoreVMCmd.java 
b/api/src/org/apache/cloudstack/api/command/user/vm/RestoreVMCmd.java
index 9c33f97..2f7d8e1 100644
--- a/api/src/org/apache/cloudstack/api/command/user/vm/RestoreVMCmd.java
+++ b/api/src/org/apache/cloudstack/api/command/user/vm/RestoreVMCmd.java
@@ -35,7 +35,7 @@ import com.cloud.user.Account;
 import com.cloud.user.UserContext;
 import com.cloud.uservm.UserVm;
 
-@APICommand(name = "restoreVirtualMachine", description="Restore a VM to 
original template or new template", responseObject=UserVmResponse.class, 
since="3.0.0")
+@APICommand(name = "restoreVirtualMachine", description="Restore a VM to 
original template/ISO or new template/ISO", 
responseObject=UserVmResponse.class, since="3.0.0")
 public class RestoreVMCmd extends BaseAsyncCmd {
     public static final Logger s_logger = Logger.getLogger(RestoreVMCmd.class);
     private static final String s_name = "restorevmresponse";
@@ -44,9 +44,10 @@ public class RestoreVMCmd extends BaseAsyncCmd {
             required=true, description="Virtual Machine ID")
     private Long vmId;
 
-    @Parameter(name=ApiConstants.TEMPLATE_ID, type=CommandType.UUID, 
entityType = TemplateResponse.class, description="an optional template Id to 
restore vm from the new template")
+    @Parameter(name=ApiConstants.TEMPLATE_ID, type=CommandType.UUID, 
entityType = TemplateResponse.class, description="an optional template Id to 
restore vm from the new template. This can be an ISO id in case of restore vm 
deployed using ISO")
     private Long templateId;
 
+
     @Override
     public String getEventType() {
         return EventTypes.EVENT_VM_RESTORE;

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a34e577d/server/src/com/cloud/vm/UserVmManagerImpl.java
----------------------------------------------------------------------
diff --git a/server/src/com/cloud/vm/UserVmManagerImpl.java 
b/server/src/com/cloud/vm/UserVmManagerImpl.java
index c10a9d8..96b9529 100755
--- a/server/src/com/cloud/vm/UserVmManagerImpl.java
+++ b/server/src/com/cloud/vm/UserVmManagerImpl.java
@@ -4237,6 +4237,7 @@ public class UserVmManagerImpl extends ManagerBase 
implements UserVmManager, Use
 
         long vmId = cmd.getVmId();
         Long newTemplateId = cmd.getTemplateId();
+
         UserVmVO vm = _vmDao.findById(vmId);
         if (vm == null) {
             InvalidParameterValueException ex = new 
InvalidParameterValueException("Cannot find VM with ID " + vmId);
@@ -4292,21 +4293,35 @@ public class UserVmManagerImpl extends ManagerBase 
implements UserVmManager, Use
 
         VolumeVO root = rootVols.get(0);
         Long templateId = root.getTemplateId();
+        boolean isISO = false;
         if(templateId == null) {
-            InvalidParameterValueException ex = new 
InvalidParameterValueException("Currently there is no support to reset a vm 
that is deployed using ISO " + vm.getUuid());
-            ex.addProxyObject(vm, vmId, "vmId");
-            throw ex;
+        // Assuming that for a vm deployed using ISO, template ID is set to 
NULL
+            isISO = true;
+            templateId = vm.getIsoId();
         }
 
         VMTemplateVO template = null;
+        //newTemplateId can be either template or ISO id. In the following 
snippet based on the vm deployment (from template or ISO) it is handled 
accordingly
         if(newTemplateId != null) {
             template = _templateDao.findById(newTemplateId);
             _accountMgr.checkAccess(caller, null, true, template);
+            if (isISO) {
+                if (!template.getFormat().equals(ImageFormat.ISO)) {
+                    throw new InvalidParameterValueException("Invalid ISO id 
provided to restore the VM ");
+                }
+            } else {
+                if (template.getFormat().equals(ImageFormat.ISO)) {
+                    throw new InvalidParameterValueException("Invalid template 
id provided to restore the VM ");
+                }
+            }
         } else {
+            if (isISO && templateId == null) {
+                throw new CloudRuntimeException("Cannot restore the VM since 
there is no ISO attached to VM");
+            }
             template = _templateDao.findById(templateId);
             if (template == null) {
                 InvalidParameterValueException ex = new 
InvalidParameterValueException(
-                        "Cannot find template for specified volumeid and 
vmId");
+                        "Cannot find template/ISO for specified volumeid and 
vmId");
                 ex.addProxyObject(vm, vmId, "vmId");
                 ex.addProxyObject(root, root.getId(), "volumeId");
                 throw ex;
@@ -4325,13 +4340,21 @@ public class UserVmManagerImpl extends ManagerBase 
implements UserVmManager, Use
             }
         }
 
-        /* If new template is provided allocate a new volume from new template 
otherwise allocate new volume from original template */
+        /* If new template/ISO is provided allocate a new volume from new 
template/ISO otherwise allocate new volume from original template/ISO */
         VolumeVO newVol = null;
-        if (newTemplateId != null){
-            newVol = volumeMgr.allocateDuplicateVolume(root, newTemplateId);
-            vm.setGuestOSId(template.getGuestOSId());
-            vm.setTemplateId(newTemplateId);
-            _vmDao.update(vmId, vm);
+        if (newTemplateId != null) {
+            if (isISO) {
+                newVol = volumeMgr.allocateDuplicateVolume(root, null);
+                vm.setIsoId(newTemplateId);
+                vm.setGuestOSId(template.getGuestOSId());
+                vm.setTemplateId(newTemplateId);
+                _vmDao.update(vmId, vm);
+            } else {
+                newVol = volumeMgr.allocateDuplicateVolume(root, 
newTemplateId);
+                vm.setGuestOSId(template.getGuestOSId());
+                vm.setTemplateId(newTemplateId);
+                _vmDao.update(vmId, vm);
+            }
         } else {
             newVol = volumeMgr.allocateDuplicateVolume(root, null);
         }

http://git-wip-us.apache.org/repos/asf/cloudstack/blob/a34e577d/server/test/com/cloud/vm/UserVmManagerTest.java
----------------------------------------------------------------------
diff --git a/server/test/com/cloud/vm/UserVmManagerTest.java 
b/server/test/com/cloud/vm/UserVmManagerTest.java
index 6a97114..5eedfa5 100755
--- a/server/test/com/cloud/vm/UserVmManagerTest.java
+++ b/server/test/com/cloud/vm/UserVmManagerTest.java
@@ -24,10 +24,8 @@ import static org.mockito.Matchers.anyInt;
 import static org.mockito.Matchers.anyLong;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.doThrow;
-import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.*;
+import static org.mockito.Mockito.times;
 
 import java.lang.reflect.Field;
 import java.util.List;
@@ -64,6 +62,7 @@ import com.cloud.storage.VolumeManager;
 import com.cloud.storage.VolumeVO;
 import com.cloud.storage.dao.VMTemplateDao;
 import com.cloud.storage.dao.VolumeDao;
+import com.cloud.storage.Storage.ImageFormat;
 import com.cloud.user.Account;
 import com.cloud.user.AccountManager;
 import com.cloud.user.AccountService;
@@ -200,6 +199,7 @@ public class UserVmManagerTest {
         doReturn(false).when(_rootVols).isEmpty();
         when(_rootVols.get(eq(0))).thenReturn(_volumeMock);
         doReturn(3L).when(_volumeMock).getTemplateId();
+        doReturn(ImageFormat.VHD).when(_templateMock).getFormat();
         when(_templateDao.findById(anyLong())).thenReturn(_templateMock);
         doNothing().when(_accountMgr).checkAccess(_account, null, true, 
_templateMock);
         when(_itMgr.stop(_vmMock, _userMock, _account)).thenReturn(true);
@@ -220,6 +220,40 @@ public class UserVmManagerTest {
 
     }
 
+    // Test restoreVM on providing new ISO Id, when VM(deployed using ISO) is 
in running state
+    @Test
+    public void testRestoreVMF5()  throws ResourceUnavailableException, 
InsufficientCapacityException, ServerApiException,
+            ConcurrentOperationException, ResourceAllocationException {
+        doReturn(VirtualMachine.State.Running).when(_vmMock).getState();
+        when(_vmDao.findById(anyLong())).thenReturn(_vmMock);
+        when(_volsDao.findByInstanceAndType(314L, 
Volume.Type.ROOT)).thenReturn(_rootVols);
+        doReturn(false).when(_rootVols).isEmpty();
+        when(_rootVols.get(eq(0))).thenReturn(_volumeMock);
+        doReturn(null).when(_volumeMock).getTemplateId();
+        doReturn(3L).when(_vmMock).getIsoId();
+        doReturn(ImageFormat.ISO).when(_templateMock).getFormat();
+        when(_templateDao.findById(anyLong())).thenReturn(_templateMock);
+        doNothing().when(_accountMgr).checkAccess(_account, null, true, 
_templateMock);
+        when(_itMgr.stop(_vmMock, _userMock, _account)).thenReturn(true);
+        when(_storageMgr.allocateDuplicateVolume(_volumeMock, 
null)).thenReturn(_volumeMock);
+        doNothing().when(_vmMock).setIsoId(14L);
+        when(_templateMock.getGuestOSId()).thenReturn(5L);
+        doNothing().when(_vmMock).setGuestOSId(anyLong());
+        doNothing().when(_vmMock).setTemplateId(3L);
+        when(_vmDao.update(314L, _vmMock)).thenReturn(true);
+        when(_itMgr.start(_vmMock, null, _userMock, 
_account)).thenReturn(_vmMock);
+        when(_storageMgr.allocateDuplicateVolume(_volumeMock, 
null)).thenReturn(_volumeMock);
+        doNothing().when(_volsDao).attachVolume(anyLong(), anyLong(), 
anyLong());
+        when(_volumeMock.getId()).thenReturn(3L);
+        doNothing().when(_volsDao).detachVolume(anyLong());
+
+        
when(_templateMock.getUuid()).thenReturn("b1a3626e-72e0-4697-8c7c-a110940cc55d");
+
+        _userVmMgr.restoreVMInternal(_account, _vmMock, 14L);
+
+        verify(_vmMock, times(1)).setIsoId(14L);
+
+    }
     // Test scaleVm on incompatible HV.
     @Test(expected=InvalidParameterValueException.class)
     public void testScaleVMF1()  throws Exception {

Reply via email to