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

« back to all changes in this revision

Viewing changes to src/xml.c

Tags: upstream-0.2.2
ImportĀ upstreamĀ versionĀ 0.2.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
#include <stdlib.h>
15
15
#include <string.h>
16
16
#include <stdarg.h>
 
17
#ifdef WITH_XEN
17
18
#include <xs.h>
18
 
#include <libxml/parser.h>
19
 
#include <libxml/tree.h>
20
 
#include <libxml/xpath.h>
 
19
#endif
21
20
#include <math.h> /* for isnan() */
22
21
#include "internal.h"
23
22
#include "hash.h"
24
23
#include "sexpr.h"
25
24
#include "xml.h"
 
25
#include "xs_internal.h" /* for xenStoreDomainGetNetworkID */
26
26
 
 
27
/**
 
28
 * virXMLError:
 
29
 * @conn: a connection if any
 
30
 * @error: the error number
 
31
 * @info: information/format string
 
32
 * @value: extra integer parameter for the error string
 
33
 *
 
34
 * Report an error coming from the XML module.
 
35
 */
27
36
static void
28
 
virXMLError(virErrorNumber error, const char *info, int value)
 
37
virXMLError(virConnectPtr conn, virErrorNumber error, const char *info, int value)
29
38
{
30
39
    const char *errmsg;
31
40
 
33
42
        return;
34
43
 
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);
38
47
}
39
48
 
 
49
#ifndef PROXY
 
50
/**
 
51
 * virXPathString:
 
52
 * @xpath: the XPath string to evaluate
 
53
 * @ctxt: an XPath context
 
54
 *
 
55
 * Convenience function to evaluate an XPath string
 
56
 *
 
57
 * Returns a new string which must be deallocated by the caller or NULL
 
58
 *         if the evaluation failed.
 
59
 */
 
60
char *
 
61
virXPathString(const char *xpath, xmlXPathContextPtr ctxt) {
 
62
    xmlXPathObjectPtr obj;
 
63
    char *ret;
 
64
 
 
65
    if ((ctxt == NULL) || (xpath == NULL)) {
 
66
        virXMLError(NULL, VIR_ERR_INTERNAL_ERROR, 
 
67
                    "Invalid parameter to virXPathString()", 0);
 
68
        return(NULL);
 
69
    }
 
70
    obj = xmlXPathEval(BAD_CAST xpath, ctxt);
 
71
    if ((obj == NULL) || (obj->type != XPATH_STRING) ||
 
72
        (obj->stringval == NULL) || (obj->stringval[0] == 0))
 
73
        return(NULL);
 
74
    ret = strdup((char *) obj->stringval);
 
75
    xmlXPathFreeObject(obj);
 
76
    if (ret == NULL) {
 
77
        virXMLError(NULL, VIR_ERR_NO_MEMORY, "strdup", 0);
 
78
    }
 
79
    return(ret);
 
80
}
 
81
 
 
82
/**
 
83
 * virXPathNumber:
 
84
 * @xpath: the XPath string to evaluate
 
85
 * @ctxt: an XPath context
 
86
 * @value: the returned double value
 
87
 *
 
88
 * Convenience function to evaluate an XPath number
 
89
 *
 
90
 * Returns 0 in case of success in which case @value is set,
 
91
 *         or -1 if the evaluation failed.
 
92
 */
 
93
int
 
94
virXPathNumber(const char *xpath, xmlXPathContextPtr ctxt, double *value) {
 
95
    xmlXPathObjectPtr obj;
 
96
 
 
97
    if ((ctxt == NULL) || (xpath == NULL) || (value == NULL)) {
 
98
        virXMLError(NULL, VIR_ERR_INTERNAL_ERROR, 
 
99
                    "Invalid parameter to virXPathNumber()", 0);
 
100
        return(-1);
 
101
    }
 
102
    obj = xmlXPathEval(BAD_CAST xpath, ctxt);
 
103
    if ((obj == NULL) || (obj->type != XPATH_NUMBER) ||
 
104
        (isnan(obj->floatval))) {
 
105
        xmlXPathFreeObject(obj);
 
106
        return(-1);
 
107
    }
 
108
    
 
109
    *value = obj->floatval;
 
110
    xmlXPathFreeObject(obj);
 
111
    return(0);
 
112
}
 
113
 
 
114
/**
 
115
 * virXPathLong:
 
116
 * @xpath: the XPath string to evaluate
 
117
 * @ctxt: an XPath context
 
118
 * @value: the returned long value
 
119
 *
 
120
 * Convenience function to evaluate an XPath number
 
121
 *
 
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.
 
125
 */
 
126
int
 
127
virXPathLong(const char *xpath, xmlXPathContextPtr ctxt, long *value) {
 
128
    xmlXPathObjectPtr obj;
 
129
    int ret = 0;
 
130
 
 
131
    if ((ctxt == NULL) || (xpath == NULL) || (value == NULL)) {
 
132
        virXMLError(NULL, VIR_ERR_INTERNAL_ERROR, 
 
133
                    "Invalid parameter to virXPathNumber()", 0);
 
134
        return(-1);
 
135
    }
 
136
    obj = xmlXPathEval(BAD_CAST xpath, ctxt);
 
137
    if ((obj != NULL) && (obj->type == XPATH_STRING) &&
 
138
        (obj->stringval != NULL) && (obj->stringval[0] != 0)) {
 
139
        char *conv = NULL;
 
140
        long val;
 
141
 
 
142
        val = strtol((const char*)obj->stringval, &conv, 10);
 
143
        if (conv == (const char*)obj->stringval) {
 
144
            ret = -2;
 
145
        } else {
 
146
            *value = val;
 
147
        }
 
148
    } else if ((obj != NULL) && (obj->type == XPATH_NUMBER) &&
 
149
               (!(isnan(obj->floatval)))) {
 
150
        *value = (long) obj->floatval;
 
151
        if (*value != obj->floatval) {
 
152
            ret = -2;
 
153
        }
 
154
    } else {
 
155
        ret = -1;
 
156
    }
 
157
    
 
158
    xmlXPathFreeObject(obj);
 
159
    return(ret);
 
160
}
 
161
 
 
162
/**
 
163
 * virXPathBoolean:
 
164
 * @xpath: the XPath string to evaluate
 
165
 * @ctxt: an XPath context
 
166
 *
 
167
 * Convenience function to evaluate an XPath boolean
 
168
 *
 
169
 * Returns 0 if false, 1 if true, or -1 if the evaluation failed.
 
170
 */
 
171
int
 
172
virXPathBoolean(const char *xpath, xmlXPathContextPtr ctxt) {
 
173
    xmlXPathObjectPtr obj;
 
174
    int ret;
 
175
 
 
176
    if ((ctxt == NULL) || (xpath == NULL)) {
 
177
        virXMLError(NULL, VIR_ERR_INTERNAL_ERROR, 
 
178
                    "Invalid parameter to virXPathBoolean()", 0);
 
179
        return(-1);
 
180
    }
 
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);
 
185
        return(-1);
 
186
    }
 
187
    ret = obj->boolval;
 
188
    
 
189
    xmlXPathFreeObject(obj);
 
190
    return(ret);
 
191
}
 
192
 
 
193
/**
 
194
 * virXPathNode:
 
195
 * @xpath: the XPath string to evaluate
 
196
 * @ctxt: an XPath context
 
197
 *
 
198
 * Convenience function to evaluate an XPath node set and returning
 
199
 * only one node, the first one in the set if any
 
200
 *
 
201
 * Returns a pointer to the node or NULL if the evaluation failed.
 
202
 */
 
203
xmlNodePtr
 
204
virXPathNode(const char *xpath, xmlXPathContextPtr ctxt) {
 
205
    xmlXPathObjectPtr obj;
 
206
    xmlNodePtr ret;
 
207
 
 
208
    if ((ctxt == NULL) || (xpath == NULL)) {
 
209
        virXMLError(NULL, VIR_ERR_INTERNAL_ERROR, 
 
210
                    "Invalid parameter to virXPathNode()", 0);
 
211
        return(NULL);
 
212
    }
 
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);
 
218
        return(NULL);
 
219
    }
 
220
    
 
221
    ret = obj->nodesetval->nodeTab[0];
 
222
    xmlXPathFreeObject(obj);
 
223
    return(ret);
 
224
}
 
225
/**
 
226
 * virXPathNodeSet:
 
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)
 
230
 *
 
231
 * Convenience function to evaluate an XPath node set
 
232
 *
 
233
 * Returns the number of nodes found in which case @list is set (and
 
234
 *         must be freed) or -1 if the evaluation failed.
 
235
 */
 
236
int
 
237
virXPathNodeSet(const char *xpath, xmlXPathContextPtr ctxt, xmlNodePtr **list) {
 
238
    xmlXPathObjectPtr obj;
 
239
    int ret;
 
240
 
 
241
    if ((ctxt == NULL) || (xpath == NULL)) {
 
242
        virXMLError(NULL, VIR_ERR_INTERNAL_ERROR, 
 
243
                    "Invalid parameter to virXPathNodeSet()", 0);
 
244
        return(-1);
 
245
    }
 
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);
 
