libxl_driver.c 123.7 KB
Newer Older
1 2 3 4 5 6
/*
 * libxl_driver.c: core driver methods for managing libxenlight domains
 *
 * Copyright (C) 2006-2013 Red Hat, Inc.
 * Copyright (C) 2011-2013 SUSE LINUX Products GmbH, Nuernberg, Germany.
 * Copyright (C) 2011 Univention GmbH.
J
Jim Fehlig 已提交
7 8 9 10 11 12 13 14 15 16 17 18
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
19
 * License along with this library.  If not, see
O
Osier Yang 已提交
20
 * <http://www.gnu.org/licenses/>.
M
Markus Groß 已提交
21 22 23 24 25
 *
 * Authors:
 *     Jim Fehlig <jfehlig@novell.com>
 *     Markus Groß <gross@univention.de>
 *     Daniel P. Berrange <berrange@redhat.com>
J
Jim Fehlig 已提交
26 27 28 29
 */

#include <config.h>

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

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

#define VIR_FROM_THIS VIR_FROM_LIBXL

#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

64 65
#define LIBXL_CONFIG_FORMAT_XM "xen-xm"

66 67 68
/* Number of Xen scheduler parameters */
#define XEN_SCHED_CREDIT_NPARAM   2

69

J
Jim Fehlig 已提交
70 71 72
static libxlDriverPrivatePtr libxl_driver = NULL;

/* Function declarations */
73 74
static int
libxlDomainManagedSaveLoad(virDomainObjPtr vm,
75 76
                           void *opaque);

J
Jim Fehlig 已提交
77
static int
78 79
libxlVmStart(libxlDriverPrivatePtr driver, virDomainObjPtr vm,
             bool start_paused, int restore_fd);
J
Jim Fehlig 已提交
80

J
Jim Fehlig 已提交
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101

/* Function definitions */
static virDomainObjPtr
libxlDomObjFromDomain(virDomainPtr dom)
{
    virDomainObjPtr vm;
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    char uuidstr[VIR_UUID_STRING_BUFLEN];

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

    return vm;
}

102 103 104
static void
libxlDomainEventQueue(libxlDriverPrivatePtr driver, virDomainEventPtr event)
{
105
    virDomainEventStateQueue(driver->domainEventState, event);
106 107
}

108 109
static int
libxlAutostartDomain(virDomainObjPtr vm,
110 111 112 113
                     void *opaque)
{
    libxlDriverPrivatePtr driver = opaque;
    virErrorPtr err;
114
    int ret = -1;
115

116
    virObjectLock(vm);
117 118 119
    virResetLastError();

    if (vm->autostart && !virDomainObjIsActive(vm) &&
120
        libxlVmStart(driver, vm, false, -1) < 0) {
121 122 123 124
        err = virGetLastError();
        VIR_ERROR(_("Failed to autostart VM '%s': %s"),
                  vm->def->name,
                  err ? err->message : _("unknown error"));
125
        goto cleanup;
126 127
    }

128 129
    ret = 0;
cleanup:
130
    virObjectUnlock(vm);
131
    return ret;
132 133
}

134 135 136 137
static int
libxlDoNodeGetInfo(libxlDriverPrivatePtr driver, virNodeInfoPtr info)
{
    libxl_physinfo phy_info;
138
    virArch hostarch = virArchFromHost();
139 140
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
    int ret = -1;
141

142
    if (libxl_get_physinfo(cfg->ctx, &phy_info)) {
143 144
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("libxl_get_physinfo_info failed"));
145
        goto cleanup;
146 147
    }

148
    if (virStrcpyStatic(info->model, virArchToString(hostarch)) == NULL) {
149 150
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("machine type %s too big for destination"),
151
                       virArchToString(hostarch));
152
        goto cleanup;
153 154
    }

155
    info->memory = phy_info.total_pages * (cfg->verInfo->pagesize / 1024);
156 157 158 159 160 161
    info->cpus = phy_info.nr_cpus;
    info->nodes = phy_info.nr_nodes;
    info->cores = phy_info.cores_per_socket;
    info->threads = phy_info.threads_per_core;
    info->sockets = 1;
    info->mhz = phy_info.cpu_khz / 1000;
162 163 164 165 166 167

    ret = 0;

cleanup:
    virObjectUnref(cfg);
    return ret;
168 169
}

170 171 172
static char *
libxlDomainManagedSavePath(libxlDriverPrivatePtr driver, virDomainObjPtr vm) {
    char *ret;
173
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
174

175 176
    ignore_value(virAsprintf(&ret, "%s/%s.save", cfg->saveDir, vm->def->name));
    virObjectUnref(cfg);
177 178 179
    return ret;
}

180 181 182 183 184 185 186 187 188 189
/*
 * This internal function expects the driver lock to already be held on
 * entry.
 */
static int ATTRIBUTE_NONNULL(4) ATTRIBUTE_NONNULL(5)
libxlSaveImageOpen(libxlDriverPrivatePtr driver,
                   libxlDriverConfigPtr cfg,
                   const char *from,
                   virDomainDefPtr *ret_def,
                   libxlSavefileHeaderPtr ret_hdr)
190 191 192 193 194 195
{
    int fd;
    virDomainDefPtr def = NULL;
    libxlSavefileHeader hdr;
    char *xml = NULL;

L
Laine Stump 已提交
196
    if ((fd = virFileOpenAs(from, O_RDONLY, 0, -1, -1, 0)) < 0) {
197 198
        virReportSystemError(-fd,
                             _("Failed to open domain image file '%s'"), from);
199 200 201 202
        goto error;
    }

    if (saferead(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
203 204
        virReportError(VIR_ERR_OPERATION_FAILED,
                       "%s", _("failed to read libxl header"));
205 206 207 208
        goto error;
    }

    if (memcmp(hdr.magic, LIBXL_SAVE_MAGIC, sizeof(hdr.magic))) {
209
        virReportError(VIR_ERR_INVALID_ARG, "%s", _("image magic is incorrect"));
210 211 212 213
        goto error;
    }

    if (hdr.version > LIBXL_SAVE_VERSION) {
214 215 216
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("image version is not supported (%d > %d)"),
                       hdr.version, LIBXL_SAVE_VERSION);
217 218 219 220
        goto error;
    }

    if (hdr.xmlLen <= 0) {
221 222
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("invalid XML length: %d"), hdr.xmlLen);
223 224 225
        goto error;
    }

226
    if (VIR_ALLOC_N(xml, hdr.xmlLen) < 0)
227 228 229
        goto error;

    if (saferead(fd, xml, hdr.xmlLen) != hdr.xmlLen) {
230
        virReportError(VIR_ERR_OPERATION_FAILED, "%s", _("failed to read XML"));
231 232 233
        goto error;
    }

234
    if (!(def = virDomainDefParseString(xml, cfg->caps, driver->xmlopt,
235
                                        1 << VIR_DOMAIN_VIRT_XEN,
236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
                                        VIR_DOMAIN_XML_INACTIVE)))
        goto error;

    VIR_FREE(xml);

    *ret_def = def;
    *ret_hdr = hdr;

    return fd;

error:
    VIR_FREE(xml);
    virDomainDefFree(def);
    VIR_FORCE_CLOSE(fd);
    return -1;
}

J
Jim Fehlig 已提交
253 254 255 256 257 258
/*
 * Cleanup function for domain that has reached shutoff state.
 *
 * virDomainObjPtr should be locked on invocation
 */
static void
J
Jiri Denemark 已提交
259 260 261
libxlVmCleanup(libxlDriverPrivatePtr driver,
               virDomainObjPtr vm,
               virDomainShutoffReason reason)
J
Jim Fehlig 已提交
262 263
{
    libxlDomainObjPrivatePtr priv = vm->privateData;
264
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
J
Jim Fehlig 已提交
265 266
    int vnc_port;
    char *file;
267
    size_t i;
J
Jim Fehlig 已提交
268

J
Jim Fehlig 已提交
269 270 271
    if (priv->deathW) {
        libxl_evdisable_domain_death(priv->ctx, priv->deathW);
        priv->deathW = NULL;
J
Jim Fehlig 已提交
272 273 274 275
    }

    if (vm->persistent) {
        vm->def->id = -1;
J
Jiri Denemark 已提交
276
        virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, reason);
J
Jim Fehlig 已提交
277 278
    }

279
    if (virAtomicIntDecAndTest(&driver->nactive) && driver->inhibitCallback)
280 281
        driver->inhibitCallback(false, driver->inhibitOpaque);

J
Jim Fehlig 已提交
282 283 284 285 286
    if ((vm->def->ngraphics == 1) &&
        vm->def->graphics[0]->type == VIR_DOMAIN_GRAPHICS_TYPE_VNC &&
        vm->def->graphics[0]->data.vnc.autoport) {
        vnc_port = vm->def->graphics[0]->data.vnc.port;
        if (vnc_port >= LIBXL_VNC_PORT_MIN) {
287 288
            if (virPortAllocatorRelease(driver->reservedVNCPorts,
                                        vnc_port) < 0)
J
Jim Fehlig 已提交
289 290 291 292
                VIR_DEBUG("Could not mark port %d as unused", vnc_port);
        }
    }

293 294 295
    /* Remove any cputune settings */
    if (vm->def->cputune.nvcpupin) {
        for (i = 0; i < vm->def->cputune.nvcpupin; ++i) {
296
            virBitmapFree(vm->def->cputune.vcpupin[i]->cpumask);
297 298 299 300 301 302
            VIR_FREE(vm->def->cputune.vcpupin[i]);
        }
        VIR_FREE(vm->def->cputune.vcpupin);
        vm->def->cputune.nvcpupin = 0;
    }

303
    if (virAsprintf(&file, "%s/%s.xml", cfg->stateDir, vm->def->name) > 0) {
J
Jim Fehlig 已提交
304 305 306 307
        if (unlink(file) < 0 && errno != ENOENT && errno != ENOTDIR)
            VIR_DEBUG("Failed to remove domain XML for %s", vm->def->name);
        VIR_FREE(file);
    }
308 309 310 311 312 313 314

    if (vm->newDef) {
        virDomainDefFree(vm->def);
        vm->def = vm->newDef;
        vm->def->id = -1;
        vm->newDef = NULL;
    }
J
Jim Fehlig 已提交
315

J
Jim Fehlig 已提交
316
    libxlDomainObjRegisteredTimeoutsCleanup(priv);
317
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
318 319 320 321 322 323 324 325
}

/*
 * Reap a domain from libxenlight.
 *
 * virDomainObjPtr should be locked on invocation
 */
static int
J
Jiri Denemark 已提交
326 327 328
libxlVmReap(libxlDriverPrivatePtr driver,
            virDomainObjPtr vm,
            virDomainShutoffReason reason)
J
Jim Fehlig 已提交
329 330 331
{
    libxlDomainObjPrivatePtr priv = vm->privateData;

J
Jim Fehlig 已提交
332
    if (libxl_domain_destroy(priv->ctx, vm->def->id, NULL) < 0) {
333 334
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Unable to cleanup domain %d"), vm->def->id);
J
Jim Fehlig 已提交
335 336 337
        return -1;
    }

J
Jiri Denemark 已提交
338
    libxlVmCleanup(driver, vm, reason);
J
Jim Fehlig 已提交
339 340 341 342
    return 0;
}

/*
J
Jim Fehlig 已提交
343 344 345 346 347
 * Handle previously registered event notification from libxenlight.
 *
 * Note: Xen 4.3 removed the const from the event handler signature.
 * Detect which signature to use based on
 * LIBXL_HAVE_NONCONST_EVENT_OCCURS_EVENT_ARG.
J
Jim Fehlig 已提交
348
 */
J
Jim Fehlig 已提交
349 350 351 352 353 354 355

#ifdef LIBXL_HAVE_NONCONST_EVENT_OCCURS_EVENT_ARG
# define VIR_LIBXL_EVENT_CONST /* empty */
#else
# define VIR_LIBXL_EVENT_CONST const
#endif

356
static void
J
Jim Fehlig 已提交
357
libxlEventHandler(void *data, VIR_LIBXL_EVENT_CONST libxl_event *event)
J
Jim Fehlig 已提交
358 359
{
    libxlDriverPrivatePtr driver = libxl_driver;
J
Jim Fehlig 已提交
360
    libxlDomainObjPrivatePtr priv = ((virDomainObjPtr)data)->privateData;
361
    virDomainObjPtr vm = NULL;
362
    virDomainEventPtr dom_event = NULL;
363
    libxl_shutdown_reason xl_reason = event->u.domain_shutdown.shutdown_reason;
J
Jim Fehlig 已提交
364

J
Jim Fehlig 已提交
365
    if (event->type == LIBXL_EVENT_TYPE_DOMAIN_SHUTDOWN) {
J
Jiri Denemark 已提交
366 367
        virDomainShutoffReason reason;

368 369 370 371 372 373 374
        /*
         * Similar to the xl implementation, ignore SUSPEND.  Any actions needed
         * after calling libxl_domain_suspend() are handled by it's callers.
         */
        if (xl_reason == LIBXL_SHUTDOWN_REASON_SUSPEND)
            goto cleanup;

375
        vm = virDomainObjListFindByID(driver->domains, event->domid);
376
        if (!vm)
J
Jim Fehlig 已提交
377 378
            goto cleanup;

379
        switch (xl_reason) {
J
Jim Fehlig 已提交
380 381
            case LIBXL_SHUTDOWN_REASON_POWEROFF:
            case LIBXL_SHUTDOWN_REASON_CRASH:
382
                if (xl_reason == LIBXL_SHUTDOWN_REASON_CRASH) {
383 384 385
                    dom_event = virDomainEventNewFromObj(vm,
                                              VIR_DOMAIN_EVENT_STOPPED,
                                              VIR_DOMAIN_EVENT_STOPPED_CRASHED);
J
Jiri Denemark 已提交
386 387 388 389
                    reason = VIR_DOMAIN_SHUTOFF_CRASHED;
                } else {
                    reason = VIR_DOMAIN_SHUTOFF_SHUTDOWN;
                }
J
Jim Fehlig 已提交
390
                libxlVmReap(driver, vm, reason);
J
Jim Fehlig 已提交
391
                if (!vm->persistent) {
392
                    virDomainObjListRemove(driver->domains, vm);
J
Jim Fehlig 已提交
393 394 395
                    vm = NULL;
                }
                break;
J
Jim Fehlig 已提交
396 397
            case LIBXL_SHUTDOWN_REASON_REBOOT:
                libxlVmReap(driver, vm, VIR_DOMAIN_SHUTOFF_SHUTDOWN);
398
                libxlVmStart(driver, vm, 0, -1);
J
Jim Fehlig 已提交
399 400
                break;
            default:
401
                VIR_INFO("Unhandled shutdown_reason %d", xl_reason);
J
Jim Fehlig 已提交
402 403 404 405 406 407
                break;
        }
    }

cleanup:
    if (vm)
408
        virObjectUnlock(vm);
409
    if (dom_event)
410
        libxlDomainEventQueue(driver, dom_event);
J
Jim Fehlig 已提交
411 412
    /* Cast away any const */
    libxl_event_free(priv->ctx, (libxl_event *)event);
J
Jim Fehlig 已提交
413 414
}

J
Jim Fehlig 已提交
415 416 417 418 419 420
static const struct libxl_event_hooks ev_hooks = {
    .event_occurs_mask = LIBXL_EVENTMASK_ALL,
    .event_occurs = libxlEventHandler,
    .disaster = NULL,
};

J
Jim Fehlig 已提交
421 422 423 424 425 426 427 428 429
/*
 * Register domain events with libxenlight and insert event handles
 * in libvirt's event loop.
 */
static int
libxlCreateDomEvents(virDomainObjPtr vm)
{
    libxlDomainObjPrivatePtr priv = vm->privateData;

J
Jim Fehlig 已提交
430
    libxl_event_register_callbacks(priv->ctx, &ev_hooks, vm);
J
Jim Fehlig 已提交
431

J
Jim Fehlig 已提交
432
    if (libxl_evenable_domain_death(priv->ctx, vm->def->id, 0, &priv->deathW))
J
Jim Fehlig 已提交
433 434 435 436 437
        goto error;

    return 0;

error:
438
    if (priv->deathW) {
J
Jim Fehlig 已提交
439
        libxl_evdisable_domain_death(priv->ctx, priv->deathW);
440 441
        priv->deathW = NULL;
    }
J
Jim Fehlig 已提交
442 443 444
    return -1;
}

445
static int
446
libxlDomainSetVcpuAffinities(libxlDriverPrivatePtr driver, virDomainObjPtr vm)
447 448 449
{
    libxlDomainObjPrivatePtr priv = vm->privateData;
    virDomainDefPtr def = vm->def;
J
Jim Fehlig 已提交
450
    libxl_bitmap map;
451
    virBitmapPtr cpumask = NULL;
452 453 454
    uint8_t *cpumap = NULL;
    virNodeInfo nodeinfo;
    size_t cpumaplen;
455 456
    int vcpu;
    size_t i;
457 458 459 460 461 462 463 464 465 466 467
    int ret = -1;

    if (libxlDoNodeGetInfo(driver, &nodeinfo) < 0)
        goto cleanup;

    cpumaplen = VIR_CPU_MAPLEN(VIR_NODEINFO_MAXCPUS(nodeinfo));

    for (vcpu = 0; vcpu < def->cputune.nvcpupin; ++vcpu) {
        if (vcpu != def->cputune.vcpupin[vcpu]->vcpuid)
            continue;

468
        if (VIR_ALLOC_N(cpumap, cpumaplen) < 0)
469 470
            goto cleanup;

471
        cpumask = def->cputune.vcpupin[vcpu]->cpumask;
472

473 474 475 476
        for (i = 0; i < virBitmapSize(cpumask); ++i) {
            bool bit;
            ignore_value(virBitmapGetBit(cpumask, i, &bit));
            if (bit)
477
                VIR_USE_CPU(cpumap, i);
478 479 480 481 482
        }

        map.size = cpumaplen;
        map.map = cpumap;

J
Jim Fehlig 已提交
483
        if (libxl_set_vcpuaffinity(priv->ctx, def->id, vcpu, &map) != 0) {
484 485
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Failed to pin vcpu '%d' with libxenlight"), vcpu);
486 487 488 489 490 491 492 493 494 495 496 497 498
            goto cleanup;
        }

        VIR_FREE(cpumap);
    }

    ret = 0;

cleanup:
    VIR_FREE(cpumap);
    return ret;
}

