capabilities.c 26.6 KB
Newer Older
1 2 3
/*
 * capabilities.c: hypervisor capabilities
 *
4
 * Copyright (C) 2006-2008, 2010-2011, 2013 Red Hat, Inc.
5 6 7 8 9 10 11 12 13 14 15 16 17
 * Copyright (C) 2006-2008 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
18
 * License along with this library.  If not, see
O
Osier Yang 已提交
19
 * <http://www.gnu.org/licenses/>.
20 21 22 23
 *
 * Author: Daniel P. Berrange <berrange@redhat.com>
 */

24 25
#include <config.h>

26 27
#include <strings.h>

28
#include "capabilities.h"
29
#include "virbuffer.h"
30
#include "viralloc.h"
31
#include "viruuid.h"
32
#include "cpu_conf.h"
33
#include "virerror.h"
34
#include "virstring.h"
35 36 37

#define VIR_FROM_THIS VIR_FROM_CAPABILITIES

38 39
VIR_ENUM_DECL(virCapsHostPMTarget)
VIR_ENUM_IMPL(virCapsHostPMTarget, VIR_NODE_SUSPEND_TARGET_LAST,
40
              "suspend_mem", "suspend_disk", "suspend_hybrid");
41

42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
static virClassPtr virCapsClass;
static void virCapabilitiesDispose(void *obj);

static int virCapabilitiesOnceInit(void)
{
    if (!(virCapsClass = virClassNew(virClassForObject(),
                                     "virCaps",
                                     sizeof(virCaps),
                                     virCapabilitiesDispose)))
        return -1;

    return 0;
}

VIR_ONCE_GLOBAL_INIT(virCapabilities)

58 59
/**
 * virCapabilitiesNew:
60
 * @hostarch: host machine architecture
61 62
 * @offlineMigrate: non-zero if offline migration is available
 * @liveMigrate: non-zero if live migration is available
63
 *
64 65 66
 * Allocate a new capabilities object
 */
virCapsPtr
67
virCapabilitiesNew(virArch hostarch,
68 69 70 71 72
                   int offlineMigrate,
                   int liveMigrate)
{
    virCapsPtr caps;

73 74 75 76
    if (virCapabilitiesInitialize() < 0)
        return NULL;

    if (!(caps = virObjectNew(virCapsClass)))
77
        return NULL;
78

79
    caps->host.arch = hostarch;
80 81 82 83 84 85
    caps->host.offlineMigrate = offlineMigrate;
    caps->host.liveMigrate = liveMigrate;

    return caps;
}

86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
void
virCapabilitiesClearHostNUMACellCPUTopology(virCapsHostNUMACellCPUPtr cpus,
                                            size_t ncpus)
{
    size_t i;

    if (!cpus)
        return;

    for (i = 0; i < ncpus; i++) {
        virBitmapFree(cpus[i].siblings);
        cpus[i].siblings = NULL;
    }
}

101 102 103
static void
virCapabilitiesFreeHostNUMACell(virCapsHostNUMACellPtr cell)
{
104 105 106
    if (cell == NULL)
        return;

107 108
    virCapabilitiesClearHostNUMACellCPUTopology(cell->cpus, cell->ncpus);

109 110
    VIR_FREE(cell->cpus);
    VIR_FREE(cell);
111 112
}

113 114 115 116 117 118 119 120 121 122
static void
virCapabilitiesFreeGuestMachine(virCapsGuestMachinePtr machine)
{
    if (machine == NULL)
        return;
    VIR_FREE(machine->name);
    VIR_FREE(machine->canonical);
    VIR_FREE(machine);
}

123 124 125 126
static void
virCapabilitiesFreeGuestDomain(virCapsGuestDomainPtr dom)
{
    int i;
127 128 129
    if (dom == NULL)
        return;

130 131
    VIR_FREE(dom->info.emulator);
    VIR_FREE(dom->info.loader);
132
    for (i = 0; i < dom->info.nmachines; i++)
133
        virCapabilitiesFreeGuestMachine(dom->info.machines[i]);
134 135
    VIR_FREE(dom->info.machines);
    VIR_FREE(dom->type);
136

137
    VIR_FREE(dom);
138 139 140 141 142
}

