libxl_conf.c 41.6 KB
Newer Older
1 2 3
/*
 * libxl_conf.c: libxl configuration management
 *
4
 * Copyright (C) 2012-2014 Red Hat, Inc.
5
 * Copyright (c) 2011-2013 SUSE LINUX Products GmbH, Nuernberg, Germany.
E
Eric Blake 已提交
6
 * Copyright (C) 2011 Univention GmbH.
J
Jim Fehlig 已提交
7 8 9 10 11 12 13 14 15 16 17 18
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
19
 * License along with this library.  If not, see
O
Osier Yang 已提交
20
 * <http://www.gnu.org/licenses/>.
M
Markus Groß 已提交
21 22 23
 *
 * Authors:
 *     Jim Fehlig <jfehlig@novell.com>
24
 *     Markus Groß <gross@univention.de>
J
Jim Fehlig 已提交
25 26 27 28 29 30 31 32 33 34
 */

#include <config.h>

#include <regex.h>
#include <libxl.h>
#include <sys/types.h>
#include <sys/socket.h>

#include "internal.h"
35
#include "virlog.h"
36
#include "virerror.h"
J
Jim Fehlig 已提交
37
#include "datatypes.h"
E
Eric Blake 已提交
38
#include "virfile.h"
J
Jim Fehlig 已提交
39
#include "virstring.h"
40
#include "viralloc.h"
41
#include "viruuid.h"
J
Jim Fehlig 已提交
42
#include "capabilities.h"
J
Jim Fehlig 已提交
43
#include "libxl_domain.h"
J
Jim Fehlig 已提交
44
#include "libxl_conf.h"
J
Jim Fehlig 已提交
45
#include "libxl_utils.h"
46
#include "virstoragefile.h"
J
Jim Fehlig 已提交
47 48 49 50


#define VIR_FROM_THIS VIR_FROM_LIBXL

51 52
VIR_LOG_INIT("libxl.libxl_conf");

J
Jim Fehlig 已提交
53 54 55 56 57
/* see xen-unstable.hg/xen/include/asm-x86/cpufeature.h */
#define LIBXL_X86_FEATURE_PAE_MASK 0x40


struct guest_arch {
58
    virArch arch;
J
Jim Fehlig 已提交
59 60 61 62 63 64 65
    int bits;
    int hvm;
    int pae;
    int nonpae;
    int ia64_be;
};

66
#define XEN_CAP_REGEX "(xen|hvm)-[[:digit:]]+\\.[[:digit:]]+-(aarch64|armv7l|x86_32|x86_64|ia64|powerpc64)(p|be)?"
J
Jim Fehlig 已提交
67 68


69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
static virClassPtr libxlDriverConfigClass;
static void libxlDriverConfigDispose(void *obj);

static int libxlConfigOnceInit(void)
{
    if (!(libxlDriverConfigClass = virClassNew(virClassForObject(),
                                               "libxlDriverConfig",
                                               sizeof(libxlDriverConfig),
                                               libxlDriverConfigDispose)))
        return -1;

    return 0;
}

VIR_ONCE_GLOBAL_INIT(libxlConfig)

static void
libxlDriverConfigDispose(void *obj)
{
    libxlDriverConfigPtr cfg = obj;

    virObjectUnref(cfg->caps);
    libxl_ctx_free(cfg->ctx);
    xtl_logger_destroy(cfg->logger);
    if (cfg->logger_file)
        VIR_FORCE_FCLOSE(cfg->logger_file);

    VIR_FREE(cfg->configDir);
    VIR_FREE(cfg->autostartDir);
    VIR_FREE(cfg->logDir);
    VIR_FREE(cfg->stateDir);
    VIR_FREE(cfg->libDir);
    VIR_FREE(cfg->saveDir);
102
    VIR_FREE(cfg->autoDumpDir);
103 104
}

J
Jim Fehlig 已提交
105 106
static int
libxlCapsInitHost(libxl_ctx *ctx, virCapsPtr caps)
J
Jim Fehlig 已提交
107
{
J
Jim Fehlig 已提交
108 109
    libxl_physinfo phy_info;
    int host_pae;
J
Jim Fehlig 已提交
110

J
Jim Fehlig 已提交
111 112 113 114
    if (libxl_get_physinfo(ctx, &phy_info) != 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Failed to get node physical info from libxenlight"));
        return -1;
J
Jim Fehlig 已提交
115 116
    }

J
Jim Fehlig 已提交
117 118 119 120 121 122 123 124 125
    /* hw_caps is an array of 32-bit words whose meaning is listed in
     * xen-unstable.hg/xen/include/asm-x86/cpufeature.h.  Each feature
     * is defined in the form X*32+Y, corresponding to the Y'th bit in
     * the X'th 32-bit word of hw_cap.
     */
    host_pae = phy_info.hw_cap[0] & LIBXL_X86_FEATURE_PAE_MASK;
    if (host_pae &&
        virCapabilitiesAddHostFeature(caps, "pae") < 0)
        return -1;
J
Jim Fehlig 已提交
126

J
Jim Fehlig 已提交
127
    return 0;
J
Jim Fehlig 已提交
128 129
}

