Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create new Instance from VM backup #10140

Draft
wants to merge 44 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 37 commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
35ed72c
Initial api and service layer changes
abh1sar Dec 25, 2024
e094e14
Nas backup provider changes
abh1sar Dec 25, 2024
27feeda
Add hypervisor, service_offering and template to backups table.
abh1sar Dec 30, 2024
f98da37
Create backup_details table and add details related to vm.
abh1sar Jan 1, 2025
04a2deb
Initial UI form
abh1sar Jan 2, 2025
d3439ad
Save networkIds and diskOfferingIds in backup_details. Create require…
abh1sar Jan 3, 2025
753d80f
Restore backup to VM plugin change for VeeamBackupProvider
abh1sar Jan 5, 2025
72c943f
UI form updates
abh1sar Jan 6, 2025
7ae078e
Create instance from backup using just the backupid
abh1sar Jan 7, 2025
31f89df
Remove zone and iso from DeployVMFromBackup.vue
abh1sar Jan 7, 2025
7e3f083
Create multiple data volumes using the deployVirtualMachine Api
abh1sar Jan 9, 2025
f46fad8
Create multiple data volumes for createVMFromBackup api and ui
abh1sar Jan 9, 2025
d941809
Merge remote-tracking branch 'upstream/main' into instance
abh1sar Jan 9, 2025
10f7beb
Fix build failure after merge
abh1sar Jan 9, 2025
edbdd01
setup ssh key pair again after restore
abh1sar Jan 10, 2025
f004264
added miniops and maxiops customisation in ui
abh1sar Jan 10, 2025
b1a86b8
added UT for backupManager and UserVmManager
abh1sar Jan 12, 2025
3b317e0
Minor ui fixes and null checks
abh1sar Jan 13, 2025
cfc9c6f
Remove import vm from restorebackuptoinstance
abh1sar Jan 14, 2025
8717e3a
set willDeleteBackupsOnOfferingRemoval to false for dummy and veeam. …
abh1sar Jan 14, 2025
f4f0655
Preserve device Ids of data volumes in the new instance.
abh1sar Jan 14, 2025
07f24cb
Throw exception if diskOffering stored in the backup is not present.
abh1sar Jan 14, 2025
38ad9be
Limit the volume size of new instance to minimum of backup volume size
abh1sar Jan 14, 2025
c2db7af
diskofferingid not supported by createVmFromBackup
abh1sar Jan 14, 2025
50aae80
remove userdata from ui form
abh1sar Jan 14, 2025
963437d
Remove console logs from ui forms
abh1sar Jan 14, 2025
300d096
fix UT failures in BackupManagerTest and UserVmManagerImplTest
abh1sar Jan 15, 2025
3c3885c
Merge branch 'main' into instance-from-backup
abh1sar Jan 15, 2025
0bea21f
Peserve override disk offering from backup
abh1sar Jan 16, 2025
129cb85
Merge branch 'instance-from-backup' of https://github.com/shapeblue/c…
abh1sar Jan 16, 2025
723537b
Merge remote-tracking branch 'upstream/main' into instance
abh1sar Jan 16, 2025
683aebe
Fix ut issue on merge
abh1sar Jan 16, 2025
5992a1e
Addressed minor review comments
abh1sar Jan 16, 2025
2da38da
Merge remote-tracking branch 'upstream/main' into instance
abh1sar Jan 16, 2025
5ab6c4a
Fix spelling errors.
abh1sar Jan 16, 2025
26d26d8
added more Unit Tests
abh1sar Jan 19, 2025
0cebdae
Merge branch 'main' into instance-from-backup
abh1sar Jan 19, 2025
7c600c7
Return diskofferingid for compute only diskoffering as well in servic…
abh1sar Jan 28, 2025
ac96d06
minor ui fixes
abh1sar Jan 28, 2025
08d4581
Handle inactive disk offering edge case
abh1sar Jan 28, 2025
735c379
Merge remote-tracking branch 'upstream/main' into instance
abh1sar Jan 28, 2025
675fc8d
backupvmdetails will be shown in listbackupsresponse only if listvmde…
abh1sar Feb 5, 2025
b708397
Merge remote-tracking branch 'upstream/main' into instance
abh1sar Feb 5, 2025
4d2e444
remove extra line from schema-42010to42100.sql
abh1sar Feb 5, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions api/src/main/java/com/cloud/event/EventTypes.java
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,7 @@ public class EventTypes {
public static final String EVENT_VM_BACKUP_OFFERING_REMOVE = "BACKUP.OFFERING.REMOVE";
public static final String EVENT_VM_BACKUP_CREATE = "BACKUP.CREATE";
public static final String EVENT_VM_BACKUP_RESTORE = "BACKUP.RESTORE";
public static final String EVENT_VM_BACKUP_RESTORE_TO_VM = "BACKUP.RESTORE.TO.VM";
public static final String EVENT_VM_BACKUP_DELETE = "BACKUP.DELETE";
public static final String EVENT_VM_BACKUP_RESTORE_VOLUME_TO_VM = "BACKUP.RESTORE.VOLUME.TO.VM";
public static final String EVENT_VM_BACKUP_SCHEDULE_CONFIGURE = "BACKUP.SCHEDULE.CONFIGURE";
Expand Down
21 changes: 21 additions & 0 deletions api/src/main/java/com/cloud/offering/DiskOfferingInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
private Long _size;
private Long _minIops;
private Long _maxIops;
private Long _deviceId;

public DiskOfferingInfo() {
}
Expand All @@ -31,6 +32,18 @@
_diskOffering = diskOffering;
}