static void
virCapabilitiesFreeGuestFeature(virCapsGuestFeaturePtr feature)
{
143 144
    if (feature == NULL)
        return;
145 146
    VIR_FREE(feature->name);
    VIR_FREE(feature);
147 148 149 150 151 152
}

static void
virCapabilitiesFreeGuest(virCapsGuestPtr guest)
{
    int i;
153 154 155
    if (guest == NULL)
        return;

156
    VIR_FREE(guest->ostype);
157

158 159
    VIR_FREE(guest->arch.defaultInfo.emulator);
    VIR_FREE(guest->arch.defaultInfo.loader);
160
    for (i = 0; i < guest->arch.defaultInfo.nmachines; i++)
161
        virCapabilitiesFreeGuestMachine(guest->arch.defaultInfo.machines[i]);
162
    VIR_FREE(guest->arch.defaultInfo.machines);
163

164
    for (i = 0; i < guest->arch.ndomains; i++)
165
        virCapabilitiesFreeGuestDomain(guest->arch.domains[i]);
166
    VIR_FREE(guest->arch.domains);
167

168
    for (i = 0; i < guest->nfeatures; i++)
169
        virCapabilitiesFreeGuestFeature(guest->features[i]);
170
    VIR_FREE(guest->features);
171

172
    VIR_FREE(guest);
173 174
}

175 176 177 178 179
void
virCapabilitiesFreeNUMAInfo(virCapsPtr caps)
{
    int i;

180
    for (i = 0; i < caps->host.nnumaCell; i++)
181 182
        virCapabilitiesFreeHostNUMACell(caps->host.numaCell[i]);
    VIR_FREE(caps->host.numaCell);
183
    caps->host.nnumaCell = 0;
184
}
185

186 187 188 189
static void
virCapabilitiesDispose(void *object)
{
    virCapsPtr caps = object;
190 191
    int i;

192
    for (i = 0; i < caps->nguests; i++)
193
        virCapabilitiesFreeGuest(caps->guests[i]);
194
    VIR_FREE(caps->guests);
195

196
    for (i = 0; i < caps->host.nfeatures; i++)
197 198
        VIR_FREE(caps->host.features[i]);
    VIR_FREE(caps->host.features);
199 200

    virCapabilitiesFreeNUMAInfo(caps);
201

202
    for (i = 0; i < caps->host.nmigrateTrans; i++)
203 204
        VIR_FREE(caps->host.migrateTrans[i]);
    VIR_FREE(caps->host.migrateTrans);
205

206 207 208 209 210 211
    for (i = 0; i < caps->host.nsecModels; i++) {
        VIR_FREE(caps->host.secModels[i].model);
        VIR_FREE(caps->host.secModels[i].doi);
    }
    VIR_FREE(caps->host.secModels);

212
    virCPUDefFree(caps->host.cpu);
213 214 215 216 217 218 219 220 221 222 223 224 225 226
}


/**
 * virCapabilitiesAddHostFeature:
 * @caps: capabilities to extend
 * @name: name of new feature
 *
 * Registers a new host CPU feature, eg 'pae', or 'vmx'
 */
int
virCapabilitiesAddHostFeature(virCapsPtr caps,
                              const char *name)
{
E
Eric Blake 已提交
227 228
    if (VIR_RESIZE_N(caps->host.features, caps->host.nfeatures_max,
                     caps->host.nfeatures, 1) < 0)
229 230
        return -1;

231
    if (VIR_STRDUP(caps->host.features[caps->host.nfeatures], name) < 0)
232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248
        return -1;
    caps->host.nfeatures++;

    return 0;
}

/**
 * virCapabilitiesAddHostMigrateTransport:
 * @caps: capabilities to extend
 * @name: name of migration transport
 *
 * Registers a new domain migration transport URI
 */
int
virCapabilitiesAddHostMigrateTransport(virCapsPtr caps,
                                       const char *name)
{
E
Eric Blake 已提交
249 250
    if (VIR_RESIZE_N(caps->host.migrateTrans, caps->host.nmigrateTrans_max,
                     caps->host.nmigrateTrans, 1) < 0)
251 252
        return -1;

253
    if (VIR_STRDUP(caps->host.migrateTrans[caps->host.nmigrateTrans], name) < 0)
254 255 256 257 258 259 260 261 262 263 264 265
        return -1;
    caps->host.nmigrateTrans++;

    return 0;
}


