int qemuCapsProbeCPUModels(const char *qemu, virBitmapPtr qemuCaps, const char *arch, unsigned int *count, const char ***cpus) { char *output = NULL; int ret = -1; qemuCapsParseCPUModels parse; virCommandPtr cmd; if (count) *count = 0; if (cpus) *cpus = NULL; if (STREQ(arch, "i686") || STREQ(arch, "x86_64")) parse = qemuCapsParseX86Models; else if (STREQ(arch, "ppc64")) parse = qemuCapsParsePPCModels; else { VIR_DEBUG("don't know how to parse %s CPU models", arch); return 0; } cmd = virCommandNewArgList(qemu, "-cpu", "?", NULL); if (qemuCapsGet(qemuCaps, QEMU_CAPS_NODEFCONFIG)) virCommandAddArg(cmd, "-nodefconfig"); virCommandAddEnvPassCommon(cmd); virCommandSetOutputBuffer(cmd, &output); virCommandClearCaps(cmd); if (virCommandRun(cmd, NULL) < 0) goto cleanup; if (parse(output, count, cpus) < 0) goto cleanup; ret = 0; cleanup: VIR_FREE(output); virCommandFree(cmd); return ret; }
char * virISCSIGetSession(const char *devpath, bool probe) { /* * # iscsiadm --mode session * tcp: [1] 192.168.122.170:3260,1 demo-tgt-b * tcp: [2] 192.168.122.170:3260,1 demo-tgt-a * * Pull out 2nd and 4th fields */ const char *regexes[] = { "^tcp:\\s+\\[(\\S+)\\]\\s+\\S+\\s+(\\S+).*$" }; int vars[] = { 2, }; struct virISCSISessionData cbdata = { .session = NULL, .devpath = devpath, }; char *error = NULL; int exitstatus = 0; virCommandPtr cmd = virCommandNewArgList(ISCSIADM, "--mode", "session", NULL); virCommandSetErrorBuffer(cmd, &error); if (virCommandRunRegex(cmd, 1, regexes, vars, virISCSIExtractSession, &cbdata, NULL, &exitstatus) < 0) goto cleanup; if (cbdata.session == NULL && !probe) virReportError(VIR_ERR_INTERNAL_ERROR, _("cannot find iscsiadm session: %s"), NULLSTR(error)); cleanup: VIR_FREE(error); virCommandFree(cmd); return cbdata.session; }
static int virNetSocketForkDaemon(const char *binary) { int ret; virCommandPtr cmd = virCommandNewArgList(binary, "--timeout=30", NULL); virCommandAddEnvPassCommon(cmd); virCommandAddEnvPass(cmd, "XDG_CACHE_HOME"); virCommandAddEnvPass(cmd, "XDG_CONFIG_HOME"); virCommandAddEnvPass(cmd, "XDG_RUNTIME_DIR"); virCommandClearCaps(cmd); virCommandDaemonize(cmd); ret = virCommandRun(cmd, NULL); virCommandFree(cmd); return ret; }
/** * @conn connection to report errors against * @pool storage pool to unmount * * Ensure that a FS storage pool is not mounted on its target location. * If already unmounted, this is a no-op * * Returns 0 if successfully unmounted, -1 on error */ static int virStorageBackendFileSystemUnmount(virStoragePoolObjPtr pool) { virCommandPtr cmd = NULL; int ret = -1; int rc; if (pool->def->type == VIR_STORAGE_POOL_NETFS) { if (pool->def->source.nhost != 1) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("Expected exactly 1 host for the storage pool")); return -1; } if (pool->def->source.hosts[0].name == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("missing source host")); return -1; } if (pool->def->source.dir == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("missing source dir")); return -1; } } else { if (pool->def->source.ndevice != 1) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("missing source device")); return -1; } } /* Short-circuit if already unmounted */ if ((rc = virStorageBackendFileSystemIsMounted(pool)) != 1) return rc; cmd = virCommandNewArgList(UMOUNT, pool->def->target.path, NULL); if (virCommandRun(cmd, NULL) < 0) goto cleanup; ret = 0; cleanup: virCommandFree(cmd); return ret; }
static int virStorageBackendSheepdogRefreshAllVol(virConnectPtr conn ATTRIBUTE_UNUSED, virStoragePoolObjPtr pool) { int ret = -1; char *output = NULL; char **lines = NULL; char **cells = NULL; size_t i; virCommandPtr cmd = virCommandNewArgList(COLLIE, "vdi", "list", "-r", NULL); virStorageBackendSheepdogAddHostArg(cmd, pool); virCommandSetOutputBuffer(cmd, &output); if (virCommandRun(cmd, NULL) < 0) goto cleanup; lines = virStringSplit(output, "\n", 0); if (lines == NULL) goto cleanup; for (i = 0; lines[i]; i++) { const char *line = lines[i]; if (line == NULL) break; cells = virStringSplit(line, " ", 0); if (cells != NULL && virStringListLength(cells) > 2) { if (virStorageBackendSheepdogAddVolume(conn, pool, cells[1]) < 0) goto cleanup; } virStringFreeList(cells); cells = NULL; } ret = 0; cleanup: virCommandFree(cmd); virStringFreeList(lines); virStringFreeList(cells); VIR_FREE(output); return ret; }
static char * virStorageBackendISCSISession(virStoragePoolObjPtr pool, int probe) { /* * # iscsiadm --mode session * tcp: [1] 192.168.122.170:3260,1 demo-tgt-b * tcp: [2] 192.168.122.170:3260,1 demo-tgt-a * * Pull out 2nd and 4th fields */ const char *regexes[] = { "^tcp:\\s+\\[(\\S+)\\]\\s+\\S+\\s+(\\S+)\\s*$" }; int vars[] = { 2, }; char *session = NULL; virCommandPtr cmd = virCommandNewArgList(ISCSIADM, "--mode", "session", NULL); /* Note that we ignore the exitstatus. Older versions of iscsiadm tools * returned an exit status of > 0, even if they succeeded. We will just * rely on whether session got filled in properly. */ if (virStorageBackendRunProgRegex(pool, cmd, 1, regexes, vars, virStorageBackendISCSIExtractSession, &session, NULL) < 0) goto cleanup; if (session == NULL && !probe) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("cannot find session")); goto cleanup; } cleanup: virCommandFree(cmd); return session; }
/* virPolkitAgentCreate: * * Allocate and setup a polkit agent * * Returns a virCommandPtr on success and NULL on failure */ virPolkitAgentPtr virPolkitAgentCreate(void) { virPolkitAgentPtr agent = NULL; int pipe_fd[2] = {-1, -1}; struct pollfd pollfd; int outfd = STDOUT_FILENO; int errfd = STDERR_FILENO; if (!isatty(STDIN_FILENO)) goto error; if (pipe2(pipe_fd, 0) < 0) goto error; if (VIR_ALLOC(agent) < 0) goto error; agent->cmd = virCommandNewArgList(PKTTYAGENT, "--process", NULL); virCommandAddArgFormat(agent->cmd, "%lld", (long long int) getpid()); virCommandAddArg(agent->cmd, "--notify-fd"); virCommandAddArgFormat(agent->cmd, "%d", pipe_fd[1]); virCommandAddArg(agent->cmd, "--fallback"); virCommandSetInputFD(agent->cmd, STDIN_FILENO); virCommandSetOutputFD(agent->cmd, &outfd); virCommandSetErrorFD(agent->cmd, &errfd); virCommandPassFD(agent->cmd, pipe_fd[1], VIR_COMMAND_PASS_FD_CLOSE_PARENT); if (virCommandRunAsync(agent->cmd, NULL) < 0) goto error; pollfd.fd = pipe_fd[0]; pollfd.events = POLLHUP; if (poll(&pollfd, 1, -1) < 0) goto error; return agent; error: VIR_FORCE_CLOSE(pipe_fd[0]); VIR_FORCE_CLOSE(pipe_fd[1]); virPolkitAgentDestroy(agent); return NULL; }
static int virConnectAuthGainPolkit(const char *privilege) { virCommandPtr cmd; int ret = -1; if (geteuid() == 0) return 0; cmd = virCommandNewArgList(POLKIT_AUTH, "--obtain", privilege, NULL); if (virCommandRun(cmd, NULL) < 0) goto cleanup; ret = 0; cleanup: virCommandFree(cmd); return ret; }
static int virStorageBackendSheepdogResizeVol(virConnectPtr conn ATTRIBUTE_UNUSED, virStoragePoolObjPtr pool, virStorageVolDefPtr vol, unsigned long long capacity, unsigned int flags) { virCheckFlags(0, -1); virCommandPtr cmd = virCommandNewArgList(COLLIE, "vdi", "resize", vol->name, NULL); virCommandAddArgFormat(cmd, "%llu", capacity); virStorageBackendSheepdogAddHostArg(cmd, pool); int ret = virCommandRun(cmd, NULL); virCommandFree(cmd); return ret; }
static int virStorageBackendSheepdogRefreshPool(virConnectPtr conn ATTRIBUTE_UNUSED, virStoragePoolObjPtr pool) { int ret; char *output = NULL; virCommandPtr cmd; cmd = virCommandNewArgList(COLLIE, "node", "info", "-r", NULL); virStorageBackendSheepdogAddHostArg(cmd, pool); virCommandSetOutputBuffer(cmd, &output); ret = virCommandRun(cmd, NULL); if (ret == 0) ret = virStorageBackendSheepdogParseNodeInfo(pool->def, output); virCommandFree(cmd); VIR_FREE(output); return ret; }
static int openvzListDomains(virConnectPtr conn ATTRIBUTE_UNUSED, int *ids, int nids) { int got = 0; int veid; int outfd = -1; int rc = -1; int ret; char buf[32]; char *endptr; virCommandPtr cmd = virCommandNewArgList(VZLIST, "-ovpsid", "-H" , NULL); virCommandSetOutputFD(cmd, &outfd); if (virCommandRunAsync(cmd, NULL) < 0) goto cleanup; while (got < nids) { ret = openvz_readline(outfd, buf, 32); if (!ret) break; if (virStrToLong_i(buf, &endptr, 10, &veid) < 0) { openvzError(VIR_ERR_INTERNAL_ERROR, _("Could not parse VPS ID %s"), buf); continue; } ids[got] = veid; got ++; } if (virCommandWait(cmd, NULL) < 0) goto cleanup; if (VIR_CLOSE(outfd) < 0) { virReportSystemError(errno, "%s", _("failed to close file")); goto cleanup; } rc = got; cleanup: VIR_FORCE_CLOSE(outfd); virCommandFree(cmd); return rc; }
/* * @sourceList: Pointer to a storage pool source list * * Use the pvs command to fill the list of pv_name and vg_name associated * into the passed sourceList. * * Returns 0 if successful, -1 and sets error on failure */ static int virStorageBackendLogicalGetPoolSources(virStoragePoolSourceListPtr sourceList) { /* * # pvs --noheadings -o pv_name,vg_name * /dev/sdb * /dev/sdc VolGroup00 */ const char *regexes[] = { "^\\s*(\\S+)\\s+(\\S+)\\s*$" }; int vars[] = { 2 }; virCommandPtr cmd; int ret = -1; /* * NOTE: ignoring errors here; this is just to "touch" any logical volumes * that might be hanging around, so if this fails for some reason, the * worst that happens is that scanning doesn't pick everything up */ cmd = virCommandNew(VGSCAN); if (virCommandRun(cmd, NULL) < 0) VIR_WARN("Failure when running vgscan to refresh physical volumes"); virCommandFree(cmd); cmd = virCommandNewArgList(PVS, "--noheadings", "-o", "pv_name,vg_name", NULL); if (virCommandRunRegex(cmd, 1, regexes, vars, virStorageBackendLogicalFindPoolSourcesFunc, sourceList, "pvs") < 0) goto cleanup; ret = 0; cleanup: virCommandFree(cmd); return ret; }
static char * virStorageBackendISCSISession(virStoragePoolObjPtr pool, bool probe) { /* * # iscsiadm --mode session * tcp: [1] 192.168.122.170:3260,1 demo-tgt-b * tcp: [2] 192.168.122.170:3260,1 demo-tgt-a * * Pull out 2nd and 4th fields */ const char *regexes[] = { "^tcp:\\s+\\[(\\S+)\\]\\s+\\S+\\s+(\\S+).*$" }; int vars[] = { 2, }; char *session = NULL; virCommandPtr cmd = virCommandNewArgList(ISCSIADM, "--mode", "session", NULL); if (virStorageBackendRunProgRegex(pool, cmd, 1, regexes, vars, virStorageBackendISCSIExtractSession, &session, NULL) < 0) goto cleanup; if (session == NULL && !probe) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("cannot find session")); goto cleanup; } cleanup: virCommandFree(cmd); return session; }
static int openvzGetVEStatus(virDomainObjPtr vm, int *status, int *reason) { virCommandPtr cmd; char *outbuf; char *line; int state; int ret = -1; cmd = virCommandNewArgList(VZLIST, vm->def->name, "-ostatus", "-H", NULL); virCommandSetOutputBuffer(cmd, &outbuf); if (virCommandRun(cmd, NULL) < 0) goto cleanup; if ((line = strchr(outbuf, '\n')) == NULL) { openvzError(VIR_ERR_INTERNAL_ERROR, "%s", _("Failed to parse vzlist output")); goto cleanup; } *line++ = '\0'; state = virDomainObjGetState(vm, reason); if (STREQ(outbuf, "running")) { /* There is no way to detect whether a domain is paused or not * with vzlist */ if (state == VIR_DOMAIN_PAUSED) *status = state; else *status = VIR_DOMAIN_RUNNING; } else { *status = VIR_DOMAIN_SHUTOFF; } ret = 0; cleanup: virCommandFree(cmd); VIR_FREE(outbuf); return ret; }
/* * load (add) a profile. Will create one if necessary */ static int load_profile(virSecurityManagerPtr mgr, const char *profile, virDomainDefPtr def, const char *fn, bool append) { int rc = -1; bool create = true; char *xml = NULL; virCommandPtr cmd = NULL; const char *probe = virSecurityManagerGetAllowDiskFormatProbing(mgr) ? "1" : "0"; xml = virDomainDefFormat(def, VIR_DOMAIN_XML_SECURE); if (!xml) goto cleanup; if (profile_status_file(profile) >= 0) create = false; cmd = virCommandNewArgList(VIRT_AA_HELPER, "-p", probe, create ? "-c" : "-r", "-u", profile, NULL); if (!create && fn) { if (append) { virCommandAddArgList(cmd, "-F", fn, NULL); } else { virCommandAddArgList(cmd, "-f", fn, NULL); } } virCommandSetInputBuffer(cmd, xml); rc = virCommandRun(cmd, NULL); cleanup: VIR_FREE(xml); virCommandFree(cmd); return rc; }
char * virNumaGetAutoPlacementAdvice(unsigned short vcpus, unsigned long long balloon) { virCommandPtr cmd = NULL; char *output = NULL; cmd = virCommandNewArgList(NUMAD, "-w", NULL); virCommandAddArgFormat(cmd, "%d:%llu", vcpus, VIR_DIV_UP(balloon, 1024)); virCommandSetOutputBuffer(cmd, &output); if (virCommandRun(cmd, NULL) < 0) virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Failed to query numad for the " "advisory nodeset")); virCommandFree(cmd); return output; }
/** * virNodeSuspendSetNodeWakeup: * @alarmTime: time in seconds from now, at which the RTC alarm has to be set. * * Set up the RTC alarm to the specified time. * Return 0 on success, -1 on failure. */ static int virNodeSuspendSetNodeWakeup(unsigned long long alarmTime) { virCommandPtr setAlarmCmd; int ret = -1; if (alarmTime <= MIN_TIME_REQ_FOR_SUSPEND) { virNodeSuspendError(VIR_ERR_INVALID_ARG, "%s", _("Suspend duration is too short")); return -1; } setAlarmCmd = virCommandNewArgList("rtcwake", "-m", "no", "-s", NULL); virCommandAddArgFormat(setAlarmCmd, "%lld", alarmTime); if (virCommandRun(setAlarmCmd, NULL) < 0) goto cleanup; ret = 0; cleanup: virCommandFree(setAlarmCmd); return ret; }
static int virStorageBackendZFSDeletePool(virConnectPtr conn ATTRIBUTE_UNUSED, virStoragePoolObjPtr pool, unsigned int flags) { virCommandPtr cmd = NULL; int ret = -1; virCheckFlags(0, -1); cmd = virCommandNewArgList(ZPOOL, "destroy", pool->def->source.name, NULL); if (virCommandRun(cmd, NULL) < 0) goto cleanup; ret = 0; cleanup: virCommandFree(cmd); return ret; }
static int virStorageBackendFileSystemNetFindNFSPoolSources(virNetfsDiscoverState *state) { int ret = -1; /* * # showmount --no-headers -e HOSTNAME * /tmp * * /A dir demo1.foo.bar,demo2.foo.bar * * Extract directory name (including possible interior spaces ...). */ const char *regexes[] = { "^(/.*\\S) +\\S+$" }; int vars[] = { 1 }; virCommandPtr cmd = NULL; cmd = virCommandNewArgList(SHOWMOUNT, "--no-headers", "--exports", state->host, NULL); if (virCommandRunRegex(cmd, 1, regexes, vars, virStorageBackendFileSystemNetFindPoolSourcesFunc, state, NULL) < 0) goto cleanup; ret = 0; cleanup: virCommandFree(cmd); return ret; }
static int virStorageBackendZFSDeleteVol(virConnectPtr conn ATTRIBUTE_UNUSED, virStoragePoolObjPtr pool, virStorageVolDefPtr vol, unsigned int flags) { int ret = -1; virCommandPtr destroy_cmd = virCommandNewArgList(ZFS, "destroy", NULL); virCheckFlags(0, -1); virCommandAddArgFormat(destroy_cmd, "%s/%s", pool->def->source.name, vol->name); if (virCommandRun(destroy_cmd, NULL) < 0) goto cleanup; ret = 0; cleanup: virCommandFree(destroy_cmd); return ret; }
int qemuCapsProbeMachineTypes(const char *binary, virCapsGuestMachinePtr **machines, int *nmachines) { char *output; int ret = -1; virCommandPtr cmd; int status; /* Make sure the binary we are about to try exec'ing exists. * Technically we could catch the exec() failure, but that's * in a sub-process so it's hard to feed back a useful error. */ if (!virFileIsExecutable(binary)) { virReportSystemError(errno, _("Cannot find QEMU binary %s"), binary); return -1; } cmd = virCommandNewArgList(binary, "-M", "?", NULL); virCommandAddEnvPassCommon(cmd); virCommandSetOutputBuffer(cmd, &output); virCommandClearCaps(cmd); /* Ignore failure from older qemu that did not understand '-M ?'. */ if (virCommandRun(cmd, &status) < 0) goto cleanup; if (qemuCapsParseMachineTypesStr(output, machines, nmachines) < 0) goto cleanup; ret = 0; cleanup: VIR_FREE(output); virCommandFree(cmd); return ret; }
static int openvzExtractVersionInfo(const char *cmdstr, int *retversion) { int ret = -1; unsigned long version; char *help = NULL; char *tmp; virCommandPtr cmd = virCommandNewArgList(cmdstr, "--help", NULL); if (retversion) *retversion = 0; virCommandAddEnvString(cmd, "LC_ALL=C"); virCommandSetOutputBuffer(cmd, &help); if (virCommandRun(cmd, NULL) < 0) goto cleanup; tmp = help; /* expected format: vzctl version <major>.<minor>.<micro> */ if ((tmp = STRSKIP(tmp, "vzctl version ")) == NULL) goto cleanup; if (virParseVersionString(tmp, &version, true) < 0) goto cleanup; if (retversion) *retversion = version; ret = 0; cleanup: virCommandFree(cmd); VIR_FREE(help); return ret; }
static int virStorageBackendSheepdogRefreshVol(virConnectPtr conn ATTRIBUTE_UNUSED, virStoragePoolObjPtr pool, virStorageVolDefPtr vol) { int ret; char *output = NULL; virCommandPtr cmd = virCommandNewArgList(COLLIE, "vdi", "list", vol->name, "-r", NULL); virStorageBackendSheepdogAddHostArg(cmd, pool); virCommandSetOutputBuffer(cmd, &output); ret = virCommandRun(cmd, NULL); if (ret < 0) goto cleanup; if ((ret = virStorageBackendSheepdogParseVdiList(vol, output)) < 0) goto cleanup; vol->type = VIR_STORAGE_VOL_NETWORK; VIR_FREE(vol->key); if (virAsprintf(&vol->key, "%s/%s", pool->def->source.name, vol->name) == -1) { virReportOOMError(); goto cleanup; } VIR_FREE(vol->target.path); if (!(vol->target.path = strdup(vol->name))) { virReportOOMError(); goto cleanup; } cleanup: virCommandFree(cmd); return ret; }
int vmwareExtractVersion(struct vmware_driver *driver) { unsigned long version = 0; char *tmp; int ret = -1; virCommandPtr cmd; char * outbuf = NULL; const char * bin = (driver->type == TYPE_PLAYER) ? "vmplayer" : "vmware"; const char * pattern = (driver->type == TYPE_PLAYER) ? "VMware Player " : "VMware Workstation "; cmd = virCommandNewArgList(bin, "-v", NULL); virCommandSetOutputBuffer(cmd, &outbuf); if (virCommandRun(cmd, NULL) < 0) goto cleanup; if ((tmp = STRSKIP(outbuf, pattern)) == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, _("failed to parse %s version"), bin); goto cleanup; } if (virParseVersionString(tmp, &version, false) < 0) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("version parsing error")); goto cleanup; } driver->version = version; ret = 0; cleanup: virCommandFree(cmd); VIR_FREE(outbuf); return ret; }
static int virStorageBackendVzPoolStart(virStoragePoolObjPtr pool) { virStoragePoolDefPtr def = virStoragePoolObjGetDef(pool); VIR_AUTOFREE(char *) grp_name = NULL; VIR_AUTOFREE(char *) usr_name = NULL; VIR_AUTOFREE(char *) mode = NULL; VIR_AUTOPTR(virCommand) cmd = NULL; /* Check the permissions */ if (def->target.perms.mode == (mode_t)-1) def->target.perms.mode = VIR_STORAGE_DEFAULT_POOL_PERM_MODE; if (def->target.perms.uid == (uid_t)-1) def->target.perms.uid = geteuid(); if (def->target.perms.gid == (gid_t)-1) def->target.perms.gid = getegid(); /* Convert ids to names because vstorage uses names */ if (!(grp_name = virGetGroupName(def->target.perms.gid))) return -1; if (!(usr_name = virGetUserName(def->target.perms.uid))) return -1; if (virAsprintf(&mode, "%o", def->target.perms.mode) < 0) return -1; cmd = virCommandNewArgList(VSTORAGE_MOUNT, "-c", def->source.name, def->target.path, "-m", mode, "-g", grp_name, "-u", usr_name, NULL); return virCommandRun(cmd, NULL); }
static void testCleanupImages(void) { virCommandPtr cmd; VIR_FREE(qemuimg); VIR_FREE(absraw); VIR_FREE(canonraw); VIR_FREE(absqcow2); VIR_FREE(canonqcow2); VIR_FREE(abswrap); VIR_FREE(absqed); VIR_FREE(abslink2); if (chdir(abs_builddir) < 0) { fprintf(stderr, "unable to return to correct directory, refusing to " "clean up %s\n", datadir); return; } cmd = virCommandNewArgList("rm", "-rf", datadir, NULL); ignore_value(virCommandRun(cmd, NULL)); virCommandFree(cmd); }
static char * virStorageBackendSCSISerial(const char *dev) { char *serial = NULL; #ifdef HAVE_UDEV virCommandPtr cmd = virCommandNewArgList( "/lib/udev/scsi_id", "--replace-whitespace", "--whitelisted", "--device", dev, NULL ); /* Run the program and capture its output */ virCommandSetOutputBuffer(cmd, &serial); if (virCommandRun(cmd, NULL) < 0) goto cleanup; #endif if (serial && STRNEQ(serial, "")) { char *nl = strchr(serial, '\n'); if (nl) *nl = '\0'; } else { VIR_FREE(serial); if (!(serial = strdup(dev))) virReportOOMError(); } #ifdef HAVE_UDEV cleanup: virCommandFree(cmd); #endif return serial; }
static int virStorageBackendSheepdogBuildVol(virConnectPtr conn, virStoragePoolObjPtr pool, virStorageVolDefPtr vol, unsigned int flags) { int ret = -1; virCheckFlags(0, -1); virCommandPtr cmd = virCommandNewArgList(COLLIE, "vdi", "create", vol->name, NULL); virCommandAddArgFormat(cmd, "%llu", vol->target.capacity); virStorageBackendSheepdogAddHostArg(cmd, pool); if (virCommandRun(cmd, NULL) < 0) goto cleanup; if (virStorageBackendSheepdogRefreshVol(conn, pool, vol) < 0) goto cleanup; ret = 0; cleanup: virCommandFree(cmd); return ret; }
static int testPrepImages(void) { int ret = EXIT_FAILURE; virCommandPtr cmd = NULL; qemuimg = virFindFileInPath("kvm-img"); if (!qemuimg) qemuimg = virFindFileInPath("qemu-img"); if (!qemuimg) goto skip; if (virAsprintf(&absraw, "%s/raw", datadir) < 0 || virAsprintf(&absqcow2, "%s/qcow2", datadir) < 0 || virAsprintf(&abswrap, "%s/wrap", datadir) < 0 || virAsprintf(&absqed, "%s/qed", datadir) < 0 || virAsprintf(&abslink2, "%s/sub/link2", datadir) < 0) { virReportOOMError(); goto cleanup; } if (virFileMakePath(datadir "/sub") < 0) { fprintf(stderr, "unable to create directory %s\n", datadir "/sub"); goto cleanup; } if (chdir(datadir) < 0) { fprintf(stderr, "unable to test relative backing chains\n"); goto cleanup; } /* I'm lazy enough to use a shell one-liner instead of open/write/close */ virCommandFree(cmd); cmd = virCommandNewArgList("sh", "-c", "printf %1024d 0 > raw", NULL); if (virCommandRun(cmd, NULL) < 0) { fprintf(stderr, "unable to create raw file\n"); goto cleanup; } if (!(canonraw = canonicalize_file_name(absraw))) { virReportOOMError(); goto cleanup; } /* Create a qcow2 wrapping relative raw; later on, we modify its * metadata to test other configurations */ virCommandFree(cmd); cmd = virCommandNewArgList(qemuimg, "create", "-f", "qcow2", "-obacking_file=raw,backing_fmt=raw", "qcow2", NULL); if (virCommandRun(cmd, NULL) < 0) goto skip; /* Make sure our later uses of 'qemu-img rebase' will work */ virCommandFree(cmd); cmd = virCommandNewArgList(qemuimg, "rebase", "-u", "-f", "qcow2", "-F", "raw", "-b", "raw", "qcow2", NULL); if (virCommandRun(cmd, NULL) < 0) goto skip; if (!(canonqcow2 = canonicalize_file_name(absqcow2))) { virReportOOMError(); goto cleanup; } /* Create a second qcow2 wrapping the first, to be sure that we * can correctly avoid insecure probing. */ virCommandFree(cmd); cmd = virCommandNewArgList(qemuimg, "create", "-f", "qcow2", NULL); virCommandAddArgFormat(cmd, "-obacking_file=%s,backing_fmt=qcow2", absqcow2); virCommandAddArg(cmd, "wrap"); if (virCommandRun(cmd, NULL) < 0) goto skip; /* Create a qed file. */ virCommandFree(cmd); cmd = virCommandNewArgList(qemuimg, "create", "-f", "qed", NULL); virCommandAddArgFormat(cmd, "-obacking_file=%s,backing_fmt=raw", absraw); virCommandAddArg(cmd, "qed"); if (virCommandRun(cmd, NULL) < 0) goto skip; /* Create some symlinks in a sub-directory. */ if (symlink("../qcow2", datadir "/sub/link1") < 0 || symlink("../wrap", datadir "/sub/link2") < 0) { fprintf(stderr, "unable to create symlink"); goto cleanup; } ret = 0; cleanup: virCommandFree(cmd); if (ret) testCleanupImages(); return ret; skip: fputs("qemu-img is too old; skipping this test\n", stderr); ret = EXIT_AM_SKIP; goto cleanup; }
static int mymain(void) { int ret; virCommandPtr cmd = NULL; /* Prep some files with qemu-img; if that is not found on PATH, or * if it lacks support for qcow2 and qed, skip this test. */ if ((ret = testPrepImages()) != 0) return ret; #define TEST_ONE_CHAIN(id, start, format, chain, flags) \ do { \ struct testChainData data = { \ start, format, chain, ARRAY_CARDINALITY(chain), flags, \ }; \ if (virtTestRun("Storage backing chain " id, 1, \ testStorageChain, &data) < 0) \ ret = -1; \ } while (0) #define TEST_CHAIN(id, relstart, absstart, format, chain1, flags1, \ chain2, flags2, chain3, flags3, chain4, flags4) \ do { \ TEST_ONE_CHAIN(#id "a", relstart, format, chain1, flags1); \ TEST_ONE_CHAIN(#id "b", relstart, format, chain2, flags2); \ TEST_ONE_CHAIN(#id "c", absstart, format, chain3, flags3); \ TEST_ONE_CHAIN(#id "d", absstart, format, chain4, flags4); \ } while (0) /* Expected details about files in chains */ const testFileData raw = { NULL, NULL, NULL, VIR_STORAGE_FILE_NONE, false, 0, false, }; const testFileData qcow2_relback_relstart = { canonraw, "raw", ".", VIR_STORAGE_FILE_RAW, true, 1024, false, }; const testFileData qcow2_relback_absstart = { canonraw, "raw", datadir, VIR_STORAGE_FILE_RAW, true, 1024, false, }; const testFileData qcow2_absback = { canonraw, absraw, datadir, VIR_STORAGE_FILE_RAW, true, 1024, false, }; const testFileData qcow2_as_probe = { canonraw, absraw, datadir, VIR_STORAGE_FILE_AUTO, true, 1024, false, }; const testFileData qcow2_bogus = { NULL, datadir "/bogus", datadir, VIR_STORAGE_FILE_NONE, false, 1024, false, }; const testFileData qcow2_protocol = { "nbd:example.org:6000", NULL, NULL, VIR_STORAGE_FILE_RAW, false, 1024, false, }; const testFileData wrap = { canonqcow2, absqcow2, datadir, VIR_STORAGE_FILE_QCOW2, true, 1024, false, }; const testFileData wrap_as_raw = { canonqcow2, absqcow2, datadir, VIR_STORAGE_FILE_RAW, true, 1024, false, }; const testFileData wrap_as_probe = { canonqcow2, absqcow2, datadir, VIR_STORAGE_FILE_AUTO, true, 1024, false, }; const testFileData qed = { canonraw, absraw, datadir, VIR_STORAGE_FILE_RAW, true, 1024, false, }; const testFileData link1_rel = { canonraw, "../raw", "sub/../sub/..", VIR_STORAGE_FILE_RAW, true, 1024, false, }; const testFileData link1_abs = { canonraw, "../raw", datadir "/sub/../sub/..", VIR_STORAGE_FILE_RAW, true, 1024, false, }; const testFileData link2_rel = { canonqcow2, "../sub/link1", "sub/../sub", VIR_STORAGE_FILE_QCOW2, true, 1024, false, }; const testFileData link2_abs = { canonqcow2, "../sub/link1", datadir "/sub/../sub", VIR_STORAGE_FILE_QCOW2, true, 1024, false, }; /* The actual tests, in several groups. */ /* Missing file */ const testFileData chain0[] = { }; TEST_ONE_CHAIN("0", "bogus", VIR_STORAGE_FILE_RAW, chain0, EXP_FAIL); /* Raw image, whether with right format or no specified format */ const testFileData chain1[] = { raw }; TEST_CHAIN(1, "raw", absraw, VIR_STORAGE_FILE_RAW, chain1, EXP_PASS, chain1, ALLOW_PROBE | EXP_PASS, chain1, EXP_PASS, chain1, ALLOW_PROBE | EXP_PASS); TEST_CHAIN(2, "raw", absraw, VIR_STORAGE_FILE_AUTO, chain1, EXP_PASS, chain1, ALLOW_PROBE | EXP_PASS, chain1, EXP_PASS, chain1, ALLOW_PROBE | EXP_PASS); /* Qcow2 file with relative raw backing, format provided */ const testFileData chain3a[] = { qcow2_relback_relstart, raw }; const testFileData chain3c[] = { qcow2_relback_absstart, raw }; const testFileData chain4a[] = { raw }; TEST_CHAIN(3, "qcow2", absqcow2, VIR_STORAGE_FILE_QCOW2, chain3a, EXP_PASS, chain3a, ALLOW_PROBE | EXP_PASS, chain3c, EXP_PASS, chain3c, ALLOW_PROBE | EXP_PASS); TEST_CHAIN(4, "qcow2", absqcow2, VIR_STORAGE_FILE_AUTO, chain4a, EXP_PASS, chain3a, ALLOW_PROBE | EXP_PASS, chain4a, EXP_PASS, chain3c, ALLOW_PROBE | EXP_PASS); /* Rewrite qcow2 file to use absolute backing name */ virCommandFree(cmd); cmd = virCommandNewArgList(qemuimg, "rebase", "-u", "-f", "qcow2", "-F", "raw", "-b", absraw, "qcow2", NULL); if (virCommandRun(cmd, NULL) < 0) ret = -1; /* Qcow2 file with raw as absolute backing, backing format provided */ const testFileData chain5[] = { qcow2_absback, raw }; const testFileData chain6[] = { raw }; TEST_CHAIN(5, "qcow2", absqcow2, VIR_STORAGE_FILE_QCOW2, chain5, EXP_PASS, chain5, ALLOW_PROBE | EXP_PASS, chain5, EXP_PASS, chain5, ALLOW_PROBE | EXP_PASS); TEST_CHAIN(6, "qcow2", absqcow2, VIR_STORAGE_FILE_AUTO, chain6, EXP_PASS, chain5, ALLOW_PROBE | EXP_PASS, chain6, EXP_PASS, chain5, ALLOW_PROBE | EXP_PASS); /* Wrapped file access */ const testFileData chain7[] = { wrap, qcow2_absback, raw }; TEST_CHAIN(7, "wrap", abswrap, VIR_STORAGE_FILE_QCOW2, chain7, EXP_PASS, chain7, ALLOW_PROBE | EXP_PASS, chain7, EXP_PASS, chain7, ALLOW_PROBE | EXP_PASS); /* Rewrite qcow2 and wrap file to omit backing file type */ virCommandFree(cmd); cmd = virCommandNewArgList(qemuimg, "rebase", "-u", "-f", "qcow2", "-b", absraw, "qcow2", NULL); if (virCommandRun(cmd, NULL) < 0) ret = -1; virCommandFree(cmd); cmd = virCommandNewArgList(qemuimg, "rebase", "-u", "-f", "qcow2", "-b", absqcow2, "wrap", NULL); if (virCommandRun(cmd, NULL) < 0) ret = -1; /* Qcow2 file with raw as absolute backing, backing format omitted */ const testFileData chain8a[] = { wrap_as_raw, raw }; const testFileData chain8b[] = { wrap_as_probe, qcow2_as_probe, raw }; TEST_CHAIN(8, "wrap", abswrap, VIR_STORAGE_FILE_QCOW2, chain8a, EXP_PASS, chain8b, ALLOW_PROBE | EXP_PASS, chain8a, EXP_PASS, chain8b, ALLOW_PROBE | EXP_PASS); /* Rewrite qcow2 to a missing backing file, with backing type */ virCommandFree(cmd); cmd = virCommandNewArgList(qemuimg, "rebase", "-u", "-f", "qcow2", "-F", "qcow2", "-b", datadir "/bogus", "qcow2", NULL); if (virCommandRun(cmd, NULL) < 0) ret = -1; /* Qcow2 file with missing backing file but specified type */ const testFileData chain9[] = { qcow2_bogus }; TEST_CHAIN(9, "qcow2", absqcow2, VIR_STORAGE_FILE_QCOW2, chain9, EXP_WARN, chain9, ALLOW_PROBE | EXP_WARN, chain9, EXP_WARN, chain9, ALLOW_PROBE | EXP_WARN); /* Rewrite qcow2 to a missing backing file, without backing type */ virCommandFree(cmd); cmd = virCommandNewArgList(qemuimg, "rebase", "-u", "-f", "qcow2", "-b", datadir "/bogus", "qcow2", NULL); if (virCommandRun(cmd, NULL) < 0) ret = -1; /* Qcow2 file with missing backing file and no specified type */ const testFileData chain10[] = { qcow2_bogus }; TEST_CHAIN(10, "qcow2", absqcow2, VIR_STORAGE_FILE_QCOW2, chain10, EXP_WARN, chain10, ALLOW_PROBE | EXP_WARN, chain10, EXP_WARN, chain10, ALLOW_PROBE | EXP_WARN); /* Rewrite qcow2 to use an nbd: protocol as backend */ virCommandFree(cmd); cmd = virCommandNewArgList(qemuimg, "rebase", "-u", "-f", "qcow2", "-F", "raw", "-b", "nbd:example.org:6000", "qcow2", NULL); if (virCommandRun(cmd, NULL) < 0) ret = -1; /* Qcow2 file with backing protocol instead of file */ const testFileData chain11[] = { qcow2_protocol }; TEST_CHAIN(11, "qcow2", absqcow2, VIR_STORAGE_FILE_QCOW2, chain11, EXP_PASS, chain11, ALLOW_PROBE | EXP_PASS, chain11, EXP_PASS, chain11, ALLOW_PROBE | EXP_PASS); /* qed file */ const testFileData chain12a[] = { raw }; const testFileData chain12b[] = { qed, raw }; TEST_CHAIN(12, "qed", absqed, VIR_STORAGE_FILE_AUTO, chain12a, EXP_PASS, chain12b, ALLOW_PROBE | EXP_PASS, chain12a, EXP_PASS, chain12b, ALLOW_PROBE | EXP_PASS); /* Rewrite qcow2 and wrap file to use backing names relative to a * symlink from a different directory */ virCommandFree(cmd); cmd = virCommandNewArgList(qemuimg, "rebase", "-u", "-f", "qcow2", "-F", "raw", "-b", "../raw", "qcow2", NULL); if (virCommandRun(cmd, NULL) < 0) ret = -1; virCommandFree(cmd); cmd = virCommandNewArgList(qemuimg, "rebase", "-u", "-f", "qcow2", "-F", "qcow2", "-b", "../sub/link1", "wrap", NULL); if (virCommandRun(cmd, NULL) < 0) ret = -1; /* Behavior of symlinks to qcow2 with relative backing files */ const testFileData chain13a[] = { link2_rel, link1_rel, raw }; const testFileData chain13c[] = { link2_abs, link1_abs, raw }; TEST_CHAIN(13, "sub/link2", abslink2, VIR_STORAGE_FILE_QCOW2, chain13a, EXP_PASS, chain13a, ALLOW_PROBE | EXP_PASS, chain13c, EXP_PASS, chain13c, ALLOW_PROBE | EXP_PASS); /* Final cleanup */ testCleanupImages(); virCommandFree(cmd); return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; }