M
Markus Groß 已提交
499 500 501 502 503
static int
libxlFreeMem(libxlDomainObjPrivatePtr priv, libxl_domain_config *d_config)
{
    uint32_t needed_mem;
    uint32_t free_mem;
504
    size_t i;
M
Markus Groß 已提交
505 506 507 508
    int ret = -1;
    int tries = 3;
    int wait_secs = 10;

J
Jim Fehlig 已提交
509
    if ((ret = libxl_domain_need_memory(priv->ctx, &d_config->b_info,
M
Markus Groß 已提交
510 511
                                        &needed_mem)) >= 0) {
        for (i = 0; i < tries; ++i) {
J
Jim Fehlig 已提交
512
            if ((ret = libxl_get_free_memory(priv->ctx, &free_mem)) < 0)
M
Markus Groß 已提交
513 514 515 516 517 518 519
                break;

            if (free_mem >= needed_mem) {
                ret = 0;
                break;
            }

J
Jim Fehlig 已提交
520
            if ((ret = libxl_set_memory_target(priv->ctx, 0,
M
Markus Groß 已提交
521 522 523 524
                                               free_mem - needed_mem,
                                               /* relative */ 1, 0)) < 0)
                break;

J
Jim Fehlig 已提交
525
            ret = libxl_wait_for_free_memory(priv->ctx, 0, needed_mem,
M
Markus Groß 已提交
526 527 528 529
                                             wait_secs);
            if (ret == 0 || ret != ERROR_NOMEM)
                break;

J
Jim Fehlig 已提交
530
            if ((ret = libxl_wait_for_memory_target(priv->ctx, 0, 1)) < 0)
M
Markus Groß 已提交
531 532 533 534 535 536 537
                break;
        }
    }

    return ret;
}

J
Jim Fehlig 已提交
538 539 540 541 542 543
/*
 * Start a domain through libxenlight.
 *
 * virDomainObjPtr should be locked on invocation
 */
static int
544 545
libxlVmStart(libxlDriverPrivatePtr driver, virDomainObjPtr vm,
             bool start_paused, int restore_fd)
J
Jim Fehlig 已提交
546 547
{
    libxl_domain_config d_config;
548
    virDomainDefPtr def = NULL;
549
    virDomainEventPtr event = NULL;
550
    libxlSavefileHeader hdr;
J
Jim Fehlig 已提交
551 552 553
    int ret;
    uint32_t domid = 0;
    char *dom_xml = NULL;
554 555
    char *managed_save_path = NULL;
    int managed_save_fd = -1;
J
Jim Fehlig 已提交
556
    libxlDomainObjPrivatePtr priv = vm->privateData;
557
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
B
Bamvor Jian Zhang 已提交
558 559 560
#ifdef LIBXL_HAVE_DOMAIN_CREATE_RESTORE_PARAMS
    libxl_domain_restore_params params;
#endif
J
Jim Fehlig 已提交
561

J
Jim Fehlig 已提交
562 563 564
    if (libxlDomainObjPrivateInitCtx(vm) < 0)
        goto error;

565 566 567
    /* If there is a managed saved state restore it instead of starting
     * from scratch. The old state is removed once the restoring succeeded. */
    if (restore_fd < 0) {
568 569
        managed_save_path = libxlDomainManagedSavePath(driver, vm);
        if (managed_save_path == NULL)
570 571
            goto error;

572
        if (virFileExists(managed_save_path)) {
573

574 575
            managed_save_fd = libxlSaveImageOpen(driver, cfg,
                                                 managed_save_path,
576 577
                                                 &def, &hdr);
            if (managed_save_fd < 0)
578 579
                goto error;

580 581
            restore_fd = managed_save_fd;

582 583 584 585 586 587
            if (STRNEQ(vm->def->name, def->name) ||
                memcmp(vm->def->uuid, def->uuid, VIR_UUID_BUFLEN)) {
                char vm_uuidstr[VIR_UUID_STRING_BUFLEN];
                char def_uuidstr[VIR_UUID_STRING_BUFLEN];
                virUUIDFormat(vm->def->uuid, vm_uuidstr);
                virUUIDFormat(def->uuid, def_uuidstr);
588 589 590 591
                virReportError(VIR_ERR_OPERATION_FAILED,
                               _("cannot restore domain '%s' uuid %s from a file"
                                 " which belongs to domain '%s' uuid %s"),
                               vm->def->name, vm_uuidstr, def->name, def_uuidstr);
592 593 594
                goto error;
            }

595
            virDomainObjAssignDef(vm, def, true, NULL);
596 597
            def = NULL;

598
            if (unlink(managed_save_path) < 0)
599 600
                VIR_WARN("Failed to remove the managed state %s",
                         managed_save_path);
601

602
            vm->hasManagedSave = false;
603
        }
604
        VIR_FREE(managed_save_path);
605 606
    }

J
Jim Fehlig 已提交
607
    libxl_domain_config_init(&d_config);
J
Jim Fehlig 已提交
608

609
    if (libxlBuildDomainConfig(driver, vm, &d_config) < 0)
610
        goto error;
J
Jim Fehlig 已提交
611

612
    if (cfg->autoballoon && libxlFreeMem(priv, &d_config) < 0) {
613 614 615
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("libxenlight failed to get free memory for domain '%s'"),
                       d_config.c_info.name);
M
Markus Groß 已提交
616 617
        goto error;
    }
J
Jim Fehlig 已提交
618

J
Jim Fehlig 已提交
619 620
    /* use as synchronous operations => ao_how = NULL and no intermediate reports => ao_progress = NULL */

621
    if (restore_fd < 0) {
J
Jim Fehlig 已提交
622 623
        ret = libxl_domain_create_new(priv->ctx, &d_config,
                                      &domid, NULL, NULL);
624
    } else {
B
Bamvor Jian Zhang 已提交
625 626 627 628 629
#ifdef LIBXL_HAVE_DOMAIN_CREATE_RESTORE_PARAMS
        params.checkpointed_stream = 0;
        ret = libxl_domain_create_restore(priv->ctx, &d_config, &domid,
                                          restore_fd, &params, NULL, NULL);
#else
J
Jim Fehlig 已提交
630 631
        ret = libxl_domain_create_restore(priv->ctx, &d_config, &domid,
                                          restore_fd, NULL, NULL);
B
Bamvor Jian Zhang 已提交
632
#endif
633
    }
634

J
Jim Fehlig 已提交
635
    if (ret) {
636
        if (restore_fd < 0)
637 638 639
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("libxenlight failed to create new domain '%s'"),
                           d_config.c_info.name);
640
        else
641 642 643
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("libxenlight failed to restore domain '%s'"),
                           d_config.c_info.name);
J
Jim Fehlig 已提交
644 645 646
        goto error;
    }

647 648
    vm->def->id = domid;
    if ((dom_xml = virDomainDefFormat(vm->def, 0)) == NULL)
J
Jim Fehlig 已提交
649 650
        goto error;

J
Jim Fehlig 已提交
651
    if (libxl_userdata_store(priv->ctx, domid, "libvirt-xml",
J
Jim Fehlig 已提交
652
                             (uint8_t *)dom_xml, strlen(dom_xml) + 1)) {
653 654
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("libxenlight failed to store userdata"));
J
Jim Fehlig 已提交
655 656 657 658 659 660
        goto error;
    }

    if (libxlCreateDomEvents(vm) < 0)
        goto error;

661
    if (libxlDomainSetVcpuAffinities(driver, vm) < 0)
662 663
        goto error;

J
Jim Fehlig 已提交
664
    if (!start_paused) {
J
Jim Fehlig 已提交
665
        libxl_domain_unpause(priv->ctx, domid);
J
Jiri Denemark 已提交
666
        virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_BOOTED);
J
Jim Fehlig 已提交
667
    } else {
J
Jiri Denemark 已提交
668
        virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER);
J
Jim Fehlig 已提交
669 670
    }

671

672
    if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
J
Jim Fehlig 已提交
673 674
        goto error;

675
    if (virAtomicIntInc(&driver->nactive) == 1 && driver->inhibitCallback)
676 677
        driver->inhibitCallback(true, driver->inhibitOpaque);

678
    event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STARTED,
679 680 681
                                     restore_fd < 0 ?
                                         VIR_DOMAIN_EVENT_STARTED_BOOTED :
                                         VIR_DOMAIN_EVENT_STARTED_RESTORED);
682 683
    if (event)
        libxlDomainEventQueue(driver, event);
684

J
Jim Fehlig 已提交
685
    libxl_domain_config_dispose(&d_config);
J
Jim Fehlig 已提交
686
    VIR_FREE(dom_xml);
687
    VIR_FORCE_CLOSE(managed_save_fd);
688
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
689 690 691 692
    return 0;

error:
    if (domid > 0) {
J
Jim Fehlig 已提交
693
        libxl_domain_destroy(priv->ctx, domid, NULL);
694
        vm->def->id = -1;
J
Jiri Denemark 已提交
695
        virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, VIR_DOMAIN_SHUTOFF_FAILED);
J
Jim Fehlig 已提交
696
    }
J
Jim Fehlig 已提交
697
    libxl_domain_config_dispose(&d_config);
J
Jim Fehlig 已提交
698
    VIR_FREE(dom_xml);
699
    VIR_FREE(managed_save_path);
700
    virDomainDefFree(def);
701
    VIR_FORCE_CLOSE(managed_save_fd);
702
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
703 704 705 706 707 708 709 710
    return -1;
}


/*
 * Reconnect to running domains that were previously started/created
 * with libxenlight driver.
 */
711 712
static int
libxlReconnectDomain(virDomainObjPtr vm,
J
Jim Fehlig 已提交
713 714 715
                     void *opaque)
{
    libxlDriverPrivatePtr driver = opaque;
716
    libxlDomainObjPrivatePtr priv = vm->privateData;
J
Jim Fehlig 已提交
717 718 719 720 721
    int rc;
    libxl_dominfo d_info;
    int len;
    uint8_t *data = NULL;

722
    virObjectLock(vm);
J
Jim Fehlig 已提交
723

724
    libxlDomainObjPrivateInitCtx(vm);
J
Jim Fehlig 已提交
725
    /* Does domain still exist? */
726
    rc = libxl_domain_info(priv->ctx, &d_info, vm->def->id);
J
Jim Fehlig 已提交
727 728 729 730 731 732 733 734 735
    if (rc == ERROR_INVAL) {
        goto out;
    } else if (rc != 0) {
        VIR_DEBUG("libxl_domain_info failed (code %d), ignoring domain %d",
                  rc, vm->def->id);
        goto out;
    }

    /* Is this a domain that was under libvirt control? */
736
    if (libxl_userdata_retrieve(priv->ctx, vm->def->id,
J
Jim Fehlig 已提交
737 738 739 740 741 742 743
                                "libvirt-xml", &data, &len)) {
        VIR_DEBUG("libxl_userdata_retrieve failed, ignoring domain %d", vm->def->id);
        goto out;
    }

    /* Update domid in case it changed (e.g. reboot) while we were gone? */
    vm->def->id = d_info.domid;
J
Jiri Denemark 已提交
744
    virDomainObjSetState(vm, VIR_DOMAIN_RUNNING, VIR_DOMAIN_RUNNING_UNKNOWN);
J
Jim Fehlig 已提交
745

746
    if (virAtomicIntInc(&driver->nactive) == 1 && driver->inhibitCallback)
747 748
        driver->inhibitCallback(true, driver->inhibitOpaque);

J
Jim Fehlig 已提交
749 750
    /* Recreate domain death et. al. events */
    libxlCreateDomEvents(vm);
751
    virObjectUnlock(vm);
752
    return 0;
J
Jim Fehlig 已提交
753 754

out:
J
Jiri Denemark 已提交
755
    libxlVmCleanup(driver, vm, VIR_DOMAIN_SHUTOFF_UNKNOWN);
J
Jim Fehlig 已提交
756
    if (!vm->persistent)
757
        virDomainObjListRemoveLocked(driver->domains, vm);
J
Jim Fehlig 已提交
758
    else
759
        virObjectUnlock(vm);
760 761

    return -1;
J
Jim Fehlig 已提交
762 763 764 765 766
}

static void
libxlReconnectDomains(libxlDriverPrivatePtr driver)
{
767
    virDomainObjListForEach(driver->domains, libxlReconnectDomain, driver);
J
Jim Fehlig 已提交
768 769 770
}

static int
771
libxlStateCleanup(void)
J
Jim Fehlig 已提交
772 773 774 775
{
    if (!libxl_driver)
        return -1;

776
    virObjectUnref(libxl_driver->config);
777
    virObjectUnref(libxl_driver->xmlopt);
778
    virObjectUnref(libxl_driver->domains);
779
    virObjectUnref(libxl_driver->reservedVNCPorts);
J
Jim Fehlig 已提交
780

E
Eric Blake 已提交
781
    virDomainEventStateFree(libxl_driver->domainEventState);
782
    virSysinfoDefFree(libxl_driver->hostsysinfo);
783

J
Jim Fehlig 已提交
784 785 786 787 788 789
    virMutexDestroy(&libxl_driver->lock);
    VIR_FREE(libxl_driver);

    return 0;
}

790 791
static bool
libxlDriverShouldLoad(bool privileged)
792
{
793
    bool ret = false;
J
Jim Fehlig 已提交
794
    virCommandPtr cmd;
795
    int status;
J
Jim Fehlig 已提交
796

797
    /* Don't load if non-root */
J
Jim Fehlig 已提交
798
    if (!privileged) {
799
        VIR_INFO("Not running privileged, disabling libxenlight driver");
800
        return ret;
J
Jim Fehlig 已提交
801 802
    }

803 804 805 806 807 808 809 810 811
    /* Don't load if not running on a Xen control domain (dom0) */
    if (!virFileExists("/proc/xen/capabilities")) {
        VIR_INFO("No Xen capabilities detected, probably not running "
                 "in a Xen Dom0.  Disabling libxenlight driver");

        return ret;
    }

    /* Don't load if legacy xen toolstack (xend) is in use */
J
Jim Fehlig 已提交
812 813
    cmd = virCommandNewArgList("/usr/sbin/xend", "status", NULL);
    if (virCommandRun(cmd, &status) == 0 && status == 0) {
814
        VIR_INFO("Legacy xen tool stack seems to be in use, disabling "
J
Jim Fehlig 已提交
815
                  "libxenlight driver.");
816 817
    } else {
        ret = true;
J
Jim Fehlig 已提交
818 819 820
    }
    virCommandFree(cmd);

821 822 823 824 825 826 827 828
    return ret;
}

static int
libxlStateInitialize(bool privileged,
                     virStateInhibitCallback callback ATTRIBUTE_UNUSED,
                     void *opaque ATTRIBUTE_UNUSED)
{
829
    libxlDriverConfigPtr cfg;
830 831 832 833 834
    char ebuf[1024];

    if (!libxlDriverShouldLoad(privileged))
        return 0;

J
Jim Fehlig 已提交
835 836 837 838
    if (VIR_ALLOC(libxl_driver) < 0)
        return -1;

    if (virMutexInit(&libxl_driver->lock) < 0) {
839 840
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("cannot initialize mutex"));
J
Jim Fehlig 已提交
841 842 843 844 845
        VIR_FREE(libxl_driver);
        return -1;
    }

    /* Allocate bitmap for vnc port reservation */
846
    if (!(libxl_driver->reservedVNCPorts =
J
Ján Tomko 已提交
847 848
          virPortAllocatorNew(_("VNC"),
                              LIBXL_VNC_PORT_MIN,
849 850
                              LIBXL_VNC_PORT_MAX)))
        goto error;
J
Jim Fehlig 已提交
851

852 853
    if (!(libxl_driver->domains = virDomainObjListNew()))
        goto error;
J
Jim Fehlig 已提交
854

855
    if (!(cfg = libxlDriverConfigNew()))
856
        goto error;
J
Jim Fehlig 已提交
857

858 859
    libxl_driver->config = cfg;
    if (virFileMakePath(cfg->logDir) < 0) {
860 861
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to create log dir '%s': %s"),
862
                       cfg->logDir,
863
                       virStrerror(errno, ebuf, sizeof(ebuf)));
J
Jim Fehlig 已提交
864 865
        goto error;
    }
866
    if (virFileMakePath(cfg->stateDir) < 0) {
867 868
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to create state dir '%s': %s"),
869
                       cfg->stateDir,
870
                       virStrerror(errno, ebuf, sizeof(ebuf)));
J
Jim Fehlig 已提交
871 872
        goto error;
    }
873
    if (virFileMakePath(cfg->libDir) < 0) {
874 875
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to create lib dir '%s': %s"),
876
                       cfg->libDir,
877
                       virStrerror(errno, ebuf, sizeof(ebuf)));
J
Jim Fehlig 已提交
878 879
        goto error;
    }
880
    if (virFileMakePath(cfg->saveDir) < 0) {
881 882
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to create save dir '%s': %s"),
883
                       cfg->saveDir,
884
                       virStrerror(errno, ebuf, sizeof(ebuf)));
J
Jim Fehlig 已提交
885 886 887
        goto error;
    }

888
    /* read the host sysinfo */
889
    libxl_driver->hostsysinfo = virSysinfoRead();
890

891
    libxl_driver->domainEventState = virDomainEventStateNew();
E
Eric Blake 已提交
892
    if (!libxl_driver->domainEventState)
