xen_xm.c 67.4 KB
Newer Older
1 2 3
/*
 * xen_xm.c: Xen XM parsing functions
 *
4
 * Copyright (C) 2006-2007, 2009-2014 Red Hat, Inc.
5 6 7 8 9 10 11 12 13 14 15 16 17 18
 * Copyright (C) 2011 Univention GmbH
 * Copyright (C) 2006 Daniel P. Berrange
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
19
 * License along with this library.  If not, see
O
Osier Yang 已提交
20
 * <http://www.gnu.org/licenses/>.
21 22 23 24 25 26 27 28
 *
 * Author: Daniel P. Berrange <berrange@redhat.com>
 * Author: Markus Groß <gross@univention.de>
 */

#include <config.h>

#include "internal.h"
29
#include "virerror.h"
30
#include "virconf.h"
31
#include "viralloc.h"
32
#include "verify.h"
33
#include "viruuid.h"
34
#include "virsexpr.h"
35 36 37 38
#include "count-one-bits.h"
#include "xenxs_private.h"
#include "xen_xm.h"
#include "xen_sxpr.h"
M
Michal Novotny 已提交
39
#include "domain_conf.h"
40
#include "virstoragefile.h"
41
#include "virstring.h"
42

43
/* Convenience method to grab a long int from the config file object */
44 45 46
static int xenXMConfigGetBool(virConfPtr conf,
                              const char *name,
                              int *value,
47 48
                              int def)
{
49 50 51 52 53 54 55 56 57 58 59 60 61
    virConfValuePtr val;

    *value = 0;
    if (!(val = virConfGetValue(conf, name))) {
        *value = def;
        return 0;
    }

    if (val->type == VIR_CONF_LONG) {
        *value = val->l ? 1 : 0;
    } else if (val->type == VIR_CONF_STRING) {
        *value = STREQ(val->str, "1") ? 1 : 0;
    } else {
62 63
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("config value %s was malformed"), name);
64 65 66 67 68 69 70 71 72 73
        return -1;
    }
    return 0;
}


/* Convenience method to grab a int from the config file object */
static int xenXMConfigGetULong(virConfPtr conf,
                               const char *name,
                               unsigned long *value,
74 75
                               unsigned long def)
{
76 77 78 79 80 81 82 83 84 85 86 87 88 89
    virConfValuePtr val;

    *value = 0;
    if (!(val = virConfGetValue(conf, name))) {
        *value = def;
        return 0;
    }

    if (val->type == VIR_CONF_LONG) {
        *value = val->l;
    } else if (val->type == VIR_CONF_STRING) {
        char *ret;
        *value = strtol(val->str, &ret, 10);
        if (ret == val->str) {
90 91
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("config value %s was malformed"), name);
92 93 94
            return -1;
        }
    } else {
95 96
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("config value %s was malformed"), name);
97 98 99 100 101 102
        return -1;
    }
    return 0;
}


103 104 105 106
/* Convenience method to grab a int from the config file object */
static int xenXMConfigGetULongLong(virConfPtr conf,
                                   const char *name,
                                   unsigned long long *value,
107 108
                                   unsigned long long def)
{
109 110 111 112 113 114 115 116 117 118 119 120 121 122
    virConfValuePtr val;

    *value = 0;
    if (!(val = virConfGetValue(conf, name))) {
        *value = def;
        return 0;
    }

    if (val->type == VIR_CONF_LONG) {
        *value = val->l;
    } else if (val->type == VIR_CONF_STRING) {
        char *ret;
        *value = strtoll(val->str, &ret, 10);
        if (ret == val->str) {
123 124
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("config value %s was malformed"), name);
125 126 127
            return -1;
        }
    } else {
128 129
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("config value %s was malformed"), name);
130 131 132 133 134 135
        return -1;
    }
    return 0;
}


136 137 138 139
/* Convenience method to grab a string from the config file object */
static int xenXMConfigGetString(virConfPtr conf,
                                const char *name,
                                const char **value,
140 141
                                const char *def)
{
142 143 144 145 146 147 148 149 150
    virConfValuePtr val;

    *value = NULL;
    if (!(val = virConfGetValue(conf, name))) {
        *value = def;
        return 0;
    }

    if (val->type != VIR_CONF_STRING) {
151 152
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("config value %s was malformed"), name);
153 154 155 156 157 158 159 160 161 162 163 164
        return -1;
    }
    if (!val->str)
        *value = def;
    else
        *value = val->str;
    return 0;
}

static int xenXMConfigCopyStringInternal(virConfPtr conf,
                                         const char *name,
                                         char **value,
165 166
                                         int allowMissing)
{
167 168 169 170 171 172
    virConfValuePtr val;

    *value = NULL;
    if (!(val = virConfGetValue(conf, name))) {
        if (allowMissing)
            return 0;
173 174
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("config value %s was missing"), name);
175 176 177 178
        return -1;
    }

    if (val->type != VIR_CONF_STRING) {
179 180
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("config value %s was not a string"), name);
181 182 183 184 185
        return -1;
    }
    if (!val->str) {
        if (allowMissing)
            return 0;
186 187
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("config value %s was missing"), name);
188 189 190
        return -1;
    }

191
    return VIR_STRDUP(*value, val->str);
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208
}


static int xenXMConfigCopyString(virConfPtr conf,
                                 const char *name,
                                 char **value) {
    return xenXMConfigCopyStringInternal(conf, name, value, 0);
}

static int xenXMConfigCopyStringOpt(virConfPtr conf,
                                    const char *name,
                                    char **value) {
    return xenXMConfigCopyStringInternal(conf, name, value, 1);
}


/* Convenience method to grab a string UUID from the config file object */
209 210 211
static int
xenXMConfigGetUUID(virConfPtr conf, const char *name, unsigned char *uuid)
{
212
    virConfValuePtr val;
213 214

    if (!uuid || !name || !conf) {
215
        virReportError(VIR_ERR_INVALID_ARG, "%s",
216
                       _("Arguments must be non null"));
217 218 219
        return -1;
    }

220
    if (!(val = virConfGetValue(conf, name))) {
221 222 223 224 225 226 227
        if (virUUIDGenerate(uuid)) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           "%s", _("Failed to generate UUID"));
            return -1;
        } else {
            return 0;
        }
228 229
    }

230
    if (val->type != VIR_CONF_STRING) {
231 232
        virReportError(VIR_ERR_CONF_SYNTAX,
                       _("config value %s not a string"), name);
233 234 235 236
        return -1;
    }

    if (!val->str) {
237 238
        virReportError(VIR_ERR_CONF_SYNTAX,
                       _("%s can't be empty"), name);
239 240
        return -1;
    }
241

242
    if (virUUIDParse(val->str, uuid) < 0) {
243 244
        virReportError(VIR_ERR_CONF_SYNTAX,
                       _("%s not parseable"), val->str);
245 246
        return -1;
    }
247

248
    return 0;
249 250 251 252 253 254 255 256
}

#define MAX_VFB 1024
/*
 * Turn a config record into a lump of XML describing the
 * domain, suitable for later feeding for virDomainCreateXML
 */
virDomainDefPtr
M
Markus Groß 已提交
257
xenParseXM(virConfPtr conf, int xendConfigVersion,
258 259
                       virCapsPtr caps)
{
260 261 262 263 264 265 266 267 268
    const char *str;
    int hvm = 0;
    int val;
    virConfValuePtr list;
    virDomainDefPtr def = NULL;
    virDomainDiskDefPtr disk = NULL;
    virDomainNetDefPtr net = NULL;
    virDomainGraphicsDefPtr graphics = NULL;
    virDomainHostdevDefPtr hostdev = NULL;
269
    size_t i;
270
    const char *defaultMachine;
271 272
    int vmlocaltime = 0;
    unsigned long count;
273
    char *script = NULL;
274
    char *listenAddr = NULL;
275

276
    if (VIR_ALLOC(def) < 0)
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291
        return NULL;

    def->virtType = VIR_DOMAIN_VIRT_XEN;
    def->id = -1;

    if (xenXMConfigCopyString(conf, "name", &def->name) < 0)
        goto cleanup;
    if (xenXMConfigGetUUID(conf, "uuid", def->uuid) < 0)
        goto cleanup;


    if ((xenXMConfigGetString(conf, "builder", &str, "linux") == 0) &&
        STREQ(str, "hvm"))
        hvm = 1;

292 293
    if (VIR_STRDUP(def->os.type, hvm ? "hvm" : "xen") < 0)
        goto cleanup;
294

295 296 297 298 299
    def->os.arch =
        virCapabilitiesDefaultGuestArch(caps,
                                        def->os.type,
                                        virDomainVirtTypeToString(def->virtType));
    if (!def->os.arch) {
300 301 302
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("no supported architecture for os type '%s'"),
                       def->os.type);
303 304 305 306 307 308 309 310
        goto cleanup;
    }

    defaultMachine = virCapabilitiesDefaultGuestMachine(caps,
                                                        def->os.type,
                                                        def->os.arch,
                                                        virDomainVirtTypeToString(def->virtType));
    if (defaultMachine != NULL) {
311 312
        if (VIR_STRDUP(def->os.machine, defaultMachine) < 0)
            goto cleanup;
313 314 315 316 317 318 319 320 321 322
    }

    if (hvm) {
        const char *boot;
        if (xenXMConfigCopyString(conf, "kernel", &def->os.loader) < 0)
            goto cleanup;

        if (xenXMConfigGetString(conf, "boot", &boot, "c") < 0)
            goto cleanup;

323
        for (i = 0; i < VIR_DOMAIN_BOOT_LAST && boot[i]; i++) {
324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354
            switch (*boot) {
            case 'a':
                def->os.bootDevs[i] = VIR_DOMAIN_BOOT_FLOPPY;
                break;
            case 'd':
                def->os.bootDevs[i] = VIR_DOMAIN_BOOT_CDROM;
                break;
            case 'n':
                def->os.bootDevs[i] = VIR_DOMAIN_BOOT_NET;
                break;
            case 'c':
            default:
                def->os.bootDevs[i] = VIR_DOMAIN_BOOT_DISK;
                break;
            }
            def->os.nBootDevs++;
        }
    } else {
        if (xenXMConfigCopyStringOpt(conf, "bootloader", &def->os.bootloader) < 0)
            goto cleanup;
        if (xenXMConfigCopyStringOpt(conf, "bootargs", &def->os.bootloaderArgs) < 0)
            goto cleanup;

        if (xenXMConfigCopyStringOpt(conf, "kernel", &def->os.kernel) < 0)
            goto cleanup;
        if (xenXMConfigCopyStringOpt(conf, "ramdisk", &def->os.initrd) < 0)
            goto cleanup;
        if (xenXMConfigCopyStringOpt(conf, "extra", &def->os.cmdline) < 0)
            goto cleanup;
    }

