libxl_driver.c 194.0 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 <xenstore.h>
34
#include <fcntl.h>
35
#include <regex.h>
J
Jim Fehlig 已提交
36 37

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

#define VIR_FROM_THIS VIR_FROM_LIBXL

68 69
VIR_LOG_INIT("libxl.libxl_driver");

J
Jim Fehlig 已提交
70 71 72 73 74 75
#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

76
#define LIBXL_NB_TOTAL_CPU_STAT_PARAM 1
77
#define LIBXL_NB_TOTAL_BLK_STAT_PARAM 6
78

79
#define HYPERVISOR_CAPABILITIES "/proc/xen/capabilities"
R
Roman Bogorodskiy 已提交
80
#define HYPERVISOR_XENSTORED "/dev/xen/xenstored"
81

82 83 84
/* Number of Xen scheduler parameters */
#define XEN_SCHED_CREDIT_NPARAM   2

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

94

95
static libxlDriverPrivatePtr libxl_driver;
J
Jim Fehlig 已提交
96

97 98 99 100 101 102 103 104 105
/* 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;
};

106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
/* Object used to store disk statistics across multiple xen backends */
typedef struct _libxlBlockStats libxlBlockStats;
typedef libxlBlockStats *libxlBlockStatsPtr;
struct _libxlBlockStats {
    long long rd_req;
    long long rd_bytes;
    long long wr_req;
    long long wr_bytes;
    long long f_req;

    char *backend;
    union {
        struct {
            long long ds_req;
            long long oo_req;
        } vbd;
    } u;
};

J
Jim Fehlig 已提交
125
/* Function declarations */
126 127
static int
libxlDomainManagedSaveLoad(virDomainObjPtr vm,
128 129
                           void *opaque);

J
Jim Fehlig 已提交
130 131

/* Function definitions */
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 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308
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 已提交
309 310 311 312 313 314 315
static virDomainObjPtr
libxlDomObjFromDomain(virDomainPtr dom)
{
    virDomainObjPtr vm;
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    char uuidstr[VIR_UUID_STRING_BUFLEN];

W
Wang Yufei 已提交
316
    vm = virDomainObjListFindByUUIDRef(driver->domains, dom->uuid);
J
Jim Fehlig 已提交
317 318 319 320 321 322 323 324 325 326 327
    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;
}

328 329
static int
libxlAutostartDomain(virDomainObjPtr vm,
330 331 332
                     void *opaque)
{
    libxlDriverPrivatePtr driver = opaque;
333
    int ret = -1;
334

W
Wang Yufei 已提交
335
    virObjectRef(vm);
336
    virObjectLock(vm);
337 338
    virResetLastError();

W
Wang Yufei 已提交
339 340
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;
341

342
    if (vm->autostart && !virDomainObjIsActive(vm) &&
343
        libxlDomainStartNew(driver, vm, false) < 0) {
344 345 346
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to autostart VM '%s': %s"),
                       vm->def->name, virGetLastErrorMessage());
347
        goto endjob;
348 349
    }

350
    ret = 0;
351 352

 endjob:
W
Wang Yufei 已提交
353 354 355
    libxlDomainObjEndJob(driver, vm);
 cleanup:
    virDomainObjEndAPI(&vm);
356

357
    return ret;
358 359
}

J
Jim Fehlig 已提交
360 361 362 363
/*
 * Reconnect to running domains that were previously started/created
 * with libxenlight driver.
 */
364 365
static int
libxlReconnectDomain(virDomainObjPtr vm,
J
Jim Fehlig 已提交
366 367 368
                     void *opaque)
{
    libxlDriverPrivatePtr driver = opaque;
369
    libxlDomainObjPrivatePtr priv = vm->privateData;
J
Jim Fehlig 已提交
370
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
J
Jim Fehlig 已提交
371 372 373 374
    int rc;
    libxl_dominfo d_info;
    int len;
    uint8_t *data = NULL;
375
    virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
376
    unsigned int hostdev_flags = VIR_HOSTDEV_SP_PCI;
377
    int ret = -1;
378 379 380 381

#ifdef LIBXL_HAVE_PVUSB
    hostdev_flags |= VIR_HOSTDEV_SP_USB;
#endif
J
Jim Fehlig 已提交
382

383
    virObjectRef(vm);
384
    virObjectLock(vm);
J
Jim Fehlig 已提交
385

386 387
    libxl_dominfo_init(&d_info);

J
Jim Fehlig 已提交
388
    /* Does domain still exist? */
J
Jim Fehlig 已提交
389
    rc = libxl_domain_info(cfg->ctx, &d_info, vm->def->id);
J
Jim Fehlig 已提交
390
    if (rc == ERROR_INVAL) {
391
        goto error;
J
Jim Fehlig 已提交
392 393 394
    } else if (rc != 0) {
        VIR_DEBUG("libxl_domain_info failed (code %d), ignoring domain %d",
                  rc, vm->def->id);
395
        goto error;
J
Jim Fehlig 已提交
396 397 398
    }

    /* Is this a domain that was under libvirt control? */
J
Jim Fehlig 已提交
399
    if (libxl_userdata_retrieve(cfg->ctx, vm->def->id,
J
Jim Fehlig 已提交
400 401
                                "libvirt-xml", &data, &len)) {
        VIR_DEBUG("libxl_userdata_retrieve failed, ignoring domain %d", vm->def->id);
402
        goto error;
J
Jim Fehlig 已提交
403 404 405 406
    }

    /* Update domid in case it changed (e.g. reboot) while we were gone? */
    vm->def->id = d_info.domid;
407

408 409
    libxlLoggerOpenFile(cfg->logger, vm->def->id, vm->def->name, NULL);

410
    /* Update hostdev state */
411
    if (virHostdevUpdateActiveDomainDevices(hostdev_mgr, LIBXL_DRIVER_NAME,
412
                                            vm->def, hostdev_flags) < 0)
413
        goto error;
414

415
    if (virAtomicIntInc(&driver->nactive) == 1 && driver->inhibitCallback)
416 417
        driver->inhibitCallback(true, driver->inhibitOpaque);

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

C
Cédric Bosdonnat 已提交
421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441
    /* now that we know it's reconnected call the hook if present */
    if (virHookPresent(VIR_HOOK_DRIVER_LIBXL) &&
        STRNEQ("Domain-0", vm->def->name)) {
        char *xml = virDomainDefFormat(vm->def, cfg->caps, 0);
        int hookret;

        /* we can't stop the operation even if the script raised an error */
        hookret = virHookCall(VIR_HOOK_DRIVER_LIBXL, vm->def->name,
                              VIR_HOOK_LIBXL_OP_RECONNECT, VIR_HOOK_SUBOP_BEGIN,
                              NULL, xml, NULL);
        VIR_FREE(xml);
        if (hookret < 0) {
            /* Stop the domain if the hook failed */
            if (virDomainObjIsActive(vm)) {
                libxlDomainDestroyInternal(driver, vm);
                virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, VIR_DOMAIN_SHUTOFF_FAILED);
            }
            goto error;
        }
    }

442 443 444
    ret = 0;

 cleanup:
445
    libxl_dominfo_dispose(&d_info);
446
    virObjectUnlock(vm);
447
    virObjectUnref(vm);
J
Jim Fehlig 已提交
448
    virObjectUnref(cfg);
449
    return ret;
J
Jim Fehlig 已提交
450

451
 error:
452
    libxlDomainCleanup(driver, vm);
453
    if (!vm->persistent) {
454
        virDomainObjListRemoveLocked(driver->domains, vm);
455

456 457 458 459 460
        /* virDomainObjListRemoveLocked leaves the object unlocked,
         * lock it again to factorize more code. */
        virObjectLock(vm);
    }
    goto cleanup;
J
Jim Fehlig 已提交
461 462 463 464 465
}

static void
libxlReconnectDomains(libxlDriverPrivatePtr driver)
{
466
    virDomainObjListForEach(driver->domains, libxlReconnectDomain, driver);
J
Jim Fehlig 已提交
467 468 469
}

static int
470
libxlStateCleanup(void)
J
Jim Fehlig 已提交
471 472 473 474
{
    if (!libxl_driver)
        return -1;

475
    virObjectUnref(libxl_driver->hostdevMgr);
476
    virObjectUnref(libxl_driver->config);
477
    virObjectUnref(libxl_driver->xmlopt);
478
    virObjectUnref(libxl_driver->domains);
479 480
    virPortAllocatorRangeFree(libxl_driver->reservedGraphicsPorts);
    virPortAllocatorRangeFree(libxl_driver->migrationPorts);
481
    virLockManagerPluginUnref(libxl_driver->lockManager);
J
Jim Fehlig 已提交
482

483
    virObjectUnref(libxl_driver->domainEventState);
484
    virSysinfoDefFree(libxl_driver->hostsysinfo);
485

J
Jim Fehlig 已提交
486 487 488 489 490 491
    virMutexDestroy(&libxl_driver->lock);
    VIR_FREE(libxl_driver);

    return 0;
}

492 493
static bool
libxlDriverShouldLoad(bool privileged)
494
{
495
    bool ret = false;
J
Jim Fehlig 已提交
496

497
    /* Don't load if non-root */
J
Jim Fehlig 已提交
498
    if (!privileged) {
499
        VIR_INFO("Not running privileged, disabling libxenlight driver");
500
        return ret;
J
Jim Fehlig 已提交
501 502
    }

R
Roman Bogorodskiy 已提交
503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523
    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");
524 525 526 527
        return ret;
    }

    /* Don't load if legacy xen toolstack (xend) is in use */
528 529 530 531 532 533 534 535 536 537 538
    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);
539 540
    } else {
        ret = true;
J
Jim Fehlig 已提交
541 542
    }

543 544 545
    return ret;
}

546 547 548 549 550 551 552 553 554 555
/* 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,
};

556 557 558 559 560 561 562 563
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
};

564 565 566 567 568 569
const struct libxl_event_hooks ev_hooks = {
    .event_occurs_mask = LIBXL_EVENTMASK_ALL,
    .event_occurs = libxlDomainEventHandler,
    .disaster = NULL,
};

J
Jim Fehlig 已提交
570 571 572 573 574 575 576 577
static int
libxlAddDom0(libxlDriverPrivatePtr driver)
{
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
    virDomainDefPtr def = NULL;
    virDomainObjPtr vm = NULL;
    virDomainDefPtr oldDef = NULL;
    libxl_dominfo d_info;
578
    unsigned long long maxmem;
J
Jim Fehlig 已提交
579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610
    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 已提交
611
    vm->persistent = 1;
J
Jim Fehlig 已提交
612
    virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_BOOTED);
613
    if (virDomainDefSetVcpusMax(vm->def, d_info.vcpu_max_id + 1, driver->xmlopt))
614 615
        goto cleanup;

616 617
    if (virDomainDefSetVcpus(vm->def, d_info.vcpu_online) < 0)
        goto cleanup;
J
Jim Fehlig 已提交
618
    vm->def->mem.cur_balloon = d_info.current_memkb;
619 620 621
    if (libxlDriverGetDom0MaxmemConf(cfg, &maxmem) < 0)
        maxmem = d_info.current_memkb;
    virDomainDefSetMemoryTotal(vm->def, maxmem);
J
Jim Fehlig 已提交
622 623 624 625 626 627 628 629 630 631 632 633 634

    ret = 0;

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

635 636 637 638 639
static int
libxlStateInitialize(bool privileged,
                     virStateInhibitCallback callback ATTRIBUTE_UNUSED,
                     void *opaque ATTRIBUTE_UNUSED)
{
640
    libxlDriverConfigPtr cfg;
641
    char *driverConf = NULL;
642 643 644 645 646
    char ebuf[1024];

    if (!libxlDriverShouldLoad(privileged))
        return 0;

J
Jim Fehlig 已提交
647 648 649 650
    if (VIR_ALLOC(libxl_driver) < 0)
        return -1;

    if (virMutexInit(&libxl_driver->lock) < 0) {
651 652
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("cannot initialize mutex"));
J
Jim Fehlig 已提交
653 654 655 656 657
        VIR_FREE(libxl_driver);
        return -1;
    }

    /* Allocate bitmap for vnc port reservation */
658
    if (!(libxl_driver->reservedGraphicsPorts =
659 660
          virPortAllocatorRangeNew(_("VNC"),
                                   LIBXL_VNC_PORT_MIN,
661
                                   LIBXL_VNC_PORT_MAX)))
662
        goto error;
J
Jim Fehlig 已提交
663

J
Jim Fehlig 已提交
664 665
    /* Allocate bitmap for migration port reservation */
    if (!(libxl_driver->migrationPorts =
666 667
          virPortAllocatorRangeNew(_("migration"),
                                   LIBXL_MIGRATION_PORT_MIN,
668
                                   LIBXL_MIGRATION_PORT_MAX)))
J
Jim Fehlig 已提交
669 670
        goto error;

671 672
    if (!(libxl_driver->domains = virDomainObjListNew()))
        goto error;
J
Jim Fehlig 已提交
673

674 675 676
    if (!(libxl_driver->hostdevMgr = virHostdevManagerGetDefault()))
        goto error;

677
    if (!(cfg = libxlDriverConfigNew()))
678
        goto error;
J
Jim Fehlig 已提交
679

680 681 682 683 684 685 686
    if (virAsprintf(&driverConf, "%s/libxl.conf", cfg->configBaseDir) < 0)
        goto error;

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

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

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

693 694 695
    /* Register callback to handle domain events */
    libxl_event_register_callbacks(cfg->ctx, &ev_hooks, libxl_driver);

696 697
    libxl_driver->config = cfg;
    if (virFileMakePath(cfg->stateDir) < 0) {
698 699
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to create state dir '%s': %s"),
700
                       cfg->stateDir,
701
                       virStrerror(errno, ebuf, sizeof(ebuf)));
J
Jim Fehlig 已提交
702 703
        goto error;
    }
704
    if (virFileMakePath(cfg->libDir) < 0) {
705 706
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to create lib dir '%s': %s"),
707
                       cfg->libDir,
708
                       virStrerror(errno, ebuf, sizeof(ebuf)));
J
Jim Fehlig 已提交
709 710
        goto error;
    }
711
    if (virFileMakePath(cfg->saveDir) < 0) {
712 713
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to create save dir '%s': %s"),
714
                       cfg->saveDir,
715
                       virStrerror(errno, ebuf, sizeof(ebuf)));
J
Jim Fehlig 已提交
716 717
        goto error;
    }
718 719 720 721 722 723 724
    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
Joao Martins 已提交
725 726 727 728 729 730 731
    if (virFileMakePath(cfg->channelDir) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to create channel dir '%s': %s"),
                       cfg->channelDir,
                       virStrerror(errno, ebuf, sizeof(ebuf)));
        goto error;
    }
J
Jim Fehlig 已提交
732

733 734 735 736 737 738 739 740
    if (!(libxl_driver->lockManager =
          virLockManagerPluginNew(cfg->lockManagerName ?
                                  cfg->lockManagerName : "nop",
                                  "libxl",
                                  cfg->configBaseDir,
                                  0)))
        goto error;

741
    /* read the host sysinfo */
742
    libxl_driver->hostsysinfo = virSysinfoRead();
743

744
    libxl_driver->domainEventState = virObjectEventStateNew();
E
Eric Blake 已提交
745
    if (!libxl_driver->domainEventState)
746 747
        goto error;

748
    if ((cfg->caps = libxlMakeCapabilities(cfg->ctx)) == NULL) {
749 750
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("cannot create capabilities for libxenlight"));
J
Jim Fehlig 已提交
751 752 753
        goto error;
    }

754
    if (!(libxl_driver->xmlopt = libxlCreateXMLConf()))
755
        goto error;
J
Jim Fehlig 已提交
756

J
Jim Fehlig 已提交
757 758 759 760
    /* Add Domain-0 */
    if (libxlAddDom0(libxl_driver) < 0)
        goto error;

J
Jim Fehlig 已提交
761
    /* Load running domains first. */
762
    if (virDomainObjListLoadAllConfigs(libxl_driver->domains,
763 764
                                       cfg->stateDir,
                                       cfg->autostartDir,
765
                                       true,
766
                                       cfg->caps,
767
                                       libxl_driver->xmlopt,
768
                                       NULL, NULL) < 0)
J
Jim Fehlig 已提交
769 770 771 772 773
        goto error;

    libxlReconnectDomains(libxl_driver);

    /* Then inactive persistent configs */
774
    if (virDomainObjListLoadAllConfigs(libxl_driver->domains,
775 776
                                       cfg->configDir,
                                       cfg->autostartDir,
777
                                       false,
778
                                       cfg->caps,
779
                                       libxl_driver->xmlopt,
780
                                       NULL, NULL) < 0)
J
Jim Fehlig 已提交
781 782
        goto error;

783 784
    virDomainObjListForEach(libxl_driver->domains, libxlDomainManagedSaveLoad,
                            libxl_driver);
785

J
Jim Fehlig 已提交
786 787
    return 0;

788
 error:
789
    VIR_FREE(driverConf);
790
    libxlStateCleanup();
791
    return -1;
J
Jim Fehlig 已提交
792 793
}

794 795 796 797 798 799 800 801 802 803
static void
libxlStateAutoStart(void)
{
    if (!libxl_driver)
        return;

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

J
Jim Fehlig 已提交
804
static int
805
libxlStateReload(void)
J
Jim Fehlig 已提交
806
{
807 808
    libxlDriverConfigPtr cfg;

J
Jim Fehlig 已提交
809 810 811
    if (!libxl_driver)
        return 0;

812 813
    cfg = libxlDriverConfigGet(libxl_driver);

814
    virDomainObjListLoadAllConfigs(libxl_driver->domains,
815 816
                                   cfg->configDir,
                                   cfg->autostartDir,
817
                                   true,
818
                                   cfg->caps,
819
                                   libxl_driver->xmlopt,
820 821
                                   NULL, libxl_driver);

822 823
    virDomainObjListForEach(libxl_driver->domains, libxlAutostartDomain,
                            libxl_driver);
824

825
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
826 827 828 829
    return 0;
}


830 831 832 833 834 835 836 837 838 839
static int
libxlConnectURIProbe(char **uri)
{
    if (libxl_driver == NULL)
        return 0;

    return VIR_STRDUP(*uri, "xen:///system");
}


J
Jim Fehlig 已提交
840
static virDrvOpenStatus
841 842
libxlConnectOpen(virConnectPtr conn,
                 virConnectAuthPtr auth ATTRIBUTE_UNUSED,
843
                 virConfPtr conf ATTRIBUTE_UNUSED,
844
                 unsigned int flags)
J
Jim Fehlig 已提交
845
{
E
Eric Blake 已提交
846 847
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

J
Jim Fehlig 已提交
848
    if (conn->uri == NULL) {
849
        return VIR_DRV_OPEN_DECLINED;
J
Jim Fehlig 已提交
850 851 852 853 854 855 856
    } else {
        /* Only xen scheme */
        if (conn->uri->scheme == NULL || STRNEQ(conn->uri->scheme, "xen"))
            return VIR_DRV_OPEN_DECLINED;

        /* Error if xen or libxl scheme specified but driver not started. */
        if (libxl_driver == NULL) {
857 858
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("libxenlight state driver is not active"));
J
Jim Fehlig 已提交
859 860 861 862 863 864 865 866
            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")) {
867
            virReportError(VIR_ERR_INTERNAL_ERROR,
868
                           _("unexpected Xen URI path '%s', try xen:///system"),
869
                           NULLSTR(conn->uri->path));
J
Jim Fehlig 已提交
870 871 872 873
            return VIR_DRV_OPEN_ERROR;
        }
    }

874 875 876
    if (virConnectOpenEnsureACL(conn) < 0)
        return VIR_DRV_OPEN_ERROR;

J
Jim Fehlig 已提交
877 878 879 880 881 882
    conn->privateData = libxl_driver;

    return VIR_DRV_OPEN_SUCCESS;
};

static int
883
libxlConnectClose(virConnectPtr conn ATTRIBUTE_UNUSED)
J
Jim Fehlig 已提交
884 885 886 887 888 889
{
    conn->privateData = NULL;
    return 0;
}

static const char *
890
libxlConnectGetType(virConnectPtr conn)
J
Jim Fehlig 已提交
891
{
892 893 894
    if (virConnectGetTypeEnsureACL(conn) < 0)
        return NULL;

J
Jim Fehlig 已提交
895
    return "Xen";
J
Jim Fehlig 已提交
896 897 898
}

static int
899
libxlConnectGetVersion(virConnectPtr conn, unsigned long *version)
J
Jim Fehlig 已提交
900 901
{
    libxlDriverPrivatePtr driver = conn->privateData;
902
    libxlDriverConfigPtr cfg;
J
Jim Fehlig 已提交
903

904 905 906
    if (virConnectGetVersionEnsureACL(conn) < 0)
        return 0;

907 908 909
    cfg = libxlDriverConfigGet(driver);
    *version = cfg->version;
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
910 911 912
    return 0;
}

913

914
static char *libxlConnectGetHostname(virConnectPtr conn)
915
{
916 917 918
    if (virConnectGetHostnameEnsureACL(conn) < 0)
        return NULL;

919 920 921
    return virGetHostname();
}

922 923 924 925 926 927 928 929
static char *
libxlConnectGetSysinfo(virConnectPtr conn, unsigned int flags)
{
    libxlDriverPrivatePtr driver = conn->privateData;
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    virCheckFlags(0, NULL);

930 931 932
    if (virConnectGetSysinfoEnsureACL(conn) < 0)
        return NULL;

933 934 935 936 937 938 939 940
    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;
941
    if (virBufferCheckError(&buf) < 0)
942 943 944
        return NULL;
    return virBufferContentAndReset(&buf);
}
945

