Beispiel #1
0
virCPUDefPtr
virCPUDefParseXML(const xmlNodePtr node,
                  xmlXPathContextPtr ctxt,
                  enum virCPUType mode)
{
    virCPUDefPtr def;
    xmlNodePtr *nodes = NULL;
    int n;
    unsigned int i;
    char *cpuMode;

    if (!xmlStrEqual(node->name, BAD_CAST "cpu")) {
        virCPUReportError(VIR_ERR_INTERNAL_ERROR,
                          "%s",
                          _("XML does not contain expected 'cpu' element"));
        return NULL;
    }

    if (VIR_ALLOC(def) < 0) {
        virReportOOMError();
        return NULL;
    }

    if (mode == VIR_CPU_TYPE_AUTO) {
        if (virXPathBoolean("boolean(./arch)", ctxt)) {
            if (virXPathBoolean("boolean(./@match)", ctxt)) {
                virCPUReportError(VIR_ERR_XML_ERROR, "%s",
                        _("'arch' element element cannot be used inside 'cpu'"
                          " element with 'match' attribute'"));
                goto error;
            }
            def->type = VIR_CPU_TYPE_HOST;
        } else {
            def->type = VIR_CPU_TYPE_GUEST;
        }
    } else {
        def->type = mode;
    }

    if ((cpuMode = virXMLPropString(node, "mode"))) {
        if (def->type == VIR_CPU_TYPE_HOST) {
            VIR_FREE(cpuMode);
            virCPUReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                              _("Attribute mode is only allowed for guest CPU"));
            goto error;
        } else {
            def->mode = virCPUModeTypeFromString(cpuMode);

            if (def->mode < 0) {
                virCPUReportError(VIR_ERR_INTERNAL_ERROR,
                                  _("Invalid mode attribute '%s'"),
                                  cpuMode);
                VIR_FREE(cpuMode);
                goto error;
            }
            VIR_FREE(cpuMode);
        }
    } else {
        if (def->type == VIR_CPU_TYPE_HOST)
            def->mode = -1;
        else
            def->mode = VIR_CPU_MODE_CUSTOM;
    }

    if (def->type == VIR_CPU_TYPE_GUEST) {
        char *match = virXMLPropString(node, "match");

        if (!match) {
            if (virXPathBoolean("boolean(./model)", ctxt))
                def->match = VIR_CPU_MATCH_EXACT;
            else
                def->match = -1;
        } else {
            def->match = virCPUMatchTypeFromString(match);
            VIR_FREE(match);

            if (def->match < 0) {
                virCPUReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("Invalid match attribute for CPU specification"));
                goto error;
            }
        }
    }

    if (def->type == VIR_CPU_TYPE_HOST) {
        def->arch = virXPathString("string(./arch[1])", ctxt);
        if (!def->arch) {
            virCPUReportError(VIR_ERR_INTERNAL_ERROR,
                    "%s", _("Missing CPU architecture"));
            goto error;
        }
    }

    if (!(def->model = virXPathString("string(./model[1])", ctxt)) &&
        def->type == VIR_CPU_TYPE_HOST) {
        virCPUReportError(VIR_ERR_INTERNAL_ERROR,
                "%s", _("Missing CPU model name"));
        goto error;
    }

    if (def->type == VIR_CPU_TYPE_GUEST &&
        def->mode != VIR_CPU_MODE_HOST_PASSTHROUGH &&
        virXPathBoolean("boolean(./model[1]/@fallback)", ctxt)) {
        const char *fallback;

        fallback = virXPathString("string(./model[1]/@fallback)", ctxt);
        if (fallback) {
            def->fallback = virCPUFallbackTypeFromString(fallback);
            VIR_FREE(fallback);
            if (def->fallback < 0) {
                virCPUReportError(VIR_ERR_XML_ERROR, "%s",
                                  _("Invalid fallback attribute"));
                goto error;
            }
        }
    }

    def->vendor = virXPathString("string(./vendor[1])", ctxt);
    if (def->vendor && !def->model) {
        virCPUReportError(VIR_ERR_INTERNAL_ERROR,
                "%s", _("CPU vendor specified without CPU model"));
        goto error;
    }

    if (virXPathNode("./topology[1]", ctxt)) {
        int ret;
        unsigned long ul;

        ret = virXPathULong("string(./topology[1]/@sockets)",
                            ctxt, &ul);
        if (ret < 0) {
            virCPUReportError(VIR_ERR_INTERNAL_ERROR,
                    "%s", _("Missing 'sockets' attribute in CPU topology"));
            goto error;
        }
        def->sockets = (unsigned int) ul;

        ret = virXPathULong("string(./topology[1]/@cores)",
                            ctxt, &ul);
        if (ret < 0) {
            virCPUReportError(VIR_ERR_INTERNAL_ERROR,
                    "%s", _("Missing 'cores' attribute in CPU topology"));
            goto error;
        }
        def->cores = (unsigned int) ul;

        ret = virXPathULong("string(./topology[1]/@threads)",
                            ctxt, &ul);
        if (ret < 0) {
            virCPUReportError(VIR_ERR_INTERNAL_ERROR,
                    "%s", _("Missing 'threads' attribute in CPU topology"));
            goto error;
        }
        def->threads = (unsigned int) ul;

        if (!def->sockets || !def->cores || !def->threads) {
            virCPUReportError(VIR_ERR_INTERNAL_ERROR,
                    "%s", _("Invalid CPU topology"));
            goto error;
        }
    }

    n = virXPathNodeSet("./feature", ctxt, &nodes);
    if (n < 0)
        goto error;

    if (n > 0) {
        if (!def->model) {
            virCPUReportError(VIR_ERR_INTERNAL_ERROR,
                    "%s", _("Non-empty feature list specified without CPU model"));
            goto error;
        }

        if (VIR_RESIZE_N(def->features, def->nfeatures_max,
                         def->nfeatures, n) < 0)
            goto no_memory;
        def->nfeatures = n;
    }

    for (i = 0 ; i < n ; i++) {
        char *name;
        int policy; /* enum virDomainCPUFeaturePolicy */
        unsigned int j;

        if (def->type == VIR_CPU_TYPE_GUEST) {
            char *strpolicy;

            strpolicy = virXMLPropString(nodes[i], "policy");
            if (strpolicy == NULL)
                policy = VIR_CPU_FEATURE_REQUIRE;
            else
                policy = virCPUFeaturePolicyTypeFromString(strpolicy);
            VIR_FREE(strpolicy);

            if (policy < 0) {
                virCPUReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("Invalid CPU feature policy"));
                goto error;
            }
        } else {
            policy = -1;
        }

        if (!(name = virXMLPropString(nodes[i], "name")) || *name == 0) {
            VIR_FREE(name);
            virCPUReportError(VIR_ERR_INTERNAL_ERROR,
                    "%s", _("Invalid CPU feature name"));
            goto error;
        }

        for (j = 0 ; j < i ; j++) {
            if (STREQ(name, def->features[j].name)) {
                virCPUReportError(VIR_ERR_INTERNAL_ERROR,
                        _("CPU feature `%s' specified more than once"),
                        name);
                VIR_FREE(name);
                goto error;
            }
        }

        def->features[i].name = name;
        def->features[i].policy = policy;
    }

    if (virXPathNode("./numa[1]", ctxt)) {
        VIR_FREE(nodes);
        n = virXPathNodeSet("./numa[1]/cell", ctxt, &nodes);
        if (n <= 0) {
            virCPUReportError(VIR_ERR_INTERNAL_ERROR,
                    "%s", _("NUMA topology defined without NUMA cells"));
            goto error;
        }

        if (VIR_RESIZE_N(def->cells, def->ncells_max,
                         def->ncells, n) < 0)
            goto no_memory;

        def->ncells = n;

        for (i = 0 ; i < n ; i++) {
            char *cpus, *memory;
            int cpumasklen = VIR_DOMAIN_CPUMASK_LEN;
            int ret, ncpus = 0;

            def->cells[i].cellid = i;
            cpus = virXMLPropString(nodes[i], "cpus");
            if (!cpus) {
                virCPUReportError(VIR_ERR_INTERNAL_ERROR,
                    "%s", _("Missing 'cpus' attribute in NUMA cell"));
                goto error;
            }
            def->cells[i].cpustr = cpus;

            if (VIR_ALLOC_N(def->cells[i].cpumask, cpumasklen) < 0)
                goto no_memory;

            ncpus = virDomainCpuSetParse(cpus, 0, def->cells[i].cpumask,
                                         cpumasklen);
            if (ncpus <= 0)
                goto error;
            def->cells_cpus += ncpus;

            memory = virXMLPropString(nodes[i], "memory");
            if (!memory) {
                virCPUReportError(VIR_ERR_INTERNAL_ERROR,
                    "%s", _("Missing 'memory' attribute in NUMA cell"));
                goto error;
            }

            ret  = virStrToLong_ui(memory, NULL, 10, &def->cells[i].mem);
            if (ret == -1) {
                virCPUReportError(VIR_ERR_INTERNAL_ERROR,
                    "%s", _("Invalid 'memory' attribute in NUMA cell"));
                VIR_FREE(memory);
                goto error;
            }
            VIR_FREE(memory);
        }
    }

cleanup:
    VIR_FREE(nodes);
    return def;

no_memory:
    virReportOOMError();

error:
    virCPUDefFree(def);
    def = NULL;
    goto cleanup;
}
static int
virStorageBackendLogicalMakeVol(virStoragePoolObjPtr pool,
                                char **const groups,
                                void *data)
{
    virStorageVolDefPtr vol = NULL;
    unsigned long long offset, size, length;

    /* See if we're only looking for a specific volume */
    if (data != NULL) {
        vol = data;
        if (STRNEQ(vol->name, groups[0]))
            return 0;
    }

    /* Or filling in more data on an existing volume */
    if (vol == NULL)
        vol = virStorageVolDefFindByName(pool, groups[0]);

    /* Or a completely new volume */
    if (vol == NULL) {
        if (VIR_ALLOC(vol) < 0) {
            virReportOOMError();
            return -1;
        }

        vol->type = VIR_STORAGE_VOL_BLOCK;

        if ((vol->name = strdup(groups[0])) == NULL) {
            virReportOOMError();
            virStorageVolDefFree(vol);
            return -1;
        }

        if (VIR_REALLOC_N(pool->volumes.objs,
                          pool->volumes.count + 1)) {
            virReportOOMError();
            virStorageVolDefFree(vol);
            return -1;
        }
        pool->volumes.objs[pool->volumes.count++] = vol;
    }

    if (vol->target.path == NULL) {
        if (virAsprintf(&vol->target.path, "%s/%s",
                        pool->def->target.path, vol->name) < 0) {
            virReportOOMError();
            virStorageVolDefFree(vol);
            return -1;
        }
    }

    if (groups[1] && !STREQ(groups[1], "")) {
        if (virAsprintf(&vol->backingStore.path, "%s/%s",
                        pool->def->target.path, groups[1]) < 0) {
            virReportOOMError();
            virStorageVolDefFree(vol);
            return -1;
        }

        vol->backingStore.format = VIR_STORAGE_POOL_LOGICAL_LVM2;
    }

    if (vol->key == NULL &&
        (vol->key = strdup(groups[2])) == NULL) {
        virReportOOMError();
        return -1;
    }

    if (virStorageBackendUpdateVolInfo(vol, 1) < 0)
        return -1;


    /* Finally fill in extents information */
    if (VIR_REALLOC_N(vol->source.extents,
                      vol->source.nextent + 1) < 0) {
        virReportOOMError();
        return -1;
    }

    if ((vol->source.extents[vol->source.nextent].path =
         strdup(groups[3])) == NULL) {
        virReportOOMError();
        return -1;
    }

    if (virStrToLong_ull(groups[4], NULL, 10, &offset) < 0) {
        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
                              "%s", _("malformed volume extent offset value"));
        return -1;
    }
    if (virStrToLong_ull(groups[5], NULL, 10, &length) < 0) {
        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
                              "%s", _("malformed volume extent length value"));
        return -1;
    }
    if (virStrToLong_ull(groups[6], NULL, 10, &size) < 0) {
        virStorageReportError(VIR_ERR_INTERNAL_ERROR,
                              "%s", _("malformed volume extent size value"));
        return -1;
    }

    vol->source.extents[vol->source.nextent].start = offset * size;
    vol->source.extents[vol->source.nextent].end = (offset * size) + length;
    vol->source.nextent++;

    return 0;
}
Beispiel #3
0
/*
 * Attempt to create a new LUN
 *
 * Returns:
 *
 *  0  => Success
 *  -1 => Failure due to some sort of OOM or other fatal issue found when
 *        attempting to get/update information about a found volume
 *  -2 => Failure to find a stable path, not fatal, caller can try another
 */
