[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[libvirt] [PATCH] Support kvm-img or qemu-img dynamically



This patch adds a new function virFindFileInPath() and uses it to find
where a binary lives in the PATH environment variable. Using this, we
can dynamically find where utility functions exist (and if they even
exists). So such we remove the build-time check for qemu-img and make it
dynamic for kvm-img and qemu-img. Several distros uses kvm-img over
qemu-img when installing KVM. kvm-img also includes several patches
which Red Hat is trying to upstream with QEMU so this patch supports
those features which are commented out in libvirt when using kvm-img

Signed-off-by: Doug Goldstein <cardoe gentoo org>
---
 configure.in             |   15 ---------
 src/libvirt_private.syms |    1 +
 src/storage_backend_fs.c |   74 ++++++++++++++++++++++++++++++++-------------
 src/util.c               |   28 +++++++++++++++++
 src/util.h               |    2 +
 5 files changed, 83 insertions(+), 37 deletions(-)
diff --git a/configure.in b/configure.in
index 5c0575c..552c761 100644
--- a/configure.in
+++ b/configure.in
@@ -889,21 +889,6 @@ if test "$with_storage_fs" = "yes"; then
     [Location or name of the showmount program])
 fi
 
-AC_PATH_PROG([QEMU_IMG], [qemu-img], [], [$PATH:/sbin:/usr/sbin:/bin:/usr/bin])
-if test -n "$QEMU_IMG" ; then
-  AC_DEFINE_UNQUOTED([HAVE_QEMU_IMG], 1, [whether qemu-img is available for non-raw files])
-  AC_DEFINE_UNQUOTED([QEMU_IMG],["$QEMU_IMG"],
-      [Location or name of the qemu-img program])
-fi
-
-AC_PATH_PROG([QCOW_CREATE], [qcow-create], [], [$PATH:/sbin:/usr/sbin:/bin:/usr/bin])
-if test -n "$QCOW_CREATE" ; then
-  AC_DEFINE_UNQUOTED([HAVE_QCOW_CREATE], 1, [whether qcow-create is available for non-raw files])
-  AC_DEFINE_UNQUOTED([QCOW_CREATE],["$QCOW_CREATE"],
-      [Location or name of the qcow-create program])
-fi
-
-
 if test "$with_storage_lvm" = "yes" -o "$with_storage_lvm" = "check"; then
   AC_PATH_PROG([PVCREATE], [pvcreate], [], [$PATH:/sbin:/usr/sbin])
   AC_PATH_PROG([VGCREATE], [vgcreate], [], [$PATH:/sbin:/usr/sbin])
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index b39216f..0c55684 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -330,6 +330,7 @@ virFormatMacAddr;
 virGetHostname;
 virParseMacAddr;
 virFileDeletePid;
+virFindFileInPath;
 virFileExists;
 virFileHasSuffix;
 virFileLinkPointsTo;
diff --git a/src/storage_backend_fs.c b/src/storage_backend_fs.c
index be6d011..ea5de7f 100644
--- a/src/storage_backend_fs.c
+++ b/src/storage_backend_fs.c
@@ -1183,11 +1183,12 @@ static int createFileDir(virConnectPtr conn,
     return 0;
 }
 
-#if HAVE_QEMU_IMG
 static int createQemuImg(virConnectPtr conn,
                          virStorageVolDefPtr vol,
                          virStorageVolDefPtr inputvol) {
     char size[100];
+    char *create_tool;
+    short use_kvmimg;
 
     const char *type = virStorageVolFormatFileSystemTypeToString(vol->target.format);
     const char *backingType = vol->backingStore.path ?
@@ -1203,24 +1204,27 @@ static int createQemuImg(virConnectPtr conn,
 
     const char **imgargv;
     const char *imgargvnormal[] = {
-        QEMU_IMG, "create",
+        NULL, "create",
         "-f", type,
         vol->target.path,
         size,
         NULL,
     };
-    /* XXX including "backingType" here too, once QEMU accepts
-     * the patches to specify it. It'll probably be -F backingType */
+    /* Extra NULL fields are for including "backingType" when using
+     * kvm-img. It's -F backingType
+     */
     const char *imgargvbacking[] = {
-        QEMU_IMG, "create",
+        NULL, "create",
         "-f", type,
         "-b", vol->backingStore.path,
         vol->target.path,
         size,
         NULL,
+        NULL,
+        NULL
     };
     const char *convargv[] = {
-        QEMU_IMG, "convert",
+        NULL, "convert",
         "-f", inputType,
         "-O", type,
         inputPath,
@@ -1228,14 +1232,6 @@ static int createQemuImg(virConnectPtr conn,
         NULL,
     };
 
-    if (inputvol) {
-        imgargv = convargv;
-    } else if (vol->backingStore.path) {
-        imgargv = imgargvbacking;
-    } else {
-        imgargv = imgargvnormal;
-    }
-
     if (type == NULL) {
         virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
                               _("unknown storage vol type %d"),
@@ -1277,17 +1273,45 @@ static int createQemuImg(virConnectPtr conn,
         }
     }
 
+    if ((create_tool = virFindFileInPath("kvm-img")) != NULL)
+    	use_kvmimg = 1;
+    else if ((create_tool = virFindFileInPath("qemu-img")) != NULL)
+        use_kvmimg = 0;
+    else
+        virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
+                              _("unable to find kvm-img or qemu-img"));
+
+    if (inputvol) {
+        convargv[0] = create_tool;
+        imgargv = convargv;
+    } else if (vol->backingStore.path) {
+        imgargvbacking[0] = create_tool;
+        if (use_kvmimg) {
+            imgargvbacking[6] = "-F";
+            imgargvbacking[7] = backingType;
+            imgargvbacking[8] = vol->target.path;
+            imgargvbacking[9] = size;
+        }
+        imgargv = imgargvbacking;
+    } else {
+        imgargvnormal[0] = create_tool;
+        imgargv = imgargvnormal;
+    }
+
+
     /* Size in KB */
     snprintf(size, sizeof(size), "%llu", vol->capacity/1024);
 
     if (virRun(conn, imgargv, NULL) < 0) {
+        VIR_FREE(imgargv[0]);
         return -1;
     }
 
+    VIR_FREE(imgargv[0]);
+
     return 0;
 }
 
-#elif HAVE_QCOW_CREATE
 /*
  * Xen removed the fully-functional qemu-img, and replaced it
  * with a partially functional qcow-create. Go figure ??!?
@@ -1321,18 +1345,20 @@ static int createQemuCreate(virConnectPtr conn,
     /* Size in MB - yes different units to qemu-img :-( */
     snprintf(size, sizeof(size), "%llu", vol->capacity/1024/1024);
 
-    imgargv[0] = QCOW_CREATE;
+    imgargv[0] = virFindFileInPath("qcow-create");
     imgargv[1] = size;
     imgargv[2] = vol->target.path;
     imgargv[3] = NULL;
 
     if (virRun(conn, imgargv, NULL) < 0) {
+        VIR_FREE(imgargv[0]);
         return -1;
     }
 
+    VIR_FREE(imgargv[0]);
+
     return 0;
 }