130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
static int
libxlCapsInitNuma(libxl_ctx *ctx, virCapsPtr caps)
{
    libxl_numainfo *numa_info = NULL;
    libxl_cputopology *cpu_topo = NULL;
    int nr_nodes = 0, nr_cpus = 0;
    virCapsHostNUMACellCPUPtr *cpus = NULL;
    int *nr_cpus_node = NULL;
    size_t i;
    int ret = -1;

    /* Let's try to fetch all the topology information */
    numa_info = libxl_get_numainfo(ctx, &nr_nodes);
    if (numa_info == NULL || nr_nodes == 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("libxl_get_numainfo failed"));
        goto cleanup;
    } else {
        cpu_topo = libxl_get_cpu_topology(ctx, &nr_cpus);
        if (cpu_topo == NULL || nr_cpus == 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("libxl_get_cpu_topology failed"));
            goto cleanup;
        }
    }

    if (VIR_ALLOC_N(cpus, nr_nodes) < 0)
        goto cleanup;

    if (VIR_ALLOC_N(nr_cpus_node, nr_nodes) < 0)
        goto cleanup;

    /* For each node, prepare a list of CPUs belonging to that node */
    for (i = 0; i < nr_cpus; i++) {
        int node = cpu_topo[i].node;

        if (cpu_topo[i].core == LIBXL_CPUTOPOLOGY_INVALID_ENTRY)
            continue;

        nr_cpus_node[node]++;

        if (nr_cpus_node[node] == 1) {
            if (VIR_ALLOC(cpus[node]) < 0)
                goto cleanup;
        } else {
            if (VIR_REALLOC_N(cpus[node], nr_cpus_node[node]) < 0)
                goto cleanup;
        }

        /* Mapping between what libxl tells and what libvirt wants */
        cpus[node][nr_cpus_node[node]-1].id = i;
        cpus[node][nr_cpus_node[node]-1].socket_id = cpu_topo[i].socket;
        cpus[node][nr_cpus_node[node]-1].core_id = cpu_topo[i].core;
        /* Allocate the siblings maps. We will be filling them later */
        cpus[node][nr_cpus_node[node]-1].siblings = virBitmapNew(nr_cpus);
        if (!cpus[node][nr_cpus_node[node]-1].siblings) {
            virReportOOMError();
            goto cleanup;
        }
    }

    /* Let's now populate the siblings bitmaps */
    for (i = 0; i < nr_cpus; i++) {
        int node = cpu_topo[i].node;
        size_t j;

        if (cpu_topo[i].core == LIBXL_CPUTOPOLOGY_INVALID_ENTRY)
            continue;

        for (j = 0; j < nr_cpus_node[node]; j++) {
            if (cpus[node][j].socket_id == cpu_topo[i].socket &&
                cpus[node][j].core_id == cpu_topo[i].core)
                ignore_value(virBitmapSetBit(cpus[node][j].siblings, i));
        }
    }

    for (i = 0; i < nr_nodes; i++) {
        if (numa_info[i].size == LIBXL_NUMAINFO_INVALID_ENTRY)
            continue;

210
        if (virCapabilitiesAddHostNUMACell(caps, i,
211
                                           numa_info[i].size / 1024,
212 213
                                           nr_cpus_node[i], cpus[i],
                                           0, NULL) < 0) {
214 215 216 217 218 219 220 221 222 223 224 225 226
            virCapabilitiesClearHostNUMACellCPUTopology(cpus[i],
                                                        nr_cpus_node[i]);
            goto cleanup;
        }

        /* This is safe, as the CPU list is now stored in the NUMA cell */
        cpus[i] = NULL;
    }

    ret = 0;

 cleanup:
    if (ret != 0) {
227
        for (i = 0; cpus && i < nr_nodes; i++)
228 229 230 231 232 233 234 235 236 237 238 239
            VIR_FREE(cpus[i]);
        virCapabilitiesFreeNUMAInfo(caps);
    }

    VIR_FREE(cpus);
    VIR_FREE(nr_cpus_node);
    libxl_cputopology_list_free(cpu_topo, nr_cpus);
    libxl_numainfo_list_free(numa_info, nr_nodes);

    return ret;
}

J
Jim Fehlig 已提交
240 241
static int
libxlCapsInitGuests(libxl_ctx *ctx, virCapsPtr caps)
J
Jim Fehlig 已提交
242
{
J
Jim Fehlig 已提交
243
    const libxl_version_info *ver_info;
244 245
    int err;
    regex_t regex;
J
Jim Fehlig 已提交
246 247 248
    char *str, *token;
    regmatch_t subs[4];
    char *saveptr = NULL;
249
    size_t i;
J
Jim Fehlig 已提交
250
    virArch hostarch = caps->host.arch;
J
Jim Fehlig 已提交
251 252 253 254 255 256

    struct guest_arch guest_archs[32];
    int nr_guest_archs = 0;

    memset(guest_archs, 0, sizeof(guest_archs));

J
Jim Fehlig 已提交
257 258 259 260 261
    if ((ver_info = libxl_get_version_info(ctx)) == NULL) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Failed to get version info from libxenlight"));
        return -1;
    }
262 263 264 265 266 267 268 269 270 271

    err = regcomp(&regex, XEN_CAP_REGEX, REG_EXTENDED);
    if (err != 0) {
        char error[100];
        regerror(err, &regex, error, sizeof(error));
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to compile regex %s"), error);
        return -1;
    }

J
Jim Fehlig 已提交
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296
    /* Format of capabilities string is documented in the code in
     * xen-unstable.hg/xen/arch/.../setup.c.
     *
     * It is a space-separated list of supported guest architectures.
     *
     * For x86:
     *    TYP-VER-ARCH[p]
     *    ^   ^   ^    ^
     *    |   |   |    +-- PAE supported
     *    |   |   +------- x86_32 or x86_64
     *    |   +----------- the version of Xen, eg. "3.0"
     *    +--------------- "xen" or "hvm" for para or full virt respectively
     *
     * For IA64:
     *    TYP-VER-ARCH[be]
     *    ^   ^   ^    ^
     *    |   |   |    +-- Big-endian supported
     *    |   |   +------- always "ia64"
     *    |   +----------- the version of Xen, eg. "3.0"
     *    +--------------- "xen" or "hvm" for para or full virt respectively
     */

    /* Split capabilities string into tokens. strtok_r is OK here because
     * we "own" the buffer.  Parse out the features from each token.
     */
J
Jim Fehlig 已提交
297
    for (str = ver_info->capabilities, nr_guest_archs = 0;
J
Jim Fehlig 已提交
298 299 300
         nr_guest_archs < sizeof(guest_archs) / sizeof(guest_archs[0])
                 && (token = strtok_r(str, " ", &saveptr)) != NULL;
         str = NULL) {
301
        if (regexec(&regex, token, sizeof(subs) / sizeof(subs[0]),
J
Jim Fehlig 已提交
302 303
                    subs, 0) == 0) {
            int hvm = STRPREFIX(&token[subs[1].rm_so], "hvm");
304 305
            virArch arch;
            int pae = 0, nonpae = 0, ia64_be = 0;
J
Jim Fehlig 已提交
306 307

            if (STRPREFIX(&token[subs[2].rm_so], "x86_32")) {
308
                arch = VIR_ARCH_I686;
J
Jim Fehlig 已提交
309 310 311 312 313 314 315
                if (subs[3].rm_so != -1 &&
                    STRPREFIX(&token[subs[3].rm_so], "p"))
                    pae = 1;
                else
                    nonpae = 1;
            }
            else if (STRPREFIX(&token[subs[2].rm_so], "x86_64")) {
316
                arch = VIR_ARCH_X86_64;
J
Jim Fehlig 已提交
317 318
            }
            else if (STRPREFIX(&token[subs[2].rm_so], "ia64")) {
319
                arch = VIR_ARCH_ITANIUM;
J
Jim Fehlig 已提交
320 321 322 323 324
                if (subs[3].rm_so != -1 &&
                    STRPREFIX(&token[subs[3].rm_so], "be"))
                    ia64_be = 1;
            }
            else if (STRPREFIX(&token[subs[2].rm_so], "powerpc64")) {
325
                arch = VIR_ARCH_PPC64;
326 327 328 329
            } else if (STRPREFIX(&token[subs[2].rm_so], "armv7l")) {
                arch = VIR_ARCH_ARMV7L;
            } else if (STRPREFIX(&token[subs[2].rm_so], "aarch64")) {
                arch = VIR_ARCH_AARCH64;
J
Jim Fehlig 已提交
330 331 332 333 334
            } else {
                continue;
            }

            /* Search for existing matching (model,hvm) tuple */
335
            for (i = 0; i < nr_guest_archs; i++) {
336
                if ((guest_archs[i].arch == arch) &&
337
                    guest_archs[i].hvm == hvm)
J
Jim Fehlig 已提交
338 339 340 341 342 343 344 345 346 347
                    break;
            }

            /* Too many arch flavours - highly unlikely ! */
            if (i >= ARRAY_CARDINALITY(guest_archs))
                continue;
            /* Didn't find a match, so create a new one */
            if (i == nr_guest_archs)
                nr_guest_archs++;

348
            guest_archs[i].arch = arch;
J
Jim Fehlig 已提交
349 350 351 352 353 354 355 356 357 358 359 360 361 362
            guest_archs[i].hvm = hvm;

            /* Careful not to overwrite a previous positive
               setting with a negative one here - some archs
               can do both pae & non-pae, but Xen reports
               separately capabilities so we're merging archs */
            if (pae)
                guest_archs[i].pae = pae;
            if (nonpae)
                guest_archs[i].nonpae = nonpae;
            if (ia64_be)
                guest_archs[i].ia64_be = ia64_be;
        }
    }
