xen_driver.c 80.8 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++) {
235 236 237
                bool used;
                ignore_value(virBitmapGetBit(cpulist, m, &used));
                if ((!used) &&
238
                    (VIR_CPU_USABLE(cpumap, cpumaplen, n, m))) {
239
                    ignore_value(virBitmapSetBit(cpulist, m));
240 241
                    nb++;
                    /* if all CPU are used just return NULL */
D
Daniel P. Berrange 已提交
242
                    if (nb == priv->nbNodeCpus)
243 244 245 246 247
                        goto done;

                }
            }
        }
248
        res = virBitmapFormat(cpulist);
249 250
    }

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

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

    return 0;
}

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

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

285 286 287 288 289 290 291 292 293 294 295
/*----- 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.
 */

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

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

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

320 321 322 323 324 325 326 327
    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 已提交
328 329 330 331 332

    return ret;
}
#endif

333

334 335
static int
xenDomainDeviceDefPostParse(virDomainDeviceDefPtr dev,
336
                            const virDomainDef *def,
337 338 339 340 341 342 343 344 345
                            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;

346 347 348 349 350 351 352 353 354 355
    /* 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;
    }

356 357 358 359 360
    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:
361
            dev->data.video->vram = 16 * 1024;
362 363 364 365 366 367 368 369 370 371 372 373 374
        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;
        }
    }

375 376 377 378 379 380 381 382 383
    return 0;
}


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

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

393 394 395 396
    return 0;
}


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

403

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


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

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

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

429 430 431 432 433 434 435
#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

436
        if (!(conn->uri = virURIParse("xen:///")))
437
            return VIR_DRV_OPEN_ERROR;
438 439 440 441 442 443 444
    } 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;

445 446 447 448 449 450
#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
451 452 453 454 455

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

462 463 464 465 466 467
            /* 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 {
468
            return VIR_DRV_OPEN_DECLINED;
469 470
        }
    }
471

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

475 476 477
    if (virConnectOpenEnsureACL(conn) < 0)
        return VIR_DRV_OPEN_ERROR;

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

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

495 496 497 498 499
    priv->handle = -1;
    priv->xendConfigVersion = -1;
    priv->xshandle = NULL;


500 501 502 503 504 505
    /* 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;
506

507
    /* XenD is required to succeed */
508
    VIR_DEBUG("Trying XenD sub-driver");
509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527
    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;
528

D
Daniel P. Berrange 已提交
529 530
    xenNumaInit(conn);

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

536
    if (!(priv->xmlopt = xenDomainXMLConfInit()))
537
        goto error;
538

539
#if WITH_XEN_INOTIFY
540 541 542 543 544
    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;
545 546
#endif

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

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

556
    return VIR_DRV_OPEN_SUCCESS;
557

558
 error:
559
    VIR_DEBUG("Failed to activate a mandatory sub-driver");
560 561 562 563 564 565 566 567 568 569 570 571
#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 已提交
572
    virMutexDestroy(&priv->lock);
573
    VIR_FREE(priv->saveDir);
574
    VIR_FREE(priv);
D
Daniel P. Berrange 已提交
575
    conn->privateData = NULL;
576
    return VIR_DRV_OPEN_ERROR;
577 578 579
}

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

584
    virObjectUnref(priv->caps);
585
    virObjectUnref(priv->xmlopt);
586
    virObjectEventStateFree(priv->domainEvents);
587

588 589 590 591 592 593 594 595 596 597 598 599
#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);
600

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

605
    return 0;
606 607
}

608 609 610 611 612 613 614 615 616 617 618

#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;
}


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

625
    return "Xen";
626 627
}

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

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

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

650
    return xenHypervisorGetVersion(conn, hvVer);
651 652
}

653

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

659 660 661
    return virGetHostname();
}

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

    virCheckFlags(0, NULL);

670 671 672
    if (virConnectGetSysinfoEnsureACL(conn) < 0)
        return NULL;

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

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

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

static int
693
xenUnifiedConnectIsSecure(virConnectPtr conn)
694
{
695
    xenUnifiedPrivatePtr priv = conn->privateData;
696 697 698 699 700 701 702 703 704 705
    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;
}

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

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

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

724
    return xenHypervisorGetMaxVcpus(conn, type);
725 726 727
}

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

733
    return xenDaemonNodeGetInfo(conn, info);
734 735 736
}

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

741 742 743
    if (virConnectGetCapabilitiesEnsureACL(conn) < 0)
        return NULL;

744
    return virCapabilitiesFormatXML(priv->caps);
745 746 747
}

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

753
    return xenStoreListDomains(conn, ids, maxids);
754 755 756
}

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

762
    return xenStoreNumOfDomains(conn);
763 764 765
}

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

774
    virCheckFlags(0, NULL);
775

776 777
    if (!(def = virDomainDefParseString(xml, priv->caps, priv->xmlopt,
                                        1 << VIR_DOMAIN_VIRT_XEN,
778
                                        VIR_DOMAIN_DEF_PARSE_INACTIVE)))
779 780
        goto cleanup;

781 782 783
    if (virDomainCreateXMLEnsureACL(conn, def) < 0)
        goto cleanup;

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

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

791
 cleanup:
792 793
    virDomainDefFree(def);
    return ret;
794 795 796
}

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

802 803
    if (!(def = xenGetDomainDefForID(conn, id)))
        goto cleanup;
804

805 806 807
    if (virDomainLookupByIDEnsureACL(conn, def) < 0)
        goto cleanup;

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

811 812
    ret->id = def->id;

813
 cleanup:
814
    virDomainDefFree(def);
815
    return ret;
816 817 818
}

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

825 826
    if (!(def = xenGetDomainDefForUUID(conn, uuid)))
        goto cleanup;
827

828 829 830
    if (virDomainLookupByUUIDEnsureACL(conn, def) < 0)
        goto cleanup;

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

834
    ret->id = def->id;
835

836
 cleanup:
837
    virDomainDefFree(def);
838
    return ret;
839 840 841
}

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

848 849
    if (!(def = xenGetDomainDefForName(conn, name)))
        goto cleanup;
850

851 852 853
    if (virDomainLookupByNameEnsureACL(conn, def) < 0)
        goto cleanup;

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

857
    ret->id = def->id;
858

859
 cleanup:
860
    virDomainDefFree(def);
861
    return ret;
862 863
}

864 865 866 867

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

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

874
    ret = def->id == -1 ? 0 : 1;
875

876
 cleanup:
877
    virDomainDefFree(def);