static int
virStorageBackendSCSINewLun(virStoragePoolObjPtr pool,
                            uint32_t host ATTRIBUTE_UNUSED,
                            uint32_t bus,
                            uint32_t target,
                            uint32_t lun,
                            const char *dev)
{
    virStorageVolDefPtr vol = NULL;
    char *devpath = NULL;
    int retval = -1;

    /* Check if the pool is using a stable target path. The call to
     * virStorageBackendStablePath will fail if the pool target path
     * isn't stable and just return the strdup'd 'devpath' anyway.
     * This would be indistinguishable to failing to find the stable
     * path to the device if the virDirRead loop to search the
     * target pool path for our devpath had failed.
     */
    if (!virStorageBackendPoolPathIsStable(pool->def->target.path) &&
        !(STREQ(pool->def->target.path, "/dev") ||
          STREQ(pool->def->target.path, "/dev/"))) {
        virReportError(VIR_ERR_INVALID_ARG,
                       _("unable to use target path '%s' for dev '%s'"),
                       NULLSTR(pool->def->target.path), dev);
        goto cleanup;
    }

    if (VIR_ALLOC(vol) < 0)
        goto cleanup;

    vol->type = VIR_STORAGE_VOL_BLOCK;

    /* 'host' is dynamically allocated by the kernel, first come,
     * first served, per HBA. As such it isn't suitable for use
     * in the volume name. We only need uniqueness per-pool, so
     * just leave 'host' out
     */
    if (virAsprintf(&(vol->name), "unit:%u:%u:%u", bus, target, lun) < 0)
        goto cleanup;

    if (virAsprintf(&devpath, "/dev/%s", dev) < 0)
        goto cleanup;

    VIR_DEBUG("Trying to create volume for '%s'", devpath);

    /* Now figure out the stable path
     *
     * XXX this method is O(N) because it scans the pool target
     * dir every time its run. Should figure out a more efficient
     * way of doing this...
     */
    if ((vol->target.path = virStorageBackendStablePath(pool,
                                                        devpath,
                                                        true)) == NULL)
        goto cleanup;

    if (STREQ(devpath, vol->target.path) &&
        !(STREQ(pool->def->target.path, "/dev") ||
          STREQ(pool->def->target.path, "/dev/"))) {

        VIR_DEBUG("No stable path found for '%s' in '%s'",
                  devpath, pool->def->target.path);

        retval = -2;
        goto cleanup;
    }

    /* Allow a volume read failure to ignore or skip this block file */
    if ((retval = virStorageBackendUpdateVolInfo(vol, true,
                                                 VIR_STORAGE_VOL_OPEN_DEFAULT,
                                                 VIR_STORAGE_VOL_READ_NOERROR)) < 0)
        goto cleanup;

    if (!(vol->key = virStorageBackendSCSISerial(vol->target.path)))
        goto cleanup;

    pool->def->capacity += vol->target.capacity;
    pool->def->allocation += vol->target.allocation;

    if (VIR_APPEND_ELEMENT(pool->volumes.objs, pool->volumes.count, vol) < 0)
        goto cleanup;

    vol = NULL;
    retval = 0;

 cleanup:
    virStorageVolDefFree(vol);
    VIR_FREE(devpath);
    return retval;
}
Beispiel #4
0
static int
xenFormatXLUSB(virConfPtr conf,
               virDomainDefPtr def)
{
    virConfValuePtr usbVal = NULL;
    int hasUSB = 0;
    size_t i;

    for (i = 0; i < def->nhostdevs; i++) {
        if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
            def->hostdevs[i]->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
            hasUSB = 1;
            break;
        }
    }

    if (!hasUSB)
        return 0;

    if (VIR_ALLOC(usbVal) < 0)
        return -1;

    usbVal->type = VIR_CONF_LIST;
    usbVal->list = NULL;

    for (i = 0; i < def->nhostdevs; i++) {
        if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
            def->hostdevs[i]->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
            virConfValuePtr val, tmp;
            char *buf;

            if (virAsprintf(&buf, "hostbus=%x,hostaddr=%x",
                            def->hostdevs[i]->source.subsys.u.usb.bus,
                            def->hostdevs[i]->source.subsys.u.usb.device) < 0)
                goto error;

            if (VIR_ALLOC(val) < 0) {
                VIR_FREE(buf);
                goto error;
            }
            val->type = VIR_CONF_STRING;
            val->str = buf;
            tmp = usbVal->list;
            while (tmp && tmp->next)
                tmp = tmp->next;
            if (tmp)
                tmp->next = val;
            else
                usbVal->list = val;
        }
    }

    if (usbVal->list != NULL) {
        int ret = virConfSetValue(conf, "usbdev", usbVal);
        usbVal = NULL;
        if (ret < 0)
            return -1;
    }
    VIR_FREE(usbVal);

    return 0;

 error:
    virConfFreeValue(usbVal);
    return -1;
}
Beispiel #5
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;
}
Beispiel #6
0
/* Functions */
virCapsPtr virLXCDriverCapsInit(virLXCDriverPtr driver)
{
    virCapsPtr caps;
    virCapsGuestPtr guest;
    virArch altArch;
    char *lxc_path = NULL;

    if ((caps = virCapabilitiesNew(virArchFromHost(),
                                   false, false)) == NULL)
        goto error;

    /* Some machines have problematic NUMA toplogy causing
     * unexpected failures. We don't want to break the lxc
     * driver in this scenario, so log errors & carry on
     */
    if (nodeCapsInitNUMA(caps) < 0) {
        virCapabilitiesFreeNUMAInfo(caps);
        VIR_WARN("Failed to query host NUMA topology, disabling NUMA capabilities");
    }

    /* Only probe for power management capabilities in the driver,
     * not in the emulator */
    if (driver && virNodeSuspendGetTargetMask(&caps->host.powerMgmt) < 0)
        VIR_WARN("Failed to get host power management capabilities");

    if (virGetHostUUID(caps->host.host_uuid)) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("cannot get the host uuid"));
        goto error;
    }

    if (!(lxc_path = virFileFindResource("libvirt_lxc",
                                         abs_topbuilddir "/src",
                                         LIBEXECDIR)))
        goto error;

    if ((guest = virCapabilitiesAddGuest(caps,
                                         VIR_DOMAIN_OSTYPE_EXE,
                                         caps->host.arch,
                                         lxc_path,
                                         NULL,
                                         0,
                                         NULL)) == NULL)
        goto error;

    if (virCapabilitiesAddGuestDomain(guest,
                                      VIR_DOMAIN_VIRT_LXC,
                                      NULL,
                                      NULL,
                                      0,
                                      NULL) == NULL)
        goto error;

    /* On 64-bit hosts, we can use personality() to request a 32bit process */
    if ((altArch = lxcContainerGetAlt32bitArch(caps->host.arch)) != VIR_ARCH_NONE) {
        if ((guest = virCapabilitiesAddGuest(caps,
                                             VIR_DOMAIN_OSTYPE_EXE,
                                             altArch,
                                             lxc_path,
                                             NULL,
                                             0,
                                             NULL)) == NULL)
            goto error;

        if (virCapabilitiesAddGuestDomain(guest,
                                          VIR_DOMAIN_VIRT_LXC,
                                          NULL,
                                          NULL,
                                          0,
                                          NULL) == NULL)
            goto error;
    }

    VIR_FREE(lxc_path);

    if (driver) {
        /* Security driver data */
        const char *doi, *model, *label, *type;

        doi = virSecurityManagerGetDOI(driver->securityManager);
        model = virSecurityManagerGetModel(driver->securityManager);
        label = virSecurityManagerGetBaseLabel(driver->securityManager,
                                               VIR_DOMAIN_VIRT_LXC);
        type = virDomainVirtTypeToString(VIR_DOMAIN_VIRT_LXC);
        /* Allocate the primary security driver for LXC. */
        if (VIR_ALLOC(caps->host.secModels) < 0)
            goto error;
        caps->host.nsecModels = 1;
        if (VIR_STRDUP(caps->host.secModels[0].model, model) < 0)
            goto error;
        if (VIR_STRDUP(caps->host.secModels[0].doi, doi) < 0)
            goto error;
        if (label &&
            virCapabilitiesHostSecModelAddBaseLabel(&caps->host.secModels[0],
                                                    type,
                                                    label) < 0)
            goto error;

        VIR_DEBUG("Initialized caps for security driver \"%s\" with "
                  "DOI \"%s\"", model, doi);
    } else {
        VIR_INFO("No driver, not initializing security driver");
    }

    return caps;

 error:
    VIR_FREE(lxc_path);
    virObjectUnref(caps);
    return NULL;
}
Beispiel #7
0
static int
xenParseXLOS(virConfPtr conf, virDomainDefPtr def, virCapsPtr caps)
{
    size_t i;

    if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
        const char *bios;
        const char *boot;

        if (xenConfigGetString(conf, "bios", &bios, NULL) < 0)
            return -1;

        if (bios && STREQ(bios, "ovmf")) {
            if (VIR_ALLOC(def->os.loader) < 0)
                return -1;

            def->os.loader->type = VIR_DOMAIN_LOADER_TYPE_PFLASH;
            def->os.loader->readonly = VIR_TRISTATE_BOOL_YES;

            if (VIR_STRDUP(def->os.loader->path,
                           LIBXL_FIRMWARE_DIR "/ovmf.bin") < 0)
                return -1;
        } else {
            for (i = 0; i < caps->nguests; i++) {
                if (caps->guests[i]->ostype == VIR_DOMAIN_OSTYPE_HVM &&
                    caps->guests[i]->arch.id == def->os.arch) {
                    if (VIR_ALLOC(def->os.loader) < 0 ||
                        VIR_STRDUP(def->os.loader->path,
                                   caps->guests[i]->arch.defaultInfo.loader) < 0)
                        return -1;
                }
            }
        }

#ifdef LIBXL_HAVE_BUILDINFO_KERNEL
        if (xenConfigCopyStringOpt(conf, "kernel", &def->os.kernel) < 0)
            return -1;

        if (xenConfigCopyStringOpt(conf, "ramdisk", &def->os.initrd) < 0)
            return -1;

        if (xenParseCmdline(conf, &def->os.cmdline) < 0)
            return -1;
#endif

        if (xenConfigGetString(conf, "boot", &boot, "c") < 0)
            return -1;

        for (i = 0; i < VIR_DOMAIN_BOOT_LAST && boot[i]; i++) {
            switch (boot[i]) {
            case 'a':
                def->os.bootDevs[i] = VIR_DOMAIN_BOOT_FLOPPY;
                break;
            case 'd':
                def->os.bootDevs[i] = VIR_DOMAIN_BOOT_CDROM;
                break;
            case 'n':
                def->os.bootDevs[i] = VIR_DOMAIN_BOOT_NET;
                break;
            case 'c':
            default:
                def->os.bootDevs[i] = VIR_DOMAIN_BOOT_DISK;
                break;
            }
            def->os.nBootDevs++;
        }
    } else {
        if (xenConfigCopyStringOpt(conf, "bootloader", &def->os.bootloader) < 0)
            return -1;
        if (xenConfigCopyStringOpt(conf, "bootargs", &def->os.bootloaderArgs) < 0)
            return -1;

        if (xenConfigCopyStringOpt(conf, "kernel", &def->os.kernel) < 0)
            return -1;

        if (xenConfigCopyStringOpt(conf, "ramdisk", &def->os.initrd) < 0)
            return -1;

        if (xenParseCmdline(conf, &def->os.cmdline) < 0)
            return -1;
    }

    return 0;
}
Beispiel #8
0
virQEMUDriverConfigPtr virQEMUDriverConfigNew(bool privileged)
{
    virQEMUDriverConfigPtr cfg;

    if (virQEMUConfigInitialize() < 0)
        return NULL;

    if (!(cfg = virObjectNew(virQEMUDriverConfigClass)))
        return NULL;

    cfg->uri = privileged ? "qemu:///system" : "qemu:///session";

    if (privileged) {
        if (virGetUserID(QEMU_USER, &cfg->user) < 0)
            goto error;
        if (virGetGroupID(QEMU_GROUP, &cfg->group) < 0)
            goto error;
    } else {
        cfg->user = (uid_t)-1;
        cfg->group = (gid_t)-1;
    }
    cfg->dynamicOwnership = privileged;

    cfg->cgroupControllers = -1; /* -1 == auto-detect */

    if (privileged) {
        if (virAsprintf(&cfg->logDir,
                        "%s/log/libvirt/qemu", LOCALSTATEDIR) < 0)
            goto error;

        if (VIR_STRDUP(cfg->configBaseDir, SYSCONFDIR "/libvirt") < 0)
            goto error;

        if (virAsprintf(&cfg->stateDir,
                      "%s/run/libvirt/qemu", LOCALSTATEDIR) < 0)
            goto error;

        if (virAsprintf(&cfg->cacheDir,
                      "%s/cache/libvirt/qemu", LOCALSTATEDIR) < 0)
            goto error;

        if (virAsprintf(&cfg->libDir,
                      "%s/lib/libvirt/qemu", LOCALSTATEDIR) < 0)
            goto error;
        if (virAsprintf(&cfg->saveDir, "%s/save", cfg->libDir) < 0)
            goto error;
        if (virAsprintf(&cfg->snapshotDir, "%s/snapshot", cfg->libDir) < 0)
            goto error;
        if (virAsprintf(&cfg->autoDumpPath, "%s/dump", cfg->libDir) < 0)
            goto error;
        if (virAsprintf(&cfg->channelTargetDir,
                        "%s/channel/target", cfg->libDir) < 0)
            goto error;
        if (virAsprintf(&cfg->nvramDir, "%s/nvram", cfg->libDir) < 0)
            goto error;
    } else {
        char *rundir;
        char *cachedir;

        cachedir = virGetUserCacheDirectory();
        if (!cachedir)
            goto error;

        if (virAsprintf(&cfg->logDir,
                        "%s/qemu/log", cachedir) < 0) {
            VIR_FREE(cachedir);
            goto error;
        }
        if (virAsprintf(&cfg->cacheDir, "%s/qemu/cache", cachedir) < 0) {
            VIR_FREE(cachedir);
            goto error;
        }
        VIR_FREE(cachedir);

        rundir = virGetUserRuntimeDirectory();
        if (!rundir)
            goto error;
        if (virAsprintf(&cfg->stateDir, "%s/qemu/run", rundir) < 0) {
            VIR_FREE(rundir);
            goto error;
        }
        VIR_FREE(rundir);

        if (!(cfg->configBaseDir = virGetUserConfigDirectory()))
            goto error;

        if (virAsprintf(&cfg->libDir, "%s/qemu/lib", cfg->configBaseDir) < 0)
            goto error;
        if (virAsprintf(&cfg->saveDir, "%s/qemu/save", cfg->configBaseDir) < 0)
            goto error;
        if (virAsprintf(&cfg->snapshotDir, "%s/qemu/snapshot", cfg->configBaseDir) < 0)
            goto error;
        if (virAsprintf(&cfg->autoDumpPath, "%s/qemu/dump", cfg->configBaseDir) < 0)
            goto error;
        if (virAsprintf(&cfg->channelTargetDir,
                        "%s/qemu/channel/target", cfg->configBaseDir) < 0)
            goto error;
        if (virAsprintf(&cfg->nvramDir,
                        "%s/qemu/nvram", cfg->configBaseDir) < 0)
            goto error;
    }

    if (virAsprintf(&cfg->configDir, "%s/qemu", cfg->configBaseDir) < 0)
        goto error;
    if (virAsprintf(&cfg->autostartDir, "%s/qemu/autostart", cfg->configBaseDir) < 0)
        goto error;


    if (VIR_STRDUP(cfg->vncListen, "127.0.0.1") < 0)
        goto error;

    if (VIR_STRDUP(cfg->vncTLSx509certdir, SYSCONFDIR "/pki/libvirt-vnc") < 0)
        goto error;

    if (VIR_STRDUP(cfg->spiceListen, "127.0.0.1") < 0)
        goto error;

    if (VIR_STRDUP(cfg->spiceTLSx509certdir,
                   SYSCONFDIR "/pki/libvirt-spice") < 0)
        goto error;

    cfg->remotePortMin = QEMU_REMOTE_PORT_MIN;
    cfg->remotePortMax = QEMU_REMOTE_PORT_MAX;

    cfg->webSocketPortMin = QEMU_WEBSOCKET_PORT_MIN;
    cfg->webSocketPortMax = QEMU_WEBSOCKET_PORT_MAX;

    cfg->migrationPortMin = QEMU_MIGRATION_PORT_MIN;
    cfg->migrationPortMax = QEMU_MIGRATION_PORT_MAX;

    /* For privileged driver, try and find hugetlbfs mounts automatically.
     * Non-privileged driver requires admin to create a dir for the
     * user, chown it, and then let user configure it manually. */
    if (privileged &&
        virFileFindHugeTLBFS(&cfg->hugetlbfs, &cfg->nhugetlbfs) < 0) {
        /* This however is not implemented on all platforms. */
        virErrorPtr err = virGetLastError();
        if (err && err->code != VIR_ERR_NO_SUPPORT)
            goto error;
    }

    if (VIR_STRDUP(cfg->bridgeHelperName, QEMU_BRIDGE_HELPER) < 0)
        goto error;

    cfg->clearEmulatorCapabilities = true;

    cfg->securityDefaultConfined = true;
    cfg->securityRequireConfined = false;

    cfg->keepAliveInterval = 5;
    cfg->keepAliveCount = 5;
    cfg->seccompSandbox = -1;

    cfg->logTimestamp = true;
    cfg->stdioLogD = true;

#ifdef DEFAULT_LOADER_NVRAM
    if (virFirmwareParseList(DEFAULT_LOADER_NVRAM,
                             &cfg->firmwares,
                             &cfg->nfirmwares) < 0)
        goto error;

#else
    if (VIR_ALLOC_N(cfg->firmwares, 2) < 0)
        goto error;
    cfg->nfirmwares = 2;
    if (VIR_ALLOC(cfg->firmwares[0]) < 0 || VIR_ALLOC(cfg->firmwares[1]) < 0)
        goto error;

    if (VIR_STRDUP(cfg->firmwares[0]->name, VIR_QEMU_AAVMF_LOADER_PATH) < 0 ||
        VIR_STRDUP(cfg->firmwares[0]->nvram, VIR_QEMU_AAVMF_NVRAM_PATH) < 0  ||
        VIR_STRDUP(cfg->firmwares[1]->name, VIR_QEMU_OVMF_LOADER_PATH) < 0 ||
        VIR_STRDUP(cfg->firmwares[1]->nvram, VIR_QEMU_OVMF_NVRAM_PATH) < 0)
        goto error;
#endif

    return cfg;

 error:
    virObjectUnref(cfg);
    return NULL;
}
Beispiel #9
0
int virQEMUDriverConfigLoadFile(virQEMUDriverConfigPtr cfg,
                                const char *filename)
{
    virConfPtr conf = NULL;
    virConfValuePtr p;
    int ret = -1;
    size_t i;
    char *stdioHandler = NULL;

    /* Just check the file is readable before opening it, otherwise
     * libvirt emits an error.
     */
    if (access(filename, R_OK) == -1) {
        VIR_INFO("Could not read qemu config file %s", filename);
        return 0;
    }

    if (!(conf = virConfReadFile(filename, 0)))
        goto cleanup;

#define CHECK_TYPE(name, typ)                         \
    if (p && p->type != (typ)) {                      \
        virReportError(VIR_ERR_INTERNAL_ERROR,        \
                       "%s: %s: expected type " #typ, \
                       filename, (name));             \
        goto cleanup;                                 \
    }

#define CHECK_TYPE_ALT(name, type1, type2)                      \
    if (p && (p->type != (type1) && p->type != (type2))) {      \
        virReportError(VIR_ERR_INTERNAL_ERROR,                  \
                       "%s: %s: expected type " #type1,         \
                       filename, (name));                       \
        goto cleanup;                                           \
    }

#define GET_VALUE_LONG(NAME, VAR)                               \
    p = virConfGetValue(conf, NAME);                            \
    CHECK_TYPE_ALT(NAME, VIR_CONF_LONG, VIR_CONF_ULONG);        \
    if (p)                                                      \
        VAR = p->l;

#define GET_VALUE_ULONG(NAME, VAR)    \
    p = virConfGetValue(conf, NAME);  \
    CHECK_TYPE(NAME, VIR_CONF_ULONG); \
    if (p)                            \
        VAR = p->l;

#define GET_VALUE_BOOL(NAME, VAR)     \
    p = virConfGetValue(conf, NAME);  \
    CHECK_TYPE(NAME, VIR_CONF_ULONG); \
    if (p)                            \
        VAR = p->l != 0;

#define GET_VALUE_STR(NAME, VAR)           \
    p = virConfGetValue(conf, NAME);       \
    CHECK_TYPE(NAME, VIR_CONF_STRING);     \
    if (p && p->str) {                     \
        VIR_FREE(VAR);                     \
        if (VIR_STRDUP(VAR, p->str) < 0)   \
            goto cleanup;                  \
    }

    GET_VALUE_BOOL("vnc_auto_unix_socket", cfg->vncAutoUnixSocket);
    GET_VALUE_BOOL("vnc_tls", cfg->vncTLS);
    GET_VALUE_BOOL("vnc_tls_x509_verify", cfg->vncTLSx509verify);
    GET_VALUE_STR("vnc_tls_x509_cert_dir", cfg->vncTLSx509certdir);
    GET_VALUE_STR("vnc_listen", cfg->vncListen);
    GET_VALUE_STR("vnc_password", cfg->vncPassword);
    GET_VALUE_BOOL("vnc_sasl", cfg->vncSASL);
    GET_VALUE_STR("vnc_sasl_dir", cfg->vncSASLdir);
    GET_VALUE_BOOL("vnc_allow_host_audio", cfg->vncAllowHostAudio);
    GET_VALUE_BOOL("nographics_allow_host_audio", cfg->nogfxAllowHostAudio);

    p = virConfGetValue(conf, "security_driver");
    if (p && p->type == VIR_CONF_LIST) {
        size_t len, j;
        virConfValuePtr pp;

        /* Calc length and check items */
        for (len = 0, pp = p->list; pp; len++, pp = pp->next) {
            if (pp->type != VIR_CONF_STRING) {
                virReportError(VIR_ERR_CONF_SYNTAX, "%s",
                               _("security_driver must be a list of strings"));
                goto cleanup;
            }
        }

        if (VIR_ALLOC_N(cfg->securityDriverNames, len + 1) < 0)
            goto cleanup;

        for (i = 0, pp = p->list; pp; i++, pp = pp->next) {
            for (j = 0; j < i; j++) {
                if (STREQ(pp->str, cfg->securityDriverNames[j])) {
                    virReportError(VIR_ERR_CONF_SYNTAX,
                                   _("Duplicate security driver %s"), pp->str);
                    goto cleanup;
                }
            }
            if (VIR_STRDUP(cfg->securityDriverNames[i], pp->str) < 0)
                goto cleanup;
        }
        cfg->securityDriverNames[len] = NULL;
    } else {
        CHECK_TYPE("security_driver", VIR_CONF_STRING);
        if (p && p->str) {
            if (VIR_ALLOC_N(cfg->securityDriverNames, 2) < 0)
                goto cleanup;
            if (VIR_STRDUP(cfg->securityDriverNames[0], p->str) < 0)
                goto cleanup;

            cfg->securityDriverNames[1] = NULL;
        }
    }

    GET_VALUE_BOOL("security_default_confined", cfg->securityDefaultConfined);
    GET_VALUE_BOOL("security_require_confined", cfg->securityRequireConfined);

    GET_VALUE_BOOL("spice_tls", cfg->spiceTLS);
    GET_VALUE_STR("spice_tls_x509_cert_dir", cfg->spiceTLSx509certdir);
    GET_VALUE_BOOL("spice_sasl", cfg->spiceSASL);
    GET_VALUE_STR("spice_sasl_dir", cfg->spiceSASLdir);
    GET_VALUE_STR("spice_listen", cfg->spiceListen);
    GET_VALUE_STR("spice_password", cfg->spicePassword);
    GET_VALUE_BOOL("spice_auto_unix_socket", cfg->spiceAutoUnixSocket);


    GET_VALUE_ULONG("remote_websocket_port_min", cfg->webSocketPortMin);
    if (cfg->webSocketPortMin < QEMU_WEBSOCKET_PORT_MIN) {
        /* if the port is too low, we can't get the display name
         * to tell to vnc (usually subtract 5700, e.g. localhost:1
         * for port 5701) */
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("%s: remote_websocket_port_min: port must be greater "
                         "than or equal to %d"),
                        filename, QEMU_WEBSOCKET_PORT_MIN);
        goto cleanup;
    }

    GET_VALUE_ULONG("remote_websocket_port_max", cfg->webSocketPortMax);
    if (cfg->webSocketPortMax > QEMU_WEBSOCKET_PORT_MAX ||
        cfg->webSocketPortMax < cfg->webSocketPortMin) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("%s: remote_websocket_port_max: port must be between "
                          "the minimal port and %d"),
                       filename, QEMU_WEBSOCKET_PORT_MAX);
        goto cleanup;
    }

    if (cfg->webSocketPortMin > cfg->webSocketPortMax) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("%s: remote_websocket_port_min: min port must not be "
                          "greater than max port"), filename);
        goto cleanup;
    }

    GET_VALUE_ULONG("remote_display_port_min", cfg->remotePortMin);
    if (cfg->remotePortMin < QEMU_REMOTE_PORT_MIN) {
        /* if the port is too low, we can't get the display name
         * to tell to vnc (usually subtract 5900, e.g. localhost:1
         * for port 5901) */
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("%s: remote_display_port_min: port must be greater "
                         "than or equal to %d"),
                        filename, QEMU_REMOTE_PORT_MIN);
        goto cleanup;
    }

    GET_VALUE_ULONG("remote_display_port_max", cfg->remotePortMax);
    if (cfg->remotePortMax > QEMU_REMOTE_PORT_MAX ||
        cfg->remotePortMax < cfg->remotePortMin) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("%s: remote_display_port_max: port must be between "
                          "the minimal port and %d"),
                       filename, QEMU_REMOTE_PORT_MAX);
        goto cleanup;
    }

    if (cfg->remotePortMin > cfg->remotePortMax) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("%s: remote_display_port_min: min port must not be "
                          "greater than max port"), filename);
        goto cleanup;
    }

    GET_VALUE_ULONG("migration_port_min", cfg->migrationPortMin);
    if (cfg->migrationPortMin <= 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("%s: migration_port_min: port must be greater than 0"),
                        filename);
        goto cleanup;
    }

    GET_VALUE_ULONG("migration_port_max", cfg->migrationPortMax);
    if (cfg->migrationPortMax > 65535 ||
        cfg->migrationPortMax < cfg->migrationPortMin) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                        _("%s: migration_port_max: port must be between "
                          "the minimal port %d and 65535"),
                       filename, cfg->migrationPortMin);
        goto cleanup;
    }

    p = virConfGetValue(conf, "user");
    CHECK_TYPE("user", VIR_CONF_STRING);
    if (p && p->str &&
        virGetUserID(p->str, &cfg->user) < 0)
        goto cleanup;

    p = virConfGetValue(conf, "group");
    CHECK_TYPE("group", VIR_CONF_STRING);
    if (p && p->str &&
        virGetGroupID(p->str, &cfg->group) < 0)
        goto cleanup;

    GET_VALUE_BOOL("dynamic_ownership", cfg->dynamicOwnership);

    p = virConfGetValue(conf, "cgroup_controllers");
    CHECK_TYPE("cgroup_controllers", VIR_CONF_LIST);
    if (p) {
        cfg->cgroupControllers = 0;
        virConfValuePtr pp;
        for (i = 0, pp = p->list; pp; ++i, pp = pp->next) {
            int ctl;
            if (pp->type != VIR_CONF_STRING) {
                virReportError(VIR_ERR_CONF_SYNTAX, "%s",
                               _("cgroup_controllers must be a "
                                 "list of strings"));
                goto cleanup;
            }

            if ((ctl = virCgroupControllerTypeFromString(pp->str)) < 0) {
                virReportError(VIR_ERR_CONF_SYNTAX,
                               _("Unknown cgroup controller '%s'"), pp->str);
                goto cleanup;
            }
            cfg->cgroupControllers |= (1 << ctl);
        }
    }

    p = virConfGetValue(conf, "cgroup_device_acl");
    CHECK_TYPE("cgroup_device_acl", VIR_CONF_LIST);
    if (p) {
        int len = 0;
        virConfValuePtr pp;
        for (pp = p->list; pp; pp = pp->next)
            len++;
        if (VIR_ALLOC_N(cfg->cgroupDeviceACL, 1+len) < 0)
            goto cleanup;

        for (i = 0, pp = p->list; pp; ++i, pp = pp->next) {
            if (pp->type != VIR_CONF_STRING) {
                virReportError(VIR_ERR_CONF_SYNTAX, "%s",
                               _("cgroup_device_acl must be a "
                                 "list of strings"));
                goto cleanup;
            }
            if (VIR_STRDUP(cfg->cgroupDeviceACL[i], pp->str) < 0)
                goto cleanup;
        }
        cfg->cgroupDeviceACL[i] = NULL;
    }

    GET_VALUE_STR("save_image_format", cfg->saveImageFormat);
    GET_VALUE_STR("dump_image_format", cfg->dumpImageFormat);
    GET_VALUE_STR("snapshot_image_format", cfg->snapshotImageFormat);

    GET_VALUE_STR("auto_dump_path", cfg->autoDumpPath);
    GET_VALUE_BOOL("auto_dump_bypass_cache", cfg->autoDumpBypassCache);
    GET_VALUE_BOOL("auto_start_bypass_cache", cfg->autoStartBypassCache);

    /* Some crazy backcompat. Back in the old days, this was just a pure
     * string. We must continue supporting it. These days however, this may be
     * an array of strings. */
    p = virConfGetValue(conf, "hugetlbfs_mount");
    if (p) {
        /* There already might be something autodetected. Avoid leaking it. */
        while (cfg->nhugetlbfs) {
            cfg->nhugetlbfs--;
            VIR_FREE(cfg->hugetlbfs[cfg->nhugetlbfs].mnt_dir);
        }
        VIR_FREE(cfg->hugetlbfs);

        if (p->type == VIR_CONF_LIST) {
            size_t len = 0;
            virConfValuePtr pp = p->list;

            /* Calc length and check items */
            while (pp) {
                if (pp->type != VIR_CONF_STRING) {
                    virReportError(VIR_ERR_CONF_SYNTAX, "%s",
                                   _("hugetlbfs_mount must be a list of strings"));
                    goto cleanup;
                }
                len++;
                pp = pp->next;
            }

            if (len && VIR_ALLOC_N(cfg->hugetlbfs, len) < 0)
                goto cleanup;
            cfg->nhugetlbfs = len;

            pp = p->list;
            len = 0;
            while (pp) {
                if (virQEMUDriverConfigHugeTLBFSInit(&cfg->hugetlbfs[len],
                                                     pp->str, !len) < 0)
                    goto cleanup;
                len++;
                pp = pp->next;
            }
        } else {
            CHECK_TYPE("hugetlbfs_mount", VIR_CONF_STRING);
            if (STRNEQ(p->str, "")) {
                if (VIR_ALLOC_N(cfg->hugetlbfs, 1) < 0)
                    goto cleanup;
                cfg->nhugetlbfs = 1;
                if (virQEMUDriverConfigHugeTLBFSInit(&cfg->hugetlbfs[0],
                                                     p->str, true) < 0)
                    goto cleanup;
            }
        }
    }

    GET_VALUE_STR("bridge_helper", cfg->bridgeHelperName);

    GET_VALUE_BOOL("mac_filter", cfg->macFilter);

    GET_VALUE_BOOL("relaxed_acs_check", cfg->relaxedACS);
    GET_VALUE_BOOL("clear_emulator_capabilities", cfg->clearEmulatorCapabilities);
    GET_VALUE_BOOL("allow_disk_format_probing", cfg->allowDiskFormatProbing);
    GET_VALUE_BOOL("set_process_name", cfg->setProcessName);
    GET_VALUE_ULONG("max_processes", cfg->maxProcesses);
    GET_VALUE_ULONG("max_files", cfg->maxFiles);

    GET_VALUE_STR("lock_manager", cfg->lockManagerName);
    GET_VALUE_STR("stdio_handler", stdioHandler);
    if (stdioHandler) {
        if (STREQ(stdioHandler, "logd")) {
            cfg->stdioLogD = true;
        } else if (STREQ(stdioHandler, "file")) {
            cfg->stdioLogD = false;
        } else {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("Unknown stdio handler %s"),
                           stdioHandler);
            VIR_FREE(stdioHandler);
            goto cleanup;
        }
        VIR_FREE(stdioHandler);
    }

    GET_VALUE_ULONG("max_queued", cfg->maxQueuedJobs);

    GET_VALUE_LONG("keepalive_interval", cfg->keepAliveInterval);
    GET_VALUE_ULONG("keepalive_count", cfg->keepAliveCount);

    GET_VALUE_LONG("seccomp_sandbox", cfg->seccompSandbox);

    GET_VALUE_STR("migration_host", cfg->migrateHost);
    virStringStripIPv6Brackets(cfg->migrateHost);
    if (cfg->migrateHost &&
        (STRPREFIX(cfg->migrateHost, "localhost") ||
         virSocketAddrIsNumericLocalhost(cfg->migrateHost))) {
        virReportError(VIR_ERR_CONF_SYNTAX,
                       _("migration_host must not be the address of"
                         " the local machine: %s"),
                       cfg->migrateHost);
        goto cleanup;
    }

    GET_VALUE_STR("migration_address", cfg->migrationAddress);
    virStringStripIPv6Brackets(cfg->migrationAddress);
    if (cfg->migrationAddress &&
        (STRPREFIX(cfg->migrationAddress, "localhost") ||
         virSocketAddrIsNumericLocalhost(cfg->migrationAddress))) {
        virReportError(VIR_ERR_CONF_SYNTAX,
                       _("migration_address must not be the address of"
                         " the local machine: %s"),
                       cfg->migrationAddress);
        goto cleanup;
    }

    GET_VALUE_BOOL("log_timestamp", cfg->logTimestamp);

    if ((p = virConfGetValue(conf, "nvram"))) {
        size_t len;
        virConfValuePtr pp;

        CHECK_TYPE("nvram", VIR_CONF_LIST);

        virFirmwareFreeList(cfg->firmwares, cfg->nfirmwares);
        /* Calc length and check items */
        for (len = 0, pp = p->list; pp; len++, pp = pp->next) {
            if (pp->type != VIR_CONF_STRING) {
                virReportError(VIR_ERR_CONF_SYNTAX, "%s",
                               _("nvram must be a list of strings"));
                goto cleanup;
            }
        }

        if (len && VIR_ALLOC_N(cfg->firmwares, len) < 0)
            goto cleanup;
        cfg->nfirmwares = len;

        for (i = 0, pp = p->list; pp; i++, pp = pp->next) {
            if (VIR_ALLOC(cfg->firmwares[i]) < 0)
                goto cleanup;
            if (virFirmwareParse(pp->str, cfg->firmwares[i]) < 0)
                goto cleanup;
        }
    }

    ret = 0;

 cleanup:
    virConfFree(conf);
    return ret;
}
Beispiel #10
0
/**
 * virObjectEventCallbackListAddID:
 * @conn: pointer to the connection
 * @cbList: the list
 * @key: the optional key of the object to filter on
 * @filter: optional last-ditch filter callback
 * @filter_opaque: opaque data to pass to @filter
 * @klass: the base event class
 * @eventID: the event ID
 * @callback: the callback to add
 * @opaque: opaque data to pass to @callback
 * @freecb: callback to free @opaque
 * @legacy: true if callback is tracked by function instead of callbackID
 * @callbackID: filled with callback ID
 * @serverFilter: true if server supports object filtering
 *
 * Internal function to add a callback from a virObjectEventCallbackListPtr
 */
