xen_driver.c 81.2 KB
Newer Older
1
/*
2
 * xen_driver.c: Unified Xen driver.
3
 *
4
 * Copyright (C) 2007-2014 Red Hat, Inc.
5
 *
O
Osier Yang 已提交
6 7 8 9 10 11 12 13 14 15 16
 * 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
17
 * License along with this library.  If not, see
O
Osier Yang 已提交
18
 * <http://www.gnu.org/licenses/>.
19 20 21 22
 *
 * Richard W.M. Jones <rjones@redhat.com>
 */

23
#include <config.h>
24

25 26 27
/* Note:
 *
 * This driver provides a unified interface to the five
28
 * separate underlying Xen drivers (xen_internal,
29 30 31 32 33 34 35
 * xend_internal, xs_internal and xm_internal).  Historically
 * the body of libvirt.c handled the five Xen drivers,
 * and contained Xen-specific code.
 */

#include <stdint.h>
#include <unistd.h>
36
#include <string.h>
37
#include <errno.h>
38
#include <sys/types.h>
39
#include <fcntl.h>
40 41
#include <xen/dom0_ops.h>

42
#include "virerror.h"
43
#include "virlog.h"
44
#include "datatypes.h"
45
#include "xen_driver.h"
46

47
#include "xen_sxpr.h"
48
#include "xen_xm.h"
49
#include "xen_hypervisor.h"
50 51 52
#include "xend_internal.h"
#include "xs_internal.h"
#include "xm_internal.h"
53
#if WITH_XEN_INOTIFY
54
# include "xen_inotify.h"
55
#endif
56
#include "virxml.h"
57
#include "viralloc.h"
58
#include "node_device_conf.h"
59
#include "virpci.h"
60
#include "viruuid.h"
61
#include "fdstream.h"
E
Eric Blake 已提交
62
#include "virfile.h"
M
Martin Kletzander 已提交
63
#include "viruri.h"
64
#include "vircommand.h"
65
#include "virnodesuspend.h"
66
#include "nodeinfo.h"
67
#include "configmake.h"
68
#include "virstring.h"
69
#include "viraccessapicheck.h"
70

71
#define VIR_FROM_THIS VIR_FROM_XEN
72 73 74

VIR_LOG_INIT("xen.xen_driver");

75
#define XEN_SAVE_DIR LOCALSTATEDIR "/lib/libvirt/xen/save"
76

77
static int
78
xenUnifiedNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info);
79

80
static int
81 82 83 84
xenUnifiedDomainGetVcpusFlagsInternal(virDomainPtr dom,
                                      virDomainDefPtr def,
                                      unsigned int flags);

85
static int
86 87 88 89 90 91
xenUnifiedDomainGetVcpusInternal(virDomainPtr dom,
                                 virDomainDefPtr def,
                                 virVcpuInfoPtr info,
                                 int maxinfo,
                                 unsigned char *cpumaps,
                                 int maplen);
92

93

94 95
static bool is_privileged;
static virSysinfoDefPtr hostsysinfo;
J
John Levon 已提交
96

97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
static virDomainDefPtr xenGetDomainDefForID(virConnectPtr conn, int id)
{
    virDomainDefPtr ret;

    ret = xenHypervisorLookupDomainByID(conn, id);

    if (!ret && virGetLastError() == NULL)
        virReportError(VIR_ERR_NO_DOMAIN, __FUNCTION__);

    return ret;
}


static virDomainDefPtr xenGetDomainDefForName(virConnectPtr conn, const char *name)
{
    xenUnifiedPrivatePtr priv = conn->privateData;
    virDomainDefPtr ret;

    ret = xenDaemonLookupByName(conn, name);

    /* Try XM for inactive domains. */
    if (!ret &&
        priv->xendConfigVersion <= XEND_CONFIG_VERSION_3_0_3)
        ret = xenXMDomainLookupByName(conn, name);

    if (!ret && virGetLastError() == NULL)
        virReportError(VIR_ERR_NO_DOMAIN, __FUNCTION__);

    return ret;
}


static virDomainDefPtr xenGetDomainDefForUUID(virConnectPtr conn, const unsigned char *uuid)
{
    xenUnifiedPrivatePtr priv = conn->privateData;
    virDomainDefPtr ret;

    ret = xenHypervisorLookupDomainByUUID(conn, uuid);

    /* Try XM for inactive domains. */
    if (!ret) {
        if (priv->xendConfigVersion <= XEND_CONFIG_VERSION_3_0_3)
            ret = xenXMDomainLookupByUUID(conn, uuid);
        else
            ret = xenDaemonLookupByUUID(conn, uuid);
    }

    if (!ret && virGetLastError() == NULL)
        virReportError(VIR_ERR_NO_DOMAIN, __FUNCTION__);

    return ret;
}


151 152 153 154 155 156 157
static virDomainDefPtr xenGetDomainDefForDom(virDomainPtr dom)
{
    /* UUID lookup is more efficient than name lookup */
    return xenGetDomainDefForUUID(dom->conn, dom->uuid);
}


158 159 160 161 162
/**
 * xenNumaInit:
 * @conn: pointer to the hypervisor connection
 *
 * Initializer for previous variables. We currently assume that
R
Richard W.M. Jones 已提交
163
 * the number of physical CPU and the number of NUMA cell is fixed
164 165 166
 * until reboot which might be false in future Xen implementations.
 */
static void
167 168
xenNumaInit(virConnectPtr conn)
{
169
    virNodeInfo nodeInfo;
D
Daniel P. Berrange 已提交
170
    xenUnifiedPrivatePtr priv;
171 172 173 174 175 176
    int ret;

    ret = xenUnifiedNodeGetInfo(conn, &nodeInfo);
    if (ret < 0)
        return;

D
Daniel P. Berrange 已提交
177
    priv = conn->privateData;
178

D
Daniel P. Berrange 已提交
179 180
    priv->nbNodeCells = nodeInfo.nodes;
    priv->nbNodeCpus = nodeInfo.cpus;
181 182
}

D
Daniel P. Berrange 已提交
183

184 185 186
/**
 * xenDomainUsedCpus:
 * @dom: the domain
187
 * @def: the domain definition
188 189 190 191 192 193 194 195
 *
 * Analyze which set of CPUs are used by the domain and
 * return a string providing the ranges.
 *
 * Returns the string which needs to be freed by the caller or
 *         NULL if the domain uses all CPU or in case of error.
 */
char *
196
xenDomainUsedCpus(virDomainPtr dom, virDomainDefPtr def)
197 198
{
    char *res = NULL;
D
Daniel P. Berrange 已提交
199
    int ncpus;
200
    int nb_vcpu;
201
    virBitmapPtr cpulist = NULL;
202 203 204 205 206 207
    unsigned char *cpumap = NULL;
    size_t cpumaplen;
    int nb = 0;
    int n, m;
    virVcpuInfoPtr cpuinfo = NULL;
    virNodeInfo nodeinfo;
D
Daniel P. Berrange 已提交
208
    xenUnifiedPrivatePtr priv;
209

D
Daniel P. Berrange 已提交
210 211 212
    priv = dom->conn->privateData;

    if (priv->nbNodeCpus <= 0)
213
        return NULL;
214 215 216
    nb_vcpu = xenUnifiedDomainGetVcpusFlagsInternal(dom, def,
                                                    (VIR_DOMAIN_VCPU_LIVE |
                                                     VIR_DOMAIN_VCPU_MAXIMUM));
217
    if (nb_vcpu <= 0)
218
        return NULL;
219
    if (xenUnifiedNodeGetInfo(dom->conn, &nodeinfo) < 0)
220
        return NULL;
221

222
    if (!(cpulist = virBitmapNew(priv->nbNodeCpus)))
223
        goto done;
224
    if (VIR_ALLOC_N(cpuinfo, nb_vcpu) < 0)
225 226
        goto done;
    cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo));
227
    if (xalloc_oversized(nb_vcpu, cpumaplen) ||
228
        VIR_ALLOC_N(cpumap, nb_vcpu * cpumaplen) < 0)
229 230
        goto done;

231 232
    if ((ncpus = xenUnifiedDomainGetVcpusInternal(dom, def, cpuinfo, nb_vcpu,
                                                  cpumap, cpumaplen)) >= 0) {
233 234
        for (n = 0; n < ncpus; n++) {
            for (m = 0; m < priv->nbNodeCpus; m++) {
J
Ján Tomko 已提交
235
                if (!virBitmapIsBitSet(cpulist, m) &&
236
                    (VIR_CPU_USABLE(cpumap, cpumaplen, n, m))) {
237
                    ignore_value(virBitmapSetBit(cpulist, m));
238 239
                    nb++;
                    /* if all CPU are used just return NULL */
D
Daniel P. Berrange 已提交
240
                    if (nb == priv->nbNodeCpus)
241 242 243 244 245
                        goto done;

                }
            }
        }
246
        res = virBitmapFormat(cpulist);
247 248
    }

249
 done:
250
    virBitmapFree(cpulist);
251 252
    VIR_FREE(cpumap);
    VIR_FREE(cpuinfo);
253
    return res;
254 255
}

J
John Levon 已提交
256
static int
257
xenUnifiedStateInitialize(bool privileged,
258 259
                          virStateInhibitCallback callback ATTRIBUTE_UNUSED,
                          void *opaque ATTRIBUTE_UNUSED)
J
John Levon 已提交
260
{
261
    /* Don't allow driver to work in non-root libvirtd */
J
Jim Fehlig 已提交
262
    if (privileged) {
263
        is_privileged = true;
J
Jim Fehlig 已提交
264 265 266 267 268 269 270 271 272 273
        hostsysinfo = virSysinfoRead();
    }

    return 0;
}

static int
xenUnifiedStateCleanup(void)
{
    virSysinfoDefFree(hostsysinfo);
J
John Levon 已提交
274 275 276 277
    return 0;
}

static virStateDriver state_driver = {
278
    .name = "Xen",
279
    .stateInitialize = xenUnifiedStateInitialize,
J
Jim Fehlig 已提交
280
    .stateCleanup = xenUnifiedStateCleanup,
J
John Levon 已提交
281 282
};

283 284 285 286 287 288 289 290 291 292 293
/*----- Dispatch functions. -----*/

/* These dispatch functions follow the model used historically
 * by libvirt.c -- trying each low-level Xen driver in turn
 * until one succeeds.  However since we know what low-level
 * drivers can perform which functions, it is probably better
 * in future to optimise these dispatch functions to just call
 * the single function (or small number of appropriate functions)
 * in the low level drivers directly.
 */

294
static int
295
xenUnifiedProbe(void)
296 297 298
{
#ifdef __linux__
    if (virFileExists("/proc/xen"))
299
        return 1;
300
#endif
301
#ifdef __sun
302
    int fd;
303

304 305
    if ((fd = open("/dev/xen/domcaps", O_RDONLY)) >= 0) {
        VIR_FORCE_CLOSE(fd);
306
        return 1;
307 308
    }
#endif
309
    return 0;
310 311
}

J
Jim Fehlig 已提交
312
#ifdef WITH_LIBXL
313
static bool
314
xenUnifiedXendProbe(void)
J
Jim Fehlig 已提交
315
{
316
    bool ret = false;
J
Jim Fehlig 已提交
317

318 319 320 321 322 323 324 325
    if (virFileExists("/usr/sbin/xend")) {
        virCommandPtr cmd;

        cmd = virCommandNewArgList("/usr/sbin/xend", "status", NULL);
        if (virCommandRun(cmd, NULL) == 0)
            ret = true;
        virCommandFree(cmd);
    }
J
Jim Fehlig 已提交
326 327 328 329 330

    return ret;
}
#endif

331

332 333
static int
xenDomainDeviceDefPostParse(virDomainDeviceDefPtr dev,
334
                            const virDomainDef *def,
335 336 337 338 339 340 341 342 343
                            virCapsPtr caps ATTRIBUTE_UNUSED,
                            void *opaque ATTRIBUTE_UNUSED)
{
    if (dev->type == VIR_DOMAIN_DEVICE_CHR &&
        dev->data.chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE &&
        dev->data.chr->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_NONE &&
        STRNEQ(def->os.type, "hvm"))
        dev->data.chr->targetType = VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_XEN;

344 345 346 347 348 349 350 351 352 353
    /* forbid capabilities mode hostdev in this kind of hypervisor */
    if (dev->type == VIR_DOMAIN_DEVICE_HOSTDEV &&
        dev->data.hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("hostdev mode 'capabilities' is not "
                         "supported in %s"),
                       virDomainVirtTypeToString(def->virtType));
        return -1;
    }

354 355 356 357 358
    if (dev->type == VIR_DOMAIN_DEVICE_VIDEO && dev->data.video->vram == 0) {
        switch (dev->data.video->type) {
        case VIR_DOMAIN_VIDEO_TYPE_VGA:
        case VIR_DOMAIN_VIDEO_TYPE_CIRRUS:
        case VIR_DOMAIN_VIDEO_TYPE_VMVGA:
359
            dev->data.video->vram = 16 * 1024;
360 361 362 363 364 365 366 367 368 369 370 371 372
        break;

        case VIR_DOMAIN_VIDEO_TYPE_XEN:
            /* Original Xen PVFB hardcoded to 4 MB */
            dev->data.video->vram = 4 * 1024;
            break;

        case VIR_DOMAIN_VIDEO_TYPE_QXL:
            /* Use 64M as the minimal video video memory for qxl device */
            return 64 * 1024;
        }
    }