251
        if (list != NULL)
 
252
            *list = NULL;
 
253
        return(-1);
 
254
    }
 
255
    
 
256
    ret = obj->nodesetval->nodeNr;
 
257
    if (list != NULL) {
 
258
        *list = malloc(ret * sizeof(xmlNodePtr));
 
259
        if (*list == NULL) {
 
260
            virXMLError(NULL, VIR_ERR_NO_MEMORY, 
 
261
                        _("allocate string array"), ret * sizeof(xmlNodePtr));
 
262
        } else {
 
263
            memcpy(*list, obj->nodesetval->nodeTab, ret * sizeof(xmlNodePtr));
 
264
        }
 
265
    }
 
266
    xmlXPathFreeObject(obj);
 
267
    return(ret);
 
268
}
 
269
#endif /* !PROXY */
 
270
 
40
271
/**
41
272
 * virBufferGrow:
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
44
275
 *
45
 
 * Grow the available space of an XML buffer.
 
276
 * Grow the available space of an XML buffer to at least @len bytes.
46
277
 *
47
278
 * Returns the new available space or -1 in case of error
48
279
 */
61
292
 
62
293
    newbuf = (char *) realloc(buf->content, size);
63
294
    if (newbuf == NULL) {
64
 
        virXMLError(VIR_ERR_NO_MEMORY, _("growing buffer"), size);
 
295
        virXMLError(NULL, VIR_ERR_NO_MEMORY, _("growing buffer"), size);
65
296
        return (-1);
66
297
    }
67
298
    buf->content = newbuf;
96
327
 
97
328
    needSize = buf->use + len + 2;
98
329
    if (needSize > buf->size) {
99
 
        if (!virBufferGrow(buf, needSize)) {
 
330
        if (!virBufferGrow(buf, needSize - buf->use)) {
100
331
            return (-1);
101
332
        }
102
333
    }
113
344
    virBufferPtr buf;
114
345
 
115
346
    if (!(buf = malloc(sizeof(*buf)))) {
116
 
        virXMLError(VIR_ERR_NO_MEMORY, _("allocate new buffer"), sizeof(*buf));
 
347
        virXMLError(NULL, VIR_ERR_NO_MEMORY, _("allocate new buffer"), sizeof(*buf));
117
348
        return NULL;
118
349
    }
119
350
    if (size && (buf->content = malloc(size))==NULL) {
120
 
        virXMLError(VIR_ERR_NO_MEMORY, _("allocate buffer content"), size);
 
351
        virXMLError(NULL, VIR_ERR_NO_MEMORY, _("allocate buffer content"), size);
121
352
        free(buf);
122
353
        return NULL;
123
354
    }
126
357
 
127
358
    return buf;
128
359
}
129
 
        
 
360
 
130
361
void
131
362
virBufferFree(virBufferPtr buf)
132
363
{
133
364
    if (buf) {
134
365
        if (buf->content)
135
 
           free(buf->content);
136
 
        free(buf);
 
366
            free(buf->content);
 
367
        free(buf);
137
368
    }
138
369
}
139
370
 
189
420
{
190
421
    va_list ap;
191
422
    char *str;
192
 
    
 
423
 
193
424
    va_start(ap, buf);
194
 
    
 
425
 
195
426
    while ((str = va_arg(ap, char *)) != NULL) {
196
427
        unsigned int len = strlen(str);
197
428
        unsigned int needSize = buf->use + len + 2;
198
429
 
199
430
        if (needSize > buf->size) {
200
 
           if (!virBufferGrow(buf, needSize))
201
 
              return -1;
202
 
        }
 
431
            if (!virBufferGrow(buf, needSize - buf->use))
 
432
                return -1;
 
433
        }
203
434
        memcpy(&buf->content[buf->use], str, len);
204
435
        buf->use += len;
205
436
        buf->content[buf->use] = 0;
208
439
    return 0;
209
440
}
210
441
 
211
 
#if 0
212
 
 
213
 
/*
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 ...
217
 
 */
218
 
 
219
 
/**
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
225
 
 *
226
 
 * Extract one information the device used by the domain from xensttore
227
 
 *
228
 
 * Returns the new string or NULL in case of error
229
 
 */
230
 
static char *
231
 
virDomainGetXMLDeviceInfo(virDomainPtr domain, const char *sub,
232
 
                          long dev, const char *name)
233
 
{
234
 
    char s[256];
235
 
    unsigned int len = 0;
236
 
 
237
 
    snprintf(s, 255, "/local/domain/0/backend/%s/%d/%ld/%s",
238
 
             sub, domain->handle, dev, name);
239
 
    s[255] = 0;
240
 
 
241
 
    return xs_read(domain->conn->xshandle, 0, &s[0], &len);
242
 
}
243
 
 
244
 
/**
245
 
 * virDomainGetXMLDevice:
246
 
 * @domain: a domain object
247
 
 * @buf: the output buffer object
248
 
 * @dev: the xenstrore internal device number
249
 
 *
250
 
 * Extract and dump in the buffer information on the device used by the domain
251
 
 *
252
 
 * Returns 0 in case of success, -1 in case of failure
253
 
 */
254
 
static int
255
 
virDomainGetXMLDevice(virDomainPtr domain, virBufferPtr buf, long dev)
256
 
{
257
 
    char *type, *val;
258
 
 
259
 
    type = virDomainGetXMLDeviceInfo(domain, "vbd", dev, "type");
260
 
    if (type == NULL)
261
 
        return (-1);
262
 
    if (!strcmp(type, "file")) {
263
 
        virBufferVSprintf(buf, "    <disk type='file'>\n");
264
 
        val = virDomainGetXMLDeviceInfo(domain, "vbd", dev, "params");
265
 
        if (val != NULL) {
266
 
            virBufferVSprintf(buf, "      <source file='%s'/>\n", val);
267
 
            free(val);
268
 
        }
269
 
        val = virDomainGetXMLDeviceInfo(domain, "vbd", dev, "dev");
270
 
        if (val != NULL) {
271
 
            char *tmp = val;
272
 
            if (!strncmp(tmp, "ioemu:", 6))
273
 
                tmp += 6;
274
 
            virBufferVSprintf(buf, "      <target dev='%s'/>\n", tmp);
275
 
            free(val);
276
 
        }
277
 
        val = virDomainGetXMLDeviceInfo(domain, "vbd", dev, "read-only");
278
 
        if (val != NULL) {
279
 
            virBufferVSprintf(buf, "      <readonly/>\n", val);
280
 
            free(val);
281
 
        }
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");
286
 
        if (val != NULL) {
287
 
            virBufferVSprintf(buf, "      <source device='%s'/>\n", val);
288
 
            free(val);
289
 
        }
290
 
        val = virDomainGetXMLDeviceInfo(domain, "vbd", dev, "dev");
291
 
        if (val != NULL) {
292
 
            char *tmp = val;
293
 
            if (!strncmp(tmp, "ioemu:", 6))
294
 
                tmp += 6;
295
 
            virBufferVSprintf(buf, "      <target dev='%s'/>\n", tmp);
296
 
            free(val);
297
 
        }
298
 
        val = virDomainGetXMLDeviceInfo(domain, "vbd", dev, "read-only");
299
 
        if (val != NULL) {
300
 
            virBufferVSprintf(buf, "      <readonly/>\n", val);
301
 
            free(val);
302
 
        }
303
 
        virBufferAdd(buf, "    </disk>\n", 12);
304
 
    } else {
305
 
        TODO fprintf(stderr, "Don't know how to handle device type %s\n",
306
 
                     type);
307
 
    }
308
 
    free(type);
309
 
 
310
 
    return (0);
311
 
}
312
 
 
313
 
/**
314
 
 * virDomainGetXMLDevices:
315
 
 * @domain: a domain object
316
 
 * @buf: the output buffer object
317
 
 *
318
 
 * Extract the devices used by the domain and dumps then in the buffer
319
 
 *
320
 
 * Returns 0 in case of success, -1 in case of failure
321
 
 */
322
 
static int
323
 
virDomainGetXMLDevices(virDomainPtr domain, virBufferPtr buf)
324
 
{
325
 
    int ret = -1;
326
 
    unsigned int num, i;
327
 
    long id;
328
 
    char **list = NULL, *endptr;
329
 
    char backend[200];
330
 
    virConnectPtr conn;
331
 
 
332
 
    if (!VIR_IS_CONNECTED_DOMAIN(domain))
333
 
        return (-1);
334
 
 
335
 
    conn = domain->conn;
336
 
 
337
 
    snprintf(backend, 199, "/local/domain/0/backend/vbd/%d",
338
 
             virDomainGetID(domain));
339
 
    backend[199] = 0;
340
 
    list = xs_directory(conn->xshandle, 0, backend, &num);
341
 
    ret = 0;
342
 
    if (list == NULL)
343
 
        goto done;
344
 
 
345
 
    for (i = 0; i < num; i++) {
346
 
        id = strtol(list[i], &endptr, 10);
347
 
        if ((endptr == list[i]) || (*endptr != 0)) {
348
 
            ret = -1;
349
 
            goto done;
350
 
        }
351
 
        virDomainGetXMLDevice(domain, buf, id);
352
 
    }
353
 
 
354
 
  done:
355
 
    if (list != NULL)
356
 
        free(list);
357
 
 
358
 
    return (ret);
359
 
}
360
 
 
361
 
