libxl_driver.c 150.4 KB
Newer Older
1 2 3
/*
 * libxl_driver.c: core driver methods for managing libxenlight domains
 *
4
 * Copyright (C) 2006-2014 Red Hat, Inc.
5
 * Copyright (C) 2011-2015 SUSE LINUX Products GmbH, Nuernberg, Germany.
6
 * Copyright (C) 2011 Univention GmbH.
J
Jim Fehlig 已提交
7 8 9 10 11 12 13 14 15 16 17 18
 *
 * 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
19
 * License along with this library.  If not, see
O
Osier Yang 已提交
20
 * <http://www.gnu.org/licenses/>.
M
Markus Groß 已提交
21 22 23 24 25
 *
 * Authors:
 *     Jim Fehlig <jfehlig@novell.com>
 *     Markus Groß <gross@univention.de>
 *     Daniel P. Berrange <berrange@redhat.com>
J
Jim Fehlig 已提交
26 27 28 29
 */

#include <config.h>

30
#include <math.h>
J
Jim Fehlig 已提交
31
#include <libxl.h>
32
#include <libxl_utils.h>
33
#include <fcntl.h>
34
#include <regex.h>
J
Jim Fehlig 已提交
35 36

#include "internal.h"
37
#include "virlog.h"
38
#include "virerror.h"
39
#include "virconf.h"
J
Jim Fehlig 已提交
40
#include "datatypes.h"
E
Eric Blake 已提交
41
#include "virfile.h"
42
#include "viralloc.h"
43
#include "viruuid.h"
44
#include "vircommand.h"
J
Jim Fehlig 已提交
45
#include "libxl_domain.h"
J
Jim Fehlig 已提交
46 47
#include "libxl_driver.h"
#include "libxl_conf.h"
J
Jim Fehlig 已提交
48
#include "libxl_migration.h"
49
#include "xen_xm.h"
50
#include "xen_sxpr.h"
51
#include "xen_xl.h"
52
#include "virtypedparam.h"
M
Martin Kletzander 已提交
53
#include "viruri.h"
54
#include "virstring.h"
55
#include "virsysinfo.h"
56
#include "viraccessapicheck.h"
57
#include "viratomic.h"
58
#include "virhostdev.h"
59
#include "network/bridge_driver.h"
60
#include "locking/domain_lock.h"
J
Jim Fehlig 已提交
61 62 63

#define VIR_FROM_THIS VIR_FROM_LIBXL

64 65
VIR_LOG_INIT("libxl.libxl_driver");

J
Jim Fehlig 已提交
66 67 68 69 70 71
#define LIBXL_DOM_REQ_POWEROFF 0
#define LIBXL_DOM_REQ_REBOOT   1
#define LIBXL_DOM_REQ_SUSPEND  2
#define LIBXL_DOM_REQ_CRASH    3
#define LIBXL_DOM_REQ_HALT     4

72
#define LIBXL_CONFIG_FORMAT_XL "xen-xl"
73
#define LIBXL_CONFIG_FORMAT_XM "xen-xm"
74
#define LIBXL_CONFIG_FORMAT_SEXPR "xen-sxpr"
75

76 77
#define HYPERVISOR_CAPABILITIES "/proc/xen/capabilities"

78 79 80
/* Number of Xen scheduler parameters */
#define XEN_SCHED_CREDIT_NPARAM   2

81

82
static libxlDriverPrivatePtr libxl_driver;
J
Jim Fehlig 已提交
83

84 85 86 87 88 89 90 91 92
/* Object used to store info related to libxl event registrations */
typedef struct _libxlOSEventHookInfo libxlOSEventHookInfo;
typedef libxlOSEventHookInfo *libxlOSEventHookInfoPtr;
struct _libxlOSEventHookInfo {
    libxl_ctx *ctx;
    void *xl_priv;
    int id;
};

J
Jim Fehlig 已提交
93
/* Function declarations */
94 95
static int
libxlDomainManagedSaveLoad(virDomainObjPtr vm,
96 97
                           void *opaque);

J
Jim Fehlig 已提交
98 99

/* Function definitions */
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
static void
libxlOSEventHookInfoFree(void *obj)
{
    VIR_FREE(obj);
}

static void
libxlFDEventCallback(int watch ATTRIBUTE_UNUSED,
                     int fd,
                     int vir_events,
                     void *fd_info)
{
    libxlOSEventHookInfoPtr info = fd_info;
    int events = 0;

    if (vir_events & VIR_EVENT_HANDLE_READABLE)
        events |= POLLIN;
    if (vir_events & VIR_EVENT_HANDLE_WRITABLE)
        events |= POLLOUT;
    if (vir_events & VIR_EVENT_HANDLE_ERROR)
        events |= POLLERR;
    if (vir_events & VIR_EVENT_HANDLE_HANGUP)
        events |= POLLHUP;

    libxl_osevent_occurred_fd(info->ctx, info->xl_priv, fd, 0, events);
}

static int
libxlFDRegisterEventHook(void *priv,
                         int fd,
                         void **hndp,
                         short events,
                         void *xl_priv)
{
    int vir_events = VIR_EVENT_HANDLE_ERROR;
    libxlOSEventHookInfoPtr info;

    if (VIR_ALLOC(info) < 0)
        return -1;

    info->ctx = priv;
    info->xl_priv = xl_priv;

    if (events & POLLIN)
        vir_events |= VIR_EVENT_HANDLE_READABLE;
    if (events & POLLOUT)
        vir_events |= VIR_EVENT_HANDLE_WRITABLE;

    info->id = virEventAddHandle(fd, vir_events, libxlFDEventCallback,
                                 info, libxlOSEventHookInfoFree);
    if (info->id < 0) {
        VIR_FREE(info);
        return -1;
    }

    *hndp = info;

    return 0;
}

static int
libxlFDModifyEventHook(void *priv ATTRIBUTE_UNUSED,
                       int fd ATTRIBUTE_UNUSED,
                       void **hndp,
                       short events)
{
    libxlOSEventHookInfoPtr info = *hndp;
    int vir_events = VIR_EVENT_HANDLE_ERROR;

    if (events & POLLIN)
        vir_events |= VIR_EVENT_HANDLE_READABLE;
    if (events & POLLOUT)
        vir_events |= VIR_EVENT_HANDLE_WRITABLE;

    virEventUpdateHandle(info->id, vir_events);

    return 0;
}

static void
libxlFDDeregisterEventHook(void *priv ATTRIBUTE_UNUSED,
                           int fd ATTRIBUTE_UNUSED,
                           void *hnd)
{
    libxlOSEventHookInfoPtr info = hnd;

    virEventRemoveHandle(info->id);
}

static void
libxlTimerCallback(int timer ATTRIBUTE_UNUSED, void *timer_info)
{
    libxlOSEventHookInfoPtr info = timer_info;

    /*
     * libxl expects the event to be deregistered when calling
     * libxl_osevent_occurred_timeout, but we dont want the event info
     * destroyed.  Disable the timeout and only remove it after returning
     * from libxl.
     */
    virEventUpdateTimeout(info->id, -1);
    libxl_osevent_occurred_timeout(info->ctx, info->xl_priv);
    virEventRemoveTimeout(info->id);
}

static int
libxlTimeoutRegisterEventHook(void *priv,
                              void **hndp,
                              struct timeval abs_t,
                              void *xl_priv)
{
    libxlOSEventHookInfoPtr info;
    struct timeval now;
    struct timeval res;
    static struct timeval zero;
    int timeout;

    if (VIR_ALLOC(info) < 0)
        return -1;

    info->ctx = priv;
    info->xl_priv = xl_priv;

    gettimeofday(&now, NULL);
    timersub(&abs_t, &now, &res);
    /* Ensure timeout is not overflowed */
    if (timercmp(&res, &zero, <)) {
        timeout = 0;
    } else if (res.tv_sec > INT_MAX / 1000) {
        timeout = INT_MAX;
    } else {
        timeout = res.tv_sec * 1000 + (res.tv_usec + 999) / 1000;
    }
    info->id = virEventAddTimeout(timeout, libxlTimerCallback,
                                  info, libxlOSEventHookInfoFree);
    if (info->id < 0) {
        VIR_FREE(info);
        return -1;
    }

    *hndp = info;

    return 0;
}

/*
 * Note:  There are two changes wrt timeouts starting with xen-unstable
 * changeset 26469:
 *
 * 1. Timeout modify callbacks will only be invoked with an abs_t of {0,0},
 * i.e. make the timeout fire immediately.  Prior to this commit, timeout
 * modify callbacks were never invoked.
 *
 * 2. Timeout deregister hooks will no longer be called.
 */
static int
libxlTimeoutModifyEventHook(void *priv ATTRIBUTE_UNUSED,
                            void **hndp,
                            struct timeval abs_t ATTRIBUTE_UNUSED)
{
    libxlOSEventHookInfoPtr info = *hndp;

    /* Make the timeout fire */
    virEventUpdateTimeout(info->id, 0);

    return 0;
}

static void
libxlTimeoutDeregisterEventHook(void *priv ATTRIBUTE_UNUSED,
                                void *hnd)
{
    libxlOSEventHookInfoPtr info = hnd;

    virEventRemoveTimeout(info->id);
}

J
Jim Fehlig 已提交
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295
static virDomainObjPtr
libxlDomObjFromDomain(virDomainPtr dom)
{
    virDomainObjPtr vm;
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    char uuidstr[VIR_UUID_STRING_BUFLEN];

    vm = virDomainObjListFindByUUID(driver->domains, dom->uuid);
    if (!vm) {
        virUUIDFormat(dom->uuid, uuidstr);
        virReportError(VIR_ERR_NO_DOMAIN,
                       _("no domain with matching uuid '%s' (%s)"),
                       uuidstr, dom->name);
        return NULL;
    }

    return vm;
}

296 297
static int
libxlAutostartDomain(virDomainObjPtr vm,
298 299 300 301
                     void *opaque)
{
    libxlDriverPrivatePtr driver = opaque;
    virErrorPtr err;
302
    int ret = -1;
303

304
    virObjectLock(vm);
305 306
    virResetLastError();

307 308 309 310 311
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0) {
        virObjectUnlock(vm);
        return ret;
    }

312
    if (vm->autostart && !virDomainObjIsActive(vm) &&
313
        libxlDomainStart(driver, vm, false, -1) < 0) {
314 315 316 317
        err = virGetLastError();
        VIR_ERROR(_("Failed to autostart VM '%s': %s"),
                  vm->def->name,
                  err ? err->message : _("unknown error"));
318
        goto endjob;
319 320
    }

321
    ret = 0;
322 323 324 325 326

 endjob:
    if (libxlDomainObjEndJob(driver, vm))
        virObjectUnlock(vm);

327
    return ret;
328 329
}

J
Jim Fehlig 已提交
330 331 332 333
/*
 * Reconnect to running domains that were previously started/created
 * with libxenlight driver.
 */
334 335
static int
libxlReconnectDomain(virDomainObjPtr vm,
J
Jim Fehlig 已提交
336 337 338
                     void *opaque)
{
    libxlDriverPrivatePtr driver = opaque;
339
    libxlDomainObjPrivatePtr priv = vm->privateData;
J
Jim Fehlig 已提交
340
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
J
Jim Fehlig 已提交
341 342 343 344
    int rc;
    libxl_dominfo d_info;
    int len;
    uint8_t *data = NULL;
345
    virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
J
Jim Fehlig 已提交
346

347
    virObjectLock(vm);
J
Jim Fehlig 已提交
348 349

    /* Does domain still exist? */
J
Jim Fehlig 已提交
350
    rc = libxl_domain_info(cfg->ctx, &d_info, vm->def->id);
J
Jim Fehlig 已提交
351 352 353 354 355 356 357 358 359
    if (rc == ERROR_INVAL) {
        goto out;
    } else if (rc != 0) {
        VIR_DEBUG("libxl_domain_info failed (code %d), ignoring domain %d",
                  rc, vm->def->id);
        goto out;
    }

    /* Is this a domain that was under libvirt control? */
J
Jim Fehlig 已提交
360
    if (libxl_userdata_retrieve(cfg->ctx, vm->def->id,
J
Jim Fehlig 已提交
361 362 363 364 365 366 367
                                "libvirt-xml", &data, &len)) {
        VIR_DEBUG("libxl_userdata_retrieve failed, ignoring domain %d", vm->def->id);
        goto out;
    }

    /* Update domid in case it changed (e.g. reboot) while we were gone? */
    vm->def->id = d_info.domid;
368 369 370 371 372 373

    /* Update hostdev state */
    if (virHostdevUpdateDomainActiveDevices(hostdev_mgr, LIBXL_DRIVER_NAME,
                                            vm->def, VIR_HOSTDEV_SP_PCI) < 0)
        goto out;

J
Jiri Denemark 已提交
374
    virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_UNKNOWN);
J
Jim Fehlig 已提交
375

376
    if (virAtomicIntInc(&driver->nactive) == 1 && driver->inhibitCallback)
377 378
        driver->inhibitCallback(true, driver->inhibitOpaque);

379
    /* Enable domain death events */
J
Jim Fehlig 已提交
380
    libxl_evenable_domain_death(cfg->ctx, vm->def->id, 0, &priv->deathW);
381

382
    virObjectUnlock(vm);
J
Jim Fehlig 已提交
383
    virObjectUnref(cfg);
384
    return 0;
J
Jim Fehlig 已提交
385

386
 out:
387
    libxlDomainCleanup(driver, vm, VIR_DOMAIN_SHUTOFF_UNKNOWN);
J
Jim Fehlig 已提交
388
    if (!vm->persistent)
389
        virDomainObjListRemoveLocked(driver->domains, vm);
J
Jim Fehlig 已提交
390
    else
391
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
392
    virObjectUnref(cfg);
393 394

    return -1;
J
Jim Fehlig 已提交
395 396 397 398 399
}

static void
libxlReconnectDomains(libxlDriverPrivatePtr driver)
{
400
    virDomainObjListForEach(driver->domains, libxlReconnectDomain, driver);
J
Jim Fehlig 已提交
401 402 403
}

static int
404
libxlStateCleanup(void)
J
Jim Fehlig 已提交
405 406 407 408
{
    if (!libxl_driver)
        return -1;

409
    virObjectUnref(libxl_driver->hostdevMgr);
410
    virObjectUnref(libxl_driver->config);
411
    virObjectUnref(libxl_driver->xmlopt);
412
    virObjectUnref(libxl_driver->domains);
413
    virObjectUnref(libxl_driver->reservedVNCPorts);
J
Jim Fehlig 已提交
414
    virObjectUnref(libxl_driver->migrationPorts);
415
    virLockManagerPluginUnref(libxl_driver->lockManager);
J
Jim Fehlig 已提交
416

417
    virObjectEventStateFree(libxl_driver->domainEventState);
418
    virSysinfoDefFree(libxl_driver->hostsysinfo);
419

J
Jim Fehlig 已提交
420 421 422 423 424 425
    virMutexDestroy(&libxl_driver->lock);
    VIR_FREE(libxl_driver);

    return 0;
}

426 427
static bool
libxlDriverShouldLoad(bool privileged)
428
{
429 430
    bool ret = false;
    int status;
431
    char *output = NULL;
J
Jim Fehlig 已提交
432

433
    /* Don't load if non-root */
J
Jim Fehlig 已提交
434
    if (!privileged) {
435
        VIR_INFO("Not running privileged, disabling libxenlight driver");
436
        return ret;
J
Jim Fehlig 已提交
437 438
    }

439 440 441
    if (!virFileExists(HYPERVISOR_CAPABILITIES)) {
        VIR_INFO("Disabling driver as " HYPERVISOR_CAPABILITIES
                 " does not exist");
442
        return ret;
443
    }
444 445 446 447 448
    /*
     * Don't load if not running on a Xen control domain (dom0). It is not
     * sufficient to check for the file to exist as any guest can mount
     * xenfs to /proc/xen.
     */
449
    status = virFileReadAll(HYPERVISOR_CAPABILITIES, 10, &output);
450
    if (status >= 0)
451 452 453
        status = strncmp(output, "control_d", 9);
    VIR_FREE(output);
    if (status) {
454 455 456 457 458 459 460
        VIR_INFO("No Xen capabilities detected, probably not running "
                 "in a Xen Dom0.  Disabling libxenlight driver");

        return ret;
    }

    /* Don't load if legacy xen toolstack (xend) is in use */
461 462 463 464 465 466 467 468 469 470 471
    if (virFileExists("/usr/sbin/xend")) {
        virCommandPtr cmd;

        cmd = virCommandNewArgList("/usr/sbin/xend", "status", NULL);
        if (virCommandRun(cmd, NULL) == 0) {
            VIR_INFO("Legacy xen tool stack seems to be in use, disabling "
                     "libxenlight driver.");
        } else {
            ret = true;
        }
        virCommandFree(cmd);
472 473
    } else {
        ret = true;
J
Jim Fehlig 已提交
474 475
    }

476 477 478
    return ret;
}

479 480 481 482 483 484 485 486 487 488
/* Callbacks wrapping libvirt's event loop interface */
static const libxl_osevent_hooks libxl_osevent_callbacks = {
    .fd_register = libxlFDRegisterEventHook,
    .fd_modify = libxlFDModifyEventHook,
    .fd_deregister = libxlFDDeregisterEventHook,
    .timeout_register = libxlTimeoutRegisterEventHook,
    .timeout_modify = libxlTimeoutModifyEventHook,
    .timeout_deregister = libxlTimeoutDeregisterEventHook,
};

489 490 491 492 493 494 495 496
static const libxl_childproc_hooks libxl_child_hooks = {
#ifdef LIBXL_HAVE_SIGCHLD_OWNER_SELECTIVE_REAP
    .chldowner = libxl_sigchld_owner_libxl_always_selective_reap,
#else
    .chldowner = libxl_sigchld_owner_libxl,
#endif
};

497 498 499 500 501 502
const struct libxl_event_hooks ev_hooks = {
    .event_occurs_mask = LIBXL_EVENTMASK_ALL,
    .event_occurs = libxlDomainEventHandler,
    .disaster = NULL,
};

503 504 505 506 507
static int
libxlStateInitialize(bool privileged,
                     virStateInhibitCallback callback ATTRIBUTE_UNUSED,
                     void *opaque ATTRIBUTE_UNUSED)
{
508
    libxlDriverConfigPtr cfg;
509
    char *driverConf = NULL;
510 511 512 513 514
    char ebuf[1024];

    if (!libxlDriverShouldLoad(privileged))
        return 0;

J
Jim Fehlig 已提交
515 516 517 518
    if (VIR_ALLOC(libxl_driver) < 0)
        return -1;

    if (virMutexInit(&libxl_driver->lock) < 0) {
519 520
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("cannot initialize mutex"));
J
Jim Fehlig 已提交
521 522 523 524 525
        VIR_FREE(libxl_driver);
        return -1;
    }

    /* Allocate bitmap for vnc port reservation */
526
    if (!(libxl_driver->reservedVNCPorts =
J
Ján Tomko 已提交
527 528
          virPortAllocatorNew(_("VNC"),
                              LIBXL_VNC_PORT_MIN,
529 530
                              LIBXL_VNC_PORT_MAX,
                              0)))
531
        goto error;
J
Jim Fehlig 已提交
532

J
Jim Fehlig 已提交
533 534 535 536
    /* Allocate bitmap for migration port reservation */
    if (!(libxl_driver->migrationPorts =
          virPortAllocatorNew(_("migration"),
                              LIBXL_MIGRATION_PORT_MIN,
537
                              LIBXL_MIGRATION_PORT_MAX, 0)))
J
Jim Fehlig 已提交
538 539
        goto error;

540 541
    if (!(libxl_driver->domains = virDomainObjListNew()))
        goto error;
J
Jim Fehlig 已提交
542

543 544 545
    if (!(libxl_driver->hostdevMgr = virHostdevManagerGetDefault()))
        goto error;

546
    if (!(cfg = libxlDriverConfigNew()))
547
        goto error;
J
Jim Fehlig 已提交
548

549 550 551 552 553 554 555
    if (virAsprintf(&driverConf, "%s/libxl.conf", cfg->configBaseDir) < 0)
        goto error;

    if (libxlDriverConfigLoadFile(cfg, driverConf) < 0)
        goto error;
    VIR_FREE(driverConf);

556 557 558
    /* Register the callbacks providing access to libvirt's event loop */
    libxl_osevent_register_hooks(cfg->ctx, &libxl_osevent_callbacks, cfg->ctx);

559 560 561
    /* Setup child process handling.  See $xen-src/tools/libxl/libxl_event.h */
    libxl_childproc_setmode(cfg->ctx, &libxl_child_hooks, cfg->ctx);

562 563 564
    /* Register callback to handle domain events */
    libxl_event_register_callbacks(cfg->ctx, &ev_hooks, libxl_driver);

565 566
    libxl_driver->config = cfg;
    if (virFileMakePath(cfg->stateDir) < 0) {
567 568
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to create state dir '%s': %s"),
569
                       cfg->stateDir,
570
                       virStrerror(errno, ebuf, sizeof(ebuf)));
J
Jim Fehlig 已提交
571 572
        goto error;
    }
573
    if (virFileMakePath(cfg->libDir) < 0) {
574 575
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to create lib dir '%s': %s"),
576
                       cfg->libDir,
577
                       virStrerror(errno, ebuf, sizeof(ebuf)));
J
Jim Fehlig 已提交
578 579
        goto error;
    }
580
    if (virFileMakePath(cfg->saveDir) < 0) {
581 582
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to create save dir '%s': %s"),
583
                       cfg->saveDir,
584
                       virStrerror(errno, ebuf, sizeof(ebuf)));
J
Jim Fehlig 已提交
585 586
        goto error;
    }
587 588 589 590 591 592 593
    if (virFileMakePath(cfg->autoDumpDir) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to create dump dir '%s': %s"),
                       cfg->autoDumpDir,
                       virStrerror(errno, ebuf, sizeof(ebuf)));
        goto error;
    }
J
Jim Fehlig 已提交
594

595 596 597 598 599 600 601 602
    if (!(libxl_driver->lockManager =
          virLockManagerPluginNew(cfg->lockManagerName ?
                                  cfg->lockManagerName : "nop",
                                  "libxl",
                                  cfg->configBaseDir,
                                  0)))
        goto error;

603
    /* read the host sysinfo */
604
    libxl_driver->hostsysinfo = virSysinfoRead();
605

606
    libxl_driver->domainEventState = virObjectEventStateNew();
E
Eric Blake 已提交
607
    if (!libxl_driver->domainEventState)
608 609
        goto error;

610
    if ((cfg->caps = libxlMakeCapabilities(cfg->ctx)) == NULL) {
611 612
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("cannot create capabilities for libxenlight"));
J
Jim Fehlig 已提交
613 614 615
        goto error;
    }

616
    if (!(libxl_driver->xmlopt = libxlCreateXMLConf()))
617
        goto error;
J
Jim Fehlig 已提交
618 619

    /* Load running domains first. */
620
    if (virDomainObjListLoadAllConfigs(libxl_driver->domains,
621 622
                                       cfg->stateDir,
                                       cfg->autostartDir,
623
                                       1,
624
                                       cfg->caps,
625
                                       libxl_driver->xmlopt,
626
                                       NULL, NULL) < 0)
J
Jim Fehlig 已提交
627 628 629 630 631
        goto error;

    libxlReconnectDomains(libxl_driver);

    /* Then inactive persistent configs */
