libxl_driver.c 154.6 KB
Newer Older
1 2 3
/*
 * libxl_driver.c: core driver methods for managing libxenlight domains
 *
4
 * Copyright (C) 2006-2015 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
#define HYPERVISOR_CAPABILITIES "/proc/xen/capabilities"
R
Roman Bogorodskiy 已提交
77
#define HYPERVISOR_XENSTORED "/dev/xen/xenstored"
78

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

J
Jim Fehlig 已提交
82 83 84 85 86 87 88 89 90
#define LIBXL_CHECK_DOM0_GOTO(name, label)                               \
    do {                                                                  \
        if (STREQ_NULLABLE(name, "Domain-0")) {                           \
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",               \
                           _("Domain-0 does not support requested operation")); \
            goto label;                                                   \
        }                                                                 \
    } while (0)

91

92
static libxlDriverPrivatePtr libxl_driver;
J
Jim Fehlig 已提交
93

94 95 96 97 98 99 100 101 102
/* 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 已提交
103
/* Function declarations */
104 105
static int
libxlDomainManagedSaveLoad(virDomainObjPtr vm,
106 107
                           void *opaque);

J
Jim Fehlig 已提交
108 109

/* Function definitions */
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 277 278 279 280 281 282 283 284 285 286
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 已提交
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305
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;
}

306 307
static int
libxlAutostartDomain(virDomainObjPtr vm,
308 309 310 311
                     void *opaque)
{
    libxlDriverPrivatePtr driver = opaque;
    virErrorPtr err;
312
    int ret = -1;
313

314
    virObjectLock(vm);
315 316
    virResetLastError();

317 318 319 320 321
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0) {
        virObjectUnlock(vm);
        return ret;
    }

322
    if (vm->autostart && !virDomainObjIsActive(vm) &&
323
        libxlDomainStart(driver, vm, false, -1) < 0) {
324 325 326 327
        err = virGetLastError();
        VIR_ERROR(_("Failed to autostart VM '%s': %s"),
                  vm->def->name,
                  err ? err->message : _("unknown error"));
328
        goto endjob;
329 330
    }

331
    ret = 0;
332 333 334 335 336

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

337
    return ret;
338 339
}

J
Jim Fehlig 已提交
340 341 342 343
/*
 * Reconnect to running domains that were previously started/created
 * with libxenlight driver.
 */
344 345
static int
libxlReconnectDomain(virDomainObjPtr vm,
J
Jim Fehlig 已提交
346 347 348
                     void *opaque)
{
    libxlDriverPrivatePtr driver = opaque;
349
    libxlDomainObjPrivatePtr priv = vm->privateData;
J
Jim Fehlig 已提交
350
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
J
Jim Fehlig 已提交
351 352 353 354
    int rc;
    libxl_dominfo d_info;
    int len;
    uint8_t *data = NULL;
355
    virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
J
Jim Fehlig 已提交
356

357
    virObjectLock(vm);
J
Jim Fehlig 已提交
358 359

    /* Does domain still exist? */
J
Jim Fehlig 已提交
360
    rc = libxl_domain_info(cfg->ctx, &d_info, vm->def->id);
J
Jim Fehlig 已提交
361 362 363 364 365 366 367 368 369
    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 已提交
370
    if (libxl_userdata_retrieve(cfg->ctx, vm->def->id,
J
Jim Fehlig 已提交
371 372 373 374 375 376 377
                                "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;
378 379

    /* Update hostdev state */
380
    if (virHostdevUpdateActiveDomainDevices(hostdev_mgr, LIBXL_DRIVER_NAME,
381 382 383
                                            vm->def, VIR_HOSTDEV_SP_PCI) < 0)
        goto out;

384
    if (virAtomicIntInc(&driver->nactive) == 1 && driver->inhibitCallback)
385 386
        driver->inhibitCallback(true, driver->inhibitOpaque);

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

390
    virObjectUnlock(vm);
J
Jim Fehlig 已提交
391
    virObjectUnref(cfg);
392
    return 0;
J
Jim Fehlig 已提交
393

394
 out:
395
    libxlDomainCleanup(driver, vm);
J
Jim Fehlig 已提交
396
    if (!vm->persistent)
397
        virDomainObjListRemoveLocked(driver->domains, vm);
J
Jim Fehlig 已提交
398
    else
399
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
400
    virObjectUnref(cfg);
401 402

    return -1;
J
Jim Fehlig 已提交
403 404 405 406 407
}

static void
libxlReconnectDomains(libxlDriverPrivatePtr driver)
{
408
    virDomainObjListForEach(driver->domains, libxlReconnectDomain, driver);
J
Jim Fehlig 已提交
409 410 411
}

static int
412
libxlStateCleanup(void)
J
Jim Fehlig 已提交
413 414 415 416
{
    if (!libxl_driver)
        return -1;

417
    virObjectUnref(libxl_driver->hostdevMgr);
418
    virObjectUnref(libxl_driver->config);
419
    virObjectUnref(libxl_driver->xmlopt);
420
    virObjectUnref(libxl_driver->domains);
421
    virObjectUnref(libxl_driver->reservedGraphicsPorts);
J
Jim Fehlig 已提交
422
    virObjectUnref(libxl_driver->migrationPorts);
423
    virLockManagerPluginUnref(libxl_driver->lockManager);
J
Jim Fehlig 已提交
424

425
    virObjectEventStateFree(libxl_driver->domainEventState);
426
    virSysinfoDefFree(libxl_driver->hostsysinfo);
427

J
Jim Fehlig 已提交
428 429 430 431 432 433
    virMutexDestroy(&libxl_driver->lock);
    VIR_FREE(libxl_driver);

    return 0;
}

434 435
static bool
libxlDriverShouldLoad(bool privileged)
436
{
437
    bool ret = false;
J
Jim Fehlig 已提交
438

439
    /* Don't load if non-root */
J
Jim Fehlig 已提交
440
    if (!privileged) {
441
        VIR_INFO("Not running privileged, disabling libxenlight driver");
442
        return ret;
J
Jim Fehlig 已提交
443 444
    }

R
Roman Bogorodskiy 已提交
445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465
    if (virFileExists(HYPERVISOR_CAPABILITIES)) {
        int status;
        char *output = NULL;
        /*
         * 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.
         */
        status = virFileReadAll(HYPERVISOR_CAPABILITIES, 10, &output);
        if (status >= 0)
            status = strncmp(output, "control_d", 9);
        VIR_FREE(output);
        if (status) {
            VIR_INFO("No Xen capabilities detected, probably not running "
                     "in a Xen Dom0.  Disabling libxenlight driver");

            return ret;
        }
    } else if (!virFileExists(HYPERVISOR_XENSTORED)) {
        VIR_INFO("Disabling driver as neither " HYPERVISOR_CAPABILITIES
                 " nor " HYPERVISOR_XENSTORED " exist");
466 467 468 469
        return ret;
    }

    /* Don't load if legacy xen toolstack (xend) is in use */
470 471 472 473 474 475 476 477 478 479 480
    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);
481 482
    } else {
        ret = true;
J
Jim Fehlig 已提交
483 484
    }

485 486 487
    return ret;
}

488 489 490 491 492 493 494 495 496 497
/* 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,
};

498 499 500 501 502 503 504 505
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
};

506 507 508 509 510 511
const struct libxl_event_hooks ev_hooks = {
    .event_occurs_mask = LIBXL_EVENTMASK_ALL,
    .event_occurs = libxlDomainEventHandler,
    .disaster = NULL,
};

J
Jim Fehlig 已提交
512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551
static int
libxlAddDom0(libxlDriverPrivatePtr driver)
{
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
    virDomainDefPtr def = NULL;
    virDomainObjPtr vm = NULL;
    virDomainDefPtr oldDef = NULL;
    libxl_dominfo d_info;
    int ret = -1;

    libxl_dominfo_init(&d_info);

    /* Ensure we have a dom0 */
    if (libxl_domain_info(cfg->ctx, &d_info, 0) != 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("unable to get Domain-0 information from libxenlight"));
        goto cleanup;
    }

    if (!(def = virDomainDefNew()))
        goto cleanup;

    def->id = 0;
    def->virtType = VIR_DOMAIN_VIRT_XEN;
    if (VIR_STRDUP(def->name, "Domain-0") < 0)
        goto cleanup;

    def->os.type = VIR_DOMAIN_OSTYPE_XEN;

    if (virUUIDParse("00000000-0000-0000-0000-000000000000", def->uuid) < 0)
        goto cleanup;

    if (!(vm = virDomainObjListAdd(driver->domains, def,
                                   driver->xmlopt,
                                   0,
                                   &oldDef)))
        goto cleanup;

    def = NULL;

J
Jim Fehlig 已提交
552
    virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_BOOTED);
J
Jim Fehlig 已提交
553 554 555
    vm->def->vcpus = d_info.vcpu_online;
    vm->def->maxvcpus = d_info.vcpu_max_id + 1;
    vm->def->mem.cur_balloon = d_info.current_memkb;
556
    virDomainDefSetMemoryTotal(vm->def, d_info.max_memkb);
J
Jim Fehlig 已提交
557 558 559 560 561 562 563 564 565 566 567 568 569

    ret = 0;

 cleanup:
    libxl_dominfo_dispose(&d_info);
    virDomainDefFree(def);
    virDomainDefFree(oldDef);
    if (vm)
        virObjectUnlock(vm);
    virObjectUnref(cfg);
    return ret;
}

570 571 572 573 574
static int
libxlStateInitialize(bool privileged,
                     virStateInhibitCallback callback ATTRIBUTE_UNUSED,
                     void *opaque ATTRIBUTE_UNUSED)
{
575
    libxlDriverConfigPtr cfg;
576
    char *driverConf = NULL;
577 578 579 580 581
    char ebuf[1024];

    if (!libxlDriverShouldLoad(privileged))
        return 0;

J
Jim Fehlig 已提交
582 583 584 585
    if (VIR_ALLOC(libxl_driver) < 0)
        return -1;

    if (virMutexInit(&libxl_driver->lock) < 0) {
586 587
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("cannot initialize mutex"));
J
Jim Fehlig 已提交
588 589 590 591 592
        VIR_FREE(libxl_driver);
        return -1;
    }

    /* Allocate bitmap for vnc port reservation */
593
    if (!(libxl_driver->reservedGraphicsPorts =
J
Ján Tomko 已提交
594 595
          virPortAllocatorNew(_("VNC"),
                              LIBXL_VNC_PORT_MIN,
596 597
                              LIBXL_VNC_PORT_MAX,
                              0)))
598
        goto error;
J
Jim Fehlig 已提交
599

J
Jim Fehlig 已提交
600 601 602 603
    /* Allocate bitmap for migration port reservation */
    if (!(libxl_driver->migrationPorts =
          virPortAllocatorNew(_("migration"),
                              LIBXL_MIGRATION_PORT_MIN,
604
                              LIBXL_MIGRATION_PORT_MAX, 0)))
J
Jim Fehlig 已提交
605 606
        goto error;

607 608
    if (!(libxl_driver->domains = virDomainObjListNew()))
        goto error;
J
Jim Fehlig 已提交
609

610 611 612
    if (!(libxl_driver->hostdevMgr = virHostdevManagerGetDefault()))
        goto error;

613
    if (!(cfg = libxlDriverConfigNew()))
614
        goto error;
J
Jim Fehlig 已提交
615

616 617 618 619 620 621 622
    if (virAsprintf(&driverConf, "%s/libxl.conf", cfg->configBaseDir) < 0)
        goto error;

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

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

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

629 630 631
    /* Register callback to handle domain events */
    libxl_event_register_callbacks(cfg->ctx, &ev_hooks, libxl_driver);

632 633
    libxl_driver->config = cfg;
    if (virFileMakePath(cfg->stateDir) < 0) {
634 635
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to create state dir '%s': %s"),
636
                       cfg->stateDir,
637
                       virStrerror(errno, ebuf, sizeof(ebuf)));
J
Jim Fehlig 已提交
638 639
        goto error;
    }
640
    if (virFileMakePath(cfg->libDir) < 0) {
641 642
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to create lib dir '%s': %s"),
643
                       cfg->libDir,
644
                       virStrerror(errno, ebuf, sizeof(ebuf)));
J
Jim Fehlig 已提交
645 646
        goto error;
    }
647
    if (virFileMakePath(cfg->saveDir) < 0) {
648 649
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to create save dir '%s': %s"),
650
                       cfg->saveDir,
651
                       virStrerror(errno, ebuf, sizeof(ebuf)));
J
Jim Fehlig 已提交
652 653
        goto error;
    }
654 655 656 657 658 659 660
    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 已提交
661

662 663 664 665 666 667 668 669
    if (!(libxl_driver->lockManager =
          virLockManagerPluginNew(cfg->lockManagerName ?
                                  cfg->lockManagerName : "nop",
                                  "libxl",
                                  cfg->configBaseDir,
                                  0)))
        goto error;

670
    /* read the host sysinfo */
671
    libxl_driver->hostsysinfo = virSysinfoRead();
672

673
    libxl_driver->domainEventState = virObjectEventStateNew();
E
Eric Blake 已提交
674
    if (!libxl_driver->domainEventState)
675 676
        goto error;

677
    if ((cfg->caps = libxlMakeCapabilities(cfg->ctx)) == NULL) {
678 679
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("cannot create capabilities for libxenlight"));
J
Jim Fehlig 已提交
680 681 682
        goto error;
    }

683
    if (!(libxl_driver->xmlopt = libxlCreateXMLConf()))
684
        goto error;
J
Jim Fehlig 已提交
685

J
Jim Fehlig 已提交
686 687 688 689
    /* Add Domain-0 */
    if (libxlAddDom0(libxl_driver) < 0)
        goto error;

J
Jim Fehlig 已提交
690
    /* Load running domains first. */
691
    if (virDomainObjListLoadAllConfigs(libxl_driver->domains,
692 693
                                       cfg->stateDir,
                                       cfg->autostartDir,
694
                                       1,
695
                                       cfg->caps,
696
                                       libxl_driver->xmlopt,
697
                                       NULL, NULL) < 0)
J
Jim Fehlig 已提交
698 699 700 701 702
        goto error;

    libxlReconnectDomains(libxl_driver);

    /* Then inactive persistent configs */
703
    if (virDomainObjListLoadAllConfigs(libxl_driver->domains,
704 705
                                       cfg->configDir,
                                       cfg->autostartDir,
706
                                       0,
707
                                       cfg->caps,
708
                                       libxl_driver->xmlopt,
709
                                       NULL, NULL) < 0)
J
Jim Fehlig 已提交
710 711
        goto error;

712 713
    virDomainObjListForEach(libxl_driver->domains, libxlDomainManagedSaveLoad,
                            libxl_driver);
714

J
Jim Fehlig 已提交
715 716
    return 0;

717
 error:
718
    VIR_FREE(driverConf);
719
    libxlStateCleanup();
720
    return -1;
J
Jim Fehlig 已提交
721 722
}

723 724 725 726 727 728 729 730 731 732
static void
libxlStateAutoStart(void)
{
    if (!libxl_driver)
        return;

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

J
Jim Fehlig 已提交
733
static int
734
libxlStateReload(void)
J
Jim Fehlig 已提交
735
{
736 737
    libxlDriverConfigPtr cfg;

J
Jim Fehlig 已提交
738 739 740
    if (!libxl_driver)
        return 0;

741 742
    cfg = libxlDriverConfigGet(libxl_driver);

743
    virDomainObjListLoadAllConfigs(libxl_driver->domains,
744 745
                                   cfg->configDir,
                                   cfg->autostartDir,
746
                                   1,
747
                                   cfg->caps,
748
                                   libxl_driver->xmlopt,
749 750
                                   NULL, libxl_driver);

751 752
    virDomainObjListForEach(libxl_driver->domains, libxlAutostartDomain,
                            libxl_driver);
753

754
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
755 756 757 758 759
    return 0;
}


static virDrvOpenStatus
760 761 762
libxlConnectOpen(virConnectPtr conn,
                 virConnectAuthPtr auth ATTRIBUTE_UNUSED,
                 unsigned int flags)
J
Jim Fehlig 已提交
763
{
E
Eric Blake 已提交
764 765
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

J
Jim Fehlig 已提交
766 767 768 769
    if (conn->uri == NULL) {
        if (libxl_driver == NULL)
            return VIR_DRV_OPEN_DECLINED;

770
        if (!(conn->uri = virURIParse("xen:///")))
J
Jim Fehlig 已提交
771 772 773 774 775 776 777 778 779 780 781 782
            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) {
783 784
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("libxenlight state driver is not active"));
J
Jim Fehlig 已提交
785 786 787 788 789 790 791 792
            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")) {
793 794 795
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("unexpected Xen URI path '%s', try xen:///"),
                           NULLSTR(conn->uri->path));
J
Jim Fehlig 已提交
796 797 798 799
            return VIR_DRV_OPEN_ERROR;
        }
    }

800 801 802
    if (virConnectOpenEnsureACL(conn) < 0)
        return VIR_DRV_OPEN_ERROR;

J
Jim Fehlig 已提交
803 804 805 806 807 808
    conn->privateData = libxl_driver;

    return VIR_DRV_OPEN_SUCCESS;
};

static int
809
libxlConnectClose(virConnectPtr conn ATTRIBUTE_UNUSED)
J
Jim Fehlig 已提交
810 811 812 813 814 815
{
    conn->privateData = NULL;
    return 0;
}

static const char *
816
libxlConnectGetType(virConnectPtr conn)
J
Jim Fehlig 已提交
817
{
818 819 820
    if (virConnectGetTypeEnsureACL(conn) < 0)
        return NULL;

J
Jim Fehlig 已提交
821
    return "Xen";
J
Jim Fehlig 已提交
822 823 824
}

