Skip to content

Commit beb05ae

Browse files
committed
Backup storage capacity and alert framework layer.
1 parent 4197912 commit beb05ae

File tree

10 files changed

+106
-32
lines changed

10 files changed

+106
-32
lines changed

api/src/main/java/org/apache/cloudstack/backup/BackupManager.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import java.util.List;
2121
import java.util.Map;
2222

23+
import com.cloud.capacity.Capacity;
2324
import com.cloud.exception.ResourceAllocationException;
2425
import org.apache.cloudstack.api.command.admin.backup.ImportBackupOfferingCmd;
2526
import org.apache.cloudstack.api.command.admin.backup.UpdateBackupOfferingCmd;
@@ -251,4 +252,6 @@ public interface BackupManager extends BackupService, Configurable, PluggableSer
251252
Map<String, String> getVmDetailsForBackup(VirtualMachine vm);
252253

253254
Map<String, String> getDiskOfferingDetailsForBackup(Long vmId);
255+
256+
Capacity getBackupStorageUsedStats(Long zoneId);
254257
}

api/src/main/java/org/apache/cloudstack/backup/BackupProvider.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,4 +123,10 @@ public interface BackupProvider {
123123
*/
124124
boolean supportsInstanceFromBackup();
125125

126+
/**
127+
* Returns the backup storage usage (Used, Total) for a backup provider
128+
* @param zoneId the zone for which to return metrics
129+
* @return a pair of Used size and Total size for the backup storage
130+
*/
131+
Pair<Long, Long> getBackupStorageStats(Long zoneId);
126132
}

plugins/backup/dummy/src/main/java/org/apache/cloudstack/backup/DummyBackupProvider.java

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,13 @@
2525

2626
import javax.inject.Inject;
2727

28-
import com.cloud.configuration.Resource;
28+
import com.cloud.storage.Volume;
2929
import com.cloud.storage.dao.VolumeDao;
3030

3131
import org.apache.cloudstack.backup.dao.BackupDao;
32+
import org.apache.commons.collections.CollectionUtils;
33+
import org.apache.logging.log4j.LogManager;
34+
import org.apache.logging.log4j.Logger;
3235

3336
import com.cloud.utils.Pair;
3437
import com.cloud.utils.component.AdapterBase;
@@ -37,7 +40,7 @@
3740
import com.cloud.vm.VirtualMachine;
3841

