@@ -223,6 +223,26 @@ public class KVMStorageProcessor implements StorageProcessor {
223223 " </devices>\n " +
224224 "</domain>" ;
225225
226+ private static final String DUMMY_VM_XML_BLOCK = "<domain type='qemu'>\n " +
227+ " <name>%s</name>\n " +
228+ " <memory unit='MiB'>256</memory>\n " +
229+ " <currentMemory unit='MiB'>256</currentMemory>\n " +
230+ " <vcpu>1</vcpu>\n " +
231+ " <os>\n " +
232+ " <type arch='%s' machine='%s'>hvm</type>\n " +
233+ " <boot dev='hd'/>\n " +
234+ " </os>\n " +
235+ " <devices>\n " +
236+ " <emulator>%s</emulator>\n " +
237+ " <disk type='block' device='disk'>\n " +
238+ " <driver name='qemu' type='qcow2' cache='none'/>\n " +
239+ " <source dev='%s'/>\n " +
240+ " <target dev='sda'/>\n " +
241+ " </disk>\n " +
242+ " <graphics type='vnc' port='-1'/>\n " +
243+ " </devices>\n " +
244+ "</domain>" ;
245+
226246
227247 public KVMStorageProcessor (final KVMStoragePoolManager storagePoolMgr , final LibvirtComputingResource resource ) {
228248 this .storagePoolMgr = storagePoolMgr ;
@@ -2038,9 +2058,21 @@ public Answer createSnapshot(final CreateObjectCommand cmd) {
20382058 newSnapshot .setPhysicalSize (snapshotSize );
20392059 }
20402060 } else if (primaryPool .getType () == StoragePoolType .CLVM || primaryPool .getType () == StoragePoolType .CLVM_NG ) {
2041- CreateObjectAnswer result = takeClvmVolumeSnapshotOfStoppedVm (disk , snapshotName );
2042- if (result != null ) return result ;
2043- newSnapshot .setPath (snapshotPath );
2061+ if (primaryPool .getType () == StoragePoolType .CLVM_NG && snapshotTO .isKvmIncrementalSnapshot ()) {
2062+ if (secondaryPool == null ) {
2063+ String errorMsg = String .format ("Incremental snapshots for CLVM_NG require secondary storage. " +
2064+ "Please configure secondary storage or disable incremental snapshots for volume [%s]." , volume .getName ());
2065+ logger .error (errorMsg );
2066+ return new CreateObjectAnswer (errorMsg );
2067+ }
2068+ logger .info ("Taking incremental snapshot of CLVM_NG volume [{}] using QCOW2 backup to secondary storage." , volume .getName ());
2069+ newSnapshot = takeIncrementalVolumeSnapshotOfStoppedVm (snapshotTO , primaryPool , secondaryPool ,
2070+ imageStoreTo .getUrl (), snapshotName , volume , conn , cmd .getWait ());
2071+ } else {
2072+ CreateObjectAnswer result = takeClvmVolumeSnapshotOfStoppedVm (disk , snapshotName );
2073+ if (result != null ) return result ;
2074+ newSnapshot .setPath (snapshotPath );
2075+ }
20442076 } else {
20452077 if (snapshotTO .isKvmIncrementalSnapshot ()) {
20462078 newSnapshot = takeIncrementalVolumeSnapshotOfStoppedVm (snapshotTO , primaryPool , secondaryPool , imageStoreTo != null ? imageStoreTo .getUrl () : null , snapshotName , volume , conn , cmd .getWait ());
@@ -2113,7 +2145,11 @@ private String getVmXml(KVMStoragePool primaryPool, VolumeObjectTO volumeObjectT
21132145 String machine = resource .isGuestAarch64 () ? LibvirtComputingResource .VIRT : LibvirtComputingResource .PC ;
21142146 String cpuArch = resource .getGuestCpuArch () != null ? resource .getGuestCpuArch () : "x86_64" ;
21152147
2116- return String .format (DUMMY_VM_XML , vmName , cpuArch , machine , resource .getHypervisorPath (), primaryPool .getLocalPathFor (volumeObjectTo .getPath ()));
2148+ String volumePath = primaryPool .getLocalPathFor (volumeObjectTo .getPath ());
2149+ boolean isClvmNg = StoragePoolType .CLVM_NG == primaryPool .getType ();
2150+
2151+ String xmlTemplate = isClvmNg ? DUMMY_VM_XML_BLOCK : DUMMY_VM_XML ;
2152+ return String .format (xmlTemplate , vmName , cpuArch , machine , resource .getHypervisorPath (), volumePath );
21172153 }
21182154
21192155 private SnapshotObjectTO takeIncrementalVolumeSnapshotOfRunningVm (SnapshotObjectTO snapshotObjectTO , KVMStoragePool primaryPool , KVMStoragePool secondaryPool ,
0 commit comments