363
    regfree(&regex);
J
Jim Fehlig 已提交
364

J
Jim Fehlig 已提交
365 366 367 368
    for (i = 0; i < nr_guest_archs; ++i) {
        virCapsGuestPtr guest;
        char const *const xen_machines[] = {guest_archs[i].hvm ? "xenfv" : "xenpv"};
        virCapsGuestMachinePtr *machines;
J
Jim Fehlig 已提交
369

J
Jim Fehlig 已提交
370 371
        if ((machines = virCapabilitiesAllocMachines(xen_machines, 1)) == NULL)
            return -1;
J
Jim Fehlig 已提交
372

J
Jim Fehlig 已提交
373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438
        if ((guest = virCapabilitiesAddGuest(caps,
                                             guest_archs[i].hvm ? "hvm" : "xen",
                                             guest_archs[i].arch,
                                             ((hostarch == VIR_ARCH_X86_64) ?
                                              "/usr/lib64/xen/bin/qemu-dm" :
                                              "/usr/lib/xen/bin/qemu-dm"),
                                             (guest_archs[i].hvm ?
                                              "/usr/lib/xen/boot/hvmloader" :
                                              NULL),
                                             1,
                                             machines)) == NULL) {
            virCapabilitiesFreeMachines(machines, 1);
            return -1;
        }
        machines = NULL;

        if (virCapabilitiesAddGuestDomain(guest,
                                          "xen",
                                          NULL,
                                          NULL,
                                          0,
                                          NULL) == NULL)
            return -1;

        if (guest_archs[i].pae &&
            virCapabilitiesAddGuestFeature(guest,
                                           "pae",
                                           1,
                                           0) == NULL)
            return -1;

        if (guest_archs[i].nonpae &&
            virCapabilitiesAddGuestFeature(guest,
                                           "nonpae",
                                           1,
                                           0) == NULL)
            return -1;

        if (guest_archs[i].ia64_be &&
            virCapabilitiesAddGuestFeature(guest,
                                           "ia64_be",
                                           1,
                                           0) == NULL)
            return -1;

        if (guest_archs[i].hvm) {
            if (virCapabilitiesAddGuestFeature(guest,
                                               "acpi",
                                               1,
                                               1) == NULL)
                return -1;

            if (virCapabilitiesAddGuestFeature(guest, "apic",
                                               1,
                                               0) == NULL)
                return -1;

            if (virCapabilitiesAddGuestFeature(guest,
                                               "hap",
                                               0,
                                               1) == NULL)
                return -1;
        }
    }

    return 0;
J
Jim Fehlig 已提交
439 440 441
}

static int
442
libxlMakeDomCreateInfo(libxl_ctx *ctx,
J
Jim Fehlig 已提交
443 444
                       virDomainDefPtr def,
                       libxl_domain_create_info *c_info)
J
Jim Fehlig 已提交
445 446 447
{
    char uuidstr[VIR_UUID_STRING_BUFLEN];

J
Jim Fehlig 已提交
448 449 450 451 452 453
    libxl_domain_create_info_init(c_info);

    if (STREQ(def->os.type, "hvm"))
        c_info->type = LIBXL_DOMAIN_TYPE_HVM;
    else
        c_info->type = LIBXL_DOMAIN_TYPE_PV;
J
Jim Fehlig 已提交
454

455
    if (VIR_STRDUP(c_info->name, def->name) < 0)
J
Jim Fehlig 已提交
456 457
        goto error;

J
Jim Fehlig 已提交
458 459
    if (def->nseclabels &&
        def->seclabels[0]->type == VIR_DOMAIN_SECLABEL_STATIC) {
460
        if (libxl_flask_context_to_sid(ctx,
J
Jim Fehlig 已提交
461 462 463 464 465 466 467 468 469
                                       def->seclabels[0]->label,
                                       strlen(def->seclabels[0]->label),
                                       &c_info->ssidref)) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("libxenlight failed to resolve security label '%s'"),
                           def->seclabels[0]->label);
        }
    }

J
Jim Fehlig 已提交
470
    virUUIDFormat(def->uuid, uuidstr);
471
    if (libxl_uuid_from_string(&c_info->uuid, uuidstr)) {
472 473
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("libxenlight failed to parse UUID '%s'"), uuidstr);
J
Jim Fehlig 已提交
474 475 476 477 478
        goto error;
    }

    return 0;

479
 error:
J
Jim Fehlig 已提交
480
    libxl_domain_create_info_dispose(c_info);
J
Jim Fehlig 已提交
481 482 483
    return -1;
}

B
Bamvor Jian Zhang 已提交
484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569
static int
libxlMakeChrdevStr(virDomainChrDefPtr def, char **buf)
{
    virDomainChrSourceDef srcdef = def->source;
    const char *type = virDomainChrTypeToString(srcdef.type);

    if (!type) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       "%s", _("unknown chrdev type"));
        return -1;
    }

    switch (srcdef.type) {
    case VIR_DOMAIN_CHR_TYPE_NULL:
    case VIR_DOMAIN_CHR_TYPE_STDIO:
    case VIR_DOMAIN_CHR_TYPE_VC:
    case VIR_DOMAIN_CHR_TYPE_PTY:
        if (VIR_STRDUP(*buf, type) < 0)
            return -1;
        break;

    case VIR_DOMAIN_CHR_TYPE_FILE:
    case VIR_DOMAIN_CHR_TYPE_PIPE:
        if (virAsprintf(buf, "%s:%s", type, srcdef.data.file.path) < 0)
            return -1;
        break;

    case VIR_DOMAIN_CHR_TYPE_DEV:
        if (VIR_STRDUP(*buf, srcdef.data.file.path) < 0)
            return -1;
        break;

    case VIR_DOMAIN_CHR_TYPE_UDP: {
        const char *connectHost = srcdef.data.udp.connectHost;
        const char *bindHost = srcdef.data.udp.bindHost;
        const char *bindService  = srcdef.data.udp.bindService;

        if (connectHost == NULL)
            connectHost = "";
        if (bindHost == NULL)
            bindHost = "";
        if (bindService == NULL)
            bindService = "0";

        if (virAsprintf(buf, "udp:%s:%s@%s:%s",
                        connectHost,
                        srcdef.data.udp.connectService,
                        bindHost,
                        bindService) < 0)
            return -1;
        break;
    }

    case VIR_DOMAIN_CHR_TYPE_TCP: {
        const char *prefix;

        if (srcdef.data.tcp.protocol == VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET)
            prefix = "telnet";
        else
            prefix = "tcp";

        if (virAsprintf(buf, "%s:%s:%s%s",
                        prefix,
                        srcdef.data.tcp.host,
                        srcdef.data.tcp.service,
                        srcdef.data.tcp.listen ? ",server,nowait" : "") < 0)
            return -1;
        break;
    }

    case VIR_DOMAIN_CHR_TYPE_UNIX:
        if (virAsprintf(buf, "unix:%s%s",
                        srcdef.data.nix.path,
                        srcdef.data.nix.listen ? ",server,nowait" : "") < 0)
            return -1;
        break;

    default:
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("unsupported chardev '%s'"), type);
        return -1;
    }

    return 0;
}

