[PATCH] transparent support for pushing qcow2 images to rhev-m
Jim Meyering
jim at meyering.net
Tue Dec 6 10:23:37 UTC 2011
Ian McLeod wrote:
> Below is a further revision to this patch incorporating some feedback
> from both Pete and Jim.
>
...
> 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;
> + }
Thanks.
I've added our usual ChangeLog-style commit log for you,
and made an additional change to avoid the duplication in the above:
+ char const *fmt = qcow2 ? "COW" : "RAW";
+ char const *vol_type = qcow2 ? "Sparse" : "Preallocated";
rc = xmlTextWriterWriteAttribute(writer,
- BAD_CAST "ovf:volume-format", BAD_CAST "RAW");
+ BAD_CAST "ovf:volume-format", BAD_CAST fmt);
if (rc < 0) goto err_xml;
rc = xmlTextWriterWriteAttribute(writer,
- BAD_CAST "ovf:volume-type", BAD_CAST "Preallocated");
+ BAD_CAST "ovf:volume-type", BAD_CAST vol_type);
I also moved each of the declarations in read_qcow_size "down" to
the point of first use. That makes for more readable code (shorter
and more maintainable).
>From ab30576d6dd55efe5a7c087d6dc8dcd77967e734 Mon Sep 17 00:00:00 2001
From: Jim Meyering <meyering at redhat.com>
Date: Tue, 6 Dec 2011 11:16:16 +0100
Subject: [PATCH] rhev-m: add QCOW image support
* dc-rhev-image.c: Automatically detect and use a QCOW image.
Include <endian.h> and <inttypes.h>.
(QCOW_MAGIC, QCOW_VERSION): Define.
(struct qcow_header): Define.
(read_qcow_size): New function.
(spitovf): Add/use boolean qcow2 parameter.
(copyimage): Use read_qcow_size to determine image size and type.
* NEWS (New features): Mention it.
---
NEWS | 6 ++++
dc-rhev-image.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++-------
2 files changed, 76 insertions(+), 10 deletions(-)
diff --git a/NEWS b/NEWS
index 83a0a95..23682d3 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,12 @@ iwhd NEWS -*- outline -*-
* Noteworthy changes in release ?.? (????-??-??) [?]
+** New features
+
+ Add automatic qcow2 format detection to the dc-rhev-image helper
+ utility. This change allows you to use both raw and qcow2 images to
+ create templates in a RHEV-M environment.
+
* Noteworthy changes in release 1.1 (2011-12-01) [stable]
diff --git a/dc-rhev-image.c b/dc-rhev-image.c
index 7e9781e..bf26212 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,36 @@ 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(const char *image_file)
+{
+ FILE *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);
+ }
+
+ struct qcow_header header;
+ size_t 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 +1428,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,11 +1575,13 @@ 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;
+ char const *fmt = qcow2 ? "COW" : "RAW";
+ char const *vol_type = qcow2 ? "Sparse" : "Preallocated";
rc = xmlTextWriterWriteAttribute(writer,
- BAD_CAST "ovf:volume-format", BAD_CAST "RAW");
+ BAD_CAST "ovf:volume-format", BAD_CAST fmt);
if (rc < 0) goto err_xml;
rc = xmlTextWriterWriteAttribute(writer,
- BAD_CAST "ovf:volume-type", BAD_CAST "Preallocated");
+ BAD_CAST "ovf:volume-type", BAD_CAST vol_type);
if (rc < 0) goto err_xml;
rc = xmlTextWriterWriteAttribute(writer,
BAD_CAST "ovf:disk-interface", BAD_CAST "VirtIO");
@@ -1896,12 +1950,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);
+ uint64_t 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 +1977,8 @@ 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");
+ char const *fmt = qcow_size ? "COW" : "RAW";
+ fprintf(fp, "FORMAT=%s\n", fmt);
fprintf(fp, "IMAGE=%s\n", idp->image);
fprintf(fp, "DISKTYPE=1\n");
fprintf(fp, "PUUID=%s\n", NULID);
@@ -1935,7 +1995,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);
--
1.7.8
More information about the iwhd-devel
mailing list