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

89
static bool is_privileged = false;
J
John Levon 已提交
90

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

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

D
Daniel P. Berrange 已提交
109
    priv = conn->privateData;
110

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

D
Daniel P. Berrange 已提交
115

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

    if (!VIR_IS_CONNECTED_DOMAIN(dom))
142
        return NULL;
143

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

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

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

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

                }
            }
        }
186
        res = virBitmapFormat(cpulist);
187 188 189
    }

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

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

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

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

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

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

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

258

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


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

280

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


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

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

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

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

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

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

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

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

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

365 366 367 368 369
    priv->handle = -1;
    priv->xendConfigVersion = -1;
    priv->xshandle = NULL;


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

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

D
Daniel P. Berrange 已提交
399 400
    xenNumaInit(conn);

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

406
    if (!(priv->xmlopt = xenDomainXMLConfInit()))
407
        goto error;
408

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

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

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

428
    return VIR_DRV_OPEN_SUCCESS;
429

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

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

456
    virObjectUnref(priv->caps);
457
    virObjectUnref(priv->xmlopt);
458
    virDomainEventStateFree(priv->domainEvents);
459

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

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

477
    return 0;
478 479
}

480 481 482 483 484 485 486 487 488 489 490

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


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

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

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

516 517 518 519 520 521 522

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


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

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

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

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

558
    return xenHypervisorGetMaxVcpus(conn, type);
559 560 561
}

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

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

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

D
Daniel P. Berrange 已提交
578
    return xml;
579 580 581
}

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

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

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

599
    return xenDaemonCreateXML(conn, xmlDesc);
600 601 602
}

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

607
    ret = xenHypervisorLookupDomainByID(conn, id);
608

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

612
    return ret;
613 614 615
}

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

622
    ret = xenHypervisorLookupDomainByUUID(conn, uuid);
623

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

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

    return ret;
636 637 638
}

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

645
    ret = xenDaemonLookupByName(conn, name);
646 647

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

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

    return ret;
655 656
}

657 658 659 660

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

    /* ID field in dom may be outdated, so re-lookup */
666 667 668 669 670 671 672 673 674
    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);
    }
675 676 677 678

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

    return ret;
}

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

done:
    if (currdom)
        virDomainFree(currdom);

    return ret;
}

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

740
static int
741
xenUnifiedDomainSuspend(virDomainPtr dom)
742
{
743
    return xenDaemonDomainSuspend(dom);
744 745 746
}

static int
747
xenUnifiedDomainResume(virDomainPtr dom)
748
{
749
    return xenDaemonDomainResume(dom);
750 751 752
}

static int
753 754
xenUnifiedDomainShutdownFlags(virDomainPtr dom,
                              unsigned int flags)
755
{
756 757
    virCheckFlags(0, -1);

758
    return xenDaemonDomainShutdown(dom);
759 760
}

761 762 763 764 765 766
static int
xenUnifiedDomainShutdown(virDomainPtr dom)
{
    return xenUnifiedDomainShutdownFlags(dom, 0);
}

767
static int
768
xenUnifiedDomainReboot(virDomainPtr dom, unsigned int flags)
769
{
770
    virCheckFlags(0, -1);
771

772
    return xenDaemonDomainReboot(dom);
773 774
}

775 776 777 778 779 780
static int
xenUnifiedDomainDestroyFlags(virDomainPtr dom,
                             unsigned int flags)
{
    virCheckFlags(0, -1);

781
    return xenDaemonDomainDestroy(dom);
782 783
}

784 785 786 787 788 789
static int
xenUnifiedDomainDestroy(virDomainPtr dom)
{
    return xenUnifiedDomainDestroyFlags(dom, 0);
}

790
static char *
791
xenUnifiedDomainGetOSType(virDomainPtr dom)
792
{
793
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
794

795 796 797 798 799 800 801
    if (dom->id < 0) {
        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 {
            return xenDaemonDomainGetOSType(dom);
802
        }
803 804 805
    } else {
        return xenHypervisorDomainGetOSType(dom);
    }
806 807
}

808

809
static unsigned long long
810
xenUnifiedDomainGetMaxMemory(virDomainPtr dom)
811
{
812
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
813

814 815 816 817 818 819 820 821
    if (dom->id < 0) {
        if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
            return xenXMDomainGetMaxMemory(dom);
        else
            return xenDaemonDomainGetMaxMemory(dom);
    } else {
        return xenHypervisorGetMaxMemory(dom);
    }
822 823 824
}

static int
825
xenUnifiedDomainSetMaxMemory(virDomainPtr dom, unsigned long memory)
826
{
827
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
828

829 830 831 832 833 834 835
    if (dom->id < 0) {
        if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
            return xenXMDomainSetMaxMemory(dom, memory);
        else
            return xenDaemonDomainSetMaxMemory(dom, memory);
    } else {
        return xenHypervisorSetMaxMemory(dom, memory);
836
    }
837 838 839
}

static int
840
xenUnifiedDomainSetMemory(virDomainPtr dom, unsigned long memory)
841
{
842
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
843

844 845 846 847
    if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
        return xenXMDomainSetMemory(dom, memory);
    else
        return xenDaemonDomainSetMemory(dom, memory);
848 849 850
}

static int
851
xenUnifiedDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info)
852
{
853
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
854

855 856 857 858 859 860 861 862
    if (dom->id < 0) {
        if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
            return xenXMDomainGetInfo(dom, info);
        else
            return xenDaemonDomainGetInfo(dom, info);
    } else {
        return xenHypervisorGetDomainInfo(dom, info);
    }
863 864
}

865 866 867 868 869 870
static int
xenUnifiedDomainGetState(virDomainPtr dom,
                         int *state,
                         int *reason,
                         unsigned int flags)
{
871
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
872 873 874

    virCheckFlags(0, -1);

875 876 877 878 879 880 881
    if (dom->id < 0) {
        if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
            return xenXMDomainGetState(dom, state, reason);
        else
            return xenDaemonDomainGetState(dom, state, reason);
    } else {
        return xenHypervisorGetDomainState(dom, state, reason);
882 883 884
    }
}