static int
825
libxlConnectGetVersion(virConnectPtr conn, unsigned long *version)
J
Jim Fehlig 已提交
826 827
{
    libxlDriverPrivatePtr driver = conn->privateData;
828
    libxlDriverConfigPtr cfg;
J
Jim Fehlig 已提交
829

830 831 832
    if (virConnectGetVersionEnsureACL(conn) < 0)
        return 0;

833 834 835
    cfg = libxlDriverConfigGet(driver);
    *version = cfg->version;
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
836 837 838
    return 0;
}

839

840
static char *libxlConnectGetHostname(virConnectPtr conn)
841
{
842 843 844
    if (virConnectGetHostnameEnsureACL(conn) < 0)
        return NULL;

845 846 847
    return virGetHostname();
}

848 849 850 851 852 853 854 855
static char *
libxlConnectGetSysinfo(virConnectPtr conn, unsigned int flags)
{
    libxlDriverPrivatePtr driver = conn->privateData;
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    virCheckFlags(0, NULL);

856 857 858
    if (virConnectGetSysinfoEnsureACL(conn) < 0)
        return NULL;

859 860 861 862 863 864 865 866
    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;
867
    if (virBufferCheckError(&buf) < 0)
868 869 870
        return NULL;
    return virBufferContentAndReset(&buf);
}
871

J
Jim Fehlig 已提交
872
static int
873
libxlConnectGetMaxVcpus(virConnectPtr conn, const char *type ATTRIBUTE_UNUSED)
J
Jim Fehlig 已提交
874 875 876
{
    int ret;
    libxlDriverPrivatePtr driver = conn->privateData;
877
    libxlDriverConfigPtr cfg;
J
Jim Fehlig 已提交
878

879 880 881
    if (virConnectGetMaxVcpusEnsureACL(conn) < 0)
        return -1;

882 883
    cfg = libxlDriverConfigGet(driver);
    ret = libxl_get_max_cpus(cfg->ctx);
884 885 886 887 888
    /* 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)
889
        ret = -1;
J
Jim Fehlig 已提交
890

891
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
892 893 894 895 896 897
    return ret;
}

static int
libxlNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info)
{
898 899 900
    if (virNodeGetInfoEnsureACL(conn) < 0)
        return -1;

901
    return libxlDriverNodeGetInfo(conn->privateData, info);
J
Jim Fehlig 已提交
902 903 904
}

static char *
905
libxlConnectGetCapabilities(virConnectPtr conn)
J
Jim Fehlig 已提交
906 907 908
{
    libxlDriverPrivatePtr driver = conn->privateData;
    char *xml;
909
    libxlDriverConfigPtr cfg;
J
Jim Fehlig 已提交
910

911 912 913
    if (virConnectGetCapabilitiesEnsureACL(conn) < 0)
        return NULL;

914
    cfg = libxlDriverConfigGet(driver);
915
    xml = virCapabilitiesFormatXML(cfg->caps);
J
Jim Fehlig 已提交
916

917
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
918 919 920 921
    return xml;
}

static int
922
libxlConnectListDomains(virConnectPtr conn, int *ids, int nids)
J
Jim Fehlig 已提交
923 924 925 926
{
    libxlDriverPrivatePtr driver = conn->privateData;
    int n;

927 928 929
    if (virConnectListDomainsEnsureACL(conn) < 0)
        return -1;

930 931
    n = virDomainObjListGetActiveIDs(driver->domains, ids, nids,
                                     virConnectListDomainsCheckACL, conn);
J
Jim Fehlig 已提交
932 933 934 935 936

    return n;
}

static int
937
libxlConnectNumOfDomains(virConnectPtr conn)
J
Jim Fehlig 已提交
938 939 940 941
{
    libxlDriverPrivatePtr driver = conn->privateData;
    int n;

942 943 944
    if (virConnectNumOfDomainsEnsureACL(conn) < 0)
        return -1;

945 946
    n = virDomainObjListNumOfDomains(driver->domains, true,
                                     virConnectNumOfDomainsCheckACL, conn);
J
Jim Fehlig 已提交
947 948 949 950 951 952 953 954 955 956 957 958

    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;
959
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
960
    unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;
J
Jim Fehlig 已提交
961

962 963 964 965 966
    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 已提交
967

968
    if (!(def = virDomainDefParseString(xml, cfg->caps, driver->xmlopt,
969
                                        parse_flags)))
J
Jim Fehlig 已提交
970 971
        goto cleanup;

972 973 974
    if (virDomainCreateXMLEnsureACL(conn, def) < 0)
        goto cleanup;

975
    if (!(vm = virDomainObjListAdd(driver->domains, def,
976
                                   driver->xmlopt,
977
                                   VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
978 979
                                   VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                   NULL)))
J
Jim Fehlig 已提交
980 981 982
        goto cleanup;
    def = NULL;

983 984 985 986 987 988 989 990
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0) {
        if (!vm->persistent) {
            virDomainObjListRemove(driver->domains, vm);
            vm = NULL;
        }
        goto cleanup;
    }

991
    if (libxlDomainStart(driver, vm, (flags & VIR_DOMAIN_START_PAUSED) != 0,
992
                     -1) < 0) {
993 994 995
        if (!vm->persistent) {
            virDomainObjListRemove(driver->domains, vm);
            vm = NULL;
996
            goto cleanup;
997
        }
998
        goto endjob;
J
Jim Fehlig 已提交
999 1000 1001 1002 1003 1004
    }

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

1005 1006 1007 1008
 endjob:
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

1009
 cleanup:
J
Jim Fehlig 已提交
1010 1011
    virDomainDefFree(def);
    if (vm)
1012
        virObjectUnlock(vm);
1013
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
1014 1015 1016 1017 1018 1019 1020 1021 1022 1023
    return dom;
}

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

1024
    vm = virDomainObjListFindByID(driver->domains, id);
J
Jim Fehlig 已提交
1025
    if (!vm) {
1026
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
J
Jim Fehlig 已提交
1027 1028 1029
        goto cleanup;
    }

1030 1031 1032
    if (virDomainLookupByIDEnsureACL(conn, vm->def) < 0)
        goto cleanup;

J
Jim Fehlig 已提交
1033 1034 1035 1036
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
    if (dom)
        dom->id = vm->def->id;

1037
 cleanup:
J
Jim Fehlig 已提交
1038
    if (vm)
1039
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
1040 1041 1042 1043 1044 1045 1046 1047 1048 1049
    return dom;
}

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

1050
    vm = virDomainObjListFindByUUID(driver->domains, uuid);
J
Jim Fehlig 已提交
1051
    if (!vm) {
1052
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
J
Jim Fehlig 已提交
1053 1054 1055
        goto cleanup;
    }

1056 1057 1058
    if (virDomainLookupByUUIDEnsureACL(conn, vm->def) < 0)
        goto cleanup;

J
Jim Fehlig 已提交
1059 1060 1061 1062
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
    if (dom)
        dom->id = vm->def->id;

1063
 cleanup:
J
Jim Fehlig 已提交
1064
    if (vm)
1065
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
1066 1067 1068 1069 1070 1071 1072 1073 1074 1075
    return dom;
}

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

1076
    vm = virDomainObjListFindByName(driver->domains, name);
J
Jim Fehlig 已提交
1077
    if (!vm) {
1078
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
J
Jim Fehlig 已提交
1079 1080 1081
        goto cleanup;
    }

1082 1083 1084
    if (virDomainLookupByNameEnsureACL(conn, vm->def) < 0)
        goto cleanup;

J
Jim Fehlig 已提交
1085 1086 1087 1088
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
    if (dom)
        dom->id = vm->def->id;

1089
 cleanup:
1090
    virDomainObjEndAPI(&vm);
J
Jim Fehlig 已提交
1091 1092 1093
    return dom;
}

1094 1095 1096 1097
static int
libxlDomainSuspend(virDomainPtr dom)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
1098
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
1099
    virDomainObjPtr vm;
1100
    virObjectEventPtr event = NULL;
1101 1102
    int ret = -1;

J
Jim Fehlig 已提交
1103
    if (!(vm = libxlDomObjFromDomain(dom)))
1104
        goto cleanup;
1105

J
Jim Fehlig 已提交
1106 1107
    LIBXL_CHECK_DOM0_GOTO(vm->def->name, cleanup);

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

1111 1112 1113
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

1114
    if (!virDomainObjIsActive(vm)) {
1115
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
1116
        goto endjob;
1117 1118
    }

J
Jiri Denemark 已提交
1119
    if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_PAUSED) {
J
Jim Fehlig 已提交
1120
        if (libxl_domain_pause(cfg->ctx, vm->def->id) != 0) {
1121 1122
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Failed to suspend domain '%d' with libxenlight"),
1123
                           vm->def->id);
1124
            goto endjob;
1125 1126
        }

J
Jiri Denemark 已提交
1127
        virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER);
1128

1129
        event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_SUSPENDED,
1130 1131 1132
                                         VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
    }

1133
    if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
1134
        goto endjob;
1135 1136 1137

    ret = 0;

1138
 endjob:
1139 1140 1141
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

1142
 cleanup:
1143
    if (vm)
1144
        virObjectUnlock(vm);
1145
    if (event)
1146
        libxlDomainEventQueue(driver, event);
1147
    virObjectUnref(cfg);
1148 1149 1150 1151 1152 1153 1154 1155
    return ret;
}


static int
libxlDomainResume(virDomainPtr dom)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
1156
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
1157
    virDomainObjPtr vm;
1158
    virObjectEventPtr event = NULL;
1159 1160
    int ret = -1;

J
Jim Fehlig 已提交
1161
    if (!(vm = libxlDomObjFromDomain(dom)))
1162 1163
        goto cleanup;

J
Jim Fehlig 已提交
1164 1165
    LIBXL_CHECK_DOM0_GOTO(vm->def->name, cleanup);

1166 1167 1168
    if (virDomainResumeEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

1169 1170 1171
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

1172
    if (!virDomainObjIsActive(vm)) {
1173
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
1174
        goto endjob;
1175 1176
    }

J
Jiri Denemark 已提交
1177
    if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
J
Jim Fehlig 已提交
1178
        if (libxl_domain_unpause(cfg->ctx, vm->def->id) != 0) {
1179 1180
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Failed to resume domain '%d' with libxenlight"),
1181
                           vm->def->id);
1182
            goto endjob;
1183 1184
        }

J
Jiri Denemark 已提交
1185 1186
        virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
                             VIR_DOMAIN_RUNNING_UNPAUSED);
1187

1188
        event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_RESUMED,
1189 1190 1191
                                         VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
    }

1192
    if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
1193
        goto endjob;
1194 1195 1196

    ret = 0;

1197
 endjob:
1198 1199 1200
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

1201
 cleanup:
1202
    if (vm)
1203
        virObjectUnlock(vm);
1204
    if (event)
1205
        libxlDomainEventQueue(driver, event);
1206
    virObjectUnref(cfg);
1207 1208 1209
    return ret;
}

J
Jim Fehlig 已提交
1210
static int
1211
libxlDomainShutdownFlags(virDomainPtr dom, unsigned int flags)
J
Jim Fehlig 已提交
1212
{
J
Jim Fehlig 已提交
1213 1214
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
J
Jim Fehlig 已提交
1215 1216 1217
    virDomainObjPtr vm;
    int ret = -1;

1218 1219 1220 1221 1222
    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;
1223

J
Jim Fehlig 已提交
1224
    if (!(vm = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
1225 1226
        goto cleanup;

J
Jim Fehlig 已提交
1227 1228
    LIBXL_CHECK_DOM0_GOTO(vm->def->name, cleanup);

1229
    if (virDomainShutdownFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
1230 1231
        goto cleanup;

J
Jim Fehlig 已提交
1232
    if (!virDomainObjIsActive(vm)) {
1233 1234
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("Domain is not running"));
J
Jim Fehlig 已提交
1235 1236 1237
        goto cleanup;
    }

1238
    if (flags & VIR_DOMAIN_SHUTDOWN_PARAVIRT) {
J
Jim Fehlig 已提交
1239
        ret = libxl_domain_shutdown(cfg->ctx, vm->def->id);
1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253
        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 已提交
1254
        ret = libxl_send_trigger(cfg->ctx, vm->def->id,
1255 1256 1257 1258
                                 LIBXL_TRIGGER_POWER, 0);
        if (ret == 0)
            goto cleanup;

1259 1260
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to shutdown domain '%d' with libxenlight"),
1261
                       vm->def->id);
1262
        ret = -1;
J
Jim Fehlig 已提交
1263 1264
    }

1265
 cleanup:
J
Jim Fehlig 已提交
1266
    if (vm)
1267
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
1268
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
1269 1270 1271
    return ret;
}

1272 1273 1274 1275 1276 1277 1278
static int
libxlDomainShutdown(virDomainPtr dom)
{
    return libxlDomainShutdownFlags(dom, 0);
}


J
Jim Fehlig 已提交
1279
static int
E
Eric Blake 已提交
1280
libxlDomainReboot(virDomainPtr dom, unsigned int flags)
J
Jim Fehlig 已提交
1281
{
J
Jim Fehlig 已提交
1282 1283
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
J
Jim Fehlig 已提交
1284 1285 1286
    virDomainObjPtr vm;
    int ret = -1;

J
Jim Fehlig 已提交
1287 1288 1289
    virCheckFlags(VIR_DOMAIN_REBOOT_PARAVIRT, -1);
    if (flags == 0)
        flags = VIR_DOMAIN_REBOOT_PARAVIRT;
E
Eric Blake 已提交
1290

J
Jim Fehlig 已提交
1291
    if (!(vm = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
1292 1293
        goto cleanup;

J
Jim Fehlig 已提交
1294 1295
    LIBXL_CHECK_DOM0_GOTO(vm->def->name, cleanup);

1296
    if (virDomainRebootEnsureACL(dom->conn, vm->def, flags) < 0)
1297 1298
        goto cleanup;

J
Jim Fehlig 已提交
1299
    if (!virDomainObjIsActive(vm)) {
1300 1301
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("Domain is not running"));
J
Jim Fehlig 已提交
1302 1303 1304
        goto cleanup;
    }

J
Jim Fehlig 已提交
1305
    if (flags & VIR_DOMAIN_REBOOT_PARAVIRT) {
J
Jim Fehlig 已提交
1306
        ret = libxl_domain_reboot(cfg->ctx, vm->def->id);
J
Jim Fehlig 已提交
1307 1308 1309
        if (ret == 0)
            goto cleanup;

1310 1311
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to reboot domain '%d' with libxenlight"),
1312
                       vm->def->id);
J
Jim Fehlig 已提交
1313
        ret = -1;
J
Jim Fehlig 已提交
1314 1315
    }

1316
 cleanup:
J
Jim Fehlig 已提交
1317
    if (vm)
1318
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
1319
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
1320 1321 1322 1323
    return ret;
}

static int
1324 1325
libxlDomainDestroyFlags(virDomainPtr dom,
                        unsigned int flags)
J
Jim Fehlig 已提交
1326 1327
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
J
Jim Fehlig 已提交
1328
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
J
Jim Fehlig 已提交
1329 1330
    virDomainObjPtr vm;
    int ret = -1;
1331
    virObjectEventPtr event = NULL;
J
Jim Fehlig 已提交
1332

1333 1334
    virCheckFlags(0, -1);

J
Jim Fehlig 已提交
1335
    if (!(vm = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
1336 1337
        goto cleanup;

J
Jim Fehlig 已提交
1338 1339
    LIBXL_CHECK_DOM0_GOTO(vm->def->name, cleanup);

1340 1341 1342
    if (virDomainDestroyFlagsEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

1343 1344 1345
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

J
Jim Fehlig 已提交
1346
    if (!virDomainObjIsActive(vm)) {
1347 1348
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("Domain is not running"));
1349
        goto endjob;
J
Jim Fehlig 已提交
1350 1351
    }

1352
    if (libxlDomainDestroyInternal(driver, vm) < 0) {
1353
        virReportError(VIR_ERR_INTERNAL_ERROR,
1354
                       _("Failed to destroy domain '%d'"), vm->def->id);
1355
        goto endjob;
J
Jim Fehlig 已提交
1356 1357
    }

1358 1359 1360 1361 1362 1363 1364
    virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF,
                         VIR_DOMAIN_SHUTOFF_DESTROYED);

    event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_DESTROYED);

    libxlDomainCleanup(driver, vm);
1365 1366
    if (!vm->persistent)
        virDomainObjListRemove(driver->domains, vm);
J
Jim Fehlig 已提交
1367 1368 1369

    ret = 0;

1370 1371 1372 1373
 endjob:
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

1374
 cleanup:
J
Jim Fehlig 已提交
1375
    if (vm)
1376
        virObjectUnlock(vm);
1377 1378
    if (event)
        libxlDomainEventQueue(driver, event);
J
Jim Fehlig 已提交
1379
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
1380 1381 1382
    return ret;
}

1383 1384 1385 1386 1387 1388
static int
libxlDomainDestroy(virDomainPtr dom)
{
    return libxlDomainDestroyFlags(dom, 0);
}

1389 1390 1391 1392 1393 1394
static char *
libxlDomainGetOSType(virDomainPtr dom)
{
    virDomainObjPtr vm;
    char *type = NULL;

J
Jim Fehlig 已提交
1395
    if (!(vm = libxlDomObjFromDomain(dom)))
1396 1397
        goto cleanup;

1398 1399 1400
    if (virDomainGetOSTypeEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

1401
    if (VIR_STRDUP(type, virDomainOSTypeToString(vm->def->os.type)) < 0)
1402
        goto cleanup;
1403

1404
 cleanup:
1405
    if (vm)
1406
        virObjectUnlock(vm);
1407 1408 1409
    return type;
}

1410
static unsigned long long
1411 1412 1413
libxlDomainGetMaxMemory(virDomainPtr dom)
{
    virDomainObjPtr vm;
1414
    unsigned long long ret = 0;
1415

J
Jim Fehlig 已提交
1416
    if (!(vm = libxlDomObjFromDomain(dom)))
1417
        goto cleanup;
1418 1419 1420 1421

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

1422
    ret = virDomainDefGetMemoryActual(vm->def);
1423

1424
 cleanup:
1425
    if (vm)
1426
        virObjectUnlock(vm);
1427 1428 1429 1430
    return ret;
}

static int
1431
libxlDomainSetMemoryFlags(virDomainPtr dom, unsigned long newmem,
1432 1433 1434
                          unsigned int flags)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
1435
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
1436
    virDomainObjPtr vm;
1437 1438
    virDomainDefPtr persistentDef = NULL;
    bool isActive;
1439 1440 1441
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_MEM_LIVE |
1442 1443
                  VIR_DOMAIN_MEM_CONFIG |
                  VIR_DOMAIN_MEM_MAXIMUM, -1);
1444

J
Jim Fehlig 已提交
1445
    if (!(vm = libxlDomObjFromDomain(dom)))
1446 1447
        goto cleanup;

1448 1449 1450
    if (virDomainSetMemoryFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
        goto cleanup;

1451 1452 1453
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466
    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;
1467 1468
    }

1469
    if (!isActive && (flags & VIR_DOMAIN_MEM_LIVE)) {
1470 1471
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("cannot set memory on an inactive domain"));
1472
        goto endjob;
1473 1474 1475 1476
    }

    if (flags & VIR_DOMAIN_MEM_CONFIG) {
        if (!vm->persistent) {
1477 1478
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                           _("cannot change persistent config of a transient domain"));
1479
            goto endjob;
1480
        }
1481
        if (!(persistentDef = virDomainObjGetPersistentDef(cfg->caps,
1482
                                                           driver->xmlopt,
1483
                                                           vm)))
1484
            goto endjob;
1485 1486
    }

1487 1488
    if (flags & VIR_DOMAIN_MEM_MAXIMUM) {
        /* resize the maximum memory */
1489

1490
        if (flags & VIR_DOMAIN_MEM_LIVE) {
J
Jim Fehlig 已提交
1491
            if (libxl_domain_setmaxmem(cfg->ctx, vm->def->id, newmem) < 0) {
1492 1493
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("Failed to set maximum memory for domain '%d'"
1494
                                 " with libxenlight"), vm->def->id);
1495
                goto endjob;
1496 1497 1498 1499 1500 1501
            }
        }

        if (flags & VIR_DOMAIN_MEM_CONFIG) {
            /* Help clang 2.8 decipher the logic flow.  */
            sa_assert(persistentDef);
1502
            virDomainDefSetMemoryTotal(persistentDef, newmem);
1503 1504
            if (persistentDef->mem.cur_balloon > newmem)
                persistentDef->mem.cur_balloon = newmem;
1505
            ret = virDomainSaveConfig(cfg->configDir, persistentDef);
1506
            goto endjob;
1507 1508
        }