J
Jim Fehlig 已提交
946
static int
947
libxlConnectGetMaxVcpus(virConnectPtr conn, const char *type ATTRIBUTE_UNUSED)
J
Jim Fehlig 已提交
948 949 950
{
    int ret;
    libxlDriverPrivatePtr driver = conn->privateData;
951
    libxlDriverConfigPtr cfg;
J
Jim Fehlig 已提交
952

953 954 955
    if (virConnectGetMaxVcpusEnsureACL(conn) < 0)
        return -1;

956 957
    cfg = libxlDriverConfigGet(driver);
    ret = libxl_get_max_cpus(cfg->ctx);
958 959 960 961 962
    /* 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)
963
        ret = -1;
J
Jim Fehlig 已提交
964

965
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
966 967 968 969 970 971
    return ret;
}

static int
libxlNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info)
{
972 973 974
    if (virNodeGetInfoEnsureACL(conn) < 0)
        return -1;

975
    return libxlDriverNodeGetInfo(conn->privateData, info);
J
Jim Fehlig 已提交
976 977 978
}

static char *
979
libxlConnectGetCapabilities(virConnectPtr conn)
J
Jim Fehlig 已提交
980 981 982
{
    libxlDriverPrivatePtr driver = conn->privateData;
    char *xml;
983
    libxlDriverConfigPtr cfg;
J
Jim Fehlig 已提交
984

985 986 987
    if (virConnectGetCapabilitiesEnsureACL(conn) < 0)
        return NULL;

988
    cfg = libxlDriverConfigGet(driver);
989
    xml = virCapabilitiesFormatXML(cfg->caps);
J
Jim Fehlig 已提交
990

991
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
992 993 994 995
    return xml;
}

static int
996
libxlConnectListDomains(virConnectPtr conn, int *ids, int nids)
J
Jim Fehlig 已提交
997 998 999 1000
{
    libxlDriverPrivatePtr driver = conn->privateData;
    int n;

1001 1002 1003
    if (virConnectListDomainsEnsureACL(conn) < 0)
        return -1;

1004 1005
    n = virDomainObjListGetActiveIDs(driver->domains, ids, nids,
                                     virConnectListDomainsCheckACL, conn);
J
Jim Fehlig 已提交
1006 1007 1008 1009 1010

    return n;
}

static int
1011
libxlConnectNumOfDomains(virConnectPtr conn)
J
Jim Fehlig 已提交
1012 1013 1014 1015
{
    libxlDriverPrivatePtr driver = conn->privateData;
    int n;

1016 1017 1018
    if (virConnectNumOfDomainsEnsureACL(conn) < 0)
        return -1;

1019 1020
    n = virDomainObjListNumOfDomains(driver->domains, true,
                                     virConnectNumOfDomainsCheckACL, conn);
J
Jim Fehlig 已提交
1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032

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

1036 1037 1038 1039
    virCheckFlags(VIR_DOMAIN_START_PAUSED |
                  VIR_DOMAIN_START_VALIDATE, NULL);

    if (flags & VIR_DOMAIN_START_VALIDATE)
1040
        parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA;
J
Jim Fehlig 已提交
1041

1042
    if (!(def = virDomainDefParseString(xml, cfg->caps, driver->xmlopt,
1043
                                        NULL, parse_flags)))
J
Jim Fehlig 已提交
1044 1045
        goto cleanup;

1046 1047 1048
    if (virDomainCreateXMLEnsureACL(conn, def) < 0)
        goto cleanup;

1049
    if (!(vm = virDomainObjListAdd(driver->domains, def,
1050
                                   driver->xmlopt,
1051
                                   VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
1052 1053
                                   VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                   NULL)))
J
Jim Fehlig 已提交
1054
        goto cleanup;
W
Wang Yufei 已提交
1055
    virObjectRef(vm);
J
Jim Fehlig 已提交
1056 1057
    def = NULL;

1058 1059 1060
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0) {
        if (!vm->persistent) {
            virDomainObjListRemove(driver->domains, vm);
1061
            virObjectLock(vm);
1062 1063 1064 1065
        }
        goto cleanup;
    }

1066 1067
    if (libxlDomainStartNew(driver, vm,
                         (flags & VIR_DOMAIN_START_PAUSED) != 0) < 0) {
1068 1069
        if (!vm->persistent) {
            virDomainObjListRemove(driver->domains, vm);
1070
            virObjectLock(vm);
1071
        }
1072
        goto endjob;
J
Jim Fehlig 已提交
1073 1074
    }

1075
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid, vm->def->id);
J
Jim Fehlig 已提交
1076

1077
 endjob:
W
Wang Yufei 已提交
1078
    libxlDomainObjEndJob(driver, vm);
1079

1080
 cleanup:
J
Jim Fehlig 已提交
1081
    virDomainDefFree(def);
W
Wang Yufei 已提交
1082
    virDomainObjEndAPI(&vm);
1083
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
1084 1085 1086 1087 1088 1089 1090 1091 1092 1093
    return dom;
}

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

1094
    vm = virDomainObjListFindByIDRef(driver->domains, id);
J
Jim Fehlig 已提交
1095
    if (!vm) {
1096
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
J
Jim Fehlig 已提交
1097 1098 1099
        goto cleanup;
    }

1100 1101 1102
    if (virDomainLookupByIDEnsureACL(conn, vm->def) < 0)
        goto cleanup;

1103
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid, vm->def->id);
J
Jim Fehlig 已提交
1104

1105
 cleanup:
1106
    virDomainObjEndAPI(&vm);
J
Jim Fehlig 已提交
1107 1108 1109 1110 1111 1112 1113 1114 1115 1116
    return dom;
}

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

1117
    vm = virDomainObjListFindByUUIDRef(driver->domains, uuid);
J
Jim Fehlig 已提交
1118
    if (!vm) {
1119
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
J
Jim Fehlig 已提交
1120 1121 1122
        goto cleanup;
    }

1123 1124 1125
    if (virDomainLookupByUUIDEnsureACL(conn, vm->def) < 0)
        goto cleanup;

1126
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid, vm->def->id);
J
Jim Fehlig 已提交
1127

1128
 cleanup:
1129
    virDomainObjEndAPI(&vm);
J
Jim Fehlig 已提交
1130 1131 1132 1133 1134 1135 1136 1137 1138 1139
    return dom;
}

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

1140
    vm = virDomainObjListFindByName(driver->domains, name);
J
Jim Fehlig 已提交
1141
    if (!vm) {
1142
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
J
Jim Fehlig 已提交
1143 1144 1145
        goto cleanup;
    }

1146 1147 1148
    if (virDomainLookupByNameEnsureACL(conn, vm->def) < 0)
        goto cleanup;

1149
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid, vm->def->id);
J
Jim Fehlig 已提交
1150

1151
 cleanup:
1152
    virDomainObjEndAPI(&vm);
J
Jim Fehlig 已提交
1153 1154 1155
    return dom;
}

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

J
Jim Fehlig 已提交
1165
    if (!(vm = libxlDomObjFromDomain(dom)))
1166
        goto cleanup;
1167

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

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

1173 1174 1175
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

1176
    if (!virDomainObjIsActive(vm)) {
1177
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
1178
        goto endjob;
1179 1180
    }

J
Jiri Denemark 已提交
1181
    if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_PAUSED) {
J
Jim Fehlig 已提交
1182
        if (libxl_domain_pause(cfg->ctx, vm->def->id) != 0) {
1183 1184
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Failed to suspend domain '%d' with libxenlight"),
1185
                           vm->def->id);
1186
            goto endjob;
1187 1188
        }

J
Jiri Denemark 已提交
1189
        virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER);
1190

1191
        event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_SUSPENDED,
1192 1193 1194
                                         VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
    }

1195
    if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, cfg->caps) < 0)
1196
        goto endjob;
1197 1198 1199

    ret = 0;

1200
 endjob:
W
Wang Yufei 已提交
1201
    libxlDomainObjEndJob(driver, vm);
1202

1203
 cleanup:
W
Wang Yufei 已提交
1204
    virDomainObjEndAPI(&vm);
1205
    if (event)
1206
        libxlDomainEventQueue(driver, event);
1207
    virObjectUnref(cfg);
1208 1209 1210 1211 1212 1213 1214 1215
    return ret;
}


static int
libxlDomainResume(virDomainPtr dom)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
1216
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
1217
    virDomainObjPtr vm;
1218
    virObjectEventPtr event = NULL;
1219 1220
    int ret = -1;

J
Jim Fehlig 已提交
1221
    if (!(vm = libxlDomObjFromDomain(dom)))
1222 1223
        goto cleanup;

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

1226 1227 1228
    if (virDomainResumeEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

1229 1230 1231
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

1232
    if (!virDomainObjIsActive(vm)) {
1233
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
1234
        goto endjob;
1235 1236
    }

J
Jiri Denemark 已提交
1237
    if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
J
Jim Fehlig 已提交
1238
        if (libxl_domain_unpause(cfg->ctx, vm->def->id) != 0) {
1239 1240
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Failed to resume domain '%d' with libxenlight"),
1241
                           vm->def->id);
1242
            goto endjob;
1243 1244
        }

J
Jiri Denemark 已提交
1245 1246
        virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
                             VIR_DOMAIN_RUNNING_UNPAUSED);
1247

1248
        event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_RESUMED,
1249 1250 1251
                                         VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
    }

1252
    if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, cfg->caps) < 0)
1253
        goto endjob;
1254 1255 1256

    ret = 0;

1257
 endjob:
W
Wang Yufei 已提交
1258
    libxlDomainObjEndJob(driver, vm);
1259

1260
 cleanup:
W
Wang Yufei 已提交
1261
    virDomainObjEndAPI(&vm);
1262
    if (event)
1263
        libxlDomainEventQueue(driver, event);
1264
    virObjectUnref(cfg);
1265 1266 1267
    return ret;
}

J
Jim Fehlig 已提交
1268
static int
1269
libxlDomainShutdownFlags(virDomainPtr dom, unsigned int flags)
J
Jim Fehlig 已提交
1270
{
J
Jim Fehlig 已提交
1271 1272
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
J
Jim Fehlig 已提交
1273 1274 1275
    virDomainObjPtr vm;
    int ret = -1;

1276 1277 1278 1279 1280
    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;
1281

J
Jim Fehlig 已提交
1282
    if (!(vm = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
1283 1284
        goto cleanup;

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

1287
    if (virDomainShutdownFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
1288 1289
        goto cleanup;

J
Jim Fehlig 已提交
1290
    if (!virDomainObjIsActive(vm)) {
1291 1292
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("Domain is not running"));
J
Jim Fehlig 已提交
1293 1294 1295
        goto cleanup;
    }

1296
    if (flags & VIR_DOMAIN_SHUTDOWN_PARAVIRT) {
J
Jim Fehlig 已提交
1297
        ret = libxl_domain_shutdown(cfg->ctx, vm->def->id);
1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311
        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 已提交
1312
        ret = libxl_send_trigger(cfg->ctx, vm->def->id,
1313 1314 1315 1316
                                 LIBXL_TRIGGER_POWER, 0);
        if (ret == 0)
            goto cleanup;

1317 1318
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to shutdown domain '%d' with libxenlight"),
1319
                       vm->def->id);
1320
        ret = -1;
J
Jim Fehlig 已提交
1321 1322
    }

1323
 cleanup:
1324
    virDomainObjEndAPI(&vm);
J
Jim Fehlig 已提交
1325
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
1326 1327 1328
    return ret;
}

1329 1330 1331 1332 1333 1334 1335
static int
libxlDomainShutdown(virDomainPtr dom)
{
    return libxlDomainShutdownFlags(dom, 0);
}


J
Jim Fehlig 已提交
1336
static int
E
Eric Blake 已提交
1337
libxlDomainReboot(virDomainPtr dom, unsigned int flags)
J
Jim Fehlig 已提交
1338
{
J
Jim Fehlig 已提交
1339 1340
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
J
Jim Fehlig 已提交
1341 1342 1343
    virDomainObjPtr vm;
    int ret = -1;

J
Jim Fehlig 已提交
1344 1345 1346
    virCheckFlags(VIR_DOMAIN_REBOOT_PARAVIRT, -1);
    if (flags == 0)
        flags = VIR_DOMAIN_REBOOT_PARAVIRT;
E
Eric Blake 已提交
1347

J
Jim Fehlig 已提交
1348
    if (!(vm = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
1349 1350
        goto cleanup;

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

1353
    if (virDomainRebootEnsureACL(dom->conn, vm->def, flags) < 0)
1354 1355
        goto cleanup;

J
Jim Fehlig 已提交
1356
    if (!virDomainObjIsActive(vm)) {
1357 1358
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("Domain is not running"));
J
Jim Fehlig 已提交
1359 1360 1361
        goto cleanup;
    }

J
Jim Fehlig 已提交
1362
    if (flags & VIR_DOMAIN_REBOOT_PARAVIRT) {
J
Jim Fehlig 已提交
1363
        ret = libxl_domain_reboot(cfg->ctx, vm->def->id);
J
Jim Fehlig 已提交
1364 1365 1366
        if (ret == 0)
            goto cleanup;

1367 1368
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to reboot domain '%d' with libxenlight"),
1369
                       vm->def->id);
J
Jim Fehlig 已提交
1370
        ret = -1;
J
Jim Fehlig 已提交
1371 1372
    }

1373
 cleanup:
1374
    virDomainObjEndAPI(&vm);
J
Jim Fehlig 已提交
1375
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
1376 1377 1378 1379
    return ret;
}

static int
1380 1381
libxlDomainDestroyFlags(virDomainPtr dom,
                        unsigned int flags)
J
Jim Fehlig 已提交
1382 1383
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
J
Jim Fehlig 已提交
1384
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
J
Jim Fehlig 已提交
1385 1386
    virDomainObjPtr vm;
    int ret = -1;
1387
    virObjectEventPtr event = NULL;
J
Jim Fehlig 已提交
1388

1389 1390
    virCheckFlags(0, -1);

J
Jim Fehlig 已提交
1391
    if (!(vm = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
1392 1393
        goto cleanup;

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

1396 1397 1398
    if (virDomainDestroyFlagsEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

1399 1400 1401
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

J
Jim Fehlig 已提交
1402
    if (!virDomainObjIsActive(vm)) {
1403 1404
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("Domain is not running"));
1405
        goto endjob;
J
Jim Fehlig 已提交
1406 1407
    }

1408
    if (libxlDomainDestroyInternal(driver, vm) < 0) {
1409
        virReportError(VIR_ERR_INTERNAL_ERROR,
1410
                       _("Failed to destroy domain '%d'"), vm->def->id);
1411
        goto endjob;
J
Jim Fehlig 已提交
1412 1413
    }

1414 1415 1416 1417 1418 1419 1420
    virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF,
                         VIR_DOMAIN_SHUTOFF_DESTROYED);

    event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_DESTROYED);

    libxlDomainCleanup(driver, vm);
1421
    if (!vm->persistent) {
1422
        virDomainObjListRemove(driver->domains, vm);
1423 1424
        virObjectLock(vm);
    }
J
Jim Fehlig 已提交
1425 1426 1427

    ret = 0;

1428
 endjob:
W
Wang Yufei 已提交
1429
    libxlDomainObjEndJob(driver, vm);
1430

1431
 cleanup:
W
Wang Yufei 已提交
1432
    virDomainObjEndAPI(&vm);
1433 1434
    if (event)
        libxlDomainEventQueue(driver, event);
J
Jim Fehlig 已提交
1435
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
1436 1437 1438
    return ret;
}

1439 1440 1441 1442 1443 1444
static int
libxlDomainDestroy(virDomainPtr dom)
{
    return libxlDomainDestroyFlags(dom, 0);
}

1445 1446 1447 1448 1449 1450
static char *
libxlDomainGetOSType(virDomainPtr dom)
{
    virDomainObjPtr vm;
    char *type = NULL;

J
Jim Fehlig 已提交
1451
    if (!(vm = libxlDomObjFromDomain(dom)))
1452 1453
        goto cleanup;

1454 1455 1456
    if (virDomainGetOSTypeEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

1457
    if (VIR_STRDUP(type, virDomainOSTypeToString(vm->def->os.type)) < 0)
1458
        goto cleanup;
1459

1460
 cleanup:
1461
    virDomainObjEndAPI(&vm);
1462 1463 1464
    return type;
}

1465
static unsigned long long
1466 1467 1468
libxlDomainGetMaxMemory(virDomainPtr dom)
{
    virDomainObjPtr vm;
1469
    unsigned long long ret = 0;
1470

J
Jim Fehlig 已提交
1471
    if (!(vm = libxlDomObjFromDomain(dom)))
1472
        goto cleanup;
1473 1474 1475 1476

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

1477
    ret = virDomainDefGetMemoryTotal(vm->def);
1478

1479
 cleanup:
1480
    virDomainObjEndAPI(&vm);
1481 1482 1483
    return ret;
}

1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513

/*
 * Helper method for --current, --live, and --config options, and check
 * whether domain is active or can get persistent domain configuration.
 *
 * Return 0 if success, also change the flags and get the persistent
 * domain configuration if needed. Return -1 on error.
 */
static int
virDomainLiveConfigHelperMethod(virCapsPtr caps,
                                virDomainXMLOptionPtr xmlopt,
                                virDomainObjPtr dom,
                                unsigned int *flags,
                                virDomainDefPtr *persistentDef)
{
    if (virDomainObjUpdateModificationImpact(dom, flags) < 0)
        return -1;

    if (*flags & VIR_DOMAIN_AFFECT_CONFIG) {
        if (!(*persistentDef = virDomainObjGetPersistentDef(caps, xmlopt, dom))) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("Get persistent config failed"));
            return -1;
        }
    }

    return 0;
}


1514
static int
1515
libxlDomainSetMemoryFlags(virDomainPtr dom, unsigned long newmem,
1516 1517 1518
                          unsigned int flags)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
1519
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
1520
    virDomainObjPtr vm;
1521
    virDomainDefPtr persistentDef = NULL;
1522 1523 1524
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_MEM_LIVE |
1525 1526
                  VIR_DOMAIN_MEM_CONFIG |
                  VIR_DOMAIN_MEM_MAXIMUM, -1);
1527

J
Jim Fehlig 已提交
1528
    if (!(vm = libxlDomObjFromDomain(dom)))
1529 1530
        goto cleanup;

1531 1532 1533
    if (virDomainSetMemoryFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
        goto cleanup;

1534 1535 1536
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

1537 1538
    if (virDomainLiveConfigHelperMethod(cfg->caps, driver->xmlopt, vm, &flags,
                                        &persistentDef) < 0)
1539
        goto endjob;
1540

1541 1542
    if (flags & VIR_DOMAIN_MEM_MAXIMUM) {
        /* resize the maximum memory */
1543

1544
        if (flags & VIR_DOMAIN_MEM_LIVE) {
J
Jim Fehlig 已提交
1545
            if (libxl_domain_setmaxmem(cfg->ctx, vm->def->id, newmem) < 0) {
1546 1547
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("Failed to set maximum memory for domain '%d'"
1548
                                 " with libxenlight"), vm->def->id);
1549
                goto endjob;
1550 1551 1552 1553 1554 1555
            }
        }

        if (flags & VIR_DOMAIN_MEM_CONFIG) {
            /* Help clang 2.8 decipher the logic flow.  */
            sa_assert(persistentDef);
1556
            virDomainDefSetMemoryTotal(persistentDef, newmem);
1557 1558
            if (persistentDef->mem.cur_balloon > newmem)
                persistentDef->mem.cur_balloon = newmem;
1559
            ret = virDomainSaveConfig(cfg->configDir, cfg->caps, persistentDef);
1560
            goto endjob;
1561 1562
        }

1563 1564
    } else {
        /* resize the current memory */
1565

1566
        if (newmem > virDomainDefGetMemoryTotal(vm->def)) {
1567 1568
            virReportError(VIR_ERR_INVALID_ARG, "%s",
                           _("cannot set memory higher than max memory"));
1569
            goto endjob;
1570 1571 1572
        }

        if (flags & VIR_DOMAIN_MEM_LIVE) {
1573 1574 1575 1576
            int res;

            /* Unlock virDomainObj while ballooning memory */
            virObjectUnlock(vm);
J
Jim Fehlig 已提交
1577
            res = libxl_set_memory_target(cfg->ctx, vm->def->id, newmem, 0,
1578 1579 1580
                                          /* force */ 1);
            virObjectLock(vm);
            if (res < 0) {
1581 1582
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("Failed to set memory for domain '%d'"
1583
                                 " with libxenlight"), vm->def->id);
1584
                goto endjob;
1585 1586 1587 1588 1589 1590
            }
        }

        if (flags & VIR_DOMAIN_MEM_CONFIG) {
            sa_assert(persistentDef);
            persistentDef->mem.cur_balloon = newmem;
1591
            ret = virDomainSaveConfig(cfg->configDir, cfg->caps, persistentDef);
1592
            goto endjob;
1593
        }
1594 1595
    }

1596 1597
    ret = 0;

1598
 endjob:
W
Wang Yufei 已提交
1599
    libxlDomainObjEndJob(driver, vm);
1600

1601
 cleanup:
W
Wang Yufei 已提交
1602
    virDomainObjEndAPI(&vm);
1603
    virObjectUnref(cfg);
1604 1605 1606 1607 1608 1609 1610 1611 1612
    return ret;
}

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

1613 1614 1615 1616 1617 1618
static int
libxlDomainSetMaxMemory(virDomainPtr dom, unsigned long memory)
{
    return libxlDomainSetMemoryFlags(dom, memory, VIR_DOMAIN_MEM_MAXIMUM);
}

J
Jim Fehlig 已提交
1619 1620 1621
static int
libxlDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info)
{
J
Jim Fehlig 已提交
1622 1623
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
J
Jim Fehlig 已提交
1624
    virDomainObjPtr vm;
1625
    libxl_dominfo d_info;
J
Jim Fehlig 已提交
1626 1627
    int ret = -1;

J
Jim Fehlig 已提交
1628
    if (!(vm = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
1629 1630
        goto cleanup;

1631 1632 1633
    if (virDomainGetInfoEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

1634
    info->maxMem = virDomainDefGetMemoryTotal(vm->def);
1635 1636 1637 1638
    if (!virDomainObjIsActive(vm)) {
        info->cpuTime = 0;
        info->memory = vm->def->mem.cur_balloon;
    } else {
1639 1640
        libxl_dominfo_init(&d_info);

J
Jim Fehlig 已提交
1641
        if (libxl_domain_info(cfg->ctx, &d_info, vm->def->id) != 0) {
1642
            virReportError(VIR_ERR_INTERNAL_ERROR,
1643 1644
                           _("libxl_domain_info failed for domain '%d'"),
                           vm->def->id);
1645 1646 1647 1648
            goto cleanup;
        }
        info->cpuTime = d_info.cpu_time;
        info->memory = d_info.current_memkb;
1649 1650

        libxl_dominfo_dispose(&d_info);
1651 1652
    }

J
Jiri Denemark 已提交
1653
    info->state = virDomainObjGetState(vm, NULL);
1654
    info->nrVirtCpu = virDomainDefGetVcpus(vm->def);
J
Jim Fehlig 已提交
1655 1656
    ret = 0;

1657
 cleanup:
1658
    virDomainObjEndAPI(&vm);
J
Jim Fehlig 已提交
1659
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
1660 1661 1662
    return ret;
}

1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673
static int
libxlDomainGetState(virDomainPtr dom,
                    int *state,
                    int *reason,
                    unsigned int flags)
{
    virDomainObjPtr vm;
    int ret = -1;

    virCheckFlags(0, -1);

J
Jim Fehlig 已提交
1674
    if (!(vm = libxlDomObjFromDomain(dom)))
1675 1676
        goto cleanup;

1677 1678 1679
    if (virDomainGetStateEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

J
Jiri Denemark 已提交
1680
    *state = virDomainObjGetState(vm, reason);
1681 1682
    ret = 0;

1683
 cleanup:
1684
    virDomainObjEndAPI(&vm);
1685 1686 1687
    return ret;
}

1688 1689 1690
/*
 * virDomainObjPtr must be locked on invocation
 */
1691
static int
1692 1693
libxlDoDomainSave(libxlDriverPrivatePtr driver, virDomainObjPtr vm,
                  const char *to)
1694
{
J
Jim Fehlig 已提交
1695
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
1696
    libxlSavefileHeader hdr;
1697
    virObjectEventPtr event = NULL;
1698 1699
    char *xml = NULL;
    uint32_t xml_len;
1700
    int fd = -1;
1701 1702 1703
    int ret = -1;

    if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
1704 1705 1706
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("Domain '%d' has to be running because libxenlight will"
                         " suspend it"), vm->def->id);
1707 1708 1709 1710
        goto cleanup;
    }

    if ((fd = virFileOpenAs(to, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR,
L
Laine Stump 已提交
1711
                            -1, -1, 0)) < 0) {
1712 1713 1714 1715 1716
        virReportSystemError(-fd,
                             _("Failed to create domain save file '%s'"), to);
        goto cleanup;
    }

1717
    if ((xml = virDomainDefFormat(vm->def, cfg->caps, 0)) == NULL)
1718 1719 1720 1721 1722 1723 1724 1725 1726
        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)) {
1727 1728
        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                       _("Failed to write save file header"));
1729 1730 1731 1732
        goto cleanup;
    }

    if (safewrite(fd, xml, xml_len) != xml_len) {
1733 1734
        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                       _("Failed to write xml description"));
1735 1736 1737
        goto cleanup;
    }

1738 1739
    /* Unlock virDomainObj while saving domain */
    virObjectUnlock(vm);
J
Jim Fehlig 已提交
1740
    ret = libxl_domain_suspend(cfg->ctx, vm->def->id, fd, 0, NULL);
1741 1742 1743
    virObjectLock(vm);

    if (ret != 0) {
1744 1745 1746
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to save domain '%d' with libxenlight"),
                       vm->def->id);
1747
        ret = -1;
1748 1749 1750
        goto cleanup;
    }

1751 1752 1753
    virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF,
                         VIR_DOMAIN_SHUTOFF_SAVED);

1754
    event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
1755 1756
                                         VIR_DOMAIN_EVENT_STOPPED_SAVED);

1757
    if (libxlDomainDestroyInternal(driver, vm) < 0) {
1758 1759
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to destroy domain '%d'"), vm->def->id);
1760 1761 1762
        goto cleanup;
    }

1763
    libxlDomainCleanup(driver, vm);
1764
    vm->hasManagedSave = true;
1765 1766
    ret = 0;

1767
 cleanup:
1768 1769 1770 1771 1772
    VIR_FREE(xml);
    if (VIR_CLOSE(fd) < 0)
        virReportSystemError(errno, "%s", _("cannot close file"));
    if (event)
        libxlDomainEventQueue(driver, event);
J
Jim Fehlig 已提交
1773
    virObjectUnref(cfg);
1774 1775 1776 1777
    return ret;
}

static int
1778 1779
libxlDomainSaveFlags(virDomainPtr dom, const char *to, const char *dxml,
                     unsigned int flags)
1780
{
1781 1782
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    virDomainObjPtr vm;
1783
    int ret = -1;
1784
    bool remove_dom = false;
1785

1786 1787 1788 1789 1790
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
    virReportUnsupportedError();
    return -1;
#endif

1791 1792
    virCheckFlags(0, -1);
    if (dxml) {
1793 1794
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
1795 1796 1797
        return -1;
    }

J
Jim Fehlig 已提交
1798
    if (!(vm = libxlDomObjFromDomain(dom)))
1799 1800
        goto cleanup;

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

1803 1804 1805
    if (virDomainSaveFlagsEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

1806 1807 1808
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

1809
    if (!virDomainObjIsActive(vm)) {
1810
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
1811
        goto endjob;
1812 1813
    }

1814
    if (libxlDoDomainSave(driver, vm, to) < 0)
1815
        goto endjob;
1816

1817 1818
    if (!vm->persistent)
        remove_dom = true;
1819 1820

    ret = 0;
1821

1822
 endjob:
W
Wang Yufei 已提交
1823
    libxlDomainObjEndJob(driver, vm);
1824

1825
 cleanup:
1826 1827
    if (remove_dom && vm) {
        virDomainObjListRemove(driver->domains, vm);
1828
        virObjectLock(vm);
1829
    }
W
Wang Yufei 已提交
1830
    virDomainObjEndAPI(&vm);
1831 1832
    return ret;
}
1833

1834
static int
1835 1836 1837 1838 1839 1840 1841 1842
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)
1843 1844
{
    libxlDriverPrivatePtr driver = conn->privateData;
1845
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
1846 1847 1848 1849 1850
    virDomainObjPtr vm = NULL;
    virDomainDefPtr def = NULL;
    libxlSavefileHeader hdr;
    int fd = -1;
    int ret = -1;
1851

1852 1853 1854 1855 1856
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
    virReportUnsupportedError();
    return -1;
#endif

1857
    virCheckFlags(VIR_DOMAIN_SAVE_PAUSED, -1);
1858
    if (dxml) {
1859 1860
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
1861 1862 1863
        return -1;
    }

1864
    fd = libxlDomainSaveImageOpen(driver, cfg, from, &def, &hdr);
1865
    if (fd < 0)
1866
        goto cleanup;
1867

1868
    if (virDomainRestoreFlagsEnsureACL(conn, def) < 0)
1869
        goto cleanup;
1870

1871
    if (!(vm = virDomainObjListAdd(driver->domains, def,
1872
                                   driver->xmlopt,
1873 1874 1875
                                   VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
                                   VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                   NULL)))
1876
        goto cleanup;
W
Wang Yufei 已提交
1877
    virObjectRef(vm);
1878 1879
    def = NULL;

1880 1881 1882
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0) {
        if (!vm->persistent) {
            virDomainObjListRemove(driver->domains, vm);
1883
            virObjectLock(vm);
1884 1885 1886 1887
        }
        goto cleanup;
    }

