domaincapstest.c 10.2 KB
Newer Older
M
Michal Privoznik 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
/*
 * Copyright (C) Red Hat, Inc. 2014
 *
 * 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
 * License along with this library.  If not, see
 * <http://www.gnu.org/licenses/>.
 *
 * Authors:
 *      Michal Privoznik <mprivozn@redhat.com>
 */

#include <config.h>
#include <stdlib.h>

#include "testutils.h"
#include "domain_capabilities.h"


#define VIR_FROM_THIS VIR_FROM_NONE

31 32
typedef int (*virDomainCapsFill)(virDomainCapsPtr domCaps,
                                 void *opaque);
M
Michal Privoznik 已提交
33 34 35 36

#define SET_ALL_BITS(x) \
    memset(&(x.values), 0xff, sizeof(x.values))

37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
static int ATTRIBUTE_SENTINEL
fillStringValues(virDomainCapsStringValuesPtr values, ...)
{
    int ret = 0;
    va_list list;
    const char *str;

    va_start(list, values);
    while ((str = va_arg(list, const char *))) {
        if (VIR_REALLOC_N(values->values, values->nvalues + 1) < 0 ||
            VIR_STRDUP(values->values[values->nvalues], str) < 0) {
            ret = -1;
            break;
        }
        values->nvalues++;
    }
    va_end(list);

    return ret;
}

58
static int
J
Jiri Denemark 已提交
59
fillAllCaps(virDomainCapsPtr domCaps)
M
Michal Privoznik 已提交
60
{
61 62
    virDomainCapsOSPtr os = &domCaps->os;
    virDomainCapsLoaderPtr loader = &os->loader;
M
Michal Privoznik 已提交
63
    virDomainCapsDeviceDiskPtr disk = &domCaps->disk;
64
    virDomainCapsDeviceGraphicsPtr graphics = &domCaps->graphics;
65
    virDomainCapsDeviceVideoPtr video = &domCaps->video;
M
Michal Privoznik 已提交
66 67 68
    virDomainCapsDeviceHostdevPtr hostdev = &domCaps->hostdev;
    domCaps->maxvcpus = 255;

69
    os->supported = true;
70

71
    loader->supported = true;
72 73
    SET_ALL_BITS(loader->type);
    SET_ALL_BITS(loader->readonly);
74 75 76 77 78
    if (fillStringValues(&loader->values,
                         "/foo/bar",
                         "/tmp/my_path",
                         NULL) < 0)
        return -1;
79

80
    disk->supported = true;
M
Michal Privoznik 已提交
81 82 83
    SET_ALL_BITS(disk->diskDevice);
    SET_ALL_BITS(disk->bus);

84 85 86
    graphics->supported = true;
    SET_ALL_BITS(graphics->type);

87 88 89
    video->supported = true;
    SET_ALL_BITS(video->modelType);

90
    hostdev->supported = true;
M
Michal Privoznik 已提交
91 92 93 94 95
    SET_ALL_BITS(hostdev->mode);
    SET_ALL_BITS(hostdev->startupPolicy);
    SET_ALL_BITS(hostdev->subsysType);
    SET_ALL_BITS(hostdev->capsType);
    SET_ALL_BITS(hostdev->pciBackend);
96
    return 0;
M
Michal Privoznik 已提交
97 98
}

99

J
Jiri Denemark 已提交
100
#if WITH_QEMU
101
# include "testutilsqemu.h"
102

103
static int
104
fillQemuCaps(virDomainCapsPtr domCaps,
J
Jiri Denemark 已提交
105
             const char *name,
J
Jiri Denemark 已提交
106
             const char *arch,
107
             const char *machine,
J
Jiri Denemark 已提交
108
             virQEMUDriverConfigPtr cfg)
