示例#1
0
int
libxlDriverNodeGetInfo(libxlDriverPrivatePtr driver, virNodeInfoPtr info)
{
    libxl_physinfo phy_info;
    virArch hostarch = virArchFromHost();
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
    int ret = -1;

    if (libxl_get_physinfo(cfg->ctx, &phy_info)) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("libxl_get_physinfo_info failed"));
        goto cleanup;
    }

    if (virStrcpyStatic(info->model, virArchToString(hostarch)) == NULL) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("machine type %s too big for destination"),
                       virArchToString(hostarch));
        goto cleanup;
    }

    info->memory = phy_info.total_pages * (cfg->verInfo->pagesize / 1024);
    info->cpus = phy_info.nr_cpus;
    info->nodes = phy_info.nr_nodes;
    info->cores = phy_info.cores_per_socket;
    info->threads = phy_info.threads_per_core;
    info->sockets = 1;
    info->mhz = phy_info.cpu_khz / 1000;

    ret = 0;

 cleanup:
    virObjectUnref(cfg);
    return ret;
}
示例#2
0
文件: nodeinfo.c 项目: emaste/libvirt
int nodeGetInfo(virConnectPtr conn ATTRIBUTE_UNUSED, virNodeInfoPtr nodeinfo)
{
    virArch hostarch = virArchFromHost();

    if (virStrcpyStatic(nodeinfo->model, virArchToString(hostarch)) == NULL)
        return -1;

#ifdef __linux__
    {
    int ret = -1;
    FILE *cpuinfo = fopen(CPUINFO_PATH, "r");
    if (!cpuinfo) {
        virReportSystemError(errno,
                             _("cannot open %s"), CPUINFO_PATH);
        return -1;
    }

    ret = linuxNodeInfoCPUPopulate(cpuinfo, SYSFS_SYSTEM_PATH, nodeinfo);
    if (ret < 0)
        goto cleanup;

    /* Convert to KB. */
    nodeinfo->memory = physmem_total() / 1024;

cleanup:
    VIR_FORCE_FCLOSE(cpuinfo);
    return ret;
    }
#else
    /* XXX Solaris will need an impl later if they port QEMU driver */
    virReportError(VIR_ERR_NO_SUPPORT, "%s",
                   _("node info not implemented on this platform"));
    return -1;
#endif
}
示例#3
0
int
virTypedParamsCopy(virTypedParameterPtr *dst,
                   virTypedParameterPtr src,
                   int nparams)
{
    size_t i;

    *dst = NULL;
    if (!src || nparams <= 0)
        return 0;

    if (VIR_ALLOC_N(*dst, nparams) < 0)
        return -1;

    for (i = 0; i < nparams; i++) {
        ignore_value(virStrcpyStatic((*dst)[i].field, src[i].field));
        (*dst)[i].type = src[i].type;
        if (src[i].type == VIR_TYPED_PARAM_STRING) {
            if (VIR_STRDUP((*dst)[i].value.s, src[i].value.s) < 0) {
                virTypedParamsFree(*dst, i - 1);
                *dst = NULL;
                return -1;
            }
        } else {
            (*dst)[i].value = src[i].value;
        }
    }

    return 0;
}
示例#4
0
static int virNetDevBridgeCmd(const char *brname,
                              u_long op,
                              void *arg,
                              size_t argsize)
{
    int s;
    int ret = -1;
    struct ifdrv ifd;

    memset(&ifd, 0, sizeof(ifd));

    if ((s = socket(AF_LOCAL, SOCK_DGRAM, 0)) < 0) {
        virReportSystemError(errno, "%s",
                             _("Cannot open network interface control socket"));
        return -1;
    }

    if (virStrcpyStatic(ifd.ifd_name, brname) == NULL) {
       virReportSystemError(ERANGE,
                            _("Network interface name '%s' is too long"),
                            brname);
       goto cleanup;
    }

    ifd.ifd_cmd = op;
    ifd.ifd_len = argsize;
    ifd.ifd_data = arg;

    ret = ioctl(s, SIOCSDRVSPEC, &ifd);

 cleanup:
    VIR_FORCE_CLOSE(s);

    return ret;
}
示例#5
0
static int virNetDevSetupControlFull(const char *ifname,
                                     struct ifreq *ifr,
                                     int domain,
                                     int type)
{
    int fd;

    memset(ifr, 0, sizeof(*ifr));

    if (virStrcpyStatic(ifr->ifr_name, ifname) == NULL) {
        virReportSystemError(ERANGE,
                             _("Network interface name '%s' is too long"),
                             ifname);
        return -1;
    }

    if ((fd = socket(domain, type, 0)) < 0) {
        virReportSystemError(errno, "%s",
                             _("Cannot open network interface control socket"));
        return -1;
    }

    if (virSetInherit(fd, false) < 0) {
        virReportSystemError(errno, "%s",
                             _("Cannot set close-on-exec flag for socket"));
        VIR_FORCE_CLOSE(fd);
        return -1;
    }

    return fd;
}
示例#6
0
int nodeGetInfo(virConnectPtr conn ATTRIBUTE_UNUSED, virNodeInfoPtr nodeinfo) {
    struct utsname info;

    memset(nodeinfo, 0, sizeof(*nodeinfo));
    uname(&info);

    if (virStrcpyStatic(nodeinfo->model, info.machine) == NULL)
        return -1;

#ifdef __linux__
    {
    int ret;
    FILE *cpuinfo = fopen(CPUINFO_PATH, "r");
    if (!cpuinfo) {
        virReportSystemError(errno,
                             _("cannot open %s"), CPUINFO_PATH);
        return -1;
    }
    ret = linuxNodeInfoCPUPopulate(cpuinfo, nodeinfo);
    fclose(cpuinfo);
    if (ret < 0)
        return -1;

    /* Convert to KB. */
    nodeinfo->memory = physmem_total () / 1024;

    return ret;
    }
#else
    /* XXX Solaris will need an impl later if they port QEMU driver */
    nodeReportError(VIR_ERR_NO_SUPPORT, "%s",
                    _("node info not implemented on this platform"));
    return -1;
#endif
}
示例#7
0
文件: datatypes.c 项目: rbu/libvirt
/**
 * virGetStorageVol:
 * @conn: the hypervisor connection
 * @pool: pool owning the volume
 * @name: pointer to the storage vol name
 * @key: pointer to unique key of the volume
 *
 * Lookup if the storage vol is already registered for that connection,
 * if yes return a new pointer to it, if no allocate a new structure,
 * and register it in the table. In any case a corresponding call to
 * virUnrefStorageVol() is needed to not leak data.
 *
 * Returns a pointer to the storage vol, or NULL in case of failure
 */
virStorageVolPtr
virGetStorageVol(virConnectPtr conn, const char *pool, const char *name,
                 const char *key) {
    virStorageVolPtr ret = NULL;

    if (!VIR_IS_CONNECT(conn)) {
        virLibConnError(VIR_ERR_INVALID_ARG, _("no connection"));
        return NULL;
    }
    if (name == NULL) {
        virLibConnError(VIR_ERR_INVALID_ARG, _("missing name"));
        return NULL;
    }
    if (key == NULL) {
        virLibConnError(VIR_ERR_INVALID_ARG, _("missing key"));
        return NULL;
    }
    virMutexLock(&conn->lock);

    if (VIR_ALLOC(ret) < 0) {
        virMutexUnlock(&conn->lock);
        virReportOOMError();
        goto error;
    }
    ret->pool = strdup(pool);
    if (ret->pool == NULL) {
        virMutexUnlock(&conn->lock);
        virReportOOMError();
        goto error;
    }
    ret->name = strdup(name);
    if (ret->name == NULL) {
        virMutexUnlock(&conn->lock);
        virReportOOMError();
        goto error;
    }
    if (virStrcpyStatic(ret->key, key) == NULL) {
        virMutexUnlock(&conn->lock);
        virLibConnError(VIR_ERR_INTERNAL_ERROR,
                        _("Volume key %s too large for destination"), key);
        goto error;
    }
    ret->magic = VIR_STORAGE_VOL_MAGIC;
    ret->conn = conn;

    conn->refs++;
    ret->refs++;
    virMutexUnlock(&conn->lock);
    return(ret);

error:
    if (ret != NULL) {
        VIR_FREE(ret->name);
        VIR_FREE(ret->pool);
        VIR_FREE(ret);
    }
    return(NULL);
}
示例#8
0
/* Assign name, type, and the appropriately typed arg to param; in the
 * case of a string, the caller is assumed to have malloc'd a string,
 * or can pass NULL to have this function malloc an empty string.
 * Return 0 on success, -1 after an error message on failure.  */
