Exemple #1
0
/*
 * 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;
}
Exemple #2
0
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;
}