373 374 375 376 377 378 379 380 381
    return 0;
}


static int
xenDomainDefPostParse(virDomainDefPtr def,
                      virCapsPtr caps ATTRIBUTE_UNUSED,
                      void *opaque ATTRIBUTE_UNUSED)
{
382 383 384 385 386 387 388 389 390
    if (!def->memballoon) {
        virDomainMemballoonDefPtr memballoon;
        if (VIR_ALLOC(memballoon) < 0)
            return -1;

        memballoon->model = VIR_DOMAIN_MEMBALLOON_MODEL_XEN;
        def->memballoon = memballoon;
    }

391 392 393 394
    return 0;
}


395 396
virDomainDefParserConfig xenDomainDefParserConfig = {
    .macPrefix = { 0x00, 0x16, 0x3e },
397
    .devicesPostParseCallback = xenDomainDeviceDefPostParse,
398
    .domainPostParseCallback = xenDomainDefPostParse,
399 400
};

401

402 403 404 405 406 407 408 409
virDomainXMLOptionPtr
xenDomainXMLConfInit(void)
{
    return virDomainXMLOptionNew(&xenDomainDefParserConfig,
                                 NULL, NULL);
}


410
static virDrvOpenStatus
411
xenUnifiedConnectOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags)
412
{
413
    xenUnifiedPrivatePtr priv;
414
    char ebuf[1024];
415

J
John Levon 已提交
416 417 418 419
    /*
     * Only the libvirtd instance can open this driver.
     * Everything else falls back to the remote driver.
     */
420
    if (!is_privileged)
J
John Levon 已提交
421 422
        return VIR_DRV_OPEN_DECLINED;

423 424 425 426
    if (conn->uri == NULL) {
        if (!xenUnifiedProbe())
            return VIR_DRV_OPEN_DECLINED;

427 428 429 430 431 432 433
#ifdef WITH_LIBXL
        /* Decline xen:// URI if xend is not running and libxenlight
         * driver is potentially available. */
        if (!xenUnifiedXendProbe())
            return VIR_DRV_OPEN_DECLINED;
#endif

434
        if (!(conn->uri = virURIParse("xen:///")))
435
            return VIR_DRV_OPEN_ERROR;
436 437 438 439 440 441 442
    } else {
        if (conn->uri->scheme) {
            /* Decline any scheme which isn't "xen://" or "http://". */
            if (STRCASENEQ(conn->uri->scheme, "xen") &&
                STRCASENEQ(conn->uri->scheme, "http"))
                return VIR_DRV_OPEN_DECLINED;

443 444 445 446 447 448
#ifdef WITH_LIBXL
            /* Decline xen:// URI if xend is not running and libxenlight
             * driver is potentially available. */
            if (!xenUnifiedXendProbe())
                return VIR_DRV_OPEN_DECLINED;
#endif
449 450 451 452 453

            /* Return an error if the path isn't '' or '/' */
            if (conn->uri->path &&
                STRNEQ(conn->uri->path, "") &&
                STRNEQ(conn->uri->path, "/")) {
454 455 456
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("unexpected Xen URI path '%s', try xen:///"),
                               conn->uri->path);
457 458
                return VIR_DRV_OPEN_ERROR;
            }
459

460 461 462 463 464 465
            /* Decline any xen:// URI with a server specified, allowing remote
             * driver to handle, but keep any http:/// URIs */
            if (STRCASEEQ(conn->uri->scheme, "xen") &&
                conn->uri->server)
                return VIR_DRV_OPEN_DECLINED;
        } else {
466
            return VIR_DRV_OPEN_DECLINED;
467 468
        }
    }
469

470 471
    /* We now know the URI is definitely for this driver, so beyond
     * here, don't return DECLINED, always use ERROR */
472

473 474 475
    if (virConnectOpenEnsureACL(conn) < 0)
        return VIR_DRV_OPEN_ERROR;

476
    /* Allocate per-connection private data. */
477
    if (VIR_ALLOC(priv) < 0)
478
        return VIR_DRV_OPEN_ERROR;
D
Daniel P. Berrange 已提交
479
    if (virMutexInit(&priv->lock) < 0) {
480 481
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("cannot initialize mutex"));
D
Daniel P. Berrange 已提交
482 483 484
        VIR_FREE(priv);
        return VIR_DRV_OPEN_ERROR;
    }
485

486
    if (!(priv->domainEvents = virObjectEventStateNew())) {
D
Daniel P. Berrange 已提交
487 488
        virMutexDestroy(&priv->lock);
        VIR_FREE(priv);
489 490
        return VIR_DRV_OPEN_ERROR;
    }
D
Daniel P. Berrange 已提交
491 492
    conn->privateData = priv;

493 494 495 496 497
    priv->handle = -1;
    priv->xendConfigVersion = -1;
    priv->xshandle = NULL;


498 499 500 501 502 503
    /* Hypervisor required to succeed */
    VIR_DEBUG("Trying hypervisor sub-driver");
    if (xenHypervisorOpen(conn, auth, flags) < 0)
        goto error;
    VIR_DEBUG("Activated hypervisor sub-driver");
    priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET] = 1;
504

505
    /* XenD is required to succeed */
506
    VIR_DEBUG("Trying XenD sub-driver");
507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525
    if (xenDaemonOpen(conn, auth, flags) < 0)
        goto error;
    VIR_DEBUG("Activated XenD sub-driver");
    priv->opened[XEN_UNIFIED_XEND_OFFSET] = 1;

    /* For old XenD, the XM driver is required to succeed */
    if (priv->xendConfigVersion <= XEND_CONFIG_VERSION_3_0_3) {
        VIR_DEBUG("Trying XM sub-driver");
        if (xenXMOpen(conn, auth, flags) < 0)
            goto error;
        VIR_DEBUG("Activated XM sub-driver");
        priv->opened[XEN_UNIFIED_XM_OFFSET] = 1;
    }

    VIR_DEBUG("Trying XS sub-driver");
    if (xenStoreOpen(conn, auth, flags) < 0)
        goto error;
    VIR_DEBUG("Activated XS sub-driver");
    priv->opened[XEN_UNIFIED_XS_OFFSET] = 1;
526

D
Daniel P. Berrange 已提交
527 528
    xenNumaInit(conn);

529
    if (!(priv->caps = xenHypervisorMakeCapabilities(conn))) {
530
        VIR_DEBUG("Failed to make capabilities");
531
        goto error;
532 533
    }

534
    if (!(priv->xmlopt = xenDomainXMLConfInit()))
535
        goto error;
536

537
#if WITH_XEN_INOTIFY
538 539 540 541 542
    VIR_DEBUG("Trying Xen inotify sub-driver");
    if (xenInotifyOpen(conn, auth, flags) < 0)
        goto error;
    VIR_DEBUG("Activated Xen inotify sub-driver");
    priv->opened[XEN_UNIFIED_INOTIFY_OFFSET] = 1;
543 544
#endif

545
    if (VIR_STRDUP(priv->saveDir, XEN_SAVE_DIR) < 0)
546
        goto error;
547 548

    if (virFileMakePath(priv->saveDir) < 0) {
549
        VIR_ERROR(_("Errored to create save dir '%s': %s"), priv->saveDir,
550
                  virStrerror(errno, ebuf, sizeof(ebuf)));
551
        goto error;
552 553
    }

554
    return VIR_DRV_OPEN_SUCCESS;
555

556
 error:
557
    VIR_DEBUG("Failed to activate a mandatory sub-driver");
558 559 560 561 562 563 564 565 566 567 568 569
#if WITH_XEN_INOTIFY
    if (priv->opened[XEN_UNIFIED_INOTIFY_OFFSET])
        xenInotifyClose(conn);
#endif
    if (priv->opened[XEN_UNIFIED_XM_OFFSET])
        xenXMClose(conn);
    if (priv->opened[XEN_UNIFIED_XS_OFFSET])
        xenStoreClose(conn);
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
        xenDaemonClose(conn);
    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET])
        xenHypervisorClose(conn);
D
Daniel P. Berrange 已提交
570
    virMutexDestroy(&priv->lock);
571
    VIR_FREE(priv->saveDir);
572
    VIR_FREE(priv);
D
Daniel P. Berrange 已提交
573
    conn->privateData = NULL;
574
    return VIR_DRV_OPEN_ERROR;
575 576 577
}

static int
578
xenUnifiedConnectClose(virConnectPtr conn)
579
{
580
    xenUnifiedPrivatePtr priv = conn->privateData;
581

582
    virObjectUnref(priv->caps);
583
    virObjectUnref(priv->xmlopt);
584
    virObjectEventStateFree(priv->domainEvents);
585

586 587 588 589 590 591 592 593 594 595 596 597
#if WITH_XEN_INOTIFY
    if (priv->opened[XEN_UNIFIED_INOTIFY_OFFSET])
        xenInotifyClose(conn);
#endif
    if (priv->opened[XEN_UNIFIED_XM_OFFSET])
        xenXMClose(conn);
    if (priv->opened[XEN_UNIFIED_XS_OFFSET])
        xenStoreClose(conn);
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
        xenDaemonClose(conn);
    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET])
        xenHypervisorClose(conn);
598

599
    VIR_FREE(priv->saveDir);
D
Daniel P. Berrange 已提交
600 601
    virMutexDestroy(&priv->lock);
    VIR_FREE(conn->privateData);
602

603
    return 0;
604 605
}

606 607 608 609 610 611 612 613 614 615 616

#define HV_VERSION ((DOM0_INTERFACE_VERSION >> 24) * 1000000 +         \
                    ((DOM0_INTERFACE_VERSION >> 16) & 0xFF) * 1000 +   \
                    (DOM0_INTERFACE_VERSION & 0xFFFF))

unsigned long xenUnifiedVersion(void)
{
    return HV_VERSION;
}


617
static const char *
618
xenUnifiedConnectGetType(virConnectPtr conn)
619
{
620 621 622
    if (virConnectGetTypeEnsureACL(conn) < 0)
        return NULL;

623
    return "Xen";
624 625
}

626 627
/* Which features are supported by this driver? */
static int
628
xenUnifiedConnectSupportsFeature(virConnectPtr conn, int feature)
629
{
630 631 632
    if (virConnectSupportsFeatureEnsureACL(conn) < 0)
        return -1;

633
    switch (feature) {
634 635 636 637 638
    case VIR_DRV_FEATURE_MIGRATION_V1:
    case VIR_DRV_FEATURE_MIGRATION_DIRECT:
        return 1;
    default:
        return 0;
639 640 641
    }
}

642
static int
643
xenUnifiedConnectGetVersion(virConnectPtr conn, unsigned long *hvVer)
644
{
645 646 647
    if (virConnectGetVersionEnsureACL(conn) < 0)
        return -1;

648
    return xenHypervisorGetVersion(conn, hvVer);
649 650
}

651

652
static char *xenUnifiedConnectGetHostname(virConnectPtr conn)
653
{
654 655 656
    if (virConnectGetHostnameEnsureACL(conn) < 0)
        return NULL;

657 658 659
    return virGetHostname();
}

J
Jim Fehlig 已提交
660 661 662 663 664 665 666 667
static char *
xenUnifiedConnectGetSysinfo(virConnectPtr conn ATTRIBUTE_UNUSED,
                            unsigned int flags)
{
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    virCheckFlags(0, NULL);

668 669 670
    if (virConnectGetSysinfoEnsureACL(conn) < 0)
        return NULL;

J
Jim Fehlig 已提交
671 672 673 674 675 676 677 678
    if (!hostsysinfo) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("Host SMBIOS information is not available"));
        return NULL;
    }

    if (virSysinfoFormat(&buf, hostsysinfo) < 0)
        return NULL;
679
    if (virBufferCheckError(&buf) < 0)
J
Jim Fehlig 已提交
680 681 682
        return NULL;
    return virBufferContentAndReset(&buf);
}
683

684
static int
685
xenUnifiedConnectIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED)
686 687 688 689 690
{
    return 0;
}

static int
691
xenUnifiedConnectIsSecure(virConnectPtr conn)
692
{
693
    xenUnifiedPrivatePtr priv = conn->privateData;
694 695 696 697 698 699 700 701 702 703
    int ret = 1;

    /* All drivers are secure, except for XenD over TCP */
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET] &&
        priv->addrfamily != AF_UNIX)
        ret = 0;

    return ret;
}

704
static int
705
xenUnifiedConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED)
706 707 708 709 710
{
    /* XenD reconnects for each request */
    return 1;
}

711
int
712
xenUnifiedConnectGetMaxVcpus(virConnectPtr conn, const char *type)
713
{
714 715 716
    if (virConnectGetMaxVcpusEnsureACL(conn) < 0)
        return -1;

717
    if (type && STRCASENEQ(type, "Xen")) {
718
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
719 720
        return -1;
    }
721

722
    return xenHypervisorGetMaxVcpus(conn, type);
723 724 725
}

static int
726
xenUnifiedNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info)
727
{
728 729 730
    if (virNodeGetInfoEnsureACL(conn) < 0)
        return -1;

731
    return xenDaemonNodeGetInfo(conn, info);
732 733 734
}

static char *
735
xenUnifiedConnectGetCapabilities(virConnectPtr conn)
736
{
D
Daniel P. Berrange 已提交
737
    xenUnifiedPrivatePtr priv = conn->privateData;
738

739 740 741
    if (virConnectGetCapabilitiesEnsureACL(conn) < 0)
        return NULL;

742
    return virCapabilitiesFormatXML(priv->caps);
743 744 745
}

