Merge lp:~ubuntu-branches/ubuntu/maverick/libvirt/maverick-201009152343 into lp:ubuntu/maverick/libvirt

Proposed by James Westby
Status: Work in progress
Proposed branch: lp:~ubuntu-branches/ubuntu/maverick/libvirt/maverick-201009152343
Merge into: lp:ubuntu/maverick/libvirt
Diff against target: 2282 lines (+2266/-0) (has conflicts)
2 files modified
.pc/9026-Rebuild-network-filter-for-UML-guests-on-updates.patch/src/uml/uml_driver.c (+2211/-0)
debian/patches/9026-Rebuild-network-filter-for-UML-guests-on-updates.patch (+55/-0)
Conflict adding file .pc/9026-Rebuild-network-filter-for-UML-guests-on-updates.patch.  Moved existing file to .pc/9026-Rebuild-network-filter-for-UML-guests-on-updates.patch.moved.
Conflict adding file debian/patches/9026-Rebuild-network-filter-for-UML-guests-on-updates.patch.  Moved existing file to debian/patches/9026-Rebuild-network-filter-for-UML-guests-on-updates.patch.moved.
To merge this branch: bzr merge lp:~ubuntu-branches/ubuntu/maverick/libvirt/maverick-201009152343

Description of the change

The package history in the archive and the history in the bzr branch differ. As the archive is authoritative the history of lp:ubuntu/maverick/libvirt now reflects that and the old bzr branch has been pushed to lp:~ubuntu-branches/ubuntu/maverick/libvirt/maverick-201009152343. A merge should be performed if necessary.

To post a comment you must log in.

Unmerged revisions

105. By Soren Hansen

releasing version 0.8.3-1ubuntu11

104. By Soren Hansen

9026-Rebuild-network-filter-for-UML-guests-on-updates.patch.
NWFilter updates are supposed to be immediate. Add this support to
the UML driver.

103. By Soren Hansen