J
Jim Fehlig 已提交
570
static int
571 572 573
libxlMakeDomBuildInfo(virDomainDefPtr def,
                      libxl_ctx *ctx,
                      libxl_domain_config *d_config)
J
Jim Fehlig 已提交
574 575 576
{
    libxl_domain_build_info *b_info = &d_config->b_info;
    int hvm = STREQ(def->os.type, "hvm");
577
    size_t i;
J
Jim Fehlig 已提交
578

J
Jim Fehlig 已提交
579
    libxl_domain_build_info_init(b_info);
J
Jim Fehlig 已提交
580

J
Jim Fehlig 已提交
581 582
    if (hvm)
        libxl_domain_build_info_init_type(b_info, LIBXL_DOMAIN_TYPE_HVM);
583
    else
J
Jim Fehlig 已提交
584
        libxl_domain_build_info_init_type(b_info, LIBXL_DOMAIN_TYPE_PV);
585

J
Jim Fehlig 已提交
586
    b_info->max_vcpus = def->maxvcpus;
587
    if (libxl_cpu_bitmap_alloc(ctx, &b_info->avail_vcpus, def->maxvcpus))
588 589 590 591 592
        goto error;
    libxl_bitmap_set_none(&b_info->avail_vcpus);
    for (i = 0; i < def->vcpus; i++)
        libxl_bitmap_set((&b_info->avail_vcpus), i);

J
Jim Fehlig 已提交
593 594 595 596 597 598 599 600 601 602 603 604 605
    if (def->clock.ntimers > 0 &&
        def->clock.timers[0]->name == VIR_DOMAIN_TIMER_NAME_TSC) {
        switch (def->clock.timers[0]->mode) {
            case VIR_DOMAIN_TIMER_MODE_NATIVE:
                b_info->tsc_mode = 2;
                break;
            case VIR_DOMAIN_TIMER_MODE_PARAVIRT:
                b_info->tsc_mode = 3;
                break;
            default:
                b_info->tsc_mode = 1;
        }
    }
J
Jim Fehlig 已提交
606
    b_info->sched_params.weight = 1000;
J
Jim Fehlig 已提交
607 608 609
    b_info->max_memkb = def->mem.max_balloon;
    b_info->target_memkb = def->mem.cur_balloon;
    if (hvm) {
610 611
        char bootorder[VIR_DOMAIN_BOOT_LAST + 1];

J
Jim Fehlig 已提交
612
        libxl_defbool_set(&b_info->u.hvm.pae,
613 614
                          def->features[VIR_DOMAIN_FEATURE_PAE] ==
                          VIR_DOMAIN_FEATURE_STATE_ON);
J
Jim Fehlig 已提交
615
        libxl_defbool_set(&b_info->u.hvm.apic,
616 617
                          def->features[VIR_DOMAIN_FEATURE_APIC] ==
                          VIR_DOMAIN_FEATURE_STATE_ON);
J
Jim Fehlig 已提交
618
        libxl_defbool_set(&b_info->u.hvm.acpi,
619 620
                          def->features[VIR_DOMAIN_FEATURE_ACPI] ==
                          VIR_DOMAIN_FEATURE_STATE_ON);
P
Paolo Bonzini 已提交
621 622 623
        for (i = 0; i < def->clock.ntimers; i++) {
            if (def->clock.timers[i]->name == VIR_DOMAIN_TIMER_NAME_HPET &&
                def->clock.timers[i]->present == 1) {
J
Jim Fehlig 已提交
624
                libxl_defbool_set(&b_info->u.hvm.hpet, 1);
P
Paolo Bonzini 已提交
625 626
            }
        }
627
        for (i = 0; i < def->os.nBootDevs; i++) {
628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650
            switch (def->os.bootDevs[i]) {
                case VIR_DOMAIN_BOOT_FLOPPY:
                    bootorder[i] = 'a';
                    break;
                default:
                case VIR_DOMAIN_BOOT_DISK:
                    bootorder[i] = 'c';
                    break;
                case VIR_DOMAIN_BOOT_CDROM:
                    bootorder[i] = 'd';
                    break;
                case VIR_DOMAIN_BOOT_NET:
                    bootorder[i] = 'n';
                    break;
            }
        }
        if (def->os.nBootDevs == 0) {
            bootorder[0] = 'c';
            bootorder[1] = '\0';
        }
        else {
            bootorder[def->os.nBootDevs] = '\0';
        }
651
        if (VIR_STRDUP(b_info->u.hvm.boot, bootorder) < 0)
652
            goto error;
P
Paolo Bonzini 已提交
653

B
Bamvor Jian Zhang 已提交
654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671
        if (def->nserials) {
            if (def->nserials > 1) {
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               "%s",
                               _("Only one serial device is supported by libxl"));
                goto error;
            }
            if (libxlMakeChrdevStr(def->serials[0], &b_info->u.hvm.serial) < 0)
                goto error;
        }

        if (def->nparallels) {
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           "%s",
                           _("Parallel devices are not supported by libxl"));
            goto error;
        }

J
Jim Fehlig 已提交
672 673 674 675 676 677 678
        /*
         * The following comment and calculation were taken directly from
         * libxenlight's internal function libxl_get_required_shadow_memory():
         *
         * 256 pages (1MB) per vcpu, plus 1 page per MiB of RAM for the P2M map,
         * plus 1 page per MiB of RAM to shadow the resident processes.
         */