static int
746
xenUnifiedConnectListDomains(virConnectPtr conn, int *ids, int maxids)
747
{
748 749 750
    if (virConnectListDomainsEnsureACL(conn) < 0)
        return -1;

751
    return xenStoreListDomains(conn, ids, maxids);
752 753 754
}

static int
755
xenUnifiedConnectNumOfDomains(virConnectPtr conn)
756
{
757 758 759
    if (virConnectNumOfDomainsEnsureACL(conn) < 0)
        return -1;

760
    return xenStoreNumOfDomains(conn);
761 762 763
}

static virDomainPtr
764
xenUnifiedDomainCreateXML(virConnectPtr conn,
765 766
                          const char *xml,
                          unsigned int flags)
767
{
768 769 770
    xenUnifiedPrivatePtr priv = conn->privateData;
    virDomainDefPtr def = NULL;
    virDomainPtr ret = NULL;
771
    unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;
772

773 774 775 776
    virCheckFlags(VIR_DOMAIN_START_VALIDATE, NULL);

    if (flags & VIR_DOMAIN_START_VALIDATE)
        parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE;
777

778 779
    if (!(def = virDomainDefParseString(xml, priv->caps, priv->xmlopt,
                                        1 << VIR_DOMAIN_VIRT_XEN,
780
                                        parse_flags)))
781 782
        goto cleanup;

783 784 785
    if (virDomainCreateXMLEnsureACL(conn, def) < 0)
        goto cleanup;

786 787 788 789 790 791 792
    if (xenDaemonCreateXML(conn, def) < 0)
        goto cleanup;

    ret = virGetDomain(conn, def->name, def->uuid);
    if (ret)
        ret->id = def->id;

793
 cleanup:
794 795
    virDomainDefFree(def);
    return ret;
796 797 798
}

static virDomainPtr
799
xenUnifiedDomainLookupByID(virConnectPtr conn, int id)
800
{
801
    virDomainPtr ret = NULL;
802
    virDomainDefPtr def = NULL;
803

804 805
    if (!(def = xenGetDomainDefForID(conn, id)))
        goto cleanup;
806

807 808 809
    if (virDomainLookupByIDEnsureACL(conn, def) < 0)
        goto cleanup;

810 811
    if (!(ret = virGetDomain(conn, def->name, def->uuid)))
        goto cleanup;
812

813 814
    ret->id = def->id;

815
 cleanup:
816
    virDomainDefFree(def);
817
    return ret;
818 819 820
}

static virDomainPtr
821 822
xenUnifiedDomainLookupByUUID(virConnectPtr conn,
                             const unsigned char *uuid)
823
{
824 825
    virDomainPtr ret = NULL;
    virDomainDefPtr def = NULL;
826

827 828
    if (!(def = xenGetDomainDefForUUID(conn, uuid)))
        goto cleanup;
829

830 831 832
    if (virDomainLookupByUUIDEnsureACL(conn, def) < 0)
        goto cleanup;

833 834
    if (!(ret = virGetDomain(conn, def->name, def->uuid)))
        goto cleanup;
835

836
    ret->id = def->id;
837

838
 cleanup:
839
    virDomainDefFree(def);
840
    return ret;
841 842 843
}

static virDomainPtr
844 845
xenUnifiedDomainLookupByName(virConnectPtr conn,
                             const char *name)
846
{
847 848
    virDomainPtr ret = NULL;
    virDomainDefPtr def = NULL;
849

850 851
    if (!(def = xenGetDomainDefForName(conn, name)))
        goto cleanup;
852

853 854 855
    if (virDomainLookupByNameEnsureACL(conn, def) < 0)
        goto cleanup;

856 857
    if (!(ret = virGetDomain(conn, def->name, def->uuid)))
        goto cleanup;
858

859
    ret->id = def->id;
860

861
 cleanup:
862
    virDomainDefFree(def);
863
    return ret;
864 865
}

866 867 868 869

static int
xenUnifiedDomainIsActive(virDomainPtr dom)
{
870
    virDomainDefPtr def;
871 872
    int ret = -1;

873 874
    if (!(def = xenGetDomainDefForUUID(dom->conn, dom->uuid)))
        goto cleanup;
875

876
    ret = def->id == -1 ? 0 : 1;
877

878
 cleanup:
879
    virDomainDefFree(def);
880 881 882 883
    return ret;
}

static int
884
xenUnifiedDomainIsPersistent(virDomainPtr dom)
885
{
886
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
887
    virDomainDefPtr def = NULL;
888 889 890 891 892
    int ret = -1;

    if (priv->opened[XEN_UNIFIED_XM_OFFSET]) {
        /* Old Xen, pre-inactive domain management.
         * If the XM driver can see the guest, it is definitely persistent */
893 894
        def = xenXMDomainLookupByUUID(dom->conn, dom->uuid);
        if (def)
895 896 897 898 899
            ret = 1;
        else
            ret = 0;
    } else {
        /* New Xen with inactive domain management */
900 901 902
        def = xenDaemonLookupByUUID(dom->conn, dom->uuid);
        if (def) {
            if (def->id == -1) {
903 904 905 906 907 908 909 910 911
                /* If its inactive, then trivially, it must be persistent */
                ret = 1;
            } else {
                char *path;
                char uuidstr[VIR_UUID_STRING_BUFLEN];

                /* If its running there's no official way to tell, so we
                 * go behind xend's back & look at the config dir */
                virUUIDFormat(dom->uuid, uuidstr);
912
                if (virAsprintf(&path, "%s/%s", XEND_DOMAINS_DIR, uuidstr) < 0)
913
                    goto cleanup;
914 915 916 917
                if (access(path, R_OK) == 0)
                    ret = 1;
                else if (errno == ENOENT)
                    ret = 0;
918 919 920 921
            }
        }
    }

922
 cleanup:
923
    virDomainDefFree(def);
924 925 926 927

    return ret;
}

928 929 930 931 932 933
static int
xenUnifiedDomainIsUpdated(virDomainPtr dom ATTRIBUTE_UNUSED)
{
    return 0;
}

934
static int
935
xenUnifiedDomainSuspend(virDomainPtr dom)
936
{
937 938 939 940 941 942
    int ret = -1;
    virDomainDefPtr def;

    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

943 944 945
    if (virDomainSuspendEnsureACL(dom->conn, def) < 0)
        goto cleanup;

946 947
    ret = xenDaemonDomainSuspend(dom->conn, def);

948
 cleanup:
949 950
    virDomainDefFree(def);
    return ret;
951 952 953
}

static int
954
xenUnifiedDomainResume(virDomainPtr dom)
955
{
956 957 958 959 960 961
    int ret = -1;
    virDomainDefPtr def;

    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

962 963 964
    if (virDomainResumeEnsureACL(dom->conn, def) < 0)
        goto cleanup;

965 966
    ret = xenDaemonDomainResume(dom->conn, def);

967
 cleanup:
968 969
    virDomainDefFree(def);
    return ret;
970 971 972
}

static int
973 974
xenUnifiedDomainShutdownFlags(virDomainPtr dom,
                              unsigned int flags)
975
{
976 977 978
    int ret = -1;
    virDomainDefPtr def;

979 980
    virCheckFlags(0, -1);

981 982 983
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

984
    if (virDomainShutdownFlagsEnsureACL(dom->conn, def, flags) < 0)
985 986
        goto cleanup;

987 988
    ret = xenDaemonDomainShutdown(dom->conn, def);

989
 cleanup:
990 991
    virDomainDefFree(def);
    return ret;
992 993
}

994 995 996 997 998 999
static int
xenUnifiedDomainShutdown(virDomainPtr dom)
{
    return xenUnifiedDomainShutdownFlags(dom, 0);
}

1000
static int
1001
xenUnifiedDomainReboot(virDomainPtr dom, unsigned int flags)
1002
{
1003 1004 1005
    int ret = -1;
    virDomainDefPtr def;

1006
    virCheckFlags(0, -1);
1007

1008 1009 1010
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

1011
    if (virDomainRebootEnsureACL(dom->conn, def, flags) < 0)
1012 1013
        goto cleanup;

1014 1015
    ret = xenDaemonDomainReboot(dom->conn, def);

1016
 cleanup:
1017 1018
    virDomainDefFree(def);
    return ret;
1019 1020
}

1021 1022 1023 1024
static int
xenUnifiedDomainDestroyFlags(virDomainPtr dom,
                             unsigned int flags)
{
1025 1026 1027
    int ret = -1;
    virDomainDefPtr def;

1028 1029
    virCheckFlags(0, -1);

1030 1031 1032
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

1033 1034 1035
    if (virDomainDestroyFlagsEnsureACL(dom->conn, def) < 0)
        goto cleanup;

1036 1037
    ret = xenDaemonDomainDestroy(dom->conn, def);

1038
 cleanup:
1039 1040
    virDomainDefFree(def);
    return ret;
1041 1042
}

1043 1044 1045 1046 1047 1048
static int
xenUnifiedDomainDestroy(virDomainPtr dom)
{
    return xenUnifiedDomainDestroyFlags(dom, 0);
}

1049
static char *
1050
xenUnifiedDomainGetOSType(virDomainPtr dom)
1051
{
1052
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1053 1054 1055 1056 1057
    char *ret = NULL;
    virDomainDefPtr def;

    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;
1058

1059 1060 1061
    if (virDomainGetOSTypeEnsureACL(dom->conn, def) < 0)
        goto cleanup;

1062
    if (def->id < 0) {
1063 1064 1065 1066 1067
        if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("Unable to query OS type for inactive domain"));
            return NULL;
        } else {
1068
            ret = xenDaemonDomainGetOSType(dom->conn, def);
1069
        }
1070
    } else {
1071
        ret = xenHypervisorDomainGetOSType(dom->conn, def);
1072
    }
1073

1074
 cleanup:
1075 1076
    virDomainDefFree(def);
    return ret;
1077 1078
}

1079

1080
static unsigned long long
1081
xenUnifiedDomainGetMaxMemory(virDomainPtr dom)
1082
{
1083
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1084 1085 1086 1087 1088
    unsigned long long ret = 0;
    virDomainDefPtr def;

    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;
1089

1090 1091 1092
    if (virDomainGetMaxMemoryEnsureACL(dom->conn, def) < 0)
        goto cleanup;

1093
    if (def->id < 0) {
1094
        if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
1095
            ret = xenXMDomainGetMaxMemory(dom->conn, def);
1096
        else
1097
            ret = xenDaemonDomainGetMaxMemory(dom->conn, def);
1098
    } else {
1099
        ret = xenHypervisorGetMaxMemory(dom->conn, def);
1100
    }
1101

1102
 cleanup:
1103 1104
    virDomainDefFree(def);
    return ret;
1105 1106 1107
}

static int
1108
xenUnifiedDomainSetMaxMemory(virDomainPtr dom, unsigned long memory)
1109
{
1110
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1111 1112
    int ret = -1;
    virDomainDefPtr def;
1113

1114 1115 1116
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

1117 1118 1119
    if (virDomainSetMaxMemoryEnsureACL(dom->conn, def) < 0)
        goto cleanup;

1120
    if (def->id < 0) {
1121
        if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
1122
            ret = xenXMDomainSetMaxMemory(dom->conn, def, memory);
1123
        else
1124
            ret = xenDaemonDomainSetMaxMemory(dom->conn, def, memory);
1125
    } else {
1126
        ret = xenHypervisorSetMaxMemory(dom->conn, def, memory);
1127
    }
1128

1129
 cleanup:
1130 1131
    virDomainDefFree(def);
    return ret;
1132 1133 1134
}

static int
1135
xenUnifiedDomainSetMemory(virDomainPtr dom, unsigned long memory)
1136
{
1137
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1138 1139 1140 1141 1142
    int ret = -1;
    virDomainDefPtr def;

    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;
1143

1144 1145 1146
    if (virDomainSetMemoryEnsureACL(dom->conn, def) < 0)
        goto cleanup;

1147 1148
    if (def->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
        ret = xenXMDomainSetMemory(dom->conn, def, memory);
1149
    else
1150 1151
        ret = xenDaemonDomainSetMemory(dom->conn, def, memory);

1152
 cleanup:
1153 1154
    virDomainDefFree(def);
    return ret;
1155 1156 1157
}

static int
1158
xenUnifiedDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info)
1159
{
1160
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1161 1162 1163 1164 1165
    int ret = -1;
    virDomainDefPtr def;

    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;
1166

1167 1168 1169
    if (virDomainGetInfoEnsureACL(dom->conn, def) < 0)
        goto cleanup;

1170
    if (def->id < 0) {
1171
        if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
1172
            ret = xenXMDomainGetInfo(dom->conn, def, info);
1173
        else
1174
            ret = xenDaemonDomainGetInfo(dom->conn, def, info);
1175
    } else {
1176
        ret = xenHypervisorGetDomainInfo(dom->conn, def, info);
1177
    }
1178

1179
 cleanup:
1180 1181
    virDomainDefFree(def);
    return ret;
1182 1183
}

