~serge-hallyn/ubuntu/raring/libvirt/libvirt-hugepages

« back to all changes in this revision

Viewing changes to src/conf/domain_conf.c

  • Committer: James Westby
  • Author(s): Jamie Strandboge
  • Date: 2009-12-02 14:22:21 UTC
  • mfrom: (1.2.3 upstream) (3.4.9 squeeze)
  • Revision ID: james.westby@canonical.com-20091202142221-ltkr0to6h52mla1y
Tags: 0.7.2-4ubuntu1
* Merge from debian testing. Remaining changes:
  - debian/control:
    + Don't build-depend on QEmu
    + Bump bridge-utils, dnsmasq-base, netcat-openbsd, and iptables
      to Depends of libvirt-bin
    + Recommends qemu-kvm (>= 0.11.0-0ubuntu6)
    + Add versioned Conflicts/Replaces to libvirt0 for libvirt0-dbg,
      since we used to ship them as such
    + We call libxen-dev libxen3-dev, so change all references
    + Build-Depends on libxml2-utils
    + Build-Depends on open-iscsi-utils instead of open-iscsi due to
      LP: #414986
  - debian/postinst:
    + rename the libvirt group to libvirtd
    + add each admin user to the libvirtd group
  - debian/libvirt-bin.postrm: rename the libvirt group to libvirtd
  - debian/rules: add DEB_MAKE_CHECK_TARGET := check
  - debian/patches/900[0-7]: updated/refreshed for new paths in 0.7.2
  - debian/patches/series: don't apply 0002-qemu-disable-network.diff.patch
  - AppArmor integration:
    + debian/control: Build-Depends on libapparmor-dev and Suggests
      apparmor (>= 2.3+1289-0ubuntu14)
    + debian/libvirt-bin.dirs: add /etc/apparmor.d/abstractions,
      /etc/apparmor.d/force-complain, /etc/apparmor.d/libvirt,
      /etc/cron.daily and /usr/share/apport/package-hooks
    + add debian/libvirt-bin.cron.daily (LP: #438165)
    + add debian/libvirt-bin.apport
    + debian/libvirt-bin.install: install apparmor profiles, abstractions
      and apport hook
    + debian/postinst: reload apparmor profiles
    + debian/libvirt-bin.postrm: remove apparmor symlinks on purge
    + debian/libvirt-bin.preinst: added to force complain on certain
      upgrades
    + debian/README.Debian: add AppArmor section based on the upstream
      documentation
    + debian/rules: use --with-apparmor and copy apparmor and apport hook to
      debian/tmp
  - Dropped the following patches now included upstream:
    + 0005-Close-logfile-fd-after-spawning-qemu.patch
    + 9090-reenable-nonfile-labels.patch
    + 9091-apparmor.patch
    + 9092-apparmor-autoreconf.patch
* AppArmor integration updates:
  - debian/apparmor/usr.sbin.libvirtd: allow libvirtd access to
    /usr/lib/libvirt/* (LP: #480478)
  - debian/apparmor/libvirt-qemu: allow guests access to
    /etc/pki/libvirt-vnc/** (LP: #484562)
  - debian/libvirt-bin.postinst: 0.7.2 moved /usr/bin/virt-aa-helper to
    /usr/lib/libvirt, so the profile changed from usr.bin.virt-aa-helper
    to usr.lib.libvirt.virt-aa-helper and needs to be migrated. If the user
    made no changes to the old profile, remove it, otherwise, update the
    paths, preserving the shipped usr.lib.libvirt.virt-aa-helper
  - update to 0.7.4 version of the sVirt AppArmor driver (can be dropped in
    0.7.4):
    + debian/patches/9008-apparmor-caps-mockup.patch
    + debian/patches/9009-apparmor-lp453335.patch
    + debian/patches/9010-apparmor-lp460271.patch
    + debian/patches/9011-apparmor-code-cleanups.patch
  - add virt-aa-helper-test and examples/apparmor that were omitted from the
    upstream tarball (can be dropped in 0.7.5):
    + debian/patches/9012-apparmor-add-virt-aa-helper-test.patch
    + debian/patches/9013-apparmor-examples.patch
    + debian/rules: add post-patches target to make virt-aa-helper-test
      executable
* debian/patches/0005-Fix-SELinux-linking-issues.patch: updated to work
  when both apparmor and selinux are available. This patch should be
  dropped in 0.7.4.
* debian/patches/9007-default-config-test-case.patch: updated to not fail
  if building in a deep directory
* debian/patches/9014-event-fuzz.patch: add a little fuzz to not be quite
  so precise with expected expiry time. Fixes FTBFS with HZ=100 kernels.
  Can be dropped in 0.7.5.
* debian/patches/9015-hal-startup-failure-is-nonfatal.patch: disable hal
  driver if hald is not running instead of dying. Can be dropped in
  0.7.4.
* debian/control: temporarily remove Build-Depends on libcap-ng-dev, which
  isn't available in Ubuntu main yet
* revert change to new source format 3.0 (quilt) since Launchpad can't
  handle it yet (see LP: #293106)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * domain_conf.c: domain XML processing
 
3
 *
 
4
 * Copyright (C) 2006-2009 Red Hat, Inc.
 
5
 * Copyright (C) 2006-2008 Daniel P. Berrange
 
6
 *
 
7
 * This library is free software; you can redistribute it and/or
 
8
 * modify it under the terms of the GNU Lesser General Public
 
9
 * License as published by the Free Software Foundation; either
 
10
 * version 2.1 of the License, or (at your option) any later version.
 
11
 *
 
12
 * This library is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
15
 * Lesser General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU Lesser General Public
 
18
 * License along with this library; if not, write to the Free Software
 
19
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
 
20
 *
 
21
 * Author: Daniel P. Berrange <berrange@redhat.com>
 
22
 */
 
23
 
 
24
#include <config.h>
 
25
 
 
26
#include <sys/types.h>
 
27
#include <sys/stat.h>
 
28
#include <unistd.h>
 
29
#include <fcntl.h>
 
30
#include <dirent.h>
 
31
 
 
32
#include "virterror_internal.h"
 
33
#include "datatypes.h"
 
34
#include "domain_conf.h"
 
35
#include "memory.h"
 
36
#include "verify.h"
 
37
#include "xml.h"
 
38
#include "uuid.h"
 
39
#include "util.h"
 
40
#include "buf.h"
 
41
#include "c-ctype.h"
 
42
#include "logging.h"
 
43
 
 
44
#define VIR_FROM_THIS VIR_FROM_DOMAIN
 
45
 
 
46
VIR_ENUM_IMPL(virDomainVirt, VIR_DOMAIN_VIRT_LAST,
 
47
              "qemu",
 
48
              "kqemu",
 
49
              "kvm",
 
50
              "xen",
 
51
              "lxc",
 
52
              "uml",
 
53
              "openvz",
 
54
              "vserver",
 
55
              "ldom",
 
56
              "test",
 
57
              "vmware",
 
58
              "hyperv",
 
59
              "vbox",
 
60
              "one",
 
61
              "phyp")
 
62
 
 
63
VIR_ENUM_IMPL(virDomainBoot, VIR_DOMAIN_BOOT_LAST,
 
64
              "fd",
 
65
              "cdrom",
 
66
              "hd",
 
67
              "network")
 
68
 
 
69
VIR_ENUM_IMPL(virDomainFeature, VIR_DOMAIN_FEATURE_LAST,
 
70
              "acpi",
 
71
              "apic",
 
72
              "pae")
 
73
 
 
74
VIR_ENUM_IMPL(virDomainLifecycle, VIR_DOMAIN_LIFECYCLE_LAST,
 
75
              "destroy",
 
76
              "restart",
 
77
              "rename-restart",
 
78
              "preserve")
 
79
 
 
80
VIR_ENUM_IMPL(virDomainDevice, VIR_DOMAIN_DEVICE_LAST,
 
81
              "disk",
 
82
              "filesystem",
 
83
              "interface",
 
84
              "input",
 
85
              "sound",
 
86
              "video",
 
87
              "hostdev")
 
88
 
 
89
VIR_ENUM_IMPL(virDomainDisk, VIR_DOMAIN_DISK_TYPE_LAST,
 
90
              "block",
 
91
              "file")
 
92
 
 
93
VIR_ENUM_IMPL(virDomainDiskDevice, VIR_DOMAIN_DISK_DEVICE_LAST,
 
94
              "disk",
 
95
              "cdrom",
 
96
              "floppy")
 
97
 
 
98
VIR_ENUM_IMPL(virDomainDiskBus, VIR_DOMAIN_DISK_BUS_LAST,
 
99
              "ide",
 
100
              "fdc",
 
101
              "scsi",
 
102
              "virtio",
 
103
              "xen",
 
104
              "usb",
 
105
              "uml")
 
106
 
 
107
VIR_ENUM_IMPL(virDomainDiskCache, VIR_DOMAIN_DISK_CACHE_LAST,
 
108
              "default",
 
109
              "none",
 
110
              "writethrough",
 
111
              "writeback")
 
112
 
 
113
VIR_ENUM_IMPL(virDomainFS, VIR_DOMAIN_FS_TYPE_LAST,
 
114
              "mount",
 
115
              "block",
 
116
              "file",
 
117
              "template")
 
118
 
 
119
VIR_ENUM_IMPL(virDomainNet, VIR_DOMAIN_NET_TYPE_LAST,
 
120
              "user",
 
121
              "ethernet",
 
122
              "server",
 
123
              "client",
 
124
              "mcast",
 
125
              "network",
 
126
              "bridge",
 
127
              "internal")
 
128
 
 
129
VIR_ENUM_IMPL(virDomainChr, VIR_DOMAIN_CHR_TYPE_LAST,
 
130
              "null",
 
131
              "vc",
 
132
              "pty",
 
133
              "dev",
 
134
              "file",
 
135
              "pipe",
 
136
              "stdio",
 
137
              "udp",
 
138
              "tcp",
 
139
              "unix")
 
140
 
 
141
VIR_ENUM_IMPL(virDomainSoundModel, VIR_DOMAIN_SOUND_MODEL_LAST,
 
142
              "sb16",
 
143
              "es1370",
 
144
              "pcspk",
 
145
              "ac97")
 
146
 
 
147
VIR_ENUM_IMPL(virDomainVideo, VIR_DOMAIN_VIDEO_TYPE_LAST,
 
148
              "vga",
 
149
              "cirrus",
 
150
              "vmvga",
 
151
              "xen",
 
152
              "vbox")
 
153
 
 
154
VIR_ENUM_IMPL(virDomainInput, VIR_DOMAIN_INPUT_TYPE_LAST,
 
155
              "mouse",
 
156
              "tablet")
 
157
 
 
158
VIR_ENUM_IMPL(virDomainInputBus, VIR_DOMAIN_INPUT_BUS_LAST,
 
159
              "ps2",
 
160
              "usb",
 
161
              "xen")
 
162
 
 
163
VIR_ENUM_IMPL(virDomainGraphics, VIR_DOMAIN_GRAPHICS_TYPE_LAST,
 
164
              "sdl",
 
165
              "vnc",
 
166
              "rdp",
 
167
              "desktop")
 
168
 
 
169
VIR_ENUM_IMPL(virDomainHostdevMode, VIR_DOMAIN_HOSTDEV_MODE_LAST,
 
170
              "subsystem",
 
171
              "capabilities")
 
172
 
 
173
VIR_ENUM_IMPL(virDomainHostdevSubsys, VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST,
 
174
              "usb",
 
175
              "pci")
 
176
 
 
177
VIR_ENUM_IMPL(virDomainState, VIR_DOMAIN_CRASHED+1,
 
178
              "nostate",
 
179
              "running",
 
180
              "blocked",
 
181
              "paused",
 
182
              "shutdown",
 
183
              "shutoff",
 
184
              "crashed")
 
185
 
 
186
VIR_ENUM_IMPL(virDomainSeclabel, VIR_DOMAIN_SECLABEL_LAST,
 
187
              "dynamic",
 
188
              "static")
 
189
 
 
190
#define virDomainReportError(conn, code, fmt...)                           \
 
191
        virReportErrorHelper(conn, VIR_FROM_DOMAIN, code, __FILE__,        \
 
192
                               __FUNCTION__, __LINE__, fmt)
 
193
 
 
194
#ifndef PROXY
 
195
 
 
196
virDomainObjPtr virDomainFindByID(const virDomainObjListPtr doms,
 
197
                                  int id)
 
198
{
 
199
    unsigned int i;
 
200
 
 
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]);
 
207
    }
 
208
 
 
209
    return NULL;
 
210
}
 
211
 
 
212
 
 
213
virDomainObjPtr virDomainFindByUUID(const virDomainObjListPtr doms,
 
214
                                    const unsigned char *uuid)
 
215
{
 
216
    unsigned int i;
 
217
 
 
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]);
 
223
    }
 
224
 
 
225
    return NULL;
 
226
}
 
227
 
 
228
virDomainObjPtr virDomainFindByName(const virDomainObjListPtr doms,
 
229
                                    const char *name)
 
230
{
 
231
    unsigned int i;
 
232
 
 
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]);
 
238
    }
 
239
 
 
240
    return NULL;
 
241
}
 
242
 
 
243
#endif /* !PROXY */
 
244
 
 
245
void virDomainGraphicsDefFree(virDomainGraphicsDefPtr def)
 
246
{
 
247
    if (!def)
 
248
        return;
 
249
 
 
250
    switch (def->type) {
 
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);
 
255
        break;
 
256
 
 
257
    case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
 
258
        VIR_FREE(def->data.sdl.display);
 
259
        VIR_FREE(def->data.sdl.xauth);
 
260
        break;
 
261
 
 
262
    case VIR_DOMAIN_GRAPHICS_TYPE_RDP:
 
263
        VIR_FREE(def->data.rdp.listenAddr);
 
264
        break;
 
265
 
 
266
    case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
 
267
        VIR_FREE(def->data.desktop.display);
 
268
        break;
 
269
    }
 
270
 
 
271
    VIR_FREE(def);
 
272
}
 
273
 
 
274
void virDomainInputDefFree(virDomainInputDefPtr def)
 
275
{
 
276
    if (!def)
 
277
        return;
 
278
 
 
279
    VIR_FREE(def);
 
280
}
 
281
 
 
282
void virDomainDiskDefFree(virDomainDiskDefPtr def)
 
283
{
 
284
    if (!def)
 
285
        return;
 
286
 
 
287
    VIR_FREE(def->serial);
 
288
    VIR_FREE(def->src);
 
289
    VIR_FREE(def->dst);
 
290
    VIR_FREE(def->driverName);
 
291
    VIR_FREE(def->driverType);
 
292
    virStorageEncryptionFree(def->encryption);
 
293
 
 
294
    VIR_FREE(def);
 
295
}
 
296
 
 
297
void virDomainFSDefFree(virDomainFSDefPtr def)
 
298
{
 
299
    if (!def)
 
300
        return;
 
301
 
 
302
    VIR_FREE(def->src);
 
303
    VIR_FREE(def->dst);
 
304
 
 
305
    VIR_FREE(def);
 
306
}
 
307
 
 
308
void virDomainNetDefFree(virDomainNetDefPtr def)
 
309
{
 
310
    if (!def)
 
311
        return;
 
312
 
 
313
    VIR_FREE(def->model);
 
314
 
 
315
    switch (def->type) {
 
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);
 
320
        break;
 
321
 
 
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);
 
326
        break;
 
327
 
 
328
    case VIR_DOMAIN_NET_TYPE_NETWORK:
 
329
        VIR_FREE(def->data.network.name);
 
330
        break;
 
331
 
 
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);
 
336
        break;
 
337
 
 
338
    case VIR_DOMAIN_NET_TYPE_INTERNAL:
 
339
        VIR_FREE(def->data.internal.name);
 
340
        break;
 
341
    }
 
342
 
 
343
    VIR_FREE(def->ifname);
 
344
    VIR_FREE(def->nic_name);
 
345
    VIR_FREE(def->hostnet_name);
 
346
    VIR_FREE(def);
 
347
}
 
348
 
 
349
void virDomainChrDefFree(virDomainChrDefPtr def)
 
350
{
 
351
    if (!def)
 
352
        return;
 
353
 
 
354
    switch (def->type) {
 
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);
 
360
        break;
 
361
 
 
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);
 
367
        break;
 
368
 
 
369
    case VIR_DOMAIN_CHR_TYPE_TCP:
 
370
        VIR_FREE(def->data.tcp.host);
 
371
        VIR_FREE(def->data.tcp.service);
 
372
        break;
 
373
 
 
374
    case VIR_DOMAIN_CHR_TYPE_UNIX:
 
375
        VIR_FREE(def->data.nix.path);
 
376
        break;
 
377
    }
 
378
 
 
379
    VIR_FREE(def);
 
380
}
 
381
 
 
382
void virDomainSoundDefFree(virDomainSoundDefPtr def)
 
383
{
 
384
    if (!def)
 
385
        return;
 
386
 
 
387
    VIR_FREE(def);
 
388
}
 
389
 
 
390
void virDomainVideoDefFree(virDomainVideoDefPtr def)
 
391
{
 
392
    if (!def)
 
393
        return;
 
394
 
 
395
    VIR_FREE(def->accel);
 
396
    VIR_FREE(def);
 
397
}
 
398
 
 
399
void virDomainHostdevDefFree(virDomainHostdevDefPtr def)
 
400
{
 
401
    if (!def)
 
402
        return;
 
403
 
 
404
    VIR_FREE(def->target);
 
405
    VIR_FREE(def);
 
406
}
 
407
 
 
408
void virDomainDeviceDefFree(virDomainDeviceDefPtr def)
 
409
{
 
410
    if (!def)
 
411
        return;
 
412
 
 
413
    switch (def->type) {
 
414
    case VIR_DOMAIN_DEVICE_DISK:
 
415
        virDomainDiskDefFree(def->data.disk);
 
416
        break;
 
417
    case VIR_DOMAIN_DEVICE_NET:
 
418
        virDomainNetDefFree(def->data.net);
 
419
        break;
 
420
    case VIR_DOMAIN_DEVICE_INPUT:
 
421
        virDomainInputDefFree(def->data.input);
 
422
        break;
 
423
    case VIR_DOMAIN_DEVICE_SOUND:
 
424
        virDomainSoundDefFree(def->data.sound);
 
425
        break;
 
426
    case VIR_DOMAIN_DEVICE_VIDEO:
 
427
        virDomainVideoDefFree(def->data.video);
 
428
        break;
 
429
    case VIR_DOMAIN_DEVICE_HOSTDEV:
 
430
        virDomainHostdevDefFree(def->data.hostdev);
 
431
        break;
 
432
    }
 
433
 
 
434
    VIR_FREE(def);
 
435
}
 
436
 
 
437
void virSecurityLabelDefFree(virDomainDefPtr def);
 
438
 
 
439
void virSecurityLabelDefFree(virDomainDefPtr def)
 
440
{
 
441
    VIR_FREE(def->seclabel.model);
 
442
    VIR_FREE(def->seclabel.label);
 
443
    VIR_FREE(def->seclabel.imagelabel);
 
444
}
 
445
 
 
446
void virDomainDefFree(virDomainDefPtr def)
 
447
{
 
448
    unsigned int i;
 
449
 
 
450
    if (!def)
 
451
        return;
 
452
 
 
453
    for (i = 0 ; i < def->ngraphics ; i++)
 
454
        virDomainGraphicsDefFree(def->graphics[i]);
 
455
    VIR_FREE(def->graphics);
 
456
 
 
457
    for (i = 0 ; i < def->ninputs ; i++)
 
458
        virDomainInputDefFree(def->inputs[i]);
 
459
    VIR_FREE(def->inputs);
 
460
 
 
461
    for (i = 0 ; i < def->ndisks ; i++)
 
462
        virDomainDiskDefFree(def->disks[i]);
 
463
    VIR_FREE(def->disks);
 
464
 
 
465
    for (i = 0 ; i < def->nfss ; i++)
 
466
        virDomainFSDefFree(def->fss[i]);
 
467
    VIR_FREE(def->fss);
 
468
 
 
469
    for (i = 0 ; i < def->nnets ; i++)
 
470
        virDomainNetDefFree(def->nets[i]);
 
471
    VIR_FREE(def->nets);
 
472
    for (i = 0 ; i < def->nserials ; i++)
 
473
        virDomainChrDefFree(def->serials[i]);
 
474
    VIR_FREE(def->serials);
 
475
 
 
476
    for (i = 0 ; i < def->nparallels ; i++)
 
477
        virDomainChrDefFree(def->parallels[i]);
 
478
    VIR_FREE(def->parallels);
 
479
 
 
480
    virDomainChrDefFree(def->console);
 
481
 
 
482
    for (i = 0 ; i < def->nsounds ; i++)
 
483
        virDomainSoundDefFree(def->sounds[i]);
 
484
    VIR_FREE(def->sounds);
 
485
 
 
486
    for (i = 0 ; i < def->nvideos ; i++)
 
487
        virDomainVideoDefFree(def->videos[i]);
 
488
    VIR_FREE(def->videos);
 
489
 
 
490
    for (i = 0 ; i < def->nhostdevs ; i++)
 
491
        virDomainHostdevDefFree(def->hostdevs[i]);
 
492
    VIR_FREE(def->hostdevs);
 
493
 
 
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);
 