/**
362
 
 * virDomainGetXMLInterface:
363
 
 * @domain: a domain object
364
 
 * @buf: the output buffer object
365
 
 * @dev: the xenstrore internal device number
366
 
 *
367
 
 * Extract and dump in the buffer information on the interface used by
368
 
 * the domain
369
 
 *
370
 
 * Returns 0 in case of success, -1 in case of failure
371
 
 */
372
 
static int
373
 
virDomainGetXMLInterface(virDomainPtr domain, virBufferPtr buf, long dev)
374
 
{
375
 
    char *type, *val;
376
 
 
377
 
    type = virDomainGetXMLDeviceInfo(domain, "vif", dev, "bridge");
378
 
    if (type == NULL) {
379
 
        virBufferVSprintf(buf, "    <interface type='default'>\n");
380
 
        val = virDomainGetXMLDeviceInfo(domain, "vif", dev, "mac");
381
 
        if (val != NULL) {
382
 
            virBufferVSprintf(buf, "      <mac address='%s'/>\n", val);
383
 
            free(val);
384
 
        }
385
 
        val = virDomainGetXMLDeviceInfo(domain, "vif", dev, "script");
386
 
        if (val != NULL) {
387
 
            virBufferVSprintf(buf, "      <script path='%s'/>\n", val);
388
 
            free(val);
389
 
        }
390
 
        virBufferAdd(buf, "    </interface>\n", 17);
391
 
    } else {
392
 
        virBufferVSprintf(buf, "    <interface type='bridge'>\n");
393
 
        virBufferVSprintf(buf, "      <source bridge='%s'/>\n", type);
394
 
        val = virDomainGetXMLDeviceInfo(domain, "vif", dev, "mac");
395
 
        if (val != NULL) {
396
 
            virBufferVSprintf(buf, "      <mac address='%s'/>\n", val);
397
 
            free(val);
398
 
        }
399
 
        val = virDomainGetXMLDeviceInfo(domain, "vif", dev, "script");
400
 
        if (val != NULL) {
401
 
            virBufferVSprintf(buf, "      <script path='%s'/>\n", val);
402
 
            free(val);
403
 
        }
404
 
        virBufferAdd(buf, "    </interface>\n", 17);
405
 
    }
406
 
    free(type);
407
 
 
408
 
    return (0);
409
 
}
410
 
 
411
 
/**
412
 
 * virDomainGetXMLInterfaces:
413
 
 * @domain: a domain object
414
 
 * @buf: the output buffer object
415
 
 *
416
 
 * Extract the interfaces used by the domain and dumps then in the buffer
417
 
 *
418
 
 * Returns 0 in case of success, -1 in case of failure
419
 
 */
420
 
static int
421
 
virDomainGetXMLInterfaces(virDomainPtr domain, virBufferPtr buf)
422
 
{
423
 
    int ret = -1;
424
 
    unsigned int num, i;
425
 
    long id;
426
 
    char **list = NULL, *endptr;
427
 
    char backend[200];
428
 
    virConnectPtr conn;
429
 
 
430
 
    if (!VIR_IS_CONNECTED_DOMAIN(domain))
431
 
        return (-1);
432
 
 
433
 
    conn = domain->conn;
434
 
 
435
 
    snprintf(backend, 199, "/local/domain/0/backend/vif/%d",
436
 
             virDomainGetID(domain));
437
 
    backend[199] = 0;
438
 
    list = xs_directory(conn->xshandle, 0, backend, &num);
439
 
    ret = 0;
440
 
    if (list == NULL)
441
 
        goto done;
442
 
 
443
 
    for (i = 0; i < num; i++) {
444
 
        id = strtol(list[i], &endptr, 10);
445
 
        if ((endptr == list[i]) || (*endptr != 0)) {
446
 
            ret = -1;
447
 
            goto done;
448
 
        }
449
 
        virDomainGetXMLInterface(domain, buf, id);
450
 
    }
451
 
 
452
 
  done:
453
 
    if (list != NULL)
454
 
        free(list);
455
 
 
456
 
    return (ret);
457
 
}
458
 
 
459
 
 
460
 
 
461
 
 
462
 
/**
463
 
 * virDomainGetXMLBoot:
464
 
 * @domain: a domain object
465
 
 * @buf: the output buffer object
466
 
 *
467
 
 * Extract the boot information used to start that domain
468
 
 *
469
 
 * Returns 0 in case of success, -1 in case of failure
470
 
 */
471
 
static int
472
 
virDomainGetXMLBoot(virDomainPtr domain, virBufferPtr buf)
473
 
{
474
 
    char *vm, *str;
475
 
 
476
 
    if (!VIR_IS_DOMAIN(domain))
477
 
        return (-1);
478
 
 
479
 
    vm = virDomainGetVM(domain);
480
 
    if (vm == NULL)
481
 
        return (-1);
482
 
 
483
 
    virBufferAdd(buf, "  <os>\n", 7);
484
 
    str = virDomainGetVMInfo(domain, vm, "image/ostype");
485
 
    if (str != NULL) {
486
 
        virBufferVSprintf(buf, "    <type>%s</type>\n", str);
487
 
        free(str);
488
 
    }
489
 
    str = virDomainGetVMInfo(domain, vm, "image/kernel");
490
 
    if (str != NULL) {
491
 
        virBufferVSprintf(buf, "    <kernel>%s</kernel>\n", str);
492
 
        free(str);
493
 
    }
494
 
    str = virDomainGetVMInfo(domain, vm, "image/ramdisk");
495
 
    if (str != NULL) {
496
 
        if (str[0] != 0)
497
 
            virBufferVSprintf(buf, "    <initrd>%s</initrd>\n", str);
498
 
        free(str);
499
 
    }
500
 
    str = virDomainGetVMInfo(domain, vm, "image/cmdline");
501
 
    if (str != NULL) {
502
 
        if (str[0] != 0)
503
 
            virBufferVSprintf(buf, "    <cmdline>%s</cmdline>\n", str);
504
 
        free(str);
505
 
    }
506
 
    virBufferAdd(buf, "  </os>\n", 8);
507
 
 
508
 
    free(vm);
509
 
    return (0);
510
 
}
511
 
 
512
 
/**
513
 
 * virDomainGetXMLDesc:
514
 
 * @domain: a domain object
515
 
 * @flags: and OR'ed set of extraction flags, not used yet
516
 
 *
517
 
 * Provide an XML description of the domain. NOTE: this API is subject
518
 
 * to changes.
519
 
 *
520
 
 * Returns a 0 terminated UTF-8 encoded XML instance, or NULL in case of error.
521
 
 *         the caller must free() the returned value.
522
 
 */
523
 
char *
524
 
virDomainGetXMLDesc(virDomainPtr domain, int flags)
525
 
{
526
 
    char *ret = NULL;
527
 
    unsigned char uuid[16];
528
 
    virBuffer buf;
529
 
    virDomainInfo info;
530
 
 
531
 
    if (!VIR_IS_DOMAIN(domain))
532
 
        return (NULL);
533
 
    if (flags != 0)
534
 
        return (NULL);
535
 
    if (virDomainGetInfo(domain, &info) < 0)
536
 
        return (NULL);
537
 
 
538
 
    ret = malloc(1000);
539
 
    if (ret == NULL)
540
 
        return (NULL);
541
 
    buf.content = ret;
542
 
    buf.size = 1000;
543
 
    buf.use = 0;
544
 
 
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]);
556
 
    }
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);
565
 
 
566
 
    buf.content[buf.use] = 0;
567
 
    return (ret);
568
 
}
569
 
 
570
 
#endif /* 0 - UNUSED */
571
442
 
572
443
#ifndef PROXY
573
444
/**
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
578
450
 *
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.
583
455
 *
584
456
 * Returns 0 in case of success, -1 in case of error
585
457
 */
586
 
static int virDomainParseXMLGraphicsDesc(xmlNodePtr node, virBufferPtr buf, int xendConfigVersion)
 
458
static int virDomainParseXMLGraphicsDescImage(virConnectPtr conn ATTRIBUTE_UNUSED, xmlNodePtr node, virBufferPtr buf, int xendConfigVersion)
587
459
{
588
460
    xmlChar *graphics_type = NULL;
589
461
 
591
463
    if (graphics_type != NULL) {
592
464
        if (xmlStrEqual(graphics_type, BAD_CAST "sdl")) {
593
465
            virBufferAdd(buf, "(sdl 1)", 7);
594
 
            // TODO:
595
 
            // Need to understand sdl options
596
 
            //
597
 
            //virBufferAdd(buf, "(display localhost:10.0)", 24);
598
 
            //virBufferAdd(buf, "(xauthority /root/.Xauthority)", 30);
 
466
            /* TODO:
 
467
             * Need to understand sdl options
 
468
             *
 
469
             *virBufferAdd(buf, "(display localhost:10.0)", 24);
 
470
             *virBufferAdd(buf, "(xauthority /root/.Xauthority)", 30);
 
471
             */
599
472
        }
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);
606
482
                    if (port == -1)
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);
611
487
                }