/**
 * virCapabilitiesAddHostNUMACell:
 * @caps: capabilities to extend
 * @num: ID number of NUMA cell
 * @ncpus: number of CPUs in cell
266
 * @cpus: array of CPU definition structures, the pointer is stolen
267 268 269 270 271 272 273 274
 *
 * Registers a new NUMA cell for a host, passing in a
 * array of CPU IDs belonging to the cell
 */
int
virCapabilitiesAddHostNUMACell(virCapsPtr caps,
                               int num,
                               int ncpus,
275
                               unsigned long long mem,
276
                               virCapsHostNUMACellCPUPtr cpus)
277
{
278
    virCapsHostNUMACellPtr cell;
279

E
Eric Blake 已提交
280 281
    if (VIR_RESIZE_N(caps->host.numaCell, caps->host.nnumaCell_max,
                     caps->host.nnumaCell, 1) < 0)
282 283
        return -1;

284
    if (VIR_ALLOC(cell) < 0)
285 286
        return -1;

287 288
    cell->ncpus = ncpus;
    cell->num = num;
289
    cell->mem = mem;
290
    cell->cpus = cpus;
291

E
Eric Blake 已提交
292
    caps->host.numaCell[caps->host.nnumaCell++] = cell;
293 294 295 296

    return 0;
}

297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317

/**
 * virCapabilitiesSetHostCPU:
 * @caps: capabilities to extend
 * @cpu: CPU definition
 *
 * Sets host CPU specification
 */
int
virCapabilitiesSetHostCPU(virCapsPtr caps,
                          virCPUDefPtr cpu)
{
    if (cpu == NULL)
        return -1;

    caps->host.cpu = cpu;

    return 0;
}


318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336
/**
 * virCapabilitiesAllocMachines:
 * @machines: machine variants for emulator ('pc', or 'isapc', etc)
 * @nmachines: number of machine variants for emulator
 *
 * Allocate a table of virCapsGuestMachinePtr from the supplied table
 * of machine names.
 */
virCapsGuestMachinePtr *
virCapabilitiesAllocMachines(const char *const *names, int nnames)
{
    virCapsGuestMachinePtr *machines;
    int i;

    if (VIR_ALLOC_N(machines, nnames) < 0)
        return NULL;

    for (i = 0; i < nnames; i++) {
        if (VIR_ALLOC(machines[i]) < 0 ||
337
            VIR_STRDUP(machines[i]->name, names[i]) < 0) {
338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364
            virCapabilitiesFreeMachines(machines, nnames);
            return NULL;
        }
    }

    return machines;
}

/**
 * virCapabilitiesFreeMachines:
 * @machines: table of vircapsGuestMachinePtr
 *
 * Free a table of virCapsGuestMachinePtr
 */
void
virCapabilitiesFreeMachines(virCapsGuestMachinePtr *machines,
                            int nmachines)
{
    int i;
    if (!machines)
        return;
    for (i = 0; i < nmachines && machines[i]; i++) {
        virCapabilitiesFreeGuestMachine(machines[i]);
        machines[i] = NULL;
    }
    VIR_FREE(machines);
}
365 366 367 368 369

/**
 * virCapabilitiesAddGuest:
 * @caps: capabilities to extend
 * @ostype: guest operating system type ('hvm' or 'xen')
370
 * @arch: guest CPU architecture
371 372 373 374 375 376 377 378 379 380 381 382 383
 * @wordsize: number of bits in CPU word
 * @emulator: path to default device emulator for arch/ostype
 * @loader: path to default BIOS loader for arch/ostype
 * @nmachines: number of machine variants for emulator
 * @machines: machine variants for emulator ('pc', or 'isapc', etc)
 *
 * Registers a new guest operating system. This should be
 * followed by registration of at least one domain for
 * running the guest
 */
virCapsGuestPtr
virCapabilitiesAddGuest(virCapsPtr caps,
                        const char *ostype,
384
                        virArch arch,
385 386 387
                        const char *emulator,
                        const char *loader,
                        int nmachines,
388
                        virCapsGuestMachinePtr *machines)