885
static int
886 887
xenUnifiedDomainSaveFlags(virDomainPtr dom, const char *to, const char *dxml,
                          unsigned int flags)
888
{
889 890
    virCheckFlags(0, -1);
    if (dxml) {
891 892
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
893 894 895
        return -1;
    }

896
    return xenDaemonDomainSave(dom, to);
897 898 899
}

static int
900 901 902 903 904
xenUnifiedDomainSave(virDomainPtr dom, const char *to)
{
    return xenUnifiedDomainSaveFlags(dom, to, NULL, 0);
}

905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921
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)
{
922
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
923 924 925 926 927 928 929 930 931
    char *name;
    int ret = -1;

    virCheckFlags(0, -1);

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

932
    ret = xenDaemonDomainSave(dom, name);
933 934 935 936 937 938 939 940 941

cleanup:
    VIR_FREE(name);
    return ret;
}

static int
xenUnifiedDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags)
{
942
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959
    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)
{
960
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
961 962 963 964 965 966 967 968 969 970 971 972 973 974
    char *name;
    int ret = -1;

    virCheckFlags(0, -1);

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

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

975 976 977
static int
xenUnifiedDomainRestoreFlags(virConnectPtr conn, const char *from,
                             const char *dxml, unsigned int flags)
978
{
979 980
    virCheckFlags(0, -1);
    if (dxml) {
981 982
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
983 984 985
        return -1;
    }

986
    return xenDaemonDomainRestore(conn, from);
987 988
}

989
static int
990
xenUnifiedDomainRestore(virConnectPtr conn, const char *from)
991 992 993 994
{
    return xenUnifiedDomainRestoreFlags(conn, from, NULL, 0);
}

995
static int
996
xenUnifiedDomainCoreDump(virDomainPtr dom, const char *to, unsigned int flags)
997
{
998
    return xenDaemonDomainCoreDump(dom, to, flags);
999 1000 1001
}

static int
1002 1003
xenUnifiedDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
                              unsigned int flags)
1004
{
1005
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1006

1007 1008 1009 1010 1011 1012 1013 1014 1015
    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)) {
1016 1017
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid flag combination: (0x%x)"), flags);
1018 1019 1020
        return -1;
    }
    if (!nvcpus || (unsigned short) nvcpus != nvcpus) {
1021 1022
        virReportError(VIR_ERR_INVALID_ARG,
                       _("argument out of range: %d"), nvcpus);
1023 1024 1025
        return -1;
    }

1026 1027 1028
    /* Try non-hypervisor methods first, then hypervisor direct method
     * as a last resort.
     */
1029 1030 1031 1032
    if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
        return xenXMDomainSetVcpusFlags(dom, nvcpus, flags);
    else
        return xenDaemonDomainSetVcpusFlags(dom, nvcpus, flags);
1033 1034
}

1035
static int
1036
xenUnifiedDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus)
1037
{
1038
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1039 1040 1041 1042 1043
    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.  */
1044 1045 1046 1047
    if (priv->xendConfigVersion >= XEND_CONFIG_VERSION_3_0_4)
        flags |= VIR_DOMAIN_VCPU_CONFIG;

    return xenUnifiedDomainSetVcpusFlags(dom, nvcpus, flags);
1048 1049
}

1050
static int
1051 1052
xenUnifiedDomainPinVcpu(virDomainPtr dom, unsigned int vcpu,
                        unsigned char *cpumap, int maplen)
1053
{
1054
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1055

1056 1057 1058 1059 1060 1061 1062 1063
    if (dom->id < 0) {
        if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
            return xenXMDomainPinVcpu(dom, vcpu, cpumap, maplen);
        else
            return xenDaemonDomainPinVcpu(dom, vcpu, cpumap, maplen);
    } else {
        return xenHypervisorPinVcpu(dom, vcpu, cpumap, maplen);
    }
1064 1065 1066
}

static int
1067 1068 1069
xenUnifiedDomainGetVcpus(virDomainPtr dom,
                         virVcpuInfoPtr info, int maxinfo,
                         unsigned char *cpumaps, int maplen)
1070
{
1071
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1072 1073 1074 1075 1076 1077 1078
    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"));
            return -1;
        } else {
            return xenDaemonDomainGetVcpus(dom, info, maxinfo, cpumaps, maplen);
1079
        }
1080 1081 1082
    } else {
        return xenHypervisorGetVcpus(dom, info, maxinfo, cpumaps, maplen);
    }
1083 1084 1085
}

static int
1086
xenUnifiedDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags)
1087
{
1088
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1089

1090 1091 1092 1093
    virCheckFlags(VIR_DOMAIN_VCPU_LIVE |
                  VIR_DOMAIN_VCPU_CONFIG |
                  VIR_DOMAIN_VCPU_MAXIMUM, -1);

1094 1095 1096 1097 1098 1099 1100 1101 1102 1103
    if (dom->id < 0) {
        if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
            return xenXMDomainGetVcpusFlags(dom, flags);
        else
            return xenDaemonDomainGetVcpusFlags(dom, flags);
    } else {
        if (flags == (VIR_DOMAIN_VCPU_CONFIG | VIR_DOMAIN_VCPU_MAXIMUM))
            return xenHypervisorGetVcpuMax(dom);
        else
            return xenDaemonDomainGetVcpusFlags(dom, flags);
1104
    }
1105 1106
}

1107
static int
1108
xenUnifiedDomainGetMaxVcpus(virDomainPtr dom)
1109 1110 1111 1112 1113
{
    return xenUnifiedDomainGetVcpusFlags(dom, (VIR_DOMAIN_VCPU_LIVE |
                                               VIR_DOMAIN_VCPU_MAXIMUM));
}

1114
static char *
1115
xenUnifiedDomainGetXMLDesc(virDomainPtr dom, unsigned int flags)
1116
{
1117
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1118

1119 1120
    if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
        return xenXMDomainGetXMLDesc(dom, flags);
1121
    } else {
1122 1123 1124 1125 1126 1127 1128
        char *cpus, *res;
        xenUnifiedLock(priv);
        cpus = xenDomainUsedCpus(dom);
        xenUnifiedUnlock(priv);
        res = xenDaemonDomainGetXMLDesc(dom, flags, cpus);
        VIR_FREE(cpus);
        return res;
1129
    }