int
virTypedParameterAssign(virTypedParameterPtr param, const char *name,
                        int type, ...)
{
    va_list ap;
    int ret = -1;

    va_start(ap, type);

    if (virStrcpyStatic(param->field, name) == NULL) {
        virReportError(VIR_ERR_INTERNAL_ERROR, _("Field name '%s' too long"),
                       name);
        goto cleanup;
    }
    param->type = type;
    switch (type) {
    case VIR_TYPED_PARAM_INT:
        param->value.i = va_arg(ap, int);
        break;
    case VIR_TYPED_PARAM_UINT:
        param->value.ui = va_arg(ap, unsigned int);
        break;
    case VIR_TYPED_PARAM_LLONG:
        param->value.l = va_arg(ap, long long int);
        break;
    case VIR_TYPED_PARAM_ULLONG:
        param->value.ul = va_arg(ap, unsigned long long int);
        break;
    case VIR_TYPED_PARAM_DOUBLE:
        param->value.d = va_arg(ap, double);
        break;
    case VIR_TYPED_PARAM_BOOLEAN:
        param->value.b = !!va_arg(ap, int);
        break;
    case VIR_TYPED_PARAM_STRING:
        param->value.s = va_arg(ap, char *);
        if (!param->value.s && VIR_STRDUP(param->value.s, "") < 0)
            goto cleanup;
        break;
    default:
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unexpected type %d for field %s"), type, name);
        goto cleanup;
    }

    ret = 0;
 cleanup:
    va_end(ap);
    return ret;
}
示例#9
0
static int
virHostCPUStatsAssign(virNodeCPUStatsPtr param,
                      const char *name,
                      unsigned long long value)
{
    if (virStrcpyStatic(param->field, name) == NULL) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("kernel cpu time field is too long"
                               " for the destination"));
        return -1;
    }
    param->value = value;
    return 0;
}
示例#10
0
int
virNWFilterLockIface(const char *ifname) {
    virNWFilterIfaceLockPtr ifaceLock;

    virMutexLock(&ifaceMapLock);

    ifaceLock = virHashLookup(ifaceLockMap, ifname);
    if (!ifaceLock) {
        if (VIR_ALLOC(ifaceLock) < 0) {
            virReportOOMError();
            goto err_exit;
        }

        if (virMutexInitRecursive(&ifaceLock->lock) < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("mutex initialization failed"));
            VIR_FREE(ifaceLock);
            goto err_exit;
        }

        if (virStrcpyStatic(ifaceLock->ifname, ifname) == NULL) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("interface name %s does not fit into "
                             "buffer "),
                           ifaceLock->ifname);
            VIR_FREE(ifaceLock);
            goto err_exit;
        }

        while (virHashAddEntry(ifaceLockMap, ifname, ifaceLock)) {
            VIR_FREE(ifaceLock);
            goto err_exit;
        }

        ifaceLock->refctr = 0;
    }

    ifaceLock->refctr++;

    virMutexUnlock(&ifaceMapLock);

    virMutexLock(&ifaceLock->lock);

    return 0;

 err_exit:
    virMutexUnlock(&ifaceMapLock);

    return -1;
}
示例#11
0
static int lxcMonitorServer(const char *sockpath)
{
    int fd;
    struct sockaddr_un addr;

    if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
        virReportSystemError(errno,
                             _("failed to create server socket '%s'"),
                             sockpath);
        goto error;
    }

    unlink(sockpath);
    memset(&addr, 0, sizeof(addr));
    addr.sun_family = AF_UNIX;
    if (virStrcpyStatic(addr.sun_path, sockpath) == NULL) {
        lxcError(VIR_ERR_INTERNAL_ERROR,
                 _("Socket path %s too long for destination"), sockpath);
        goto error;
    }

    if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
        virReportSystemError(errno,
                             _("failed to bind server socket '%s'"),
                             sockpath);
        goto error;
    }
    if (listen(fd, 30 /* backlog */ ) < 0) {
        virReportSystemError(errno,
                             _("failed to listen server socket %s"),
                             sockpath);
        goto error;
    }

    return fd;

error:
    VIR_FORCE_CLOSE(fd);
    return -1;
}
示例#12
0
static int
virHostMemGetStatsFreeBSD(virNodeMemoryStatsPtr params,
                          int *nparams)
{
    size_t i, j = 0;
    unsigned long pagesize = getpagesize() >> 10;
    long bufpages;
    size_t bufpages_size = sizeof(bufpages);
    struct field_sysctl_map {
        const char *field;
        const char *sysctl_name;
    } sysctl_map[] = {
        {VIR_NODE_MEMORY_STATS_TOTAL, "vm.stats.vm.v_page_count"},
        {VIR_NODE_MEMORY_STATS_FREE, "vm.stats.vm.v_free_count"},
        {VIR_NODE_MEMORY_STATS_CACHED, "vm.stats.vm.v_cache_count"},
        {NULL, NULL}
    };

    if ((*nparams) == 0) {
        *nparams = BSD_MEMORY_STATS_ALL;
        return 0;
    }

    if ((*nparams) != BSD_MEMORY_STATS_ALL) {
        virReportInvalidArg(nparams,
                            _("nparams in %s must be %d"),
                            __FUNCTION__, BSD_MEMORY_STATS_ALL);
        return -1;
    }

    for (i = 0; sysctl_map[i].field != NULL; i++) {
        u_int value;
        size_t value_size = sizeof(value);
        virNodeMemoryStatsPtr param;

        if (sysctlbyname(sysctl_map[i].sysctl_name, &value,
                         &value_size, NULL, 0) < 0) {
            virReportSystemError(errno,
                                 _("sysctl failed for '%s'"),
                                 sysctl_map[i].sysctl_name);
            return -1;
        }

        param = &params[j++];
        if (virStrcpyStatic(param->field, sysctl_map[i].field) == NULL) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Field '%s' too long for destination"),
                           sysctl_map[i].field);
            return -1;
        }
        param->value = (unsigned long long)value * pagesize;
    }

    {
        virNodeMemoryStatsPtr param = &params[j++];

        if (sysctlbyname("vfs.bufspace", &bufpages, &bufpages_size, NULL, 0) < 0) {
            virReportSystemError(errno,
                                 _("sysctl failed for '%s'"),
                                 "vfs.bufspace");
            return -1;
        }
        if (virStrcpyStatic(param->field, VIR_NODE_MEMORY_STATS_BUFFERS) == NULL) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Field '%s' too long for destination"),
                           VIR_NODE_MEMORY_STATS_BUFFERS);
            return -1;
        }
        param->value = (unsigned long long)bufpages >> 10;
    }

    return 0;
}
示例#13
0
static int
virHostMemGetStatsLinux(FILE *meminfo,
                        int cellNum,
                        virNodeMemoryStatsPtr params,
                        int *nparams)
{
    int ret = -1;
    size_t i = 0, j = 0, k = 0;
    int found = 0;
    int nr_param;
    char line[1024];
    char meminfo_hdr[VIR_NODE_MEMORY_STATS_FIELD_LENGTH];
    unsigned long val;
    struct field_conv {
        const char *meminfo_hdr;  /* meminfo header */
        const char *field;        /* MemoryStats field name */
    } field_conv[] = {
        {"MemTotal:", VIR_NODE_MEMORY_STATS_TOTAL},
        {"MemFree:",  VIR_NODE_MEMORY_STATS_FREE},
        {"Buffers:",  VIR_NODE_MEMORY_STATS_BUFFERS},
        {"Cached:",   VIR_NODE_MEMORY_STATS_CACHED},
        {NULL,        NULL}
    };

    if (cellNum == VIR_NODE_MEMORY_STATS_ALL_CELLS) {
        nr_param = LINUX_NB_MEMORY_STATS_ALL;
    } else {
        nr_param = LINUX_NB_MEMORY_STATS_CELL;
    }

    if ((*nparams) == 0) {
        /* Current number of memory stats supported by linux */
        *nparams = nr_param;
        ret = 0;
        goto cleanup;
    }

    if ((*nparams) != nr_param) {
        virReportInvalidArg(nparams,
                            _("nparams in %s must be %d"),
                            __FUNCTION__, nr_param);
        goto cleanup;
    }

    while (fgets(line, sizeof(line), meminfo) != NULL) {
        char *buf = line;

        if (STRPREFIX(buf, "Node ")) {
            /*
             * /sys/devices/system/node/nodeX/meminfo format is below.
             * So, skip prefix "Node XX ".
             *
             * Node 0 MemTotal:        8386980 kB
             * Node 0 MemFree:         5300920 kB
             *         :
             */
            char *p;

            p = buf;
            for (i = 0; i < 2; i++) {
                p = strchr(p, ' ');
                if (p == NULL) {
                    virReportError(VIR_ERR_INTERNAL_ERROR,
                                   "%s", _("no prefix found"));
                    goto cleanup;
                }
                p++;
            }
            buf = p;
        }

        if (sscanf(buf, "%s %lu kB", meminfo_hdr, &val) < 2)
            continue;

        for (j = 0; field_conv[j].meminfo_hdr != NULL; j++) {
            struct field_conv *convp = &field_conv[j];

            if (STREQ(meminfo_hdr, convp->meminfo_hdr)) {
                virNodeMemoryStatsPtr param = &params[k++];

                if (virStrcpyStatic(param->field, convp->field) == NULL) {
                    virReportError(VIR_ERR_INTERNAL_ERROR,
                                   "%s", _("Field kernel memory too long for destination"));
                    goto cleanup;
                }
                param->value = val;
                found++;
                break;
            }
        }
        if (found >= nr_param)
            break;
    }

    if (found == 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("no available memory line found"));
        goto cleanup;
    }

    ret = 0;

 cleanup:
    return ret;
}
示例#14
0
/* Validate that PARAMS contains only recognized parameter names with
 * correct types, and with no duplicates except for parameters
 * specified with VIR_TYPED_PARAM_MULTIPLE flag in type.
 * Pass in as many name/type pairs as appropriate, and pass NULL to end
 * the list of accepted parameters.  Return 0 on success, -1 on failure
 * with error message already issued.  */
