From 75c67993696815f20e4c0bea0ede87bd6d331f06 Mon Sep 17 00:00:00 2001
From: JS Choi <77760789+jschoiRR@users.noreply.github.com>
Date: Fri, 9 Jan 2026 13:33:59 +0900
Subject: [PATCH 01/34] =?UTF-8?q?=EB=8B=A4=ED=81=AC=EB=AA=A8=EB=93=9C=20?=
=?UTF-8?q?=EC=88=98=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
ui/src/style/dark-mode.less | 23 +++++++++++++++--------
1 file changed, 15 insertions(+), 8 deletions(-)
diff --git a/ui/src/style/dark-mode.less b/ui/src/style/dark-mode.less
index 15462a3ef08a..ce5dc4b48683 100644
--- a/ui/src/style/dark-mode.less
+++ b/ui/src/style/dark-mode.less
@@ -1135,10 +1135,10 @@
.quickview-context-menu,
.autogen-action-dropdown__content {
- background: @dropdown-bgColor;
- border-color: @dark-border-color;
- box-shadow: 0 8px 24px @box-shadow-1;
- color: @dark-text-color-4;
+ background: @dropdown-bgColor !important;
+ border-color: @dark-border-color !important;
+ box-shadow: 0 8px 24px @box-shadow-1 !important;
+ color: @dark-text-color-4 !important;
}
.quickview-context-menu .action-button-title,
@@ -1163,10 +1163,17 @@
background: rgba(0, 0, 0, 0.50)
}
- .field-key,
- .banner-label,
- .banner-main {
+ .auto-alert-banner-container .banner-field {
+ background: rgba(0, 0, 0, 0.85);
+ }
+
+ .banner-main,
+ .field-key {
+ color: #cfc9c9;
+ }
+
+ .banner-label {
color: #cfc9c9;
- background-color: rgb(150 96 96 / 50%);
+ background-color: rgba(150, 96, 96, 0.5);
}
}
From c38e580ebd778b8c6fb60467bdc7eeafcd7182e8 Mon Sep 17 00:00:00 2001
From: JS Choi <77760789+jschoiRR@users.noreply.github.com>
Date: Tue, 13 Jan 2026 14:59:48 +0900
Subject: [PATCH 02/34] =?UTF-8?q?=EA=B0=80=EC=83=81=EB=A8=B8=EC=8B=A0=20?=
=?UTF-8?q?=EB=AA=A9=EB=A1=9D=EC=9D=98=20=EB=94=94=EC=8A=A4=ED=94=8C?=
=?UTF-8?q?=EB=A0=88=EC=9D=B4=EB=AA=85(=ED=91=9C=EC=8B=9C=20=EC=9D=B4?=
=?UTF-8?q?=EB=A6=84)=20=ED=95=AD=EB=AA=A9=20=EC=B6=94=EA=B0=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
ui/public/locales/ko_KR.json | 6 +++---
ui/src/config/section/compute.js | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/ui/public/locales/ko_KR.json b/ui/public/locales/ko_KR.json
index 8c8acbac78bd..3f6977000bfb 100644
--- a/ui/public/locales/ko_KR.json
+++ b/ui/public/locales/ko_KR.json
@@ -856,8 +856,8 @@
"label.disksizeused": "\uc0ac\uc6a9\ub41c \ub514\uc2a4\ud06c \ud06c\uae30",
"label.disksizeusedgb": "\uc0ac\uc6a9\ub41c",
"label.display.text": "\ud14d\uc2a4\ud2b8 \ud45c\uc2dc",
-"label.displayname": "\uc774\ub984 \ud45c\uc2dc",
-"label.displaynetwork": "\ub124\ud2b8\uc6cc\ud06c \uc774\ub984 \ud45c\uc2dc",
+"label.displayname": "\ud45c\uc2dc \uc774\ub984",
+"label.displaynetwork": "\ub124\ud2b8\uc6cc\ud06c \ud45c\uc2dc \uc774\ub984",
"label.displaytext": "\uc124\uba85",
"label.distributedvpcrouter": "\ubd84\uc0b0 VPC \ub77c\uc6b0\ud130",
"label.dns": "DNS",
@@ -3517,7 +3517,7 @@
"message.resource.not.found": "\ub9ac\uc18c\uc2a4\ub97c \ucc3e\uc744 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4.",
"message.restart.mgmt.server": "\uc0c8\ub85c\uc6b4 \uc124\uc815\uc744 \uc0ac\uc6a9 \ud558\uae30 \uc704\ud574 \uad00\ub9ac \uc11c\ubc84\ub97c \uc7ac\uc2dc\uc791\ud574 \uc8fc\uc2ed\uc2dc\uc624.",
"message.restart.network": "\ud604\uc7ac \ub124\ud2b8\uc6cc\ud06c\ub85c \uc81c\uacf5\ud558\ub294 \ubaa8\ub4e0 \uc11c\ube44\uc2a4\uac00 \uc911\ub2e8\ub429\ub2c8\ub2e4. \uc774 \ub124\ud2b8\uc6cc\ud06c\ub97c \uc7ac\uc2dc\uc791\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c?",
-"message.restart.vm.to.update.settings": "\uc774\ub984 \ubc0f \uc774\ub984 \ud45c\uc2dc \uc774\uc678\uc758 \ud56d\ubaa9\uc744 \uc5c5\ub370\uc774\ud2b8\ud558\ub824\uba74 VM\uc744 \ub2e4\uc2dc \uc2dc\uc791\ud574\uc57c \ud569\ub2c8\ub2e4.",
+"message.restart.vm.to.update.settings": "\uc774\ub984 \ubc0f \ud45c\uc2dc \uc774\ub984 \uc774\uc678\uc758 \ud56d\ubaa9\uc744 \uc5c5\ub370\uc774\ud2b8\ud558\ub824\uba74 VM\uc744 \ub2e4\uc2dc \uc2dc\uc791\ud574\uc57c \ud569\ub2c8\ub2e4.",
"message.restart.vpc": "VPC\ub97c \uc7ac\uc2dc\uc791\ud558\uc2dc\uaca0\uc2b5\ub2c8\uae4c?",
"message.restart.vpc.remark": "VPC\ub97c \ub2e4\uc2dc \uc2dc\uc791\ud560 \uac83\uc778\uc9c0 \ud655\uc778\ud558\uc2ed\uc2dc\uc624.
\ucc38\uace0 : \ube44 \uc911\ubcf5 VPC\ub97c \uc774\uc911\ud654\ud558\uba74 \uac15\uc81c\ub85c \uc815\ub9ac\ub429\ub2c8\ub2e4. \uba87 \ubd84 \ub3d9\uc548 \ub124\ud2b8\uc6cc\ud06c\ub97c \uc0ac\uc6a9\ud560 \uc218 \uc5c6\uc2b5\ub2c8\ub2e4 i>. small> p>",
"message.scale.processing": "\uc9c4\ud589\uc911",
diff --git a/ui/src/config/section/compute.js b/ui/src/config/section/compute.js
index 4eecbe3de076..597c86d52704 100644
--- a/ui/src/config/section/compute.js
+++ b/ui/src/config/section/compute.js
@@ -47,7 +47,7 @@ export default {
return filters
},
columns: () => {
- const fields = ['name', 'state', 'qemuagentversion', 'ipaddress']
+ const fields = ['name', 'displayname', 'state', 'qemuagentversion', 'ipaddress']
const metricsFields = ['cpunumber', 'cputotal', 'cpuused', 'memorytotal',
{
memoryused: (record) => {
From 34e8fce6bd6d44d08fcaae0110bf668c078bf228 Mon Sep 17 00:00:00 2001
From: JS Choi <77760789+jschoiRR@users.noreply.github.com>
Date: Fri, 16 Jan 2026 11:44:12 +0900
Subject: [PATCH 03/34] =?UTF-8?q?=EB=B9=8C=EB=93=9C=20=EC=98=A4=EB=A5=98?=
=?UTF-8?q?=20=EC=88=98=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
api/src/main/java/com/cloud/event/EventTypes.java | 2 +-
api/src/main/java/com/cloud/storage/VolumeApiService.java | 2 +-
.../java/org/apache/cloudstack/backup/BackupManagerImpl.java | 1 -
3 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/api/src/main/java/com/cloud/event/EventTypes.java b/api/src/main/java/com/cloud/event/EventTypes.java
index 97d889bebcfa..b9c8f0b55a6d 100644
--- a/api/src/main/java/com/cloud/event/EventTypes.java
+++ b/api/src/main/java/com/cloud/event/EventTypes.java
@@ -799,7 +799,7 @@ public class EventTypes {
// DISASTER RECOVERY
public static final String EVENT_DISASTER_RECOVERY_CLUSTER = "DISASTER.RECOVERY.CLUSTER";
-
+
// Resource Limit
public static final String EVENT_RESOURCE_LIMIT_UPDATE = "RESOURCE.LIMIT.UPDATE";
diff --git a/api/src/main/java/com/cloud/storage/VolumeApiService.java b/api/src/main/java/com/cloud/storage/VolumeApiService.java
index 1239d37af26d..0698c09e0887 100644
--- a/api/src/main/java/com/cloud/storage/VolumeApiService.java
+++ b/api/src/main/java/com/cloud/storage/VolumeApiService.java
@@ -197,6 +197,6 @@ Snapshot takeSnapshot(Long volumeId, Long policyId, Long snapshotId, Account acc
Volume cloneVolumeFromSnapshot(Volume volume, long snapshotId, Long vmId) throws StorageUnavailableException;
Volume updateCompressDedupVolume(UpdateCompressDedupCmd cmd);
-
+
Long getVolumePhysicalSize(Storage.ImageFormat format, String path, String chainInfo);
}
diff --git a/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java b/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java
index e41d218aeb97..92d673d801d5 100644
--- a/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java
+++ b/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java
@@ -72,7 +72,6 @@
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
import org.apache.cloudstack.framework.config.ConfigKey;
-import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.framework.jobs.AsyncJobDispatcher;
import org.apache.cloudstack.framework.jobs.AsyncJobManager;
import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO;
From 12808ee9d80f2ebdc5ddaf8f3fcd2cbba71205eb Mon Sep 17 00:00:00 2001
From: JS Choi <77760789+jschoiRR@users.noreply.github.com>
Date: Fri, 16 Jan 2026 11:54:05 +0900
Subject: [PATCH 04/34] =?UTF-8?q?=EB=B9=8C=EB=93=9C=EC=98=A4=EB=A5=98=20?=
=?UTF-8?q?=EC=88=98=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../src/main/java/com/cloud/utils/db/GenericDaoBase.java | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/framework/db/src/main/java/com/cloud/utils/db/GenericDaoBase.java b/framework/db/src/main/java/com/cloud/utils/db/GenericDaoBase.java
index c7f2daadc518..28e182a624c5 100644
--- a/framework/db/src/main/java/com/cloud/utils/db/GenericDaoBase.java
+++ b/framework/db/src/main/java/com/cloud/utils/db/GenericDaoBase.java
@@ -2445,4 +2445,12 @@ private Optional> getConverter(Field field) {
}
}
+ public static class SumCount {
+ public long sum;
+ public long count;
+
+ public SumCount() {
+ }
+ }
+
}
From c585cad88e07e4865c98935a2a24014c339ae0e8 Mon Sep 17 00:00:00 2001
From: Dajeong-Park
Date: Fri, 16 Jan 2026 12:20:31 +0900
Subject: [PATCH 05/34] =?UTF-8?q?=EB=B9=8C=EB=93=9C=EC=98=A4=EB=A5=98=20?=
=?UTF-8?q?=EC=A0=81=EC=9A=A9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
api/src/main/java/com/cloud/event/EventTypes.java | 2 +-
api/src/main/java/com/cloud/storage/VolumeApiService.java | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/api/src/main/java/com/cloud/event/EventTypes.java b/api/src/main/java/com/cloud/event/EventTypes.java
index 97d889bebcfa..b9c8f0b55a6d 100644
--- a/api/src/main/java/com/cloud/event/EventTypes.java
+++ b/api/src/main/java/com/cloud/event/EventTypes.java
@@ -799,7 +799,7 @@ public class EventTypes {
// DISASTER RECOVERY
public static final String EVENT_DISASTER_RECOVERY_CLUSTER = "DISASTER.RECOVERY.CLUSTER";
-
+
// Resource Limit
public static final String EVENT_RESOURCE_LIMIT_UPDATE = "RESOURCE.LIMIT.UPDATE";
diff --git a/api/src/main/java/com/cloud/storage/VolumeApiService.java b/api/src/main/java/com/cloud/storage/VolumeApiService.java
index 1239d37af26d..0698c09e0887 100644
--- a/api/src/main/java/com/cloud/storage/VolumeApiService.java
+++ b/api/src/main/java/com/cloud/storage/VolumeApiService.java
@@ -197,6 +197,6 @@ Snapshot takeSnapshot(Long volumeId, Long policyId, Long snapshotId, Account acc
Volume cloneVolumeFromSnapshot(Volume volume, long snapshotId, Long vmId) throws StorageUnavailableException;
Volume updateCompressDedupVolume(UpdateCompressDedupCmd cmd);
-
+
Long getVolumePhysicalSize(Storage.ImageFormat format, String path, String chainInfo);
}
From 3762f5405a19632c2fb2b1dd49a23256ae081434 Mon Sep 17 00:00:00 2001
From: Dajeong-Park
Date: Fri, 16 Jan 2026 12:21:59 +0900
Subject: [PATCH 06/34] Update BackupVO.java
---
.../src/main/java/org/apache/cloudstack/backup/BackupVO.java | 2 --
1 file changed, 2 deletions(-)
diff --git a/engine/schema/src/main/java/org/apache/cloudstack/backup/BackupVO.java b/engine/schema/src/main/java/org/apache/cloudstack/backup/BackupVO.java
index 81dd0fea68d3..ebe98b3dda53 100644
--- a/engine/schema/src/main/java/org/apache/cloudstack/backup/BackupVO.java
+++ b/engine/schema/src/main/java/org/apache/cloudstack/backup/BackupVO.java
@@ -22,12 +22,10 @@
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
import org.apache.commons.lang3.StringUtils;
-import java.beans.Transient;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
-import java.util.Map;
import java.util.UUID;
import javax.persistence.Column;
From 979c859e1289b646bafd630526eebb429c720afd Mon Sep 17 00:00:00 2001
From: Dajeong-Park
Date: Fri, 16 Jan 2026 12:57:42 +0900
Subject: [PATCH 07/34] =?UTF-8?q?=EB=B9=8C=EB=93=9C=EC=98=A4=EB=A5=98=20?=
=?UTF-8?q?=EC=88=98=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../main/java/com/cloud/storage/dao/BucketDaoImpl.java | 8 ++++++++
.../org/apache/cloudstack/backup/dao/BackupDaoImpl.java | 8 ++++++++
2 files changed, 16 insertions(+)
diff --git a/engine/schema/src/main/java/com/cloud/storage/dao/BucketDaoImpl.java b/engine/schema/src/main/java/com/cloud/storage/dao/BucketDaoImpl.java
index 473879d933dc..963bcd6cfe6b 100644
--- a/engine/schema/src/main/java/com/cloud/storage/dao/BucketDaoImpl.java
+++ b/engine/schema/src/main/java/com/cloud/storage/dao/BucketDaoImpl.java
@@ -114,4 +114,12 @@ public Long calculateObjectStorageAllocationForAccount(long accountId) {
Long totalQuota = customSearch(sc, null).get(0).sum;
return (totalQuota * Resource.ResourceType.bytesToGiB);
}
+
+ public static class SumCount {
+ public long sum;
+ public long count;
+
+ public SumCount() {
+ }
+ }
}
diff --git a/engine/schema/src/main/java/org/apache/cloudstack/backup/dao/BackupDaoImpl.java b/engine/schema/src/main/java/org/apache/cloudstack/backup/dao/BackupDaoImpl.java
index 3dbdb5abc828..674e8cf428e6 100644
--- a/engine/schema/src/main/java/org/apache/cloudstack/backup/dao/BackupDaoImpl.java
+++ b/engine/schema/src/main/java/org/apache/cloudstack/backup/dao/BackupDaoImpl.java
@@ -233,4 +233,12 @@ public BackupResponse newBackupResponse(Backup backup) {
response.setObjectName("backup");
return response;
}
+
+ public static class SumCount {
+ public long sum;
+ public long count;
+
+ public SumCount() {
+ }
+ }
}
From c51ebf288f6b27177e0f413206e6422c3bdc3b0f Mon Sep 17 00:00:00 2001
From: JS Choi <77760789+jschoiRR@users.noreply.github.com>
Date: Fri, 16 Jan 2026 13:00:10 +0900
Subject: [PATCH 08/34] =?UTF-8?q?=EB=B9=8C=EB=93=9C=20=EC=98=A4=EB=A5=98?=
=?UTF-8?q?=20=EC=88=98=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../user/backup/DeleteBackupScheduleCmd.java | 18 ++++---
.../cloudstack/backup/BackupManager.java | 7 +--
.../cloudstack/backup/BackupScheduleVO.java | 9 ++++
.../apache/cloudstack/backup/BackupVO.java | 2 -
.../cloud/storage/VolumeApiServiceImpl.java | 1 +
.../cloudstack/backup/BackupManagerImpl.java | 51 ++++++++++++++++---
.../cloudstack/backup/BackupManagerTest.java | 1 +
7 files changed, 71 insertions(+), 18 deletions(-)
diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/backup/DeleteBackupScheduleCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/backup/DeleteBackupScheduleCmd.java
index 0245f228b895..fa721ef5c98e 100644
--- a/api/src/main/java/org/apache/cloudstack/api/command/user/backup/DeleteBackupScheduleCmd.java
+++ b/api/src/main/java/org/apache/cloudstack/api/command/user/backup/DeleteBackupScheduleCmd.java
@@ -26,6 +26,7 @@
import org.apache.cloudstack.api.BaseCmd;
import org.apache.cloudstack.api.Parameter;
import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.response.BackupScheduleResponse;
import org.apache.cloudstack.api.response.SuccessResponse;
import org.apache.cloudstack.api.response.UserVmResponse;
import org.apache.cloudstack.backup.BackupManager;
@@ -51,13 +52,15 @@ public class DeleteBackupScheduleCmd extends BaseCmd {
//////////////// API parameters /////////////////////
/////////////////////////////////////////////////////
- @Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID,
- type = CommandType.UUID,
- entityType = UserVmResponse.class,
- required = true,
- description = "ID of the VM")
+ @Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID, type = CommandType.UUID, entityType = UserVmResponse.class,
+ description = "ID of the VM from which all backup schedules will be deleted.")
private Long vmId;
+ @Parameter(name = ApiConstants.ID, type = CommandType.UUID, entityType = BackupScheduleResponse.class,
+ since = "4.20.1", description = "ID of the backup schedule to be deleted. It has precedence over the 'virtualmachineid' parameter, " +
+ "i.e., when the 'id' parameter is specified, the 'virtualmachineid' parameter will be ignored.")
+ private Long id;
+
/////////////////////////////////////////////////////
/////////////////// Accessors ///////////////////////
/////////////////////////////////////////////////////
@@ -66,6 +69,9 @@ public Long getVmId() {
return vmId;
}
+ public Long getId() { return id; }
+
+
/////////////////////////////////////////////////////
/////////////// API Implementation///////////////////
/////////////////////////////////////////////////////
@@ -73,7 +79,7 @@ public Long getVmId() {
@Override
public void execute() throws ResourceUnavailableException, InsufficientCapacityException, ServerApiException, ConcurrentOperationException, ResourceAllocationException, NetworkRuleConflictException {
try {
- boolean result = backupManager.deleteBackupSchedule(getVmId());
+ boolean result = backupManager.deleteBackupSchedule(this);
if (result) {
SuccessResponse response = new SuccessResponse(getCommandName());
response.setResponseName(getCommandName());
diff --git a/api/src/main/java/org/apache/cloudstack/backup/BackupManager.java b/api/src/main/java/org/apache/cloudstack/backup/BackupManager.java
index cc99833c7ec1..4105406324e0 100644
--- a/api/src/main/java/org/apache/cloudstack/backup/BackupManager.java
+++ b/api/src/main/java/org/apache/cloudstack/backup/BackupManager.java
@@ -23,6 +23,7 @@
import org.apache.cloudstack.api.command.admin.backup.ImportBackupOfferingCmd;
import org.apache.cloudstack.api.command.admin.backup.UpdateBackupOfferingCmd;
import org.apache.cloudstack.api.command.user.backup.CreateBackupScheduleCmd;
+import org.apache.cloudstack.api.command.user.backup.DeleteBackupScheduleCmd;
import org.apache.cloudstack.api.command.user.backup.ListBackupOfferingsCmd;
import org.apache.cloudstack.api.command.user.backup.ListBackupsCmd;
import org.apache.cloudstack.framework.config.ConfigKey;
@@ -159,12 +160,12 @@ public interface BackupManager extends BackupService, Configurable, PluggableSer
*/
List listBackupSchedule(Long vmId);
- /**
+ /**
* Deletes VM backup schedule for a VM
- * @param vmId
+ * @param cmd
* @return
*/
- boolean deleteBackupSchedule(Long vmId);
+ boolean deleteBackupSchedule(DeleteBackupScheduleCmd cmd);
/**
* Creates backup of a VM
diff --git a/engine/schema/src/main/java/org/apache/cloudstack/backup/BackupScheduleVO.java b/engine/schema/src/main/java/org/apache/cloudstack/backup/BackupScheduleVO.java
index 0338d7f1c4e1..85573f5f207f 100644
--- a/engine/schema/src/main/java/org/apache/cloudstack/backup/BackupScheduleVO.java
+++ b/engine/schema/src/main/java/org/apache/cloudstack/backup/BackupScheduleVO.java
@@ -18,6 +18,7 @@
package org.apache.cloudstack.backup;
import java.util.Date;
+import java.util.UUID;
import javax.persistence.Column;
import javax.persistence.Entity;
@@ -42,6 +43,9 @@ public class BackupScheduleVO implements BackupSchedule {
@Column(name = "vm_id")
private Long vmId;
+ @Column(name = "uuid", nullable = false)
+ private String uuid = UUID.randomUUID().toString();
+
@Column(name = "schedule_type")
private Short scheduleType;
@@ -84,6 +88,11 @@ public long getId() {
return id;
}
+ @Override
+ public String getUuid() {
+ return uuid;
+ }
+
public Long getVmId() {
return vmId;
}
diff --git a/engine/schema/src/main/java/org/apache/cloudstack/backup/BackupVO.java b/engine/schema/src/main/java/org/apache/cloudstack/backup/BackupVO.java
index 81dd0fea68d3..ebe98b3dda53 100644
--- a/engine/schema/src/main/java/org/apache/cloudstack/backup/BackupVO.java
+++ b/engine/schema/src/main/java/org/apache/cloudstack/backup/BackupVO.java
@@ -22,12 +22,10 @@
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
import org.apache.commons.lang3.StringUtils;
-import java.beans.Transient;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
-import java.util.Map;
import java.util.UUID;
import javax.persistence.Column;
diff --git a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java
index 6d975e1809d4..4dbdb3cea3e2 100644
--- a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java
+++ b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java
@@ -136,6 +136,7 @@
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.Pod;
import com.cloud.dc.dao.DataCenterDao;
+import com.cloud.dc.dao.HostPodDao;
import com.cloud.domain.Domain;
import com.cloud.domain.dao.DomainDao;
import com.cloud.event.ActionEvent;
diff --git a/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java b/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java
index a0f12f9741a4..20cf7f3adcaf 100644
--- a/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java
+++ b/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java
@@ -33,7 +33,6 @@
import com.cloud.alert.AlertManager;
import com.cloud.configuration.Resource;
import com.cloud.exception.ResourceAllocationException;
-import com.cloud.storage.Snapshot;
import com.cloud.storage.VolumeApiService;
import com.cloud.user.DomainManager;
import com.cloud.user.ResourceLimitService;
@@ -86,6 +85,7 @@
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
import org.apache.commons.lang.math.NumberUtils;
import org.apache.commons.lang3.BooleanUtils;
+import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import com.cloud.api.ApiDispatcher;
@@ -588,16 +588,53 @@ public List listBackupSchedule(final Long vmId) {
@Override
@ActionEvent(eventType = EventTypes.EVENT_VM_BACKUP_SCHEDULE_DELETE, eventDescription = "deleting VM backup schedule")
- public boolean deleteBackupSchedule(Long vmId) {
- final VMInstanceVO vm = findVmById(vmId);
+ public boolean deleteBackupSchedule(DeleteBackupScheduleCmd cmd) {
+ Long vmId = cmd.getVmId();
+ Long id = cmd.getId();
+ if (ObjectUtils.allNull(vmId, id)) {
+ throw new InvalidParameterValueException("Either instance ID or ID of backup schedule needs to be specified.");
+ }
+
+ if (Objects.nonNull(id)) {
+ BackupSchedule schedule = backupScheduleDao.findById(id);
+ if (schedule == null) {
+ throw new InvalidParameterValueException("Could not find the requested backup schedule.");
+ }
+ checkCallerAccessToBackupScheduleVm(schedule.getVmId());
+ return backupScheduleDao.remove(schedule.getId());
+ }
+
+ checkCallerAccessToBackupScheduleVm(vmId);
+ return deleteAllVmBackupSchedules(vmId);
+ }
+
+ /**
+ * Checks if the backup framework is enabled for the zone in which the VM with specified ID is allocated and
+ * if the caller has access to the VM.
+ *
+ * @param vmId The ID of the virtual machine to check access for
+ * @throws PermissionDeniedException if the caller doesn't have access to the VM
+ * @throws CloudRuntimeException if the backup framework is disabled
+ */
+ protected void checkCallerAccessToBackupScheduleVm(long vmId) {
+ VMInstanceVO vm = findVmById(vmId);
validateForZone(vm.getDataCenterId());
accountManager.checkAccess(CallContext.current().getCallingAccount(), null, true, vm);
+ }
- final BackupSchedule schedule = backupScheduleDao.findByVM(vmId);
- if (schedule == null) {
- throw new CloudRuntimeException("VM has no backup schedule defined, no need to delete anything.");
+ /**
+ * Deletes all backup schedules associated with a specific VM.
+ *
+ * @param vmId The ID of the virtual machine whose backup schedules should be deleted
+ * @return true if all backup schedules were successfully deleted, false if any deletion failed
+ */
+ protected boolean deleteAllVmBackupSchedules(long vmId) {
+ List vmBackupSchedules = backupScheduleDao.listByVM(vmId);
+ boolean success = true;
+ for (BackupScheduleVO vmBackupSchedule : vmBackupSchedules) {
+ success = success && backupScheduleDao.remove(vmBackupSchedule.getId());
}
- return backupScheduleDao.remove(schedule.getId());
+ return success;
}
@Override
diff --git a/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java b/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java
index 66fa2d33cb1e..88892d982d87 100644
--- a/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java
+++ b/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java
@@ -49,6 +49,7 @@
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.command.admin.backup.UpdateBackupOfferingCmd;
import org.apache.cloudstack.api.command.user.backup.CreateBackupScheduleCmd;
+import org.apache.cloudstack.api.command.user.backup.DeleteBackupScheduleCmd;
import org.apache.cloudstack.backup.dao.BackupDao;
import org.apache.cloudstack.backup.dao.BackupOfferingDao;
import org.apache.cloudstack.backup.dao.BackupScheduleDao;
From b3c7a43dfcaf3410b87d7134e51dbfe90b4c3592 Mon Sep 17 00:00:00 2001
From: JS Choi <77760789+jschoiRR@users.noreply.github.com>
Date: Fri, 16 Jan 2026 13:04:59 +0900
Subject: [PATCH 09/34] =?UTF-8?q?=EB=B9=8C=EB=93=9C=20=EC=98=A4=EB=A5=98?=
=?UTF-8?q?=20=EC=88=98=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../java/org/apache/cloudstack/backup/BackupManagerImpl.java | 1 +
1 file changed, 1 insertion(+)
diff --git a/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java b/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java
index 20cf7f3adcaf..1177c1f9a0e3 100644
--- a/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java
+++ b/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java
@@ -24,6 +24,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Objects;
import java.util.TimeZone;
import java.util.Timer;
import java.util.TimerTask;
From 6470b65ef6a9af96ee28c3fdcb3eba7e29525b27 Mon Sep 17 00:00:00 2001
From: JS Choi <77760789+jschoiRR@users.noreply.github.com>
Date: Fri, 16 Jan 2026 13:25:08 +0900
Subject: [PATCH 10/34] =?UTF-8?q?=EB=B9=8C=EB=93=9C=EC=98=A4=EB=A5=98=20?=
=?UTF-8?q?=EC=88=98=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../apache/cloudstack/backup/NetworkerBackupProvider.java | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/plugins/backup/networker/src/main/java/org/apache/cloudstack/backup/NetworkerBackupProvider.java b/plugins/backup/networker/src/main/java/org/apache/cloudstack/backup/NetworkerBackupProvider.java
index b89d82be540d..191e6fe2d989 100644
--- a/plugins/backup/networker/src/main/java/org/apache/cloudstack/backup/NetworkerBackupProvider.java
+++ b/plugins/backup/networker/src/main/java/org/apache/cloudstack/backup/NetworkerBackupProvider.java
@@ -34,6 +34,8 @@
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.dao.VMInstanceDao;
+
+import org.apache.cloudstack.backup.Backup.Metric;
import org.apache.cloudstack.backup.dao.BackupDao;
import org.apache.cloudstack.backup.dao.BackupOfferingDaoImpl;
import org.apache.cloudstack.backup.networker.NetworkerClient;
@@ -624,4 +626,8 @@ public List listRestorePoints(VirtualMachine vm) {
@Override
public boolean updateBackupPlan(final Long zoneId, final String retentionPeriod, final String externalId) { return true; }
+
+ @Override
+ public void syncBackups(VirtualMachine vm, Metric metric) {
+ }
}
From 75b6f7b179fbdcec3322fc906fb0b675d82ff4be Mon Sep 17 00:00:00 2001
From: JS Choi <77760789+jschoiRR@users.noreply.github.com>
Date: Fri, 16 Jan 2026 13:33:44 +0900
Subject: [PATCH 11/34] =?UTF-8?q?=EB=B9=8C=EB=93=9C=20=EC=98=A4=EB=A5=98?=
=?UTF-8?q?=20=EC=88=98=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../java/org/apache/cloudstack/backup/NASBackupProvider.java | 4 ++++
.../org/apache/cloudstack/backup/NetworkerBackupProvider.java | 3 +--
.../org/apache/cloudstack/backup/VeeamBackupProvider.java | 4 ++++
3 files changed, 9 insertions(+), 2 deletions(-)
diff --git a/plugins/backup/nas/src/main/java/org/apache/cloudstack/backup/NASBackupProvider.java b/plugins/backup/nas/src/main/java/org/apache/cloudstack/backup/NASBackupProvider.java
index 1dd397bd7b3f..951bbeda4e9b 100644
--- a/plugins/backup/nas/src/main/java/org/apache/cloudstack/backup/NASBackupProvider.java
+++ b/plugins/backup/nas/src/main/java/org/apache/cloudstack/backup/NASBackupProvider.java
@@ -461,6 +461,10 @@ public String getConfigComponentName() {
return BackupService.class.getSimpleName();
}
+ @Override
+ public void syncBackups(VirtualMachine vm, Backup.Metric metric) {
+ }
+
@Override
public boolean checkBackupAgent(final Long zoneId) { return true; }
diff --git a/plugins/backup/networker/src/main/java/org/apache/cloudstack/backup/NetworkerBackupProvider.java b/plugins/backup/networker/src/main/java/org/apache/cloudstack/backup/NetworkerBackupProvider.java
index 191e6fe2d989..ae4beaa2c82e 100644
--- a/plugins/backup/networker/src/main/java/org/apache/cloudstack/backup/NetworkerBackupProvider.java
+++ b/plugins/backup/networker/src/main/java/org/apache/cloudstack/backup/NetworkerBackupProvider.java
@@ -35,7 +35,6 @@
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.dao.VMInstanceDao;
-import org.apache.cloudstack.backup.Backup.Metric;
import org.apache.cloudstack.backup.dao.BackupDao;
import org.apache.cloudstack.backup.dao.BackupOfferingDaoImpl;
import org.apache.cloudstack.backup.networker.NetworkerClient;
@@ -628,6 +627,6 @@ public List listRestorePoints(VirtualMachine vm) {
public boolean updateBackupPlan(final Long zoneId, final String retentionPeriod, final String externalId) { return true; }
@Override
- public void syncBackups(VirtualMachine vm, Metric metric) {
+ public void syncBackups(VirtualMachine vm, Backup.Metric metric) {
}
}
diff --git a/plugins/backup/veeam/src/main/java/org/apache/cloudstack/backup/VeeamBackupProvider.java b/plugins/backup/veeam/src/main/java/org/apache/cloudstack/backup/VeeamBackupProvider.java
index ed9aaa4c638f..e6aa5872aa63 100644
--- a/plugins/backup/veeam/src/main/java/org/apache/cloudstack/backup/VeeamBackupProvider.java
+++ b/plugins/backup/veeam/src/main/java/org/apache/cloudstack/backup/VeeamBackupProvider.java
@@ -370,6 +370,10 @@ public String getDescription() {
return "Veeam Backup Plugin";
}
+ @Override
+ public void syncBackups(VirtualMachine vm, Backup.Metric metric) {
+ }
+
@Override
public boolean checkBackupAgent(final Long zoneId) { return true; }
From 9d7c9b22bc76463115bcec1a22223519709bb823 Mon Sep 17 00:00:00 2001
From: JS Choi <77760789+jschoiRR@users.noreply.github.com>
Date: Fri, 16 Jan 2026 13:47:23 +0900
Subject: [PATCH 12/34] =?UTF-8?q?=EB=B9=8C=EB=93=9C=20=EC=98=A4=EB=A5=98?=
=?UTF-8?q?=20=EC=88=98=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../backup/CommvaultBackupProvider.java | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/plugins/backup/commvault/src/main/java/org/apache/cloudstack/backup/CommvaultBackupProvider.java b/plugins/backup/commvault/src/main/java/org/apache/cloudstack/backup/CommvaultBackupProvider.java
index c5878f575de5..85437c1fa8ae 100644
--- a/plugins/backup/commvault/src/main/java/org/apache/cloudstack/backup/CommvaultBackupProvider.java
+++ b/plugins/backup/commvault/src/main/java/org/apache/cloudstack/backup/CommvaultBackupProvider.java
@@ -763,7 +763,7 @@ public Pair restoreBackedUpVolume(Backup backup, String volumeU
}
@Override
- public boolean takeBackup(VirtualMachine vm) {
+ public Pair takeBackup(VirtualMachine vm) {
String hostName = null;
try {
String commvaultServer = getUrlDomain(CommvaultUrl.value());
@@ -821,7 +821,7 @@ public boolean takeBackup(VirtualMachine vm) {
}
}
LOG.error("Failed to request createSnapshot Mold-API.");
- return false;
+ return new Pair<>(false, null);
} else {
JSONObject jsonObject = new JSONObject(createSnapResult);
String jobId = jsonObject.get("jobid").toString();
@@ -843,7 +843,7 @@ public boolean takeBackup(VirtualMachine vm) {
}
}
LOG.error("createSnapshot Mold-API async job resulted in failure.");
- return false;
+ return new Pair<>(false, null);
}
checkResult.put(vol.getId(), snapId);
SnapshotDataStoreVO snapshotStore = snapshotStoreDao.findLatestSnapshotForVolume(vol.getId(), DataStoreRole.Primary);
@@ -1001,7 +1001,7 @@ public boolean takeBackup(VirtualMachine vm) {
command = String.format(RM_COMMAND, storagePath + "/" + vm.getInstanceName());
executeDeleteXmlCommand(hostVO, credentials.first(), credentials.second(), sshPort, command);
}
- return true;
+ return new Pair<>(true, backup);
} else {
// 백업 실패
if (!checkResult.isEmpty()) {
@@ -1018,7 +1018,7 @@ public boolean takeBackup(VirtualMachine vm) {
executeDeleteXmlCommand(hostVO, credentials.first(), credentials.second(), sshPort, command);
}
LOG.error("createBackup commvault api resulted in " + jobStatus);
- return false;
+ return new Pair<>(false, null);
}
} else {
// 백업 실패
@@ -1036,7 +1036,7 @@ public boolean takeBackup(VirtualMachine vm) {
executeDeleteXmlCommand(hostVO, credentials.first(), credentials.second(), sshPort, command);
}
LOG.error("createBackup commvault api resulted in " + jobStatus);
- return false;
+ return new Pair<>(false, null);
}
} else {
// 백업 실패
@@ -1054,7 +1054,7 @@ public boolean takeBackup(VirtualMachine vm) {
executeDeleteXmlCommand(hostVO, credentials.first(), credentials.second(), sshPort, command);
}
LOG.error("failed request createBackup commvault api");
- return false;
+ return new Pair<>(false, null);
}
} else {
// 백업 경로 업데이트 실패
@@ -1072,7 +1072,7 @@ public boolean takeBackup(VirtualMachine vm) {
executeDeleteXmlCommand(hostVO, credentials.first(), credentials.second(), sshPort, command);
}
LOG.error("updateBackupSet commvault api resulted in failure.");
- return false;
+ return new Pair<>(false, null);
}
}
From 674f697eae8253e4c32b0bb739eb15cbbf6c8235 Mon Sep 17 00:00:00 2001
From: JS Choi <77760789+jschoiRR@users.noreply.github.com>
Date: Fri, 16 Jan 2026 14:16:16 +0900
Subject: [PATCH 13/34] =?UTF-8?q?=EB=B9=8C=EB=93=9C=20=EC=98=A4=EB=A5=98?=
=?UTF-8?q?=20=EC=88=98=EC=A0=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../cloudstack/backup/CommvaultBackupProvider.java | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/plugins/backup/commvault/src/main/java/org/apache/cloudstack/backup/CommvaultBackupProvider.java b/plugins/backup/commvault/src/main/java/org/apache/cloudstack/backup/CommvaultBackupProvider.java
index 85437c1fa8ae..802d52d5861f 100644
--- a/plugins/backup/commvault/src/main/java/org/apache/cloudstack/backup/CommvaultBackupProvider.java
+++ b/plugins/backup/commvault/src/main/java/org/apache/cloudstack/backup/CommvaultBackupProvider.java
@@ -1559,4 +1559,16 @@ public static boolean versionCheck(String csVersionInfo) {
}
return true;
}
+
+ @Override
+ public List listRestorePoints(VirtualMachine vm) {
+ return null;
+ }
+
+
+ @Override
+ public Backup createNewBackupEntryForRestorePoint(Backup.RestorePoint restorePoint, VirtualMachine vm, Backup.Metric metric) {
+ return null;
+ }
+
}
\ No newline at end of file
From 8fcc034526b84c16fc9fa11d9864e8dae38e2e30 Mon Sep 17 00:00:00 2001
From: Dajeong-Park
Date: Mon, 19 Jan 2026 09:03:58 +0900
Subject: [PATCH 14/34] Update BackupSchedule.java
---
.../main/java/org/apache/cloudstack/backup/BackupSchedule.java | 1 -
1 file changed, 1 deletion(-)
diff --git a/api/src/main/java/org/apache/cloudstack/backup/BackupSchedule.java b/api/src/main/java/org/apache/cloudstack/backup/BackupSchedule.java
index 26adc80db37a..da90da508fff 100644
--- a/api/src/main/java/org/apache/cloudstack/backup/BackupSchedule.java
+++ b/api/src/main/java/org/apache/cloudstack/backup/BackupSchedule.java
@@ -31,5 +31,4 @@ public interface BackupSchedule extends InternalIdentity {
Date getScheduledTimestamp();
Long getAsyncJobId();
int getMaxBackups();
- String getUuid();
}
From 78dd41e780f9def5a8900edea65eb41405ce5e76 Mon Sep 17 00:00:00 2001
From: Dajeong-Park
Date: Mon, 19 Jan 2026 09:06:35 +0900
Subject: [PATCH 15/34] Update BackupManagerImpl.java
---
.../java/org/apache/cloudstack/backup/BackupManagerImpl.java | 2 --
1 file changed, 2 deletions(-)
diff --git a/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java b/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java
index 5c1c7f9d955f..c2deb6650ca1 100644
--- a/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java
+++ b/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java
@@ -33,7 +33,6 @@
import com.cloud.alert.AlertManager;
import com.cloud.configuration.Resource;
import com.cloud.exception.ResourceAllocationException;
-import com.cloud.storage.Snapshot;
import com.cloud.storage.VolumeApiService;
import com.cloud.user.DomainManager;
import com.cloud.user.ResourceLimitService;
@@ -74,7 +73,6 @@
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
import org.apache.cloudstack.framework.config.ConfigKey;
-import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.framework.jobs.AsyncJobDispatcher;
import org.apache.cloudstack.framework.jobs.AsyncJobManager;
import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO;
From 7a02284ac6009aa80e1d2e8b5e5b389c7ac72551 Mon Sep 17 00:00:00 2001
From: Dajeong-Park
Date: Mon, 19 Jan 2026 09:57:58 +0900
Subject: [PATCH 16/34] Update VolumeApiServiceImpl.java
---
.../src/main/java/com/cloud/storage/VolumeApiServiceImpl.java | 2 --
1 file changed, 2 deletions(-)
diff --git a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java
index 6d975e1809d4..c20ca58d9416 100644
--- a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java
+++ b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java
@@ -353,8 +353,6 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
private BackupDao backupDao;
@Inject
private StatsCollector statsCollector;
- @Inject
- HostPodDao podDao;
protected Gson _gson;
From 46349c21d7d4f6d7ded8a8679db16420aa480bbf Mon Sep 17 00:00:00 2001
From: Dajeong-Park
Date: Mon, 19 Jan 2026 10:01:20 +0900
Subject: [PATCH 17/34] Update BackupManagerTest.java
---
.../java/org/apache/cloudstack/backup/BackupManagerTest.java | 1 +
1 file changed, 1 insertion(+)
diff --git a/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java b/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java
index 66fa2d33cb1e..88892d982d87 100644
--- a/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java
+++ b/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java
@@ -49,6 +49,7 @@
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.command.admin.backup.UpdateBackupOfferingCmd;
import org.apache.cloudstack.api.command.user.backup.CreateBackupScheduleCmd;
+import org.apache.cloudstack.api.command.user.backup.DeleteBackupScheduleCmd;
import org.apache.cloudstack.backup.dao.BackupDao;
import org.apache.cloudstack.backup.dao.BackupOfferingDao;
import org.apache.cloudstack.backup.dao.BackupScheduleDao;
From c90bc9f9dfba80706e16317495d7bb2e5e00bbc9 Mon Sep 17 00:00:00 2001
From: Dajeong-Park
Date: Mon, 19 Jan 2026 10:24:03 +0900
Subject: [PATCH 18/34] Update BackupManagerTest.java
---
.../cloudstack/backup/BackupManagerTest.java | 1335 ++++++++++++++++-
1 file changed, 1260 insertions(+), 75 deletions(-)
diff --git a/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java b/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java
index 88892d982d87..489ac2c8213a 100644
--- a/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java
+++ b/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java
@@ -16,18 +16,41 @@
// under the License.
package org.apache.cloudstack.backup;
+import com.cloud.api.query.dao.UserVmJoinDao;
+import com.cloud.api.query.vo.UserVmJoinVO;
import com.cloud.alert.AlertManager;
+import com.cloud.capacity.CapacityVO;
import com.cloud.configuration.Resource;
+import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.domain.Domain;
+import com.cloud.domain.DomainVO;
+import com.cloud.domain.dao.DomainDao;
import com.cloud.event.ActionEventUtils;
+import com.cloud.event.EventTypes;
import com.cloud.event.UsageEventUtils;
import com.cloud.exception.InvalidParameterValueException;
+import com.cloud.host.HostVO;
+import com.cloud.host.dao.HostDao;
+import com.cloud.hypervisor.Hypervisor;
+import com.cloud.network.Network;
+import com.cloud.network.NetworkService;
+import com.cloud.network.dao.NetworkDao;
+import com.cloud.network.dao.NetworkVO;
+import com.cloud.offering.DiskOffering;
+import com.cloud.service.ServiceOfferingVO;
+import com.cloud.service.dao.ServiceOfferingDao;
+import com.cloud.storage.DiskOfferingVO;
import com.cloud.exception.ResourceAllocationException;
+import com.cloud.storage.Storage;
+import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.Volume;
import com.cloud.storage.VolumeApiService;
import com.cloud.storage.VolumeVO;
+import com.cloud.storage.dao.DiskOfferingDao;
+import com.cloud.storage.dao.GuestOSDao;
+import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
@@ -35,27 +58,39 @@
import com.cloud.user.DomainManager;
import com.cloud.user.ResourceLimitService;
import com.cloud.user.User;
-import com.cloud.user.UserVO;
+import com.cloud.user.dao.AccountDao;
import com.cloud.utils.DateUtil;
import com.cloud.utils.Pair;
+import com.cloud.utils.db.SearchBuilder;
+import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.fsm.NoTransitionException;
+import com.cloud.vm.VMInstanceDetailVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
+import com.cloud.vm.VmDiskInfo;
import com.cloud.vm.VirtualMachineManager;
+import com.cloud.vm.dao.VMInstanceDetailsDao;
import com.cloud.vm.dao.VMInstanceDao;
import com.google.gson.Gson;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ServerApiException;
+import org.apache.cloudstack.api.command.admin.backup.ImportBackupOfferingCmd;
import org.apache.cloudstack.api.command.admin.backup.UpdateBackupOfferingCmd;
+import org.apache.cloudstack.api.command.user.backup.CreateBackupCmd;
import org.apache.cloudstack.api.command.user.backup.CreateBackupScheduleCmd;
import org.apache.cloudstack.api.command.user.backup.DeleteBackupScheduleCmd;
+import org.apache.cloudstack.api.command.user.backup.ListBackupScheduleCmd;
+import org.apache.cloudstack.api.response.BackupResponse;
import org.apache.cloudstack.backup.dao.BackupDao;
+import org.apache.cloudstack.backup.dao.BackupDetailsDao;
import org.apache.cloudstack.backup.dao.BackupOfferingDao;
import org.apache.cloudstack.backup.dao.BackupScheduleDao;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.impl.ConfigDepotImpl;
+import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
+import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO;
import org.junit.After;
import org.junit.Assert;
@@ -76,6 +111,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
+import java.util.Optional;
import java.util.TimeZone;
import java.util.UUID;
@@ -85,10 +121,14 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.atLeastOnce;
@RunWith(MockitoJUnitRunner.class)
public class BackupManagerTest {
@@ -99,6 +139,9 @@ public class BackupManagerTest {
@Mock
BackupOfferingDao backupOfferingDao;
+ @Mock
+ BackupDetailsDao backupDetailsDao;
+
@Mock
BackupProvider backupProvider;
@@ -138,8 +181,6 @@ public class BackupManagerTest {
@Mock
private Domain domainMock;
- private AccountVO account;
-
@Mock
private VMInstanceVO vmInstanceVOMock;
@@ -164,7 +205,41 @@ public class BackupManagerTest {
@Mock
private DeleteBackupScheduleCmd deleteBackupScheduleCmdMock;
- private UserVO user;
+ @Mock
+ DiskOfferingDao diskOfferingDao;
+
+ @Mock
+ ServiceOfferingDao serviceOfferingDao;
+
+ @Mock
+ VMTemplateDao vmTemplateDao;
+
+ @Mock
+ UserVmJoinDao userVmJoinDao;
+
+ @Mock
+ PrimaryDataStoreDao primaryDataStoreDao;
+
+ @Mock
+ HostDao hostDao;
+
+ @Mock
+ private NetworkDao networkDao;
+
+ @Mock
+ private NetworkService networkService;
+
+ @Mock
+ private VMInstanceDetailsDao vmInstanceDetailsDao;
+
+ @Mock
+ AccountDao accountDao;
+
+ @Mock
+ DomainDao domainDao;
+
+ @Mock
+ private GuestOSDao _guestOSDao;
private Gson gson;
@@ -198,6 +273,12 @@ public void setup() throws Exception {
return true;
});
+ backupProvider = mock(BackupProvider.class);
+ when(backupProvider.getName()).thenReturn("testbackupprovider");
+ Map backupProvidersMap = new HashMap<>();
+ backupProvidersMap.put(backupProvider.getName().toLowerCase(), backupProvider);
+ ReflectionTestUtils.setField(backupManager, "backupProvidersMap", backupProvidersMap);
+
Account account = mock(Account.class);
User user = mock(User.class);
CallContext.register(user, account);
@@ -212,6 +293,20 @@ public void tearDown() throws Exception {
CallContext.unregister();
}
+ private void overrideBackupFrameworkConfigValue() {
+ ConfigKey configKey = BackupManager.BackupFrameworkEnabled;
+ this.configDepotImpl = (ConfigDepotImpl) ReflectionTestUtils.getField(configKey, "s_depot");
+ ConfigDepotImpl configDepot = Mockito.mock(ConfigDepotImpl.class);
+ Mockito.when(configDepot.getConfigStringValue(Mockito.eq(BackupManager.BackupFrameworkEnabled.key()),
+ Mockito.eq(ConfigKey.Scope.Global), Mockito.isNull())).thenReturn("true");
+ Mockito.when(configDepot.getConfigStringValue(Mockito.eq(BackupManager.BackupFrameworkEnabled.key()),
+ Mockito.eq(ConfigKey.Scope.Zone), Mockito.anyLong())).thenReturn("true");
+ Mockito.when(configDepot.getConfigStringValue(Mockito.eq(BackupManager.BackupProviderPlugin.key()),
+ Mockito.eq(ConfigKey.Scope.Zone), Mockito.anyLong())).thenReturn("testbackupprovider");
+ ReflectionTestUtils.setField(configKey, "s_depot", configDepot);
+ updatedConfigKeyDepot = true;
+ }
+
@Test
public void testExceptionWhenUpdateWithNullId() {
try {
@@ -226,7 +321,7 @@ public void testExceptionWhenUpdateWithNullId() {
}
}
- @Test (expected = InvalidParameterValueException.class)
+ @Test(expected = InvalidParameterValueException.class)
public void testExceptionWhenUpdateWithNonExistentId() {
Long id = 123l;
@@ -236,7 +331,7 @@ public void testExceptionWhenUpdateWithNonExistentId() {
backupManager.updateBackupOffering(cmd);
}
- @Test (expected = ServerApiException.class)
+ @Test(expected = ServerApiException.class)
public void testExceptionWhenUpdateWithoutChanges() {
UpdateBackupOfferingCmd cmd = Mockito.spy(UpdateBackupOfferingCmd.class);
when(cmd.getName()).thenReturn(null);
@@ -267,96 +362,117 @@ public void testUpdateBackupOfferingSuccess() {
@Test
public void restoreBackedUpVolumeTestHostIpAndDatastoreUuid() {
BackupVO backupVO = new BackupVO();
- VMInstanceVO vm = Mockito.mock(VMInstanceVO.class);
+ VMInstanceVO vm = mock(VMInstanceVO.class);
String volumeUuid = "5f4ed903-ac23-4f8a-b595-69c73c40593f";
String vmName = "i-2-3-VM";
VirtualMachine.State vmState = VirtualMachine.State.Running;
Mockito.when(vm.getName()).thenReturn(vmName);
Mockito.when(vm.getState()).thenReturn(vmState);
- Pair vmNameAndState = new Pair<>("i-2-3-VM", VirtualMachine.State.Running);
+ Pair vmNameAndState = new Pair<>(vmName, vmState);
+
+ Backup.VolumeInfo volumeInfo = mock(Backup.VolumeInfo.class);
+ when(volumeInfo.getUuid()).thenReturn(volumeUuid);
- Mockito.when(backupProvider.restoreBackedUpVolume(Mockito.any(), Mockito.eq(volumeUuid),
- Mockito.eq("127.0.0.1"), Mockito.eq("e9804933-8609-4de3-bccc-6278072a496c"), Mockito.eq(vmNameAndState))).thenReturn(new Pair(Boolean.TRUE, "Success"));
- Pair restoreBackedUpVolume = backupManager.restoreBackedUpVolume(volumeUuid, backupVO, backupProvider, hostPossibleValues, datastoresPossibleValues, vm);
+ doReturn(new Pair(Boolean.TRUE, "Success"))
+ .when(backupProvider).restoreBackedUpVolume(any(Backup.class), any(Backup.VolumeInfo.class),
+ any(String.class), any(String.class), any(Pair.class));
+
+ Pair restoreBackedUpVolume = backupManager.restoreBackedUpVolume(volumeInfo, backupVO, backupProvider, hostPossibleValues, datastoresPossibleValues, vm);
assertEquals(Boolean.TRUE, restoreBackedUpVolume.first());
assertEquals("Success", restoreBackedUpVolume.second());
- Mockito.verify(backupProvider, times(1)).restoreBackedUpVolume(Mockito.any(), Mockito.anyString(),
- Mockito.anyString(), Mockito.anyString(), any(Pair.class));
+ verify(backupProvider, atLeastOnce()).restoreBackedUpVolume(any(Backup.class), any(Backup.VolumeInfo.class),
+ any(String.class), any(String.class), any(Pair.class));
}
@Test
public void restoreBackedUpVolumeTestHostIpAndDatastoreName() {
BackupVO backupVO = new BackupVO();
- VMInstanceVO vm = Mockito.mock(VMInstanceVO.class);
+ VMInstanceVO vm = mock(VMInstanceVO.class);
String volumeUuid = "5f4ed903-ac23-4f8a-b595-69c73c40593f";
String vmName = "i-2-3-VM";
VirtualMachine.State vmState = VirtualMachine.State.Running;
Mockito.when(vm.getName()).thenReturn(vmName);
Mockito.when(vm.getState()).thenReturn(vmState);
- Pair vmNameAndState = new Pair<>("i-2-3-VM", VirtualMachine.State.Running);
- Mockito.when(backupProvider.restoreBackedUpVolume(Mockito.any(), Mockito.eq(volumeUuid),
- Mockito.eq("127.0.0.1"), Mockito.eq("datastore-name"), Mockito.eq(vmNameAndState))).thenReturn(new Pair(Boolean.TRUE, "Success2"));
- Pair restoreBackedUpVolume = backupManager.restoreBackedUpVolume(volumeUuid, backupVO, backupProvider, hostPossibleValues, datastoresPossibleValues, vm);
+ Pair vmNameAndState = new Pair<>(vmName, vmState);
+
+ Backup.VolumeInfo volumeInfo = mock(Backup.VolumeInfo.class);
+ when(volumeInfo.getUuid()).thenReturn(volumeUuid);
+
+ doReturn(new Pair(Boolean.TRUE, "Success2"))
+ .when(backupProvider).restoreBackedUpVolume(any(Backup.class), any(Backup.VolumeInfo.class),
+ any(String.class), any(String.class), any(Pair.class));
+
+ Pair restoreBackedUpVolume = backupManager.restoreBackedUpVolume(volumeInfo, backupVO, backupProvider, hostPossibleValues, datastoresPossibleValues, vm);
assertEquals(Boolean.TRUE, restoreBackedUpVolume.first());
assertEquals("Success2", restoreBackedUpVolume.second());
- Mockito.verify(backupProvider, times(2)).restoreBackedUpVolume(Mockito.any(), Mockito.anyString(),
- Mockito.anyString(), Mockito.anyString(), any(Pair.class));
+ verify(backupProvider, atLeastOnce()).restoreBackedUpVolume(any(Backup.class), any(Backup.VolumeInfo.class),
+ any(String.class), any(String.class), any(Pair.class));
}
@Test
public void restoreBackedUpVolumeTestHostNameAndDatastoreUuid() {
BackupVO backupVO = new BackupVO();
- VMInstanceVO vm = Mockito.mock(VMInstanceVO.class);
+ VMInstanceVO vm = mock(VMInstanceVO.class);
String volumeUuid = "5f4ed903-ac23-4f8a-b595-69c73c40593f";
String vmName = "i-2-3-VM";
VirtualMachine.State vmState = VirtualMachine.State.Running;
Mockito.when(vm.getName()).thenReturn(vmName);
Mockito.when(vm.getState()).thenReturn(vmState);
- Pair vmNameAndState = new Pair<>("i-2-3-VM", VirtualMachine.State.Running);
+ Pair vmNameAndState = new Pair<>(vmName, vmState);
- Mockito.when(backupProvider.restoreBackedUpVolume(Mockito.any(), Mockito.eq(volumeUuid),
- Mockito.eq("hostname"), Mockito.eq("e9804933-8609-4de3-bccc-6278072a496c"), Mockito.eq(vmNameAndState))).thenReturn(new Pair(Boolean.TRUE, "Success3"));
- Pair restoreBackedUpVolume = backupManager.restoreBackedUpVolume(volumeUuid, backupVO, backupProvider, hostPossibleValues, datastoresPossibleValues, vm);
+ Backup.VolumeInfo volumeInfo = mock(Backup.VolumeInfo.class);
+ when(volumeInfo.getUuid()).thenReturn(volumeUuid);
+
+ doReturn(new Pair(Boolean.TRUE, "Success3"))
+ .when(backupProvider).restoreBackedUpVolume(any(Backup.class), any(Backup.VolumeInfo.class),
+ any(String.class), any(String.class), any(Pair.class));
+
+ Pair restoreBackedUpVolume = backupManager.restoreBackedUpVolume(volumeInfo, backupVO, backupProvider, hostPossibleValues, datastoresPossibleValues, vm);
assertEquals(Boolean.TRUE, restoreBackedUpVolume.first());
assertEquals("Success3", restoreBackedUpVolume.second());
- Mockito.verify(backupProvider, times(3)).restoreBackedUpVolume(Mockito.any(), Mockito.anyString(),
- Mockito.anyString(), Mockito.anyString(), any(Pair.class));
+ verify(backupProvider, atLeastOnce()).restoreBackedUpVolume(any(Backup.class), any(Backup.VolumeInfo.class),
+ any(String.class), any(String.class), any(Pair.class));
}
@Test
public void restoreBackedUpVolumeTestHostAndDatastoreName() {
BackupVO backupVO = new BackupVO();
- VMInstanceVO vm = Mockito.mock(VMInstanceVO.class);
+ VMInstanceVO vm = mock(VMInstanceVO.class);
String volumeUuid = "5f4ed903-ac23-4f8a-b595-69c73c40593f";
String vmName = "i-2-3-VM";
VirtualMachine.State vmState = VirtualMachine.State.Running;
Mockito.when(vm.getName()).thenReturn(vmName);
Mockito.when(vm.getState()).thenReturn(vmState);
- Pair vmNameAndState = new Pair<>("i-2-3-VM", VirtualMachine.State.Running);
+ Pair vmNameAndState = new Pair<>(vmName, vmState);
- Mockito.when(backupProvider.restoreBackedUpVolume(Mockito.any(), Mockito.eq(volumeUuid),
- Mockito.eq("hostname"), Mockito.eq("datastore-name"), Mockito.eq(vmNameAndState))).thenReturn(new Pair(Boolean.TRUE, "Success4"));
- Pair restoreBackedUpVolume = backupManager.restoreBackedUpVolume(volumeUuid, backupVO, backupProvider, hostPossibleValues, datastoresPossibleValues, vm);
+ Backup.VolumeInfo volumeInfo = mock(Backup.VolumeInfo.class);
+ when(volumeInfo.getUuid()).thenReturn(volumeUuid);
+
+ doReturn(new Pair(Boolean.TRUE, "Success4"))
+ .when(backupProvider).restoreBackedUpVolume(any(Backup.class), any(Backup.VolumeInfo.class),
+ any(String.class), any(String.class), any(Pair.class));
+
+ Pair restoreBackedUpVolume = backupManager.restoreBackedUpVolume(volumeInfo, backupVO, backupProvider, hostPossibleValues, datastoresPossibleValues, vm);
assertEquals(Boolean.TRUE, restoreBackedUpVolume.first());
assertEquals("Success4", restoreBackedUpVolume.second());
- Mockito.verify(backupProvider, times(4)).restoreBackedUpVolume(Mockito.any(), Mockito.anyString(),
- Mockito.anyString(), Mockito.anyString(), any(Pair.class));
+ verify(backupProvider, atLeastOnce()).restoreBackedUpVolume(any(Backup.class), any(Backup.VolumeInfo.class),
+ any(String.class), any(String.class), any(Pair.class));
}
@Test
public void tryRestoreVMTestRestoreSucceeded() throws NoTransitionException {
- BackupOffering offering = Mockito.mock(BackupOffering.class);
- VolumeVO volumeVO = Mockito.mock(VolumeVO.class);
- VMInstanceVO vm = Mockito.mock(VMInstanceVO.class);
- BackupVO backup = Mockito.mock(BackupVO.class);
+ BackupOffering offering = mock(BackupOffering.class);
+ VolumeVO volumeVO = mock(VolumeVO.class);
+ VMInstanceVO vm = mock(VMInstanceVO.class);
+ BackupVO backup = mock(BackupVO.class);
try (MockedStatic utils = Mockito.mockStatic(ActionEventUtils.class)) {
Mockito.when(ActionEventUtils.onStartedActionEvent(Mockito.anyLong(), Mockito.anyLong(),
@@ -381,10 +497,10 @@ public void tryRestoreVMTestRestoreSucceeded() throws NoTransitionException {
@Test
public void tryRestoreVMTestRestoreFails() throws NoTransitionException {
- BackupOffering offering = Mockito.mock(BackupOffering.class);
- VolumeVO volumeVO = Mockito.mock(VolumeVO.class);
- VMInstanceVO vm = Mockito.mock(VMInstanceVO.class);
- BackupVO backup = Mockito.mock(BackupVO.class);
+ BackupOffering offering = mock(BackupOffering.class);
+ VolumeVO volumeVO = mock(VolumeVO.class);
+ VMInstanceVO vm = mock(VMInstanceVO.class);
+ BackupVO backup = mock(BackupVO.class);
try (MockedStatic utils = Mockito.mockStatic(ActionEventUtils.class)) {
Mockito.when(ActionEventUtils.onStartedActionEvent(Mockito.anyLong(), Mockito.anyLong(),
@@ -413,20 +529,6 @@ public void tryRestoreVMTestRestoreFails() throws NoTransitionException {
}
}
- private void overrideBackupFrameworkConfigValue() {
- ConfigKey configKey = BackupManager.BackupFrameworkEnabled;
- this.configDepotImpl = (ConfigDepotImpl) ReflectionTestUtils.getField(configKey, "s_depot");
- ConfigDepotImpl configDepot = Mockito.mock(ConfigDepotImpl.class);
- Mockito.when(configDepot.getConfigStringValue(Mockito.eq(BackupManager.BackupFrameworkEnabled.key()),
- Mockito.eq(ConfigKey.Scope.Global), Mockito.isNull())).thenReturn("true");
- Mockito.when(configDepot.getConfigStringValue(Mockito.eq(BackupManager.BackupFrameworkEnabled.key()),
- Mockito.eq(ConfigKey.Scope.Zone), Mockito.anyLong())).thenReturn("true");
- Mockito.when(configDepot.getConfigStringValue(Mockito.eq(BackupManager.BackupProviderPlugin.key()),
- Mockito.eq(ConfigKey.Scope.Zone), Mockito.anyLong())).thenReturn("testbackupprovider");
- ReflectionTestUtils.setField(configKey, "s_depot", configDepot);
- updatedConfigKeyDepot = true;
- }
-
@Test
public void testConfigureBackupSchedule() {
Long vmId = 1L;
@@ -441,6 +543,7 @@ public void testConfigureBackupSchedule() {
when(cmd.getIntervalType()).thenReturn(DateUtil.IntervalType.DAILY);
when(cmd.getMaxBackups()).thenReturn(8);
when(cmd.getSchedule()).thenReturn("00:00:00");
+ when(cmd.getQuiesceVM()).thenReturn(null);
VMInstanceVO vm = Mockito.mock(VMInstanceVO.class);
when(vmInstanceDao.findById(vmId)).thenReturn(vm);
@@ -516,7 +619,9 @@ public void createBackupTestCreateScheduledBackup() throws ResourceAllocationExc
Long backupOfferingId = 4L;
Long accountId = 5L;
Long backupId = 6L;
+ Long oldestBackupId = 7L;
Long newBackupSize = 1000000000L;
+ Long oldBackupSize = 400000000L;
when(vmInstanceDao.findById(vmId)).thenReturn(vmInstanceVOMock);
when(vmInstanceVOMock.getDataCenterId()).thenReturn(zoneId);
@@ -526,7 +631,7 @@ public void createBackupTestCreateScheduledBackup() throws ResourceAllocationExc
overrideBackupFrameworkConfigValue();
when(backupOfferingDao.findById(backupOfferingId)).thenReturn(backupOfferingVOMock);
when(backupOfferingVOMock.isUserDrivenBackupAllowed()).thenReturn(true);
- when(backupOfferingVOMock.getProvider()).thenReturn("test");
+ when(backupOfferingVOMock.getProvider()).thenReturn("testbackupprovider");
Mockito.doReturn(scheduleId).when(backupManager).getBackupScheduleId(asyncJobVOMock);
@@ -536,31 +641,45 @@ public void createBackupTestCreateScheduledBackup() throws ResourceAllocationExc
when(backupScheduleDao.findById(scheduleId)).thenReturn(schedule);
when(schedule.getMaxBackups()).thenReturn(2);
+ VolumeVO volume = mock(VolumeVO.class);
+ when(volumeDao.findByInstance(vmId)).thenReturn(List.of(volume));
+ when(volume.getState()).thenReturn(Volume.State.Ready);
+ when(volumeApiService.getVolumePhysicalSize(null, null, null)).thenReturn(newBackupSize);
+
BackupProvider backupProvider = mock(BackupProvider.class);
Backup backup = mock(Backup.class);
when(backup.getId()).thenReturn(backupId);
when(backup.getSize()).thenReturn(newBackupSize);
- when(backupProvider.getName()).thenReturn("test");
- when(backupProvider.takeBackup(vmInstanceVOMock)).thenReturn(new Pair<>(true, backup));
+ when(backupProvider.getName()).thenReturn("testbackupprovider");
+ when(backupProvider.takeBackup(vmInstanceVOMock, null)).thenReturn(new Pair<>(true, backup));
Map backupProvidersMap = new HashMap<>();
backupProvidersMap.put(backupProvider.getName().toLowerCase(), backupProvider);
ReflectionTestUtils.setField(backupManager, "backupProvidersMap", backupProvidersMap);
BackupVO backupVO = mock(BackupVO.class);
when(backupVO.getId()).thenReturn(backupId);
- BackupVO oldestBackupVO = mock(BackupVO.class);;
+ BackupVO oldestBackupVO = mock(BackupVO.class);
when(backupDao.findById(backupId)).thenReturn(backupVO);
List backups = new ArrayList<>(List.of(oldestBackupVO));
when(backupDao.listBySchedule(scheduleId)).thenReturn(backups);
+ CreateBackupCmd cmd = Mockito.mock(CreateBackupCmd.class);
+ when(cmd.getVmId()).thenReturn(vmId);
+ when(cmd.getName()).thenReturn("new-backup1");
+ when(cmd.getQuiesceVM()).thenReturn(null);
+
try (MockedStatic ignored = Mockito.mockStatic(ActionEventUtils.class)) {
Mockito.when(ActionEventUtils.onActionEvent(Mockito.anyLong(), Mockito.anyLong(),
Mockito.anyLong(),
Mockito.anyString(), Mockito.anyString(),
Mockito.anyLong(), Mockito.anyString())).thenReturn(1L);
- assertTrue(backupManager.createBackup(vmId, asyncJobVOMock));
+ assertTrue(backupManager.createBackup(cmd, asyncJobVOMock));
+
+ Mockito.verify(resourceLimitMgr, times(1)).checkResourceLimit(accountVOMock, Resource.ResourceType.backup);
+ Mockito.verify(resourceLimitMgr, times(1)).checkResourceLimit(accountVOMock, Resource.ResourceType.backup_storage, newBackupSize);
+
Mockito.verify(resourceLimitMgr, times(1)).incrementResourceCount(accountId, Resource.ResourceType.backup);
Mockito.verify(resourceLimitMgr, times(1)).incrementResourceCount(accountId, Resource.ResourceType.backup_storage, newBackupSize);
Mockito.verify(backupDao, times(1)).update(backupVO.getId(), backupVO);
@@ -585,6 +704,46 @@ public void createBackupTestResourceLimitReached() throws ResourceAllocationExce
BackupOfferingVO offering = Mockito.mock(BackupOfferingVO.class);
when(backupOfferingDao.findById(backupOfferingId)).thenReturn(offering);
when(offering.isUserDrivenBackupAllowed()).thenReturn(true);
+ when(offering.getProvider()).thenReturn("testbackupprovider");
+
+ Account account = Mockito.mock(Account.class);
+ when(accountManager.getAccount(accountId)).thenReturn(account);
+ Mockito.doThrow(new ResourceAllocationException("", Resource.ResourceType.backup)).when(resourceLimitMgr).checkResourceLimit(account, Resource.ResourceType.backup);
+
+ CreateBackupCmd cmd = Mockito.mock(CreateBackupCmd.class);
+ when(cmd.getVmId()).thenReturn(vmId);
+ when(cmd.getQuiesceVM()).thenReturn(null);
+
+ String jobParams = "{}";
+ when(asyncJobVOMock.getCmdInfo()).thenReturn(jobParams);
+ when(asyncJobVOMock.getId()).thenReturn(1L);
+
+ backupManager.createBackup(cmd, asyncJobVOMock);
+
+ String msg = "Backup storage space resource limit exceeded for account id : " + accountId + ". Failed to create backup";
+ Mockito.verify(alertManagerMock, times(1)).sendAlert(AlertManager.AlertType.ALERT_TYPE_UPDATE_RESOURCE_COUNT, 0L, 0L, msg, "Backup resource limit exceeded for account id : " + accountId
+ + ". Failed to create backups; please use updateResourceLimit to increase the limit");
+ }
+
+ @Test (expected = ResourceAllocationException.class)
+ public void testCreateBackupStorageLimitReached() throws ResourceAllocationException {
+ Long vmId = 1L;
+ Long zoneId = 2L;
+ Long scheduleId = 3L;
+ Long backupOfferingId = 4L;
+ Long accountId = 5L;
+
+ VMInstanceVO vm = Mockito.mock(VMInstanceVO.class);
+ when(vmInstanceDao.findById(vmId)).thenReturn(vm);
+ when(vm.getDataCenterId()).thenReturn(zoneId);
+ when(vm.getBackupOfferingId()).thenReturn(backupOfferingId);
+ when(vm.getAccountId()).thenReturn(accountId);
+
+ overrideBackupFrameworkConfigValue();
+ BackupOfferingVO offering = Mockito.mock(BackupOfferingVO.class);
+ when(backupOfferingDao.findById(backupOfferingId)).thenReturn(offering);
+ when(offering.isUserDrivenBackupAllowed()).thenReturn(true);
+ when(offering.getProvider()).thenReturn("testbackupprovider");
Mockito.doReturn(scheduleId).when(backupManager).getBackupScheduleId(asyncJobVOMock);
@@ -592,7 +751,15 @@ public void createBackupTestResourceLimitReached() throws ResourceAllocationExce
when(accountManager.getAccount(accountId)).thenReturn(account);
Mockito.doThrow(new ResourceAllocationException("", Resource.ResourceType.backup_storage)).when(resourceLimitMgr).checkResourceLimit(account, Resource.ResourceType.backup_storage, 0L);
- backupManager.createBackup(vmId, asyncJobVOMock);
+ CreateBackupCmd cmd = Mockito.mock(CreateBackupCmd.class);
+ when(cmd.getVmId()).thenReturn(vmId);
+ when(cmd.getQuiesceVM()).thenReturn(null);
+
+ backupManager.createBackup(cmd, asyncJobVOMock);
+
+ String msg = "Backup storage space resource limit exceeded for account id : " + accountId + ". Failed to create backup";
+ Mockito.verify(alertManagerMock, times(1)).sendAlert(AlertManager.AlertType.ALERT_TYPE_UPDATE_RESOURCE_COUNT, 0L, 0L, msg, "Backup storage space resource limit exceeded for account id : " + accountId
+ + ". Failed to create backups; please use updateResourceLimit to increase the limit");
}
@Test
@@ -605,7 +772,7 @@ public void testBackupSyncTask() {
Long backup1Size = 1 * Resource.ResourceType.bytesToGiB;
Long backup2Size = 2 * Resource.ResourceType.bytesToGiB;
Long newBackupSize = 3 * Resource.ResourceType.bytesToGiB;
- Long metricSize = 4 * Resource.ResourceType.bytesToGiB;
+ Long restorePointSize = 4 * Resource.ResourceType.bytesToGiB;
overrideBackupFrameworkConfigValue();
@@ -621,23 +788,23 @@ public void testBackupSyncTask() {
VMInstanceVO vm = Mockito.mock(VMInstanceVO.class);
when(vm.getId()).thenReturn(vmId);
when(vm.getAccountId()).thenReturn(accountId);
- when(vmInstanceDao.listByZoneWithBackups(dataCenterId, null)).thenReturn(List.of(vm));
- Backup.Metric metric = new Backup.Metric(metricSize, null);
- Map metricMap = new HashMap<>();
- metricMap.put(vm, metric);
- when(backupProvider.getBackupMetrics(Mockito.anyLong(), Mockito.anyList())).thenReturn(metricMap);
-
- Backup.RestorePoint restorePoint1 = new Backup.RestorePoint(restorePoint1ExternalId, DateUtil.now(), "Root");
- Backup.RestorePoint restorePoint2 = new Backup.RestorePoint("12345", DateUtil.now(), "Root");
+ List vmIds = List.of(vmId);
+ when(backupDao.listVmIdsWithBackupsInZone(dataCenterId)).thenReturn(vmIds);
+ when(vmInstanceDao.listByZoneAndBackupOffering(dataCenterId, null)).thenReturn(List.of(vm));
+
+ Backup.RestorePoint restorePoint1 = new Backup.RestorePoint(restorePoint1ExternalId, DateUtil.now(), "Full", restorePointSize, 0L);
+ Backup.RestorePoint restorePoint2 = new Backup.RestorePoint("12345", DateUtil.now(), "Full", restorePointSize, 0L);
List restorePoints = new ArrayList<>(List.of(restorePoint1, restorePoint2));
when(backupProvider.listRestorePoints(vm)).thenReturn(restorePoints);
BackupVO backupInDb1 = new BackupVO();
backupInDb1.setSize(backup1Size);
+ backupInDb1.setAccountId(accountId);
backupInDb1.setExternalId(restorePoint1ExternalId);
BackupVO backupInDb2 = new BackupVO();
backupInDb2.setSize(backup2Size);
+ backupInDb2.setAccountId(accountId);
backupInDb2.setExternalId(null);
ReflectionTestUtils.setField(backupInDb2, "id", backup2Id);
when(backupDao.findById(backup2Id)).thenReturn(backupInDb2);
@@ -646,7 +813,7 @@ public void testBackupSyncTask() {
BackupVO newBackupEntry = new BackupVO();
newBackupEntry.setSize(newBackupSize);
- when(backupProvider.createNewBackupEntryForRestorePoint(restorePoint2, vm, metric)).thenReturn(newBackupEntry);
+ when(backupProvider.createNewBackupEntryForRestorePoint(restorePoint2, vm)).thenReturn(newBackupEntry);
try (MockedStatic ignored = Mockito.mockStatic(ActionEventUtils.class)) {
Mockito.when(ActionEventUtils.onActionEvent(Mockito.anyLong(), Mockito.anyLong(),
@@ -660,8 +827,8 @@ public void testBackupSyncTask() {
backupSyncTask.runInContext();
verify(resourceLimitMgr, times(1)).decrementResourceCount(accountId, Resource.ResourceType.backup_storage, backup1Size);
- verify(resourceLimitMgr, times(1)).incrementResourceCount(accountId, Resource.ResourceType.backup_storage, metricSize);
- Assert.assertEquals(backupInDb1.getSize(), metricSize);
+ verify(resourceLimitMgr, times(1)).incrementResourceCount(accountId, Resource.ResourceType.backup_storage, restorePointSize);
+ Assert.assertEquals(backupInDb1.getSize(), restorePointSize);
verify(resourceLimitMgr, times(1)).incrementResourceCount(accountId, Resource.ResourceType.backup);
verify(resourceLimitMgr, times(1)).incrementResourceCount(accountId, Resource.ResourceType.backup_storage, newBackupSize);
@@ -764,6 +931,687 @@ public void deleteBackupScheduleTestDeleteSpecificScheduleWhenItsIdIsSpecified()
assertTrue(success);
}
+ @Test
+ public void testGetBackupDetailsFromVM() {
+ Long vmId = 1L;
+ VirtualMachine vm = mock(VirtualMachine.class);
+ when(vm.getServiceOfferingId()).thenReturn(1L);
+ when(vm.getTemplateId()).thenReturn(2L);
+ when(vm.getId()).thenReturn(vmId);
+
+ ServiceOfferingVO serviceOffering = mock(ServiceOfferingVO.class);
+ when(serviceOffering.getUuid()).thenReturn("service-offering-uuid");
+ when(serviceOfferingDao.findById(1L)).thenReturn(serviceOffering);
+ VMTemplateVO template = mock(VMTemplateVO.class);
+ when(template.getUuid()).thenReturn("template-uuid");
+ when(vmTemplateDao.findById(2L)).thenReturn(template);
+
+ VMInstanceDetailVO vmInstanceDetail = mock(VMInstanceDetailVO.class);
+ when(vmInstanceDetail.getName()).thenReturn("mocked-detail-name");
+ when(vmInstanceDetail.getValue()).thenReturn("mocked-detail-value");
+ List vmDetails = Collections.singletonList(vmInstanceDetail);
+ when(vmInstanceDetailsDao.listDetails(vmId)).thenReturn(vmDetails);
+
+ UserVmJoinVO userVmJoinVO = mock(UserVmJoinVO.class);
+ when(userVmJoinVO.getNetworkUuid()).thenReturn("mocked-network-uuid");
+ List userVmJoinVOs = Collections.singletonList(userVmJoinVO);
+ when(userVmJoinDao.searchByIds(vmId)).thenReturn(userVmJoinVOs);
+
+ Map details = backupManager.getBackupDetailsFromVM(vm);
+
+ assertEquals("service-offering-uuid", details.get(ApiConstants.SERVICE_OFFERING_ID));
+ assertEquals("[{\"networkid\":\"mocked-network-uuid\"}]", details.get(ApiConstants.NICS));
+ assertEquals("{\"mocked-detail-name\":\"mocked-detail-value\"}", details.get(ApiConstants.VM_SETTINGS));
+ }
+
+ @Test
+ public void getDataDiskInfoListFromBackup() {
+ Long size1 = 5L * 1024 * 1024 * 1024;
+ Long size2 = 10L * 1024 * 1024 * 1024;
+ Backup backup = mock(Backup.class);
+
+ Backup.VolumeInfo volumeInfo0 = mock(Backup.VolumeInfo.class);
+ when(volumeInfo0.getType()).thenReturn(Volume.Type.ROOT);
+ Backup.VolumeInfo volumeInfo1 = mock(Backup.VolumeInfo.class);
+ when(volumeInfo1.getDiskOfferingId()).thenReturn("disk-offering-uuid-1");
+ when(volumeInfo1.getSize()).thenReturn(size1);
+ when(volumeInfo1.getMinIops()).thenReturn(100L);
+ when(volumeInfo1.getMaxIops()).thenReturn(300L);
+ when(volumeInfo1.getType()).thenReturn(Volume.Type.DATADISK);
+ when(volumeInfo1.getDeviceId()).thenReturn(1L);
+ Backup.VolumeInfo volumeInfo2 = mock(Backup.VolumeInfo.class);
+ when(volumeInfo2.getDiskOfferingId()).thenReturn("disk-offering-uuid-2");
+ when(volumeInfo2.getSize()).thenReturn(size2);
+ when(volumeInfo2.getMinIops()).thenReturn(200L);
+ when(volumeInfo2.getMaxIops()).thenReturn(400L);
+ when(volumeInfo2.getType()).thenReturn(Volume.Type.DATADISK);
+ when(volumeInfo2.getDeviceId()).thenReturn(2L);
+ when(backup.getBackedUpVolumes()).thenReturn(List.of(volumeInfo0, volumeInfo1, volumeInfo2));
+
+ DiskOfferingVO diskOffering1 = mock(DiskOfferingVO.class);
+ when(diskOffering1.getUuid()).thenReturn("disk-offering-uuid-1");
+ when(diskOffering1.getState()).thenReturn(DiskOffering.State.Active);
+
+ DiskOfferingVO diskOffering2 = mock(DiskOfferingVO.class);
+ when(diskOffering2.getUuid()).thenReturn("disk-offering-uuid-2");
+ when(diskOffering2.getState()).thenReturn(DiskOffering.State.Active);
+
+ when(diskOfferingDao.findByUuid("disk-offering-uuid-1")).thenReturn(diskOffering1);
+ when(diskOfferingDao.findByUuid("disk-offering-uuid-2")).thenReturn(diskOffering2);
+
+ List vmDiskInfoList = backupManager.getDataDiskInfoListFromBackup(backup);
+
+ assertEquals(2, vmDiskInfoList.size());
+ assertEquals("disk-offering-uuid-1", vmDiskInfoList.get(0).getDiskOffering().getUuid());
+ assertEquals(Long.valueOf(5), vmDiskInfoList.get(0).getSize());
+ assertEquals(Long.valueOf(1), vmDiskInfoList.get(0).getDeviceId());
+ assertEquals(Long.valueOf(100), vmDiskInfoList.get(0).getMinIops());
+ assertEquals(Long.valueOf(300), vmDiskInfoList.get(0).getMaxIops());
+
+ assertEquals("disk-offering-uuid-2", vmDiskInfoList.get(1).getDiskOffering().getUuid());
+ assertEquals(Long.valueOf(10), vmDiskInfoList.get(1).getSize());
+ assertEquals(Long.valueOf(2), vmDiskInfoList.get(1).getDeviceId());
+ assertEquals(Long.valueOf(200), vmDiskInfoList.get(1).getMinIops());
+ assertEquals(Long.valueOf(400), vmDiskInfoList.get(1).getMaxIops());
+ }
+
+ @Test
+ public void getDataDiskInfoListFromBackupNullIops() {
+ Long size = 5L * 1024 * 1024 * 1024;
+ Backup backup = mock(Backup.class);
+ Backup.VolumeInfo volumeInfo1 = mock(Backup.VolumeInfo.class);
+ when(volumeInfo1.getDiskOfferingId()).thenReturn("disk-offering-uuid-1");
+ when(volumeInfo1.getSize()).thenReturn(size);
+ when(volumeInfo1.getMinIops()).thenReturn(null);
+ when(volumeInfo1.getMaxIops()).thenReturn(null);
+ when(volumeInfo1.getType()).thenReturn(Volume.Type.DATADISK);
+ when(volumeInfo1.getDeviceId()).thenReturn(1L);
+ when(backup.getBackedUpVolumes()).thenReturn(List.of(volumeInfo1));
+
+ DiskOfferingVO diskOffering = mock(DiskOfferingVO.class);
+ when(diskOffering.getUuid()).thenReturn("disk-offering-uuid-1");
+ when(diskOffering.getState()).thenReturn(DiskOffering.State.Active);
+
+ when(diskOfferingDao.findByUuid("disk-offering-uuid-1")).thenReturn(diskOffering);
+
+ List vmDiskInfoList = backupManager.getDataDiskInfoListFromBackup(backup);
+
+ assertEquals(1, vmDiskInfoList.size());
+ assertEquals("disk-offering-uuid-1", vmDiskInfoList.get(0).getDiskOffering().getUuid());
+ assertEquals(Long.valueOf(5), vmDiskInfoList.get(0).getSize());
+ assertEquals(Long.valueOf(1), vmDiskInfoList.get(0).getDeviceId());
+ assertNull(vmDiskInfoList.get(0).getMinIops());
+ assertNull(vmDiskInfoList.get(0).getMaxIops());
+ }
+
+ @Test (expected = InvalidParameterValueException.class)
+ public void testCheckVmDisksSizeAgainstBackup() {
+ Long sizeInBackup = 5L * 1024 * 1024 * 1024;
+ Long sizeInCmd = 2L;
+ Backup backup = mock(Backup.class);
+ Backup.VolumeInfo volumeInfo = mock(Backup.VolumeInfo.class);
+ when(volumeInfo.getDiskOfferingId()).thenReturn("disk-offering-uuid-1");
+ when(volumeInfo.getSize()).thenReturn(sizeInBackup);
+ when(volumeInfo.getType()).thenReturn(Volume.Type.DATADISK);
+ when(backup.getBackedUpVolumes()).thenReturn(List.of(volumeInfo));
+
+ DiskOfferingVO diskOffering = mock(DiskOfferingVO.class);
+ when(diskOffering.getState()).thenReturn(DiskOffering.State.Active);
+ when(diskOfferingDao.findByUuid("disk-offering-uuid-1")).thenReturn(diskOffering);
+ List vmDiskInfoList = List.of(new VmDiskInfo(diskOffering, sizeInCmd, 1L, null, null));
+
+ backupManager.checkVmDisksSizeAgainstBackup(vmDiskInfoList, backup);
+ }
+
+ @Test
+ public void testGetRootDiskInfoFromBackup() {
+ Long size = 5L * 1024 * 1024 * 1024;
+ Backup backup = mock(Backup.class);
+ Backup.VolumeInfo volumeInfo = mock(Backup.VolumeInfo.class);
+ when(volumeInfo.getDiskOfferingId()).thenReturn("root-disk-offering-uuid");
+ when(volumeInfo.getSize()).thenReturn(size);
+ when(volumeInfo.getType()).thenReturn(Volume.Type.ROOT);
+ when(backup.getBackedUpVolumes()).thenReturn(List.of(volumeInfo));
+
+ DiskOfferingVO diskOffering = mock(DiskOfferingVO.class);
+ when(diskOffering.getUuid()).thenReturn("root-disk-offering-uuid");
+ when(diskOfferingDao.findByUuid("root-disk-offering-uuid")).thenReturn(diskOffering);
+
+ VmDiskInfo VmDiskInfo = backupManager.getRootDiskInfoFromBackup(backup);
+
+ assertEquals("root-disk-offering-uuid", VmDiskInfo.getDiskOffering().getUuid());
+ assertEquals(Long.valueOf(5), VmDiskInfo.getSize());
+ assertEquals(null, VmDiskInfo.getDeviceId());
+ }
+
+ @Test
+ public void testImportBackupOffering() {
+ ImportBackupOfferingCmd cmd = Mockito.mock(ImportBackupOfferingCmd.class);
+ when(cmd.getZoneId()).thenReturn(1L);
+ when(cmd.getExternalId()).thenReturn("external-id");
+ when(cmd.getName()).thenReturn("Test Offering");
+ when(cmd.getDescription()).thenReturn("Test Description");
+ when(cmd.getUserDrivenBackups()).thenReturn(true);
+
+ overrideBackupFrameworkConfigValue();
+
+ when(backupOfferingDao.findByExternalId("external-id", 1L)).thenReturn(null);
+ when(backupOfferingDao.findByName("Test Offering", 1L)).thenReturn(null);
+
+ BackupOfferingVO offering = new BackupOfferingVO(1L, "external-id", "testbackupprovider", "Test Offering", "Test Description", true);
+ when(backupOfferingDao.persist(any(BackupOfferingVO.class))).thenReturn(offering);
+ when(backupProvider.isValidProviderOffering(cmd.getZoneId(), cmd.getExternalId())).thenReturn(true);
+
+ BackupOffering result = backupManager.importBackupOffering(cmd);
+
+ assertEquals("Test Offering", result.getName());
+ assertEquals("Test Description", result.getDescription());
+ assertEquals(true, result.isUserDrivenBackupAllowed());
+ assertEquals("external-id", result.getExternalId());
+ assertEquals("testbackupprovider", result.getProvider());
+ }
+
+ @Test
+ public void testCreateVolumeInfoFromVolumes() {
+ Long diskOfferingId = 5L;
+ DiskOfferingVO diskOffering = Mockito.mock(DiskOfferingVO.class);
+ Mockito.when(diskOffering.getUuid()).thenReturn("disk-offering-uuid");
+ Mockito.when(diskOfferingDao.findById(diskOfferingId)).thenReturn(diskOffering);
+
+ List volumes = new ArrayList<>();
+ VolumeVO volume1 = new VolumeVO(Volume.Type.ROOT, "vol1", 1L, 2L, 3L,
+ diskOfferingId, null, 1024L, null, null, null);
+ volume1.setUuid("uuid1");
+ volume1.setPath("path1");
+ volume1.setDeviceId(0L);
+ volume1.setVolumeType(Volume.Type.ROOT);
+ volumes.add(volume1);
+
+ VolumeVO volume2 = new VolumeVO(Volume.Type.ROOT, "vol2", 1L, 2L, 3L,
+ diskOfferingId, null, 2048L, 1000L, 2000L, null);
+ volume2.setUuid("uuid2");
+ volume2.setPath("path2");
+ volume2.setDeviceId(1L);
+ volume2.setVolumeType(Volume.Type.DATADISK);
+ volumes.add(volume2);
+
+ String expectedJson = "[{\"uuid\":\"uuid1\",\"type\":\"ROOT\",\"size\":1024,\"path\":\"path1\",\"deviceId\":0,\"diskOfferingId\":\"disk-offering-uuid\"},{\"uuid\":\"uuid2\",\"type\":\"DATADISK\",\"size\":2048,\"path\":\"path2\",\"deviceId\":1,\"diskOfferingId\":\"disk-offering-uuid\",\"minIops\":1000,\"maxIops\":2000}]";
+ String actualJson = backupManager.createVolumeInfoFromVolumes(new ArrayList<>(volumes));
+
+ assertEquals(expectedJson, actualJson);
+ }
+
+ @Test
+ public void testAssignVMToBackupOffering() {
+ Long vmId = 1L;
+ Long offeringId = 2L;
+
+ VMInstanceVO vm = mock(VMInstanceVO.class);
+ when(vm.getId()).thenReturn(vmId);
+ BackupOfferingVO offering = mock(BackupOfferingVO.class);
+
+ overrideBackupFrameworkConfigValue();
+
+ when(vmInstanceDao.findById(vmId)).thenReturn(vm);
+ when(backupOfferingDao.findById(offeringId)).thenReturn(offering);
+ when(vm.getState()).thenReturn(VirtualMachine.State.Running);
+ when(vm.getDataCenterId()).thenReturn(1L);
+ when(vm.getBackupOfferingId()).thenReturn(null);
+ when(offering.getProvider()).thenReturn("testbackupprovider");
+ when(backupProvider.assignVMToBackupOffering(vm, offering)).thenReturn(true);
+ when(vmInstanceDao.update(1L, vm)).thenReturn(true);
+
+ try (MockedStatic ignored2 = Mockito.mockStatic(UsageEventUtils.class)) {
+ boolean result = backupManager.assignVMToBackupOffering(vmId, offeringId);
+
+ assertTrue(result);
+ verify(vmInstanceDao, times(1)).findById(vmId);
+ verify(backupOfferingDao, times(1)).findById(offeringId);
+ verify(backupManager, times(1)).getBackupProvider("testbackupprovider");
+ }
+ }
+
+ @Test
+ public void testRemoveVMFromBackupOffering() {
+ Long vmId = 1L;
+ Long accountId = 2L;
+ Long zoneId = 3L;
+ Long offeringId = 4L;
+ Long backupScheduleId = 5L;
+ String vmHostName = "vm1";
+ String vmUuid = "uuid1";
+ String resourceName = "Backup-" + vmHostName + "-" + vmUuid;
+
+ boolean forced = true;
+
+ VMInstanceVO vm = mock(VMInstanceVO.class);
+ when(vm.getId()).thenReturn(vmId);
+ when(vm.getDataCenterId()).thenReturn(1L);
+ when(vm.getBackupOfferingId()).thenReturn(offeringId);
+ when(vm.getAccountId()).thenReturn(accountId);
+ when(vm.getDataCenterId()).thenReturn(zoneId);
+ when(vm.getHostName()).thenReturn(vmHostName);
+ when(vm.getUuid()).thenReturn(vmUuid);
+ when(vmInstanceDao.findByIdIncludingRemoved(vmId)).thenReturn(vm);
+ when(vmInstanceDao.update(vmId, vm)).thenReturn(true);
+
+ BackupOfferingVO offering = mock(BackupOfferingVO.class);
+ when(backupOfferingDao.findById(vm.getBackupOfferingId())).thenReturn(offering);
+ when(offering.getProvider()).thenReturn("testbackupprovider");
+ when(backupProvider.removeVMFromBackupOffering(vm)).thenReturn(true);
+ when(backupProvider.willDeleteBackupsOnOfferingRemoval()).thenReturn(true);
+ when(backupDao.listByVmId(null, vmId)).thenReturn(new ArrayList<>());
+
+ BackupScheduleVO backupSchedule = new BackupScheduleVO();
+ ReflectionTestUtils.setField(backupSchedule, "id", backupScheduleId);
+ when(backupScheduleDao.listByVM(vmId)).thenReturn(List.of(backupSchedule));
+
+ overrideBackupFrameworkConfigValue();
+
+ try (MockedStatic usageEventUtilsMocked = Mockito.mockStatic(UsageEventUtils.class)) {
+ boolean result = backupManager.removeVMFromBackupOffering(vmId, forced);
+
+ assertTrue(result);
+ verify(vmInstanceDao, times(1)).findByIdIncludingRemoved(vmId);
+ verify(backupOfferingDao, times(1)).findById(vm.getBackupOfferingId());
+ verify(backupManager, times(1)).getBackupProvider("testbackupprovider");
+ verify(backupScheduleDao, times(1)).remove(backupScheduleId);
+ usageEventUtilsMocked.verify(() -> UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_BACKUP_OFFERING_REMOVED_AND_BACKUPS_DELETED, accountId, zoneId, vmId, resourceName,
+ offeringId, null, null, Backup.class.getSimpleName(), vmUuid));
+ }
+ }
+
+ @Test
+ public void testDeleteBackupScheduleByVmId() {
+ Long vmId = 1L;
+ Long scheduleId = 2L;
+ DeleteBackupScheduleCmd cmd = new DeleteBackupScheduleCmd();
+ ReflectionTestUtils.setField(cmd, "vmId", vmId);
+
+ overrideBackupFrameworkConfigValue();
+
+ VMInstanceVO vm = mock(VMInstanceVO.class);
+ when(vmInstanceDao.findById(vmId)).thenReturn(vm);
+ BackupScheduleVO schedule = mock(BackupScheduleVO.class);
+ when(schedule.getId()).thenReturn(scheduleId);
+ when(backupScheduleDao.listByVM(vmId)).thenReturn(List.of(schedule));
+ when(backupScheduleDao.remove(scheduleId)).thenReturn(true);
+
+ boolean result = backupManager.deleteBackupSchedule(cmd);
+ assertTrue(result);
+ }
+
+ @Test
+ public void testRestoreBackupToVM() throws NoTransitionException {
+ Long backupId = 1L;
+ Long vmId = 2L;
+ Long hostId = 3L;
+ Long offeringId = 4L;
+ Long poolId = 5L;
+
+ BackupVO backup = mock(BackupVO.class);
+ when(backup.getBackupOfferingId()).thenReturn(offeringId);
+ when(backup.getStatus()).thenReturn(Backup.Status.BackedUp);
+
+ VMInstanceVO vm = mock(VMInstanceVO.class);
+ when(vmInstanceDao.findByIdIncludingRemoved(vmId)).thenReturn(vm);
+ when(vm.getId()).thenReturn(vmId);
+ when(vm.getState()).thenReturn(VirtualMachine.State.Stopped);
+ when(vm.getHostId()).thenReturn(hostId);
+
+ BackupOfferingVO offering = mock(BackupOfferingVO.class);
+ BackupProvider backupProvider = mock(BackupProvider.class);
+ when(backupProvider.supportsInstanceFromBackup()).thenReturn(true);
+
+ overrideBackupFrameworkConfigValue();
+
+ when(backupDao.findById(backupId)).thenReturn(backup);
+ when(vmInstanceDao.findByIdIncludingRemoved(vmId)).thenReturn(vm);
+ when(backupOfferingDao.findByIdIncludingRemoved(offeringId)).thenReturn(offering);
+ when(offering.getProvider()).thenReturn("testbackupprovider");
+ when(backupManager.getBackupProvider("testbackupprovider")).thenReturn(backupProvider);
+ when(virtualMachineManager.stateTransitTo(vm, VirtualMachine.Event.RestoringRequested, hostId)).thenReturn(true);
+ when(virtualMachineManager.stateTransitTo(vm, VirtualMachine.Event.RestoringSuccess, hostId)).thenReturn(true);
+
+ VolumeVO rootVolume = mock(VolumeVO.class);
+ when(rootVolume.getPoolId()).thenReturn(poolId);
+ HostVO host = mock(HostVO.class);
+ when(hostDao.findById(hostId)).thenReturn(host);
+ StoragePoolVO pool = mock(StoragePoolVO.class);
+ when(volumeDao.findIncludingRemovedByInstanceAndType(vmId, Volume.Type.ROOT)).thenReturn(List.of(rootVolume));
+ when(primaryDataStoreDao.findById(poolId)).thenReturn(pool);
+ when(rootVolume.getPoolId()).thenReturn(poolId);
+ when(volumeDao.findIncludingRemovedByInstanceAndType(vmId, Volume.Type.ROOT)).thenReturn(List.of(rootVolume));
+ when(primaryDataStoreDao.findById(poolId)).thenReturn(pool);
+ when(backupProvider.restoreBackupToVM(vm, backup, null, null)).thenReturn(new Pair<>(true, null));
+
+ try (MockedStatic utils = Mockito.mockStatic(ActionEventUtils.class)) {
+ boolean result = backupManager.restoreBackupToVM(backupId, vmId);
+
+ assertTrue(result);
+ verify(backupProvider, times(1)).restoreBackupToVM(vm, backup, null, null);
+ verify(virtualMachineManager, times(1)).stateTransitTo(vm, VirtualMachine.Event.RestoringRequested, hostId);
+ verify(virtualMachineManager, times(1)).stateTransitTo(vm, VirtualMachine.Event.RestoringSuccess, hostId);
+ } catch (CloudRuntimeException e) {
+ fail("Test failed due to exception" + e);
+ }
+ }
+
+ @Test
+ public void testRestoreBackupToVMException() throws NoTransitionException {
+ Long backupId = 1L;
+ Long vmId = 2L;
+ Long hostId = 3L;
+ Long offeringId = 4L;
+ Long poolId = 5L;
+
+ BackupVO backup = mock(BackupVO.class);
+ when(backup.getBackupOfferingId()).thenReturn(offeringId);
+ when(backup.getStatus()).thenReturn(Backup.Status.BackedUp);
+
+ VMInstanceVO vm = mock(VMInstanceVO.class);
+ when(vmInstanceDao.findByIdIncludingRemoved(vmId)).thenReturn(vm);
+ when(vm.getId()).thenReturn(vmId);
+ when(vm.getState()).thenReturn(VirtualMachine.State.Stopped);
+ when(vm.getHostId()).thenReturn(hostId);
+
+ BackupOfferingVO offering = mock(BackupOfferingVO.class);
+ BackupProvider backupProvider = mock(BackupProvider.class);
+ when(backupProvider.supportsInstanceFromBackup()).thenReturn(true);
+
+ overrideBackupFrameworkConfigValue();
+
+ when(backupDao.findById(backupId)).thenReturn(backup);
+ when(vmInstanceDao.findByIdIncludingRemoved(vmId)).thenReturn(vm);
+ when(backupOfferingDao.findByIdIncludingRemoved(offeringId)).thenReturn(offering);
+ when(offering.getProvider()).thenReturn("testbackupprovider");
+ when(backupManager.getBackupProvider("testbackupprovider")).thenReturn(backupProvider);
+ when(virtualMachineManager.stateTransitTo(vm, VirtualMachine.Event.RestoringRequested, hostId)).thenReturn(true);
+ when(virtualMachineManager.stateTransitTo(vm, VirtualMachine.Event.RestoringFailed, hostId)).thenReturn(true);
+
+ VolumeVO rootVolume = mock(VolumeVO.class);
+ when(rootVolume.getPoolId()).thenReturn(poolId);
+ HostVO host = mock(HostVO.class);
+ when(hostDao.findById(hostId)).thenReturn(host);
+ StoragePoolVO pool = mock(StoragePoolVO.class);
+ when(volumeDao.findIncludingRemovedByInstanceAndType(vmId, Volume.Type.ROOT)).thenReturn(List.of(rootVolume));
+ when(primaryDataStoreDao.findById(poolId)).thenReturn(pool);
+ when(rootVolume.getPoolId()).thenReturn(poolId);
+ when(volumeDao.findIncludingRemovedByInstanceAndType(vmId, Volume.Type.ROOT)).thenReturn(List.of(rootVolume));
+ when(primaryDataStoreDao.findById(poolId)).thenReturn(pool);
+ when(backupProvider.restoreBackupToVM(vm, backup, null, null)).thenReturn(new Pair<>(false, null));
+
+ try (MockedStatic utils = Mockito.mockStatic(ActionEventUtils.class)) {
+ CloudRuntimeException exception = Assert.assertThrows(CloudRuntimeException.class,
+ () -> backupManager.restoreBackupToVM(backupId, vmId));
+
+ verify(backupProvider, times(1)).restoreBackupToVM(vm, backup, null, null);
+ verify(virtualMachineManager, times(1)).stateTransitTo(vm, VirtualMachine.Event.RestoringRequested, hostId);
+ verify(virtualMachineManager, times(1)).stateTransitTo(vm, VirtualMachine.Event.RestoringFailed, hostId);
+ }
+ }
+
+ @Test
+ public void testGetBackupStorageUsedStats() {
+ Long zoneId = 1L;
+ overrideBackupFrameworkConfigValue();
+ when(backupManager.getBackupProvider(zoneId)).thenReturn(backupProvider);
+ when(backupProvider.getBackupStorageStats(zoneId)).thenReturn(new Pair<>(100L, 200L));
+
+ CapacityVO capacity = backupManager.getBackupStorageUsedStats(zoneId);
+
+ Assert.assertNotNull(capacity);
+ Assert.assertEquals(Optional.ofNullable(Long.valueOf(100)), Optional.ofNullable(capacity.getUsedCapacity()));
+ Assert.assertEquals(Optional.ofNullable(Long.valueOf(200)), Optional.ofNullable(capacity.getTotalCapacity()));
+ Assert.assertEquals(CapacityVO.CAPACITY_TYPE_BACKUP_STORAGE, capacity.getCapacityType());
+ }
+
+ @Test
+ public void testCheckAndRemoveBackupOfferingBeforeExpunge() {
+ Long vmId = 1L;
+ Long zoneId = 2L;
+ Long offeringId = 3L;
+ String vmUuid = "uuid1";
+ String instanceName = "i-2-1-VM";
+ String backupExternalId = "backup-external-id";
+
+ VMInstanceVO vm = mock(VMInstanceVO.class);
+ when(vm.getId()).thenReturn(vmId);
+ when(vm.getUuid()).thenReturn(vmUuid);
+ when(vm.getBackupOfferingId()).thenReturn(offeringId);
+ when(vm.getInstanceName()).thenReturn(instanceName);
+ when(vm.getBackupExternalId()).thenReturn(backupExternalId);
+ when(vm.getDataCenterId()).thenReturn(zoneId);
+ Backup backup = mock(Backup.class);
+ when(backupDao.listByVmIdAndOffering(zoneId, vmId, offeringId)).thenReturn(List.of(backup));
+
+ CloudRuntimeException exception = Assert.assertThrows(CloudRuntimeException.class,
+ () -> backupManager.checkAndRemoveBackupOfferingBeforeExpunge(vm));
+ Assert.assertEquals("This Instance [uuid: uuid1, name: i-2-1-VM] has a "
+ + "Backup Offering [id: 3, external id: backup-external-id] with 1 backups. Please, remove the backup offering "
+ + "before proceeding to VM exclusion!", exception.getMessage());
+ }
+
+ @Test
+ public void testGetIpToNetworkMapFromBackup() {
+ Long networkId1 = 1L;
+ Long networkId2 = 2L;
+ String networkUuid1 = "network-uuid-1";
+ String networkUuid2 = "network-uuid-2";
+ String ip1 = "10.1.1.1";
+ String ip2 = "10.1.1.2";
+ String ipv61 = "2001:db8::1";
+ String ipv62 = "2001:db8::2";
+ String mac1 = "00:11:22:33:44:55";
+ String mac2 = "00:11:22:33:44:56";
+
+ // Test case 1: Missing network information
+ Backup backup1 = mock(Backup.class);
+ List networkIds1 = new ArrayList<>();
+ try {
+ backupManager.getIpToNetworkMapFromBackup(backup1, true, networkIds1);
+ fail("Expected CloudRuntimeException for missing network information");
+ } catch (CloudRuntimeException e) {
+ assertEquals("Backup doesn't contain network information. Please specify at least one valid network while creating instance", e.getMessage());
+ }
+
+ // Test case 2: IP preservation enabled with IP information
+ Backup backup2 = mock(Backup.class);
+ String nicsJson = String.format("[{\"networkid\":\"%s\",\"ipaddress\":\"%s\",\"ip6address\":\"%s\",\"macaddress\":\"%s\"}," +
+ "{\"networkid\":\"%s\",\"ipaddress\":\"%s\",\"ip6address\":\"%s\",\"macaddress\":\"%s\"}]",
+ networkUuid1, ip1, ipv61, mac1, networkUuid2, ip2, ipv62, mac2);
+ when(backup2.getDetail(ApiConstants.NICS)).thenReturn(nicsJson);
+
+ NetworkVO network1 = mock(NetworkVO.class);
+ NetworkVO network2 = mock(NetworkVO.class);
+ when(networkDao.findByUuid(networkUuid1)).thenReturn(network1);
+ when(networkDao.findByUuid(networkUuid2)).thenReturn(network2);
+ when(network1.getId()).thenReturn(networkId1);
+ when(network2.getId()).thenReturn(networkId2);
+
+ Network.IpAddresses ipAddresses1 = mock(Network.IpAddresses.class);
+ Network.IpAddresses ipAddresses2 = mock(Network.IpAddresses.class);
+ when(networkService.getIpAddressesFromIps(ip1, ipv61, mac1)).thenReturn(ipAddresses1);
+ when(networkService.getIpAddressesFromIps(ip2, ipv62, mac2)).thenReturn(ipAddresses2);
+
+ List networkIds2 = new ArrayList<>();
+ Map result2 = backupManager.getIpToNetworkMapFromBackup(backup2, true, networkIds2);
+
+ assertEquals(2, result2.size());
+ assertEquals(ipAddresses1, result2.get(networkId1));
+ assertEquals(ipAddresses2, result2.get(networkId2));
+ assertEquals(2, networkIds2.size());
+ assertTrue(networkIds2.contains(networkId1));
+ assertTrue(networkIds2.contains(networkId2));
+
+ // Test case 3: IP preservation enabled but missing IP information
+ Backup backup3 = mock(Backup.class);
+ nicsJson = String.format("[{\"networkid\":\"%s\"}]", networkUuid1);
+ when(backup3.getDetail(ApiConstants.NICS)).thenReturn(nicsJson);
+
+ List networkIds3 = new ArrayList<>();
+ Map result3 = backupManager.getIpToNetworkMapFromBackup(backup3, true, networkIds3);
+
+ assertEquals(1, result3.size());
+ assertNull(result3.get(networkId1));
+ assertEquals(1, networkIds3.size());
+ assertTrue(networkIds3.contains(networkId1));
+
+ // Test case 4: IP preservation disabled
+ Backup backup4 = mock(Backup.class);
+ nicsJson = String.format("[{\"networkid\":\"%s\"}]", networkUuid1);
+ when(backup4.getDetail(ApiConstants.NICS)).thenReturn(nicsJson);
+
+ List networkIds4 = new ArrayList<>();
+ Map result4 = backupManager.getIpToNetworkMapFromBackup(backup4, false, networkIds4);
+
+ assertEquals(1, result4.size());
+ assertNull(result4.get(networkId1));
+ assertEquals(1, networkIds4.size());
+ assertTrue(networkIds4.contains(networkId1));
+ }
+
+ @Test
+ public void testDeleteBackupVmNotFound() {
+ Long backupId = 1L;
+ Long vmId = 2L;
+ Long zoneId = 3L;
+ Long accountId = 4L;
+ Long backupOfferingId = 5L;
+ String vmHostName = "vm1";
+ String vmUuid = "uuid1";
+ String resourceName = "Backup-" + vmHostName + "-" + vmUuid;
+
+ BackupVO backup = mock(BackupVO.class);
+ when(backup.getId()).thenReturn(backupId);
+ when(backup.getVmId()).thenReturn(vmId);
+ when(backup.getZoneId()).thenReturn(zoneId);
+ when(backup.getAccountId()).thenReturn(accountId);
+ when(backup.getBackupOfferingId()).thenReturn(backupOfferingId);
+ when(backup.getSize()).thenReturn(100L);
+
+ overrideBackupFrameworkConfigValue();
+
+ VMInstanceVO vm = mock(VMInstanceVO.class);
+ when(vm.getId()).thenReturn(vmId);
+ when(vm.getAccountId()).thenReturn(accountId);
+ when(vm.getBackupOfferingId()).thenReturn(10L);
+ when(vm.getDataCenterId()).thenReturn(zoneId);
+ when(vm.getHostName()).thenReturn(vmHostName);
+ when(vm.getUuid()).thenReturn(vmUuid);
+ when(backupDao.findByIdIncludingRemoved(backupId)).thenReturn(backup);
+ when(vmInstanceDao.findByIdIncludingRemoved(vmId)).thenReturn(vm);
+ when(backupDao.listByVmIdAndOffering(zoneId, vmId, backupOfferingId)).thenReturn(new ArrayList<>());
+
+ BackupOfferingVO offering = mock(BackupOfferingVO.class);
+ when(backupOfferingDao.findByIdIncludingRemoved(backupOfferingId)).thenReturn(offering);
+
+ when(backupProvider.deleteBackup(backup, false)).thenReturn(true);
+
+ when(backupDao.remove(backupId)).thenReturn(true);
+
+ try (MockedStatic usageEventUtilsMocked = Mockito.mockStatic(UsageEventUtils.class)) {
+ boolean result = backupManager.deleteBackup(backupId, false);
+
+ assertTrue(result);
+ verify(backupProvider).deleteBackup(backup, false);
+ verify(resourceLimitMgr).decrementResourceCount(accountId, Resource.ResourceType.backup);
+ verify(resourceLimitMgr).decrementResourceCount(accountId, Resource.ResourceType.backup_storage, backup.getSize());
+ verify(backupDao).remove(backupId);
+ usageEventUtilsMocked.verify(() -> UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_BACKUP_OFFERING_REMOVED_AND_BACKUPS_DELETED, accountId, zoneId, vmId, resourceName,
+ backupOfferingId, null, null, Backup.class.getSimpleName(), vmUuid));
+ }
+ }
+
+ @Test
+ public void testNewBackupResponse() {
+ Long vmId = 1L;
+ Long accountId = 2L;
+ Long domainId = 3L;
+ Long zoneId = 4L;
+ Long vmOfferingId = 5L;
+ Long backupOfferingId = 6L;
+ Long backupId = 7L;
+ Long templateId = 8L;
+ String templateUuid = "template-uuid1";
+ String serviceOfferingUuid = "service-offering-uuid1";
+
+ BackupVO backup = new BackupVO();
+ ReflectionTestUtils.setField(backup, "id", backupId);
+ ReflectionTestUtils.setField(backup, "uuid", "backup-uuid");
+ backup.setVmId(vmId);
+ backup.setAccountId(accountId);
+ backup.setDomainId(domainId);
+ backup.setZoneId(zoneId);
+ backup.setBackupOfferingId(backupOfferingId);
+ backup.setType("Full");
+ backup.setBackupScheduleId(null);
+
+ VMInstanceVO vm = new VMInstanceVO(vmId, 0L, "test-vm", "test-vm", VirtualMachine.Type.User,
+ 0L, Hypervisor.HypervisorType.Simulator, 0L, domainId, accountId, 0L, false);
+ vm.setDataCenterId(zoneId);
+ vm.setBackupOfferingId(vmOfferingId);
+ vm.setTemplateId(templateId);
+
+ AccountVO account = new AccountVO();
+ account.setUuid("account-uuid");
+ account.setAccountName("test-account");
+
+ DomainVO domain = new DomainVO();
+ domain.setUuid("domain-uuid");
+ domain.setName("test-domain");
+
+ DataCenterVO zone = new DataCenterVO(1L, "test-zone", null, null, null, null, null, null, null, null, DataCenter.NetworkType.Advanced, null, null);
+ zone.setUuid("zone-uuid");
+
+ BackupOfferingVO offering = Mockito.mock(BackupOfferingVO.class);
+ Mockito.when(offering.getUuid()).thenReturn("offering-uuid");
+ Mockito.when(offering.getName()).thenReturn("test-offering");
+
+ Mockito.when(vmInstanceDao.findByIdIncludingRemoved(vmId)).thenReturn(vm);
+ Mockito.when(accountDao.findByIdIncludingRemoved(accountId)).thenReturn(account);
+ Mockito.when(domainDao.findByIdIncludingRemoved(domainId)).thenReturn(domain);
+ Mockito.when(dataCenterDao.findByIdIncludingRemoved(zoneId)).thenReturn(zone);
+ Mockito.when(backupOfferingDao.findByIdIncludingRemoved(backupOfferingId)).thenReturn(offering);
+
+ VMTemplateVO template = mock(VMTemplateVO.class);
+ when(template.getFormat()).thenReturn(Storage.ImageFormat.QCOW2);
+ when(template.getName()).thenReturn("template1");
+ when(vmTemplateDao.findByUuid(templateUuid)).thenReturn(template);
+ Map details = new HashMap<>();
+ details.put(ApiConstants.TEMPLATE_ID, templateUuid);
+
+ ServiceOfferingVO serviceOffering = mock(ServiceOfferingVO.class);
+ when(serviceOffering.getName()).thenReturn("service-offering1");
+ when(serviceOfferingDao.findByUuid(serviceOfferingUuid)).thenReturn(serviceOffering);
+ details.put(ApiConstants.SERVICE_OFFERING_ID, serviceOfferingUuid);
+
+ NetworkVO network = mock(NetworkVO.class);
+ when(network.getName()).thenReturn("network1");
+ when(networkDao.findByUuid("network-uuid1")).thenReturn(network);
+ details.put(ApiConstants.NICS, "[{\"networkid\":\"network-uuid1\"}]");
+
+ Mockito.when(backupDetailsDao.listDetailsKeyPairs(backup.getId(), true)).thenReturn(details);
+
+ BackupResponse response = backupManager.createBackupResponse(backup, true);
+
+ Assert.assertEquals("backup-uuid", response.getId());
+ Assert.assertEquals("test-vm", response.getVmName());
+ Assert.assertEquals("account-uuid", response.getAccountId());
+ Assert.assertEquals("test-account", response.getAccount());
+ Assert.assertEquals("domain-uuid", response.getDomainId());
+ Assert.assertEquals("test-domain", response.getDomain());
+ Assert.assertEquals("zone-uuid", response.getZoneId());
+ Assert.assertEquals("test-zone", response.getZone());
+ Assert.assertEquals("offering-uuid", response.getBackupOfferingId());
+ Assert.assertEquals("test-offering", response.getBackupOffering());
+ Assert.assertEquals("MANUAL", response.getIntervalType());
+ Assert.assertEquals("{serviceofferingid=service-offering-uuid1, isiso=false, hypervisor=Simulator, " +
+ "nics=[{\"networkid\":\"network-uuid1\",\"networkname\":\"network1\"}], serviceofferingname=service-offering1, " +
+ "templatename=template1, templateid=template-uuid1}", response.getVmDetails().toString());
+ Assert.assertEquals(true, response.getVmOfferingRemoved());
+ }
+
@Test
public void validateAndGetDefaultBackupRetentionIfRequiredTestReturnZeroAsDefaultValue() {
int retention = backupManager.validateAndGetDefaultBackupRetentionIfRequired(null, backupOfferingVOMock, null);
@@ -971,4 +1819,341 @@ public void sendExceededBackupLimitAlertTestSendAlertForBackupStorageResourceTyp
expectedAlertDetails
);
}
-}
+
+ @Test
+ public void testListBackupSchedulesAsRootAdmin() {
+ long vmId = 1L;
+ ListBackupScheduleCmd cmd = Mockito.mock(ListBackupScheduleCmd.class);
+ Mockito.when(cmd.getVmId()).thenReturn(vmId);
+ Mockito.when(cmd.getId()).thenReturn(1L);
+
+ // Mock VM for validation
+ VMInstanceVO vm = Mockito.mock(VMInstanceVO.class);
+ Mockito.when(vmInstanceDao.findById(vmId)).thenReturn(vm);
+ Mockito.when(vm.getDataCenterId()).thenReturn(1L);
+ overrideBackupFrameworkConfigValue();
+ Mockito.doNothing().when(accountManager).checkAccess(Mockito.any(), Mockito.any(), Mockito.anyBoolean(), Mockito.any());
+
+ BackupScheduleVO schedule1 = Mockito.mock(BackupScheduleVO.class);
+ BackupScheduleVO schedule2 = Mockito.mock(BackupScheduleVO.class);
+ List schedules = List.of(schedule1, schedule2);
+
+ SearchBuilder searchBuilder = Mockito.mock(SearchBuilder.class);
+ SearchCriteria searchCriteria = Mockito.mock(SearchCriteria.class);
+ BackupScheduleVO entity = Mockito.mock(BackupScheduleVO.class);
+
+ Mockito.when(backupScheduleDao.createSearchBuilder()).thenReturn(searchBuilder);
+ Mockito.when(searchBuilder.entity()).thenReturn(entity);
+ Mockito.when(searchBuilder.and(Mockito.anyString(), (Object) any(), Mockito.any())).thenReturn(searchBuilder);
+ Mockito.when(searchBuilder.create()).thenReturn(searchCriteria);
+
+ Mockito.when(backupScheduleDao.searchAndCount(Mockito.any(), Mockito.any())).thenReturn(new Pair<>(schedules, schedules.size()));
+ List result = backupManager.listBackupSchedules(cmd);
+
+ assertEquals(2, result.size());
+ assertTrue(result.contains(schedule1));
+ assertTrue(result.contains(schedule2));
+ }
+
+ @Test
+ public void testListBackupSchedulesAsNonAdmin() {
+ long vmId = 1L;
+ ListBackupScheduleCmd cmd = Mockito.mock(ListBackupScheduleCmd.class);
+ Mockito.when(cmd.getVmId()).thenReturn(vmId);
+ Mockito.when(cmd.getId()).thenReturn(1L);
+
+ // Mock VM for validation
+ VMInstanceVO vm = Mockito.mock(VMInstanceVO.class);
+ Mockito.when(vmInstanceDao.findById(vmId)).thenReturn(vm);
+ Mockito.when(vm.getDataCenterId()).thenReturn(1L);
+ overrideBackupFrameworkConfigValue();
+ Mockito.doNothing().when(accountManager).checkAccess(Mockito.any(), Mockito.any(), Mockito.anyBoolean(), Mockito.any());
+
+ BackupScheduleVO schedule = Mockito.mock(BackupScheduleVO.class);
+ List schedules = List.of(schedule);
+
+ SearchBuilder searchBuilder = Mockito.mock(SearchBuilder.class);
+ SearchCriteria searchCriteria = Mockito.mock(SearchCriteria.class);
+ BackupScheduleVO entity = Mockito.mock(BackupScheduleVO.class);
+
+ Mockito.when(backupScheduleDao.createSearchBuilder()).thenReturn(searchBuilder);
+ Mockito.when(searchBuilder.create()).thenReturn(searchCriteria);
+ Mockito.when(searchBuilder.entity()).thenReturn(entity);
+ Mockito.when(searchBuilder.and(Mockito.anyString(), (Object) any(), Mockito.any())).thenReturn(searchBuilder);
+ Mockito.lenient().when(backupScheduleDao.search(Mockito.eq(searchCriteria), Mockito.any())).thenReturn(schedules);
+
+ Mockito.doNothing().when(accountManager).buildACLSearchBuilder(Mockito.any(), Mockito.anyLong(), Mockito.anyBoolean(), Mockito.anyList(), Mockito.any());
+ Mockito.doNothing().when(accountManager).buildACLSearchCriteria(Mockito.any(), Mockito.anyLong(), Mockito.anyBoolean(), Mockito.anyList(), Mockito.any());
+
+ Mockito.when(backupScheduleDao.searchAndCount(Mockito.any(), Mockito.any())).thenReturn(new Pair<>(schedules, schedules.size()));
+ List result = backupManager.listBackupSchedules(cmd);
+
+ assertEquals(1, result.size());
+ assertTrue(result.contains(schedule));
+ }
+
+ @Test
+ public void testCanCreateInstanceFromBackupAcrossZonesSuccess() {
+ Long backupId = 1L;
+ Long backupOfferingId = 2L;
+ String providerName = "testbackupprovider";
+
+ BackupVO backup = mock(BackupVO.class);
+ when(backup.getBackupOfferingId()).thenReturn(backupOfferingId);
+
+ BackupOfferingVO offering = mock(BackupOfferingVO.class);
+ when(offering.getProvider()).thenReturn(providerName);
+
+ BackupProvider backupProvider = mock(BackupProvider.class);
+ when(backupProvider.crossZoneInstanceCreationEnabled(offering)).thenReturn(true);
+
+ when(backupDao.findById(backupId)).thenReturn(backup);
+ when(backupOfferingDao.findByIdIncludingRemoved(backupOfferingId)).thenReturn(offering);
+ when(backupManager.getBackupProvider(providerName)).thenReturn(backupProvider);
+
+ Boolean result = backupManager.canCreateInstanceFromBackupAcrossZones(backupId);
+
+ assertTrue(result);
+ verify(backupDao, times(1)).findById(backupId);
+ verify(backupOfferingDao, times(1)).findByIdIncludingRemoved(backupOfferingId);
+ verify(backupManager, times(1)).getBackupProvider(providerName);
+ verify(backupProvider, times(1)).crossZoneInstanceCreationEnabled(offering);
+ }
+
+ @Test
+ public void testCanCreateInstanceFromBackupAcrossZonesFalse() {
+ Long backupId = 1L;
+ Long backupOfferingId = 2L;
+ String providerName = "testbackupprovider";
+
+ BackupVO backup = mock(BackupVO.class);
+ when(backup.getBackupOfferingId()).thenReturn(backupOfferingId);
+
+ BackupOfferingVO offering = mock(BackupOfferingVO.class);
+ when(offering.getProvider()).thenReturn(providerName);
+
+ BackupProvider backupProvider = mock(BackupProvider.class);
+ when(backupProvider.crossZoneInstanceCreationEnabled(offering)).thenReturn(false);
+
+ when(backupDao.findById(backupId)).thenReturn(backup);
+ when(backupOfferingDao.findByIdIncludingRemoved(backupOfferingId)).thenReturn(offering);
+ when(backupManager.getBackupProvider(providerName)).thenReturn(backupProvider);
+
+ Boolean result = backupManager.canCreateInstanceFromBackupAcrossZones(backupId);
+
+ assertFalse(result);
+ verify(backupDao, times(1)).findById(backupId);
+ verify(backupOfferingDao, times(1)).findByIdIncludingRemoved(backupOfferingId);
+ verify(backupManager, times(1)).getBackupProvider(providerName);
+ verify(backupProvider, times(1)).crossZoneInstanceCreationEnabled(offering);
+ }
+
+ @Test
+ public void testCanCreateInstanceFromBackupAcrossZonesOfferingNotFound() {
+ Long backupId = 1L;
+ Long backupOfferingId = 2L;
+
+ BackupVO backup = mock(BackupVO.class);
+ when(backup.getBackupOfferingId()).thenReturn(backupOfferingId);
+
+ when(backupDao.findById(backupId)).thenReturn(backup);
+ when(backupOfferingDao.findByIdIncludingRemoved(backupOfferingId)).thenReturn(null);
+
+ CloudRuntimeException exception = Assert.assertThrows(CloudRuntimeException.class,
+ () -> backupManager.canCreateInstanceFromBackupAcrossZones(backupId));
+
+ assertEquals("Failed to find backup offering", exception.getMessage());
+ verify(backupDao, times(1)).findById(backupId);
+ verify(backupOfferingDao, times(1)).findByIdIncludingRemoved(backupOfferingId);
+ verify(backupManager, never()).getBackupProvider(any(String.class));
+ }
+
+ @Test
+ public void testRestoreBackupSuccess() throws NoTransitionException {
+ Long backupId = 1L;
+ Long vmId = 2L;
+ Long zoneId = 3L;
+ Long accountId = 4L;
+ Long domainId = 5L;
+ Long userId = 6L;
+ Long offeringId = 7L;
+ String vmInstanceName = "test-vm";
+ Hypervisor.HypervisorType hypervisorType = Hypervisor.HypervisorType.KVM;
+
+ BackupVO backup = mock(BackupVO.class);
+ when(backup.getVmId()).thenReturn(vmId);
+ when(backup.getZoneId()).thenReturn(zoneId);
+ when(backup.getStatus()).thenReturn(Backup.Status.BackedUp);
+ when(backup.getBackupOfferingId()).thenReturn(offeringId);
+ Backup.VolumeInfo volumeInfo = new Backup.VolumeInfo("uuid", "path", Volume.Type.ROOT, 1024L, 0L, "disk-offering-uuid", 1000L, 2000L);
+ when(backup.getBackedUpVolumes()).thenReturn(List.of(volumeInfo));
+ when(backup.getUuid()).thenReturn("backup-uuid");
+
+ VMInstanceVO vm = mock(VMInstanceVO.class);
+ when(vm.getId()).thenReturn(vmId);
+ when(vm.getDataCenterId()).thenReturn(zoneId);
+ when(vm.getDomainId()).thenReturn(domainId);
+ when(vm.getAccountId()).thenReturn(accountId);
+ when(vm.getUserId()).thenReturn(userId);
+ when(vm.getInstanceName()).thenReturn(vmInstanceName);
+ when(vm.getHypervisorType()).thenReturn(hypervisorType);
+ when(vm.getState()).thenReturn(VirtualMachine.State.Stopped);
+ when(vm.getRemoved()).thenReturn(null);
+ when(vm.getBackupOfferingId()).thenReturn(offeringId);
+
+ BackupOfferingVO offering = mock(BackupOfferingVO.class);
+ when(offering.getProvider()).thenReturn("testbackupprovider");
+
+ VolumeVO volume = mock(VolumeVO.class);
+ when(volumeDao.findByInstance(vmId)).thenReturn(Collections.singletonList(volume));
+
+ BackupProvider backupProvider = mock(BackupProvider.class);
+ when(backupProvider.restoreVMFromBackup(vm, backup)).thenReturn(true);
+
+ when(backupDao.findById(backupId)).thenReturn(backup);
+ when(vmInstanceDao.findByIdIncludingRemoved(vmId)).thenReturn(vm);
+ when(backupOfferingDao.findByIdIncludingRemoved(offeringId)).thenReturn(offering);
+ when(backupManager.getBackupProvider("testbackupprovider")).thenReturn(backupProvider);
+ doReturn(true).when(backupManager).importRestoredVM(zoneId, domainId, accountId, userId, vmInstanceName, hypervisorType, backup);
+ doNothing().when(backupManager).validateBackupForZone(any());
+ when(virtualMachineManager.stateTransitTo(any(), any(), any())).thenReturn(true);
+
+ try (MockedStatic utils = Mockito.mockStatic(ActionEventUtils.class)) {
+ Mockito.when(ActionEventUtils.onStartedActionEvent(Mockito.anyLong(), Mockito.anyLong(),
+ Mockito.anyString(), Mockito.anyString(), Mockito.anyLong(), Mockito.anyString(),
+ Mockito.eq(true), Mockito.eq(0))).thenReturn(1L);
+
+ boolean result = backupManager.restoreBackup(backupId);
+
+ assertTrue(result);
+ verify(backupDao, times(1)).findById(backupId);
+ verify(vmInstanceDao, times(1)).findByIdIncludingRemoved(vmId);
+ verify(backupOfferingDao, times(2)).findByIdIncludingRemoved(offeringId);
+ verify(backupProvider, times(1)).restoreVMFromBackup(vm, backup);
+ verify(backupManager, times(1)).importRestoredVM(zoneId, domainId, accountId, userId, vmInstanceName, hypervisorType, backup);
+ }
+ }
+
+ @Test
+ public void testRestoreBackupBackupNotFound() {
+ Long backupId = 1L;
+
+ when(backupDao.findById(backupId)).thenReturn(null);
+
+ CloudRuntimeException exception = Assert.assertThrows(CloudRuntimeException.class,
+ () -> backupManager.restoreBackup(backupId));
+
+ assertEquals("Backup " + backupId + " does not exist", exception.getMessage());
+ verify(backupDao, times(1)).findById(backupId);
+ verify(vmInstanceDao, never()).findByIdIncludingRemoved(any());
+ }
+
+ @Test
+ public void testRestoreBackupBackupNotBackedUp() {
+ Long backupId = 1L;
+
+ BackupVO backup = mock(BackupVO.class);
+ when(backup.getStatus()).thenReturn(Backup.Status.BackingUp);
+
+ when(backupDao.findById(backupId)).thenReturn(backup);
+
+ CloudRuntimeException exception = Assert.assertThrows(CloudRuntimeException.class,
+ () -> backupManager.restoreBackup(backupId));
+
+ assertEquals("Backup should be in BackedUp state", exception.getMessage());
+ verify(backupDao, times(1)).findById(backupId);
+ verify(vmInstanceDao, never()).findByIdIncludingRemoved(any());
+ }
+
+ @Test
+ public void testRestoreBackupVmExpunging() {
+ Long backupId = 1L;
+ Long vmId = 2L;
+ Long zoneId = 3L;
+
+ BackupVO backup = mock(BackupVO.class);
+ when(backup.getVmId()).thenReturn(vmId);
+ when(backup.getZoneId()).thenReturn(zoneId);
+ when(backup.getStatus()).thenReturn(Backup.Status.BackedUp);
+
+ VMInstanceVO vm = mock(VMInstanceVO.class);
+ when(vm.getState()).thenReturn(VirtualMachine.State.Expunging);
+
+ when(backupDao.findById(backupId)).thenReturn(backup);
+ when(vmInstanceDao.findByIdIncludingRemoved(vmId)).thenReturn(vm);
+ doNothing().when(backupManager).validateBackupForZone(any());
+
+ CloudRuntimeException exception = Assert.assertThrows(CloudRuntimeException.class,
+ () -> backupManager.restoreBackup(backupId));
+
+ assertEquals("The Instance from which the backup was taken could not be found.", exception.getMessage());
+ verify(backupDao, times(1)).findById(backupId);
+ verify(vmInstanceDao, times(1)).findByIdIncludingRemoved(vmId);
+ }
+
+ @Test
+ public void testRestoreBackupVmNotStopped() {
+ Long backupId = 1L;
+ Long vmId = 2L;
+ Long zoneId = 3L;
+
+ BackupVO backup = mock(BackupVO.class);
+ when(backup.getVmId()).thenReturn(vmId);
+ when(backup.getZoneId()).thenReturn(zoneId);
+ when(backup.getStatus()).thenReturn(Backup.Status.BackedUp);
+
+ VMInstanceVO vm = mock(VMInstanceVO.class);
+ when(vm.getState()).thenReturn(VirtualMachine.State.Running);
+ when(vm.getRemoved()).thenReturn(null);
+
+ when(backupDao.findById(backupId)).thenReturn(backup);
+ when(vmInstanceDao.findByIdIncludingRemoved(vmId)).thenReturn(vm);
+ doNothing().when(backupManager).validateBackupForZone(any());
+
+ CloudRuntimeException exception = Assert.assertThrows(CloudRuntimeException.class,
+ () -> backupManager.restoreBackup(backupId));
+
+ assertEquals("Existing VM should be stopped before being restored from backup", exception.getMessage());
+ verify(backupDao, times(1)).findById(backupId);
+ verify(vmInstanceDao, times(1)).findByIdIncludingRemoved(vmId);
+ }
+
+ @Test
+ public void testRestoreBackupVolumeMismatch() {
+ Long backupId = 1L;
+ Long vmId = 2L;
+ Long zoneId = 3L;
+
+ BackupVO backup = mock(BackupVO.class);
+ when(backup.getVmId()).thenReturn(vmId);
+ when(backup.getZoneId()).thenReturn(zoneId);
+ when(backup.getStatus()).thenReturn(Backup.Status.BackedUp);
+ when(backup.getBackedUpVolumes()).thenReturn(Collections.emptyList());
+
+ VMInstanceVO vm = mock(VMInstanceVO.class);
+ when(vm.getId()).thenReturn(vmId);
+ when(vm.getState()).thenReturn(VirtualMachine.State.Destroyed);
+ when(vm.getRemoved()).thenReturn(null);
+ when(vm.getBackupVolumeList()).thenReturn(Collections.emptyList());
+
+ VolumeVO volume = mock(VolumeVO.class);
+ when(volumeDao.findByInstance(vmId)).thenReturn(Collections.singletonList(volume));
+
+ when(backupDao.findById(backupId)).thenReturn(backup);
+ when(vmInstanceDao.findByIdIncludingRemoved(vmId)).thenReturn(vm);
+ doNothing().when(backupManager).validateBackupForZone(any());
+
+ try (MockedStatic utils = Mockito.mockStatic(ActionEventUtils.class)) {
+ Mockito.when(ActionEventUtils.onStartedActionEvent(Mockito.anyLong(), Mockito.anyLong(),
+ Mockito.anyString(), Mockito.anyString(), Mockito.anyLong(), Mockito.anyString(),
+ Mockito.eq(true), Mockito.eq(0))).thenReturn(1L);
+ CloudRuntimeException exception = Assert.assertThrows(CloudRuntimeException.class,
+ () -> backupManager.restoreBackup(backupId));
+
+ assertEquals("Unable to restore VM with the current backup as the backup has different number of disks as the VM", exception.getMessage());
+ }
+ verify(backupDao, times(1)).findById(backupId);
+ verify(vmInstanceDao, times(1)).findByIdIncludingRemoved(vmId);
+ verify(volumeDao, times(1)).findByInstance(vmId);
+ }
+}
\ No newline at end of file
From 4b86daa8b89009080d48e5a4a8811efcd473e301 Mon Sep 17 00:00:00 2001
From: Dajeong-Park
Date: Mon, 19 Jan 2026 10:29:04 +0900
Subject: [PATCH 19/34] Update BackupManagerTest.java
---
.../cloudstack/backup/BackupManagerTest.java | 60 -------------------
1 file changed, 60 deletions(-)
diff --git a/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java b/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java
index 489ac2c8213a..7f3bc99548fa 100644
--- a/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java
+++ b/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java
@@ -70,7 +70,6 @@
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VmDiskInfo;
import com.cloud.vm.VirtualMachineManager;
-import com.cloud.vm.dao.VMInstanceDetailsDao;
import com.cloud.vm.dao.VMInstanceDao;
import com.google.gson.Gson;
import org.apache.cloudstack.api.ApiConstants;
@@ -83,7 +82,6 @@
import org.apache.cloudstack.api.command.user.backup.ListBackupScheduleCmd;
import org.apache.cloudstack.api.response.BackupResponse;
import org.apache.cloudstack.backup.dao.BackupDao;
-import org.apache.cloudstack.backup.dao.BackupDetailsDao;
import org.apache.cloudstack.backup.dao.BackupOfferingDao;
import org.apache.cloudstack.backup.dao.BackupScheduleDao;
import org.apache.cloudstack.context.CallContext;
@@ -139,9 +137,6 @@ public class BackupManagerTest {
@Mock
BackupOfferingDao backupOfferingDao;
- @Mock
- BackupDetailsDao backupDetailsDao;
-
@Mock
BackupProvider backupProvider;
@@ -229,9 +224,6 @@ public class BackupManagerTest {
@Mock
private NetworkService networkService;
- @Mock
- private VMInstanceDetailsDao vmInstanceDetailsDao;
-
@Mock
AccountDao accountDao;
@@ -949,8 +941,6 @@ public void testGetBackupDetailsFromVM() {
VMInstanceDetailVO vmInstanceDetail = mock(VMInstanceDetailVO.class);
when(vmInstanceDetail.getName()).thenReturn("mocked-detail-name");
when(vmInstanceDetail.getValue()).thenReturn("mocked-detail-value");
- List vmDetails = Collections.singletonList(vmInstanceDetail);
- when(vmInstanceDetailsDao.listDetails(vmId)).thenReturn(vmDetails);
UserVmJoinVO userVmJoinVO = mock(UserVmJoinVO.class);
when(userVmJoinVO.getNetworkUuid()).thenReturn("mocked-network-uuid");
@@ -998,21 +988,6 @@ public void getDataDiskInfoListFromBackup() {
when(diskOfferingDao.findByUuid("disk-offering-uuid-1")).thenReturn(diskOffering1);
when(diskOfferingDao.findByUuid("disk-offering-uuid-2")).thenReturn(diskOffering2);
-
- List vmDiskInfoList = backupManager.getDataDiskInfoListFromBackup(backup);
-
- assertEquals(2, vmDiskInfoList.size());
- assertEquals("disk-offering-uuid-1", vmDiskInfoList.get(0).getDiskOffering().getUuid());
- assertEquals(Long.valueOf(5), vmDiskInfoList.get(0).getSize());
- assertEquals(Long.valueOf(1), vmDiskInfoList.get(0).getDeviceId());
- assertEquals(Long.valueOf(100), vmDiskInfoList.get(0).getMinIops());
- assertEquals(Long.valueOf(300), vmDiskInfoList.get(0).getMaxIops());
-
- assertEquals("disk-offering-uuid-2", vmDiskInfoList.get(1).getDiskOffering().getUuid());
- assertEquals(Long.valueOf(10), vmDiskInfoList.get(1).getSize());
- assertEquals(Long.valueOf(2), vmDiskInfoList.get(1).getDeviceId());
- assertEquals(Long.valueOf(200), vmDiskInfoList.get(1).getMinIops());
- assertEquals(Long.valueOf(400), vmDiskInfoList.get(1).getMaxIops());
}
@Test
@@ -1033,34 +1008,6 @@ public void getDataDiskInfoListFromBackupNullIops() {
when(diskOffering.getState()).thenReturn(DiskOffering.State.Active);
when(diskOfferingDao.findByUuid("disk-offering-uuid-1")).thenReturn(diskOffering);
-
- List vmDiskInfoList = backupManager.getDataDiskInfoListFromBackup(backup);
-
- assertEquals(1, vmDiskInfoList.size());
- assertEquals("disk-offering-uuid-1", vmDiskInfoList.get(0).getDiskOffering().getUuid());
- assertEquals(Long.valueOf(5), vmDiskInfoList.get(0).getSize());
- assertEquals(Long.valueOf(1), vmDiskInfoList.get(0).getDeviceId());
- assertNull(vmDiskInfoList.get(0).getMinIops());
- assertNull(vmDiskInfoList.get(0).getMaxIops());
- }
-
- @Test (expected = InvalidParameterValueException.class)
- public void testCheckVmDisksSizeAgainstBackup() {
- Long sizeInBackup = 5L * 1024 * 1024 * 1024;
- Long sizeInCmd = 2L;
- Backup backup = mock(Backup.class);
- Backup.VolumeInfo volumeInfo = mock(Backup.VolumeInfo.class);
- when(volumeInfo.getDiskOfferingId()).thenReturn("disk-offering-uuid-1");
- when(volumeInfo.getSize()).thenReturn(sizeInBackup);
- when(volumeInfo.getType()).thenReturn(Volume.Type.DATADISK);
- when(backup.getBackedUpVolumes()).thenReturn(List.of(volumeInfo));
-
- DiskOfferingVO diskOffering = mock(DiskOfferingVO.class);
- when(diskOffering.getState()).thenReturn(DiskOffering.State.Active);
- when(diskOfferingDao.findByUuid("disk-offering-uuid-1")).thenReturn(diskOffering);
- List vmDiskInfoList = List.of(new VmDiskInfo(diskOffering, sizeInCmd, 1L, null, null));
-
- backupManager.checkVmDisksSizeAgainstBackup(vmDiskInfoList, backup);
}
@Test
@@ -1586,13 +1533,6 @@ public void testNewBackupResponse() {
when(serviceOfferingDao.findByUuid(serviceOfferingUuid)).thenReturn(serviceOffering);
details.put(ApiConstants.SERVICE_OFFERING_ID, serviceOfferingUuid);
- NetworkVO network = mock(NetworkVO.class);
- when(network.getName()).thenReturn("network1");
- when(networkDao.findByUuid("network-uuid1")).thenReturn(network);
- details.put(ApiConstants.NICS, "[{\"networkid\":\"network-uuid1\"}]");
-
- Mockito.when(backupDetailsDao.listDetailsKeyPairs(backup.getId(), true)).thenReturn(details);
-
BackupResponse response = backupManager.createBackupResponse(backup, true);
Assert.assertEquals("backup-uuid", response.getId());
From ad2cbc7ab7c605ececbe7315290ca41b2d8902df Mon Sep 17 00:00:00 2001
From: Dajeong-Park
Date: Mon, 19 Jan 2026 10:31:48 +0900
Subject: [PATCH 20/34] Update BackupManagerTest.java
---
.../apache/cloudstack/backup/BackupManagerTest.java | 12 ------------
1 file changed, 12 deletions(-)
diff --git a/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java b/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java
index 7f3bc99548fa..6c226e75dd56 100644
--- a/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java
+++ b/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java
@@ -65,10 +65,8 @@
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.fsm.NoTransitionException;
-import com.cloud.vm.VMInstanceDetailVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
-import com.cloud.vm.VmDiskInfo;
import com.cloud.vm.VirtualMachineManager;
import com.cloud.vm.dao.VMInstanceDao;
import com.google.gson.Gson;
@@ -938,10 +936,6 @@ public void testGetBackupDetailsFromVM() {
when(template.getUuid()).thenReturn("template-uuid");
when(vmTemplateDao.findById(2L)).thenReturn(template);
- VMInstanceDetailVO vmInstanceDetail = mock(VMInstanceDetailVO.class);
- when(vmInstanceDetail.getName()).thenReturn("mocked-detail-name");
- when(vmInstanceDetail.getValue()).thenReturn("mocked-detail-value");
-
UserVmJoinVO userVmJoinVO = mock(UserVmJoinVO.class);
when(userVmJoinVO.getNetworkUuid()).thenReturn("mocked-network-uuid");
List userVmJoinVOs = Collections.singletonList(userVmJoinVO);
@@ -1023,12 +1017,6 @@ public void testGetRootDiskInfoFromBackup() {
DiskOfferingVO diskOffering = mock(DiskOfferingVO.class);
when(diskOffering.getUuid()).thenReturn("root-disk-offering-uuid");
when(diskOfferingDao.findByUuid("root-disk-offering-uuid")).thenReturn(diskOffering);
-
- VmDiskInfo VmDiskInfo = backupManager.getRootDiskInfoFromBackup(backup);
-
- assertEquals("root-disk-offering-uuid", VmDiskInfo.getDiskOffering().getUuid());
- assertEquals(Long.valueOf(5), VmDiskInfo.getSize());
- assertEquals(null, VmDiskInfo.getDeviceId());
}
@Test
From 1642b48eea7cbbfdbdf1ad7f813fd0157256a0a4 Mon Sep 17 00:00:00 2001
From: Dajeong-Park
Date: Mon, 19 Jan 2026 10:34:24 +0900
Subject: [PATCH 21/34] Revert "Update BackupManagerTest.java"
This reverts commit ad2cbc7ab7c605ececbe7315290ca41b2d8902df.
---
.../apache/cloudstack/backup/BackupManagerTest.java | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java b/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java
index 6c226e75dd56..7f3bc99548fa 100644
--- a/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java
+++ b/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java
@@ -65,8 +65,10 @@
import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.fsm.NoTransitionException;
+import com.cloud.vm.VMInstanceDetailVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
+import com.cloud.vm.VmDiskInfo;
import com.cloud.vm.VirtualMachineManager;
import com.cloud.vm.dao.VMInstanceDao;
import com.google.gson.Gson;
@@ -936,6 +938,10 @@ public void testGetBackupDetailsFromVM() {
when(template.getUuid()).thenReturn("template-uuid");
when(vmTemplateDao.findById(2L)).thenReturn(template);
+ VMInstanceDetailVO vmInstanceDetail = mock(VMInstanceDetailVO.class);
+ when(vmInstanceDetail.getName()).thenReturn("mocked-detail-name");
+ when(vmInstanceDetail.getValue()).thenReturn("mocked-detail-value");
+
UserVmJoinVO userVmJoinVO = mock(UserVmJoinVO.class);
when(userVmJoinVO.getNetworkUuid()).thenReturn("mocked-network-uuid");
List userVmJoinVOs = Collections.singletonList(userVmJoinVO);
@@ -1017,6 +1023,12 @@ public void testGetRootDiskInfoFromBackup() {
DiskOfferingVO diskOffering = mock(DiskOfferingVO.class);
when(diskOffering.getUuid()).thenReturn("root-disk-offering-uuid");
when(diskOfferingDao.findByUuid("root-disk-offering-uuid")).thenReturn(diskOffering);
+
+ VmDiskInfo VmDiskInfo = backupManager.getRootDiskInfoFromBackup(backup);
+
+ assertEquals("root-disk-offering-uuid", VmDiskInfo.getDiskOffering().getUuid());
+ assertEquals(Long.valueOf(5), VmDiskInfo.getSize());
+ assertEquals(null, VmDiskInfo.getDeviceId());
}
@Test
From 62e972b64771a6d0edbb64775c7814f399dac7ca Mon Sep 17 00:00:00 2001
From: Dajeong-Park
Date: Mon, 19 Jan 2026 10:34:31 +0900
Subject: [PATCH 22/34] Revert "Update BackupManagerTest.java"
This reverts commit 4b86daa8b89009080d48e5a4a8811efcd473e301.
---
.../cloudstack/backup/BackupManagerTest.java | 60 +++++++++++++++++++
1 file changed, 60 insertions(+)
diff --git a/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java b/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java
index 7f3bc99548fa..489ac2c8213a 100644
--- a/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java
+++ b/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java
@@ -70,6 +70,7 @@
import com.cloud.vm.VirtualMachine;
import com.cloud.vm.VmDiskInfo;
import com.cloud.vm.VirtualMachineManager;
+import com.cloud.vm.dao.VMInstanceDetailsDao;
import com.cloud.vm.dao.VMInstanceDao;
import com.google.gson.Gson;
import org.apache.cloudstack.api.ApiConstants;
@@ -82,6 +83,7 @@
import org.apache.cloudstack.api.command.user.backup.ListBackupScheduleCmd;
import org.apache.cloudstack.api.response.BackupResponse;
import org.apache.cloudstack.backup.dao.BackupDao;
+import org.apache.cloudstack.backup.dao.BackupDetailsDao;
import org.apache.cloudstack.backup.dao.BackupOfferingDao;
import org.apache.cloudstack.backup.dao.BackupScheduleDao;
import org.apache.cloudstack.context.CallContext;
@@ -137,6 +139,9 @@ public class BackupManagerTest {
@Mock
BackupOfferingDao backupOfferingDao;
+ @Mock
+ BackupDetailsDao backupDetailsDao;
+
@Mock
BackupProvider backupProvider;
@@ -224,6 +229,9 @@ public class BackupManagerTest {
@Mock
private NetworkService networkService;
+ @Mock
+ private VMInstanceDetailsDao vmInstanceDetailsDao;
+
@Mock
AccountDao accountDao;
@@ -941,6 +949,8 @@ public void testGetBackupDetailsFromVM() {
VMInstanceDetailVO vmInstanceDetail = mock(VMInstanceDetailVO.class);
when(vmInstanceDetail.getName()).thenReturn("mocked-detail-name");
when(vmInstanceDetail.getValue()).thenReturn("mocked-detail-value");
+ List vmDetails = Collections.singletonList(vmInstanceDetail);
+ when(vmInstanceDetailsDao.listDetails(vmId)).thenReturn(vmDetails);
UserVmJoinVO userVmJoinVO = mock(UserVmJoinVO.class);
when(userVmJoinVO.getNetworkUuid()).thenReturn("mocked-network-uuid");
@@ -988,6 +998,21 @@ public void getDataDiskInfoListFromBackup() {
when(diskOfferingDao.findByUuid("disk-offering-uuid-1")).thenReturn(diskOffering1);
when(diskOfferingDao.findByUuid("disk-offering-uuid-2")).thenReturn(diskOffering2);
+
+ List vmDiskInfoList = backupManager.getDataDiskInfoListFromBackup(backup);
+
+ assertEquals(2, vmDiskInfoList.size());
+ assertEquals("disk-offering-uuid-1", vmDiskInfoList.get(0).getDiskOffering().getUuid());
+ assertEquals(Long.valueOf(5), vmDiskInfoList.get(0).getSize());
+ assertEquals(Long.valueOf(1), vmDiskInfoList.get(0).getDeviceId());
+ assertEquals(Long.valueOf(100), vmDiskInfoList.get(0).getMinIops());
+ assertEquals(Long.valueOf(300), vmDiskInfoList.get(0).getMaxIops());
+
+ assertEquals("disk-offering-uuid-2", vmDiskInfoList.get(1).getDiskOffering().getUuid());
+ assertEquals(Long.valueOf(10), vmDiskInfoList.get(1).getSize());
+ assertEquals(Long.valueOf(2), vmDiskInfoList.get(1).getDeviceId());
+ assertEquals(Long.valueOf(200), vmDiskInfoList.get(1).getMinIops());
+ assertEquals(Long.valueOf(400), vmDiskInfoList.get(1).getMaxIops());
}
@Test
@@ -1008,6 +1033,34 @@ public void getDataDiskInfoListFromBackupNullIops() {
when(diskOffering.getState()).thenReturn(DiskOffering.State.Active);
when(diskOfferingDao.findByUuid("disk-offering-uuid-1")).thenReturn(diskOffering);
+
+ List vmDiskInfoList = backupManager.getDataDiskInfoListFromBackup(backup);
+
+ assertEquals(1, vmDiskInfoList.size());
+ assertEquals("disk-offering-uuid-1", vmDiskInfoList.get(0).getDiskOffering().getUuid());
+ assertEquals(Long.valueOf(5), vmDiskInfoList.get(0).getSize());
+ assertEquals(Long.valueOf(1), vmDiskInfoList.get(0).getDeviceId());
+ assertNull(vmDiskInfoList.get(0).getMinIops());
+ assertNull(vmDiskInfoList.get(0).getMaxIops());
+ }
+
+ @Test (expected = InvalidParameterValueException.class)
+ public void testCheckVmDisksSizeAgainstBackup() {
+ Long sizeInBackup = 5L * 1024 * 1024 * 1024;
+ Long sizeInCmd = 2L;
+ Backup backup = mock(Backup.class);
+ Backup.VolumeInfo volumeInfo = mock(Backup.VolumeInfo.class);
+ when(volumeInfo.getDiskOfferingId()).thenReturn("disk-offering-uuid-1");
+ when(volumeInfo.getSize()).thenReturn(sizeInBackup);
+ when(volumeInfo.getType()).thenReturn(Volume.Type.DATADISK);
+ when(backup.getBackedUpVolumes()).thenReturn(List.of(volumeInfo));
+
+ DiskOfferingVO diskOffering = mock(DiskOfferingVO.class);
+ when(diskOffering.getState()).thenReturn(DiskOffering.State.Active);
+ when(diskOfferingDao.findByUuid("disk-offering-uuid-1")).thenReturn(diskOffering);
+ List vmDiskInfoList = List.of(new VmDiskInfo(diskOffering, sizeInCmd, 1L, null, null));
+
+ backupManager.checkVmDisksSizeAgainstBackup(vmDiskInfoList, backup);
}
@Test
@@ -1533,6 +1586,13 @@ public void testNewBackupResponse() {
when(serviceOfferingDao.findByUuid(serviceOfferingUuid)).thenReturn(serviceOffering);
details.put(ApiConstants.SERVICE_OFFERING_ID, serviceOfferingUuid);
+ NetworkVO network = mock(NetworkVO.class);
+ when(network.getName()).thenReturn("network1");
+ when(networkDao.findByUuid("network-uuid1")).thenReturn(network);
+ details.put(ApiConstants.NICS, "[{\"networkid\":\"network-uuid1\"}]");
+
+ Mockito.when(backupDetailsDao.listDetailsKeyPairs(backup.getId(), true)).thenReturn(details);
+
BackupResponse response = backupManager.createBackupResponse(backup, true);
Assert.assertEquals("backup-uuid", response.getId());
From b27cb6d28ab93840da6544de5314475e4d5523a8 Mon Sep 17 00:00:00 2001
From: Dajeong-Park
Date: Mon, 19 Jan 2026 10:34:36 +0900
Subject: [PATCH 23/34] Revert "Update BackupManagerTest.java"
This reverts commit c90bc9f9dfba80706e16317495d7bb2e5e00bbc9.
---
.../cloudstack/backup/BackupManagerTest.java | 1335 +----------------
1 file changed, 75 insertions(+), 1260 deletions(-)
diff --git a/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java b/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java
index 489ac2c8213a..88892d982d87 100644
--- a/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java
+++ b/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java
@@ -16,41 +16,18 @@
// under the License.
package org.apache.cloudstack.backup;
-import com.cloud.api.query.dao.UserVmJoinDao;
-import com.cloud.api.query.vo.UserVmJoinVO;
import com.cloud.alert.AlertManager;
-import com.cloud.capacity.CapacityVO;
import com.cloud.configuration.Resource;
-import com.cloud.dc.DataCenter;
import com.cloud.dc.DataCenterVO;
import com.cloud.dc.dao.DataCenterDao;
import com.cloud.domain.Domain;
-import com.cloud.domain.DomainVO;
-import com.cloud.domain.dao.DomainDao;
import com.cloud.event.ActionEventUtils;
-import com.cloud.event.EventTypes;
import com.cloud.event.UsageEventUtils;
import com.cloud.exception.InvalidParameterValueException;
-import com.cloud.host.HostVO;
-import com.cloud.host.dao.HostDao;
-import com.cloud.hypervisor.Hypervisor;
-import com.cloud.network.Network;
-import com.cloud.network.NetworkService;
-import com.cloud.network.dao.NetworkDao;
-import com.cloud.network.dao.NetworkVO;
-import com.cloud.offering.DiskOffering;
-import com.cloud.service.ServiceOfferingVO;
-import com.cloud.service.dao.ServiceOfferingDao;
-import com.cloud.storage.DiskOfferingVO;
import com.cloud.exception.ResourceAllocationException;
-import com.cloud.storage.Storage;
-import com.cloud.storage.VMTemplateVO;
import com.cloud.storage.Volume;
import com.cloud.storage.VolumeApiService;
import com.cloud.storage.VolumeVO;
-import com.cloud.storage.dao.DiskOfferingDao;
-import com.cloud.storage.dao.GuestOSDao;
-import com.cloud.storage.dao.VMTemplateDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.user.Account;
import com.cloud.user.AccountManager;
@@ -58,39 +35,27 @@
import com.cloud.user.DomainManager;
import com.cloud.user.ResourceLimitService;
import com.cloud.user.User;
-import com.cloud.user.dao.AccountDao;
+import com.cloud.user.UserVO;
import com.cloud.utils.DateUtil;
import com.cloud.utils.Pair;
-import com.cloud.utils.db.SearchBuilder;
-import com.cloud.utils.db.SearchCriteria;
import com.cloud.utils.exception.CloudRuntimeException;
import com.cloud.utils.fsm.NoTransitionException;
-import com.cloud.vm.VMInstanceDetailVO;
import com.cloud.vm.VMInstanceVO;
import com.cloud.vm.VirtualMachine;
-import com.cloud.vm.VmDiskInfo;
import com.cloud.vm.VirtualMachineManager;
-import com.cloud.vm.dao.VMInstanceDetailsDao;
import com.cloud.vm.dao.VMInstanceDao;
import com.google.gson.Gson;
import org.apache.cloudstack.api.ApiConstants;
import org.apache.cloudstack.api.ServerApiException;
-import org.apache.cloudstack.api.command.admin.backup.ImportBackupOfferingCmd;
import org.apache.cloudstack.api.command.admin.backup.UpdateBackupOfferingCmd;
-import org.apache.cloudstack.api.command.user.backup.CreateBackupCmd;
import org.apache.cloudstack.api.command.user.backup.CreateBackupScheduleCmd;
import org.apache.cloudstack.api.command.user.backup.DeleteBackupScheduleCmd;
-import org.apache.cloudstack.api.command.user.backup.ListBackupScheduleCmd;
-import org.apache.cloudstack.api.response.BackupResponse;
import org.apache.cloudstack.backup.dao.BackupDao;
-import org.apache.cloudstack.backup.dao.BackupDetailsDao;
import org.apache.cloudstack.backup.dao.BackupOfferingDao;
import org.apache.cloudstack.backup.dao.BackupScheduleDao;
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.framework.config.ConfigKey;
import org.apache.cloudstack.framework.config.impl.ConfigDepotImpl;
-import org.apache.cloudstack.storage.datastore.db.PrimaryDataStoreDao;
-import org.apache.cloudstack.storage.datastore.db.StoragePoolVO;
import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO;
import org.junit.After;
import org.junit.Assert;
@@ -111,7 +76,6 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
-import java.util.Optional;
import java.util.TimeZone;
import java.util.UUID;
@@ -121,14 +85,10 @@
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
-import static org.mockito.Mockito.atLeastOnce;
@RunWith(MockitoJUnitRunner.class)
public class BackupManagerTest {
@@ -139,9 +99,6 @@ public class BackupManagerTest {
@Mock
BackupOfferingDao backupOfferingDao;
- @Mock
- BackupDetailsDao backupDetailsDao;
-
@Mock
BackupProvider backupProvider;
@@ -181,6 +138,8 @@ public class BackupManagerTest {
@Mock
private Domain domainMock;
+ private AccountVO account;
+
@Mock
private VMInstanceVO vmInstanceVOMock;
@@ -205,41 +164,7 @@ public class BackupManagerTest {
@Mock
private DeleteBackupScheduleCmd deleteBackupScheduleCmdMock;
- @Mock
- DiskOfferingDao diskOfferingDao;
-
- @Mock
- ServiceOfferingDao serviceOfferingDao;
-
- @Mock
- VMTemplateDao vmTemplateDao;
-
- @Mock
- UserVmJoinDao userVmJoinDao;
-
- @Mock
- PrimaryDataStoreDao primaryDataStoreDao;
-
- @Mock
- HostDao hostDao;
-
- @Mock
- private NetworkDao networkDao;
-
- @Mock
- private NetworkService networkService;
-
- @Mock
- private VMInstanceDetailsDao vmInstanceDetailsDao;
-
- @Mock
- AccountDao accountDao;
-
- @Mock
- DomainDao domainDao;
-
- @Mock
- private GuestOSDao _guestOSDao;
+ private UserVO user;
private Gson gson;
@@ -273,12 +198,6 @@ public void setup() throws Exception {
return true;
});
- backupProvider = mock(BackupProvider.class);
- when(backupProvider.getName()).thenReturn("testbackupprovider");
- Map backupProvidersMap = new HashMap<>();
- backupProvidersMap.put(backupProvider.getName().toLowerCase(), backupProvider);
- ReflectionTestUtils.setField(backupManager, "backupProvidersMap", backupProvidersMap);
-
Account account = mock(Account.class);
User user = mock(User.class);
CallContext.register(user, account);
@@ -293,20 +212,6 @@ public void tearDown() throws Exception {
CallContext.unregister();
}
- private void overrideBackupFrameworkConfigValue() {
- ConfigKey configKey = BackupManager.BackupFrameworkEnabled;
- this.configDepotImpl = (ConfigDepotImpl) ReflectionTestUtils.getField(configKey, "s_depot");
- ConfigDepotImpl configDepot = Mockito.mock(ConfigDepotImpl.class);
- Mockito.when(configDepot.getConfigStringValue(Mockito.eq(BackupManager.BackupFrameworkEnabled.key()),
- Mockito.eq(ConfigKey.Scope.Global), Mockito.isNull())).thenReturn("true");
- Mockito.when(configDepot.getConfigStringValue(Mockito.eq(BackupManager.BackupFrameworkEnabled.key()),
- Mockito.eq(ConfigKey.Scope.Zone), Mockito.anyLong())).thenReturn("true");
- Mockito.when(configDepot.getConfigStringValue(Mockito.eq(BackupManager.BackupProviderPlugin.key()),
- Mockito.eq(ConfigKey.Scope.Zone), Mockito.anyLong())).thenReturn("testbackupprovider");
- ReflectionTestUtils.setField(configKey, "s_depot", configDepot);
- updatedConfigKeyDepot = true;
- }
-
@Test
public void testExceptionWhenUpdateWithNullId() {
try {
@@ -321,7 +226,7 @@ public void testExceptionWhenUpdateWithNullId() {
}
}
- @Test(expected = InvalidParameterValueException.class)
+ @Test (expected = InvalidParameterValueException.class)
public void testExceptionWhenUpdateWithNonExistentId() {
Long id = 123l;
@@ -331,7 +236,7 @@ public void testExceptionWhenUpdateWithNonExistentId() {
backupManager.updateBackupOffering(cmd);
}
- @Test(expected = ServerApiException.class)
+ @Test (expected = ServerApiException.class)
public void testExceptionWhenUpdateWithoutChanges() {
UpdateBackupOfferingCmd cmd = Mockito.spy(UpdateBackupOfferingCmd.class);
when(cmd.getName()).thenReturn(null);
@@ -362,117 +267,96 @@ public void testUpdateBackupOfferingSuccess() {
@Test
public void restoreBackedUpVolumeTestHostIpAndDatastoreUuid() {
BackupVO backupVO = new BackupVO();
- VMInstanceVO vm = mock(VMInstanceVO.class);
+ VMInstanceVO vm = Mockito.mock(VMInstanceVO.class);
String volumeUuid = "5f4ed903-ac23-4f8a-b595-69c73c40593f";
String vmName = "i-2-3-VM";
VirtualMachine.State vmState = VirtualMachine.State.Running;
Mockito.when(vm.getName()).thenReturn(vmName);
Mockito.when(vm.getState()).thenReturn(vmState);
- Pair vmNameAndState = new Pair<>(vmName, vmState);
-
- Backup.VolumeInfo volumeInfo = mock(Backup.VolumeInfo.class);
- when(volumeInfo.getUuid()).thenReturn(volumeUuid);
+ Pair vmNameAndState = new Pair<>("i-2-3-VM", VirtualMachine.State.Running);
- doReturn(new Pair(Boolean.TRUE, "Success"))
- .when(backupProvider).restoreBackedUpVolume(any(Backup.class), any(Backup.VolumeInfo.class),
- any(String.class), any(String.class), any(Pair.class));
-
- Pair restoreBackedUpVolume = backupManager.restoreBackedUpVolume(volumeInfo, backupVO, backupProvider, hostPossibleValues, datastoresPossibleValues, vm);
+ Mockito.when(backupProvider.restoreBackedUpVolume(Mockito.any(), Mockito.eq(volumeUuid),
+ Mockito.eq("127.0.0.1"), Mockito.eq("e9804933-8609-4de3-bccc-6278072a496c"), Mockito.eq(vmNameAndState))).thenReturn(new Pair(Boolean.TRUE, "Success"));
+ Pair restoreBackedUpVolume = backupManager.restoreBackedUpVolume(volumeUuid, backupVO, backupProvider, hostPossibleValues, datastoresPossibleValues, vm);
assertEquals(Boolean.TRUE, restoreBackedUpVolume.first());
assertEquals("Success", restoreBackedUpVolume.second());
- verify(backupProvider, atLeastOnce()).restoreBackedUpVolume(any(Backup.class), any(Backup.VolumeInfo.class),
- any(String.class), any(String.class), any(Pair.class));
+ Mockito.verify(backupProvider, times(1)).restoreBackedUpVolume(Mockito.any(), Mockito.anyString(),
+ Mockito.anyString(), Mockito.anyString(), any(Pair.class));
}
@Test
public void restoreBackedUpVolumeTestHostIpAndDatastoreName() {
BackupVO backupVO = new BackupVO();
- VMInstanceVO vm = mock(VMInstanceVO.class);
+ VMInstanceVO vm = Mockito.mock(VMInstanceVO.class);
String volumeUuid = "5f4ed903-ac23-4f8a-b595-69c73c40593f";
String vmName = "i-2-3-VM";
VirtualMachine.State vmState = VirtualMachine.State.Running;
Mockito.when(vm.getName()).thenReturn(vmName);
Mockito.when(vm.getState()).thenReturn(vmState);
- Pair vmNameAndState = new Pair<>(vmName, vmState);
-
- Backup.VolumeInfo volumeInfo = mock(Backup.VolumeInfo.class);
- when(volumeInfo.getUuid()).thenReturn(volumeUuid);
-
- doReturn(new Pair(Boolean.TRUE, "Success2"))
- .when(backupProvider).restoreBackedUpVolume(any(Backup.class), any(Backup.VolumeInfo.class),
- any(String.class), any(String.class), any(Pair.class));
-
- Pair restoreBackedUpVolume = backupManager.restoreBackedUpVolume(volumeInfo, backupVO, backupProvider, hostPossibleValues, datastoresPossibleValues, vm);
+ Pair vmNameAndState = new Pair<>("i-2-3-VM", VirtualMachine.State.Running);
+ Mockito.when(backupProvider.restoreBackedUpVolume(Mockito.any(), Mockito.eq(volumeUuid),
+ Mockito.eq("127.0.0.1"), Mockito.eq("datastore-name"), Mockito.eq(vmNameAndState))).thenReturn(new Pair(Boolean.TRUE, "Success2"));
+ Pair restoreBackedUpVolume = backupManager.restoreBackedUpVolume(volumeUuid, backupVO, backupProvider, hostPossibleValues, datastoresPossibleValues, vm);
assertEquals(Boolean.TRUE, restoreBackedUpVolume.first());
assertEquals("Success2", restoreBackedUpVolume.second());
- verify(backupProvider, atLeastOnce()).restoreBackedUpVolume(any(Backup.class), any(Backup.VolumeInfo.class),
- any(String.class), any(String.class), any(Pair.class));
+ Mockito.verify(backupProvider, times(2)).restoreBackedUpVolume(Mockito.any(), Mockito.anyString(),
+ Mockito.anyString(), Mockito.anyString(), any(Pair.class));
}
@Test
public void restoreBackedUpVolumeTestHostNameAndDatastoreUuid() {
BackupVO backupVO = new BackupVO();
- VMInstanceVO vm = mock(VMInstanceVO.class);
+ VMInstanceVO vm = Mockito.mock(VMInstanceVO.class);
String volumeUuid = "5f4ed903-ac23-4f8a-b595-69c73c40593f";
String vmName = "i-2-3-VM";
VirtualMachine.State vmState = VirtualMachine.State.Running;
Mockito.when(vm.getName()).thenReturn(vmName);
Mockito.when(vm.getState()).thenReturn(vmState);
- Pair vmNameAndState = new Pair<>(vmName, vmState);
+ Pair vmNameAndState = new Pair<>("i-2-3-VM", VirtualMachine.State.Running);
- Backup.VolumeInfo volumeInfo = mock(Backup.VolumeInfo.class);
- when(volumeInfo.getUuid()).thenReturn(volumeUuid);
-
- doReturn(new Pair(Boolean.TRUE, "Success3"))
- .when(backupProvider).restoreBackedUpVolume(any(Backup.class), any(Backup.VolumeInfo.class),
- any(String.class), any(String.class), any(Pair.class));
-
- Pair restoreBackedUpVolume = backupManager.restoreBackedUpVolume(volumeInfo, backupVO, backupProvider, hostPossibleValues, datastoresPossibleValues, vm);
+ Mockito.when(backupProvider.restoreBackedUpVolume(Mockito.any(), Mockito.eq(volumeUuid),
+ Mockito.eq("hostname"), Mockito.eq("e9804933-8609-4de3-bccc-6278072a496c"), Mockito.eq(vmNameAndState))).thenReturn(new Pair(Boolean.TRUE, "Success3"));
+ Pair restoreBackedUpVolume = backupManager.restoreBackedUpVolume(volumeUuid, backupVO, backupProvider, hostPossibleValues, datastoresPossibleValues, vm);
assertEquals(Boolean.TRUE, restoreBackedUpVolume.first());
assertEquals("Success3", restoreBackedUpVolume.second());
- verify(backupProvider, atLeastOnce()).restoreBackedUpVolume(any(Backup.class), any(Backup.VolumeInfo.class),
- any(String.class), any(String.class), any(Pair.class));
+ Mockito.verify(backupProvider, times(3)).restoreBackedUpVolume(Mockito.any(), Mockito.anyString(),
+ Mockito.anyString(), Mockito.anyString(), any(Pair.class));
}
@Test
public void restoreBackedUpVolumeTestHostAndDatastoreName() {
BackupVO backupVO = new BackupVO();
- VMInstanceVO vm = mock(VMInstanceVO.class);
+ VMInstanceVO vm = Mockito.mock(VMInstanceVO.class);
String volumeUuid = "5f4ed903-ac23-4f8a-b595-69c73c40593f";
String vmName = "i-2-3-VM";
VirtualMachine.State vmState = VirtualMachine.State.Running;
Mockito.when(vm.getName()).thenReturn(vmName);
Mockito.when(vm.getState()).thenReturn(vmState);
- Pair vmNameAndState = new Pair<>(vmName, vmState);
+ Pair vmNameAndState = new Pair<>("i-2-3-VM", VirtualMachine.State.Running);
- Backup.VolumeInfo volumeInfo = mock(Backup.VolumeInfo.class);
- when(volumeInfo.getUuid()).thenReturn(volumeUuid);
-
- doReturn(new Pair(Boolean.TRUE, "Success4"))
- .when(backupProvider).restoreBackedUpVolume(any(Backup.class), any(Backup.VolumeInfo.class),
- any(String.class), any(String.class), any(Pair.class));
-
- Pair restoreBackedUpVolume = backupManager.restoreBackedUpVolume(volumeInfo, backupVO, backupProvider, hostPossibleValues, datastoresPossibleValues, vm);
+ Mockito.when(backupProvider.restoreBackedUpVolume(Mockito.any(), Mockito.eq(volumeUuid),
+ Mockito.eq("hostname"), Mockito.eq("datastore-name"), Mockito.eq(vmNameAndState))).thenReturn(new Pair(Boolean.TRUE, "Success4"));
+ Pair restoreBackedUpVolume = backupManager.restoreBackedUpVolume(volumeUuid, backupVO, backupProvider, hostPossibleValues, datastoresPossibleValues, vm);
assertEquals(Boolean.TRUE, restoreBackedUpVolume.first());
assertEquals("Success4", restoreBackedUpVolume.second());
- verify(backupProvider, atLeastOnce()).restoreBackedUpVolume(any(Backup.class), any(Backup.VolumeInfo.class),
- any(String.class), any(String.class), any(Pair.class));
+ Mockito.verify(backupProvider, times(4)).restoreBackedUpVolume(Mockito.any(), Mockito.anyString(),
+ Mockito.anyString(), Mockito.anyString(), any(Pair.class));
}
@Test
public void tryRestoreVMTestRestoreSucceeded() throws NoTransitionException {
- BackupOffering offering = mock(BackupOffering.class);
- VolumeVO volumeVO = mock(VolumeVO.class);
- VMInstanceVO vm = mock(VMInstanceVO.class);
- BackupVO backup = mock(BackupVO.class);
+ BackupOffering offering = Mockito.mock(BackupOffering.class);
+ VolumeVO volumeVO = Mockito.mock(VolumeVO.class);
+ VMInstanceVO vm = Mockito.mock(VMInstanceVO.class);
+ BackupVO backup = Mockito.mock(BackupVO.class);
try (MockedStatic utils = Mockito.mockStatic(ActionEventUtils.class)) {
Mockito.when(ActionEventUtils.onStartedActionEvent(Mockito.anyLong(), Mockito.anyLong(),
@@ -497,10 +381,10 @@ public void tryRestoreVMTestRestoreSucceeded() throws NoTransitionException {
@Test
public void tryRestoreVMTestRestoreFails() throws NoTransitionException {
- BackupOffering offering = mock(BackupOffering.class);
- VolumeVO volumeVO = mock(VolumeVO.class);
- VMInstanceVO vm = mock(VMInstanceVO.class);
- BackupVO backup = mock(BackupVO.class);
+ BackupOffering offering = Mockito.mock(BackupOffering.class);
+ VolumeVO volumeVO = Mockito.mock(VolumeVO.class);
+ VMInstanceVO vm = Mockito.mock(VMInstanceVO.class);
+ BackupVO backup = Mockito.mock(BackupVO.class);
try (MockedStatic utils = Mockito.mockStatic(ActionEventUtils.class)) {
Mockito.when(ActionEventUtils.onStartedActionEvent(Mockito.anyLong(), Mockito.anyLong(),
@@ -529,6 +413,20 @@ public void tryRestoreVMTestRestoreFails() throws NoTransitionException {
}
}
+ private void overrideBackupFrameworkConfigValue() {
+ ConfigKey configKey = BackupManager.BackupFrameworkEnabled;
+ this.configDepotImpl = (ConfigDepotImpl) ReflectionTestUtils.getField(configKey, "s_depot");
+ ConfigDepotImpl configDepot = Mockito.mock(ConfigDepotImpl.class);
+ Mockito.when(configDepot.getConfigStringValue(Mockito.eq(BackupManager.BackupFrameworkEnabled.key()),
+ Mockito.eq(ConfigKey.Scope.Global), Mockito.isNull())).thenReturn("true");
+ Mockito.when(configDepot.getConfigStringValue(Mockito.eq(BackupManager.BackupFrameworkEnabled.key()),
+ Mockito.eq(ConfigKey.Scope.Zone), Mockito.anyLong())).thenReturn("true");
+ Mockito.when(configDepot.getConfigStringValue(Mockito.eq(BackupManager.BackupProviderPlugin.key()),
+ Mockito.eq(ConfigKey.Scope.Zone), Mockito.anyLong())).thenReturn("testbackupprovider");
+ ReflectionTestUtils.setField(configKey, "s_depot", configDepot);
+ updatedConfigKeyDepot = true;
+ }
+
@Test
public void testConfigureBackupSchedule() {
Long vmId = 1L;
@@ -543,7 +441,6 @@ public void testConfigureBackupSchedule() {
when(cmd.getIntervalType()).thenReturn(DateUtil.IntervalType.DAILY);
when(cmd.getMaxBackups()).thenReturn(8);
when(cmd.getSchedule()).thenReturn("00:00:00");
- when(cmd.getQuiesceVM()).thenReturn(null);
VMInstanceVO vm = Mockito.mock(VMInstanceVO.class);
when(vmInstanceDao.findById(vmId)).thenReturn(vm);
@@ -619,9 +516,7 @@ public void createBackupTestCreateScheduledBackup() throws ResourceAllocationExc
Long backupOfferingId = 4L;
Long accountId = 5L;
Long backupId = 6L;
- Long oldestBackupId = 7L;
Long newBackupSize = 1000000000L;
- Long oldBackupSize = 400000000L;
when(vmInstanceDao.findById(vmId)).thenReturn(vmInstanceVOMock);
when(vmInstanceVOMock.getDataCenterId()).thenReturn(zoneId);
@@ -631,7 +526,7 @@ public void createBackupTestCreateScheduledBackup() throws ResourceAllocationExc
overrideBackupFrameworkConfigValue();
when(backupOfferingDao.findById(backupOfferingId)).thenReturn(backupOfferingVOMock);
when(backupOfferingVOMock.isUserDrivenBackupAllowed()).thenReturn(true);
- when(backupOfferingVOMock.getProvider()).thenReturn("testbackupprovider");
+ when(backupOfferingVOMock.getProvider()).thenReturn("test");
Mockito.doReturn(scheduleId).when(backupManager).getBackupScheduleId(asyncJobVOMock);
@@ -641,45 +536,31 @@ public void createBackupTestCreateScheduledBackup() throws ResourceAllocationExc
when(backupScheduleDao.findById(scheduleId)).thenReturn(schedule);
when(schedule.getMaxBackups()).thenReturn(2);
- VolumeVO volume = mock(VolumeVO.class);
- when(volumeDao.findByInstance(vmId)).thenReturn(List.of(volume));
- when(volume.getState()).thenReturn(Volume.State.Ready);
- when(volumeApiService.getVolumePhysicalSize(null, null, null)).thenReturn(newBackupSize);
-
BackupProvider backupProvider = mock(BackupProvider.class);
Backup backup = mock(Backup.class);
when(backup.getId()).thenReturn(backupId);
when(backup.getSize()).thenReturn(newBackupSize);
- when(backupProvider.getName()).thenReturn("testbackupprovider");
- when(backupProvider.takeBackup(vmInstanceVOMock, null)).thenReturn(new Pair<>(true, backup));
+ when(backupProvider.getName()).thenReturn("test");
+ when(backupProvider.takeBackup(vmInstanceVOMock)).thenReturn(new Pair<>(true, backup));
Map backupProvidersMap = new HashMap<>();
backupProvidersMap.put(backupProvider.getName().toLowerCase(), backupProvider);
ReflectionTestUtils.setField(backupManager, "backupProvidersMap", backupProvidersMap);
BackupVO backupVO = mock(BackupVO.class);
when(backupVO.getId()).thenReturn(backupId);
- BackupVO oldestBackupVO = mock(BackupVO.class);
+ BackupVO oldestBackupVO = mock(BackupVO.class);;
when(backupDao.findById(backupId)).thenReturn(backupVO);
List backups = new ArrayList<>(List.of(oldestBackupVO));
when(backupDao.listBySchedule(scheduleId)).thenReturn(backups);
- CreateBackupCmd cmd = Mockito.mock(CreateBackupCmd.class);
- when(cmd.getVmId()).thenReturn(vmId);
- when(cmd.getName()).thenReturn("new-backup1");
- when(cmd.getQuiesceVM()).thenReturn(null);
-
try (MockedStatic ignored = Mockito.mockStatic(ActionEventUtils.class)) {
Mockito.when(ActionEventUtils.onActionEvent(Mockito.anyLong(), Mockito.anyLong(),
Mockito.anyLong(),
Mockito.anyString(), Mockito.anyString(),
Mockito.anyLong(), Mockito.anyString())).thenReturn(1L);
- assertTrue(backupManager.createBackup(cmd, asyncJobVOMock));
-
- Mockito.verify(resourceLimitMgr, times(1)).checkResourceLimit(accountVOMock, Resource.ResourceType.backup);
- Mockito.verify(resourceLimitMgr, times(1)).checkResourceLimit(accountVOMock, Resource.ResourceType.backup_storage, newBackupSize);
-
+ assertTrue(backupManager.createBackup(vmId, asyncJobVOMock));
Mockito.verify(resourceLimitMgr, times(1)).incrementResourceCount(accountId, Resource.ResourceType.backup);
Mockito.verify(resourceLimitMgr, times(1)).incrementResourceCount(accountId, Resource.ResourceType.backup_storage, newBackupSize);
Mockito.verify(backupDao, times(1)).update(backupVO.getId(), backupVO);
@@ -704,46 +585,6 @@ public void createBackupTestResourceLimitReached() throws ResourceAllocationExce
BackupOfferingVO offering = Mockito.mock(BackupOfferingVO.class);
when(backupOfferingDao.findById(backupOfferingId)).thenReturn(offering);
when(offering.isUserDrivenBackupAllowed()).thenReturn(true);
- when(offering.getProvider()).thenReturn("testbackupprovider");
-
- Account account = Mockito.mock(Account.class);
- when(accountManager.getAccount(accountId)).thenReturn(account);
- Mockito.doThrow(new ResourceAllocationException("", Resource.ResourceType.backup)).when(resourceLimitMgr).checkResourceLimit(account, Resource.ResourceType.backup);
-
- CreateBackupCmd cmd = Mockito.mock(CreateBackupCmd.class);
- when(cmd.getVmId()).thenReturn(vmId);
- when(cmd.getQuiesceVM()).thenReturn(null);
-
- String jobParams = "{}";
- when(asyncJobVOMock.getCmdInfo()).thenReturn(jobParams);
- when(asyncJobVOMock.getId()).thenReturn(1L);
-
- backupManager.createBackup(cmd, asyncJobVOMock);
-
- String msg = "Backup storage space resource limit exceeded for account id : " + accountId + ". Failed to create backup";
- Mockito.verify(alertManagerMock, times(1)).sendAlert(AlertManager.AlertType.ALERT_TYPE_UPDATE_RESOURCE_COUNT, 0L, 0L, msg, "Backup resource limit exceeded for account id : " + accountId
- + ". Failed to create backups; please use updateResourceLimit to increase the limit");
- }
-
- @Test (expected = ResourceAllocationException.class)
- public void testCreateBackupStorageLimitReached() throws ResourceAllocationException {
- Long vmId = 1L;
- Long zoneId = 2L;
- Long scheduleId = 3L;
- Long backupOfferingId = 4L;
- Long accountId = 5L;
-
- VMInstanceVO vm = Mockito.mock(VMInstanceVO.class);
- when(vmInstanceDao.findById(vmId)).thenReturn(vm);
- when(vm.getDataCenterId()).thenReturn(zoneId);
- when(vm.getBackupOfferingId()).thenReturn(backupOfferingId);
- when(vm.getAccountId()).thenReturn(accountId);
-
- overrideBackupFrameworkConfigValue();
- BackupOfferingVO offering = Mockito.mock(BackupOfferingVO.class);
- when(backupOfferingDao.findById(backupOfferingId)).thenReturn(offering);
- when(offering.isUserDrivenBackupAllowed()).thenReturn(true);
- when(offering.getProvider()).thenReturn("testbackupprovider");
Mockito.doReturn(scheduleId).when(backupManager).getBackupScheduleId(asyncJobVOMock);
@@ -751,15 +592,7 @@ public void testCreateBackupStorageLimitReached() throws ResourceAllocationExcep
when(accountManager.getAccount(accountId)).thenReturn(account);
Mockito.doThrow(new ResourceAllocationException("", Resource.ResourceType.backup_storage)).when(resourceLimitMgr).checkResourceLimit(account, Resource.ResourceType.backup_storage, 0L);
- CreateBackupCmd cmd = Mockito.mock(CreateBackupCmd.class);
- when(cmd.getVmId()).thenReturn(vmId);
- when(cmd.getQuiesceVM()).thenReturn(null);
-
- backupManager.createBackup(cmd, asyncJobVOMock);
-
- String msg = "Backup storage space resource limit exceeded for account id : " + accountId + ". Failed to create backup";
- Mockito.verify(alertManagerMock, times(1)).sendAlert(AlertManager.AlertType.ALERT_TYPE_UPDATE_RESOURCE_COUNT, 0L, 0L, msg, "Backup storage space resource limit exceeded for account id : " + accountId
- + ". Failed to create backups; please use updateResourceLimit to increase the limit");
+ backupManager.createBackup(vmId, asyncJobVOMock);
}
@Test
@@ -772,7 +605,7 @@ public void testBackupSyncTask() {
Long backup1Size = 1 * Resource.ResourceType.bytesToGiB;
Long backup2Size = 2 * Resource.ResourceType.bytesToGiB;
Long newBackupSize = 3 * Resource.ResourceType.bytesToGiB;
- Long restorePointSize = 4 * Resource.ResourceType.bytesToGiB;
+ Long metricSize = 4 * Resource.ResourceType.bytesToGiB;
overrideBackupFrameworkConfigValue();
@@ -788,23 +621,23 @@ public void testBackupSyncTask() {
VMInstanceVO vm = Mockito.mock(VMInstanceVO.class);
when(vm.getId()).thenReturn(vmId);
when(vm.getAccountId()).thenReturn(accountId);
- List vmIds = List.of(vmId);
- when(backupDao.listVmIdsWithBackupsInZone(dataCenterId)).thenReturn(vmIds);
- when(vmInstanceDao.listByZoneAndBackupOffering(dataCenterId, null)).thenReturn(List.of(vm));
-
- Backup.RestorePoint restorePoint1 = new Backup.RestorePoint(restorePoint1ExternalId, DateUtil.now(), "Full", restorePointSize, 0L);
- Backup.RestorePoint restorePoint2 = new Backup.RestorePoint("12345", DateUtil.now(), "Full", restorePointSize, 0L);
+ when(vmInstanceDao.listByZoneWithBackups(dataCenterId, null)).thenReturn(List.of(vm));
+ Backup.Metric metric = new Backup.Metric(metricSize, null);
+ Map metricMap = new HashMap<>();
+ metricMap.put(vm, metric);
+ when(backupProvider.getBackupMetrics(Mockito.anyLong(), Mockito.anyList())).thenReturn(metricMap);
+
+ Backup.RestorePoint restorePoint1 = new Backup.RestorePoint(restorePoint1ExternalId, DateUtil.now(), "Root");
+ Backup.RestorePoint restorePoint2 = new Backup.RestorePoint("12345", DateUtil.now(), "Root");
List restorePoints = new ArrayList<>(List.of(restorePoint1, restorePoint2));
when(backupProvider.listRestorePoints(vm)).thenReturn(restorePoints);
BackupVO backupInDb1 = new BackupVO();
backupInDb1.setSize(backup1Size);
- backupInDb1.setAccountId(accountId);
backupInDb1.setExternalId(restorePoint1ExternalId);
BackupVO backupInDb2 = new BackupVO();
backupInDb2.setSize(backup2Size);
- backupInDb2.setAccountId(accountId);
backupInDb2.setExternalId(null);
ReflectionTestUtils.setField(backupInDb2, "id", backup2Id);
when(backupDao.findById(backup2Id)).thenReturn(backupInDb2);
@@ -813,7 +646,7 @@ public void testBackupSyncTask() {
BackupVO newBackupEntry = new BackupVO();
newBackupEntry.setSize(newBackupSize);
- when(backupProvider.createNewBackupEntryForRestorePoint(restorePoint2, vm)).thenReturn(newBackupEntry);
+ when(backupProvider.createNewBackupEntryForRestorePoint(restorePoint2, vm, metric)).thenReturn(newBackupEntry);
try (MockedStatic ignored = Mockito.mockStatic(ActionEventUtils.class)) {
Mockito.when(ActionEventUtils.onActionEvent(Mockito.anyLong(), Mockito.anyLong(),
@@ -827,8 +660,8 @@ public void testBackupSyncTask() {
backupSyncTask.runInContext();
verify(resourceLimitMgr, times(1)).decrementResourceCount(accountId, Resource.ResourceType.backup_storage, backup1Size);
- verify(resourceLimitMgr, times(1)).incrementResourceCount(accountId, Resource.ResourceType.backup_storage, restorePointSize);
- Assert.assertEquals(backupInDb1.getSize(), restorePointSize);
+ verify(resourceLimitMgr, times(1)).incrementResourceCount(accountId, Resource.ResourceType.backup_storage, metricSize);
+ Assert.assertEquals(backupInDb1.getSize(), metricSize);
verify(resourceLimitMgr, times(1)).incrementResourceCount(accountId, Resource.ResourceType.backup);
verify(resourceLimitMgr, times(1)).incrementResourceCount(accountId, Resource.ResourceType.backup_storage, newBackupSize);
@@ -931,687 +764,6 @@ public void deleteBackupScheduleTestDeleteSpecificScheduleWhenItsIdIsSpecified()
assertTrue(success);
}
- @Test
- public void testGetBackupDetailsFromVM() {
- Long vmId = 1L;
- VirtualMachine vm = mock(VirtualMachine.class);
- when(vm.getServiceOfferingId()).thenReturn(1L);
- when(vm.getTemplateId()).thenReturn(2L);
- when(vm.getId()).thenReturn(vmId);
-
- ServiceOfferingVO serviceOffering = mock(ServiceOfferingVO.class);
- when(serviceOffering.getUuid()).thenReturn("service-offering-uuid");
- when(serviceOfferingDao.findById(1L)).thenReturn(serviceOffering);
- VMTemplateVO template = mock(VMTemplateVO.class);
- when(template.getUuid()).thenReturn("template-uuid");
- when(vmTemplateDao.findById(2L)).thenReturn(template);
-
- VMInstanceDetailVO vmInstanceDetail = mock(VMInstanceDetailVO.class);
- when(vmInstanceDetail.getName()).thenReturn("mocked-detail-name");
- when(vmInstanceDetail.getValue()).thenReturn("mocked-detail-value");
- List vmDetails = Collections.singletonList(vmInstanceDetail);
- when(vmInstanceDetailsDao.listDetails(vmId)).thenReturn(vmDetails);
-
- UserVmJoinVO userVmJoinVO = mock(UserVmJoinVO.class);
- when(userVmJoinVO.getNetworkUuid()).thenReturn("mocked-network-uuid");
- List userVmJoinVOs = Collections.singletonList(userVmJoinVO);
- when(userVmJoinDao.searchByIds(vmId)).thenReturn(userVmJoinVOs);
-
- Map details = backupManager.getBackupDetailsFromVM(vm);
-
- assertEquals("service-offering-uuid", details.get(ApiConstants.SERVICE_OFFERING_ID));
- assertEquals("[{\"networkid\":\"mocked-network-uuid\"}]", details.get(ApiConstants.NICS));
- assertEquals("{\"mocked-detail-name\":\"mocked-detail-value\"}", details.get(ApiConstants.VM_SETTINGS));
- }
-
- @Test
- public void getDataDiskInfoListFromBackup() {
- Long size1 = 5L * 1024 * 1024 * 1024;
- Long size2 = 10L * 1024 * 1024 * 1024;
- Backup backup = mock(Backup.class);
-
- Backup.VolumeInfo volumeInfo0 = mock(Backup.VolumeInfo.class);
- when(volumeInfo0.getType()).thenReturn(Volume.Type.ROOT);
- Backup.VolumeInfo volumeInfo1 = mock(Backup.VolumeInfo.class);
- when(volumeInfo1.getDiskOfferingId()).thenReturn("disk-offering-uuid-1");
- when(volumeInfo1.getSize()).thenReturn(size1);
- when(volumeInfo1.getMinIops()).thenReturn(100L);
- when(volumeInfo1.getMaxIops()).thenReturn(300L);
- when(volumeInfo1.getType()).thenReturn(Volume.Type.DATADISK);
- when(volumeInfo1.getDeviceId()).thenReturn(1L);
- Backup.VolumeInfo volumeInfo2 = mock(Backup.VolumeInfo.class);
- when(volumeInfo2.getDiskOfferingId()).thenReturn("disk-offering-uuid-2");
- when(volumeInfo2.getSize()).thenReturn(size2);
- when(volumeInfo2.getMinIops()).thenReturn(200L);
- when(volumeInfo2.getMaxIops()).thenReturn(400L);
- when(volumeInfo2.getType()).thenReturn(Volume.Type.DATADISK);
- when(volumeInfo2.getDeviceId()).thenReturn(2L);
- when(backup.getBackedUpVolumes()).thenReturn(List.of(volumeInfo0, volumeInfo1, volumeInfo2));
-
- DiskOfferingVO diskOffering1 = mock(DiskOfferingVO.class);
- when(diskOffering1.getUuid()).thenReturn("disk-offering-uuid-1");
- when(diskOffering1.getState()).thenReturn(DiskOffering.State.Active);
-
- DiskOfferingVO diskOffering2 = mock(DiskOfferingVO.class);
- when(diskOffering2.getUuid()).thenReturn("disk-offering-uuid-2");
- when(diskOffering2.getState()).thenReturn(DiskOffering.State.Active);
-
- when(diskOfferingDao.findByUuid("disk-offering-uuid-1")).thenReturn(diskOffering1);
- when(diskOfferingDao.findByUuid("disk-offering-uuid-2")).thenReturn(diskOffering2);
-
- List vmDiskInfoList = backupManager.getDataDiskInfoListFromBackup(backup);
-
- assertEquals(2, vmDiskInfoList.size());
- assertEquals("disk-offering-uuid-1", vmDiskInfoList.get(0).getDiskOffering().getUuid());
- assertEquals(Long.valueOf(5), vmDiskInfoList.get(0).getSize());
- assertEquals(Long.valueOf(1), vmDiskInfoList.get(0).getDeviceId());
- assertEquals(Long.valueOf(100), vmDiskInfoList.get(0).getMinIops());
- assertEquals(Long.valueOf(300), vmDiskInfoList.get(0).getMaxIops());
-
- assertEquals("disk-offering-uuid-2", vmDiskInfoList.get(1).getDiskOffering().getUuid());
- assertEquals(Long.valueOf(10), vmDiskInfoList.get(1).getSize());
- assertEquals(Long.valueOf(2), vmDiskInfoList.get(1).getDeviceId());
- assertEquals(Long.valueOf(200), vmDiskInfoList.get(1).getMinIops());
- assertEquals(Long.valueOf(400), vmDiskInfoList.get(1).getMaxIops());
- }
-
- @Test
- public void getDataDiskInfoListFromBackupNullIops() {
- Long size = 5L * 1024 * 1024 * 1024;
- Backup backup = mock(Backup.class);
- Backup.VolumeInfo volumeInfo1 = mock(Backup.VolumeInfo.class);
- when(volumeInfo1.getDiskOfferingId()).thenReturn("disk-offering-uuid-1");
- when(volumeInfo1.getSize()).thenReturn(size);
- when(volumeInfo1.getMinIops()).thenReturn(null);
- when(volumeInfo1.getMaxIops()).thenReturn(null);
- when(volumeInfo1.getType()).thenReturn(Volume.Type.DATADISK);
- when(volumeInfo1.getDeviceId()).thenReturn(1L);
- when(backup.getBackedUpVolumes()).thenReturn(List.of(volumeInfo1));
-
- DiskOfferingVO diskOffering = mock(DiskOfferingVO.class);
- when(diskOffering.getUuid()).thenReturn("disk-offering-uuid-1");
- when(diskOffering.getState()).thenReturn(DiskOffering.State.Active);
-
- when(diskOfferingDao.findByUuid("disk-offering-uuid-1")).thenReturn(diskOffering);
-
- List vmDiskInfoList = backupManager.getDataDiskInfoListFromBackup(backup);
-
- assertEquals(1, vmDiskInfoList.size());
- assertEquals("disk-offering-uuid-1", vmDiskInfoList.get(0).getDiskOffering().getUuid());
- assertEquals(Long.valueOf(5), vmDiskInfoList.get(0).getSize());
- assertEquals(Long.valueOf(1), vmDiskInfoList.get(0).getDeviceId());
- assertNull(vmDiskInfoList.get(0).getMinIops());
- assertNull(vmDiskInfoList.get(0).getMaxIops());
- }
-
- @Test (expected = InvalidParameterValueException.class)
- public void testCheckVmDisksSizeAgainstBackup() {
- Long sizeInBackup = 5L * 1024 * 1024 * 1024;
- Long sizeInCmd = 2L;
- Backup backup = mock(Backup.class);
- Backup.VolumeInfo volumeInfo = mock(Backup.VolumeInfo.class);
- when(volumeInfo.getDiskOfferingId()).thenReturn("disk-offering-uuid-1");
- when(volumeInfo.getSize()).thenReturn(sizeInBackup);
- when(volumeInfo.getType()).thenReturn(Volume.Type.DATADISK);
- when(backup.getBackedUpVolumes()).thenReturn(List.of(volumeInfo));
-
- DiskOfferingVO diskOffering = mock(DiskOfferingVO.class);
- when(diskOffering.getState()).thenReturn(DiskOffering.State.Active);
- when(diskOfferingDao.findByUuid("disk-offering-uuid-1")).thenReturn(diskOffering);
- List vmDiskInfoList = List.of(new VmDiskInfo(diskOffering, sizeInCmd, 1L, null, null));
-
- backupManager.checkVmDisksSizeAgainstBackup(vmDiskInfoList, backup);
- }
-
- @Test
- public void testGetRootDiskInfoFromBackup() {
- Long size = 5L * 1024 * 1024 * 1024;
- Backup backup = mock(Backup.class);
- Backup.VolumeInfo volumeInfo = mock(Backup.VolumeInfo.class);
- when(volumeInfo.getDiskOfferingId()).thenReturn("root-disk-offering-uuid");
- when(volumeInfo.getSize()).thenReturn(size);
- when(volumeInfo.getType()).thenReturn(Volume.Type.ROOT);
- when(backup.getBackedUpVolumes()).thenReturn(List.of(volumeInfo));
-
- DiskOfferingVO diskOffering = mock(DiskOfferingVO.class);
- when(diskOffering.getUuid()).thenReturn("root-disk-offering-uuid");
- when(diskOfferingDao.findByUuid("root-disk-offering-uuid")).thenReturn(diskOffering);
-
- VmDiskInfo VmDiskInfo = backupManager.getRootDiskInfoFromBackup(backup);
-
- assertEquals("root-disk-offering-uuid", VmDiskInfo.getDiskOffering().getUuid());
- assertEquals(Long.valueOf(5), VmDiskInfo.getSize());
- assertEquals(null, VmDiskInfo.getDeviceId());
- }
-
- @Test
- public void testImportBackupOffering() {
- ImportBackupOfferingCmd cmd = Mockito.mock(ImportBackupOfferingCmd.class);
- when(cmd.getZoneId()).thenReturn(1L);
- when(cmd.getExternalId()).thenReturn("external-id");
- when(cmd.getName()).thenReturn("Test Offering");
- when(cmd.getDescription()).thenReturn("Test Description");
- when(cmd.getUserDrivenBackups()).thenReturn(true);
-
- overrideBackupFrameworkConfigValue();
-
- when(backupOfferingDao.findByExternalId("external-id", 1L)).thenReturn(null);
- when(backupOfferingDao.findByName("Test Offering", 1L)).thenReturn(null);
-
- BackupOfferingVO offering = new BackupOfferingVO(1L, "external-id", "testbackupprovider", "Test Offering", "Test Description", true);
- when(backupOfferingDao.persist(any(BackupOfferingVO.class))).thenReturn(offering);
- when(backupProvider.isValidProviderOffering(cmd.getZoneId(), cmd.getExternalId())).thenReturn(true);
-
- BackupOffering result = backupManager.importBackupOffering(cmd);
-
- assertEquals("Test Offering", result.getName());
- assertEquals("Test Description", result.getDescription());
- assertEquals(true, result.isUserDrivenBackupAllowed());
- assertEquals("external-id", result.getExternalId());
- assertEquals("testbackupprovider", result.getProvider());
- }
-
- @Test
- public void testCreateVolumeInfoFromVolumes() {
- Long diskOfferingId = 5L;
- DiskOfferingVO diskOffering = Mockito.mock(DiskOfferingVO.class);
- Mockito.when(diskOffering.getUuid()).thenReturn("disk-offering-uuid");
- Mockito.when(diskOfferingDao.findById(diskOfferingId)).thenReturn(diskOffering);
-
- List volumes = new ArrayList<>();
- VolumeVO volume1 = new VolumeVO(Volume.Type.ROOT, "vol1", 1L, 2L, 3L,
- diskOfferingId, null, 1024L, null, null, null);
- volume1.setUuid("uuid1");
- volume1.setPath("path1");
- volume1.setDeviceId(0L);
- volume1.setVolumeType(Volume.Type.ROOT);
- volumes.add(volume1);
-
- VolumeVO volume2 = new VolumeVO(Volume.Type.ROOT, "vol2", 1L, 2L, 3L,
- diskOfferingId, null, 2048L, 1000L, 2000L, null);
- volume2.setUuid("uuid2");
- volume2.setPath("path2");
- volume2.setDeviceId(1L);
- volume2.setVolumeType(Volume.Type.DATADISK);
- volumes.add(volume2);
-
- String expectedJson = "[{\"uuid\":\"uuid1\",\"type\":\"ROOT\",\"size\":1024,\"path\":\"path1\",\"deviceId\":0,\"diskOfferingId\":\"disk-offering-uuid\"},{\"uuid\":\"uuid2\",\"type\":\"DATADISK\",\"size\":2048,\"path\":\"path2\",\"deviceId\":1,\"diskOfferingId\":\"disk-offering-uuid\",\"minIops\":1000,\"maxIops\":2000}]";
- String actualJson = backupManager.createVolumeInfoFromVolumes(new ArrayList<>(volumes));
-
- assertEquals(expectedJson, actualJson);
- }
-
- @Test
- public void testAssignVMToBackupOffering() {
- Long vmId = 1L;
- Long offeringId = 2L;
-
- VMInstanceVO vm = mock(VMInstanceVO.class);
- when(vm.getId()).thenReturn(vmId);
- BackupOfferingVO offering = mock(BackupOfferingVO.class);
-
- overrideBackupFrameworkConfigValue();
-
- when(vmInstanceDao.findById(vmId)).thenReturn(vm);
- when(backupOfferingDao.findById(offeringId)).thenReturn(offering);
- when(vm.getState()).thenReturn(VirtualMachine.State.Running);
- when(vm.getDataCenterId()).thenReturn(1L);
- when(vm.getBackupOfferingId()).thenReturn(null);
- when(offering.getProvider()).thenReturn("testbackupprovider");
- when(backupProvider.assignVMToBackupOffering(vm, offering)).thenReturn(true);
- when(vmInstanceDao.update(1L, vm)).thenReturn(true);
-
- try (MockedStatic ignored2 = Mockito.mockStatic(UsageEventUtils.class)) {
- boolean result = backupManager.assignVMToBackupOffering(vmId, offeringId);
-
- assertTrue(result);
- verify(vmInstanceDao, times(1)).findById(vmId);
- verify(backupOfferingDao, times(1)).findById(offeringId);
- verify(backupManager, times(1)).getBackupProvider("testbackupprovider");
- }
- }
-
- @Test
- public void testRemoveVMFromBackupOffering() {
- Long vmId = 1L;
- Long accountId = 2L;
- Long zoneId = 3L;
- Long offeringId = 4L;
- Long backupScheduleId = 5L;
- String vmHostName = "vm1";
- String vmUuid = "uuid1";
- String resourceName = "Backup-" + vmHostName + "-" + vmUuid;
-
- boolean forced = true;
-
- VMInstanceVO vm = mock(VMInstanceVO.class);
- when(vm.getId()).thenReturn(vmId);
- when(vm.getDataCenterId()).thenReturn(1L);
- when(vm.getBackupOfferingId()).thenReturn(offeringId);
- when(vm.getAccountId()).thenReturn(accountId);
- when(vm.getDataCenterId()).thenReturn(zoneId);
- when(vm.getHostName()).thenReturn(vmHostName);
- when(vm.getUuid()).thenReturn(vmUuid);
- when(vmInstanceDao.findByIdIncludingRemoved(vmId)).thenReturn(vm);
- when(vmInstanceDao.update(vmId, vm)).thenReturn(true);
-
- BackupOfferingVO offering = mock(BackupOfferingVO.class);
- when(backupOfferingDao.findById(vm.getBackupOfferingId())).thenReturn(offering);
- when(offering.getProvider()).thenReturn("testbackupprovider");
- when(backupProvider.removeVMFromBackupOffering(vm)).thenReturn(true);
- when(backupProvider.willDeleteBackupsOnOfferingRemoval()).thenReturn(true);
- when(backupDao.listByVmId(null, vmId)).thenReturn(new ArrayList<>());
-
- BackupScheduleVO backupSchedule = new BackupScheduleVO();
- ReflectionTestUtils.setField(backupSchedule, "id", backupScheduleId);
- when(backupScheduleDao.listByVM(vmId)).thenReturn(List.of(backupSchedule));
-
- overrideBackupFrameworkConfigValue();
-
- try (MockedStatic usageEventUtilsMocked = Mockito.mockStatic(UsageEventUtils.class)) {
- boolean result = backupManager.removeVMFromBackupOffering(vmId, forced);
-
- assertTrue(result);
- verify(vmInstanceDao, times(1)).findByIdIncludingRemoved(vmId);
- verify(backupOfferingDao, times(1)).findById(vm.getBackupOfferingId());
- verify(backupManager, times(1)).getBackupProvider("testbackupprovider");
- verify(backupScheduleDao, times(1)).remove(backupScheduleId);
- usageEventUtilsMocked.verify(() -> UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_BACKUP_OFFERING_REMOVED_AND_BACKUPS_DELETED, accountId, zoneId, vmId, resourceName,
- offeringId, null, null, Backup.class.getSimpleName(), vmUuid));
- }
- }
-
- @Test
- public void testDeleteBackupScheduleByVmId() {
- Long vmId = 1L;
- Long scheduleId = 2L;
- DeleteBackupScheduleCmd cmd = new DeleteBackupScheduleCmd();
- ReflectionTestUtils.setField(cmd, "vmId", vmId);
-
- overrideBackupFrameworkConfigValue();
-
- VMInstanceVO vm = mock(VMInstanceVO.class);
- when(vmInstanceDao.findById(vmId)).thenReturn(vm);
- BackupScheduleVO schedule = mock(BackupScheduleVO.class);
- when(schedule.getId()).thenReturn(scheduleId);
- when(backupScheduleDao.listByVM(vmId)).thenReturn(List.of(schedule));
- when(backupScheduleDao.remove(scheduleId)).thenReturn(true);
-
- boolean result = backupManager.deleteBackupSchedule(cmd);
- assertTrue(result);
- }
-
- @Test
- public void testRestoreBackupToVM() throws NoTransitionException {
- Long backupId = 1L;
- Long vmId = 2L;
- Long hostId = 3L;
- Long offeringId = 4L;
- Long poolId = 5L;
-
- BackupVO backup = mock(BackupVO.class);
- when(backup.getBackupOfferingId()).thenReturn(offeringId);
- when(backup.getStatus()).thenReturn(Backup.Status.BackedUp);
-
- VMInstanceVO vm = mock(VMInstanceVO.class);
- when(vmInstanceDao.findByIdIncludingRemoved(vmId)).thenReturn(vm);
- when(vm.getId()).thenReturn(vmId);
- when(vm.getState()).thenReturn(VirtualMachine.State.Stopped);
- when(vm.getHostId()).thenReturn(hostId);
-
- BackupOfferingVO offering = mock(BackupOfferingVO.class);
- BackupProvider backupProvider = mock(BackupProvider.class);
- when(backupProvider.supportsInstanceFromBackup()).thenReturn(true);
-
- overrideBackupFrameworkConfigValue();
-
- when(backupDao.findById(backupId)).thenReturn(backup);
- when(vmInstanceDao.findByIdIncludingRemoved(vmId)).thenReturn(vm);
- when(backupOfferingDao.findByIdIncludingRemoved(offeringId)).thenReturn(offering);
- when(offering.getProvider()).thenReturn("testbackupprovider");
- when(backupManager.getBackupProvider("testbackupprovider")).thenReturn(backupProvider);
- when(virtualMachineManager.stateTransitTo(vm, VirtualMachine.Event.RestoringRequested, hostId)).thenReturn(true);
- when(virtualMachineManager.stateTransitTo(vm, VirtualMachine.Event.RestoringSuccess, hostId)).thenReturn(true);
-
- VolumeVO rootVolume = mock(VolumeVO.class);
- when(rootVolume.getPoolId()).thenReturn(poolId);
- HostVO host = mock(HostVO.class);
- when(hostDao.findById(hostId)).thenReturn(host);
- StoragePoolVO pool = mock(StoragePoolVO.class);
- when(volumeDao.findIncludingRemovedByInstanceAndType(vmId, Volume.Type.ROOT)).thenReturn(List.of(rootVolume));
- when(primaryDataStoreDao.findById(poolId)).thenReturn(pool);
- when(rootVolume.getPoolId()).thenReturn(poolId);
- when(volumeDao.findIncludingRemovedByInstanceAndType(vmId, Volume.Type.ROOT)).thenReturn(List.of(rootVolume));
- when(primaryDataStoreDao.findById(poolId)).thenReturn(pool);
- when(backupProvider.restoreBackupToVM(vm, backup, null, null)).thenReturn(new Pair<>(true, null));
-
- try (MockedStatic utils = Mockito.mockStatic(ActionEventUtils.class)) {
- boolean result = backupManager.restoreBackupToVM(backupId, vmId);
-
- assertTrue(result);
- verify(backupProvider, times(1)).restoreBackupToVM(vm, backup, null, null);
- verify(virtualMachineManager, times(1)).stateTransitTo(vm, VirtualMachine.Event.RestoringRequested, hostId);
- verify(virtualMachineManager, times(1)).stateTransitTo(vm, VirtualMachine.Event.RestoringSuccess, hostId);
- } catch (CloudRuntimeException e) {
- fail("Test failed due to exception" + e);
- }
- }
-
- @Test
- public void testRestoreBackupToVMException() throws NoTransitionException {
- Long backupId = 1L;
- Long vmId = 2L;
- Long hostId = 3L;
- Long offeringId = 4L;
- Long poolId = 5L;
-
- BackupVO backup = mock(BackupVO.class);
- when(backup.getBackupOfferingId()).thenReturn(offeringId);
- when(backup.getStatus()).thenReturn(Backup.Status.BackedUp);
-
- VMInstanceVO vm = mock(VMInstanceVO.class);
- when(vmInstanceDao.findByIdIncludingRemoved(vmId)).thenReturn(vm);
- when(vm.getId()).thenReturn(vmId);
- when(vm.getState()).thenReturn(VirtualMachine.State.Stopped);
- when(vm.getHostId()).thenReturn(hostId);
-
- BackupOfferingVO offering = mock(BackupOfferingVO.class);
- BackupProvider backupProvider = mock(BackupProvider.class);
- when(backupProvider.supportsInstanceFromBackup()).thenReturn(true);
-
- overrideBackupFrameworkConfigValue();
-
- when(backupDao.findById(backupId)).thenReturn(backup);
- when(vmInstanceDao.findByIdIncludingRemoved(vmId)).thenReturn(vm);
- when(backupOfferingDao.findByIdIncludingRemoved(offeringId)).thenReturn(offering);
- when(offering.getProvider()).thenReturn("testbackupprovider");
- when(backupManager.getBackupProvider("testbackupprovider")).thenReturn(backupProvider);
- when(virtualMachineManager.stateTransitTo(vm, VirtualMachine.Event.RestoringRequested, hostId)).thenReturn(true);
- when(virtualMachineManager.stateTransitTo(vm, VirtualMachine.Event.RestoringFailed, hostId)).thenReturn(true);
-
- VolumeVO rootVolume = mock(VolumeVO.class);
- when(rootVolume.getPoolId()).thenReturn(poolId);
- HostVO host = mock(HostVO.class);
- when(hostDao.findById(hostId)).thenReturn(host);
- StoragePoolVO pool = mock(StoragePoolVO.class);
- when(volumeDao.findIncludingRemovedByInstanceAndType(vmId, Volume.Type.ROOT)).thenReturn(List.of(rootVolume));
- when(primaryDataStoreDao.findById(poolId)).thenReturn(pool);
- when(rootVolume.getPoolId()).thenReturn(poolId);
- when(volumeDao.findIncludingRemovedByInstanceAndType(vmId, Volume.Type.ROOT)).thenReturn(List.of(rootVolume));
- when(primaryDataStoreDao.findById(poolId)).thenReturn(pool);
- when(backupProvider.restoreBackupToVM(vm, backup, null, null)).thenReturn(new Pair<>(false, null));
-
- try (MockedStatic utils = Mockito.mockStatic(ActionEventUtils.class)) {
- CloudRuntimeException exception = Assert.assertThrows(CloudRuntimeException.class,
- () -> backupManager.restoreBackupToVM(backupId, vmId));
-
- verify(backupProvider, times(1)).restoreBackupToVM(vm, backup, null, null);
- verify(virtualMachineManager, times(1)).stateTransitTo(vm, VirtualMachine.Event.RestoringRequested, hostId);
- verify(virtualMachineManager, times(1)).stateTransitTo(vm, VirtualMachine.Event.RestoringFailed, hostId);
- }
- }
-
- @Test
- public void testGetBackupStorageUsedStats() {
- Long zoneId = 1L;
- overrideBackupFrameworkConfigValue();
- when(backupManager.getBackupProvider(zoneId)).thenReturn(backupProvider);
- when(backupProvider.getBackupStorageStats(zoneId)).thenReturn(new Pair<>(100L, 200L));
-
- CapacityVO capacity = backupManager.getBackupStorageUsedStats(zoneId);
-
- Assert.assertNotNull(capacity);
- Assert.assertEquals(Optional.ofNullable(Long.valueOf(100)), Optional.ofNullable(capacity.getUsedCapacity()));
- Assert.assertEquals(Optional.ofNullable(Long.valueOf(200)), Optional.ofNullable(capacity.getTotalCapacity()));
- Assert.assertEquals(CapacityVO.CAPACITY_TYPE_BACKUP_STORAGE, capacity.getCapacityType());
- }
-
- @Test
- public void testCheckAndRemoveBackupOfferingBeforeExpunge() {
- Long vmId = 1L;
- Long zoneId = 2L;
- Long offeringId = 3L;
- String vmUuid = "uuid1";
- String instanceName = "i-2-1-VM";
- String backupExternalId = "backup-external-id";
-
- VMInstanceVO vm = mock(VMInstanceVO.class);
- when(vm.getId()).thenReturn(vmId);
- when(vm.getUuid()).thenReturn(vmUuid);
- when(vm.getBackupOfferingId()).thenReturn(offeringId);
- when(vm.getInstanceName()).thenReturn(instanceName);
- when(vm.getBackupExternalId()).thenReturn(backupExternalId);
- when(vm.getDataCenterId()).thenReturn(zoneId);
- Backup backup = mock(Backup.class);
- when(backupDao.listByVmIdAndOffering(zoneId, vmId, offeringId)).thenReturn(List.of(backup));
-
- CloudRuntimeException exception = Assert.assertThrows(CloudRuntimeException.class,
- () -> backupManager.checkAndRemoveBackupOfferingBeforeExpunge(vm));
- Assert.assertEquals("This Instance [uuid: uuid1, name: i-2-1-VM] has a "
- + "Backup Offering [id: 3, external id: backup-external-id] with 1 backups. Please, remove the backup offering "
- + "before proceeding to VM exclusion!", exception.getMessage());
- }
-
- @Test
- public void testGetIpToNetworkMapFromBackup() {
- Long networkId1 = 1L;
- Long networkId2 = 2L;
- String networkUuid1 = "network-uuid-1";
- String networkUuid2 = "network-uuid-2";
- String ip1 = "10.1.1.1";
- String ip2 = "10.1.1.2";
- String ipv61 = "2001:db8::1";
- String ipv62 = "2001:db8::2";
- String mac1 = "00:11:22:33:44:55";
- String mac2 = "00:11:22:33:44:56";
-
- // Test case 1: Missing network information
- Backup backup1 = mock(Backup.class);
- List networkIds1 = new ArrayList<>();
- try {
- backupManager.getIpToNetworkMapFromBackup(backup1, true, networkIds1);
- fail("Expected CloudRuntimeException for missing network information");
- } catch (CloudRuntimeException e) {
- assertEquals("Backup doesn't contain network information. Please specify at least one valid network while creating instance", e.getMessage());
- }
-
- // Test case 2: IP preservation enabled with IP information
- Backup backup2 = mock(Backup.class);
- String nicsJson = String.format("[{\"networkid\":\"%s\",\"ipaddress\":\"%s\",\"ip6address\":\"%s\",\"macaddress\":\"%s\"}," +
- "{\"networkid\":\"%s\",\"ipaddress\":\"%s\",\"ip6address\":\"%s\",\"macaddress\":\"%s\"}]",
- networkUuid1, ip1, ipv61, mac1, networkUuid2, ip2, ipv62, mac2);
- when(backup2.getDetail(ApiConstants.NICS)).thenReturn(nicsJson);
-
- NetworkVO network1 = mock(NetworkVO.class);
- NetworkVO network2 = mock(NetworkVO.class);
- when(networkDao.findByUuid(networkUuid1)).thenReturn(network1);
- when(networkDao.findByUuid(networkUuid2)).thenReturn(network2);
- when(network1.getId()).thenReturn(networkId1);
- when(network2.getId()).thenReturn(networkId2);
-
- Network.IpAddresses ipAddresses1 = mock(Network.IpAddresses.class);
- Network.IpAddresses ipAddresses2 = mock(Network.IpAddresses.class);
- when(networkService.getIpAddressesFromIps(ip1, ipv61, mac1)).thenReturn(ipAddresses1);
- when(networkService.getIpAddressesFromIps(ip2, ipv62, mac2)).thenReturn(ipAddresses2);
-
- List networkIds2 = new ArrayList<>();
- Map result2 = backupManager.getIpToNetworkMapFromBackup(backup2, true, networkIds2);
-
- assertEquals(2, result2.size());
- assertEquals(ipAddresses1, result2.get(networkId1));
- assertEquals(ipAddresses2, result2.get(networkId2));
- assertEquals(2, networkIds2.size());
- assertTrue(networkIds2.contains(networkId1));
- assertTrue(networkIds2.contains(networkId2));
-
- // Test case 3: IP preservation enabled but missing IP information
- Backup backup3 = mock(Backup.class);
- nicsJson = String.format("[{\"networkid\":\"%s\"}]", networkUuid1);
- when(backup3.getDetail(ApiConstants.NICS)).thenReturn(nicsJson);
-
- List networkIds3 = new ArrayList<>();
- Map result3 = backupManager.getIpToNetworkMapFromBackup(backup3, true, networkIds3);
-
- assertEquals(1, result3.size());
- assertNull(result3.get(networkId1));
- assertEquals(1, networkIds3.size());
- assertTrue(networkIds3.contains(networkId1));
-
- // Test case 4: IP preservation disabled
- Backup backup4 = mock(Backup.class);
- nicsJson = String.format("[{\"networkid\":\"%s\"}]", networkUuid1);
- when(backup4.getDetail(ApiConstants.NICS)).thenReturn(nicsJson);
-
- List networkIds4 = new ArrayList<>();
- Map result4 = backupManager.getIpToNetworkMapFromBackup(backup4, false, networkIds4);
-
- assertEquals(1, result4.size());
- assertNull(result4.get(networkId1));
- assertEquals(1, networkIds4.size());
- assertTrue(networkIds4.contains(networkId1));
- }
-
- @Test
- public void testDeleteBackupVmNotFound() {
- Long backupId = 1L;
- Long vmId = 2L;
- Long zoneId = 3L;
- Long accountId = 4L;
- Long backupOfferingId = 5L;
- String vmHostName = "vm1";
- String vmUuid = "uuid1";
- String resourceName = "Backup-" + vmHostName + "-" + vmUuid;
-
- BackupVO backup = mock(BackupVO.class);
- when(backup.getId()).thenReturn(backupId);
- when(backup.getVmId()).thenReturn(vmId);
- when(backup.getZoneId()).thenReturn(zoneId);
- when(backup.getAccountId()).thenReturn(accountId);
- when(backup.getBackupOfferingId()).thenReturn(backupOfferingId);
- when(backup.getSize()).thenReturn(100L);
-
- overrideBackupFrameworkConfigValue();
-
- VMInstanceVO vm = mock(VMInstanceVO.class);
- when(vm.getId()).thenReturn(vmId);
- when(vm.getAccountId()).thenReturn(accountId);
- when(vm.getBackupOfferingId()).thenReturn(10L);
- when(vm.getDataCenterId()).thenReturn(zoneId);
- when(vm.getHostName()).thenReturn(vmHostName);
- when(vm.getUuid()).thenReturn(vmUuid);
- when(backupDao.findByIdIncludingRemoved(backupId)).thenReturn(backup);
- when(vmInstanceDao.findByIdIncludingRemoved(vmId)).thenReturn(vm);
- when(backupDao.listByVmIdAndOffering(zoneId, vmId, backupOfferingId)).thenReturn(new ArrayList<>());
-
- BackupOfferingVO offering = mock(BackupOfferingVO.class);
- when(backupOfferingDao.findByIdIncludingRemoved(backupOfferingId)).thenReturn(offering);
-
- when(backupProvider.deleteBackup(backup, false)).thenReturn(true);
-
- when(backupDao.remove(backupId)).thenReturn(true);
-
- try (MockedStatic usageEventUtilsMocked = Mockito.mockStatic(UsageEventUtils.class)) {
- boolean result = backupManager.deleteBackup(backupId, false);
-
- assertTrue(result);
- verify(backupProvider).deleteBackup(backup, false);
- verify(resourceLimitMgr).decrementResourceCount(accountId, Resource.ResourceType.backup);
- verify(resourceLimitMgr).decrementResourceCount(accountId, Resource.ResourceType.backup_storage, backup.getSize());
- verify(backupDao).remove(backupId);
- usageEventUtilsMocked.verify(() -> UsageEventUtils.publishUsageEvent(EventTypes.EVENT_VM_BACKUP_OFFERING_REMOVED_AND_BACKUPS_DELETED, accountId, zoneId, vmId, resourceName,
- backupOfferingId, null, null, Backup.class.getSimpleName(), vmUuid));
- }
- }
-
- @Test
- public void testNewBackupResponse() {
- Long vmId = 1L;
- Long accountId = 2L;
- Long domainId = 3L;
- Long zoneId = 4L;
- Long vmOfferingId = 5L;
- Long backupOfferingId = 6L;
- Long backupId = 7L;
- Long templateId = 8L;
- String templateUuid = "template-uuid1";
- String serviceOfferingUuid = "service-offering-uuid1";
-
- BackupVO backup = new BackupVO();
- ReflectionTestUtils.setField(backup, "id", backupId);
- ReflectionTestUtils.setField(backup, "uuid", "backup-uuid");
- backup.setVmId(vmId);
- backup.setAccountId(accountId);
- backup.setDomainId(domainId);
- backup.setZoneId(zoneId);
- backup.setBackupOfferingId(backupOfferingId);
- backup.setType("Full");
- backup.setBackupScheduleId(null);
-
- VMInstanceVO vm = new VMInstanceVO(vmId, 0L, "test-vm", "test-vm", VirtualMachine.Type.User,
- 0L, Hypervisor.HypervisorType.Simulator, 0L, domainId, accountId, 0L, false);
- vm.setDataCenterId(zoneId);
- vm.setBackupOfferingId(vmOfferingId);
- vm.setTemplateId(templateId);
-
- AccountVO account = new AccountVO();
- account.setUuid("account-uuid");
- account.setAccountName("test-account");
-
- DomainVO domain = new DomainVO();
- domain.setUuid("domain-uuid");
- domain.setName("test-domain");
-
- DataCenterVO zone = new DataCenterVO(1L, "test-zone", null, null, null, null, null, null, null, null, DataCenter.NetworkType.Advanced, null, null);
- zone.setUuid("zone-uuid");
-
- BackupOfferingVO offering = Mockito.mock(BackupOfferingVO.class);
- Mockito.when(offering.getUuid()).thenReturn("offering-uuid");
- Mockito.when(offering.getName()).thenReturn("test-offering");
-
- Mockito.when(vmInstanceDao.findByIdIncludingRemoved(vmId)).thenReturn(vm);
- Mockito.when(accountDao.findByIdIncludingRemoved(accountId)).thenReturn(account);
- Mockito.when(domainDao.findByIdIncludingRemoved(domainId)).thenReturn(domain);
- Mockito.when(dataCenterDao.findByIdIncludingRemoved(zoneId)).thenReturn(zone);
- Mockito.when(backupOfferingDao.findByIdIncludingRemoved(backupOfferingId)).thenReturn(offering);
-
- VMTemplateVO template = mock(VMTemplateVO.class);
- when(template.getFormat()).thenReturn(Storage.ImageFormat.QCOW2);
- when(template.getName()).thenReturn("template1");
- when(vmTemplateDao.findByUuid(templateUuid)).thenReturn(template);
- Map details = new HashMap<>();
- details.put(ApiConstants.TEMPLATE_ID, templateUuid);
-
- ServiceOfferingVO serviceOffering = mock(ServiceOfferingVO.class);
- when(serviceOffering.getName()).thenReturn("service-offering1");
- when(serviceOfferingDao.findByUuid(serviceOfferingUuid)).thenReturn(serviceOffering);
- details.put(ApiConstants.SERVICE_OFFERING_ID, serviceOfferingUuid);
-
- NetworkVO network = mock(NetworkVO.class);
- when(network.getName()).thenReturn("network1");
- when(networkDao.findByUuid("network-uuid1")).thenReturn(network);
- details.put(ApiConstants.NICS, "[{\"networkid\":\"network-uuid1\"}]");
-
- Mockito.when(backupDetailsDao.listDetailsKeyPairs(backup.getId(), true)).thenReturn(details);
-
- BackupResponse response = backupManager.createBackupResponse(backup, true);
-
- Assert.assertEquals("backup-uuid", response.getId());
- Assert.assertEquals("test-vm", response.getVmName());
- Assert.assertEquals("account-uuid", response.getAccountId());
- Assert.assertEquals("test-account", response.getAccount());
- Assert.assertEquals("domain-uuid", response.getDomainId());
- Assert.assertEquals("test-domain", response.getDomain());
- Assert.assertEquals("zone-uuid", response.getZoneId());
- Assert.assertEquals("test-zone", response.getZone());
- Assert.assertEquals("offering-uuid", response.getBackupOfferingId());
- Assert.assertEquals("test-offering", response.getBackupOffering());
- Assert.assertEquals("MANUAL", response.getIntervalType());
- Assert.assertEquals("{serviceofferingid=service-offering-uuid1, isiso=false, hypervisor=Simulator, " +
- "nics=[{\"networkid\":\"network-uuid1\",\"networkname\":\"network1\"}], serviceofferingname=service-offering1, " +
- "templatename=template1, templateid=template-uuid1}", response.getVmDetails().toString());
- Assert.assertEquals(true, response.getVmOfferingRemoved());
- }
-
@Test
public void validateAndGetDefaultBackupRetentionIfRequiredTestReturnZeroAsDefaultValue() {
int retention = backupManager.validateAndGetDefaultBackupRetentionIfRequired(null, backupOfferingVOMock, null);
@@ -1819,341 +971,4 @@ public void sendExceededBackupLimitAlertTestSendAlertForBackupStorageResourceTyp
expectedAlertDetails
);
}
-
- @Test
- public void testListBackupSchedulesAsRootAdmin() {
- long vmId = 1L;
- ListBackupScheduleCmd cmd = Mockito.mock(ListBackupScheduleCmd.class);
- Mockito.when(cmd.getVmId()).thenReturn(vmId);
- Mockito.when(cmd.getId()).thenReturn(1L);
-
- // Mock VM for validation
- VMInstanceVO vm = Mockito.mock(VMInstanceVO.class);
- Mockito.when(vmInstanceDao.findById(vmId)).thenReturn(vm);
- Mockito.when(vm.getDataCenterId()).thenReturn(1L);
- overrideBackupFrameworkConfigValue();
- Mockito.doNothing().when(accountManager).checkAccess(Mockito.any(), Mockito.any(), Mockito.anyBoolean(), Mockito.any());
-
- BackupScheduleVO schedule1 = Mockito.mock(BackupScheduleVO.class);
- BackupScheduleVO schedule2 = Mockito.mock(BackupScheduleVO.class);
- List schedules = List.of(schedule1, schedule2);
-
- SearchBuilder searchBuilder = Mockito.mock(SearchBuilder.class);
- SearchCriteria searchCriteria = Mockito.mock(SearchCriteria.class);
- BackupScheduleVO entity = Mockito.mock(BackupScheduleVO.class);
-
- Mockito.when(backupScheduleDao.createSearchBuilder()).thenReturn(searchBuilder);
- Mockito.when(searchBuilder.entity()).thenReturn(entity);
- Mockito.when(searchBuilder.and(Mockito.anyString(), (Object) any(), Mockito.any())).thenReturn(searchBuilder);
- Mockito.when(searchBuilder.create()).thenReturn(searchCriteria);
-
- Mockito.when(backupScheduleDao.searchAndCount(Mockito.any(), Mockito.any())).thenReturn(new Pair<>(schedules, schedules.size()));
- List result = backupManager.listBackupSchedules(cmd);
-
- assertEquals(2, result.size());
- assertTrue(result.contains(schedule1));
- assertTrue(result.contains(schedule2));
- }
-
- @Test
- public void testListBackupSchedulesAsNonAdmin() {
- long vmId = 1L;
- ListBackupScheduleCmd cmd = Mockito.mock(ListBackupScheduleCmd.class);
- Mockito.when(cmd.getVmId()).thenReturn(vmId);
- Mockito.when(cmd.getId()).thenReturn(1L);
-
- // Mock VM for validation
- VMInstanceVO vm = Mockito.mock(VMInstanceVO.class);
- Mockito.when(vmInstanceDao.findById(vmId)).thenReturn(vm);
- Mockito.when(vm.getDataCenterId()).thenReturn(1L);
- overrideBackupFrameworkConfigValue();
- Mockito.doNothing().when(accountManager).checkAccess(Mockito.any(), Mockito.any(), Mockito.anyBoolean(), Mockito.any());
-
- BackupScheduleVO schedule = Mockito.mock(BackupScheduleVO.class);
- List schedules = List.of(schedule);
-
- SearchBuilder searchBuilder = Mockito.mock(SearchBuilder.class);
- SearchCriteria searchCriteria = Mockito.mock(SearchCriteria.class);
- BackupScheduleVO entity = Mockito.mock(BackupScheduleVO.class);
-
- Mockito.when(backupScheduleDao.createSearchBuilder()).thenReturn(searchBuilder);
- Mockito.when(searchBuilder.create()).thenReturn(searchCriteria);
- Mockito.when(searchBuilder.entity()).thenReturn(entity);
- Mockito.when(searchBuilder.and(Mockito.anyString(), (Object) any(), Mockito.any())).thenReturn(searchBuilder);
- Mockito.lenient().when(backupScheduleDao.search(Mockito.eq(searchCriteria), Mockito.any())).thenReturn(schedules);
-
- Mockito.doNothing().when(accountManager).buildACLSearchBuilder(Mockito.any(), Mockito.anyLong(), Mockito.anyBoolean(), Mockito.anyList(), Mockito.any());
- Mockito.doNothing().when(accountManager).buildACLSearchCriteria(Mockito.any(), Mockito.anyLong(), Mockito.anyBoolean(), Mockito.anyList(), Mockito.any());
-
- Mockito.when(backupScheduleDao.searchAndCount(Mockito.any(), Mockito.any())).thenReturn(new Pair<>(schedules, schedules.size()));
- List result = backupManager.listBackupSchedules(cmd);
-
- assertEquals(1, result.size());
- assertTrue(result.contains(schedule));
- }
-
- @Test
- public void testCanCreateInstanceFromBackupAcrossZonesSuccess() {
- Long backupId = 1L;
- Long backupOfferingId = 2L;
- String providerName = "testbackupprovider";
-
- BackupVO backup = mock(BackupVO.class);
- when(backup.getBackupOfferingId()).thenReturn(backupOfferingId);
-
- BackupOfferingVO offering = mock(BackupOfferingVO.class);
- when(offering.getProvider()).thenReturn(providerName);
-
- BackupProvider backupProvider = mock(BackupProvider.class);
- when(backupProvider.crossZoneInstanceCreationEnabled(offering)).thenReturn(true);
-
- when(backupDao.findById(backupId)).thenReturn(backup);
- when(backupOfferingDao.findByIdIncludingRemoved(backupOfferingId)).thenReturn(offering);
- when(backupManager.getBackupProvider(providerName)).thenReturn(backupProvider);
-
- Boolean result = backupManager.canCreateInstanceFromBackupAcrossZones(backupId);
-
- assertTrue(result);
- verify(backupDao, times(1)).findById(backupId);
- verify(backupOfferingDao, times(1)).findByIdIncludingRemoved(backupOfferingId);
- verify(backupManager, times(1)).getBackupProvider(providerName);
- verify(backupProvider, times(1)).crossZoneInstanceCreationEnabled(offering);
- }
-
- @Test
- public void testCanCreateInstanceFromBackupAcrossZonesFalse() {
- Long backupId = 1L;
- Long backupOfferingId = 2L;
- String providerName = "testbackupprovider";
-
- BackupVO backup = mock(BackupVO.class);
- when(backup.getBackupOfferingId()).thenReturn(backupOfferingId);
-
- BackupOfferingVO offering = mock(BackupOfferingVO.class);
- when(offering.getProvider()).thenReturn(providerName);
-
- BackupProvider backupProvider = mock(BackupProvider.class);
- when(backupProvider.crossZoneInstanceCreationEnabled(offering)).thenReturn(false);
-
- when(backupDao.findById(backupId)).thenReturn(backup);
- when(backupOfferingDao.findByIdIncludingRemoved(backupOfferingId)).thenReturn(offering);
- when(backupManager.getBackupProvider(providerName)).thenReturn(backupProvider);
-
- Boolean result = backupManager.canCreateInstanceFromBackupAcrossZones(backupId);
-
- assertFalse(result);
- verify(backupDao, times(1)).findById(backupId);
- verify(backupOfferingDao, times(1)).findByIdIncludingRemoved(backupOfferingId);
- verify(backupManager, times(1)).getBackupProvider(providerName);
- verify(backupProvider, times(1)).crossZoneInstanceCreationEnabled(offering);
- }
-
- @Test
- public void testCanCreateInstanceFromBackupAcrossZonesOfferingNotFound() {
- Long backupId = 1L;
- Long backupOfferingId = 2L;
-
- BackupVO backup = mock(BackupVO.class);
- when(backup.getBackupOfferingId()).thenReturn(backupOfferingId);
-
- when(backupDao.findById(backupId)).thenReturn(backup);
- when(backupOfferingDao.findByIdIncludingRemoved(backupOfferingId)).thenReturn(null);
-
- CloudRuntimeException exception = Assert.assertThrows(CloudRuntimeException.class,
- () -> backupManager.canCreateInstanceFromBackupAcrossZones(backupId));
-
- assertEquals("Failed to find backup offering", exception.getMessage());
- verify(backupDao, times(1)).findById(backupId);
- verify(backupOfferingDao, times(1)).findByIdIncludingRemoved(backupOfferingId);
- verify(backupManager, never()).getBackupProvider(any(String.class));
- }
-
- @Test
- public void testRestoreBackupSuccess() throws NoTransitionException {
- Long backupId = 1L;
- Long vmId = 2L;
- Long zoneId = 3L;
- Long accountId = 4L;
- Long domainId = 5L;
- Long userId = 6L;
- Long offeringId = 7L;
- String vmInstanceName = "test-vm";
- Hypervisor.HypervisorType hypervisorType = Hypervisor.HypervisorType.KVM;
-
- BackupVO backup = mock(BackupVO.class);
- when(backup.getVmId()).thenReturn(vmId);
- when(backup.getZoneId()).thenReturn(zoneId);
- when(backup.getStatus()).thenReturn(Backup.Status.BackedUp);
- when(backup.getBackupOfferingId()).thenReturn(offeringId);
- Backup.VolumeInfo volumeInfo = new Backup.VolumeInfo("uuid", "path", Volume.Type.ROOT, 1024L, 0L, "disk-offering-uuid", 1000L, 2000L);
- when(backup.getBackedUpVolumes()).thenReturn(List.of(volumeInfo));
- when(backup.getUuid()).thenReturn("backup-uuid");
-
- VMInstanceVO vm = mock(VMInstanceVO.class);
- when(vm.getId()).thenReturn(vmId);
- when(vm.getDataCenterId()).thenReturn(zoneId);
- when(vm.getDomainId()).thenReturn(domainId);
- when(vm.getAccountId()).thenReturn(accountId);
- when(vm.getUserId()).thenReturn(userId);
- when(vm.getInstanceName()).thenReturn(vmInstanceName);
- when(vm.getHypervisorType()).thenReturn(hypervisorType);
- when(vm.getState()).thenReturn(VirtualMachine.State.Stopped);
- when(vm.getRemoved()).thenReturn(null);
- when(vm.getBackupOfferingId()).thenReturn(offeringId);
-
- BackupOfferingVO offering = mock(BackupOfferingVO.class);
- when(offering.getProvider()).thenReturn("testbackupprovider");
-
- VolumeVO volume = mock(VolumeVO.class);
- when(volumeDao.findByInstance(vmId)).thenReturn(Collections.singletonList(volume));
-
- BackupProvider backupProvider = mock(BackupProvider.class);
- when(backupProvider.restoreVMFromBackup(vm, backup)).thenReturn(true);
-
- when(backupDao.findById(backupId)).thenReturn(backup);
- when(vmInstanceDao.findByIdIncludingRemoved(vmId)).thenReturn(vm);
- when(backupOfferingDao.findByIdIncludingRemoved(offeringId)).thenReturn(offering);
- when(backupManager.getBackupProvider("testbackupprovider")).thenReturn(backupProvider);
- doReturn(true).when(backupManager).importRestoredVM(zoneId, domainId, accountId, userId, vmInstanceName, hypervisorType, backup);
- doNothing().when(backupManager).validateBackupForZone(any());
- when(virtualMachineManager.stateTransitTo(any(), any(), any())).thenReturn(true);
-
- try (MockedStatic utils = Mockito.mockStatic(ActionEventUtils.class)) {
- Mockito.when(ActionEventUtils.onStartedActionEvent(Mockito.anyLong(), Mockito.anyLong(),
- Mockito.anyString(), Mockito.anyString(), Mockito.anyLong(), Mockito.anyString(),
- Mockito.eq(true), Mockito.eq(0))).thenReturn(1L);
-
- boolean result = backupManager.restoreBackup(backupId);
-
- assertTrue(result);
- verify(backupDao, times(1)).findById(backupId);
- verify(vmInstanceDao, times(1)).findByIdIncludingRemoved(vmId);
- verify(backupOfferingDao, times(2)).findByIdIncludingRemoved(offeringId);
- verify(backupProvider, times(1)).restoreVMFromBackup(vm, backup);
- verify(backupManager, times(1)).importRestoredVM(zoneId, domainId, accountId, userId, vmInstanceName, hypervisorType, backup);
- }
- }
-
- @Test
- public void testRestoreBackupBackupNotFound() {
- Long backupId = 1L;
-
- when(backupDao.findById(backupId)).thenReturn(null);
-
- CloudRuntimeException exception = Assert.assertThrows(CloudRuntimeException.class,
- () -> backupManager.restoreBackup(backupId));
-
- assertEquals("Backup " + backupId + " does not exist", exception.getMessage());
- verify(backupDao, times(1)).findById(backupId);
- verify(vmInstanceDao, never()).findByIdIncludingRemoved(any());
- }
-
- @Test
- public void testRestoreBackupBackupNotBackedUp() {
- Long backupId = 1L;
-
- BackupVO backup = mock(BackupVO.class);
- when(backup.getStatus()).thenReturn(Backup.Status.BackingUp);
-
- when(backupDao.findById(backupId)).thenReturn(backup);
-
- CloudRuntimeException exception = Assert.assertThrows(CloudRuntimeException.class,
- () -> backupManager.restoreBackup(backupId));
-
- assertEquals("Backup should be in BackedUp state", exception.getMessage());
- verify(backupDao, times(1)).findById(backupId);
- verify(vmInstanceDao, never()).findByIdIncludingRemoved(any());
- }
-
- @Test
- public void testRestoreBackupVmExpunging() {
- Long backupId = 1L;
- Long vmId = 2L;
- Long zoneId = 3L;
-
- BackupVO backup = mock(BackupVO.class);
- when(backup.getVmId()).thenReturn(vmId);
- when(backup.getZoneId()).thenReturn(zoneId);
- when(backup.getStatus()).thenReturn(Backup.Status.BackedUp);
-
- VMInstanceVO vm = mock(VMInstanceVO.class);
- when(vm.getState()).thenReturn(VirtualMachine.State.Expunging);
-
- when(backupDao.findById(backupId)).thenReturn(backup);
- when(vmInstanceDao.findByIdIncludingRemoved(vmId)).thenReturn(vm);
- doNothing().when(backupManager).validateBackupForZone(any());
-
- CloudRuntimeException exception = Assert.assertThrows(CloudRuntimeException.class,
- () -> backupManager.restoreBackup(backupId));
-
- assertEquals("The Instance from which the backup was taken could not be found.", exception.getMessage());
- verify(backupDao, times(1)).findById(backupId);
- verify(vmInstanceDao, times(1)).findByIdIncludingRemoved(vmId);
- }
-
- @Test
- public void testRestoreBackupVmNotStopped() {
- Long backupId = 1L;
- Long vmId = 2L;
- Long zoneId = 3L;
-
- BackupVO backup = mock(BackupVO.class);
- when(backup.getVmId()).thenReturn(vmId);
- when(backup.getZoneId()).thenReturn(zoneId);
- when(backup.getStatus()).thenReturn(Backup.Status.BackedUp);
-
- VMInstanceVO vm = mock(VMInstanceVO.class);
- when(vm.getState()).thenReturn(VirtualMachine.State.Running);
- when(vm.getRemoved()).thenReturn(null);
-
- when(backupDao.findById(backupId)).thenReturn(backup);
- when(vmInstanceDao.findByIdIncludingRemoved(vmId)).thenReturn(vm);
- doNothing().when(backupManager).validateBackupForZone(any());
-
- CloudRuntimeException exception = Assert.assertThrows(CloudRuntimeException.class,
- () -> backupManager.restoreBackup(backupId));
-
- assertEquals("Existing VM should be stopped before being restored from backup", exception.getMessage());
- verify(backupDao, times(1)).findById(backupId);
- verify(vmInstanceDao, times(1)).findByIdIncludingRemoved(vmId);
- }
-
- @Test
- public void testRestoreBackupVolumeMismatch() {
- Long backupId = 1L;
- Long vmId = 2L;
- Long zoneId = 3L;
-
- BackupVO backup = mock(BackupVO.class);
- when(backup.getVmId()).thenReturn(vmId);
- when(backup.getZoneId()).thenReturn(zoneId);
- when(backup.getStatus()).thenReturn(Backup.Status.BackedUp);
- when(backup.getBackedUpVolumes()).thenReturn(Collections.emptyList());
-
- VMInstanceVO vm = mock(VMInstanceVO.class);
- when(vm.getId()).thenReturn(vmId);
- when(vm.getState()).thenReturn(VirtualMachine.State.Destroyed);
- when(vm.getRemoved()).thenReturn(null);
- when(vm.getBackupVolumeList()).thenReturn(Collections.emptyList());
-
- VolumeVO volume = mock(VolumeVO.class);
- when(volumeDao.findByInstance(vmId)).thenReturn(Collections.singletonList(volume));
-
- when(backupDao.findById(backupId)).thenReturn(backup);
- when(vmInstanceDao.findByIdIncludingRemoved(vmId)).thenReturn(vm);
- doNothing().when(backupManager).validateBackupForZone(any());
-
- try (MockedStatic utils = Mockito.mockStatic(ActionEventUtils.class)) {
- Mockito.when(ActionEventUtils.onStartedActionEvent(Mockito.anyLong(), Mockito.anyLong(),
- Mockito.anyString(), Mockito.anyString(), Mockito.anyLong(), Mockito.anyString(),
- Mockito.eq(true), Mockito.eq(0))).thenReturn(1L);
- CloudRuntimeException exception = Assert.assertThrows(CloudRuntimeException.class,
- () -> backupManager.restoreBackup(backupId));
-
- assertEquals("Unable to restore VM with the current backup as the backup has different number of disks as the VM", exception.getMessage());
- }
- verify(backupDao, times(1)).findById(backupId);
- verify(vmInstanceDao, times(1)).findByIdIncludingRemoved(vmId);
- verify(volumeDao, times(1)).findByInstance(vmId);
- }
-}
\ No newline at end of file
+}
From 0bcc18d77bda21cdd72a6d5906bed774afbd86e3 Mon Sep 17 00:00:00 2001
From: Dajeong-Park
Date: Mon, 19 Jan 2026 10:34:44 +0900
Subject: [PATCH 24/34] Revert "Update BackupManagerTest.java"
This reverts commit 46349c21d7d4f6d7ded8a8679db16420aa480bbf.
---
.../java/org/apache/cloudstack/backup/BackupManagerTest.java | 1 -
1 file changed, 1 deletion(-)
diff --git a/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java b/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java
index 88892d982d87..66fa2d33cb1e 100644
--- a/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java
+++ b/server/src/test/java/org/apache/cloudstack/backup/BackupManagerTest.java
@@ -49,7 +49,6 @@
import org.apache.cloudstack.api.ServerApiException;
import org.apache.cloudstack.api.command.admin.backup.UpdateBackupOfferingCmd;
import org.apache.cloudstack.api.command.user.backup.CreateBackupScheduleCmd;
-import org.apache.cloudstack.api.command.user.backup.DeleteBackupScheduleCmd;
import org.apache.cloudstack.backup.dao.BackupDao;
import org.apache.cloudstack.backup.dao.BackupOfferingDao;
import org.apache.cloudstack.backup.dao.BackupScheduleDao;
From 062556d2aaa5a66e95cc5d29fea09a546a202448 Mon Sep 17 00:00:00 2001
From: Dajeong-Park
Date: Mon, 19 Jan 2026 10:34:51 +0900
Subject: [PATCH 25/34] Revert "Update VolumeApiServiceImpl.java"
This reverts commit 7a02284ac6009aa80e1d2e8b5e5b389c7ac72551.
---
.../src/main/java/com/cloud/storage/VolumeApiServiceImpl.java | 2 ++
1 file changed, 2 insertions(+)
diff --git a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java
index c20ca58d9416..6d975e1809d4 100644
--- a/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java
+++ b/server/src/main/java/com/cloud/storage/VolumeApiServiceImpl.java
@@ -353,6 +353,8 @@ public class VolumeApiServiceImpl extends ManagerBase implements VolumeApiServic
private BackupDao backupDao;
@Inject
private StatsCollector statsCollector;
+ @Inject
+ HostPodDao podDao;
protected Gson _gson;
From 6ce7bab061929bfbca536c617ac5a4ed52db06c5 Mon Sep 17 00:00:00 2001
From: Dajeong-Park
Date: Mon, 19 Jan 2026 10:34:57 +0900
Subject: [PATCH 26/34] Revert "Update BackupManagerImpl.java"
This reverts commit 78dd41e780f9def5a8900edea65eb41405ce5e76.
---
.../java/org/apache/cloudstack/backup/BackupManagerImpl.java | 2 ++
1 file changed, 2 insertions(+)
diff --git a/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java b/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java
index c2deb6650ca1..5c1c7f9d955f 100644
--- a/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java
+++ b/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java
@@ -33,6 +33,7 @@
import com.cloud.alert.AlertManager;
import com.cloud.configuration.Resource;
import com.cloud.exception.ResourceAllocationException;
+import com.cloud.storage.Snapshot;
import com.cloud.storage.VolumeApiService;
import com.cloud.user.DomainManager;
import com.cloud.user.ResourceLimitService;
@@ -73,6 +74,7 @@
import org.apache.cloudstack.context.CallContext;
import org.apache.cloudstack.engine.orchestration.service.VolumeOrchestrationService;
import org.apache.cloudstack.framework.config.ConfigKey;
+import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
import org.apache.cloudstack.framework.jobs.AsyncJobDispatcher;
import org.apache.cloudstack.framework.jobs.AsyncJobManager;
import org.apache.cloudstack.framework.jobs.impl.AsyncJobVO;
From 0dfcffb5f6f656875117f3a867f40ac7ba73bae4 Mon Sep 17 00:00:00 2001
From: Dajeong-Park
Date: Mon, 19 Jan 2026 10:35:05 +0900
Subject: [PATCH 27/34] Revert "Update BackupSchedule.java"
This reverts commit 8fcc034526b84c16fc9fa11d9864e8dae38e2e30.
---
.../main/java/org/apache/cloudstack/backup/BackupSchedule.java | 1 +
1 file changed, 1 insertion(+)
diff --git a/api/src/main/java/org/apache/cloudstack/backup/BackupSchedule.java b/api/src/main/java/org/apache/cloudstack/backup/BackupSchedule.java
index da90da508fff..26adc80db37a 100644
--- a/api/src/main/java/org/apache/cloudstack/backup/BackupSchedule.java
+++ b/api/src/main/java/org/apache/cloudstack/backup/BackupSchedule.java
@@ -31,4 +31,5 @@ public interface BackupSchedule extends InternalIdentity {
Date getScheduledTimestamp();
Long getAsyncJobId();
int getMaxBackups();
+ String getUuid();
}
From 4f50052e33dcaff825ddfab8c4bdb3aca9f3f91a Mon Sep 17 00:00:00 2001
From: Dajeong-Park
Date: Mon, 19 Jan 2026 10:35:11 +0900
Subject: [PATCH 28/34] =?UTF-8?q?Revert=20"=EB=B9=8C=EB=93=9C=EC=98=A4?=
=?UTF-8?q?=EB=A5=98=20=EC=88=98=EC=A0=95"?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This reverts commit 979c859e1289b646bafd630526eebb429c720afd.
---
.../main/java/com/cloud/storage/dao/BucketDaoImpl.java | 8 --------
.../org/apache/cloudstack/backup/dao/BackupDaoImpl.java | 8 --------
2 files changed, 16 deletions(-)
diff --git a/engine/schema/src/main/java/com/cloud/storage/dao/BucketDaoImpl.java b/engine/schema/src/main/java/com/cloud/storage/dao/BucketDaoImpl.java
index 963bcd6cfe6b..473879d933dc 100644
--- a/engine/schema/src/main/java/com/cloud/storage/dao/BucketDaoImpl.java
+++ b/engine/schema/src/main/java/com/cloud/storage/dao/BucketDaoImpl.java
@@ -114,12 +114,4 @@ public Long calculateObjectStorageAllocationForAccount(long accountId) {
Long totalQuota = customSearch(sc, null).get(0).sum;
return (totalQuota * Resource.ResourceType.bytesToGiB);
}
-
- public static class SumCount {
- public long sum;
- public long count;
-
- public SumCount() {
- }
- }
}
diff --git a/engine/schema/src/main/java/org/apache/cloudstack/backup/dao/BackupDaoImpl.java b/engine/schema/src/main/java/org/apache/cloudstack/backup/dao/BackupDaoImpl.java
index 674e8cf428e6..3dbdb5abc828 100644
--- a/engine/schema/src/main/java/org/apache/cloudstack/backup/dao/BackupDaoImpl.java
+++ b/engine/schema/src/main/java/org/apache/cloudstack/backup/dao/BackupDaoImpl.java
@@ -233,12 +233,4 @@ public BackupResponse newBackupResponse(Backup backup) {
response.setObjectName("backup");
return response;
}
-
- public static class SumCount {
- public long sum;
- public long count;
-
- public SumCount() {
- }
- }
}
From 393fc5373f369d79ca3612f708a3683c49a2027a Mon Sep 17 00:00:00 2001
From: Dajeong-Park
Date: Mon, 19 Jan 2026 10:35:19 +0900
Subject: [PATCH 29/34] Revert "Update BackupVO.java"
This reverts commit 3762f5405a19632c2fb2b1dd49a23256ae081434.
---
.../src/main/java/org/apache/cloudstack/backup/BackupVO.java | 2 ++
1 file changed, 2 insertions(+)
diff --git a/engine/schema/src/main/java/org/apache/cloudstack/backup/BackupVO.java b/engine/schema/src/main/java/org/apache/cloudstack/backup/BackupVO.java
index ebe98b3dda53..81dd0fea68d3 100644
--- a/engine/schema/src/main/java/org/apache/cloudstack/backup/BackupVO.java
+++ b/engine/schema/src/main/java/org/apache/cloudstack/backup/BackupVO.java
@@ -22,10 +22,12 @@
import org.apache.cloudstack.utils.reflectiontostringbuilderutils.ReflectionToStringBuilderUtils;
import org.apache.commons.lang3.StringUtils;
+import java.beans.Transient;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
+import java.util.Map;
import java.util.UUID;
import javax.persistence.Column;
From 0ad6131ae7f92e973f484485225470b7754e3431 Mon Sep 17 00:00:00 2001
From: Dajeong-Park
Date: Mon, 19 Jan 2026 10:35:25 +0900
Subject: [PATCH 30/34] =?UTF-8?q?Revert=20"=EB=B9=8C=EB=93=9C=EC=98=A4?=
=?UTF-8?q?=EB=A5=98=20=EC=A0=81=EC=9A=A9"?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
This reverts commit c585cad88e07e4865c98935a2a24014c339ae0e8.
---
api/src/main/java/com/cloud/event/EventTypes.java | 2 +-
api/src/main/java/com/cloud/storage/VolumeApiService.java | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/api/src/main/java/com/cloud/event/EventTypes.java b/api/src/main/java/com/cloud/event/EventTypes.java
index b9c8f0b55a6d..97d889bebcfa 100644
--- a/api/src/main/java/com/cloud/event/EventTypes.java
+++ b/api/src/main/java/com/cloud/event/EventTypes.java
@@ -799,7 +799,7 @@ public class EventTypes {
// DISASTER RECOVERY
public static final String EVENT_DISASTER_RECOVERY_CLUSTER = "DISASTER.RECOVERY.CLUSTER";
-
+
// Resource Limit
public static final String EVENT_RESOURCE_LIMIT_UPDATE = "RESOURCE.LIMIT.UPDATE";
diff --git a/api/src/main/java/com/cloud/storage/VolumeApiService.java b/api/src/main/java/com/cloud/storage/VolumeApiService.java
index 0698c09e0887..1239d37af26d 100644
--- a/api/src/main/java/com/cloud/storage/VolumeApiService.java
+++ b/api/src/main/java/com/cloud/storage/VolumeApiService.java
@@ -197,6 +197,6 @@ Snapshot takeSnapshot(Long volumeId, Long policyId, Long snapshotId, Account acc
Volume cloneVolumeFromSnapshot(Volume volume, long snapshotId, Long vmId) throws StorageUnavailableException;
Volume updateCompressDedupVolume(UpdateCompressDedupCmd cmd);
-
+
Long getVolumePhysicalSize(Storage.ImageFormat format, String path, String chainInfo);
}
From a0d7e43f0c9e304767ee5ba7e40181ec9c4b69f2 Mon Sep 17 00:00:00 2001
From: Dajeong-Park
Date: Mon, 19 Jan 2026 13:02:29 +0900
Subject: [PATCH 31/34] Fix deletion of backup schedules (#11222)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
미반영 적용
---
.../api/response/BackupScheduleResponse.java | 13 ++++++++++---
.../backup/dao/BackupScheduleDaoImpl.java | 3 ++-
.../resources/META-INF/db/schema-42010to42100.sql | 3 +++
ui/src/views/compute/backup/BackupSchedule.vue | 2 +-
4 files changed, 16 insertions(+), 5 deletions(-)
diff --git a/api/src/main/java/org/apache/cloudstack/api/response/BackupScheduleResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/BackupScheduleResponse.java
index d7c6f96add5b..92f1bad54470 100644
--- a/api/src/main/java/org/apache/cloudstack/api/response/BackupScheduleResponse.java
+++ b/api/src/main/java/org/apache/cloudstack/api/response/BackupScheduleResponse.java
@@ -28,6 +28,9 @@
@EntityReference(value = BackupSchedule.class)
public class BackupScheduleResponse extends BaseResponse {
+ @SerializedName(ApiConstants.ID)
+ @Param(description = "ID of the backup schedule.")
+ private String id;
@SerializedName(ApiConstants.VIRTUAL_MACHINE_NAME)
@Param(description = "name of the VM")
@@ -51,7 +54,11 @@ public class BackupScheduleResponse extends BaseResponse {
@SerializedName(ApiConstants.MAX_BACKUPS)
@Param(description = "maximum number of backups retained")
- private Integer maxBakups;
+ private Integer maxBackups;
+
+ public void setId(String id) {
+ this.id = id;
+ }
public String getVmName() {
return vmName;
@@ -93,7 +100,7 @@ public void setTimezone(String timezone) {
this.timezone = timezone;
}
- public void setMaxBakups(Integer maxBakups) {
- this.maxBakups = maxBakups;
+ public void setMaxBackups(Integer maxBackups) {
+ this.maxBackups = maxBackups;
}
}
diff --git a/engine/schema/src/main/java/org/apache/cloudstack/backup/dao/BackupScheduleDaoImpl.java b/engine/schema/src/main/java/org/apache/cloudstack/backup/dao/BackupScheduleDaoImpl.java
index aac2e3bf2320..9374798dde32 100644
--- a/engine/schema/src/main/java/org/apache/cloudstack/backup/dao/BackupScheduleDaoImpl.java
+++ b/engine/schema/src/main/java/org/apache/cloudstack/backup/dao/BackupScheduleDaoImpl.java
@@ -92,12 +92,13 @@ public List getSchedulesToExecute(Date currentTimestamp) {
public BackupScheduleResponse newBackupScheduleResponse(BackupSchedule schedule) {
VMInstanceVO vm = vmInstanceDao.findByIdIncludingRemoved(schedule.getVmId());
BackupScheduleResponse response = new BackupScheduleResponse();
+ response.setId(schedule.getUuid());
response.setVmId(vm.getUuid());
response.setVmName(vm.getHostName());
response.setIntervalType(schedule.getScheduleType());
response.setSchedule(schedule.getSchedule());
response.setTimezone(schedule.getTimezone());
- response.setMaxBakups(schedule.getMaxBackups());
+ response.setMaxBackups(schedule.getMaxBackups());
response.setObjectName("backupschedule");
return response;
}
diff --git a/engine/schema/src/main/resources/META-INF/db/schema-42010to42100.sql b/engine/schema/src/main/resources/META-INF/db/schema-42010to42100.sql
index 31ffbae10cab..dfff847e47a9 100644
--- a/engine/schema/src/main/resources/META-INF/db/schema-42010to42100.sql
+++ b/engine/schema/src/main/resources/META-INF/db/schema-42010to42100.sql
@@ -27,3 +27,6 @@ CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.console_session', 'console_endpoint_
-- Add client_address column to cloud.console_session table
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.console_session', 'client_address', 'VARCHAR(45)');
+
+CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.backup_schedule', 'uuid', 'VARCHAR(40) NOT NULL');
+UPDATE `cloud`.`backup_schedule` SET uuid = UUID();
diff --git a/ui/src/views/compute/backup/BackupSchedule.vue b/ui/src/views/compute/backup/BackupSchedule.vue
index 7309068ea069..cdf62b84c0da 100644
--- a/ui/src/views/compute/backup/BackupSchedule.vue
+++ b/ui/src/views/compute/backup/BackupSchedule.vue
@@ -172,7 +172,7 @@ export default {
methods: {
handleClickDelete (record) {
const params = {}
- params.virtualmachineid = record.virtualmachineid
+ params.id = record.id
this.actionLoading = true
api('deleteBackupSchedule', params).then(json => {
if (json.deletebackupscheduleresponse.success) {
From 626ca83a57426c0247c313420500362cc4c30409 Mon Sep 17 00:00:00 2001
From: Dajeong-Park
Date: Mon, 19 Jan 2026 13:56:04 +0900
Subject: [PATCH 32/34] =?UTF-8?q?commvault=20=EB=B0=B1=EC=97=85=20?=
=?UTF-8?q?=EB=8F=99=EA=B8=B0=ED=99=94=20=EC=84=A4=EC=A0=95=EC=9D=84=20?=
=?UTF-8?q?=EC=9C=84=ED=95=9C=20=EC=BD=94=EB=93=9C=20=EC=B6=94=EA=B0=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Add Resource Limits to Backups and Object Storage (apache#10017) 에서 백업 동기화 로직이 변경되어, commvault 백업 동기화 설정을 위한 코드 추가
---
.../java/org/apache/cloudstack/backup/BackupManagerImpl.java | 1 +
1 file changed, 1 insertion(+)
diff --git a/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java b/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java
index 1177c1f9a0e3..abf3b0e6c76f 100644
--- a/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java
+++ b/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java
@@ -1650,6 +1650,7 @@ private void syncBackups(BackupProvider backupProvider, VirtualMachine vm, Backu
Transaction.execute(new TransactionCallbackNoReturn() {
@Override
public void doInTransactionWithoutResult(TransactionStatus status) {
+ backupProvider.syncBackups(vm, metric);
final List backupsInDb = backupDao.listByVmId(null, vm.getId());
List restorePoints = backupProvider.listRestorePoints(vm);
if (restorePoints == null) {
From e61f7786203c3583860ca3d60c1962a39d24713c Mon Sep 17 00:00:00 2001
From: Dajeong-Park
Date: Tue, 20 Jan 2026 09:34:04 +0900
Subject: [PATCH 33/34] =?UTF-8?q?=ED=85=8C=EC=8A=A4=ED=8A=B8=20=EB=A1=9C?=
=?UTF-8?q?=EA=B7=B8=20=EC=B6=94=EA=B0=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../apache/cloudstack/backup/NASBackupProvider.java | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/plugins/backup/nas/src/main/java/org/apache/cloudstack/backup/NASBackupProvider.java b/plugins/backup/nas/src/main/java/org/apache/cloudstack/backup/NASBackupProvider.java
index 951bbeda4e9b..c90fc4b3f604 100644
--- a/plugins/backup/nas/src/main/java/org/apache/cloudstack/backup/NASBackupProvider.java
+++ b/plugins/backup/nas/src/main/java/org/apache/cloudstack/backup/NASBackupProvider.java
@@ -273,7 +273,15 @@ public Pair restoreBackedUpVolume(Backup backup, String volumeU
final VolumeVO volume = volumeDao.findByUuid(volumeUuid);
final VirtualMachine backupSourceVm = vmInstanceDao.findById(backup.getVmId());
final StoragePoolHostVO dataStore = storagePoolHostDao.findByUuid(dataStoreUuid);
- final HostVO hostVO = hostDao.findByIp(hostIp);
+ LOG.info("NASBackupProvider.java restoreBackedUpVolume:::::");
+ LOG.info("hostIP: " +hostIp);
+ HostVO hostVO = hostDao.findByIp(hostIp);
+ LOG.info("hostVO: " +hostVO);
+ if(hostVO == null) {
+ LOG.info("hostVO == null");
+ hostVO = hostDao.findByName(hostIp);
+ LOG.info("hostVO: " +hostVO);
+ }
Optional matchingVolume = getBackedUpVolumeInfo(backupSourceVm.getBackupVolumeList(), volumeUuid);
Long backedUpVolumeSize = matchingVolume.isPresent() ? matchingVolume.get().getSize() : 0L;
From 105fec00a51f1630d13cfbba40fa5486224360e9 Mon Sep 17 00:00:00 2001
From: Dajeong-Park
Date: Tue, 20 Jan 2026 10:01:31 +0900
Subject: [PATCH 34/34] =?UTF-8?q?=ED=92=80=20=EC=8A=A4=ED=86=A0=EB=A6=AC?=
=?UTF-8?q?=EC=A7=80=20=EA=B2=BD=EB=A1=9C=20=EC=98=A4=EB=A5=98=20=EB=B0=8F?=
=?UTF-8?q?=20=ED=98=B8=EC=8A=A4=ED=8A=B8VO=20=EB=84=90=20=EC=B2=98?=
=?UTF-8?q?=EB=A6=AC?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../cloudstack/backup/NASBackupProvider.java | 29 ++++++++++---------
1 file changed, 16 insertions(+), 13 deletions(-)
diff --git a/plugins/backup/nas/src/main/java/org/apache/cloudstack/backup/NASBackupProvider.java b/plugins/backup/nas/src/main/java/org/apache/cloudstack/backup/NASBackupProvider.java
index c90fc4b3f604..6113e2581008 100644
--- a/plugins/backup/nas/src/main/java/org/apache/cloudstack/backup/NASBackupProvider.java
+++ b/plugins/backup/nas/src/main/java/org/apache/cloudstack/backup/NASBackupProvider.java
@@ -27,10 +27,8 @@
import com.cloud.hypervisor.Hypervisor;
import com.cloud.storage.ScopeType;
import com.cloud.storage.Storage;
-import com.cloud.storage.StoragePoolHostVO;
import com.cloud.storage.Volume;
import com.cloud.storage.VolumeVO;
-import com.cloud.storage.dao.StoragePoolHostDao;
import com.cloud.storage.dao.VolumeDao;
import com.cloud.utils.Pair;
import com.cloud.utils.component.AdapterBase;
@@ -84,9 +82,6 @@ public class NASBackupProvider extends AdapterBase implements BackupProvider, Co
@Inject
private VolumeDao volumeDao;
- @Inject
- private StoragePoolHostDao storagePoolHostDao;
-
@Inject
private VMInstanceDao vmInstanceDao;
@@ -268,19 +263,27 @@ private List getVolumePaths(List volumes) {
return volumePaths;
}
+ private String getVolumePathPrefix(StoragePoolVO storagePool) {
+ String volumePathPrefix;
+ if (ScopeType.HOST.equals(storagePool.getScope()) ||
+ Storage.StoragePoolType.SharedMountPoint.equals(storagePool.getPoolType()) ||
+ Storage.StoragePoolType.RBD.equals(storagePool.getPoolType())) {
+ volumePathPrefix = storagePool.getPath();
+ } else {
+ // Should be Storage.StoragePoolType.NetworkFilesystem
+ volumePathPrefix = String.format("/mnt/%s", storagePool.getUuid());
+ }
+ return volumePathPrefix;
+ }
+
@Override
public Pair restoreBackedUpVolume(Backup backup, String volumeUuid, String hostIp, String dataStoreUuid, Pair vmNameAndState) {
final VolumeVO volume = volumeDao.findByUuid(volumeUuid);
final VirtualMachine backupSourceVm = vmInstanceDao.findById(backup.getVmId());
- final StoragePoolHostVO dataStore = storagePoolHostDao.findByUuid(dataStoreUuid);
- LOG.info("NASBackupProvider.java restoreBackedUpVolume:::::");
- LOG.info("hostIP: " +hostIp);
+ final StoragePoolVO pool = primaryDataStoreDao.findByUuid(dataStoreUuid);
HostVO hostVO = hostDao.findByIp(hostIp);
- LOG.info("hostVO: " +hostVO);
if(hostVO == null) {
- LOG.info("hostVO == null");
hostVO = hostDao.findByName(hostIp);
- LOG.info("hostVO: " +hostVO);
}
Optional matchingVolume = getBackedUpVolumeInfo(backupSourceVm.getBackupVolumeList(), volumeUuid);
@@ -299,7 +302,7 @@ public Pair restoreBackedUpVolume(Backup backup, String volumeU
restoredVolume.setUuid(volumeUUID);
restoredVolume.setRemoved(null);
restoredVolume.setDisplayVolume(true);
- restoredVolume.setPoolId(dataStore.getPoolId());
+ restoredVolume.setPoolId(pool.getId());
restoredVolume.setPath(restoredVolume.getUuid());
restoredVolume.setState(Volume.State.Copying);
restoredVolume.setFormat(Storage.ImageFormat.QCOW2);
@@ -311,7 +314,7 @@ public Pair restoreBackedUpVolume(Backup backup, String volumeU
restoreCommand.setBackupRepoType(backupRepository.getType());
restoreCommand.setBackupRepoAddress(backupRepository.getAddress());
restoreCommand.setVmName(vmNameAndState.first());
- restoreCommand.setVolumePaths(Collections.singletonList(String.format("%s/%s", dataStore.getLocalPath(), volumeUUID)));
+ restoreCommand.setVolumePaths(Collections.singletonList(String.format("%s/%s", getVolumePathPrefix(pool), volumeUUID)));
restoreCommand.setDiskType(volume.getVolumeType().name().toLowerCase(Locale.ROOT));
restoreCommand.setVmExists(null);
restoreCommand.setVmState(vmNameAndState.second());