632
    if (virDomainObjListLoadAllConfigs(libxl_driver->domains,
633 634
                                       cfg->configDir,
                                       cfg->autostartDir,
635
                                       0,
636
                                       cfg->caps,
637
                                       libxl_driver->xmlopt,
638
                                       NULL, NULL) < 0)
J
Jim Fehlig 已提交
639 640
        goto error;

641 642
    virDomainObjListForEach(libxl_driver->domains, libxlDomainManagedSaveLoad,
                            libxl_driver);
643

J
Jim Fehlig 已提交
644 645
    return 0;

646
 error:
647
    VIR_FREE(driverConf);
648
    libxlStateCleanup();
649
    return -1;
J
Jim Fehlig 已提交
650 651
}

652 653 654 655 656 657 658 659 660 661
static void
libxlStateAutoStart(void)
{
    if (!libxl_driver)
        return;

    virDomainObjListForEach(libxl_driver->domains, libxlAutostartDomain,
                            libxl_driver);
}

J
Jim Fehlig 已提交
662
static int
663
libxlStateReload(void)
J
Jim Fehlig 已提交
664
{
665 666
    libxlDriverConfigPtr cfg;

J
Jim Fehlig 已提交
667 668 669
    if (!libxl_driver)
        return 0;

670 671
    cfg = libxlDriverConfigGet(libxl_driver);

672
    virDomainObjListLoadAllConfigs(libxl_driver->domains,
673 674
                                   cfg->configDir,
                                   cfg->autostartDir,
675
                                   1,
676
                                   cfg->caps,
677
                                   libxl_driver->xmlopt,
678 679
                                   NULL, libxl_driver);

680 681
    virDomainObjListForEach(libxl_driver->domains, libxlAutostartDomain,
                            libxl_driver);
682

683
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
684 685 686 687 688
    return 0;
}


static virDrvOpenStatus
689 690 691
libxlConnectOpen(virConnectPtr conn,
                 virConnectAuthPtr auth ATTRIBUTE_UNUSED,
                 unsigned int flags)
J
Jim Fehlig 已提交
692
{
E
Eric Blake 已提交
693 694
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

J
Jim Fehlig 已提交
695 696 697 698
    if (conn->uri == NULL) {
        if (libxl_driver == NULL)
            return VIR_DRV_OPEN_DECLINED;

699
        if (!(conn->uri = virURIParse("xen:///")))
J
Jim Fehlig 已提交
700 701 702 703 704 705 706 707 708 709 710 711
            return VIR_DRV_OPEN_ERROR;
    } else {
        /* Only xen scheme */
        if (conn->uri->scheme == NULL || STRNEQ(conn->uri->scheme, "xen"))
            return VIR_DRV_OPEN_DECLINED;

        /* If server name is given, its for remote driver */
        if (conn->uri->server != NULL)
            return VIR_DRV_OPEN_DECLINED;

        /* Error if xen or libxl scheme specified but driver not started. */
        if (libxl_driver == NULL) {
712 713
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("libxenlight state driver is not active"));
J
Jim Fehlig 已提交
714 715 716 717 718 719 720 721
            return VIR_DRV_OPEN_ERROR;
        }

        /* /session isn't supported in libxenlight */
        if (conn->uri->path &&
            STRNEQ(conn->uri->path, "") &&
            STRNEQ(conn->uri->path, "/") &&
            STRNEQ(conn->uri->path, "/system")) {
722 723 724
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("unexpected Xen URI path '%s', try xen:///"),
                           NULLSTR(conn->uri->path));
J
Jim Fehlig 已提交
725 726 727 728
            return VIR_DRV_OPEN_ERROR;
        }
    }

729 730 731
    if (virConnectOpenEnsureACL(conn) < 0)
        return VIR_DRV_OPEN_ERROR;

J
Jim Fehlig 已提交
732 733 734 735 736 737
    conn->privateData = libxl_driver;

    return VIR_DRV_OPEN_SUCCESS;
};

static int
738
libxlConnectClose(virConnectPtr conn ATTRIBUTE_UNUSED)
J
Jim Fehlig 已提交
739 740 741 742 743 744
{
    conn->privateData = NULL;
    return 0;
}

static const char *
745
libxlConnectGetType(virConnectPtr conn)
J
Jim Fehlig 已提交
746
{
747 748 749
    if (virConnectGetTypeEnsureACL(conn) < 0)
        return NULL;

J
Jim Fehlig 已提交
750
    return "Xen";
J
Jim Fehlig 已提交
751 752 753
}

static int
754
libxlConnectGetVersion(virConnectPtr conn, unsigned long *version)
J
Jim Fehlig 已提交
755 756
{
    libxlDriverPrivatePtr driver = conn->privateData;
757
    libxlDriverConfigPtr cfg;
J
Jim Fehlig 已提交
758

759 760 761
    if (virConnectGetVersionEnsureACL(conn) < 0)
        return 0;

762 763 764
    cfg = libxlDriverConfigGet(driver);
    *version = cfg->version;
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
765 766 767
    return 0;
}

768

769
static char *libxlConnectGetHostname(virConnectPtr conn)
770
{
771 772 773
    if (virConnectGetHostnameEnsureACL(conn) < 0)
        return NULL;

774 775 776
    return virGetHostname();
}

777 778 779 780 781 782 783 784
static char *
libxlConnectGetSysinfo(virConnectPtr conn, unsigned int flags)
{
    libxlDriverPrivatePtr driver = conn->privateData;
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    virCheckFlags(0, NULL);

785 786 787
    if (virConnectGetSysinfoEnsureACL(conn) < 0)
        return NULL;

788 789 790 791 792 793 794 795
    if (!driver->hostsysinfo) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("Host SMBIOS information is not available"));
        return NULL;
    }

    if (virSysinfoFormat(&buf, driver->hostsysinfo) < 0)
        return NULL;
796
    if (virBufferCheckError(&buf) < 0)
797 798 799
        return NULL;
    return virBufferContentAndReset(&buf);
}
800

J
Jim Fehlig 已提交
801
static int
802
libxlConnectGetMaxVcpus(virConnectPtr conn, const char *type ATTRIBUTE_UNUSED)
J
Jim Fehlig 已提交
803 804 805
{
    int ret;
    libxlDriverPrivatePtr driver = conn->privateData;
806
    libxlDriverConfigPtr cfg;
J
Jim Fehlig 已提交
807

808 809 810
    if (virConnectGetMaxVcpusEnsureACL(conn) < 0)
        return -1;

811 812
    cfg = libxlDriverConfigGet(driver);
    ret = libxl_get_max_cpus(cfg->ctx);
813 814 815 816 817
    /* On failure, libxl_get_max_cpus() will return ERROR_FAIL from Xen 4.4
     * onward, but it ever returning 0 is obviously wrong too (and it is
     * what happens, on failure, on Xen 4.3 and earlier). Therefore, a 'less
     * or equal' is the catchall we want. */
    if (ret <= 0)
818
        ret = -1;
J
Jim Fehlig 已提交
819

820
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
821 822 823 824 825 826
    return ret;
}

static int
libxlNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info)
{
827 828 829
    if (virNodeGetInfoEnsureACL(conn) < 0)
        return -1;

830
    return libxlDriverNodeGetInfo(conn->privateData, info);
J
Jim Fehlig 已提交
831 832 833
}

static char *
834
libxlConnectGetCapabilities(virConnectPtr conn)
J
Jim Fehlig 已提交
835 836 837
{
    libxlDriverPrivatePtr driver = conn->privateData;
    char *xml;
838
    libxlDriverConfigPtr cfg;
J
Jim Fehlig 已提交
839

840 841 842
    if (virConnectGetCapabilitiesEnsureACL(conn) < 0)
        return NULL;

843
    cfg = libxlDriverConfigGet(driver);
844
    xml = virCapabilitiesFormatXML(cfg->caps);
J
Jim Fehlig 已提交
845

846
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
847 848 849 850
    return xml;
}

static int
851
libxlConnectListDomains(virConnectPtr conn, int *ids, int nids)
J
Jim Fehlig 已提交
852 853 854 855
{
    libxlDriverPrivatePtr driver = conn->privateData;
    int n;

856 857 858
    if (virConnectListDomainsEnsureACL(conn) < 0)
        return -1;

859 860
    n = virDomainObjListGetActiveIDs(driver->domains, ids, nids,
                                     virConnectListDomainsCheckACL, conn);
J
Jim Fehlig 已提交
861 862 863 864 865

    return n;
}

static int
866
libxlConnectNumOfDomains(virConnectPtr conn)
J
Jim Fehlig 已提交
867 868 869 870
{
    libxlDriverPrivatePtr driver = conn->privateData;
    int n;

871 872 873
    if (virConnectNumOfDomainsEnsureACL(conn) < 0)
        return -1;

874 875
    n = virDomainObjListNumOfDomains(driver->domains, true,
                                     virConnectNumOfDomainsCheckACL, conn);
J
Jim Fehlig 已提交
876 877 878 879 880 881 882 883 884 885 886 887

    return n;
}

static virDomainPtr
libxlDomainCreateXML(virConnectPtr conn, const char *xml,
                     unsigned int flags)
{
    libxlDriverPrivatePtr driver = conn->privateData;
    virDomainDefPtr def;
    virDomainObjPtr vm = NULL;
    virDomainPtr dom = NULL;
888
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
889
    unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;
J
Jim Fehlig 已提交
890

891 892 893 894 895
    virCheckFlags(VIR_DOMAIN_START_PAUSED |
                  VIR_DOMAIN_START_VALIDATE, NULL);

    if (flags & VIR_DOMAIN_START_VALIDATE)
        parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE;
J
Jim Fehlig 已提交
896

897
    if (!(def = virDomainDefParseString(xml, cfg->caps, driver->xmlopt,
898
                                        parse_flags)))
J
Jim Fehlig 已提交
899 900
        goto cleanup;

901 902 903
    if (virDomainCreateXMLEnsureACL(conn, def) < 0)
        goto cleanup;

904
    if (!(vm = virDomainObjListAdd(driver->domains, def,
905
                                   driver->xmlopt,
906 907
                                   VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                   NULL)))
J
Jim Fehlig 已提交
908 909 910
        goto cleanup;
    def = NULL;

911 912 913 914 915 916 917 918
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0) {
        if (!vm->persistent) {
            virDomainObjListRemove(driver->domains, vm);
            vm = NULL;
        }
        goto cleanup;
    }

919
    if (libxlDomainStart(driver, vm, (flags & VIR_DOMAIN_START_PAUSED) != 0,
920
                     -1) < 0) {
921
        virDomainObjListRemove(driver->domains, vm);
922
        goto endjob;
J
Jim Fehlig 已提交
923 924 925 926 927 928
    }

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

929 930 931 932
 endjob:
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

933
 cleanup:
J
Jim Fehlig 已提交
934 935
    virDomainDefFree(def);
    if (vm)
936
        virObjectUnlock(vm);
937
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
938 939 940 941 942 943 944 945 946 947
    return dom;
}

static virDomainPtr
libxlDomainLookupByID(virConnectPtr conn, int id)
{
    libxlDriverPrivatePtr driver = conn->privateData;
    virDomainObjPtr vm;
    virDomainPtr dom = NULL;

948
    vm = virDomainObjListFindByID(driver->domains, id);
J
Jim Fehlig 已提交
949
    if (!vm) {
950
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
J
Jim Fehlig 已提交
951 952 953
        goto cleanup;
    }

954 955 956
    if (virDomainLookupByIDEnsureACL(conn, vm->def) < 0)
        goto cleanup;

J
Jim Fehlig 已提交
957 958 959 960
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
    if (dom)
        dom->id = vm->def->id;

961
 cleanup:
J
Jim Fehlig 已提交
962
    if (vm)
963
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
964 965 966 967 968 969 970 971 972 973
    return dom;
}

static virDomainPtr
libxlDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
{
    libxlDriverPrivatePtr driver = conn->privateData;
    virDomainObjPtr vm;
    virDomainPtr dom = NULL;

974
    vm = virDomainObjListFindByUUID(driver->domains, uuid);
J
Jim Fehlig 已提交
975
    if (!vm) {
976
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
J
Jim Fehlig 已提交
977 978 979
        goto cleanup;
    }

980 981 982
    if (virDomainLookupByUUIDEnsureACL(conn, vm->def) < 0)
        goto cleanup;

J
Jim Fehlig 已提交
983 984 985 986
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
    if (dom)
        dom->id = vm->def->id;

987
 cleanup:
J
Jim Fehlig 已提交
988
    if (vm)
989
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
990 991 992 993 994 995 996 997 998 999
    return dom;
}

static virDomainPtr
libxlDomainLookupByName(virConnectPtr conn, const char *name)
{
    libxlDriverPrivatePtr driver = conn->privateData;
    virDomainObjPtr vm;
    virDomainPtr dom = NULL;

1000
    vm = virDomainObjListFindByName(driver->domains, name);
J
Jim Fehlig 已提交
1001
    if (!vm) {
1002
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
J
Jim Fehlig 已提交
1003 1004 1005
        goto cleanup;
    }

1006 1007 1008
    if (virDomainLookupByNameEnsureACL(conn, vm->def) < 0)
        goto cleanup;

J
Jim Fehlig 已提交
1009 1010 1011 1012
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
    if (dom)
        dom->id = vm->def->id;

1013
 cleanup:
1014
    virDomainObjEndAPI(&vm);
J
Jim Fehlig 已提交
1015 1016 1017
    return dom;
}

1018 1019 1020 1021
static int
libxlDomainSuspend(virDomainPtr dom)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
1022
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
1023
    virDomainObjPtr vm;
1024
    virObjectEventPtr event = NULL;
1025 1026
    int ret = -1;

J
Jim Fehlig 已提交
1027
    if (!(vm = libxlDomObjFromDomain(dom)))
1028
        goto cleanup;
1029 1030 1031 1032

    if (virDomainSuspendEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

1033 1034 1035
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

1036
    if (!virDomainObjIsActive(vm)) {
1037
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
1038
        goto endjob;
1039 1040
    }

J
Jiri Denemark 已提交
1041
    if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_PAUSED) {
J
Jim Fehlig 已提交
1042
        if (libxl_domain_pause(cfg->ctx, vm->def->id) != 0) {
1043 1044
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Failed to suspend domain '%d' with libxenlight"),
1045
                           vm->def->id);
1046
            goto endjob;
1047 1048
        }

J
Jiri Denemark 已提交
1049
        virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER);
1050

1051
        event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_SUSPENDED,
1052 1053 1054
                                         VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
    }

1055
    if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
1056
        goto endjob;
1057 1058 1059

    ret = 0;

1060
 endjob:
1061 1062 1063
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

1064
 cleanup:
1065
    if (vm)
1066
        virObjectUnlock(vm);
1067
    if (event)
1068
        libxlDomainEventQueue(driver, event);
1069
    virObjectUnref(cfg);
1070 1071 1072 1073 1074 1075 1076 1077
    return ret;
}


static int
libxlDomainResume(virDomainPtr dom)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
1078
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
1079
    virDomainObjPtr vm;
1080
    virObjectEventPtr event = NULL;
1081 1082
    int ret = -1;

J
Jim Fehlig 已提交
1083
    if (!(vm = libxlDomObjFromDomain(dom)))
1084 1085
        goto cleanup;

1086 1087 1088
    if (virDomainResumeEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

1089 1090 1091
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

1092
    if (!virDomainObjIsActive(vm)) {
1093
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
1094
        goto endjob;
1095 1096
    }

J
Jiri Denemark 已提交
1097
    if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
J
Jim Fehlig 已提交
1098
        if (libxl_domain_unpause(cfg->ctx, vm->def->id) != 0) {
1099 1100
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Failed to resume domain '%d' with libxenlight"),
1101
                           vm->def->id);
1102
            goto endjob;
1103 1104
        }

J
Jiri Denemark 已提交
1105 1106
        virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
                             VIR_DOMAIN_RUNNING_UNPAUSED);
1107

1108
        event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_RESUMED,
1109 1110 1111
                                         VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
    }

1112
    if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
1113
        goto endjob;
1114 1115 1116

    ret = 0;

1117
 endjob:
1118 1119 1120
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

1121
 cleanup:
1122
    if (vm)
1123
        virObjectUnlock(vm);
1124
    if (event)
1125
        libxlDomainEventQueue(driver, event);
1126
    virObjectUnref(cfg);
1127 1128 1129
    return ret;
}

J
Jim Fehlig 已提交
1130
static int
1131
libxlDomainShutdownFlags(virDomainPtr dom, unsigned int flags)
J
Jim Fehlig 已提交
1132
{
J
Jim Fehlig 已提交
1133 1134
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
J
Jim Fehlig 已提交
1135 1136 1137
    virDomainObjPtr vm;
    int ret = -1;

1138 1139 1140 1141 1142
    virCheckFlags(VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN |
                  VIR_DOMAIN_SHUTDOWN_PARAVIRT, -1);
    if (flags == 0)
        flags = VIR_DOMAIN_SHUTDOWN_PARAVIRT |
            VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN;
1143

J
Jim Fehlig 已提交
1144
    if (!(vm = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
1145 1146
        goto cleanup;

1147
    if (virDomainShutdownFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
1148 1149
        goto cleanup;

J
Jim Fehlig 已提交
1150
    if (!virDomainObjIsActive(vm)) {
1151 1152
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("Domain is not running"));
J
Jim Fehlig 已提交
1153 1154 1155
        goto cleanup;
    }

1156
    if (flags & VIR_DOMAIN_SHUTDOWN_PARAVIRT) {
J
Jim Fehlig 已提交
1157
        ret = libxl_domain_shutdown(cfg->ctx, vm->def->id);
1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171
        if (ret == 0)
            goto cleanup;

        if (ret != ERROR_NOPARAVIRT) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Failed to shutdown domain '%d' with libxenlight"),
                           vm->def->id);
            ret = -1;
            goto cleanup;
        }
        ret = -1;
    }

    if (flags & VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN) {
J
Jim Fehlig 已提交
1172
        ret = libxl_send_trigger(cfg->ctx, vm->def->id,
1173 1174 1175 1176
                                 LIBXL_TRIGGER_POWER, 0);
        if (ret == 0)
            goto cleanup;

1177 1178
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to shutdown domain '%d' with libxenlight"),
1179
                       vm->def->id);
1180
        ret = -1;
J
Jim Fehlig 已提交
1181 1182
    }

1183
 cleanup:
J
Jim Fehlig 已提交
1184
    if (vm)
1185
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
1186
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
1187 1188 1189
    return ret;
}

1190 1191 1192 1193 1194 1195 1196
static int
libxlDomainShutdown(virDomainPtr dom)
{
    return libxlDomainShutdownFlags(dom, 0);
}


J
Jim Fehlig 已提交
1197
static int
E
Eric Blake 已提交
1198
libxlDomainReboot(virDomainPtr dom, unsigned int flags)
J
Jim Fehlig 已提交
1199
{
J
Jim Fehlig 已提交
1200 1201
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
J
Jim Fehlig 已提交
1202 1203 1204
    virDomainObjPtr vm;
    int ret = -1;

J
Jim Fehlig 已提交
1205 1206 1207
    virCheckFlags(VIR_DOMAIN_REBOOT_PARAVIRT, -1);
    if (flags == 0)
        flags = VIR_DOMAIN_REBOOT_PARAVIRT;
E
Eric Blake 已提交
1208

J
Jim Fehlig 已提交
1209
    if (!(vm = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
1210 1211
        goto cleanup;

1212
    if (virDomainRebootEnsureACL(dom->conn, vm->def, flags) < 0)
1213 1214
        goto cleanup;

J
Jim Fehlig 已提交
1215
    if (!virDomainObjIsActive(vm)) {
1216 1217
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("Domain is not running"));
J
Jim Fehlig 已提交
1218 1219 1220
        goto cleanup;
    }

J
Jim Fehlig 已提交
1221
    if (flags & VIR_DOMAIN_REBOOT_PARAVIRT) {
J
Jim Fehlig 已提交
1222
        ret = libxl_domain_reboot(cfg->ctx, vm->def->id);
J
Jim Fehlig 已提交
1223 1224 1225
        if (ret == 0)
            goto cleanup;

1226 1227
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to reboot domain '%d' with libxenlight"),
1228
                       vm->def->id);
J
Jim Fehlig 已提交
1229
        ret = -1;
J
Jim Fehlig 已提交
1230 1231
    }

1232
 cleanup:
J
Jim Fehlig 已提交
1233
    if (vm)
1234
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
1235
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
1236 1237 1238 1239
    return ret;
}

static int
1240 1241
libxlDomainDestroyFlags(virDomainPtr dom,
                        unsigned int flags)
J
Jim Fehlig 已提交
1242 1243
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
J
Jim Fehlig 已提交
1244
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
J
Jim Fehlig 已提交
1245 1246
    virDomainObjPtr vm;
    int ret = -1;
1247
    virObjectEventPtr event = NULL;
J
Jim Fehlig 已提交
1248

1249 1250
    virCheckFlags(0, -1);

J
Jim Fehlig 已提交
1251
    if (!(vm = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
1252 1253
        goto cleanup;

1254 1255 1256
    if (virDomainDestroyFlagsEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

1257 1258 1259
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

J
Jim Fehlig 已提交
1260
    if (!virDomainObjIsActive(vm)) {
1261 1262
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("Domain is not running"));
1263
        goto endjob;
J
Jim Fehlig 已提交
1264 1265
    }

1266
    event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
1267 1268
                                     VIR_DOMAIN_EVENT_STOPPED_DESTROYED);

1269
    if (libxlDomainDestroyInternal(driver, vm) < 0) {
1270
        virReportError(VIR_ERR_INTERNAL_ERROR,
1271
                       _("Failed to destroy domain '%d'"), vm->def->id);
1272
        goto endjob;
J
Jim Fehlig 已提交
1273 1274
    }

1275 1276 1277
    libxlDomainCleanup(driver, vm, VIR_DOMAIN_SHUTOFF_DESTROYED);
    if (!vm->persistent)
        virDomainObjListRemove(driver->domains, vm);
J
Jim Fehlig 已提交
1278 1279 1280

    ret = 0;

1281 1282 1283 1284
 endjob:
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

1285
 cleanup:
J
Jim Fehlig 已提交
1286
    if (vm)
1287
        virObjectUnlock(vm);
1288 1289
    if (event)
        libxlDomainEventQueue(driver, event);
J
Jim Fehlig 已提交
1290
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
1291 1292 1293
    return ret;
}

1294 1295 1296 1297 1298 1299
static int
libxlDomainDestroy(virDomainPtr dom)
{
    return libxlDomainDestroyFlags(dom, 0);
}

