35
44
errmsg = __virErrorMsg(error, info);
36
__virRaiseError(NULL, NULL, VIR_FROM_XML, error, VIR_ERR_ERROR,
45
__virRaiseError(conn, NULL, NULL, VIR_FROM_XML, error, VIR_ERR_ERROR,
37
46
errmsg, info, NULL, value, 0, errmsg, info, value);
52
* @xpath: the XPath string to evaluate
53
* @ctxt: an XPath context
55
* Convenience function to evaluate an XPath string
57
* Returns a new string which must be deallocated by the caller or NULL
58
* if the evaluation failed.
61
virXPathString(const char *xpath, xmlXPathContextPtr ctxt) {
62
xmlXPathObjectPtr obj;
65
if ((ctxt == NULL) || (xpath == NULL)) {
66
virXMLError(NULL, VIR_ERR_INTERNAL_ERROR,
67
"Invalid parameter to virXPathString()", 0);
70
obj = xmlXPathEval(BAD_CAST xpath, ctxt);
71
if ((obj == NULL) || (obj->type != XPATH_STRING) ||
72
(obj->stringval == NULL) || (obj->stringval[0] == 0))
74
ret = strdup((char *) obj->stringval);
75
xmlXPathFreeObject(obj);
77
virXMLError(NULL, VIR_ERR_NO_MEMORY, "strdup", 0);
84
* @xpath: the XPath string to evaluate
85
* @ctxt: an XPath context
86
* @value: the returned double value
88
* Convenience function to evaluate an XPath number
90
* Returns 0 in case of success in which case @value is set,
91
* or -1 if the evaluation failed.
94
virXPathNumber(const char *xpath, xmlXPathContextPtr ctxt, double *value) {
95
xmlXPathObjectPtr obj;
97
if ((ctxt == NULL) || (xpath == NULL) || (value == NULL)) {
98
virXMLError(NULL, VIR_ERR_INTERNAL_ERROR,
99
"Invalid parameter to virXPathNumber()", 0);
102
obj = xmlXPathEval(BAD_CAST xpath, ctxt);
103
if ((obj == NULL) || (obj->type != XPATH_NUMBER) ||
104
(isnan(obj->floatval))) {
105
xmlXPathFreeObject(obj);
109
*value = obj->floatval;
110
xmlXPathFreeObject(obj);
116
* @xpath: the XPath string to evaluate
117
* @ctxt: an XPath context
118
* @value: the returned long value
120
* Convenience function to evaluate an XPath number
122
* Returns 0 in case of success in which case @value is set,
123
* or -1 if the XPath evaluation failed or -2 if the
124
* value doesn't have a long format.
127
virXPathLong(const char *xpath, xmlXPathContextPtr ctxt, long *value) {
128
xmlXPathObjectPtr obj;
131
if ((ctxt == NULL) || (xpath == NULL) || (value == NULL)) {
132
virXMLError(NULL, VIR_ERR_INTERNAL_ERROR,
133
"Invalid parameter to virXPathNumber()", 0);
136
obj = xmlXPathEval(BAD_CAST xpath, ctxt);
137
if ((obj != NULL) && (obj->type == XPATH_STRING) &&
138
(obj->stringval != NULL) && (obj->stringval[0] != 0)) {
142
val = strtol((const char*)obj->stringval, &conv, 10);
143
if (conv == (const char*)obj->stringval) {
148
} else if ((obj != NULL) && (obj->type == XPATH_NUMBER) &&
149
(!(isnan(obj->floatval)))) {
150
*value = (long) obj->floatval;
151
if (*value != obj->floatval) {
158
xmlXPathFreeObject(obj);
164
* @xpath: the XPath string to evaluate
165
* @ctxt: an XPath context
167
* Convenience function to evaluate an XPath boolean
169
* Returns 0 if false, 1 if true, or -1 if the evaluation failed.
172
virXPathBoolean(const char *xpath, xmlXPathContextPtr ctxt) {
173
xmlXPathObjectPtr obj;
176
if ((ctxt == NULL) || (xpath == NULL)) {
177
virXMLError(NULL, VIR_ERR_INTERNAL_ERROR,
178
"Invalid parameter to virXPathBoolean()", 0);
181
obj = xmlXPathEval(BAD_CAST xpath, ctxt);
182
if ((obj == NULL) || (obj->type != XPATH_BOOLEAN) ||
183
(obj->boolval < 0) || (obj->boolval > 1)) {
184
xmlXPathFreeObject(obj);
189
xmlXPathFreeObject(obj);
195
* @xpath: the XPath string to evaluate
196
* @ctxt: an XPath context
198
* Convenience function to evaluate an XPath node set and returning
199
* only one node, the first one in the set if any
201
* Returns a pointer to the node or NULL if the evaluation failed.
204
virXPathNode(const char *xpath, xmlXPathContextPtr ctxt) {
205
xmlXPathObjectPtr obj;
208
if ((ctxt == NULL) || (xpath == NULL)) {
209
virXMLError(NULL, VIR_ERR_INTERNAL_ERROR,
210
"Invalid parameter to virXPathNode()", 0);
213
obj = xmlXPathEval(BAD_CAST xpath, ctxt);
214
if ((obj == NULL) || (obj->type != XPATH_NODESET) ||
215
(obj->nodesetval == NULL) || (obj->nodesetval->nodeNr <= 0) ||
216
(obj->nodesetval->nodeTab == NULL)) {
217
xmlXPathFreeObject(obj);
221
ret = obj->nodesetval->nodeTab[0];
222
xmlXPathFreeObject(obj);
227
* @xpath: the XPath string to evaluate
228
* @ctxt: an XPath context
229
* @list: the returned list of nodes (or NULL if only count matters)
231
* Convenience function to evaluate an XPath node set
233
* Returns the number of nodes found in which case @list is set (and
234
* must be freed) or -1 if the evaluation failed.
237
virXPathNodeSet(const char *xpath, xmlXPathContextPtr ctxt, xmlNodePtr **list) {
238
xmlXPathObjectPtr obj;
241
if ((ctxt == NULL) || (xpath == NULL)) {
242
virXMLError(NULL, VIR_ERR_INTERNAL_ERROR,
243
"Invalid parameter to virXPathNodeSet()", 0);
246
obj = xmlXPathEval(BAD_CAST xpath, ctxt);
247
if ((obj == NULL) || (obj->type != XPATH_NODESET) ||
248
(obj->nodesetval == NULL) || (obj->nodesetval->nodeNr <= 0) ||
249
(obj->nodesetval->nodeTab == NULL)) {
250
xmlXPathFreeObject(obj);
256
ret = obj->nodesetval->nodeNr;
258
*list = malloc(ret * sizeof(xmlNodePtr));
260
virXMLError(NULL, VIR_ERR_NO_MEMORY,
261
_("allocate string array"), ret * sizeof(xmlNodePtr));
263
memcpy(*list, obj->nodesetval->nodeTab, ret * sizeof(xmlNodePtr));
266
xmlXPathFreeObject(obj);
42
273
* @buf: the buffer
43
* @len: the minimum free size to allocate
274
* @len: the minimum free size to allocate on top of existing used space
45
* Grow the available space of an XML buffer.
276
* Grow the available space of an XML buffer to at least @len bytes.
47
278
* Returns the new available space or -1 in case of error
214
* This block of function are now implemented by a xend poll in
215
* xend_internal.c instead of querying the Xen store, code is kept
216
* for reference of in case Xend may not be available in the future ...
220
* virDomainGetXMLDevice:
221
* @domain: a domain object
222
* @sub: the xenstore subsection 'vbd', 'vif', ...
223
* @dev: the xenstrore internal device number
224
* @name: the value's name
226
* Extract one information the device used by the domain from xensttore
228
* Returns the new string or NULL in case of error
231
virDomainGetXMLDeviceInfo(virDomainPtr domain, const char *sub,
232
long dev, const char *name)
235
unsigned int len = 0;
237
snprintf(s, 255, "/local/domain/0/backend/%s/%d/%ld/%s",
238
sub, domain->handle, dev, name);
241
return xs_read(domain->conn->xshandle, 0, &s[0], &len);
245
* virDomainGetXMLDevice:
246
* @domain: a domain object
247
* @buf: the output buffer object
248
* @dev: the xenstrore internal device number
250
* Extract and dump in the buffer information on the device used by the domain
252
* Returns 0 in case of success, -1 in case of failure
255
virDomainGetXMLDevice(virDomainPtr domain, virBufferPtr buf, long dev)
259
type = virDomainGetXMLDeviceInfo(domain, "vbd", dev, "type");
262
if (!strcmp(type, "file")) {
263
virBufferVSprintf(buf, " <disk type='file'>\n");
264
val = virDomainGetXMLDeviceInfo(domain, "vbd", dev, "params");
266
virBufferVSprintf(buf, " <source file='%s'/>\n", val);
269
val = virDomainGetXMLDeviceInfo(domain, "vbd", dev, "dev");
272
if (!strncmp(tmp, "ioemu:", 6))
274
virBufferVSprintf(buf, " <target dev='%s'/>\n", tmp);
277
val = virDomainGetXMLDeviceInfo(domain, "vbd", dev, "read-only");
279
virBufferVSprintf(buf, " <readonly/>\n", val);
282
virBufferAdd(buf, " </disk>\n", 12);
283
} else if (!strcmp(type, "phy")) {
284
virBufferVSprintf(buf, " <disk type='device'>\n");
285
val = virDomainGetXMLDeviceInfo(domain, "vbd", dev, "params");
287
virBufferVSprintf(buf, " <source device='%s'/>\n", val);
290
val = virDomainGetXMLDeviceInfo(domain, "vbd", dev, "dev");
293
if (!strncmp(tmp, "ioemu:", 6))
295
virBufferVSprintf(buf, " <target dev='%s'/>\n", tmp);
298
val = virDomainGetXMLDeviceInfo(domain, "vbd", dev, "read-only");
300
virBufferVSprintf(buf, " <readonly/>\n", val);
303
virBufferAdd(buf, " </disk>\n", 12);
305
TODO fprintf(stderr, "Don't know how to handle device type %s\n",
314
* virDomainGetXMLDevices:
315
* @domain: a domain object
316
* @buf: the output buffer object
318
* Extract the devices used by the domain and dumps then in the buffer
320
* Returns 0 in case of success, -1 in case of failure
323
virDomainGetXMLDevices(virDomainPtr domain, virBufferPtr buf)
328
char **list = NULL, *endptr;
332
if (!VIR_IS_CONNECTED_DOMAIN(domain))
337
snprintf(backend, 199, "/local/domain/0/backend/vbd/%d",
338
virDomainGetID(domain));
340
list = xs_directory(conn->xshandle, 0, backend, &num);
345
for (i = 0; i < num; i++) {
346
id = strtol(list[i], &endptr, 10);
347
if ((endptr == list[i]) || (*endptr != 0)) {
351
virDomainGetXMLDevice(domain, buf, id);
362
* virDomainGetXMLInterface:
363
* @domain: a domain object
364
* @buf: the output buffer object
365
* @dev: the xenstrore internal device number
367
* Extract and dump in the buffer information on the interface used by
370
* Returns 0 in case of success, -1 in case of failure
373
virDomainGetXMLInterface(virDomainPtr domain, virBufferPtr buf, long dev)
377
type = virDomainGetXMLDeviceInfo(domain, "vif", dev, "bridge");
379
virBufferVSprintf(buf, " <interface type='default'>\n");
380
val = virDomainGetXMLDeviceInfo(domain, "vif", dev, "mac");
382
virBufferVSprintf(buf, " <mac address='%s'/>\n", val);
385
val = virDomainGetXMLDeviceInfo(domain, "vif", dev, "script");
387
virBufferVSprintf(buf, " <script path='%s'/>\n", val);
390
virBufferAdd(buf, " </interface>\n", 17);
392
virBufferVSprintf(buf, " <interface type='bridge'>\n");
393
virBufferVSprintf(buf, " <source bridge='%s'/>\n", type);
394
val = virDomainGetXMLDeviceInfo(domain, "vif", dev, "mac");
396
virBufferVSprintf(buf, " <mac address='%s'/>\n", val);
399
val = virDomainGetXMLDeviceInfo(domain, "vif", dev, "script");
401
virBufferVSprintf(buf, " <script path='%s'/>\n", val);
404
virBufferAdd(buf, " </interface>\n", 17);
412
* virDomainGetXMLInterfaces:
413
* @domain: a domain object
414
* @buf: the output buffer object
416
* Extract the interfaces used by the domain and dumps then in the buffer
418
* Returns 0 in case of success, -1 in case of failure
421
virDomainGetXMLInterfaces(virDomainPtr domain, virBufferPtr buf)
426
char **list = NULL, *endptr;
430
if (!VIR_IS_CONNECTED_DOMAIN(domain))
435
snprintf(backend, 199, "/local/domain/0/backend/vif/%d",
436
virDomainGetID(domain));
438
list = xs_directory(conn->xshandle, 0, backend, &num);
443
for (i = 0; i < num; i++) {
444
id = strtol(list[i], &endptr, 10);
445
if ((endptr == list[i]) || (*endptr != 0)) {
449
virDomainGetXMLInterface(domain, buf, id);
463
* virDomainGetXMLBoot:
464
* @domain: a domain object
465
* @buf: the output buffer object
467
* Extract the boot information used to start that domain
469
* Returns 0 in case of success, -1 in case of failure
472
virDomainGetXMLBoot(virDomainPtr domain, virBufferPtr buf)
476
if (!VIR_IS_DOMAIN(domain))
479
vm = virDomainGetVM(domain);
483
virBufferAdd(buf, " <os>\n", 7);
484
str = virDomainGetVMInfo(domain, vm, "image/ostype");
486
virBufferVSprintf(buf, " <type>%s</type>\n", str);
489
str = virDomainGetVMInfo(domain, vm, "image/kernel");
491
virBufferVSprintf(buf, " <kernel>%s</kernel>\n", str);
494
str = virDomainGetVMInfo(domain, vm, "image/ramdisk");
497
virBufferVSprintf(buf, " <initrd>%s</initrd>\n", str);
500
str = virDomainGetVMInfo(domain, vm, "image/cmdline");
503
virBufferVSprintf(buf, " <cmdline>%s</cmdline>\n", str);
506
virBufferAdd(buf, " </os>\n", 8);
513
* virDomainGetXMLDesc:
514
* @domain: a domain object
515
* @flags: and OR'ed set of extraction flags, not used yet
517
* Provide an XML description of the domain. NOTE: this API is subject
520
* Returns a 0 terminated UTF-8 encoded XML instance, or NULL in case of error.
521
* the caller must free() the returned value.
524
virDomainGetXMLDesc(virDomainPtr domain, int flags)
527
unsigned char uuid[16];
531
if (!VIR_IS_DOMAIN(domain))
535
if (virDomainGetInfo(domain, &info) < 0)
545
virBufferVSprintf(&buf, "<domain type='xen' id='%d'>\n",
546
virDomainGetID(domain));
547
virBufferVSprintf(&buf, " <name>%s</name>\n",
548
virDomainGetName(domain));
549
if (virDomainGetUUID(domain, &uuid[0]) == 0) {
550
virBufferVSprintf(&buf,
551
" <uuid>%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x</uuid>\n",
552
uuid[0], uuid[1], uuid[2], uuid[3],
553
uuid[4], uuid[5], uuid[6], uuid[7],
554
uuid[8], uuid[9], uuid[10], uuid[11],
555
uuid[12], uuid[13], uuid[14], uuid[15]);
557
virDomainGetXMLBoot(domain, &buf);
558
virBufferVSprintf(&buf, " <memory>%lu</memory>\n", info.maxMem);
559
virBufferVSprintf(&buf, " <vcpu>%d</vcpu>\n", (int) info.nrVirtCpu);
560
virBufferAdd(&buf, " <devices>\n", 12);
561
virDomainGetXMLDevices(domain, &buf);
562
virDomainGetXMLInterfaces(domain, &buf);
563
virBufferAdd(&buf, " </devices>\n", 13);
564
virBufferAdd(&buf, "</domain>\n", 10);
566
buf.content[buf.use] = 0;
570
#endif /* 0 - UNUSED */
574
* virtDomainParseXMLGraphicsDesc:
445
* virtDomainParseXMLGraphicsDescImage:
446
* @conn: pointer to the hypervisor connection
575
447
* @node: node containing graphics description
576
448
* @buf: a buffer for the result S-Expr
577
449
* @xendConfigVersion: xend configuration file format
579
* Parse the graphics part of the XML description and add it to the S-Expr
580
* in buf. This is a temporary interface as the S-Expr interface will be
581
* replaced by XML-RPC in the future. However the XML format should stay
451
* Parse the graphics part of the XML description and add it to the S-Expr
452
* in buf. This is a temporary interface as the S-Expr interface will be
453
* replaced by XML-RPC in the future. However the XML format should stay
582
454
* valid over time.
584
456
* Returns 0 in case of success, -1 in case of error
586
static int virDomainParseXMLGraphicsDesc(xmlNodePtr node, virBufferPtr buf, int xendConfigVersion)
458
static int virDomainParseXMLGraphicsDescImage(virConnectPtr conn ATTRIBUTE_UNUSED, xmlNodePtr node, virBufferPtr buf, int xendConfigVersion)
588
460
xmlChar *graphics_type = NULL;
591
463
if (graphics_type != NULL) {
592
464
if (xmlStrEqual(graphics_type, BAD_CAST "sdl")) {
593
465
virBufferAdd(buf, "(sdl 1)", 7);
595
// Need to understand sdl options
597
//virBufferAdd(buf, "(display localhost:10.0)", 24);
598
//virBufferAdd(buf, "(xauthority /root/.Xauthority)", 30);
467
* Need to understand sdl options
469
*virBufferAdd(buf, "(display localhost:10.0)", 24);
470
*virBufferAdd(buf, "(xauthority /root/.Xauthority)", 30);
600
473
else if (xmlStrEqual(graphics_type, BAD_CAST "vnc")) {
601
474
virBufferAdd(buf, "(vnc 1)", 7);
602
475
if (xendConfigVersion >= 2) {
603
476
xmlChar *vncport = xmlGetProp(node, BAD_CAST "port");
477
xmlChar *vnclisten = xmlGetProp(node, BAD_CAST "listen");
478
xmlChar *vncpasswd = xmlGetProp(node, BAD_CAST "passwd");
479
xmlChar *keymap = xmlGetProp(node, BAD_CAST "keymap");
604
480
if (vncport != NULL) {
605
481
long port = strtol((const char *)vncport, NULL, 10);
607
483
virBufferAdd(buf, "(vncunused 1)", 13);
608
else if (port > 5900)
609
virBufferVSprintf(buf, "(vncdisplay %d)", port - 5900);
484
else if (port >= 5900)
485
virBufferVSprintf(buf, "(vncdisplay %ld)", port - 5900);
610
486
xmlFree(vncport);
488
if (vnclisten != NULL) {
489
virBufferVSprintf(buf, "(vnclisten %s)", vnclisten);
492
if (vncpasswd != NULL) {
493
virBufferVSprintf(buf, "(vncpasswd %s)", vncpasswd);
496
if (keymap != NULL) {
497
virBufferVSprintf(buf, "(keymap %s)", keymap);
502
xmlFree(graphics_type);
509
* virtDomainParseXMLGraphicsDescVFB:
510
* @conn: pointer to the hypervisor connection
511
* @node: node containing graphics description
512
* @buf: a buffer for the result S-Expr
514
* Parse the graphics part of the XML description and add it to the S-Expr
515
* in buf. This is a temporary interface as the S-Expr interface will be
516
* replaced by XML-RPC in the future. However the XML format should stay
519
* Returns 0 in case of success, -1 in case of error
521
static int virDomainParseXMLGraphicsDescVFB(virConnectPtr conn ATTRIBUTE_UNUSED, xmlNodePtr node, virBufferPtr buf)
523
xmlChar *graphics_type = NULL;
525
graphics_type = xmlGetProp(node, BAD_CAST "type");
526
if (graphics_type != NULL) {
527
virBufferAdd(buf, "(device (vkbd))", 15);
528
virBufferAdd(buf, "(device (vfb ", 13);
529
if (xmlStrEqual(graphics_type, BAD_CAST "sdl")) {
530
virBufferAdd(buf, "(type sdl)", 10);
532
* Need to understand sdl options
534
*virBufferAdd(buf, "(display localhost:10.0)", 24);
535
*virBufferAdd(buf, "(xauthority /root/.Xauthority)", 30);
538
else if (xmlStrEqual(graphics_type, BAD_CAST "vnc")) {
539
virBufferAdd(buf, "(type vnc)", 10);
540
xmlChar *vncport = xmlGetProp(node, BAD_CAST "port");
541
xmlChar *vnclisten = xmlGetProp(node, BAD_CAST "listen");
542
xmlChar *vncpasswd = xmlGetProp(node, BAD_CAST "passwd");
543
xmlChar *keymap = xmlGetProp(node, BAD_CAST "keymap");
544
if (vncport != NULL) {
545
long port = strtol((const char *)vncport, NULL, 10);
547
virBufferAdd(buf, "(vncunused 1)", 13);
548
else if (port >= 5900)
549
virBufferVSprintf(buf, "(vncdisplay %ld)", port - 5900);
552
if (vnclisten != NULL) {
553
virBufferVSprintf(buf, "(vnclisten %s)", vnclisten);
556
if (vncpasswd != NULL) {
557
virBufferVSprintf(buf, "(vncpasswd %s)", vncpasswd);
560
if (keymap != NULL) {
561
virBufferVSprintf(buf, "(keymap %s)", keymap);
565
virBufferAdd(buf, "))", 2);
614
566
xmlFree(graphics_type);
648
603
&& (xmlStrEqual(cur->name, BAD_CAST "type"))) {
649
604
txt = cur->children;
650
605
if ((txt != NULL) && (txt->type == XML_TEXT_NODE) &&
652
607
type = txt->content;
653
608
} else if ((loader == NULL) &&
654
609
(xmlStrEqual(cur->name, BAD_CAST "loader"))) {
655
610
txt = cur->children;
656
611
if ((txt != NULL) && (txt->type == XML_TEXT_NODE) &&
658
613
loader = txt->content;
659
} else if ((boot_dev == NULL) &&
660
(xmlStrEqual(cur->name, BAD_CAST "boot"))) {
661
boot_dev = xmlGetProp(cur, BAD_CAST "dev");
614
} else if ((xmlStrEqual(cur->name, BAD_CAST "boot"))) {
615
xmlChar *boot_dev = xmlGetProp(cur, BAD_CAST "dev");
616
if (nbootorder == ((sizeof(bootorder)/sizeof(bootorder[0]))-1)) {
617
virXMLError(conn, VIR_ERR_XML_ERROR, "too many boot devices", 0);
620
if (xmlStrEqual(boot_dev, BAD_CAST "fd")) {
621
bootorder[nbootorder++] = 'a';
622
} else if (xmlStrEqual(boot_dev, BAD_CAST "cdrom")) {
623
bootorder[nbootorder++] = 'd';
624
} else if (xmlStrEqual(boot_dev, BAD_CAST "network")) {
625
bootorder[nbootorder++] = 'n';
626
} else if (xmlStrEqual(boot_dev, BAD_CAST "hd")) {
627
bootorder[nbootorder++] = 'c';
630
/* Any other type of boot dev is unsupported right now */
631
virXMLError(conn, VIR_ERR_XML_ERROR, NULL, 0);
639
bootorder[nbootorder] = '\0';
666
640
if ((type == NULL) || (!xmlStrEqual(type, BAD_CAST "hvm"))) {
667
641
/* VIR_ERR_OS_TYPE */
668
virXMLError(VIR_ERR_OS_TYPE, (const char *) type, 0);
642
virXMLError(conn, VIR_ERR_OS_TYPE, (const char *) type, 0);
671
645
virBufferAdd(buf, "(image (hvm ", 12);
672
646
if (loader == NULL) {
673
virXMLError(VIR_ERR_NO_KERNEL, NULL, 0);
647
virXMLError(conn, VIR_ERR_NO_KERNEL, NULL, 0);
676
virBufferVSprintf(buf, "(kernel '%s')", (const char *) loader);
650
virBufferVSprintf(buf, "(kernel '%s')", (const char *) loader);
679
653
/* get the device emulation model */
680
obj = xmlXPathEval(BAD_CAST "string(/domain/devices/emulator[1])", ctxt);
681
if ((obj == NULL) || (obj->type != XPATH_STRING) ||
682
(obj->stringval == NULL) || (obj->stringval[0] == 0)) {
683
virXMLError(VIR_ERR_NO_KERNEL, NULL, 0); /* TODO: error */
686
virBufferVSprintf(buf, "(device_model '%s')",
687
(const char *) obj->stringval);
688
xmlXPathFreeObject(obj);
692
if (xmlStrEqual(boot_dev, BAD_CAST "fd")) {
693
virBufferVSprintf(buf, "(boot a)", (const char *) boot_dev);
694
} else if (xmlStrEqual(boot_dev, BAD_CAST "cdrom")) {
695
virBufferVSprintf(buf, "(boot d)", (const char *) boot_dev);
696
} else if (xmlStrEqual(boot_dev, BAD_CAST "hd")) {
697
virBufferVSprintf(buf, "(boot c)", (const char *) boot_dev);
699
/* Any other type of boot dev is unsupported right now */
700
virXMLError(VIR_ERR_XML_ERROR, NULL, 0);
703
/* get the 1st floppy device file */
704
obj = xmlXPathEval(BAD_CAST "/domain/devices/disk[@device='floppy' and target/@dev='fda']/source", ctxt);
705
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
706
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) {
707
cur = obj->nodesetval->nodeTab[0];
708
virBufferVSprintf(buf, "(fda '%s')",
709
(const char *) xmlGetProp(cur, BAD_CAST "file"));
713
xmlXPathFreeObject(obj);
717
/* get the 2nd floppy device file */
718
obj = xmlXPathEval(BAD_CAST "/domain/devices/disk[@device='floppy' and target/@dev='fdb']/source", ctxt);
719
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
720
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) {
721
xmlChar *fdfile = NULL;
722
cur = obj->nodesetval->nodeTab[0];
723
fdfile = xmlGetProp(cur, BAD_CAST "file");
724
virBufferVSprintf(buf, "(fdb '%s')",
725
(const char *) fdfile);
730
xmlXPathFreeObject(obj);
735
/* get the cdrom device file */
736
/* Only XenD <= 3.0.2 wants cdrom config here */
737
if (xendConfigVersion == 1) {
738
obj = xmlXPathEval(BAD_CAST "/domain/devices/disk[@device='cdrom' and target/@dev='hdc']/source", ctxt);
739
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
740
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) {
741
xmlChar *cdfile = NULL;
742
cur = obj->nodesetval->nodeTab[0];
743
cdfile = xmlGetProp(cur, BAD_CAST "file");
744
virBufferVSprintf(buf, "(cdrom '%s')",
745
(const char *)cdfile);
750
xmlXPathFreeObject(obj);
755
obj = xmlXPathEval(BAD_CAST "/domain/features/acpi", ctxt);
756
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
757
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) {
758
virBufferAdd(buf, "(acpi 1)", 8);
761
xmlXPathFreeObject(obj);
762
obj = xmlXPathEval(BAD_CAST "/domain/features/apic", ctxt);
763
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
764
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) {
765
virBufferAdd(buf, "(apic 1)", 8);
768
xmlXPathFreeObject(obj);
769
obj = xmlXPathEval(BAD_CAST "/domain/features/pae", ctxt);
770
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
771
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) {
772
virBufferAdd(buf, "(pae 1)", 7);
775
xmlXPathFreeObject(obj);
779
obj = xmlXPathEval(BAD_CAST "count(domain/devices/console) > 0", ctxt);
780
if ((obj == NULL) || (obj->type != XPATH_BOOLEAN)) {
781
virXMLError(VIR_ERR_XML_ERROR, NULL, 0);
785
virBufferAdd(buf, "(serial pty)", 12);
787
xmlXPathFreeObject(obj);
790
/* Is a graphics device specified? */
791
obj = xmlXPathEval(BAD_CAST "/domain/devices/graphics[1]", ctxt);
792
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
793
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr > 0)) {
794
res = virDomainParseXMLGraphicsDesc(obj->nodesetval->nodeTab[0], buf, xendConfigVersion);
799
xmlXPathFreeObject(obj);
654
str = virXPathString("string(/domain/devices/emulator[1])", ctxt);
656
virXMLError(conn, VIR_ERR_NO_KERNEL, NULL, 0); /* TODO: error */
659
virBufferVSprintf(buf, "(device_model '%s')", str);
662
virBufferVSprintf(buf, "(vcpus %d)", vcpus);
665
virBufferVSprintf(buf, "(boot %s)", bootorder);
667
/* get the 1st floppy device file */
668
cur = virXPathNode("/domain/devices/disk[@device='floppy' and target/@dev='fda']/source",
672
fdfile = xmlGetProp(cur, BAD_CAST "file");
673
if (fdfile != NULL) {
674
virBufferVSprintf(buf, "(fda '%s')", fdfile);
679
/* get the 2nd floppy device file */
680
cur = virXPathNode("/domain/devices/disk[@device='floppy' and target/@dev='fdb']/source",
684
fdfile = xmlGetProp(cur, BAD_CAST "file");
685
if (fdfile != NULL) {
686
virBufferVSprintf(buf, "(fdb '%s')", fdfile);
692
/* get the cdrom device file */
693
/* Only XenD <= 3.0.2 wants cdrom config here */
694
if (xendConfigVersion == 1) {
695
cur = virXPathNode("/domain/devices/disk[@device='cdrom' and target/@dev='hdc']/source",
700
cdfile = xmlGetProp(cur, BAD_CAST "file");
701
if (cdfile != NULL) {
702
virBufferVSprintf(buf, "(cdrom '%s')",
703
(const char *)cdfile);
709
if (virXPathNode("/domain/features/acpi", ctxt) != NULL)
710
virBufferAdd(buf, "(acpi 1)", 8);
711
if (virXPathNode("/domain/features/apic", ctxt) != NULL)
712
virBufferAdd(buf, "(apic 1)", 8);
713
if (virXPathNode("/domain/features/pae", ctxt) != NULL)
714
virBufferAdd(buf, "(pae 1)", 7);
716
res = virXPathBoolean("count(domain/devices/console) > 0", ctxt);
718
virXMLError(conn, VIR_ERR_XML_ERROR, NULL, 0);
722
virBufferAdd(buf, "(serial pty)", 12);
725
/* HVM graphics for xen <= 3.0.5 */
726
if (xendConfigVersion < 4) {
727
/* Is a graphics device specified? */
728
cur = virXPathNode("/domain/devices/graphics[1]", ctxt);
730
res = virDomainParseXMLGraphicsDescImage(conn, cur, buf,
801
738
virBufferAdd(buf, "))", 2);
811
xmlXPathFreeObject(obj);
816
747
* virDomainParseXMLOSDescPV:
748
* @conn: pointer to the hypervisor connection
817
749
* @node: node containing PV OS description
818
750
* @buf: a buffer for the result S-Expr
819
751
* @ctxt: a path context representing the XML description
1211
1226
* extract some of the basics, name, memory, cpus ...
1213
obj = xmlXPathEval(BAD_CAST "string(/domain/name[1])", ctxt);
1214
if ((obj == NULL) || (obj->type != XPATH_STRING) ||
1215
(obj->stringval == NULL) || (obj->stringval[0] == 0)) {
1216
virXMLError(VIR_ERR_NO_NAME, xmldesc, 0);
1219
virBufferVSprintf(&buf, "(name '%s')", obj->stringval);
1220
nam = strdup((const char *) obj->stringval);
1228
nam = virXPathString("string(/domain/name[1])", ctxt);
1221
1229
if (nam == NULL) {
1222
virXMLError(VIR_ERR_NO_MEMORY, "copying name", 0);
1230
virXMLError(conn, VIR_ERR_NO_NAME, xmldesc, 0);
1225
xmlXPathFreeObject(obj);
1227
obj = xmlXPathEval(BAD_CAST "number(/domain/memory[1])", ctxt);
1228
if ((obj == NULL) || (obj->type != XPATH_NUMBER) ||
1229
(isnan(obj->floatval)) || (obj->floatval < 64000)) {
1230
virBufferVSprintf(&buf, "(memory 128)(maxmem 128)");
1232
unsigned long mem = (obj->floatval / 1024);
1234
virBufferVSprintf(&buf, "(memory %lu)(maxmem %lu)", mem, mem);
1236
xmlXPathFreeObject(obj);
1238
obj = xmlXPathEval(BAD_CAST "number(/domain/vcpu[1])", ctxt);
1239
if ((obj == NULL) || (obj->type != XPATH_NUMBER) ||
1240
(isnan(obj->floatval)) || (obj->floatval <= 0)) {
1241
virBufferVSprintf(&buf, "(vcpus 1)");
1243
unsigned int cpu = (unsigned int) obj->floatval;
1245
virBufferVSprintf(&buf, "(vcpus %u)", cpu);
1247
xmlXPathFreeObject(obj);
1249
obj = xmlXPathEval(BAD_CAST "string(/domain/uuid[1])", ctxt);
1250
if ((obj == NULL) || ((obj->type == XPATH_STRING) &&
1251
(obj->stringval != NULL) && (obj->stringval[0] != 0))) {
1252
virBufferVSprintf(&buf, "(uuid '%s')", obj->stringval);
1254
xmlXPathFreeObject(obj);
1256
obj = xmlXPathEval(BAD_CAST "string(/domain/bootloader[1])", ctxt);
1257
if ((obj != NULL) && (obj->type == XPATH_STRING) &&
1258
(obj->stringval != NULL) && (obj->stringval[0] != 0)) {
1259
virBufferVSprintf(&buf, "(bootloader '%s')", obj->stringval);
1262
xmlXPathFreeObject(obj);
1264
obj = xmlXPathEval(BAD_CAST "string(/domain/on_poweroff[1])", ctxt);
1265
if ((obj != NULL) && (obj->type == XPATH_STRING) &&
1266
(obj->stringval != NULL) && (obj->stringval[0] != 0)) {
1267
virBufferVSprintf(&buf, "(on_poweroff '%s')", obj->stringval);
1269
xmlXPathFreeObject(obj);
1271
obj = xmlXPathEval(BAD_CAST "string(/domain/on_reboot[1])", ctxt);
1272
if ((obj != NULL) && (obj->type == XPATH_STRING) &&
1273
(obj->stringval != NULL) && (obj->stringval[0] != 0)) {
1274
virBufferVSprintf(&buf, "(on_reboot '%s')", obj->stringval);
1276
xmlXPathFreeObject(obj);
1278
obj = xmlXPathEval(BAD_CAST "string(/domain/on_crash[1])", ctxt);
1279
if ((obj != NULL) && (obj->type == XPATH_STRING) &&
1280
(obj->stringval != NULL) && (obj->stringval[0] != 0)) {
1281
virBufferVSprintf(&buf, "(on_crash '%s')", obj->stringval);
1283
xmlXPathFreeObject(obj);
1285
obj = xmlXPathEval(BAD_CAST "/domain/os[1]", ctxt);
1286
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
1287
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr == 1)) {
1288
/* Analyze of the os description, based on HVM or PV. */
1289
tmpobj = xmlXPathEval(BAD_CAST "string(/domain/os/type[1])", ctxt);
1290
if ((tmpobj != NULL) &&
1291
((tmpobj->type != XPATH_STRING) || (tmpobj->stringval == NULL) ||
1292
(tmpobj->stringval[0] == 0))) {
1293
xmlXPathFreeObject(tmpobj);
1294
virXMLError(VIR_ERR_OS_TYPE, nam, 0);
1298
if ((tmpobj == NULL) || !xmlStrEqual(tmpobj->stringval, BAD_CAST "hvm")) {
1299
res = virDomainParseXMLOSDescPV(obj->nodesetval->nodeTab[0], &buf, ctxt, xendConfigVersion);
1302
res = virDomainParseXMLOSDescHVM(obj->nodesetval->nodeTab[0], &buf, ctxt, xendConfigVersion);
1305
xmlXPathFreeObject(tmpobj);
1309
} else if (bootloader == 0) {
1310
virXMLError(VIR_ERR_NO_OS, nam, 0);
1313
xmlXPathFreeObject(obj);
1233
virBufferVSprintf(&buf, "(name '%s')", nam);
1235
if ((virXPathNumber("number(/domain/memory[1])", ctxt, &f) < 0) ||
1236
(f < MIN_XEN_GUEST_SIZE * 1024)) {
1239
max_mem = (f / 1024);
1242
if ((virXPathNumber("number(/domain/currentMemory[1])", ctxt, &f) < 0) ||
1243
(f < MIN_XEN_GUEST_SIZE * 1024)) {
1247
if (mem > max_mem) {
1251
virBufferVSprintf(&buf, "(memory %lu)(maxmem %lu)", mem, max_mem);
1253
if ((virXPathNumber("number(/domain/vcpu[1])", ctxt, &f) == 0) &&
1255
vcpus = (unsigned int) f;
1257
virBufferVSprintf(&buf, "(vcpus %u)", vcpus);
1259
str = virXPathString("string(/domain/uuid[1])", ctxt);
1261
virBufferVSprintf(&buf, "(uuid '%s')", str);
1265
str = virXPathString("string(/domain/bootloader[1])", ctxt);
1267
virBufferVSprintf(&buf, "(bootloader '%s')", str);
1269
* if using pygrub, the kernel and initrd strings are not
1270
* significant and should be discarded
1272
if (strstr(str, "pygrub"))
1279
str = virXPathString("string(/domain/on_poweroff[1])", ctxt);
1281
virBufferVSprintf(&buf, "(on_poweroff '%s')", str);
1285
str = virXPathString("string(/domain/on_reboot[1])", ctxt);
1287
virBufferVSprintf(&buf, "(on_reboot '%s')", str);
1291
str = virXPathString("string(/domain/on_crash[1])", ctxt);
1293
virBufferVSprintf(&buf, "(on_crash '%s')", str);
1297
if (bootloader != 2) {
1298
if ((node = virXPathNode("/domain/os[1]", ctxt)) != NULL) {
1299
/* Analyze of the os description, based on HVM or PV. */
1300
str = virXPathString("string(/domain/os/type[1])", ctxt);
1302
if ((str == NULL) || (strcmp(str, "hvm"))) {
1303
res = virDomainParseXMLOSDescPV(conn, node,
1304
&buf, ctxt, xendConfigVersion);
1307
res = virDomainParseXMLOSDescHVM(conn, node, &buf, ctxt,
1308
vcpus, xendConfigVersion);
1311
if (str != NULL) free(str);
1315
} else if (bootloader == 0) {
1316
virXMLError(conn, VIR_ERR_NO_OS, nam, 0);
1315
1321
/* analyze of the devices */
1316
obj = xmlXPathEval(BAD_CAST "/domain/devices/disk", ctxt);
1317
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
1318
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) {
1319
for (i = 0; i < obj->nodesetval->nodeNr; i++) {
1320
res = virDomainParseXMLDiskDesc(obj->nodesetval->nodeTab[i], &buf, hvm, xendConfigVersion);
1322
nb_nodes = virXPathNodeSet("/domain/devices/disk", ctxt, &nodes);
1324
for (i = 0; i < nb_nodes; i++) {
1325
res = virDomainParseXMLDiskDesc(conn, nodes[i], &buf,
1326
hvm, xendConfigVersion);
1326
xmlXPathFreeObject(obj);
1328
obj = xmlXPathEval(BAD_CAST "/domain/devices/interface", ctxt);
1329
if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
1330
(obj->nodesetval != NULL) && (obj->nodesetval->nodeNr >= 0)) {
1331
for (i = 0; i < obj->nodesetval->nodeNr; i++) {
1335
nb_nodes = virXPathNodeSet("/domain/devices/interface", ctxt, &nodes);
1337
for (i = 0; i < nb_nodes; i++) {
1332
1338
virBufferAdd(&buf, "(device ", 8);
1333
res = virDomainParseXMLIfDesc(obj->nodesetval->nodeTab[i], &buf, hvm);
1339
res = virDomainParseXMLIfDesc(conn, nodes[i], &buf, hvm);
1334
1340
if (res != 0) {
1337
1344
virBufferAdd(&buf, ")", 1);
1340
xmlXPathFreeObject(obj);
1349
/* New style PV graphics config xen >= 3.0.4,
1350
* or HVM graphics config xen >= 3.0.5 */
1351
if ((xendConfigVersion >= 3 && !hvm) ||
1352
(xendConfigVersion >= 4 && hvm)) {
1353
nb_nodes = virXPathNodeSet("/domain/devices/graphics", ctxt, &nodes);
1355
for (i = 0; i < nb_nodes; i++) {
1356
res = virDomainParseXMLGraphicsDescVFB(conn, nodes[i], &buf);
1343
1367
virBufferAdd(&buf, ")", 1); /* closes (vm */
1387
1412
* pairs as long as there is 32 of them in the end.
1390
for (i = 0;i < 16;) {
1415
for (i = 0;i < VIR_UUID_BUFLEN;) {
1391
1416
rawuuid[i] = 0;
1394
if ((*cur == '-') || (*cur == ' ')) {
1398
if ((*cur >= '0') && (*cur <= '9'))
1399
rawuuid[i] = *cur - '0';
1400
else if ((*cur >= 'a') && (*cur <= 'f'))
1401
rawuuid[i] = *cur - 'a' + 10;
1402
else if ((*cur >= 'A') && (*cur <= 'F'))
1403
rawuuid[i] = *cur - 'A' + 10;
1419
if ((*cur == '-') || (*cur == ' ')) {
1423
if ((*cur >= '0') && (*cur <= '9'))
1424
rawuuid[i] = *cur - '0';
1425
else if ((*cur >= 'a') && (*cur <= 'f'))
1426
rawuuid[i] = *cur - 'a' + 10;
1427
else if ((*cur >= 'A') && (*cur <= 'F'))
1428
rawuuid[i] = *cur - 'A' + 10;
1410
if ((*cur >= '0') && (*cur <= '9'))
1411
rawuuid[i] += *cur - '0';
1412
else if ((*cur >= 'a') && (*cur <= 'f'))
1413
rawuuid[i] += *cur - 'a' + 10;
1414
else if ((*cur >= 'A') && (*cur <= 'F'))
1415
rawuuid[i] += *cur - 'A' + 10;
1435
if ((*cur >= '0') && (*cur <= '9'))
1436
rawuuid[i] += *cur - '0';
1437
else if ((*cur >= 'a') && (*cur <= 'f'))
1438
rawuuid[i] += *cur - 'a' + 10;
1439
else if ((*cur >= 'A') && (*cur <= 'F'))
1440
rawuuid[i] += *cur - 'A' + 10;
1422
1447
dst_uuid = (unsigned char *) *ptr;
1425
for (i = 0; i < 16; i++)
1450
for (i = 0; i < VIR_UUID_BUFLEN; i++)
1426
1451
dst_uuid[i] = rawuuid[i] & 0xFF;
1429
1454
return(dst_uuid);
1459
* virParseXMLDevice:
1460
* @conn: pointer to the hypervisor connection
1461
* @xmldesc: string with the XML description
1462
* @hvm: 1 for fully virtualized guest, 0 for paravirtualized
1463
* @xendConfigVersion: xend configuration file format
1465
* Parse the XML description and turn it into the xend sexp needed to
1466
* create the device. This is a temporary interface as the S-Expr interface
1467
* will be replaced by XML-RPC in the future. However the XML format should
1468
* stay valid over time.
1470
* Returns the 0-terminated S-Expr string, or NULL in case of error.
1471
* the caller must free() the returned value.
1474
virParseXMLDevice(virConnectPtr conn, char *xmldesc, int hvm, int xendConfigVersion)
1476
xmlDocPtr xml = NULL;
1480
buf.content = malloc(1000);
1481
if (buf.content == NULL)
1485
xml = xmlReadDoc((const xmlChar *) xmldesc, "domain.xml", NULL,
1486
XML_PARSE_NOENT | XML_PARSE_NONET |
1487
XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
1490
node = xmlDocGetRootElement(xml);
1493
if (xmlStrEqual(node->name, BAD_CAST "disk")) {
1494
if (virDomainParseXMLDiskDesc(conn, node, &buf, hvm, xendConfigVersion) != 0)
1497
else if (xmlStrEqual(node->name, BAD_CAST "interface")) {
1498
if (virDomainParseXMLIfDesc(conn, node, &buf, hvm) != 0)
1512
* virDomainXMLDevID:
1513
* @domain: pointer to domain object
1514
* @xmldesc: string with the XML description
1515
* @class: Xen device class "vbd" or "vif" (OUT)
1516
* @ref: Xen device reference (OUT)
1518
* Set class according to XML root, and:
1519
* - if disk, copy in ref the target name from description
1520
* - if network, get MAC address from description, scan XenStore and
1521
* copy in ref the corresponding vif number.
1523
* Returns 0 in case of success, -1 in case of failure.
1526
virDomainXMLDevID(virDomainPtr domain, char *xmldesc, char *class, char *ref)
1528
xmlDocPtr xml = NULL;
1529
xmlNodePtr node, cur;
1530
xmlChar *attr = NULL;
1533
#endif /* WITH_XEN */
1536
xml = xmlReadDoc((const xmlChar *) xmldesc, "domain.xml", NULL,
1537
XML_PARSE_NOENT | XML_PARSE_NONET |
1538
XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
1541
node = xmlDocGetRootElement(xml);
1544
if (xmlStrEqual(node->name, BAD_CAST "disk")) {
1545
strcpy(class, "vbd");
1546
for (cur = node->children; cur != NULL; cur = cur->next) {
1547
if ((cur->type != XML_ELEMENT_NODE) ||
1548
(!xmlStrEqual(cur->name, BAD_CAST "target"))) continue;
1549
attr = xmlGetProp(cur, BAD_CAST "dev");
1552
strcpy(ref, (char *)attr);
1556
else if (xmlStrEqual(node->name, BAD_CAST "interface")) {
1557
strcpy(class, "vif");
1558
for (cur = node->children; cur != NULL; cur = cur->next) {
1559
if ((cur->type != XML_ELEMENT_NODE) ||
1560
(!xmlStrEqual(cur->name, BAD_CAST "mac"))) continue;
1561
attr = xmlGetProp(cur, BAD_CAST "address");
1566
xref = xenStoreDomainGetNetworkID(domain->conn, domain->id,
1573
#else /* without xen */
1574
/* hack to avoid the warning that domain is unused */
1577
#endif /* WITH_XEN */
1433
1594
* Local variables:
1434
1595
* indent-tabs-mode: nil