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

5 6
# include "testutilsqemu.h"
# 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 12 13
# include "virstring.h"

# define VIR_FROM_THIS VIR_FROM_QEMU
14

15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
static virCapsGuestMachinePtr *testQemuAllocMachines(int *nmachines)
{
    virCapsGuestMachinePtr *machines;
    static const char *const x86_machines[] = {
        "pc", "isapc"
    };

    machines = virCapabilitiesAllocMachines(x86_machines,
                                            ARRAY_CARDINALITY(x86_machines));
    if (machines == NULL)
        return NULL;

    *nmachines = ARRAY_CARDINALITY(x86_machines);

    return machines;
}

M
Mark McLoughlin 已提交
32 33 34 35 36 37 38 39 40 41 42 43
/* Newer versions of qemu have versioned machine types to allow
 * compatibility with older releases.
 * The 'pc' machine type is an alias of the newest machine type.
 */
static virCapsGuestMachinePtr *testQemuAllocNewerMachines(int *nmachines)
{
    virCapsGuestMachinePtr *machines;
    char *canonical;
    static const char *const x86_machines[] = {
        "pc-0.11", "pc", "pc-0.10", "isapc"
    };

44
    if (VIR_STRDUP(canonical, x86_machines[0]) < 0)
M
Mark McLoughlin 已提交
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
        return NULL;

    machines = virCapabilitiesAllocMachines(x86_machines,
                                            ARRAY_CARDINALITY(x86_machines));
    if (machines == NULL) {
        VIR_FREE(canonical);
        return NULL;
    }

    machines[1]->canonical = canonical;

    *nmachines = ARRAY_CARDINALITY(x86_machines);

    return machines;
}

61

62 63 64 65 66 67 68 69 70 71
static int testQemuAddPPC64Guest(virCapsPtr caps)
{
    static const char *machine[] = { "pseries" };
    virCapsGuestMachinePtr *machines = NULL;
    virCapsGuestPtr guest;

    machines = virCapabilitiesAllocMachines(machine, 1);
    if (!machines)
        goto error;

72
    guest = virCapabilitiesAddGuest(caps, "hvm", VIR_ARCH_PPC64,
73 74 75 76 77 78 79 80 81 82
                                    "/usr/bin/qemu-system-ppc64", NULL,
                                     1, machines);
    if (!guest)
        goto error;

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

    return 0;

83
 error:
84 85 86 87 88
    /* No way to free a guest? */
    virCapabilitiesFreeMachines(machines, 1);
    return -1;
}

O
Olivia Yin 已提交
89 90 91 92 93
static int testQemuAddPPCGuest(virCapsPtr caps)
{
    static const char *machine[] = { "g3beige",
                                     "mac99",
                                     "prep",
94
                                     "ppce500" };
O
Olivia Yin 已提交
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112
    virCapsGuestMachinePtr *machines = NULL;
    virCapsGuestPtr guest;

    machines = virCapabilitiesAllocMachines(machine, 1);
    if (!machines)
        goto error;

    guest = virCapabilitiesAddGuest(caps, "hvm", VIR_ARCH_PPC,
                                    "/usr/bin/qemu-system-ppc", NULL,
                                     1, machines);
    if (!guest)
        goto error;

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

    return 0;

113
 error:
O
Olivia Yin 已提交
114 115 116 117 118
    /* No way to free a guest? */
    virCapabilitiesFreeMachines(machines, 1);
    return -1;
}

119 120
static int testQemuAddS390Guest(virCapsPtr caps)
{
121 122
    static const char *s390_machines[] = { "s390-virtio",
                                           "s390-ccw-virtio" };
123 124 125 126 127 128 129 130
    virCapsGuestMachinePtr *machines = NULL;
    virCapsGuestPtr guest;

    machines = virCapabilitiesAllocMachines(s390_machines,
                                            ARRAY_CARDINALITY(s390_machines));
    if (!machines)
        goto error;

131
    guest = virCapabilitiesAddGuest(caps, "hvm", VIR_ARCH_S390X,
132 133 134 135 136 137 138 139 140 141 142
                                    "/usr/bin/qemu-system-s390x", NULL,
                                    ARRAY_CARDINALITY(s390_machines),
                                    machines);
    if (!guest)
        goto error;

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

    return 0;

143
 error:
144 145 146 147
    virCapabilitiesFreeMachines(machines, ARRAY_CARDINALITY(s390_machines));
    return -1;
}

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
static int testQemuAddArmGuest(virCapsPtr caps)
{
    static const char *machines[] = { "vexpress-a9",
                                      "vexpress-a15",
                                      "versatilepb" };
    virCapsGuestMachinePtr *capsmachines = NULL;
    virCapsGuestPtr guest;

    capsmachines = virCapabilitiesAllocMachines(machines,
                                                ARRAY_CARDINALITY(machines));
    if (!capsmachines)
        goto error;

    guest = virCapabilitiesAddGuest(caps, "hvm", VIR_ARCH_ARMV7L,
                                    "/usr/bin/qemu-system-arm", NULL,
                                    ARRAY_CARDINALITY(machines),
                                    capsmachines);
    if (!guest)
        goto error;

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

    return 0;

173
 error:
174 175 176 177
    virCapabilitiesFreeMachines(capsmachines, ARRAY_CARDINALITY(machines));
    return -1;
}

