xen_driver.c 72.1 KB
Newer Older
1
/*
2
 * xen_driver.c: Unified Xen driver.
3
 *
4
 * Copyright (C) 2007-2013 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

70
#define VIR_FROM_THIS VIR_FROM_XEN
71
#define XEN_SAVE_DIR LOCALSTATEDIR "/lib/libvirt/xen/save"
72

73
static int
74
xenUnifiedNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info);
75
static int
76
xenUnifiedDomainGetMaxVcpus(virDomainPtr dom);
77
static int
78 79 80
xenUnifiedDomainGetVcpus(virDomainPtr dom,
                         virVcpuInfoPtr info, int maxinfo,
                         unsigned char *cpumaps, int maplen);
81

82

83
static bool is_privileged = false;
J
John Levon 已提交
84

85 86 87 88 89 90 91 92 93 94 95 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
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;
}


139 140 141 142 143 144 145
static virDomainDefPtr xenGetDomainDefForDom(virDomainPtr dom)
{
    /* UUID lookup is more efficient than name lookup */
    return xenGetDomainDefForUUID(dom->conn, dom->uuid);
}


146 147 148 149 150
/**
 * xenNumaInit:
 * @conn: pointer to the hypervisor connection
 *
 * Initializer for previous variables. We currently assume that
R
Richard W.M. Jones 已提交
151
 * the number of physical CPU and the number of NUMA cell is fixed
152 153 154 155 156
 * until reboot which might be false in future Xen implementations.
 */
static void
xenNumaInit(virConnectPtr conn) {
    virNodeInfo nodeInfo;
D
Daniel P. Berrange 已提交
157
    xenUnifiedPrivatePtr priv;
158 159 160 161 162 163
    int ret;

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

D
Daniel P. Berrange 已提交
164
    priv = conn->privateData;
165

D
Daniel P. Berrange 已提交
166 167
    priv->nbNodeCells = nodeInfo.nodes;
    priv->nbNodeCpus = nodeInfo.cpus;
168 169
}

D
Daniel P. Berrange 已提交
170

171 172 173 174 175 176 177 178 179 180 181 182 183 184
/**
 * xenDomainUsedCpus:
 * @dom: the domain
 *
 * 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 *
xenDomainUsedCpus(virDomainPtr dom)
{
    char *res = NULL;
D
Daniel P. Berrange 已提交
185
    int ncpus;
186
    int nb_vcpu;
187
    virBitmapPtr cpulist = NULL;
188 189 190 191 192 193
    unsigned char *cpumap = NULL;
    size_t cpumaplen;
    int nb = 0;
    int n, m;
    virVcpuInfoPtr cpuinfo = NULL;
    virNodeInfo nodeinfo;
D
Daniel P. Berrange 已提交
194
    xenUnifiedPrivatePtr priv;
195 196

    if (!VIR_IS_CONNECTED_DOMAIN(dom))
197
        return NULL;
198

D
Daniel P. Berrange 已提交
199 200 201
    priv = dom->conn->privateData;

    if (priv->nbNodeCpus <= 0)
202
        return NULL;
203 204
    nb_vcpu = xenUnifiedDomainGetMaxVcpus(dom);
    if (nb_vcpu <= 0)
205
        return NULL;
206
    if (xenUnifiedNodeGetInfo(dom->conn, &nodeinfo) < 0)
207
        return NULL;
208

209
    if (!(cpulist = virBitmapNew(priv->nbNodeCpus))) {
210
        virReportOOMError();
211
        goto done;
212 213
    }
    if (VIR_ALLOC_N(cpuinfo, nb_vcpu) < 0) {
214
        virReportOOMError();
215
        goto done;
216
    }
217
    cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo));
218
    if (xalloc_oversized(nb_vcpu, cpumaplen) ||
219
        VIR_ALLOC_N(cpumap, nb_vcpu * cpumaplen) < 0) {
220
        virReportOOMError();
221
        goto done;
222
    }
223 224 225

    if ((ncpus = xenUnifiedDomainGetVcpus(dom, cpuinfo, nb_vcpu,
                                          cpumap, cpumaplen)) >= 0) {
226
        for (n = 0 ; n < ncpus ; n++) {
D
Daniel P. Berrange 已提交
227
            for (m = 0 ; m < priv->nbNodeCpus; m++) {
228 229 230
                bool used;
                ignore_value(virBitmapGetBit(cpulist, m, &used));
                if ((!used) &&
231
                    (VIR_CPU_USABLE(cpumap, cpumaplen, n, m))) {
232
                    ignore_value(virBitmapSetBit(cpulist, m));
233 234
                    nb++;
                    /* if all CPU are used just return NULL */
D
Daniel P. Berrange 已提交
235
                    if (nb == priv->nbNodeCpus)
236 237 238 239 240
                        goto done;

                }
            }
        }
241
        res = virBitmapFormat(cpulist);
242 243 244
    }

done:
245
    virBitmapFree(cpulist);
246 247
    VIR_FREE(cpumap);
    VIR_FREE(cpuinfo);
248
    return res;
249 250
}

J
John Levon 已提交
251
static int
252
xenUnifiedStateInitialize(bool privileged,
253 254
                          virStateInhibitCallback callback ATTRIBUTE_UNUSED,
                          void *opaque ATTRIBUTE_UNUSED)
J
John Levon 已提交
255
{
256 257 258
    /* Don't allow driver to work in non-root libvirtd */
    if (privileged)
        is_privileged = true;
J
John Levon 已提交
259 260 261 262
    return 0;
}

static virStateDriver state_driver = {
263
    .name = "Xen",
264
    .stateInitialize = xenUnifiedStateInitialize,
J
John Levon 已提交
265 266
};

267 268 269 270 271 272 273 274 275 276 277
/*----- 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.
 */

278
static int
279
xenUnifiedProbe(void)
280 281 282
{
#ifdef __linux__
    if (virFileExists("/proc/xen"))
283
        return 1;
284
#endif
285
#ifdef __sun
286
    int fd;
287

288 289
    if ((fd = open("/dev/xen/domcaps", O_RDONLY)) >= 0) {
        VIR_FORCE_CLOSE(fd);
290
        return 1;
291 292
    }
#endif
293
    return 0;
294 295
}

J
Jim Fehlig 已提交
296 297
#ifdef WITH_LIBXL
static int
298
xenUnifiedXendProbe(void)
J
Jim Fehlig 已提交
299 300 301 302 303 304 305 306 307 308 309 310 311 312
{
    virCommandPtr cmd;
    int status;
    int ret = 0;

    cmd = virCommandNewArgList("/usr/sbin/xend", "status", NULL);
    if (virCommandRun(cmd, &status) == 0 && status == 0)
        ret = 1;
    virCommandFree(cmd);

    return ret;
}
#endif

313

314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329
static int
xenDomainDeviceDefPostParse(virDomainDeviceDefPtr dev,
                            virDomainDefPtr def,
                            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;

    return 0;
}


330 331
virDomainDefParserConfig xenDomainDefParserConfig = {
    .macPrefix = { 0x00, 0x16, 0x3e },
332
    .devicesPostParseCallback = xenDomainDeviceDefPostParse,
333 334
};

335

336 337 338 339 340 341 342 343
virDomainXMLOptionPtr
xenDomainXMLConfInit(void)
{
    return virDomainXMLOptionNew(&xenDomainDefParserConfig,
                                 NULL, NULL);
}


344
static virDrvOpenStatus
345
xenUnifiedConnectOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags)
346
{
347
    xenUnifiedPrivatePtr priv;
348
    char ebuf[1024];
349

J
John Levon 已提交
350 351 352 353
    /*
     * Only the libvirtd instance can open this driver.
     * Everything else falls back to the remote driver.
     */
354
    if (!is_privileged)
J
John Levon 已提交
355 356
        return VIR_DRV_OPEN_DECLINED;

357 358 359 360
    if (conn->uri == NULL) {
        if (!xenUnifiedProbe())
            return VIR_DRV_OPEN_DECLINED;

361
        if (!(conn->uri = virURIParse("xen:///")))
362
            return VIR_DRV_OPEN_ERROR;
363 364 365 366 367 368 369 370 371 372 373 374
    } 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;


            /* Return an error if the path isn't '' or '/' */
            if (conn->uri->path &&
                STRNEQ(conn->uri->path, "") &&
                STRNEQ(conn->uri->path, "/")) {
375 376 377
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("unexpected Xen URI path '%s', try xen:///"),
                               conn->uri->path);
378 379
                return VIR_DRV_OPEN_ERROR;
            }
380

381 382 383 384 385 386
            /* 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 {
387
            return VIR_DRV_OPEN_DECLINED;
388 389
        }
    }
390

J
Jim Fehlig 已提交
391 392 393 394 395 396 397
#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

398 399
    /* We now know the URI is definitely for this driver, so beyond
     * here, don't return DECLINED, always use ERROR */
400 401

    /* Allocate per-connection private data. */
402
    if (VIR_ALLOC(priv) < 0) {
403
        virReportOOMError();
404 405
        return VIR_DRV_OPEN_ERROR;
    }
D
Daniel P. Berrange 已提交
406
    if (virMutexInit(&priv->lock) < 0) {
407 408
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("cannot initialize mutex"));
D
Daniel P. Berrange 已提交
409 410 411
        VIR_FREE(priv);
        return VIR_DRV_OPEN_ERROR;
    }
412

