capabilities.c 26.1 KB
Newer Older
1 2 3
/*
 * capabilities.c: hypervisor capabilities
 *
4
 * Copyright (C) 2006-2008, 2010-2011 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 "virutil.h"
32
#include "viruuid.h"
33
#include "cpu_conf.h"
34
#include "virerror.h"
35 36 37 38


#define VIR_FROM_THIS VIR_FROM_CAPABILITIES

39 40
VIR_ENUM_DECL(virCapsHostPMTarget)
VIR_ENUM_IMPL(virCapsHostPMTarget, VIR_NODE_SUSPEND_TARGET_LAST,
41
              "suspend_mem", "suspend_disk", "suspend_hybrid");
42 43 44

/**
 * virCapabilitiesNew:
45
 * @hostarch: host machine architecture
46 47
 * @offlineMigrate: non-zero if offline migration is available
 * @liveMigrate: non-zero if live migration is available
48
 *
49 50 51
 * Allocate a new capabilities object
 */
virCapsPtr
52
virCapabilitiesNew(virArch hostarch,
53 54 55 56 57
                   int offlineMigrate,
                   int liveMigrate)
{
    virCapsPtr caps;

58
    if (VIR_ALLOC(caps) < 0)
59
        return NULL;
60

61
    caps->host.arch = hostarch;
62 63 64 65 66 67
    caps->host.offlineMigrate = offlineMigrate;
    caps->host.liveMigrate = liveMigrate;

    return caps;
}

68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
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;
    }
}

83 84 85
static void
virCapabilitiesFreeHostNUMACell(virCapsHostNUMACellPtr cell)
{
86 87 88
    if (cell == NULL)
        return;

89 90
    virCapabilitiesClearHostNUMACellCPUTopology(cell->cpus, cell->ncpus);

91 92
    VIR_FREE(cell->cpus);
    VIR_FREE(cell);
93 94
}

95 96 97 98 99 100 101 102 103 104
static void
virCapabilitiesFreeGuestMachine(virCapsGuestMachinePtr machine)
{
    if (machine == NULL)
        return;
    VIR_FREE(machine->name);
    VIR_FREE(machine->canonical);
    VIR_FREE(machine);
}

105 106 107 108
static void
virCapabilitiesFreeGuestDomain(virCapsGuestDomainPtr dom)
{
    int i;
109 110 111
    if (dom == NULL)
        return;

112 113
    VIR_FREE(dom->info.emulator);
    VIR_FREE(dom->info.loader);
114
    for (i = 0 ; i < dom->info.nmachines ; i++)
115
        virCapabilitiesFreeGuestMachine(dom->info.machines[i]);
116 117
    VIR_FREE(dom->info.machines);
    VIR_FREE(dom->type);
118

119
    VIR_FREE(dom);
120 121 122 123 124
}

static void
virCapabilitiesFreeGuestFeature(virCapsGuestFeaturePtr feature)
{
125 126
    if (feature == NULL)
        return;
127 128
    VIR_FREE(feature->name);
    VIR_FREE(feature);
129 130 131 132 133 134
}

static void
virCapabilitiesFreeGuest(virCapsGuestPtr guest)
{
    int i;
135 136 137
    if (guest == NULL)
        return;

138
    VIR_FREE(guest->ostype);
139

140 141
    VIR_FREE(guest->arch.defaultInfo.emulator);
    VIR_FREE(guest->arch.defaultInfo.loader);
142
    for (i = 0 ; i < guest->arch.defaultInfo.nmachines ; i++)
143
        virCapabilitiesFreeGuestMachine(guest->arch.defaultInfo.machines[i]);
144
    VIR_FREE(guest->arch.defaultInfo.machines);
145 146 147

    for (i = 0 ; i < guest->arch.ndomains ; i++)
        virCapabilitiesFreeGuestDomain(guest->arch.domains[i]);
148
    VIR_FREE(guest->arch.domains);
149 150 151

    for (i = 0 ; i < guest->nfeatures ; i++)
        virCapabilitiesFreeGuestFeature(guest->features[i]);
152
    VIR_FREE(guest->features);
153

154
    VIR_FREE(guest);
155 156
}

157 158 159 160 161 162 163 164
void
virCapabilitiesFreeNUMAInfo(virCapsPtr caps)
{
    int i;

    for (i = 0 ; i < caps->host.nnumaCell ; i++)
        virCapabilitiesFreeHostNUMACell(caps->host.numaCell[i]);
    VIR_FREE(caps->host.numaCell);
165
    caps->host.nnumaCell = 0;
166
}
167 168 169 170 171 172 173 174 175 176