1300 1301 1302 1303 1304 1305
static char *
libxlDomainGetOSType(virDomainPtr dom)
{
    virDomainObjPtr vm;
    char *type = NULL;

J
Jim Fehlig 已提交
1306
    if (!(vm = libxlDomObjFromDomain(dom)))
1307 1308
        goto cleanup;

1309 1310 1311
    if (virDomainGetOSTypeEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

1312
    if (VIR_STRDUP(type, virDomainOSTypeToString(vm->def->os.type)) < 0)
1313
        goto cleanup;
1314

1315
 cleanup:
1316
    if (vm)
1317
        virObjectUnlock(vm);
1318 1319 1320
    return type;
}

1321
static unsigned long long
1322 1323 1324
libxlDomainGetMaxMemory(virDomainPtr dom)
{
    virDomainObjPtr vm;
1325
    unsigned long long ret = 0;
1326

J
Jim Fehlig 已提交
1327
    if (!(vm = libxlDomObjFromDomain(dom)))
1328
        goto cleanup;
1329 1330 1331 1332

    if (virDomainGetMaxMemoryEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

1333
    ret = virDomainDefGetMemoryActual(vm->def);
1334

1335
 cleanup:
1336
    if (vm)
1337
        virObjectUnlock(vm);
1338 1339 1340 1341
    return ret;
}

static int
1342
libxlDomainSetMemoryFlags(virDomainPtr dom, unsigned long newmem,
1343 1344 1345
                          unsigned int flags)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
1346
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
1347
    virDomainObjPtr vm;
1348 1349
    virDomainDefPtr persistentDef = NULL;
    bool isActive;
1350 1351 1352
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_MEM_LIVE |
1353 1354
                  VIR_DOMAIN_MEM_CONFIG |
                  VIR_DOMAIN_MEM_MAXIMUM, -1);
1355

J
Jim Fehlig 已提交
1356
    if (!(vm = libxlDomObjFromDomain(dom)))
1357 1358
        goto cleanup;

1359 1360 1361
    if (virDomainSetMemoryFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
        goto cleanup;

1362 1363 1364
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377
    isActive = virDomainObjIsActive(vm);

    if (flags == VIR_DOMAIN_MEM_CURRENT) {
        if (isActive)
            flags = VIR_DOMAIN_MEM_LIVE;
        else
            flags = VIR_DOMAIN_MEM_CONFIG;
    }
    if (flags == VIR_DOMAIN_MEM_MAXIMUM) {
        if (isActive)
            flags = VIR_DOMAIN_MEM_LIVE | VIR_DOMAIN_MEM_MAXIMUM;
        else
            flags = VIR_DOMAIN_MEM_CONFIG | VIR_DOMAIN_MEM_MAXIMUM;
1378 1379
    }

1380
    if (!isActive && (flags & VIR_DOMAIN_MEM_LIVE)) {
1381 1382
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("cannot set memory on an inactive domain"));
1383
        goto endjob;
1384 1385 1386 1387
    }

    if (flags & VIR_DOMAIN_MEM_CONFIG) {
        if (!vm->persistent) {
1388 1389
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                           _("cannot change persistent config of a transient domain"));
1390
            goto endjob;
1391
        }
1392
        if (!(persistentDef = virDomainObjGetPersistentDef(cfg->caps,
1393
                                                           driver->xmlopt,
1394
                                                           vm)))
1395
            goto endjob;
1396 1397
    }

1398 1399
    if (flags & VIR_DOMAIN_MEM_MAXIMUM) {
        /* resize the maximum memory */
1400

1401
        if (flags & VIR_DOMAIN_MEM_LIVE) {
J
Jim Fehlig 已提交
1402
            if (libxl_domain_setmaxmem(cfg->ctx, vm->def->id, newmem) < 0) {
1403 1404
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("Failed to set maximum memory for domain '%d'"
1405
                                 " with libxenlight"), vm->def->id);
1406
                goto endjob;
1407 1408 1409 1410 1411 1412
            }
        }

        if (flags & VIR_DOMAIN_MEM_CONFIG) {
            /* Help clang 2.8 decipher the logic flow.  */
            sa_assert(persistentDef);
1413
            virDomainDefSetMemoryInitial(persistentDef, newmem);
1414 1415
            if (persistentDef->mem.cur_balloon > newmem)
                persistentDef->mem.cur_balloon = newmem;
1416
            ret = virDomainSaveConfig(cfg->configDir, persistentDef);
1417
            goto endjob;
1418 1419
        }

1420 1421
    } else {
        /* resize the current memory */
1422

1423
        if (newmem > virDomainDefGetMemoryActual(vm->def)) {
1424 1425
            virReportError(VIR_ERR_INVALID_ARG, "%s",
                           _("cannot set memory higher than max memory"));
1426
            goto endjob;
1427 1428 1429
        }

        if (flags & VIR_DOMAIN_MEM_LIVE) {
1430 1431 1432 1433
            int res;

            /* Unlock virDomainObj while ballooning memory */
            virObjectUnlock(vm);
J
Jim Fehlig 已提交
1434
            res = libxl_set_memory_target(cfg->ctx, vm->def->id, newmem, 0,
1435 1436 1437
                                          /* force */ 1);
            virObjectLock(vm);
            if (res < 0) {
1438 1439
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("Failed to set memory for domain '%d'"
1440
                                 " with libxenlight"), vm->def->id);
1441
                goto endjob;
1442 1443 1444 1445 1446 1447
            }
        }

        if (flags & VIR_DOMAIN_MEM_CONFIG) {
            sa_assert(persistentDef);
            persistentDef->mem.cur_balloon = newmem;
1448
            ret = virDomainSaveConfig(cfg->configDir, persistentDef);
1449
            goto endjob;
1450
        }
1451 1452
    }

1453 1454
    ret = 0;

1455
 endjob:
1456 1457 1458
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

1459
 cleanup:
1460
    if (vm)
1461
        virObjectUnlock(vm);
1462
    virObjectUnref(cfg);
1463 1464 1465 1466 1467 1468 1469 1470 1471
    return ret;
}

static int
libxlDomainSetMemory(virDomainPtr dom, unsigned long memory)
{
    return libxlDomainSetMemoryFlags(dom, memory, VIR_DOMAIN_MEM_LIVE);
}

1472 1473 1474 1475 1476 1477
static int
libxlDomainSetMaxMemory(virDomainPtr dom, unsigned long memory)
{
    return libxlDomainSetMemoryFlags(dom, memory, VIR_DOMAIN_MEM_MAXIMUM);
}

J
Jim Fehlig 已提交
1478 1479 1480
static int
libxlDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info)
{
J
Jim Fehlig 已提交
1481 1482
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
J
Jim Fehlig 已提交
1483
    virDomainObjPtr vm;
1484
    libxl_dominfo d_info;
J
Jim Fehlig 已提交
1485 1486
    int ret = -1;

J
Jim Fehlig 已提交
1487
    if (!(vm = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
1488 1489
        goto cleanup;

1490 1491 1492
    if (virDomainGetInfoEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

1493 1494 1495
    if (!virDomainObjIsActive(vm)) {
        info->cpuTime = 0;
        info->memory = vm->def->mem.cur_balloon;
1496
        info->maxMem = virDomainDefGetMemoryActual(vm->def);
1497
    } else {
J
Jim Fehlig 已提交
1498
        if (libxl_domain_info(cfg->ctx, &d_info, vm->def->id) != 0) {
1499
            virReportError(VIR_ERR_INTERNAL_ERROR,
1500 1501
                           _("libxl_domain_info failed for domain '%d'"),
                           vm->def->id);
1502 1503 1504 1505
            goto cleanup;
        }
        info->cpuTime = d_info.cpu_time;
        info->memory = d_info.current_memkb;
1506
        info->maxMem = d_info.max_memkb;
1507 1508
    }

J
Jiri Denemark 已提交
1509
    info->state = virDomainObjGetState(vm, NULL);
J
Jim Fehlig 已提交
1510 1511 1512
    info->nrVirtCpu = vm->def->vcpus;
    ret = 0;

1513
 cleanup:
J
Jim Fehlig 已提交
1514
    if (vm)
1515
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
1516
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
1517 1518 1519
    return ret;
}

1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530
static int
libxlDomainGetState(virDomainPtr dom,
                    int *state,
                    int *reason,
                    unsigned int flags)
{
    virDomainObjPtr vm;
    int ret = -1;

    virCheckFlags(0, -1);

J
Jim Fehlig 已提交
1531
    if (!(vm = libxlDomObjFromDomain(dom)))
1532 1533
        goto cleanup;

1534 1535 1536
    if (virDomainGetStateEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

J
Jiri Denemark 已提交
1537
    *state = virDomainObjGetState(vm, reason);
1538 1539
    ret = 0;

1540
 cleanup:
1541
    if (vm)
1542
        virObjectUnlock(vm);
1543 1544 1545
    return ret;
}

1546 1547 1548
/*
 * virDomainObjPtr must be locked on invocation
 */
1549
static int
1550 1551
libxlDoDomainSave(libxlDriverPrivatePtr driver, virDomainObjPtr vm,
                  const char *to)
1552
{
J
Jim Fehlig 已提交
1553
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
1554
    libxlSavefileHeader hdr;
1555
    virObjectEventPtr event = NULL;
1556 1557
    char *xml = NULL;
    uint32_t xml_len;
1558
    int fd = -1;
1559 1560 1561
    int ret = -1;

    if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
1562 1563 1564
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("Domain '%d' has to be running because libxenlight will"
                         " suspend it"), vm->def->id);
1565 1566 1567 1568
        goto cleanup;
    }

    if ((fd = virFileOpenAs(to, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR,
L
Laine Stump 已提交
1569
                            -1, -1, 0)) < 0) {
1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584
        virReportSystemError(-fd,
                             _("Failed to create domain save file '%s'"), to);
        goto cleanup;
    }

    if ((xml = virDomainDefFormat(vm->def, 0)) == NULL)
        goto cleanup;
    xml_len = strlen(xml) + 1;

    memset(&hdr, 0, sizeof(hdr));
    memcpy(hdr.magic, LIBXL_SAVE_MAGIC, sizeof(hdr.magic));
    hdr.version = LIBXL_SAVE_VERSION;
    hdr.xmlLen = xml_len;

    if (safewrite(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
1585 1586
        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                       _("Failed to write save file header"));
1587 1588 1589 1590
        goto cleanup;
    }

    if (safewrite(fd, xml, xml_len) != xml_len) {
1591 1592
        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                       _("Failed to write xml description"));
1593 1594 1595
        goto cleanup;
    }

1596 1597
    /* Unlock virDomainObj while saving domain */
    virObjectUnlock(vm);
J
Jim Fehlig 已提交
1598
    ret = libxl_domain_suspend(cfg->ctx, vm->def->id, fd, 0, NULL);
1599 1600 1601
    virObjectLock(vm);

    if (ret != 0) {
1602 1603 1604
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to save domain '%d' with libxenlight"),
                       vm->def->id);
1605
        ret = -1;
1606 1607 1608
        goto cleanup;
    }

1609
    event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
1610 1611
                                         VIR_DOMAIN_EVENT_STOPPED_SAVED);

1612
    if (libxlDomainDestroyInternal(driver, vm) < 0) {
1613 1614
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to destroy domain '%d'"), vm->def->id);
1615 1616 1617
        goto cleanup;
    }

1618
    libxlDomainCleanup(driver, vm, VIR_DOMAIN_SHUTOFF_SAVED);
1619
    vm->hasManagedSave = true;
1620 1621
    ret = 0;

1622
 cleanup:
1623 1624 1625 1626 1627
    VIR_FREE(xml);
    if (VIR_CLOSE(fd) < 0)
        virReportSystemError(errno, "%s", _("cannot close file"));
    if (event)
        libxlDomainEventQueue(driver, event);
J
Jim Fehlig 已提交
1628
    virObjectUnref(cfg);
1629 1630 1631 1632
    return ret;
}

static int
1633 1634
libxlDomainSaveFlags(virDomainPtr dom, const char *to, const char *dxml,
                     unsigned int flags)
1635
{
1636 1637
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    virDomainObjPtr vm;
1638
    int ret = -1;
1639
    bool remove_dom = false;
1640

1641 1642 1643 1644 1645
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
    virReportUnsupportedError();
    return -1;
#endif

1646 1647
    virCheckFlags(0, -1);
    if (dxml) {
1648 1649
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
1650 1651 1652
        return -1;
    }

J
Jim Fehlig 已提交
1653
    if (!(vm = libxlDomObjFromDomain(dom)))
1654 1655
        goto cleanup;

1656 1657 1658
    if (virDomainSaveFlagsEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

1659 1660 1661
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

1662
    if (!virDomainObjIsActive(vm)) {
1663
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
1664
        goto endjob;
1665 1666
    }

1667
    if (libxlDoDomainSave(driver, vm, to) < 0)
1668
        goto endjob;
1669

1670 1671
    if (!vm->persistent)
        remove_dom = true;
1672 1673

    ret = 0;
1674

1675
 endjob:
1676 1677 1678
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

1679
 cleanup:
1680 1681 1682 1683
    if (remove_dom && vm) {
        virDomainObjListRemove(driver->domains, vm);
        vm = NULL;
    }
1684
    if (vm)
1685
        virObjectUnlock(vm);
1686 1687
    return ret;
}
1688

1689
static int
1690 1691 1692 1693 1694 1695 1696 1697
libxlDomainSave(virDomainPtr dom, const char *to)
{
    return libxlDomainSaveFlags(dom, to, NULL, 0);
}

static int
libxlDomainRestoreFlags(virConnectPtr conn, const char *from,
                        const char *dxml, unsigned int flags)
1698 1699
{
    libxlDriverPrivatePtr driver = conn->privateData;
1700
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
1701 1702 1703 1704 1705
    virDomainObjPtr vm = NULL;
    virDomainDefPtr def = NULL;
    libxlSavefileHeader hdr;
    int fd = -1;
    int ret = -1;
1706

1707 1708 1709 1710 1711
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
    virReportUnsupportedError();
    return -1;
#endif

1712
    virCheckFlags(VIR_DOMAIN_SAVE_PAUSED, -1);
1713
    if (dxml) {
1714 1715
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
1716 1717 1718
        return -1;
    }

1719
    fd = libxlDomainSaveImageOpen(driver, cfg, from, &def, &hdr);
1720
    if (fd < 0)
1721
        goto cleanup;
1722

1723
    if (virDomainRestoreFlagsEnsureACL(conn, def) < 0)
1724
        goto cleanup;
1725

1726
    if (!(vm = virDomainObjListAdd(driver->domains, def,
1727
                                   driver->xmlopt,
1728 1729 1730
                                   VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
                                   VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                   NULL)))
1731
        goto cleanup;
1732 1733 1734

    def = NULL;

1735 1736 1737 1738 1739 1740 1741 1742
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0) {
        if (!vm->persistent) {
            virDomainObjListRemove(driver->domains, vm);
            vm = NULL;
        }
        goto cleanup;
    }

1743
    ret = libxlDomainStart(driver, vm, (flags & VIR_DOMAIN_SAVE_PAUSED) != 0, fd);
1744
    if (ret < 0 && !vm->persistent)
1745
        virDomainObjListRemove(driver->domains, vm);
1746 1747

    if (!libxlDomainObjEndJob(driver, vm))
1748 1749
        vm = NULL;

1750
 cleanup:
1751 1752
    if (VIR_CLOSE(fd) < 0)
        virReportSystemError(errno, "%s", _("cannot close file"));
1753 1754
    virDomainDefFree(def);
    if (vm)
1755
        virObjectUnlock(vm);
1756
    virObjectUnref(cfg);
1757 1758 1759
    return ret;
}

1760 1761 1762 1763 1764 1765
static int
libxlDomainRestore(virConnectPtr conn, const char *from)
{
    return libxlDomainRestoreFlags(conn, from, NULL, 0);
}

1766
static int
1767
libxlDomainCoreDump(virDomainPtr dom, const char *to, unsigned int flags)
1768 1769
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
J
Jim Fehlig 已提交
1770
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
1771
    virDomainObjPtr vm;
1772
    virObjectEventPtr event = NULL;
1773
    bool remove_dom = false;
1774 1775 1776 1777 1778
    bool paused = false;
    int ret = -1;

    virCheckFlags(VIR_DUMP_LIVE | VIR_DUMP_CRASH, -1);

J
Jim Fehlig 已提交
1779
    if (!(vm = libxlDomObjFromDomain(dom)))
1780 1781
        goto cleanup;

1782 1783 1784
    if (virDomainCoreDumpEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

1785 1786 1787
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

1788
    if (!virDomainObjIsActive(vm)) {
1789
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
1790
        goto endjob;
1791 1792 1793 1794
    }

    if (!(flags & VIR_DUMP_LIVE) &&
        virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
J
Jim Fehlig 已提交
1795
        if (libxl_domain_pause(cfg->ctx, vm->def->id) != 0) {
1796 1797 1798
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Before dumping core, failed to suspend domain '%d'"
                             " with libxenlight"),
1799
                           vm->def->id);
1800
            goto endjob;
1801 1802 1803 1804 1805
        }
        virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_DUMP);
        paused = true;
    }

1806 1807
    /* Unlock virDomainObj while dumping core */
    virObjectUnlock(vm);
J
Jim Fehlig 已提交
1808
    ret = libxl_domain_core_dump(cfg->ctx, vm->def->id, to, NULL);
1809 1810
    virObjectLock(vm);
    if (ret != 0) {
1811 1812
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to dump core of domain '%d' with libxenlight"),
1813
                       vm->def->id);
1814 1815
        ret = -1;
        goto unpause;
1816 1817 1818
    }

    if (flags & VIR_DUMP_CRASH) {
1819
        if (libxlDomainDestroyInternal(driver, vm) < 0) {
1820
            virReportError(VIR_ERR_INTERNAL_ERROR,
1821
                           _("Failed to destroy domain '%d'"), vm->def->id);
1822
            goto unpause;
1823 1824
        }

1825
        libxlDomainCleanup(driver, vm, VIR_DOMAIN_SHUTOFF_CRASHED);
1826
        event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
1827
                                         VIR_DOMAIN_EVENT_STOPPED_CRASHED);
1828 1829
        if (!vm->persistent)
            remove_dom = true;
1830 1831 1832 1833
    }

    ret = 0;

1834
 unpause:
1835
    if (virDomainObjIsActive(vm) && paused) {
J
Jim Fehlig 已提交
1836
        if (libxl_domain_unpause(cfg->ctx, vm->def->id) != 0) {
1837 1838
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("After dumping core, failed to resume domain '%d' with"
1839
                             " libxenlight"), vm->def->id);
1840 1841 1842 1843 1844
        } else {
            virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
                                 VIR_DOMAIN_RUNNING_UNPAUSED);
        }
    }
1845

1846
 endjob:
1847 1848 1849
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

1850
 cleanup:
1851 1852 1853 1854
    if (remove_dom && vm) {
        virDomainObjListRemove(driver->domains, vm);
        vm = NULL;
    }
1855
    if (vm)
1856
        virObjectUnlock(vm);
1857
    if (event)
1858
        libxlDomainEventQueue(driver, event);
J
Jim Fehlig 已提交
1859
    virObjectUnref(cfg);
1860 1861 1862
    return ret;
}

1863 1864 1865 1866 1867 1868 1869
static int
libxlDomainManagedSave(virDomainPtr dom, unsigned int flags)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    virDomainObjPtr vm = NULL;
    char *name = NULL;
    int ret = -1;
1870
    bool remove_dom = false;
1871 1872 1873

    virCheckFlags(0, -1);

J
Jim Fehlig 已提交
1874
    if (!(vm = libxlDomObjFromDomain(dom)))
1875 1876
        goto cleanup;

1877 1878 1879
    if (virDomainManagedSaveEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

1880 1881 1882
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

1883
    if (!virDomainObjIsActive(vm)) {
1884
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
1885
        goto endjob;
1886
    }
1887
    if (!vm->persistent) {
1888 1889
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("cannot do managed save for transient domain"));
1890
        goto endjob;
1891
    }
1892 1893 1894

    name = libxlDomainManagedSavePath(driver, vm);
    if (name == NULL)
1895
        goto endjob;
1896 1897 1898

    VIR_INFO("Saving state to %s", name);

1899
    if (libxlDoDomainSave(driver, vm, name) < 0)
1900
        goto endjob;
1901

1902 1903
    if (!vm->persistent)
        remove_dom = true;
1904 1905

    ret = 0;
1906

1907
 endjob:
1908 1909 1910
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

1911
 cleanup:
1912 1913 1914 1915
    if (remove_dom && vm) {
        virDomainObjListRemove(driver->domains, vm);
        vm = NULL;
    }
1916
    if (vm)
1917
        virObjectUnlock(vm);
1918 1919 1920 1921
    VIR_FREE(name);
    return ret;
}

1922 1923
static int
libxlDomainManagedSaveLoad(virDomainObjPtr vm,
1924 1925 1926 1927
                           void *opaque)
{
    libxlDriverPrivatePtr driver = opaque;
    char *name;
1928
    int ret = -1;
1929

1930
    virObjectLock(vm);
1931 1932 1933 1934 1935 1936

    if (!(name = libxlDomainManagedSavePath(driver, vm)))
        goto cleanup;

    vm->hasManagedSave = virFileExists(name);

1937
    ret = 0;
1938
 cleanup:
1939
    virObjectUnlock(vm);
1940
    VIR_FREE(name);
1941
    return ret;
1942 1943
}

1944 1945 1946 1947 1948 1949 1950 1951
static int
libxlDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    int ret = -1;

    virCheckFlags(0, -1);

J
Jim Fehlig 已提交
1952
    if (!(vm = libxlDomObjFromDomain(dom)))
1953 1954
        goto cleanup;

1955 1956 1957
    if (virDomainHasManagedSaveImageEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

1958
    ret = vm->hasManagedSave;
1959

1960
 cleanup:
1961
    if (vm)
1962
        virObjectUnlock(vm);
1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975
    return ret;
}

static int
libxlDomainManagedSaveRemove(virDomainPtr dom, unsigned int flags)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    virDomainObjPtr vm = NULL;
    int ret = -1;
    char *name = NULL;

    virCheckFlags(0, -1);

J
Jim Fehlig 已提交
1976
    if (!(vm = libxlDomObjFromDomain(dom)))
1977 1978
        goto cleanup;

1979 1980 1981
    if (virDomainManagedSaveRemoveEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

1982 1983 1984 1985 1986
    name = libxlDomainManagedSavePath(driver, vm);
    if (name == NULL)
        goto cleanup;

    ret = unlink(name);
1987
    vm->hasManagedSave = false;
1988

1989
 cleanup:
1990 1991
    VIR_FREE(name);
    if (vm)
1992
        virObjectUnlock(vm);
1993 1994 1995
    return ret;
}

1996 1997 1998 1999 2000
static int
libxlDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
                         unsigned int flags)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
2001
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
2002 2003
    virDomainDefPtr def;
    virDomainObjPtr vm;
J
Jim Fehlig 已提交
2004
    libxl_bitmap map;
2005 2006
    uint8_t *bitmask = NULL;
    unsigned int maplen;
2007 2008
    size_t i;
    unsigned int pos;
2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020
    int max;
    int ret = -1;

    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)) {
2021 2022
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid flag combination: (0x%x)"), flags);
2023 2024 2025 2026
        return -1;
    }

    if (!nvcpus) {
2027
        virReportError(VIR_ERR_INVALID_ARG, "%s", _("nvcpus is zero"));
2028 2029 2030
        return -1;
    }

J
Jim Fehlig 已提交
2031
    if (!(vm = libxlDomObjFromDomain(dom)))
2032 2033
        goto cleanup;

2034 2035 2036
    if (virDomainSetVcpusFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
        goto cleanup;

2037 2038 2039
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

2040
    if (!virDomainObjIsActive(vm) && (flags & VIR_DOMAIN_VCPU_LIVE)) {
2041 2042
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("cannot set vcpus on an inactive domain"));
2043
        goto endjob;
2044 2045 2046
    }

    if (!vm->persistent && (flags & VIR_DOMAIN_VCPU_CONFIG)) {
2047 2048
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("cannot change persistent config of a transient domain"));
2049
        goto endjob;