413
    if (!(priv->domainEvents = virDomainEventStateNew())) {
D
Daniel P. Berrange 已提交
414 415
        virMutexDestroy(&priv->lock);
        VIR_FREE(priv);
416 417
        return VIR_DRV_OPEN_ERROR;
    }
D
Daniel P. Berrange 已提交
418 419
    conn->privateData = priv;

420 421 422 423 424
    priv->handle = -1;
    priv->xendConfigVersion = -1;
    priv->xshandle = NULL;


425 426 427 428 429 430
    /* 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;
431

432
    /* XenD is required to succeed */
433
    VIR_DEBUG("Trying XenD sub-driver");
434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452
    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;
453

D
Daniel P. Berrange 已提交
454 455
    xenNumaInit(conn);

456
    if (!(priv->caps = xenHypervisorMakeCapabilities(conn))) {
457
        VIR_DEBUG("Failed to make capabilities");
458
        goto error;
459 460
    }

461
    if (!(priv->xmlopt = xenDomainXMLConfInit()))
462
        goto error;
463

464
#if WITH_XEN_INOTIFY
465 466 467 468 469
    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;
470 471
#endif

E
Eric Blake 已提交
472
    if (!(priv->saveDir = strdup(XEN_SAVE_DIR))) {
473
        virReportOOMError();
474
        goto error;
475 476 477
    }

    if (virFileMakePath(priv->saveDir) < 0) {
478
        VIR_ERROR(_("Errored to create save dir '%s': %s"), priv->saveDir,
479
                  virStrerror(errno, ebuf, sizeof(ebuf)));
480
        goto error;
481 482
    }

483
    return VIR_DRV_OPEN_SUCCESS;
484

485
error:
486
    VIR_DEBUG("Failed to activate a mandatory sub-driver");
487 488 489 490 491 492 493 494 495 496 497 498
#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 已提交
499
    virMutexDestroy(&priv->lock);
500
    VIR_FREE(priv->saveDir);
501
    VIR_FREE(priv);
D
Daniel P. Berrange 已提交
502
    conn->privateData = NULL;
503
    return VIR_DRV_OPEN_ERROR;
504 505 506
}

static int
507
xenUnifiedConnectClose(virConnectPtr conn)
508
{
509
    xenUnifiedPrivatePtr priv = conn->privateData;
510

511
    virObjectUnref(priv->caps);
512
    virObjectUnref(priv->xmlopt);
513
    virDomainEventStateFree(priv->domainEvents);
514

515 516 517 518 519 520 521 522 523 524 525 526
#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);
527

528
    VIR_FREE(priv->saveDir);
D
Daniel P. Berrange 已提交
529 530
    virMutexDestroy(&priv->lock);
    VIR_FREE(conn->privateData);
531

532
    return 0;
533 534
}

535 536 537 538 539 540 541 542 543 544 545

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


546
static const char *
547
xenUnifiedConnectGetType(virConnectPtr conn ATTRIBUTE_UNUSED)
548
{
549
    return "Xen";
550 551
}

552 553
/* Which features are supported by this driver? */
static int
554
xenUnifiedConnectSupportsFeature(virConnectPtr conn ATTRIBUTE_UNUSED, int feature)
555 556
{
    switch (feature) {
557 558 559 560 561
    case VIR_DRV_FEATURE_MIGRATION_V1:
    case VIR_DRV_FEATURE_MIGRATION_DIRECT:
        return 1;
    default:
        return 0;
562 563 564
    }
}

565
static int
566
xenUnifiedConnectGetVersion(virConnectPtr conn, unsigned long *hvVer)
567
{
568
    return xenHypervisorGetVersion(conn, hvVer);
569 570
}

571 572 573 574 575 576 577

static char *xenUnifiedConnectGetHostname(virConnectPtr conn ATTRIBUTE_UNUSED)
{
    return virGetHostname();
}


578
static int
579
xenUnifiedConnectIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED)
580 581 582 583 584
{
    return 0;
}

static int
585
xenUnifiedConnectIsSecure(virConnectPtr conn)
586
{
587
    xenUnifiedPrivatePtr priv = conn->privateData;
588 589 590 591 592 593 594 595 596 597
    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;
}

598
static int
599
xenUnifiedConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED)
600 601 602 603 604
{
    /* XenD reconnects for each request */
    return 1;
}

605
int
606
xenUnifiedConnectGetMaxVcpus(virConnectPtr conn, const char *type)
607
{
608
    if (type && STRCASENEQ(type, "Xen")) {
609
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
610 611
        return -1;
    }
612

613
    return xenHypervisorGetMaxVcpus(conn, type);
614 615 616
}

static int
617
xenUnifiedNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info)
618
{
619
    return xenDaemonNodeGetInfo(conn, info);
620 621 622
}

static char *
623
xenUnifiedConnectGetCapabilities(virConnectPtr conn)
624
{
D
Daniel P. Berrange 已提交
625 626
    xenUnifiedPrivatePtr priv = conn->privateData;
    char *xml;
627

D
Daniel P. Berrange 已提交
628
    if (!(xml = virCapabilitiesFormatXML(priv->caps))) {
629
        virReportOOMError();
D
Daniel P. Berrange 已提交
630 631
        return NULL;
    }
632

D
Daniel P. Berrange 已提交
633
    return xml;
634 635 636
}

static int
637
xenUnifiedConnectListDomains(virConnectPtr conn, int *ids, int maxids)
638
{
639
    return xenStoreListDomains(conn, ids, maxids);
640 641 642
}

static int
643
xenUnifiedConnectNumOfDomains(virConnectPtr conn)
644
{
645
    return xenStoreNumOfDomains(conn);
646 647 648
}

static virDomainPtr
649
xenUnifiedDomainCreateXML(virConnectPtr conn,
650 651
                          const char *xml,
                          unsigned int flags)
652
{
653 654 655 656
    xenUnifiedPrivatePtr priv = conn->privateData;
    virDomainDefPtr def = NULL;
    virDomainPtr ret = NULL;

657
    virCheckFlags(0, NULL);
658

659 660 661 662 663 664 665 666 667 668 669 670 671 672 673
    if (!(def = virDomainDefParseString(xml, priv->caps, priv->xmlopt,
                                        1 << VIR_DOMAIN_VIRT_XEN,
                                        VIR_DOMAIN_XML_INACTIVE)))
        goto cleanup;

    if (xenDaemonCreateXML(conn, def) < 0)
        goto cleanup;

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

cleanup:
    virDomainDefFree(def);
    return ret;
674 675 676
}

static virDomainPtr
677
xenUnifiedDomainLookupByID(virConnectPtr conn, int id)
678
{
679
    virDomainPtr ret = NULL;
680
    virDomainDefPtr def = NULL;
681

682 683
    if (!(def = xenGetDomainDefForID(conn, id)))
        goto cleanup;
684

685 686
    if (!(ret = virGetDomain(conn, def->name, def->uuid)))
        goto cleanup;
687

688 689 690 691
    ret->id = def->id;

cleanup:
    virDomainDefFree(def);
692
    return ret;
693 694 695
}

static virDomainPtr
696 697
xenUnifiedDomainLookupByUUID(virConnectPtr conn,
                             const unsigned char *uuid)
698
{
699 700
    virDomainPtr ret = NULL;
    virDomainDefPtr def = NULL;
701

702 703
    if (!(def = xenGetDomainDefForUUID(conn, uuid)))
        goto cleanup;
704

705 706
    if (!(ret = virGetDomain(conn, def->name, def->uuid)))
        goto cleanup;
707

708
    ret->id = def->id;
709

710 711
cleanup:
    virDomainDefFree(def);
712
    return ret;
713 714 715
}

static virDomainPtr
716 717
xenUnifiedDomainLookupByName(virConnectPtr conn,
                             const char *name)
718
{
719 720
    virDomainPtr ret = NULL;
    virDomainDefPtr def = NULL;
721

722 723
    if (!(def = xenGetDomainDefForName(conn, name)))
        goto cleanup;
724

725 726
    if (!(ret = virGetDomain(conn, def->name, def->uuid)))
        goto cleanup;
727

728
    ret->id = def->id;
729

730 731
cleanup:
    virDomainDefFree(def);
732
    return ret;
733 734
}

735 736 737 738

static int
xenUnifiedDomainIsActive(virDomainPtr dom)
{
739
    virDomainDefPtr def;
740 741
    int ret = -1;

742 743
    if (!(def = xenGetDomainDefForUUID(dom->conn, dom->uuid)))
        goto cleanup;
744

745
    ret = def->id == -1 ? 0 : 1;
746

747 748
cleanup:
    virDomainDefFree(def);
749 750 751 752
    return ret;
}

