Switch to using a unix socket for the qemu monitor
[libvirt.git] / src / domain_conf.c
1 /*
2  * domain_conf.c: domain XML processing
3  *
4  * Copyright (C) 2006-2009 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/stat.h>
28 #include <unistd.h>
29 #include <fcntl.h>
30 #include <dirent.h>
31
32 #include "virterror_internal.h"
33 #include "datatypes.h"
34 #include "domain_conf.h"
35 #include "memory.h"
36 #include "verify.h"
37 #include "xml.h"
38 #include "uuid.h"
39 #include "util.h"
40 #include "buf.h"
41 #include "c-ctype.h"
42 #include "logging.h"
43
44 #define VIR_FROM_THIS VIR_FROM_DOMAIN
45
46 VIR_ENUM_IMPL(virDomainVirt, VIR_DOMAIN_VIRT_LAST,
47               "qemu",
48               "kqemu",
49               "kvm",
50               "xen",
51               "lxc",
52               "uml",
53               "openvz",
54               "vserver",
55               "ldom",
56               "test",
57               "vmware",
58               "hyperv",
59               "vbox",
60               "one")
61
62 VIR_ENUM_IMPL(virDomainBoot, VIR_DOMAIN_BOOT_LAST,
63               "fd",
64               "cdrom",
65               "hd",
66               "network")
67
68 VIR_ENUM_IMPL(virDomainFeature, VIR_DOMAIN_FEATURE_LAST,
69               "acpi",
70               "apic",
71               "pae")
72
73 VIR_ENUM_IMPL(virDomainLifecycle, VIR_DOMAIN_LIFECYCLE_LAST,
74               "destroy",
75               "restart",
76               "rename-restart",
77               "preserve")
78
79 VIR_ENUM_IMPL(virDomainDevice, VIR_DOMAIN_DEVICE_LAST,
80               "disk",
81               "filesystem",
82               "interface",
83               "input",
84               "sound",
85               "video",
86               "hostdev")
87
88 VIR_ENUM_IMPL(virDomainDisk, VIR_DOMAIN_DISK_TYPE_LAST,
89               "block",
90               "file")
91
92 VIR_ENUM_IMPL(virDomainDiskDevice, VIR_DOMAIN_DISK_DEVICE_LAST,
93               "disk",
94               "cdrom",
95               "floppy")
96
97 VIR_ENUM_IMPL(virDomainDiskBus, VIR_DOMAIN_DISK_BUS_LAST,
98               "ide",
99               "fdc",
100               "scsi",
101               "virtio",
102               "xen",
103               "usb",
104               "uml")
105
106 VIR_ENUM_IMPL(virDomainDiskCache, VIR_DOMAIN_DISK_CACHE_LAST,
107               "default",
108               "none",
109               "writethrough",
110               "writeback")
111
112 VIR_ENUM_IMPL(virDomainFS, VIR_DOMAIN_FS_TYPE_LAST,
113               "mount",
114               "block",
115               "file",
116               "template")
117
118 VIR_ENUM_IMPL(virDomainNet, VIR_DOMAIN_NET_TYPE_LAST,
119               "user",
120               "ethernet",
121               "server",
122               "client",
123               "mcast",
124               "network",
125               "bridge",
126               "internal")
127
128 VIR_ENUM_IMPL(virDomainChr, VIR_DOMAIN_CHR_TYPE_LAST,
129               "null",
130               "vc",
131               "pty",
132               "dev",
133               "file",
134               "pipe",
135               "stdio",
136               "udp",
137               "tcp",
138               "unix")
139
140 VIR_ENUM_IMPL(virDomainSoundModel, VIR_DOMAIN_SOUND_MODEL_LAST,
141               "sb16",
142               "es1370",
143               "pcspk",
144               "ac97")
145
146 VIR_ENUM_IMPL(virDomainVideo, VIR_DOMAIN_VIDEO_TYPE_LAST,
147               "vga",
148               "cirrus",
149               "vmvga",
150               "xen",
151               "vbox")
152
153 VIR_ENUM_IMPL(virDomainInput, VIR_DOMAIN_INPUT_TYPE_LAST,
154               "mouse",
155               "tablet")
156
157 VIR_ENUM_IMPL(virDomainInputBus, VIR_DOMAIN_INPUT_BUS_LAST,
158               "ps2",
159               "usb",
160               "xen")
161
162 VIR_ENUM_IMPL(virDomainGraphics, VIR_DOMAIN_GRAPHICS_TYPE_LAST,
163               "sdl",
164               "vnc",
165               "rdp",
166               "desktop")
167
168 VIR_ENUM_IMPL(virDomainHostdevMode, VIR_DOMAIN_HOSTDEV_MODE_LAST,
169               "subsystem",
170               "capabilities")
171
172 VIR_ENUM_IMPL(virDomainHostdevSubsys, VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST,
173               "usb",
174               "pci")
175
176 VIR_ENUM_IMPL(virDomainState, VIR_DOMAIN_CRASHED+1,
177               "nostate",
178               "running",
179               "blocked",
180               "paused",
181               "shutdown",
182               "shutoff",
183               "crashed")
184
185 VIR_ENUM_IMPL(virDomainSeclabel, VIR_DOMAIN_SECLABEL_LAST,
186               "dynamic",
187               "static")
188
189 #define virDomainReportError(conn, code, fmt...)                           \
190         virReportErrorHelper(conn, VIR_FROM_DOMAIN, code, __FILE__,        \
191                                __FUNCTION__, __LINE__, fmt)
192
193 #ifndef PROXY
194
195 virDomainObjPtr virDomainFindByID(const virDomainObjListPtr doms,
196                                   int id)
197 {
198     unsigned int i;
199
200     for (i = 0 ; i < doms->count ; i++) {
201         virDomainObjLock(doms->objs[i]);
202         if (virDomainIsActive(doms->objs[i]) &&
203             doms->objs[i]->def->id == id)
204             return doms->objs[i];
205         virDomainObjUnlock(doms->objs[i]);
206     }
207
208     return NULL;
209 }
210
211
212 virDomainObjPtr virDomainFindByUUID(const virDomainObjListPtr doms,
213                                     const unsigned char *uuid)
214 {
215     unsigned int i;
216
217     for (i = 0 ; i < doms->count ; i++) {
218         virDomainObjLock(doms->objs[i]);
219         if (!memcmp(doms->objs[i]->def->uuid, uuid, VIR_UUID_BUFLEN))
220             return doms->objs[i];
221         virDomainObjUnlock(doms->objs[i]);
222     }
223
224     return NULL;
225 }
226
227 virDomainObjPtr virDomainFindByName(const virDomainObjListPtr doms,
228                                     const char *name)
229 {
230     unsigned int i;
231
232     for (i = 0 ; i < doms->count ; i++) {
233         virDomainObjLock(doms->objs[i]);
234         if (STREQ(doms->objs[i]->def->name, name))
235             return doms->objs[i];
236         virDomainObjUnlock(doms->objs[i]);
237     }
238
239     return NULL;
240 }
241
242 #endif /* !PROXY */
243
244 void virDomainGraphicsDefFree(virDomainGraphicsDefPtr def)
245 {
246     if (!def)
247         return;
248
249     switch (def->type) {
250     case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
251         VIR_FREE(def->data.vnc.listenAddr);
252         VIR_FREE(def->data.vnc.keymap);
253         VIR_FREE(def->data.vnc.passwd);
254         break;
255
256     case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
257         VIR_FREE(def->data.sdl.display);
258         VIR_FREE(def->data.sdl.xauth);
259         break;
260
261     case VIR_DOMAIN_GRAPHICS_TYPE_RDP:
262         VIR_FREE(def->data.rdp.listenAddr);
263         break;
264
265     case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
266         VIR_FREE(def->data.desktop.display);
267         break;
268     }
269
270     VIR_FREE(def);
271 }
272
273 void virDomainInputDefFree(virDomainInputDefPtr def)
274 {
275     if (!def)
276         return;
277
278     VIR_FREE(def);
279 }
280
281 void virDomainDiskDefFree(virDomainDiskDefPtr def)
282 {
283     if (!def)
284         return;
285
286     VIR_FREE(def->src);
287     VIR_FREE(def->dst);
288     VIR_FREE(def->driverName);
289     VIR_FREE(def->driverType);
290
291     VIR_FREE(def);
292 }
293
294 void virDomainFSDefFree(virDomainFSDefPtr def)
295 {
296     if (!def)
297         return;
298
299     VIR_FREE(def->src);
300     VIR_FREE(def->dst);
301
302     VIR_FREE(def);
303 }
304
305 void virDomainNetDefFree(virDomainNetDefPtr def)
306 {
307     if (!def)
308         return;
309
310     VIR_FREE(def->model);
311
312     switch (def->type) {
313     case VIR_DOMAIN_NET_TYPE_ETHERNET:
314         VIR_FREE(def->data.ethernet.dev);
315         VIR_FREE(def->data.ethernet.script);
316         VIR_FREE(def->data.ethernet.ipaddr);
317         break;
318
319     case VIR_DOMAIN_NET_TYPE_SERVER:
320     case VIR_DOMAIN_NET_TYPE_CLIENT:
321     case VIR_DOMAIN_NET_TYPE_MCAST:
322         VIR_FREE(def->data.socket.address);
323         break;
324
325     case VIR_DOMAIN_NET_TYPE_NETWORK:
326         VIR_FREE(def->data.network.name);
327         break;
328
329     case VIR_DOMAIN_NET_TYPE_BRIDGE:
330         VIR_FREE(def->data.bridge.brname);
331         VIR_FREE(def->data.bridge.script);
332         VIR_FREE(def->data.bridge.ipaddr);
333         break;
334
335     case VIR_DOMAIN_NET_TYPE_INTERNAL:
336         VIR_FREE(def->data.internal.name);
337         break;
338     }
339
340     VIR_FREE(def->ifname);
341     VIR_FREE(def);
342 }
343
344 void virDomainChrDefFree(virDomainChrDefPtr def)
345 {
346     if (!def)
347         return;
348
349     switch (def->type) {
350     case VIR_DOMAIN_CHR_TYPE_PTY:
351     case VIR_DOMAIN_CHR_TYPE_DEV:
352     case VIR_DOMAIN_CHR_TYPE_FILE:
353     case VIR_DOMAIN_CHR_TYPE_PIPE:
354         VIR_FREE(def->data.file.path);
355         break;
356
357     case VIR_DOMAIN_CHR_TYPE_UDP:
358         VIR_FREE(def->data.udp.bindHost);
359         VIR_FREE(def->data.udp.bindService);
360         VIR_FREE(def->data.udp.connectHost);
361         VIR_FREE(def->data.udp.connectService);
362         break;
363
364     case VIR_DOMAIN_CHR_TYPE_TCP:
365         VIR_FREE(def->data.tcp.host);
366         VIR_FREE(def->data.tcp.service);
367         break;
368
369     case VIR_DOMAIN_CHR_TYPE_UNIX:
370         VIR_FREE(def->data.nix.path);
371         break;
372     }
373
374     VIR_FREE(def);
375 }
376
377 void virDomainSoundDefFree(virDomainSoundDefPtr def)
378 {
379     if (!def)
380         return;
381
382     VIR_FREE(def);
383 }
384
385 void virDomainVideoDefFree(virDomainVideoDefPtr def)
386 {
387     if (!def)
388         return;
389
390     VIR_FREE(def);
391 }
392
393 void virDomainHostdevDefFree(virDomainHostdevDefPtr def)
394 {
395     if (!def)
396         return;
397
398     VIR_FREE(def->target);
399     VIR_FREE(def);
400 }
401
402 void virDomainDeviceDefFree(virDomainDeviceDefPtr def)
403 {
404     if (!def)
405         return;
406
407     switch (def->type) {
408     case VIR_DOMAIN_DEVICE_DISK:
409         virDomainDiskDefFree(def->data.disk);
410         break;
411     case VIR_DOMAIN_DEVICE_NET:
412         virDomainNetDefFree(def->data.net);
413         break;
414     case VIR_DOMAIN_DEVICE_INPUT:
415         virDomainInputDefFree(def->data.input);
416         break;
417     case VIR_DOMAIN_DEVICE_SOUND:
418         virDomainSoundDefFree(def->data.sound);
419         break;
420     case VIR_DOMAIN_DEVICE_VIDEO:
421         virDomainVideoDefFree(def->data.video);
422         break;
423     case VIR_DOMAIN_DEVICE_HOSTDEV:
424         virDomainHostdevDefFree(def->data.hostdev);
425         break;
426     }
427
428     VIR_FREE(def);
429 }
430
431 void virSecurityLabelDefFree(virDomainDefPtr def);
432
433 void virSecurityLabelDefFree(virDomainDefPtr def)
434 {
435     VIR_FREE(def->seclabel.model);
436     VIR_FREE(def->seclabel.label);
437     VIR_FREE(def->seclabel.imagelabel);
438 }
439
440 void virDomainDefFree(virDomainDefPtr def)
441 {
442     unsigned int i;
443
444     if (!def)
445         return;
446
447     for (i = 0 ; i < def->ngraphics ; i++)
448         virDomainGraphicsDefFree(def->graphics[i]);
449     VIR_FREE(def->graphics);
450
451     for (i = 0 ; i < def->ninputs ; i++)
452         virDomainInputDefFree(def->inputs[i]);
453     VIR_FREE(def->inputs);
454
455     for (i = 0 ; i < def->ndisks ; i++)
456         virDomainDiskDefFree(def->disks[i]);
457     VIR_FREE(def->disks);
458
459     for (i = 0 ; i < def->nfss ; i++)
460         virDomainFSDefFree(def->fss[i]);
461     VIR_FREE(def->fss);
462
463     for (i = 0 ; i < def->nnets ; i++)
464         virDomainNetDefFree(def->nets[i]);
465     VIR_FREE(def->nets);
466     for (i = 0 ; i < def->nserials ; i++)
467         virDomainChrDefFree(def->serials[i]);
468     VIR_FREE(def->serials);
469
470     for (i = 0 ; i < def->nparallels ; i++)
471         virDomainChrDefFree(def->parallels[i]);
472     VIR_FREE(def->parallels);
473
474     virDomainChrDefFree(def->console);
475
476     for (i = 0 ; i < def->nsounds ; i++)
477         virDomainSoundDefFree(def->sounds[i]);
478     VIR_FREE(def->sounds);
479
480     for (i = 0 ; i < def->nvideos ; i++)
481         virDomainVideoDefFree(def->videos[i]);
482     VIR_FREE(def->videos);
483
484     for (i = 0 ; i < def->nhostdevs ; i++)
485         virDomainHostdevDefFree(def->hostdevs[i]);
486     VIR_FREE(def->hostdevs);
487
488     VIR_FREE(def->os.type);
489     VIR_FREE(def->os.arch);
490     VIR_FREE(def->os.machine);
491     VIR_FREE(def->os.init);
492     VIR_FREE(def->os.kernel);
493     VIR_FREE(def->os.initrd);
494     VIR_FREE(def->os.cmdline);
495     VIR_FREE(def->os.root);
496     VIR_FREE(def->os.loader);
497     VIR_FREE(def->os.bootloader);
498     VIR_FREE(def->os.bootloaderArgs);
499
500     VIR_FREE(def->name);
501     VIR_FREE(def->cpumask);
502     VIR_FREE(def->emulator);
503
504     virSecurityLabelDefFree(def);
505
506     VIR_FREE(def);
507 }
508
509 #ifndef PROXY
510
511 void virDomainObjFree(virDomainObjPtr dom)
512 {
513     if (!dom)
514         return;
515
516     virDomainDefFree(dom->def);
517     virDomainDefFree(dom->newDef);
518
519     virDomainChrDefFree(dom->monitor_chr);
520
521     VIR_FREE(dom->vcpupids);
522
523     virMutexDestroy(&dom->lock);
524
525     VIR_FREE(dom);
526 }
527
528 void virDomainObjListFree(virDomainObjListPtr vms)
529 {
530     unsigned int i;
531
532     for (i = 0 ; i < vms->count ; i++)
533         virDomainObjFree(vms->objs[i]);
534
535     VIR_FREE(vms->objs);
536     vms->count = 0;
537 }
538
539
540 static virDomainObjPtr virDomainObjNew(virConnectPtr conn)
541 {
542     virDomainObjPtr domain;
543
544     if (VIR_ALLOC(domain) < 0) {
545         virReportOOMError(conn);
546         return NULL;
547     }
548
549     if (virMutexInit(&domain->lock) < 0) {
550         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
551                              "%s", _("cannot initialize mutex"));
552         VIR_FREE(domain);
553         return NULL;
554     }
555
556     virDomainObjLock(domain);
557     domain->state = VIR_DOMAIN_SHUTOFF;
558     domain->monitorWatch = -1;
559     domain->monitor = -1;
560
561     return domain;
562 }
563
564 virDomainObjPtr virDomainAssignDef(virConnectPtr conn,
565                                    virDomainObjListPtr doms,
566                                    const virDomainDefPtr def)
567 {
568     virDomainObjPtr domain;
569
570     if ((domain = virDomainFindByUUID(doms, def->uuid))) {
571         if (!virDomainIsActive(domain)) {
572             virDomainDefFree(domain->def);
573             domain->def = def;
574         } else {
575             if (domain->newDef)
576                 virDomainDefFree(domain->newDef);
577             domain->newDef = def;
578         }
579
580         return domain;
581     }
582
583     if (VIR_REALLOC_N(doms->objs, doms->count + 1) < 0) {
584         virReportOOMError(conn);
585         return NULL;
586     }
587
588     if (!(domain = virDomainObjNew(conn)))
589         return NULL;
590
591     domain->def = def;
592
593     doms->objs[doms->count] = domain;
594     doms->count++;
595
596     return domain;
597 }
598
599 void virDomainRemoveInactive(virDomainObjListPtr doms,
600                              virDomainObjPtr dom)
601 {
602     unsigned int i;
603
604     virDomainObjUnlock(dom);
605
606     for (i = 0 ; i < doms->count ; i++) {
607         virDomainObjLock(doms->objs[i]);
608         if (doms->objs[i] == dom) {
609             virDomainObjUnlock(doms->objs[i]);
610             virDomainObjFree(doms->objs[i]);
611
612             if (i < (doms->count - 1))
613                 memmove(doms->objs + i, doms->objs + i + 1,
614                         sizeof(*(doms->objs)) * (doms->count - (i + 1)));
615
616             if (VIR_REALLOC_N(doms->objs, doms->count - 1) < 0) {
617                 ; /* Failure to reduce memory allocation isn't fatal */
618             }
619             doms->count--;
620
621             break;
622         }
623         virDomainObjUnlock(doms->objs[i]);
624     }
625
626 }
627 #endif /* ! PROXY */
628
629
630 int virDomainDiskCompare(virDomainDiskDefPtr a,
631                          virDomainDiskDefPtr b) {
632     if (a->bus == b->bus)
633         return virDiskNameToIndex(a->dst) - virDiskNameToIndex(b->dst);
634     else
635         return a->bus - b->bus;
636 }
637
638
639 #ifndef PROXY
640 /* Parse the XML definition for a disk
641  * @param node XML nodeset to parse for disk definition
642  */
643 static virDomainDiskDefPtr
644 virDomainDiskDefParseXML(virConnectPtr conn,
645                          xmlNodePtr node,
646                          int flags ATTRIBUTE_UNUSED) {
647     virDomainDiskDefPtr def;
648     xmlNodePtr cur;
649     char *type = NULL;
650     char *device = NULL;
651     char *driverName = NULL;
652     char *driverType = NULL;
653     char *source = NULL;
654     char *target = NULL;
655     char *bus = NULL;
656     char *cachetag = NULL;
657
658     if (VIR_ALLOC(def) < 0) {
659         virReportOOMError(conn);
660         return NULL;
661     }
662
663     type = virXMLPropString(node, "type");
664     if (type) {
665         if ((def->type = virDomainDiskTypeFromString(type)) < 0) {
666             virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
667                                  _("unknown disk type '%s'"), type);
668             goto error;
669         }
670     } else {
671         def->type = VIR_DOMAIN_DISK_TYPE_FILE;
672     }
673
674     cur = node->children;
675     while (cur != NULL) {
676         if (cur->type == XML_ELEMENT_NODE) {
677             if ((source == NULL) &&
678                 (xmlStrEqual(cur->name, BAD_CAST "source"))) {
679
680                 if (def->type == VIR_DOMAIN_DISK_TYPE_FILE)
681                     source = virXMLPropString(cur, "file");
682                 else
683                     source = virXMLPropString(cur, "dev");
684
685                 /* People sometimes pass a bogus '' source path
686                    when they mean to omit the source element
687                    completely. eg CDROM without media. This is
688                    just a little compatability check to help
689                    those broken apps */
690                 if (source && STREQ(source, ""))
691                     VIR_FREE(source);
692             } else if ((target == NULL) &&
693                        (xmlStrEqual(cur->name, BAD_CAST "target"))) {
694                 target = virXMLPropString(cur, "dev");
695                 bus = virXMLPropString(cur, "bus");
696
697                 /* HACK: Work around for compat with Xen
698                  * driver in previous libvirt releases */
699                 if (target &&
700                     STRPREFIX(target, "ioemu:"))
701                     memmove(target, target+6, strlen(target)-5);
702             } else if ((driverName == NULL) &&
703                        (xmlStrEqual(cur->name, BAD_CAST "driver"))) {
704                 driverName = virXMLPropString(cur, "name");
705                 driverType = virXMLPropString(cur, "type");
706                 cachetag = virXMLPropString(cur, "cache");
707             } else if (xmlStrEqual(cur->name, BAD_CAST "readonly")) {
708                 def->readonly = 1;
709             } else if (xmlStrEqual(cur->name, BAD_CAST "shareable")) {
710                 def->shared = 1;
711             }
712         }
713         cur = cur->next;
714     }
715
716     device = virXMLPropString(node, "device");
717     if (device) {
718         if ((def->device = virDomainDiskDeviceTypeFromString(device)) < 0) {
719             virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
720                                  _("unknown disk device '%s'"), device);
721             goto error;
722         }
723     } else {
724         def->device = VIR_DOMAIN_DISK_DEVICE_DISK;
725     }
726
727     /* Only CDROM and Floppy devices are allowed missing source path
728      * to indicate no media present */
729     if (source == NULL &&
730         def->device != VIR_DOMAIN_DISK_DEVICE_CDROM &&
731         def->device != VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
732         virDomainReportError(conn, VIR_ERR_NO_SOURCE,
733                              target ? "%s" : NULL, target);
734         goto error;
735     }
736
737     if (target == NULL) {
738         virDomainReportError(conn, VIR_ERR_NO_TARGET,
739                              source ? "%s" : NULL, source);
740         goto error;
741     }
742
743     if (def->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY &&
744         !STRPREFIX(target, "fd")) {
745         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
746                              _("Invalid floppy device name: %s"), target);
747         goto error;
748     }
749
750     /* Force CDROM to be listed as read only */
751     if (def->device == VIR_DOMAIN_DISK_DEVICE_CDROM)
752         def->readonly = 1;
753
754     if (def->device == VIR_DOMAIN_DISK_DEVICE_DISK &&
755         !STRPREFIX((const char *)target, "hd") &&
756         !STRPREFIX((const char *)target, "sd") &&
757         !STRPREFIX((const char *)target, "vd") &&
758         !STRPREFIX((const char *)target, "xvd") &&
759         !STRPREFIX((const char *)target, "ubd")) {
760         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
761                              _("Invalid harddisk device name: %s"), target);
762         goto error;
763     }
764
765     if (bus) {
766         if ((def->bus = virDomainDiskBusTypeFromString(bus)) < 0) {
767             virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
768                                  _("unknown disk bus type '%s'"), bus);
769             goto error;
770         }
771     } else {
772         if (def->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
773             def->bus = VIR_DOMAIN_DISK_BUS_FDC;
774         } else {
775             if (STRPREFIX(target, "hd"))
776                 def->bus = VIR_DOMAIN_DISK_BUS_IDE;
777             else if (STRPREFIX(target, "sd"))
778                 def->bus = VIR_DOMAIN_DISK_BUS_SCSI;
779             else if (STRPREFIX(target, "vd"))
780                 def->bus = VIR_DOMAIN_DISK_BUS_VIRTIO;
781             else if (STRPREFIX(target, "xvd"))
782                 def->bus = VIR_DOMAIN_DISK_BUS_XEN;
783             else if (STRPREFIX(target, "ubd"))
784                 def->bus = VIR_DOMAIN_DISK_BUS_UML;
785             else
786                 def->bus = VIR_DOMAIN_DISK_BUS_IDE;
787         }
788     }
789
790     if (def->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY &&
791         def->bus != VIR_DOMAIN_DISK_BUS_FDC) {
792         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
793                              _("Invalid bus type '%s' for floppy disk"), bus);
794         goto error;
795     }
796     if (def->device != VIR_DOMAIN_DISK_DEVICE_FLOPPY &&
797         def->bus == VIR_DOMAIN_DISK_BUS_FDC) {
798         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
799                              _("Invalid bus type '%s' for disk"), bus);
800         goto error;
801     }
802
803     if (cachetag &&
804         (def->cachemode = virDomainDiskCacheTypeFromString(cachetag)) < 0) {
805         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
806                              _("unknown disk cache mode '%s'"), cachetag);
807         goto error;
808     }
809
810     def->src = source;
811     source = NULL;
812     def->dst = target;
813     target = NULL;
814     def->driverName = driverName;
815     driverName = NULL;
816     def->driverType = driverType;
817     driverType = NULL;
818
819 cleanup:
820     VIR_FREE(bus);
821     VIR_FREE(type);
822     VIR_FREE(target);
823     VIR_FREE(source);
824     VIR_FREE(device);
825     VIR_FREE(driverType);
826     VIR_FREE(driverName);
827     VIR_FREE(cachetag);
828
829     return def;
830
831  error:
832     virDomainDiskDefFree(def);
833     def = NULL;
834     goto cleanup;
835 }
836
837
838 /* Parse the XML definition for a disk
839  * @param node XML nodeset to parse for disk definition
840  */
841 static virDomainFSDefPtr
842 virDomainFSDefParseXML(virConnectPtr conn,
843                        xmlNodePtr node,
844                        int flags ATTRIBUTE_UNUSED) {
845     virDomainFSDefPtr def;
846     xmlNodePtr cur;
847     char *type = NULL;
848     char *source = NULL;
849     char *target = NULL;
850
851     if (VIR_ALLOC(def) < 0) {
852         virReportOOMError(conn);
853         return NULL;
854     }
855
856     type = virXMLPropString(node, "type");
857     if (type) {
858         if ((def->type = virDomainFSTypeFromString(type)) < 0) {
859             virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
860                                  _("unknown filesystem type '%s'"), type);
861             goto error;
862         }
863     } else {
864         def->type = VIR_DOMAIN_FS_TYPE_MOUNT;
865     }
866
867     cur = node->children;
868     while (cur != NULL) {
869         if (cur->type == XML_ELEMENT_NODE) {
870             if ((source == NULL) &&
871                 (xmlStrEqual(cur->name, BAD_CAST "source"))) {
872
873                 if (def->type == VIR_DOMAIN_FS_TYPE_MOUNT)
874                     source = virXMLPropString(cur, "dir");
875                 else if (def->type == VIR_DOMAIN_FS_TYPE_FILE)
876                     source = virXMLPropString(cur, "file");
877                 else if (def->type == VIR_DOMAIN_FS_TYPE_BLOCK)
878                     source = virXMLPropString(cur, "dev");
879                 else if (def->type == VIR_DOMAIN_FS_TYPE_TEMPLATE)
880                     source = virXMLPropString(cur, "name");
881             } else if ((target == NULL) &&
882                        (xmlStrEqual(cur->name, BAD_CAST "target"))) {
883                 target = virXMLPropString(cur, "dir");
884             } else if (xmlStrEqual(cur->name, BAD_CAST "readonly")) {
885                 def->readonly = 1;
886             }
887         }
888         cur = cur->next;
889     }
890
891     if (source == NULL) {
892         virDomainReportError(conn, VIR_ERR_NO_SOURCE,
893                              target ? "%s" : NULL, target);
894         goto error;
895     }
896
897     if (target == NULL) {
898         virDomainReportError(conn, VIR_ERR_NO_TARGET,
899                              source ? "%s" : NULL, source);
900         goto error;
901     }
902
903     def->src = source;
904     source = NULL;
905     def->dst = target;
906     target = NULL;
907
908 cleanup:
909     VIR_FREE(type);
910     VIR_FREE(target);
911     VIR_FREE(source);
912
913     return def;
914
915  error:
916     virDomainFSDefFree(def);
917     def = NULL;
918     goto cleanup;
919 }
920
921
922
923 /* Parse the XML definition for a network interface
924  * @param node XML nodeset to parse for net definition
925  * @return 0 on success, -1 on failure
926  */
927 static virDomainNetDefPtr
928 virDomainNetDefParseXML(virConnectPtr conn,
929                         virCapsPtr caps,
930                         xmlNodePtr node,
931                         int flags ATTRIBUTE_UNUSED) {
932     virDomainNetDefPtr def;
933     xmlNodePtr cur;
934     char *macaddr = NULL;
935     char *type = NULL;
936     char *network = NULL;
937     char *bridge = NULL;
938     char *dev = NULL;
939     char *ifname = NULL;
940     char *script = NULL;
941     char *address = NULL;
942     char *port = NULL;
943     char *model = NULL;
944     char *internal = NULL;
945
946     if (VIR_ALLOC(def) < 0) {
947         virReportOOMError(conn);
948         return NULL;
949     }
950
951     type = virXMLPropString(node, "type");
952     if (type != NULL) {
953         if ((def->type = virDomainNetTypeFromString(type)) < 0) {
954             virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
955                                  _("unknown interface type '%s'"), type);
956             goto error;
957         }
958     } else {
959         def->type = VIR_DOMAIN_NET_TYPE_USER;
960     }
961
962     cur = node->children;
963     while (cur != NULL) {
964         if (cur->type == XML_ELEMENT_NODE) {
965             if ((macaddr == NULL) &&
966                 (xmlStrEqual(cur->name, BAD_CAST "mac"))) {
967                 macaddr = virXMLPropString(cur, "address");
968             } else if ((network == NULL) &&
969                        (def->type == VIR_DOMAIN_NET_TYPE_NETWORK) &&
970                        (xmlStrEqual(cur->name, BAD_CAST "source"))) {
971                 network = virXMLPropString(cur, "network");
972             } else if ((internal == NULL) &&
973                        (def->type == VIR_DOMAIN_NET_TYPE_INTERNAL) &&
974                        (xmlStrEqual(cur->name, BAD_CAST "source"))) {
975                 internal = virXMLPropString(cur, "name");
976             } else if ((network == NULL) &&
977                        (def->type == VIR_DOMAIN_NET_TYPE_BRIDGE) &&
978                        (xmlStrEqual(cur->name, BAD_CAST "source"))) {
979                 bridge = virXMLPropString(cur, "bridge");
980             } else if ((dev == NULL) &&
981                        (def->type == VIR_DOMAIN_NET_TYPE_ETHERNET) &&
982                        xmlStrEqual(cur->name, BAD_CAST "source")) {
983                 dev = virXMLPropString(cur, "dev");
984             } else if ((network == NULL) &&
985                        ((def->type == VIR_DOMAIN_NET_TYPE_SERVER) ||
986                         (def->type == VIR_DOMAIN_NET_TYPE_CLIENT) ||
987                         (def->type == VIR_DOMAIN_NET_TYPE_MCAST)) &&
988                        (xmlStrEqual(cur->name, BAD_CAST "source"))) {
989                 address = virXMLPropString(cur, "address");
990                 port = virXMLPropString(cur, "port");
991             } else if ((address == NULL) &&
992                        (def->type == VIR_DOMAIN_NET_TYPE_ETHERNET ||
993                         def->type == VIR_DOMAIN_NET_TYPE_BRIDGE) &&
994                        (xmlStrEqual(cur->name, BAD_CAST "ip"))) {
995                 address = virXMLPropString(cur, "address");
996             } else if ((ifname == NULL) &&
997                        xmlStrEqual(cur->name, BAD_CAST "target")) {
998                 ifname = virXMLPropString(cur, "dev");
999                 if (STRPREFIX((const char*)ifname, "vnet")) {
1000                     /* An auto-generated target name, blank it out */
1001                     VIR_FREE(ifname);
1002                 }
1003             } else if ((script == NULL) &&
1004                        (def->type == VIR_DOMAIN_NET_TYPE_ETHERNET ||
1005                         def->type == VIR_DOMAIN_NET_TYPE_BRIDGE) &&
1006                        xmlStrEqual(cur->name, BAD_CAST "script")) {
1007                 script = virXMLPropString(cur, "path");
1008             } else if (xmlStrEqual (cur->name, BAD_CAST "model")) {
1009                 model = virXMLPropString(cur, "type");
1010             }
1011         }
1012         cur = cur->next;
1013     }
1014
1015     if (macaddr) {
1016         virParseMacAddr((const char *)macaddr, def->mac);
1017     } else {
1018         virCapabilitiesGenerateMac(caps, def->mac);
1019     }
1020
1021     switch (def->type) {
1022     case VIR_DOMAIN_NET_TYPE_NETWORK:
1023         if (network == NULL) {
1024             virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
1025     _("No <source> 'network' attribute specified with <interface type='network'/>"));
1026             goto error;
1027         }
1028         def->data.network.name = network;
1029         network = NULL;
1030         break;
1031
1032     case VIR_DOMAIN_NET_TYPE_ETHERNET:
1033
1034         if (script != NULL) {
1035             def->data.ethernet.script = script;
1036             script = NULL;
1037         }
1038         if (dev != NULL) {
1039             def->data.ethernet.dev = dev;
1040             dev = NULL;
1041         }
1042         if (address != NULL) {
1043             def->data.ethernet.ipaddr = address;
1044             address = NULL;
1045         }
1046         break;
1047
1048     case VIR_DOMAIN_NET_TYPE_BRIDGE:
1049         if (bridge == NULL) {
1050             virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
1051     _("No <source> 'dev' attribute specified with <interface type='bridge'/>"));
1052             goto error;
1053         }
1054         def->data.bridge.brname = bridge;
1055         bridge = NULL;
1056         if (script != NULL) {
1057             def->data.bridge.script = script;
1058             script = NULL;
1059         }
1060         if (address != NULL) {
1061             def->data.bridge.ipaddr = address;
1062             address = NULL;
1063         }
1064         break;
1065
1066     case VIR_DOMAIN_NET_TYPE_CLIENT:
1067     case VIR_DOMAIN_NET_TYPE_SERVER:
1068     case VIR_DOMAIN_NET_TYPE_MCAST:
1069         if (port == NULL) {
1070             virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
1071             _("No <source> 'port' attribute specified with socket interface"));
1072             goto error;
1073         }
1074         if (virStrToLong_i(port, NULL, 10, &def->data.socket.port) < 0) {
1075             virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
1076             _("Cannot parse <source> 'port' attribute with socket interface"));
1077             goto error;
1078         }
1079
1080         if (address == NULL) {
1081             if (def->type == VIR_DOMAIN_NET_TYPE_CLIENT ||
1082                 def->type == VIR_DOMAIN_NET_TYPE_MCAST) {
1083                 virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
1084         _("No <source> 'address' attribute specified with socket interface"));
1085                 goto error;
1086             }
1087         } else {
1088             def->data.socket.address = address;
1089             address = NULL;
1090         }
1091         break;
1092
1093     case VIR_DOMAIN_NET_TYPE_INTERNAL:
1094         if (internal == NULL) {
1095             virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
1096         _("No <source> 'name' attribute specified with <interface type='internal'/>"));
1097             goto error;
1098         }
1099         def->data.internal.name = internal;
1100         internal = NULL;
1101         break;
1102     }
1103
1104     if (ifname != NULL) {
1105         def->ifname = ifname;
1106         ifname = NULL;
1107     }
1108
1109     /* NIC model (see -net nic,model=?).  We only check that it looks
1110      * reasonable, not that it is a supported NIC type.  FWIW kvm
1111      * supports these types as of April 2008:
1112      * i82551 i82557b i82559er ne2k_pci pcnet rtl8139 e1000 virtio
1113      */
1114     if (model != NULL) {
1115         int i;
1116         for (i = 0 ; i < strlen(model) ; i++) {
1117             int char_ok = c_isalnum(model[i]) || model[i] == '_';
1118             if (!char_ok) {
1119                 virDomainReportError (conn, VIR_ERR_INVALID_ARG, "%s",
1120                               _("Model name contains invalid characters"));
1121                 goto error;
1122             }
1123         }
1124         def->model = model;
1125         model = NULL;
1126     }
1127
1128 cleanup:
1129     VIR_FREE(macaddr);
1130     VIR_FREE(network);
1131     VIR_FREE(address);
1132     VIR_FREE(port);
1133     VIR_FREE(ifname);
1134     VIR_FREE(dev);
1135     VIR_FREE(script);
1136     VIR_FREE(bridge);
1137     VIR_FREE(model);
1138     VIR_FREE(type);
1139     VIR_FREE(internal);
1140
1141     return def;
1142
1143 error:
1144     virDomainNetDefFree(def);
1145     def = NULL;
1146     goto cleanup;
1147 }
1148
1149
1150 /* Parse the XML definition for a character device
1151  * @param node XML nodeset to parse for net definition
1152  *
1153  * The XML we're dealing with looks like
1154  *
1155  * <serial type="pty">
1156  *   <source path="/dev/pts/3"/>
1157  *   <target port="1"/>
1158  * </serial>
1159  *
1160  * <serial type="dev">
1161  *   <source path="/dev/ttyS0"/>
1162  *   <target port="1"/>
1163  * </serial>
1164  *
1165  * <serial type="tcp">
1166  *   <source mode="connect" host="0.0.0.0" service="2445"/>
1167  *   <target port="1"/>
1168  * </serial>
1169  *
1170  * <serial type="tcp">
1171  *   <source mode="bind" host="0.0.0.0" service="2445"/>
1172  *   <target port="1"/>
1173  * </serial>
1174  *
1175  * <serial type="udp">
1176  *   <source mode="bind" host="0.0.0.0" service="2445"/>
1177  *   <source mode="connect" host="0.0.0.0" service="2445"/>
1178  *   <target port="1"/>
1179  * </serial>
1180  *
1181  * <serial type="unix">
1182  *   <source mode="bind" path="/tmp/foo"/>
1183  *   <target port="1"/>
1184  * </serial>
1185  *
1186  */
1187 static virDomainChrDefPtr
1188 virDomainChrDefParseXML(virConnectPtr conn,
1189                         xmlNodePtr node,
1190                         int flags ATTRIBUTE_UNUSED) {
1191     xmlNodePtr cur;
1192     char *type = NULL;
1193     char *bindHost = NULL;
1194     char *bindService = NULL;
1195     char *connectHost = NULL;
1196     char *connectService = NULL;
1197     char *path = NULL;
1198     char *mode = NULL;
1199     char *protocol = NULL;
1200     virDomainChrDefPtr def;
1201
1202     if (VIR_ALLOC(def) < 0) {
1203         virReportOOMError(conn);
1204         return NULL;
1205     }
1206
1207     def->type = VIR_DOMAIN_CHR_TYPE_PTY;
1208     type = virXMLPropString(node, "type");
1209     if (type != NULL) {
1210         if (STREQ(type, "null"))
1211             def->type = VIR_DOMAIN_CHR_TYPE_NULL;
1212         else if (STREQ(type, "vc"))
1213             def->type = VIR_DOMAIN_CHR_TYPE_VC;
1214         else if (STREQ(type, "pty"))
1215             def->type = VIR_DOMAIN_CHR_TYPE_PTY;
1216         else if (STREQ(type, "dev"))
1217             def->type = VIR_DOMAIN_CHR_TYPE_DEV;
1218         else if (STREQ(type, "file"))
1219             def->type = VIR_DOMAIN_CHR_TYPE_FILE;
1220         else if (STREQ(type, "pipe"))
1221             def->type = VIR_DOMAIN_CHR_TYPE_PIPE;
1222         else if (STREQ(type, "stdio"))
1223             def->type = VIR_DOMAIN_CHR_TYPE_STDIO;
1224         else if (STREQ(type, "udp"))
1225             def->type = VIR_DOMAIN_CHR_TYPE_UDP;
1226         else if (STREQ(type, "tcp"))
1227             def->type = VIR_DOMAIN_CHR_TYPE_TCP;
1228         else if (STREQ(type, "unix"))
1229             def->type = VIR_DOMAIN_CHR_TYPE_UNIX;
1230         else
1231             def->type = VIR_DOMAIN_CHR_TYPE_NULL;
1232     }
1233
1234     cur = node->children;
1235     while (cur != NULL) {
1236         if (cur->type == XML_ELEMENT_NODE) {
1237             if (xmlStrEqual(cur->name, BAD_CAST "source")) {
1238                 if (mode == NULL)
1239                     mode = virXMLPropString(cur, "mode");
1240
1241                 switch (def->type) {
1242                 case VIR_DOMAIN_CHR_TYPE_PTY:
1243                 case VIR_DOMAIN_CHR_TYPE_DEV:
1244                 case VIR_DOMAIN_CHR_TYPE_FILE:
1245                 case VIR_DOMAIN_CHR_TYPE_PIPE:
1246                 case VIR_DOMAIN_CHR_TYPE_UNIX:
1247                     if (path == NULL)
1248                         path = virXMLPropString(cur, "path");
1249
1250                     break;
1251
1252                 case VIR_DOMAIN_CHR_TYPE_UDP:
1253                 case VIR_DOMAIN_CHR_TYPE_TCP:
1254                     if (mode == NULL ||
1255                         STREQ((const char *)mode, "connect")) {
1256
1257                         if (connectHost == NULL)
1258                             connectHost = virXMLPropString(cur, "host");
1259                         if (connectService == NULL)
1260                             connectService = virXMLPropString(cur, "service");
1261                     } else {
1262                         if (bindHost == NULL)
1263                             bindHost = virXMLPropString(cur, "host");
1264                         if (bindService == NULL)
1265                             bindService = virXMLPropString(cur, "service");
1266                     }
1267
1268                     if (def->type == VIR_DOMAIN_CHR_TYPE_UDP)
1269                         VIR_FREE(mode);
1270                 }
1271             } else if (xmlStrEqual(cur->name, BAD_CAST "protocol")) {
1272                 if (protocol == NULL)
1273                     protocol = virXMLPropString(cur, "type");
1274             }
1275         }
1276         cur = cur->next;
1277     }
1278
1279
1280     switch (def->type) {
1281     case VIR_DOMAIN_CHR_TYPE_NULL:
1282         /* Nada */
1283         break;
1284
1285     case VIR_DOMAIN_CHR_TYPE_VC:
1286         break;
1287
1288     case VIR_DOMAIN_CHR_TYPE_PTY:
1289     case VIR_DOMAIN_CHR_TYPE_DEV:
1290     case VIR_DOMAIN_CHR_TYPE_FILE:
1291     case VIR_DOMAIN_CHR_TYPE_PIPE:
1292         if (path == NULL &&
1293             def->type != VIR_DOMAIN_CHR_TYPE_PTY) {
1294             virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
1295                        _("Missing source path attribute for char device"));
1296             goto error;
1297         }
1298
1299         def->data.file.path = path;
1300         path = NULL;
1301         break;
1302
1303     case VIR_DOMAIN_CHR_TYPE_STDIO:
1304         /* Nada */
1305         break;
1306
1307     case VIR_DOMAIN_CHR_TYPE_TCP:
1308         if (mode == NULL ||
1309             STREQ(mode, "connect")) {
1310             if (connectHost == NULL) {
1311                 virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
1312                         _("Missing source host attribute for char device"));
1313                 goto error;
1314             }
1315             if (connectService == NULL) {
1316                 virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
1317                      _("Missing source service attribute for char device"));
1318                 goto error;
1319             }
1320
1321             def->data.tcp.host = connectHost;
1322             connectHost = NULL;
1323             def->data.tcp.service = connectService;
1324             connectService = NULL;
1325             def->data.tcp.listen = 0;
1326         } else {
1327             if (bindHost == NULL) {
1328                 virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
1329                         _("Missing source host attribute for char device"));
1330                 goto error;
1331             }
1332             if (bindService == NULL) {
1333                 virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
1334                      _("Missing source service attribute for char device"));
1335                 goto error;
1336             }
1337
1338             def->data.tcp.host = bindHost;
1339             bindHost = NULL;
1340             def->data.tcp.service = bindService;
1341             bindService = NULL;
1342             def->data.tcp.listen = 1;
1343         }
1344         if (protocol != NULL &&
1345             STREQ(protocol, "telnet"))
1346             def->data.tcp.protocol = VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET;
1347         else
1348             def->data.tcp.protocol = VIR_DOMAIN_CHR_TCP_PROTOCOL_RAW;
1349         break;
1350
1351     case VIR_DOMAIN_CHR_TYPE_UDP:
1352         if (connectService == NULL) {
1353             virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
1354                    _("Missing source service attribute for char device"));
1355             goto error;
1356         }
1357
1358         def->data.udp.connectHost = connectHost;
1359         connectHost = NULL;
1360         def->data.udp.connectService = connectService;
1361         connectService = NULL;
1362
1363         def->data.udp.bindHost = bindHost;
1364         bindHost = NULL;
1365         def->data.udp.bindService = bindService;
1366         bindService = NULL;
1367         break;
1368
1369     case VIR_DOMAIN_CHR_TYPE_UNIX:
1370         if (path == NULL) {
1371             virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
1372                          _("Missing source path attribute for char device"));
1373             goto error;
1374         }
1375
1376         if (mode != NULL &&
1377             STRNEQ(mode, "connect"))
1378             def->data.nix.listen = 1;
1379         else
1380             def->data.nix.listen = 0;
1381
1382         def->data.nix.path = path;
1383         path = NULL;
1384         break;
1385     }
1386
1387 cleanup:
1388     VIR_FREE(mode);
1389     VIR_FREE(protocol);
1390     VIR_FREE(type);
1391     VIR_FREE(bindHost);
1392     VIR_FREE(bindService);
1393     VIR_FREE(connectHost);
1394     VIR_FREE(connectService);
1395     VIR_FREE(path);
1396
1397     return def;
1398
1399 error:
1400     virDomainChrDefFree(def);
1401     def = NULL;
1402     goto cleanup;
1403 }
1404
1405 /* Parse the XML definition for a network interface */
1406 static virDomainInputDefPtr
1407 virDomainInputDefParseXML(virConnectPtr conn,
1408                           const char *ostype,
1409                           xmlNodePtr node,
1410                           int flags ATTRIBUTE_UNUSED) {
1411     virDomainInputDefPtr def;
1412     char *type = NULL;
1413     char *bus = NULL;
1414
1415     if (VIR_ALLOC(def) < 0) {
1416         virReportOOMError(conn);
1417         return NULL;
1418     }
1419
1420     type = virXMLPropString(node, "type");
1421     bus = virXMLPropString(node, "bus");
1422
1423     if (!type) {
1424         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1425                              "%s", _("missing input device type"));
1426         goto error;
1427     }
1428
1429     if ((def->type = virDomainInputTypeFromString(type)) < 0) {
1430         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1431                              _("unknown input device type '%s'"), type);
1432         goto error;
1433     }
1434
1435     if (bus) {
1436         if ((def->bus = virDomainInputBusTypeFromString(bus)) < 0) {
1437             virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1438                                  _("unknown input bus type '%s'"), bus);
1439             goto error;
1440         }
1441
1442         if (STREQ(ostype, "hvm")) {
1443             if (def->bus == VIR_DOMAIN_INPUT_BUS_PS2 && /* Only allow mouse for ps2 */
1444                 def->type != VIR_DOMAIN_INPUT_TYPE_MOUSE) {
1445                 virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1446                                  _("ps2 bus does not support %s input device"),
1447                                      type);
1448                 goto error;
1449             }
1450             if (def->bus == VIR_DOMAIN_INPUT_BUS_XEN) {
1451                 virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1452                                      _("unsupported input bus %s"),
1453                                      bus);
1454                 goto error;
1455             }
1456         } else {
1457             if (def->bus != VIR_DOMAIN_INPUT_BUS_XEN) {
1458                 virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1459                                      _("unsupported input bus %s"),
1460                                      bus);
1461             }
1462             if (def->type != VIR_DOMAIN_INPUT_TYPE_MOUSE) {
1463                 virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1464                                  _("xen bus does not support %s input device"),
1465                                      type);
1466                 goto error;
1467             }
1468         }
1469     } else {
1470         if (STREQ(ostype, "hvm")) {
1471             if (def->type == VIR_DOMAIN_INPUT_TYPE_MOUSE)
1472                 def->bus = VIR_DOMAIN_INPUT_BUS_PS2;
1473             else
1474                 def->bus = VIR_DOMAIN_INPUT_BUS_USB;
1475         } else {
1476             def->bus = VIR_DOMAIN_INPUT_BUS_XEN;
1477         }
1478     }
1479
1480 cleanup:
1481     VIR_FREE(type);
1482     VIR_FREE(bus);
1483
1484     return def;
1485
1486 error:
1487     virDomainInputDefFree(def);
1488     def = NULL;
1489     goto cleanup;
1490 }
1491
1492
1493 /* Parse the XML definition for a graphics device */
1494 static virDomainGraphicsDefPtr
1495 virDomainGraphicsDefParseXML(virConnectPtr conn,
1496                              xmlNodePtr node, int flags) {
1497     virDomainGraphicsDefPtr def;
1498     char *type = NULL;
1499
1500     if (VIR_ALLOC(def) < 0) {
1501         virReportOOMError(conn);
1502         return NULL;
1503     }
1504
1505     type = virXMLPropString(node, "type");
1506
1507     if (!type) {
1508         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1509                              "%s", _("missing graphics device type"));
1510         goto error;
1511     }
1512
1513     if ((def->type = virDomainGraphicsTypeFromString(type)) < 0) {
1514         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1515                              _("unknown graphics device type '%s'"), type);
1516         goto error;
1517     }
1518
1519     if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
1520         char *port = virXMLPropString(node, "port");
1521         char *autoport;
1522
1523         if (port) {
1524             if (virStrToLong_i(port, NULL, 10, &def->data.vnc.port) < 0) {
1525                 virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1526                                      _("cannot parse vnc port %s"), port);
1527                 VIR_FREE(port);
1528                 goto error;
1529             }
1530             VIR_FREE(port);
1531             /* Legacy compat syntax, used -1 for auto-port */
1532             if (def->data.vnc.port == -1) {
1533                 if (flags & VIR_DOMAIN_XML_INACTIVE)
1534                     def->data.vnc.port = 0;
1535                 def->data.vnc.autoport = 1;
1536             }
1537         } else {
1538             def->data.vnc.port = 0;
1539             def->data.vnc.autoport = 1;
1540         }
1541
1542         if ((autoport = virXMLPropString(node, "autoport")) != NULL) {
1543             if (STREQ(autoport, "yes")) {
1544                 if (flags & VIR_DOMAIN_XML_INACTIVE)
1545                     def->data.vnc.port = 0;
1546                 def->data.vnc.autoport = 1;
1547             }
1548             VIR_FREE(autoport);
1549         }
1550
1551         def->data.vnc.listenAddr = virXMLPropString(node, "listen");
1552         def->data.vnc.passwd = virXMLPropString(node, "passwd");
1553         def->data.vnc.keymap = virXMLPropString(node, "keymap");
1554     } else if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
1555         char *fullscreen = virXMLPropString(node, "fullscreen");
1556
1557         if (fullscreen != NULL) {
1558             if (STREQ(fullscreen, "yes")) {
1559                 def->data.sdl.fullscreen = 1;
1560             } else if (STREQ(fullscreen, "no")) {
1561                 def->data.sdl.fullscreen = 0;
1562             } else {
1563                 virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1564                              _("unknown fullscreen value '%s'"), fullscreen);
1565                 VIR_FREE(fullscreen);
1566                 goto error;
1567             }
1568             VIR_FREE(fullscreen);
1569         } else
1570             def->data.sdl.fullscreen = 0;
1571         def->data.sdl.xauth = virXMLPropString(node, "xauth");
1572         def->data.sdl.display = virXMLPropString(node, "display");
1573     } else if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_RDP) {
1574         char *port = virXMLPropString(node, "port");
1575         char *autoport;
1576         char *replaceUser;
1577         char *multiUser;
1578
1579         if (port) {
1580             if (virStrToLong_i(port, NULL, 10, &def->data.rdp.port) < 0) {
1581                 virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1582                                      _("cannot parse rdp port %s"), port);
1583                 VIR_FREE(port);
1584                 goto error;
1585             }
1586             VIR_FREE(port);
1587         } else {
1588             def->data.rdp.port = 0;
1589             def->data.rdp.autoport = 1;
1590         }
1591
1592         if ((autoport = virXMLPropString(node, "autoport")) != NULL) {
1593             if (STREQ(autoport, "yes")) {
1594                 if (flags & VIR_DOMAIN_XML_INACTIVE)
1595                     def->data.rdp.port = 0;
1596                 def->data.rdp.autoport = 1;
1597             }
1598             VIR_FREE(autoport);
1599         }
1600
1601         if ((replaceUser = virXMLPropString(node, "replaceUser")) != NULL) {
1602             if (STREQ(replaceUser, "yes")) {
1603                 def->data.rdp.replaceUser = 1;
1604             }
1605             VIR_FREE(replaceUser);
1606         }
1607
1608         if ((multiUser = virXMLPropString(node, "multiUser")) != NULL) {
1609             if (STREQ(multiUser, "yes")) {
1610                 def->data.rdp.multiUser = 1;
1611             }
1612             VIR_FREE(multiUser);
1613         }
1614
1615         def->data.rdp.listenAddr = virXMLPropString(node, "listen");
1616     } else if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP) {
1617         char *fullscreen = virXMLPropString(node, "fullscreen");
1618
1619         if (fullscreen != NULL) {
1620             if (STREQ(fullscreen, "yes")) {
1621                 def->data.desktop.fullscreen = 1;
1622             } else if (STREQ(fullscreen, "no")) {
1623                 def->data.desktop.fullscreen = 0;
1624             } else {
1625                 virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1626                              _("unknown fullscreen value '%s'"), fullscreen);
1627                 VIR_FREE(fullscreen);
1628                 goto error;
1629             }
1630             VIR_FREE(fullscreen);
1631         } else
1632             def->data.desktop.fullscreen = 0;
1633
1634         def->data.desktop.display = virXMLPropString(node, "display");
1635     }
1636
1637 cleanup:
1638     VIR_FREE(type);
1639
1640     return def;
1641
1642 error:
1643     virDomainGraphicsDefFree(def);
1644     def = NULL;
1645     goto cleanup;
1646 }
1647
1648
1649 static virDomainSoundDefPtr
1650 virDomainSoundDefParseXML(virConnectPtr conn,
1651                           const xmlNodePtr node,
1652                           int flags ATTRIBUTE_UNUSED) {
1653
1654     char *model;
1655     virDomainSoundDefPtr def;
1656
1657     if (VIR_ALLOC(def) < 0) {
1658         virReportOOMError(conn);
1659         return NULL;
1660     }
1661
1662     model = virXMLPropString(node, "model");
1663     if ((def->model = virDomainSoundModelTypeFromString(model)) < 0) {
1664         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1665                              _("unknown sound model '%s'"), model);
1666         goto error;
1667     }
1668
1669 cleanup:
1670     VIR_FREE(model);
1671
1672     return def;
1673
1674 error:
1675     virDomainSoundDefFree(def);
1676     def = NULL;
1677     goto cleanup;
1678 }
1679
1680
1681 int
1682 virDomainVideoDefaultRAM(virDomainDefPtr def,
1683                          int type)
1684 {
1685     switch (type) {
1686         /* Wierd, QEMU defaults to 9 MB ??! */
1687     case VIR_DOMAIN_VIDEO_TYPE_VGA:
1688     case VIR_DOMAIN_VIDEO_TYPE_CIRRUS:
1689     case VIR_DOMAIN_VIDEO_TYPE_VMVGA:
1690         if (def->virtType == VIR_DOMAIN_VIRT_VBOX)
1691             return 8 * 1024;
1692         else
1693             return 9 * 1024;
1694         break;
1695
1696     case VIR_DOMAIN_VIDEO_TYPE_XEN:
1697         /* Original Xen PVFB hardcoded to 4 MB */
1698         return 4 * 1024;
1699
1700     default:
1701         return 0;
1702     }
1703 }
1704
1705
1706 int
1707 virDomainVideoDefaultType(virDomainDefPtr def)
1708 {
1709     switch (def->virtType) {
1710     case VIR_DOMAIN_VIRT_TEST:
1711     case VIR_DOMAIN_VIRT_QEMU:
1712     case VIR_DOMAIN_VIRT_KQEMU:
1713     case VIR_DOMAIN_VIRT_KVM:
1714     case VIR_DOMAIN_VIRT_XEN:
1715         if (def->os.type &&
1716             (STREQ(def->os.type, "xen") ||
1717              STREQ(def->os.type, "linux")))
1718             return VIR_DOMAIN_VIDEO_TYPE_XEN;
1719         else
1720             return VIR_DOMAIN_VIDEO_TYPE_CIRRUS;
1721
1722     case VIR_DOMAIN_VIRT_VBOX:
1723         return VIR_DOMAIN_VIDEO_TYPE_VBOX;
1724
1725     default:
1726         return -1;
1727     }
1728 }
1729
1730 static virDomainVideoDefPtr
1731 virDomainVideoDefParseXML(virConnectPtr conn,
1732                           const xmlNodePtr node,
1733                           virDomainDefPtr dom,
1734                           int flags ATTRIBUTE_UNUSED) {
1735     virDomainVideoDefPtr def;
1736     xmlNodePtr cur;
1737     char *type = NULL;
1738     char *heads = NULL;
1739     char *vram = NULL;
1740
1741     if (VIR_ALLOC(def) < 0) {
1742         virReportOOMError(conn);
1743         return NULL;
1744     }
1745
1746     cur = node->children;
1747     while (cur != NULL) {
1748         if (cur->type == XML_ELEMENT_NODE) {
1749             if ((type == NULL) && (vram == NULL) && (heads == NULL) &&
1750                 xmlStrEqual(cur->name, BAD_CAST "model")) {
1751                 type = virXMLPropString(cur, "type");
1752                 vram = virXMLPropString(cur, "vram");
1753                 heads = virXMLPropString(cur, "heads");
1754             }
1755         }
1756         cur = cur->next;
1757     }
1758
1759     if (type) {
1760         if ((def->type = virDomainVideoTypeFromString(type)) < 0) {
1761             virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1762                                  _("unknown video model '%s'"), type);
1763             goto error;
1764         }
1765     } else {
1766         if ((def->type = virDomainVideoDefaultType(dom)) < 0) {
1767             virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
1768                                  _("missing video model and cannot determine default"));
1769             goto error;
1770         }
1771     }
1772
1773     if (vram) {
1774         if (virStrToLong_ui(vram, NULL, 10, &def->vram) < 0) {
1775             virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1776                                  _("cannot parse video ram '%s'"), vram);
1777             goto error;
1778         }
1779     } else {
1780         def->vram = virDomainVideoDefaultRAM(dom, def->type);
1781     }
1782
1783     if (heads) {
1784         if (virStrToLong_ui(heads, NULL, 10, &def->heads) < 0) {
1785             virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1786                                  _("cannot parse video heads '%s'"), heads);
1787             goto error;
1788         }
1789     } else {
1790         def->heads = 1;
1791     }
1792
1793     VIR_FREE(type);
1794     VIR_FREE(vram);
1795     VIR_FREE(heads);
1796
1797     return def;
1798
1799 error:
1800     virDomainVideoDefFree(def);
1801     VIR_FREE(type);
1802     VIR_FREE(vram);
1803     VIR_FREE(heads);
1804     return NULL;
1805 }
1806
1807 static int
1808 virDomainHostdevSubsysUsbDefParseXML(virConnectPtr conn,
1809                                      const xmlNodePtr node,
1810                                      virDomainHostdevDefPtr def,
1811                                      int flags ATTRIBUTE_UNUSED) {
1812
1813     int ret = -1;
1814     int got_product, got_vendor;
1815     xmlNodePtr cur;
1816
1817     /* Product can validly be 0, so we need some extra help to determine
1818      * if it is uninitialized*/
1819     got_product = 0;
1820     got_vendor = 0;
1821
1822     cur = node->children;
1823     while (cur != NULL) {
1824         if (cur->type == XML_ELEMENT_NODE) {
1825             if (xmlStrEqual(cur->name, BAD_CAST "vendor")) {
1826                 char *vendor = virXMLPropString(cur, "id");
1827
1828                 if (vendor) {
1829                     got_vendor = 1;
1830                     if (virStrToLong_ui(vendor, NULL, 0,
1831                                     &def->source.subsys.u.usb.vendor) < 0) {
1832                         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1833                                  _("cannot parse vendor id %s"), vendor);
1834                         VIR_FREE(vendor);
1835                         goto out;
1836                     }
1837                     VIR_FREE(vendor);
1838                 } else {
1839                     virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1840                                          "%s", _("usb vendor needs id"));
1841                     goto out;
1842                 }
1843             } else if (xmlStrEqual(cur->name, BAD_CAST "product")) {
1844                 char* product = virXMLPropString(cur, "id");
1845
1846                 if (product) {
1847                     got_product = 1;
1848                     if (virStrToLong_ui(product, NULL, 0,
1849                                         &def->source.subsys.u.usb.product) < 0) {
1850                         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1851                                              _("cannot parse product %s"),
1852                                              product);
1853                         VIR_FREE(product);
1854                         goto out;
1855                     }
1856                     VIR_FREE(product);
1857                 } else {
1858                     virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1859                                          "%s", _("usb product needs id"));
1860                     goto out;
1861                 }
1862             } else if (xmlStrEqual(cur->name, BAD_CAST "address")) {
1863                 char *bus, *device;
1864
1865                 bus = virXMLPropString(cur, "bus");
1866                 if (bus) {
1867                     if (virStrToLong_ui(bus, NULL, 0,
1868                                         &def->source.subsys.u.usb.bus) < 0) {
1869                         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1870                                              _("cannot parse bus %s"), bus);
1871                         VIR_FREE(bus);
1872                         goto out;
1873                     }
1874                     VIR_FREE(bus);
1875                 } else {
1876                     virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1877                                          "%s", _("usb address needs bus id"));
1878                     goto out;
1879                 }
1880
1881                 device = virXMLPropString(cur, "device");
1882                 if (device) {
1883                     if (virStrToLong_ui(device, NULL, 0,
1884                                         &def->source.subsys.u.usb.device) < 0)  {
1885                         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1886                                              _("cannot parse device %s"),
1887                                              device);
1888                         VIR_FREE(device);
1889                         goto out;
1890                     }
1891                     VIR_FREE(device);
1892                 } else {
1893                     virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
1894                                          _("usb address needs device id"));
1895                     goto out;
1896                 }
1897             } else {
1898                 virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1899                                      _("unknown usb source type '%s'"),
1900                                      cur->name);
1901                 goto out;
1902             }
1903         }
1904         cur = cur->next;
1905     }
1906
1907     if (got_vendor && def->source.subsys.u.usb.vendor == 0) {
1908         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1909             "%s", _("vendor cannot be 0."));
1910         goto out;
1911     }
1912
1913     if (!got_vendor && got_product) {
1914         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1915             "%s", _("missing vendor"));
1916         goto out;
1917     }
1918     if (got_vendor && !got_product) {
1919         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1920             "%s", _("missing product"));
1921         goto out;
1922     }
1923
1924     ret = 0;
1925 out:
1926     return ret;
1927 }
1928
1929
1930 static int
1931 virDomainHostdevSubsysPciDefParseXML(virConnectPtr conn,
1932                                      const xmlNodePtr node,
1933                                      virDomainHostdevDefPtr def) {
1934
1935     int ret = -1;
1936     xmlNodePtr cur;
1937
1938     cur = node->children;
1939     while (cur != NULL) {
1940         if (cur->type == XML_ELEMENT_NODE) {
1941             if (xmlStrEqual(cur->name, BAD_CAST "address")) {
1942
1943                 char *domain = virXMLPropString(cur, "domain");
1944                 if (domain) {
1945                     if (virStrToLong_ui(domain, NULL, 0,
1946                                     &def->source.subsys.u.pci.domain) < 0) {
1947                         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1948                                              _("cannot parse domain %s"),
1949                                              domain);
1950                         VIR_FREE(domain);
1951                         goto out;
1952                     }
1953                     VIR_FREE(domain);
1954                 }
1955
1956                 char *bus = virXMLPropString(cur, "bus");
1957                 if (bus) {
1958                     if (virStrToLong_ui(bus, NULL, 0,
1959                                         &def->source.subsys.u.pci.bus) < 0) {
1960                         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1961                                              _("cannot parse bus %s"), bus);
1962                         VIR_FREE(bus);
1963                         goto out;
1964                     }
1965                     VIR_FREE(bus);
1966                 } else {
1967                     virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1968                                          "%s", _("pci address needs bus id"));
1969                     goto out;
1970                 }
1971
1972                 char *slot = virXMLPropString(cur, "slot");
1973                 if (slot) {
1974                     if (virStrToLong_ui(slot, NULL, 0,
1975                                         &def->source.subsys.u.pci.slot) < 0)  {
1976                         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1977                                              _("cannot parse slot %s"),
1978                                              slot);
1979                         VIR_FREE(slot);
1980                         goto out;
1981                     }
1982                     VIR_FREE(slot);
1983                 } else {
1984                     virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1985                                          "%s", _("pci address needs slot id"));
1986                     goto out;
1987                 }
1988
1989                 char *function = virXMLPropString(cur, "function");
1990                 if (function) {
1991                     if (virStrToLong_ui(function, NULL, 0,
1992                                     &def->source.subsys.u.pci.function) < 0)  {
1993                         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1994                                              _("cannot parse function %s"),
1995                                              function);
1996                         VIR_FREE(function);
1997                         goto out;
1998                     }
1999                     VIR_FREE(function);
2000                 } else {
2001                     virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
2002                                          _("pci address needs function id"));
2003                     goto out;
2004                 }
2005             } else {
2006                 virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2007                                      _("unknown pci source type '%s'"),
2008                                      cur->name);
2009                 goto out;
2010             }
2011         }
2012         cur = cur->next;
2013     }
2014
2015     ret = 0;
2016 out:
2017     return ret;
2018 }
2019
2020
2021 static virDomainHostdevDefPtr
2022 virDomainHostdevDefParseXML(virConnectPtr conn,
2023                             const xmlNodePtr node,
2024                             int flags) {
2025
2026     xmlNodePtr cur;
2027     virDomainHostdevDefPtr def;
2028     char *mode, *type = NULL, *managed = NULL;
2029
2030     if (VIR_ALLOC(def) < 0) {
2031         virReportOOMError(conn);
2032         return NULL;
2033     }
2034     def->target = NULL;
2035
2036     mode = virXMLPropString(node, "mode");
2037     if (mode) {
2038         if ((def->mode=virDomainHostdevModeTypeFromString(mode)) < 0) {
2039              virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2040                                   _("unknown hostdev mode '%s'"), mode);
2041             goto error;
2042         }
2043     } else {
2044         def->mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS;
2045     }
2046
2047     type = virXMLPropString(node, "type");
2048     if (type) {
2049         if ((def->source.subsys.type = virDomainHostdevSubsysTypeFromString(type)) < 0) {
2050             virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2051                                  _("unknown host device type '%s'"), type);
2052             goto error;
2053         }
2054     } else {
2055         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2056                              "%s", _("missing type in hostdev"));
2057         goto error;
2058     }
2059
2060     managed = virXMLPropString(node, "managed");
2061     if (managed != NULL) {
2062         if (STREQ(managed, "yes"))
2063             def->managed = 1;
2064         VIR_FREE(managed);
2065     }
2066
2067     cur = node->children;
2068     while (cur != NULL) {
2069         if (cur->type == XML_ELEMENT_NODE) {
2070             if (xmlStrEqual(cur->name, BAD_CAST "source")) {
2071                 if (def->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
2072                     def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
2073                         if (virDomainHostdevSubsysUsbDefParseXML(conn, cur,
2074                                                                  def, flags) < 0)
2075                             goto error;
2076                 }
2077                 if (def->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
2078                     def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
2079                         if (virDomainHostdevSubsysPciDefParseXML(conn, cur, def) < 0)
2080                             goto error;
2081                 }
2082             } else {
2083                 virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2084                                      _("unknown node %s"), cur->name);
2085             }
2086         }
2087         cur = cur->next;
2088     }
2089
2090 cleanup:
2091     VIR_FREE(type);
2092     VIR_FREE(mode);
2093     return def;
2094
2095 error:
2096     virDomainHostdevDefFree(def);
2097     def = NULL;
2098     goto cleanup;
2099 }
2100
2101
2102 static int virDomainLifecycleParseXML(virConnectPtr conn,
2103                                       xmlXPathContextPtr ctxt,
2104                                       const char *xpath,
2105                                       int *val,
2106                                       int defaultVal)
2107 {
2108     char *tmp = virXPathString(conn, xpath, ctxt);
2109     if (tmp == NULL) {
2110         *val = defaultVal;
2111     } else {
2112         *val = virDomainLifecycleTypeFromString(tmp);
2113         if (*val < 0) {
2114             virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2115                                  _("unknown lifecycle action %s"), tmp);
2116             VIR_FREE(tmp);
2117             return -1;
2118         }
2119         VIR_FREE(tmp);
2120     }
2121     return 0;
2122 }
2123
2124 static int
2125 virSecurityLabelDefParseXML(virConnectPtr conn,
2126                             const virDomainDefPtr def,
2127                             xmlXPathContextPtr ctxt,
2128                             int flags)
2129 {
2130     char *p;
2131
2132     if (virXPathNode(conn, "./seclabel", ctxt) == NULL)
2133         return 0;
2134
2135     p = virXPathStringLimit(conn, "string(./seclabel/@type)",
2136                             VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
2137     if (p == NULL) {
2138         virDomainReportError(conn, VIR_ERR_XML_ERROR,
2139                              "%s", _("missing security type"));
2140         goto error;
2141     }
2142     def->seclabel.type = virDomainSeclabelTypeFromString(p);
2143     VIR_FREE(p);
2144     if (def->seclabel.type < 0) {
2145         virDomainReportError(conn, VIR_ERR_XML_ERROR,
2146                              _("invalid security type"));
2147         goto error;
2148     }
2149
2150     /* Only parse details, if using static labels, or
2151      * if the 'live' VM XML is requested
2152      */
2153     if (def->seclabel.type == VIR_DOMAIN_SECLABEL_STATIC ||
2154         !(flags & VIR_DOMAIN_XML_INACTIVE)) {
2155         p = virXPathStringLimit(conn, "string(./seclabel/@model)",
2156                                 VIR_SECURITY_MODEL_BUFLEN-1, ctxt);
2157         if (p == NULL) {
2158             virDomainReportError(conn, VIR_ERR_XML_ERROR,
2159                                  "%s", _("missing security model"));
2160             goto error;
2161         }
2162         def->seclabel.model = p;
2163
2164         p = virXPathStringLimit(conn, "string(./seclabel/label[1])",
2165                                 VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
2166         if (p == NULL) {
2167             virDomainReportError(conn, VIR_ERR_XML_ERROR,
2168                                  _("security label is missing"));
2169             goto error;
2170         }
2171
2172         def->seclabel.label = p;
2173     }
2174
2175     /* Only parse imagelabel, if requested live XML for dynamic label */
2176     if (def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC &&
2177         !(flags & VIR_DOMAIN_XML_INACTIVE)) {
2178         p = virXPathStringLimit(conn, "string(./seclabel/imagelabel[1])",
2179                                 VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
2180         if (p == NULL) {
2181             virDomainReportError(conn, VIR_ERR_XML_ERROR,
2182                                  _("security imagelabel is missing"));
2183             goto error;
2184         }
2185         def->seclabel.imagelabel = p;
2186     }
2187
2188     return 0;
2189
2190 error:
2191     virSecurityLabelDefFree(def);
2192     return -1;
2193 }
2194
2195 virDomainDeviceDefPtr virDomainDeviceDefParse(virConnectPtr conn,
2196                                               virCapsPtr caps,
2197                                               const virDomainDefPtr def,
2198                                               const char *xmlStr,
2199                                               int flags)
2200 {
2201     xmlDocPtr xml;
2202     xmlNodePtr node;
2203     virDomainDeviceDefPtr dev = NULL;
2204
2205     if (!(xml = xmlReadDoc(BAD_CAST xmlStr, "device.xml", NULL,
2206                            XML_PARSE_NOENT | XML_PARSE_NONET |
2207                            XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
2208         virDomainReportError(conn, VIR_ERR_XML_ERROR, NULL);
2209         goto error;
2210     }
2211
2212     node = xmlDocGetRootElement(xml);
2213     if (node == NULL) {
2214         virDomainReportError(conn, VIR_ERR_XML_ERROR,
2215                              "%s", _("missing root element"));
2216         goto error;
2217     }
2218
2219     if (VIR_ALLOC(dev) < 0) {
2220         virReportOOMError(conn);
2221         goto error;
2222     }
2223
2224     if (xmlStrEqual(node->name, BAD_CAST "disk")) {
2225         dev->type = VIR_DOMAIN_DEVICE_DISK;
2226         if (!(dev->data.disk = virDomainDiskDefParseXML(conn, node, flags)))
2227             goto error;
2228     } else if (xmlStrEqual(node->name, BAD_CAST "filesystem")) {
2229         dev->type = VIR_DOMAIN_DEVICE_FS;
2230         if (!(dev->data.fs = virDomainFSDefParseXML(conn, node, flags)))
2231             goto error;
2232     } else if (xmlStrEqual(node->name, BAD_CAST "interface")) {
2233         dev->type = VIR_DOMAIN_DEVICE_NET;
2234         if (!(dev->data.net = virDomainNetDefParseXML(conn, caps, node, flags)))
2235             goto error;
2236     } else if (xmlStrEqual(node->name, BAD_CAST "input")) {
2237         dev->type = VIR_DOMAIN_DEVICE_INPUT;
2238         if (!(dev->data.input = virDomainInputDefParseXML(conn, def->os.type,
2239                                                           node, flags)))
2240             goto error;
2241     } else if (xmlStrEqual(node->name, BAD_CAST "sound")) {
2242         dev->type = VIR_DOMAIN_DEVICE_SOUND;
2243         if (!(dev->data.sound = virDomainSoundDefParseXML(conn, node, flags)))
2244             goto error;
2245     } else if (xmlStrEqual(node->name, BAD_CAST "video")) {
2246         dev->type = VIR_DOMAIN_DEVICE_VIDEO;
2247         if (!(dev->data.video = virDomainVideoDefParseXML(conn, node, def, flags)))
2248             goto error;
2249     } else if (xmlStrEqual(node->name, BAD_CAST "hostdev")) {
2250         dev->type = VIR_DOMAIN_DEVICE_HOSTDEV;
2251         if (!(dev->data.hostdev = virDomainHostdevDefParseXML(conn, node, flags)))
2252             goto error;
2253     } else {
2254         virDomainReportError(conn, VIR_ERR_XML_ERROR,
2255                              "%s", _("unknown device type"));
2256         goto error;
2257     }
2258
2259     xmlFreeDoc(xml);
2260
2261     return dev;
2262
2263   error:
2264     xmlFreeDoc(xml);
2265     VIR_FREE(dev);
2266     return NULL;
2267 }
2268 #endif
2269
2270 int virDomainDiskQSort(const void *a, const void *b)
2271 {
2272     const virDomainDiskDefPtr *da = a;
2273     const virDomainDiskDefPtr *db = b;
2274
2275     return virDomainDiskCompare(*da, *db);
2276 }
2277
2278 #ifndef PROXY
2279 static char *virDomainDefDefaultEmulator(virConnectPtr conn,
2280                                          virDomainDefPtr def,
2281                                          virCapsPtr caps) {
2282     const char *type;
2283     const char *emulator;
2284     char *retemu;
2285
2286     type = virDomainVirtTypeToString(def->virtType);
2287     if (!type) {
2288         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2289                              "%s", _("unknown virt type"));
2290         return NULL;
2291     }
2292
2293     emulator = virCapabilitiesDefaultGuestEmulator(caps,
2294                                                    def->os.type,
2295                                                    def->os.arch,
2296                                                    type);
2297
2298     if (!emulator) {
2299         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2300                              _("no emulator for domain %s os type %s on architecture %s"),
2301                              type, def->os.type, def->os.arch);
2302         return NULL;
2303     }
2304
2305     retemu = strdup(emulator);
2306     if (!retemu)
2307         virReportOOMError(conn);
2308
2309     return retemu;
2310 }
2311
2312 static virDomainDefPtr virDomainDefParseXML(virConnectPtr conn,
2313                                             virCapsPtr caps,
2314                                             xmlXPathContextPtr ctxt, int flags)
2315 {
2316     xmlNodePtr *nodes = NULL, node = NULL;
2317     char *tmp = NULL;
2318     int i, n;
2319     long id = -1;
2320     virDomainDefPtr def;
2321
2322     if (VIR_ALLOC(def) < 0) {
2323         virReportOOMError(conn);
2324         return NULL;
2325     }
2326
2327     if (!(flags & VIR_DOMAIN_XML_INACTIVE))
2328         if((virXPathLong(conn, "string(./@id)", ctxt, &id)) < 0)
2329             id = -1;
2330     def->id = (int)id;
2331
2332     /* Find out what type of virtualization to use */
2333     if (!(tmp = virXPathString(conn, "string(./@type)", ctxt))) {
2334         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2335                              "%s", _("missing domain type attribute"));
2336         goto error;
2337     }
2338
2339     if ((def->virtType = virDomainVirtTypeFromString(tmp)) < 0) {
2340         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2341                              _("invalid domain type %s"), tmp);
2342         goto error;
2343     }
2344     VIR_FREE(tmp);
2345
2346     /* Extract domain name */
2347     if (!(def->name = virXPathString(conn, "string(./name[1])", ctxt))) {
2348         virDomainReportError(conn, VIR_ERR_NO_NAME, NULL);
2349         goto error;
2350     }
2351
2352     /* Extract domain uuid */
2353     tmp = virXPathString(conn, "string(./uuid[1])", ctxt);
2354     if (!tmp) {
2355         int err;
2356         if ((err = virUUIDGenerate(def->uuid))) {
2357             virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2358                                  "%s", _("Failed to generate UUID"));
2359             goto error;
2360         }
2361     } else {
2362         if (virUUIDParse(tmp, def->uuid) < 0) {
2363             virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2364                                  "%s", _("malformed uuid element"));
2365             goto error;
2366         }
2367         VIR_FREE(tmp);
2368     }
2369
2370     /* Extract domain memory */
2371     if (virXPathULong(conn, "string(./memory[1])", ctxt, &def->maxmem) < 0) {
2372         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2373                              "%s", _("missing memory element"));
2374         goto error;
2375     }
2376
2377     if (virXPathULong(conn, "string(./currentMemory[1])", ctxt, &def->memory) < 0)
2378         def->memory = def->maxmem;
2379
2380     if (virXPathULong(conn, "string(./vcpu[1])", ctxt, &def->vcpus) < 0)
2381         def->vcpus = 1;
2382
2383     tmp = virXPathString(conn, "string(./vcpu[1]/@cpuset)", ctxt);
2384     if (tmp) {
2385         char *set = tmp;
2386         def->cpumasklen = VIR_DOMAIN_CPUMASK_LEN;
2387         if (VIR_ALLOC_N(def->cpumask, def->cpumasklen) < 0) {
2388             virReportOOMError(conn);
2389             goto error;
2390         }
2391         if (virDomainCpuSetParse(conn, (const char **)&set,
2392                                  0, def->cpumask,
2393                                  def->cpumasklen) < 0)
2394             goto error;
2395         VIR_FREE(tmp);
2396     }
2397
2398     n = virXPathNodeSet(conn, "./features/*", ctxt, &nodes);
2399     if (n < 0)
2400         goto error;
2401     if (n) {
2402         for (i = 0 ; i < n ; i++) {
2403             int val = virDomainFeatureTypeFromString((const char *)nodes[i]->name);
2404             if (val < 0) {
2405                 virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2406                                      _("unexpected feature %s"),
2407                                      nodes[i]->name);
2408                 goto error;
2409             }
2410             def->features |= (1 << val);
2411         }
2412         VIR_FREE(nodes);
2413     }
2414
2415     if (virDomainLifecycleParseXML(conn, ctxt, "string(./on_reboot[1])",
2416                                    &def->onReboot, VIR_DOMAIN_LIFECYCLE_RESTART) < 0)
2417         goto error;
2418
2419     if (virDomainLifecycleParseXML(conn, ctxt, "string(./on_poweroff[1])",
2420                                    &def->onPoweroff, VIR_DOMAIN_LIFECYCLE_DESTROY) < 0)
2421         goto error;
2422
2423     if (virDomainLifecycleParseXML(conn, ctxt, "string(./on_crash[1])",
2424                                    &def->onCrash, VIR_DOMAIN_LIFECYCLE_DESTROY) < 0)
2425         goto error;
2426
2427
2428     tmp = virXPathString(conn, "string(./clock/@offset)", ctxt);
2429     if (tmp && STREQ(tmp, "localtime"))
2430         def->localtime = 1;
2431     VIR_FREE(tmp);
2432
2433     def->os.bootloader = virXPathString(conn, "string(./bootloader)", ctxt);
2434     def->os.bootloaderArgs = virXPathString(conn, "string(./bootloader_args)", ctxt);
2435
2436     def->os.type = virXPathString(conn, "string(./os/type[1])", ctxt);
2437     if (!def->os.type) {
2438         if (def->os.bootloader) {
2439             def->os.type = strdup("xen");
2440             if (!def->os.type) {
2441                 virReportOOMError(conn);
2442                 goto error;
2443             }
2444         } else {
2445             virDomainReportError(conn, VIR_ERR_OS_TYPE,
2446                                  "%s", _("no OS type"));
2447             goto error;
2448         }
2449     }
2450     /*
2451      * HACK: For xen driver we previously used bogus 'linux' as the
2452      * os type for paravirt, whereas capabilities declare it to
2453      * be 'xen'. So we accept the former and convert
2454      */
2455     if (STREQ(def->os.type, "linux") &&
2456         def->virtType == VIR_DOMAIN_VIRT_XEN) {
2457         VIR_FREE(def->os.type);
2458         if (!(def->os.type = strdup("xen"))) {
2459             virReportOOMError(conn);
2460             goto error;
2461         }
2462     }
2463
2464     if (!virCapabilitiesSupportsGuestOSType(caps, def->os.type)) {
2465         virDomainReportError(conn, VIR_ERR_OS_TYPE,
2466                              "%s", def->os.type);
2467         goto error;
2468     }
2469
2470     def->os.arch = virXPathString(conn, "string(./os/type[1]/@arch)", ctxt);
2471     if (def->os.arch) {
2472         if (!virCapabilitiesSupportsGuestArch(caps, def->os.type, def->os.arch)) {
2473             virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2474                                  _("os type '%s' & arch '%s' combination is not supported"),
2475                                  def->os.type, def->os.arch);
2476             goto error;
2477         }
2478     } else {
2479         const char *defaultArch = virCapabilitiesDefaultGuestArch(caps, def->os.type, virDomainVirtTypeToString(def->virtType));
2480         if (defaultArch == NULL) {
2481             virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2482                                  _("no supported architecture for os type '%s'"),
2483                                  def->os.type);
2484             goto error;
2485         }
2486         if (!(def->os.arch = strdup(defaultArch))) {
2487             virReportOOMError(conn);
2488             goto error;
2489         }
2490     }
2491
2492     def->os.machine = virXPathString(conn, "string(./os/type[1]/@machine)", ctxt);
2493     if (!def->os.machine) {
2494         const char *defaultMachine = virCapabilitiesDefaultGuestMachine(caps,
2495                                                                         def->os.type,
2496                                                                         def->os.arch);
2497         if (defaultMachine != NULL) {
2498             if (!(def->os.machine = strdup(defaultMachine))) {
2499                 virReportOOMError(conn);
2500                 goto error;
2501             }
2502         }
2503     }
2504
2505     /*
2506      * Booting options for different OS types....
2507      *
2508      *   - A bootloader (and optional kernel+initrd)  (xen)
2509      *   - A kernel + initrd                          (xen)
2510      *   - A boot device (and optional kernel+initrd) (hvm)
2511      *   - An init script                             (exe)
2512      */
2513
2514     if (STREQ(def->os.type, "exe")) {
2515         def->os.init = virXPathString(conn, "string(./os/init[1])", ctxt);
2516     }
2517
2518     if (STREQ(def->os.type, "xen") ||
2519         STREQ(def->os.type, "hvm") ||
2520         STREQ(def->os.type, "uml")) {
2521         def->os.kernel = virXPathString(conn, "string(./os/kernel[1])", ctxt);
2522         def->os.initrd = virXPathString(conn, "string(./os/initrd[1])", ctxt);
2523         def->os.cmdline = virXPathString(conn, "string(./os/cmdline[1])", ctxt);
2524         def->os.root = virXPathString(conn, "string(./os/root[1])", ctxt);
2525         def->os.loader = virXPathString(conn, "string(./os/loader[1])", ctxt);
2526     }
2527
2528     if (STREQ(def->os.type, "hvm")) {
2529         /* analysis of the boot devices */
2530         if ((n = virXPathNodeSet(conn, "./os/boot", ctxt, &nodes)) < 0) {
2531             virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2532                                  "%s", _("cannot extract boot device"));
2533             goto error;
2534         }
2535         for (i = 0 ; i < n && i < VIR_DOMAIN_BOOT_LAST ; i++) {
2536             int val;
2537             char *dev = virXMLPropString(nodes[i], "dev");
2538             if (!dev) {
2539                 virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2540                                      "%s", _("missing boot device"));
2541                 goto error;
2542             }
2543             if ((val = virDomainBootTypeFromString(dev)) < 0) {
2544                 virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2545                                      _("unknown boot device '%s'"),
2546                                      dev);
2547                 VIR_FREE(dev);
2548                 goto error;
2549             }
2550             VIR_FREE(dev);
2551             def->os.bootDevs[def->os.nBootDevs++] = val;
2552         }
2553         if (def->os.nBootDevs == 0) {
2554             def->os.nBootDevs = 1;
2555             def->os.bootDevs[0] = VIR_DOMAIN_BOOT_DISK;
2556         }
2557         VIR_FREE(nodes);
2558     }
2559
2560     def->emulator = virXPathString(conn, "string(./devices/emulator[1])", ctxt);
2561     if (!def->emulator && virCapabilitiesIsEmulatorRequired(caps)) {
2562         def->emulator = virDomainDefDefaultEmulator(conn, def, caps);
2563         if (!def->emulator)
2564             goto error;
2565     }
2566
2567     /* analysis of the disk devices */
2568     if ((n = virXPathNodeSet(conn, "./devices/disk", ctxt, &nodes)) < 0) {
2569         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2570                              "%s", _("cannot extract disk devices"));
2571         goto error;
2572     }
2573     if (n && VIR_ALLOC_N(def->disks, n) < 0)
2574         goto no_memory;
2575     for (i = 0 ; i < n ; i++) {
2576         virDomainDiskDefPtr disk = virDomainDiskDefParseXML(conn,
2577                                                             nodes[i],
2578                                                             flags);
2579         if (!disk)
2580             goto error;
2581
2582         def->disks[def->ndisks++] = disk;
2583     }
2584     qsort(def->disks, def->ndisks, sizeof(*def->disks),
2585           virDomainDiskQSort);
2586     VIR_FREE(nodes);
2587
2588     /* analysis of the filesystems */
2589     if ((n = virXPathNodeSet(conn, "./devices/filesystem", ctxt, &nodes)) < 0) {
2590         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2591                              "%s", _("cannot extract filesystem devices"));
2592         goto error;
2593     }
2594     if (n && VIR_ALLOC_N(def->fss, n) < 0)
2595         goto no_memory;
2596     for (i = 0 ; i < n ; i++) {
2597         virDomainFSDefPtr fs = virDomainFSDefParseXML(conn,
2598                                                       nodes[i],
2599                                                       flags);
2600         if (!fs)
2601             goto error;
2602
2603         def->fss[def->nfss++] = fs;
2604     }
2605     VIR_FREE(nodes);
2606
2607     /* analysis of the network devices */
2608     if ((n = virXPathNodeSet(conn, "./devices/interface", ctxt, &nodes)) < 0) {
2609         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2610                              "%s", _("cannot extract network devices"));
2611         goto error;
2612     }
2613     if (n && VIR_ALLOC_N(def->nets, n) < 0)
2614         goto no_memory;
2615     for (i = 0 ; i < n ; i++) {
2616         virDomainNetDefPtr net = virDomainNetDefParseXML(conn,
2617                                                          caps,
2618                                                          nodes[i],
2619                                                          flags);
2620         if (!net)
2621             goto error;
2622
2623         def->nets[def->nnets++] = net;
2624     }
2625     VIR_FREE(nodes);
2626
2627
2628     /* analysis of the character devices */
2629     if ((n = virXPathNodeSet(conn, "./devices/parallel", ctxt, &nodes)) < 0) {
2630         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2631                              "%s", _("cannot extract parallel devices"));
2632         goto error;
2633     }
2634     if (n && VIR_ALLOC_N(def->parallels, n) < 0)
2635         goto no_memory;
2636
2637     for (i = 0 ; i < n ; i++) {
2638         virDomainChrDefPtr chr = virDomainChrDefParseXML(conn,
2639                                                          nodes[i],
2640                                                          flags);
2641         if (!chr)
2642             goto error;
2643
2644         chr->dstPort = i;
2645         def->parallels[def->nparallels++] = chr;
2646     }
2647     VIR_FREE(nodes);
2648
2649     if ((n = virXPathNodeSet(conn, "./devices/serial", ctxt, &nodes)) < 0) {
2650         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2651                              "%s", _("cannot extract serial devices"));
2652         goto error;
2653     }
2654     if (n && VIR_ALLOC_N(def->serials, n) < 0)
2655         goto no_memory;
2656
2657     for (i = 0 ; i < n ; i++) {
2658         virDomainChrDefPtr chr = virDomainChrDefParseXML(conn,
2659                                                          nodes[i],
2660                                                          flags);
2661         if (!chr)
2662             goto error;
2663
2664         chr->dstPort = i;
2665         def->serials[def->nserials++] = chr;
2666     }
2667     VIR_FREE(nodes);
2668
2669     if ((node = virXPathNode(conn, "./devices/console[1]", ctxt)) != NULL) {
2670         virDomainChrDefPtr chr = virDomainChrDefParseXML(conn,
2671                                                          node,
2672                                                          flags);
2673         if (!chr)
2674             goto error;
2675
2676         chr->dstPort = 0;
2677         /*
2678          * For HVM console actually created a serial device
2679          * while for non-HVM it was a parvirt console
2680          */
2681         if (STREQ(def->os.type, "hvm")) {
2682             if (def->nserials != 0) {
2683                 virDomainChrDefFree(chr);
2684             } else {
2685                 if (VIR_ALLOC_N(def->serials, 1) < 0) {
2686                     virDomainChrDefFree(chr);
2687                     goto no_memory;
2688                 }
2689                 def->nserials = 1;
2690                 def->serials[0] = chr;
2691             }
2692         } else {
2693             def->console = chr;
2694         }
2695     }
2696
2697
2698     /* analysis of the input devices */
2699     if ((n = virXPathNodeSet(conn, "./devices/input", ctxt, &nodes)) < 0) {
2700         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2701                              "%s", _("cannot extract input devices"));
2702         goto error;
2703     }
2704     if (n && VIR_ALLOC_N(def->inputs, n) < 0)
2705         goto no_memory;
2706
2707     for (i = 0 ; i < n ; i++) {
2708         virDomainInputDefPtr input = virDomainInputDefParseXML(conn,
2709                                                                def->os.type,
2710                                                                nodes[i],
2711                                                                flags);
2712         if (!input)
2713             goto error;
2714
2715
2716         /* With QEMU / KVM / Xen graphics, mouse + PS/2 is implicit
2717          * with graphics, so don't store it.
2718          * XXX will this be true for other virt types ? */
2719         if ((STREQ(def->os.type, "hvm") &&
2720              input->bus == VIR_DOMAIN_INPUT_BUS_PS2 &&
2721              input->type == VIR_DOMAIN_INPUT_TYPE_MOUSE) ||
2722             (STRNEQ(def->os.type, "hvm") &&
2723              input->bus == VIR_DOMAIN_INPUT_BUS_XEN &&
2724              input->type == VIR_DOMAIN_INPUT_TYPE_MOUSE)) {
2725             virDomainInputDefFree(input);
2726             continue;
2727         }
2728
2729         def->inputs[def->ninputs++] = input;
2730     }
2731     VIR_FREE(nodes);
2732
2733     /* analysis of the graphics devices */
2734     if ((n = virXPathNodeSet(conn, "./devices/graphics", ctxt, &nodes)) < 0) {
2735         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2736                              "%s", _("cannot extract graphics devices"));
2737         goto error;
2738     }
2739     if (n && VIR_ALLOC_N(def->graphics, n) < 0)
2740         goto no_memory;
2741     for (i = 0 ; i < n ; i++) {
2742         virDomainGraphicsDefPtr graphics = virDomainGraphicsDefParseXML(conn,
2743                                                                         nodes[i],
2744                                                                         flags);
2745         if (!graphics)
2746             goto error;
2747
2748         def->graphics[def->ngraphics++] = graphics;
2749     }
2750     VIR_FREE(nodes);
2751
2752     /* If graphics are enabled, there's an implicit PS2 mouse */
2753     if (def->ngraphics > 0) {
2754         virDomainInputDefPtr input;
2755
2756         if (VIR_ALLOC(input) < 0) {
2757             virReportOOMError(conn);
2758             goto error;
2759         }
2760         if (STREQ(def->os.type, "hvm")) {
2761             input->type = VIR_DOMAIN_INPUT_TYPE_MOUSE;
2762             input->bus = VIR_DOMAIN_INPUT_BUS_PS2;
2763         } else {
2764             input->type = VIR_DOMAIN_INPUT_TYPE_MOUSE;
2765             input->bus = VIR_DOMAIN_INPUT_BUS_XEN;
2766         }
2767
2768         if (VIR_REALLOC_N(def->inputs, def->ninputs + 1) < 0) {
2769             virDomainInputDefFree(input);
2770             goto no_memory;
2771         }
2772         def->inputs[def->ninputs] = input;
2773         def->ninputs++;
2774     }
2775
2776
2777     /* analysis of the sound devices */
2778     if ((n = virXPathNodeSet(conn, "./devices/sound", ctxt, &nodes)) < 0) {
2779         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2780                              "%s", _("cannot extract sound devices"));
2781         goto error;
2782     }
2783     if (n && VIR_ALLOC_N(def->sounds, n) < 0)
2784         goto no_memory;
2785     for (i = 0 ; i < n ; i++) {
2786         int collision = 0, j;
2787         virDomainSoundDefPtr sound = virDomainSoundDefParseXML(conn,
2788                                                                nodes[i],
2789                                                                flags);
2790         if (!sound)
2791             goto error;
2792
2793         /* Verify there's no duplicated sound card */
2794         for (j = 0 ; j < def->nsounds ; j++) {
2795             if (def->sounds[j]->model == sound->model)
2796                 collision = 1;
2797         }
2798         if (collision) {
2799             virDomainSoundDefFree(sound);
2800             continue;
2801         }
2802
2803         def->sounds[def->nsounds++] = sound;
2804     }
2805     VIR_FREE(nodes);
2806
2807     /* analysis of the video devices */
2808     if ((n = virXPathNodeSet(conn, "./devices/video", ctxt, &nodes)) < 0) {
2809         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2810                              "%s", _("cannot extract video devices"));
2811         goto error;
2812     }
2813     if (n && VIR_ALLOC_N(def->videos, n) < 0)
2814         goto no_memory;
2815     for (i = 0 ; i < n ; i++) {
2816         virDomainVideoDefPtr video = virDomainVideoDefParseXML(conn,
2817                                                                nodes[i],
2818                                                                def,
2819                                                                flags);
2820         if (!video)
2821             goto error;
2822         def->videos[def->nvideos++] = video;
2823     }
2824     VIR_FREE(nodes);
2825
2826     /* For backwards compatability, if no <video> tag is set but there
2827      * is a <graphics> tag, then we add a single video tag */
2828     if (def->ngraphics && !def->nvideos) {
2829         virDomainVideoDefPtr video;
2830         if (VIR_ALLOC(video) < 0)
2831             goto no_memory;
2832         video->type = virDomainVideoDefaultType(def);
2833         if (video->type < 0) {
2834             virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
2835                                  _("cannot determine default video type"));
2836             VIR_FREE(video);
2837             goto error;
2838         }
2839         video->vram = virDomainVideoDefaultRAM(def, video->type);
2840         video->heads = 1;
2841         if (VIR_ALLOC_N(def->videos, 1) < 0) {
2842             virDomainVideoDefFree(video);
2843             goto no_memory;
2844         }
2845         def->videos[def->nvideos++] = video;
2846     }
2847
2848     /* analysis of the host devices */
2849     if ((n = virXPathNodeSet(conn, "./devices/hostdev", ctxt, &nodes)) < 0) {
2850         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2851                              "%s", _("cannot extract host devices"));
2852         goto error;
2853     }
2854     if (n && VIR_ALLOC_N(def->hostdevs, n) < 0)
2855         goto no_memory;
2856     for (i = 0 ; i < n ; i++) {
2857         virDomainHostdevDefPtr hostdev = virDomainHostdevDefParseXML(conn,
2858                                                                      nodes[i],
2859                                                                      flags);
2860         if (!hostdev)
2861             goto error;
2862
2863         def->hostdevs[def->nhostdevs++] = hostdev;
2864     }
2865     VIR_FREE(nodes);
2866
2867     /* analysis of security label */
2868     if (virSecurityLabelDefParseXML(conn, def, ctxt, flags) == -1)
2869         goto error;
2870
2871     return def;
2872
2873 no_memory:
2874     virReportOOMError(conn);
2875     /* fallthrough */
2876
2877  error:
2878     VIR_FREE(tmp);
2879     VIR_FREE(nodes);
2880     virDomainDefFree(def);
2881     return NULL;
2882 }
2883
2884
2885 static virDomainObjPtr virDomainObjParseXML(virConnectPtr conn,
2886                                             virCapsPtr caps,
2887                                             xmlXPathContextPtr ctxt)
2888 {
2889     char *tmp = NULL;
2890     long val;
2891     xmlNodePtr config;
2892     xmlNodePtr oldnode;
2893     virDomainObjPtr obj;
2894     char *monitorpath;
2895
2896     if (!(obj = virDomainObjNew(conn)))
2897         return NULL;
2898
2899     if (!(config = virXPathNode(conn, "./domain", ctxt))) {
2900         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2901                              "%s", _("no domain config"));
2902         goto error;
2903     }
2904
2905     oldnode = ctxt->node;
2906     ctxt->node = config;
2907     obj->def = virDomainDefParseXML(conn, caps, ctxt, 0);
2908     ctxt->node = oldnode;
2909     if (!obj->def)
2910         goto error;
2911
2912     if (!(tmp = virXPathString(conn, "string(./@state)", ctxt))) {
2913         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2914                              "%s", _("missing domain state"));
2915         goto error;
2916     }
2917     if ((obj->state = virDomainStateTypeFromString(tmp)) < 0) {
2918         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2919                              _("invalid domain state '%s'"), tmp);
2920         VIR_FREE(tmp);
2921         goto error;
2922     }
2923     VIR_FREE(tmp);
2924
2925     if ((virXPathLong(conn, "string(./@pid)", ctxt, &val)) < 0) {
2926         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2927                              "%s", _("invalid pid"));
2928         goto error;
2929     }
2930     obj->pid = (pid_t)val;
2931
2932     if (VIR_ALLOC(obj->monitor_chr) < 0) {
2933         virReportOOMError(conn);
2934         goto error;
2935     }
2936
2937     if (!(monitorpath =
2938           virXPathString(conn, "string(./monitor[1]/@path)", ctxt))) {
2939         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2940                              "%s", _("no monitor path"));
2941         goto error;
2942     }
2943
2944     tmp = virXPathString(conn, "string(./monitor[1]/@type)", ctxt);
2945     if (tmp)
2946         obj->monitor_chr->type = virDomainChrTypeFromString(tmp);
2947     else
2948         obj->monitor_chr->type = VIR_DOMAIN_CHR_TYPE_PTY;
2949     VIR_FREE(tmp);
2950
2951     switch (obj->monitor_chr->type) {
2952     case VIR_DOMAIN_CHR_TYPE_PTY:
2953         obj->monitor_chr->data.file.path = monitorpath;
2954         break;
2955     case VIR_DOMAIN_CHR_TYPE_UNIX:
2956         obj->monitor_chr->data.nix.path = monitorpath;
2957         break;
2958     default:
2959         VIR_FREE(monitorpath);
2960         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2961                              _("unsupported monitor type '%s'"),
2962                              virDomainChrTypeToString(obj->monitor_chr->type));
2963         break;
2964     }
2965
2966     return obj;
2967
2968 error:
2969     virDomainChrDefFree(obj->monitor_chr);
2970     virDomainObjFree(obj);
2971     return NULL;
2972 }
2973
2974
2975 /* Called from SAX on parsing errors in the XML. */
2976 static void
2977 catchXMLError (void *ctx, const char *msg ATTRIBUTE_UNUSED, ...)
2978 {
2979     xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
2980
2981     if (ctxt) {
2982         virConnectPtr conn = ctxt->_private;
2983
2984         if (virGetLastError() == NULL &&
2985             ctxt->lastError.level == XML_ERR_FATAL &&
2986             ctxt->lastError.message != NULL) {
2987             virDomainReportError (conn, VIR_ERR_XML_DETAIL,
2988                                   _("at line %d: %s"),
2989                                   ctxt->lastError.line,
2990                                   ctxt->lastError.message);
2991         }
2992     }
2993 }
2994
2995 virDomainDefPtr virDomainDefParseString(virConnectPtr conn,
2996                                         virCapsPtr caps,
2997                                         const char *xmlStr,
2998                                         int flags)
2999 {
3000     xmlParserCtxtPtr pctxt;
3001     xmlDocPtr xml = NULL;
3002     xmlNodePtr root;
3003     virDomainDefPtr def = NULL;
3004
3005     /* Set up a parser context so we can catch the details of XML errors. */
3006     pctxt = xmlNewParserCtxt ();
3007     if (!pctxt || !pctxt->sax)
3008         goto cleanup;
3009     pctxt->sax->error = catchXMLError;
3010     pctxt->_private = conn;
3011
3012     if (conn) virResetError (&conn->err);
3013     xml = xmlCtxtReadDoc (pctxt, BAD_CAST xmlStr, "domain.xml", NULL,
3014                           XML_PARSE_NOENT | XML_PARSE_NONET |
3015                           XML_PARSE_NOWARNING);
3016     if (!xml) {
3017         if (virGetLastError() == NULL)
3018               virDomainReportError(conn, VIR_ERR_XML_ERROR,
3019                                    "%s", _("failed to parse xml document"));
3020         goto cleanup;
3021     }
3022
3023     if ((root = xmlDocGetRootElement(xml)) == NULL) {
3024         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3025                               "%s", _("missing root element"));
3026         goto cleanup;
3027     }
3028
3029     def = virDomainDefParseNode(conn, caps, xml, root, flags);
3030
3031 cleanup:
3032     xmlFreeParserCtxt (pctxt);
3033     xmlFreeDoc (xml);
3034     return def;
3035 }
3036
3037 virDomainDefPtr virDomainDefParseFile(virConnectPtr conn,
3038                                       virCapsPtr caps,
3039                                       const char *filename, int flags)
3040 {
3041     xmlParserCtxtPtr pctxt;
3042     xmlDocPtr xml = NULL;
3043     xmlNodePtr root;
3044     virDomainDefPtr def = NULL;
3045
3046     /* Set up a parser context so we can catch the details of XML errors. */
3047     pctxt = xmlNewParserCtxt ();
3048     if (!pctxt || !pctxt->sax)
3049         goto cleanup;
3050     pctxt->sax->error = catchXMLError;
3051     pctxt->_private = conn;
3052
3053     if (conn) virResetError (&conn->err);
3054     xml = xmlCtxtReadFile (pctxt, filename, NULL,
3055                            XML_PARSE_NOENT | XML_PARSE_NONET |
3056                            XML_PARSE_NOWARNING);
3057     if (!xml) {
3058         if (virGetLastError() == NULL)
3059               virDomainReportError(conn, VIR_ERR_XML_ERROR,
3060                                    "%s", _("failed to parse xml document"));
3061         goto cleanup;
3062     }
3063
3064     if ((root = xmlDocGetRootElement(xml)) == NULL) {
3065         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3066                               "%s", _("missing root element"));
3067         goto cleanup;
3068     }
3069
3070     def = virDomainDefParseNode(conn, caps, xml, root, flags);
3071
3072 cleanup:
3073     xmlFreeParserCtxt (pctxt);
3074     xmlFreeDoc (xml);
3075     return def;
3076 }
3077
3078
3079 virDomainDefPtr virDomainDefParseNode(virConnectPtr conn,
3080                                       virCapsPtr caps,
3081                                       xmlDocPtr xml,
3082                                       xmlNodePtr root,
3083                                       int flags)
3084 {
3085     xmlXPathContextPtr ctxt = NULL;
3086     virDomainDefPtr def = NULL;
3087
3088     if (!xmlStrEqual(root->name, BAD_CAST "domain")) {
3089         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3090                               "%s", _("incorrect root element"));
3091         goto cleanup;
3092     }
3093
3094     ctxt = xmlXPathNewContext(xml);
3095     if (ctxt == NULL) {
3096         virReportOOMError(conn);
3097         goto cleanup;
3098     }
3099
3100     ctxt->node = root;
3101     def = virDomainDefParseXML(conn, caps, ctxt, flags);
3102
3103 cleanup:
3104     xmlXPathFreeContext(ctxt);
3105     return def;
3106 }
3107
3108
3109 virDomainObjPtr virDomainObjParseFile(virConnectPtr conn,
3110                                       virCapsPtr caps,
3111                                       const char *filename)
3112 {
3113     xmlParserCtxtPtr pctxt;
3114     xmlDocPtr xml = NULL;
3115     xmlNodePtr root;
3116     virDomainObjPtr obj = NULL;
3117
3118     /* Set up a parser context so we can catch the details of XML errors. */
3119     pctxt = xmlNewParserCtxt ();
3120     if (!pctxt || !pctxt->sax)
3121         goto cleanup;
3122     pctxt->sax->error = catchXMLError;
3123     pctxt->_private = conn;
3124
3125     if (conn) virResetError (&conn->err);
3126     xml = xmlCtxtReadFile (pctxt, filename, NULL,
3127                            XML_PARSE_NOENT | XML_PARSE_NONET |
3128                            XML_PARSE_NOWARNING);
3129     if (!xml) {
3130         if (virGetLastError() == NULL)
3131               virDomainReportError(conn, VIR_ERR_XML_ERROR,
3132                                    "%s", _("failed to parse xml document"));
3133         goto cleanup;
3134     }
3135
3136     if ((root = xmlDocGetRootElement(xml)) == NULL) {
3137         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3138                               "%s", _("missing root element"));
3139         goto cleanup;
3140     }
3141
3142     obj = virDomainObjParseNode(conn, caps, xml, root);
3143
3144 cleanup:
3145     xmlFreeParserCtxt (pctxt);
3146     xmlFreeDoc (xml);
3147     return obj;
3148 }
3149
3150
3151 virDomainObjPtr virDomainObjParseNode(virConnectPtr conn,
3152                                       virCapsPtr caps,
3153                                       xmlDocPtr xml,
3154                                       xmlNodePtr root)
3155 {
3156     xmlXPathContextPtr ctxt = NULL;
3157     virDomainObjPtr obj = NULL;
3158
3159     if (!xmlStrEqual(root->name, BAD_CAST "domstatus")) {
3160         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3161                              "%s", _("incorrect root element"));
3162         goto cleanup;
3163     }
3164
3165     ctxt = xmlXPathNewContext(xml);
3166     if (ctxt == NULL) {
3167         virReportOOMError(conn);
3168         goto cleanup;
3169     }
3170
3171     ctxt->node = root;
3172     obj = virDomainObjParseXML(conn, caps, ctxt);
3173
3174 cleanup:
3175     xmlXPathFreeContext(ctxt);
3176     return obj;
3177 }
3178
3179 #endif /* ! PROXY */
3180
3181 /************************************************************************
3182  *                                                                        *
3183  * Parser and converter for the CPUset strings used in libvirt                *
3184  *                                                                        *
3185  ************************************************************************/
3186 /**
3187  * virDomainCpuNumberParse
3188  * @str: pointer to the char pointer used
3189  * @maxcpu: maximum CPU number allowed
3190  *
3191  * Parse a CPU number
3192  *
3193  * Returns the CPU number or -1 in case of error. @str will be
3194  *         updated to skip the number.
3195  */
3196 static int
3197 virDomainCpuNumberParse(const char **str, int maxcpu)
3198 {
3199     int ret = 0;
3200     const char *cur = *str;
3201
3202     if (!c_isdigit(*cur))
3203         return (-1);
3204
3205     while (c_isdigit(*cur)) {
3206         ret = ret * 10 + (*cur - '0');
3207         if (ret >= maxcpu)
3208             return (-1);
3209         cur++;
3210     }
3211     *str = cur;
3212     return (ret);
3213 }
3214
3215 /**
3216  * virDomainCpuSetFormat:
3217  * @conn: connection
3218  * @cpuset: pointer to a char array for the CPU set
3219  * @maxcpu: number of elements available in @cpuset
3220  *
3221  * Serialize the cpuset to a string
3222  *
3223  * Returns the new string NULL in case of error. The string need to be
3224  *         freed by the caller.
3225  */
3226 char *
3227 virDomainCpuSetFormat(virConnectPtr conn, char *cpuset, int maxcpu)
3228 {
3229     virBuffer buf = VIR_BUFFER_INITIALIZER;
3230     int start, cur;
3231     int first = 1;
3232
3233     if ((cpuset == NULL) || (maxcpu <= 0) || (maxcpu > 100000))
3234         return (NULL);
3235
3236     cur = 0;
3237     start = -1;
3238     while (cur < maxcpu) {
3239         if (cpuset[cur]) {
3240             if (start == -1)
3241                 start = cur;
3242         } else if (start != -1) {
3243             if (!first)
3244                 virBufferAddLit(&buf, ",");
3245             else
3246                 first = 0;
3247             if (cur == start + 1)
3248                 virBufferVSprintf(&buf, "%d", start);
3249             else
3250                 virBufferVSprintf(&buf, "%d-%d", start, cur - 1);
3251             start = -1;
3252         }
3253         cur++;
3254     }
3255     if (start != -1) {
3256         if (!first)
3257             virBufferAddLit(&buf, ",");
3258         if (maxcpu == start + 1)
3259             virBufferVSprintf(&buf, "%d", start);
3260         else
3261             virBufferVSprintf(&buf, "%d-%d", start, maxcpu - 1);
3262     }
3263
3264     if (virBufferError(&buf)) {
3265         virReportOOMError(conn);
3266         return NULL;
3267     }
3268
3269     return virBufferContentAndReset(&buf);
3270 }
3271
3272 /**
3273  * virDomainCpuSetParse:
3274  * @conn: connection
3275  * @str: pointer to a CPU set string pointer
3276  * @sep: potential character used to mark the end of string if not 0
3277  * @cpuset: pointer to a char array for the CPU set
3278  * @maxcpu: number of elements available in @cpuset
3279  *
3280  * Parse the cpu set, it will set the value for enabled CPUs in the @cpuset
3281  * to 1, and 0 otherwise. The syntax allows coma separated entries each
3282  * can be either a CPU number, ^N to unset that CPU or N-M for ranges.
3283  *
3284  * Returns the number of CPU found in that set, or -1 in case of error.
3285  *         @cpuset is modified accordingly to the value parsed.
3286  *         @str is updated to the end of the part parsed
3287  */
3288 int
3289 virDomainCpuSetParse(virConnectPtr conn, const char **str, char sep,
3290                      char *cpuset, int maxcpu)
3291 {
3292     const char *cur;
3293     int ret = 0;
3294     int i, start, last;
3295     int neg = 0;
3296
3297     if ((str == NULL) || (cpuset == NULL) || (maxcpu <= 0) ||
3298         (maxcpu > 100000))
3299         return (-1);
3300
3301     cur = *str;
3302     virSkipSpaces(&cur);
3303     if (*cur == 0)
3304         goto parse_error;
3305
3306     /* initialize cpumap to all 0s */
3307     for (i = 0; i < maxcpu; i++)
3308         cpuset[i] = 0;
3309     ret = 0;
3310
3311     while ((*cur != 0) && (*cur != sep)) {
3312         /*
3313          * 3 constructs are allowed:
3314          *     - N   : a single CPU number
3315          *     - N-M : a range of CPU numbers with N < M
3316          *     - ^N  : remove a single CPU number from the current set
3317          */
3318         if (*cur == '^') {
3319             cur++;
3320             neg = 1;
3321         }
3322
3323         if (!c_isdigit(*cur))
3324             goto parse_error;
3325         start = virDomainCpuNumberParse(&cur, maxcpu);
3326         if (start < 0)
3327             goto parse_error;
3328         virSkipSpaces(&cur);
3329         if ((*cur == ',') || (*cur == 0) || (*cur == sep)) {
3330             if (neg) {
3331                 if (cpuset[start] == 1) {
3332                     cpuset[start] = 0;
3333                     ret--;
3334                 }
3335             } else {
3336                 if (cpuset[start] == 0) {
3337                     cpuset[start] = 1;
3338                     ret++;
3339                 }
3340             }
3341         } else if (*cur == '-') {
3342             if (neg)
3343                 goto parse_error;
3344             cur++;
3345             virSkipSpaces(&cur);
3346             last = virDomainCpuNumberParse(&cur, maxcpu);
3347             if (last < start)
3348                 goto parse_error;
3349             for (i = start; i <= last; i++) {
3350                 if (cpuset[i] == 0) {
3351                     cpuset[i] = 1;
3352                     ret++;
3353                 }
3354             }
3355             virSkipSpaces(&cur);
3356         }
3357         if (*cur == ',') {
3358             cur++;
3359             virSkipSpaces(&cur);
3360             neg = 0;
3361         } else if ((*cur == 0) || (*cur == sep)) {
3362             break;
3363         } else
3364             goto parse_error;
3365     }
3366     *str = cur;
3367     return (ret);
3368
3369   parse_error:
3370     virDomainReportError(conn, VIR_ERR_XEN_CALL,
3371                          "%s", _("topology cpuset syntax error"));
3372     return (-1);
3373 }
3374
3375
3376 static int
3377 virDomainLifecycleDefFormat(virConnectPtr conn,
3378                             virBufferPtr buf,
3379                             int type,
3380                             const char *name)
3381 {
3382     const char *typeStr = virDomainLifecycleTypeToString(type);
3383     if (!typeStr) {
3384         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3385                              _("unexpected lifecycle type %d"), type);
3386         return -1;
3387     }
3388
3389     virBufferVSprintf(buf, "  <%s>%s</%s>\n", name, typeStr, name);
3390
3391     return 0;
3392 }
3393
3394
3395 static int
3396 virDomainDiskDefFormat(virConnectPtr conn,
3397                        virBufferPtr buf,
3398                        virDomainDiskDefPtr def)
3399 {
3400     const char *type = virDomainDiskTypeToString(def->type);
3401     const char *device = virDomainDiskDeviceTypeToString(def->device);
3402     const char *bus = virDomainDiskBusTypeToString(def->bus);
3403     const char *cachemode = virDomainDiskCacheTypeToString(def->cachemode);
3404
3405     if (!type) {
3406         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3407                              _("unexpected disk type %d"), def->type);
3408         return -1;
3409     }
3410     if (!device) {
3411         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3412                              _("unexpected disk device %d"), def->device);
3413         return -1;
3414     }
3415     if (!bus) {
3416         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3417                              _("unexpected disk bus %d"), def->bus);
3418         return -1;
3419     }
3420     if (!cachemode) {
3421         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3422                              _("unexpected disk cache mode %d"), def->cachemode);
3423         return -1;
3424     }
3425
3426     virBufferVSprintf(buf,
3427                       "    <disk type='%s' device='%s'>\n",
3428                       type, device);
3429
3430     if (def->driverName) {
3431         virBufferVSprintf(buf, "      <driver name='%s'", def->driverName);
3432         if (def->driverType)
3433             virBufferVSprintf(buf, " type='%s'", def->driverType);
3434         if (def->cachemode)
3435             virBufferVSprintf(buf, " cache='%s'", cachemode);
3436         virBufferVSprintf(buf, "/>\n");
3437     }
3438
3439     if (def->src) {
3440         if (def->type == VIR_DOMAIN_DISK_TYPE_FILE)
3441             virBufferEscapeString(buf, "      <source file='%s'/>\n",
3442                                   def->src);
3443         else
3444             virBufferEscapeString(buf, "      <source dev='%s'/>\n",
3445                                   def->src);
3446     }
3447
3448     virBufferVSprintf(buf, "      <target dev='%s' bus='%s'/>\n",
3449                       def->dst, bus);
3450
3451     if (def->readonly)
3452         virBufferAddLit(buf, "      <readonly/>\n");
3453     if (def->shared)
3454         virBufferAddLit(buf, "      <shareable/>\n");
3455
3456     virBufferAddLit(buf, "    </disk>\n");
3457
3458     return 0;
3459 }
3460
3461 static int
3462 virDomainFSDefFormat(virConnectPtr conn,
3463                      virBufferPtr buf,
3464                      virDomainFSDefPtr def)
3465 {
3466     const char *type = virDomainFSTypeToString(def->type);
3467
3468     if (!type) {
3469         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3470                              _("unexpected filesystem type %d"), def->type);
3471         return -1;
3472     }
3473
3474     virBufferVSprintf(buf,
3475                       "    <filesystem type='%s'>\n",
3476                       type);
3477
3478     if (def->src) {
3479         switch (def->type) {
3480         case VIR_DOMAIN_FS_TYPE_MOUNT:
3481             virBufferEscapeString(buf, "      <source dir='%s'/>\n",
3482                                   def->src);
3483             break;
3484
3485         case VIR_DOMAIN_FS_TYPE_BLOCK:
3486             virBufferEscapeString(buf, "      <source dev='%s'/>\n",
3487                                   def->src);
3488             break;
3489
3490         case VIR_DOMAIN_FS_TYPE_FILE:
3491             virBufferEscapeString(buf, "      <source file='%s'/>\n",
3492                                   def->src);
3493             break;
3494
3495         case VIR_DOMAIN_FS_TYPE_TEMPLATE:
3496             virBufferEscapeString(buf, "      <source name='%s'/>\n",
3497                                   def->src);
3498         }
3499     }
3500
3501     virBufferVSprintf(buf, "      <target dir='%s'/>\n",
3502                       def->dst);
3503
3504     if (def->readonly)
3505         virBufferAddLit(buf, "      <readonly/>\n");
3506
3507     virBufferAddLit(buf, "    </filesystem>\n");
3508
3509     return 0;
3510 }
3511
3512 static int
3513 virDomainNetDefFormat(virConnectPtr conn,
3514                       virBufferPtr buf,
3515                       virDomainNetDefPtr def)
3516 {
3517     const char *type = virDomainNetTypeToString(def->type);
3518
3519     if (!type) {
3520         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3521                              _("unexpected net type %d"), def->type);
3522         return -1;
3523     }
3524
3525     virBufferVSprintf(buf, "    <interface type='%s'>\n", type);
3526
3527     virBufferVSprintf(buf,
3528                       "      <mac address='%02x:%02x:%02x:%02x:%02x:%02x'/>\n",
3529                       def->mac[0], def->mac[1], def->mac[2],
3530                       def->mac[3], def->mac[4], def->mac[5]);
3531
3532     switch (def->type) {
3533     case VIR_DOMAIN_NET_TYPE_NETWORK:
3534         virBufferEscapeString(buf, "      <source network='%s'/>\n",
3535                               def->data.network.name);
3536         break;
3537
3538     case VIR_DOMAIN_NET_TYPE_ETHERNET:
3539         if (def->data.ethernet.dev)
3540             virBufferEscapeString(buf, "      <source dev='%s'/>\n",
3541                                   def->data.ethernet.dev);
3542         if (def->data.ethernet.ipaddr)
3543             virBufferVSprintf(buf, "      <ip address='%s'/>\n",
3544                               def->data.ethernet.ipaddr);
3545         if (def->data.ethernet.script)
3546             virBufferEscapeString(buf, "      <script path='%s'/>\n",
3547                                   def->data.ethernet.script);
3548         break;
3549
3550     case VIR_DOMAIN_NET_TYPE_BRIDGE:
3551         virBufferEscapeString(buf, "      <source bridge='%s'/>\n",
3552                               def->data.bridge.brname);
3553         if (def->data.bridge.ipaddr)
3554             virBufferVSprintf(buf, "      <ip address='%s'/>\n",
3555                               def->data.bridge.ipaddr);
3556         if (def->data.bridge.script)
3557             virBufferEscapeString(buf, "      <script path='%s'/>\n",
3558                                   def->data.bridge.script);
3559         break;
3560
3561     case VIR_DOMAIN_NET_TYPE_SERVER:
3562     case VIR_DOMAIN_NET_TYPE_CLIENT:
3563     case VIR_DOMAIN_NET_TYPE_MCAST:
3564         if (def->data.socket.address)
3565             virBufferVSprintf(buf, "      <source address='%s' port='%d'/>\n",
3566                               def->data.socket.address, def->data.socket.port);
3567         else
3568             virBufferVSprintf(buf, "      <source port='%d'/>\n",
3569                               def->data.socket.port);
3570         break;
3571
3572     case VIR_DOMAIN_NET_TYPE_INTERNAL:
3573         virBufferEscapeString(buf, "      <source name='%s'/>\n",
3574                               def->data.internal.name);
3575         break;
3576
3577     }
3578
3579     if (def->ifname)
3580         virBufferEscapeString(buf, "      <target dev='%s'/>\n",
3581                               def->ifname);
3582     if (def->model)
3583         virBufferEscapeString(buf, "      <model type='%s'/>\n",
3584                               def->model);
3585
3586     virBufferAddLit(buf, "    </interface>\n");
3587
3588     return 0;
3589 }
3590
3591
3592 static int
3593 virDomainChrDefFormat(virConnectPtr conn,
3594                       virBufferPtr buf,
3595                       virDomainChrDefPtr def,
3596                       const char *name,
3597                       int flags)
3598 {
3599     const char *type = virDomainChrTypeToString(def->type);
3600
3601     if (!type) {
3602         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3603                              _("unexpected char type %d"), def->type);
3604         return -1;
3605     }
3606
3607     /* Compat with legacy  <console tty='/dev/pts/5'/> syntax */
3608     virBufferVSprintf(buf, "    <%s type='%s'",
3609                       name, type);
3610     if (STREQ(name, "console") &&
3611         def->type == VIR_DOMAIN_CHR_TYPE_PTY &&
3612         !(flags & VIR_DOMAIN_XML_INACTIVE) &&
3613         def->data.file.path) {
3614         virBufferEscapeString(buf, " tty='%s'>\n",
3615                               def->data.file.path);
3616     } else {
3617         virBufferAddLit(buf, ">\n");
3618     }
3619
3620     switch (def->type) {
3621     case VIR_DOMAIN_CHR_TYPE_NULL:
3622     case VIR_DOMAIN_CHR_TYPE_VC:
3623     case VIR_DOMAIN_CHR_TYPE_STDIO:
3624         /* nada */
3625         break;
3626
3627     case VIR_DOMAIN_CHR_TYPE_PTY:
3628     case VIR_DOMAIN_CHR_TYPE_DEV:
3629     case VIR_DOMAIN_CHR_TYPE_FILE:
3630     case VIR_DOMAIN_CHR_TYPE_PIPE:
3631         if (def->type != VIR_DOMAIN_CHR_TYPE_PTY ||
3632             (def->data.file.path && !(flags & VIR_DOMAIN_XML_INACTIVE))) {
3633             virBufferEscapeString(buf, "      <source path='%s'/>\n",
3634                                   def->data.file.path);
3635         }
3636         break;
3637
3638     case VIR_DOMAIN_CHR_TYPE_UDP:
3639         if (def->data.udp.bindService &&
3640             def->data.udp.bindHost) {
3641             virBufferVSprintf(buf, "      <source mode='bind' host='%s' service='%s'/>\n",
3642                               def->data.udp.bindHost,
3643                               def->data.udp.bindService);
3644         } else if (def->data.udp.bindHost) {
3645             virBufferVSprintf(buf, "      <source mode='bind' host='%s'/>\n",
3646                               def->data.udp.bindHost);
3647         } else if (def->data.udp.bindService) {
3648             virBufferVSprintf(buf, "      <source mode='bind' service='%s'/>\n",
3649                               def->data.udp.bindService);
3650         }
3651
3652         if (def->data.udp.connectService &&
3653             def->data.udp.connectHost) {
3654             virBufferVSprintf(buf, "      <source mode='connect' host='%s' service='%s'/>\n",
3655                               def->data.udp.connectHost,
3656                               def->data.udp.connectService);
3657         } else if (def->data.udp.connectHost) {
3658             virBufferVSprintf(buf, "      <source mode='connect' host='%s'/>\n",
3659                               def->data.udp.connectHost);
3660         } else if (def->data.udp.connectService) {
3661             virBufferVSprintf(buf, "      <source mode='connect' service='%s'/>\n",
3662                               def->data.udp.connectService);
3663         }
3664         break;
3665
3666     case VIR_DOMAIN_CHR_TYPE_TCP:
3667         virBufferVSprintf(buf, "      <source mode='%s' host='%s' service='%s'/>\n",
3668                           def->data.tcp.listen ? "bind" : "connect",
3669                           def->data.tcp.host,
3670                           def->data.tcp.service);
3671         virBufferVSprintf(buf, "      <protocol type='%s'/>\n",
3672                           def->data.tcp.protocol ==
3673                           VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET
3674                           ? "telnet" : "raw");
3675         break;
3676
3677     case VIR_DOMAIN_CHR_TYPE_UNIX:
3678         virBufferVSprintf(buf, "      <source mode='%s'",
3679                           def->data.nix.listen ? "bind" : "connect");
3680         virBufferEscapeString(buf, " path='%s'/>\n",
3681                               def->data.nix.path);
3682         break;
3683     }
3684
3685     virBufferVSprintf(buf, "      <target port='%d'/>\n",
3686                       def->dstPort);
3687
3688     virBufferVSprintf(buf, "    </%s>\n",
3689                       name);
3690
3691     return 0;
3692 }
3693
3694 static int
3695 virDomainSoundDefFormat(virConnectPtr conn,
3696                         virBufferPtr buf,
3697                         virDomainSoundDefPtr def)
3698 {
3699     const char *model = virDomainSoundModelTypeToString(def->model);
3700
3701     if (!model) {
3702         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3703                              _("unexpected sound model %d"), def->model);
3704         return -1;
3705     }
3706
3707     virBufferVSprintf(buf, "    <sound model='%s'/>\n",
3708                       model);
3709
3710     return 0;
3711 }
3712
3713 static int
3714 virDomainVideoDefFormat(virConnectPtr conn,
3715                         virBufferPtr buf,
3716                         virDomainVideoDefPtr def)
3717 {
3718     const char *model = virDomainVideoTypeToString(def->type);
3719
3720     if (!model) {
3721         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3722                              _("unexpected video model %d"), def->type);
3723         return -1;
3724     }
3725
3726     virBufferAddLit(buf, "    <video>\n");
3727     virBufferVSprintf(buf, "      <model type='%s'",
3728                       model);
3729     if (def->vram)
3730         virBufferVSprintf(buf, " vram='%u'", def->vram);
3731     if (def->heads)
3732         virBufferVSprintf(buf, " heads='%u'", def->heads);
3733     virBufferAddLit(buf, "/>\n");
3734     virBufferAddLit(buf, "    </video>\n");
3735
3736     return 0;
3737 }
3738
3739 static int
3740 virDomainInputDefFormat(virConnectPtr conn,
3741                         virBufferPtr buf,
3742                         virDomainInputDefPtr def)
3743 {
3744     const char *type = virDomainInputTypeToString(def->type);
3745     const char *bus = virDomainInputBusTypeToString(def->bus);
3746
3747     if (!type) {
3748         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3749                              _("unexpected input type %d"), def->type);
3750         return -1;
3751     }
3752     if (!bus) {
3753         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3754                              _("unexpected input bus type %d"), def->bus);
3755         return -1;
3756     }
3757
3758     virBufferVSprintf(buf, "    <input type='%s' bus='%s'/>\n",
3759                       type, bus);
3760
3761     return 0;
3762 }
3763
3764
3765 static int
3766 virDomainGraphicsDefFormat(virConnectPtr conn,
3767                            virBufferPtr buf,
3768                            virDomainDefPtr vm,
3769                            virDomainGraphicsDefPtr def,
3770                            int flags)
3771 {
3772     const char *type = virDomainGraphicsTypeToString(def->type);
3773
3774     if (!type) {
3775         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3776                              _("unexpected net type %d"), def->type);
3777         return -1;
3778     }
3779
3780     virBufferVSprintf(buf, "    <graphics type='%s'", type);
3781
3782     switch (def->type) {
3783     case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
3784         if (def->data.vnc.port &&
3785             (!def->data.vnc.autoport || vm->id != -1))
3786             virBufferVSprintf(buf, " port='%d'",
3787                               def->data.vnc.port);
3788         else if (def->data.vnc.autoport)
3789             virBufferAddLit(buf, " port='-1'");
3790
3791         virBufferVSprintf(buf, " autoport='%s'",
3792                           def->data.vnc.autoport ? "yes" : "no");
3793
3794         if (def->data.vnc.listenAddr)
3795             virBufferVSprintf(buf, " listen='%s'",
3796                               def->data.vnc.listenAddr);
3797
3798         if (def->data.vnc.keymap)
3799             virBufferEscapeString(buf, " keymap='%s'",
3800                                   def->data.vnc.keymap);
3801
3802         if (def->data.vnc.passwd &&
3803             (flags & VIR_DOMAIN_XML_SECURE))
3804             virBufferEscapeString(buf, " passwd='%s'",
3805                                   def->data.vnc.passwd);
3806
3807         break;
3808
3809     case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
3810         if (def->data.sdl.display)
3811             virBufferEscapeString(buf, " display='%s'",
3812                                   def->data.sdl.display);
3813
3814         if (def->data.sdl.xauth)
3815             virBufferEscapeString(buf, " xauth='%s'",
3816                                   def->data.sdl.xauth);
3817         if (def->data.sdl.fullscreen)
3818             virBufferAddLit(buf, " fullscreen='yes'");
3819
3820         break;
3821
3822     case VIR_DOMAIN_GRAPHICS_TYPE_RDP:
3823         if (def->data.rdp.port)
3824             virBufferVSprintf(buf, " port='%d'",
3825                               def->data.rdp.port);
3826         else if (def->data.rdp.autoport)
3827             virBufferAddLit(buf, " port='0'");
3828
3829         if (def->data.rdp.autoport)
3830             virBufferVSprintf(buf, " autoport='yes'");
3831
3832         if (def->data.rdp.replaceUser)
3833             virBufferVSprintf(buf, " replaceUser='yes'");
3834
3835         if (def->data.rdp.multiUser)
3836             virBufferVSprintf(buf, " multiUser='yes'");
3837
3838         if (def->data.rdp.listenAddr)
3839             virBufferVSprintf(buf, " listen='%s'", def->data.rdp.listenAddr);
3840
3841         break;
3842
3843     case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
3844         if (def->data.desktop.display)
3845             virBufferEscapeString(buf, " display='%s'",
3846                                   def->data.desktop.display);
3847
3848         if (def->data.desktop.fullscreen)
3849             virBufferAddLit(buf, " fullscreen='yes'");
3850
3851         break;
3852
3853     }
3854
3855     virBufferAddLit(buf, "/>\n");
3856
3857     return 0;
3858 }
3859
3860
3861 static int
3862 virDomainHostdevDefFormat(virConnectPtr conn,
3863                           virBufferPtr buf,
3864                           virDomainHostdevDefPtr def)
3865 {
3866     const char *mode = virDomainHostdevModeTypeToString(def->mode);
3867     const char *type;
3868
3869     if (!mode || def->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) {
3870         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3871                              _("unexpected hostdev mode %d"), def->mode);
3872         return -1;
3873     }
3874
3875     type = virDomainHostdevSubsysTypeToString(def->source.subsys.type);
3876     if (!type || (def->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB && def->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) ) {
3877         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3878                              _("unexpected hostdev type %d"),
3879                              def->source.subsys.type);
3880         return -1;
3881     }
3882
3883     virBufferVSprintf(buf, "    <hostdev mode='%s' type='%s' managed='%s'>\n",
3884                       mode, type, def->managed ? "yes" : "no");
3885     virBufferAddLit(buf, "      <source>\n");
3886
3887     if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
3888         if (def->source.subsys.u.usb.vendor) {
3889             virBufferVSprintf(buf, "        <vendor id='0x%.4x'/>\n",
3890                               def->source.subsys.u.usb.vendor);
3891             virBufferVSprintf(buf, "        <product id='0x%.4x'/>\n",
3892                               def->source.subsys.u.usb.product);
3893         } else {
3894             virBufferVSprintf(buf, "        <address bus='%d' device='%d'/>\n",
3895                               def->source.subsys.u.usb.bus,
3896                               def->source.subsys.u.usb.device);
3897         }
3898     }
3899     if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
3900         virBufferVSprintf(buf, "        <address domain='0x%.4x' bus='0x%.2x' slot='0x%.2x' function='0x%.1x'/>\n",
3901                           def->source.subsys.u.pci.domain,
3902                           def->source.subsys.u.pci.bus,
3903                           def->source.subsys.u.pci.slot,
3904                           def->source.subsys.u.pci.function);
3905     }
3906
3907     virBufferAddLit(buf, "      </source>\n");
3908     virBufferAddLit(buf, "    </hostdev>\n");
3909
3910     return 0;
3911 }
3912
3913
3914 char *virDomainDefFormat(virConnectPtr conn,
3915                          virDomainDefPtr def,
3916                          int flags)
3917 {
3918     virBuffer buf = VIR_BUFFER_INITIALIZER;
3919     unsigned char *uuid;
3920     char uuidstr[VIR_UUID_STRING_BUFLEN];
3921     const char *type = NULL, *tmp;
3922     int n, allones = 1;
3923
3924     if (!(type = virDomainVirtTypeToString(def->virtType))) {
3925         virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3926                          _("unexpected domain type %d"), def->virtType);
3927         goto cleanup;
3928     }
3929
3930     if&nbs