1888 1889 1890
    ret = libxlDomainStartRestore(driver, vm,
                                  (flags & VIR_DOMAIN_SAVE_PAUSED) != 0,
                                  fd, hdr.version);
1891
    if (ret < 0 && !vm->persistent) {
1892
        virDomainObjListRemove(driver->domains, vm);
1893 1894
        virObjectLock(vm);
    }
1895

W
Wang Yufei 已提交
1896
    libxlDomainObjEndJob(driver, vm);
1897

1898
 cleanup:
1899 1900
    if (VIR_CLOSE(fd) < 0)
        virReportSystemError(errno, "%s", _("cannot close file"));
1901
    virDomainDefFree(def);
W
Wang Yufei 已提交
1902
    virDomainObjEndAPI(&vm);
1903
    virObjectUnref(cfg);
1904 1905 1906
    return ret;
}

1907 1908 1909 1910 1911 1912
static int
libxlDomainRestore(virConnectPtr conn, const char *from)
{
    return libxlDomainRestoreFlags(conn, from, NULL, 0);
}

1913
static int
1914
libxlDomainCoreDump(virDomainPtr dom, const char *to, unsigned int flags)
1915 1916
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
J
Jim Fehlig 已提交
1917
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
1918
    virDomainObjPtr vm;
1919
    virObjectEventPtr event = NULL;
1920
    bool remove_dom = false;
1921 1922 1923 1924 1925
    bool paused = false;
    int ret = -1;

    virCheckFlags(VIR_DUMP_LIVE | VIR_DUMP_CRASH, -1);

J
Jim Fehlig 已提交
1926
    if (!(vm = libxlDomObjFromDomain(dom)))
1927 1928
        goto cleanup;

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

1931 1932 1933
    if (virDomainCoreDumpEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

1934 1935 1936
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

1937
    if (!virDomainObjIsActive(vm)) {
1938
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
1939
        goto endjob;
1940 1941 1942 1943
    }

    if (!(flags & VIR_DUMP_LIVE) &&
        virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
J
Jim Fehlig 已提交
1944
        if (libxl_domain_pause(cfg->ctx, vm->def->id) != 0) {
1945 1946 1947
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Before dumping core, failed to suspend domain '%d'"
                             " with libxenlight"),
1948
                           vm->def->id);
1949
            goto endjob;
1950 1951 1952 1953 1954
        }
        virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_DUMP);
        paused = true;
    }

1955 1956
    /* Unlock virDomainObj while dumping core */
    virObjectUnlock(vm);
J
Jim Fehlig 已提交
1957
    ret = libxl_domain_core_dump(cfg->ctx, vm->def->id, to, NULL);
1958 1959
    virObjectLock(vm);
    if (ret != 0) {
1960 1961
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to dump core of domain '%d' with libxenlight"),
1962
                       vm->def->id);
1963 1964
        ret = -1;
        goto unpause;
1965 1966 1967
    }

    if (flags & VIR_DUMP_CRASH) {
1968
        if (libxlDomainDestroyInternal(driver, vm) < 0) {
1969
            virReportError(VIR_ERR_INTERNAL_ERROR,
1970
                           _("Failed to destroy domain '%d'"), vm->def->id);
1971
            goto unpause;
1972 1973
        }

1974 1975 1976
        libxlDomainCleanup(driver, vm);
        virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF,
                             VIR_DOMAIN_SHUTOFF_CRASHED);
1977
        event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
1978
                                         VIR_DOMAIN_EVENT_STOPPED_CRASHED);
1979 1980
        if (!vm->persistent)
            remove_dom = true;
1981 1982 1983 1984
    }

    ret = 0;

1985
 unpause:
1986
    if (virDomainObjIsActive(vm) && paused) {
J
Jim Fehlig 已提交
1987
        if (libxl_domain_unpause(cfg->ctx, vm->def->id) != 0) {
1988 1989
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("After dumping core, failed to resume domain '%d' with"
1990
                             " libxenlight"), vm->def->id);
1991 1992 1993 1994 1995
        } else {
            virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
                                 VIR_DOMAIN_RUNNING_UNPAUSED);
        }
    }
1996

1997
 endjob:
W
Wang Yufei 已提交
1998
    libxlDomainObjEndJob(driver, vm);
1999

2000
 cleanup:
2001 2002
    if (remove_dom && vm) {
        virDomainObjListRemove(driver->domains, vm);
2003
        virObjectLock(vm);
2004
    }
W
Wang Yufei 已提交
2005
    virDomainObjEndAPI(&vm);
2006
    if (event)
2007
        libxlDomainEventQueue(driver, event);
J
Jim Fehlig 已提交
2008
    virObjectUnref(cfg);
2009 2010 2011
    return ret;
}

2012 2013 2014 2015 2016 2017 2018
static int
libxlDomainManagedSave(virDomainPtr dom, unsigned int flags)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    virDomainObjPtr vm = NULL;
    char *name = NULL;
    int ret = -1;
2019
    bool remove_dom = false;
2020 2021 2022

    virCheckFlags(0, -1);

J
Jim Fehlig 已提交
2023
    if (!(vm = libxlDomObjFromDomain(dom)))
2024 2025
        goto cleanup;

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

2028 2029 2030
    if (virDomainManagedSaveEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

2031 2032 2033
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

2034
    if (!virDomainObjIsActive(vm)) {
2035
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
2036
        goto endjob;
2037
    }
2038
    if (!vm->persistent) {
2039 2040
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("cannot do managed save for transient domain"));
2041
        goto endjob;
2042
    }
2043 2044 2045

    name = libxlDomainManagedSavePath(driver, vm);
    if (name == NULL)
2046
        goto endjob;
2047 2048 2049

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

2050
    if (libxlDoDomainSave(driver, vm, name) < 0)
2051
        goto endjob;
2052

2053 2054
    if (!vm->persistent)
        remove_dom = true;
2055 2056

    ret = 0;
2057

2058
 endjob:
W
Wang Yufei 已提交
2059
    libxlDomainObjEndJob(driver, vm);
2060

2061
 cleanup:
2062 2063
    if (remove_dom && vm) {
        virDomainObjListRemove(driver->domains, vm);
2064
        virObjectLock(vm);
2065
    }
W
Wang Yufei 已提交
2066
    virDomainObjEndAPI(&vm);
2067 2068 2069 2070
    VIR_FREE(name);
    return ret;
}

2071 2072
static int
libxlDomainManagedSaveLoad(virDomainObjPtr vm,
2073 2074 2075 2076
                           void *opaque)
{
    libxlDriverPrivatePtr driver = opaque;
    char *name;
2077
    int ret = -1;
2078

2079
    virObjectLock(vm);
2080 2081 2082 2083 2084 2085

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

    vm->hasManagedSave = virFileExists(name);

2086
    ret = 0;
2087
 cleanup:
2088
    virObjectUnlock(vm);
2089
    VIR_FREE(name);
2090
    return ret;
2091 2092
}

2093 2094 2095 2096 2097 2098 2099 2100
static int
libxlDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    int ret = -1;

    virCheckFlags(0, -1);

J
Jim Fehlig 已提交
2101
    if (!(vm = libxlDomObjFromDomain(dom)))
2102 2103
        goto cleanup;

2104 2105 2106
    if (virDomainHasManagedSaveImageEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

2107
    ret = vm->hasManagedSave;
2108

2109
 cleanup:
2110
    virDomainObjEndAPI(&vm);
2111 2112 2113 2114 2115 2116 2117 2118 2119 2120 2121 2122 2123
    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 已提交
2124
    if (!(vm = libxlDomObjFromDomain(dom)))
2125 2126
        goto cleanup;

2127 2128 2129
    if (virDomainManagedSaveRemoveEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

2130 2131 2132 2133 2134
    name = libxlDomainManagedSavePath(driver, vm);
    if (name == NULL)
        goto cleanup;

    ret = unlink(name);
2135
    vm->hasManagedSave = false;
2136

2137
 cleanup:
2138
    VIR_FREE(name);
2139
    virDomainObjEndAPI(&vm);
2140 2141 2142
    return ret;
}

2143 2144 2145 2146 2147
static int
libxlDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
                         unsigned int flags)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
2148
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
2149 2150
    virDomainDefPtr def;
    virDomainObjPtr vm;
J
Jim Fehlig 已提交
2151
    libxl_bitmap map;
2152 2153
    uint8_t *bitmask = NULL;
    unsigned int maplen;
2154 2155
    size_t i;
    unsigned int pos;
2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167
    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)) {
2168 2169
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid flag combination: (0x%x)"), flags);
2170 2171 2172 2173
        return -1;
    }

    if (!nvcpus) {
2174
        virReportError(VIR_ERR_INVALID_ARG, "%s", _("nvcpus is zero"));
2175 2176 2177
        return -1;
    }

J
Jim Fehlig 已提交
2178
    if (!(vm = libxlDomObjFromDomain(dom)))
2179 2180
        goto cleanup;

2181 2182 2183
    if (virDomainSetVcpusFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
        goto cleanup;

2184 2185 2186
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

2187
    if (!virDomainObjIsActive(vm) && (flags & VIR_DOMAIN_VCPU_LIVE)) {
2188 2189
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("cannot set vcpus on an inactive domain"));
2190
        goto endjob;
2191 2192 2193
    }

    if (!vm->persistent && (flags & VIR_DOMAIN_VCPU_CONFIG)) {
2194 2195
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("cannot change persistent config of a transient domain"));
2196
        goto endjob;
2197 2198
    }

2199
    if ((max = libxlConnectGetMaxVcpus(dom->conn, NULL)) < 0) {
2200 2201
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("could not determine max vcpus for the domain"));
2202
        goto endjob;
2203 2204
    }

2205 2206
    if (!(flags & VIR_DOMAIN_VCPU_MAXIMUM) && virDomainDefGetVcpusMax(vm->def) < max)
        max = virDomainDefGetVcpusMax(vm->def);
2207 2208

    if (nvcpus > max) {
2209 2210 2211
        virReportError(VIR_ERR_INVALID_ARG,
                       _("requested vcpus is greater than max allowable"
                         " vcpus for the domain: %d > %d"), nvcpus, max);
2212
        goto endjob;
2213 2214
    }

2215
    if (!(def = virDomainObjGetPersistentDef(cfg->caps, driver->xmlopt, vm)))
2216
        goto endjob;
2217

E
Eric Blake 已提交
2218
    maplen = VIR_CPU_MAPLEN(nvcpus);
2219
    if (VIR_ALLOC_N(bitmask, maplen) < 0)
2220
        goto endjob;
2221 2222

    for (i = 0; i < nvcpus; ++i) {
E
Eric Blake 已提交
2223
        pos = i / 8;
2224 2225 2226 2227 2228 2229 2230 2231
        bitmask[pos] |= 1 << (i % 8);
    }

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

    switch (flags) {
    case VIR_DOMAIN_VCPU_MAXIMUM | VIR_DOMAIN_VCPU_CONFIG:
2232
        if (virDomainDefSetVcpusMax(def, nvcpus, driver->xmlopt) < 0)
2233
            goto cleanup;
2234 2235 2236
        break;

    case VIR_DOMAIN_VCPU_CONFIG:
2237 2238
        if (virDomainDefSetVcpus(def, nvcpus) < 0)
            goto cleanup;
2239 2240 2241
        break;

    case VIR_DOMAIN_VCPU_LIVE:
J
Jim Fehlig 已提交
2242
        if (libxl_set_vcpuonline(cfg->ctx, vm->def->id, &map) != 0) {
2243 2244
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Failed to set vcpus for domain '%d'"
2245
                             " with libxenlight"), vm->def->id);
2246
            goto endjob;
2247
        }
2248 2249
        if (virDomainDefSetVcpus(vm->def, nvcpus) < 0)
            goto endjob;
2250 2251 2252
        break;

    case VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG:
J
Jim Fehlig 已提交
2253
        if (libxl_set_vcpuonline(cfg->ctx, vm->def->id, &map) != 0) {
2254 2255
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Failed to set vcpus for domain '%d'"
2256
                             " with libxenlight"), vm->def->id);
2257
            goto endjob;
2258
        }
2259 2260 2261
        if (virDomainDefSetVcpus(vm->def, nvcpus) < 0 ||
            virDomainDefSetVcpus(def, nvcpus) < 0)
            goto endjob;
2262 2263 2264 2265 2266
        break;
    }

    ret = 0;

2267
    if (flags & VIR_DOMAIN_VCPU_LIVE) {
2268
        if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, cfg->caps) < 0) {
2269 2270 2271 2272 2273
            VIR_WARN("Unable to save status on vm %s after changing vcpus",
                     vm->def->name);
        }
    }
    if (flags & VIR_DOMAIN_VCPU_CONFIG) {
2274
        if (virDomainSaveConfig(cfg->configDir, cfg->caps, def) < 0) {
2275 2276 2277 2278
            VIR_WARN("Unable to save configuration of vm %s after changing vcpus",
                     vm->def->name);
        }
    }
2279

2280
 endjob:
W
Wang Yufei 已提交
2281
    libxlDomainObjEndJob(driver, vm);
2282

2283
 cleanup:
2284
    VIR_FREE(bitmask);
W
Wang Yufei 已提交
2285 2286
    virDomainObjEndAPI(&vm);
    virObjectUnref(cfg);
2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301
    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;
2302
    bool active;
2303 2304 2305 2306 2307

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

J
Jim Fehlig 已提交
2308
    if (!(vm = libxlDomObjFromDomain(dom)))
2309 2310
        goto cleanup;

2311
    if (virDomainGetVcpusFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
2312 2313
        goto cleanup;

2314 2315 2316 2317 2318 2319 2320 2321 2322
    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)) {
2323 2324
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid flag combination: (0x%x)"), flags);
2325 2326 2327
        return -1;
    }

2328
    if (flags & VIR_DOMAIN_VCPU_LIVE) {
2329
        if (!active) {
2330 2331
            virReportError(VIR_ERR_OPERATION_INVALID,
                           "%s", _("Domain is not running"));
2332 2333 2334 2335
            goto cleanup;
        }
        def = vm->def;
    } else {
2336
        if (!vm->persistent) {
2337 2338
            virReportError(VIR_ERR_OPERATION_INVALID,
                           "%s", _("domain is transient"));
2339 2340
            goto cleanup;
        }
2341 2342 2343
        def = vm->newDef ? vm->newDef : vm->def;
    }

2344 2345 2346
    if (flags & VIR_DOMAIN_VCPU_MAXIMUM)
        ret = virDomainDefGetVcpusMax(def);
    else
2347
        ret = virDomainDefGetVcpus(def);
2348

2349
 cleanup:
2350
    virDomainObjEndAPI(&vm);
2351 2352 2353
    return ret;
}

2354 2355 2356 2357 2358 2359 2360
static int
libxlDomainGetMaxVcpus(virDomainPtr dom)
{
    return libxlDomainGetVcpusFlags(dom, (VIR_DOMAIN_AFFECT_LIVE |
                                          VIR_DOMAIN_VCPU_MAXIMUM));
}

2361
static int
2362 2363 2364
libxlDomainPinVcpuFlags(virDomainPtr dom, unsigned int vcpu,
                        unsigned char *cpumap, int maplen,
                        unsigned int flags)
2365 2366
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
2367
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
2368
    virDomainDefPtr targetDef = NULL;
2369
    virBitmapPtr pcpumap = NULL;
2370
    virDomainVcpuDefPtr vcpuinfo;
2371 2372
    virDomainObjPtr vm;
    int ret = -1;
2373 2374 2375

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);
2376

J
Jim Fehlig 已提交
2377
    if (!(vm = libxlDomObjFromDomain(dom)))
2378 2379
        goto cleanup;

2380
    if (virDomainPinVcpuFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
2381 2382
        goto cleanup;

2383 2384 2385
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

2386 2387
    if (virDomainLiveConfigHelperMethod(cfg->caps, driver->xmlopt, vm,
                                        &flags, &targetDef) < 0)
2388
        goto endjob;
2389

2390
    if (flags & VIR_DOMAIN_AFFECT_LIVE)
2391 2392 2393 2394 2395
        targetDef = vm->def;

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

2396 2397
    pcpumap = virBitmapNewData(cpumap, maplen);
    if (!pcpumap)
2398
        goto endjob;
2399

2400 2401 2402 2403 2404 2405 2406
    if (!(vcpuinfo = virDomainDefGetVcpu(targetDef, vcpu)) ||
        !vcpuinfo->online) {
        virReportError(VIR_ERR_INVALID_ARG,
                       _("vcpu '%u' is not active"), vcpu);
        goto endjob;
    }

2407 2408
    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
        libxl_bitmap map = { .size = maplen, .map = cpumap };
J
Jim Fehlig 已提交
2409
        if (libxl_set_vcpuaffinity(cfg->ctx, vm->def->id, vcpu, &map) != 0) {
2410 2411 2412
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Failed to pin vcpu '%d' with libxenlight"),
                           vcpu);
2413
            goto endjob;
2414
        }
2415
    }
2416

2417 2418 2419
    virBitmapFree(vcpuinfo->cpumask);
    vcpuinfo->cpumask = pcpumap;
    pcpumap = NULL;
2420

2421 2422
    ret = 0;

2423
    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
2424
        ret = virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, cfg->caps);
2425
    } else if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
2426
        ret = virDomainSaveConfig(cfg->configDir, cfg->caps, targetDef);
2427 2428
    }

2429
 endjob:
W
Wang Yufei 已提交
2430
    libxlDomainObjEndJob(driver, vm);
2431

2432
 cleanup:
W
Wang Yufei 已提交
2433
    virDomainObjEndAPI(&vm);
2434
    virBitmapFree(pcpumap);
2435
    virObjectUnref(cfg);
2436 2437 2438
    return ret;
}

2439 2440 2441 2442 2443 2444 2445 2446
static int
libxlDomainPinVcpu(virDomainPtr dom, unsigned int vcpu, unsigned char *cpumap,
                   int maplen)
{
    return libxlDomainPinVcpuFlags(dom, vcpu, cpumap, maplen,
                                   VIR_DOMAIN_AFFECT_LIVE);
}

2447 2448 2449 2450 2451 2452 2453 2454 2455
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;
2456
    int ret = -1;
2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470

    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;

2471
    if (flags & VIR_DOMAIN_AFFECT_LIVE)
2472 2473 2474 2475 2476
        targetDef = vm->def;

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

2477 2478
    ret = virDomainDefGetVcpuPinInfoHelper(targetDef, maplen, ncpumaps, cpumaps,
                                           libxl_get_max_cpus(cfg->ctx), NULL);
2479

2480
 cleanup:
2481
    virDomainObjEndAPI(&vm);
2482 2483 2484
    virObjectUnref(cfg);
    return ret;
}
2485 2486 2487 2488 2489

static int
libxlDomainGetVcpus(virDomainPtr dom, virVcpuInfoPtr info, int maxinfo,
                    unsigned char *cpumaps, int maplen)
{
J
Jim Fehlig 已提交
2490 2491
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
2492 2493 2494 2495
    virDomainObjPtr vm;
    int ret = -1;
    libxl_vcpuinfo *vcpuinfo;
    int maxcpu, hostcpus;
2496
    size_t i;
2497 2498
    unsigned char *cpumap;

J
Jim Fehlig 已提交
2499
    if (!(vm = libxlDomObjFromDomain(dom)))
2500 2501
        goto cleanup;

2502 2503 2504
    if (virDomainGetVcpusEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

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

J
Jim Fehlig 已提交
2510
    if ((vcpuinfo = libxl_list_vcpu(cfg->ctx, vm->def->id, &maxcpu,
2511
                                    &hostcpus)) == NULL) {
2512 2513
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to list vcpus for domain '%d' with libxenlight"),
2514
                       vm->def->id);
2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 2525 2526 2527 2528 2529 2530 2531 2532 2533 2534 2535 2536
        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 已提交
2537
        libxl_vcpuinfo_dispose(&vcpuinfo[i]);
2538 2539 2540 2541 2542
    }
    VIR_FREE(vcpuinfo);

    ret = maxinfo;

2543
 cleanup:
2544
    virDomainObjEndAPI(&vm);
J
Jim Fehlig 已提交
2545
    virObjectUnref(cfg);
2546 2547 2548
    return ret;
}

J
Jim Fehlig 已提交
2549
static char *
2550
libxlDomainGetXMLDesc(virDomainPtr dom, unsigned int flags)
J
Jim Fehlig 已提交
2551
{
2552 2553
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
J
Jim Fehlig 已提交
2554
    virDomainObjPtr vm;
2555
    virDomainDefPtr def;
J
Jim Fehlig 已提交
2556 2557
    char *ret = NULL;

2558 2559
    /* Flags checked by virDomainDefFormat */

J
Jim Fehlig 已提交
2560
    if (!(vm = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
2561 2562
        goto cleanup;

2563 2564 2565
    if (virDomainGetXMLDescEnsureACL(dom->conn, vm->def, flags) < 0)
        goto cleanup;

2566 2567 2568 2569 2570
    if ((flags & VIR_DOMAIN_XML_INACTIVE) && vm->newDef)
        def = vm->newDef;
    else
        def = vm->def;

2571
    ret = virDomainDefFormat(def, cfg->caps,
2572
                             virDomainDefFormatConvertXMLFlags(flags));
J
Jim Fehlig 已提交
2573

2574
 cleanup:
2575
    virDomainObjEndAPI(&vm);
2576
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
2577 2578 2579
    return ret;
}

2580
static char *
2581 2582 2583
libxlConnectDomainXMLFromNative(virConnectPtr conn,
                                const char *nativeFormat,
                                const char *nativeConfig,
2584
                                unsigned int flags)
2585 2586
{
    libxlDriverPrivatePtr driver = conn->privateData;
2587
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
2588 2589 2590 2591
    virDomainDefPtr def = NULL;
    virConfPtr conf = NULL;
    char *xml = NULL;

E
Eric Blake 已提交
2592 2593
    virCheckFlags(0, NULL);

2594 2595 2596
    if (virConnectDomainXMLFromNativeEnsureACL(conn) < 0)
        goto cleanup;

2597
    if (STREQ(nativeFormat, XEN_CONFIG_FORMAT_XL)) {
J
Ján Tomko 已提交
2598
        if (!(conf = virConfReadString(nativeConfig, 0)))
2599 2600 2601
            goto cleanup;
        if (!(def = xenParseXL(conf,
                               cfg->caps,
2602
                               driver->xmlopt)))
2603
            goto cleanup;
2604
    } else if (STREQ(nativeFormat, XEN_CONFIG_FORMAT_XM)) {
J
Ján Tomko 已提交
2605
        if (!(conf = virConfReadString(nativeConfig, 0)))
2606 2607 2608
            goto cleanup;

        if (!(def = xenParseXM(conf,
2609 2610
                               cfg->caps,
                               driver->xmlopt)))
2611
            goto cleanup;
2612
    } else if (STREQ(nativeFormat, XEN_CONFIG_FORMAT_SEXPR)) {
2613 2614 2615
        /* only support latest xend config format */
        if (!(def = xenParseSxprString(nativeConfig,
                                       NULL,
2616 2617 2618
                                       -1,
                                       cfg->caps,
                                       driver->xmlopt))) {
2619 2620 2621 2622 2623
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("parsing sxpr config failed"));
            goto cleanup;
        }
    } else {
2624 2625
        virReportError(VIR_ERR_INVALID_ARG,
                       _("unsupported config type %s"), nativeFormat);
2626 2627 2628
        goto cleanup;
    }

2629
    xml = virDomainDefFormat(def, cfg->caps, VIR_DOMAIN_DEF_FORMAT_INACTIVE);
2630

2631
 cleanup:
2632 2633 2634
    virDomainDefFree(def);
    if (conf)
        virConfFree(conf);
2635
    virObjectUnref(cfg);
2636 2637 2638 2639 2640
    return xml;
}

#define MAX_CONFIG_SIZE (1024 * 65)
static char *
2641 2642 2643
libxlConnectDomainXMLToNative(virConnectPtr conn, const char * nativeFormat,
                              const char * domainXml,
                              unsigned int flags)
2644 2645
{
    libxlDriverPrivatePtr driver = conn->privateData;
2646
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
2647 2648 2649 2650 2651
    virDomainDefPtr def = NULL;
    virConfPtr conf = NULL;
    int len = MAX_CONFIG_SIZE;
    char *ret = NULL;

E
Eric Blake 已提交
2652 2653
    virCheckFlags(0, NULL);

2654 2655 2656
    if (virConnectDomainXMLToNativeEnsureACL(conn) < 0)
        goto cleanup;

2657
    if (!(def = virDomainDefParseString(domainXml,
2658
                                        cfg->caps, driver->xmlopt, NULL,
2659
                                        VIR_DOMAIN_DEF_PARSE_INACTIVE)))
2660 2661
        goto cleanup;

2662
    if (STREQ(nativeFormat, XEN_CONFIG_FORMAT_XL)) {
2663
        if (!(conf = xenFormatXL(def, conn)))
2664
            goto cleanup;
2665
    } else if (STREQ(nativeFormat, XEN_CONFIG_FORMAT_XM)) {
2666
        if (!(conf = xenFormatXM(conn, def)))
2667 2668 2669 2670 2671
            goto cleanup;
    } else {

        virReportError(VIR_ERR_INVALID_ARG,
                       _("unsupported config type %s"), nativeFormat);
2672
        goto cleanup;
2673
    }
2674

2675
    if (VIR_ALLOC_N(ret, len) < 0)
2676 2677 2678 2679 2680 2681 2682
        goto cleanup;

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

2683
 cleanup:
2684 2685 2686
    virDomainDefFree(def);
    if (conf)
        virConfFree(conf);
2687
    virObjectUnref(cfg);
2688 2689 2690
    return ret;
}

J
Jim Fehlig 已提交
2691
static int
2692 2693
libxlConnectListDefinedDomains(virConnectPtr conn,
                               char **const names, int nnames)
J
Jim Fehlig 已提交
2694 2695 2696 2697
{
    libxlDriverPrivatePtr driver = conn->privateData;
    int n;

2698 2699 2700
    if (virConnectListDefinedDomainsEnsureACL(conn) < 0)
        return -1;

2701 2702
    n = virDomainObjListGetInactiveNames(driver->domains, names, nnames,
                                         virConnectListDefinedDomainsCheckACL, conn);
J
Jim Fehlig 已提交
2703 2704 2705 2706
    return n;
}

static int
2707
libxlConnectNumOfDefinedDomains(virConnectPtr conn)
J
Jim Fehlig 已提交
2708 2709 2710 2711
{
    libxlDriverPrivatePtr driver = conn->privateData;
    int n;

2712 2713 2714
    if (virConnectNumOfDefinedDomainsEnsureACL(conn) < 0)
        return -1;

2715
    n = virDomainObjListNumOfDomains(driver->domains, false,
2716 2717
                                     virConnectNumOfDefinedDomainsCheckACL,
                                     conn);
J
Jim Fehlig 已提交
2718 2719 2720 2721 2722
    return n;
}

static int
libxlDomainCreateWithFlags(virDomainPtr dom,
E
Eric Blake 已提交
2723
                           unsigned int flags)
J
Jim Fehlig 已提交
2724 2725 2726 2727 2728 2729 2730
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_START_PAUSED, -1);