static int
753
xenUnifiedDomainIsPersistent(virDomainPtr dom)
754
{
755
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
756
    virDomainDefPtr def = NULL;
757 758 759 760 761
    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 */
762 763
        def = xenXMDomainLookupByUUID(dom->conn, dom->uuid);
        if (def)
764 765 766 767 768
            ret = 1;
        else
            ret = 0;
    } else {
        /* New Xen with inactive domain management */
769 770 771
        def = xenDaemonLookupByUUID(dom->conn, dom->uuid);
        if (def) {
            if (def->id == -1) {
772 773 774 775 776 777 778 779 780 781 782
                /* 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);
                if (virAsprintf(&path, "%s/%s", XEND_DOMAINS_DIR, uuidstr) < 0) {
                    virReportOOMError();
783
                    goto cleanup;
784
                }
785 786 787 788
                if (access(path, R_OK) == 0)
                    ret = 1;
                else if (errno == ENOENT)
                    ret = 0;
789 790 791 792
            }
        }
    }

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

    return ret;
}

799 800 801 802 803 804
static int
xenUnifiedDomainIsUpdated(virDomainPtr dom ATTRIBUTE_UNUSED)
{
    return 0;
}

805
static int
806
xenUnifiedDomainSuspend(virDomainPtr dom)
807
{
808 809 810 811 812 813 814 815 816 817 818
    int ret = -1;
    virDomainDefPtr def;

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

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

cleanup:
    virDomainDefFree(def);
    return ret;
819 820 821
}

static int
822
xenUnifiedDomainResume(virDomainPtr dom)
823
{
824 825 826 827 828 829 830 831 832 833 834
    int ret = -1;
    virDomainDefPtr def;

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

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

cleanup:
    virDomainDefFree(def);
    return ret;
835 836 837
}

static int
838 839
xenUnifiedDomainShutdownFlags(virDomainPtr dom,
                              unsigned int flags)
840
{
841 842 843
    int ret = -1;
    virDomainDefPtr def;

844 845
    virCheckFlags(0, -1);

846 847 848 849 850 851 852 853
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

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

cleanup:
    virDomainDefFree(def);
    return ret;
854 855
}

856 857 858 859 860 861
static int
xenUnifiedDomainShutdown(virDomainPtr dom)
{
    return xenUnifiedDomainShutdownFlags(dom, 0);
}

862
static int
863
xenUnifiedDomainReboot(virDomainPtr dom, unsigned int flags)
864
{
865 866 867
    int ret = -1;
    virDomainDefPtr def;

868
    virCheckFlags(0, -1);
869

870 871 872 873 874 875 876 877
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

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

cleanup:
    virDomainDefFree(def);
    return ret;
878 879
}

880 881 882 883
static int
xenUnifiedDomainDestroyFlags(virDomainPtr dom,
                             unsigned int flags)
{
884 885 886
    int ret = -1;
    virDomainDefPtr def;

887 888
    virCheckFlags(0, -1);

889 890 891 892 893 894 895 896
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

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

cleanup:
    virDomainDefFree(def);
    return ret;
897 898
}

899 900 901 902 903 904
static int
xenUnifiedDomainDestroy(virDomainPtr dom)
{
    return xenUnifiedDomainDestroyFlags(dom, 0);
}

905
static char *
906
xenUnifiedDomainGetOSType(virDomainPtr dom)
907
{
908
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
909 910 911 912 913
    char *ret = NULL;
    virDomainDefPtr def;

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

915
    if (def->id < 0) {
916 917 918 919 920
        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 {
921
            ret = xenDaemonDomainGetOSType(dom->conn, def);
922
        }
923
    } else {
924
        ret = xenHypervisorDomainGetOSType(dom->conn, def);
925
    }
926 927 928 929

cleanup:
    virDomainDefFree(def);
    return ret;
930 931
}

932

933
static unsigned long long
934
xenUnifiedDomainGetMaxMemory(virDomainPtr dom)
935
{
936
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
937 938 939 940 941
    unsigned long long ret = 0;
    virDomainDefPtr def;

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

943
    if (def->id < 0) {
944
        if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
945
            ret = xenXMDomainGetMaxMemory(dom->conn, def);
946
        else
947
            ret = xenDaemonDomainGetMaxMemory(dom->conn, def);
948
    } else {
949
        ret = xenHypervisorGetMaxMemory(dom->conn, def);
950
    }
951 952 953 954

cleanup:
    virDomainDefFree(def);
    return ret;
955 956 957
}

static int
958
xenUnifiedDomainSetMaxMemory(virDomainPtr dom, unsigned long memory)
959
{
960
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
961 962
    int ret = -1;
    virDomainDefPtr def;
963

964 965 966 967
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

    if (def->id < 0) {
968
        if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
969
            ret = xenXMDomainSetMaxMemory(dom->conn, def, memory);
970
        else
971
            ret = xenDaemonDomainSetMaxMemory(dom->conn, def, memory);
972
    } else {
973
        ret = xenHypervisorSetMaxMemory(dom->conn, def, memory);
974
    }
975 976 977 978

cleanup:
    virDomainDefFree(def);
    return ret;
979 980 981
}

static int
982
xenUnifiedDomainSetMemory(virDomainPtr dom, unsigned long memory)
983
{
984
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
985 986 987 988 989
    int ret = -1;
    virDomainDefPtr def;

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

991 992
    if (def->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
        ret = xenXMDomainSetMemory(dom->conn, def, memory);
993
    else
994 995 996 997 998
        ret = xenDaemonDomainSetMemory(dom->conn, def, memory);

cleanup:
    virDomainDefFree(def);
    return ret;
999 1000 1001
}

static int
1002
xenUnifiedDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info)
1003
{
1004
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1005 1006 1007 1008 1009
    int ret = -1;
    virDomainDefPtr def;

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

1011
    if (def->id < 0) {
1012
        if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
1013
            ret = xenXMDomainGetInfo(dom->conn, def, info);
1014
        else
1015
            ret = xenDaemonDomainGetInfo(dom->conn, def, info);
1016
    } else {
1017
        ret = xenHypervisorGetDomainInfo(dom->conn, def, info);
1018
    }
1019 1020 1021 1022

cleanup:
    virDomainDefFree(def);
    return ret;
1023 1024
}

1025 1026 1027 1028 1029 1030
static int
xenUnifiedDomainGetState(virDomainPtr dom,
                         int *state,
                         int *reason,
                         unsigned int flags)
{
1031
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1032 1033
    int ret = -1;
    virDomainDefPtr def;
1034 1035 1036

    virCheckFlags(0, -1);

1037 1038 1039 1040
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

    if (def->id < 0) {
1041
        if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
1042
            ret = xenXMDomainGetState(dom->conn, def, state, reason);
1043
        else
1044
            ret = xenDaemonDomainGetState(dom->conn, def, state, reason);
1045
    } else {
1046
        ret = xenHypervisorGetDomainState(dom->conn, def, state, reason);
1047
    }
1048 1049 1050 1051

cleanup:
    virDomainDefFree(def);
    return ret;
1052 1053
}

1054
static int
1055 1056
xenUnifiedDomainSaveFlags(virDomainPtr dom, const char *to, const char *dxml,
                          unsigned int flags)
1057
{
1058 1059 1060
    int ret = -1;
    virDomainDefPtr def;

1061
    virCheckFlags(0, -1);
1062

1063
    if (dxml) {
1064 1065
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
1066 1067 1068
        return -1;
    }

1069 1070 1071 1072 1073 1074 1075 1076
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

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

cleanup:
    virDomainDefFree(def);
    return ret;
1077 1078 1079
}

static int
1080 1081 1082 1083 1084
xenUnifiedDomainSave(virDomainPtr dom, const char *to)
{
    return xenUnifiedDomainSaveFlags(dom, to, NULL, 0);
}

1085
static char *
1086 1087
xenUnifiedDomainManagedSavePath(xenUnifiedPrivatePtr priv,
                                virDomainDefPtr def)
1088 1089 1090
{
    char *ret;

1091
    if (virAsprintf(&ret, "%s/%s.save", priv->saveDir, def->name) < 0) {
1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102
        virReportOOMError();
        return NULL;
    }

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

static int
xenUnifiedDomainManagedSave(virDomainPtr dom, unsigned int flags)
{
1103
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1104 1105
    char *name = NULL;
    virDomainDefPtr def = NULL;
1106 1107 1108 1109
    int ret = -1;

    virCheckFlags(0, -1);

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

    if (!(name = xenUnifiedDomainManagedSavePath(priv, def)))
1114 1115
        goto cleanup;

1116
    ret = xenDaemonDomainSave(dom->conn, def, name);
1117 1118 1119

cleanup:
    VIR_FREE(name);
1120
    virDomainDefFree(def);
1121 1122 1123 1124 1125 1126
    return ret;
}

static int
xenUnifiedDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags)
{
1127
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1128 1129
    char *name = NULL;
    virDomainDefPtr def = NULL;
1130 1131 1132 1133
    int ret = -1;

    virCheckFlags(0, -1);

1134 1135 1136 1137 1138
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

    if (!(name = xenUnifiedDomainManagedSavePath(priv, def)))
        goto cleanup;
1139 1140

    ret = virFileExists(name);
1141 1142

cleanup:
1143
    VIR_FREE(name);
1144
    virDomainDefFree(def);
1145 1146 1147 1148 1149 1150
    return ret;
}

static int
xenUnifiedDomainManagedSaveRemove(virDomainPtr dom, unsigned int flags)
{
1151
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1152 1153
    char *name = NULL;
    virDomainDefPtr def = NULL;
1154 1155 1156 1157
    int ret = -1;

    virCheckFlags(0, -1);

1158 1159 1160 1161 1162
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

    if (!(name = xenUnifiedDomainManagedSavePath(priv, def)))
        goto cleanup;
1163 1164

    ret = unlink(name);
1165 1166

cleanup:
1167 1168 1169 1170
    VIR_FREE(name);
    return ret;
}

1171 1172 1173
static int
xenUnifiedDomainRestoreFlags(virConnectPtr conn, const char *from,
                             const char *dxml, unsigned int flags)
1174
{
1175 1176
    virCheckFlags(0, -1);
    if (dxml) {
1177 1178
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
1179 1180 1181
        return -1;
    }

1182
    return xenDaemonDomainRestore(conn, from);
1183 1184
}

1185
static int
1186
xenUnifiedDomainRestore(virConnectPtr conn, const char *from)
1187 1188 1189 1190
{
    return xenUnifiedDomainRestoreFlags(conn, from, NULL, 0);
}

1191
static int
1192
xenUnifiedDomainCoreDump(virDomainPtr dom, const char *to, unsigned int flags)
1193
{
1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206
    virDomainDefPtr def = NULL;
    int ret = -1;

    virCheckFlags(0, -1);

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

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

cleanup:
    virDomainDefFree(def);
    return ret;
1207 1208 1209
}

static int
1210 1211
xenUnifiedDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
                              unsigned int flags)
1212
{
1213
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1214 1215
    virDomainDefPtr def = NULL;
    int ret = -1;
1216

1217 1218 1219 1220 1221 1222 1223 1224 1225
    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)) {
1226 1227
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid flag combination: (0x%x)"), flags);
1228 1229 1230
        return -1;
    }
    if (!nvcpus || (unsigned short) nvcpus != nvcpus) {
1231 1232
        virReportError(VIR_ERR_INVALID_ARG,
                       _("argument out of range: %d"), nvcpus);
1233 1234 1235
        return -1;
    }

1236 1237 1238
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

1239 1240 1241
    /* Try non-hypervisor methods first, then hypervisor direct method
     * as a last resort.
     */
1242
    if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
1243
        ret = xenXMDomainSetVcpusFlags(dom->conn, def, nvcpus, flags);
1244
    else
1245 1246 1247 1248 1249
        ret = xenDaemonDomainSetVcpusFlags(dom->conn, def, nvcpus, flags);

cleanup:
    virDomainDefFree(def);
    return ret;
1250 1251
}

1252
static int
1253
xenUnifiedDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus)
1254
{
1255
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1256 1257 1258 1259 1260
    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.  */
1261 1262 1263 1264
    if (priv->xendConfigVersion >= XEND_CONFIG_VERSION_3_0_4)
        flags |= VIR_DOMAIN_VCPU_CONFIG;

    return xenUnifiedDomainSetVcpusFlags(dom, nvcpus, flags);
1265 1266
}

1267
static int
1268 1269
xenUnifiedDomainPinVcpu(virDomainPtr dom, unsigned int vcpu,
                        unsigned char *cpumap, int maplen)
1270
{
1271
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1272 1273 1274 1275 1276
    virDomainDefPtr def = NULL;
    int ret = -1;

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

1278 1279
    if (dom->id < 0) {
        if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
1280
            ret = xenXMDomainPinVcpu(dom->conn, def, vcpu, cpumap, maplen);
1281
        else
1282
            ret = xenDaemonDomainPinVcpu(dom->conn, def, vcpu, cpumap, maplen);
1283
    } else {
1284
        ret = xenHypervisorPinVcpu(dom->conn, def, vcpu, cpumap, maplen);
1285
    }
1286 1287 1288 1289

cleanup:
    virDomainDefFree(def);
    return ret;
1290 1291 1292
}

static int
1293 1294 1295
xenUnifiedDomainGetVcpus(virDomainPtr dom,
                         virVcpuInfoPtr info, int maxinfo,
                         unsigned char *cpumaps, int maplen)
1296
{
1297
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1298 1299 1300 1301 1302 1303
    virDomainDefPtr def = NULL;
    int ret = -1;

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

1304 1305 1306 1307
    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"));
1308
            goto cleanup;
1309
        } else {
1310
            ret = xenDaemonDomainGetVcpus(dom->conn, def, info, maxinfo, cpumaps, maplen);
1311
        }
1312
    } else {
1313
        ret = xenHypervisorGetVcpus(dom->conn, def, info, maxinfo, cpumaps, maplen);
1314
    }