355 356
    if (xenXMConfigGetULongLong(conf, "memory", &def->mem.cur_balloon,
                                MIN_XEN_GUEST_SIZE * 2) < 0)
357 358
        goto cleanup;

359 360
    if (xenXMConfigGetULongLong(conf, "maxmem", &def->mem.max_balloon,
                                def->mem.cur_balloon) < 0)
361 362 363 364 365 366 367 368 369 370 371 372 373 374 375
        goto cleanup;

    def->mem.cur_balloon *= 1024;
    def->mem.max_balloon *= 1024;

    if (xenXMConfigGetULong(conf, "vcpus", &count, 1) < 0 ||
        MAX_VIRT_CPUS < count)
        goto cleanup;
    def->maxvcpus = count;
    if (xenXMConfigGetULong(conf, "vcpu_avail", &count, -1) < 0)
        goto cleanup;
    def->vcpus = MIN(count_one_bits_l(count), def->maxvcpus);

    if (xenXMConfigGetString(conf, "cpus", &str, NULL) < 0)
        goto cleanup;
H
Hu Tao 已提交
376
    if (str && (virBitmapParse(str, 0, &def->cpumask, 4096) < 0))
377 378 379 380 381
            goto cleanup;

    if (xenXMConfigGetString(conf, "on_poweroff", &str, "destroy") < 0)
        goto cleanup;
    if ((def->onPoweroff = virDomainLifecycleTypeFromString(str)) < 0) {
382 383
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unexpected value %s for on_poweroff"), str);
384 385 386 387 388 389
        goto cleanup;
    }

    if (xenXMConfigGetString(conf, "on_reboot", &str, "restart") < 0)
        goto cleanup;
    if ((def->onReboot = virDomainLifecycleTypeFromString(str)) < 0) {
390 391
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unexpected value %s for on_reboot"), str);
392 393 394 395 396 397
        goto cleanup;
    }

    if (xenXMConfigGetString(conf, "on_crash", &str, "restart") < 0)
        goto cleanup;
    if ((def->onCrash = virDomainLifecycleCrashTypeFromString(str)) < 0) {
398 399
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unexpected value %s for on_crash"), str);
400 401 402 403 404 405 406 407 408
        goto cleanup;
    }



    if (hvm) {
        if (xenXMConfigGetBool(conf, "pae", &val, 0) < 0)
            goto cleanup;
        else if (val)
409
            def->features[VIR_DOMAIN_FEATURE_PAE] = VIR_DOMAIN_FEATURE_STATE_ON;
410 411 412
        if (xenXMConfigGetBool(conf, "acpi", &val, 0) < 0)
            goto cleanup;
        else if (val)
413
            def->features[VIR_DOMAIN_FEATURE_ACPI] = VIR_DOMAIN_FEATURE_STATE_ON;
414 415 416
        if (xenXMConfigGetBool(conf, "apic", &val, 0) < 0)
            goto cleanup;
        else if (val)
417
            def->features[VIR_DOMAIN_FEATURE_APIC] = VIR_DOMAIN_FEATURE_STATE_ON;
418 419 420
        if (xenXMConfigGetBool(conf, "hap", &val, 0) < 0)
            goto cleanup;
        else if (val)
421
            def->features[VIR_DOMAIN_FEATURE_HAP] = VIR_DOMAIN_FEATURE_STATE_ON;
422 423 424
        if (xenXMConfigGetBool(conf, "viridian", &val, 0) < 0)
            goto cleanup;
        else if (val)
425
            def->features[VIR_DOMAIN_FEATURE_VIRIDIAN] = VIR_DOMAIN_FEATURE_STATE_ON;
426 427 428 429 430 431 432

        if (xenXMConfigGetBool(conf, "hpet", &val, -1) < 0)
            goto cleanup;
        else if (val != -1) {
            virDomainTimerDefPtr timer;

            if (VIR_ALLOC_N(def->clock.timers, 1) < 0 ||
433
                VIR_ALLOC(timer) < 0)
434 435 436 437 438 439 440 441 442
                goto cleanup;

            timer->name = VIR_DOMAIN_TIMER_NAME_HPET;
            timer->present = val;
            timer->tickpolicy = -1;

            def->clock.ntimers = 1;
            def->clock.timers[0] = timer;
        }
443 444 445 446
    }
    if (xenXMConfigGetBool(conf, "localtime", &vmlocaltime, 0) < 0)
        goto cleanup;

P
Philipp Hahn 已提交
447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471
    if (hvm) {
        /* only managed HVM domains since 3.1.0 have persistent rtc_timeoffset */
        if (xendConfigVersion < XEND_CONFIG_VERSION_3_1_0) {
            if (vmlocaltime)
                def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME;
            else
                def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_UTC;
            def->clock.data.utc_reset = true;
        } else {
            unsigned long rtc_timeoffset;
            def->clock.offset = VIR_DOMAIN_CLOCK_OFFSET_VARIABLE;
            if (xenXMConfigGetULong(conf, "rtc_timeoffset", &rtc_timeoffset, 0) < 0)
                goto cleanup;
            def->clock.data.variable.adjustment = (int)rtc_timeoffset;
            def->clock.data.variable.basis = vmlocaltime ?
                VIR_DOMAIN_CLOCK_BASIS_LOCALTIME :
                VIR_DOMAIN_CLOCK_BASIS_UTC;
        }
    } else {
        /* PV domains do not have an emulated RTC and the offset is fixed. */
        def->clock.offset = vmlocaltime ?
            VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME :
            VIR_DOMAIN_CLOCK_OFFSET_UTC;
        def->clock.data.utc_reset = true;
    } /* !hvm */
