示例#1
0
static void
virDomainSnapshotDiskDefFormat(virBufferPtr buf,
                               virDomainSnapshotDiskDefPtr disk)
{
    int type = disk->src->type;

    if (!disk->name)
        return;

    virBufferEscapeString(buf, "<disk name='%s'", disk->name);
    if (disk->snapshot > 0)
        virBufferAsprintf(buf, " snapshot='%s'",
                          virDomainSnapshotLocationTypeToString(disk->snapshot));

    if (!disk->src->path && disk->src->format == 0) {
        virBufferAddLit(buf, "/>\n");
        return;
    }

    virBufferAsprintf(buf, " type='%s'>\n", virStorageTypeToString(type));
    virBufferAdjustIndent(buf, 2);

    if (disk->src->format > 0)
        virBufferEscapeString(buf, "<driver type='%s'/>\n",
                              virStorageFileFormatTypeToString(disk->src->format));
    virDomainDiskSourceFormat(buf, disk->src, 0, 0);

    virBufferAdjustIndent(buf, -2);
    virBufferAddLit(buf, "</disk>\n");
}
示例#2
0
virStorageFileBackendPtr
virStorageFileBackendForTypeInternal(int type,
                                     int protocol,
                                     bool report)
{
    size_t i;

    for (i = 0; i < virStorageFileBackendsCount; i++) {
        if (virStorageFileBackends[i]->type == type) {
            if (type == VIR_STORAGE_TYPE_NETWORK &&
                virStorageFileBackends[i]->protocol != protocol)
                continue;

            return virStorageFileBackends[i];
        }
    }

    if (!report)
        return NULL;

    if (type == VIR_STORAGE_TYPE_NETWORK) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("missing storage backend for network files "
                         "using %s protocol"),
                       virStorageNetProtocolTypeToString(protocol));
    } else {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("missing storage backend for '%s' storage"),
                       virStorageTypeToString(type));
    }

    return NULL;
}
示例#3
0
int
qemuTeardownImageCgroup(virDomainObjPtr vm,
                        virStorageSourcePtr src)
{
    qemuDomainObjPrivatePtr priv = vm->privateData;
    int perms = VIR_CGROUP_DEVICE_READ |
                VIR_CGROUP_DEVICE_WRITE |
                VIR_CGROUP_DEVICE_MKNOD;
    int ret;

    if (!virCgroupHasController(priv->cgroup,
                                VIR_CGROUP_CONTROLLER_DEVICES))
        return 0;

    if (!src->path || !virStorageSourceIsLocalStorage(src)) {
        VIR_DEBUG("Not updating cgroups for disk path '%s', type: %s",
                  NULLSTR(src->path), virStorageTypeToString(src->type));
        return 0;
    }

    VIR_DEBUG("Deny path %s", src->path);

    ret = virCgroupDenyDevicePath(priv->cgroup, src->path, perms, true);

    virDomainAuditCgroupPath(vm, priv->cgroup, "deny", src->path,
                             virCgroupGetDevicePermsString(perms), ret == 0);

    return ret;
}
示例#4
0
int
qemuTeardownImageCgroup(virDomainObjPtr vm,
                        virStorageSourcePtr src)
{
    qemuDomainObjPrivatePtr priv = vm->privateData;
    int perms = VIR_CGROUP_DEVICE_RWM;
    size_t i;
    int ret;

    if (!virCgroupHasController(priv->cgroup,
                                VIR_CGROUP_CONTROLLER_DEVICES))
        return 0;

    if (!src->path || !virStorageSourceIsLocalStorage(src)) {
        VIR_DEBUG("Not updating cgroups for disk path '%s', type: %s",
                  NULLSTR(src->path), virStorageTypeToString(src->type));
        return 0;
    }

    if (virFileExists(DEVICE_MAPPER_CONTROL_PATH)) {
        for (i = 0; i < vm->def->ndisks; i++) {
            virStorageSourcePtr diskSrc = vm->def->disks[i]->src;

            if (src == diskSrc)
                continue;

            if (virStoragePRDefIsManaged(diskSrc->pr))
                break;
        }

        if (i == vm->def->ndisks) {
            VIR_DEBUG("Disabling device mapper control");
            ret = virCgroupDenyDevicePath(priv->cgroup,
                                          DEVICE_MAPPER_CONTROL_PATH, perms, true);
            virDomainAuditCgroupPath(vm, priv->cgroup, "deny",
                                     DEVICE_MAPPER_CONTROL_PATH,
                                     virCgroupGetDevicePermsString(perms), ret);
            if (ret < 0)
                return ret;
        }
    }

    VIR_DEBUG("Deny path %s", src->path);

    ret = virCgroupDenyDevicePath(priv->cgroup, src->path, perms, true);

    virDomainAuditCgroupPath(vm, priv->cgroup, "deny", src->path,
                             virCgroupGetDevicePermsString(perms), ret);

    /* If you're looking for a counter part to
     * qemuSetupImagePathCgroup you're at the right place.
     * However, we can't just blindly deny all the device mapper
     * targets of src->path because they might still be used by
     * another disk in domain. Just like we are not removing
     * disks from namespace. */

    return ret;
}
示例#5
0
int
virStorageFileBackendRegister(virStorageFileBackendPtr backend)
{
    VIR_DEBUG("Registering storage file backend '%s' protocol '%s'",
              virStorageTypeToString(backend->type),
              virStorageNetProtocolTypeToString(backend->protocol));

    if (virStorageFileBackendsCount >= VIR_STORAGE_BACKENDS_MAX) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Too many drivers, cannot register storage file "
                         "backend '%s'"),
                       virStorageTypeToString(backend->type));
        return -1;
    }

    virStorageFileBackends[virStorageFileBackendsCount] = backend;
    virStorageFileBackendsCount++;
    return 0;
}
示例#6
0
static int
qemuSetImageCgroupInternal(virDomainObjPtr vm,
                           virStorageSourcePtr src,
                           bool deny,
                           bool forceReadonly)
{
    qemuDomainObjPrivatePtr priv = vm->privateData;
    int perms = VIR_CGROUP_DEVICE_READ;
    int ret;

    if (!virCgroupHasController(priv->cgroup,
                                VIR_CGROUP_CONTROLLER_DEVICES))
        return 0;

    if (!src->path || !virStorageSourceIsLocalStorage(src)) {
        VIR_DEBUG("Not updating cgroups for disk path '%s', type: %s",
                  NULLSTR(src->path), virStorageTypeToString(src->type));
        return 0;
    }

    if (deny) {
        perms |= VIR_CGROUP_DEVICE_WRITE | VIR_CGROUP_DEVICE_MKNOD;

        VIR_DEBUG("Deny path %s", src->path);

        ret = virCgroupDenyDevicePath(priv->cgroup, src->path, perms);
    } else {
        if (!src->readonly && !forceReadonly)
            perms |= VIR_CGROUP_DEVICE_WRITE;

        VIR_DEBUG("Allow path %s, perms: %s",
                  src->path, virCgroupGetDevicePermsString(perms));

        ret = virCgroupAllowDevicePath(priv->cgroup, src->path, perms);
    }

    virDomainAuditCgroupPath(vm, priv->cgroup,
                             deny ? "deny" : "allow",
                             src->path,
                             virCgroupGetDevicePermsString(perms),
                             ret == 0);

    /* Get this for root squash NFS */
    if (ret < 0 &&
        virLastErrorIsSystemErrno(EACCES)) {
        VIR_DEBUG("Ignoring EACCES for %s", src->path);
        virResetLastError();
        ret = 0;
    }

    return ret;
}
示例#7
0
static int
qemuSetupImageCgroupInternal(virDomainObjPtr vm,
                             virStorageSourcePtr src,
                             bool forceReadonly)
{
    if (!src->path || !virStorageSourceIsLocalStorage(src)) {
        VIR_DEBUG("Not updating cgroups for disk path '%s', type: %s",
                  NULLSTR(src->path), virStorageTypeToString(src->type));
        return 0;
    }

    return qemuSetupImagePathCgroup(vm, src->path, src->readonly || forceReadonly);
}
示例#8
0
static int
qemuSetupImageCgroupInternal(virDomainObjPtr vm,
                             virStorageSourcePtr src,
                             bool forceReadonly)
{
    if (!src->path || !virStorageSourceIsLocalStorage(src)) {
        VIR_DEBUG("Not updating cgroups for disk path '%s', type: %s",
                  NULLSTR(src->path), virStorageTypeToString(src->type));
        return 0;
    }

    if (virStoragePRDefIsManaged(src->pr) &&
        virFileExists(DEVICE_MAPPER_CONTROL_PATH) &&
        qemuSetupImagePathCgroup(vm, DEVICE_MAPPER_CONTROL_PATH, false) < 0)
        return -1;

    return qemuSetupImagePathCgroup(vm, src->path, src->readonly || forceReadonly);
}
示例#9
0
int
virStorageFileBackendForType(int type,
                             int protocol,
                             bool required,
                             virStorageFileBackendPtr *backend)
{
    size_t i;

    *backend = NULL;

    if (virStorageFileBackendInitialize() < 0)
        return -1;

    for (i = 0; i < virStorageFileBackendsCount; i++) {
        if (virStorageFileBackends[i]->type == type) {
            if (type == VIR_STORAGE_TYPE_NETWORK &&
                virStorageFileBackends[i]->protocol != protocol)
                continue;

            *backend = virStorageFileBackends[i];
            return 0;
        }
    }

    if (!required)
        return 0;

    if (type == VIR_STORAGE_TYPE_NETWORK) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("missing storage backend for network files "
                         "using %s protocol"),
                       virStorageNetProtocolTypeToString(protocol));
    } else {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("missing storage backend for '%s' storage"),
                       virStorageTypeToString(type));
    }

    return -1;
}
示例#10
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;
}
示例#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;
}