505
 
 
506
    VIR_FREE(def->name);
 
507
    VIR_FREE(def->cpumask);
 
508
    VIR_FREE(def->emulator);
 
509
    VIR_FREE(def->description);
 
510
 
 
511
    virSecurityLabelDefFree(def);
 
512
 
 
513
    VIR_FREE(def);
 
514
}
 
515
 
 
516
#ifndef PROXY
 
517
 
 
518
void virDomainObjFree(virDomainObjPtr dom)
 
519
{
 
520
    if (!dom)
 
521
        return;
 
522
 
 
523
    virDomainDefFree(dom->def);
 
524
    virDomainDefFree(dom->newDef);
 
525
 
 
526
    virDomainChrDefFree(dom->monitor_chr);
 
527
 
 
528
    VIR_FREE(dom->vcpupids);
 
529
 
 
530
    virMutexDestroy(&dom->lock);
 
531
 
 
532
    VIR_FREE(dom);
 
533
}
 
534
 
 
535
void virDomainObjListFree(virDomainObjListPtr vms)
 
536
{
 
537
    unsigned int i;
 
538
 
 
539
    if (!vms)
 
540
        return;
 
541
 
 
542
    for (i = 0 ; i < vms->count ; i++)
 
543
        virDomainObjFree(vms->objs[i]);
 
544
 
 
545
    VIR_FREE(vms->objs);
 
546
    vms->count = 0;
 
547
}
 
548
 
 
549
 
 
550
static virDomainObjPtr virDomainObjNew(virConnectPtr conn)
 
551
{
 
552
    virDomainObjPtr domain;
 
553
 
 
554
    if (VIR_ALLOC(domain) < 0) {
 
555
        virReportOOMError(conn);
 
556
        return NULL;
 
557
    }
 
558
 
 
559
    if (virMutexInit(&domain->lock) < 0) {
 
560
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
561
                             "%s", _("cannot initialize mutex"));
 
562
        VIR_FREE(domain);
 
563
        return NULL;
 
564
    }
 
565
 
 
566
    virDomainObjLock(domain);
 
567
    domain->state = VIR_DOMAIN_SHUTOFF;
 
568
    domain->monitorWatch = -1;
 
569
    domain->monitor = -1;
 
570
 
 
571
    return domain;
 
572
}
 
573
 
 
574
virDomainObjPtr virDomainAssignDef(virConnectPtr conn,
 
575
                                   virDomainObjListPtr doms,
 
576
                                   const virDomainDefPtr def)
 
577
{
 
578
    virDomainObjPtr domain;
 
579
 
 
580
    if ((domain = virDomainFindByUUID(doms, def->uuid))) {
 
581
        if (!virDomainIsActive(domain)) {
 
582
            virDomainDefFree(domain->def);
 
583
            domain->def = def;
 
584
        } else {
 
585
            if (domain->newDef)
 
586
                virDomainDefFree(domain->newDef);
 
587
            domain->newDef = def;
 
588
        }
 
589
 
 
590
        return domain;
 
591
    }
 
592
 
 
593
    if (VIR_REALLOC_N(doms->objs, doms->count + 1) < 0) {
 
594
        virReportOOMError(conn);
 
595
        return NULL;
 
596
    }
 
597
 
 
598
    if (!(domain = virDomainObjNew(conn)))
 
599
        return NULL;
 
600
 
 
601
    domain->def = def;
 
602
 
 
603
    doms->objs[doms->count] = domain;
 
604
    doms->count++;
 
605
 
 
606
    return domain;
 
607
}
 
608
 
 
609
void virDomainRemoveInactive(virDomainObjListPtr doms,
 
610
                             virDomainObjPtr dom)
 
611
{
 
612
    unsigned int i;
 
613
 
 
614
    virDomainObjUnlock(dom);
 
615
 
 
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]);
 
621
 
 
622
            if (i < (doms->count - 1))
 
623
                memmove(doms->objs + i, doms->objs + i + 1,
 
624
                        sizeof(*(doms->objs)) * (doms->count - (i + 1)));
 
625
 
 
626
            if (VIR_REALLOC_N(doms->objs, doms->count - 1) < 0) {
 
627
                ; /* Failure to reduce memory allocation isn't fatal */
 
628
            }
 
629
            doms->count--;
 
630
 
 
631
            break;
 
632
        }
 
633
        virDomainObjUnlock(doms->objs[i]);
 
634
    }
 
635
 
 
636
}
 
637
 
 
638
 
 
639
/* Parse the XML definition for a disk
 
640
 * @param node XML nodeset to parse for disk definition
 
641
 */
 
642
static virDomainDiskDefPtr
 
643
virDomainDiskDefParseXML(virConnectPtr conn,
 
644
                         xmlNodePtr node,
 
645
                         int flags) {
 
646
    virDomainDiskDefPtr def;
 
647
    xmlNodePtr cur;
 
648
    char *type = NULL;
 
649
    char *device = NULL;
 
650
    char *driverName = NULL;
 
651
    char *driverType = NULL;
 
652
    char *source = NULL;
 
653
    char *target = NULL;
 
654
    char *bus = NULL;
 
655
    char *cachetag = NULL;
 
656
    char *devaddr = NULL;
 
657
    virStorageEncryptionPtr encryption = NULL;
 
658
    char *serial = NULL;
 
659
 
 
660
    if (VIR_ALLOC(def) < 0) {
 
661
        virReportOOMError(conn);
 
662
        return NULL;
 
663
    }
 
664
 
 
665
    type = virXMLPropString(node, "type");
 
666
    if (type) {
 
667
        if ((def->type = virDomainDiskTypeFromString(type)) < 0) {
 
668
            virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
669
                                 _("unknown disk type '%s'"), type);
 
670
            goto error;
 
671
        }
 
672
    } else {
 
673
        def->type = VIR_DOMAIN_DISK_TYPE_FILE;
 
674
    }
 
675
 
 
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"))) {
 
681
 
 
682
                if (def->type == VIR_DOMAIN_DISK_TYPE_FILE)
 
683
                    source = virXMLPropString(cur, "file");
 
684
                else
 
685
                    source = virXMLPropString(cur, "dev");
 
686
 
 
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
 
691
                   those broken apps */
 
692
                if (source && STREQ(source, ""))
 
693
                    VIR_FREE(source);
 
694
            } else if ((target == NULL) &&
 
695
                       (xmlStrEqual(cur->name, BAD_CAST "target"))) {
 
696
                target = virXMLPropString(cur, "dev");
 
697
                bus = virXMLPropString(cur, "bus");
 
698
 
 
699
                /* HACK: Work around for compat with Xen
 
700
                 * driver in previous libvirt releases */
 
701
                if (target &&
 
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")) {
 
710
                def->readonly = 1;
 
711
            } else if (xmlStrEqual(cur->name, BAD_CAST "shareable")) {
 
712
                def->shared = 1;
 
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,
 
719
                                                           cur);
 
720
                if (encryption == NULL)
 
721
                    goto error;
 
722
            } else if ((serial == NULL) &&
 
723
                       (xmlStrEqual(cur->name, BAD_CAST "serial"))) {
 
724
                serial = (char *)xmlNodeGetContent(cur);
 
725
            }
 
726
        }
 
727
        cur = cur->next;
 
728
    }
 
729
 
 
730
    device = virXMLPropString(node, "device");
 
731
    if (device) {
 
732
        if ((def->device = virDomainDiskDeviceTypeFromString(device)) < 0) {
 
733
            virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
734
                                 _("unknown disk device '%s'"), device);
 
735
            goto error;
 
736
        }
 
737
    } else {
 
738
        def->device = VIR_DOMAIN_DISK_DEVICE_DISK;
 
739
    }
 
740
 
 
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);
 
748
        goto error;
 
749
    }
 
750
 
 
751
    if (target == NULL) {
 
752
        virDomainReportError(conn, VIR_ERR_NO_TARGET,
 
753
                             source ? "%s" : NULL, source);
 
754
        goto error;
 
755
    }
 
756
 
 
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);
 
761
        goto error;
 
762
    }
 
763
 
 
764
    /* Force CDROM to be listed as read only */
 
765
    if (def->device == VIR_DOMAIN_DISK_DEVICE_CDROM)
 
766
        def->readonly = 1;
 
767
 
 
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);
 
776
        goto error;
 
777
    }
 
778
 
 
779
    if (bus) {
 
780
        if ((def->bus = virDomainDiskBusTypeFromString(bus)) < 0) {
 
781
            virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
782
                                 _("unknown disk bus type '%s'"), bus);
 
783
            goto error;
 
784
        }
 
785
    } else {
 
786
        if (def->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY) {
 
787
            def->bus = VIR_DOMAIN_DISK_BUS_FDC;
 
788
        } else {
 
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;
 
799
            else
 
800
                def->bus = VIR_DOMAIN_DISK_BUS_IDE;
 
801
        }
 
802
    }
 
803
 
 
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);
 
808
        goto error;
 
809
    }
 
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);
 
814
        goto error;
 
815
    }
 
816
 
 
817
    if (cachetag &&
 
818
        (def->cachemode = virDomainDiskCacheTypeFromString(cachetag)) < 0) {
 
819
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
820
                             _("unknown disk cache mode '%s'"), cachetag);
 
821
        goto error;
 
822
    }
 
823
 
 
824
    if (devaddr &&
 
825
        sscanf(devaddr, "%x:%x:%x",
 
826
               &def->pci_addr.domain,
 
827
               &def->pci_addr.bus,
 
828
               &def->pci_addr.slot) < 3) {
 
829
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
830
                             _("Unable to parse devaddr parameter '%s'"),
 
831
                             devaddr);
 
832
        goto error;
 
833
    }
 
834
 
 
835
    def->src = source;
 
836
    source = NULL;
 
837
    def->dst = target;
 
838
    target = NULL;
 
839
    def->driverName = driverName;
 
840
    driverName = NULL;
 
841
    def->driverType = driverType;
 
842
    driverType = NULL;
 
843
    def->encryption = encryption;
 
844
    encryption = NULL;
 
845
    def->serial = serial;
 
846
    serial = NULL;
 
847
 
 
848
cleanup:
 
849
    VIR_FREE(bus);
 
850
    VIR_FREE(type);
 
851
    VIR_FREE(target);
 
852
    VIR_FREE(source);
 
853
    VIR_FREE(device);
 
854
    VIR_FREE(driverType);
 
855
    VIR_FREE(driverName);
 
856
    VIR_FREE(cachetag);
 
857
    VIR_FREE(devaddr);
 
858
    VIR_FREE(serial);
 
859
    virStorageEncryptionFree(encryption);
 
860
 
 
861
    return def;
 
862
 
 
863
 error:
 
864
    virDomainDiskDefFree(def);
 
865
    def = NULL;
 
866
    goto cleanup;
 
867
}
 
868
 
 
869
 
 
870
/* Parse the XML definition for a disk
 
871
 * @param node XML nodeset to parse for disk definition
 
872
 */
 
873
static virDomainFSDefPtr
 
874
virDomainFSDefParseXML(virConnectPtr conn,
 
875
                       xmlNodePtr node,
 
876
                       int flags ATTRIBUTE_UNUSED) {
 
877
    virDomainFSDefPtr def;
 
878
    xmlNodePtr cur;
 
879
    char *type = NULL;
 
880
    char *source = NULL;
 
881
    char *target = NULL;
 
882
 
 
883
    if (VIR_ALLOC(def) < 0) {
 
884
        virReportOOMError(conn);
 
885
        return NULL;
 
886
    }
 
887
 
 
888
    type = virXMLPropString(node, "type");
 
889
    if (type) {
 
890
        if ((def->type = virDomainFSTypeFromString(type)) < 0) {
 
891
            virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
892
                                 _("unknown filesystem type '%s'"), type);
 
893
            goto error;
 
894
        }
 
895
    } else {
 
896
        def->type = VIR_DOMAIN_FS_TYPE_MOUNT;
 
897
    }
 
898
 
 
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"))) {
 
904
 
 
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")) {
 
917
                def->readonly = 1;
 
918
            }
 
919
        }
 
920
        cur = cur->next;
 
921
    }
 
922
 
 
923
    if (source == NULL) {
 
924
        virDomainReportError(conn, VIR_ERR_NO_SOURCE,
 
925
                             target ? "%s" : NULL, target);
 
926
        goto error;
 
927
    }
 
928
 
 
929
    if (target == NULL) {
 
930
        virDomainReportError(conn, VIR_ERR_NO_TARGET,
 
931
                             source ? "%s" : NULL, source);
 
932
        goto error;
 
933
    }
 
934
 
 
935
    def->src = source;
 
936
    source = NULL;
 
937
    def->dst = target;
 
938
    target = NULL;
 
939
 
 
940
cleanup:
 
941
    VIR_FREE(type);
 
942
    VIR_FREE(target);
 
943
    VIR_FREE(source);
 
944
 
 
945
    return def;
 
946
 
 
947
 error:
 
948
    virDomainFSDefFree(def);
 
949
    def = NULL;
 
950
    goto cleanup;
 
951
}
 
952
 
 
953
 
 
954
 
 
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
 
958
 */
 
959
static virDomainNetDefPtr
 
960
virDomainNetDefParseXML(virConnectPtr conn,
 
961
                        virCapsPtr caps,
 
962
                        xmlNodePtr node,
 
963
                        int flags ATTRIBUTE_UNUSED) {
 
964
    virDomainNetDefPtr def;
 
965
    xmlNodePtr cur;
 
966
    char *macaddr = NULL;
 
967
    char *type = NULL;
 
968
    char *network = NULL;
 
969
    char *bridge = NULL;
 
970
    char *dev = NULL;
 
971
    char *ifname = NULL;
 
972
    char *script = NULL;
 
973
    char *address = NULL;
 
974
    char *port = NULL;
 
975
    char *model = NULL;
 
976
    char *internal = NULL;
 
977
    char *nic_name = NULL;
 
978
    char *hostnet_name = NULL;
 
979
    char *devaddr = NULL;
 
980
    char *vlan = NULL;
 
981
 
 
982
    if (VIR_ALLOC(def) < 0) {
 
983
        virReportOOMError(conn);
 
984
        return NULL;
 
985
    }
 
986
 
 
987
    type = virXMLPropString(node, "type");
 
988
    if (type != NULL) {
 
989
        if ((def->type = virDomainNetTypeFromString(type)) < 0) {
 
990
            virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
991
                                 _("unknown interface type '%s'"), type);
 
992
            goto error;
 
993
        }
 
994
    } else {
 
995
        def->type = VIR_DOMAIN_NET_TYPE_USER;
 
996
    }
 
997
 
 
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 */
 
1038
                    VIR_FREE(ifname);
 
1039
                }
 
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");
 
1053
            }
 
1054
        }
 
1055
        cur = cur->next;
 
1056
    }
 
1057
 
 
1058
    if (macaddr) {
 
1059
        virParseMacAddr((const char *)macaddr, def->mac);
 
1060
    } else {
 
1061
        virCapabilitiesGenerateMac(caps, def->mac);
 
1062
    }
 
1063
 
 
1064
    if (devaddr &&
 
1065
        sscanf(devaddr, "%x:%x:%x",
 
1066
               &def->pci_addr.domain,
 
1067
               &def->pci_addr.bus,
 
1068
               &def->pci_addr.slot) < 3) {
 
1069
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
1070
                             _("Unable to parse devaddr parameter '%s'"),
 
1071
                             devaddr);
 
1072
        goto error;
 
1073
    }
 
1074
 
 
1075
    def->nic_name = nic_name;
 
1076
    def->hostnet_name = hostnet_name;
 
1077
    nic_name = hostnet_name = NULL;
 
1078
 
 
1079
    def->vlan = -1;
 
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"));
 
1083
        goto error;
 
1084
    }
 
1085
 
 
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'/>"));
 
1091
            goto error;
 
1092
        }
 
1093
        def->data.network.name = network;
 
1094
        network = NULL;
 
1095
        break;
 
1096
 
 
1097
    case VIR_DOMAIN_NET_TYPE_ETHERNET:
 
1098
 
 
1099
        if (script != NULL) {
 
1100
            def->data.ethernet.script = script;
 
1101
            script = NULL;
 
1102
        }
 
1103
        if (dev != NULL) {
 
1104
            def->data.ethernet.dev = dev;
 
1105
            dev = NULL;
 
1106
        }
 
1107
        if (address != NULL) {
 
1108
            def->data.ethernet.ipaddr = address;
 
1109
            address = NULL;
 
1110
        }
 
1111
        break;
 
1112
 
 
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'/>"));
 
1117
            goto error;
 
1118
        }
 
1119
        def->data.bridge.brname = bridge;
 
1120
        bridge = NULL;
 
1121
        if (script != NULL) {
 
1122
            def->data.bridge.script = script;
 
1123
            script = NULL;
 
1124
        }
 
1125
        if (address != NULL) {
 
1126
            def->data.bridge.ipaddr = address;
 
1127
            address = NULL;
 
1128
        }
 
1129
        break;
 
1130
 
 
1131
    case VIR_DOMAIN_NET_TYPE_CLIENT:
 
1132
    case VIR_DOMAIN_NET_TYPE_SERVER:
 
1133
    case VIR_DOMAIN_NET_TYPE_MCAST:
 
1134
        if (port == NULL) {
 
1135
            virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
 
1136
            _("No <source> 'port' attribute specified with socket interface"));
 
1137
            goto error;
 
1138
        }
 
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"));
 
1142
            goto error;
 
1143
        }
 
1144
 
 
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"));
 
1150
                goto error;
 
1151
            }
 
1152
        } else {
 
1153
            def->data.socket.address = address;
 
1154
            address = NULL;
 
1155
        }
 
1156
        break;
 
1157
 
 
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'/>"));
 
1162
            goto error;
 
1163
        }
 
1164
        def->data.internal.name = internal;
 
1165
        internal = NULL;
 
1166
        break;
 
1167
    }
 
1168
 
 
1169
    if (ifname != NULL) {
 
1170
        def->ifname = ifname;
 
1171
        ifname = NULL;
 
1172
    }
 
1173
 
 
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
 
1178
     */
 
1179
    if (model != NULL) {
 
1180
        int i;
 
1181
        for (i = 0 ; i < strlen(model) ; i++) {
 
1182
            int char_ok = c_isalnum(model[i]) || model[i] == '_';
 
1183
            if (!char_ok) {
 
1184
                virDomainReportError (conn, VIR_ERR_INVALID_ARG, "%s",
 
1185
                              _("Model name contains invalid characters"));
 
1186
                goto error;
 
1187
            }
 
1188
        }
 
1189
        def->model = model;
 
1190
        model = NULL;
 
1191
    }
 
1192
 
 
1193
cleanup:
 
1194
    VIR_FREE(macaddr);
 
1195
    VIR_FREE(network);
 
1196
    VIR_FREE(address);
 
1197
    VIR_FREE(port);
 
1198
    VIR_FREE(ifname);
 
1199
    VIR_FREE(dev);
 
1200
    VIR_FREE(script);
 
1201
    VIR_FREE(bridge);
 
1202
    VIR_FREE(model);
 
1203
    VIR_FREE(type);
 
1204
    VIR_FREE(internal);
 
1205
    VIR_FREE(nic_name);
 
1206
    VIR_FREE(hostnet_name);
 
1207
    VIR_FREE(devaddr);
 
1208
    VIR_FREE(vlan);
 
1209
 
 
1210
    return def;
 
1211
 
 
1212
error:
 
1213
    virDomainNetDefFree(def);
 
1214
    def = NULL;
 
1215
    goto cleanup;
 
1216
}
 
