testutilsqemu.c 21.4 KB
Newer Older
1
#include <config.h>
A
Atsushi SAKAI 已提交
2
#ifdef WITH_QEMU
3

4
# include "testutilsqemu.h"
P
Pavel Hrdina 已提交
5
# include "testutilshostcpus.h"
6
# include "testutils.h"
7
# include "viralloc.h"
J
Jiri Denemark 已提交
8
# include "cpu_conf.h"
9
# include "qemu/qemu_driver.h"
10
# include "qemu/qemu_domain.h"
11
# define LIBVIRT_QEMU_CAPSPRIV_H_ALLOW
12
# include "qemu/qemu_capspriv.h"
13
# include "virstring.h"
14
# include "virfilecache.h"
15 16

# define VIR_FROM_THIS VIR_FROM_QEMU
17

18 19
virCPUDefPtr cpuDefault;
virCPUDefPtr cpuHaswell;
20
virCPUDefPtr cpuPower8;
21
virCPUDefPtr cpuPower9;
22

23

24 25 26 27 28 29 30 31 32 33 34
static const char *qemu_emulators[VIR_ARCH_LAST] = {
    [VIR_ARCH_I686] = "/usr/bin/qemu-system-i386",
    [VIR_ARCH_X86_64] = "/usr/bin/qemu-system-x86_64",
    [VIR_ARCH_AARCH64] = "/usr/bin/qemu-system-aarch64",
    [VIR_ARCH_ARMV7L] = "/usr/bin/qemu-system-arm",
    [VIR_ARCH_PPC64] = "/usr/bin/qemu-system-ppc64",
    [VIR_ARCH_PPC] = "/usr/bin/qemu-system-ppc",
    [VIR_ARCH_RISCV32] = "/usr/bin/qemu-system-riscv32",
    [VIR_ARCH_RISCV64] = "/usr/bin/qemu-system-riscv64",
    [VIR_ARCH_S390X] = "/usr/bin/qemu-system-s390x"
};
M
Mark McLoughlin 已提交
35

36 37 38 39
static const virArch arch_alias[VIR_ARCH_LAST] = {
    [VIR_ARCH_PPC64LE] = VIR_ARCH_PPC64,
    [VIR_ARCH_ARMV6L] = VIR_ARCH_ARMV7L,
};
M
Mark McLoughlin 已提交
40

41 42 43
static const char *const i386_machines[] = {
    "pc", "isapc", NULL
};
44 45 46
/**
 * Oldest supported qemu-1.5 supports machine types back to pc-0.10.
 */
47
static const char *const x86_64_machines[] = {
48 49 50 51 52 53
    "pc", "isapc", "q35",
    "pc-0.10", "pc-0.11", "pc-0.12", "pc-0.13", "pc-0.15", "pc-1.0", "pc-1.2",
    "pc-i440fx-1.4", "pc-i440fx-2.1", "pc-i440fx-2.3", "pc-i440fx-2.5",
    "pc-i440fx-2.6", "pc-i440fx-2.9", "pc-i440fx-2.12",
    "pc-q35-2.3", "pc-q35-2.4", "pc-q35-2.5", "pc-q35-2.7", "pc-q35-2.10",
    NULL
54 55
};
static const char *const aarch64_machines[] = {
56
    "virt", "virt-2.6", "versatilepb", NULL
57 58
};
static const char *const arm_machines[] = {
59
    "vexpress-a9", "vexpress-a15", "versatilepb", "virt", NULL
60 61 62 63 64 65 66 67 68 69 70 71 72 73
};
static const char *const ppc64_machines[] = {
    "pseries", NULL
};
static const char *const ppc_machines[] = {
    "g3beige", "mac99", "prep", "ppce500", NULL
};
static const char *const riscv32_machines[] = {
    "spike_v1.10", "spike_v1.9.1", "sifive_e", "virt", "sifive_u", NULL
};
static const char *const riscv64_machines[] = {
    "spike_v1.10", "spike_v1.9.1", "sifive_e", "virt", "sifive_u", NULL
};
static const char *const s390x_machines[] = {
74
    "s390-virtio", "s390-ccw-virtio", "s390-ccw", NULL
75
};
M
Mark McLoughlin 已提交
76

