backup: Wire up qemu full pull backup commands over QMP
[libvirt/ericb.git] / tests / virhostdevtest.c
blobf86042667886047398b8880d0d7b8ab77b7bb27b
1 /*
2 * Copyright (C) 2014 SUSE LINUX Products GmbH, Nuernberg, Germany.
3 * Copyright (C) 2014-2016 Red Hat, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library. If not, see
17 * <http://www.gnu.org/licenses/>.
20 #include <config.h>
22 #include "testutils.h"
24 #ifdef __linux__
26 # include <sys/types.h>
27 # include <sys/stat.h>
28 # include <sys/ioctl.h>
29 # include <fcntl.h>
30 # include "virlog.h"
31 # include "virhostdev.h"
33 # define VIR_FROM_THIS VIR_FROM_NONE
35 VIR_LOG_INIT("tests.hostdevtest");
37 # define CHECK_LIST_COUNT(list, cnt, cb) \
38 do { \
39 size_t actualCount; \
40 if ((actualCount = cb(list)) != cnt) { \
41 virReportError(VIR_ERR_INTERNAL_ERROR, \
42 "Unexpected count of items in " #list ": %zu, " \
43 "expecting %zu", actualCount, (size_t) cnt); \
44 goto cleanup; \
45 } \
46 } while (0)
48 # define CHECK_PCI_LIST_COUNT(list, cnt) \
49 CHECK_LIST_COUNT(list, cnt, virPCIDeviceListCount)
51 # define TEST_STATE_DIR abs_builddir "/hostdevmgr"
52 static const char *drv_name = "test_driver";
53 static const char *dom_name = "test_domain";
54 static const unsigned char *uuid =
55 (unsigned char *)("f92360b0-2541-8791-fb32-d1f838811541");
56 static int nhostdevs = 3;
57 static virDomainHostdevDefPtr hostdevs[] = {NULL, NULL, NULL};
58 static virPCIDevicePtr dev[] = {NULL, NULL, NULL};
59 static virHostdevManagerPtr mgr;
61 static void
62 myCleanup(void)
64 size_t i;
65 for (i = 0; i < nhostdevs; i++) {
66 virPCIDeviceFree(dev[i]);
67 virDomainHostdevDefFree(hostdevs[i]);
70 if (mgr) {
71 if (!getenv("LIBVIRT_SKIP_CLEANUP"))
72 virFileDeleteTree(mgr->stateDir);
74 virObjectUnref(mgr->activePCIHostdevs);
75 virObjectUnref(mgr->activeUSBHostdevs);
76 virObjectUnref(mgr->inactivePCIHostdevs);
77 virObjectUnref(mgr->activeSCSIHostdevs);
78 VIR_FREE(mgr->stateDir);
79 VIR_FREE(mgr);
83 static int
84 myInit(void)
86 size_t i;
88 for (i = 0; i < nhostdevs; i++) {
89 virDomainHostdevSubsys subsys;
90 hostdevs[i] = virDomainHostdevDefNew();
91 if (!hostdevs[i])
92 goto cleanup;
93 hostdevs[i]->mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS;
94 subsys.type = VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI;
95 subsys.u.pci.addr.domain = 0;
96 subsys.u.pci.addr.bus = 0;
97 subsys.u.pci.addr.slot = i + 1;
98 subsys.u.pci.addr.function = 0;
99 subsys.u.pci.backend = VIR_DOMAIN_HOSTDEV_PCI_BACKEND_VFIO;
100 hostdevs[i]->source.subsys = subsys;
103 for (i = 0; i < nhostdevs; i++) {
104 if (!(dev[i] = virPCIDeviceNew(0, 0, i + 1, 0)))
105 goto cleanup;
107 virPCIDeviceSetStubDriver(dev[i], VIR_PCI_STUB_DRIVER_VFIO);
110 if (VIR_ALLOC(mgr) < 0)
111 goto cleanup;
112 if ((mgr->activePCIHostdevs = virPCIDeviceListNew()) == NULL)
113 goto cleanup;
114 if ((mgr->activeUSBHostdevs = virUSBDeviceListNew()) == NULL)
115 goto cleanup;
116 if ((mgr->inactivePCIHostdevs = virPCIDeviceListNew()) == NULL)
117 goto cleanup;
118 if ((mgr->activeSCSIHostdevs = virSCSIDeviceListNew()) == NULL)
119 goto cleanup;
120 if (VIR_STRDUP(mgr->stateDir, TEST_STATE_DIR) < 0)
121 goto cleanup;
122 if (virFileMakePath(mgr->stateDir) < 0)
123 goto cleanup;
125 return 0;
127 cleanup:
128 myCleanup();
129 return -1;
132 static int
133 testVirHostdevPreparePCIHostdevs_unmanaged(void)
135 int ret = -1;
136 size_t active_count, inactive_count, i;
138 for (i = 0; i < nhostdevs; i++)
139 hostdevs[i]->managed = false;
141 active_count = virPCIDeviceListCount(mgr->activePCIHostdevs);
142 inactive_count = virPCIDeviceListCount(mgr->inactivePCIHostdevs);
144 /* Test normal functionality */
145 VIR_DEBUG("Test 0 hostdevs");
146 if (virHostdevPreparePCIDevices(mgr, drv_name, dom_name, uuid,
147 NULL, 0, 0) < 0)
148 goto cleanup;
149 CHECK_PCI_LIST_COUNT(mgr->activePCIHostdevs, active_count);
150 CHECK_PCI_LIST_COUNT(mgr->inactivePCIHostdevs, inactive_count);
152 /* Test unmanaged hostdevs */
153 VIR_DEBUG("Test >=1 unmanaged hostdevs");
154 if (virHostdevPreparePCIDevices(mgr, drv_name, dom_name, uuid,
155 hostdevs, nhostdevs, 0) < 0)
156 goto cleanup;
157 CHECK_PCI_LIST_COUNT(mgr->activePCIHostdevs, active_count + nhostdevs);
158 CHECK_PCI_LIST_COUNT(mgr->inactivePCIHostdevs, inactive_count - nhostdevs);
160 /* Test conflict */
161 active_count = virPCIDeviceListCount(mgr->activePCIHostdevs);
162 inactive_count = virPCIDeviceListCount(mgr->inactivePCIHostdevs);
163 VIR_DEBUG("Test: prepare same hostdevs for same driver/domain again");
164 if (!virHostdevPreparePCIDevices(mgr, drv_name, dom_name, uuid,
165 &hostdevs[0], 1, 0))
166 goto cleanup;
167 CHECK_PCI_LIST_COUNT(mgr->activePCIHostdevs, active_count);
168 CHECK_PCI_LIST_COUNT(mgr->inactivePCIHostdevs, inactive_count);
170 VIR_DEBUG("Test: prepare same hostdevs for same driver, diff domain again");
171 if (!virHostdevPreparePCIDevices(mgr, drv_name, "test_domain1", uuid,
172 &hostdevs[1], 1, 0))
173 goto cleanup;
174 CHECK_PCI_LIST_COUNT(mgr->activePCIHostdevs, active_count);
175 CHECK_PCI_LIST_COUNT(mgr->inactivePCIHostdevs, inactive_count);
177 VIR_DEBUG("Test: prepare same hostdevs for diff driver/domain again");
178 if (!virHostdevPreparePCIDevices(mgr, "test_driver1", dom_name, uuid,
179 &hostdevs[2], 1, 0))
180 goto cleanup;
181 CHECK_PCI_LIST_COUNT(mgr->activePCIHostdevs, active_count);
182 CHECK_PCI_LIST_COUNT(mgr->inactivePCIHostdevs, inactive_count);
184 ret = 0;
186 cleanup:
187 return ret;
191 static int
192 testVirHostdevReAttachPCIHostdevs_unmanaged(void)
194 int ret = -1;
195 size_t active_count, inactive_count, i;
197 for (i = 0; i < nhostdevs; i++) {
198 if (hostdevs[i]->managed != false) {
199 VIR_DEBUG("invalid test");
200 return -1;
204 active_count = virPCIDeviceListCount(mgr->activePCIHostdevs);
205 inactive_count = virPCIDeviceListCount(mgr->inactivePCIHostdevs);
207 VIR_DEBUG("Test 0 hostdevs");
208 virHostdevReAttachPCIDevices(mgr, drv_name, dom_name, NULL, 0, NULL);
209 CHECK_PCI_LIST_COUNT(mgr->activePCIHostdevs, active_count);
210 CHECK_PCI_LIST_COUNT(mgr->inactivePCIHostdevs, inactive_count);
212 VIR_DEBUG("Test >=1 unmanaged hostdevs");
213 virHostdevReAttachPCIDevices(mgr, drv_name, dom_name,
214 hostdevs, nhostdevs, NULL);
215 CHECK_PCI_LIST_COUNT(mgr->activePCIHostdevs, active_count - nhostdevs);
216 CHECK_PCI_LIST_COUNT(mgr->inactivePCIHostdevs, inactive_count + nhostdevs);
218 ret = 0;
220 cleanup:
221 return ret;
225 static int
226 testVirHostdevPreparePCIHostdevs_managed(bool mixed)
228 int ret = -1;
229 size_t active_count, inactive_count, i;
231 for (i = 0; i < nhostdevs; i++)
232 hostdevs[i]->managed = true;
234 active_count = virPCIDeviceListCount(mgr->activePCIHostdevs);
235 inactive_count = virPCIDeviceListCount(mgr->inactivePCIHostdevs);
237 /* Test normal functionality */
238 VIR_DEBUG("Test >=1 hostdevs");
239 if (virHostdevPreparePCIDevices(mgr, drv_name, dom_name, uuid,
240 hostdevs, nhostdevs, 0) < 0)
241 goto cleanup;
242 CHECK_PCI_LIST_COUNT(mgr->activePCIHostdevs, active_count + nhostdevs);
243 /* If testing a mixed roundtrip, devices are already in the inactive list
244 * before we start and are removed from it as soon as we attach them to
245 * the guest */
246 if (mixed)
247 CHECK_PCI_LIST_COUNT(mgr->inactivePCIHostdevs, inactive_count - nhostdevs);
248 else
249 CHECK_PCI_LIST_COUNT(mgr->inactivePCIHostdevs, inactive_count);
251 /* Test conflict */
252 active_count = virPCIDeviceListCount(mgr->activePCIHostdevs);
253 inactive_count = virPCIDeviceListCount(mgr->inactivePCIHostdevs);
254 VIR_DEBUG("Test: prepare same hostdevs for same driver/domain again");
255 if (!virHostdevPreparePCIDevices(mgr, drv_name, dom_name, uuid,
256 &hostdevs[0], 1, 0))
257 goto cleanup;
258 CHECK_PCI_LIST_COUNT(mgr->activePCIHostdevs, active_count);
259 CHECK_PCI_LIST_COUNT(mgr->inactivePCIHostdevs, inactive_count);
261 VIR_DEBUG("Test: prepare same hostdevs for same driver, diff domain again");
262 if (!virHostdevPreparePCIDevices(mgr, drv_name, "test_domain1", uuid,
263 &hostdevs[1], 1, 0))
264 goto cleanup;
265 CHECK_PCI_LIST_COUNT(mgr->activePCIHostdevs, active_count);
266 CHECK_PCI_LIST_COUNT(mgr->inactivePCIHostdevs, inactive_count);
268 VIR_DEBUG("Test: prepare same hostdevs for diff driver/domain again");
269 if (!virHostdevPreparePCIDevices(mgr, "test_driver1", dom_name, uuid,
270 &hostdevs[2], 1, 0))
271 goto cleanup;
272 CHECK_PCI_LIST_COUNT(mgr->activePCIHostdevs, active_count);
273 CHECK_PCI_LIST_COUNT(mgr->inactivePCIHostdevs, inactive_count);
275 ret = 0;
277 cleanup:
278 return ret;
282 static int
283 testVirHostdevReAttachPCIHostdevs_managed(bool mixed)
285 int ret = -1;
286 size_t active_count, inactive_count, i;
288 for (i = 0; i < nhostdevs; i++) {
289 if (hostdevs[i]->managed != true) {
290 VIR_DEBUG("invalid test");
291 return -1;
295 active_count = virPCIDeviceListCount(mgr->activePCIHostdevs);
296 inactive_count = virPCIDeviceListCount(mgr->inactivePCIHostdevs);
298 VIR_DEBUG("Test 0 hostdevs");
299 virHostdevReAttachPCIDevices(mgr, drv_name, dom_name, NULL, 0, NULL);
300 CHECK_PCI_LIST_COUNT(mgr->activePCIHostdevs, active_count);
301 CHECK_PCI_LIST_COUNT(mgr->inactivePCIHostdevs, inactive_count);
303 VIR_DEBUG("Test >=1 hostdevs");
304 virHostdevReAttachPCIDevices(mgr, drv_name, dom_name,
305 hostdevs, nhostdevs, NULL);
306 CHECK_PCI_LIST_COUNT(mgr->activePCIHostdevs, active_count - nhostdevs);
307 /* If testing a mixed roundtrip, devices are added back to the inactive
308 * list as soon as we detach from the guest */
309 if (mixed)
310 CHECK_PCI_LIST_COUNT(mgr->inactivePCIHostdevs, inactive_count + nhostdevs);
311 else
312 CHECK_PCI_LIST_COUNT(mgr->inactivePCIHostdevs, inactive_count);
314 ret = 0;
316 cleanup:
317 return ret;
321 static int
322 testVirHostdevDetachPCINodeDevice(void)
324 int ret = -1;
325 size_t active_count, inactive_count, i;
327 for (i = 0; i < nhostdevs; i++) {
328 active_count = virPCIDeviceListCount(mgr->activePCIHostdevs);
329 inactive_count = virPCIDeviceListCount(mgr->inactivePCIHostdevs);
330 if (virHostdevPCINodeDeviceDetach(mgr, dev[i]) < 0)
331 goto cleanup;
332 CHECK_PCI_LIST_COUNT(mgr->activePCIHostdevs, active_count);
333 CHECK_PCI_LIST_COUNT(mgr->inactivePCIHostdevs, inactive_count + 1);
336 ret = 0;
338 cleanup:
339 return ret;
342 static int
343 testVirHostdevResetPCINodeDevice(void)
345 int ret = -1;
346 size_t active_count, inactive_count, i;
348 for (i = 0; i < nhostdevs; i++) {
349 active_count = virPCIDeviceListCount(mgr->activePCIHostdevs);
350 inactive_count = virPCIDeviceListCount(mgr->inactivePCIHostdevs);
351 if (virHostdevPCINodeDeviceReset(mgr, dev[i]) < 0)
352 goto cleanup;
353 CHECK_PCI_LIST_COUNT(mgr->activePCIHostdevs, active_count);
354 CHECK_PCI_LIST_COUNT(mgr->inactivePCIHostdevs, inactive_count);
357 ret = 0;
359 cleanup:
360 return ret;
364 static int
365 testVirHostdevReAttachPCINodeDevice(void)
367 int ret = -1;
368 size_t active_count, inactive_count, i;
370 for (i = 0; i < nhostdevs; i++) {
371 active_count = virPCIDeviceListCount(mgr->activePCIHostdevs);
372 inactive_count = virPCIDeviceListCount(mgr->inactivePCIHostdevs);
373 if (virHostdevPCINodeDeviceReAttach(mgr, dev[i]) < 0)
374 goto cleanup;
375 CHECK_PCI_LIST_COUNT(mgr->activePCIHostdevs, active_count);
376 CHECK_PCI_LIST_COUNT(mgr->inactivePCIHostdevs, inactive_count - 1);
379 ret = 0;
381 cleanup:
382 return ret;
386 static int
387 testVirHostdevUpdateActivePCIHostdevs(void)
389 int ret = -1;
390 size_t active_count, inactive_count;
392 active_count = virPCIDeviceListCount(mgr->activePCIHostdevs);
393 inactive_count = virPCIDeviceListCount(mgr->inactivePCIHostdevs);
395 VIR_DEBUG("Test 0 hostdevs");
396 if (virHostdevUpdateActivePCIDevices(mgr, NULL, 0,
397 drv_name, dom_name) < 0)
398 goto cleanup;
399 CHECK_PCI_LIST_COUNT(mgr->activePCIHostdevs, active_count);
400 CHECK_PCI_LIST_COUNT(mgr->inactivePCIHostdevs, inactive_count);
402 VIR_DEBUG("Test >=1 hostdevs");
403 if (virHostdevUpdateActivePCIDevices(mgr, hostdevs, nhostdevs,
404 drv_name, dom_name) < 0)
405 goto cleanup;
406 CHECK_PCI_LIST_COUNT(mgr->activePCIHostdevs, active_count + nhostdevs);
407 CHECK_PCI_LIST_COUNT(mgr->inactivePCIHostdevs, inactive_count);
409 ret = 0;
411 cleanup:
412 return ret;
416 * testVirHostdevRoundtripNoGuest:
417 * @opaque: unused
419 * Perform a roundtrip without ever assigning devices to the guest.
421 * 1. Detach devices from the host
422 * 2. Reattach devices to the host
424 static int
425 testVirHostdevRoundtripNoGuest(const void *opaque ATTRIBUTE_UNUSED)
427 int ret = -1;
429 if (testVirHostdevDetachPCINodeDevice() < 0)
430 goto out;
431 if (testVirHostdevReAttachPCINodeDevice() < 0)
432 goto out;
434 ret = 0;
436 out:
437 return ret;
441 * testVirHostdevRoundtripUnmanaged:
442 * @opaque: unused
444 * Perform a roundtrip with unmanaged devices.
446 * 1. Detach devices from the host
447 * 2. Attach devices to the guest as unmanaged
448 * 3. Detach devices from the guest as unmanaged
449 * 4. Reattach devices to the host
451 static int
452 testVirHostdevRoundtripUnmanaged(const void *opaque ATTRIBUTE_UNUSED)
454 int ret = -1;
456 if (testVirHostdevDetachPCINodeDevice() < 0)
457 goto out;
458 if (testVirHostdevPreparePCIHostdevs_unmanaged() < 0)
459 goto out;
460 if (testVirHostdevReAttachPCIHostdevs_unmanaged() < 0)
461 goto out;
462 if (testVirHostdevReAttachPCINodeDevice() < 0)
463 goto out;
465 ret = 0;
467 out:
468 return ret;
472 * testVirHostdevRoundtripManaged:
473 * @opaque: unused
475 * Perform a roundtrip with managed devices.
477 * 1. Attach devices to the guest as managed
478 * 2. Detach devices from the guest as managed
480 static int
481 testVirHostdevRoundtripManaged(const void *opaque ATTRIBUTE_UNUSED)
483 int ret = -1;
485 if (testVirHostdevPreparePCIHostdevs_managed(false) < 0)
486 goto out;
487 if (testVirHostdevReAttachPCIHostdevs_managed(false) < 0)
488 goto out;
490 ret = 0;
492 out:
493 return ret;
497 * testVirHostdevRoundtripMixed:
498 * @opaque: unused
500 * Perform a roundtrip with managed devices but manually detach the devices
501 * from the host first.
503 * 1. Detach devices from the host
504 * 2. Attach devices to the guest as managed
505 * 3. Detach devices from the guest as managed
506 * 4. Reattach devices to the host
508 static int
509 testVirHostdevRoundtripMixed(const void *opaque ATTRIBUTE_UNUSED)
511 int ret = -1;
513 if (testVirHostdevDetachPCINodeDevice() < 0)
514 goto out;
515 if (testVirHostdevPreparePCIHostdevs_managed(true) < 0)
516 goto out;
517 if (testVirHostdevReAttachPCIHostdevs_managed(true) < 0)
518 goto out;
519 if (testVirHostdevReAttachPCINodeDevice() < 0)
520 goto out;
522 ret = 0;
524 out:
525 return ret;
529 * testVirHostdevOther:
530 * @opaque: unused
532 * Perform other operations on devices.
534 * 1. Reset devices
535 * 2. Update list of active devices
537 static int
538 testVirHostdevOther(const void *opaque ATTRIBUTE_UNUSED)
540 int ret = -1;
542 if (testVirHostdevResetPCINodeDevice() < 0)
543 goto out;
544 if (testVirHostdevUpdateActivePCIHostdevs() < 0)
545 goto out;
547 ret = 0;
549 out:
550 return ret;
553 # define FAKEROOTDIRTEMPLATE abs_builddir "/fakerootdir-XXXXXX"
555 static int
556 mymain(void)
558 int ret = 0;
559 VIR_AUTOFREE(char *) fakerootdir = NULL;
561 if (VIR_STRDUP_QUIET(fakerootdir, FAKEROOTDIRTEMPLATE) < 0) {
562 fprintf(stderr, "Out of memory\n");
563 abort();
566 if (!mkdtemp(fakerootdir)) {
567 fprintf(stderr, "Cannot create fakerootdir");
568 abort();
571 setenv("LIBVIRT_FAKE_ROOT_DIR", fakerootdir, 1);
573 # define DO_TEST(fnc) \
574 do { \
575 VIR_DEBUG("Testing: %s", #fnc); \
576 if (virTestRun(#fnc, fnc, NULL) < 0) \
577 ret = -1; \
578 } while (0)
580 if (myInit() < 0) {
581 fprintf(stderr, "Init data structures failed.");
582 virFileDeleteTree(fakerootdir);
583 return EXIT_FAILURE;
586 DO_TEST(testVirHostdevRoundtripNoGuest);
587 DO_TEST(testVirHostdevRoundtripUnmanaged);
588 DO_TEST(testVirHostdevRoundtripManaged);
589 DO_TEST(testVirHostdevRoundtripMixed);
590 DO_TEST(testVirHostdevOther);
592 myCleanup();
594 if (getenv("LIBVIRT_SKIP_CLEANUP") == NULL)
595 virFileDeleteTree(fakerootdir);
597 return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE;
600 VIR_TEST_MAIN_PRELOAD(mymain, abs_builddir "/.libs/virpcimock.so")
601 #else
603 main(void)
605 return EXIT_AM_SKIP;
607 #endif