2050 2051
    }

2052
    if ((max = libxlConnectGetMaxVcpus(dom->conn, NULL)) < 0) {
2053 2054
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("could not determine max vcpus for the domain"));
2055
        goto endjob;
2056 2057
    }

2058
    if (!(flags & VIR_DOMAIN_VCPU_MAXIMUM) && vm->def->maxvcpus < max)
2059 2060 2061
        max = vm->def->maxvcpus;

    if (nvcpus > max) {
2062 2063 2064
        virReportError(VIR_ERR_INVALID_ARG,
                       _("requested vcpus is greater than max allowable"
                         " vcpus for the domain: %d > %d"), nvcpus, max);
2065
        goto endjob;
2066 2067
    }

2068
    if (!(def = virDomainObjGetPersistentDef(cfg->caps, driver->xmlopt, vm)))
2069
        goto endjob;
2070

E
Eric Blake 已提交
2071
    maplen = VIR_CPU_MAPLEN(nvcpus);
2072
    if (VIR_ALLOC_N(bitmask, maplen) < 0)
2073
        goto endjob;
2074 2075

    for (i = 0; i < nvcpus; ++i) {
E
Eric Blake 已提交
2076
        pos = i / 8;
2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094
        bitmask[pos] |= 1 << (i % 8);
    }

    map.size = maplen;
    map.map = bitmask;

    switch (flags) {
    case VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_CONFIG:
        def->maxvcpus = nvcpus;
        if (nvcpus < def->vcpus)
            def->vcpus = nvcpus;
        break;

    case VIR_DOMAIN_VCPU_CONFIG:
        def->vcpus = nvcpus;
        break;

    case VIR_DOMAIN_VCPU_LIVE:
J
Jim Fehlig 已提交
2095
        if (libxl_set_vcpuonline(cfg->ctx, vm->def->id, &map) != 0) {
2096 2097
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Failed to set vcpus for domain '%d'"
2098
                             " with libxenlight"), vm->def->id);
2099
            goto endjob;
2100 2101 2102 2103
        }
        break;

    case VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG:
J
Jim Fehlig 已提交
2104
        if (libxl_set_vcpuonline(cfg->ctx, vm->def->id, &map) != 0) {
2105 2106
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Failed to set vcpus for domain '%d'"
2107
                             " with libxenlight"), vm->def->id);
2108
            goto endjob;
2109 2110 2111 2112 2113 2114 2115 2116
        }
        def->vcpus = nvcpus;
        break;
    }

    ret = 0;

    if (flags & VIR_DOMAIN_VCPU_CONFIG)
2117
        ret = virDomainSaveConfig(cfg->configDir, def);
2118

2119
 endjob:
2120 2121 2122
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

2123
 cleanup:
2124 2125
    VIR_FREE(bitmask);
     if (vm)
2126
        virObjectUnlock(vm);
2127
     virObjectUnref(cfg);
2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142
    return ret;
}

static int
libxlDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus)
{
    return libxlDomainSetVcpusFlags(dom, nvcpus, VIR_DOMAIN_VCPU_LIVE);
}

static int
libxlDomainGetVcpusFlags(virDomainPtr dom, unsigned int flags)
{
    virDomainObjPtr vm;
    virDomainDefPtr def;
    int ret = -1;
2143
    bool active;
2144 2145 2146 2147 2148

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

J
Jim Fehlig 已提交
2149
    if (!(vm = libxlDomObjFromDomain(dom)))
2150 2151
        goto cleanup;

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

2155 2156 2157 2158 2159 2160 2161 2162 2163
    active = virDomainObjIsActive(vm);

    if ((flags & (VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG)) == 0) {
        if (active)
            flags |= VIR_DOMAIN_VCPU_LIVE;
        else
            flags |= VIR_DOMAIN_VCPU_CONFIG;
    }
    if ((flags & VIR_DOMAIN_VCPU_LIVE) && (flags & VIR_DOMAIN_VCPU_CONFIG)) {
2164 2165
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid flag combination: (0x%x)"), flags);
2166 2167 2168
        return -1;
    }

2169
    if (flags & VIR_DOMAIN_VCPU_LIVE) {
2170
        if (!active) {
2171 2172
            virReportError(VIR_ERR_OPERATION_INVALID,
                           "%s", _("Domain is not running"));
2173 2174 2175 2176
            goto cleanup;
        }
        def = vm->def;
    } else {
2177
        if (!vm->persistent) {
2178 2179
            virReportError(VIR_ERR_OPERATION_INVALID,
                           "%s", _("domain is transient"));
2180 2181
            goto cleanup;
        }
2182 2183 2184 2185 2186
        def = vm->newDef ? vm->newDef : vm->def;
    }

    ret = (flags & VIR_DOMAIN_VCPU_MAXIMUM) ? def->maxvcpus : def->vcpus;

2187
 cleanup:
2188
    if (vm)
2189
        virObjectUnlock(vm);
2190 2191 2192 2193
    return ret;
}

static int
2194 2195 2196
libxlDomainPinVcpuFlags(virDomainPtr dom, unsigned int vcpu,
                        unsigned char *cpumap, int maplen,
                        unsigned int flags)
2197 2198
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
2199
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
2200
    virDomainDefPtr targetDef = NULL;
2201
    virBitmapPtr pcpumap = NULL;
2202 2203
    virDomainObjPtr vm;
    int ret = -1;
2204 2205 2206

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);
2207

J
Jim Fehlig 已提交
2208
    if (!(vm = libxlDomObjFromDomain(dom)))
2209 2210
        goto cleanup;

2211
    if (virDomainPinVcpuFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
2212 2213
        goto cleanup;

2214 2215 2216
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

2217
    if ((flags & VIR_DOMAIN_AFFECT_LIVE) && !virDomainObjIsActive(vm)) {
2218
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
2219
                       _("domain is inactive"));
2220
        goto endjob;
2221 2222
    }

2223 2224
    if (virDomainLiveConfigHelperMethod(cfg->caps, driver->xmlopt, vm,
                                        &flags, &targetDef) < 0)
2225
        goto endjob;
2226

2227
    if (flags & VIR_DOMAIN_AFFECT_LIVE)
2228 2229 2230 2231 2232
        targetDef = vm->def;

    /* Make sure coverity knows targetDef is valid at this point. */
    sa_assert(targetDef);

2233 2234
    pcpumap = virBitmapNewData(cpumap, maplen);
    if (!pcpumap)
2235
        goto endjob;
2236

2237 2238
    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
        libxl_bitmap map = { .size = maplen, .map = cpumap };
J
Jim Fehlig 已提交
2239
        if (libxl_set_vcpuaffinity(cfg->ctx, vm->def->id, vcpu, &map) != 0) {
2240 2241 2242
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Failed to pin vcpu '%d' with libxenlight"),
                           vcpu);
2243
            goto endjob;
2244
        }
2245
    }
2246

2247 2248
    /* full bitmap means reset the settings (if any). */
    if (virBitmapIsAllSet(pcpumap)) {
2249 2250 2251
        virDomainPinDel(&targetDef->cputune.vcpupin,
                        &targetDef->cputune.nvcpupin,
                        vcpu);
2252
        goto done;
2253 2254
    }

2255 2256
    if (!targetDef->cputune.vcpupin) {
        if (VIR_ALLOC(targetDef->cputune.vcpupin) < 0)
2257
            goto endjob;
2258
        targetDef->cputune.nvcpupin = 0;
H
Hu Tao 已提交
2259
    }
2260 2261 2262 2263 2264
    if (virDomainPinAdd(&targetDef->cputune.vcpupin,
                        &targetDef->cputune.nvcpupin,
                        cpumap,
                        maplen,
                        vcpu) < 0) {
2265 2266
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("failed to update or add vcpupin xml"));
2267
        goto endjob;
2268 2269
    }

2270
 done:
2271 2272
    ret = 0;

2273 2274 2275 2276 2277 2278
    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
        ret = virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm);
    } else if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
        ret = virDomainSaveConfig(cfg->configDir, targetDef);
    }

2279
 endjob:
2280 2281 2282
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

2283
 cleanup:
2284
    if (vm)
2285
        virObjectUnlock(vm);
2286
    virBitmapFree(pcpumap);
2287
    virObjectUnref(cfg);
2288 2289 2290
    return ret;
}

2291 2292 2293 2294 2295 2296 2297 2298
static int
libxlDomainPinVcpu(virDomainPtr dom, unsigned int vcpu, unsigned char *cpumap,
                   int maplen)
{
    return libxlDomainPinVcpuFlags(dom, vcpu, cpumap, maplen,
                                   VIR_DOMAIN_AFFECT_LIVE);
}

2299 2300 2301 2302 2303 2304 2305 2306 2307
static int
libxlDomainGetVcpuPinInfo(virDomainPtr dom, int ncpumaps,
                          unsigned char *cpumaps, int maplen,
                          unsigned int flags)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
    virDomainObjPtr vm = NULL;
    virDomainDefPtr targetDef = NULL;
2308
    virDomainPinDefPtr *vcpupin_list;
2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325
    virBitmapPtr cpumask = NULL;
    int maxcpu, hostcpus, vcpu, pcpu, n, ret = -1;
    unsigned char *cpumap;

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

    if (!(vm = libxlDomObjFromDomain(dom)))
        goto cleanup;

    if (virDomainGetVcpuPinInfoEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

    if (virDomainLiveConfigHelperMethod(cfg->caps, driver->xmlopt, vm,
                                        &flags, &targetDef) < 0)
        goto cleanup;

2326
    if (flags & VIR_DOMAIN_AFFECT_LIVE)
2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348 2349 2350 2351 2352 2353 2354
        targetDef = vm->def;

    /* Make sure coverity knows targetDef is valid at this point. */
    sa_assert(targetDef);

    /* Clamp to actual number of vcpus */
    if (ncpumaps > targetDef->vcpus)
        ncpumaps = targetDef->vcpus;

    if ((hostcpus = libxl_get_max_cpus(cfg->ctx)) < 0)
        goto cleanup;

    maxcpu = maplen * 8;
    if (maxcpu > hostcpus)
        maxcpu = hostcpus;

    /* initialize cpumaps */
    memset(cpumaps, 0xff, maplen * ncpumaps);
    if (maxcpu % 8) {
        for (vcpu = 0; vcpu < ncpumaps; vcpu++) {
            cpumap = VIR_GET_CPUMAP(cpumaps, maplen, vcpu);
            cpumap[maplen - 1] &= (1 << maxcpu % 8) - 1;
        }
    }

    /* if vcpupin setting exists, there may be unused pcpus */
    for (n = 0; n < targetDef->cputune.nvcpupin; n++) {
        vcpupin_list = targetDef->cputune.vcpupin;
2355
        vcpu = vcpupin_list[n]->id;
2356 2357 2358
        cpumask = vcpupin_list[n]->cpumask;
        cpumap = VIR_GET_CPUMAP(cpumaps, maplen, vcpu);
        for (pcpu = 0; pcpu < maxcpu; pcpu++) {
J
Ján Tomko 已提交
2359
            if (!virBitmapIsBitSet(cpumask, pcpu))
2360 2361 2362 2363 2364
                VIR_UNUSE_CPU(cpumap, pcpu);
        }
    }
    ret = ncpumaps;

2365
 cleanup:
2366 2367 2368 2369 2370
    if (vm)
        virObjectUnlock(vm);
    virObjectUnref(cfg);
    return ret;
}
2371 2372 2373 2374 2375

static int
libxlDomainGetVcpus(virDomainPtr dom, virVcpuInfoPtr info, int maxinfo,
                    unsigned char *cpumaps, int maplen)
{
J
Jim Fehlig 已提交
2376 2377
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
2378 2379 2380 2381
    virDomainObjPtr vm;
    int ret = -1;
    libxl_vcpuinfo *vcpuinfo;
    int maxcpu, hostcpus;
2382
    size_t i;
2383 2384
    unsigned char *cpumap;

J
Jim Fehlig 已提交
2385
    if (!(vm = libxlDomObjFromDomain(dom)))
2386 2387
        goto cleanup;

2388 2389 2390
    if (virDomainGetVcpusEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

2391
    if (!virDomainObjIsActive(vm)) {
2392
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
2393 2394 2395
        goto cleanup;
    }

J
Jim Fehlig 已提交
2396
    if ((vcpuinfo = libxl_list_vcpu(cfg->ctx, vm->def->id, &maxcpu,
2397
                                    &hostcpus)) == NULL) {
2398 2399
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to list vcpus for domain '%d' with libxenlight"),
2400
                       vm->def->id);
2401 2402 2403 2404 2405 2406 2407 2408 2409 2410 2411 2412 2413 2414 2415 2416 2417 2418 2419 2420 2421 2422
        goto cleanup;
    }

    if (cpumaps && maplen > 0)
        memset(cpumaps, 0, maplen * maxinfo);
    for (i = 0; i < maxcpu && i < maxinfo; ++i) {
        info[i].number = vcpuinfo[i].vcpuid;
        info[i].cpu = vcpuinfo[i].cpu;
        info[i].cpuTime = vcpuinfo[i].vcpu_time;
        if (vcpuinfo[i].running)
            info[i].state = VIR_VCPU_RUNNING;
        else if (vcpuinfo[i].blocked)
            info[i].state = VIR_VCPU_BLOCKED;
        else
            info[i].state = VIR_VCPU_OFFLINE;

        if (cpumaps && maplen > 0) {
            cpumap = VIR_GET_CPUMAP(cpumaps, maplen, i);
            memcpy(cpumap, vcpuinfo[i].cpumap.map,
                   MIN(maplen, vcpuinfo[i].cpumap.size));
        }

J
Jim Fehlig 已提交
2423
        libxl_vcpuinfo_dispose(&vcpuinfo[i]);
2424 2425 2426 2427 2428
    }
    VIR_FREE(vcpuinfo);

    ret = maxinfo;

2429
 cleanup:
2430
    if (vm)
2431
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
2432
    virObjectUnref(cfg);
2433 2434 2435
    return ret;
}

J
Jim Fehlig 已提交
2436
static char *
2437
libxlDomainGetXMLDesc(virDomainPtr dom, unsigned int flags)
J
Jim Fehlig 已提交
2438 2439 2440 2441
{
    virDomainObjPtr vm;
    char *ret = NULL;

2442 2443
    /* Flags checked by virDomainDefFormat */

J
Jim Fehlig 已提交
2444
    if (!(vm = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
2445 2446
        goto cleanup;

2447 2448 2449
    if (virDomainGetXMLDescEnsureACL(dom->conn, vm->def, flags) < 0)
        goto cleanup;

2450 2451
    ret = virDomainDefFormat(vm->def,
                              virDomainDefFormatConvertXMLFlags(flags));
J
Jim Fehlig 已提交
2452

2453
 cleanup:
J
Jim Fehlig 已提交
2454
    if (vm)
2455
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
2456 2457 2458
    return ret;
}

2459
static char *
2460 2461 2462
libxlConnectDomainXMLFromNative(virConnectPtr conn,
                                const char *nativeFormat,
                                const char *nativeConfig,
2463
                                unsigned int flags)
2464 2465
{
    libxlDriverPrivatePtr driver = conn->privateData;
2466
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
2467 2468 2469 2470
    virDomainDefPtr def = NULL;
    virConfPtr conf = NULL;
    char *xml = NULL;

E
Eric Blake 已提交
2471 2472
    virCheckFlags(0, NULL);

2473 2474 2475
    if (virConnectDomainXMLFromNativeEnsureACL(conn) < 0)
        goto cleanup;

2476 2477 2478 2479 2480
    if (STREQ(nativeFormat, LIBXL_CONFIG_FORMAT_XL)) {
        if (!(conf = virConfReadMem(nativeConfig, strlen(nativeConfig), 0)))
            goto cleanup;
        if (!(def = xenParseXL(conf,
                               cfg->caps,
2481
                               cfg->verInfo->xen_version_major)))
2482 2483
            goto cleanup;
    } else if (STREQ(nativeFormat, LIBXL_CONFIG_FORMAT_XM)) {
2484 2485 2486 2487 2488
        if (!(conf = virConfReadMem(nativeConfig, strlen(nativeConfig), 0)))
            goto cleanup;

        if (!(def = xenParseXM(conf,
                               cfg->verInfo->xen_version_major,
2489
                               cfg->caps)))
2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501
            goto cleanup;
    } else if (STREQ(nativeFormat, LIBXL_CONFIG_FORMAT_SEXPR)) {
        /* only support latest xend config format */
        if (!(def = xenParseSxprString(nativeConfig,
                                       XEND_CONFIG_VERSION_3_1_0,
                                       NULL,
                                       -1))) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("parsing sxpr config failed"));
            goto cleanup;
        }
    } else {
2502 2503
        virReportError(VIR_ERR_INVALID_ARG,
                       _("unsupported config type %s"), nativeFormat);
2504 2505 2506
        goto cleanup;
    }

2507
    xml = virDomainDefFormat(def, VIR_DOMAIN_DEF_FORMAT_INACTIVE);
2508

2509
 cleanup:
2510 2511 2512
    virDomainDefFree(def);
    if (conf)
        virConfFree(conf);
2513
    virObjectUnref(cfg);
2514 2515 2516 2517 2518
    return xml;
}

#define MAX_CONFIG_SIZE (1024 * 65)
static char *
2519 2520 2521
libxlConnectDomainXMLToNative(virConnectPtr conn, const char * nativeFormat,
                              const char * domainXml,
                              unsigned int flags)
2522 2523
{
    libxlDriverPrivatePtr driver = conn->privateData;
2524
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
2525 2526 2527 2528 2529
    virDomainDefPtr def = NULL;
    virConfPtr conf = NULL;
    int len = MAX_CONFIG_SIZE;
    char *ret = NULL;

E
Eric Blake 已提交
2530 2531
    virCheckFlags(0, NULL);

2532 2533 2534
    if (virConnectDomainXMLToNativeEnsureACL(conn) < 0)
        goto cleanup;

2535
    if (!(def = virDomainDefParseString(domainXml,
2536
                                        cfg->caps, driver->xmlopt,
2537
                                        VIR_DOMAIN_DEF_PARSE_INACTIVE)))
2538 2539
        goto cleanup;

2540 2541 2542 2543 2544 2545 2546 2547 2548 2549
    if (STREQ(nativeFormat, LIBXL_CONFIG_FORMAT_XL)) {
        if (!(conf = xenFormatXL(def, conn, cfg->verInfo->xen_version_major)))
            goto cleanup;
    } else if (STREQ(nativeFormat, LIBXL_CONFIG_FORMAT_XM)) {
        if (!(conf = xenFormatXM(conn, def, cfg->verInfo->xen_version_major)))
            goto cleanup;
    } else {

        virReportError(VIR_ERR_INVALID_ARG,
                       _("unsupported config type %s"), nativeFormat);
2550
        goto cleanup;
2551
    }
2552

2553
    if (VIR_ALLOC_N(ret, len) < 0)
2554 2555 2556 2557 2558 2559 2560
        goto cleanup;

    if (virConfWriteMem(ret, &len, conf) < 0) {
        VIR_FREE(ret);
        goto cleanup;
    }

2561
 cleanup:
2562 2563 2564
    virDomainDefFree(def);
    if (conf)
        virConfFree(conf);
2565
    virObjectUnref(cfg);
2566 2567 2568
    return ret;
}

J
Jim Fehlig 已提交
2569
static int
2570 2571
libxlConnectListDefinedDomains(virConnectPtr conn,
                               char **const names, int nnames)
J
Jim Fehlig 已提交
2572 2573 2574 2575
{
    libxlDriverPrivatePtr driver = conn->privateData;
    int n;

2576 2577 2578
    if (virConnectListDefinedDomainsEnsureACL(conn) < 0)
        return -1;

2579 2580
    n = virDomainObjListGetInactiveNames(driver->domains, names, nnames,
                                         virConnectListDefinedDomainsCheckACL, conn);
J
Jim Fehlig 已提交
2581 2582 2583 2584
    return n;
}

static int
2585
libxlConnectNumOfDefinedDomains(virConnectPtr conn)
J
Jim Fehlig 已提交
2586 2587 2588 2589
{
    libxlDriverPrivatePtr driver = conn->privateData;
    int n;

2590 2591 2592
    if (virConnectNumOfDefinedDomainsEnsureACL(conn) < 0)
        return -1;

2593
    n = virDomainObjListNumOfDomains(driver->domains, false,
2594 2595
                                     virConnectNumOfDefinedDomainsCheckACL,
                                     conn);
J
Jim Fehlig 已提交
2596 2597 2598 2599 2600
    return n;
}

static int
libxlDomainCreateWithFlags(virDomainPtr dom,
E
Eric Blake 已提交
2601
                           unsigned int flags)
J
Jim Fehlig 已提交
2602 2603 2604 2605 2606 2607 2608
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_START_PAUSED, -1);

J
Jim Fehlig 已提交
2609
    if (!(vm = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
2610 2611
        goto cleanup;

2612 2613 2614
    if (virDomainCreateWithFlagsEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

2615 2616 2617
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

J
Jim Fehlig 已提交
2618
    if (virDomainObjIsActive(vm)) {
2619 2620
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("Domain is already running"));
2621
        goto endjob;
J
Jim Fehlig 已提交
2622 2623
    }

2624
    ret = libxlDomainStart(driver, vm, (flags & VIR_DOMAIN_START_PAUSED) != 0, -1);
2625
    if (ret < 0)
2626
        goto endjob;
2627
    dom->id = vm->def->id;
J
Jim Fehlig 已提交
2628

2629 2630 2631 2632
 endjob:
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

2633
 cleanup:
J
Jim Fehlig 已提交
2634
    if (vm)
2635
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
2636 2637 2638 2639 2640 2641 2642 2643 2644 2645
    return ret;
}

static int
libxlDomainCreate(virDomainPtr dom)
{
    return libxlDomainCreateWithFlags(dom, 0);
}

static virDomainPtr
2646
libxlDomainDefineXMLFlags(virConnectPtr conn, const char *xml, unsigned int flags)
J
Jim Fehlig 已提交
2647 2648
{
    libxlDriverPrivatePtr driver = conn->privateData;
2649
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
J
Jim Fehlig 已提交
2650 2651 2652
    virDomainDefPtr def = NULL;
    virDomainObjPtr vm = NULL;
    virDomainPtr dom = NULL;
2653
    virObjectEventPtr event = NULL;
2654
    virDomainDefPtr oldDef = NULL;
2655
    unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;
J
Jim Fehlig 已提交
2656

2657 2658 2659 2660
    virCheckFlags(VIR_DOMAIN_DEFINE_VALIDATE, NULL);

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

2662
    if (!(def = virDomainDefParseString(xml, cfg->caps, driver->xmlopt,
2663
                                        parse_flags)))
2664
        goto cleanup;
J
Jim Fehlig 已提交
2665

2666
    if (virDomainDefineXMLFlagsEnsureACL(conn, def) < 0)
2667
        goto cleanup;
2668

2669
    if (!(vm = virDomainObjListAdd(driver->domains, def,
2670
                                   driver->xmlopt,
2671 2672
                                   0,
                                   &oldDef)))
2673
        goto cleanup;
2674

J
Jim Fehlig 已提交
2675 2676 2677
    def = NULL;
    vm->persistent = 1;

2678
    if (virDomainSaveConfig(cfg->configDir,
J
Jim Fehlig 已提交
2679
                            vm->newDef ? vm->newDef : vm->def) < 0) {
2680
        virDomainObjListRemove(driver->domains, vm);
J
Jim Fehlig 已提交
2681 2682 2683 2684 2685 2686 2687 2688
        vm = NULL;
        goto cleanup;
    }

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

2689
    event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_DEFINED,
2690
                                     !oldDef ?
2691 2692 2693
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED :
                                     VIR_DOMAIN_EVENT_DEFINED_UPDATED);

2694
 cleanup:
J
Jim Fehlig 已提交
2695
    virDomainDefFree(def);
2696
    virDomainDefFree(oldDef);
J
Jim Fehlig 已提交
2697
    if (vm)
2698
        virObjectUnlock(vm);
2699 2700
    if (event)
        libxlDomainEventQueue(driver, event);
2701
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
2702 2703 2704
    return dom;
}