J
Jim Fehlig 已提交
679
        b_info->shadow_memkb = 4 * (256 * libxl_bitmap_count_set(&b_info->avail_vcpus) +
J
Jim Fehlig 已提交
680 681
                                    2 * (b_info->max_memkb / 1024));
    } else {
682 683 684 685 686 687 688 689 690 691 692
        /*
         * For compatibility with the legacy xen toolstack, default to pygrub
         * if bootloader is not specified AND direct kernel boot is not specified.
         */
        if (def->os.bootloader) {
            if (VIR_STRDUP(b_info->u.pv.bootloader, def->os.bootloader) < 0)
                goto error;
        } else if (def->os.kernel == NULL) {
            if (VIR_STRDUP(b_info->u.pv.bootloader, LIBXL_BOOTLOADER_PATH) < 0)
                goto error;
        }
J
Jim Fehlig 已提交
693
        if (def->os.bootloaderArgs) {
J
Jim Fehlig 已提交
694 695
            if (!(b_info->u.pv.bootloader_args =
                  virStringSplit(def->os.bootloaderArgs, " \t\n", 0)))
J
Jim Fehlig 已提交
696 697
                goto error;
        }
698 699
        if (VIR_STRDUP(b_info->u.pv.cmdline, def->os.cmdline) < 0)
            goto error;
J
Jim Fehlig 已提交
700
        if (def->os.kernel) {
701
            /* libxl_init_build_info() sets VIR_STRDUP(kernel.path, "hvmloader") */
J
Jim Fehlig 已提交
702
            VIR_FREE(b_info->u.pv.kernel);
703
            if (VIR_STRDUP(b_info->u.pv.kernel, def->os.kernel) < 0)
J
Jim Fehlig 已提交
704 705
                goto error;
        }
706 707
        if (VIR_STRDUP(b_info->u.pv.ramdisk, def->os.initrd) < 0)
            goto error;
J
Jim Fehlig 已提交
708 709 710 711
    }

    return 0;

712
 error:
J
Jim Fehlig 已提交
713
    libxl_domain_build_info_dispose(b_info);
J
Jim Fehlig 已提交
714 715 716
    return -1;
}

717
int
J
Jim Fehlig 已提交
718
libxlMakeDisk(virDomainDiskDefPtr l_disk, libxl_device_disk *x_disk)
719
{
720 721 722
    const char *driver;
    int format;

723 724
    libxl_device_disk_init(x_disk);

725
    if (VIR_STRDUP(x_disk->pdev_path, virDomainDiskGetSource(l_disk)) < 0)
726 727
        return -1;

728
    if (VIR_STRDUP(x_disk->vdev, l_disk->dst) < 0)
729 730
        return -1;

731 732 733 734 735
    driver = virDomainDiskGetDriver(l_disk);
    format = virDomainDiskGetFormat(l_disk);
    if (driver) {
        if (STREQ(driver, "tap") || STREQ(driver, "tap2")) {
            switch (format) {
736
            case VIR_STORAGE_FILE_QCOW:
J
Jim Fehlig 已提交
737 738
                x_disk->format = LIBXL_DISK_FORMAT_QCOW;
                x_disk->backend = LIBXL_DISK_BACKEND_QDISK;
739 740
                break;
            case VIR_STORAGE_FILE_QCOW2:
J
Jim Fehlig 已提交
741 742
                x_disk->format = LIBXL_DISK_FORMAT_QCOW2;
                x_disk->backend = LIBXL_DISK_BACKEND_QDISK;
743 744
                break;
            case VIR_STORAGE_FILE_VHD:
J
Jim Fehlig 已提交
745 746
                x_disk->format = LIBXL_DISK_FORMAT_VHD;
                x_disk->backend = LIBXL_DISK_BACKEND_TAP;
747 748
                break;
            case VIR_STORAGE_FILE_NONE:
749
                /* No subtype specified, default to raw/tap */
750
            case VIR_STORAGE_FILE_RAW:
J
Jim Fehlig 已提交
751 752
                x_disk->format = LIBXL_DISK_FORMAT_RAW;
                x_disk->backend = LIBXL_DISK_BACKEND_TAP;
753 754 755
                break;
            default:
                virReportError(VIR_ERR_INTERNAL_ERROR,
756 757
                               _("libxenlight does not support disk format %s "
                                 "with disk driver %s"),
758 759
                               virStorageFileFormatTypeToString(format),
                               driver);
760
                return -1;
761
            }
762
        } else if (STREQ(driver, "qemu")) {
J
Jim Fehlig 已提交
763
            x_disk->backend = LIBXL_DISK_BACKEND_QDISK;
764
            switch (format) {
J
Jim Fehlig 已提交
765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782
            case VIR_STORAGE_FILE_QCOW:
                x_disk->format = LIBXL_DISK_FORMAT_QCOW;
                break;
            case VIR_STORAGE_FILE_QCOW2:
                x_disk->format = LIBXL_DISK_FORMAT_QCOW2;
                break;
            case VIR_STORAGE_FILE_VHD:
                x_disk->format = LIBXL_DISK_FORMAT_VHD;
                break;
            case VIR_STORAGE_FILE_NONE:
                /* No subtype specified, default to raw */
            case VIR_STORAGE_FILE_RAW:
                x_disk->format = LIBXL_DISK_FORMAT_RAW;
                break;
            default:
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("libxenlight does not support disk format %s "
                                 "with disk driver %s"),
783 784
                               virStorageFileFormatTypeToString(format),
                               driver);
J
Jim Fehlig 已提交
785 786
                return -1;
            }
787 788 789
        } else if (STREQ(driver, "file")) {
            if (format != VIR_STORAGE_FILE_NONE &&
                format != VIR_STORAGE_FILE_RAW) {
790 791 792
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("libxenlight does not support disk format %s "
                                 "with disk driver %s"),
793 794
                               virStorageFileFormatTypeToString(format),
                               driver);
795 796
                return -1;
            }
J
Jim Fehlig 已提交
797 798
            x_disk->format = LIBXL_DISK_FORMAT_RAW;
            x_disk->backend = LIBXL_DISK_BACKEND_TAP;
799 800 801
        } else if (STREQ(driver, "phy")) {
            if (format != VIR_STORAGE_FILE_NONE &&
                format != VIR_STORAGE_FILE_RAW) {
802 803 804
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("libxenlight does not support disk format %s "
                                 "with disk driver %s"),
805 806
                               virStorageFileFormatTypeToString(format),
                               driver);
807 808
                return -1;
            }
J
Jim Fehlig 已提交
809 810
            x_disk->format = LIBXL_DISK_FORMAT_RAW;
            x_disk->backend = LIBXL_DISK_BACKEND_PHY;
811
        } else {
812 813
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("libxenlight does not support disk driver %s"),
814
                           driver);
815 816 817
            return -1;
        }
    } else {
J
Jim Fehlig 已提交
818 819 820 821 822
        /*
         * If driverName is not specified, default to raw as per
         * xl-disk-configuration.txt in the xen documentation and let
         * libxl pick a suitable backend.
         */
J
Jim Fehlig 已提交
823
        x_disk->format = LIBXL_DISK_FORMAT_RAW;
J
Jim Fehlig 已提交
824
        x_disk->backend = LIBXL_DISK_BACKEND_UNKNOWN;
825 826
    }

J
Jim Fehlig 已提交
827 828
    /* XXX is this right? */
    x_disk->removable = 1;