612
 
            }
613
 
        }
 
488
                if (vnclisten != NULL) {
 
489
                    virBufferVSprintf(buf, "(vnclisten %s)", vnclisten);
 
490
                    xmlFree(vnclisten);
 
491
                }
 
492
                if (vncpasswd != NULL) {
 
493
                    virBufferVSprintf(buf, "(vncpasswd %s)", vncpasswd);
 
494
                    xmlFree(vncpasswd);
 
495
                }
 
496
                if (keymap != NULL) {
 
497
                    virBufferVSprintf(buf, "(keymap %s)", keymap);
 
498
                    xmlFree(keymap);
 
499
                }
 
500
            }
 
501
        }
 
502
        xmlFree(graphics_type);
 
503
    }
 
504
    return 0;
 
505
}
 
506
 
 
507
 
 
508
/**
 
509
 * virtDomainParseXMLGraphicsDescVFB:
 
510
 * @conn: pointer to the hypervisor connection
 
511
 * @node: node containing graphics description
 
512
 * @buf: a buffer for the result S-Expr
 
513
 *
 
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
 
517
 * valid over time.
 
518
 *
 
519
 * Returns 0 in case of success, -1 in case of error
 
520
 */
 
521
static int virDomainParseXMLGraphicsDescVFB(virConnectPtr conn ATTRIBUTE_UNUSED, xmlNodePtr node, virBufferPtr buf)
 
522
{
 
523
    xmlChar *graphics_type = NULL;
 
524
 
 
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);
 
531
            /* TODO:
 
532
             * Need to understand sdl options
 
533
             *
 
534
             *virBufferAdd(buf, "(display localhost:10.0)", 24);
 
535
             *virBufferAdd(buf, "(xauthority /root/.Xauthority)", 30);
 
536
             */
 
537
        }
 
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);
 
546
                if (port == -1)
 
547
                    virBufferAdd(buf, "(vncunused 1)", 13);
 
548
                else if (port >= 5900)
 
549
                    virBufferVSprintf(buf, "(vncdisplay %ld)", port - 5900);
 
550
                xmlFree(vncport);
 
551
            }
 
552
            if (vnclisten != NULL) {
 
553
                virBufferVSprintf(buf, "(vnclisten %s)", vnclisten);
 
554
                xmlFree(vnclisten);
 
555
            }
 
556
            if (vncpasswd != NULL) {
 
557
                virBufferVSprintf(buf, "(vncpasswd %s)", vncpasswd);
 
558
                xmlFree(vncpasswd);
 
559
            }
 
560
            if (keymap != NULL) {
 
561
                virBufferVSprintf(buf, "(keymap %s)", keymap);
 
562
                xmlFree(keymap);
 
563
            }
 
564
        }
 
565
        virBufferAdd(buf, "))", 2);
614
566
        xmlFree(graphics_type);
615
567
    }
616
568
    return 0;
619
571
 
620
572
/**
621
573
 * virDomainParseXMLOSDescHVM:
 
574
 * @conn: pointer to the hypervisor connection
622
575
 * @node: node containing HVM OS description
623
576
 * @buf: a buffer for the result S-Expr
624
577
 * @ctxt: a path context representing the XML description
 
578
 * @vcpus: number of virtual CPUs to configure
625
579
 * @xendConfigVersion: xend configuration file format
626
580
 *
627
581
 * Parse the OS part of the XML description for an HVM domain and add it to
632
586
 * Returns 0 in case of success, -1 in case of error.
633
587
 */
634
588
static int
635
 
virDomainParseXMLOSDescHVM(xmlNodePtr node, virBufferPtr buf, xmlXPathContextPtr ctxt, int xendConfigVersion)
 
589
virDomainParseXMLOSDescHVM(virConnectPtr conn, xmlNodePtr node, virBufferPtr buf, xmlXPathContextPtr ctxt, int vcpus, int xendConfigVersion)
636
590
{
637
 
    xmlXPathObjectPtr obj = NULL;
638
591
    xmlNodePtr cur, txt;
639
592
    xmlChar *type = NULL;
640
593
    xmlChar *loader = NULL;
641
 
    xmlChar *boot_dev = NULL;
 
594
    char bootorder[5];
 
595
    int nbootorder = 0;
642
596
    int res;
 
597
    char *str;
643
598
 
644
599
    cur = node->children;
645
600
    while (cur != NULL) {
648
603
                && (xmlStrEqual(cur->name, BAD_CAST "type"))) {
649
604
                txt = cur->children;
650
605
                if ((txt != NULL) && (txt->type == XML_TEXT_NODE) &&
651
 
                    (txt->next == NULL))
 
606
                    (txt->next == NULL))
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) &&
657
 
                    (txt->next == NULL))
 
612
                    (txt->next == NULL))
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);
 
618
                    return (-1);
 
619
                }
 
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';
 
628
                } else {
 
629
                    xmlFree(boot_dev);
 
630
                    /* Any other type of boot dev is unsupported right now */
 
631
                    virXMLError(conn, VIR_ERR_XML_ERROR, NULL, 0);
 
632
                    return (-1);
 
633
                }
 
634
                xmlFree(boot_dev);
662
635
            }
663
636
        }
664
637
        cur = cur->next;
665
638
    }
 
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);
669
643
        return (-1);
670
644
    }
671
645
    virBufferAdd(buf, "(image (hvm ", 12);
672
646
    if (loader == NULL) {
673
 
       virXMLError(VIR_ERR_NO_KERNEL, NULL, 0);
674
 
       goto error;
 
647
        virXMLError(conn, VIR_ERR_NO_KERNEL, NULL, 0);
 
648
        goto error;
675
649
    } else {
676
 
       virBufferVSprintf(buf, "(kernel '%s')", (const char *) loader);
 
650
        virBufferVSprintf(buf, "(kernel '%s')", (const char *) loader);
677
651
    }
678
652
 
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 */
684
 
        goto error;
685
 
    }
686
 
    virBufferVSprintf(buf, "(device_model '%s')",
687
 
                      (const char *) obj->stringval);
688
 
    xmlXPathFreeObject(obj);
689
 
    obj = NULL;
690
 
 
691
 
    if (boot_dev) {
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);
698
 
       } else {
699
 
         /* Any other type of boot dev is unsupported right now */
700
 
         virXMLError(VIR_ERR_XML_ERROR, NULL, 0);
701
 
       }
702
 
 
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"));
710
 
           cur = NULL;
711
 
       }
712
 
       if (obj) {
713
 
           xmlXPathFreeObject(obj);
714
 
           obj = NULL;
715
 
       }
716
 
 
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);
726
 
           xmlFree(fdfile);
727
 
           cur = NULL;
728
 
       }
729
 
       if (obj) {
730
 
           xmlXPathFreeObject(obj);
731
 
           obj = NULL;
732
 
       }
733
 
 
734
 
 
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);
746
 
               xmlFree(cdfile);
747
 
               cur = NULL;
748
 
           }
749
 
           if (obj) {
750
 
               xmlXPathFreeObject(obj);
751
 
               obj = NULL;
752
 
           }
753
 
       }
754
 
 
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);
759
 
       }
760
 
       if (obj)
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);
766
 
       }
767
 
       if (obj)
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);
773
 
       }
774
 
       if (obj)
775
 
           xmlXPathFreeObject(obj);
776
 
       obj = NULL;
777
 
    }
778
 
 
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);
782
 
      goto error;
783
 
    }
784
 
    if (obj->boolval) {
785
 
      virBufferAdd(buf, "(serial pty)", 12);
786
 
    }
787
 
    xmlXPathFreeObject(obj);
788
 
    obj = NULL;
789
 
    
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);
795
 
        if (res != 0) {
796
 
            goto error;
797
 
        }
798
 
    }
799
 
    xmlXPathFreeObject(obj);
 
654
    str = virXPathString("string(/domain/devices/emulator[1])", ctxt);
 
655
    if (str == NULL) {
 
656
        virXMLError(conn, VIR_ERR_NO_KERNEL, NULL, 0); /* TODO: error */
 
657
        goto error;
 
658
    }
 
659
    virBufferVSprintf(buf, "(device_model '%s')", str);
 
660
    xmlFree(str);
 
661
 
 
662
    virBufferVSprintf(buf, "(vcpus %d)", vcpus);
 
663
 
 
664
    if (nbootorder)
 
665
        virBufferVSprintf(buf, "(boot %s)", bootorder);
 
666
 
 
667
    /* get the 1st floppy device file */
 
668
        cur = virXPathNode("/domain/devices/disk[@device='floppy' and target/@dev='fda']/source",
 
669
                       ctxt);
 
670
        if (cur != NULL) {
 
671
        xmlChar *fdfile;
 
672
        fdfile = xmlGetProp(cur, BAD_CAST "file");
 
673
            if (fdfile != NULL) {
 
674
            virBufferVSprintf(buf, "(fda '%s')", fdfile);
 
675
            free(fdfile);
 
676
            }
 
677
    }
 