J
Jim Fehlig 已提交
2731
    if (!(vm = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
2732 2733
        goto cleanup;

2734 2735 2736
    if (virDomainCreateWithFlagsEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

2737 2738 2739
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

J
Jim Fehlig 已提交
2740
    if (virDomainObjIsActive(vm)) {
2741 2742
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("Domain is already running"));
2743
        goto endjob;
J
Jim Fehlig 已提交
2744 2745
    }

2746 2747
    ret = libxlDomainStartNew(driver, vm,
                              (flags & VIR_DOMAIN_START_PAUSED) != 0);
2748
    if (ret < 0)
2749
        goto endjob;
2750
    dom->id = vm->def->id;
J
Jim Fehlig 已提交
2751

2752
 endjob:
W
Wang Yufei 已提交
2753
    libxlDomainObjEndJob(driver, vm);
2754

2755
 cleanup:
W
Wang Yufei 已提交
2756
    virDomainObjEndAPI(&vm);
J
Jim Fehlig 已提交
2757 2758 2759 2760 2761 2762 2763 2764 2765 2766
    return ret;
}

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

static virDomainPtr
2767
libxlDomainDefineXMLFlags(virConnectPtr conn, const char *xml, unsigned int flags)
J
Jim Fehlig 已提交
2768 2769
{
    libxlDriverPrivatePtr driver = conn->privateData;
2770
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
J
Jim Fehlig 已提交
2771 2772 2773
    virDomainDefPtr def = NULL;
    virDomainObjPtr vm = NULL;
    virDomainPtr dom = NULL;
2774
    virObjectEventPtr event = NULL;
2775
    virDomainDefPtr oldDef = NULL;
2776
    unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;
J
Jim Fehlig 已提交
2777

2778 2779 2780
    virCheckFlags(VIR_DOMAIN_DEFINE_VALIDATE, NULL);

    if (flags & VIR_DOMAIN_DEFINE_VALIDATE)
2781
        parse_flags |= VIR_DOMAIN_DEF_PARSE_VALIDATE_SCHEMA;
2782

2783
    if (!(def = virDomainDefParseString(xml, cfg->caps, driver->xmlopt,
2784
                                        NULL, parse_flags)))
2785
        goto cleanup;
J
Jim Fehlig 已提交
2786

2787 2788 2789
    if (virXMLCheckIllegalChars("name", def->name, "\n") < 0)
        goto cleanup;

2790
    if (virDomainDefineXMLFlagsEnsureACL(conn, def) < 0)
2791
        goto cleanup;
2792

2793
    if (!(vm = virDomainObjListAdd(driver->domains, def,
2794
                                   driver->xmlopt,
2795 2796
                                   0,
                                   &oldDef)))
2797
        goto cleanup;
2798

2799
    virObjectRef(vm);
J
Jim Fehlig 已提交
2800 2801 2802
    def = NULL;
    vm->persistent = 1;

2803
    if (virDomainSaveConfig(cfg->configDir,
2804
                            cfg->caps,
J
Jim Fehlig 已提交
2805
                            vm->newDef ? vm->newDef : vm->def) < 0) {
2806
        virDomainObjListRemove(driver->domains, vm);
2807
        virObjectLock(vm);
J
Jim Fehlig 已提交
2808 2809 2810
        goto cleanup;
    }

2811
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid, vm->def->id);
J
Jim Fehlig 已提交
2812

2813
    event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_DEFINED,
2814
                                     !oldDef ?
2815 2816 2817
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED :
                                     VIR_DOMAIN_EVENT_DEFINED_UPDATED);

2818
 cleanup:
J
Jim Fehlig 已提交
2819
    virDomainDefFree(def);
2820
    virDomainDefFree(oldDef);
2821
    virDomainObjEndAPI(&vm);
2822 2823
    if (event)
        libxlDomainEventQueue(driver, event);
2824
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
2825 2826 2827
    return dom;
}

2828 2829 2830 2831 2832 2833
static virDomainPtr
libxlDomainDefineXML(virConnectPtr conn, const char *xml)
{
    return libxlDomainDefineXMLFlags(conn, xml, 0);
}

J
Jim Fehlig 已提交
2834
static int
2835 2836
libxlDomainUndefineFlags(virDomainPtr dom,
                         unsigned int flags)
J
Jim Fehlig 已提交
2837 2838
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
2839
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
J
Jim Fehlig 已提交
2840
    virDomainObjPtr vm;
2841
    virObjectEventPtr event = NULL;
2842
    char *name = NULL;
J
Jim Fehlig 已提交
2843 2844
    int ret = -1;

2845 2846
    virCheckFlags(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE, -1);

J
Jim Fehlig 已提交
2847
    if (!(vm = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
2848 2849
        goto cleanup;

2850 2851 2852
    if (virDomainUndefineFlagsEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

J
Jim Fehlig 已提交
2853
    if (!vm->persistent) {
2854 2855
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("cannot undefine transient domain"));
J
Jim Fehlig 已提交
2856 2857 2858
        goto cleanup;
    }

2859 2860 2861 2862 2863 2864 2865
    name = libxlDomainManagedSavePath(driver, vm);
    if (name == NULL)
        goto cleanup;

    if (virFileExists(name)) {
        if (flags & VIR_DOMAIN_UNDEFINE_MANAGED_SAVE) {
            if (unlink(name) < 0) {
2866 2867
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("Failed to remove domain managed save image"));
2868 2869 2870
                goto cleanup;
            }
        } else {
2871 2872 2873
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                           _("Refusing to undefine while domain managed "
                             "save image exists"));
2874 2875 2876 2877
            goto cleanup;
        }
    }

2878
    if (virDomainDeleteConfig(cfg->configDir, cfg->autostartDir, vm) < 0)
J
Jim Fehlig 已提交
2879 2880
        goto cleanup;

2881
    event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_UNDEFINED,
2882 2883
                                     VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);

2884 2885 2886
    if (virDomainObjIsActive(vm)) {
        vm->persistent = 0;
    } else {
2887
        virDomainObjListRemove(driver->domains, vm);
2888
        virObjectLock(vm);
2889 2890
    }

J
Jim Fehlig 已提交
2891 2892
    ret = 0;

2893
 cleanup:
2894
    VIR_FREE(name);
2895
    virDomainObjEndAPI(&vm);
2896 2897
    if (event)
        libxlDomainEventQueue(driver, event);
2898
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
2899 2900 2901
    return ret;
}

2902 2903 2904 2905 2906 2907
static int
libxlDomainUndefine(virDomainPtr dom)
{
    return libxlDomainUndefineFlags(dom, 0);
}

2908
static int
J
Jim Fehlig 已提交
2909
libxlDomainChangeEjectableMedia(virDomainObjPtr vm, virDomainDiskDefPtr disk)
2910
{
J
Jim Fehlig 已提交
2911
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(libxl_driver);
2912 2913
    virDomainDiskDefPtr origdisk = NULL;
    libxl_device_disk x_disk;
2914
    size_t i;
2915 2916
    int ret = -1;

2917
    for (i = 0; i < vm->def->ndisks; i++) {
2918 2919 2920 2921 2922 2923 2924 2925
        if (vm->def->disks[i]->bus == disk->bus &&
            STREQ(vm->def->disks[i]->dst, disk->dst)) {
            origdisk = vm->def->disks[i];
            break;
        }
    }

    if (!origdisk) {
2926 2927 2928
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("No device with bus '%s' and target '%s'"),
                       virDomainDiskBusTypeToString(disk->bus), disk->dst);
2929 2930 2931 2932
        goto cleanup;
    }

    if (origdisk->device != VIR_DOMAIN_DISK_DEVICE_CDROM) {
2933 2934 2935
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Removable media not supported for %s device"),
                       virDomainDiskDeviceTypeToString(disk->device));
2936 2937 2938
        return -1;
    }

J
Jim Fehlig 已提交
2939
    if (libxlMakeDisk(disk, &x_disk) < 0)
2940 2941
        goto cleanup;

J
Jim Fehlig 已提交
2942
    if ((ret = libxl_cdrom_insert(cfg->ctx, vm->def->id, &x_disk, NULL)) < 0) {
2943 2944 2945
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("libxenlight failed to change media for disk '%s'"),
                       disk->dst);
2946 2947 2948
        goto cleanup;
    }

2949 2950 2951
    if (virDomainDiskSetSource(origdisk, virDomainDiskGetSource(disk)) < 0)
        goto cleanup;
    virDomainDiskSetType(origdisk, virDomainDiskGetType(disk));
2952 2953 2954 2955 2956

    virDomainDiskDefFree(disk);

    ret = 0;

2957
 cleanup:
J
Jim Fehlig 已提交
2958
    virObjectUnref(cfg);
2959 2960 2961 2962
    return ret;
}

static int
J
Jim Fehlig 已提交
2963
libxlDomainAttachDeviceDiskLive(virDomainObjPtr vm, virDomainDeviceDefPtr dev)
2964
{
J
Jim Fehlig 已提交
2965
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(libxl_driver);
2966 2967 2968 2969 2970 2971
    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 已提交
2972
            ret = libxlDomainChangeEjectableMedia(vm, l_disk);
2973 2974 2975
            break;
        case VIR_DOMAIN_DISK_DEVICE_DISK:
            if (l_disk->bus == VIR_DOMAIN_DISK_BUS_XEN) {
2976
                if (virDomainDiskIndexByName(vm->def, l_disk->dst, true) >= 0) {
2977 2978
                    virReportError(VIR_ERR_OPERATION_FAILED,
                                   _("target %s already exists"), l_disk->dst);
2979 2980 2981
                    goto cleanup;
                }

2982
                if (!virDomainDiskGetSource(l_disk)) {
2983 2984
                    virReportError(VIR_ERR_INTERNAL_ERROR,
                                   "%s", _("disk source path is missing"));
2985 2986 2987
                    goto cleanup;
                }

2988
                if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks+1) < 0)
2989 2990
                    goto cleanup;

J
Jim Fehlig 已提交
2991
                if (libxlMakeDisk(l_disk, &x_disk) < 0)
2992 2993
                    goto cleanup;

2994 2995 2996 2997 2998
                if (virDomainLockDiskAttach(libxl_driver->lockManager,
                                            "xen:///system",
                                            vm, l_disk) < 0)
                    goto cleanup;

J
Jim Fehlig 已提交
2999
                if ((ret = libxl_device_disk_add(cfg->ctx, vm->def->id,
J
Jim Fehlig 已提交
3000
                                                &x_disk, NULL)) < 0) {
3001 3002 3003
                    virReportError(VIR_ERR_INTERNAL_ERROR,
                                   _("libxenlight failed to attach disk '%s'"),
                                   l_disk->dst);
3004 3005 3006 3007 3008
                    if (virDomainLockDiskDetach(libxl_driver->lockManager,
                                                vm, l_disk) < 0) {
                        VIR_WARN("Unable to release lock on %s",
                                 virDomainDiskGetSource(l_disk));
                    }
3009 3010 3011
                    goto cleanup;
                }

3012
                libxlUpdateDiskDef(l_disk, &x_disk);
3013 3014 3015
                virDomainDiskInsertPreAlloced(vm->def, l_disk);

            } else {
3016 3017 3018
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("disk bus '%s' cannot be hotplugged."),
                               virDomainDiskBusTypeToString(l_disk->bus));
3019 3020 3021
            }
            break;
        default:
3022 3023 3024
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("disk device type '%s' cannot be hotplugged"),
                           virDomainDiskDeviceTypeToString(l_disk->device));
3025 3026 3027
            break;
    }

3028
 cleanup:
J
Jim Fehlig 已提交
3029
    virObjectUnref(cfg);
3030 3031 3032
    return ret;
}

3033 3034 3035 3036 3037
static int
libxlDomainAttachHostPCIDevice(libxlDriverPrivatePtr driver,
                               virDomainObjPtr vm,
                               virDomainHostdevDefPtr hostdev)
{
J
Jim Fehlig 已提交
3038
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
3039
    libxl_device_pci pcidev;
3040 3041
    virDomainHostdevDefPtr found;
    virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
3042
    virDomainHostdevSubsysPCIPtr pcisrc = &hostdev->source.subsys.u.pci;
J
Jim Fehlig 已提交
3043
    int ret = -1;
3044

3045 3046
    libxl_device_pci_init(&pcidev);

3047 3048 3049
    if (virDomainHostdevFind(vm->def, hostdev, &found) >= 0) {
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("target pci device %.4x:%.2x:%.2x.%.1x already exists"),
3050 3051
                       pcisrc->addr.domain, pcisrc->addr.bus,
                       pcisrc->addr.slot, pcisrc->addr.function);
J
Jim Fehlig 已提交
3052
        goto cleanup;
3053 3054 3055
    }

    if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs + 1) < 0)
J
Jim Fehlig 已提交
3056
        goto cleanup;
3057 3058 3059 3060

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

3063
    if (libxlMakePCI(hostdev, &pcidev) < 0)
C
Chunyan Liu 已提交
3064
        goto error;
3065

J
Jim Fehlig 已提交
3066
    if (libxl_device_pci_add(cfg->ctx, vm->def->id, &pcidev, 0) < 0) {
3067 3068
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("libxenlight failed to attach pci device %.4x:%.2x:%.2x.%.1x"),
3069 3070
                       pcisrc->addr.domain, pcisrc->addr.bus,
                       pcisrc->addr.slot, pcisrc->addr.function);
C
Chunyan Liu 已提交
3071
        goto error;
3072 3073 3074
    }

    vm->def->hostdevs[vm->def->nhostdevs++] = hostdev;
J
Jim Fehlig 已提交
3075 3076
    ret = 0;
    goto cleanup;
3077

3078
 error:
3079 3080
    virHostdevReAttachPCIDevices(hostdev_mgr, LIBXL_DRIVER_NAME,
                                 vm->def->name, &hostdev, 1, NULL);
J
Jim Fehlig 已提交
3081 3082 3083

 cleanup:
    virObjectUnref(cfg);
3084
    libxl_device_pci_dispose(&pcidev);
J
Jim Fehlig 已提交
3085
    return ret;
3086 3087
}

3088
#ifdef LIBXL_HAVE_PVUSB
3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142
static int
libxlDomainAttachControllerDevice(libxlDriverPrivatePtr driver,
                                  virDomainObjPtr vm,
                                  virDomainControllerDefPtr controller)
{
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
    const char *type = virDomainControllerTypeToString(controller->type);
    libxl_device_usbctrl usbctrl;
    int ret = -1;

    libxl_device_usbctrl_init(&usbctrl);

    if (controller->type != VIR_DOMAIN_CONTROLLER_TYPE_USB) {
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
                       _("'%s' controller cannot be hot plugged."),
                       type);
        goto cleanup;
    }

    if (controller->idx == -1)
        controller->idx = virDomainControllerFindUnusedIndex(vm->def,
                                                             controller->type);

    if (controller->opts.usbopts.ports == -1)
        controller->opts.usbopts.ports = 8;

    if (virDomainControllerFind(vm->def, controller->type, controller->idx) >= 0) {
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("target %s:%d already exists"),
                       type, controller->idx);
        goto cleanup;
    }

    if (VIR_REALLOC_N(vm->def->controllers, vm->def->ncontrollers + 1) < 0)
        goto cleanup;

    if (libxlMakeUSBController(controller, &usbctrl) < 0)
        goto cleanup;

    if (libxl_device_usbctrl_add(cfg->ctx, vm->def->id, &usbctrl, 0) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("libxenlight failed to attach USB controller"));
        goto cleanup;
    }

    virDomainControllerInsertPreAlloced(vm->def, controller);
    ret = 0;

 cleanup:
    virObjectUnref(cfg);
    libxl_device_usbctrl_dispose(&usbctrl);
    return ret;
}

3143 3144 3145 3146 3147 3148 3149 3150 3151
static int
libxlDomainAttachHostUSBDevice(libxlDriverPrivatePtr driver,
                               virDomainObjPtr vm,
                               virDomainHostdevDefPtr hostdev)
{
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
    libxl_device_usbdev usbdev;
    virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
    int ret = -1;
3152 3153
    size_t i;
    int ports = 0, usbdevs = 0;
3154 3155 3156 3157 3158 3159 3160

    libxl_device_usbdev_init(&usbdev);

    if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS ||
        hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)
        goto cleanup;

3161 3162 3163 3164 3165 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190
    /* search for available controller:port */
    for (i = 0; i < vm->def->ncontrollers; i++)
        ports += vm->def->controllers[i]->opts.usbopts.ports;

    for (i = 0; i < vm->def->nhostdevs; i++) {
        if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
            hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB)
            usbdevs++;
    }

    if (ports <= usbdevs) {
        /* no free ports, we will create a new usb controller */
        virDomainControllerDefPtr controller;

        if (!(controller = virDomainControllerDefNew(VIR_DOMAIN_CONTROLLER_TYPE_USB)))
            goto cleanup;

        controller->model = VIR_DOMAIN_CONTROLLER_MODEL_USB_QUSB2;
        controller->idx = -1;
        controller->opts.usbopts.ports = 8;

        if (libxlDomainAttachControllerDevice(driver, vm, controller) < 0) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("No available USB controller and port, and "
                             "failed to attach a new one"));
            virDomainControllerDefFree(controller);
            goto cleanup;
        }
    }

3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223
    if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs + 1) < 0)
        goto cleanup;

    if (virHostdevPrepareUSBDevices(hostdev_mgr, LIBXL_DRIVER_NAME,
                                    vm->def->name, &hostdev, 1, 0) < 0)
        goto cleanup;

    if (libxlMakeUSB(hostdev, &usbdev) < 0)
        goto reattach;

    if (libxl_device_usbdev_add(cfg->ctx, vm->def->id, &usbdev, 0) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("libxenlight failed to attach usb device Busnum:%3x, Devnum:%3x"),
                       hostdev->source.subsys.u.usb.bus,
                       hostdev->source.subsys.u.usb.device);
        goto reattach;
    }

    vm->def->hostdevs[vm->def->nhostdevs++] = hostdev;
    ret = 0;
    goto cleanup;

 reattach:
    virHostdevReAttachUSBDevices(hostdev_mgr, LIBXL_DRIVER_NAME,
                                 vm->def->name, &hostdev, 1);

 cleanup:
    virObjectUnref(cfg);
    libxl_device_usbdev_dispose(&usbdev);
    return ret;
}
#endif

3224 3225 3226
static int
libxlDomainAttachHostDevice(libxlDriverPrivatePtr driver,
                            virDomainObjPtr vm,
3227
                            virDomainHostdevDefPtr hostdev)
3228 3229 3230 3231 3232 3233 3234 3235 3236 3237
{
    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 已提交
3238
        if (libxlDomainAttachHostPCIDevice(driver, vm, hostdev) < 0)
C
Chunyan Liu 已提交
3239
            return -1;
3240 3241
        break;

3242 3243 3244 3245 3246 3247 3248
#ifdef LIBXL_HAVE_PVUSB
    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
        if (libxlDomainAttachHostUSBDevice(driver, vm, hostdev) < 0)
            return -1;
        break;
#endif

3249 3250 3251 3252
    default:
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("hostdev subsys type '%s' not supported"),
                       virDomainHostdevSubsysTypeToString(hostdev->source.subsys.type));
C
Chunyan Liu 已提交
3253
        return -1;
3254 3255 3256 3257 3258
    }

    return 0;
}

3259
static int
J
Jim Fehlig 已提交
3260
libxlDomainDetachDeviceDiskLive(virDomainObjPtr vm, virDomainDeviceDefPtr dev)
3261
{
J
Jim Fehlig 已提交
3262
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(libxl_driver);
3263 3264
    virDomainDiskDefPtr l_disk = NULL;
    libxl_device_disk x_disk;
3265
    int idx;
3266 3267 3268 3269 3270 3271
    int ret = -1;

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

3272 3273 3274
                if ((idx = virDomainDiskIndexByName(vm->def,
                                                    dev->data.disk->dst,
                                                    false)) < 0) {
3275 3276
                    virReportError(VIR_ERR_OPERATION_FAILED,
                                   _("disk %s not found"), dev->data.disk->dst);
3277 3278 3279
                    goto cleanup;
                }

3280
                l_disk = vm->def->disks[idx];
3281

J
Jim Fehlig 已提交
3282
                if (libxlMakeDisk(l_disk, &x_disk) < 0)
3283 3284
                    goto cleanup;

J
Jim Fehlig 已提交
3285
                if ((ret = libxl_device_disk_remove(cfg->ctx, vm->def->id,
J
Jim Fehlig 已提交
3286
                                                    &x_disk, NULL)) < 0) {
3287 3288 3289
                    virReportError(VIR_ERR_INTERNAL_ERROR,
                                   _("libxenlight failed to detach disk '%s'"),
                                   l_disk->dst);
3290 3291 3292
                    goto cleanup;
                }

3293 3294 3295 3296 3297
                if (virDomainLockDiskDetach(libxl_driver->lockManager,
                                            vm, l_disk) < 0)
                    VIR_WARN("Unable to release lock on %s",
                             virDomainDiskGetSource(l_disk));

3298
                virDomainDiskRemove(vm->def, idx);
3299 3300 3301
                virDomainDiskDefFree(l_disk);

            } else {
3302 3303 3304
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("disk bus '%s' cannot be hot unplugged."),
                               virDomainDiskBusTypeToString(dev->data.disk->bus));
3305 3306 3307
            }
            break;
        default:
3308 3309 3310
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("device type '%s' cannot hot unplugged"),
                           virDomainDiskDeviceTypeToString(dev->data.disk->device));
3311 3312 3313
            break;
    }

3314
 cleanup:
J
Jim Fehlig 已提交
3315
    virObjectUnref(cfg);
3316 3317 3318
    return ret;
}

3319 3320 3321 3322 3323
static int
libxlDomainAttachNetDevice(libxlDriverPrivatePtr driver,
                           virDomainObjPtr vm,
                           virDomainNetDefPtr net)
{
J
Jim Fehlig 已提交
3324
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
3325
    virDomainNetType actualType;
3326 3327
    libxl_device_nic nic;
    int ret = -1;
3328
    char mac[VIR_MAC_STRING_BUFLEN];
3329

3330 3331
    libxl_device_nic_init(&nic);

3332 3333
    /* preallocate new slot for device */
    if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets + 1) < 0)
3334
        goto cleanup;
3335 3336 3337 3338 3339

    /* 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.
     */
3340
    if (virDomainNetAllocateActualDevice(vm->def, net) < 0)
3341
        goto cleanup;
3342 3343 3344

    actualType = virDomainNetGetActualType(net);

3345 3346 3347 3348
    if (virDomainHasNet(vm->def, net)) {
        virReportError(VIR_ERR_INVALID_ARG,
                       _("network device with mac %s already exists"),
                       virMacAddrFormat(&net->mac, mac));
3349
        goto cleanup;
3350 3351
    }

3352
    if (actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363
        virDomainHostdevDefPtr hostdev = virDomainNetGetActualHostdev(net);
        virDomainHostdevSubsysPCIPtr pcisrc = &hostdev->source.subsys.u.pci;

        /* For those just allocated from a network pool whose backend is
         * still VIR_DOMAIN_HOSTDEV_PCI_BACKEND_DEFAULT, we need to set
         * backend correctly.
         */
        if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS &&
            hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI)
            pcisrc->backend = VIR_DOMAIN_HOSTDEV_PCI_BACKEND_XEN;

3364 3365 3366
        /* 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
3367
         * the nets list if successful.
3368
         */
3369
        ret = libxlDomainAttachHostDevice(driver, vm, hostdev);
3370
        goto cleanup;
3371 3372
    }