1130 1131
}

1132 1133

static char *
1134 1135 1136 1137
xenUnifiedConnectDomainXMLFromNative(virConnectPtr conn,
                                     const char *format,
                                     const char *config,
                                     unsigned int flags)
1138 1139 1140 1141
{
    virDomainDefPtr def = NULL;
    char *ret = NULL;
    virConfPtr conf = NULL;
1142 1143 1144
    int id;
    char * tty;
    int vncport;
1145
    xenUnifiedPrivatePtr priv = conn->privateData;
1146

E
Eric Blake 已提交
1147 1148
    virCheckFlags(0, NULL);

1149 1150
    if (STRNEQ(format, XEN_CONFIG_FORMAT_XM) &&
        STRNEQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
1151 1152
        virReportError(VIR_ERR_INVALID_ARG,
                       _("unsupported config type %s"), format);
1153 1154 1155 1156
        return NULL;
    }

    if (STREQ(format, XEN_CONFIG_FORMAT_XM)) {
1157
        conf = virConfReadMem(config, strlen(config), 0);
1158 1159 1160
        if (!conf)
            goto cleanup;

M
Markus Groß 已提交
1161
        def = xenParseXM(conf, priv->xendConfigVersion, priv->caps);
1162
    } else if (STREQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
1163 1164 1165 1166 1167
        id = xenGetDomIdFromSxprString(config, priv->xendConfigVersion);
        xenUnifiedLock(priv);
        tty = xenStoreDomainGetConsolePath(conn, id);
        vncport = xenStoreDomainGetVNCPort(conn, id);
        xenUnifiedUnlock(priv);
M
Markus Groß 已提交
1168
        def = xenParseSxprString(config, priv->xendConfigVersion, tty,
1169
                                       vncport);
1170 1171 1172 1173
    }
    if (!def)
        goto cleanup;

1174
    ret = virDomainDefFormat(def, 0);
1175 1176 1177

cleanup:
    virDomainDefFree(def);
1178 1179
    if (conf)
        virConfFree(conf);
1180 1181 1182 1183 1184 1185
    return ret;
}


#define MAX_CONFIG_SIZE (1024 * 65)
static char *
1186 1187 1188 1189
xenUnifiedConnectDomainXMLToNative(virConnectPtr conn,
                                   const char *format,
                                   const char *xmlData,
                                   unsigned int flags)
1190 1191 1192 1193
{
    virDomainDefPtr def = NULL;
    char *ret = NULL;
    virConfPtr conf = NULL;
1194
    xenUnifiedPrivatePtr priv = conn->privateData;
1195

E
Eric Blake 已提交
1196 1197
    virCheckFlags(0, NULL);

1198 1199
    if (STRNEQ(format, XEN_CONFIG_FORMAT_XM) &&
        STRNEQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
1200 1201
        virReportError(VIR_ERR_INVALID_ARG,
                       _("unsupported config type %s"), format);
1202 1203 1204
        goto cleanup;
    }

1205 1206
    if (!(def = virDomainDefParseString(xmlData, priv->caps, priv->xmlopt,
                                        1 << VIR_DOMAIN_VIRT_XEN, 0)))
1207 1208 1209 1210
        goto cleanup;

    if (STREQ(format, XEN_CONFIG_FORMAT_XM)) {
        int len = MAX_CONFIG_SIZE;
M
Markus Groß 已提交
1211
        conf = xenFormatXM(conn, def, priv->xendConfigVersion);
1212 1213 1214 1215
        if (!conf)
            goto cleanup;

        if (VIR_ALLOC_N(ret, len) < 0) {
1216
            virReportOOMError();
1217 1218 1219 1220 1221 1222 1223 1224
            goto cleanup;
        }

        if (virConfWriteMem(ret, &len, conf) < 0) {
            VIR_FREE(ret);
            goto cleanup;
        }
    } else if (STREQ(format, XEN_CONFIG_FORMAT_SEXPR)) {
M
Markus Groß 已提交
1225
        ret = xenFormatSxpr(conn, def, priv->xendConfigVersion);
1226 1227 1228 1229 1230 1231 1232 1233 1234 1235
    }

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


1236
static int
1237 1238 1239 1240 1241 1242 1243 1244
xenUnifiedDomainMigratePrepare(virConnectPtr dconn,
                               char **cookie,
                               int *cookielen,
                               const char *uri_in,
                               char **uri_out,
                               unsigned long flags,
                               const char *dname,
                               unsigned long resource)
1245
{
E
Eric Blake 已提交
1246 1247
    virCheckFlags(XEN_MIGRATION_FLAGS, -1);

1248 1249 1250
    return xenDaemonDomainMigratePrepare(dconn, cookie, cookielen,
                                         uri_in, uri_out,
                                         flags, dname, resource);
1251 1252 1253
}

static int
1254 1255 1256 1257 1258 1259 1260
xenUnifiedDomainMigratePerform(virDomainPtr dom,
                               const char *cookie,
                               int cookielen,
                               const char *uri,
                               unsigned long flags,
                               const char *dname,
                               unsigned long resource)
1261
{
E
Eric Blake 已提交
1262 1263
    virCheckFlags(XEN_MIGRATION_FLAGS, -1);

1264 1265
    return xenDaemonDomainMigratePerform(dom, cookie, cookielen, uri,
                                         flags, dname, resource);
1266 1267 1268
}

static virDomainPtr
1269 1270 1271 1272 1273 1274
xenUnifiedDomainMigrateFinish(virConnectPtr dconn,
                              const char *dname,
                              const char *cookie ATTRIBUTE_UNUSED,
                              int cookielen ATTRIBUTE_UNUSED,
                              const char *uri ATTRIBUTE_UNUSED,
                              unsigned long flags)
1275
{
1276 1277 1278 1279
    virDomainPtr dom = NULL;
    char *domain_xml = NULL;
    virDomainPtr dom_new = NULL;

E
Eric Blake 已提交
1280 1281
    virCheckFlags(XEN_MIGRATION_FLAGS, NULL);

1282
    if (!(dom = xenUnifiedDomainLookupByName(dconn, dname)))
1283 1284 1285
        return NULL;

    if (flags & VIR_MIGRATE_PERSIST_DEST) {
1286
        domain_xml = xenDaemonDomainGetXMLDesc(dom, 0, NULL);
1287
        if (! domain_xml) {
1288 1289
            virReportError(VIR_ERR_MIGRATE_PERSIST_FAILED,
                           "%s", _("failed to get XML representation of migrated domain"));
1290
            goto error;
1291 1292
        }

1293
        dom_new = xenDaemonDomainDefineXML(dconn, domain_xml);
1294
        if (! dom_new) {
1295 1296
            virReportError(VIR_ERR_MIGRATE_PERSIST_FAILED,
                           "%s", _("failed to define domain on destination host"));
1297
            goto error;
1298 1299 1300
        }

        /* Free additional reference added by Define */
1301
        virDomainFree(dom_new);
1302 1303
    }

1304
    VIR_FREE(domain_xml);
1305 1306 1307 1308

    return dom;


1309
error:
1310
    virDomainFree(dom);
1311

1312
    VIR_FREE(domain_xml);
1313 1314

    return NULL;
1315 1316
}

1317
static int
1318 1319
xenUnifiedConnectListDefinedDomains(virConnectPtr conn, char **const names,
                                    int maxnames)
1320
{
1321
    xenUnifiedPrivatePtr priv = conn->privateData;
1322

1323 1324 1325 1326 1327
    if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
        return xenXMListDefinedDomains(conn, names, maxnames);
    } else {
        return xenDaemonListDefinedDomains(conn, names, maxnames);
    }
1328 1329 1330
}

