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