/**
 * virCapabilitiesFree:
 * @caps: object to free
 *
 * Free all memory associated with capabilities
 */
void
virCapabilitiesFree(virCapsPtr caps) {
    int i;
177 178
    if (caps == NULL)
        return;
179 180 181

    for (i = 0 ; i < caps->nguests ; i++)
        virCapabilitiesFreeGuest(caps->guests[i]);
182
    VIR_FREE(caps->guests);
183 184

    for (i = 0 ; i < caps->host.nfeatures ; i++)
185 186
        VIR_FREE(caps->host.features[i]);
    VIR_FREE(caps->host.features);
187 188

    virCapabilitiesFreeNUMAInfo(caps);
189

190
    for (i = 0 ; i < caps->host.nmigrateTrans ; i++)
191 192
        VIR_FREE(caps->host.migrateTrans[i]);
    VIR_FREE(caps->host.migrateTrans);
193

194 195 196 197 198 199
    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);

200 201
    virCPUDefFree(caps->host.cpu);

202
    VIR_FREE(caps);
203 204 205 206 207 208 209 210 211 212 213 214 215 216
}


/**
 * 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 已提交
217 218
    if (VIR_RESIZE_N(caps->host.features, caps->host.nfeatures_max,
                     caps->host.nfeatures, 1) < 0)
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
        return -1;

    if ((caps->host.features[caps->host.nfeatures] = strdup(name)) == NULL)
        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 已提交
239 240
    if (VIR_RESIZE_N(caps->host.migrateTrans, caps->host.nmigrateTrans_max,
                     caps->host.nmigrateTrans, 1) < 0)
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
        return -1;

    if ((caps->host.migrateTrans[caps->host.nmigrateTrans] = strdup(name)) == NULL)
        return -1;
    caps->host.nmigrateTrans++;

    return 0;
}


/**
 * virCapabilitiesAddHostNUMACell:
 * @caps: capabilities to extend
 * @num: ID number of NUMA cell
 * @ncpus: number of CPUs in cell
256
 * @cpus: array of CPU definition structures, the pointer is stolen
257 258 259 260 261 262 263 264
 *
 * 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,
265
                               virCapsHostNUMACellCPUPtr cpus)
266
{
267
    virCapsHostNUMACellPtr cell;
268

E
Eric Blake 已提交
269 270
    if (VIR_RESIZE_N(caps->host.numaCell, caps->host.nnumaCell_max,
                     caps->host.nnumaCell, 1) < 0)
271 272
        return -1;

273
    if (VIR_ALLOC(cell) < 0)
274 275
        return -1;

276 277
    cell->ncpus = ncpus;
    cell->num = num;
278
    cell->cpus = cpus;
279

E
Eric Blake 已提交
280
    caps->host.numaCell[caps->host.nnumaCell++] = cell;
281 282 283 284

    return 0;
}

285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305

/**
 * 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;
}


306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 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
/**
 * 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 ||
            !(machines[i]->name = strdup(names[i]))) {
            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);
}
353 354 355 356 357

/**
 * virCapabilitiesAddGuest:
 * @caps: capabilities to extend
 * @ostype: guest operating system type ('hvm' or 'xen')
358
 * @arch: guest CPU architecture
359 360 361 362 363 364 365 366 367 368 369 370 371
 * @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,
372
                        virArch arch,
373 374 375
                        const char *emulator,
                        const char *loader,
                        int nmachines,
376
                        virCapsGuestMachinePtr *machines)
377
{
378
    virCapsGuestPtr guest;
379

380
    if (VIR_ALLOC(guest) < 0)
381 382 383 384 385
        goto no_memory;

    if ((guest->ostype = strdup(ostype)) == NULL)
        goto no_memory;

386 387
    guest->arch.id = arch;
    guest->arch.wordsize = virArchGetWordSize(arch);
388 389 390 391 392 393 394 395

    if (emulator &&
        (guest->arch.defaultInfo.emulator = strdup(emulator)) == NULL)
        goto no_memory;
    if (loader &&
        (guest->arch.defaultInfo.loader = strdup(loader)) == NULL)
        goto no_memory;

E
Eric Blake 已提交
396 397
    if (VIR_RESIZE_N(caps->guests, caps->nguests_max,
                     caps->nguests, 1) < 0)
398
        goto no_memory;
E
Eric Blake 已提交
399
    caps->guests[caps->nguests++] = guest;
400

D
Daniel P. Berrange 已提交
401 402 403 404 405
    if (nmachines) {
        guest->arch.defaultInfo.nmachines = nmachines;
        guest->arch.defaultInfo.machines = machines;
    }

406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431
    return guest;

 no_memory:
    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,
432
                              virCapsGuestMachinePtr *machines)
433
{
434
    virCapsGuestDomainPtr dom;
435

436
    if (VIR_ALLOC(dom) < 0)
437 438 439 440 441 442 443 444 445 446 447 448
        goto no_memory;

    if ((dom->type = strdup(hvtype)) == NULL)
        goto no_memory;

    if (emulator &&
        (dom->info.emulator = strdup(emulator)) == NULL)
        goto no_memory;
    if (loader &&
        (dom->info.loader = strdup(loader)) == NULL)
        goto no_memory;

E
Eric Blake 已提交
449 450
    if (VIR_RESIZE_N(guest->arch.domains, guest->arch.ndomains_max,
                     guest->arch.ndomains, 1) < 0)
451 452 453 454
        goto no_memory;
    guest->arch.domains[guest->arch.ndomains] = dom;
    guest->arch.ndomains++;

D
Daniel P. Berrange 已提交
455 456 457 458
    if (nmachines) {
        dom->info.nmachines = nmachines;
        dom->info.machines = machines;
    }
459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482

    return dom;

 no_memory:
    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)
{
483
    virCapsGuestFeaturePtr feature;
484

485
    if (VIR_ALLOC(feature) < 0)
486 487 488 489 490 491 492
        goto no_memory;

    if ((feature->name = strdup(name)) == NULL)
        goto no_memory;
    feature->defaultOn = defaultOn;
    feature->toggle = toggle;

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

    return feature;

 no_memory:
    virCapabilitiesFreeGuestFeature(feature);
    return NULL;
}

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

525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546

/**
 * 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;
    for (i = 0 ; i < caps->nguests ; i++) {
        if (STREQ(caps->guests[i]->ostype, ostype))
            return 1;
    }
    return 0;
}


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


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

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

    /* Otherwise find the first match */
    for (i = 0 ; i < caps->nguests ; i++) {
        if (STREQ(caps->guests[i]->ostype, ostype)) {
            for (j = 0 ; j < caps->guests[i]->arch.ndomains ; j++) {
                if (STREQ(caps->guests[i]->arch.domains[j]->type, domain))
                    return caps->guests[i]->arch.id;
            }
        }
    }

    return VIR_ARCH_NONE;