878 879 880 881
    return ret;
}

static int
882
xenUnifiedDomainIsPersistent(virDomainPtr dom)
883
{
884
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
885
    virDomainDefPtr def = NULL;
886 887 888 889 890
    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 */
891 892
        def = xenXMDomainLookupByUUID(dom->conn, dom->uuid);
        if (def)
893 894 895 896 897
            ret = 1;
        else
            ret = 0;
    } else {
        /* New Xen with inactive domain management */
898 899 900
        def = xenDaemonLookupByUUID(dom->conn, dom->uuid);
        if (def) {
            if (def->id == -1) {
901 902 903 904 905 906 907 908 909
                /* 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);
910
                if (virAsprintf(&path, "%s/%s", XEND_DOMAINS_DIR, uuidstr) < 0)
911
                    goto cleanup;
912 913 914 915
                if (access(path, R_OK) == 0)
                    ret = 1;
                else if (errno == ENOENT)
                    ret = 0;
916 917 918 919
            }
        }
    }

920
 cleanup:
921
    virDomainDefFree(def);
922 923 924 925

    return ret;
}

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

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

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

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

944 945
    ret = xenDaemonDomainSuspend(dom->conn, def);

946
 cleanup:
947 948
    virDomainDefFree(def);
    return ret;
949 950 951
}

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

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

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

963 964
    ret = xenDaemonDomainResume(dom->conn, def);

965
 cleanup:
966 967
    virDomainDefFree(def);
    return ret;
968 969 970
}

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

977 978
    virCheckFlags(0, -1);

979 980 981
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

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

985 986
    ret = xenDaemonDomainShutdown(dom->conn, def);

987
 cleanup:
988 989
    virDomainDefFree(def);
    return ret;
990 991
}

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

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

1004
    virCheckFlags(0, -1);
1005

1006 1007 1008
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

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

1012 1013
    ret = xenDaemonDomainReboot(dom->conn, def);

1014
 cleanup:
1015 1016
    virDomainDefFree(def);
    return ret;
1017 1018
}

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

1026 1027
    virCheckFlags(0, -1);

1028 1029 1030
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

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

1034 1035
    ret = xenDaemonDomainDestroy(dom->conn, def);

1036
 cleanup:
1037 1038
    virDomainDefFree(def);
    return ret;
1039 1040
}

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

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

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

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

1060
    if (def->id < 0) {
1061 1062 1063 1064 1065
        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 {
1066
            ret = xenDaemonDomainGetOSType(dom->conn, def);
1067
        }
1068
    } else {
1069
        ret = xenHypervisorDomainGetOSType(dom->conn, def);
1070
    }
1071

1072
 cleanup:
1073 1074
    virDomainDefFree(def);
    return ret;
1075 1076
}

1077

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

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

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

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

1100
 cleanup:
1101 1102
    virDomainDefFree(def);
    return ret;
1103 1104 1105
}

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

1112 1113 1114
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

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

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

1127
 cleanup:
1128 1129
    virDomainDefFree(def);
    return ret;
1130 1131 1132
}

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

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

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

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

1150
 cleanup:
1151 1152
    virDomainDefFree(def);
    return ret;
1153 1154 1155
}

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

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

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

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

1177
 cleanup:
1178 1179
    virDomainDefFree(def);
    return ret;
1180 1181
}

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

    virCheckFlags(0, -1);

1194 1195 1196
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

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

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

1209
 cleanup:
1210 1211
    virDomainDefFree(def);
    return ret;
1212 1213
}

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

1221
    virCheckFlags(0, -1);
1222

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

1229 1230 1231
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

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

1235 1236
    ret = xenDaemonDomainSave(dom->conn, def, to);

1237
 cleanup:
1238 1239
    virDomainDefFree(def);
    return ret;
1240 1241 1242
}

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

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

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

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

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

    virCheckFlags(0, -1);

1271 1272 1273
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

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

1277
    if (!(name = xenUnifiedDomainManagedSavePath(priv, def)))
1278 1279
        goto cleanup;

1280
    ret = xenDaemonDomainSave(dom->conn, def, name);
1281

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

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

    virCheckFlags(0, -1);

1298 1299 1300
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

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

1304 1305
    if (!(name = xenUnifiedDomainManagedSavePath(priv, def)))
        goto cleanup;
1306 1307

    ret = virFileExists(name);
1308

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

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

    virCheckFlags(0, -1);

1325 1326 1327
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

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

1331 1332
    if (!(name = xenUnifiedDomainManagedSavePath(priv, def)))
        goto cleanup;
1333 1334

    ret = unlink(name);
1335

1336
 cleanup:
1337 1338 1339 1340
    VIR_FREE(name);
    return ret;
}

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

1352
    return xenDaemonDomainRestore(conn, from);
1353 1354
}

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

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

    virCheckFlags(0, -1);

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

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

1375 1376
    ret = xenDaemonDomainCoreDump(dom->conn, def, to, flags);

1377
 cleanup:
1378 1379
    virDomainDefFree(def);
    return ret;
1380 1381 1382
}

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

1390 1391 1392 1393 1394 1395 1396 1397 1398
    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)) {
1399 1400
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid flag combination: (0x%x)"), flags);
1401 1402 1403
        return -1;
    }
    if (!nvcpus || (unsigned short) nvcpus != nvcpus) {
1404 1405
        virReportError(VIR_ERR_INVALID_ARG,
                       _("argument out of range: %d"), nvcpus);
1406 1407 1408
        return -1;
    }

1409 1410 1411
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

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

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

1423
 cleanup:
1424 1425
    virDomainDefFree(def);
    return ret;
1426 1427
}

1428
static int
1429
xenUnifiedDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus)
1430
{
1431
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1432 1433 1434 1435 1436
    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.  */
1437 1438 1439 1440
    if (priv->xendConfigVersion >= XEND_CONFIG_VERSION_3_0_4)
        flags |= VIR_DOMAIN_VCPU_CONFIG;

    return xenUnifiedDomainSetVcpusFlags(dom, nvcpus, flags);
1441 1442
}

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

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

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

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

1466
 cleanup:
1467 1468
    virDomainDefFree(def);
    return ret;
1469 1470 1471
}

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

1482 1483 1484 1485 1486
    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 {
1487 1488
            ret = xenDaemonDomainGetVcpus(dom->conn, def, info, maxinfo,
                                          cpumaps, maplen);
1489
        }
1490
    } else {
1491 1492
        ret = xenHypervisorGetVcpus(dom->conn, def, info, maxinfo, cpumaps,
                                    maplen);
1493
    }