1315 1316 1317 1318

cleanup:
    virDomainDefFree(def);
    return ret;
1319 1320 1321
}

static int
1322
xenUnifiedDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags)
1323
{
1324
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1325 1326
    virDomainDefPtr def = NULL;
    int ret = -1;
1327

1328 1329 1330 1331
    virCheckFlags(VIR_DOMAIN_VCPU_LIVE |
                  VIR_DOMAIN_VCPU_CONFIG |
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);

1332 1333 1334
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

1335 1336
    if (dom->id < 0) {
        if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
1337
            ret = xenXMDomainGetVcpusFlags(dom->conn, def, flags);
1338
        else
1339
            ret = xenDaemonDomainGetVcpusFlags(dom->conn, def, flags);
1340 1341
    } else {
        if (flags == (VIR_DOMAIN_VCPU_CONFIG | VIR_DOMAIN_VCPU_MAXIMUM))
1342
            ret = xenHypervisorGetVcpuMax(dom->conn, def);
1343
        else
1344
            ret = xenDaemonDomainGetVcpusFlags(dom->conn, def, flags);
1345
    }
1346 1347 1348 1349

cleanup:
    virDomainDefFree(def);
    return ret;
1350 1351
}

1352
static int
1353
xenUnifiedDomainGetMaxVcpus(virDomainPtr dom)
1354 1355 1356 1357 1358
{
    return xenUnifiedDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_LIVE |
                                               VIR_DOMAIN_VCPU_MAXIMUM));
}

1359
static char *
1360
xenUnifiedDomainGetXMLDesc(virDomainPtr dom, unsigned int flags)
1361
{
1362
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1363 1364 1365 1366 1367 1368
    virDomainDefPtr minidef = NULL;
    virDomainDefPtr def = NULL;
    char *ret = NULL;

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

1370
    if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
1371
        def = xenXMDomainGetXMLDesc(dom->conn, minidef);
1372
    } else {
1373
        char *cpus;
1374 1375 1376
        xenUnifiedLock(priv);
        cpus = xenDomainUsedCpus(dom);
        xenUnifiedUnlock(priv);
1377
        def = xenDaemonDomainGetXMLDesc(dom->conn, minidef, cpus);
1378
        VIR_FREE(cpus);
1379
    }
1380 1381 1382 1383 1384 1385 1386 1387

    if (def)
        ret = virDomainDefFormat(def, flags);

cleanup:
    virDomainDefFree(def);
    virDomainDefFree(minidef);
    return ret;
1388 1389
}

1390 1391

static char *
1392 1393 1394 1395
xenUnifiedConnectDomainXMLFromNative(virConnectPtr conn,
                                     const char *format,
                                     const char *config,
                                     unsigned int flags)
1396 1397 1398 1399
{
    virDomainDefPtr def = NULL;
    char *ret = NULL;
    virConfPtr conf = NULL;
1400 1401 1402
    int id;
    char * tty;
    int vncport;
1403
    xenUnifiedPrivatePtr priv = conn->privateData;
1404

E
Eric Blake 已提交
1405 1406
    virCheckFlags(0, NULL);

1407 1408
    if (STRNEQ(format, XEN_CONFIG_FORMAT_XM) &&
        STRNEQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
1409 1410
        virReportError(VIR_ERR_INVALID_ARG,
                       _("unsupported config type %s"), format);
1411 1412 1413 1414
        return NULL;
    }

    if (STREQ(format, XEN_CONFIG_FORMAT_XM)) {
1415
        conf = virConfReadMem(config, strlen(config), 0);
1416 1417 1418
        if (!conf)
            goto cleanup;

M
Markus Groß 已提交
1419
        def = xenParseXM(conf, priv->xendConfigVersion, priv->caps);
1420
    } else if (STREQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
1421 1422 1423 1424 1425
        id = xenGetDomIdFromSxprString(config, priv->xendConfigVersion);
        xenUnifiedLock(priv);
        tty = xenStoreDomainGetConsolePath(conn, id);
        vncport = xenStoreDomainGetVNCPort(conn, id);
        xenUnifiedUnlock(priv);
M
Markus Groß 已提交
1426
        def = xenParseSxprString(config, priv->xendConfigVersion, tty,
1427
                                       vncport);
1428 1429 1430 1431
    }
    if (!def)
        goto cleanup;

1432
    ret = virDomainDefFormat(def, 0);
1433 1434 1435

cleanup:
    virDomainDefFree(def);
1436 1437
    if (conf)
        virConfFree(conf);
1438 1439 1440 1441 1442 1443
    return ret;
}


#define MAX_CONFIG_SIZE (1024 * 65)
static char *
1444 1445 1446 1447
xenUnifiedConnectDomainXMLToNative(virConnectPtr conn,
                                   const char *format,
                                   const char *xmlData,
                                   unsigned int flags)