2705 2706 2707 2708 2709 2710
static virDomainPtr
libxlDomainDefineXML(virConnectPtr conn, const char *xml)
{
    return libxlDomainDefineXMLFlags(conn, xml, 0);
}

J
Jim Fehlig 已提交
2711
static int
2712 2713
libxlDomainUndefineFlags(virDomainPtr dom,
                         unsigned int flags)
J
Jim Fehlig 已提交
2714 2715
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
2716
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
J
Jim Fehlig 已提交
2717
    virDomainObjPtr vm;
2718
    virObjectEventPtr event = NULL;
2719
    char *name = NULL;
J
Jim Fehlig 已提交
2720 2721
    int ret = -1;

2722 2723
    virCheckFlags(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE, -1);

J
Jim Fehlig 已提交
2724
    if (!(vm = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
2725 2726
        goto cleanup;

2727 2728 2729
    if (virDomainUndefineFlagsEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

J
Jim Fehlig 已提交
2730
    if (!vm->persistent) {
2731 2732
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("cannot undefine transient domain"));
J
Jim Fehlig 已提交
2733 2734 2735
        goto cleanup;
    }

2736 2737 2738 2739 2740 2741 2742
    name = libxlDomainManagedSavePath(driver, vm);
    if (name == NULL)
        goto cleanup;

    if (virFileExists(name)) {
        if (flags & VIR_DOMAIN_UNDEFINE_MANAGED_SAVE) {
            if (unlink(name) < 0) {
2743 2744
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("Failed to remove domain managed save image"));
2745 2746 2747
                goto cleanup;
            }
        } else {
2748 2749 2750
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                           _("Refusing to undefine while domain managed "
                             "save image exists"));
2751 2752 2753 2754
            goto cleanup;
        }
    }

2755
    if (virDomainDeleteConfig(cfg->configDir, cfg->autostartDir, vm) < 0)
J
Jim Fehlig 已提交
2756 2757
        goto cleanup;

2758
    event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_UNDEFINED,
2759 2760
                                     VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);

2761 2762 2763
    if (virDomainObjIsActive(vm)) {
        vm->persistent = 0;
    } else {
2764
        virDomainObjListRemove(driver->domains, vm);
2765 2766 2767
        vm = NULL;
    }

J
Jim Fehlig 已提交
2768 2769
    ret = 0;

2770
 cleanup:
2771
    VIR_FREE(name);
J
Jim Fehlig 已提交
2772
    if (vm)
2773
        virObjectUnlock(vm);
2774 2775
    if (event)
        libxlDomainEventQueue(driver, event);
2776
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
2777 2778 2779
    return ret;
}

2780 2781 2782 2783 2784 2785
static int
libxlDomainUndefine(virDomainPtr dom)
{
    return libxlDomainUndefineFlags(dom, 0);
}

2786
static int
J
Jim Fehlig 已提交
2787
libxlDomainChangeEjectableMedia(virDomainObjPtr vm, virDomainDiskDefPtr disk)
2788
{
J
Jim Fehlig 已提交
2789
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(libxl_driver);
2790 2791
    virDomainDiskDefPtr origdisk = NULL;
    libxl_device_disk x_disk;
2792
    size_t i;
2793 2794
    int ret = -1;

2795
    for (i = 0; i < vm->def->ndisks; i++) {
2796 2797 2798 2799 2800 2801 2802 2803
        if (vm->def->disks[i]->bus == disk->bus &&
            STREQ(vm->def->disks[i]->dst, disk->dst)) {
            origdisk = vm->def->disks[i];
            break;
        }
    }

    if (!origdisk) {
2804 2805 2806
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("No device with bus '%s' and target '%s'"),
                       virDomainDiskBusTypeToString(disk->bus), disk->dst);
2807 2808 2809 2810
        goto cleanup;
    }

    if (origdisk->device != VIR_DOMAIN_DISK_DEVICE_CDROM) {
2811 2812 2813
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Removable media not supported for %s device"),
                       virDomainDiskDeviceTypeToString(disk->device));
2814 2815 2816
        return -1;
    }

J
Jim Fehlig 已提交
2817
    if (libxlMakeDisk(disk, &x_disk) < 0)
2818 2819
        goto cleanup;

J
Jim Fehlig 已提交
2820
    if ((ret = libxl_cdrom_insert(cfg->ctx, vm->def->id, &x_disk, NULL)) < 0) {
2821 2822 2823
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("libxenlight failed to change media for disk '%s'"),
                       disk->dst);
2824 2825 2826
        goto cleanup;
    }

2827 2828 2829
    if (virDomainDiskSetSource(origdisk, virDomainDiskGetSource(disk)) < 0)
        goto cleanup;
    virDomainDiskSetType(origdisk, virDomainDiskGetType(disk));
2830 2831 2832 2833 2834

    virDomainDiskDefFree(disk);

    ret = 0;

2835
 cleanup:
J
Jim Fehlig 已提交
2836
    virObjectUnref(cfg);
2837 2838 2839 2840
    return ret;
}

static int
J
Jim Fehlig 已提交
2841
libxlDomainAttachDeviceDiskLive(virDomainObjPtr vm, virDomainDeviceDefPtr dev)
2842
{
J
Jim Fehlig 已提交
2843
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(libxl_driver);
2844 2845 2846 2847 2848 2849
    virDomainDiskDefPtr l_disk = dev->data.disk;
    libxl_device_disk x_disk;
    int ret = -1;

    switch (l_disk->device)  {
        case VIR_DOMAIN_DISK_DEVICE_CDROM:
J
Jim Fehlig 已提交
2850
            ret = libxlDomainChangeEjectableMedia(vm, l_disk);
2851 2852 2853
            break;
        case VIR_DOMAIN_DISK_DEVICE_DISK:
            if (l_disk->bus == VIR_DOMAIN_DISK_BUS_XEN) {
2854
                if (virDomainDiskIndexByName(vm->def, l_disk->dst, true) >= 0) {
2855 2856
                    virReportError(VIR_ERR_OPERATION_FAILED,
                                   _("target %s already exists"), l_disk->dst);
2857 2858 2859
                    goto cleanup;
                }

2860
                if (!virDomainDiskGetSource(l_disk)) {
2861 2862
                    virReportError(VIR_ERR_INTERNAL_ERROR,
                                   "%s", _("disk source path is missing"));
2863 2864 2865
                    goto cleanup;
                }

2866
                if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks+1) < 0)
2867 2868
                    goto cleanup;

J
Jim Fehlig 已提交
2869
                if (libxlMakeDisk(l_disk, &x_disk) < 0)
2870 2871
                    goto cleanup;

2872 2873 2874 2875 2876
                if (virDomainLockDiskAttach(libxl_driver->lockManager,
                                            "xen:///system",
                                            vm, l_disk) < 0)
                    goto cleanup;

J
Jim Fehlig 已提交
2877
                if ((ret = libxl_device_disk_add(cfg->ctx, vm->def->id,
J
Jim Fehlig 已提交
2878
                                                &x_disk, NULL)) < 0) {
2879 2880 2881
                    virReportError(VIR_ERR_INTERNAL_ERROR,
                                   _("libxenlight failed to attach disk '%s'"),
                                   l_disk->dst);
2882 2883 2884 2885 2886
                    if (virDomainLockDiskDetach(libxl_driver->lockManager,
                                                vm, l_disk) < 0) {
                        VIR_WARN("Unable to release lock on %s",
                                 virDomainDiskGetSource(l_disk));
                    }
2887 2888 2889 2890 2891 2892
                    goto cleanup;
                }

                virDomainDiskInsertPreAlloced(vm->def, l_disk);

            } else {
2893 2894 2895
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("disk bus '%s' cannot be hotplugged."),
                               virDomainDiskBusTypeToString(l_disk->bus));
2896 2897 2898
            }
            break;
        default:
2899 2900 2901
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("disk device type '%s' cannot be hotplugged"),
                           virDomainDiskDeviceTypeToString(l_disk->device));
2902 2903 2904
            break;
    }

2905
 cleanup:
J
Jim Fehlig 已提交
2906
    virObjectUnref(cfg);
2907 2908 2909
    return ret;
}

2910 2911 2912 2913 2914
static int
libxlDomainAttachHostPCIDevice(libxlDriverPrivatePtr driver,
                               virDomainObjPtr vm,
                               virDomainHostdevDefPtr hostdev)
{
J
Jim Fehlig 已提交
2915
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
2916
    libxl_device_pci pcidev;
2917 2918
    virDomainHostdevDefPtr found;
    virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
2919
    virDomainHostdevSubsysPCIPtr pcisrc = &hostdev->source.subsys.u.pci;
J
Jim Fehlig 已提交
2920
    int ret = -1;
2921

2922 2923
    libxl_device_pci_init(&pcidev);

2924 2925 2926
    if (virDomainHostdevFind(vm->def, hostdev, &found) >= 0) {
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("target pci device %.4x:%.2x:%.2x.%.1x already exists"),
2927 2928
                       pcisrc->addr.domain, pcisrc->addr.bus,
                       pcisrc->addr.slot, pcisrc->addr.function);
J
Jim Fehlig 已提交
2929
        goto cleanup;
2930 2931 2932
    }

    if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs + 1) < 0)
J
Jim Fehlig 已提交
2933
        goto cleanup;
2934 2935 2936 2937

    if (virHostdevPreparePCIDevices(hostdev_mgr, LIBXL_DRIVER_NAME,
                                    vm->def->name, vm->def->uuid,
                                    &hostdev, 1, 0) < 0)
J
Jim Fehlig 已提交
2938
        goto cleanup;
2939

2940
    if (libxlMakePCI(hostdev, &pcidev) < 0)
C
Chunyan Liu 已提交
2941
        goto error;
2942

J
Jim Fehlig 已提交
2943
    if (libxl_device_pci_add(cfg->ctx, vm->def->id, &pcidev, 0) < 0) {
2944 2945
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("libxenlight failed to attach pci device %.4x:%.2x:%.2x.%.1x"),
2946 2947
                       pcisrc->addr.domain, pcisrc->addr.bus,
                       pcisrc->addr.slot, pcisrc->addr.function);
C
Chunyan Liu 已提交
2948
        goto error;
2949 2950 2951
    }

    vm->def->hostdevs[vm->def->nhostdevs++] = hostdev;
J
Jim Fehlig 已提交
2952 2953
    ret = 0;
    goto cleanup;
2954

2955
 error:
2956 2957
    virHostdevReAttachPCIDevices(hostdev_mgr, LIBXL_DRIVER_NAME,
                                 vm->def->name, &hostdev, 1, NULL);
J
Jim Fehlig 已提交
2958 2959 2960

 cleanup:
    virObjectUnref(cfg);
2961
    libxl_device_pci_dispose(&pcidev);
J
Jim Fehlig 已提交
2962
    return ret;
2963 2964 2965 2966 2967
}

static int
libxlDomainAttachHostDevice(libxlDriverPrivatePtr driver,
                            virDomainObjPtr vm,
2968
                            virDomainHostdevDefPtr hostdev)
2969 2970 2971 2972 2973 2974 2975 2976 2977 2978
{
    if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("hostdev mode '%s' not supported"),
                       virDomainHostdevModeTypeToString(hostdev->mode));
        return -1;
    }

    switch (hostdev->source.subsys.type) {
    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
J
Jim Fehlig 已提交
2979
        if (libxlDomainAttachHostPCIDevice(driver, vm, hostdev) < 0)
C
Chunyan Liu 已提交
2980
            return -1;
2981 2982 2983 2984 2985 2986
        break;

    default:
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("hostdev subsys type '%s' not supported"),
                       virDomainHostdevSubsysTypeToString(hostdev->source.subsys.type));
C
Chunyan Liu 已提交
2987
        return -1;
2988 2989 2990 2991 2992
    }

    return 0;
}

2993
static int
J
Jim Fehlig 已提交
2994
libxlDomainDetachDeviceDiskLive(virDomainObjPtr vm, virDomainDeviceDefPtr dev)
2995
{
J
Jim Fehlig 已提交
2996
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(libxl_driver);
2997 2998
    virDomainDiskDefPtr l_disk = NULL;
    libxl_device_disk x_disk;
2999
    int idx;
3000 3001 3002 3003 3004 3005
    int ret = -1;

    switch (dev->data.disk->device)  {
        case VIR_DOMAIN_DISK_DEVICE_DISK:
            if (dev->data.disk->bus == VIR_DOMAIN_DISK_BUS_XEN) {

3006 3007 3008
                if ((idx = virDomainDiskIndexByName(vm->def,
                                                    dev->data.disk->dst,
                                                    false)) < 0) {
3009 3010
                    virReportError(VIR_ERR_OPERATION_FAILED,
                                   _("disk %s not found"), dev->data.disk->dst);
3011 3012 3013
                    goto cleanup;
                }

3014
                l_disk = vm->def->disks[idx];
3015

J
Jim Fehlig 已提交
3016
                if (libxlMakeDisk(l_disk, &x_disk) < 0)
3017 3018
                    goto cleanup;

J
Jim Fehlig 已提交
3019
                if ((ret = libxl_device_disk_remove(cfg->ctx, vm->def->id,
J
Jim Fehlig 已提交
3020
                                                    &x_disk, NULL)) < 0) {
3021 3022 3023
                    virReportError(VIR_ERR_INTERNAL_ERROR,
                                   _("libxenlight failed to detach disk '%s'"),
                                   l_disk->dst);
3024 3025 3026
                    goto cleanup;
                }

3027 3028 3029 3030 3031
                if (virDomainLockDiskDetach(libxl_driver->lockManager,
                                            vm, l_disk) < 0)
                    VIR_WARN("Unable to release lock on %s",
                             virDomainDiskGetSource(l_disk));

3032
                virDomainDiskRemove(vm->def, idx);
3033 3034 3035
                virDomainDiskDefFree(l_disk);

            } else {
3036 3037 3038
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("disk bus '%s' cannot be hot unplugged."),
                               virDomainDiskBusTypeToString(dev->data.disk->bus));
3039 3040 3041
            }
            break;
        default:
3042 3043 3044
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("device type '%s' cannot hot unplugged"),
                           virDomainDiskDeviceTypeToString(dev->data.disk->device));
3045 3046 3047
            break;
    }

3048
 cleanup:
J
Jim Fehlig 已提交
3049
    virObjectUnref(cfg);
3050 3051 3052
    return ret;
}

3053 3054 3055 3056 3057
static int
libxlDomainAttachNetDevice(libxlDriverPrivatePtr driver,
                           virDomainObjPtr vm,
                           virDomainNetDefPtr net)
{
J
Jim Fehlig 已提交
3058
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
3059 3060 3061
    int actualType;
    libxl_device_nic nic;
    int ret = -1;
3062
    char mac[VIR_MAC_STRING_BUFLEN];
3063 3064 3065

    /* preallocate new slot for device */
    if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets + 1) < 0)
J
Jim Fehlig 已提交
3066
        goto out;
3067 3068 3069 3070 3071 3072

    /* If appropriate, grab a physical device from the configured
     * network's pool of devices, or resolve bridge device name
     * to the one defined in the network definition.
     */
    if (networkAllocateActualDevice(vm->def, net) < 0)
J
Jim Fehlig 已提交
3073
        goto out;
3074 3075 3076

    actualType = virDomainNetGetActualType(net);

3077 3078 3079 3080 3081 3082 3083
    if (virDomainHasNet(vm->def, net)) {
        virReportError(VIR_ERR_INVALID_ARG,
                       _("network device with mac %s already exists"),
                       virMacAddrFormat(&net->mac, mac));
        return -1;
    }

3084 3085 3086 3087 3088 3089
    if (actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
        /* This is really a "smart hostdev", so it should be attached
         * as a hostdev (the hostdev code will reach over into the
         * netdev-specific code as appropriate), then also added to
         * the nets list (see out:) if successful.
         */
J
Jim Fehlig 已提交
3090
        ret = libxlDomainAttachHostDevice(driver, vm,
3091 3092 3093 3094 3095 3096 3097 3098
                                          virDomainNetGetActualHostdev(net));
        goto out;
    }

    libxl_device_nic_init(&nic);
    if (libxlMakeNic(vm->def, net, &nic) < 0)
        goto cleanup;

J
Jim Fehlig 已提交
3099
    if (libxl_device_nic_add(cfg->ctx, vm->def->id, &nic, 0)) {
3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("libxenlight failed to attach network device"));
        goto cleanup;
    }

    ret = 0;

 cleanup:
    libxl_device_nic_dispose(&nic);
 out:
    if (!ret)
        vm->def->nets[vm->def->nnets++] = net;
J
Jim Fehlig 已提交
3112
    virObjectUnref(cfg);
3113 3114 3115
    return ret;
}

3116
static int
3117 3118
libxlDomainAttachDeviceLive(libxlDriverPrivatePtr driver,
                            virDomainObjPtr vm,
3119 3120 3121 3122 3123 3124
                            virDomainDeviceDefPtr dev)
{
    int ret = -1;

    switch (dev->type) {
        case VIR_DOMAIN_DEVICE_DISK:
J
Jim Fehlig 已提交
3125
            ret = libxlDomainAttachDeviceDiskLive(vm, dev);
3126 3127 3128 3129
            if (!ret)
                dev->data.disk = NULL;
            break;

3130
        case VIR_DOMAIN_DEVICE_NET:
J
Jim Fehlig 已提交
3131
            ret = libxlDomainAttachNetDevice(driver, vm,
3132 3133 3134 3135 3136
                                             dev->data.net);
            if (!ret)
                dev->data.net = NULL;
            break;

3137
        case VIR_DOMAIN_DEVICE_HOSTDEV:
J
Jim Fehlig 已提交
3138
            ret = libxlDomainAttachHostDevice(driver, vm,
3139
                                              dev->data.hostdev);
3140 3141 3142 3143
            if (!ret)
                dev->data.hostdev = NULL;
            break;

3144
        default:
3145 3146 3147
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("device type '%s' cannot be attached"),
                           virDomainDeviceTypeToString(dev->type));
3148 3149 3150 3151 3152 3153 3154 3155 3156 3157
            break;
    }

    return ret;
}

static int
libxlDomainAttachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev)
{
    virDomainDiskDefPtr disk;
3158
    virDomainNetDefPtr net;
3159 3160
    virDomainHostdevDefPtr hostdev;
    virDomainHostdevDefPtr found;
3161
    virDomainHostdevSubsysPCIPtr pcisrc;
3162
    char mac[VIR_MAC_STRING_BUFLEN];
3163 3164 3165 3166

    switch (dev->type) {
        case VIR_DOMAIN_DEVICE_DISK:
            disk = dev->data.disk;
3167
            if (virDomainDiskIndexByName(vmdef, disk->dst, true) >= 0) {
3168 3169
                virReportError(VIR_ERR_INVALID_ARG,
                               _("target %s already exists."), disk->dst);
3170 3171
                return -1;
            }
3172
            if (virDomainDiskInsert(vmdef, disk))
3173 3174 3175 3176
                return -1;
            /* vmdef has the pointer. Generic codes for vmdef will do all jobs */
            dev->data.disk = NULL;
            break;
3177 3178 3179

        case VIR_DOMAIN_DEVICE_NET:
            net = dev->data.net;
3180 3181 3182 3183 3184 3185
            if (virDomainHasNet(vmdef, net)) {
                virReportError(VIR_ERR_INVALID_ARG,
                               _("network device with mac %s already exists"),
                               virMacAddrFormat(&net->mac, mac));
                return -1;
            }
3186 3187 3188 3189 3190
            if (virDomainNetInsert(vmdef, net))
                return -1;
            dev->data.net = NULL;
            break;

3191 3192 3193 3194 3195 3196 3197
        case VIR_DOMAIN_DEVICE_HOSTDEV:
            hostdev = dev->data.hostdev;

            if (hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
                return -1;

            if (virDomainHostdevFind(vmdef, hostdev, &found) >= 0) {
3198
                pcisrc = &hostdev->source.subsys.u.pci;
3199 3200 3201
                virReportError(VIR_ERR_OPERATION_FAILED,
                               _("target pci device %.4x:%.2x:%.2x.%.1x\
                                  already exists"),
3202 3203
                               pcisrc->addr.domain, pcisrc->addr.bus,
                               pcisrc->addr.slot, pcisrc->addr.function);
3204 3205 3206
                return -1;
            }

3207 3208
            if (virDomainHostdevInsert(vmdef, hostdev) < 0)
                return -1;
3209
            break;
3210 3211

        default:
3212 3213
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("persistent attach of device is not supported"));
3214 3215 3216 3217 3218 3219
            return -1;
    }
    return 0;
}

static int
3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252
libxlComparePCIDevice(virDomainDefPtr def ATTRIBUTE_UNUSED,
                      virDomainDeviceDefPtr device ATTRIBUTE_UNUSED,
                      virDomainDeviceInfoPtr info1,
                      void *opaque)
{
    virDomainDeviceInfoPtr info2 = opaque;

    if (info1->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI ||
        info2->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI)
        return 0;

    if (info1->addr.pci.domain == info2->addr.pci.domain &&
        info1->addr.pci.bus == info2->addr.pci.bus &&
        info1->addr.pci.slot == info2->addr.pci.slot &&
        info1->addr.pci.function != info2->addr.pci.function)
        return -1;
    return 0;
}

static bool
libxlIsMultiFunctionDevice(virDomainDefPtr def,
                           virDomainDeviceInfoPtr dev)
{
    if (virDomainDeviceInfoIterate(def, libxlComparePCIDevice, dev) < 0)
        return true;
    return false;
}

static int
libxlDomainDetachHostPCIDevice(libxlDriverPrivatePtr driver,
                               virDomainObjPtr vm,
                               virDomainHostdevDefPtr hostdev)
{
J
Jim Fehlig 已提交
3253
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
3254
    virDomainHostdevSubsysPtr subsys = &hostdev->source.subsys;
3255
    virDomainHostdevSubsysPCIPtr pcisrc = &subsys->u.pci;
3256 3257 3258 3259
    libxl_device_pci pcidev;
    virDomainHostdevDefPtr detach;
    int idx;
    virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
J
Jim Fehlig 已提交
3260
    int ret = -1;
3261

3262 3263
    libxl_device_pci_init(&pcidev);

3264 3265 3266 3267
    idx = virDomainHostdevFind(vm->def, hostdev, &detach);
    if (idx < 0) {
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("host pci device %.4x:%.2x:%.2x.%.1x not found"),
3268 3269
                       pcisrc->addr.domain, pcisrc->addr.bus,
                       pcisrc->addr.slot, pcisrc->addr.function);
J
Jim Fehlig 已提交
3270
        goto cleanup;
3271 3272 3273 3274 3275
    }

    if (libxlIsMultiFunctionDevice(vm->def, detach->info)) {
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("cannot hot unplug multifunction PCI device: %.4x:%.2x:%.2x.%.1x"),
3276 3277
                       pcisrc->addr.domain, pcisrc->addr.bus,
                       pcisrc->addr.slot, pcisrc->addr.function);