int
virTypedParamsValidate(virTypedParameterPtr params, int nparams, ...)
{
    va_list ap;
    int ret = -1;
    size_t i, j;
    const char *name;
    int type;
    size_t nkeys = 0, nkeysalloc = 0;
    virTypedParameterPtr sorted = NULL, keys = NULL;

    va_start(ap, nparams);

    if (VIR_ALLOC_N(sorted, nparams) < 0)
        goto cleanup;

    /* Here we intentionally don't copy values */
    memcpy(sorted, params, sizeof(*params) * nparams);
    qsort(sorted, nparams, sizeof(*sorted), virTypedParamsSortName);

    name = va_arg(ap, const char *);
    while (name) {
        type = va_arg(ap, int);
        if (VIR_RESIZE_N(keys, nkeysalloc, nkeys, 1) < 0)
            goto cleanup;

        if (virStrcpyStatic(keys[nkeys].field, name) == NULL) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Field name '%s' too long"), name);
            goto cleanup;
        }

        keys[nkeys].type = type & ~VIR_TYPED_PARAM_MULTIPLE;
        /* Value is not used anyway */
        keys[nkeys].value.i = type & VIR_TYPED_PARAM_MULTIPLE;

        nkeys++;
        name = va_arg(ap, const char *);
    }

    qsort(keys, nkeys, sizeof(*keys), virTypedParamsSortName);

    for (i = 0, j = 0; i < nparams && j < nkeys;) {
        if (STRNEQ(sorted[i].field, keys[j].field)) {
            j++;
        } else {
            if (i > j && !(keys[j].value.i & VIR_TYPED_PARAM_MULTIPLE)) {
                virReportError(VIR_ERR_INVALID_ARG,
                               _("parameter '%s' occurs multiple times"),
                               sorted[i].field);
                goto cleanup;
            }
            if (sorted[i].type != keys[j].type) {
                const char *badtype;

                badtype = virTypedParameterTypeToString(sorted[i].type);
                if (!badtype)
                    badtype = virTypedParameterTypeToString(0);
                virReportError(VIR_ERR_INVALID_ARG,
                               _("invalid type '%s' for parameter '%s', "
                                 "expected '%s'"),
                               badtype, sorted[i].field,
                               virTypedParameterTypeToString(keys[j].type));
                goto cleanup;
            }
            i++;
        }
    }

    if (j == nkeys && i != nparams) {
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
                       _("parameter '%s' not supported"),
                       sorted[i].field);
        goto cleanup;
    }

    ret = 0;
 cleanup:
    va_end(ap);
    VIR_FREE(sorted);
    VIR_FREE(keys);
    return ret;
}
virNetDevVPortProfilePtr
virNetDevVPortProfileParse(xmlNodePtr node, unsigned int flags)
{
    char *virtPortType;
    char *virtPortManagerID = NULL;
    char *virtPortTypeID = NULL;
    char *virtPortTypeIDVersion = NULL;
    char *virtPortInstanceID = NULL;
    char *virtPortProfileID = NULL;
    char *virtPortInterfaceID = NULL;
    virNetDevVPortProfilePtr virtPort = NULL;
    xmlNodePtr cur = node->children;

    if (VIR_ALLOC(virtPort) < 0)
        return NULL;

    if ((virtPortType = virXMLPropString(node, "type")) &&
        (virtPort->virtPortType = virNetDevVPortTypeFromString(virtPortType)) <= 0) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("unknown virtualport type %s"), virtPortType);
        goto error;
    }

    if ((virtPort->virtPortType == VIR_NETDEV_VPORT_PROFILE_NONE) &&
        (flags & VIR_VPORT_XML_REQUIRE_TYPE)) {
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("missing required virtualport type"));
        goto error;
    }

    while (cur != NULL) {
        if (xmlStrEqual(cur->name, BAD_CAST "parameters")) {
            virtPortManagerID = virXMLPropString(cur, "managerid");
            virtPortTypeID = virXMLPropString(cur, "typeid");
            virtPortTypeIDVersion = virXMLPropString(cur, "typeidversion");
            virtPortInstanceID = virXMLPropString(cur, "instanceid");
            virtPortProfileID = virXMLPropString(cur, "profileid");
            virtPortInterfaceID = virXMLPropString(cur, "interfaceid");
            break;
        }
        cur = cur->next;
    }

    if (virtPortManagerID) {
        unsigned int val;

        if (virStrToLong_ui(virtPortManagerID, NULL, 0, &val)) {
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("cannot parse value of managerid parameter"));
            goto error;
        }
        if (val > 0xff) {
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("value of managerid out of range"));
            goto error;
        }
        virtPort->managerID = (uint8_t)val;
        virtPort->managerID_specified = true;
    }

    if (virtPortTypeID) {
        unsigned int val;

        if (virStrToLong_ui(virtPortTypeID, NULL, 0, &val)) {
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("cannot parse value of typeid parameter"));
            goto error;
        }
        if (val > 0xffffff) {
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("value for typeid out of range"));
            goto error;
        }
        virtPort->typeID = (uint32_t)val;
        virtPort->typeID_specified = true;
    }

    if (virtPortTypeIDVersion) {
        unsigned int val;

        if (virStrToLong_ui(virtPortTypeIDVersion, NULL, 0, &val)) {
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("cannot parse value of typeidversion parameter"));
            goto error;
        }
        if (val > 0xff) {
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("value of typeidversion out of range"));
            goto error;
        }
        virtPort->typeIDVersion = (uint8_t)val;
        virtPort->typeIDVersion_specified = true;
    }

    if (virtPortInstanceID) {
        if (virUUIDParse(virtPortInstanceID, virtPort->instanceID) < 0) {
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("cannot parse instanceid parameter as a uuid"));
            goto error;
        }
        virtPort->instanceID_specified = true;
    }

    if (virtPortProfileID &&
        !virStrcpyStatic(virtPort->profileID, virtPortProfileID)) {
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("profileid parameter too long"));
        goto error;
    }

    if (virtPortInterfaceID) {
        if (virUUIDParse(virtPortInterfaceID, virtPort->interfaceID) < 0) {
            virReportError(VIR_ERR_XML_ERROR, "%s",
                           _("cannot parse interfaceid parameter as a uuid"));
            goto error;
        }
        virtPort->interfaceID_specified = true;
    }

    /* generate default instanceID/interfaceID if appropriate */
    if (flags & VIR_VPORT_XML_GENERATE_MISSING_DEFAULTS) {
        if (!virtPort->instanceID_specified &&
            (virtPort->virtPortType == VIR_NETDEV_VPORT_PROFILE_8021QBG ||
             virtPort->virtPortType == VIR_NETDEV_VPORT_PROFILE_NONE)) {
            if (virUUIDGenerate(virtPort->instanceID) < 0) {
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("cannot generate a random uuid for instanceid"));
                goto error;
            }
            virtPort->instanceID_specified = true;
        }
        if (!virtPort->interfaceID_specified &&
            (virtPort->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH ||
             virtPort->virtPortType == VIR_NETDEV_VPORT_PROFILE_NONE)) {
            if (virUUIDGenerate(virtPort->interfaceID) < 0) {
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("cannot generate a random uuid for interfaceid"));
                goto error;
            }
            virtPort->interfaceID_specified = true;
        }
    }

    /* check for required/unsupported attributes */

    if ((flags & VIR_VPORT_XML_REQUIRE_ALL_ATTRIBUTES) &&
        (virNetDevVPortProfileCheckComplete(virtPort, false) < 0)) {
        goto error;
    }

    if (virNetDevVPortProfileCheckNoExtras(virtPort) < 0)
        goto error;

