Skip to content

Commit 2032bbd

Browse files
GeanJairgean.silvabernardodemarco
authored
Addition of the status filter in the backup listing API (#13254)
Co-authored-by: gean.silva <gean.silva@scclouds.com.br> Co-authored-by: Gean Jair Silva <89494158+GeanJS@users.noreply.github.com> Co-authored-by: Bernardo De Marco Gonçalves <bernardomg2004@gmail.com>
1 parent 7e84850 commit 2032bbd

7 files changed

Lines changed: 97 additions & 3 deletions

File tree

api/src/main/java/org/apache/cloudstack/api/command/user/backup/ListBackupsCmd.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,12 @@ public class ListBackupsCmd extends BaseListProjectAndAccountResourcesCmd {
8989
description = "list backups by backup offering")
9090
private Long backupOfferingId;
9191

92+
@Parameter(name = ApiConstants.STATUS,
93+
type = CommandType.STRING,
94+
since = "4.23.0",
95+
description = "list backups by status")
96+
private String backupStatus;
97+
9298
@Parameter(name = ApiConstants.LIST_VM_DETAILS,
9399
type = CommandType.BOOLEAN,
94100
since = "4.21.0",
@@ -119,6 +125,10 @@ public Long getZoneId() {
119125
return zoneId;
120126
}
121127

128+
public String getBackupStatus() {
129+
return backupStatus;
130+
}
131+
122132
public Boolean getListVmDetails() {
123133
return listVmDetails;
124134
}

server/src/main/java/org/apache/cloudstack/backup/BackupManagerImpl.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import javax.naming.ConfigurationException;
4040

4141
import com.cloud.utils.DomainHelper;
42+
import com.cloud.utils.EnumUtils;
4243
import org.apache.cloudstack.api.ApiCommandResourceType;
4344
import org.apache.cloudstack.api.ApiConstants;
4445
import org.apache.cloudstack.api.InternalIdentity;
@@ -256,6 +257,8 @@ public class BackupManagerImpl extends ManagerBase implements BackupManager {
256257
private static Map<String, BackupProvider> backupProvidersMap = new HashMap<>();
257258
private List<BackupProvider> backupProviders;
258259

260+
private static final List<Backup.Status> INVALID_BACKUP_STATUS = List.of(Backup.Status.Expunged, Backup.Status.Removed);
261+
259262
public AsyncJobDispatcher getAsyncJobDispatcher() {
260263
return asyncJobDispatcher;
261264
}
@@ -1084,13 +1087,28 @@ protected void deleteExcessBackups(List<BackupVO> backups, int amountOfBackupsTo
10841087
}
10851088
}
10861089

1090+
private Backup.Status validateBackupStatus(final String backupStatus) {
1091+
if (backupStatus == null) {
1092+
return null;
1093+
}
1094+
1095+
Backup.Status status = EnumUtils.getEnumIgnoreCase(Backup.Status.class, backupStatus);
1096+
if (status == null || INVALID_BACKUP_STATUS.contains(status)) {
1097+
throw new InvalidParameterValueException(String.format("Invalid backup status: %s. Valid values are: " +
1098+
"Allocated, Queued, BackingUp, BackedUp, Error, Failed, Restoring.", backupStatus));
1099+
}
1100+
1101+
return status;
1102+
}
1103+
10871104
@Override
10881105
public Pair<List<Backup>, Integer> listBackups(final ListBackupsCmd cmd) {
10891106
final Long id = cmd.getId();
10901107
final Long vmId = cmd.getVmId();
10911108
final String name = cmd.getName();
10921109
final Long zoneId = cmd.getZoneId();
10931110
final Long backupOfferingId = cmd.getBackupOfferingId();
1111+
final Backup.Status backupStatus = validateBackupStatus(cmd.getBackupStatus());
10941112
final Account caller = CallContext.current().getCallingAccount();
10951113
final String keyword = cmd.getKeyword();
10961114
List<Long> permittedAccounts = new ArrayList<Long>();
@@ -1119,6 +1137,7 @@ public Pair<List<Backup>, Integer> listBackups(final ListBackupsCmd cmd) {
11191137
sb.and("name", sb.entity().getName(), SearchCriteria.Op.EQ);
11201138
sb.and("zoneId", sb.entity().getZoneId(), SearchCriteria.Op.EQ);
11211139
sb.and("backupOfferingId", sb.entity().getBackupOfferingId(), SearchCriteria.Op.EQ);
1140+
sb.and("backupStatus", sb.entity().getStatus(), SearchCriteria.Op.EQ);
11221141

11231142
if (keyword != null) {
11241143
sb.and().op("keywordName", sb.entity().getName(), SearchCriteria.Op.LIKE);
@@ -1151,6 +1170,8 @@ public Pair<List<Backup>, Integer> listBackups(final ListBackupsCmd cmd) {
11511170
sc.setParameters("backupOfferingId", backupOfferingId);
11521171
}
11531172

1173+
sc.setParametersIfNotNull("backupStatus", backupStatus);
1174+
11541175
if (keyword != null) {
11551176
String keywordMatch = "%" + keyword + "%";
11561177
sc.setParameters("keywordName", keywordMatch);

ui/public/locales/en.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -469,6 +469,8 @@
469469
"label.back.login": "Back to login",
470470
"label.backup": "Backup",
471471
"label.backups": "Backups",
472+
"label.backedup": "BackedUp",
473+
"label.backingup": "BackingUp",
472474
"label.backup.attach.restore": "Restore and attach backup volume",
473475
"label.backup.configure.schedule": "Configure Backup Schedule",
474476
"label.backup.offering.assign": "Assign Instance to backup offering",
@@ -2052,6 +2054,7 @@
20522054
"label.purge.usage.records.error": "Failed while purging usage records",
20532055
"label.purpose": "Purpose",
20542056
"label.qostype": "QoS type",
2057+
"label.queued": "Queued",
20552058
"label.quickview": "Quick view",
20562059
"label.quiescevm": "Quiesce Instance",
20572060
"label.quiettime": "Quiet time (in sec)",
@@ -2210,6 +2213,7 @@
22102213
"label.restartrequired": "Restart required",
22112214
"label.restore": "Restore",
22122215
"label.restore.volume.attach": "Restore volume and attach",
2216+
"label.restoring": "Restoring",
22132217
"label.use.backup.ip.address": "Use IP Addresses from Backup",
22142218
"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",
22152219
"label.review": "Review",

ui/public/locales/pt_BR.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -436,7 +436,8 @@
436436
"label.backup": "Backup",
437437
"label.backups": "Backups",
438438
"label.back.login": "Voltar à página de login",
439-
"label.backup": "Backups",
439+
"label.backedup": "Salvo",
440+
"label.backingup": "Salvando",
440441
"label.backup.attach.restore": "Restaurar e anexar volume de backup",
441442
"label.backuplimit": "Limite de backups",
442443
"label.backup.storage": "Armazenamento de backup",
@@ -1828,6 +1829,7 @@
18281829
"label.purgeresources": "Limpar Recursos",
18291830
"label.purpose": "Prop\u00f3sito",
18301831
"label.qostype": "Tipo de QoS",
1832+
"label.queued": "Enfileirado",
18311833
"label.quickview": "Visualiza\u00e7\u00e3o r\u00e1pida",
18321834
"label.quiescevm": "Quiesce VM",
18331835
"label.quiettime": "Tempo em espera (em seg)",
@@ -1982,6 +1984,7 @@
19821984
"label.restartrequired": "Reiniciar obrigat\u00f3rio",
19831985
"label.restore": "Restaurar",
19841986
"label.restore.volume.attach": "Restaurar volume e anex\u00e1-lo",
1987+
"label.restoring": "Restaurando",
19851988
"label.review": "Revisar",
19861989
"label.role": "Fun\u00e7\u00e3o",
19871990
"label.roleid": "Fun\u00e7\u00e3o",

ui/src/components/view/SearchView.vue

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ export default {
337337
'type', 'scope', 'managementserverid', 'serviceofferingid',
338338
'diskofferingid', 'networkid', 'usagetype', 'restartrequired', 'gpuenabled',
339339
'displaynetwork', 'guestiptype', 'usersource', 'arch', 'oscategoryid', 'templatetype', 'gpucardid', 'vgpuprofileid',
340-
'extensionid', 'backupoffering', 'volumeid', 'virtualmachineid', 'hsmprofileid', 'kmskeyid'].includes(item)
340+
'extensionid', 'backupoffering', 'volumeid', 'virtualmachineid', 'hsmprofileid', 'kmskeyid', 'status'].includes(item)
341341
) {
342342
type = 'list'
343343
} else if (item === 'tags') {
@@ -530,6 +530,7 @@ export default {
530530
let extensionIndex = -1
531531
let hsmProfileIndex = -1
532532
let kmsKeyIndex = -1
533+
let backupStatusIndex = -1
533534
534535
if (arrayField.includes('type')) {
535536
if (this.$route.path === '/alert') {
@@ -687,6 +688,11 @@ export default {
687688
promises.push(await this.fetchKMSKeys(searchKeyword))
688689
}
689690
691+
if (arrayField.includes('status')) {
692+
backupStatusIndex = this.fields.findIndex(item => item.name === 'status')
693+
this.fields[backupStatusIndex].opts = this.fetchAvailableBackupStatus()
694+
}
695+
690696
Promise.all(promises).then(response => {
691697
if (typeIndex > -1) {
692698
const types = response.filter(item => item.type === 'type')
@@ -1662,6 +1668,38 @@ export default {
16621668
})
16631669
})
16641670
},
1671+
fetchAvailableBackupStatus () {
1672+
return [
1673+
{
1674+
id: 'Allocated',
1675+
name: 'label.allocated'
1676+
},
1677+
{
1678+
id: 'Queued',
1679+
name: 'label.queued'
1680+
},
1681+
{
1682+
id: 'BackingUp',
1683+
name: 'label.backingup'
1684+
},
1685+
{
1686+
id: 'BackedUp',
1687+
name: 'label.backedup'
1688+
},
1689+
{
1690+
id: 'Error',
1691+
name: 'label.error'
1692+
},
1693+
{
1694+
id: 'Failed',
1695+
name: 'label.failed'
1696+
},
1697+
{
1698+
id: 'Restoring',
1699+
name: 'label.restoring'
1700+
}
1701+
]
1702+
},
16651703
onSearch (value) {
16661704
this.paramsFilter = {}
16671705
this.searchQuery = value

ui/src/components/widgets/Status.vue

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,24 @@ export default {
106106
case 'no':
107107
state = this.$t('label.no')
108108
break
109+
case 'backedup':
110+
state = this.$t('label.backedup')
111+
break
112+
case 'backingup':
113+
state = this.$t('label.backingup')
114+
break
115+
case 'allocated':
116+
state = this.$t('label.allocated')
117+
break
118+
case 'queued':
119+
state = this.$t('label.queued')
120+
break
121+
case 'restoring':
122+
state = this.$t('label.restoring')
123+
break
124+
case 'failed':
125+
state = this.$t('label.failed')
126+
break
109127
}
110128
return state.charAt(0).toUpperCase() + state.slice(1)
111129
}

ui/src/config/section/storage.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -495,7 +495,7 @@ export default {
495495
columns: ['name', 'status', 'size', 'virtualsize', 'virtualmachinename', 'backupofferingname', 'intervaltype', 'type', 'created', 'account', 'domain', 'zone'],
496496
details: ['name', 'description', 'virtualmachinename', 'id', 'intervaltype', 'type', 'externalid', 'size', 'virtualsize', 'volumes', 'backupofferingname', 'zone', 'account', 'domain', 'created'],
497497
searchFilters: () => {
498-
var filters = ['name', 'zoneid', 'domainid', 'account', 'backupofferingid']
498+
var filters = ['name', 'zoneid', 'domainid', 'account', 'backupofferingid', 'status']
499499
return filters
500500
},
501501
tabs: [

0 commit comments

Comments
 (0)