2
* domain_conf.c: domain XML processing
4
* Copyright (C) 2006-2009 Red Hat, Inc.
5
* Copyright (C) 2006-2008 Daniel P. Berrange
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.
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.
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
21
* Author: Daniel P. Berrange <berrange@redhat.com>
26
#include <sys/types.h>
32
#include "virterror_internal.h"
33
#include "datatypes.h"
34
#include "domain_conf.h"
44
#define VIR_FROM_THIS VIR_FROM_DOMAIN
46
VIR_ENUM_IMPL(virDomainVirt, VIR_DOMAIN_VIRT_LAST,
63
VIR_ENUM_IMPL(virDomainBoot, VIR_DOMAIN_BOOT_LAST,
69
VIR_ENUM_IMPL(virDomainFeature, VIR_DOMAIN_FEATURE_LAST,
74
VIR_ENUM_IMPL(virDomainLifecycle, VIR_DOMAIN_LIFECYCLE_LAST,
80
VIR_ENUM_IMPL(virDomainDevice, VIR_DOMAIN_DEVICE_LAST,
89
VIR_ENUM_IMPL(virDomainDisk, VIR_DOMAIN_DISK_TYPE_LAST,
93
VIR_ENUM_IMPL(virDomainDiskDevice, VIR_DOMAIN_DISK_DEVICE_LAST,
98
VIR_ENUM_IMPL(virDomainDiskBus, VIR_DOMAIN_DISK_BUS_LAST,
107
VIR_ENUM_IMPL(virDomainDiskCache, VIR_DOMAIN_DISK_CACHE_LAST,
113
VIR_ENUM_IMPL(virDomainFS, VIR_DOMAIN_FS_TYPE_LAST,
119
VIR_ENUM_IMPL(virDomainNet, VIR_DOMAIN_NET_TYPE_LAST,
129
VIR_ENUM_IMPL(virDomainChr, VIR_DOMAIN_CHR_TYPE_LAST,
141
VIR_ENUM_IMPL(virDomainSoundModel, VIR_DOMAIN_SOUND_MODEL_LAST,
147
VIR_ENUM_IMPL(virDomainVideo, VIR_DOMAIN_VIDEO_TYPE_LAST,
154
VIR_ENUM_IMPL(virDomainInput, VIR_DOMAIN_INPUT_TYPE_LAST,
158
VIR_ENUM_IMPL(virDomainInputBus, VIR_DOMAIN_INPUT_BUS_LAST,
163
VIR_ENUM_IMPL(virDomainGraphics, VIR_DOMAIN_GRAPHICS_TYPE_LAST,
169
VIR_ENUM_IMPL(virDomainHostdevMode, VIR_DOMAIN_HOSTDEV_MODE_LAST,
173
VIR_ENUM_IMPL(virDomainHostdevSubsys, VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST,
177
VIR_ENUM_IMPL(virDomainState, VIR_DOMAIN_CRASHED+1,
186
VIR_ENUM_IMPL(virDomainSeclabel, VIR_DOMAIN_SECLABEL_LAST,
190
#define virDomainReportError(conn, code, fmt...) \
191
virReportErrorHelper(conn, VIR_FROM_DOMAIN, code, __FILE__, \
192
__FUNCTION__, __LINE__, fmt)
196
virDomainObjPtr virDomainFindByID(const virDomainObjListPtr doms,
201
for (i = 0 ; i < doms->count ; i++) {
202
virDomainObjLock(doms->objs[i]);
203
if (virDomainIsActive(doms->objs[i]) &&
204
doms->objs[i]->def->id == id)
205
return doms->objs[i];
206
virDomainObjUnlock(doms->objs[i]);
213
virDomainObjPtr virDomainFindByUUID(const virDomainObjListPtr doms,
214
const unsigned char *uuid)
218
for (i = 0 ; i < doms->count ; i++) {
219
virDomainObjLock(doms->objs[i]);
220
if (!memcmp(doms->objs[i]->def->uuid, uuid, VIR_UUID_BUFLEN))
221
return doms->objs[i];
222
virDomainObjUnlock(doms->objs[i]);
228
virDomainObjPtr virDomainFindByName(const virDomainObjListPtr doms,
233
for (i = 0 ; i < doms->count ; i++) {
234
virDomainObjLock(doms->objs[i]);
235
if (STREQ(doms->objs[i]->def->name, name))
236
return doms->objs[i];
237
virDomainObjUnlock(doms->objs[i]);
245
void virDomainGraphicsDefFree(virDomainGraphicsDefPtr def)
251
case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
252
VIR_FREE(def->data.vnc.listenAddr);
253
VIR_FREE(def->data.vnc.keymap);
254
VIR_FREE(def->data.vnc.passwd);
257
case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
258
VIR_FREE(def->data.sdl.display);
259
VIR_FREE(def->data.sdl.xauth);
262
case VIR_DOMAIN_GRAPHICS_TYPE_RDP:
263
VIR_FREE(def->data.rdp.listenAddr);
266
case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
267
VIR_FREE(def->data.desktop.display);
274
void virDomainInputDefFree(virDomainInputDefPtr def)
282
void virDomainDiskDefFree(virDomainDiskDefPtr def)
287
VIR_FREE(def->serial);
290
VIR_FREE(def->driverName);
291
VIR_FREE(def->driverType);
292
virStorageEncryptionFree(def->encryption);
297
void virDomainFSDefFree(virDomainFSDefPtr def)
308
void virDomainNetDefFree(virDomainNetDefPtr def)
313
VIR_FREE(def->model);
316
case VIR_DOMAIN_NET_TYPE_ETHERNET:
317
VIR_FREE(def->data.ethernet.dev);
318
VIR_FREE(def->data.ethernet.script);
319
VIR_FREE(def->data.ethernet.ipaddr);
322
case VIR_DOMAIN_NET_TYPE_SERVER:
323
case VIR_DOMAIN_NET_TYPE_CLIENT:
324
case VIR_DOMAIN_NET_TYPE_MCAST:
325
VIR_FREE(def->data.socket.address);
328
case VIR_DOMAIN_NET_TYPE_NETWORK:
329
VIR_FREE(def->data.network.name);
332
case VIR_DOMAIN_NET_TYPE_BRIDGE:
333
VIR_FREE(def->data.bridge.brname);
334
VIR_FREE(def->data.bridge.script);
335
VIR_FREE(def->data.bridge.ipaddr);
338
case VIR_DOMAIN_NET_TYPE_INTERNAL:
339
VIR_FREE(def->data.internal.name);
343
VIR_FREE(def->ifname);
344
VIR_FREE(def->nic_name);
345
VIR_FREE(def->hostnet_name);
349
void virDomainChrDefFree(virDomainChrDefPtr def)
355
case VIR_DOMAIN_CHR_TYPE_PTY:
356
case VIR_DOMAIN_CHR_TYPE_DEV:
357
case VIR_DOMAIN_CHR_TYPE_FILE:
358
case VIR_DOMAIN_CHR_TYPE_PIPE:
359
VIR_FREE(def->data.file.path);
362
case VIR_DOMAIN_CHR_TYPE_UDP:
363
VIR_FREE(def->data.udp.bindHost);
364
VIR_FREE(def->data.udp.bindService);
365
VIR_FREE(def->data.udp.connectHost);
366
VIR_FREE(def->data.udp.connectService);
369
case VIR_DOMAIN_CHR_TYPE_TCP:
370
VIR_FREE(def->data.tcp.host);
371
VIR_FREE(def->data.tcp.service);
374
case VIR_DOMAIN_CHR_TYPE_UNIX:
375
VIR_FREE(def->data.nix.path);
382
void virDomainSoundDefFree(virDomainSoundDefPtr def)
390
void virDomainVideoDefFree(virDomainVideoDefPtr def)
395
VIR_FREE(def->accel);
399
void virDomainHostdevDefFree(virDomainHostdevDefPtr def)
404
VIR_FREE(def->target);
408
void virDomainDeviceDefFree(virDomainDeviceDefPtr def)
414
case VIR_DOMAIN_DEVICE_DISK:
415
virDomainDiskDefFree(def->data.disk);
417
case VIR_DOMAIN_DEVICE_NET:
418
virDomainNetDefFree(def->data.net);
420
case VIR_DOMAIN_DEVICE_INPUT:
421
virDomainInputDefFree(def->data.input);
423
case VIR_DOMAIN_DEVICE_SOUND:
424
virDomainSoundDefFree(def->data.sound);
426
case VIR_DOMAIN_DEVICE_VIDEO:
427
virDomainVideoDefFree(def->data.video);
429
case VIR_DOMAIN_DEVICE_HOSTDEV:
430
virDomainHostdevDefFree(def->data.hostdev);
437
void virSecurityLabelDefFree(virDomainDefPtr def);
439
void virSecurityLabelDefFree(virDomainDefPtr def)
441
VIR_FREE(def->seclabel.model);
442
VIR_FREE(def->seclabel.label);
443
VIR_FREE(def->seclabel.imagelabel);
446
void virDomainDefFree(virDomainDefPtr def)
453
for (i = 0 ; i < def->ngraphics ; i++)
454
virDomainGraphicsDefFree(def->graphics[i]);
455
VIR_FREE(def->graphics);
457
for (i = 0 ; i < def->ninputs ; i++)
458
virDomainInputDefFree(def->inputs[i]);
459
VIR_FREE(def->inputs);
461
for (i = 0 ; i < def->ndisks ; i++)
462
virDomainDiskDefFree(def->disks[i]);
463
VIR_FREE(def->disks);
465
for (i = 0 ; i < def->nfss ; i++)
466
virDomainFSDefFree(def->fss[i]);
469
for (i = 0 ; i < def->nnets ; i++)
470
virDomainNetDefFree(def->nets[i]);
472
for (i = 0 ; i < def->nserials ; i++)
473
virDomainChrDefFree(def->serials[i]);
474
VIR_FREE(def->serials);
476
for (i = 0 ; i < def->nparallels ; i++)
477
virDomainChrDefFree(def->parallels[i]);
478
VIR_FREE(def->parallels);
480
virDomainChrDefFree(def->console);
482
for (i = 0 ; i < def->nsounds ; i++)
483
virDomainSoundDefFree(def->sounds[i]);
484
VIR_FREE(def->sounds);
486
for (i = 0 ; i < def->nvideos ; i++)
487
virDomainVideoDefFree(def->videos[i]);
488
VIR_FREE(def->videos);
490
for (i = 0 ; i < def->nhostdevs ; i++)
491
virDomainHostdevDefFree(def->hostdevs[i]);
492
VIR_FREE(def->hostdevs);
494
VIR_FREE(def->os.type);
495
VIR_FREE(def->os.arch);
496
VIR_FREE(def->os.machine);
497
VIR_FREE(def->os.init);
498
VIR_FREE(def->os.kernel);
499
VIR_FREE(def->os.initrd);
500
VIR_FREE(def->os.cmdline);
501
VIR_FREE(def->os.root);
502
VIR_FREE(def->os.loader);
503
VIR_FREE(def->os.bootloader);
504
VIR_FREE(def->os.bootloaderArgs);
507
VIR_FREE(def->cpumask);
508
VIR_FREE(def->emulator);
509
VIR_FREE(def->description);
511
virSecurityLabelDefFree(def);
518
void virDomainObjFree(virDomainObjPtr dom)
523
virDomainDefFree(dom->def);
524
virDomainDefFree(dom->newDef);
526
virDomainChrDefFree(dom->monitor_chr);
528
VIR_FREE(dom->vcpupids);
530
virMutexDestroy(&dom->lock);
535
void virDomainObjListFree(virDomainObjListPtr vms)
542
for (i = 0 ; i < vms->count ; i++)
543
virDomainObjFree(vms->objs[i]);
550
static virDomainObjPtr virDomainObjNew(virConnectPtr conn)
552
virDomainObjPtr domain;
554
if (VIR_ALLOC(domain) < 0) {
555
virReportOOMError(conn);
559
if (virMutexInit(&domain->lock) < 0) {
560
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
561
"%s", _("cannot initialize mutex"));
566
virDomainObjLock(domain);
567
domain->state = VIR_DOMAIN_SHUTOFF;
568
domain->monitorWatch = -1;
569
domain->monitor = -1;
574
virDomainObjPtr virDomainAssignDef(virConnectPtr conn,
575
virDomainObjListPtr doms,
576
const virDomainDefPtr def)
578
virDomainObjPtr domain;
580
if ((domain = virDomainFindByUUID(doms, def->uuid))) {
581
if (!virDomainIsActive(domain)) {
582
virDomainDefFree(domain->def);
586
virDomainDefFree(domain->newDef);
587
domain->newDef = def;
593
if (VIR_REALLOC_N(doms->objs, doms->count + 1) < 0) {
594
virReportOOMError(conn);
598
if (!(domain = virDomainObjNew(conn)))
603
doms->objs[doms->count] = domain;
609
void virDomainRemoveInactive(virDomainObjListPtr doms,
614
virDomainObjUnlock(dom);
616
for (i = 0 ; i < doms->count ; i++) {
617
virDomainObjLock(doms->objs[i]);
618
if (doms->objs[i] == dom) {
619
virDomainObjUnlock(doms->objs[i]);
620
virDomainObjFree(doms->objs[i]);
622
if (i < (doms->count - 1))
623
memmove(doms->objs + i, doms->objs + i + 1,
624
sizeof(*(doms->objs)) * (doms->count - (i + 1)));
626
if (VIR_REALLOC_N(doms->objs, doms->count - 1) < 0) {
627
; /* Failure to reduce memory allocation isn't fatal */
633
virDomainObjUnlock(doms->objs[i]);
639
/* Parse the XML definition for a disk
640
* @param node XML nodeset to parse for disk definition
642
static virDomainDiskDefPtr
643
virDomainDiskDefParseXML(virConnectPtr conn,
646
virDomainDiskDefPtr def;
650
char *driverName = NULL;
651
char *driverType = NULL;
655
char *cachetag = NULL;
656
char *devaddr = NULL;
657
virStorageEncryptionPtr encryption = NULL;
660
if (VIR_ALLOC(def) < 0) {
661
virReportOOMError(conn);
665
type = virXMLPropString(node, "type");
667
if ((def->type = virDomainDiskTypeFromString(type)) < 0) {
668
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
669
_("unknown disk type '%s'"), type);
673
def->type = VIR_DOMAIN_DISK_TYPE_FILE;
676
cur = node->children;
677
while (cur != NULL) {
678
if (cur->type == XML_ELEMENT_NODE) {
679
if ((source == NULL) &&
680
(xmlStrEqual(cur->name, BAD_CAST "source"))) {
682
if (def->type == VIR_DOMAIN_DISK_TYPE_FILE)
683
source = virXMLPropString(cur, "file");
685
source = virXMLPropString(cur, "dev");
687
/* People sometimes pass a bogus '' source path
688
when they mean to omit the source element
689
completely. eg CDROM without media. This is
690
just a little compatability check to help
692
if (source && STREQ(source, ""))
694
} else if ((target == NULL) &&
695
(xmlStrEqual(cur->name, BAD_CAST "target"))) {
696
target = virXMLPropString(cur, "dev");
697
bus = virXMLPropString(cur, "bus");
699
/* HACK: Work around for compat with Xen
700
* driver in previous libvirt releases */
702
STRPREFIX(target, "ioemu:"))
703
memmove(target, target+6, strlen(target)-5);
704
} else if ((driverName == NULL) &&
705
(xmlStrEqual(cur->name, BAD_CAST "driver"))) {
706
driverName = virXMLPropString(cur, "name");
707
driverType = virXMLPropString(cur, "type");
708
cachetag = virXMLPropString(cur, "cache");
709
} else if (xmlStrEqual(cur->name, BAD_CAST "readonly")) {
711
} else if (xmlStrEqual(cur->name, BAD_CAST "shareable")) {
713
} else if ((flags & VIR_DOMAIN_XML_INTERNAL_STATUS) &&
714
xmlStrEqual(cur->name, BAD_CAST "state")) {
715
devaddr = virXMLPropString(cur, "devaddr");
716
} else if (encryption == NULL &&
717
xmlStrEqual(cur->name, BAD_CAST "encryption")) {
718
encryption = virStorageEncryptionParseNode(conn, node->doc,
720
if (encryption == NULL)
722
} else if ((serial == NULL) &&
723
(xmlStrEqual(cur->name, BAD_CAST "serial"))) {
724
serial = (char *)xmlNodeGetContent(cur);
730
device = virXMLPropString(node, "device");
732
if ((def->device = virDomainDiskDeviceTypeFromString(device)) < 0) {
733
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
734
_("unknown disk device '%s'"), device);
738
def->device = VIR_DOMAIN_DISK_DEVICE_DISK;
741
/* Only CDROM and Floppy devices are allowed missing source path
742
* to indicate no media present */
743
if (source == NULL &&
744
def->device != VIR_DOMAIN_DISK_DEVICE_CDROM &&
745
def->device != VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
746
virDomainReportError(conn, VIR_ERR_NO_SOURCE,
747
target ? "%s" : NULL, target);
751
if (target == NULL) {
752
virDomainReportError(conn, VIR_ERR_NO_TARGET,
753
source ? "%s" : NULL, source);
757
if (def->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY &&
758
!STRPREFIX(target, "fd")) {
759
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
760
_("Invalid floppy device name: %s"), target);
764
/* Force CDROM to be listed as read only */
765
if (def->device == VIR_DOMAIN_DISK_DEVICE_CDROM)
768
if (def->device == VIR_DOMAIN_DISK_DEVICE_DISK &&
769
!STRPREFIX((const char *)target, "hd") &&
770
!STRPREFIX((const char *)target, "sd") &&
771
!STRPREFIX((const char *)target, "vd") &&
772
!STRPREFIX((const char *)target, "xvd") &&
773
!STRPREFIX((const char *)target, "ubd")) {
774
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
775
_("Invalid harddisk device name: %s"), target);
780
if ((def->bus = virDomainDiskBusTypeFromString(bus)) < 0) {
781
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
782
_("unknown disk bus type '%s'"), bus);
786
if (def->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
787
def->bus = VIR_DOMAIN_DISK_BUS_FDC;
789
if (STRPREFIX(target, "hd"))
790
def->bus = VIR_DOMAIN_DISK_BUS_IDE;
791
else if (STRPREFIX(target, "sd"))
792
def->bus = VIR_DOMAIN_DISK_BUS_SCSI;
793
else if (STRPREFIX(target, "vd"))
794
def->bus = VIR_DOMAIN_DISK_BUS_VIRTIO;
795
else if (STRPREFIX(target, "xvd"))
796
def->bus = VIR_DOMAIN_DISK_BUS_XEN;
797
else if (STRPREFIX(target, "ubd"))
798
def->bus = VIR_DOMAIN_DISK_BUS_UML;
800
def->bus = VIR_DOMAIN_DISK_BUS_IDE;
804
if (def->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY &&
805
def->bus != VIR_DOMAIN_DISK_BUS_FDC) {
806
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
807
_("Invalid bus type '%s' for floppy disk"), bus);
810
if (def->device != VIR_DOMAIN_DISK_DEVICE_FLOPPY &&
811
def->bus == VIR_DOMAIN_DISK_BUS_FDC) {
812
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
813
_("Invalid bus type '%s' for disk"), bus);
818
(def->cachemode = virDomainDiskCacheTypeFromString(cachetag)) < 0) {
819
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
820
_("unknown disk cache mode '%s'"), cachetag);
825
sscanf(devaddr, "%x:%x:%x",
826
&def->pci_addr.domain,
828
&def->pci_addr.slot) < 3) {
829
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
830
_("Unable to parse devaddr parameter '%s'"),
839
def->driverName = driverName;
841
def->driverType = driverType;
843
def->encryption = encryption;
845
def->serial = serial;
854
VIR_FREE(driverType);
855
VIR_FREE(driverName);
859
virStorageEncryptionFree(encryption);
864
virDomainDiskDefFree(def);
870
/* Parse the XML definition for a disk
871
* @param node XML nodeset to parse for disk definition
873
static virDomainFSDefPtr
874
virDomainFSDefParseXML(virConnectPtr conn,
876
int flags ATTRIBUTE_UNUSED) {
877
virDomainFSDefPtr def;
883
if (VIR_ALLOC(def) < 0) {
884
virReportOOMError(conn);
888
type = virXMLPropString(node, "type");
890
if ((def->type = virDomainFSTypeFromString(type)) < 0) {
891
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
892
_("unknown filesystem type '%s'"), type);
896
def->type = VIR_DOMAIN_FS_TYPE_MOUNT;
899
cur = node->children;
900
while (cur != NULL) {
901
if (cur->type == XML_ELEMENT_NODE) {
902
if ((source == NULL) &&
903
(xmlStrEqual(cur->name, BAD_CAST "source"))) {
905
if (def->type == VIR_DOMAIN_FS_TYPE_MOUNT)
906
source = virXMLPropString(cur, "dir");
907
else if (def->type == VIR_DOMAIN_FS_TYPE_FILE)
908
source = virXMLPropString(cur, "file");
909
else if (def->type == VIR_DOMAIN_FS_TYPE_BLOCK)
910
source = virXMLPropString(cur, "dev");
911
else if (def->type == VIR_DOMAIN_FS_TYPE_TEMPLATE)
912
source = virXMLPropString(cur, "name");
913
} else if ((target == NULL) &&
914
(xmlStrEqual(cur->name, BAD_CAST "target"))) {
915
target = virXMLPropString(cur, "dir");
916
} else if (xmlStrEqual(cur->name, BAD_CAST "readonly")) {
923
if (source == NULL) {
924
virDomainReportError(conn, VIR_ERR_NO_SOURCE,
925
target ? "%s" : NULL, target);
929
if (target == NULL) {
930
virDomainReportError(conn, VIR_ERR_NO_TARGET,
931
source ? "%s" : NULL, source);
948
virDomainFSDefFree(def);
955
/* Parse the XML definition for a network interface
956
* @param node XML nodeset to parse for net definition
957
* @return 0 on success, -1 on failure
959
static virDomainNetDefPtr
960
virDomainNetDefParseXML(virConnectPtr conn,
963
int flags ATTRIBUTE_UNUSED) {
964
virDomainNetDefPtr def;
966
char *macaddr = NULL;
968
char *network = NULL;
973
char *address = NULL;
976
char *internal = NULL;
977
char *nic_name = NULL;
978
char *hostnet_name = NULL;
979
char *devaddr = NULL;
982
if (VIR_ALLOC(def) < 0) {
983
virReportOOMError(conn);
987
type = virXMLPropString(node, "type");
989
if ((def->type = virDomainNetTypeFromString(type)) < 0) {
990
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
991
_("unknown interface type '%s'"), type);
995
def->type = VIR_DOMAIN_NET_TYPE_USER;
998
cur = node->children;
999
while (cur != NULL) {
1000
if (cur->type == XML_ELEMENT_NODE) {
1001
if ((macaddr == NULL) &&
1002
(xmlStrEqual(cur->name, BAD_CAST "mac"))) {
1003
macaddr = virXMLPropString(cur, "address");
1004
} else if ((network == NULL) &&
1005
(def->type == VIR_DOMAIN_NET_TYPE_NETWORK) &&
1006
(xmlStrEqual(cur->name, BAD_CAST "source"))) {
1007
network = virXMLPropString(cur, "network");
1008
} else if ((internal == NULL) &&
1009
(def->type == VIR_DOMAIN_NET_TYPE_INTERNAL) &&
1010
(xmlStrEqual(cur->name, BAD_CAST "source"))) {
1011
internal = virXMLPropString(cur, "name");
1012
} else if ((network == NULL) &&
1013
(def->type == VIR_DOMAIN_NET_TYPE_BRIDGE) &&
1014
(xmlStrEqual(cur->name, BAD_CAST "source"))) {
1015
bridge = virXMLPropString(cur, "bridge");
1016
} else if ((dev == NULL) &&
1017
(def->type == VIR_DOMAIN_NET_TYPE_ETHERNET) &&
1018
xmlStrEqual(cur->name, BAD_CAST "source")) {
1019
dev = virXMLPropString(cur, "dev");
1020
} else if ((network == NULL) &&
1021
((def->type == VIR_DOMAIN_NET_TYPE_SERVER) ||
1022
(def->type == VIR_DOMAIN_NET_TYPE_CLIENT) ||
1023
(def->type == VIR_DOMAIN_NET_TYPE_MCAST)) &&
1024
(xmlStrEqual(cur->name, BAD_CAST "source"))) {
1025
address = virXMLPropString(cur, "address");
1026
port = virXMLPropString(cur, "port");
1027
} else if ((address == NULL) &&
1028
(def->type == VIR_DOMAIN_NET_TYPE_ETHERNET ||
1029
def->type == VIR_DOMAIN_NET_TYPE_BRIDGE) &&
1030
(xmlStrEqual(cur->name, BAD_CAST "ip"))) {
1031
address = virXMLPropString(cur, "address");
1032
} else if ((ifname == NULL) &&
1033
xmlStrEqual(cur->name, BAD_CAST "target")) {
1034
ifname = virXMLPropString(cur, "dev");
1035
if ((ifname != NULL) &&
1036
(STRPREFIX((const char*)ifname, "vnet"))) {
1037
/* An auto-generated target name, blank it out */
1040
} else if ((script == NULL) &&
1041
(def->type == VIR_DOMAIN_NET_TYPE_ETHERNET ||
1042
def->type == VIR_DOMAIN_NET_TYPE_BRIDGE) &&
1043
xmlStrEqual(cur->name, BAD_CAST "script")) {
1044
script = virXMLPropString(cur, "path");
1045
} else if (xmlStrEqual (cur->name, BAD_CAST "model")) {
1046
model = virXMLPropString(cur, "type");
1047
} else if ((flags & VIR_DOMAIN_XML_INTERNAL_STATUS) &&
1048
xmlStrEqual(cur->name, BAD_CAST "state")) {
1049
nic_name = virXMLPropString(cur, "nic");
1050
hostnet_name = virXMLPropString(cur, "hostnet");
1051
devaddr = virXMLPropString(cur, "devaddr");
1052
vlan = virXMLPropString(cur, "vlan");
1059
virParseMacAddr((const char *)macaddr, def->mac);
1061
virCapabilitiesGenerateMac(caps, def->mac);
1065
sscanf(devaddr, "%x:%x:%x",
1066
&def->pci_addr.domain,
1068
&def->pci_addr.slot) < 3) {
1069
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1070
_("Unable to parse devaddr parameter '%s'"),
1075
def->nic_name = nic_name;
1076
def->hostnet_name = hostnet_name;
1077
nic_name = hostnet_name = NULL;
1080
if (vlan && virStrToLong_i(vlan, NULL, 10, &def->vlan) < 0) {
1081
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
1082
_("Cannot parse <state> 'vlan' attribute"));
1086
switch (def->type) {
1087
case VIR_DOMAIN_NET_TYPE_NETWORK:
1088
if (network == NULL) {
1089
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
1090
_("No <source> 'network' attribute specified with <interface type='network'/>"));
1093
def->data.network.name = network;
1097
case VIR_DOMAIN_NET_TYPE_ETHERNET:
1099
if (script != NULL) {
1100
def->data.ethernet.script = script;
1104
def->data.ethernet.dev = dev;
1107
if (address != NULL) {
1108
def->data.ethernet.ipaddr = address;
1113
case VIR_DOMAIN_NET_TYPE_BRIDGE:
1114
if (bridge == NULL) {
1115
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
1116
_("No <source> 'bridge' attribute specified with <interface type='bridge'/>"));
1119
def->data.bridge.brname = bridge;
1121
if (script != NULL) {
1122
def->data.bridge.script = script;
1125
if (address != NULL) {
1126
def->data.bridge.ipaddr = address;
1131
case VIR_DOMAIN_NET_TYPE_CLIENT:
1132
case VIR_DOMAIN_NET_TYPE_SERVER:
1133
case VIR_DOMAIN_NET_TYPE_MCAST:
1135
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
1136
_("No <source> 'port' attribute specified with socket interface"));
1139
if (virStrToLong_i(port, NULL, 10, &def->data.socket.port) < 0) {
1140
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
1141
_("Cannot parse <source> 'port' attribute with socket interface"));
1145
if (address == NULL) {
1146
if (def->type == VIR_DOMAIN_NET_TYPE_CLIENT ||
1147
def->type == VIR_DOMAIN_NET_TYPE_MCAST) {
1148
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
1149
_("No <source> 'address' attribute specified with socket interface"));
1153
def->data.socket.address = address;
1158
case VIR_DOMAIN_NET_TYPE_INTERNAL:
1159
if (internal == NULL) {
1160
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
1161
_("No <source> 'name' attribute specified with <interface type='internal'/>"));
1164
def->data.internal.name = internal;
1169
if (ifname != NULL) {
1170
def->ifname = ifname;
1174
/* NIC model (see -net nic,model=?). We only check that it looks
1175
* reasonable, not that it is a supported NIC type. FWIW kvm
1176
* supports these types as of April 2008:
1177
* i82551 i82557b i82559er ne2k_pci pcnet rtl8139 e1000 virtio
1179
if (model != NULL) {
1181
for (i = 0 ; i < strlen(model) ; i++) {
1182
int char_ok = c_isalnum(model[i]) || model[i] == '_';
1184
virDomainReportError (conn, VIR_ERR_INVALID_ARG, "%s",
1185
_("Model name contains invalid characters"));
1206
VIR_FREE(hostnet_name);
1213
virDomainNetDefFree(def);
1219
/* Parse the XML definition for a character device
1220
* @param node XML nodeset to parse for net definition
1222
* The XML we're dealing with looks like
1224
* <serial type="pty">
1225
* <source path="/dev/pts/3"/>
1226
* <target port="1"/>
1229
* <serial type="dev">
1230
* <source path="/dev/ttyS0"/>
1231
* <target port="1"/>
1234
* <serial type="tcp">
1235
* <source mode="connect" host="0.0.0.0" service="2445"/>
1236
* <target port="1"/>
1239
* <serial type="tcp">
1240
* <source mode="bind" host="0.0.0.0" service="2445"/>
1241
* <target port="1"/>
1242
* <protocol type='raw'/>
1245
* <serial type="udp">
1246
* <source mode="bind" host="0.0.0.0" service="2445"/>
1247
* <source mode="connect" host="0.0.0.0" service="2445"/>
1248
* <target port="1"/>
1251
* <serial type="unix">
1252
* <source mode="bind" path="/tmp/foo"/>
1253
* <target port="1"/>
1257
static virDomainChrDefPtr
1258
virDomainChrDefParseXML(virConnectPtr conn,
1260
int flags ATTRIBUTE_UNUSED) {
1263
char *bindHost = NULL;
1264
char *bindService = NULL;
1265
char *connectHost = NULL;
1266
char *connectService = NULL;
1269
char *protocol = NULL;
1270
virDomainChrDefPtr def;
1272
if (VIR_ALLOC(def) < 0) {
1273
virReportOOMError(conn);
1277
type = virXMLPropString(node, "type");
1279
def->type = VIR_DOMAIN_CHR_TYPE_PTY;
1280
else if ((def->type = virDomainChrTypeFromString(type)) < 0)
1281
def->type = VIR_DOMAIN_CHR_TYPE_NULL;
1283
cur = node->children;
1284
while (cur != NULL) {
1285
if (cur->type == XML_ELEMENT_NODE) {
1286
if (xmlStrEqual(cur->name, BAD_CAST "source")) {
1288
mode = virXMLPropString(cur, "mode");
1290
switch (def->type) {
1291
case VIR_DOMAIN_CHR_TYPE_PTY:
1292
case VIR_DOMAIN_CHR_TYPE_DEV:
1293
case VIR_DOMAIN_CHR_TYPE_FILE:
1294
case VIR_DOMAIN_CHR_TYPE_PIPE:
1295
case VIR_DOMAIN_CHR_TYPE_UNIX:
1297
path = virXMLPropString(cur, "path");
1301
case VIR_DOMAIN_CHR_TYPE_UDP:
1302
case VIR_DOMAIN_CHR_TYPE_TCP:
1304
STREQ((const char *)mode, "connect")) {
1306
if (connectHost == NULL)
1307
connectHost = virXMLPropString(cur, "host");
1308
if (connectService == NULL)
1309
connectService = virXMLPropString(cur, "service");
1310
} else if (STREQ((const char *)mode, "bind")) {
1311
if (bindHost == NULL)
1312
bindHost = virXMLPropString(cur, "host");
1313
if (bindService == NULL)
1314
bindService = virXMLPropString(cur, "service");
1316
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1317
_("Unknown source mode '%s'"),
1322
if (def->type == VIR_DOMAIN_CHR_TYPE_UDP)
1325
} else if (xmlStrEqual(cur->name, BAD_CAST "protocol")) {
1326
if (protocol == NULL)
1327
protocol = virXMLPropString(cur, "type");
1334
switch (def->type) {
1335
case VIR_DOMAIN_CHR_TYPE_NULL:
1339
case VIR_DOMAIN_CHR_TYPE_VC:
1342
case VIR_DOMAIN_CHR_TYPE_PTY:
1343
case VIR_DOMAIN_CHR_TYPE_DEV:
1344
case VIR_DOMAIN_CHR_TYPE_FILE:
1345
case VIR_DOMAIN_CHR_TYPE_PIPE:
1347
def->type != VIR_DOMAIN_CHR_TYPE_PTY) {
1348
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
1349
_("Missing source path attribute for char device"));
1353
def->data.file.path = path;
1357
case VIR_DOMAIN_CHR_TYPE_STDIO:
1361
case VIR_DOMAIN_CHR_TYPE_TCP:
1363
STREQ(mode, "connect")) {
1364
if (connectHost == NULL) {
1365
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
1366
_("Missing source host attribute for char device"));
1369
if (connectService == NULL) {
1370
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
1371
_("Missing source service attribute for char device"));
1375
def->data.tcp.host = connectHost;
1377
def->data.tcp.service = connectService;
1378
connectService = NULL;
1379
def->data.tcp.listen = 0;
1381
if (bindHost == NULL) {
1382
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
1383
_("Missing source host attribute for char device"));
1386
if (bindService == NULL) {
1387
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
1388
_("Missing source service attribute for char device"));
1392
def->data.tcp.host = bindHost;
1394
def->data.tcp.service = bindService;
1396
def->data.tcp.listen = 1;
1399
if (protocol == NULL ||
1400
STREQ(protocol, "raw"))
1401
def->data.tcp.protocol = VIR_DOMAIN_CHR_TCP_PROTOCOL_RAW;
1402
else if (STREQ(protocol, "telnet"))
1403
def->data.tcp.protocol = VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET;
1405
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1406
_("Unknown protocol '%s'"), protocol);
1412
case VIR_DOMAIN_CHR_TYPE_UDP:
1413
if (connectService == NULL) {
1414
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
1415
_("Missing source service attribute for char device"));
1419
def->data.udp.connectHost = connectHost;
1421
def->data.udp.connectService = connectService;
1422
connectService = NULL;
1424
def->data.udp.bindHost = bindHost;
1426
def->data.udp.bindService = bindService;
1430
case VIR_DOMAIN_CHR_TYPE_UNIX:
1432
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
1433
_("Missing source path attribute for char device"));
1438
STRNEQ(mode, "connect"))
1439
def->data.nix.listen = 1;
1441
def->data.nix.listen = 0;
1443
def->data.nix.path = path;
1453
VIR_FREE(bindService);
1454
VIR_FREE(connectHost);
1455
VIR_FREE(connectService);
1461
virDomainChrDefFree(def);
1466
/* Parse the XML definition for a network interface */
1467
static virDomainInputDefPtr
1468
virDomainInputDefParseXML(virConnectPtr conn,
1471
int flags ATTRIBUTE_UNUSED) {
1472
virDomainInputDefPtr def;
1476
if (VIR_ALLOC(def) < 0) {
1477
virReportOOMError(conn);
1481
type = virXMLPropString(node, "type");
1482
bus = virXMLPropString(node, "bus");
1485
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1486
"%s", _("missing input device type"));
1490
if ((def->type = virDomainInputTypeFromString(type)) < 0) {
1491
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1492
_("unknown input device type '%s'"), type);
1497
if ((def->bus = virDomainInputBusTypeFromString(bus)) < 0) {
1498
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1499
_("unknown input bus type '%s'"), bus);
1503
if (STREQ(ostype, "hvm")) {
1504
if (def->bus == VIR_DOMAIN_INPUT_BUS_PS2 && /* Only allow mouse for ps2 */
1505
def->type != VIR_DOMAIN_INPUT_TYPE_MOUSE) {
1506
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1507
_("ps2 bus does not support %s input device"),
1511
if (def->bus == VIR_DOMAIN_INPUT_BUS_XEN) {
1512
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1513
_("unsupported input bus %s"),
1518
if (def->bus != VIR_DOMAIN_INPUT_BUS_XEN) {
1519
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1520
_("unsupported input bus %s"),
1523
if (def->type != VIR_DOMAIN_INPUT_TYPE_MOUSE) {
1524
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1525
_("xen bus does not support %s input device"),
1531
if (STREQ(ostype, "hvm")) {
1532
if (def->type == VIR_DOMAIN_INPUT_TYPE_MOUSE)
1533
def->bus = VIR_DOMAIN_INPUT_BUS_PS2;
1535
def->bus = VIR_DOMAIN_INPUT_BUS_USB;
1537
def->bus = VIR_DOMAIN_INPUT_BUS_XEN;
1548
virDomainInputDefFree(def);
1554
/* Parse the XML definition for a graphics device */
1555
static virDomainGraphicsDefPtr
1556
virDomainGraphicsDefParseXML(virConnectPtr conn,
1557
xmlNodePtr node, int flags) {
1558
virDomainGraphicsDefPtr def;
1561
if (VIR_ALLOC(def) < 0) {
1562
virReportOOMError(conn);
1566
type = virXMLPropString(node, "type");
1569
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1570
"%s", _("missing graphics device type"));
1574
if ((def->type = virDomainGraphicsTypeFromString(type)) < 0) {
1575
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1576
_("unknown graphics device type '%s'"), type);
1580
if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
1581
char *port = virXMLPropString(node, "port");
1585
if (virStrToLong_i(port, NULL, 10, &def->data.vnc.port) < 0) {
1586
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1587
_("cannot parse vnc port %s"), port);
1592
/* Legacy compat syntax, used -1 for auto-port */
1593
if (def->data.vnc.port == -1) {
1594
if (flags & VIR_DOMAIN_XML_INACTIVE)
1595
def->data.vnc.port = 0;
1596
def->data.vnc.autoport = 1;
1599
def->data.vnc.port = 0;
1600
def->data.vnc.autoport = 1;
1603
if ((autoport = virXMLPropString(node, "autoport")) != NULL) {
1604
if (STREQ(autoport, "yes")) {
1605
if (flags & VIR_DOMAIN_XML_INACTIVE)
1606
def->data.vnc.port = 0;
1607
def->data.vnc.autoport = 1;
1612
def->data.vnc.listenAddr = virXMLPropString(node, "listen");
1613
def->data.vnc.passwd = virXMLPropString(node, "passwd");
1614
def->data.vnc.keymap = virXMLPropString(node, "keymap");
1615
} else if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
1616
char *fullscreen = virXMLPropString(node, "fullscreen");
1618
if (fullscreen != NULL) {
1619
if (STREQ(fullscreen, "yes")) {
1620
def->data.sdl.fullscreen = 1;
1621
} else if (STREQ(fullscreen, "no")) {
1622
def->data.sdl.fullscreen = 0;
1624
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1625
_("unknown fullscreen value '%s'"), fullscreen);
1626
VIR_FREE(fullscreen);
1629
VIR_FREE(fullscreen);
1631
def->data.sdl.fullscreen = 0;
1632
def->data.sdl.xauth = virXMLPropString(node, "xauth");
1633
def->data.sdl.display = virXMLPropString(node, "display");
1634
} else if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_RDP) {
1635
char *port = virXMLPropString(node, "port");
1641
if (virStrToLong_i(port, NULL, 10, &def->data.rdp.port) < 0) {
1642
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1643
_("cannot parse rdp port %s"), port);
1649
def->data.rdp.port = 0;
1650
def->data.rdp.autoport = 1;
1653
if ((autoport = virXMLPropString(node, "autoport")) != NULL) {
1654
if (STREQ(autoport, "yes")) {
1655
if (flags & VIR_DOMAIN_XML_INACTIVE)
1656
def->data.rdp.port = 0;
1657
def->data.rdp.autoport = 1;
1662
if ((replaceUser = virXMLPropString(node, "replaceUser")) != NULL) {
1663
if (STREQ(replaceUser, "yes")) {
1664
def->data.rdp.replaceUser = 1;
1666
VIR_FREE(replaceUser);
1669
if ((multiUser = virXMLPropString(node, "multiUser")) != NULL) {
1670
if (STREQ(multiUser, "yes")) {
1671
def->data.rdp.multiUser = 1;
1673
VIR_FREE(multiUser);
1676
def->data.rdp.listenAddr = virXMLPropString(node, "listen");
1677
} else if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP) {
1678
char *fullscreen = virXMLPropString(node, "fullscreen");
1680
if (fullscreen != NULL) {
1681
if (STREQ(fullscreen, "yes")) {
1682
def->data.desktop.fullscreen = 1;
1683
} else if (STREQ(fullscreen, "no")) {
1684
def->data.desktop.fullscreen = 0;
1686
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1687
_("unknown fullscreen value '%s'"), fullscreen);
1688
VIR_FREE(fullscreen);
1691
VIR_FREE(fullscreen);
1693
def->data.desktop.fullscreen = 0;
1695
def->data.desktop.display = virXMLPropString(node, "display");
1704
virDomainGraphicsDefFree(def);
1710
static virDomainSoundDefPtr
1711
virDomainSoundDefParseXML(virConnectPtr conn,
1712
const xmlNodePtr node,
1713
int flags ATTRIBUTE_UNUSED) {
1716
virDomainSoundDefPtr def;
1718
if (VIR_ALLOC(def) < 0) {
1719
virReportOOMError(conn);
1723
model = virXMLPropString(node, "model");
1724
if ((def->model = virDomainSoundModelTypeFromString(model)) < 0) {
1725
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1726
_("unknown sound model '%s'"), model);
1736
virDomainSoundDefFree(def);
1743
virDomainVideoDefaultRAM(virDomainDefPtr def,
1747
/* Wierd, QEMU defaults to 9 MB ??! */
1748
case VIR_DOMAIN_VIDEO_TYPE_VGA:
1749
case VIR_DOMAIN_VIDEO_TYPE_CIRRUS:
1750
case VIR_DOMAIN_VIDEO_TYPE_VMVGA:
1751
if (def->virtType == VIR_DOMAIN_VIRT_VBOX)
1757
case VIR_DOMAIN_VIDEO_TYPE_XEN:
1758
/* Original Xen PVFB hardcoded to 4 MB */
1768
virDomainVideoDefaultType(virDomainDefPtr def)
1770
switch (def->virtType) {
1771
case VIR_DOMAIN_VIRT_TEST:
1772
case VIR_DOMAIN_VIRT_QEMU:
1773
case VIR_DOMAIN_VIRT_KQEMU:
1774
case VIR_DOMAIN_VIRT_KVM:
1775
case VIR_DOMAIN_VIRT_XEN:
1777
(STREQ(def->os.type, "xen") ||
1778
STREQ(def->os.type, "linux")))
1779
return VIR_DOMAIN_VIDEO_TYPE_XEN;
1781
return VIR_DOMAIN_VIDEO_TYPE_CIRRUS;
1783
case VIR_DOMAIN_VIRT_VBOX:
1784
return VIR_DOMAIN_VIDEO_TYPE_VBOX;
1791
static virDomainVideoAccelDefPtr
1792
virDomainVideoAccelDefParseXML(virConnectPtr conn, const xmlNodePtr node) {
1794
virDomainVideoAccelDefPtr def;
1795
char *support3d = NULL;
1796
char *support2d = NULL;
1798
cur = node->children;
1799
while (cur != NULL) {
1800
if (cur->type == XML_ELEMENT_NODE) {
1801
if ((support3d == NULL) && (support2d == NULL) &&
1802
xmlStrEqual(cur->name, BAD_CAST "acceleration")) {
1803
support3d = virXMLPropString(cur, "accel3d");
1804
support2d = virXMLPropString(cur, "accel2d");
1810
if ((support3d == NULL) && (support2d == NULL))
1813
if (VIR_ALLOC(def) < 0) {
1814
virReportOOMError(conn);
1819
if (STREQ(support3d, "yes"))
1823
VIR_FREE(support3d);
1827
if (STREQ(support2d, "yes"))
1831
VIR_FREE(support2d);
1837
static virDomainVideoDefPtr
1838
virDomainVideoDefParseXML(virConnectPtr conn,
1839
const xmlNodePtr node,
1840
virDomainDefPtr dom,
1841
int flags ATTRIBUTE_UNUSED) {
1842
virDomainVideoDefPtr def;
1848
if (VIR_ALLOC(def) < 0) {
1849
virReportOOMError(conn);
1853
cur = node->children;
1854
while (cur != NULL) {
1855
if (cur->type == XML_ELEMENT_NODE) {
1856
if ((type == NULL) && (vram == NULL) && (heads == NULL) &&
1857
xmlStrEqual(cur->name, BAD_CAST "model")) {
1858
type = virXMLPropString(cur, "type");
1859
vram = virXMLPropString(cur, "vram");
1860
heads = virXMLPropString(cur, "heads");
1861
def->accel = virDomainVideoAccelDefParseXML(conn, cur);
1868
if ((def->type = virDomainVideoTypeFromString(type)) < 0) {
1869
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1870
_("unknown video model '%s'"), type);
1874
if ((def->type = virDomainVideoDefaultType(dom)) < 0) {
1875
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
1876
_("missing video model and cannot determine default"));
1882
if (virStrToLong_ui(vram, NULL, 10, &def->vram) < 0) {
1883
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1884
_("cannot parse video ram '%s'"), vram);
1888
def->vram = virDomainVideoDefaultRAM(dom, def->type);
1892
if (virStrToLong_ui(heads, NULL, 10, &def->heads) < 0) {
1893
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1894
_("cannot parse video heads '%s'"), heads);
1908
virDomainVideoDefFree(def);
1916
virDomainHostdevSubsysUsbDefParseXML(virConnectPtr conn,
1917
const xmlNodePtr node,
1918
virDomainHostdevDefPtr def,
1919
int flags ATTRIBUTE_UNUSED) {
1922
int got_product, got_vendor;
1925
/* Product can validly be 0, so we need some extra help to determine
1926
* if it is uninitialized*/
1930
cur = node->children;
1931
while (cur != NULL) {
1932
if (cur->type == XML_ELEMENT_NODE) {
1933
if (xmlStrEqual(cur->name, BAD_CAST "vendor")) {
1934
char *vendor = virXMLPropString(cur, "id");
1938
if (virStrToLong_ui(vendor, NULL, 0,
1939
&def->source.subsys.u.usb.vendor) < 0) {
1940
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1941
_("cannot parse vendor id %s"), vendor);
1947
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1948
"%s", _("usb vendor needs id"));
1951
} else if (xmlStrEqual(cur->name, BAD_CAST "product")) {
1952
char* product = virXMLPropString(cur, "id");
1956
if (virStrToLong_ui(product, NULL, 0,
1957
&def->source.subsys.u.usb.product) < 0) {
1958
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1959
_("cannot parse product %s"),
1966
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1967
"%s", _("usb product needs id"));
1970
} else if (xmlStrEqual(cur->name, BAD_CAST "address")) {
1973
bus = virXMLPropString(cur, "bus");
1975
if (virStrToLong_ui(bus, NULL, 0,
1976
&def->source.subsys.u.usb.bus) < 0) {
1977
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1978
_("cannot parse bus %s"), bus);
1984
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1985
"%s", _("usb address needs bus id"));
1989
device = virXMLPropString(cur, "device");
1991
if (virStrToLong_ui(device, NULL, 0,
1992
&def->source.subsys.u.usb.device) < 0) {
1993
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
1994
_("cannot parse device %s"),
2001
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
2002
_("usb address needs device id"));
2006
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2007
_("unknown usb source type '%s'"),
2015
if (got_vendor && def->source.subsys.u.usb.vendor == 0) {
2016
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2017
"%s", _("vendor cannot be 0."));
2021
if (!got_vendor && got_product) {
2022
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2023
"%s", _("missing vendor"));
2026
if (got_vendor && !got_product) {
2027
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2028
"%s", _("missing product"));
2039
virDomainHostdevSubsysPciDefParseXML(virConnectPtr conn,
2040
const xmlNodePtr node,
2041
virDomainHostdevDefPtr def,
2047
cur = node->children;
2048
while (cur != NULL) {
2049
if (cur->type == XML_ELEMENT_NODE) {
2050
if (xmlStrEqual(cur->name, BAD_CAST "address")) {
2052
char *domain = virXMLPropString(cur, "domain");
2054
if (virStrToLong_ui(domain, NULL, 0,
2055
&def->source.subsys.u.pci.domain) < 0) {
2056
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2057
_("cannot parse domain %s"),
2065
char *bus = virXMLPropString(cur, "bus");
2067
if (virStrToLong_ui(bus, NULL, 0,
2068
&def->source.subsys.u.pci.bus) < 0) {
2069
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2070
_("cannot parse bus %s"), bus);
2076
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2077
"%s", _("pci address needs bus id"));
2081
char *slot = virXMLPropString(cur, "slot");
2083
if (virStrToLong_ui(slot, NULL, 0,
2084
&def->source.subsys.u.pci.slot) < 0) {
2085
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2086
_("cannot parse slot %s"),
2093
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2094
"%s", _("pci address needs slot id"));
2098
char *function = virXMLPropString(cur, "function");
2100
if (virStrToLong_ui(function, NULL, 0,
2101
&def->source.subsys.u.pci.function) < 0) {
2102
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2103
_("cannot parse function %s"),
2110
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
2111
_("pci address needs function id"));
2114
} else if ((flags & VIR_DOMAIN_XML_INTERNAL_STATUS) &&
2115
xmlStrEqual(cur->name, BAD_CAST "state")) {
2116
char *devaddr = virXMLPropString(cur, "devaddr");
2118
sscanf(devaddr, "%x:%x:%x",
2119
&def->source.subsys.u.pci.guest_addr.domain,
2120
&def->source.subsys.u.pci.guest_addr.bus,
2121
&def->source.subsys.u.pci.guest_addr.slot) < 3) {
2122
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2123
_("Unable to parse devaddr parameter '%s'"),
2129
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2130
_("unknown pci source type '%s'"),
2144
static virDomainHostdevDefPtr
2145
virDomainHostdevDefParseXML(virConnectPtr conn,
2146
const xmlNodePtr node,
2150
virDomainHostdevDefPtr def;
2151
char *mode, *type = NULL, *managed = NULL;
2153
if (VIR_ALLOC(def) < 0) {
2154
virReportOOMError(conn);
2159
mode = virXMLPropString(node, "mode");
2161
if ((def->mode=virDomainHostdevModeTypeFromString(mode)) < 0) {
2162
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2163
_("unknown hostdev mode '%s'"), mode);
2167
def->mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS;
2170
type = virXMLPropString(node, "type");
2172
if ((def->source.subsys.type = virDomainHostdevSubsysTypeFromString(type)) < 0) {
2173
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2174
_("unknown host device type '%s'"), type);
2178
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2179
"%s", _("missing type in hostdev"));
2183
managed = virXMLPropString(node, "managed");
2184
if (managed != NULL) {
2185
if (STREQ(managed, "yes"))
2190
cur = node->children;
2191
while (cur != NULL) {
2192
if (cur->type == XML_ELEMENT_NODE) {
2193
if (xmlStrEqual(cur->name, BAD_CAST "source")) {
2194
if (def->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
2195
def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
2196
if (virDomainHostdevSubsysUsbDefParseXML(conn, cur,
2200
if (def->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
2201
def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
2202
if (virDomainHostdevSubsysPciDefParseXML(conn, cur, def, flags) < 0)
2206
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2207
_("unknown node %s"), cur->name);
2219
virDomainHostdevDefFree(def);
2225
static int virDomainLifecycleParseXML(virConnectPtr conn,
2226
xmlXPathContextPtr ctxt,
2231
char *tmp = virXPathString(conn, xpath, ctxt);
2235
*val = virDomainLifecycleTypeFromString(tmp);
2237
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2238
_("unknown lifecycle action %s"), tmp);
2248
virSecurityLabelDefParseXML(virConnectPtr conn,
2249
const virDomainDefPtr def,
2250
xmlXPathContextPtr ctxt,
2255
if (virXPathNode(conn, "./seclabel", ctxt) == NULL)
2258
p = virXPathStringLimit(conn, "string(./seclabel/@type)",
2259
VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
2261
virDomainReportError(conn, VIR_ERR_XML_ERROR,
2262
"%s", _("missing security type"));
2265
def->seclabel.type = virDomainSeclabelTypeFromString(p);
2267
if (def->seclabel.type < 0) {
2268
virDomainReportError(conn, VIR_ERR_XML_ERROR,
2269
"%s", _("invalid security type"));
2273
/* Only parse details, if using static labels, or
2274
* if the 'live' VM XML is requested
2276
if (def->seclabel.type == VIR_DOMAIN_SECLABEL_STATIC ||
2277
!(flags & VIR_DOMAIN_XML_INACTIVE)) {
2278
p = virXPathStringLimit(conn, "string(./seclabel/@model)",
2279
VIR_SECURITY_MODEL_BUFLEN-1, ctxt);
2281
virDomainReportError(conn, VIR_ERR_XML_ERROR,
2282
"%s", _("missing security model"));
2285
def->seclabel.model = p;
2287
p = virXPathStringLimit(conn, "string(./seclabel/label[1])",
2288
VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
2290
virDomainReportError(conn, VIR_ERR_XML_ERROR,
2291
"%s", _("security label is missing"));
2295
def->seclabel.label = p;
2298
/* Only parse imagelabel, if requested live XML for dynamic label */
2299
if (def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC &&
2300
!(flags & VIR_DOMAIN_XML_INACTIVE)) {
2301
p = virXPathStringLimit(conn, "string(./seclabel/imagelabel[1])",
2302
VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
2304
virDomainReportError(conn, VIR_ERR_XML_ERROR,
2305
"%s", _("security imagelabel is missing"));
2308
def->seclabel.imagelabel = p;
2314
virSecurityLabelDefFree(def);
2318
virDomainDeviceDefPtr virDomainDeviceDefParse(virConnectPtr conn,
2320
const virDomainDefPtr def,
2326
virDomainDeviceDefPtr dev = NULL;
2328
if (!(xml = xmlReadDoc(BAD_CAST xmlStr, "device.xml", NULL,
2329
XML_PARSE_NOENT | XML_PARSE_NONET |
2330
XML_PARSE_NOERROR | XML_PARSE_NOWARNING))) {
2331
virDomainReportError(conn, VIR_ERR_XML_ERROR, NULL);
2335
node = xmlDocGetRootElement(xml);
2337
virDomainReportError(conn, VIR_ERR_XML_ERROR,
2338
"%s", _("missing root element"));
2342
if (VIR_ALLOC(dev) < 0) {
2343
virReportOOMError(conn);
2347
if (xmlStrEqual(node->name, BAD_CAST "disk")) {
2348
dev->type = VIR_DOMAIN_DEVICE_DISK;
2349
if (!(dev->data.disk = virDomainDiskDefParseXML(conn, node, flags)))
2351
} else if (xmlStrEqual(node->name, BAD_CAST "filesystem")) {
2352
dev->type = VIR_DOMAIN_DEVICE_FS;
2353
if (!(dev->data.fs = virDomainFSDefParseXML(conn, node, flags)))
2355
} else if (xmlStrEqual(node->name, BAD_CAST "interface")) {
2356
dev->type = VIR_DOMAIN_DEVICE_NET;
2357
if (!(dev->data.net = virDomainNetDefParseXML(conn, caps, node, flags)))
2359
} else if (xmlStrEqual(node->name, BAD_CAST "input")) {
2360
dev->type = VIR_DOMAIN_DEVICE_INPUT;
2361
if (!(dev->data.input = virDomainInputDefParseXML(conn, def->os.type,
2364
} else if (xmlStrEqual(node->name, BAD_CAST "sound")) {
2365
dev->type = VIR_DOMAIN_DEVICE_SOUND;
2366
if (!(dev->data.sound = virDomainSoundDefParseXML(conn, node, flags)))
2368
} else if (xmlStrEqual(node->name, BAD_CAST "video")) {
2369
dev->type = VIR_DOMAIN_DEVICE_VIDEO;
2370
if (!(dev->data.video = virDomainVideoDefParseXML(conn, node, def, flags)))
2372
} else if (xmlStrEqual(node->name, BAD_CAST "hostdev")) {
2373
dev->type = VIR_DOMAIN_DEVICE_HOSTDEV;
2374
if (!(dev->data.hostdev = virDomainHostdevDefParseXML(conn, node, flags)))
2377
virDomainReportError(conn, VIR_ERR_XML_ERROR,
2378
"%s", _("unknown device type"));
2394
int virDomainDiskInsert(virDomainDefPtr def,
2395
virDomainDiskDefPtr disk)
2398
if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0)
2401
virDomainDiskInsertPreAlloced(def, disk);
2406
void virDomainDiskInsertPreAlloced(virDomainDefPtr def,
2407
virDomainDiskDefPtr disk)
2410
/* Tenatively plan to insert disk at the end. */
2413
/* Then work backwards looking for disks on
2414
* the same bus. If we find a disk with a drive
2415
* index greater than the new one, insert at
2418
for (i = (def->ndisks - 1) ; i >= 0 ; i--) {
2419
/* If bus matches and current disk is after
2420
* new disk, then new disk should go here */
2421
if (def->disks[i]->bus == disk->bus &&
2422
(virDiskNameToIndex(def->disks[i]->dst) >
2423
virDiskNameToIndex(disk->dst))) {
2425
} else if (def->disks[i]->bus == disk->bus &&
2427
/* Last disk with match bus is before the
2428
* new disk, then put new disk just after
2434
/* No disks with this bus yet, so put at end of list */
2436
insertAt = def->ndisks;
2438
if (insertAt < def->ndisks)
2439
memmove(def->disks + insertAt + 1,
2440
def->disks + insertAt,
2441
(sizeof(def->disks[0]) * (def->ndisks-insertAt)));
2443
def->disks[insertAt] = disk;
2449
static char *virDomainDefDefaultEmulator(virConnectPtr conn,
2450
virDomainDefPtr def,
2453
const char *emulator;
2456
type = virDomainVirtTypeToString(def->virtType);
2458
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2459
"%s", _("unknown virt type"));
2463
emulator = virCapabilitiesDefaultGuestEmulator(caps,
2469
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2470
_("no emulator for domain %s os type %s on architecture %s"),
2471
type, def->os.type, def->os.arch);
2475
retemu = strdup(emulator);
2477
virReportOOMError(conn);
2482
static virDomainDefPtr virDomainDefParseXML(virConnectPtr conn,
2484
xmlXPathContextPtr ctxt, int flags)
2486
xmlNodePtr *nodes = NULL, node = NULL;
2490
virDomainDefPtr def;
2492
if (VIR_ALLOC(def) < 0) {
2493
virReportOOMError(conn);
2497
if (!(flags & VIR_DOMAIN_XML_INACTIVE))
2498
if((virXPathLong(conn, "string(./@id)", ctxt, &id)) < 0)
2502
/* Find out what type of virtualization to use */
2503
if (!(tmp = virXPathString(conn, "string(./@type)", ctxt))) {
2504
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2505
"%s", _("missing domain type attribute"));
2509
if ((def->virtType = virDomainVirtTypeFromString(tmp)) < 0) {
2510
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2511
_("invalid domain type %s"), tmp);
2516
/* Extract domain name */
2517
if (!(def->name = virXPathString(conn, "string(./name[1])", ctxt))) {
2518
virDomainReportError(conn, VIR_ERR_NO_NAME, NULL);
2522
/* Extract domain uuid */
2523
tmp = virXPathString(conn, "string(./uuid[1])", ctxt);
2525
if (virUUIDGenerate(def->uuid)) {
2526
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2527
"%s", _("Failed to generate UUID"));
2531
if (virUUIDParse(tmp, def->uuid) < 0) {
2532
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2533
"%s", _("malformed uuid element"));
2539
/* Extract documentation if present */
2540
def->description = virXPathString(conn, "string(./description[1])", ctxt);
2542
/* Extract domain memory */
2543
if (virXPathULong(conn, "string(./memory[1])", ctxt, &def->maxmem) < 0) {
2544
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2545
"%s", _("missing memory element"));
2549
if (virXPathULong(conn, "string(./currentMemory[1])", ctxt, &def->memory) < 0)
2550
def->memory = def->maxmem;
2552
node = virXPathNode(conn, "./memoryBacking/hugepages", ctxt);
2554
def->hugepage_backed = 1;
2556
if (virXPathULong(conn, "string(./vcpu[1])", ctxt, &def->vcpus) < 0)
2559
tmp = virXPathString(conn, "string(./vcpu[1]/@cpuset)", ctxt);
2562
def->cpumasklen = VIR_DOMAIN_CPUMASK_LEN;
2563
if (VIR_ALLOC_N(def->cpumask, def->cpumasklen) < 0) {
2564
virReportOOMError(conn);
2567
if (virDomainCpuSetParse(conn, (const char **)&set,
2569
def->cpumasklen) < 0)
2574
n = virXPathNodeSet(conn, "./features/*", ctxt, &nodes);
2578
for (i = 0 ; i < n ; i++) {
2579
int val = virDomainFeatureTypeFromString((const char *)nodes[i]->name);
2581
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2582
_("unexpected feature %s"),
2586
def->features |= (1 << val);
2591
if (virDomainLifecycleParseXML(conn, ctxt, "string(./on_reboot[1])",
2592
&def->onReboot, VIR_DOMAIN_LIFECYCLE_RESTART) < 0)
2595
if (virDomainLifecycleParseXML(conn, ctxt, "string(./on_poweroff[1])",
2596
&def->onPoweroff, VIR_DOMAIN_LIFECYCLE_DESTROY) < 0)
2599
if (virDomainLifecycleParseXML(conn, ctxt, "string(./on_crash[1])",
2600
&def->onCrash, VIR_DOMAIN_LIFECYCLE_DESTROY) < 0)
2604
tmp = virXPathString(conn, "string(./clock/@offset)", ctxt);
2605
if (tmp && STREQ(tmp, "localtime"))
2609
def->os.bootloader = virXPathString(conn, "string(./bootloader)", ctxt);
2610
def->os.bootloaderArgs = virXPathString(conn, "string(./bootloader_args)", ctxt);
2612
def->os.type = virXPathString(conn, "string(./os/type[1])", ctxt);
2613
if (!def->os.type) {
2614
if (def->os.bootloader) {
2615
def->os.type = strdup("xen");
2616
if (!def->os.type) {
2617
virReportOOMError(conn);
2621
virDomainReportError(conn, VIR_ERR_OS_TYPE,
2622
"%s", _("no OS type"));
2627
* HACK: For xen driver we previously used bogus 'linux' as the
2628
* os type for paravirt, whereas capabilities declare it to
2629
* be 'xen'. So we accept the former and convert
2631
if (STREQ(def->os.type, "linux") &&
2632
def->virtType == VIR_DOMAIN_VIRT_XEN) {
2633
VIR_FREE(def->os.type);
2634
if (!(def->os.type = strdup("xen"))) {
2635
virReportOOMError(conn);
2640
if (!virCapabilitiesSupportsGuestOSType(caps, def->os.type)) {
2641
virDomainReportError(conn, VIR_ERR_OS_TYPE,
2642
"%s", def->os.type);
2646
def->os.arch = virXPathString(conn, "string(./os/type[1]/@arch)", ctxt);
2648
if (!virCapabilitiesSupportsGuestArch(caps, def->os.type, def->os.arch)) {
2649
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2650
_("os type '%s' & arch '%s' combination is not supported"),
2651
def->os.type, def->os.arch);
2655
const char *defaultArch = virCapabilitiesDefaultGuestArch(caps, def->os.type, virDomainVirtTypeToString(def->virtType));
2656
if (defaultArch == NULL) {
2657
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2658
_("no supported architecture for os type '%s'"),
2662
if (!(def->os.arch = strdup(defaultArch))) {
2663
virReportOOMError(conn);
2668
def->os.machine = virXPathString(conn, "string(./os/type[1]/@machine)", ctxt);
2669
if (!def->os.machine) {
2670
const char *defaultMachine = virCapabilitiesDefaultGuestMachine(caps,
2673
virDomainVirtTypeToString(def->virtType));
2674
if (defaultMachine != NULL) {
2675
if (!(def->os.machine = strdup(defaultMachine))) {
2676
virReportOOMError(conn);
2683
* Booting options for different OS types....
2685
* - A bootloader (and optional kernel+initrd) (xen)
2686
* - A kernel + initrd (xen)
2687
* - A boot device (and optional kernel+initrd) (hvm)
2688
* - An init script (exe)
2691
if (STREQ(def->os.type, "exe")) {
2692
def->os.init = virXPathString(conn, "string(./os/init[1])", ctxt);
2695
if (STREQ(def->os.type, "xen") ||
2696
STREQ(def->os.type, "hvm") ||
2697
STREQ(def->os.type, "uml")) {
2698
def->os.kernel = virXPathString(conn, "string(./os/kernel[1])", ctxt);
2699
def->os.initrd = virXPathString(conn, "string(./os/initrd[1])", ctxt);
2700
def->os.cmdline = virXPathString(conn, "string(./os/cmdline[1])", ctxt);
2701
def->os.root = virXPathString(conn, "string(./os/root[1])", ctxt);
2702
def->os.loader = virXPathString(conn, "string(./os/loader[1])", ctxt);
2705
if (STREQ(def->os.type, "hvm")) {
2706
/* analysis of the boot devices */
2707
if ((n = virXPathNodeSet(conn, "./os/boot", ctxt, &nodes)) < 0) {
2708
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2709
"%s", _("cannot extract boot device"));
2712
for (i = 0 ; i < n && i < VIR_DOMAIN_BOOT_LAST ; i++) {
2714
char *dev = virXMLPropString(nodes[i], "dev");
2716
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2717
"%s", _("missing boot device"));
2720
if ((val = virDomainBootTypeFromString(dev)) < 0) {
2721
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2722
_("unknown boot device '%s'"),
2728
def->os.bootDevs[def->os.nBootDevs++] = val;
2730
if (def->os.nBootDevs == 0) {
2731
def->os.nBootDevs = 1;
2732
def->os.bootDevs[0] = VIR_DOMAIN_BOOT_DISK;
2737
def->emulator = virXPathString(conn, "string(./devices/emulator[1])", ctxt);
2738
if (!def->emulator && virCapabilitiesIsEmulatorRequired(caps)) {
2739
def->emulator = virDomainDefDefaultEmulator(conn, def, caps);
2744
/* analysis of the disk devices */
2745
if ((n = virXPathNodeSet(conn, "./devices/disk", ctxt, &nodes)) < 0) {
2746
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2747
"%s", _("cannot extract disk devices"));
2750
if (n && VIR_ALLOC_N(def->disks, n) < 0)
2752
for (i = 0 ; i < n ; i++) {
2753
virDomainDiskDefPtr disk = virDomainDiskDefParseXML(conn,
2759
def->disks[def->ndisks++] = disk;
2763
/* analysis of the filesystems */
2764
if ((n = virXPathNodeSet(conn, "./devices/filesystem", ctxt, &nodes)) < 0) {
2765
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2766
"%s", _("cannot extract filesystem devices"));
2769
if (n && VIR_ALLOC_N(def->fss, n) < 0)
2771
for (i = 0 ; i < n ; i++) {
2772
virDomainFSDefPtr fs = virDomainFSDefParseXML(conn,
2778
def->fss[def->nfss++] = fs;
2782
/* analysis of the network devices */
2783
if ((n = virXPathNodeSet(conn, "./devices/interface", ctxt, &nodes)) < 0) {
2784
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2785
"%s", _("cannot extract network devices"));
2788
if (n && VIR_ALLOC_N(def->nets, n) < 0)
2790
for (i = 0 ; i < n ; i++) {
2791
virDomainNetDefPtr net = virDomainNetDefParseXML(conn,
2798
def->nets[def->nnets++] = net;
2803
/* analysis of the character devices */
2804
if ((n = virXPathNodeSet(conn, "./devices/parallel", ctxt, &nodes)) < 0) {
2805
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2806
"%s", _("cannot extract parallel devices"));
2809
if (n && VIR_ALLOC_N(def->parallels, n) < 0)
2812
for (i = 0 ; i < n ; i++) {
2813
virDomainChrDefPtr chr = virDomainChrDefParseXML(conn,
2820
def->parallels[def->nparallels++] = chr;
2824
if ((n = virXPathNodeSet(conn, "./devices/serial", ctxt, &nodes)) < 0) {
2825
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2826
"%s", _("cannot extract serial devices"));
2829
if (n && VIR_ALLOC_N(def->serials, n) < 0)
2832
for (i = 0 ; i < n ; i++) {
2833
virDomainChrDefPtr chr = virDomainChrDefParseXML(conn,
2840
def->serials[def->nserials++] = chr;
2844
if ((node = virXPathNode(conn, "./devices/console[1]", ctxt)) != NULL) {
2845
virDomainChrDefPtr chr = virDomainChrDefParseXML(conn,
2853
* For HVM console actually created a serial device
2854
* while for non-HVM it was a parvirt console
2856
if (STREQ(def->os.type, "hvm")) {
2857
if (def->nserials != 0) {
2858
virDomainChrDefFree(chr);
2860
if (VIR_ALLOC_N(def->serials, 1) < 0) {
2861
virDomainChrDefFree(chr);
2865
def->serials[0] = chr;
2873
/* analysis of the input devices */
2874
if ((n = virXPathNodeSet(conn, "./devices/input", ctxt, &nodes)) < 0) {
2875
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2876
"%s", _("cannot extract input devices"));
2879
if (n && VIR_ALLOC_N(def->inputs, n) < 0)
2882
for (i = 0 ; i < n ; i++) {
2883
virDomainInputDefPtr input = virDomainInputDefParseXML(conn,
2891
/* With QEMU / KVM / Xen graphics, mouse + PS/2 is implicit
2892
* with graphics, so don't store it.
2893
* XXX will this be true for other virt types ? */
2894
if ((STREQ(def->os.type, "hvm") &&
2895
input->bus == VIR_DOMAIN_INPUT_BUS_PS2 &&
2896
input->type == VIR_DOMAIN_INPUT_TYPE_MOUSE) ||
2897
(STRNEQ(def->os.type, "hvm") &&
2898
input->bus == VIR_DOMAIN_INPUT_BUS_XEN &&
2899
input->type == VIR_DOMAIN_INPUT_TYPE_MOUSE)) {
2900
virDomainInputDefFree(input);
2904
def->inputs[def->ninputs++] = input;
2908
/* analysis of the graphics devices */
2909
if ((n = virXPathNodeSet(conn, "./devices/graphics", ctxt, &nodes)) < 0) {
2910
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2911
"%s", _("cannot extract graphics devices"));
2914
if (n && VIR_ALLOC_N(def->graphics, n) < 0)
2916
for (i = 0 ; i < n ; i++) {
2917
virDomainGraphicsDefPtr graphics = virDomainGraphicsDefParseXML(conn,
2923
def->graphics[def->ngraphics++] = graphics;
2927
/* If graphics are enabled, there's an implicit PS2 mouse */
2928
if (def->ngraphics > 0) {
2929
virDomainInputDefPtr input;
2931
if (VIR_ALLOC(input) < 0) {
2932
virReportOOMError(conn);
2935
if (STREQ(def->os.type, "hvm")) {
2936
input->type = VIR_DOMAIN_INPUT_TYPE_MOUSE;
2937
input->bus = VIR_DOMAIN_INPUT_BUS_PS2;
2939
input->type = VIR_DOMAIN_INPUT_TYPE_MOUSE;
2940
input->bus = VIR_DOMAIN_INPUT_BUS_XEN;
2943
if (VIR_REALLOC_N(def->inputs, def->ninputs + 1) < 0) {
2944
virDomainInputDefFree(input);
2947
def->inputs[def->ninputs] = input;
2952
/* analysis of the sound devices */
2953
if ((n = virXPathNodeSet(conn, "./devices/sound", ctxt, &nodes)) < 0) {
2954
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2955
"%s", _("cannot extract sound devices"));
2958
if (n && VIR_ALLOC_N(def->sounds, n) < 0)
2960
for (i = 0 ; i < n ; i++) {
2961
int collision = 0, j;
2962
virDomainSoundDefPtr sound = virDomainSoundDefParseXML(conn,
2968
/* Verify there's no duplicated sound card */
2969
for (j = 0 ; j < def->nsounds ; j++) {
2970
if (def->sounds[j]->model == sound->model)
2974
virDomainSoundDefFree(sound);
2978
def->sounds[def->nsounds++] = sound;
2982
/* analysis of the video devices */
2983
if ((n = virXPathNodeSet(conn, "./devices/video", ctxt, &nodes)) < 0) {
2984
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
2985
"%s", _("cannot extract video devices"));
2988
if (n && VIR_ALLOC_N(def->videos, n) < 0)
2990
for (i = 0 ; i < n ; i++) {
2991
virDomainVideoDefPtr video = virDomainVideoDefParseXML(conn,
2997
def->videos[def->nvideos++] = video;
3001
/* For backwards compatability, if no <video> tag is set but there
3002
* is a <graphics> tag, then we add a single video tag */
3003
if (def->ngraphics && !def->nvideos) {
3004
virDomainVideoDefPtr video;
3005
if (VIR_ALLOC(video) < 0)
3007
video->type = virDomainVideoDefaultType(def);
3008
if (video->type < 0) {
3009
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
3010
_("cannot determine default video type"));
3014
video->vram = virDomainVideoDefaultRAM(def, video->type);
3016
if (VIR_ALLOC_N(def->videos, 1) < 0) {
3017
virDomainVideoDefFree(video);
3020
def->videos[def->nvideos++] = video;
3023
/* analysis of the host devices */
3024
if ((n = virXPathNodeSet(conn, "./devices/hostdev", ctxt, &nodes)) < 0) {
3025
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3026
"%s", _("cannot extract host devices"));
3029
if (n && VIR_ALLOC_N(def->hostdevs, n) < 0)
3031
for (i = 0 ; i < n ; i++) {
3032
virDomainHostdevDefPtr hostdev = virDomainHostdevDefParseXML(conn,
3038
def->hostdevs[def->nhostdevs++] = hostdev;
3042
/* analysis of security label */
3043
if (virSecurityLabelDefParseXML(conn, def, ctxt, flags) == -1)
3049
virReportOOMError(conn);
3055
virDomainDefFree(def);
3060
static virDomainObjPtr virDomainObjParseXML(virConnectPtr conn,
3062
xmlXPathContextPtr ctxt)
3068
virDomainObjPtr obj;
3070
xmlNodePtr *nodes = NULL;
3073
if (!(obj = virDomainObjNew(conn)))
3076
if (!(config = virXPathNode(conn, "./domain", ctxt))) {
3077
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3078
"%s", _("no domain config"));
3082
oldnode = ctxt->node;
3083
ctxt->node = config;
3084
obj->def = virDomainDefParseXML(conn, caps, ctxt,
3085
VIR_DOMAIN_XML_INTERNAL_STATUS);
3086
ctxt->node = oldnode;
3090
if (!(tmp = virXPathString(conn, "string(./@state)", ctxt))) {
3091
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3092
"%s", _("missing domain state"));
3095
if ((obj->state = virDomainStateTypeFromString(tmp)) < 0) {
3096
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3097
_("invalid domain state '%s'"), tmp);
3103
if ((virXPathLong(conn, "string(./@pid)", ctxt, &val)) < 0) {
3104
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3105
"%s", _("invalid pid"));
3108
obj->pid = (pid_t)val;
3110
if (VIR_ALLOC(obj->monitor_chr) < 0) {
3111
virReportOOMError(conn);
3116
virXPathString(conn, "string(./monitor[1]/@path)", ctxt))) {
3117
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3118
"%s", _("no monitor path"));
3122
tmp = virXPathString(conn, "string(./monitor[1]/@type)", ctxt);
3124
obj->monitor_chr->type = virDomainChrTypeFromString(tmp);
3126
obj->monitor_chr->type = VIR_DOMAIN_CHR_TYPE_PTY;
3129
switch (obj->monitor_chr->type) {
3130
case VIR_DOMAIN_CHR_TYPE_PTY:
3131
obj->monitor_chr->data.file.path = monitorpath;
3133
case VIR_DOMAIN_CHR_TYPE_UNIX:
3134
obj->monitor_chr->data.nix.path = monitorpath;
3137
VIR_FREE(monitorpath);
3138
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3139
_("unsupported monitor type '%s'"),
3140
virDomainChrTypeToString(obj->monitor_chr->type));
3144
n = virXPathNodeSet(conn, "./vcpus/vcpu", ctxt, &nodes);
3149
if (VIR_REALLOC_N(obj->vcpupids, obj->nvcpupids) < 0)
3152
for (i = 0 ; i < n ; i++) {
3153
char *pidstr = virXMLPropString(nodes[i], "pid");
3157
if (virStrToLong_i(pidstr, NULL, 10, &(obj->vcpupids[i])) < 0) {
3170
virDomainChrDefFree(obj->monitor_chr);
3171
virDomainObjFree(obj);
3176
/* Called from SAX on parsing errors in the XML. */
3178
catchXMLError (void *ctx, const char *msg ATTRIBUTE_UNUSED, ...)
3180
xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
3183
virConnectPtr conn = ctxt->_private;
3185
if (virGetLastError() == NULL &&
3186
ctxt->lastError.level == XML_ERR_FATAL &&
3187
ctxt->lastError.message != NULL) {
3188
virDomainReportError (conn, VIR_ERR_XML_DETAIL,
3189
_("at line %d: %s"),
3190
ctxt->lastError.line,
3191
ctxt->lastError.message);
3196
virDomainDefPtr virDomainDefParseString(virConnectPtr conn,
3201
xmlParserCtxtPtr pctxt;
3202
xmlDocPtr xml = NULL;
3204
virDomainDefPtr def = NULL;
3206
/* Set up a parser context so we can catch the details of XML errors. */
3207
pctxt = xmlNewParserCtxt ();
3208
if (!pctxt || !pctxt->sax)
3210
pctxt->sax->error = catchXMLError;
3211
pctxt->_private = conn;
3213
if (conn) virResetError (&conn->err);
3214
xml = xmlCtxtReadDoc (pctxt, BAD_CAST xmlStr, "domain.xml", NULL,
3215
XML_PARSE_NOENT | XML_PARSE_NONET |
3216
XML_PARSE_NOWARNING);
3218
if (virGetLastError() == NULL)
3219
virDomainReportError(conn, VIR_ERR_XML_ERROR,
3220
"%s", _("failed to parse xml document"));
3224
if ((root = xmlDocGetRootElement(xml)) == NULL) {
3225
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3226
"%s", _("missing root element"));
3230
def = virDomainDefParseNode(conn, caps, xml, root, flags);
3233
xmlFreeParserCtxt (pctxt);
3238
virDomainDefPtr virDomainDefParseFile(virConnectPtr conn,
3240
const char *filename, int flags)
3242
xmlParserCtxtPtr pctxt;
3243
xmlDocPtr xml = NULL;
3245
virDomainDefPtr def = NULL;
3247
/* Set up a parser context so we can catch the details of XML errors. */
3248
pctxt = xmlNewParserCtxt ();
3249
if (!pctxt || !pctxt->sax)
3251
pctxt->sax->error = catchXMLError;
3252
pctxt->_private = conn;
3254
if (conn) virResetError (&conn->err);
3255
xml = xmlCtxtReadFile (pctxt, filename, NULL,
3256
XML_PARSE_NOENT | XML_PARSE_NONET |
3257
XML_PARSE_NOWARNING);
3259
if (virGetLastError() == NULL)
3260
virDomainReportError(conn, VIR_ERR_XML_ERROR,
3261
"%s", _("failed to parse xml document"));
3265
if ((root = xmlDocGetRootElement(xml)) == NULL) {
3266
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3267
"%s", _("missing root element"));
3271
def = virDomainDefParseNode(conn, caps, xml, root, flags);
3274
xmlFreeParserCtxt (pctxt);
3280
virDomainDefPtr virDomainDefParseNode(virConnectPtr conn,
3286
xmlXPathContextPtr ctxt = NULL;
3287
virDomainDefPtr def = NULL;
3289
if (!xmlStrEqual(root->name, BAD_CAST "domain")) {
3290
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3291
"%s", _("incorrect root element"));
3295
ctxt = xmlXPathNewContext(xml);
3297
virReportOOMError(conn);
3302
def = virDomainDefParseXML(conn, caps, ctxt, flags);
3305
xmlXPathFreeContext(ctxt);
3310
virDomainObjPtr virDomainObjParseFile(virConnectPtr conn,
3312
const char *filename)
3314
xmlParserCtxtPtr pctxt;
3315
xmlDocPtr xml = NULL;
3317
virDomainObjPtr obj = NULL;
3319
/* Set up a parser context so we can catch the details of XML errors. */
3320
pctxt = xmlNewParserCtxt ();
3321
if (!pctxt || !pctxt->sax)
3323
pctxt->sax->error = catchXMLError;
3324
pctxt->_private = conn;
3326
if (conn) virResetError (&conn->err);
3327
xml = xmlCtxtReadFile (pctxt, filename, NULL,
3328
XML_PARSE_NOENT | XML_PARSE_NONET |
3329
XML_PARSE_NOWARNING);
3331
if (virGetLastError() == NULL)
3332
virDomainReportError(conn, VIR_ERR_XML_ERROR,
3333
"%s", _("failed to parse xml document"));
3337
if ((root = xmlDocGetRootElement(xml)) == NULL) {
3338
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3339
"%s", _("missing root element"));
3343
obj = virDomainObjParseNode(conn, caps, xml, root);
3346
xmlFreeParserCtxt (pctxt);
3352
virDomainObjPtr virDomainObjParseNode(virConnectPtr conn,
3357
xmlXPathContextPtr ctxt = NULL;
3358
virDomainObjPtr obj = NULL;
3360
if (!xmlStrEqual(root->name, BAD_CAST "domstatus")) {
3361
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3362
"%s", _("incorrect root element"));
3366
ctxt = xmlXPathNewContext(xml);
3368
virReportOOMError(conn);
3373
obj = virDomainObjParseXML(conn, caps, ctxt);
3376
xmlXPathFreeContext(ctxt);
3380
#endif /* ! PROXY */
3382
/************************************************************************
3384
* Parser and converter for the CPUset strings used in libvirt *
3386
************************************************************************/
3388
* virDomainCpuNumberParse
3389
* @str: pointer to the char pointer used
3390
* @maxcpu: maximum CPU number allowed
3392
* Parse a CPU number
3394
* Returns the CPU number or -1 in case of error. @str will be
3395
* updated to skip the number.
3398
virDomainCpuNumberParse(const char **str, int maxcpu)
3401
const char *cur = *str;
3403
if (!c_isdigit(*cur))
3406
while (c_isdigit(*cur)) {
3407
ret = ret * 10 + (*cur - '0');
3417
* virDomainCpuSetFormat:
3419
* @cpuset: pointer to a char array for the CPU set
3420
* @maxcpu: number of elements available in @cpuset
3422
* Serialize the cpuset to a string
3424
* Returns the new string NULL in case of error. The string need to be
3425
* freed by the caller.
3428
virDomainCpuSetFormat(virConnectPtr conn, char *cpuset, int maxcpu)
3430
virBuffer buf = VIR_BUFFER_INITIALIZER;
3434
if ((cpuset == NULL) || (maxcpu <= 0) || (maxcpu > 100000))
3439
while (cur < maxcpu) {
3443
} else if (start != -1) {
3445
virBufferAddLit(&buf, ",");
3448
if (cur == start + 1)
3449
virBufferVSprintf(&buf, "%d", start);
3451
virBufferVSprintf(&buf, "%d-%d", start, cur - 1);
3458
virBufferAddLit(&buf, ",");
3459
if (maxcpu == start + 1)
3460
virBufferVSprintf(&buf, "%d", start);
3462
virBufferVSprintf(&buf, "%d-%d", start, maxcpu - 1);
3465
if (virBufferError(&buf)) {
3466
virReportOOMError(conn);
3470
return virBufferContentAndReset(&buf);
3474
* virDomainCpuSetParse:
3476
* @str: pointer to a CPU set string pointer
3477
* @sep: potential character used to mark the end of string if not 0
3478
* @cpuset: pointer to a char array for the CPU set
3479
* @maxcpu: number of elements available in @cpuset
3481
* Parse the cpu set, it will set the value for enabled CPUs in the @cpuset
3482
* to 1, and 0 otherwise. The syntax allows coma separated entries each
3483
* can be either a CPU number, ^N to unset that CPU or N-M for ranges.
3485
* Returns the number of CPU found in that set, or -1 in case of error.
3486
* @cpuset is modified accordingly to the value parsed.
3487
* @str is updated to the end of the part parsed
3490
virDomainCpuSetParse(virConnectPtr conn, const char **str, char sep,
3491
char *cpuset, int maxcpu)
3498
if ((str == NULL) || (cpuset == NULL) || (maxcpu <= 0) ||
3503
virSkipSpaces(&cur);
3507
/* initialize cpumap to all 0s */
3508
for (i = 0; i < maxcpu; i++)
3512
while ((*cur != 0) && (*cur != sep)) {
3514
* 3 constructs are allowed:
3515
* - N : a single CPU number
3516
* - N-M : a range of CPU numbers with N < M
3517
* - ^N : remove a single CPU number from the current set
3524
if (!c_isdigit(*cur))
3526
start = virDomainCpuNumberParse(&cur, maxcpu);
3529
virSkipSpaces(&cur);
3530
if ((*cur == ',') || (*cur == 0) || (*cur == sep)) {
3532
if (cpuset[start] == 1) {
3537
if (cpuset[start] == 0) {
3542
} else if (*cur == '-') {
3546
virSkipSpaces(&cur);
3547
last = virDomainCpuNumberParse(&cur, maxcpu);
3550
for (i = start; i <= last; i++) {
3551
if (cpuset[i] == 0) {
3556
virSkipSpaces(&cur);
3560
virSkipSpaces(&cur);
3562
} else if ((*cur == 0) || (*cur == sep)) {
3571
virDomainReportError(conn, VIR_ERR_XEN_CALL,
3572
"%s", _("topology cpuset syntax error"));
3578
virDomainLifecycleDefFormat(virConnectPtr conn,
3583
const char *typeStr = virDomainLifecycleTypeToString(type);
3585
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3586
_("unexpected lifecycle type %d"), type);
3590
virBufferVSprintf(buf, " <%s>%s</%s>\n", name, typeStr, name);
3597
virDomainDiskDefFormat(virConnectPtr conn,
3599
virDomainDiskDefPtr def,
3602
const char *type = virDomainDiskTypeToString(def->type);
3603
const char *device = virDomainDiskDeviceTypeToString(def->device);
3604
const char *bus = virDomainDiskBusTypeToString(def->bus);
3605
const char *cachemode = virDomainDiskCacheTypeToString(def->cachemode);
3608
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3609
_("unexpected disk type %d"), def->type);
3613
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3614
_("unexpected disk device %d"), def->device);
3618
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3619
_("unexpected disk bus %d"), def->bus);
3623
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3624
_("unexpected disk cache mode %d"), def->cachemode);
3628
virBufferVSprintf(buf,
3629
" <disk type='%s' device='%s'>\n",
3632
if (def->driverName) {
3633
virBufferVSprintf(buf, " <driver name='%s'", def->driverName);
3634
if (def->driverType)
3635
virBufferVSprintf(buf, " type='%s'", def->driverType);
3637
virBufferVSprintf(buf, " cache='%s'", cachemode);
3638
virBufferVSprintf(buf, "/>\n");
3642
if (def->type == VIR_DOMAIN_DISK_TYPE_FILE)
3643
virBufferEscapeString(buf, " <source file='%s'/>\n",
3646
virBufferEscapeString(buf, " <source dev='%s'/>\n",
3650
virBufferVSprintf(buf, " <target dev='%s' bus='%s'/>\n",
3654
virBufferAddLit(buf, " <readonly/>\n");
3656
virBufferAddLit(buf, " <shareable/>\n");
3658
virBufferEscapeString(buf, " <serial>%s</serial>\n",
3660
if (def->encryption != NULL &&
3661
virStorageEncryptionFormat(conn, buf, def->encryption) < 0)
3664
if (flags & VIR_DOMAIN_XML_INTERNAL_STATUS) {
3665
virBufferAddLit(buf, " <state");
3666
if (virDiskHasValidPciAddr(def))
3667
virBufferVSprintf(buf, " devaddr='%.4x:%.2x:%.2x'",
3668
def->pci_addr.domain,
3670
def->pci_addr.slot);
3671
virBufferAddLit(buf, "/>\n");
3674
virBufferAddLit(buf, " </disk>\n");
3680
virDomainFSDefFormat(virConnectPtr conn,
3682
virDomainFSDefPtr def)
3684
const char *type = virDomainFSTypeToString(def->type);
3687
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3688
_("unexpected filesystem type %d"), def->type);
3692
virBufferVSprintf(buf,
3693
" <filesystem type='%s'>\n",
3697
switch (def->type) {
3698
case VIR_DOMAIN_FS_TYPE_MOUNT:
3699
virBufferEscapeString(buf, " <source dir='%s'/>\n",
3703
case VIR_DOMAIN_FS_TYPE_BLOCK:
3704
virBufferEscapeString(buf, " <source dev='%s'/>\n",
3708
case VIR_DOMAIN_FS_TYPE_FILE:
3709
virBufferEscapeString(buf, " <source file='%s'/>\n",
3713
case VIR_DOMAIN_FS_TYPE_TEMPLATE:
3714
virBufferEscapeString(buf, " <source name='%s'/>\n",
3719
virBufferVSprintf(buf, " <target dir='%s'/>\n",
3723
virBufferAddLit(buf, " <readonly/>\n");
3725
virBufferAddLit(buf, " </filesystem>\n");
3731
virDomainNetDefFormat(virConnectPtr conn,
3733
virDomainNetDefPtr def,
3736
const char *type = virDomainNetTypeToString(def->type);
3739
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3740
_("unexpected net type %d"), def->type);
3744
virBufferVSprintf(buf, " <interface type='%s'>\n", type);
3746
virBufferVSprintf(buf,
3747
" <mac address='%02x:%02x:%02x:%02x:%02x:%02x'/>\n",
3748
def->mac[0], def->mac[1], def->mac[2],
3749
def->mac[3], def->mac[4], def->mac[5]);
3751
switch (def->type) {
3752
case VIR_DOMAIN_NET_TYPE_NETWORK:
3753
virBufferEscapeString(buf, " <source network='%s'/>\n",
3754
def->data.network.name);
3757
case VIR_DOMAIN_NET_TYPE_ETHERNET:
3758
if (def->data.ethernet.dev)
3759
virBufferEscapeString(buf, " <source dev='%s'/>\n",
3760
def->data.ethernet.dev);
3761
if (def->data.ethernet.ipaddr)
3762
virBufferVSprintf(buf, " <ip address='%s'/>\n",
3763
def->data.ethernet.ipaddr);
3764
if (def->data.ethernet.script)
3765
virBufferEscapeString(buf, " <script path='%s'/>\n",
3766
def->data.ethernet.script);
3769
case VIR_DOMAIN_NET_TYPE_BRIDGE:
3770
virBufferEscapeString(buf, " <source bridge='%s'/>\n",
3771
def->data.bridge.brname);
3772
if (def->data.bridge.ipaddr)
3773
virBufferVSprintf(buf, " <ip address='%s'/>\n",
3774
def->data.bridge.ipaddr);
3775
if (def->data.bridge.script)
3776
virBufferEscapeString(buf, " <script path='%s'/>\n",
3777
def->data.bridge.script);
3780
case VIR_DOMAIN_NET_TYPE_SERVER:
3781
case VIR_DOMAIN_NET_TYPE_CLIENT:
3782
case VIR_DOMAIN_NET_TYPE_MCAST:
3783
if (def->data.socket.address)
3784
virBufferVSprintf(buf, " <source address='%s' port='%d'/>\n",
3785
def->data.socket.address, def->data.socket.port);
3787
virBufferVSprintf(buf, " <source port='%d'/>\n",
3788
def->data.socket.port);
3791
case VIR_DOMAIN_NET_TYPE_INTERNAL:
3792
virBufferEscapeString(buf, " <source name='%s'/>\n",
3793
def->data.internal.name);
3799
virBufferEscapeString(buf, " <target dev='%s'/>\n",
3802
virBufferEscapeString(buf, " <model type='%s'/>\n",
3805
if (flags & VIR_DOMAIN_XML_INTERNAL_STATUS) {
3806
virBufferAddLit(buf, " <state");
3808
virBufferEscapeString(buf, " nic='%s'", def->nic_name);
3809
if (def->hostnet_name)
3810
virBufferEscapeString(buf, " hostnet='%s'", def->hostnet_name);
3811
if (virNetHasValidPciAddr(def))
3812
virBufferVSprintf(buf, " devaddr='%.4x:%.2x:%.2x'",
3813
def->pci_addr.domain,
3815
def->pci_addr.slot);
3817
virBufferVSprintf(buf, " vlan='%d'", def->vlan);
3818
virBufferAddLit(buf, "/>\n");
3821
virBufferAddLit(buf, " </interface>\n");
3828
virDomainChrDefFormat(virConnectPtr conn,
3830
virDomainChrDefPtr def,
3834
const char *type = virDomainChrTypeToString(def->type);
3837
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3838
_("unexpected char type %d"), def->type);
3842
/* Compat with legacy <console tty='/dev/pts/5'/> syntax */
3843
virBufferVSprintf(buf, " <%s type='%s'",
3845
if (STREQ(name, "console") &&
3846
def->type == VIR_DOMAIN_CHR_TYPE_PTY &&
3847
!(flags & VIR_DOMAIN_XML_INACTIVE) &&
3848
def->data.file.path) {
3849
virBufferEscapeString(buf, " tty='%s'>\n",
3850
def->data.file.path);
3852
virBufferAddLit(buf, ">\n");
3855
switch (def->type) {
3856
case VIR_DOMAIN_CHR_TYPE_NULL:
3857
case VIR_DOMAIN_CHR_TYPE_VC:
3858
case VIR_DOMAIN_CHR_TYPE_STDIO:
3862
case VIR_DOMAIN_CHR_TYPE_PTY:
3863
case VIR_DOMAIN_CHR_TYPE_DEV:
3864
case VIR_DOMAIN_CHR_TYPE_FILE:
3865
case VIR_DOMAIN_CHR_TYPE_PIPE:
3866
if (def->type != VIR_DOMAIN_CHR_TYPE_PTY ||
3867
(def->data.file.path && !(flags & VIR_DOMAIN_XML_INACTIVE))) {
3868
virBufferEscapeString(buf, " <source path='%s'/>\n",
3869
def->data.file.path);
3873
case VIR_DOMAIN_CHR_TYPE_UDP:
3874
if (def->data.udp.bindService &&
3875
def->data.udp.bindHost) {
3876
virBufferVSprintf(buf, " <source mode='bind' host='%s' service='%s'/>\n",
3877
def->data.udp.bindHost,
3878
def->data.udp.bindService);
3879
} else if (def->data.udp.bindHost) {
3880
virBufferVSprintf(buf, " <source mode='bind' host='%s'/>\n",
3881
def->data.udp.bindHost);
3882
} else if (def->data.udp.bindService) {
3883
virBufferVSprintf(buf, " <source mode='bind' service='%s'/>\n",
3884
def->data.udp.bindService);
3887
if (def->data.udp.connectService &&
3888
def->data.udp.connectHost) {
3889
virBufferVSprintf(buf, " <source mode='connect' host='%s' service='%s'/>\n",
3890
def->data.udp.connectHost,
3891
def->data.udp.connectService);
3892
} else if (def->data.udp.connectHost) {
3893
virBufferVSprintf(buf, " <source mode='connect' host='%s'/>\n",
3894
def->data.udp.connectHost);
3895
} else if (def->data.udp.connectService) {
3896
virBufferVSprintf(buf, " <source mode='connect' service='%s'/>\n",
3897
def->data.udp.connectService);
3901
case VIR_DOMAIN_CHR_TYPE_TCP:
3902
virBufferVSprintf(buf, " <source mode='%s' host='%s' service='%s'/>\n",
3903
def->data.tcp.listen ? "bind" : "connect",
3905
def->data.tcp.service);
3906
virBufferVSprintf(buf, " <protocol type='%s'/>\n",
3907
def->data.tcp.protocol ==
3908
VIR_DOMAIN_CHR_TCP_PROTOCOL_TELNET
3909
? "telnet" : "raw");
3912
case VIR_DOMAIN_CHR_TYPE_UNIX:
3913
virBufferVSprintf(buf, " <source mode='%s'",
3914
def->data.nix.listen ? "bind" : "connect");
3915
virBufferEscapeString(buf, " path='%s'/>\n",
3916
def->data.nix.path);
3920
virBufferVSprintf(buf, " <target port='%d'/>\n",
3923
virBufferVSprintf(buf, " </%s>\n",
3930
virDomainSoundDefFormat(virConnectPtr conn,
3932
virDomainSoundDefPtr def)
3934
const char *model = virDomainSoundModelTypeToString(def->model);
3937
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3938
_("unexpected sound model %d"), def->model);
3942
virBufferVSprintf(buf, " <sound model='%s'/>\n",
3950
virDomainVideoAccelDefFormat(virBufferPtr buf,
3951
virDomainVideoAccelDefPtr def)
3953
virBufferVSprintf(buf, " <acceleration accel3d='%s'",
3954
def->support3d ? "yes" : "no");
3955
virBufferVSprintf(buf, " accel2d='%s'",
3956
def->support2d ? "yes" : "no");
3957
virBufferAddLit(buf, "/>\n");
3962
virDomainVideoDefFormat(virConnectPtr conn,
3964
virDomainVideoDefPtr def)
3966
const char *model = virDomainVideoTypeToString(def->type);
3969
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
3970
_("unexpected video model %d"), def->type);
3974
virBufferAddLit(buf, " <video>\n");
3975
virBufferVSprintf(buf, " <model type='%s'",
3978
virBufferVSprintf(buf, " vram='%u'", def->vram);
3980
virBufferVSprintf(buf, " heads='%u'", def->heads);
3982
virBufferAddLit(buf, ">\n");
3983
virDomainVideoAccelDefFormat(buf, def->accel);
3984
virBufferAddLit(buf, " </model>\n");
3986
virBufferAddLit(buf, "/>\n");
3989
virBufferAddLit(buf, " </video>\n");
3995
virDomainInputDefFormat(virConnectPtr conn,
3997
virDomainInputDefPtr def)
3999
const char *type = virDomainInputTypeToString(def->type);
4000
const char *bus = virDomainInputBusTypeToString(def->bus);
4003
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
4004
_("unexpected input type %d"), def->type);
4008
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
4009
_("unexpected input bus type %d"), def->bus);
4013
virBufferVSprintf(buf, " <input type='%s' bus='%s'/>\n",
4021
virDomainGraphicsDefFormat(virConnectPtr conn,
4024
virDomainGraphicsDefPtr def,
4027
const char *type = virDomainGraphicsTypeToString(def->type);
4030
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
4031
_("unexpected net type %d"), def->type);
4035
virBufferVSprintf(buf, " <graphics type='%s'", type);
4037
switch (def->type) {
4038
case VIR_DOMAIN_GRAPHICS_TYPE_VNC:
4039
if (def->data.vnc.port &&
4040
(!def->data.vnc.autoport || vm->id != -1))
4041
virBufferVSprintf(buf, " port='%d'",
4042
def->data.vnc.port);
4043
else if (def->data.vnc.autoport)
4044
virBufferAddLit(buf, " port='-1'");
4046
virBufferVSprintf(buf, " autoport='%s'",
4047
def->data.vnc.autoport ? "yes" : "no");
4049
if (def->data.vnc.listenAddr)
4050
virBufferVSprintf(buf, " listen='%s'",
4051
def->data.vnc.listenAddr);
4053
if (def->data.vnc.keymap)
4054
virBufferEscapeString(buf, " keymap='%s'",
4055
def->data.vnc.keymap);
4057
if (def->data.vnc.passwd &&
4058
(flags & VIR_DOMAIN_XML_SECURE))
4059
virBufferEscapeString(buf, " passwd='%s'",
4060
def->data.vnc.passwd);
4064
case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
4065
if (def->data.sdl.display)
4066
virBufferEscapeString(buf, " display='%s'",
4067
def->data.sdl.display);
4069
if (def->data.sdl.xauth)
4070
virBufferEscapeString(buf, " xauth='%s'",
4071
def->data.sdl.xauth);
4072
if (def->data.sdl.fullscreen)
4073
virBufferAddLit(buf, " fullscreen='yes'");
4077
case VIR_DOMAIN_GRAPHICS_TYPE_RDP:
4078
if (def->data.rdp.port)
4079
virBufferVSprintf(buf, " port='%d'",
4080
def->data.rdp.port);
4081
else if (def->data.rdp.autoport)
4082
virBufferAddLit(buf, " port='0'");
4084
if (def->data.rdp.autoport)
4085
virBufferVSprintf(buf, " autoport='yes'");
4087
if (def->data.rdp.replaceUser)
4088
virBufferVSprintf(buf, " replaceUser='yes'");
4090
if (def->data.rdp.multiUser)
4091
virBufferVSprintf(buf, " multiUser='yes'");
4093
if (def->data.rdp.listenAddr)
4094
virBufferVSprintf(buf, " listen='%s'", def->data.rdp.listenAddr);
4098
case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
4099
if (def->data.desktop.display)
4100
virBufferEscapeString(buf, " display='%s'",
4101
def->data.desktop.display);
4103
if (def->data.desktop.fullscreen)
4104
virBufferAddLit(buf, " fullscreen='yes'");
4110
virBufferAddLit(buf, "/>\n");
4117
virDomainHostdevDefFormat(virConnectPtr conn,
4119
virDomainHostdevDefPtr def,
4122
const char *mode = virDomainHostdevModeTypeToString(def->mode);
4125
if (!mode || def->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) {
4126
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
4127
_("unexpected hostdev mode %d"), def->mode);
4131
type = virDomainHostdevSubsysTypeToString(def->source.subsys.type);
4132
if (!type || (def->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB && def->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) ) {
4133
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
4134
_("unexpected hostdev type %d"),
4135
def->source.subsys.type);
4139
virBufferVSprintf(buf, " <hostdev mode='%s' type='%s' managed='%s'>\n",
4140
mode, type, def->managed ? "yes" : "no");
4141
virBufferAddLit(buf, " <source>\n");
4143
if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
4144
if (def->source.subsys.u.usb.vendor) {
4145
virBufferVSprintf(buf, " <vendor id='0x%.4x'/>\n",
4146
def->source.subsys.u.usb.vendor);
4147
virBufferVSprintf(buf, " <product id='0x%.4x'/>\n",
4148
def->source.subsys.u.usb.product);
4150
virBufferVSprintf(buf, " <address bus='%d' device='%d'/>\n",
4151
def->source.subsys.u.usb.bus,
4152
def->source.subsys.u.usb.device);
4155
if (def->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
4156
virBufferVSprintf(buf, " <address domain='0x%.4x' bus='0x%.2x' slot='0x%.2x' function='0x%.1x'/>\n",
4157
def->source.subsys.u.pci.domain,
4158
def->source.subsys.u.pci.bus,
4159
def->source.subsys.u.pci.slot,
4160
def->source.subsys.u.pci.function);
4161
if (flags & VIR_DOMAIN_XML_INTERNAL_STATUS) {
4162
virBufferAddLit(buf, " <state");
4163
if (virHostdevHasValidGuestAddr(def))
4164
virBufferVSprintf(buf, " devaddr='%.4x:%.2x:%.2x'",
4165
def->source.subsys.u.pci.guest_addr.domain,
4166
def->source.subsys.u.pci.guest_addr.bus,
4167
def->source.subsys.u.pci.guest_addr.slot);
4168
virBufferAddLit(buf, "/>\n");
4172
virBufferAddLit(buf, " </source>\n");
4173
virBufferAddLit(buf, " </hostdev>\n");
4179
char *virDomainDefFormat(virConnectPtr conn,
4180
virDomainDefPtr def,
4183
virBuffer buf = VIR_BUFFER_INITIALIZER;
4184
unsigned char *uuid;
4185
char uuidstr[VIR_UUID_STRING_BUFLEN];
4186
const char *type = NULL, *tmp;
4189
if (!(type = virDomainVirtTypeToString(def->virtType))) {
4190
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
4191
_("unexpected domain type %d"), def->virtType);
4196
virBufferVSprintf(&buf, "<domain type='%s' id='%d'>\n", type, def->id);
4198
virBufferVSprintf(&buf, "<domain type='%s'>\n", type);
4200
virBufferEscapeString(&buf, " <name>%s</name>\n", def->name);
4203
virUUIDFormat(uuid, uuidstr);
4204
virBufferVSprintf(&buf, " <uuid>%s</uuid>\n", uuidstr);
4206
if (def->description)
4207
virBufferEscapeString(&buf, " <description>%s</description>\n",
4210
virBufferVSprintf(&buf, " <memory>%lu</memory>\n", def->maxmem);
4211
virBufferVSprintf(&buf, " <currentMemory>%lu</currentMemory>\n",
4213
if (def->hugepage_backed) {
4214
virBufferAddLit(&buf, " <memoryBacking>\n");
4215
virBufferAddLit(&buf, " <hugepages/>\n");
4216
virBufferAddLit(&buf, " </memoryBacking>\n");
4218
for (n = 0 ; n < def->cpumasklen ; n++)
4219
if (def->cpumask[n] != 1)
4223
virBufferVSprintf(&buf, " <vcpu>%lu</vcpu>\n", def->vcpus);
4225
char *cpumask = NULL;
4227
virDomainCpuSetFormat(conn, def->cpumask, def->cpumasklen)) == NULL)
4229
virBufferVSprintf(&buf, " <vcpu cpuset='%s'>%lu</vcpu>\n",
4230
cpumask, def->vcpus);
4234
if (def->os.bootloader) {
4235
virBufferEscapeString(&buf, " <bootloader>%s</bootloader>\n",
4236
def->os.bootloader);
4237
if (def->os.bootloaderArgs)
4238
virBufferEscapeString(&buf, " <bootloader_args>%s</bootloader_args>\n",
4239
def->os.bootloaderArgs);
4241
virBufferAddLit(&buf, " <os>\n");
4243
virBufferAddLit(&buf, " <type");
4245
virBufferVSprintf(&buf, " arch='%s'", def->os.arch);
4246
if (def->os.machine)
4247
virBufferVSprintf(&buf, " machine='%s'", def->os.machine);
4249
* HACK: For xen driver we previously used bogus 'linux' as the
4250
* os type for paravirt, whereas capabilities declare it to
4251
* be 'xen'. So we convert to the former for backcompat
4253
if (def->virtType == VIR_DOMAIN_VIRT_XEN &&
4254
STREQ(def->os.type, "xen"))
4255
virBufferVSprintf(&buf, ">%s</type>\n", "linux");
4257
virBufferVSprintf(&buf, ">%s</type>\n", def->os.type);
4260
virBufferEscapeString(&buf, " <init>%s</init>\n",
4263
virBufferEscapeString(&buf, " <loader>%s</loader>\n",
4266
virBufferEscapeString(&buf, " <kernel>%s</kernel>\n",
4269
virBufferEscapeString(&buf, " <initrd>%s</initrd>\n",
4271
if (def->os.cmdline)
4272
virBufferEscapeString(&buf, " <cmdline>%s</cmdline>\n",
4275
virBufferEscapeString(&buf, " <root>%s</root>\n",
4278
if (!def->os.bootloader) {
4279
for (n = 0 ; n < def->os.nBootDevs ; n++) {
4280
const char *boottype =
4281
virDomainBootTypeToString(def->os.bootDevs[n]);
4283
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
4284
_("unexpected boot device type %d"),
4285
def->os.bootDevs[n]);
4288
virBufferVSprintf(&buf, " <boot dev='%s'/>\n", boottype);
4292
virBufferAddLit(&buf, " </os>\n");
4294
if (def->features) {
4296
virBufferAddLit(&buf, " <features>\n");
4297
for (i = 0 ; i < VIR_DOMAIN_FEATURE_LAST ; i++) {
4298
if (def->features & (1 << i)) {
4299
const char *name = virDomainFeatureTypeToString(i);
4301
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
4302
_("unexpected feature %d"), i);
4305
virBufferVSprintf(&buf, " <%s/>\n", name);
4308
virBufferAddLit(&buf, " </features>\n");
4311
virBufferVSprintf(&buf, " <clock offset='%s'/>\n",
4312
def->localtime ? "localtime" : "utc");
4314
if (virDomainLifecycleDefFormat(conn, &buf, def->onPoweroff,
4317
if (virDomainLifecycleDefFormat(conn, &buf, def->onReboot,
4320
if (virDomainLifecycleDefFormat(conn, &buf, def->onCrash,
4324
virBufferAddLit(&buf, " <devices>\n");
4327
virBufferEscapeString(&buf, " <emulator>%s</emulator>\n",
4330
for (n = 0 ; n < def->ndisks ; n++)
4331
if (virDomainDiskDefFormat(conn, &buf, def->disks[n], flags) < 0)
4334
for (n = 0 ; n < def->nfss ; n++)
4335
if (virDomainFSDefFormat(conn, &buf, def->fss[n]) < 0)
4339
for (n = 0 ; n < def->nnets ; n++)
4340
if (virDomainNetDefFormat(conn, &buf, def->nets[n], flags) < 0)
4343
for (n = 0 ; n < def->nserials ; n++)
4344
if (virDomainChrDefFormat(conn, &buf, def->serials[n], "serial", flags) < 0)
4347
for (n = 0 ; n < def->nparallels ; n++)
4348
if (virDomainChrDefFormat(conn, &buf, def->parallels[n], "parallel", flags) < 0)
4351
/* If there's a PV console that's preferred.. */
4353
if (virDomainChrDefFormat(conn, &buf, def->console, "console", flags) < 0)
4355
} else if (def->nserials != 0) {
4356
/* ..else for legacy compat duplicate the first serial device as a
4358
if (virDomainChrDefFormat(conn, &buf, def->serials[0], "console", flags) < 0)
4362
for (n = 0 ; n < def->ninputs ; n++)
4363
if (def->inputs[n]->bus == VIR_DOMAIN_INPUT_BUS_USB &&
4364
virDomainInputDefFormat(conn, &buf, def->inputs[n]) < 0)
4367
if (def->ngraphics > 0) {
4368
/* If graphics is enabled, add the implicit mouse */
4369
virDomainInputDef autoInput = {
4370
VIR_DOMAIN_INPUT_TYPE_MOUSE,
4371
STREQ(def->os.type, "hvm") ?
4372
VIR_DOMAIN_INPUT_BUS_PS2 : VIR_DOMAIN_INPUT_BUS_XEN
4375
if (virDomainInputDefFormat(conn, &buf, &autoInput) < 0)
4378
for (n = 0 ; n < def->ngraphics ; n++)
4379
if (virDomainGraphicsDefFormat(conn, &buf, def, def->graphics[n], flags) < 0)
4383
for (n = 0 ; n < def->nsounds ; n++)
4384
if (virDomainSoundDefFormat(conn, &buf, def->sounds[n]) < 0)
4387
for (n = 0 ; n < def->nvideos ; n++)
4388
if (virDomainVideoDefFormat(conn, &buf, def->videos[n]) < 0)
4391
for (n = 0 ; n < def->nhostdevs ; n++)
4392
if (virDomainHostdevDefFormat(conn, &buf, def->hostdevs[n], flags) < 0)
4395
virBufferAddLit(&buf, " </devices>\n");
4397
if (def->seclabel.model) {
4398
const char *sectype = virDomainSeclabelTypeToString(def->seclabel.type);
4401
if (!def->seclabel.label ||
4402
(def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC &&
4403
(flags & VIR_DOMAIN_XML_INACTIVE))) {
4404
virBufferVSprintf(&buf, " <seclabel type='%s' model='%s'/>\n",
4405
sectype, def->seclabel.model);
4407
virBufferVSprintf(&buf, " <seclabel type='%s' model='%s'>\n",
4408
sectype, def->seclabel.model);
4409
virBufferEscapeString(&buf, " <label>%s</label>\n",
4410
def->seclabel.label);
4411
if (def->seclabel.imagelabel &&
4412
def->seclabel.type == VIR_DOMAIN_SECLABEL_DYNAMIC)
4413
virBufferEscapeString(&buf, " <imagelabel>%s</imagelabel>\n",
4414
def->seclabel.imagelabel);
4415
virBufferAddLit(&buf, " </seclabel>\n");
4419
virBufferAddLit(&buf, "</domain>\n");
4421
if (virBufferError(&buf))
4424
return virBufferContentAndReset(&buf);
4427
virReportOOMError(conn);
4429
tmp = virBufferContentAndReset(&buf);
4434
char *virDomainObjFormat(virConnectPtr conn,
4435
virDomainObjPtr obj,
4438
char *config_xml = NULL, *xml = NULL;
4439
virBuffer buf = VIR_BUFFER_INITIALIZER;
4440
const char *monitorpath;
4442
virBufferVSprintf(&buf, "<domstatus state='%s' pid='%d'>\n",
4443
virDomainStateTypeToString(obj->state),
4446
/* obj->monitor_chr is set only for qemu */
4447
if (obj->monitor_chr) {
4448
switch (obj->monitor_chr->type) {
4449
case VIR_DOMAIN_CHR_TYPE_UNIX:
4450
monitorpath = obj->monitor_chr->data.nix.path;
4453
case VIR_DOMAIN_CHR_TYPE_PTY:
4454
monitorpath = obj->monitor_chr->data.file.path;
4458
virBufferEscapeString(&buf, " <monitor path='%s'", monitorpath);
4459
virBufferVSprintf(&buf, " type='%s'/>\n",
4460
virDomainChrTypeToString(obj->monitor_chr->type));
4464
if (obj->nvcpupids) {
4466
virBufferAddLit(&buf, " <vcpus>\n");
4467
for (i = 0 ; i < obj->nvcpupids ; i++) {
4468
virBufferVSprintf(&buf, " <vcpu pid='%d'/>\n", obj->vcpupids[i]);
4470
virBufferAddLit(&buf, " </vcpus>\n");
4473
if (!(config_xml = virDomainDefFormat(conn,
4478
virBufferAdd(&buf, config_xml, strlen(config_xml));
4479
VIR_FREE(config_xml);
4480
virBufferAddLit(&buf, "</domstatus>\n");
4482
if (virBufferError(&buf))
4485
return virBufferContentAndReset(&buf);
4488
virReportOOMError(conn);
4490
xml = virBufferContentAndReset(&buf);
4498
int virDomainSaveXML(virConnectPtr conn,
4499
const char *configDir,
4500
virDomainDefPtr def,
4503
char *configFile = NULL;
4504
int fd = -1, ret = -1;
4507
if ((configFile = virDomainConfigFile(conn, configDir, def->name)) == NULL)
4510
if (virFileMakePath(configDir)) {
4511
virReportSystemError(conn, errno,
4512
_("cannot create config directory '%s'"),
4517
if ((fd = open(configFile,
4518
O_WRONLY | O_CREAT | O_TRUNC,
4519
S_IRUSR | S_IWUSR )) < 0) {
4520
virReportSystemError(conn, errno,
4521
_("cannot create config file '%s'"),
4526
towrite = strlen(xml);
4527
if (safewrite(fd, xml, towrite) < 0) {
4528
virReportSystemError(conn, errno,
4529
_("cannot write config file '%s'"),
4534
if (close(fd) < 0) {
4535
virReportSystemError(conn, errno,
4536
_("cannot save config file '%s'"),
4545
VIR_FREE(configFile);
4549
int virDomainSaveConfig(virConnectPtr conn,
4550
const char *configDir,
4551
virDomainDefPtr def)
4556
if (!(xml = virDomainDefFormat(conn,
4558
VIR_DOMAIN_XML_SECURE)))
4561
if (virDomainSaveXML(conn, configDir, def, xml))
4570
int virDomainSaveStatus(virConnectPtr conn,
4571
const char *statusDir,
4572
virDomainObjPtr obj)
4574
int flags = VIR_DOMAIN_XML_SECURE|VIR_DOMAIN_XML_INTERNAL_STATUS;
4578
if (!(xml = virDomainObjFormat(conn, obj, flags)))
4581
if (virDomainSaveXML(conn, statusDir, obj->def, xml))
4591
virDomainObjPtr virDomainLoadConfig(virConnectPtr conn,
4593
virDomainObjListPtr doms,
4594
const char *configDir,
4595
const char *autostartDir,
4597
virDomainLoadConfigNotify notify,
4600
char *configFile = NULL, *autostartLink = NULL;
4601
virDomainDefPtr def = NULL;
4602
virDomainObjPtr dom;
4606
if ((configFile = virDomainConfigFile(conn, configDir, name)) == NULL)
4608
if ((autostartLink = virDomainConfigFile(conn, autostartDir, name)) == NULL)
4611
if ((autostart = virFileLinkPointsTo(autostartLink, configFile)) < 0)
4614
if (!(def = virDomainDefParseFile(conn, caps, configFile,
4615
VIR_DOMAIN_XML_INACTIVE)))
4618
if ((dom = virDomainFindByName(doms, def->name))) {
4619
virDomainObjUnlock(dom);
4624
if (!(dom = virDomainAssignDef(conn, doms, def)))
4627
dom->autostart = autostart;
4630
(*notify)(dom, newVM, opaque);
4632
VIR_FREE(configFile);
4633
VIR_FREE(autostartLink);
4637
VIR_FREE(configFile);
4638
VIR_FREE(autostartLink);
4639
virDomainDefFree(def);
4643
static virDomainObjPtr virDomainLoadStatus(virConnectPtr conn,
4645
virDomainObjListPtr doms,
4646
const char *statusDir,
4648
virDomainLoadConfigNotify notify,
4651
char *statusFile = NULL;
4652
virDomainObjPtr obj = NULL;
4653
virDomainObjPtr tmp = NULL;
4655
if ((statusFile = virDomainConfigFile(conn, statusDir, name)) == NULL)
4658
if (!(obj = virDomainObjParseFile(conn, caps, statusFile)))
4661
tmp = virDomainFindByName(doms, obj->def->name);
4663
virDomainObjUnlock(obj);
4664
virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
4665
_("unexpected domain %s already exists"),
4670
if (VIR_REALLOC_N(doms->objs, doms->count + 1) < 0) {
4671
virReportOOMError(conn);
4675
doms->objs[doms->count] = obj;
4679
(*notify)(obj, 1, opaque);
4681
VIR_FREE(statusFile);
4685
virDomainObjFree(obj);
4686
VIR_FREE(statusFile);
4690
int virDomainLoadAllConfigs(virConnectPtr conn,
4692
virDomainObjListPtr doms,
4693
const char *configDir,
4694
const char *autostartDir,
4696
virDomainLoadConfigNotify notify,
4700
struct dirent *entry;
4702
VIR_INFO("Scanning for configs in %s", configDir);
4704
if (!(dir = opendir(configDir))) {
4705
if (errno == ENOENT)
4707
virReportSystemError(conn, errno,
4708
_("Failed to open dir '%s'"),
4713
while ((entry = readdir(dir))) {
4714
virDomainObjPtr dom;
4716
if (entry->d_name[0] == '.')
4719
if (!virFileStripSuffix(entry->d_name, ".xml"))
4722
/* NB: ignoring errors, so one malformed config doesn't
4723
kill the whole process */
4724
VIR_INFO("Loading config file '%s.xml'", entry->d_name);
4726
dom = virDomainLoadStatus(conn,
4734
dom = virDomainLoadConfig(conn,
4743
virDomainObjUnlock(dom);
4745
dom->persistent = 1;
4754
int virDomainDeleteConfig(virConnectPtr conn,
4755
const char *configDir,
4756
const char *autostartDir,
4757
virDomainObjPtr dom)
4759
char *configFile = NULL, *autostartLink = NULL;
4762
if ((configFile = virDomainConfigFile(conn, configDir, dom->def->name)) == NULL)
4764
if ((autostartLink = virDomainConfigFile(conn, autostartDir, dom->def->name)) == NULL)
4767
/* Not fatal if this doesn't work */
4768
unlink(autostartLink);
4770
if (unlink(configFile) < 0 &&
4772
virReportSystemError(conn, errno,
4773
_("cannot remove config %s"),
4781
VIR_FREE(configFile);
4782
VIR_FREE(autostartLink);
4786
char *virDomainConfigFile(virConnectPtr conn,
4792
if (virAsprintf(&ret, "%s/%s.xml", dir, name) < 0) {
4793
virReportOOMError(conn);
4800
/* Translates a device name of the form (regex) "[fhv]d[a-z]+" into
4801
* the corresponding bus,index combination (e.g. sda => (0,0), sdi (1,1),
4802
* hdd => (1,1), vdaa => (0,26))
4803
* @param disk The disk device
4804
* @param busIdx parsed bus number
4805
* @param devIdx parsed device number
4806
* @return 0 on success, -1 on failure
4808
int virDiskNameToBusDeviceIndex(const virDomainDiskDefPtr disk,
4812
int idx = virDiskNameToIndex(disk->dst);
4816
switch (disk->bus) {
4817
case VIR_DOMAIN_DISK_BUS_IDE:
4821
case VIR_DOMAIN_DISK_BUS_SCSI:
4825
case VIR_DOMAIN_DISK_BUS_FDC:
4826
case VIR_DOMAIN_DISK_BUS_USB:
4827
case VIR_DOMAIN_DISK_BUS_VIRTIO:
4828
case VIR_DOMAIN_DISK_BUS_XEN:
4838
virDomainFSDefPtr virDomainGetRootFilesystem(virDomainDefPtr def)
4842
for (i = 0 ; i < def->nfss ; i++) {
4843
if (def->fss[i]->type != VIR_DOMAIN_FS_TYPE_MOUNT)
4846
if (STREQ(def->fss[i]->dst, "/"))
4854
void virDomainObjLock(virDomainObjPtr obj)
4856
virMutexLock(&obj->lock);
4859
void virDomainObjUnlock(virDomainObjPtr obj)
4861
virMutexUnlock(&obj->lock);
4864
#endif /* ! PROXY */