77 78
static const char *const *qemu_machines[VIR_ARCH_LAST] = {
    [VIR_ARCH_I686] = i386_machines,
79
    [VIR_ARCH_X86_64] = x86_64_machines,
80 81 82 83 84 85 86 87
    [VIR_ARCH_AARCH64] = aarch64_machines,
    [VIR_ARCH_ARMV7L] = arm_machines,
    [VIR_ARCH_PPC64] = ppc64_machines,
    [VIR_ARCH_PPC] = ppc_machines,
    [VIR_ARCH_RISCV32] = riscv32_machines,
    [VIR_ARCH_RISCV64] = riscv64_machines,
    [VIR_ARCH_S390X] = s390x_machines,
};
M
Mark McLoughlin 已提交
88

89 90
static const char *const *kvm_machines[VIR_ARCH_LAST] = {
    [VIR_ARCH_I686] = i386_machines,
91
    [VIR_ARCH_X86_64] = x86_64_machines,
92 93 94 95 96 97 98 99
    [VIR_ARCH_AARCH64] = aarch64_machines,
    [VIR_ARCH_ARMV7L] = arm_machines,
    [VIR_ARCH_PPC64] = ppc64_machines,
    [VIR_ARCH_PPC] = ppc_machines,
    [VIR_ARCH_RISCV32] = riscv32_machines,
    [VIR_ARCH_RISCV64] = riscv64_machines,
    [VIR_ARCH_S390X] = s390x_machines,
};
100

101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116

char *
virFindFileInPath(const char *file)
{
    if (g_str_has_prefix(file, "qemu-system") ||
        g_str_equal(file, "qemu-kvm")) {
        return g_strdup_printf("/usr/bin/%s", file);
    }

    /* Nothing in tests should be relying on real files
     * in host OS, so we return NULL to try to force
     * an error in such a case
     */
    return NULL;
}

117 118 119 120 121 122 123 124 125 126 127 128

virCapsHostNUMAPtr
virCapabilitiesHostNUMANewHost(void)
{
    /*
     * Build a NUMA topology with cell_id (NUMA node id
     * being 3(0 + 3),4(1 + 3), 5 and 6
     */
    return virTestCapsBuildNUMATopology(3);
}


129
static int
130 131
testQemuAddGuest(virCapsPtr caps,
                 virArch arch)
132
{
133
    size_t nmachines;
134 135
    virCapsGuestMachinePtr *machines = NULL;
    virCapsGuestPtr guest;
136
    virArch emu_arch = arch;
137

138 139
    if (arch_alias[arch] != VIR_ARCH_NONE)
        emu_arch = arch_alias[arch];
140

141 142
    if (qemu_emulators[emu_arch] == NULL)
        return 0;
143

144 145 146 147
    nmachines = g_strv_length((gchar **)qemu_machines[emu_arch]);
    machines = virCapabilitiesAllocMachines(qemu_machines[emu_arch],
                                            nmachines);
    if (machines == NULL)
148 149 150 151
        goto error;

    if (!(guest = virCapabilitiesAddGuest(caps,
                                          VIR_DOMAIN_OSTYPE_HVM,
152 153
                                          arch,
                                          qemu_emulators[emu_arch],
154 155 156 157 158 159
                                          NULL,
                                          nmachines,
                                          machines)))
        goto error;

    machines = NULL;
160 161 162 163 164
    nmachines = 0;

    if (arch == VIR_ARCH_I686 ||
        arch == VIR_ARCH_X86_64)
        virCapabilitiesAddGuestFeature(guest, VIR_CAPS_GUEST_FEATURE_TYPE_CPUSELECTION);
165 166 167 168 169 170 171 172 173

    if (!virCapabilitiesAddGuestDomain(guest,
                                       VIR_DOMAIN_VIRT_QEMU,
                                       NULL,
                                       NULL,
                                       0,
                                       NULL))
        goto error;

174 175 176 177
    nmachines = g_strv_length((char **)kvm_machines[emu_arch]);
    machines = virCapabilitiesAllocMachines(kvm_machines[emu_arch],
                                            nmachines);
    if (machines == NULL)
178 179 180 181
        goto error;

    if (!virCapabilitiesAddGuestDomain(guest,
                                       VIR_DOMAIN_VIRT_KVM,
182
                                       qemu_emulators[emu_arch],
183 184 185 186 187
                                       NULL,
                                       nmachines,
                                       machines))
        goto error;

L
Lubomir Rintel 已提交
188 189 190 191 192 193 194
    return 0;

 error:
    virCapabilitiesFreeMachines(machines, nmachines);
    return -1;
}