678
 
 
679
    /* get the 2nd floppy device file */
 
680
        cur = virXPathNode("/domain/devices/disk[@device='floppy' and target/@dev='fdb']/source",
 
681
                       ctxt);
 
682
        if (cur != NULL) {
 
683
        xmlChar *fdfile;
 
684
        fdfile = xmlGetProp(cur, BAD_CAST "file");
 
685
            if (fdfile != NULL) {
 
686
            virBufferVSprintf(buf, "(fdb '%s')", fdfile);
 
687
            free(fdfile);
 
688
            }
 
689
    }
 
690
 
 
691
 
 
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",
 
696
                               ctxt);
 
697
            if (cur != NULL) {
 
698
            xmlChar *cdfile;
 
699
 
 
700
            cdfile = xmlGetProp(cur, BAD_CAST "file");
 
701
            if (cdfile != NULL) {
 
702
                virBufferVSprintf(buf, "(cdrom '%s')",
 
703
                                  (const char *)cdfile);
 
704
                xmlFree(cdfile);
 
705
            }
 
706
        }
 
707
    }
 
708
 
 
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);
 
715
 
 
716
    res = virXPathBoolean("count(domain/devices/console) > 0", ctxt);
 
717
    if (res < 0) {
 
718
        virXMLError(conn, VIR_ERR_XML_ERROR, NULL, 0);
 
719
        goto error;
 
720
    }
 
721
    if (res) {
 
722
        virBufferAdd(buf, "(serial pty)", 12);
 
723
    }
 
724
 
 
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);
 
729
        if (cur != NULL) {
 
730
            res = virDomainParseXMLGraphicsDescImage(conn, cur, buf,
 
731
                                                     xendConfigVersion);
 
732
            if (res != 0) {
 
733
                goto error;
 
734
            }
 
735
        }
 
736
    }
800
737
 
801
738
    virBufferAdd(buf, "))", 2);
802
739
 
803
 
    if (boot_dev)
804
 
        xmlFree(boot_dev);
805
 
 
806
740
    return (0);
807
 
error:
808
 
    if (boot_dev)
809
 
        xmlFree(boot_dev);
810
 
    if (obj != NULL)
811
 
        xmlXPathFreeObject(obj);
 
741
 
 
742
 error:
812
743
    return(-1);
813
744
}
814
745
 
815
746
/**
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
827
759
 * Returns 0 in case of success, -1 in case of error.
828
760
 */
829
761
static int
830
 
virDomainParseXMLOSDescPV(xmlNodePtr node, virBufferPtr buf, xmlXPathContextPtr ctxt, int xendConfigVersion)
 
762
virDomainParseXMLOSDescPV(virConnectPtr conn, xmlNodePtr node, virBufferPtr buf, xmlXPathContextPtr ctxt, int xendConfigVersion)
831
763
{
832
764
    xmlNodePtr cur, txt;
833
 
    xmlXPathObjectPtr obj = NULL;
834
765
    const xmlChar *type = NULL;
835
766
    const xmlChar *root = NULL;
836
767
    const xmlChar *kernel = NULL;
845
776
                && (xmlStrEqual(cur->name, BAD_CAST "type"))) {
846
777
                txt = cur->children;
847
778
                if ((txt != NULL) && (txt->type == XML_TEXT_NODE) &&
848
 
                    (txt->next == NULL))
 
779
                    (txt->next == NULL))
849
780
                    type = txt->content;
850
781
            } else if ((kernel == NULL) &&
851
782
                       (xmlStrEqual(cur->name, BAD_CAST "kernel"))) {
852
783
                txt = cur->children;
853
784
                if ((txt != NULL) && (txt->type == XML_TEXT_NODE) &&
854
 
                    (txt->next == NULL))
 
785
                    (txt->next == NULL))
855
786
                    kernel = txt->content;
856
787
            } else if ((root == NULL) &&
857
788
                       (xmlStrEqual(cur->name, BAD_CAST "root"))) {
858
789
                txt = cur->children;
859
790
                if ((txt != NULL) && (txt->type == XML_TEXT_NODE) &&
860
 
                    (txt->next == NULL))
 
791
                    (txt->next == NULL))
861
792
                    root = txt->content;
862
793
            } else if ((initrd == NULL) &&
863
794
                       (xmlStrEqual(cur->name, BAD_CAST "initrd"))) {
864
795
                txt = cur->children;
865
796
                if ((txt != NULL) && (txt->type == XML_TEXT_NODE) &&
866
 
                    (txt->next == NULL))
 
797
                    (txt->next == NULL))
867
798
                    initrd = txt->content;
868
799
            } else if ((cmdline == NULL) &&
869
800
                       (xmlStrEqual(cur->name, BAD_CAST "cmdline"))) {
870
801
                txt = cur->children;
871
802
                if ((txt != NULL) && (txt->type == XML_TEXT_NODE) &&
872
 
                    (txt->next == NULL))
 
803
                    (txt->next == NULL))
873
804
                    cmdline = txt->content;
874
805
            }
875
806
        }
877
808
    }
878
809
    if ((type != NULL) && (!xmlStrEqual(type, BAD_CAST "linux"))) {
879
810
        /* VIR_ERR_OS_TYPE */
880
 
        virXMLError(VIR_ERR_OS_TYPE, (const char *) type, 0);
 
811
        virXMLError(conn, VIR_ERR_OS_TYPE, (const char *) type, 0);
881
812
        return (-1);
882
813
    }
883
814
    virBufferAdd(buf, "(image (linux ", 14);
884
815
    if (kernel == NULL) {
885
 
        virXMLError(VIR_ERR_NO_KERNEL, NULL, 0);
886
 
        return (-1);
 
816
        virXMLError(conn, VIR_ERR_NO_KERNEL, NULL, 0);
 
817
        return (-1);
887
818
    } else {
888
 
        virBufferVSprintf(buf, "(kernel '%s')", (const char *) kernel);
 
819
        virBufferVSprintf(buf, "(kernel '%s')", (const char *) kernel);
889
820
    }
890
821
    if (initrd != NULL)
891
822
        virBufferVSprintf(buf, "(ramdisk '%s')", (const char *) initrd);
894
825
    if (cmdline != NULL)
895
826
        virBufferVSprintf(buf, "(args '%s')", (const char *) cmdline);
896
827
 
897
 
    /* Is a graphics device specified? */
898
 
    obj = xmlXPathEval(BAD_CAST "/domain/devices/graphics[1]", ctxt);
899
 
    if ((obj != NULL) && (obj->type == XPATH_NODESET) &&
900
 
        (obj->nodesetval != NULL) && (obj->nodesetval->nodeNr > 0)) {
901
 
        res = virDomainParseXMLGraphicsDesc(obj->nodesetval->nodeTab[0], buf, xendConfigVersion);
902
 
        if (res != 0) {
903
 
            goto error;
 
828
    /* PV graphics for xen <= 3.0.4 */
 
829
    if (xendConfigVersion < 3) {
 
830
        cur = virXPathNode("/domain/devices/graphics[1]", ctxt);
 
831
        if (cur != NULL) {
 
832
            res = virDomainParseXMLGraphicsDescImage(conn, cur, buf,
 
833
                                                     xendConfigVersion);
 
834
            if (res != 0) {
 
835
                goto error;
 
836
            }
904
837
        }
905
838
    }
906
 
    xmlXPathFreeObject(obj);
907
839
 
908
840
 error:
909
841
    virBufferAdd(buf, "))", 2);
911
843
}
912
844
 
913
845
/**
 
846
 * virCatchXMLParseError:
 
847
 * @ctx: the context
 
848
 * @msg: the error message
 
849
 * @...: extra arguments
 
850
 *
 
851
 * SAX callback on parsing errors, act as a gate for libvirt own
 
852
 * error reporting.
 
853
 */
 
854
static void
 
855
virCatchXMLParseError(void *ctx, const char *msg ATTRIBUTE_UNUSED, ...) {
 
856
    xmlParserCtxtPtr ctxt = (xmlParserCtxtPtr) ctx;
 
857
 
 
858
    if ((ctxt != NULL) &&
 
859
        (ctxt->lastError.level == XML_ERR_FATAL) &&
 
860
        (ctxt->lastError.message != NULL)) {
 
861
        virXMLError(NULL, VIR_ERR_XML_DETAIL, ctxt->lastError.message,
 
862
                    ctxt->lastError.line);
 
863
    }
 
864
}
 
865
 
 
866
/**
914
867
 * virDomainParseXMLDiskDesc:
915
868
 * @node: node containing disk description
 
869
 * @conn: pointer to the hypervisor connection
916
870
 * @buf: a buffer for the result S-Expr
917
871
 * @xendConfigVersion: xend configuration file format
918
872
 *
924
878
 * Returns 0 in case of success, -1 in case of error.
925
879
 */
926
880
static int
927
 
virDomainParseXMLDiskDesc(xmlNodePtr node, virBufferPtr buf, int hvm, int xendConfigVersion)
 
881
virDomainParseXMLDiskDesc(virConnectPtr conn, xmlNodePtr node, virBufferPtr buf, int hvm, int xendConfigVersion)
928
882
{
929
883
    xmlNodePtr cur;
930
884
    xmlChar *type = NULL;
934
888
    xmlChar *drvName = NULL;
935
889
    xmlChar *drvType = NULL;
936
890
    int ro = 0;
 
891
    int shareable = 0;
937
892
    int typ = 0;
938
893
    int cdrom = 0;
 
894
    int isNoSrcCdrom = 0;
939
895
 
940
896
    type = xmlGetProp(node, BAD_CAST "type");
941
897
    if (type != NULL) {
967
923
                    drvType = xmlGetProp(cur, BAD_CAST "type");
968
924
            } else if (xmlStrEqual(cur->name, BAD_CAST "readonly")) {
969
925
                ro = 1;
 
926
            } else if (xmlStrEqual(cur->name, BAD_CAST "shareable")) {
 
927
                shareable = 1;
970
928
            }
971
929
        }
972
930
        cur = cur->next;
973
931
    }