608 609 610 611 612 613 614
}

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

629
    for (i = 0 ; i < caps->nguests ; i++) {
630 631 632
        virCapsGuestPtr guest = caps->guests[i];
        int j;

633 634
        if (!STREQ(guest->ostype, ostype) ||
            guest->arch.id != arch)
635 636 637
            continue;

        for (j = 0; j < guest->arch.ndomains; j++) {
638
            virCapsGuestDomainPtr dom = guest->arch.domains[j];
639 640 641 642 643 644 645 646 647 648 649

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

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

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

        if (guest->arch.defaultInfo.nmachines)
650
            return caps->guests[i]->arch.defaultInfo.machines[0]->name;
651
    }
652

653 654 655 656
    return NULL;
}

/**
657
 * virCapabilitiesDefaultGuestEmulator:
658 659 660 661 662 663 664 665 666 667 668 669
 * @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,
670
                                    virArch arch,
671 672 673 674 675 676
                                    const char *domain)
{
    int i, j;
    for (i = 0 ; i < caps->nguests ; i++) {
        char *emulator;
        if (STREQ(caps->guests[i]->ostype, ostype) &&
677
            caps->guests[i]->arch.id == arch) {
678 679 680 681 682 683 684 685 686 687 688 689 690
            emulator = caps->guests[i]->arch.defaultInfo.emulator;
            for (j = 0 ; j < caps->guests[i]->arch.ndomains ; j++) {
                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;
}

691 692 693 694 695 696 697 698 699 700 701 702 703 704 705
static void
virCapabilitiesFormatNUMATopology(virBufferPtr xml,
                                  size_t ncells,
                                  virCapsHostNUMACellPtr *cells)
{
    int i;
    int j;

    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);
        virBufferAsprintf(xml, "          <cpus num='%d'>\n", cells[i]->ncpus);
        for (j = 0; j < cells[i]->ncpus; j++)
            virBufferAsprintf(xml, "            <cpu id='%d'/>\n",
706
                              cells[i]->cpus[j].id);
707 708 709 710 711 712
        virBufferAddLit(xml, "          </cpus>\n");
        virBufferAddLit(xml, "        </cell>\n");
    }
    virBufferAddLit(xml, "      </cells>\n");
    virBufferAddLit(xml, "    </topology>\n");
}
713 714 715 716 717 718 719 720 721 722 723 724

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

729 730
    virBufferAddLit(&xml, "<capabilities>\n\n");
    virBufferAddLit(&xml, "  <host>\n");
731 732
    if (virUUIDIsValid(caps->host.host_uuid)) {
        virUUIDFormat(caps->host.host_uuid, host_uuid);
733
        virBufferAsprintf(&xml,"    <uuid>%s</uuid>\n", host_uuid);
734
    }
735
    virBufferAddLit(&xml, "    <cpu>\n");
736 737 738
    if (caps->host.arch)
        virBufferAsprintf(&xml, "      <arch>%s</arch>\n",
                          virArchToString(caps->host.arch));
739 740

    if (caps->host.nfeatures) {
741
        virBufferAddLit(&xml, "      <features>\n");
742
        for (i = 0 ; i < caps->host.nfeatures ; i++) {
743
            virBufferAsprintf(&xml, "        <%s/>\n",
744
                              caps->host.features[i]);
745
        }
746
        virBufferAddLit(&xml, "      </features>\n");
747
    }
748

749
    virBufferAdjustIndent(&xml, 6);
750
    virCPUDefFormatBuf(&xml, caps->host.cpu, 0);
751
    virBufferAdjustIndent(&xml, -6);
752

753
    virBufferAddLit(&xml, "    </cpu>\n");
754

755 756 757 758 759 760 761 762 763 764
    /* 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);
765
        }
766 767 768 769
        virBufferAddLit(&xml, "    </power_management>\n");
    } else {
        /* The host does not support any PM feature. */
        virBufferAddLit(&xml, "    <power_management/>\n");