static int
virObjectEventCallbackListAddID(virConnectPtr conn,
                                virObjectEventCallbackListPtr cbList,
                                const char *key,
                                virObjectEventCallbackFilter filter,
                                void *filter_opaque,
                                virClassPtr klass,
                                int eventID,
                                virConnectObjectEventGenericCallback callback,
                                void *opaque,
                                virFreeCallback freecb,
                                bool legacy,
                                int *callbackID,
                                bool serverFilter)
{
    virObjectEventCallbackPtr cb;
    int ret = -1;
    int remoteID = -1;

    VIR_DEBUG("conn=%p cblist=%p key=%p filter=%p filter_opaque=%p "
              "klass=%p eventID=%d callback=%p opaque=%p "
              "legacy=%d callbackID=%p serverFilter=%d",
              conn, cbList, key, filter, filter_opaque, klass, eventID,
              callback, opaque, legacy, callbackID, serverFilter);

    /* Check incoming */
    if (!cbList)
        return -1;

    /* If there is no additional filtering, then check if we already
     * have this callback on our list.  */
    if (!filter &&
        virObjectEventCallbackLookup(conn, cbList, key,
                                     klass, eventID, callback, legacy,
                                     serverFilter ? &remoteID : NULL) != -1) {
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("event callback already tracked"));
        return -1;
    }
    /* Allocate new cb */
    if (VIR_ALLOC(cb) < 0)
        goto cleanup;
    cb->conn = virObjectRef(conn);
    *callbackID = cb->callbackID = cbList->nextID++;
    cb->cb = callback;
    cb->klass = klass;
    cb->eventID = eventID;
    cb->opaque = opaque;
    cb->freecb = freecb;
    cb->remoteID = remoteID;

    if (key) {
        cb->key_filter = true;
        if (VIR_STRDUP(cb->key, key) < 0)
            goto cleanup;
    }
    cb->filter = filter;
    cb->filter_opaque = filter_opaque;
    cb->legacy = legacy;

    if (VIR_APPEND_ELEMENT(cbList->callbacks, cbList->count, cb) < 0)
        goto cleanup;

    /* When additional filtering is being done, every client callback
     * is matched to exactly one server callback.  */
    if (filter) {
        ret = 1;
    } else {
        ret = virObjectEventCallbackListCount(conn, cbList, klass, eventID,
                                              key, serverFilter);
        if (serverFilter && remoteID < 0)
            ret++;
    }

 cleanup:
    virObjectEventCallbackFree(cb);
    return ret;
}
Beispiel #11
0
static virCPUDefPtr
genericBaseline(virCPUDefPtr *cpus,
                unsigned int ncpus,
                const char **models,
                unsigned int nmodels,
                unsigned int flags)
{
    virCPUDefPtr cpu = NULL;
    virCPUFeatureDefPtr features = NULL;
    unsigned int nfeatures;
    unsigned int count;
    size_t i, j;

    virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES |
                  VIR_CONNECT_BASELINE_CPU_MIGRATABLE, NULL);

    if (!cpuModelIsAllowed(cpus[0]->model, models, nmodels)) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("CPU model %s is not supported by hypervisor"),
                       cpus[0]->model);
        goto error;
    }

    if (VIR_ALLOC(cpu) < 0 ||
        VIR_STRDUP(cpu->model, cpus[0]->model) < 0 ||
        VIR_ALLOC_N(features, cpus[0]->nfeatures) < 0)
        goto error;

    cpu->arch = cpus[0]->arch;
    cpu->type = VIR_CPU_TYPE_HOST;

    count = nfeatures = cpus[0]->nfeatures;
    for (i = 0; i < nfeatures; i++)
        features[i].name = cpus[0]->features[i].name;

    for (i = 1; i < ncpus; i++) {
        virHashTablePtr hash;

        if (cpu->arch != cpus[i]->arch) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("CPUs have incompatible architectures: '%s' != '%s'"),
                           virArchToString(cpu->arch),
                           virArchToString(cpus[i]->arch));
            goto error;
        }

        if (STRNEQ(cpu->model, cpus[i]->model)) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("CPU models don't match: '%s' != '%s'"),
                           cpu->model, cpus[i]->model);
            goto error;
        }

        if (!(hash = genericHashFeatures(cpus[i])))
            goto error;

        for (j = 0; j < nfeatures; j++) {
            if (features[j].name &&
                !virHashLookup(hash, features[j].name)) {
                features[j].name = NULL;
                count--;
            }
        }

        virHashFree(hash);
    }

    if (VIR_ALLOC_N(cpu->features, count) < 0)
        goto error;
    cpu->nfeatures = count;

    j = 0;
    for (i = 0; i < nfeatures; i++) {
        if (!features[i].name)
            continue;

        if (VIR_STRDUP(cpu->features[j++].name, features[i].name) < 0)
            goto error;
    }

 cleanup:
    VIR_FREE(features);

    return cpu;

 error:
    virCPUDefFree(cpu);
    cpu = NULL;
    goto cleanup;
}
Beispiel #12
0
static int
virStorageBackendSCSINewLun(virStoragePoolObjPtr pool,
                            uint32_t host ATTRIBUTE_UNUSED,
                            uint32_t bus,
                            uint32_t target,
                            uint32_t lun,
                            const char *dev)
{
    virStorageVolDefPtr vol;
    char *devpath = NULL;
    int retval = 0;

    if (VIR_ALLOC(vol) < 0) {
        retval = -1;
        goto out;
    }

    vol->type = VIR_STORAGE_VOL_BLOCK;

    /* 'host' is dynamically allocated by the kernel, first come,
     * first served, per HBA. As such it isn't suitable for use
     * in the volume name. We only need uniqueness per-pool, so
     * just leave 'host' out
     */
    if (virAsprintf(&(vol->name), "unit:%u:%u:%u", bus, target, lun) < 0) {
        retval = -1;
        goto free_vol;
    }

    if (virAsprintf(&devpath, "/dev/%s", dev) < 0) {
        retval = -1;
        goto free_vol;
    }

    VIR_DEBUG("Trying to create volume for '%s'", devpath);

    /* Now figure out the stable path
     *
     * XXX this method is O(N) because it scans the pool target
     * dir every time its run. Should figure out a more efficient
     * way of doing this...
     */
    if ((vol->target.path = virStorageBackendStablePath(pool,
                                                        devpath,
                                                        true)) == NULL) {
        retval = -1;
        goto free_vol;
    }

    if (STREQ(devpath, vol->target.path) &&
        !(STREQ(pool->def->target.path, "/dev") ||
          STREQ(pool->def->target.path, "/dev/"))) {

        VIR_DEBUG("No stable path found for '%s' in '%s'",
                  devpath, pool->def->target.path);

        retval = -1;
        goto free_vol;
    }

    if (virStorageBackendUpdateVolInfo(vol, true,
                                       VIR_STORAGE_VOL_OPEN_DEFAULT) < 0) {
        retval = -1;
        goto free_vol;
    }

    if (!(vol->key = virStorageBackendSCSISerial(vol->target.path))) {
        retval = -1;
        goto free_vol;
    }

    pool->def->capacity += vol->target.capacity;
    pool->def->allocation += vol->target.allocation;

    if (VIR_APPEND_ELEMENT(pool->volumes.objs, pool->volumes.count, vol) < 0) {
        retval = -1;
        goto free_vol;
    }

    goto out;

 free_vol:
    virStorageVolDefFree(vol);
 out:
    VIR_FREE(devpath);
    return retval;
}
Beispiel #13
0
static int virLockManagerLockDaemonNew(virLockManagerPtr lock,
                                       unsigned int type,
                                       size_t nparams,
                                       virLockManagerParamPtr params,
                                       unsigned int flags)
{
    virLockManagerLockDaemonPrivatePtr priv;
    size_t i;

    virCheckFlags(VIR_LOCK_MANAGER_USES_STATE, -1);

    if (VIR_ALLOC(priv) < 0) {
        virReportOOMError();
        return -1;
    }
    lock->privateData = priv;

    switch (type) {
    case VIR_LOCK_MANAGER_OBJECT_TYPE_DOMAIN:
        for (i = 0 ; i < nparams ; i++) {
            if (STREQ(params[i].key, "uuid")) {
                memcpy(priv->uuid, params[i].value.uuid, VIR_UUID_BUFLEN);
            } else if (STREQ(params[i].key, "name")) {
                if (!(priv->name = strdup(params[i].value.str))) {
                    virReportOOMError();
                    return -1;
                }
            } else if (STREQ(params[i].key, "id")) {
                priv->id = params[i].value.i;
            } else if (STREQ(params[i].key, "pid")) {
                priv->pid = params[i].value.i;
            } else if (STREQ(params[i].key, "uri")) {
                /* ignored */
            } else {
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("Unexpected parameter %s for object"),
                               params[i].key);
            }
        }
        if (priv->id == 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("Missing ID parameter for domain object"));
            return -1;
        }
        if (priv->pid == 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("Missing PID parameter for domain object"));
            return -1;
        }
        if (!priv->name) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("Missing name parameter for domain object"));
            return -1;
        }
        if (!virUUIDIsValid(priv->uuid)) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("Missing UUID parameter for domain object"));
            return -1;
        }
        break;

    default:
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Unknown lock manager object type %d"),
                       type);
        return -1;
    }

    return 0;
}
static virCapsPtr
parallelsBuildCapabilities(void)
{
    virCapsPtr caps = NULL;
    virCPUDefPtr cpu = NULL;
    virCPUDataPtr data = NULL;
    virCapsGuestPtr guest;
    virNodeInfo nodeinfo;

    if ((caps = virCapabilitiesNew(virArchFromHost(),
                                   false, false)) == NULL)
        return NULL;

    if (nodeCapsInitNUMA(caps) < 0)
        goto error;

    if ((guest = virCapabilitiesAddGuest(caps, "hvm",
                                         VIR_ARCH_X86_64,
                                         "parallels",
                                         NULL, 0, NULL)) == NULL)
        goto error;

    if ((guest = virCapabilitiesAddGuest(caps, "hvm",
                                         VIR_ARCH_I686,
                                         "parallels",
                                         NULL, 0, NULL)) == NULL)
        goto error;


    if (virCapabilitiesAddGuestDomain(guest,
                                      "parallels", NULL, NULL, 0, NULL) == NULL)
        goto error;

    if ((guest = virCapabilitiesAddGuest(caps, "exe",
                                         VIR_ARCH_X86_64,
                                         "parallels",
                                         NULL, 0, NULL)) == NULL)
        goto error;

    if (virCapabilitiesAddGuestDomain(guest,
                                      "parallels", NULL, NULL, 0, NULL) == NULL)
        goto error;

    if (nodeGetInfo(&nodeinfo))
        goto error;

    if (VIR_ALLOC(cpu) < 0)
        goto error;

    cpu->arch = caps->host.arch;
    cpu->type = VIR_CPU_TYPE_HOST;
    cpu->sockets = nodeinfo.sockets;
    cpu->cores = nodeinfo.cores;
    cpu->threads = nodeinfo.threads;

    caps->host.cpu = cpu;

    if (!(data = cpuNodeData(cpu->arch))
        || cpuDecode(cpu, data, NULL, 0, NULL) < 0) {
        goto cleanup;
    }

 cleanup:
    cpuDataFree(data);
    return caps;

 error:
    virObjectUnref(caps);
    goto cleanup;
}
Beispiel #15
0
/**
 * virDomainEventCallbackListAddID:
 * @conn: pointer to the connection
 * @cbList: the list
 * @eventID: the event ID
 * @callback: the callback to add
 * @opaque: opaque data tio pass to callback
 * @callbackID: filled with callback ID
 *
 * Internal function to add a callback from a virDomainEventCallbackListPtr
 */
