xen_driver.c 69.7 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
/* The five Xen drivers below us. */
D
Daniel P. Berrange 已提交
84
static struct xenUnifiedDriver const * const drivers[XEN_UNIFIED_NR_DRIVERS] = {
85 86 87 88
    [XEN_UNIFIED_HYPERVISOR_OFFSET] = &xenHypervisorDriver,
    [XEN_UNIFIED_XEND_OFFSET] = &xenDaemonDriver,
    [XEN_UNIFIED_XS_OFFSET] = &xenStoreDriver,
    [XEN_UNIFIED_XM_OFFSET] = &xenXMDriver,
89 90
};

91
static bool is_privileged = false;
J
John Levon 已提交
92

93 94 95 96 97
/**
 * xenNumaInit:
 * @conn: pointer to the hypervisor connection
 *
 * Initializer for previous variables. We currently assume that
R
Richard W.M. Jones 已提交
98
 * the number of physical CPU and the number of NUMA cell is fixed
99 100 101 102 103
 * until reboot which might be false in future Xen implementations.
 */
static void
xenNumaInit(virConnectPtr conn) {
    virNodeInfo nodeInfo;
D
Daniel P. Berrange 已提交
104
    xenUnifiedPrivatePtr priv;
105 106 107 108 109 110
    int ret;

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

D
Daniel P. Berrange 已提交
111
    priv = conn->privateData;
112

D
Daniel P. Berrange 已提交
113 114
    priv->nbNodeCells = nodeInfo.nodes;
    priv->nbNodeCpus = nodeInfo.cpus;
115 116
}

D
Daniel P. Berrange 已提交
117

118 119 120 121 122 123 124 125 126 127 128 129 130 131
/**
 * 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 已提交
132
    int ncpus;
133
    int nb_vcpu;
134
    virBitmapPtr cpulist = NULL;
135 136 137 138 139 140
    unsigned char *cpumap = NULL;
    size_t cpumaplen;
    int nb = 0;
    int n, m;
    virVcpuInfoPtr cpuinfo = NULL;
    virNodeInfo nodeinfo;
D
Daniel P. Berrange 已提交
141
    xenUnifiedPrivatePtr priv;
142 143

    if (!VIR_IS_CONNECTED_DOMAIN(dom))
144
        return NULL;
145

D
Daniel P. Berrange 已提交
146 147 148
    priv = dom->conn->privateData;

    if (priv->nbNodeCpus <= 0)
149
        return NULL;
150 151
    nb_vcpu = xenUnifiedDomainGetMaxVcpus(dom);
    if (nb_vcpu <= 0)
152
        return NULL;
153
    if (xenUnifiedNodeGetInfo(dom->conn, &nodeinfo) < 0)
154
        return NULL;
155

156
    if (!(cpulist = virBitmapNew(priv->nbNodeCpus))) {
157
        virReportOOMError();
158
        goto done;
159 160
    }
    if (VIR_ALLOC_N(cpuinfo, nb_vcpu) < 0) {
161
        virReportOOMError();
162
        goto done;
163
    }
164
    cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo));
165
    if (xalloc_oversized(nb_vcpu, cpumaplen) ||
166
        VIR_ALLOC_N(cpumap, nb_vcpu * cpumaplen) < 0) {
167
        virReportOOMError();
168
        goto done;
169
    }
170 171 172

    if ((ncpus = xenUnifiedDomainGetVcpus(dom, cpuinfo, nb_vcpu,
                                          cpumap, cpumaplen)) >= 0) {
173
        for (n = 0 ; n < ncpus ; n++) {
D
Daniel P. Berrange 已提交
174
            for (m = 0 ; m < priv->nbNodeCpus; m++) {
175 176 177
                bool used;
                ignore_value(virBitmapGetBit(cpulist, m, &used));
                if ((!used) &&
178
                    (VIR_CPU_USABLE(cpumap, cpumaplen, n, m))) {
179
                    ignore_value(virBitmapSetBit(cpulist, m));
180 181
                    nb++;
                    /* if all CPU are used just return NULL */
D
Daniel P. Berrange 已提交
182
                    if (nb == priv->nbNodeCpus)
183 184 185 186 187
                        goto done;

                }
            }
        }
188
        res = virBitmapFormat(cpulist);
189 190 191
    }

done:
192
    virBitmapFree(cpulist);
193 194
    VIR_FREE(cpumap);
    VIR_FREE(cpuinfo);
195
    return res;
196 197
}

J
John Levon 已提交
198
static int
199
xenUnifiedStateInitialize(bool privileged,
200 201
                          virStateInhibitCallback callback ATTRIBUTE_UNUSED,
                          void *opaque ATTRIBUTE_UNUSED)
J
John Levon 已提交
202
{
203 204 205
    /* Don't allow driver to work in non-root libvirtd */
    if (privileged)
        is_privileged = true;
J
John Levon 已提交
206 207 208 209
    return 0;
}

static virStateDriver state_driver = {
210
    .name = "Xen",
211
    .stateInitialize = xenUnifiedStateInitialize,
J
John Levon 已提交
212 213
};

214 215 216 217 218 219 220 221 222 223 224
/*----- 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.
 */

225
static int
226
xenUnifiedProbe(void)
227 228 229
{
#ifdef __linux__
    if (virFileExists("/proc/xen"))
230
        return 1;
231
#endif
232
#ifdef __sun
233
    int fd;
234

235 236
    if ((fd = open("/dev/xen/domcaps", O_RDONLY)) >= 0) {
        VIR_FORCE_CLOSE(fd);
237
        return 1;
238 239
    }
#endif
240
    return 0;
241 242
}

J
Jim Fehlig 已提交
243 244
#ifdef WITH_LIBXL
static int
245
xenUnifiedXendProbe(void)
J
Jim Fehlig 已提交
246 247 248 249 250 251 252 253 254 255 256 257 258 259
{
    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

260

261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
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;
}


277 278
virDomainDefParserConfig xenDomainDefParserConfig = {
    .macPrefix = { 0x00, 0x16, 0x3e },
279
    .devicesPostParseCallback = xenDomainDeviceDefPostParse,
280 281
};

282

283 284 285 286 287 288 289 290
virDomainXMLOptionPtr
xenDomainXMLConfInit(void)
{
    return virDomainXMLOptionNew(&xenDomainDefParserConfig,
                                 NULL, NULL);
}


291
static virDrvOpenStatus
292
xenUnifiedConnectOpen(virConnectPtr conn, virConnectAuthPtr auth, unsigned int flags)
293
{
294
    xenUnifiedPrivatePtr priv;
295
    char ebuf[1024];
296

J
John Levon 已提交
297 298 299 300
    /*
     * Only the libvirtd instance can open this driver.
     * Everything else falls back to the remote driver.
     */
301
    if (!is_privileged)
J
John Levon 已提交
302 303
        return VIR_DRV_OPEN_DECLINED;

304 305 306 307
    if (conn->uri == NULL) {
        if (!xenUnifiedProbe())
            return VIR_DRV_OPEN_DECLINED;

308
        if (!(conn->uri = virURIParse("xen:///")))
309
            return VIR_DRV_OPEN_ERROR;
310 311 312 313 314 315 316 317 318 319 320 321
    } 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, "/")) {
322 323 324
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("unexpected Xen URI path '%s', try xen:///"),
                               conn->uri->path);
325 326
                return VIR_DRV_OPEN_ERROR;
            }
327

328 329 330 331 332 333
            /* 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 {
334
            return VIR_DRV_OPEN_DECLINED;
335 336
        }
    }
337

J
Jim Fehlig 已提交
338 339 340 341 342 343 344
#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

345 346
    /* We now know the URI is definitely for this driver, so beyond
     * here, don't return DECLINED, always use ERROR */
347 348

    /* Allocate per-connection private data. */
349
    if (VIR_ALLOC(priv) < 0) {
350
        virReportOOMError();
351 352
        return VIR_DRV_OPEN_ERROR;
    }
D
Daniel P. Berrange 已提交
353
    if (virMutexInit(&priv->lock) < 0) {
354 355
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("cannot initialize mutex"));
D
Daniel P. Berrange 已提交
356 357 358
        VIR_FREE(priv);
        return VIR_DRV_OPEN_ERROR;
    }
359

360
    if (!(priv->domainEvents = virDomainEventStateNew())) {
D
Daniel P. Berrange 已提交
361 362
        virMutexDestroy(&priv->lock);
        VIR_FREE(priv);
363 364
        return VIR_DRV_OPEN_ERROR;
    }
D
Daniel P. Berrange 已提交
365 366
    conn->privateData = priv;

367 368 369 370 371
    priv->handle = -1;
    priv->xendConfigVersion = -1;
    priv->xshandle = NULL;


