diff --git a/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotCmd.java b/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotCmd.java index 72437c8d3fe..cf4c1d43dea 100644 --- a/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotCmd.java +++ b/api/src/main/java/org/apache/cloudstack/api/command/user/snapshot/CreateSnapshotCmd.java @@ -223,10 +223,12 @@ public class CreateSnapshotCmd extends BaseAsyncCreateCmd { response.setResponseName(getCommandName()); setResponseObject(response); } else { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create snapshot due to an internal error creating snapshot for volume " + getVolumeUuid()); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, String.format("Snapshot from volume [%s] was not found in database.", getVolumeUuid())); } } catch (Exception e) { - throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, "Failed to create snapshot due to an internal error creating snapshot for volume " + getVolumeUuid()); + String errorMessage = "Failed to create snapshot due to an internal error creating snapshot for volume " + getVolumeUuid(); + s_logger.error(errorMessage, e); + throw new ServerApiException(ApiErrorCode.INTERNAL_ERROR, errorMessage); } } diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java index e380ef187f0..1540ccac32b 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/LibvirtComputingResource.java @@ -4311,8 +4311,8 @@ public class LibvirtComputingResource extends ServerResourceBase implements Serv String backingFileFmt = backingFileinfo.get(new String("file_format")); qemu.rebase(file, backingFile, backingFileFmt, false); } - } catch (QemuImgException e) { - s_logger.error("Failed to set backing file format of " + volPath + " due to : " + e.getMessage()); + } catch (QemuImgException | LibvirtException e) { + s_logger.error("Failed to set backing file format of " + volPath + " due to : " + e.getMessage(), e); } } diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCreatePrivateTemplateFromVolumeCommandWrapper.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCreatePrivateTemplateFromVolumeCommandWrapper.java index 4bdebe1a135..e621e5facee 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCreatePrivateTemplateFromVolumeCommandWrapper.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/resource/wrapper/LibvirtCreatePrivateTemplateFromVolumeCommandWrapper.java @@ -55,6 +55,7 @@ import com.cloud.storage.template.QCOW2Processor; import com.cloud.storage.template.TemplateLocation; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.script.Script; +import org.libvirt.LibvirtException; @ResourceWrapper(handles = CreatePrivateTemplateFromVolumeCommand.class) public final class LibvirtCreatePrivateTemplateFromVolumeCommandWrapper extends CommandWrapper { @@ -120,7 +121,7 @@ public final class LibvirtCreatePrivateTemplateFromVolumeCommandWrapper extends final QemuImg q = new QemuImg(0); try { q.convert(srcFile, destFile); - } catch (final QemuImgException e) { + } catch (final QemuImgException | LibvirtException e) { s_logger.error("Failed to create new template while converting " + srcFile.getFileName() + " to " + destFile.getFileName() + " the error was: " + e.getMessage()); } diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/IscsiAdmStorageAdaptor.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/IscsiAdmStorageAdaptor.java index 7684789c3d2..fb896834e1b 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/IscsiAdmStorageAdaptor.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/IscsiAdmStorageAdaptor.java @@ -35,6 +35,7 @@ import com.cloud.utils.StringUtils; import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.script.OutputInterpreter; import com.cloud.utils.script.Script; +import org.libvirt.LibvirtException; @StorageAdaptorInfo(storagePoolType=StoragePoolType.Iscsi) public class IscsiAdmStorageAdaptor implements StorageAdaptor { @@ -420,7 +421,7 @@ public class IscsiAdmStorageAdaptor implements StorageAdaptor { try { q.convert(srcFile, destFile); - } catch (QemuImgException ex) { + } catch (QemuImgException | LibvirtException ex) { String msg = "Failed to copy data from " + srcDisk.getPath() + " to " + destDisk.getPath() + ". The error was the following: " + ex.getMessage(); diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java index 09dc8b1f23e..8c997ea8e8d 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/KVMStorageProcessor.java @@ -621,7 +621,7 @@ public class KVMStorageProcessor implements StorageProcessor { final QemuImg q = new QemuImg(cmd.getWaitInMillSeconds()); try { q.convert(srcFile, destFile); - } catch (final QemuImgException e) { + } catch (final QemuImgException | LibvirtException e) { final String message = "Failed to create new template while converting " + srcFile.getFileName() + " to " + destFile.getFileName() + " the error was: " + e.getMessage(); @@ -977,7 +977,7 @@ public class KVMStorageProcessor implements StorageProcessor { } catch (final IOException e) { s_logger.error("Failed to create " + snapshotDestPath + ". The error was: " + e.getMessage()); return new CopyCmdAnswer(e.toString()); - } catch (final QemuImgException e) { + } catch (final QemuImgException | LibvirtException e) { s_logger.error("Failed to backup the RBD snapshot from " + rbdSnapshot + " to " + snapshotFile + " the error was: " + e.getMessage()); return new CopyCmdAnswer(e.toString()); diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java index 630b9885514..c17cd447769 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java @@ -810,7 +810,7 @@ public class LibvirtStorageAdaptor implements StorageAdaptor { Map info = qemu.info(destFile); virtualSize = Long.parseLong(info.get(new String("virtual_size"))); actualSize = new File(destFile.getFileName()).length(); - } catch (QemuImgException e) { + } catch (QemuImgException | LibvirtException e) { s_logger.error("Failed to create " + volPath + " due to a failed executing of qemu-img: " + e.getMessage()); } @@ -1015,7 +1015,7 @@ public class LibvirtStorageAdaptor implements StorageAdaptor { Map options = new HashMap(); qemu.convert(sourceFile, destFile, options, null); } - } catch (QemuImgException e) { + } catch (QemuImgException | LibvirtException e) { s_logger.error("Failed to create " + disk.getPath() + " due to a failed executing of qemu-img: " + e.getMessage()); } @@ -1066,7 +1066,7 @@ public class LibvirtStorageAdaptor implements StorageAdaptor { srcFile = new QemuImgFile(template.getPath(), template.getFormat()); try{ qemu.convert(srcFile, destFile); - } catch (QemuImgException e) { + } catch (QemuImgException | LibvirtException e) { s_logger.error("Failed to create " + disk.getPath() + " due to a failed executing of qemu-img: " + e.getMessage()); } @@ -1300,12 +1300,12 @@ public class LibvirtStorageAdaptor implements StorageAdaptor { Long virtualSize = Long.parseLong(destInfo.get(new String("virtual_size"))); newDisk.setVirtualSize(virtualSize); newDisk.setSize(virtualSize); - } catch (QemuImgException e) { + } catch (QemuImgException | LibvirtException e) { s_logger.error("Failed to convert " + srcFile.getFileName() + " to " + destFile.getFileName() + " the error was: " + e.getMessage()); newDisk = null; } } - } catch (QemuImgException e) { + } catch (QemuImgException | LibvirtException e) { s_logger.error("Failed to fetch the information of file " + srcFile.getFileName() + " the error was: " + e.getMessage()); newDisk = null; } @@ -1349,7 +1349,7 @@ public class LibvirtStorageAdaptor implements StorageAdaptor { rbd.close(image); r.ioCtxDestroy(io); - } catch (QemuImgException e) { + } catch (QemuImgException | LibvirtException e) { s_logger.error("Failed to convert from " + srcFile.getFileName() + " to " + destFile.getFileName() + " the error was: " + e.getMessage()); newDisk = null; } catch (RadosException e) { @@ -1373,7 +1373,7 @@ public class LibvirtStorageAdaptor implements StorageAdaptor { try { qemu.convert(srcFile, destFile); - } catch (QemuImgException e) { + } catch (QemuImgException | LibvirtException e) { s_logger.error("Failed to convert " + srcFile.getFileName() + " to " + destFile.getFileName() + " the error was: " + e.getMessage()); newDisk = null; } @@ -1410,7 +1410,7 @@ public class LibvirtStorageAdaptor implements StorageAdaptor { QemuImgFile srcFile = new QemuImgFile(snapshot.getPath(), snapshot.getFormat()); qemu.convert(srcFile, destFile, snapshotName); } - } catch (QemuImgException e) { + } catch (QemuImgException | LibvirtException e) { s_logger.error("Failed to create " + destPath + " due to a failed executing of qemu-img: " + e.getMessage()); } diff --git a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/ScaleIOStorageAdaptor.java b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/ScaleIOStorageAdaptor.java index 62eb5440468..1c2ba5a200e 100644 --- a/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/ScaleIOStorageAdaptor.java +++ b/plugins/hypervisors/kvm/src/main/java/com/cloud/hypervisor/kvm/storage/ScaleIOStorageAdaptor.java @@ -38,6 +38,7 @@ import com.cloud.utils.exception.CloudRuntimeException; import com.cloud.utils.script.OutputInterpreter; import com.cloud.utils.script.Script; import com.google.common.base.Strings; +import org.libvirt.LibvirtException; @StorageAdaptorInfo(storagePoolType= Storage.StoragePoolType.PowerFlex) public class ScaleIOStorageAdaptor implements StorageAdaptor { @@ -270,8 +271,8 @@ public class ScaleIOStorageAdaptor implements StorageAdaptor { LOGGER.debug("Starting copy from source image " + srcFile.getFileName() + " to PowerFlex volume: " + destDisk.getPath()); qemu.convert(srcFile, destFile); LOGGER.debug("Succesfully converted source image " + srcFile.getFileName() + " to PowerFlex volume: " + destDisk.getPath()); - } catch (QemuImgException e) { - LOGGER.error("Failed to convert from " + srcFile.getFileName() + " to " + destFile.getFileName() + " the error was: " + e.getMessage()); + } catch (QemuImgException | LibvirtException e) { + LOGGER.error("Failed to convert from " + srcFile.getFileName() + " to " + destFile.getFileName() + " the error was: " + e.getMessage(), e); destDisk = null; } @@ -364,8 +365,8 @@ public class ScaleIOStorageAdaptor implements StorageAdaptor { QemuImg qemu = new QemuImg(timeout); qemu.convert(srcFile, destFile); LOGGER.debug("Succesfully converted source downloaded template " + srcFile.getFileName() + " to PowerFlex template volume: " + destDisk.getPath()); - } catch (QemuImgException e) { - LOGGER.error("Failed to convert from " + srcFile.getFileName() + " to " + destFile.getFileName() + " the error was: " + e.getMessage()); + } catch (QemuImgException | LibvirtException e) { + LOGGER.error("Failed to convert from " + srcFile.getFileName() + " to " + destFile.getFileName() + " the error was: " + e.getMessage(), e); destDisk = null; } finally { Script.runSimpleBashScript("rm -f " + srcTemplateFilePath); diff --git a/plugins/hypervisors/kvm/src/main/java/org/apache/cloudstack/utils/qemu/QemuImg.java b/plugins/hypervisors/kvm/src/main/java/org/apache/cloudstack/utils/qemu/QemuImg.java index 3006d256697..44ef71a3acf 100644 --- a/plugins/hypervisors/kvm/src/main/java/org/apache/cloudstack/utils/qemu/QemuImg.java +++ b/plugins/hypervisors/kvm/src/main/java/org/apache/cloudstack/utils/qemu/QemuImg.java @@ -20,12 +20,13 @@ import java.util.HashMap; import java.util.Iterator; import java.util.Map; -import org.apache.commons.lang.StringUtils; -import org.apache.commons.lang.NotImplementedException; - +import com.cloud.hypervisor.kvm.resource.LibvirtConnection; import com.cloud.storage.Storage; import com.cloud.utils.script.OutputInterpreter; import com.cloud.utils.script.Script; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.NotImplementedException; +import org.libvirt.LibvirtException; public class QemuImg { @@ -234,7 +235,7 @@ public class QemuImg { * @return void */ public void convert(final QemuImgFile srcFile, final QemuImgFile destFile, - final Map options, final String snapshotName) throws QemuImgException { + final Map options, final String snapshotName) throws QemuImgException, LibvirtException { Script script = new Script(_qemuImgPath, timeout); if (StringUtils.isNotBlank(snapshotName)) { String qemuPath = Script.runSimpleBashScript(getQemuImgPathScript); @@ -242,6 +243,11 @@ public class QemuImg { } script.add("convert"); + Long version = LibvirtConnection.getConnection().getVersion(); + if (version >= 2010000) { + script.add("-U"); + } + // autodetect source format. Sometime int he future we may teach KVMPhysicalDisk about more formats, then we can explicitly pass them if necessary //s.add("-f"); //s.add(srcFile.getFormat().toString()); @@ -292,7 +298,7 @@ public class QemuImg { * The destination file * @return void */ - public void convert(final QemuImgFile srcFile, final QemuImgFile destFile) throws QemuImgException { + public void convert(final QemuImgFile srcFile, final QemuImgFile destFile) throws QemuImgException, LibvirtException { this.convert(srcFile, destFile, null, null); } @@ -311,7 +317,7 @@ public class QemuImg { * The snapshot name * @return void */ - public void convert(final QemuImgFile srcFile, final QemuImgFile destFile, String snapshotName) throws QemuImgException { + public void convert(final QemuImgFile srcFile, final QemuImgFile destFile, String snapshotName) throws QemuImgException, LibvirtException { this.convert(srcFile, destFile, null, snapshotName); } @@ -343,10 +349,15 @@ public class QemuImg { * A QemuImgFile object containing the file to get the information from * @return A HashMap with String key-value information as returned by 'qemu-img info' */ - public Map info(final QemuImgFile file) throws QemuImgException { + public Map info(final QemuImgFile file) throws QemuImgException, LibvirtException { final Script s = new Script(_qemuImgPath); s.add("info"); + Long version = LibvirtConnection.getConnection().getVersion(); + if (version >= 2010000) { + s.add("-U"); + } s.add(file.getFileName()); + final OutputInterpreter.AllLinesParser parser = new OutputInterpreter.AllLinesParser(); final String result = s.execute(parser); if (result != null) { diff --git a/plugins/hypervisors/kvm/src/test/java/org/apache/cloudstack/utils/qemu/QemuImgTest.java b/plugins/hypervisors/kvm/src/test/java/org/apache/cloudstack/utils/qemu/QemuImgTest.java index e81890a9832..c58c4308243 100644 --- a/plugins/hypervisors/kvm/src/test/java/org/apache/cloudstack/utils/qemu/QemuImgTest.java +++ b/plugins/hypervisors/kvm/src/test/java/org/apache/cloudstack/utils/qemu/QemuImgTest.java @@ -30,13 +30,14 @@ import org.junit.Ignore; import org.junit.Test; import org.apache.cloudstack.utils.qemu.QemuImg.PhysicalDiskFormat; +import org.libvirt.LibvirtException; @Ignore public class QemuImgTest { @Test - public void testCreateAndInfo() throws QemuImgException { + public void testCreateAndInfo() throws QemuImgException, LibvirtException { String filename = "/tmp/" + UUID.randomUUID() + ".qcow2"; /* 10TB virtual_size */ @@ -63,7 +64,7 @@ public class QemuImgTest { } @Test - public void testCreateAndInfoWithOptions() throws QemuImgException { + public void testCreateAndInfoWithOptions() throws QemuImgException, LibvirtException { String filename = "/tmp/" + UUID.randomUUID() + ".qcow2"; /* 10TB virtual_size */ @@ -118,7 +119,7 @@ public class QemuImgTest { } @Test - public void testCreateAndResize() throws QemuImgException { + public void testCreateAndResize() throws QemuImgException, LibvirtException { String filename = "/tmp/" + UUID.randomUUID() + ".qcow2"; long startSize = 20480; @@ -147,7 +148,7 @@ public class QemuImgTest { } @Test - public void testCreateAndResizeDeltaPositive() throws QemuImgException { + public void testCreateAndResizeDeltaPositive() throws QemuImgException, LibvirtException { String filename = "/tmp/" + UUID.randomUUID() + ".qcow2"; long startSize = 20480; @@ -175,7 +176,7 @@ public class QemuImgTest { } @Test - public void testCreateAndResizeDeltaNegative() throws QemuImgException { + public void testCreateAndResizeDeltaNegative() throws QemuImgException, LibvirtException { String filename = "/tmp/" + UUID.randomUUID() + ".qcow2"; long startSize = 81920; @@ -239,7 +240,7 @@ public class QemuImgTest { } @Test - public void testCreateWithBackingFile() throws QemuImgException { + public void testCreateWithBackingFile() throws QemuImgException, LibvirtException { String firstFileName = "/tmp/" + UUID.randomUUID() + ".qcow2"; String secondFileName = "/tmp/" + UUID.randomUUID() + ".qcow2"; @@ -262,7 +263,7 @@ public class QemuImgTest { } @Test - public void testConvertBasic() throws QemuImgException { + public void testConvertBasic() throws QemuImgException, LibvirtException { long srcSize = 20480; String srcFileName = "/tmp/" + UUID.randomUUID() + ".qcow2"; String destFileName = "/tmp/" + UUID.randomUUID() + ".qcow2"; @@ -287,7 +288,7 @@ public class QemuImgTest { } @Test - public void testConvertAdvanced() throws QemuImgException { + public void testConvertAdvanced() throws QemuImgException, LibvirtException { long srcSize = 4019200; String srcFileName = "/tmp/" + UUID.randomUUID() + ".qcow2"; String destFileName = "/tmp/" + UUID.randomUUID() + ".qcow2"; diff --git a/scripts/storage/qcow2/resizevolume.sh b/scripts/storage/qcow2/resizevolume.sh index 136abd1e496..a45f2e1151a 100755 --- a/scripts/storage/qcow2/resizevolume.sh +++ b/scripts/storage/qcow2/resizevolume.sh @@ -178,7 +178,23 @@ resizeqcow2() { fi ##### end sanity ##### - actualsize=`qemu-img info $path | grep "virtual size" | sed -re 's/^.*\(([0-9]+).*$/\1/g'` + regex=".*version\s([0-9]+)\.([0-9]+).*" + content=$(qemu-img --version | grep version) + + qemu_force_share_flag="" + if [[ $content =~ $regex ]] + then + version_first_element="${BASH_REMATCH[1]}" + version_second_element="${BASH_REMATCH[2]}" + if [[ ${version_first_element} -gt 2 ]] || [[ ${version_first_element} -eq 2 && ${version_second_element} -ge 10 ]] + then + qemu_force_share_flag=" -U " + fi + else + echo "Could not retrieve qemu version. Skipping validation to add --force-share flag." + fi + + actualsize=`qemu-img info $qemu_force_share_flag $path | grep "virtual size" | sed -re 's/^.*\(([0-9]+).*$/\1/g'` if [ $actualsize -ne $currentsize ] then