static int
virDomainEventCallbackListAddID(virConnectPtr conn,
                                virDomainEventCallbackListPtr cbList,
                                virDomainPtr dom,
                                int eventID,
                                virConnectDomainEventGenericCallback callback,
                                void *opaque,
                                virFreeCallback freecb,
                                int *callbackID)
{
    virDomainEventCallbackPtr event;
    int i;
    int ret = 0;

    /* Check incoming */
    if ( !cbList ) {
        return -1;
    }

    /* check if we already have this callback on our list */
    for (i = 0 ; i < cbList->count ; i++) {
        if (cbList->callbacks[i]->cb == VIR_DOMAIN_EVENT_CALLBACK(callback) &&
            cbList->callbacks[i]->eventID == eventID &&
            cbList->callbacks[i]->conn == conn) {
            eventReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                             _("event callback already tracked"));
            return -1;
        }
    }
    /* Allocate new event */
    if (VIR_ALLOC(event) < 0)
        goto no_memory;
    event->conn = conn;
    event->cb = callback;
    event->eventID = eventID;
    event->opaque = opaque;
    event->freecb = freecb;

    if (dom) {
        if (VIR_ALLOC(event->dom) < 0)
            goto no_memory;
        if (!(event->dom->name = strdup(dom->name)))
            goto no_memory;
        memcpy(event->dom->uuid, dom->uuid, VIR_UUID_BUFLEN);
        event->dom->id = dom->id;
    }

    /* Make space on list */
    if (VIR_REALLOC_N(cbList->callbacks, cbList->count + 1) < 0)
        goto no_memory;

    event->conn->refs++;

    cbList->callbacks[cbList->count] = event;
    cbList->count++;

    event->callbackID = cbList->nextID++;

    for (i = 0 ; i < cbList->count ; i++) {
        if (cbList->callbacks[i]->eventID == eventID &&
            cbList->callbacks[i]->conn == conn &&
            !cbList->callbacks[i]->deleted)
            ret++;
    }

    if (callbackID)
        *callbackID = event->callbackID;

    return ret;