472 473 474 475 476 477 478 479 480 481 482

    if (xenXMConfigCopyStringOpt(conf, "device_model", &def->emulator) < 0)
        goto cleanup;

    list = virConfGetValue(conf, "disk");
    if (list && list->type == VIR_CONF_LIST) {
        list = list->list;
        while (list) {
            char *head;
            char *offset;
            char *tmp;
483
            const char *src;
484 485 486 487 488 489

            if ((list->type != VIR_CONF_STRING) || (list->str == NULL))
                goto skipdisk;
            head = list->str;

            if (VIR_ALLOC(disk) < 0)
490
                goto cleanup;
491 492 493 494 495 496 497 498 499 500 501 502 503 504

            /*
             * Disks have 3 components, SOURCE,DEST-DEVICE,MODE
             * eg, phy:/dev/HostVG/XenGuest1,xvda,w
             * The SOURCE is usually prefixed with a driver type,
             * and optionally driver sub-type
             * The DEST-DEVICE is optionally post-fixed with disk type
             */

            /* Extract the source file path*/
            if (!(offset = strchr(head, ',')))
                goto skipdisk;

            if (offset == head) {
505 506
                /* No source file given, eg CDROM with no media */
                ignore_value(virDomainDiskSetSource(disk, NULL));
507
            } else {
508
                if (VIR_STRNDUP(tmp, head, offset - head) < 0)
509
                    goto cleanup;
510 511
                if (virDomainDiskSetSource(disk, tmp) < 0) {
                    VIR_FREE(tmp);
512 513
                    goto cleanup;
                }
514
                VIR_FREE(tmp);
515 516 517 518 519 520 521 522 523 524 525
            }
            head = offset + 1;

            /* Remove legacy ioemu: junk */
            if (STRPREFIX(head, "ioemu:"))
                head = head + 6;

            /* Extract the dest device name */
            if (!(offset = strchr(head, ',')))
                goto skipdisk;
            if (VIR_ALLOC_N(disk->dst, (offset - head) + 1) < 0)
526
                goto cleanup;
527 528
            if (virStrncpy(disk->dst, head, offset - head,
                           (offset - head) + 1) == NULL) {
529 530
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("Dest file %s too big for destination"), head);
531 532 533 534 535
                goto cleanup;
            }
            head = offset + 1;

            /* Extract source driver type */
536 537 538
            src = virDomainDiskGetSource(disk);
            if (src) {
                size_t len;
539
                /* The main type  phy:, file:, tap: ... */
540 541 542
                if ((tmp = strchr(src, ':')) != NULL) {
                    len = tmp - src;
                    if (VIR_STRNDUP(tmp, src, len) < 0)
543
                        goto cleanup;
544 545
                    if (virDomainDiskSetDriver(disk, tmp) < 0) {
                        VIR_FREE(tmp);
546 547
                        goto cleanup;
                    }
548
                    VIR_FREE(tmp);
549 550

                    /* Strip the prefix we found off the source file name */
551 552 553
                    if (virDomainDiskSetSource(disk, src + len + 1) < 0)
                        goto cleanup;
                    src = virDomainDiskGetSource(disk);
554 555 556
                }

                /* And the sub-type for tap:XXX: type */
557
                if (STREQ_NULLABLE(virDomainDiskGetDriver(disk), "tap")) {
558 559
                    char *driverType;

560
                    if (!(tmp = strchr(src, ':')))
561
                        goto skipdisk;
562
                    len = tmp - src;
563

564
                    if (VIR_STRNDUP(driverType, src, len) < 0)
565
                        goto cleanup;
566
                    if (STREQ(driverType, "aio"))
567
                        virDomainDiskSetFormat(disk, VIR_STORAGE_FILE_RAW);
568
                    else
569 570
                        virDomainDiskSetFormat(disk,
                                               virStorageFileFormatTypeFromString(driverType));
571
                    VIR_FREE(driverType);
572
                    if (virDomainDiskGetFormat(disk) <= 0) {
573
                        virReportError(VIR_ERR_INTERNAL_ERROR,
574
                                       _("Unknown driver type %s"),
575
                                       src);
576 577 578 579
                        goto cleanup;
                    }

                    /* Strip the prefix we found off the source file name */
580 581 582
                    if (virDomainDiskSetSource(disk, src + len + 1) < 0)
                        goto cleanup;
                    src = virDomainDiskGetSource(disk);
583 584 585 586
                }
            }

            /* No source, or driver name, so fix to phy: */
587 588
            if (!virDomainDiskGetDriver(disk) &&
                virDomainDiskSetDriver(disk, "phy") < 0)
589
                goto cleanup;
590 591 592


            /* phy: type indicates a block device */
593 594
            virDomainDiskSetType(disk,
                                 STREQ(virDomainDiskGetDriver(disk), "phy") ?
E
Eric Blake 已提交
595 596
                                 VIR_STORAGE_TYPE_BLOCK :
                                 VIR_STORAGE_TYPE_FILE);
597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615

            /* Check for a :cdrom/:disk postfix */
            disk->device = VIR_DOMAIN_DISK_DEVICE_DISK;
            if ((tmp = strchr(disk->dst, ':')) != NULL) {
                if (STREQ(tmp, ":cdrom"))
                    disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
                tmp[0] = '\0';
            }

            if (STRPREFIX(disk->dst, "xvd") || !hvm) {
                disk->bus = VIR_DOMAIN_DISK_BUS_XEN;
            } else if (STRPREFIX(disk->dst, "sd")) {
                disk->bus = VIR_DOMAIN_DISK_BUS_SCSI;
            } else {
                disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
            }

            if (STREQ(head, "r") ||
                STREQ(head, "ro"))
616
                disk->readonly = true;
617 618
            else if ((STREQ(head, "w!")) ||
                     (STREQ(head, "!")))
619
                disk->shared = true;
620 621

            /* Maintain list in sorted order according to target device name */
622
            if (VIR_APPEND_ELEMENT(def->disks, def->ndisks, disk) < 0)
623
                goto cleanup;
624 625 626 627 628 629 630

            skipdisk:
            list = list->next;
            virDomainDiskDefFree(disk);
        }
    }

631
    if (hvm && xendConfigVersion == XEND_CONFIG_VERSION_3_0_2) {
632 633 634 635
        if (xenXMConfigGetString(conf, "cdrom", &str, NULL) < 0)
            goto cleanup;
        if (str) {
            if (VIR_ALLOC(disk) < 0)
636
                goto cleanup;
637

E
Eric Blake 已提交
638
            virDomainDiskSetType(disk, VIR_STORAGE_TYPE_FILE);
639
            disk->device = VIR_DOMAIN_DISK_DEVICE_CDROM;
640
            if (virDomainDiskSetDriver(disk, "file") < 0)
641
                goto cleanup;
642
            if (virDomainDiskSetSource(disk, str) < 0)
643 644 645
                goto cleanup;
            if (VIR_STRDUP(disk->dst, "hdc") < 0)
                goto cleanup;
646
            disk->bus = VIR_DOMAIN_DISK_BUS_IDE;
647
            disk->readonly = true;
648

649
            if (VIR_APPEND_ELEMENT(def->disks, def->ndisks, disk) < 0)
650
                goto cleanup;
651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687
        }
    }

    list = virConfGetValue(conf, "vif");
    if (list && list->type == VIR_CONF_LIST) {
        list = list->list;
        while (list) {
            char model[10];
            char type[10];
            char ip[16];
            char mac[18];
            char bridge[50];
            char vifname[50];
            char *key;

            bridge[0] = '\0';
            mac[0] = '\0';
            ip[0] = '\0';
            model[0] = '\0';
            type[0] = '\0';
            vifname[0] = '\0';

            if ((list->type != VIR_CONF_STRING) || (list->str == NULL))
                goto skipnic;

            key = list->str;
            while (key) {
                char *data;
                char *nextkey = strchr(key, ',');

                if (!(data = strchr(key, '=')))
                    goto skipnic;
                data++;

                if (STRPREFIX(key, "mac=")) {
                    int len = nextkey ? (nextkey - data) : sizeof(mac) - 1;
                    if (virStrncpy(mac, data, len, sizeof(mac)) == NULL) {
688 689 690
                        virReportError(VIR_ERR_INTERNAL_ERROR,
                                       _("MAC address %s too big for destination"),
                                       data);
691 692 693 694 695
                        goto skipnic;
                    }
                } else if (STRPREFIX(key, "bridge=")) {
                    int len = nextkey ? (nextkey - data) : sizeof(bridge) - 1;
                    if (virStrncpy(bridge, data, len, sizeof(bridge)) == NULL) {
696 697 698
                        virReportError(VIR_ERR_INTERNAL_ERROR,
                                       _("Bridge %s too big for destination"),
                                       data);
699 700 701
                        goto skipnic;
                    }
                } else if (STRPREFIX(key, "script=")) {
702 703
                    int len = nextkey ? (nextkey - data) : strlen(data);
                    VIR_FREE(script);
704 705
                    if (VIR_STRNDUP(script, data, len) < 0)
                        goto cleanup;
706 707 708
                } else if (STRPREFIX(key, "model=")) {
                    int len = nextkey ? (nextkey - data) : sizeof(model) - 1;
                    if (virStrncpy(model, data, len, sizeof(model)) == NULL) {
709 710
                        virReportError(VIR_ERR_INTERNAL_ERROR,
                                       _("Model %s too big for destination"), data);
711 712 713 714 715
                        goto skipnic;
                    }
                } else if (STRPREFIX(key, "type=")) {
                    int len = nextkey ? (nextkey - data) : sizeof(type) - 1;
                    if (virStrncpy(type, data, len, sizeof(type)) == NULL) {
716 717
                        virReportError(VIR_ERR_INTERNAL_ERROR,
                                       _("Type %s too big for destination"), data);
718 719 720 721 722
                        goto skipnic;
                    }
                } else if (STRPREFIX(key, "vifname=")) {
                    int len = nextkey ? (nextkey - data) : sizeof(vifname) - 1;
                    if (virStrncpy(vifname, data, len, sizeof(vifname)) == NULL) {
723 724 725
                        virReportError(VIR_ERR_INTERNAL_ERROR,
                                       _("Vifname %s too big for destination"),
                                       data);
726 727 728 729 730
                        goto skipnic;
                    }
                } else if (STRPREFIX(key, "ip=")) {
                    int len = nextkey ? (nextkey - data) : sizeof(ip) - 1;
                    if (virStrncpy(ip, data, len, sizeof(ip)) == NULL) {
731 732
                        virReportError(VIR_ERR_INTERNAL_ERROR,
                                       _("IP %s too big for destination"), data);
733 734 735 736 737 738 739 740 741 742 743 744
                        goto skipnic;
                    }
                }

                while (nextkey && (nextkey[0] == ',' ||
                                   nextkey[0] == ' ' ||
                                   nextkey[0] == '\t'))
                    nextkey++;
                key = nextkey;
            }

            if (VIR_ALLOC(net) < 0)
745
                goto cleanup;
746 747

            if (mac[0]) {
748
                if (virMacAddrParse(mac, &net->mac) < 0) {
749 750
                    virReportError(VIR_ERR_INTERNAL_ERROR,
                                   _("malformed mac address '%s'"), mac);
751 752 753 754
                    goto cleanup;
                }
            }

755 756
            if (bridge[0] || STREQ_NULLABLE(script, "vif-bridge") ||
                STREQ_NULLABLE(script, "vif-vnic")) {
757 758 759 760 761 762
                net->type = VIR_DOMAIN_NET_TYPE_BRIDGE;
            } else {
                net->type = VIR_DOMAIN_NET_TYPE_ETHERNET;
            }

            if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
763 764 765 766
                if (bridge[0] && VIR_STRDUP(net->data.bridge.brname, bridge) < 0)
                    goto cleanup;
                if (ip[0] && VIR_STRDUP(net->data.bridge.ipaddr, ip) < 0)
                    goto cleanup;
767
            } else {
768 769
                if (ip[0] && VIR_STRDUP(net->data.ethernet.ipaddr, ip) < 0)
                    goto cleanup;
770 771
            }

772
            if (script && script[0] &&
773 774
                VIR_STRDUP(net->script, script) < 0)
                goto cleanup;
775

776
            if (model[0] &&
777
                VIR_STRDUP(net->model, model) < 0)
778
                goto cleanup;
779

780 781 782
            if (!model[0] && type[0] && STREQ(type, "netfront") &&
                VIR_STRDUP(net->model, "netfront") < 0)
                goto cleanup;
783 784

            if (vifname[0] &&
785 786
                VIR_STRDUP(net->ifname, vifname) < 0)
                goto cleanup;
787

788
            if (VIR_APPEND_ELEMENT(def->nets, def->nnets, net) < 0)
789
                goto cleanup;
790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822

        skipnic:
            list = list->next;
            virDomainNetDefFree(net);
        }
    }

    list = virConfGetValue(conf, "pci");
    if (list && list->type == VIR_CONF_LIST) {
        list = list->list;
        while (list) {
            char domain[5];
            char bus[3];
            char slot[3];
            char func[2];
            char *key, *nextkey;
            int domainID;
            int busID;
            int slotID;
            int funcID;

            domain[0] = bus[0] = slot[0] = func[0] = '\0';

            if ((list->type != VIR_CONF_STRING) || (list->str == NULL))
                goto skippci;

            /* pci=['0000:00:1b.0','0000:00:13.0'] */
            if (!(key = list->str))
                goto skippci;
            if (!(nextkey = strchr(key, ':')))
                goto skippci;

            if (virStrncpy(domain, key, (nextkey - key), sizeof(domain)) == NULL) {
823 824
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("Domain %s too big for destination"), key);
825 826 827 828 829 830 831 832
                goto skippci;
            }

            key = nextkey + 1;
            if (!(nextkey = strchr(key, ':')))
                goto skippci;

            if (virStrncpy(bus, key, (nextkey - key), sizeof(bus)) == NULL) {
833 834
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("Bus %s too big for destination"), key);
835 836 837 838 839 840 841 842
                goto skippci;
            }

            key = nextkey + 1;
            if (!(nextkey = strchr(key, '.')))
                goto skippci;

            if (virStrncpy(slot, key, (nextkey - key), sizeof(slot)) == NULL) {
843 844
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("Slot %s too big for destination"), key);
845 846 847 848 849 850 851 852
                goto skippci;
            }

            key = nextkey + 1;
            if (strlen(key) != 1)
                goto skippci;

            if (virStrncpy(func, key, 1, sizeof(func)) == NULL) {
853 854
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("Function %s too big for destination"), key);
855 856 857 858 859 860 861 862 863 864 865 866
                goto skippci;
            }

            if (virStrToLong_i(domain, NULL, 16, &domainID) < 0)
                goto skippci;
            if (virStrToLong_i(bus, NULL, 16, &busID) < 0)
                goto skippci;
            if (virStrToLong_i(slot, NULL, 16, &slotID) < 0)
                goto skippci;
            if (virStrToLong_i(func, NULL, 16, &funcID) < 0)
                goto skippci;