1448 1449 1450 1451
{
    virDomainDefPtr def = NULL;
    char *ret = NULL;
    virConfPtr conf = NULL;
1452
    xenUnifiedPrivatePtr priv = conn->privateData;
1453

E
Eric Blake 已提交
1454 1455
    virCheckFlags(0, NULL);

1456 1457
    if (STRNEQ(format, XEN_CONFIG_FORMAT_XM) &&
        STRNEQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
1458 1459
        virReportError(VIR_ERR_INVALID_ARG,
                       _("unsupported config type %s"), format);
1460 1461 1462
        goto cleanup;
    }

1463 1464
    if (!(def = virDomainDefParseString(xmlData, priv->caps, priv->xmlopt,
                                        1 << VIR_DOMAIN_VIRT_XEN, 0)))
1465 1466 1467 1468
        goto cleanup;

    if (STREQ(format, XEN_CONFIG_FORMAT_XM)) {
        int len = MAX_CONFIG_SIZE;
M
Markus Groß 已提交
1469
        conf = xenFormatXM(conn, def, priv->xendConfigVersion);
1470 1471 1472 1473
        if (!conf)
            goto cleanup;

        if (VIR_ALLOC_N(ret, len) < 0) {
1474
            virReportOOMError();
1475 1476 1477 1478 1479 1480 1481 1482
            goto cleanup;
        }

        if (virConfWriteMem(ret, &len, conf) < 0) {
            VIR_FREE(ret);
            goto cleanup;
        }
    } else if (STREQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
M
Markus Groß 已提交
1483
        ret = xenFormatSxpr(conn, def, priv->xendConfigVersion);
1484 1485 1486 1487 1488 1489 1490 1491 1492 1493
    }

cleanup:
    virDomainDefFree(def);
    if (conf)
        virConfFree(conf);
    return ret;
}


1494
static int
1495 1496 1497 1498 1499 1500 1501 1502
xenUnifiedDomainMigratePrepare(virConnectPtr dconn,
                               char **cookie,
                               int *cookielen,
                               const char *uri_in,
                               char **uri_out,
                               unsigned long flags,
                               const char *dname,
                               unsigned long resource)
1503
{
E
Eric Blake 已提交
1504 1505
    virCheckFlags(XEN_MIGRATION_FLAGS, -1);

1506 1507 1508
    return xenDaemonDomainMigratePrepare(dconn, cookie, cookielen,
                                         uri_in, uri_out,
                                         flags, dname, resource);
1509 1510 1511
}

static int
1512 1513 1514 1515 1516 1517 1518
xenUnifiedDomainMigratePerform(virDomainPtr dom,
                               const char *cookie,
                               int cookielen,
                               const char *uri,
                               unsigned long flags,
                               const char *dname,
                               unsigned long resource)
1519
{
1520 1521 1522
    virDomainDefPtr def = NULL;
    int ret = -1;

E
Eric Blake 已提交
1523 1524
    virCheckFlags(XEN_MIGRATION_FLAGS, -1);

1525 1526 1527 1528 1529 1530 1531 1532 1533 1534
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

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

cleanup:
    virDomainDefFree(def);
    return ret;
1535 1536 1537
}

static virDomainPtr
1538 1539 1540 1541 1542 1543
xenUnifiedDomainMigrateFinish(virConnectPtr dconn,
                              const char *dname,
                              const char *cookie ATTRIBUTE_UNUSED,
                              int cookielen ATTRIBUTE_UNUSED,
                              const char *uri ATTRIBUTE_UNUSED,
                              unsigned long flags)
1544
{
1545 1546 1547 1548
    xenUnifiedPrivatePtr priv = dconn->privateData;
    virDomainPtr ret = NULL;
    virDomainDefPtr minidef = NULL;
    virDomainDefPtr def = NULL;
1549

E
Eric Blake 已提交
1550 1551
    virCheckFlags(XEN_MIGRATION_FLAGS, NULL);

1552 1553
    if (!(minidef = xenGetDomainDefForName(dconn, dname)))
        goto cleanup;
1554 1555

    if (flags & VIR_MIGRATE_PERSIST_DEST) {
1556 1557
        if (!(def = xenDaemonDomainGetXMLDesc(dconn, minidef, NULL)))
            goto cleanup;
1558

1559 1560 1561 1562 1563 1564
        if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
            if (xenXMDomainDefineXML(dconn, def) < 0)
                goto cleanup;
        } else {
            if (xenDaemonDomainDefineXML(dconn, def) < 0)
                goto cleanup;
1565 1566 1567
        }
    }

1568 1569 1570
    ret = virGetDomain(dconn, minidef->name, minidef->uuid);
    if (ret)
        ret->id = minidef->id;
1571

1572 1573 1574 1575
cleanup:
    virDomainDefFree(def);
    virDomainDefFree(minidef);
    return ret;
1576 1577
}

1578
static int
1579 1580
xenUnifiedConnectListDefinedDomains(virConnectPtr conn, char **const names,
                                    int maxnames)
1581
{
1582
    xenUnifiedPrivatePtr priv = conn->privateData;
1583

1584 1585 1586 1587 1588
    if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
        return xenXMListDefinedDomains(conn, names, maxnames);
    } else {
        return xenDaemonListDefinedDomains(conn, names, maxnames);
    }
1589 1590 1591
}

static int
1592
xenUnifiedConnectNumOfDefinedDomains(virConnectPtr conn)
1593
{
1594
    xenUnifiedPrivatePtr priv = conn->privateData;
1595

1596 1597 1598 1599 1600
    if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
        return xenXMNumOfDefinedDomains(conn);
    } else {
        return xenDaemonNumOfDefinedDomains(conn);
    }
1601 1602 1603
}

static int
1604
xenUnifiedDomainCreateWithFlags(virDomainPtr dom, unsigned int flags)
1605
{
1606
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1607
    int ret = -1;
1608
    virDomainDefPtr def = NULL;
1609
    char *name = NULL;
1610

1611 1612
    virCheckFlags(0, -1);

1613 1614 1615 1616
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

    if (!(name = xenUnifiedDomainManagedSavePath(priv, def)))
1617 1618 1619
        goto cleanup;

    if (virFileExists(name)) {
1620 1621 1622
        ret = xenDaemonDomainRestore(dom->conn, name);
        if (ret == 0)
            unlink(name);
1623 1624 1625
        goto cleanup;
    }

1626
    if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
1627
        ret = xenXMDomainCreate(dom->conn, def);
1628
    else
1629 1630 1631 1632
        ret = xenDaemonDomainCreate(dom->conn, def);

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

1634
cleanup:
1635
    virDomainDefFree(def);
1636 1637
    VIR_FREE(name);
    return ret;
1638 1639
}

1640
static int
1641
xenUnifiedDomainCreate(virDomainPtr dom)
1642 1643 1644 1645
{
    return xenUnifiedDomainCreateWithFlags(dom, 0);
}

1646
static virDomainPtr
1647
xenUnifiedDomainDefineXML(virConnectPtr conn, const char *xml)
1648
{
1649
    xenUnifiedPrivatePtr priv = conn->privateData;
1650 1651
    virDomainDefPtr def = NULL;
    virDomainPtr ret = NULL;
1652

1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673
    if (!(def = virDomainDefParseString(xml, priv->caps, priv->xmlopt,
                                        1 << VIR_DOMAIN_VIRT_XEN,
                                        VIR_DOMAIN_XML_INACTIVE)))
        goto cleanup;

    if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
        if (xenXMDomainDefineXML(conn, def) < 0)
            goto cleanup;
        def = NULL; /* XM driver owns it now */
    } else {
        if (xenDaemonDomainDefineXML(conn, def) < 0)
            goto cleanup;
    }

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

cleanup:
    virDomainDefFree(def);
    return ret;
1674 1675 1676
}

static int
1677
xenUnifiedDomainUndefineFlags(virDomainPtr dom, unsigned int flags)
1678
{
1679
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1680 1681
    virDomainDefPtr def = NULL;
    int ret = -1;
1682

1683
    virCheckFlags(0, -1);
1684 1685 1686 1687

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

1688
    if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
1689
        ret = xenXMDomainUndefine(dom->conn, def);
1690
    else
1691 1692 1693 1694 1695
        ret = xenDaemonDomainUndefine(dom->conn, def);

cleanup:
    virDomainDefFree(def);
    return ret;
1696 1697
}

1698
static int
1699
xenUnifiedDomainUndefine(virDomainPtr dom) {
1700 1701 1702
    return xenUnifiedDomainUndefineFlags(dom, 0);
}

1703
static int
1704
xenUnifiedDomainAttachDevice(virDomainPtr dom, const char *xml)
1705
{
1706
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1707
    unsigned int flags = VIR_DOMAIN_DEVICE_MODIFY_LIVE;
1708 1709
    virDomainDefPtr def = NULL;
    int ret = -1;
1710

1711 1712 1713 1714 1715
    /*
     * 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
     */
1716
    if (priv->xendConfigVersion >= XEND_CONFIG_VERSION_3_0_4)
1717
        flags |= VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
1718

1719 1720 1721
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

1722
    if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
1723
        ret = xenXMDomainAttachDeviceFlags(dom->conn, def, xml, flags);
1724
    else
1725
        ret = xenDaemonAttachDeviceFlags(dom->conn, def, xml, flags);
1726

1727 1728 1729
cleanup:
    virDomainDefFree(def);
    return ret;
1730 1731 1732
}

static int
1733 1734
xenUnifiedDomainAttachDeviceFlags(virDomainPtr dom, const char *xml,
                                  unsigned int flags)
1735
{
1736
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1737 1738 1739 1740 1741
    virDomainDefPtr def = NULL;
    int ret = -1;

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

1743
    if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
1744
        ret = xenXMDomainAttachDeviceFlags(dom->conn, def, xml, flags);
1745
    else
1746 1747 1748 1749 1750
        ret = xenDaemonAttachDeviceFlags(dom->conn, def, xml, flags);

cleanup:
    virDomainDefFree(def);
    return ret;
1751 1752 1753
}