1509 1510
    } else {
        /* resize the current memory */
1511

1512
        if (newmem > virDomainDefGetMemoryActual(vm->def)) {
1513 1514
            virReportError(VIR_ERR_INVALID_ARG, "%s",
                           _("cannot set memory higher than max memory"));
1515
            goto endjob;
1516 1517 1518
        }

        if (flags & VIR_DOMAIN_MEM_LIVE) {
1519 1520 1521 1522
            int res;

            /* Unlock virDomainObj while ballooning memory */
            virObjectUnlock(vm);
J
Jim Fehlig 已提交
1523
            res = libxl_set_memory_target(cfg->ctx, vm->def->id, newmem, 0,
1524 1525 1526
                                          /* force */ 1);
            virObjectLock(vm);
            if (res < 0) {
1527 1528
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("Failed to set memory for domain '%d'"
1529
                                 " with libxenlight"), vm->def->id);
1530
                goto endjob;
1531 1532 1533 1534 1535 1536
            }
        }

        if (flags & VIR_DOMAIN_MEM_CONFIG) {
            sa_assert(persistentDef);
            persistentDef->mem.cur_balloon = newmem;
1537
            ret = virDomainSaveConfig(cfg->configDir, persistentDef);
1538
            goto endjob;
1539
        }
1540 1541
    }

1542 1543
    ret = 0;

1544
 endjob:
1545 1546 1547
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

1548
 cleanup:
1549
    if (vm)
1550
        virObjectUnlock(vm);
1551
    virObjectUnref(cfg);
1552 1553 1554 1555 1556 1557 1558 1559 1560
    return ret;
}

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

1561 1562 1563 1564 1565 1566
static int
libxlDomainSetMaxMemory(virDomainPtr dom, unsigned long memory)
{
    return libxlDomainSetMemoryFlags(dom, memory, VIR_DOMAIN_MEM_MAXIMUM);
}

J
Jim Fehlig 已提交
1567 1568 1569
static int
libxlDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info)
{
J
Jim Fehlig 已提交
1570 1571
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
J
Jim Fehlig 已提交
1572
    virDomainObjPtr vm;
1573
    libxl_dominfo d_info;
J
Jim Fehlig 已提交
1574 1575
    int ret = -1;

J
Jim Fehlig 已提交
1576
    if (!(vm = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
1577 1578
        goto cleanup;

1579 1580 1581
    if (virDomainGetInfoEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

1582 1583 1584
    if (!virDomainObjIsActive(vm)) {
        info->cpuTime = 0;
        info->memory = vm->def->mem.cur_balloon;
1585
        info->maxMem = virDomainDefGetMemoryActual(vm->def);
1586
    } else {
J
Jim Fehlig 已提交
1587
        if (libxl_domain_info(cfg->ctx, &d_info, vm->def->id) != 0) {
1588
            virReportError(VIR_ERR_INTERNAL_ERROR,
1589 1590
                           _("libxl_domain_info failed for domain '%d'"),
                           vm->def->id);
1591 1592 1593 1594
            goto cleanup;
        }
        info->cpuTime = d_info.cpu_time;
        info->memory = d_info.current_memkb;
1595
        info->maxMem = d_info.max_memkb;
1596 1597
    }

J
Jiri Denemark 已提交
1598
    info->state = virDomainObjGetState(vm, NULL);
J
Jim Fehlig 已提交
1599 1600 1601
    info->nrVirtCpu = vm->def->vcpus;
    ret = 0;

1602
 cleanup:
J
Jim Fehlig 已提交
1603
    if (vm)
1604
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
1605
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
1606 1607 1608
    return ret;
}

1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619
static int
libxlDomainGetState(virDomainPtr dom,
                    int *state,
                    int *reason,
                    unsigned int flags)
{
    virDomainObjPtr vm;
    int ret = -1;

    virCheckFlags(0, -1);

J
Jim Fehlig 已提交
1620
    if (!(vm = libxlDomObjFromDomain(dom)))
1621 1622
        goto cleanup;

1623 1624 1625
    if (virDomainGetStateEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

J
Jiri Denemark 已提交
1626
    *state = virDomainObjGetState(vm, reason);
1627 1628
    ret = 0;

1629
 cleanup:
1630
    if (vm)
1631
        virObjectUnlock(vm);
1632 1633 1634
    return ret;
}

1635 1636 1637
/*
 * virDomainObjPtr must be locked on invocation
 */
1638
static int
1639 1640
libxlDoDomainSave(libxlDriverPrivatePtr driver, virDomainObjPtr vm,
                  const char *to)
1641
{
J
Jim Fehlig 已提交
1642
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
1643
    libxlSavefileHeader hdr;
1644
    virObjectEventPtr event = NULL;
1645 1646
    char *xml = NULL;
    uint32_t xml_len;
1647
    int fd = -1;
1648 1649 1650
    int ret = -1;

    if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
1651 1652 1653
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("Domain '%d' has to be running because libxenlight will"
                         " suspend it"), vm->def->id);
1654 1655 1656 1657
        goto cleanup;
    }

    if ((fd = virFileOpenAs(to, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR,
L
Laine Stump 已提交
1658
                            -1, -1, 0)) < 0) {
1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673
        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)) {
1674 1675
        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                       _("Failed to write save file header"));
1676 1677 1678 1679
        goto cleanup;
    }

    if (safewrite(fd, xml, xml_len) != xml_len) {
1680 1681
        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                       _("Failed to write xml description"));
1682 1683 1684
        goto cleanup;
    }

1685 1686
    /* Unlock virDomainObj while saving domain */
    virObjectUnlock(vm);
J
Jim Fehlig 已提交
1687
    ret = libxl_domain_suspend(cfg->ctx, vm->def->id, fd, 0, NULL);
1688 1689 1690
    virObjectLock(vm);

    if (ret != 0) {
1691 1692 1693
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to save domain '%d' with libxenlight"),
                       vm->def->id);
1694
        ret = -1;
1695 1696 1697
        goto cleanup;
    }

1698 1699 1700
    virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF,
                         VIR_DOMAIN_SHUTOFF_SAVED);

1701
    event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
1702 1703
                                         VIR_DOMAIN_EVENT_STOPPED_SAVED);

1704
    if (libxlDomainDestroyInternal(driver, vm) < 0) {
1705 1706
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to destroy domain '%d'"), vm->def->id);
1707 1708 1709
        goto cleanup;
    }

1710
    libxlDomainCleanup(driver, vm);
1711
    vm->hasManagedSave = true;
1712 1713
    ret = 0;

1714
 cleanup:
1715 1716 1717 1718 1719
    VIR_FREE(xml);
    if (VIR_CLOSE(fd) < 0)
        virReportSystemError(errno, "%s", _("cannot close file"));
    if (event)
        libxlDomainEventQueue(driver, event);
J
Jim Fehlig 已提交
1720
    virObjectUnref(cfg);
1721 1722 1723 1724
    return ret;
}

static int
1725 1726
libxlDomainSaveFlags(virDomainPtr dom, const char *to, const char *dxml,
                     unsigned int flags)
1727
{
1728 1729
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    virDomainObjPtr vm;
1730
    int ret = -1;
1731
    bool remove_dom = false;
1732

1733 1734 1735 1736 1737
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
    virReportUnsupportedError();
    return -1;
#endif

1738 1739
    virCheckFlags(0, -1);
    if (dxml) {
1740 1741
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
1742 1743 1744
        return -1;
    }

J
Jim Fehlig 已提交
1745
    if (!(vm = libxlDomObjFromDomain(dom)))
1746 1747
        goto cleanup;

J
Jim Fehlig 已提交
1748 1749
    LIBXL_CHECK_DOM0_GOTO(vm->def->name, cleanup);

1750 1751 1752
    if (virDomainSaveFlagsEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

1753 1754 1755
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

1756
    if (!virDomainObjIsActive(vm)) {
1757
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
1758
        goto endjob;
1759 1760
    }

1761
    if (libxlDoDomainSave(driver, vm, to) < 0)
1762
        goto endjob;
1763

1764 1765
    if (!vm->persistent)
        remove_dom = true;
1766 1767

    ret = 0;
1768

1769
 endjob:
1770 1771 1772
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

1773
 cleanup:
1774 1775 1776 1777
    if (remove_dom && vm) {
        virDomainObjListRemove(driver->domains, vm);
        vm = NULL;
    }
1778
    if (vm)
1779
        virObjectUnlock(vm);
1780 1781
    return ret;
}
1782

1783
static int
1784 1785 1786 1787 1788 1789 1790 1791
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)
1792 1793
{
    libxlDriverPrivatePtr driver = conn->privateData;
1794
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
1795 1796 1797 1798 1799
    virDomainObjPtr vm = NULL;
    virDomainDefPtr def = NULL;
    libxlSavefileHeader hdr;
    int fd = -1;
    int ret = -1;
1800

1801 1802 1803 1804 1805
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
    virReportUnsupportedError();
    return -1;
#endif

1806
    virCheckFlags(VIR_DOMAIN_SAVE_PAUSED, -1);
1807
    if (dxml) {
1808 1809
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
1810 1811 1812
        return -1;
    }

1813
    fd = libxlDomainSaveImageOpen(driver, cfg, from, &def, &hdr);
1814
    if (fd < 0)
1815
        goto cleanup;
1816

1817
    if (virDomainRestoreFlagsEnsureACL(conn, def) < 0)
1818
        goto cleanup;
1819

1820
    if (!(vm = virDomainObjListAdd(driver->domains, def,
1821
                                   driver->xmlopt,
1822 1823 1824
                                   VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
                                   VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                   NULL)))
1825
        goto cleanup;
1826 1827 1828

    def = NULL;

1829 1830 1831 1832 1833 1834 1835 1836
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0) {
        if (!vm->persistent) {
            virDomainObjListRemove(driver->domains, vm);
            vm = NULL;
        }
        goto cleanup;
    }

1837
    ret = libxlDomainStart(driver, vm, (flags & VIR_DOMAIN_SAVE_PAUSED) != 0, fd);
1838
    if (ret < 0 && !vm->persistent)
1839
        virDomainObjListRemove(driver->domains, vm);
1840 1841

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

1844
 cleanup:
1845 1846
    if (VIR_CLOSE(fd) < 0)
        virReportSystemError(errno, "%s", _("cannot close file"));
1847 1848
    virDomainDefFree(def);
    if (vm)
1849
        virObjectUnlock(vm);
1850
    virObjectUnref(cfg);
1851 1852 1853
    return ret;
}

1854 1855 1856 1857 1858 1859
static int
libxlDomainRestore(virConnectPtr conn, const char *from)
{
    return libxlDomainRestoreFlags(conn, from, NULL, 0);
}

1860
static int
1861
libxlDomainCoreDump(virDomainPtr dom, const char *to, unsigned int flags)
1862 1863
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
J
Jim Fehlig 已提交
1864
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
1865
    virDomainObjPtr vm;
1866
    virObjectEventPtr event = NULL;
1867
    bool remove_dom = false;
1868 1869 1870 1871 1872
    bool paused = false;
    int ret = -1;

    virCheckFlags(VIR_DUMP_LIVE | VIR_DUMP_CRASH, -1);

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

J
Jim Fehlig 已提交
1876 1877
    LIBXL_CHECK_DOM0_GOTO(vm->def->name, cleanup);

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

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

1884
    if (!virDomainObjIsActive(vm)) {
1885
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
1886
        goto endjob;
1887 1888 1889 1890
    }

    if (!(flags & VIR_DUMP_LIVE) &&
        virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
J
Jim Fehlig 已提交
1891
        if (libxl_domain_pause(cfg->ctx, vm->def->id) != 0) {
1892 1893 1894
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Before dumping core, failed to suspend domain '%d'"
                             " with libxenlight"),
1895
                           vm->def->id);
1896
            goto endjob;
1897 1898 1899 1900 1901
        }
        virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_DUMP);
        paused = true;
    }

1902 1903
    /* Unlock virDomainObj while dumping core */
    virObjectUnlock(vm);
J
Jim Fehlig 已提交
1904
    ret = libxl_domain_core_dump(cfg->ctx, vm->def->id, to, NULL);
1905 1906
    virObjectLock(vm);
    if (ret != 0) {
1907 1908
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to dump core of domain '%d' with libxenlight"),
1909
                       vm->def->id);
1910 1911
        ret = -1;
        goto unpause;
1912 1913 1914
    }

    if (flags & VIR_DUMP_CRASH) {
1915
        if (libxlDomainDestroyInternal(driver, vm) < 0) {
1916
            virReportError(VIR_ERR_INTERNAL_ERROR,
1917
                           _("Failed to destroy domain '%d'"), vm->def->id);
1918
            goto unpause;
1919 1920
        }

1921 1922 1923
        libxlDomainCleanup(driver, vm);
        virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF,
                             VIR_DOMAIN_SHUTOFF_CRASHED);
1924
        event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
1925
                                         VIR_DOMAIN_EVENT_STOPPED_CRASHED);
1926 1927
        if (!vm->persistent)
            remove_dom = true;
1928 1929 1930 1931
    }

    ret = 0;

1932
 unpause:
1933
    if (virDomainObjIsActive(vm) && paused) {
J
Jim Fehlig 已提交
1934
        if (libxl_domain_unpause(cfg->ctx, vm->def->id) != 0) {
1935 1936
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("After dumping core, failed to resume domain '%d' with"
1937
                             " libxenlight"), vm->def->id);
1938 1939 1940 1941 1942
        } else {
            virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
                                 VIR_DOMAIN_RUNNING_UNPAUSED);
        }
    }
1943

1944
 endjob:
1945 1946 1947
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

1948
 cleanup:
1949 1950 1951 1952
    if (remove_dom && vm) {
        virDomainObjListRemove(driver->domains, vm);
        vm = NULL;
    }
1953
    if (vm)
1954
        virObjectUnlock(vm);
1955
    if (event)
1956
        libxlDomainEventQueue(driver, event);
J
Jim Fehlig 已提交
1957
    virObjectUnref(cfg);
1958 1959 1960
    return ret;
}

1961 1962 1963 1964 1965 1966 1967
static int
libxlDomainManagedSave(virDomainPtr dom, unsigned int flags)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    virDomainObjPtr vm = NULL;
    char *name = NULL;
    int ret = -1;
1968
    bool remove_dom = false;
1969 1970 1971

    virCheckFlags(0, -1);

J
Jim Fehlig 已提交
1972
    if (!(vm = libxlDomObjFromDomain(dom)))
1973 1974
        goto cleanup;