770 771
    }

772
    if (caps->host.offlineMigrate) {
773 774 775
        virBufferAddLit(&xml, "    <migration_features>\n");
        if (caps->host.liveMigrate)
            virBufferAddLit(&xml, "      <live/>\n");
776
        if (caps->host.nmigrateTrans) {
777
            virBufferAddLit(&xml, "      <uri_transports>\n");
778
            for (i = 0 ; i < caps->host.nmigrateTrans ; i++) {
779
                virBufferAsprintf(&xml, "        <uri_transport>%s</uri_transport>\n",
780
                                      caps->host.migrateTrans[i]);
781
            }
782
            virBufferAddLit(&xml, "      </uri_transports>\n");
783
        }
784
        virBufferAddLit(&xml, "    </migration_features>\n");
785 786
    }

787 788 789
    if (caps->host.nnumaCell)
        virCapabilitiesFormatNUMATopology(&xml, caps->host.nnumaCell,
                                          caps->host.numaCell);
790

791
    for (i = 0; i < caps->host.nsecModels; i++) {
792
        virBufferAddLit(&xml, "    <secmodel>\n");
793
        virBufferAsprintf(&xml, "      <model>%s</model>\n",
794
                          caps->host.secModels[i].model);
795
        virBufferAsprintf(&xml, "      <doi>%s</doi>\n",
796
                          caps->host.secModels[i].doi);
797 798 799
        virBufferAddLit(&xml, "    </secmodel>\n");
    }

800
    virBufferAddLit(&xml, "  </host>\n\n");