372 373 374 375 376 377
    /* 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;
378

379
    /* XenD is required to succeed */
380
    VIR_DEBUG("Trying XenD sub-driver");
381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399
    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;
400

D
Daniel P. Berrange 已提交
401 402
    xenNumaInit(conn);

403
    if (!(priv->caps = xenHypervisorMakeCapabilities(conn))) {
404
        VIR_DEBUG("Failed to make capabilities");
405
        goto error;
406 407
    }

408
    if (!(priv->xmlopt = xenDomainXMLConfInit()))
409
        goto error;
410

411
#if WITH_XEN_INOTIFY
412 413 414 415 416
    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;
417 418
#endif

E
Eric Blake 已提交
419
    if (!(priv->saveDir = strdup(XEN_SAVE_DIR))) {
420
        virReportOOMError();
421
        goto error;
422 423 424
    }

    if (virFileMakePath(priv->saveDir) < 0) {
425
        VIR_ERROR(_("Errored to create save dir '%s': %s"), priv->saveDir,
426
                  virStrerror(errno, ebuf, sizeof(ebuf)));
427
        goto error;
428 429
    }

430
    return VIR_DRV_OPEN_SUCCESS;
431

432
error:
433
    VIR_DEBUG("Failed to activate a mandatory sub-driver");
434 435 436 437 438 439 440 441 442 443 444 445
#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 已提交
446
    virMutexDestroy(&priv->lock);
447
    VIR_FREE(priv->saveDir);
448
    VIR_FREE(priv);
D
Daniel P. Berrange 已提交
449
    conn->privateData = NULL;
450
    return VIR_DRV_OPEN_ERROR;
451 452 453
}

static int
454
xenUnifiedConnectClose(virConnectPtr conn)
455
{
456
    xenUnifiedPrivatePtr priv = conn->privateData;
457

458
    virObjectUnref(priv->caps);
459
    virObjectUnref(priv->xmlopt);
460
    virDomainEventStateFree(priv->domainEvents);
461

462 463 464 465 466 467 468 469 470 471 472 473
#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);
474

475
    VIR_FREE(priv->saveDir);
D
Daniel P. Berrange 已提交
476 477
    virMutexDestroy(&priv->lock);
    VIR_FREE(conn->privateData);
478

479
    return 0;
480 481
}

482 483 484 485 486 487 488 489 490 491 492

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


493
static const char *
494
xenUnifiedConnectGetType(virConnectPtr conn ATTRIBUTE_UNUSED)
495
{
496
    return "Xen";
497 498
}

499 500
/* Which features are supported by this driver? */
static int
501
xenUnifiedConnectSupportsFeature(virConnectPtr conn ATTRIBUTE_UNUSED, int feature)
502 503
{
    switch (feature) {
504 505 506 507 508
    case VIR_DRV_FEATURE_MIGRATION_V1:
    case VIR_DRV_FEATURE_MIGRATION_DIRECT:
        return 1;
    default:
        return 0;
509 510 511
    }
}

512
static int
513
xenUnifiedConnectGetVersion(virConnectPtr conn, unsigned long *hvVer)
514
{
515
    return xenHypervisorGetVersion(conn, hvVer);
516 517
}

518 519 520 521 522 523 524

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


525
static int
526
xenUnifiedConnectIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED)
527 528 529 530 531
{
    return 0;
}

static int
532
xenUnifiedConnectIsSecure(virConnectPtr conn)
533
{
534
    xenUnifiedPrivatePtr priv = conn->privateData;
535 536 537 538 539 540 541 542 543 544
    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;
}

545
static int
546
xenUnifiedConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED)
547 548 549 550 551
{
    /* XenD reconnects for each request */
    return 1;
}

552
int
553
xenUnifiedConnectGetMaxVcpus(virConnectPtr conn, const char *type)
554
{
555
    if (type && STRCASENEQ(type, "Xen")) {
556
        virReportError(VIR_ERR_INVALID_ARG, __FUNCTION__);
557 558
        return -1;
    }
559

560
    return xenHypervisorGetMaxVcpus(conn, type);
561 562 563
}

static int
564
xenUnifiedNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info)
565
{
566
    return xenDaemonNodeGetInfo(conn, info);
567 568 569
}

static char *
570
xenUnifiedConnectGetCapabilities(virConnectPtr conn)
571
{
D
Daniel P. Berrange 已提交
572 573
    xenUnifiedPrivatePtr priv = conn->privateData;
    char *xml;
574

D
Daniel P. Berrange 已提交
575
    if (!(xml = virCapabilitiesFormatXML(priv->caps))) {
576
        virReportOOMError();
D
Daniel P. Berrange 已提交
577 578
        return NULL;
    }
579

D
Daniel P. Berrange 已提交
580
    return xml;
581 582 583
}

static int
584
xenUnifiedConnectListDomains(virConnectPtr conn, int *ids, int maxids)
585
{
586
    return xenStoreListDomains(conn, ids, maxids);
587 588 589
}

static int
590
xenUnifiedConnectNumOfDomains(virConnectPtr conn)
591
{
592
    return xenStoreNumOfDomains(conn);
593 594 595
}

static virDomainPtr
596 597
xenUnifiedDomainCreateXML(virConnectPtr conn,
                          const char *xmlDesc, unsigned int flags)
598
{
599
    virCheckFlags(0, NULL);
600

601
    return xenDaemonCreateXML(conn, xmlDesc);
602 603 604
}

static virDomainPtr
605
xenUnifiedDomainLookupByID(virConnectPtr conn, int id)
606
{
607
    virDomainPtr ret = NULL;
608

609
    ret = xenHypervisorLookupDomainByID(conn, id);
610

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

614
    return ret;
615 616 617
}

static virDomainPtr
618 619
xenUnifiedDomainLookupByUUID(virConnectPtr conn,
                             const unsigned char *uuid)
620
{
621
    xenUnifiedPrivatePtr priv = conn->privateData;
622
    virDomainPtr ret;
623

624
    ret = xenHypervisorLookupDomainByUUID(conn, uuid);
625

626
    /* Try XM for inactive domains. */
627 628 629 630 631
    if (!ret) {
        if (priv->xendConfigVersion <= XEND_CONFIG_VERSION_3_0_3)
            ret = xenXMDomainLookupByUUID(conn, uuid);
        else
            ret = xenDaemonLookupByUUID(conn, uuid);
632 633
    }

634 635 636 637
    if (!ret && virGetLastError() == NULL)
        virReportError(VIR_ERR_NO_DOMAIN, __FUNCTION__);

    return ret;
638 639 640
}

static virDomainPtr
641 642
xenUnifiedDomainLookupByName(virConnectPtr conn,
                             const char *name)
643
{
644
    xenUnifiedPrivatePtr priv = conn->privateData;
645
    virDomainPtr ret;
646

647
    ret = xenDaemonLookupByName(conn, name);
648 649

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

653 654 655 656
    if (!ret && virGetLastError() == NULL)
        virReportError(VIR_ERR_NO_DOMAIN, __FUNCTION__);

    return ret;
657 658
}

659 660 661 662

static int
xenUnifiedDomainIsActive(virDomainPtr dom)
{
663
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
664 665 666 667
    virDomainPtr currdom;
    int ret = -1;

    /* ID field in dom may be outdated, so re-lookup */
668 669 670 671 672 673 674 675 676
    currdom = xenHypervisorLookupDomainByUUID(dom->conn, dom->uuid);

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

    if (currdom) {
        ret = currdom->id == -1 ? 0 : 1;
        virDomainFree(currdom);
681 682
    } else if (virGetLastError() == NULL) {
        virReportError(VIR_ERR_NO_DOMAIN, __FUNCTION__);
683 684 685 686 687 688
    }

    return ret;
}

static int
689
xenUnifiedDomainIsPersistent(virDomainPtr dom)
690
{
691
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
692 693 694 695 696 697 698 699 700 701 702 703 704
    virDomainPtr currdom = NULL;
    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 */
        currdom = xenXMDomainLookupByUUID(dom->conn, dom->uuid);
        if (currdom)
            ret = 1;
        else
            ret = 0;
    } else {
        /* New Xen with inactive domain management */
705 706 707 708 709 710 711 712 713 714 715 716 717 718 719
        currdom = xenDaemonLookupByUUID(dom->conn, dom->uuid);
        if (currdom) {
            if (currdom->id == -1) {
                /* 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();
                    goto done;
720
                }
721 722 723 724
                if (access(path, R_OK) == 0)
                    ret = 1;
                else if (errno == ENOENT)
                    ret = 0;
725 726 727 728 729 730 731 732 733 734 735
            }
        }
    }

done:
    if (currdom)
        virDomainFree(currdom);

    return ret;
}

736 737 738 739 740 741
static int
xenUnifiedDomainIsUpdated(virDomainPtr dom ATTRIBUTE_UNUSED)
{
    return 0;
}

742
static int
743
xenUnifiedDomainSuspend(virDomainPtr dom)
744
{
745
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
746
    int i;
747

748 749 750
    /* Try non-hypervisor methods first, then hypervisor direct method
     * as a last resort.
     */
751
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
752
        if (i != XEN_UNIFIED_HYPERVISOR_OFFSET &&
753
            priv->opened[i] &&
E
Eric Blake 已提交
754
            drivers[i]->xenDomainSuspend &&
755
            drivers[i]->xenDomainSuspend(dom) == 0)
756
            return 0;
757

758
    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET] &&
E
Eric Blake 已提交
759
        xenHypervisorPauseDomain(dom) == 0)
760
        return 0;
761

762
    return -1;
763 764 765
}