static int
1331
xenUnifiedConnectNumOfDefinedDomains(virConnectPtr conn)
1332
{
1333
    xenUnifiedPrivatePtr priv = conn->privateData;
1334

1335 1336 1337 1338 1339
    if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
        return xenXMNumOfDefinedDomains(conn);
    } else {
        return xenDaemonNumOfDefinedDomains(conn);
    }
1340 1341 1342
}

static int
1343
xenUnifiedDomainCreateWithFlags(virDomainPtr dom, unsigned int flags)
1344
{
1345
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1346 1347
    int ret = -1;
    char *name = NULL;
1348

1349 1350
    virCheckFlags(0, -1);

1351 1352 1353 1354 1355
    name = xenUnifiedDomainManagedSavePath(priv, dom);
    if (!name)
        goto cleanup;

    if (virFileExists(name)) {
1356 1357 1358
        ret = xenDaemonDomainRestore(dom->conn, name);
        if (ret == 0)
            unlink(name);
1359 1360 1361
        goto cleanup;
    }

1362 1363 1364 1365
    if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
        ret = xenXMDomainCreate(dom);
    else
        ret = xenDaemonDomainCreate(dom);
1366

1367 1368 1369
cleanup:
    VIR_FREE(name);
    return ret;
1370 1371
}

1372
static int
1373
xenUnifiedDomainCreate(virDomainPtr dom)
1374 1375 1376 1377
{
    return xenUnifiedDomainCreateWithFlags(dom, 0);
}

1378
static virDomainPtr
1379
xenUnifiedDomainDefineXML(virConnectPtr conn, const char *xml)
1380
{
1381
    xenUnifiedPrivatePtr priv = conn->privateData;
1382

1383 1384 1385 1386
    if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
        return xenXMDomainDefineXML(conn, xml);
    else
        return xenDaemonDomainDefineXML(conn, xml);
1387 1388 1389
}

static int
1390
xenUnifiedDomainUndefineFlags(virDomainPtr dom, unsigned int flags)
1391
{
1392
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1393

1394
    virCheckFlags(0, -1);
1395 1396 1397 1398
    if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
        return xenXMDomainUndefine(dom);
    else
        return xenDaemonDomainUndefine(dom);
1399 1400
}

1401
static int
1402
xenUnifiedDomainUndefine(virDomainPtr dom) {
1403 1404 1405
    return xenUnifiedDomainUndefineFlags(dom, 0);
}

1406
static int
1407
xenUnifiedDomainAttachDevice(virDomainPtr dom, const char *xml)
1408
{
1409
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1410
    unsigned int flags = VIR_DOMAIN_DEVICE_MODIFY_LIVE;
1411

1412 1413 1414 1415 1416
    /*
     * 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
     */
1417
    if (priv->xendConfigVersion >= XEND_CONFIG_VERSION_3_0_4)
1418
        flags |= VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
1419

1420 1421 1422 1423
    if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
        return xenXMDomainAttachDeviceFlags(dom, xml, flags);
    else
        return xenDaemonAttachDeviceFlags(dom, xml, flags);
1424 1425 1426 1427 1428

    return -1;
}

static int
1429 1430
xenUnifiedDomainAttachDeviceFlags(virDomainPtr dom, const char *xml,
                                  unsigned int flags)
1431
{
1432
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1433

1434 1435 1436 1437
    if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
        return xenXMDomainAttachDeviceFlags(dom, xml, flags);
    else
        return xenDaemonAttachDeviceFlags(dom, xml, flags);
1438 1439 1440
}

static int
1441
xenUnifiedDomainDetachDevice(virDomainPtr dom, const char *xml)
1442
{
1443
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1444
    unsigned int flags = VIR_DOMAIN_DEVICE_MODIFY_LIVE;
1445

1446 1447 1448 1449 1450
    /*
     * 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
     */
1451
    if (priv->xendConfigVersion >= XEND_CONFIG_VERSION_3_0_4)
1452
        flags |= VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
1453

1454 1455 1456 1457
    if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
        return xenXMDomainDetachDeviceFlags(dom, xml, flags);
    else
        return xenDaemonDetachDeviceFlags(dom, xml, flags);
1458 1459 1460
}