3942
public class DummyBackupProvider extends AdapterBase implements BackupProvider {
40-
43+
private static final Logger LOG = LogManager.getLogger(DummyBackupProvider.class);
4144

4245
@Inject
4346
private BackupDao backupDao;
@@ -92,14 +95,21 @@ public Pair<Boolean, String> restoreBackedUpVolume(Backup backup, String volumeU
9295
@Override
9396
public Map<VirtualMachine, Backup.Metric> getBackupMetrics(Long zoneId, List<VirtualMachine> vms) {
9497
final Map<VirtualMachine, Backup.Metric> metrics = new HashMap<>();
95-
final Backup.Metric metric = new Backup.Metric(1000L, 100L);
96-
if (vms == null || vms.isEmpty()) {
98+
if (CollectionUtils.isEmpty(vms)) {
99+
LOG.warn("Unable to get VM Backup Metrics because the list of VMs is empty.");
97100
return metrics;
98101
}
99-
for (VirtualMachine vm : vms) {
100-
if (vm != null) {
101-
metrics.put(vm, metric);
102+
103+
for (final VirtualMachine vm : vms) {
104+
Long vmBackupSize = 0L;
105+
Long vmBackupProtectedSize = 0L;
106+
for (final Backup backup: backupDao.listByVmId(null, vm.getId())) {
107+
vmBackupSize += backup.getSize();
108+
vmBackupProtectedSize += backup.getProtectedSize();
102109
}
110+
Backup.Metric vmBackupMetric = new Backup.Metric(vmBackupSize,vmBackupProtectedSize);
111+
LOG.debug("Metrics for VM {} is [backup size: {}, data size: {}].", vm, vmBackupMetric.getBackupSize(), vmBackupMetric.getDataSize());
112+
metrics.put(vm, vmBackupMetric);
103113
}
104114
return metrics;
105115
}
@@ -134,8 +144,14 @@ public Pair<Boolean, Backup> takeBackup(VirtualMachine vm) {
134144
backup.setExternalId("dummy-external-id");
135145
backup.setType("FULL");
136146
backup.setDate(new Date());
137-
backup.setSize(1024000L);
138-
backup.setProtectedSize(Resource.ResourceType.bytesToGiB);
147+
long virtualSize = 0L;
148+
for (final Volume volume: volumeDao.findByInstance(vm.getId())) {
149+
if (Volume.State.Ready.equals(volume.getState())) {
150+
virtualSize += volume.getSize();
151+
}
152+
}
153+
backup.setSize(virtualSize);
154+
backup.setProtectedSize(virtualSize);
139155
backup.setStatus(Backup.Status.BackedUp);
140156
backup.setBackupOfferingId(vm.getBackupOfferingId());
141157
backup.setAccountId(vm.getAccountId());
@@ -154,14 +170,19 @@ public Pair<Boolean, Backup> takeBackup(VirtualMachine vm) {
154170

155171
@Override
156172
public boolean deleteBackup(Backup backup, boolean forced) {
157-
return true;
173+
return backupDao.remove(backup.getId());
158174
}
159175

160176
@Override
161177
public boolean supportsInstanceFromBackup() {
162178
return true;
163179
}
164180

181+
@Override
182+
public Pair<Long, Long> getBackupStorageStats(Long zoneId) {
183+
return new Pair<>(8L * 1024 * 1024 * 1024, 10L * 1024 * 1024 * 1024);
184+
}
185+
165186
@Override
166187
public boolean restoreBackupToVM(VirtualMachine vm, Backup backup, String hostIp, String dataStoreUuid) {
167188
return true;

plugins/backup/nas/src/main/java/org/apache/cloudstack/backup/NASBackupProvider.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,11 @@ public boolean supportsInstanceFromBackup() {
432432
return true;
433433
}
434434

435+
@Override
436+
public Pair<Long, Long> getBackupStorageStats(Long zoneId) {
437+
return new Pair<>(0L, 0L);
438+
}
439+
435440
@Override
436441
public List<BackupOffering> listBackupOfferings(Long zoneId) {
437442
final List<BackupRepository> repositories = backupRepositoryDao.listByZoneAndProvider(zoneId, getName());

plugins/backup/networker/src/main/java/org/apache/cloudstack/backup/NetworkerBackupProvider.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -640,6 +640,11 @@ public boolean supportsInstanceFromBackup() {
640640
return false;
641641
}
642642

643+
@Override
644+
public Pair<Long, Long> getBackupStorageStats(Long zoneId) {
645+
return new Pair<>(0L, 0L);
646+
}
647+
643648
@Override
644649
public boolean willDeleteBackupsOnOfferingRemoval() { return false; }
645650

plugins/backup/veeam/src/main/java/org/apache/cloudstack/backup/VeeamBackupProvider.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,11 @@ public boolean supportsInstanceFromBackup() {
366366
return true;
367367
}
368368

369+
@Override
370+
public Pair<Long, Long> getBackupStorageStats(Long zoneId) {
371+
return new Pair<>(0L, 0L);
372+
}
373+
369374
@Override
370375
public String getConfigComponentName() {
371376
return BackupService.class.getSimpleName();

server/src/main/java/com/cloud/alert/AlertManagerImpl.java

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939
import com.cloud.dc.DataCenter;
4040
import com.cloud.dc.Pod;
4141
import com.cloud.org.Cluster;
42+
43+
import org.apache.cloudstack.backup.BackupManager;
4244
import org.apache.cloudstack.framework.config.ConfigDepot;
4345
import org.apache.cloudstack.framework.config.ConfigKey;
4446
import org.apache.cloudstack.framework.config.Configurable;
@@ -125,6 +127,8 @@ public class AlertManagerImpl extends ManagerBase implements AlertManager, Confi
125127
@Inject
126128
private ConfigurationManager _configMgr;
127129
@Inject
130+
protected BackupManager backupManager;
131+
@Inject
128132
protected ConfigDepot _configDepot;
129133
@Inject
130134
private ObjectStoreDao _objectStoreDao;
@@ -543,7 +547,8 @@ public void checkForAlerts() {
543547
capacity = _capacityDao.findCapacityBy(capacityType.intValue(), dc.getId(), null, null);
544548

545549
if (capacityType == Capacity.CAPACITY_TYPE_SECONDARY_STORAGE ||
546-
capacityType == Capacity.CAPACITY_TYPE_OBJECT_STORAGE) {
550+
capacityType == Capacity.CAPACITY_TYPE_OBJECT_STORAGE ||
551+
capacityType == Capacity.CAPACITY_TYPE_BACKUP_STORAGE) {
547552
capacity.add(getUsedStats(capacityType, dc.getId(), null, null));
548553
}
549554
if (capacity == null || capacity.size() == 0) {
@@ -621,6 +626,8 @@ private SummedCapacity getUsedStats(short capacityType, long zoneId, Long podId,
621626
capacity = _storageMgr.getStoragePoolUsedStats(null, clusterId, podId, zoneId);
622627
} else if (capacityType == Capacity.CAPACITY_TYPE_OBJECT_STORAGE) {
623628
capacity = _storageMgr.getObjectStorageUsedStats(zoneId);
629+
} else if (capacityType == Capacity.CAPACITY_TYPE_BACKUP_STORAGE) {
630+
capacity = (CapacityVO) backupManager.getBackupStorageUsedStats(zoneId);
624631
}
625632
if (capacity != null) {
626633
return new SummedCapacity(capacity.getUsedCapacity(), 0, capacity.getTotalCapacity(), capacityType, clusterId, podId);
@@ -726,20 +733,20 @@ private void generateEmailAlert(DataCenterVO dc, HostPodVO pod, ClusterVO cluste
726733
msgContent = "Number of unallocated virtual network guest IPv6 subnets is low, total: " + totalStr + ", allocated: " + usedStr + " (" + pctStr + "%)";
727734
alertType = AlertManager.AlertType.ALERT_TYPE_VIRTUAL_NETWORK_IPV6_SUBNET;
728735
break;
729-
case Capacity.CAPACITY_TYPE_BACKUP_STORAGE:
730-
msgSubject = "System Alert: Low Available Backup Storage in availability zone " + dc.getName();
731-
totalStr = Double.toString(totalCapacity);
732-
usedStr = Double.toString(usedCapacity);
733-
msgContent = "Available backup storage space is low, total: " + totalStr + " MB, used: " + usedStr + " MB (" + pctStr + "%)";
734-
alertType = AlertManager.AlertType.ALERT_TYPE_BACKUP_STORAGE;
735-
break;
736-
case Capacity.CAPACITY_TYPE_OBJECT_STORAGE:
737-
msgSubject = "System Alert: Low Available Object Storage in availability zone " + dc.getName();
738-
totalStr = Double.toString(totalCapacity);
739-
usedStr = Double.toString(usedCapacity);
740-
msgContent = "Available object storage space is low, total: " + totalStr + " MB, used: " + usedStr + " MB (" + pctStr + "%)";
741-
alertType = AlertManager.AlertType.ALERT_TYPE_OBJECT_STORAGE;
742-
break;
736+
case Capacity.CAPACITY_TYPE_BACKUP_STORAGE:
737+
msgSubject = "System Alert: Low Available Backup Storage in availability zone " + dc.getName();
738+
totalStr = Double.toString(totalCapacity);
739+
usedStr = Double.toString(usedCapacity);
740+
msgContent = "Available backup storage space is low, total: " + totalStr + " MB, used: " + usedStr + " MB (" + pctStr + "%)";
741+
alertType = AlertManager.AlertType.ALERT_TYPE_BACKUP_STORAGE;
742+
break;
743+
case Capacity.CAPACITY_TYPE_OBJECT_STORAGE:
744+
msgSubject = "System Alert: Low Available Object Storage in availability zone " + dc.getName();
745+
totalStr = Double.toString(totalCapacity);
746+
usedStr = Double.toString(usedCapacity);
747+
msgContent = "Available object storage space is low, total: " + totalStr + " MB, used: " + usedStr + " MB (" + pctStr + "%)";
748+
alertType = AlertManager.AlertType.ALERT_TYPE_OBJECT_STORAGE;
749+
break;
743750
}
744751

745752
try {

server/src/main/java/com/cloud/server/ManagementServerImpl.java

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,7 @@
606606
import org.apache.cloudstack.api.command.user.zone.ListZonesCmd;
607607
import org.apache.cloudstack.auth.UserAuthenticator;
608608
import org.apache.cloudstack.auth.UserTwoFactorAuthenticator;
609+
import org.apache.cloudstack.backup.BackupManager;
609610
import org.apache.cloudstack.config.ApiServiceConfiguration;
610611
import org.apache.cloudstack.config.Configuration;
611612
import org.apache.cloudstack.config.ConfigurationGroup;
@@ -1012,6 +1013,8 @@ public class ManagementServerImpl extends ManagerBase implements ManagementServe
10121013
UserDataManager userDataManager;
10131014
@Inject
10141015
StoragePoolTagsDao storagePoolTagsDao;
1016+
@Inject
1017+
BackupManager backupManager;
10151018

10161019
@Inject
10171020
private PublicIpQuarantineDao publicIpQuarantineDao;
@@ -3390,6 +3393,9 @@ List<SummedCapacity> getStorageCapacities(Long clusterId, Long podId, Long zoneI
33903393
if (capacityTypes.contains(Capacity.CAPACITY_TYPE_OBJECT_STORAGE)) {
33913394
capacities.add(_storageMgr.getObjectStorageUsedStats(dc.getId()));
33923395
}
3396+
if (capacityTypes.contains(Capacity.CAPACITY_TYPE_OBJECT_STORAGE)) {
3397+
capacities.add((CapacityVO) backupManager.getBackupStorageUsedStats(dc.getId()));
3398+
}
33933399
for (CapacityVO capacity : capacities) {
33943400
if (capacity.getTotalCapacity() != 0) {
33953401
capacity.setUsedPercentage((float)capacity.getUsedCapacity() / capacity.getTotalCapacity());
@@ -3433,12 +3439,18 @@ protected List<CapacityVO> listCapacitiesWithDetails(final Long zoneId, final Lo
34333439
// op_host_Capacity contains only allocated stats and the real time
34343440
// stats are stored "in memory".
34353441
// List secondary and object storage capacities only when the api is invoked for the zone layer.
3436-
if ((capacityType == null ||
3437-
(capacityType == Capacity.CAPACITY_TYPE_SECONDARY_STORAGE || capacityType == Capacity.CAPACITY_TYPE_OBJECT_STORAGE)) &&
3438-
podId == null && clusterId == null &&
3439-
StringUtils.isEmpty(t)) {
3440-
taggedCapacities.add(_storageMgr.getSecondaryStorageUsedStats(null, zId));
3441-
taggedCapacities.add(_storageMgr.getObjectStorageUsedStats(zId));
3442+
if (podId == null && clusterId == null && StringUtils.isEmpty(t)) {
3443+
if (capacityType == null) {
3444+
taggedCapacities.add(_storageMgr.getSecondaryStorageUsedStats(null, zId));
3445+
taggedCapacities.add(_storageMgr.getObjectStorageUsedStats(zId));
3446+
taggedCapacities.add((CapacityVO) backupManager.getBackupStorageUsedStats(zId));
3447+
} else if (capacityType == Capacity.CAPACITY_TYPE_SECONDARY_STORAGE) {
3448+
taggedCapacities.add(_storageMgr.getSecondaryStorageUsedStats(null, zId));
3449+
} else if (capacityType == Capacity.CAPACITY_TYPE_OBJECT_STORAGE) {
3450+
taggedCapacities.add(_storageMgr.getObjectStorageUsedStats(zId));
3451+
} else if (capacityType == Capacity.CAPACITY_TYPE_BACKUP_STORAGE) {
3452+
taggedCapacities.add((CapacityVO) backupManager.getBackupStorageUsedStats(zId));
3453+
}
34423454
}
34433455
if ((capacityType == null || capacityType == Capacity.CAPACITY_TYPE_STORAGE) && storagePoolIdsForCapacity.first()) {
34443456
taggedCapacities.add(_storageMgr.getStoragePoolUsedStats(zId, podId, clusterId, storagePoolIdsForCapacity.second()));

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232

3333
import com.amazonaws.util.CollectionUtils;
3434
import com.cloud.alert.AlertManager;
35+
import com.cloud.capacity.Capacity;
36+
import com.cloud.capacity.CapacityVO;
3537
import com.cloud.configuration.Resource;
3638
import com.cloud.exception.ResourceAllocationException;
3739
import com.cloud.storage.Snapshot;
@@ -1776,4 +1778,10 @@ public BackupOffering updateBackupOffering(UpdateBackupOfferingCmd updateBackupO
17761778
return response;
17771779
}
17781780

1781+
@Override
1782+
public CapacityVO getBackupStorageUsedStats(Long zoneId) {
1783+
final BackupProvider backupProvider = getBackupProvider(zoneId);
1784+
Pair<Long, Long> backupUsage = backupProvider.getBackupStorageStats(zoneId);
1785+
return new CapacityVO(null, zoneId, null, null, backupUsage.first(), backupUsage.second(), Capacity.CAPACITY_TYPE_BACKUP_STORAGE);
1786+
}
17791787
}

ui/src/views/dashboard/CapacityDashboard.vue

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -217,7 +217,7 @@
217217
</div>
218218
</template>
219219
<div>
220-
<div v-for="ctype in ['STORAGE', 'STORAGE_ALLOCATED', 'LOCAL_STORAGE', 'SECONDARY_STORAGE', 'OBJECT_STORAGE']" :key="ctype" >
220+
<div v-for="ctype in ['STORAGE', 'STORAGE_ALLOCATED', 'LOCAL_STORAGE', 'SECONDARY_STORAGE', 'BACKUP_STORAGE', 'OBJECT_STORAGE']" :key="ctype" >
221221
<div v-if="statsMap[ctype]">
222222
<div>
223223
<strong>{{ $t(ts[ctype]) }}</strong>
@@ -377,6 +377,7 @@ export default {
377377
MEMORY: 'label.memory',
378378
PRIVATE_IP: 'label.management.ips',
379379
SECONDARY_STORAGE: 'label.secondary.storage',
380+
BACKUP_STORAGE: 'label.backup.storage',
380381
OBJECT_STORAGE: 'label.object.storage',
381382
STORAGE: 'label.primary.storage.used',
382383
STORAGE_ALLOCATED: 'label.primary.storage.allocated',
@@ -439,6 +440,7 @@ export default {
439440
case 'STORAGE':
440441
case 'STORAGE_ALLOCATED':
441442
case 'SECONDARY_STORAGE':
443+
case 'BACKUP_STORAGE':
442444
case 'OBJECT_STORAGE':
443445
case 'LOCAL_STORAGE':
444446
value = parseFloat(value / (1024 * 1024 * 1024.0), 10).toFixed(2)

0 commit comments

Comments
 (0)