static int
1754
xenUnifiedDomainDetachDevice(virDomainPtr dom, const char *xml)
1755
{
1756
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1757
    unsigned int flags = VIR_DOMAIN_DEVICE_MODIFY_LIVE;
1758 1759
    virDomainDefPtr def = NULL;
    int ret = -1;
1760

1761 1762 1763 1764 1765
    /*
     * 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
     */
1766
    if (priv->xendConfigVersion >= XEND_CONFIG_VERSION_3_0_4)
1767
        flags |= VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
1768

1769 1770 1771
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

1772
    if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
1773
        ret = xenXMDomainDetachDeviceFlags(dom->conn, def, xml, flags);
1774
    else
1775 1776 1777 1778 1779
        ret = xenDaemonDetachDeviceFlags(dom->conn, def, xml, flags);

cleanup:
    virDomainDefFree(def);
    return ret;
1780 1781 1782
}

static int
1783 1784
xenUnifiedDomainDetachDeviceFlags(virDomainPtr dom, const char *xml,
                                  unsigned int flags)
1785
{
1786
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1787 1788 1789 1790 1791
    virDomainDefPtr def = NULL;
    int ret = -1;

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

1793
    if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
1794
        ret = xenXMDomainDetachDeviceFlags(dom->conn, def, xml, flags);
1795
    else
1796 1797 1798 1799 1800
        ret = xenDaemonDetachDeviceFlags(dom->conn, def, xml, flags);

cleanup:
    virDomainDefFree(def);
    return ret;
1801 1802
}

1803
static int
1804 1805
xenUnifiedDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml,
                                  unsigned int flags)
1806
{
1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817
    virDomainDefPtr def = NULL;
    int ret = -1;

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

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

cleanup:
    virDomainDefFree(def);
    return ret;
1818 1819
}

1820
static int
1821
xenUnifiedDomainGetAutostart(virDomainPtr dom, int *autostart)
1822
{
1823
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1824 1825 1826 1827 1828
    virDomainDefPtr def = NULL;
    int ret = -1;

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

1830
    if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
1831
        ret = xenXMDomainGetAutostart(def, autostart);
1832
    else
1833 1834 1835 1836 1837
        ret = xenDaemonDomainGetAutostart(dom->conn, def, autostart);

cleanup:
    virDomainDefFree(def);
    return ret;
1838 1839 1840
}

static int
1841
xenUnifiedDomainSetAutostart(virDomainPtr dom, int autostart)
1842
{
1843
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1844 1845 1846 1847 1848
    virDomainDefPtr def = NULL;
    int ret = -1;

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

1850
    if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
1851
        ret = xenXMDomainSetAutostart(def, autostart);
1852
    else
1853 1854 1855 1856 1857
        ret = xenDaemonDomainSetAutostart(dom->conn, def, autostart);

cleanup:
    virDomainDefFree(def);
    return ret;
1858 1859
}

1860
static char *
1861
xenUnifiedDomainGetSchedulerType(virDomainPtr dom, int *nparams)
1862
{
1863
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1864 1865 1866 1867 1868
    virDomainDefPtr def = NULL;
    char *ret = NULL;

    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;
1869 1870 1871 1872 1873

    if (dom->id < 0) {
        if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("Cannot change scheduler parameters"));
1874
            goto cleanup;
1875
        }
1876
        ret = xenDaemonGetSchedulerType(dom->conn, nparams);
1877
    } else {
1878
        ret = xenHypervisorGetSchedulerType(dom->conn, nparams);
1879
    }
1880 1881 1882 1883

cleanup:
    virDomainDefFree(def);
    return ret;
1884 1885 1886
}

static int
1887 1888 1889 1890
xenUnifiedDomainGetSchedulerParametersFlags(virDomainPtr dom,
                                            virTypedParameterPtr params,
                                            int *nparams,
                                            unsigned int flags)
1891
{
1892
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1893 1894
    virDomainDefPtr def = NULL;
    int ret = -1;
1895

1896 1897
    virCheckFlags(0, -1);

1898 1899 1900
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

1901 1902 1903 1904
    if (dom->id < 0) {
        if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("Cannot change scheduler parameters"));
1905
            goto cleanup;
1906
        }
1907
        ret = xenDaemonGetSchedulerParameters(dom->conn, def, params, nparams);
1908
    } else {
1909
        ret = xenHypervisorGetSchedulerParameters(dom->conn, def, params, nparams);
1910
    }
1911 1912 1913 1914

cleanup:
    virDomainDefFree(def);
    return ret;
1915 1916 1917
}

static int
1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930
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)
1931
{
1932
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1933 1934
    virDomainDefPtr def = NULL;
    int ret = -1;
1935

1936 1937
    virCheckFlags(0, -1);

1938 1939 1940
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

1941 1942 1943 1944
    if (dom->id < 0) {
        if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("Cannot change scheduler parameters"));
1945
            goto cleanup;
1946
        }
1947
        ret = xenDaemonSetSchedulerParameters(dom->conn, def, params, nparams);
1948
    } else {
1949
        ret = xenHypervisorSetSchedulerParameters(dom->conn, def, params, nparams);
1950
    }
1951 1952 1953 1954

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

1957 1958 1959 1960 1961 1962 1963 1964 1965
static int
xenUnifiedDomainSetSchedulerParameters(virDomainPtr dom,
                                       virTypedParameterPtr params,
                                       int nparams)
{
    return xenUnifiedDomainSetSchedulerParametersFlags(dom, params,
                                                       nparams, 0);
}

1966
static int
1967 1968
xenUnifiedDomainBlockStats(virDomainPtr dom, const char *path,
                           struct _virDomainBlockStats *stats)
1969
{
1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980
    virDomainDefPtr def = NULL;
    int ret = -1;

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

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

cleanup:
    virDomainDefFree(def);
    return ret;
1981 1982 1983
}

static int
1984 1985
xenUnifiedDomainInterfaceStats(virDomainPtr dom, const char *path,
                               struct _virDomainInterfaceStats *stats)
1986
{
1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997
    virDomainDefPtr def = NULL;
    int ret = -1;

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

    ret = xenHypervisorDomainInterfaceStats(def, path, stats);

cleanup:
    virDomainDefFree(def);
    return ret;
1998 1999
}

R
Richard W.M. Jones 已提交
2000
static int
2001 2002 2003
xenUnifiedDomainBlockPeek(virDomainPtr dom, const char *path,
                          unsigned long long offset, size_t size,
                          void *buffer, unsigned int flags)
R
Richard W.M. Jones 已提交
2004
{
2005
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
2006 2007
    virDomainDefPtr def = NULL;
    int ret = -1;
R
Richard W.M. Jones 已提交
2008

E
Eric Blake 已提交
2009 2010
    virCheckFlags(0, -1);

2011 2012 2013
    if (!(def = xenGetDomainDefForDom(dom)))
        goto cleanup;

2014
    if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
2015
        ret = xenXMDomainBlockPeek(dom->conn, def, path, offset, size, buffer);
2016
    else
2017 2018 2019 2020 2021
        ret = xenDaemonDomainBlockPeek(dom->conn, def, path, offset, size, buffer);

cleanup:
    virDomainDefFree(def);
    return ret;
R
Richard W.M. Jones 已提交
2022 2023
}

2024
static int
2025 2026
xenUnifiedNodeGetCellsFreeMemory(virConnectPtr conn, unsigned long long *freeMems,
                                 int startCell, int maxCells)
2027
{
2028 2029
    return xenHypervisorNodeGetCellsFreeMemory(conn, freeMems,
                                               startCell, maxCells);
2030 2031
}

2032
static unsigned long long
2033
xenUnifiedNodeGetFreeMemory(virConnectPtr conn)
2034 2035 2036
{
    unsigned long long freeMem = 0;

2037 2038 2039
    if (xenHypervisorNodeGetCellsFreeMemory(conn, &freeMem, -1, 1) < 0)
        return 0;
    return freeMem;
2040 2041
}

2042

2043
static int
2044 2045 2046 2047
xenUnifiedConnectDomainEventRegister(virConnectPtr conn,
                                     virConnectDomainEventCallback callback,
                                     void *opaque,
                                     virFreeCallback freefunc)
2048
{
2049
    xenUnifiedPrivatePtr priv = conn->privateData;
D
Daniel P. Berrange 已提交
2050

2051
    int ret;
D
Daniel P. Berrange 已提交
2052
    xenUnifiedLock(priv);
2053

2054
    if (priv->xsWatch == -1) {
2055
        virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
D
Daniel P. Berrange 已提交
2056
        xenUnifiedUnlock(priv);
2057 2058 2059
        return -1;
    }

2060 2061
    ret = virDomainEventStateRegister(conn, priv->domainEvents,
                                      callback, opaque, freefunc);
2062

D
Daniel P. Berrange 已提交
2063
    xenUnifiedUnlock(priv);
2064
    return ret;
2065 2066
}

2067

2068
static int
2069 2070
xenUnifiedConnectDomainEventDeregister(virConnectPtr conn,
                                       virConnectDomainEventCallback callback)
2071 2072
{
    int ret;
2073
    xenUnifiedPrivatePtr priv = conn->privateData;
D
Daniel P. Berrange 已提交
2074 2075
    xenUnifiedLock(priv);

2076
    if (priv->xsWatch == -1) {
2077
        virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
D
Daniel P. Berrange 已提交
2078
        xenUnifiedUnlock(priv);
2079 2080 2081
        return -1;
    }

2082 2083 2084
    ret = virDomainEventStateDeregister(conn,
                                        priv->domainEvents,
                                        callback);
2085

D
Daniel P. Berrange 已提交
2086
    xenUnifiedUnlock(priv);
2087 2088 2089
    return ret;
}

