/* * For details on xl disk config syntax, see * docs/misc/xl-disk-configuration.txt in the Xen sources. The important * section of text is: * * More formally, the string is a series of comma-separated keyword/value * pairs, flags and positional parameters. Parameters which are not bare * keywords and which do not contain "=" symbols are assigned to the * so-far-unspecified positional parameters, in the order below. The * positional parameters may also be specified explicitly by name. * * Each parameter may be specified at most once, either as a positional * parameter or a named parameter. Default values apply if the parameter * is not specified, or if it is specified with an empty value (whether * positionally or explicitly). * * Whitespace may appear before each parameter and will be ignored. * * The order of the positional parameters mentioned in the quoted text is: * * target,format,vdev,access * * The following options must be specified by key=value: * * devtype=<devtype> * backendtype=<backend-type> * * The following options are currently not supported: * * backend=<domain-name> * script=<script> * direct-io-safe * */ static int xenParseXLDisk(virConfPtr conf, virDomainDefPtr def) { int ret = -1; virConfValuePtr list = virConfGetValue(conf, "disk"); XLU_Config *xluconf; libxl_device_disk *libxldisk; virDomainDiskDefPtr disk = NULL; if (VIR_ALLOC(libxldisk) < 0) return -1; if (!(xluconf = xlu_cfg_init(stderr, "command line"))) goto cleanup; if (list && list->type == VIR_CONF_LIST) { list = list->list; while (list) { const char *disk_spec = list->str; if (list->type != VIR_CONF_STRING || list->str == NULL) goto skipdisk; libxl_device_disk_init(libxldisk); if (xlu_disk_parse(xluconf, 1, &disk_spec, libxldisk)) goto fail; if (!(disk = virDomainDiskDefNew(NULL))) goto fail; if (xenParseXLDiskSrc(disk, libxldisk->pdev_path) < 0) goto fail; if (VIR_STRDUP(disk->dst, libxldisk->vdev) < 0) goto fail; disk->src->readonly = !libxldisk->readwrite; disk->removable = libxldisk->removable; if (libxldisk->is_cdrom) { if (virDomainDiskSetDriver(disk, "qemu") < 0) goto fail; virDomainDiskSetType(disk, VIR_STORAGE_TYPE_FILE); disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM; if (!disk->src->path || STREQ(disk->src->path, "")) disk->src->format = VIR_STORAGE_FILE_NONE; else disk->src->format = VIR_STORAGE_FILE_RAW; } else { switch (libxldisk->format) { case LIBXL_DISK_FORMAT_QCOW: disk->src->format = VIR_STORAGE_FILE_QCOW; break; case LIBXL_DISK_FORMAT_QCOW2: disk->src->format = VIR_STORAGE_FILE_QCOW2; break; case LIBXL_DISK_FORMAT_VHD: disk->src->format = VIR_STORAGE_FILE_VHD; break; case LIBXL_DISK_FORMAT_RAW: case LIBXL_DISK_FORMAT_UNKNOWN: disk->src->format = VIR_STORAGE_FILE_RAW; break; case LIBXL_DISK_FORMAT_EMPTY: break; } switch (libxldisk->backend) { case LIBXL_DISK_BACKEND_QDISK: case LIBXL_DISK_BACKEND_UNKNOWN: if (virDomainDiskSetDriver(disk, "qemu") < 0) goto fail; if (virDomainDiskGetType(disk) == VIR_STORAGE_TYPE_NONE) virDomainDiskSetType(disk, VIR_STORAGE_TYPE_FILE); break; case LIBXL_DISK_BACKEND_TAP: if (virDomainDiskSetDriver(disk, "tap") < 0) goto fail; virDomainDiskSetType(disk, VIR_STORAGE_TYPE_FILE); break; case LIBXL_DISK_BACKEND_PHY: if (virDomainDiskSetDriver(disk, "phy") < 0) goto fail; virDomainDiskSetType(disk, VIR_STORAGE_TYPE_BLOCK); break; } } if (STRPREFIX(libxldisk->vdev, "xvd") || def->os.type != VIR_DOMAIN_OSTYPE_HVM) disk->bus = VIR_DOMAIN_DISK_BUS_XEN; else if (STRPREFIX(libxldisk->vdev, "sd")) disk->bus = VIR_DOMAIN_DISK_BUS_SCSI; else disk->bus = VIR_DOMAIN_DISK_BUS_IDE; if (VIR_APPEND_ELEMENT(def->disks, def->ndisks, disk) < 0) goto fail; libxl_device_disk_dispose(libxldisk); skipdisk: list = list->next; } } ret = 0; cleanup: virDomainDiskDefFree(disk); xlu_cfg_destroy(xluconf); VIR_FREE(libxldisk); return ret; fail: libxl_device_disk_dispose(libxldisk); goto cleanup; }
static int testQemuDiskXMLToProps(const void *opaque) { struct testQemuDiskXMLToJSONData *data = (void *) opaque; virDomainDiskDefPtr disk = NULL; virStorageSourcePtr n; virJSONValuePtr formatProps = NULL; virJSONValuePtr storageProps = NULL; char *xmlpath = NULL; char *xmlstr = NULL; int ret = -1; if (virAsprintf(&xmlpath, "%s%s.xml", testQemuDiskXMLToJSONPath, data->name) < 0) goto cleanup; if (virTestLoadFile(xmlpath, &xmlstr) < 0) goto cleanup; /* qemu stores node names in the status XML portion */ if (!(disk = virDomainDiskDefParse(xmlstr, NULL, data->driver->xmlopt, VIR_DOMAIN_DEF_PARSE_STATUS))) goto cleanup; if (qemuCheckDiskConfig(disk, data->qemuCaps) < 0 || qemuDomainDeviceDefValidateDisk(disk, data->qemuCaps) < 0) { VIR_TEST_VERBOSE("invalid configuration for disk\n"); goto cleanup; } for (n = disk->src; virStorageSourceIsBacking(n); n = n->backingStore) { if (testQemuDiskXMLToJSONFakeSecrets(n) < 0) goto cleanup; if (qemuDomainValidateStorageSource(n, data->qemuCaps) < 0) goto cleanup; if (qemuDomainPrepareDiskSourceData(disk, n, NULL, data->qemuCaps) < 0) goto cleanup; if (!(formatProps = qemuBlockStorageSourceGetBlockdevProps(n)) || !(storageProps = qemuBlockStorageSourceGetBackendProps(n, false))) { if (!data->fail) { VIR_TEST_VERBOSE("failed to generate qemu blockdev props\n"); goto cleanup; } } else if (data->fail) { VIR_TEST_VERBOSE("qemu blockdev props should have failed\n"); goto cleanup; } if (VIR_APPEND_ELEMENT(data->props, data->nprops, formatProps) < 0 || VIR_APPEND_ELEMENT(data->props, data->nprops, storageProps) < 0) goto cleanup; } ret = 0; cleanup: virJSONValueFree(formatProps); virJSONValueFree(storageProps); virDomainDiskDefFree(disk); VIR_FREE(xmlpath); VIR_FREE(xmlstr); return ret; }
static int bhyveParsePCIDisk(virDomainDefPtr def, unsigned caps ATTRIBUTE_UNUSED, unsigned pcislot, unsigned pcibus, unsigned function, int bus, int device, unsigned *nvirtiodisk, unsigned *nahcidisk, char *config) { /* -s slot,virtio-blk|ahci-cd|ahci-hd,/path/to/file */ const char *separator = NULL; int idx = -1; virDomainDiskDefPtr disk = NULL; if (VIR_ALLOC(disk) < 0) goto cleanup; if (VIR_ALLOC(disk->src) < 0) goto error; disk->bus = bus; disk->device = device; disk->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI; disk->info.addr.pci.slot = pcislot; disk->info.addr.pci.bus = pcibus; disk->info.addr.pci.function = function; if (STRPREFIX(config, "/dev/")) disk->src->type = VIR_STORAGE_TYPE_BLOCK; else disk->src->type = VIR_STORAGE_TYPE_FILE; if (!config) goto error; separator = strchr(config, ','); if (VIR_STRNDUP(disk->src->path, config, separator? separator - config : -1) < 0) goto error; if (bus == VIR_DOMAIN_DISK_BUS_VIRTIO) { idx = *nvirtiodisk; *nvirtiodisk += 1; if (VIR_STRDUP(disk->dst, "vda") < 0) goto error; } else if (bus == VIR_DOMAIN_DISK_BUS_SATA) { idx = *nahcidisk; *nahcidisk += 1; if (VIR_STRDUP(disk->dst, "sda") < 0) goto error; } if (idx > 'z' - 'a') { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("too many disks")); goto error; } disk->dst[2] = 'a' + idx; if (VIR_APPEND_ELEMENT(def->disks, def->ndisks, disk) < 0) goto error; cleanup: return 0; error: virDomainDiskDefFree(disk); 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; }