109
{
J
Jiri Denemark 已提交
110 111 112
    int ret = -1;
    char *path = NULL;
    virQEMUCapsPtr qemuCaps = NULL;
113
    virDomainCapsLoaderPtr loader = &domCaps->os.loader;
114

115
    if (virAsprintf(&path, "%s/qemucapabilitiesdata/%s.%s.xml",
J
Jiri Denemark 已提交
116
                    abs_srcdir, name, arch) < 0 ||
J
Jiri Denemark 已提交
117 118 119
        !(qemuCaps = qemuTestParseCapabilities(path)))
        goto cleanup;

120 121 122 123 124 125 126 127 128 129
    if (machine &&
        VIR_STRDUP(domCaps->machine,
                   virQEMUCapsGetCanonicalMachine(qemuCaps, machine)) < 0)
        goto cleanup;

    if (!domCaps->machine &&
        VIR_STRDUP(domCaps->machine,
                   virQEMUCapsGetDefaultMachine(qemuCaps)) < 0)
        goto cleanup;

130
    if (virQEMUCapsFillDomainCaps(domCaps, qemuCaps,
131 132
                                  cfg->firmwares,
                                  cfg->nfirmwares) < 0)
J
Jiri Denemark 已提交
133
        goto cleanup;
134 135 136 137 138 139 140 141 142 143

    /* The function above tries to query host's KVM & VFIO capabilities by
     * calling qemuHostdevHostSupportsPassthroughLegacy() and
     * qemuHostdevHostSupportsPassthroughVFIO() which, however, can't be
     * successfully mocked as they are not exposed as internal APIs. Therefore,
     * instead of mocking set the expected values here by hand. */
    VIR_DOMAIN_CAPS_ENUM_SET(domCaps->hostdev.pciBackend,
                             VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT,
                             VIR_DOMAIN_HOSTDEV_PCI_BACKEND_KVM,
                             VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO);
144

J
Jiri Denemark 已提交
145 146
    /* As of f05b6a918e28 we are expecting to see OVMF_CODE.fd file which
     * may not exists everywhere. */
147 148 149 150
    while (loader->values.nvalues)
        VIR_FREE(loader->values.values[--loader->values.nvalues]);

    if (fillStringValues(&loader->values,
151
                         "/usr/share/AAVMF/AAVMF_CODE.fd",
152 153
                         "/usr/share/OVMF/OVMF_CODE.fd",
                         NULL) < 0)
M
Michal Privoznik 已提交
154 155
        goto cleanup;

J
Jiri Denemark 已提交
156
    ret = 0;
M
Michal Privoznik 已提交
157
 cleanup:
J
Jiri Denemark 已提交
158 159
    virObjectUnref(qemuCaps);
    VIR_FREE(path);
160
    return ret;
M
Michal Privoznik 已提交
161
}
J
Jiri Denemark 已提交
162 163 164 165 166 167 168 169
#endif /* WITH_QEMU */


enum testCapsType {
    CAPS_NONE,
    CAPS_ALL,
    CAPS_QEMU,
};
M
Michal Privoznik 已提交
170

J
Jiri Denemark 已提交
171 172 173
struct testData {
    const char *name;
    const char *emulator;
M
Michal Privoznik 已提交
174
    const char *machine;
J
Jiri Denemark 已提交
175
    const char *arch;
M
Michal Privoznik 已提交
176
    virDomainVirtType type;
J
Jiri Denemark 已提交
177 178 179
    enum testCapsType capsType;
    const char *capsName;
    void *capsOpaque;
M
Michal Privoznik 已提交
180 181 182 183 184
};

static int
test_virDomainCapsFormat(const void *opaque)
{
J
Jiri Denemark 已提交
185
    const struct testData *data = opaque;
M
Michal Privoznik 已提交
186 187 188 189 190
    virDomainCapsPtr domCaps = NULL;
    char *path = NULL;
    char *domCapsXML = NULL;
    int ret = -1;

191
    if (virAsprintf(&path, "%s/domaincapsschemadata/%s.xml",
J
Jiri Denemark 已提交
192
                    abs_srcdir, data->name) < 0)
M
Michal Privoznik 已提交
193 194
        goto cleanup;

J
Jiri Denemark 已提交
195 196
    if (!(domCaps = virDomainCapsNew(data->emulator, data->machine,
                                     virArchFromString(data->arch),
J
Jiri Denemark 已提交
197
                                     data->type)))
M
Michal Privoznik 已提交
198 199
        goto cleanup;

J
Jiri Denemark 已提交
200 201 202 203 204 205 206 207 208 209 210
    switch (data->capsType) {
    case CAPS_NONE:
        break;

    case CAPS_ALL:
        if (fillAllCaps(domCaps) < 0)
            goto cleanup;
        break;

    case CAPS_QEMU:
#if WITH_QEMU
211
        if (fillQemuCaps(domCaps, data->capsName, data->arch, data->machine,
212
                         data->capsOpaque) < 0)
J
Jiri Denemark 已提交
213 214 215 216 217
            goto cleanup;
#endif
        break;
    }

M
Michal Privoznik 已提交
218 219 220
    if (!(domCapsXML = virDomainCapsFormat(domCaps)))
        goto cleanup;

221
    if (virTestCompareToFile(domCapsXML, path) < 0)
M
Michal Privoznik 已提交
222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
        goto cleanup;

    ret = 0;
 cleanup:
    VIR_FREE(domCapsXML);
    VIR_FREE(path);
    virObjectUnref(domCaps);
    return ret;
}