195

196 197
virCapsPtr testQemuCapsInit(void)
{
198
    virCapsPtr caps;
199
    size_t i;
200

201
    if (!(caps = virCapabilitiesNew(VIR_ARCH_X86_64, false, false)))
202 203
        return NULL;

204 205 206 207 208 209
    /* Add dummy 'none' security_driver. This is equal to setting
     * security_driver = "none" in qemu.conf. */
    if (VIR_ALLOC_N(caps->host.secModels, 1) < 0)
        goto cleanup;
    caps->host.nsecModels = 1;

210 211
    caps->host.secModels[0].model = g_strdup("none");
    caps->host.secModels[0].doi = g_strdup("0");
212

213
    if (!(caps->host.numa = virCapabilitiesHostNUMANewHost()))
214
        goto cleanup;
215

216 217 218 219
    for (i = 0; i < VIR_ARCH_LAST; i++) {
        if (testQemuAddGuest(caps, i) < 0)
            goto cleanup;
    }
220

221
    if (virTestGetDebug()) {
222 223 224 225 226 227
        char *caps_str;

        caps_str = virCapabilitiesFormatXML(caps);
        if (!caps_str)
            goto cleanup;

228
        VIR_TEST_DEBUG("QEMU driver capabilities:\n%s", caps_str);
229 230 231 232

        VIR_FREE(caps_str);
    }

233 234
    return caps;

235
 cleanup:
236
    caps->host.cpu = NULL;
237
    virObjectUnref(caps);
238 239
    return NULL;
}
240 241


242
void
243
qemuTestSetHostArch(virQEMUDriverPtr driver,
244 245 246 247
                    virArch arch)
{
    if (arch == VIR_ARCH_NONE)
        arch = VIR_ARCH_X86_64;
248 249 250 251

    virTestHostArch = arch;
    driver->hostarch = virArchFromHost();
    driver->caps->host.arch = virArchFromHost();
252
    qemuTestSetHostCPU(driver, arch, NULL);
253 254 255 256
}


void
257 258
qemuTestSetHostCPU(virQEMUDriverPtr driver,
                   virArch arch,
259 260 261 262 263
                   virCPUDefPtr cpu)
{
    if (!cpu) {
        if (ARCH_IS_X86(arch))
            cpu = cpuDefault;
264 265
        else if (ARCH_IS_PPC64(arch))
            cpu = cpuPower8;
266 267
    }

268
    g_unsetenv("VIR_TEST_MOCK_FAKE_HOST_CPU");
P
Pavel Hrdina 已提交
269 270
    if (cpu) {
        if (cpu->model)
271
            g_setenv("VIR_TEST_MOCK_FAKE_HOST_CPU", cpu->model, TRUE);
P
Pavel Hrdina 已提交
272
    }
273 274 275 276 277 278 279 280 281 282
    if (driver) {
        if (cpu)
            driver->caps->host.arch = cpu->arch;
        driver->caps->host.cpu = cpu;

        virCPUDefFree(driver->hostcpu);
        if (cpu)
            virCPUDefRef(cpu);
        driver->hostcpu = cpu;
    }
283 284 285
}


286
virQEMUCapsPtr
287 288
qemuTestParseCapabilitiesArch(virArch arch,
                              const char *capsFile)
289 290
{
    virQEMUCapsPtr qemuCaps = NULL;
291 292
    char *binary = g_strdup_printf("/usr/bin/qemu-system-%s",
                                   virArchToString(arch));
293

294
    if (!(qemuCaps = virQEMUCapsNewBinary(binary)) ||
295
        virQEMUCapsLoadCache(arch, qemuCaps, capsFile) < 0)
296 297
        goto error;

298
    virQEMUCapsSetInvalidation(qemuCaps, false);
299 300 301 302 303 304
    return qemuCaps;

 error:
    virObjectUnref(qemuCaps);
    return NULL;
}
305

306

