コード例 #1
0
ファイル: uml_conf.c プロジェクト: Antique/libvirt
/*
 * Constructs a argv suitable for launching uml with config defined
 * for a given virtual machine.
 */
virCommandPtr umlBuildCommandLine(virConnectPtr conn,
                                  struct uml_driver *driver,
                                  virDomainObjPtr vm)
{
    size_t i, j;
    virCommandPtr cmd;

    cmd = virCommandNew(vm->def->os.kernel);

    virCommandAddEnvPassCommon(cmd);

    /* virCommandAddArgPair(cmd, "con0", "fd:0,fd:1"); */
    virCommandAddArgFormat(cmd, "mem=%lluK", vm->def->mem.cur_balloon);
    virCommandAddArgPair(cmd, "umid", vm->def->name);
    virCommandAddArgPair(cmd, "uml_dir", driver->monitorDir);

    if (vm->def->os.root)
        virCommandAddArgPair(cmd, "root", vm->def->os.root);

    for (i = 0; i < vm->def->ndisks; i++) {
        virDomainDiskDefPtr disk = vm->def->disks[i];

        if (!STRPREFIX(disk->dst, "ubd")) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("unsupported disk type '%s'"), disk->dst);
            goto error;
        }

        virCommandAddArgPair(cmd, disk->dst, virDomainDiskGetSource(disk));
    }

    for (i = 0; i < vm->def->nnets; i++) {
        char *ret = umlBuildCommandLineNet(conn, vm->def, vm->def->nets[i], i);
        if (!ret)
            goto error;
        virCommandAddArg(cmd, ret);
        VIR_FREE(ret);
    }

    for (i = 0; i < UML_MAX_CHAR_DEVICE; i++) {
        virDomainChrDefPtr chr = NULL;
        char *ret = NULL;
        for (j = 0; j < vm->def->nconsoles; j++)
            if (vm->def->consoles[j]->target.port == i)
                chr = vm->def->consoles[j];
        if (chr)
            ret = umlBuildCommandLineChr(chr, "con", cmd);
        if (!ret)
            if (virAsprintf(&ret, "con%zu=none", i) < 0)
                goto error;
        virCommandAddArg(cmd, ret);
        VIR_FREE(ret);
    }

    for (i = 0; i < UML_MAX_CHAR_DEVICE; i++) {
        virDomainChrDefPtr chr = NULL;
        char *ret = NULL;
        for (j = 0; j < vm->def->nserials; j++)
            if (vm->def->serials[j]->target.port == i)
                chr = vm->def->serials[j];
        if (chr)
            ret = umlBuildCommandLineChr(chr, "ssl", cmd);
        if (!ret)
            if (virAsprintf(&ret, "ssl%zu=none", i) < 0)
                goto error;

        virCommandAddArg(cmd, ret);
        VIR_FREE(ret);
    }

    if (vm->def->os.cmdline) {
        char *args, *next_arg;
        char *cmdline;
        if (VIR_STRDUP(cmdline, vm->def->os.cmdline) < 0)
            goto error;

        args = cmdline;
        while (*args == ' ')
            args++;

        while (*args) {
            next_arg = umlNextArg(args);
            virCommandAddArg(cmd, args);
            args = next_arg;
        }
        VIR_FREE(cmdline);
    }

    return cmd;

 error:
    virCommandFree(cmd);
    return NULL;
}
コード例 #2
0
ファイル: virhostcpu.c プロジェクト: ZhuoyuZhang/libvirt
virHostCPUParseNode(const char *node,
                    virArch arch,
                    virBitmapPtr present_cpus_map,
                    virBitmapPtr online_cpus_map,
                    int threads_per_subcore,
                    int *sockets,
                    int *cores,
                    int *threads,
                    int *offline)
{
    /* Biggest value we can expect to be used as either socket id
     * or core id. Bitmaps will need to be sized accordingly */
    const int ID_MAX = 4095;
    int ret = -1;
    int processors = 0;
    DIR *cpudir = NULL;
    struct dirent *cpudirent = NULL;
    virBitmapPtr node_cpus_map = NULL;
    virBitmapPtr sockets_map = NULL;
    virBitmapPtr *cores_maps = NULL;
    int npresent_cpus = virBitmapSize(present_cpus_map);
    int sock_max = 0;
    int sock;
    int core;
    size_t i;
    int siblings;
    unsigned int cpu;
    int direrr;

    *threads = 0;
    *cores = 0;
    *sockets = 0;

    if (!(cpudir = opendir(node))) {
        virReportSystemError(errno, _("cannot opendir %s"), node);
        goto cleanup;
    }

    /* Keep track of the CPUs that belong to the current node */
    if (!(node_cpus_map = virBitmapNew(npresent_cpus)))
        goto cleanup;

    /* enumerate sockets in the node */
    if (!(sockets_map = virBitmapNew(ID_MAX + 1)))
        goto cleanup;

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

        if (!virBitmapIsBitSet(present_cpus_map, cpu))
            continue;

        /* Mark this CPU as part of the current node */
        if (virBitmapSetBit(node_cpus_map, cpu) < 0)
            goto cleanup;

        if (!virBitmapIsBitSet(online_cpus_map, cpu))
            continue;

        /* Parse socket */
        if ((sock = virHostCPUParseSocket(node, arch, cpu)) < 0)
            goto cleanup;
        if (sock > ID_MAX) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Socket %d can't be handled (max socket is %d)"),
                           sock, ID_MAX);
            goto cleanup;
        }

        if (virBitmapSetBit(sockets_map, sock) < 0)
            goto cleanup;

        if (sock > sock_max)
            sock_max = sock;
    }

    if (direrr < 0)
        goto cleanup;

    sock_max++;

    /* allocate cores maps for each socket */
    if (VIR_ALLOC_N(cores_maps, sock_max) < 0)
        goto cleanup;

    for (i = 0; i < sock_max; i++)
        if (!(cores_maps[i] = virBitmapNew(ID_MAX + 1)))
            goto cleanup;

    /* Iterate over all CPUs in the node, in ascending order */
    for (cpu = 0; cpu < npresent_cpus; cpu++) {

        /* Skip CPUs that are not part of the current node */
        if (!virBitmapIsBitSet(node_cpus_map, cpu))
            continue;

        if (!virBitmapIsBitSet(online_cpus_map, cpu)) {
            if (threads_per_subcore > 0 &&
                cpu % threads_per_subcore != 0 &&
                virBitmapIsBitSet(online_cpus_map,
                                  cpu - (cpu % threads_per_subcore))) {
                /* Secondary offline threads are counted as online when
                 * subcores are in use and the corresponding primary
                 * thread is online */
                processors++;
            } else {
                /* But they are counted as offline otherwise */
                (*offline)++;
            }
            continue;
        }

        processors++;

        /* Parse socket */
        if ((sock = virHostCPUParseSocket(node, arch, cpu)) < 0)
            goto cleanup;
        if (!virBitmapIsBitSet(sockets_map, sock)) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("CPU socket topology has changed"));
            goto cleanup;
        }

        /* Parse core */
        if (ARCH_IS_S390(arch)) {
            /* logical cpu is equivalent to a core on s390 */
            core = cpu;
        } else {
            if ((core = virHostCPUGetValue(node, cpu,
                                           "topology/core_id", 0)) < 0)
                goto cleanup;
        }
        if (core > ID_MAX) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Core %d can't be handled (max core is %d)"),
                           core, ID_MAX);
            goto cleanup;
        }

        if (virBitmapSetBit(cores_maps[sock], core) < 0)
            goto cleanup;

        if (!(siblings = virHostCPUCountThreadSiblings(node, cpu)))
            goto cleanup;

        if (siblings > *threads)
            *threads = siblings;
    }

    /* finalize the returned data */
    *sockets = virBitmapCountBits(sockets_map);

    for (i = 0; i < sock_max; i++) {
        if (!virBitmapIsBitSet(sockets_map, i))
            continue;

        core = virBitmapCountBits(cores_maps[i]);
        if (core > *cores)
            *cores = core;
    }

    if (threads_per_subcore > 0) {
        /* The thread count ignores offline threads, which means that only
         * only primary threads have been considered so far. If subcores
         * are in use, we need to also account for secondary threads */
        *threads *= threads_per_subcore;
    }
    ret = processors;

 cleanup:
    /* don't shadow a more serious error */
    if (cpudir && closedir(cpudir) < 0 && ret >= 0) {
        virReportSystemError(errno, _("problem closing %s"), node);
        ret = -1;
    }
    if (cores_maps)
        for (i = 0; i < sock_max; i++)
            virBitmapFree(cores_maps[i]);
    VIR_FREE(cores_maps);
    virBitmapFree(sockets_map);
    virBitmapFree(node_cpus_map);

    return ret;
}
コード例 #3
0
ファイル: virhostcpu.c プロジェクト: ZhuoyuZhang/libvirt
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;
}
コード例 #4
0
static int
xenParseXMDisk(virConfPtr conf, virDomainDefPtr def)
{
    virDomainDiskDefPtr disk = NULL;
    int hvm = def->os.type == VIR_DOMAIN_OSTYPE_HVM;
    virConfValuePtr list = virConfGetValue(conf, "disk");

    if (list && list->type == VIR_CONF_LIST) {
        list = list->list;
        while (list) {
            char *head;
            char *offset;
            char *tmp;
            const char *src;

            if ((list->type != VIR_CONF_STRING) || (list->str == NULL))
                goto skipdisk;

            head = list->str;
            if (!(disk = virDomainDiskDefNew(NULL)))
                return -1;

            /*
             * Disks have 3 components, SOURCE,DEST-DEVICE,MODE
             * eg, phy:/dev/HostVG/XenGuest1,xvda,w
             * The SOURCE is usually prefixed with a driver type,
             * and optionally driver sub-type
             * The DEST-DEVICE is optionally post-fixed with disk type
             */

            /* Extract the source file path*/
            if (!(offset = strchr(head, ',')))
                goto skipdisk;

            if (offset == head) {
                /* No source file given, eg CDROM with no media */
                ignore_value(virDomainDiskSetSource(disk, NULL));
            } else {
                if (VIR_STRNDUP(tmp, head, offset - head) < 0)
                    goto cleanup;

                if (virDomainDiskSetSource(disk, tmp) < 0) {
                    VIR_FREE(tmp);
                    goto cleanup;
                }
                VIR_FREE(tmp);
            }

            head = offset + 1;
            /* Remove legacy ioemu: junk */
            if (STRPREFIX(head, "ioemu:"))
                head = head + 6;

            /* Extract the dest device name */
            if (!(offset = strchr(head, ',')))
                goto skipdisk;

            if (VIR_ALLOC_N(disk->dst, (offset - head) + 1) < 0)
                goto cleanup;

            if (virStrncpy(disk->dst, head, offset - head,
                           (offset - head) + 1) == NULL) {
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("Dest file %s too big for destination"), head);
                goto cleanup;
            }

            head = offset + 1;
            /* Extract source driver type */
            src = virDomainDiskGetSource(disk);
            if (src) {
                size_t len;
                /* The main type  phy:, file:, tap: ... */
                if ((tmp = strchr(src, ':')) != NULL) {
                    len = tmp - src;
                    if (VIR_STRNDUP(tmp, src, len) < 0)
                        goto cleanup;

                    if (virDomainDiskSetDriver(disk, tmp) < 0) {
                        VIR_FREE(tmp);
                        goto cleanup;
                    }
                    VIR_FREE(tmp);

                    /* Strip the prefix we found off the source file name */
                    if (virDomainDiskSetSource(disk, src + len + 1) < 0)
                        goto cleanup;

                    src = virDomainDiskGetSource(disk);
                }

                /* And the sub-type for tap:XXX: type */
                if (STREQ_NULLABLE(virDomainDiskGetDriver(disk), "tap")) {
                    char *driverType;

                    if (!(tmp = strchr(src, ':')))
                        goto skipdisk;
                    len = tmp - src;

                    if (VIR_STRNDUP(driverType, src, len) < 0)
                        goto cleanup;

                    if (STREQ(driverType, "aio"))
                        virDomainDiskSetFormat(disk, VIR_STORAGE_FILE_RAW);
                    else
                        virDomainDiskSetFormat(disk,
                                               virStorageFileFormatTypeFromString(driverType));
                    VIR_FREE(driverType);
                    if (virDomainDiskGetFormat(disk) <= 0) {
                        virReportError(VIR_ERR_INTERNAL_ERROR,
                                       _("Unknown driver type %s"),
                                       src);
                        goto cleanup;
                    }

                    /* Strip the prefix we found off the source file name */
                    if (virDomainDiskSetSource(disk, src + len + 1) < 0)
                        goto cleanup;
                    src = virDomainDiskGetSource(disk);
                }
            }

            /* No source, or driver name, so fix to phy: */
            if (!virDomainDiskGetDriver(disk) &&
                virDomainDiskSetDriver(disk, "phy") < 0)
                goto cleanup;

            /* phy: type indicates a block device */
            virDomainDiskSetType(disk,
                                 STREQ(virDomainDiskGetDriver(disk), "phy") ?
                                 VIR_STORAGE_TYPE_BLOCK :
                                 VIR_STORAGE_TYPE_FILE);

            /* Check for a :cdrom/:disk postfix */
            disk->device = VIR_DOMAIN_DISK_DEVICE_DISK;
            if ((tmp = strchr(disk->dst, ':')) != NULL) {
                if (STREQ(tmp, ":cdrom"))
                    disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
                tmp[0] = '\0';
            }

            if (STRPREFIX(disk->dst, "xvd") || !hvm) {
                disk->bus = VIR_DOMAIN_DISK_BUS_XEN;
            } else if (STRPREFIX(disk->dst, "sd")) {
                disk->bus = VIR_DOMAIN_DISK_BUS_SCSI;
            } else {
                disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
            }

            if (STREQ(head, "r") ||
                STREQ(head, "ro"))
                disk->src->readonly = true;
            else if ((STREQ(head, "w!")) ||
                     (STREQ(head, "!")))
                disk->src->shared = true;

            /* Maintain list in sorted order according to target device name */
            if (VIR_APPEND_ELEMENT(def->disks, def->ndisks, disk) < 0)
                goto cleanup;

            skipdisk:
            list = list->next;
            virDomainDiskDefFree(disk);
            disk = NULL;
        }
    }

    return 0;

 cleanup:
    virDomainDiskDefFree(disk);
    return -1;
}
コード例 #5
0
ファイル: lxc_controller.c プロジェクト: xushiwei/libvirt
static void virLXCControllerClientPrivateFree(void *data)
{
    VIR_FREE(data);
}
コード例 #6
0
ファイル: cputest.c プロジェクト: danwent/libvirt-ovs
static int
cpuTestGuestData(const void *arg)
{
    const struct data *data = arg;
    int ret = -1;
    virCPUDefPtr host = NULL;
    virCPUDefPtr cpu = NULL;
    virCPUDefPtr guest = NULL;
    union cpuData *guestData = NULL;
    virCPUCompareResult cmpResult;
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    char *result = NULL;

    if (!(host = cpuTestLoadXML(data->arch, data->host)) ||
        !(cpu = cpuTestLoadXML(data->arch, data->name)))
        goto cleanup;

    cmpResult = cpuGuestData(host, cpu, &guestData);
    if (cmpResult == VIR_CPU_COMPARE_ERROR ||
        cmpResult == VIR_CPU_COMPARE_INCOMPATIBLE)
        goto cleanup;

    if (VIR_ALLOC(guest) < 0 || !(guest->arch = strdup(host->arch)))
        goto cleanup;

    guest->type = VIR_CPU_TYPE_GUEST;
    guest->match = VIR_CPU_MATCH_EXACT;
    guest->fallback = cpu->fallback;
    if (cpuDecode(guest, guestData, data->models,
                  data->nmodels, data->preferred) < 0) {
        if (data->result < 0) {
            virResetLastError();
            ret = 0;
        }
        goto cleanup;
    }

    virBufferAsprintf(&buf, "%s+%s", data->host, data->name);
    if (data->nmodels)
        virBufferAsprintf(&buf, ",%s", data->modelsName);
    if (data->preferred)
        virBufferAsprintf(&buf, ",%s", data->preferred);
    virBufferAddLit(&buf, "-result");

    if (virBufferError(&buf)) {
        virBufferFreeAndReset(&buf);
        goto cleanup;
    }
    result = virBufferContentAndReset(&buf);

    ret = cpuTestCompareXML(data->arch, guest, result, 0);

cleanup:
    VIR_FREE(result);
    if (host)
        cpuDataFree(host->arch, guestData);
    virCPUDefFree(host);
    virCPUDefFree(cpu);
    virCPUDefFree(guest);
    return ret;
}
コード例 #7
0
ファイル: cputest.c プロジェクト: danwent/libvirt-ovs
static int
mymain(void)
{
    int ret = 0;
    char *map = NULL;

    abs_top_srcdir = getenv("abs_top_srcdir");
    if (!abs_top_srcdir)
        abs_top_srcdir = "..";

    if (virAsprintf(&map, "%s/src/cpu/cpu_map.xml", abs_top_srcdir) < 0 ||
        cpuMapOverride(map) < 0) {
        VIR_FREE(map);
        return EXIT_FAILURE;
    }

#define DO_TEST(arch, api, name, host, cpu,                             \
                models, nmodels, preferred, result)                     \
    do {                                                                \
        struct data data = {                                            \
            arch, api, host, cpu, models,                               \
            models == NULL ? NULL : #models,                            \
            nmodels, preferred, result    \
        };                                                              \
        if (cpuTestRun(name, &data) < 0)                                \
            ret = -1;                                                   \
    } while (0)

