capabilities.c 26.7 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
static int
692 693 694 695 696 697
virCapabilitiesFormatNUMATopology(virBufferPtr xml,
                                  size_t ncells,
                                  virCapsHostNUMACellPtr *cells)
{
    int i;
    int j;
698
    char *siblings;
699 700 701 702 703 704

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

            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");
        }

725 726 727 728 729
        virBufferAddLit(xml, "          </cpus>\n");
        virBufferAddLit(xml, "        </cell>\n");
    }
    virBufferAddLit(xml, "      </cells>\n");
    virBufferAddLit(xml, "    </topology>\n");
730 731

    return 0;
732
}
733 734 735 736 737 738 739 740 741 742 743 744

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

749 750
    virBufferAddLit(&xml, "<capabilities>\n\n");
    virBufferAddLit(&xml, "  <host>\n");
751 752
    if (virUUIDIsValid(caps->host.host_uuid)) {
        virUUIDFormat(caps->host.host_uuid, host_uuid);
753
        virBufferAsprintf(&xml,"    <uuid>%s</uuid>\n", host_uuid);
754
    }
755
    virBufferAddLit(&xml, "    <cpu>\n");
756 757 758
    if (caps->host.arch)
        virBufferAsprintf(&xml, "      <arch>%s</arch>\n",
                          virArchToString(caps->host.arch));
759 760

    if (caps->host.nfeatures) {
761
        virBufferAddLit(&xml, "      <features>\n");
762
        for (i = 0 ; i < caps->host.nfeatures ; i++) {
763
            virBufferAsprintf(&xml, "        <%s/>\n",
764
                              caps->host.features[i]);
765
        }
766
        virBufferAddLit(&xml, "      </features>\n");
767
    }
768

769
    virBufferAdjustIndent(&xml, 6);
770
    virCPUDefFormatBuf(&xml, caps->host.cpu, 0);
771
    virBufferAdjustIndent(&xml, -6);
772

773
    virBufferAddLit(&xml, "    </cpu>\n");
774

775 776 777 778 779 780 781 782 783 784
    /* 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);
785
        }
786 787 788 789
        virBufferAddLit(&xml, "    </power_management>\n");
    } else {
        /* The host does not support any PM feature. */
        virBufferAddLit(&xml, "    <power_management/>\n");
790 791
    }

792
    if (caps->host.offlineMigrate) {
793 794 795
        virBufferAddLit(&xml, "    <migration_features>\n");
        if (caps->host.liveMigrate)
            virBufferAddLit(&xml, "      <live/>\n");
796
        if (caps->host.nmigrateTrans) {
797
            virBufferAddLit(&xml, "      <uri_transports>\n");
798
            for (i = 0 ; i < caps->host.nmigrateTrans ; i++) {
799
                virBufferAsprintf(&xml, "        <uri_transport>%s</uri_transport>\n",
800
                                      caps->host.migrateTrans[i]);
801
            }
802
            virBufferAddLit(&xml, "      </uri_transports>\n");
803
        }
804
        virBufferAddLit(&xml, "    </migration_features>\n");
805 806
    }

807
    if (caps->host.nnumaCell &&
808
        virCapabilitiesFormatNUMATopology(&xml, caps->host.nnumaCell,
809 810
                                          caps->host.numaCell) < 0)
        return NULL;
811

812
    for (i = 0; i < caps->host.nsecModels; i++) {
813
        virBufferAddLit(&xml, "    <secmodel>\n");
814
        virBufferAsprintf(&xml, "      <model>%s</model>\n",
815
                          caps->host.secModels[i].model);
816
        virBufferAsprintf(&xml, "      <doi>%s</doi>\n",
817
                          caps->host.secModels[i].doi);
818 819 820
        virBufferAddLit(&xml, "    </secmodel>\n");
    }

821
    virBufferAddLit(&xml, "  </host>\n\n");