389
{
390
    virCapsGuestPtr guest;
391

392
    if (VIR_ALLOC(guest) < 0)
393
        goto error;
394

395 396
    if (VIR_STRDUP(guest->ostype, ostype) < 0)
        goto error;
397

398 399
    guest->arch.id = arch;
    guest->arch.wordsize = virArchGetWordSize(arch);
400

401 402 403
    if (VIR_STRDUP(guest->arch.defaultInfo.emulator, emulator) < 0 ||
        VIR_STRDUP(guest->arch.defaultInfo.loader, loader) < 0)
        goto error;
404

E
Eric Blake 已提交
405 406
    if (VIR_RESIZE_N(caps->guests, caps->nguests_max,
                     caps->nguests, 1) < 0)
407
        goto error;
E
Eric Blake 已提交
408
    caps->guests[caps->nguests++] = guest;
409

D
Daniel P. Berrange 已提交
410 411 412 413 414
    if (nmachines) {
        guest->arch.defaultInfo.nmachines = nmachines;
        guest->arch.defaultInfo.machines = machines;
    }

415 416
    return guest;

417
error:
418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440
    virCapabilitiesFreeGuest(guest);
    return NULL;
}


/**
 * virCapabilitiesAddGuestDomain:
 * @guest: guest to support
 * @hvtype: hypervisor type ('xen', 'qemu', 'kvm')
 * @emulator: specialized device emulator for domain
 * @loader: specialized BIOS loader for domain
 * @nmachines: number of machine variants for emulator
 * @machines: specialized machine variants for emulator
 *
 * Registers a virtual domain capable of running a
 * guest operating system
 */
virCapsGuestDomainPtr
virCapabilitiesAddGuestDomain(virCapsGuestPtr guest,
                              const char *hvtype,
                              const char *emulator,
                              const char *loader,
                              int nmachines,
441
                              virCapsGuestMachinePtr *machines)
442
{
443
    virCapsGuestDomainPtr dom;
444

445
    if (VIR_ALLOC(dom) < 0)
446
        goto error;
447

448 449 450 451
    if (VIR_STRDUP(dom->type, hvtype) < 0 ||
        VIR_STRDUP(dom->info.emulator, emulator) < 0 ||
        VIR_STRDUP(dom->info.loader, loader) < 0)
        goto error;
452

E
Eric Blake 已提交
453 454
    if (VIR_RESIZE_N(guest->arch.domains, guest->arch.ndomains_max,
                     guest->arch.ndomains, 1) < 0)
455
        goto error;
456 457 458
    guest->arch.domains[guest->arch.ndomains] = dom;
    guest->arch.ndomains++;

D
Daniel P. Berrange 已提交
459 460 461 462
    if (nmachines) {
        dom->info.nmachines = nmachines;
        dom->info.machines = machines;
    }
463 464 465

    return dom;

466
error:
467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486
    virCapabilitiesFreeGuestDomain(dom);
    return NULL;
}


/**
 * virCapabilitiesAddGuestFeature:
 * @guest: guest to associate feature with
 * @name: name of feature ('pae', 'acpi', 'apic')
 * @defaultOn: non-zero if it defaults to on
 * @toggle: non-zero if its state can be toggled
 *
 * Registers a feature for a guest domain
 */
virCapsGuestFeaturePtr
virCapabilitiesAddGuestFeature(virCapsGuestPtr guest,
                               const char *name,
                               int defaultOn,
                               int toggle)
{
487
    virCapsGuestFeaturePtr feature;
488

489
    if (VIR_ALLOC(feature) < 0)
490 491
        goto no_memory;

492
    if (VIR_STRDUP(feature->name, name) < 0)
493 494 495 496
        goto no_memory;
    feature->defaultOn = defaultOn;
    feature->toggle = toggle;

E
Eric Blake 已提交
497 498
    if (VIR_RESIZE_N(guest->features, guest->nfeatures_max,
                     guest->nfeatures, 1) < 0)
499
        goto no_memory;
E
Eric Blake 已提交
500
    guest->features[guest->nfeatures++] = feature;
501 502 503 504 505 506 507 508

    return feature;

 no_memory:
    virCapabilitiesFreeGuestFeature(feature);
    return NULL;
}