893 894
        goto error;

895
    if ((cfg->caps = libxlMakeCapabilities(cfg->ctx)) == NULL) {
896 897
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("cannot create capabilities for libxenlight"));
J
Jim Fehlig 已提交
898 899 900
        goto error;
    }

901
    if (!(libxl_driver->xmlopt = virDomainXMLOptionNew(&libxlDomainDefParserConfig,
902 903
                                                       &libxlDomainXMLPrivateDataCallbacks,
                                                       NULL)))
904
        goto error;
J
Jim Fehlig 已提交
905 906

    /* Load running domains first. */
907
    if (virDomainObjListLoadAllConfigs(libxl_driver->domains,
908 909
                                       cfg->stateDir,
                                       cfg->autostartDir,
910
                                       1,
911
                                       cfg->caps,
912 913
                                       libxl_driver->xmlopt,
                                       1 << VIR_DOMAIN_VIRT_XEN,
914
                                       NULL, NULL) < 0)
J
Jim Fehlig 已提交
915 916 917 918 919
        goto error;

    libxlReconnectDomains(libxl_driver);

    /* Then inactive persistent configs */
920
    if (virDomainObjListLoadAllConfigs(libxl_driver->domains,
921 922
                                       cfg->configDir,
                                       cfg->autostartDir,
923
                                       0,
924
                                       cfg->caps,
925 926
                                       libxl_driver->xmlopt,
                                       1 << VIR_DOMAIN_VIRT_XEN,
927
                                       NULL, NULL) < 0)
J
Jim Fehlig 已提交
928 929
        goto error;

930 931
    virDomainObjListForEach(libxl_driver->domains, libxlDomainManagedSaveLoad,
                            libxl_driver);
932

J
Jim Fehlig 已提交
933 934 935
    return 0;

error:
936
    libxlStateCleanup();
937
    return -1;
J
Jim Fehlig 已提交
938 939
}

940 941 942 943 944 945 946 947 948 949
static void
libxlStateAutoStart(void)
{
    if (!libxl_driver)
        return;

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

J
Jim Fehlig 已提交
950
static int
951
libxlStateReload(void)
J
Jim Fehlig 已提交
952
{
953 954
    libxlDriverConfigPtr cfg;

J
Jim Fehlig 已提交
955 956 957
    if (!libxl_driver)
        return 0;

958 959
    cfg = libxlDriverConfigGet(libxl_driver);

960
    virDomainObjListLoadAllConfigs(libxl_driver->domains,
961 962
                                   cfg->configDir,
                                   cfg->autostartDir,
963
                                   1,
964
                                   cfg->caps,
965 966
                                   libxl_driver->xmlopt,
                                   1 << VIR_DOMAIN_VIRT_XEN,
967 968
                                   NULL, libxl_driver);

969 970
    virDomainObjListForEach(libxl_driver->domains, libxlAutostartDomain,
                            libxl_driver);
971

972
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
973 974 975 976 977
    return 0;
}


static virDrvOpenStatus
978 979 980
libxlConnectOpen(virConnectPtr conn,
                 virConnectAuthPtr auth ATTRIBUTE_UNUSED,
                 unsigned int flags)
J
Jim Fehlig 已提交
981
{
E
Eric Blake 已提交
982 983
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

J
Jim Fehlig 已提交
984 985 986 987
    if (conn->uri == NULL) {
        if (libxl_driver == NULL)
            return VIR_DRV_OPEN_DECLINED;

988
        if (!(conn->uri = virURIParse("xen:///")))
J
Jim Fehlig 已提交
989 990 991 992 993 994 995 996 997 998 999 1000
            return VIR_DRV_OPEN_ERROR;
    } else {
        /* Only xen scheme */
        if (conn->uri->scheme == NULL || STRNEQ(conn->uri->scheme, "xen"))
            return VIR_DRV_OPEN_DECLINED;

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

        /* Error if xen or libxl scheme specified but driver not started. */
        if (libxl_driver == NULL) {
1001 1002
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("libxenlight state driver is not active"));
J
Jim Fehlig 已提交
1003 1004 1005 1006 1007 1008 1009 1010
            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")) {
1011 1012 1013
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("unexpected Xen URI path '%s', try xen:///"),
                           NULLSTR(conn->uri->path));
J
Jim Fehlig 已提交
1014 1015 1016 1017
            return VIR_DRV_OPEN_ERROR;
        }
    }

1018 1019 1020
    if (virConnectOpenEnsureACL(conn) < 0)
        return VIR_DRV_OPEN_ERROR;

J
Jim Fehlig 已提交
1021 1022 1023 1024 1025 1026
    conn->privateData = libxl_driver;

    return VIR_DRV_OPEN_SUCCESS;
};

static int
1027
libxlConnectClose(virConnectPtr conn ATTRIBUTE_UNUSED)
J
Jim Fehlig 已提交
1028 1029 1030 1031 1032 1033
{
    conn->privateData = NULL;
    return 0;
}

static const char *
1034
libxlConnectGetType(virConnectPtr conn)
J
Jim Fehlig 已提交
1035
{
1036 1037 1038
    if (virConnectGetTypeEnsureACL(conn) < 0)
        return NULL;

J
Jim Fehlig 已提交
1039
    return "Xen";
J
Jim Fehlig 已提交
1040 1041 1042
}

static int
1043
libxlConnectGetVersion(virConnectPtr conn, unsigned long *version)
J
Jim Fehlig 已提交
1044 1045
{
    libxlDriverPrivatePtr driver = conn->privateData;
1046
    libxlDriverConfigPtr cfg;
J
Jim Fehlig 已提交
1047

1048 1049 1050
    if (virConnectGetVersionEnsureACL(conn) < 0)
        return 0;

1051 1052 1053
    cfg = libxlDriverConfigGet(driver);
    *version = cfg->version;
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
1054 1055 1056
    return 0;
}

1057

1058
static char *libxlConnectGetHostname(virConnectPtr conn)
1059
{
1060 1061 1062
    if (virConnectGetHostnameEnsureACL(conn) < 0)
        return NULL;

1063 1064 1065
    return virGetHostname();
}

1066 1067 1068 1069 1070 1071 1072 1073
static char *
libxlConnectGetSysinfo(virConnectPtr conn, unsigned int flags)
{
    libxlDriverPrivatePtr driver = conn->privateData;
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    virCheckFlags(0, NULL);

1074 1075 1076
    if (virConnectGetSysinfoEnsureACL(conn) < 0)
        return NULL;

1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090
    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;
    if (virBufferError(&buf)) {
        virReportOOMError();
        return NULL;
    }
    return virBufferContentAndReset(&buf);
}
1091

J
Jim Fehlig 已提交
1092
static int
1093
libxlConnectGetMaxVcpus(virConnectPtr conn, const char *type ATTRIBUTE_UNUSED)
J
Jim Fehlig 已提交
1094 1095 1096
{
    int ret;
    libxlDriverPrivatePtr driver = conn->privateData;
1097
    libxlDriverConfigPtr cfg;
J
Jim Fehlig 已提交
1098

1099 1100 1101
    if (virConnectGetMaxVcpusEnsureACL(conn) < 0)
        return -1;

1102 1103
    cfg = libxlDriverConfigGet(driver);
    ret = libxl_get_max_cpus(cfg->ctx);
J
Jim Fehlig 已提交
1104 1105 1106
    /* libxl_get_max_cpus() will return 0 if there were any failures,
       e.g. xc_physinfo() failing */
    if (ret == 0)
1107
        ret = -1;
J
Jim Fehlig 已提交
1108

1109
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
1110 1111 1112 1113 1114 1115
    return ret;
}

static int
libxlNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info)
{
1116 1117 1118
    if (virNodeGetInfoEnsureACL(conn) < 0)
        return -1;

1119
    return libxlDoNodeGetInfo(conn->privateData, info);
J
Jim Fehlig 已提交
1120 1121 1122
}

static char *
1123
libxlConnectGetCapabilities(virConnectPtr conn)
J
Jim Fehlig 已提交
1124 1125 1126
{
    libxlDriverPrivatePtr driver = conn->privateData;
    char *xml;
1127
    libxlDriverConfigPtr cfg;
J
Jim Fehlig 已提交
1128

1129 1130 1131
    if (virConnectGetCapabilitiesEnsureACL(conn) < 0)
        return NULL;

1132 1133
    cfg = libxlDriverConfigGet(driver);
    if ((xml = virCapabilitiesFormatXML(cfg->caps)) == NULL)
J
Jim Fehlig 已提交
1134 1135
        virReportOOMError();

1136
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
1137 1138 1139 1140
    return xml;
}

static int
1141
libxlConnectListDomains(virConnectPtr conn, int *ids, int nids)
J
Jim Fehlig 已提交
1142 1143 1144 1145
{
    libxlDriverPrivatePtr driver = conn->privateData;
    int n;

1146 1147 1148
    if (virConnectListDomainsEnsureACL(conn) < 0)
        return -1;

1149 1150
    n = virDomainObjListGetActiveIDs(driver->domains, ids, nids,
                                     virConnectListDomainsCheckACL, conn);
J
Jim Fehlig 已提交
1151 1152 1153 1154 1155

    return n;
}

static int
1156
libxlConnectNumOfDomains(virConnectPtr conn)
J
Jim Fehlig 已提交
1157 1158 1159 1160
{
    libxlDriverPrivatePtr driver = conn->privateData;
    int n;

1161 1162 1163
    if (virConnectNumOfDomainsEnsureACL(conn) < 0)
        return -1;

1164 1165
    n = virDomainObjListNumOfDomains(driver->domains, true,
                                     virConnectNumOfDomainsCheckACL, conn);
J
Jim Fehlig 已提交
1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177

    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;
1178
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
J
Jim Fehlig 已提交
1179 1180 1181

    virCheckFlags(VIR_DOMAIN_START_PAUSED, NULL);

1182
    if (!(def = virDomainDefParseString(xml, cfg->caps, driver->xmlopt,
1183
                                        1 << VIR_DOMAIN_VIRT_XEN,
J
Jim Fehlig 已提交
1184 1185 1186
                                        VIR_DOMAIN_XML_INACTIVE)))
        goto cleanup;

1187 1188 1189
    if (virDomainCreateXMLEnsureACL(conn, def) < 0)
        goto cleanup;

1190
    if (!(vm = virDomainObjListAdd(driver->domains, def,
1191
                                   driver->xmlopt,
1192 1193
                                   VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                   NULL)))
J
Jim Fehlig 已提交
1194 1195 1196
        goto cleanup;
    def = NULL;

1197 1198
    if (libxlVmStart(driver, vm, (flags & VIR_DOMAIN_START_PAUSED) != 0,
                     -1) < 0) {
1199
        virDomainObjListRemove(driver->domains, vm);
J
Jim Fehlig 已提交
1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210
        vm = NULL;
        goto cleanup;
    }

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

cleanup:
    virDomainDefFree(def);
    if (vm)
1211
        virObjectUnlock(vm);
1212
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
1213 1214 1215 1216 1217 1218 1219 1220 1221 1222
    return dom;
}

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

1223
    vm = virDomainObjListFindByID(driver->domains, id);
J
Jim Fehlig 已提交
1224
    if (!vm) {
1225
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
J
Jim Fehlig 已提交
1226 1227 1228
        goto cleanup;
    }

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

J
Jim Fehlig 已提交
1232 1233 1234 1235 1236 1237
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
    if (dom)
        dom->id = vm->def->id;

  cleanup:
    if (vm)
1238
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
1239 1240 1241 1242 1243 1244 1245 1246 1247 1248
    return dom;
}

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

1249
    vm = virDomainObjListFindByUUID(driver->domains, uuid);
J
Jim Fehlig 已提交
1250
    if (!vm) {
1251
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
J
Jim Fehlig 已提交
1252 1253 1254
        goto cleanup;
    }

1255 1256 1257
    if (virDomainLookupByUUIDEnsureACL(conn, vm->def) < 0)
        goto cleanup;

J
Jim Fehlig 已提交
1258 1259 1260 1261 1262 1263
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
    if (dom)
        dom->id = vm->def->id;

  cleanup:
    if (vm)
1264
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
1265 1266 1267 1268 1269 1270 1271 1272 1273 1274
    return dom;
}

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

1275
    vm = virDomainObjListFindByName(driver->domains, name);
J
Jim Fehlig 已提交
1276
    if (!vm) {
1277
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
J
Jim Fehlig 已提交
1278 1279 1280
        goto cleanup;
    }

1281 1282 1283
    if (virDomainLookupByNameEnsureACL(conn, vm->def) < 0)
        goto cleanup;

J
Jim Fehlig 已提交
1284 1285 1286 1287 1288 1289
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
    if (dom)
        dom->id = vm->def->id;

  cleanup:
    if (vm)
1290
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
1291 1292 1293
    return dom;
}

1294 1295 1296 1297
static int
libxlDomainSuspend(virDomainPtr dom)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
1298
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
1299 1300 1301 1302 1303
    virDomainObjPtr vm;
    libxlDomainObjPrivatePtr priv;
    virDomainEventPtr event = NULL;
    int ret = -1;

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

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

1310
    if (!virDomainObjIsActive(vm)) {
1311
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
1312 1313 1314 1315 1316
        goto cleanup;
    }

    priv = vm->privateData;

J
Jiri Denemark 已提交
1317
    if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_PAUSED) {
J
Jim Fehlig 已提交
1318
        if (libxl_domain_pause(priv->ctx, dom->id) != 0) {
1319 1320 1321
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Failed to suspend domain '%d' with libxenlight"),
                           dom->id);
1322 1323 1324
            goto cleanup;
        }

J
Jiri Denemark 已提交
1325
        virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER);
1326 1327 1328 1329 1330

        event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_SUSPENDED,
                                         VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
    }

1331
    if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
1332 1333 1334 1335 1336 1337
        goto cleanup;

    ret = 0;

cleanup:
    if (vm)
1338
        virObjectUnlock(vm);
1339
    if (event)
1340
        libxlDomainEventQueue(driver, event);
1341
    virObjectUnref(cfg);
1342 1343 1344 1345 1346 1347 1348 1349
    return ret;
}


static int
libxlDomainResume(virDomainPtr dom)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
1350
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
1351 1352 1353 1354 1355
    virDomainObjPtr vm;
    libxlDomainObjPrivatePtr priv;
    virDomainEventPtr event = NULL;
    int ret = -1;

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

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

1362
    if (!virDomainObjIsActive(vm)) {
1363
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
1364 1365 1366 1367 1368
        goto cleanup;
    }

    priv = vm->privateData;

J
Jiri Denemark 已提交
1369
    if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
J
Jim Fehlig 已提交
1370
        if (libxl_domain_unpause(priv->ctx, dom->id) != 0) {
1371 1372 1373
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Failed to resume domain '%d' with libxenlight"),
                           dom->id);
1374 1375 1376
            goto cleanup;
        }

J
Jiri Denemark 已提交
1377 1378
        virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
                             VIR_DOMAIN_RUNNING_UNPAUSED);
1379 1380 1381 1382 1383

        event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_RESUMED,
                                         VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
    }

1384
    if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
1385 1386 1387 1388 1389 1390
        goto cleanup;

    ret = 0;

cleanup:
    if (vm)
1391
        virObjectUnlock(vm);
1392
    if (event)
1393
        libxlDomainEventQueue(driver, event);
1394
    virObjectUnref(cfg);
1395 1396 1397
    return ret;
}