static int
766
xenUnifiedDomainResume(virDomainPtr dom)
767
{
768
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
769
    int i;
770

771 772 773
    /* Try non-hypervisor methods first, then hypervisor direct method
     * as a last resort.
     */
774
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
775
        if (i != XEN_UNIFIED_HYPERVISOR_OFFSET &&
776
            priv->opened[i] &&
E
Eric Blake 已提交
777
            drivers[i]->xenDomainResume &&
778
            drivers[i]->xenDomainResume(dom) == 0)
779
            return 0;
780

781
    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET] &&
E
Eric Blake 已提交
782
        xenHypervisorResumeDomain(dom) == 0)
783
        return 0;
784

785
    return -1;
786 787 788
}

static int
789 790
xenUnifiedDomainShutdownFlags(virDomainPtr dom,
                              unsigned int flags)
791
{
792
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
793
    int i;
794

795 796
    virCheckFlags(0, -1);

797 798
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] &&
E
Eric Blake 已提交
799
            drivers[i]->xenDomainShutdown &&
800
            drivers[i]->xenDomainShutdown(dom) == 0)
801
            return 0;
802

803
    return -1;
804 805
}

806 807 808 809 810 811
static int
xenUnifiedDomainShutdown(virDomainPtr dom)
{
    return xenUnifiedDomainShutdownFlags(dom, 0);
}

812
static int
813
xenUnifiedDomainReboot(virDomainPtr dom, unsigned int flags)
814
{
815
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
816
    int i;
817

818 819
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] &&
E
Eric Blake 已提交
820
            drivers[i]->xenDomainReboot &&
821
            drivers[i]->xenDomainReboot(dom, flags) == 0)
822
            return 0;
823

824
    return -1;
825 826
}

827 828 829 830
static int
xenUnifiedDomainDestroyFlags(virDomainPtr dom,
                             unsigned int flags)
{
831
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
832 833 834 835 836 837 838 839 840 841
    int i;

    virCheckFlags(0, -1);

    /* Try non-hypervisor methods first, then hypervisor direct method
     * as a last resort.
     */
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (i != XEN_UNIFIED_HYPERVISOR_OFFSET &&
            priv->opened[i] &&
E
Eric Blake 已提交
842 843
            drivers[i]->xenDomainDestroyFlags &&
            drivers[i]->xenDomainDestroyFlags(dom, flags) == 0)
844 845 846
            return 0;

    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET] &&
E
Eric Blake 已提交
847
        xenHypervisorDestroyDomainFlags(dom, flags) == 0)
848 849 850 851 852
        return 0;

    return -1;
}

853 854 855 856 857 858
static int
xenUnifiedDomainDestroy(virDomainPtr dom)
{
    return xenUnifiedDomainDestroyFlags(dom, 0);
}

859
static char *
860
xenUnifiedDomainGetOSType(virDomainPtr dom)
861
{
862
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
863 864
    int i;
    char *ret;
865

866
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
E
Eric Blake 已提交
867
        if (priv->opened[i] && drivers[i]->xenDomainGetOSType) {
868
            ret = drivers[i]->xenDomainGetOSType(dom);
869 870
            if (ret) return ret;
        }
871

872
    return NULL;
873 874
}

875
static unsigned long long
876
xenUnifiedDomainGetMaxMemory(virDomainPtr dom)
877
{
878
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
879
    int i;
880
    unsigned long long ret;
881

882
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
E
Eric Blake 已提交
883
        if (priv->opened[i] && drivers[i]->xenDomainGetMaxMemory) {
884
            ret = drivers[i]->xenDomainGetMaxMemory(dom);
885 886
            if (ret != 0) return ret;
        }
887

888
    return 0;
889 890 891
}

static int
892
xenUnifiedDomainSetMaxMemory(virDomainPtr dom, unsigned long memory)
893
{
894
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
895
    int i;
896

897 898
    /* Prefer xend for setting max memory */
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
899
        if (xenDaemonDomainSetMaxMemory(dom, memory) == 0)
900 901 902
            return 0;
    }

903
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
904 905
        if (i != XEN_UNIFIED_XEND_OFFSET &&
            priv->opened[i] &&
E
Eric Blake 已提交
906
            drivers[i]->xenDomainSetMaxMemory &&
907
            drivers[i]->xenDomainSetMaxMemory(dom, memory) == 0)
908
            return 0;
909

910
    return -1;
911 912 913
}

static int
914
xenUnifiedDomainSetMemory(virDomainPtr dom, unsigned long memory)
915
{
916
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
917
    int i;
918

919 920
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] &&
E
Eric Blake 已提交
921
            drivers[i]->xenDomainSetMemory &&
922
            drivers[i]->xenDomainSetMemory(dom, memory) == 0)
923
            return 0;
924

925
    return -1;
926 927 928
}

static int
929
xenUnifiedDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info)
930
{
931
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
932
    int i;
933

934 935
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] &&
E
Eric Blake 已提交
936
            drivers[i]->xenDomainGetInfo &&
937
            drivers[i]->xenDomainGetInfo(dom, info) == 0)
938
            return 0;
939

940
    return -1;
941 942
}

943 944 945 946 947 948
static int
xenUnifiedDomainGetState(virDomainPtr dom,
                         int *state,
                         int *reason,
                         unsigned int flags)
{
949
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983
    int ret;

    virCheckFlags(0, -1);

    /* trying drivers in the same order as GetInfo for consistent results:
     * hypervisor, xend, xs, and xm */

    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET]) {
        ret = xenHypervisorGetDomainState(dom, state, reason, flags);
        if (ret >= 0)
            return ret;
    }

    if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
        ret = xenDaemonDomainGetState(dom, state, reason, flags);
        if (ret >= 0)
            return ret;
    }

    if (priv->opened[XEN_UNIFIED_XS_OFFSET]) {
        ret = xenStoreDomainGetState(dom, state, reason, flags);
        if (ret >= 0)
            return ret;
    }

    if (priv->opened[XEN_UNIFIED_XM_OFFSET]) {
        ret = xenXMDomainGetState(dom, state, reason, flags);
        if (ret >= 0)
            return ret;
    }

    return -1;
}

984
static int
985 986
xenUnifiedDomainSaveFlags(virDomainPtr dom, const char *to, const char *dxml,
                          unsigned int flags)
987
{
988
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
989

990 991
    virCheckFlags(0, -1);
    if (dxml) {
992 993
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
994 995 996
        return -1;
    }

997 998
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
        return xenDaemonDomainSave(dom, to);
999
    return -1;
1000 1001 1002
}

static int
1003 1004 1005 1006 1007
xenUnifiedDomainSave(virDomainPtr dom, const char *to)
{
    return xenUnifiedDomainSaveFlags(dom, to, NULL, 0);
}

1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024
static char *
xenUnifiedDomainManagedSavePath(xenUnifiedPrivatePtr priv, virDomainPtr dom)
{
    char *ret;

    if (virAsprintf(&ret, "%s/%s.save", priv->saveDir, dom->name) < 0) {
        virReportOOMError();
        return NULL;
    }

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

static int
xenUnifiedDomainManagedSave(virDomainPtr dom, unsigned int flags)
{
1025
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045
    char *name;
    int ret = -1;

    virCheckFlags(0, -1);

    name = xenUnifiedDomainManagedSavePath(priv, dom);
    if (!name)
        goto cleanup;

    if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
        ret = xenDaemonDomainSave(dom, name);

cleanup:
    VIR_FREE(name);
    return ret;
}

static int
xenUnifiedDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags)
{
1046
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063
    char *name;
    int ret = -1;

    virCheckFlags(0, -1);

    name = xenUnifiedDomainManagedSavePath(priv, dom);
    if (!name)
        return ret;

    ret = virFileExists(name);
    VIR_FREE(name);
    return ret;
}