822 823 824


    for (i = 0 ; i < caps->nguests ; i++) {
825
        virBufferAddLit(&xml, "  <guest>\n");
826
        virBufferAsprintf(&xml, "    <os_type>%s</os_type>\n",
827
                          caps->guests[i]->ostype);
828 829 830
        if (caps->guests[i]->arch.id)
            virBufferAsprintf(&xml, "    <arch name='%s'>\n",
                              virArchToString(caps->guests[i]->arch.id));
831
        virBufferAsprintf(&xml, "      <wordsize>%d</wordsize>\n",
832 833
                          caps->guests[i]->arch.wordsize);
        if (caps->guests[i]->arch.defaultInfo.emulator)
834
            virBufferAsprintf(&xml, "      <emulator>%s</emulator>\n",
835 836
                              caps->guests[i]->arch.defaultInfo.emulator);
            if (caps->guests[i]->arch.defaultInfo.loader)
837
                virBufferAsprintf(&xml, "      <loader>%s</loader>\n",
838
                                  caps->guests[i]->arch.defaultInfo.loader);
839 840

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

        for (j = 0 ; j < caps->guests[i]->arch.ndomains ; j++) {
849
            virBufferAsprintf(&xml, "      <domain type='%s'>\n",
850 851
                                  caps->guests[i]->arch.domains[j]->type);
            if (caps->guests[i]->arch.domains[j]->info.emulator)
852
                virBufferAsprintf(&xml, "        <emulator>%s</emulator>\n",
853 854
                                  caps->guests[i]->arch.domains[j]->info.emulator);
            if (caps->guests[i]->arch.domains[j]->info.loader)
855
                virBufferAsprintf(&xml, "        <loader>%s</loader>\n",
856
                                  caps->guests[i]->arch.domains[j]->info.loader);
857 858

            for (k = 0 ; k < caps->guests[i]->arch.domains[j]->info.nmachines ; k++) {
859
                virCapsGuestMachinePtr machine = caps->guests[i]->arch.domains[j]->info.machines[k];
860
                virBufferAddLit(&xml, "        <machine");
861
                if (machine->canonical)
862 863
                    virBufferAsprintf(&xml, " canonical='%s'", machine->canonical);
                virBufferAsprintf(&xml, ">%s</machine>\n", machine->name);
864
            }
865
            virBufferAddLit(&xml, "      </domain>\n");
866 867
        }

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

        if (caps->guests[i]->nfeatures) {
871
            virBufferAddLit(&xml, "    <features>\n");
872 873 874 875

            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") ||
876
                    STREQ(caps->guests[i]->features[j]->name, "ia64_be") ||
877 878
                    STREQ(caps->guests[i]->features[j]->name, "cpuselection") ||
                    STREQ(caps->guests[i]->features[j]->name, "deviceboot")) {
879
                    virBufferAsprintf(&xml, "      <%s/>\n",
880
                                      caps->guests[i]->features[j]->name);
881
                } else {
882
                    virBufferAsprintf(&xml, "      <%s default='%s' toggle='%s'/>\n",
883 884 885
                                      caps->guests[i]->features[j]->name,
                                      caps->guests[i]->features[j]->defaultOn ? "on" : "off",
                                      caps->guests[i]->features[j]->toggle ? "yes" : "no");
886 887 888
                }
            }

889
            virBufferAddLit(&xml, "    </features>\n");
890 891
        }

892
        virBufferAddLit(&xml, "  </guest>\n\n");
893 894
    }

895
    virBufferAddLit(&xml, "</capabilities>\n");
896

897 898
    if (virBufferError(&xml)) {
        virBufferFreeAndReset(&xml);
899
        return NULL;
900
    }
901

902
    return virBufferContentAndReset(&xml);
903
}
904 905 906

extern void
virCapabilitiesSetMacPrefix(virCapsPtr caps,
907
                            const unsigned char prefix[VIR_MAC_PREFIX_BUFLEN])
908 909 910 911 912 913
{
    memcpy(caps->macPrefix, prefix, sizeof(caps->macPrefix));
}

extern void
virCapabilitiesGenerateMac(virCapsPtr caps,
914
                           virMacAddrPtr mac)
915
{
916
    virMacAddrGenerate(caps->macPrefix, mac);
917
}
918 919 920 921 922 923 924 925 926 927

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

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