307 308
void qemuTestDriverFree(virQEMUDriver *driver)
{
309
    virMutexDestroy(&driver->lock);
310 311 312 313
    if (driver->config) {
        virFileDeleteTree(driver->config->stateDir);
        virFileDeleteTree(driver->config->configDir);
    }
314
    virObjectUnref(driver->qemuCapsCache);
315 316 317
    virObjectUnref(driver->xmlopt);
    virObjectUnref(driver->caps);
    virObjectUnref(driver->config);
318
    virObjectUnref(driver->securityManager);
319 320
}

321
int qemuTestCapsCacheInsert(virFileCachePtr cache,
322 323
                            virQEMUCapsPtr caps)
{
324 325 326 327 328 329 330 331 332 333 334
    size_t i, j;

    for (i = 0; i < G_N_ELEMENTS(qemu_emulators); i++) {
        virQEMUCapsPtr tmpCaps;
        if (qemu_emulators[i] == NULL)
            continue;
        if (caps) {
            tmpCaps = virQEMUCapsNewCopy(caps);
        } else {
            tmpCaps = virQEMUCapsNew();
        }
335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358

        if (!virQEMUCapsHasMachines(tmpCaps)) {
            virQEMUCapsSetArch(tmpCaps, i);
            for (j = 0; qemu_machines[i][j] != NULL; j++) {
                virQEMUCapsAddMachine(tmpCaps,
                                      VIR_DOMAIN_VIRT_QEMU,
                                      qemu_machines[i][j],
                                      NULL,
                                      NULL,
                                      0,
                                      false,
                                      false);
            }
            for (j = 0; kvm_machines[i][j] != NULL; j++) {
                virQEMUCapsAddMachine(tmpCaps,
                                      VIR_DOMAIN_VIRT_KVM,
                                      kvm_machines[i][j],
                                      NULL,
                                      NULL,
                                      0,
                                      false,
                                      false);
                virQEMUCapsSet(tmpCaps, QEMU_CAPS_KVM);
            }
359
        }
360

361
        if (virFileCacheInsertData(cache, qemu_emulators[i], tmpCaps) < 0) {
362 363 364 365
            virObjectUnref(tmpCaps);
            return -1;
        }
    }
366

367
    return 0;
368 369
}

370

371 372 373
# define STATEDIRTEMPLATE abs_builddir "/qemustatedir-XXXXXX"
# define CONFIGDIRTEMPLATE abs_builddir "/qemuconfigdir-XXXXXX"

374 375
int qemuTestDriverInit(virQEMUDriver *driver)
{
376
    virSecurityManagerPtr mgr = NULL;
377 378
    char statedir[] = STATEDIRTEMPLATE;
    char configdir[] = CONFIGDIRTEMPLATE;
379

380 381
    memset(driver, 0, sizeof(*driver));

382 383 384 385 386 387
    if (!(cpuDefault = virCPUDefCopy(&cpuDefaultData)) ||
        !(cpuHaswell = virCPUDefCopy(&cpuHaswellData)) ||
        !(cpuPower8 = virCPUDefCopy(&cpuPower8Data)) ||
        !(cpuPower9 = virCPUDefCopy(&cpuPower9Data)))
        return -1;

388 389 390
    if (virMutexInit(&driver->lock) < 0)
        return -1;

391
    driver->hostarch = virArchFromHost();
392
    driver->config = virQEMUDriverConfigNew(false, "");
393
    if (!driver->config)
394
        goto error;
395

396 397 398 399 400
    /* Do this early so that qemuTestDriverFree() doesn't see (unlink) the real
     * dirs. */
    VIR_FREE(driver->config->stateDir);
    VIR_FREE(driver->config->configDir);

401 402 403
    /* Overwrite some default paths so it's consistent for tests. */
    VIR_FREE(driver->config->libDir);
    VIR_FREE(driver->config->channelTargetDir);
404 405
    driver->config->libDir = g_strdup("/tmp/lib");
    driver->config->channelTargetDir = g_strdup("/tmp/channel");
406

J
Ján Tomko 已提交
407
    if (!g_mkdtemp(statedir)) {
408 409 410 411
        virFilePrintf(stderr, "Cannot create fake stateDir");
        goto error;
    }

412
    driver->config->stateDir = g_strdup(statedir);
413

J
Ján Tomko 已提交
414
    if (!g_mkdtemp(configdir)) {
415 416 417 418
        virFilePrintf(stderr, "Cannot create fake configDir");
        goto error;
    }

419
    driver->config->configDir = g_strdup(configdir);
420

421 422 423 424
    driver->caps = testQemuCapsInit();
    if (!driver->caps)
        goto error;

P
Pavel Fedin 已提交
425 426
    /* Using /dev/null for libDir and cacheDir automatically produces errors
     * upon attempt to use any of them */
427
    driver->qemuCapsCache = virQEMUCapsCacheNew("/dev/null", "/dev/null", 0, 0);
P
Pavel Fedin 已提交
428 429 430
    if (!driver->qemuCapsCache)
        goto error;

431
    driver->xmlopt = virQEMUDriverCreateXMLConf(driver, "none");
432 433 434
    if (!driver->xmlopt)
        goto error;

435
    if (qemuTestCapsCacheInsert(driver->qemuCapsCache, NULL) < 0)
P
Pavel Fedin 已提交
436 437
        goto error;

438
    if (!(mgr = virSecurityManagerNew("none", "qemu",
439 440 441 442 443
                                      VIR_SECURITY_MANAGER_PRIVILEGED)))
        goto error;
    if (!(driver->securityManager = virSecurityManagerNewStack(mgr)))
        goto error;

444 445
    qemuTestSetHostCPU(driver, driver->hostarch, NULL);

446 447 448
    return 0;

 error:
449
    virObjectUnref(mgr);
450 451 452
    qemuTestDriverFree(driver);
    return -1;
}
453