static int
1461 1462
xenUnifiedDomainDetachDeviceFlags(virDomainPtr dom, const char *xml,
                                  unsigned int flags)
1463
{
1464
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1465

1466 1467 1468 1469
    if (dom->id < 0 && priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4)
        return xenXMDomainDetachDeviceFlags(dom, xml, flags);
    else
        return xenDaemonDetachDeviceFlags(dom, xml, flags);
1470 1471
}

1472
static int
1473 1474
xenUnifiedDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml,
                                  unsigned int flags)
1475
{
1476
    return xenDaemonUpdateDeviceFlags(dom, xml, flags);
1477 1478
}

1479
static int
1480
xenUnifiedDomainGetAutostart(virDomainPtr dom, int *autostart)
1481
{
1482
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1483

1484
    if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
1485 1486 1487 1488 1489 1490
        if (priv->opened[XEN_UNIFIED_XM_OFFSET])
            return xenXMDomainGetAutostart(dom, autostart);
    } else {
        if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
            return xenDaemonDomainGetAutostart(dom, autostart);
    }
1491

1492
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1493 1494 1495 1496
    return -1;
}

static int
1497
xenUnifiedDomainSetAutostart(virDomainPtr dom, int autostart)
1498
{
1499
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1500

1501
    if (priv->xendConfigVersion < XEND_CONFIG_VERSION_3_0_4) {
1502 1503 1504 1505 1506 1507
        if (priv->opened[XEN_UNIFIED_XM_OFFSET])
            return xenXMDomainSetAutostart(dom, autostart);
    } else {
        if (priv->opened[XEN_UNIFIED_XEND_OFFSET])
            return xenDaemonDomainSetAutostart(dom, autostart);
    }
1508

1509
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1510 1511 1512
    return -1;
}

1513
static char *
1514
xenUnifiedDomainGetSchedulerType(virDomainPtr dom, int *nparams)
1515
{
1516
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1517 1518 1519 1520
    int i;
    char *schedulertype;

    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; i++) {
E
Eric Blake 已提交
1521
        if (priv->opened[i] && drivers[i]->xenDomainGetSchedulerType) {
1522
            schedulertype = drivers[i]->xenDomainGetSchedulerType(dom, nparams);
1523
            if (schedulertype != NULL)
1524
                return schedulertype;
1525 1526
        }
    }
1527
    return NULL;
1528 1529 1530
}

static int
1531 1532 1533 1534
xenUnifiedDomainGetSchedulerParametersFlags(virDomainPtr dom,
                                            virTypedParameterPtr params,
                                            int *nparams,
                                            unsigned int flags)
1535
{
1536
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1537 1538
    int i, ret;

1539 1540
    virCheckFlags(0, -1);

1541
    for (i = 0; i < XEN_UNIFIED_NR_DRIVERS; ++i) {
E
Eric Blake 已提交
1542 1543
        if (priv->opened[i] && drivers[i]->xenDomainGetSchedulerParameters) {
           ret = drivers[i]->xenDomainGetSchedulerParameters(dom, params, nparams);
1544
           if (ret == 0)
1545
               return 0;
1546
        }
1547
    }
1548
    return -1;
1549 1550 1551
}

static int
1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564
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)
1565
{
1566
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1567 1568
    int i, ret;

1569 1570
    virCheckFlags(0, -1);

1571 1572
    /* do the hypervisor call last to get better error */
    for (i = XEN_UNIFIED_NR_DRIVERS - 1; i >= 0; i--) {
E
Eric Blake 已提交
1573 1574
        if (priv->opened[i] && drivers[i]->xenDomainSetSchedulerParameters) {
           ret = drivers[i]->xenDomainSetSchedulerParameters(dom, params, nparams);
1575 1576 1577
           if (ret == 0)
               return 0;
        }
1578 1579
    }

1580
    return -1;
1581 1582
}

1583 1584 1585 1586 1587 1588 1589 1590 1591
static int
xenUnifiedDomainSetSchedulerParameters(virDomainPtr dom,
                                       virTypedParameterPtr params,
                                       int nparams)
{
    return xenUnifiedDomainSetSchedulerParametersFlags(dom, params,
                                                       nparams, 0);
}

1592
static int
1593 1594
xenUnifiedDomainBlockStats(virDomainPtr dom, const char *path,
                           struct _virDomainBlockStats *stats)
1595
{
1596
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1597 1598

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

1601
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1602 1603 1604 1605
    return -1;
}

static int
1606 1607
xenUnifiedDomainInterfaceStats(virDomainPtr dom, const char *path,
                               struct _virDomainInterfaceStats *stats)
1608
{
1609
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
1610 1611

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

1614
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1615 1616 1617
    return -1;
}

R
Richard W.M. Jones 已提交
1618
static int
1619 1620 1621
xenUnifiedDomainBlockPeek(virDomainPtr dom, const char *path,
                          unsigned long long offset, size_t size,
                          void *buffer, unsigned int flags)
R
Richard W.M. Jones 已提交
1622 1623
{
    int r;
1624
    xenUnifiedPrivatePtr priv = dom->conn->privateData;
R
Richard W.M. Jones 已提交
1625

E
Eric Blake 已提交
1626 1627
    virCheckFlags(0, -1);

R
Richard W.M. Jones 已提交
1628
    if (priv->opened[XEN_UNIFIED_XEND_OFFSET]) {
1629
        r = xenDaemonDomainBlockPeek(dom, path, offset, size, buffer);
R
Richard W.M. Jones 已提交
1630 1631 1632 1633 1634
        if (r != -2) return r;
        /* r == -2 means declined, so fall through to XM driver ... */
    }

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

1639
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
R
Richard W.M. Jones 已提交
1640 1641 1642
    return -1;
}

1643
static int
1644 1645
xenUnifiedNodeGetCellsFreeMemory(virConnectPtr conn, unsigned long long *freeMems,
                                 int startCell, int maxCells)
1646
{
1647
    xenUnifiedPrivatePtr priv = conn->privateData;
1648 1649

    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET])