867 868
            if (!(hostdev = virDomainHostdevDefAlloc()))
               goto cleanup;
869

870
            hostdev->managed = false;
871
            hostdev->source.subsys.type = VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI;
872 873 874 875
            hostdev->source.subsys.u.pci.addr.domain = domainID;
            hostdev->source.subsys.u.pci.addr.bus = busID;
            hostdev->source.subsys.u.pci.addr.slot = slotID;
            hostdev->source.subsys.u.pci.addr.function = funcID;
876

877
            if (VIR_APPEND_ELEMENT(def->hostdevs, def->nhostdevs, hostdev) < 0) {
878
                virDomainHostdevDefFree(hostdev);
879
                goto cleanup;
880
            }
881 882 883 884 885 886 887 888 889 890 891

        skippci:
            list = list->next;
        }
    }

    if (hvm) {
        if (xenXMConfigGetString(conf, "usbdevice", &str, NULL) < 0)
            goto cleanup;
        if (str &&
            (STREQ(str, "tablet") ||
892 893
             STREQ(str, "mouse") ||
             STREQ(str, "keyboard"))) {
894 895
            virDomainInputDefPtr input;
            if (VIR_ALLOC(input) < 0)
896
                goto cleanup;
897
            input->bus = VIR_DOMAIN_INPUT_BUS_USB;
898 899 900 901 902 903
            if (STREQ(str, "mouse"))
                input->type = VIR_DOMAIN_INPUT_TYPE_MOUSE;
            else if (STREQ(str, "tablet"))
                input->type = VIR_DOMAIN_INPUT_TYPE_TABLET;
            else if (STREQ(str, "keyboard"))
                input->type = VIR_DOMAIN_INPUT_TYPE_KBD;
904 905
            if (VIR_ALLOC_N(def->inputs, 1) < 0) {
                virDomainInputDefFree(input);
906
                goto cleanup;
907 908 909 910 911 912 913
            }
            def->inputs[0] = input;
            def->ninputs = 1;
        }
    }

    /* HVM guests, or old PV guests use this config format */
914
    if (hvm || xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
915 916 917 918 919
        if (xenXMConfigGetBool(conf, "vnc", &val, 0) < 0)
            goto cleanup;

        if (val) {
            if (VIR_ALLOC(graphics) < 0)
920
                goto cleanup;
921 922 923 924 925 926 927 928 929 930 931
            graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_VNC;
            if (xenXMConfigGetBool(conf, "vncunused", &val, 1) < 0)
                goto cleanup;
            graphics->data.vnc.autoport = val ? 1 : 0;

            if (!graphics->data.vnc.autoport) {
                unsigned long vncdisplay;
                if (xenXMConfigGetULong(conf, "vncdisplay", &vncdisplay, 0) < 0)
                    goto cleanup;
                graphics->data.vnc.port = (int)vncdisplay + 5900;
            }
932 933

            if (xenXMConfigCopyStringOpt(conf, "vnclisten", &listenAddr) < 0)
934
                goto cleanup;
935 936 937 938 939 940 941
            if (listenAddr &&
                virDomainGraphicsListenSetAddress(graphics, 0, listenAddr,
                                                  -1, true) < 0) {
               goto cleanup;
            }
            VIR_FREE(listenAddr);

942 943 944 945 946 947
            if (xenXMConfigCopyStringOpt(conf, "vncpasswd", &graphics->data.vnc.auth.passwd) < 0)
                goto cleanup;
            if (xenXMConfigCopyStringOpt(conf, "keymap", &graphics->data.vnc.keymap) < 0)
                goto cleanup;

            if (VIR_ALLOC_N(def->graphics, 1) < 0)
948
                goto cleanup;
949 950 951 952 953 954 955 956
            def->graphics[0] = graphics;
            def->ngraphics = 1;
            graphics = NULL;
        } else {
            if (xenXMConfigGetBool(conf, "sdl", &val, 0) < 0)
                goto cleanup;
            if (val) {
                if (VIR_ALLOC(graphics) < 0)
957
                    goto cleanup;
958 959 960 961 962 963
                graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_SDL;
                if (xenXMConfigCopyStringOpt(conf, "display", &graphics->data.sdl.display) < 0)
                    goto cleanup;
                if (xenXMConfigCopyStringOpt(conf, "xauthority", &graphics->data.sdl.xauth) < 0)
                    goto cleanup;
                if (VIR_ALLOC_N(def->graphics, 1) < 0)
964
                    goto cleanup;
965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980
                def->graphics[0] = graphics;
                def->ngraphics = 1;
                graphics = NULL;
            }
        }
    }

    if (!hvm && def->graphics == NULL) { /* New PV guests use this format */
        list = virConfGetValue(conf, "vfb");
        if (list && list->type == VIR_CONF_LIST &&
            list->list && list->list->type == VIR_CONF_STRING &&
            list->list->str) {
            char vfb[MAX_VFB];
            char *key = vfb;

            if (virStrcpyStatic(vfb, list->list->str) == NULL) {
981 982 983
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("VFB %s too big for destination"),
                               list->list->str);
984 985 986 987
                goto cleanup;
            }

            if (VIR_ALLOC(graphics) < 0)
988
                goto cleanup;
989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008

            if (strstr(key, "type=sdl"))
                graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_SDL;
            else
                graphics->type = VIR_DOMAIN_GRAPHICS_TYPE_VNC;

            while (key) {
                char *nextkey = strchr(key, ',');
                char *end = nextkey;
                if (nextkey) {
                    *end = '\0';
                    nextkey++;
                }

                if (!strchr(key, '='))
                    break;

                if (graphics->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC) {
                    if (STRPREFIX(key, "vncunused=")) {
                        if (STREQ(key + 10, "1"))
1009
                            graphics->data.vnc.autoport = true;
1010
                    } else if (STRPREFIX(key, "vnclisten=")) {
1011 1012 1013
                        if (virDomainGraphicsListenSetAddress(graphics, 0, key+10,
                                                              -1, true) < 0)
                            goto cleanup;
1014
                    } else if (STRPREFIX(key, "vncpasswd=")) {
1015 1016
                        if (VIR_STRDUP(graphics->data.vnc.auth.passwd, key + 10) < 0)
                            goto cleanup;
1017
                    } else if (STRPREFIX(key, "keymap=")) {
1018 1019
                        if (VIR_STRDUP(graphics->data.vnc.keymap, key + 7) < 0)
                            goto cleanup;
1020 1021 1022 1023 1024
                    } else if (STRPREFIX(key, "vncdisplay=")) {
                        graphics->data.vnc.port = strtol(key+11, NULL, 10) + 5900;
                    }
                } else {
                    if (STRPREFIX(key, "display=")) {
1025 1026
                        if (VIR_STRDUP(graphics->data.sdl.display, key + 8) < 0)
                            goto cleanup;
1027
                    } else if (STRPREFIX(key, "xauthority=")) {
1028 1029
                        if (VIR_STRDUP(graphics->data.sdl.xauth, key + 11) < 0)
                            goto cleanup;
1030 1031 1032 1033 1034 1035 1036 1037 1038 1039
                    }
                }

                while (nextkey && (nextkey[0] == ',' ||
                                   nextkey[0] == ' ' ||
                                   nextkey[0] == '\t'))
                    nextkey++;
                key = nextkey;
            }
            if (VIR_ALLOC_N(def->graphics, 1) < 0)
1040
                goto cleanup;
1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052
            def->graphics[0] = graphics;
            def->ngraphics = 1;
            graphics = NULL;
        }
    }

    if (hvm) {
        virDomainChrDefPtr chr = NULL;

        if (xenXMConfigGetString(conf, "parallel", &str, NULL) < 0)
            goto cleanup;
        if (str && STRNEQ(str, "none") &&
M
Markus Groß 已提交
1053
            !(chr = xenParseSxprChar(str, NULL)))
1054 1055 1056 1057 1058
            goto cleanup;

        if (chr) {
            if (VIR_ALLOC_N(def->parallels, 1) < 0) {
                virDomainChrDefFree(chr);
1059
                goto cleanup;
1060 1061
            }
            chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_PARALLEL;
M
Michal Novotny 已提交
1062
            chr->target.port = 0;
1063 1064 1065 1066 1067
            def->parallels[0] = chr;
            def->nparallels++;
            chr = NULL;
        }

1068 1069 1070 1071
        /* Try to get the list of values to support multiple serial ports */
        list = virConfGetValue(conf, "serial");
        if (list && list->type == VIR_CONF_LIST) {
            int portnum = -1;
1072

1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092
            list = list->list;
            while (list) {
                char *port = NULL;

                if ((list->type != VIR_CONF_STRING) || (list->str == NULL))
                    goto cleanup;

                port = list->str;
                portnum++;
                if (STREQ(port, "none")) {
                    list = list->next;
                    continue;
                }

                if (!(chr = xenParseSxprChar(port, NULL)))
                    goto cleanup;

                chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL;
                chr->target.port = portnum;

1093 1094 1095 1096
                if (VIR_APPEND_ELEMENT(def->serials, def->nserials, chr) < 0) {
                    virDomainChrDefFree(chr);
                    goto cleanup;
                }
1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109

                list = list->next;
            }
        } else {
            /* If domain is not using multiple serial ports we parse data old way */
            if (xenXMConfigGetString(conf, "serial", &str, NULL) < 0)
                goto cleanup;
            if (str && STRNEQ(str, "none") &&
                !(chr = xenParseSxprChar(str, NULL)))
                goto cleanup;
            if (chr) {
                if (VIR_ALLOC_N(def->serials, 1) < 0) {
                    virDomainChrDefFree(chr);
1110
                    goto cleanup;
1111 1112
                }
                chr->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_SERIAL;
M
Michal Novotny 已提交
1113
                chr->target.port = 0;
1114 1115
                def->serials[0] = chr;
                def->nserials++;
1116 1117 1118
            }
        }
    } else {
1119
        if (VIR_ALLOC_N(def->consoles, 1) < 0)
1120
            goto cleanup;
1121
        def->nconsoles = 1;
1122
        if (!(def->consoles[0] = xenParseSxprChar("pty", NULL)))
1123
            goto cleanup;
1124 1125 1126
        def->consoles[0]->deviceType = VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE;
        def->consoles[0]->target.port = 0;
        def->consoles[0]->targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_XEN;
1127 1128 1129 1130 1131 1132 1133
    }

    if (hvm) {
        if (xenXMConfigGetString(conf, "soundhw", &str, NULL) < 0)
            goto cleanup;

        if (str &&
M
Markus Groß 已提交
1134
            xenParseSxprSound(def, str) < 0)
1135 1136 1137
            goto cleanup;
    }