3373
    if (libxlMakeNic(vm->def, net, &nic, true) < 0)
3374 3375
        goto cleanup;

J
Jim Fehlig 已提交
3376
    if (libxl_device_nic_add(cfg->ctx, vm->def->id, &nic, 0)) {
3377 3378 3379 3380 3381 3382 3383 3384 3385
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("libxenlight failed to attach network device"));
        goto cleanup;
    }

    ret = 0;

 cleanup:
    libxl_device_nic_dispose(&nic);
3386 3387 3388
    if (!ret) {
        vm->def->nets[vm->def->nnets++] = net;
    } else {
3389
        virDomainNetRemoveHostdev(vm->def, net);
3390
        virDomainNetReleaseActualDevice(vm->def, net);
3391
    }
J
Jim Fehlig 已提交
3392
    virObjectUnref(cfg);
3393 3394 3395
    return ret;
}

3396
static int
3397 3398
libxlDomainAttachDeviceLive(libxlDriverPrivatePtr driver,
                            virDomainObjPtr vm,
3399 3400 3401 3402 3403 3404
                            virDomainDeviceDefPtr dev)
{
    int ret = -1;

    switch (dev->type) {
        case VIR_DOMAIN_DEVICE_DISK:
J
Jim Fehlig 已提交
3405
            ret = libxlDomainAttachDeviceDiskLive(vm, dev);
3406 3407 3408 3409
            if (!ret)
                dev->data.disk = NULL;
            break;

3410
#ifdef LIBXL_HAVE_PVUSB
3411 3412 3413 3414 3415
        case VIR_DOMAIN_DEVICE_CONTROLLER:
            ret = libxlDomainAttachControllerDevice(driver, vm, dev->data.controller);
            if (!ret)
                dev->data.controller = NULL;
            break;
3416
#endif
3417

3418
        case VIR_DOMAIN_DEVICE_NET:
J
Jim Fehlig 已提交
3419
            ret = libxlDomainAttachNetDevice(driver, vm,
3420 3421 3422 3423 3424
                                             dev->data.net);
            if (!ret)
                dev->data.net = NULL;
            break;

3425
        case VIR_DOMAIN_DEVICE_HOSTDEV:
J
Jim Fehlig 已提交
3426
            ret = libxlDomainAttachHostDevice(driver, vm,
3427
                                              dev->data.hostdev);
3428 3429 3430 3431
            if (!ret)
                dev->data.hostdev = NULL;
            break;

3432
        default:
3433 3434 3435
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("device type '%s' cannot be attached"),
                           virDomainDeviceTypeToString(dev->type));
3436 3437 3438 3439 3440 3441 3442 3443 3444 3445
            break;
    }

    return ret;
}

static int
libxlDomainAttachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev)
{
    virDomainDiskDefPtr disk;
3446
    virDomainNetDefPtr net;
3447
    virDomainHostdevDefPtr hostdev;
3448
    virDomainControllerDefPtr controller;
3449
    virDomainHostdevDefPtr found;
3450
    char mac[VIR_MAC_STRING_BUFLEN];
3451 3452 3453 3454

    switch (dev->type) {
        case VIR_DOMAIN_DEVICE_DISK:
            disk = dev->data.disk;
3455
            if (virDomainDiskIndexByName(vmdef, disk->dst, true) >= 0) {
3456 3457
                virReportError(VIR_ERR_INVALID_ARG,
                               _("target %s already exists."), disk->dst);
3458 3459
                return -1;
            }
3460
            if (virDomainDiskInsert(vmdef, disk))
3461 3462 3463 3464
                return -1;
            /* vmdef has the pointer. Generic codes for vmdef will do all jobs */
            dev->data.disk = NULL;
            break;
3465

3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480
        case VIR_DOMAIN_DEVICE_CONTROLLER:
            controller = dev->data.controller;
            if (controller->idx != -1 &&
                virDomainControllerFind(vmdef, controller->type,
                                        controller->idx) >= 0) {
                virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                               _("Target already exists"));
                return -1;
            }

            if (virDomainControllerInsert(vmdef, controller) < 0)
                return -1;
            dev->data.controller = NULL;
            break;

3481 3482
        case VIR_DOMAIN_DEVICE_NET:
            net = dev->data.net;
3483 3484 3485 3486 3487 3488
            if (virDomainHasNet(vmdef, net)) {
                virReportError(VIR_ERR_INVALID_ARG,
                               _("network device with mac %s already exists"),
                               virMacAddrFormat(&net->mac, mac));
                return -1;
            }
3489 3490 3491 3492 3493
            if (virDomainNetInsert(vmdef, net))
                return -1;
            dev->data.net = NULL;
            break;

3494 3495 3496
        case VIR_DOMAIN_DEVICE_HOSTDEV:
            hostdev = dev->data.hostdev;

3497 3498 3499 3500 3501 3502
            switch (hostdev->source.subsys.type) {
            case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI:
#ifndef LIBXL_HAVE_PVUSB
            case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
#endif
            case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST:
3503
                return -1;
3504
            }
3505 3506

            if (virDomainHostdevFind(vmdef, hostdev, &found) >= 0) {
3507 3508
                virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                               _("device is already in the domain configuration"));
3509 3510 3511
                return -1;
            }

3512 3513
            if (virDomainHostdevInsert(vmdef, hostdev) < 0)
                return -1;
3514
            dev->data.hostdev = NULL;
3515
            break;
3516 3517

        default:
3518 3519
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("persistent attach of device is not supported"));
3520 3521 3522 3523 3524 3525
            return -1;
    }
    return 0;
}

static int
3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558
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 已提交
3559
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
3560
    virDomainHostdevSubsysPtr subsys = &hostdev->source.subsys;
3561
    virDomainHostdevSubsysPCIPtr pcisrc = &subsys->u.pci;
3562 3563 3564 3565
    libxl_device_pci pcidev;
    virDomainHostdevDefPtr detach;
    int idx;
    virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
J
Jim Fehlig 已提交
3566
    int ret = -1;
3567

3568 3569
    libxl_device_pci_init(&pcidev);

3570 3571 3572 3573
    idx = virDomainHostdevFind(vm->def, hostdev, &detach);
    if (idx < 0) {
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("host pci device %.4x:%.2x:%.2x.%.1x not found"),
3574 3575
                       pcisrc->addr.domain, pcisrc->addr.bus,
                       pcisrc->addr.slot, pcisrc->addr.function);
J
Jim Fehlig 已提交
3576
        goto cleanup;
3577 3578 3579 3580 3581
    }

    if (libxlIsMultiFunctionDevice(vm->def, detach->info)) {
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("cannot hot unplug multifunction PCI device: %.4x:%.2x:%.2x.%.1x"),
3582 3583
                       pcisrc->addr.domain, pcisrc->addr.bus,
                       pcisrc->addr.slot, pcisrc->addr.function);
C
Chunyan Liu 已提交
3584
        goto error;
3585 3586 3587
    }


3588
    if (libxlMakePCI(detach, &pcidev) < 0)
C
Chunyan Liu 已提交
3589
        goto error;
3590

J
Jim Fehlig 已提交
3591
    if (libxl_device_pci_remove(cfg->ctx, vm->def->id, &pcidev, 0) < 0) {
3592 3593 3594
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("libxenlight failed to detach pci device\
                          %.4x:%.2x:%.2x.%.1x"),
3595 3596
                       pcisrc->addr.domain, pcisrc->addr.bus,
                       pcisrc->addr.slot, pcisrc->addr.function);
C
Chunyan Liu 已提交
3597
        goto error;
3598 3599 3600 3601 3602 3603 3604 3605
    }


    virDomainHostdevRemove(vm->def, idx);

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

J
Jim Fehlig 已提交
3606
    ret = 0;
3607

3608
 error:
3609
    virDomainHostdevDefFree(detach);
J
Jim Fehlig 已提交
3610 3611 3612

 cleanup:
    virObjectUnref(cfg);
3613
    libxl_device_pci_dispose(&pcidev);
J
Jim Fehlig 已提交
3614
    return ret;
3615 3616
}

3617
#ifdef LIBXL_HAVE_PVUSB
3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668
static int
libxlDomainDetachControllerDevice(libxlDriverPrivatePtr driver,
                                  virDomainObjPtr vm,
                                  virDomainDeviceDefPtr dev)
{
    int idx, ret = -1;
    virDomainControllerDefPtr detach = NULL;
    virDomainControllerDefPtr controller = dev->data.controller;
    const char *type = virDomainControllerTypeToString(controller->type);
    libxl_device_usbctrl usbctrl;
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);

    libxl_device_usbctrl_init(&usbctrl);

    if (controller->type != VIR_DOMAIN_CONTROLLER_TYPE_USB) {
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
                       _("'%s' controller cannot be hot plugged."),
                       type);
        goto cleanup;
    }

    if ((idx = virDomainControllerFind(vm->def,
                                       controller->type,
                                       controller->idx)) < 0) {
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("controller %s:%d not found"),
                       type, controller->idx);
        goto cleanup;
    }

    detach = vm->def->controllers[idx];

    if (libxlMakeUSBController(controller, &usbctrl) < 0)
        goto cleanup;

    if (libxl_device_usbctrl_remove(cfg->ctx, vm->def->id, &usbctrl, 0) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("libxenlight failed to detach USB controller"));
        goto cleanup;
    }

    virDomainControllerRemove(vm->def, idx);
    ret = 0;

 cleanup:
    virDomainControllerDefFree(detach);
    virObjectUnref(cfg);
    libxl_device_usbctrl_dispose(&usbctrl);
    return ret;
}

3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710 3711 3712 3713 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737
static int
libxlDomainDetachHostUSBDevice(libxlDriverPrivatePtr driver,
                               virDomainObjPtr vm,
                               virDomainHostdevDefPtr hostdev)
{
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
    virDomainHostdevSubsysPtr subsys = &hostdev->source.subsys;
    virDomainHostdevSubsysUSBPtr usbsrc = &subsys->u.usb;
    virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
    libxl_device_usbdev usbdev;
    libxl_device_usbdev *usbdevs = NULL;
    int num = 0;
    virDomainHostdevDefPtr detach;
    int idx;
    size_t i;
    bool found = false;
    int ret = -1;

    libxl_device_usbdev_init(&usbdev);

    idx = virDomainHostdevFind(vm->def, hostdev, &detach);
    if (idx < 0) {
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("host USB device Busnum: %3x, Devnum: %3x not found"),
                       usbsrc->bus, usbsrc->device);
        goto cleanup;
    }

    usbdevs = libxl_device_usbdev_list(cfg->ctx, vm->def->id, &num);
    for (i = 0; i < num; i++) {
        if (usbdevs[i].u.hostdev.hostbus == usbsrc->bus &&
            usbdevs[i].u.hostdev.hostaddr == usbsrc->device) {
            libxl_device_usbdev_copy(cfg->ctx, &usbdev, &usbdevs[i]);
            found = true;
            break;
        }
    }
    libxl_device_usbdev_list_free(usbdevs, num);

    if (!found) {
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("host USB device Busnum: %3x, Devnum: %3x not found"),
                       usbsrc->bus, usbsrc->device);
        goto cleanup;
    }

    if (libxl_device_usbdev_remove(cfg->ctx, vm->def->id, &usbdev, 0) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("libxenlight failed to detach USB device\
                          Busnum: %3x, Devnum: %3x"),
                       usbsrc->bus, usbsrc->device);
        goto cleanup;
    }

    virDomainHostdevRemove(vm->def, idx);

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

    ret = 0;

 cleanup:
    virDomainHostdevDefFree(detach);
    virObjectUnref(cfg);
    libxl_device_usbdev_dispose(&usbdev);
    return ret;
}
#endif

3738 3739 3740
static int
libxlDomainDetachHostDevice(libxlDriverPrivatePtr driver,
                            virDomainObjPtr vm,
3741
                            virDomainHostdevDefPtr hostdev)
3742 3743 3744 3745 3746 3747 3748 3749 3750 3751 3752 3753
{
    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 已提交
3754
            return libxlDomainDetachHostPCIDevice(driver, vm, hostdev);
3755

3756 3757 3758 3759 3760
#ifdef LIBXL_HAVE_PVUSB
        case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB:
            return libxlDomainDetachHostUSBDevice(driver, vm, hostdev);
#endif

3761 3762 3763 3764 3765 3766 3767 3768 3769
        default:
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("unexpected hostdev type %d"), subsys->type);
            break;
    }

    return -1;
}

3770 3771 3772 3773 3774
static int
libxlDomainDetachNetDevice(libxlDriverPrivatePtr driver,
                           virDomainObjPtr vm,
                           virDomainNetDefPtr net)
{
J
Jim Fehlig 已提交
3775
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
3776 3777 3778 3779 3780 3781
    int detachidx;
    virDomainNetDefPtr detach = NULL;
    libxl_device_nic nic;
    char mac[VIR_MAC_STRING_BUFLEN];
    int ret = -1;

3782 3783
    libxl_device_nic_init(&nic);

3784
    if ((detachidx = virDomainNetFindIdx(vm->def, net)) < 0)
3785
        goto cleanup;
3786 3787 3788 3789 3790 3791 3792

    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 已提交
3793
        ret = libxlDomainDetachHostDevice(driver, vm,
3794
                                          virDomainNetGetActualHostdev(detach));
3795
        goto cleanup;
3796 3797
    }

J
Jim Fehlig 已提交
3798
    if (libxl_mac_to_device_nic(cfg->ctx, vm->def->id,
3799 3800 3801
                                virMacAddrFormat(&detach->mac, mac), &nic))
        goto cleanup;

J
Jim Fehlig 已提交
3802
    if (libxl_device_nic_remove(cfg->ctx, vm->def->id, &nic, 0)) {
3803 3804 3805 3806 3807 3808 3809 3810 3811
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("libxenlight failed to detach network device"));
        goto cleanup;
    }

    ret = 0;

 cleanup:
    libxl_device_nic_dispose(&nic);
J
Jim Fehlig 已提交
3812
    if (!ret) {
3813
        virDomainNetReleaseActualDevice(vm->def, detach);
J
Jim Fehlig 已提交
3814 3815
        virDomainNetRemove(vm->def, detachidx);
    }
J
Jim Fehlig 已提交
3816
    virObjectUnref(cfg);
3817 3818 3819
    return ret;
}

3820 3821 3822
static int
libxlDomainDetachDeviceLive(libxlDriverPrivatePtr driver,
                            virDomainObjPtr vm,
3823 3824
                            virDomainDeviceDefPtr dev)
{
3825
    virDomainHostdevDefPtr hostdev;
3826 3827 3828 3829
    int ret = -1;

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

3833
#ifdef LIBXL_HAVE_PVUSB
3834 3835 3836
        case VIR_DOMAIN_DEVICE_CONTROLLER:
            ret = libxlDomainDetachControllerDevice(driver, vm, dev);
            break;
3837
#endif
3838

3839
        case VIR_DOMAIN_DEVICE_NET:
J
Jim Fehlig 已提交
3840
            ret = libxlDomainDetachNetDevice(driver, vm,
3841 3842 3843
                                             dev->data.net);
            break;

3844
        case VIR_DOMAIN_DEVICE_HOSTDEV:
3845 3846 3847 3848 3849 3850 3851 3852 3853 3854
            hostdev = dev->data.hostdev;

            /* If this is a network hostdev, we need to use the higher-level
             * detach function so that mac address / virtualport are reset
             */
            if (hostdev->parent.type == VIR_DOMAIN_DEVICE_NET)
                ret = libxlDomainDetachNetDevice(driver, vm,
                                                 hostdev->parent.data.net);
            else
                ret = libxlDomainDetachHostDevice(driver, vm, hostdev);
3855 3856
            break;

3857
        default:
3858 3859 3860
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("device type '%s' cannot be detached"),
                           virDomainDeviceTypeToString(dev->type));
3861 3862 3863 3864 3865 3866
            break;
    }

    return ret;
}

3867

3868 3869 3870
static int
libxlDomainDetachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev)
{
3871
    virDomainDiskDefPtr disk, detach;
3872
    virDomainHostdevDefPtr hostdev, det_hostdev;
3873
    virDomainControllerDefPtr cont, det_cont;
3874
    virDomainNetDefPtr net;
3875
    int idx;
3876 3877 3878 3879

    switch (dev->type) {
        case VIR_DOMAIN_DEVICE_DISK:
            disk = dev->data.disk;
3880
            if (!(detach = virDomainDiskRemoveByName(vmdef, disk->dst))) {
3881 3882
                virReportError(VIR_ERR_INVALID_ARG,
                               _("no target device %s"), disk->dst);
3883
                return -1;
3884
            }
3885
            virDomainDiskDefFree(detach);
3886
            break;
3887

3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899
        case VIR_DOMAIN_DEVICE_CONTROLLER:
            cont = dev->data.controller;
            if ((idx = virDomainControllerFind(vmdef, cont->type,
                                               cont->idx)) < 0) {
                virReportError(VIR_ERR_INVALID_ARG, "%s",
                               _("device not present in domain configuration"));
                return -1;
            }
            det_cont = virDomainControllerRemove(vmdef, idx);
            virDomainControllerDefFree(det_cont);
            break;

3900 3901 3902 3903 3904 3905 3906 3907 3908
        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;

3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920
        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;
        }

3921
        default:
3922 3923
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("persistent detach of device is not supported"));
3924
            return -1;
3925 3926
    }

3927
    return 0;
3928 3929 3930
}

static int
J
Jim Fehlig 已提交
3931
libxlDomainUpdateDeviceLive(virDomainObjPtr vm, virDomainDeviceDefPtr dev)
3932 3933 3934 3935 3936 3937 3938 3939 3940
{
    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 已提交
3941
                    ret = libxlDomainChangeEjectableMedia(vm, disk);
3942 3943 3944 3945
                    if (ret == 0)
                        dev->data.disk = NULL;
                    break;
                default:
3946 3947 3948
                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                                   _("disk bus '%s' cannot be updated."),
                                   virDomainDiskBusTypeToString(disk->bus));
3949 3950 3951 3952
                    break;
            }
            break;
        default:
3953 3954 3955
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("device type '%s' cannot be updated"),
                           virDomainDeviceTypeToString(dev->type));
3956 3957 3958 3959 3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971
            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;
3972
            if (!(orig = virDomainDiskByName(vmdef, disk->dst, false))) {
3973 3974
                virReportError(VIR_ERR_INVALID_ARG,
                               _("target %s doesn't exist."), disk->dst);
3975 3976 3977
                goto cleanup;
            }
            if (!(orig->device == VIR_DOMAIN_DISK_DEVICE_CDROM)) {
3978 3979
                virReportError(VIR_ERR_INVALID_ARG, "%s",
                               _("this disk doesn't support update"));
3980 3981 3982
                goto cleanup;
            }

3983 3984 3985 3986 3987 3988
            if (virDomainDiskSetSource(orig, virDomainDiskGetSource(disk)) < 0)
                goto cleanup;
            virDomainDiskSetType(orig, virDomainDiskGetType(disk));
            virDomainDiskSetFormat(orig, virDomainDiskGetFormat(disk));
            if (virDomainDiskSetDriver(orig, virDomainDiskGetDriver(disk)) < 0)
                goto cleanup;
3989 3990
            break;
        default:
3991 3992
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("persistent update of device is not supported"));
3993 3994 3995 3996 3997
            goto cleanup;
    }

    ret = 0;

3998
 cleanup:
3999 4000 4001 4002 4003
    return ret;
}


static int
4004 4005
libxlDomainAttachDeviceFlags(virDomainPtr dom, const char *xml,
                             unsigned int flags)
4006 4007
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
4008
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
4009 4010 4011 4012 4013 4014 4015 4016
    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 已提交
4017
    if (!(vm = libxlDomObjFromDomain(dom)))
4018 4019
        goto cleanup;

4020 4021 4022
    if (virDomainAttachDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
        goto cleanup;

4023 4024 4025
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

4026 4027
    if (virDomainObjUpdateModificationImpact(vm, &flags) < 0)
        goto endjob;
4028 4029

    if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
4030
        if (!(dev = virDomainDeviceDefParse(xml, vm->def,
4031
                                            cfg->caps, driver->xmlopt,
4032
                                            VIR_DOMAIN_DEF_PARSE_INACTIVE)))
4033
            goto endjob;
4034 4035

        /* Make a copy for updated domain. */
4036
        if (!(vmdef = virDomainObjCopyPersistentDef(vm, cfg->caps,
4037
                                                    driver->xmlopt)))
4038
            goto endjob;
4039

4040
        if (libxlDomainAttachDeviceConfig(vmdef, dev) < 0)
4041
            goto endjob;
4042
    }
4043 4044 4045 4046

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

J
Jim Fehlig 已提交
4052
        if (libxlDomainAttachDeviceLive(driver, vm, dev) < 0)
4053
            goto endjob;
4054

4055 4056 4057 4058
        /*
         * update domain status forcibly because the domain status may be
         * changed even if we attach the device failed.
         */
4059
        if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, cfg->caps) < 0)
4060
            goto endjob;
4061 4062
    }

4063 4064
    ret = 0;

4065
    /* Finally, if no error until here, we can save config. */
4066
    if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
4067
        ret = virDomainSaveConfig(cfg->configDir, cfg->caps, vmdef);
4068
        if (!ret) {
4069
            virDomainObjAssignDef(vm, vmdef, false, NULL);
4070 4071 4072 4073
            vmdef = NULL;
        }
    }

4074
 endjob:
W
Wang Yufei 已提交
4075
    libxlDomainObjEndJob(driver, vm);
4076

4077
 cleanup:
4078 4079
    virDomainDefFree(vmdef);
    virDomainDeviceDefFree(dev);
W
Wang Yufei 已提交
4080
    virDomainObjEndAPI(&vm);
4081
    virObjectUnref(cfg);
4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095
    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)
{
4096
    libxlDriverPrivatePtr driver = dom->conn->privateData;
4097
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
4098 4099 4100 4101 4102 4103 4104 4105
    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 已提交
4106
    if (!(vm = libxlDomObjFromDomain(dom)))
4107 4108
        goto cleanup;

4109 4110 4111
    if (virDomainDetachDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
        goto cleanup;

4112 4113 4114
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

4115 4116
    if (virDomainObjUpdateModificationImpact(vm, &flags) < 0)
        goto endjob;
4117 4118 4119

    if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
        if (!(dev = virDomainDeviceDefParse(xml, vm->def,
4120
                                            cfg->caps, driver->xmlopt,
4121 4122
                                            VIR_DOMAIN_DEF_PARSE_INACTIVE |
                                            VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE)))
4123
            goto endjob;
4124 4125

        /* Make a copy for updated domain. */
4126
        if (!(vmdef = virDomainObjCopyPersistentDef(vm, cfg->caps,
4127
                                                    driver->xmlopt)))
4128
            goto endjob;
4129

4130
        if (libxlDomainDetachDeviceConfig(vmdef, dev) < 0)
4131
            goto endjob;
4132 4133 4134 4135 4136 4137
    }

    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,
4138
                                            cfg->caps, driver->xmlopt,
4139 4140
                                            VIR_DOMAIN_DEF_PARSE_INACTIVE |
                                            VIR_DOMAIN_DEF_PARSE_SKIP_VALIDATE)))
4141
            goto endjob;
4142

J
Jim Fehlig 已提交
4143
        if (libxlDomainDetachDeviceLive(driver, vm, dev) < 0)
4144
            goto endjob;
4145 4146 4147 4148 4149

        /*
         * update domain status forcibly because the domain status may be
         * changed even if we attach the device failed.
         */
4150
        if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, cfg->caps) < 0)
4151
            goto endjob;
4152 4153
    }

4154 4155
    ret = 0;

4156
    /* Finally, if no error until here, we can save config. */
4157
    if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
4158
        ret = virDomainSaveConfig(cfg->configDir, cfg->caps, vmdef);
4159 4160 4161 4162 4163 4164
        if (!ret) {
            virDomainObjAssignDef(vm, vmdef, false, NULL);
            vmdef = NULL;
        }
    }

4165
 endjob:
W
Wang Yufei 已提交
4166
    libxlDomainObjEndJob(driver, vm);
4167

4168
 cleanup:
4169 4170
    virDomainDefFree(vmdef);
    virDomainDeviceDefFree(dev);
W
Wang Yufei 已提交
4171
    virDomainObjEndAPI(&vm);
4172
    virObjectUnref(cfg);
4173
    return ret;
4174 4175 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186
}

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)
{
4187
    libxlDriverPrivatePtr driver = dom->conn->privateData;
4188
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
4189 4190 4191 4192 4193 4194 4195 4196
    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 已提交
4197
    if (!(vm = libxlDomObjFromDomain(dom)))
4198 4199
        goto cleanup;

4200 4201 4202
    if (virDomainUpdateDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
        goto cleanup;

4203 4204
    if (virDomainObjUpdateModificationImpact(vm, &flags) < 0)
        goto cleanup;
4205 4206 4207

    if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
        if (!(dev = virDomainDeviceDefParse(xml, vm->def,
4208
                                            cfg->caps, driver->xmlopt,
4209
                                            VIR_DOMAIN_DEF_PARSE_INACTIVE)))
4210 4211 4212
            goto cleanup;

        /* Make a copy for updated domain. */
4213
        if (!(vmdef = virDomainObjCopyPersistentDef(vm, cfg->caps,
4214 4215 4216 4217 4218 4219 4220 4221 4222 4223 4224 4225 4226
                                                    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,
4227
                                            cfg->caps, driver->xmlopt,
4228
                                            VIR_DOMAIN_DEF_PARSE_INACTIVE)))
4229 4230
            goto cleanup;

J
Jim Fehlig 已提交
4231
        if ((ret = libxlDomainUpdateDeviceLive(vm, dev)) < 0)
4232 4233 4234 4235 4236 4237
            goto cleanup;

        /*
         * update domain status forcibly because the domain status may be
         * changed even if we attach the device failed.
         */
4238
        if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm, cfg->caps) < 0)
