/** * qemuBlockJobEmitEvents: * * Emits the VIR_DOMAIN_EVENT_ID_BLOCK_JOB and VIR_DOMAIN_EVENT_ID_BLOCK_JOB_2 * for a block job. The former event is emitted only for local disks. */ static void qemuBlockJobEmitEvents(virQEMUDriverPtr driver, virDomainObjPtr vm, virDomainDiskDefPtr disk, virDomainBlockJobType type, virConnectDomainEventBlockJobStatus status) { virObjectEventPtr event = NULL; virObjectEventPtr event2 = NULL; /* don't emit events for internal jobs and states */ if (type >= VIR_DOMAIN_BLOCK_JOB_TYPE_LAST || status >= VIR_DOMAIN_BLOCK_JOB_LAST) return; if (virStorageSourceIsLocalStorage(disk->src) && !virStorageSourceIsEmpty(disk->src)) { event = virDomainEventBlockJobNewFromObj(vm, virDomainDiskGetSource(disk), type, status); virObjectEventStateQueue(driver->domainEventState, event); } event2 = virDomainEventBlockJob2NewFromObj(vm, disk->dst, type, status); virObjectEventStateQueue(driver->domainEventState, event2); }
static int bhyveBuildDiskArgStr(const virDomainDef *def, virCommandPtr cmd) { virDomainDiskDefPtr disk; const char *bus_type; if (def->ndisks != 1) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("domain should have one and only one disk defined")); return -1; } disk = def->disks[0]; switch (disk->bus) { case VIR_DOMAIN_DISK_BUS_SATA: bus_type = "ahci-hd"; break; case VIR_DOMAIN_DISK_BUS_VIRTIO: bus_type = "virtio-blk"; break; default: virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("unsupported disk bus type")); return -1; } if (disk->device != VIR_DOMAIN_DISK_DEVICE_DISK) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("unsupported disk device")); return -1; } if (virDomainDiskGetType(disk) != VIR_STORAGE_TYPE_FILE) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("unsupported disk type")); return -1; } virCommandAddArg(cmd, "-s"); virCommandAddArgFormat(cmd, "2:0,%s,%s", bus_type, virDomainDiskGetSource(disk)); return 0; }
virCommandPtr virBhyveProcessBuildLoadCmd(bhyveConnPtr driver ATTRIBUTE_UNUSED, virDomainObjPtr vm) { virCommandPtr cmd; virDomainDiskDefPtr disk; if (vm->def->ndisks != 1) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("domain should have one and only one disk defined")); return NULL; } disk = vm->def->disks[0]; if (disk->device != VIR_DOMAIN_DISK_DEVICE_DISK) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("unsupported disk device")); return NULL; } if (virDomainDiskGetType(disk) != VIR_STORAGE_TYPE_FILE) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("unsupported disk type")); return NULL; } cmd = virCommandNew(BHYVELOAD); /* Memory */ virCommandAddArg(cmd, "-m"); virCommandAddArgFormat(cmd, "%llu", VIR_DIV_UP(vm->def->mem.max_balloon, 1024)); /* Image path */ virCommandAddArg(cmd, "-d"); virCommandAddArg(cmd, virDomainDiskGetSource(disk)); /* VM name */ virCommandAddArg(cmd, vm->def->name); return cmd; }
int libxlMakeDisk(virDomainDiskDefPtr l_disk, libxl_device_disk *x_disk) { const char *driver; int format; libxl_device_disk_init(x_disk); if (VIR_STRDUP(x_disk->pdev_path, virDomainDiskGetSource(l_disk)) < 0) return -1; if (VIR_STRDUP(x_disk->vdev, l_disk->dst) < 0) return -1; driver = virDomainDiskGetDriver(l_disk); format = virDomainDiskGetFormat(l_disk); if (driver) { if (STREQ(driver, "tap") || STREQ(driver, "tap2")) { switch (format) { case VIR_STORAGE_FILE_QCOW: x_disk->format = LIBXL_DISK_FORMAT_QCOW; x_disk->backend = LIBXL_DISK_BACKEND_QDISK; break; case VIR_STORAGE_FILE_QCOW2: x_disk->format = LIBXL_DISK_FORMAT_QCOW2; x_disk->backend = LIBXL_DISK_BACKEND_QDISK; break; case VIR_STORAGE_FILE_VHD: x_disk->format = LIBXL_DISK_FORMAT_VHD; x_disk->backend = LIBXL_DISK_BACKEND_TAP; break; case VIR_STORAGE_FILE_NONE: /* No subtype specified, default to raw/tap */ case VIR_STORAGE_FILE_RAW: x_disk->format = LIBXL_DISK_FORMAT_RAW; x_disk->backend = LIBXL_DISK_BACKEND_TAP; break; default: virReportError(VIR_ERR_INTERNAL_ERROR, _("libxenlight does not support disk format %s " "with disk driver %s"), virStorageFileFormatTypeToString(format), driver); return -1; } } else if (STREQ(driver, "qemu")) { x_disk->backend = LIBXL_DISK_BACKEND_QDISK; switch (format) { case VIR_STORAGE_FILE_QCOW: x_disk->format = LIBXL_DISK_FORMAT_QCOW; break; case VIR_STORAGE_FILE_QCOW2: x_disk->format = LIBXL_DISK_FORMAT_QCOW2; break; case VIR_STORAGE_FILE_VHD: x_disk->format = LIBXL_DISK_FORMAT_VHD; break; case VIR_STORAGE_FILE_NONE: /* No subtype specified, default to raw */ case VIR_STORAGE_FILE_RAW: x_disk->format = LIBXL_DISK_FORMAT_RAW; break; default: virReportError(VIR_ERR_INTERNAL_ERROR, _("libxenlight does not support disk format %s " "with disk driver %s"), virStorageFileFormatTypeToString(format), driver); return -1; } } else if (STREQ(driver, "file")) { if (format != VIR_STORAGE_FILE_NONE && format != VIR_STORAGE_FILE_RAW) { virReportError(VIR_ERR_INTERNAL_ERROR, _("libxenlight does not support disk format %s " "with disk driver %s"), virStorageFileFormatTypeToString(format), driver); return -1; } x_disk->format = LIBXL_DISK_FORMAT_RAW; x_disk->backend = LIBXL_DISK_BACKEND_TAP; } else if (STREQ(driver, "phy")) { if (format != VIR_STORAGE_FILE_NONE && format != VIR_STORAGE_FILE_RAW) { virReportError(VIR_ERR_INTERNAL_ERROR, _("libxenlight does not support disk format %s " "with disk driver %s"), virStorageFileFormatTypeToString(format), driver); return -1; } x_disk->format = LIBXL_DISK_FORMAT_RAW; x_disk->backend = LIBXL_DISK_BACKEND_PHY; } else { virReportError(VIR_ERR_INTERNAL_ERROR, _("libxenlight does not support disk driver %s"), driver); return -1; } } else { /* * If driverName is not specified, default to raw as per * xl-disk-configuration.txt in the xen documentation and let * libxl pick a suitable backend. */ x_disk->format = LIBXL_DISK_FORMAT_RAW; x_disk->backend = LIBXL_DISK_BACKEND_UNKNOWN; } /* XXX is this right? */ x_disk->removable = 1; x_disk->readwrite = !l_disk->readonly; x_disk->is_cdrom = l_disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM ? 1 : 0; /* An empty CDROM must have the empty format, otherwise libxl fails. */ if (x_disk->is_cdrom && !x_disk->pdev_path) x_disk->format = LIBXL_DISK_FORMAT_EMPTY; if (l_disk->transient) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("libxenlight does not support transient disks")); return -1; } return 0; }
/* * Constructs a argv suitable for launching uml with config defined * for a given virtual machine. */ virCommandPtr umlBuildCommandLine(virConnectPtr conn, struct uml_driver *driver, virDomainObjPtr vm) { size_t i, j; virCommandPtr cmd; cmd = virCommandNew(vm->def->os.kernel); virCommandAddEnvPassCommon(cmd); //virCommandAddArgPair(cmd, "con0", "fd:0,fd:1"); virCommandAddArgFormat(cmd, "mem=%lluK", vm->def->mem.cur_balloon); virCommandAddArgPair(cmd, "umid", vm->def->name); virCommandAddArgPair(cmd, "uml_dir", driver->monitorDir); if (vm->def->os.root) virCommandAddArgPair(cmd, "root", vm->def->os.root); for (i = 0; i < vm->def->ndisks; i++) { virDomainDiskDefPtr disk = vm->def->disks[i]; if (!STRPREFIX(disk->dst, "ubd")) { virReportError(VIR_ERR_INTERNAL_ERROR, _("unsupported disk type '%s'"), disk->dst); goto error; } virCommandAddArgPair(cmd, disk->dst, virDomainDiskGetSource(disk)); } for (i = 0; i < vm->def->nnets; i++) { char *ret = umlBuildCommandLineNet(conn, vm->def, vm->def->nets[i], i); if (!ret) goto error; virCommandAddArg(cmd, ret); VIR_FREE(ret); } for (i = 0; i < UML_MAX_CHAR_DEVICE; i++) { virDomainChrDefPtr chr = NULL; char *ret = NULL; for (j = 0; j < vm->def->nconsoles; j++) if (vm->def->consoles[j]->target.port == i) chr = vm->def->consoles[j]; if (chr) ret = umlBuildCommandLineChr(chr, "con", cmd); if (!ret) if (virAsprintf(&ret, "con%zu=none", i) < 0) goto error; virCommandAddArg(cmd, ret); VIR_FREE(ret); } for (i = 0; i < UML_MAX_CHAR_DEVICE; i++) { virDomainChrDefPtr chr = NULL; char *ret = NULL; for (j = 0; j < vm->def->nserials; j++) if (vm->def->serials[j]->target.port == i) chr = vm->def->serials[j]; if (chr) ret = umlBuildCommandLineChr(chr, "ssl", cmd); if (!ret) if (virAsprintf(&ret, "ssl%zu=none", i) < 0) goto error; virCommandAddArg(cmd, ret); VIR_FREE(ret); } if (vm->def->os.cmdline) { char *args, *next_arg; char *cmdline; if (VIR_STRDUP(cmdline, vm->def->os.cmdline) < 0) goto error; args = cmdline; while (*args == ' ') args++; while (*args) { next_arg = umlNextArg(args); virCommandAddArg(cmd, args); args = next_arg; } VIR_FREE(cmdline); } return cmd; error: virCommandFree(cmd); return NULL; }
int vmwareVmxPath(virDomainDefPtr vmdef, char **vmxPath) { virDomainDiskDefPtr disk = NULL; char *directoryName = NULL; char *fileName = NULL; int ret = -1; size_t i; const char *src; /* * Build VMX URL. Use the source of the first file-based harddisk * to deduce the path for the VMX file. Don't just use the * first disk, because it may be CDROM disk and ISO images are normally not * located in the virtual machine's directory. This approach * isn't perfect but should work in the majority of cases. */ if (vmdef->ndisks < 1) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Domain XML doesn't contain any disks, " "cannot deduce datastore and path for VMX file")); goto cleanup; } for (i = 0; i < vmdef->ndisks; ++i) { if (vmdef->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_DISK && virDomainDiskGetType(vmdef->disks[i]) == VIR_STORAGE_TYPE_FILE) { disk = vmdef->disks[i]; break; } } if (disk == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("Domain XML doesn't contain any file-based harddisks, " "cannot deduce datastore and path for VMX file")); goto cleanup; } src = virDomainDiskGetSource(disk); if (!src) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("First file-based harddisk has no source, cannot " "deduce datastore and path for VMX file")); goto cleanup; } if (vmwareParsePath(src, &directoryName, &fileName) < 0) goto cleanup; if (!virFileHasSuffix(fileName, ".vmdk")) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Expecting source '%s' of first file-based harddisk " "to be a VMDK image"), src); goto cleanup; } if (vmwareConstructVmxPath(directoryName, vmdef->name, vmxPath) < 0) goto cleanup; ret = 0; cleanup: VIR_FREE(directoryName); VIR_FREE(fileName); return ret; }
static int xenFormatXLDisk(virConfValuePtr list, virDomainDiskDefPtr disk) { virBuffer buf = VIR_BUFFER_INITIALIZER; virConfValuePtr val, tmp; const char *src = virDomainDiskGetSource(disk); int format = virDomainDiskGetFormat(disk); const char *driver = virDomainDiskGetDriver(disk); /* target */ virBufferAsprintf(&buf, "%s,", src); /* format */ switch (format) { case VIR_STORAGE_FILE_RAW: virBufferAddLit(&buf, "raw,"); break; case VIR_STORAGE_FILE_VHD: virBufferAddLit(&buf, "xvhd,"); break; case VIR_STORAGE_FILE_QCOW: virBufferAddLit(&buf, "qcow,"); break; case VIR_STORAGE_FILE_QCOW2: virBufferAddLit(&buf, "qcow2,"); break; /* set default */ default: virBufferAddLit(&buf, "raw,"); } /* device */ virBufferAdd(&buf, disk->dst, -1); virBufferAddLit(&buf, ","); if (disk->src->readonly) virBufferAddLit(&buf, "r,"); else if (disk->src->shared) virBufferAddLit(&buf, "!,"); else virBufferAddLit(&buf, "w,"); if (disk->transient) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("transient disks not supported yet")); goto cleanup; } if (STREQ_NULLABLE(driver, "qemu")) virBufferAddLit(&buf, "backendtype=qdisk"); else if (STREQ_NULLABLE(driver, "tap")) virBufferAddLit(&buf, "backendtype=tap"); else if (STREQ_NULLABLE(driver, "phy")) virBufferAddLit(&buf, "backendtype=phy"); if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) virBufferAddLit(&buf, ",devtype=cdrom"); if (virBufferCheckError(&buf) < 0) goto cleanup; if (VIR_ALLOC(val) < 0) goto cleanup; val->type = VIR_CONF_STRING; val->str = virBufferContentAndReset(&buf); tmp = list->list; while (tmp && tmp->next) tmp = tmp->next; if (tmp) tmp->next = val; else list->list = val; return 0; cleanup: virBufferFreeAndReset(&buf); return -1; }
/** * qemuBlockJobEventProcess: * @driver: qemu driver * @vm: domain * @disk: domain disk * @type: block job type * @status: block job status * * Update disk's mirror state in response to a block job event * from QEMU. For mirror state's that must survive libvirt * restart, also update the domain's status XML. */ void qemuBlockJobEventProcess(virQEMUDriverPtr driver, virDomainObjPtr vm, virDomainDiskDefPtr disk, qemuDomainAsyncJob asyncJob, int type, int status) { virObjectEventPtr event = NULL; virObjectEventPtr event2 = NULL; const char *path; virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver); virDomainDiskDefPtr persistDisk = NULL; qemuDomainDiskPrivatePtr diskPriv = QEMU_DOMAIN_DISK_PRIVATE(disk); VIR_DEBUG("disk=%s, mirrorState=%s, type=%d, status=%d", disk->dst, NULLSTR(virDomainDiskMirrorStateTypeToString(disk->mirrorState)), type, status); /* Have to generate two variants of the event for old vs. new * client callbacks */ if (type == VIR_DOMAIN_BLOCK_JOB_TYPE_COMMIT && disk->mirrorJob == VIR_DOMAIN_BLOCK_JOB_TYPE_ACTIVE_COMMIT) type = disk->mirrorJob; path = virDomainDiskGetSource(disk); event = virDomainEventBlockJobNewFromObj(vm, path, type, status); event2 = virDomainEventBlockJob2NewFromObj(vm, disk->dst, type, status); /* If we completed a block pull or commit, then update the XML * to match. */ switch ((virConnectDomainEventBlockJobStatus) status) { case VIR_DOMAIN_BLOCK_JOB_COMPLETED: if (disk->mirrorState == VIR_DOMAIN_DISK_MIRROR_STATE_PIVOT) { if (vm->newDef) { virStorageSourcePtr copy = NULL; if ((persistDisk = virDomainDiskByName(vm->newDef, disk->dst, false))) { copy = virStorageSourceCopy(disk->mirror, false); if (!copy || virStorageSourceInitChainElement(copy, persistDisk->src, true) < 0) { VIR_WARN("Unable to update persistent definition " "on vm %s after block job", vm->def->name); virStorageSourceFree(copy); copy = NULL; persistDisk = NULL; } } if (copy) { virStorageSourceFree(persistDisk->src); persistDisk->src = copy; } } /* XXX We want to revoke security labels as well as audit that * revocation, before dropping the original source. But it gets * tricky if both source and mirror share common backing files (we * want to only revoke the non-shared portion of the chain); so for * now, we leak the access to the original. */ virDomainLockImageDetach(driver->lockManager, vm, disk->src); virStorageSourceFree(disk->src); disk->src = disk->mirror; } else { if (disk->mirror) { virDomainLockImageDetach(driver->lockManager, vm, disk->mirror); virStorageSourceFree(disk->mirror); } } /* Recompute the cached backing chain to match our * updates. Better would be storing the chain ourselves * rather than reprobing, but we haven't quite completed * that conversion to use our XML tracking. */ disk->mirror = NULL; disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_NONE; disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN; disk->src->id = 0; ignore_value(qemuDomainDetermineDiskChain(driver, vm, disk, true, true)); ignore_value(qemuBlockNodeNamesDetect(driver, vm, asyncJob)); diskPriv->blockjob = false; break; case VIR_DOMAIN_BLOCK_JOB_READY: disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_READY; break; case VIR_DOMAIN_BLOCK_JOB_FAILED: case VIR_DOMAIN_BLOCK_JOB_CANCELED: if (disk->mirror) { virDomainLockImageDetach(driver->lockManager, vm, disk->mirror); virStorageSourceFree(disk->mirror); disk->mirror = NULL; } disk->mirrorState = VIR_DOMAIN_DISK_MIRROR_STATE_NONE; disk->mirrorJob = VIR_DOMAIN_BLOCK_JOB_TYPE_UNKNOWN; diskPriv->blockjob = false; break; case VIR_DOMAIN_BLOCK_JOB_LAST: break; } if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, driver->caps) < 0) VIR_WARN("Unable to save status on vm %s after block job", vm->def->name); if (status == VIR_DOMAIN_BLOCK_JOB_COMPLETED && vm->newDef) { if (virDomainSaveConfig(cfg->configDir, driver->caps, vm->newDef) < 0) VIR_WARN("Unable to update persistent definition on vm %s " "after block job", vm->def->name); } qemuDomainEventQueue(driver, event); qemuDomainEventQueue(driver, event2); virObjectUnref(cfg); }
/* Align def->disks to def->domain. Sort the list of def->disks, * filling in any missing disks or snapshot state defaults given by * the domain, with a fallback to a passed in default. Convert paths * to disk targets for uniformity. Issue an error and return -1 if * any def->disks[n]->name appears more than once or does not map to * dom->disks. If require_match, also ensure that there is no * conflicting requests for both internal and external snapshots. */ int virDomainSnapshotAlignDisks(virDomainSnapshotDefPtr def, int default_snapshot, bool require_match) { int ret = -1; virBitmapPtr map = NULL; size_t i; int ndisks; if (!def->dom) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("missing domain in snapshot")); goto cleanup; } if (def->ndisks > def->dom->ndisks) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("too many disk snapshot requests for domain")); goto cleanup; } /* Unlikely to have a guest without disks but technically possible. */ if (!def->dom->ndisks) { ret = 0; goto cleanup; } if (!(map = virBitmapNew(def->dom->ndisks))) goto cleanup; /* Double check requested disks. */ for (i = 0; i < def->ndisks; i++) { virDomainSnapshotDiskDefPtr disk = &def->disks[i]; int idx = virDomainDiskIndexByName(def->dom, disk->name, false); int disk_snapshot; if (idx < 0) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("no disk named '%s'"), disk->name); goto cleanup; } if (virBitmapIsBitSet(map, idx)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("disk '%s' specified twice"), disk->name); goto cleanup; } ignore_value(virBitmapSetBit(map, idx)); disk->index = idx; disk_snapshot = def->dom->disks[idx]->snapshot; if (!disk->snapshot) { if (disk_snapshot && (!require_match || disk_snapshot == VIR_DOMAIN_SNAPSHOT_LOCATION_NONE)) disk->snapshot = disk_snapshot; else disk->snapshot = default_snapshot; } else if (require_match && disk->snapshot != default_snapshot && !(disk->snapshot == VIR_DOMAIN_SNAPSHOT_LOCATION_NONE && disk_snapshot == VIR_DOMAIN_SNAPSHOT_LOCATION_NONE)) { const char *tmp; tmp = virDomainSnapshotLocationTypeToString(default_snapshot); virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("disk '%s' must use snapshot mode '%s'"), disk->name, tmp); goto cleanup; } if (disk->src->path && disk->snapshot != VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("file '%s' for disk '%s' requires " "use of external snapshot mode"), disk->src->path, disk->name); goto cleanup; } if (STRNEQ(disk->name, def->dom->disks[idx]->dst)) { VIR_FREE(disk->name); if (VIR_STRDUP(disk->name, def->dom->disks[idx]->dst) < 0) goto cleanup; } } /* Provide defaults for all remaining disks. */ ndisks = def->ndisks; if (VIR_EXPAND_N(def->disks, def->ndisks, def->dom->ndisks - def->ndisks) < 0) goto cleanup; for (i = 0; i < def->dom->ndisks; i++) { virDomainSnapshotDiskDefPtr disk; if (virBitmapIsBitSet(map, i)) continue; disk = &def->disks[ndisks++]; if (VIR_ALLOC(disk->src) < 0) goto cleanup; if (VIR_STRDUP(disk->name, def->dom->disks[i]->dst) < 0) goto cleanup; disk->index = i; /* Don't snapshot empty drives */ if (virStorageSourceIsEmpty(def->dom->disks[i]->src)) disk->snapshot = VIR_DOMAIN_SNAPSHOT_LOCATION_NONE; else disk->snapshot = def->dom->disks[i]->snapshot; disk->src->type = VIR_STORAGE_TYPE_FILE; if (!disk->snapshot) disk->snapshot = default_snapshot; } qsort(&def->disks[0], def->ndisks, sizeof(def->disks[0]), disksorter); /* Generate any default external file names, but only if the * backing file is a regular file. */ for (i = 0; i < def->ndisks; i++) { virDomainSnapshotDiskDefPtr disk = &def->disks[i]; if (disk->snapshot == VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL && !disk->src->path) { const char *original = virDomainDiskGetSource(def->dom->disks[i]); const char *tmp; struct stat sb; if (disk->src->type != VIR_STORAGE_TYPE_FILE) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("cannot generate external snapshot name " "for disk '%s' on a '%s' device"), disk->name, virStorageTypeToString(disk->src->type)); goto cleanup; } if (!original) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("cannot generate external snapshot name " "for disk '%s' without source"), disk->name); goto cleanup; } if (stat(original, &sb) < 0 || !S_ISREG(sb.st_mode)) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, _("source for disk '%s' is not a regular " "file; refusing to generate external " "snapshot name"), disk->name); goto cleanup; } tmp = strrchr(original, '.'); if (!tmp || strchr(tmp, '/')) { if (virAsprintf(&disk->src->path, "%s.%s", original, def->name) < 0) goto cleanup; } else { if ((tmp - original) > INT_MAX) { virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("integer overflow")); goto cleanup; } if (virAsprintf(&disk->src->path, "%.*s.%s", (int) (tmp - original), original, def->name) < 0) goto cleanup; } } } ret = 0; cleanup: virBitmapFree(map); return ret; }
/* * Parse the /usr/sbin/bhyveload command line. */ static int bhyveParseBhyveLoadCommandLine(virDomainDefPtr def, int argc, char **argv) { int c; /* bhyveload called with default arguments when only -m and -d are given. * Store this in a bit field and check if only those two options are given * later */ unsigned arguments = 0; size_t memory = 0; struct _getopt_data *parser; size_t i = 0; int ret = -1; const char optstr[] = "CSc:d:e:h:l:m:"; if (!argv) goto error; if (VIR_ALLOC(parser) < 0) goto error; while ((c = _getopt_internal_r(argc, argv, optstr, NULL, NULL, 0, parser, 0)) != -1) { switch (c) { case 'd': arguments |= 1; /* Iterate over the disks of the domain trying to match up the * source */ for (i = 0; i < def->ndisks; i++) { if (STREQ(virDomainDiskGetSource(def->disks[i]), parser->optarg)) { def->disks[i]->info.bootIndex = i; break; } } break; case 'm': arguments |= 2; if (bhyveParseMemsize(parser->optarg, &memory)) { virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("Failed to parse memory")); goto error; } if (def->mem.cur_balloon != 0 && def->mem.cur_balloon != memory) { virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("Failed to parse memory: size mismatch")); goto error; } def->mem.cur_balloon = memory; virDomainDefSetMemoryTotal(def, memory); break; default: arguments |= 4; } } if (arguments != 3) { /* Set os.bootloader since virDomainDefFormatInternal will only format * the bootloader arguments if os->bootloader is set. */ if (VIR_STRDUP(def->os.bootloader, argv[0]) < 0) goto error; def->os.bootloaderArgs = virStringJoin((const char**) &argv[1], " "); } if (argc != parser->optind) { virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("Failed to parse arguments for bhyveload command")); goto error; } if (def->name == NULL) { if (VIR_STRDUP(def->name, argv[argc]) < 0) goto error; } else if (STRNEQ(def->name, argv[argc])) { /* the vm name of the loader and the bhyverun command differ, throw an * error here */ virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("Failed to parse arguments: VM name mismatch")); goto error; } ret = 0; error: VIR_FREE(parser); return ret; }
static int xenFormatXMDisk(virConfValuePtr list, virDomainDiskDefPtr disk) { virBuffer buf = VIR_BUFFER_INITIALIZER; virConfValuePtr val, tmp; const char *src = virDomainDiskGetSource(disk); int format = virDomainDiskGetFormat(disk); const char *driver = virDomainDiskGetDriver(disk); if (src) { if (format) { const char *type; if (format == VIR_STORAGE_FILE_RAW) type = "aio"; else type = virStorageFileFormatTypeToString(format); virBufferAsprintf(&buf, "%s:", driver); if (STREQ(driver, "tap")) virBufferAsprintf(&buf, "%s:", type); } else { switch (virDomainDiskGetType(disk)) { case VIR_STORAGE_TYPE_FILE: virBufferAddLit(&buf, "file:"); break; case VIR_STORAGE_TYPE_BLOCK: virBufferAddLit(&buf, "phy:"); break; default: virReportError(VIR_ERR_INTERNAL_ERROR, _("unsupported disk type %s"), virStorageTypeToString(virDomainDiskGetType(disk))); goto cleanup; } } virBufferAdd(&buf, src, -1); } virBufferAddLit(&buf, ","); virBufferAdd(&buf, disk->dst, -1); if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM) virBufferAddLit(&buf, ":cdrom"); if (disk->src->readonly) virBufferAddLit(&buf, ",r"); else if (disk->src->shared) virBufferAddLit(&buf, ",!"); else virBufferAddLit(&buf, ",w"); if (disk->transient) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("transient disks not supported yet")); return -1; } if (virBufferCheckError(&buf) < 0) goto cleanup; if (VIR_ALLOC(val) < 0) goto cleanup; val->type = VIR_CONF_STRING; val->str = virBufferContentAndReset(&buf); tmp = list->list; while (tmp && tmp->next) tmp = tmp->next; if (tmp) tmp->next = val; else list->list = val; return 0; cleanup: virBufferFreeAndReset(&buf); return -1; }
static int xenParseXMDisk(virConfPtr conf, virDomainDefPtr def) { virDomainDiskDefPtr disk = NULL; int hvm = def->os.type == VIR_DOMAIN_OSTYPE_HVM; virConfValuePtr list = virConfGetValue(conf, "disk"); if (list && list->type == VIR_CONF_LIST) { list = list->list; while (list) { char *head; char *offset; char *tmp; const char *src; if ((list->type != VIR_CONF_STRING) || (list->str == NULL)) goto skipdisk; head = list->str; if (!(disk = virDomainDiskDefNew(NULL))) return -1; /* * Disks have 3 components, SOURCE,DEST-DEVICE,MODE * eg, phy:/dev/HostVG/XenGuest1,xvda,w * The SOURCE is usually prefixed with a driver type, * and optionally driver sub-type * The DEST-DEVICE is optionally post-fixed with disk type */ /* Extract the source file path*/ if (!(offset = strchr(head, ','))) goto skipdisk; if (offset == head) { /* No source file given, eg CDROM with no media */ ignore_value(virDomainDiskSetSource(disk, NULL)); } else { if (VIR_STRNDUP(tmp, head, offset - head) < 0) goto cleanup; if (virDomainDiskSetSource(disk, tmp) < 0) { VIR_FREE(tmp); goto cleanup; } VIR_FREE(tmp); } head = offset + 1; /* Remove legacy ioemu: junk */ if (STRPREFIX(head, "ioemu:")) head = head + 6; /* Extract the dest device name */ if (!(offset = strchr(head, ','))) goto skipdisk; if (VIR_ALLOC_N(disk->dst, (offset - head) + 1) < 0) goto cleanup; if (virStrncpy(disk->dst, head, offset - head, (offset - head) + 1) == NULL) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Dest file %s too big for destination"), head); goto cleanup; } head = offset + 1; /* Extract source driver type */ src = virDomainDiskGetSource(disk); if (src) { size_t len; /* The main type phy:, file:, tap: ... */ if ((tmp = strchr(src, ':')) != NULL) { len = tmp - src; if (VIR_STRNDUP(tmp, src, len) < 0) goto cleanup; if (virDomainDiskSetDriver(disk, tmp) < 0) { VIR_FREE(tmp); goto cleanup; } VIR_FREE(tmp); /* Strip the prefix we found off the source file name */ if (virDomainDiskSetSource(disk, src + len + 1) < 0) goto cleanup; src = virDomainDiskGetSource(disk); } /* And the sub-type for tap:XXX: type */ if (STREQ_NULLABLE(virDomainDiskGetDriver(disk), "tap")) { char *driverType; if (!(tmp = strchr(src, ':'))) goto skipdisk; len = tmp - src; if (VIR_STRNDUP(driverType, src, len) < 0) goto cleanup; if (STREQ(driverType, "aio")) virDomainDiskSetFormat(disk, VIR_STORAGE_FILE_RAW); else virDomainDiskSetFormat(disk, virStorageFileFormatTypeFromString(driverType)); VIR_FREE(driverType); if (virDomainDiskGetFormat(disk) <= 0) { virReportError(VIR_ERR_INTERNAL_ERROR, _("Unknown driver type %s"), src); goto cleanup; } /* Strip the prefix we found off the source file name */ if (virDomainDiskSetSource(disk, src + len + 1) < 0) goto cleanup; src = virDomainDiskGetSource(disk); } } /* No source, or driver name, so fix to phy: */ if (!virDomainDiskGetDriver(disk) && virDomainDiskSetDriver(disk, "phy") < 0) goto cleanup; /* phy: type indicates a block device */ virDomainDiskSetType(disk, STREQ(virDomainDiskGetDriver(disk), "phy") ? VIR_STORAGE_TYPE_BLOCK : VIR_STORAGE_TYPE_FILE); /* Check for a :cdrom/:disk postfix */ disk->device = VIR_DOMAIN_DISK_DEVICE_DISK; if ((tmp = strchr(disk->dst, ':')) != NULL) { if (STREQ(tmp, ":cdrom")) disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM; tmp[0] = '\0'; } if (STRPREFIX(disk->dst, "xvd") || !hvm) { disk->bus = VIR_DOMAIN_DISK_BUS_XEN; } else if (STRPREFIX(disk->dst, "sd")) { disk->bus = VIR_DOMAIN_DISK_BUS_SCSI; } else { disk->bus = VIR_DOMAIN_DISK_BUS_IDE; } if (STREQ(head, "r") || STREQ(head, "ro")) disk->src->readonly = true; else if ((STREQ(head, "w!")) || (STREQ(head, "!"))) disk->src->shared = true; /* Maintain list in sorted order according to target device name */ if (VIR_APPEND_ELEMENT(def->disks, def->ndisks, disk) < 0) goto cleanup; skipdisk: list = list->next; virDomainDiskDefFree(disk); disk = NULL; } } return 0; cleanup: virDomainDiskDefFree(disk); return -1; }