829 830
    x_disk->readwrite = !l_disk->readonly;
    x_disk->is_cdrom = l_disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM ? 1 : 0;
831 832 833
    /* An empty CDROM must have the empty format, otherwise libxl fails. */
    if (x_disk->is_cdrom && !x_disk->pdev_path)
        x_disk->format = LIBXL_DISK_FORMAT_EMPTY;
834
    if (l_disk->transient) {
835 836
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("libxenlight does not support transient disks"));
837 838
        return -1;
    }
839 840 841 842

    return 0;
}

J
Jim Fehlig 已提交
843 844 845 846 847 848
static int
libxlMakeDiskList(virDomainDefPtr def, libxl_domain_config *d_config)
{
    virDomainDiskDefPtr *l_disks = def->disks;
    int ndisks = def->ndisks;
    libxl_device_disk *x_disks;
849
    size_t i;
J
Jim Fehlig 已提交
850

851
    if (VIR_ALLOC_N(x_disks, ndisks) < 0)
J
Jim Fehlig 已提交
852 853 854
        return -1;

    for (i = 0; i < ndisks; i++) {
J
Jim Fehlig 已提交
855
        if (libxlMakeDisk(l_disks[i], &x_disks[i]) < 0)
J
Jim Fehlig 已提交
856 857 858 859 860 861 862 863
            goto error;
    }

    d_config->disks = x_disks;
    d_config->num_disks = ndisks;

    return 0;

864
 error:
J
Jim Fehlig 已提交
865
    for (i = 0; i < ndisks; i++)
J
Jim Fehlig 已提交
866
        libxl_device_disk_dispose(&x_disks[i]);
J
Jim Fehlig 已提交
867 868 869 870
    VIR_FREE(x_disks);
    return -1;
}

871
int
872 873 874
libxlMakeNic(virDomainDefPtr def,
             virDomainNetDefPtr l_nic,
             libxl_device_nic *x_nic)
875
{
876 877
    bool ioemu_nic = STREQ(def->os.type, "hvm");

J
Jim Fehlig 已提交
878 879 880 881
    /* TODO: Where is mtu stored?
     *
     * x_nics[i].mtu = 1492;
     */
882

883 884
    libxl_device_nic_init(x_nic);

885
    virMacAddrGetRaw(&l_nic->mac, x_nic->mac);
886

887
    if (ioemu_nic)
J
Jim Fehlig 已提交
888
        x_nic->nictype = LIBXL_NIC_TYPE_VIF_IOEMU;
889
    else
J
Jim Fehlig 已提交
890
        x_nic->nictype = LIBXL_NIC_TYPE_VIF;
891 892 893 894 895 896

    if (l_nic->model) {
        if (VIR_STRDUP(x_nic->model, l_nic->model) < 0)
            return -1;
        if (STREQ(l_nic->model, "netfront"))
            x_nic->nictype = LIBXL_NIC_TYPE_VIF;
897 898
    }

899
    if (VIR_STRDUP(x_nic->ifname, l_nic->ifname) < 0)
900 901
        return -1;

902 903 904 905 906 907 908 909 910 911 912 913 914
    switch (l_nic->type) {
        case VIR_DOMAIN_NET_TYPE_BRIDGE:
            if (VIR_STRDUP(x_nic->bridge, l_nic->data.bridge.brname) < 0)
                return -1;
            /* fallthrough */
        case VIR_DOMAIN_NET_TYPE_ETHERNET:
            if (VIR_STRDUP(x_nic->script, l_nic->script) < 0)
                return -1;
            break;
        default:
            virReportError(VIR_ERR_INTERNAL_ERROR,
                    _("libxenlight does not support network device type %s"),
                    virDomainNetTypeToString(l_nic->type));
915
            return -1;
916 917 918 919 920
    }

    return 0;
}

J
Jim Fehlig 已提交
921 922 923 924
static int
libxlMakeNicList(virDomainDefPtr def,  libxl_domain_config *d_config)
{
    virDomainNetDefPtr *l_nics = def->nets;
925
    size_t nnics = def->nnets;
J
Jim Fehlig 已提交
926
    libxl_device_nic *x_nics;
927
    size_t i, nvnics = 0;
J
Jim Fehlig 已提交
928

929
    if (VIR_ALLOC_N(x_nics, nnics) < 0)
J
Jim Fehlig 已提交
930 931 932
        return -1;

    for (i = 0; i < nnics; i++) {
933 934 935 936
        if (l_nics[i]->type == VIR_DOMAIN_NET_TYPE_HOSTDEV)
            continue;

        if (libxlMakeNic(def, l_nics[i], &x_nics[nvnics]))
J
Jim Fehlig 已提交
937
            goto error;
938 939 940 941 942
        /*
         * The devid (at least right now) will not get initialized by
         * libxl in the setup case but is required for starting the
         * device-model.
         */
943 944 945 946
        if (x_nics[nvnics].devid < 0)
            x_nics[nvnics].devid = nvnics;

        nvnics++;
J
Jim Fehlig 已提交
947 948
    }

949
    VIR_SHRINK_N(x_nics, nnics, nnics - nvnics);
J
Jim Fehlig 已提交
950 951
    d_config->nics = x_nics;
    d_config->num_nics = nnics;
J
Jim Fehlig 已提交
952 953 954

    return 0;

955
 error:
J
Jim Fehlig 已提交
956
    for (i = 0; i < nnics; i++)
J
Jim Fehlig 已提交
957
        libxl_device_nic_dispose(&x_nics[i]);
J
Jim Fehlig 已提交
958 959 960 961
    VIR_FREE(x_nics);
    return -1;
}

962
int
963
libxlMakeVfb(virPortAllocatorPtr graphicsports,
J
Jim Fehlig 已提交
964 965
             virDomainGraphicsDefPtr l_vfb,
             libxl_device_vfb *x_vfb)
966
{
967
    unsigned short port;
968
    const char *listenAddr;
969

970 971
    libxl_device_vfb_init(x_vfb);

972 973
    switch (l_vfb->type) {
        case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
J
Jim Fehlig 已提交
974
            libxl_defbool_set(&x_vfb->sdl.enable, 1);
975
            if (VIR_STRDUP(x_vfb->sdl.display, l_vfb->data.sdl.display) < 0)
976
                return -1;
977
            if (VIR_STRDUP(x_vfb->sdl.xauthority, l_vfb->data.sdl.xauth) < 0)
978 979 980
                return -1;
            break;
        case  VIR_DOMAIN_GRAPHICS_TYPE_VNC:
J
Jim Fehlig 已提交
981
            libxl_defbool_set(&x_vfb->vnc.enable, 1);
982
            /* driver handles selection of free port */
J
Jim Fehlig 已提交
983
            libxl_defbool_set(&x_vfb->vnc.findunused, 0);
984
            if (l_vfb->data.vnc.autoport) {
985

986
                if (virPortAllocatorAcquire(graphicsports, &port) < 0)
987
                    return -1;
988 989
                l_vfb->data.vnc.port = port;
            }
J
Jim Fehlig 已提交
990
            x_vfb->vnc.display = l_vfb->data.vnc.port - LIBXL_VNC_PORT_MIN;
991

992 993
            listenAddr = virDomainGraphicsListenGetAddress(l_vfb, 0);
            if (listenAddr) {
994
                /* libxl_device_vfb_init() does VIR_STRDUP("127.0.0.1") */
J
Jim Fehlig 已提交
995
                VIR_FREE(x_vfb->vnc.listen);
996
                if (VIR_STRDUP(x_vfb->vnc.listen, listenAddr) < 0)
997 998
                    return -1;
            }
999
            if (VIR_STRDUP(x_vfb->keymap, l_vfb->data.vnc.keymap) < 0)
1000 1001 1002
                return -1;
            break;
    }
J
Jim Fehlig 已提交
1003

1004 1005 1006
    return 0;
}