J
Jim Fehlig 已提交
1398
static int
1399
libxlDomainShutdownFlags(virDomainPtr dom, unsigned int flags)
J
Jim Fehlig 已提交
1400 1401 1402 1403 1404
{
    virDomainObjPtr vm;
    int ret = -1;
    libxlDomainObjPrivatePtr priv;

1405 1406
    virCheckFlags(0, -1);

J
Jim Fehlig 已提交
1407
    if (!(vm = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
1408 1409
        goto cleanup;

1410 1411 1412
    if (virDomainShutdownFlagsEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

J
Jim Fehlig 已提交
1413
    if (!virDomainObjIsActive(vm)) {
1414 1415
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("Domain is not running"));
J
Jim Fehlig 已提交
1416 1417 1418 1419
        goto cleanup;
    }

    priv = vm->privateData;
J
Jim Fehlig 已提交
1420
    if (libxl_domain_shutdown(priv->ctx, dom->id) != 0) {
1421 1422 1423
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to shutdown domain '%d' with libxenlight"),
                       dom->id);
J
Jim Fehlig 已提交
1424 1425 1426 1427 1428 1429 1430 1431 1432 1433
        goto cleanup;
    }

    /* vm is marked shutoff (or removed from domains list if not persistent)
     * in shutdown event handler.
     */
    ret = 0;

cleanup:
    if (vm)
1434
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
1435 1436 1437
    return ret;
}

1438 1439 1440 1441 1442 1443 1444
static int
libxlDomainShutdown(virDomainPtr dom)
{
    return libxlDomainShutdownFlags(dom, 0);
}


J
Jim Fehlig 已提交
1445
static int
E
Eric Blake 已提交
1446
libxlDomainReboot(virDomainPtr dom, unsigned int flags)
J
Jim Fehlig 已提交
1447 1448 1449 1450 1451
{
    virDomainObjPtr vm;
    int ret = -1;
    libxlDomainObjPrivatePtr priv;

E
Eric Blake 已提交
1452 1453
    virCheckFlags(0, -1);

J
Jim Fehlig 已提交
1454
    if (!(vm = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
1455 1456
        goto cleanup;

1457 1458 1459
    if (virDomainRebootEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

J
Jim Fehlig 已提交
1460
    if (!virDomainObjIsActive(vm)) {
1461 1462
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("Domain is not running"));
J
Jim Fehlig 已提交
1463 1464 1465 1466
        goto cleanup;
    }

    priv = vm->privateData;
J
Jim Fehlig 已提交
1467
    if (libxl_domain_reboot(priv->ctx, dom->id) != 0) {
1468 1469 1470
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to reboot domain '%d' with libxenlight"),
                       dom->id);
J
Jim Fehlig 已提交
1471 1472 1473 1474 1475 1476
        goto cleanup;
    }
    ret = 0;

cleanup:
    if (vm)
1477
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
1478 1479 1480 1481
    return ret;
}

static int
1482 1483
libxlDomainDestroyFlags(virDomainPtr dom,
                        unsigned int flags)
J
Jim Fehlig 已提交
1484 1485 1486 1487
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
1488
    virDomainEventPtr event = NULL;
J
Jim Fehlig 已提交
1489

1490 1491
    virCheckFlags(0, -1);

J
Jim Fehlig 已提交
1492
    if (!(vm = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
1493 1494
        goto cleanup;

1495 1496 1497
    if (virDomainDestroyFlagsEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

J
Jim Fehlig 已提交
1498
    if (!virDomainObjIsActive(vm)) {
1499 1500
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("Domain is not running"));
J
Jim Fehlig 已提交
1501 1502 1503
        goto cleanup;
    }

1504 1505 1506
    event = virDomainEventNewFromObj(vm,VIR_DOMAIN_EVENT_STOPPED,
                                     VIR_DOMAIN_EVENT_STOPPED_DESTROYED);

J
Jim Fehlig 已提交
1507
    if (libxlVmReap(driver, vm, VIR_DOMAIN_SHUTOFF_DESTROYED) != 0) {
1508 1509
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to destroy domain '%d'"), dom->id);
J
Jim Fehlig 已提交
1510 1511 1512 1513
        goto cleanup;
    }

    if (!vm->persistent) {
1514
        virDomainObjListRemove(driver->domains, vm);
J
Jim Fehlig 已提交
1515 1516 1517 1518 1519 1520 1521
        vm = NULL;
    }

    ret = 0;

cleanup:
    if (vm)
1522
        virObjectUnlock(vm);
1523 1524
    if (event)
        libxlDomainEventQueue(driver, event);
J
Jim Fehlig 已提交
1525 1526 1527
    return ret;
}

1528 1529 1530 1531 1532 1533
static int
libxlDomainDestroy(virDomainPtr dom)
{
    return libxlDomainDestroyFlags(dom, 0);
}

1534 1535 1536 1537 1538 1539
static char *
libxlDomainGetOSType(virDomainPtr dom)
{
    virDomainObjPtr vm;
    char *type = NULL;

J
Jim Fehlig 已提交
1540
    if (!(vm = libxlDomObjFromDomain(dom)))
1541 1542
        goto cleanup;

1543 1544 1545 1546 1547
    if (virDomainGetOSTypeEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

    if (VIR_STRDUP(type, vm->def->os.type) < 0)
        goto cleanup;
1548 1549 1550

cleanup:
    if (vm)
1551
        virObjectUnlock(vm);
1552 1553 1554
    return type;
}

1555
static unsigned long long
1556 1557 1558
libxlDomainGetMaxMemory(virDomainPtr dom)
{
    virDomainObjPtr vm;
1559
    unsigned long long ret = 0;
1560

J
Jim Fehlig 已提交
1561
    if (!(vm = libxlDomObjFromDomain(dom)))
1562
        goto cleanup;
1563 1564 1565 1566

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

1567 1568 1569 1570
    ret = vm->def->mem.max_balloon;

cleanup:
    if (vm)
1571
        virObjectUnlock(vm);
1572 1573 1574 1575
    return ret;
}

static int
1576
libxlDomainSetMemoryFlags(virDomainPtr dom, unsigned long newmem,
1577 1578 1579
                          unsigned int flags)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
1580
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
1581 1582
    libxlDomainObjPrivatePtr priv;
    virDomainObjPtr vm;
1583 1584
    virDomainDefPtr persistentDef = NULL;
    bool isActive;
1585 1586 1587
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_MEM_LIVE |
1588 1589
                  VIR_DOMAIN_MEM_CONFIG |
                  VIR_DOMAIN_MEM_MAXIMUM, -1);
1590

J
Jim Fehlig 已提交
1591
    if (!(vm = libxlDomObjFromDomain(dom)))
1592 1593
        goto cleanup;

1594 1595 1596
    if (virDomainSetMemoryFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
        goto cleanup;

1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609
    isActive = virDomainObjIsActive(vm);

    if (flags == VIR_DOMAIN_MEM_CURRENT) {
        if (isActive)
            flags = VIR_DOMAIN_MEM_LIVE;
        else
            flags = VIR_DOMAIN_MEM_CONFIG;
    }
    if (flags == VIR_DOMAIN_MEM_MAXIMUM) {
        if (isActive)
            flags = VIR_DOMAIN_MEM_LIVE | VIR_DOMAIN_MEM_MAXIMUM;
        else
            flags = VIR_DOMAIN_MEM_CONFIG | VIR_DOMAIN_MEM_MAXIMUM;
1610 1611
    }

1612
    if (!isActive && (flags & VIR_DOMAIN_MEM_LIVE)) {
1613 1614
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("cannot set memory on an inactive domain"));
1615 1616 1617 1618 1619
        goto cleanup;
    }

    if (flags & VIR_DOMAIN_MEM_CONFIG) {
        if (!vm->persistent) {
1620 1621
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                           _("cannot change persistent config of a transient domain"));
1622 1623
            goto cleanup;
        }
1624
        if (!(persistentDef = virDomainObjGetPersistentDef(cfg->caps,
1625
                                                           driver->xmlopt,
1626
                                                           vm)))
1627 1628 1629
            goto cleanup;
    }

1630 1631
    if (flags & VIR_DOMAIN_MEM_MAXIMUM) {
        /* resize the maximum memory */
1632

1633 1634
        if (flags & VIR_DOMAIN_MEM_LIVE) {
            priv = vm->privateData;
J
Jim Fehlig 已提交
1635
            if (libxl_domain_setmaxmem(priv->ctx, dom->id, newmem) < 0) {
1636 1637 1638
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("Failed to set maximum memory for domain '%d'"
                                 " with libxenlight"), dom->id);
1639 1640 1641 1642 1643 1644 1645 1646 1647 1648
                goto cleanup;
            }
        }

        if (flags & VIR_DOMAIN_MEM_CONFIG) {
            /* Help clang 2.8 decipher the logic flow.  */
            sa_assert(persistentDef);
            persistentDef->mem.max_balloon = newmem;
            if (persistentDef->mem.cur_balloon > newmem)
                persistentDef->mem.cur_balloon = newmem;
1649
            ret = virDomainSaveConfig(cfg->configDir, persistentDef);
1650 1651 1652
            goto cleanup;
        }

1653 1654
    } else {
        /* resize the current memory */
1655

1656
        if (newmem > vm->def->mem.max_balloon) {
1657 1658
            virReportError(VIR_ERR_INVALID_ARG, "%s",
                           _("cannot set memory higher than max memory"));
1659 1660 1661 1662 1663
            goto cleanup;
        }

        if (flags & VIR_DOMAIN_MEM_LIVE) {
            priv = vm->privateData;
J
Jim Fehlig 已提交
1664
            if (libxl_set_memory_target(priv->ctx, dom->id, newmem, 0,
1665
                                        /* force */ 1) < 0) {
1666 1667 1668
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("Failed to set memory for domain '%d'"
                                 " with libxenlight"), dom->id);
1669 1670 1671 1672 1673 1674 1675
                goto cleanup;
            }
        }

        if (flags & VIR_DOMAIN_MEM_CONFIG) {
            sa_assert(persistentDef);
            persistentDef->mem.cur_balloon = newmem;
1676
            ret = virDomainSaveConfig(cfg->configDir, persistentDef);
1677 1678
            goto cleanup;
        }
1679 1680
    }

1681 1682
    ret = 0;

1683 1684
cleanup:
    if (vm)
1685
        virObjectUnlock(vm);
1686
    virObjectUnref(cfg);
1687 1688 1689 1690 1691 1692 1693 1694 1695
    return ret;
}

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

1696 1697 1698 1699 1700 1701
static int
libxlDomainSetMaxMemory(virDomainPtr dom, unsigned long memory)
{
    return libxlDomainSetMemoryFlags(dom, memory, VIR_DOMAIN_MEM_MAXIMUM);
}

J
Jim Fehlig 已提交
1702 1703 1704 1705
static int
libxlDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info)
{
    virDomainObjPtr vm;
1706
    libxl_dominfo d_info;
1707
    libxlDomainObjPrivatePtr priv;
J
Jim Fehlig 已提交
1708 1709
    int ret = -1;

J
Jim Fehlig 已提交
1710
    if (!(vm = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
1711 1712
        goto cleanup;

1713 1714 1715
    if (virDomainGetInfoEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

1716
    priv = vm->privateData;
1717 1718 1719
    if (!virDomainObjIsActive(vm)) {
        info->cpuTime = 0;
        info->memory = vm->def->mem.cur_balloon;
1720
        info->maxMem = vm->def->mem.max_balloon;
1721
    } else {
1722
        if (libxl_domain_info(priv->ctx, &d_info, dom->id) != 0) {
1723 1724
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("libxl_domain_info failed for domain '%d'"), dom->id);
1725 1726 1727 1728
            goto cleanup;
        }
        info->cpuTime = d_info.cpu_time;
        info->memory = d_info.current_memkb;
1729
        info->maxMem = d_info.max_memkb;
1730 1731
    }

J
Jiri Denemark 已提交
1732
    info->state = virDomainObjGetState(vm, NULL);
J
Jim Fehlig 已提交
1733 1734 1735 1736 1737
    info->nrVirtCpu = vm->def->vcpus;
    ret = 0;

  cleanup:
    if (vm)
1738
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
1739 1740 1741
    return ret;
}

1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752
static int
libxlDomainGetState(virDomainPtr dom,
                    int *state,
                    int *reason,
                    unsigned int flags)
{
    virDomainObjPtr vm;
    int ret = -1;

    virCheckFlags(0, -1);

J
Jim Fehlig 已提交
1753
    if (!(vm = libxlDomObjFromDomain(dom)))
1754 1755
        goto cleanup;

1756 1757 1758
    if (virDomainGetStateEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

J
Jiri Denemark 已提交
1759
    *state = virDomainObjGetState(vm, reason);
1760 1761 1762 1763
    ret = 0;

  cleanup:
    if (vm)
1764
        virObjectUnlock(vm);
1765 1766 1767
    return ret;
}

1768 1769
/* This internal function expects the driver lock to already be held on
 * entry and the vm must be active. */
1770
static int
1771 1772
libxlDoDomainSave(libxlDriverPrivatePtr driver, virDomainObjPtr vm,
                  const char *to)
1773
{
1774
    libxlDomainObjPrivatePtr priv = vm->privateData;
1775 1776 1777 1778
    libxlSavefileHeader hdr;
    virDomainEventPtr event = NULL;
    char *xml = NULL;
    uint32_t xml_len;
1779
    int fd = -1;
1780 1781 1782
    int ret = -1;

    if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
1783 1784 1785
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("Domain '%d' has to be running because libxenlight will"
                         " suspend it"), vm->def->id);
1786 1787 1788 1789
        goto cleanup;
    }

    if ((fd = virFileOpenAs(to, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR,
L
Laine Stump 已提交
1790
                            -1, -1, 0)) < 0) {
1791 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805
        virReportSystemError(-fd,
                             _("Failed to create domain save file '%s'"), to);
        goto cleanup;
    }

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

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

    if (safewrite(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) {
1806 1807
        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                       _("Failed to write save file header"));
1808 1809 1810 1811
        goto cleanup;
    }

    if (safewrite(fd, xml, xml_len) != xml_len) {
1812 1813
        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                       _("Failed to write xml description"));
1814 1815 1816
        goto cleanup;
    }

J
Jim Fehlig 已提交
1817
    if (libxl_domain_suspend(priv->ctx, vm->def->id, fd, 0, NULL) != 0) {
1818 1819 1820
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to save domain '%d' with libxenlight"),
                       vm->def->id);
1821 1822 1823 1824 1825 1826
        goto cleanup;
    }

    event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_SAVED);

J
Jim Fehlig 已提交
1827
    if (libxlVmReap(driver, vm, VIR_DOMAIN_SHUTOFF_SAVED) != 0) {
1828 1829
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to destroy domain '%d'"), vm->def->id);
1830 1831 1832
        goto cleanup;
    }

1833
    vm->hasManagedSave = true;
1834 1835 1836 1837 1838 1839 1840 1841 1842 1843 1844 1845
    ret = 0;

cleanup:
    VIR_FREE(xml);
    if (VIR_CLOSE(fd) < 0)
        virReportSystemError(errno, "%s", _("cannot close file"));
    if (event)
        libxlDomainEventQueue(driver, event);
    return ret;
}

static int
1846 1847
libxlDomainSaveFlags(virDomainPtr dom, const char *to, const char *dxml,
                     unsigned int flags)
1848
{
1849 1850
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    virDomainObjPtr vm;
1851 1852
    int ret = -1;

1853 1854
    virCheckFlags(0, -1);
    if (dxml) {
1855 1856
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
1857 1858 1859
        return -1;
    }

J
Jim Fehlig 已提交
1860
    if (!(vm = libxlDomObjFromDomain(dom)))
1861 1862
        goto cleanup;

1863 1864 1865
    if (virDomainSaveFlagsEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

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

1871 1872 1873 1874
    if (libxlDoDomainSave(driver, vm, to) < 0)
        goto cleanup;

    if (!vm->persistent) {
1875
        virDomainObjListRemove(driver->domains, vm);
1876 1877 1878 1879
        vm = NULL;
    }

    ret = 0;
1880

1881 1882
cleanup:
    if (vm)
1883
        virObjectUnlock(vm);
1884 1885
    return ret;
}
1886

1887
static int
1888 1889 1890 1891 1892 1893 1894 1895
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)
1896 1897
{
    libxlDriverPrivatePtr driver = conn->privateData;
1898
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
1899 1900 1901 1902 1903
    virDomainObjPtr vm = NULL;
    virDomainDefPtr def = NULL;
    libxlSavefileHeader hdr;
    int fd = -1;
    int ret = -1;
1904

1905
    virCheckFlags(VIR_DOMAIN_SAVE_PAUSED, -1);
1906
    if (dxml) {
1907 1908
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
1909 1910 1911
        return -1;
    }

1912 1913 1914
    /* Lock the driver until domain def is read from the saved
       image and a virDomainObj is created and locked.
    */
1915
    libxlDriverLock(driver);
1916

1917
    fd = libxlSaveImageOpen(driver, cfg, from, &def, &hdr);
1918
    if (fd < 0)
1919
        goto cleanup_unlock;
1920

1921
    if (virDomainRestoreFlagsEnsureACL(conn, def) < 0)
1922
        goto cleanup_unlock;
1923

1924
    if (!(vm = virDomainObjListAdd(driver->domains, def,
1925
                                   driver->xmlopt,
1926 1927 1928
                                   VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
                                   VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                   NULL)))
1929
        goto cleanup_unlock;
1930

1931
    libxlDriverUnlock(driver);
1932 1933
    def = NULL;

1934 1935
    ret = libxlVmStart(driver, vm, (flags & VIR_DOMAIN_SAVE_PAUSED) != 0, fd);
    if (ret < 0 && !vm->persistent) {
1936
        virDomainObjListRemove(driver->domains, vm);
1937 1938 1939 1940
        vm = NULL;
    }

cleanup:
1941 1942
    if (VIR_CLOSE(fd) < 0)
        virReportSystemError(errno, "%s", _("cannot close file"));
1943 1944
    virDomainDefFree(def);
    if (vm)
1945
        virObjectUnlock(vm);
1946
    virObjectUnref(cfg);
1947
    return ret;
1948 1949 1950 1951

cleanup_unlock:
    libxlDriverUnlock(driver);
    goto cleanup;
1952 1953
}

1954 1955 1956 1957 1958 1959
static int
libxlDomainRestore(virConnectPtr conn, const char *from)
{
    return libxlDomainRestoreFlags(conn, from, NULL, 0);
}

1960
static int
1961
libxlDomainCoreDump(virDomainPtr dom, const char *to, unsigned int flags)
1962 1963 1964 1965 1966 1967 1968 1969 1970 1971
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    libxlDomainObjPrivatePtr priv;
    virDomainObjPtr vm;
    virDomainEventPtr event = NULL;
    bool paused = false;
    int ret = -1;

    virCheckFlags(VIR_DUMP_LIVE | VIR_DUMP_CRASH, -1);

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

1975 1976 1977
    if (virDomainCoreDumpEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

1978
    if (!virDomainObjIsActive(vm)) {
1979
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
1980 1981 1982 1983 1984 1985 1986
        goto cleanup;
    }

    priv = vm->privateData;

    if (!(flags & VIR_DUMP_LIVE) &&
        virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
J
Jim Fehlig 已提交
1987
        if (libxl_domain_pause(priv->ctx, dom->id) != 0) {
1988 1989 1990 1991
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Before dumping core, failed to suspend domain '%d'"
                             " with libxenlight"),
                           dom->id);
1992 1993 1994 1995 1996 1997
            goto cleanup;
        }
        virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_DUMP);
        paused = true;
    }

J
Jim Fehlig 已提交
1998
    if (libxl_domain_core_dump(priv->ctx, dom->id, to, NULL) != 0) {
1999 2000 2001
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to dump core of domain '%d' with libxenlight"),
                       dom->id);
2002 2003 2004 2005
        goto cleanup_unpause;
    }

    if (flags & VIR_DUMP_CRASH) {
J
Jim Fehlig 已提交
2006
        if (libxlVmReap(driver, vm, VIR_DOMAIN_SHUTOFF_CRASHED) != 0) {
2007 2008
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Failed to destroy domain '%d'"), dom->id);
2009
            goto cleanup_unpause;
2010 2011 2012 2013
        }

        event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
                                         VIR_DOMAIN_EVENT_STOPPED_CRASHED);
