use of com.cloud.agent.resource.kvm.storage.utils.QemuImgException in project cosmic by MissionCriticalCloud.
the class LibvirtStorageAdaptor method createDiskFromTemplate.
@Override
public KvmPhysicalDisk createDiskFromTemplate(final KvmPhysicalDisk template, final String name, final PhysicalDiskFormat format, final StorageProvisioningType provisioningType, final long size, final KvmStoragePool destPool, final int timeout) {
this.logger.info("Creating volume " + name + " from template " + template.getName() + " in pool " + destPool.getUuid() + " (" + destPool.getType().toString() + ") with size " + size);
KvmPhysicalDisk disk = null;
if (destPool.getType() == StoragePoolType.RBD) {
disk = createDiskFromTemplateOnRbd(template, name, size, destPool, timeout);
} else {
try {
disk = destPool.createPhysicalDisk(name, format, provisioningType, template.getVirtualSize());
if (disk == null) {
throw new CloudRuntimeException("Failed to create disk from template " + template.getName());
}
if (template.getFormat() == PhysicalDiskFormat.TAR) {
Script.runSimpleBashScript("tar -x -f " + template.getPath() + " -C " + disk.getPath(), timeout);
} else if (template.getFormat() == PhysicalDiskFormat.DIR) {
Script.runSimpleBashScript("mkdir -p " + disk.getPath());
Script.runSimpleBashScript("chmod 755 " + disk.getPath());
Script.runSimpleBashScript("tar -x -f " + template.getPath() + "/*.tar -C " + disk.getPath(), timeout);
} else if (format == PhysicalDiskFormat.QCOW2) {
final QemuImg qemu = new QemuImg(timeout);
final QemuImgFile destFile = new QemuImgFile(disk.getPath(), format);
if (size > template.getVirtualSize()) {
destFile.setSize(size);
} else {
destFile.setSize(template.getVirtualSize());
}
final Map<String, String> options = new HashMap<>();
options.put("preallocation", PreallocationType.getPreallocationType(provisioningType).toString().toLowerCase());
switch(provisioningType) {
case THIN:
final QemuImgFile backingFile = new QemuImgFile(template.getPath(), template.getFormat());
qemu.create(destFile, backingFile, options);
break;
case SPARSE:
case FAT:
final QemuImgFile srcFile = new QemuImgFile(template.getPath(), template.getFormat());
qemu.convert(srcFile, destFile, options);
break;
default:
break;
}
} else if (format == PhysicalDiskFormat.RAW) {
final QemuImgFile sourceFile = new QemuImgFile(template.getPath(), template.getFormat());
final QemuImgFile destFile = new QemuImgFile(disk.getPath(), PhysicalDiskFormat.RAW);
if (size > template.getVirtualSize()) {
destFile.setSize(size);
} else {
destFile.setSize(template.getVirtualSize());
}
final QemuImg qemu = new QemuImg(timeout);
final Map<String, String> options = new HashMap<>();
qemu.convert(sourceFile, destFile, options);
}
} catch (final QemuImgException e) {
this.logger.error("Failed to create " + disk.getPath() + " due to a failed executing of qemu-img: " + e.getMessage());
}
}
return disk;
}
use of com.cloud.agent.resource.kvm.storage.utils.QemuImgException in project cosmic by MissionCriticalCloud.
the class LibvirtStorageAdaptor method createDiskFromTemplateOnRbd.
private KvmPhysicalDisk createDiskFromTemplateOnRbd(final KvmPhysicalDisk template, final String name, final long size, final KvmStoragePool destPool, final int timeout) {
/*
* With RBD you can't run qemu-img convert with an existing RBD image as destination qemu-img will exit with the
* error that the destination already exists. So for RBD we don't create the image, but let qemu-img do that for us.
*
* We then create a KVMPhysicalDisk object that we can return
*/
final KvmStoragePool srcPool = template.getPool();
KvmPhysicalDisk disk;
final PhysicalDiskFormat format = PhysicalDiskFormat.RAW;
disk = new KvmPhysicalDisk(destPool.getSourceDir() + "/" + name, name, destPool);
disk.setFormat(format);
if (size > template.getVirtualSize()) {
disk.setSize(size);
disk.setVirtualSize(size);
} else {
// leave these as they were if size isn't applicable
disk.setSize(template.getVirtualSize());
disk.setVirtualSize(disk.getSize());
}
final QemuImg qemu = new QemuImg(timeout);
final QemuImgFile srcFile;
final QemuImgFile destFile = new QemuImgFile(KvmPhysicalDisk.rbdStringBuilder(destPool.getSourceHost(), destPool.getSourcePort(), destPool.getAuthUserName(), destPool.getAuthSecret(), disk.getPath()));
destFile.setFormat(format);
if (srcPool.getType() != StoragePoolType.RBD) {
srcFile = new QemuImgFile(template.getPath(), template.getFormat());
try {
qemu.convert(srcFile, destFile);
} catch (final QemuImgException e) {
this.logger.error("Failed to create " + disk.getPath() + " due to a failed executing of qemu-img: " + e.getMessage());
}
} else {
try {
if (srcPool.getSourceHost().equals(destPool.getSourceHost()) && srcPool.getSourceDir().equals(destPool.getSourceDir())) {
/* We are on the same Ceph cluster, but we require RBD format 2 on the source image */
this.logger.debug("Trying to perform a RBD clone (layering) since we are operating in the same storage pool");
final Rados r = new Rados(srcPool.getAuthUserName());
r.confSet("mon_host", srcPool.getSourceHost() + ":" + srcPool.getSourcePort());
r.confSet("key", srcPool.getAuthSecret());
r.confSet("client_mount_timeout", "30");
r.connect();
this.logger.debug("Succesfully connected to Ceph cluster at " + r.confGet("mon_host"));
final IoCTX io = r.ioCtxCreate(srcPool.getSourceDir());
final Rbd rbd = new Rbd(io);
final RbdImage srcImage = rbd.open(template.getName());
if (srcImage.isOldFormat()) {
/* The source image is RBD format 1, we have to do a regular copy */
this.logger.debug("The source image " + srcPool.getSourceDir() + "/" + template.getName() + " is RBD format 1. We have to perform a regular copy (" + disk.getVirtualSize() + " bytes)");
rbd.create(disk.getName(), disk.getVirtualSize(), this.rbdFeatures, this.rbdOrder);
final RbdImage destImage = rbd.open(disk.getName());
this.logger.debug("Starting to copy " + srcImage.getName() + " to " + destImage.getName() + " in Ceph pool " + srcPool.getSourceDir());
rbd.copy(srcImage, destImage);
this.logger.debug("Finished copying " + srcImage.getName() + " to " + destImage.getName() + " in Ceph pool " + srcPool.getSourceDir());
rbd.close(destImage);
} else {
final String rbdTemplateSnapName = "cloudstack-base-snap";
this.logger.debug("The source image " + srcPool.getSourceDir() + "/" + template.getName() + " is RBD format 2. We will perform a RBD clone using snapshot " + rbdTemplateSnapName);
/* The source image is format 2, we can do a RBD snapshot+clone (layering) */
this.logger.debug("Checking if RBD snapshot " + srcPool.getSourceDir() + "/" + template.getName() + "@" + rbdTemplateSnapName + " exists prior to attempting a clone operation.");
final List<RbdSnapInfo> snaps = srcImage.snapList();
this.logger.debug("Found " + snaps.size() + " snapshots on RBD image " + srcPool.getSourceDir() + "/" + template.getName());
boolean snapFound = false;
for (final RbdSnapInfo snap : snaps) {
if (rbdTemplateSnapName.equals(snap.name)) {
this.logger.debug("RBD snapshot " + srcPool.getSourceDir() + "/" + template.getName() + "@" + rbdTemplateSnapName + " already exists.");
snapFound = true;
break;
}
}
if (!snapFound) {
this.logger.debug("Creating RBD snapshot " + rbdTemplateSnapName + " on image " + name);
srcImage.snapCreate(rbdTemplateSnapName);
this.logger.debug("Protecting RBD snapshot " + rbdTemplateSnapName + " on image " + name);
srcImage.snapProtect(rbdTemplateSnapName);
}
rbd.clone(template.getName(), rbdTemplateSnapName, io, disk.getName(), this.rbdFeatures, this.rbdOrder);
this.logger.debug("Succesfully cloned " + template.getName() + "@" + rbdTemplateSnapName + " to " + disk.getName());
/* We also need to resize the image if the VM was deployed with a larger root disk size */
if (disk.getVirtualSize() > template.getVirtualSize()) {
final RbdImage diskImage = rbd.open(disk.getName());
diskImage.resize(disk.getVirtualSize());
rbd.close(diskImage);
this.logger.debug("Resized " + disk.getName() + " to " + disk.getVirtualSize());
}
}
rbd.close(srcImage);
r.ioCtxDestroy(io);
} else {
/* The source pool or host is not the same Ceph cluster, we do a simple copy with Qemu-Img */
this.logger.debug("Both the source and destination are RBD, but not the same Ceph cluster. Performing a copy");
final Rados rSrc = new Rados(srcPool.getAuthUserName());
rSrc.confSet("mon_host", srcPool.getSourceHost() + ":" + srcPool.getSourcePort());
rSrc.confSet("key", srcPool.getAuthSecret());
rSrc.confSet("client_mount_timeout", "30");
rSrc.connect();
this.logger.debug("Succesfully connected to source Ceph cluster at " + rSrc.confGet("mon_host"));
final Rados rDest = new Rados(destPool.getAuthUserName());
rDest.confSet("mon_host", destPool.getSourceHost() + ":" + destPool.getSourcePort());
rDest.confSet("key", destPool.getAuthSecret());
rDest.confSet("client_mount_timeout", "30");
rDest.connect();
this.logger.debug("Succesfully connected to source Ceph cluster at " + rDest.confGet("mon_host"));
final IoCTX sourceIo = rSrc.ioCtxCreate(srcPool.getSourceDir());
final Rbd sourceRbd = new Rbd(sourceIo);
final IoCTX destinationIo = rDest.ioCtxCreate(destPool.getSourceDir());
final Rbd destinationRbd = new Rbd(destinationIo);
this.logger.debug("Creating " + disk.getName() + " on the destination cluster " + rDest.confGet("mon_host") + " in pool " + destPool.getSourceDir());
destinationRbd.create(disk.getName(), disk.getVirtualSize(), this.rbdFeatures, this.rbdOrder);
final RbdImage srcImage = sourceRbd.open(template.getName());
final RbdImage destImage = destinationRbd.open(disk.getName());
this.logger.debug("Copying " + template.getName() + " from Ceph cluster " + rSrc.confGet("mon_host") + " to " + disk.getName() + " on cluster " + rDest.confGet("mon_host"));
sourceRbd.copy(srcImage, destImage);
sourceRbd.close(srcImage);
destinationRbd.close(destImage);
rSrc.ioCtxDestroy(sourceIo);
rDest.ioCtxDestroy(destinationIo);
}
} catch (final RadosException e) {
this.logger.error("Failed to perform a RADOS action on the Ceph cluster, the error was: " + e.getMessage());
disk = null;
} catch (final RbdException e) {
this.logger.error("Failed to perform a RBD action on the Ceph cluster, the error was: " + e.getMessage());
disk = null;
}
}
return disk;
}
use of com.cloud.agent.resource.kvm.storage.utils.QemuImgException in project cosmic by MissionCriticalCloud.
the class LibvirtCreatePrivateTemplateFromVolumeCommandWrapper method execute.
@Override
public Answer execute(final CreatePrivateTemplateFromVolumeCommand command, final LibvirtComputingResource libvirtComputingResource) {
final String secondaryStorageUrl = command.getSecondaryStorageUrl();
KvmStoragePool secondaryStorage = null;
KvmStoragePool primary = null;
final KvmStoragePoolManager storagePoolMgr = libvirtComputingResource.getStoragePoolMgr();
try {
final String templateFolder = command.getAccountId() + File.separator + command.getTemplateId() + File.separator;
final String templateInstallFolder = "/template/tmpl/" + templateFolder;
secondaryStorage = storagePoolMgr.getStoragePoolByUri(secondaryStorageUrl);
try {
primary = storagePoolMgr.getStoragePool(command.getPool().getType(), command.getPrimaryStoragePoolNameLabel());
} catch (final CloudRuntimeException e) {
if (e.getMessage().contains("not found")) {
primary = storagePoolMgr.createStoragePool(command.getPool().getUuid(), command.getPool().getHost(), command.getPool().getPort(), command.getPool().getPath(), command.getPool().getUserInfo(), command.getPool().getType());
} else {
return new CreatePrivateTemplateAnswer(command, false, e.getMessage());
}
}
final KvmPhysicalDisk disk = primary.getPhysicalDisk(command.getVolumePath());
final String tmpltPath = secondaryStorage.getLocalPath() + File.separator + templateInstallFolder;
final StorageLayer storage = libvirtComputingResource.getStorage();
storage.mkdirs(tmpltPath);
if (primary.getType() != StoragePoolType.RBD) {
final String createTmplPath = libvirtComputingResource.createTmplPath();
final int cmdsTimeout = libvirtComputingResource.getCmdsTimeout();
final Script scriptCommand = new Script(createTmplPath, cmdsTimeout, s_logger);
scriptCommand.add("-f", disk.getPath());
scriptCommand.add("-t", tmpltPath);
scriptCommand.add("-n", command.getUniqueName() + ".qcow2");
final String result = scriptCommand.execute();
if (result != null) {
s_logger.debug("failed to create template: " + result);
return new CreatePrivateTemplateAnswer(command, false, result);
}
} else {
s_logger.debug("Converting RBD disk " + disk.getPath() + " into template " + command.getUniqueName());
final QemuImgFile srcFile = new QemuImgFile(KvmPhysicalDisk.rbdStringBuilder(primary.getSourceHost(), primary.getSourcePort(), primary.getAuthUserName(), primary.getAuthSecret(), disk.getPath()));
srcFile.setFormat(PhysicalDiskFormat.RAW);
final QemuImgFile destFile = new QemuImgFile(tmpltPath + "/" + command.getUniqueName() + ".qcow2");
destFile.setFormat(PhysicalDiskFormat.QCOW2);
final QemuImg q = new QemuImg(0);
try {
q.convert(srcFile, destFile);
} catch (final QemuImgException e) {
s_logger.error("Failed to create new template while converting " + srcFile.getFileName() + " to " + destFile.getFileName() + " the error was: " + e.getMessage());
}
final File templateProp = new File(tmpltPath + "/template.properties");
if (!templateProp.exists()) {
templateProp.createNewFile();
}
String templateContent = "filename=" + command.getUniqueName() + ".qcow2" + System.getProperty("line.separator");
final DateFormat dateFormat = new SimpleDateFormat("MM_dd_yyyy");
final Date date = new Date();
templateContent += "snapshot.name=" + dateFormat.format(date) + System.getProperty("line.separator");
try (final FileOutputStream templFo = new FileOutputStream(templateProp)) {
templFo.write(templateContent.getBytes("UTF-8"));
templFo.flush();
} catch (final IOException ex) {
s_logger.error("CreatePrivateTemplateAnswer:Exception:" + ex.getMessage());
}
}
final Map<String, Object> params = new HashMap<>();
params.put(StorageLayer.InstanceConfigKey, storage);
final Processor qcow2Processor = new QCOW2Processor();
qcow2Processor.configure("QCOW2 Processor", params);
final TemplateFormatInfo info = qcow2Processor.process(tmpltPath, null, command.getUniqueName());
final TemplateLocation loc = new TemplateLocation(storage, tmpltPath);
loc.create(1, true, command.getUniqueName());
loc.addFormat(info);
loc.save();
return new CreatePrivateTemplateAnswer(command, true, null, templateInstallFolder + command.getUniqueName() + ".qcow2", info.virtualSize, info.size, command.getUniqueName(), ImageFormat.QCOW2);
} catch (final InternalErrorException e) {
return new CreatePrivateTemplateAnswer(command, false, e.toString());
} catch (final IOException e) {
return new CreatePrivateTemplateAnswer(command, false, e.toString());
} catch (final ConfigurationException e) {
return new CreatePrivateTemplateAnswer(command, false, e.toString());
} catch (final CloudRuntimeException e) {
return new CreatePrivateTemplateAnswer(command, false, e.toString());
} finally {
if (secondaryStorage != null) {
storagePoolMgr.deleteStoragePool(secondaryStorage.getType(), secondaryStorage.getUuid());
}
}
}
Aggregations