974
932
 
975
933
    if (source == NULL) {
976
 
        virXMLError(VIR_ERR_NO_SOURCE, (const char *) target, 0);
 
934
        /* There is a case without the source
 
935
         * to the CD-ROM device
 
936
         */
 
937
        if (hvm &&
 
938
            device &&
 
939
            !strcmp((const char *)device, "cdrom")) {
 
940
            isNoSrcCdrom = 1;
 
941
        }
 
942
        if (!isNoSrcCdrom) {
 
943
            virXMLError(conn, VIR_ERR_NO_SOURCE, (const char *) target, 0);
977
944
 
978
 
        if (target != NULL)
979
 
            xmlFree(target);
980
 
        if (device != NULL)
981
 
            xmlFree(device);
982
 
        return (-1);
 
945
            if (target != NULL)
 
946
                xmlFree(target);
 
947
            if (device != NULL)
 
948
                xmlFree(device);
 
949
            return (-1);
 
950
        }
983
951
    }
984
952
    if (target == NULL) {
985
 
        virXMLError(VIR_ERR_NO_TARGET, (const char *) source, 0);
 
953
        virXMLError(conn, VIR_ERR_NO_TARGET, (const char *) source, 0);
986
954
        if (source != NULL)
987
955
            xmlFree(source);
988
956
        if (device != NULL)
1034
1002
    } else
1035
1003
        virBufferVSprintf(buf, "(dev '%s')", (const char *)target);
1036
1004
 
1037
 
    if (drvName) {
 
1005
    if (drvName && !isNoSrcCdrom) {
1038
1006
        if (!strcmp((const char *)drvName, "tap")) {
1039
1007
            virBufferVSprintf(buf, "(uname '%s:%s:%s')",
1040
1008
                              (const char *)drvName,
1045
1013
                              (const char *)drvName,
1046
1014
                              (const char *)source);
1047
1015
        }
1048
 
    } else {
 
1016
    } else if (!isNoSrcCdrom) {
1049
1017
        if (typ == 0)
1050
1018
            virBufferVSprintf(buf, "(uname 'file:%s')", source);
1051
1019
        else if (typ == 1) {
1055
1023
                virBufferVSprintf(buf, "(uname 'phy:/dev/%s')", source);
1056
1024
        }
1057
1025
    }
1058
 
    if (ro == 0)
 
1026
    if (ro == 1)
 
1027
        virBufferVSprintf(buf, "(mode 'r')");
 
1028
    else if (shareable == 1)
 
1029
        virBufferVSprintf(buf, "(mode 'w!')");
 
1030
    else
1059
1031
        virBufferVSprintf(buf, "(mode 'w')");
1060
 
    else if (ro == 1)
1061
 
        virBufferVSprintf(buf, "(mode 'r')");
1062
1032
 
1063
1033
    virBufferAdd(buf, ")", 1);
1064
1034
    virBufferAdd(buf, ")", 1);
1074
1044
 
1075
1045
/**
1076
1046
 * virDomainParseXMLIfDesc:
 
1047
 * @conn: pointer to the hypervisor connection
1077
1048
 * @node: node containing the interface description
1078
1049
 * @buf: a buffer for the result S-Expr
1079
1050
 *
1085
1056
 * Returns 0 in case of success, -1 in case of error.
1086
1057
 */
1087
1058
static int
1088
 
virDomainParseXMLIfDesc(xmlNodePtr node, virBufferPtr buf, int hvm)
 
1059
virDomainParseXMLIfDesc(virConnectPtr conn ATTRIBUTE_UNUSED, xmlNodePtr node, virBufferPtr buf, int hvm)
1089
1060
{
1090
1061
    xmlNodePtr cur;
1091
1062
    xmlChar *type = NULL;
1092
1063
    xmlChar *source = NULL;
1093
1064
    xmlChar *mac = NULL;
1094
1065
    xmlChar *script = NULL;
 
1066
    xmlChar *ip = NULL;
1095
1067
    int typ = 0;
 
1068
    int ret = -1;
1096
1069
 
1097
1070
    type = xmlGetProp(node, BAD_CAST "type");
1098
1071
    if (type != NULL) {
1100
1073
            typ = 0;
1101
1074
        else if (xmlStrEqual(type, BAD_CAST "ethernet"))
1102
1075
            typ = 1;
 
1076
        else if (xmlStrEqual(type, BAD_CAST "network"))
 
1077
            typ = 2;
1103
1078
        xmlFree(type);
1104
1079
    }
1105
1080
    cur = node->children;
1107
1082
        if (cur->type == XML_ELEMENT_NODE) {
1108
1083
            if ((source == NULL) &&
1109
1084
                (xmlStrEqual(cur->name, BAD_CAST "source"))) {
1110
 
 
1111
1085
                if (typ == 0)
1112
1086
                    source = xmlGetProp(cur, BAD_CAST "bridge");
 
1087
                else if (typ == 1)
 
1088
                    source = xmlGetProp(cur, BAD_CAST "dev");
1113
1089
                else
1114
 
                    source = xmlGetProp(cur, BAD_CAST "dev");
 
1090
                    source = xmlGetProp(cur, BAD_CAST "network");
1115
1091
            } else if ((mac == NULL) &&
1116
1092
                       (xmlStrEqual(cur->name, BAD_CAST "mac"))) {
1117
1093
                mac = xmlGetProp(cur, BAD_CAST "address");
1118
1094
            } else if ((script == NULL) &&
1119
1095
                       (xmlStrEqual(cur->name, BAD_CAST "script"))) {
1120
1096
                script = xmlGetProp(cur, BAD_CAST "path");
 
1097
            } else if ((ip == NULL) &&
 
1098
                       (xmlStrEqual(cur->name, BAD_CAST "ip"))) {
 
1099
                /* XXX in future expect to need to have > 1 ip
 
1100
                   address element - eg ipv4 & ipv6. For now
 
1101
                   xen only supports a single address though
 
1102
                   so lets ignore that complication */
 
1103
                ip = xmlGetProp(cur, BAD_CAST "address");
1121
1104
            }
1122
1105
        }
1123
1106
        cur = cur->next;
1129
1112
    if (source != NULL) {
1130
1113
        if (typ == 0)
1131
1114
            virBufferVSprintf(buf, "(bridge '%s')", (const char *) source);
1132
 
        else                    /* TODO does that work like that ? */
 
1115
        else if (typ == 1)      /* TODO does that work like that ? */
1133
1116
            virBufferVSprintf(buf, "(dev '%s')", (const char *) source);
 
1117
        else {
 
1118
            virNetworkPtr network = virNetworkLookupByName(conn, (const char *) source);
 
1119
            char *bridge;
 
1120
            if (!network || !(bridge = virNetworkGetBridgeName(network))) {
 
1121
                virXMLError(conn, VIR_ERR_NO_SOURCE, (const char *) source, 0);
 
1122
                goto error;
 
1123
            }
 
1124
            virBufferVSprintf(buf, "(bridge '%s')", bridge);
 
1125
            free(bridge);
 
1126
        }
1134
1127
    }
1135
1128
    if (script != NULL)
1136
1129
        virBufferVSprintf(buf, "(script '%s')", script);
 
1130
    if (ip != NULL)
 
1131
        virBufferVSprintf(buf, "(ip '%s')", ip);
1137
1132
    if (hvm)
1138
1133
        virBufferAdd(buf, "(type ioemu)", 12);
1139
1134
 
1140
1135
    virBufferAdd(buf, ")", 1);
 
1136
    ret = 0;
 
1137
 error:
1141
1138
    if (mac != NULL)
1142
1139
        xmlFree(mac);
1143
1140
    if (source != NULL)
1144
1141
        xmlFree(source);
1145
1142
    if (script != NULL)
1146
1143
        xmlFree(script);
1147
 
    return (0);
 
1144
    if (ip != NULL)
 
1145
        xmlFree(ip);
 
1146
    return (ret);
1148
1147
}
1149
1148
 
1150
1149
/**
1151
1150
 * virDomainParseXMLDesc:
 
1151
 * @conn: pointer to the hypervisor connection
1152
1152
 * @xmldesc: string with the XML description
1153
1153
 * @xendConfigVersion: xend configuration file format
1154
1154
 *
1161
1161
 *         the caller must free() the returned value.
1162
1162
 */
1163
1163
char *
1164
 
virDomainParseXMLDesc(const char *xmldesc, char **name, int xendConfigVersion)
 
1164
virDomainParseXMLDesc(virConnectPtr conn, const char *xmldesc, char **name, int xendConfigVersion)
1165
1165
{
1166
1166
    xmlDocPtr xml = NULL;
1167
1167
    xmlNodePtr node;
1168
1168
    char *ret = NULL, *nam = NULL;
1169
1169
    virBuffer buf;
1170
1170
    xmlChar *prop;
1171
 
    xmlXPathObjectPtr obj = NULL;
1172
 
    xmlXPathObjectPtr tmpobj = NULL;
 
1171
    xmlParserCtxtPtr pctxt;
1173
1172
    xmlXPathContextPtr ctxt = NULL;
1174
1173
    int i, res;
1175
1174
    int bootloader = 0;
1176
1175
    int hvm = 0;
 
1176
    unsigned int vcpus = 1;
 
1177
    unsigned long mem = 0, max_mem = 0;
 
1178
    char *str;
 
1179
    double f;
 
1180
    xmlNodePtr *nodes;
 
1181
    int nb_nodes;
1177
1182
 
1178
1183
    if (name != NULL)
1179
1184
        *name = NULL;
1184
1189
    buf.size = 1000;
1185
1190
    buf.use = 0;
1186
1191
 
1187
 
    xml = xmlReadDoc((const xmlChar *) xmldesc, "domain.xml", NULL,
1188
 
                     XML_PARSE_NOENT | XML_PARSE_NONET |
1189
 
                     XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
 
1192
    pctxt = xmlNewParserCtxt();
 
1193
    if ((pctxt == NULL) || (pctxt->sax == NULL)) {
 
1194
        goto error;
 
1195
    }
 
1196
 
 
1197
    /* TODO pass the connection point to the error handler:
 
1198
     *   pctxt->userData = virConnectPtr;
 
1199
     */
 
1200
    pctxt->sax->error = virCatchXMLParseError;
 
1201
 
 
1202
    xml = xmlCtxtReadDoc(pctxt, (const xmlChar *) xmldesc, "domain.xml", NULL,
 
1203
                         XML_PARSE_NOENT | XML_PARSE_NONET |
 
1204
                         XML_PARSE_NOWARNING);
1190
1205
    if (xml == NULL) {
1191
1206
        goto error;
1192
1207
    }
1210
1225
    /*
1211
1226
     * extract some of the basics, name, memory, cpus ...
1212
1227
     */
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);
1217
 
        goto error;
1218
 
    }
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);
1223
1231
        goto error;
