Skip to content

Commit 9763faf

Browse files
committed
rbd: Use qemu-img to convert from QCOW2 templates to RBD directly.
This saves the step of writing to a temporary image in /tmp first before writing to RBD. This is possible due to a new version in librbd. With the rbd_default_format setting we can now force qemu-img to create format 2 RBD images. This is available since Ceph version 0.67.5 (Dumpling).
1 parent d5333f4 commit 9763faf

2 files changed

Lines changed: 17 additions & 47 deletions

File tree

plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/KVMPhysicalDisk.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,10 @@ public static String RBDStringBuilder(String monHost, int monPort, String authUs
3939
rbdOpts += ":id=" + authUserName;
4040
rbdOpts += ":key=" + authSecret;
4141
}
42+
43+
rbdOpts += ":rbd_default_format=2";
44+
rbdOpts += ":client_mount_timeout=30";
45+
4246
return rbdOpts;
4347
}
4448

plugins/hypervisors/kvm/src/com/cloud/hypervisor/kvm/storage/LibvirtStorageAdaptor.java

Lines changed: 13 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,7 @@
1616
// under the License.
1717
package com.cloud.hypervisor.kvm.storage;
1818

19-
import java.io.BufferedInputStream;
2019
import java.io.File;
21-
import java.io.FileInputStream;
22-
import java.io.IOException;
2320
import java.util.ArrayList;
2421
import java.util.List;
2522
import java.util.Map;
@@ -1096,19 +1093,19 @@ public KVMPhysicalDisk copyPhysicalDisk(KVMPhysicalDisk disk, String name, KVMSt
10961093
boolean useTmpFile = false;
10971094

10981095
try {
1099-
if (sourceFormat != destFormat) {
1100-
srcFile = new QemuImgFile(sourcePath, sourceFormat);
1101-
destFile = new QemuImgFile("/tmp/" + name);
1102-
s_logger.debug("Converting " + srcFile.getFileName() + " to " + destFile.getFileName() + " as a temporary file for RBD conversion");
1103-
qemu.convert(srcFile, destFile);
1104-
sourceFile = destFile.getFileName();
1105-
useTmpFile = true;
1106-
} else {
1107-
// Source file is RAW, we can write directly to RBD
1108-
sourceFile = sourcePath;
1109-
}
1096+
srcFile = new QemuImgFile(sourcePath, sourceFormat);
1097+
String rbdDestFile = KVMPhysicalDisk.RBDStringBuilder(destPool.getSourceHost(),
1098+
destPool.getSourcePort(),
1099+
destPool.getAuthUserName(),
1100+
destPool.getAuthSecret(),
1101+
destPool.getSourceDir() + "/" + name);
1102+
destFile = new QemuImgFile(rbdDestFile, destFormat);
1103+
1104+
s_logger.debug("Starting copy from source image " + srcFile.getFileName() + " to RBD image " + destPool.getSourceDir() + "/" + name);
1105+
qemu.convert(srcFile, destFile);
1106+
s_logger.debug("Succesfully converted source image " + srcFile.getFileName() + " to RBD image " + destPool.getSourceDir() + "/" + name);
11101107

1111-
// We now convert the temporary file to a RBD image with format 2
1108+
/* We still have to create and protect a RBD snapshot in order to do cloning */
11121109
Rados r = new Rados(destPool.getAuthUserName());
11131110
r.confSet("mon_host", destPool.getSourceHost() + ":" + destPool.getSourcePort());
11141111
r.confSet("key", destPool.getAuthSecret());
@@ -1119,35 +1116,8 @@ public KVMPhysicalDisk copyPhysicalDisk(KVMPhysicalDisk disk, String name, KVMSt
11191116
IoCTX io = r.ioCtxCreate(destPool.getSourceDir());
11201117
Rbd rbd = new Rbd(io);
11211118

1122-
s_logger.debug("Creating RBD image " + name + " in Ceph pool " + destPool.getSourceDir() + " with RBD format 2");
1123-
rbd.create(name, disk.getVirtualSize(), rbdFeatures, rbdOrder);
1124-
11251119
RbdImage image = rbd.open(name);
11261120

1127-
File fh = new File(sourceFile);
1128-
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(fh));
1129-
1130-
int chunkSize = 4194304;
1131-
long offset = 0;
1132-
s_logger.debug("Reading file " + sourceFile + " (" + fh.length() + " bytes) into RBD image " + name + " in chunks of " + chunkSize + " bytes");
1133-
while (true) {
1134-
byte[] buf = new byte[chunkSize];
1135-
1136-
int bytes = bis.read(buf);
1137-
if (bytes <= 0) {
1138-
break;
1139-
}
1140-
image.write(buf, offset, bytes);
1141-
offset += bytes;
1142-
}
1143-
s_logger.debug("Completed writing " + sourceFile + " to RBD image " + name + ". Bytes written: " + offset);
1144-
bis.close();
1145-
1146-
if (useTmpFile) {
1147-
s_logger.debug("Removing temporary file " + sourceFile);
1148-
fh.delete();
1149-
}
1150-
11511121
/* Snapshot the image and protect that snapshot so we can clone (layer) from it */
11521122
s_logger.debug("Creating RBD snapshot " + rbdTemplateSnapName + " on image " + name);
11531123
image.snapCreate(rbdTemplateSnapName);
@@ -1157,19 +1127,15 @@ public KVMPhysicalDisk copyPhysicalDisk(KVMPhysicalDisk disk, String name, KVMSt
11571127
rbd.close(image);
11581128
r.ioCtxDestroy(io);
11591129
} catch (QemuImgException e) {
1160-
s_logger.error("Failed to do a temp convert from " + srcFile.getFileName() + " to " + destFile.getFileName() + " the error was: " + e.getMessage());
1130+
s_logger.error("Failed to convert from " + srcFile.getFileName() + " to " + destFile.getFileName() + " the error was: " + e.getMessage());
11611131
newDisk = null;
11621132
} catch (RadosException e) {
11631133
s_logger.error("A Ceph RADOS operation failed (" + e.getReturnValue() + "). The error was: " + e.getMessage());
11641134
newDisk = null;
11651135
} catch (RbdException e) {
11661136
s_logger.error("A Ceph RBD operation failed (" + e.getReturnValue() + "). The error was: " + e.getMessage());
11671137
newDisk = null;
1168-
} catch (IOException e) {
1169-
s_logger.error("Failed reading the temporary file during the conversion to RBD: " + e.getMessage());
1170-
newDisk = null;
11711138
}
1172-
11731139
} else {
11741140
/**
11751141
We let Qemu-Img do the work here. Although we could work with librbd and have that do the cloning

0 commit comments

Comments
 (0)