static int
xenUnifiedDomainManagedSaveRemove(virDomainPtr dom, unsigned int flags)
{
1064
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078
    char *name;
    int ret = -1;

    virCheckFlags(0, -1);

    name = xenUnifiedDomainManagedSavePath(priv, dom);
    if (!name)
        return ret;

    ret = unlink(name);
    VIR_FREE(name);
    return ret;
}

1079 1080 1081
static int
xenUnifiedDomainRestoreFlags(virConnectPtr conn, const char *from,
                             const char *dxml, unsigned int flags)
1082
{
1083
    xenUnifiedPrivatePtr priv = conn->privateData;
1084

1085 1086
    virCheckFlags(0, -1);
    if (dxml) {
1087 1088
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
1089 1090 1091
        return -1;
    }

1092 1093
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
        return xenDaemonDomainRestore(conn, from);
1094
    return -1;
1095 1096
}

1097
static int
1098
xenUnifiedDomainRestore(virConnectPtr conn, const char *from)
1099 1100 1101 1102
{
    return xenUnifiedDomainRestoreFlags(conn, from, NULL, 0);
}

1103
static int
1104
xenUnifiedDomainCoreDump(virDomainPtr dom, const char *to, unsigned int flags)
1105
{
1106
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1107

1108 1109
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
        return xenDaemonDomainCoreDump(dom, to, flags);
1110
    return -1;
1111 1112 1113
}

static int
1114 1115
xenUnifiedDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
                              unsigned int flags)
1116
{
1117
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1118
    int ret;
1119

1120 1121 1122 1123 1124 1125 1126 1127 1128
    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)) {
1129 1130
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid flag combination: (0x%x)"), flags);
1131 1132 1133
        return -1;
    }
    if (!nvcpus || (unsigned short) nvcpus != nvcpus) {
1134 1135
        virReportError(VIR_ERR_INVALID_ARG,
                       _("argument out of range: %d"), nvcpus);
1136 1137 1138
        return -1;
    }

1139 1140 1141
    /* Try non-hypervisor methods first, then hypervisor direct method
     * as a last resort.
     */
1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
        ret = xenDaemonDomainSetVcpusFlags(dom, nvcpus, flags);
        if (ret != -2)
            return ret;
    }
    if (priv->opened[XEN_UNIFIED_XM_OFFSET]) {
        ret = xenXMDomainSetVcpusFlags(dom, nvcpus, flags);
        if (ret != -2)
            return ret;
    }
    if (flags == VIR_DOMAIN_VCPU_LIVE)
        return xenHypervisorSetVcpus(dom, nvcpus);
1154

1155
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1156
    return -1;
1157 1158
}

1159
static int
1160
xenUnifiedDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus)
1161
{
1162 1163 1164 1165 1166 1167
    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.  */
    if (dom) {
1168
        xenUnifiedPrivatePtr priv = dom->conn->privateData;
1169
        if (priv->xendConfigVersion >= XEND_CONFIG_VERSION_3_0_4)
1170
            flags |= VIR_DOMAIN_VCPU_CONFIG;
1171
        return xenUnifiedDomainSetVcpusFlags(dom, nvcpus, flags);
1172
    }
1173
    return -1;
1174 1175
}

1176
static int
1177 1178
xenUnifiedDomainPinVcpu(virDomainPtr dom, unsigned int vcpu,
                        unsigned char *cpumap, int maplen)
1179
{
1180
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1181
    int i;
1182

1183 1184
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
        if (priv->opened[i] &&
E
Eric Blake 已提交
1185
            drivers[i]->xenDomainPinVcpu &&
1186
            drivers[i]->xenDomainPinVcpu(dom, vcpu, cpumap, maplen) == 0)
1187
            return 0;
1188

1189
    return -1;
1190 1191 1192
}

static int
1193 1194 1195
xenUnifiedDomainGetVcpus(virDomainPtr dom,
                         virVcpuInfoPtr info, int maxinfo,
                         unsigned char *cpumaps, int maplen)
1196
{
1197
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1198
    int i, ret;
1199

1200
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
E
Eric Blake 已提交
1201
        if (priv->opened[i] && drivers[i]->xenDomainGetVcpus) {
1202
            ret = drivers[i]->xenDomainGetVcpus(dom, info, maxinfo, cpumaps, maplen);
1203 1204 1205
            if (ret > 0)
                return ret;
        }
1206
    return -1;
1207 1208 1209
}

static int
1210
xenUnifiedDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags)
1211
{
1212
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1213
    int ret;
1214

1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230
    virCheckFlags(VIR_DOMAIN_VCPU_LIVE |
                  VIR_DOMAIN_VCPU_CONFIG |
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);

    if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
        ret = xenDaemonDomainGetVcpusFlags(dom, flags);
        if (ret != -2)
            return ret;
    }
    if (priv->opened[XEN_UNIFIED_XM_OFFSET]) {
        ret = xenXMDomainGetVcpusFlags(dom, flags);
        if (ret != -2)
            return ret;
    }
    if (flags == (VIR_DOMAIN_VCPU_CONFIG | VIR_DOMAIN_VCPU_MAXIMUM))
        return xenHypervisorGetVcpuMax(dom);
1231

1232
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1233
    return -1;
1234 1235
}

1236
static int
1237
xenUnifiedDomainGetMaxVcpus(virDomainPtr dom)
1238 1239 1240 1241 1242
{
    return xenUnifiedDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_LIVE |
                                               VIR_DOMAIN_VCPU_MAXIMUM));
}

1243
static char *
1244
xenUnifiedDomainGetXMLDesc(virDomainPtr dom, unsigned int flags)
1245
{
1246
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1247

1248
    if (dom->id == -1 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
1249
        if (priv->opened[XEN_UNIFIED_XM_OFFSET])
1250
            return xenXMDomainGetXMLDesc(dom, flags);
1251 1252 1253
    } else {
        if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
            char *cpus, *res;
D
Daniel P. Berrange 已提交
1254
            xenUnifiedLock(priv);
1255
            cpus = xenDomainUsedCpus(dom);
D
Daniel P. Berrange 已提交
1256
            xenUnifiedUnlock(priv);
1257
            res = xenDaemonDomainGetXMLDesc(dom, flags, cpus);
1258
            VIR_FREE(cpus);
1259
            return res;
1260
        }
1261
    }
1262

1263
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1264
    return NULL;
1265 1266
}

1267 1268

static char *
1269 1270 1271 1272
xenUnifiedConnectDomainXMLFromNative(virConnectPtr conn,
                                     const char *format,
                                     const char *config,
                                     unsigned int flags)
1273 1274 1275 1276
{
    virDomainDefPtr def = NULL;
    char *ret = NULL;
    virConfPtr conf = NULL;
1277 1278 1279
    int id;
    char * tty;
    int vncport;
1280
    xenUnifiedPrivatePtr priv = conn->privateData;
1281

E
Eric Blake 已提交
1282 1283
    virCheckFlags(0, NULL);

1284 1285
    if (STRNEQ(format, XEN_CONFIG_FORMAT_XM) &&
        STRNEQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
1286 1287
        virReportError(VIR_ERR_INVALID_ARG,
                       _("unsupported config type %s"), format);
1288 1289 1290 1291
        return NULL;
    }

    if (STREQ(format, XEN_CONFIG_FORMAT_XM)) {
1292
        conf = virConfReadMem(config, strlen(config), 0);
1293 1294 1295
        if (!conf)
            goto cleanup;

M
Markus Groß 已提交
1296
        def = xenParseXM(conf, priv->xendConfigVersion, priv->caps);
1297
    } else if (STREQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
1298 1299 1300 1301 1302
        id = xenGetDomIdFromSxprString(config, priv->xendConfigVersion);
        xenUnifiedLock(priv);
        tty = xenStoreDomainGetConsolePath(conn, id);
        vncport = xenStoreDomainGetVNCPort(conn, id);
        xenUnifiedUnlock(priv);
M
Markus Groß 已提交
1303
        def = xenParseSxprString(config, priv->xendConfigVersion, tty,
1304
                                       vncport);
1305 1306 1307 1308
    }
    if (!def)
        goto cleanup;

1309
    ret = virDomainDefFormat(def, 0);
1310 1311 1312

cleanup:
    virDomainDefFree(def);
1313 1314
    if (conf)
        virConfFree(conf);
1315 1316 1317 1318 1319 1320
    return ret;
}


#define MAX_CONFIG_SIZE (1024 * 65)
static char *
1321 1322 1323 1324
xenUnifiedConnectDomainXMLToNative(virConnectPtr conn,
                                   const char *format,
                                   const char *xmlData,
                                   unsigned int flags)
