diff --git a/AUTHORS b/AUTHORS index dcb6ea58d7..e6f1a9ecdc 100644 --- a/AUTHORS +++ b/AUTHORS @@ -71,6 +71,7 @@ Patches have also been contributed by: Soren Hansen Laine Stump Abel Míguez Rodríguez + Doug Goldstein [....send patches to get your name here....] diff --git a/ChangeLog b/ChangeLog index fe576cc618..f4e0d8158f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +Thu Jun 11 15:14:37 CEST 2009 Daniel Veillard + + * configure.in src/libvirt_private.syms src/storage_backend_fs.c + src/util.c src/util.h: find and use kvm-img, qemu-img or qcow-create + dynamically at runtime, patch by Doug Goldstein + * AUTHORS: add Doug Goldstein + Tue Jun 9 15:21:17 CEST 2009 Daniel Veillard * docs/formatdomain.html docs/formatdomain.html.in: typo fix diff --git a/configure.in b/configure.in index 5c0575c873..552c76157e 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 b39216f2e4..0c55684150 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 be6d01193c..ac7c4240d4 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,47 @@ 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")); + return -1; + } + + 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 +1347,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 +1369,7 @@ _virStorageBackendFileSystemVolBuild(virConnectPtr conn, { int fd; createFile create_func; + char *create_tool; if (vol->target.format == VIR_STORAGE_VOL_FILE_RAW && (!inputvol || @@ -1353,17 +1382,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; -#elif HAVE_QCOW_CREATE + } else if ((create_tool = virFindFileInPath("qemu-img")) != NULL) { + VIR_FREE(create_tool); + create_func = createQemuImg; + } 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 3a8c105c76..664fb0f7cf 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 61e1eb5198..e6e8010355 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);