J
Jim Fehlig 已提交
1007
static int
1008
libxlMakeVfbList(virPortAllocatorPtr graphicsports,
J
Jim Fehlig 已提交
1009 1010
                 virDomainDefPtr def,
                 libxl_domain_config *d_config)
J
Jim Fehlig 已提交
1011 1012 1013 1014 1015
{
    virDomainGraphicsDefPtr *l_vfbs = def->graphics;
    int nvfbs = def->ngraphics;
    libxl_device_vfb *x_vfbs;
    libxl_device_vkb *x_vkbs;
1016
    size_t i;
J
Jim Fehlig 已提交
1017 1018 1019 1020

    if (nvfbs == 0)
        return 0;

1021
    if (VIR_ALLOC_N(x_vfbs, nvfbs) < 0)
J
Jim Fehlig 已提交
1022 1023 1024 1025 1026 1027 1028
        return -1;
    if (VIR_ALLOC_N(x_vkbs, nvfbs) < 0) {
        VIR_FREE(x_vfbs);
        return -1;
    }

    for (i = 0; i < nvfbs; i++) {
J
Jim Fehlig 已提交
1029
        libxl_device_vkb_init(&x_vkbs[i]);
J
Jim Fehlig 已提交
1030

1031
        if (libxlMakeVfb(graphicsports, l_vfbs[i], &x_vfbs[i]) < 0)
1032
            goto error;
J
Jim Fehlig 已提交
1033 1034 1035 1036 1037 1038
    }

    d_config->vfbs = x_vfbs;
    d_config->vkbs = x_vkbs;
    d_config->num_vfbs = d_config->num_vkbs = nvfbs;

1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052
    /*
     * VNC or SDL info must also be set in libxl_domain_build_info
     * for HVM domains.  Use the first vfb device.
     */
    if (STREQ(def->os.type, "hvm")) {
        libxl_domain_build_info *b_info = &d_config->b_info;
        libxl_device_vfb vfb = d_config->vfbs[0];

        if (libxl_defbool_val(vfb.vnc.enable))
            memcpy(&b_info->u.hvm.vnc, &vfb.vnc, sizeof(libxl_vnc_info));
        else if (libxl_defbool_val(vfb.sdl.enable))
            memcpy(&b_info->u.hvm.sdl, &vfb.sdl, sizeof(libxl_sdl_info));
    }

J
Jim Fehlig 已提交
1053 1054
    return 0;

1055
 error:
J
Jim Fehlig 已提交
1056
    for (i = 0; i < nvfbs; i++) {
J
Jim Fehlig 已提交
1057 1058
        libxl_device_vfb_dispose(&x_vfbs[i]);
        libxl_device_vkb_dispose(&x_vkbs[i]);
J
Jim Fehlig 已提交
1059 1060 1061 1062 1063 1064
    }
    VIR_FREE(x_vfbs);
    VIR_FREE(x_vkbs);
    return -1;
}

J
Jim Fehlig 已提交
1065 1066
static int
libxlGetAutoballoonConf(libxlDriverConfigPtr cfg, bool *autoballoon)
1067 1068
{
    regex_t regex;
J
Jim Fehlig 已提交
1069 1070 1071 1072 1073 1074 1075 1076 1077 1078
    int res;

    if ((res = regcomp(&regex,
                      "(^| )dom0_mem=((|min:|max:)[0-9]+[bBkKmMgG]?,?)+($| )",
                       REG_NOSUB | REG_EXTENDED)) != 0) {
        char error[100];
        regerror(res, &regex, error, sizeof(error));
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to compile regex %s"),
                       error);
1079

J
Jim Fehlig 已提交
1080 1081
        return -1;
    }
1082

J
Jim Fehlig 已提交
1083
    res = regexec(&regex, cfg->verInfo->commandline, 0, NULL, 0);
1084
    regfree(&regex);
J
Jim Fehlig 已提交
1085 1086
    *autoballoon = res == REG_NOMATCH;
    return 0;
1087 1088
}

1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114
libxlDriverConfigPtr
libxlDriverConfigNew(void)
{
    libxlDriverConfigPtr cfg;
    char *log_file = NULL;
    char ebuf[1024];
    unsigned int free_mem;

    if (libxlConfigInitialize() < 0)
        return NULL;

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

    if (VIR_STRDUP(cfg->configDir, LIBXL_CONFIG_DIR) < 0)
        goto error;
    if (VIR_STRDUP(cfg->autostartDir, LIBXL_AUTOSTART_DIR) < 0)
        goto error;
    if (VIR_STRDUP(cfg->logDir, LIBXL_LOG_DIR) < 0)
        goto error;
    if (VIR_STRDUP(cfg->stateDir, LIBXL_STATE_DIR) < 0)
        goto error;
    if (VIR_STRDUP(cfg->libDir, LIBXL_LIB_DIR) < 0)
        goto error;
    if (VIR_STRDUP(cfg->saveDir, LIBXL_SAVE_DIR) < 0)
        goto error;
1115 1116
    if (VIR_STRDUP(cfg->autoDumpDir, LIBXL_DUMP_DIR) < 0)
        goto error;
1117 1118 1119 1120

    if (virAsprintf(&log_file, "%s/libxl-driver.log", cfg->logDir) < 0)
        goto error;

1121 1122 1123 1124 1125 1126 1127 1128
    if (virFileMakePath(cfg->logDir) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to create log dir '%s': %s"),
                       cfg->logDir,
                       virStrerror(errno, ebuf, sizeof(ebuf)));
        goto error;
    }