#define DO_TEST_COMPARE(arch, host, cpu, result)                        \
    DO_TEST(arch, API_COMPARE,                                          \
            host "/" cpu " (" #result ")",                              \
            host, cpu, NULL, 0, NULL, result)

#define DO_TEST_UPDATE(arch, host, cpu, result)                         \
    do {                                                                \
        DO_TEST(arch, API_UPDATE,                                       \
                cpu " on " host,                                        \
                host, cpu, NULL, 0, NULL, 0);                           \
        DO_TEST_COMPARE(arch, host, host "+" cpu, result);              \
    } while (0)

#define DO_TEST_BASELINE(arch, name, result)                            \
    DO_TEST(arch, API_BASELINE, name, NULL, "baseline-" name,           \
            NULL, 0, NULL, result)

#define DO_TEST_HASFEATURE(arch, host, feature, result)                 \
    DO_TEST(arch, API_HAS_FEATURE,                                      \
            host "/" feature " (" #result ")",                          \
            host, feature, NULL, 0, NULL, result)

#define DO_TEST_GUESTDATA(arch, host, cpu, models, preferred, result)   \
    DO_TEST(arch, API_GUEST_DATA,                                       \
            host "/" cpu " (" #models ", pref=" #preferred ")",         \
            host, cpu, models,                                          \
            models == NULL ? 0 : sizeof(models) / sizeof(char *),       \
            preferred, result)

    /* host to host comparison */
    DO_TEST_COMPARE("x86", "host", "host", IDENTICAL);
    DO_TEST_COMPARE("x86", "host", "host-better", INCOMPATIBLE);
    DO_TEST_COMPARE("x86", "host", "host-worse", SUPERSET);
    DO_TEST_COMPARE("x86", "host", "host-amd-fake", INCOMPATIBLE);
    DO_TEST_COMPARE("x86", "host", "host-incomp-arch", INCOMPATIBLE);
    DO_TEST_COMPARE("x86", "host", "host-no-vendor", IDENTICAL);
    DO_TEST_COMPARE("x86", "host-no-vendor", "host", INCOMPATIBLE);

    /* guest to host comparison */
    DO_TEST_COMPARE("x86", "host", "bogus-model", ERROR);
    DO_TEST_COMPARE("x86", "host", "bogus-feature", ERROR);
    DO_TEST_COMPARE("x86", "host", "min", SUPERSET);
    DO_TEST_COMPARE("x86", "host", "pentium3", SUPERSET);
    DO_TEST_COMPARE("x86", "host", "exact", SUPERSET);
    DO_TEST_COMPARE("x86", "host", "exact-forbid", INCOMPATIBLE);
    DO_TEST_COMPARE("x86", "host", "exact-forbid-extra", SUPERSET);
    DO_TEST_COMPARE("x86", "host", "exact-disable", SUPERSET);
    DO_TEST_COMPARE("x86", "host", "exact-disable2", SUPERSET);
    DO_TEST_COMPARE("x86", "host", "exact-disable-extra", SUPERSET);
    DO_TEST_COMPARE("x86", "host", "exact-require", SUPERSET);
    DO_TEST_COMPARE("x86", "host", "exact-require-extra", INCOMPATIBLE);
    DO_TEST_COMPARE("x86", "host", "exact-force", SUPERSET);
    DO_TEST_COMPARE("x86", "host", "strict", INCOMPATIBLE);
    DO_TEST_COMPARE("x86", "host", "strict-full", IDENTICAL);
    DO_TEST_COMPARE("x86", "host", "strict-disable", IDENTICAL);
    DO_TEST_COMPARE("x86", "host", "strict-force-extra", IDENTICAL);
    DO_TEST_COMPARE("x86", "host", "guest", SUPERSET);
    DO_TEST_COMPARE("x86", "host", "pentium3-amd", INCOMPATIBLE);
    DO_TEST_COMPARE("x86", "host-amd", "pentium3-amd", SUPERSET);
    DO_TEST_COMPARE("x86", "host-worse", "nehalem-force", IDENTICAL);

    /* guest updates for migration
     * automatically compares host CPU with the result */
    DO_TEST_UPDATE("x86", "host", "min", IDENTICAL);
    DO_TEST_UPDATE("x86", "host", "pentium3", IDENTICAL);
    DO_TEST_UPDATE("x86", "host", "guest", SUPERSET);
    DO_TEST_UPDATE("x86", "host", "host-model", IDENTICAL);
    DO_TEST_UPDATE("x86", "host", "host-model-nofallback", IDENTICAL);
    DO_TEST_UPDATE("x86", "host", "host-passthrough", IDENTICAL);

    /* computing baseline CPUs */
    DO_TEST_BASELINE("x86", "incompatible-vendors", -1);
    DO_TEST_BASELINE("x86", "no-vendor", 0);
    DO_TEST_BASELINE("x86", "some-vendors", 0);
    DO_TEST_BASELINE("x86", "1", 0);
    DO_TEST_BASELINE("x86", "2", 0);

    /* CPU features */
    DO_TEST_HASFEATURE("x86", "host", "vmx", YES);
    DO_TEST_HASFEATURE("x86", "host", "lm", YES);
    DO_TEST_HASFEATURE("x86", "host", "sse4.1", YES);
    DO_TEST_HASFEATURE("x86", "host", "3dnowext", NO);
    DO_TEST_HASFEATURE("x86", "host", "skinit", NO);
    DO_TEST_HASFEATURE("x86", "host", "foo", FAIL);

    /* computing guest data and decoding the data into a guest CPU XML */
    DO_TEST_GUESTDATA("x86", "host", "guest", NULL, NULL, 0);
    DO_TEST_GUESTDATA("x86", "host-better", "pentium3", NULL, NULL, 0);
    DO_TEST_GUESTDATA("x86", "host-better", "pentium3", NULL, "pentium3", 0);
    DO_TEST_GUESTDATA("x86", "host-better", "pentium3", NULL, "core2duo", 0);
    DO_TEST_GUESTDATA("x86", "host-worse", "guest", NULL, NULL, 0);
    DO_TEST_GUESTDATA("x86", "host", "strict-force-extra", NULL, NULL, 0);
    DO_TEST_GUESTDATA("x86", "host", "nehalem-force", NULL, NULL, 0);
    DO_TEST_GUESTDATA("x86", "host", "guest", model486, NULL, 0);
    DO_TEST_GUESTDATA("x86", "host", "guest", models, NULL, 0);
    DO_TEST_GUESTDATA("x86", "host", "guest", models, "Penryn", 0);
    DO_TEST_GUESTDATA("x86", "host", "guest", models, "qemu64", 0);
    DO_TEST_GUESTDATA("x86", "host", "guest", nomodel, NULL, -1);
    DO_TEST_GUESTDATA("x86", "host", "guest-nofallback", models, "Penryn", -1);
    DO_TEST_GUESTDATA("x86", "host", "host+host-model", models, "Penryn", 0);
    DO_TEST_GUESTDATA("x86", "host", "host+host-model-nofallback",
                      models, "Penryn", -1);

    VIR_FREE(map);
    return (ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
}
コード例 #8
0
ファイル: lxc_process.c プロジェクト: candhare/libvirt
static virCommandPtr
virLXCProcessBuildControllerCmd(virLXCDriverPtr driver,
                                virDomainObjPtr vm,
                                int nveths,
                                char **veths,
                                int *ttyFDs,
                                size_t nttyFDs,
                                int *files,
                                size_t nfiles,
                                int handshakefd,
                                int * const logfd,
                                const char *pidfile)
{
    size_t i;
    char *filterstr;
    char *outputstr;
    virCommandPtr cmd;
    virLXCDriverConfigPtr cfg = virLXCDriverGetConfig(driver);

    cmd = virCommandNew(vm->def->emulator);

    /* The controller may call ip command, so we have to retain PATH. */
    virCommandAddEnvPassBlockSUID(cmd, "PATH", "/bin:/usr/bin");

    virCommandAddEnvFormat(cmd, "LIBVIRT_DEBUG=%d",
                           virLogGetDefaultPriority());

    if (virLogGetNbFilters() > 0) {
        filterstr = virLogGetFilters();
        if (!filterstr) {
            virReportOOMError();
            goto cleanup;
        }

        virCommandAddEnvPair(cmd, "LIBVIRT_LOG_FILTERS", filterstr);
        VIR_FREE(filterstr);
    }

    if (cfg->log_libvirtd) {
        if (virLogGetNbOutputs() > 0) {
            outputstr = virLogGetOutputs();
            if (!outputstr) {
                virReportOOMError();
                goto cleanup;
            }

            virCommandAddEnvPair(cmd, "LIBVIRT_LOG_OUTPUTS", outputstr);
            VIR_FREE(outputstr);
        }
    } else {
        virCommandAddEnvFormat(cmd,
                               "LIBVIRT_LOG_OUTPUTS=%d:stderr",
                               virLogGetDefaultPriority());
    }

    virCommandAddArgList(cmd, "--name", vm->def->name, NULL);
    for (i = 0; i < nttyFDs; i++) {
        virCommandAddArg(cmd, "--console");
        virCommandAddArgFormat(cmd, "%d", ttyFDs[i]);
        virCommandPassFD(cmd, ttyFDs[i], 0);
    }

    for (i = 0; i < nfiles; i++) {
        virCommandAddArg(cmd, "--passfd");
        virCommandAddArgFormat(cmd, "%d", files[i]);
        virCommandPassFD(cmd, files[i], 0);
    }

    virCommandAddArgPair(cmd, "--security",
                         virSecurityManagerGetModel(driver->securityManager));

    virCommandAddArg(cmd, "--handshake");
    virCommandAddArgFormat(cmd, "%d", handshakefd);

    for (i = 0; i < nveths; i++)
        virCommandAddArgList(cmd, "--veth", veths[i], NULL);

    virCommandPassFD(cmd, handshakefd, 0);
    virCommandDaemonize(cmd);
    virCommandSetPidFile(cmd, pidfile);
    virCommandSetOutputFD(cmd, logfd);
    virCommandSetErrorFD(cmd, logfd);
    /* So we can pause before exec'ing the controller to
     * write the live domain status XML with the PID */
    virCommandRequireHandshake(cmd);

    return cmd;
 cleanup:
    virCommandFree(cmd);
    virObjectUnref(cfg);
    return NULL;
}
コード例 #9
0
ファイル: virsh-network.c プロジェクト: avdv/libvirt
static vshNetworkListPtr
vshNetworkListCollect(vshControl *ctl,
                      unsigned int flags)
{
    vshNetworkListPtr list = vshMalloc(ctl, sizeof(*list));
    int i;
    int ret;
    char **names = NULL;
    virNetworkPtr net;
    bool success = false;
    size_t deleted = 0;
    int persistent;
    int autostart;
    int nActiveNets = 0;
    int nInactiveNets = 0;
    int nAllNets = 0;

    /* try the list with flags support (0.10.2 and later) */
    if ((ret = virConnectListAllNetworks(ctl->conn,
                                         &list->nets,
                                         flags)) >= 0) {
        list->nnets = ret;
        goto finished;
    }

    /* check if the command is actually supported */
    if (last_error && last_error->code == VIR_ERR_NO_SUPPORT)
        goto fallback;

    if (last_error && last_error->code ==  VIR_ERR_INVALID_ARG) {
        /* try the new API again but mask non-guaranteed flags */
        unsigned int newflags = flags & (VIR_CONNECT_LIST_NETWORKS_ACTIVE |
                                         VIR_CONNECT_LIST_NETWORKS_INACTIVE);

        vshResetLibvirtError();
        if ((ret = virConnectListAllNetworks(ctl->conn, &list->nets,
                                             newflags)) >= 0) {
            list->nnets = ret;
            goto filter;
        }
    }

    /* there was an error during the first or second call */
    vshError(ctl, "%s", _("Failed to list networks"));
    goto cleanup;


fallback:
    /* fall back to old method (0.10.1 and older) */
    vshResetLibvirtError();

    /* Get the number of active networks */
    if (!VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_FILTERS_ACTIVE) ||
        VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_ACTIVE)) {
        if ((nActiveNets = virConnectNumOfNetworks(ctl->conn)) < 0) {
            vshError(ctl, "%s", _("Failed to get the number of active networks"));
            goto cleanup;
        }
    }

    /* Get the number of inactive networks */
    if (!VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_FILTERS_ACTIVE) ||
        VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_INACTIVE)) {
        if ((nInactiveNets = virConnectNumOfDefinedNetworks(ctl->conn)) < 0) {
            vshError(ctl, "%s", _("Failed to get the number of inactive networks"));
            goto cleanup;
        }
    }

    nAllNets = nActiveNets + nInactiveNets;

    if (nAllNets == 0)
         return list;

    names = vshMalloc(ctl, sizeof(char *) * nAllNets);

    /* Retrieve a list of active network names */
    if (!VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_FILTERS_ACTIVE) ||
        VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_ACTIVE)) {
        if (virConnectListNetworks(ctl->conn,
                                   names, nActiveNets) < 0) {
            vshError(ctl, "%s", _("Failed to list active networks"));
            goto cleanup;
        }
    }

    /* Add the inactive networks to the end of the name list */
    if (!VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_FILTERS_ACTIVE) ||
        VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_ACTIVE)) {
        if (virConnectListDefinedNetworks(ctl->conn,
                                          &names[nActiveNets],
                                          nInactiveNets) < 0) {
            vshError(ctl, "%s", _("Failed to list inactive networks"));
            goto cleanup;
        }
    }

    list->nets = vshMalloc(ctl, sizeof(virNetworkPtr) * (nAllNets));
    list->nnets = 0;

    /* get active networks */
    for (i = 0; i < nActiveNets; i++) {
        if (!(net = virNetworkLookupByName(ctl->conn, names[i])))
            continue;
        list->nets[list->nnets++] = net;
    }

    /* get inactive networks */
    for (i = 0; i < nInactiveNets; i++) {
        if (!(net = virNetworkLookupByName(ctl->conn, names[i])))
            continue;
        list->nets[list->nnets++] = net;
    }

    /* truncate networks that weren't found */
    deleted = nAllNets - list->nnets;