J
Jim Fehlig 已提交
1975 1976
    LIBXL_CHECK_DOM0_GOTO(vm->def->name, cleanup);

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

1980 1981 1982
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

1983
    if (!virDomainObjIsActive(vm)) {
1984
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
1985
        goto endjob;
1986
    }
1987
    if (!vm->persistent) {
1988 1989
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("cannot do managed save for transient domain"));
1990
        goto endjob;
1991
    }
1992 1993 1994

    name = libxlDomainManagedSavePath(driver, vm);
    if (name == NULL)
1995
        goto endjob;
1996 1997 1998

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

1999
    if (libxlDoDomainSave(driver, vm, name) < 0)
2000
        goto endjob;
2001

2002 2003
    if (!vm->persistent)
        remove_dom = true;
2004 2005

    ret = 0;
2006

2007
 endjob:
2008 2009 2010
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

2011
 cleanup:
2012 2013 2014 2015
    if (remove_dom && vm) {
        virDomainObjListRemove(driver->domains, vm);
        vm = NULL;
    }
2016
    if (vm)
2017
        virObjectUnlock(vm);
2018 2019 2020 2021
    VIR_FREE(name);
    return ret;
}

2022 2023
static int
libxlDomainManagedSaveLoad(virDomainObjPtr vm,
2024 2025 2026 2027
                           void *opaque)
{
    libxlDriverPrivatePtr driver = opaque;
    char *name;
2028
    int ret = -1;
2029

2030
    virObjectLock(vm);
2031 2032 2033 2034 2035 2036

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

    vm->hasManagedSave = virFileExists(name);

2037
    ret = 0;
2038
 cleanup:
2039
    virObjectUnlock(vm);
2040
    VIR_FREE(name);
2041
    return ret;
2042 2043
}

2044 2045 2046 2047 2048 2049 2050 2051
static int
libxlDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    int ret = -1;

    virCheckFlags(0, -1);

J
Jim Fehlig 已提交
2052
    if (!(vm = libxlDomObjFromDomain(dom)))
2053 2054
        goto cleanup;

2055 2056 2057
    if (virDomainHasManagedSaveImageEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

2058
    ret = vm->hasManagedSave;
2059

2060
 cleanup:
2061
    if (vm)
2062
        virObjectUnlock(vm);
2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075
    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 已提交
2076
    if (!(vm = libxlDomObjFromDomain(dom)))
2077 2078
        goto cleanup;

2079 2080 2081
    if (virDomainManagedSaveRemoveEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

2082 2083 2084 2085 2086
    name = libxlDomainManagedSavePath(driver, vm);
    if (name == NULL)
        goto cleanup;

    ret = unlink(name);
2087
    vm->hasManagedSave = false;
2088

2089
 cleanup:
2090 2091
    VIR_FREE(name);
    if (vm)
2092
        virObjectUnlock(vm);
2093 2094 2095
    return ret;
}

2096 2097 2098 2099 2100
static int
libxlDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
                         unsigned int flags)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
2101
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
2102 2103
    virDomainDefPtr def;
    virDomainObjPtr vm;
J
Jim Fehlig 已提交
2104
    libxl_bitmap map;
2105 2106
    uint8_t *bitmask = NULL;
    unsigned int maplen;
2107 2108
    size_t i;
    unsigned int pos;
2109 2110 2111 2112 2113 2114 2115 2116 2117 2118 2119 2120
    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)) {
2121 2122
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid flag combination: (0x%x)"), flags);
2123 2124 2125 2126
        return -1;
    }

    if (!nvcpus) {
2127
        virReportError(VIR_ERR_INVALID_ARG, "%s", _("nvcpus is zero"));
2128 2129 2130
        return -1;
    }

J
Jim Fehlig 已提交
2131
    if (!(vm = libxlDomObjFromDomain(dom)))
2132 2133
        goto cleanup;

2134 2135 2136
    if (virDomainSetVcpusFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
        goto cleanup;

2137 2138 2139
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

2140
    if (!virDomainObjIsActive(vm) && (flags & VIR_DOMAIN_VCPU_LIVE)) {
2141 2142
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("cannot set vcpus on an inactive domain"));
2143
        goto endjob;
2144 2145 2146
    }

    if (!vm->persistent && (flags & VIR_DOMAIN_VCPU_CONFIG)) {
2147 2148
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("cannot change persistent config of a transient domain"));
2149
        goto endjob;
2150 2151
    }

2152
    if ((max = libxlConnectGetMaxVcpus(dom->conn, NULL)) < 0) {
2153 2154
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("could not determine max vcpus for the domain"));
2155
        goto endjob;
2156 2157
    }

2158
    if (!(flags & VIR_DOMAIN_VCPU_MAXIMUM) && vm->def->maxvcpus < max)
2159 2160 2161
        max = vm->def->maxvcpus;

    if (nvcpus > max) {
2162 2163 2164
        virReportError(VIR_ERR_INVALID_ARG,
                       _("requested vcpus is greater than max allowable"
                         " vcpus for the domain: %d > %d"), nvcpus, max);
2165
        goto endjob;
2166 2167
    }

2168
    if (!(def = virDomainObjGetPersistentDef(cfg->caps, driver->xmlopt, vm)))
2169
        goto endjob;
2170

E
Eric Blake 已提交
2171
    maplen = VIR_CPU_MAPLEN(nvcpus);
2172
    if (VIR_ALLOC_N(bitmask, maplen) < 0)
2173
        goto endjob;
2174 2175

    for (i = 0; i < nvcpus; ++i) {
E
Eric Blake 已提交
2176
        pos = i / 8;
2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194
        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 已提交
2195
        if (libxl_set_vcpuonline(cfg->ctx, vm->def->id, &map) != 0) {
2196 2197
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Failed to set vcpus for domain '%d'"
2198
                             " with libxenlight"), vm->def->id);
2199
            goto endjob;
2200
        }
2201
        vm->def->vcpus = nvcpus;
2202 2203 2204
        break;

    case VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG:
J
Jim Fehlig 已提交
2205
        if (libxl_set_vcpuonline(cfg->ctx, vm->def->id, &map) != 0) {
2206 2207
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Failed to set vcpus for domain '%d'"
2208
                             " with libxenlight"), vm->def->id);
2209
            goto endjob;
2210
        }
2211
        vm->def->vcpus = nvcpus;
2212 2213 2214 2215 2216 2217
        def->vcpus = nvcpus;
        break;
    }

    ret = 0;

2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229
    if (flags & VIR_DOMAIN_VCPU_LIVE) {
        if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0) {
            VIR_WARN("Unable to save status on vm %s after changing vcpus",
                     vm->def->name);
        }
    }
    if (flags & VIR_DOMAIN_VCPU_CONFIG) {
        if (virDomainSaveConfig(cfg->configDir, def) < 0) {
            VIR_WARN("Unable to save configuration of vm %s after changing vcpus",
                     vm->def->name);
        }
    }
2230

2231
 endjob:
2232 2233 2234
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

2235
 cleanup:
2236 2237
    VIR_FREE(bitmask);
     if (vm)
2238
        virObjectUnlock(vm);
2239
     virObjectUnref(cfg);
2240 2241 2242 2243 2244 2245 2246 2247 2248 2249 2250 2251 2252 2253 2254
    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;
2255
    bool active;
2256 2257 2258 2259 2260

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

J
Jim Fehlig 已提交
2261
    if (!(vm = libxlDomObjFromDomain(dom)))
2262 2263
        goto cleanup;

2264
    if (virDomainGetVcpusFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
2265 2266
        goto cleanup;

2267 2268 2269 2270 2271 2272 2273 2274 2275
    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)) {
2276 2277
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid flag combination: (0x%x)"), flags);
2278 2279 2280
        return -1;
    }

2281
    if (flags & VIR_DOMAIN_VCPU_LIVE) {
2282
        if (!active) {
2283 2284
            virReportError(VIR_ERR_OPERATION_INVALID,
                           "%s", _("Domain is not running"));
2285 2286 2287 2288
            goto cleanup;
        }
        def = vm->def;
    } else {
2289
        if (!vm->persistent) {
2290 2291
            virReportError(VIR_ERR_OPERATION_INVALID,
                           "%s", _("domain is transient"));
2292 2293
            goto cleanup;
        }
2294 2295 2296 2297 2298
        def = vm->newDef ? vm->newDef : vm->def;
    }

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

2299
 cleanup:
2300
    if (vm)
2301
        virObjectUnlock(vm);
2302 2303 2304 2305
    return ret;
}

static int
2306 2307 2308
libxlDomainPinVcpuFlags(virDomainPtr dom, unsigned int vcpu,
                        unsigned char *cpumap, int maplen,
                        unsigned int flags)
2309 2310
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
2311
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
2312
    virDomainDefPtr targetDef = NULL;
2313
    virBitmapPtr pcpumap = NULL;
2314 2315
    virDomainObjPtr vm;
    int ret = -1;
2316 2317 2318

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);
2319

J
Jim Fehlig 已提交
2320
    if (!(vm = libxlDomObjFromDomain(dom)))
2321 2322
        goto cleanup;

2323
    if (virDomainPinVcpuFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
2324 2325
        goto cleanup;

2326 2327 2328
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

2329
    if ((flags & VIR_DOMAIN_AFFECT_LIVE) && !virDomainObjIsActive(vm)) {
2330
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
2331
                       _("domain is inactive"));
2332
        goto endjob;
2333 2334
    }

2335 2336
    if (virDomainLiveConfigHelperMethod(cfg->caps, driver->xmlopt, vm,
                                        &flags, &targetDef) < 0)
2337
        goto endjob;
2338

2339
    if (flags & VIR_DOMAIN_AFFECT_LIVE)
2340 2341 2342 2343 2344
        targetDef = vm->def;

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

2345 2346
    pcpumap = virBitmapNewData(cpumap, maplen);
    if (!pcpumap)
2347
        goto endjob;
2348

2349 2350
    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
        libxl_bitmap map = { .size = maplen, .map = cpumap };
J
Jim Fehlig 已提交
2351
        if (libxl_set_vcpuaffinity(cfg->ctx, vm->def->id, vcpu, &map) != 0) {
2352 2353 2354
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Failed to pin vcpu '%d' with libxenlight"),
                           vcpu);
2355
            goto endjob;
2356
        }
2357
    }
2358

2359 2360
    if (!targetDef->cputune.vcpupin) {
        if (VIR_ALLOC(targetDef->cputune.vcpupin) < 0)
2361
            goto endjob;
2362
        targetDef->cputune.nvcpupin = 0;
H
Hu Tao 已提交
2363
    }
2364 2365 2366 2367 2368
    if (virDomainPinAdd(&targetDef->cputune.vcpupin,
                        &targetDef->cputune.nvcpupin,
                        cpumap,
                        maplen,
                        vcpu) < 0) {
2369 2370
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("failed to update or add vcpupin xml"));
2371
        goto endjob;
2372 2373
    }

2374 2375
    ret = 0;

2376 2377 2378 2379 2380 2381
    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);
    }

2382
 endjob:
2383 2384 2385
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

2386
 cleanup:
2387
    if (vm)
2388
        virObjectUnlock(vm);
2389
    virBitmapFree(pcpumap);
2390
    virObjectUnref(cfg);
2391 2392 2393
    return ret;
}

2394 2395 2396 2397 2398 2399 2400 2401
static int
libxlDomainPinVcpu(virDomainPtr dom, unsigned int vcpu, unsigned char *cpumap,
                   int maplen)
{
    return libxlDomainPinVcpuFlags(dom, vcpu, cpumap, maplen,
                                   VIR_DOMAIN_AFFECT_LIVE);
}

2402 2403 2404 2405 2406 2407 2408 2409 2410
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;
2411 2412
    int hostcpus, vcpu, ret = -1;
    virBitmapPtr allcpumap = NULL;
2413 2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426

    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;

2427
    if (flags & VIR_DOMAIN_AFFECT_LIVE)
2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439
        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;

2440 2441
    if (!(allcpumap = virBitmapNew(hostcpus)))
        goto cleanup;
2442

2443
    virBitmapSetAll(allcpumap);
2444

2445 2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460
    memset(cpumaps, 0x00, maplen * ncpumaps);

    for (vcpu = 0; vcpu < ncpumaps; vcpu++) {
        virDomainPinDefPtr pininfo;
        virBitmapPtr bitmap = NULL;

        pininfo = virDomainPinFind(targetDef->cputune.vcpupin,
                                   targetDef->cputune.nvcpupin,
                                   vcpu);

        if (pininfo && pininfo->cpumask)
            bitmap = pininfo->cpumask;
        else
            bitmap = allcpumap;

        virBitmapToDataBuf(bitmap, VIR_GET_CPUMAP(cpumaps, maplen, vcpu), maplen);
2461
    }
2462

2463 2464
    ret = ncpumaps;

2465
 cleanup:
2466
    virBitmapFree(allcpumap);
2467 2468 2469 2470 2471
    if (vm)
        virObjectUnlock(vm);
    virObjectUnref(cfg);
    return ret;
}
2472 2473 2474 2475 2476

static int
libxlDomainGetVcpus(virDomainPtr dom, virVcpuInfoPtr info, int maxinfo,
                    unsigned char *cpumaps, int maplen)
{
J
Jim Fehlig 已提交
2477 2478
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
2479 2480 2481 2482
    virDomainObjPtr vm;
    int ret = -1;
    libxl_vcpuinfo *vcpuinfo;
    int maxcpu, hostcpus;
2483
    size_t i;
2484 2485
    unsigned char *cpumap;

J
Jim Fehlig 已提交
2486
    if (!(vm = libxlDomObjFromDomain(dom)))
2487 2488
        goto cleanup;

2489 2490 2491
    if (virDomainGetVcpusEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

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

J
Jim Fehlig 已提交
2497
    if ((vcpuinfo = libxl_list_vcpu(cfg->ctx, vm->def->id, &maxcpu,
2498
                                    &hostcpus)) == NULL) {
2499 2500
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to list vcpus for domain '%d' with libxenlight"),
2501
                       vm->def->id);
2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523
        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 已提交
2524
        libxl_vcpuinfo_dispose(&vcpuinfo[i]);
2525 2526 2527 2528 2529
    }
    VIR_FREE(vcpuinfo);

    ret = maxinfo;

2530
 cleanup:
2531
    if (vm)
2532
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
2533
    virObjectUnref(cfg);
2534 2535 2536
    return ret;
}

J
Jim Fehlig 已提交
2537
static char *
2538
libxlDomainGetXMLDesc(virDomainPtr dom, unsigned int flags)
J
Jim Fehlig 已提交
2539 2540
{
    virDomainObjPtr vm;
2541
    virDomainDefPtr def;
J
Jim Fehlig 已提交
2542 2543
    char *ret = NULL;

2544 2545
    /* Flags checked by virDomainDefFormat */

J
Jim Fehlig 已提交
2546
    if (!(vm = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
2547 2548
        goto cleanup;

2549 2550 2551
    if (virDomainGetXMLDescEnsureACL(dom->conn, vm->def, flags) < 0)
        goto cleanup;

2552 2553 2554 2555 2556 2557 2558
    if ((flags & VIR_DOMAIN_XML_INACTIVE) && vm->newDef)
        def = vm->newDef;
    else
        def = vm->def;

    ret = virDomainDefFormat(def,
                             virDomainDefFormatConvertXMLFlags(flags));
J
Jim Fehlig 已提交
2559

2560
 cleanup:
J
Jim Fehlig 已提交
2561
    if (vm)
2562
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
2563 2564 2565
    return ret;
}

2566
static char *
2567 2568 2569
libxlConnectDomainXMLFromNative(virConnectPtr conn,
                                const char *nativeFormat,
                                const char *nativeConfig,
2570
                                unsigned int flags)
2571 2572
{
    libxlDriverPrivatePtr driver = conn->privateData;
2573
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
2574 2575 2576 2577
    virDomainDefPtr def = NULL;
    virConfPtr conf = NULL;
    char *xml = NULL;

E
Eric Blake 已提交
2578 2579
    virCheckFlags(0, NULL);

2580 2581 2582
    if (virConnectDomainXMLFromNativeEnsureACL(conn) < 0)
        goto cleanup;

2583 2584 2585 2586 2587
    if (STREQ(nativeFormat, LIBXL_CONFIG_FORMAT_XL)) {
        if (!(conf = virConfReadMem(nativeConfig, strlen(nativeConfig), 0)))
            goto cleanup;
        if (!(def = xenParseXL(conf,
                               cfg->caps,
2588
                               cfg->verInfo->xen_version_major)))
2589 2590
            goto cleanup;
    } else if (STREQ(nativeFormat, LIBXL_CONFIG_FORMAT_XM)) {
2591 2592 2593 2594 2595
        if (!(conf = virConfReadMem(nativeConfig, strlen(nativeConfig), 0)))
            goto cleanup;

        if (!(def = xenParseXM(conf,
                               cfg->verInfo->xen_version_major,
2596
                               cfg->caps)))
2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608
            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 {
2609 2610
        virReportError(VIR_ERR_INVALID_ARG,
                       _("unsupported config type %s"), nativeFormat);
2611 2612 2613
        goto cleanup;
    }

2614
    xml = virDomainDefFormat(def, VIR_DOMAIN_DEF_FORMAT_INACTIVE);
2615

2616
 cleanup:
2617 2618 2619
    virDomainDefFree(def);
    if (conf)
        virConfFree(conf);
2620
    virObjectUnref(cfg);
2621 2622 2623 2624 2625
    return xml;
}

#define MAX_CONFIG_SIZE (1024 * 65)
static char *
2626 2627 2628
libxlConnectDomainXMLToNative(virConnectPtr conn, const char * nativeFormat,
                              const char * domainXml,
                              unsigned int flags)
2629 2630
{
    libxlDriverPrivatePtr driver = conn->privateData;
2631
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
2632 2633 2634 2635 2636
    virDomainDefPtr def = NULL;
    virConfPtr conf = NULL;
    int len = MAX_CONFIG_SIZE;
    char *ret = NULL;

E
Eric Blake 已提交
2637 2638
    virCheckFlags(0, NULL);

2639 2640 2641
    if (virConnectDomainXMLToNativeEnsureACL(conn) < 0)
        goto cleanup;

2642
    if (!(def = virDomainDefParseString(domainXml,
2643
                                        cfg->caps, driver->xmlopt,
2644
                                        VIR_DOMAIN_DEF_PARSE_INACTIVE)))
2645 2646
        goto cleanup;

2647 2648 2649 2650 2651 2652 2653 2654 2655 2656
    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);
2657
        goto cleanup;
2658
    }
2659

2660
    if (VIR_ALLOC_N(ret, len) < 0)
2661 2662 2663 2664 2665 2666 2667
        goto cleanup;

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

2668
 cleanup:
2669 2670 2671
    virDomainDefFree(def);
    if (conf)
        virConfFree(conf);
2672
    virObjectUnref(cfg);
2673 2674 2675
    return ret;
}

J
Jim Fehlig 已提交
2676
static int
2677 2678
libxlConnectListDefinedDomains(virConnectPtr conn,
                               char **const names, int nnames)
J
Jim Fehlig 已提交
2679 2680 2681 2682
{
    libxlDriverPrivatePtr driver = conn->privateData;
    int n;

2683 2684 2685
    if (virConnectListDefinedDomainsEnsureACL(conn) < 0)
        return -1;

2686 2687
    n = virDomainObjListGetInactiveNames(driver->domains, names, nnames,
                                         virConnectListDefinedDomainsCheckACL, conn);
J
Jim Fehlig 已提交
2688 2689 2690 2691
    return n;
}

static int
2692
libxlConnectNumOfDefinedDomains(virConnectPtr conn)
J
Jim Fehlig 已提交
2693 2694 2695 2696
{
    libxlDriverPrivatePtr driver = conn->privateData;
    int n;

2697 2698 2699
    if (virConnectNumOfDefinedDomainsEnsureACL(conn) < 0)
        return -1;

2700
    n = virDomainObjListNumOfDomains(driver->domains, false,
2701 2702
                                     virConnectNumOfDefinedDomainsCheckACL,
                                     conn);
J
Jim Fehlig 已提交
2703 2704 2705 2706 2707
    return n;
}

static int
libxlDomainCreateWithFlags(virDomainPtr dom,
E
Eric Blake 已提交
2708
                           unsigned int flags)
J
Jim Fehlig 已提交
2709 2710 2711 2712 2713 2714 2715
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_START_PAUSED, -1);