1224
1232
    }
1225
 
    xmlXPathFreeObject(obj);
1226
 
 
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)");
1231
 
    } else {
1232
 
        unsigned long mem = (obj->floatval / 1024);
1233
 
 
1234
 
        virBufferVSprintf(&buf, "(memory %lu)(maxmem %lu)", mem, mem);
1235
 
    }
1236
 
    xmlXPathFreeObject(obj);
1237
 
 
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)");
1242
 
    } else {
1243
 
        unsigned int cpu = (unsigned int) obj->floatval;
1244
 
 
1245
 
        virBufferVSprintf(&buf, "(vcpus %u)", cpu);
1246
 
    }
1247
 
    xmlXPathFreeObject(obj);
1248
 
 
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);
1253
 
    }
1254
 
    xmlXPathFreeObject(obj);
1255
 
 
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);
1260
 
        bootloader = 1;
1261
 
    }
1262
 
    xmlXPathFreeObject(obj);
1263
 
 
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);
1268
 
    }
1269
 
    xmlXPathFreeObject(obj);
1270
 
 
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);
1275
 
    }
1276
 
    xmlXPathFreeObject(obj);
1277
 
 
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);
1282
 
    }
1283
 
    xmlXPathFreeObject(obj);
1284
 
 
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);
1295
 
            goto error;
1296
 
        }
1297
 
 
1298
 
        if ((tmpobj == NULL) || !xmlStrEqual(tmpobj->stringval, BAD_CAST "hvm")) {
1299
 
            res = virDomainParseXMLOSDescPV(obj->nodesetval->nodeTab[0], &buf, ctxt, xendConfigVersion);
1300
 
        } else {
1301
 
            hvm = 1;
1302
 
            res = virDomainParseXMLOSDescHVM(obj->nodesetval->nodeTab[0], &buf, ctxt, xendConfigVersion);
1303
 
        }
1304
 
 
1305
 
        xmlXPathFreeObject(tmpobj);
1306
 
 
1307
 
        if (res != 0)
1308
 
            goto error;
1309
 
    } else if (bootloader == 0) {
1310
 
        virXMLError(VIR_ERR_NO_OS, nam, 0);
1311
 
        goto error;
1312
 
    }
1313
 
    xmlXPathFreeObject(obj);
 
1233
    virBufferVSprintf(&buf, "(name '%s')", nam);
 
1234
 
 
1235
    if ((virXPathNumber("number(/domain/memory[1])", ctxt, &f) < 0) ||
 
1236
        (f < MIN_XEN_GUEST_SIZE * 1024)) {
 
1237
        max_mem = 128;
 
1238
    } else {
 
1239
        max_mem = (f / 1024);
 
1240
    }
 
1241
 
 
1242
    if ((virXPathNumber("number(/domain/currentMemory[1])", ctxt, &f) < 0) ||
 
1243
        (f < MIN_XEN_GUEST_SIZE * 1024)) {
 
1244
        mem = max_mem;
 
1245
    } else {
 
1246
        mem = (f / 1024);
 
1247
        if (mem > max_mem) {
 
1248
            max_mem = mem;
 
1249
        }
 
1250
    }
 
1251
    virBufferVSprintf(&buf, "(memory %lu)(maxmem %lu)", mem, max_mem);
 
1252
 
 
1253
    if ((virXPathNumber("number(/domain/vcpu[1])", ctxt, &f) == 0) &&
 
1254
        (f > 0)) {
 
1255
        vcpus = (unsigned int) f;
 
1256
    }
 
1257
    virBufferVSprintf(&buf, "(vcpus %u)", vcpus);
 
1258
 
 
1259
    str = virXPathString("string(/domain/uuid[1])", ctxt);
 
1260
    if (str != NULL) {
 
1261
        virBufferVSprintf(&buf, "(uuid '%s')", str);
 
1262
        free(str);
 
1263
    }
 
1264
 
 
1265
    str = virXPathString("string(/domain/bootloader[1])", ctxt);
 
1266
    if (str != NULL) {
 
1267
        virBufferVSprintf(&buf, "(bootloader '%s')", str);
 
1268
        /*
 
1269
         * if using pygrub, the kernel and initrd strings are not
 
1270
         * significant and should be discarded
 
1271
         */
 
1272
        if (strstr(str, "pygrub"))
 
1273
            bootloader = 2;
 
1274
        else
 
1275
            bootloader = 1;
 
1276
        free(str);
 
1277
    }
 
1278
 
 
1279
    str = virXPathString("string(/domain/on_poweroff[1])", ctxt);
 
1280
    if (str != NULL) {
 
1281
        virBufferVSprintf(&buf, "(on_poweroff '%s')", str);
 
1282
        free(str);
 
1283
    }
 
1284
 
 
1285
    str = virXPathString("string(/domain/on_reboot[1])", ctxt);
 
1286
    if (str != NULL) {
 
1287
        virBufferVSprintf(&buf, "(on_reboot '%s')", str);
 
1288
        free(str);
 
1289
    }
 
1290
 
 
1291
    str = virXPathString("string(/domain/on_crash[1])", ctxt);
 
1292
    if (str != NULL) {
 
1293
        virBufferVSprintf(&buf, "(on_crash '%s')", str);
 
1294
        free(str);
 
1295
    }
 
1296
 
 
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);
 
1301
 
 
1302
            if ((str == NULL) || (strcmp(str, "hvm"))) {
 
1303
                res = virDomainParseXMLOSDescPV(conn, node,
 
1304
                                                &buf, ctxt, xendConfigVersion);
 
1305
            } else {
 
1306
                hvm = 1;
 
1307
                res = virDomainParseXMLOSDescHVM(conn, node, &buf, ctxt,
 
1308
                                                 vcpus, xendConfigVersion);
 
1309
            }
 
1310
 
 
1311
            if (str != NULL) free(str);
 
1312
 
 
1313
            if (res != 0)
 
1314
                goto error;
 
1315
        } else if (bootloader == 0) {
 
1316
            virXMLError(conn, VIR_ERR_NO_OS, nam, 0);
 
1317
            goto error;
 
1318
        }
 
1319
    }
1314
1320
 
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);
1321
 
            if (res != 0) {
1322
 
                goto error;
1323
 
            }
1324
 
        }
 
1322
    nb_nodes = virXPathNodeSet("/domain/devices/disk", ctxt, &nodes);
 