1494 1495

    return ret;
1496 1497 1498
}

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

1506 1507 1508
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

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

1512 1513 1514
    ret = xenUnifiedDomainGetVcpusInternal(dom, def, info, maxinfo, cpumaps,
                                           maplen);

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

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

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

1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555
   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;

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

    ret = xenUnifiedDomainGetVcpusFlagsInternal(dom, def, flags);

1561
 cleanup:
1562 1563
    virDomainDefFree(def);
    return ret;
1564 1565
}

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

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

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

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

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

    if (def)
1599 1600
        ret = virDomainDefFormat(def,
                                 virDomainDefFormatConvertXMLFlags(flags));
1601

1602
 cleanup:
1603 1604 1605
    virDomainDefFree(def);
    virDomainDefFree(minidef);
    return ret;
1606 1607
}

1608 1609

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

E
Eric Blake 已提交
1623 1624
    virCheckFlags(0, NULL);

1625 1626 1627
    if (virConnectDomainXMLFromNativeEnsureACL(conn) < 0)
        return NULL;

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

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

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

1654
    ret = virDomainDefFormat(def, 0);
1655

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


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

E
Eric Blake 已提交
1676 1677
    virCheckFlags(0, NULL);

1678 1679 1680
    if (virConnectDomainXMLToNativeEnsureACL(conn) < 0)
        return NULL;

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

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

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

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

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

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


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

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

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

E
Eric Blake 已提交
1747 1748
    virCheckFlags(XEN_MIGRATION_FLAGS, -1);

1749 1750 1751
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

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

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

1759
 cleanup:
1760 1761
    virDomainDefFree(def);
    return ret;
1762 1763 1764
}

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

E
Eric Blake 已提交
1777 1778
    virCheckFlags(XEN_MIGRATION_FLAGS, NULL);

1779 1780
    if (!(minidef = xenGetDomainDefForName(dconn, dname)))
        goto cleanup;
1781

1782 1783 1784
    if (virDomainMigrateFinishEnsureACL(dconn, minidef) < 0)
        goto cleanup;

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

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

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

1802
 cleanup:
1803 1804 1805
    virDomainDefFree(def);
    virDomainDefFree(minidef);
    return ret;
1806 1807
}

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

1814 1815 1816
    if (virConnectListDefinedDomainsEnsureACL(conn) < 0)
        return -1;

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

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

1829 1830 1831
    if (virConnectNumOfDefinedDomainsEnsureACL(conn) < 0)
        return -1;

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

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

1847 1848
    virCheckFlags(0, -1);

1849 1850 1851
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

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

1855
    if (!(name = xenUnifiedDomainManagedSavePath(priv, def)))
1856 1857 1858
        goto cleanup;

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

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

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

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

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

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

1892 1893
    virCheckFlags(0, NULL);

1894 1895
    if (!(def = virDomainDefParseString(xml, priv->caps, priv->xmlopt,
                                        1 << VIR_DOMAIN_VIRT_XEN,
1896
                                        VIR_DOMAIN_DEF_PARSE_INACTIVE)))
1897 1898
        goto cleanup;

1899
    if (virDomainDefineXMLFlagsEnsureACL(conn, def) < 0)
1900 1901
        goto cleanup;

1902 1903 1904
    if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
        if (xenXMDomainDefineXML(conn, def) < 0)
            goto cleanup;
1905
        ret = virGetDomain(conn, def->name, def->uuid);
1906 1907 1908 1909
        def = NULL; /* XM driver owns it now */
    } else {
        if (xenDaemonDomainDefineXML(conn, def) < 0)
            goto cleanup;
1910
        ret = virGetDomain(conn, def->name, def->uuid);
1911 1912 1913 1914 1915
    }

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

1916
 cleanup:
1917 1918
    virDomainDefFree(def);
    return ret;
1919 1920
}

1921 1922 1923 1924 1925 1926
static virDomainPtr
xenUnifiedDomainDefineXML(virConnectPtr conn, const char *xml)
{
    return xenUnifiedDomainDefineXMLFlags(conn, xml, 0);
}

1927
static int
1928
xenUnifiedDomainUndefineFlags(virDomainPtr dom, unsigned int flags)
1929
{
1930
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1931 1932
    virDomainDefPtr def = NULL;
    int ret = -1;
1933

1934
    virCheckFlags(0, -1);
1935 1936 1937 1938

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

1939 1940 1941
    if (virDomainUndefineFlagsEnsureACL(dom->conn, def) < 0)
        goto cleanup;

1942
    if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
1943
        ret = xenXMDomainUndefine(dom->conn, def);
1944
    else
1945 1946
        ret = xenDaemonDomainUndefine(dom->conn, def);

1947
 cleanup:
1948 1949
    virDomainDefFree(def);
    return ret;
1950 1951
}

1952
static int
1953 1954
xenUnifiedDomainUndefine(virDomainPtr dom)
{
1955 1956 1957
    return xenUnifiedDomainUndefineFlags(dom, 0);
}

1958
static int
1959
xenUnifiedDomainAttachDevice(virDomainPtr dom, const char *xml)
1960
{
1961
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1962
    unsigned int flags = VIR_DOMAIN_DEVICE_MODIFY_LIVE;
1963 1964
    virDomainDefPtr def = NULL;
    int ret = -1;
1965

1966 1967 1968 1969 1970
    /*
     * 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
     */
1971
    if (priv->xendConfigVersion >= XEND_CONFIG_VERSION_3_0_4)
1972
        flags |= VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
1973

1974 1975 1976
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

1977 1978 1979
    if (virDomainAttachDeviceEnsureACL(dom->conn, def) < 0)
        goto cleanup;

1980
    if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
1981
        ret = xenXMDomainAttachDeviceFlags(dom->conn, def, xml, flags);
1982
    else
1983
        ret = xenDaemonAttachDeviceFlags(dom->conn, def, xml, flags);
1984

1985
 cleanup:
1986 1987
    virDomainDefFree(def);
    return ret;
1988 1989 1990
}

static int
1991 1992
xenUnifiedDomainAttachDeviceFlags(virDomainPtr dom, const char *xml,
                                  unsigned int flags)