1217
 
 
1218
 
 
1219
/* Parse the XML definition for a character device
 
1220
 * @param node XML nodeset to parse for net definition
 
1221
 *
 
1222
 * The XML we're dealing with looks like
 
1223
 *
 
1224
 * <serial type="pty">
 
1225
 *   <source path="/dev/pts/3"/>
 
1226
 *   <target port="1"/>
 
1227
 * </serial>
 
1228
 *
 
1229
 * <serial type="dev">
 
1230
 *   <source path="/dev/ttyS0"/>
 
1231
 *   <target port="1"/>
 
1232
 * </serial>
 
1233
 *
 
1234
 * <serial type="tcp">
 
1235
 *   <source mode="connect" host="0.0.0.0" service="2445"/>
 
1236
 *   <target port="1"/>
 
1237
 * </serial>
 
1238
 *
 
1239
 * <serial type="tcp">
 
1240
 *   <source mode="bind" host="0.0.0.0" service="2445"/>
 
1241
 *   <target port="1"/>
 
1242
 *   <protocol type='raw'/>
 
1243
 * </serial>
 
1244
 *
 
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"/>
 
1249
 * </serial>
 
1250
 *
 
1251
 * <serial type="unix">
 
1252
 *   <source mode="bind" path="/tmp/foo"/>
 
1253
 *   <target port="1"/>
 
1254
 * </serial>
 
1255
 *
 
1256
 */
 
1257
static virDomainChrDefPtr
 
1258
virDomainChrDefParseXML(virConnectPtr conn,
 
1259
                        xmlNodePtr node,
 
1260
                        int flags ATTRIBUTE_UNUSED) {
 
1261
    xmlNodePtr cur;
 
1262
    char *type = NULL;
 
1263
    char *bindHost = NULL;
 
1264
    char *bindService = NULL;
 
1265
    char *connectHost = NULL;
 
1266
    char *connectService = NULL;
 
1267
    char *path = NULL;
 
1268
    char *mode = NULL;
 
1269
    char *protocol = NULL;
 
1270
    virDomainChrDefPtr def;
 
1271
 
 
1272
    if (VIR_ALLOC(def) < 0) {
 
1273
        virReportOOMError(conn);
 
1274
        return NULL;
 
1275
    }
 
1276
 
 
1277
    type = virXMLPropString(node, "type");
 
1278
    if (type == NULL)
 
1279
        def->type = VIR_DOMAIN_CHR_TYPE_PTY;
 
1280
    else if ((def->type = virDomainChrTypeFromString(type)) < 0)
 
1281
        def->type = VIR_DOMAIN_CHR_TYPE_NULL;
 
1282
 
 
1283
    cur = node->children;
 
1284
    while (cur != NULL) {
 
1285
        if (cur->type == XML_ELEMENT_NODE) {
 
1286
            if (xmlStrEqual(cur->name, BAD_CAST "source")) {
 
1287
                if (mode == NULL)
 
1288
                    mode = virXMLPropString(cur, "mode");
 
1289
 
 
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:
 
1296
                    if (path == NULL)
 
1297
                        path = virXMLPropString(cur, "path");
 
1298
 
 
1299
                    break;
 
1300
 
 
1301
                case VIR_DOMAIN_CHR_TYPE_UDP:
 
1302
                case VIR_DOMAIN_CHR_TYPE_TCP:
 
1303
                    if (mode == NULL ||
 
1304
                        STREQ((const char *)mode, "connect")) {
 
1305
 
 
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");
 
1315
                    } else {
 
1316
                        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
1317
                                             _("Unknown source mode '%s'"),
 
1318
                                             mode);
 
1319
                        goto error;
 
1320
                    }
 
1321
 
 
1322
                    if (def->type == VIR_DOMAIN_CHR_TYPE_UDP)
 
1323
                        VIR_FREE(mode);
 
1324
                }
 
1325
            } else if (xmlStrEqual(cur->name, BAD_CAST "protocol")) {
 
1326
                if (protocol == NULL)
 
1327
                    protocol = virXMLPropString(cur, "type");
 
1328
            }
 
1329
        }
 
1330
        cur = cur->next;
 
1331
    }
 
1332
 
 
1333
 
 
1334
    switch (def->type) {
 
1335
    case VIR_DOMAIN_CHR_TYPE_NULL:
 
1336
        /* Nada */
 
1337
        break;
 
1338
 
 
1339
    case VIR_DOMAIN_CHR_TYPE_VC:
 
1340
        break;
 
1341
 
 
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:
 
1346
        if (path == NULL &&
 
1347
            def->type != VIR_DOMAIN_CHR_TYPE_PTY) {
 
1348
            virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
 
1349
                       _("Missing source path attribute for char device"));
 
1350
            goto error;
 
1351
        }
 
1352
 
 
1353
        def->data.file.path = path;
 
1354
        path = NULL;
 
1355
        break;
 
1356
 
 
1357
    case VIR_DOMAIN_CHR_TYPE_STDIO:
 
1358
        /* Nada */
 
1359
        break;
 
1360
 
 
1361
    case VIR_DOMAIN_CHR_TYPE_TCP:
 
1362
        if (mode == NULL ||
 
1363
            STREQ(mode, "connect")) {
 
1364
            if (connectHost == NULL) {
 
1365
                virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
 
1366
                        _("Missing source host attribute for char device"));
 
1367
                goto error;
 
1368
            }
 
1369
            if (connectService == NULL) {
 
1370
                virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
 
1371
                     _("Missing source service attribute for char device"));
 
1372
                goto error;
 
1373
            }
 
1374
 
 
1375
            def->data.tcp.host = connectHost;
 
1376
            connectHost = NULL;
 
1377
            def->data.tcp.service = connectService;
 
1378
            connectService = NULL;
 
1379
            def->data.tcp.listen = 0;
 
1380
        } else {
 
1381
            if (bindHost == NULL) {
 
1382
                virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
 
1383
                        _("Missing source host attribute for char device"));
 
1384
                goto error;
 
1385
            }
 
1386
            if (bindService == NULL) {
 
1387
                virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
 
1388
                     _("Missing source service attribute for char device"));
 
1389
                goto error;
 
1390
            }
 
1391
 
 
1392
            def->data.tcp.host = bindHost;
 
1393
            bindHost = NULL;
 
1394
            def->data.tcp.service = bindService;
 
1395
            bindService = NULL;
 
1396
            def->data.tcp.listen = 1;
 
1397
        }
 
1398
 
 
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;
 
1404
        else {
 
1405
            virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
1406
                                 _("Unknown protocol '%s'"), protocol);
 
1407
            goto error;
 
1408
        }
 
1409
 
 
1410
        break;
 
1411
 
 
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"));
 
1416
            goto error;
 
1417
        }
 
1418
 
 
1419
        def->data.udp.connectHost = connectHost;
 
1420
        connectHost = NULL;
 
1421
        def->data.udp.connectService = connectService;
 
1422
        connectService = NULL;
 
1423
 
 
1424
        def->data.udp.bindHost = bindHost;
 
1425
        bindHost = NULL;
 
1426
        def->data.udp.bindService = bindService;
 
1427
        bindService = NULL;
 
1428
        break;
 
1429
 
 
1430
    case VIR_DOMAIN_CHR_TYPE_UNIX:
 
1431
        if (path == NULL) {
 
1432
            virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
 
1433
                         _("Missing source path attribute for char device"));
 
1434
            goto error;
 
1435
        }
 
1436
 
 
1437
        if (mode != NULL &&
 
1438
            STRNEQ(mode, "connect"))
 
1439
            def->data.nix.listen = 1;
 
1440
        else
 
1441
            def->data.nix.listen = 0;
 
1442
 
 
1443
        def->data.nix.path = path;
 
1444
        path = NULL;
 
1445
        break;
 
1446
    }
 
1447
 
 
1448
cleanup:
 
1449
    VIR_FREE(mode);
 
1450
    VIR_FREE(protocol);
 
1451
    VIR_FREE(type);
 
1452
    VIR_FREE(bindHost);
 
1453
    VIR_FREE(bindService);
 
1454
    VIR_FREE(connectHost);
 
1455
    VIR_FREE(connectService);
 
1456
    VIR_FREE(path);
 
1457
 
 
1458
    return def;
 
1459
 
 
1460
error:
 
1461
    virDomainChrDefFree(def);
 
1462
    def = NULL;
 
1463
    goto cleanup;
 
1464
}
 
1465
 
 
1466
/* Parse the XML definition for a network interface */
 
1467
static virDomainInputDefPtr
 
1468
virDomainInputDefParseXML(virConnectPtr conn,
 
1469
                          const char *ostype,
 
1470
                          xmlNodePtr node,
 
1471
                          int flags ATTRIBUTE_UNUSED) {
 
1472
    virDomainInputDefPtr def;
 
1473
    char *type = NULL;
 
1474
    char *bus = NULL;
 
1475
 
 
1476
    if (VIR_ALLOC(def) < 0) {
 
1477
        virReportOOMError(conn);
 
1478
        return NULL;
 
1479
    }
 
1480
 
 
1481
    type = virXMLPropString(node, "type");
 
1482
    bus = virXMLPropString(node, "bus");
 
1483
 
 
1484
    if (!type) {
 
1485
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
1486
                             "%s", _("missing input device type"));
 
1487
        goto error;
 
1488
    }
 
1489
 
 
1490
    if ((def->type = virDomainInputTypeFromString(type)) < 0) {
 
1491
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
1492
                             _("unknown input device type '%s'"), type);
 
1493
        goto error;
 
1494
    }
 
1495
 
 
1496
    if (bus) {
 
1497
        if ((def->bus = virDomainInputBusTypeFromString(bus)) < 0) {
 
1498
            virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
1499
                                 _("unknown input bus type '%s'"), bus);
 
1500
            goto error;
 
1501
        }
 
1502
 
 
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"),
 
1508
                                     type);
 
1509
                goto error;
 
1510
            }
 
1511
            if (def->bus == VIR_DOMAIN_INPUT_BUS_XEN) {
 
1512
                virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
1513
                                     _("unsupported input bus %s"),
 
1514
                                     bus);
 
1515
                goto error;
 
1516
            }
 
1517
        } else {
 
1518
            if (def->bus != VIR_DOMAIN_INPUT_BUS_XEN) {
 
1519
                virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
1520
                                     _("unsupported input bus %s"),
 
1521
                                     bus);
 
1522
            }
 
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"),
 
1526
                                     type);
 
1527
                goto error;
 
1528
            }
 
1529
        }
 
1530
    } else {
 
1531
        if (STREQ(ostype, "hvm")) {
 
1532
            if (def->type == VIR_DOMAIN_INPUT_TYPE_MOUSE)
 
1533
                def->bus = VIR_DOMAIN_INPUT_BUS_PS2;
 
1534
            else
 
1535
                def->bus = VIR_DOMAIN_INPUT_BUS_USB;
 
1536
        } else {
 
1537
            def->bus = VIR_DOMAIN_INPUT_BUS_XEN;
 
1538
        }
 
1539
    }
 
1540
 
 
1541
cleanup:
 
1542
    VIR_FREE(type);
 
1543
    VIR_FREE(bus);
 
1544
 
 
1545
    return def;
 
1546
 
 
1547
error:
 
1548
    virDomainInputDefFree(def);
 
1549
    def = NULL;
 
1550
    goto cleanup;
 
1551
}
 
1552
 
 
1553
 
 
1554
/* Parse the XML definition for a graphics device */
 
1555
static virDomainGraphicsDefPtr
 
1556
virDomainGraphicsDefParseXML(virConnectPtr conn,
 
1557
                             xmlNodePtr node, int flags) {
 
1558
    virDomainGraphicsDefPtr def;
 
1559
    char *type = NULL;
 
1560
 
 
1561
    if (VIR_ALLOC(def) < 0) {
 
1562
        virReportOOMError(conn);
 
1563
        return NULL;
 
1564
    }
 
1565
 
 
1566
    type = virXMLPropString(node, "type");
 
1567
 
 
1568
    if (!type) {
 
1569
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
1570
                             "%s", _("missing graphics device type"));
 
1571
        goto error;
 
1572
    }
 
1573
 
 
1574
    if ((def->type = virDomainGraphicsTypeFromString(type)) < 0) {
 
1575
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
1576
                             _("unknown graphics device type '%s'"), type);
 
1577
        goto error;
 
1578
    }
 
1579
 
 
1580
    if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
 
1581
        char *port = virXMLPropString(node, "port");
 
1582
        char *autoport;
 
1583
 
 
1584
        if (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);
 
1588
                VIR_FREE(port);
 
1589
                goto error;
 
1590
            }
 
1591
            VIR_FREE(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;
 
1597
            }
 
1598
        } else {
 
1599
            def->data.vnc.port = 0;
 
1600
            def->data.vnc.autoport = 1;
 
1601
        }
 
1602
 
 
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;
 
1608
            }
 
1609
            VIR_FREE(autoport);
 
1610
        }
 
1611
 
 
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");
 
1617
 
 
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;
 
1623
            } else {
 
1624
                virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
1625
                             _("unknown fullscreen value '%s'"), fullscreen);
 
1626
                VIR_FREE(fullscreen);
 
1627
                goto error;
 
1628
            }
 
1629
            VIR_FREE(fullscreen);
 
1630
        } else
 
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");
 
1636
        char *autoport;
 
1637
        char *replaceUser;
 
1638
        char *multiUser;
 
1639
 
 
1640
        if (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);
 
1644
                VIR_FREE(port);
 
1645
                goto error;
 
1646
            }
 
1647
            VIR_FREE(port);
 
1648
        } else {
 
1649
            def->data.rdp.port = 0;
 
1650
            def->data.rdp.autoport = 1;
 
1651
        }
 
1652
 
 
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;
 
1658
            }
 
1659
            VIR_FREE(autoport);
 
1660
        }
 
1661
 
 
1662
        if ((replaceUser = virXMLPropString(node, "replaceUser")) != NULL) {
 
1663
            if (STREQ(replaceUser, "yes")) {
 
1664
                def->data.rdp.replaceUser = 1;
 
1665
            }
 
1666
            VIR_FREE(replaceUser);
 
1667
        }
 
1668
 
 
1669
        if ((multiUser = virXMLPropString(node, "multiUser")) != NULL) {
 
1670
            if (STREQ(multiUser, "yes")) {
 
1671
                def->data.rdp.multiUser = 1;
 
1672
            }
 
1673
            VIR_FREE(multiUser);
 
1674
        }
 
1675
 
 
1676
        def->data.rdp.listenAddr = virXMLPropString(node, "listen");
 
1677
    } else if (def->type == VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP) {
 
1678
        char *fullscreen = virXMLPropString(node, "fullscreen");
 
1679
 
 
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;
 
1685
            } else {
 
1686
                virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
1687
                             _("unknown fullscreen value '%s'"), fullscreen);
 
1688
                VIR_FREE(fullscreen);
 
1689
                goto error;
 
1690
            }
 
1691
            VIR_FREE(fullscreen);
 
1692
        } else
 
1693
            def->data.desktop.fullscreen = 0;
 
1694
 
 
1695
        def->data.desktop.display = virXMLPropString(node, "display");
 
1696
    }
 
1697
 
 
1698
cleanup:
 
1699
    VIR_FREE(type);
 
1700
 
 
1701
    return def;
 
1702
 
 
1703
error:
 
1704
    virDomainGraphicsDefFree(def);
 
1705
    def = NULL;
 
1706
    goto cleanup;
 
1707
}
 
1708
 
 
1709
 
 
1710
static virDomainSoundDefPtr
 
1711
virDomainSoundDefParseXML(virConnectPtr conn,
 
1712
                          const xmlNodePtr node,
 
1713
                          int flags ATTRIBUTE_UNUSED) {
 
1714
 
 
1715
    char *model;
 
1716
    virDomainSoundDefPtr def;
 
1717
 
 
1718
    if (VIR_ALLOC(def) < 0) {
 
1719
        virReportOOMError(conn);
 
1720
        return NULL;
 
1721
    }
 
1722
 
 
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);
 
1727
        goto error;
 
1728
    }
 
1729
 
 
1730
cleanup:
 
1731
    VIR_FREE(model);
 
1732
 
 
1733
    return def;
 
1734
 
 
1735
error:
 
1736
    virDomainSoundDefFree(def);
 
1737
    def = NULL;
 
1738
    goto cleanup;
 
1739
}
 
1740
 
 
1741
 
 
1742
int
 
1743
virDomainVideoDefaultRAM(virDomainDefPtr def,
 
1744
                         int type)
 
1745
{
 
1746
    switch (type) {
 
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)
 
1752
            return 8 * 1024;
 
1753
        else
 
1754
            return 9 * 1024;
 
1755
        break;
 
1756
 
 
1757
    case VIR_DOMAIN_VIDEO_TYPE_XEN:
 
1758
        /* Original Xen PVFB hardcoded to 4 MB */
 
1759
        return 4 * 1024;
 
1760
 
 
1761
    default:
 
1762
        return 0;
 
1763
    }
 
1764
}
 
1765
 
 
1766
 
 
1767
int
 
1768
virDomainVideoDefaultType(virDomainDefPtr def)
 
1769
{
 
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:
 
1776
        if (def->os.type &&
 
1777
            (STREQ(def->os.type, "xen") ||
 
1778
             STREQ(def->os.type, "linux")))
 
1779
            return VIR_DOMAIN_VIDEO_TYPE_XEN;
 
1780
        else
 
1781
            return VIR_DOMAIN_VIDEO_TYPE_CIRRUS;
 
1782
 
 
1783
    case VIR_DOMAIN_VIRT_VBOX:
 
1784
        return VIR_DOMAIN_VIDEO_TYPE_VBOX;
 
1785
 
 
1786
    default:
 
1787
        return -1;
 
1788
    }
 
1789
}
 
1790
 
 
1791
static virDomainVideoAccelDefPtr
 
1792
virDomainVideoAccelDefParseXML(virConnectPtr conn, const xmlNodePtr node) {
 
1793
    xmlNodePtr cur;
 
1794
    virDomainVideoAccelDefPtr def;
 
1795
    char *support3d = NULL;
 
1796
    char *support2d = NULL;
 
1797
 
 
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");
 
1805
            }
 
1806
        }
 
1807
        cur = cur->next;
 
1808
    }
 
1809
 
 
1810
    if ((support3d == NULL) && (support2d == NULL))
 
1811
        return(NULL);
 
1812
 
 
1813
    if (VIR_ALLOC(def) < 0) {
 
1814
        virReportOOMError(conn);
 
1815
        return NULL;
 
1816
    }
 
1817
 
 
1818
    if (support3d) {
 
1819
        if (STREQ(support3d, "yes"))
 
1820
            def->support3d = 1;
 
1821
        else
 
1822
            def->support3d = 0;
 
1823
        VIR_FREE(support3d);
 
1824
    }
 
1825
 
 
1826
    if (support2d) {
 
1827
        if (STREQ(support2d, "yes"))
 
1828
            def->support2d = 1;
 
1829
        else
 
1830
            def->support2d = 0;
 
1831
        VIR_FREE(support2d);
 
1832
    }
 
1833
 
 
1834
    return def;
 
1835
}
 
1836
 
 
1837
static virDomainVideoDefPtr
 
1838
virDomainVideoDefParseXML(virConnectPtr conn,
 
1839
                          const xmlNodePtr node,
 
1840
                          virDomainDefPtr dom,
 
1841
                          int flags ATTRIBUTE_UNUSED) {
 
1842
    virDomainVideoDefPtr def;
 
1843
    xmlNodePtr cur;
 
1844
    char *type = NULL;
 
1845
    char *heads = NULL;
 
1846
    char *vram = NULL;
 
1847
 
 
1848
    if (VIR_ALLOC(def) < 0) {
 
1849
        virReportOOMError(conn);
 
1850
        return NULL;
 
1851
    }
 
1852
 
 
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);
 
1862
            }
 
1863
        }
 
1864
        cur = cur->next;
 
1865
    }
 
1866
 
 
1867
    if (type) {
 
1868
        if ((def->type = virDomainVideoTypeFromString(type)) < 0) {
 
1869
            virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
1870
                                 _("unknown video model '%s'"), type);
 
1871
            goto error;
 
1872
        }
 
1873
    } else {
 
1874
        if ((def->type = virDomainVideoDefaultType(dom)) < 0) {
 
1875
            virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
 
1876
                                 _("missing video model and cannot determine default"));
 
1877
            goto error;
 
1878
        }
 
1879
    }
 
1880
 
 
1881
    if (vram) {
 
1882
        if (virStrToLong_ui(vram, NULL, 10, &def->vram) < 0) {
 
1883
            virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
1884
                                 _("cannot parse video ram '%s'"), vram);
 
1885
            goto error;
 
1886
        }
 