public DiskOfferingInfo(DiskOffering diskOffering, Long size, Long minIops, Long maxIops) {
_diskOffering = diskOffering;
_size = size;
_minIops = minIops;
_maxIops = maxIops;
}

public DiskOfferingInfo(DiskOffering diskOffering, Long size, Long minIops, Long maxIops, Long deviceId) {
this(diskOffering, size, minIops, maxIops);
_deviceId = deviceId;
}

public void setDiskOffering(DiskOffering diskOffering) {
_diskOffering = diskOffering;
}
Expand Down Expand Up @@ -62,4 +75,12 @@
public Long getMaxIops() {
return _maxIops;
}

public void setDeviceId(Long deviceId) {
_deviceId = deviceId;
}

Check warning on line 81 in api/src/main/java/com/cloud/offering/DiskOfferingInfo.java

View check run for this annotation

Codecov / codecov/patch

api/src/main/java/com/cloud/offering/DiskOfferingInfo.java#L79-L81

Added lines #L79 - L81 were not covered by tests

public Long getDeviceId() {

Check warning on line 83 in api/src/main/java/com/cloud/offering/DiskOfferingInfo.java

View check run for this annotation

Codecov / codecov/patch

api/src/main/java/com/cloud/offering/DiskOfferingInfo.java#L83

Added line #L83 was not covered by tests
return _deviceId;
}

Check warning on line 85 in api/src/main/java/com/cloud/offering/DiskOfferingInfo.java

View check run for this annotation

Codecov / codecov/patch

api/src/main/java/com/cloud/offering/DiskOfferingInfo.java#L85