4239 4240 4241 4242 4243
            ret = -1;
    }

    /* Finally, if no error until here, we can save config. */
    if (!ret && (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG)) {
4244
        ret = virDomainSaveConfig(cfg->configDir, cfg->caps, vmdef);
4245 4246 4247 4248 4249 4250
        if (!ret) {
            virDomainObjAssignDef(vm, vmdef, false, NULL);
            vmdef = NULL;
        }
    }

4251
 cleanup:
4252 4253
    virDomainDefFree(vmdef);
    virDomainDeviceDefFree(dev);
4254
    virDomainObjEndAPI(&vm);
4255
    virObjectUnref(cfg);
4256
    return ret;
4257 4258
}

4259 4260 4261 4262 4263
static unsigned long long
libxlNodeGetFreeMemory(virConnectPtr conn)
{
    libxl_physinfo phy_info;
    libxlDriverPrivatePtr driver = conn->privateData;
4264 4265
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
    unsigned long long ret = 0;
4266

4267
    libxl_physinfo_init(&phy_info);
4268
    if (virNodeGetFreeMemoryEnsureACL(conn) < 0)
4269
        goto cleanup;
4270

4271
    if (libxl_get_physinfo(cfg->ctx, &phy_info)) {
4272 4273
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("libxl_get_physinfo_info failed"));
4274
        goto cleanup;
4275 4276
    }

4277 4278
    ret = phy_info.free_pages * cfg->verInfo->pagesize;

4279
 cleanup:
4280
    libxl_physinfo_dispose(&phy_info);
4281 4282
    virObjectUnref(cfg);
    return ret;
4283 4284
}

4285 4286 4287 4288 4289 4290 4291 4292 4293 4294
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;
4295
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
4296 4297

    if (virNodeGetCellsFreeMemoryEnsureACL(conn) < 0)
4298
        goto cleanup;
4299

4300
    numa_info = libxl_get_numainfo(cfg->ctx, &nr_nodes);
4301
    if (numa_info == NULL || nr_nodes == 0) {
4302 4303 4304
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("libxl_get_numainfo failed"));
        goto cleanup;
4305 4306 4307
    }

    /* Check/sanitize the cell range */
4308
    if (startCell >= nr_nodes) {
4309 4310
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("start cell %d out of range (0-%d)"),
4311
                       startCell, nr_nodes - 1);
4312 4313 4314
        goto cleanup;
    }
    lastCell = startCell + maxCells - 1;
4315 4316
    if (lastCell >= nr_nodes)
        lastCell = nr_nodes - 1;
4317 4318 4319 4320 4321 4322 4323

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

4325 4326
    ret = numCells;

4327
 cleanup:
4328
    libxl_numainfo_list_free(numa_info, nr_nodes);
4329
    virObjectUnref(cfg);
4330 4331 4332
    return ret;
}

4333
static int
4334
libxlConnectDomainEventRegister(virConnectPtr conn,
4335 4336
                                virConnectDomainEventCallback callback,
                                void *opaque,
4337
                                virFreeCallback freecb)
4338 4339 4340
{
    libxlDriverPrivatePtr driver = conn->privateData;

4341 4342 4343
    if (virConnectDomainEventRegisterEnsureACL(conn) < 0)
        return -1;

4344 4345 4346 4347
    if (virDomainEventStateRegister(conn,
                                    driver->domainEventState,
                                    callback, opaque, freecb) < 0)
        return -1;
4348

4349
    return 0;
4350 4351 4352 4353
}


static int
4354 4355
libxlConnectDomainEventDeregister(virConnectPtr conn,
                                  virConnectDomainEventCallback callback)
4356 4357 4358
{
    libxlDriverPrivatePtr driver = conn->privateData;

4359 4360 4361
    if (virConnectDomainEventDeregisterEnsureACL(conn) < 0)
        return -1;

4362 4363 4364 4365
    if (virDomainEventStateDeregister(conn,
                                      driver->domainEventState,
                                      callback) < 0)
        return -1;
4366

4367
    return 0;
4368 4369
}

4370 4371 4372 4373 4374 4375
static int
libxlDomainGetAutostart(virDomainPtr dom, int *autostart)
{
    virDomainObjPtr vm;
    int ret = -1;

J
Jim Fehlig 已提交
4376
    if (!(vm = libxlDomObjFromDomain(dom)))
4377 4378
        goto cleanup;

4379 4380 4381
    if (virDomainGetAutostartEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

4382 4383 4384
    *autostart = vm->autostart;
    ret = 0;

4385
 cleanup:
4386
    virDomainObjEndAPI(&vm);
4387 4388 4389 4390 4391 4392 4393
    return ret;
}

static int
libxlDomainSetAutostart(virDomainPtr dom, int autostart)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
4394
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
4395 4396 4397 4398
    virDomainObjPtr vm;
    char *configFile = NULL, *autostartLink = NULL;
    int ret = -1;

J
Jim Fehlig 已提交
4399
    if (!(vm = libxlDomObjFromDomain(dom)))
4400 4401
        goto cleanup;

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

4404 4405 4406
    if (virDomainSetAutostartEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

4407 4408 4409
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

4410
    if (!vm->persistent) {
4411 4412
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("cannot set autostart for transient domain"));
4413
        goto endjob;
4414 4415 4416 4417 4418
    }

    autostart = (autostart != 0);

    if (vm->autostart != autostart) {
4419
        if (!(configFile = virDomainConfigFile(cfg->configDir, vm->def->name)))
4420
            goto endjob;
4421
        if (!(autostartLink = virDomainConfigFile(cfg->autostartDir, vm->def->name)))
4422
            goto endjob;
4423 4424

        if (autostart) {
4425
            if (virFileMakePath(cfg->autostartDir) < 0) {
4426
                virReportSystemError(errno,
4427
                                     _("cannot create autostart directory %s"),
4428
                                     cfg->autostartDir);
4429
                goto endjob;
4430 4431 4432 4433 4434 4435
            }

            if (symlink(configFile, autostartLink) < 0) {
                virReportSystemError(errno,
                                     _("Failed to create symlink '%s to '%s'"),
                                     autostartLink, configFile);
4436
                goto endjob;
4437 4438 4439 4440 4441 4442
            }
        } else {
            if (unlink(autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) {
                virReportSystemError(errno,
                                     _("Failed to delete symlink '%s'"),
                                     autostartLink);
4443
                goto endjob;
4444 4445 4446 4447 4448 4449 4450
            }
        }

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

4451
 endjob:
W
Wang Yufei 已提交
4452
    libxlDomainObjEndJob(driver, vm);
4453

4454
 cleanup:
4455 4456
    VIR_FREE(configFile);
    VIR_FREE(autostartLink);
W
Wang Yufei 已提交
4457
    virDomainObjEndAPI(&vm);
4458
    virObjectUnref(cfg);
4459 4460 4461
    return ret;
}

4462 4463 4464
static char *
libxlDomainGetSchedulerType(virDomainPtr dom, int *nparams)
{
J
Jim Fehlig 已提交
4465 4466
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
4467 4468
    virDomainObjPtr vm;
    char * ret = NULL;
4469
    const char *name = NULL;
J
Jim Fehlig 已提交
4470
    libxl_scheduler sched_id;
4471

J
Jim Fehlig 已提交
4472
    if (!(vm = libxlDomObjFromDomain(dom)))
4473 4474
        goto cleanup;

4475 4476 4477
    if (virDomainGetSchedulerTypeEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

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

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

4485 4486
    if (nparams)
        *nparams = 0;
4487
    switch ((int)sched_id) {
J
Jim Fehlig 已提交
4488
    case LIBXL_SCHEDULER_SEDF:
4489
        name = "sedf";
4490
        break;
J
Jim Fehlig 已提交
4491
    case LIBXL_SCHEDULER_CREDIT:
4492
        name = "credit";
4493 4494
        if (nparams)
            *nparams = XEN_SCHED_CREDIT_NPARAM;
4495
        break;
J
Jim Fehlig 已提交
4496
    case LIBXL_SCHEDULER_CREDIT2:
4497
        name = "credit2";
4498
        break;
J
Jim Fehlig 已提交
4499
    case LIBXL_SCHEDULER_ARINC653:
4500
        name = "arinc653";
4501 4502
        break;
    default:
J
Jim Fehlig 已提交
4503 4504
        virReportError(VIR_ERR_INTERNAL_ERROR,
                   _("Failed to get scheduler id for domain '%d'"
4505
                     " with libxenlight"), vm->def->id);
4506 4507 4508
        goto cleanup;
    }

4509
    ignore_value(VIR_STRDUP(ret, name));
4510

4511
 cleanup:
4512
    virDomainObjEndAPI(&vm);
J
Jim Fehlig 已提交
4513
    virObjectUnref(cfg);
4514 4515 4516
    return ret;
}

4517
static int
4518 4519 4520 4521
libxlDomainGetSchedulerParametersFlags(virDomainPtr dom,
                                       virTypedParameterPtr params,
                                       int *nparams,
                                       unsigned int flags)
4522
{
J
Jim Fehlig 已提交
4523 4524
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
4525
    virDomainObjPtr vm;
J
Jim Fehlig 已提交
4526 4527
    libxl_domain_sched_params sc_info;
    libxl_scheduler sched_id;
4528 4529
    int ret = -1;

4530 4531 4532 4533
    virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);

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

J
Jim Fehlig 已提交
4535
    if (!(vm = libxlDomObjFromDomain(dom)))
4536 4537
        goto cleanup;

4538 4539 4540
    if (virDomainGetSchedulerParametersFlagsEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

4541
    if (!virDomainObjIsActive(vm)) {
J
Jim Fehlig 已提交
4542 4543
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("Domain is not running"));
4544 4545 4546
        goto cleanup;
    }

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

J
Jim Fehlig 已提交
4549
    if (sched_id != LIBXL_SCHEDULER_CREDIT) {
4550 4551
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Only 'credit' scheduler is supported"));
4552 4553 4554
        goto cleanup;
    }

J
Jim Fehlig 已提交
4555
    if (libxl_domain_sched_params_get(cfg->ctx, vm->def->id, &sc_info) != 0) {
4556 4557
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to get scheduler parameters for domain '%d'"
4558
                         " with libxenlight"), vm->def->id);
4559 4560 4561
        goto cleanup;
    }

4562 4563
    if (virTypedParameterAssign(&params[0], VIR_DOMAIN_SCHEDULER_WEIGHT,
                                VIR_TYPED_PARAM_UINT, sc_info.weight) < 0)
4564 4565
        goto cleanup;

4566
    if (*nparams > 1) {
4567
        if (virTypedParameterAssign(&params[1], VIR_DOMAIN_SCHEDULER_CAP,
4568
                                    VIR_TYPED_PARAM_UINT, sc_info.cap) < 0)
4569
            goto cleanup;
4570 4571
    }

4572 4573
    if (*nparams > XEN_SCHED_CREDIT_NPARAM)
        *nparams = XEN_SCHED_CREDIT_NPARAM;
4574 4575
    ret = 0;

4576
 cleanup:
4577
    virDomainObjEndAPI(&vm);
J
Jim Fehlig 已提交
4578
    virObjectUnref(cfg);
4579 4580 4581 4582
    return ret;
}

static int
4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593
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)
4594
{
4595
    libxlDriverPrivatePtr driver = dom->conn->privateData;
J
Jim Fehlig 已提交
4596
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
4597
    virDomainObjPtr vm;
J
Jim Fehlig 已提交
4598
    libxl_domain_sched_params sc_info;
4599
    int sched_id;
4600
    size_t i;
4601 4602
    int ret = -1;

4603
    virCheckFlags(0, -1);
4604 4605 4606 4607 4608 4609
    if (virTypedParamsValidate(params, nparams,
                               VIR_DOMAIN_SCHEDULER_WEIGHT,
                               VIR_TYPED_PARAM_UINT,
                               VIR_DOMAIN_SCHEDULER_CAP,
                               VIR_TYPED_PARAM_UINT,
                               NULL) < 0)
4610
        return -1;
4611

J
Jim Fehlig 已提交
4612
    if (!(vm = libxlDomObjFromDomain(dom)))
4613 4614
        goto cleanup;

4615 4616 4617
    if (virDomainSetSchedulerParametersFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
        goto cleanup;

4618 4619 4620
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

4621
    if (!virDomainObjIsActive(vm)) {
4622
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
4623
        goto endjob;
4624 4625
    }

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

J
Jim Fehlig 已提交
4628
    if (sched_id != LIBXL_SCHEDULER_CREDIT) {
4629 4630
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Only 'credit' scheduler is supported"));
4631
        goto endjob;
4632 4633
    }

J
Jim Fehlig 已提交
4634
    if (libxl_domain_sched_params_get(cfg->ctx, vm->def->id, &sc_info) != 0) {
4635 4636
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to get scheduler parameters for domain '%d'"
4637
                         " with libxenlight"), vm->def->id);
4638
        goto endjob;
4639 4640 4641
    }

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

4644
        if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_WEIGHT))
4645
            sc_info.weight = params[i].value.ui;
4646
        else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_CAP))
4647 4648 4649
            sc_info.cap = params[i].value.ui;
    }

J
Jim Fehlig 已提交
4650
    if (libxl_domain_sched_params_set(cfg->ctx, vm->def->id, &sc_info) != 0) {
4651 4652
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to set scheduler parameters for domain '%d'"
4653
                         " with libxenlight"), vm->def->id);
4654
        goto endjob;
4655 4656 4657 4658
    }

    ret = 0;

4659
 endjob:
W
Wang Yufei 已提交
4660
    libxlDomainObjEndJob(driver, vm);
4661

4662
 cleanup:
W
Wang Yufei 已提交
4663
    virDomainObjEndAPI(&vm);
J
Jim Fehlig 已提交
4664
    virObjectUnref(cfg);
4665 4666 4667
    return ret;
}

B
Bamvor Jian Zhang 已提交
4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681

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

J
Jim Fehlig 已提交
4682
    if (!(vm = libxlDomObjFromDomain(dom)))
B
Bamvor Jian Zhang 已提交
4683 4684
        goto cleanup;

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

B
Bamvor Jian Zhang 已提交
4687 4688 4689 4690 4691 4692 4693 4694 4695 4696
    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;
B
Bob Liu 已提交
4697 4698
    if (dev_name) {
        size_t i;
B
Bamvor Jian Zhang 已提交
4699

B
Bob Liu 已提交
4700 4701 4702 4703 4704 4705 4706
        for (i = 0; !chr && i < vm->def->nserials; i++) {
            if (STREQ(dev_name, vm->def->serials[i]->info.alias)) {
                chr = vm->def->serials[i];
                break;
            }
        }
    } else if (vm->def->nconsoles) {
I
Ian Campbell 已提交
4707
        chr = vm->def->consoles[0];
4708 4709 4710
        if (chr->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL)
            chr = vm->def->serials[0];
    }
B
Bamvor Jian Zhang 已提交
4711 4712 4713 4714 4715 4716 4717 4718

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

4719
    if (chr->source->type != VIR_DOMAIN_CHR_TYPE_PTY) {
B
Bamvor Jian Zhang 已提交
4720 4721
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("character device %s is not using a PTY"),
4722
                       dev_name ? dev_name : NULLSTR(chr->info.alias));
B
Bamvor Jian Zhang 已提交
4723 4724 4725 4726 4727
        goto cleanup;
    }

    /* handle mutually exclusive access to console devices */
    ret = virChrdevOpen(priv->devs,
4728
                        chr->source,
B
Bamvor Jian Zhang 已提交
4729 4730 4731 4732 4733 4734 4735 4736 4737
                        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;
    }

4738
 cleanup:
4739
    virDomainObjEndAPI(&vm);
B
Bamvor Jian Zhang 已提交
4740 4741 4742
    return ret;
}

4743 4744 4745 4746 4747 4748 4749
static int
libxlDomainSetSchedulerParameters(virDomainPtr dom, virTypedParameterPtr params,
                                  int nparams)
{
    return libxlDomainSetSchedulerParametersFlags(dom, params, nparams, 0);
}

4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762
/* 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 已提交
4763 4764
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780
    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;

4781 4782
    libxl_bitmap_init(&nodemap);

J
Jim Fehlig 已提交
4783
    if (!(vm = libxlDomObjFromDomain(dom)))
4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802
        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];
4803
        int numnodes;
4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821

        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 已提交
4822
            numnodes = libxl_get_max_nodes(cfg->ctx);
4823 4824 4825
            if (numnodes <= 0)
                goto cleanup;

J
Jim Fehlig 已提交
4826
            if (libxl_node_bitmap_alloc(cfg->ctx, &nodemap, 0)) {
4827 4828 4829
                virReportOOMError();
                goto cleanup;
            }
J
Ján Tomko 已提交
4830 4831
            if (!(nodes = virBitmapNew(numnodes)))
                goto cleanup;
4832

J
Jim Fehlig 已提交
4833
            rc = libxl_domain_get_nodeaffinity(cfg->ctx,
4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852
                                               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;
                }
            }

4853
            if (!(nodeset = virBitmapFormat(nodes)))
4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869
                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;

4870
 cleanup:
4871 4872 4873
    VIR_FREE(nodeset);
    virBitmapFree(nodes);
    libxl_bitmap_dispose(&nodemap);
4874
    virDomainObjEndAPI(&vm);
J
Jim Fehlig 已提交
4875
    virObjectUnref(cfg);
4876 4877 4878 4879
    return ret;
}
#endif

J
Jim Fehlig 已提交
4880 4881 4882 4883 4884 4885
static int
libxlDomainIsActive(virDomainPtr dom)
{
    virDomainObjPtr obj;
    int ret = -1;

J
Jim Fehlig 已提交
4886
    if (!(obj = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
4887
        goto cleanup;
4888 4889 4890 4891

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

J
Jim Fehlig 已提交
4892 4893
    ret = virDomainObjIsActive(obj);

4894
 cleanup:
4895
    virDomainObjEndAPI(&obj);
J
Jim Fehlig 已提交
4896 4897 4898 4899 4900 4901 4902 4903 4904
    return ret;
}

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

J
Jim Fehlig 已提交
4905
    if (!(obj = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
4906
        goto cleanup;
4907 4908 4909 4910

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

J
Jim Fehlig 已提交
4911 4912
    ret = obj->persistent;

4913
 cleanup:
4914
    virDomainObjEndAPI(&obj);
J
Jim Fehlig 已提交
4915 4916 4917
    return ret;
}

4918 4919 4920 4921 4922 4923
static int
libxlDomainIsUpdated(virDomainPtr dom)
{
    virDomainObjPtr vm;
    int ret = -1;

J
Jim Fehlig 已提交
4924
    if (!(vm = libxlDomObjFromDomain(dom)))
4925
        goto cleanup;
4926 4927 4928 4929

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

4930 4931
    ret = vm->updated;

4932
 cleanup:
4933
    virDomainObjEndAPI(&vm);
4934 4935 4936
    return ret;
}

4937 4938
static int
libxlDomainInterfaceStats(virDomainPtr dom,
4939
                          const char *device,
4940 4941 4942 4943
                          virDomainInterfaceStatsPtr stats)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    virDomainObjPtr vm;
M
Michal Privoznik 已提交
4944
    virDomainNetDefPtr net = NULL;
4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959 4960 4961
    int ret = -1;

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

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

    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_QUERY) < 0)
        goto cleanup;

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

4962
    if (!(net = virDomainNetFind(vm->def, device)))
M
Michal Privoznik 已提交
4963 4964
        goto endjob;

4965
    if (virNetDevTapInterfaceStats(net->ifname, stats,
4966
                                   !virDomainNetTypeSharesHostView(net)) < 0)
M
Michal Privoznik 已提交
4967 4968 4969
        goto endjob;

    ret = 0;
4970 4971

 endjob:
W
Wang Yufei 已提交
4972
    libxlDomainObjEndJob(driver, vm);
4973 4974

 cleanup:
W
Wang Yufei 已提交
4975
    virDomainObjEndAPI(&vm);
4976 4977 4978
    return ret;
}

4979 4980 4981 4982 4983 4984
static int
libxlDomainGetTotalCPUStats(libxlDriverPrivatePtr driver,
                            virDomainObjPtr vm,
                            virTypedParameterPtr params,
                            unsigned int nparams)
{
J
Jim Fehlig 已提交
4985
    libxlDriverConfigPtr cfg;
4986 4987 4988 4989 4990 4991
    libxl_dominfo d_info;
    int ret = -1;

    if (nparams == 0)
        return LIBXL_NB_TOTAL_CPU_STAT_PARAM;

J
Jim Fehlig 已提交
4992 4993 4994
    libxl_dominfo_init(&d_info);
    cfg = libxlDriverConfigGet(driver);

4995 4996 4997 4998
    if (libxl_domain_info(cfg->ctx, &d_info, vm->def->id) != 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("libxl_domain_info failed for domain '%d'"),
                       vm->def->id);
J
Jim Fehlig 已提交
4999
        goto cleanup;
5000 5001 5002 5003 5004 5005 5006 5007 5008 5009
    }

    if (virTypedParameterAssign(&params[0], VIR_DOMAIN_CPU_STATS_CPUTIME,
                                VIR_TYPED_PARAM_ULLONG, d_info.cpu_time) < 0)
        goto cleanup;

    ret = nparams;

 cleanup:
    libxl_dominfo_dispose(&d_info);
J
Jim Fehlig 已提交
5010
    virObjectUnref(cfg);
5011 5012 5013 5014 5015 5016 5017 5018 5019 5020 5021 5022 5023 5024
    return ret;
}

static int
libxlDomainGetPerCPUStats(libxlDriverPrivatePtr driver,
                          virDomainObjPtr vm,
                          virTypedParameterPtr params,
                          unsigned int nparams,
                          int start_cpu,
                          unsigned int ncpus)
{
    libxl_vcpuinfo *vcpuinfo;
    int maxcpu, hostcpus;
    size_t i;
J
Jim Fehlig 已提交
5025
    libxlDriverConfigPtr cfg;
5026 5027 5028 5029 5030
    int ret = -1;

    if (nparams == 0 && ncpus != 0)
        return LIBXL_NB_TOTAL_CPU_STAT_PARAM;
    else if (nparams == 0)
5031
        return virDomainDefGetVcpusMax(vm->def);
5032

J
Jim Fehlig 已提交
5033
    cfg = libxlDriverConfigGet(driver);
5034 5035 5036 5037 5038
    if ((vcpuinfo = libxl_list_vcpu(cfg->ctx, vm->def->id, &maxcpu,
                                    &hostcpus)) == NULL) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to list vcpus for domain '%d' with libxenlight"),
                       vm->def->id);
J
Jim Fehlig 已提交
5039
        goto cleanup;
5040 5041 5042 5043 5044 5045 5046 5047 5048 5049 5050 5051
    }

    for (i = start_cpu; i < maxcpu && i < ncpus; ++i) {
        if (virTypedParameterAssign(&params[(i-start_cpu)],
                                    VIR_DOMAIN_CPU_STATS_CPUTIME,
                                    VIR_TYPED_PARAM_ULLONG,
                                    vcpuinfo[i].vcpu_time) < 0)
            goto cleanup;
    }
    ret = nparams;

 cleanup:
J
Jim Fehlig 已提交
5052 5053 5054
    if (vcpuinfo)
        libxl_vcpuinfo_list_free(vcpuinfo, maxcpu);
    virObjectUnref(cfg);
5055 5056 5057 5058 5059 5060 5061 5062 5063 5064 5065 5066 5067 5068 5069 5070 5071 5072 5073 5074 5075 5076 5077 5078 5079 5080 5081 5082 5083 5084 5085 5086 5087 5088 5089 5090
    return ret;
}

static int
libxlDomainGetCPUStats(virDomainPtr dom,
                       virTypedParameterPtr params,
                       unsigned int nparams,
                       int start_cpu,
                       unsigned int ncpus,
                       unsigned int flags)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    virDomainObjPtr vm = NULL;
    int ret = -1;

    virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);

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

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

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

    if (start_cpu == -1)
        ret = libxlDomainGetTotalCPUStats(driver, vm, params, nparams);
    else
        ret = libxlDomainGetPerCPUStats(driver, vm, params, nparams,
                                          start_cpu, ncpus);

 cleanup:
5091
    virDomainObjEndAPI(&vm);
5092 5093 5094
    return ret;
}

5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108
#define LIBXL_SET_MEMSTAT(TAG, VAL) \
        if (i < nr_stats) { \
            stats[i].tag = TAG; \
            stats[i].val = VAL; \
            i++; \
        }

static int
libxlDomainMemoryStats(virDomainPtr dom,
                       virDomainMemoryStatPtr stats,
                       unsigned int nr_stats,
                       unsigned int flags)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
J
Jim Fehlig 已提交
5109
    libxlDriverConfigPtr cfg;
5110 5111 5112 5113 5114 5115 5116 5117
    virDomainObjPtr vm;
    libxl_dominfo d_info;
    unsigned mem, maxmem;
    size_t i = 0;
    int ret = -1;

    virCheckFlags(0, -1);

5118
    libxl_dominfo_init(&d_info);
J
Jim Fehlig 已提交
5119 5120
    cfg = libxlDriverConfigGet(driver);

5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142
    if (!(vm = libxlDomObjFromDomain(dom)))
        goto cleanup;

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

    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_QUERY) < 0)
        goto cleanup;

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

    if (libxl_domain_info(cfg->ctx, &d_info, vm->def->id) != 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("libxl_domain_info failed for domain '%d'"),
                       vm->def->id);
        goto endjob;
    }
    mem = d_info.current_memkb;
5143
    maxmem = virDomainDefGetMemoryTotal(vm->def);
5144 5145 5146 5147 5148 5149 5150

    LIBXL_SET_MEMSTAT(VIR_DOMAIN_MEMORY_STAT_ACTUAL_BALLOON, mem);
    LIBXL_SET_MEMSTAT(VIR_DOMAIN_MEMORY_STAT_AVAILABLE, maxmem);

    ret = i;

 endjob:
W
Wang Yufei 已提交
5151
    libxlDomainObjEndJob(driver, vm);
5152 5153

 cleanup:
5154
    libxl_dominfo_dispose(&d_info);
W
Wang Yufei 已提交
5155
    virDomainObjEndAPI(&vm);
J
Jim Fehlig 已提交
5156
    virObjectUnref(cfg);
5157 5158 5159 5160 5161
    return ret;
}

#undef LIBXL_SET_MEMSTAT

5162 5163 5164 5165 5166 5167 5168 5169 5170 5171 5172 5173 5174 5175 5176 5177 5178 5179 5180 5181 5182 5183 5184 5185 5186 5187 5188 5189 5190 5191 5192 5193
static int
libxlDomainGetJobInfo(virDomainPtr dom,
                      virDomainJobInfoPtr info)
{
    libxlDomainObjPrivatePtr priv;
    virDomainObjPtr vm;
    int ret = -1;

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

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

    priv = vm->privateData;
    if (!priv->job.active) {
        memset(info, 0, sizeof(*info));
        info->type = VIR_DOMAIN_JOB_NONE;
        ret = 0;
        goto cleanup;
    }

    /* In libxl we don't have an estimated completion time
     * thus we always set to unbounded and update time
     * for the active job. */
    if (libxlDomainJobUpdateTime(&priv->job) < 0)
        goto cleanup;

    memcpy(info, priv->job.current, sizeof(virDomainJobInfo));
    ret = 0;

 cleanup:
5194
    virDomainObjEndAPI(&vm);
5195 5196 5197
    return ret;
}

5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 5232 5233 5234 5235 5236 5237 5238 5239 5240 5241 5242 5243 5244
static int
libxlDomainGetJobStats(virDomainPtr dom,
                       int *type,
                       virTypedParameterPtr *params,
                       int *nparams,
                       unsigned int flags)
{
    libxlDomainObjPrivatePtr priv;
    virDomainObjPtr vm;
    virDomainJobInfoPtr jobInfo;
    int ret = -1;
    int maxparams = 0;

    /* VIR_DOMAIN_JOB_STATS_COMPLETED not supported yet */
    virCheckFlags(0, -1);

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

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

    priv = vm->privateData;
    jobInfo = priv->job.current;
    if (!priv->job.active) {
        *type = VIR_DOMAIN_JOB_NONE;
        *params = NULL;
        *nparams = 0;
        ret = 0;
        goto cleanup;
    }

    /* In libxl we don't have an estimated completion time
     * thus we always set to unbounded and update time
     * for the active job. */
    if (libxlDomainJobUpdateTime(&priv->job) < 0)
        goto cleanup;

    if (virTypedParamsAddULLong(params, nparams, &maxparams,
                                VIR_DOMAIN_JOB_TIME_ELAPSED,
                                jobInfo->timeElapsed) < 0)
        goto cleanup;

    *type = jobInfo->type;
    ret = 0;

 cleanup:
5245
    virDomainObjEndAPI(&vm);
5246 5247
    return ret;
}
5248

R
Roman Bogorodskiy 已提交
5249
#ifdef __linux__
5250 5251 5252 5253 5254 5255 5256 5257 5258 5259 5260 5261 5262 5263 5264 5265 5266 5267 5268 5269 5270 5271 5272 5273 5274 5275 5276 5277 5278 5279 5280 5281 5282 5283 5284 5285 5286 5287 5288 5289 5290 5291 5292 5293 5294 5295 5296
static int
libxlDiskPathToID(const char *virtpath)
{
    static char const* drive_prefix[] = {"xvd", "hd", "sd"};
    int disk, partition, chrused;
    int fmt, id;
    size_t i;

    fmt = id = -1;

    /* Find any disk prefixes we know about */
    for (i = 0; i < ARRAY_CARDINALITY(drive_prefix); i++) {
        if (STRPREFIX(virtpath, drive_prefix[i]) &&
            !virDiskNameParse(virtpath, &disk, &partition)) {
            fmt = i;
            break;
        }
    }

    /* Handle it same way as xvd */
    if (fmt < 0 &&
        (sscanf(virtpath, "d%ip%i%n", &disk, &partition, &chrused) >= 2
         && chrused == strlen(virtpath)))
        fmt = 0;

    /* Test indexes ranges and calculate the device id */
    switch (fmt) {
    case 0: /* xvd */
        if (disk <= 15 && partition <= 15)
            id = (202 << 8) | (disk << 4) | partition;
        else if ((disk <= ((1<<20)-1)) || partition <= 255)
            id = (1 << 28) | (disk << 8) | partition;
        break;
    case 1: /* hd */
        if (disk <= 3 && partition <= 63)
            id = ((disk < 2 ? 3 : 22) << 8) | ((disk & 1) << 6) | partition;
        break;
    case 2: /* sd */
        if (disk <= 15 && (partition <= 15))
            id = (8 << 8) | (disk << 4) | partition;
        break;
    default: /* invalid */
        break;
    }
    return id;
}

5297
# define LIBXL_VBD_SECTOR_SIZE 512
5298 5299 5300 5301 5302 5303 5304 5305 5306 5307 5308 5309 5310 5311 5312 5313 5314 5315 5316 5317 5318 5319 5320 5321 5322 5323 5324 5325 5326 5327 5328 5329 5330 5331 5332 5333 5334 5335 5336 5337 5338 5339 5340 5341 5342 5343 5344 5345 5346 5347

static int
libxlDiskSectorSize(int domid, int devno)
{
    char *path, *val;
    struct xs_handle *handle;
    int ret = LIBXL_VBD_SECTOR_SIZE;
    unsigned int len;

    handle = xs_daemon_open_readonly();
    if (!handle) {
        VIR_WARN("cannot read sector size");
        return ret;
    }

    path = val = NULL;
    if (virAsprintf(&path, "/local/domain/%d/device/vbd/%d/backend",
                    domid, devno) < 0)
        goto cleanup;

    if ((val = xs_read(handle, XBT_NULL, path, &len)) == NULL)
        goto cleanup;

    VIR_FREE(path);
    if (virAsprintf(&path, "%s/physical-sector-size", val) < 0)
        goto cleanup;

    VIR_FREE(val);
    if ((val = xs_read(handle, XBT_NULL, path, &len)) == NULL)
        goto cleanup;

    if (sscanf(val, "%d", &ret) != 1)
        ret = LIBXL_VBD_SECTOR_SIZE;

 cleanup:
    VIR_FREE(val);
    VIR_FREE(path);
    xs_daemon_close(handle);
    return ret;
}

static int
libxlDomainBlockStatsVBD(virDomainObjPtr vm,
                         const char *dev,
                         libxlBlockStatsPtr stats)
{
    int ret = -1;
    int devno = libxlDiskPathToID(dev);
    int size;
    char *path, *name, *val;
5348
    unsigned long long status;
5349 5350 5351 5352 5353 5354 5355 5356 5357 5358 5359 5360 5361 5362 5363 5364 5365 5366 5367 5368 5369 5370 5371

    path = name = val = NULL;
    if (devno < 0) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("cannot find device number"));
        return ret;
    }

    size = libxlDiskSectorSize(vm->def->id, devno);

    if (VIR_STRDUP(stats->backend, "vbd") < 0)
        return ret;

    if (virAsprintf(&path, "/sys/bus/xen-backend/devices/vbd-%d-%d/statistics",
                    vm->def->id, devno) < 0)
        return ret;

    if (!virFileExists(path)) {
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("cannot open bus path"));
        goto cleanup;
    }

5372
# define LIBXL_SET_VBDSTAT(FIELD, VAR, MUL) \
5373
    if ((virAsprintf(&name, "%s/"FIELD, path) < 0) || \
5374 5375 5376 5377 5378 5379 5380 5381
        (virFileReadAll(name, 256, &val) < 0) || \
        (sscanf(val, "%llu", &status) != 1)) { \
        virReportError(VIR_ERR_OPERATION_FAILED, \
                       _("cannot read %s"), name); \
        goto cleanup; \
    } \
    VAR += (status * MUL); \
    VIR_FREE(name); \
5382 5383 5384 5385 5386 5387 5388 5389 5390 5391 5392 5393 5394 5395 5396 5397 5398 5399 5400 5401 5402 5403 5404 5405 5406 5407 5408 5409 5410 5411 5412 5413 5414 5415 5416 5417 5418 5419 5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 5431 5432 5433 5434
    VIR_FREE(val);

    LIBXL_SET_VBDSTAT("f_req",  stats->f_req,  1)
    LIBXL_SET_VBDSTAT("wr_req", stats->wr_req, 1)
    LIBXL_SET_VBDSTAT("rd_req", stats->rd_req, 1)
    LIBXL_SET_VBDSTAT("wr_sect", stats->wr_bytes, size)
    LIBXL_SET_VBDSTAT("rd_sect", stats->rd_bytes, size)

    LIBXL_SET_VBDSTAT("ds_req", stats->u.vbd.ds_req, size)
    LIBXL_SET_VBDSTAT("oo_req", stats->u.vbd.oo_req, 1)
    ret = 0;

 cleanup:
    VIR_FREE(name);
    VIR_FREE(path);
    VIR_FREE(val);

# undef LIBXL_SET_VBDSTAT

    return ret;
}
#else
static int
libxlDomainBlockStatsVBD(virDomainObjPtr vm ATTRIBUTE_UNUSED,
                         const char *dev ATTRIBUTE_UNUSED,
                         libxlBlockStatsPtr stats ATTRIBUTE_UNUSED)
{
    virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
                   "%s", _("platform unsupported"));
    return -1;
}
#endif

static int
libxlDomainBlockStatsGatherSingle(virDomainObjPtr vm,
                                  const char *path,
                                  libxlBlockStatsPtr stats)
{
    virDomainDiskDefPtr disk;
    const char *disk_drv;
    int ret = -1, disk_fmt;

    if (!(disk = virDomainDiskByName(vm->def, path, false))) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("invalid path: %s"), path);
        return ret;
    }

    disk_fmt = virDomainDiskGetFormat(disk);
    if (!(disk_drv = virDomainDiskGetDriver(disk)))
        disk_drv = "qemu";

    if (STREQ(disk_drv, "phy")) {
5435
        if (disk_fmt != VIR_STORAGE_FILE_RAW) {
5436 5437 5438 5439 5440 5441 5442 5443 5444 5445 5446 5447 5448 5449 5450 5451 5452 5453 5454 5455 5456 5457 5458 5459 5460 5461 5462 5463 5464 5465 5466 5467 5468 5469 5470 5471 5472 5473 5474 5475 5476 5477 5478 5479 5480 5481 5482 5483 5484 5485 5486 5487 5488 5489 5490 5491 5492 5493 5494 5495 5496 5497 5498 5499 5500 5501 5502 5503 5504 5505 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517 5518 5519 5520 5521 5522 5523 5524 5525 5526 5527 5528 5529 5530 5531 5532 5533 5534 5535 5536 5537 5538 5539 5540 5541 5542 5543 5544 5545 5546 5547 5548 5549 5550 5551 5552 5553 5554 5555 5556 5557 5558 5559 5560 5561 5562 5563
            virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
                           _("unsupported format %s"),
                           virStorageFileFormatTypeToString(disk_fmt));
            return ret;
        }

        ret = libxlDomainBlockStatsVBD(vm, disk->dst, stats);
    } else {
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
                       _("unsupported disk driver %s"),
                       disk_drv);
    }
    return ret;
}

static int
libxlDomainBlockStatsGather(virDomainObjPtr vm,
                            const char *path,
                            libxlBlockStatsPtr stats)
{
    int ret = -1;

    if (*path) {
        if (libxlDomainBlockStatsGatherSingle(vm, path, stats) < 0)
            return ret;
    } else {
        size_t i;

        for (i = 0; i < vm->def->ndisks; ++i) {
            if (libxlDomainBlockStatsGatherSingle(vm, vm->def->disks[i]->dst,
                                                  stats) < 0)
                return ret;
        }
    }
    return 0;
}

static int
libxlDomainBlockStats(virDomainPtr dom,
                      const char *path,
                      virDomainBlockStatsPtr stats)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    virDomainObjPtr vm;
    libxlBlockStats blkstats;
    int ret = -1;

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

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

    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_QUERY) < 0)
        goto cleanup;

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

    memset(&blkstats, 0, sizeof(libxlBlockStats));
    if ((ret = libxlDomainBlockStatsGather(vm, path, &blkstats)) < 0)
        goto endjob;

    stats->rd_req = blkstats.rd_req;
    stats->rd_bytes = blkstats.rd_bytes;
    stats->wr_req = blkstats.wr_req;
    stats->wr_bytes = blkstats.wr_bytes;
    if (STREQ_NULLABLE(blkstats.backend, "vbd"))
        stats->errs = blkstats.u.vbd.oo_req;
    else
        stats->errs = -1;

 endjob:
    libxlDomainObjEndJob(driver, vm);

 cleanup:
    virDomainObjEndAPI(&vm);
    return ret;
}

static int
libxlDomainBlockStatsFlags(virDomainPtr dom,
                           const char *path,
                           virTypedParameterPtr params,
                           int *nparams,
                           unsigned int flags)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    virDomainObjPtr vm;
    libxlBlockStats blkstats;
    int nstats;
    int ret = -1;

    virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);

    flags &= ~VIR_TYPED_PARAM_STRING_OKAY;

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

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

    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_QUERY) < 0)
        goto cleanup;

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

    /* return count of supported stats */
    if (*nparams == 0) {
        *nparams = LIBXL_NB_TOTAL_BLK_STAT_PARAM;
        ret = 0;
        goto endjob;
    }

    memset(&blkstats, 0, sizeof(libxlBlockStats));
    if ((ret = libxlDomainBlockStatsGather(vm, path, &blkstats)) < 0)
        goto endjob;

    nstats = 0;

5564 5565 5566
#define LIBXL_BLKSTAT_ASSIGN_PARAM(VAR, NAME) \
    if (nstats < *nparams && (blkstats.VAR) != -1) { \
        if (virTypedParameterAssign(params + nstats, NAME, \
5567
                                    VIR_TYPED_PARAM_LLONG, (blkstats.VAR)) < 0) \
5568 5569
            goto endjob; \
        nstats++; \
5570 5571 5572 5573 5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 5585 5586 5587 5588 5589 5590 5591 5592 5593 5594
    }

    LIBXL_BLKSTAT_ASSIGN_PARAM(wr_bytes, VIR_DOMAIN_BLOCK_STATS_WRITE_BYTES);
    LIBXL_BLKSTAT_ASSIGN_PARAM(wr_req, VIR_DOMAIN_BLOCK_STATS_WRITE_REQ);

    LIBXL_BLKSTAT_ASSIGN_PARAM(rd_bytes, VIR_DOMAIN_BLOCK_STATS_READ_BYTES);
    LIBXL_BLKSTAT_ASSIGN_PARAM(rd_req, VIR_DOMAIN_BLOCK_STATS_READ_REQ);

    LIBXL_BLKSTAT_ASSIGN_PARAM(f_req, VIR_DOMAIN_BLOCK_STATS_FLUSH_REQ);

    if (STREQ_NULLABLE(blkstats.backend, "vbd"))
        LIBXL_BLKSTAT_ASSIGN_PARAM(u.vbd.oo_req, VIR_DOMAIN_BLOCK_STATS_ERRS);

    *nparams = nstats;

#undef LIBXL_BLKSTAT_ASSIGN_PARAM

 endjob:
    libxlDomainObjEndJob(driver, vm);

 cleanup:
    virDomainObjEndAPI(&vm);
    return ret;
}

5595
static int
5596 5597 5598
libxlConnectDomainEventRegisterAny(virConnectPtr conn, virDomainPtr dom, int eventID,
                                   virConnectDomainEventGenericCallback callback,
                                   void *opaque, virFreeCallback freecb)
5599 5600 5601 5602
{
    libxlDriverPrivatePtr driver = conn->privateData;
    int ret;

5603 5604 5605
    if (virConnectDomainEventRegisterAnyEnsureACL(conn) < 0)
        return -1;

5606 5607 5608 5609
    if (virDomainEventStateRegisterID(conn,
                                      driver->domainEventState,
                                      dom, eventID, callback, opaque,
                                      freecb, &ret) < 0)
5610
        ret = -1;
5611 5612 5613 5614 5615 5616

    return ret;
}


static int
5617
libxlConnectDomainEventDeregisterAny(virConnectPtr conn, int callbackID)
5618 5619 5620
{
    libxlDriverPrivatePtr driver = conn->privateData;

5621 5622 5623
    if (virConnectDomainEventDeregisterAnyEnsureACL(conn) < 0)
        return -1;

5624 5625
    if (virObjectEventStateDeregisterID(conn,
                                        driver->domainEventState,
5626
                                        callbackID, true) < 0)
5627
        return -1;
5628

5629
    return 0;
5630 5631
}

J
Jim Fehlig 已提交
5632

5633
static int
5634
libxlConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED)
5635 5636 5637 5638
{
    return 1;
}

5639
static int
5640 5641 5642
libxlConnectListAllDomains(virConnectPtr conn,
                           virDomainPtr **domains,
                           unsigned int flags)
5643 5644 5645 5646
{
    libxlDriverPrivatePtr driver = conn->privateData;
    int ret = -1;

O
Osier Yang 已提交
5647
    virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
5648

5649 5650 5651
    if (virConnectListAllDomainsEnsureACL(conn) < 0)
        return -1;

5652 5653
    ret = virDomainObjListExport(driver->domains, conn, domains,
                                 virConnectListAllDomainsCheckACL, flags);
5654 5655 5656 5657

    return ret;
}

5658 5659 5660 5661 5662 5663 5664
/* Which features are supported by this driver? */
static int
libxlConnectSupportsFeature(virConnectPtr conn, int feature)
{
    if (virConnectSupportsFeatureEnsureACL(conn) < 0)
        return -1;

5665
    switch ((virDrvFeature) feature) {
5666
    case VIR_DRV_FEATURE_MIGRATION_V3:
5667
    case VIR_DRV_FEATURE_TYPED_PARAM_STRING:
J
Jim Fehlig 已提交
5668
    case VIR_DRV_FEATURE_MIGRATION_PARAMS:
J
Joao Martins 已提交
5669
    case VIR_DRV_FEATURE_MIGRATION_P2P:
5670
        return 1;
5671 5672 5673 5674 5675 5676 5677 5678 5679 5680 5681
    case VIR_DRV_FEATURE_FD_PASSING:
    case VIR_DRV_FEATURE_MIGRATE_CHANGE_PROTECTION:
    case VIR_DRV_FEATURE_MIGRATION_DIRECT:
    case VIR_DRV_FEATURE_MIGRATION_OFFLINE:
    case VIR_DRV_FEATURE_MIGRATION_V1:
    case VIR_DRV_FEATURE_MIGRATION_V2:
    case VIR_DRV_FEATURE_PROGRAM_KEEPALIVE:
    case VIR_DRV_FEATURE_REMOTE:
    case VIR_DRV_FEATURE_REMOTE_CLOSE_CALLBACK:
    case VIR_DRV_FEATURE_REMOTE_EVENT_CALLBACK:
    case VIR_DRV_FEATURE_XML_MIGRATABLE:
5682 5683 5684 5685
    default:
        return 0;
    }
}
5686

5687 5688 5689 5690 5691 5692 5693 5694 5695 5696 5697
static int
libxlNodeDeviceGetPCIInfo(virNodeDeviceDefPtr def,
                          unsigned *domain,
                          unsigned *bus,
                          unsigned *slot,
                          unsigned *function)
{
    virNodeDevCapsDefPtr cap;

    cap = def->caps;
    while (cap) {
5698
        if (cap->data.type == VIR_NODE_DEV_CAP_PCI_DEV) {
5699 5700 5701 5702 5703 5704 5705 5706 5707 5708 5709 5710 5711
            *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 已提交
5712
        return -1;
5713 5714
    }

C
Chunyan Liu 已提交
5715
    return 0;
5716 5717 5718 5719 5720 5721 5722 5723 5724 5725 5726 5727 5728 5729 5730 5731 5732 5733 5734 5735 5736 5737 5738 5739 5740 5741 5742 5743 5744 5745 5746 5747 5748 5749 5750 5751
}

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")) {
5752
        virPCIDeviceSetStubDriver(pci, VIR_PCI_STUB_DRIVER_XEN);
5753 5754 5755 5756 5757 5758 5759 5760 5761 5762
    } else {
        virReportError(VIR_ERR_INVALID_ARG,
                       _("unsupported driver name '%s'"), driverName);
        goto cleanup;
    }

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

    ret = 0;
5763
 cleanup:
5764 5765 5766 5767 5768 5769 5770 5771 5772 5773 5774 5775 5776 5777 5778 5779 5780 5781 5782 5783 5784 5785 5786 5787 5788 5789 5790 5791 5792 5793 5794 5795 5796 5797 5798 5799 5800 5801 5802 5803 5804 5805
    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 已提交
5806
        goto cleanup;
5807 5808

    ret = 0;
C
Chunyan Liu 已提交
5809

5810
 cleanup:
C
Chunyan Liu 已提交
5811
    virPCIDeviceFree(pci);
5812 5813 5814 5815 5816 5817 5818 5819
    virNodeDeviceDefFree(def);
    VIR_FREE(xml);
    return ret;
}

static int
libxlNodeDeviceReset(virNodeDevicePtr dev)
{
C
Chunyan Liu 已提交
5820
    virPCIDevicePtr pci = NULL;
5821 5822 5823 5824 5825 5826 5827 5828 5829 5830 5831 5832 5833 5834 5835 5836 5837 5838 5839 5840 5841 5842 5843 5844 5845 5846
    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 已提交
5847
        goto cleanup;
5848 5849

    ret = 0;
C
Chunyan Liu 已提交
5850

5851
 cleanup:
C
Chunyan Liu 已提交
5852
    virPCIDeviceFree(pci);
5853 5854 5855 5856 5857
    virNodeDeviceDefFree(def);
    VIR_FREE(xml);
    return ret;
}

J
Jim Fehlig 已提交
5858 5859 5860 5861
static char *
libxlDomainMigrateBegin3Params(virDomainPtr domain,
                               virTypedParameterPtr params,
                               int nparams,
5862 5863
                               char **cookieout,
                               int *cookieoutlen,
J
Jim Fehlig 已提交
5864 5865 5866 5867
                               unsigned int flags)
{
    const char *xmlin = NULL;
    virDomainObjPtr vm = NULL;
5868
    char *xmlout = NULL;
J
Jim Fehlig 已提交
5869

5870 5871 5872 5873 5874
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
    virReportUnsupportedError();
    return NULL;
#endif

J
Jim Fehlig 已提交
5875 5876 5877 5878 5879 5880 5881 5882 5883 5884 5885 5886
    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 已提交
5887
    if (STREQ_NULLABLE(vm->def->name, "Domain-0")) {
5888 5889 5890
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("Domain-0 cannot be migrated"));
        goto cleanup;
J
Jim Fehlig 已提交
5891 5892
    }

5893 5894
    if (virDomainMigrateBegin3ParamsEnsureACL(domain->conn, vm->def) < 0)
        goto cleanup;
J
Jim Fehlig 已提交
5895 5896 5897 5898

    if (!virDomainObjIsActive(vm)) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("domain is not running"));
5899
        goto cleanup;
J
Jim Fehlig 已提交
5900 5901
    }

5902 5903
    xmlout = libxlDomainMigrationSrcBegin(domain->conn, vm, xmlin,
                                          cookieout, cookieoutlen);
5904 5905 5906 5907

 cleanup:
    virDomainObjEndAPI(&vm);
    return xmlout;
J
Jim Fehlig 已提交
5908 5909
}