509 510 511
/**
 * virCapabilitiesSupportsGuestArch:
 * @caps: capabilities to query
512
 * @arch: Architecture to search for
513 514 515 516 517 518
 *
 * Returns non-zero if the capabilities support the
 * requested architecture
 */
extern int
virCapabilitiesSupportsGuestArch(virCapsPtr caps,
519
                                 virArch arch)
520 521
{
    int i;
522
    for (i = 0; i < caps->nguests; i++) {
523
        if (caps->guests[i]->arch.id == arch)
524 525 526 527 528
            return 1;
    }
    return 0;
}

529 530 531 532 533 534 535 536 537 538 539 540 541 542

/**
 * virCapabilitiesSupportsGuestOSType:
 * @caps: capabilities to query
 * @ostype: OS type to search for (eg 'hvm', 'xen')
 *
 * Returns non-zero if the capabilities support the
 * requested operating system type
 */
extern int
virCapabilitiesSupportsGuestOSType(virCapsPtr caps,
                                   const char *ostype)
{
    int i;
543
    for (i = 0; i < caps->nguests; i++) {
544 545 546 547 548 549 550
        if (STREQ(caps->guests[i]->ostype, ostype))
            return 1;
    }
    return 0;
}


551
/**
552
 * virCapabilitiesSupportsGuestOSTypeArch:
553 554
 * @caps: capabilities to query
 * @ostype: OS type to search for (eg 'hvm', 'xen')
555
 * @arch: Architecture to search for
556 557 558 559 560
 *
 * Returns non-zero if the capabilities support the
 * requested operating system type
 */
extern int
561 562
virCapabilitiesSupportsGuestOSTypeArch(virCapsPtr caps,
                                       const char *ostype,
563
                                       virArch arch)
564 565
{
    int i;
566
    for (i = 0; i < caps->nguests; i++) {
567
        if (STREQ(caps->guests[i]->ostype, ostype) &&
568
            caps->guests[i]->arch.id == arch)
569 570 571 572 573 574
            return 1;
    }
    return 0;
}


575 576 577 578 579 580 581 582
/**
 * virCapabilitiesDefaultGuestArch:
 * @caps: capabilities to query
 * @ostype: OS type to search for
 *
 * Returns the first architecture able to run the
 * requested operating system type
 */
583
extern virArch
584
virCapabilitiesDefaultGuestArch(virCapsPtr caps,
585 586
                                const char *ostype,
                                const char *domain)
587
{
588
    int i, j;
589 590

    /* First try to find one matching host arch */
591
    for (i = 0; i < caps->nguests; i++) {
592
        if (STREQ(caps->guests[i]->ostype, ostype)) {
593
            for (j = 0; j < caps->guests[i]->arch.ndomains; j++) {
594 595 596
                if (STREQ(caps->guests[i]->arch.domains[j]->type, domain) &&
                    caps->guests[i]->arch.id == caps->host.arch)
                    return caps->guests[i]->arch.id;
597 598
            }
        }
599
    }
600 601

    /* Otherwise find the first match */
602
    for (i = 0; i < caps->nguests; i++) {
603
        if (STREQ(caps->guests[i]->ostype, ostype)) {
604
            for (j = 0; j < caps->guests[i]->arch.ndomains; j++) {
605 606 607 608 609 610 611
                if (STREQ(caps->guests[i]->arch.domains[j]->type, domain))
                    return caps->guests[i]->arch.id;
            }
        }
    }

    return VIR_ARCH_NONE;
612 613 614 615 616 617 618
}

/**
 * virCapabilitiesDefaultGuestMachine:
 * @caps: capabilities to query
 * @ostype: OS type to search for
 * @arch: architecture to search for
619
 * @domain: domain type to search for
620 621
 *
 * Returns the first machine variant associated with
622 623
 * the requested operating system type, architecture
 * and domain type
624 625 626 627
 */
extern const char *
virCapabilitiesDefaultGuestMachine(virCapsPtr caps,
                                   const char *ostype,
628
                                   virArch arch,
629
                                   const char *domain)