1993
{
1994
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1995 1996 1997 1998 1999
    virDomainDefPtr def = NULL;
    int ret = -1;

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

2001 2002 2003
    if (virDomainAttachDeviceFlagsEnsureACL(dom->conn, def, flags) < 0)
        goto cleanup;

2004
    if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
2005
        ret = xenXMDomainAttachDeviceFlags(dom->conn, def, xml, flags);
2006
    else
2007 2008
        ret = xenDaemonAttachDeviceFlags(dom->conn, def, xml, flags);

2009
 cleanup:
2010 2011
    virDomainDefFree(def);
    return ret;
2012 2013 2014
}

static int
2015
xenUnifiedDomainDetachDevice(virDomainPtr dom, const char *xml)
2016
{
2017
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
2018
    unsigned int flags = VIR_DOMAIN_DEVICE_MODIFY_LIVE;
2019 2020
    virDomainDefPtr def = NULL;
    int ret = -1;
2021

2022 2023 2024 2025 2026
    /*
     * 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
     */
2027
    if (priv->xendConfigVersion >= XEND_CONFIG_VERSION_3_0_4)
2028
        flags |= VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
2029

2030 2031 2032
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

2033 2034 2035
    if (virDomainDetachDeviceEnsureACL(dom->conn, def) < 0)
        goto cleanup;

2036
    if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
2037
        ret = xenXMDomainDetachDeviceFlags(dom->conn, def, xml, flags);
2038
    else
2039 2040
        ret = xenDaemonDetachDeviceFlags(dom->conn, def, xml, flags);

2041
 cleanup:
2042 2043
    virDomainDefFree(def);
    return ret;
2044 2045 2046
}

static int
2047 2048
xenUnifiedDomainDetachDeviceFlags(virDomainPtr dom, const char *xml,
                                  unsigned int flags)
2049
{
2050
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
2051 2052 2053 2054 2055
    virDomainDefPtr def = NULL;
    int ret = -1;

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

2057 2058 2059
    if (virDomainDetachDeviceFlagsEnsureACL(dom->conn, def, flags) < 0)
        goto cleanup;

2060
    if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
2061
        ret = xenXMDomainDetachDeviceFlags(dom->conn, def, xml, flags);
2062
    else
2063 2064
        ret = xenDaemonDetachDeviceFlags(dom->conn, def, xml, flags);

2065
 cleanup:
2066 2067
    virDomainDefFree(def);
    return ret;
2068 2069
}

2070
static int
2071 2072
xenUnifiedDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml,
                                  unsigned int flags)
2073
{
2074 2075 2076 2077 2078 2079
    virDomainDefPtr def = NULL;
    int ret = -1;

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

2080 2081 2082
    if (virDomainUpdateDeviceFlagsEnsureACL(dom->conn, def, flags) < 0)
        goto cleanup;

2083 2084
    ret = xenDaemonUpdateDeviceFlags(dom->conn, def, xml, flags);

2085
 cleanup:
2086 2087
    virDomainDefFree(def);
    return ret;
2088 2089
}

2090
static int
2091
xenUnifiedDomainGetAutostart(virDomainPtr dom, int *autostart)
2092
{
2093
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
2094 2095 2096 2097 2098
    virDomainDefPtr def = NULL;
    int ret = -1;

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

2100 2101 2102
    if (virDomainGetAutostartEnsureACL(dom->conn, def) < 0)
        goto cleanup;

2103
    if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
2104
        ret = xenXMDomainGetAutostart(def, autostart);
2105
    else
2106 2107
        ret = xenDaemonDomainGetAutostart(dom->conn, def, autostart);

2108
 cleanup:
2109 2110
    virDomainDefFree(def);
    return ret;
2111 2112 2113
}

static int
2114
xenUnifiedDomainSetAutostart(virDomainPtr dom, int autostart)
2115
{
2116
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
2117 2118 2119 2120 2121
    virDomainDefPtr def = NULL;
    int ret = -1;

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

2123 2124 2125
    if (virDomainSetAutostartEnsureACL(dom->conn, def) < 0)
        goto cleanup;

2126
    if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
2127
        ret = xenXMDomainSetAutostart(def, autostart);
2128
    else
2129 2130
        ret = xenDaemonDomainSetAutostart(dom->conn, def, autostart);

2131
 cleanup:
2132 2133
    virDomainDefFree(def);
    return ret;
2134 2135
}

2136
static char *
2137
xenUnifiedDomainGetSchedulerType(virDomainPtr dom, int *nparams)
2138
{
2139
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
2140 2141 2142 2143 2144
    virDomainDefPtr def = NULL;
    char *ret = NULL;

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

2146 2147 2148
    if (virDomainGetSchedulerTypeEnsureACL(dom->conn, def) < 0)
        goto cleanup;

2149 2150 2151 2152
    if (dom->id < 0) {
        if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("Cannot change scheduler parameters"));
2153
            goto cleanup;
2154
        }
2155
        ret = xenDaemonGetSchedulerType(dom->conn, nparams);
2156
    } else {
2157
        ret = xenHypervisorGetSchedulerType(dom->conn, nparams);
2158
    }
2159

2160
 cleanup:
2161 2162
    virDomainDefFree(def);
    return ret;
2163 2164 2165
}

static int
2166 2167 2168 2169
xenUnifiedDomainGetSchedulerParametersFlags(virDomainPtr dom,
                                            virTypedParameterPtr params,
                                            int *nparams,
                                            unsigned int flags)
2170
{
2171
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
2172 2173
    virDomainDefPtr def = NULL;
    int ret = -1;
2174

2175 2176
    virCheckFlags(0, -1);

2177 2178 2179
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

2180 2181 2182
    if (virDomainGetSchedulerParametersFlagsEnsureACL(dom->conn, def) < 0)
        goto cleanup;

2183 2184 2185 2186
    if (dom->id < 0) {
        if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("Cannot change scheduler parameters"));
2187
            goto cleanup;
2188
        }
2189
        ret = xenDaemonGetSchedulerParameters(dom->conn, def, params, nparams);
2190
    } else {
2191
        ret = xenHypervisorGetSchedulerParameters(dom->conn, def, params, nparams);
2192
    }
2193

2194
 cleanup:
2195 2196
    virDomainDefFree(def);
    return ret;
2197 2198 2199
}

static int
2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212
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)
2213
{
2214
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
2215 2216
    virDomainDefPtr def = NULL;
    int ret = -1;
2217

2218 2219
    virCheckFlags(0, -1);

2220 2221 2222
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

2223 2224 2225
    if (virDomainSetSchedulerParametersFlagsEnsureACL(dom->conn, def, flags) < 0)
        goto cleanup;

2226 2227 2228 2229
    if (dom->id < 0) {
        if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("Cannot change scheduler parameters"));
2230
            goto cleanup;
2231
        }