1887
    } else {
 
1888
        def->vram = virDomainVideoDefaultRAM(dom, def->type);
 
1889
    }
 
1890
 
 
1891
    if (heads) {
 
1892
        if (virStrToLong_ui(heads, NULL, 10, &def->heads) < 0) {
 
1893
            virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
1894
                                 _("cannot parse video heads '%s'"), heads);
 
1895
            goto error;
 
1896
        }
 
1897
    } else {
 
1898
        def->heads = 1;
 
1899
    }
 
1900
 
 
1901
    VIR_FREE(type);
 
1902
    VIR_FREE(vram);
 
1903
    VIR_FREE(heads);
 
1904
 
 
1905
    return def;
 
1906
 
 
1907
error:
 
1908
    virDomainVideoDefFree(def);
 
1909
    VIR_FREE(type);
 
1910
    VIR_FREE(vram);
 
1911
    VIR_FREE(heads);
 
1912
    return NULL;
 
1913
}
 
1914
 
 
1915
static int
 
1916
virDomainHostdevSubsysUsbDefParseXML(virConnectPtr conn,
 
1917
                                     const xmlNodePtr node,
 
1918
                                     virDomainHostdevDefPtr def,
 
1919
                                     int flags ATTRIBUTE_UNUSED) {
 
1920
 
 
1921
    int ret = -1;
 
1922
    int got_product, got_vendor;
 
1923
    xmlNodePtr cur;
 
1924
 
 
1925
    /* Product can validly be 0, so we need some extra help to determine
 
1926
     * if it is uninitialized*/
 
1927
    got_product = 0;
 
1928
    got_vendor = 0;
 
1929
 
 
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");
 
1935
 
 
1936
                if (vendor) {
 
1937
                    got_vendor = 1;
 
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);
 
1942
                        VIR_FREE(vendor);
 
1943
                        goto out;
 
1944
                    }
 
1945
                    VIR_FREE(vendor);
 
1946
                } else {
 
1947
                    virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
1948
                                         "%s", _("usb vendor needs id"));
 
1949
                    goto out;
 
1950
                }
 
1951
            } else if (xmlStrEqual(cur->name, BAD_CAST "product")) {
 
1952
                char* product = virXMLPropString(cur, "id");
 
1953
 
 
1954
                if (product) {
 
1955
                    got_product = 1;
 
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"),
 
1960
                                             product);
 
1961
                        VIR_FREE(product);
 
1962
                        goto out;
 
1963
                    }
 
1964
                    VIR_FREE(product);
 
1965
                } else {
 
1966
                    virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
1967
                                         "%s", _("usb product needs id"));
 
1968
                    goto out;
 
1969
                }
 
1970
            } else if (xmlStrEqual(cur->name, BAD_CAST "address")) {
 
1971
                char *bus, *device;
 
1972
 
 
1973
                bus = virXMLPropString(cur, "bus");
 
1974
                if (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);
 
1979
                        VIR_FREE(bus);
 
1980
                        goto out;
 
1981
                    }
 
1982
                    VIR_FREE(bus);
 
1983
                } else {
 
1984
                    virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
1985
                                         "%s", _("usb address needs bus id"));
 
1986
                    goto out;
 
1987
                }
 
1988
 
 
1989
                device = virXMLPropString(cur, "device");
 
1990
                if (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"),
 
1995
                                             device);
 
1996
                        VIR_FREE(device);
 
1997
                        goto out;
 
1998
                    }
 
1999
                    VIR_FREE(device);
 
2000
                } else {
 
2001
                    virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
 
2002
                                         _("usb address needs device id"));
 
2003
                    goto out;
 
2004
                }
 
2005
            } else {
 
2006
                virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
2007
                                     _("unknown usb source type '%s'"),
 
2008
                                     cur->name);
 
2009
                goto out;
 
2010
            }
 
2011
        }
 
2012
        cur = cur->next;
 
2013
    }
 
2014
 
 
2015
    if (got_vendor && def->source.subsys.u.usb.vendor == 0) {
 
2016
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
2017
            "%s", _("vendor cannot be 0."));
 
2018
        goto out;
 
2019
    }
 
2020
 
 
2021
    if (!got_vendor && got_product) {
 
2022
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
2023
            "%s", _("missing vendor"));
 
2024
        goto out;
 
2025
    }
 
2026
    if (got_vendor && !got_product) {
 
2027
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
2028
            "%s", _("missing product"));
 
2029
        goto out;
 
2030
    }
 
2031
 
 
2032
    ret = 0;
 
2033
out:
 
2034
    return ret;
 
2035
}
 
2036
 
 
2037
 
 
2038
static int
 
2039
virDomainHostdevSubsysPciDefParseXML(virConnectPtr conn,
 
2040
                                     const xmlNodePtr node,
 
2041
                                     virDomainHostdevDefPtr def,
 
2042
                                     int flags) {
 
2043
 
 
2044
    int ret = -1;
 
2045
    xmlNodePtr cur;
 
2046
 
 
2047
    cur = node->children;
 
2048
    while (cur != NULL) {
 
2049
        if (cur->type == XML_ELEMENT_NODE) {
 
2050
            if (xmlStrEqual(cur->name, BAD_CAST "address")) {
 
2051
 
 
2052
                char *domain = virXMLPropString(cur, "domain");
 
2053
                if (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"),
 
2058
                                             domain);
 
2059
                        VIR_FREE(domain);
 
2060
                        goto out;
 
2061
                    }
 
2062
                    VIR_FREE(domain);
 
2063
                }
 
2064
 
 
2065
                char *bus = virXMLPropString(cur, "bus");
 
2066
                if (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);
 
2071
                        VIR_FREE(bus);
 
2072
                        goto out;
 
2073
                    }
 
2074
                    VIR_FREE(bus);
 
2075
                } else {
 
2076
                    virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
2077
                                         "%s", _("pci address needs bus id"));
 
2078
                    goto out;
 
2079
                }
 
2080
 
 
2081
                char *slot = virXMLPropString(cur, "slot");
 
2082
                if (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"),
 
2087
                                             slot);
 
2088
                        VIR_FREE(slot);
 
2089
                        goto out;
 
2090
                    }
 
2091
                    VIR_FREE(slot);
 
2092
                } else {
 
2093
                    virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
2094
                                         "%s", _("pci address needs slot id"));
 
2095
                    goto out;
 
2096
                }
 
2097
 
 
2098
                char *function = virXMLPropString(cur, "function");
 
2099
                if (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"),
 
2104
                                             function);
 
2105
                        VIR_FREE(function);
 
2106
                        goto out;
 
2107
                    }
 
2108
                    VIR_FREE(function);
 
2109
                } else {
 
2110
                    virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
 
2111
                                         _("pci address needs function id"));
 
2112
                    goto out;
 
2113
                }
 
2114
            } else if ((flags & VIR_DOMAIN_XML_INTERNAL_STATUS) &&
 
2115
                       xmlStrEqual(cur->name, BAD_CAST "state")) {
 
2116
                char *devaddr = virXMLPropString(cur, "devaddr");
 
2117
                if (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'"),
 
2124
                                         devaddr);
 
2125
                    VIR_FREE(devaddr);
 
2126
                    goto out;
 
2127
                }
 
2128
            } else {
 
2129
                virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
2130
                                     _("unknown pci source type '%s'"),
 
2131
                                     cur->name);
 
2132
                goto out;
 
2133
            }
 
2134
        }
 
2135
        cur = cur->next;
 
2136
    }
 
2137
 
 
2138
    ret = 0;
 
2139
out:
 
2140
    return ret;
 
2141
}
 
2142
 
 
2143
 
 
2144
static virDomainHostdevDefPtr
 
2145
virDomainHostdevDefParseXML(virConnectPtr conn,
 
2146
                            const xmlNodePtr node,
 
2147
                            int flags) {
 
2148
 
 
2149
    xmlNodePtr cur;
 
2150
    virDomainHostdevDefPtr def;
 
2151
    char *mode, *type = NULL, *managed = NULL;
 
2152
 
 
2153
    if (VIR_ALLOC(def) < 0) {
 
2154
        virReportOOMError(conn);
 
2155
        return NULL;
 
2156
    }
 
2157
    def->target = NULL;
 
2158
 
 
2159
    mode = virXMLPropString(node, "mode");
 
2160
    if (mode) {
 
2161
        if ((def->mode=virDomainHostdevModeTypeFromString(mode)) < 0) {
 
2162
             virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
2163
                                  _("unknown hostdev mode '%s'"), mode);
 
2164
            goto error;
 
2165
        }
 
2166
    } else {
 
2167
        def->mode = VIR_DOMAIN_HOSTDEV_MODE_SUBSYS;
 
2168
    }
 
2169
 
 
2170
    type = virXMLPropString(node, "type");
 
2171
    if (type) {
 
2172
        if ((def->source.subsys.type = virDomainHostdevSubsysTypeFromString(type)) < 0) {
 
2173
            virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
2174
                                 _("unknown host device type '%s'"), type);
 
2175
            goto error;
 
2176
        }
 
2177
    } else {
 
2178
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
2179
                             "%s", _("missing type in hostdev"));
 
2180
        goto error;
 
2181
    }
 
2182
 
 
2183
    managed = virXMLPropString(node, "managed");
 
2184
    if (managed != NULL) {
 
2185
        if (STREQ(managed, "yes"))
 
2186
            def->managed = 1;
 
2187
        VIR_FREE(managed);
 
2188
    }
 
2189
 
 
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,
 
2197
                                                                 def, flags) < 0)
 
2198
                            goto error;
 
2199
                }
 
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)
 
2203
                            goto error;
 
2204
                }
 
2205
            } else {
 
2206
                virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
2207
                                     _("unknown node %s"), cur->name);
 
2208
            }
 
2209
        }
 
2210
        cur = cur->next;
 
2211
    }
 
2212
 
 
2213
cleanup:
 
2214
    VIR_FREE(type);
 
2215
    VIR_FREE(mode);
 
2216
    return def;
 
2217
 
 
2218
error:
 
2219
    virDomainHostdevDefFree(def);
 
2220
    def = NULL;
 
2221
    goto cleanup;
 
2222
}
 
2223
 
 
2224
 
 
2225
static int virDomainLifecycleParseXML(virConnectPtr conn,
 
2226
                                      xmlXPathContextPtr ctxt,
 
2227
                                      const char *xpath,
 
2228
                                      int *val,
 
2229
                                      int defaultVal)
 
2230
{
 
2231
    char *tmp = virXPathString(conn, xpath, ctxt);
 
2232
    if (tmp == NULL) {
 
2233
        *val = defaultVal;
 
2234
    } else {
 
2235
        *val = virDomainLifecycleTypeFromString(tmp);
 
2236
        if (*val < 0) {
 
2237
            virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
2238
                                 _("unknown lifecycle action %s"), tmp);
 
2239
            VIR_FREE(tmp);
 
2240
            return -1;
 
2241
        }
 
2242
        VIR_FREE(tmp);
 
2243
    }
 
2244
    return 0;
 
2245
}
 
2246
 
 
2247
static int
 
2248
virSecurityLabelDefParseXML(virConnectPtr conn,
 
2249
                            const virDomainDefPtr def,
 
2250
                            xmlXPathContextPtr ctxt,
 
2251
                            int flags)
 
2252
{
 
2253
    char *p;
 
2254
 
 
2255
    if (virXPathNode(conn, "./seclabel", ctxt) == NULL)
 
2256
        return 0;
 
2257
 
 
2258
    p = virXPathStringLimit(conn, "string(./seclabel/@type)",
 
2259
                            VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
 
2260
    if (p == NULL) {
 
2261
        virDomainReportError(conn, VIR_ERR_XML_ERROR,
 
2262
                             "%s", _("missing security type"));
 
2263
        goto error;
 
2264
    }
 
2265
    def->seclabel.type = virDomainSeclabelTypeFromString(p);
 
2266
    VIR_FREE(p);
 
2267
    if (def->seclabel.type < 0) {
 
2268
        virDomainReportError(conn, VIR_ERR_XML_ERROR,
 
2269
                             "%s", _("invalid security type"));
 
2270
        goto error;
 
2271
    }
 
2272
 
 
2273
    /* Only parse details, if using static labels, or
 
2274
     * if the 'live' VM XML is requested
 
2275
     */
 
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);
 
2280
        if (p == NULL) {
 
2281
            virDomainReportError(conn, VIR_ERR_XML_ERROR,
 
2282
                                 "%s", _("missing security model"));
 
2283
            goto error;
 
2284
        }
 
2285
        def->seclabel.model = p;
 
2286
 
 
2287
        p = virXPathStringLimit(conn, "string(./seclabel/label[1])",
 
2288
                                VIR_SECURITY_LABEL_BUFLEN-1, ctxt);
 
2289
        if (p == NULL) {
 
2290
            virDomainReportError(conn, VIR_ERR_XML_ERROR,
 
2291
                                 "%s", _("security label is missing"));
 
2292
            goto error;
 
2293
        }
 
2294
 
 
2295
        def->seclabel.label = p;
 
2296
    }
 
2297
 
 
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);
 
2303
        if (p == NULL) {
 
2304
            virDomainReportError(conn, VIR_ERR_XML_ERROR,
 
2305
                                 "%s", _("security imagelabel is missing"));
 
2306
            goto error;
 
2307
        }
 
2308
        def->seclabel.imagelabel = p;
 
2309
    }
 
2310
 
 
2311
    return 0;
 
2312
 
 
2313
error:
 
2314
    virSecurityLabelDefFree(def);
 
2315
    return -1;
 
2316
}
 
2317
 
 
2318
virDomainDeviceDefPtr virDomainDeviceDefParse(virConnectPtr conn,
 
2319
                                              virCapsPtr caps,
 
2320
                                              const virDomainDefPtr def,
 
2321
                                              const char *xmlStr,
 
2322
                                              int flags)
 
2323
{
 
2324
    xmlDocPtr xml;
 
2325
    xmlNodePtr node;
 
2326
    virDomainDeviceDefPtr dev = NULL;
 
2327
 
 
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);
 
2332
        goto error;
 
2333
    }
 
2334
 
 
2335
    node = xmlDocGetRootElement(xml);
 
2336
    if (node == NULL) {
 
2337
        virDomainReportError(conn, VIR_ERR_XML_ERROR,
 
2338
                             "%s", _("missing root element"));
 
2339
        goto error;
 
2340
    }
 
2341
 
 
2342
    if (VIR_ALLOC(dev) < 0) {
 
2343
        virReportOOMError(conn);
 
2344
        goto error;
 
2345
    }
 
2346
 
 
2347
    if (xmlStrEqual(node->name, BAD_CAST "disk")) {
 
2348
        dev->type = VIR_DOMAIN_DEVICE_DISK;
 
2349
        if (!(dev->data.disk = virDomainDiskDefParseXML(conn, node, flags)))
 
2350
            goto error;
 
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)))
 
2354
            goto error;
 
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)))
 
2358
            goto error;
 
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,
 
2362
                                                          node, flags)))
 
2363
            goto error;
 
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)))
 
2367
            goto error;
 
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)))
 
2371
            goto error;
 
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)))
 
2375
            goto error;
 
2376
    } else {
 
2377
        virDomainReportError(conn, VIR_ERR_XML_ERROR,
 
2378
                             "%s", _("unknown device type"));
 
2379
        goto error;
 
2380
    }
 
2381
 
 
2382
    xmlFreeDoc(xml);
 
2383
 
 
2384
    return dev;
 
2385
 
 
2386
  error:
 
2387
    xmlFreeDoc(xml);
 
2388
    VIR_FREE(dev);
 
2389
    return NULL;
 
2390
}
 
2391
#endif
 
2392
 
 
2393
 
 
2394
int virDomainDiskInsert(virDomainDefPtr def,
 
2395
                        virDomainDiskDefPtr disk)
 
2396
{
 
2397
 
 
2398
    if (VIR_REALLOC_N(def->disks, def->ndisks+1) < 0)
 
2399
        return -1;
 
2400
 
 
2401
    virDomainDiskInsertPreAlloced(def, disk);
 
2402
 
 
2403
    return 0;
 
2404
}
 
2405
 
 
2406
void virDomainDiskInsertPreAlloced(virDomainDefPtr def,
 
2407
                                   virDomainDiskDefPtr disk)
 
2408
{
 
2409
    int i;
 
2410
    /* Tenatively plan to insert disk at the end. */
 
2411
    int insertAt = -1;
 
2412
 
 
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
 
2416
     * that position
 
2417
     */
 
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))) {
 
2424
            insertAt = i;
 
2425
        } else if (def->disks[i]->bus == disk->bus &&
 
2426
                   insertAt == -1) {
 
2427
            /* Last disk with match bus is before the
 
2428
             * new disk, then put new disk just after
 
2429
             */
 
2430
            insertAt = i + 1;
 
2431
        }
 
2432
    }
 
2433
 
 
2434
    /* No disks with this bus yet, so put at end of list */
 
2435
    if (insertAt == -1)
 
2436
        insertAt = def->ndisks;
 
2437
 
 
2438
    if (insertAt < def->ndisks)
 
2439
        memmove(def->disks + insertAt + 1,
 
2440
                def->disks + insertAt,
 
2441
                (sizeof(def->disks[0]) * (def->ndisks-insertAt)));
 
2442
 
 
2443
    def->disks[insertAt] = disk;
 
2444
    def->ndisks++;
 
2445
}
 
2446
 
 
2447
 
 
2448
#ifndef PROXY
 
2449
static char *virDomainDefDefaultEmulator(virConnectPtr conn,
 
2450
                                         virDomainDefPtr def,
 
2451
                                         virCapsPtr caps) {
 
2452
    const char *type;
 
2453
    const char *emulator;
 
2454
    char *retemu;
 
2455
 
 
2456
    type = virDomainVirtTypeToString(def->virtType);
 
2457
    if (!type) {
 
2458
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
2459
                             "%s", _("unknown virt type"));
 
2460
        return NULL;
 
2461
    }
 
2462
 
 
2463
    emulator = virCapabilitiesDefaultGuestEmulator(caps,
 
2464
                                                   def->os.type,
 
2465
                                                   def->os.arch,
 
2466
                                                   type);
 
2467
 
 
2468
    if (!emulator) {
 
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);
 
2472
        return NULL;
 
2473
    }
 
2474
 
 
2475
    retemu = strdup(emulator);
 
2476
    if (!retemu)
 
2477
        virReportOOMError(conn);
 
2478
 
 
2479
    return retemu;
 
2480
}
 
2481
 
 
2482
static virDomainDefPtr virDomainDefParseXML(virConnectPtr conn,
 
2483
                                            virCapsPtr caps,
 
2484
                                            xmlXPathContextPtr ctxt, int flags)
 
2485
{
 
2486
    xmlNodePtr *nodes = NULL, node = NULL;
 
2487
    char *tmp = NULL;
 
2488
    int i, n;
 
2489
    long id = -1;
 
2490
    virDomainDefPtr def;
 
2491
 
 
2492
    if (VIR_ALLOC(def) < 0) {
 
2493
        virReportOOMError(conn);
 
2494
        return NULL;
 
2495
    }
 
2496
 
 
2497
    if (!(flags & VIR_DOMAIN_XML_INACTIVE))
 
2498
        if((virXPathLong(conn, "string(./@id)", ctxt, &id)) < 0)
 
2499
            id = -1;
 
2500
    def->id = (int)id;
 
2501
 
 
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"));
 
2506
        goto error;
 
2507
    }
 
2508
 
 
2509
    if ((def->virtType = virDomainVirtTypeFromString(tmp)) < 0) {
 
2510
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
2511
                             _("invalid domain type %s"), tmp);
 
2512
        goto error;
 
2513
    }
 
2514
    VIR_FREE(tmp);
 
2515
 
 
2516
    /* Extract domain name */
 
2517
    if (!(def->name = virXPathString(conn, "string(./name[1])", ctxt))) {
 
2518
        virDomainReportError(conn, VIR_ERR_NO_NAME, NULL);
 
2519
        goto error;
 
2520
    }
 
2521
 
 
2522
    /* Extract domain uuid */
 
2523
    tmp = virXPathString(conn, "string(./uuid[1])", ctxt);
 
2524
    if (!tmp) {
 
2525
        if (virUUIDGenerate(def->uuid)) {
 
2526
            virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
2527
                                 "%s", _("Failed to generate UUID"));
 
2528
            goto error;
 
2529
        }
 
2530
    } else {
 
2531
        if (virUUIDParse(tmp, def->uuid) < 0) {
 
2532
            virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
2533
                                 "%s", _("malformed uuid element"));
 
2534
            goto error;
 
2535
        }
 