801 802 803


    for (i = 0 ; i < caps->nguests ; i++) {
804
        virBufferAddLit(&xml, "  <guest>\n");
805
        virBufferAsprintf(&xml, "    <os_type>%s</os_type>\n",
806
                          caps->guests[i]->ostype);
807 808 809
        if (caps->guests[i]->arch.id)
            virBufferAsprintf(&xml, "    <arch name='%s'>\n",
                              virArchToString(caps->guests[i]->arch.id));
810
        virBufferAsprintf(&xml, "      <wordsize>%d</wordsize>\n",
811 812
                          caps->guests[i]->arch.wordsize);
        if (caps->guests[i]->arch.defaultInfo.emulator)
813
            virBufferAsprintf(&xml, "      <emulator>%s</emulator>\n",
814 815
                              caps->guests[i]->arch.defaultInfo.emulator);
            if (caps->guests[i]->arch.defaultInfo.loader)
816
                virBufferAsprintf(&xml, "      <loader>%s</loader>\n",
817
                                  caps->guests[i]->arch.defaultInfo.loader);
818 819

        for (j = 0 ; j < caps->guests[i]->arch.defaultInfo.nmachines ; j++) {
820 821 822
            virCapsGuestMachinePtr machine = caps->guests[i]->arch.defaultInfo.machines[j];
            virBufferAddLit(&xml, "      <machine");
            if (machine->canonical)
823 824
                virBufferAsprintf(&xml, " canonical='%s'", machine->canonical);
            virBufferAsprintf(&xml, ">%s</machine>\n", machine->name);
825 826 827
        }

        for (j = 0 ; j < caps->guests[i]->arch.ndomains ; j++) {
828
            virBufferAsprintf(&xml, "      <domain type='%s'>\n",
829 830
                                  caps->guests[i]->arch.domains[j]->type);
            if (caps->guests[i]->arch.domains[j]->info.emulator)
831
                virBufferAsprintf(&xml, "        <emulator>%s</emulator>\n",
832 833
                                  caps->guests[i]->arch.domains[j]->info.emulator);
            if (caps->guests[i]->arch.domains[j]->info.loader)
834
                virBufferAsprintf(&xml, "        <loader>%s</loader>\n",
835
                                  caps->guests[i]->arch.domains[j]->info.loader);
836 837

            for (k = 0 ; k < caps->guests[i]->arch.domains[j]->info.nmachines ; k++) {
838
                virCapsGuestMachinePtr machine = caps->guests[i]->arch.domains[j]->info.machines[k];
839
                virBufferAddLit(&xml, "        <machine");
840
                if (machine->canonical)
841 842
                    virBufferAsprintf(&xml, " canonical='%s'", machine->canonical);
                virBufferAsprintf(&xml, ">%s</machine>\n", machine->name);
843
            }
844
            virBufferAddLit(&xml, "      </domain>\n");
845 846
        }

847
        virBufferAddLit(&xml, "    </arch>\n");
848 849

        if (caps->guests[i]->nfeatures) {
850
            virBufferAddLit(&xml, "    <features>\n");
851 852 853 854

            for (j = 0 ; j < caps->guests[i]->nfeatures ; j++) {
                if (STREQ(caps->guests[i]->features[j]->name, "pae") ||
                    STREQ(caps->guests[i]->features[j]->name, "nonpae") ||
855
                    STREQ(caps->guests[i]->features[j]->name, "ia64_be") ||
856 857
                    STREQ(caps->guests[i]->features[j]->name, "cpuselection") ||
                    STREQ(caps->guests[i]->features[j]->name, "deviceboot")) {
858
                    virBufferAsprintf(&xml, "      <%s/>\n",
859
                                      caps->guests[i]->features[j]->name);
860
                } else {
861
                    virBufferAsprintf(&xml, "      <%s default='%s' toggle='%s'/>\n",
862 863 864
                                      caps->guests[i]->features[j]->name,
                                      caps->guests[i]->features[j]->defaultOn ? "on" : "off",
                                      caps->guests[i]->features[j]->toggle ? "yes" : "no");
865 866 867
                }
            }

868
            virBufferAddLit(&xml, "    </features>\n");
869 870
        }

871
        virBufferAddLit(&xml, "  </guest>\n\n");
872 873
    }

874
    virBufferAddLit(&xml, "</capabilities>\n");
875

876 877
    if (virBufferError(&xml)) {
        virBufferFreeAndReset(&xml);
878
        return NULL;
879
    }
880

881
    return virBufferContentAndReset(&xml);
882
}
883 884 885

extern void
virCapabilitiesSetMacPrefix(virCapsPtr caps,
886
                            const unsigned char prefix[VIR_MAC_PREFIX_BUFLEN])
887 888 889 890 891 892
{
    memcpy(caps->macPrefix, prefix, sizeof(caps->macPrefix));
}

extern void
virCapabilitiesGenerateMac(virCapsPtr caps,
893
                           virMacAddrPtr mac)
894
{
895
    virMacAddrGenerate(caps->macPrefix, mac);
896
}
897 898 899 900 901 902 903 904 905 906

extern void
virCapabilitiesSetEmulatorRequired(virCapsPtr caps) {
    caps->emulatorRequired = 1;
}

extern unsigned int
virCapabilitiesIsEmulatorRequired(virCapsPtr caps) {
    return caps->emulatorRequired;
}