1650 1651
        return xenHypervisorNodeGetCellsFreeMemory(conn, freeMems,
                                                   startCell, maxCells);
1652

1653
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1654 1655 1656
    return -1;
}

1657
static unsigned long long
1658
xenUnifiedNodeGetFreeMemory(virConnectPtr conn)
1659 1660 1661
{
    unsigned long long freeMem = 0;
    int ret;
1662
    xenUnifiedPrivatePtr priv = conn->privateData;
1663 1664

    if (priv->opened[XEN_UNIFIED_HYPERVISOR_OFFSET]) {
1665 1666
        ret = xenHypervisorNodeGetCellsFreeMemory(conn, &freeMem,
                                                  -1, 1);
1667
        if (ret != 1)
1668 1669
            return 0;
        return freeMem;
1670 1671
    }

1672
    virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1673
    return 0;
1674 1675
}

1676

1677
static int
1678 1679 1680 1681
xenUnifiedConnectDomainEventRegister(virConnectPtr conn,
                                     virConnectDomainEventCallback callback,
                                     void *opaque,
                                     virFreeCallback freefunc)
1682
{
1683
    xenUnifiedPrivatePtr priv = conn->privateData;
D
Daniel P. Berrange 已提交
1684

1685
    int ret;
D
Daniel P. Berrange 已提交
1686
    xenUnifiedLock(priv);
1687

1688
    if (priv->xsWatch == -1) {
1689
        virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
D
Daniel P. Berrange 已提交
1690
        xenUnifiedUnlock(priv);
1691 1692 1693
        return -1;
    }

1694 1695
    ret = virDomainEventStateRegister(conn, priv->domainEvents,
                                      callback, opaque, freefunc);
1696

D
Daniel P. Berrange 已提交
1697
    xenUnifiedUnlock(priv);
1698
    return ret;
1699 1700
}

1701

1702
static int
1703 1704
xenUnifiedConnectDomainEventDeregister(virConnectPtr conn,
                                       virConnectDomainEventCallback callback)
1705 1706
{
    int ret;
1707
    xenUnifiedPrivatePtr priv = conn->privateData;
D
Daniel P. Berrange 已提交
1708 1709
    xenUnifiedLock(priv);

1710
    if (priv->xsWatch == -1) {
1711
        virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
D
Daniel P. Berrange 已提交
1712
        xenUnifiedUnlock(priv);
1713 1714 1715
        return -1;
    }

1716 1717 1718
    ret = virDomainEventStateDeregister(conn,
                                        priv->domainEvents,
                                        callback);
1719

D
Daniel P. Berrange 已提交
1720
    xenUnifiedUnlock(priv);
1721 1722 1723
    return ret;
}

1724

1725
static int
1726 1727 1728 1729 1730 1731
xenUnifiedConnectDomainEventRegisterAny(virConnectPtr conn,
                                        virDomainPtr dom,
                                        int eventID,
                                        virConnectDomainEventGenericCallback callback,
                                        void *opaque,
                                        virFreeCallback freefunc)
1732
{
1733
    xenUnifiedPrivatePtr priv = conn->privateData;
1734 1735 1736 1737 1738

    int ret;
    xenUnifiedLock(priv);

    if (priv->xsWatch == -1) {
1739
        virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1740 1741 1742 1743
        xenUnifiedUnlock(priv);
        return -1;
    }

1744 1745 1746
    if (virDomainEventStateRegisterID(conn, priv->domainEvents,
                                      dom, eventID,
                                      callback, opaque, freefunc, &ret) < 0)
1747
        ret = -1;
1748 1749

    xenUnifiedUnlock(priv);
1750
    return ret;
1751 1752 1753
}

static int
1754 1755
xenUnifiedConnectDomainEventDeregisterAny(virConnectPtr conn,
                                          int callbackID)
1756 1757
{
    int ret;
1758
    xenUnifiedPrivatePtr priv = conn->privateData;
1759 1760 1761
    xenUnifiedLock(priv);

    if (priv->xsWatch == -1) {
1762
        virReportError(VIR_ERR_NO_SUPPORT, __FUNCTION__);
1763 1764 1765 1766
        xenUnifiedUnlock(priv);
        return -1;
    }

1767 1768 1769
    ret = virDomainEventStateDeregisterID(conn,
                                          priv->domainEvents,
                                          callbackID);
1770 1771 1772 1773 1774 1775

    xenUnifiedUnlock(priv);
    return ret;
}


1776
static int
1777 1778 1779 1780 1781
xenUnifiedNodeDeviceGetPciInfo(virNodeDevicePtr dev,
                               unsigned *domain,
                               unsigned *bus,
                               unsigned *slot,
                               unsigned *function)
1782 1783 1784 1785 1786 1787 1788 1789 1790 1791
{
    virNodeDeviceDefPtr def = NULL;
    virNodeDevCapsDefPtr cap;
    char *xml = NULL;
    int ret = -1;

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

1792
    def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL);
1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809
    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) {
1810 1811
        virReportError(VIR_ERR_INVALID_ARG,
                       _("device %s is not a PCI device"), dev->name);
1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822
        goto out;
    }

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

static int
1823 1824 1825
xenUnifiedNodeDeviceDetachFlags(virNodeDevicePtr dev,
                                const char *driverName,
                                unsigned int flags)
1826
{
1827
    virPCIDevicePtr pci;
1828 1829 1830
    unsigned domain, bus, slot, function;
    int ret = -1;

1831 1832
    virCheckFlags(0, -1);

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

1836
    pci = virPCIDeviceNew(domain, bus, slot, function);
1837 1838 1839
    if (!pci)
        return -1;

1840 1841 1842 1843 1844 1845 1846 1847 1848
    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)
1849 1850 1851 1852
        goto out;

    ret = 0;
out:
1853
    virPCIDeviceFree(pci);
1854 1855 1856
    return ret;
}

1857 1858 1859 1860 1861 1862
static int
xenUnifiedNodeDeviceDettach(virNodeDevicePtr dev)
{
    return xenUnifiedNodeDeviceDetachFlags(dev, NULL, 0);
}