454 455 456 457 458 459 460 461
int
testQemuCapsSetGIC(virQEMUCapsPtr qemuCaps,
                   int gic)
{
    virGICCapability *gicCapabilities = NULL;
    size_t ngicCapabilities = 0;

    if (VIR_ALLOC_N(gicCapabilities, 2) < 0)
462
        return -1;
463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482

# define IMPL_BOTH \
         VIR_GIC_IMPLEMENTATION_KERNEL|VIR_GIC_IMPLEMENTATION_EMULATED

    if (gic & GIC_V2) {
        gicCapabilities[ngicCapabilities].version = VIR_GIC_VERSION_2;
        gicCapabilities[ngicCapabilities].implementation = IMPL_BOTH;
        ngicCapabilities++;
    }
    if (gic & GIC_V3) {
        gicCapabilities[ngicCapabilities].version = VIR_GIC_VERSION_3;
        gicCapabilities[ngicCapabilities].implementation = IMPL_BOTH;
        ngicCapabilities++;
    }

# undef IMPL_BOTH

    virQEMUCapsSetGICCapabilities(qemuCaps,
                                  gicCapabilities, ngicCapabilities);

483
    return 0;
484 485
}

A
Atsushi SAKAI 已提交
486
#endif
487 488 489


char *
490
testQemuGetLatestCapsForArch(const char *arch,
491 492 493 494 495 496 497 498 499 500 501 502
                             const char *suffix)
{
    struct dirent *ent;
    DIR *dir = NULL;
    int rc;
    char *fullsuffix = NULL;
    char *tmp = NULL;
    unsigned long maxver = 0;
    unsigned long ver;
    const char *maxname = NULL;
    char *ret = NULL;

503
    fullsuffix = g_strdup_printf("%s.%s", arch, suffix);
504

505
    if (virDirOpen(&dir, TEST_QEMU_CAPS_PATH) < 0)
506 507
        goto cleanup;

508
    while ((rc = virDirRead(dir, &ent, TEST_QEMU_CAPS_PATH)) > 0) {
509 510
        VIR_FREE(tmp);

511
        tmp = g_strdup(STRSKIP(ent->d_name, "caps_"));
512

513
        if (!tmp)
514 515
            continue;

516
        if (!virStringStripSuffix(tmp, fullsuffix))
517 518 519
            continue;

        if (virParseVersionString(tmp, &ver, false) < 0) {
520
            VIR_TEST_DEBUG("skipping caps file '%s'", ent->d_name);
521 522 523 524 525 526 527 528 529 530 531 532 533
            continue;
        }

        if (ver > maxver) {
            maxname = ent->d_name;
            maxver = ver;
        }
    }

    if (rc < 0)
        goto cleanup;

    if (!maxname) {
534
        VIR_TEST_VERBOSE("failed to find capabilities for '%s' in '%s'",
535
                         arch, TEST_QEMU_CAPS_PATH);
536 537 538
        goto cleanup;
    }

539
    ret = g_strdup_printf("%s/%s", TEST_QEMU_CAPS_PATH, maxname);
540 541 542 543 544 545 546

 cleanup:
    VIR_FREE(tmp);
    VIR_FREE(fullsuffix);
    virDirClose(&dir);
    return ret;
}
547 548


