4343
4444import javax .naming .ConfigurationException ;
4545
46+ import com .ceph .rbd .jna .RbdImageInfo ;
47+ import com .fasterxml .jackson .core .JsonProcessingException ;
48+ import com .fasterxml .jackson .databind .JsonNode ;
49+ import com .fasterxml .jackson .databind .ObjectMapper ;
4650import org .apache .cloudstack .agent .directdownload .DirectDownloadAnswer ;
4751import org .apache .cloudstack .agent .directdownload .DirectDownloadCommand ;
4852import org .apache .cloudstack .direct .download .DirectDownloadHelper ;
@@ -305,7 +309,7 @@ public Answer copyTemplateToPrimaryStorage(final CopyCommand cmd) {
305309 newTemplate .setPath (primaryVol .getName ());
306310 newTemplate .setSize (primaryVol .getSize ());
307311
308- if (List .of (
312+ if (List .of (
309313 StoragePoolType .RBD ,
310314 StoragePoolType .PowerFlex ,
311315 StoragePoolType .Linstor ,
@@ -696,7 +700,7 @@ public Answer createTemplateFromVolume(final CopyCommand cmd) {
696700 templateContent += "snapshot.name=" + dateFormat .format (date ) + System .getProperty ("line.separator" );
697701
698702
699- try (FileOutputStream templFo = new FileOutputStream (templateProp );){
703+ try (FileOutputStream templFo = new FileOutputStream (templateProp );) {
700704 templFo .write (templateContent .getBytes ());
701705 templFo .flush ();
702706 } catch (final IOException e ) {
@@ -761,11 +765,9 @@ private Answer createTemplateFromVolumeOrSnapshot(CopyCommand cmd) {
761765
762766 if (srcData instanceof VolumeObjectTO ) {
763767 isVolume = true ;
764- }
765- else if (srcData instanceof SnapshotObjectTO ) {
768+ } else if (srcData instanceof SnapshotObjectTO ) {
766769 isVolume = false ;
767- }
768- else {
770+ } else {
769771 return new CopyCmdAnswer ("unsupported object type" );
770772 }
771773
@@ -831,8 +833,7 @@ else if (srcData instanceof SnapshotObjectTO) {
831833
832834 if (isVolume ) {
833835 templateContent += "volume.name=" + dateFormat .format (date ) + System .getProperty ("line.separator" );
834- }
835- else {
836+ } else {
836837 templateContent += "snapshot.name=" + dateFormat .format (date ) + System .getProperty ("line.separator" );
837838 }
838839
@@ -870,8 +871,7 @@ else if (srcData instanceof SnapshotObjectTO) {
870871 } catch (Exception ex ) {
871872 if (isVolume ) {
872873 logger .debug ("Failed to create template from volume: " , ex );
873- }
874- else {
874+ } else {
875875 logger .debug ("Failed to create template from snapshot: " , ex );
876876 }
877877
@@ -1034,7 +1034,7 @@ public Answer backupSnapshot(final CopyCommand cmd) {
10341034 q .convert (srcFile , destFile );
10351035
10361036 final File snapFile = new File (snapshotFile );
1037- if (snapFile .exists ()) {
1037+ if (snapFile .exists ()) {
10381038 size = snapFile .length ();
10391039 }
10401040
@@ -1067,7 +1067,7 @@ public Answer backupSnapshot(final CopyCommand cmd) {
10671067 return new CopyCmdAnswer (result );
10681068 }
10691069 final File snapFile = new File (snapshotDestPath + "/" + descName );
1070- if (snapFile .exists ()){
1070+ if (snapFile .exists ()) {
10711071 size = snapFile .length ();
10721072 }
10731073 }
@@ -1404,7 +1404,7 @@ protected synchronized void attachOrDetachDisk(final Connect conn, final boolean
14041404 if (resource .getHypervisorType () == Hypervisor .HypervisorType .LXC ) {
14051405 final String device = resource .mapRbdDevice (attachingDisk );
14061406 if (device != null ) {
1407- logger .debug ("RBD device on host is: " + device );
1407+ logger .debug ("RBD device on host is: " + device );
14081408 attachingDisk .setPath (device );
14091409 }
14101410 }
@@ -1441,11 +1441,11 @@ protected synchronized void attachOrDetachDisk(final Connect conn, final boolean
14411441 }
14421442 diskdef .setSerial (serial );
14431443 if (attachingPool .getType () == StoragePoolType .RBD ) {
1444- if (resource .getHypervisorType () == Hypervisor .HypervisorType .LXC ){
1444+ if (resource .getHypervisorType () == Hypervisor .HypervisorType .LXC ) {
14451445 // For LXC, map image to host and then attach to Vm
14461446 final String device = resource .mapRbdDevice (attachingDisk );
14471447 if (device != null ) {
1448- logger .debug ("RBD device on host is: " + device );
1448+ logger .debug ("RBD device on host is: " + device );
14491449 diskdef .defBlockBasedDisk (device , devId , busT );
14501450 } else {
14511451 throw new InternalErrorException ("Error while mapping disk " +attachingDisk .getPath ()+" on host" );
@@ -1515,7 +1515,7 @@ protected synchronized void attachOrDetachDisk(final Connect conn, final boolean
15151515 if ((iopsWriteRateMaxLength != null ) && (iopsWriteRateMaxLength > 0 )) {
15161516 diskdef .setIopsWriteRateMaxLength (iopsWriteRateMaxLength );
15171517 }
1518- if (cacheMode != null ) {
1518+ if (cacheMode != null ) {
15191519 diskdef .setCacheMode (DiskDef .DiskCacheMode .valueOf (cacheMode .toUpperCase ()));
15201520 }
15211521
@@ -1675,7 +1675,7 @@ public Answer createVolume(final CreateObjectCommand cmd) {
16751675 }
16761676
16771677 final VolumeObjectTO newVol = new VolumeObjectTO ();
1678- if (vol != null ) {
1678+ if (vol != null ) {
16791679 newVol .setPath (vol .getName ());
16801680 if (vol .getQemuEncryptFormat () != null ) {
16811681 newVol .setEncryptFormat (vol .getQemuEncryptFormat ().toString ());
@@ -1778,6 +1778,7 @@ public Answer createSnapshot(final CreateObjectCommand cmd) {
17781778
17791779 String diskPath = disk .getPath ();
17801780 String snapshotPath = diskPath + File .separator + snapshotName ;
1781+ Long snapshotSize = null ;
17811782 if (state == DomainInfo .DomainState .VIR_DOMAIN_RUNNING && !primaryPool .isExternalSnapshot ()) {
17821783
17831784 validateAvailableSizeOnPoolToTakeVolumeSnapshot (primaryPool , disk );
@@ -1838,6 +1839,27 @@ public Answer createSnapshot(final CreateObjectCommand cmd) {
18381839 logger .debug ("Attempting to create RBD snapshot " + disk .getName () + "@" + snapshotName );
18391840 image .snapCreate (snapshotName );
18401841
1842+ RbdImageInfo imageInfo = image .stat ();
1843+ logger .debug ("RBD image " + image .getName () + " info - size: " + imageInfo .size + ", obj_size: " + imageInfo .obj_size + ", num_objs: " + imageInfo .num_objs );
1844+
1845+ long rbdSnapshotSize = getRdbSnapshotSize (primaryPool .getSourceDir (), disk .getName (), snapshotName , primaryPool .getSourceHost (), primaryPool .getAuthUserName (), primaryPool .getAuthSecret ());
1846+ if (rbdSnapshotSize > 0 ) {
1847+ snapshotSize = rbdSnapshotSize ;
1848+ }
1849+
1850+ List <RbdSnapInfo > snapInfo = image .snapList ();
1851+ for (RbdSnapInfo snap : snapInfo ) {
1852+ logger .debug ("RBD snap info - id: " + snap .id + ", name:" + snap .name + ", size: " + snap .size );
1853+ }
1854+
1855+ final RbdImage imageSnap = rbd .open (disk .getName (), snapshotName );
1856+ imageSnap .stat ();
1857+ logger .debug ("RBD image snapshot " + image .getName () + " info - size: " + imageInfo .size + ", obj_size: " + imageInfo .obj_size + ", num_objs: " + imageInfo .num_objs );
1858+
1859+ final RbdImage snap = rbd .open (disk .getName () + "@" + snapshotName );
1860+ snap .stat ();
1861+ logger .debug ("RBD snapshot " + image .getName () + " info - size: " + imageInfo .size + ", obj_size: " + imageInfo .obj_size + ", num_objs: " + imageInfo .num_objs );
1862+
18411863 rbd .close (image );
18421864 r .ioCtxDestroy (io );
18431865 } catch (final Exception e ) {
@@ -1861,8 +1883,11 @@ public Answer createSnapshot(final CreateObjectCommand cmd) {
18611883 }
18621884
18631885 final SnapshotObjectTO newSnapshot = new SnapshotObjectTO ();
1864-
18651886 newSnapshot .setPath (snapshotPath );
1887+ if (snapshotSize != null ) {
1888+ newSnapshot .setPhysicalSize (snapshotSize );
1889+ }
1890+
18661891 return new CreateObjectAnswer (newSnapshot );
18671892 } catch (CloudRuntimeException | LibvirtException | IOException ex ) {
18681893 String errorMsg = String .format ("Failed take snapshot for volume [%s], in VM [%s], due to [%s]." , volume , vmName , ex .getMessage ());
@@ -1873,6 +1898,33 @@ public Answer createSnapshot(final CreateObjectCommand cmd) {
18731898 }
18741899 }
18751900
1901+ private long getRdbSnapshotSize (String poolPath , String diskName , String snapshotName , String rbdMonitor , String authUser , String authSecret ) {
1902+ logger .debug ("Get RBD snapshot size for {}/{}@{}" , poolPath , diskName , snapshotName );
1903+ //rbd du cloudstack/e29110ce-ffab-4a27-b2ad-6d87905039d8@d2e2d6d5-ff66-46f1-be7b-76e0504e965d --format json --pretty-format
1904+ //rbd du cloudstack/e29110ce-ffab-4a27-b2ad-6d87905039d8@d2e2d6d5-ff66-46f1-be7b-76e0504e965d --format json --mon-host 10.0.33.201 --id cloudstack --key AQApZshoQKVHCxAA42Bb8kBoUyLH2cEcFbd2jQ== 2>/dev/null
1905+ String snapshotDetailsInJson = Script .runSimpleBashScript (String .format ("rbd du %s/%s@%s --format json --mon-host %s --id %s --key %s 2>/dev/null" , poolPath , diskName , snapshotName , rbdMonitor , authUser , authSecret ));
1906+ if (StringUtils .isNotBlank (snapshotDetailsInJson )) {
1907+ logger .debug ("RBD snapshot size for {}/{}@{} cmd output: " , poolPath , diskName , snapshotName , snapshotDetailsInJson );
1908+ ObjectMapper mapper = new ObjectMapper ();
1909+ try {
1910+ JsonNode root = mapper .readTree (snapshotDetailsInJson );
1911+ for (JsonNode image : root .path ("images" )) {
1912+ if (snapshotName .equals (image .path ("snapshot" ).asText ())) {
1913+ long usedSizeInBytes = image .path ("used_size" ).asLong ();
1914+ if (usedSizeInBytes > 0 ) {
1915+ logger .debug ("RBD snapshot {}/{}@{} used size in bytes: {}" , poolPath , diskName , snapshotName , usedSizeInBytes );
1916+ return usedSizeInBytes ;
1917+ }
1918+ }
1919+ }
1920+ } catch (JsonProcessingException e ) {
1921+ logger .error ("Unable to get the RBD snapshot size" , e );
1922+ }
1923+ }
1924+
1925+ return 0 ;
1926+ }
1927+
18761928 protected void deleteFullVmSnapshotAfterConvertingItToExternalDiskSnapshot (Domain vm , String snapshotName , VolumeObjectTO volume , String vmName ) throws LibvirtException {
18771929 logger .debug (String .format ("Deleting full Instance Snapshot [%s] of Instance [%s] as we already converted it to an external disk Snapshot of the volume [%s]." , snapshotName , vmName ,
18781930 volume ));
0 commit comments