2536
        VIR_FREE(tmp);
 
2537
    }
 
2538
 
 
2539
    /* Extract documentation if present */
 
2540
    def->description = virXPathString(conn, "string(./description[1])", ctxt);
 
2541
 
 
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"));
 
2546
        goto error;
 
2547
    }
 
2548
 
 
2549
    if (virXPathULong(conn, "string(./currentMemory[1])", ctxt, &def->memory) < 0)
 
2550
        def->memory = def->maxmem;
 
2551
 
 
2552
    node = virXPathNode(conn, "./memoryBacking/hugepages", ctxt);
 
2553
    if (node)
 
2554
        def->hugepage_backed = 1;
 
2555
 
 
2556
    if (virXPathULong(conn, "string(./vcpu[1])", ctxt, &def->vcpus) < 0)
 
2557
        def->vcpus = 1;
 
2558
 
 
2559
    tmp = virXPathString(conn, "string(./vcpu[1]/@cpuset)", ctxt);
 
2560
    if (tmp) {
 
2561
        char *set = tmp;
 
2562
        def->cpumasklen = VIR_DOMAIN_CPUMASK_LEN;
 
2563
        if (VIR_ALLOC_N(def->cpumask, def->cpumasklen) < 0) {
 
2564
            virReportOOMError(conn);
 
2565
            goto error;
 
2566
        }
 
2567
        if (virDomainCpuSetParse(conn, (const char **)&set,
 
2568
                                 0, def->cpumask,
 
2569
                                 def->cpumasklen) < 0)
 
2570
            goto error;
 
2571
        VIR_FREE(tmp);
 
2572
    }
 
2573
 
 
2574
    n = virXPathNodeSet(conn, "./features/*", ctxt, &nodes);
 
2575
    if (n < 0)
 
2576
        goto error;
 
2577
    if (n) {
 
2578
        for (i = 0 ; i < n ; i++) {
 
2579
            int val = virDomainFeatureTypeFromString((const char *)nodes[i]->name);
 
2580
            if (val < 0) {
 
2581
                virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
2582
                                     _("unexpected feature %s"),
 
2583
                                     nodes[i]->name);
 
2584
                goto error;
 
2585
            }
 
2586
            def->features |= (1 << val);
 
2587
        }
 
2588
        VIR_FREE(nodes);
 
2589
    }
 
2590
 
 
2591
    if (virDomainLifecycleParseXML(conn, ctxt, "string(./on_reboot[1])",
 
2592
                                   &def->onReboot, VIR_DOMAIN_LIFECYCLE_RESTART) < 0)
 
2593
        goto error;
 
2594
 
 
2595
    if (virDomainLifecycleParseXML(conn, ctxt, "string(./on_poweroff[1])",
 
2596
                                   &def->onPoweroff, VIR_DOMAIN_LIFECYCLE_DESTROY) < 0)
 
2597
        goto error;
 
2598
 
 
2599
    if (virDomainLifecycleParseXML(conn, ctxt, "string(./on_crash[1])",
 
2600
                                   &def->onCrash, VIR_DOMAIN_LIFECYCLE_DESTROY) < 0)
 
2601
        goto error;
 
2602
 
 
2603
 
 
2604
    tmp = virXPathString(conn, "string(./clock/@offset)", ctxt);
 
2605
    if (tmp && STREQ(tmp, "localtime"))
 
2606
        def->localtime = 1;
 
2607
    VIR_FREE(tmp);
 
2608
 
 
2609
    def->os.bootloader = virXPathString(conn, "string(./bootloader)", ctxt);
 
2610
    def->os.bootloaderArgs = virXPathString(conn, "string(./bootloader_args)", ctxt);
 
2611
 
 
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);
 
2618
                goto error;
 
2619
            }
 
2620
        } else {
 
2621
            virDomainReportError(conn, VIR_ERR_OS_TYPE,
 
2622
                                 "%s", _("no OS type"));
 
2623
            goto error;
 
2624
        }
 
2625
    }
 
2626
    /*
 
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
 
2630
     */
 
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);
 
2636
            goto error;
 
2637
        }
 
2638
    }
 
2639
 
 
2640
    if (!virCapabilitiesSupportsGuestOSType(caps, def->os.type)) {
 
2641
        virDomainReportError(conn, VIR_ERR_OS_TYPE,
 
2642
                             "%s", def->os.type);
 
2643
        goto error;
 
2644
    }
 
2645
 
 
2646
    def->os.arch = virXPathString(conn, "string(./os/type[1]/@arch)", ctxt);
 
2647
    if (def->os.arch) {
 
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);
 
2652
            goto error;
 
2653
        }
 
2654
    } else {
 
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'"),
 
2659
                                 def->os.type);
 
2660
            goto error;
 
2661
        }
 
2662
        if (!(def->os.arch = strdup(defaultArch))) {
 
2663
            virReportOOMError(conn);
 
2664
            goto error;
 
2665
        }
 
2666
    }
 
2667
 
 
2668
    def->os.machine = virXPathString(conn, "string(./os/type[1]/@machine)", ctxt);
 
2669
    if (!def->os.machine) {
 
2670
        const char *defaultMachine = virCapabilitiesDefaultGuestMachine(caps,
 
2671
                                                                        def->os.type,
 
2672
                                                                        def->os.arch,
 
2673
                                                                        virDomainVirtTypeToString(def->virtType));
 
2674
        if (defaultMachine != NULL) {
 
2675
            if (!(def->os.machine = strdup(defaultMachine))) {
 
2676
                virReportOOMError(conn);
 
2677
                goto error;
 
2678
            }
 
2679
        }
 
2680
    }
 
2681
 
 
2682
    /*
 
2683
     * Booting options for different OS types....
 
2684
     *
 
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)
 
2689
     */
 
2690
 
 
2691
    if (STREQ(def->os.type, "exe")) {
 
2692
        def->os.init = virXPathString(conn, "string(./os/init[1])", ctxt);
 
2693
    }
 
2694
 
 
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);
 
2703
    }
 
2704
 
 
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"));
 
2710
            goto error;
 
2711
        }
 
2712
        for (i = 0 ; i < n && i < VIR_DOMAIN_BOOT_LAST ; i++) {
 
2713
            int val;
 
2714
            char *dev = virXMLPropString(nodes[i], "dev");
 
2715
            if (!dev) {
 
2716
                virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
2717
                                     "%s", _("missing boot device"));
 
2718
                goto error;
 
2719
            }
 
2720
            if ((val = virDomainBootTypeFromString(dev)) < 0) {
 
2721
                virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
2722
                                     _("unknown boot device '%s'"),
 
2723
                                     dev);
 
2724
                VIR_FREE(dev);
 
2725
                goto error;
 
2726
            }
 
2727
            VIR_FREE(dev);
 
2728
            def->os.bootDevs[def->os.nBootDevs++] = val;
 
2729
        }
 
2730
        if (def->os.nBootDevs == 0) {
 
2731
            def->os.nBootDevs = 1;
 
2732
            def->os.bootDevs[0] = VIR_DOMAIN_BOOT_DISK;
 
2733
        }
 
2734
        VIR_FREE(nodes);
 
2735
    }
 
2736
 
 
2737
    def->emulator = virXPathString(conn, "string(./devices/emulator[1])", ctxt);
 
2738
    if (!def->emulator && virCapabilitiesIsEmulatorRequired(caps)) {
 
2739
        def->emulator = virDomainDefDefaultEmulator(conn, def, caps);
 
2740
        if (!def->emulator)
 
2741
            goto error;
 
2742
    }
 
2743
 
 
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"));
 
2748
        goto error;
 
2749
    }
 
2750
    if (n && VIR_ALLOC_N(def->disks, n) < 0)
 
2751
        goto no_memory;
 
2752
    for (i = 0 ; i < n ; i++) {
 
2753
        virDomainDiskDefPtr disk = virDomainDiskDefParseXML(conn,
 
2754
                                                            nodes[i],
 
2755
                                                            flags);
 
2756
        if (!disk)
 
2757
            goto error;
 
2758
 
 
2759
        def->disks[def->ndisks++] = disk;
 
2760
    }
 
2761
    VIR_FREE(nodes);
 
2762
 
 
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"));
 
2767
        goto error;
 
2768
    }
 
2769
    if (n && VIR_ALLOC_N(def->fss, n) < 0)
 
2770
        goto no_memory;
 
2771
    for (i = 0 ; i < n ; i++) {
 
2772
        virDomainFSDefPtr fs = virDomainFSDefParseXML(conn,
 
2773
                                                      nodes[i],
 
2774
                                                      flags);
 
2775
        if (!fs)
 
2776
            goto error;
 
2777
 
 
2778
        def->fss[def->nfss++] = fs;
 
2779
    }
 
2780
    VIR_FREE(nodes);
 
2781
 
 
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"));
 
2786
        goto error;
 
2787
    }
 
2788
    if (n && VIR_ALLOC_N(def->nets, n) < 0)
 
2789
        goto no_memory;
 
2790
    for (i = 0 ; i < n ; i++) {
 
2791
        virDomainNetDefPtr net = virDomainNetDefParseXML(conn,
 
2792
                                                         caps,
 
2793
                                                         nodes[i],
 
2794
                                                         flags);
 
2795
        if (!net)
 
2796
            goto error;
 
2797
 
 
2798
        def->nets[def->nnets++] = net;
 
2799
    }
 
2800
    VIR_FREE(nodes);
 
2801
 
 
2802
 
 
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"));
 
2807
        goto error;
 
2808
    }
 
2809
    if (n && VIR_ALLOC_N(def->parallels, n) < 0)
 
2810
        goto no_memory;
 
2811
 
 
2812
    for (i = 0 ; i < n ; i++) {
 
2813
        virDomainChrDefPtr chr = virDomainChrDefParseXML(conn,
 
2814
                                                         nodes[i],
 
2815
                                                         flags);
 
2816
        if (!chr)
 
2817
            goto error;
 
2818
 
 
2819
        chr->dstPort = i;
 
2820
        def->parallels[def->nparallels++] = chr;
 
2821
    }
 
2822
    VIR_FREE(nodes);
 
2823
 
 
2824
    if ((n = virXPathNodeSet(conn, "./devices/serial", ctxt, &nodes)) < 0) {
 
2825
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
2826
                             "%s", _("cannot extract serial devices"));
 
2827
        goto error;
 
2828
    }
 
2829
    if (n && VIR_ALLOC_N(def->serials, n) < 0)
 
2830
        goto no_memory;
 
2831
 
 
2832
    for (i = 0 ; i < n ; i++) {
 
2833
        virDomainChrDefPtr chr = virDomainChrDefParseXML(conn,
 
2834
                                                         nodes[i],
 
2835
                                                         flags);
 
2836
        if (!chr)
 
2837
            goto error;
 
2838
 
 
2839
        chr->dstPort = i;
 
2840
        def->serials[def->nserials++] = chr;
 
2841
    }
 
2842
    VIR_FREE(nodes);
 
2843
 
 
2844
    if ((node = virXPathNode(conn, "./devices/console[1]", ctxt)) != NULL) {
 
2845
        virDomainChrDefPtr chr = virDomainChrDefParseXML(conn,
 
2846
                                                         node,
 
2847
                                                         flags);
 
2848
        if (!chr)
 
2849
            goto error;
 
2850
 
 
2851
        chr->dstPort = 0;
 
2852
        /*
 
2853
         * For HVM console actually created a serial device
 
2854
         * while for non-HVM it was a parvirt console
 
2855
         */
 
2856
        if (STREQ(def->os.type, "hvm")) {
 
2857
            if (def->nserials != 0) {
 
2858
                virDomainChrDefFree(chr);
 
2859
            } else {
 
2860
                if (VIR_ALLOC_N(def->serials, 1) < 0) {
 
2861
                    virDomainChrDefFree(chr);
 
2862
                    goto no_memory;
 
2863
                }
 
2864
                def->nserials = 1;
 
2865
                def->serials[0] = chr;
 
2866
            }
 
2867
        } else {
 
2868
            def->console = chr;
 
2869
        }
 
2870
    }
 
2871
 
 
2872
 
 
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"));
 
2877
        goto error;
 
2878
    }
 
2879
    if (n && VIR_ALLOC_N(def->inputs, n) < 0)
 
2880
        goto no_memory;
 
2881
 
 
2882
    for (i = 0 ; i < n ; i++) {
 
2883
        virDomainInputDefPtr input = virDomainInputDefParseXML(conn,
 
2884
                                                               def->os.type,
 
2885
                                                               nodes[i],
 
2886
                                                               flags);
 
2887
        if (!input)
 
2888
            goto error;
 
2889
 
 
2890
 
 
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);
 
2901
            continue;
 
2902
        }
 
2903
 
 
2904
        def->inputs[def->ninputs++] = input;
 
2905
    }
 
2906
    VIR_FREE(nodes);
 
2907
 
 
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"));
 
2912
        goto error;
 
2913
    }
 
2914
    if (n && VIR_ALLOC_N(def->graphics, n) < 0)
 
2915
        goto no_memory;
 
2916
    for (i = 0 ; i < n ; i++) {
 
2917
        virDomainGraphicsDefPtr graphics = virDomainGraphicsDefParseXML(conn,
 
2918
                                                                        nodes[i],
 
2919
                                                                        flags);
 
2920
        if (!graphics)
 
2921
            goto error;
 
2922
 
 
2923
        def->graphics[def->ngraphics++] = graphics;
 
2924
    }
 
2925
    VIR_FREE(nodes);
 
2926
 
 
2927
    /* If graphics are enabled, there's an implicit PS2 mouse */
 
2928
    if (def->ngraphics > 0) {
 
2929
        virDomainInputDefPtr input;
 
2930
 
 
2931
        if (VIR_ALLOC(input) < 0) {
 
2932
            virReportOOMError(conn);
 
2933
            goto error;
 
2934
        }
 
2935
        if (STREQ(def->os.type, "hvm")) {
 
2936
            input->type = VIR_DOMAIN_INPUT_TYPE_MOUSE;
 
2937
            input->bus = VIR_DOMAIN_INPUT_BUS_PS2;
 
2938
        } else {
 
2939
            input->type = VIR_DOMAIN_INPUT_TYPE_MOUSE;
 
2940
            input->bus = VIR_DOMAIN_INPUT_BUS_XEN;
 
2941
        }
 
2942
 
 
2943
        if (VIR_REALLOC_N(def->inputs, def->ninputs + 1) < 0) {
 
2944
            virDomainInputDefFree(input);
 
2945
            goto no_memory;
 
2946
        }
 
2947
        def->inputs[def->ninputs] = input;
 
2948
        def->ninputs++;
 
2949
    }
 
2950
 
 
2951
 
 
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"));
 
2956
        goto error;
 
2957
    }
 
2958
    if (n && VIR_ALLOC_N(def->sounds, n) < 0)
 
2959
        goto no_memory;
 
2960
    for (i = 0 ; i < n ; i++) {
 
2961
        int collision = 0, j;
 
2962
        virDomainSoundDefPtr sound = virDomainSoundDefParseXML(conn,
 
2963
                                                               nodes[i],
 
2964
                                                               flags);
 
2965
        if (!sound)
 
2966
            goto error;
 
2967
 
 
2968
        /* Verify there's no duplicated sound card */
 
2969
        for (j = 0 ; j < def->nsounds ; j++) {
 
2970
            if (def->sounds[j]->model == sound->model)
 
2971
                collision = 1;
 
2972
        }
 
2973
        if (collision) {
 
2974
            virDomainSoundDefFree(sound);
 
2975
            continue;
 
2976
        }
 
2977
 
 
2978
        def->sounds[def->nsounds++] = sound;
 
2979
    }
 
2980
    VIR_FREE(nodes);
 
2981
 
 
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"));
 
2986
        goto error;
 
2987
    }
 
2988
    if (n && VIR_ALLOC_N(def->videos, n) < 0)
 
2989
        goto no_memory;
 
2990
    for (i = 0 ; i < n ; i++) {
 
2991
        virDomainVideoDefPtr video = virDomainVideoDefParseXML(conn,
 
2992
                                                               nodes[i],
 
2993
                                                               def,
 
2994
                                                               flags);
 
2995
        if (!video)
 
2996
            goto error;
 
2997
        def->videos[def->nvideos++] = video;
 
2998
    }
 
2999
    VIR_FREE(nodes);
 
3000
 
 
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)
 
3006
            goto no_memory;
 
3007
        video->type = virDomainVideoDefaultType(def);
 
3008
        if (video->type < 0) {
 
3009
            virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR, "%s",
 
3010
                                 _("cannot determine default video type"));
 
3011
            VIR_FREE(video);
 
3012
            goto error;
 
3013
        }
 
3014
        video->vram = virDomainVideoDefaultRAM(def, video->type);
 
3015
        video->heads = 1;
 
3016
        if (VIR_ALLOC_N(def->videos, 1) < 0) {
 
3017
            virDomainVideoDefFree(video);
 
3018
            goto no_memory;
 
3019
        }
 
3020
        def->videos[def->nvideos++] = video;
 
3021
    }
 
3022
 
 
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"));
 
3027
        goto error;
 
3028
    }
 
3029
    if (n && VIR_ALLOC_N(def->hostdevs, n) < 0)
 
3030
        goto no_memory;
 
3031
    for (i = 0 ; i < n ; i++) {
 
3032
        virDomainHostdevDefPtr hostdev = virDomainHostdevDefParseXML(conn,
 
3033
                                                                     nodes[i],
 
3034
                                                                     flags);
 
3035
        if (!hostdev)
 
3036
            goto error;
 
3037
 
 
3038
        def->hostdevs[def->nhostdevs++] = hostdev;
 
3039
    }
 
3040
    VIR_FREE(nodes);
 
3041
 
 
3042
    /* analysis of security label */
 
3043
    if (virSecurityLabelDefParseXML(conn, def, ctxt, flags) == -1)
 
3044
        goto error;
 
3045
 
 
3046
    return def;
 
3047
 
 
3048
no_memory:
 
3049
    virReportOOMError(conn);
 
3050
    /* fallthrough */
 
3051
 
 
3052
 error:
 
3053
    VIR_FREE(tmp);
 
3054
    VIR_FREE(nodes);
 
3055
    virDomainDefFree(def);
 
3056
    return NULL;
 
3057
}
 
3058
 
 
3059
 
 
3060
static virDomainObjPtr virDomainObjParseXML(virConnectPtr conn,
 
3061
                                            virCapsPtr caps,
 
3062
                                            xmlXPathContextPtr ctxt)
 
3063
{
 
3064
    char *tmp = NULL;
 
3065
    long val;
 
3066
    xmlNodePtr config;
 
3067
    xmlNodePtr oldnode;
 
3068
    virDomainObjPtr obj;
 
3069
    char *monitorpath;
 
3070
    xmlNodePtr *nodes = NULL;
 
3071
    int n, i;
 
3072
 
 
3073
    if (!(obj = virDomainObjNew(conn)))
 
3074
        return NULL;
 
3075
 
 
3076
    if (!(config = virXPathNode(conn, "./domain", ctxt))) {
 
3077
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
3078
                             "%s", _("no domain config"));
 
3079
        goto error;
 
3080
    }
 
3081
 
 
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;
 
3087
    if (!obj->def)
 
3088
        goto error;
 
3089
 
 
3090
    if (!(tmp = virXPathString(conn, "string(./@state)", ctxt))) {
 
3091
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
3092
                             "%s", _("missing domain state"));
 
3093
        goto error;
 
3094
    }
 
3095
    if ((obj->state = virDomainStateTypeFromString(tmp)) < 0) {
 
3096
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
3097
                             _("invalid domain state '%s'"), tmp);
 
3098
        VIR_FREE(tmp);
 
3099
        goto error;
 
3100
    }
 
3101
    VIR_FREE(tmp);
 
3102
 
 
3103
    if ((virXPathLong(conn, "string(./@pid)", ctxt, &val)) < 0) {
 
3104
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
3105
                             "%s", _("invalid pid"));
 
3106
        goto error;
 
3107
    }
 
3108
    obj->pid = (pid_t)val;
 
3109
 
 
3110
    if (VIR_ALLOC(obj->monitor_chr) < 0) {
 
3111
        virReportOOMError(conn);
 
3112
        goto error;
 
3113
    }
 
3114
 
 
3115
    if (!(monitorpath =
 
3116
          virXPathString(conn, "string(./monitor[1]/@path)", ctxt))) {
 
3117
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
3118
                             "%s", _("no monitor path"));
 
3119
        goto error;
 
3120
    }
 