1184 1185 1186 1187 1188 1189
static int
xenUnifiedDomainGetState(virDomainPtr dom,
                         int *state,
                         int *reason,
                         unsigned int flags)
{
1190
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1191 1192
    int ret = -1;
    virDomainDefPtr def;
1193 1194 1195

    virCheckFlags(0, -1);

1196 1197 1198
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

1199 1200 1201
    if (virDomainGetStateEnsureACL(dom->conn, def) < 0)
        goto cleanup;

1202
    if (def->id < 0) {
1203
        if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
1204
            ret = xenXMDomainGetState(dom->conn, def, state, reason);
1205
        else
1206
            ret = xenDaemonDomainGetState(dom->conn, def, state, reason);
1207
    } else {
1208
        ret = xenHypervisorGetDomainState(dom->conn, def, state, reason);
1209
    }
1210

1211
 cleanup:
1212 1213
    virDomainDefFree(def);
    return ret;
1214 1215
}

1216
static int
1217 1218
xenUnifiedDomainSaveFlags(virDomainPtr dom, const char *to, const char *dxml,
                          unsigned int flags)
1219
{
1220 1221 1222
    int ret = -1;
    virDomainDefPtr def;

1223
    virCheckFlags(0, -1);
1224

1225
    if (dxml) {
1226 1227
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
1228 1229 1230
        return -1;
    }

1231 1232 1233
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

1234 1235 1236
    if (virDomainSaveFlagsEnsureACL(dom->conn, def) < 0)
        goto cleanup;

1237 1238
    ret = xenDaemonDomainSave(dom->conn, def, to);

1239
 cleanup:
1240 1241
    virDomainDefFree(def);
    return ret;
1242 1243 1244
}

static int
1245 1246 1247 1248 1249
xenUnifiedDomainSave(virDomainPtr dom, const char *to)
{
    return xenUnifiedDomainSaveFlags(dom, to, NULL, 0);
}

1250
static char *
1251 1252
xenUnifiedDomainManagedSavePath(xenUnifiedPrivatePtr priv,
                                virDomainDefPtr def)
1253 1254 1255
{
    char *ret;

1256
    if (virAsprintf(&ret, "%s/%s.save", priv->saveDir, def->name) < 0)
1257 1258 1259 1260 1261 1262 1263 1264 1265
        return NULL;

    VIR_DEBUG("managed save image: %s", ret);
    return ret;
}

static int
xenUnifiedDomainManagedSave(virDomainPtr dom, unsigned int flags)
{
1266
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1267 1268
    char *name = NULL;
    virDomainDefPtr def = NULL;
1269 1270 1271 1272
    int ret = -1;

    virCheckFlags(0, -1);

1273 1274 1275
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

1276 1277 1278
    if (virDomainManagedSaveEnsureACL(dom->conn, def) < 0)
        goto cleanup;

1279
    if (!(name = xenUnifiedDomainManagedSavePath(priv, def)))
1280 1281
        goto cleanup;

1282
    ret = xenDaemonDomainSave(dom->conn, def, name);
1283

1284
 cleanup:
1285
    VIR_FREE(name);
1286
    virDomainDefFree(def);
1287 1288 1289 1290 1291 1292
    return ret;
}

static int
xenUnifiedDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags)
{
1293
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1294 1295
    char *name = NULL;
    virDomainDefPtr def = NULL;
1296 1297 1298 1299
    int ret = -1;

    virCheckFlags(0, -1);

1300 1301 1302
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

1303 1304 1305
    if (virDomainHasManagedSaveImageEnsureACL(dom->conn, def) < 0)
        goto cleanup;

1306 1307
    if (!(name = xenUnifiedDomainManagedSavePath(priv, def)))
        goto cleanup;
1308 1309

    ret = virFileExists(name);
1310

1311
 cleanup:
1312
    VIR_FREE(name);
1313
    virDomainDefFree(def);
1314 1315 1316 1317 1318 1319
    return ret;
}

static int
xenUnifiedDomainManagedSaveRemove(virDomainPtr dom, unsigned int flags)
{
1320
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1321 1322
    char *name = NULL;
    virDomainDefPtr def = NULL;
1323 1324 1325 1326
    int ret = -1;

    virCheckFlags(0, -1);

1327 1328 1329
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

1330 1331 1332
    if (virDomainManagedSaveRemoveEnsureACL(dom->conn, def) < 0)
        goto cleanup;

1333 1334
    if (!(name = xenUnifiedDomainManagedSavePath(priv, def)))
        goto cleanup;
1335 1336

    ret = unlink(name);
1337

1338
 cleanup:
1339 1340 1341 1342
    VIR_FREE(name);
    return ret;
}

1343 1344 1345
static int
xenUnifiedDomainRestoreFlags(virConnectPtr conn, const char *from,
                             const char *dxml, unsigned int flags)
1346
{
1347 1348
    virCheckFlags(0, -1);
    if (dxml) {
1349 1350
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
1351 1352 1353
        return -1;
    }

1354
    return xenDaemonDomainRestore(conn, from);
1355 1356
}

1357
static int
1358
xenUnifiedDomainRestore(virConnectPtr conn, const char *from)
1359 1360 1361 1362
{
    return xenUnifiedDomainRestoreFlags(conn, from, NULL, 0);
}

1363
static int
1364
xenUnifiedDomainCoreDump(virDomainPtr dom, const char *to, unsigned int flags)
1365
{
1366 1367 1368 1369 1370 1371 1372 1373
    virDomainDefPtr def = NULL;
    int ret = -1;

    virCheckFlags(0, -1);

    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

1374 1375 1376
    if (virDomainCoreDumpEnsureACL(dom->conn, def) < 0)
        goto cleanup;

1377 1378
    ret = xenDaemonDomainCoreDump(dom->conn, def, to, flags);

1379
 cleanup:
1380 1381
    virDomainDefFree(def);
    return ret;
1382 1383 1384
}

static int
1385 1386
xenUnifiedDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
                              unsigned int flags)
1387
{
1388
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1389 1390
    virDomainDefPtr def = NULL;
    int ret = -1;
1391

1392 1393 1394 1395 1396 1397 1398 1399 1400
    virCheckFlags(VIR_DOMAIN_VCPU_LIVE |
                  VIR_DOMAIN_VCPU_CONFIG |
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);

    /* At least one of LIVE or CONFIG must be set.  MAXIMUM cannot be
     * mixed with LIVE.  */
    if ((flags & (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG)) == 0 ||
        (flags & (VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_LIVE)) ==
         (VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_LIVE)) {
1401 1402
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid flag combination: (0x%x)"), flags);
1403 1404 1405
        return -1;
    }
    if (!nvcpus || (unsigned short) nvcpus != nvcpus) {
1406 1407
        virReportError(VIR_ERR_INVALID_ARG,
                       _("argument out of range: %d"), nvcpus);
1408 1409 1410
        return -1;
    }

1411 1412 1413
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

1414 1415 1416
    if (virDomainSetVcpusFlagsEnsureACL(dom->conn, def, flags) < 0)
        goto cleanup;

1417 1418 1419
    /* Try non-hypervisor methods first, then hypervisor direct method
     * as a last resort.
     */
1420
    if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
1421
        ret = xenXMDomainSetVcpusFlags(dom->conn, def, nvcpus, flags);
1422
    else
1423 1424
        ret = xenDaemonDomainSetVcpusFlags(dom->conn, def, nvcpus, flags);

1425
 cleanup:
1426 1427
    virDomainDefFree(def);
    return ret;
1428 1429
}

1430
static int
1431
xenUnifiedDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus)
1432
{
1433
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1434 1435 1436 1437 1438
    unsigned int flags = VIR_DOMAIN_VCPU_LIVE;

    /* Per the documented API, it is hypervisor-dependent whether this
     * affects just _LIVE or _LIVE|_CONFIG; in xen's case, that
     * depends on xendConfigVersion.  */
1439 1440 1441 1442
    if (priv->xendConfigVersion >= XEND_CONFIG_VERSION_3_0_4)
        flags |= VIR_DOMAIN_VCPU_CONFIG;

    return xenUnifiedDomainSetVcpusFlags(dom, nvcpus, flags);
1443 1444
}

1445
static int
1446 1447
xenUnifiedDomainPinVcpu(virDomainPtr dom, unsigned int vcpu,
                        unsigned char *cpumap, int maplen)
1448
{
1449
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1450 1451 1452 1453 1454
    virDomainDefPtr def = NULL;
    int ret = -1;

    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;
1455

1456 1457 1458
    if (virDomainPinVcpuEnsureACL(dom->conn, def) < 0)
        goto cleanup;

1459 1460
    if (dom->id < 0) {
        if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
1461
            ret = xenXMDomainPinVcpu(dom->conn, def, vcpu, cpumap, maplen);
1462
        else
1463
            ret = xenDaemonDomainPinVcpu(dom->conn, def, vcpu, cpumap, maplen);
1464
    } else {
1465
        ret = xenHypervisorPinVcpu(dom->conn, def, vcpu, cpumap, maplen);
1466
    }
1467

1468
 cleanup:
1469 1470
    virDomainDefFree(def);
    return ret;
1471 1472 1473
}

static int
1474 1475 1476 1477 1478 1479
xenUnifiedDomainGetVcpusInternal(virDomainPtr dom,
                                 virDomainDefPtr def,
                                 virVcpuInfoPtr info,
                                 int maxinfo,
                                 unsigned char *cpumaps,
                                 int maplen)
1480
{
1481
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1482 1483
    int ret = -1;

1484 1485 1486 1487 1488
    if (dom->id < 0) {
        if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("Cannot get VCPUs of inactive domain"));
        } else {
1489 1490
            ret = xenDaemonDomainGetVcpus(dom->conn, def, info, maxinfo,
                                          cpumaps, maplen);
1491
        }
1492
    } else {
1493 1494
        ret = xenHypervisorGetVcpus(dom->conn, def, info, maxinfo, cpumaps,
                                    maplen);
1495
    }
1496 1497

    return ret;
1498 1499 1500
}

static int
1501 1502 1503
xenUnifiedDomainGetVcpus(virDomainPtr dom,
                         virVcpuInfoPtr info, int maxinfo,
                         unsigned char *cpumaps, int maplen)
1504
{
1505 1506
    virDomainDefPtr def = NULL;
    int ret = -1;
1507

1508 1509 1510
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

1511
    if (virDomainGetVcpusEnsureACL(dom->conn, def) < 0)
1512 1513
        goto cleanup;

1514 1515 1516
    ret = xenUnifiedDomainGetVcpusInternal(dom, def, info, maxinfo, cpumaps,
                                           maplen);

1517
 cleanup:
1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529
    virDomainDefFree(def);
    return ret;
}

static int
xenUnifiedDomainGetVcpusFlagsInternal(virDomainPtr dom,
                                      virDomainDefPtr def,
                                      unsigned int flags)
{
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
    int ret = -1;

1530 1531
    if (dom->id < 0) {
        if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
1532
            ret = xenXMDomainGetVcpusFlags(dom->conn, def, flags);
1533
        else
1534
            ret = xenDaemonDomainGetVcpusFlags(dom->conn, def, flags);
1535 1536
    } else {
        if (flags == (VIR_DOMAIN_VCPU_CONFIG | VIR_DOMAIN_VCPU_MAXIMUM))
1537
            ret = xenHypervisorGetVcpuMax(dom->conn, def);
1538
        else
1539
            ret = xenDaemonDomainGetVcpusFlags(dom->conn, def, flags);
1540
    }
1541

1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557
   return ret;
}

static int
xenUnifiedDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags)
{
    virDomainDefPtr def = NULL;
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_VCPU_LIVE |
                  VIR_DOMAIN_VCPU_CONFIG |
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);

    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

1558
    if (virDomainGetVcpusFlagsEnsureACL(dom->conn, def, flags) < 0)
1559 1560 1561 1562
        goto cleanup;

    ret = xenUnifiedDomainGetVcpusFlagsInternal(dom, def, flags);

1563
 cleanup:
1564 1565
    virDomainDefFree(def);
    return ret;
1566 1567
}

1568
static int
1569
xenUnifiedDomainGetMaxVcpus(virDomainPtr dom)
1570 1571 1572 1573 1574
{
    return xenUnifiedDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_LIVE |
                                               VIR_DOMAIN_VCPU_MAXIMUM));
}

1575
static char *
1576
xenUnifiedDomainGetXMLDesc(virDomainPtr dom, unsigned int flags)
1577
{
1578
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1579 1580 1581 1582 1583 1584
    virDomainDefPtr minidef = NULL;
    virDomainDefPtr def = NULL;
    char *ret = NULL;

    if (!(minidef = xenGetDomainDefForDom(dom)))
        goto cleanup;
1585

1586 1587 1588
    if (virDomainGetXMLDescEnsureACL(dom->conn, minidef, flags) < 0)
        goto cleanup;

1589
    if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
1590
        def = xenXMDomainGetXMLDesc(dom->conn, minidef);
1591
    } else {
1592
        char *cpus;
1593
        xenUnifiedLock(priv);
1594
        cpus = xenDomainUsedCpus(dom, minidef);
1595
        xenUnifiedUnlock(priv);
1596
        def = xenDaemonDomainGetXMLDesc(dom->conn, minidef, cpus);
1597
        VIR_FREE(cpus);
1598
    }
1599 1600

    if (def)
1601 1602
        ret = virDomainDefFormat(def,
                                 virDomainDefFormatConvertXMLFlags(flags));
1603

1604
 cleanup:
1605 1606 1607
    virDomainDefFree(def);
    virDomainDefFree(minidef);
    return ret;
1608 1609
}

1610 1611

static char *
1612 1613 1614 1615
xenUnifiedConnectDomainXMLFromNative(virConnectPtr conn,
                                     const char *format,
                                     const char *config,
                                     unsigned int flags)