no_memory:
    virReportOOMError();

    if (event) {
        if (event->dom)
            VIR_FREE(event->dom->name);
        VIR_FREE(event->dom);
    }
    VIR_FREE(event);
    return -1;
}
Beispiel #16
0
/* flags is bitwise-or of virDomainSnapshotParseFlags.
 * If flags does not include VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE, then
 * caps and expectedVirtTypes are ignored.
 */
virDomainSnapshotDefPtr
virDomainSnapshotDefParseString(const char *xmlStr,
                                virCapsPtr caps,
                                unsigned int expectedVirtTypes,
                                unsigned int flags)
{
    xmlXPathContextPtr ctxt = NULL;
    xmlDocPtr xml = NULL;
    virDomainSnapshotDefPtr def = NULL;
    virDomainSnapshotDefPtr ret = NULL;
    xmlNodePtr *nodes = NULL;
    int i;
    char *creation = NULL, *state = NULL;
    struct timeval tv;
    int active;
    char *tmp;
    int keepBlanksDefault = xmlKeepBlanksDefault(0);
    char *memorySnapshot = NULL;
    char *memoryFile = NULL;
    bool offline = !!(flags & VIR_DOMAIN_SNAPSHOT_PARSE_OFFLINE);

    xml = virXMLParseCtxt(NULL, xmlStr, _("(domain_snapshot)"), &ctxt);
    if (!xml) {
        xmlKeepBlanksDefault(keepBlanksDefault);
        return NULL;
    }
    xmlKeepBlanksDefault(keepBlanksDefault);

    if (VIR_ALLOC(def) < 0) {
        virReportOOMError();
        goto cleanup;
    }

    if (!xmlStrEqual(ctxt->node->name, BAD_CAST "domainsnapshot")) {
        virReportError(VIR_ERR_XML_ERROR, "%s", _("domainsnapshot"));
        goto cleanup;
    }

    gettimeofday(&tv, NULL);

    def->name = virXPathString("string(./name)", ctxt);
    if (def->name == NULL) {
        if (flags & VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE) {
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("a redefined snapshot must have a name"));
            goto cleanup;
        }
        if (virAsprintf(&def->name, "%lld", (long long)tv.tv_sec) < 0) {
            virReportOOMError();
            goto cleanup;
        }
    }

    def->description = virXPathString("string(./description)", ctxt);

    if (flags & VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE) {
        if (virXPathLongLong("string(./creationTime)", ctxt,
                             &def->creationTime) < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("missing creationTime from existing snapshot"));
            goto cleanup;
        }

        def->parent = virXPathString("string(./parent/name)", ctxt);

        state = virXPathString("string(./state)", ctxt);
        if (state == NULL) {
            /* there was no state in an existing snapshot; this
             * should never happen
             */
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("missing state from existing snapshot"));
            goto cleanup;
        }
        def->state = virDomainSnapshotStateTypeFromString(state);
        if (def->state < 0) {
            virReportError(VIR_ERR_XML_ERROR,
                           _("Invalid state '%s' in domain snapshot XML"),
                           state);
            goto cleanup;
        }
        offline = (def->state == VIR_DOMAIN_SHUTOFF ||
                   def->state == VIR_DOMAIN_DISK_SNAPSHOT);

        /* Older snapshots were created with just <domain>/<uuid>, and
         * lack domain/@type.  In that case, leave dom NULL, and
         * clients will have to decide between best effort
         * initialization or outright failure.  */
        if ((tmp = virXPathString("string(./domain/@type)", ctxt))) {
            xmlNodePtr domainNode = virXPathNode("./domain", ctxt);

            VIR_FREE(tmp);
            if (!domainNode) {
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("missing domain in snapshot"));
                goto cleanup;
            }
            def->dom = virDomainDefParseNode(caps, xml, domainNode,
                                             expectedVirtTypes,
                                             (VIR_DOMAIN_XML_INACTIVE |
                                              VIR_DOMAIN_XML_SECURE));
            if (!def->dom)
                goto cleanup;
        } else {
            VIR_WARN("parsing older snapshot that lacks domain");
        }
    } else {
        def->creationTime = tv.tv_sec;
    }

    memorySnapshot = virXPathString("string(./memory/@snapshot)", ctxt);
    memoryFile = virXPathString("string(./memory/@file)", ctxt);
    if (memorySnapshot) {
        def->memory = virDomainSnapshotLocationTypeFromString(memorySnapshot);
        if (def->memory <= 0) {
            virReportError(VIR_ERR_XML_ERROR,
                           _("unknown memory snapshot setting '%s'"),
                           memorySnapshot);
            goto cleanup;
        }
        if (memoryFile &&
            def->memory != VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL) {
            virReportError(VIR_ERR_XML_ERROR,
                           _("memory filename '%s' requires external snapshot"),
                           memoryFile);
            goto cleanup;
        }
        if (!memoryFile &&
            def->memory == VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL) {
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("external memory snapshots require a filename"));
            goto cleanup;
        }
    } else if (memoryFile) {
        def->memory = VIR_DOMAIN_SNAPSHOT_LOCATION_EXTERNAL;
    } else if (flags & VIR_DOMAIN_SNAPSHOT_PARSE_REDEFINE) {
        def->memory = (offline ?
                       VIR_DOMAIN_SNAPSHOT_LOCATION_NONE :
                       VIR_DOMAIN_SNAPSHOT_LOCATION_INTERNAL);
    }
    if (offline && def->memory &&
        def->memory != VIR_DOMAIN_SNAPSHOT_LOCATION_NONE) {
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("memory state cannot be saved with offline or "
                         "disk-only snapshot"));
        goto cleanup;
    }
    def->file = memoryFile;
    memoryFile = NULL;

    if ((i = virXPathNodeSet("./disks/*", ctxt, &nodes)) < 0)
        goto cleanup;
    if (flags & VIR_DOMAIN_SNAPSHOT_PARSE_DISKS) {
        def->ndisks = i;
        if (def->ndisks && VIR_ALLOC_N(def->disks, def->ndisks) < 0) {
            virReportOOMError();
            goto cleanup;
        }
        for (i = 0; i < def->ndisks; i++) {
            if (virDomainSnapshotDiskDefParseXML(nodes[i], &def->disks[i]) < 0)
                goto cleanup;
        }
        VIR_FREE(nodes);
    } else if (i) {
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("unable to handle disk requests in snapshot"));
        goto cleanup;
    }

    if (flags & VIR_DOMAIN_SNAPSHOT_PARSE_INTERNAL) {
        if (virXPathInt("string(./active)", ctxt, &active) < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("Could not find 'active' element"));
            goto cleanup;
        }
        def->current = active != 0;
    }

    ret = def;

cleanup:
    VIR_FREE(creation);
    VIR_FREE(state);
    VIR_FREE(nodes);
    VIR_FREE(memorySnapshot);
    VIR_FREE(memoryFile);
    xmlXPathFreeContext(ctxt);
    if (ret == NULL)
        virDomainSnapshotDefFree(def);
    xmlFreeDoc(xml);

    return ret;
}
Beispiel #17
0
virCapsPtr
vmwareCapsInit(void)
{
    virCapsPtr caps = NULL;
    virCapsGuestPtr guest = NULL;
    virCPUDefPtr cpu = NULL;
    virCPUDataPtr data = NULL;

    if ((caps = virCapabilitiesNew(virArchFromHost(),
                                   0, 0)) == NULL)
        goto error;

    if (nodeCapsInitNUMA(caps) < 0)
        goto error;

    /* i686 guests are always supported */
    if ((guest = virCapabilitiesAddGuest(caps,
                                         "hvm",
                                         VIR_ARCH_I686,
                                         NULL, NULL, 0, NULL)) == NULL)
        goto error;

    if (virCapabilitiesAddGuestDomain(guest,
                                      "vmware",
                                      NULL, NULL, 0, NULL) == NULL)
        goto error;

    if (VIR_ALLOC(cpu) < 0)
        goto error;

    cpu->arch = caps->host.arch;
    cpu->type = VIR_CPU_TYPE_HOST;

    if (!(data = cpuNodeData(cpu->arch))
        || cpuDecode(cpu, data, NULL, 0, NULL) < 0) {
        goto error;
    }

    /* x86_64 guests are supported if
     *  - Host arch is x86_64
     * Or
     *  - Host CPU is x86_64 with virtualization extensions
     */
    if (caps->host.arch == VIR_ARCH_X86_64 ||
        (cpuHasFeature(data, "lm") &&
         (cpuHasFeature(data, "vmx") ||
          cpuHasFeature(data, "svm")))) {

        if ((guest = virCapabilitiesAddGuest(caps,
                                             "hvm",
                                             VIR_ARCH_X86_64,
                                             NULL, NULL, 0, NULL)) == NULL)
            goto error;

        if (virCapabilitiesAddGuestDomain(guest,
                                          "vmware",
                                          NULL, NULL, 0, NULL) == NULL)
            goto error;
    }

cleanup:
    virCPUDefFree(cpu);
    cpuDataFree(data);

    return caps;

error:
    virObjectUnref(caps);
    goto cleanup;
}
Beispiel #18
0
/**
 * xenInotifyOpen:
 * @conn: pointer to the connection block
 * @name: URL for the target, NULL for local
 * @flags: combination of virDrvOpenFlag(s)
 *
 * Connects and starts listening for inotify events
 *
 * Returns 0 or -1 in case of error.
 */
int
xenInotifyOpen(virConnectPtr conn,
               virConnectAuthPtr auth ATTRIBUTE_UNUSED,
               unsigned int flags)
{
    DIR *dh;
    struct dirent *ent;
    char *path;
    xenUnifiedPrivatePtr priv = conn->privateData;

    virCheckFlags(VIR_CONNECT_RO, -1);

    if (priv->configDir) {
        priv->useXenConfigCache = 1;
    } else {
        /* /var/lib/xend/domains/<uuid>/config.sxp */
        priv->configDir = XEND_DOMAINS_DIR;
        priv->useXenConfigCache = 0;

        if (VIR_ALLOC(priv->configInfoList) < 0)
            return -1;

        /* populate initial list */
        if (!(dh = opendir(priv->configDir))) {
            virReportSystemError(errno,
                                 _("cannot open directory: %s"),
                                 priv->configDir);
            return -1;
        }
        while ((ent = readdir(dh))) {
            if (STRPREFIX(ent->d_name, "."))
                continue;

            /* Build the full file path */
            if (!(path = virFileBuildPath(priv->configDir, ent->d_name, NULL))) {
                closedir(dh);
                return -1;
            }

            if (xenInotifyAddDomainConfigInfo(conn, path) < 0) {
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               "%s", _("Error adding file to config list"));
                closedir(dh);
                VIR_FREE(path);
                return -1;
            }

            VIR_FREE(path);
        }
        closedir(dh);
    }

    if ((priv->inotifyFD = inotify_init()) < 0) {
        virReportSystemError(errno,
                             "%s", _("initializing inotify"));
        return -1;
    }

    VIR_DEBUG("Adding a watch on %s", priv->configDir);
    if (inotify_add_watch(priv->inotifyFD,
                          priv->configDir,
                          IN_CREATE |
                          IN_CLOSE_WRITE | IN_DELETE |
                          IN_MOVED_TO | IN_MOVED_FROM) < 0) {
        virReportSystemError(errno,
                             _("adding watch on %s"),
                             priv->configDir);
        return -1;
    }

    VIR_DEBUG("Building initial config cache");
    if (priv->useXenConfigCache &&
        xenXMConfigCacheRefresh(conn) < 0) {
        VIR_DEBUG("Failed to enable XM config cache %s", conn->err.message);
        return -1;
    }

    VIR_DEBUG("Registering with event loop");
    /* Add the handle for monitoring */
    if ((priv->inotifyWatch = virEventAddHandle(priv->inotifyFD, VIR_EVENT_HANDLE_READABLE,
                                                xenInotifyEvent, conn, NULL)) < 0) {
        VIR_DEBUG("Failed to add inotify handle, disabling events");
    }

    return 0;
}
Beispiel #19
0
/**
 * virNetlinkEventServiceStart:
 *
 * start a monitor to receive netlink messages for libvirtd.
 * This registers a netlink socket with the event interface.
 *
 * @protocol: netlink protocol
 * @groups: broadcast groups to join in
 * Returns -1 if the monitor cannot be registered, 0 upon success
 */
