Qemu 2.10 requires -U flag to read volume metadata (#4567)

Co-authored-by: Daniel Augusto Veronezi Salvador <daniel@scclouds.com.br>
This commit is contained in:
Daniel Augusto Veronezi Salvador 2021-03-18 07:54:01 -03:00 committed by GitHub
parent 850ea61dc9
commit 4e90a8c454
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 69 additions and 36 deletions

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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<CreatePrivateTemplateFromVolumeCommand, Answer, LibvirtComputingResource> {
@ -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());
}

View File

@ -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();

View File

@ -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());

View File

@ -810,7 +810,7 @@ public class LibvirtStorageAdaptor implements StorageAdaptor {
Map<String, String> 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<String, String> options = new HashMap<String, String>();
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());
}

View File

@ -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);

View File

@ -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<String, String> options, final String snapshotName) throws QemuImgException {
final Map<String, String> 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<String, String> info(final QemuImgFile file) throws QemuImgException {
public Map<String, String> 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) {

View File

@ -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";

View File

@ -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