1616 1617 1618 1619
{
    virDomainDefPtr def = NULL;
    char *ret = NULL;
    virConfPtr conf = NULL;
1620 1621 1622
    int id;
    char * tty;
    int vncport;
1623
    xenUnifiedPrivatePtr priv = conn->privateData;
1624

E
Eric Blake 已提交
1625 1626
    virCheckFlags(0, NULL);

1627 1628 1629
    if (virConnectDomainXMLFromNativeEnsureACL(conn) < 0)
        return NULL;

1630 1631
    if (STRNEQ(format, XEN_CONFIG_FORMAT_XM) &&
        STRNEQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
1632 1633
        virReportError(VIR_ERR_INVALID_ARG,
                       _("unsupported config type %s"), format);
1634 1635 1636 1637
        return NULL;
    }

    if (STREQ(format, XEN_CONFIG_FORMAT_XM)) {
1638
        conf = virConfReadMem(config, strlen(config), 0);
1639 1640 1641
        if (!conf)
            goto cleanup;

M
Markus Groß 已提交
1642
        def = xenParseXM(conf, priv->xendConfigVersion, priv->caps);
1643
    } else if (STREQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
1644 1645
        if (xenGetDomIdFromSxprString(config, priv->xendConfigVersion, &id) < 0)
            goto cleanup;
1646 1647 1648 1649
        xenUnifiedLock(priv);
        tty = xenStoreDomainGetConsolePath(conn, id);
        vncport = xenStoreDomainGetVNCPort(conn, id);
        xenUnifiedUnlock(priv);
M
Markus Groß 已提交
1650
        def = xenParseSxprString(config, priv->xendConfigVersion, tty,
1651
                                       vncport);
1652 1653 1654 1655
    }
    if (!def)
        goto cleanup;

1656
    ret = virDomainDefFormat(def, 0);
1657

1658
 cleanup:
1659
    virDomainDefFree(def);
1660 1661
    if (conf)
        virConfFree(conf);
1662 1663 1664 1665 1666 1667
    return ret;
}


#define MAX_CONFIG_SIZE (1024 * 65)
static char *
1668 1669 1670 1671
xenUnifiedConnectDomainXMLToNative(virConnectPtr conn,
                                   const char *format,
                                   const char *xmlData,
                                   unsigned int flags)
1672 1673 1674 1675
{
    virDomainDefPtr def = NULL;
    char *ret = NULL;
    virConfPtr conf = NULL;
1676
    xenUnifiedPrivatePtr priv = conn->privateData;
1677

E
Eric Blake 已提交
1678 1679
    virCheckFlags(0, NULL);

1680 1681 1682
    if (virConnectDomainXMLToNativeEnsureACL(conn) < 0)
        return NULL;

1683 1684
    if (STRNEQ(format, XEN_CONFIG_FORMAT_XM) &&
        STRNEQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
1685 1686
        virReportError(VIR_ERR_INVALID_ARG,
                       _("unsupported config type %s"), format);
1687 1688 1689
        goto cleanup;
    }

1690
    if (!(def = virDomainDefParseString(xmlData, priv->caps, priv->xmlopt,
1691
                                        1 << VIR_DOMAIN_VIRT_XEN,
1692
                                        VIR_DOMAIN_DEF_PARSE_INACTIVE)))
1693 1694 1695 1696
        goto cleanup;

    if (STREQ(format, XEN_CONFIG_FORMAT_XM)) {
        int len = MAX_CONFIG_SIZE;
M
Markus Groß 已提交
1697
        conf = xenFormatXM(conn, def, priv->xendConfigVersion);
1698 1699 1700
        if (!conf)
            goto cleanup;

1701
        if (VIR_ALLOC_N(ret, len) < 0)
1702 1703 1704 1705 1706 1707 1708
            goto cleanup;

        if (virConfWriteMem(ret, &len, conf) < 0) {
            VIR_FREE(ret);
            goto cleanup;
        }
    } else if (STREQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
M
Markus Groß 已提交
1709
        ret = xenFormatSxpr(conn, def, priv->xendConfigVersion);
1710 1711
    }

1712
 cleanup:
1713 1714 1715 1716 1717 1718 1719
    virDomainDefFree(def);
    if (conf)
        virConfFree(conf);
    return ret;
}


1720
static int
1721 1722 1723 1724 1725 1726 1727 1728
xenUnifiedDomainMigratePrepare(virConnectPtr dconn,
                               char **cookie,
                               int *cookielen,
                               const char *uri_in,
                               char **uri_out,
                               unsigned long flags,
                               const char *dname,
                               unsigned long resource)
1729
{
E
Eric Blake 已提交
1730 1731
    virCheckFlags(XEN_MIGRATION_FLAGS, -1);

1732 1733 1734
    return xenDaemonDomainMigratePrepare(dconn, cookie, cookielen,
                                         uri_in, uri_out,
                                         flags, dname, resource);
1735 1736 1737
}

static int
1738 1739 1740 1741 1742 1743 1744
xenUnifiedDomainMigratePerform(virDomainPtr dom,
                               const char *cookie,
                               int cookielen,
                               const char *uri,
                               unsigned long flags,
                               const char *dname,
                               unsigned long resource)
1745
{
1746 1747 1748
    virDomainDefPtr def = NULL;
    int ret = -1;

E
Eric Blake 已提交
1749 1750
    virCheckFlags(XEN_MIGRATION_FLAGS, -1);

1751 1752 1753
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

1754 1755 1756
    if (virDomainMigratePerformEnsureACL(dom->conn, def) < 0)
        goto cleanup;

1757 1758 1759 1760
    ret = xenDaemonDomainMigratePerform(dom->conn, def,
                                        cookie, cookielen, uri,
                                        flags, dname, resource);

1761
 cleanup:
1762 1763
    virDomainDefFree(def);
    return ret;
1764 1765 1766
}

static virDomainPtr
1767 1768 1769 1770 1771 1772
xenUnifiedDomainMigrateFinish(virConnectPtr dconn,
                              const char *dname,
                              const char *cookie ATTRIBUTE_UNUSED,
                              int cookielen ATTRIBUTE_UNUSED,
                              const char *uri ATTRIBUTE_UNUSED,
                              unsigned long flags)
1773
{
1774 1775 1776 1777
    xenUnifiedPrivatePtr priv = dconn->privateData;
    virDomainPtr ret = NULL;
    virDomainDefPtr minidef = NULL;
    virDomainDefPtr def = NULL;
1778

E
Eric Blake 已提交
1779 1780
    virCheckFlags(XEN_MIGRATION_FLAGS, NULL);

1781 1782
    if (!(minidef = xenGetDomainDefForName(dconn, dname)))
        goto cleanup;
1783

1784 1785 1786
    if (virDomainMigrateFinishEnsureACL(dconn, minidef) < 0)
        goto cleanup;

1787
    if (flags & VIR_MIGRATE_PERSIST_DEST) {
1788 1789
        if (!(def = xenDaemonDomainGetXMLDesc(dconn, minidef, NULL)))
            goto cleanup;
1790

1791 1792 1793 1794 1795 1796
        if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
            if (xenXMDomainDefineXML(dconn, def) < 0)
                goto cleanup;
        } else {
            if (xenDaemonDomainDefineXML(dconn, def) < 0)
                goto cleanup;
1797 1798 1799
        }
    }

1800 1801 1802
    ret = virGetDomain(dconn, minidef->name, minidef->uuid);
    if (ret)
        ret->id = minidef->id;
1803

1804
 cleanup:
1805 1806 1807
    virDomainDefFree(def);
    virDomainDefFree(minidef);
    return ret;
1808 1809
}

1810
static int
1811 1812
xenUnifiedConnectListDefinedDomains(virConnectPtr conn, char **const names,
                                    int maxnames)
1813
{
1814
    xenUnifiedPrivatePtr priv = conn->privateData;
1815

1816 1817 1818
    if (virConnectListDefinedDomainsEnsureACL(conn) < 0)
        return -1;

1819 1820 1821 1822 1823
    if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
        return xenXMListDefinedDomains(conn, names, maxnames);
    } else {
        return xenDaemonListDefinedDomains(conn, names, maxnames);
    }
1824 1825 1826
}

static int
1827
xenUnifiedConnectNumOfDefinedDomains(virConnectPtr conn)
1828
{
1829
    xenUnifiedPrivatePtr priv = conn->privateData;
1830

1831 1832 1833
    if (virConnectNumOfDefinedDomainsEnsureACL(conn) < 0)
        return -1;

1834 1835 1836 1837 1838
    if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
        return xenXMNumOfDefinedDomains(conn);
    } else {
        return xenDaemonNumOfDefinedDomains(conn);
    }
1839 1840 1841
}

static int
1842
xenUnifiedDomainCreateWithFlags(virDomainPtr dom, unsigned int flags)
1843
{
1844
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1845
    int ret = -1;
1846
    virDomainDefPtr def = NULL;
1847
    char *name = NULL;
1848

1849 1850
    virCheckFlags(0, -1);

1851 1852 1853
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

1854 1855 1856
    if (virDomainCreateWithFlagsEnsureACL(dom->conn, def) < 0)
        goto cleanup;

1857
    if (!(name = xenUnifiedDomainManagedSavePath(priv, def)))
1858 1859 1860
        goto cleanup;

    if (virFileExists(name)) {
1861 1862 1863
        ret = xenDaemonDomainRestore(dom->conn, name);
        if (ret == 0)
            unlink(name);
1864 1865 1866
        goto cleanup;
    }

1867
    if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
1868
        ret = xenXMDomainCreate(dom->conn, def);
1869
    else
1870 1871 1872 1873
        ret = xenDaemonDomainCreate(dom->conn, def);

    if (ret >= 0)
        dom->id = def->id;
1874

1875
 cleanup:
1876
    virDomainDefFree(def);
1877 1878
    VIR_FREE(name);
    return ret;
1879 1880
}

1881
static int
1882
xenUnifiedDomainCreate(virDomainPtr dom)
1883 1884 1885 1886
{
    return xenUnifiedDomainCreateWithFlags(dom, 0);
}

1887
static virDomainPtr
1888
xenUnifiedDomainDefineXMLFlags(virConnectPtr conn, const char *xml, unsigned int flags)
1889
{
1890
    xenUnifiedPrivatePtr priv = conn->privateData;
1891 1892
    virDomainDefPtr def = NULL;
    virDomainPtr ret = NULL;
1893
    unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;
1894

1895 1896 1897 1898
    virCheckFlags(VIR_DOMAIN_DEFINE_VALIDATE, NULL);

    if (flags & VIR_DOMAIN_DEFINE_VALIDATE)
        parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE;
1899

1900 1901
    if (!(def = virDomainDefParseString(xml, priv->caps, priv->xmlopt,
                                        1 << VIR_DOMAIN_VIRT_XEN,
1902
                                        parse_flags)))
1903 1904
        goto cleanup;

1905
    if (virDomainDefineXMLFlagsEnsureACL(conn, def) < 0)
1906 1907
        goto cleanup;

1908 1909 1910
    if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
        if (xenXMDomainDefineXML(conn, def) < 0)
            goto cleanup;
1911
        ret = virGetDomain(conn, def->name, def->uuid);
1912 1913 1914 1915
        def = NULL; /* XM driver owns it now */
    } else {
        if (xenDaemonDomainDefineXML(conn, def) < 0)
            goto cleanup;
1916
        ret = virGetDomain(conn, def->name, def->uuid);
1917 1918 1919 1920 1921
    }

    if (ret)
        ret->id = -1;

1922
 cleanup:
1923 1924
    virDomainDefFree(def);
    return ret;
1925 1926
}

1927 1928 1929 1930 1931 1932
static virDomainPtr
xenUnifiedDomainDefineXML(virConnectPtr conn, const char *xml)
{
    return xenUnifiedDomainDefineXMLFlags(conn, xml, 0);
}

1933
static int
1934
xenUnifiedDomainUndefineFlags(virDomainPtr dom, unsigned int flags)
1935
{
1936
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1937 1938
    virDomainDefPtr def = NULL;
    int ret = -1;
1939

1940
    virCheckFlags(0, -1);
1941 1942 1943 1944

    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

1945 1946 1947
    if (virDomainUndefineFlagsEnsureACL(dom->conn, def) < 0)
        goto cleanup;

1948
    if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
1949
        ret = xenXMDomainUndefine(dom->conn, def);
1950
    else
1951 1952
        ret = xenDaemonDomainUndefine(dom->conn, def);

1953
 cleanup:
1954 1955
    virDomainDefFree(def);
    return ret;
1956 1957
}

1958
static int
1959 1960
xenUnifiedDomainUndefine(virDomainPtr dom)
{
1961 1962 1963
    return xenUnifiedDomainUndefineFlags(dom, 0);
}

1964
static int
1965
xenUnifiedDomainAttachDevice(virDomainPtr dom, const char *xml)
1966
{
1967
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1968
    unsigned int flags = VIR_DOMAIN_DEVICE_MODIFY_LIVE;
1969 1970
    virDomainDefPtr def = NULL;
    int ret = -1;
1971

1972 1973 1974 1975 1976
    /*
     * HACK: xend with xendConfigVersion >= 3 does not support changing live
     * config without touching persistent config, we add the extra flag here
     * to make this API work
     */
1977
    if (priv->xendConfigVersion >= XEND_CONFIG_VERSION_3_0_4)
1978
        flags |= VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
1979

1980 1981 1982
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

1983 1984 1985
    if (virDomainAttachDeviceEnsureACL(dom->conn, def) < 0)
        goto cleanup;

1986
    if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
1987
        ret = xenXMDomainAttachDeviceFlags(dom->conn, def, xml, flags);
1988
    else
1989
        ret = xenDaemonAttachDeviceFlags(dom->conn, def, xml, flags);
1990

1991
 cleanup:
1992 1993
    virDomainDefFree(def);
    return ret;
1994 1995 1996
}