1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165
    if ((cfg->logger_file = fopen(log_file, "a")) == NULL)  {
        VIR_ERROR(_("Failed to create log file '%s': %s"),
                  log_file, virStrerror(errno, ebuf, sizeof(ebuf)));
        goto error;
    }
    VIR_FREE(log_file);

    cfg->logger =
        (xentoollog_logger *)xtl_createlogger_stdiostream(cfg->logger_file,
                                                          XTL_DEBUG, 0);
    if (!cfg->logger) {
        VIR_ERROR(_("cannot create logger for libxenlight, disabling driver"));
        goto error;
    }

    if (libxl_ctx_alloc(&cfg->ctx, LIBXL_VERSION, 0, cfg->logger)) {
        VIR_ERROR(_("cannot initialize libxenlight context, probably not "
                    "running in a Xen Dom0, disabling driver"));
        goto error;
    }

    if ((cfg->verInfo = libxl_get_version_info(cfg->ctx)) == NULL) {
        VIR_ERROR(_("cannot version information from libxenlight, "
                    "disabling driver"));
        goto error;
    }
    cfg->version = (cfg->verInfo->xen_version_major * 1000000) +
        (cfg->verInfo->xen_version_minor * 1000);

    /* This will fill xenstore info about free and dom0 memory if missing,
     * should be called before starting first domain */
    if (libxl_get_free_memory(cfg->ctx, &free_mem)) {
        VIR_ERROR(_("Unable to configure libxl's memory management parameters"));
        goto error;
    }

    /* setup autoballoon */
J
Jim Fehlig 已提交
1166 1167
    if (libxlGetAutoballoonConf(cfg, &cfg->autoballoon) < 0)
        goto error;
1168 1169 1170

    return cfg;

1171
 error:
1172 1173 1174 1175 1176 1177 1178 1179
    VIR_FREE(log_file);
    virObjectUnref(cfg);
    return NULL;
}

libxlDriverConfigPtr
libxlDriverConfigGet(libxlDriverPrivatePtr driver)
{
1180 1181 1182 1183 1184 1185
    libxlDriverConfigPtr cfg;

    libxlDriverLock(driver);
    cfg = virObjectRef(driver->config);
    libxlDriverUnlock(driver);
    return cfg;
1186 1187
}

1188
int
1189
libxlMakePCI(virDomainHostdevDefPtr hostdev, libxl_device_pci *pcidev)
1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204
{
    if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
        return -1;
    if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
        return -1;

    pcidev->domain = hostdev->source.subsys.u.pci.addr.domain;
    pcidev->bus = hostdev->source.subsys.u.pci.addr.bus;
    pcidev->dev = hostdev->source.subsys.u.pci.addr.slot;
    pcidev->func = hostdev->source.subsys.u.pci.addr.function;

    return 0;
}

static int
1205
libxlMakePCIList(virDomainDefPtr def, libxl_domain_config *d_config)
1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226
{
    virDomainHostdevDefPtr *l_hostdevs = def->hostdevs;
    size_t nhostdevs = def->nhostdevs;
    size_t npcidevs = 0;
    libxl_device_pci *x_pcidevs;
    size_t i, j;

    if (nhostdevs == 0)
        return 0;

    if (VIR_ALLOC_N(x_pcidevs, nhostdevs) < 0)
        return -1;

    for (i = 0, j = 0; i < nhostdevs; i++) {
        if (l_hostdevs[i]->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS)
            continue;
        if (l_hostdevs[i]->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
            continue;

        libxl_device_pci_init(&x_pcidevs[j]);

1227
        if (libxlMakePCI(l_hostdevs[i], &x_pcidevs[j]) < 0)
1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239
            goto error;

        npcidevs++;
        j++;
    }

    VIR_SHRINK_N(x_pcidevs, nhostdevs, nhostdevs - npcidevs);
    d_config->pcidevs = x_pcidevs;
    d_config->num_pcidevs = npcidevs;

    return 0;

1240
 error:
1241 1242 1243 1244 1245 1246 1247
    for (i = 0; i < npcidevs; i++)
        libxl_device_pci_dispose(&x_pcidevs[i]);

    VIR_FREE(x_pcidevs);
    return -1;
}

1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278
int
libxlDriverNodeGetInfo(libxlDriverPrivatePtr driver, virNodeInfoPtr info)
{
    libxl_physinfo phy_info;
    virArch hostarch = virArchFromHost();
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
    int ret = -1;

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

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

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

    ret = 0;

1279
 cleanup:
1280 1281 1282 1283
    virObjectUnref(cfg);
    return ret;
}

J
Jim Fehlig 已提交
1284 1285 1286
virCapsPtr
libxlMakeCapabilities(libxl_ctx *ctx)
{
J
Jim Fehlig 已提交
1287
    virCapsPtr caps;
J
Jim Fehlig 已提交
1288

J
Jim Fehlig 已提交
1289
    if ((caps = virCapabilitiesNew(virArchFromHost(), 1, 1)) == NULL)
1290
        return NULL;
J
Jim Fehlig 已提交
1291

J
Jim Fehlig 已提交
1292 1293
    if (libxlCapsInitHost(ctx, caps) < 0)
        goto error;
J
Jim Fehlig 已提交
1294

1295 1296 1297
    if (libxlCapsInitNuma(ctx, caps) < 0)
        goto error;

J
Jim Fehlig 已提交
1298 1299 1300 1301
    if (libxlCapsInitGuests(ctx, caps) < 0)
        goto error;

    return caps;
J
Jim Fehlig 已提交
1302

1303
 error:
J
Jim Fehlig 已提交
1304 1305
    virObjectUnref(caps);
    return NULL;
J
Jim Fehlig 已提交
1306 1307 1308
}

int
1309
libxlBuildDomainConfig(virPortAllocatorPtr graphicsports,
1310 1311 1312
                       virDomainDefPtr def,
                       libxl_ctx *ctx,
                       libxl_domain_config *d_config)
J
Jim Fehlig 已提交
1313
{
1314
    libxl_domain_config_init(d_config);
J
Jim Fehlig 已提交
1315

1316
    if (libxlMakeDomCreateInfo(ctx, def, &d_config->c_info) < 0)
J
Jim Fehlig 已提交
1317 1318
        return -1;

1319
    if (libxlMakeDomBuildInfo(def, ctx, d_config) < 0)
1320
        return -1;
J
Jim Fehlig 已提交
1321

1322
    if (libxlMakeDiskList(def, d_config) < 0)
1323
        return -1;
J
Jim Fehlig 已提交
1324

1325
    if (libxlMakeNicList(def, d_config) < 0)
1326
        return -1;
J
Jim Fehlig 已提交
1327

1328
    if (libxlMakeVfbList(graphicsports, def, d_config) < 0)
1329
        return -1;
J
Jim Fehlig 已提交
1330

1331
    if (libxlMakePCIList(def, d_config) < 0)
1332 1333
        return -1;

J
Jim Fehlig 已提交
1334 1335 1336 1337 1338 1339
    d_config->on_reboot = def->onReboot;
    d_config->on_poweroff = def->onPoweroff;
    d_config->on_crash = def->onCrash;

    return 0;
}
1340 1341 1342 1343 1344 1345 1346 1347

virDomainXMLOptionPtr
libxlCreateXMLConf(void)
{
    return virDomainXMLOptionNew(&libxlDomainDefParserConfig,
                                 &libxlDomainXMLPrivateDataCallbacks,
                                 NULL);
}