1138
    VIR_FREE(script);
1139 1140
    return def;

1141
 cleanup:
1142 1143 1144 1145
    virDomainGraphicsDefFree(graphics);
    virDomainNetDefFree(net);
    virDomainDiskDefFree(disk);
    virDomainDefFree(def);
1146
    VIR_FREE(script);
1147
    VIR_FREE(listenAddr);
1148 1149
    return NULL;
}
1150 1151 1152


static
1153 1154
int xenXMConfigSetInt(virConfPtr conf, const char *setting, long long l)
{
1155 1156
    virConfValuePtr value = NULL;

1157
    if ((long) l != l) {
1158 1159
        virReportError(VIR_ERR_OVERFLOW, _("failed to store %lld to %s"),
                       l, setting);
1160 1161
        return -1;
    }
1162
    if (VIR_ALLOC(value) < 0)
1163 1164 1165 1166 1167 1168 1169 1170 1171 1172
        return -1;

    value->type = VIR_CONF_LONG;
    value->next = NULL;
    value->l = l;

    return virConfSetValue(conf, setting, value);
}


1173 1174 1175
static int
xenXMConfigSetString(virConfPtr conf, const char *setting, const char *str)
{
1176 1177
    virConfValuePtr value = NULL;

1178
    if (VIR_ALLOC(value) < 0)
1179 1180 1181 1182
        return -1;

    value->type = VIR_CONF_STRING;
    value->next = NULL;
1183
    if (VIR_STRDUP(value->str, str) < 0) {
1184 1185 1186 1187 1188 1189 1190 1191
        VIR_FREE(value);
        return -1;
    }

    return virConfSetValue(conf, setting, value);
}


1192 1193 1194 1195 1196
static int
xenFormatXMDisk(virConfValuePtr list,
                virDomainDiskDefPtr disk,
                int hvm,
                int xendConfigVersion)
1197 1198 1199
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    virConfValuePtr val, tmp;
1200 1201 1202
    const char *src = virDomainDiskGetSource(disk);
    int format = virDomainDiskGetFormat(disk);
    const char *driver = virDomainDiskGetDriver(disk);
1203

1204 1205
    if (src) {
        if (format) {
1206 1207
            const char *type;

1208
            if (format == VIR_STORAGE_FILE_RAW)
1209
                type = "aio";
1210
            else
1211 1212 1213
                type = virStorageFileFormatTypeToString(format);
            virBufferAsprintf(&buf, "%s:", driver);
            if (STREQ(driver, "tap"))
1214
                virBufferAsprintf(&buf, "%s:", type);
1215
        } else {
1216
            switch (virDomainDiskGetType(disk)) {
E
Eric Blake 已提交
1217
            case VIR_STORAGE_TYPE_FILE:
1218 1219
                virBufferAddLit(&buf, "file:");
                break;
E
Eric Blake 已提交
1220
            case VIR_STORAGE_TYPE_BLOCK:
1221 1222 1223
                virBufferAddLit(&buf, "phy:");
                break;
            default:
1224 1225
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("unsupported disk type %s"),
E
Eric Blake 已提交
1226
                               virStorageTypeToString(virDomainDiskGetType(disk)));
1227 1228 1229
                goto cleanup;
            }
        }
1230
        virBufferAdd(&buf, src, -1);
1231 1232
    }
    virBufferAddLit(&buf, ",");
1233
    if (hvm && xendConfigVersion == XEND_CONFIG_VERSION_3_0_2)
1234 1235
        virBufferAddLit(&buf, "ioemu:");

1236
    virBufferAdd(&buf, disk->dst, -1);
1237 1238 1239 1240 1241 1242 1243 1244 1245
    if (disk->device == VIR_DOMAIN_DISK_DEVICE_CDROM)
        virBufferAddLit(&buf, ":cdrom");

    if (disk->readonly)
        virBufferAddLit(&buf, ",r");
    else if (disk->shared)
        virBufferAddLit(&buf, ",!");
    else
        virBufferAddLit(&buf, ",w");
1246
    if (disk->transient) {
1247
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
1248
                       _("transient disks not supported yet"));
1249 1250
        return -1;
    }
1251 1252 1253 1254 1255 1256

    if (virBufferError(&buf)) {
        virReportOOMError();
        goto cleanup;
    }

1257
    if (VIR_ALLOC(val) < 0)
1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271
        goto cleanup;

    val->type = VIR_CONF_STRING;
    val->str = virBufferContentAndReset(&buf);
    tmp = list->list;
    while (tmp && tmp->next)
        tmp = tmp->next;
    if (tmp)
        tmp->next = val;
    else
        list->list = val;

    return 0;

1272
 cleanup:
1273 1274 1275 1276
    virBufferFreeAndReset(&buf);
    return -1;
}

1277 1278 1279 1280 1281 1282 1283 1284 1285
static int xenFormatXMSerial(virConfValuePtr list,
                             virDomainChrDefPtr serial)
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    virConfValuePtr val, tmp;
    int ret;

    if (serial) {
        ret = xenFormatSxprChr(serial, &buf);
1286
        if (ret < 0)
1287 1288 1289 1290 1291 1292 1293 1294 1295
            goto cleanup;
    } else {
        virBufferAddLit(&buf, "none");
    }
    if (virBufferError(&buf)) {
        virReportOOMError();
        goto cleanup;
    }

1296
    if (VIR_ALLOC(val) < 0)
1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310
        goto cleanup;

    val->type = VIR_CONF_STRING;
    val->str = virBufferContentAndReset(&buf);
    tmp = list->list;
    while (tmp && tmp->next)
        tmp = tmp->next;
    if (tmp)
        tmp->next = val;
    else
        list->list = val;

    return 0;

1311
 cleanup:
1312 1313 1314 1315
    virBufferFreeAndReset(&buf);
    return -1;
}

M
Markus Groß 已提交
1316
static int xenFormatXMNet(virConnectPtr conn,
1317 1318 1319 1320 1321 1322
                                      virConfValuePtr list,
                                      virDomainNetDefPtr net,
                                      int hvm, int xendConfigVersion)
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    virConfValuePtr val, tmp;
1323
    char macaddr[VIR_MAC_STRING_BUFLEN];
1324

1325
    virBufferAsprintf(&buf, "mac=%s", virMacAddrFormat(&net->mac, macaddr));