2232
        ret = xenDaemonSetSchedulerParameters(dom->conn, def, params, nparams);
2233
    } else {
2234
        ret = xenHypervisorSetSchedulerParameters(dom->conn, def, params, nparams);
2235
    }
2236

2237
 cleanup:
2238 2239
    virDomainDefFree(def);
    return ret;
2240 2241
}

2242 2243 2244 2245 2246 2247 2248 2249 2250
static int
xenUnifiedDomainSetSchedulerParameters(virDomainPtr dom,
                                       virTypedParameterPtr params,
                                       int nparams)
{
    return xenUnifiedDomainSetSchedulerParametersFlags(dom, params,
                                                       nparams, 0);
}

2251
static int
2252
xenUnifiedDomainBlockStats(virDomainPtr dom, const char *path,
2253
                           virDomainBlockStatsPtr stats)
2254
{
2255 2256 2257 2258 2259 2260
    virDomainDefPtr def = NULL;
    int ret = -1;

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

2261 2262 2263
    if (virDomainBlockStatsEnsureACL(dom->conn, def) < 0)
        goto cleanup;

2264 2265
    ret = xenHypervisorDomainBlockStats(dom->conn, def, path, stats);

2266
 cleanup:
2267 2268
    virDomainDefFree(def);
    return ret;
2269 2270 2271
}

static int
2272
xenUnifiedDomainInterfaceStats(virDomainPtr dom, const char *path,
2273
                               virDomainInterfaceStatsPtr stats)
2274
{
2275 2276 2277 2278 2279 2280
    virDomainDefPtr def = NULL;
    int ret = -1;

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

2281 2282 2283
    if (virDomainInterfaceStatsEnsureACL(dom->conn, def) < 0)
        goto cleanup;

2284 2285
    ret = xenHypervisorDomainInterfaceStats(def, path, stats);

2286
 cleanup:
2287 2288
    virDomainDefFree(def);
    return ret;
2289 2290
}

R
Richard W.M. Jones 已提交
2291
static int
2292 2293 2294
xenUnifiedDomainBlockPeek(virDomainPtr dom, const char *path,
                          unsigned long long offset, size_t size,
                          void *buffer, unsigned int flags)
R
Richard W.M. Jones 已提交
2295
{
2296
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
2297 2298
    virDomainDefPtr def = NULL;
    int ret = -1;
R
Richard W.M. Jones 已提交
2299

E
Eric Blake 已提交
2300 2301
    virCheckFlags(0, -1);

2302 2303 2304
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

2305 2306 2307
    if (virDomainBlockPeekEnsureACL(dom->conn, def) < 0)
        goto cleanup;

2308
    if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
2309
        ret = xenXMDomainBlockPeek(dom->conn, def, path, offset, size, buffer);
2310
    else
2311 2312
        ret = xenDaemonDomainBlockPeek(dom->conn, def, path, offset, size, buffer);

2313
 cleanup:
2314 2315
    virDomainDefFree(def);
    return ret;
R
Richard W.M. Jones 已提交
2316 2317
}

2318
static int
2319 2320
xenUnifiedNodeGetCellsFreeMemory(virConnectPtr conn, unsigned long long *freeMems,
                                 int startCell, int maxCells)
2321
{
2322 2323 2324
    if (virNodeGetCellsFreeMemoryEnsureACL(conn) < 0)
        return 0;

2325 2326
    return xenHypervisorNodeGetCellsFreeMemory(conn, freeMems,
                                               startCell, maxCells);
2327 2328
}

2329
static unsigned long long
2330
xenUnifiedNodeGetFreeMemory(virConnectPtr conn)
2331 2332 2333
{
    unsigned long long freeMem = 0;

2334 2335 2336
    if (virNodeGetFreeMemoryEnsureACL(conn) < 0)
        return 0;

2337 2338 2339
    if (xenHypervisorNodeGetCellsFreeMemory(conn, &freeMem, -1, 1) < 0)
        return 0;
    return freeMem;
2340 2341
}

2342

2343
static int
2344 2345 2346 2347
xenUnifiedConnectDomainEventRegister(virConnectPtr conn,
                                     virConnectDomainEventCallback callback,
                                     void *opaque,
                                     virFreeCallback freefunc)
2348
{
2349
    xenUnifiedPrivatePtr priv = conn->privateData;
2350
    int ret = 0;
2351 2352 2353 2354

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

D
Daniel P. Berrange 已提交
2355
    xenUnifiedLock(priv);
2356

2357
    if (priv->xsWatch == -1) {
2358
        virReportUnsupportedError();
D
Daniel P. Berrange 已提交
2359
        xenUnifiedUnlock(priv);
2360 2361 2362
        return -1;
    }

2363 2364 2365
    if (virDomainEventStateRegister(conn, priv->domainEvents,
                                    callback, opaque, freefunc) < 0)
        ret = -1;
2366

D
Daniel P. Berrange 已提交
2367
    xenUnifiedUnlock(priv);
2368
    return ret;
2369 2370
}

2371

2372
static int
2373 2374
xenUnifiedConnectDomainEventDeregister(virConnectPtr conn,
                                       virConnectDomainEventCallback callback)
2375
{
2376
    int ret = 0;
2377
    xenUnifiedPrivatePtr priv = conn->privateData;
2378 2379 2380 2381

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

D
Daniel P. Berrange 已提交
2382 2383
    xenUnifiedLock(priv);

2384
    if (priv->xsWatch == -1) {
2385
        virReportUnsupportedError();
D
Daniel P. Berrange 已提交
2386
        xenUnifiedUnlock(priv);
2387 2388 2389
        return -1;
    }

2390 2391 2392 2393
    if (virDomainEventStateDeregister(conn,
                                      priv->domainEvents,
                                      callback) < 0)
        ret = -1;
2394

D
Daniel P. Berrange 已提交
2395
    xenUnifiedUnlock(priv);
2396 2397 2398
    return ret;
}

2399

2400
static int
2401 2402 2403 2404 2405 2406
xenUnifiedConnectDomainEventRegisterAny(virConnectPtr conn,
                                        virDomainPtr dom,
                                        int eventID,
                                        virConnectDomainEventGenericCallback callback,
                                        void *opaque,
                                        virFreeCallback freefunc)