3121
 
 
3122
    tmp = virXPathString(conn, "string(./monitor[1]/@type)", ctxt);
 
3123
    if (tmp)
 
3124
        obj->monitor_chr->type = virDomainChrTypeFromString(tmp);
 
3125
    else
 
3126
        obj->monitor_chr->type = VIR_DOMAIN_CHR_TYPE_PTY;
 
3127
    VIR_FREE(tmp);
 
3128
 
 
3129
    switch (obj->monitor_chr->type) {
 
3130
    case VIR_DOMAIN_CHR_TYPE_PTY:
 
3131
        obj->monitor_chr->data.file.path = monitorpath;
 
3132
        break;
 
3133
    case VIR_DOMAIN_CHR_TYPE_UNIX:
 
3134
        obj->monitor_chr->data.nix.path = monitorpath;
 
3135
        break;
 
3136
    default:
 
3137
        VIR_FREE(monitorpath);
 
3138
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
3139
                             _("unsupported monitor type '%s'"),
 
3140
                             virDomainChrTypeToString(obj->monitor_chr->type));
 
3141
        break;
 
3142
    }
 
3143
 
 
3144
    n = virXPathNodeSet(conn, "./vcpus/vcpu", ctxt, &nodes);
 
3145
    if (n < 0)
 
3146
        goto error;
 
3147
    if (n) {
 
3148
        obj->nvcpupids = n;
 
3149
        if (VIR_REALLOC_N(obj->vcpupids, obj->nvcpupids) < 0)
 
3150
            goto error;
 
3151
 
 
3152
        for (i = 0 ; i < n ; i++) {
 
3153
            char *pidstr = virXMLPropString(nodes[i], "pid");
 
3154
            if (!pidstr)
 
3155
                goto error;
 
3156
 
 
3157
            if (virStrToLong_i(pidstr, NULL, 10, &(obj->vcpupids[i])) < 0) {
 
3158
                VIR_FREE(pidstr);
 
3159
                goto error;
 
3160
            }
 
3161
            VIR_FREE(pidstr);
 
3162
        }
 
3163
        VIR_FREE(nodes);
 
3164
    }
 
3165
 
 
3166
    return obj;
 
3167
 
 
3168
error:
 
3169
    VIR_FREE(nodes);
 
3170
    virDomainChrDefFree(obj->monitor_chr);
 
3171
    virDomainObjFree(obj);
 
3172
    return NULL;
 
3173
}
 
3174
 
 
3175
 
 
3176
/* Called from SAX on parsing errors in the XML. */
 
3177
static void
 
3178
catchXMLError (void *ctx, const char *msg ATTRIBUTE_UNUSED, ...)
 
3179
{
 
3180
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
 
3181
 
 
3182
    if (ctxt) {
 
3183
        virConnectPtr conn = ctxt->_private;
 
3184
 
 
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);
 
3192
        }
 
3193
    }
 
3194
}
 
3195
 
 
3196
virDomainDefPtr virDomainDefParseString(virConnectPtr conn,
 
3197
                                        virCapsPtr caps,
 
3198
                                        const char *xmlStr,
 
3199
                                        int flags)
 
3200
{
 
3201
    xmlParserCtxtPtr pctxt;
 
3202
    xmlDocPtr xml = NULL;
 
3203
    xmlNodePtr root;
 
3204
    virDomainDefPtr def = NULL;
 
3205
 
 
3206
    /* Set up a parser context so we can catch the details of XML errors. */
 
3207
    pctxt = xmlNewParserCtxt ();
 
3208
    if (!pctxt || !pctxt->sax)
 
3209
        goto cleanup;
 
3210
    pctxt->sax->error = catchXMLError;
 
3211
    pctxt->_private = conn;
 
3212
 
 
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);
 
3217
    if (!xml) {
 
3218
        if (virGetLastError() == NULL)
 
3219
              virDomainReportError(conn, VIR_ERR_XML_ERROR,
 
3220
                                   "%s", _("failed to parse xml document"));
 
3221
        goto cleanup;
 
3222
    }
 
3223
 
 
3224
    if ((root = xmlDocGetRootElement(xml)) == NULL) {
 
3225
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
3226
                              "%s", _("missing root element"));
 
3227
        goto cleanup;
 
3228
    }
 
3229
 
 
3230
    def = virDomainDefParseNode(conn, caps, xml, root, flags);
 
3231
 
 
3232
cleanup:
 
3233
    xmlFreeParserCtxt (pctxt);
 
3234
    xmlFreeDoc (xml);
 
3235
    return def;
 
3236
}
 
3237
 
 
3238
virDomainDefPtr virDomainDefParseFile(virConnectPtr conn,
 
3239
                                      virCapsPtr caps,
 
3240
                                      const char *filename, int flags)
 
3241
{
 
3242
    xmlParserCtxtPtr pctxt;
 
3243
    xmlDocPtr xml = NULL;
 
3244
    xmlNodePtr root;
 
3245
    virDomainDefPtr def = NULL;
 
3246
 
 
3247
    /* Set up a parser context so we can catch the details of XML errors. */
 
3248
    pctxt = xmlNewParserCtxt ();
 
3249
    if (!pctxt || !pctxt->sax)
 
3250
        goto cleanup;
 
3251
    pctxt->sax->error = catchXMLError;
 
3252
    pctxt->_private = conn;
 
3253
 
 
3254
    if (conn) virResetError (&conn->err);
 
3255
    xml = xmlCtxtReadFile (pctxt, filename, NULL,
 
3256
                           XML_PARSE_NOENT | XML_PARSE_NONET |
 
3257
                           XML_PARSE_NOWARNING);
 
3258
    if (!xml) {
 
3259
        if (virGetLastError() == NULL)
 
3260
              virDomainReportError(conn, VIR_ERR_XML_ERROR,
 
3261
                                   "%s", _("failed to parse xml document"));
 
3262
        goto cleanup;
 
3263
    }
 
3264
 
 
3265
    if ((root = xmlDocGetRootElement(xml)) == NULL) {
 
3266
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
3267
                              "%s", _("missing root element"));
 
3268
        goto cleanup;
 
3269
    }
 
3270
 
 
3271
    def = virDomainDefParseNode(conn, caps, xml, root, flags);
 
3272
 
 
3273
cleanup:
 
3274
    xmlFreeParserCtxt (pctxt);
 
3275
    xmlFreeDoc (xml);
 
3276
    return def;
 
3277
}
 
3278
 
 
3279
 
 
3280
virDomainDefPtr virDomainDefParseNode(virConnectPtr conn,
 
3281
                                      virCapsPtr caps,
 
3282
                                      xmlDocPtr xml,
 
3283
                                      xmlNodePtr root,
 
3284
                                      int flags)
 
3285
{
 
3286
    xmlXPathContextPtr ctxt = NULL;
 
3287
    virDomainDefPtr def = NULL;
 
3288
 
 
3289
    if (!xmlStrEqual(root->name, BAD_CAST "domain")) {
 
3290
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
3291
                              "%s", _("incorrect root element"));
 
3292
        goto cleanup;
 
3293
    }
 
3294
 
 
3295
    ctxt = xmlXPathNewContext(xml);
 
3296
    if (ctxt == NULL) {
 
3297
        virReportOOMError(conn);
 
3298
        goto cleanup;
 
3299
    }
 
3300
 
 
3301
    ctxt->node = root;
 
3302
    def = virDomainDefParseXML(conn, caps, ctxt, flags);
 
3303
 
 
3304
cleanup:
 
3305
    xmlXPathFreeContext(ctxt);
 
3306
    return def;
 
3307
}
 
3308
 
 
3309
 
 
3310
virDomainObjPtr virDomainObjParseFile(virConnectPtr conn,
 
3311
                                      virCapsPtr caps,
 
3312
                                      const char *filename)
 
3313
{
 
3314
    xmlParserCtxtPtr pctxt;
 
3315
    xmlDocPtr xml = NULL;
 
3316
    xmlNodePtr root;
 
3317
    virDomainObjPtr obj = NULL;
 
3318
 
 
3319
    /* Set up a parser context so we can catch the details of XML errors. */
 
3320
    pctxt = xmlNewParserCtxt ();
 
3321
    if (!pctxt || !pctxt->sax)
 
3322
        goto cleanup;
 
3323
    pctxt->sax->error = catchXMLError;
 
3324
    pctxt->_private = conn;
 
3325
 
 
3326
    if (conn) virResetError (&conn->err);
 
3327
    xml = xmlCtxtReadFile (pctxt, filename, NULL,
 
3328
                           XML_PARSE_NOENT | XML_PARSE_NONET |
 
3329
                           XML_PARSE_NOWARNING);
 
3330
    if (!xml) {
 
3331
        if (virGetLastError() == NULL)
 
3332
              virDomainReportError(conn, VIR_ERR_XML_ERROR,
 
3333
                                   "%s", _("failed to parse xml document"));
 
3334
        goto cleanup;
 
3335
    }
 
3336
 
 
3337
    if ((root = xmlDocGetRootElement(xml)) == NULL) {
 
3338
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
3339
                              "%s", _("missing root element"));
 
3340
        goto cleanup;
 
3341
    }
 
3342
 
 
3343
    obj = virDomainObjParseNode(conn, caps, xml, root);
 
3344
 
 
3345
cleanup:
 
3346
    xmlFreeParserCtxt (pctxt);
 
3347
    xmlFreeDoc (xml);
 
3348
    return obj;
 
3349
}
 
3350
 
 
3351
 
 
3352
virDomainObjPtr virDomainObjParseNode(virConnectPtr conn,
 
3353
                                      virCapsPtr caps,
 
3354
                                      xmlDocPtr xml,
 
3355
                                      xmlNodePtr root)
 
3356
{
 
3357
    xmlXPathContextPtr ctxt = NULL;
 
3358
    virDomainObjPtr obj = NULL;
 
3359
 
 
3360
    if (!xmlStrEqual(root->name, BAD_CAST "domstatus")) {
 
3361
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
3362
                             "%s", _("incorrect root element"));
 
3363
        goto cleanup;
 
3364
    }
 
3365
 
 
3366
    ctxt = xmlXPathNewContext(xml);
 
3367
    if (ctxt == NULL) {
 
3368
        virReportOOMError(conn);
 
3369
        goto cleanup;
 
3370
    }
 
3371
 
 
3372
    ctxt->node = root;
 
3373
    obj = virDomainObjParseXML(conn, caps, ctxt);
 
3374
 
 
3375
cleanup:
 
3376
    xmlXPathFreeContext(ctxt);
 
3377
    return obj;
 
3378
}
 
3379
 
 
3380
#endif /* ! PROXY */
 
3381
 
 
3382
/************************************************************************
 
3383
 *                                                                        *
 
3384
 * Parser and converter for the CPUset strings used in libvirt                *
 
3385
 *                                                                        *
 
3386
 ************************************************************************/
 
3387
/**
 
3388
 * virDomainCpuNumberParse
 
3389
 * @str: pointer to the char pointer used
 
3390
 * @maxcpu: maximum CPU number allowed
 
3391
 *
 
3392
 * Parse a CPU number
 
3393
 *
 
3394
 * Returns the CPU number or -1 in case of error. @str will be
 
3395
 *         updated to skip the number.
 
3396
 */
 
3397
static int
 
3398
virDomainCpuNumberParse(const char **str, int maxcpu)
 
3399
{
 
3400
    int ret = 0;
 
3401
    const char *cur = *str;
 
3402
 
 
3403
    if (!c_isdigit(*cur))
 
3404
        return (-1);
 
3405
 
 
3406
    while (c_isdigit(*cur)) {
 
3407
        ret = ret * 10 + (*cur - '0');
 
3408
        if (ret >= maxcpu)
 
3409
            return (-1);
 
3410
        cur++;
 
3411
    }
 
3412
    *str = cur;
 
3413
    return (ret);
 
3414
}
 
3415
 
 
3416
/**
 
3417
 * virDomainCpuSetFormat:
 
3418
 * @conn: connection
 
3419
 * @cpuset: pointer to a char array for the CPU set
 
3420
 * @maxcpu: number of elements available in @cpuset
 
3421
 *
 
3422
 * Serialize the cpuset to a string
 
3423
 *
 
3424
 * Returns the new string NULL in case of error. The string need to be
 
3425
 *         freed by the caller.
 
3426
 */
 
3427
char *
 
3428
virDomainCpuSetFormat(virConnectPtr conn, char *cpuset, int maxcpu)
 
3429
{
 
3430
    virBuffer buf = VIR_BUFFER_INITIALIZER;
 
3431
    int start, cur;
 
3432
    int first = 1;
 
3433
 
 
3434
    if ((cpuset == NULL) || (maxcpu <= 0) || (maxcpu > 100000))
 
3435
        return (NULL);
 
3436
 
 
3437
    cur = 0;
 
3438
    start = -1;
 
3439
    while (cur < maxcpu) {
 
3440
        if (cpuset[cur]) {
 
3441
            if (start == -1)
 
3442
                start = cur;
 
3443
        } else if (start != -1) {
 
3444
            if (!first)
 
3445
                virBufferAddLit(&buf, ",");
 
3446
            else
 
3447
                first = 0;
 
3448
            if (cur == start + 1)
 
3449
                virBufferVSprintf(&buf, "%d", start);
 
3450
            else
 
3451
                virBufferVSprintf(&buf, "%d-%d", start, cur - 1);
 
3452
            start = -1;
 
3453
        }
 
3454
        cur++;
 
3455
    }
 
3456
    if (start != -1) {
 
3457
        if (!first)
 
3458
            virBufferAddLit(&buf, ",");
 
3459
        if (maxcpu == start + 1)
 
3460
            virBufferVSprintf(&buf, "%d", start);
 
3461
        else
 
3462
            virBufferVSprintf(&buf, "%d-%d", start, maxcpu - 1);
 
3463
    }
 
3464
 
 
3465
    if (virBufferError(&buf)) {
 
3466
        virReportOOMError(conn);
 
3467
        return NULL;
 
3468
    }
 
3469
 
 
3470
    return virBufferContentAndReset(&buf);
 
3471
}
 
3472
 
 
3473
/**
 
3474
 * virDomainCpuSetParse:
 
3475
 * @conn: connection
 
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
 
3480
 *
 
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.
 
3484
 *
 
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
 
3488
 */
 
3489
int
 
3490
virDomainCpuSetParse(virConnectPtr conn, const char **str, char sep,
 
3491
                     char *cpuset, int maxcpu)
 
3492
{
 
3493
    const char *cur;
 
3494
    int ret = 0;
 
3495
    int i, start, last;
 
3496
    int neg = 0;
 
3497
 
 
3498
    if ((str == NULL) || (cpuset == NULL) || (maxcpu <= 0) ||
 
3499
        (maxcpu > 100000))
 
3500
        return (-1);
 
3501
 
 
3502
    cur = *str;
 
3503
    virSkipSpaces(&cur);
 
3504
    if (*cur == 0)
 
3505
        goto parse_error;
 
3506
 
 
3507
    /* initialize cpumap to all 0s */
 
3508
    for (i = 0; i < maxcpu; i++)
 
3509
        cpuset[i] = 0;
 
3510
    ret = 0;
 
3511
 
 
3512
    while ((*cur != 0) && (*cur != sep)) {
 
3513
        /*
 
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
 
3518
         */
 
3519
        if (*cur == '^') {
 
3520
            cur++;
 
3521
            neg = 1;
 
3522
        }
 
3523
 
 
3524
        if (!c_isdigit(*cur))
 
3525
            goto parse_error;
 
3526
        start = virDomainCpuNumberParse(&cur, maxcpu);
 
3527
        if (start < 0)
 
3528
            goto parse_error;
 
3529
        virSkipSpaces(&cur);
 
3530
        if ((*cur == ',') || (*cur == 0) || (*cur == sep)) {
 
3531
            if (neg) {
 
3532
                if (cpuset[start] == 1) {
 
3533
                    cpuset[start] = 0;
 
3534
                    ret--;
 
3535
                }
 
3536
            } else {
 
3537
                if (cpuset[start] == 0) {
 
3538
                    cpuset[start] = 1;
 
3539
                    ret++;
 
3540
                }
 
3541
            }
 
3542
        } else if (*cur == '-') {
 
3543
            if (neg)
 
3544
                goto parse_error;
 
3545
            cur++;
 
3546
            virSkipSpaces(&cur);
 
3547
            last = virDomainCpuNumberParse(&cur, maxcpu);
 
3548
            if (last < start)
 
3549
                goto parse_error;
 
3550
            for (i = start; i <= last; i++) {
 
3551
                if (cpuset[i] == 0) {
 
3552
                    cpuset[i] = 1;
 
3553
                    ret++;
 
3554
                }
 
3555
            }
 
3556
            virSkipSpaces(&cur);
 
3557
        }
 
3558
        if (*cur == ',') {
 
3559
            cur++;
 
3560
            virSkipSpaces(&cur);
 
3561
            neg = 0;
 
3562
        } else if ((*cur == 0) || (*cur == sep)) {
 
3563
            break;
 
3564
        } else
 
3565
            goto parse_error;
 
3566
    }
 
3567
    *str = cur;
 
3568
    return (ret);
 
3569
 
 
3570
  parse_error:
 
3571
    virDomainReportError(conn, VIR_ERR_XEN_CALL,
 
3572
                         "%s", _("topology cpuset syntax error"));
 
3573
    return (-1);
 
3574
}
 
3575
 
 
3576
 
 
3577
static int
 
3578
virDomainLifecycleDefFormat(virConnectPtr conn,
 
3579
                            virBufferPtr buf,
 
3580
                            int type,
 
3581
                            const char *name)
 
3582
{
 
3583
    const char *typeStr = virDomainLifecycleTypeToString(type);
 
3584
    if (!typeStr) {
 
3585
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
3586
                             _("unexpected lifecycle type %d"), type);
 
3587
        return -1;
 
3588
    }
 
3589
 
 
3590
    virBufferVSprintf(buf, "  <%s>%s</%s>\n", name, typeStr, name);
 
3591
 
 
3592
    return 0;
 
3593
}
 
3594
 
 
3595
 
 
3596
static int
 
3597
virDomainDiskDefFormat(virConnectPtr conn,
 
3598
                       virBufferPtr buf,
 
3599
                       virDomainDiskDefPtr def,
 
3600
                       int flags)
 
3601
{
 
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);
 
3606
 
 
3607
    if (!type) {
 
3608
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
3609
                             _("unexpected disk type %d"), def->type);
 
3610
        return -1;
 
3611
    }
 
3612
    if (!device) {
 
3613
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
3614
                             _("unexpected disk device %d"), def->device);
 
3615
        return -1;
 
3616
    }
 
3617
    if (!bus) {
 
3618
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
3619
                             _("unexpected disk bus %d"), def->bus);
 
3620
        return -1;
 
3621
    }
 
3622
    if (!cachemode) {
 
3623
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
3624
                             _("unexpected disk cache mode %d"), def->cachemode);
 
3625
        return -1;
 
3626
    }
 
3627
 
 
3628
    virBufferVSprintf(buf,
 
3629
                      "    <disk type='%s' device='%s'>\n",
 
3630
                      type, device);
 
3631
 
 
3632
    if (def->driverName) {
 
3633
        virBufferVSprintf(buf, "      <driver name='%s'", def->driverName);
 
3634
        if (def->driverType)
 
3635
            virBufferVSprintf(buf, " type='%s'", def->driverType);
 
3636
        if (def->cachemode)
 
3637
            virBufferVSprintf(buf, " cache='%s'", cachemode);
 
3638
        virBufferVSprintf(buf, "/>\n");
 
3639
    }
 
3640
 
 
3641
    if (def->src) {
 
3642
        if (def->type == VIR_DOMAIN_DISK_TYPE_FILE)
 
3643
            virBufferEscapeString(buf, "      <source file='%s'/>\n",
 
3644
                                  def->src);
 
3645
        else
 
3646
            virBufferEscapeString(buf, "      <source dev='%s'/>\n",
 
3647
                                  def->src);
 
3648
    }
 
3649
 
 
3650
    virBufferVSprintf(buf, "      <target dev='%s' bus='%s'/>\n",
 
3651
                      def->dst, bus);
 
3652
 
 
3653
    if (def->readonly)
 
3654
        virBufferAddLit(buf, "      <readonly/>\n");
 
3655
    if (def->shared)
 
3656
        virBufferAddLit(buf, "      <shareable/>\n");
 
3657
    if (def->serial)
 
3658
        virBufferEscapeString(buf, "      <serial>%s</serial>\n",
 
3659
                              def->serial);
 
