[PATCH] transparent support for pushing qcow2 images to rhev-m

Pete Zaitcev zaitcev at redhat.com
Fri Dec 2 19:48:34 UTC 2011


On Fri, 02 Dec 2011 11:36:55 -0600
Ian McLeod <imcleod at redhat.com> wrote:

> speeds up the NFS file transfer (an internal RHEV-M domain transfer)

Did you mean "and internal" in the changelog?

> +	if (bswap_32(header.magic) == QCOW_MAGIC &&
> +	    bswap_32(header.version) == QCOW_VERSION)
> +		return  bswap_64(header.size);
> +	else
> +		return 0;

This is not portable to PPC. Not that we care too much about PPC or ARM,
but still, costs us nothing to do it right in this case, so I fixed that up.

Please let me know if attached works for you.

-- Pete

diff --git a/dc-rhev-image.c b/dc-rhev-image.c
index 7e9781e..6c32b49 100644
--- a/dc-rhev-image.c
+++ b/dc-rhev-image.c
@@ -34,7 +34,9 @@
 #include <stdbool.h>
 #include <stdint.h>
 #include <unistd.h>
+#include <endian.h>
 #include <errno.h>
+#include <inttypes.h>
 #include <time.h>
 
 #include <curl/curl.h>
@@ -63,6 +65,9 @@
 #define NFSUID 36
 #define NFSGID 36
 
+#define QCOW_MAGIC (('Q' << 24) | ('F' << 16) | ('I' << 8) | 0xfb)
+#define QCOW_VERSION 2
+
 #ifndef MIN
 # define MIN(a,b) (((a) < (b)) ? (a) : (b))
 #endif
@@ -137,6 +142,22 @@ struct api_conn {
 	char *path;	/* "/rhevm-api" or "/rhevm-api-powershell" */
 };
 
+struct qcow_header {
+	uint32_t magic;
+	uint32_t version;
+	uint64_t backing_file_offset;
+	uint32_t backing_file_size;
+	uint32_t cluster_bits;
+	uint64_t size; /* in bytes */
+	uint32_t crypt_method;
+	uint32_t l1_size;
+	uint64_t l1_table_offset;
+	uint64_t refcount_table_offset;
+	uint32_t refcount_table_clusters;
+	uint32_t nb_snapshots;
+	uint64_t snapshots_offset;
+};
+
 static void Usage(void)
 {
 	fprintf(stderr, "ERROR Usage: " TAG " [" TAG ".conf]\n");
@@ -156,6 +177,39 @@ static char **env_p;
 		uri->token##_len = (len);	\
 	} while (0)
 