C
Cole Robinson 已提交
549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564
virHashTablePtr
testQemuGetLatestCaps(void)
{
    const char *archs[] = {
        "aarch64",
        "ppc64",
        "riscv64",
        "s390x",
        "x86_64",
    };
    virHashTablePtr capslatest;
    size_t i;

    if (!(capslatest = virHashCreate(4, virHashValueFree)))
        goto error;

565
    VIR_TEST_VERBOSE("");
C
Cole Robinson 已提交
566

567
    for (i = 0; i < G_N_ELEMENTS(archs); ++i) {
568
        char *cap = testQemuGetLatestCapsForArch(archs[i], "xml");
C
Cole Robinson 已提交
569 570 571 572

        if (!cap || virHashAddEntry(capslatest, archs[i], cap) < 0)
            goto error;

573
        VIR_TEST_VERBOSE("latest caps for %s: %s", archs[i], cap);
C
Cole Robinson 已提交
574 575
    }

576 577
    VIR_TEST_VERBOSE("");

C
Cole Robinson 已提交
578 579 580 581 582 583 584 585
    return capslatest;

 error:
    virHashFree(capslatest);
    return NULL;
}


586
int
587
testQemuCapsIterate(const char *suffix,
588 589 590 591 592 593 594
                    testQemuCapsIterateCallback callback,
                    void *opaque)
{
    struct dirent *ent;
    DIR *dir = NULL;
    int rc;
    int ret = -1;
595
    bool fail = false;
596 597 598 599

    if (!callback)
        return 0;

600 601 602 603 604 605
    /* Validate suffix */
    if (!STRPREFIX(suffix, ".")) {
        VIR_TEST_VERBOSE("malformed suffix '%s'", suffix);
        goto cleanup;
    }

606
    if (virDirOpen(&dir, TEST_QEMU_CAPS_PATH) < 0)
607 608
        goto cleanup;

609
    while ((rc = virDirRead(dir, &ent, TEST_QEMU_CAPS_PATH)) > 0) {
610
        g_autofree char *tmp = g_strdup(ent->d_name);
611
        char *version = NULL;
612 613 614 615 616 617
        char *archName = NULL;

        /* Strip the trailing suffix, moving on if it's not present */
        if (!virStringStripSuffix(tmp, suffix))
            continue;

618 619 620 621 622 623
        /* Strip the leading prefix */
        if (!(version = STRSKIP(tmp, "caps_"))) {
            VIR_TEST_VERBOSE("malformed file name '%s'", ent->d_name);
            goto cleanup;
        }

624 625 626 627 628
        /* Find the last dot */
        if (!(archName = strrchr(tmp, '.'))) {
            VIR_TEST_VERBOSE("malformed file name '%s'", ent->d_name);
            goto cleanup;
        }
629

630 631 632
        /* The version number and the architecture name are separated by
         * a dot: overwriting that dot with \0 results in both being usable
         * as independent, null-terminated strings */
633 634 635
        archName[0] = '\0';
        archName++;

636 637 638 639 640 641
        /* Run the user-provided callback.
         *
         * We skip the dot that, as verified earlier, starts the suffix
         * to make it nicer to rebuild the original file name from inside
         * the callback.
         */
642
        if (callback(TEST_QEMU_CAPS_PATH, "caps", version,
643 644
                     archName, suffix + 1, opaque) < 0)
            fail = true;
645 646
    }

647
    if (rc < 0 || fail)
648 649 650 651 652 653 654 655 656
        goto cleanup;

    ret = 0;

 cleanup:
    virDirClose(&dir);

    return ret;
}
657 658 659 660 661 662 663 664 665 666 667 668