3660
    if (def->encryption != NULL &&
 
3661
        virStorageEncryptionFormat(conn, buf, def->encryption) < 0)
 
3662
        return -1;
 
3663
 
 
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,
 
3669
                              def->pci_addr.bus,
 
3670
                              def->pci_addr.slot);
 
3671
        virBufferAddLit(buf, "/>\n");
 
3672
    }
 
3673
 
 
3674
    virBufferAddLit(buf, "    </disk>\n");
 
3675
 
 
3676
    return 0;
 
3677
}
 
3678
 
 
3679
static int
 
3680
virDomainFSDefFormat(virConnectPtr conn,
 
3681
                     virBufferPtr buf,
 
3682
                     virDomainFSDefPtr def)
 
3683
{
 
3684
    const char *type = virDomainFSTypeToString(def->type);
 
3685
 
 
3686
    if (!type) {
 
3687
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
3688
                             _("unexpected filesystem type %d"), def->type);
 
3689
        return -1;
 
3690
    }
 
3691
 
 
3692
    virBufferVSprintf(buf,
 
3693
                      "    <filesystem type='%s'>\n",
 
3694
                      type);
 
3695
 
 
3696
    if (def->src) {
 
3697
        switch (def->type) {
 
3698
        case VIR_DOMAIN_FS_TYPE_MOUNT:
 
3699
            virBufferEscapeString(buf, "      <source dir='%s'/>\n",
 
3700
                                  def->src);
 
3701
            break;
 
3702
 
 
3703
        case VIR_DOMAIN_FS_TYPE_BLOCK:
 
3704
            virBufferEscapeString(buf, "      <source dev='%s'/>\n",
 
3705
                                  def->src);
 
3706
            break;
 
3707
 
 
3708
        case VIR_DOMAIN_FS_TYPE_FILE:
 
3709
            virBufferEscapeString(buf, "      <source file='%s'/>\n",
 
3710
                                  def->src);
 
3711
            break;
 
3712
 
 
3713
        case VIR_DOMAIN_FS_TYPE_TEMPLATE:
 
3714
            virBufferEscapeString(buf, "      <source name='%s'/>\n",
 
3715
                                  def->src);
 
3716
        }
 
3717
    }
 
3718
 
 
3719
    virBufferVSprintf(buf, "      <target dir='%s'/>\n",
 
3720
                      def->dst);
 
3721
 
 
3722
    if (def->readonly)
 
3723
        virBufferAddLit(buf, "      <readonly/>\n");
 
3724
 
 
3725
    virBufferAddLit(buf, "    </filesystem>\n");
 
3726
 
 
3727
    return 0;
 
3728
}
 
3729
 
 
3730
static int
 
3731
virDomainNetDefFormat(virConnectPtr conn,
 
3732
                      virBufferPtr buf,
 
3733
                      virDomainNetDefPtr def,
 
3734
                      int flags)
 
3735
{
 
3736
    const char *type = virDomainNetTypeToString(def->type);
 
3737
 
 
3738
    if (!type) {
 
3739
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
3740
                             _("unexpected net type %d"), def->type);
 
3741
        return -1;
 
3742
    }
 
3743
 
 
3744
    virBufferVSprintf(buf, "    <interface type='%s'>\n", type);
 
3745
 
 
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]);
 
3750
 
 
3751
    switch (def->type) {
 
3752
    case VIR_DOMAIN_NET_TYPE_NETWORK:
 
3753
        virBufferEscapeString(buf, "      <source network='%s'/>\n",
 
3754
                              def->data.network.name);
 
3755
        break;
 
3756
 
 
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);
 
3767
        break;
 
3768
 
 
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);
 
3778
        break;
 
3779
 
 
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);
 
3786
        else
 
3787
            virBufferVSprintf(buf, "      <source port='%d'/>\n",
 
3788
                              def->data.socket.port);
 
3789
        break;
 
3790
 
 
3791
    case VIR_DOMAIN_NET_TYPE_INTERNAL:
 
3792
        virBufferEscapeString(buf, "      <source name='%s'/>\n",
 
3793
                              def->data.internal.name);
 
3794
        break;
 
3795
 
 
3796
    }
 
3797
 
 
3798
    if (def->ifname)
 
3799
        virBufferEscapeString(buf, "      <target dev='%s'/>\n",
 
3800
                              def->ifname);
 
3801
    if (def->model)
 
3802
        virBufferEscapeString(buf, "      <model type='%s'/>\n",
 
3803
                              def->model);
 
3804
 
 
3805
    if (flags & VIR_DOMAIN_XML_INTERNAL_STATUS) {
 
3806
        virBufferAddLit(buf, "      <state");
 
3807
        if (def->nic_name)
 
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,
 
3814
                              def->pci_addr.bus,
 
3815
                              def->pci_addr.slot);
 
3816
        if (def->vlan > 0)
 
3817
            virBufferVSprintf(buf, " vlan='%d'", def->vlan);
 
3818
        virBufferAddLit(buf, "/>\n");
 
3819
    }
 
3820
 
 
3821
    virBufferAddLit(buf, "    </interface>\n");
 
3822
 
 
3823
    return 0;
 
3824
}
 
3825
 
 
3826
 
 
3827
static int
 
3828
virDomainChrDefFormat(virConnectPtr conn,
 
3829
                      virBufferPtr buf,
 
3830
                      virDomainChrDefPtr def,
 
3831
                      const char *name,
 
3832
                      int flags)
 
3833
{
 
3834
    const char *type = virDomainChrTypeToString(def->type);
 
3835
 
 
3836
    if (!type) {
 
3837
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
3838
                             _("unexpected char type %d"), def->type);
 
3839
        return -1;
 
3840
    }
 
3841
 
 
3842
    /* Compat with legacy  <console tty='/dev/pts/5'/> syntax */
 
3843
    virBufferVSprintf(buf, "    <%s type='%s'",
 
3844
                      name, type);
 
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);
 
3851
    } else {
 
3852
        virBufferAddLit(buf, ">\n");
 
3853
    }
 
3854
 
 
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:
 
3859
        /* nada */
 
3860
        break;
 
3861
 
 
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);
 
3870
        }
 
3871
        break;
 
3872
 
 
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);
 
3885
        }
 
3886
 
 
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);
 
3898
        }
 
3899
        break;
 
3900
 
 
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",
 
3904
                          def->data.tcp.host,
 
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");
 
3910
        break;
 
3911
 
 
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);
 
3917
        break;
 
3918
    }
 
3919
 
 
3920
    virBufferVSprintf(buf, "      <target port='%d'/>\n",
 
3921
                      def->dstPort);
 
3922
 
 
3923
    virBufferVSprintf(buf, "    </%s>\n",
 
3924
                      name);
 
3925
 
 
3926
    return 0;
 
3927
}
 
3928
 
 
3929
static int
 
3930
virDomainSoundDefFormat(virConnectPtr conn,
 
3931
                        virBufferPtr buf,
 
3932
                        virDomainSoundDefPtr def)
 
3933
{
 
3934
    const char *model = virDomainSoundModelTypeToString(def->model);
 
3935
 
 
3936
    if (!model) {
 
3937
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
3938
                             _("unexpected sound model %d"), def->model);
 
3939
        return -1;
 
3940
    }
 
3941
 
 
3942
    virBufferVSprintf(buf, "    <sound model='%s'/>\n",
 
3943
                      model);
 
3944
 
 
3945
    return 0;
 
3946
}
 
3947
 
 
3948
 
 
3949
static void
 
3950
virDomainVideoAccelDefFormat(virBufferPtr buf,
 
3951
                             virDomainVideoAccelDefPtr def)
 
3952
{
 
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");
 
3958
}
 
3959
 
 
3960
 
 
3961
static int
 
3962
virDomainVideoDefFormat(virConnectPtr conn,
 
3963
                        virBufferPtr buf,
 
3964
                        virDomainVideoDefPtr def)
 
3965
{
 
3966
    const char *model = virDomainVideoTypeToString(def->type);
 
3967
 
 
3968
    if (!model) {
 
3969
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
3970
                             _("unexpected video model %d"), def->type);
 
3971
        return -1;
 
3972
    }
 
3973
 
 
3974
    virBufferAddLit(buf, "    <video>\n");
 
3975
    virBufferVSprintf(buf, "      <model type='%s'",
 
3976
                      model);
 
3977
    if (def->vram)
 
3978
        virBufferVSprintf(buf, " vram='%u'", def->vram);
 
3979
    if (def->heads)
 
3980
        virBufferVSprintf(buf, " heads='%u'", def->heads);
 
3981
    if (def->accel) {
 
3982
        virBufferAddLit(buf, ">\n");
 
3983
        virDomainVideoAccelDefFormat(buf, def->accel);
 
3984
        virBufferAddLit(buf, "      </model>\n");
 
3985
    } else {
 
3986
        virBufferAddLit(buf, "/>\n");
 
3987
    }
 
3988
 
 
3989
    virBufferAddLit(buf, "    </video>\n");
 
3990
 
 
3991
    return 0;
 
3992
}
 
3993
 
 
3994
static int
 
3995
virDomainInputDefFormat(virConnectPtr conn,
 
3996
                        virBufferPtr buf,
 
3997
                        virDomainInputDefPtr def)
 
3998
{
 
3999
    const char *type = virDomainInputTypeToString(def->type);
 
4000
    const char *bus = virDomainInputBusTypeToString(def->bus);
 
4001
 
 
4002
    if (!type) {
 
4003
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
4004
                             _("unexpected input type %d"), def->type);
 
4005
        return -1;
 
4006
    }
 
4007
    if (!bus) {
 
4008
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
4009
                             _("unexpected input bus type %d"), def->bus);
 
4010
        return -1;
 
4011
    }
 
4012
 
 
4013
    virBufferVSprintf(buf, "    <input type='%s' bus='%s'/>\n",
 
4014
                      type, bus);
 
4015
 
 
4016
    return 0;
 
4017
}
 
4018
 
 
4019
 
 
4020
static int
 
4021
virDomainGraphicsDefFormat(virConnectPtr conn,
 
4022
                           virBufferPtr buf,
 
4023
                           virDomainDefPtr vm,
 
4024
                           virDomainGraphicsDefPtr def,
 
4025
                           int flags)
 
4026
{
 
4027
    const char *type = virDomainGraphicsTypeToString(def->type);
 
4028
 
 
4029
    if (!type) {
 
4030
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
4031
                             _("unexpected net type %d"), def->type);
 
4032
        return -1;
 
4033
    }
 
4034
 
 
4035
    virBufferVSprintf(buf, "    <graphics type='%s'", type);
 
4036
 
 
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'");
 
4045
 
 
4046
        virBufferVSprintf(buf, " autoport='%s'",
 
4047
                          def->data.vnc.autoport ? "yes" : "no");
 
4048
 
 
4049
        if (def->data.vnc.listenAddr)
 
4050
            virBufferVSprintf(buf, " listen='%s'",
 
4051
                              def->data.vnc.listenAddr);
 
4052
 
 
4053
        if (def->data.vnc.keymap)
 
4054
            virBufferEscapeString(buf, " keymap='%s'",
 
4055
                                  def->data.vnc.keymap);
 
4056
 
 
4057
        if (def->data.vnc.passwd &&
 
4058
            (flags & VIR_DOMAIN_XML_SECURE))
 
4059
            virBufferEscapeString(buf, " passwd='%s'",
 
4060
                                  def->data.vnc.passwd);
 
4061
 
 
4062
        break;
 
4063
 
 
4064
    case VIR_DOMAIN_GRAPHICS_TYPE_SDL:
 
4065
        if (def->data.sdl.display)
 
4066
            virBufferEscapeString(buf, " display='%s'",
 
4067
                                  def->data.sdl.display);
 
4068
 
 
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'");
 
4074
 
 
4075
        break;
 
4076
 
 
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'");
 
4083
 
 
4084
        if (def->data.rdp.autoport)
 
4085
            virBufferVSprintf(buf, " autoport='yes'");
 
4086
 
 
4087
        if (def->data.rdp.replaceUser)
 
4088
            virBufferVSprintf(buf, " replaceUser='yes'");
 
4089
 
 
4090
        if (def->data.rdp.multiUser)
 
4091
            virBufferVSprintf(buf, " multiUser='yes'");
 
4092
 
 
4093
        if (def->data.rdp.listenAddr)
 
4094
            virBufferVSprintf(buf, " listen='%s'", def->data.rdp.listenAddr);
 
4095
 
 
4096
        break;
 
4097
 
 
4098
    case VIR_DOMAIN_GRAPHICS_TYPE_DESKTOP:
 
4099
        if (def->data.desktop.display)
 
4100
            virBufferEscapeString(buf, " display='%s'",
 
4101
                                  def->data.desktop.display);
 
4102
 
 
4103
        if (def->data.desktop.fullscreen)
 
4104
            virBufferAddLit(buf, " fullscreen='yes'");
 
4105
 
 
4106
        break;
 
4107
 
 
4108
    }
 
4109
 
 
4110
    virBufferAddLit(buf, "/>\n");
 
4111
 
 
4112
    return 0;
 
4113
}
 
4114
 
 
4115
 
 
4116
static int
 
4117
virDomainHostdevDefFormat(virConnectPtr conn,
 
4118
                          virBufferPtr buf,
 
4119
                          virDomainHostdevDefPtr def,
 
4120
                          int flags)
 
4121
{
 
4122
    const char *mode = virDomainHostdevModeTypeToString(def->mode);
 
4123
    const char *type;
 
4124
 
 
4125
    if (!mode || def->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) {
 
4126
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
4127
                             _("unexpected hostdev mode %d"), def->mode);
 
4128
        return -1;
 
4129
    }
 
4130
 
 
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);
 
4136
        return -1;
 
4137
    }
 
4138
 
 
4139
    virBufferVSprintf(buf, "    <hostdev mode='%s' type='%s' managed='%s'>\n",
 
4140
                      mode, type, def->managed ? "yes" : "no");
 
4141
    virBufferAddLit(buf, "      <source>\n");
 
4142
 
 
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);
 
4149
        } else {
 
4150
            virBufferVSprintf(buf, "        <address bus='%d' device='%d'/>\n",
 
4151
                              def->source.subsys.u.usb.bus,
 
4152
                              def->source.subsys.u.usb.device);
 
4153
        }
 
4154
    }
 
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");
 
4169
        }
 
4170
    }
 
4171
 
 
4172
    virBufferAddLit(buf, "      </source>\n");
 
4173
    virBufferAddLit(buf, "    </hostdev>\n");
 
4174
 
 
4175
    return 0;
 
4176
}
 
4177
 
 
4178
 
 
4179
char *virDomainDefFormat(virConnectPtr conn,
 
4180
                         virDomainDefPtr def,
 
4181
                         int flags)
 
4182
{
 
4183
    virBuffer buf = VIR_BUFFER_INITIALIZER;
 
4184
    unsigned char *uuid;
 
4185
    char uuidstr[VIR_UUID_STRING_BUFLEN];
 
4186
    const char *type = NULL, *tmp;
 
4187
    int n, allones = 1;
 
4188
 
 
4189
    if (!(type = virDomainVirtTypeToString(def->virtType))) {
 
4190
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
4191
                         _("unexpected domain type %d"), def->virtType);
 
4192
        goto cleanup;
 
4193
    }
 
4194
 
 
4195
    if (def->id >= 0)
 
4196
        virBufferVSprintf(&buf, "<domain type='%s' id='%d'>\n", type, def->id);
 
4197
    else
 
4198
        virBufferVSprintf(&buf, "<domain type='%s'>\n", type);
 
4199
 
 
4200
    virBufferEscapeString(&buf, "  <name>%s</name>\n", def->name);
 
4201
 
 
4202
    uuid = def->uuid;
 
4203
    virUUIDFormat(uuid, uuidstr);
 
4204
    virBufferVSprintf(&buf, "  <uuid>%s</uuid>\n", uuidstr);
 
4205
 
 
4206
    if (def->description)
 
4207
        virBufferEscapeString(&buf, "  <description>%s</description>\n",
 
4208
                              def->description);
 
4209
 
 
4210
    virBufferVSprintf(&buf, "  <memory>%lu</memory>\n", def->maxmem);
 
4211
    virBufferVSprintf(&buf, "  <currentMemory>%lu</currentMemory>\n",
 
4212
                      def->memory);
 
4213
    if (def->hugepage_backed) {
 
4214
        virBufferAddLit(&buf, "  <memoryBacking>\n");
 
4215
        virBufferAddLit(&buf, "    <hugepages/>\n");
 
4216
        virBufferAddLit(&buf, "  </memoryBacking>\n");
 
4217
    }
 
4218
    for (n = 0 ; n < def->cpumasklen ; n++)
 
4219
        if (def->cpumask[n] != 1)
 
4220
            allones = 0;
 
4221
 
 
4222
    if (allones) {
 
4223
        virBufferVSprintf(&buf, "  <vcpu>%lu</vcpu>\n", def->vcpus);
 
4224
    } else {
 
4225
        char *cpumask = NULL;
 
4226
        if ((cpumask =
 
4227
             virDomainCpuSetFormat(conn, def->cpumask, def->cpumasklen)) == NULL)
 
4228
            goto cleanup;
 
4229
        virBufferVSprintf(&buf, "  <vcpu cpuset='%s'>%lu</vcpu>\n",
 
4230
                          cpumask, def->vcpus);
 
4231
        VIR_FREE(cpumask);
 
4232
    }
 
4233
 
 
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);
 
4240
    }
 
4241
    virBufferAddLit(&buf, "  <os>\n");
 
4242
 
 
4243
    virBufferAddLit(&buf, "    <type");
 
4244
    if (def->os.arch)
 
4245
        virBufferVSprintf(&buf, " arch='%s'", def->os.arch);
 
4246
    if (def->os.machine)
 
4247
        virBufferVSprintf(&buf, " machine='%s'", def->os.machine);
 
4248
    /*
 
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
 
4252
     */
 
4253
    if (def->virtType == VIR_DOMAIN_VIRT_XEN &&
 
4254
        STREQ(def->os.type, "xen"))
 
4255
        virBufferVSprintf(&buf, ">%s</type>\n", "linux");
 
4256
    else
 
4257
        virBufferVSprintf(&buf, ">%s</type>\n", def->os.type);
 
4258
 
 
4259
    if (def->os.init)
 
4260
        virBufferEscapeString(&buf, "    <init>%s</init>\n",
 
4261
                              def->os.init);
 
4262
    if (def->os.loader)
 
4263
        virBufferEscapeString(&buf, "    <loader>%s</loader>\n",
 
4264
                              def->os.loader);
 
4265
    if (def->os.kernel)
 
4266
        virBufferEscapeString(&buf, "    <kernel>%s</kernel>\n",
 
4267
                              def->os.kernel);
 
4268
    if (def->os.initrd)
 
4269
        virBufferEscapeString(&buf, "    <initrd>%s</initrd>\n",
 
4270
                              def->os.initrd);
 
4271
    if (def->os.cmdline)
 
4272
        virBufferEscapeString(&buf, "    <cmdline>%s</cmdline>\n",
 
4273
                              def->os.cmdline);
 
4274
    if (def->os.root)
 
4275
        virBufferEscapeString(&buf, "    <root>%s</root>\n",
 
4276
                              def->os.root);
 
4277
 
 
4278
    if (!def->os.bootloader) {
 
4279
        for (n = 0 ; n < def->os.nBootDevs ; n++) {
 
4280
            const char *boottype =
 
4281
                virDomainBootTypeToString(def->os.bootDevs[n]);
 
4282
            if (!boottype) {
 
4283
                virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
4284
                                     _("unexpected boot device type %d"),
 
4285
                                     def->os.bootDevs[n]);
 
4286
                goto cleanup;
 
4287
            }
 
4288
            virBufferVSprintf(&buf, "    <boot dev='%s'/>\n", boottype);
 
4289
        }
 
4290
    }
 
4291
 
 
4292
    virBufferAddLit(&buf, "  </os>\n");
 
4293
 
 
4294
    if (def->features) {
 
4295
        int i;
 
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);
 
4300
                if (!name) {
 
4301
                    virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
4302
                                         _("unexpected feature %d"), i);
 
4303
                    goto cleanup;
 
4304
                }
 
4305
                virBufferVSprintf(&buf, "    <%s/>\n", name);
 
4306
            }
 
4307
        }
 
4308
        virBufferAddLit(&buf, "  </features>\n");
 
4309
    }
 
4310
 
 
4311
    virBufferVSprintf(&buf, "  <clock offset='%s'/>\n",
 
4312
                      def->localtime ? "localtime" : "utc");
 