J
Jim Fehlig 已提交
2014 2015 2016 2017
        if (!vm->persistent) {
            virDomainObjListRemove(driver->domains, vm);
            vm = NULL;
        }
2018 2019 2020 2021 2022
    }

    ret = 0;

cleanup_unpause:
J
Jim Fehlig 已提交
2023
    if (vm && virDomainObjIsActive(vm) && paused) {
J
Jim Fehlig 已提交
2024
        if (libxl_domain_unpause(priv->ctx, dom->id) != 0) {
2025 2026 2027
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("After dumping core, failed to resume domain '%d' with"
                             " libxenlight"), dom->id);
2028 2029 2030 2031 2032 2033 2034
        } else {
            virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
                                 VIR_DOMAIN_RUNNING_UNPAUSED);
        }
    }
cleanup:
    if (vm)
2035
        virObjectUnlock(vm);
2036
    if (event)
2037 2038 2039 2040
        libxlDomainEventQueue(driver, event);
    return ret;
}

2041 2042 2043 2044 2045 2046 2047 2048 2049 2050
static int
libxlDomainManagedSave(virDomainPtr dom, unsigned int flags)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    virDomainObjPtr vm = NULL;
    char *name = NULL;
    int ret = -1;

    virCheckFlags(0, -1);

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

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

2057
    if (!virDomainObjIsActive(vm)) {
2058
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
2059 2060
        goto cleanup;
    }
2061
    if (!vm->persistent) {
2062 2063
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("cannot do managed save for transient domain"));
2064 2065
        goto cleanup;
    }
2066 2067 2068 2069 2070 2071 2072

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

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

2073 2074 2075 2076
    if (libxlDoDomainSave(driver, vm, name) < 0)
        goto cleanup;

    if (!vm->persistent) {
2077
        virDomainObjListRemove(driver->domains, vm);
2078 2079 2080 2081
        vm = NULL;
    }

    ret = 0;
2082 2083 2084

cleanup:
    if (vm)
2085
        virObjectUnlock(vm);
2086 2087 2088 2089
    VIR_FREE(name);
    return ret;
}

2090 2091
static int
libxlDomainManagedSaveLoad(virDomainObjPtr vm,
2092 2093 2094 2095
                           void *opaque)
{
    libxlDriverPrivatePtr driver = opaque;
    char *name;
2096
    int ret = -1;
2097

2098
    virObjectLock(vm);
2099 2100 2101 2102 2103 2104

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

    vm->hasManagedSave = virFileExists(name);

2105
    ret = 0;
2106
cleanup:
2107
    virObjectUnlock(vm);
2108
    VIR_FREE(name);
2109
    return ret;
2110 2111
}

2112 2113 2114 2115 2116 2117 2118 2119
static int
libxlDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    int ret = -1;

    virCheckFlags(0, -1);

J
Jim Fehlig 已提交
2120
    if (!(vm = libxlDomObjFromDomain(dom)))
2121 2122
        goto cleanup;

2123 2124 2125
    if (virDomainHasManagedSaveImageEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

2126
    ret = vm->hasManagedSave;
2127 2128 2129

cleanup:
    if (vm)
2130
        virObjectUnlock(vm);
2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143
    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 已提交
2144
    if (!(vm = libxlDomObjFromDomain(dom)))
2145 2146
        goto cleanup;

2147 2148 2149
    if (virDomainManagedSaveRemoveEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

2150 2151 2152 2153 2154
    name = libxlDomainManagedSavePath(driver, vm);
    if (name == NULL)
        goto cleanup;

    ret = unlink(name);
2155
    vm->hasManagedSave = false;
2156 2157 2158 2159

cleanup:
    VIR_FREE(name);
    if (vm)
2160
        virObjectUnlock(vm);
2161 2162 2163
    return ret;
}

2164 2165 2166 2167 2168
static int
libxlDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
                         unsigned int flags)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
2169
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
2170 2171 2172
    libxlDomainObjPrivatePtr priv;
    virDomainDefPtr def;
    virDomainObjPtr vm;
J
Jim Fehlig 已提交
2173
    libxl_bitmap map;
2174 2175
    uint8_t *bitmask = NULL;
    unsigned int maplen;
2176 2177
    size_t i;
    unsigned int pos;
2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189
    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)) {
2190 2191
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid flag combination: (0x%x)"), flags);
2192 2193 2194 2195
        return -1;
    }

    if (!nvcpus) {
2196
        virReportError(VIR_ERR_INVALID_ARG, "%s", _("nvcpus is zero"));
2197 2198 2199
        return -1;
    }

J
Jim Fehlig 已提交
2200
    if (!(vm = libxlDomObjFromDomain(dom)))
2201 2202
        goto cleanup;

2203 2204 2205
    if (virDomainSetVcpusFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
        goto cleanup;

2206
    if (!virDomainObjIsActive(vm) && (flags & VIR_DOMAIN_VCPU_LIVE)) {
2207 2208
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("cannot set vcpus on an inactive domain"));
2209 2210 2211 2212
        goto cleanup;
    }

    if (!vm->persistent && (flags & VIR_DOMAIN_VCPU_CONFIG)) {
2213 2214
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("cannot change persistent config of a transient domain"));
2215 2216 2217
        goto cleanup;
    }

2218
    if ((max = libxlConnectGetMaxVcpus(dom->conn, NULL)) < 0) {
2219 2220
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("could not determine max vcpus for the domain"));
2221 2222 2223 2224 2225 2226 2227 2228
        goto cleanup;
    }

    if (!(flags & VIR_DOMAIN_VCPU_MAXIMUM) && vm->def->maxvcpus < max) {
        max = vm->def->maxvcpus;
    }

    if (nvcpus > max) {
2229 2230 2231
        virReportError(VIR_ERR_INVALID_ARG,
                       _("requested vcpus is greater than max allowable"
                         " vcpus for the domain: %d > %d"), nvcpus, max);
2232 2233 2234 2235 2236
        goto cleanup;
    }

    priv = vm->privateData;

2237
    if (!(def = virDomainObjGetPersistentDef(cfg->caps, driver->xmlopt, vm)))
2238 2239
        goto cleanup;

E
Eric Blake 已提交
2240
    maplen = VIR_CPU_MAPLEN(nvcpus);
2241
    if (VIR_ALLOC_N(bitmask, maplen) < 0)
2242 2243 2244
        goto cleanup;

    for (i = 0; i < nvcpus; ++i) {
E
Eric Blake 已提交
2245
        pos = i / 8;
2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263
        bitmask[pos] |= 1 << (i % 8);
    }

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

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

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

    case VIR_DOMAIN_VCPU_LIVE:
J
Jim Fehlig 已提交
2264
        if (libxl_set_vcpuonline(priv->ctx, dom->id, &map) != 0) {
2265 2266 2267
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Failed to set vcpus for domain '%d'"
                             " with libxenlight"), dom->id);
2268 2269 2270 2271 2272
            goto cleanup;
        }
        break;

    case VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG:
J
Jim Fehlig 已提交
2273
        if (libxl_set_vcpuonline(priv->ctx, dom->id, &map) != 0) {
2274 2275 2276
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Failed to set vcpus for domain '%d'"
                             " with libxenlight"), dom->id);
2277 2278 2279 2280 2281 2282 2283 2284 2285
            goto cleanup;
        }
        def->vcpus = nvcpus;
        break;
    }

    ret = 0;

    if (flags & VIR_DOMAIN_VCPU_CONFIG)
2286
        ret = virDomainSaveConfig(cfg->configDir, def);
2287 2288 2289 2290

cleanup:
    VIR_FREE(bitmask);
     if (vm)
2291
        virObjectUnlock(vm);
2292
     virObjectUnref(cfg);
2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307
    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;
2308
    bool active;
2309 2310 2311 2312 2313

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

J
Jim Fehlig 已提交
2314
    if (!(vm = libxlDomObjFromDomain(dom)))
2315 2316
        goto cleanup;

2317 2318 2319
    if (virDomainGetVcpusFlagsEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

2320 2321 2322 2323 2324 2325 2326 2327 2328
    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)) {
2329 2330
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid flag combination: (0x%x)"), flags);
2331 2332 2333
        return -1;
    }

2334
    if (flags & VIR_DOMAIN_VCPU_LIVE) {
2335
        if (!active) {
2336 2337
            virReportError(VIR_ERR_OPERATION_INVALID,
                           "%s", _("Domain is not running"));
2338 2339 2340 2341
            goto cleanup;
        }
        def = vm->def;
    } else {
2342
        if (!vm->persistent) {
2343 2344
            virReportError(VIR_ERR_OPERATION_INVALID,
                           "%s", _("domain is transient"));
2345 2346
            goto cleanup;
        }
2347 2348 2349 2350 2351 2352 2353
        def = vm->newDef ? vm->newDef : vm->def;
    }

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

cleanup:
    if (vm)
2354
        virObjectUnlock(vm);
2355 2356 2357 2358 2359 2360 2361 2362
    return ret;
}

static int
libxlDomainPinVcpu(virDomainPtr dom, unsigned int vcpu, unsigned char *cpumap,
                   int maplen)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
2363
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
2364 2365 2366
    libxlDomainObjPrivatePtr priv;
    virDomainObjPtr vm;
    int ret = -1;
J
Jim Fehlig 已提交
2367
    libxl_bitmap map;
2368

J
Jim Fehlig 已提交
2369
    if (!(vm = libxlDomObjFromDomain(dom)))
2370 2371
        goto cleanup;

2372 2373 2374
    if (virDomainPinVcpuEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

2375
    if (!virDomainObjIsActive(vm)) {
2376 2377
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("cannot pin vcpus on an inactive domain"));
2378 2379 2380 2381 2382 2383 2384
        goto cleanup;
    }

    priv = vm->privateData;

    map.size = maplen;
    map.map = cpumap;
J
Jim Fehlig 已提交
2385
    if (libxl_set_vcpuaffinity(priv->ctx, dom->id, vcpu, &map) != 0) {
2386 2387
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to pin vcpu '%d' with libxenlight"), vcpu);
2388 2389
        goto cleanup;
    }
2390

H
Hu Tao 已提交
2391
    if (!vm->def->cputune.vcpupin) {
2392
        if (VIR_ALLOC(vm->def->cputune.vcpupin) < 0)
H
Hu Tao 已提交
2393 2394 2395
            goto cleanup;
        vm->def->cputune.nvcpupin = 0;
    }
2396
    if (virDomainVcpuPinAdd(&vm->def->cputune.vcpupin,
H
Hu Tao 已提交
2397 2398 2399 2400
                            &vm->def->cputune.nvcpupin,
                            cpumap,
                            maplen,
                            vcpu) < 0) {
2401 2402
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("failed to update or add vcpupin xml"));
2403 2404 2405
        goto cleanup;
    }

2406
    if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
2407 2408
        goto cleanup;

2409 2410 2411 2412
    ret = 0;

cleanup:
    if (vm)
2413
        virObjectUnlock(vm);
2414
    virObjectUnref(cfg);
2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426 2427
    return ret;
}


static int
libxlDomainGetVcpus(virDomainPtr dom, virVcpuInfoPtr info, int maxinfo,
                    unsigned char *cpumaps, int maplen)
{
    libxlDomainObjPrivatePtr priv;
    virDomainObjPtr vm;
    int ret = -1;
    libxl_vcpuinfo *vcpuinfo;
    int maxcpu, hostcpus;
2428
    size_t i;
2429 2430
    unsigned char *cpumap;

J
Jim Fehlig 已提交
2431
    if (!(vm = libxlDomObjFromDomain(dom)))
2432 2433
        goto cleanup;

2434 2435 2436
    if (virDomainGetVcpusEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

2437
    if (!virDomainObjIsActive(vm)) {
2438
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
2439 2440 2441 2442
        goto cleanup;
    }

    priv = vm->privateData;
J
Jim Fehlig 已提交
2443
    if ((vcpuinfo = libxl_list_vcpu(priv->ctx, dom->id, &maxcpu,
2444
                                    &hostcpus)) == NULL) {
2445 2446 2447
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to list vcpus for domain '%d' with libxenlight"),
                       dom->id);
2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469
        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 已提交
2470
        libxl_vcpuinfo_dispose(&vcpuinfo[i]);
2471 2472 2473 2474 2475 2476 2477
    }
    VIR_FREE(vcpuinfo);

    ret = maxinfo;

cleanup:
    if (vm)
2478
        virObjectUnlock(vm);
2479 2480 2481
    return ret;
}

J
Jim Fehlig 已提交
2482
static char *
2483
libxlDomainGetXMLDesc(virDomainPtr dom, unsigned int flags)
J
Jim Fehlig 已提交
2484 2485 2486 2487
{
    virDomainObjPtr vm;
    char *ret = NULL;

2488 2489
    /* Flags checked by virDomainDefFormat */

J
Jim Fehlig 已提交
2490
    if (!(vm = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
2491 2492
        goto cleanup;

2493 2494 2495
    if (virDomainGetXMLDescEnsureACL(dom->conn, vm->def, flags) < 0)
        goto cleanup;

J
Jim Fehlig 已提交
2496 2497 2498 2499
    ret = virDomainDefFormat(vm->def, flags);

  cleanup:
    if (vm)
2500
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
2501 2502 2503
    return ret;
}

2504
static char *
2505 2506 2507
libxlConnectDomainXMLFromNative(virConnectPtr conn, const char * nativeFormat,
                                const char * nativeConfig,
                                unsigned int flags)
2508 2509
{
    libxlDriverPrivatePtr driver = conn->privateData;
2510
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
2511 2512 2513 2514
    virDomainDefPtr def = NULL;
    virConfPtr conf = NULL;
    char *xml = NULL;

E
Eric Blake 已提交
2515 2516
    virCheckFlags(0, NULL);

2517 2518 2519
    if (virConnectDomainXMLFromNativeEnsureACL(conn) < 0)
        goto cleanup;

2520
    if (STRNEQ(nativeFormat, LIBXL_CONFIG_FORMAT_XM)) {
2521 2522
        virReportError(VIR_ERR_INVALID_ARG,
                       _("unsupported config type %s"), nativeFormat);
2523 2524 2525 2526 2527 2528
        goto cleanup;
    }

    if (!(conf = virConfReadMem(nativeConfig, strlen(nativeConfig), 0)))
        goto cleanup;

2529
    if (!(def = xenParseXM(conf,
2530 2531
                           cfg->verInfo->xen_version_major,
                           cfg->caps))) {
2532
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("parsing xm config failed"));
2533 2534 2535 2536 2537 2538 2539 2540 2541
        goto cleanup;
    }

    xml = virDomainDefFormat(def, VIR_DOMAIN_XML_INACTIVE);

cleanup:
    virDomainDefFree(def);
    if (conf)
        virConfFree(conf);
2542
    virObjectUnref(cfg);
2543 2544 2545 2546 2547
    return xml;
}

#define MAX_CONFIG_SIZE (1024 * 65)
static char *
2548 2549 2550
libxlConnectDomainXMLToNative(virConnectPtr conn, const char * nativeFormat,
                              const char * domainXml,
                              unsigned int flags)
2551 2552
{
    libxlDriverPrivatePtr driver = conn->privateData;
2553
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
2554 2555 2556 2557 2558
    virDomainDefPtr def = NULL;
    virConfPtr conf = NULL;
    int len = MAX_CONFIG_SIZE;
    char *ret = NULL;

E
Eric Blake 已提交
2559 2560
    virCheckFlags(0, NULL);

2561 2562 2563
    if (virConnectDomainXMLToNativeEnsureACL(conn) < 0)
        goto cleanup;

2564
    if (STRNEQ(nativeFormat, LIBXL_CONFIG_FORMAT_XM)) {
2565 2566
        virReportError(VIR_ERR_INVALID_ARG,
                       _("unsupported config type %s"), nativeFormat);
2567 2568 2569
        goto cleanup;
    }

2570
    if (!(def = virDomainDefParseString(domainXml,
2571
                                        cfg->caps, driver->xmlopt,
M
Matthias Bolte 已提交
2572
                                        1 << VIR_DOMAIN_VIRT_XEN, 0)))
2573 2574
        goto cleanup;

2575
    if (!(conf = xenFormatXM(conn, def, cfg->verInfo->xen_version_major)))
2576 2577
        goto cleanup;

2578
    if (VIR_ALLOC_N(ret, len) < 0)
2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589
        goto cleanup;

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

cleanup:
    virDomainDefFree(def);
    if (conf)
        virConfFree(conf);
2590
    virObjectUnref(cfg);
2591 2592 2593
    return ret;
}

J
Jim Fehlig 已提交
2594
static int
2595 2596
libxlConnectListDefinedDomains(virConnectPtr conn,
                               char **const names, int nnames)
J
Jim Fehlig 已提交
2597 2598 2599 2600
{
    libxlDriverPrivatePtr driver = conn->privateData;
    int n;

2601 2602 2603
    if (virConnectListDefinedDomainsEnsureACL(conn) < 0)
        return -1;

2604 2605
    n = virDomainObjListGetInactiveNames(driver->domains, names, nnames,
                                         virConnectListDefinedDomainsCheckACL, conn);
J
Jim Fehlig 已提交
2606 2607 2608 2609
    return n;
}

static int
2610
libxlConnectNumOfDefinedDomains(virConnectPtr conn)
J
Jim Fehlig 已提交
2611 2612 2613 2614
{
    libxlDriverPrivatePtr driver = conn->privateData;
    int n;

2615 2616 2617
    if (virConnectNumOfDefinedDomainsEnsureACL(conn) < 0)
        return -1;

2618
    n = virDomainObjListNumOfDomains(driver->domains, false,
2619 2620
                                     virConnectNumOfDefinedDomainsCheckACL,
                                     conn);
J
Jim Fehlig 已提交
2621 2622 2623 2624 2625
    return n;
}

static int
libxlDomainCreateWithFlags(virDomainPtr dom,
E
Eric Blake 已提交
2626
                           unsigned int flags)
J
Jim Fehlig 已提交
2627 2628 2629 2630 2631 2632 2633
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_START_PAUSED, -1);