1325 1326 1327 1328
{
    virDomainDefPtr def = NULL;
    char *ret = NULL;
    virConfPtr conf = NULL;
1329
    xenUnifiedPrivatePtr priv = conn->privateData;
1330

E
Eric Blake 已提交
1331 1332
    virCheckFlags(0, NULL);

1333 1334
    if (STRNEQ(format, XEN_CONFIG_FORMAT_XM) &&
        STRNEQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
1335 1336
        virReportError(VIR_ERR_INVALID_ARG,
                       _("unsupported config type %s"), format);
1337 1338 1339
        goto cleanup;
    }

1340 1341
    if (!(def = virDomainDefParseString(xmlData, priv->caps, priv->xmlopt,
                                        1 << VIR_DOMAIN_VIRT_XEN, 0)))
1342 1343 1344 1345
        goto cleanup;

    if (STREQ(format, XEN_CONFIG_FORMAT_XM)) {
        int len = MAX_CONFIG_SIZE;
M
Markus Groß 已提交
1346
        conf = xenFormatXM(conn, def, priv->xendConfigVersion);
1347 1348 1349 1350
        if (!conf)
            goto cleanup;

        if (VIR_ALLOC_N(ret, len) < 0) {
1351
            virReportOOMError();
1352 1353 1354 1355 1356 1357 1358 1359
            goto cleanup;
        }

        if (virConfWriteMem(ret, &len, conf) < 0) {
            VIR_FREE(ret);
            goto cleanup;
        }
    } else if (STREQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
M
Markus Groß 已提交
1360
        ret = xenFormatSxpr(conn, def, priv->xendConfigVersion);
1361 1362 1363 1364 1365 1366 1367 1368 1369 1370
    }

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


1371
static int
1372 1373 1374 1375 1376 1377 1378 1379
xenUnifiedDomainMigratePrepare(virConnectPtr dconn,
                               char **cookie,
                               int *cookielen,
                               const char *uri_in,
                               char **uri_out,
                               unsigned long flags,
                               const char *dname,
                               unsigned long resource)
1380
{
1381
    xenUnifiedPrivatePtr priv = dconn->privateData;
1382

E
Eric Blake 已提交
1383 1384
    virCheckFlags(XEN_MIGRATION_FLAGS, -1);

1385
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
1386 1387 1388
        return xenDaemonDomainMigratePrepare(dconn, cookie, cookielen,
                                             uri_in, uri_out,
                                             flags, dname, resource);
1389

1390
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1391 1392 1393 1394
    return -1;
}

static int
1395 1396 1397 1398 1399 1400 1401
xenUnifiedDomainMigratePerform(virDomainPtr dom,
                               const char *cookie,
                               int cookielen,
                               const char *uri,
                               unsigned long flags,
                               const char *dname,
                               unsigned long resource)
1402
{
1403
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1404

E
Eric Blake 已提交
1405 1406
    virCheckFlags(XEN_MIGRATION_FLAGS, -1);

1407
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
1408 1409
        return xenDaemonDomainMigratePerform(dom, cookie, cookielen, uri,
                                             flags, dname, resource);
1410

1411
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1412 1413 1414 1415
    return -1;
}

static virDomainPtr
1416 1417 1418 1419 1420 1421
xenUnifiedDomainMigrateFinish(virConnectPtr dconn,
                              const char *dname,
                              const char *cookie ATTRIBUTE_UNUSED,
                              int cookielen ATTRIBUTE_UNUSED,
                              const char *uri ATTRIBUTE_UNUSED,
                              unsigned long flags)
1422
{
1423 1424 1425 1426
    virDomainPtr dom = NULL;
    char *domain_xml = NULL;
    virDomainPtr dom_new = NULL;

E
Eric Blake 已提交
1427 1428
    virCheckFlags(XEN_MIGRATION_FLAGS, NULL);

1429
    dom = xenUnifiedDomainLookupByName(dconn, dname);
1430 1431 1432 1433 1434
    if (! dom) {
        return NULL;
    }

    if (flags & VIR_MIGRATE_PERSIST_DEST) {
1435
        domain_xml = xenDaemonDomainGetXMLDesc(dom, 0, NULL);
1436
        if (! domain_xml) {
1437 1438
            virReportError(VIR_ERR_MIGRATE_PERSIST_FAILED,
                           "%s", _("failed to get XML representation of migrated domain"));
1439 1440 1441
            goto failure;
        }

1442
        dom_new = xenDaemonDomainDefineXML(dconn, domain_xml);
1443
        if (! dom_new) {
1444 1445
            virReportError(VIR_ERR_MIGRATE_PERSIST_FAILED,
                           "%s", _("failed to define domain on destination host"));
1446 1447 1448 1449
            goto failure;
        }

        /* Free additional reference added by Define */
1450
        virDomainFree(dom_new);
1451 1452
    }

1453
    VIR_FREE(domain_xml);
1454 1455 1456 1457 1458

    return dom;


failure:
1459
    virDomainFree(dom);
1460

1461
    VIR_FREE(domain_xml);
1462 1463

    return NULL;
1464 1465
}

1466
static int
1467 1468
xenUnifiedConnectListDefinedDomains(virConnectPtr conn, char **const names,
                                    int maxnames)
1469
{
1470
    xenUnifiedPrivatePtr priv = conn->privateData;
1471 1472
    int i;
    int ret;
1473

1474
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
E
Eric Blake 已提交
1475
        if (priv->opened[i] && drivers[i]->xenListDefinedDomains) {
1476
            ret = drivers[i]->xenListDefinedDomains(conn, names, maxnames);
1477 1478
            if (ret >= 0) return ret;
        }
1479

1480
    return -1;
1481 1482 1483
}

static int
1484
xenUnifiedConnectNumOfDefinedDomains(virConnectPtr conn)
1485
{
1486
    xenUnifiedPrivatePtr priv = conn->privateData;
1487 1488
    int i;
    int ret;
1489

1490
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
E
Eric Blake 已提交
1491
        if (priv->opened[i] && drivers[i]->xenNumOfDefinedDomains) {
1492
            ret = drivers[i]->xenNumOfDefinedDomains(conn);
1493 1494
            if (ret >= 0) return ret;
        }
1495

1496
    return -1;
1497 1498 1499
}

static int
1500
xenUnifiedDomainCreateWithFlags(virDomainPtr dom, unsigned int flags)
1501
{
1502
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1503
    int i;
1504 1505
    int ret = -1;
    char *name = NULL;
1506

1507 1508
    virCheckFlags(0, -1);

1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522
    name = xenUnifiedDomainManagedSavePath(priv, dom);
    if (!name)
        goto cleanup;

    if (virFileExists(name)) {
        if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
            ret = xenDaemonDomainRestore(dom->conn, name);
            if (ret == 0)
                unlink(name);
        }
        goto cleanup;
    }

    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i) {
E
Eric Blake 已提交
1523
        if (priv->opened[i] && drivers[i]->xenDomainCreate &&
1524 1525 1526 1527 1528
            drivers[i]->xenDomainCreate(dom) == 0) {
            ret = 0;
            goto cleanup;
        }
    }
1529

1530 1531 1532
cleanup:
    VIR_FREE(name);
    return ret;
1533 1534
}

1535
static int
1536
xenUnifiedDomainCreate(virDomainPtr dom)
1537 1538 1539 1540
{
    return xenUnifiedDomainCreateWithFlags(dom, 0);
}

1541
static virDomainPtr
1542
xenUnifiedDomainDefineXML(virConnectPtr conn, const char *xml)
1543
{
1544
    xenUnifiedPrivatePtr priv = conn->privateData;
1545 1546
    int i;
    virDomainPtr ret;
1547

1548
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
E
Eric Blake 已提交
1549
        if (priv->opened[i] && drivers[i]->xenDomainDefineXML) {
1550
            ret = drivers[i]->xenDomainDefineXML(conn, xml);
1551 1552
            if (ret) return ret;
        }
1553

1554
    return NULL;
1555 1556 1557
}

static int
1558
xenUnifiedDomainUndefineFlags(virDomainPtr dom, unsigned int flags)
1559
{
1560
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1561
    int i;
1562

1563
    virCheckFlags(0, -1);
1564
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
E
Eric Blake 已提交
1565
        if (priv->opened[i] && drivers[i]->xenDomainUndefine &&
1566
            drivers[i]->xenDomainUndefine(dom) == 0)
1567
            return 0;
1568

1569
    return -1;
1570 1571
}

1572
static int
1573
xenUnifiedDomainUndefine(virDomainPtr dom) {
1574 1575 1576
    return xenUnifiedDomainUndefineFlags(dom, 0);
}

