diff --git a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java index 2e686560a01..6ae349ca712 100644 --- a/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java +++ b/api/src/main/java/org/apache/cloudstack/api/ApiConstants.java @@ -332,6 +332,7 @@ public class ApiConstants { public static final String IS_2FA_VERIFIED = "is2faverified"; public static final String IS_2FA_MANDATED = "is2famandated"; + public static final String IS_ACTIVE = "isactive"; public static final String IS_ASYNC = "isasync"; public static final String IP_AVAILABLE = "ipavailable"; public static final String IP_LIMIT = "iplimit"; diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/backup/DeleteVmCheckpointCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/backup/DeleteVmCheckpointCmd.java index a05db27de4d..47b62ddcc50 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/backup/DeleteVmCheckpointCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/backup/DeleteVmCheckpointCmd.java @@ -30,7 +30,7 @@ import org.apache.cloudstack.api.response.UserVmResponse; import org.apache.cloudstack.backup.IncrementalBackupService; import org.apache.cloudstack.context.CallContext; -@APICommand(name = "deleteVmCheckpoint", +@APICommand(name = "deleteVirtualMachineCheckpoint", description = "Delete a VM checkpoint", responseObject = SuccessResponse.class, since = "4.22.0", @@ -61,6 +61,14 @@ public class DeleteVmCheckpointCmd extends BaseCmd implements AdminCmd { return checkpointId; } + public void setVmId(Long vmId) { + this.vmId = vmId; + } + + public void setCheckpointId(String checkpointId) { + this.checkpointId = checkpointId; + } + @Override public void execute() { boolean result = incrementalBackupService.deleteVmCheckpoint(this); diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/backup/FinalizeBackupCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/backup/FinalizeBackupCmd.java index 3ea69b66b5b..e6e270c7f6f 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/backup/FinalizeBackupCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/backup/FinalizeBackupCmd.java @@ -22,25 +22,33 @@ import javax.inject.Inject; import org.apache.cloudstack.acl.RoleType; import org.apache.cloudstack.api.APICommand; import org.apache.cloudstack.api.ApiConstants; -import org.apache.cloudstack.api.BaseCmd; +import org.apache.cloudstack.api.ApiErrorCode; +import org.apache.cloudstack.api.BaseAsyncCmd; import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.ServerApiException; import org.apache.cloudstack.api.command.admin.AdminCmd; import org.apache.cloudstack.api.response.BackupResponse; -import org.apache.cloudstack.api.response.SuccessResponse; import org.apache.cloudstack.api.response.UserVmResponse; +import org.apache.cloudstack.backup.Backup; +import org.apache.cloudstack.backup.BackupManager; import org.apache.cloudstack.backup.IncrementalBackupService; import org.apache.cloudstack.context.CallContext; +import com.cloud.event.EventTypes; + @APICommand(name = "finalizeBackup", description = "Finalize a VM backup session", - responseObject = SuccessResponse.class, + responseObject = BackupResponse.class, since = "4.22.0", authorized = {RoleType.Admin}) -public class FinalizeBackupCmd extends BaseCmd implements AdminCmd { +public class FinalizeBackupCmd extends BaseAsyncCmd implements AdminCmd { @Inject private IncrementalBackupService incrementalBackupService; + @Inject + private BackupManager backupManager; + @Parameter(name = ApiConstants.VIRTUAL_MACHINE_ID, type = CommandType.UUID, entityType = UserVmResponse.class, @@ -63,19 +71,16 @@ public class FinalizeBackupCmd extends BaseCmd implements AdminCmd { return backupId; } - public void setVmId(Long vmId) { - this.vmId = vmId; - } - - public void setBackupId(Long backupId) { - this.backupId = backupId; - } - @Override public void execute() { - boolean result = incrementalBackupService.finalizeBackup(this); - SuccessResponse response = new SuccessResponse(getCommandName()); - response.setSuccess(result); + Backup backup = incrementalBackupService.finalizeBackup(this); + + if (backup == null) { + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create Backup"); + } + + BackupResponse response = backupManager.createBackupResponse(backup, null); + response.setResponseName(getCommandName()); setResponseObject(response); } @@ -84,4 +89,15 @@ public class FinalizeBackupCmd extends BaseCmd implements AdminCmd { public long getEntityOwnerId() { return CallContext.current().getCallingAccount().getId(); } + + + @Override + public String getEventType() { + return EventTypes.EVENT_VM_BACKUP_CREATE; + } + + @Override + public String getEventDescription() { + return "Finalizing backup " + backupId; + } } diff --git a/api/src/main/java/org/apache/cloudstack/api/command/admin/backup/ListVmCheckpointsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/admin/backup/ListVmCheckpointsCmd.java index 737227bf6c7..0d223ffaf5d 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/admin/backup/ListVmCheckpointsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/admin/backup/ListVmCheckpointsCmd.java @@ -32,7 +32,7 @@ import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.UserVmResponse; import org.apache.cloudstack.backup.IncrementalBackupService; -@APICommand(name = "listVmCheckpoints", +@APICommand(name = "listVirtualMachineCheckpoints", description = "List checkpoints for a VM", responseObject = CheckpointResponse.class, since = "4.22.0", diff --git a/api/src/main/java/org/apache/cloudstack/api/response/CheckpointResponse.java b/api/src/main/java/org/apache/cloudstack/api/response/CheckpointResponse.java index 40be9d6d6d0..2bec7711064 100644 --- a/api/src/main/java/org/apache/cloudstack/api/response/CheckpointResponse.java +++ b/api/src/main/java/org/apache/cloudstack/api/response/CheckpointResponse.java @@ -17,6 +17,9 @@ package org.apache.cloudstack.api.response; +import java.util.Date; + +import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.BaseResponse; import com.cloud.serializer.Param; @@ -24,24 +27,24 @@ import com.google.gson.annotations.SerializedName; public class CheckpointResponse extends BaseResponse { - @SerializedName("checkpointid") + @SerializedName(ApiConstants.ID) @Param(description = "the checkpoint ID") - private String checkpointId; + private String id; - @SerializedName("createtime") + @SerializedName(ApiConstants.CREATED) @Param(description = "the checkpoint creation time") - private Long createTime; + private Date created; - @SerializedName("isactive") + @SerializedName(ApiConstants.IS_ACTIVE) @Param(description = "whether this is the active checkpoint") private Boolean isActive; - public void setCheckpointId(String checkpointId) { - this.checkpointId = checkpointId; + public void setId(String id) { + this.id = id; } - public void setCreateTime(Long createTime) { - this.createTime = createTime; + public void setCreated(Date created) { + this.created = created; } public void setIsActive(Boolean isActive) { diff --git a/api/src/main/java/org/apache/cloudstack/backup/IncrementalBackupService.java b/api/src/main/java/org/apache/cloudstack/backup/IncrementalBackupService.java index ed97f780db1..053f1c1455e 100644 --- a/api/src/main/java/org/apache/cloudstack/backup/IncrementalBackupService.java +++ b/api/src/main/java/org/apache/cloudstack/backup/IncrementalBackupService.java @@ -58,7 +58,7 @@ public interface IncrementalBackupService extends Configurable, PluggableService * Finalize a backup session * Stops NBD server, updates checkpoint tracking, deletes old checkpoints */ - boolean finalizeBackup(FinalizeBackupCmd cmd); + Backup finalizeBackup(FinalizeBackupCmd cmd); /** * Create an image transfer object for a disk diff --git a/server/src/main/java/org/apache/cloudstack/backup/IncrementalBackupServiceImpl.java b/server/src/main/java/org/apache/cloudstack/backup/IncrementalBackupServiceImpl.java index 40c459782b6..be6dcae12b8 100644 --- a/server/src/main/java/org/apache/cloudstack/backup/IncrementalBackupServiceImpl.java +++ b/server/src/main/java/org/apache/cloudstack/backup/IncrementalBackupServiceImpl.java @@ -17,6 +17,7 @@ package org.apache.cloudstack.backup; +import java.time.Instant; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; @@ -247,7 +248,7 @@ public class IncrementalBackupServiceImpl extends ManagerBase implements Increme } @Override - public boolean finalizeBackup(FinalizeBackupCmd cmd) { + public Backup finalizeBackup(FinalizeBackupCmd cmd) { Long vmId = cmd.getVmId(); Long backupId = cmd.getBackupId(); @@ -317,7 +318,7 @@ public class IncrementalBackupServiceImpl extends ManagerBase implements Increme backup.setStatus(Backup.Status.BackedUp); backupDao.update(backupId, backup); - return true; + return backup; } @@ -673,14 +674,20 @@ public class IncrementalBackupServiceImpl extends ManagerBase implements Increme // Return active checkpoint (POC: simplified, no libvirt query) List responses = new ArrayList<>(); - if (vm.getActiveCheckpointId() != null) { - CheckpointResponse response = new CheckpointResponse(); - response.setCheckpointId(vm.getActiveCheckpointId()); - response.setCreateTime(vm.getActiveCheckpointCreateTime()); - response.setIsActive(true); - responses.add(response); + if (vm.getActiveCheckpointId() == null) { + return responses; } - + CheckpointResponse response = new CheckpointResponse(); + response.setObjectName("checkpoint"); + response.setId(vm.getActiveCheckpointId()); + Long createTimeSeconds = vm.getActiveCheckpointCreateTime(); + if (createTimeSeconds != null) { + response.setCreated(Date.from(Instant.ofEpochSecond(createTimeSeconds))); + } else { + response.setCreated(new Date()); + } + response.setIsActive(true); + responses.add(response); return responses; }