static int
mymain(void)
{
    int ret = 0;

J
Jiri Denemark 已提交
237
#if WITH_QEMU
238 239
    virQEMUDriverConfigPtr cfg = virQEMUDriverConfigNew(false);

240 241
    if (!cfg)
        return EXIT_FAILURE;
J
Jiri Denemark 已提交
242 243 244 245 246 247 248 249 250 251 252 253
#endif

#define DO_TEST(Name, Emulator, Machine, Arch, Type, CapsType)          \
    do {                                                                \
        struct testData data = {                                        \
            .name = Name,                                               \
            .emulator = Emulator,                                       \
            .machine = Machine,                                         \
            .arch = Arch,                                               \
            .type = Type,                                               \
            .capsType = CapsType,                                       \
        };                                                              \
254
        if (virTestRun(Name, test_virDomainCapsFormat, &data) < 0)      \
J
Jiri Denemark 已提交
255 256
            ret = -1;                                                   \
    } while (0)
257

J
Jiri Denemark 已提交
258 259
#define DO_TEST_QEMU(Name, CapsName, Emulator, Machine, Arch, Type)     \
    do {                                                                \
260 261 262 263 264 265 266 267
        char *name = NULL;                                              \
        if (virAsprintf(&name, "qemu_%s%s%s.%s",                        \
                        Name,                                           \
                        Machine ? "-" : "", Machine ? Machine : "",     \
                        Arch) < 0) {                                    \
            ret = -1;                                                   \
            break;                                                      \
        }                                                               \
J
Jiri Denemark 已提交
268
        struct testData data = {                                        \
269
            .name = name,                                               \
J
Jiri Denemark 已提交
270 271 272 273 274 275 276 277
            .emulator = Emulator,                                       \
            .machine = Machine,                                         \
            .arch = Arch,                                               \
            .type = Type,                                               \
            .capsType = CAPS_QEMU,                                      \
            .capsName = CapsName,                                       \
            .capsOpaque = cfg,                                          \
        };                                                              \
278
        if (virTestRun(name, test_virDomainCapsFormat, &data) < 0)      \
J
Jiri Denemark 已提交
279
            ret = -1;                                                   \
280
        VIR_FREE(name);                                                 \
281 282
    } while (0)

J
Jiri Denemark 已提交
283
    DO_TEST("basic", "/bin/emulatorbin", "my-machine-type",
J
Jiri Denemark 已提交
284
            "x86_64", VIR_DOMAIN_VIRT_UML, CAPS_NONE);
J
Jiri Denemark 已提交
285
    DO_TEST("full", "/bin/emulatorbin", "my-machine-type",
J
Jiri Denemark 已提交
286
            "x86_64", VIR_DOMAIN_VIRT_KVM, CAPS_ALL);
J
Jiri Denemark 已提交
287 288 289

#if WITH_QEMU

290
    DO_TEST_QEMU("1.7.0", "caps_1.7.0",
291
                 "/usr/bin/qemu-system-x86_64", NULL,
J
Jiri Denemark 已提交
292
                 "x86_64", VIR_DOMAIN_VIRT_KVM);
293

294
    DO_TEST_QEMU("2.6.0", "caps_2.6.0",
295
                 "/usr/bin/qemu-system-x86_64", NULL,
J
Jiri Denemark 已提交
296
                 "x86_64", VIR_DOMAIN_VIRT_KVM);
297

298
    DO_TEST_QEMU("2.6.0", "caps_2.6.0-gicv2",
299
                 "/usr/bin/qemu-system-aarch64", NULL,
J
Jiri Denemark 已提交
300
                 "aarch64", VIR_DOMAIN_VIRT_KVM);
301

302
    DO_TEST_QEMU("2.6.0-gicv2", "caps_2.6.0-gicv2",
303
                 "/usr/bin/qemu-system-aarch64", "virt",
J
Jiri Denemark 已提交
304
                 "aarch64", VIR_DOMAIN_VIRT_KVM);
305

306
    DO_TEST_QEMU("2.6.0-gicv3", "caps_2.6.0-gicv3",
307
                 "/usr/bin/qemu-system-aarch64", "virt",
J
Jiri Denemark 已提交
308
                 "aarch64", VIR_DOMAIN_VIRT_KVM);
309

310
    DO_TEST_QEMU("2.6.0", "caps_2.6.0",
311
                 "/usr/bin/qemu-system-ppc64", NULL,
J
Jiri Denemark 已提交
312
                 "ppc64le", VIR_DOMAIN_VIRT_KVM);
313

314 315
#endif /* WITH_QEMU */

M
Michal Privoznik 已提交
316 317 318 319
    return ret;
}

VIRT_TEST_MAIN(mymain)