2407
{
2408
    xenUnifiedPrivatePtr priv = conn->privateData;
2409
    int ret;
2410 2411 2412 2413

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

2414 2415 2416
    xenUnifiedLock(priv);

    if (priv->xsWatch == -1) {
2417
        virReportUnsupportedError();
2418 2419 2420 2421
        xenUnifiedUnlock(priv);
        return -1;
    }

2422 2423 2424
    if (virDomainEventStateRegisterID(conn, priv->domainEvents,
                                      dom, eventID,
                                      callback, opaque, freefunc, &ret) < 0)
2425
        ret = -1;
2426 2427

    xenUnifiedUnlock(priv);
2428
    return ret;
2429 2430 2431
}

static int
2432 2433
xenUnifiedConnectDomainEventDeregisterAny(virConnectPtr conn,
                                          int callbackID)
2434
{
2435
    int ret = 0;
2436
    xenUnifiedPrivatePtr priv = conn->privateData;
2437 2438 2439 2440

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

2441 2442 2443
    xenUnifiedLock(priv);

    if (priv->xsWatch == -1) {
2444
        virReportUnsupportedError();
2445 2446 2447 2448
        xenUnifiedUnlock(priv);
        return -1;
    }

2449 2450 2451 2452
    if (virObjectEventStateDeregisterID(conn,
                                        priv->domainEvents,
                                        callbackID) < 0)
        ret = -1;
2453 2454 2455 2456 2457 2458

    xenUnifiedUnlock(priv);
    return ret;
}


2459
static int
2460
xenUnifiedNodeDeviceGetPCIInfo(virNodeDevicePtr dev,
2461 2462 2463 2464
                               unsigned *domain,
                               unsigned *bus,
                               unsigned *slot,
                               unsigned *function)
2465 2466 2467 2468 2469 2470 2471 2472 2473 2474
{
    virNodeDeviceDefPtr def = NULL;
    virNodeDevCapsDefPtr cap;
    char *xml = NULL;
    int ret = -1;

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

2475
    def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL);
2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492
    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) {
2493 2494
        virReportError(VIR_ERR_INVALID_ARG,
                       _("device %s is not a PCI device"), dev->name);
2495 2496 2497 2498
        goto out;
    }

    ret = 0;
2499
 out:
2500 2501 2502 2503 2504 2505
    virNodeDeviceDefFree(def);
    VIR_FREE(xml);
    return ret;
}

static int
2506 2507 2508
xenUnifiedNodeDeviceDetachFlags(virNodeDevicePtr dev,
                                const char *driverName,
                                unsigned int flags)
2509
{
2510
    virPCIDevicePtr pci;
2511 2512 2513
    unsigned domain, bus, slot, function;
    int ret = -1;

2514 2515
    virCheckFlags(0, -1);

2516
    if (xenUnifiedNodeDeviceGetPCIInfo(dev, &domain, &bus, &slot, &function) < 0)
2517 2518
        return -1;

2519
    pci = virPCIDeviceNew(domain, bus, slot, function);
2520 2521 2522
    if (!pci)
        return -1;

2523
    if (!driverName) {
2524 2525
        if (virPCIDeviceSetStubDriver(pci, "pciback") < 0)
            goto out;
2526 2527 2528 2529 2530 2531
    } else {
        virReportError(VIR_ERR_INVALID_ARG,
                       _("unknown driver name '%s'"), driverName);
        goto out;
    }

2532
    if (virPCIDeviceDetach(pci, NULL, NULL) < 0)
2533 2534 2535
        goto out;

    ret = 0;
2536
 out:
2537
    virPCIDeviceFree(pci);
2538 2539 2540
    return ret;
}

2541 2542 2543 2544 2545 2546
static int
xenUnifiedNodeDeviceDettach(virNodeDevicePtr dev)
{
    return xenUnifiedNodeDeviceDetachFlags(dev, NULL, 0);
}

2547
static int
2548
xenUnifiedNodeDeviceAssignedDomainId(virNodeDevicePtr dev)
2549 2550
{
    int numdomains;
2551 2552
    int ret = -1;
    size_t i;
2553 2554 2555 2556 2557 2558 2559 2560
    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 */
2561
    numdomains = xenUnifiedConnectNumOfDomains(conn);
2562
    if (numdomains < 0)
2563
        return ret;
2564
    if (numdomains > 0) {
2565
        if (VIR_ALLOC_N(ids, numdomains) < 0)
2566
            goto out;
2567
        if ((numdomains = xenUnifiedConnectListDomains(conn, &ids[0], numdomains)) < 0)
2568 2569 2570 2571
            goto out;
    }

    /* Get pci bdf */
2572
    if (xenUnifiedNodeDeviceGetPCIInfo(dev, &domain, &bus, &slot, &function) < 0)
2573 2574 2575
        goto out;

    if (virAsprintf(&bdf, "%04x:%02x:%02x.%0x",
2576
                    domain, bus, slot, function) < 0)
2577 2578 2579 2580
        goto out;

    xenUnifiedLock(priv);
    /* Check if bdf is assigned to one of active domains */
2581
    for (i = 0; i < numdomains; i++) {
2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593
        xref = xenStoreDomainGetPCIID(conn, ids[i], bdf);
        if (xref == NULL) {
            continue;
        } else {
            ret = ids[i];
            break;
        }
    }
    xenUnifiedUnlock(priv);

    VIR_FREE(xref);
    VIR_FREE(bdf);
2594
 out:
2595 2596 2597 2598 2599
    VIR_FREE(ids);

    return ret;
}

2600
static int
2601
xenUnifiedNodeDeviceReAttach(virNodeDevicePtr dev)
2602
{
2603
    virPCIDevicePtr pci;
2604 2605
    unsigned domain, bus, slot, function;
    int ret = -1;
2606
    int domid;
2607

2608
    if (xenUnifiedNodeDeviceGetPCIInfo(dev, &domain, &bus, &slot, &function) < 0)
2609 2610
        return -1;

2611
    pci = virPCIDeviceNew(domain, bus, slot, function);
2612 2613 2614
    if (!pci)
        return -1;

2615 2616
    /* Check if device is assigned to an active guest */
    if ((domid = xenUnifiedNodeDeviceAssignedDomainId(dev)) >= 0) {
2617 2618 2619
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Device %s has been assigned to guest %d"),
                       dev->name, domid);
2620 2621 2622
        goto out;
    }

2623
    if (virPCIDeviceReattach(pci, NULL, NULL) < 0)
2624 2625 2626
        goto out;

    ret = 0;
2627
 out:
2628
    virPCIDeviceFree(pci);
2629 2630 2631 2632
    return ret;
}