cleanup:
    VIR_FREE(virtPortManagerID);
    VIR_FREE(virtPortTypeID);
    VIR_FREE(virtPortTypeIDVersion);
    VIR_FREE(virtPortInstanceID);
    VIR_FREE(virtPortProfileID);
    VIR_FREE(virtPortType);
    VIR_FREE(virtPortInterfaceID);

    return virtPort;

error:
    VIR_FREE(virtPort);
    goto cleanup;
}
示例#16
0
int linuxNodeGetCPUStats(FILE *procstat,
                         int cpuNum,
                         virNodeCPUStatsPtr params,
                         int *nparams)
{
    int ret = -1;
    char line[1024];
    unsigned long long usr, ni, sys, idle, iowait;
    unsigned long long irq, softirq, steal, guest, guest_nice;
    char cpu_header[3 + INT_BUFSIZE_BOUND(cpuNum)];

    if ((*nparams) == 0) {
        /* Current number of cpu stats supported by linux */
        *nparams = LINUX_NB_CPU_STATS;
        ret = 0;
        goto cleanup;
    }

    if ((*nparams) != LINUX_NB_CPU_STATS) {
        nodeReportError(VIR_ERR_INVALID_ARG,
                        "%s", _("Invalid parameter count"));
        goto cleanup;
    }

    if (cpuNum == VIR_NODE_CPU_STATS_ALL_CPUS) {
        strcpy(cpu_header, "cpu");
    } else {
        snprintf(cpu_header, sizeof(cpu_header), "cpu%d", cpuNum);
    }

    while (fgets(line, sizeof(line), procstat) != NULL) {
        char *buf = line;

        if (STRPREFIX(buf, cpu_header)) { /* aka logical CPU time */
            int i;

            if (sscanf(buf,
                       "%*s %llu %llu %llu %llu %llu" // user ~ iowait
                       "%llu %llu %llu %llu %llu",    // irq  ~ guest_nice
                       &usr, &ni, &sys, &idle, &iowait,
                       &irq, &softirq, &steal, &guest, &guest_nice) < 4) {
                continue;
            }

            for (i = 0; i < *nparams; i++) {
                virNodeCPUStatsPtr param = &params[i];

                switch (i) {
                case 0: /* fill kernel cpu time here */
                    if (virStrcpyStatic(param->field, VIR_NODE_CPU_STATS_KERNEL) == NULL) {
                        nodeReportError(VIR_ERR_INTERNAL_ERROR,
                                        "%s", _("Field kernel cpu time too long for destination"));
                        goto cleanup;
                    }
                    param->value = (sys + irq + softirq) * TICK_TO_NSEC;
                    break;

                case 1: /* fill user cpu time here */
                    if (virStrcpyStatic(param->field, VIR_NODE_CPU_STATS_USER) == NULL) {
                        nodeReportError(VIR_ERR_INTERNAL_ERROR,
                                        "%s", _("Field kernel cpu time too long for destination"));
                        goto cleanup;
                    }
                    param->value = (usr + ni) * TICK_TO_NSEC;
                    break;

                case 2: /* fill idle cpu time here */
                    if (virStrcpyStatic(param->field, VIR_NODE_CPU_STATS_IDLE) == NULL) {
                        nodeReportError(VIR_ERR_INTERNAL_ERROR,
                                        "%s", _("Field kernel cpu time too long for destination"));
                        goto cleanup;
                    }
                    param->value = idle * TICK_TO_NSEC;
                    break;

                case 3: /* fill iowait cpu time here */
                    if (virStrcpyStatic(param->field, VIR_NODE_CPU_STATS_IOWAIT) == NULL) {
                        nodeReportError(VIR_ERR_INTERNAL_ERROR,
                                        "%s", _("Field kernel cpu time too long for destination"));
                        goto cleanup;
                    }
                    param->value = iowait * TICK_TO_NSEC;
                    break;

                default:
                    break;
                    /* should not hit here */
                }
            }
            ret = 0;
            goto cleanup;
        }
    }

    nodeReportError(VIR_ERR_INVALID_ARG, "%s", _("Invalid cpu number"));

cleanup:
    return ret;
}
示例#17
0
int linuxNodeInfoCPUPopulate(FILE *cpuinfo,
                             const char *sysfs_cpudir,
                             virNodeInfoPtr nodeinfo)
{
    char line[1024];
    DIR *cpudir = NULL;
    struct dirent *cpudirent = NULL;
    unsigned int cpu;
    unsigned long core, sock, cur_threads;
    cpu_set_t core_mask;
    cpu_set_t socket_mask;
    int online;

    nodeinfo->cpus = 0;
    nodeinfo->mhz = 0;
    nodeinfo->cores = 0;

    nodeinfo->nodes = 1;
# if HAVE_NUMACTL
    if (numa_available() >= 0)
        nodeinfo->nodes = numa_max_node() + 1;
# endif

    if (!virStrcpyStatic(sysfs_path, sysfs_cpudir)) {
        virReportSystemError(errno, _("cannot copy %s"), sysfs_cpudir);
        return -1;
    }
    /* NB: It is impossible to fill our nodes, since cpuinfo
     * has no knowledge of NUMA nodes */

    /* NOTE: hyperthreads are ignored here; they are parsed out of /sys */
    while (fgets(line, sizeof(line), cpuinfo) != NULL) {
# if defined(__x86_64__) || \
    defined(__amd64__)  || \
    defined(__i386__)
        char *buf = line;
        if (STRPREFIX(buf, "cpu MHz")) {
            char *p;
            unsigned int ui;
            buf += 9;
            while (*buf && c_isspace(*buf))
                buf++;
            if (*buf != ':' || !buf[1]) {
                nodeReportError(VIR_ERR_INTERNAL_ERROR,
                                "%s", _("parsing cpuinfo cpu MHz"));
                return -1;
            }
            if (virStrToLong_ui(buf+1, &p, 10, &ui) == 0
                /* Accept trailing fractional part.  */
                && (*p == '\0' || *p == '.' || c_isspace(*p)))
                nodeinfo->mhz = ui;
        }
# elif defined(__powerpc__) || \
      defined(__powerpc64__)
        char *buf = line;
        if (STRPREFIX(buf, "clock")) {
            char *p;
            unsigned int ui;
            buf += 5;
            while (*buf && c_isspace(*buf))
                buf++;
            if (*buf != ':' || !buf[1]) {
                nodeReportError(VIR_ERR_INTERNAL_ERROR,
                                "%s", _("parsing cpuinfo cpu MHz"));
                return -1;
            }
            if (virStrToLong_ui(buf+1, &p, 10, &ui) == 0
                /* Accept trailing fractional part.  */
                && (*p == '\0' || *p == '.' || c_isspace(*p)))
                nodeinfo->mhz = ui;
            /* No other interesting infos are available in /proc/cpuinfo.
             * However, there is a line identifying processor's version,
             * identification and machine, but we don't want it to be caught
             * and parsed in next iteration, because it is not in expected
             * format and thus lead to error. */
        }
# else
#  warning Parser for /proc/cpuinfo needs to be adapted for your architecture
# endif
    }

    /* OK, we've parsed clock speed out of /proc/cpuinfo. Get the core, socket
     * thread and topology information from /sys
     */
    cpudir = opendir(sysfs_cpudir);
    if (cpudir == NULL) {
        virReportSystemError(errno, _("cannot opendir %s"), sysfs_cpudir);
        return -1;
    }

    CPU_ZERO(&core_mask);
    CPU_ZERO(&socket_mask);

    while ((cpudirent = readdir(cpudir))) {
        if (sscanf(cpudirent->d_name, "cpu%u", &cpu) != 1)
            continue;

        online = cpu_online(cpu);
        if (online < 0) {
            closedir(cpudir);
            return -1;
        }
        if (!online)
            continue;
        nodeinfo->cpus++;

        /* Parse core */
        core = parse_core(cpu);
        if (!CPU_ISSET(core, &core_mask)) {
            CPU_SET(core, &core_mask);
            nodeinfo->cores++;
        }

        /* Parse socket */
        sock = parse_socket(cpu);
        if (!CPU_ISSET(sock, &socket_mask)) {
            CPU_SET(sock, &socket_mask);
            nodeinfo->sockets++;
        }

        cur_threads = count_thread_siblings(cpu);
        if (cur_threads == 0) {
            closedir(cpudir);
            return -1;
        }
        if (cur_threads > nodeinfo->threads)
            nodeinfo->threads = cur_threads;
    }
    if (errno) {
        virReportSystemError(errno,
                             _("problem reading %s"), sysfs_path);
        closedir(cpudir);
        return -1;
    }

    closedir(cpudir);

    /* there should always be at least one cpu, socket and one thread */
    if (nodeinfo->cpus == 0) {
        nodeReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("no CPUs found"));
        return -1;
    }
    if (nodeinfo->sockets == 0) {
        nodeReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("no sockets found"));
        return -1;
    }
    if (nodeinfo->threads == 0) {
        nodeReportError(VIR_ERR_INTERNAL_ERROR,
                        "%s", _("no threads found"));
        return -1;
    }

    /* nodeinfo->sockets is supposed to be a number of sockets per NUMA node,
     * however if NUMA nodes are not composed of whole sockets, we just lie
     * about the number of NUMA nodes and force apps to check capabilities XML
     * for the actual NUMA topology.
     */
    if (nodeinfo->sockets % nodeinfo->nodes == 0)
        nodeinfo->sockets /= nodeinfo->nodes;
    else
        nodeinfo->nodes = 1;

    return 0;
}
示例#18
0
static int
qemuAgentOpenUnix(const char *monitor, pid_t cpid, bool *inProgress)
{
    struct sockaddr_un addr;
    int monfd;
    int timeout = 3; /* In seconds */
    int ret, i = 0;

    *inProgress = false;

    if ((monfd = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) {
        virReportSystemError(errno,
                             "%s", _("failed to create socket"));
        return -1;
    }

    if (virSetNonBlock(monfd) < 0) {
        virReportSystemError(errno, "%s",
                             _("Unable to put monitor "
                               "into non-blocking mode"));
        goto error;
    }

    if (virSetCloseExec(monfd) < 0) {
        virReportSystemError(errno, "%s",
                             _("Unable to set monitor "
                               "close-on-exec flag"));
        goto error;
    }

    memset(&addr, 0, sizeof(addr));
    addr.sun_family = AF_UNIX;
    if (virStrcpyStatic(addr.sun_path, monitor) == NULL) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Agent path %s too big for destination"), monitor);
        goto error;
    }

    do {
        ret = connect(monfd, (struct sockaddr *) &addr, sizeof(addr));

        if (ret == 0)
            break;

        if ((errno == ENOENT || errno == ECONNREFUSED) &&
            virProcessKill(cpid, 0) == 0) {
            /* ENOENT       : Socket may not have shown up yet
             * ECONNREFUSED : Leftover socket hasn't been removed yet */
            continue;
        }

        if ((errno == EINPROGRESS) ||
            (errno == EAGAIN)) {
            VIR_DEBUG("Connection attempt continuing in background");
            *inProgress = true;
            ret = 0;
            break;
        }

        virReportSystemError(errno, "%s",
                             _("failed to connect to monitor socket"));
        goto error;

    } while ((++i <= timeout*5) && (usleep(.2 * 1000000) <= 0));

    if (ret != 0) {
        virReportSystemError(errno, "%s",
                             _("monitor socket did not show up."));
        goto error;
    }

    return monfd;

error:
    VIR_FORCE_CLOSE(monfd);
    return -1;
}
示例#19
0
int nodeGetInfo(virNodeInfoPtr nodeinfo)
{
    virArch hostarch = virArchFromHost();

    memset(nodeinfo, 0, sizeof(*nodeinfo));

    if (virStrcpyStatic(nodeinfo->model, virArchToString(hostarch)) == NULL)
        return -1;

#ifdef __linux__
    {
    int ret = -1;
    FILE *cpuinfo = fopen(CPUINFO_PATH, "r");
    if (!cpuinfo) {
        virReportSystemError(errno,
                             _("cannot open %s"), CPUINFO_PATH);
        return -1;
    }

    ret = linuxNodeInfoCPUPopulate(cpuinfo, SYSFS_SYSTEM_PATH, nodeinfo);
    if (ret < 0)
        goto cleanup;

    /* Convert to KB. */
    nodeinfo->memory = physmem_total() / 1024;

cleanup:
    VIR_FORCE_FCLOSE(cpuinfo);
    return ret;
    }
#elif defined(__FreeBSD__)
    {
    nodeinfo->nodes = 1;
    nodeinfo->sockets = 1;
    nodeinfo->threads = 1;

    nodeinfo->cpus = freebsdNodeGetCPUCount();
    if (nodeinfo->cpus == -1)
        return -1;

    nodeinfo->cores = nodeinfo->cpus;

    unsigned long cpu_freq;
    size_t cpu_freq_len = sizeof(cpu_freq);

    if (sysctlbyname("dev.cpu.0.freq", &cpu_freq, &cpu_freq_len, NULL, 0) < 0) {
        virReportSystemError(errno, "%s", _("cannot obtain CPU freq"));
        return -1;
    }

    nodeinfo->mhz = cpu_freq;

    /* get memory information */
    int mib[2] = { CTL_HW, HW_PHYSMEM };
    unsigned long physmem;
    size_t len = sizeof(physmem);

    if (sysctl(mib, 2, &physmem, &len, NULL, 0) == -1) {
        virReportSystemError(errno, "%s", _("cannot obtain memory size"));
        return -1;
    }

    nodeinfo->memory = (unsigned long)(physmem / 1024);

    return 0;
    }
#else
    /* XXX Solaris will need an impl later if they port QEMU driver */
    virReportError(VIR_ERR_NO_SUPPORT, "%s",
                   _("node info not implemented on this platform"));
    return -1;
#endif
}
示例#20
0
int virNetSocketNewListenUNIX(const char *path,
                              mode_t mask,
                              uid_t user,
                              gid_t grp,
                              virNetSocketPtr *retsock)
{
    virSocketAddr addr;
    mode_t oldmask;
    int fd;

    *retsock = NULL;

    memset(&addr, 0, sizeof(addr));

    addr.len = sizeof(addr.data.un);

    if ((fd = socket(PF_UNIX, SOCK_STREAM, 0)) < 0) {
        virReportSystemError(errno, "%s", _("Failed to create socket"));
        goto error;
    }

    addr.data.un.sun_family = AF_UNIX;
    if (virStrcpyStatic(addr.data.un.sun_path, path) == NULL) {
        virReportSystemError(ENOMEM, _("Path %s too long for unix socket"), path);
        goto error;
    }
    if (addr.data.un.sun_path[0] == '@')
        addr.data.un.sun_path[0] = '\0';
    else
        unlink(addr.data.un.sun_path);

    oldmask = umask(~mask);

    if (bind(fd, &addr.data.sa, addr.len) < 0) {
        umask(oldmask);
        virReportSystemError(errno,
                             _("Failed to bind socket to '%s'"),
                             path);
        goto error;
    }
    umask(oldmask);

    /* chown() doesn't work for abstract sockets but we use them only
     * if libvirtd runs unprivileged
     */
    if (grp != 0 && chown(path, user, grp)) {
        virReportSystemError(errno,
                             _("Failed to change ownership of '%s' to %d:%d"),
                             path, (int) user, (int) grp);
        goto error;
    }

    if (!(*retsock = virNetSocketNew(&addr, NULL, false, fd, -1, 0)))
        goto error;

    return 0;

error:
    if (path[0] != '@')
        unlink(path);
    VIR_FORCE_CLOSE(fd);
    return -1;
}
示例#21
0
/* virNetDevVPortProfileMerge() - merge the attributes in mods into
 * orig. If anything that is set in mods has already been set in orig
 * *and doesn't match*, log an error and return -1, otherwise return 0.
 */