C
Chunyan Liu 已提交
3278
        goto error;
3279 3280 3281
    }


3282
    if (libxlMakePCI(detach, &pcidev) < 0)
C
Chunyan Liu 已提交
3283
        goto error;
3284

J
Jim Fehlig 已提交
3285
    if (libxl_device_pci_remove(cfg->ctx, vm->def->id, &pcidev, 0) < 0) {
3286 3287 3288
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("libxenlight failed to detach pci device\
                          %.4x:%.2x:%.2x.%.1x"),
3289 3290
                       pcisrc->addr.domain, pcisrc->addr.bus,
                       pcisrc->addr.slot, pcisrc->addr.function);
C
Chunyan Liu 已提交
3291
        goto error;
3292 3293 3294 3295 3296 3297 3298 3299
    }


    virDomainHostdevRemove(vm->def, idx);

    virHostdevReAttachPCIDevices(hostdev_mgr, LIBXL_DRIVER_NAME,
                                 vm->def->name, &hostdev, 1, NULL);

J
Jim Fehlig 已提交
3300
    ret = 0;
3301

3302
 error:
3303
    virDomainHostdevDefFree(detach);
J
Jim Fehlig 已提交
3304 3305 3306

 cleanup:
    virObjectUnref(cfg);
3307
    libxl_device_pci_dispose(&pcidev);
J
Jim Fehlig 已提交
3308
    return ret;
3309 3310 3311 3312 3313
}

static int
libxlDomainDetachHostDevice(libxlDriverPrivatePtr driver,
                            virDomainObjPtr vm,
3314
                            virDomainHostdevDefPtr hostdev)
3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326
{
    virDomainHostdevSubsysPtr subsys = &hostdev->source.subsys;

    if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("hostdev mode '%s' not supported"),
                       virDomainHostdevModeTypeToString(hostdev->mode));
        return -1;
    }

    switch (subsys->type) {
        case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
J
Jim Fehlig 已提交
3327
            return libxlDomainDetachHostPCIDevice(driver, vm, hostdev);
3328 3329 3330 3331 3332 3333 3334 3335 3336 3337

        default:
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("unexpected hostdev type %d"), subsys->type);
            break;
    }

    return -1;
}

3338 3339 3340 3341 3342
static int
libxlDomainDetachNetDevice(libxlDriverPrivatePtr driver,
                           virDomainObjPtr vm,
                           virDomainNetDefPtr net)
{
J
Jim Fehlig 已提交
3343
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
3344 3345 3346 3347 3348 3349 3350
    int detachidx;
    virDomainNetDefPtr detach = NULL;
    libxl_device_nic nic;
    char mac[VIR_MAC_STRING_BUFLEN];
    int ret = -1;

    if ((detachidx = virDomainNetFindIdx(vm->def, net)) < 0)
J
Jim Fehlig 已提交
3351
        goto out;
3352 3353 3354 3355 3356 3357 3358

    detach = vm->def->nets[detachidx];

    if (virDomainNetGetActualType(detach) == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
        /* This is really a "smart hostdev", so it should be attached as a
         * hostdev, then also removed from nets list (see out:) if successful.
         */
J
Jim Fehlig 已提交
3359
        ret = libxlDomainDetachHostDevice(driver, vm,
3360 3361 3362 3363 3364
                                          virDomainNetGetActualHostdev(detach));
        goto out;
    }

    libxl_device_nic_init(&nic);
J
Jim Fehlig 已提交
3365
    if (libxl_mac_to_device_nic(cfg->ctx, vm->def->id,
3366 3367 3368
                                virMacAddrFormat(&detach->mac, mac), &nic))
        goto cleanup;

J
Jim Fehlig 已提交
3369
    if (libxl_device_nic_remove(cfg->ctx, vm->def->id, &nic, 0)) {
3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("libxenlight failed to detach network device"));
        goto cleanup;
    }

    ret = 0;

 cleanup:
    libxl_device_nic_dispose(&nic);
 out:
    if (!ret)
        virDomainNetRemove(vm->def, detachidx);
J
Jim Fehlig 已提交
3382
    virObjectUnref(cfg);
3383 3384 3385
    return ret;
}

3386 3387 3388
static int
libxlDomainDetachDeviceLive(libxlDriverPrivatePtr driver,
                            virDomainObjPtr vm,
3389 3390 3391 3392 3393 3394
                            virDomainDeviceDefPtr dev)
{
    int ret = -1;

    switch (dev->type) {
        case VIR_DOMAIN_DEVICE_DISK:
J
Jim Fehlig 已提交
3395
            ret = libxlDomainDetachDeviceDiskLive(vm, dev);
3396 3397
            break;

3398
        case VIR_DOMAIN_DEVICE_NET:
J
Jim Fehlig 已提交
3399
            ret = libxlDomainDetachNetDevice(driver, vm,
3400 3401 3402
                                             dev->data.net);
            break;

3403
        case VIR_DOMAIN_DEVICE_HOSTDEV:
J
Jim Fehlig 已提交
3404
            ret = libxlDomainDetachHostDevice(driver, vm,
3405
                                              dev->data.hostdev);
3406 3407
            break;

3408
        default:
3409 3410 3411
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("device type '%s' cannot be detached"),
                           virDomainDeviceTypeToString(dev->type));
3412 3413 3414 3415 3416 3417
            break;
    }

    return ret;
}

3418

3419 3420 3421
static int
libxlDomainDetachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev)
{
3422
    virDomainDiskDefPtr disk, detach;
3423
    virDomainHostdevDefPtr hostdev, det_hostdev;
3424
    virDomainNetDefPtr net;
3425
    int idx;
3426 3427 3428 3429

    switch (dev->type) {
        case VIR_DOMAIN_DEVICE_DISK:
            disk = dev->data.disk;
3430
            if (!(detach = virDomainDiskRemoveByName(vmdef, disk->dst))) {
3431 3432
                virReportError(VIR_ERR_INVALID_ARG,
                               _("no target device %s"), disk->dst);
3433
                return -1;
3434
            }
3435
            virDomainDiskDefFree(detach);
3436
            break;
3437

3438 3439 3440 3441 3442 3443 3444 3445 3446
        case VIR_DOMAIN_DEVICE_NET:
            net = dev->data.net;
            if ((idx = virDomainNetFindIdx(vmdef, net)) < 0)
                return -1;

            /* this is guaranteed to succeed */
            virDomainNetDefFree(virDomainNetRemove(vmdef, idx));
            break;

3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458
        case VIR_DOMAIN_DEVICE_HOSTDEV: {
            hostdev = dev->data.hostdev;
            if ((idx = virDomainHostdevFind(vmdef, hostdev, &det_hostdev)) < 0) {
                virReportError(VIR_ERR_INVALID_ARG, "%s",
                               _("device not present in domain configuration"));
                return -1;
            }
            virDomainHostdevRemove(vmdef, idx);
            virDomainHostdevDefFree(det_hostdev);
            break;
        }

3459
        default:
3460 3461
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("persistent detach of device is not supported"));
3462
            return -1;
3463 3464
    }

3465
    return 0;
3466 3467 3468
}

static int
J
Jim Fehlig 已提交
3469
libxlDomainUpdateDeviceLive(virDomainObjPtr vm, virDomainDeviceDefPtr dev)
3470 3471 3472 3473 3474 3475 3476 3477 3478
{
    virDomainDiskDefPtr disk;
    int ret = -1;

    switch (dev->type) {
        case VIR_DOMAIN_DEVICE_DISK:
            disk = dev->data.disk;
            switch (disk->device) {
                case VIR_DOMAIN_DISK_DEVICE_CDROM:
J
Jim Fehlig 已提交
3479
                    ret = libxlDomainChangeEjectableMedia(vm, disk);
3480 3481 3482 3483
                    if (ret == 0)
                        dev->data.disk = NULL;
                    break;
                default:
3484 3485 3486
                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                                   _("disk bus '%s' cannot be updated."),
                                   virDomainDiskBusTypeToString(disk->bus));
3487 3488 3489 3490
                    break;
            }
            break;
        default:
3491 3492 3493
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("device type '%s' cannot be updated"),
                           virDomainDeviceTypeToString(dev->type));
3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504
            break;
    }

    return ret;
}

static int
libxlDomainUpdateDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev)
{
    virDomainDiskDefPtr orig;
    virDomainDiskDefPtr disk;
3505
    int idx;
3506 3507 3508 3509 3510
    int ret = -1;

    switch (dev->type) {
        case VIR_DOMAIN_DEVICE_DISK:
            disk = dev->data.disk;
3511
            if ((idx = virDomainDiskIndexByName(vmdef, disk->dst, false)) < 0) {
3512 3513
                virReportError(VIR_ERR_INVALID_ARG,
                               _("target %s doesn't exist."), disk->dst);
3514 3515
                goto cleanup;
            }
3516
            orig = vmdef->disks[idx];
3517
            if (!(orig->device == VIR_DOMAIN_DISK_DEVICE_CDROM)) {
3518 3519
                virReportError(VIR_ERR_INVALID_ARG, "%s",
                               _("this disk doesn't support update"));
3520 3521 3522
                goto cleanup;
            }

3523 3524 3525 3526 3527 3528
            if (virDomainDiskSetSource(orig, virDomainDiskGetSource(disk)) < 0)
                goto cleanup;
            virDomainDiskSetType(orig, virDomainDiskGetType(disk));
            virDomainDiskSetFormat(orig, virDomainDiskGetFormat(disk));
            if (virDomainDiskSetDriver(orig, virDomainDiskGetDriver(disk)) < 0)
                goto cleanup;
3529 3530
            break;
        default:
3531 3532
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("persistent update of device is not supported"));
3533 3534 3535 3536 3537
            goto cleanup;
    }

    ret = 0;

3538
 cleanup:
3539 3540 3541 3542 3543
    return ret;
}


static int
3544 3545
libxlDomainAttachDeviceFlags(virDomainPtr dom, const char *xml,
                             unsigned int flags)
3546 3547
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
3548
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
3549 3550 3551 3552 3553 3554 3555 3556
    virDomainObjPtr vm = NULL;
    virDomainDefPtr vmdef = NULL;
    virDomainDeviceDefPtr dev = NULL;
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_LIVE |
                  VIR_DOMAIN_DEVICE_MODIFY_CONFIG, -1);

J
Jim Fehlig 已提交
3557
    if (!(vm = libxlDomObjFromDomain(dom)))
3558 3559
        goto cleanup;

3560 3561 3562
    if (virDomainAttachDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
        goto cleanup;

3563 3564 3565
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

3566 3567 3568 3569 3570 3571 3572 3573
    if (virDomainObjIsActive(vm)) {
        if (flags == VIR_DOMAIN_DEVICE_MODIFY_CURRENT)
            flags |= VIR_DOMAIN_DEVICE_MODIFY_LIVE;
    } else {
        if (flags == VIR_DOMAIN_DEVICE_MODIFY_CURRENT)
            flags |= VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
        /* check consistency between flags and the vm state */
        if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) {
3574 3575
            virReportError(VIR_ERR_OPERATION_INVALID,
                           "%s", _("Domain is not running"));
3576
            goto endjob;
3577 3578 3579 3580
        }
    }

    if ((flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) && !vm->persistent) {
3581 3582
         virReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("cannot modify device on transient domain"));
3583
         goto endjob;
3584 3585 3586
    }

    if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
3587
        if (!(dev = virDomainDeviceDefParse(xml, vm->def,
3588
                                            cfg->caps, driver->xmlopt,
3589
                                            VIR_DOMAIN_DEF_PARSE_INACTIVE)))
3590
            goto endjob;
3591 3592

        /* Make a copy for updated domain. */
3593
        if (!(vmdef = virDomainObjCopyPersistentDef(vm, cfg->caps,
3594
                                                    driver->xmlopt)))
3595
            goto endjob;
3596

3597
        if (libxlDomainAttachDeviceConfig(vmdef, dev) < 0)
3598
            goto endjob;
3599
    }
3600 3601 3602 3603

    if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) {
        /* If dev exists it was created to modify the domain config. Free it. */
        virDomainDeviceDefFree(dev);
3604
        if (!(dev = virDomainDeviceDefParse(xml, vm->def,
3605
                                            cfg->caps, driver->xmlopt,
3606
                                            VIR_DOMAIN_DEF_PARSE_INACTIVE)))
3607
            goto endjob;
3608

J
Jim Fehlig 已提交
3609
        if (libxlDomainAttachDeviceLive(driver, vm, dev) < 0)
3610
            goto endjob;
3611

3612 3613 3614 3615
        /*
         * update domain status forcibly because the domain status may be
         * changed even if we attach the device failed.
         */
3616
        if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
3617
            goto endjob;
3618 3619
    }

3620 3621
    ret = 0;

3622
    /* Finally, if no error until here, we can save config. */
3623
    if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
3624
        ret = virDomainSaveConfig(cfg->configDir, vmdef);
3625
        if (!ret) {
3626
            virDomainObjAssignDef(vm, vmdef, false, NULL);
3627 3628 3629 3630
            vmdef = NULL;
        }
    }

3631
 endjob:
3632 3633 3634
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

3635
 cleanup:
3636 3637 3638
    virDomainDefFree(vmdef);
    virDomainDeviceDefFree(dev);
    if (vm)
3639
        virObjectUnlock(vm);
3640
    virObjectUnref(cfg);
3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654
    return ret;
}

static int
libxlDomainAttachDevice(virDomainPtr dom, const char *xml)
{
    return libxlDomainAttachDeviceFlags(dom, xml,
                                        VIR_DOMAIN_DEVICE_MODIFY_LIVE);
}

static int
libxlDomainDetachDeviceFlags(virDomainPtr dom, const char *xml,
                             unsigned int flags)
{
3655
    libxlDriverPrivatePtr driver = dom->conn->privateData;
3656
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
3657 3658 3659 3660 3661 3662 3663 3664
    virDomainObjPtr vm = NULL;
    virDomainDefPtr vmdef = NULL;
    virDomainDeviceDefPtr dev = NULL;
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_LIVE |
                  VIR_DOMAIN_DEVICE_MODIFY_CONFIG, -1);

J
Jim Fehlig 已提交
3665
    if (!(vm = libxlDomObjFromDomain(dom)))
3666 3667
        goto cleanup;

3668 3669 3670
    if (virDomainDetachDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
        goto cleanup;

3671 3672 3673
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

3674 3675 3676 3677 3678 3679 3680 3681 3682 3683
    if (virDomainObjIsActive(vm)) {
        if (flags == VIR_DOMAIN_DEVICE_MODIFY_CURRENT)
            flags |= VIR_DOMAIN_DEVICE_MODIFY_LIVE;
    } else {
        if (flags == VIR_DOMAIN_DEVICE_MODIFY_CURRENT)
            flags |= VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
        /* check consistency between flags and the vm state */
        if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) {
            virReportError(VIR_ERR_OPERATION_INVALID,
                           "%s", _("Domain is not running"));
3684
            goto endjob;
3685 3686 3687 3688 3689 3690
        }
    }

    if ((flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) && !vm->persistent) {
         virReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("cannot modify device on transient domain"));
3691
         goto endjob;
3692 3693 3694 3695
    }

    if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
        if (!(dev = virDomainDeviceDefParse(xml, vm->def,
3696
                                            cfg->caps, driver->xmlopt,
3697
                                            VIR_DOMAIN_DEF_PARSE_INACTIVE)))
3698
            goto endjob;
3699 3700

        /* Make a copy for updated domain. */
3701
        if (!(vmdef = virDomainObjCopyPersistentDef(vm, cfg->caps,
3702
                                                    driver->xmlopt)))
3703
            goto endjob;
3704

3705
        if (libxlDomainDetachDeviceConfig(vmdef, dev) < 0)
3706
            goto endjob;
3707 3708 3709 3710 3711 3712
    }

    if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) {
        /* If dev exists it was created to modify the domain config. Free it. */
        virDomainDeviceDefFree(dev);
        if (!(dev = virDomainDeviceDefParse(xml, vm->def,
3713
                                            cfg->caps, driver->xmlopt,
3714
                                            VIR_DOMAIN_DEF_PARSE_INACTIVE)))
3715
            goto endjob;
3716

J
Jim Fehlig 已提交
3717
        if (libxlDomainDetachDeviceLive(driver, vm, dev) < 0)
3718
            goto endjob;
3719 3720 3721 3722 3723

        /*
         * update domain status forcibly because the domain status may be
         * changed even if we attach the device failed.
         */
3724
        if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
3725
            goto endjob;
3726 3727
    }

3728 3729
    ret = 0;

3730
    /* Finally, if no error until here, we can save config. */
3731
    if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
3732
        ret = virDomainSaveConfig(cfg->configDir, vmdef);
3733 3734 3735 3736 3737 3738
        if (!ret) {
            virDomainObjAssignDef(vm, vmdef, false, NULL);
            vmdef = NULL;
        }
    }

3739
 endjob:
3740 3741 3742
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

3743
 cleanup:
3744 3745 3746 3747
    virDomainDefFree(vmdef);
    virDomainDeviceDefFree(dev);
    if (vm)
        virObjectUnlock(vm);
3748
    virObjectUnref(cfg);
3749
    return ret;
3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760 3761 3762
}

static int
libxlDomainDetachDevice(virDomainPtr dom, const char *xml)
{
    return libxlDomainDetachDeviceFlags(dom, xml,
                                        VIR_DOMAIN_DEVICE_MODIFY_LIVE);
}

static int
libxlDomainUpdateDeviceFlags(virDomainPtr dom, const char *xml,
                             unsigned int flags)
{
3763
    libxlDriverPrivatePtr driver = dom->conn->privateData;
3764
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
3765 3766 3767 3768 3769 3770 3771 3772
    virDomainObjPtr vm = NULL;
    virDomainDefPtr vmdef = NULL;
    virDomainDeviceDefPtr dev = NULL;
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_LIVE |
                  VIR_DOMAIN_DEVICE_MODIFY_CONFIG, -1);

J
Jim Fehlig 已提交
3773
    if (!(vm = libxlDomObjFromDomain(dom)))
3774 3775
        goto cleanup;

3776 3777 3778
    if (virDomainUpdateDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
        goto cleanup;

3779 3780 3781 3782 3783 3784 3785 3786 3787 3788 3789 3790 3791 3792 3793 3794 3795 3796 3797 3798 3799 3800
    if (virDomainObjIsActive(vm)) {
        if (flags == VIR_DOMAIN_DEVICE_MODIFY_CURRENT)
            flags |= VIR_DOMAIN_DEVICE_MODIFY_LIVE;
    } else {
        if (flags == VIR_DOMAIN_DEVICE_MODIFY_CURRENT)
            flags |= VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
        /* check consistency between flags and the vm state */
        if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) {
            virReportError(VIR_ERR_OPERATION_INVALID,
                           "%s", _("Domain is not running"));
            goto cleanup;
        }
    }

    if ((flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) && !vm->persistent) {
         virReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("cannot modify device on transient domain"));
         goto cleanup;
    }

    if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
        if (!(dev = virDomainDeviceDefParse(xml, vm->def,
3801
                                            cfg->caps, driver->xmlopt,
3802
                                            VIR_DOMAIN_DEF_PARSE_INACTIVE)))
3803 3804 3805
            goto cleanup;

        /* Make a copy for updated domain. */
3806
        if (!(vmdef = virDomainObjCopyPersistentDef(vm, cfg->caps,
3807 3808 3809 3810 3811 3812 3813 3814 3815 3816 3817 3818 3819
                                                    driver->xmlopt)))
            goto cleanup;

        if ((ret = libxlDomainUpdateDeviceConfig(vmdef, dev)) < 0)
            goto cleanup;
    } else {
        ret = 0;
    }

    if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) {
        /* If dev exists it was created to modify the domain config. Free it. */
        virDomainDeviceDefFree(dev);
        if (!(dev = virDomainDeviceDefParse(xml, vm->def,
3820
                                            cfg->caps, driver->xmlopt,
3821
                                            VIR_DOMAIN_DEF_PARSE_INACTIVE)))
3822 3823
            goto cleanup;

J
Jim Fehlig 已提交
3824
        if ((ret = libxlDomainUpdateDeviceLive(vm, dev)) < 0)
3825 3826 3827 3828 3829 3830
            goto cleanup;

        /*
         * update domain status forcibly because the domain status may be
         * changed even if we attach the device failed.
         */
3831
        if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
3832 3833 3834 3835 3836
            ret = -1;
    }

    /* Finally, if no error until here, we can save config. */
    if (!ret && (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG)) {
3837
        ret = virDomainSaveConfig(cfg->configDir, vmdef);
3838 3839 3840 3841 3842 3843
        if (!ret) {
            virDomainObjAssignDef(vm, vmdef, false, NULL);
            vmdef = NULL;
        }
    }

3844
 cleanup:
3845 3846 3847 3848
    virDomainDefFree(vmdef);
    virDomainDeviceDefFree(dev);
    if (vm)
        virObjectUnlock(vm);
3849
    virObjectUnref(cfg);
3850
    return ret;
3851 3852
}

3853 3854 3855 3856 3857
static unsigned long long
libxlNodeGetFreeMemory(virConnectPtr conn)
{
    libxl_physinfo phy_info;
    libxlDriverPrivatePtr driver = conn->privateData;
3858 3859
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
    unsigned long long ret = 0;
3860

3861
    if (virNodeGetFreeMemoryEnsureACL(conn) < 0)
3862
        goto cleanup;
3863

3864
    if (libxl_get_physinfo(cfg->ctx, &phy_info)) {
3865 3866
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("libxl_get_physinfo_info failed"));
3867
        goto cleanup;
3868 3869
    }

3870 3871
    ret = phy_info.free_pages * cfg->verInfo->pagesize;

3872
 cleanup:
3873 3874
    virObjectUnref(cfg);
    return ret;
3875 3876
}

3877 3878 3879 3880 3881 3882 3883 3884 3885 3886
static int
libxlNodeGetCellsFreeMemory(virConnectPtr conn,
                            unsigned long long *freeMems,
                            int startCell,
                            int maxCells)
{
    int n, lastCell, numCells;
    int ret = -1, nr_nodes = 0;
    libxl_numainfo *numa_info = NULL;
    libxlDriverPrivatePtr driver = conn->privateData;
3887
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
3888 3889

    if (virNodeGetCellsFreeMemoryEnsureACL(conn) < 0)
3890
        goto cleanup;
3891

3892
    numa_info = libxl_get_numainfo(cfg->ctx, &nr_nodes);
3893
    if (numa_info == NULL || nr_nodes == 0) {
3894 3895 3896
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("libxl_get_numainfo failed"));
        goto cleanup;
3897 3898 3899
    }

    /* Check/sanitize the cell range */
3900
    if (startCell >= nr_nodes) {
3901 3902
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("start cell %d out of range (0-%d)"),
3903
                       startCell, nr_nodes - 1);