1326 1327 1328

    switch (net->type) {
    case VIR_DOMAIN_NET_TYPE_BRIDGE:
1329
        virBufferAsprintf(&buf, ",bridge=%s", net->data.bridge.brname);
1330
        if (net->data.bridge.ipaddr)
1331 1332
            virBufferAsprintf(&buf, ",ip=%s", net->data.bridge.ipaddr);
        virBufferAsprintf(&buf, ",script=%s", DEFAULT_VIF_SCRIPT);
1333 1334 1335
        break;

    case VIR_DOMAIN_NET_TYPE_ETHERNET:
1336 1337
        if (net->script)
            virBufferAsprintf(&buf, ",script=%s", net->script);
1338
        if (net->data.ethernet.ipaddr)
1339
            virBufferAsprintf(&buf, ",ip=%s", net->data.ethernet.ipaddr);
1340 1341 1342 1343 1344 1345 1346
        break;

    case VIR_DOMAIN_NET_TYPE_NETWORK:
    {
        virNetworkPtr network = virNetworkLookupByName(conn, net->data.network.name);
        char *bridge;
        if (!network) {
1347 1348
            virReportError(VIR_ERR_NO_NETWORK, "%s",
                           net->data.network.name);
1349 1350 1351 1352 1353
            return -1;
        }
        bridge = virNetworkGetBridgeName(network);
        virNetworkFree(network);
        if (!bridge) {
1354 1355 1356
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("network %s is not active"),
                           net->data.network.name);
1357 1358 1359
            return -1;
        }

1360 1361
        virBufferAsprintf(&buf, ",bridge=%s", bridge);
        virBufferAsprintf(&buf, ",script=%s", DEFAULT_VIF_SCRIPT);
1362 1363 1364 1365
    }
    break;

    default:
1366 1367 1368
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unsupported network type %d"),
                       net->type);
1369 1370 1371 1372 1373
        goto cleanup;
    }

    if (!hvm) {
        if (net->model != NULL)
1374
            virBufferAsprintf(&buf, ",model=%s", net->model);
1375 1376
    }
    else {
1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390
        if (net->model != NULL && STREQ(net->model, "netfront")) {
            virBufferAddLit(&buf, ",type=netfront");
        }
        else {
            if (net->model != NULL)
                virBufferAsprintf(&buf, ",model=%s", net->model);

            /*
             * apparently type ioemu breaks paravirt drivers on HVM so skip this
             * from XEND_CONFIG_MAX_VERS_NET_TYPE_IOEMU
             */
            if (xendConfigVersion <= XEND_CONFIG_MAX_VERS_NET_TYPE_IOEMU)
                virBufferAddLit(&buf, ",type=ioemu");
        }
1391 1392 1393
    }

    if (net->ifname)
1394
        virBufferAsprintf(&buf, ",vifname=%s",
1395 1396 1397 1398 1399 1400 1401
                          net->ifname);

    if (virBufferError(&buf)) {
        virReportOOMError();
        goto cleanup;
    }

1402
    if (VIR_ALLOC(val) < 0)
1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416
        goto cleanup;

    val->type = VIR_CONF_STRING;
    val->str = virBufferContentAndReset(&buf);
    tmp = list->list;
    while (tmp && tmp->next)
        tmp = tmp->next;
    if (tmp)
        tmp->next = val;
    else
        list->list = val;

    return 0;

1417
 cleanup:
1418 1419 1420 1421 1422 1423 1424
    virBufferFreeAndReset(&buf);
    return -1;
}



static int
M
Markus Groß 已提交
1425
xenFormatXMPCI(virConfPtr conf,
1426 1427 1428 1429 1430
                           virDomainDefPtr def)
{

    virConfValuePtr pciVal = NULL;
    int hasPCI = 0;
1431
    size_t i;
1432

1433
    for (i = 0; i < def->nhostdevs; i++)
1434 1435 1436 1437 1438 1439 1440
        if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
            def->hostdevs[i]->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
            hasPCI = 1;

    if (!hasPCI)
        return 0;

1441
    if (VIR_ALLOC(pciVal) < 0)
1442 1443 1444 1445 1446
        return -1;

    pciVal->type = VIR_CONF_LIST;
    pciVal->list = NULL;

1447
    for (i = 0; i < def->nhostdevs; i++) {
1448 1449 1450 1451 1452 1453
        if (def->hostdevs[i]->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
            def->hostdevs[i]->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) {
            virConfValuePtr val, tmp;
            char *buf;

            if (virAsprintf(&buf, "%04x:%02x:%02x.%x",
1454 1455 1456
                            def->hostdevs[i]->source.subsys.u.pci.addr.domain,
                            def->hostdevs[i]->source.subsys.u.pci.addr.bus,
                            def->hostdevs[i]->source.subsys.u.pci.addr.slot,
1457
                            def->hostdevs[i]->source.subsys.u.pci.addr.function) < 0)
1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485
                goto error;

            if (VIR_ALLOC(val) < 0) {
                VIR_FREE(buf);
                goto error;
            }
            val->type = VIR_CONF_STRING;
            val->str = buf;
            tmp = pciVal->list;
            while (tmp && tmp->next)
                tmp = tmp->next;
            if (tmp)
                tmp->next = val;
            else
                pciVal->list = val;
        }
    }

    if (pciVal->list != NULL) {
        int ret = virConfSetValue(conf, "pci", pciVal);
        pciVal = NULL;
        if (ret < 0)
            return -1;
    }
    VIR_FREE(pciVal);

    return 0;

1486
 error:
1487 1488 1489 1490 1491 1492 1493 1494 1495
    virConfFreeValue(pciVal);
    return -1;
}


/* Computing the vcpu_avail bitmask works because MAX_VIRT_CPUS is
   either 32, or 64 on a platform where long is big enough.  */
verify(MAX_VIRT_CPUS <= sizeof(1UL) * CHAR_BIT);