B
Bob Liu 已提交
5910 5911 5912 5913 5914 5915 5916 5917 5918 5919 5920 5921 5922 5923 5924 5925 5926 5927 5928 5929 5930 5931 5932 5933 5934 5935 5936 5937 5938 5939 5940 5941 5942 5943 5944 5945 5946 5947
static int
libxlDomainMigratePrepareTunnel3Params(virConnectPtr dconn,
                                       virStreamPtr st,
                                       virTypedParameterPtr params,
                                       int nparams,
                                       const char *cookiein,
                                       int cookieinlen,
                                       char **cookieout ATTRIBUTE_UNUSED,
                                       int *cookieoutlen ATTRIBUTE_UNUSED,
                                       unsigned int flags)
{
    libxlDriverPrivatePtr driver = dconn->privateData;
    virDomainDefPtr def = NULL;
    const char *dom_xml = NULL;
    const char *dname = NULL;
    const char *uri_in = NULL;

#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
    virReportUnsupportedError();
    return -1;
#endif

    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;

5948
    if (!(def = libxlDomainMigrationDstPrepareDef(driver, dom_xml, dname)))
B
Bob Liu 已提交
5949 5950 5951 5952 5953
        goto error;

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

5954 5955
    if (libxlDomainMigrationDstPrepareTunnel3(dconn, st, &def, cookiein,
                                              cookieinlen, flags) < 0)
B
Bob Liu 已提交
5956 5957 5958 5959 5960 5961 5962 5963 5964
        goto error;

    return 0;

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

J
Jim Fehlig 已提交
5965 5966 5967 5968
static int
libxlDomainMigratePrepare3Params(virConnectPtr dconn,
                                 virTypedParameterPtr params,
                                 int nparams,
5969 5970
                                 const char *cookiein,
                                 int cookieinlen,
J
Jim Fehlig 已提交
5971 5972 5973 5974 5975 5976 5977 5978 5979 5980 5981
                                 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;

5982 5983 5984 5985 5986
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
    virReportUnsupportedError();
    return -1;
#endif

J
Jim Fehlig 已提交
5987 5988 5989 5990 5991 5992 5993 5994 5995 5996 5997 5998 5999 6000 6001 6002
    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;

6003
    if (!(def = libxlDomainMigrationDstPrepareDef(driver, dom_xml, dname)))
J
Jim Fehlig 已提交
6004 6005 6006 6007 6008
        goto error;

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

6009 6010
    if (libxlDomainMigrationDstPrepare(dconn, &def, uri_in, uri_out,
                                       cookiein, cookieinlen, flags) < 0)
J
Jim Fehlig 已提交
6011 6012 6013 6014 6015 6016 6017 6018 6019 6020 6021 6022 6023 6024 6025 6026 6027 6028 6029 6030 6031 6032 6033 6034 6035 6036 6037
        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;

6038 6039 6040 6041 6042
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
    virReportUnsupportedError();
    return -1;
#endif

J
Jim Fehlig 已提交
6043 6044 6045 6046 6047 6048 6049 6050 6051 6052 6053 6054 6055 6056 6057 6058 6059 6060 6061 6062 6063 6064
    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;

B
Bob Liu 已提交
6065
    if ((flags & (VIR_MIGRATE_TUNNELLED | VIR_MIGRATE_PEER2PEER))) {
6066 6067
        if (libxlDomainMigrationSrcPerformP2P(driver, vm, dom->conn, dom_xml,
                                              dconnuri, uri, dname, flags) < 0)
J
Joao Martins 已提交
6068 6069
            goto cleanup;
    } else {
6070 6071
        if (libxlDomainMigrationSrcPerform(driver, vm, dom_xml, dconnuri,
                                           uri, dname, flags) < 0)
J
Joao Martins 已提交
6072 6073
            goto cleanup;
    }
J
Jim Fehlig 已提交
6074 6075 6076 6077

    ret = 0;

 cleanup:
6078
    virDomainObjEndAPI(&vm);
J
Jim Fehlig 已提交
6079 6080 6081 6082 6083 6084 6085 6086 6087 6088 6089 6090 6091 6092 6093 6094 6095
    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;
6096
    virDomainPtr ret = NULL;
J
Jim Fehlig 已提交
6097

6098 6099 6100 6101 6102
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
    virReportUnsupportedError();
    return NULL;
#endif

J
Jim Fehlig 已提交
6103 6104 6105 6106 6107 6108 6109 6110 6111 6112 6113 6114 6115 6116 6117 6118 6119 6120 6121 6122
    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) {
6123
        virDomainObjEndAPI(&vm);
J
Jim Fehlig 已提交
6124 6125 6126
        return NULL;
    }

6127
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0) {
6128
        virDomainObjEndAPI(&vm);
6129 6130 6131
        return NULL;
    }

6132
    ret = libxlDomainMigrationDstFinish(dconn, vm, flags, cancelled);
6133

W
Wang Yufei 已提交
6134
    libxlDomainObjEndJob(driver, vm);
6135

6136
    virDomainObjEndAPI(&vm);
6137 6138

    return ret;
J
Jim Fehlig 已提交
6139 6140 6141 6142 6143 6144 6145 6146 6147 6148 6149 6150 6151
}

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;
6152
    int ret = -1;
J
Jim Fehlig 已提交
6153

6154 6155 6156 6157 6158
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
    virReportUnsupportedError();
    return -1;
#endif

J
Jim Fehlig 已提交
6159 6160 6161 6162 6163 6164 6165
    virCheckFlags(LIBXL_MIGRATION_FLAGS, -1);
    if (virTypedParamsValidate(params, nparams, LIBXL_MIGRATION_PARAMETERS) < 0)
        return -1;

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

6166 6167
    if (virDomainMigrateConfirm3ParamsEnsureACL(domain->conn, vm->def) < 0)
        goto cleanup;
J
Jim Fehlig 已提交
6168

6169
    ret = libxlDomainMigrationSrcConfirm(driver, vm, flags, cancelled);
6170 6171 6172 6173

 cleanup:
    virDomainObjEndAPI(&vm);
    return ret;
J
Jim Fehlig 已提交
6174 6175
}

6176 6177 6178 6179 6180 6181 6182 6183 6184 6185 6186 6187 6188 6189 6190 6191 6192
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;
}
6193

6194 6195 6196 6197 6198 6199 6200 6201 6202 6203 6204 6205 6206 6207 6208 6209 6210 6211 6212 6213 6214 6215 6216 6217 6218 6219 6220 6221 6222 6223 6224 6225 6226 6227 6228 6229 6230 6231 6232 6233 6234 6235 6236 6237 6238 6239 6240 6241 6242 6243 6244 6245 6246 6247 6248 6249 6250 6251 6252 6253 6254 6255 6256 6257 6258 6259 6260 6261 6262 6263 6264 6265 6266 6267 6268 6269 6270 6271 6272 6273 6274 6275 6276 6277 6278 6279 6280 6281 6282 6283 6284 6285 6286 6287 6288 6289 6290 6291 6292 6293 6294 6295 6296 6297 6298 6299 6300 6301 6302 6303 6304 6305 6306 6307 6308 6309 6310 6311 6312 6313 6314 6315 6316 6317 6318 6319 6320 6321 6322 6323 6324 6325 6326 6327 6328 6329 6330 6331 6332
static int
libxlGetDHCPInterfaces(virDomainPtr dom,
                       virDomainObjPtr vm,
                       virDomainInterfacePtr **ifaces)
{
    int rv = -1;
    int n_leases = 0;
    size_t i, j;
    size_t ifaces_count = 0;
    virNetworkPtr network = NULL;
    char macaddr[VIR_MAC_STRING_BUFLEN];
    virDomainInterfacePtr iface = NULL;
    virNetworkDHCPLeasePtr *leases = NULL;
    virDomainInterfacePtr *ifaces_ret = NULL;

    if (!dom->conn->networkDriver ||
        !dom->conn->networkDriver->networkGetDHCPLeases) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Network driver does not support DHCP lease query"));
        return -1;
    }

    for (i = 0; i < vm->def->nnets; i++) {
        if (vm->def->nets[i]->type != VIR_DOMAIN_NET_TYPE_NETWORK)
            continue;

        virMacAddrFormat(&(vm->def->nets[i]->mac), macaddr);
        virObjectUnref(network);
        network = virNetworkLookupByName(dom->conn,
                                         vm->def->nets[i]->data.network.name);

        if ((n_leases = virNetworkGetDHCPLeases(network, macaddr,
                                                &leases, 0)) < 0)
            goto error;

        if (n_leases) {
            if (VIR_EXPAND_N(ifaces_ret, ifaces_count, 1) < 0)
                goto error;

            if (VIR_ALLOC(ifaces_ret[ifaces_count - 1]) < 0)
                goto error;

            iface = ifaces_ret[ifaces_count - 1];
            /* Assuming each lease corresponds to a separate IP */
            iface->naddrs = n_leases;

            if (VIR_ALLOC_N(iface->addrs, iface->naddrs) < 0)
                goto error;

            if (VIR_STRDUP(iface->name, vm->def->nets[i]->ifname) < 0)
                goto cleanup;

            if (VIR_STRDUP(iface->hwaddr, macaddr) < 0)
                goto cleanup;
        }

        for (j = 0; j < n_leases; j++) {
            virNetworkDHCPLeasePtr lease = leases[j];
            virDomainIPAddressPtr ip_addr = &iface->addrs[j];

            if (VIR_STRDUP(ip_addr->addr, lease->ipaddr) < 0)
                goto cleanup;

            ip_addr->type = lease->type;
            ip_addr->prefix = lease->prefix;
        }

        for (j = 0; j < n_leases; j++)
            virNetworkDHCPLeaseFree(leases[j]);

        VIR_FREE(leases);
    }

    *ifaces = ifaces_ret;
    ifaces_ret = NULL;
    rv = ifaces_count;

 cleanup:
    virObjectUnref(network);
    if (leases) {
        for (i = 0; i < n_leases; i++)
            virNetworkDHCPLeaseFree(leases[i]);
    }
    VIR_FREE(leases);

    return rv;

 error:
    if (ifaces_ret) {
        for (i = 0; i < ifaces_count; i++)
            virDomainInterfaceFree(ifaces_ret[i]);
    }
    VIR_FREE(ifaces_ret);

    goto cleanup;
}


static int
libxlDomainInterfaceAddresses(virDomainPtr dom,
                              virDomainInterfacePtr **ifaces,
                              unsigned int source,
                              unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    int ret = -1;

    virCheckFlags(0, -1);

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

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

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

    switch (source) {
    case VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_LEASE:
        ret = libxlGetDHCPInterfaces(dom, vm, ifaces);
        break;

    default:
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED,
                       _("Unsupported IP address data source %d"),
                       source);
        break;
    }

 cleanup:
    virDomainObjEndAPI(&vm);
    return ret;
}


6333 6334 6335 6336 6337 6338 6339 6340 6341 6342 6343 6344 6345 6346 6347 6348 6349 6350 6351 6352 6353 6354 6355 6356 6357 6358 6359 6360 6361 6362 6363 6364 6365 6366 6367 6368 6369 6370 6371 6372 6373 6374 6375 6376 6377 6378 6379 6380 6381 6382 6383 6384 6385 6386 6387 6388 6389 6390 6391 6392 6393 6394 6395 6396 6397 6398 6399 6400 6401 6402 6403 6404 6405
static char *
libxlConnectGetDomainCapabilities(virConnectPtr conn,
                                  const char *emulatorbin,
                                  const char *arch_str,
                                  const char *machine,
                                  const char *virttype_str,
                                  unsigned int flags)
{
    libxlDriverPrivatePtr driver = conn->privateData;
    libxlDriverConfigPtr cfg;
    char *ret = NULL;
    int virttype = VIR_DOMAIN_VIRT_XEN;
    virDomainCapsPtr domCaps = NULL;
    int arch = virArchFromHost(); /* virArch */

    virCheckFlags(0, ret);

    if (virConnectGetDomainCapabilitiesEnsureACL(conn) < 0)
        return ret;

    cfg = libxlDriverConfigGet(driver);

    if (virttype_str &&
        (virttype = virDomainVirtTypeFromString(virttype_str)) < 0) {
        virReportError(VIR_ERR_INVALID_ARG,
                       _("unknown virttype: %s"),
                       virttype_str);
        goto cleanup;
    }

    if (virttype != VIR_DOMAIN_VIRT_XEN) {
        virReportError(VIR_ERR_INVALID_ARG,
                       _("unknown virttype: %s"),
                       virttype_str);
        goto cleanup;
    }

    if (arch_str && (arch = virArchFromString(arch_str)) == VIR_ARCH_NONE) {
        virReportError(VIR_ERR_INVALID_ARG,
                       _("unknown architecture: %s"),
                       arch_str);
        goto cleanup;
    }

    if (emulatorbin == NULL)
        emulatorbin = "/usr/bin/qemu-system-x86_64";

    if (machine) {
        if (STRNEQ(machine, "xenpv") && STRNEQ(machine, "xenfv")) {
            virReportError(VIR_ERR_INVALID_ARG, "%s",
                           _("Xen only supports 'xenpv' and 'xenfv' machines"));
            goto cleanup;
        }
    } else {
        machine = "xenpv";
    }

    if (!(domCaps = virDomainCapsNew(emulatorbin, machine, arch, virttype)))
        goto cleanup;

    if (libxlMakeDomainCapabilities(domCaps, cfg->firmwares,
                                    cfg->nfirmwares) < 0)
        goto cleanup;

    ret = virDomainCapsFormat(domCaps);

 cleanup:
    virObjectUnref(domCaps);
    virObjectUnref(cfg);
    return ret;
}


6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 6416 6417 6418 6419 6420 6421 6422 6423 6424 6425
static int
libxlConnectCompareCPU(virConnectPtr conn,
                       const char *xmlDesc,
                       unsigned int flags)
{
    libxlDriverPrivatePtr driver = conn->privateData;
    libxlDriverConfigPtr cfg;
    int ret = VIR_CPU_COMPARE_ERROR;
    bool failIncompatible;

    virCheckFlags(VIR_CONNECT_COMPARE_CPU_FAIL_INCOMPATIBLE,
                  VIR_CPU_COMPARE_ERROR);

    if (virConnectCompareCPUEnsureACL(conn) < 0)
        return ret;

    failIncompatible = !!(flags & VIR_CONNECT_COMPARE_CPU_FAIL_INCOMPATIBLE);

    cfg = libxlDriverConfigGet(driver);

J
Jiri Denemark 已提交
6426 6427
    ret = virCPUCompareXML(cfg->caps->host.arch, cfg->caps->host.cpu,
                           xmlDesc, failIncompatible);
6428 6429 6430 6431 6432

    virObjectUnref(cfg);
    return ret;
}

6433 6434 6435 6436 6437 6438
static char *
libxlConnectBaselineCPU(virConnectPtr conn,
                        const char **xmlCPUs,
                        unsigned int ncpus,
                        unsigned int flags)
{
J
Jiri Denemark 已提交
6439 6440 6441
    virCPUDefPtr *cpus = NULL;
    virCPUDefPtr cpu = NULL;
    char *cpustr = NULL;
6442 6443 6444 6445 6446 6447 6448

    virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES |
                  VIR_CONNECT_BASELINE_CPU_MIGRATABLE, NULL);

    if (virConnectBaselineCPUEnsureACL(conn) < 0)
        goto cleanup;

J
Jiri Denemark 已提交
6449 6450 6451
    if (!(cpus = virCPUDefListParse(xmlCPUs, ncpus, VIR_CPU_TYPE_HOST)))
        goto cleanup;

6452
    if (!(cpu = cpuBaseline(cpus, ncpus, NULL,
J
Jiri Denemark 已提交
6453 6454 6455 6456 6457 6458 6459
                            !!(flags & VIR_CONNECT_BASELINE_CPU_MIGRATABLE))))
        goto cleanup;

    if ((flags & VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES) &&
        virCPUExpandFeatures(cpus[0]->arch, cpu) < 0)
        goto cleanup;

6460
    cpustr = virCPUDefFormat(cpu, NULL);
6461 6462

 cleanup:
J
Jiri Denemark 已提交
6463 6464 6465 6466
    virCPUDefListFree(cpus);
    virCPUDefFree(cpu);

    return cpustr;
6467 6468
}

6469
static virHypervisorDriver libxlHypervisorDriver = {
6470
    .name = LIBXL_DRIVER_NAME,
6471
    .connectURIProbe = libxlConnectURIProbe,
6472 6473 6474 6475
    .connectOpen = libxlConnectOpen, /* 0.9.0 */
    .connectClose = libxlConnectClose, /* 0.9.0 */
    .connectGetType = libxlConnectGetType, /* 0.9.0 */
    .connectGetVersion = libxlConnectGetVersion, /* 0.9.0 */
6476
    .connectGetHostname = libxlConnectGetHostname, /* 0.9.0 */
6477
    .connectGetSysinfo = libxlConnectGetSysinfo, /* 1.1.0 */
6478
    .connectGetMaxVcpus = libxlConnectGetMaxVcpus, /* 0.9.0 */
6479
    .nodeGetInfo = libxlNodeGetInfo, /* 0.9.0 */
6480 6481 6482 6483
    .connectGetCapabilities = libxlConnectGetCapabilities, /* 0.9.0 */
    .connectListDomains = libxlConnectListDomains, /* 0.9.0 */
    .connectNumOfDomains = libxlConnectNumOfDomains, /* 0.9.0 */
    .connectListAllDomains = libxlConnectListAllDomains, /* 0.9.13 */
6484 6485 6486 6487 6488 6489 6490
    .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 */
6491
    .domainShutdownFlags = libxlDomainShutdownFlags, /* 0.9.10 */
6492 6493
    .domainReboot = libxlDomainReboot, /* 0.9.0 */
    .domainDestroy = libxlDomainDestroy, /* 0.9.0 */
6494
    .domainDestroyFlags = libxlDomainDestroyFlags, /* 0.9.4 */
6495 6496
    .domainGetOSType = libxlDomainGetOSType, /* 0.9.0 */
    .domainGetMaxMemory = libxlDomainGetMaxMemory, /* 0.9.0 */
6497
    .domainSetMaxMemory = libxlDomainSetMaxMemory, /* 0.9.2 */
6498 6499 6500 6501
    .domainSetMemory = libxlDomainSetMemory, /* 0.9.0 */
    .domainSetMemoryFlags = libxlDomainSetMemoryFlags, /* 0.9.0 */
    .domainGetInfo = libxlDomainGetInfo, /* 0.9.0 */
    .domainGetState = libxlDomainGetState, /* 0.9.2 */
6502
    .domainSave = libxlDomainSave, /* 0.9.2 */
6503
    .domainSaveFlags = libxlDomainSaveFlags, /* 0.9.4 */
6504
    .domainRestore = libxlDomainRestore, /* 0.9.2 */
6505
    .domainRestoreFlags = libxlDomainRestoreFlags, /* 0.9.4 */
6506
    .domainCoreDump = libxlDomainCoreDump, /* 0.9.2 */
6507 6508 6509
    .domainSetVcpus = libxlDomainSetVcpus, /* 0.9.0 */
    .domainSetVcpusFlags = libxlDomainSetVcpusFlags, /* 0.9.0 */
    .domainGetVcpusFlags = libxlDomainGetVcpusFlags, /* 0.9.0 */
6510
    .domainGetMaxVcpus = libxlDomainGetMaxVcpus, /* 3.0.0 */
6511
    .domainPinVcpu = libxlDomainPinVcpu, /* 0.9.0 */
6512
    .domainPinVcpuFlags = libxlDomainPinVcpuFlags, /* 1.2.1 */
6513
    .domainGetVcpus = libxlDomainGetVcpus, /* 0.9.0 */
6514
    .domainGetVcpuPinInfo = libxlDomainGetVcpuPinInfo, /* 1.2.1 */
6515
    .domainGetXMLDesc = libxlDomainGetXMLDesc, /* 0.9.0 */
6516 6517 6518 6519
    .connectDomainXMLFromNative = libxlConnectDomainXMLFromNative, /* 0.9.0 */
    .connectDomainXMLToNative = libxlConnectDomainXMLToNative, /* 0.9.0 */
    .connectListDefinedDomains = libxlConnectListDefinedDomains, /* 0.9.0 */
    .connectNumOfDefinedDomains = libxlConnectNumOfDefinedDomains, /* 0.9.0 */
6520 6521 6522
    .domainCreate = libxlDomainCreate, /* 0.9.0 */
    .domainCreateWithFlags = libxlDomainCreateWithFlags, /* 0.9.0 */
    .domainDefineXML = libxlDomainDefineXML, /* 0.9.0 */
6523
    .domainDefineXMLFlags = libxlDomainDefineXMLFlags, /* 1.2.12 */
6524
    .domainUndefine = libxlDomainUndefine, /* 0.9.0 */
6525
    .domainUndefineFlags = libxlDomainUndefineFlags, /* 0.9.4 */
6526 6527 6528 6529 6530
    .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 */
6531 6532 6533 6534
    .domainGetAutostart = libxlDomainGetAutostart, /* 0.9.0 */
    .domainSetAutostart = libxlDomainSetAutostart, /* 0.9.0 */
    .domainGetSchedulerType = libxlDomainGetSchedulerType, /* 0.9.0 */
    .domainGetSchedulerParameters = libxlDomainGetSchedulerParameters, /* 0.9.0 */
6535
    .domainGetSchedulerParametersFlags = libxlDomainGetSchedulerParametersFlags, /* 0.9.2 */
6536
    .domainSetSchedulerParameters = libxlDomainSetSchedulerParameters, /* 0.9.0 */
6537
    .domainSetSchedulerParametersFlags = libxlDomainSetSchedulerParametersFlags, /* 0.9.2 */
6538 6539 6540
#ifdef LIBXL_HAVE_DOMAIN_NODEAFFINITY
    .domainGetNumaParameters = libxlDomainGetNumaParameters, /* 1.1.1 */
#endif
6541
    .nodeGetFreeMemory = libxlNodeGetFreeMemory, /* 0.9.0 */
6542
    .nodeGetCellsFreeMemory = libxlNodeGetCellsFreeMemory, /* 1.1.1 */
6543
    .domainGetJobInfo = libxlDomainGetJobInfo, /* 1.3.1 */
6544
    .domainGetJobStats = libxlDomainGetJobStats, /* 1.3.1 */
P
Pavel Hrdina 已提交
6545 6546
    .domainMemoryStats = libxlDomainMemoryStats, /* 1.3.0 */
    .domainGetCPUStats = libxlDomainGetCPUStats, /* 1.3.0 */
6547
    .domainInterfaceStats = libxlDomainInterfaceStats, /* 1.3.2 */
6548 6549
    .domainBlockStats = libxlDomainBlockStats, /* 2.1.0 */
    .domainBlockStatsFlags = libxlDomainBlockStatsFlags, /* 2.1.0 */
6550 6551
    .connectDomainEventRegister = libxlConnectDomainEventRegister, /* 0.9.0 */
    .connectDomainEventDeregister = libxlConnectDomainEventDeregister, /* 0.9.0 */
6552 6553 6554
    .domainManagedSave = libxlDomainManagedSave, /* 0.9.2 */
    .domainHasManagedSaveImage = libxlDomainHasManagedSaveImage, /* 0.9.2 */
    .domainManagedSaveRemove = libxlDomainManagedSaveRemove, /* 0.9.2 */
B
Bamvor Jian Zhang 已提交
6555
    .domainOpenConsole = libxlDomainOpenConsole, /* 1.1.2 */
6556 6557 6558
    .domainIsActive = libxlDomainIsActive, /* 0.9.0 */
    .domainIsPersistent = libxlDomainIsPersistent, /* 0.9.0 */
    .domainIsUpdated = libxlDomainIsUpdated, /* 0.9.0 */
6559 6560 6561
    .connectDomainEventRegisterAny = libxlConnectDomainEventRegisterAny, /* 0.9.0 */
    .connectDomainEventDeregisterAny = libxlConnectDomainEventDeregisterAny, /* 0.9.0 */
    .connectIsAlive = libxlConnectIsAlive, /* 0.9.8 */
6562
    .connectSupportsFeature = libxlConnectSupportsFeature, /* 1.1.1 */
6563 6564 6565 6566
    .nodeDeviceDettach = libxlNodeDeviceDettach, /* 1.2.3 */
    .nodeDeviceDetachFlags = libxlNodeDeviceDetachFlags, /* 1.2.3 */
    .nodeDeviceReAttach = libxlNodeDeviceReAttach, /* 1.2.3 */
    .nodeDeviceReset = libxlNodeDeviceReset, /* 1.2.3 */
6567 6568
    .domainMigrateBegin3Params = libxlDomainMigrateBegin3Params, /* 1.2.6 */
    .domainMigratePrepare3Params = libxlDomainMigratePrepare3Params, /* 1.2.6 */
B
Bob Liu 已提交
6569
    .domainMigratePrepareTunnel3Params = libxlDomainMigratePrepareTunnel3Params, /* 3.1.0 */
6570 6571 6572
    .domainMigratePerform3Params = libxlDomainMigratePerform3Params, /* 1.2.6 */
    .domainMigrateFinish3Params = libxlDomainMigrateFinish3Params, /* 1.2.6 */
    .domainMigrateConfirm3Params = libxlDomainMigrateConfirm3Params, /* 1.2.6 */
6573
    .nodeGetSecurityModel = libxlNodeGetSecurityModel, /* 1.2.16 */
6574
    .domainInterfaceAddresses = libxlDomainInterfaceAddresses, /* 1.3.5 */
6575
    .connectGetDomainCapabilities = libxlConnectGetDomainCapabilities, /* 2.0.0 */
6576
    .connectCompareCPU = libxlConnectCompareCPU, /* 2.3.0 */
6577
    .connectBaselineCPU = libxlConnectBaselineCPU, /* 2.3.0 */
J
Jim Fehlig 已提交
6578 6579
};

6580
static virConnectDriver libxlConnectDriver = {
6581
    .localOnly = true,
6582 6583 6584
    .hypervisorDriver = &libxlHypervisorDriver,
};

J
Jim Fehlig 已提交
6585 6586
static virStateDriver libxlStateDriver = {
    .name = "LIBXL",
6587
    .stateInitialize = libxlStateInitialize,
6588
    .stateAutoStart = libxlStateAutoStart,
6589 6590
    .stateCleanup = libxlStateCleanup,
    .stateReload = libxlStateReload,
J
Jim Fehlig 已提交
6591 6592 6593 6594 6595 6596
};


int
libxlRegister(void)
{
6597 6598
    if (virRegisterConnectDriver(&libxlConnectDriver,
                                 true) < 0)
J
Jim Fehlig 已提交
6599 6600 6601 6602 6603 6604
        return -1;
    if (virRegisterStateDriver(&libxlStateDriver) < 0)
        return -1;

    return 0;
}