J
Jim Fehlig 已提交
2716
    if (!(vm = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
2717 2718
        goto cleanup;

2719 2720 2721
    if (virDomainCreateWithFlagsEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

2722 2723 2724
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

J
Jim Fehlig 已提交
2725
    if (virDomainObjIsActive(vm)) {
2726 2727
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("Domain is already running"));
2728
        goto endjob;
J
Jim Fehlig 已提交
2729 2730
    }

2731
    ret = libxlDomainStart(driver, vm, (flags & VIR_DOMAIN_START_PAUSED) != 0, -1);
2732
    if (ret < 0)
2733
        goto endjob;
2734
    dom->id = vm->def->id;
J
Jim Fehlig 已提交
2735

2736 2737 2738 2739
 endjob:
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

2740
 cleanup:
J
Jim Fehlig 已提交
2741
    if (vm)
2742
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
2743 2744 2745 2746 2747 2748 2749 2750 2751 2752
    return ret;
}

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

static virDomainPtr
2753
libxlDomainDefineXMLFlags(virConnectPtr conn, const char *xml, unsigned int flags)
J
Jim Fehlig 已提交
2754 2755
{
    libxlDriverPrivatePtr driver = conn->privateData;
2756
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
J
Jim Fehlig 已提交
2757 2758 2759
    virDomainDefPtr def = NULL;
    virDomainObjPtr vm = NULL;
    virDomainPtr dom = NULL;
2760
    virObjectEventPtr event = NULL;
2761
    virDomainDefPtr oldDef = NULL;
2762
    unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;
J
Jim Fehlig 已提交
2763

2764 2765 2766 2767
    virCheckFlags(VIR_DOMAIN_DEFINE_VALIDATE, NULL);

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

2769
    if (!(def = virDomainDefParseString(xml, cfg->caps, driver->xmlopt,
2770
                                        parse_flags)))
2771
        goto cleanup;
J
Jim Fehlig 已提交
2772

2773
    if (virDomainDefineXMLFlagsEnsureACL(conn, def) < 0)
2774
        goto cleanup;
2775

2776
    if (!(vm = virDomainObjListAdd(driver->domains, def,
2777
                                   driver->xmlopt,
2778 2779
                                   0,
                                   &oldDef)))
2780
        goto cleanup;
2781

J
Jim Fehlig 已提交
2782 2783 2784
    def = NULL;
    vm->persistent = 1;

2785
    if (virDomainSaveConfig(cfg->configDir,
J
Jim Fehlig 已提交
2786
                            vm->newDef ? vm->newDef : vm->def) < 0) {
2787
        virDomainObjListRemove(driver->domains, vm);
J
Jim Fehlig 已提交
2788 2789 2790 2791 2792 2793 2794 2795
        vm = NULL;
        goto cleanup;
    }

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

2796
    event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_DEFINED,
2797
                                     !oldDef ?
2798 2799 2800
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED :
                                     VIR_DOMAIN_EVENT_DEFINED_UPDATED);

2801
 cleanup:
J
Jim Fehlig 已提交
2802
    virDomainDefFree(def);
2803
    virDomainDefFree(oldDef);
J
Jim Fehlig 已提交
2804
    if (vm)
2805
        virObjectUnlock(vm);
2806 2807
    if (event)
        libxlDomainEventQueue(driver, event);
2808
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
2809 2810 2811
    return dom;
}

2812 2813 2814 2815 2816 2817
static virDomainPtr
libxlDomainDefineXML(virConnectPtr conn, const char *xml)
{
    return libxlDomainDefineXMLFlags(conn, xml, 0);
}

J
Jim Fehlig 已提交
2818
static int
2819 2820
libxlDomainUndefineFlags(virDomainPtr dom,
                         unsigned int flags)
J
Jim Fehlig 已提交
2821 2822
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
2823
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
J
Jim Fehlig 已提交
2824
    virDomainObjPtr vm;
2825
    virObjectEventPtr event = NULL;
2826
    char *name = NULL;
J
Jim Fehlig 已提交
2827 2828
    int ret = -1;

2829 2830
    virCheckFlags(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE, -1);

J
Jim Fehlig 已提交
2831
    if (!(vm = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
2832 2833
        goto cleanup;

2834 2835 2836
    if (virDomainUndefineFlagsEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

J
Jim Fehlig 已提交
2837
    if (!vm->persistent) {
2838 2839
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("cannot undefine transient domain"));
J
Jim Fehlig 已提交
2840 2841 2842
        goto cleanup;
    }

2843 2844 2845 2846 2847 2848 2849
    name = libxlDomainManagedSavePath(driver, vm);
    if (name == NULL)
        goto cleanup;

    if (virFileExists(name)) {
        if (flags & VIR_DOMAIN_UNDEFINE_MANAGED_SAVE) {
            if (unlink(name) < 0) {
2850 2851
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("Failed to remove domain managed save image"));
2852 2853 2854
                goto cleanup;
            }
        } else {
2855 2856 2857
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                           _("Refusing to undefine while domain managed "
                             "save image exists"));
2858 2859 2860 2861
            goto cleanup;
        }
    }

2862
    if (virDomainDeleteConfig(cfg->configDir, cfg->autostartDir, vm) < 0)
J
Jim Fehlig 已提交
2863 2864
        goto cleanup;

2865
    event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_UNDEFINED,
2866 2867
                                     VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);

2868 2869 2870
    if (virDomainObjIsActive(vm)) {
        vm->persistent = 0;
    } else {
2871
        virDomainObjListRemove(driver->domains, vm);
2872 2873 2874
        vm = NULL;
    }

J
Jim Fehlig 已提交
2875 2876
    ret = 0;

2877
 cleanup:
2878
    VIR_FREE(name);
J
Jim Fehlig 已提交
2879
    if (vm)
2880
        virObjectUnlock(vm);
2881 2882
    if (event)
        libxlDomainEventQueue(driver, event);
2883
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
2884 2885 2886
    return ret;
}

2887 2888 2889 2890 2891 2892
static int
libxlDomainUndefine(virDomainPtr dom)
{
    return libxlDomainUndefineFlags(dom, 0);
}

2893
static int
J
Jim Fehlig 已提交
2894
libxlDomainChangeEjectableMedia(virDomainObjPtr vm, virDomainDiskDefPtr disk)
2895
{
J
Jim Fehlig 已提交
2896
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(libxl_driver);
2897 2898
    virDomainDiskDefPtr origdisk = NULL;
    libxl_device_disk x_disk;
2899
    size_t i;
2900 2901
    int ret = -1;

2902
    for (i = 0; i < vm->def->ndisks; i++) {
2903 2904 2905 2906 2907 2908 2909 2910
        if (vm->def->disks[i]->bus == disk->bus &&
            STREQ(vm->def->disks[i]->dst, disk->dst)) {
            origdisk = vm->def->disks[i];
            break;
        }
    }

    if (!origdisk) {
2911 2912 2913
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("No device with bus '%s' and target '%s'"),
                       virDomainDiskBusTypeToString(disk->bus), disk->dst);
2914 2915 2916 2917
        goto cleanup;
    }

    if (origdisk->device != VIR_DOMAIN_DISK_DEVICE_CDROM) {
2918 2919 2920
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Removable media not supported for %s device"),
                       virDomainDiskDeviceTypeToString(disk->device));
2921 2922 2923
        return -1;
    }

J
Jim Fehlig 已提交
2924
    if (libxlMakeDisk(disk, &x_disk) < 0)
2925 2926
        goto cleanup;

J
Jim Fehlig 已提交
2927
    if ((ret = libxl_cdrom_insert(cfg->ctx, vm->def->id, &x_disk, NULL)) < 0) {
2928 2929 2930
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("libxenlight failed to change media for disk '%s'"),
                       disk->dst);
2931 2932 2933
        goto cleanup;
    }

2934 2935 2936
    if (virDomainDiskSetSource(origdisk, virDomainDiskGetSource(disk)) < 0)
        goto cleanup;
    virDomainDiskSetType(origdisk, virDomainDiskGetType(disk));
2937 2938 2939 2940 2941

    virDomainDiskDefFree(disk);

    ret = 0;

2942
 cleanup:
J
Jim Fehlig 已提交
2943
    virObjectUnref(cfg);
2944 2945 2946 2947
    return ret;
}

static int
J
Jim Fehlig 已提交
2948
libxlDomainAttachDeviceDiskLive(virDomainObjPtr vm, virDomainDeviceDefPtr dev)
2949
{
J
Jim Fehlig 已提交
2950
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(libxl_driver);
2951 2952 2953 2954 2955 2956
    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 已提交
2957
            ret = libxlDomainChangeEjectableMedia(vm, l_disk);
2958 2959 2960
            break;
        case VIR_DOMAIN_DISK_DEVICE_DISK:
            if (l_disk->bus == VIR_DOMAIN_DISK_BUS_XEN) {
2961
                if (virDomainDiskIndexByName(vm->def, l_disk->dst, true) >= 0) {
2962 2963
                    virReportError(VIR_ERR_OPERATION_FAILED,
                                   _("target %s already exists"), l_disk->dst);
2964 2965 2966
                    goto cleanup;
                }

2967
                if (!virDomainDiskGetSource(l_disk)) {
2968 2969
                    virReportError(VIR_ERR_INTERNAL_ERROR,
                                   "%s", _("disk source path is missing"));
2970 2971 2972
                    goto cleanup;
                }

2973
                if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks+1) < 0)
2974 2975
                    goto cleanup;

J
Jim Fehlig 已提交
2976
                if (libxlMakeDisk(l_disk, &x_disk) < 0)
2977 2978
                    goto cleanup;

2979 2980 2981 2982 2983
                if (virDomainLockDiskAttach(libxl_driver->lockManager,
                                            "xen:///system",
                                            vm, l_disk) < 0)
                    goto cleanup;

J
Jim Fehlig 已提交
2984
                if ((ret = libxl_device_disk_add(cfg->ctx, vm->def->id,
J
Jim Fehlig 已提交
2985
                                                &x_disk, NULL)) < 0) {
2986 2987 2988
                    virReportError(VIR_ERR_INTERNAL_ERROR,
                                   _("libxenlight failed to attach disk '%s'"),
                                   l_disk->dst);
2989 2990 2991 2992 2993
                    if (virDomainLockDiskDetach(libxl_driver->lockManager,
                                                vm, l_disk) < 0) {
                        VIR_WARN("Unable to release lock on %s",
                                 virDomainDiskGetSource(l_disk));
                    }
2994 2995 2996 2997 2998 2999
                    goto cleanup;
                }

                virDomainDiskInsertPreAlloced(vm->def, l_disk);

            } else {
3000 3001 3002
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("disk bus '%s' cannot be hotplugged."),
                               virDomainDiskBusTypeToString(l_disk->bus));
3003 3004 3005
            }
            break;
        default:
3006 3007 3008
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("disk device type '%s' cannot be hotplugged"),
                           virDomainDiskDeviceTypeToString(l_disk->device));
3009 3010 3011
            break;
    }

3012
 cleanup:
J
Jim Fehlig 已提交
3013
    virObjectUnref(cfg);
3014 3015 3016
    return ret;
}

3017 3018 3019 3020 3021
static int
libxlDomainAttachHostPCIDevice(libxlDriverPrivatePtr driver,
                               virDomainObjPtr vm,
                               virDomainHostdevDefPtr hostdev)
{
J
Jim Fehlig 已提交
3022
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
3023
    libxl_device_pci pcidev;
3024 3025
    virDomainHostdevDefPtr found;
    virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
3026
    virDomainHostdevSubsysPCIPtr pcisrc = &hostdev->source.subsys.u.pci;
J
Jim Fehlig 已提交
3027
    int ret = -1;
3028

3029 3030
    libxl_device_pci_init(&pcidev);

3031 3032 3033
    if (virDomainHostdevFind(vm->def, hostdev, &found) >= 0) {
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("target pci device %.4x:%.2x:%.2x.%.1x already exists"),
3034 3035
                       pcisrc->addr.domain, pcisrc->addr.bus,
                       pcisrc->addr.slot, pcisrc->addr.function);
J
Jim Fehlig 已提交
3036
        goto cleanup;
3037 3038 3039
    }

    if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs + 1) < 0)
J
Jim Fehlig 已提交
3040
        goto cleanup;
3041 3042 3043 3044

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

3047
    if (libxlMakePCI(hostdev, &pcidev) < 0)
C
Chunyan Liu 已提交
3048
        goto error;
3049

J
Jim Fehlig 已提交
3050
    if (libxl_device_pci_add(cfg->ctx, vm->def->id, &pcidev, 0) < 0) {
3051 3052
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("libxenlight failed to attach pci device %.4x:%.2x:%.2x.%.1x"),
3053 3054
                       pcisrc->addr.domain, pcisrc->addr.bus,
                       pcisrc->addr.slot, pcisrc->addr.function);
C
Chunyan Liu 已提交
3055
        goto error;
3056 3057 3058
    }

    vm->def->hostdevs[vm->def->nhostdevs++] = hostdev;
J
Jim Fehlig 已提交
3059 3060
    ret = 0;
    goto cleanup;
3061

3062
 error:
3063 3064
    virHostdevReAttachPCIDevices(hostdev_mgr, LIBXL_DRIVER_NAME,
                                 vm->def->name, &hostdev, 1, NULL);
J
Jim Fehlig 已提交
3065 3066 3067

 cleanup:
    virObjectUnref(cfg);
3068
    libxl_device_pci_dispose(&pcidev);
J
Jim Fehlig 已提交
3069
    return ret;
3070 3071 3072 3073 3074
}

static int
libxlDomainAttachHostDevice(libxlDriverPrivatePtr driver,
                            virDomainObjPtr vm,
3075
                            virDomainHostdevDefPtr hostdev)
3076 3077 3078 3079 3080 3081 3082 3083 3084 3085
{
    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 已提交
3086
        if (libxlDomainAttachHostPCIDevice(driver, vm, hostdev) < 0)
C
Chunyan Liu 已提交
3087
            return -1;
3088 3089 3090 3091 3092 3093
        break;

    default:
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("hostdev subsys type '%s' not supported"),
                       virDomainHostdevSubsysTypeToString(hostdev->source.subsys.type));
C
Chunyan Liu 已提交
3094
        return -1;
3095 3096 3097 3098 3099
    }

    return 0;
}