2090

2091
static int
2092 2093 2094 2095 2096 2097
xenUnifiedConnectDomainEventRegisterAny(virConnectPtr conn,
                                        virDomainPtr dom,
                                        int eventID,
                                        virConnectDomainEventGenericCallback callback,
                                        void *opaque,
                                        virFreeCallback freefunc)
2098
{
2099
    xenUnifiedPrivatePtr priv = conn->privateData;
2100 2101 2102 2103 2104

    int ret;
    xenUnifiedLock(priv);

    if (priv->xsWatch == -1) {
2105
        virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
2106 2107 2108 2109
        xenUnifiedUnlock(priv);
        return -1;
    }

2110 2111 2112
    if (virDomainEventStateRegisterID(conn, priv->domainEvents,
                                      dom, eventID,
                                      callback, opaque, freefunc, &ret) < 0)
2113
        ret = -1;
2114 2115

    xenUnifiedUnlock(priv);
2116
    return ret;
2117 2118 2119
}

static int
2120 2121
xenUnifiedConnectDomainEventDeregisterAny(virConnectPtr conn,
                                          int callbackID)
2122 2123
{
    int ret;
2124
    xenUnifiedPrivatePtr priv = conn->privateData;
2125 2126 2127
    xenUnifiedLock(priv);

    if (priv->xsWatch == -1) {
2128
        virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
2129 2130 2131 2132
        xenUnifiedUnlock(priv);
        return -1;
    }

2133 2134 2135
    ret = virDomainEventStateDeregisterID(conn,
                                          priv->domainEvents,
                                          callbackID);
2136 2137 2138 2139 2140 2141

    xenUnifiedUnlock(priv);
    return ret;
}


2142
static int
2143 2144 2145 2146 2147
xenUnifiedNodeDeviceGetPciInfo(virNodeDevicePtr dev,
                               unsigned *domain,
                               unsigned *bus,
                               unsigned *slot,
                               unsigned *function)
2148 2149 2150 2151 2152 2153 2154 2155 2156 2157
{
    virNodeDeviceDefPtr def = NULL;
    virNodeDevCapsDefPtr cap;
    char *xml = NULL;
    int ret = -1;

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

2158
    def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL);
2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175
    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) {
2176 2177
        virReportError(VIR_ERR_INVALID_ARG,
                       _("device %s is not a PCI device"), dev->name);
2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188
        goto out;
    }

    ret = 0;
out:
    virNodeDeviceDefFree(def);
    VIR_FREE(xml);
    return ret;
}

static int
2189 2190 2191
xenUnifiedNodeDeviceDetachFlags(virNodeDevicePtr dev,
                                const char *driverName,
                                unsigned int flags)
2192
{
2193
    virPCIDevicePtr pci;
2194 2195 2196
    unsigned domain, bus, slot, function;
    int ret = -1;

2197 2198
    virCheckFlags(0, -1);

2199 2200 2201
    if (xenUnifiedNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0)
        return -1;

2202
    pci = virPCIDeviceNew(domain, bus, slot, function);
2203 2204 2205
    if (!pci)
        return -1;

2206 2207 2208 2209 2210 2211 2212 2213 2214
    if (!driverName) {
        virPCIDeviceSetStubDriver(pci, "pciback");
    } else {
        virReportError(VIR_ERR_INVALID_ARG,
                       _("unknown driver name '%s'"), driverName);
        goto out;
    }

    if (virPCIDeviceDetach(pci, NULL, NULL, NULL) < 0)
2215 2216 2217 2218
        goto out;

    ret = 0;
out:
2219
    virPCIDeviceFree(pci);
2220 2221 2222
    return ret;
}

2223 2224 2225 2226 2227 2228
static int
xenUnifiedNodeDeviceDettach(virNodeDevicePtr dev)
{
    return xenUnifiedNodeDeviceDetachFlags(dev, NULL, 0);
}

2229
static int
2230
xenUnifiedNodeDeviceAssignedDomainId(virNodeDevicePtr dev)
2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241
{
    int numdomains;
    int ret = -1, i;
    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 */
2242
    numdomains = xenUnifiedConnectNumOfDomains(conn);
2243 2244 2245 2246 2247 2248 2249 2250
    if (numdomains < 0) {
        return ret;
    }
    if (numdomains > 0){
        if (VIR_ALLOC_N(ids, numdomains) < 0) {
            virReportOOMError();
            goto out;
        }
2251
        if ((numdomains = xenUnifiedConnectListDomains(conn, &ids[0], numdomains)) < 0) {
2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267
            goto out;
        }
    }

    /* Get pci bdf */
    if (xenUnifiedNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0)
        goto out;

    if (virAsprintf(&bdf, "%04x:%02x:%02x.%0x",
                    domain, bus, slot, function) < 0) {
        virReportOOMError();
        goto out;
    }

    xenUnifiedLock(priv);
    /* Check if bdf is assigned to one of active domains */
2268
    for (i = 0; i < numdomains; i++) {
2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286
        xref = xenStoreDomainGetPCIID(conn, ids[i], bdf);
        if (xref == NULL) {
            continue;
        } else {
            ret = ids[i];
            break;
        }
    }
    xenUnifiedUnlock(priv);

    VIR_FREE(xref);
    VIR_FREE(bdf);
out:
    VIR_FREE(ids);

    return ret;
}

2287
static int
2288
xenUnifiedNodeDeviceReAttach(virNodeDevicePtr dev)
2289
{
2290
    virPCIDevicePtr pci;
2291 2292
    unsigned domain, bus, slot, function;
    int ret = -1;
2293
    int domid;
2294 2295 2296 2297

    if (xenUnifiedNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0)
        return -1;

2298
    pci = virPCIDeviceNew(domain, bus, slot, function);
2299 2300 2301
    if (!pci)
        return -1;

2302 2303
    /* Check if device is assigned to an active guest */
    if ((domid = xenUnifiedNodeDeviceAssignedDomainId(dev)) >= 0) {
2304 2305 2306
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Device %s has been assigned to guest %d"),
                       dev->name, domid);
2307 2308 2309
        goto out;
    }

2310
    if (virPCIDeviceReattach(pci, NULL, NULL) < 0)
2311 2312 2313 2314
        goto out;

    ret = 0;
out:
2315
    virPCIDeviceFree(pci);
2316 2317 2318 2319
    return ret;
}

static int
2320
xenUnifiedNodeDeviceReset(virNodeDevicePtr dev)
2321
{
2322
    virPCIDevicePtr pci;
2323 2324 2325 2326 2327 2328
    unsigned domain, bus, slot, function;
    int ret = -1;

    if (xenUnifiedNodeDeviceGetPciInfo(dev, &domain, &bus, &slot, &function) < 0)
        return -1;

2329
    pci = virPCIDeviceNew(domain, bus, slot, function);
2330 2331 2332
    if (!pci)
        return -1;

2333
    if (virPCIDeviceReset(pci, NULL, NULL) < 0)
2334 2335 2336 2337
        goto out;

    ret = 0;
out:
2338
    virPCIDeviceFree(pci);
2339 2340 2341 2342
    return ret;
}


2343 2344
static int
xenUnifiedDomainOpenConsole(virDomainPtr dom,
2345
                            const char *dev_name,
2346 2347 2348 2349 2350 2351 2352 2353 2354 2355
                            virStreamPtr st,
                            unsigned int flags)
{
    virDomainDefPtr def = NULL;
    int ret = -1;
    virDomainChrDefPtr chr = NULL;

    virCheckFlags(0, -1);

    if (dom->id == -1) {
2356 2357
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
2358 2359 2360
        goto cleanup;
    }

2361
    if (dev_name) {
2362
        /* XXX support device aliases in future */
2363 2364
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("Named device aliases are not supported"));
2365 2366 2367 2368 2369 2370 2371
        goto cleanup;
    }

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

2372 2373
    if (def->nconsoles)
        chr = def->consoles[0];
2374 2375 2376 2377
    else if (def->nserials)
        chr = def->serials[0];

    if (!chr) {
2378 2379
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("cannot find default console device"));
2380 2381 2382
        goto cleanup;
    }

2383
    if (chr->source.type != VIR_DOMAIN_CHR_TYPE_PTY) {
2384 2385
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("character device %s is not using a PTY"), dev_name);
2386 2387 2388
        goto cleanup;
    }

2389
    if (virFDStreamOpenFile(st, chr->source.data.file.path,
E
Eric Blake 已提交
2390
                            0, 0, O_RDWR) < 0)
2391 2392 2393 2394 2395 2396 2397
        goto cleanup;

    ret = 0;
cleanup:
    virDomainDefFree(def);
    return ret;
}
2398 2399 2400 2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417

static int
xenUnifiedNodeGetMemoryParameters(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  virTypedParameterPtr params,
                                  int *nparams,
                                  unsigned int flags)
{
    return nodeGetMemoryParameters(params, nparams, flags);
}


static int
xenUnifiedNodeSetMemoryParameters(virConnectPtr conn ATTRIBUTE_UNUSED,
                                  virTypedParameterPtr params,
                                  int nparams,
                                  unsigned int flags)
{
    return nodeSetMemoryParameters(params, nparams, flags);
}