Added line #L85 was not covered by tests
}
15 changes: 10 additions & 5 deletions api/src/main/java/com/cloud/vm/UserVmService.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import org.apache.cloudstack.api.command.admin.vm.AssignVMCmd;
import org.apache.cloudstack.api.command.admin.vm.RecoverVMCmd;
import org.apache.cloudstack.api.command.user.vm.AddNicToVMCmd;
import org.apache.cloudstack.api.command.user.vm.CreateVMFromBackupCmd;
import org.apache.cloudstack.api.command.user.vm.DeployVMCmd;
import org.apache.cloudstack.api.command.user.vm.DestroyVMCmd;
import org.apache.cloudstack.api.command.user.vm.RebootVMCmd;
Expand Down Expand Up @@ -55,6 +56,7 @@
import com.cloud.hypervisor.Hypervisor.HypervisorType;
import com.cloud.network.Network.IpAddresses;
import com.cloud.offering.DiskOffering;
import com.cloud.offering.DiskOfferingInfo;
import com.cloud.offering.ServiceOffering;
import com.cloud.storage.StoragePool;
import com.cloud.template.VirtualMachineTemplate;
Expand Down Expand Up @@ -217,7 +219,7 @@ void startVirtualMachineForHA(VirtualMachine vm, Map<VirtualMachineProfile.Param
* available.
*/
UserVm createBasicSecurityGroupVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List<Long> securityGroupIdList,
Account owner, String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, HTTPMethod httpmethod,
Account owner, String hostName, String displayName, Long diskOfferingId, Long diskSize, List<DiskOfferingInfo> dataDiskOfferingsInfo, String group, HypervisorType hypervisor, HTTPMethod httpmethod,
String userData, Long userDataId, String userDataDetails, List<String> sshKeyPairs, Map<Long, IpAddresses> requestedIps, IpAddresses defaultIp, Boolean displayVm, String keyboard,
List<Long> affinityGroupIdList, Map<String, String> customParameter, String customId, Map<String, Map<Integer, String>> dhcpOptionMap,
Map<Long, DiskOffering> dataDiskTemplateToDiskOfferingMap,
Expand Down Expand Up @@ -294,7 +296,7 @@ UserVm createBasicSecurityGroupVirtualMachine(DataCenter zone, ServiceOffering s
* available.
*/
UserVm createAdvancedSecurityGroupVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List<Long> networkIdList,
List<Long> securityGroupIdList, Account owner, String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor,
List<Long> securityGroupIdList, Account owner, String hostName, String displayName, Long diskOfferingId, Long diskSize, List<DiskOfferingInfo> dataDiskOfferingsInfo, String group, HypervisorType hypervisor,
HTTPMethod httpmethod, String userData, Long userDataId, String userDataDetails, List<String> sshKeyPairs, Map<Long, IpAddresses> requestedIps, IpAddresses defaultIps, Boolean displayVm, String keyboard,
List<Long> affinityGroupIdList, Map<String, String> customParameters, String customId, Map<String, Map<Integer, String>> dhcpOptionMap,
Map<Long, DiskOffering> dataDiskTemplateToDiskOfferingMap, Map<String, String> userVmOVFProperties, boolean dynamicScalingEnabled, Long overrideDiskOfferingId, String vmType) throws InsufficientCapacityException, ConcurrentOperationException, ResourceUnavailableException, StorageUnavailableException, ResourceAllocationException;
Expand Down Expand Up @@ -366,7 +368,7 @@ UserVm createAdvancedSecurityGroupVirtualMachine(DataCenter zone, ServiceOfferin
* available.
*/
UserVm createAdvancedVirtualMachine(DataCenter zone, ServiceOffering serviceOffering, VirtualMachineTemplate template, List<Long> networkIdList, Account owner,
String hostName, String displayName, Long diskOfferingId, Long diskSize, String group, HypervisorType hypervisor, HTTPMethod httpmethod, String userData,
String hostName, String displayName, Long diskOfferingId, Long diskSize, List<DiskOfferingInfo> dataDiskOfferingsInfo, String group, HypervisorType hypervisor, HTTPMethod httpmethod, String userData,
Long userDataId, String userDataDetails, List<String> sshKeyPairs, Map<Long, IpAddresses> requestedIps, IpAddresses defaultIps, Boolean displayVm, String keyboard, List<Long> affinityGroupIdList,
Map<String, String> customParameters, String customId, Map<String, Map<Integer, String>> dhcpOptionMap, Map<Long, DiskOffering> dataDiskTemplateToDiskOfferingMap,
Map<String, String> templateOvfPropertiesMap, boolean dynamicScalingEnabled, String vmType, Long overrideDiskOfferingId)
Expand Down Expand Up @@ -412,8 +414,7 @@ UserVm createAdvancedVirtualMachine(DataCenter zone, ServiceOffering serviceOffe
void deletePrivateTemplateRecord(Long templateId);

HypervisorType getHypervisorTypeOfUserVM(long vmid);

UserVm createVirtualMachine(DeployVMCmd cmd) throws InsufficientCapacityException, ResourceUnavailableException, ConcurrentOperationException,
UserVm createVirtualMachine(DeployVMCmd cmd) throws InsufficientCapacityException, ResourceUnavailableException, ConcurrentOperationException,
StorageUnavailableException, ResourceAllocationException;

/**
Expand Down Expand Up @@ -513,4 +514,8 @@ UserVm importVM(final DataCenter zone, final Host host, final VirtualMachineTemp
* @return true if the VM is successfully unmanaged, false if not.
*/
boolean unmanageUserVM(Long vmId);

UserVm allocateVMFromBackup(CreateVMFromBackupCmd cmd) throws InsufficientCapacityException, ResourceAllocationException, ResourceUnavailableException;

UserVm restoreVMFromBackup(CreateVMFromBackupCmd cmd) throws ResourceUnavailableException, InsufficientCapacityException, ResourceAllocationException;
}
5 changes: 5 additions & 0 deletions api/src/main/java/org/apache/cloudstack/api/ApiConstants.java
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ public class ApiConstants {
public static final String MAX_IOPS = "maxiops";
public static final String HYPERVISOR_SNAPSHOT_RESERVE = "hypervisorsnapshotreserve";
public static final String DATACENTER_NAME = "datacentername";
public static final String DATADISKS_DETAILS = "datadisksdetails";
public static final String DATADISK_OFFERING_LIST = "datadiskofferinglist";
public static final String DEFAULT_VALUE = "defaultvalue";
public static final String DELETE_PROTECTION = "deleteprotection";
Expand All @@ -145,6 +146,7 @@ public class ApiConstants {
public static final String DESTINATION_ZONE_ID = "destzoneid";
public static final String DETAILS = "details";
public static final String DEVICE_ID = "deviceid";
public static final String DEVICE_IDS = "deviceids";
public static final String DIRECT_DOWNLOAD = "directdownload";
public static final String DISK = "disk";
public static final String DISK_OFFERING_ID = "diskofferingid";
Expand All @@ -156,7 +158,9 @@ public class ApiConstants {
public static final String DISK_IO_WRITE = "diskiowrite";
public static final String DISK_IO_PSTOTAL = "diskiopstotal";
public static final String DISK_SIZE = "disksize";
public static final String DISK_SIZES = "disksizes";
public static final String DISK_SIZE_STRICTNESS = "disksizestrictness";
public static final String DISK_OFFERING_IDS = "diskofferingids";
public static final String DISK_OFFERING_STRICTNESS = "diskofferingstrictness";
public static final String DOWNLOAD_DETAILS = "downloaddetails";
public static final String UTILIZATION = "utilization";
Expand Down Expand Up @@ -552,6 +556,7 @@ public class ApiConstants {
public static final String IS_DEDICATED = "isdedicated";
public static final String TAKEN = "taken";
public static final String VM_AVAILABLE = "vmavailable";
public static final String VM_DETAILS = "vmdetails";
public static final String VM_LIMIT = "vmlimit";
public static final String VM_TOTAL = "vmtotal";
public static final String VM_TYPE = "vmtype";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package org.apache.cloudstack.api.command.user.vm;

import javax.inject.Inject;

import org.apache.cloudstack.acl.RoleType;
import org.apache.cloudstack.api.APICommand;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ApiErrorCode;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ResponseObject;
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.command.user.UserCmd;
import org.apache.cloudstack.api.response.BackupResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
import org.apache.cloudstack.backup.BackupManager;

import com.cloud.exception.ConcurrentOperationException;
import com.cloud.exception.InsufficientCapacityException;
import com.cloud.exception.InsufficientServerCapacityException;
import com.cloud.exception.ResourceAllocationException;
import com.cloud.exception.ResourceUnavailableException;
import com.cloud.uservm.UserVm;
import com.cloud.vm.VirtualMachine;

@APICommand(name = "createVMFromBackup",
description = "Creates and automatically starts a VM from a backup.",
responseObject = UserVmResponse.class,
responseView = ResponseObject.ResponseView.Restricted,
entityType = {VirtualMachine.class},
requestHasSensitiveInfo = false, responseHasSensitiveInfo = true,
since = "4.21.0",
authorized = {RoleType.Admin, RoleType.ResourceAdmin, RoleType.DomainAdmin, RoleType.User})

public class CreateVMFromBackupCmd extends DeployVMCmd implements UserCmd {

@Inject
BackupManager backupManager;

@Parameter(name = ApiConstants.BACKUP_ID,
type = CommandType.UUID,
entityType = BackupResponse.class,
required = true,
description = "backup ID to create the VM from")
private Long backupId;

public Long getBackupId() {

Check warning on line 62 in api/src/main/java/org/apache/cloudstack/api/command/user/vm/CreateVMFromBackupCmd.java

View check run for this annotation

Codecov / codecov/patch

api/src/main/java/org/apache/cloudstack/api/command/user/vm/CreateVMFromBackupCmd.java#L62

Added line #L62 was not covered by tests
return backupId;
}

Check warning on line 64 in api/src/main/java/org/apache/cloudstack/api/command/user/vm/CreateVMFromBackupCmd.java

View check run for this annotation

Codecov / codecov/patch

api/src/main/java/org/apache/cloudstack/api/command/user/vm/CreateVMFromBackupCmd.java#L64

Added line #L64 was not covered by tests

@Override
public void create() {
UserVm vm;
try {
vm = _userVmService.allocateVMFromBackup(this);

Check warning on line 70 in api/src/main/java/org/apache/cloudstack/api/command/user/vm/CreateVMFromBackupCmd.java

View check run for this annotation

Codecov / codecov/patch

api/src/main/java/org/apache/cloudstack/api/command/user/vm/CreateVMFromBackupCmd.java#L67-L70

Added lines #L67 - L70 were not covered by tests
if (vm != null) {
setEntityId(vm.getId());
setEntityUuid(vm.getUuid());

Check warning on line 73 in api/src/main/java/org/apache/cloudstack/api/command/user/vm/CreateVMFromBackupCmd.java

View check run for this annotation

Codecov / codecov/patch

api/src/main/java/org/apache/cloudstack/api/command/user/vm/CreateVMFromBackupCmd.java#L72-L73

Added lines #L72 - L73 were not covered by tests
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to deploy vm");

Check warning on line 75 in api/src/main/java/org/apache/cloudstack/api/command/user/vm/CreateVMFromBackupCmd.java

View check run for this annotation

Codecov / codecov/patch

api/src/main/java/org/apache/cloudstack/api/command/user/vm/CreateVMFromBackupCmd.java#L75

Added line #L75 was not covered by tests
}
} catch (InsufficientCapacityException ex) {
logger.info(ex);
logger.trace(ex.getMessage(), ex);
throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, ex.getMessage());
} catch (ResourceUnavailableException ex) {
logger.warn("Exception: ", ex);
throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage());
} catch (ConcurrentOperationException ex) {
logger.warn("Exception: ", ex);
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage());
} catch (ResourceAllocationException ex) {
logger.warn("Exception: ", ex);
throw new ServerApiException(ApiErrorCode.RESOURCE_ALLOCATION_ERROR, ex.getMessage());
}
}

Check warning on line 91 in api/src/main/java/org/apache/cloudstack/api/command/user/vm/CreateVMFromBackupCmd.java

View check run for this annotation

Codecov / codecov/patch

api/src/main/java/org/apache/cloudstack/api/command/user/vm/CreateVMFromBackupCmd.java#L77-L91

Added lines #L77 - L91 were not covered by tests

@Override
public void execute () {
UserVm vm = null;
try {
vm = _userVmService.restoreVMFromBackup(this);
} catch (ResourceUnavailableException ex) {
logger.warn("Exception: ", ex);
throw new ServerApiException(ApiErrorCode.RESOURCE_UNAVAILABLE_ERROR, ex.getMessage());
} catch (ResourceAllocationException ex) {
logger.warn("Exception: ", ex);
throw new ServerApiException(ApiErrorCode.RESOURCE_ALLOCATION_ERROR, ex.getMessage());
} catch (ConcurrentOperationException ex) {
logger.warn("Exception: ", ex);
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, ex.getMessage());
} catch (InsufficientCapacityException ex) {
StringBuilder message = new StringBuilder(ex.getMessage());

Check warning on line 108 in api/src/main/java/org/apache/cloudstack/api/command/user/vm/CreateVMFromBackupCmd.java

View check run for this annotation

Codecov / codecov/patch

api/src/main/java/org/apache/cloudstack/api/command/user/vm/CreateVMFromBackupCmd.java#L94-L108

Added lines #L94 - L108 were not covered by tests
if (ex instanceof InsufficientServerCapacityException) {
if (((InsufficientServerCapacityException)ex).isAffinityApplied()) {
message.append(", Please check the affinity groups provided, there may not be sufficient capacity to follow them");

Check warning on line 111 in api/src/main/java/org/apache/cloudstack/api/command/user/vm/CreateVMFromBackupCmd.java

View check run for this annotation

Codecov / codecov/patch

api/src/main/java/org/apache/cloudstack/api/command/user/vm/CreateVMFromBackupCmd.java#L111

Added line #L111 was not covered by tests
}
}
logger.info(String.format("%s: %s", message.toString(), ex.getLocalizedMessage()));
logger.debug(message.toString(), ex);
throw new ServerApiException(ApiErrorCode.INSUFFICIENT_CAPACITY_ERROR, message.toString());
}

Check warning on line 117 in api/src/main/java/org/apache/cloudstack/api/command/user/vm/CreateVMFromBackupCmd.java

View check run for this annotation

Codecov / codecov/patch

api/src/main/java/org/apache/cloudstack/api/command/user/vm/CreateVMFromBackupCmd.java#L114-L117

Added lines #L114 - L117 were not covered by tests

if (vm != null) {
UserVmResponse response = _responseGenerator.createUserVmResponse(getResponseView(), "virtualmachine", vm).get(0);
response.setResponseName(getCommandName());
setResponseObject(response);
} else {
throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to deploy vm uuid:"+getEntityUuid());

Check warning on line 124 in api/src/main/java/org/apache/cloudstack/api/command/user/vm/CreateVMFromBackupCmd.java

View check run for this annotation

Codecov / codecov/patch

api/src/main/java/org/apache/cloudstack/api/command/user/vm/CreateVMFromBackupCmd.java#L120-L124

Added lines #L120 - L124 were not covered by tests
}
}

Check warning on line 126 in api/src/main/java/org/apache/cloudstack/api/command/user/vm/CreateVMFromBackupCmd.java

View check run for this annotation

Codecov / codecov/patch

api/src/main/java/org/apache/cloudstack/api/command/user/vm/CreateVMFromBackupCmd.java#L126

Added line #L126 was not covered by tests
}
Loading
Loading