Skip to content

Commit e805e45

Browse files
authored
Show chain size in snapshot response for incremental snapshots (#11313)
1 parent 9f5828a commit e805e45

File tree

8 files changed

+49
-5
lines changed

8 files changed

+49
-5
lines changed

api/src/main/java/org/apache/cloudstack/api/ApiConstants.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1143,6 +1143,7 @@ public class ApiConstants {
11431143
public static final String NETWORK_SPANNED_ZONES = "zonesnetworkspans";
11441144
public static final String METADATA = "metadata";
11451145
public static final String PHYSICAL_SIZE = "physicalsize";
1146+
public static final String CHAIN_SIZE = "chainsize";
11461147
public static final String OVM3_POOL = "ovm3pool";
11471148
public static final String OVM3_CLUSTER = "ovm3cluster";
11481149
public static final String OVM3_VIP = "ovm3vip";

api/src/main/java/org/apache/cloudstack/api/response/SnapshotResponse.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,10 @@ public class SnapshotResponse extends BaseResponseWithTagInformation implements
107107
@Param(description = "physical size of backedup snapshot on image store")
108108
private long physicalSize;
109109

110+
@SerializedName(ApiConstants.CHAIN_SIZE)
111+
@Param(description = "chain size of snapshot including all parent snapshots. Shown only for incremental snapshots if snapshot.show.chain.size setting is set to true", since = "4.21.0")
112+
private Long chainSize;
113+
110114
@SerializedName(ApiConstants.ZONE_ID)
111115
@Param(description = "id of the availability zone")
112116
private String zoneId;
@@ -244,6 +248,10 @@ public void setPhysicalSize(long physicalSize) {
244248
this.physicalSize = physicalSize;
245249
}
246250

251+
public void setChainSize(long chainSize) {
252+
this.chainSize = chainSize;
253+
}
254+
247255
@Override
248256
public void setProjectId(String projectId) {
249257
this.projectId = projectId;

server/src/main/java/com/cloud/api/query/dao/SnapshotJoinDaoImpl.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import com.cloud.storage.VMTemplateStorageResourceAssoc;
4747
import com.cloud.storage.Volume.Type;
4848
import com.cloud.storage.VolumeVO;
49+
import com.cloud.storage.snapshot.SnapshotManager;
4950
import com.cloud.user.Account;
5051
import com.cloud.user.AccountService;
5152
import com.cloud.utils.db.Filter;
@@ -96,9 +97,27 @@ private void setSnapshotInfoDetailsInResponse(SnapshotJoinVO snapshot, SnapshotR
9697
} else {
9798
snapshotResponse.setRevertable(snapshotInfo.isRevertable());
9899
snapshotResponse.setPhysicalSize(snapshotInfo.getPhysicalSize());
100+
101+
boolean showChainSize = SnapshotManager.snapshotShowChainSize.valueIn(snapshot.getDataCenterId());
102+
if (showChainSize && snapshotInfo.getParent() != null) {
103+
long chainSize = calculateChainSize(snapshotInfo);
104+
snapshotResponse.setChainSize(chainSize);
105+
}
99106
}
100107
}
101108

109+
private long calculateChainSize(SnapshotInfo snapshotInfo) {
110+
long chainSize = snapshotInfo.getPhysicalSize();
111+
SnapshotInfo parent = snapshotInfo.getParent();
112+
113+
while (parent != null) {
114+
chainSize += parent.getPhysicalSize();
115+
parent = parent.getParent();
116+
}
117+
118+
return chainSize;
119+
}
120+
102121
private String getSnapshotStatus(SnapshotJoinVO snapshot) {
103122
String status = snapshot.getStatus().toString();
104123
if (snapshot.getDownloadState() == null) {

server/src/main/java/com/cloud/storage/snapshot/SnapshotManager.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,10 @@ public interface SnapshotManager extends Configurable {
6161
ConfigKey<Integer> snapshotDeltaMax = new ConfigKey<>(Integer.class, "snapshot.delta.max", "Snapshots", "16", "Max delta snapshots between two full snapshots. " +
6262
"Only valid for KVM and XenServer.", true, ConfigKey.Scope.Global, null);
6363

64+
ConfigKey<Boolean> snapshotShowChainSize = new ConfigKey<>(Boolean.class, "snapshot.show.chain.size", "Snapshots", "false",
65+
"Whether to show chain size (sum of physical size of snapshot and all its parents) for incremental snapshots in the snapshot response",
66+
true, ConfigKey.Scope.Global, null);
67+
6468
void deletePoliciesForVolume(Long volumeId);
6569

6670
/**

server/src/main/java/com/cloud/storage/snapshot/SnapshotManagerImpl.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ public String getConfigComponentName() {
294294
@Override
295295
public ConfigKey<?>[] getConfigKeys() {
296296
return new ConfigKey<?>[] {BackupRetryAttempts, BackupRetryInterval, SnapshotHourlyMax, SnapshotDailyMax, SnapshotMonthlyMax, SnapshotWeeklyMax, usageSnapshotSelection,
297-
SnapshotInfo.BackupSnapshotAfterTakingSnapshot, VmStorageSnapshotKvm, kvmIncrementalSnapshot, snapshotDeltaMax};
297+
SnapshotInfo.BackupSnapshotAfterTakingSnapshot, VmStorageSnapshotKvm, kvmIncrementalSnapshot, snapshotDeltaMax, snapshotShowChainSize};
298298
}
299299

300300
@Override

ui/public/locales/en.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,7 @@
509509
"label.certificate.upload.failed": "Certificate upload failed",
510510
"label.certificate.upload.failed.description": "Failed to update SSL Certificate. Failed to pass certificate validation check.",
511511
"label.certificateid": "Certificate ID",
512+
"label.chainsize": "Chain size",
512513
"label.change": "Change",
513514
"label.change.affinity": "Change affinity",
514515
"label.change.bgp.peers": "Change BGP peers",

ui/src/components/view/DetailsTab.vue

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,17 +75,22 @@
7575
</div>
7676
<div v-else-if="['template', 'iso'].includes($route.meta.name) && item === 'size'">
7777
<div>
78-
{{ parseFloat(dataResource.size / (1024.0 * 1024.0 * 1024.0)).toFixed(2) }} GiB
78+
{{ sizeInGiB(dataResource.size) }} GiB
7979
</div>
8080
</div>
8181
<div v-else-if="['volume', 'snapshot', 'template', 'iso'].includes($route.meta.name) && item === 'physicalsize'">
8282
<div>
83-
{{ parseFloat(dataResource.physicalsize / (1024.0 * 1024.0 * 1024.0)).toFixed(2) }} GiB
83+
{{ sizeInGiB(dataResource.physicalsize) }} GiB
8484
</div>
8585
</div>
8686
<div v-else-if="['volume', 'snapshot', 'template', 'iso'].includes($route.meta.name) && item === 'virtualsize'">
8787
<div>
88-
{{ parseFloat(dataResource.virtualsize / (1024.0 * 1024.0 * 1024.0)).toFixed(2) }} GiB
88+
{{ sizeInGiB(dataResource.virtualsize) }} GiB
89+
</div>
90+
</div>
91+
<div v-else-if="$route.meta.name === 'snapshot' && item === 'chainsize'">
92+
<div>
93+
{{ sizeInGiB(dataResource.chainsize) }} GiB
8994
</div>
9095
</div>
9196
<div v-else-if="['name', 'type'].includes(item)">
@@ -473,6 +478,12 @@ export default {
473478
}
474479
475480
return `label.${source}`
481+
},
482+
sizeInGiB (sizeInBytes) {
483+
if (!sizeInBytes || sizeInBytes === 0) {
484+
return '0.00'
485+
}
486+
return parseFloat(sizeInBytes / (1024.0 * 1024.0 * 1024.0)).toFixed(2)
476487
}
477488
}
478489
}

ui/src/config/section/storage.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ export default {
324324
fields.push('zonename')
325325
return fields
326326
},
327-
details: ['name', 'id', 'volumename', 'volumetype', 'snapshottype', 'intervaltype', 'physicalsize', 'virtualsize', 'account', 'domain', 'created'],
327+
details: ['name', 'id', 'volumename', 'volumetype', 'snapshottype', 'intervaltype', 'physicalsize', 'virtualsize', 'chainsize', 'account', 'domain', 'created'],
328328
tabs: [
329329
{
330330
name: 'details',

0 commit comments

Comments
 (0)