static int
1997 1998
xenUnifiedDomainAttachDeviceFlags(virDomainPtr dom, const char *xml,
                                  unsigned int flags)
1999
{
2000
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
2001 2002 2003 2004 2005
    virDomainDefPtr def = NULL;
    int ret = -1;

    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;
2006

2007 2008 2009
    if (virDomainAttachDeviceFlagsEnsureACL(dom->conn, def, flags) < 0)
        goto cleanup;

2010
    if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
2011
        ret = xenXMDomainAttachDeviceFlags(dom->conn, def, xml, flags);
2012
    else
2013 2014
        ret = xenDaemonAttachDeviceFlags(dom->conn, def, xml, flags);

2015
 cleanup:
2016 2017
    virDomainDefFree(def);
    return ret;
2018 2019 2020
}

static int
2021
xenUnifiedDomainDetachDevice(virDomainPtr dom, const char *xml)
2022
{
2023
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
2024
    unsigned int flags = VIR_DOMAIN_DEVICE_MODIFY_LIVE;
2025 2026
    virDomainDefPtr def = NULL;
    int ret = -1;
2027

2028 2029 2030 2031 2032
    /*
     * HACK: xend with xendConfigVersion >= 3 does not support changing live
     * config without touching persistent config, we add the extra flag here
     * to make this API work
     */
2033
    if (priv->xendConfigVersion >= XEND_CONFIG_VERSION_3_0_4)
2034
        flags |= VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
2035

2036 2037 2038
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

2039 2040 2041
    if (virDomainDetachDeviceEnsureACL(dom->conn, def) < 0)
        goto cleanup;

2042
    if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
2043
        ret = xenXMDomainDetachDeviceFlags(dom->conn, def, xml, flags);
2044
    else
2045 2046
        ret = xenDaemonDetachDeviceFlags(dom->conn, def, xml, flags);

2047
 cleanup:
2048 2049
    virDomainDefFree(def);
    return ret;
2050 2051 2052
}

static int
2053 2054
xenUnifiedDomainDetachDeviceFlags(virDomainPtr dom, const char *xml,
                                  unsigned int flags)
2055
{
2056
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
2057 2058 2059 2060 2061
    virDomainDefPtr def = NULL;
    int ret = -1;

    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;
2062

2063 2064 2065
    if (virDomainDetachDeviceFlagsEnsureACL(dom->conn, def, flags) < 0)
        goto cleanup;

2066
    if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
2067
        ret = xenXMDomainDetachDeviceFlags(dom->conn, def, xml, flags);
2068
    else
2069 2070
        ret = xenDaemonDetachDeviceFlags(dom->conn, def, xml, flags);

2071
 cleanup:
2072 2073
    virDomainDefFree(def);
    return ret;
2074 2075
}

2076
static int
2077 2078
xenUnifiedDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml,
                                  unsigned int flags)
2079
{
2080 2081 2082 2083 2084 2085
    virDomainDefPtr def = NULL;
    int ret = -1;

    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

2086 2087 2088
    if (virDomainUpdateDeviceFlagsEnsureACL(dom->conn, def, flags) < 0)
        goto cleanup;

2089 2090
    ret = xenDaemonUpdateDeviceFlags(dom->conn, def, xml, flags);

2091
 cleanup:
2092 2093
    virDomainDefFree(def);
    return ret;
2094 2095
}

2096
static int
2097
xenUnifiedDomainGetAutostart(virDomainPtr dom, int *autostart)
2098
{
2099
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
2100 2101 2102 2103 2104
    virDomainDefPtr def = NULL;
    int ret = -1;

    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;
2105

2106 2107 2108
    if (virDomainGetAutostartEnsureACL(dom->conn, def) < 0)
        goto cleanup;

2109
    if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
2110
        ret = xenXMDomainGetAutostart(def, autostart);
2111
    else
2112 2113
        ret = xenDaemonDomainGetAutostart(dom->conn, def, autostart);

2114
 cleanup:
2115 2116
    virDomainDefFree(def);
    return ret;
2117 2118 2119
}

static int
2120
xenUnifiedDomainSetAutostart(virDomainPtr dom, int autostart)
2121
{
2122
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
2123 2124 2125 2126 2127
    virDomainDefPtr def = NULL;
    int ret = -1;

    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;
2128

2129 2130 2131
    if (virDomainSetAutostartEnsureACL(dom->conn, def) < 0)
        goto cleanup;

2132
    if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
2133
        ret = xenXMDomainSetAutostart(def, autostart);
2134
    else
2135 2136
        ret = xenDaemonDomainSetAutostart(dom->conn, def, autostart);

2137
 cleanup:
2138 2139
    virDomainDefFree(def);
    return ret;
2140 2141
}

2142
static char *
2143
xenUnifiedDomainGetSchedulerType(virDomainPtr dom, int *nparams)
2144
{
2145
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
2146 2147 2148 2149 2150
    virDomainDefPtr def = NULL;
    char *ret = NULL;

    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;
2151

2152 2153 2154
    if (virDomainGetSchedulerTypeEnsureACL(dom->conn, def) < 0)
        goto cleanup;

2155 2156 2157 2158
    if (dom->id < 0) {
        if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("Cannot change scheduler parameters"));
2159
            goto cleanup;
2160
        }
2161
        ret = xenDaemonGetSchedulerType(dom->conn, nparams);
2162
    } else {
2163
        ret = xenHypervisorGetSchedulerType(dom->conn, nparams);
2164
    }
2165

2166
 cleanup:
2167 2168
    virDomainDefFree(def);
    return ret;
2169 2170 2171
}

static int
2172 2173 2174 2175
xenUnifiedDomainGetSchedulerParametersFlags(virDomainPtr dom,
                                            virTypedParameterPtr params,
                                            int *nparams,
                                            unsigned int flags)
2176
{
2177
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
2178 2179
    virDomainDefPtr def = NULL;
    int ret = -1;
2180

2181 2182
    virCheckFlags(0, -1);

2183 2184 2185
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

2186 2187 2188
    if (virDomainGetSchedulerParametersFlagsEnsureACL(dom->conn, def) < 0)
        goto cleanup;

2189 2190 2191 2192
    if (dom->id < 0) {
        if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("Cannot change scheduler parameters"));
2193
            goto cleanup;
2194
        }
2195
        ret = xenDaemonGetSchedulerParameters(dom->conn, def, params, nparams);
2196
    } else {
2197
        ret = xenHypervisorGetSchedulerParameters(dom->conn, def, params, nparams);
2198
    }
2199

2200
 cleanup:
2201 2202
    virDomainDefFree(def);
    return ret;
2203 2204 2205
}

static int
2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216 2217 2218
xenUnifiedDomainGetSchedulerParameters(virDomainPtr dom,
                                       virTypedParameterPtr params,
                                       int *nparams)
{
    return xenUnifiedDomainGetSchedulerParametersFlags(dom, params,
                                                       nparams, 0);
}

static int
xenUnifiedDomainSetSchedulerParametersFlags(virDomainPtr dom,
                                            virTypedParameterPtr params,
                                            int nparams,
                                            unsigned int flags)
2219
{
2220
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
2221 2222
    virDomainDefPtr def = NULL;
    int ret = -1;
2223

2224 2225
    virCheckFlags(0, -1);

2226 2227 2228
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

2229 2230 2231
    if (virDomainSetSchedulerParametersFlagsEnsureACL(dom->conn, def, flags) < 0)
        goto cleanup;

2232 2233 2234 2235
    if (dom->id < 0) {
        if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("Cannot change scheduler parameters"));
2236
            goto cleanup;
2237
        }
2238
        ret = xenDaemonSetSchedulerParameters(dom->conn, def, params, nparams);
2239
    } else {
2240
        ret = xenHypervisorSetSchedulerParameters(dom->conn, def, params, nparams);
2241
    }
2242

2243
 cleanup:
2244 2245
    virDomainDefFree(def);
    return ret;
2246 2247
}

2248 2249 2250 2251 2252 2253 2254 2255 2256
static int
xenUnifiedDomainSetSchedulerParameters(virDomainPtr dom,
                                       virTypedParameterPtr params,
                                       int nparams)
{
    return xenUnifiedDomainSetSchedulerParametersFlags(dom, params,
                                                       nparams, 0);
}

2257
static int
2258
xenUnifiedDomainBlockStats(virDomainPtr dom, const char *path,
2259
                           virDomainBlockStatsPtr stats)
2260
{
2261 2262 2263 2264 2265 2266
    virDomainDefPtr def = NULL;
    int ret = -1;

    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

2267 2268 2269
    if (virDomainBlockStatsEnsureACL(dom->conn, def) < 0)
        goto cleanup;

2270 2271
    ret = xenHypervisorDomainBlockStats(dom->conn, def, path, stats);

2272
 cleanup:
2273 2274
    virDomainDefFree(def);
    return ret;
2275 2276 2277
}

static int
2278
xenUnifiedDomainInterfaceStats(virDomainPtr dom, const char *path,
2279
                               virDomainInterfaceStatsPtr stats)
2280
{
2281 2282 2283 2284 2285 2286
    virDomainDefPtr def = NULL;
    int ret = -1;

    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

2287 2288 2289
    if (virDomainInterfaceStatsEnsureACL(dom->conn, def) < 0)
        goto cleanup;

2290 2291
    ret = xenHypervisorDomainInterfaceStats(def, path, stats);

2292
 cleanup:
2293 2294
    virDomainDefFree(def);
    return ret;
2295 2296
}

R
Richard W.M. Jones 已提交
2297
static int
2298 2299 2300
xenUnifiedDomainBlockPeek(virDomainPtr dom, const char *path,
                          unsigned long long offset, size_t size,
                          void *buffer, unsigned int flags)
R
Richard W.M. Jones 已提交
2301
{
2302
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
2303 2304
    virDomainDefPtr def = NULL;
    int ret = -1;
R
Richard W.M. Jones 已提交
2305

E
Eric Blake 已提交
2306 2307
    virCheckFlags(0, -1);

2308 2309 2310
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

2311 2312 2313
    if (virDomainBlockPeekEnsureACL(dom->conn, def) < 0)
        goto cleanup;

2314
    if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
2315
        ret = xenXMDomainBlockPeek(dom->conn, def, path, offset, size, buffer);
2316
    else
2317 2318
        ret = xenDaemonDomainBlockPeek(dom->conn, def, path, offset, size, buffer);

2319
 cleanup:
2320 2321
    virDomainDefFree(def);
    return ret;
R
Richard W.M. Jones 已提交
2322 2323
}

2324
static int
2325 2326
xenUnifiedNodeGetCellsFreeMemory(virConnectPtr conn, unsigned long long *freeMems,
                                 int startCell, int maxCells)
2327
{
2328 2329 2330
    if (virNodeGetCellsFreeMemoryEnsureACL(conn) < 0)
        return 0;

2331 2332
    return xenHypervisorNodeGetCellsFreeMemory(conn, freeMems,
                                               startCell, maxCells);
2333 2334
}

2335
static unsigned long long
2336
xenUnifiedNodeGetFreeMemory(virConnectPtr conn)
2337 2338 2339
{
    unsigned long long freeMem = 0;

2340 2341 2342
    if (virNodeGetFreeMemoryEnsureACL(conn) < 0)
        return 0;

2343 2344 2345
    if (xenHypervisorNodeGetCellsFreeMemory(conn, &freeMem, -1, 1) < 0)
        return 0;
    return freeMem;
2346 2347
}

2348

2349
static int
2350 2351 2352 2353
xenUnifiedConnectDomainEventRegister(virConnectPtr conn,
                                     virConnectDomainEventCallback callback,
                                     void *opaque,
                                     virFreeCallback freefunc)
2354
{
2355
    xenUnifiedPrivatePtr priv = conn->privateData;
2356
    int ret = 0;
2357 2358 2359 2360

    if (virConnectDomainEventRegisterEnsureACL(conn) < 0)
        return -1;

D
Daniel P. Berrange 已提交
2361
    xenUnifiedLock(priv);
2362

2363
    if (priv->xsWatch == -1) {
2364
        virReportUnsupportedError();
D
Daniel P. Berrange 已提交
2365
        xenUnifiedUnlock(priv);
2366 2367 2368
        return -1;
    }

2369 2370 2371
    if (virDomainEventStateRegister(conn, priv->domainEvents,
                                    callback, opaque, freefunc) < 0)
        ret = -1;
2372

D
Daniel P. Berrange 已提交
2373
    xenUnifiedUnlock(priv);
2374
    return ret;
2375 2376
}

2377

2378
static int
2379 2380
xenUnifiedConnectDomainEventDeregister(virConnectPtr conn,
                                       virConnectDomainEventCallback callback)