filter:
    /* filter list the list if the list was acquired by fallback means */
    for (i = 0; i < list->nnets; i++) {
        net = list->nets[i];

        /* persistence filter */
        if (VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_FILTERS_PERSISTENT)) {
            if ((persistent = virNetworkIsPersistent(net)) < 0) {
                vshError(ctl, "%s", _("Failed to get network persistence info"));
                goto cleanup;
            }

            if (!((VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_PERSISTENT) && persistent) ||
                  (VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_TRANSIENT) && !persistent)))
                goto remove_entry;
        }

        /* autostart filter */
        if (VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_FILTERS_AUTOSTART)) {
            if (virNetworkGetAutostart(net, &autostart) < 0) {
                vshError(ctl, "%s", _("Failed to get network autostart state"));
                goto cleanup;
            }

            if (!((VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_AUTOSTART) && autostart) ||
                  (VSH_MATCH(VIR_CONNECT_LIST_NETWORKS_NO_AUTOSTART) && !autostart)))
                goto remove_entry;
        }
        /* the pool matched all filters, it may stay */
        continue;

remove_entry:
        /* the pool has to be removed as it failed one of the filters */
        virNetworkFree(list->nets[i]);
        list->nets[i] = NULL;
        deleted++;
    }

finished:
    /* sort the list */
    if (list->nets && list->nnets)
        qsort(list->nets, list->nnets,
              sizeof(*list->nets), vshNetworkSorter);

    /* truncate the list if filter simulation deleted entries */
    if (deleted)
        VIR_SHRINK_N(list->nets, list->nnets, deleted);

    success = true;

cleanup:
    for (i = 0; i < nAllNets; i++)
        VIR_FREE(names[i]);
    VIR_FREE(names);

    if (!success) {
        vshNetworkListFree(list);
        list = NULL;
    }

    return list;
}
コード例 #10
0
ファイル: lxc_process.c プロジェクト: candhare/libvirt
/**
 * virLXCProcessCleanup:
 * @driver: pointer to driver structure
 * @vm: pointer to VM to clean up
 * @reason: reason for switching the VM to shutoff state
 *
 * Cleanout resources associated with the now dead VM
 *
 */