J
Jim Fehlig 已提交
2634
    if (!(vm = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
2635 2636
        goto cleanup;

2637 2638 2639
    if (virDomainCreateWithFlagsEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

J
Jim Fehlig 已提交
2640
    if (virDomainObjIsActive(vm)) {
2641 2642
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("Domain is already running"));
J
Jim Fehlig 已提交
2643 2644 2645
        goto cleanup;
    }

2646
    ret = libxlVmStart(driver, vm, (flags & VIR_DOMAIN_START_PAUSED) != 0, -1);
J
Jim Fehlig 已提交
2647 2648 2649

cleanup:
    if (vm)
2650
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
2651 2652 2653 2654 2655 2656 2657 2658 2659 2660 2661 2662 2663
    return ret;
}

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

static virDomainPtr
libxlDomainDefineXML(virConnectPtr conn, const char *xml)
{
    libxlDriverPrivatePtr driver = conn->privateData;
2664
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
J
Jim Fehlig 已提交
2665 2666 2667
    virDomainDefPtr def = NULL;
    virDomainObjPtr vm = NULL;
    virDomainPtr dom = NULL;
2668
    virDomainEventPtr event = NULL;
2669
    virDomainDefPtr oldDef = NULL;
J
Jim Fehlig 已提交
2670

2671
    /* Lock the driver until the virDomainObj is created and locked */
J
Jim Fehlig 已提交
2672
    libxlDriverLock(driver);
2673
    if (!(def = virDomainDefParseString(xml, cfg->caps, driver->xmlopt,
M
Matthias Bolte 已提交
2674
                                        1 << VIR_DOMAIN_VIRT_XEN,
J
Jim Fehlig 已提交
2675
                                        VIR_DOMAIN_XML_INACTIVE)))
2676
        goto cleanup_unlock;
J
Jim Fehlig 已提交
2677

2678
    if (virDomainDefineXMLEnsureACL(conn, def) < 0)
2679
        goto cleanup_unlock;
2680

2681
    if (!(vm = virDomainObjListAdd(driver->domains, def,
2682
                                   driver->xmlopt,
2683 2684
                                   0,
                                   &oldDef)))
2685 2686
        goto cleanup_unlock;

J
Jim Fehlig 已提交
2687 2688
    def = NULL;
    vm->persistent = 1;
2689
    libxlDriverUnlock(driver);
J
Jim Fehlig 已提交
2690

2691
    if (virDomainSaveConfig(cfg->configDir,
J
Jim Fehlig 已提交
2692
                            vm->newDef ? vm->newDef : vm->def) < 0) {
2693
        virDomainObjListRemove(driver->domains, vm);
J
Jim Fehlig 已提交
2694 2695 2696 2697 2698 2699 2700 2701
        vm = NULL;
        goto cleanup;
    }

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

2702
    event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_DEFINED,
2703
                                     !oldDef ?
2704 2705 2706
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED :
                                     VIR_DOMAIN_EVENT_DEFINED_UPDATED);

J
Jim Fehlig 已提交
2707 2708
cleanup:
    virDomainDefFree(def);
2709
    virDomainDefFree(oldDef);
J
Jim Fehlig 已提交
2710
    if (vm)
2711
        virObjectUnlock(vm);
2712 2713
    if (event)
        libxlDomainEventQueue(driver, event);
2714
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
2715
    return dom;
2716 2717 2718 2719

cleanup_unlock:
    libxlDriverUnlock(driver);
    goto cleanup;
J
Jim Fehlig 已提交
2720 2721 2722
}

static int
2723 2724
libxlDomainUndefineFlags(virDomainPtr dom,
                         unsigned int flags)
J
Jim Fehlig 已提交
2725 2726
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
2727
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
J
Jim Fehlig 已提交
2728
    virDomainObjPtr vm;
2729
    virDomainEventPtr event = NULL;
2730
    char *name = NULL;
J
Jim Fehlig 已提交
2731 2732
    int ret = -1;

2733 2734
    virCheckFlags(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE, -1);

J
Jim Fehlig 已提交
2735
    if (!(vm = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
2736 2737
        goto cleanup;

2738 2739 2740
    if (virDomainUndefineFlagsEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

J
Jim Fehlig 已提交
2741
    if (!vm->persistent) {
2742 2743
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("cannot undefine transient domain"));
J
Jim Fehlig 已提交
2744 2745 2746
        goto cleanup;
    }

2747 2748 2749 2750 2751 2752 2753
    name = libxlDomainManagedSavePath(driver, vm);
    if (name == NULL)
        goto cleanup;

    if (virFileExists(name)) {
        if (flags & VIR_DOMAIN_UNDEFINE_MANAGED_SAVE) {
            if (unlink(name) < 0) {
2754 2755
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("Failed to remove domain managed save image"));
2756 2757 2758
                goto cleanup;
            }
        } else {
2759 2760 2761
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                           _("Refusing to undefine while domain managed "
                             "save image exists"));
2762 2763 2764 2765
            goto cleanup;
        }
    }

2766
    if (virDomainDeleteConfig(cfg->configDir, cfg->autostartDir, vm) < 0)
J
Jim Fehlig 已提交
2767 2768
        goto cleanup;

2769 2770 2771
    event = virDomainEventNewFromObj(vm, VIR_DOMAIN_EVENT_UNDEFINED,
                                     VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);

2772 2773 2774
    if (virDomainObjIsActive(vm)) {
        vm->persistent = 0;
    } else {
2775
        virDomainObjListRemove(driver->domains, vm);
2776 2777 2778
        vm = NULL;
    }

J
Jim Fehlig 已提交
2779 2780 2781
    ret = 0;

  cleanup:
2782
    VIR_FREE(name);
J
Jim Fehlig 已提交
2783
    if (vm)
2784
        virObjectUnlock(vm);
2785 2786
    if (event)
        libxlDomainEventQueue(driver, event);
2787
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
2788 2789 2790
    return ret;
}

2791 2792 2793 2794 2795 2796
static int
libxlDomainUndefine(virDomainPtr dom)
{
    return libxlDomainUndefineFlags(dom, 0);
}

2797 2798 2799 2800 2801 2802
static int
libxlDomainChangeEjectableMedia(libxlDomainObjPrivatePtr priv,
                                virDomainObjPtr vm, virDomainDiskDefPtr disk)
{
    virDomainDiskDefPtr origdisk = NULL;
    libxl_device_disk x_disk;
2803
    size_t i;
2804 2805
    int ret = -1;

2806
    for (i = 0; i < vm->def->ndisks; i++) {
2807 2808 2809 2810 2811 2812 2813 2814
        if (vm->def->disks[i]->bus == disk->bus &&
            STREQ(vm->def->disks[i]->dst, disk->dst)) {
            origdisk = vm->def->disks[i];
            break;
        }
    }

    if (!origdisk) {
2815 2816 2817
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("No device with bus '%s' and target '%s'"),
                       virDomainDiskBusTypeToString(disk->bus), disk->dst);
2818 2819 2820 2821
        goto cleanup;
    }

    if (origdisk->device != VIR_DOMAIN_DISK_DEVICE_CDROM) {
2822 2823 2824
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Removable media not supported for %s device"),
                       virDomainDiskDeviceTypeToString(disk->device));
2825 2826 2827
        return -1;
    }

J
Jim Fehlig 已提交
2828
    if (libxlMakeDisk(disk, &x_disk) < 0)
2829 2830
        goto cleanup;

J
Jim Fehlig 已提交
2831
    if ((ret = libxl_cdrom_insert(priv->ctx, vm->def->id, &x_disk, NULL)) < 0) {
2832 2833 2834
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("libxenlight failed to change media for disk '%s'"),
                       disk->dst);
2835 2836 2837 2838 2839 2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865
        goto cleanup;
    }

    VIR_FREE(origdisk->src);
    origdisk->src = disk->src;
    disk->src = NULL;
    origdisk->type = disk->type;


    virDomainDiskDefFree(disk);

    ret = 0;

cleanup:
    return ret;
}

static int
libxlDomainAttachDeviceDiskLive(libxlDomainObjPrivatePtr priv,
                                virDomainObjPtr vm, virDomainDeviceDefPtr dev)
{
    virDomainDiskDefPtr l_disk = dev->data.disk;
    libxl_device_disk x_disk;
    int ret = -1;

    switch (l_disk->device)  {
        case VIR_DOMAIN_DISK_DEVICE_CDROM:
            ret = libxlDomainChangeEjectableMedia(priv, vm, l_disk);
            break;
        case VIR_DOMAIN_DISK_DEVICE_DISK:
            if (l_disk->bus == VIR_DOMAIN_DISK_BUS_XEN) {
2866
                if (virDomainDiskIndexByName(vm->def, l_disk->dst, true) >= 0) {
2867 2868
                    virReportError(VIR_ERR_OPERATION_FAILED,
                                   _("target %s already exists"), l_disk->dst);
2869 2870 2871 2872
                    goto cleanup;
                }

                if (!l_disk->src) {
2873 2874
                    virReportError(VIR_ERR_INTERNAL_ERROR,
                                   "%s", _("disk source path is missing"));
2875 2876 2877
                    goto cleanup;
                }

2878
                if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks+1) < 0)
2879 2880
                    goto cleanup;

J
Jim Fehlig 已提交
2881
                if (libxlMakeDisk(l_disk, &x_disk) < 0)
2882 2883
                    goto cleanup;

J
Jim Fehlig 已提交
2884 2885
                if ((ret = libxl_device_disk_add(priv->ctx, vm->def->id,
                                                &x_disk, NULL)) < 0) {
2886 2887 2888
                    virReportError(VIR_ERR_INTERNAL_ERROR,
                                   _("libxenlight failed to attach disk '%s'"),
                                   l_disk->dst);
2889 2890 2891 2892 2893 2894
                    goto cleanup;
                }

                virDomainDiskInsertPreAlloced(vm->def, l_disk);

            } else {
2895 2896 2897
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("disk bus '%s' cannot be hotplugged."),
                               virDomainDiskBusTypeToString(l_disk->bus));
2898 2899 2900
            }
            break;
        default:
2901 2902 2903
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("disk device type '%s' cannot be hotplugged"),
                           virDomainDiskDeviceTypeToString(l_disk->device));
2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916
            break;
    }

cleanup:
    return ret;
}

static int
libxlDomainDetachDeviceDiskLive(libxlDomainObjPrivatePtr priv,
                                virDomainObjPtr vm, virDomainDeviceDefPtr dev)
{
    virDomainDiskDefPtr l_disk = NULL;
    libxl_device_disk x_disk;
2917
    int idx;
2918 2919 2920 2921 2922 2923
    int ret = -1;

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

2924 2925 2926
                if ((idx = virDomainDiskIndexByName(vm->def,
                                                    dev->data.disk->dst,
                                                    false)) < 0) {
2927 2928
                    virReportError(VIR_ERR_OPERATION_FAILED,
                                   _("disk %s not found"), dev->data.disk->dst);
2929 2930 2931
                    goto cleanup;
                }

2932
                l_disk = vm->def->disks[idx];
2933

J
Jim Fehlig 已提交
2934
                if (libxlMakeDisk(l_disk, &x_disk) < 0)
2935 2936
                    goto cleanup;

J
Jim Fehlig 已提交
2937 2938
                if ((ret = libxl_device_disk_remove(priv->ctx, vm->def->id,
                                                    &x_disk, NULL)) < 0) {
2939 2940 2941
                    virReportError(VIR_ERR_INTERNAL_ERROR,
                                   _("libxenlight failed to detach disk '%s'"),
                                   l_disk->dst);
2942 2943 2944
                    goto cleanup;
                }

2945
                virDomainDiskRemove(vm->def, idx);
2946 2947 2948
                virDomainDiskDefFree(l_disk);

            } else {
2949 2950 2951
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("disk bus '%s' cannot be hot unplugged."),
                               virDomainDiskBusTypeToString(dev->data.disk->bus));
2952 2953 2954
            }
            break;
        default:
2955 2956 2957
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("device type '%s' cannot hot unplugged"),
                           virDomainDiskDeviceTypeToString(dev->data.disk->device));
2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975 2976 2977 2978
            break;
    }

cleanup:
    return ret;
}

static int
libxlDomainAttachDeviceLive(libxlDomainObjPrivatePtr priv, virDomainObjPtr vm,
                            virDomainDeviceDefPtr dev)
{
    int ret = -1;

    switch (dev->type) {
        case VIR_DOMAIN_DEVICE_DISK:
            ret = libxlDomainAttachDeviceDiskLive(priv, vm, dev);
            if (!ret)
                dev->data.disk = NULL;
            break;

        default:
2979 2980 2981
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("device type '%s' cannot be attached"),
                           virDomainDeviceTypeToString(dev->type));
2982 2983 2984 2985 2986 2987 2988 2989 2990 2991 2992 2993 2994 2995
            break;
    }

    return ret;
}

static int
libxlDomainAttachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev)
{
    virDomainDiskDefPtr disk;

    switch (dev->type) {
        case VIR_DOMAIN_DEVICE_DISK:
            disk = dev->data.disk;
2996
            if (virDomainDiskIndexByName(vmdef, disk->dst, true) >= 0) {
2997 2998
                virReportError(VIR_ERR_INVALID_ARG,
                               _("target %s already exists."), disk->dst);
2999 3000
                return -1;
            }
3001
            if (virDomainDiskInsert(vmdef, disk))
3002 3003 3004 3005 3006 3007
                return -1;
            /* vmdef has the pointer. Generic codes for vmdef will do all jobs */
            dev->data.disk = NULL;
            break;

        default:
3008 3009
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("persistent attach of device is not supported"));
3010 3011 3012 3013 3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026
            return -1;
    }
    return 0;
}

static int
libxlDomainDetachDeviceLive(libxlDomainObjPrivatePtr priv, virDomainObjPtr vm,
                            virDomainDeviceDefPtr dev)
{
    int ret = -1;

    switch (dev->type) {
        case VIR_DOMAIN_DEVICE_DISK:
            ret = libxlDomainDetachDeviceDiskLive(priv, vm, dev);
            break;

        default:
3027 3028 3029
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("device type '%s' cannot be detached"),
                           virDomainDeviceTypeToString(dev->type));
3030 3031 3032 3033 3034 3035 3036 3037 3038
            break;
    }

    return ret;
}

static int
libxlDomainDetachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev)
{
3039
    virDomainDiskDefPtr disk, detach;
3040 3041 3042 3043 3044
    int ret = -1;

    switch (dev->type) {
        case VIR_DOMAIN_DEVICE_DISK:
            disk = dev->data.disk;
3045
            if (!(detach = virDomainDiskRemoveByName(vmdef, disk->dst))) {
3046 3047
                virReportError(VIR_ERR_INVALID_ARG,
                               _("no target device %s"), disk->dst);
3048 3049
                break;
            }
3050
            virDomainDiskDefFree(detach);
3051 3052 3053
            ret = 0;
            break;
        default:
3054 3055
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("persistent detach of device is not supported"));
3056 3057 3058 3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078
            break;
    }

    return ret;
}

static int
libxlDomainUpdateDeviceLive(libxlDomainObjPrivatePtr priv,
                            virDomainObjPtr vm, virDomainDeviceDefPtr dev)
{
    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:
                    ret = libxlDomainChangeEjectableMedia(priv, vm, disk);
                    if (ret == 0)
                        dev->data.disk = NULL;
                    break;
                default:
3079 3080 3081
                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                                   _("disk bus '%s' cannot be updated."),
                                   virDomainDiskBusTypeToString(disk->bus));
3082 3083 3084 3085
                    break;
            }
            break;
        default:
3086 3087 3088
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("device type '%s' cannot be updated"),
                           virDomainDeviceTypeToString(dev->type));
3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099
            break;
    }

    return ret;
}

static int
libxlDomainUpdateDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev)
{
    virDomainDiskDefPtr orig;
    virDomainDiskDefPtr disk;
3100
    int idx;
3101 3102 3103 3104 3105
    int ret = -1;

    switch (dev->type) {
        case VIR_DOMAIN_DEVICE_DISK:
            disk = dev->data.disk;
3106
            if ((idx = virDomainDiskIndexByName(vmdef, disk->dst, false)) < 0) {
3107 3108
                virReportError(VIR_ERR_INVALID_ARG,
                               _("target %s doesn't exist."), disk->dst);
3109 3110
                goto cleanup;
            }
3111
            orig = vmdef->disks[idx];
3112
            if (!(orig->device == VIR_DOMAIN_DISK_DEVICE_CDROM)) {
3113 3114
                virReportError(VIR_ERR_INVALID_ARG, "%s",
                               _("this disk doesn't support update"));
3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125
                goto cleanup;
            }

            VIR_FREE(orig->src);
            orig->src = disk->src;
            orig->type = disk->type;
            if (disk->driverName) {
                VIR_FREE(orig->driverName);
                orig->driverName = disk->driverName;
                disk->driverName = NULL;
            }
3126
            orig->format = disk->format;
3127 3128 3129
            disk->src = NULL;
            break;
        default:
3130 3131
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("persistent update of device is not supported"));
3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142
            goto cleanup;
    }

    ret = 0;

cleanup:
    return ret;
}


static int
3143 3144
libxlDomainAttachDeviceFlags(virDomainPtr dom, const char *xml,
                             unsigned int flags)
3145 3146
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
3147
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
3148 3149 3150 3151 3152 3153 3154 3155 3156
    virDomainObjPtr vm = NULL;
    virDomainDefPtr vmdef = NULL;
    virDomainDeviceDefPtr dev = NULL;
    libxlDomainObjPrivatePtr priv;
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_LIVE |
                  VIR_DOMAIN_DEVICE_MODIFY_CONFIG, -1);