3904 3905 3906
        goto cleanup;
    }
    lastCell = startCell + maxCells - 1;
3907 3908
    if (lastCell >= nr_nodes)
        lastCell = nr_nodes - 1;
3909 3910 3911 3912 3913 3914 3915

    for (numCells = 0, n = startCell; n <= lastCell; n++) {
        if (numa_info[n].size == LIBXL_NUMAINFO_INVALID_ENTRY)
            freeMems[numCells++] = 0;
        else
            freeMems[numCells++] = numa_info[n].free;
    }
3916

3917 3918
    ret = numCells;

3919
 cleanup:
3920
    libxl_numainfo_list_free(numa_info, nr_nodes);
3921
    virObjectUnref(cfg);
3922 3923 3924
    return ret;
}

3925
static int
3926
libxlConnectDomainEventRegister(virConnectPtr conn,
3927 3928
                                virConnectDomainEventCallback callback,
                                void *opaque,
3929
                                virFreeCallback freecb)
3930 3931 3932
{
    libxlDriverPrivatePtr driver = conn->privateData;

3933 3934 3935
    if (virConnectDomainEventRegisterEnsureACL(conn) < 0)
        return -1;

3936 3937 3938 3939
    if (virDomainEventStateRegister(conn,
                                    driver->domainEventState,
                                    callback, opaque, freecb) < 0)
        return -1;
3940

3941
    return 0;
3942 3943 3944 3945
}


static int
3946 3947
libxlConnectDomainEventDeregister(virConnectPtr conn,
                                  virConnectDomainEventCallback callback)
3948 3949 3950
{
    libxlDriverPrivatePtr driver = conn->privateData;

3951 3952 3953
    if (virConnectDomainEventDeregisterEnsureACL(conn) < 0)
        return -1;

3954 3955 3956 3957
    if (virDomainEventStateDeregister(conn,
                                      driver->domainEventState,
                                      callback) < 0)
        return -1;
3958

3959
    return 0;
3960 3961
}

3962 3963 3964 3965 3966 3967
static int
libxlDomainGetAutostart(virDomainPtr dom, int *autostart)
{
    virDomainObjPtr vm;
    int ret = -1;

J
Jim Fehlig 已提交
3968
    if (!(vm = libxlDomObjFromDomain(dom)))
3969 3970
        goto cleanup;

3971 3972 3973
    if (virDomainGetAutostartEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

3974 3975 3976
    *autostart = vm->autostart;
    ret = 0;

3977
 cleanup:
3978
    if (vm)
3979
        virObjectUnlock(vm);
3980 3981 3982 3983 3984 3985 3986
    return ret;
}

static int
libxlDomainSetAutostart(virDomainPtr dom, int autostart)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
3987
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
3988 3989 3990 3991
    virDomainObjPtr vm;
    char *configFile = NULL, *autostartLink = NULL;
    int ret = -1;

J
Jim Fehlig 已提交
3992
    if (!(vm = libxlDomObjFromDomain(dom)))
3993 3994
        goto cleanup;

3995 3996 3997
    if (virDomainSetAutostartEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

3998 3999 4000
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

4001
    if (!vm->persistent) {
4002 4003
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("cannot set autostart for transient domain"));
4004
        goto endjob;
4005 4006 4007 4008 4009
    }

    autostart = (autostart != 0);

    if (vm->autostart != autostart) {
4010
        if (!(configFile = virDomainConfigFile(cfg->configDir, vm->def->name)))
4011
            goto endjob;
4012
        if (!(autostartLink = virDomainConfigFile(cfg->autostartDir, vm->def->name)))
4013
            goto endjob;
4014 4015

        if (autostart) {
4016
            if (virFileMakePath(cfg->autostartDir) < 0) {
4017
                virReportSystemError(errno,
4018
                                     _("cannot create autostart directory %s"),
4019
                                     cfg->autostartDir);
4020
                goto endjob;
4021 4022 4023 4024 4025 4026
            }

            if (symlink(configFile, autostartLink) < 0) {
                virReportSystemError(errno,
                                     _("Failed to create symlink '%s to '%s'"),
                                     autostartLink, configFile);
4027
                goto endjob;
4028 4029 4030 4031 4032 4033
            }
        } else {
            if (unlink(autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) {
                virReportSystemError(errno,
                                     _("Failed to delete symlink '%s'"),
                                     autostartLink);
4034
                goto endjob;
4035 4036 4037 4038 4039 4040 4041
            }
        }

        vm->autostart = autostart;
    }
    ret = 0;

4042
 endjob:
4043 4044 4045
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

4046
 cleanup:
4047 4048 4049
    VIR_FREE(configFile);
    VIR_FREE(autostartLink);
    if (vm)
4050
        virObjectUnlock(vm);
4051
    virObjectUnref(cfg);
4052 4053 4054
    return ret;
}

4055 4056 4057
static char *
libxlDomainGetSchedulerType(virDomainPtr dom, int *nparams)
{
J
Jim Fehlig 已提交
4058 4059
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
4060 4061
    virDomainObjPtr vm;
    char * ret = NULL;
4062
    const char *name = NULL;
J
Jim Fehlig 已提交
4063
    libxl_scheduler sched_id;
4064

J
Jim Fehlig 已提交
4065
    if (!(vm = libxlDomObjFromDomain(dom)))
4066 4067
        goto cleanup;

4068 4069 4070
    if (virDomainGetSchedulerTypeEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

4071
    if (!virDomainObjIsActive(vm)) {
4072
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
4073 4074 4075
        goto cleanup;
    }

J
Jim Fehlig 已提交
4076
    sched_id = libxl_get_scheduler(cfg->ctx);
4077

4078 4079
    if (nparams)
        *nparams = 0;
4080
    switch (sched_id) {
J
Jim Fehlig 已提交
4081
    case LIBXL_SCHEDULER_SEDF:
4082
        name = "sedf";
4083
        break;
J
Jim Fehlig 已提交
4084
    case LIBXL_SCHEDULER_CREDIT:
4085
        name = "credit";
4086 4087
        if (nparams)
            *nparams = XEN_SCHED_CREDIT_NPARAM;
4088
        break;
J
Jim Fehlig 已提交
4089
    case LIBXL_SCHEDULER_CREDIT2:
4090
        name = "credit2";
4091
        break;
J
Jim Fehlig 已提交
4092
    case LIBXL_SCHEDULER_ARINC653:
4093
        name = "arinc653";
4094 4095
        break;
    default:
J
Jim Fehlig 已提交
4096 4097
        virReportError(VIR_ERR_INTERNAL_ERROR,
                   _("Failed to get scheduler id for domain '%d'"
4098
                     " with libxenlight"), vm->def->id);
4099 4100 4101
        goto cleanup;
    }

4102
    ignore_value(VIR_STRDUP(ret, name));
4103

4104
 cleanup:
4105
    if (vm)
4106
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
4107
    virObjectUnref(cfg);
4108 4109 4110
    return ret;
}

4111
static int
4112 4113 4114 4115
libxlDomainGetSchedulerParametersFlags(virDomainPtr dom,
                                       virTypedParameterPtr params,
                                       int *nparams,
                                       unsigned int flags)
4116
{
J
Jim Fehlig 已提交
4117 4118
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
4119
    virDomainObjPtr vm;
J
Jim Fehlig 已提交
4120 4121
    libxl_domain_sched_params sc_info;
    libxl_scheduler sched_id;
4122 4123
    int ret = -1;

4124 4125 4126 4127
    virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);

    /* We don't return strings, and thus trivially support this flag.  */
    flags &= ~VIR_TYPED_PARAM_STRING_OKAY;
4128

J
Jim Fehlig 已提交
4129
    if (!(vm = libxlDomObjFromDomain(dom)))
4130 4131
        goto cleanup;

4132 4133 4134
    if (virDomainGetSchedulerParametersFlagsEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

4135
    if (!virDomainObjIsActive(vm)) {
J
Jim Fehlig 已提交
4136 4137
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("Domain is not running"));
4138 4139 4140
        goto cleanup;
    }

J
Jim Fehlig 已提交
4141
    sched_id = libxl_get_scheduler(cfg->ctx);
4142

J
Jim Fehlig 已提交
4143
    if (sched_id != LIBXL_SCHEDULER_CREDIT) {
4144 4145
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Only 'credit' scheduler is supported"));
4146 4147 4148
        goto cleanup;
    }

J
Jim Fehlig 已提交
4149
    if (libxl_domain_sched_params_get(cfg->ctx, vm->def->id, &sc_info) != 0) {
4150 4151
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to get scheduler parameters for domain '%d'"
4152
                         " with libxenlight"), vm->def->id);
4153 4154 4155
        goto cleanup;
    }

4156 4157
    if (virTypedParameterAssign(&params[0], VIR_DOMAIN_SCHEDULER_WEIGHT,
                                VIR_TYPED_PARAM_UINT, sc_info.weight) < 0)
4158 4159
        goto cleanup;

4160
    if (*nparams > 1) {
4161 4162
        if (virTypedParameterAssign(&params[0], VIR_DOMAIN_SCHEDULER_CAP,
                                    VIR_TYPED_PARAM_UINT, sc_info.cap) < 0)
4163
            goto cleanup;
4164 4165
    }

4166 4167
    if (*nparams > XEN_SCHED_CREDIT_NPARAM)
        *nparams = XEN_SCHED_CREDIT_NPARAM;
4168 4169
    ret = 0;

4170
 cleanup:
4171
    if (vm)
4172
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
4173
    virObjectUnref(cfg);
4174 4175 4176 4177
    return ret;
}

static int
4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188
libxlDomainGetSchedulerParameters(virDomainPtr dom, virTypedParameterPtr params,
                                  int *nparams)
{
    return libxlDomainGetSchedulerParametersFlags(dom, params, nparams, 0);
}

static int
libxlDomainSetSchedulerParametersFlags(virDomainPtr dom,
                                       virTypedParameterPtr params,
                                       int nparams,
                                       unsigned int flags)
4189
{
4190
    libxlDriverPrivatePtr driver = dom->conn->privateData;
J
Jim Fehlig 已提交
4191
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
4192
    virDomainObjPtr vm;
J
Jim Fehlig 已提交
4193
    libxl_domain_sched_params sc_info;
4194
    int sched_id;
4195
    size_t i;
4196 4197
    int ret = -1;

4198
    virCheckFlags(0, -1);
4199 4200 4201 4202 4203 4204
    if (virTypedParamsValidate(params, nparams,
                               VIR_DOMAIN_SCHEDULER_WEIGHT,
                               VIR_TYPED_PARAM_UINT,
                               VIR_DOMAIN_SCHEDULER_CAP,
                               VIR_TYPED_PARAM_UINT,
                               NULL) < 0)
4205
        return -1;
4206

J
Jim Fehlig 已提交
4207
    if (!(vm = libxlDomObjFromDomain(dom)))
4208 4209
        goto cleanup;

4210 4211 4212
    if (virDomainSetSchedulerParametersFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
        goto cleanup;

4213 4214 4215
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

4216
    if (!virDomainObjIsActive(vm)) {
4217
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
4218
        goto endjob;
4219 4220
    }

J
Jim Fehlig 已提交
4221
    sched_id = libxl_get_scheduler(cfg->ctx);
4222

J
Jim Fehlig 已提交
4223
    if (sched_id != LIBXL_SCHEDULER_CREDIT) {
4224 4225
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Only 'credit' scheduler is supported"));
4226
        goto endjob;
4227 4228
    }

J
Jim Fehlig 已提交
4229
    if (libxl_domain_sched_params_get(cfg->ctx, vm->def->id, &sc_info) != 0) {
4230 4231
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to get scheduler parameters for domain '%d'"
4232
                         " with libxenlight"), vm->def->id);
4233
        goto endjob;
4234 4235 4236
    }

    for (i = 0; i < nparams; ++i) {
4237
        virTypedParameterPtr param = &params[i];
4238

4239
        if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_WEIGHT))
4240
            sc_info.weight = params[i].value.ui;
4241
        else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_CAP))
4242 4243 4244
            sc_info.cap = params[i].value.ui;
    }

J
Jim Fehlig 已提交
4245
    if (libxl_domain_sched_params_set(cfg->ctx, vm->def->id, &sc_info) != 0) {
4246 4247
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to set scheduler parameters for domain '%d'"
4248
                         " with libxenlight"), vm->def->id);
4249
        goto endjob;
4250 4251 4252 4253
    }

    ret = 0;

4254
 endjob:
4255 4256 4257
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

4258
 cleanup:
4259
    if (vm)
4260
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
4261
    virObjectUnref(cfg);
4262 4263 4264
    return ret;
}

B
Bamvor Jian Zhang 已提交
4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285

static int
libxlDomainOpenConsole(virDomainPtr dom,
                       const char *dev_name,
                       virStreamPtr st,
                       unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    int ret = -1;
    virDomainChrDefPtr chr = NULL;
    libxlDomainObjPrivatePtr priv;

    virCheckFlags(VIR_DOMAIN_CONSOLE_FORCE, -1);

    if (dev_name) {
        /* XXX support device aliases in future */
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                       _("Named device aliases are not supported"));
        goto cleanup;
    }

J
Jim Fehlig 已提交
4286
    if (!(vm = libxlDomObjFromDomain(dom)))
B
Bamvor Jian Zhang 已提交
4287 4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299
        goto cleanup;

    if (virDomainOpenConsoleEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

    if (!virDomainObjIsActive(vm)) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
        goto cleanup;
    }

    priv = vm->privateData;

I
Ian Campbell 已提交
4300 4301
    if (vm->def->nconsoles)
        chr = vm->def->consoles[0];
B
Bamvor Jian Zhang 已提交
4302 4303 4304 4305 4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328

    if (!chr) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("cannot find character device %s"),
                       NULLSTR(dev_name));
        goto cleanup;
    }

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

    /* handle mutually exclusive access to console devices */
    ret = virChrdevOpen(priv->devs,
                        &chr->source,
                        st,
                        (flags & VIR_DOMAIN_CONSOLE_FORCE) != 0);

    if (ret == 1) {
        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                       _("Active console session exists for this domain"));
        ret = -1;
    }

4329
 cleanup:
B
Bamvor Jian Zhang 已提交
4330 4331 4332 4333 4334
    if (vm)
        virObjectUnlock(vm);
    return ret;
}

4335 4336 4337 4338 4339 4340 4341
static int
libxlDomainSetSchedulerParameters(virDomainPtr dom, virTypedParameterPtr params,
                                  int nparams)
{
    return libxlDomainSetSchedulerParametersFlags(dom, params, nparams, 0);
}

4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354
/* NUMA node affinity information is available through libxl
 * starting from Xen 4.3. */
#ifdef LIBXL_HAVE_DOMAIN_NODEAFFINITY

/* Number of Xen NUMA parameters */
# define LIBXL_NUMA_NPARAM 2

static int
libxlDomainGetNumaParameters(virDomainPtr dom,
                             virTypedParameterPtr params,
                             int *nparams,
                             unsigned int flags)
{
J
Jim Fehlig 已提交
4355 4356
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372
    virDomainObjPtr vm;
    libxl_bitmap nodemap;
    virBitmapPtr nodes = NULL;
    char *nodeset = NULL;
    int rc, ret = -1;
    size_t i, j;

    /* In Xen 4.3, it is possible to query the NUMA node affinity of a domain
     * via libxl, but not to change it. We therefore only allow AFFECT_LIVE. */
    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_TYPED_PARAM_STRING_OKAY, -1);

    /* We blindly return a string, and let libvirt.c and remote_driver.c do
     * the filtering on behalf of older clients that can't parse it. */
    flags &= ~VIR_TYPED_PARAM_STRING_OKAY;

4373 4374
    libxl_bitmap_init(&nodemap);

J
Jim Fehlig 已提交
4375
    if (!(vm = libxlDomObjFromDomain(dom)))
4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393 4394
        goto cleanup;

    if (virDomainGetNumaParametersEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

    if (!virDomainObjIsActive(vm)) {
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("Domain is not running"));
        goto cleanup;
    }

    if ((*nparams) == 0) {
        *nparams = LIBXL_NUMA_NPARAM;
        ret = 0;
        goto cleanup;
    }

    for (i = 0; i < LIBXL_NUMA_NPARAM && i < *nparams; i++) {
        virMemoryParameterPtr param = &params[i];
4395
        int numnodes;
4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413

        switch (i) {
        case 0:
            /* NUMA mode */

            /* Xen implements something that is really close to numactl's
             * 'interleave' policy (see `man 8 numactl' for details). */
            if (virTypedParameterAssign(param, VIR_DOMAIN_NUMA_MODE,
                                        VIR_TYPED_PARAM_INT,
                                        VIR_DOMAIN_NUMATUNE_MEM_INTERLEAVE) < 0)
                goto cleanup;

            break;

        case 1:
            /* Node affinity */

            /* Let's allocate both libxl and libvirt bitmaps */
J
Jim Fehlig 已提交
4414
            numnodes = libxl_get_max_nodes(cfg->ctx);
4415 4416 4417
            if (numnodes <= 0)
                goto cleanup;

J
Jim Fehlig 已提交
4418
            if (libxl_node_bitmap_alloc(cfg->ctx, &nodemap, 0)) {
4419 4420 4421
                virReportOOMError();
                goto cleanup;
            }
J
Ján Tomko 已提交
4422 4423
            if (!(nodes = virBitmapNew(numnodes)))
                goto cleanup;
4424

J
Jim Fehlig 已提交
4425
            rc = libxl_domain_get_nodeaffinity(cfg->ctx,
4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444
                                               vm->def->id,
                                               &nodemap);
            if (rc != 0) {
                virReportSystemError(-rc, "%s",
                                     _("unable to get numa affinity"));
                goto cleanup;
            }

            /* First, we convert libxl_bitmap into virBitmap. After that,
             * we format virBitmap as a string that can be returned. */
            virBitmapClearAll(nodes);
            libxl_for_each_set_bit(j, nodemap) {
                if (virBitmapSetBit(nodes, j)) {
                    virReportError(VIR_ERR_INTERNAL_ERROR,
                                   _("Node %zu out of range"), j);
                    goto cleanup;
                }
            }

4445
            if (!(nodeset = virBitmapFormat(nodes)))
4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461
                goto cleanup;

            if (virTypedParameterAssign(param, VIR_DOMAIN_NUMA_NODESET,
                                        VIR_TYPED_PARAM_STRING, nodeset) < 0)
                goto cleanup;

            nodeset = NULL;

            break;
        }
    }

    if (*nparams > LIBXL_NUMA_NPARAM)
        *nparams = LIBXL_NUMA_NPARAM;
    ret = 0;

4462
 cleanup:
4463 4464 4465 4466 4467
    VIR_FREE(nodeset);
    virBitmapFree(nodes);
    libxl_bitmap_dispose(&nodemap);
    if (vm)
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
4468
    virObjectUnref(cfg);
4469 4470 4471 4472
    return ret;
}
#endif