2418 2419 2420 2421 2422 2423 2424 2425 2426 2427 2428

static int
xenUnifiedNodeSuspendForDuration(virConnectPtr conn ATTRIBUTE_UNUSED,
                                 unsigned int target,
                                 unsigned long long duration,
                                 unsigned int flags)
{
    return nodeSuspendForDuration(target, duration, flags);
}


E
Eric Blake 已提交
2429
/*----- Register with libvirt.c, and initialize Xen drivers. -----*/
2430 2431 2432

/* The interface which we export upwards to libvirt.c. */
static virDriver xenUnifiedDriver = {
2433 2434
    .no = VIR_DRV_XEN_UNIFIED,
    .name = "Xen",
2435 2436 2437 2438 2439
    .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 */
2440
    .connectGetHostname = xenUnifiedConnectGetHostname, /* 0.7.3 */
2441
    .connectGetMaxVcpus = xenUnifiedConnectGetMaxVcpus, /* 0.2.1 */
2442
    .nodeGetInfo = xenUnifiedNodeGetInfo, /* 0.1.0 */
2443 2444 2445
    .connectGetCapabilities = xenUnifiedConnectGetCapabilities, /* 0.2.1 */
    .connectListDomains = xenUnifiedConnectListDomains, /* 0.0.3 */
    .connectNumOfDomains = xenUnifiedConnectNumOfDomains, /* 0.0.3 */
2446 2447 2448 2449 2450 2451 2452
    .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 */
2453
    .domainShutdownFlags = xenUnifiedDomainShutdownFlags, /* 0.9.10 */
2454 2455
    .domainReboot = xenUnifiedDomainReboot, /* 0.1.0 */
    .domainDestroy = xenUnifiedDomainDestroy, /* 0.0.3 */
2456
    .domainDestroyFlags = xenUnifiedDomainDestroyFlags, /* 0.9.4 */
2457 2458 2459 2460 2461 2462 2463
    .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 */
2464
    .domainSaveFlags = xenUnifiedDomainSaveFlags, /* 0.9.4 */
2465 2466 2467
    .domainManagedSave = xenUnifiedDomainManagedSave, /* 1.0.1 */
    .domainHasManagedSaveImage = xenUnifiedDomainHasManagedSaveImage, /* 1.0.1 */
    .domainManagedSaveRemove = xenUnifiedDomainManagedSaveRemove, /* 1.0.1 */
2468
    .domainRestore = xenUnifiedDomainRestore, /* 0.0.3 */
2469
    .domainRestoreFlags = xenUnifiedDomainRestoreFlags, /* 0.9.4 */
2470 2471 2472 2473 2474 2475 2476 2477
    .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 */
2478 2479 2480 2481
    .connectDomainXMLFromNative = xenUnifiedConnectDomainXMLFromNative, /* 0.6.4 */
    .connectDomainXMLToNative = xenUnifiedConnectDomainXMLToNative, /* 0.6.4 */
    .connectListDefinedDomains = xenUnifiedConnectListDefinedDomains, /* 0.1.1 */
    .connectNumOfDefinedDomains = xenUnifiedConnectNumOfDefinedDomains, /* 0.1.5 */
2482 2483 2484 2485
    .domainCreate = xenUnifiedDomainCreate, /* 0.1.1 */
    .domainCreateWithFlags = xenUnifiedDomainCreateWithFlags, /* 0.8.2 */
    .domainDefineXML = xenUnifiedDomainDefineXML, /* 0.1.1 */
    .domainUndefine = xenUnifiedDomainUndefine, /* 0.1.1 */
2486
    .domainUndefineFlags = xenUnifiedDomainUndefineFlags, /* 0.9.4 */
2487 2488 2489 2490 2491 2492 2493 2494 2495
    .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 */
2496
    .domainGetSchedulerParametersFlags = xenUnifiedDomainGetSchedulerParametersFlags, /* 0.9.2 */
2497
    .domainSetSchedulerParameters = xenUnifiedDomainSetSchedulerParameters, /* 0.2.3 */
2498
    .domainSetSchedulerParametersFlags = xenUnifiedDomainSetSchedulerParametersFlags, /* 0.9.2 */
2499 2500 2501 2502 2503 2504 2505 2506
    .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 */
2507 2508
    .connectDomainEventRegister = xenUnifiedConnectDomainEventRegister, /* 0.5.0 */
    .connectDomainEventDeregister = xenUnifiedConnectDomainEventDeregister, /* 0.5.0 */
2509
    .nodeDeviceDettach = xenUnifiedNodeDeviceDettach, /* 0.6.1 */
2510
    .nodeDeviceDetachFlags = xenUnifiedNodeDeviceDetachFlags, /* 1.0.5 */
2511 2512
    .nodeDeviceReAttach = xenUnifiedNodeDeviceReAttach, /* 0.6.1 */
    .nodeDeviceReset = xenUnifiedNodeDeviceReset, /* 0.6.1 */
2513 2514
    .connectIsEncrypted = xenUnifiedConnectIsEncrypted, /* 0.7.3 */
    .connectIsSecure = xenUnifiedConnectIsSecure, /* 0.7.3 */
2515 2516 2517
    .domainIsActive = xenUnifiedDomainIsActive, /* 0.7.3 */
    .domainIsPersistent = xenUnifiedDomainIsPersistent, /* 0.7.3 */
    .domainIsUpdated = xenUnifiedDomainIsUpdated, /* 0.8.6 */
2518 2519
    .connectDomainEventRegisterAny = xenUnifiedConnectDomainEventRegisterAny, /* 0.8.0 */
    .connectDomainEventDeregisterAny = xenUnifiedConnectDomainEventDeregisterAny, /* 0.8.0 */
2520
    .domainOpenConsole = xenUnifiedDomainOpenConsole, /* 0.8.6 */
2521
    .connectIsAlive = xenUnifiedConnectIsAlive, /* 0.9.8 */
2522
    .nodeSuspendForDuration = xenUnifiedNodeSuspendForDuration, /* 0.9.8 */
2523 2524
    .nodeGetMemoryParameters = xenUnifiedNodeGetMemoryParameters, /* 0.10.2 */
    .nodeSetMemoryParameters = xenUnifiedNodeSetMemoryParameters, /* 0.10.2 */
2525 2526
};

2527
/**
2528
 * xenRegister:
2529 2530 2531 2532 2533
 *
 * Register xen related drivers
 *
 * Returns the driver priority or -1 in case of error.
 */
2534
int
2535
xenRegister(void)
2536
{
2537
    if (virRegisterStateDriver(&state_driver) == -1) return -1;
J
John Levon 已提交
2538

2539
    return virRegisterDriver(&xenUnifiedDriver);
2540 2541
}

2542 2543 2544 2545 2546 2547 2548 2549 2550
/**
 * xenUnifiedDomainInfoListFree:
 *
 * Free the Domain Info List
 */
void
xenUnifiedDomainInfoListFree(xenUnifiedDomainInfoListPtr list)
{
    int i;
J
John Levon 已提交
2551 2552 2553 2554

    if (list == NULL)
        return;

2555 2556 2557 2558
    for (i=0; i<list->count; i++) {
        VIR_FREE(list->doms[i]->name);
        VIR_FREE(list->doms[i]);
    }
2559
    VIR_FREE(list->doms);
2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581
    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 */
    for (n=0; n < list->count; n++) {
        if (STREQ(list->doms[n]->name, name) &&
            !memcmp(list->doms[n]->uuid, uuid, VIR_UUID_BUFLEN)) {
2582
            VIR_DEBUG("WARNING: dom already tracked");
2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604
            return -1;
        }
    }

    if (VIR_ALLOC(info) < 0)
        goto memory_error;
    if (!(info->name = strdup(name)))
        goto memory_error;

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

    /* Make space on list */
    n = list->count;
    if (VIR_REALLOC_N(list->doms, n + 1) < 0) {
        goto memory_error;
    }

    list->doms[n] = info;
    list->count++;
    return 0;
memory_error:
2605
    virReportOOMError();
2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625
    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)
{
    int i;
    for (i = 0 ; i < list->count ; i++) {
2626
        if (list->doms[i]->id == id &&
2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650
            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]);

            if (i < (list->count - 1))
                memmove(list->doms + i,
                        list->doms + i + 1,
                        sizeof(*(list->doms)) *
                                (list->count - (i + 1)));

            if (VIR_REALLOC_N(list->doms,
                              list->count - 1) < 0) {
                ; /* Failure to reduce memory allocation isn't fatal */
            }
            list->count--;

            return 0;
        }
    }
    return -1;
}

2651

2652 2653
/**
 * xenUnifiedDomainEventDispatch:
D
Daniel P. Berrange 已提交
2654 2655
 * @priv: the connection to dispatch events on
 * @event: the event to dispatch
2656 2657 2658
 *
 * Dispatch domain events to registered callbacks
 *
D
Daniel P. Berrange 已提交
2659 2660
 * The caller must hold the lock in 'priv' before invoking
 *
2661
 */
2662
void xenUnifiedDomainEventDispatch(xenUnifiedPrivatePtr priv,
2663
                                    virDomainEventPtr event)
2664
{
D
Daniel P. Berrange 已提交
2665
    if (!priv)
2666
        return;
2667

2668
    virDomainEventStateQueue(priv->domainEvents, event);
D
Daniel P. Berrange 已提交
2669 2670 2671 2672 2673 2674 2675 2676 2677 2678
}

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

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