From b058f0a5a5c20f80790135f92f10d444fc31dc31 Mon Sep 17 00:00:00 2001 From: "gean.silva" Date: Tue, 26 May 2026 16:14:27 -0300 Subject: [PATCH] remove file --- .../command/user/backup/ListBackupsCmd.java | 10 +++++ .../cloudstack/backup/BackupManagerImpl.java | 21 ++++++++++ ui/public/locales/en.json | 4 ++ ui/public/locales/pt_BR.json | 5 ++- ui/src/components/view/SearchView.vue | 40 ++++++++++++++++++- ui/src/components/widgets/Status.vue | 18 +++++++++ ui/src/config/section/storage.js | 2 +- 7 files changed, 97 insertions(+), 3 deletions(-) diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/backup/ListBackupsCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/backup/ListBackupsCmd.java index fb9c92f433e5..35cadd9f2e5e 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/backup/ListBackupsCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/backup/ListBackupsCmd.java @@ -89,6 +89,12 @@ public class ListBackupsCmd extends BaseListProjectAndAccountResourcesCmd { description = "list backups by backup offering") private Long backupOfferingId; + @Parameter(name = ApiConstants.STATUS, + type = CommandType.STRING, + since = "4.23.0", + description = "list backups by status") + private String backupStatus; + @Parameter(name = ApiConstants.LIST_VM_DETAILS, type = CommandType.BOOLEAN, since = "4.21.0", @@ -119,6 +125,10 @@ public Long getZoneId() { return zoneId; } + public String getBackupStatus() { + return backupStatus; + } + public Boolean getListVmDetails() { return listVmDetails; } 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 fd4fc9466066..044dc849bbda 100644 --- a/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java +++ b/server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java @@ -39,6 +39,7 @@ import javax.naming.ConfigurationException; import com.cloud.utils.DomainHelper; +import com.cloud.utils.EnumUtils; import org.apache.cloudstack.api.ApiCommandResourceType; import org.apache.cloudstack.api.ApiConstants; import org.apache.cloudstack.api.InternalIdentity; @@ -256,6 +257,8 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager { private static Map backupProvidersMap = new HashMap<>(); private List backupProviders; + private static final List INVALID_BACKUP_STATUS = List.of(Backup.Status.Expunged, Backup.Status.Removed); + public AsyncJobDispatcher getAsyncJobDispatcher() { return asyncJobDispatcher; } @@ -1089,6 +1092,20 @@ protected void deleteExcessBackups(List backups, int amountOfBackupsTo } } + private Backup.Status validateBackupStatus(final String backupStatus) { + if (backupStatus == null) { + return null; + } + + Backup.Status status = EnumUtils.getEnumIgnoreCase(Backup.Status.class, backupStatus); + if (status == null || INVALID_BACKUP_STATUS.contains(status)) { + throw new InvalidParameterValueException(String.format("Invalid backup status: %s. Valid values are: " + + "Allocated, Queued, BackingUp, BackedUp, Error, Failed, Restoring.", backupStatus)); + } + + return status; + } + @Override public Pair, Integer> listBackups(final ListBackupsCmd cmd) { final Long id = cmd.getId(); @@ -1096,6 +1113,7 @@ public Pair, Integer> listBackups(final ListBackupsCmd cmd) { final String name = cmd.getName(); final Long zoneId = cmd.getZoneId(); final Long backupOfferingId = cmd.getBackupOfferingId(); + final Backup.Status backupStatus = validateBackupStatus(cmd.getBackupStatus()); final Account caller = CallContext.current().getCallingAccount(); final String keyword = cmd.getKeyword(); List permittedAccounts = new ArrayList(); @@ -1124,6 +1142,7 @@ public Pair, Integer> listBackups(final ListBackupsCmd cmd) { sb.and("name", sb.entity().getName(), SearchCriteria.Op.EQ); sb.and("zoneId", sb.entity().getZoneId(), SearchCriteria.Op.EQ); sb.and("backupOfferingId", sb.entity().getBackupOfferingId(), SearchCriteria.Op.EQ); + sb.and("backupStatus", sb.entity().getStatus(), SearchCriteria.Op.EQ); if (keyword != null) { sb.and().op("keywordName", sb.entity().getName(), SearchCriteria.Op.LIKE); @@ -1156,6 +1175,8 @@ public Pair, Integer> listBackups(final ListBackupsCmd cmd) { sc.setParameters("backupOfferingId", backupOfferingId); } + sc.setParametersIfNotNull("backupStatus", backupStatus); + if (keyword != null) { String keywordMatch = "%" + keyword + "%"; sc.setParameters("keywordName", keywordMatch); diff --git a/ui/public/locales/en.json b/ui/public/locales/en.json index 1187b3e62b40..4f068e2f8e97 100644 --- a/ui/public/locales/en.json +++ b/ui/public/locales/en.json @@ -460,6 +460,8 @@ "label.back.login": "Back to login", "label.backup": "Backup", "label.backups": "Backups", +"label.backedup": "BackedUp", +"label.backingup": "BackingUp", "label.backup.attach.restore": "Restore and attach backup volume", "label.backup.configure.schedule": "Configure Backup Schedule", "label.backup.offering.assign": "Assign Instance to backup offering", @@ -2014,6 +2016,7 @@ "label.purge.usage.records.error": "Failed while purging usage records", "label.purpose": "Purpose", "label.qostype": "QoS type", +"label.queued": "Queued", "label.quickview": "Quick view", "label.quiescevm": "Quiesce Instance", "label.quiettime": "Quiet time (in sec)", @@ -2170,6 +2173,7 @@ "label.restartrequired": "Restart required", "label.restore": "Restore", "label.restore.volume.attach": "Restore volume and attach", +"label.restoring": "Restoring", "label.use.backup.ip.address": "Use IP Addresses from Backup", "label.use.backup.ip.address.tooltip": "Use the same IP/MAC addresses as stored in the backup metadata. The command will error out if the IP/MAC addresses are not available", "label.review": "Review", diff --git a/ui/public/locales/pt_BR.json b/ui/public/locales/pt_BR.json index 4b446eccff32..978edd43cea0 100644 --- a/ui/public/locales/pt_BR.json +++ b/ui/public/locales/pt_BR.json @@ -428,7 +428,8 @@ "label.backup": "Backup", "label.backups": "Backups", "label.back.login": "Voltar à página de login", -"label.backup": "Backups", +"label.backedup": "Salvo", +"label.backingup": "Salvando", "label.backup.attach.restore": "Restaurar e anexar volume de backup", "label.backuplimit": "Limite de backups", "label.backup.storage": "Armazenamento de backup", @@ -1814,6 +1815,7 @@ "label.purgeresources": "Limpar Recursos", "label.purpose": "Prop\u00f3sito", "label.qostype": "Tipo de QoS", +"label.queued": "Enfileirado", "label.quickview": "Visualiza\u00e7\u00e3o r\u00e1pida", "label.quiescevm": "Quiesce VM", "label.quiettime": "Tempo em espera (em seg)", @@ -1967,6 +1969,7 @@ "label.restartrequired": "Reiniciar obrigat\u00f3rio", "label.restore": "Restaurar", "label.restore.volume.attach": "Restaurar volume e anex\u00e1-lo", +"label.restoring": "Restaurando", "label.review": "Revisar", "label.role": "Fun\u00e7\u00e3o", "label.roleid": "Fun\u00e7\u00e3o", diff --git a/ui/src/components/view/SearchView.vue b/ui/src/components/view/SearchView.vue index bd952f049476..31f4607c582d 100644 --- a/ui/src/components/view/SearchView.vue +++ b/ui/src/components/view/SearchView.vue @@ -325,7 +325,7 @@ export default { 'type', 'scope', 'managementserverid', 'serviceofferingid', 'diskofferingid', 'networkid', 'usagetype', 'restartrequired', 'gpuenabled', 'displaynetwork', 'guestiptype', 'usersource', 'arch', 'oscategoryid', 'templatetype', 'gpucardid', 'vgpuprofileid', - 'extensionid', 'backupoffering', 'volumeid', 'virtualmachineid'].includes(item) + 'extensionid', 'backupoffering', 'volumeid', 'virtualmachineid', 'status'].includes(item) ) { type = 'list' } else if (item === 'tags') { @@ -516,6 +516,7 @@ export default { let gpuCardIndex = -1 let vgpuProfileIndex = -1 let extensionIndex = -1 + let backupStatusIndex = -1 if (arrayField.includes('type')) { if (this.$route.path === '/alert') { @@ -661,6 +662,11 @@ export default { promises.push(await this.fetchVolumes(searchKeyword)) } + if (arrayField.includes('status')) { + backupStatusIndex = this.fields.findIndex(item => item.name === 'status') + this.fields[backupStatusIndex].opts = this.fetchAvailableBackupStatus() + } + Promise.all(promises).then(response => { if (typeIndex > -1) { const types = response.filter(item => item.type === 'type') @@ -1590,6 +1596,38 @@ export default { }) }) }, + fetchAvailableBackupStatus () { + return [ + { + id: 'Allocated', + name: 'label.allocated' + }, + { + id: 'Queued', + name: 'label.queued' + }, + { + id: 'BackingUp', + name: 'label.backingup' + }, + { + id: 'BackedUp', + name: 'label.backedup' + }, + { + id: 'Error', + name: 'label.error' + }, + { + id: 'Failed', + name: 'label.failed' + }, + { + id: 'Restoring', + name: 'label.restoring' + } + ] + }, onSearch (value) { this.paramsFilter = {} this.searchQuery = value diff --git a/ui/src/components/widgets/Status.vue b/ui/src/components/widgets/Status.vue index 6b9f71b5de84..678dfc37ae97 100644 --- a/ui/src/components/widgets/Status.vue +++ b/ui/src/components/widgets/Status.vue @@ -106,6 +106,24 @@ export default { case 'no': state = this.$t('label.no') break + case 'backedup': + state = this.$t('label.backedup') + break + case 'backingup': + state = this.$t('label.backingup') + break + case 'allocated': + state = this.$t('label.allocated') + break + case 'qeued': + state = this.$t('label.queued') + break + case 'restoring': + state = this.$t('label.restoring') + break + case 'failed': + state = this.$t('label.failed') + break } return state.charAt(0).toUpperCase() + state.slice(1) } diff --git a/ui/src/config/section/storage.js b/ui/src/config/section/storage.js index 75432314b034..94dc59c78bb3 100644 --- a/ui/src/config/section/storage.js +++ b/ui/src/config/section/storage.js @@ -476,7 +476,7 @@ export default { columns: ['name', 'status', 'size', 'virtualsize', 'virtualmachinename', 'backupofferingname', 'intervaltype', 'type', 'created', 'account', 'domain', 'zone'], details: ['name', 'description', 'virtualmachinename', 'id', 'intervaltype', 'type', 'externalid', 'size', 'virtualsize', 'volumes', 'backupofferingname', 'zone', 'account', 'domain', 'created'], searchFilters: () => { - var filters = ['name', 'zoneid', 'domainid', 'account', 'backupofferingid'] + var filters = ['name', 'zoneid', 'domainid', 'account', 'backupofferingid', 'status'] return filters }, tabs: [