static void virLXCProcessCleanup(virLXCDriverPtr driver,
                                 virDomainObjPtr vm,
                                 virDomainShutoffReason reason)
{
    size_t i;
    virLXCDomainObjPrivatePtr priv = vm->privateData;
    virNetDevVPortProfilePtr vport = NULL;
    virLXCDriverConfigPtr cfg = virLXCDriverGetConfig(driver);

    VIR_DEBUG("Cleanup VM name=%s pid=%d reason=%d",
              vm->def->name, (int)vm->pid, (int)reason);

    /* now that we know it's stopped call the hook if present */
    if (virHookPresent(VIR_HOOK_DRIVER_LXC)) {
        char *xml = virDomainDefFormat(vm->def, 0);

        /* we can't stop the operation even if the script raised an error */
        virHookCall(VIR_HOOK_DRIVER_LXC, vm->def->name,
                    VIR_HOOK_LXC_OP_STOPPED, VIR_HOOK_SUBOP_END,
                    NULL, xml, NULL);
        VIR_FREE(xml);
    }

    /* Stop autodestroy in case guest is restarted */
    virCloseCallbacksUnset(driver->closeCallbacks, vm,
                           lxcProcessAutoDestroy);

    if (priv->monitor) {
        virLXCMonitorClose(priv->monitor);
        virObjectUnref(priv->monitor);
        priv->monitor = NULL;
    }

    virPidFileDelete(cfg->stateDir, vm->def->name);
    lxcProcessRemoveDomainStatus(cfg, vm);

    virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, reason);
    vm->pid = -1;
    vm->def->id = -1;

    if (virAtomicIntDecAndTest(&driver->nactive) && driver->inhibitCallback)
        driver->inhibitCallback(false, driver->inhibitOpaque);

    virLXCDomainReAttachHostDevices(driver, vm->def);

    for (i = 0; i < vm->def->nnets; i++) {
        virDomainNetDefPtr iface = vm->def->nets[i];
        vport = virDomainNetGetActualVirtPortProfile(iface);
        if (iface->ifname) {
            if (vport &&
                vport->virtPortType == VIR_NETDEV_VPORT_PROFILE_OPENVSWITCH)
                ignore_value(virNetDevOpenvswitchRemovePort(
                                virDomainNetGetActualBridgeName(iface),
                                iface->ifname));
            ignore_value(virNetDevVethDelete(iface->ifname));
        }
        networkReleaseActualDevice(vm->def, iface);
    }

    virDomainConfVMNWFilterTeardown(vm);

    if (priv->cgroup) {
        virCgroupRemove(priv->cgroup);
        virCgroupFree(&priv->cgroup);
    }

    /* Get machined to terminate the machine as it may not have cleaned it
     * properly. See https://bugs.freedesktop.org/show_bug.cgi?id=68370 for
     * the bug we are working around here.
     */
    virSystemdTerminateMachine(vm->def->name, "lxc", true);


    /* The "release" hook cleans up additional resources */
    if (virHookPresent(VIR_HOOK_DRIVER_LXC)) {
        char *xml = virDomainDefFormat(vm->def, 0);

        /* we can't stop the operation even if the script raised an error */
        virHookCall(VIR_HOOK_DRIVER_LXC, vm->def->name,
                    VIR_HOOK_LXC_OP_RELEASE, VIR_HOOK_SUBOP_END,
                    NULL, xml, NULL);
        VIR_FREE(xml);
    }

    if (vm->newDef) {
        virDomainDefFree(vm->def);
        vm->def = vm->newDef;
        vm->def->id = -1;
        vm->newDef = NULL;
    }
    virObjectUnref(cfg);
}
コード例 #11
0
ファイル: lxc_process.c プロジェクト: candhare/libvirt
int virLXCProcessStop(virLXCDriverPtr driver,
                      virDomainObjPtr vm,
                      virDomainShutoffReason reason)
{
    int rc;
    virLXCDomainObjPrivatePtr priv;

    VIR_DEBUG("Stopping VM name=%s pid=%d reason=%d",
              vm->def->name, (int)vm->pid, (int)reason);
    if (!virDomainObjIsActive(vm)) {
        VIR_DEBUG("VM '%s' not active", vm->def->name);
        return 0;
    }

    priv = vm->privateData;

    if (vm->pid <= 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Invalid PID %d for container"), vm->pid);
        return -1;
    }

    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);
    }

    /* If the LXC domain is suspended we send all processes a SIGKILL
     * and thaw them. Upon wakeup the process sees the pending signal
     * and dies immediately. It is guaranteed that priv->cgroup != NULL
     * here because the domain has aleady been suspended using the
     * freezer cgroup.
     */
    if (reason == VIR_DOMAIN_SHUTOFF_DESTROYED &&
        virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
        if (virCgroupKillRecursive(priv->cgroup, SIGKILL) <= 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("Unable to kill all processes"));
            return -1;
        }

        if (virCgroupSetFreezerState(priv->cgroup, "THAWED") < 0) {
            virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                           _("Unable to thaw all processes"));

            return -1;
        }

        goto cleanup;
    }

    if (priv->cgroup) {
        rc = virCgroupKillPainfully(priv->cgroup);
        if (rc < 0)
            return -1;
        if (rc > 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("Some processes refused to die"));
            return -1;
        }
    } else {
        /* If cgroup doesn't exist, just try cleaning up the
         * libvirt_lxc process */
        if (virProcessKillPainfully(vm->pid, true) < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Processes %d refused to die"), (int)vm->pid);
            return -1;
        }
    }

 cleanup:
    virLXCProcessCleanup(driver, vm, reason);

    return 0;
}
コード例 #12
0
ファイル: lxc_process.c プロジェクト: candhare/libvirt
static int
virLXCProcessReconnectDomain(virDomainObjPtr vm,
                             void *opaque)
{
    virLXCDriverPtr driver = opaque;
    virLXCDomainObjPrivatePtr priv;
    int ret = -1;

    virObjectLock(vm);
    VIR_DEBUG("Reconnect id=%d pid=%d state=%d", vm->def->id, vm->pid, vm->state.state);

    priv = vm->privateData;

    if (vm->pid != 0) {
        vm->def->id = vm->pid;
        virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
                             VIR_DOMAIN_RUNNING_UNKNOWN);

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

        if (!(priv->monitor = virLXCProcessConnectMonitor(driver, vm)))
            goto error;

        if (virCgroupNewDetectMachine(vm->def->name, "lxc", vm->pid,
                                      -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;
        }

        if (virLXCUpdateActiveUSBHostdevs(driver, vm->def) < 0)
            goto error;

        if (virSecurityManagerReserveLabel(driver->securityManager,
                                           vm->def, vm->pid) < 0)
            goto error;

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

            /* we can't stop the operation even if the script raised an error */
            hookret = virHookCall(VIR_HOOK_DRIVER_LXC, vm->def->name,
                                  VIR_HOOK_LXC_OP_RECONNECT, VIR_HOOK_SUBOP_BEGIN,
                                  NULL, xml, NULL);
            VIR_FREE(xml);
            if (hookret < 0)
                goto error;
        }

    } else {
        vm->def->id = -1;
    }

    ret = 0;
 cleanup:
    virObjectUnlock(vm);
    return ret;

 error:
    virLXCProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED);
    virDomainAuditStop(vm, "failed");
    goto cleanup;
}
コード例 #13
0
ファイル: lxc_process.c プロジェクト: candhare/libvirt
/**
 * 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;
    char *pidfile = NULL;
    bool clearSeclabel = false;
    bool need_stop = false;

    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 (vm->def->nconsoles == 0) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("At least one PTY console is required"));
        return -1;
    }

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

    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)
        goto cleanup;

    if (!(pidfile = virPidFileBuildPath(cfg->stateDir, vm->def->name)))
        goto cleanup;

    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)");

    clearSeclabel = vm->def->nseclabels == 0 ||
                    vm->def->seclabels[0]->type == VIR_DOMAIN_SECLABEL_DEFAULT;

    if (vm->def->nseclabels &&
        vm->def->seclabels[0]->type == VIR_DOMAIN_SECLABEL_DEFAULT)
        vm->def->seclabels[0]->type = VIR_DOMAIN_SECLABEL_NONE;

    if (virSecurityManagerCheckAllLabel(driver->securityManager, vm->def) < 0)
        goto cleanup;

    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;

    VIR_DEBUG("Setting up consoles");
    for (i = 0; i < vm->def->nconsoles; i++) {
        char *ttyPath;

        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;
    }

    VIR_DEBUG("Setting up Interfaces");
    if (virLXCProcessSetupInterfaces(conn, vm->def, &nveths, &veths) < 0)
        goto cleanup;

    VIR_DEBUG("Preparing to launch");
    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],
                                                &logfd,
                                                pidfile)))
        goto cleanup;

    /* 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)));

    VIR_DEBUG("Launching container");
    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;
    }

    /* It has started running, so get its pid */
    if ((r = virPidFileReadPath(pidfile, &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"),
                                 pidfile);
        goto cleanup;
    }

    need_stop = true;
    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 (VIR_CLOSE(handshakefds[1]) < 0) {
        virReportSystemError(errno, "%s", _("could not close handshake fd"));
        goto cleanup;
    }

    if (virCommandHandshakeWait(cmd) < 0)
        goto cleanup;

    /* Write domain status to disk for the controller to
     * read when it starts */
    if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
        goto cleanup;

    /* Allow the child to exec the controller */
    if (virCommandHandshakeNotify(cmd) < 0)
        goto cleanup;

    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 cleanup;
    }

    /* We know the cgroup must exist by this synchronization
     * point so lets detect that first, since it gives us a
     * more reliable way to kill everything off if something
     * goes wrong from here onwards ... */
    if (virCgroupNewDetectMachine(vm->def->name, "lxc", vm->pid,
                                  -1, &priv->cgroup) < 0)
        goto cleanup;

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

    /* And we can get the first monitor connection now too */
    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;
    }

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

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

    /* We don't need the temporary NIC names anymore, clear them */
    virLXCProcessCleanInterfaces(vm->def);

    /* 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 cleanup;
    }

    rc = 0;

 cleanup:
    if (VIR_CLOSE(logfd) < 0) {
        virReportSystemError(errno, "%s", _("could not close logfile"));
        rc = -1;
    }
    if (rc != 0) {
        err = virSaveLastError();
        if (need_stop) {
            virLXCProcessStop(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED);
        } else {
            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 ||
                clearSeclabel)) {
                VIR_FREE(vm->def->seclabels[0]->model);
                VIR_FREE(vm->def->seclabels[0]->label);
                VIR_FREE(vm->def->seclabels[0]->imagelabel);
                VIR_DELETE_ELEMENT(vm->def->seclabels, 0, vm->def->nseclabels);
            }
            virLXCProcessCleanup(driver, vm, VIR_DOMAIN_SHUTOFF_FAILED);
        }
    }
    virCommandFree(cmd);
    for (i = 0; i < nveths; i++)
        VIR_FREE(veths[i]);
    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(pidfile);
    VIR_FREE(logfile);
    virObjectUnref(cfg);
    virObjectUnref(caps);

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

    return rc;
}
コード例 #14
0
ファイル: netdev_bandwidth_conf.c プロジェクト: 6WIND/libvirt
static int
virNetDevBandwidthParseRate(xmlNodePtr node, virNetDevBandwidthRatePtr rate)
{
    int ret = -1;
    char *average = NULL;
    char *peak = NULL;
    char *burst = NULL;
    char *floor = NULL;

    if (!node || !rate) {
        virReportError(VIR_ERR_INVALID_ARG, "%s",
                       _("invalid argument supplied"));
        return -1;
    }

    average = virXMLPropString(node, "average");
    peak = virXMLPropString(node, "peak");
    burst = virXMLPropString(node, "burst");
    floor = virXMLPropString(node, "floor");

    if (average) {
        if (virStrToLong_ull(average, NULL, 10, &rate->average) < 0) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("could not convert bandwidth average value '%s'"),
                           average);
            goto cleanup;
        }
    } else if (!floor) {
        virReportError(VIR_ERR_XML_DETAIL, "%s",
                       _("Missing mandatory average or floor attributes"));
        goto cleanup;
    }

    if ((peak || burst) && !average) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("'peak' and 'burst' require 'average' attribute"));
        goto cleanup;
    }

    if (peak && virStrToLong_ull(peak, NULL, 10, &rate->peak) < 0) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("could not convert bandwidth peak value '%s'"),
                       peak);
        goto cleanup;
    }

    if (burst && virStrToLong_ull(burst, NULL, 10, &rate->burst) < 0) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("could not convert bandwidth burst value '%s'"),
                       burst);
        goto cleanup;
    }

    if (floor && virStrToLong_ull(floor, NULL, 10, &rate->floor) < 0) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("could not convert bandwidth floor value '%s'"),
                       floor);
        goto cleanup;
    }

    ret = 0;

 cleanup:
    VIR_FREE(average);
    VIR_FREE(peak);
    VIR_FREE(burst);
    VIR_FREE(floor);

    return ret;
}
コード例 #15
0
ファイル: openvz_conf.c プロジェクト: i-ninth/libvirt
int openvzLoadDomains(struct openvz_driver *driver)
{
    int veid, ret;
    char *status;
    char uuidstr[VIR_UUID_STRING_BUFLEN];
    virDomainObjPtr dom = NULL;
    virDomainDefPtr def = NULL;
    char *temp = NULL;
    char *outbuf = NULL;
    char *line;
    virCommandPtr cmd = NULL;

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

    cmd = virCommandNewArgList(VZLIST, "-a", "-ovpsid,status", "-H", NULL);
    virCommandSetOutputBuffer(cmd, &outbuf);
    if (virCommandRun(cmd, NULL) < 0)
        goto cleanup;

    line = outbuf;
    while (line[0] != '\0') {
        unsigned int flags = 0;
        if (virStrToLong_i(line, &status, 10, &veid) < 0 ||
            *status++ != ' ' ||
            (line = strchr(status, '\n')) == NULL) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("Failed to parse vzlist output"));
            goto cleanup;
        }
        *line++ = '\0';

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

        def->virtType = VIR_DOMAIN_VIRT_OPENVZ;

        if (STREQ(status, "stopped"))
            def->id = -1;
        else
            def->id = veid;
        if (virAsprintf(&def->name, "%i", veid) < 0)
            goto cleanup;

        openvzGetVPSUUID(veid, uuidstr, sizeof(uuidstr));
        ret = virUUIDParse(uuidstr, def->uuid);

        if (ret == -1) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("UUID in config file malformed"));
            goto cleanup;
        }

        if (VIR_STRDUP(def->os.type, "exe") < 0)
            goto cleanup;
        if (VIR_STRDUP(def->os.init, "/sbin/init") < 0)
            goto cleanup;

        ret = openvzReadVPSConfigParam(veid, "CPUS", &temp);
        if (ret < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Could not read config for container %d"),
                           veid);
            goto cleanup;
        } else if (ret > 0) {
            def->maxvcpus = strtoI(temp);
        }

        if (ret == 0 || def->maxvcpus == 0)
            def->maxvcpus = openvzGetNodeCPUs();
        def->vcpus = def->maxvcpus;

        /* XXX load rest of VM config data .... */

        openvzReadNetworkConf(def, veid);
        openvzReadFSConf(def, veid);
        openvzReadMemConf(def, veid);

        virUUIDFormat(def->uuid, uuidstr);
        flags = VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE;
        if (STRNEQ(status, "stopped"))
            flags |= VIR_DOMAIN_OBJ_LIST_ADD_LIVE;

        if (!(dom = virDomainObjListAdd(driver->domains,
                                        def,
                                        driver->xmlopt,
                                        flags,
                                        NULL)))
            goto cleanup;

        if (STREQ(status, "stopped")) {
            virDomainObjSetState(dom, VIR_DOMAIN_SHUTOFF,
                                 VIR_DOMAIN_SHUTOFF_UNKNOWN);
            dom->pid = -1;
        } else {
            virDomainObjSetState(dom, VIR_DOMAIN_RUNNING,
                                 VIR_DOMAIN_RUNNING_UNKNOWN);
            dom->pid = veid;
        }
        /* XXX OpenVZ doesn't appear to have concept of a transient domain */
        dom->persistent = 1;

        virObjectUnlock(dom);
        dom = NULL;
        def = NULL;
    }

    virCommandFree(cmd);
    VIR_FREE(temp);
    VIR_FREE(outbuf);

    return 0;

 cleanup:
    virCommandFree(cmd);
    VIR_FREE(temp);
    VIR_FREE(outbuf);
    virObjectUnref(dom);
    virDomainDefFree(def);
    return -1;
}
コード例 #16
0
ファイル: virdbus.c プロジェクト: cbosdo/libvirt
static void virDBusWatchFree(void *data) {
    struct virDBusWatch *info = data;
    VIR_FREE(info);
}
コード例 #17
0
ファイル: qemu_conf.c プロジェクト: pdf/libvirt
int qemudLoadDriverConfig(struct qemud_driver *driver,
                          const char *filename) {
    virConfPtr conf;
    virConfValuePtr p;
    char *user;
    char *group;
    int i;

    /* Setup critical defaults */
    driver->securityDefaultConfined = true;
    driver->securityRequireConfined = false;
    driver->dynamicOwnership = 1;
    driver->clearEmulatorCapabilities = 1;

    if (!(driver->vncListen = strdup("127.0.0.1"))) {
        virReportOOMError();
        return -1;
    }
    if (!(driver->vncTLSx509certdir = strdup(SYSCONFDIR "/pki/libvirt-vnc"))) {
        virReportOOMError();
        return -1;
    }

    if (!(driver->spiceListen = strdup("127.0.0.1"))) {
        virReportOOMError();
        return -1;
    }
    if (!(driver->spiceTLSx509certdir
          = strdup(SYSCONFDIR "/pki/libvirt-spice"))) {
        virReportOOMError();
        return -1;
    }

#if defined HAVE_MNTENT_H && defined HAVE_GETMNTENT_R
    /* For privileged driver, try and find hugepage mount automatically.
     * Non-privileged driver requires admin to create a dir for the
     * user, chown it, and then let user configure it manually */
    if (driver->privileged &&
        !(driver->hugetlbfs_mount = virFileFindMountPoint("hugetlbfs"))) {
        if (errno != ENOENT) {
            virReportSystemError(errno, "%s",
                                 _("unable to find hugetlbfs mountpoint"));
            return -1;
        }
    }
#endif

    if (!(driver->lockManager =
          virLockManagerPluginNew("nop", NULL, 0)))
        return -1;

    driver->keepAliveInterval = 5;
    driver->keepAliveCount = 5;

    /* 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;
    }

    conf = virConfReadFile (filename, 0);
    if (!conf) {
        return -1;
    }


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

    p = virConfGetValue (conf, "vnc_auto_unix_socket");
    CHECK_TYPE ("vnc_auto_unix_socket", VIR_CONF_LONG);
    if (p) driver->vncAutoUnixSocket = p->l;

    p = virConfGetValue (conf, "vnc_tls");
    CHECK_TYPE ("vnc_tls", VIR_CONF_LONG);
    if (p) driver->vncTLS = p->l;

    p = virConfGetValue (conf, "vnc_tls_x509_verify");
    CHECK_TYPE ("vnc_tls_x509_verify", VIR_CONF_LONG);
    if (p) driver->vncTLSx509verify = p->l;

    p = virConfGetValue (conf, "vnc_tls_x509_cert_dir");
    CHECK_TYPE ("vnc_tls_x509_cert_dir", VIR_CONF_STRING);
    if (p && p->str) {
        VIR_FREE(driver->vncTLSx509certdir);
        if (!(driver->vncTLSx509certdir = strdup(p->str))) {
            virReportOOMError();
            virConfFree(conf);
            return -1;
        }
    }

    p = virConfGetValue (conf, "vnc_listen");
    CHECK_TYPE ("vnc_listen", VIR_CONF_STRING);
    if (p && p->str) {
        VIR_FREE(driver->vncListen);
        if (!(driver->vncListen = strdup(p->str))) {
            virReportOOMError();
            virConfFree(conf);
            return -1;
        }
    }

    p = virConfGetValue (conf, "vnc_password");
    CHECK_TYPE ("vnc_password", VIR_CONF_STRING);
    if (p && p->str) {
        VIR_FREE(driver->vncPassword);
        if (!(driver->vncPassword = strdup(p->str))) {
            virReportOOMError();
            virConfFree(conf);
            return -1;
        }
    }

    p = virConfGetValue (conf, "security_driver");
    CHECK_TYPE ("security_driver", VIR_CONF_STRING);
    if (p && p->str) {
        if (!(driver->securityDriverName = strdup(p->str))) {
            virReportOOMError();
            virConfFree(conf);
            return -1;
        }
    }

    p = virConfGetValue (conf, "security_default_confined");
    CHECK_TYPE ("security_default_confined", VIR_CONF_LONG);
    if (p) driver->securityDefaultConfined = p->l;

    p = virConfGetValue (conf, "security_require_confined");
    CHECK_TYPE ("security_require_confined", VIR_CONF_LONG);
    if (p) driver->securityRequireConfined = p->l;


    p = virConfGetValue (conf, "vnc_sasl");
    CHECK_TYPE ("vnc_sasl", VIR_CONF_LONG);
    if (p) driver->vncSASL = p->l;

    p = virConfGetValue (conf, "vnc_sasl_dir");
    CHECK_TYPE ("vnc_sasl_dir", VIR_CONF_STRING);
    if (p && p->str) {
        VIR_FREE(driver->vncSASLdir);
        if (!(driver->vncSASLdir = strdup(p->str))) {
            virReportOOMError();
            virConfFree(conf);
            return -1;
        }
    }

    p = virConfGetValue (conf, "spice_tls");
    CHECK_TYPE ("spice_tls", VIR_CONF_LONG);
    if (p) driver->spiceTLS = p->l;

    p = virConfGetValue (conf, "spice_tls_x509_cert_dir");
    CHECK_TYPE ("spice_tls_x509_cert_dir", VIR_CONF_STRING);
    if (p && p->str) {
        VIR_FREE(driver->spiceTLSx509certdir);
        if (!(driver->spiceTLSx509certdir = strdup(p->str))) {
            virReportOOMError();
            virConfFree(conf);
            return -1;
        }
    }

    p = virConfGetValue (conf, "spice_listen");
    CHECK_TYPE ("spice_listen", VIR_CONF_STRING);
    if (p && p->str) {
        VIR_FREE(driver->spiceListen);
        if (!(driver->spiceListen = strdup(p->str))) {
            virReportOOMError();
            virConfFree(conf);
            return -1;
        }
    }

    p = virConfGetValue (conf, "spice_password");
    CHECK_TYPE ("spice_password", VIR_CONF_STRING);
    if (p && p->str) {
        VIR_FREE(driver->spicePassword);
        if (!(driver->spicePassword = strdup(p->str))) {
            virReportOOMError();
            virConfFree(conf);
            return -1;
        }
    }

    p = virConfGetValue (conf, "user");
    CHECK_TYPE ("user", VIR_CONF_STRING);
    if (!(user = strdup(p && p->str ? p->str : QEMU_USER))) {
        virReportOOMError();
        virConfFree(conf);
        return -1;
    }
    if (virGetUserID(user, &driver->user) < 0) {
        VIR_FREE(user);
        virConfFree(conf);
        return -1;
    }
    VIR_FREE(user);


    p = virConfGetValue (conf, "group");
    CHECK_TYPE ("group", VIR_CONF_STRING);
    if (!(group = strdup(p && p->str ? p->str : QEMU_GROUP))) {
        virReportOOMError();
        virConfFree(conf);
        return -1;
    }
    if (virGetGroupID(group, &driver->group) < 0) {
        VIR_FREE(group);
        virConfFree(conf);
        return -1;
    }
    VIR_FREE(group);


    p = virConfGetValue (conf, "dynamic_ownership");
    CHECK_TYPE ("dynamic_ownership", VIR_CONF_LONG);
    if (p) driver->dynamicOwnership = p->l;


    p = virConfGetValue (conf, "cgroup_controllers");
    CHECK_TYPE ("cgroup_controllers", VIR_CONF_LIST);
    if (p) {
        virConfValuePtr pp;
        for (i = 0, pp = p->list; pp; ++i, pp = pp->next) {
            int ctl;
            if (pp->type != VIR_CONF_STRING) {
                VIR_ERROR(_("cgroup_controllers must be a list of strings"));
                virConfFree(conf);
                return -1;
            }
            ctl = virCgroupControllerTypeFromString(pp->str);
            if (ctl < 0) {
                VIR_ERROR(_("Unknown cgroup controller '%s'"), pp->str);
                virConfFree(conf);
                return -1;
            }
            driver->cgroupControllers |= (1 << ctl);
        }
    } else {
        driver->cgroupControllers =
            (1 << VIR_CGROUP_CONTROLLER_CPU) |
            (1 << VIR_CGROUP_CONTROLLER_DEVICES) |
            (1 << VIR_CGROUP_CONTROLLER_MEMORY) |
            (1 << VIR_CGROUP_CONTROLLER_BLKIO) |
            (1 << VIR_CGROUP_CONTROLLER_CPUSET) |
            (1 << VIR_CGROUP_CONTROLLER_CPUACCT);
    }
    for (i = 0 ; i < VIR_CGROUP_CONTROLLER_LAST ; i++) {
        if (driver->cgroupControllers & (1 << i)) {
            VIR_INFO("Configured cgroup controller '%s'",
                     virCgroupControllerTypeToString(i));
        }
    }

    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(driver->cgroupDeviceACL, 1+len) < 0) {
            virReportOOMError();
            virConfFree(conf);
            return -1;
        }
        for (i = 0, pp = p->list; pp; ++i, pp = pp->next) {
            if (pp->type != VIR_CONF_STRING) {
                VIR_ERROR(_("cgroup_device_acl must be a list of strings"));
                virConfFree(conf);
                return -1;
            }
            driver->cgroupDeviceACL[i] = strdup (pp->str);
            if (driver->cgroupDeviceACL[i] == NULL) {
                virReportOOMError();
                virConfFree(conf);
                return -1;
            }

        }
        driver->cgroupDeviceACL[i] = NULL;
    }

    p = virConfGetValue (conf, "save_image_format");
    CHECK_TYPE ("save_image_format", VIR_CONF_STRING);
    if (p && p->str) {
        VIR_FREE(driver->saveImageFormat);
        if (!(driver->saveImageFormat = strdup(p->str))) {
            virReportOOMError();
            virConfFree(conf);
            return -1;
        }
    }

    p = virConfGetValue (conf, "dump_image_format");
    CHECK_TYPE ("dump_image_format", VIR_CONF_STRING);
    if (p && p->str) {
        VIR_FREE(driver->dumpImageFormat);
        if (!(driver->dumpImageFormat = strdup(p->str))) {
            virReportOOMError();
            virConfFree(conf);
            return -1;
        }
    }

    p = virConfGetValue (conf, "auto_dump_path");
    CHECK_TYPE ("auto_dump_path", VIR_CONF_STRING);
    if (p && p->str) {
        VIR_FREE(driver->autoDumpPath);
        if (!(driver->autoDumpPath = strdup(p->str))) {
            virReportOOMError();
            virConfFree(conf);
            return -1;
        }
    }

    p = virConfGetValue (conf, "auto_dump_bypass_cache");
    CHECK_TYPE ("auto_dump_bypass_cache", VIR_CONF_LONG);
    if (p) driver->autoDumpBypassCache = true;

    p = virConfGetValue (conf, "auto_start_bypass_cache");
    CHECK_TYPE ("auto_start_bypass_cache", VIR_CONF_LONG);
    if (p) driver->autoStartBypassCache = true;

    p = virConfGetValue (conf, "hugetlbfs_mount");
    CHECK_TYPE ("hugetlbfs_mount", VIR_CONF_STRING);
    if (p && p->str) {
        VIR_FREE(driver->hugetlbfs_mount);
        if (!(driver->hugetlbfs_mount = strdup(p->str))) {
            virReportOOMError();
            virConfFree(conf);
            return -1;
        }
    }

    p = virConfGetValue (conf, "mac_filter");
    CHECK_TYPE ("mac_filter", VIR_CONF_LONG);
    if (p && p->l) {
        driver->macFilter = p->l;
        if (!(driver->ebtables = ebtablesContextNew("qemu"))) {
            driver->macFilter = 0;
            virReportSystemError(errno,
                                 _("failed to enable mac filter in '%s'"),
                                 __FILE__);
            virConfFree(conf);
            return -1;
        }

        if ((errno = networkDisableAllFrames(driver))) {
            virReportSystemError(errno,
                         _("failed to add rule to drop all frames in '%s'"),
                                 __FILE__);
            virConfFree(conf);
            return -1;
        }
    }

    p = virConfGetValue (conf, "relaxed_acs_check");
    CHECK_TYPE ("relaxed_acs_check", VIR_CONF_LONG);
    if (p) driver->relaxedACS = p->l;

    p = virConfGetValue (conf, "vnc_allow_host_audio");
    CHECK_TYPE ("vnc_allow_host_audio", VIR_CONF_LONG);
    if (p) driver->vncAllowHostAudio = p->l;

    p = virConfGetValue (conf, "clear_emulator_capabilities");
    CHECK_TYPE ("clear_emulator_capabilities", VIR_CONF_LONG);
    if (p) driver->clearEmulatorCapabilities = p->l;

    p = virConfGetValue (conf, "allow_disk_format_probing");
    CHECK_TYPE ("allow_disk_format_probing", VIR_CONF_LONG);
    if (p) driver->allowDiskFormatProbing = p->l;

    p = virConfGetValue (conf, "set_process_name");
    CHECK_TYPE ("set_process_name", VIR_CONF_LONG);
    if (p) driver->setProcessName = p->l;

    p = virConfGetValue(conf, "max_processes");
    CHECK_TYPE("max_processes", VIR_CONF_LONG);
    if (p) driver->maxProcesses = p->l;

    p = virConfGetValue(conf, "max_files");
    CHECK_TYPE("max_files", VIR_CONF_LONG);
    if (p) driver->maxFiles = p->l;

    p = virConfGetValue (conf, "lock_manager");
    CHECK_TYPE ("lock_manager", VIR_CONF_STRING);
    if (p && p->str) {
        char *lockConf;
        virLockManagerPluginUnref(driver->lockManager);
        if (virAsprintf(&lockConf, "%s/libvirt/qemu-%s.conf", SYSCONFDIR, p->str) < 0) {
            virReportOOMError();
            virConfFree(conf);
            return -1;
        }
        if (!(driver->lockManager =
              virLockManagerPluginNew(p->str, lockConf, 0)))
            VIR_ERROR(_("Failed to load lock manager %s"), p->str);
        VIR_FREE(lockConf);
    }

    p = virConfGetValue(conf, "max_queued");
    CHECK_TYPE("max_queued", VIR_CONF_LONG);
    if (p) driver->max_queued = p->l;

    p = virConfGetValue(conf, "keepalive_interval");
    CHECK_TYPE("keepalive_interval", VIR_CONF_LONG);
    if (p) driver->keepAliveInterval = p->l;

    p = virConfGetValue(conf, "keepalive_count");
    CHECK_TYPE("keepalive_count", VIR_CONF_LONG);
    if (p) driver->keepAliveCount = p->l;

    virConfFree (conf);
    return 0;
}
コード例 #18
0
ファイル: libvirtdconftest.c プロジェクト: 6WIND/libvirt
static int
testCorrupt(const void *opaque)
{
    const struct testCorruptData *data = opaque;
    struct daemonConfig *conf = daemonConfigNew(false);
    int ret = 0;
    int type = VIR_CONF_NONE;
    char *newdata = munge_param(data->filedata,
                                data->params,
                                data->paramnum,
                                &type);
    virErrorPtr err = NULL;

    if (!newdata)
        return -1;

    //VIR_DEBUG("New config [%s]", newdata);

    if (daemonConfigLoadData(conf, data->filename, newdata) != -1) {
        VIR_DEBUG("Did not see a failure");
        ret = -1;
        goto cleanup;
    }

    err = virGetLastError();
    if (!err || !err->message) {
        VIR_DEBUG("No error or message %p", err);
        ret = -1;
        goto cleanup;
    }

#if !WITH_SASL
    if (strstr(err->message, "unsupported auth sasl")) {
        VIR_DEBUG("sasl unsupported, skipping this config");
        goto cleanup;
    }
#endif

    switch (type) {
    case VIR_CONF_LONG:
        if (!strstr(err->message, "invalid type: got string; expected long")) {
            VIR_DEBUG("Wrong error for long: '%s'",
                      err->message);
            ret = -1;
        }
        break;
    case VIR_CONF_STRING:
        if (!strstr(err->message, "invalid type: got long; expected string")) {
            VIR_DEBUG("Wrong error for string: '%s'",
                      err->message);
            ret = -1;
        }
        break;
    case VIR_CONF_LIST:
        if (!strstr(err->message, "must be a string or list of strings")) {
            VIR_DEBUG("Wrong error for list: '%s'",
                      err->message);
            ret = -1;
        }
        break;
    }

cleanup:
    VIR_FREE(newdata);
    daemonConfigFree(conf);
    return ret;
}
コード例 #19
0
ファイル: cputest.c プロジェクト: danwent/libvirt-ovs
static int
cpuTestBaseline(const void *arg)
{
    const struct data *data = arg;
    int ret = -1;
    virCPUDefPtr *cpus = NULL;
    virCPUDefPtr baseline = NULL;
    unsigned int ncpus = 0;
    char *result = NULL;
    unsigned int i;

    if (!(cpus = cpuTestLoadMultiXML(data->arch, data->name, &ncpus)))
        goto cleanup;

    baseline = cpuBaseline(cpus, ncpus, NULL, 0);
    if (data->result < 0) {
        virResetLastError();
        if (!baseline)
            ret = 0;
        else if (virTestGetVerbose()) {
            fprintf(stderr, "\n%-70s... ",
                    "cpuBaseline was expected to fail but it succeeded");
        }
        goto cleanup;
    }
    if (!baseline)
        goto cleanup;

    if (virAsprintf(&result, "%s-result", data->name) < 0)
        goto cleanup;

    if (cpuTestCompareXML(data->arch, baseline, result, 0) < 0)
        goto cleanup;

    for (i = 0; i < ncpus; i++) {
        virCPUCompareResult cmp;

        cmp = cpuCompare(cpus[i], baseline);
        if (cmp != VIR_CPU_COMPARE_SUPERSET &&
            cmp != VIR_CPU_COMPARE_IDENTICAL) {
            if (virTestGetVerbose()) {
                fprintf(stderr,
                        "\nbaseline CPU is incompatible with CPU %u\n", i);
                fprintf(stderr, "%74s", "... ");
            }
            ret = -1;
            goto cleanup;
        }
    }

    ret = 0;

cleanup:
    if (cpus) {
        for (i = 0; i < ncpus; i++)
            virCPUDefFree(cpus[i]);
        VIR_FREE(cpus);
    }
    virCPUDefFree(baseline);
    VIR_FREE(result);
    return ret;
}
コード例 #20
0
ファイル: viruritest.c プロジェクト: bigclouds/libvirt
static int testURIParse(const void *args)
{
    int ret = -1;
    virURIPtr uri = NULL;
    const struct URIParseData *data = args;
    char *uristr = NULL;
    size_t i;

    if (!(uri = virURIParse(data->uri)))
        goto cleanup;

    if (!STREQ(uri->scheme, data->scheme)) {
        VIR_DEBUG("Expected scheme '%s', actual '%s'",
                  data->scheme, uri->scheme);
        goto cleanup;
    }

    if (!STREQ(uri->server, data->server)) {
        VIR_DEBUG("Expected server '%s', actual '%s'",
                  data->server, uri->server);
        goto cleanup;
    }

    if (uri->port != data->port) {
        VIR_DEBUG("Expected port '%d', actual '%d'",
                  data->port, uri->port);
        goto cleanup;
    }

    if (!STREQ_NULLABLE(uri->path, data->path)) {
        VIR_DEBUG("Expected path '%s', actual '%s'",
                  data->path, uri->path);
        goto cleanup;
    }

    if (!STREQ_NULLABLE(uri->query, data->query)) {
        VIR_DEBUG("Expected query '%s', actual '%s'",
                  data->query, uri->query);
        goto cleanup;
    }

    if (!STREQ_NULLABLE(uri->fragment, data->fragment)) {
        VIR_DEBUG("Expected fragment '%s', actual '%s'",
                  data->fragment, uri->fragment);
        goto cleanup;
    }

    for (i = 0 ; data->params && data->params[i].name && i < uri->paramsCount ; i++) {
        if (!STREQ_NULLABLE(data->params[i].name, uri->params[i].name)) {
            VIR_DEBUG("Expected param name %zu '%s', actual '%s'",
                      i, data->params[i].name, uri->params[i].name);
            goto cleanup;
        }
        if (!STREQ_NULLABLE(data->params[i].value, uri->params[i].value)) {
            VIR_DEBUG("Expected param value %zu '%s', actual '%s'",
                      i, data->params[i].value, uri->params[i].value);
            goto cleanup;
        }
    }
    if (data->params && data->params[i].name) {
        VIR_DEBUG("Missing parameter %zu %s=%s",
                  i, data->params[i].name, data->params[i].value);
        goto cleanup;
    }
    if (i != uri->paramsCount) {
        VIR_DEBUG("Unexpected parameter %zu %s=%s",
                  i, uri->params[i].name, uri->params[i].value);
        goto cleanup;
    }

    VIR_FREE(uri->query);
    uri->query = virURIFormatParams(uri);

    if (!(uristr = virURIFormat(uri)))
        goto cleanup;

    if (!STREQ(uristr, data->uri_out)) {
        VIR_DEBUG("URI did not roundtrip, expect '%s', actual '%s'",
                  data->uri_out, uristr);
        goto cleanup;
    }

    ret = 0;
cleanup:
    VIR_FREE(uristr);
    virURIFree(uri);
    return ret;
}
コード例 #21
0
ファイル: conf.c プロジェクト: mithleshvrts/libvirt-0.10.2
/**
 * virConfParseValue:
 * @ctxt: the parsing context
 *
 * Parse one value
 *
 * Returns a pointer to the value or NULL in case of error
 */
static virConfValuePtr
virConfParseValue(virConfParserCtxtPtr ctxt)
{
    virConfValuePtr ret, lst = NULL, tmp, prev;
    virConfType type = VIR_CONF_NONE;
    char *str = NULL;
    long  l = 0;

    SKIP_BLANKS;
    if (ctxt->cur >= ctxt->end) {
        virConfError(ctxt, VIR_ERR_CONF_SYNTAX, _("expecting a value"));
        return NULL;
    }
    if ((CUR == '"') || (CUR == '\'')) {
        type = VIR_CONF_STRING;
        str = virConfParseString(ctxt);
        if (str == NULL)
            return NULL;
    } else if (CUR == '[') {
        if (ctxt->conf->flags & VIR_CONF_FLAG_VMX_FORMAT) {
            virConfError(ctxt, VIR_ERR_CONF_SYNTAX,
                         _("lists not allowed in VMX format"));
            return NULL;
        }
        type = VIR_CONF_LIST;
        NEXT;
        SKIP_BLANKS_AND_EOL;
        if ((ctxt->cur < ctxt->end) && (CUR != ']')) {
            if ((lst = virConfParseValue(ctxt)) == NULL)
                return NULL;
            SKIP_BLANKS_AND_EOL;
        }
        while ((ctxt->cur < ctxt->end) && (CUR != ']')) {

            /* Tell Clang that when execution reaches this point
               "lst" is guaranteed to be non-NULL.  This stops it
               from issuing an invalid NULL-dereference warning about
               "prev = lst; while (prev->next..." below.  */
            sa_assert (lst);

            if (CUR != ',') {
                virConfError(ctxt, VIR_ERR_CONF_SYNTAX,
                             _("expecting a separator in list"));
                virConfFreeList(lst);
                return NULL;
            }
            NEXT;
            SKIP_BLANKS_AND_EOL;
            if (CUR == ']') {
                break;
            }
            tmp = virConfParseValue(ctxt);
            if (tmp == NULL) {
                virConfFreeList(lst);
                return NULL;
            }
            prev = lst;
            while (prev->next != NULL) prev = prev->next;
            prev->next = tmp;
            SKIP_BLANKS_AND_EOL;
        }
        if (CUR == ']') {
            NEXT;
        } else {
            virConfError(ctxt, VIR_ERR_CONF_SYNTAX,
                         _("list is not closed with ]"));
            virConfFreeList(lst);
            return NULL;
        }
    } else if (c_isdigit(CUR) || (CUR == '-') || (CUR == '+')) {
        if (ctxt->conf->flags & VIR_CONF_FLAG_VMX_FORMAT) {
            virConfError(ctxt, VIR_ERR_CONF_SYNTAX,
                         _("numbers not allowed in VMX format"));
            return NULL;
        }
        if (virConfParseLong(ctxt, &l) < 0) {
            return NULL;
        }
        type = VIR_CONF_LONG;
    } else {
        virConfError(ctxt, VIR_ERR_CONF_SYNTAX, _("expecting a value"));
        return NULL;
    }
    if (VIR_ALLOC(ret) < 0) {
        virReportOOMError();
        virConfFreeList(lst);
        VIR_FREE(str);
        return NULL;
    }
    ret->type = type;
    ret->l = l;
    ret->str = str;
    ret->list = lst;
    return ret;
}
コード例 #22
0
ファイル: node_device_driver.c プロジェクト: rbu/libvirt
static int
nodeDeviceVportCreateDelete(const int parent_host,
                            const char *wwpn,
                            const char *wwnn,
                            int operation)
{
    int retval = 0;
    char *operation_path = NULL, *vport_name = NULL;
    const char *operation_file = NULL;
    struct stat st;

    switch (operation) {
    case VPORT_CREATE:
        operation_file = LINUX_SYSFS_VPORT_CREATE_POSTFIX;
        break;
    case VPORT_DELETE:
        operation_file = LINUX_SYSFS_VPORT_DELETE_POSTFIX;
        break;
    default:
        virNodeDeviceReportError(VIR_ERR_INTERNAL_ERROR,
                                 _("Invalid vport operation (%d)"), operation);
        retval = -1;
        goto cleanup;
        break;
    }

    if (virAsprintf(&operation_path,
                    "%shost%d%s",
                    LINUX_SYSFS_FC_HOST_PREFIX,
                    parent_host,
                    operation_file) < 0) {

        virReportOOMError();
        retval = -1;
        goto cleanup;
    }

    if (stat(operation_path, &st) != 0) {
        VIR_FREE(operation_path);
        if (virAsprintf(&operation_path,
                        "%shost%d%s",
                        LINUX_SYSFS_SCSI_HOST_PREFIX,
                        parent_host,
                        operation_file) < 0) {
            virReportOOMError();
            retval = -1;
            goto cleanup;
        }

        if (stat(operation_path, &st) != 0) {
            VIR_ERROR(_("No vport operation path found for host%d"),
                      parent_host);
            retval = -1;
            goto cleanup;
        }
    }

    VIR_DEBUG("Vport operation path is '%s'", operation_path);

    if (virAsprintf(&vport_name,
                    "%s:%s",
                    wwpn,
                    wwnn) < 0) {

        virReportOOMError();
        retval = -1;
        goto cleanup;
    }

    if (virFileWriteStr(operation_path, vport_name, 0) == -1) {
        virReportSystemError(errno,
                             _("Write of '%s' to '%s' during "
                               "vport create/delete failed"),
                             vport_name, operation_path);
        retval = -1;
    }

cleanup:
    VIR_FREE(vport_name);
    VIR_FREE(operation_path);
    VIR_DEBUG("%s", _("Vport operation complete"));
    return retval;
}
コード例 #23
0
ファイル: block_stats.c プロジェクト: foomango/libvirt
int
xenLinuxDomainDeviceID(int domid, const char *path)
{
    int major, minor;
    int part;
    int retval;
    char *mod_path;

    int const scsi_majors[] = { SCSI_DISK0_MAJOR, SCSI_DISK1_MAJOR,
                                SCSI_DISK2_MAJOR, SCSI_DISK3_MAJOR,
                                SCSI_DISK4_MAJOR, SCSI_DISK5_MAJOR,
                                SCSI_DISK6_MAJOR, SCSI_DISK7_MAJOR,
                                SCSI_DISK8_MAJOR, SCSI_DISK9_MAJOR,
                                SCSI_DISK10_MAJOR, SCSI_DISK11_MAJOR,
                                SCSI_DISK12_MAJOR, SCSI_DISK13_MAJOR,
                                SCSI_DISK14_MAJOR, SCSI_DISK15_MAJOR };
    int const ide_majors[] = { IDE0_MAJOR, IDE1_MAJOR, IDE2_MAJOR, IDE3_MAJOR,
                               IDE4_MAJOR, IDE5_MAJOR, IDE6_MAJOR, IDE7_MAJOR,
                               IDE8_MAJOR, IDE9_MAJOR };

    /*
     * Possible block device majors & partition ranges. This
     * matches the ranges supported in Xend xen/util/blkif.py
     *
     * hdNM:  N=a-t, M=1-63, major={IDE0_MAJOR -> IDE9_MAJOR}
     * sdNM:  N=a-z,aa-iv, M=1-15, major={SCSI_DISK0_MAJOR -> SCSI_DISK15_MAJOR}
     * xvdNM: N=a-p M=1-15, major=XENVBD_MAJOR
     * xvdNM: N=q-z,aa-iz M=1-15, major=(1<<28)
     *
     * The path for statistics will be
     *
     * /sys/devices/xen-backend/(vbd|tap)-{domid}-{devid}/statistics/{...}
     */

    if (strlen(path) >= 5 && STRPREFIX(path, "/dev/"))
        retval = virAsprintf(&mod_path, "%s", path);
    else
        retval = virAsprintf(&mod_path, "/dev/%s", path);

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

    retval = -1;

    if (disk_re_match("/dev/sd[a-z]([1-9]|1[0-5])?$", mod_path, &part)) {
        major = scsi_majors[(mod_path[7] - 'a') / 16];
        minor = ((mod_path[7] - 'a') % 16) * 16 + part;
        retval = major * 256 + minor;
    }
    else if (disk_re_match("/dev/sd[a-h][a-z]([1-9]|1[0-5])?$",
                           mod_path, &part) ||
             disk_re_match("/dev/sdi[a-v]([1-9]|1[0-5])?$",
                           mod_path, &part)) {
        major = scsi_majors[((mod_path[7] - 'a' + 1) * 26 + (mod_path[8] - 'a')) / 16];
        minor = (((mod_path[7] - 'a' + 1) * 26 + (mod_path[8] - 'a')) % 16)
            * 16 + part;
        retval = major * 256 + minor;
    }
    else if (disk_re_match("/dev/hd[a-t]([1-9]|[1-5][0-9]|6[0-3])?$",
                           mod_path, &part)) {
        major = ide_majors[(mod_path[7] - 'a') / 2];
        minor = ((mod_path[7] - 'a') % 2) * 64 + part;
        retval = major * 256 + minor;
    }
    else if (disk_re_match("/dev/xvd[a-p]([1-9]|1[0-5])?$", mod_path, &part))
        retval = (202 << 8) + ((mod_path[8] - 'a') << 4) + part;
    else if (disk_re_match("/dev/xvd[q-z]([1-9]|1[0-5])?$", mod_path, &part))
        retval = (1 << 28) + ((mod_path[8] - 'a') << 8) + part;
    else if (disk_re_match("/dev/xvd[a-i][a-z]([1-9]|1[0-5])?$",
                           mod_path, &part))
        retval = (1 << 28) + (((mod_path[8] - 'a' + 1) * 26 + (mod_path[9] - 'a')) << 8) + part;
    /*
     * OK, we've now checked the common case (things that work); check the
     * beginning of the strings for better error messages
     */
    else if (strlen(mod_path) >= 7 && STRPREFIX(mod_path, "/dev/sd"))
        statsError(VIR_ERR_INVALID_ARG,
                   _("invalid path, device names must be in the range "
                     "sda[1-15] - sdiv[1-15] for domain %d"), domid);
    else if (strlen(mod_path) >= 7 && STRPREFIX(mod_path, "/dev/hd"))
        statsError(VIR_ERR_INVALID_ARG,
                   _("invalid path, device names must be in the range "
                     "hda[1-63] - hdt[1-63] for domain %d"), domid);
    else if (strlen(mod_path) >= 8 && STRPREFIX(mod_path, "/dev/xvd"))
        statsError(VIR_ERR_INVALID_ARG,
                   _("invalid path, device names must be in the range "
                     "xvda[1-15] - xvdiz[1-15] for domain %d"), domid);
    else
        statsError(VIR_ERR_INVALID_ARG,
                   _("unsupported path, use xvdN, hdN, or sdN for domain %d"),
                   domid);

    VIR_FREE(mod_path);

    return retval;
}
コード例 #24
0
ファイル: openvz_conf.c プロジェクト: i-ninth/libvirt
int
openvzReadNetworkConf(virDomainDefPtr def,
                      int veid)
{
    int ret;
    virDomainNetDefPtr net = NULL;
    char *temp = NULL;
    char *token, *saveptr = NULL;

    /*parse routing network configuration*
     * Sample from config:
     *   IP_ADDRESS="1.1.1.1 1.1.1.2"
     *   splited IPs by space
     */
    ret = openvzReadVPSConfigParam(veid, "IP_ADDRESS", &temp);
    if (ret < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Could not read 'IP_ADDRESS' from config for container %d"),
                       veid);
        goto error;
    } else if (ret > 0) {
        token = strtok_r(temp, " ", &saveptr);
        while (token != NULL) {
            if (VIR_ALLOC(net) < 0)
                goto error;

            net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
            if (VIR_STRDUP(net->data.ethernet.ipaddr, token) < 0)
                goto error;

            if (VIR_APPEND_ELEMENT_COPY(def->nets, def->nnets, net) < 0)
                goto error;

            token = strtok_r(NULL, " ", &saveptr);
        }
    }

    /*parse bridge devices*/
    /*Sample from config:
     *NETIF="ifname=eth10,mac=00:18:51:C1:05:EE,host_ifname=veth105.10,host_mac=00:18:51:8F:D9:F3"
     *devices splited by ';'
     */
    ret = openvzReadVPSConfigParam(veid, "NETIF", &temp);
    if (ret < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Could not read 'NETIF' from config for container %d"),
                       veid);
        goto error;
    } else if (ret > 0) {
        token = strtok_r(temp, ";", &saveptr);
        while (token != NULL) {
            /*add new device to list*/
            if (VIR_ALLOC(net) < 0)
                goto error;

            net->type = VIR_DOMAIN_NET_TYPE_BRIDGE;

            char *p = token;
            char cpy_temp[32];
            int len;

            /*parse string*/
            do {
                char *next = strchrnul(p, ',');
                if (STRPREFIX(p, "ifname=")) {
                    /* skip in libvirt */
                } else if (STRPREFIX(p, "host_ifname=")) {
                    p += 12;
                    len = next - p;
                    if (len > 16) {
                        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                       _("Too long network device name"));
                        goto error;
                    }

                    if (VIR_ALLOC_N(net->ifname, len+1) < 0)
                        goto error;

                    if (virStrncpy(net->ifname, p, len, len+1) == NULL) {
                        virReportError(VIR_ERR_INTERNAL_ERROR,
                                       _("Network ifname %s too long for destination"), p);
                        goto error;
                    }
                } else if (STRPREFIX(p, "bridge=")) {
                    p += 7;
                    len = next - p;
                    if (len > 16) {
                        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                       _("Too long bridge device name"));
                        goto error;
                    }

                    if (VIR_ALLOC_N(net->data.bridge.brname, len+1) < 0)
                        goto error;

                    if (virStrncpy(net->data.bridge.brname, p, len, len+1) == NULL) {
                        virReportError(VIR_ERR_INTERNAL_ERROR,
                                       _("Bridge name %s too long for destination"), p);
                        goto error;
                    }
                } else if (STRPREFIX(p, "mac=")) {
                    p += 4;
                    len = next - p;
                    if (len != 17) { /* should be 17 */
                        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                       _("Wrong length MAC address"));
                        goto error;
                    }
                    if (virStrncpy(cpy_temp, p, len, sizeof(cpy_temp)) == NULL) {
                        virReportError(VIR_ERR_INTERNAL_ERROR,
                                       _("MAC address %s too long for destination"), p);
                        goto error;
                    }
                    if (virMacAddrParse(cpy_temp, &net->mac) < 0) {
                        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                       _("Wrong MAC address"));
                        goto error;
                    }
                }
                p = ++next;
            } while (p < token + strlen(token));

            if (VIR_APPEND_ELEMENT_COPY(def->nets, def->nnets, net) < 0)
                goto error;

            token = strtok_r(NULL, ";", &saveptr);
        }
    }

    VIR_FREE(temp);

    return 0;

 error:
    VIR_FREE(temp);
    virDomainNetDefFree(net);
    return -1;
}
コード例 #25
0
ファイル: virjson.c プロジェクト: miurahr/libvirt
/* XXX add an incremental streaming parser - yajl trivially supports it */
virJSONValuePtr virJSONValueFromString(const char *jsonstring)
{
    yajl_handle hand;
    virJSONParser parser = { NULL, NULL, 0 };
    virJSONValuePtr ret = NULL;
# ifndef WITH_YAJL2
    yajl_parser_config cfg = { 1, 1 };
# endif

    VIR_DEBUG("string=%s", jsonstring);

# ifdef WITH_YAJL2
    hand = yajl_alloc(&parserCallbacks, NULL, &parser);
    if (hand) {
        yajl_config(hand, yajl_allow_comments, 1);
        yajl_config(hand, yajl_dont_validate_strings, 0);
    }
# else
    hand = yajl_alloc(&parserCallbacks, &cfg, NULL, &parser);
# endif
    if (!hand) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Unable to create JSON parser"));
        goto cleanup;
    }

    if (yajl_parse(hand,
                   (const unsigned char *)jsonstring,
                   strlen(jsonstring)) != yajl_status_ok) {
        unsigned char *errstr = yajl_get_error(hand, 1,
                                               (const unsigned char*)jsonstring,
                                               strlen(jsonstring));

        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("cannot parse json %s: %s"),
                       jsonstring, (const char*) errstr);
        VIR_FREE(errstr);
        virJSONValueFree(parser.head);
        goto cleanup;
    }

    if (parser.nstate != 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("cannot parse json %s: unterminated string/map/array"),
                       jsonstring);
        virJSONValueFree(parser.head);
    } else {
        ret = parser.head;
    }