M
Markus Groß 已提交
1496
virConfPtr xenFormatXM(virConnectPtr conn,
1497
                                   virDomainDefPtr def,
1498 1499
                                   int xendConfigVersion)
{
1500
    virConfPtr conf = NULL;
1501 1502
    int hvm = 0, vmlocaltime = 0;
    size_t i;
1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513
    char *cpus = NULL;
    const char *lifecycle;
    char uuid[VIR_UUID_STRING_BUFLEN];
    virConfValuePtr diskVal = NULL;
    virConfValuePtr netVal = NULL;

    if (!(conf = virConfNew()))
        goto cleanup;


    if (xenXMConfigSetString(conf, "name", def->name) < 0)
1514
        goto cleanup;
1515 1516 1517

    virUUIDFormat(def->uuid, uuid);
    if (xenXMConfigSetString(conf, "uuid", uuid) < 0)
1518
        goto cleanup;
1519

1520 1521
    if (xenXMConfigSetInt(conf, "maxmem",
                          VIR_DIV_UP(def->mem.max_balloon, 1024)) < 0)
1522
        goto cleanup;
1523

1524 1525
    if (xenXMConfigSetInt(conf, "memory",
                          VIR_DIV_UP(def->mem.cur_balloon, 1024)) < 0)
1526
        goto cleanup;
1527 1528

    if (xenXMConfigSetInt(conf, "vcpus", def->maxvcpus) < 0)
1529
        goto cleanup;
1530 1531 1532 1533
    /* Computing the vcpu_avail bitmask works because MAX_VIRT_CPUS is
       either 32, or 64 on a platform where long is big enough.  */
    if (def->vcpus < def->maxvcpus &&
        xenXMConfigSetInt(conf, "vcpu_avail", (1UL << def->vcpus) - 1) < 0)
1534
        goto cleanup;
1535 1536

    if ((def->cpumask != NULL) &&
H
Hu Tao 已提交
1537
        ((cpus = virBitmapFormat(def->cpumask)) == NULL)) {
1538
        goto cleanup;
H
Hu Tao 已提交
1539
    }
1540 1541 1542

    if (cpus &&
        xenXMConfigSetString(conf, "cpus", cpus) < 0)
1543
        goto cleanup;
1544 1545 1546 1547 1548 1549 1550
    VIR_FREE(cpus);

    hvm = STREQ(def->os.type, "hvm") ? 1 : 0;

    if (hvm) {
        char boot[VIR_DOMAIN_BOOT_LAST+1];
        if (xenXMConfigSetString(conf, "builder", "hvm") < 0)
1551
            goto cleanup;
1552 1553 1554

        if (def->os.loader &&
            xenXMConfigSetString(conf, "kernel", def->os.loader) < 0)
1555
            goto cleanup;
1556

1557
        for (i = 0; i < def->os.nBootDevs; i++) {
1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581
            switch (def->os.bootDevs[i]) {
            case VIR_DOMAIN_BOOT_FLOPPY:
                boot[i] = 'a';
                break;
            case VIR_DOMAIN_BOOT_CDROM:
                boot[i] = 'd';
                break;
            case VIR_DOMAIN_BOOT_NET:
                boot[i] = 'n';
                break;
            case VIR_DOMAIN_BOOT_DISK:
            default:
                boot[i] = 'c';
                break;
            }
        }
        if (!def->os.nBootDevs) {
            boot[0] = 'c';
            boot[1] = '\0';
        } else {
            boot[def->os.nBootDevs] = '\0';
        }

        if (xenXMConfigSetString(conf, "boot", boot) < 0)
1582
            goto cleanup;
1583 1584

        if (xenXMConfigSetInt(conf, "pae",
1585 1586
                              (def->features[VIR_DOMAIN_FEATURE_PAE] ==
                               VIR_DOMAIN_FEATURE_STATE_ON) ? 1 : 0) < 0)
1587
            goto cleanup;
1588 1589

        if (xenXMConfigSetInt(conf, "acpi",
1590 1591
                              (def->features[VIR_DOMAIN_FEATURE_ACPI] ==
                               VIR_DOMAIN_FEATURE_STATE_ON) ? 1 : 0) < 0)
1592
            goto cleanup;
1593 1594

        if (xenXMConfigSetInt(conf, "apic",
1595 1596
                              (def->features[VIR_DOMAIN_FEATURE_APIC] ==
                               VIR_DOMAIN_FEATURE_STATE_ON) ? 1 : 0) < 0)
1597
            goto cleanup;
1598

1599
        if (xendConfigVersion >= XEND_CONFIG_VERSION_3_0_4) {
1600
            if (xenXMConfigSetInt(conf, "hap",
1601 1602
                                  (def->features[VIR_DOMAIN_FEATURE_HAP] ==
                                   VIR_DOMAIN_FEATURE_STATE_ON) ? 1 : 0) < 0)
1603
                goto cleanup;
1604

1605
            if (xenXMConfigSetInt(conf, "viridian",
1606 1607
                                  (def->features[VIR_DOMAIN_FEATURE_VIRIDIAN] ==
                                   VIR_DOMAIN_FEATURE_STATE_ON) ? 1 : 0) < 0)
1608
                goto cleanup;
1609 1610
        }

1611 1612 1613 1614
        for (i = 0; i < def->clock.ntimers; i++) {
            if (def->clock.timers[i]->name == VIR_DOMAIN_TIMER_NAME_HPET &&
                def->clock.timers[i]->present != -1 &&
                xenXMConfigSetInt(conf, "hpet", def->clock.timers[i]->present) < 0)
1615
                goto cleanup;
1616 1617
        }

1618
        if (xendConfigVersion == XEND_CONFIG_VERSION_3_0_2) {
1619
            for (i = 0; i < def->ndisks; i++) {
1620 1621 1622
                if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_CDROM &&
                    def->disks[i]->dst &&
                    STREQ(def->disks[i]->dst, "hdc") &&
1623
                    virDomainDiskGetSource(def->disks[i])) {
1624
                    if (xenXMConfigSetString(conf, "cdrom",
1625
                                             virDomainDiskGetSource(def->disks[i])) < 0)
1626
                        goto cleanup;
1627 1628 1629 1630 1631 1632 1633 1634 1635
                    break;
                }
            }
        }

        /* XXX floppy disks */
    } else {
        if (def->os.bootloader &&
            xenXMConfigSetString(conf, "bootloader", def->os.bootloader) < 0)
1636
            goto cleanup;
1637 1638
        if (def->os.bootloaderArgs &&
            xenXMConfigSetString(conf, "bootargs", def->os.bootloaderArgs) < 0)
1639
            goto cleanup;
1640 1641
        if (def->os.kernel &&
            xenXMConfigSetString(conf, "kernel", def->os.kernel) < 0)
1642
            goto cleanup;
1643 1644
        if (def->os.initrd &&
            xenXMConfigSetString(conf, "ramdisk", def->os.initrd) < 0)
1645
            goto cleanup;
1646 1647
        if (def->os.cmdline &&
            xenXMConfigSetString(conf, "extra", def->os.cmdline) < 0)
1648
            goto cleanup;
P
Philipp Hahn 已提交
1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661
    } /* !hvm */


    if (xendConfigVersion < XEND_CONFIG_VERSION_3_1_0) {
        /* <3.1: UTC and LOCALTIME */
        switch (def->clock.offset) {
        case VIR_DOMAIN_CLOCK_OFFSET_UTC:
            vmlocaltime = 0;
            break;
        case VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME:
            vmlocaltime = 1;
            break;
        default:
1662 1663 1664
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("unsupported clock offset='%s'"),
                           virDomainClockOffsetTypeToString(def->clock.offset));
P
Philipp Hahn 已提交
1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677
            goto cleanup;
        }
    } else {
        if (hvm) {
            /* >=3.1 HV: VARIABLE */
            int rtc_timeoffset;
            switch (def->clock.offset) {
            case VIR_DOMAIN_CLOCK_OFFSET_VARIABLE:
                vmlocaltime = (int)def->clock.data.variable.basis;
                rtc_timeoffset = def->clock.data.variable.adjustment;
                break;
            case VIR_DOMAIN_CLOCK_OFFSET_UTC:
                if (def->clock.data.utc_reset) {
1678
                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
1679
                                   _("unsupported clock adjustment='reset'"));
P
Philipp Hahn 已提交
1680 1681 1682 1683 1684 1685 1686
                    goto cleanup;
                }
                vmlocaltime = 0;
                rtc_timeoffset = 0;
                break;
            case VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME:
                if (def->clock.data.utc_reset) {
1687
                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
1688
                                   _("unsupported clock adjustment='reset'"));
P
Philipp Hahn 已提交
1689 1690 1691 1692 1693 1694
                    goto cleanup;
                }
                vmlocaltime = 1;
                rtc_timeoffset = 0;
                break;
            default:
1695 1696 1697
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("unsupported clock offset='%s'"),
                               virDomainClockOffsetTypeToString(def->clock.offset));
P
Philipp Hahn 已提交
1698 1699 1700
                goto cleanup;
            }
            if (xenXMConfigSetInt(conf, "rtc_timeoffset", rtc_timeoffset) < 0)
1701
                goto cleanup;
P
Philipp Hahn 已提交
1702 1703 1704 1705 1706 1707 1708 1709 1710 1711
        } else {
            /* >=3.1 PV: UTC and LOCALTIME */
            switch (def->clock.offset) {
            case VIR_DOMAIN_CLOCK_OFFSET_UTC:
                vmlocaltime = 0;
                break;
            case VIR_DOMAIN_CLOCK_OFFSET_LOCALTIME:
                vmlocaltime = 1;
                break;
            default:
1712 1713 1714
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("unsupported clock offset='%s'"),
                               virDomainClockOffsetTypeToString(def->clock.offset));
P
Philipp Hahn 已提交
1715 1716 1717
                goto cleanup;
            }
        } /* !hvm */
1718
    }
P
Philipp Hahn 已提交
1719
    if (xenXMConfigSetInt(conf, "localtime", vmlocaltime) < 0)
1720
        goto cleanup;
P
Philipp Hahn 已提交
1721

1722 1723

    if (!(lifecycle = virDomainLifecycleTypeToString(def->onPoweroff))) {
1724 1725
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unexpected lifecycle action %d"), def->onPoweroff);
1726 1727 1728
        goto cleanup;
    }
    if (xenXMConfigSetString(conf, "on_poweroff", lifecycle) < 0)
1729
        goto cleanup;
1730 1731 1732


    if (!(lifecycle = virDomainLifecycleTypeToString(def->onReboot))) {
1733 1734
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unexpected lifecycle action %d"), def->onReboot);
1735 1736 1737
        goto cleanup;
    }
    if (xenXMConfigSetString(conf, "on_reboot", lifecycle) < 0)
1738
        goto cleanup;
1739 1740 1741


    if (!(lifecycle = virDomainLifecycleCrashTypeToString(def->onCrash))) {
1742 1743
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("unexpected lifecycle action %d"), def->onCrash);
1744 1745 1746
        goto cleanup;
    }
    if (xenXMConfigSetString(conf, "on_crash", lifecycle) < 0)
1747
        goto cleanup;