static int
virNetDevVPortProfileMerge(virNetDevVPortProfilePtr orig,
                           virNetDevVPortProfilePtr mods)
{
    enum virNetDevVPortProfile otype;

    if (!orig || !mods)
        return 0;

    otype = orig->virtPortType;

    if (mods->virtPortType != VIR_NETDEV_VPORT_PROFILE_NONE) {
        if (otype != VIR_NETDEV_VPORT_PROFILE_NONE &&
            otype != mods->virtPortType) {
            virReportError(VIR_ERR_XML_ERROR,
                           _("attempt to merge virtualports "
                             "with mismatched types (%s and %s)"),
                           virNetDevVPortTypeToString(otype),
                           virNetDevVPortTypeToString(mods->virtPortType));
            return -1;
        }
        otype = orig->virtPortType = mods->virtPortType;
    }

    if (mods->managerID_specified &&
        (otype == VIR_NETDEV_VPORT_PROFILE_8021QBG ||
         otype == VIR_NETDEV_VPORT_PROFILE_NONE)) {
        if (orig->managerID_specified &&
            (orig->managerID != mods->managerID)) {
            virReportError(VIR_ERR_XML_ERROR,
                           _("attempt to merge virtualports "
                             "with mismatched managerids (%d and %d)"),
                           orig->managerID, mods->managerID);
            return -1;
        }
        orig->managerID = mods->managerID;
        orig->managerID_specified = true;
    }

    if (mods->typeID_specified &&
        (otype == VIR_NETDEV_VPORT_PROFILE_8021QBG ||
         otype == VIR_NETDEV_VPORT_PROFILE_NONE)) {
        if (orig->typeID_specified &&
            (orig->typeID != mods->typeID)) {
            virReportError(VIR_ERR_XML_ERROR,
                           _("attempt to merge virtualports "
                             "with mismatched typeids (%d and %d)"),
                           orig->typeID, mods->typeID);
            return -1;
        }
        orig->typeID = mods->typeID;
        orig->typeID_specified = true;
    }

    if (mods->typeIDVersion_specified &&
        (otype == VIR_NETDEV_VPORT_PROFILE_8021QBG ||
         otype == VIR_NETDEV_VPORT_PROFILE_NONE)) {
        if (orig->typeIDVersion_specified &&
            (orig->typeIDVersion != mods->typeIDVersion)) {
            virReportError(VIR_ERR_XML_ERROR,
                           _("attempt to merge virtualports with "
                             "mismatched typeidversions (%d and %d)"),
                           orig->typeIDVersion, mods->typeIDVersion);
            return -1;
        }
        orig->typeIDVersion = mods->typeIDVersion;
        orig->typeIDVersion_specified = true;
    }

    if (mods->instanceID_specified &&
        (otype == VIR_NETDEV_VPORT_PROFILE_8021QBG ||
         otype == VIR_NETDEV_VPORT_PROFILE_NONE)) {
        if (orig->instanceID_specified &&
            memcmp(orig->instanceID, mods->instanceID,
                   sizeof(orig->instanceID))) {
            char origuuid[VIR_UUID_STRING_BUFLEN];
            char modsuuid[VIR_UUID_STRING_BUFLEN];

            virReportError(VIR_ERR_XML_ERROR,
                           _("attempt to merge virtualports with "
                             "mismatched instanceids ('%s' and '%s')"),
                           virUUIDFormat(orig->instanceID, origuuid),
                           virUUIDFormat(mods->instanceID, modsuuid));
            return -1;
        }
        memcpy(orig->instanceID, mods->instanceID, sizeof(orig->instanceID));
        orig->instanceID_specified = true;
    }

    if (mods->interfaceID_specified &&
        (otype == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH ||
         otype == VIR_NETDEV_VPORT_PROFILE_NONE)) {
        if (orig->interfaceID_specified &&
            memcmp(orig->interfaceID, mods->interfaceID,
                   sizeof(orig->interfaceID))) {
            char origuuid[VIR_UUID_STRING_BUFLEN];
            char modsuuid[VIR_UUID_STRING_BUFLEN];

            virReportError(VIR_ERR_XML_ERROR,
                           _("attempt to merge virtualports with "
                             "mismatched interfaceids ('%s' and '%s')"),
                           virUUIDFormat(orig->interfaceID, origuuid),
                           virUUIDFormat(mods->interfaceID, modsuuid));
            return -1;
        }
        memcpy(orig->interfaceID, mods->interfaceID, sizeof(orig->interfaceID));
        orig->interfaceID_specified = true;
    }

    if (mods->profileID[0] &&
        (otype == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH ||
         otype == VIR_NETDEV_VPORT_PROFILE_8021QBH ||
         otype == VIR_NETDEV_VPORT_PROFILE_NONE)) {
        if (orig->profileID[0] &&
            STRNEQ(orig->profileID, mods->profileID)) {
            virReportError(VIR_ERR_XML_ERROR,
                           _("attempt to merge virtualports with "
                             "mismatched profileids ('%s' and '%s')"),
                           orig->profileID, mods->profileID);
            return -1;
        }
        if (virStrcpyStatic(orig->profileID, mods->profileID) == NULL) {
            /* this should never happen - it indicates mods->profileID
             * isn't properly null terminated. */
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("corrupted profileid string"));
            return -1;
        }
    }
    return 0;
}
static int virLockManagerSanlockSetupLockspace(void)
{
    int fd = -1;
    struct stat st;
    int rv;
    struct sanlk_lockspace ls;
    char *path = NULL;
    char *dir = NULL;
    int retries = LOCKSPACE_RETRIES;

    if (virAsprintf(&path, "%s/%s",
                    driver->autoDiskLeasePath,
                    VIR_LOCK_MANAGER_SANLOCK_AUTO_DISK_LOCKSPACE) < 0) {
        virReportOOMError();
        goto error;
    }

    if (!virStrcpyStatic(ls.name,
                         VIR_LOCK_MANAGER_SANLOCK_AUTO_DISK_LOCKSPACE)) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Lockspace path '%s' exceeded %d characters"),
                       VIR_LOCK_MANAGER_SANLOCK_AUTO_DISK_LOCKSPACE,
                       SANLK_PATH_LEN);
        goto error;
    }
    ls.host_id = 0; /* Doesn't matter for initialization */
    ls.flags = 0;
    if (!virStrcpy(ls.host_id_disk.path, path, SANLK_PATH_LEN)) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Lockspace path '%s' exceeded %d characters"),
                       path, SANLK_PATH_LEN);
        goto error;
    }
    ls.host_id_disk.offset = 0;

    /* Stage 1: Ensure the lockspace file exists on disk, has
     * space allocated for it and is initialized with lease
     */
    if (stat(path, &st) < 0) {
        int perms = 0600;
        VIR_DEBUG("Lockspace %s does not yet exist", path);

        if (!(dir = mdir_name(path))) {
            virReportOOMError();
            goto error;
        }
        if (stat(dir, &st) < 0 || !S_ISDIR(st.st_mode)) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Unable to create lockspace %s: parent directory"
                             " does not exist or is not a directory"),
                           path);
            goto error;
        }

        if (driver->group != (gid_t) -1)
            perms |= 0060;

        if ((fd = open(path, O_WRONLY|O_CREAT|O_EXCL, perms)) < 0) {
            if (errno != EEXIST) {
                virReportSystemError(errno,
                                     _("Unable to create lockspace %s"),
                                     path);
                goto error;
            }
            VIR_DEBUG("Someone else just created lockspace %s", path);
        } else {
            /* chown() the path to make sure sanlock can access it */
            if ((driver->user != (uid_t) -1 || driver->group != (gid_t) -1) &&
                    (fchown(fd, driver->user, driver->group) < 0)) {
                virReportSystemError(errno,
                                     _("cannot chown '%s' to (%u, %u)"),
                                     path,
                                     (unsigned int) driver->user,
                                     (unsigned int) driver->group);
                goto error_unlink;
            }

            if ((rv = sanlock_align(&ls.host_id_disk)) < 0) {
                if (rv <= -200)
                    virReportError(VIR_ERR_INTERNAL_ERROR,
                                   _("Unable to query sector size %s: error %d"),
                                   path, rv);
                else
                    virReportSystemError(-rv,
                                         _("Unable to query sector size %s"),
                                         path);
                goto error_unlink;
            }

            /*
             * Pre allocate enough data for 1 block of leases at preferred alignment
             */
            if (safezero(fd, 0, rv) < 0) {
                virReportSystemError(errno,
                                     _("Unable to allocate lockspace %s"),
                                     path);
                goto error_unlink;
            }

            if (VIR_CLOSE(fd) < 0) {
                virReportSystemError(errno,
                                     _("Unable to save lockspace %s"),
                                     path);
                goto error_unlink;
            }

            if ((rv = sanlock_init(&ls, NULL, 0, 0)) < 0) {
                if (rv <= -200)
                    virReportError(VIR_ERR_INTERNAL_ERROR,
                                   _("Unable to initialize lockspace %s: error %d"),
                                   path, rv);
                else
                    virReportSystemError(-rv,
                                         _("Unable to initialize lockspace %s"),
                                         path);
                goto error_unlink;
            }
            VIR_DEBUG("Lockspace %s has been initialized", path);
        }
    } else if (S_ISREG(st.st_mode)) {
        /* okay, the lease file exists. Check the permissions */
        if (((driver->user != (uid_t) -1 && driver->user != st.st_uid) ||
                (driver->group != (gid_t) -1 && driver->group != st.st_gid)) &&
                (chown(path, driver->user, driver->group) < 0)) {
            virReportSystemError(errno,
                                 _("cannot chown '%s' to (%u, %u)"),
                                 path,
                                 (unsigned int) driver->user,
                                 (unsigned int) driver->group);
            goto error;
        }

        if ((driver->group != (gid_t) -1 && (st.st_mode & 0060) != 0060) &&
                chmod(path, 0660) < 0) {
            virReportSystemError(errno,
                                 _("cannot chmod '%s' to 0660"),
                                 path);
            goto error;
        }
    }

    ls.host_id = driver->hostID;
    /* Stage 2: Try to register the lockspace with the daemon.  If the lockspace
     * is already registered, we should get EEXIST back in which case we can
     * just carry on with life. If EINPROGRESS is returned, we have two options:
     * either call a sanlock API that blocks us until lockspace changes state,
     * or we can fallback to polling.
     */