+/*
+ * return size of virtual disk inside qcow2 file
+ * return 0 if file is not qcow2
+ */
+static uint64_t
+read_qcow_size(char *image_file)
+{
+	struct qcow_header header;
+	FILE *fp;
+	size_t n_read;
+
+	fp = fopen(image_file, "r");
+	if (!fp) {
+		fprintf(stderr,
+		    "ERROR unable to open %s for qcow2 analysis: %s\n",
+		    image_file, strerror(errno));
+		exit(EXIT_FAILURE);
+	}
+
+	n_read = fread(&header, sizeof(header), 1, fp);
+	fclose(fp);
+
+	if (n_read != 1) {
+		return 0;
+	}
+
+	if (be32toh(header.magic) == QCOW_MAGIC &&
+	    be32toh(header.version) == QCOW_VERSION)
+		return be64toh(header.size);
+	else
+		return 0;
+}
+
 static struct http_uri *huri_parse(struct http_uri *uri, const char *uri_text)
 {
 	const char *p, *temp;
@@ -1377,7 +1431,8 @@ static void gen_uuids(struct id_pack *idp)
 }
 
 static void spitovf(const struct config *cfg, const struct stor_dom *sd,
-    const char *poolid, const struct id_pack *idp, off_t vol_size)
+    const char *poolid, const struct id_pack *idp, off_t vol_size,
+    bool qcow2)
 {
 	time_t now;
 	struct tm now_tm;
@@ -1523,12 +1578,21 @@ static void spitovf(const struct config *cfg, const struct stor_dom *sd,
 	    BAD_CAST "ovf:format",
 	    BAD_CAST "http://www.vmware.com/technical-resources/interfaces/vmdk_access.html");
 	if (rc < 0) goto err_xml;
-	rc = xmlTextWriterWriteAttribute(writer,
-	    BAD_CAST "ovf:volume-format", BAD_CAST "RAW");
-	if (rc < 0) goto err_xml;
-	rc = xmlTextWriterWriteAttribute(writer,
-	    BAD_CAST "ovf:volume-type", BAD_CAST "Preallocated");
-	if (rc < 0) goto err_xml;
+	if (qcow2) {
+		rc = xmlTextWriterWriteAttribute(writer,
+		    BAD_CAST "ovf:volume-format", BAD_CAST "COW");
+		if (rc < 0) goto err_xml;
+		rc = xmlTextWriterWriteAttribute(writer,
+		    BAD_CAST "ovf:volume-type", BAD_CAST "Sparse");
+		if (rc < 0) goto err_xml;
+	} else {
+		rc = xmlTextWriterWriteAttribute(writer,
+		    BAD_CAST "ovf:volume-format", BAD_CAST "RAW");
+		if (rc < 0) goto err_xml;
+		rc = xmlTextWriterWriteAttribute(writer,
+		    BAD_CAST "ovf:volume-type", BAD_CAST "Preallocated");
+		if (rc < 0) goto err_xml;
+	}
 	rc = xmlTextWriterWriteAttribute(writer,
 	    BAD_CAST "ovf:disk-interface", BAD_CAST "VirtIO");
 	if (rc < 0) goto err_xml;
@@ -1848,6 +1912,7 @@ static void copyimage(const struct config *cfg, const struct id_pack *idp,
 	char *imgsrc, *imgdst, *imgmeta;
 	time_t now;
 	off_t vol_size;
+	uint64_t qcow_size;
 	FILE *fp;
 
 	if (geteuid() == 0) {
@@ -1896,12 +1961,17 @@ static void copyimage(const struct config *cfg, const struct id_pack *idp,
 	/* No error processing here, it exits on error. */
 	copy_file_preserving(imgsrc, imgdst);
 
-	if (stat(imgdst, &statb) < 0) {
-		fprintf(stderr, "ERROR failed to stat %s: %s\n",
-		    imgdst, strerror(errno));
-		exit(EXIT_FAILURE);
+	qcow_size = read_qcow_size(imgsrc);
+	if (qcow_size) {
+		vol_size = qcow_size;
+	} else {
+		if (stat(imgdst, &statb) < 0) {
+			fprintf(stderr, "ERROR failed to stat %s: %s\n",
+			    imgdst, strerror(errno));
+			exit(EXIT_FAILURE);
+		}
+		vol_size = statb.st_size;
 	}
-	vol_size = statb.st_size;
 
 	rc = asprintf(&imgmeta, "%s.meta", imgdst);
 	if (rc < 0)
@@ -1918,7 +1988,10 @@ static void copyimage(const struct config *cfg, const struct id_pack *idp,
 	fprintf(fp, "VOLTYPE=LEAF\n");
 	fprintf(fp, "CTIME=%llu\n", (long long)now);
 	/* saved template has FORMAT=COW */
-	fprintf(fp, "FORMAT=RAW\n");
+	if (qcow_size)
+		fprintf(fp, "FORMAT=COW\n");
+	else
+		fprintf(fp, "FORMAT=RAW\n");
 	fprintf(fp, "IMAGE=%s\n", idp->image);
 	fprintf(fp, "DISKTYPE=1\n");
 	fprintf(fp, "PUUID=%s\n", NULID);
@@ -1935,7 +2008,7 @@ static void copyimage(const struct config *cfg, const struct id_pack *idp,
 		exit(EXIT_FAILURE);
 	}
 
-	spitovf(cfg, sd, poolid, idp, vol_size);
+	spitovf(cfg, sd, poolid, idp, vol_size, qcow_size != 0);
 
 	free(imgmeta);
 	free(imgdst);


More information about the iwhd-devel mailing list