cleanup:
    yajl_free(hand);

    if (parser.nstate) {
        size_t i;
        for (i = 0; i < parser.nstate; i++)
            VIR_FREE(parser.state[i].key);
        VIR_FREE(parser.state);
    }

    VIR_DEBUG("result=%p", parser.head);

    return ret;
}
コード例 #26
0
ファイル: openvz_conf.c プロジェクト: i-ninth/libvirt
static int
openvzReadFSConf(virDomainDefPtr def,
                 int veid)
{
    int ret;
    virDomainFSDefPtr fs = NULL;
    char *veid_str = NULL;
    char *temp = NULL;
    const char *param;
    unsigned long long barrier, limit;

    ret = openvzReadVPSConfigParam(veid, "OSTEMPLATE", &temp);
    if (ret < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Could not read 'OSTEMPLATE' from config for container %d"),
                       veid);
        goto error;
    } else if (ret > 0) {
        if (VIR_ALLOC(fs) < 0)
            goto error;

        fs->type = VIR_DOMAIN_FS_TYPE_TEMPLATE;
        if (VIR_STRDUP(fs->src, temp) < 0)
            goto error;
    } else {
        /* OSTEMPLATE was not found, VE was booted from a private dir directly */
        ret = openvzReadVPSConfigParam(veid, "VE_PRIVATE", &temp);
        if (ret <= 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Could not read 'VE_PRIVATE' from config for container %d"),
                           veid);
            goto error;
        }

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

        if (virAsprintf(&veid_str, "%d", veid) < 0)
            goto error;

        fs->type = VIR_DOMAIN_FS_TYPE_MOUNT;
        if (!(fs->src = openvz_replace(temp, "$VEID", veid_str)))
            goto no_memory;

        VIR_FREE(veid_str);
    }

    if (VIR_STRDUP(fs->dst, "/") < 0)
        goto error;

    param = "DISKSPACE";
    ret = openvzReadVPSConfigParam(veid, param, &temp);
    if (ret > 0) {
        if (openvzParseBarrierLimit(temp, &barrier, &limit)) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Could not read '%s' from config for container %d"),
                           param, veid);
            goto error;
        } else {
            /* Ensure that we can multiply by 1024 without overflowing. */
            if (barrier > ULLONG_MAX / 1024 ||
                limit > ULLONG_MAX / 1024) {
                virReportSystemError(VIR_ERR_OVERFLOW, "%s",
                                     _("Unable to parse quota"));
                goto error;
            }
            fs->space_soft_limit = barrier * 1024; /* unit is bytes */
            fs->space_hard_limit = limit * 1024;   /* unit is bytes */
        }
    }

    if (VIR_APPEND_ELEMENT(def->fss, def->nfss, fs) < 0)
        goto error;

    VIR_FREE(temp);

    return 0;
 no_memory:
    virReportOOMError();
 error:
    VIR_FREE(temp);
    virDomainFSDefFree(fs);
    return -1;
}
コード例 #27
0
ファイル: virhostcpu.c プロジェクト: ZhuoyuZhang/libvirt
int
virHostCPUGetInfoPopulateLinux(FILE *cpuinfo,
                               virArch arch,
                               unsigned int *cpus,
                               unsigned int *mhz,
                               unsigned int *nodes,
                               unsigned int *sockets,
                               unsigned int *cores,
                               unsigned int *threads)
{
    virBitmapPtr present_cpus_map = NULL;
    virBitmapPtr online_cpus_map = NULL;
    char line[1024];
    DIR *nodedir = NULL;
    struct dirent *nodedirent = NULL;
    int nodecpus, nodecores, nodesockets, nodethreads, offline = 0;
    int threads_per_subcore = 0;
    unsigned int node;
    int ret = -1;
    char *sysfs_nodedir = NULL;
    char *sysfs_cpudir = NULL;
    int direrr;

    *mhz = 0;
    *cpus = *nodes = *sockets = *cores = *threads = 0;

    /* Start with parsing CPU clock speed from /proc/cpuinfo */
    while (fgets(line, sizeof(line), cpuinfo) != NULL) {
        if (ARCH_IS_X86(arch)) {
            char *buf = line;
            if (STRPREFIX(buf, "cpu MHz")) {
                char *p;
                unsigned int ui;

                buf += 7;
                while (*buf && c_isspace(*buf))
                    buf++;

                if (*buf != ':' || !buf[1]) {
                    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                   _("parsing cpu MHz from cpuinfo"));
                    goto cleanup;
                }

                if (virStrToLong_ui(buf+1, &p, 10, &ui) == 0 &&
                    /* Accept trailing fractional part.  */
                    (*p == '\0' || *p == '.' || c_isspace(*p)))
                    *mhz = ui;
            }
        } else if (ARCH_IS_PPC(arch)) {
            char *buf = line;
            if (STRPREFIX(buf, "clock")) {
                char *p;
                unsigned int ui;

                buf += 5;
                while (*buf && c_isspace(*buf))
                    buf++;

                if (*buf != ':' || !buf[1]) {
                    virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                                   _("parsing cpu MHz from cpuinfo"));
                    goto cleanup;
                }

                if (virStrToLong_ui(buf+1, &p, 10, &ui) == 0 &&
                    /* Accept trailing fractional part.  */
                    (*p == '\0' || *p == '.' || c_isspace(*p)))
                    *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 if (ARCH_IS_ARM(arch)) {
            char *buf = line;
            if (STRPREFIX(buf, "BogoMIPS")) {
                char *p;
                unsigned int ui;

                buf += 8;
                while (*buf && c_isspace(*buf))
                    buf++;

                if (*buf != ':' || !buf[1]) {
                    virReportError(VIR_ERR_INTERNAL_ERROR,
                                   "%s", _("parsing cpu MHz from cpuinfo"));
                    goto cleanup;
                }

                if (virStrToLong_ui(buf+1, &p, 10, &ui) == 0
                    /* Accept trailing fractional part.  */
                    && (*p == '\0' || *p == '.' || c_isspace(*p)))
                    *mhz = ui;
            }
        } else if (ARCH_IS_S390(arch)) {
            /* s390x has no realistic value for CPU speed,
             * assign a value of zero to signify this */
            *mhz = 0;
        } else {
            VIR_WARN("Parser for /proc/cpuinfo needs to be adapted for your architecture");
            break;
        }
    }

    /* Get information about what CPUs are present in the host and what
     * CPUs are online, so that we don't have to so for each node */
    present_cpus_map = virHostCPUGetPresentBitmap();
    if (!present_cpus_map)
        goto cleanup;
    online_cpus_map = virHostCPUGetOnlineBitmap();
    if (!online_cpus_map)
        goto cleanup;

    /* OK, we've parsed clock speed out of /proc/cpuinfo. Get the
     * core, node, socket, thread and topology information from /sys
     */
    if (virAsprintf(&sysfs_nodedir, "%s/node", sysfs_system_path) < 0)
        goto cleanup;

    if (!(nodedir = opendir(sysfs_nodedir))) {
        /* the host isn't probably running a NUMA architecture */
        goto fallback;
    }

    /* PPC-KVM needs the secondary threads of a core to be offline on the
     * host. The kvm scheduler brings the secondary threads online in the
     * guest context. Moreover, P8 processor has split-core capability
     * where, there can be 1,2 or 4 subcores per core. The primaries of the
     * subcores alone will be online on the host for a subcore in the
     * host. Even though the actual threads per core for P8 processor is 8,
     * depending on the subcores_per_core = 1, 2 or 4, the threads per
     * subcore will vary accordingly to 8, 4 and 2 repectively.
     * So, On host threads_per_core what is arrived at from sysfs in the
     * current logic is actually the subcores_per_core. Threads per subcore
     * can only be obtained from the kvm device. For example, on P8 wih 1
     * core having 8 threads, sub_cores_percore=4, the threads 0,2,4 & 6
     * will be online. The sysfs reflects this and in the current logic
     * variable 'threads' will be 4 which is nothing but subcores_per_core.
     * If the user tampers the cpu online/offline states using chcpu or other
     * means, then it is an unsupported configuration for kvm.
     * The code below tries to keep in mind
     *  - when the libvirtd is run inside a KVM guest or Phyp based guest.
     *  - Or on the kvm host where user manually tampers the cpu states to
     *    offline/online randomly.
     * On hosts other than POWER this will be 0, in which case a simpler
     * thread-counting logic will be used  */
    if ((threads_per_subcore = virHostCPUGetThreadsPerSubcore(arch)) < 0)
        goto cleanup;

    /* If the subcore configuration is not valid, just pretend subcores
     * are not in use and count threads one by one */
    if (!virHostCPUHasValidSubcoreConfiguration(threads_per_subcore))
        threads_per_subcore = 0;

    while ((direrr = virDirRead(nodedir, &nodedirent, sysfs_nodedir)) > 0) {
        if (sscanf(nodedirent->d_name, "node%u", &node) != 1)
            continue;

        (*nodes)++;

        if (virAsprintf(&sysfs_cpudir, "%s/node/%s",
                        sysfs_system_path, nodedirent->d_name) < 0)
            goto cleanup;

        if ((nodecpus = virHostCPUParseNode(sysfs_cpudir, arch,
                                            present_cpus_map,
                                            online_cpus_map,
                                            threads_per_subcore,
                                            &nodesockets, &nodecores,
                                            &nodethreads, &offline)) < 0)
            goto cleanup;

        VIR_FREE(sysfs_cpudir);

        *cpus += nodecpus;

        *sockets += nodesockets;

        if (nodecores > *cores)
            *cores = nodecores;

        if (nodethreads > *threads)
            *threads = nodethreads;
    }

    if (direrr < 0)
        goto cleanup;

    if (*cpus && *nodes)
        goto done;

 fallback:
    VIR_FREE(sysfs_cpudir);

    if (virAsprintf(&sysfs_cpudir, "%s/cpu", sysfs_system_path) < 0)
        goto cleanup;

    if ((nodecpus = virHostCPUParseNode(sysfs_cpudir, arch,
                                        present_cpus_map,
                                        online_cpus_map,
                                        threads_per_subcore,
                                        &nodesockets, &nodecores,
                                        &nodethreads, &offline)) < 0)
        goto cleanup;

    *nodes = 1;
    *cpus = nodecpus;
    *sockets = nodesockets;
    *cores = nodecores;
    *threads = nodethreads;

 done:
    /* There should always be at least one cpu, socket, node, and thread. */
    if (*cpus == 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("no CPUs found"));
        goto cleanup;
    }

    if (*sockets == 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("no sockets found"));
        goto cleanup;
    }

    if (*threads == 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("no threads found"));
        goto cleanup;
    }

    /* Now check if the topology makes sense. There are machines that don't
     * expose their real number of nodes or for example the AMD Bulldozer
     * architecture that exposes their Clustered integer core modules as both
     * threads and cores. This approach throws off our detection. Unfortunately
     * the nodeinfo structure isn't designed to carry the full topology so
     * we're going to lie about the detected topology to notify the user
     * to check the host capabilities for the actual topology. */
    if ((*sockets *
         *cores *
         *threads) != (*cpus + offline)) {
        *nodes = 1;
        *sockets = 1;
        *cores = *cpus + offline;
        *threads = 1;
    }

    ret = 0;

 cleanup:
    /* don't shadow a more serious error */
    if (nodedir && closedir(nodedir) < 0 && ret >= 0) {
        virReportSystemError(errno, _("problem closing %s"), sysfs_nodedir);
        ret = -1;
    }

    virBitmapFree(present_cpus_map);
    virBitmapFree(online_cpus_map);
    VIR_FREE(sysfs_nodedir);
    VIR_FREE(sysfs_cpudir);
    return ret;
}
コード例 #28
0
ファイル: openvz_conf.c プロジェクト: i-ninth/libvirt
static int
openvzReadMemConf(virDomainDefPtr def, int veid)
{
    int ret = -1;
    char *temp = NULL;
    unsigned long long barrier, limit;
    const char *param;
    long kb_per_pages;

    kb_per_pages = openvzKBPerPages();
    if (kb_per_pages < 0)
        goto error;

    /* Memory allocation guarantee */
    param = "VMGUARPAGES";
    ret = openvzReadVPSConfigParam(veid, param, &temp);
    if (ret < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Could not read '%s' from config for container %d"),
                       param, veid);
        goto error;
    } else if (ret > 0) {
        ret = openvzParseBarrierLimit(temp, &barrier, NULL);
        if (ret < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Could not parse barrier of '%s' "
                             "from config for container %d"), param, veid);
            goto error;
        }
        if (barrier == LONG_MAX)
            def->mem.min_guarantee = 0ull;
        else
            def->mem.min_guarantee = barrier * kb_per_pages;
    }

    /* Memory hard and soft limits */
    param = "PRIVVMPAGES";
    ret = openvzReadVPSConfigParam(veid, param, &temp);
    if (ret < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Could not read '%s' from config for container %d"),
                       param, veid);
        goto error;
    } else if (ret > 0) {
        ret = openvzParseBarrierLimit(temp, &barrier, &limit);
        if (ret < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Could not parse barrier and limit of '%s' "
                             "from config for container %d"), param, veid);
            goto error;
        }
        if (barrier == LONG_MAX)
            def->mem.soft_limit = 0ull;
        else
            def->mem.soft_limit = barrier * kb_per_pages;

        if (limit == LONG_MAX)
            def->mem.hard_limit = 0ull;
        else
            def->mem.hard_limit = limit * kb_per_pages;
    }

    ret = 0;
 error:
    VIR_FREE(temp);
    return ret;
}
コード例 #29
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.
 */