retry:
    if ((rv = sanlock_add_lockspace(&ls, 0)) < 0) {
        if (-rv == EINPROGRESS && --retries) {
#ifdef HAVE_SANLOCK_INQ_LOCKSPACE
            /* we have this function which blocks until lockspace change the
             * state. It returns 0 if lockspace has been added, -ENOENT if it
             * hasn't. */
            VIR_DEBUG("Inquiring lockspace");
            if (sanlock_inq_lockspace(&ls, SANLK_INQ_WAIT) < 0)
                VIR_DEBUG("Unable to inquire lockspace");
#else
            /* fall back to polling */
            VIR_DEBUG("Sleeping for %dms", LOCKSPACE_SLEEP);
            usleep(LOCKSPACE_SLEEP * 1000);
#endif
            VIR_DEBUG("Retrying to add lockspace (left %d)", retries);
            goto retry;
        }
        if (-rv != EEXIST) {
            if (rv <= -200)
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("Unable to add lockspace %s: error %d"),
                               path, rv);
            else
                virReportSystemError(-rv,
                                     _("Unable to add lockspace %s"),
                                     path);
            goto error;
        } else {
            VIR_DEBUG("Lockspace %s is already registered", path);
        }
    } else {
        VIR_DEBUG("Lockspace %s has been registered", path);
    }

    VIR_FREE(path);
    VIR_FREE(dir);
    return 0;