1323
    if (nb_nodes > 0) {
 
1324
        for (i = 0; i < nb_nodes; i++) {
 
1325
            res = virDomainParseXMLDiskDesc(conn, nodes[i], &buf,
 
1326
                                            hvm, xendConfigVersion);
 
1327
            if (res != 0) {
 
1328
                free(nodes);
 
1329
                goto error;
 
1330
            }
 
1331
        }
 
1332
        free(nodes);
1325
1333
    }
1326
 
    xmlXPathFreeObject(obj);
1327
1334
 
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);
 
1336
    if (nb_nodes > 0) {
 
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) {
 
1341
                free(nodes);
1335
1342
                goto error;
1336
1343
            }
1337
1344
            virBufferAdd(&buf, ")", 1);
1338
1345
        }
1339
 
    }
1340
 
    xmlXPathFreeObject(obj);
 
1346
        free(nodes);
 
1347
    }
 
1348
 
 
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);
 
1354
        if (nb_nodes > 0) {
 
1355
            for (i = 0; i < nb_nodes; i++) {
 
1356
                res = virDomainParseXMLGraphicsDescVFB(conn, nodes[i], &buf);
 
1357
                if (res != 0) {
 
1358
                    free(nodes);
 
1359
                    goto error;
 
1360
                }
 
1361
            }
 
1362
            free(nodes);
 
1363
        }
 
1364
    }
1341
1365
 
1342
1366
 
1343
1367
    virBufferAdd(&buf, ")", 1); /* closes (vm */
1345
1369
 
1346
1370
    xmlXPathFreeContext(ctxt);
1347
1371
    xmlFreeDoc(xml);
 
1372
    xmlFreeParserCtxt(pctxt);
1348
1373
 
1349
1374
    if (name != NULL)
1350
1375
        *name = nam;
1353
1378
 
1354
1379
    return (ret);
1355
1380
 
1356
 
  error:
 
1381
 error:
1357
1382
    if (nam != NULL)
1358
1383
        free(nam);
1359
1384
    if (name != NULL)
1360
1385
        *name = NULL;
1361
 
    if (obj != NULL)
1362
 
        xmlXPathFreeObject(obj);
1363
1386
    if (ctxt != NULL)
1364
1387
        xmlXPathFreeContext(ctxt);
1365
1388
    if (xml != NULL)
1366
1389
        xmlFreeDoc(xml);
 
1390
    if (pctxt != NULL)
 
1391
        xmlFreeParserCtxt(pctxt);
1367
1392
    if (ret != NULL)
1368
1393
        free(ret);
1369
1394
    return (NULL);
1374
1399
 
1375
1400
 
1376
1401
unsigned char *virParseUUID(char **ptr, const char *uuid) {
1377
 
    int rawuuid[16];
 
1402
    int rawuuid[VIR_UUID_BUFLEN];
1378
1403
    const char *cur;
1379
1404
    unsigned char *dst_uuid = NULL;
1380
1405
    int i;
1387
1412
     * pairs as long as there is 32 of them in the end.
1388
1413
     */
1389
1414
    cur = uuid;
1390
 
    for (i = 0;i < 16;) {
 
1415
    for (i = 0;i < VIR_UUID_BUFLEN;) {
1391
1416
        rawuuid[i] = 0;
1392
1417
        if (*cur == 0)
1393
 
            goto error;
1394
 
        if ((*cur == '-') || (*cur == ' ')) {
1395
 
            cur++;
1396
 
            continue;
1397
 
        }
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;
1404
 
        else
1405
 
            goto error;
1406
 
        rawuuid[i] *= 16;
1407
 
        cur++;
 
1418
            goto error;
 
1419
        if ((*cur == '-') || (*cur == ' ')) {
 
1420
            cur++;
 
1421
            continue;
 
1422
        }
 
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;
 
1429
        else
 
1430
            goto error;
 
1431
        rawuuid[i] *= 16;
 
1432
        cur++;
1408
1433
        if (*cur == 0)
1409
 
            goto error;
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;
1416
 
        else
1417
 
            goto error;
 
1434
            goto error;
 
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;
 
1441
        else
 
1442
            goto error;
1418
1443
        i++;
1419
 
        cur++;
 
1444
        cur++;
1420
1445
    }
1421
1446
 
1422
1447
    dst_uuid = (unsigned char *) *ptr;
1423
1448
    *ptr += 16;
1424
1449
 
1425
 
    for (i = 0; i < 16; i++)
 
1450
    for (i = 0; i < VIR_UUID_BUFLEN; i++)
1426
1451
        dst_uuid[i] = rawuuid[i] & 0xFF;
1427
1452
 
1428
 
error:
 
1453
 error:
1429
1454
    return(dst_uuid);
1430
1455
}
1431
1456
 
 
1457
#ifndef PROXY
 
1458
/**
 
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
 
1464
 *
 
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.
 
1469
 *
 
1470
 * Returns the 0-terminated S-Expr string, or NULL in case of error.
 
1471
 *         the caller must free() the returned value.
 
1472
 */
 
1473
char *
 
1474
virParseXMLDevice(virConnectPtr conn, char *xmldesc, int hvm, int xendConfigVersion)
 
1475
{
 
1476
    xmlDocPtr xml = NULL;
 
1477
    xmlNodePtr node;
 
1478
    virBuffer buf;
 
1479
 
 
1480
    buf.content = malloc(1000);
 
1481
    if (buf.content == NULL)
 
1482
        return (NULL);
 
1483
    buf.size = 1000;
 
1484
    buf.use = 0;
 
1485
    xml = xmlReadDoc((const xmlChar *) xmldesc, "domain.xml", NULL,
 
1486
                     XML_PARSE_NOENT | XML_PARSE_NONET |
 
1487
                     XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
 
1488
    if (xml == NULL)
 
1489
        goto error;
 
1490
    node = xmlDocGetRootElement(xml);
 
1491
    if (node == NULL)
 
1492
        goto error;
 
1493
    if (xmlStrEqual(node->name, BAD_CAST "disk")) {
 
1494
        if (virDomainParseXMLDiskDesc(conn, node, &buf, hvm, xendConfigVersion) != 0)
 
1495
            goto error;
 
1496
    }
 
1497
    else if (xmlStrEqual(node->name, BAD_CAST "interface")) {
 
1498
        if (virDomainParseXMLIfDesc(conn, node, &buf, hvm) != 0)
 
1499
            goto error;
 
1500
    }
 
1501
 cleanup:
 
1502
    if (xml != NULL)
 
1503
        xmlFreeDoc(xml);
 
1504
    return buf.content;
 
1505
 error:
 
1506
    free(buf.content);
 
1507
    buf.content = NULL;
 
1508
    goto cleanup;
 
1509
}
 
1510
 
 
1511
/**
 
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)
 
1517
 *
 
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.
 
1522
 *
 
1523
 * Returns 0 in case of success, -1 in case of failure.
 
1524
 */
 
1525
int
 
1526
virDomainXMLDevID(virDomainPtr domain, char *xmldesc, char *class, char *ref)
 
1527
{
 
1528
    xmlDocPtr xml = NULL;
 
1529
    xmlNodePtr node, cur;
 
1530
    xmlChar *attr = NULL;
 
1531
#ifdef WITH_XEN
 
1532
    char *xref;
 
1533
#endif /* WITH_XEN */
 
1534
    int ret = 0;
 
1535
 
 
1536
    xml = xmlReadDoc((const xmlChar *) xmldesc, "domain.xml", NULL,
 
1537
                     XML_PARSE_NOENT | XML_PARSE_NONET |
 
1538
                     XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
 
1539
    if (xml == NULL)
 
1540
        goto error;
 
1541
    node = xmlDocGetRootElement(xml);
 
1542
    if (node == NULL)
 
1543
        goto error;
 
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");
 
1550
            if (attr == NULL)
 
1551
                goto error;
 
1552
            strcpy(ref, (char *)attr);
 
1553
            goto cleanup;
 
1554
        }
 
1555
    }
 
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");
 
1562
            if (attr == NULL)
 
1563
                goto error;
 
1564
 
 
1565
#ifdef WITH_XEN
 
1566
            xref = xenStoreDomainGetNetworkID(domain->conn, domain->id,
 
1567
                                              (char *) attr);
 
1568
            if (xref != NULL) {
 
1569
                strcpy(ref, xref);
 
1570
                free(xref);
 
1571
                goto cleanup;
 
1572
            }
 
1573
#else /* without xen */
 
1574
            /* hack to avoid the warning that domain is unused */
 
1575
            if (domain->id < 0)
 
1576
                ret = -1;
 
1577
#endif /* WITH_XEN */
 
1578
 
 
1579
            goto error;
 
1580
        }
 
1581
    }
 
1582
 error:
 
1583
    ret = -1;
 
1584
 cleanup:
 
1585
    if (xml != NULL)
 
1586
        xmlFreeDoc(xml);
 
1587
    if (attr != NULL)
 
1588
        xmlFree(attr);
 
1589
    return ret;
 
1590
}
 
1591
#endif /* !PROXY */
 
1592
 
1432
1593
/*
1433
1594
 * Local variables:
1434
1595
 *  indent-tabs-mode: nil