-#endif /* HAVE_QEMU_IMG, elif HAVE_QCOW_CREATE */
 
 static int
 _virStorageBackendFileSystemVolBuild(virConnectPtr conn,
@@ -1341,6 +1367,7 @@ _virStorageBackendFileSystemVolBuild(virConnectPtr conn,
 {
     int fd;
     createFile create_func;
+    char *create_tool;
 
     if (vol->target.format == VIR_STORAGE_VOL_FILE_RAW &&
         (!inputvol ||
@@ -1353,17 +1380,20 @@ _virStorageBackendFileSystemVolBuild(virConnectPtr conn,
         create_func = createRaw;
     } else if (vol->target.format == VIR_STORAGE_VOL_FILE_DIR) {
         create_func = createFileDir;
-    } else {
-#if HAVE_QEMU_IMG
+    } else if ((create_tool = virFindFileInPath("kvm-img")) != NULL) {
+        VIR_FREE(create_tool);
+        create_func = createQemuImg;
+    } else if ((create_tool = virFindFileInPath("qemu-img")) != NULL) {
+        VIR_FREE(create_tool);
         create_func = createQemuImg;
-#elif HAVE_QCOW_CREATE
+    } else if ((create_tool = virFindFileInPath("qcow-create")) != NULL) {
+        VIR_FREE(create_tool);
         create_func = createQemuCreate;
-#else
+    } else {
         virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
                               "%s", _("creation of non-raw images "
                                       "is not supported without qemu-img"));
         return -1;
-#endif
     }
 
     if (create_func(conn, vol, inputvol) < 0)
diff --git a/src/util.c b/src/util.c
index 3a8c105..664fb0f 100644
--- a/src/util.c
+++ b/src/util.c
@@ -1073,7 +1073,35 @@ int virFileResolveLink(const char *linkpath,
 #endif
 }
 
+/*
+ * Finds a requested file in the PATH env. e.g.:
+ * "kvm-img" will return "/usr/bin/kvm-img"
+ *
+ * You must free the result
+ */
+char *virFindFileInPath(const char *file)
+{
+    char pathenv[PATH_MAX];
+    char *penv = &pathenv; /* this is for glibc 2.10 strsep chnages */
+    char *pathseg;
+    char fullpath[PATH_MAX];
+
+    /* copy PATH env so we can tweak it */
+    strncpy(pathenv, getenv("PATH"), PATH_MAX);
+    pathenv[PATH_MAX - 1] = '\0';
+
 
+    /* for each path segment, append the file to search for and test for
+     * it. return it if found.
+     */
+    while ((pathseg = strsep(&penv, ":")) != NULL) {
+       snprintf(fullpath, PATH_MAX, "%s/%s", pathseg, file);
+       if (virFileExists(fullpath))
+           return strdup(fullpath);
+    }
+
+    return NULL;
+}
 int virFileExists(const char *path)
 {
     struct stat st;
diff --git a/src/util.h b/src/util.h
index 61e1eb5..e6e8010 100644
--- a/src/util.h
+++ b/src/util.h
@@ -101,6 +101,8 @@ int virFileLinkPointsTo(const char *checkLink,
 int virFileResolveLink(const char *linkpath,
                        char **resultpath);
 
+char *virFindFileInPath(const char *file);
+
 int virFileExists(const char *path);
 
 int virFileMakePath(const char *path);

[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]