error_unlink:
    unlink(path);
error:
    VIR_FORCE_CLOSE(fd);
    VIR_FREE(path);
    VIR_FREE(dir);
    return -1;
}
示例#23
0
virNetDevVPortProfilePtr
virNetDevVPortProfileParse(xmlNodePtr node)
{
    char *virtPortType;
    char *virtPortManagerID = NULL;
    char *virtPortTypeID = NULL;
    char *virtPortTypeIDVersion = NULL;
    char *virtPortInstanceID = NULL;
    char *virtPortProfileID = NULL;
    char *virtPortInterfaceID = NULL;
    virNetDevVPortProfilePtr virtPort = NULL;
    xmlNodePtr cur = node->children;

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

    virtPortType = virXMLPropString(node, "type");
    if (!virtPortType) {
        virReportError(VIR_ERR_XML_ERROR, "%s",
                       _("missing virtualportprofile type"));
        goto error;
    }

    if ((virtPort->virtPortType = virNetDevVPortTypeFromString(virtPortType)) <= 0) {
        virReportError(VIR_ERR_XML_ERROR,
                       _("unknown virtualportprofile type %s"), virtPortType);
        goto error;
    }

    while (cur != NULL) {
        if (xmlStrEqual(cur->name, BAD_CAST "parameters")) {

            virtPortManagerID = virXMLPropString(cur, "managerid");
            virtPortTypeID = virXMLPropString(cur, "typeid");
            virtPortTypeIDVersion = virXMLPropString(cur, "typeidversion");
            virtPortInstanceID = virXMLPropString(cur, "instanceid");
            virtPortProfileID = virXMLPropString(cur, "profileid");
            virtPortInterfaceID = virXMLPropString(cur, "interfaceid");
            break;
        }

        cur = cur->next;
    }

    switch (virtPort->virtPortType) {
    case VIR_NETDEV_VPORT_PROFILE_8021QBG:
        if (virtPortManagerID     != NULL && virtPortTypeID     != NULL &&
            virtPortTypeIDVersion != NULL) {
            unsigned int val;

            if (virStrToLong_ui(virtPortManagerID, NULL, 0, &val)) {
                virReportError(VIR_ERR_XML_ERROR, "%s",
                                     _("cannot parse value of managerid parameter"));
                goto error;
            }

            if (val > 0xff) {
                virReportError(VIR_ERR_XML_ERROR, "%s",
                                     _("value of managerid out of range"));
                goto error;
            }

            virtPort->u.virtPort8021Qbg.managerID = (uint8_t)val;

            if (virStrToLong_ui(virtPortTypeID, NULL, 0, &val)) {
                virReportError(VIR_ERR_XML_ERROR, "%s",
                                     _("cannot parse value of typeid parameter"));
                goto error;
            }

            if (val > 0xffffff) {
                virReportError(VIR_ERR_XML_ERROR, "%s",
                                     _("value for typeid out of range"));
                goto error;
            }

            virtPort->u.virtPort8021Qbg.typeID = (uint32_t)val;

            if (virStrToLong_ui(virtPortTypeIDVersion, NULL, 0, &val)) {
                virReportError(VIR_ERR_XML_ERROR, "%s",
                                     _("cannot parse value of typeidversion parameter"));
                goto error;
            }

            if (val > 0xff) {
                virReportError(VIR_ERR_XML_ERROR, "%s",
                                     _("value of typeidversion out of range"));
                goto error;
            }

            virtPort->u.virtPort8021Qbg.typeIDVersion = (uint8_t)val;

            if (virtPortInstanceID != NULL) {
                if (virUUIDParse(virtPortInstanceID,
                                 virtPort->u.virtPort8021Qbg.instanceID)) {
                    virReportError(VIR_ERR_XML_ERROR, "%s",
                                         _("cannot parse instanceid parameter as a uuid"));
                    goto error;
                }
            } else {
                if (virUUIDGenerate(virtPort->u.virtPort8021Qbg.instanceID)) {
                    virReportError(VIR_ERR_XML_ERROR, "%s",
                                         _("cannot generate a random uuid for instanceid"));
                    goto error;
                }
            }

            virtPort->virtPortType = VIR_NETDEV_VPORT_PROFILE_8021QBG;

        } else {
                    virReportError(VIR_ERR_XML_ERROR, "%s",
                                         _("a parameter is missing for 802.1Qbg description"));
            goto error;
        }
        break;

    case VIR_NETDEV_VPORT_PROFILE_8021QBH:
        if (virtPortProfileID != NULL) {
            if (virStrcpyStatic(virtPort->u.virtPort8021Qbh.profileID,
                                virtPortProfileID) != NULL) {
                virtPort->virtPortType = VIR_NETDEV_VPORT_PROFILE_8021QBH;
            } else {
                virReportError(VIR_ERR_XML_ERROR, "%s",
                                     _("profileid parameter too long"));
                goto error;
            }
        } else {
            virReportError(VIR_ERR_XML_ERROR, "%s",
                                 _("profileid parameter is missing for 802.1Qbh description"));
            goto error;
        }
        break;
    case VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH:
        if (virtPortInterfaceID != NULL) {
            if (virUUIDParse(virtPortInterfaceID,
                             virtPort->u.openvswitch.interfaceID)) {
                virReportError(VIR_ERR_XML_ERROR, "%s",
                               _("cannot parse interfaceid parameter as a uuid"));
                goto error;
            }
        } else {
            if (virUUIDGenerate(virtPort->u.openvswitch.interfaceID)) {
                virReportError(VIR_ERR_XML_ERROR, "%s",
                               _("cannot generate a random uuid for interfaceid"));
                goto error;
            }
        }
        /* profileid is not mandatory for Open vSwitch */
        if (virtPortProfileID != NULL) {
            if (virStrcpyStatic(virtPort->u.openvswitch.profileID,
                                virtPortProfileID) == NULL) {
                virReportError(VIR_ERR_XML_ERROR, "%s",
                               _("profileid parameter too long"));
                goto error;
            }
        } else {
            virtPort->u.openvswitch.profileID[0] = '\0';
        }
        break;

    default:
        virReportError(VIR_ERR_XML_ERROR,
                       _("unexpected virtualport type %d"), virtPort->virtPortType);
        goto error;
    }

cleanup:
    VIR_FREE(virtPortManagerID);
    VIR_FREE(virtPortTypeID);
    VIR_FREE(virtPortTypeIDVersion);
    VIR_FREE(virtPortInstanceID);
    VIR_FREE(virtPortProfileID);
    VIR_FREE(virtPortType);

    return virtPort;

error:
    VIR_FREE(virtPort);
    goto cleanup;
}
示例#24
0
static int
virHostCPUGetStatsFreeBSD(int cpuNum,
                          virNodeCPUStatsPtr params,
                          int *nparams)
{
    const char *sysctl_name;
    long *cpu_times;
    struct clockinfo clkinfo;
    size_t i, j, cpu_times_size, clkinfo_size;
    int cpu_times_num, offset, hz, stathz, ret = -1;
    struct field_cpu_map {
        const char *field;
        int idx[CPUSTATES];
    } cpu_map[] = {
        {VIR_NODE_CPU_STATS_KERNEL, {CP_SYS}},
        {VIR_NODE_CPU_STATS_USER, {CP_USER, CP_NICE}},
        {VIR_NODE_CPU_STATS_IDLE, {CP_IDLE}},
        {VIR_NODE_CPU_STATS_INTR, {CP_INTR}},
        {NULL, {0}}
    };

    if ((*nparams) == 0) {
        *nparams = BSD_CPU_STATS_ALL;
        return 0;
    }

    if ((*nparams) != BSD_CPU_STATS_ALL) {
        virReportInvalidArg(*nparams,
                            _("nparams in %s must be equal to %d"),
                            __FUNCTION__, BSD_CPU_STATS_ALL);
        return -1;
    }

    clkinfo_size = sizeof(clkinfo);
    if (sysctlbyname("kern.clockrate", &clkinfo, &clkinfo_size, NULL, 0) < 0) {
        virReportSystemError(errno,
                             _("sysctl failed for '%s'"),
                             "kern.clockrate");
        return -1;
    }

    stathz = clkinfo.stathz;
    hz = clkinfo.hz;

    if (cpuNum == VIR_NODE_CPU_STATS_ALL_CPUS) {
        sysctl_name = "kern.cp_time";
        cpu_times_num = 1;
        offset = 0;
    } else {
        sysctl_name = "kern.cp_times";
        cpu_times_num = virHostCPUGetCountAppleFreeBSD();

        if (cpuNum >= cpu_times_num) {
            virReportInvalidArg(cpuNum,
                                _("Invalid cpuNum in %s"),
                                __FUNCTION__);
            return -1;
        }

        offset = cpu_times_num * CPUSTATES;
    }

    cpu_times_size = sizeof(long) * cpu_times_num * CPUSTATES;

    if (VIR_ALLOC_N(cpu_times, cpu_times_num * CPUSTATES) < 0)
        goto cleanup;

    if (sysctlbyname(sysctl_name, cpu_times, &cpu_times_size, NULL, 0) < 0) {
        virReportSystemError(errno,
                             _("sysctl failed for '%s'"),
                             sysctl_name);
        goto cleanup;
    }

    for (i = 0; cpu_map[i].field != NULL; i++) {
        virNodeCPUStatsPtr param = &params[i];

        if (virStrcpyStatic(param->field, cpu_map[i].field) == NULL) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Field '%s' too long for destination"),
                           cpu_map[i].field);
            goto cleanup;
        }

        param->value = 0;
        for (j = 0; j < ARRAY_CARDINALITY(cpu_map[i].idx); j++)
            param->value += cpu_times[offset + cpu_map[i].idx[j]] * TICK_TO_NSEC;
    }

    ret = 0;

 cleanup:
    VIR_FREE(cpu_times);

    return ret;
}
示例#25
0
/* Assign name, type, and convert the argument from a const string.
 * In case of a string, the string is copied.
 * Return 0 on success, -1 after an error message on failure.  */