J
Jim Fehlig 已提交
3157
    if (!(vm = libxlDomObjFromDomain(dom)))
3158 3159
        goto cleanup;

3160 3161 3162
    if (virDomainAttachDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
        goto cleanup;

3163 3164 3165 3166 3167 3168 3169 3170
    if (virDomainObjIsActive(vm)) {
        if (flags == VIR_DOMAIN_DEVICE_MODIFY_CURRENT)
            flags |= VIR_DOMAIN_DEVICE_MODIFY_LIVE;
    } else {
        if (flags == VIR_DOMAIN_DEVICE_MODIFY_CURRENT)
            flags |= VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
        /* check consistency between flags and the vm state */
        if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) {
3171 3172
            virReportError(VIR_ERR_OPERATION_INVALID,
                           "%s", _("Domain is not running"));
3173 3174 3175 3176 3177
            goto cleanup;
        }
    }

    if ((flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) && !vm->persistent) {
3178 3179
         virReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("cannot modify device on transient domain"));
3180 3181 3182 3183 3184 3185
         goto cleanup;
    }

    priv = vm->privateData;

    if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
3186
        if (!(dev = virDomainDeviceDefParse(xml, vm->def,
3187
                                            cfg->caps, driver->xmlopt,
3188 3189 3190 3191
                                            VIR_DOMAIN_XML_INACTIVE)))
            goto cleanup;

        /* Make a copy for updated domain. */
3192
        if (!(vmdef = virDomainObjCopyPersistentDef(vm, cfg->caps,
3193
                                                    driver->xmlopt)))
3194 3195
            goto cleanup;

3196 3197 3198
        if ((ret = libxlDomainAttachDeviceConfig(vmdef, dev)) < 0)
            goto cleanup;
    } else {
3199
        ret = 0;
3200
    }
3201 3202 3203 3204

    if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) {
        /* If dev exists it was created to modify the domain config. Free it. */
        virDomainDeviceDefFree(dev);
3205
        if (!(dev = virDomainDeviceDefParse(xml, vm->def,
3206
                                            cfg->caps, driver->xmlopt,
3207 3208 3209
                                            VIR_DOMAIN_XML_INACTIVE)))
            goto cleanup;

3210 3211 3212
        if ((ret = libxlDomainAttachDeviceLive(priv, vm, dev)) < 0)
            goto cleanup;

3213 3214 3215 3216
        /*
         * update domain status forcibly because the domain status may be
         * changed even if we attach the device failed.
         */
3217
        if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
3218 3219 3220 3221 3222
            ret = -1;
    }

    /* Finally, if no error until here, we can save config. */
    if (!ret && (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG)) {
3223
        ret = virDomainSaveConfig(cfg->configDir, vmdef);
3224
        if (!ret) {
3225
            virDomainObjAssignDef(vm, vmdef, false, NULL);
3226 3227 3228 3229 3230 3231 3232 3233
            vmdef = NULL;
        }
    }

cleanup:
    virDomainDefFree(vmdef);
    virDomainDeviceDefFree(dev);
    if (vm)
3234
        virObjectUnlock(vm);
3235
    virObjectUnref(cfg);
3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249
    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)
{
3250
    libxlDriverPrivatePtr driver = dom->conn->privateData;
3251
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
3252 3253 3254 3255 3256 3257 3258 3259 3260
    virDomainObjPtr vm = NULL;
    virDomainDefPtr vmdef = NULL;
    virDomainDeviceDefPtr dev = NULL;
    libxlDomainObjPrivatePtr priv;
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_LIVE |
                  VIR_DOMAIN_DEVICE_MODIFY_CONFIG, -1);

J
Jim Fehlig 已提交
3261
    if (!(vm = libxlDomObjFromDomain(dom)))
3262 3263
        goto cleanup;

3264 3265 3266
    if (virDomainDetachDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
        goto cleanup;

3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290
    if (virDomainObjIsActive(vm)) {
        if (flags == VIR_DOMAIN_DEVICE_MODIFY_CURRENT)
            flags |= VIR_DOMAIN_DEVICE_MODIFY_LIVE;
    } else {
        if (flags == VIR_DOMAIN_DEVICE_MODIFY_CURRENT)
            flags |= VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
        /* check consistency between flags and the vm state */
        if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) {
            virReportError(VIR_ERR_OPERATION_INVALID,
                           "%s", _("Domain is not running"));
            goto cleanup;
        }
    }

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

    priv = vm->privateData;

    if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
        if (!(dev = virDomainDeviceDefParse(xml, vm->def,
3291
                                            cfg->caps, driver->xmlopt,
3292 3293 3294 3295
                                            VIR_DOMAIN_XML_INACTIVE)))
            goto cleanup;

        /* Make a copy for updated domain. */
3296
        if (!(vmdef = virDomainObjCopyPersistentDef(vm, cfg->caps,
3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309
                                                    driver->xmlopt)))
            goto cleanup;

        if ((ret = libxlDomainDetachDeviceConfig(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,
3310
                                            cfg->caps, driver->xmlopt,
3311 3312 3313 3314 3315 3316 3317 3318 3319 3320
                                            VIR_DOMAIN_XML_INACTIVE)))
            goto cleanup;

        if ((ret = libxlDomainDetachDeviceLive(priv, vm, dev)) < 0)
            goto cleanup;

        /*
         * update domain status forcibly because the domain status may be
         * changed even if we attach the device failed.
         */
3321
        if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
3322 3323 3324 3325 3326
            ret = -1;
    }

    /* Finally, if no error until here, we can save config. */
    if (!ret && (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG)) {
3327
        ret = virDomainSaveConfig(cfg->configDir, vmdef);
3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338
        if (!ret) {
            virDomainObjAssignDef(vm, vmdef, false, NULL);
            vmdef = NULL;
        }
    }

cleanup:
    virDomainDefFree(vmdef);
    virDomainDeviceDefFree(dev);
    if (vm)
        virObjectUnlock(vm);
3339
    virObjectUnref(cfg);
3340
    return ret;
3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353
}

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)
{
3354
    libxlDriverPrivatePtr driver = dom->conn->privateData;
3355
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
3356 3357 3358 3359 3360 3361 3362 3363 3364
    virDomainObjPtr vm = NULL;
    virDomainDefPtr vmdef = NULL;
    virDomainDeviceDefPtr dev = NULL;
    libxlDomainObjPrivatePtr priv;
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_DEVICE_MODIFY_LIVE |
                  VIR_DOMAIN_DEVICE_MODIFY_CONFIG, -1);

J
Jim Fehlig 已提交
3365
    if (!(vm = libxlDomObjFromDomain(dom)))
3366 3367
        goto cleanup;

3368 3369 3370
    if (virDomainUpdateDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
        goto cleanup;

3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394
    if (virDomainObjIsActive(vm)) {
        if (flags == VIR_DOMAIN_DEVICE_MODIFY_CURRENT)
            flags |= VIR_DOMAIN_DEVICE_MODIFY_LIVE;
    } else {
        if (flags == VIR_DOMAIN_DEVICE_MODIFY_CURRENT)
            flags |= VIR_DOMAIN_DEVICE_MODIFY_CONFIG;
        /* check consistency between flags and the vm state */
        if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) {
            virReportError(VIR_ERR_OPERATION_INVALID,
                           "%s", _("Domain is not running"));
            goto cleanup;
        }
    }

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

    priv = vm->privateData;

    if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
        if (!(dev = virDomainDeviceDefParse(xml, vm->def,
3395
                                            cfg->caps, driver->xmlopt,
3396 3397 3398 3399
                                            VIR_DOMAIN_XML_INACTIVE)))
            goto cleanup;

        /* Make a copy for updated domain. */
3400
        if (!(vmdef = virDomainObjCopyPersistentDef(vm, cfg->caps,
3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413
                                                    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,
3414
                                            cfg->caps, driver->xmlopt,
3415 3416 3417 3418 3419 3420 3421 3422 3423 3424
                                            VIR_DOMAIN_XML_INACTIVE)))
            goto cleanup;

        if ((ret = libxlDomainUpdateDeviceLive(priv, vm, dev)) < 0)
            goto cleanup;

        /*
         * update domain status forcibly because the domain status may be
         * changed even if we attach the device failed.
         */
3425
        if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
3426 3427 3428 3429 3430
            ret = -1;
    }

    /* Finally, if no error until here, we can save config. */
    if (!ret && (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG)) {
3431
        ret = virDomainSaveConfig(cfg->configDir, vmdef);
3432 3433 3434 3435 3436 3437 3438 3439 3440 3441 3442
        if (!ret) {
            virDomainObjAssignDef(vm, vmdef, false, NULL);
            vmdef = NULL;
        }
    }

cleanup:
    virDomainDefFree(vmdef);
    virDomainDeviceDefFree(dev);
    if (vm)
        virObjectUnlock(vm);
3443
    virObjectUnref(cfg);
3444
    return ret;
3445 3446
}

3447 3448 3449 3450 3451
static unsigned long long
libxlNodeGetFreeMemory(virConnectPtr conn)
{
    libxl_physinfo phy_info;
    libxlDriverPrivatePtr driver = conn->privateData;
3452 3453
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
    unsigned long long ret = 0;
3454

3455
    if (virNodeGetFreeMemoryEnsureACL(conn) < 0)
3456
        goto cleanup;
3457

3458
    if (libxl_get_physinfo(cfg->ctx, &phy_info)) {
3459 3460
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("libxl_get_physinfo_info failed"));
3461
        goto cleanup;
3462 3463
    }

3464 3465 3466 3467 3468
    ret = phy_info.free_pages * cfg->verInfo->pagesize;

cleanup:
    virObjectUnref(cfg);
    return ret;
3469 3470
}

3471 3472 3473 3474 3475 3476 3477 3478 3479 3480
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;
3481
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
3482 3483

    if (virNodeGetCellsFreeMemoryEnsureACL(conn) < 0)
3484
        goto cleanup;
3485

3486
    numa_info = libxl_get_numainfo(cfg->ctx, &nr_nodes);
3487
    if (numa_info == NULL || nr_nodes == 0) {
3488 3489 3490
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("libxl_get_numainfo failed"));
        goto cleanup;
3491 3492 3493
    }

    /* Check/sanitize the cell range */
3494
    if (startCell >= nr_nodes) {
3495 3496
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("start cell %d out of range (0-%d)"),
3497
                       startCell, nr_nodes - 1);
3498 3499 3500
        goto cleanup;
    }
    lastCell = startCell + maxCells - 1;
3501 3502
    if (lastCell >= nr_nodes)
        lastCell = nr_nodes - 1;
3503 3504 3505 3506 3507 3508 3509

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

3511 3512 3513 3514
    ret = numCells;

cleanup:
    libxl_numainfo_list_free(numa_info, nr_nodes);
3515
    virObjectUnref(cfg);
3516 3517 3518
    return ret;
}

3519
static int
3520 3521 3522
libxlConnectDomainEventRegister(virConnectPtr conn,
                                virConnectDomainEventCallback callback, void *opaque,
                                virFreeCallback freecb)
3523 3524 3525 3526
{
    libxlDriverPrivatePtr driver = conn->privateData;
    int ret;

3527 3528 3529
    if (virConnectDomainEventRegisterEnsureACL(conn) < 0)
        return -1;

3530 3531 3532
    ret = virDomainEventStateRegister(conn,
                                      driver->domainEventState,
                                      callback, opaque, freecb);
3533 3534 3535 3536 3537 3538

    return ret;
}


static int
3539 3540
libxlConnectDomainEventDeregister(virConnectPtr conn,
                                  virConnectDomainEventCallback callback)
3541 3542 3543 3544
{
    libxlDriverPrivatePtr driver = conn->privateData;
    int ret;

3545 3546 3547
    if (virConnectDomainEventDeregisterEnsureACL(conn) < 0)
        return -1;

3548 3549 3550
    ret = virDomainEventStateDeregister(conn,
                                        driver->domainEventState,
                                        callback);
3551 3552 3553 3554

    return ret;
}

3555 3556 3557 3558 3559 3560
static int
libxlDomainGetAutostart(virDomainPtr dom, int *autostart)
{
    virDomainObjPtr vm;
    int ret = -1;

J
Jim Fehlig 已提交
3561
    if (!(vm = libxlDomObjFromDomain(dom)))
3562 3563
        goto cleanup;

3564 3565 3566
    if (virDomainGetAutostartEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

3567 3568 3569 3570 3571
    *autostart = vm->autostart;
    ret = 0;

cleanup:
    if (vm)
3572
        virObjectUnlock(vm);
3573 3574 3575 3576 3577 3578 3579
    return ret;
}

static int
libxlDomainSetAutostart(virDomainPtr dom, int autostart)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
3580
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
3581 3582 3583 3584
    virDomainObjPtr vm;
    char *configFile = NULL, *autostartLink = NULL;
    int ret = -1;

J
Jim Fehlig 已提交
3585
    if (!(vm = libxlDomObjFromDomain(dom)))
3586 3587
        goto cleanup;

3588 3589 3590
    if (virDomainSetAutostartEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

3591
    if (!vm->persistent) {
3592 3593
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("cannot set autostart for transient domain"));
3594 3595 3596 3597 3598 3599
        goto cleanup;
    }

    autostart = (autostart != 0);

    if (vm->autostart != autostart) {
3600
        if (!(configFile = virDomainConfigFile(cfg->configDir, vm->def->name)))
3601
            goto cleanup;
3602
        if (!(autostartLink = virDomainConfigFile(cfg->autostartDir, vm->def->name)))
3603 3604 3605
            goto cleanup;

        if (autostart) {
3606
            if (virFileMakePath(cfg->autostartDir) < 0) {
3607
                virReportSystemError(errno,
3608
                                     _("cannot create autostart directory %s"),
3609
                                     cfg->autostartDir);
3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635
                goto cleanup;
            }

            if (symlink(configFile, autostartLink) < 0) {
                virReportSystemError(errno,
                                     _("Failed to create symlink '%s to '%s'"),
                                     autostartLink, configFile);
                goto cleanup;
            }
        } else {
            if (unlink(autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) {
                virReportSystemError(errno,
                                     _("Failed to delete symlink '%s'"),
                                     autostartLink);
                goto cleanup;
            }
        }

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

cleanup:
    VIR_FREE(configFile);
    VIR_FREE(autostartLink);
    if (vm)
3636
        virObjectUnlock(vm);
3637
    virObjectUnref(cfg);
3638 3639 3640
    return ret;
}

3641 3642 3643 3644 3645 3646
static char *
libxlDomainGetSchedulerType(virDomainPtr dom, int *nparams)
{
    libxlDomainObjPrivatePtr priv;
    virDomainObjPtr vm;
    char * ret = NULL;
3647
    const char *name = NULL;
J
Jim Fehlig 已提交
3648
    libxl_scheduler sched_id;
3649

J
Jim Fehlig 已提交
3650
    if (!(vm = libxlDomObjFromDomain(dom)))
3651 3652
        goto cleanup;

3653 3654 3655
    if (virDomainGetSchedulerTypeEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

3656
    if (!virDomainObjIsActive(vm)) {
3657
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
3658 3659 3660 3661
        goto cleanup;
    }

    priv = vm->privateData;
J
Jim Fehlig 已提交
3662
    sched_id = libxl_get_scheduler(priv->ctx);
3663

3664 3665
    if (nparams)
        *nparams = 0;
3666
    switch (sched_id) {
J
Jim Fehlig 已提交
3667
    case LIBXL_SCHEDULER_SEDF:
3668
        name = "sedf";
3669
        break;
J
Jim Fehlig 已提交
3670
    case LIBXL_SCHEDULER_CREDIT:
3671
        name = "credit";
3672 3673
        if (nparams)
            *nparams = XEN_SCHED_CREDIT_NPARAM;
3674
        break;
J
Jim Fehlig 已提交
3675
    case LIBXL_SCHEDULER_CREDIT2:
3676
        name = "credit2";
3677
        break;
J
Jim Fehlig 已提交
3678
    case LIBXL_SCHEDULER_ARINC653:
3679
        name = "arinc653";
3680 3681
        break;
    default:
J
Jim Fehlig 已提交
3682 3683 3684
        virReportError(VIR_ERR_INTERNAL_ERROR,
                   _("Failed to get scheduler id for domain '%d'"
                     " with libxenlight"), dom->id);
3685 3686 3687
        goto cleanup;
    }

3688
    ignore_value(VIR_STRDUP(ret, name));
3689 3690 3691

cleanup:
    if (vm)
3692
        virObjectUnlock(vm);
3693 3694 3695
    return ret;
}

3696
static int
3697 3698 3699 3700
libxlDomainGetSchedulerParametersFlags(virDomainPtr dom,
                                       virTypedParameterPtr params,
                                       int *nparams,
                                       unsigned int flags)
3701 3702 3703
{
    libxlDomainObjPrivatePtr priv;
    virDomainObjPtr vm;
J
Jim Fehlig 已提交
3704 3705
    libxl_domain_sched_params sc_info;
    libxl_scheduler sched_id;
3706 3707
    int ret = -1;

3708 3709 3710 3711
    virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);

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

J
Jim Fehlig 已提交
3713
    if (!(vm = libxlDomObjFromDomain(dom)))
3714 3715
        goto cleanup;

3716 3717 3718
    if (virDomainGetSchedulerParametersFlagsEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

3719
    if (!virDomainObjIsActive(vm)) {
J
Jim Fehlig 已提交
3720 3721
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("Domain is not running"));
3722 3723 3724 3725 3726
        goto cleanup;
    }

    priv = vm->privateData;

J
Jim Fehlig 已提交
3727
    sched_id = libxl_get_scheduler(priv->ctx);
3728

J
Jim Fehlig 已提交
3729
    if (sched_id != LIBXL_SCHEDULER_CREDIT) {
3730 3731
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Only 'credit' scheduler is supported"));
3732 3733 3734
        goto cleanup;
    }

J
Jim Fehlig 已提交
3735
    if (libxl_domain_sched_params_get(priv->ctx, dom->id, &sc_info) != 0) {
3736 3737 3738
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to get scheduler parameters for domain '%d'"
                         " with libxenlight"), dom->id);
3739 3740 3741
        goto cleanup;
    }

3742 3743
    if (virTypedParameterAssign(&params[0], VIR_DOMAIN_SCHEDULER_WEIGHT,
                                VIR_TYPED_PARAM_UINT, sc_info.weight) < 0)
3744 3745
        goto cleanup;

3746
    if (*nparams > 1) {
3747 3748
        if (virTypedParameterAssign(&params[0], VIR_DOMAIN_SCHEDULER_CAP,
                                    VIR_TYPED_PARAM_UINT, sc_info.cap) < 0)
3749
            goto cleanup;
3750 3751
    }

3752 3753
    if (*nparams > XEN_SCHED_CREDIT_NPARAM)
        *nparams = XEN_SCHED_CREDIT_NPARAM;
3754 3755 3756 3757
    ret = 0;

cleanup:
    if (vm)
3758
        virObjectUnlock(vm);
3759 3760 3761 3762
    return ret;
}