Merge previous work branch that diverged due to quilt madness.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== added directory '.pc/9026-Rebuild-network-filter-for-UML-guests-on-updates.patch'
=== renamed directory '.pc/9026-Rebuild-network-filter-for-UML-guests-on-updates.patch' => '.pc/9026-Rebuild-network-filter-for-UML-guests-on-updates.patch.moved'
=== added file '.pc/9026-Rebuild-network-filter-for-UML-guests-on-updates.patch/.timestamp'
=== added directory '.pc/9026-Rebuild-network-filter-for-UML-guests-on-updates.patch/src'
=== added directory '.pc/9026-Rebuild-network-filter-for-UML-guests-on-updates.patch/src/uml'
=== added file '.pc/9026-Rebuild-network-filter-for-UML-guests-on-updates.patch/src/uml/uml_driver.c'
--- .pc/9026-Rebuild-network-filter-for-UML-guests-on-updates.patch/src/uml/uml_driver.c 1970-01-01 00:00:00 +0000
+++ .pc/9026-Rebuild-network-filter-for-UML-guests-on-updates.patch/src/uml/uml_driver.c 2010-09-15 23:50:58 +0000
@@ -0,0 +1,2211 @@
1/*
2 * uml_driver.c: core driver methods for managing UML guests
3 *
4 * Copyright (C) 2006-2010 Red Hat, Inc.
5 * Copyright (C) 2006-2008 Daniel P. Berrange
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 *
21 * Author: Daniel P. Berrange <berrange@redhat.com>
22 */
23
24#include <config.h>
25
26#include <sys/types.h>
27#include <sys/poll.h>
28#include <dirent.h>
29#include <limits.h>
30#include <string.h>
31#include <stdio.h>
32#include <stdarg.h>
33#include <stdlib.h>
34#include <unistd.h>
35#include <errno.h>
36#include <sys/utsname.h>
37#include <sys/stat.h>
38#include <fcntl.h>
39#include <signal.h>
40#include <paths.h>
41#include <pwd.h>
42#include <stdio.h>
43#include <sys/wait.h>
44#include <sys/ioctl.h>
45#include <sys/inotify.h>
46#include <sys/un.h>
47
48#include "uml_driver.h"
49#include "uml_conf.h"
50#include "event.h"
51#include "buf.h"
52#include "util.h"
53#include "nodeinfo.h"
54#include "stats_linux.h"
55#include "capabilities.h"
56#include "memory.h"
57#include "uuid.h"
58#include "domain_conf.h"
59#include "datatypes.h"
60#include "logging.h"
61#include "domain_nwfilter.h"
62
63#define VIR_FROM_THIS VIR_FROM_UML
64
65/* For storing short-lived temporary files. */
66#define TEMPDIR LOCAL_STATE_DIR "/cache/libvirt"
67
68typedef struct _umlDomainObjPrivate umlDomainObjPrivate;
69typedef umlDomainObjPrivate *umlDomainObjPrivatePtr;
70struct _umlDomainObjPrivate {
71 int monitor;
72 int monitorWatch;
73};
74
75
76static int umlShutdown(void);
77
78static void *umlDomainObjPrivateAlloc(void)
79{
80 umlDomainObjPrivatePtr priv;
81
82 if (VIR_ALLOC(priv) < 0)
83 return NULL;
84
85 priv->monitor = -1;
86 priv->monitorWatch = -1;
87
88 return priv;
89}
90
91static void umlDomainObjPrivateFree(void *data)
92{
93 umlDomainObjPrivatePtr priv = data;
94
95 VIR_FREE(priv);
96}
97
98
99static void umlDriverLock(struct uml_driver *driver)
100{
101 virMutexLock(&driver->lock);
102}
103static void umlDriverUnlock(struct uml_driver *driver)
104{
105 virMutexUnlock(&driver->lock);
106}
107
108
109static int umlOpenMonitor(struct uml_driver *driver,
110 virDomainObjPtr vm);
111static int umlReadPidFile(struct uml_driver *driver,
112 virDomainObjPtr vm);
113
114static int umlSetCloseExec(int fd) {
115 int flags;
116 if ((flags = fcntl(fd, F_GETFD)) < 0)
117 goto error;
118 flags |= FD_CLOEXEC;
119 if ((fcntl(fd, F_SETFD, flags)) < 0)
120 goto error;
121 return 0;
122 error:
123 VIR_ERROR0(_("Failed to set close-on-exec file descriptor flag"));
124 return -1;
125}
126
127static int umlStartVMDaemon(virConnectPtr conn,
128 struct uml_driver *driver,
129 virDomainObjPtr vm);
130
131static void umlShutdownVMDaemon(virConnectPtr conn,
132 struct uml_driver *driver,
133 virDomainObjPtr vm);
134
135
136static int umlMonitorCommand(const struct uml_driver *driver,
137 const virDomainObjPtr vm,
138 const char *cmd,
139 char **reply);
140
141static struct uml_driver *uml_driver = NULL;
142
143struct umlAutostartData {
144 struct uml_driver *driver;
145 virConnectPtr conn;
146};
147
148static void
149umlAutostartDomain(void *payload, const char *name ATTRIBUTE_UNUSED, void *opaque)
150{
151 virDomainObjPtr vm = payload;
152 const struct umlAutostartData *data = opaque;
153
154 virDomainObjLock(vm);
155 if (vm->autostart &&
156 !virDomainObjIsActive(vm)) {
157 virResetLastError();
158 if (umlStartVMDaemon(data->conn, data->driver, vm) < 0) {
159 virErrorPtr err = virGetLastError();
160 VIR_ERROR(_("Failed to autostart VM '%s': %s"),
161 vm->def->name, err ? err->message : _("unknown error"));
162 }
163 }
164 virDomainObjUnlock(vm);
165}
166
167static void
168umlAutostartConfigs(struct uml_driver *driver) {
169 /* XXX: Figure out a better way todo this. The domain
170 * startup code needs a connection handle in order
171 * to lookup the bridge associated with a virtual
172 * network
173 */
174 virConnectPtr conn = virConnectOpen(driver->privileged ?
175 "uml:///system" :
176 "uml:///session");
177 /* Ignoring NULL conn which is mostly harmless here */
178
179 struct umlAutostartData data = { driver, conn };
180
181 virHashForEach(driver->domains.objs, umlAutostartDomain, &data);
182
183 if (conn)
184 virConnectClose(conn);
185}
186
187
188static int
189umlIdentifyOneChrPTY(struct uml_driver *driver,
190 virDomainObjPtr dom,
191 virDomainChrDefPtr def,
192 const char *dev)
193{
194 char *cmd;
195 char *res = NULL;
196 int retries = 0;
197 if (virAsprintf(&cmd, "config %s%d", dev, def->target.port) < 0) {
198 virReportOOMError();
199 return -1;
200 }
201requery:
202 if (umlMonitorCommand(driver, dom, cmd, &res) < 0)
203 return -1;
204
205 if (res && STRPREFIX(res, "pts:")) {
206 VIR_FREE(def->data.file.path);
207 if ((def->data.file.path = strdup(res + 4)) == NULL) {
208 virReportOOMError();
209 VIR_FREE(res);
210 VIR_FREE(cmd);
211 return -1;
212 }
213 } else if (!res || STRPREFIX(res, "pts")) {
214 /* It can take a while to startup, so retry for
215 upto 5 seconds */
216 /* XXX should do this in a better non-blocking
217 way somehow ...perhaps register a timer */
218 if (retries++ < 50) {
219 usleep(1000*10);
220 goto requery;
221 }
222 }
223
224 VIR_FREE(cmd);
225 VIR_FREE(res);
226 return 0;
227}
228
229static int
230umlIdentifyChrPTY(struct uml_driver *driver,
231 virDomainObjPtr dom)
232{
233 int i;
234
235 if (dom->def->console &&
236 dom->def->console->type == VIR_DOMAIN_CHR_TYPE_PTY)
237 if (umlIdentifyOneChrPTY(driver, dom,
238 dom->def->console, "con") < 0)
239 return -1;
240
241 for (i = 0 ; i < dom->def->nserials; i++)
242 if (dom->def->serials[i]->type == VIR_DOMAIN_CHR_TYPE_PTY &&
243 umlIdentifyOneChrPTY(driver, dom,
244 dom->def->serials[i], "ssl") < 0)
245 return -1;
246
247 return 0;
248}
249
250static void
251umlInotifyEvent(int watch,
252 int fd,
253 int events ATTRIBUTE_UNUSED,
254 void *data)
255{
256 char buf[1024];
257 struct inotify_event *e;
258 int got;
259 char *tmp, *name;
260 struct uml_driver *driver = data;
261 virDomainObjPtr dom;
262
263 umlDriverLock(driver);
264 if (watch != driver->inotifyWatch)
265 goto cleanup;
266
267reread:
268 got = read(fd, buf, sizeof(buf));
269 if (got == -1) {
270 if (errno == EINTR)
271 goto reread;
272 goto cleanup;
273 }
274
275 tmp = buf;
276 while (got) {
277 if (got < sizeof(struct inotify_event))
278 goto cleanup; /* bad */
279
280 e = (struct inotify_event *)tmp;
281 tmp += sizeof(struct inotify_event);
282 got -= sizeof(struct inotify_event);
283
284 if (got < e->len)
285 goto cleanup;
286
287 tmp += e->len;
288 got -= e->len;
289
290 name = (char *)&(e->name);
291
292 dom = virDomainFindByName(&driver->domains, name);
293
294 if (!dom) {
295 continue;
296 }
297
298 if (e->mask & IN_DELETE) {
299 VIR_DEBUG("Got inotify domain shutdown '%s'", name);
300 if (!virDomainObjIsActive(dom)) {
301 virDomainObjUnlock(dom);
302 continue;
303 }
304
305 umlShutdownVMDaemon(NULL, driver, dom);
306 } else if (e->mask & (IN_CREATE | IN_MODIFY)) {
307 VIR_DEBUG("Got inotify domain startup '%s'", name);
308 if (virDomainObjIsActive(dom)) {
309 virDomainObjUnlock(dom);
310 continue;
311 }
312
313 if (umlReadPidFile(driver, dom) < 0) {
314 virDomainObjUnlock(dom);
315 continue;
316 }
317
318 dom->def->id = driver->nextvmid++;
319 dom->state = VIR_DOMAIN_RUNNING;
320
321 if (umlOpenMonitor(driver, dom) < 0) {
322 VIR_WARN0("Could not open monitor for new domain");
323 umlShutdownVMDaemon(NULL, driver, dom);
324 } else if (umlIdentifyChrPTY(driver, dom) < 0) {
325 VIR_WARN0("Could not identify charater devices for new domain");
326 umlShutdownVMDaemon(NULL, driver, dom);
327 }
328 }
329 virDomainObjUnlock(dom);
330 }
331
332cleanup:
333 umlDriverUnlock(driver);
334}
335
336/**
337 * umlStartup:
338 *
339 * Initialization function for the Uml daemon
340 */
341static int
342umlStartup(int privileged) {
343 uid_t uid = geteuid();
344 char *base = NULL;
345 char driverConf[PATH_MAX];
346 char *userdir = NULL;
347
348 if (VIR_ALLOC(uml_driver) < 0)
349 return -1;
350
351 uml_driver->privileged = privileged;
352
353 if (virMutexInit(&uml_driver->lock) < 0) {
354 VIR_FREE(uml_driver);
355 return -1;
356 }
357 umlDriverLock(uml_driver);
358
359 /* Don't have a dom0 so start from 1 */
360 uml_driver->nextvmid = 1;
361 uml_driver->inotifyWatch = -1;
362
363 if (virDomainObjListInit(&uml_driver->domains) < 0)
364 goto error;
365
366 userdir = virGetUserDirectory(uid);
367 if (!userdir)
368 goto error;
369
370 if (privileged) {
371 if (virAsprintf(&uml_driver->logDir,
372 "%s/log/libvirt/uml", LOCAL_STATE_DIR) == -1)
373 goto out_of_memory;
374
375 if ((base = strdup (SYSCONF_DIR "/libvirt")) == NULL)
376 goto out_of_memory;
377 } else {
378
379 if (virAsprintf(&uml_driver->logDir,
380 "%s/.libvirt/uml/log", userdir) == -1)
381 goto out_of_memory;
382
383 if (virAsprintf(&base, "%s/.libvirt", userdir) == -1)
384 goto out_of_memory;
385 }
386
387 if (virAsprintf(&uml_driver->monitorDir,
388 "%s/.uml", userdir) == -1)
389 goto out_of_memory;
390
391 /* Configuration paths are either ~/.libvirt/uml/... (session) or
392 * /etc/libvirt/uml/... (system).
393 */
394 if (snprintf (driverConf, sizeof(driverConf), "%s/uml.conf", base) == -1)
395 goto out_of_memory;
396 driverConf[sizeof(driverConf)-1] = '\0';
397
398 if (virAsprintf(&uml_driver->configDir, "%s/uml", base) == -1)
399 goto out_of_memory;
400
401 if (virAsprintf(&uml_driver->autostartDir, "%s/uml/autostart", base) == -1)
402 goto out_of_memory;
403
404 VIR_FREE(base);
405
406 if ((uml_driver->caps = umlCapsInit()) == NULL)
407 goto out_of_memory;
408
409 uml_driver->caps->privateDataAllocFunc = umlDomainObjPrivateAlloc;
410 uml_driver->caps->privateDataFreeFunc = umlDomainObjPrivateFree;
411
412 if ((uml_driver->inotifyFD = inotify_init()) < 0) {
413 VIR_ERROR0(_("cannot initialize inotify"));
414 goto error;
415 }
416
417 if (virFileMakePath(uml_driver->monitorDir) != 0) {
418 char ebuf[1024];
419 VIR_ERROR(_("Failed to create monitor directory %s: %s"),
420 uml_driver->monitorDir, virStrerror(errno, ebuf, sizeof ebuf));
421 goto error;
422 }
423
424 VIR_INFO("Adding inotify watch on %s", uml_driver->monitorDir);
425 if (inotify_add_watch(uml_driver->inotifyFD,
426 uml_driver->monitorDir,
427 IN_CREATE | IN_MODIFY | IN_DELETE) < 0) {
428 goto error;
429 }
430
431 if ((uml_driver->inotifyWatch =
432 virEventAddHandle(uml_driver->inotifyFD, POLLIN,
433 umlInotifyEvent, uml_driver, NULL)) < 0)
434 goto error;
435
436 if (virDomainLoadAllConfigs(uml_driver->caps,
437 &uml_driver->domains,
438 uml_driver->configDir,
439 uml_driver->autostartDir,
440 0, NULL, NULL) < 0)
441 goto error;
442
443 umlAutostartConfigs(uml_driver);
444
445 umlDriverUnlock(uml_driver);
446 VIR_FREE(userdir);
447
448 return 0;
449
450out_of_memory:
451 VIR_ERROR0(_("umlStartup: out of memory"));
452
453error:
454 VIR_FREE(userdir);
455 VIR_FREE(base);
456 umlDriverUnlock(uml_driver);
457 umlShutdown();
458 return -1;
459}
460
461/**
462 * umlReload:
463 *
464 * Function to restart the Uml daemon, it will recheck the configuration
465 * files and update its state and the networking
466 */
467static int
468umlReload(void) {
469 if (!uml_driver)
470 return 0;
471
472 umlDriverLock(uml_driver);
473 virDomainLoadAllConfigs(uml_driver->caps,
474 &uml_driver->domains,
475 uml_driver->configDir,
476 uml_driver->autostartDir,
477 0, NULL, NULL);
478
479 umlAutostartConfigs(uml_driver);
480 umlDriverUnlock(uml_driver);
481
482 return 0;
483}
484
485/**
486 * umlActive:
487 *
488 * Checks if the Uml daemon is active, i.e. has an active domain or
489 * an active network
490 *
491 * Returns 1 if active, 0 otherwise
492 */
493static int
494umlActive(void) {
495 int active = 0;
496
497 if (!uml_driver)
498 return 0;
499
500 umlDriverLock(uml_driver);
501 active = virDomainObjListNumOfDomains(&uml_driver->domains, 1);
502 umlDriverUnlock(uml_driver);
503
504 return active;
505}
506
507static void
508umlShutdownOneVM(void *payload, const char *name ATTRIBUTE_UNUSED, void *opaque)
509{
510 virDomainObjPtr dom = payload;
511 struct uml_driver *driver = opaque;
512
513 virDomainObjLock(dom);
514 if (virDomainObjIsActive(dom))
515 umlShutdownVMDaemon(NULL, driver, dom);
516 virDomainObjUnlock(dom);
517}
518
519/**
520 * umlShutdown:
521 *
522 * Shutdown the Uml daemon, it will stop all active domains and networks
523 */
524static int
525umlShutdown(void) {
526 if (!uml_driver)
527 return -1;
528
529 umlDriverLock(uml_driver);
530 if (uml_driver->inotifyWatch != -1)
531 virEventRemoveHandle(uml_driver->inotifyWatch);
532 close(uml_driver->inotifyFD);
533 virCapabilitiesFree(uml_driver->caps);
534
535 /* shutdown active VMs
536 * XXX allow them to stay around & reconnect */
537 virHashForEach(uml_driver->domains.objs, umlShutdownOneVM, uml_driver);
538
539 virDomainObjListDeinit(&uml_driver->domains);
540
541 VIR_FREE(uml_driver->logDir);
542 VIR_FREE(uml_driver->configDir);
543 VIR_FREE(uml_driver->autostartDir);
544 VIR_FREE(uml_driver->monitorDir);
545
546 if (uml_driver->brctl)
547 brShutdown(uml_driver->brctl);
548
549 umlDriverUnlock(uml_driver);
550 virMutexDestroy(&uml_driver->lock);
551 VIR_FREE(uml_driver);
552
553 return 0;
554}
555
556
557static int umlReadPidFile(struct uml_driver *driver,
558 virDomainObjPtr vm)
559{
560 int rc = -1;
561 FILE *file;
562 char *pidfile = NULL;
563 int retries = 0;
564
565 vm->pid = -1;
566 if (virAsprintf(&pidfile, "%s/%s/pid",
567 driver->monitorDir, vm->def->name) < 0) {
568 virReportOOMError();
569 return -1;
570 }
571
572reopen:
573 if (!(file = fopen(pidfile, "r"))) {
574 if (errno == ENOENT &&
575 retries++ < 50) {
576 usleep(1000 * 100);
577 goto reopen;
578 }
579 goto cleanup;
580 }
581
582 if (fscanf(file, "%d", &vm->pid) != 1) {
583 errno = EINVAL;
584 fclose(file);
585 goto cleanup;
586 }
587
588 if (fclose(file) < 0)
589 goto cleanup;
590
591 rc = 0;
592
593 cleanup:
594 if (rc != 0)
595 virReportSystemError(errno,
596 _("failed to read pid: %s"),
597 pidfile);
598 VIR_FREE(pidfile);
599 return rc;
600}
601
602static int umlMonitorAddress(const struct uml_driver *driver,
603 virDomainObjPtr vm,
604 struct sockaddr_un *addr) {
605 char *sockname;
606 int retval = 0;
607
608 if (virAsprintf(&sockname, "%s/%s/mconsole",
609 driver->monitorDir, vm->def->name) < 0) {
610 virReportOOMError();
611 return -1;
612 }
613
614 memset(addr, 0, sizeof *addr);
615 addr->sun_family = AF_UNIX;
616 if (virStrcpyStatic(addr->sun_path, sockname) == NULL) {
617 umlReportError(VIR_ERR_INTERNAL_ERROR,
618 _("Unix path %s too long for destination"), sockname);
619 retval = -1;
620 }
621 VIR_FREE(sockname);
622 return retval;
623}
624
625static int umlOpenMonitor(struct uml_driver *driver,
626 virDomainObjPtr vm) {
627 struct sockaddr_un addr;
628 struct stat sb;
629 int retries = 0;
630 umlDomainObjPrivatePtr priv = vm->privateData;
631
632 if (umlMonitorAddress(driver, vm, &addr) < 0)
633 return -1;
634
635 VIR_DEBUG("Dest address for monitor is '%s'", addr.sun_path);
636restat:
637 if (stat(addr.sun_path, &sb) < 0) {
638 if (errno == ENOENT &&
639 retries++ < 50) {
640 usleep(1000 * 100);
641 goto restat;
642 }
643 return -1;
644 }
645
646 if ((priv->monitor = socket(PF_UNIX, SOCK_DGRAM, 0)) < 0) {
647 virReportSystemError(errno,
648 "%s", _("cannot open socket"));
649 return -1;
650 }
651
652 memset(addr.sun_path, 0, sizeof addr.sun_path);
653 sprintf(addr.sun_path + 1, "libvirt-uml-%u", vm->pid);
654 VIR_DEBUG("Reply address for monitor is '%s'", addr.sun_path+1);
655 if (bind(priv->monitor, (struct sockaddr *)&addr, sizeof addr) < 0) {
656 virReportSystemError(errno,
657 "%s", _("cannot bind socket"));
658 close(priv->monitor);
659 priv->monitor = -1;
660 return -1;
661 }
662
663 return 0;
664}
665
666
667#define MONITOR_MAGIC 0xcafebabe
668#define MONITOR_BUFLEN 512
669#define MONITOR_VERSION 2
670
671struct monitor_request {
672 uint32_t magic;
673 uint32_t version;
674 uint32_t length;
675 char data[MONITOR_BUFLEN];
676};
677
678struct monitor_response {
679 uint32_t error;
680 uint32_t extra;
681 uint32_t length;
682 char data[MONITOR_BUFLEN];
683};
684
685
686static int umlMonitorCommand(const struct uml_driver *driver,
687 const virDomainObjPtr vm,
688 const char *cmd,
689 char **reply)
690{
691 struct monitor_request req;
692 struct monitor_response res;
693 char *retdata = NULL;
694 int retlen = 0, ret = 0;
695 struct sockaddr_un addr;
696 unsigned int addrlen;
697 umlDomainObjPrivatePtr priv = vm->privateData;
698
699 VIR_DEBUG("Run command '%s'", cmd);
700
701 *reply = NULL;
702
703 if (umlMonitorAddress(driver, vm, &addr) < 0)
704 return -1;
705
706 memset(&req, 0, sizeof(req));
707 req.magic = MONITOR_MAGIC;
708 req.version = MONITOR_VERSION;
709 req.length = strlen(cmd);
710 if (req.length > (MONITOR_BUFLEN-1)) {
711 virReportSystemError(EINVAL,
712 _("cannot send too long command %s (%d bytes)"),
713 cmd, req.length);
714 return -1;
715 }
716 if (virStrcpyStatic(req.data, cmd) == NULL) {
717 umlReportError(VIR_ERR_INTERNAL_ERROR,
718 _("Command %s too long for destination"), cmd);
719 return -1;
720 }
721
722 if (sendto(priv->monitor, &req, sizeof req, 0,
723 (struct sockaddr *)&addr, sizeof addr) != (sizeof req)) {
724 virReportSystemError(errno,
725 _("cannot send command %s"),
726 cmd);
727 return -1;
728 }
729
730 do {
731 ssize_t nbytes;
732 addrlen = sizeof(addr);
733 nbytes = recvfrom(priv->monitor, &res, sizeof res, 0,
734 (struct sockaddr *)&addr, &addrlen);
735 if (nbytes < 0) {
736 if (errno == EAGAIN || errno == EINTR)
737 continue;
738 virReportSystemError(errno, _("cannot read reply %s"), cmd);
739 goto error;
740 }
741 /* Ensure res.length is safe to read before validating its value. */
742 if (nbytes < offsetof(struct monitor_request, data) ||
743 nbytes < offsetof(struct monitor_request, data) + res.length) {
744 virReportSystemError(0, _("incomplete reply %s"), cmd);
745 goto error;
746 }
747
748 if (VIR_REALLOC_N(retdata, retlen + res.length) < 0) {
749 virReportOOMError();
750 goto error;
751 }
752 memcpy(retdata + retlen, res.data, res.length);
753 retlen += res.length - 1;
754 retdata[retlen] = '\0';
755
756 if (res.error)
757 ret = -1;
758
759 } while (res.extra);
760
761 VIR_DEBUG("Command reply is '%s'", NULLSTR(retdata));
762
763 if (ret < 0)
764 VIR_FREE(retdata);
765 else
766 *reply = retdata;
767
768 return ret;
769
770error:
771 VIR_FREE(retdata);
772 return -1;
773}
774
775
776static int umlCleanupTapDevices(virConnectPtr conn ATTRIBUTE_UNUSED,
777 virDomainObjPtr vm) {
778 int i;
779 int err;
780 int ret = 0;
781 brControl *brctl = NULL;
782 VIR_ERROR0(_("Cleanup tap"));
783 if (brInit(&brctl) < 0)
784 return -1;
785
786 for (i = 0 ; i < vm->def->nnets ; i++) {
787 virDomainNetDefPtr def = vm->def->nets[i];
788
789 if (def->type != VIR_DOMAIN_NET_TYPE_BRIDGE &&
790 def->type != VIR_DOMAIN_NET_TYPE_NETWORK)
791 continue;
792
793 VIR_ERROR(_("Cleanup '%s'"), def->ifname);
794 err = brDeleteTap(brctl, def->ifname);
795 if (err) {
796 VIR_ERROR(_("Cleanup failed %d"), err);
797 ret = -1;
798 }
799 }
800 VIR_ERROR0(_("Cleanup tap done"));
801 brShutdown(brctl);
802 return ret;
803}
804
805static int umlStartVMDaemon(virConnectPtr conn,
806 struct uml_driver *driver,
807 virDomainObjPtr vm) {
808 const char **argv = NULL, **tmp;
809 const char **progenv = NULL;
810 int i, ret;
811 pid_t pid;
812 char *logfile;
813 int logfd = -1;
814 struct stat sb;
815 fd_set keepfd;
816 char ebuf[1024];
817 umlDomainObjPrivatePtr priv = vm->privateData;
818
819 FD_ZERO(&keepfd);
820
821 if (virDomainObjIsActive(vm)) {
822 umlReportError(VIR_ERR_INTERNAL_ERROR, "%s",
823 _("VM is already active"));
824 return -1;
825 }
826
827 if (!vm->def->os.kernel) {
828 umlReportError(VIR_ERR_INTERNAL_ERROR, "%s",
829 _("no kernel specified"));
830 return -1;
831 }
832 /* Make sure the binary we are about to try exec'ing exists.
833 * Technically we could catch the exec() failure, but that's
834 * in a sub-process so its hard to feed back a useful error
835 */
836 if (stat(vm->def->os.kernel, &sb) < 0) {
837 virReportSystemError(errno,
838 _("Cannot find UML kernel %s"),
839 vm->def->os.kernel);
840 return -1;
841 }
842
843 if (virFileMakePath(driver->logDir) != 0) {
844 virReportSystemError(errno,
845 _("cannot create log directory %s"),
846 driver->logDir);
847 return -1;
848 }
849
850 if (virAsprintf(&logfile, "%s/%s.log",
851 driver->logDir, vm->def->name) < 0) {
852 virReportOOMError();
853 return -1;
854 }
855
856 if ((logfd = open(logfile, O_CREAT | O_TRUNC | O_WRONLY,
857 S_IRUSR | S_IWUSR)) < 0) {
858 virReportSystemError(errno,
859 _("failed to create logfile %s"),
860 logfile);
861 VIR_FREE(logfile);
862 return -1;
863 }
864 VIR_FREE(logfile);
865
866 if (umlSetCloseExec(logfd) < 0) {
867 virReportSystemError(errno,
868 "%s", _("Unable to set VM logfile close-on-exec flag"));
869 close(logfd);
870 return -1;
871 }
872
873 if (umlBuildCommandLine(conn, driver, vm, &keepfd,
874 &argv, &progenv) < 0) {
875 close(logfd);
876 virDomainConfVMNWFilterTeardown(vm);
877 umlCleanupTapDevices(conn, vm);
878 return -1;
879 }
880
881 tmp = progenv;
882 while (*tmp) {
883 if (safewrite(logfd, *tmp, strlen(*tmp)) < 0)
884 VIR_WARN("Unable to write envv to logfile: %s",
885 virStrerror(errno, ebuf, sizeof ebuf));
886 if (safewrite(logfd, " ", 1) < 0)
887 VIR_WARN("Unable to write envv to logfile: %s",
888 virStrerror(errno, ebuf, sizeof ebuf));
889 tmp++;
890 }
891 tmp = argv;
892 while (*tmp) {
893 if (safewrite(logfd, *tmp, strlen(*tmp)) < 0)
894 VIR_WARN("Unable to write argv to logfile: %s",
895 virStrerror(errno, ebuf, sizeof ebuf));
896 if (safewrite(logfd, " ", 1) < 0)
897 VIR_WARN("Unable to write argv to logfile: %s",
898 virStrerror(errno, ebuf, sizeof ebuf));
899 tmp++;
900 }
901 if (safewrite(logfd, "\n", 1) < 0)
902 VIR_WARN("Unable to write argv to logfile: %s",
903 virStrerror(errno, ebuf, sizeof ebuf));
904
905 priv->monitor = -1;
906
907 ret = virExecDaemonize(argv, progenv, &keepfd, &pid,
908 -1, &logfd, &logfd,
909 VIR_EXEC_CLEAR_CAPS,
910 NULL, NULL, NULL);
911 close(logfd);
912
913 /*
914 * At the moment, the only thing that populates keepfd is
915 * umlBuildCommandLineChr. We want to close every fd it opens.
916 */
917 for (i = 0; i < FD_SETSIZE; i++)
918 if (FD_ISSET(i, &keepfd))
919 close(i);
920
921 for (i = 0 ; argv[i] ; i++)
922 VIR_FREE(argv[i]);
923 VIR_FREE(argv);
924
925 for (i = 0 ; progenv[i] ; i++)
926 VIR_FREE(progenv[i]);
927 VIR_FREE(progenv);
928
929 if (ret < 0) {
930 virDomainConfVMNWFilterTeardown(vm);
931 umlCleanupTapDevices(conn, vm);
932 }
933
934
935 /* NB we don't mark it running here - we do that async
936 with inotify */
937 /* XXX what if someone else tries to start it again
938 before we get the inotification ? Sounds like
939 trouble.... */
940
941 return ret;
942}
943
944static void umlShutdownVMDaemon(virConnectPtr conn ATTRIBUTE_UNUSED,
945 struct uml_driver *driver ATTRIBUTE_UNUSED,
946 virDomainObjPtr vm)
947{
948 int ret;
949 umlDomainObjPrivatePtr priv = vm->privateData;
950
951 if (!virDomainObjIsActive(vm))
952 return;
953
954 virKillProcess(vm->pid, SIGTERM);
955
956 if (priv->monitor != -1)
957 close(priv->monitor);
958 priv->monitor = -1;
959
960 if ((ret = waitpid(vm->pid, NULL, 0)) != vm->pid) {
961 VIR_WARN("Got unexpected pid %d != %d",
962 ret, vm->pid);
963 }
964
965 vm->pid = -1;
966 vm->def->id = -1;
967 vm->state = VIR_DOMAIN_SHUTOFF;
968
969 virDomainConfVMNWFilterTeardown(vm);
970 umlCleanupTapDevices(conn, vm);
971
972 if (vm->newDef) {
973 virDomainDefFree(vm->def);
974 vm->def = vm->newDef;
975 vm->def->id = -1;
976 vm->newDef = NULL;
977 }
978}
979
980
981static virDrvOpenStatus umlOpen(virConnectPtr conn,
982 virConnectAuthPtr auth ATTRIBUTE_UNUSED,
983 int flags ATTRIBUTE_UNUSED) {
984 if (conn->uri == NULL) {
985 if (uml_driver == NULL)
986 return VIR_DRV_OPEN_DECLINED;
987
988 conn->uri = xmlParseURI(uml_driver->privileged ?
989 "uml:///system" :
990 "uml:///session");
991 if (!conn->uri) {
992 virReportOOMError();
993 return VIR_DRV_OPEN_ERROR;
994 }
995 } else {
996 if (conn->uri->scheme == NULL ||
997 STRNEQ (conn->uri->scheme, "uml"))
998 return VIR_DRV_OPEN_DECLINED;
999
1000 /* Allow remote driver to deal with URIs with hostname server */
1001 if (conn->uri->server != NULL)
1002 return VIR_DRV_OPEN_DECLINED;
1003
1004
1005 /* Check path and tell them correct path if they made a mistake */
1006 if (uml_driver->privileged) {
1007 if (STRNEQ (conn->uri->path, "/system") &&
1008 STRNEQ (conn->uri->path, "/session")) {
1009 umlReportError(VIR_ERR_INTERNAL_ERROR,
1010 _("unexpected UML URI path '%s', try uml:///system"),
1011 conn->uri->path);
1012 return VIR_DRV_OPEN_ERROR;
1013 }
1014 } else {
1015 if (STRNEQ (conn->uri->path, "/session")) {
1016 umlReportError(VIR_ERR_INTERNAL_ERROR,
1017 _("unexpected UML URI path '%s', try uml:///session"),
1018 conn->uri->path);
1019 return VIR_DRV_OPEN_ERROR;
1020 }
1021 }
1022
1023 /* URI was good, but driver isn't active */
1024 if (uml_driver == NULL) {
1025 umlReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1026 _("uml state driver is not active"));
1027 return VIR_DRV_OPEN_ERROR;
1028 }
1029 }
1030
1031 conn->privateData = uml_driver;
1032
1033 return VIR_DRV_OPEN_SUCCESS;
1034}
1035
1036static int umlClose(virConnectPtr conn) {
1037 /*struct uml_driver *driver = conn->privateData;*/
1038
1039 conn->privateData = NULL;
1040
1041 return 0;
1042}
1043
1044static const char *umlGetType(virConnectPtr conn ATTRIBUTE_UNUSED) {
1045 return "UML";
1046}
1047
1048
1049static int umlIsSecure(virConnectPtr conn ATTRIBUTE_UNUSED)
1050{
1051 /* Trivially secure, since always inside the daemon */
1052 return 1;
1053}
1054
1055
1056static int umlIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED)
1057{
1058 /* Not encrypted, but remote driver takes care of that */
1059 return 0;
1060}
1061
1062
1063static char *umlGetCapabilities(virConnectPtr conn) {
1064 struct uml_driver *driver = (struct uml_driver *)conn->privateData;
1065 char *xml;
1066
1067 umlDriverLock(driver);
1068 if ((xml = virCapabilitiesFormatXML(driver->caps)) == NULL)
1069 virReportOOMError();
1070 umlDriverUnlock(driver);
1071
1072 return xml;
1073}
1074
1075
1076
1077static int umlGetProcessInfo(unsigned long long *cpuTime, int pid) {
1078 char proc[PATH_MAX];
1079 FILE *pidinfo;
1080 unsigned long long usertime, systime;
1081
1082 if (snprintf(proc, sizeof(proc), "/proc/%d/stat", pid) >= (int)sizeof(proc)) {
1083 return -1;
1084 }
1085
1086 if (!(pidinfo = fopen(proc, "r"))) {
1087 /*printf("cannot read pid info");*/
1088 /* VM probably shut down, so fake 0 */
1089 *cpuTime = 0;
1090 return 0;
1091 }
1092
1093 if (fscanf(pidinfo, "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %llu %llu", &usertime, &systime) != 2) {
1094 umlDebug("not enough arg");
1095 fclose(pidinfo);
1096 return -1;
1097 }
1098
1099 /* We got jiffies
1100 * We want nanoseconds
1101 * _SC_CLK_TCK is jiffies per second
1102 * So calulate thus....
1103 */
1104 *cpuTime = 1000ull * 1000ull * 1000ull * (usertime + systime) / (unsigned long long)sysconf(_SC_CLK_TCK);
1105
1106 umlDebug("Got %llu %llu %llu", usertime, systime, *cpuTime);
1107
1108 fclose(pidinfo);
1109
1110 return 0;
1111}
1112
1113
1114static virDomainPtr umlDomainLookupByID(virConnectPtr conn,
1115 int id) {
1116 struct uml_driver *driver = (struct uml_driver *)conn->privateData;
1117 virDomainObjPtr vm;
1118 virDomainPtr dom = NULL;
1119
1120 umlDriverLock(driver);
1121 vm = virDomainFindByID(&driver->domains, id);
1122 umlDriverUnlock(driver);
1123
1124 if (!vm) {
1125 umlReportError(VIR_ERR_NO_DOMAIN, NULL);
1126 goto cleanup;
1127 }
1128
1129 dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
1130 if (dom) dom->id = vm->def->id;
1131
1132cleanup:
1133 if (vm)
1134 virDomainObjUnlock(vm);
1135 return dom;
1136}
1137
1138static virDomainPtr umlDomainLookupByUUID(virConnectPtr conn,
1139 const unsigned char *uuid) {
1140 struct uml_driver *driver = (struct uml_driver *)conn->privateData;
1141 virDomainObjPtr vm;
1142 virDomainPtr dom = NULL;
1143
1144 umlDriverLock(driver);
1145 vm = virDomainFindByUUID(&driver->domains, uuid);
1146 umlDriverUnlock(driver);
1147
1148 if (!vm) {
1149 umlReportError(VIR_ERR_NO_DOMAIN, NULL);
1150 goto cleanup;
1151 }
1152
1153 dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
1154 if (dom) dom->id = vm->def->id;
1155
1156cleanup:
1157 if (vm)
1158 virDomainObjUnlock(vm);
1159 return dom;
1160}
1161
1162static virDomainPtr umlDomainLookupByName(virConnectPtr conn,
1163 const char *name) {
1164 struct uml_driver *driver = (struct uml_driver *)conn->privateData;
1165 virDomainObjPtr vm;
1166 virDomainPtr dom = NULL;
1167
1168 umlDriverLock(driver);
1169 vm = virDomainFindByName(&driver->domains, name);
1170 umlDriverUnlock(driver);
1171
1172 if (!vm) {
1173 umlReportError(VIR_ERR_NO_DOMAIN, NULL);
1174 goto cleanup;
1175 }
1176
1177 dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
1178 if (dom) dom->id = vm->def->id;
1179
1180cleanup:
1181 if (vm)
1182 virDomainObjUnlock(vm);
1183 return dom;
1184}
1185
1186
1187static int umlDomainIsActive(virDomainPtr dom)
1188{
1189 struct uml_driver *driver = dom->conn->privateData;
1190 virDomainObjPtr obj;
1191 int ret = -1;
1192
1193 umlDriverLock(driver);
1194 obj = virDomainFindByUUID(&driver->domains, dom->uuid);
1195 umlDriverUnlock(driver);
1196 if (!obj) {
1197 umlReportError(VIR_ERR_NO_DOMAIN, NULL);
1198 goto cleanup;
1199 }
1200 ret = virDomainObjIsActive(obj);
1201
1202cleanup:
1203 if (obj)
1204 virDomainObjUnlock(obj);
1205 return ret;
1206}
1207
1208
1209static int umlDomainIsPersistent(virDomainPtr dom)
1210{
1211 struct uml_driver *driver = dom->conn->privateData;
1212 virDomainObjPtr obj;
1213 int ret = -1;
1214
1215 umlDriverLock(driver);
1216 obj = virDomainFindByUUID(&driver->domains, dom->uuid);
1217 umlDriverUnlock(driver);
1218 if (!obj) {
1219 umlReportError(VIR_ERR_NO_DOMAIN, NULL);
1220 goto cleanup;
1221 }
1222 ret = obj->persistent;
1223
1224cleanup:
1225 if (obj)
1226 virDomainObjUnlock(obj);
1227 return ret;
1228}
1229
1230
1231static int umlGetVersion(virConnectPtr conn, unsigned long *version) {
1232 struct uml_driver *driver = conn->privateData;
1233 struct utsname ut;
1234 int ret = -1;
1235
1236 umlDriverLock(driver);
1237
1238 if (driver->umlVersion == 0) {
1239 uname(&ut);
1240
1241 if (virParseVersionString(ut.release, &driver->umlVersion) < 0) {
1242 umlReportError(VIR_ERR_INTERNAL_ERROR,
1243 _("cannot parse version %s"), ut.release);
1244 goto cleanup;
1245 }
1246 }
1247
1248 *version = driver->umlVersion;
1249 ret = 0;
1250
1251cleanup:
1252 umlDriverUnlock(driver);
1253 return ret;
1254}
1255
1256static int umlListDomains(virConnectPtr conn, int *ids, int nids) {
1257 struct uml_driver *driver = conn->privateData;
1258 int n;
1259
1260 umlDriverLock(driver);
1261 n = virDomainObjListGetActiveIDs(&driver->domains, ids, nids);
1262 umlDriverUnlock(driver);
1263
1264 return n;
1265}
1266static int umlNumDomains(virConnectPtr conn) {
1267 struct uml_driver *driver = conn->privateData;
1268 int n;
1269
1270 umlDriverLock(driver);
1271 n = virDomainObjListNumOfDomains(&driver->domains, 1);
1272 umlDriverUnlock(driver);
1273
1274 return n;
1275}
1276static virDomainPtr umlDomainCreate(virConnectPtr conn, const char *xml,
1277 unsigned int flags) {
1278 struct uml_driver *driver = conn->privateData;
1279 virDomainDefPtr def;
1280 virDomainObjPtr vm = NULL;
1281 virDomainPtr dom = NULL;
1282
1283 virCheckFlags(0, NULL);
1284
1285 umlDriverLock(driver);
1286 if (!(def = virDomainDefParseString(driver->caps, xml,
1287 VIR_DOMAIN_XML_INACTIVE)))
1288 goto cleanup;
1289
1290 if (virDomainObjIsDuplicate(&driver->domains, def, 1) < 0)
1291 goto cleanup;
1292
1293 if (!(vm = virDomainAssignDef(driver->caps,
1294 &driver->domains,
1295 def, false)))
1296 goto cleanup;
1297 def = NULL;
1298
1299 if (umlStartVMDaemon(conn, driver, vm) < 0) {
1300 virDomainRemoveInactive(&driver->domains,
1301 vm);
1302 vm = NULL;
1303 goto cleanup;
1304 }
1305
1306 dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
1307 if (dom) dom->id = vm->def->id;
1308
1309cleanup:
1310 virDomainDefFree(def);
1311 if (vm)
1312 virDomainObjUnlock(vm);
1313 umlDriverUnlock(driver);
1314 return dom;
1315}
1316
1317
1318static int umlDomainShutdown(virDomainPtr dom) {
1319 struct uml_driver *driver = dom->conn->privateData;
1320 virDomainObjPtr vm;
1321 char *info = NULL;
1322 int ret = -1;
1323
1324 umlDriverLock(driver);
1325 vm = virDomainFindByID(&driver->domains, dom->id);
1326 umlDriverUnlock(driver);
1327 if (!vm) {
1328 umlReportError(VIR_ERR_INVALID_DOMAIN,
1329 _("no domain with matching id %d"), dom->id);
1330 goto cleanup;
1331 }
1332
1333#if 0
1334 if (umlMonitorCommand(driver, vm, "system_powerdown", &info) < 0) {
1335 umlReportError(VIR_ERR_OPERATION_FAILED, "%s",
1336 _("shutdown operation failed"));
1337 goto cleanup;
1338 }
1339 ret = 0;
1340#endif
1341
1342cleanup:
1343 VIR_FREE(info);
1344 if (vm)
1345 virDomainObjUnlock(vm);
1346 return ret;
1347}
1348
1349
1350static int umlDomainDestroy(virDomainPtr dom) {
1351 struct uml_driver *driver = dom->conn->privateData;
1352 virDomainObjPtr vm;
1353 int ret = -1;
1354
1355 umlDriverLock(driver);
1356 vm = virDomainFindByID(&driver->domains, dom->id);
1357 if (!vm) {
1358 umlReportError(VIR_ERR_INVALID_DOMAIN,
1359 _("no domain with matching id %d"), dom->id);
1360 goto cleanup;
1361 }
1362
1363 umlShutdownVMDaemon(dom->conn, driver, vm);
1364 if (!vm->persistent) {
1365 virDomainRemoveInactive(&driver->domains,
1366 vm);
1367 vm = NULL;
1368 }
1369 ret = 0;
1370
1371cleanup:
1372 if (vm)
1373 virDomainObjUnlock(vm);
1374 umlDriverUnlock(driver);
1375 return ret;
1376}
1377
1378
1379static char *umlDomainGetOSType(virDomainPtr dom) {
1380 struct uml_driver *driver = dom->conn->privateData;
1381 virDomainObjPtr vm;
1382 char *type = NULL;
1383
1384 umlDriverLock(driver);
1385 vm = virDomainFindByUUID(&driver->domains, dom->uuid);
1386 umlDriverUnlock(driver);
1387 if (!vm) {
1388 umlReportError(VIR_ERR_INVALID_DOMAIN, "%s",
1389 _("no domain with matching uuid"));
1390 goto cleanup;
1391 }
1392
1393 if (!(type = strdup(vm->def->os.type)))
1394 virReportOOMError();
1395
1396cleanup:
1397 if (vm)
1398 virDomainObjUnlock(vm);
1399 return type;
1400}
1401
1402/* Returns max memory in kb, 0 if error */
1403static unsigned long umlDomainGetMaxMemory(virDomainPtr dom) {
1404 struct uml_driver *driver = dom->conn->privateData;
1405 virDomainObjPtr vm;
1406 unsigned long ret = 0;
1407
1408 umlDriverLock(driver);
1409 vm = virDomainFindByUUID(&driver->domains, dom->uuid);
1410 umlDriverUnlock(driver);
1411
1412 if (!vm) {
1413 char uuidstr[VIR_UUID_STRING_BUFLEN];
1414
1415 virUUIDFormat(dom->uuid, uuidstr);
1416 umlReportError(VIR_ERR_INVALID_DOMAIN,
1417 _("no domain with matching uuid '%s'"), uuidstr);
1418 goto cleanup;
1419 }
1420 ret = vm->def->maxmem;
1421
1422cleanup:
1423 if (vm)
1424 virDomainObjUnlock(vm);
1425 return ret;
1426}
1427
1428static int umlDomainSetMaxMemory(virDomainPtr dom, unsigned long newmax) {
1429 struct uml_driver *driver = dom->conn->privateData;
1430 virDomainObjPtr vm;
1431 int ret = -1;
1432
1433 umlDriverLock(driver);
1434 vm = virDomainFindByUUID(&driver->domains, dom->uuid);
1435 umlDriverUnlock(driver);
1436
1437 if (!vm) {
1438 char uuidstr[VIR_UUID_STRING_BUFLEN];
1439
1440 virUUIDFormat(dom->uuid, uuidstr);
1441 umlReportError(VIR_ERR_INVALID_DOMAIN,
1442 _("no domain with matching uuid '%s'"), uuidstr);
1443 goto cleanup;
1444 }
1445
1446 if (newmax < vm->def->memory) {
1447 umlReportError(VIR_ERR_INVALID_ARG, "%s",
1448 _("cannot set max memory lower than current memory"));
1449 goto cleanup;
1450 }
1451
1452 vm->def->maxmem = newmax;
1453 ret = 0;
1454
1455cleanup:
1456 if (vm)
1457 virDomainObjUnlock(vm);
1458 return ret;
1459}
1460
1461static int umlDomainSetMemory(virDomainPtr dom, unsigned long newmem) {
1462 struct uml_driver *driver = dom->conn->privateData;
1463 virDomainObjPtr vm;
1464 int ret = -1;
1465
1466 umlDriverLock(driver);
1467 vm = virDomainFindByUUID(&driver->domains, dom->uuid);
1468 umlDriverUnlock(driver);
1469
1470 if (!vm) {
1471 char uuidstr[VIR_UUID_STRING_BUFLEN];
1472
1473 virUUIDFormat(dom->uuid, uuidstr);
1474 umlReportError(VIR_ERR_INVALID_DOMAIN,
1475 _("no domain with matching uuid '%s'"), uuidstr);
1476 goto cleanup;
1477 }
1478
1479 if (virDomainObjIsActive(vm)) {
1480 umlReportError(VIR_ERR_NO_SUPPORT, "%s",
1481 _("cannot set memory of an active domain"));
1482 goto cleanup;
1483 }
1484
1485 if (newmem > vm->def->maxmem) {
1486 umlReportError(VIR_ERR_INVALID_ARG, "%s",
1487 _("cannot set memory higher than max memory"));
1488 goto cleanup;
1489 }
1490
1491 vm->def->memory = newmem;
1492 ret = 0;
1493
1494cleanup:
1495 if (vm)
1496 virDomainObjUnlock(vm);
1497 return ret;
1498}
1499
1500static int umlDomainGetInfo(virDomainPtr dom,
1501 virDomainInfoPtr info) {
1502 struct uml_driver *driver = dom->conn->privateData;
1503 virDomainObjPtr vm;
1504 int ret = -1;
1505
1506 umlDriverLock(driver);
1507 vm = virDomainFindByUUID(&driver->domains, dom->uuid);
1508 umlDriverUnlock(driver);
1509
1510 if (!vm) {
1511 umlReportError(VIR_ERR_INVALID_DOMAIN, "%s",
1512 _("no domain with matching uuid"));
1513 goto cleanup;
1514 }
1515
1516 info->state = vm->state;
1517
1518 if (!virDomainObjIsActive(vm)) {
1519 info->cpuTime = 0;
1520 } else {
1521 if (umlGetProcessInfo(&(info->cpuTime), vm->pid) < 0) {
1522 umlReportError(VIR_ERR_OPERATION_FAILED, "%s",
1523 _("cannot read cputime for domain"));
1524 goto cleanup;
1525 }
1526 }
1527
1528 info->maxMem = vm->def->maxmem;
1529 info->memory = vm->def->memory;
1530 info->nrVirtCpu = vm->def->vcpus;
1531 ret = 0;
1532
1533cleanup:
1534 if (vm)
1535 virDomainObjUnlock(vm);
1536 return ret;
1537}
1538
1539
1540static char *umlDomainDumpXML(virDomainPtr dom,
1541 int flags ATTRIBUTE_UNUSED) {
1542 struct uml_driver *driver = dom->conn->privateData;
1543 virDomainObjPtr vm;
1544 char *ret = NULL;
1545
1546 umlDriverLock(driver);
1547 vm = virDomainFindByUUID(&driver->domains, dom->uuid);
1548 umlDriverUnlock(driver);
1549
1550 if (!vm) {
1551 umlReportError(VIR_ERR_INVALID_DOMAIN, "%s",
1552 _("no domain with matching uuid"));
1553 goto cleanup;
1554 }
1555
1556 ret = virDomainDefFormat((flags & VIR_DOMAIN_XML_INACTIVE) && vm->newDef ?
1557 vm->newDef : vm->def,
1558 flags);
1559
1560cleanup:
1561 if (vm)
1562 virDomainObjUnlock(vm);
1563 return ret;
1564}
1565
1566
1567static int umlListDefinedDomains(virConnectPtr conn,
1568 char **const names, int nnames) {
1569 struct uml_driver *driver = conn->privateData;
1570 int n;
1571
1572 umlDriverLock(driver);
1573 n = virDomainObjListGetInactiveNames(&driver->domains, names, nnames);
1574 umlDriverUnlock(driver);
1575
1576 return n;
1577}
1578
1579static int umlNumDefinedDomains(virConnectPtr conn) {
1580 struct uml_driver *driver = conn->privateData;
1581 int n;
1582
1583 umlDriverLock(driver);
1584 n = virDomainObjListNumOfDomains(&driver->domains, 0);
1585 umlDriverUnlock(driver);
1586
1587 return n;
1588}
1589
1590
1591static int umlDomainStartWithFlags(virDomainPtr dom, unsigned int flags) {
1592 struct uml_driver *driver = dom->conn->privateData;
1593 virDomainObjPtr vm;
1594 int ret = -1;
1595
1596 virCheckFlags(0, -1);
1597
1598 umlDriverLock(driver);
1599 vm = virDomainFindByUUID(&driver->domains, dom->uuid);
1600
1601 if (!vm) {
1602 umlReportError(VIR_ERR_INVALID_DOMAIN, "%s",
1603 _("no domain with matching uuid"));
1604 goto cleanup;
1605 }
1606
1607 ret = umlStartVMDaemon(dom->conn, driver, vm);
1608
1609cleanup:
1610 if (vm)
1611 virDomainObjUnlock(vm);
1612 umlDriverUnlock(driver);
1613 return ret;
1614}
1615
1616static int umlDomainStart(virDomainPtr dom) {
1617 return umlDomainStartWithFlags(dom, 0);
1618}
1619
1620static virDomainPtr umlDomainDefine(virConnectPtr conn, const char *xml) {
1621 struct uml_driver *driver = conn->privateData;
1622 virDomainDefPtr def;
1623 virDomainObjPtr vm = NULL;
1624 virDomainPtr dom = NULL;
1625
1626 umlDriverLock(driver);
1627 if (!(def = virDomainDefParseString(driver->caps, xml,
1628 VIR_DOMAIN_XML_INACTIVE)))
1629 goto cleanup;
1630
1631 if (virDomainObjIsDuplicate(&driver->domains, def, 0) < 0)
1632 goto cleanup;
1633
1634 if (!(vm = virDomainAssignDef(driver->caps,
1635 &driver->domains,
1636 def, false)))
1637 goto cleanup;
1638 def = NULL;
1639 vm->persistent = 1;
1640
1641 if (virDomainSaveConfig(driver->configDir,
1642 vm->newDef ? vm->newDef : vm->def) < 0) {
1643 virDomainRemoveInactive(&driver->domains,
1644 vm);
1645 vm = NULL;
1646 goto cleanup;
1647 }
1648
1649 dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
1650 if (dom) dom->id = vm->def->id;
1651
1652cleanup:
1653 virDomainDefFree(def);
1654 if (vm)
1655 virDomainObjUnlock(vm);
1656 umlDriverUnlock(driver);
1657 return dom;
1658}
1659
1660static int umlDomainUndefine(virDomainPtr dom) {
1661 struct uml_driver *driver = dom->conn->privateData;
1662 virDomainObjPtr vm;
1663 int ret = -1;
1664
1665 umlDriverLock(driver);
1666 vm = virDomainFindByUUID(&driver->domains, dom->uuid);
1667 if (!vm) {
1668 umlReportError(VIR_ERR_INVALID_DOMAIN, "%s",
1669 _("no domain with matching uuid"));
1670 goto cleanup;
1671 }
1672
1673 if (virDomainObjIsActive(vm)) {
1674 umlReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1675 _("cannot delete active domain"));
1676 goto cleanup;
1677 }
1678
1679 if (!vm->persistent) {
1680 umlReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1681 _("cannot undefine transient domain"));
1682 goto cleanup;
1683 }
1684
1685 if (virDomainDeleteConfig(driver->configDir, driver->autostartDir, vm) < 0)
1686 goto cleanup;
1687
1688 virDomainRemoveInactive(&driver->domains,
1689 vm);
1690 vm = NULL;
1691 ret = 0;
1692
1693cleanup:
1694 if (vm)
1695 virDomainObjUnlock(vm);
1696 umlDriverUnlock(driver);
1697 return ret;
1698}
1699
1700
1701static int umlDomainAttachUmlDisk(struct uml_driver *driver,
1702 virDomainObjPtr vm,
1703 virDomainDiskDefPtr disk)
1704{
1705 int i;
1706 char *cmd = NULL;
1707 char *reply = NULL;
1708
1709 for (i = 0 ; i < vm->def->ndisks ; i++) {
1710 if (STREQ(vm->def->disks[i]->dst, disk->dst)) {
1711 umlReportError(VIR_ERR_OPERATION_FAILED,
1712 _("target %s already exists"), disk->dst);
1713 return -1;
1714 }
1715 }
1716
1717 if (!disk->src) {
1718 umlReportError(VIR_ERR_INTERNAL_ERROR,
1719 "%s", _("disk source path is missing"));
1720 goto error;
1721 }
1722
1723 if (virAsprintf(&cmd, "config %s=%s", disk->dst, disk->src) < 0) {
1724 virReportOOMError();
1725 return -1;
1726 }
1727
1728 if (umlMonitorCommand(driver, vm, cmd, &reply) < 0)
1729 goto error;
1730
1731 if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks+1) < 0) {
1732 virReportOOMError();
1733 goto error;
1734 }
1735
1736 virDomainDiskInsertPreAlloced(vm->def, disk);
1737
1738 VIR_FREE(reply);
1739 VIR_FREE(cmd);
1740
1741 return 0;
1742
1743error:
1744
1745 VIR_FREE(reply);
1746 VIR_FREE(cmd);
1747
1748 return -1;
1749}
1750
1751
1752static int umlDomainAttachDevice(virDomainPtr dom, const char *xml)
1753{
1754 struct uml_driver *driver = dom->conn->privateData;
1755 virDomainObjPtr vm;
1756 virDomainDeviceDefPtr dev = NULL;
1757 int ret = -1;
1758
1759 umlDriverLock(driver);
1760
1761 vm = virDomainFindByUUID(&driver->domains, dom->uuid);
1762 if (!vm) {
1763 char uuidstr[VIR_UUID_STRING_BUFLEN];
1764 virUUIDFormat(dom->uuid, uuidstr);
1765 umlReportError(VIR_ERR_NO_DOMAIN,
1766 _("no domain with matching uuid '%s'"), uuidstr);
1767 goto cleanup;
1768 }
1769
1770 if (!virDomainObjIsActive(vm)) {
1771 umlReportError(VIR_ERR_OPERATION_INVALID,
1772 "%s", _("cannot attach device on inactive domain"));
1773 goto cleanup;
1774 }
1775
1776 dev = virDomainDeviceDefParse(driver->caps, vm->def, xml,
1777 VIR_DOMAIN_XML_INACTIVE);
1778
1779 if (dev == NULL)
1780 goto cleanup;
1781
1782 if (dev->type == VIR_DOMAIN_DEVICE_DISK) {
1783 if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_UML) {
1784 ret = umlDomainAttachUmlDisk(driver, vm, dev->data.disk);
1785 if (ret == 0)
1786 dev->data.disk = NULL;
1787 } else {
1788 umlReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1789 _("disk bus '%s' cannot be hotplugged."),
1790 virDomainDiskBusTypeToString(dev->data.disk->bus));
1791 }
1792 } else {
1793 umlReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1794 _("device type '%s' cannot be attached"),
1795 virDomainDeviceTypeToString(dev->type));
1796 goto cleanup;
1797 }
1798
1799cleanup:
1800
1801 virDomainDeviceDefFree(dev);
1802 if (vm)
1803 virDomainObjUnlock(vm);
1804 umlDriverUnlock(driver);
1805 return ret;
1806}
1807
1808
1809static int umlDomainAttachDeviceFlags(virDomainPtr dom,
1810 const char *xml,
1811 unsigned int flags) {
1812 if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
1813 umlReportError(VIR_ERR_OPERATION_INVALID,
1814 "%s", _("cannot modify the persistent configuration of a domain"));
1815 return -1;
1816 }
1817
1818 return umlDomainAttachDevice(dom, xml);
1819}
1820
1821
1822static int umlDomainDetachUmlDisk(struct uml_driver *driver,
1823 virDomainObjPtr vm,
1824 virDomainDeviceDefPtr dev)
1825{
1826 int i, ret = -1;
1827 virDomainDiskDefPtr detach = NULL;
1828 char *cmd;
1829 char *reply;
1830
1831 for (i = 0 ; i < vm->def->ndisks ; i++) {
1832 if (STREQ(vm->def->disks[i]->dst, dev->data.disk->dst)) {
1833 break;
1834 }
1835 }
1836
1837 if (i == vm->def->ndisks) {
1838 umlReportError(VIR_ERR_OPERATION_FAILED,
1839 _("disk %s not found"), dev->data.disk->dst);
1840 return -1;
1841 }
1842
1843 detach = vm->def->disks[i];
1844
1845 if (virAsprintf(&cmd, "remove %s", detach->dst) < 0) {
1846 virReportOOMError();
1847 return -1;
1848 }
1849
1850 if (umlMonitorCommand(driver, vm, cmd, &reply) < 0)
1851 goto cleanup;
1852
1853 virDomainDiskRemove(vm->def, i);
1854
1855 virDomainDiskDefFree(detach);
1856
1857 ret = 0;
1858
1859 VIR_FREE(reply);
1860
1861cleanup:
1862 VIR_FREE(cmd);
1863
1864 return ret;
1865}
1866
1867
1868static int umlDomainDetachDevice(virDomainPtr dom, const char *xml) {
1869 struct uml_driver *driver = dom->conn->privateData;
1870 virDomainObjPtr vm;
1871 virDomainDeviceDefPtr dev = NULL;
1872 int ret = -1;
1873
1874 umlDriverLock(driver);
1875 vm = virDomainFindByUUID(&driver->domains, dom->uuid);
1876 if (!vm) {
1877 char uuidstr[VIR_UUID_STRING_BUFLEN];
1878 virUUIDFormat(dom->uuid, uuidstr);
1879 umlReportError(VIR_ERR_NO_DOMAIN,
1880 _("no domain with matching uuid '%s'"), uuidstr);
1881 goto cleanup;
1882 }
1883
1884 if (!virDomainObjIsActive(vm)) {
1885 umlReportError(VIR_ERR_OPERATION_INVALID,
1886 "%s", _("cannot detach device on inactive domain"));
1887 goto cleanup;
1888 }
1889
1890 dev = virDomainDeviceDefParse(driver->caps, vm->def, xml,
1891 VIR_DOMAIN_XML_INACTIVE);
1892 if (dev == NULL)
1893 goto cleanup;
1894
1895 if (dev->type == VIR_DOMAIN_DEVICE_DISK &&
1896 dev->data.disk->device == VIR_DOMAIN_DISK_DEVICE_DISK) {
1897 if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_UML)
1898 ret = umlDomainDetachUmlDisk(driver, vm, dev);
1899 else {
1900 umlReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
1901 _("This type of disk cannot be hot unplugged"));
1902 }
1903 } else {
1904 umlReportError(VIR_ERR_CONFIG_UNSUPPORTED,
1905 "%s", _("This type of device cannot be hot unplugged"));
1906 }
1907
1908cleanup:
1909 virDomainDeviceDefFree(dev);
1910 if (vm)
1911 virDomainObjUnlock(vm);
1912 umlDriverUnlock(driver);
1913 return ret;
1914}
1915
1916
1917static int umlDomainDetachDeviceFlags(virDomainPtr dom,
1918 const char *xml,
1919 unsigned int flags) {
1920 if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
1921 umlReportError(VIR_ERR_OPERATION_INVALID,
1922 "%s", _("cannot modify the persistent configuration of a domain"));
1923 return -1;
1924 }
1925
1926 return umlDomainDetachDevice(dom, xml);
1927}
1928
1929
1930static int umlDomainGetAutostart(virDomainPtr dom,
1931 int *autostart) {
1932 struct uml_driver *driver = dom->conn->privateData;
1933 virDomainObjPtr vm;
1934 int ret = -1;
1935
1936 umlDriverLock(driver);
1937 vm = virDomainFindByUUID(&driver->domains, dom->uuid);
1938
1939 if (!vm) {
1940 umlReportError(VIR_ERR_INVALID_DOMAIN, "%s",
1941 _("no domain with matching uuid"));
1942 goto cleanup;
1943 }
1944
1945 *autostart = vm->autostart;
1946 ret = 0;
1947
1948cleanup:
1949 if (vm)
1950 virDomainObjUnlock(vm);
1951 umlDriverUnlock(driver);
1952 return ret;
1953}
1954
1955static int umlDomainSetAutostart(virDomainPtr dom,
1956 int autostart) {
1957 struct uml_driver *driver = dom->conn->privateData;
1958 virDomainObjPtr vm;
1959 char *configFile = NULL, *autostartLink = NULL;
1960 int ret = -1;
1961
1962 umlDriverLock(driver);
1963 vm = virDomainFindByUUID(&driver->domains, dom->uuid);
1964
1965 if (!vm) {
1966 umlReportError(VIR_ERR_INVALID_DOMAIN, "%s",
1967 _("no domain with matching uuid"));
1968 goto cleanup;
1969 }
1970
1971 if (!vm->persistent) {
1972 umlReportError(VIR_ERR_INTERNAL_ERROR, "%s",
1973 _("cannot set autostart for transient domain"));
1974 goto cleanup;
1975 }
1976
1977 autostart = (autostart != 0);
1978
1979 if (vm->autostart != autostart) {
1980 if ((configFile = virDomainConfigFile(driver->configDir, vm->def->name)) == NULL)
1981 goto cleanup;
1982 if ((autostartLink = virDomainConfigFile(driver->autostartDir, vm->def->name)) == NULL)
1983 goto cleanup;
1984
1985 if (autostart) {
1986 int err;
1987
1988 if ((err = virFileMakePath(driver->autostartDir))) {
1989 virReportSystemError(err,
1990 _("cannot create autostart directory %s"),
1991 driver->autostartDir);
1992 goto cleanup;
1993 }
1994
1995 if (symlink(configFile, autostartLink) < 0) {
1996 virReportSystemError(errno,
1997 _("Failed to create symlink '%s to '%s'"),
1998 autostartLink, configFile);
1999 goto cleanup;
2000 }
2001 } else {
2002 if (unlink(autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) {
2003 virReportSystemError(errno,
2004 _("Failed to delete symlink '%s'"),
2005 autostartLink);
2006 goto cleanup;
2007 }
2008 }
2009
2010 vm->autostart = autostart;
2011 }
2012 ret = 0;
2013
2014cleanup:
2015 VIR_FREE(configFile);
2016 VIR_FREE(autostartLink);
2017 if (vm)
2018 virDomainObjUnlock(vm);
2019 umlDriverUnlock(driver);
2020 return ret;
2021}
2022
2023
2024static int
2025umlDomainBlockPeek (virDomainPtr dom,
2026 const char *path,
2027 unsigned long long offset, size_t size,
2028 void *buffer,
2029 unsigned int flags ATTRIBUTE_UNUSED)
2030{
2031 struct uml_driver *driver = dom->conn->privateData;
2032 virDomainObjPtr vm;
2033 int fd = -1, ret = -1, i;
2034
2035 umlDriverLock(driver);
2036 vm = virDomainFindByUUID(&driver->domains, dom->uuid);
2037 umlDriverUnlock(driver);
2038
2039 if (!vm) {
2040 umlReportError(VIR_ERR_INVALID_DOMAIN, "%s",
2041 _("no domain with matching uuid"));
2042 goto cleanup;
2043 }
2044
2045 if (!path || path[0] == '\0') {
2046 umlReportError(VIR_ERR_INVALID_ARG, "%s",
2047 _("NULL or empty path"));
2048 goto cleanup;
2049 }
2050
2051 /* Check the path belongs to this domain. */
2052 for (i = 0 ; i < vm->def->ndisks ; i++) {
2053 if (vm->def->disks[i]->src != NULL &&
2054 STREQ (vm->def->disks[i]->src, path)) {
2055 ret = 0;
2056 break;
2057 }
2058 }
2059
2060 if (ret == 0) {
2061 ret = -1;
2062 /* The path is correct, now try to open it and get its size. */
2063 fd = open (path, O_RDONLY);
2064 if (fd == -1) {
2065 virReportSystemError(errno,
2066 _("cannot open %s"), path);
2067 goto cleanup;
2068 }
2069
2070 /* Seek and read. */
2071 /* NB. Because we configure with AC_SYS_LARGEFILE, off_t should
2072 * be 64 bits on all platforms.
2073 */
2074 if (lseek (fd, offset, SEEK_SET) == (off_t) -1 ||
2075 saferead (fd, buffer, size) == (ssize_t) -1) {
2076 virReportSystemError(errno,
2077 _("cannot read %s"), path);
2078 goto cleanup;
2079 }
2080
2081 ret = 0;
2082 } else {
2083 umlReportError(VIR_ERR_INVALID_ARG, "%s",
2084 _("invalid path"));
2085 }
2086
2087cleanup:
2088 if (fd >= 0) close (fd);
2089 if (vm)
2090 virDomainObjUnlock(vm);
2091 return ret;
2092}
2093
2094
2095
2096static virDriver umlDriver = {
2097 VIR_DRV_UML,
2098 "UML",
2099 umlOpen, /* open */
2100 umlClose, /* close */
2101 NULL, /* supports_feature */
2102 umlGetType, /* type */
2103 umlGetVersion, /* version */
2104 NULL, /* libvirtVersion (impl. in libvirt.c) */
2105 virGetHostname, /* getHostname */
2106 NULL, /* getMaxVcpus */
2107 nodeGetInfo, /* nodeGetInfo */
2108 umlGetCapabilities, /* getCapabilities */
2109 umlListDomains, /* listDomains */
2110 umlNumDomains, /* numOfDomains */
2111 umlDomainCreate, /* domainCreateXML */
2112 umlDomainLookupByID, /* domainLookupByID */
2113 umlDomainLookupByUUID, /* domainLookupByUUID */
2114 umlDomainLookupByName, /* domainLookupByName */
2115 NULL, /* domainSuspend */
2116 NULL, /* domainResume */
2117 umlDomainShutdown, /* domainShutdown */
2118 NULL, /* domainReboot */
2119 umlDomainDestroy, /* domainDestroy */
2120 umlDomainGetOSType, /* domainGetOSType */
2121 umlDomainGetMaxMemory, /* domainGetMaxMemory */
2122 umlDomainSetMaxMemory, /* domainSetMaxMemory */
2123 umlDomainSetMemory, /* domainSetMemory */
2124 umlDomainGetInfo, /* domainGetInfo */
2125 NULL, /* domainSave */
2126 NULL, /* domainRestore */
2127 NULL, /* domainCoreDump */
2128 NULL, /* domainSetVcpus */
2129 NULL, /* domainPinVcpu */
2130 NULL, /* domainGetVcpus */
2131 NULL, /* domainGetMaxVcpus */
2132 NULL, /* domainGetSecurityLabel */
2133 NULL, /* nodeGetSecurityModel */
2134 umlDomainDumpXML, /* domainDumpXML */
2135 NULL, /* domainXMLFromNative */
2136 NULL, /* domainXMLToNative */
2137 umlListDefinedDomains, /* listDefinedDomains */
2138 umlNumDefinedDomains, /* numOfDefinedDomains */
2139 umlDomainStart, /* domainCreate */
2140 umlDomainStartWithFlags, /* domainCreateWithFlags */
2141 umlDomainDefine, /* domainDefineXML */
2142 umlDomainUndefine, /* domainUndefine */
2143 umlDomainAttachDevice, /* domainAttachDevice */
2144 umlDomainAttachDeviceFlags, /* domainAttachDeviceFlags */
2145 umlDomainDetachDevice, /* domainDetachDevice */
2146 umlDomainDetachDeviceFlags, /* domainDetachDeviceFlags */
2147 NULL, /* domainUpdateDeviceFlags */
2148 umlDomainGetAutostart, /* domainGetAutostart */
2149 umlDomainSetAutostart, /* domainSetAutostart */
2150 NULL, /* domainGetSchedulerType */
2151 NULL, /* domainGetSchedulerParameters */
2152 NULL, /* domainSetSchedulerParameters */
2153 NULL, /* domainMigratePrepare */
2154 NULL, /* domainMigratePerform */
2155 NULL, /* domainMigrateFinish */
2156 NULL, /* domainBlockStats */
2157 NULL, /* domainInterfaceStats */
2158 NULL, /* domainMemoryStats */
2159 umlDomainBlockPeek, /* domainBlockPeek */
2160 NULL, /* domainMemoryPeek */
2161 NULL, /* domainGetBlockInfo */
2162 nodeGetCellsFreeMemory, /* nodeGetCellsFreeMemory */
2163 nodeGetFreeMemory, /* getFreeMemory */
2164 NULL, /* domainEventRegister */
2165 NULL, /* domainEventDeregister */
2166 NULL, /* domainMigratePrepare2 */
2167 NULL, /* domainMigrateFinish2 */
2168 NULL, /* nodeDeviceDettach */
2169 NULL, /* nodeDeviceReAttach */
2170 NULL, /* nodeDeviceReset */
2171 NULL, /* domainMigratePrepareTunnel */
2172 umlIsEncrypted, /* isEncrypted */
2173 umlIsSecure, /* isSecure */
2174 umlDomainIsActive, /* domainIsActive */
2175 umlDomainIsPersistent, /* domainIsPersistent */
2176 NULL, /* cpuCompare */
2177 NULL, /* cpuBaseline */
2178 NULL, /* domainGetJobInfo */
2179 NULL, /* domainAbortJob */
2180 NULL, /* domainMigrateSetMaxDowntime */
2181 NULL, /* domainEventRegisterAny */
2182 NULL, /* domainEventDeregisterAny */
2183 NULL, /* domainManagedSave */
2184 NULL, /* domainHasManagedSaveImage */
2185 NULL, /* domainManagedSaveRemove */
2186 NULL, /* domainSnapshotCreateXML */
2187 NULL, /* domainSnapshotDumpXML */
2188 NULL, /* domainSnapshotNum */
2189 NULL, /* domainSnapshotListNames */
2190 NULL, /* domainSnapshotLookupByName */
2191 NULL, /* domainHasCurrentSnapshot */
2192 NULL, /* domainSnapshotCurrent */
2193 NULL, /* domainRevertToSnapshot */
2194 NULL, /* domainSnapshotDelete */
2195 NULL, /* qemuDomainMonitorCommand */
2196};
2197
2198
2199static virStateDriver umlStateDriver = {
2200 .name = "UML",
2201 .initialize = umlStartup,
2202 .cleanup = umlShutdown,
2203 .reload = umlReload,
2204 .active = umlActive,
2205};
2206
2207int umlRegister(void) {
2208 virRegisterDriver(&umlDriver);
2209 virRegisterStateDriver(&umlStateDriver);
2210 return 0;
2211}
02212
=== added file 'debian/patches/9026-Rebuild-network-filter-for-UML-guests-on-updates.patch'
--- debian/patches/9026-Rebuild-network-filter-for-UML-guests-on-updates.patch 1970-01-01 00:00:00 +0000
+++ debian/patches/9026-Rebuild-network-filter-for-UML-guests-on-updates.patch 2010-09-15 23:50:58 +0000
@@ -0,0 +1,55 @@
1From daa597d7b0a147ae8942390345b90f444185e9df Mon Sep 17 00:00:00 2001
2From: Soren Hansen <soren@linux2go.dk>
3Date: Mon, 13 Sep 2010 23:25:53 +0200
4Subject: [PATCH] Rebuild network filter for UML guests on updates
5
6When nwfilter support was added to UML, I didn't realise the UML driver
7needed instrumentation to make updating nwfilters on the fly work. This
8patch adds this bit of glue.
9
10Signed-off-by: Soren Hansen <soren@linux2go.dk>
11---
12 src/uml/uml_driver.c | 18 ++++++++++++++++++
13 1 files changed, 18 insertions(+), 0 deletions(-)
14
15diff --git a/src/uml/uml_driver.c b/src/uml/uml_driver.c
16index 40345d5..9101928 100644
17--- a/src/uml/uml_driver.c
18+++ b/src/uml/uml_driver.c
19@@ -2198,6 +2198,18 @@ static virDriver umlDriver = {
20 NULL, /* qemuDomainMonitorCommand */
21 };
22
23+static int
24+umlVMFilterRebuild(virConnectPtr conn ATTRIBUTE_UNUSED,
25+ virHashIterator iter, void *data)
26+{
27+ struct uml_driver *driver = uml_driver;
28+
29+ umlDriverLock(driver);
30+ virHashForEach(uml_driver->domains.objs, iter, data);
31+ umlDriverUnlock(driver);
32+
33+ return 0;
34+}
35
36 static virStateDriver umlStateDriver = {
37 .name = "UML",
38@@ -2207,8 +2219,14 @@ static virStateDriver umlStateDriver = {
39 .active = umlActive,
40 };
41
42+static virNWFilterCallbackDriver umlCallbackDriver = {
43+ .name = "UML",
44+ .vmFilterRebuild = umlVMFilterRebuild,
45+};
46+
47 int umlRegister(void) {
48 virRegisterDriver(&umlDriver);
49 virRegisterStateDriver(&umlStateDriver);
50+ virNWFilterRegisterCallbackDriver(&umlCallbackDriver);
51 return 0;
52 }
53--
541.7.1
55
056
=== renamed file 'debian/patches/9026-Rebuild-network-filter-for-UML-guests-on-updates.patch' => 'debian/patches/9026-Rebuild-network-filter-for-UML-guests-on-updates.patch.moved'

Subscribers

People subscribed via source and target branches