2381
{
2382
    int ret = 0;
2383
    xenUnifiedPrivatePtr priv = conn->privateData;
2384 2385 2386 2387

    if (virConnectDomainEventDeregisterEnsureACL(conn) < 0)
        return -1;

D
Daniel P. Berrange 已提交
2388 2389
    xenUnifiedLock(priv);

2390
    if (priv->xsWatch == -1) {
2391
        virReportUnsupportedError();
D
Daniel P. Berrange 已提交
2392
        xenUnifiedUnlock(priv);
2393 2394 2395
        return -1;
    }

2396 2397 2398 2399
    if (virDomainEventStateDeregister(conn,
                                      priv->domainEvents,
                                      callback) < 0)
        ret = -1;
2400

D
Daniel P. Berrange 已提交
2401
    xenUnifiedUnlock(priv);
2402 2403 2404
    return ret;
}

2405

2406
static int
2407 2408 2409 2410 2411 2412
xenUnifiedConnectDomainEventRegisterAny(virConnectPtr conn,
                                        virDomainPtr dom,
                                        int eventID,
                                        virConnectDomainEventGenericCallback callback,
                                        void *opaque,
                                        virFreeCallback freefunc)
2413
{
2414
    xenUnifiedPrivatePtr priv = conn->privateData;
2415
    int ret;
2416 2417 2418 2419

    if (virConnectDomainEventRegisterAnyEnsureACL(conn) < 0)
        return -1;

2420 2421 2422
    xenUnifiedLock(priv);

    if (priv->xsWatch == -1) {
2423
        virReportUnsupportedError();
2424 2425 2426 2427
        xenUnifiedUnlock(priv);
        return -1;
    }

2428 2429 2430
    if (virDomainEventStateRegisterID(conn, priv->domainEvents,
                                      dom, eventID,
                                      callback, opaque, freefunc, &ret) < 0)
2431
        ret = -1;
2432 2433

    xenUnifiedUnlock(priv);
2434
    return ret;
2435 2436 2437
}

static int
2438 2439
xenUnifiedConnectDomainEventDeregisterAny(virConnectPtr conn,
                                          int callbackID)
2440
{
2441
    int ret = 0;
2442
    xenUnifiedPrivatePtr priv = conn->privateData;
2443 2444 2445 2446

    if (virConnectDomainEventDeregisterAnyEnsureACL(conn) < 0)
        return -1;

2447 2448 2449
    xenUnifiedLock(priv);

    if (priv->xsWatch == -1) {
2450
        virReportUnsupportedError();
2451 2452 2453 2454
        xenUnifiedUnlock(priv);
        return -1;
    }

2455 2456 2457 2458
    if (virObjectEventStateDeregisterID(conn,
                                        priv->domainEvents,
                                        callbackID) < 0)
        ret = -1;
2459 2460 2461 2462 2463 2464

    xenUnifiedUnlock(priv);
    return ret;
}


2465
static int
2466
xenUnifiedNodeDeviceGetPCIInfo(virNodeDevicePtr dev,
2467 2468 2469 2470
                               unsigned *domain,
                               unsigned *bus,
                               unsigned *slot,
                               unsigned *function)
2471 2472 2473 2474 2475 2476 2477 2478 2479 2480
{
    virNodeDeviceDefPtr def = NULL;
    virNodeDevCapsDefPtr cap;
    char *xml = NULL;
    int ret = -1;

    xml = virNodeDeviceGetXMLDesc(dev, 0);
    if (!xml)
        goto out;

2481
    def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL);
2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498
    if (!def)
        goto out;

    cap = def->caps;
    while (cap) {
        if (cap->type == VIR_NODE_DEV_CAP_PCI_DEV) {
            *domain   = cap->data.pci_dev.domain;
            *bus      = cap->data.pci_dev.bus;
            *slot     = cap->data.pci_dev.slot;
            *function = cap->data.pci_dev.function;
            break;
        }

        cap = cap->next;
    }

    if (!cap) {
2499 2500
        virReportError(VIR_ERR_INVALID_ARG,
                       _("device %s is not a PCI device"), dev->name);
2501 2502 2503 2504
        goto out;
    }

    ret = 0;
2505
 out:
2506 2507 2508 2509 2510 2511
    virNodeDeviceDefFree(def);
    VIR_FREE(xml);
    return ret;
}

static int
2512 2513 2514
xenUnifiedNodeDeviceDetachFlags(virNodeDevicePtr dev,
                                const char *driverName,
                                unsigned int flags)
2515
{
2516
    virPCIDevicePtr pci;
2517 2518 2519
    unsigned domain, bus, slot, function;
    int ret = -1;

2520 2521
    virCheckFlags(0, -1);

2522
    if (xenUnifiedNodeDeviceGetPCIInfo(dev, &domain, &bus, &slot, &function) < 0)
2523 2524
        return -1;

2525
    pci = virPCIDeviceNew(domain, bus, slot, function);
2526 2527 2528
    if (!pci)
        return -1;

2529
    if (!driverName) {
2530 2531
        if (virPCIDeviceSetStubDriver(pci, "pciback") < 0)
            goto out;
2532 2533 2534 2535 2536 2537
    } else {
        virReportError(VIR_ERR_INVALID_ARG,
                       _("unknown driver name '%s'"), driverName);
        goto out;
    }

2538
    if (virPCIDeviceDetach(pci, NULL, NULL) < 0)
2539 2540 2541
        goto out;

    ret = 0;
2542
 out:
2543
    virPCIDeviceFree(pci);
2544 2545 2546
    return ret;
}

2547 2548 2549 2550 2551 2552
static int
xenUnifiedNodeDeviceDettach(virNodeDevicePtr dev)
{
    return xenUnifiedNodeDeviceDetachFlags(dev, NULL, 0);
}

2553
static int
2554
xenUnifiedNodeDeviceAssignedDomainId(virNodeDevicePtr dev)
2555 2556
{
    int numdomains;
2557 2558
    int ret = -1;
    size_t i;
2559 2560 2561 2562 2563 2564 2565 2566
    int *ids = NULL;
    char *bdf = NULL;
    char *xref = NULL;
    unsigned int domain, bus, slot, function;
    virConnectPtr conn = dev->conn;
    xenUnifiedPrivatePtr priv = conn->privateData;

    /* Get active domains */
2567
    numdomains = xenUnifiedConnectNumOfDomains(conn);
2568
    if (numdomains < 0)
2569
        return ret;
2570
    if (numdomains > 0) {
2571
        if (VIR_ALLOC_N(ids, numdomains) < 0)
2572
            goto out;
2573
        if ((numdomains = xenUnifiedConnectListDomains(conn, &ids[0], numdomains)) < 0)
2574 2575 2576 2577
            goto out;
    }

    /* Get pci bdf */
2578
    if (xenUnifiedNodeDeviceGetPCIInfo(dev, &domain, &bus, &slot, &function) < 0)
2579 2580 2581
        goto out;

    if (virAsprintf(&bdf, "%04x:%02x:%02x.%0x",
2582
                    domain, bus, slot, function) < 0)
2583 2584 2585 2586
        goto out;

    xenUnifiedLock(priv);
    /* Check if bdf is assigned to one of active domains */
2587
    for (i = 0; i < numdomains; i++) {
2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599
        xref = xenStoreDomainGetPCIID(conn, ids[i], bdf);
        if (xref == NULL) {
            continue;
        } else {
            ret = ids[i];
            break;
        }
    }
    xenUnifiedUnlock(priv);

    VIR_FREE(xref);
    VIR_FREE(bdf);
2600
 out:
2601 2602 2603 2604 2605
    VIR_FREE(ids);

    return ret;
}

2606
static int
2607
xenUnifiedNodeDeviceReAttach(virNodeDevicePtr dev)
2608
{
2609
    virPCIDevicePtr pci;
2610 2611
    unsigned domain, bus, slot, function;
    int ret = -1;
2612
    int domid;
2613

2614
    if (xenUnifiedNodeDeviceGetPCIInfo(dev, &domain, &bus, &slot, &function) < 0)
2615 2616
        return -1;

2617
    pci = virPCIDeviceNew(domain, bus, slot, function);
2618 2619 2620
    if (!pci)
        return -1;

2621 2622
    /* Check if device is assigned to an active guest */
    if ((domid = xenUnifiedNodeDeviceAssignedDomainId(dev)) >= 0) {
2623 2624 2625
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Device %s has been assigned to guest %d"),
                       dev->name, domid);
2626 2627 2628
        goto out;
    }

2629
    if (virPCIDeviceReattach(pci, NULL, NULL) < 0)
2630 2631 2632
        goto out;

    ret = 0;
2633
 out:
2634
    virPCIDeviceFree(pci);
2635 2636 2637 2638
    return ret;
}

static int
2639
xenUnifiedNodeDeviceReset(virNodeDevicePtr dev)
2640
{
2641
    virPCIDevicePtr pci;
2642 2643 2644
    unsigned domain, bus, slot, function;
    int ret = -1;

2645
    if (xenUnifiedNodeDeviceGetPCIInfo(dev, &domain, &bus, &slot, &function) < 0)
2646 2647
        return -1;

2648
    pci = virPCIDeviceNew(domain, bus, slot, function);
2649 2650 2651
    if (!pci)
        return -1;

2652
    if (virPCIDeviceReset(pci, NULL, NULL) < 0)
2653 2654 2655
        goto out;

    ret = 0;
2656
 out:
2657
    virPCIDeviceFree(pci);
2658 2659 2660 2661
    return ret;
}


2662 2663
static int
xenUnifiedDomainOpenConsole(virDomainPtr dom,
2664
                            const char *dev_name,
2665 2666 2667 2668 2669 2670 2671 2672 2673 2674
                            virStreamPtr st,
                            unsigned int flags)
{
    virDomainDefPtr def = NULL;
    int ret = -1;
    virDomainChrDefPtr chr = NULL;

    virCheckFlags(0, -1);

    if (dom->id == -1) {
2675 2676
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
2677 2678 2679
        goto cleanup;
    }

2680
    if (dev_name) {
2681
        /* XXX support device aliases in future */
2682 2683
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("Named device aliases are not supported"));
2684 2685 2686 2687 2688 2689 2690
        goto cleanup;
    }

    def = xenDaemonDomainFetch(dom->conn, dom->id, dom->name, NULL);
    if (!def)
        goto cleanup;

2691 2692
    if (def->nconsoles)
        chr = def->consoles[0];
2693 2694 2695 2696
    else if (def->nserials)
        chr = def->serials[0];

    if (!chr) {
2697 2698
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("cannot find default console device"));
2699 2700 2701
        goto cleanup;
    }

2702
    if (chr->source.type != VIR_DOMAIN_CHR_TYPE_PTY) {
2703 2704
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("character device %s is not using a PTY"), dev_name);
2705 2706 2707
        goto cleanup;
    }

2708
    if (virFDStreamOpenFile(st, chr->source.data.file.path,
E
Eric Blake 已提交
2709
                            0, 0, O_RDWR) < 0)
2710 2711 2712
        goto cleanup;

    ret = 0;
2713
 cleanup:
2714 2715 2716
    virDomainDefFree(def);
    return ret;
}
2717 2718

static int
2719
xenUnifiedNodeGetMemoryParameters(virConnectPtr conn,
2720 2721 2722 2723
                                  virTypedParameterPtr params,
                                  int *nparams,
                                  unsigned int flags)
{
2724 2725 2726
    if (virNodeGetMemoryParametersEnsureACL(conn) < 0)
        return -1;

2727 2728 2729 2730 2731
    return nodeGetMemoryParameters(params, nparams, flags);
}


static int
2732
xenUnifiedNodeSetMemoryParameters(virConnectPtr conn,
2733 2734 2735 2736
                                  virTypedParameterPtr params,
                                  int nparams,
                                  unsigned int flags)
{
2737 2738 2739
    if (virNodeSetMemoryParametersEnsureACL(conn) < 0)
        return -1;

2740 2741 2742
    return nodeSetMemoryParameters(params, nparams, flags);
}

2743 2744

static int
2745
xenUnifiedNodeSuspendForDuration(virConnectPtr conn,
2746 2747 2748 2749
                                 unsigned int target,
                                 unsigned long long duration,
                                 unsigned int flags)
{
2750 2751 2752
    if (virNodeSuspendForDurationEnsureACL(conn) < 0)
        return -1;

2753 2754 2755 2756
    return nodeSuspendForDuration(target, duration, flags);
}


E
Eric Blake 已提交
2757
/*----- Register with libvirt.c, and initialize Xen drivers. -----*/
2758 2759

