|
201 | 201 | import com.cloud.user.Account; |
202 | 202 | import com.cloud.user.ResourceLimitService; |
203 | 203 | import com.cloud.user.User; |
| 204 | +import com.cloud.uservm.UserVm; |
204 | 205 | import com.cloud.utils.DateUtil; |
205 | 206 | import com.cloud.utils.Journal; |
206 | 207 | import com.cloud.utils.Pair; |
@@ -5629,4 +5630,107 @@ protected void resourceCountDecrement (long accountId, Long cpu, Long memory) { |
5629 | 5630 | _resourceLimitMgr.decrementResourceCount(accountId, ResourceType.memory, memory); |
5630 | 5631 | } |
5631 | 5632 |
|
| 5633 | + @Override |
| 5634 | + public UserVm restoreVirtualMachine(final long vmId, final Long newTemplateId) throws ResourceUnavailableException, InsufficientCapacityException { |
| 5635 | + final AsyncJobExecutionContext jobContext = AsyncJobExecutionContext.getCurrentExecutionContext(); |
| 5636 | + if (jobContext.isJobDispatchedBy(VmWorkConstants.VM_WORK_JOB_DISPATCHER)) { |
| 5637 | + VmWorkJobVO placeHolder = null; |
| 5638 | + placeHolder = createPlaceHolderWork(vmId); |
| 5639 | + try { |
| 5640 | + return orchestrateRestoreVirtualMachine(vmId, newTemplateId); |
| 5641 | + } finally { |
| 5642 | + if (placeHolder != null) { |
| 5643 | + _workJobDao.expunge(placeHolder.getId()); |
| 5644 | + } |
| 5645 | + } |
| 5646 | + } else { |
| 5647 | + final Outcome<VirtualMachine> outcome = restoreVirtualMachineThroughJobQueue(vmId, newTemplateId); |
| 5648 | + |
| 5649 | + try { |
| 5650 | + outcome.get(); |
| 5651 | + } catch (final InterruptedException e) { |
| 5652 | + throw new RuntimeException("Operation is interrupted", e); |
| 5653 | + } catch (final java.util.concurrent.ExecutionException e) { |
| 5654 | + throw new RuntimeException("Execution exception", e); |
| 5655 | + } |
| 5656 | + |
| 5657 | + final Object jobResult = _jobMgr.unmarshallResultObject(outcome.getJob()); |
| 5658 | + if (jobResult != null) { |
| 5659 | + if (jobResult instanceof ResourceUnavailableException) { |
| 5660 | + throw (ResourceUnavailableException)jobResult; |
| 5661 | + } else if (jobResult instanceof ConcurrentOperationException) { |
| 5662 | + throw (ConcurrentOperationException)jobResult; |
| 5663 | + } else if (jobResult instanceof RuntimeException) { |
| 5664 | + throw (RuntimeException)jobResult; |
| 5665 | + } else if (jobResult instanceof Throwable) { |
| 5666 | + throw new RuntimeException("Unexpected exception", (Throwable)jobResult); |
| 5667 | + } else if (jobResult instanceof HashMap) { |
| 5668 | + HashMap<Long, String> passwordMap = (HashMap<Long, String>)jobResult; |
| 5669 | + UserVmVO userVm = _userVmDao.findById(vmId); |
| 5670 | + userVm.setPassword(passwordMap.get(vmId)); |
| 5671 | + return userVm; |
| 5672 | + } |
| 5673 | + } |
| 5674 | + throw new RuntimeException("Unexpected job execution result"); |
| 5675 | + } |
| 5676 | + } |
| 5677 | + |
| 5678 | + private UserVm orchestrateRestoreVirtualMachine(final long vmId, final Long newTemplateId) throws ResourceUnavailableException, InsufficientCapacityException { |
| 5679 | + s_logger.debug("Restoring vm " + vmId + " with new templateId " + newTemplateId); |
| 5680 | + final CallContext context = CallContext.current(); |
| 5681 | + final Account account = context.getCallingAccount(); |
| 5682 | + return _userVmService.restoreVirtualMachine(account, vmId, newTemplateId); |
| 5683 | + } |
| 5684 | + |
| 5685 | + public Outcome<VirtualMachine> restoreVirtualMachineThroughJobQueue(final long vmId, final Long newTemplateId) { |
| 5686 | + |
| 5687 | + final CallContext context = CallContext.current(); |
| 5688 | + final User user = context.getCallingUser(); |
| 5689 | + final Account account = context.getCallingAccount(); |
| 5690 | + |
| 5691 | + final List<VmWorkJobVO> pendingWorkJobs = _workJobDao.listPendingWorkJobs( |
| 5692 | + VirtualMachine.Type.Instance, vmId, |
| 5693 | + VmWorkRestore.class.getName()); |
| 5694 | + |
| 5695 | + VmWorkJobVO workJob = null; |
| 5696 | + if (pendingWorkJobs != null && pendingWorkJobs.size() > 0) { |
| 5697 | + assert pendingWorkJobs.size() == 1; |
| 5698 | + workJob = pendingWorkJobs.get(0); |
| 5699 | + } else { |
| 5700 | + |
| 5701 | + workJob = new VmWorkJobVO(context.getContextId()); |
| 5702 | + |
| 5703 | + workJob.setDispatcher(VmWorkConstants.VM_WORK_JOB_DISPATCHER); |
| 5704 | + workJob.setCmd(VmWorkRestore.class.getName()); |
| 5705 | + |
| 5706 | + workJob.setAccountId(account.getId()); |
| 5707 | + workJob.setUserId(user.getId()); |
| 5708 | + workJob.setVmType(VirtualMachine.Type.Instance); |
| 5709 | + workJob.setVmInstanceId(vmId); |
| 5710 | + workJob.setRelated(AsyncJobExecutionContext.getOriginJobId()); |
| 5711 | + |
| 5712 | + final VmWorkRestore workInfo = new VmWorkRestore(user.getId(), account.getId(), vmId, |
| 5713 | + VirtualMachineManagerImpl.VM_WORK_JOB_HANDLER, newTemplateId); |
| 5714 | + workJob.setCmdInfo(VmWorkSerializer.serialize(workInfo)); |
| 5715 | + |
| 5716 | + _jobMgr.submitAsyncJob(workJob, VmWorkConstants.VM_WORK_QUEUE, vmId); |
| 5717 | + } |
| 5718 | + AsyncJobExecutionContext.getCurrentExecutionContext().joinJob(workJob.getId()); |
| 5719 | + |
| 5720 | + return new VmJobVirtualMachineOutcome(workJob, vmId); |
| 5721 | + } |
| 5722 | + |
| 5723 | + @ReflectionUse |
| 5724 | + private Pair<JobInfo.Status, String> orchestrateRestoreVirtualMachine(final VmWorkRestore work) throws Exception { |
| 5725 | + final VMInstanceVO vm = _entityMgr.findById(VMInstanceVO.class, work.getVmId()); |
| 5726 | + if (vm == null) { |
| 5727 | + s_logger.info("Unable to find vm " + work.getVmId()); |
| 5728 | + } |
| 5729 | + assert vm != null; |
| 5730 | + UserVm uservm = orchestrateRestoreVirtualMachine(vm.getId(), work.getTemplateId()); |
| 5731 | + HashMap<Long, String> passwordMap = new HashMap<Long, String>(); |
| 5732 | + passwordMap.put(uservm.getId(), uservm.getPassword()); |
| 5733 | + return new Pair<JobInfo.Status, String>(JobInfo.Status.SUCCEEDED, _jobMgr.marshallResultObject(passwordMap)); |
| 5734 | + } |
| 5735 | + |
5632 | 5736 | } |
0 commit comments