1577
static int
1578
xenUnifiedDomainAttachDevice(virDomainPtr dom, const char *xml)
1579
{
1580
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1581
    int i;
1582
    unsigned int flags = VIR_DOMAIN_DEVICE_MODIFY_LIVE;
1583

1584 1585 1586 1587 1588 1589
    /*
     * 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
     */
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET] &&
1590
        priv->xendConfigVersion >= XEND_CONFIG_VERSION_3_0_4)
1591
        flags |= VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
1592 1593

    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
E
Eric Blake 已提交
1594 1595
        if (priv->opened[i] && drivers[i]->xenDomainAttachDeviceFlags &&
            drivers[i]->xenDomainAttachDeviceFlags(dom, xml, flags) == 0)
1596 1597 1598 1599 1600 1601
            return 0;

    return -1;
}

static int
1602 1603
xenUnifiedDomainAttachDeviceFlags(virDomainPtr dom, const char *xml,
                                  unsigned int flags)
1604
{
1605
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1606
    int i;
1607

1608
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
E
Eric Blake 已提交
1609 1610
        if (priv->opened[i] && drivers[i]->xenDomainAttachDeviceFlags &&
            drivers[i]->xenDomainAttachDeviceFlags(dom, xml, flags) == 0)
1611
            return 0;
1612

1613
    return -1;
1614 1615 1616
}

static int
1617
xenUnifiedDomainDetachDevice(virDomainPtr dom, const char *xml)
1618
{
1619
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1620
    int i;
1621
    unsigned int flags = VIR_DOMAIN_DEVICE_MODIFY_LIVE;
1622

1623 1624 1625 1626 1627 1628
    /*
     * 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
     */
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET] &&
1629
        priv->xendConfigVersion >= XEND_CONFIG_VERSION_3_0_4)
1630
        flags |= VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
1631 1632

    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
E
Eric Blake 已提交
1633 1634
        if (priv->opened[i] && drivers[i]->xenDomainDetachDeviceFlags &&
            drivers[i]->xenDomainDetachDeviceFlags(dom, xml, flags) == 0)
1635 1636 1637 1638 1639 1640
            return 0;

    return -1;
}

static int
1641 1642
xenUnifiedDomainDetachDeviceFlags(virDomainPtr dom, const char *xml,
                                  unsigned int flags)
1643
{
1644
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1645
    int i;
1646

1647
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i)
E
Eric Blake 已提交
1648 1649
        if (priv->opened[i] && drivers[i]->xenDomainDetachDeviceFlags &&
            drivers[i]->xenDomainDetachDeviceFlags(dom, xml, flags) == 0)
1650
            return 0;
1651

1652
    return -1;
1653 1654
}

1655
static int
1656 1657
xenUnifiedDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml,
                                  unsigned int flags)
1658
{
1659
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1660

1661 1662
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
        return xenDaemonUpdateDeviceFlags(dom, xml, flags);
1663 1664 1665
    return -1;
}

1666
static int
1667
xenUnifiedDomainGetAutostart(virDomainPtr dom, int *autostart)
1668
{
1669
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1670

1671
    if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
1672 1673 1674 1675 1676 1677
        if (priv->opened[XEN_UNIFIED_XM_OFFSET])
            return xenXMDomainGetAutostart(dom, autostart);
    } else {
        if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
            return xenDaemonDomainGetAutostart(dom, autostart);
    }
1678

1679
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1680 1681 1682 1683
    return -1;
}

static int
1684
xenUnifiedDomainSetAutostart(virDomainPtr dom, int autostart)
1685
{
1686
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1687

1688
    if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
1689 1690 1691 1692 1693 1694
        if (priv->opened[XEN_UNIFIED_XM_OFFSET])
            return xenXMDomainSetAutostart(dom, autostart);
    } else {
        if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
            return xenDaemonDomainSetAutostart(dom, autostart);
    }
1695

1696
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1697 1698 1699
    return -1;
}

1700
static char *
1701
xenUnifiedDomainGetSchedulerType(virDomainPtr dom, int *nparams)
1702
{
1703
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1704 1705 1706 1707
    int i;
    char *schedulertype;

    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; i++) {
E
Eric Blake 已提交
1708
        if (priv->opened[i] && drivers[i]->xenDomainGetSchedulerType) {
1709
            schedulertype = drivers[i]->xenDomainGetSchedulerType(dom, nparams);
1710
            if (schedulertype != NULL)
1711
                return schedulertype;
1712 1713
        }
    }
1714
    return NULL;
1715 1716 1717
}

static int
1718 1719 1720 1721
xenUnifiedDomainGetSchedulerParametersFlags(virDomainPtr dom,
                                            virTypedParameterPtr params,
                                            int *nparams,
                                            unsigned int flags)
1722
{
1723
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1724 1725
    int i, ret;

1726 1727
    virCheckFlags(0, -1);

1728
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i) {
E
Eric Blake 已提交
1729 1730
        if (priv->opened[i] && drivers[i]->xenDomainGetSchedulerParameters) {
           ret = drivers[i]->xenDomainGetSchedulerParameters(dom, params, nparams);
1731
           if (ret == 0)
1732
               return 0;
1733
        }
1734
    }
1735
    return -1;
1736 1737 1738
}

static int
1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751
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)
1752
{
1753
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1754 1755
    int i, ret;

1756 1757
    virCheckFlags(0, -1);

1758 1759
    /* do the hypervisor call last to get better error */
    for (i = XEN_UNIFIED_NR_DRIVERS - 1; i >= 0; i--) {
E
Eric Blake 已提交
1760 1761
        if (priv->opened[i] && drivers[i]->xenDomainSetSchedulerParameters) {
           ret = drivers[i]->xenDomainSetSchedulerParameters(dom, params, nparams);
1762 1763 1764
           if (ret == 0)
               return 0;
        }
1765 1766
    }

1767
    return -1;
1768 1769
}

1770 1771 1772 1773 1774 1775 1776 1777 1778
static int
xenUnifiedDomainSetSchedulerParameters(virDomainPtr dom,
                                       virTypedParameterPtr params,
                                       int nparams)
{
    return xenUnifiedDomainSetSchedulerParametersFlags(dom, params,
                                                       nparams, 0);
}

1779
static int
1780 1781
xenUnifiedDomainBlockStats(virDomainPtr dom, const char *path,
                           struct _virDomainBlockStats *stats)
1782
{
1783
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1784 1785

    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET])
1786
        return xenHypervisorDomainBlockStats(dom, path, stats);
1787

1788
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1789 1790 1791 1792
    return -1;
}

static int
1793 1794
xenUnifiedDomainInterfaceStats(virDomainPtr dom, const char *path,
                               struct _virDomainInterfaceStats *stats)
1795
{
1796
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1797 1798

    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET])
1799
        return xenHypervisorDomainInterfaceStats(dom, path, stats);
1800

1801
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1802 1803 1804
    return -1;
}

R
Richard W.M. Jones 已提交
1805
static int
1806 1807 1808
xenUnifiedDomainBlockPeek(virDomainPtr dom, const char *path,
                          unsigned long long offset, size_t size,
                          void *buffer, unsigned int flags)
R
Richard W.M. Jones 已提交
1809 1810
{
    int r;
1811
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
R
Richard W.M. Jones 已提交
1812

E
Eric Blake 已提交
1813 1814
    virCheckFlags(0, -1);

R
Richard W.M. Jones 已提交
1815
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
1816
        r = xenDaemonDomainBlockPeek(dom, path, offset, size, buffer);
R
Richard W.M. Jones 已提交
1817 1818 1819 1820 1821
        if (r != -2) return r;
        /* r == -2 means declined, so fall through to XM driver ... */
    }

    if (priv->opened[XEN_UNIFIED_XM_OFFSET]) {
1822
        if (xenXMDomainBlockPeek(dom, path, offset, size, buffer) == 0)
R
Richard W.M. Jones 已提交
1823 1824 1825
            return 0;
    }

1826
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
R
Richard W.M. Jones 已提交
1827 1828 1829
    return -1;
}

1830
static int
1831 1832
xenUnifiedNodeGetCellsFreeMemory(virConnectPtr conn, unsigned long long *freeMems,
                                 int startCell, int maxCells)
1833
{
1834
    xenUnifiedPrivatePtr priv = conn->privateData;
1835 1836

    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET])
1837 1838
        return xenHypervisorNodeGetCellsFreeMemory(conn, freeMems,
                                                   startCell, maxCells);
1839

1840
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1841 1842 1843
    return -1;
}