630 631
{
    int i;
632

633
    for (i = 0; i < caps->nguests; i++) {
634 635 636
        virCapsGuestPtr guest = caps->guests[i];
        int j;

637 638
        if (!STREQ(guest->ostype, ostype) ||
            guest->arch.id != arch)
639 640 641
            continue;

        for (j = 0; j < guest->arch.ndomains; j++) {
642
            virCapsGuestDomainPtr dom = guest->arch.domains[j];
643 644 645 646 647 648 649 650 651 652 653

            if (!STREQ(dom->type, domain))
                continue;

            if (!dom->info.nmachines)
                break;

            return dom->info.machines[0]->name;
        }

        if (guest->arch.defaultInfo.nmachines)
654
            return caps->guests[i]->arch.defaultInfo.machines[0]->name;
655
    }
656

657 658 659 660
    return NULL;
}

/**
661
 * virCapabilitiesDefaultGuestEmulator:
662 663 664 665 666 667 668 669 670 671 672 673
 * @caps: capabilities to query
 * @ostype: OS type to search for ('xen', 'hvm')
 * @arch: architecture to search for
 * @domain: domain type ('xen', 'qemu', 'kvm')
 *
 * Returns the first emulator path associated with
 * the requested operating system type, architecture
 * and domain type
 */
extern const char *
virCapabilitiesDefaultGuestEmulator(virCapsPtr caps,
                                    const char *ostype,
674
                                    virArch arch,
675 676 677
                                    const char *domain)
{
    int i, j;
678
    for (i = 0; i < caps->nguests; i++) {
679 680
        char *emulator;
        if (STREQ(caps->guests[i]->ostype, ostype) &&
681
            caps->guests[i]->arch.id == arch) {
682
            emulator = caps->guests[i]->arch.defaultInfo.emulator;
683
            for (j = 0; j < caps->guests[i]->arch.ndomains; j++) {
684 685 686 687 688 689 690 691 692 693 694
                if (STREQ(caps->guests[i]->arch.domains[j]->type, domain)) {
                    if (caps->guests[i]->arch.domains[j]->info.emulator)
                        emulator = caps->guests[i]->arch.domains[j]->info.emulator;
                }
            }
            return emulator;
        }
    }
    return NULL;
}

695
static int
696 697 698 699 700 701
virCapabilitiesFormatNUMATopology(virBufferPtr xml,
                                  size_t ncells,
                                  virCapsHostNUMACellPtr *cells)
{
    int i;
    int j;
702
    char *siblings;
703 704 705 706 707

    virBufferAddLit(xml, "    <topology>\n");
    virBufferAsprintf(xml, "      <cells num='%zu'>\n", ncells);
    for (i = 0; i < ncells; i++) {
        virBufferAsprintf(xml, "        <cell id='%d'>\n", cells[i]->num);
708 709 710 711 712 713 714

        /* Print out the numacell memory total if it is available */
        if (cells[i]->mem)
            virBufferAsprintf(xml,
                              "          <memory unit='KiB'>%llu</memory>\n",
                              cells[i]->mem);

715
        virBufferAsprintf(xml, "          <cpus num='%d'>\n", cells[i]->ncpus);
716 717
        for (j = 0; j < cells[i]->ncpus; j++) {
            virBufferAsprintf(xml, "            <cpu id='%d'",
718
                              cells[i]->cpus[j].id);
719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735

            if (cells[i]->cpus[j].siblings) {
                if (!(siblings = virBitmapFormat(cells[i]->cpus[j].siblings))) {
                    virReportOOMError();
                    return -1;
                }

                virBufferAsprintf(xml,
                                  " socket_id='%d' core_id='%d' siblings='%s'",
                                  cells[i]->cpus[j].socket_id,
                                  cells[i]->cpus[j].core_id,
                                  siblings);
                VIR_FREE(siblings);
            }
            virBufferAddLit(xml, "/>\n");
        }

736 737 738 739 740
        virBufferAddLit(xml, "          </cpus>\n");
        virBufferAddLit(xml, "        </cell>\n");
    }
    virBufferAddLit(xml, "      </cells>\n");
    virBufferAddLit(xml, "    </topology>\n");
741 742

    return 0;
743
}
744 745 746 747 748 749 750 751 752 753 754 755