178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200
static int testQemuAddAARCH64Guest(virCapsPtr caps)
{
    static const char *machines[] = { "virt"};
    virCapsGuestMachinePtr *capsmachines = NULL;
    virCapsGuestPtr guest;

    capsmachines = virCapabilitiesAllocMachines(machines,
                                                ARRAY_CARDINALITY(machines));
    if (!capsmachines)
        goto error;

    guest = virCapabilitiesAddGuest(caps, "hvm", VIR_ARCH_AARCH64,
                                    "/usr/bin/qemu-system-aarch64", NULL,
                                    ARRAY_CARDINALITY(machines),
                                    capsmachines);
    if (!guest)
        goto error;

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

    return 0;

201
 error:
202 203 204
    virCapabilitiesFreeMachines(capsmachines, ARRAY_CARDINALITY(machines));
    return -1;
}
205

206 207
virCapsPtr testQemuCapsInit(void)
{
208 209
    virCapsPtr caps;
    virCapsGuestPtr guest;
210 211
    virCapsGuestMachinePtr *machines = NULL;
    int nmachines = 0;
212 213 214
    static const char *const xen_machines[] = {
        "xenner"
    };
J
Jiri Denemark 已提交
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
    static virCPUFeatureDef host_cpu_features[] = {
        { (char *) "lahf_lm",   -1 },
        { (char *) "xtpr",      -1 },
        { (char *) "cx16",      -1 },
        { (char *) "tm2",       -1 },
        { (char *) "est",       -1 },
        { (char *) "vmx",       -1 },
        { (char *) "ds_cpl",    -1 },
        { (char *) "pbe",       -1 },
        { (char *) "tm",        -1 },
        { (char *) "ht",        -1 },
        { (char *) "ss",        -1 },
        { (char *) "acpi",      -1 },
        { (char *) "ds",        -1 }
    };
    static virCPUDef host_cpu = {
        VIR_CPU_TYPE_HOST,      /* type */
232
        0,                      /* mode */
J
Jiri Denemark 已提交
233
        0,                      /* match */
234
        VIR_ARCH_X86_64,        /* arch */
J
Jiri Denemark 已提交
235
        (char *) "core2duo",    /* model */
236
        NULL,                   /* vendor_id */
237
        0,                      /* fallback */
J
Jiri Denemark 已提交
238
        (char *) "Intel",       /* vendor */
J
Jiri Denemark 已提交
239 240 241 242
        1,                      /* sockets */
        2,                      /* cores */
        1,                      /* threads */
        ARRAY_CARDINALITY(host_cpu_features), /* nfeatures */
E
Eric Blake 已提交
243
        ARRAY_CARDINALITY(host_cpu_features), /* nfeatures_max */
E
Eric Blake 已提交
244
        host_cpu_features,      /* features */
J
Jiri Denemark 已提交
245
    };
246

247
    if ((caps = virCapabilitiesNew(host_cpu.arch,
248
                                   false, false)) == NULL)
249 250
        return NULL;

251 252 253 254 255 256 257 258 259 260
    /* 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;

    if (VIR_STRDUP(caps->host.secModels[0].model, "none") < 0 ||
        VIR_STRDUP(caps->host.secModels[0].doi, "0") < 0)
        goto cleanup;

J
Jiri Denemark 已提交
261 262
    if ((caps->host.cpu = virCPUDefCopy(&host_cpu)) == NULL ||
        (machines = testQemuAllocMachines(&nmachines)) == NULL)
263 264
        goto cleanup;

265
    if ((guest = virCapabilitiesAddGuest(caps, "hvm", VIR_ARCH_I686,
266
                                         "/usr/bin/qemu", NULL,
267
                                         nmachines, machines)) == NULL ||
268
        !virCapabilitiesAddGuestFeature(guest, "cpuselection", true, false))
269
        goto cleanup;
270 271
    machines = NULL;

272 273 274 275 276 277 278 279
    if (virCapabilitiesAddGuestDomain(guest,
                                      "qemu",
                                      NULL,
                                      NULL,
                                      0,
                                      NULL) == NULL)
        goto cleanup;

M
Mark McLoughlin 已提交
280
    if ((machines = testQemuAllocNewerMachines(&nmachines)) == NULL)
281 282
        goto cleanup;

283
    if ((guest = virCapabilitiesAddGuest(caps, "hvm", VIR_ARCH_X86_64,
284
                                         "/usr/bin/qemu-system-x86_64", NULL,
285
                                         nmachines, machines)) == NULL ||
286
        !virCapabilitiesAddGuestFeature(guest, "cpuselection", true, false))
287
        goto cleanup;
288 289
    machines = NULL;

290 291 292 293 294 295 296
    if (virCapabilitiesAddGuestDomain(guest,
                                      "qemu",
                                      NULL,
                                      NULL,
                                      0,
                                      NULL) == NULL)
        goto cleanup;
297 298 299 300

    if ((machines = testQemuAllocMachines(&nmachines)) == NULL)
        goto cleanup;

301 302 303 304
    if (virCapabilitiesAddGuestDomain(guest,
                                      "kvm",
                                      "/usr/bin/kvm",
                                      NULL,
305 306
                                      nmachines,
                                      machines) == NULL)
307
        goto cleanup;
308
    machines = NULL;
309

310
    nmachines = ARRAY_CARDINALITY(xen_machines);
311 312 313
    if ((machines = virCapabilitiesAllocMachines(xen_machines, nmachines)) == NULL)
        goto cleanup;

314
    if ((guest = virCapabilitiesAddGuest(caps, "xen", VIR_ARCH_X86_64,
315
                                         "/usr/bin/xenner", NULL,
316
                                         nmachines, machines)) == NULL)
317
        goto cleanup;
318 319
    machines = NULL;

320 321 322 323 324 325 326 327
    if (virCapabilitiesAddGuestDomain(guest,
                                      "kvm",
                                      "/usr/bin/kvm",
                                      NULL,
                                      0,
                                      NULL) == NULL)
        goto cleanup;

328 329 330
    if (testQemuAddPPC64Guest(caps))
        goto cleanup;

O
Olivia Yin 已提交
331 332 333
    if (testQemuAddPPCGuest(caps))
        goto cleanup;

334 335 336
    if (testQemuAddS390Guest(caps))
        goto cleanup;

337 338 339
    if (testQemuAddArmGuest(caps))
        goto cleanup;

340 341 342
    if (testQemuAddAARCH64Guest(caps))
        goto cleanup;

343
    if (virTestGetDebug()) {
344 345 346 347 348 349 350 351 352 353 354
        char *caps_str;

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

        fprintf(stderr, "QEMU driver capabilities:\n%s", caps_str);

        VIR_FREE(caps_str);
    }

355 356
    return caps;

357
 cleanup:
358
    virCapabilitiesFreeMachines(machines, nmachines);
359
    virObjectUnref(caps);
360 361
    return NULL;
}
362 363 364


static char *
365 366
testSCSIDeviceGetSgName(const char *sysfs_prefix ATTRIBUTE_UNUSED,
                        const char *adapter ATTRIBUTE_UNUSED,
367 368 369 370 371 372 373 374 375 376 377 378 379 380 381
                        unsigned int bus ATTRIBUTE_UNUSED,
                        unsigned int target ATTRIBUTE_UNUSED,
                        unsigned int unit ATTRIBUTE_UNUSED)
{
    char *sg = NULL;

    if (VIR_STRDUP(sg, "sg0") < 0)
        return NULL;

    return sg;
}

qemuBuildCommandLineCallbacks testCallbacks = {
    .qemuGetSCSIDeviceSgName = testSCSIDeviceGetSgName,
};
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

virQEMUCapsPtr
qemuTestParseCapabilities(const char *capsFile)
{
    virQEMUCapsPtr qemuCaps = NULL;
    xmlDocPtr xml;
    xmlXPathContextPtr ctxt = NULL;
    ssize_t i, n;
    xmlNodePtr *nodes = NULL;

    if (!(xml = virXMLParseFileCtxt(capsFile, &ctxt)))
        goto error;

    if ((n = virXPathNodeSet("/qemuCaps/flag", ctxt, &nodes)) < 0) {
        fprintf(stderr, "failed to parse qemu capabilities flags");
        goto error;
    }

    if (n > 0) {
        if (!(qemuCaps = virQEMUCapsNew()))
            goto error;

        for (i = 0; i < n; i++) {
            char *str = virXMLPropString(nodes[i], "name");
            if (str) {
                int flag = virQEMUCapsTypeFromString(str);
                if (flag < 0) {
                    fprintf(stderr, "Unknown qemu capabilities flag %s", str);
                    VIR_FREE(str);
                    goto error;
                }
                VIR_FREE(str);
                virQEMUCapsSet(qemuCaps, flag);
            }
        }
    }

    VIR_FREE(nodes);
    xmlFreeDoc(xml);
    xmlXPathFreeContext(ctxt);
    return qemuCaps;

 error:
    VIR_FREE(nodes);
    virObjectUnref(qemuCaps);
    xmlFreeDoc(xml);
    xmlXPathFreeContext(ctxt);
    return NULL;
}
A
Atsushi SAKAI 已提交
431
#endif