1844
static unsigned long long
1845
xenUnifiedNodeGetFreeMemory(virConnectPtr conn)
1846 1847 1848
{
    unsigned long long freeMem = 0;
    int ret;
1849
    xenUnifiedPrivatePtr priv = conn->privateData;
1850 1851

    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET]) {
1852 1853
        ret = xenHypervisorNodeGetCellsFreeMemory(conn, &freeMem,
                                                  -1, 1);
1854
        if (ret != 1)
1855 1856
            return 0;
        return freeMem;
1857 1858
    }

1859
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1860
    return 0;
1861 1862
}

1863

1864
static int
1865 1866 1867 1868
xenUnifiedConnectDomainEventRegister(virConnectPtr conn,
                                     virConnectDomainEventCallback callback,
                                     void *opaque,
                                     virFreeCallback freefunc)
1869
{
1870
    xenUnifiedPrivatePtr priv = conn->privateData;
D
Daniel P. Berrange 已提交
1871

1872
    int ret;
D
Daniel P. Berrange 已提交
1873
    xenUnifiedLock(priv);
1874

1875
    if (priv->xsWatch == -1) {
1876
        virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
D
Daniel P. Berrange 已提交
1877
        xenUnifiedUnlock(priv);
1878 1879 1880
        return -1;
    }

1881 1882
    ret = virDomainEventStateRegister(conn, priv->domainEvents,
                                      callback, opaque, freefunc);
1883

D
Daniel P. Berrange 已提交
1884
    xenUnifiedUnlock(priv);
1885
    return ret;
1886 1887
}

1888

1889
static int
1890 1891
xenUnifiedConnectDomainEventDeregister(virConnectPtr conn,
                                       virConnectDomainEventCallback callback)
1892 1893
{
    int ret;
1894
    xenUnifiedPrivatePtr priv = conn->privateData;
D
Daniel P. Berrange 已提交
1895 1896
    xenUnifiedLock(priv);

1897
    if (priv->xsWatch == -1) {
1898
        virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
D
Daniel P. Berrange 已提交
1899
        xenUnifiedUnlock(priv);
1900 1901 1902
        return -1;
    }

1903 1904 1905
    ret = virDomainEventStateDeregister(conn,
                                        priv->domainEvents,
                                        callback);
1906

D
Daniel P. Berrange 已提交
1907
    xenUnifiedUnlock(priv);
1908 1909 1910
    return ret;
}

1911

1912
static int
1913 1914 1915 1916 1917 1918
xenUnifiedConnectDomainEventRegisterAny(virConnectPtr conn,
                                        virDomainPtr dom,
                                        int eventID,
                                        virConnectDomainEventGenericCallback callback,
                                        void *opaque,
                                        virFreeCallback freefunc)
1919
{
1920
    xenUnifiedPrivatePtr priv = conn->privateData;
1921 1922 1923 1924 1925

    int ret;
    xenUnifiedLock(priv);

    if (priv->xsWatch == -1) {
1926
        virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1927 1928 1929 1930
        xenUnifiedUnlock(priv);
        return -1;
    }

1931 1932 1933
    if (virDomainEventStateRegisterID(conn, priv->domainEvents,
                                      dom, eventID,
                                      callback, opaque, freefunc, &ret) < 0)
1934
        ret = -1;
1935 1936

    xenUnifiedUnlock(priv);
1937
    return ret;
1938 1939 1940
}

static int
1941 1942
xenUnifiedConnectDomainEventDeregisterAny(virConnectPtr conn,
                                          int callbackID)
1943 1944
{
    int ret;
1945
    xenUnifiedPrivatePtr priv = conn->privateData;
1946 1947 1948
    xenUnifiedLock(priv);

    if (priv->xsWatch == -1) {
1949
        virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1950 1951 1952 1953
        xenUnifiedUnlock(priv);
        return -1;
    }

1954 1955 1956
    ret = virDomainEventStateDeregisterID(conn,
                                          priv->domainEvents,
                                          callbackID);
1957 1958 1959 1960 1961 1962

    xenUnifiedUnlock(priv);
    return ret;
}


1963
static int
1964 1965 1966 1967 1968
xenUnifiedNodeDeviceGetPciInfo(virNodeDevicePtr dev,
                               unsigned *domain,
                               unsigned *bus,
                               unsigned *slot,
                               unsigned *function)
1969 1970 1971 1972 1973 1974 1975 1976 1977 1978
{
    virNodeDeviceDefPtr def = NULL;
    virNodeDevCapsDefPtr cap;
    char *xml = NULL;
    int ret = -1;

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

1979
    def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL);
1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996
    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) {
1997 1998
        virReportError(VIR_ERR_INVALID_ARG,
                       _("device %s is not a PCI device"), dev->name);
1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009
        goto out;
    }

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

static int
2010 2011 2012
xenUnifiedNodeDeviceDetachFlags(virNodeDevicePtr dev,
                                const char *driverName,
                                unsigned int flags)
2013
{
2014
    virPCIDevicePtr pci;
2015 2016 2017
    unsigned domain, bus, slot, function;
    int ret = -1;

2018 2019
    virCheckFlags(0, -1);

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

2023
    pci = virPCIDeviceNew(domain, bus, slot, function);
2024 2025 2026
    if (!pci)
        return -1;

2027 2028 2029 2030 2031 2032 2033 2034 2035
    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)
2036 2037 2038 2039
        goto out;

    ret = 0;
out:
2040
    virPCIDeviceFree(pci);
2041 2042 2043
    return ret;
}

2044 2045 2046 2047 2048 2049
static int
xenUnifiedNodeDeviceDettach(virNodeDevicePtr dev)
{
    return xenUnifiedNodeDeviceDetachFlags(dev, NULL, 0);
}

2050
static int
2051
xenUnifiedNodeDeviceAssignedDomainId(virNodeDevicePtr dev)
2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062
{
    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 */
2063
    numdomains = xenUnifiedConnectNumOfDomains(conn);
2064 2065 2066 2067 2068 2069 2070 2071
    if (numdomains < 0) {
        return ret;
    }
    if (numdomains > 0){
        if (VIR_ALLOC_N(ids, numdomains) < 0) {
            virReportOOMError();
            goto out;
        }
2072
        if ((numdomains = xenUnifiedConnectListDomains(conn, &ids[0], numdomains)) < 0) {
2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088
            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 */
2089
    for (i = 0; i < numdomains; i++) {
2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107
        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;
}

2108
static int
2109
xenUnifiedNodeDeviceReAttach(virNodeDevicePtr dev)
2110
{
2111
    virPCIDevicePtr pci;
2112 2113
    unsigned domain, bus, slot, function;
    int ret = -1;
2114
    int domid;
2115 2116 2117 2118

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

2119
    pci = virPCIDeviceNew(domain, bus, slot, function);
2120 2121 2122
    if (!pci)
        return -1;

2123 2124
    /* Check if device is assigned to an active guest */
    if ((domid = xenUnifiedNodeDeviceAssignedDomainId(dev)) >= 0) {
2125 2126 2127
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Device %s has been assigned to guest %d"),
                       dev->name, domid);
2128 2129 2130
        goto out;
    }

2131
    if (virPCIDeviceReattach(pci, NULL, NULL) < 0)
2132 2133 2134 2135
        goto out;

    ret = 0;
out:
2136
    virPCIDeviceFree(pci);
2137 2138 2139 2140
    return ret;
}

static int
2141
xenUnifiedNodeDeviceReset(virNodeDevicePtr dev)
2142
{
2143
    virPCIDevicePtr pci;
2144 2145 2146 2147 2148 2149
    unsigned domain, bus, slot, function;
    int ret = -1;

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

2150
    pci = virPCIDeviceNew(domain, bus, slot, function);
2151 2152 2153
    if (!pci)
        return -1;

2154
    if (virPCIDeviceReset(pci, NULL, NULL) < 0)
2155 2156 2157 2158
        goto out;

    ret = 0;
out:
2159
    virPCIDeviceFree(pci);
2160 2161 2162 2163
    return ret;
}


2164 2165
static int
xenUnifiedDomainOpenConsole(virDomainPtr dom,
2166
                            const char *dev_name,
2167 2168 2169 2170 2171 2172 2173 2174 2175 2176
                            virStreamPtr st,
                            unsigned int flags)
{
    virDomainDefPtr def = NULL;
    int ret = -1;
    virDomainChrDefPtr chr = NULL;

    virCheckFlags(0, -1);

    if (dom->id == -1) {
2177 2178
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
2179 2180 2181
        goto cleanup;
    }

2182
    if (dev_name) {
2183
        /* XXX support device aliases in future */
2184 2185
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("Named device aliases are not supported"));
2186 2187 2188 2189 2190 2191 2192
        goto cleanup;
    }

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

2193 2194
    if (def->nconsoles)
        chr = def->consoles[0];
2195 2196 2197 2198
    else if (def->nserials)
        chr = def->serials[0];

    if (!chr) {
2199 2200
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("cannot find default console device"));
2201 2202 2203
        goto cleanup;
    }

2204
    if (chr->source.type != VIR_DOMAIN_CHR_TYPE_PTY) {
2205 2206
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("character device %s is not using a PTY"), dev_name);
2207 2208 2209
        goto cleanup;
    }