/**
 * virCapabilitiesFormatXML:
 * @caps: capabilities to format
 *
 * Convert the capabilities object into an XML representation
 *
 * Returns the XML document as a string
 */
char *
virCapabilitiesFormatXML(virCapsPtr caps)
{
756
    virBuffer xml = VIR_BUFFER_INITIALIZER;
757
    int i, j, k;
758
    char host_uuid[VIR_UUID_STRING_BUFLEN];
759

760 761
    virBufferAddLit(&xml, "<capabilities>\n\n");
    virBufferAddLit(&xml, "  <host>\n");
762 763
    if (virUUIDIsValid(caps->host.host_uuid)) {
        virUUIDFormat(caps->host.host_uuid, host_uuid);
764
        virBufferAsprintf(&xml,"    <uuid>%s</uuid>\n", host_uuid);
765
    }
766
    virBufferAddLit(&xml, "    <cpu>\n");
767 768 769
    if (caps->host.arch)
        virBufferAsprintf(&xml, "      <arch>%s</arch>\n",
                          virArchToString(caps->host.arch));
770 771

    if (caps->host.nfeatures) {
772
        virBufferAddLit(&xml, "      <features>\n");
773
        for (i = 0; i < caps->host.nfeatures; i++) {
774
            virBufferAsprintf(&xml, "        <%s/>\n",
775
                              caps->host.features[i]);
776
        }
777
        virBufferAddLit(&xml, "      </features>\n");
778
    }
779

780
    virBufferAdjustIndent(&xml, 6);
781
    virCPUDefFormatBuf(&xml, caps->host.cpu, 0);
782
    virBufferAdjustIndent(&xml, -6);
783

784
    virBufferAddLit(&xml, "    </cpu>\n");
785

786 787 788 789 790 791 792 793 794 795
    /* The PM query was successful. */
    if (caps->host.powerMgmt) {
        /* The host supports some PM features. */
        unsigned int pm = caps->host.powerMgmt;
        virBufferAddLit(&xml, "    <power_management>\n");
        while (pm) {
            int bit = ffs(pm) - 1;
            virBufferAsprintf(&xml, "      <%s/>\n",
                              virCapsHostPMTargetTypeToString(bit));
            pm &= ~(1U << bit);
796
        }
797 798 799 800
        virBufferAddLit(&xml, "    </power_management>\n");
    } else {
        /* The host does not support any PM feature. */
        virBufferAddLit(&xml, "    <power_management/>\n");
801 802
    }

803
    if (caps->host.offlineMigrate) {
804 805 806
        virBufferAddLit(&xml, "    <migration_features>\n");
        if (caps->host.liveMigrate)
            virBufferAddLit(&xml, "      <live/>\n");
807
        if (caps->host.nmigrateTrans) {
808
            virBufferAddLit(&xml, "      <uri_transports>\n");
809
            for (i = 0; i < caps->host.nmigrateTrans; i++) {
810
                virBufferAsprintf(&xml, "        <uri_transport>%s</uri_transport>\n",
811
                                      caps->host.migrateTrans[i]);
812
            }
813
            virBufferAddLit(&xml, "      </uri_transports>\n");
814
        }
815
        virBufferAddLit(&xml, "    </migration_features>\n");
816 817
    }

818
    if (caps->host.nnumaCell &&
819
        virCapabilitiesFormatNUMATopology(&xml, caps->host.nnumaCell,
820 821
                                          caps->host.numaCell) < 0)
        return NULL;
822

823
    for (i = 0; i < caps->host.nsecModels; i++) {
824
        virBufferAddLit(&xml, "    <secmodel>\n");
825
        virBufferAsprintf(&xml, "      <model>%s</model>\n",
826
                          caps->host.secModels[i].model);
827
        virBufferAsprintf(&xml, "      <doi>%s</doi>\n",
828
                          caps->host.secModels[i].doi);
829 830 831
        virBufferAddLit(&xml, "    </secmodel>\n");
    }

832
    virBufferAddLit(&xml, "  </host>\n\n");
833 834


835
    for (i = 0; i < caps->nguests; i++) {
836
        virBufferAddLit(&xml, "  <guest>\n");
837
        virBufferAsprintf(&xml, "    <os_type>%s</os_type>\n",
838
                          caps->guests[i]->ostype);
839 840 841
        if (caps->guests[i]->arch.id)
            virBufferAsprintf(&xml, "    <arch name='%s'>\n",
                              virArchToString(caps->guests[i]->arch.id));
842
        virBufferAsprintf(&xml, "      <wordsize>%d</wordsize>\n",
843 844
                          caps->guests[i]->arch.wordsize);
        if (caps->guests[i]->arch.defaultInfo.emulator)
845
            virBufferAsprintf(&xml, "      <emulator>%s</emulator>\n",
846 847
                              caps->guests[i]->arch.defaultInfo.emulator);
            if (caps->guests[i]->arch.defaultInfo.loader)
848
                virBufferAsprintf(&xml, "      <loader>%s</loader>\n",
849
                                  caps->guests[i]->arch.defaultInfo.loader);
850

851
        for (j = 0; j < caps->guests[i]->arch.defaultInfo.nmachines; j++) {
852 853 854
            virCapsGuestMachinePtr machine = caps->guests[i]->arch.defaultInfo.machines[j];
            virBufferAddLit(&xml, "      <machine");
            if (machine->canonical)
855 856
                virBufferAsprintf(&xml, " canonical='%s'", machine->canonical);
            virBufferAsprintf(&xml, ">%s</machine>\n", machine->name);
857 858
        }

859
        for (j = 0; j < caps->guests[i]->arch.ndomains; j++) {
860
            virBufferAsprintf(&xml, "      <domain type='%s'>\n",
861 862
                                  caps->guests[i]->arch.domains[j]->type);
            if (caps->guests[i]->arch.domains[j]->info.emulator)
863
                virBufferAsprintf(&xml, "        <emulator>%s</emulator>\n",
864 865
                                  caps->guests[i]->arch.domains[j]->info.emulator);
            if (caps->guests[i]->arch.domains[j]->info.loader)
866
                virBufferAsprintf(&xml, "        <loader>%s</loader>\n",
867
                                  caps->guests[i]->arch.domains[j]->info.loader);
868

869
            for (k = 0; k < caps->guests[i]->arch.domains[j]->info.nmachines; k++) {
870
                virCapsGuestMachinePtr machine = caps->guests[i]->arch.domains[j]->info.machines[k];
871
                virBufferAddLit(&xml, "        <machine");
872
                if (machine->canonical)
873 874
                    virBufferAsprintf(&xml, " canonical='%s'", machine->canonical);
                virBufferAsprintf(&xml, ">%s</machine>\n", machine->name);
875
            }
876
            virBufferAddLit(&xml, "      </domain>\n");
877 878
        }

879
        virBufferAddLit(&xml, "    </arch>\n");
880 881

        if (caps->guests[i]->nfeatures) {
882
            virBufferAddLit(&xml, "    <features>\n");
883

884
            for (j = 0; j < caps->guests[i]->nfeatures; j++) {
885 886
                if (STREQ(caps->guests[i]->features[j]->name, "pae") ||
                    STREQ(caps->guests[i]->features[j]->name, "nonpae") ||
887
                    STREQ(caps->guests[i]->features[j]->name, "ia64_be") ||
888 889
                    STREQ(caps->guests[i]->features[j]->name, "cpuselection") ||
                    STREQ(caps->guests[i]->features[j]->name, "deviceboot")) {
890
                    virBufferAsprintf(&xml, "      <%s/>\n",
891
                                      caps->guests[i]->features[j]->name);
892
                } else {
893
                    virBufferAsprintf(&xml, "      <%s default='%s' toggle='%s'/>\n",
894 895 896
                                      caps->guests[i]->features[j]->name,
                                      caps->guests[i]->features[j]->defaultOn ? "on" : "off",
                                      caps->guests[i]->features[j]->toggle ? "yes" : "no");
897 898 899
                }
            }

900
            virBufferAddLit(&xml, "    </features>\n");
901 902
        }

903
        virBufferAddLit(&xml, "  </guest>\n\n");
904 905
    }

906
    virBufferAddLit(&xml, "</capabilities>\n");
907

908 909
    if (virBufferError(&xml)) {
        virBufferFreeAndReset(&xml);
910
        return NULL;
911
    }
912

913
    return virBufferContentAndReset(&xml);
914
}