|
74 | 74 | import org.apache.cloudstack.api.command.admin.vm.ExpungeVMCmd; |
75 | 75 | import org.apache.cloudstack.api.command.admin.vm.RecoverVMCmd; |
76 | 76 | import org.apache.cloudstack.api.command.user.vm.AddNicToVMCmd; |
| 77 | +import org.apache.cloudstack.api.command.user.vm.CreateVMFromBackupCmd; |
77 | 78 | import org.apache.cloudstack.api.command.user.vm.DeployVMCmd; |
78 | 79 | import org.apache.cloudstack.api.command.user.vm.DeployVnfApplianceCmd; |
79 | 80 | import org.apache.cloudstack.api.command.user.vm.DestroyVMCmd; |
|
96 | 97 | import org.apache.cloudstack.api.command.user.volume.ResizeVolumeCmd; |
97 | 98 | import org.apache.cloudstack.backup.Backup; |
98 | 99 | import org.apache.cloudstack.backup.BackupManager; |
| 100 | +import org.apache.cloudstack.backup.BackupVO; |
99 | 101 | import org.apache.cloudstack.backup.dao.BackupDao; |
100 | 102 | import org.apache.cloudstack.context.CallContext; |
101 | 103 | import org.apache.cloudstack.engine.cloud.entity.api.VirtualMachineEntity; |
@@ -8725,6 +8727,172 @@ public boolean unmanageUserVM(Long vmId) { |
8725 | 8727 | return true; |
8726 | 8728 | } |
8727 | 8729 |
|
| 8730 | + @Override |
| 8731 | + public UserVm allocateVMFromBackup(CreateVMFromBackupCmd cmd) throws InsufficientCapacityException, ResourceAllocationException, ResourceUnavailableException { |
| 8732 | + //Verify that all objects exist before passing them to the service |
| 8733 | + Account owner = _accountService.getActiveAccountById(cmd.getEntityOwnerId()); |
| 8734 | + Long zoneId = cmd.getZoneId(); |
| 8735 | + DataCenter zone = _entityMgr.findById(DataCenter.class, zoneId); |
| 8736 | + if (zone == null) { |
| 8737 | + throw new InvalidParameterValueException("Unable to find zone by id=" + zoneId); |
| 8738 | + } |
| 8739 | + |
| 8740 | + BackupVO backup = backupDao.findById(cmd.getBackupId()); |
| 8741 | + if (backup == null) { |
| 8742 | + throw new InvalidParameterValueException("Backup " + cmd.getBackupId() + " does not exist"); |
| 8743 | + } |
| 8744 | + if (backup.getZoneId() != cmd.getZoneId()) { |
| 8745 | + throw new InvalidParameterValueException("Instance should be created in the same zone as the backup"); |
| 8746 | + } |
| 8747 | + backupManager.validateBackupForZone(backup.getZoneId()); |
| 8748 | + |
| 8749 | + verifyDetails(cmd.getDetails()); |
| 8750 | + |
| 8751 | + Long serviceOfferingId = cmd.getServiceOfferingId(); |
| 8752 | + Long overrideDiskOfferingId = cmd.getOverrideDiskOfferingId(); |
| 8753 | + |
| 8754 | + ServiceOffering serviceOffering = _entityMgr.findById(ServiceOffering.class, serviceOfferingId); |
| 8755 | + if (serviceOffering == null) { |
| 8756 | + throw new InvalidParameterValueException("Unable to find service offering: " + serviceOfferingId); |
| 8757 | + } |
| 8758 | + |
| 8759 | + if (ServiceOffering.State.Inactive.equals(serviceOffering.getState())) { |
| 8760 | + throw new InvalidParameterValueException(String.format("Service offering is inactive: [%s].", serviceOffering.getUuid())); |
| 8761 | + } |
| 8762 | + |
| 8763 | + if (serviceOffering.getDiskOfferingStrictness() && overrideDiskOfferingId != null) { |
| 8764 | + throw new InvalidParameterValueException(String.format("Cannot override disk offering id %d since provided service offering is strictly mapped to its disk offering", overrideDiskOfferingId)); |
| 8765 | + } |
| 8766 | + |
| 8767 | + if (!serviceOffering.isDynamic()) { |
| 8768 | + for(String detail: cmd.getDetails().keySet()) { |
| 8769 | + if(detail.equalsIgnoreCase(VmDetailConstants.CPU_NUMBER) || detail.equalsIgnoreCase(VmDetailConstants.CPU_SPEED) || detail.equalsIgnoreCase(VmDetailConstants.MEMORY)) { |
| 8770 | + throw new InvalidParameterValueException("cpuNumber or cpuSpeed or memory should not be specified for static service offering"); |
| 8771 | + } |
| 8772 | + } |
| 8773 | + } |
| 8774 | + |
| 8775 | + Long templateId = cmd.getTemplateId(); |
| 8776 | + VirtualMachineTemplate template = _entityMgr.findById(VirtualMachineTemplate.class, templateId); |
| 8777 | + // todo : check for dummy template |
| 8778 | + if (template == null) { |
| 8779 | + throw new InvalidParameterValueException("Unable to use template " + templateId); |
| 8780 | + } |
| 8781 | + |
| 8782 | + if (template.isDeployAsIs()) { |
| 8783 | + throw new InvalidParameterValueException("Deploy as is template not supported"); |
| 8784 | + } |
| 8785 | + |
| 8786 | + Long diskOfferingId = cmd.getDiskOfferingId(); |
| 8787 | + DiskOffering diskOffering = null; |
| 8788 | + if (diskOfferingId != null) { |
| 8789 | + diskOffering = _entityMgr.findById(DiskOffering.class, diskOfferingId); |
| 8790 | + if (diskOffering == null) { |
| 8791 | + throw new InvalidParameterValueException("Unable to find disk offering " + diskOfferingId); |
| 8792 | + } |
| 8793 | + if (diskOffering.isComputeOnly()) { |
| 8794 | + throw new InvalidParameterValueException(String.format("The disk offering id %d provided is directly mapped to a service offering, please provide an individual disk offering", diskOfferingId)); |
| 8795 | + } |
| 8796 | + } |
| 8797 | + |
| 8798 | + DiskOffering diskOfferingMappedInServiceOffering = _entityMgr.findById(DiskOffering.class, serviceOffering.getDiskOfferingId()); |
| 8799 | + if (diskOfferingMappedInServiceOffering.isUseLocalStorage()) { |
| 8800 | + throw new InvalidParameterValueException("Local storage disk offering not supported for instance created from backup"); |
| 8801 | + } |
| 8802 | + if (diskOffering != null && diskOffering.isUseLocalStorage()) { |
| 8803 | + throw new InvalidParameterValueException("Local storage disk offering not supported for instance created from backup"); |
| 8804 | + } |
| 8805 | + |
| 8806 | + List<Long> networkIds = cmd.getNetworkIds(); |
| 8807 | + LinkedHashMap<Integer, Long> userVmNetworkMap = getVmOvfNetworkMapping(zone, owner, template, cmd.getVmNetworkMap()); |
| 8808 | + if (MapUtils.isNotEmpty(userVmNetworkMap)) { |
| 8809 | + networkIds = new ArrayList<>(userVmNetworkMap.values()); |
| 8810 | + } |
| 8811 | + |
| 8812 | + if (cmd.getUserData() != null) { |
| 8813 | + throw new InvalidParameterValueException("User data not supported for instance created from backup"); |
| 8814 | + } |
| 8815 | + |
| 8816 | + String name = cmd.getName(); |
| 8817 | + String displayName = cmd.getDisplayName(); |
| 8818 | + Long size = cmd.getSize(); |
| 8819 | + Map<Long, DiskOffering> dataDiskTemplateToDiskOfferingMap = cmd.getDataDiskTemplateToDiskOfferingMap(); |
| 8820 | + List<String> sshKeyPairs = new ArrayList<String>(); |
| 8821 | + String ipAddress = cmd.getIpAddress(); |
| 8822 | + String ip6Address = cmd.getIp6Address(); |
| 8823 | + String macAddress = cmd.getMacAddress(); |
| 8824 | + IpAddresses addrs = new IpAddresses(ipAddress, ip6Address, macAddress); |
| 8825 | + Map<String, String> userVmOVFProperties = new HashMap<>(); |
| 8826 | + |
| 8827 | + UserVm vm = null; |
| 8828 | + if (zone.getNetworkType() == NetworkType.Basic) { |
| 8829 | + if (networkIds != null) { |
| 8830 | + throw new InvalidParameterValueException("Can't specify network Ids in Basic zone"); |
| 8831 | + } else { |
| 8832 | + vm = createBasicSecurityGroupVirtualMachine(zone, serviceOffering, template, getSecurityGroupIdList(cmd, zone, template, owner), owner, name, displayName, diskOfferingId, |
| 8833 | + size , null , cmd.getHypervisor(), cmd.getHttpMethod(), null, null, null, sshKeyPairs, cmd.getIpToNetworkMap(), addrs, null , null , cmd.getAffinityGroupIdList(), |
| 8834 | + cmd.getDetails(), cmd.getCustomId(), cmd.getDhcpOptionsMap(), |
| 8835 | + dataDiskTemplateToDiskOfferingMap, userVmOVFProperties, false, overrideDiskOfferingId); |
| 8836 | + } |
| 8837 | + } else { |
| 8838 | + if (_networkModel.checkSecurityGroupSupportForNetwork(owner, zone, networkIds, |
| 8839 | + cmd.getSecurityGroupIdList())) { |
| 8840 | + vm = createAdvancedSecurityGroupVirtualMachine(zone, serviceOffering, template, networkIds, getSecurityGroupIdList(cmd, zone, template, owner), owner, name, |
| 8841 | + displayName, diskOfferingId, size, null, cmd.getHypervisor(), cmd.getHttpMethod(), null, null, null, sshKeyPairs, cmd.getIpToNetworkMap(), addrs, null, null, |
| 8842 | + cmd.getAffinityGroupIdList(), cmd.getDetails(), cmd.getCustomId(), cmd.getDhcpOptionsMap(), |
| 8843 | + dataDiskTemplateToDiskOfferingMap, userVmOVFProperties, false, overrideDiskOfferingId, null); |
| 8844 | + |
| 8845 | + } else { |
| 8846 | + if (cmd.getSecurityGroupIdList() != null && !cmd.getSecurityGroupIdList().isEmpty()) { |
| 8847 | + throw new InvalidParameterValueException("Can't create vm with security groups; security group feature is not enabled per zone"); |
| 8848 | + } |
| 8849 | + vm = createAdvancedVirtualMachine(zone, serviceOffering, template, networkIds, owner, name, displayName, diskOfferingId, size, null, |
| 8850 | + cmd.getHypervisor(), cmd.getHttpMethod(), null, null, null, sshKeyPairs, cmd.getIpToNetworkMap(), addrs, null, null, cmd.getAffinityGroupIdList(), cmd.getDetails(), |
| 8851 | + cmd.getCustomId(), cmd.getDhcpOptionsMap(), dataDiskTemplateToDiskOfferingMap, userVmOVFProperties, false, null, overrideDiskOfferingId); |
| 8852 | + } |
| 8853 | + } |
| 8854 | + |
| 8855 | + return vm; |
| 8856 | + } |
| 8857 | + |
| 8858 | + @Override |
| 8859 | + public UserVm restoreVMFromBackup(CreateVMFromBackupCmd cmd) throws ResourceUnavailableException, InsufficientCapacityException, ResourceAllocationException { |
| 8860 | + long vmId = cmd.getEntityId(); |
| 8861 | + Map<Long, DiskOffering> diskOfferingMap = cmd.getDataDiskTemplateToDiskOfferingMap(); |
| 8862 | + Map<VirtualMachineProfile.Param, Object> additonalParams = new HashMap<>(); |
| 8863 | + UserVm vm; |
| 8864 | + try { |
| 8865 | + vm = startVirtualMachine(vmId, null, null, null, diskOfferingMap, additonalParams, null); |
| 8866 | + } catch (ResourceUnavailableException e) { |
| 8867 | + throw new CloudRuntimeException("Unable to start the instance " + e); |
| 8868 | + } |
| 8869 | + boolean status = false; |
| 8870 | + try { |
| 8871 | + VirtualMachineEntity vmEntity = _orchSrvc.getVirtualMachine(vm.getUuid()); |
| 8872 | + status = vmEntity.stop(Long.toString(CallContext.current().getCallingUserId())); |
| 8873 | + if (!status) { |
| 8874 | + // todo : error handling |
| 8875 | + } |
| 8876 | + } catch (ResourceUnavailableException e) { |
| 8877 | + throw new CloudRuntimeException("Unable to contact the agent to stop the instance before restore " + e); |
| 8878 | + // todo : error handling |
| 8879 | + } catch (CloudException e) { |
| 8880 | + throw new CloudRuntimeException("Unable to contact the agent to stop the instance before restore " + e); |
| 8881 | + // todo : error handling |
| 8882 | + } |
| 8883 | + |
| 8884 | + backupManager.restoreBackupToVM(cmd.getBackupId(), vmId); |
| 8885 | + |
| 8886 | + if (cmd.getStartVm()) { |
| 8887 | + try { |
| 8888 | + vm = startVirtualMachine(vmId, null, null, null, diskOfferingMap, additonalParams, null); |
| 8889 | + } catch (ResourceUnavailableException e) { |
| 8890 | + throw new CloudRuntimeException("Unable to start the instance " + e); |
| 8891 | + } |
| 8892 | + } |
| 8893 | + return vm; |
| 8894 | + } |
| 8895 | + |
8728 | 8896 | /* |
8729 | 8897 | Generate usage events related to unmanaging a VM |
8730 | 8898 | */ |
|
0 commit comments