@@ -2553,20 +2553,48 @@ private long getVgPhysicalExtentSize(String vgName) {
25532553 }
25542554
25552555 /**
2556- * Calculate LVM LV size for QCOW2 image accounting for metadata overhead
2557- * @param qcow2PhysicalSize Physical size in bytes from qemu-img info
2556+ * Calculate LVM LV size for CLVM_NG template allocation.
2557+ * Templates need space for actual data plus overhead for QCOW2 metadata expansion during conversion.
2558+ * Formula: physical_size + 50% of virtual_size
2559+ *
2560+ * @param physicalSize Physical size in bytes (actual allocated data in source template)
2561+ * @param virtualSize Virtual size in bytes (full disk capacity)
25582562 * @param vgName Volume group name to query PE size
2559- * @return Size in bytes to allocate for LV
2563+ * @return Size in bytes to allocate for template LV
25602564 */
2561- private long calculateClvmNgLvSize (long qcow2PhysicalSize , String vgName ) {
2565+ private long calculateClvmNgTemplateLvSize (long physicalSize , long virtualSize , String vgName ) {
25622566 long peSize = getVgPhysicalExtentSize (vgName );
2563- long roundedSize = ((qcow2PhysicalSize + peSize - 1 ) / peSize ) * peSize ;
25642567
2568+ long minOverhead = 64 * 1024 * 1024L ;
2569+ long virtualSizeOverhead = (long ) (virtualSize * 0.30 );
2570+ long overhead = Math .max (minOverhead , virtualSizeOverhead );
2571+
2572+ long targetSize = physicalSize + overhead ;
2573+ long roundedSize = ((targetSize + peSize - 1 ) / peSize ) * peSize ;
2574+
2575+ logger .info ("Calculated template LV size: {} bytes (physical: {}, virtual: {}, overhead: {} (50% of virtual), rounded to {} PEs, PE size = {} bytes)" ,
2576+ roundedSize , physicalSize , virtualSize , overhead , roundedSize / peSize , peSize );
2577+
2578+ return roundedSize ;
2579+ }
2580+
2581+ /**
2582+ * Calculate LVM LV size for CLVM_NG volume allocation.
2583+ * Volumes with backing files need approximately the virtual size allocated on block devices.
2584+ * Formula: virtual_size + 1 PE (for QCOW2 metadata and header)
2585+ *
2586+ * @param virtualSize Virtual size in bytes (full disk capacity)
2587+ * @param vgName Volume group name to query PE size
2588+ * @return Size in bytes to allocate for volume LV
2589+ */
2590+ private long calculateClvmNgVolumeLvSize (long virtualSize , String vgName ) {
2591+ long peSize = getVgPhysicalExtentSize (vgName );
2592+
2593+ long roundedSize = ((virtualSize + peSize - 1 ) / peSize ) * peSize ;
25652594 long finalSize = roundedSize + peSize ;
2566- logger .info ("Calculated LV size for QCOW2 physical size {} bytes: {} bytes " +
2567- "(rounded to {} PEs + 1 PE overhead, PE size = {} bytes)" ,
2568- qcow2PhysicalSize , finalSize ,
2569- roundedSize / peSize , peSize );
2595+
2596+ logger .info ("Calculated volume LV size: {} bytes (virtual: {}, rounded to {} PEs + 1 PE overhead, PE size = {} bytes)" ,
2597+ finalSize , virtualSize , roundedSize / peSize , peSize );
25702598
25712599 return finalSize ;
25722600 }
@@ -2618,7 +2646,7 @@ private long getQcow2PhysicalSize(String imagePath) {
26182646
26192647 private KVMPhysicalDisk createClvmNgDiskWithBacking (String volumeUuid , int timeout , long virtualSize , String backingFile , KVMStoragePool pool ) {
26202648 String vgName = getVgName (pool .getLocalPath ());
2621- long lvSize = calculateClvmNgLvSize (virtualSize , vgName );
2649+ long lvSize = calculateClvmNgVolumeLvSize (virtualSize , vgName );
26222650 String volumePath = "/dev/" + vgName + "/" + volumeUuid ;
26232651
26242652 logger .debug ("Creating CLVM_NG volume {} with LV size {} bytes (virtual size: {} bytes)" , volumeUuid , lvSize , virtualSize );
@@ -2681,10 +2709,12 @@ public void createTemplateOnClvmNg(String templatePath, String templateUuid, int
26812709
26822710 logger .info ("Creating new template LV {} in VG {} for template {}" , lvName , vgName , templateUuid );
26832711
2684- // TODO: need to verify if virtual / physical size is to be used!
2685- //long physicalSize = getQcow2PhysicalSize(templatePath);
2686- long virualSize = getQcow2VirtualSize (templatePath );
2687- long lvSize = calculateClvmNgLvSize (virualSize , vgName );
2712+ long virtualSize = getQcow2VirtualSize (templatePath );
2713+ long physicalSize = getQcow2PhysicalSize (templatePath );
2714+ long lvSize = calculateClvmNgTemplateLvSize (physicalSize , virtualSize , vgName );
2715+
2716+ logger .info ("Template source - Physical: {} bytes, Virtual: {} bytes, LV will be: {} bytes" ,
2717+ physicalSize , virtualSize , lvSize );
26882718
26892719 Script lvcreate = new Script ("lvcreate" , Duration .millis (timeout ), logger );
26902720 lvcreate .add ("-n" , lvName );
@@ -2695,11 +2725,11 @@ public void createTemplateOnClvmNg(String templatePath, String templateUuid, int
26952725 throw new CloudRuntimeException ("Failed to create LV for CLVM_NG template: " + result );
26962726 }
26972727
2698-
26992728 Script qemuImgConvert = new Script ("qemu-img" , Duration .millis (timeout ), logger );
27002729 qemuImgConvert .add ("convert" );
27012730 qemuImgConvert .add (templatePath );
27022731 qemuImgConvert .add ("-O" , "qcow2" );
2732+ qemuImgConvert .add ("-o" , "cluster_size=64k,extended_l2=off,preallocation=off" );
27032733 qemuImgConvert .add (lvPath );
27042734 result = qemuImgConvert .execute ();
27052735
@@ -2708,8 +2738,9 @@ public void createTemplateOnClvmNg(String templatePath, String templateUuid, int
27082738 throw new CloudRuntimeException ("Failed to convert template to CLVM_NG volume: " + result );
27092739 }
27102740
2711- logger .info ("Created template LV {} with size {} bytes (physical: {}, overhead: {})" ,
2712- lvName , lvSize , virualSize , lvSize - virualSize );
2741+ long actualVirtualSize = getQcow2VirtualSize (lvPath );
2742+ logger .info ("Created template LV {} with size {} bytes (source physical: {}, actual virtual: {}, overhead: {})" ,
2743+ lvName , lvSize , physicalSize , actualVirtualSize , lvSize - physicalSize );
27132744
27142745 try {
27152746 ensureTemplateLvInSharedMode (lvPath , true );
@@ -2721,7 +2752,8 @@ public void createTemplateOnClvmNg(String templatePath, String templateUuid, int
27212752
27222753 KVMPhysicalDisk templateDisk = new KVMPhysicalDisk (lvPath , lvName , pool );
27232754 templateDisk .setFormat (PhysicalDiskFormat .QCOW2 );
2724- templateDisk .setVirtualSize (virualSize );
2755+ templateDisk .setVirtualSize (actualVirtualSize );
2756+ templateDisk .setSize (lvSize );
27252757 templateDisk .setSize (lvSize );
27262758
27272759 }
@@ -2741,5 +2773,4 @@ private void removeLvOnFailure(String lvPath, int timeout) {
27412773 lvremove .add (lvPath );
27422774 lvremove .execute ();
27432775 }
2744-
27452776}
0 commit comments