1863
static int
1864
xenUnifiedNodeDeviceAssignedDomainId(virNodeDevicePtr dev)
1865 1866 1867 1868 1869 1870 1871 1872 1873 1874 1875
{
    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 */
1876
    numdomains = xenUnifiedConnectNumOfDomains(conn);
1877 1878 1879 1880 1881 1882 1883 1884
    if (numdomains < 0) {
        return ret;
    }
    if (numdomains > 0){
        if (VIR_ALLOC_N(ids, numdomains) < 0) {
            virReportOOMError();
            goto out;
        }
1885
        if ((numdomains = xenUnifiedConnectListDomains(conn, &ids[0], numdomains)) < 0) {
1886 1887 1888 1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901
            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 */
1902
    for (i = 0; i < numdomains; i++) {
1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920
        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;
}

1921
static int
1922
xenUnifiedNodeDeviceReAttach(virNodeDevicePtr dev)
1923
{
1924
    virPCIDevicePtr pci;
1925 1926
    unsigned domain, bus, slot, function;
    int ret = -1;
1927
    int domid;
1928 1929 1930 1931

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

1932
    pci = virPCIDeviceNew(domain, bus, slot, function);
1933 1934 1935
    if (!pci)
        return -1;

1936 1937
    /* Check if device is assigned to an active guest */
    if ((domid = xenUnifiedNodeDeviceAssignedDomainId(dev)) >= 0) {
1938 1939 1940
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Device %s has been assigned to guest %d"),
                       dev->name, domid);
1941 1942 1943
        goto out;
    }

1944
    if (virPCIDeviceReattach(pci, NULL, NULL) < 0)
1945 1946 1947 1948
        goto out;

    ret = 0;
out:
1949
    virPCIDeviceFree(pci);
1950 1951 1952 1953
    return ret;
}

static int
1954
xenUnifiedNodeDeviceReset(virNodeDevicePtr dev)
1955
{
1956
    virPCIDevicePtr pci;
1957 1958 1959 1960 1961 1962
    unsigned domain, bus, slot, function;
    int ret = -1;

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

1963
    pci = virPCIDeviceNew(domain, bus, slot, function);
1964 1965 1966
    if (!pci)
        return -1;

1967
    if (virPCIDeviceReset(pci, NULL, NULL) < 0)
1968 1969 1970 1971
        goto out;

    ret = 0;
out:
1972
    virPCIDeviceFree(pci);
1973 1974 1975 1976
    return ret;
}


1977 1978
static int
xenUnifiedDomainOpenConsole(virDomainPtr dom,
1979
                            const char *dev_name,
1980 1981 1982 1983 1984 1985 1986 1987 1988 1989
                            virStreamPtr st,
                            unsigned int flags)
{
    virDomainDefPtr def = NULL;
    int ret = -1;
    virDomainChrDefPtr chr = NULL;

    virCheckFlags(0, -1);

    if (dom->id == -1) {
1990 1991
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
1992 1993 1994
        goto cleanup;
    }

1995
    if (dev_name) {
1996
        /* XXX support device aliases in future */
1997 1998
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("Named device aliases are not supported"));
1999 2000 2001 2002 2003 2004 2005
        goto cleanup;
    }

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

2006 2007
    if (def->nconsoles)
        chr = def->consoles[0];
2008 2009 2010 2011
    else if (def->nserials)
        chr = def->serials[0];

    if (!chr) {
2012 2013
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("cannot find default console device"));
2014 2015 2016
        goto cleanup;
    }

2017
    if (chr->source.type != VIR_DOMAIN_CHR_TYPE_PTY) {
2018 2019
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("character device %s is not using a PTY"), dev_name);
2020 2021 2022
        goto cleanup;
    }

2023
    if (virFDStreamOpenFile(st, chr->source.data.file.path,
E
Eric Blake 已提交
2024
                            0, 0, O_RDWR) < 0)
2025 2026 2027 2028 2029 2030 2031
        goto cleanup;

    ret = 0;
cleanup:
    virDomainDefFree(def);
    return ret;
}
2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051

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

2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062

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 已提交
2063
/*----- Register with libvirt.c, and initialize Xen drivers. -----*/
2064 2065 2066