3100
static int
J
Jim Fehlig 已提交
3101
libxlDomainDetachDeviceDiskLive(virDomainObjPtr vm, virDomainDeviceDefPtr dev)
3102
{
J
Jim Fehlig 已提交
3103
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(libxl_driver);
3104 3105
    virDomainDiskDefPtr l_disk = NULL;
    libxl_device_disk x_disk;
3106
    int idx;
3107 3108 3109 3110 3111 3112
    int ret = -1;

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

3113 3114 3115
                if ((idx = virDomainDiskIndexByName(vm->def,
                                                    dev->data.disk->dst,
                                                    false)) < 0) {
3116 3117
                    virReportError(VIR_ERR_OPERATION_FAILED,
                                   _("disk %s not found"), dev->data.disk->dst);
3118 3119 3120
                    goto cleanup;
                }

3121
                l_disk = vm->def->disks[idx];
3122

J
Jim Fehlig 已提交
3123
                if (libxlMakeDisk(l_disk, &x_disk) < 0)
3124 3125
                    goto cleanup;

J
Jim Fehlig 已提交
3126
                if ((ret = libxl_device_disk_remove(cfg->ctx, vm->def->id,
J
Jim Fehlig 已提交
3127
                                                    &x_disk, NULL)) < 0) {
3128 3129 3130
                    virReportError(VIR_ERR_INTERNAL_ERROR,
                                   _("libxenlight failed to detach disk '%s'"),
                                   l_disk->dst);
3131 3132 3133
                    goto cleanup;
                }

3134 3135 3136 3137 3138
                if (virDomainLockDiskDetach(libxl_driver->lockManager,
                                            vm, l_disk) < 0)
                    VIR_WARN("Unable to release lock on %s",
                             virDomainDiskGetSource(l_disk));

3139
                virDomainDiskRemove(vm->def, idx);
3140 3141 3142
                virDomainDiskDefFree(l_disk);

            } else {
3143 3144 3145
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("disk bus '%s' cannot be hot unplugged."),
                               virDomainDiskBusTypeToString(dev->data.disk->bus));
3146 3147 3148
            }
            break;
        default:
3149 3150 3151
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("device type '%s' cannot hot unplugged"),
                           virDomainDiskDeviceTypeToString(dev->data.disk->device));
3152 3153 3154
            break;
    }

3155
 cleanup:
J
Jim Fehlig 已提交
3156
    virObjectUnref(cfg);
3157 3158 3159
    return ret;
}

3160 3161 3162 3163 3164
static int
libxlDomainAttachNetDevice(libxlDriverPrivatePtr driver,
                           virDomainObjPtr vm,
                           virDomainNetDefPtr net)
{
J
Jim Fehlig 已提交
3165
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
3166 3167 3168
    int actualType;
    libxl_device_nic nic;
    int ret = -1;
3169
    char mac[VIR_MAC_STRING_BUFLEN];
3170 3171 3172

    /* preallocate new slot for device */
    if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets + 1) < 0)
J
Jim Fehlig 已提交
3173
        goto out;
3174 3175 3176 3177 3178 3179

    /* 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 已提交
3180
        goto out;
3181 3182 3183

    actualType = virDomainNetGetActualType(net);

3184 3185 3186 3187 3188 3189 3190
    if (virDomainHasNet(vm->def, net)) {
        virReportError(VIR_ERR_INVALID_ARG,
                       _("network device with mac %s already exists"),
                       virMacAddrFormat(&net->mac, mac));
        return -1;
    }

3191 3192 3193 3194 3195 3196
    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 已提交
3197
        ret = libxlDomainAttachHostDevice(driver, vm,
3198 3199 3200 3201 3202 3203 3204 3205
                                          virDomainNetGetActualHostdev(net));
        goto out;
    }

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

J
Jim Fehlig 已提交
3206
    if (libxl_device_nic_add(cfg->ctx, vm->def->id, &nic, 0)) {
3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218
        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 已提交
3219
    virObjectUnref(cfg);
3220 3221 3222
    return ret;
}

3223
static int
3224 3225
libxlDomainAttachDeviceLive(libxlDriverPrivatePtr driver,
                            virDomainObjPtr vm,
3226 3227 3228 3229 3230 3231
                            virDomainDeviceDefPtr dev)
{
    int ret = -1;

    switch (dev->type) {
        case VIR_DOMAIN_DEVICE_DISK:
J
Jim Fehlig 已提交
3232
            ret = libxlDomainAttachDeviceDiskLive(vm, dev);
3233 3234 3235 3236
            if (!ret)
                dev->data.disk = NULL;
            break;

3237
        case VIR_DOMAIN_DEVICE_NET:
J
Jim Fehlig 已提交
3238
            ret = libxlDomainAttachNetDevice(driver, vm,
3239 3240 3241 3242 3243
                                             dev->data.net);
            if (!ret)
                dev->data.net = NULL;
            break;

3244
        case VIR_DOMAIN_DEVICE_HOSTDEV:
J
Jim Fehlig 已提交
3245
            ret = libxlDomainAttachHostDevice(driver, vm,
3246
                                              dev->data.hostdev);
3247 3248 3249 3250
            if (!ret)
                dev->data.hostdev = NULL;
            break;

3251
        default:
3252 3253 3254
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("device type '%s' cannot be attached"),
                           virDomainDeviceTypeToString(dev->type));
3255 3256 3257 3258 3259 3260 3261 3262 3263 3264
            break;
    }

    return ret;
}

static int
libxlDomainAttachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev)
{
    virDomainDiskDefPtr disk;
3265
    virDomainNetDefPtr net;
3266 3267
    virDomainHostdevDefPtr hostdev;
    virDomainHostdevDefPtr found;
3268
    virDomainHostdevSubsysPCIPtr pcisrc;
3269
    char mac[VIR_MAC_STRING_BUFLEN];
3270 3271 3272 3273

    switch (dev->type) {
        case VIR_DOMAIN_DEVICE_DISK:
            disk = dev->data.disk;
3274
            if (virDomainDiskIndexByName(vmdef, disk->dst, true) >= 0) {
3275 3276
                virReportError(VIR_ERR_INVALID_ARG,
                               _("target %s already exists."), disk->dst);
3277 3278
                return -1;
            }
3279
            if (virDomainDiskInsert(vmdef, disk))
3280 3281 3282 3283
                return -1;
            /* vmdef has the pointer. Generic codes for vmdef will do all jobs */
            dev->data.disk = NULL;
            break;
3284 3285 3286

        case VIR_DOMAIN_DEVICE_NET:
            net = dev->data.net;
3287 3288 3289 3290 3291 3292
            if (virDomainHasNet(vmdef, net)) {
                virReportError(VIR_ERR_INVALID_ARG,
                               _("network device with mac %s already exists"),
                               virMacAddrFormat(&net->mac, mac));
                return -1;
            }
3293 3294 3295 3296 3297
            if (virDomainNetInsert(vmdef, net))
                return -1;
            dev->data.net = NULL;
            break;

3298 3299 3300 3301 3302 3303 3304
        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) {
3305
                pcisrc = &hostdev->source.subsys.u.pci;
3306 3307 3308
                virReportError(VIR_ERR_OPERATION_FAILED,
                               _("target pci device %.4x:%.2x:%.2x.%.1x\
                                  already exists"),
3309 3310
                               pcisrc->addr.domain, pcisrc->addr.bus,
                               pcisrc->addr.slot, pcisrc->addr.function);
3311 3312 3313
                return -1;
            }

3314 3315
            if (virDomainHostdevInsert(vmdef, hostdev) < 0)
                return -1;
3316
            dev->data.hostdev = NULL;
3317
            break;
3318 3319

        default:
3320 3321
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("persistent attach of device is not supported"));
3322 3323 3324 3325 3326 3327
            return -1;
    }
    return 0;
}

static int
3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360
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 已提交
3361
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
3362
    virDomainHostdevSubsysPtr subsys = &hostdev->source.subsys;
3363
    virDomainHostdevSubsysPCIPtr pcisrc = &subsys->u.pci;
3364 3365 3366 3367
    libxl_device_pci pcidev;
    virDomainHostdevDefPtr detach;
    int idx;
    virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
J
Jim Fehlig 已提交
3368
    int ret = -1;
3369

3370 3371
    libxl_device_pci_init(&pcidev);

3372 3373 3374 3375
    idx = virDomainHostdevFind(vm->def, hostdev, &detach);
    if (idx < 0) {
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("host pci device %.4x:%.2x:%.2x.%.1x not found"),
3376 3377
                       pcisrc->addr.domain, pcisrc->addr.bus,
                       pcisrc->addr.slot, pcisrc->addr.function);
J
Jim Fehlig 已提交
3378
        goto cleanup;
3379 3380 3381 3382 3383
    }

    if (libxlIsMultiFunctionDevice(vm->def, detach->info)) {
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("cannot hot unplug multifunction PCI device: %.4x:%.2x:%.2x.%.1x"),
3384 3385
                       pcisrc->addr.domain, pcisrc->addr.bus,
                       pcisrc->addr.slot, pcisrc->addr.function);
C
Chunyan Liu 已提交
3386
        goto error;
3387 3388 3389
    }


3390
    if (libxlMakePCI(detach, &pcidev) < 0)
C
Chunyan Liu 已提交
3391
        goto error;
3392

J
Jim Fehlig 已提交
3393
    if (libxl_device_pci_remove(cfg->ctx, vm->def->id, &pcidev, 0) < 0) {
3394 3395 3396
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("libxenlight failed to detach pci device\
                          %.4x:%.2x:%.2x.%.1x"),
3397 3398
                       pcisrc->addr.domain, pcisrc->addr.bus,
                       pcisrc->addr.slot, pcisrc->addr.function);
C
Chunyan Liu 已提交
3399
        goto error;
3400 3401 3402 3403 3404 3405 3406 3407
    }


    virDomainHostdevRemove(vm->def, idx);

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

J
Jim Fehlig 已提交
3408
    ret = 0;
3409

3410
 error:
3411
    virDomainHostdevDefFree(detach);
J
Jim Fehlig 已提交
3412 3413 3414

 cleanup:
    virObjectUnref(cfg);
3415
    libxl_device_pci_dispose(&pcidev);
J
Jim Fehlig 已提交
3416
    return ret;
3417 3418 3419 3420 3421
}

static int
libxlDomainDetachHostDevice(libxlDriverPrivatePtr driver,
                            virDomainObjPtr vm,
3422
                            virDomainHostdevDefPtr hostdev)
3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434
{
    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 已提交
3435
            return libxlDomainDetachHostPCIDevice(driver, vm, hostdev);
3436 3437 3438 3439 3440 3441 3442 3443 3444 3445

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

    return -1;
}

3446 3447 3448 3449 3450
static int
libxlDomainDetachNetDevice(libxlDriverPrivatePtr driver,
                           virDomainObjPtr vm,
                           virDomainNetDefPtr net)
{
J
Jim Fehlig 已提交
3451
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
3452 3453 3454 3455 3456 3457 3458
    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 已提交
3459
        goto out;
3460 3461 3462 3463 3464 3465 3466

    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 已提交
3467
        ret = libxlDomainDetachHostDevice(driver, vm,
3468 3469 3470 3471 3472
                                          virDomainNetGetActualHostdev(detach));
        goto out;
    }

    libxl_device_nic_init(&nic);
J
Jim Fehlig 已提交
3473
    if (libxl_mac_to_device_nic(cfg->ctx, vm->def->id,
3474 3475 3476
                                virMacAddrFormat(&detach->mac, mac), &nic))
        goto cleanup;

J
Jim Fehlig 已提交
3477
    if (libxl_device_nic_remove(cfg->ctx, vm->def->id, &nic, 0)) {
3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489
        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 已提交
3490
    virObjectUnref(cfg);
3491 3492 3493
    return ret;
}

3494 3495 3496
static int
libxlDomainDetachDeviceLive(libxlDriverPrivatePtr driver,
                            virDomainObjPtr vm,
3497 3498 3499 3500 3501 3502
                            virDomainDeviceDefPtr dev)
{
    int ret = -1;

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

3506
        case VIR_DOMAIN_DEVICE_NET:
J
Jim Fehlig 已提交
3507
            ret = libxlDomainDetachNetDevice(driver, vm,
3508 3509 3510
                                             dev->data.net);
            break;

3511
        case VIR_DOMAIN_DEVICE_HOSTDEV:
J
Jim Fehlig 已提交
3512
            ret = libxlDomainDetachHostDevice(driver, vm,
3513
                                              dev->data.hostdev);
3514 3515
            break;

3516
        default:
3517 3518 3519
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("device type '%s' cannot be detached"),
                           virDomainDeviceTypeToString(dev->type));
3520 3521 3522 3523 3524 3525
            break;
    }

    return ret;
}

3526

3527 3528 3529
static int
libxlDomainDetachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev)
{
3530
    virDomainDiskDefPtr disk, detach;
3531
    virDomainHostdevDefPtr hostdev, det_hostdev;
3532
    virDomainNetDefPtr net;
3533
    int idx;
3534 3535 3536 3537

    switch (dev->type) {
        case VIR_DOMAIN_DEVICE_DISK:
            disk = dev->data.disk;
3538
            if (!(detach = virDomainDiskRemoveByName(vmdef, disk->dst))) {
3539 3540
                virReportError(VIR_ERR_INVALID_ARG,
                               _("no target device %s"), disk->dst);
3541
                return -1;
3542
            }
3543
            virDomainDiskDefFree(detach);
3544
            break;
3545

3546 3547 3548 3549 3550 3551 3552 3553 3554
        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;

3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566
        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;
        }

3567
        default:
3568 3569
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("persistent detach of device is not supported"));
3570
            return -1;
3571 3572
    }

3573
    return 0;
3574 3575 3576
}

static int
J
Jim Fehlig 已提交
3577
libxlDomainUpdateDeviceLive(virDomainObjPtr vm, virDomainDeviceDefPtr dev)
3578 3579 3580 3581 3582 3583 3584 3585 3586
{
    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 已提交
3587
                    ret = libxlDomainChangeEjectableMedia(vm, disk);
3588 3589 3590 3591
                    if (ret == 0)
                        dev->data.disk = NULL;
                    break;
                default:
3592 3593 3594
                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                                   _("disk bus '%s' cannot be updated."),
                                   virDomainDiskBusTypeToString(disk->bus));
3595 3596 3597 3598
                    break;
            }
            break;
        default:
3599 3600 3601
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("device type '%s' cannot be updated"),
                           virDomainDeviceTypeToString(dev->type));
3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617
            break;
    }

    return ret;
}

static int
libxlDomainUpdateDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev)
{
    virDomainDiskDefPtr orig;
    virDomainDiskDefPtr disk;
    int ret = -1;

    switch (dev->type) {
        case VIR_DOMAIN_DEVICE_DISK:
            disk = dev->data.disk;
3618
            if (!(orig = virDomainDiskByName(vmdef, disk->dst, false))) {
3619 3620
                virReportError(VIR_ERR_INVALID_ARG,
                               _("target %s doesn't exist."), disk->dst);
3621 3622 3623
                goto cleanup;
            }
            if (!(orig->device == VIR_DOMAIN_DISK_DEVICE_CDROM)) {
3624 3625
                virReportError(VIR_ERR_INVALID_ARG, "%s",
                               _("this disk doesn't support update"));
3626 3627 3628
                goto cleanup;
            }

3629 3630 3631 3632 3633 3634
            if (virDomainDiskSetSource(orig, virDomainDiskGetSource(disk)) < 0)
                goto cleanup;
            virDomainDiskSetType(orig, virDomainDiskGetType(disk));
            virDomainDiskSetFormat(orig, virDomainDiskGetFormat(disk));
            if (virDomainDiskSetDriver(orig, virDomainDiskGetDriver(disk)) < 0)
                goto cleanup;
3635 3636
            break;
        default:
3637 3638
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("persistent update of device is not supported"));
3639 3640 3641 3642 3643
            goto cleanup;
    }

    ret = 0;

3644
 cleanup:
3645 3646 3647 3648 3649
    return ret;
}


static int
3650 3651
libxlDomainAttachDeviceFlags(virDomainPtr dom, const char *xml,
                             unsigned int flags)
3652 3653
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
3654
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
3655 3656 3657 3658 3659 3660 3661 3662
    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 已提交
3663
    if (!(vm = libxlDomObjFromDomain(dom)))
3664 3665
        goto cleanup;

3666 3667 3668
    if (virDomainAttachDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
        goto cleanup;

3669 3670 3671
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

3672 3673 3674 3675 3676 3677 3678 3679
    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) {
3680 3681
            virReportError(VIR_ERR_OPERATION_INVALID,
                           "%s", _("Domain is not running"));
3682
            goto endjob;
3683 3684 3685 3686
        }
    }

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

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

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

3703
        if (libxlDomainAttachDeviceConfig(vmdef, dev) < 0)
3704
            goto endjob;
3705
    }
3706 3707 3708 3709

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

J
Jim Fehlig 已提交
3715
        if (libxlDomainAttachDeviceLive(driver, vm, dev) < 0)
3716
            goto endjob;
3717

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

3726 3727
    ret = 0;

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

3737
 endjob:
3738 3739 3740
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

3741
 cleanup:
3742 3743 3744
    virDomainDefFree(vmdef);
    virDomainDeviceDefFree(dev);
    if (vm)
3745
        virObjectUnlock(vm);
3746
    virObjectUnref(cfg);
3747 3748 3749 3750 3751 3752 3753 3754 3755 3756 3757 3758 3759 3760
    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)
{
3761
    libxlDriverPrivatePtr driver = dom->conn->privateData;
3762
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
3763 3764 3765 3766 3767 3768 3769 3770
    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 已提交
3771
    if (!(vm = libxlDomObjFromDomain(dom)))
3772 3773
        goto cleanup;

3774 3775 3776
    if (virDomainDetachDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
        goto cleanup;

3777 3778 3779
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

3780 3781 3782 3783 3784 3785 3786 3787 3788 3789
    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"));
3790
            goto endjob;
3791 3792 3793 3794 3795 3796
        }
    }

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

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

        /* Make a copy for updated domain. */
3807
        if (!(vmdef = virDomainObjCopyPersistentDef(vm, cfg->caps,
3808
                                                    driver->xmlopt)))