int
testQemuInfoSetArgs(struct testQemuInfo *info,
                    virHashTablePtr capslatest, ...)
{
    va_list argptr;
    testQemuInfoArgName argname;
    virQEMUCapsPtr qemuCaps = NULL;
    int gic = GIC_NONE;
    char *capsarch = NULL;
    char *capsver = NULL;
669
    g_autofree char *capsfile = NULL;
670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753
    int flag;
    int ret = -1;

    va_start(argptr, capslatest);
    argname = va_arg(argptr, testQemuInfoArgName);
    while (argname != ARG_END) {
        switch (argname) {
        case ARG_QEMU_CAPS:
            if (qemuCaps || !(qemuCaps = virQEMUCapsNew()))
                goto cleanup;

            while ((flag = va_arg(argptr, int)) < QEMU_CAPS_LAST)
                virQEMUCapsSet(qemuCaps, flag);

            /* Some tests are run with NONE capabilities, which is just
             * another name for QEMU_CAPS_LAST. If that is the case the
             * arguments look like this :
             *
             *   ARG_QEMU_CAPS, NONE, QEMU_CAPS_LAST, ARG_END
             *
             * Fetch one argument more and if it is QEMU_CAPS_LAST then
             * break from the switch() to force getting next argument
             * in the line. If it is not QEMU_CAPS_LAST then we've
             * fetched real ARG_* and we must process it.
             */
            if ((flag = va_arg(argptr, int)) != QEMU_CAPS_LAST) {
                argname = flag;
                continue;
            }

            break;

        case ARG_GIC:
            gic = va_arg(argptr, int);
            break;

        case ARG_MIGRATE_FROM:
            info->migrateFrom = va_arg(argptr, char *);
            break;

        case ARG_MIGRATE_FD:
            info->migrateFd = va_arg(argptr, int);
            break;

        case ARG_FLAGS:
            info->flags = va_arg(argptr, int);
            break;

        case ARG_PARSEFLAGS:
            info->parseFlags = va_arg(argptr, int);
            break;

        case ARG_CAPS_ARCH:
            capsarch = va_arg(argptr, char *);
            break;

        case ARG_CAPS_VER:
            capsver = va_arg(argptr, char *);
            break;

        case ARG_END:
        default:
            fprintf(stderr, "Unexpected test info argument");
            goto cleanup;
        }

        argname = va_arg(argptr, testQemuInfoArgName);
    }

    if (!!capsarch ^ !!capsver) {
        fprintf(stderr, "ARG_CAPS_ARCH and ARG_CAPS_VER "
                        "must be specified together.\n");
        goto cleanup;
    }

    if (qemuCaps && (capsarch || capsver)) {
        fprintf(stderr, "ARG_QEMU_CAPS can not be combined with ARG_CAPS_ARCH "
                        "or ARG_CAPS_VER\n");
        goto cleanup;
    }

    if (!qemuCaps && capsarch && capsver) {
        bool stripmachinealiases = false;

754 755
        info->arch = virArchFromString(capsarch);

756
        if (STREQ(capsver, "latest")) {
757
            capsfile = g_strdup(virHashLookup(capslatest, capsarch));
758
            stripmachinealiases = true;
759 760
        } else capsfile = g_strdup_printf("%s/caps_%s.%s.xml",
                                          TEST_QEMU_CAPS_PATH, capsver, capsarch);
761

762
        if (!(qemuCaps = qemuTestParseCapabilitiesArch(info->arch, capsfile)))
763 764 765 766 767 768 769 770 771 772 773
            goto cleanup;

        if (stripmachinealiases)
            virQEMUCapsStripMachineAliases(qemuCaps);
        info->flags |= FLAG_REAL_CAPS;
    }

    if (!qemuCaps) {
        fprintf(stderr, "No qemuCaps generated\n");
        goto cleanup;
    }
774
    info->qemuCaps = g_steal_pointer(&qemuCaps);
775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795

    if (gic != GIC_NONE && testQemuCapsSetGIC(info->qemuCaps, gic) < 0)
        goto cleanup;

    ret = 0;

 cleanup:
    virObjectUnref(qemuCaps);
    va_end(argptr);

    return ret;
}


void
testQemuInfoClear(struct testQemuInfo *info)
{
    VIR_FREE(info->infile);
    VIR_FREE(info->outfile);
    virObjectUnref(info->qemuCaps);
}