int
virNetlinkEventServiceStart(unsigned int protocol, unsigned int groups)
{
    virNetlinkEventSrvPrivatePtr srv;
    int fd;
    int ret = -1;

    if (protocol >= MAX_LINKS) {
        virReportSystemError(EINVAL,
                             _("invalid protocol argument: %d"), protocol);
        return -EINVAL;
    }

    if (server[protocol])
        return 0;

    VIR_INFO("starting netlink event service with protocol %d", protocol);

    if (VIR_ALLOC(srv) < 0)
        return -1;

    if (virMutexInit(&srv->lock) < 0) {
        VIR_FREE(srv);
        return -1;
    }

    virNetlinkEventServerLock(srv);

    /* Allocate a new socket and get fd */
    if (!(srv->netlinknh = virNetlinkCreateSocket(protocol)))
        goto error_locked;

    fd = nl_socket_get_fd(srv->netlinknh);
    if (fd < 0) {
        virReportSystemError(errno,
                             "%s", _("cannot get netlink socket fd"));
        goto error_server;
    }

    if (groups && nl_socket_add_membership(srv->netlinknh, groups) < 0) {
        virReportSystemError(errno,
                             "%s", _("cannot add netlink membership"));
        goto error_server;
    }

    if (nl_socket_set_nonblocking(srv->netlinknh)) {
        virReportSystemError(errno, "%s",
                             _("cannot set netlink socket nonblocking"));
        goto error_server;
    }

    if ((srv->eventwatch = virEventAddHandle(fd,
                                             VIR_EVENT_HANDLE_READABLE,
                                             virNetlinkEventCallback,
                                             srv, NULL)) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Failed to add netlink event handle watch"));
        goto error_server;
    }

    srv->netlinkfd = fd;
    VIR_DEBUG("netlink event listener on fd: %i running", fd);

    ret = 0;
    server[protocol] = srv;

 error_server:
    if (ret < 0) {
        nl_close(srv->netlinknh);
        virNetlinkFree(srv->netlinknh);
    }
 error_locked:
    virNetlinkEventServerUnlock(srv);
    if (ret < 0) {
        virMutexDestroy(&srv->lock);
        VIR_FREE(srv);
    }
    return ret;
}
Beispiel #20
0
/**
 * virLXCProcessStart:
 * @conn: pointer to connection
 * @driver: pointer to driver structure
 * @vm: pointer to virtual machine structure
 * @autoDestroy: mark the domain for auto destruction
 * @reason: reason for switching vm to running state
 *
 * Starts a vm
 *
 * Returns 0 on success or -1 in case of error
 */