J
Jim Fehlig 已提交
4473 4474 4475 4476 4477 4478
static int
libxlDomainIsActive(virDomainPtr dom)
{
    virDomainObjPtr obj;
    int ret = -1;

J
Jim Fehlig 已提交
4479
    if (!(obj = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
4480
        goto cleanup;
4481 4482 4483 4484

    if (virDomainIsActiveEnsureACL(dom->conn, obj->def) < 0)
        goto cleanup;

J
Jim Fehlig 已提交
4485 4486
    ret = virDomainObjIsActive(obj);

4487
 cleanup:
J
Jim Fehlig 已提交
4488
    if (obj)
4489
        virObjectUnlock(obj);
J
Jim Fehlig 已提交
4490 4491 4492 4493 4494 4495 4496 4497 4498
    return ret;
}

static int
libxlDomainIsPersistent(virDomainPtr dom)
{
    virDomainObjPtr obj;
    int ret = -1;

J
Jim Fehlig 已提交
4499
    if (!(obj = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
4500
        goto cleanup;
4501 4502 4503 4504

    if (virDomainIsPersistentEnsureACL(dom->conn, obj->def) < 0)
        goto cleanup;

J
Jim Fehlig 已提交
4505 4506
    ret = obj->persistent;

4507
 cleanup:
J
Jim Fehlig 已提交
4508
    if (obj)
4509
        virObjectUnlock(obj);
J
Jim Fehlig 已提交
4510 4511 4512
    return ret;
}

4513 4514 4515 4516 4517 4518
static int
libxlDomainIsUpdated(virDomainPtr dom)
{
    virDomainObjPtr vm;
    int ret = -1;

J
Jim Fehlig 已提交
4519
    if (!(vm = libxlDomObjFromDomain(dom)))
4520
        goto cleanup;
4521 4522 4523 4524

    if (virDomainIsUpdatedEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

4525 4526
    ret = vm->updated;

4527
 cleanup:
4528
    if (vm)
4529
        virObjectUnlock(vm);
4530 4531 4532
    return ret;
}

4533
static int
4534 4535 4536
libxlConnectDomainEventRegisterAny(virConnectPtr conn, virDomainPtr dom, int eventID,
                                   virConnectDomainEventGenericCallback callback,
                                   void *opaque, virFreeCallback freecb)
4537 4538 4539 4540
{
    libxlDriverPrivatePtr driver = conn->privateData;
    int ret;

4541 4542 4543
    if (virConnectDomainEventRegisterAnyEnsureACL(conn) < 0)
        return -1;

4544 4545 4546 4547
    if (virDomainEventStateRegisterID(conn,
                                      driver->domainEventState,
                                      dom, eventID, callback, opaque,
                                      freecb, &ret) < 0)
4548
        ret = -1;
4549 4550 4551 4552 4553 4554

    return ret;
}


static int
4555
libxlConnectDomainEventDeregisterAny(virConnectPtr conn, int callbackID)
4556 4557 4558
{
    libxlDriverPrivatePtr driver = conn->privateData;

4559 4560 4561
    if (virConnectDomainEventDeregisterAnyEnsureACL(conn) < 0)
        return -1;

4562 4563 4564 4565
    if (virObjectEventStateDeregisterID(conn,
                                        driver->domainEventState,
                                        callbackID) < 0)
        return -1;
4566

4567
    return 0;
4568 4569
}

J
Jim Fehlig 已提交
4570

4571
static int
4572
libxlConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED)
4573 4574 4575 4576
{
    return 1;
}

4577
static int
4578 4579 4580
libxlConnectListAllDomains(virConnectPtr conn,
                           virDomainPtr **domains,
                           unsigned int flags)
4581 4582 4583 4584
{
    libxlDriverPrivatePtr driver = conn->privateData;
    int ret = -1;

O
Osier Yang 已提交
4585
    virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
4586

4587 4588 4589
    if (virConnectListAllDomainsEnsureACL(conn) < 0)
        return -1;

4590 4591
    ret = virDomainObjListExport(driver->domains, conn, domains,
                                 virConnectListAllDomainsCheckACL, flags);
4592 4593 4594 4595

    return ret;
}

4596 4597 4598 4599 4600 4601 4602 4603 4604
/* Which features are supported by this driver? */
static int
libxlConnectSupportsFeature(virConnectPtr conn, int feature)
{
    if (virConnectSupportsFeatureEnsureACL(conn) < 0)
        return -1;

    switch (feature) {
    case VIR_DRV_FEATURE_TYPED_PARAM_STRING:
J
Jim Fehlig 已提交
4605
    case VIR_DRV_FEATURE_MIGRATION_PARAMS:
4606 4607 4608 4609 4610
        return 1;
    default:
        return 0;
    }
}
4611

4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636
static int
libxlNodeDeviceGetPCIInfo(virNodeDeviceDefPtr def,
                          unsigned *domain,
                          unsigned *bus,
                          unsigned *slot,
                          unsigned *function)
{
    virNodeDevCapsDefPtr cap;

    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) {
        virReportError(VIR_ERR_INVALID_ARG,
                       _("device %s is not a PCI device"), def->name);
C
Chunyan Liu 已提交
4637
        return -1;
4638 4639
    }

C
Chunyan Liu 已提交
4640
    return 0;
4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688
}

static int
libxlNodeDeviceDetachFlags(virNodeDevicePtr dev,
                           const char *driverName,
                           unsigned int flags)
{
    virPCIDevicePtr pci = NULL;
    unsigned domain = 0, bus = 0, slot = 0, function = 0;
    int ret = -1;
    virNodeDeviceDefPtr def = NULL;
    char *xml = NULL;
    libxlDriverPrivatePtr driver = dev->conn->privateData;
    virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;

    virCheckFlags(0, -1);

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

    def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL);
    if (!def)
        goto cleanup;

    if (virNodeDeviceDetachFlagsEnsureACL(dev->conn, def) < 0)
        goto cleanup;

    if (libxlNodeDeviceGetPCIInfo(def, &domain, &bus, &slot, &function) < 0)
        goto cleanup;

    pci = virPCIDeviceNew(domain, bus, slot, function);
    if (!pci)
        goto cleanup;

    if (!driverName || STREQ(driverName, "xen")) {
        if (virPCIDeviceSetStubDriver(pci, "pciback") < 0)
            goto cleanup;
    } else {
        virReportError(VIR_ERR_INVALID_ARG,
                       _("unsupported driver name '%s'"), driverName);
        goto cleanup;
    }

    if (virHostdevPCINodeDeviceDetach(hostdev_mgr, pci) < 0)
        goto cleanup;

    ret = 0;
4689
 cleanup:
4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713 4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731
    virPCIDeviceFree(pci);
    virNodeDeviceDefFree(def);
    VIR_FREE(xml);
    return ret;
}

static int
libxlNodeDeviceDettach(virNodeDevicePtr dev)
{
    return libxlNodeDeviceDetachFlags(dev, NULL, 0);
}

static int
libxlNodeDeviceReAttach(virNodeDevicePtr dev)
{
    virPCIDevicePtr pci = NULL;
    unsigned domain = 0, bus = 0, slot = 0, function = 0;
    int ret = -1;
    virNodeDeviceDefPtr def = NULL;
    char *xml = NULL;
    libxlDriverPrivatePtr driver = dev->conn->privateData;
    virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;

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

    def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL);
    if (!def)
        goto cleanup;

    if (virNodeDeviceReAttachEnsureACL(dev->conn, def) < 0)
        goto cleanup;

    if (libxlNodeDeviceGetPCIInfo(def, &domain, &bus, &slot, &function) < 0)
        goto cleanup;

    pci = virPCIDeviceNew(domain, bus, slot, function);
    if (!pci)
        goto cleanup;

    if (virHostdevPCINodeDeviceReAttach(hostdev_mgr, pci) < 0)
C
Chunyan Liu 已提交
4732
        goto cleanup;
4733 4734

    ret = 0;
C
Chunyan Liu 已提交
4735

4736
 cleanup:
C
Chunyan Liu 已提交
4737
    virPCIDeviceFree(pci);
4738 4739 4740 4741 4742 4743 4744 4745
    virNodeDeviceDefFree(def);
    VIR_FREE(xml);
    return ret;
}

static int
libxlNodeDeviceReset(virNodeDevicePtr dev)
{
C
Chunyan Liu 已提交
4746
    virPCIDevicePtr pci = NULL;
4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772
    unsigned domain = 0, bus = 0, slot = 0, function = 0;
    int ret = -1;
    virNodeDeviceDefPtr def = NULL;
    char *xml = NULL;
    libxlDriverPrivatePtr driver = dev->conn->privateData;
    virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;

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

    def = virNodeDeviceDefParseString(xml, EXISTING_DEVICE, NULL);
    if (!def)
        goto cleanup;

    if (virNodeDeviceResetEnsureACL(dev->conn, def) < 0)
        goto cleanup;

    if (libxlNodeDeviceGetPCIInfo(def, &domain, &bus, &slot, &function) < 0)
        goto cleanup;

    pci = virPCIDeviceNew(domain, bus, slot, function);
    if (!pci)
        goto cleanup;

    if (virHostdevPCINodeDeviceReset(hostdev_mgr, pci) < 0)
C
Chunyan Liu 已提交
4773
        goto cleanup;
4774 4775

    ret = 0;
C
Chunyan Liu 已提交
4776

4777
 cleanup:
C
Chunyan Liu 已提交
4778
    virPCIDeviceFree(pci);
4779 4780 4781 4782 4783
    virNodeDeviceDefFree(def);
    VIR_FREE(xml);
    return ret;
}

J
Jim Fehlig 已提交
4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794
static char *
libxlDomainMigrateBegin3Params(virDomainPtr domain,
                               virTypedParameterPtr params,
                               int nparams,
                               char **cookieout ATTRIBUTE_UNUSED,
                               int *cookieoutlen ATTRIBUTE_UNUSED,
                               unsigned int flags)
{
    const char *xmlin = NULL;
    virDomainObjPtr vm = NULL;

4795 4796 4797 4798 4799
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
    virReportUnsupportedError();
    return NULL;
#endif

J
Jim Fehlig 已提交
4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843
    virCheckFlags(LIBXL_MIGRATION_FLAGS, NULL);
    if (virTypedParamsValidate(params, nparams, LIBXL_MIGRATION_PARAMETERS) < 0)
        return NULL;

    if (virTypedParamsGetString(params, nparams,
                                VIR_MIGRATE_PARAM_DEST_XML,
                                &xmlin) < 0)
        return NULL;

    if (!(vm = libxlDomObjFromDomain(domain)))
        return NULL;

    if (virDomainMigrateBegin3ParamsEnsureACL(domain->conn, vm->def) < 0) {
        virObjectUnlock(vm);
        return NULL;
    }

    if (!virDomainObjIsActive(vm)) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
        virObjectUnlock(vm);
        return NULL;
    }

    return libxlDomainMigrationBegin(domain->conn, vm, xmlin);
}

static int
libxlDomainMigratePrepare3Params(virConnectPtr dconn,
                                 virTypedParameterPtr params,
                                 int nparams,
                                 const char *cookiein ATTRIBUTE_UNUSED,
                                 int cookieinlen ATTRIBUTE_UNUSED,
                                 char **cookieout ATTRIBUTE_UNUSED,
                                 int *cookieoutlen ATTRIBUTE_UNUSED,
                                 char **uri_out,
                                 unsigned int flags)
{
    libxlDriverPrivatePtr driver = dconn->privateData;
    virDomainDefPtr def = NULL;
    const char *dom_xml = NULL;
    const char *dname = NULL;
    const char *uri_in = NULL;

4844 4845 4846 4847 4848
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
    virReportUnsupportedError();
    return -1;
#endif

J
Jim Fehlig 已提交
4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870
    virCheckFlags(LIBXL_MIGRATION_FLAGS, -1);
    if (virTypedParamsValidate(params, nparams, LIBXL_MIGRATION_PARAMETERS) < 0)
        goto error;

    if (virTypedParamsGetString(params, nparams,
                                VIR_MIGRATE_PARAM_DEST_XML,
                                &dom_xml) < 0 ||
        virTypedParamsGetString(params, nparams,
                                VIR_MIGRATE_PARAM_DEST_NAME,
                                &dname) < 0 ||
        virTypedParamsGetString(params, nparams,
                                VIR_MIGRATE_PARAM_URI,
                                &uri_in) < 0)

        goto error;

    if (!(def = libxlDomainMigrationPrepareDef(driver, dom_xml, dname)))
        goto error;

    if (virDomainMigratePrepare3ParamsEnsureACL(dconn, def) < 0)
        goto error;

4871
    if (libxlDomainMigrationPrepare(dconn, &def, uri_in, uri_out, flags) < 0)
J
Jim Fehlig 已提交
4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898
        goto error;

    return 0;

 error:
    virDomainDefFree(def);
    return -1;
}

static int
libxlDomainMigratePerform3Params(virDomainPtr dom,
                                 const char *dconnuri,
                                 virTypedParameterPtr params,
                                 int nparams,
                                 const char *cookiein ATTRIBUTE_UNUSED,
                                 int cookieinlen ATTRIBUTE_UNUSED,
                                 char **cookieout ATTRIBUTE_UNUSED,
                                 int *cookieoutlen ATTRIBUTE_UNUSED,
                                 unsigned int flags)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    virDomainObjPtr vm = NULL;
    const char *dom_xml = NULL;
    const char *dname = NULL;
    const char *uri = NULL;
    int ret = -1;

4899 4900 4901 4902 4903
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
    virReportUnsupportedError();
    return -1;
#endif

J
Jim Fehlig 已提交
4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926
    virCheckFlags(LIBXL_MIGRATION_FLAGS, -1);
    if (virTypedParamsValidate(params, nparams, LIBXL_MIGRATION_PARAMETERS) < 0)
        goto cleanup;

    if (virTypedParamsGetString(params, nparams,
                                VIR_MIGRATE_PARAM_DEST_XML,
                                &dom_xml) < 0 ||
        virTypedParamsGetString(params, nparams,
                                VIR_MIGRATE_PARAM_DEST_NAME,
                                &dname) < 0 ||
        virTypedParamsGetString(params, nparams,
                                VIR_MIGRATE_PARAM_URI,
                                &uri) < 0)

        goto cleanup;

    if (!(vm = libxlDomObjFromDomain(dom)))
        goto cleanup;

    if (virDomainMigratePerform3ParamsEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

    if (libxlDomainMigrationPerform(driver, vm, dom_xml, dconnuri,
4927
                                    uri, dname, flags) < 0)
J
Jim Fehlig 已提交
4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951
        goto cleanup;

    ret = 0;

 cleanup:
    if (vm)
        virObjectUnlock(vm);
    return ret;
}

static virDomainPtr
libxlDomainMigrateFinish3Params(virConnectPtr dconn,
                                virTypedParameterPtr params,
                                int nparams,
                                const char *cookiein ATTRIBUTE_UNUSED,
                                int cookieinlen ATTRIBUTE_UNUSED,
                                char **cookieout ATTRIBUTE_UNUSED,
                                int *cookieoutlen ATTRIBUTE_UNUSED,
                                unsigned int flags,
                                int cancelled)
{
    libxlDriverPrivatePtr driver = dconn->privateData;
    virDomainObjPtr vm = NULL;
    const char *dname = NULL;
4952
    virDomainPtr ret = NULL;
J
Jim Fehlig 已提交
4953

4954 4955 4956 4957 4958
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
    virReportUnsupportedError();
    return NULL;
#endif

J
Jim Fehlig 已提交
4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978
    virCheckFlags(LIBXL_MIGRATION_FLAGS, NULL);
    if (virTypedParamsValidate(params, nparams, LIBXL_MIGRATION_PARAMETERS) < 0)
        return NULL;

    if (virTypedParamsGetString(params, nparams,
                                VIR_MIGRATE_PARAM_DEST_NAME,
                                &dname) < 0)
        return NULL;

    if (!dname ||
        !(vm = virDomainObjListFindByName(driver->domains, dname))) {
        /* Migration obviously failed if the domain doesn't exist */
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("Migration failed. No domain on destination host "
                         "with matching name '%s'"),
                       NULLSTR(dname));
        return NULL;
    }

    if (virDomainMigrateFinish3ParamsEnsureACL(dconn, vm->def) < 0) {
4979
        virDomainObjEndAPI(&vm);
J
Jim Fehlig 已提交
4980 4981 4982
        return NULL;
    }

4983
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0) {
4984
        virDomainObjEndAPI(&vm);
4985 4986 4987 4988 4989 4990 4991 4992
        return NULL;
    }

    ret = libxlDomainMigrationFinish(dconn, vm, flags, cancelled);

    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

4993
    virDomainObjEndAPI(&vm);
4994 4995

    return ret;
J
Jim Fehlig 已提交
4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009
}

static int
libxlDomainMigrateConfirm3Params(virDomainPtr domain,
                                 virTypedParameterPtr params,
                                 int nparams,
                                 const char *cookiein ATTRIBUTE_UNUSED,
                                 int cookieinlen ATTRIBUTE_UNUSED,
                                 unsigned int flags,
                                 int cancelled)
{
    libxlDriverPrivatePtr driver = domain->conn->privateData;
    virDomainObjPtr vm = NULL;

5010 5011 5012 5013 5014
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
    virReportUnsupportedError();
    return -1;
#endif

J
Jim Fehlig 已提交
5015 5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029
    virCheckFlags(LIBXL_MIGRATION_FLAGS, -1);
    if (virTypedParamsValidate(params, nparams, LIBXL_MIGRATION_PARAMETERS) < 0)
        return -1;

    if (!(vm = libxlDomObjFromDomain(domain)))
        return -1;

    if (virDomainMigrateConfirm3ParamsEnsureACL(domain->conn, vm->def) < 0) {
        virObjectUnlock(vm);
        return -1;
    }

    return libxlDomainMigrationConfirm(driver, vm, flags, cancelled);
}

5030

5031
static virHypervisorDriver libxlHypervisorDriver = {
5032
    .name = LIBXL_DRIVER_NAME,
5033 5034 5035 5036
    .connectOpen = libxlConnectOpen, /* 0.9.0 */
    .connectClose = libxlConnectClose, /* 0.9.0 */
    .connectGetType = libxlConnectGetType, /* 0.9.0 */
    .connectGetVersion = libxlConnectGetVersion, /* 0.9.0 */
5037
    .connectGetHostname = libxlConnectGetHostname, /* 0.9.0 */
5038
    .connectGetSysinfo = libxlConnectGetSysinfo, /* 1.1.0 */
5039
    .connectGetMaxVcpus = libxlConnectGetMaxVcpus, /* 0.9.0 */
5040
    .nodeGetInfo = libxlNodeGetInfo, /* 0.9.0 */
5041 5042 5043 5044
    .connectGetCapabilities = libxlConnectGetCapabilities, /* 0.9.0 */
    .connectListDomains = libxlConnectListDomains, /* 0.9.0 */
    .connectNumOfDomains = libxlConnectNumOfDomains, /* 0.9.0 */
    .connectListAllDomains = libxlConnectListAllDomains, /* 0.9.13 */
5045 5046 5047 5048 5049 5050 5051
    .domainCreateXML = libxlDomainCreateXML, /* 0.9.0 */
    .domainLookupByID = libxlDomainLookupByID, /* 0.9.0 */
    .domainLookupByUUID = libxlDomainLookupByUUID, /* 0.9.0 */
    .domainLookupByName = libxlDomainLookupByName, /* 0.9.0 */
    .domainSuspend = libxlDomainSuspend, /* 0.9.0 */
    .domainResume = libxlDomainResume, /* 0.9.0 */
    .domainShutdown = libxlDomainShutdown, /* 0.9.0 */
5052
    .domainShutdownFlags = libxlDomainShutdownFlags, /* 0.9.10 */
5053 5054
    .domainReboot = libxlDomainReboot, /* 0.9.0 */
    .domainDestroy = libxlDomainDestroy, /* 0.9.0 */
5055
    .domainDestroyFlags = libxlDomainDestroyFlags, /* 0.9.4 */
5056 5057
    .domainGetOSType = libxlDomainGetOSType, /* 0.9.0 */
    .domainGetMaxMemory = libxlDomainGetMaxMemory, /* 0.9.0 */
5058
    .domainSetMaxMemory = libxlDomainSetMaxMemory, /* 0.9.2 */
5059 5060 5061 5062
    .domainSetMemory = libxlDomainSetMemory, /* 0.9.0 */
    .domainSetMemoryFlags = libxlDomainSetMemoryFlags, /* 0.9.0 */
    .domainGetInfo = libxlDomainGetInfo, /* 0.9.0 */
    .domainGetState = libxlDomainGetState, /* 0.9.2 */
5063
    .domainSave = libxlDomainSave, /* 0.9.2 */
5064
    .domainSaveFlags = libxlDomainSaveFlags, /* 0.9.4 */
5065
    .domainRestore = libxlDomainRestore, /* 0.9.2 */
5066
    .domainRestoreFlags = libxlDomainRestoreFlags, /* 0.9.4 */
5067
    .domainCoreDump = libxlDomainCoreDump, /* 0.9.2 */
5068 5069 5070 5071
    .domainSetVcpus = libxlDomainSetVcpus, /* 0.9.0 */
    .domainSetVcpusFlags = libxlDomainSetVcpusFlags, /* 0.9.0 */
    .domainGetVcpusFlags = libxlDomainGetVcpusFlags, /* 0.9.0 */
    .domainPinVcpu = libxlDomainPinVcpu, /* 0.9.0 */
5072
    .domainPinVcpuFlags = libxlDomainPinVcpuFlags, /* 1.2.1 */
5073
    .domainGetVcpus = libxlDomainGetVcpus, /* 0.9.0 */
5074
    .domainGetVcpuPinInfo = libxlDomainGetVcpuPinInfo, /* 1.2.1 */
5075
    .domainGetXMLDesc = libxlDomainGetXMLDesc, /* 0.9.0 */
5076 5077 5078 5079
    .connectDomainXMLFromNative = libxlConnectDomainXMLFromNative, /* 0.9.0 */
    .connectDomainXMLToNative = libxlConnectDomainXMLToNative, /* 0.9.0 */
    .connectListDefinedDomains = libxlConnectListDefinedDomains, /* 0.9.0 */
    .connectNumOfDefinedDomains = libxlConnectNumOfDefinedDomains, /* 0.9.0 */
5080 5081 5082
    .domainCreate = libxlDomainCreate, /* 0.9.0 */
    .domainCreateWithFlags = libxlDomainCreateWithFlags, /* 0.9.0 */
    .domainDefineXML = libxlDomainDefineXML, /* 0.9.0 */
5083
    .domainDefineXMLFlags = libxlDomainDefineXMLFlags, /* 1.2.12 */
5084
    .domainUndefine = libxlDomainUndefine, /* 0.9.0 */
5085
    .domainUndefineFlags = libxlDomainUndefineFlags, /* 0.9.4 */
5086 5087 5088 5089 5090
    .domainAttachDevice = libxlDomainAttachDevice, /* 0.9.2 */
    .domainAttachDeviceFlags = libxlDomainAttachDeviceFlags, /* 0.9.2 */
    .domainDetachDevice = libxlDomainDetachDevice,    /* 0.9.2 */
    .domainDetachDeviceFlags = libxlDomainDetachDeviceFlags, /* 0.9.2 */
    .domainUpdateDeviceFlags = libxlDomainUpdateDeviceFlags, /* 0.9.2 */
5091 5092 5093 5094
    .domainGetAutostart = libxlDomainGetAutostart, /* 0.9.0 */
    .domainSetAutostart = libxlDomainSetAutostart, /* 0.9.0 */
    .domainGetSchedulerType = libxlDomainGetSchedulerType, /* 0.9.0 */
    .domainGetSchedulerParameters = libxlDomainGetSchedulerParameters, /* 0.9.0 */
5095
    .domainGetSchedulerParametersFlags = libxlDomainGetSchedulerParametersFlags, /* 0.9.2 */
5096
    .domainSetSchedulerParameters = libxlDomainSetSchedulerParameters, /* 0.9.0 */
5097
    .domainSetSchedulerParametersFlags = libxlDomainSetSchedulerParametersFlags, /* 0.9.2 */
5098 5099 5100
#ifdef LIBXL_HAVE_DOMAIN_NODEAFFINITY
    .domainGetNumaParameters = libxlDomainGetNumaParameters, /* 1.1.1 */
#endif
5101
    .nodeGetFreeMemory = libxlNodeGetFreeMemory, /* 0.9.0 */
5102
    .nodeGetCellsFreeMemory = libxlNodeGetCellsFreeMemory, /* 1.1.1 */
5103 5104
    .connectDomainEventRegister = libxlConnectDomainEventRegister, /* 0.9.0 */
    .connectDomainEventDeregister = libxlConnectDomainEventDeregister, /* 0.9.0 */
5105 5106 5107
    .domainManagedSave = libxlDomainManagedSave, /* 0.9.2 */
    .domainHasManagedSaveImage = libxlDomainHasManagedSaveImage, /* 0.9.2 */
    .domainManagedSaveRemove = libxlDomainManagedSaveRemove, /* 0.9.2 */
B
Bamvor Jian Zhang 已提交
5108
    .domainOpenConsole = libxlDomainOpenConsole, /* 1.1.2 */
5109 5110 5111
    .domainIsActive = libxlDomainIsActive, /* 0.9.0 */
    .domainIsPersistent = libxlDomainIsPersistent, /* 0.9.0 */
    .domainIsUpdated = libxlDomainIsUpdated, /* 0.9.0 */
5112 5113 5114
    .connectDomainEventRegisterAny = libxlConnectDomainEventRegisterAny, /* 0.9.0 */
    .connectDomainEventDeregisterAny = libxlConnectDomainEventDeregisterAny, /* 0.9.0 */
    .connectIsAlive = libxlConnectIsAlive, /* 0.9.8 */
5115
    .connectSupportsFeature = libxlConnectSupportsFeature, /* 1.1.1 */
5116 5117 5118 5119
    .nodeDeviceDettach = libxlNodeDeviceDettach, /* 1.2.3 */
    .nodeDeviceDetachFlags = libxlNodeDeviceDetachFlags, /* 1.2.3 */
    .nodeDeviceReAttach = libxlNodeDeviceReAttach, /* 1.2.3 */
    .nodeDeviceReset = libxlNodeDeviceReset, /* 1.2.3 */
5120 5121 5122 5123 5124
    .domainMigrateBegin3Params = libxlDomainMigrateBegin3Params, /* 1.2.6 */
    .domainMigratePrepare3Params = libxlDomainMigratePrepare3Params, /* 1.2.6 */
    .domainMigratePerform3Params = libxlDomainMigratePerform3Params, /* 1.2.6 */
    .domainMigrateFinish3Params = libxlDomainMigrateFinish3Params, /* 1.2.6 */
    .domainMigrateConfirm3Params = libxlDomainMigrateConfirm3Params, /* 1.2.6 */
J
Jim Fehlig 已提交
5125 5126
};

5127 5128 5129 5130
static virConnectDriver libxlConnectDriver = {
    .hypervisorDriver = &libxlHypervisorDriver,
};

J
Jim Fehlig 已提交
5131 5132
static virStateDriver libxlStateDriver = {
    .name = "LIBXL",
5133
    .stateInitialize = libxlStateInitialize,
5134
    .stateAutoStart = libxlStateAutoStart,
5135 5136
    .stateCleanup = libxlStateCleanup,
    .stateReload = libxlStateReload,
J
Jim Fehlig 已提交
5137 5138 5139 5140 5141 5142
};


int
libxlRegister(void)
{
5143 5144
    if (virRegisterConnectDriver(&libxlConnectDriver,
                                 true) < 0)
J
Jim Fehlig 已提交
5145 5146 5147 5148 5149 5150
        return -1;
    if (virRegisterStateDriver(&libxlStateDriver) < 0)
        return -1;

    return 0;
}