3809
            goto endjob;
3810

3811
        if (libxlDomainDetachDeviceConfig(vmdef, dev) < 0)
3812
            goto endjob;
3813 3814 3815 3816 3817 3818
    }

    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,
3819
                                            cfg->caps, driver->xmlopt,
3820
                                            VIR_DOMAIN_DEF_PARSE_INACTIVE)))
3821
            goto endjob;
3822

J
Jim Fehlig 已提交
3823
        if (libxlDomainDetachDeviceLive(driver, vm, dev) < 0)
3824
            goto endjob;
3825 3826 3827 3828 3829

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

3834 3835
    ret = 0;

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

3845
 endjob:
3846 3847 3848
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

3849
 cleanup:
3850 3851 3852 3853
    virDomainDefFree(vmdef);
    virDomainDeviceDefFree(dev);
    if (vm)
        virObjectUnlock(vm);
3854
    virObjectUnref(cfg);
3855
    return ret;
3856 3857 3858 3859 3860 3861 3862 3863 3864 3865 3866 3867 3868
}

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)
{
3869
    libxlDriverPrivatePtr driver = dom->conn->privateData;
3870
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
3871 3872 3873 3874 3875 3876 3877 3878
    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 已提交
3879
    if (!(vm = libxlDomObjFromDomain(dom)))
3880 3881
        goto cleanup;

3882 3883 3884
    if (virDomainUpdateDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
        goto cleanup;

3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906
    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,
3907
                                            cfg->caps, driver->xmlopt,
3908
                                            VIR_DOMAIN_DEF_PARSE_INACTIVE)))
3909 3910 3911
            goto cleanup;

        /* Make a copy for updated domain. */
3912
        if (!(vmdef = virDomainObjCopyPersistentDef(vm, cfg->caps,
3913 3914 3915 3916 3917 3918 3919 3920 3921 3922 3923 3924 3925
                                                    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,
3926
                                            cfg->caps, driver->xmlopt,
3927
                                            VIR_DOMAIN_DEF_PARSE_INACTIVE)))
3928 3929
            goto cleanup;

J
Jim Fehlig 已提交
3930
        if ((ret = libxlDomainUpdateDeviceLive(vm, dev)) < 0)
3931 3932 3933 3934 3935 3936
            goto cleanup;

        /*
         * update domain status forcibly because the domain status may be
         * changed even if we attach the device failed.
         */
3937
        if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
3938 3939 3940 3941 3942
            ret = -1;
    }

    /* Finally, if no error until here, we can save config. */
    if (!ret && (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG)) {
3943
        ret = virDomainSaveConfig(cfg->configDir, vmdef);
3944 3945 3946 3947 3948 3949
        if (!ret) {
            virDomainObjAssignDef(vm, vmdef, false, NULL);
            vmdef = NULL;
        }
    }

3950
 cleanup:
3951 3952 3953 3954
    virDomainDefFree(vmdef);
    virDomainDeviceDefFree(dev);
    if (vm)
        virObjectUnlock(vm);
3955
    virObjectUnref(cfg);
3956
    return ret;
3957 3958
}

3959 3960 3961 3962 3963
static unsigned long long
libxlNodeGetFreeMemory(virConnectPtr conn)
{
    libxl_physinfo phy_info;
    libxlDriverPrivatePtr driver = conn->privateData;
3964 3965
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
    unsigned long long ret = 0;
3966

3967
    if (virNodeGetFreeMemoryEnsureACL(conn) < 0)
3968
        goto cleanup;
3969

3970
    if (libxl_get_physinfo(cfg->ctx, &phy_info)) {
3971 3972
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("libxl_get_physinfo_info failed"));
3973
        goto cleanup;
3974 3975
    }

3976 3977
    ret = phy_info.free_pages * cfg->verInfo->pagesize;

3978
 cleanup:
3979 3980
    virObjectUnref(cfg);
    return ret;
3981 3982
}

3983 3984 3985 3986 3987 3988 3989 3990 3991 3992
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;
3993
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
3994 3995

    if (virNodeGetCellsFreeMemoryEnsureACL(conn) < 0)
3996
        goto cleanup;
3997

3998
    numa_info = libxl_get_numainfo(cfg->ctx, &nr_nodes);
3999
    if (numa_info == NULL || nr_nodes == 0) {
4000 4001 4002
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("libxl_get_numainfo failed"));
        goto cleanup;
4003 4004 4005
    }

    /* Check/sanitize the cell range */
4006
    if (startCell >= nr_nodes) {
4007 4008
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("start cell %d out of range (0-%d)"),
4009
                       startCell, nr_nodes - 1);
4010 4011 4012
        goto cleanup;
    }
    lastCell = startCell + maxCells - 1;
4013 4014
    if (lastCell >= nr_nodes)
        lastCell = nr_nodes - 1;
4015 4016 4017 4018 4019 4020 4021

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

4023 4024
    ret = numCells;

4025
 cleanup:
4026
    libxl_numainfo_list_free(numa_info, nr_nodes);
4027
    virObjectUnref(cfg);
4028 4029 4030
    return ret;
}

4031
static int
4032
libxlConnectDomainEventRegister(virConnectPtr conn,
4033 4034
                                virConnectDomainEventCallback callback,
                                void *opaque,
4035
                                virFreeCallback freecb)
4036 4037 4038
{
    libxlDriverPrivatePtr driver = conn->privateData;

4039 4040 4041
    if (virConnectDomainEventRegisterEnsureACL(conn) < 0)
        return -1;

4042 4043 4044 4045
    if (virDomainEventStateRegister(conn,
                                    driver->domainEventState,
                                    callback, opaque, freecb) < 0)
        return -1;
4046

4047
    return 0;
4048 4049 4050 4051
}


static int
4052 4053
libxlConnectDomainEventDeregister(virConnectPtr conn,
                                  virConnectDomainEventCallback callback)
4054 4055 4056
{
    libxlDriverPrivatePtr driver = conn->privateData;

4057 4058 4059
    if (virConnectDomainEventDeregisterEnsureACL(conn) < 0)
        return -1;

4060 4061 4062 4063
    if (virDomainEventStateDeregister(conn,
                                      driver->domainEventState,
                                      callback) < 0)
        return -1;
4064

4065
    return 0;
4066 4067
}

4068 4069 4070 4071 4072 4073
static int
libxlDomainGetAutostart(virDomainPtr dom, int *autostart)
{
    virDomainObjPtr vm;
    int ret = -1;

J
Jim Fehlig 已提交
4074
    if (!(vm = libxlDomObjFromDomain(dom)))
4075 4076
        goto cleanup;

4077 4078 4079
    if (virDomainGetAutostartEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

4080 4081 4082
    *autostart = vm->autostart;
    ret = 0;

4083
 cleanup:
4084
    if (vm)
4085
        virObjectUnlock(vm);
4086 4087 4088 4089 4090 4091 4092
    return ret;
}

static int
libxlDomainSetAutostart(virDomainPtr dom, int autostart)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
4093
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
4094 4095 4096 4097
    virDomainObjPtr vm;
    char *configFile = NULL, *autostartLink = NULL;
    int ret = -1;

J
Jim Fehlig 已提交
4098
    if (!(vm = libxlDomObjFromDomain(dom)))
4099 4100
        goto cleanup;

J
Jim Fehlig 已提交
4101 4102
    LIBXL_CHECK_DOM0_GOTO(vm->def->name, cleanup);

4103 4104 4105
    if (virDomainSetAutostartEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

4106 4107 4108
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

4109
    if (!vm->persistent) {
4110 4111
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("cannot set autostart for transient domain"));
4112
        goto endjob;
4113 4114 4115 4116 4117
    }

    autostart = (autostart != 0);

    if (vm->autostart != autostart) {
4118
        if (!(configFile = virDomainConfigFile(cfg->configDir, vm->def->name)))
4119
            goto endjob;
4120
        if (!(autostartLink = virDomainConfigFile(cfg->autostartDir, vm->def->name)))
4121
            goto endjob;
4122 4123

        if (autostart) {
4124
            if (virFileMakePath(cfg->autostartDir) < 0) {
4125
                virReportSystemError(errno,
4126
                                     _("cannot create autostart directory %s"),
4127
                                     cfg->autostartDir);
4128
                goto endjob;
4129 4130 4131 4132 4133 4134
            }

            if (symlink(configFile, autostartLink) < 0) {
                virReportSystemError(errno,
                                     _("Failed to create symlink '%s to '%s'"),
                                     autostartLink, configFile);
4135
                goto endjob;
4136 4137 4138 4139 4140 4141
            }
        } else {
            if (unlink(autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) {
                virReportSystemError(errno,
                                     _("Failed to delete symlink '%s'"),
                                     autostartLink);
4142
                goto endjob;
4143 4144 4145 4146 4147 4148 4149
            }
        }

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

4150
 endjob:
4151 4152 4153
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

4154
 cleanup:
4155 4156 4157
    VIR_FREE(configFile);
    VIR_FREE(autostartLink);
    if (vm)
4158
        virObjectUnlock(vm);
4159
    virObjectUnref(cfg);
4160 4161 4162
    return ret;
}

4163 4164 4165
static char *
libxlDomainGetSchedulerType(virDomainPtr dom, int *nparams)
{
J
Jim Fehlig 已提交
4166 4167
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
4168 4169
    virDomainObjPtr vm;
    char * ret = NULL;
4170
    const char *name = NULL;
J
Jim Fehlig 已提交
4171
    libxl_scheduler sched_id;
4172

J
Jim Fehlig 已提交
4173
    if (!(vm = libxlDomObjFromDomain(dom)))
4174 4175
        goto cleanup;

4176 4177 4178
    if (virDomainGetSchedulerTypeEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

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

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

4186 4187
    if (nparams)
        *nparams = 0;
4188
    switch (sched_id) {
J
Jim Fehlig 已提交
4189
    case LIBXL_SCHEDULER_SEDF:
4190
        name = "sedf";
4191
        break;
J
Jim Fehlig 已提交
4192
    case LIBXL_SCHEDULER_CREDIT:
4193
        name = "credit";
4194 4195
        if (nparams)
            *nparams = XEN_SCHED_CREDIT_NPARAM;
4196
        break;
J
Jim Fehlig 已提交
4197
    case LIBXL_SCHEDULER_CREDIT2:
4198
        name = "credit2";
4199
        break;
J
Jim Fehlig 已提交
4200
    case LIBXL_SCHEDULER_ARINC653:
4201
        name = "arinc653";
4202 4203
        break;
    default:
J
Jim Fehlig 已提交
4204 4205
        virReportError(VIR_ERR_INTERNAL_ERROR,
                   _("Failed to get scheduler id for domain '%d'"
4206
                     " with libxenlight"), vm->def->id);
4207 4208 4209
        goto cleanup;
    }

4210
    ignore_value(VIR_STRDUP(ret, name));
4211

4212
 cleanup:
4213
    if (vm)
4214
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
4215
    virObjectUnref(cfg);
4216 4217 4218
    return ret;
}

4219
static int
4220 4221 4222 4223
libxlDomainGetSchedulerParametersFlags(virDomainPtr dom,
                                       virTypedParameterPtr params,
                                       int *nparams,
                                       unsigned int flags)
4224
{
J
Jim Fehlig 已提交
4225 4226
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
4227
    virDomainObjPtr vm;
J
Jim Fehlig 已提交
4228 4229
    libxl_domain_sched_params sc_info;
    libxl_scheduler sched_id;
4230 4231
    int ret = -1;

4232 4233 4234 4235
    virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);

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

J
Jim Fehlig 已提交
4237
    if (!(vm = libxlDomObjFromDomain(dom)))
4238 4239
        goto cleanup;

4240 4241 4242
    if (virDomainGetSchedulerParametersFlagsEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

4243
    if (!virDomainObjIsActive(vm)) {
J
Jim Fehlig 已提交
4244 4245
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("Domain is not running"));
4246 4247 4248
        goto cleanup;
    }

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

J
Jim Fehlig 已提交
4251
    if (sched_id != LIBXL_SCHEDULER_CREDIT) {
4252 4253
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Only 'credit' scheduler is supported"));
4254 4255 4256
        goto cleanup;
    }

J
Jim Fehlig 已提交
4257
    if (libxl_domain_sched_params_get(cfg->ctx, vm->def->id, &sc_info) != 0) {
4258 4259
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to get scheduler parameters for domain '%d'"
4260
                         " with libxenlight"), vm->def->id);
4261 4262 4263
        goto cleanup;
    }

4264 4265
    if (virTypedParameterAssign(&params[0], VIR_DOMAIN_SCHEDULER_WEIGHT,
                                VIR_TYPED_PARAM_UINT, sc_info.weight) < 0)
4266 4267
        goto cleanup;

4268
    if (*nparams > 1) {
4269 4270
        if (virTypedParameterAssign(&params[0], VIR_DOMAIN_SCHEDULER_CAP,
                                    VIR_TYPED_PARAM_UINT, sc_info.cap) < 0)
4271
            goto cleanup;
4272 4273
    }

4274 4275
    if (*nparams > XEN_SCHED_CREDIT_NPARAM)
        *nparams = XEN_SCHED_CREDIT_NPARAM;
4276 4277
    ret = 0;

4278
 cleanup:
4279
    if (vm)
4280
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
4281
    virObjectUnref(cfg);
4282 4283 4284 4285
    return ret;
}

static int
4286 4287 4288 4289 4290 4291 4292 4293 4294 4295 4296
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)
4297
{
4298
    libxlDriverPrivatePtr driver = dom->conn->privateData;
J
Jim Fehlig 已提交
4299
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
4300
    virDomainObjPtr vm;
J
Jim Fehlig 已提交
4301
    libxl_domain_sched_params sc_info;
4302
    int sched_id;
4303
    size_t i;
4304 4305
    int ret = -1;

4306
    virCheckFlags(0, -1);
4307 4308 4309 4310 4311 4312
    if (virTypedParamsValidate(params, nparams,
                               VIR_DOMAIN_SCHEDULER_WEIGHT,
                               VIR_TYPED_PARAM_UINT,
                               VIR_DOMAIN_SCHEDULER_CAP,
                               VIR_TYPED_PARAM_UINT,
                               NULL) < 0)
4313
        return -1;
4314

J
Jim Fehlig 已提交
4315
    if (!(vm = libxlDomObjFromDomain(dom)))
4316 4317
        goto cleanup;

4318 4319 4320
    if (virDomainSetSchedulerParametersFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
        goto cleanup;

4321 4322 4323
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

4324
    if (!virDomainObjIsActive(vm)) {
4325
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
4326
        goto endjob;
4327 4328
    }

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

J
Jim Fehlig 已提交
4331
    if (sched_id != LIBXL_SCHEDULER_CREDIT) {
4332 4333
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Only 'credit' scheduler is supported"));
4334
        goto endjob;
4335 4336
    }

J
Jim Fehlig 已提交
4337
    if (libxl_domain_sched_params_get(cfg->ctx, vm->def->id, &sc_info) != 0) {
4338 4339
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to get scheduler parameters for domain '%d'"
4340
                         " with libxenlight"), vm->def->id);
4341
        goto endjob;
4342 4343 4344
    }

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

4347
        if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_WEIGHT))
4348
            sc_info.weight = params[i].value.ui;
4349
        else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_CAP))
4350 4351 4352
            sc_info.cap = params[i].value.ui;
    }

J
Jim Fehlig 已提交
4353
    if (libxl_domain_sched_params_set(cfg->ctx, vm->def->id, &sc_info) != 0) {
4354 4355
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to set scheduler parameters for domain '%d'"
4356
                         " with libxenlight"), vm->def->id);
4357
        goto endjob;
4358 4359 4360 4361
    }

    ret = 0;

4362
 endjob:
4363 4364 4365
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

4366
 cleanup:
4367
    if (vm)
4368
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
4369
    virObjectUnref(cfg);
4370 4371 4372
    return ret;
}

B
Bamvor Jian Zhang 已提交
4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 4391 4392 4393

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 已提交
4394
    if (!(vm = libxlDomObjFromDomain(dom)))
B
Bamvor Jian Zhang 已提交
4395 4396
        goto cleanup;

J
Jim Fehlig 已提交
4397 4398
    LIBXL_CHECK_DOM0_GOTO(vm->def->name, cleanup);

B
Bamvor Jian Zhang 已提交
4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409
    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 已提交
4410 4411
    if (vm->def->nconsoles)
        chr = vm->def->consoles[0];
B
Bamvor Jian Zhang 已提交
4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422

    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"),
4423
                       dev_name ? dev_name : NULLSTR(chr->info.alias));
B
Bamvor Jian Zhang 已提交
4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438
        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;
    }

4439
 cleanup:
B
Bamvor Jian Zhang 已提交
4440 4441 4442 4443 4444
    if (vm)
        virObjectUnlock(vm);
    return ret;
}

4445 4446 4447 4448 4449 4450 4451
static int
libxlDomainSetSchedulerParameters(virDomainPtr dom, virTypedParameterPtr params,
                                  int nparams)
{
    return libxlDomainSetSchedulerParametersFlags(dom, params, nparams, 0);
}