int virLXCProcessStart(virConnectPtr conn,
                       virLXCDriverPtr  driver,
                       virDomainObjPtr vm,
                       unsigned int nfiles, int *files,
                       bool autoDestroy,
                       virDomainRunningReason reason)
{
    int rc = -1, r;
    size_t nttyFDs = 0;
    int *ttyFDs = NULL;
    size_t i;
    char *logfile = NULL;
    int logfd = -1;
    size_t nveths = 0;
    char **veths = NULL;
    int handshakefds[2] = { -1, -1 };
    off_t pos = -1;
    char ebuf[1024];
    char *timestamp;
    virCommandPtr cmd = NULL;
    virLXCDomainObjPrivatePtr priv = vm->privateData;
    virCapsPtr caps = NULL;
    virErrorPtr err = NULL;
    virLXCDriverConfigPtr cfg = virLXCDriverGetConfig(driver);
    virCgroupPtr selfcgroup;
    int status;

    if (virCgroupNewSelf(&selfcgroup) < 0)
        return -1;

    if (!virCgroupHasController(selfcgroup,
                                VIR_CGROUP_CONTROLLER_CPUACCT)) {
        virCgroupFree(&selfcgroup);
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Unable to find 'cpuacct' cgroups controller mount"));
        return -1;
    }
    if (!virCgroupHasController(selfcgroup,
                                VIR_CGROUP_CONTROLLER_DEVICES)) {
        virCgroupFree(&selfcgroup);
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Unable to find 'devices' cgroups controller mount"));
        return -1;
    }
    if (!virCgroupHasController(selfcgroup,
                                VIR_CGROUP_CONTROLLER_MEMORY)) {
        virCgroupFree(&selfcgroup);
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Unable to find 'memory' cgroups controller mount"));
        return -1;
    }
    virCgroupFree(&selfcgroup);

    if (virFileMakePath(cfg->logDir) < 0) {
        virReportSystemError(errno,
                             _("Cannot create log directory '%s'"),
                             cfg->logDir);
        return -1;
    }

    if (!vm->def->resource) {
        virDomainResourceDefPtr res;

        if (VIR_ALLOC(res) < 0)
            goto cleanup;

        if (VIR_STRDUP(res->partition, "/machine") < 0) {
            VIR_FREE(res);
            goto cleanup;
        }

        vm->def->resource = res;
    }

    if (virAsprintf(&logfile, "%s/%s.log",
                    cfg->logDir, vm->def->name) < 0)
        return -1;

    if (!(caps = virLXCDriverGetCapabilities(driver, false)))
        goto cleanup;

    /* Do this up front, so any part of the startup process can add
     * runtime state to vm->def that won't be persisted. This let's us
     * report implicit runtime defaults in the XML, like vnc listen/socket
     */
    VIR_DEBUG("Setting current domain def as transient");
    if (virDomainObjSetDefTransient(caps, driver->xmlopt, vm, true) < 0)
        goto cleanup;

    /* Run an early hook to set-up missing devices */
    if (virHookPresent(VIR_HOOK_DRIVER_LXC)) {
        char *xml = virDomainDefFormat(vm->def, 0);
        int hookret;

        hookret = virHookCall(VIR_HOOK_DRIVER_LXC, vm->def->name,
                              VIR_HOOK_LXC_OP_PREPARE, VIR_HOOK_SUBOP_BEGIN,
                              NULL, xml, NULL);
        VIR_FREE(xml);

        /*
         * If the script raised an error abort the launch
         */
        if (hookret < 0)
            goto cleanup;
    }

    if (virLXCProcessEnsureRootFS(vm) < 0)
        goto cleanup;

    /* Must be run before security labelling */
    VIR_DEBUG("Preparing host devices");
    if (virLXCPrepareHostDevices(driver, vm->def) < 0)
        goto cleanup;

    /* Here we open all the PTYs we need on the host OS side.
     * The LXC controller will open the guest OS side PTYs
     * and forward I/O between them.
     */
    nttyFDs = vm->def->nconsoles;
    if (VIR_ALLOC_N(ttyFDs, nttyFDs) < 0)
        goto cleanup;
    for (i = 0; i < vm->def->nconsoles; i++)
        ttyFDs[i] = -1;

    /* If you are using a SecurityDriver with dynamic labelling,
       then generate a security label for isolation */
    VIR_DEBUG("Generating domain security label (if required)");
    if (vm->def->nseclabels &&
        vm->def->seclabels[0]->type == VIR_DOMAIN_SECLABEL_DEFAULT)
        vm->def->seclabels[0]->type = VIR_DOMAIN_SECLABEL_NONE;

    if (virSecurityManagerGenLabel(driver->securityManager, vm->def) < 0) {
        virDomainAuditSecurityLabel(vm, false);
        goto cleanup;
    }
    virDomainAuditSecurityLabel(vm, true);

    VIR_DEBUG("Setting domain security labels");
    if (virSecurityManagerSetAllLabel(driver->securityManager,
                                      vm->def, NULL) < 0)
        goto cleanup;

    for (i = 0; i < vm->def->nconsoles; i++) {
        char *ttyPath;
        if (vm->def->consoles[i]->source.type != VIR_DOMAIN_CHR_TYPE_PTY) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("Only PTY console types are supported"));
            goto cleanup;
        }

        if (virFileOpenTty(&ttyFDs[i], &ttyPath, 1) < 0) {
            virReportSystemError(errno, "%s",
                                 _("Failed to allocate tty"));
            goto cleanup;
        }

        VIR_FREE(vm->def->consoles[i]->source.data.file.path);
        vm->def->consoles[i]->source.data.file.path = ttyPath;

        VIR_FREE(vm->def->consoles[i]->info.alias);
        if (virAsprintf(&vm->def->consoles[i]->info.alias, "console%zu", i) < 0)
            goto cleanup;
    }

    if (virLXCProcessSetupInterfaces(conn, vm->def, &nveths, &veths) < 0)
        goto cleanup;

    /* Save the configuration for the controller */
    if (virDomainSaveConfig(cfg->stateDir, vm->def) < 0)
        goto cleanup;

    if ((logfd = open(logfile, O_WRONLY | O_APPEND | O_CREAT,
             S_IRUSR|S_IWUSR)) < 0) {
        virReportSystemError(errno,
                             _("Failed to open '%s'"),
                             logfile);
        goto cleanup;
    }

    if (pipe(handshakefds) < 0) {
        virReportSystemError(errno, "%s",
                             _("Unable to create pipe"));
        goto cleanup;
    }

    if (!(cmd = virLXCProcessBuildControllerCmd(driver,
                                                vm,
                                                nveths, veths,
                                                ttyFDs, nttyFDs,
                                                files, nfiles,
                                                handshakefds[1])))
        goto cleanup;
    virCommandSetOutputFD(cmd, &logfd);
    virCommandSetErrorFD(cmd, &logfd);

    /* now that we know it is about to start call the hook if present */
    if (virHookPresent(VIR_HOOK_DRIVER_LXC)) {
        char *xml = virDomainDefFormat(vm->def, 0);
        int hookret;

        hookret = virHookCall(VIR_HOOK_DRIVER_LXC, vm->def->name,
                              VIR_HOOK_LXC_OP_START, VIR_HOOK_SUBOP_BEGIN,
                              NULL, xml, NULL);
        VIR_FREE(xml);

        /*
         * If the script raised an error abort the launch
         */
        if (hookret < 0)
            goto cleanup;
    }

    /* Log timestamp */
    if ((timestamp = virTimeStringNow()) == NULL)
        goto cleanup;
    if (safewrite(logfd, timestamp, strlen(timestamp)) < 0 ||
        safewrite(logfd, START_POSTFIX, strlen(START_POSTFIX)) < 0) {
        VIR_WARN("Unable to write timestamp to logfile: %s",
                 virStrerror(errno, ebuf, sizeof(ebuf)));
    }
    VIR_FREE(timestamp);

    /* Log generated command line */
    virCommandWriteArgLog(cmd, logfd);
    if ((pos = lseek(logfd, 0, SEEK_END)) < 0)
        VIR_WARN("Unable to seek to end of logfile: %s",
                 virStrerror(errno, ebuf, sizeof(ebuf)));

    virCommandRawStatus(cmd);
    if (virCommandRun(cmd, &status) < 0)
        goto cleanup;

    if (status != 0) {
        if (virLXCProcessReadLogOutput(vm, logfile, pos, ebuf,
                                       sizeof(ebuf)) <= 0) {
            if (WIFEXITED(status))
                snprintf(ebuf, sizeof(ebuf), _("unexpected exit status %d"),
                         WEXITSTATUS(status));
            else
                snprintf(ebuf, sizeof(ebuf), "%s", _("terminated abnormally"));
        }
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("guest failed to start: %s"), ebuf);
        goto cleanup;
    }


    if (VIR_CLOSE(handshakefds[1]) < 0) {
        virReportSystemError(errno, "%s", _("could not close handshake fd"));
        goto cleanup;
    }

    /* Connect to the controller as a client *first* because
     * this will block until the child has written their
     * pid file out to disk & created their cgroup */
    if (!(priv->monitor = virLXCProcessConnectMonitor(driver, vm))) {
        /* Intentionally overwrite the real monitor error message,
         * since a better one is almost always found in the logs
         */
        if (virLXCProcessReadLogOutput(vm, logfile, pos, ebuf, sizeof(ebuf)) > 0) {
            virResetLastError();
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("guest failed to start: %s"), ebuf);
        }
        goto cleanup;
    }

    /* And get its pid */
    if ((r = virPidFileRead(cfg->stateDir, vm->def->name, &vm->pid)) < 0) {
        if (virLXCProcessReadLogOutput(vm, logfile, pos, ebuf, sizeof(ebuf)) > 0)
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("guest failed to start: %s"), ebuf);
        else
            virReportSystemError(-r,
                                 _("Failed to read pid file %s/%s.pid"),
                                 cfg->stateDir, vm->def->name);
        goto cleanup;
    }

    if (virCgroupNewDetectMachine(vm->def->name, "lxc", vm->pid,
                                  vm->def->resource ?
                                  vm->def->resource->partition :
                                  NULL,
                                  -1, &priv->cgroup) < 0)
        goto error;

    if (!priv->cgroup) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("No valid cgroup for machine %s"),
                       vm->def->name);
        goto error;
    }

    priv->stopReason = VIR_DOMAIN_EVENT_STOPPED_FAILED;
    priv->wantReboot = false;
    vm->def->id = vm->pid;
    virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, reason);
    priv->doneStopEvent = false;

    if (virAtomicIntInc(&driver->nactive) == 1 && driver->inhibitCallback)
        driver->inhibitCallback(true, driver->inhibitOpaque);

    if (lxcContainerWaitForContinue(handshakefds[0]) < 0) {
        char out[1024];

        if (!(virLXCProcessReadLogOutput(vm, logfile, pos, out, 1024) < 0)) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("guest failed to start: %s"), out);
        }

        goto error;
    }

    if (autoDestroy &&
        virCloseCallbacksSet(driver->closeCallbacks, vm,
                             conn, lxcProcessAutoDestroy) < 0)
        goto error;

    if (virDomainObjSetDefTransient(caps, driver->xmlopt,
                                    vm, false) < 0)
        goto error;

    /* Write domain status to disk.
     *
     * XXX: Earlier we wrote the plain "live" domain XML to this
     * location for the benefit of libvirt_lxc. We're now overwriting
     * it with the live status XML instead. This is a (currently
     * harmless) inconsistency we should fix one day */
    if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
        goto error;

    /* finally we can call the 'started' hook script if any */
    if (virHookPresent(VIR_HOOK_DRIVER_LXC)) {
        char *xml = virDomainDefFormat(vm->def, 0);
        int hookret;

        hookret = virHookCall(VIR_HOOK_DRIVER_LXC, vm->def->name,
                              VIR_HOOK_LXC_OP_STARTED, VIR_HOOK_SUBOP_BEGIN,
                              NULL, xml, NULL);
        VIR_FREE(xml);

        /*
         * If the script raised an error abort the launch
         */
        if (hookret < 0)
            goto error;
    }

    rc = 0;

 cleanup:
    if (rc != 0 && !err)
        err = virSaveLastError();
    virCommandFree(cmd);
    if (VIR_CLOSE(logfd) < 0) {
        virReportSystemError(errno, "%s", _("could not close logfile"));
        rc = -1;
    }
    for (i = 0; i < nveths; i++) {
        if (rc != 0 && veths[i])
            ignore_value(virNetDevVethDelete(veths[i]));
        VIR_FREE(veths[i]);
    }
    if (rc != 0) {
        if (vm->newDef) {
            virDomainDefFree(vm->newDef);
            vm->newDef = NULL;
        }
        if (priv->monitor) {
            virObjectUnref(priv->monitor);
            priv->monitor = NULL;
        }
        virDomainConfVMNWFilterTeardown(vm);

        virSecurityManagerRestoreAllLabel(driver->securityManager,
                                          vm->def, false);
        virSecurityManagerReleaseLabel(driver->securityManager, vm->def);
        /* Clear out dynamically assigned labels */
        if (vm->def->nseclabels &&
            vm->def->seclabels[0]->type == VIR_DOMAIN_SECLABEL_DYNAMIC) {
            VIR_FREE(vm->def->seclabels[0]->model);
            VIR_FREE(vm->def->seclabels[0]->label);
            VIR_FREE(vm->def->seclabels[0]->imagelabel);
        }
    }
    for (i = 0; i < nttyFDs; i++)
        VIR_FORCE_CLOSE(ttyFDs[i]);
    VIR_FREE(ttyFDs);
    VIR_FORCE_CLOSE(handshakefds[0]);
    VIR_FORCE_CLOSE(handshakefds[1]);
    VIR_FREE(logfile);
    virObjectUnref(cfg);
    virObjectUnref(caps);

    if (err) {
        virSetError(err);
        virFreeError(err);
    }

    return rc;

 error:
    err = virSaveLastError();
    virLXCProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED);
    goto cleanup;
}
Beispiel #21
0
static int
xenFormatXLInputDevs(virConfPtr conf, virDomainDefPtr def)
{
    size_t i;
    const char *devtype;
    virConfValuePtr usbdevices = NULL, lastdev;

    if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
        if (VIR_ALLOC(usbdevices) < 0)
            goto error;

        usbdevices->type = VIR_CONF_LIST;
        usbdevices->list = NULL;
        lastdev = NULL;
        for (i = 0; i < def->ninputs; i++) {
            if (def->inputs[i]->bus == VIR_DOMAIN_INPUT_BUS_USB) {
                if (xenConfigSetInt(conf, "usb", 1) < 0)
                    goto error;

                switch (def->inputs[i]->type) {
                    case VIR_DOMAIN_INPUT_TYPE_MOUSE:
                        devtype = "mouse";
                        break;
                    case VIR_DOMAIN_INPUT_TYPE_TABLET:
                        devtype = "tablet";
                        break;
                    case VIR_DOMAIN_INPUT_TYPE_KBD:
                        devtype = "keyboard";
                        break;
                    default:
                        continue;
                }

                if (lastdev == NULL) {
                    if (VIR_ALLOC(lastdev) < 0)
                        goto error;
                    usbdevices->list = lastdev;
                } else {
                    if (VIR_ALLOC(lastdev->next) < 0)
                        goto error;
                    lastdev = lastdev->next;
                }
                lastdev->type = VIR_CONF_STRING;
                if (VIR_STRDUP(lastdev->str, devtype) < 0)
                    goto error;
            }
        }
        if (usbdevices->list != NULL) {
            if (usbdevices->list->next == NULL) {
                /* for compatibility with Xen <= 4.2, use old syntax when
                 * only one device present */
                if (xenConfigSetString(conf, "usbdevice", usbdevices->list->str) < 0)
                    goto error;
                virConfFreeValue(usbdevices);
            } else {
                virConfSetValue(conf, "usbdevice", usbdevices);
            }
        } else {
            VIR_FREE(usbdevices);
        }
    }

    return 0;
 error:
    virConfFreeValue(usbdevices);
    return -1;
}
static virDrvOpenStatus
hypervConnectOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags)
{
    virDrvOpenStatus result = VIR_DRV_OPEN_ERROR;
    char *plus;
    hypervPrivate *priv = NULL;
    char *username = NULL;
    char *password = NULL;
    virBuffer query = VIR_BUFFER_INITIALIZER;
    Msvm_ComputerSystem *computerSystem = NULL;

    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

    /* Decline if the URI is NULL or the scheme is NULL */
    if (conn->uri == NULL || conn->uri->scheme == NULL) {
        return VIR_DRV_OPEN_DECLINED;
    }

    /* Decline if the scheme is not hyperv */
    plus = strchr(conn->uri->scheme, '+');

    if (plus == NULL) {
        if (STRCASENEQ(conn->uri->scheme, "hyperv")) {
            return VIR_DRV_OPEN_DECLINED;
        }
    } else {
        if (plus - conn->uri->scheme != 6 ||
            STRCASENEQLEN(conn->uri->scheme, "hyperv", 6)) {
            return VIR_DRV_OPEN_DECLINED;
        }

        virReportError(VIR_ERR_INVALID_ARG,
                       _("Transport '%s' in URI scheme is not supported, try again "
                         "without the transport part"), plus + 1);
        return VIR_DRV_OPEN_ERROR;
    }

    /* Require server part */
    if (conn->uri->server == NULL) {
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("URI is missing the server part"));
        return VIR_DRV_OPEN_ERROR;
    }

    /* Require auth */
    if (auth == NULL || auth->cb == NULL) {
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("Missing or invalid auth pointer"));
        return VIR_DRV_OPEN_ERROR;
    }

    /* Allocate per-connection private data */
    if (VIR_ALLOC(priv) < 0)
        goto cleanup;

    if (hypervParseUri(&priv->parsedUri, conn->uri) < 0) {
        goto cleanup;
    }

    /* Set the port dependent on the transport protocol if no port is
     * specified. This allows us to rely on the port parameter being
     * correctly set when building URIs later on, without the need to
     * distinguish between the situations port == 0 and port != 0 */
    if (conn->uri->port == 0) {
        if (STRCASEEQ(priv->parsedUri->transport, "https")) {
            conn->uri->port = 5986;
        } else {
            conn->uri->port = 5985;
        }
    }

    /* Request credentials */
    if (conn->uri->user != NULL) {
        if (VIR_STRDUP(username, conn->uri->user) < 0)
            goto cleanup;
    } else {
        username = virAuthGetUsername(conn, auth, "hyperv", "administrator", conn->uri->server);

        if (username == NULL) {
            virReportError(VIR_ERR_AUTH_FAILED, "%s", _("Username request failed"));
            goto cleanup;
        }
    }

    password = virAuthGetPassword(conn, auth, "hyperv", username, conn->uri->server);

    if (password == NULL) {
        virReportError(VIR_ERR_AUTH_FAILED, "%s", _("Password request failed"));
        goto cleanup;
    }

    /* Initialize the openwsman connection */
    priv->client = wsmc_create(conn->uri->server, conn->uri->port, "/wsman",
                               priv->parsedUri->transport, username, password);

    if (priv->client == NULL) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Could not create openwsman client"));
        goto cleanup;
    }

    if (wsmc_transport_init(priv->client, NULL) != 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Could not initialize openwsman transport"));
        goto cleanup;
    }

    /* FIXME: Currently only basic authentication is supported  */
    wsman_transport_set_auth_method(priv->client, "basic");

    /* Check if the connection can be established and if the server has the
     * Hyper-V role installed. If the call to hypervGetMsvmComputerSystemList
     * succeeds than the connection has been established. If the returned list
     * is empty than the server isn't a Hyper-V server. */
    virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_SELECT);
    virBufferAddLit(&query, "where ");
    virBufferAddLit(&query, MSVM_COMPUTERSYSTEM_WQL_PHYSICAL);

    if (hypervGetMsvmComputerSystemList(priv, &query, &computerSystem) < 0) {
        goto cleanup;
    }

    if (computerSystem == NULL) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("%s is not a Hyper-V server"), conn->uri->server);
        goto cleanup;
    }

    conn->privateData = priv;
    priv = NULL;
    result = VIR_DRV_OPEN_SUCCESS;

 cleanup:
    hypervFreePrivate(&priv);
    VIR_FREE(username);
    VIR_FREE(password);
    hypervFreeObject(priv, (hypervObject *)computerSystem);

    return result;
}
Beispiel #23
0
static int
xenParseXLSpice(virConfPtr conf, virDomainDefPtr def)
{
    virDomainGraphicsDefPtr graphics = NULL;
    unsigned long port;
    char *listenAddr = NULL;
    int val;

    if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
        if (xenConfigGetBool(conf, "spice", &val, 0) < 0)
            return -1;

        if (val) {
            if (VIR_ALLOC(graphics) < 0)
                return -1;

            graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_SPICE;
            if (xenConfigCopyStringOpt(conf, "spicehost", &listenAddr) < 0)
                goto cleanup;
            if (virDomainGraphicsListenAppendAddress(graphics, listenAddr) < 0)
                goto cleanup;
            VIR_FREE(listenAddr);

            if (xenConfigGetULong(conf, "spicetls_port", &port, 0) < 0)
                goto cleanup;
            graphics->data.spice.tlsPort = (int)port;

            if (xenConfigGetULong(conf, "spiceport", &port, 0) < 0)
                goto cleanup;

            graphics->data.spice.port = (int)port;

            if (!graphics->data.spice.tlsPort &&
                !graphics->data.spice.port)
            graphics->data.spice.autoport = 1;

            if (xenConfigGetBool(conf, "spicedisable_ticketing", &val, 0) < 0)
                goto cleanup;
            if (!val) {
                if (xenConfigCopyString(conf, "spicepasswd",
                                        &graphics->data.spice.auth.passwd) < 0)
                    goto cleanup;
            }

            if (xenConfigGetBool(conf, "spiceagent_mouse",
                                 &val, 0) < 0)
                goto cleanup;
            if (val) {
                graphics->data.spice.mousemode =
                    VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_CLIENT;
            } else {
                graphics->data.spice.mousemode =
                    VIR_DOMAIN_GRAPHICS_SPICE_MOUSE_MODE_SERVER;
            }

            if (xenConfigGetBool(conf, "spice_clipboard_sharing", &val, 0) < 0)
                goto cleanup;
            if (val)
                graphics->data.spice.copypaste = VIR_TRISTATE_BOOL_YES;
            else
                graphics->data.spice.copypaste = VIR_TRISTATE_BOOL_NO;

            if (VIR_ALLOC_N(def->graphics, 1) < 0)
                goto cleanup;
            def->graphics[0] = graphics;
            def->ngraphics = 1;
        }
    }

    return 0;

 cleanup:
    VIR_FREE(listenAddr);
    virDomainGraphicsDefFree(graphics);
    return -1;
}
static char *
hypervDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
{
    char *xml = NULL;
    hypervPrivate *priv = domain->conn->privateData;
    virDomainDefPtr def = NULL;
    char uuid_string[VIR_UUID_STRING_BUFLEN];
    virBuffer query = VIR_BUFFER_INITIALIZER;
    Msvm_ComputerSystem *computerSystem = NULL;
    Msvm_VirtualSystemSettingData *virtualSystemSettingData = NULL;
    Msvm_ProcessorSettingData *processorSettingData = NULL;
    Msvm_MemorySettingData *memorySettingData = NULL;

    /* Flags checked by virDomainDefFormat */

    if (VIR_ALLOC(def) < 0)
        goto cleanup;

    virUUIDFormat(domain->uuid, uuid_string);

    /* Get Msvm_ComputerSystem */
    if (hypervMsvmComputerSystemFromDomain(domain, &computerSystem) < 0) {
        goto cleanup;
    }

    /* Get Msvm_VirtualSystemSettingData */
    virBufferAsprintf(&query,
                      "associators of "
                      "{Msvm_ComputerSystem.CreationClassName=\"Msvm_ComputerSystem\","
                      "Name=\"%s\"} "
                      "where AssocClass = Msvm_SettingsDefineState "
                      "ResultClass = Msvm_VirtualSystemSettingData",
                      uuid_string);

    if (hypervGetMsvmVirtualSystemSettingDataList(priv, &query,
                                                  &virtualSystemSettingData) < 0) {
        goto cleanup;
    }

    if (virtualSystemSettingData == NULL) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Could not lookup %s for domain %s"),
                       "Msvm_VirtualSystemSettingData",
                       computerSystem->data->ElementName);
        goto cleanup;
    }

    /* Get Msvm_ProcessorSettingData */
    virBufferAsprintf(&query,
                      "associators of "
                      "{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} "
                      "where AssocClass = Msvm_VirtualSystemSettingDataComponent "
                      "ResultClass = Msvm_ProcessorSettingData",
                      virtualSystemSettingData->data->InstanceID);

    if (hypervGetMsvmProcessorSettingDataList(priv, &query,
                                              &processorSettingData) < 0) {
        goto cleanup;
    }

    if (processorSettingData == NULL) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Could not lookup %s for domain %s"),
                       "Msvm_ProcessorSettingData",
                       computerSystem->data->ElementName);
        goto cleanup;
    }

    /* Get Msvm_MemorySettingData */
    virBufferAsprintf(&query,
                      "associators of "
                      "{Msvm_VirtualSystemSettingData.InstanceID=\"%s\"} "
                      "where AssocClass = Msvm_VirtualSystemSettingDataComponent "
                      "ResultClass = Msvm_MemorySettingData",
                      virtualSystemSettingData->data->InstanceID);

    if (hypervGetMsvmMemorySettingDataList(priv, &query,
                                           &memorySettingData) < 0) {
        goto cleanup;
    }


    if (memorySettingData == NULL) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Could not lookup %s for domain %s"),
                       "Msvm_MemorySettingData",
                       computerSystem->data->ElementName);
        goto cleanup;
    }

    /* Fill struct */
    def->virtType = VIR_DOMAIN_VIRT_HYPERV;

    if (hypervIsMsvmComputerSystemActive(computerSystem, NULL)) {
        def->id = computerSystem->data->ProcessID;
    } else {
        def->id = -1;
    }

    if (virUUIDParse(computerSystem->data->Name, def->uuid) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Could not parse UUID from string '%s'"),
                       computerSystem->data->Name);
        return NULL;
    }

    if (VIR_STRDUP(def->name, computerSystem->data->ElementName) < 0)
        goto cleanup;

    def->mem.max_balloon = memorySettingData->data->Limit * 1024; /* megabyte to kilobyte */
    def->mem.cur_balloon = memorySettingData->data->VirtualQuantity * 1024; /* megabyte to kilobyte */

    def->vcpus = processorSettingData->data->VirtualQuantity;
    def->maxvcpus = processorSettingData->data->VirtualQuantity;

    if (VIR_STRDUP(def->os.type, "hvm") < 0)
        goto cleanup;

    /* FIXME: devices section is totally missing */

    xml = virDomainDefFormat(def, flags);

 cleanup:
    virDomainDefFree(def);
    hypervFreeObject(priv, (hypervObject *)computerSystem);
    hypervFreeObject(priv, (hypervObject *)virtualSystemSettingData);
    hypervFreeObject(priv, (hypervObject *)processorSettingData);
    hypervFreeObject(priv, (hypervObject *)memorySettingData);

    return xml;
}
Beispiel #25
0
static int
xenFormatXLDisk(virConfValuePtr list, virDomainDiskDefPtr disk)
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    virConfValuePtr val, tmp;
    int format = virDomainDiskGetFormat(disk);
    const char *driver = virDomainDiskGetDriver(disk);
    char *target = NULL;

    /* format */
    virBufferAddLit(&buf, "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 */
    virBufferAsprintf(&buf, "vdev=%s,", disk->dst);

    /* access */
    virBufferAddLit(&buf, "access=");
    if (disk->src->readonly)
        virBufferAddLit(&buf, "ro,");
    else if (disk->src->shared)
        virBufferAddLit(&buf, "!,");
    else
        virBufferAddLit(&buf, "rw,");
    if (disk->transient) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("transient disks not supported yet"));
        goto cleanup;
    }

    /* backendtype */
    if (driver) {
        virBufferAddLit(&buf, "backendtype=");
        if (STREQ(driver, "qemu") || STREQ(driver, "file"))
            virBufferAddLit(&buf, "qdisk,");
        else if (STREQ(driver, "tap"))
            virBufferAddLit(&buf, "tap,");
        else if (STREQ(driver, "phy"))
            virBufferAddLit(&buf, "phy,");
    }

    /* devtype */
    if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM)
        virBufferAddLit(&buf, "devtype=cdrom,");

    /*
     * target
     * From $xensrc/docs/misc/xl-disk-configuration.txt:
     * When this parameter is specified by name, ie with the "target="
     * syntax in the configuration file, it consumes the whole rest of the
     * <diskspec> including trailing whitespaces.  Therefore in that case
     * it must come last.
     */
    if (xenFormatXLDiskSrc(disk->src, &target) < 0)
        goto cleanup;

    virBufferAsprintf(&buf, "target=%s", target);

    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:
    VIR_FREE(target);
    virBufferFreeAndReset(&buf);
    return -1;
}
Beispiel #26
0
/**
 * virNetDevIPAddrAdd:
 * @ifname: the interface name
 * @addr: the IP address (IPv4 or IPv6)
 * @peer: The IP address of peer (IPv4 or IPv6)
 * @prefix: number of 1 bits in the netmask
 *
 * Add an IP address to an interface. This function *does not* remove
 * any previously added IP addresses - that must be done separately with
 * virNetDevIPAddrClear.
 *
 * Returns 0 in case of success or -1 in case of error.
 */
