testutilsqemu.c 12.8 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 245 246 247
        host_cpu_features,      /* features */
        0,                      /* ncells */
        NULL,                   /* cells */
        0,                      /* cells_cpus */
J
Jiri Denemark 已提交
248
    };
249

250
    if ((caps = virCapabilitiesNew(host_cpu.arch,
251
                                   false, false)) == NULL)
252 253
        return NULL;

254 255 256 257 258 259 260 261 262 263
    /* 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 已提交
264 265
    if ((caps->host.cpu = virCPUDefCopy(&host_cpu)) == NULL ||
        (machines = testQemuAllocMachines(&nmachines)) == NULL)
266 267
        goto cleanup;

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

275 276 277 278 279 280 281 282
    if (virCapabilitiesAddGuestDomain(guest,
                                      "qemu",
                                      NULL,
                                      NULL,
                                      0,
                                      NULL) == NULL)
        goto cleanup;

M
Mark McLoughlin 已提交
283
    if ((machines = testQemuAllocNewerMachines(&nmachines)) == NULL)
284 285
        goto cleanup;

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

293 294 295 296 297 298 299
    if (virCapabilitiesAddGuestDomain(guest,
                                      "qemu",
                                      NULL,
                                      NULL,
                                      0,
                                      NULL) == NULL)
        goto cleanup;
300 301 302 303

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

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

313
    nmachines = ARRAY_CARDINALITY(xen_machines);
314 315 316
    if ((machines = virCapabilitiesAllocMachines(xen_machines, nmachines)) == NULL)
        goto cleanup;

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

323 324 325 326 327 328 329 330
    if (virCapabilitiesAddGuestDomain(guest,
                                      "kvm",
                                      "/usr/bin/kvm",
                                      NULL,
                                      0,
                                      NULL) == NULL)
        goto cleanup;

331 332 333
    if (testQemuAddPPC64Guest(caps))
        goto cleanup;

O
Olivia Yin 已提交
334 335 336
    if (testQemuAddPPCGuest(caps))
        goto cleanup;

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

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

343 344 345
    if (testQemuAddAARCH64Guest(caps))
        goto cleanup;

346
    if (virTestGetDebug()) {
347 348 349 350 351 352 353 354 355 356 357
        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);
    }

358 359
    return caps;

360
 cleanup:
361
    virCapabilitiesFreeMachines(machines, nmachines);
362
    virObjectUnref(caps);
363 364
    return NULL;
}
365 366 367


static char *
368 369
testSCSIDeviceGetSgName(const char *sysfs_prefix ATTRIBUTE_UNUSED,
                        const char *adapter ATTRIBUTE_UNUSED,
370 371 372 373 374 375 376 377 378 379 380 381 382 383 384
                        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,
};
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

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 已提交
434
#endif