static int
2633
xenUnifiedNodeDeviceReset(virNodeDevicePtr dev)
2634
{
2635
    virPCIDevicePtr pci;
2636 2637 2638
    unsigned domain, bus, slot, function;
    int ret = -1;

2639
    if (xenUnifiedNodeDeviceGetPCIInfo(dev, &domain, &bus, &slot, &function) < 0)
2640 2641
        return -1;

2642
    pci = virPCIDeviceNew(domain, bus, slot, function);
2643 2644 2645
    if (!pci)
        return -1;

2646
    if (virPCIDeviceReset(pci, NULL, NULL) < 0)
2647 2648 2649
        goto out;

    ret = 0;
2650
 out:
2651
    virPCIDeviceFree(pci);
2652 2653 2654 2655
    return ret;
}


2656 2657
static int
xenUnifiedDomainOpenConsole(virDomainPtr dom,
2658
                            const char *dev_name,
2659 2660 2661 2662 2663 2664 2665 2666 2667 2668
                            virStreamPtr st,
                            unsigned int flags)
{
    virDomainDefPtr def = NULL;
    int ret = -1;
    virDomainChrDefPtr chr = NULL;

    virCheckFlags(0, -1);

    if (dom->id == -1) {
2669 2670
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
2671 2672 2673
        goto cleanup;
    }

2674
    if (dev_name) {
2675
        /* XXX support device aliases in future */
2676 2677
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("Named device aliases are not supported"));
2678 2679 2680 2681 2682 2683 2684
        goto cleanup;
    }

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

2685 2686
    if (def->nconsoles)
        chr = def->consoles[0];
2687 2688 2689 2690
    else if (def->nserials)
        chr = def->serials[0];

    if (!chr) {
2691 2692
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("cannot find default console device"));
2693 2694 2695
        goto cleanup;
    }

2696
    if (chr->source.type != VIR_DOMAIN_CHR_TYPE_PTY) {
2697 2698
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("character device %s is not using a PTY"), dev_name);
2699 2700 2701
        goto cleanup;
    }

2702
    if (virFDStreamOpenFile(st, chr->source.data.file.path,
E
Eric Blake 已提交
2703
                            0, 0, O_RDWR) < 0)
2704 2705 2706
        goto cleanup;

    ret = 0;
2707
 cleanup:
2708 2709 2710
    virDomainDefFree(def);
    return ret;
}
2711 2712

static int
2713
xenUnifiedNodeGetMemoryParameters(virConnectPtr conn,
2714 2715 2716 2717
                                  virTypedParameterPtr params,
                                  int *nparams,
                                  unsigned int flags)
{
2718 2719 2720
    if (virNodeGetMemoryParametersEnsureACL(conn) < 0)
        return -1;

2721 2722 2723 2724 2725
    return nodeGetMemoryParameters(params, nparams, flags);
}


static int
2726
xenUnifiedNodeSetMemoryParameters(virConnectPtr conn,
2727 2728 2729 2730
                                  virTypedParameterPtr params,
                                  int nparams,
                                  unsigned int flags)
{
2731 2732 2733
    if (virNodeSetMemoryParametersEnsureACL(conn) < 0)
        return -1;

2734 2735 2736
    return nodeSetMemoryParameters(params, nparams, flags);
}

2737 2738

static int
2739
xenUnifiedNodeSuspendForDuration(virConnectPtr conn,
2740 2741 2742 2743
                                 unsigned int target,
                                 unsigned long long duration,
                                 unsigned int flags)
{
2744 2745 2746
    if (virNodeSuspendForDurationEnsureACL(conn) < 0)
        return -1;

2747 2748 2749 2750
    return nodeSuspendForDuration(target, duration, flags);
}


E
Eric Blake 已提交
2751
/*----- Register with libvirt.c, and initialize Xen drivers. -----*/
2752 2753