int
virNetDevIPAddrAdd(const char *ifname,
                   virSocketAddr *addr,
                   virSocketAddr *peer,
                   unsigned int prefix)
{
    virSocketAddr *broadcast = NULL;
    int ret = -1;
    struct nl_msg *nlmsg = NULL;
    struct nlmsghdr *resp = NULL;
    unsigned int recvbuflen;
    char *ipStr = NULL;
    char *peerStr = NULL;
    char *bcastStr = NULL;

    ipStr = virSocketAddrFormat(addr);
    if (peer && VIR_SOCKET_ADDR_VALID(peer))
       peerStr = virSocketAddrFormat(peer);

    /* The caller needs to provide a correct address */
    if (VIR_SOCKET_ADDR_FAMILY(addr) == AF_INET &&
        !(peer && VIR_SOCKET_ADDR_VALID(peer))) {
        /* compute a broadcast address if this is IPv4 */
        if (VIR_ALLOC(broadcast) < 0)
            goto cleanup;

        if (virSocketAddrBroadcastByPrefix(addr, prefix, broadcast) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to determine broadcast address for '%s/%d'"),
                       ipStr, prefix);
            goto cleanup;
        }
        bcastStr = virSocketAddrFormat(broadcast);
    }

    VIR_DEBUG("Adding IP address %s/%d%s%s%s%s to %s",
              NULLSTR(ipStr), prefix,
              peerStr ? " peer " : "", peerStr ? peerStr : "",
              bcastStr ? " bcast " : "", bcastStr ? bcastStr : "",
              ifname);

    if (!(nlmsg = virNetDevCreateNetlinkAddressMessage(RTM_NEWADDR, ifname,
                                                       addr, prefix,
                                                       broadcast, peer)))
        goto cleanup;

    if (virNetlinkCommand(nlmsg, &resp, &recvbuflen,
                          0, 0, NETLINK_ROUTE, 0) < 0)
        goto cleanup;


    if (virNetlinkGetErrorCode(resp, recvbuflen) < 0) {
        virReportError(VIR_ERR_SYSTEM_ERROR,
                       _("Failed to add IP address %s/%d%s%s%s%s to %s"),
                       ipStr, prefix,
                       peerStr ? " peer " : "", peerStr ? peerStr : "",
                       bcastStr ? " bcast " : "", bcastStr ? bcastStr : "",
                       ifname);
        goto cleanup;
    }

    ret = 0;
 cleanup:
    VIR_FREE(ipStr);
    VIR_FREE(peerStr);
    VIR_FREE(bcastStr);
    nlmsg_free(nlmsg);
    VIR_FREE(resp);
    VIR_FREE(broadcast);
    return ret;
}
Beispiel #27
0
/**
 * virNetlinkEventServiceStart:
 *
 * start a monitor to receive netlink messages for libvirtd.
 * This registers a netlink socket with the event interface.
 *
 * Returns -1 if the monitor cannot be registered, 0 upon success
 */
int
virNetlinkEventServiceStart(void)
{
    virNetlinkEventSrvPrivatePtr srv;
    int fd;
    int ret = -1;

    if (server)
        return 0;

    VIR_INFO("starting netlink event service");

    if (VIR_ALLOC(srv) < 0) {
        virReportOOMError();
        return -1;
    }

    if (virMutexInit(&srv->lock) < 0) {
        VIR_FREE(srv);
        return -1;
    }

    virNetlinkEventServerLock(srv);

    /* Allocate a new socket and get fd */
    srv->netlinknh = virNetlinkAlloc();

    if (!srv->netlinknh) {
        virReportSystemError(errno,
                             "%s", _("cannot allocate nlhandle for virNetlinkEvent server"));
        goto error_locked;
    }

    if (nl_connect(srv->netlinknh, NETLINK_ROUTE) < 0) {
        virReportSystemError(errno,
                             "%s", _("cannot connect to netlink socket"));
        goto error_server;
    }

    fd = nl_socket_get_fd(srv->netlinknh);

    if (fd < 0) {
        virReportSystemError(errno,
                             "%s", _("cannot get netlink socket fd"));
        goto error_server;
    }

    if (nl_socket_set_nonblocking(srv->netlinknh)) {
        virReportSystemError(errno, "%s",
                             _("cannot set netlink socket nonblocking"));
        goto error_server;
    }

    if ((srv->eventwatch = virEventAddHandle(fd,
                                             VIR_EVENT_HANDLE_READABLE,
                                             virNetlinkEventCallback,
                                             srv, NULL)) < 0) {
        netlinkError(VIR_ERR_INTERNAL_ERROR, "%s",
                     _("Failed to add netlink event handle watch"));
        goto error_server;
    }

    srv->netlinkfd = fd;
    VIR_DEBUG("netlink event listener on fd: %i running", fd);

    ret = 0;
    server = srv;

error_server:
    if (ret < 0) {
        nl_close(srv->netlinknh);
        virNetlinkFree(srv->netlinknh);
    }
error_locked:
    virNetlinkEventServerUnlock(srv);
    if (ret < 0) {
        virMutexDestroy(&srv->lock);
        VIR_FREE(srv);
    }
    return ret;
}
virStorageBackendProbeTarget(virStorageVolTargetPtr target,
                             char **backingStore,
                             int *backingStoreFormat,
                             unsigned long long *allocation,
                             unsigned long long *capacity,
                             virStorageEncryptionPtr *encryption)
{
    int fd = -1;
    int ret = -1;
    virStorageFileMetadata *meta;

    if (VIR_ALLOC(meta) < 0) {
        virReportOOMError();
        return ret;
    }

    *backingStore = NULL;
    *backingStoreFormat = VIR_STORAGE_FILE_AUTO;
    if (encryption)
        *encryption = NULL;

    if ((ret = virStorageBackendVolOpenCheckMode(target->path,
                                        VIR_STORAGE_VOL_FS_REFRESH_FLAGS)) < 0)
        goto error; /* Take care to propagate ret, it is not always -1 */
    fd = ret;

    if ((ret = virStorageBackendUpdateVolTargetInfoFD(target, fd,
                                                      allocation,
                                                      capacity)) < 0) {
        goto error;
    }

    if ((target->format = virStorageFileProbeFormatFromFD(target->path, fd)) < 0) {
        ret = -1;
        goto error;
    }

    if (virStorageFileGetMetadataFromFD(target->path, fd,
                                        target->format,
                                        meta) < 0) {
        ret = -1;
        goto error;
    }

    VIR_FORCE_CLOSE(fd);

    if (meta->backingStore) {
        *backingStore = meta->backingStore;
        meta->backingStore = NULL;
        if (meta->backingStoreFormat == VIR_STORAGE_FILE_AUTO) {
            if ((ret = virStorageFileProbeFormat(*backingStore)) < 0) {
                /* If the backing file is currently unavailable, only log an error,
                 * but continue. Returning -1 here would disable the whole storage
                 * pool, making it unavailable for even maintenance. */
                virStorageReportError(VIR_ERR_INTERNAL_ERROR,
                                      _("cannot probe backing volume format: %s"),
                                      *backingStore);
                ret = -3;
            } else {
                *backingStoreFormat = ret;
                ret = 0;
            }
        } else {
            *backingStoreFormat = meta->backingStoreFormat;
            ret = 0;
        }
    } else {
        ret = 0;
    }

    if (capacity && meta->capacity)
        *capacity = meta->capacity;

    if (encryption != NULL && meta->encrypted) {
        if (VIR_ALLOC(*encryption) < 0) {
            virReportOOMError();
            goto cleanup;
        }

        switch (target->format) {
        case VIR_STORAGE_FILE_QCOW:
        case VIR_STORAGE_FILE_QCOW2:
            (*encryption)->format = VIR_STORAGE_ENCRYPTION_FORMAT_QCOW;
            break;
        default:
            break;
        }

        /* XXX ideally we'd fill in secret UUID here
         * but we cannot guarantee 'conn' is non-NULL
         * at this point in time :-(  So we only fill
         * in secrets when someone first queries a vol
         */
    }

    virStorageFileFreeMetadata(meta);

    return ret;

error:
    VIR_FORCE_CLOSE(fd);

cleanup:
    virStorageFileFreeMetadata(meta);
    return ret;

}
Beispiel #29
0
static int virStorageBackendRBDRefreshPool(virConnectPtr conn ATTRIBUTE_UNUSED,
        virStoragePoolObjPtr pool)
{
    size_t max_size = 1024;
    int ret = -1;
    int len = -1;
    int i;
    char *name, *names = NULL;
    virStorageBackendRBDStatePtr ptr;
    ptr.cluster = NULL;
    ptr.ioctx = NULL;

    if (virStorageBackendRBDOpenRADOSConn(&ptr, conn, pool) < 0) {
        goto cleanup;
    }

    if (rados_ioctx_create(ptr.cluster,
                           pool->def->source.name, &ptr.ioctx) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to create the RBD IoCTX. Does the pool '%s' exist?"),
                       pool->def->source.name);
        goto cleanup;
    }

    struct rados_cluster_stat_t stat;
    if (rados_cluster_stat(ptr.cluster, &stat) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("failed to stat the RADOS cluster"));
        goto cleanup;
    }

    struct rados_pool_stat_t poolstat;
    if (rados_ioctx_pool_stat(ptr.ioctx, &poolstat) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to stat the RADOS pool '%s'"),
                       pool->def->source.name);
        goto cleanup;
    }

    pool->def->capacity = stat.kb * 1024;
    pool->def->available = stat.kb_avail * 1024;
    pool->def->allocation = poolstat.num_bytes;

    VIR_DEBUG("Utilization of RBD pool %s: (kb: %llu kb_avail: %llu num_bytes: %llu)",
              pool->def->source.name, (unsigned long long)stat.kb,
              (unsigned long long)stat.kb_avail,
              (unsigned long long)poolstat.num_bytes);

    while (true) {
        if (VIR_ALLOC_N(names, max_size) < 0)
            goto out_of_memory;

        len = rbd_list(ptr.ioctx, names, &max_size);
        if (len >= 0)
            break;
        if (len != -ERANGE) {
            VIR_WARN("%s", _("A problem occurred while listing RBD images"));
            goto cleanup;
        }
        VIR_FREE(names);
    }

    for (i = 0, name = names; name < names + max_size; i++) {
        virStorageVolDefPtr vol;

        if (VIR_REALLOC_N(pool->volumes.objs, pool->volumes.count + 1) < 0) {
            virStoragePoolObjClearVols(pool);
            goto out_of_memory;
        }

        if (STREQ(name, ""))
            break;

        if (VIR_ALLOC(vol) < 0)
            goto out_of_memory;

        vol->name = strdup(name);
        if (vol->name == NULL) {
            VIR_FREE(vol);
            goto out_of_memory;
        }

        name += strlen(name) + 1;

        if (volStorageBackendRBDRefreshVolInfo(vol, pool, ptr) < 0) {
            virStorageVolDefFree(vol);
            goto cleanup;
        }

        pool->volumes.objs[pool->volumes.count++] = vol;
    }

    VIR_DEBUG("Found %d images in RBD pool %s",
              pool->volumes.count, pool->def->source.name);

    ret = 0;

cleanup:
    VIR_FREE(names);
    virStorageBackendRBDCloseRADOSConn(ptr);
    return ret;

out_of_memory:
    virReportOOMError();
    goto cleanup;
}
Beispiel #30
0
struct daemonConfig*
daemonConfigNew(bool privileged ATTRIBUTE_UNUSED)
{
    struct daemonConfig *data;
    char *localhost;
    int ret;

    if (VIR_ALLOC(data) < 0) {
        virReportOOMError();
        return NULL;
    }

    data->listen_tls = 1;
    data->listen_tcp = 0;

    if (!(data->tls_port = strdup(LIBVIRTD_TLS_PORT)))
        goto no_memory;
    if (!(data->tcp_port = strdup(LIBVIRTD_TCP_PORT)))
        goto no_memory;

    /* Only default to PolicyKit if running as root */
#if WITH_POLKIT
    if (privileged) {
        data->auth_unix_rw = REMOTE_AUTH_POLKIT;
        data->auth_unix_ro = REMOTE_AUTH_POLKIT;
    } else {
#endif
        data->auth_unix_rw = REMOTE_AUTH_NONE;
        data->auth_unix_ro = REMOTE_AUTH_NONE;
#if WITH_POLKIT
    }
#endif

    if (data->auth_unix_rw == REMOTE_AUTH_POLKIT)
        data->unix_sock_rw_perms = strdup("0777"); /* Allow world */
    else
        data->unix_sock_rw_perms = strdup("0700"); /* Allow user only */
    data->unix_sock_ro_perms = strdup("0777"); /* Always allow world */
    if (!data->unix_sock_ro_perms ||
        !data->unix_sock_rw_perms)
        goto no_memory;

#if WITH_SASL
    data->auth_tcp = REMOTE_AUTH_SASL;
#else
    data->auth_tcp = REMOTE_AUTH_NONE;
#endif
    data->auth_tls = REMOTE_AUTH_NONE;

    data->mdns_adv = 0;

    data->min_workers = 5;
    data->max_workers = 20;
    data->max_clients = 20;

    data->prio_workers = 5;

    data->max_requests = 20;
    data->max_client_requests = 5;

    data->log_buffer_size = 64;

    data->audit_level = 1;
    data->audit_logging = 0;

    data->keepalive_interval = 5;
    data->keepalive_count = 5;
    data->keepalive_required = 0;

    localhost = virGetHostname(NULL);
    if (localhost == NULL) {
        /* we couldn't resolve the hostname; assume that we are
         * running in disconnected operation, and report a less
         * useful Avahi string
         */
        ret = virAsprintf(&data->mdns_name, "Virtualization Host");
    } else {
        char *tmp;
        /* Extract the host part of the potentially FQDN */
        if ((tmp = strchr(localhost, '.')))
            *tmp = '\0';
        ret = virAsprintf(&data->mdns_name, "Virtualization Host %s",
                          localhost);
    }
    VIR_FREE(localhost);
    if (ret < 0)
        goto no_memory;

    return data;

no_memory:
    virReportOOMError();
    daemonConfigFree(data);
    return NULL;
}