static int
3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773
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)
3774 3775 3776
{
    libxlDomainObjPrivatePtr priv;
    virDomainObjPtr vm;
J
Jim Fehlig 已提交
3777
    libxl_domain_sched_params sc_info;
3778
    int sched_id;
3779
    size_t i;
3780 3781
    int ret = -1;

3782
    virCheckFlags(0, -1);
3783 3784 3785 3786 3787 3788
    if (virTypedParamsValidate(params, nparams,
                               VIR_DOMAIN_SCHEDULER_WEIGHT,
                               VIR_TYPED_PARAM_UINT,
                               VIR_DOMAIN_SCHEDULER_CAP,
                               VIR_TYPED_PARAM_UINT,
                               NULL) < 0)
3789
        return -1;
3790

J
Jim Fehlig 已提交
3791
    if (!(vm = libxlDomObjFromDomain(dom)))
3792 3793
        goto cleanup;

3794 3795 3796
    if (virDomainSetSchedulerParametersFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
        goto cleanup;

3797
    if (!virDomainObjIsActive(vm)) {
3798
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
3799 3800 3801 3802 3803
        goto cleanup;
    }

    priv = vm->privateData;

J
Jim Fehlig 已提交
3804
    sched_id = libxl_get_scheduler(priv->ctx);
3805

J
Jim Fehlig 已提交
3806
    if (sched_id != LIBXL_SCHEDULER_CREDIT) {
3807 3808
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Only 'credit' scheduler is supported"));
3809 3810 3811
        goto cleanup;
    }

J
Jim Fehlig 已提交
3812
    if (libxl_domain_sched_params_get(priv->ctx, dom->id, &sc_info) != 0) {
3813 3814 3815
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to get scheduler parameters for domain '%d'"
                         " with libxenlight"), dom->id);
3816 3817 3818 3819
        goto cleanup;
    }

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

3822
        if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_WEIGHT))
3823
            sc_info.weight = params[i].value.ui;
3824
        else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_CAP))
3825 3826 3827
            sc_info.cap = params[i].value.ui;
    }

J
Jim Fehlig 已提交
3828
    if (libxl_domain_sched_params_set(priv->ctx, dom->id, &sc_info) != 0) {
3829 3830 3831
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to set scheduler parameters for domain '%d'"
                         " with libxenlight"), dom->id);
3832 3833 3834 3835 3836 3837 3838
        goto cleanup;
    }

    ret = 0;

cleanup:
    if (vm)
3839
        virObjectUnlock(vm);
3840 3841 3842
    return ret;
}

B
Bamvor Jian Zhang 已提交
3843 3844 3845 3846 3847 3848 3849 3850 3851 3852 3853 3854 3855 3856 3857 3858 3859 3860 3861 3862 3863 3864

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;
    char *console = NULL;

    virCheckFlags(VIR_DOMAIN_CONSOLE_FORCE, -1);

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

J
Jim Fehlig 已提交
3865
    if (!(vm = libxlDomObjFromDomain(dom)))
B
Bamvor Jian Zhang 已提交
3866 3867 3868 3869 3870 3871 3872 3873 3874 3875 3876 3877 3878 3879 3880 3881 3882 3883 3884 3885 3886 3887 3888 3889 3890 3891 3892 3893 3894 3895 3896 3897 3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918 3919 3920 3921
        goto cleanup;

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

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

    priv = vm->privateData;

    if (vm->def->nserials)
        chr = vm->def->serials[0];

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

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

    ret = libxl_primary_console_get_tty(priv->ctx, vm->def->id, &console);
    if (ret)
        goto cleanup;

    if (VIR_STRDUP(chr->source.data.file.path, console) < 0)
        goto cleanup;

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

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

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

3922 3923 3924 3925 3926 3927 3928
static int
libxlDomainSetSchedulerParameters(virDomainPtr dom, virTypedParameterPtr params,
                                  int nparams)
{
    return libxlDomainSetSchedulerParametersFlags(dom, params, nparams, 0);
}

3929 3930 3931 3932 3933 3934 3935 3936 3937 3938 3939 3940 3941 3942 3943 3944 3945 3946 3947 3948 3949 3950 3951 3952 3953 3954 3955 3956 3957 3958
/* 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)
{
    libxlDomainObjPrivatePtr priv;
    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;

J
Jim Fehlig 已提交
3959
    if (!(vm = libxlDomObjFromDomain(dom)))
3960 3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973 3974 3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987 3988 3989 3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057
        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;
    }

    priv = vm->privateData;

    libxl_bitmap_init(&nodemap);

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

        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 */
            if (libxl_node_bitmap_alloc(priv->ctx, &nodemap, 0) ||
                !(nodes = virBitmapNew(libxl_get_max_nodes(priv->ctx)))) {
                virReportOOMError();
                goto cleanup;
            }

            rc = libxl_domain_get_nodeaffinity(priv->ctx,
                                               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;
                }
            }

            nodeset = virBitmapFormat(nodes);
            if (!nodeset && VIR_STRDUP(nodeset, "") < 0)
                goto cleanup;

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

            nodeset = NULL;

            break;

        default:
            break;
        }
    }

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

cleanup:
    VIR_FREE(nodeset);
    virBitmapFree(nodes);
    libxl_bitmap_dispose(&nodemap);
    if (vm)
        virObjectUnlock(vm);
    return ret;
}
#endif

J
Jim Fehlig 已提交
4058 4059 4060 4061 4062 4063
static int
libxlDomainIsActive(virDomainPtr dom)
{
    virDomainObjPtr obj;
    int ret = -1;

J
Jim Fehlig 已提交
4064
    if (!(obj = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
4065
        goto cleanup;
4066 4067 4068 4069

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

J
Jim Fehlig 已提交
4070 4071 4072 4073
    ret = virDomainObjIsActive(obj);

  cleanup:
    if (obj)
4074
        virObjectUnlock(obj);
J
Jim Fehlig 已提交
4075 4076 4077 4078 4079 4080 4081 4082 4083
    return ret;
}

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

J
Jim Fehlig 已提交
4084
    if (!(obj = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
4085
        goto cleanup;
4086 4087 4088 4089

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

J
Jim Fehlig 已提交
4090 4091 4092 4093
    ret = obj->persistent;

  cleanup:
    if (obj)
4094
        virObjectUnlock(obj);
J
Jim Fehlig 已提交
4095 4096 4097
    return ret;
}

4098 4099 4100 4101 4102 4103
static int
libxlDomainIsUpdated(virDomainPtr dom)
{
    virDomainObjPtr vm;
    int ret = -1;

J
Jim Fehlig 已提交
4104
    if (!(vm = libxlDomObjFromDomain(dom)))
4105
        goto cleanup;
4106 4107 4108 4109

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

4110 4111 4112 4113
    ret = vm->updated;

cleanup:
    if (vm)
4114
        virObjectUnlock(vm);
4115 4116 4117
    return ret;
}

4118
static int
4119 4120 4121
libxlConnectDomainEventRegisterAny(virConnectPtr conn, virDomainPtr dom, int eventID,
                                   virConnectDomainEventGenericCallback callback,
                                   void *opaque, virFreeCallback freecb)
4122 4123 4124 4125
{
    libxlDriverPrivatePtr driver = conn->privateData;
    int ret;

4126 4127 4128
    if (virConnectDomainEventRegisterAnyEnsureACL(conn) < 0)
        return -1;

4129 4130 4131 4132
    if (virDomainEventStateRegisterID(conn,
                                      driver->domainEventState,
                                      dom, eventID, callback, opaque,
                                      freecb, &ret) < 0)
4133
        ret = -1;
4134 4135 4136 4137 4138 4139

    return ret;
}


static int
4140
libxlConnectDomainEventDeregisterAny(virConnectPtr conn, int callbackID)
4141 4142 4143 4144
{
    libxlDriverPrivatePtr driver = conn->privateData;
    int ret;

4145 4146 4147
    if (virConnectDomainEventDeregisterAnyEnsureACL(conn) < 0)
        return -1;

4148 4149 4150
    ret = virDomainEventStateDeregisterID(conn,
                                          driver->domainEventState,
                                          callbackID);
4151 4152 4153 4154

    return ret;
}

J
Jim Fehlig 已提交
4155

4156
static int
4157
libxlConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED)
4158 4159 4160 4161
{
    return 1;
}

4162
static int
4163 4164 4165
libxlConnectListAllDomains(virConnectPtr conn,
                           virDomainPtr **domains,
                           unsigned int flags)
4166 4167 4168 4169
{
    libxlDriverPrivatePtr driver = conn->privateData;
    int ret = -1;

O
Osier Yang 已提交
4170
    virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
4171

4172 4173 4174
    if (virConnectListAllDomainsEnsureACL(conn) < 0)
        return -1;

4175 4176
    ret = virDomainObjListExport(driver->domains, conn, domains,
                                 virConnectListAllDomainsCheckACL, flags);
4177 4178 4179 4180

    return ret;
}

4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193 4194
/* Which features are supported by this driver? */
static int
libxlConnectSupportsFeature(virConnectPtr conn, int feature)
{
    if (virConnectSupportsFeatureEnsureACL(conn) < 0)
        return -1;

    switch (feature) {
    case VIR_DRV_FEATURE_TYPED_PARAM_STRING:
        return 1;
    default:
        return 0;
    }
}
4195

4196

J
Jim Fehlig 已提交
4197
static virDriver libxlDriver = {
4198 4199
    .no = VIR_DRV_LIBXL,
    .name = "xenlight",
4200 4201 4202 4203
    .connectOpen = libxlConnectOpen, /* 0.9.0 */
    .connectClose = libxlConnectClose, /* 0.9.0 */
    .connectGetType = libxlConnectGetType, /* 0.9.0 */
    .connectGetVersion = libxlConnectGetVersion, /* 0.9.0 */
4204
    .connectGetHostname = libxlConnectGetHostname, /* 0.9.0 */
4205
    .connectGetSysinfo = libxlConnectGetSysinfo, /* 1.1.0 */
4206
    .connectGetMaxVcpus = libxlConnectGetMaxVcpus, /* 0.9.0 */
4207
    .nodeGetInfo = libxlNodeGetInfo, /* 0.9.0 */
4208 4209 4210 4211
    .connectGetCapabilities = libxlConnectGetCapabilities, /* 0.9.0 */
    .connectListDomains = libxlConnectListDomains, /* 0.9.0 */
    .connectNumOfDomains = libxlConnectNumOfDomains, /* 0.9.0 */
    .connectListAllDomains = libxlConnectListAllDomains, /* 0.9.13 */
4212 4213 4214 4215 4216 4217 4218
    .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 */
4219
    .domainShutdownFlags = libxlDomainShutdownFlags, /* 0.9.10 */
4220 4221
    .domainReboot = libxlDomainReboot, /* 0.9.0 */
    .domainDestroy = libxlDomainDestroy, /* 0.9.0 */
4222
    .domainDestroyFlags = libxlDomainDestroyFlags, /* 0.9.4 */
4223 4224
    .domainGetOSType = libxlDomainGetOSType, /* 0.9.0 */
    .domainGetMaxMemory = libxlDomainGetMaxMemory, /* 0.9.0 */
4225
    .domainSetMaxMemory = libxlDomainSetMaxMemory, /* 0.9.2 */
4226 4227 4228 4229
    .domainSetMemory = libxlDomainSetMemory, /* 0.9.0 */
    .domainSetMemoryFlags = libxlDomainSetMemoryFlags, /* 0.9.0 */
    .domainGetInfo = libxlDomainGetInfo, /* 0.9.0 */
    .domainGetState = libxlDomainGetState, /* 0.9.2 */
4230
    .domainSave = libxlDomainSave, /* 0.9.2 */
4231
    .domainSaveFlags = libxlDomainSaveFlags, /* 0.9.4 */
4232
    .domainRestore = libxlDomainRestore, /* 0.9.2 */
4233
    .domainRestoreFlags = libxlDomainRestoreFlags, /* 0.9.4 */
4234
    .domainCoreDump = libxlDomainCoreDump, /* 0.9.2 */
4235 4236 4237 4238 4239 4240
    .domainSetVcpus = libxlDomainSetVcpus, /* 0.9.0 */
    .domainSetVcpusFlags = libxlDomainSetVcpusFlags, /* 0.9.0 */
    .domainGetVcpusFlags = libxlDomainGetVcpusFlags, /* 0.9.0 */
    .domainPinVcpu = libxlDomainPinVcpu, /* 0.9.0 */
    .domainGetVcpus = libxlDomainGetVcpus, /* 0.9.0 */
    .domainGetXMLDesc = libxlDomainGetXMLDesc, /* 0.9.0 */
4241 4242 4243 4244
    .connectDomainXMLFromNative = libxlConnectDomainXMLFromNative, /* 0.9.0 */
    .connectDomainXMLToNative = libxlConnectDomainXMLToNative, /* 0.9.0 */
    .connectListDefinedDomains = libxlConnectListDefinedDomains, /* 0.9.0 */
    .connectNumOfDefinedDomains = libxlConnectNumOfDefinedDomains, /* 0.9.0 */
4245 4246 4247 4248
    .domainCreate = libxlDomainCreate, /* 0.9.0 */
    .domainCreateWithFlags = libxlDomainCreateWithFlags, /* 0.9.0 */
    .domainDefineXML = libxlDomainDefineXML, /* 0.9.0 */
    .domainUndefine = libxlDomainUndefine, /* 0.9.0 */
4249
    .domainUndefineFlags = libxlDomainUndefineFlags, /* 0.9.4 */
4250 4251 4252 4253 4254
    .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 */
4255 4256 4257 4258
    .domainGetAutostart = libxlDomainGetAutostart, /* 0.9.0 */
    .domainSetAutostart = libxlDomainSetAutostart, /* 0.9.0 */
    .domainGetSchedulerType = libxlDomainGetSchedulerType, /* 0.9.0 */
    .domainGetSchedulerParameters = libxlDomainGetSchedulerParameters, /* 0.9.0 */
4259
    .domainGetSchedulerParametersFlags = libxlDomainGetSchedulerParametersFlags, /* 0.9.2 */
4260
    .domainSetSchedulerParameters = libxlDomainSetSchedulerParameters, /* 0.9.0 */
4261
    .domainSetSchedulerParametersFlags = libxlDomainSetSchedulerParametersFlags, /* 0.9.2 */
4262 4263 4264
#ifdef LIBXL_HAVE_DOMAIN_NODEAFFINITY
    .domainGetNumaParameters = libxlDomainGetNumaParameters, /* 1.1.1 */
#endif
4265
    .nodeGetFreeMemory = libxlNodeGetFreeMemory, /* 0.9.0 */
4266
    .nodeGetCellsFreeMemory = libxlNodeGetCellsFreeMemory, /* 1.1.1 */
4267 4268
    .connectDomainEventRegister = libxlConnectDomainEventRegister, /* 0.9.0 */
    .connectDomainEventDeregister = libxlConnectDomainEventDeregister, /* 0.9.0 */
4269 4270 4271
    .domainManagedSave = libxlDomainManagedSave, /* 0.9.2 */
    .domainHasManagedSaveImage = libxlDomainHasManagedSaveImage, /* 0.9.2 */
    .domainManagedSaveRemove = libxlDomainManagedSaveRemove, /* 0.9.2 */
B
Bamvor Jian Zhang 已提交
4272
    .domainOpenConsole = libxlDomainOpenConsole, /* 1.1.2 */
4273 4274 4275
    .domainIsActive = libxlDomainIsActive, /* 0.9.0 */
    .domainIsPersistent = libxlDomainIsPersistent, /* 0.9.0 */
    .domainIsUpdated = libxlDomainIsUpdated, /* 0.9.0 */
4276 4277 4278
    .connectDomainEventRegisterAny = libxlConnectDomainEventRegisterAny, /* 0.9.0 */
    .connectDomainEventDeregisterAny = libxlConnectDomainEventDeregisterAny, /* 0.9.0 */
    .connectIsAlive = libxlConnectIsAlive, /* 0.9.8 */
4279
    .connectSupportsFeature = libxlConnectSupportsFeature, /* 1.1.1 */
J
Jim Fehlig 已提交
4280 4281 4282 4283
};

static virStateDriver libxlStateDriver = {
    .name = "LIBXL",
4284
    .stateInitialize = libxlStateInitialize,
4285
    .stateAutoStart = libxlStateAutoStart,
4286 4287
    .stateCleanup = libxlStateCleanup,
    .stateReload = libxlStateReload,
J
Jim Fehlig 已提交
4288 4289 4290 4291 4292 4293 4294 4295 4296 4297 4298 4299 4300
};


int
libxlRegister(void)
{
    if (virRegisterDriver(&libxlDriver) < 0)
        return -1;
    if (virRegisterStateDriver(&libxlStateDriver) < 0)
        return -1;

    return 0;
}