/* The interface which we export upwards to libvirt.c. */
static virDriver xenUnifiedDriver = {
2067 2068
    .no = VIR_DRV_XEN_UNIFIED,
    .name = "Xen",
2069 2070 2071 2072 2073
    .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 */
2074
    .connectGetHostname = xenUnifiedConnectGetHostname, /* 0.7.3 */
2075
    .connectGetMaxVcpus = xenUnifiedConnectGetMaxVcpus, /* 0.2.1 */
2076
    .nodeGetInfo = xenUnifiedNodeGetInfo, /* 0.1.0 */
2077 2078 2079
    .connectGetCapabilities = xenUnifiedConnectGetCapabilities, /* 0.2.1 */
    .connectListDomains = xenUnifiedConnectListDomains, /* 0.0.3 */
    .connectNumOfDomains = xenUnifiedConnectNumOfDomains, /* 0.0.3 */
2080 2081 2082 2083 2084 2085 2086
    .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 */
2087
    .domainShutdownFlags = xenUnifiedDomainShutdownFlags, /* 0.9.10 */
2088 2089
    .domainReboot = xenUnifiedDomainReboot, /* 0.1.0 */
    .domainDestroy = xenUnifiedDomainDestroy, /* 0.0.3 */
2090
    .domainDestroyFlags = xenUnifiedDomainDestroyFlags, /* 0.9.4 */
2091 2092 2093 2094 2095 2096 2097
    .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 */
2098
    .domainSaveFlags = xenUnifiedDomainSaveFlags, /* 0.9.4 */
2099 2100 2101
    .domainManagedSave = xenUnifiedDomainManagedSave, /* 1.0.1 */
    .domainHasManagedSaveImage = xenUnifiedDomainHasManagedSaveImage, /* 1.0.1 */
    .domainManagedSaveRemove = xenUnifiedDomainManagedSaveRemove, /* 1.0.1 */
2102
    .domainRestore = xenUnifiedDomainRestore, /* 0.0.3 */
2103
    .domainRestoreFlags = xenUnifiedDomainRestoreFlags, /* 0.9.4 */
2104 2105 2106 2107 2108 2109 2110 2111
    .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 */
2112 2113 2114 2115
    .connectDomainXMLFromNative = xenUnifiedConnectDomainXMLFromNative, /* 0.6.4 */
    .connectDomainXMLToNative = xenUnifiedConnectDomainXMLToNative, /* 0.6.4 */
    .connectListDefinedDomains = xenUnifiedConnectListDefinedDomains, /* 0.1.1 */
    .connectNumOfDefinedDomains = xenUnifiedConnectNumOfDefinedDomains, /* 0.1.5 */
2116 2117 2118 2119
    .domainCreate = xenUnifiedDomainCreate, /* 0.1.1 */
    .domainCreateWithFlags = xenUnifiedDomainCreateWithFlags, /* 0.8.2 */
    .domainDefineXML = xenUnifiedDomainDefineXML, /* 0.1.1 */
    .domainUndefine = xenUnifiedDomainUndefine, /* 0.1.1 */
2120
    .domainUndefineFlags = xenUnifiedDomainUndefineFlags, /* 0.9.4 */
2121 2122 2123 2124 2125 2126 2127 2128 2129
    .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 */
2130
    .domainGetSchedulerParametersFlags = xenUnifiedDomainGetSchedulerParametersFlags, /* 0.9.2 */
2131
    .domainSetSchedulerParameters = xenUnifiedDomainSetSchedulerParameters, /* 0.2.3 */
2132
    .domainSetSchedulerParametersFlags = xenUnifiedDomainSetSchedulerParametersFlags, /* 0.9.2 */
2133 2134 2135 2136 2137 2138 2139 2140
    .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 */
2141 2142
    .connectDomainEventRegister = xenUnifiedConnectDomainEventRegister, /* 0.5.0 */
    .connectDomainEventDeregister = xenUnifiedConnectDomainEventDeregister, /* 0.5.0 */
2143
    .nodeDeviceDettach = xenUnifiedNodeDeviceDettach, /* 0.6.1 */
2144
    .nodeDeviceDetachFlags = xenUnifiedNodeDeviceDetachFlags, /* 1.0.5 */
2145 2146
    .nodeDeviceReAttach = xenUnifiedNodeDeviceReAttach, /* 0.6.1 */
    .nodeDeviceReset = xenUnifiedNodeDeviceReset, /* 0.6.1 */
2147 2148
    .connectIsEncrypted = xenUnifiedConnectIsEncrypted, /* 0.7.3 */
    .connectIsSecure = xenUnifiedConnectIsSecure, /* 0.7.3 */
2149 2150 2151
    .domainIsActive = xenUnifiedDomainIsActive, /* 0.7.3 */
    .domainIsPersistent = xenUnifiedDomainIsPersistent, /* 0.7.3 */
    .domainIsUpdated = xenUnifiedDomainIsUpdated, /* 0.8.6 */
2152 2153
    .connectDomainEventRegisterAny = xenUnifiedConnectDomainEventRegisterAny, /* 0.8.0 */
    .connectDomainEventDeregisterAny = xenUnifiedConnectDomainEventDeregisterAny, /* 0.8.0 */
2154
    .domainOpenConsole = xenUnifiedDomainOpenConsole, /* 0.8.6 */
2155
    .connectIsAlive = xenUnifiedConnectIsAlive, /* 0.9.8 */
2156
    .nodeSuspendForDuration = xenUnifiedNodeSuspendForDuration, /* 0.9.8 */
2157 2158
    .nodeGetMemoryParameters = xenUnifiedNodeGetMemoryParameters, /* 0.10.2 */
    .nodeSetMemoryParameters = xenUnifiedNodeSetMemoryParameters, /* 0.10.2 */
2159 2160
};

2161
/**
2162
 * xenRegister:
2163 2164 2165 2166 2167
 *
 * Register xen related drivers
 *
 * Returns the driver priority or -1 in case of error.
 */
2168
int
2169
xenRegister(void)
2170
{
2171
    if (virRegisterStateDriver(&state_driver) == -1) return -1;
J
John Levon 已提交
2172

2173
    return virRegisterDriver(&xenUnifiedDriver);
2174 2175
}

2176 2177 2178 2179 2180 2181 2182 2183 2184
/**
 * xenUnifiedDomainInfoListFree:
 *
 * Free the Domain Info List
 */
void
xenUnifiedDomainInfoListFree(xenUnifiedDomainInfoListPtr list)
{
    int i;
J
John Levon 已提交
2185 2186 2187 2188

    if (list == NULL)
        return;

2189 2190 2191 2192
    for (i=0; i<list->count; i++) {
        VIR_FREE(list->doms[i]->name);
        VIR_FREE(list->doms[i]);
    }
2193
    VIR_FREE(list->doms);
2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215
    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)) {
2216
            VIR_DEBUG("WARNING: dom already tracked");
2217 2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238
            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:
2239
    virReportOOMError();
2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259
    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++) {
2260
        if (list->doms[i]->id == id &&
2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284
            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;
}

2285

2286 2287
/**
 * xenUnifiedDomainEventDispatch:
D
Daniel P. Berrange 已提交
2288 2289
 * @priv: the connection to dispatch events on
 * @event: the event to dispatch
2290 2291 2292
 *
 * Dispatch domain events to registered callbacks
 *
D
Daniel P. Berrange 已提交
2293 2294
 * The caller must hold the lock in 'priv' before invoking
 *
2295
 */
2296
void xenUnifiedDomainEventDispatch(xenUnifiedPrivatePtr priv,
2297
                                    virDomainEventPtr event)
2298
{
D
Daniel P. Berrange 已提交
2299
    if (!priv)
2300
        return;
2301

2302
    virDomainEventStateQueue(priv->domainEvents, event);
D
Daniel P. Berrange 已提交
2303 2304 2305 2306 2307 2308 2309 2310 2311 2312
}

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

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