virDrvOpenStatus
xenInotifyOpen(virConnectPtr conn,
               virConnectAuthPtr auth ATTRIBUTE_UNUSED,
               unsigned int flags)
{
    DIR *dh;
    struct dirent *ent;
    char *path;
    xenUnifiedPrivatePtr priv = (xenUnifiedPrivatePtr) conn->privateData;

    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

    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) {
            virReportOOMError();
            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;
}
コード例 #30
0
ファイル: uml_conf.c プロジェクト: Antique/libvirt
static char *
umlBuildCommandLineNet(virConnectPtr conn,
                       virDomainDefPtr vm,
                       virDomainNetDefPtr def,
                       int idx)
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    char macaddr[VIR_MAC_STRING_BUFLEN];

    /* General format:  ethNN=type,options */

    virBufferAsprintf(&buf, "eth%d=", idx);

    switch (def->type) {
    case VIR_DOMAIN_NET_TYPE_USER:
        /* ethNNN=slirp,macaddr */
        virBufferAddLit(&buf, "slirp");
        break;

    case VIR_DOMAIN_NET_TYPE_ETHERNET:
        /* ethNNN=tuntap,tapname,macaddr,gateway */
        virBufferAddLit(&buf, "tuntap,");
        if (def->ifname)
            virBufferAdd(&buf, def->ifname, -1);
        if (def->guestIP.nips > 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("IP address not supported for ethernet interface"));
            goto error;
        }
        break;

    case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("vhostuser networking type not supported"));
        goto error;

    case VIR_DOMAIN_NET_TYPE_SERVER:
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("TCP server networking type not supported"));
        goto error;

    case VIR_DOMAIN_NET_TYPE_CLIENT:
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("TCP client networking type not supported"));
        goto error;

    case VIR_DOMAIN_NET_TYPE_UDP:
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("UDP networking type not supported"));
        goto error;

    case VIR_DOMAIN_NET_TYPE_MCAST:
        /* ethNNN=tuntap,macaddr,ipaddr,port */
        virBufferAddLit(&buf, "mcast");
        break;

    case VIR_DOMAIN_NET_TYPE_NETWORK:
    {
        char *bridge;
        virNetworkPtr network = virNetworkLookupByName(conn,
                                                       def->data.network.name);
        if (!network) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Network '%s' not found"),
                           def->data.network.name);
            goto error;
        }
        bridge = virNetworkGetBridgeName(network);
        virObjectUnref(network);
        if (bridge == NULL)
            goto error;

        if (umlConnectTapDevice(vm, def, bridge) < 0) {
            VIR_FREE(bridge);
            goto error;
        }

        /* ethNNN=tuntap,tapname,macaddr,gateway */
        virBufferAsprintf(&buf, "tuntap,%s", def->ifname);
        break;
    }

    case VIR_DOMAIN_NET_TYPE_BRIDGE:
        if (umlConnectTapDevice(vm, def,
                                def->data.bridge.brname) < 0)
            goto error;

        /* ethNNN=tuntap,tapname,macaddr,gateway */
        virBufferAsprintf(&buf, "tuntap,%s", def->ifname);
        break;

    case VIR_DOMAIN_NET_TYPE_INTERNAL:
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("internal networking type not supported"));
        goto error;

    case VIR_DOMAIN_NET_TYPE_DIRECT:
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("direct networking type not supported"));
        goto error;

    case VIR_DOMAIN_NET_TYPE_HOSTDEV:
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("hostdev networking type not supported"));
        goto error;

    case VIR_DOMAIN_NET_TYPE_LAST:
        break;
    }

    if (def->script) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("interface script execution not supported by this driver"));
        goto error;
    }

    virBufferAsprintf(&buf, ",%s", virMacAddrFormat(&def->mac, macaddr));

    if (def->type == VIR_DOMAIN_NET_TYPE_MCAST) {
        virBufferAsprintf(&buf, ",%s,%d",
                          def->data.socket.address,
                          def->data.socket.port);
    }

    if (virBufferCheckError(&buf) < 0)
        return NULL;

    return virBufferContentAndReset(&buf);

 error:
    virBufferFreeAndReset(&buf);
    return NULL;
}