int
virTypedParameterAssignFromStr(virTypedParameterPtr param, const char *name,
                               int type, const char *val)
{
    int ret = -1;

    if (!val) {
        virReportError(VIR_ERR_INVALID_ARG, _("NULL value for field '%s'"),
                       name);
        goto cleanup;
    }

    if (virStrcpyStatic(param->field, name) == NULL) {
        virReportError(VIR_ERR_INTERNAL_ERROR, _("Field name '%s' too long"),
                       name);
        goto cleanup;
    }

    param->type = type;
    switch (type) {
    case VIR_TYPED_PARAM_INT:
        if (virStrToLong_i(val, NULL, 10, &param->value.i) < 0) {
            virReportError(VIR_ERR_INVALID_ARG,
                           _("Invalid value for field '%s': expected int"),
                           name);
            goto cleanup;
        }
        break;
    case VIR_TYPED_PARAM_UINT:
        if (virStrToLong_ui(val, NULL, 10, &param->value.ui) < 0) {
            virReportError(VIR_ERR_INVALID_ARG,
                           _("Invalid value for field '%s': "
                             "expected unsigned int"),
                           name);
            goto cleanup;
        }
        break;
    case VIR_TYPED_PARAM_LLONG:
        if (virStrToLong_ll(val, NULL, 10, &param->value.l) < 0) {
            virReportError(VIR_ERR_INVALID_ARG,
                           _("Invalid value for field '%s': "
                             "expected long long"),
                           name);
            goto cleanup;
        }
        break;
    case VIR_TYPED_PARAM_ULLONG:
        if (virStrToLong_ull(val, NULL, 10, &param->value.ul) < 0) {
            virReportError(VIR_ERR_INVALID_ARG,
                           _("Invalid value for field '%s': "
                             "expected unsigned long long"),
                           name);
            goto cleanup;
        }
        break;
    case VIR_TYPED_PARAM_DOUBLE:
        if (virStrToDouble(val, NULL, &param->value.d) < 0) {
            virReportError(VIR_ERR_INVALID_ARG,
                           _("Invalid value for field '%s': "
                             "expected double"),
                           name);
            goto cleanup;
        }
        break;
    case VIR_TYPED_PARAM_BOOLEAN:
        if (STRCASEEQ(val, "true") || STREQ(val, "1")) {
            param->value.b = true;
        } else if (STRCASEEQ(val, "false") || STREQ(val, "0")) {
            param->value.b = false;
        } else {
            virReportError(VIR_ERR_INVALID_ARG,
                           _("Invalid boolean value for field '%s'"), name);
            goto cleanup;
        }
        break;
    case VIR_TYPED_PARAM_STRING:
        if (VIR_STRDUP(param->value.s, val) < 0)
            goto cleanup;
        break;
    default:
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unexpected type %d for field %s"), type, name);
        goto cleanup;
    }

    ret = 0;
 cleanup:
    return ret;
}