4313
 
 
4314
    if (virDomainLifecycleDefFormat(conn, &buf, def->onPoweroff,
 
4315
                                    "on_poweroff") < 0)
 
4316
        goto cleanup;
 
4317
    if (virDomainLifecycleDefFormat(conn, &buf, def->onReboot,
 
4318
                                    "on_reboot") < 0)
 
4319
        goto cleanup;
 
4320
    if (virDomainLifecycleDefFormat(conn, &buf, def->onCrash,
 
4321
                                    "on_crash") < 0)
 
4322
        goto cleanup;
 
4323
 
 
4324
    virBufferAddLit(&buf, "  <devices>\n");
 
4325
 
 
4326
    if (def->emulator)
 
4327
        virBufferEscapeString(&buf, "    <emulator>%s</emulator>\n",
 
4328
                              def->emulator);
 
4329
 
 
4330
    for (n = 0 ; n < def->ndisks ; n++)
 
4331
        if (virDomainDiskDefFormat(conn, &buf, def->disks[n], flags) < 0)
 
4332
            goto cleanup;
 
4333
 
 
4334
    for (n = 0 ; n < def->nfss ; n++)
 
4335
        if (virDomainFSDefFormat(conn, &buf, def->fss[n]) < 0)
 
4336
            goto cleanup;
 
4337
 
 
4338
 
 
4339
    for (n = 0 ; n < def->nnets ; n++)
 
4340
        if (virDomainNetDefFormat(conn, &buf, def->nets[n], flags) < 0)
 
4341
            goto cleanup;
 
4342
 
 
4343
    for (n = 0 ; n < def->nserials ; n++)
 
4344
        if (virDomainChrDefFormat(conn, &buf, def->serials[n], "serial", flags) < 0)
 
4345
            goto cleanup;
 
4346
 
 
4347
    for (n = 0 ; n < def->nparallels ; n++)
 
4348
        if (virDomainChrDefFormat(conn, &buf, def->parallels[n], "parallel", flags) < 0)
 
4349
            goto cleanup;
 
4350
 
 
4351
    /* If there's a PV console that's preferred.. */
 
4352
    if (def->console) {
 
4353
        if (virDomainChrDefFormat(conn, &buf, def->console, "console", flags) < 0)
 
4354
            goto cleanup;
 
4355
    } else if (def->nserials != 0) {
 
4356
        /* ..else for legacy compat duplicate the first serial device as a
 
4357
         * console */
 
4358
        if (virDomainChrDefFormat(conn, &buf, def->serials[0], "console", flags) < 0)
 
4359
            goto cleanup;
 
4360
    }
 
4361
 
 
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)
 
4365
            goto cleanup;
 
4366
 
 
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
 
4373
        };
 
4374
 
 
4375
        if (virDomainInputDefFormat(conn, &buf, &autoInput) < 0)
 
4376
            goto cleanup;
 
4377
 
 
4378
        for (n = 0 ; n < def->ngraphics ; n++)
 
4379
            if (virDomainGraphicsDefFormat(conn, &buf, def, def->graphics[n], flags) < 0)
 
4380
                goto cleanup;
 
4381
    }
 
4382
 
 
4383
    for (n = 0 ; n < def->nsounds ; n++)
 
4384
        if (virDomainSoundDefFormat(conn, &buf, def->sounds[n]) < 0)
 
4385
            goto cleanup;
 
4386
 
 
4387
    for (n = 0 ; n < def->nvideos ; n++)
 
4388
        if (virDomainVideoDefFormat(conn, &buf, def->videos[n]) < 0)
 
4389
            goto cleanup;
 
4390
 
 
4391
    for (n = 0 ; n < def->nhostdevs ; n++)
 
4392
        if (virDomainHostdevDefFormat(conn, &buf, def->hostdevs[n], flags) < 0)
 
4393
            goto cleanup;
 
4394
 
 
4395
    virBufferAddLit(&buf, "  </devices>\n");
 
4396
 
 
4397
    if (def->seclabel.model) {
 
4398
        const char *sectype = virDomainSeclabelTypeToString(def->seclabel.type);
 
4399
        if (!sectype)
 
4400
            goto cleanup;
 
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);
 
4406
        } else {
 
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");
 
4416
        }
 
4417
    }
 
4418
 
 
4419
    virBufferAddLit(&buf, "</domain>\n");
 
4420
 
 
4421
    if (virBufferError(&buf))
 
4422
        goto no_memory;
 
4423
 
 
4424
    return virBufferContentAndReset(&buf);
 
4425
 
 
4426
 no_memory:
 
4427
    virReportOOMError(conn);
 
4428
 cleanup:
 
4429
    tmp = virBufferContentAndReset(&buf);
 
4430
    VIR_FREE(tmp);
 
4431
    return NULL;
 
4432
}
 
4433
 
 
4434
char *virDomainObjFormat(virConnectPtr conn,
 
4435
                         virDomainObjPtr obj,
 
4436
                         int flags)
 
4437
{
 
4438
    char *config_xml = NULL, *xml = NULL;
 
4439
    virBuffer buf = VIR_BUFFER_INITIALIZER;
 
4440
    const char *monitorpath;
 
4441
 
 
4442
    virBufferVSprintf(&buf, "<domstatus state='%s' pid='%d'>\n",
 
4443
                      virDomainStateTypeToString(obj->state),
 
4444
                      obj->pid);
 
4445
 
 
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;
 
4451
            break;
 
4452
        default:
 
4453
        case VIR_DOMAIN_CHR_TYPE_PTY:
 
4454
            monitorpath = obj->monitor_chr->data.file.path;
 
4455
            break;
 
4456
        }
 
4457
 
 
4458
        virBufferEscapeString(&buf, "  <monitor path='%s'", monitorpath);
 
4459
        virBufferVSprintf(&buf, " type='%s'/>\n",
 
4460
                          virDomainChrTypeToString(obj->monitor_chr->type));
 
4461
    }
 
4462
 
 
4463
 
 
4464
    if (obj->nvcpupids) {
 
4465
        int i;
 
4466
        virBufferAddLit(&buf, "  <vcpus>\n");
 
4467
        for (i = 0 ; i < obj->nvcpupids ; i++) {
 
4468
            virBufferVSprintf(&buf, "    <vcpu pid='%d'/>\n", obj->vcpupids[i]);
 
4469
        }
 
4470
        virBufferAddLit(&buf, "  </vcpus>\n");
 
4471
    }
 
4472
 
 
4473
    if (!(config_xml = virDomainDefFormat(conn,
 
4474
                                          obj->def,
 
4475
                                          flags)))
 
4476
        goto error;
 
4477
 
 
4478
    virBufferAdd(&buf, config_xml, strlen(config_xml));
 
4479
    VIR_FREE(config_xml);
 
4480
    virBufferAddLit(&buf, "</domstatus>\n");
 
4481
 
 
4482
    if (virBufferError(&buf))
 
4483
        goto no_memory;
 
4484
 
 
4485
    return virBufferContentAndReset(&buf);
 
4486
 
 
4487
no_memory:
 
4488
    virReportOOMError(conn);
 
4489
error:
 
4490
    xml = virBufferContentAndReset(&buf);
 
4491
    VIR_FREE(xml);
 
4492
    return NULL;
 
4493
}
 
4494
 
 
4495
 
 
4496
#ifndef PROXY
 
4497
 
 
4498
int virDomainSaveXML(virConnectPtr conn,
 
4499
                     const char *configDir,
 
4500
                     virDomainDefPtr def,
 
4501
                     const char *xml)
 
4502
{
 
4503
    char *configFile = NULL;
 
4504
    int fd = -1, ret = -1;
 
4505
    size_t towrite;
 
4506
 
 
4507
    if ((configFile = virDomainConfigFile(conn, configDir, def->name)) == NULL)
 
4508
        goto cleanup;
 
4509
 
 
4510
    if (virFileMakePath(configDir)) {
 
4511
        virReportSystemError(conn, errno,
 
4512
                             _("cannot create config directory '%s'"),
 
4513
                             configDir);
 
4514
        goto cleanup;
 
4515
    }
 
4516
 
 
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'"),
 
4522
                             configFile);
 
4523
        goto cleanup;
 
4524
    }
 
4525
 
 
4526
    towrite = strlen(xml);
 
4527
    if (safewrite(fd, xml, towrite) < 0) {
 
4528
        virReportSystemError(conn, errno,
 
4529
                             _("cannot write config file '%s'"),
 
4530
                             configFile);
 
4531
        goto cleanup;
 
4532
    }
 
4533
 
 
4534
    if (close(fd) < 0) {
 
4535
        virReportSystemError(conn, errno,
 
4536
                             _("cannot save config file '%s'"),
 
4537
                             configFile);
 
4538
        goto cleanup;
 
4539
    }
 
4540
 
 
4541
    ret = 0;
 
4542
 cleanup:
 
4543
    if (fd != -1)
 
4544
        close(fd);
 
4545
    VIR_FREE(configFile);
 
4546
    return ret;
 
4547
}
 
4548
 
 
4549
int virDomainSaveConfig(virConnectPtr conn,
 
4550
                        const char *configDir,
 
4551
                        virDomainDefPtr def)
 
4552
{
 
4553
    int ret = -1;
 
4554
    char *xml;
 
4555
 
 
4556
    if (!(xml = virDomainDefFormat(conn,
 
4557
                                   def,
 
4558
                                   VIR_DOMAIN_XML_SECURE)))
 
4559
        goto cleanup;
 
4560
 
 
4561
    if (virDomainSaveXML(conn, configDir, def, xml))
 
4562
        goto cleanup;
 
4563
 
 
4564
    ret = 0;
 
4565
cleanup:
 
4566
    VIR_FREE(xml);
 
4567
    return ret;
 
4568
}
 
4569
 
 
4570
int virDomainSaveStatus(virConnectPtr conn,
 
4571
                        const char *statusDir,
 
4572
                        virDomainObjPtr obj)
 
4573
{
 
4574
    int flags = VIR_DOMAIN_XML_SECURE|VIR_DOMAIN_XML_INTERNAL_STATUS;
 
4575
    int ret = -1;
 
4576
    char *xml;
 
4577
 
 
4578
    if (!(xml = virDomainObjFormat(conn, obj, flags)))
 
4579
        goto cleanup;
 
4580
 
 
4581
    if (virDomainSaveXML(conn, statusDir, obj->def, xml))
 
4582
        goto cleanup;
 
4583
 
 
4584
    ret = 0;
 
4585
cleanup:
 
4586
    VIR_FREE(xml);
 
4587
    return ret;
 
4588
}
 
4589
 
 
4590
 
 
4591
virDomainObjPtr virDomainLoadConfig(virConnectPtr conn,
 
4592
                                    virCapsPtr caps,
 
4593
                                    virDomainObjListPtr doms,
 
4594
                                    const char *configDir,
 
4595
                                    const char *autostartDir,
 
4596
                                    const char *name,
 
4597
                                    virDomainLoadConfigNotify notify,
 
4598
                                    void *opaque)
 
4599
{
 
4600
    char *configFile = NULL, *autostartLink = NULL;
 
4601
    virDomainDefPtr def = NULL;
 
4602
    virDomainObjPtr dom;
 
4603
    int autostart;
 
4604
    int newVM = 1;
 
4605
 
 
4606
    if ((configFile = virDomainConfigFile(conn, configDir, name)) == NULL)
 
4607
        goto error;
 
4608
    if ((autostartLink = virDomainConfigFile(conn, autostartDir, name)) == NULL)
 
4609
        goto error;
 
4610
 
 
4611
    if ((autostart = virFileLinkPointsTo(autostartLink, configFile)) < 0)
 
4612
        goto error;
 
4613
 
 
4614
    if (!(def = virDomainDefParseFile(conn, caps, configFile,
 
4615
                                      VIR_DOMAIN_XML_INACTIVE)))
 
4616
        goto error;
 
4617
 
 
4618
    if ((dom = virDomainFindByName(doms, def->name))) {
 
4619
        virDomainObjUnlock(dom);
 
4620
        dom = NULL;
 
4621
        newVM = 0;
 
4622
    }
 
4623
 
 
4624
    if (!(dom = virDomainAssignDef(conn, doms, def)))
 
4625
        goto error;
 
4626
 
 
4627
    dom->autostart = autostart;
 
4628
 
 
4629
    if (notify)
 
4630
        (*notify)(dom, newVM, opaque);
 
4631
 
 
4632
    VIR_FREE(configFile);
 
4633
    VIR_FREE(autostartLink);
 
4634
    return dom;
 
4635
 
 
4636
error:
 
4637
    VIR_FREE(configFile);
 
4638
    VIR_FREE(autostartLink);
 
4639
    virDomainDefFree(def);
 
4640
    return NULL;
 
4641
}
 
4642
 
 
4643
static virDomainObjPtr virDomainLoadStatus(virConnectPtr conn,
 
4644
                                           virCapsPtr caps,
 
4645
                                           virDomainObjListPtr doms,
 
4646
                                           const char *statusDir,
 
4647
                                           const char *name,
 
4648
                                           virDomainLoadConfigNotify notify,
 
4649
                                           void *opaque)
 
4650
{
 
4651
    char *statusFile = NULL;
 
4652
    virDomainObjPtr obj = NULL;
 
4653
    virDomainObjPtr tmp = NULL;
 
4654
 
 
4655
    if ((statusFile = virDomainConfigFile(conn, statusDir, name)) == NULL)
 
4656
        goto error;
 
4657
 
 
4658
    if (!(obj = virDomainObjParseFile(conn, caps, statusFile)))
 
4659
        goto error;
 
4660
 
 
4661
    tmp = virDomainFindByName(doms, obj->def->name);
 
4662
    if (tmp) {
 
4663
        virDomainObjUnlock(obj);
 
4664
        virDomainReportError(conn, VIR_ERR_INTERNAL_ERROR,
 
4665
                             _("unexpected domain %s already exists"),
 
4666
                             obj->def->name);
 
4667
        goto error;
 
4668
    }
 
4669
 
 
4670
    if (VIR_REALLOC_N(doms->objs, doms->count + 1) < 0) {
 
4671
        virReportOOMError(conn);
 
4672
        goto error;
 
4673
    }
 
4674
 
 
4675
    doms->objs[doms->count] = obj;
 
4676
    doms->count++;
 
4677
 
 
4678
    if (notify)
 
4679
        (*notify)(obj, 1, opaque);
 
4680
 
 
4681
    VIR_FREE(statusFile);
 
4682
    return obj;
 
4683
 
 
4684
error:
 
4685
    virDomainObjFree(obj);
 
4686
    VIR_FREE(statusFile);
 
4687
    return NULL;
 
4688
}
 
4689
 
 
4690
int virDomainLoadAllConfigs(virConnectPtr conn,
 
4691
                            virCapsPtr caps,
 
4692
                            virDomainObjListPtr doms,
 
4693
                            const char *configDir,
 
4694
                            const char *autostartDir,
 
4695
                            int liveStatus,
 
4696
                            virDomainLoadConfigNotify notify,
 
4697
                            void *opaque)
 
4698
{
 
4699
    DIR *dir;
 
4700
    struct dirent *entry;
 
4701
 
 
4702
    VIR_INFO("Scanning for configs in %s", configDir);
 
4703
 
 
4704
    if (!(dir = opendir(configDir))) {
 
4705
        if (errno == ENOENT)
 
4706
            return 0;
 
4707
        virReportSystemError(conn, errno,
 
4708
                             _("Failed to open dir '%s'"),
 
4709
                             configDir);
 
4710
        return -1;
 
4711
    }
 
4712
 
 
4713
    while ((entry = readdir(dir))) {
 
4714
        virDomainObjPtr dom;
 
4715
 
 
4716
        if (entry->d_name[0] == '.')
 
4717
            continue;
 
4718
 
 
4719
        if (!virFileStripSuffix(entry->d_name, ".xml"))
 
4720
            continue;
 
4721
 
 
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);
 
4725
        if (liveStatus)
 
4726
            dom = virDomainLoadStatus(conn,
 
4727
                                      caps,
 
4728
                                      doms,
 
4729
                                      configDir,
 
4730
                                      entry->d_name,
 
4731
                                      notify,
 
4732
                                      opaque);
 
4733
        else
 
4734
            dom = virDomainLoadConfig(conn,
 
4735
                                      caps,
 
4736
                                      doms,
 
4737
                                      configDir,
 
4738
                                      autostartDir,
 
4739
                                      entry->d_name,
 
4740
                                      notify,
 
4741
                                      opaque);
 
4742
        if (dom) {
 
4743
            virDomainObjUnlock(dom);
 
4744
            if (!liveStatus)
 
4745
                dom->persistent = 1;
 
4746
        }
 
4747
    }
 
4748
 
 
4749
    closedir(dir);
 
4750
 
 
4751
    return 0;
 
4752
}
 
4753
 
 
4754
int virDomainDeleteConfig(virConnectPtr conn,
 
4755
                          const char *configDir,
 
4756
                          const char *autostartDir,
 
4757
                          virDomainObjPtr dom)
 
4758
{
 
4759
    char *configFile = NULL, *autostartLink = NULL;
 
4760
    int ret = -1;
 
4761
 
 
4762
    if ((configFile = virDomainConfigFile(conn, configDir, dom->def->name)) == NULL)
 
4763
        goto cleanup;
 
4764
    if ((autostartLink = virDomainConfigFile(conn, autostartDir, dom->def->name)) == NULL)
 
4765
        goto cleanup;
 
4766
 
 
4767
    /* Not fatal if this doesn't work */
 
4768
    unlink(autostartLink);
 
4769
 
 
4770
    if (unlink(configFile) < 0 &&
 
4771
        errno != ENOENT) {
 
4772
        virReportSystemError(conn, errno,
 
4773
                             _("cannot remove config %s"),
 
4774
                             configFile);
 
4775
        goto cleanup;
 
4776
    }
 
4777
 
 
4778
    ret = 0;
 
4779
 
 
4780
cleanup:
 
4781
    VIR_FREE(configFile);
 
4782
    VIR_FREE(autostartLink);
 
4783
    return ret;
 
4784
}
 
4785
 
 
4786
char *virDomainConfigFile(virConnectPtr conn,
 
4787
                          const char *dir,
 
4788
                          const char *name)
 
4789
{
 
4790
    char *ret = NULL;
 
4791
 
 
4792
    if (virAsprintf(&ret, "%s/%s.xml", dir, name) < 0) {
 
4793
        virReportOOMError(conn);
 
4794
        return NULL;
 
4795
    }
 
4796
 
 
4797
    return ret;
 
4798
}
 
4799
 
 
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
 
4807
 */
 
4808
int virDiskNameToBusDeviceIndex(const virDomainDiskDefPtr disk,
 
4809
                                int *busIdx,
 
4810
                                int *devIdx) {
 
4811
 
 
4812
    int idx = virDiskNameToIndex(disk->dst);
 
4813
    if (idx < 0)
 
4814
        return -1;
 
4815
 
 
4816
    switch (disk->bus) {
 
4817
        case VIR_DOMAIN_DISK_BUS_IDE:
 
4818
            *busIdx = idx / 2;
 
4819
            *devIdx = idx % 2;
 
4820
            break;
 
4821
        case VIR_DOMAIN_DISK_BUS_SCSI:
 
4822
            *busIdx = idx / 7;
 
4823
            *devIdx = idx % 7;
 
4824
            break;
 
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:
 
4829
        default:
 
4830
            *busIdx = 0;
 
4831
            *devIdx = idx;
 
4832
            break;
 
4833
    }
 
4834
 
 
4835
    return 0;
 
4836
}
 
4837
 
 
4838
virDomainFSDefPtr virDomainGetRootFilesystem(virDomainDefPtr def)
 
4839
{
 
4840
    int i;
 
4841
 
 
4842
    for (i = 0 ; i < def->nfss ; i++) {
 
4843
        if (def->fss[i]->type != VIR_DOMAIN_FS_TYPE_MOUNT)
 
4844
            continue;
 
4845
 
 
4846
        if (STREQ(def->fss[i]->dst, "/"))
 
4847
            return def->fss[i];
 
4848
    }
 
4849
 
 
4850
    return NULL;
 
4851
}
 
4852
 
 
4853
 
 
4854
void virDomainObjLock(virDomainObjPtr obj)
 
4855
{
 
4856
    virMutexLock(&obj->lock);
 
4857
}
 
4858
 
 
4859
void virDomainObjUnlock(virDomainObjPtr obj)
 
4860
{
 
4861
    virMutexUnlock(&obj->lock);
 
4862
}
 
4863
 
 
4864
#endif /* ! PROXY */