/* The interface which we export upwards to libvirt.c. */
2754
static virHypervisorDriver xenUnifiedDriver = {
2755 2756
    .no = VIR_DRV_XEN_UNIFIED,
    .name = "Xen",
2757 2758 2759 2760 2761
    .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 */
2762
    .connectGetHostname = xenUnifiedConnectGetHostname, /* 0.7.3 */
2763
    .connectGetSysinfo = xenUnifiedConnectGetSysinfo, /* 1.1.0 */
2764
    .connectGetMaxVcpus = xenUnifiedConnectGetMaxVcpus, /* 0.2.1 */
2765
    .nodeGetInfo = xenUnifiedNodeGetInfo, /* 0.1.0 */
2766 2767 2768
    .connectGetCapabilities = xenUnifiedConnectGetCapabilities, /* 0.2.1 */
    .connectListDomains = xenUnifiedConnectListDomains, /* 0.0.3 */
    .connectNumOfDomains = xenUnifiedConnectNumOfDomains, /* 0.0.3 */
2769 2770 2771 2772 2773 2774 2775
    .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 */
2776
    .domainShutdownFlags = xenUnifiedDomainShutdownFlags, /* 0.9.10 */
2777 2778
    .domainReboot = xenUnifiedDomainReboot, /* 0.1.0 */
    .domainDestroy = xenUnifiedDomainDestroy, /* 0.0.3 */
2779
    .domainDestroyFlags = xenUnifiedDomainDestroyFlags, /* 0.9.4 */
2780 2781 2782 2783 2784 2785 2786
    .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 */
2787
    .domainSaveFlags = xenUnifiedDomainSaveFlags, /* 0.9.4 */
2788 2789 2790
    .domainManagedSave = xenUnifiedDomainManagedSave, /* 1.0.1 */
    .domainHasManagedSaveImage = xenUnifiedDomainHasManagedSaveImage, /* 1.0.1 */
    .domainManagedSaveRemove = xenUnifiedDomainManagedSaveRemove, /* 1.0.1 */
2791
    .domainRestore = xenUnifiedDomainRestore, /* 0.0.3 */
2792
    .domainRestoreFlags = xenUnifiedDomainRestoreFlags, /* 0.9.4 */
2793 2794 2795 2796 2797 2798 2799 2800
    .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 */
2801 2802 2803 2804
    .connectDomainXMLFromNative = xenUnifiedConnectDomainXMLFromNative, /* 0.6.4 */
    .connectDomainXMLToNative = xenUnifiedConnectDomainXMLToNative, /* 0.6.4 */
    .connectListDefinedDomains = xenUnifiedConnectListDefinedDomains, /* 0.1.1 */
    .connectNumOfDefinedDomains = xenUnifiedConnectNumOfDefinedDomains, /* 0.1.5 */
2805 2806 2807
    .domainCreate = xenUnifiedDomainCreate, /* 0.1.1 */
    .domainCreateWithFlags = xenUnifiedDomainCreateWithFlags, /* 0.8.2 */
    .domainDefineXML = xenUnifiedDomainDefineXML, /* 0.1.1 */
2808
    .domainDefineXMLFlags = xenUnifiedDomainDefineXMLFlags, /* 1.2.12 */
2809
    .domainUndefine = xenUnifiedDomainUndefine, /* 0.1.1 */
2810
    .domainUndefineFlags = xenUnifiedDomainUndefineFlags, /* 0.9.4 */
2811 2812 2813 2814 2815 2816 2817 2818 2819
    .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 */
2820
    .domainGetSchedulerParametersFlags = xenUnifiedDomainGetSchedulerParametersFlags, /* 0.9.2 */
2821
    .domainSetSchedulerParameters = xenUnifiedDomainSetSchedulerParameters, /* 0.2.3 */
2822
    .domainSetSchedulerParametersFlags = xenUnifiedDomainSetSchedulerParametersFlags, /* 0.9.2 */
2823 2824 2825 2826 2827 2828 2829 2830
    .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 */
2831 2832
    .connectDomainEventRegister = xenUnifiedConnectDomainEventRegister, /* 0.5.0 */
    .connectDomainEventDeregister = xenUnifiedConnectDomainEventDeregister, /* 0.5.0 */
2833
    .nodeDeviceDettach = xenUnifiedNodeDeviceDettach, /* 0.6.1 */
2834
    .nodeDeviceDetachFlags = xenUnifiedNodeDeviceDetachFlags, /* 1.0.5 */
2835 2836
    .nodeDeviceReAttach = xenUnifiedNodeDeviceReAttach, /* 0.6.1 */
    .nodeDeviceReset = xenUnifiedNodeDeviceReset, /* 0.6.1 */
2837 2838
    .connectIsEncrypted = xenUnifiedConnectIsEncrypted, /* 0.7.3 */
    .connectIsSecure = xenUnifiedConnectIsSecure, /* 0.7.3 */
2839 2840 2841
    .domainIsActive = xenUnifiedDomainIsActive, /* 0.7.3 */
    .domainIsPersistent = xenUnifiedDomainIsPersistent, /* 0.7.3 */
    .domainIsUpdated = xenUnifiedDomainIsUpdated, /* 0.8.6 */
2842 2843
    .connectDomainEventRegisterAny = xenUnifiedConnectDomainEventRegisterAny, /* 0.8.0 */
    .connectDomainEventDeregisterAny = xenUnifiedConnectDomainEventDeregisterAny, /* 0.8.0 */
2844
    .domainOpenConsole = xenUnifiedDomainOpenConsole, /* 0.8.6 */
2845
    .connectIsAlive = xenUnifiedConnectIsAlive, /* 0.9.8 */
2846
    .nodeSuspendForDuration = xenUnifiedNodeSuspendForDuration, /* 0.9.8 */
2847 2848
    .nodeGetMemoryParameters = xenUnifiedNodeGetMemoryParameters, /* 0.10.2 */
    .nodeSetMemoryParameters = xenUnifiedNodeSetMemoryParameters, /* 0.10.2 */
2849 2850
};

2851
/**
2852
 * xenRegister:
2853 2854 2855 2856 2857
 *
 * Register xen related drivers
 *
 * Returns the driver priority or -1 in case of error.
 */
2858
int
2859
xenRegister(void)
2860
{
2861
    if (virRegisterStateDriver(&state_driver) == -1) return -1;
J
John Levon 已提交
2862

2863
    return virRegisterHypervisorDriver(&xenUnifiedDriver);
2864 2865
}

2866 2867 2868 2869 2870 2871 2872 2873
/**
 * xenUnifiedDomainInfoListFree:
 *
 * Free the Domain Info List
 */
void
xenUnifiedDomainInfoListFree(xenUnifiedDomainInfoListPtr list)
{
2874
    size_t i;
J
John Levon 已提交
2875 2876 2877 2878

    if (list == NULL)
        return;

2879
    for (i = 0; i < list->count; i++) {
2880 2881 2882
        VIR_FREE(list->doms[i]->name);
        VIR_FREE(list->doms[i]);
    }
2883
    VIR_FREE(list->doms);
2884 2885 2886 2887 2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902
    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 */
2903
    for (n = 0; n < list->count; n++) {
2904 2905
        if (STREQ(list->doms[n]->name, name) &&
            !memcmp(list->doms[n]->uuid, uuid, VIR_UUID_BUFLEN)) {
2906
            VIR_DEBUG("WARNING: dom already tracked");
2907 2908 2909 2910 2911
            return -1;
        }
    }

    if (VIR_ALLOC(info) < 0)
2912
        goto error;
2913 2914
    if (VIR_STRDUP(info->name, name) < 0)
        goto error;
2915 2916 2917 2918 2919

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

    /* Make space on list */
2920
    if (VIR_APPEND_ELEMENT(list->doms, list->count, info) < 0)
2921
        goto error;
2922 2923

    return 0;
2924
 error:
2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942
    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)
{
2943
    size_t i;
2944
    for (i = 0; i < list->count; i++) {
2945
        if (list->doms[i]->id == id &&
2946 2947 2948 2949 2950 2951
            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]);

2952
            VIR_DELETE_ELEMENT(list->doms, i, list->count);
2953 2954 2955 2956 2957 2958
            return 0;
        }
    }
    return -1;
}

2959

2960 2961
/**
 * xenUnifiedDomainEventDispatch:
D
Daniel P. Berrange 已提交
2962 2963
 * @priv: the connection to dispatch events on
 * @event: the event to dispatch
2964 2965 2966
 *
 * Dispatch domain events to registered callbacks
 *
D
Daniel P. Berrange 已提交
2967 2968
 * The caller must hold the lock in 'priv' before invoking
 *
2969
 */
2970
void xenUnifiedDomainEventDispatch(xenUnifiedPrivatePtr priv,
2971
                                    virObjectEventPtr event)
2972
{
D
Daniel P. Berrange 已提交
2973
    if (!priv)
2974
        return;
2975

2976
    virObjectEventStateQueue(priv->domainEvents, event);
D
Daniel P. Berrange 已提交
2977 2978 2979 2980 2981 2982 2983 2984 2985 2986
}

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

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