2210
    if (virFDStreamOpenFile(st, chr->source.data.file.path,
E
Eric Blake 已提交
2211
                            0, 0, O_RDWR) < 0)
2212 2213 2214 2215 2216 2217 2218
        goto cleanup;

    ret = 0;
cleanup:
    virDomainDefFree(def);
    return ret;
}
2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238

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

2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249

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 已提交
2250
/*----- Register with libvirt.c, and initialize Xen drivers. -----*/
2251 2252 2253

/* The interface which we export upwards to libvirt.c. */
static virDriver xenUnifiedDriver = {
2254 2255
    .no = VIR_DRV_XEN_UNIFIED,
    .name = "Xen",
2256 2257 2258 2259 2260
    .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 */
2261
    .connectGetHostname = xenUnifiedConnectGetHostname, /* 0.7.3 */
2262
    .connectGetMaxVcpus = xenUnifiedConnectGetMaxVcpus, /* 0.2.1 */
2263
    .nodeGetInfo = xenUnifiedNodeGetInfo, /* 0.1.0 */
2264 2265 2266
    .connectGetCapabilities = xenUnifiedConnectGetCapabilities, /* 0.2.1 */
    .connectListDomains = xenUnifiedConnectListDomains, /* 0.0.3 */
    .connectNumOfDomains = xenUnifiedConnectNumOfDomains, /* 0.0.3 */
2267 2268 2269 2270 2271 2272 2273
    .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 */
2274
    .domainShutdownFlags = xenUnifiedDomainShutdownFlags, /* 0.9.10 */
2275 2276
    .domainReboot = xenUnifiedDomainReboot, /* 0.1.0 */
    .domainDestroy = xenUnifiedDomainDestroy, /* 0.0.3 */
2277
    .domainDestroyFlags = xenUnifiedDomainDestroyFlags, /* 0.9.4 */
2278 2279 2280 2281 2282 2283 2284
    .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 */
2285
    .domainSaveFlags = xenUnifiedDomainSaveFlags, /* 0.9.4 */
2286 2287 2288
    .domainManagedSave = xenUnifiedDomainManagedSave, /* 1.0.1 */
    .domainHasManagedSaveImage = xenUnifiedDomainHasManagedSaveImage, /* 1.0.1 */
    .domainManagedSaveRemove = xenUnifiedDomainManagedSaveRemove, /* 1.0.1 */
2289
    .domainRestore = xenUnifiedDomainRestore, /* 0.0.3 */
2290
    .domainRestoreFlags = xenUnifiedDomainRestoreFlags, /* 0.9.4 */
2291 2292 2293 2294 2295 2296 2297 2298
    .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 */
2299 2300 2301 2302
    .connectDomainXMLFromNative = xenUnifiedConnectDomainXMLFromNative, /* 0.6.4 */
    .connectDomainXMLToNative = xenUnifiedConnectDomainXMLToNative, /* 0.6.4 */
    .connectListDefinedDomains = xenUnifiedConnectListDefinedDomains, /* 0.1.1 */
    .connectNumOfDefinedDomains = xenUnifiedConnectNumOfDefinedDomains, /* 0.1.5 */
2303 2304 2305 2306
    .domainCreate = xenUnifiedDomainCreate, /* 0.1.1 */
    .domainCreateWithFlags = xenUnifiedDomainCreateWithFlags, /* 0.8.2 */
    .domainDefineXML = xenUnifiedDomainDefineXML, /* 0.1.1 */
    .domainUndefine = xenUnifiedDomainUndefine, /* 0.1.1 */
2307
    .domainUndefineFlags = xenUnifiedDomainUndefineFlags, /* 0.9.4 */
2308 2309 2310 2311 2312 2313 2314 2315 2316
    .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 */
2317
    .domainGetSchedulerParametersFlags = xenUnifiedDomainGetSchedulerParametersFlags, /* 0.9.2 */
2318
    .domainSetSchedulerParameters = xenUnifiedDomainSetSchedulerParameters, /* 0.2.3 */
2319
    .domainSetSchedulerParametersFlags = xenUnifiedDomainSetSchedulerParametersFlags, /* 0.9.2 */
2320 2321 2322 2323 2324 2325 2326 2327
    .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 */
2328 2329
    .connectDomainEventRegister = xenUnifiedConnectDomainEventRegister, /* 0.5.0 */
    .connectDomainEventDeregister = xenUnifiedConnectDomainEventDeregister, /* 0.5.0 */
2330
    .nodeDeviceDettach = xenUnifiedNodeDeviceDettach, /* 0.6.1 */
2331
    .nodeDeviceDetachFlags = xenUnifiedNodeDeviceDetachFlags, /* 1.0.5 */
2332 2333
    .nodeDeviceReAttach = xenUnifiedNodeDeviceReAttach, /* 0.6.1 */
    .nodeDeviceReset = xenUnifiedNodeDeviceReset, /* 0.6.1 */
2334 2335
    .connectIsEncrypted = xenUnifiedConnectIsEncrypted, /* 0.7.3 */
    .connectIsSecure = xenUnifiedConnectIsSecure, /* 0.7.3 */
2336 2337 2338
    .domainIsActive = xenUnifiedDomainIsActive, /* 0.7.3 */
    .domainIsPersistent = xenUnifiedDomainIsPersistent, /* 0.7.3 */
    .domainIsUpdated = xenUnifiedDomainIsUpdated, /* 0.8.6 */
2339 2340
    .connectDomainEventRegisterAny = xenUnifiedConnectDomainEventRegisterAny, /* 0.8.0 */
    .connectDomainEventDeregisterAny = xenUnifiedConnectDomainEventDeregisterAny, /* 0.8.0 */
2341
    .domainOpenConsole = xenUnifiedDomainOpenConsole, /* 0.8.6 */
2342
    .connectIsAlive = xenUnifiedConnectIsAlive, /* 0.9.8 */
2343
    .nodeSuspendForDuration = xenUnifiedNodeSuspendForDuration, /* 0.9.8 */
2344 2345
    .nodeGetMemoryParameters = xenUnifiedNodeGetMemoryParameters, /* 0.10.2 */
    .nodeSetMemoryParameters = xenUnifiedNodeSetMemoryParameters, /* 0.10.2 */
2346 2347
};

2348
/**
2349
 * xenRegister:
2350 2351 2352 2353 2354
 *
 * Register xen related drivers
 *
 * Returns the driver priority or -1 in case of error.
 */
2355
int
2356
xenRegister(void)
2357
{
2358
    if (virRegisterStateDriver(&state_driver) == -1) return -1;
J
John Levon 已提交
2359

2360
    return virRegisterDriver(&xenUnifiedDriver);
2361 2362
}

2363 2364 2365 2366 2367 2368 2369 2370 2371
/**
 * xenUnifiedDomainInfoListFree:
 *
 * Free the Domain Info List
 */
void
xenUnifiedDomainInfoListFree(xenUnifiedDomainInfoListPtr list)
{
    int i;
J
John Levon 已提交
2372 2373 2374 2375

    if (list == NULL)
        return;

2376 2377 2378 2379
    for (i=0; i<list->count; i++) {
        VIR_FREE(list->doms[i]->name);
        VIR_FREE(list->doms[i]);
    }
2380
    VIR_FREE(list->doms);
2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402
    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)) {
2403
            VIR_DEBUG("WARNING: dom already tracked");
2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425
            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:
2426
    virReportOOMError();
2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446
    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++) {
2447
        if (list->doms[i]->id == id &&
2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471
            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;
}

2472

2473 2474
/**
 * xenUnifiedDomainEventDispatch:
D
Daniel P. Berrange 已提交
2475 2476
 * @priv: the connection to dispatch events on
 * @event: the event to dispatch
2477 2478 2479
 *
 * Dispatch domain events to registered callbacks
 *
D
Daniel P. Berrange 已提交
2480 2481
 * The caller must hold the lock in 'priv' before invoking
 *
2482
 */
2483
void xenUnifiedDomainEventDispatch(xenUnifiedPrivatePtr priv,
2484
                                    virDomainEventPtr event)
2485
{
D
Daniel P. Berrange 已提交
2486
    if (!priv)
2487
        return;
2488

2489
    virDomainEventStateQueue(priv->domainEvents, event);
D
Daniel P. Berrange 已提交
2490 2491 2492 2493 2494 2495 2496 2497 2498 2499
}

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

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