/* The interface which we export upwards to libvirt.c. */
2760
static virHypervisorDriver xenUnifiedHypervisorDriver = {
2761
    .name = "Xen",
2762 2763 2764 2765 2766
    .connectOpen = xenUnifiedConnectOpen, /* 0.0.3 */
    .connectClose = xenUnifiedConnectClose, /* 0.0.3 */
    .connectSupportsFeature = xenUnifiedConnectSupportsFeature, /* 0.3.2 */
    .connectGetType = xenUnifiedConnectGetType, /* 0.0.3 */
    .connectGetVersion = xenUnifiedConnectGetVersion, /* 0.0.3 */
2767
    .connectGetHostname = xenUnifiedConnectGetHostname, /* 0.7.3 */
2768
    .connectGetSysinfo = xenUnifiedConnectGetSysinfo, /* 1.1.0 */
2769
    .connectGetMaxVcpus = xenUnifiedConnectGetMaxVcpus, /* 0.2.1 */
2770
    .nodeGetInfo = xenUnifiedNodeGetInfo, /* 0.1.0 */
2771 2772 2773
    .connectGetCapabilities = xenUnifiedConnectGetCapabilities, /* 0.2.1 */
    .connectListDomains = xenUnifiedConnectListDomains, /* 0.0.3 */
    .connectNumOfDomains = xenUnifiedConnectNumOfDomains, /* 0.0.3 */
2774 2775 2776 2777 2778 2779 2780
    .domainCreateXML = xenUnifiedDomainCreateXML, /* 0.0.3 */
    .domainLookupByID = xenUnifiedDomainLookupByID, /* 0.0.3 */
    .domainLookupByUUID = xenUnifiedDomainLookupByUUID, /* 0.0.5 */
    .domainLookupByName = xenUnifiedDomainLookupByName, /* 0.0.3 */
    .domainSuspend = xenUnifiedDomainSuspend, /* 0.0.3 */
    .domainResume = xenUnifiedDomainResume, /* 0.0.3 */
    .domainShutdown = xenUnifiedDomainShutdown, /* 0.0.3 */
2781
    .domainShutdownFlags = xenUnifiedDomainShutdownFlags, /* 0.9.10 */
2782 2783
    .domainReboot = xenUnifiedDomainReboot, /* 0.1.0 */
    .domainDestroy = xenUnifiedDomainDestroy, /* 0.0.3 */
2784
    .domainDestroyFlags = xenUnifiedDomainDestroyFlags, /* 0.9.4 */
2785 2786 2787 2788 2789 2790 2791
    .domainGetOSType = xenUnifiedDomainGetOSType, /* 0.0.3 */
    .domainGetMaxMemory = xenUnifiedDomainGetMaxMemory, /* 0.0.3 */
    .domainSetMaxMemory = xenUnifiedDomainSetMaxMemory, /* 0.0.3 */
    .domainSetMemory = xenUnifiedDomainSetMemory, /* 0.1.1 */
    .domainGetInfo = xenUnifiedDomainGetInfo, /* 0.0.3 */
    .domainGetState = xenUnifiedDomainGetState, /* 0.9.2 */
    .domainSave = xenUnifiedDomainSave, /* 0.0.3 */
2792
    .domainSaveFlags = xenUnifiedDomainSaveFlags, /* 0.9.4 */
2793 2794 2795
    .domainManagedSave = xenUnifiedDomainManagedSave, /* 1.0.1 */
    .domainHasManagedSaveImage = xenUnifiedDomainHasManagedSaveImage, /* 1.0.1 */
    .domainManagedSaveRemove = xenUnifiedDomainManagedSaveRemove, /* 1.0.1 */
2796
    .domainRestore = xenUnifiedDomainRestore, /* 0.0.3 */
2797
    .domainRestoreFlags = xenUnifiedDomainRestoreFlags, /* 0.9.4 */
2798 2799 2800 2801 2802 2803 2804 2805
    .domainCoreDump = xenUnifiedDomainCoreDump, /* 0.1.9 */
    .domainSetVcpus = xenUnifiedDomainSetVcpus, /* 0.1.4 */
    .domainSetVcpusFlags = xenUnifiedDomainSetVcpusFlags, /* 0.8.5 */
    .domainGetVcpusFlags = xenUnifiedDomainGetVcpusFlags, /* 0.8.5 */
    .domainPinVcpu = xenUnifiedDomainPinVcpu, /* 0.1.4 */
    .domainGetVcpus = xenUnifiedDomainGetVcpus, /* 0.1.4 */
    .domainGetMaxVcpus = xenUnifiedDomainGetMaxVcpus, /* 0.2.1 */
    .domainGetXMLDesc = xenUnifiedDomainGetXMLDesc, /* 0.0.3 */
2806 2807 2808 2809
    .connectDomainXMLFromNative = xenUnifiedConnectDomainXMLFromNative, /* 0.6.4 */
    .connectDomainXMLToNative = xenUnifiedConnectDomainXMLToNative, /* 0.6.4 */
    .connectListDefinedDomains = xenUnifiedConnectListDefinedDomains, /* 0.1.1 */
    .connectNumOfDefinedDomains = xenUnifiedConnectNumOfDefinedDomains, /* 0.1.5 */
2810 2811 2812
    .domainCreate = xenUnifiedDomainCreate, /* 0.1.1 */
    .domainCreateWithFlags = xenUnifiedDomainCreateWithFlags, /* 0.8.2 */
    .domainDefineXML = xenUnifiedDomainDefineXML, /* 0.1.1 */
2813
    .domainDefineXMLFlags = xenUnifiedDomainDefineXMLFlags, /* 1.2.12 */
2814
    .domainUndefine = xenUnifiedDomainUndefine, /* 0.1.1 */
2815
    .domainUndefineFlags = xenUnifiedDomainUndefineFlags, /* 0.9.4 */
2816 2817 2818 2819 2820 2821 2822 2823 2824
    .domainAttachDevice = xenUnifiedDomainAttachDevice, /* 0.1.9 */
    .domainAttachDeviceFlags = xenUnifiedDomainAttachDeviceFlags, /* 0.7.7 */
    .domainDetachDevice = xenUnifiedDomainDetachDevice, /* 0.1.9 */
    .domainDetachDeviceFlags = xenUnifiedDomainDetachDeviceFlags, /* 0.7.7 */
    .domainUpdateDeviceFlags = xenUnifiedDomainUpdateDeviceFlags, /* 0.8.0 */
    .domainGetAutostart = xenUnifiedDomainGetAutostart, /* 0.4.4 */
    .domainSetAutostart = xenUnifiedDomainSetAutostart, /* 0.4.4 */
    .domainGetSchedulerType = xenUnifiedDomainGetSchedulerType, /* 0.2.3 */
    .domainGetSchedulerParameters = xenUnifiedDomainGetSchedulerParameters, /* 0.2.3 */
2825
    .domainGetSchedulerParametersFlags = xenUnifiedDomainGetSchedulerParametersFlags, /* 0.9.2 */
2826
    .domainSetSchedulerParameters = xenUnifiedDomainSetSchedulerParameters, /* 0.2.3 */
2827
    .domainSetSchedulerParametersFlags = xenUnifiedDomainSetSchedulerParametersFlags, /* 0.9.2 */
2828 2829 2830 2831 2832 2833 2834 2835
    .domainMigratePrepare = xenUnifiedDomainMigratePrepare, /* 0.3.2 */
    .domainMigratePerform = xenUnifiedDomainMigratePerform, /* 0.3.2 */
    .domainMigrateFinish = xenUnifiedDomainMigrateFinish, /* 0.3.2 */
    .domainBlockStats = xenUnifiedDomainBlockStats, /* 0.3.2 */
    .domainInterfaceStats = xenUnifiedDomainInterfaceStats, /* 0.3.2 */
    .domainBlockPeek = xenUnifiedDomainBlockPeek, /* 0.4.4 */
    .nodeGetCellsFreeMemory = xenUnifiedNodeGetCellsFreeMemory, /* 0.3.3 */
    .nodeGetFreeMemory = xenUnifiedNodeGetFreeMemory, /* 0.3.3 */
2836 2837
    .connectDomainEventRegister = xenUnifiedConnectDomainEventRegister, /* 0.5.0 */
    .connectDomainEventDeregister = xenUnifiedConnectDomainEventDeregister, /* 0.5.0 */
2838
    .nodeDeviceDettach = xenUnifiedNodeDeviceDettach, /* 0.6.1 */
2839
    .nodeDeviceDetachFlags = xenUnifiedNodeDeviceDetachFlags, /* 1.0.5 */
2840 2841
    .nodeDeviceReAttach = xenUnifiedNodeDeviceReAttach, /* 0.6.1 */
    .nodeDeviceReset = xenUnifiedNodeDeviceReset, /* 0.6.1 */
2842 2843
    .connectIsEncrypted = xenUnifiedConnectIsEncrypted, /* 0.7.3 */
    .connectIsSecure = xenUnifiedConnectIsSecure, /* 0.7.3 */
2844 2845 2846
    .domainIsActive = xenUnifiedDomainIsActive, /* 0.7.3 */
    .domainIsPersistent = xenUnifiedDomainIsPersistent, /* 0.7.3 */
    .domainIsUpdated = xenUnifiedDomainIsUpdated, /* 0.8.6 */
2847 2848
    .connectDomainEventRegisterAny = xenUnifiedConnectDomainEventRegisterAny, /* 0.8.0 */
    .connectDomainEventDeregisterAny = xenUnifiedConnectDomainEventDeregisterAny, /* 0.8.0 */
2849
    .domainOpenConsole = xenUnifiedDomainOpenConsole, /* 0.8.6 */
2850
    .connectIsAlive = xenUnifiedConnectIsAlive, /* 0.9.8 */
2851
    .nodeSuspendForDuration = xenUnifiedNodeSuspendForDuration, /* 0.9.8 */
2852 2853
    .nodeGetMemoryParameters = xenUnifiedNodeGetMemoryParameters, /* 0.10.2 */
    .nodeSetMemoryParameters = xenUnifiedNodeSetMemoryParameters, /* 0.10.2 */
2854 2855
};

2856 2857 2858 2859 2860

static virConnectDriver xenUnifiedConnectDriver = {
    .hypervisorDriver = &xenUnifiedHypervisorDriver,
};

2861
/**
2862
 * xenRegister:
2863 2864 2865 2866 2867
 *
 * Register xen related drivers
 *
 * Returns the driver priority or -1 in case of error.
 */
2868
int
2869
xenRegister(void)
2870
{
2871
    if (virRegisterStateDriver(&state_driver) == -1) return -1;
J
John Levon 已提交
2872

2873 2874
    return virRegisterConnectDriver(&xenUnifiedConnectDriver,
                                    true);
2875 2876
}

2877 2878 2879 2880 2881 2882 2883 2884
/**
 * xenUnifiedDomainInfoListFree:
 *
 * Free the Domain Info List
 */
void
xenUnifiedDomainInfoListFree(xenUnifiedDomainInfoListPtr list)
{
2885
    size_t i;
J
John Levon 已提交
2886 2887 2888 2889

    if (list == NULL)
        return;

2890
    for (i = 0; i < list->count; i++) {
2891 2892 2893
        VIR_FREE(list->doms[i]->name);
        VIR_FREE(list->doms[i]);
    }
2894
    VIR_FREE(list->doms);
2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913
    VIR_FREE(list);
}

/**
 * xenUnifiedAddDomainInfo:
 *
 * Add name and uuid to the domain info list
 *
 * Returns: 0 on success, -1 on failure
 */
int
xenUnifiedAddDomainInfo(xenUnifiedDomainInfoListPtr list,
                        int id, char *name,
                        unsigned char *uuid)
{
    xenUnifiedDomainInfoPtr info;
    int n;

    /* check if we already have this callback on our list */
2914
    for (n = 0; n < list->count; n++) {
2915 2916
        if (STREQ(list->doms[n]->name, name) &&
            !memcmp(list->doms[n]->uuid, uuid, VIR_UUID_BUFLEN)) {
2917
            VIR_DEBUG("WARNING: dom already tracked");
2918 2919 2920 2921 2922
            return -1;
        }
    }

    if (VIR_ALLOC(info) < 0)
2923
        goto error;
2924 2925
    if (VIR_STRDUP(info->name, name) < 0)
        goto error;
2926 2927 2928 2929 2930

    memcpy(info->uuid, uuid, VIR_UUID_BUFLEN);
    info->id = id;

    /* Make space on list */
2931
    if (VIR_APPEND_ELEMENT(list->doms, list->count, info) < 0)
2932
        goto error;
2933 2934

    return 0;
2935
 error:
2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953
    if (info)
        VIR_FREE(info->name);
    VIR_FREE(info);
    return -1;
}

/**
 * xenUnifiedRemoveDomainInfo:
 *
 * Removes name and uuid to the domain info list
 *
 * Returns: 0 on success, -1 on failure
 */
int
xenUnifiedRemoveDomainInfo(xenUnifiedDomainInfoListPtr list,
                           int id, char *name,
                           unsigned char *uuid)
{
2954
    size_t i;
2955
    for (i = 0; i < list->count; i++) {
2956
        if (list->doms[i]->id == id &&
2957 2958 2959 2960 2961 2962
            STREQ(list->doms[i]->name, name) &&
            !memcmp(list->doms[i]->uuid, uuid, VIR_UUID_BUFLEN)) {

            VIR_FREE(list->doms[i]->name);
            VIR_FREE(list->doms[i]);

2963
            VIR_DELETE_ELEMENT(list->doms, i, list->count);
2964 2965 2966 2967 2968 2969
            return 0;
        }
    }
    return -1;
}

2970

2971 2972
/**
 * xenUnifiedDomainEventDispatch:
D
Daniel P. Berrange 已提交
2973 2974
 * @priv: the connection to dispatch events on
 * @event: the event to dispatch
2975 2976 2977
 *
 * Dispatch domain events to registered callbacks
 *
D
Daniel P. Berrange 已提交
2978 2979
 * The caller must hold the lock in 'priv' before invoking
 *
2980
 */
2981
void xenUnifiedDomainEventDispatch(xenUnifiedPrivatePtr priv,
2982
                                    virObjectEventPtr event)
2983
{
D
Daniel P. Berrange 已提交
2984
    if (!priv)
2985
        return;
2986

2987
    virObjectEventStateQueue(priv->domainEvents, event);
D
Daniel P. Berrange 已提交
2988 2989 2990 2991 2992 2993 2994 2995 2996 2997
}

void xenUnifiedLock(xenUnifiedPrivatePtr priv)
{
    virMutexLock(&priv->lock);
}

void xenUnifiedUnlock(xenUnifiedPrivatePtr priv)
{
    virMutexUnlock(&priv->lock);
2998
}