4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464
/* 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 已提交
4465 4466
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
4467 4468 4469 4470 4471 4472 4473 4474 4475 4476 4477 4478 4479 4480 4481 4482
    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;

4483 4484
    libxl_bitmap_init(&nodemap);

J
Jim Fehlig 已提交
4485
    if (!(vm = libxlDomObjFromDomain(dom)))
4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503 4504
        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];
4505
        int numnodes;
4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523

        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 已提交
4524
            numnodes = libxl_get_max_nodes(cfg->ctx);
4525 4526 4527
            if (numnodes <= 0)
                goto cleanup;

J
Jim Fehlig 已提交
4528
            if (libxl_node_bitmap_alloc(cfg->ctx, &nodemap, 0)) {
4529 4530 4531
                virReportOOMError();
                goto cleanup;
            }
J
Ján Tomko 已提交
4532 4533
            if (!(nodes = virBitmapNew(numnodes)))
                goto cleanup;
4534

J
Jim Fehlig 已提交
4535
            rc = libxl_domain_get_nodeaffinity(cfg->ctx,
4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554
                                               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;
                }
            }

4555
            if (!(nodeset = virBitmapFormat(nodes)))
4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571
                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;

4572
 cleanup:
4573 4574 4575 4576 4577
    VIR_FREE(nodeset);
    virBitmapFree(nodes);
    libxl_bitmap_dispose(&nodemap);
    if (vm)
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
4578
    virObjectUnref(cfg);
4579 4580 4581 4582
    return ret;
}
#endif

J
Jim Fehlig 已提交
4583 4584 4585 4586 4587 4588
static int
libxlDomainIsActive(virDomainPtr dom)
{
    virDomainObjPtr obj;
    int ret = -1;

J
Jim Fehlig 已提交
4589
    if (!(obj = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
4590
        goto cleanup;
4591 4592 4593 4594

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

J
Jim Fehlig 已提交
4595 4596
    ret = virDomainObjIsActive(obj);

4597
 cleanup:
J
Jim Fehlig 已提交
4598
    if (obj)
4599
        virObjectUnlock(obj);
J
Jim Fehlig 已提交
4600 4601 4602 4603 4604 4605 4606 4607 4608
    return ret;
}

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

J
Jim Fehlig 已提交
4609
    if (!(obj = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
4610
        goto cleanup;
4611 4612 4613 4614

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

J
Jim Fehlig 已提交
4615 4616
    ret = obj->persistent;

4617
 cleanup:
J
Jim Fehlig 已提交
4618
    if (obj)
4619
        virObjectUnlock(obj);
J
Jim Fehlig 已提交
4620 4621 4622
    return ret;
}

4623 4624 4625 4626 4627 4628
static int
libxlDomainIsUpdated(virDomainPtr dom)
{
    virDomainObjPtr vm;
    int ret = -1;

J
Jim Fehlig 已提交
4629
    if (!(vm = libxlDomObjFromDomain(dom)))
4630
        goto cleanup;
4631 4632 4633 4634

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

4635 4636
    ret = vm->updated;

4637
 cleanup:
4638
    if (vm)
4639
        virObjectUnlock(vm);
4640 4641 4642
    return ret;
}

4643
static int
4644 4645 4646
libxlConnectDomainEventRegisterAny(virConnectPtr conn, virDomainPtr dom, int eventID,
                                   virConnectDomainEventGenericCallback callback,
                                   void *opaque, virFreeCallback freecb)
4647 4648 4649 4650
{
    libxlDriverPrivatePtr driver = conn->privateData;
    int ret;

4651 4652 4653
    if (virConnectDomainEventRegisterAnyEnsureACL(conn) < 0)
        return -1;

4654 4655 4656 4657
    if (virDomainEventStateRegisterID(conn,
                                      driver->domainEventState,
                                      dom, eventID, callback, opaque,
                                      freecb, &ret) < 0)
4658
        ret = -1;
4659 4660 4661 4662 4663 4664

    return ret;
}


static int
4665
libxlConnectDomainEventDeregisterAny(virConnectPtr conn, int callbackID)
4666 4667 4668
{
    libxlDriverPrivatePtr driver = conn->privateData;

4669 4670 4671
    if (virConnectDomainEventDeregisterAnyEnsureACL(conn) < 0)
        return -1;

4672 4673 4674 4675
    if (virObjectEventStateDeregisterID(conn,
                                        driver->domainEventState,
                                        callbackID) < 0)
        return -1;
4676

4677
    return 0;
4678 4679
}

J
Jim Fehlig 已提交
4680

4681
static int
4682
libxlConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED)
4683 4684 4685 4686
{
    return 1;
}

4687
static int
4688 4689 4690
libxlConnectListAllDomains(virConnectPtr conn,
                           virDomainPtr **domains,
                           unsigned int flags)
4691 4692 4693 4694
{
    libxlDriverPrivatePtr driver = conn->privateData;
    int ret = -1;

O
Osier Yang 已提交
4695
    virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
4696

4697 4698 4699
    if (virConnectListAllDomainsEnsureACL(conn) < 0)
        return -1;

4700 4701
    ret = virDomainObjListExport(driver->domains, conn, domains,
                                 virConnectListAllDomainsCheckACL, flags);
4702 4703 4704 4705

    return ret;
}

4706 4707 4708 4709 4710 4711 4712 4713 4714
/* 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 已提交
4715
    case VIR_DRV_FEATURE_MIGRATION_PARAMS:
4716 4717 4718 4719 4720
        return 1;
    default:
        return 0;
    }
}
4721

4722 4723 4724 4725 4726 4727 4728 4729 4730 4731 4732
static int
libxlNodeDeviceGetPCIInfo(virNodeDeviceDefPtr def,
                          unsigned *domain,
                          unsigned *bus,
                          unsigned *slot,
                          unsigned *function)
{
    virNodeDevCapsDefPtr cap;

    cap = def->caps;
    while (cap) {
4733
        if (cap->data.type == VIR_NODE_DEV_CAP_PCI_DEV) {
4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746
            *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 已提交
4747
        return -1;
4748 4749
    }

C
Chunyan Liu 已提交
4750
    return 0;
4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798
}

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;
4799
 cleanup:
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
    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 已提交
4842
        goto cleanup;
4843 4844

    ret = 0;
C
Chunyan Liu 已提交
4845

4846
 cleanup:
C
Chunyan Liu 已提交
4847
    virPCIDeviceFree(pci);
4848 4849 4850 4851 4852 4853 4854 4855
    virNodeDeviceDefFree(def);
    VIR_FREE(xml);
    return ret;
}

static int
libxlNodeDeviceReset(virNodeDevicePtr dev)
{
C
Chunyan Liu 已提交
4856
    virPCIDevicePtr pci = NULL;
4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882
    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 已提交
4883
        goto cleanup;
4884 4885

    ret = 0;
C
Chunyan Liu 已提交
4886

4887
 cleanup:
C
Chunyan Liu 已提交
4888
    virPCIDeviceFree(pci);
4889 4890 4891 4892 4893
    virNodeDeviceDefFree(def);
    VIR_FREE(xml);
    return ret;
}

J
Jim Fehlig 已提交
4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904
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;

4905 4906 4907 4908 4909
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
    virReportUnsupportedError();
    return NULL;
#endif

J
Jim Fehlig 已提交
4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921
    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;

J
Jim Fehlig 已提交
4922 4923 4924 4925 4926 4927
    if (STREQ_NULLABLE(vm->def->name, "Domain-0")) {
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                           _("Domain-0 cannot be migrated"));
            return NULL;
    }

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 4952 4953 4954 4955 4956 4957 4958 4959
    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;

4960 4961 4962 4963 4964
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
    virReportUnsupportedError();
    return -1;
#endif

J
Jim Fehlig 已提交
4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 4981 4982 4983 4984 4985 4986
    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;

4987
    if (libxlDomainMigrationPrepare(dconn, &def, uri_in, uri_out, flags) < 0)
J
Jim Fehlig 已提交
4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 4998 4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014
        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;

5015 5016 5017 5018 5019
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
    virReportUnsupportedError();
    return -1;
#endif

J
Jim Fehlig 已提交
5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042
    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,
5043
                                    uri, dname, flags) < 0)
J
Jim Fehlig 已提交
5044 5045 5046 5047 5048 5049 5050 5051 5052 5053 5054 5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067
        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;
5068
    virDomainPtr ret = NULL;
J
Jim Fehlig 已提交
5069

5070 5071 5072 5073 5074
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
    virReportUnsupportedError();
    return NULL;
#endif

J
Jim Fehlig 已提交
5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094
    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) {
5095
        virDomainObjEndAPI(&vm);
J
Jim Fehlig 已提交
5096 5097 5098
        return NULL;
    }

5099
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0) {
5100
        virDomainObjEndAPI(&vm);
5101 5102 5103 5104 5105 5106 5107 5108
        return NULL;
    }

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

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

5109
    virDomainObjEndAPI(&vm);
5110 5111

    return ret;
J
Jim Fehlig 已提交
5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125
}

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;

5126 5127 5128 5129 5130
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
    virReportUnsupportedError();
    return -1;
#endif

J
Jim Fehlig 已提交
5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145
    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);
}

5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160 5161 5162
static int libxlNodeGetSecurityModel(virConnectPtr conn,
                                     virSecurityModelPtr secmodel)
{
    memset(secmodel, 0, sizeof(*secmodel));

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

    /*
     * Currently the libxl driver does not support security model.
     * Similar to the qemu driver, treat this as success and simply
     * return no data in secmodel.  Avoids spamming the libvirt log
     * with "this function is not supported by the connection driver:
     * virNodeGetSecurityModel"
     */
    return 0;
}
5163

5164
static virHypervisorDriver libxlHypervisorDriver = {
5165
    .name = LIBXL_DRIVER_NAME,
5166 5167 5168 5169
    .connectOpen = libxlConnectOpen, /* 0.9.0 */
    .connectClose = libxlConnectClose, /* 0.9.0 */
    .connectGetType = libxlConnectGetType, /* 0.9.0 */
    .connectGetVersion = libxlConnectGetVersion, /* 0.9.0 */
5170
    .connectGetHostname = libxlConnectGetHostname, /* 0.9.0 */
5171
    .connectGetSysinfo = libxlConnectGetSysinfo, /* 1.1.0 */
5172
    .connectGetMaxVcpus = libxlConnectGetMaxVcpus, /* 0.9.0 */
5173
    .nodeGetInfo = libxlNodeGetInfo, /* 0.9.0 */
5174 5175 5176 5177
    .connectGetCapabilities = libxlConnectGetCapabilities, /* 0.9.0 */
    .connectListDomains = libxlConnectListDomains, /* 0.9.0 */
    .connectNumOfDomains = libxlConnectNumOfDomains, /* 0.9.0 */
    .connectListAllDomains = libxlConnectListAllDomains, /* 0.9.13 */
5178 5179 5180 5181 5182 5183 5184
    .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 */
5185
    .domainShutdownFlags = libxlDomainShutdownFlags, /* 0.9.10 */
5186 5187
    .domainReboot = libxlDomainReboot, /* 0.9.0 */
    .domainDestroy = libxlDomainDestroy, /* 0.9.0 */
5188
    .domainDestroyFlags = libxlDomainDestroyFlags, /* 0.9.4 */
5189 5190
    .domainGetOSType = libxlDomainGetOSType, /* 0.9.0 */
    .domainGetMaxMemory = libxlDomainGetMaxMemory, /* 0.9.0 */
5191
    .domainSetMaxMemory = libxlDomainSetMaxMemory, /* 0.9.2 */
5192 5193 5194 5195
    .domainSetMemory = libxlDomainSetMemory, /* 0.9.0 */
    .domainSetMemoryFlags = libxlDomainSetMemoryFlags, /* 0.9.0 */
    .domainGetInfo = libxlDomainGetInfo, /* 0.9.0 */
    .domainGetState = libxlDomainGetState, /* 0.9.2 */
5196
    .domainSave = libxlDomainSave, /* 0.9.2 */
5197
    .domainSaveFlags = libxlDomainSaveFlags, /* 0.9.4 */
5198
    .domainRestore = libxlDomainRestore, /* 0.9.2 */
5199
    .domainRestoreFlags = libxlDomainRestoreFlags, /* 0.9.4 */
5200
    .domainCoreDump = libxlDomainCoreDump, /* 0.9.2 */
5201 5202 5203 5204
    .domainSetVcpus = libxlDomainSetVcpus, /* 0.9.0 */
    .domainSetVcpusFlags = libxlDomainSetVcpusFlags, /* 0.9.0 */
    .domainGetVcpusFlags = libxlDomainGetVcpusFlags, /* 0.9.0 */
    .domainPinVcpu = libxlDomainPinVcpu, /* 0.9.0 */
5205
    .domainPinVcpuFlags = libxlDomainPinVcpuFlags, /* 1.2.1 */
5206
    .domainGetVcpus = libxlDomainGetVcpus, /* 0.9.0 */
5207
    .domainGetVcpuPinInfo = libxlDomainGetVcpuPinInfo, /* 1.2.1 */
5208
    .domainGetXMLDesc = libxlDomainGetXMLDesc, /* 0.9.0 */
5209 5210 5211 5212
    .connectDomainXMLFromNative = libxlConnectDomainXMLFromNative, /* 0.9.0 */
    .connectDomainXMLToNative = libxlConnectDomainXMLToNative, /* 0.9.0 */
    .connectListDefinedDomains = libxlConnectListDefinedDomains, /* 0.9.0 */
    .connectNumOfDefinedDomains = libxlConnectNumOfDefinedDomains, /* 0.9.0 */
5213 5214 5215
    .domainCreate = libxlDomainCreate, /* 0.9.0 */
    .domainCreateWithFlags = libxlDomainCreateWithFlags, /* 0.9.0 */
    .domainDefineXML = libxlDomainDefineXML, /* 0.9.0 */
5216
    .domainDefineXMLFlags = libxlDomainDefineXMLFlags, /* 1.2.12 */
5217
    .domainUndefine = libxlDomainUndefine, /* 0.9.0 */
5218
    .domainUndefineFlags = libxlDomainUndefineFlags, /* 0.9.4 */
5219 5220 5221 5222 5223
    .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 */
5224 5225 5226 5227
    .domainGetAutostart = libxlDomainGetAutostart, /* 0.9.0 */
    .domainSetAutostart = libxlDomainSetAutostart, /* 0.9.0 */
    .domainGetSchedulerType = libxlDomainGetSchedulerType, /* 0.9.0 */
    .domainGetSchedulerParameters = libxlDomainGetSchedulerParameters, /* 0.9.0 */
5228
    .domainGetSchedulerParametersFlags = libxlDomainGetSchedulerParametersFlags, /* 0.9.2 */
5229
    .domainSetSchedulerParameters = libxlDomainSetSchedulerParameters, /* 0.9.0 */
5230
    .domainSetSchedulerParametersFlags = libxlDomainSetSchedulerParametersFlags, /* 0.9.2 */
5231 5232 5233
#ifdef LIBXL_HAVE_DOMAIN_NODEAFFINITY
    .domainGetNumaParameters = libxlDomainGetNumaParameters, /* 1.1.1 */
#endif
5234
    .nodeGetFreeMemory = libxlNodeGetFreeMemory, /* 0.9.0 */
5235
    .nodeGetCellsFreeMemory = libxlNodeGetCellsFreeMemory, /* 1.1.1 */
5236 5237
    .connectDomainEventRegister = libxlConnectDomainEventRegister, /* 0.9.0 */
    .connectDomainEventDeregister = libxlConnectDomainEventDeregister, /* 0.9.0 */
5238 5239 5240
    .domainManagedSave = libxlDomainManagedSave, /* 0.9.2 */
    .domainHasManagedSaveImage = libxlDomainHasManagedSaveImage, /* 0.9.2 */
    .domainManagedSaveRemove = libxlDomainManagedSaveRemove, /* 0.9.2 */
B
Bamvor Jian Zhang 已提交
5241
    .domainOpenConsole = libxlDomainOpenConsole, /* 1.1.2 */
5242 5243 5244
    .domainIsActive = libxlDomainIsActive, /* 0.9.0 */
    .domainIsPersistent = libxlDomainIsPersistent, /* 0.9.0 */
    .domainIsUpdated = libxlDomainIsUpdated, /* 0.9.0 */
5245 5246 5247
    .connectDomainEventRegisterAny = libxlConnectDomainEventRegisterAny, /* 0.9.0 */
    .connectDomainEventDeregisterAny = libxlConnectDomainEventDeregisterAny, /* 0.9.0 */
    .connectIsAlive = libxlConnectIsAlive, /* 0.9.8 */
5248
    .connectSupportsFeature = libxlConnectSupportsFeature, /* 1.1.1 */
5249 5250 5251 5252
    .nodeDeviceDettach = libxlNodeDeviceDettach, /* 1.2.3 */
    .nodeDeviceDetachFlags = libxlNodeDeviceDetachFlags, /* 1.2.3 */
    .nodeDeviceReAttach = libxlNodeDeviceReAttach, /* 1.2.3 */
    .nodeDeviceReset = libxlNodeDeviceReset, /* 1.2.3 */
5253 5254 5255 5256 5257
    .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 */
5258
    .nodeGetSecurityModel = libxlNodeGetSecurityModel, /* 1.2.16 */
J
Jim Fehlig 已提交
5259 5260
};

5261 5262 5263 5264
static virConnectDriver libxlConnectDriver = {
    .hypervisorDriver = &libxlHypervisorDriver,
};

J
Jim Fehlig 已提交
5265 5266
static virStateDriver libxlStateDriver = {
    .name = "LIBXL",
5267
    .stateInitialize = libxlStateInitialize,
5268
    .stateAutoStart = libxlStateAutoStart,
5269 5270
    .stateCleanup = libxlStateCleanup,
    .stateReload = libxlStateReload,
J
Jim Fehlig 已提交
5271 5272 5273 5274 5275 5276
};


int
libxlRegister(void)
{
5277 5278
    if (virRegisterConnectDriver(&libxlConnectDriver,
                                 true) < 0)
J
Jim Fehlig 已提交
5279 5280 5281 5282 5283 5284
        return -1;
    if (virRegisterStateDriver(&libxlStateDriver) < 0)
        return -1;

    return 0;
}