示例#1
0
/**
 * 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);
}
示例#2
0
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;
}
示例#3
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;
}
示例#4
0
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;
}
示例#5
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;
}
示例#6
0
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;
}
示例#7
0
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;
}
示例#8
0
/**
 * 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);
}
示例#9
0
/* 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;
}
示例#10
0
/*
 * 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;
}
示例#11
0
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;
}
示例#12
0
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;
}