1748 1749 1750 1751 1752 1753



    if (hvm) {
        if (def->emulator &&
            xenXMConfigSetString(conf, "device_model", def->emulator) < 0)
1754
            goto cleanup;
1755

1756
        for (i = 0; i < def->ninputs; i++) {
1757 1758
            if (def->inputs[i]->bus == VIR_DOMAIN_INPUT_BUS_USB) {
                if (xenXMConfigSetInt(conf, "usb", 1) < 0)
1759
                    goto cleanup;
1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773
                switch (def->inputs[i]->type) {
                    case VIR_DOMAIN_INPUT_TYPE_MOUSE:
                        if (xenXMConfigSetString(conf, "usbdevice", "mouse") < 0)
                            goto cleanup;
                        break;
                    case VIR_DOMAIN_INPUT_TYPE_TABLET:
                        if (xenXMConfigSetString(conf, "usbdevice", "tablet") < 0)
                            goto cleanup;
                        break;
                    case VIR_DOMAIN_INPUT_TYPE_KBD:
                        if (xenXMConfigSetString(conf, "usbdevice", "keyboard") < 0)
                            goto cleanup;
                        break;
                }
1774 1775 1776 1777 1778 1779
                break;
            }
        }
    }

    if (def->ngraphics == 1) {
1780
        if (hvm || (xendConfigVersion < XEND_CONFIG_MIN_VERS_PVFB_NEWCONF)) {
1781 1782
            if (def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
                if (xenXMConfigSetInt(conf, "sdl", 1) < 0)
1783
                    goto cleanup;
1784
                if (xenXMConfigSetInt(conf, "vnc", 0) < 0)
1785
                    goto cleanup;
1786 1787 1788
                if (def->graphics[0]->data.sdl.display &&
                    xenXMConfigSetString(conf, "display",
                                     def->graphics[0]->data.sdl.display) < 0)
1789
                    goto cleanup;
1790 1791 1792
                if (def->graphics[0]->data.sdl.xauth &&
                    xenXMConfigSetString(conf, "xauthority",
                                         def->graphics[0]->data.sdl.xauth) < 0)
1793
                    goto cleanup;
1794
            } else {
1795 1796
                const char *listenAddr;

1797
                if (xenXMConfigSetInt(conf, "sdl", 0) < 0)
1798
                    goto cleanup;
1799
                if (xenXMConfigSetInt(conf, "vnc", 1) < 0)
1800
                    goto cleanup;
1801 1802
                if (xenXMConfigSetInt(conf, "vncunused",
                              def->graphics[0]->data.vnc.autoport ? 1 : 0) < 0)
1803
                    goto cleanup;
1804 1805 1806
                if (!def->graphics[0]->data.vnc.autoport &&
                    xenXMConfigSetInt(conf, "vncdisplay",
                                  def->graphics[0]->data.vnc.port - 5900) < 0)
1807
                    goto cleanup;
1808 1809 1810
                listenAddr = virDomainGraphicsListenGetAddress(def->graphics[0], 0);
                if (listenAddr &&
                    xenXMConfigSetString(conf, "vnclisten", listenAddr) < 0)
1811
                    goto cleanup;
1812 1813 1814
                if (def->graphics[0]->data.vnc.auth.passwd &&
                    xenXMConfigSetString(conf, "vncpasswd",
                                        def->graphics[0]->data.vnc.auth.passwd) < 0)
1815
                    goto cleanup;
1816 1817 1818
                if (def->graphics[0]->data.vnc.keymap &&
                    xenXMConfigSetString(conf, "keymap",
                                        def->graphics[0]->data.vnc.keymap) < 0)
1819
                    goto cleanup;
1820 1821 1822 1823 1824 1825 1826 1827
            }
        } else {
            virConfValuePtr vfb, disp;
            char *vfbstr = NULL;
            virBuffer buf = VIR_BUFFER_INITIALIZER;
            if (def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_SDL) {
                virBufferAddLit(&buf, "type=sdl");
                if (def->graphics[0]->data.sdl.display)
1828
                    virBufferAsprintf(&buf, ",display=%s",
1829 1830
                                      def->graphics[0]->data.sdl.display);
                if (def->graphics[0]->data.sdl.xauth)
1831
                    virBufferAsprintf(&buf, ",xauthority=%s",
1832 1833
                                      def->graphics[0]->data.sdl.xauth);
            } else {
1834 1835 1836
                const char *listenAddr
                    = virDomainGraphicsListenGetAddress(def->graphics[0], 0);

1837
                virBufferAddLit(&buf, "type=vnc");
1838
                virBufferAsprintf(&buf, ",vncunused=%d",
1839 1840
                                  def->graphics[0]->data.vnc.autoport ? 1 : 0);
                if (!def->graphics[0]->data.vnc.autoport)
1841
                    virBufferAsprintf(&buf, ",vncdisplay=%d",
1842
                                      def->graphics[0]->data.vnc.port - 5900);
1843 1844
                if (listenAddr)
                    virBufferAsprintf(&buf, ",vnclisten=%s", listenAddr);
1845
                if (def->graphics[0]->data.vnc.auth.passwd)
1846
                    virBufferAsprintf(&buf, ",vncpasswd=%s",
1847 1848
                                      def->graphics[0]->data.vnc.auth.passwd);
                if (def->graphics[0]->data.vnc.keymap)
1849
                    virBufferAsprintf(&buf, ",keymap=%s",
1850 1851 1852 1853
                                      def->graphics[0]->data.vnc.keymap);
            }
            if (virBufferError(&buf)) {
                virBufferFreeAndReset(&buf);
1854 1855
                virReportOOMError();
                goto cleanup;
1856 1857 1858 1859 1860 1861
            }

            vfbstr = virBufferContentAndReset(&buf);

            if (VIR_ALLOC(vfb) < 0) {
                VIR_FREE(vfbstr);
1862
                goto cleanup;
1863 1864 1865 1866 1867
            }

            if (VIR_ALLOC(disp) < 0) {
                VIR_FREE(vfb);
                VIR_FREE(vfbstr);
1868
                goto cleanup;
1869 1870 1871 1872 1873 1874 1875 1876
            }

            vfb->type = VIR_CONF_LIST;
            vfb->list = disp;
            disp->type = VIR_CONF_STRING;
            disp->str = vfbstr;

            if (virConfSetValue(conf, "vfb", vfb) < 0)
1877
                goto cleanup;
1878 1879 1880 1881 1882
        }
    }

    /* analyze of the devices */
    if (VIR_ALLOC(diskVal) < 0)
1883
        goto cleanup;
1884 1885 1886
    diskVal->type = VIR_CONF_LIST;
    diskVal->list = NULL;

1887
    for (i = 0; i < def->ndisks; i++) {
1888
        if (xendConfigVersion == XEND_CONFIG_VERSION_3_0_2 &&
1889 1890 1891 1892 1893 1894 1895 1896
            def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_CDROM &&
            def->disks[i]->dst &&
            STREQ(def->disks[i]->dst, "hdc")) {
            continue;
        }
        if (def->disks[i]->device == VIR_DOMAIN_DISK_DEVICE_FLOPPY)
            continue;

M
Markus Groß 已提交
1897 1898
        if (xenFormatXMDisk(diskVal, def->disks[i],
                            hvm, xendConfigVersion) < 0)
1899 1900 1901 1902 1903 1904
            goto cleanup;
    }
    if (diskVal->list != NULL) {
        int ret = virConfSetValue(conf, "disk", diskVal);
        diskVal = NULL;
        if (ret < 0)
1905
            goto cleanup;
1906 1907 1908 1909
    }
    VIR_FREE(diskVal);

    if (VIR_ALLOC(netVal) < 0)
1910
        goto cleanup;
1911 1912 1913
    netVal->type = VIR_CONF_LIST;
    netVal->list = NULL;

1914
    for (i = 0; i < def->nnets; i++) {
E
Eric Blake 已提交
1915
        if (xenFormatXMNet(conn, netVal, def->nets[i],
M
Markus Groß 已提交
1916
                           hvm, xendConfigVersion) < 0)
1917 1918 1919 1920 1921 1922
            goto cleanup;
    }
    if (netVal->list != NULL) {
        int ret = virConfSetValue(conf, "vif", netVal);
        netVal = NULL;
        if (ret < 0)
1923
            goto cleanup;
1924 1925 1926
    }
    VIR_FREE(netVal);

M
Markus Groß 已提交
1927
    if (xenFormatXMPCI(conf, def) < 0)
1928 1929 1930 1931 1932 1933 1934 1935
        goto cleanup;

    if (hvm) {
        if (def->nparallels) {
            virBuffer buf = VIR_BUFFER_INITIALIZER;
            char *str;
            int ret;

M
Markus Groß 已提交
1936
            ret = xenFormatSxprChr(def->parallels[0], &buf);
1937 1938 1939 1940 1941
            str = virBufferContentAndReset(&buf);
            if (ret == 0)
                ret = xenXMConfigSetString(conf, "parallel", str);
            VIR_FREE(str);
            if (ret < 0)
1942
                goto cleanup;
1943 1944
        } else {
            if (xenXMConfigSetString(conf, "parallel", "none") < 0)
1945
                goto cleanup;
1946 1947 1948
        }

        if (def->nserials) {
1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959
            if ((def->nserials == 1) && (def->serials[0]->target.port == 0)) {
                virBuffer buf = VIR_BUFFER_INITIALIZER;
                char *str;
                int ret;

                ret = xenFormatSxprChr(def->serials[0], &buf);
                str = virBufferContentAndReset(&buf);
                if (ret == 0)
                    ret = xenXMConfigSetString(conf, "serial", str);
                VIR_FREE(str);
                if (ret < 0)
1960
                    goto cleanup;
1961
            } else {
1962 1963
                size_t j = 0;
                int maxport = -1, port;
1964
                virConfValuePtr serialVal = NULL;
1965

1966
                if (VIR_ALLOC(serialVal) < 0)
1967
                    goto cleanup;
1968 1969 1970 1971 1972 1973 1974
                serialVal->type = VIR_CONF_LIST;
                serialVal->list = NULL;

                for (i = 0; i < def->nserials; i++)
                    if (def->serials[i]->target.port > maxport)
                        maxport = def->serials[i]->target.port;

1975
                for (port = 0; port <= maxport; port++) {
1976 1977
                    virDomainChrDefPtr chr = NULL;
                    for (j = 0; j < def->nserials; j++) {
1978
                        if (def->serials[j]->target.port == port) {
1979 1980 1981 1982
                            chr = def->serials[j];
                            break;
                        }
                    }
1983 1984
                    if (xenFormatXMSerial(serialVal, chr) < 0) {
                        virConfFreeValue(serialVal);
1985
                        goto cleanup;
1986
                    }
1987 1988 1989 1990 1991 1992
                }

                if (serialVal->list != NULL) {
                    int ret = virConfSetValue(conf, "serial", serialVal);
                    serialVal = NULL;
                    if (ret < 0)
1993
                        goto cleanup;
1994 1995 1996
                }
                VIR_FREE(serialVal);
            }
1997 1998
        } else {
            if (xenXMConfigSetString(conf, "serial", "none") < 0)
1999
                goto cleanup;
2000 2001 2002 2003 2004 2005
        }


        if (def->sounds) {
            virBuffer buf = VIR_BUFFER_INITIALIZER;
            char *str = NULL;
M
Markus Groß 已提交
2006
            int ret = xenFormatSxprSound(def, &buf);
2007 2008 2009 2010 2011 2012
            str = virBufferContentAndReset(&buf);
            if (ret == 0)
                ret = xenXMConfigSetString(conf, "soundhw", str);

            VIR_FREE(str);
            if (ret < 0)
2013
                goto cleanup;
2014 2015 2016 2017 2018
        }
    }

    return conf;

2019
 cleanup:
2020 2021 2022 2023 2024
    virConfFreeValue(diskVal);
    virConfFreeValue(netVal);
    VIR_FREE(cpus);
    if (conf)
        virConfFree(conf);
2025
    return NULL;
2026
}