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

#include <config.h>

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

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

#define VIR_FROM_THIS VIR_FROM_LIBXL

62 63
VIR_LOG_INIT("libxl.libxl_driver");

J
Jim Fehlig 已提交
64 65 66 67 68 69
#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

70
#define LIBXL_CONFIG_FORMAT_XM "xen-xm"
71
#define LIBXL_CONFIG_FORMAT_SEXPR "xen-sxpr"
72

73 74
#define HYPERVISOR_CAPABILITIES "/proc/xen/capabilities"

75 76 77
/* Number of Xen scheduler parameters */
#define XEN_SCHED_CREDIT_NPARAM   2

78

79
static libxlDriverPrivatePtr libxl_driver;
J
Jim Fehlig 已提交
80 81

/* Function declarations */
82 83
static int
libxlDomainManagedSaveLoad(virDomainObjPtr vm,
84 85
                           void *opaque);

J
Jim Fehlig 已提交
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106

/* 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;
}

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

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

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

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

J
Jim Fehlig 已提交
133 134 135 136
/*
 * Reconnect to running domains that were previously started/created
 * with libxenlight driver.
 */
137 138
static int
libxlReconnectDomain(virDomainObjPtr vm,
J
Jim Fehlig 已提交
139 140 141
                     void *opaque)
{
    libxlDriverPrivatePtr driver = opaque;
142
    libxlDomainObjPrivatePtr priv = vm->privateData;
J
Jim Fehlig 已提交
143 144 145 146
    int rc;
    libxl_dominfo d_info;
    int len;
    uint8_t *data = NULL;
147
    virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
J
Jim Fehlig 已提交
148

149
    virObjectLock(vm);
J
Jim Fehlig 已提交
150

151
    libxlDomainObjPrivateInitCtx(vm);
J
Jim Fehlig 已提交
152
    /* Does domain still exist? */
153
    rc = libxl_domain_info(priv->ctx, &d_info, vm->def->id);
J
Jim Fehlig 已提交
154 155 156 157 158 159 160 161 162
    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? */
163
    if (libxl_userdata_retrieve(priv->ctx, vm->def->id,
J
Jim Fehlig 已提交
164 165 166 167 168 169 170
                                "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;
171 172 173 174 175 176

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

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

179
    if (virAtomicIntInc(&driver->nactive) == 1 && driver->inhibitCallback)
180 181
        driver->inhibitCallback(true, driver->inhibitOpaque);

182
    /* Re-register domain death et. al. events */
183
    libxlDomainEventsRegister(driver, vm);
184
    virObjectUnlock(vm);
185
    return 0;
J
Jim Fehlig 已提交
186

187
 out:
188
    libxlDomainCleanup(driver, vm, VIR_DOMAIN_SHUTOFF_UNKNOWN);
J
Jim Fehlig 已提交
189
    if (!vm->persistent)
190
        virDomainObjListRemoveLocked(driver->domains, vm);
J
Jim Fehlig 已提交
191
    else
192
        virObjectUnlock(vm);
193 194

    return -1;
J
Jim Fehlig 已提交
195 196 197 198 199
}

static void
libxlReconnectDomains(libxlDriverPrivatePtr driver)
{
200
    virDomainObjListForEach(driver->domains, libxlReconnectDomain, driver);
J
Jim Fehlig 已提交
201 202 203
}

static int
204
libxlStateCleanup(void)
J
Jim Fehlig 已提交
205 206 207 208
{
    if (!libxl_driver)
        return -1;

209
    virObjectUnref(libxl_driver->hostdevMgr);
210
    virObjectUnref(libxl_driver->config);
211
    virObjectUnref(libxl_driver->xmlopt);
212
    virObjectUnref(libxl_driver->domains);
213
    virObjectUnref(libxl_driver->reservedVNCPorts);
J
Jim Fehlig 已提交
214
    virObjectUnref(libxl_driver->migrationPorts);
J
Jim Fehlig 已提交
215

216
    virObjectEventStateFree(libxl_driver->domainEventState);
217
    virSysinfoDefFree(libxl_driver->hostsysinfo);
218

J
Jim Fehlig 已提交
219 220 221 222 223 224
    virMutexDestroy(&libxl_driver->lock);
    VIR_FREE(libxl_driver);

    return 0;
}

225 226
static bool
libxlDriverShouldLoad(bool privileged)
227
{
228 229
    bool ret = false;
    int status;
230
    char *output = NULL;
J
Jim Fehlig 已提交
231

232
    /* Don't load if non-root */
J
Jim Fehlig 已提交
233
    if (!privileged) {
234
        VIR_INFO("Not running privileged, disabling libxenlight driver");
235
        return ret;
J
Jim Fehlig 已提交
236 237
    }

238 239 240
    if (!virFileExists(HYPERVISOR_CAPABILITIES)) {
        VIR_INFO("Disabling driver as " HYPERVISOR_CAPABILITIES
                 " does not exist");
241
        return ret;
242
    }
243 244 245 246 247
    /*
     * Don't load if not running on a Xen control domain (dom0). It is not
     * sufficient to check for the file to exist as any guest can mount
     * xenfs to /proc/xen.
     */
248
    status = virFileReadAll(HYPERVISOR_CAPABILITIES, 10, &output);
249
    if (status >= 0)
250 251 252
        status = strncmp(output, "control_d", 9);
    VIR_FREE(output);
    if (status) {
253 254 255 256 257 258 259
        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 */
260 261 262 263 264 265 266 267 268 269 270
    if (virFileExists("/usr/sbin/xend")) {
        virCommandPtr cmd;

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

275 276 277 278 279 280 281 282
    return ret;
}

static int
libxlStateInitialize(bool privileged,
                     virStateInhibitCallback callback ATTRIBUTE_UNUSED,
                     void *opaque ATTRIBUTE_UNUSED)
{
283
    libxlDriverConfigPtr cfg;
284 285 286 287 288
    char ebuf[1024];

    if (!libxlDriverShouldLoad(privileged))
        return 0;

J
Jim Fehlig 已提交
289 290 291 292
    if (VIR_ALLOC(libxl_driver) < 0)
        return -1;

    if (virMutexInit(&libxl_driver->lock) < 0) {
293 294
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("cannot initialize mutex"));
J
Jim Fehlig 已提交
295 296 297 298 299
        VIR_FREE(libxl_driver);
        return -1;
    }

    /* Allocate bitmap for vnc port reservation */
300
    if (!(libxl_driver->reservedVNCPorts =
J
Ján Tomko 已提交
301 302
          virPortAllocatorNew(_("VNC"),
                              LIBXL_VNC_PORT_MIN,
303 304
                              LIBXL_VNC_PORT_MAX,
                              0)))
305
        goto error;
J
Jim Fehlig 已提交
306

J
Jim Fehlig 已提交
307 308 309 310
    /* Allocate bitmap for migration port reservation */
    if (!(libxl_driver->migrationPorts =
          virPortAllocatorNew(_("migration"),
                              LIBXL_MIGRATION_PORT_MIN,
311
                              LIBXL_MIGRATION_PORT_MAX, 0)))
J
Jim Fehlig 已提交
312 313
        goto error;

314 315
    if (!(libxl_driver->domains = virDomainObjListNew()))
        goto error;
J
Jim Fehlig 已提交
316

317 318 319
    if (!(libxl_driver->hostdevMgr = virHostdevManagerGetDefault()))
        goto error;

320
    if (!(cfg = libxlDriverConfigNew()))
321
        goto error;
J
Jim Fehlig 已提交
322

323 324
    libxl_driver->config = cfg;
    if (virFileMakePath(cfg->stateDir) < 0) {
325 326
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to create state dir '%s': %s"),
327
                       cfg->stateDir,
328
                       virStrerror(errno, ebuf, sizeof(ebuf)));
J
Jim Fehlig 已提交
329 330
        goto error;
    }
331
    if (virFileMakePath(cfg->libDir) < 0) {
332 333
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to create lib dir '%s': %s"),
334
                       cfg->libDir,
335
                       virStrerror(errno, ebuf, sizeof(ebuf)));
J
Jim Fehlig 已提交
336 337
        goto error;
    }
338
    if (virFileMakePath(cfg->saveDir) < 0) {
339 340
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to create save dir '%s': %s"),
341
                       cfg->saveDir,
342
                       virStrerror(errno, ebuf, sizeof(ebuf)));
J
Jim Fehlig 已提交
343 344
        goto error;
    }
345 346 347 348 349 350 351
    if (virFileMakePath(cfg->autoDumpDir) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("failed to create dump dir '%s': %s"),
                       cfg->autoDumpDir,
                       virStrerror(errno, ebuf, sizeof(ebuf)));
        goto error;
    }
J
Jim Fehlig 已提交
352

353
    /* read the host sysinfo */
354
    libxl_driver->hostsysinfo = virSysinfoRead();
355

356
    libxl_driver->domainEventState = virObjectEventStateNew();
E
Eric Blake 已提交
357
    if (!libxl_driver->domainEventState)
358 359
        goto error;

360
    if ((cfg->caps = libxlMakeCapabilities(cfg->ctx)) == NULL) {
361 362
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("cannot create capabilities for libxenlight"));
J
Jim Fehlig 已提交
363 364 365
        goto error;
    }

366
    if (!(libxl_driver->xmlopt = libxlCreateXMLConf()))
367
        goto error;
J
Jim Fehlig 已提交
368 369

    /* Load running domains first. */
370
    if (virDomainObjListLoadAllConfigs(libxl_driver->domains,
371 372
                                       cfg->stateDir,
                                       cfg->autostartDir,
373
                                       1,
374
                                       cfg->caps,
375 376
                                       libxl_driver->xmlopt,
                                       1 << VIR_DOMAIN_VIRT_XEN,
377
                                       NULL, NULL) < 0)
J
Jim Fehlig 已提交
378 379 380 381 382
        goto error;

    libxlReconnectDomains(libxl_driver);

    /* Then inactive persistent configs */
383
    if (virDomainObjListLoadAllConfigs(libxl_driver->domains,
384 385
                                       cfg->configDir,
                                       cfg->autostartDir,
386
                                       0,
387
                                       cfg->caps,
388 389
                                       libxl_driver->xmlopt,
                                       1 << VIR_DOMAIN_VIRT_XEN,
390
                                       NULL, NULL) < 0)
J
Jim Fehlig 已提交
391 392
        goto error;

393 394
    virDomainObjListForEach(libxl_driver->domains, libxlDomainManagedSaveLoad,
                            libxl_driver);
395

J
Jim Fehlig 已提交
396 397
    return 0;

398
 error:
399
    libxlStateCleanup();
400
    return -1;
J
Jim Fehlig 已提交
401 402
}

403 404 405 406 407 408 409 410 411 412
static void
libxlStateAutoStart(void)
{
    if (!libxl_driver)
        return;

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

J
Jim Fehlig 已提交
413
static int
414
libxlStateReload(void)
J
Jim Fehlig 已提交
415
{
416 417
    libxlDriverConfigPtr cfg;

J
Jim Fehlig 已提交
418 419 420
    if (!libxl_driver)
        return 0;

421 422
    cfg = libxlDriverConfigGet(libxl_driver);

423
    virDomainObjListLoadAllConfigs(libxl_driver->domains,
424 425
                                   cfg->configDir,
                                   cfg->autostartDir,
426
                                   1,
427
                                   cfg->caps,
428 429
                                   libxl_driver->xmlopt,
                                   1 << VIR_DOMAIN_VIRT_XEN,
430 431
                                   NULL, libxl_driver);

432 433
    virDomainObjListForEach(libxl_driver->domains, libxlAutostartDomain,
                            libxl_driver);
434

435
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
436 437 438 439 440
    return 0;
}


static virDrvOpenStatus
441 442 443
libxlConnectOpen(virConnectPtr conn,
                 virConnectAuthPtr auth ATTRIBUTE_UNUSED,
                 unsigned int flags)
J
Jim Fehlig 已提交
444
{
E
Eric Blake 已提交
445 446
    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

J
Jim Fehlig 已提交
447 448 449 450
    if (conn->uri == NULL) {
        if (libxl_driver == NULL)
            return VIR_DRV_OPEN_DECLINED;

451
        if (!(conn->uri = virURIParse("xen:///")))
J
Jim Fehlig 已提交
452 453 454 455 456 457 458 459 460 461 462 463
            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) {
464 465
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("libxenlight state driver is not active"));
J
Jim Fehlig 已提交
466 467 468 469 470 471 472 473
            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")) {
474 475 476
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("unexpected Xen URI path '%s', try xen:///"),
                           NULLSTR(conn->uri->path));
J
Jim Fehlig 已提交
477 478 479 480
            return VIR_DRV_OPEN_ERROR;
        }
    }

481 482 483
    if (virConnectOpenEnsureACL(conn) < 0)
        return VIR_DRV_OPEN_ERROR;

J
Jim Fehlig 已提交
484 485 486 487 488 489
    conn->privateData = libxl_driver;

    return VIR_DRV_OPEN_SUCCESS;
};

static int
490
libxlConnectClose(virConnectPtr conn ATTRIBUTE_UNUSED)
J
Jim Fehlig 已提交
491 492 493 494 495 496
{
    conn->privateData = NULL;
    return 0;
}

static const char *
497
libxlConnectGetType(virConnectPtr conn)
J
Jim Fehlig 已提交
498
{
499 500 501
    if (virConnectGetTypeEnsureACL(conn) < 0)
        return NULL;

J
Jim Fehlig 已提交
502
    return "Xen";
J
Jim Fehlig 已提交
503 504 505
}

static int
506
libxlConnectGetVersion(virConnectPtr conn, unsigned long *version)
J
Jim Fehlig 已提交
507 508
{
    libxlDriverPrivatePtr driver = conn->privateData;
509
    libxlDriverConfigPtr cfg;
J
Jim Fehlig 已提交
510

511 512 513
    if (virConnectGetVersionEnsureACL(conn) < 0)
        return 0;

514 515 516
    cfg = libxlDriverConfigGet(driver);
    *version = cfg->version;
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
517 518 519
    return 0;
}

520

521
static char *libxlConnectGetHostname(virConnectPtr conn)
522
{
523 524 525
    if (virConnectGetHostnameEnsureACL(conn) < 0)
        return NULL;

526 527 528
    return virGetHostname();
}

529 530 531 532 533 534 535 536
static char *
libxlConnectGetSysinfo(virConnectPtr conn, unsigned int flags)
{
    libxlDriverPrivatePtr driver = conn->privateData;
    virBuffer buf = VIR_BUFFER_INITIALIZER;

    virCheckFlags(0, NULL);

537 538 539
    if (virConnectGetSysinfoEnsureACL(conn) < 0)
        return NULL;

540 541 542 543 544 545 546 547
    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;
548
    if (virBufferCheckError(&buf) < 0)
549 550 551
        return NULL;
    return virBufferContentAndReset(&buf);
}
552

J
Jim Fehlig 已提交
553
static int
554
libxlConnectGetMaxVcpus(virConnectPtr conn, const char *type ATTRIBUTE_UNUSED)
J
Jim Fehlig 已提交
555 556 557
{
    int ret;
    libxlDriverPrivatePtr driver = conn->privateData;
558
    libxlDriverConfigPtr cfg;
J
Jim Fehlig 已提交
559

560 561 562
    if (virConnectGetMaxVcpusEnsureACL(conn) < 0)
        return -1;

563 564
    cfg = libxlDriverConfigGet(driver);
    ret = libxl_get_max_cpus(cfg->ctx);
565 566 567 568 569
    /* On failure, libxl_get_max_cpus() will return ERROR_FAIL from Xen 4.4
     * onward, but it ever returning 0 is obviously wrong too (and it is
     * what happens, on failure, on Xen 4.3 and earlier). Therefore, a 'less
     * or equal' is the catchall we want. */
    if (ret <= 0)
570
        ret = -1;
J
Jim Fehlig 已提交
571

572
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
573 574 575 576 577 578
    return ret;
}

static int
libxlNodeGetInfo(virConnectPtr conn, virNodeInfoPtr info)
{
579 580 581
    if (virNodeGetInfoEnsureACL(conn) < 0)
        return -1;

582
    return libxlDriverNodeGetInfo(conn->privateData, info);
J
Jim Fehlig 已提交
583 584 585
}

static char *
586
libxlConnectGetCapabilities(virConnectPtr conn)
J
Jim Fehlig 已提交
587 588 589
{
    libxlDriverPrivatePtr driver = conn->privateData;
    char *xml;
590
    libxlDriverConfigPtr cfg;
J
Jim Fehlig 已提交
591

592 593 594
    if (virConnectGetCapabilitiesEnsureACL(conn) < 0)
        return NULL;

595
    cfg = libxlDriverConfigGet(driver);
596
    xml = virCapabilitiesFormatXML(cfg->caps);
J
Jim Fehlig 已提交
597

598
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
599 600 601 602
    return xml;
}

static int
603
libxlConnectListDomains(virConnectPtr conn, int *ids, int nids)
J
Jim Fehlig 已提交
604 605 606 607
{
    libxlDriverPrivatePtr driver = conn->privateData;
    int n;

608 609 610
    if (virConnectListDomainsEnsureACL(conn) < 0)
        return -1;

611 612
    n = virDomainObjListGetActiveIDs(driver->domains, ids, nids,
                                     virConnectListDomainsCheckACL, conn);
J
Jim Fehlig 已提交
613 614 615 616 617

    return n;
}

static int
618
libxlConnectNumOfDomains(virConnectPtr conn)
J
Jim Fehlig 已提交
619 620 621 622
{
    libxlDriverPrivatePtr driver = conn->privateData;
    int n;

623 624 625
    if (virConnectNumOfDomainsEnsureACL(conn) < 0)
        return -1;

626 627
    n = virDomainObjListNumOfDomains(driver->domains, true,
                                     virConnectNumOfDomainsCheckACL, conn);
J
Jim Fehlig 已提交
628 629 630 631 632 633 634 635 636 637 638 639

    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;
640
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
J
Jim Fehlig 已提交
641 642 643

    virCheckFlags(VIR_DOMAIN_START_PAUSED, NULL);

644
    if (!(def = virDomainDefParseString(xml, cfg->caps, driver->xmlopt,
645
                                        1 << VIR_DOMAIN_VIRT_XEN,
J
Jim Fehlig 已提交
646 647 648
                                        VIR_DOMAIN_XML_INACTIVE)))
        goto cleanup;

649 650 651
    if (virDomainCreateXMLEnsureACL(conn, def) < 0)
        goto cleanup;

652
    if (!(vm = virDomainObjListAdd(driver->domains, def,
653
                                   driver->xmlopt,
654 655
                                   VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                   NULL)))
J
Jim Fehlig 已提交
656 657 658
        goto cleanup;
    def = NULL;

659
    if (libxlDomainStart(driver, vm, (flags & VIR_DOMAIN_START_PAUSED) != 0,
660
                     -1) < 0) {
661
        virDomainObjListRemove(driver->domains, vm);
J
Jim Fehlig 已提交
662 663 664 665 666 667 668 669
        vm = NULL;
        goto cleanup;
    }

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

670
 cleanup:
J
Jim Fehlig 已提交
671 672
    virDomainDefFree(def);
    if (vm)
673
        virObjectUnlock(vm);
674
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
675 676 677 678 679 680 681 682 683 684
    return dom;
}

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

685
    vm = virDomainObjListFindByID(driver->domains, id);
J
Jim Fehlig 已提交
686
    if (!vm) {
687
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
J
Jim Fehlig 已提交
688 689 690
        goto cleanup;
    }

691 692 693
    if (virDomainLookupByIDEnsureACL(conn, vm->def) < 0)
        goto cleanup;

J
Jim Fehlig 已提交
694 695 696 697
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
    if (dom)
        dom->id = vm->def->id;

698
 cleanup:
J
Jim Fehlig 已提交
699
    if (vm)
700
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
701 702 703 704 705 706 707 708 709 710
    return dom;
}

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

711
    vm = virDomainObjListFindByUUID(driver->domains, uuid);
J
Jim Fehlig 已提交
712
    if (!vm) {
713
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
J
Jim Fehlig 已提交
714 715 716
        goto cleanup;
    }

717 718 719
    if (virDomainLookupByUUIDEnsureACL(conn, vm->def) < 0)
        goto cleanup;

J
Jim Fehlig 已提交
720 721 722 723
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
    if (dom)
        dom->id = vm->def->id;

724
 cleanup:
J
Jim Fehlig 已提交
725
    if (vm)
726
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
727 728 729 730 731 732 733 734 735 736
    return dom;
}

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

737
    vm = virDomainObjListFindByName(driver->domains, name);
J
Jim Fehlig 已提交
738
    if (!vm) {
739
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
J
Jim Fehlig 已提交
740 741 742
        goto cleanup;
    }

743 744 745
    if (virDomainLookupByNameEnsureACL(conn, vm->def) < 0)
        goto cleanup;

J
Jim Fehlig 已提交
746 747 748 749
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
    if (dom)
        dom->id = vm->def->id;

750
 cleanup:
J
Jim Fehlig 已提交
751
    if (vm)
752
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
753 754 755
    return dom;
}

756 757 758 759
static int
libxlDomainSuspend(virDomainPtr dom)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
760
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
761 762
    virDomainObjPtr vm;
    libxlDomainObjPrivatePtr priv;
763
    virObjectEventPtr event = NULL;
764 765
    int ret = -1;

J
Jim Fehlig 已提交
766
    if (!(vm = libxlDomObjFromDomain(dom)))
767
        goto cleanup;
768 769 770 771

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

772 773 774
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

775
    if (!virDomainObjIsActive(vm)) {
776
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
777
        goto endjob;
778 779 780 781
    }

    priv = vm->privateData;

J
Jiri Denemark 已提交
782
    if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_PAUSED) {
783
        if (libxl_domain_pause(priv->ctx, vm->def->id) != 0) {
784 785
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Failed to suspend domain '%d' with libxenlight"),
786
                           vm->def->id);
787
            goto endjob;
788 789
        }

J
Jiri Denemark 已提交
790
        virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER);
791

792
        event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_SUSPENDED,
793 794 795
                                         VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
    }

796
    if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
797
        goto endjob;
798 799 800

    ret = 0;

801
 endjob:
802 803 804
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

805
 cleanup:
806
    if (vm)
807
        virObjectUnlock(vm);
808
    if (event)
809
        libxlDomainEventQueue(driver, event);
810
    virObjectUnref(cfg);
811 812 813 814 815 816 817 818
    return ret;
}


static int
libxlDomainResume(virDomainPtr dom)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
819
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
820 821
    virDomainObjPtr vm;
    libxlDomainObjPrivatePtr priv;
822
    virObjectEventPtr event = NULL;
823 824
    int ret = -1;

J
Jim Fehlig 已提交
825
    if (!(vm = libxlDomObjFromDomain(dom)))
826 827
        goto cleanup;

828 829 830
    if (virDomainResumeEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

831 832 833
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

834
    if (!virDomainObjIsActive(vm)) {
835
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
836
        goto endjob;
837 838 839 840
    }

    priv = vm->privateData;

J
Jiri Denemark 已提交
841
    if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
842
        if (libxl_domain_unpause(priv->ctx, vm->def->id) != 0) {
843 844
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Failed to resume domain '%d' with libxenlight"),
845
                           vm->def->id);
846
            goto endjob;
847 848
        }

J
Jiri Denemark 已提交
849 850
        virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
                             VIR_DOMAIN_RUNNING_UNPAUSED);
851

852
        event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_RESUMED,
853 854 855
                                         VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
    }

856
    if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
857
        goto endjob;
858 859 860

    ret = 0;

861
 endjob:
862 863 864
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

865
 cleanup:
866
    if (vm)
867
        virObjectUnlock(vm);
868
    if (event)
869
        libxlDomainEventQueue(driver, event);
870
    virObjectUnref(cfg);
871 872 873
    return ret;
}

J
Jim Fehlig 已提交
874
static int
875
libxlDomainShutdownFlags(virDomainPtr dom, unsigned int flags)
J
Jim Fehlig 已提交
876 877 878 879 880
{
    virDomainObjPtr vm;
    int ret = -1;
    libxlDomainObjPrivatePtr priv;

881 882 883 884 885
    virCheckFlags(VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN |
                  VIR_DOMAIN_SHUTDOWN_PARAVIRT, -1);
    if (flags == 0)
        flags = VIR_DOMAIN_SHUTDOWN_PARAVIRT |
            VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN;
886

J
Jim Fehlig 已提交
887
    if (!(vm = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
888 889
        goto cleanup;

890
    if (virDomainShutdownFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
891 892
        goto cleanup;

J
Jim Fehlig 已提交
893
    if (!virDomainObjIsActive(vm)) {
894 895
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("Domain is not running"));
J
Jim Fehlig 已提交
896 897 898 899
        goto cleanup;
    }

    priv = vm->privateData;
900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920
    if (flags & VIR_DOMAIN_SHUTDOWN_PARAVIRT) {
        ret = libxl_domain_shutdown(priv->ctx, vm->def->id);
        if (ret == 0)
            goto cleanup;

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

    if (flags & VIR_DOMAIN_SHUTDOWN_ACPI_POWER_BTN) {
        ret = libxl_send_trigger(priv->ctx, vm->def->id,
                                 LIBXL_TRIGGER_POWER, 0);
        if (ret == 0)
            goto cleanup;

921 922
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to shutdown domain '%d' with libxenlight"),
923
                       vm->def->id);
924
        ret = -1;
J
Jim Fehlig 已提交
925 926
    }

927
 cleanup:
J
Jim Fehlig 已提交
928
    if (vm)
929
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
930 931 932
    return ret;
}

933 934 935 936 937 938 939
static int
libxlDomainShutdown(virDomainPtr dom)
{
    return libxlDomainShutdownFlags(dom, 0);
}


J
Jim Fehlig 已提交
940
static int
E
Eric Blake 已提交
941
libxlDomainReboot(virDomainPtr dom, unsigned int flags)
J
Jim Fehlig 已提交
942 943 944 945 946
{
    virDomainObjPtr vm;
    int ret = -1;
    libxlDomainObjPrivatePtr priv;

J
Jim Fehlig 已提交
947 948 949
    virCheckFlags(VIR_DOMAIN_REBOOT_PARAVIRT, -1);
    if (flags == 0)
        flags = VIR_DOMAIN_REBOOT_PARAVIRT;
E
Eric Blake 已提交
950

J
Jim Fehlig 已提交
951
    if (!(vm = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
952 953
        goto cleanup;

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

J
Jim Fehlig 已提交
957
    if (!virDomainObjIsActive(vm)) {
958 959
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("Domain is not running"));
J
Jim Fehlig 已提交
960 961 962 963
        goto cleanup;
    }

    priv = vm->privateData;
J
Jim Fehlig 已提交
964 965 966 967 968
    if (flags & VIR_DOMAIN_REBOOT_PARAVIRT) {
        ret = libxl_domain_reboot(priv->ctx, vm->def->id);
        if (ret == 0)
            goto cleanup;

969 970
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to reboot domain '%d' with libxenlight"),
971
                       vm->def->id);
J
Jim Fehlig 已提交
972
        ret = -1;
J
Jim Fehlig 已提交
973 974
    }

975
 cleanup:
J
Jim Fehlig 已提交
976
    if (vm)
977
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
978 979 980 981
    return ret;
}

static int
982 983
libxlDomainDestroyFlags(virDomainPtr dom,
                        unsigned int flags)
J
Jim Fehlig 已提交
984 985 986 987
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
988
    virObjectEventPtr event = NULL;
J
Jim Fehlig 已提交
989
    libxlDomainObjPrivatePtr priv;
J
Jim Fehlig 已提交
990

991 992
    virCheckFlags(0, -1);

J
Jim Fehlig 已提交
993
    if (!(vm = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
994 995
        goto cleanup;

996 997 998
    if (virDomainDestroyFlagsEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

J
Jim Fehlig 已提交
999
    if (!virDomainObjIsActive(vm)) {
1000 1001
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("Domain is not running"));
J
Jim Fehlig 已提交
1002 1003 1004
        goto cleanup;
    }

1005
    event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
1006 1007
                                     VIR_DOMAIN_EVENT_STOPPED_DESTROYED);

J
Jim Fehlig 已提交
1008 1009
    priv = vm->privateData;
    if (libxl_domain_destroy(priv->ctx, vm->def->id, NULL) < 0) {
1010
        virReportError(VIR_ERR_INTERNAL_ERROR,
1011
                       _("Failed to destroy domain '%d'"), vm->def->id);
J
Jim Fehlig 已提交
1012 1013 1014
        goto cleanup;
    }

1015
    if (libxlDomainCleanupJob(driver, vm, VIR_DOMAIN_SHUTOFF_DESTROYED)) {
1016 1017 1018 1019
        if (!vm->persistent) {
            virDomainObjListRemove(driver->domains, vm);
            vm = NULL;
        }
J
Jim Fehlig 已提交
1020 1021 1022 1023
    }

    ret = 0;

1024
 cleanup:
J
Jim Fehlig 已提交
1025
    if (vm)
1026
        virObjectUnlock(vm);
1027 1028
    if (event)
        libxlDomainEventQueue(driver, event);
J
Jim Fehlig 已提交
1029 1030 1031
    return ret;
}

1032 1033 1034 1035 1036 1037
static int
libxlDomainDestroy(virDomainPtr dom)
{
    return libxlDomainDestroyFlags(dom, 0);
}

1038 1039 1040 1041 1042 1043
static char *
libxlDomainGetOSType(virDomainPtr dom)
{
    virDomainObjPtr vm;
    char *type = NULL;

J
Jim Fehlig 已提交
1044
    if (!(vm = libxlDomObjFromDomain(dom)))
1045 1046
        goto cleanup;

1047 1048 1049 1050 1051
    if (virDomainGetOSTypeEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

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

1053
 cleanup:
1054
    if (vm)
1055
        virObjectUnlock(vm);
1056 1057 1058
    return type;
}

1059
static unsigned long long
1060 1061 1062
libxlDomainGetMaxMemory(virDomainPtr dom)
{
    virDomainObjPtr vm;
1063
    unsigned long long ret = 0;
1064

J
Jim Fehlig 已提交
1065
    if (!(vm = libxlDomObjFromDomain(dom)))
1066
        goto cleanup;
1067 1068 1069 1070

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

1071 1072
    ret = vm->def->mem.max_balloon;

1073
 cleanup:
1074
    if (vm)
1075
        virObjectUnlock(vm);
1076 1077 1078 1079
    return ret;
}

static int
1080
libxlDomainSetMemoryFlags(virDomainPtr dom, unsigned long newmem,
1081 1082 1083
                          unsigned int flags)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
1084
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
1085 1086
    libxlDomainObjPrivatePtr priv;
    virDomainObjPtr vm;
1087 1088
    virDomainDefPtr persistentDef = NULL;
    bool isActive;
1089 1090 1091
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_MEM_LIVE |
1092 1093
                  VIR_DOMAIN_MEM_CONFIG |
                  VIR_DOMAIN_MEM_MAXIMUM, -1);
1094

J
Jim Fehlig 已提交
1095
    if (!(vm = libxlDomObjFromDomain(dom)))
1096 1097
        goto cleanup;

1098 1099 1100
    if (virDomainSetMemoryFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
        goto cleanup;

1101 1102 1103
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116
    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;
1117 1118
    }

1119
    if (!isActive && (flags & VIR_DOMAIN_MEM_LIVE)) {
1120 1121
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("cannot set memory on an inactive domain"));
1122
        goto endjob;
1123 1124 1125 1126
    }

    if (flags & VIR_DOMAIN_MEM_CONFIG) {
        if (!vm->persistent) {
1127 1128
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                           _("cannot change persistent config of a transient domain"));
1129
            goto endjob;
1130
        }
1131
        if (!(persistentDef = virDomainObjGetPersistentDef(cfg->caps,
1132
                                                           driver->xmlopt,
1133
                                                           vm)))
1134
            goto endjob;
1135 1136
    }

1137 1138
    if (flags & VIR_DOMAIN_MEM_MAXIMUM) {
        /* resize the maximum memory */
1139

1140 1141
        if (flags & VIR_DOMAIN_MEM_LIVE) {
            priv = vm->privateData;
1142
            if (libxl_domain_setmaxmem(priv->ctx, vm->def->id, newmem) < 0) {
1143 1144
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("Failed to set maximum memory for domain '%d'"
1145
                                 " with libxenlight"), vm->def->id);
1146
                goto endjob;
1147 1148 1149 1150 1151 1152 1153 1154 1155
            }
        }

        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;
1156
            ret = virDomainSaveConfig(cfg->configDir, persistentDef);
1157
            goto endjob;
1158 1159
        }

1160 1161
    } else {
        /* resize the current memory */
1162

1163
        if (newmem > vm->def->mem.max_balloon) {
1164 1165
            virReportError(VIR_ERR_INVALID_ARG, "%s",
                           _("cannot set memory higher than max memory"));
1166
            goto endjob;
1167 1168 1169
        }

        if (flags & VIR_DOMAIN_MEM_LIVE) {
1170 1171
            int res;

1172
            priv = vm->privateData;
1173 1174
            /* Unlock virDomainObj while ballooning memory */
            virObjectUnlock(vm);
1175
            res = libxl_set_memory_target(priv->ctx, vm->def->id, newmem, 0,
1176 1177 1178
                                          /* force */ 1);
            virObjectLock(vm);
            if (res < 0) {
1179 1180
                virReportError(VIR_ERR_INTERNAL_ERROR,
                               _("Failed to set memory for domain '%d'"
1181
                                 " with libxenlight"), vm->def->id);
1182
                goto endjob;
1183 1184 1185 1186 1187 1188
            }
        }

        if (flags & VIR_DOMAIN_MEM_CONFIG) {
            sa_assert(persistentDef);
            persistentDef->mem.cur_balloon = newmem;
1189
            ret = virDomainSaveConfig(cfg->configDir, persistentDef);
1190
            goto endjob;
1191
        }
1192 1193
    }

1194 1195
    ret = 0;

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

1200
 cleanup:
1201
    if (vm)
1202
        virObjectUnlock(vm);
1203
    virObjectUnref(cfg);
1204 1205 1206 1207 1208 1209 1210 1211 1212
    return ret;
}

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

1213 1214 1215 1216 1217 1218
static int
libxlDomainSetMaxMemory(virDomainPtr dom, unsigned long memory)
{
    return libxlDomainSetMemoryFlags(dom, memory, VIR_DOMAIN_MEM_MAXIMUM);
}

J
Jim Fehlig 已提交
1219 1220 1221 1222
static int
libxlDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info)
{
    virDomainObjPtr vm;
1223
    libxl_dominfo d_info;
1224
    libxlDomainObjPrivatePtr priv;
J
Jim Fehlig 已提交
1225 1226
    int ret = -1;

J
Jim Fehlig 已提交
1227
    if (!(vm = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
1228 1229
        goto cleanup;

1230 1231 1232
    if (virDomainGetInfoEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

1233
    priv = vm->privateData;
1234 1235 1236
    if (!virDomainObjIsActive(vm)) {
        info->cpuTime = 0;
        info->memory = vm->def->mem.cur_balloon;
1237
        info->maxMem = vm->def->mem.max_balloon;
1238
    } else {
1239
        if (libxl_domain_info(priv->ctx, &d_info, vm->def->id) != 0) {
1240
            virReportError(VIR_ERR_INTERNAL_ERROR,
1241 1242
                           _("libxl_domain_info failed for domain '%d'"),
                           vm->def->id);
1243 1244 1245 1246
            goto cleanup;
        }
        info->cpuTime = d_info.cpu_time;
        info->memory = d_info.current_memkb;
1247
        info->maxMem = d_info.max_memkb;
1248 1249
    }

J
Jiri Denemark 已提交
1250
    info->state = virDomainObjGetState(vm, NULL);
J
Jim Fehlig 已提交
1251 1252 1253
    info->nrVirtCpu = vm->def->vcpus;
    ret = 0;

1254
 cleanup:
J
Jim Fehlig 已提交
1255
    if (vm)
1256
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
1257 1258 1259
    return ret;
}

1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270
static int
libxlDomainGetState(virDomainPtr dom,
                    int *state,
                    int *reason,
                    unsigned int flags)
{
    virDomainObjPtr vm;
    int ret = -1;

    virCheckFlags(0, -1);

J
Jim Fehlig 已提交
1271
    if (!(vm = libxlDomObjFromDomain(dom)))
1272 1273
        goto cleanup;

1274 1275 1276
    if (virDomainGetStateEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

J
Jiri Denemark 已提交
1277
    *state = virDomainObjGetState(vm, reason);
1278 1279
    ret = 0;

1280
 cleanup:
1281
    if (vm)
1282
        virObjectUnlock(vm);
1283 1284 1285
    return ret;
}

1286 1287 1288
/*
 * virDomainObjPtr must be locked on invocation
 */
1289
static int
1290 1291
libxlDoDomainSave(libxlDriverPrivatePtr driver, virDomainObjPtr vm,
                  const char *to)
1292
{
1293
    libxlDomainObjPrivatePtr priv = vm->privateData;
1294
    libxlSavefileHeader hdr;
1295
    virObjectEventPtr event = NULL;
1296 1297
    char *xml = NULL;
    uint32_t xml_len;
1298
    int fd = -1;
1299 1300 1301
    int ret = -1;

    if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
1302 1303 1304
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("Domain '%d' has to be running because libxenlight will"
                         " suspend it"), vm->def->id);
1305 1306 1307 1308
        goto cleanup;
    }

    if ((fd = virFileOpenAs(to, O_CREAT|O_TRUNC|O_WRONLY, S_IRUSR|S_IWUSR,
L
Laine Stump 已提交
1309
                            -1, -1, 0)) < 0) {
1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324
        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)) {
1325 1326
        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                       _("Failed to write save file header"));
1327 1328 1329 1330
        goto cleanup;
    }

    if (safewrite(fd, xml, xml_len) != xml_len) {
1331 1332
        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                       _("Failed to write xml description"));
1333 1334 1335
        goto cleanup;
    }

1336 1337 1338 1339 1340 1341
    /* Unlock virDomainObj while saving domain */
    virObjectUnlock(vm);
    ret = libxl_domain_suspend(priv->ctx, vm->def->id, fd, 0, NULL);
    virObjectLock(vm);

    if (ret != 0) {
1342 1343 1344
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to save domain '%d' with libxenlight"),
                       vm->def->id);
1345
        ret = -1;
1346 1347 1348
        goto cleanup;
    }

1349
    event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
1350 1351
                                         VIR_DOMAIN_EVENT_STOPPED_SAVED);

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

1358
    libxlDomainCleanup(driver, vm, VIR_DOMAIN_SHUTOFF_SAVED);
1359
    vm->hasManagedSave = true;
1360 1361
    ret = 0;

1362
 cleanup:
1363 1364 1365 1366 1367 1368 1369 1370 1371
    VIR_FREE(xml);
    if (VIR_CLOSE(fd) < 0)
        virReportSystemError(errno, "%s", _("cannot close file"));
    if (event)
        libxlDomainEventQueue(driver, event);
    return ret;
}

static int
1372 1373
libxlDomainSaveFlags(virDomainPtr dom, const char *to, const char *dxml,
                     unsigned int flags)
1374
{
1375 1376
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    virDomainObjPtr vm;
1377
    int ret = -1;
1378
    bool remove_dom = false;
1379

1380 1381 1382 1383 1384
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
    virReportUnsupportedError();
    return -1;
#endif

1385 1386
    virCheckFlags(0, -1);
    if (dxml) {
1387 1388
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
1389 1390 1391
        return -1;
    }

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

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

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

1401
    if (!virDomainObjIsActive(vm)) {
1402
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
1403
        goto endjob;
1404 1405
    }

1406
    if (libxlDoDomainSave(driver, vm, to) < 0)
1407
        goto endjob;
1408

1409 1410
    if (!vm->persistent)
        remove_dom = true;
1411 1412

    ret = 0;
1413

1414
 endjob:
1415 1416 1417
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

1418
 cleanup:
1419 1420 1421 1422
    if (remove_dom && vm) {
        virDomainObjListRemove(driver->domains, vm);
        vm = NULL;
    }
1423
    if (vm)
1424
        virObjectUnlock(vm);
1425 1426
    return ret;
}
1427

1428
static int
1429 1430 1431 1432 1433 1434 1435 1436
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)
1437 1438
{
    libxlDriverPrivatePtr driver = conn->privateData;
1439
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
1440 1441 1442 1443 1444
    virDomainObjPtr vm = NULL;
    virDomainDefPtr def = NULL;
    libxlSavefileHeader hdr;
    int fd = -1;
    int ret = -1;
1445

1446 1447 1448 1449 1450
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
    virReportUnsupportedError();
    return -1;
#endif

1451
    virCheckFlags(VIR_DOMAIN_SAVE_PAUSED, -1);
1452
    if (dxml) {
1453 1454
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
1455 1456 1457
        return -1;
    }

1458
    fd = libxlDomainSaveImageOpen(driver, cfg, from, &def, &hdr);
1459
    if (fd < 0)
1460
        goto cleanup_unlock;
1461

1462
    if (virDomainRestoreFlagsEnsureACL(conn, def) < 0)
1463
        goto cleanup_unlock;
1464

1465
    if (!(vm = virDomainObjListAdd(driver->domains, def,
1466
                                   driver->xmlopt,
1467 1468 1469
                                   VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
                                   VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                   NULL)))
1470
        goto cleanup_unlock;
1471 1472 1473

    def = NULL;

1474
    ret = libxlDomainStart(driver, vm, (flags & VIR_DOMAIN_SAVE_PAUSED) != 0, fd);
1475
    if (ret < 0 && !vm->persistent) {
1476
        virDomainObjListRemove(driver->domains, vm);
1477 1478 1479
        vm = NULL;
    }

1480
 cleanup:
1481 1482
    if (VIR_CLOSE(fd) < 0)
        virReportSystemError(errno, "%s", _("cannot close file"));
1483 1484
    virDomainDefFree(def);
    if (vm)
1485
        virObjectUnlock(vm);
1486
    virObjectUnref(cfg);
1487
    return ret;
1488

1489
 cleanup_unlock:
1490 1491
    libxlDriverUnlock(driver);
    goto cleanup;
1492 1493
}

1494 1495 1496 1497 1498 1499
static int
libxlDomainRestore(virConnectPtr conn, const char *from)
{
    return libxlDomainRestoreFlags(conn, from, NULL, 0);
}

1500
static int
1501
libxlDomainCoreDump(virDomainPtr dom, const char *to, unsigned int flags)
1502 1503 1504 1505
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    libxlDomainObjPrivatePtr priv;
    virDomainObjPtr vm;
1506
    virObjectEventPtr event = NULL;
1507
    bool remove_dom = false;
1508 1509 1510 1511 1512
    bool paused = false;
    int ret = -1;

    virCheckFlags(VIR_DUMP_LIVE | VIR_DUMP_CRASH, -1);

J
Jim Fehlig 已提交
1513
    if (!(vm = libxlDomObjFromDomain(dom)))
1514 1515
        goto cleanup;

1516 1517 1518
    if (virDomainCoreDumpEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

1519 1520 1521
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

1522
    if (!virDomainObjIsActive(vm)) {
1523
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
1524
        goto endjob;
1525 1526 1527 1528 1529 1530
    }

    priv = vm->privateData;

    if (!(flags & VIR_DUMP_LIVE) &&
        virDomainObjGetState(vm, NULL) == VIR_DOMAIN_RUNNING) {
1531
        if (libxl_domain_pause(priv->ctx, vm->def->id) != 0) {
1532 1533 1534
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Before dumping core, failed to suspend domain '%d'"
                             " with libxenlight"),
1535
                           vm->def->id);
1536
            goto endjob;
1537 1538 1539 1540 1541
        }
        virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_DUMP);
        paused = true;
    }

1542 1543
    /* Unlock virDomainObj while dumping core */
    virObjectUnlock(vm);
1544
    ret = libxl_domain_core_dump(priv->ctx, vm->def->id, to, NULL);
1545 1546
    virObjectLock(vm);
    if (ret != 0) {
1547 1548
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to dump core of domain '%d' with libxenlight"),
1549
                       vm->def->id);
1550 1551
        ret = -1;
        goto unpause;
1552 1553 1554
    }

    if (flags & VIR_DUMP_CRASH) {
1555
        if (libxl_domain_destroy(priv->ctx, vm->def->id, NULL) < 0) {
1556
            virReportError(VIR_ERR_INTERNAL_ERROR,
1557
                           _("Failed to destroy domain '%d'"), vm->def->id);
1558
            goto unpause;
1559 1560
        }

1561
        libxlDomainCleanup(driver, vm, VIR_DOMAIN_SHUTOFF_CRASHED);
1562
        event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
1563
                                         VIR_DOMAIN_EVENT_STOPPED_CRASHED);
1564 1565
        if (!vm->persistent)
            remove_dom = true;
1566 1567 1568 1569
    }

    ret = 0;

1570
 unpause:
1571
    if (virDomainObjIsActive(vm) && paused) {
1572
        if (libxl_domain_unpause(priv->ctx, vm->def->id) != 0) {
1573 1574
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("After dumping core, failed to resume domain '%d' with"
1575
                             " libxenlight"), vm->def->id);
1576 1577 1578 1579 1580
        } else {
            virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
                                 VIR_DOMAIN_RUNNING_UNPAUSED);
        }
    }
1581

1582
 endjob:
1583 1584 1585
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

1586
 cleanup:
1587 1588 1589 1590
    if (remove_dom && vm) {
        virDomainObjListRemove(driver->domains, vm);
        vm = NULL;
    }
1591
    if (vm)
1592
        virObjectUnlock(vm);
1593
    if (event)
1594 1595 1596 1597
        libxlDomainEventQueue(driver, event);
    return ret;
}

1598 1599 1600 1601 1602 1603 1604
static int
libxlDomainManagedSave(virDomainPtr dom, unsigned int flags)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    virDomainObjPtr vm = NULL;
    char *name = NULL;
    int ret = -1;
1605
    bool remove_dom = false;
1606 1607 1608

    virCheckFlags(0, -1);

J
Jim Fehlig 已提交
1609
    if (!(vm = libxlDomObjFromDomain(dom)))
1610 1611
        goto cleanup;

1612 1613 1614
    if (virDomainManagedSaveEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

1615 1616 1617
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

1618
    if (!virDomainObjIsActive(vm)) {
1619
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
1620
        goto endjob;
1621
    }
1622
    if (!vm->persistent) {
1623 1624
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("cannot do managed save for transient domain"));
1625
        goto endjob;
1626
    }
1627 1628 1629

    name = libxlDomainManagedSavePath(driver, vm);
    if (name == NULL)
1630
        goto endjob;
1631 1632 1633

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

1634
    if (libxlDoDomainSave(driver, vm, name) < 0)
1635
        goto endjob;
1636

1637 1638
    if (!vm->persistent)
        remove_dom = true;
1639 1640

    ret = 0;
1641

1642
 endjob:
1643 1644 1645
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

1646
 cleanup:
1647 1648 1649 1650
    if (remove_dom && vm) {
        virDomainObjListRemove(driver->domains, vm);
        vm = NULL;
    }
1651
    if (vm)
1652
        virObjectUnlock(vm);
1653 1654 1655 1656
    VIR_FREE(name);
    return ret;
}

1657 1658
static int
libxlDomainManagedSaveLoad(virDomainObjPtr vm,
1659 1660 1661 1662
                           void *opaque)
{
    libxlDriverPrivatePtr driver = opaque;
    char *name;
1663
    int ret = -1;
1664

1665
    virObjectLock(vm);
1666 1667 1668 1669 1670 1671

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

    vm->hasManagedSave = virFileExists(name);

1672
    ret = 0;
1673
 cleanup:
1674
    virObjectUnlock(vm);
1675
    VIR_FREE(name);
1676
    return ret;
1677 1678
}

1679 1680 1681 1682 1683 1684 1685 1686
static int
libxlDomainHasManagedSaveImage(virDomainPtr dom, unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    int ret = -1;

    virCheckFlags(0, -1);

J
Jim Fehlig 已提交
1687
    if (!(vm = libxlDomObjFromDomain(dom)))
1688 1689
        goto cleanup;

1690 1691 1692
    if (virDomainHasManagedSaveImageEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

1693
    ret = vm->hasManagedSave;
1694

1695
 cleanup:
1696
    if (vm)
1697
        virObjectUnlock(vm);
1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710
    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 已提交
1711
    if (!(vm = libxlDomObjFromDomain(dom)))
1712 1713
        goto cleanup;

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

1717 1718 1719 1720 1721
    name = libxlDomainManagedSavePath(driver, vm);
    if (name == NULL)
        goto cleanup;

    ret = unlink(name);
1722
    vm->hasManagedSave = false;
1723

1724
 cleanup:
1725 1726
    VIR_FREE(name);
    if (vm)
1727
        virObjectUnlock(vm);
1728 1729 1730
    return ret;
}

1731 1732 1733 1734 1735
static int
libxlDomainSetVcpusFlags(virDomainPtr dom, unsigned int nvcpus,
                         unsigned int flags)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
1736
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
1737 1738 1739
    libxlDomainObjPrivatePtr priv;
    virDomainDefPtr def;
    virDomainObjPtr vm;
J
Jim Fehlig 已提交
1740
    libxl_bitmap map;
1741 1742
    uint8_t *bitmask = NULL;
    unsigned int maplen;
1743 1744
    size_t i;
    unsigned int pos;
1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756
    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)) {
1757 1758
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid flag combination: (0x%x)"), flags);
1759 1760 1761 1762
        return -1;
    }

    if (!nvcpus) {
1763
        virReportError(VIR_ERR_INVALID_ARG, "%s", _("nvcpus is zero"));
1764 1765 1766
        return -1;
    }

J
Jim Fehlig 已提交
1767
    if (!(vm = libxlDomObjFromDomain(dom)))
1768 1769
        goto cleanup;

1770 1771 1772
    if (virDomainSetVcpusFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
        goto cleanup;

1773 1774 1775
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

1776
    if (!virDomainObjIsActive(vm) && (flags & VIR_DOMAIN_VCPU_LIVE)) {
1777 1778
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("cannot set vcpus on an inactive domain"));
1779
        goto endjob;
1780 1781 1782
    }

    if (!vm->persistent && (flags & VIR_DOMAIN_VCPU_CONFIG)) {
1783 1784
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("cannot change persistent config of a transient domain"));
1785
        goto endjob;
1786 1787
    }

1788
    if ((max = libxlConnectGetMaxVcpus(dom->conn, NULL)) < 0) {
1789 1790
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("could not determine max vcpus for the domain"));
1791
        goto endjob;
1792 1793
    }

1794
    if (!(flags & VIR_DOMAIN_VCPU_MAXIMUM) && vm->def->maxvcpus < max)
1795 1796 1797
        max = vm->def->maxvcpus;

    if (nvcpus > max) {
1798 1799 1800
        virReportError(VIR_ERR_INVALID_ARG,
                       _("requested vcpus is greater than max allowable"
                         " vcpus for the domain: %d > %d"), nvcpus, max);
1801
        goto endjob;
1802 1803 1804 1805
    }

    priv = vm->privateData;

1806
    if (!(def = virDomainObjGetPersistentDef(cfg->caps, driver->xmlopt, vm)))
1807
        goto endjob;
1808

E
Eric Blake 已提交
1809
    maplen = VIR_CPU_MAPLEN(nvcpus);
1810
    if (VIR_ALLOC_N(bitmask, maplen) < 0)
1811
        goto endjob;
1812 1813

    for (i = 0; i < nvcpus; ++i) {
E
Eric Blake 已提交
1814
        pos = i / 8;
1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 1831 1832
        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:
1833
        if (libxl_set_vcpuonline(priv->ctx, vm->def->id, &map) != 0) {
1834 1835
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Failed to set vcpus for domain '%d'"
1836
                             " with libxenlight"), vm->def->id);
1837
            goto endjob;
1838 1839 1840 1841
        }
        break;

    case VIR_DOMAIN_VCPU_LIVE | VIR_DOMAIN_VCPU_CONFIG:
1842
        if (libxl_set_vcpuonline(priv->ctx, vm->def->id, &map) != 0) {
1843 1844
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Failed to set vcpus for domain '%d'"
1845
                             " with libxenlight"), vm->def->id);
1846
            goto endjob;
1847 1848 1849 1850 1851 1852 1853 1854
        }
        def->vcpus = nvcpus;
        break;
    }

    ret = 0;

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

1857
 endjob:
1858 1859 1860
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

1861
 cleanup:
1862 1863
    VIR_FREE(bitmask);
     if (vm)
1864
        virObjectUnlock(vm);
1865
     virObjectUnref(cfg);
1866 1867 1868 1869 1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880
    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;
1881
    bool active;
1882 1883 1884 1885 1886

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

J
Jim Fehlig 已提交
1887
    if (!(vm = libxlDomObjFromDomain(dom)))
1888 1889
        goto cleanup;

1890
    if (virDomainGetVcpusFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
1891 1892
        goto cleanup;

1893 1894 1895 1896 1897 1898 1899 1900 1901
    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)) {
1902 1903
        virReportError(VIR_ERR_INVALID_ARG,
                       _("invalid flag combination: (0x%x)"), flags);
1904 1905 1906
        return -1;
    }

1907
    if (flags & VIR_DOMAIN_VCPU_LIVE) {
1908
        if (!active) {
1909 1910
            virReportError(VIR_ERR_OPERATION_INVALID,
                           "%s", _("Domain is not running"));
1911 1912 1913 1914
            goto cleanup;
        }
        def = vm->def;
    } else {
1915
        if (!vm->persistent) {
1916 1917
            virReportError(VIR_ERR_OPERATION_INVALID,
                           "%s", _("domain is transient"));
1918 1919
            goto cleanup;
        }
1920 1921 1922 1923 1924
        def = vm->newDef ? vm->newDef : vm->def;
    }

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

1925
 cleanup:
1926
    if (vm)
1927
        virObjectUnlock(vm);
1928 1929 1930 1931
    return ret;
}

static int
1932 1933 1934
libxlDomainPinVcpuFlags(virDomainPtr dom, unsigned int vcpu,
                        unsigned char *cpumap, int maplen,
                        unsigned int flags)
1935 1936
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
1937
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
1938
    virDomainDefPtr targetDef = NULL;
1939
    virBitmapPtr pcpumap = NULL;
1940 1941
    virDomainObjPtr vm;
    int ret = -1;
1942 1943 1944

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);
1945

J
Jim Fehlig 已提交
1946
    if (!(vm = libxlDomObjFromDomain(dom)))
1947 1948
        goto cleanup;

1949
    if (virDomainPinVcpuFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
1950 1951
        goto cleanup;

1952 1953 1954
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

1955
    if ((flags & VIR_DOMAIN_AFFECT_LIVE) && !virDomainObjIsActive(vm)) {
1956
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
1957
                       _("domain is inactive"));
1958
        goto endjob;
1959 1960
    }

1961 1962
    if (virDomainLiveConfigHelperMethod(cfg->caps, driver->xmlopt, vm,
                                        &flags, &targetDef) < 0)
1963
        goto endjob;
1964

1965
    if (flags & VIR_DOMAIN_AFFECT_LIVE)
1966 1967 1968 1969 1970
        targetDef = vm->def;

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

1971 1972
    pcpumap = virBitmapNewData(cpumap, maplen);
    if (!pcpumap)
1973
        goto endjob;
1974

1975 1976 1977 1978 1979
    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
        libxl_bitmap map = { .size = maplen, .map = cpumap };
        libxlDomainObjPrivatePtr priv;

        priv = vm->privateData;
1980
        if (libxl_set_vcpuaffinity(priv->ctx, vm->def->id, vcpu, &map) != 0) {
1981 1982 1983
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Failed to pin vcpu '%d' with libxenlight"),
                           vcpu);
1984
            goto endjob;
1985
        }
1986
    }
1987

1988 1989
    /* full bitmap means reset the settings (if any). */
    if (virBitmapIsAllSet(pcpumap)) {
1990
        virDomainVcpuPinDel(targetDef, vcpu);
1991
        goto done;
1992 1993
    }

1994 1995
    if (!targetDef->cputune.vcpupin) {
        if (VIR_ALLOC(targetDef->cputune.vcpupin) < 0)
1996
            goto endjob;
1997
        targetDef->cputune.nvcpupin = 0;
H
Hu Tao 已提交
1998
    }
1999 2000
    if (virDomainVcpuPinAdd(&targetDef->cputune.vcpupin,
                            &targetDef->cputune.nvcpupin,
H
Hu Tao 已提交
2001 2002 2003
                            cpumap,
                            maplen,
                            vcpu) < 0) {
2004 2005
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       "%s", _("failed to update or add vcpupin xml"));
2006
        goto endjob;
2007 2008
    }

2009
 done:
2010 2011
    ret = 0;

2012 2013 2014 2015 2016 2017
    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
        ret = virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm);
    } else if (flags & VIR_DOMAIN_AFFECT_CONFIG) {
        ret = virDomainSaveConfig(cfg->configDir, targetDef);
    }

2018
 endjob:
2019 2020 2021
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

2022
 cleanup:
2023
    if (vm)
2024
        virObjectUnlock(vm);
2025
    virBitmapFree(pcpumap);
2026
    virObjectUnref(cfg);
2027 2028 2029
    return ret;
}

2030 2031 2032 2033 2034 2035 2036 2037
static int
libxlDomainPinVcpu(virDomainPtr dom, unsigned int vcpu, unsigned char *cpumap,
                   int maplen)
{
    return libxlDomainPinVcpuFlags(dom, vcpu, cpumap, maplen,
                                   VIR_DOMAIN_AFFECT_LIVE);
}

2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065
static int
libxlDomainGetVcpuPinInfo(virDomainPtr dom, int ncpumaps,
                          unsigned char *cpumaps, int maplen,
                          unsigned int flags)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
    virDomainObjPtr vm = NULL;
    virDomainDefPtr targetDef = NULL;
    virDomainVcpuPinDefPtr *vcpupin_list;
    virBitmapPtr cpumask = NULL;
    int maxcpu, hostcpus, vcpu, pcpu, n, ret = -1;
    unsigned char *cpumap;
    bool pinned;

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

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

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

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

2066
    if (flags & VIR_DOMAIN_AFFECT_LIVE)
2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107
        targetDef = vm->def;

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

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

    /* we use cfg->ctx, as vm->privateData->ctx may be NULL if VM is down. */
    if ((hostcpus = libxl_get_max_cpus(cfg->ctx)) < 0)
        goto cleanup;

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

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

    /* if vcpupin setting exists, there may be unused pcpus */
    for (n = 0; n < targetDef->cputune.nvcpupin; n++) {
        vcpupin_list = targetDef->cputune.vcpupin;
        vcpu = vcpupin_list[n]->vcpuid;
        cpumask = vcpupin_list[n]->cpumask;
        cpumap = VIR_GET_CPUMAP(cpumaps, maplen, vcpu);
        for (pcpu = 0; pcpu < maxcpu; pcpu++) {
            if (virBitmapGetBit(cpumask, pcpu, &pinned) < 0)
                goto cleanup;
            if (!pinned)
                VIR_UNUSE_CPU(cpumap, pcpu);
        }
    }
    ret = ncpumaps;

2108
 cleanup:
2109 2110 2111 2112 2113
    if (vm)
        virObjectUnlock(vm);
    virObjectUnref(cfg);
    return ret;
}
2114 2115 2116 2117 2118 2119 2120 2121 2122 2123

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;
2124
    size_t i;
2125 2126
    unsigned char *cpumap;

J
Jim Fehlig 已提交
2127
    if (!(vm = libxlDomObjFromDomain(dom)))
2128 2129
        goto cleanup;

2130 2131 2132
    if (virDomainGetVcpusEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

2133
    if (!virDomainObjIsActive(vm)) {
2134
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
2135 2136 2137 2138
        goto cleanup;
    }

    priv = vm->privateData;
2139
    if ((vcpuinfo = libxl_list_vcpu(priv->ctx, vm->def->id, &maxcpu,
2140
                                    &hostcpus)) == NULL) {
2141 2142
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to list vcpus for domain '%d' with libxenlight"),
2143
                       vm->def->id);
2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165
        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 已提交
2166
        libxl_vcpuinfo_dispose(&vcpuinfo[i]);
2167 2168 2169 2170 2171
    }
    VIR_FREE(vcpuinfo);

    ret = maxinfo;

2172
 cleanup:
2173
    if (vm)
2174
        virObjectUnlock(vm);
2175 2176 2177
    return ret;
}

J
Jim Fehlig 已提交
2178
static char *
2179
libxlDomainGetXMLDesc(virDomainPtr dom, unsigned int flags)
J
Jim Fehlig 已提交
2180 2181 2182 2183
{
    virDomainObjPtr vm;
    char *ret = NULL;

2184 2185
    /* Flags checked by virDomainDefFormat */

J
Jim Fehlig 已提交
2186
    if (!(vm = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
2187 2188
        goto cleanup;

2189 2190 2191
    if (virDomainGetXMLDescEnsureACL(dom->conn, vm->def, flags) < 0)
        goto cleanup;

J
Jim Fehlig 已提交
2192 2193
    ret = virDomainDefFormat(vm->def, flags);

2194
 cleanup:
J
Jim Fehlig 已提交
2195
    if (vm)
2196
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
2197 2198 2199
    return ret;
}

2200
static char *
2201 2202 2203
libxlConnectDomainXMLFromNative(virConnectPtr conn,
                                const char *nativeFormat,
                                const char *nativeConfig,
2204
                                unsigned int flags)
2205 2206
{
    libxlDriverPrivatePtr driver = conn->privateData;
2207
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
2208 2209 2210 2211
    virDomainDefPtr def = NULL;
    virConfPtr conf = NULL;
    char *xml = NULL;

E
Eric Blake 已提交
2212 2213
    virCheckFlags(0, NULL);

2214 2215 2216
    if (virConnectDomainXMLFromNativeEnsureACL(conn) < 0)
        goto cleanup;

2217
    if (STREQ(nativeFormat, LIBXL_CONFIG_FORMAT_XM)) {
2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228 2229 2230 2231 2232 2233 2234 2235 2236 2237 2238
        if (!(conf = virConfReadMem(nativeConfig, strlen(nativeConfig), 0)))
            goto cleanup;

        if (!(def = xenParseXM(conf,
                               cfg->verInfo->xen_version_major,
                               cfg->caps))) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("parsing xm config failed"));
            goto cleanup;
        }
    } else if (STREQ(nativeFormat, LIBXL_CONFIG_FORMAT_SEXPR)) {
        /* only support latest xend config format */
        if (!(def = xenParseSxprString(nativeConfig,
                                       XEND_CONFIG_VERSION_3_1_0,
                                       NULL,
                                       -1))) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("parsing sxpr config failed"));
            goto cleanup;
        }
    } else {
2239 2240
        virReportError(VIR_ERR_INVALID_ARG,
                       _("unsupported config type %s"), nativeFormat);
2241 2242 2243 2244 2245
        goto cleanup;
    }

    xml = virDomainDefFormat(def, VIR_DOMAIN_XML_INACTIVE);

2246
 cleanup:
2247 2248 2249
    virDomainDefFree(def);
    if (conf)
        virConfFree(conf);
2250
    virObjectUnref(cfg);
2251 2252 2253 2254 2255
    return xml;
}

#define MAX_CONFIG_SIZE (1024 * 65)
static char *
2256 2257 2258
libxlConnectDomainXMLToNative(virConnectPtr conn, const char * nativeFormat,
                              const char * domainXml,
                              unsigned int flags)
2259 2260
{
    libxlDriverPrivatePtr driver = conn->privateData;
2261
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
2262 2263 2264 2265 2266
    virDomainDefPtr def = NULL;
    virConfPtr conf = NULL;
    int len = MAX_CONFIG_SIZE;
    char *ret = NULL;

E
Eric Blake 已提交
2267 2268
    virCheckFlags(0, NULL);

2269 2270 2271
    if (virConnectDomainXMLToNativeEnsureACL(conn) < 0)
        goto cleanup;

2272 2273 2274 2275 2276 2277
    if (STRNEQ(nativeFormat, LIBXL_CONFIG_FORMAT_XM)) {
        virReportError(VIR_ERR_INVALID_ARG,
                       _("unsupported config type %s"), nativeFormat);
        goto cleanup;
    }

2278
    if (!(def = virDomainDefParseString(domainXml,
2279
                                        cfg->caps, driver->xmlopt,
2280 2281
                                        1 << VIR_DOMAIN_VIRT_XEN,
                                        VIR_DOMAIN_XML_INACTIVE)))
2282 2283
        goto cleanup;

2284
    if (!(conf = xenFormatXM(conn, def, cfg->verInfo->xen_version_major)))
2285 2286
        goto cleanup;

2287
    if (VIR_ALLOC_N(ret, len) < 0)
2288 2289 2290 2291 2292 2293 2294
        goto cleanup;

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

2295
 cleanup:
2296 2297 2298
    virDomainDefFree(def);
    if (conf)
        virConfFree(conf);
2299
    virObjectUnref(cfg);
2300 2301 2302
    return ret;
}

J
Jim Fehlig 已提交
2303
static int
2304 2305
libxlConnectListDefinedDomains(virConnectPtr conn,
                               char **const names, int nnames)
J
Jim Fehlig 已提交
2306 2307 2308 2309
{
    libxlDriverPrivatePtr driver = conn->privateData;
    int n;

2310 2311 2312
    if (virConnectListDefinedDomainsEnsureACL(conn) < 0)
        return -1;

2313 2314
    n = virDomainObjListGetInactiveNames(driver->domains, names, nnames,
                                         virConnectListDefinedDomainsCheckACL, conn);
J
Jim Fehlig 已提交
2315 2316 2317 2318
    return n;
}

static int
2319
libxlConnectNumOfDefinedDomains(virConnectPtr conn)
J
Jim Fehlig 已提交
2320 2321 2322 2323
{
    libxlDriverPrivatePtr driver = conn->privateData;
    int n;

2324 2325 2326
    if (virConnectNumOfDefinedDomainsEnsureACL(conn) < 0)
        return -1;

2327
    n = virDomainObjListNumOfDomains(driver->domains, false,
2328 2329
                                     virConnectNumOfDefinedDomainsCheckACL,
                                     conn);
J
Jim Fehlig 已提交
2330 2331 2332 2333 2334
    return n;
}

static int
libxlDomainCreateWithFlags(virDomainPtr dom,
E
Eric Blake 已提交
2335
                           unsigned int flags)
J
Jim Fehlig 已提交
2336 2337 2338 2339 2340 2341 2342
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_START_PAUSED, -1);

J
Jim Fehlig 已提交
2343
    if (!(vm = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
2344 2345
        goto cleanup;

2346 2347 2348
    if (virDomainCreateWithFlagsEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

J
Jim Fehlig 已提交
2349
    if (virDomainObjIsActive(vm)) {
2350 2351
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("Domain is already running"));
J
Jim Fehlig 已提交
2352 2353 2354
        goto cleanup;
    }

2355
    ret = libxlDomainStart(driver, vm, (flags & VIR_DOMAIN_START_PAUSED) != 0, -1);
J
Jim Fehlig 已提交
2356

2357
 cleanup:
J
Jim Fehlig 已提交
2358
    if (vm)
2359
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372
    return ret;
}

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

static virDomainPtr
libxlDomainDefineXML(virConnectPtr conn, const char *xml)
{
    libxlDriverPrivatePtr driver = conn->privateData;
2373
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
J
Jim Fehlig 已提交
2374 2375 2376
    virDomainDefPtr def = NULL;
    virDomainObjPtr vm = NULL;
    virDomainPtr dom = NULL;
2377
    virObjectEventPtr event = NULL;
2378
    virDomainDefPtr oldDef = NULL;
J
Jim Fehlig 已提交
2379

2380
    if (!(def = virDomainDefParseString(xml, cfg->caps, driver->xmlopt,
M
Matthias Bolte 已提交
2381
                                        1 << VIR_DOMAIN_VIRT_XEN,
J
Jim Fehlig 已提交
2382
                                        VIR_DOMAIN_XML_INACTIVE)))
2383
        goto cleanup;
J
Jim Fehlig 已提交
2384

2385
    if (virDomainDefineXMLEnsureACL(conn, def) < 0)
2386
        goto cleanup;
2387

2388
    if (!(vm = virDomainObjListAdd(driver->domains, def,
2389
                                   driver->xmlopt,
2390 2391
                                   0,
                                   &oldDef)))
2392
        goto cleanup;
2393

J
Jim Fehlig 已提交
2394 2395 2396
    def = NULL;
    vm->persistent = 1;

2397
    if (virDomainSaveConfig(cfg->configDir,
J
Jim Fehlig 已提交
2398
                            vm->newDef ? vm->newDef : vm->def) < 0) {
2399
        virDomainObjListRemove(driver->domains, vm);
J
Jim Fehlig 已提交
2400 2401 2402 2403 2404 2405 2406 2407
        vm = NULL;
        goto cleanup;
    }

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

2408
    event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_DEFINED,
2409
                                     !oldDef ?
2410 2411 2412
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED :
                                     VIR_DOMAIN_EVENT_DEFINED_UPDATED);

2413
 cleanup:
J
Jim Fehlig 已提交
2414
    virDomainDefFree(def);
2415
    virDomainDefFree(oldDef);
J
Jim Fehlig 已提交
2416
    if (vm)
2417
        virObjectUnlock(vm);
2418 2419
    if (event)
        libxlDomainEventQueue(driver, event);
2420
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
2421 2422 2423 2424
    return dom;
}

static int
2425 2426
libxlDomainUndefineFlags(virDomainPtr dom,
                         unsigned int flags)
J
Jim Fehlig 已提交
2427 2428
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
2429
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
J
Jim Fehlig 已提交
2430
    virDomainObjPtr vm;
2431
    virObjectEventPtr event = NULL;
2432
    char *name = NULL;
J
Jim Fehlig 已提交
2433 2434
    int ret = -1;

2435 2436
    virCheckFlags(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE, -1);

J
Jim Fehlig 已提交
2437
    if (!(vm = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
2438 2439
        goto cleanup;

2440 2441 2442
    if (virDomainUndefineFlagsEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

J
Jim Fehlig 已提交
2443
    if (!vm->persistent) {
2444 2445
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("cannot undefine transient domain"));
J
Jim Fehlig 已提交
2446 2447 2448
        goto cleanup;
    }

2449 2450 2451 2452 2453 2454 2455
    name = libxlDomainManagedSavePath(driver, vm);
    if (name == NULL)
        goto cleanup;

    if (virFileExists(name)) {
        if (flags & VIR_DOMAIN_UNDEFINE_MANAGED_SAVE) {
            if (unlink(name) < 0) {
2456 2457
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("Failed to remove domain managed save image"));
2458 2459 2460
                goto cleanup;
            }
        } else {
2461 2462 2463
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                           _("Refusing to undefine while domain managed "
                             "save image exists"));
2464 2465 2466 2467
            goto cleanup;
        }
    }

2468
    if (virDomainDeleteConfig(cfg->configDir, cfg->autostartDir, vm) < 0)
J
Jim Fehlig 已提交
2469 2470
        goto cleanup;

2471
    event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_UNDEFINED,
2472 2473
                                     VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);

2474 2475 2476
    if (virDomainObjIsActive(vm)) {
        vm->persistent = 0;
    } else {
2477
        virDomainObjListRemove(driver->domains, vm);
2478 2479 2480
        vm = NULL;
    }

J
Jim Fehlig 已提交
2481 2482
    ret = 0;

2483
 cleanup:
2484
    VIR_FREE(name);
J
Jim Fehlig 已提交
2485
    if (vm)
2486
        virObjectUnlock(vm);
2487 2488
    if (event)
        libxlDomainEventQueue(driver, event);
2489
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
2490 2491 2492
    return ret;
}

2493 2494 2495 2496 2497 2498
static int
libxlDomainUndefine(virDomainPtr dom)
{
    return libxlDomainUndefineFlags(dom, 0);
}

2499 2500 2501 2502 2503 2504
static int
libxlDomainChangeEjectableMedia(libxlDomainObjPrivatePtr priv,
                                virDomainObjPtr vm, virDomainDiskDefPtr disk)
{
    virDomainDiskDefPtr origdisk = NULL;
    libxl_device_disk x_disk;
2505
    size_t i;
2506 2507
    int ret = -1;

2508
    for (i = 0; i < vm->def->ndisks; i++) {
2509 2510 2511 2512 2513 2514 2515 2516
        if (vm->def->disks[i]->bus == disk->bus &&
            STREQ(vm->def->disks[i]->dst, disk->dst)) {
            origdisk = vm->def->disks[i];
            break;
        }
    }

    if (!origdisk) {
2517 2518 2519
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("No device with bus '%s' and target '%s'"),
                       virDomainDiskBusTypeToString(disk->bus), disk->dst);
2520 2521 2522 2523
        goto cleanup;
    }

    if (origdisk->device != VIR_DOMAIN_DISK_DEVICE_CDROM) {
2524 2525 2526
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Removable media not supported for %s device"),
                       virDomainDiskDeviceTypeToString(disk->device));
2527 2528 2529
        return -1;
    }

J
Jim Fehlig 已提交
2530
    if (libxlMakeDisk(disk, &x_disk) < 0)
2531 2532
        goto cleanup;

J
Jim Fehlig 已提交
2533
    if ((ret = libxl_cdrom_insert(priv->ctx, vm->def->id, &x_disk, NULL)) < 0) {
2534 2535 2536
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("libxenlight failed to change media for disk '%s'"),
                       disk->dst);
2537 2538 2539
        goto cleanup;
    }

2540 2541 2542
    if (virDomainDiskSetSource(origdisk, virDomainDiskGetSource(disk)) < 0)
        goto cleanup;
    virDomainDiskSetType(origdisk, virDomainDiskGetType(disk));
2543 2544 2545 2546 2547

    virDomainDiskDefFree(disk);

    ret = 0;

2548
 cleanup:
2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565
    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) {
2566
                if (virDomainDiskIndexByName(vm->def, l_disk->dst, true) >= 0) {
2567 2568
                    virReportError(VIR_ERR_OPERATION_FAILED,
                                   _("target %s already exists"), l_disk->dst);
2569 2570 2571
                    goto cleanup;
                }

2572
                if (!virDomainDiskGetSource(l_disk)) {
2573 2574
                    virReportError(VIR_ERR_INTERNAL_ERROR,
                                   "%s", _("disk source path is missing"));
2575 2576 2577
                    goto cleanup;
                }

2578
                if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks+1) < 0)
2579 2580
                    goto cleanup;

J
Jim Fehlig 已提交
2581
                if (libxlMakeDisk(l_disk, &x_disk) < 0)
2582 2583
                    goto cleanup;

J
Jim Fehlig 已提交
2584 2585
                if ((ret = libxl_device_disk_add(priv->ctx, vm->def->id,
                                                &x_disk, NULL)) < 0) {
2586 2587 2588
                    virReportError(VIR_ERR_INTERNAL_ERROR,
                                   _("libxenlight failed to attach disk '%s'"),
                                   l_disk->dst);
2589 2590 2591 2592 2593 2594
                    goto cleanup;
                }

                virDomainDiskInsertPreAlloced(vm->def, l_disk);

            } else {
2595 2596 2597
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("disk bus '%s' cannot be hotplugged."),
                               virDomainDiskBusTypeToString(l_disk->bus));
2598 2599 2600
            }
            break;
        default:
2601 2602 2603
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("disk device type '%s' cannot be hotplugged"),
                           virDomainDiskDeviceTypeToString(l_disk->device));
2604 2605 2606
            break;
    }

2607
 cleanup:
2608 2609 2610
    return ret;
}

2611 2612 2613 2614 2615 2616 2617 2618 2619
static int
libxlDomainAttachHostPCIDevice(libxlDriverPrivatePtr driver,
                               libxlDomainObjPrivatePtr priv,
                               virDomainObjPtr vm,
                               virDomainHostdevDefPtr hostdev)
{
    libxl_device_pci pcidev;
    virDomainHostdevDefPtr found;
    virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
2620
    virDomainHostdevSubsysPCIPtr pcisrc = &hostdev->source.subsys.u.pci;
2621 2622 2623 2624 2625 2626 2627

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

    if (virDomainHostdevFind(vm->def, hostdev, &found) >= 0) {
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("target pci device %.4x:%.2x:%.2x.%.1x already exists"),
2628 2629
                       pcisrc->addr.domain, pcisrc->addr.bus,
                       pcisrc->addr.slot, pcisrc->addr.function);
2630 2631 2632 2633 2634 2635 2636 2637 2638
        return -1;
    }

    if (VIR_REALLOC_N(vm->def->hostdevs, vm->def->nhostdevs + 1) < 0)
        return -1;

    if (virHostdevPreparePCIDevices(hostdev_mgr, LIBXL_DRIVER_NAME,
                                    vm->def->name, vm->def->uuid,
                                    &hostdev, 1, 0) < 0)
C
Chunyan Liu 已提交
2639
        return -1;
2640

2641
    if (libxlMakePCI(hostdev, &pcidev) < 0)
C
Chunyan Liu 已提交
2642
        goto error;
2643 2644 2645 2646

    if (libxl_device_pci_add(priv->ctx, vm->def->id, &pcidev, 0) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("libxenlight failed to attach pci device %.4x:%.2x:%.2x.%.1x"),
2647 2648
                       pcisrc->addr.domain, pcisrc->addr.bus,
                       pcisrc->addr.slot, pcisrc->addr.function);
C
Chunyan Liu 已提交
2649
        goto error;
2650 2651 2652 2653 2654
    }

    vm->def->hostdevs[vm->def->nhostdevs++] = hostdev;
    return 0;

2655
 error:
2656 2657 2658 2659 2660 2661 2662 2663 2664
    virHostdevReAttachPCIDevices(hostdev_mgr, LIBXL_DRIVER_NAME,
                                 vm->def->name, &hostdev, 1, NULL);
    return -1;
}

static int
libxlDomainAttachHostDevice(libxlDriverPrivatePtr driver,
                            libxlDomainObjPrivatePtr priv,
                            virDomainObjPtr vm,
2665
                            virDomainHostdevDefPtr hostdev)
2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676
{
    if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS) {
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("hostdev mode '%s' not supported"),
                       virDomainHostdevModeTypeToString(hostdev->mode));
        return -1;
    }

    switch (hostdev->source.subsys.type) {
    case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
        if (libxlDomainAttachHostPCIDevice(driver, priv, vm, hostdev) < 0)
C
Chunyan Liu 已提交
2677
            return -1;
2678 2679 2680 2681 2682 2683
        break;

    default:
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("hostdev subsys type '%s' not supported"),
                       virDomainHostdevSubsysTypeToString(hostdev->source.subsys.type));
C
Chunyan Liu 已提交
2684
        return -1;
2685 2686 2687 2688 2689
    }

    return 0;
}

2690 2691 2692 2693 2694 2695
static int
libxlDomainDetachDeviceDiskLive(libxlDomainObjPrivatePtr priv,
                                virDomainObjPtr vm, virDomainDeviceDefPtr dev)
{
    virDomainDiskDefPtr l_disk = NULL;
    libxl_device_disk x_disk;
2696
    int idx;
2697 2698 2699 2700 2701 2702
    int ret = -1;

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

2703 2704 2705
                if ((idx = virDomainDiskIndexByName(vm->def,
                                                    dev->data.disk->dst,
                                                    false)) < 0) {
2706 2707
                    virReportError(VIR_ERR_OPERATION_FAILED,
                                   _("disk %s not found"), dev->data.disk->dst);
2708 2709 2710
                    goto cleanup;
                }

2711
                l_disk = vm->def->disks[idx];
2712

J
Jim Fehlig 已提交
2713
                if (libxlMakeDisk(l_disk, &x_disk) < 0)
2714 2715
                    goto cleanup;

J
Jim Fehlig 已提交
2716 2717
                if ((ret = libxl_device_disk_remove(priv->ctx, vm->def->id,
                                                    &x_disk, NULL)) < 0) {
2718 2719 2720
                    virReportError(VIR_ERR_INTERNAL_ERROR,
                                   _("libxenlight failed to detach disk '%s'"),
                                   l_disk->dst);
2721 2722 2723
                    goto cleanup;
                }

2724
                virDomainDiskRemove(vm->def, idx);
2725 2726 2727
                virDomainDiskDefFree(l_disk);

            } else {
2728 2729 2730
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("disk bus '%s' cannot be hot unplugged."),
                               virDomainDiskBusTypeToString(dev->data.disk->bus));
2731 2732 2733
            }
            break;
        default:
2734 2735 2736
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("device type '%s' cannot hot unplugged"),
                           virDomainDiskDeviceTypeToString(dev->data.disk->device));
2737 2738 2739
            break;
    }

2740
 cleanup:
2741 2742 2743
    return ret;
}

2744 2745 2746 2747 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797
static int
libxlDomainAttachNetDevice(libxlDriverPrivatePtr driver,
                           libxlDomainObjPrivatePtr priv,
                           virDomainObjPtr vm,
                           virDomainNetDefPtr net)
{
    int actualType;
    libxl_device_nic nic;
    int ret = -1;

    /* preallocate new slot for device */
    if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets + 1) < 0)
        return -1;

    /* If appropriate, grab a physical device from the configured
     * network's pool of devices, or resolve bridge device name
     * to the one defined in the network definition.
     */
    if (networkAllocateActualDevice(vm->def, net) < 0)
        return -1;

    actualType = virDomainNetGetActualType(net);

    if (actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
        /* This is really a "smart hostdev", so it should be attached
         * as a hostdev (the hostdev code will reach over into the
         * netdev-specific code as appropriate), then also added to
         * the nets list (see out:) if successful.
         */
        ret = libxlDomainAttachHostDevice(driver, priv, vm,
                                          virDomainNetGetActualHostdev(net));
        goto out;
    }

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

    if (libxl_device_nic_add(priv->ctx, vm->def->id, &nic, 0)) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("libxenlight failed to attach network device"));
        goto cleanup;
    }

    ret = 0;

 cleanup:
    libxl_device_nic_dispose(&nic);
 out:
    if (!ret)
        vm->def->nets[vm->def->nnets++] = net;
    return ret;
}

2798
static int
2799 2800 2801
libxlDomainAttachDeviceLive(libxlDriverPrivatePtr driver,
                            libxlDomainObjPrivatePtr priv,
                            virDomainObjPtr vm,
2802 2803 2804 2805 2806 2807 2808 2809 2810 2811 2812
                            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;

2813 2814 2815 2816 2817 2818 2819
        case VIR_DOMAIN_DEVICE_NET:
            ret = libxlDomainAttachNetDevice(driver, priv, vm,
                                             dev->data.net);
            if (!ret)
                dev->data.net = NULL;
            break;

2820
        case VIR_DOMAIN_DEVICE_HOSTDEV:
2821 2822
            ret = libxlDomainAttachHostDevice(driver, priv, vm,
                                              dev->data.hostdev);
2823 2824 2825 2826
            if (!ret)
                dev->data.hostdev = NULL;
            break;

2827
        default:
2828 2829 2830
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("device type '%s' cannot be attached"),
                           virDomainDeviceTypeToString(dev->type));
2831 2832 2833 2834 2835 2836 2837 2838 2839 2840
            break;
    }

    return ret;
}

static int
libxlDomainAttachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev)
{
    virDomainDiskDefPtr disk;
2841
    virDomainNetDefPtr net;
2842 2843
    virDomainHostdevDefPtr hostdev;
    virDomainHostdevDefPtr found;
2844
    virDomainHostdevSubsysPCIPtr pcisrc;
2845 2846 2847 2848

    switch (dev->type) {
        case VIR_DOMAIN_DEVICE_DISK:
            disk = dev->data.disk;
2849
            if (virDomainDiskIndexByName(vmdef, disk->dst, true) >= 0) {
2850 2851
                virReportError(VIR_ERR_INVALID_ARG,
                               _("target %s already exists."), disk->dst);
2852 2853
                return -1;
            }
2854
            if (virDomainDiskInsert(vmdef, disk))
2855 2856 2857 2858
                return -1;
            /* vmdef has the pointer. Generic codes for vmdef will do all jobs */
            dev->data.disk = NULL;
            break;
2859 2860 2861 2862 2863 2864 2865 2866

        case VIR_DOMAIN_DEVICE_NET:
            net = dev->data.net;
            if (virDomainNetInsert(vmdef, net))
                return -1;
            dev->data.net = NULL;
            break;

2867 2868 2869 2870 2871 2872 2873
        case VIR_DOMAIN_DEVICE_HOSTDEV:
            hostdev = dev->data.hostdev;

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

            if (virDomainHostdevFind(vmdef, hostdev, &found) >= 0) {
2874
                pcisrc = &hostdev->source.subsys.u.pci;
2875 2876 2877
                virReportError(VIR_ERR_OPERATION_FAILED,
                               _("target pci device %.4x:%.2x:%.2x.%.1x\
                                  already exists"),
2878 2879
                               pcisrc->addr.domain, pcisrc->addr.bus,
                               pcisrc->addr.slot, pcisrc->addr.function);
2880 2881 2882
                return -1;
            }

2883 2884
            if (virDomainHostdevInsert(vmdef, hostdev) < 0)
                return -1;
2885
            break;
2886 2887

        default:
2888 2889
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("persistent attach of device is not supported"));
2890 2891 2892 2893 2894 2895
            return -1;
    }
    return 0;
}

static int
2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930
libxlComparePCIDevice(virDomainDefPtr def ATTRIBUTE_UNUSED,
                      virDomainDeviceDefPtr device ATTRIBUTE_UNUSED,
                      virDomainDeviceInfoPtr info1,
                      void *opaque)
{
    virDomainDeviceInfoPtr info2 = opaque;

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

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

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

static int
libxlDomainDetachHostPCIDevice(libxlDriverPrivatePtr driver,
                               libxlDomainObjPrivatePtr priv,
                               virDomainObjPtr vm,
                               virDomainHostdevDefPtr hostdev)
{
    virDomainHostdevSubsysPtr subsys = &hostdev->source.subsys;
2931
    virDomainHostdevSubsysPCIPtr pcisrc = &subsys->u.pci;
2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943
    libxl_device_pci pcidev;
    virDomainHostdevDefPtr detach;
    int idx;
    virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;

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

    idx = virDomainHostdevFind(vm->def, hostdev, &detach);
    if (idx < 0) {
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("host pci device %.4x:%.2x:%.2x.%.1x not found"),
2944 2945
                       pcisrc->addr.domain, pcisrc->addr.bus,
                       pcisrc->addr.slot, pcisrc->addr.function);
2946 2947 2948 2949 2950 2951
        return -1;
    }

    if (libxlIsMultiFunctionDevice(vm->def, detach->info)) {
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("cannot hot unplug multifunction PCI device: %.4x:%.2x:%.2x.%.1x"),
2952 2953
                       pcisrc->addr.domain, pcisrc->addr.bus,
                       pcisrc->addr.slot, pcisrc->addr.function);
C
Chunyan Liu 已提交
2954
        goto error;
2955 2956 2957 2958 2959
    }


    libxl_device_pci_init(&pcidev);

2960
    if (libxlMakePCI(detach, &pcidev) < 0)
C
Chunyan Liu 已提交
2961
        goto error;
2962 2963 2964 2965 2966

    if (libxl_device_pci_remove(priv->ctx, vm->def->id, &pcidev, 0) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("libxenlight failed to detach pci device\
                          %.4x:%.2x:%.2x.%.1x"),
2967 2968
                       pcisrc->addr.domain, pcisrc->addr.bus,
                       pcisrc->addr.slot, pcisrc->addr.function);
C
Chunyan Liu 已提交
2969
        goto error;
2970 2971 2972 2973 2974 2975 2976 2977 2978 2979 2980
    }

    libxl_device_pci_dispose(&pcidev);

    virDomainHostdevRemove(vm->def, idx);

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

    return 0;

2981
 error:
2982 2983 2984 2985 2986 2987 2988 2989
    virDomainHostdevDefFree(detach);
    return -1;
}

static int
libxlDomainDetachHostDevice(libxlDriverPrivatePtr driver,
                            libxlDomainObjPrivatePtr priv,
                            virDomainObjPtr vm,
2990
                            virDomainHostdevDefPtr hostdev)
2991 2992 2993 2994 2995 2996 2997 2998 2999 3000 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013
{
    virDomainHostdevSubsysPtr subsys = &hostdev->source.subsys;

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

    switch (subsys->type) {
        case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI:
            return libxlDomainDetachHostPCIDevice(driver, priv, vm, hostdev);

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

    return -1;
}

3014 3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060
static int
libxlDomainDetachNetDevice(libxlDriverPrivatePtr driver,
                           libxlDomainObjPrivatePtr priv,
                           virDomainObjPtr vm,
                           virDomainNetDefPtr net)
{
    int detachidx;
    virDomainNetDefPtr detach = NULL;
    libxl_device_nic nic;
    char mac[VIR_MAC_STRING_BUFLEN];
    int ret = -1;

    if ((detachidx = virDomainNetFindIdx(vm->def, net)) < 0)
        return -1;

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

    if (virDomainNetGetActualType(detach) == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
        /* This is really a "smart hostdev", so it should be attached as a
         * hostdev, then also removed from nets list (see out:) if successful.
         */
        ret = libxlDomainDetachHostDevice(driver, priv, vm,
                                          virDomainNetGetActualHostdev(detach));
        goto out;
    }

    libxl_device_nic_init(&nic);
    if (libxl_mac_to_device_nic(priv->ctx, vm->def->id,
                                virMacAddrFormat(&detach->mac, mac), &nic))
        goto cleanup;

    if (libxl_device_nic_remove(priv->ctx, vm->def->id, &nic, 0)) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("libxenlight failed to detach network device"));
        goto cleanup;
    }

    ret = 0;

 cleanup:
    libxl_device_nic_dispose(&nic);
 out:
    if (!ret)
        virDomainNetRemove(vm->def, detachidx);
    return ret;
}

3061 3062 3063 3064
static int
libxlDomainDetachDeviceLive(libxlDriverPrivatePtr driver,
                            libxlDomainObjPrivatePtr priv,
                            virDomainObjPtr vm,
3065 3066 3067 3068 3069 3070 3071 3072 3073
                            virDomainDeviceDefPtr dev)
{
    int ret = -1;

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

3074 3075 3076 3077 3078
        case VIR_DOMAIN_DEVICE_NET:
            ret = libxlDomainDetachNetDevice(driver, priv, vm,
                                             dev->data.net);
            break;

3079
        case VIR_DOMAIN_DEVICE_HOSTDEV:
3080 3081
            ret = libxlDomainDetachHostDevice(driver, priv, vm,
                                              dev->data.hostdev);
3082 3083
            break;

3084
        default:
3085 3086 3087
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("device type '%s' cannot be detached"),
                           virDomainDeviceTypeToString(dev->type));
3088 3089 3090 3091 3092 3093
            break;
    }

    return ret;
}

3094

3095 3096 3097
static int
libxlDomainDetachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev)
{
3098
    virDomainDiskDefPtr disk, detach;
3099
    virDomainHostdevDefPtr hostdev, det_hostdev;
3100
    virDomainNetDefPtr net;
3101
    int idx;
3102 3103 3104 3105

    switch (dev->type) {
        case VIR_DOMAIN_DEVICE_DISK:
            disk = dev->data.disk;
3106
            if (!(detach = virDomainDiskRemoveByName(vmdef, disk->dst))) {
3107 3108
                virReportError(VIR_ERR_INVALID_ARG,
                               _("no target device %s"), disk->dst);
3109
                return -1;
3110
            }
3111
            virDomainDiskDefFree(detach);
3112
            break;
3113

3114 3115 3116 3117 3118 3119 3120 3121 3122
        case VIR_DOMAIN_DEVICE_NET:
            net = dev->data.net;
            if ((idx = virDomainNetFindIdx(vmdef, net)) < 0)
                return -1;

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

3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134
        case VIR_DOMAIN_DEVICE_HOSTDEV: {
            hostdev = dev->data.hostdev;
            if ((idx = virDomainHostdevFind(vmdef, hostdev, &det_hostdev)) < 0) {
                virReportError(VIR_ERR_INVALID_ARG, "%s",
                               _("device not present in domain configuration"));
                return -1;
            }
            virDomainHostdevRemove(vmdef, idx);
            virDomainHostdevDefFree(det_hostdev);
            break;
        }

3135
        default:
3136 3137
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("persistent detach of device is not supported"));
3138
            return -1;
3139 3140
    }

3141
    return 0;
3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160
}

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:
3161 3162 3163
                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                                   _("disk bus '%s' cannot be updated."),
                                   virDomainDiskBusTypeToString(disk->bus));
3164 3165 3166 3167
                    break;
            }
            break;
        default:
3168 3169 3170
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("device type '%s' cannot be updated"),
                           virDomainDeviceTypeToString(dev->type));
3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181
            break;
    }

    return ret;
}

static int
libxlDomainUpdateDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev)
{
    virDomainDiskDefPtr orig;
    virDomainDiskDefPtr disk;
3182
    int idx;
3183 3184 3185 3186 3187
    int ret = -1;

    switch (dev->type) {
        case VIR_DOMAIN_DEVICE_DISK:
            disk = dev->data.disk;
3188
            if ((idx = virDomainDiskIndexByName(vmdef, disk->dst, false)) < 0) {
3189 3190
                virReportError(VIR_ERR_INVALID_ARG,
                               _("target %s doesn't exist."), disk->dst);
3191 3192
                goto cleanup;
            }
3193
            orig = vmdef->disks[idx];
3194
            if (!(orig->device == VIR_DOMAIN_DISK_DEVICE_CDROM)) {
3195 3196
                virReportError(VIR_ERR_INVALID_ARG, "%s",
                               _("this disk doesn't support update"));
3197 3198 3199
                goto cleanup;
            }

3200 3201 3202 3203 3204 3205
            if (virDomainDiskSetSource(orig, virDomainDiskGetSource(disk)) < 0)
                goto cleanup;
            virDomainDiskSetType(orig, virDomainDiskGetType(disk));
            virDomainDiskSetFormat(orig, virDomainDiskGetFormat(disk));
            if (virDomainDiskSetDriver(orig, virDomainDiskGetDriver(disk)) < 0)
                goto cleanup;
3206 3207
            break;
        default:
3208 3209
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("persistent update of device is not supported"));
3210 3211 3212 3213 3214
            goto cleanup;
    }

    ret = 0;

3215
 cleanup:
3216 3217 3218 3219 3220
    return ret;
}


static int
3221 3222
libxlDomainAttachDeviceFlags(virDomainPtr dom, const char *xml,
                             unsigned int flags)
3223 3224
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
3225
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
3226 3227 3228 3229 3230 3231 3232 3233 3234
    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 已提交
3235
    if (!(vm = libxlDomObjFromDomain(dom)))
3236 3237
        goto cleanup;

3238 3239 3240
    if (virDomainAttachDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
        goto cleanup;

3241 3242 3243
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

3244 3245 3246 3247 3248 3249 3250 3251
    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) {
3252 3253
            virReportError(VIR_ERR_OPERATION_INVALID,
                           "%s", _("Domain is not running"));
3254
            goto endjob;
3255 3256 3257 3258
        }
    }

    if ((flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) && !vm->persistent) {
3259 3260
         virReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("cannot modify device on transient domain"));
3261
         goto endjob;
3262 3263 3264 3265 3266
    }

    priv = vm->privateData;

    if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
3267
        if (!(dev = virDomainDeviceDefParse(xml, vm->def,
3268
                                            cfg->caps, driver->xmlopt,
3269
                                            VIR_DOMAIN_XML_INACTIVE)))
3270
            goto endjob;
3271 3272

        /* Make a copy for updated domain. */
3273
        if (!(vmdef = virDomainObjCopyPersistentDef(vm, cfg->caps,
3274
                                                    driver->xmlopt)))
3275
            goto endjob;
3276

3277
        if (libxlDomainAttachDeviceConfig(vmdef, dev) < 0)
3278
            goto endjob;
3279
    }
3280 3281 3282 3283

    if (flags & VIR_DOMAIN_DEVICE_MODIFY_LIVE) {
        /* If dev exists it was created to modify the domain config. Free it. */
        virDomainDeviceDefFree(dev);
3284
        if (!(dev = virDomainDeviceDefParse(xml, vm->def,
3285
                                            cfg->caps, driver->xmlopt,
3286
                                            VIR_DOMAIN_XML_INACTIVE)))
3287
            goto endjob;
3288

3289
        if (libxlDomainAttachDeviceLive(driver, priv, vm, dev) < 0)
3290
            goto endjob;
3291

3292 3293 3294 3295
        /*
         * update domain status forcibly because the domain status may be
         * changed even if we attach the device failed.
         */
3296
        if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
3297
            goto endjob;
3298 3299
    }

3300 3301
    ret = 0;

3302
    /* Finally, if no error until here, we can save config. */
3303
    if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
3304
        ret = virDomainSaveConfig(cfg->configDir, vmdef);
3305
        if (!ret) {
3306
            virDomainObjAssignDef(vm, vmdef, false, NULL);
3307 3308 3309 3310
            vmdef = NULL;
        }
    }

3311
 endjob:
3312 3313 3314
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

3315
 cleanup:
3316 3317 3318
    virDomainDefFree(vmdef);
    virDomainDeviceDefFree(dev);
    if (vm)
3319
        virObjectUnlock(vm);
3320
    virObjectUnref(cfg);
3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334
    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)
{
3335
    libxlDriverPrivatePtr driver = dom->conn->privateData;
3336
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
3337 3338 3339 3340 3341 3342 3343 3344 3345
    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 已提交
3346
    if (!(vm = libxlDomObjFromDomain(dom)))
3347 3348
        goto cleanup;

3349 3350 3351
    if (virDomainDetachDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
        goto cleanup;

3352 3353 3354
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

3355 3356 3357 3358 3359 3360 3361 3362 3363 3364
    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"));
3365
            goto endjob;
3366 3367 3368 3369 3370 3371
        }
    }

    if ((flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) && !vm->persistent) {
         virReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("cannot modify device on transient domain"));
3372
         goto endjob;
3373 3374 3375 3376 3377 3378
    }

    priv = vm->privateData;

    if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
        if (!(dev = virDomainDeviceDefParse(xml, vm->def,
3379
                                            cfg->caps, driver->xmlopt,
3380
                                            VIR_DOMAIN_XML_INACTIVE)))
3381
            goto endjob;
3382 3383

        /* Make a copy for updated domain. */
3384
        if (!(vmdef = virDomainObjCopyPersistentDef(vm, cfg->caps,
3385
                                                    driver->xmlopt)))
3386
            goto endjob;
3387

3388
        if (libxlDomainDetachDeviceConfig(vmdef, dev) < 0)
3389
            goto endjob;
3390 3391 3392 3393 3394 3395
    }

    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,
3396
                                            cfg->caps, driver->xmlopt,
3397
                                            VIR_DOMAIN_XML_INACTIVE)))
3398
            goto endjob;
3399

3400
        if (libxlDomainDetachDeviceLive(driver, priv, vm, dev) < 0)
3401
            goto endjob;
3402 3403 3404 3405 3406

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

3411 3412
    ret = 0;

3413
    /* Finally, if no error until here, we can save config. */
3414
    if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
3415
        ret = virDomainSaveConfig(cfg->configDir, vmdef);
3416 3417 3418 3419 3420 3421
        if (!ret) {
            virDomainObjAssignDef(vm, vmdef, false, NULL);
            vmdef = NULL;
        }
    }

3422
 endjob:
3423 3424 3425
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

3426
 cleanup:
3427 3428 3429 3430
    virDomainDefFree(vmdef);
    virDomainDeviceDefFree(dev);
    if (vm)
        virObjectUnlock(vm);
3431
    virObjectUnref(cfg);
3432
    return ret;
3433 3434 3435 3436 3437 3438 3439 3440 3441 3442 3443 3444 3445
}

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)
{
3446
    libxlDriverPrivatePtr driver = dom->conn->privateData;
3447
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
3448 3449 3450 3451 3452 3453 3454 3455 3456
    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 已提交
3457
    if (!(vm = libxlDomObjFromDomain(dom)))
3458 3459
        goto cleanup;

3460 3461 3462
    if (virDomainUpdateDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
        goto cleanup;

3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486
    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,
3487
                                            cfg->caps, driver->xmlopt,
3488 3489 3490 3491
                                            VIR_DOMAIN_XML_INACTIVE)))
            goto cleanup;

        /* Make a copy for updated domain. */
3492
        if (!(vmdef = virDomainObjCopyPersistentDef(vm, cfg->caps,
3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505
                                                    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,
3506
                                            cfg->caps, driver->xmlopt,
3507 3508 3509 3510 3511 3512 3513 3514 3515 3516
                                            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.
         */
3517
        if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
3518 3519 3520 3521 3522
            ret = -1;
    }

    /* Finally, if no error until here, we can save config. */
    if (!ret && (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG)) {
3523
        ret = virDomainSaveConfig(cfg->configDir, vmdef);
3524 3525 3526 3527 3528 3529
        if (!ret) {
            virDomainObjAssignDef(vm, vmdef, false, NULL);
            vmdef = NULL;
        }
    }

3530
 cleanup:
3531 3532 3533 3534
    virDomainDefFree(vmdef);
    virDomainDeviceDefFree(dev);
    if (vm)
        virObjectUnlock(vm);
3535
    virObjectUnref(cfg);
3536
    return ret;
3537 3538
}

3539 3540 3541 3542 3543
static unsigned long long
libxlNodeGetFreeMemory(virConnectPtr conn)
{
    libxl_physinfo phy_info;
    libxlDriverPrivatePtr driver = conn->privateData;
3544 3545
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
    unsigned long long ret = 0;
3546

3547
    if (virNodeGetFreeMemoryEnsureACL(conn) < 0)
3548
        goto cleanup;
3549

3550
    if (libxl_get_physinfo(cfg->ctx, &phy_info)) {
3551 3552
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("libxl_get_physinfo_info failed"));
3553
        goto cleanup;
3554 3555
    }

3556 3557
    ret = phy_info.free_pages * cfg->verInfo->pagesize;

3558
 cleanup:
3559 3560
    virObjectUnref(cfg);
    return ret;
3561 3562
}

3563 3564 3565 3566 3567 3568 3569 3570 3571 3572
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;
3573
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
3574 3575

    if (virNodeGetCellsFreeMemoryEnsureACL(conn) < 0)
3576
        goto cleanup;
3577

3578
    numa_info = libxl_get_numainfo(cfg->ctx, &nr_nodes);
3579
    if (numa_info == NULL || nr_nodes == 0) {
3580 3581 3582
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("libxl_get_numainfo failed"));
        goto cleanup;
3583 3584 3585
    }

    /* Check/sanitize the cell range */
3586
    if (startCell >= nr_nodes) {
3587 3588
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("start cell %d out of range (0-%d)"),
3589
                       startCell, nr_nodes - 1);
3590 3591 3592
        goto cleanup;
    }
    lastCell = startCell + maxCells - 1;
3593 3594
    if (lastCell >= nr_nodes)
        lastCell = nr_nodes - 1;
3595 3596 3597 3598 3599 3600 3601

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

3603 3604
    ret = numCells;

3605
 cleanup:
3606
    libxl_numainfo_list_free(numa_info, nr_nodes);
3607
    virObjectUnref(cfg);
3608 3609 3610
    return ret;
}

3611
static int
3612
libxlConnectDomainEventRegister(virConnectPtr conn,
3613 3614
                                virConnectDomainEventCallback callback,
                                void *opaque,
3615
                                virFreeCallback freecb)
3616 3617 3618
{
    libxlDriverPrivatePtr driver = conn->privateData;

3619 3620 3621
    if (virConnectDomainEventRegisterEnsureACL(conn) < 0)
        return -1;

3622 3623 3624 3625
    if (virDomainEventStateRegister(conn,
                                    driver->domainEventState,
                                    callback, opaque, freecb) < 0)
        return -1;
3626

3627
    return 0;
3628 3629 3630 3631
}


static int
3632 3633
libxlConnectDomainEventDeregister(virConnectPtr conn,
                                  virConnectDomainEventCallback callback)
3634 3635 3636
{
    libxlDriverPrivatePtr driver = conn->privateData;

3637 3638 3639
    if (virConnectDomainEventDeregisterEnsureACL(conn) < 0)
        return -1;

3640 3641 3642 3643
    if (virDomainEventStateDeregister(conn,
                                      driver->domainEventState,
                                      callback) < 0)
        return -1;
3644

3645
    return 0;
3646 3647
}

3648 3649 3650 3651 3652 3653
static int
libxlDomainGetAutostart(virDomainPtr dom, int *autostart)
{
    virDomainObjPtr vm;
    int ret = -1;

J
Jim Fehlig 已提交
3654
    if (!(vm = libxlDomObjFromDomain(dom)))
3655 3656
        goto cleanup;

3657 3658 3659
    if (virDomainGetAutostartEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

3660 3661 3662
    *autostart = vm->autostart;
    ret = 0;

3663
 cleanup:
3664
    if (vm)
3665
        virObjectUnlock(vm);
3666 3667 3668 3669 3670 3671 3672
    return ret;
}

static int
libxlDomainSetAutostart(virDomainPtr dom, int autostart)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
3673
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
3674 3675 3676 3677
    virDomainObjPtr vm;
    char *configFile = NULL, *autostartLink = NULL;
    int ret = -1;

J
Jim Fehlig 已提交
3678
    if (!(vm = libxlDomObjFromDomain(dom)))
3679 3680
        goto cleanup;

3681 3682 3683
    if (virDomainSetAutostartEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

3684 3685 3686
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

3687
    if (!vm->persistent) {
3688 3689
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("cannot set autostart for transient domain"));
3690
        goto endjob;
3691 3692 3693 3694 3695
    }

    autostart = (autostart != 0);

    if (vm->autostart != autostart) {
3696
        if (!(configFile = virDomainConfigFile(cfg->configDir, vm->def->name)))
3697
            goto endjob;
3698
        if (!(autostartLink = virDomainConfigFile(cfg->autostartDir, vm->def->name)))
3699
            goto endjob;
3700 3701

        if (autostart) {
3702
            if (virFileMakePath(cfg->autostartDir) < 0) {
3703
                virReportSystemError(errno,
3704
                                     _("cannot create autostart directory %s"),
3705
                                     cfg->autostartDir);
3706
                goto endjob;
3707 3708 3709 3710 3711 3712
            }

            if (symlink(configFile, autostartLink) < 0) {
                virReportSystemError(errno,
                                     _("Failed to create symlink '%s to '%s'"),
                                     autostartLink, configFile);
3713
                goto endjob;
3714 3715 3716 3717 3718 3719
            }
        } else {
            if (unlink(autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) {
                virReportSystemError(errno,
                                     _("Failed to delete symlink '%s'"),
                                     autostartLink);
3720
                goto endjob;
3721 3722 3723 3724 3725 3726 3727
            }
        }

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

3728
 endjob:
3729 3730 3731
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

3732
 cleanup:
3733 3734 3735
    VIR_FREE(configFile);
    VIR_FREE(autostartLink);
    if (vm)
3736
        virObjectUnlock(vm);
3737
    virObjectUnref(cfg);
3738 3739 3740
    return ret;
}

3741 3742 3743 3744 3745 3746
static char *
libxlDomainGetSchedulerType(virDomainPtr dom, int *nparams)
{
    libxlDomainObjPrivatePtr priv;
    virDomainObjPtr vm;
    char * ret = NULL;
3747
    const char *name = NULL;
J
Jim Fehlig 已提交
3748
    libxl_scheduler sched_id;
3749

J
Jim Fehlig 已提交
3750
    if (!(vm = libxlDomObjFromDomain(dom)))
3751 3752
        goto cleanup;

3753 3754 3755
    if (virDomainGetSchedulerTypeEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

3756
    if (!virDomainObjIsActive(vm)) {
3757
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
3758 3759 3760 3761
        goto cleanup;
    }

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

3764 3765
    if (nparams)
        *nparams = 0;
3766
    switch (sched_id) {
J
Jim Fehlig 已提交
3767
    case LIBXL_SCHEDULER_SEDF:
3768
        name = "sedf";
3769
        break;
J
Jim Fehlig 已提交
3770
    case LIBXL_SCHEDULER_CREDIT:
3771
        name = "credit";
3772 3773
        if (nparams)
            *nparams = XEN_SCHED_CREDIT_NPARAM;
3774
        break;
J
Jim Fehlig 已提交
3775
    case LIBXL_SCHEDULER_CREDIT2:
3776
        name = "credit2";
3777
        break;
J
Jim Fehlig 已提交
3778
    case LIBXL_SCHEDULER_ARINC653:
3779
        name = "arinc653";
3780 3781
        break;
    default:
J
Jim Fehlig 已提交
3782 3783
        virReportError(VIR_ERR_INTERNAL_ERROR,
                   _("Failed to get scheduler id for domain '%d'"
3784
                     " with libxenlight"), vm->def->id);
3785 3786 3787
        goto cleanup;
    }

3788
    ignore_value(VIR_STRDUP(ret, name));
3789

3790
 cleanup:
3791
    if (vm)
3792
        virObjectUnlock(vm);
3793 3794 3795
    return ret;
}

3796
static int
3797 3798 3799 3800
libxlDomainGetSchedulerParametersFlags(virDomainPtr dom,
                                       virTypedParameterPtr params,
                                       int *nparams,
                                       unsigned int flags)
3801 3802 3803
{
    libxlDomainObjPrivatePtr priv;
    virDomainObjPtr vm;
J
Jim Fehlig 已提交
3804 3805
    libxl_domain_sched_params sc_info;
    libxl_scheduler sched_id;
3806 3807
    int ret = -1;

3808 3809 3810 3811
    virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);

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

J
Jim Fehlig 已提交
3813
    if (!(vm = libxlDomObjFromDomain(dom)))
3814 3815
        goto cleanup;

3816 3817 3818
    if (virDomainGetSchedulerParametersFlagsEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

3819
    if (!virDomainObjIsActive(vm)) {
J
Jim Fehlig 已提交
3820 3821
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("Domain is not running"));
3822 3823 3824 3825 3826
        goto cleanup;
    }

    priv = vm->privateData;

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

J
Jim Fehlig 已提交
3829
    if (sched_id != LIBXL_SCHEDULER_CREDIT) {
3830 3831
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Only 'credit' scheduler is supported"));
3832 3833 3834
        goto cleanup;
    }

3835
    if (libxl_domain_sched_params_get(priv->ctx, vm->def->id, &sc_info) != 0) {
3836 3837
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to get scheduler parameters for domain '%d'"
3838
                         " with libxenlight"), vm->def->id);
3839 3840 3841
        goto cleanup;
    }

3842 3843
    if (virTypedParameterAssign(&params[0], VIR_DOMAIN_SCHEDULER_WEIGHT,
                                VIR_TYPED_PARAM_UINT, sc_info.weight) < 0)
3844 3845
        goto cleanup;

3846
    if (*nparams > 1) {
3847 3848
        if (virTypedParameterAssign(&params[0], VIR_DOMAIN_SCHEDULER_CAP,
                                    VIR_TYPED_PARAM_UINT, sc_info.cap) < 0)
3849
            goto cleanup;
3850 3851
    }

3852 3853
    if (*nparams > XEN_SCHED_CREDIT_NPARAM)
        *nparams = XEN_SCHED_CREDIT_NPARAM;
3854 3855
    ret = 0;

3856
 cleanup:
3857
    if (vm)
3858
        virObjectUnlock(vm);
3859 3860 3861 3862
    return ret;
}

static int
3863 3864 3865 3866 3867 3868 3869 3870 3871 3872 3873
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)
3874
{
3875
    libxlDriverPrivatePtr driver = dom->conn->privateData;
3876 3877
    libxlDomainObjPrivatePtr priv;
    virDomainObjPtr vm;
J
Jim Fehlig 已提交
3878
    libxl_domain_sched_params sc_info;
3879
    int sched_id;
3880
    size_t i;
3881 3882
    int ret = -1;

3883
    virCheckFlags(0, -1);
3884 3885 3886 3887 3888 3889
    if (virTypedParamsValidate(params, nparams,
                               VIR_DOMAIN_SCHEDULER_WEIGHT,
                               VIR_TYPED_PARAM_UINT,
                               VIR_DOMAIN_SCHEDULER_CAP,
                               VIR_TYPED_PARAM_UINT,
                               NULL) < 0)
3890
        return -1;
3891

J
Jim Fehlig 已提交
3892
    if (!(vm = libxlDomObjFromDomain(dom)))
3893 3894
        goto cleanup;

3895 3896 3897
    if (virDomainSetSchedulerParametersFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
        goto cleanup;

3898 3899 3900
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

3901
    if (!virDomainObjIsActive(vm)) {
3902
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
3903
        goto endjob;
3904 3905 3906 3907
    }

    priv = vm->privateData;

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

J
Jim Fehlig 已提交
3910
    if (sched_id != LIBXL_SCHEDULER_CREDIT) {
3911 3912
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Only 'credit' scheduler is supported"));
3913
        goto endjob;
3914 3915
    }

3916
    if (libxl_domain_sched_params_get(priv->ctx, vm->def->id, &sc_info) != 0) {
3917 3918
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to get scheduler parameters for domain '%d'"
3919
                         " with libxenlight"), vm->def->id);
3920
        goto endjob;
3921 3922 3923
    }

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

3926
        if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_WEIGHT))
3927
            sc_info.weight = params[i].value.ui;
3928
        else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_CAP))
3929 3930 3931
            sc_info.cap = params[i].value.ui;
    }

3932
    if (libxl_domain_sched_params_set(priv->ctx, vm->def->id, &sc_info) != 0) {
3933 3934
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to set scheduler parameters for domain '%d'"
3935
                         " with libxenlight"), vm->def->id);
3936
        goto endjob;
3937 3938 3939 3940
    }

    ret = 0;

3941
 endjob:
3942 3943 3944
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

3945
 cleanup:
3946
    if (vm)
3947
        virObjectUnlock(vm);
3948 3949 3950
    return ret;
}

B
Bamvor Jian Zhang 已提交
3951 3952 3953 3954 3955 3956 3957 3958 3959

static int
libxlDomainOpenConsole(virDomainPtr dom,
                       const char *dev_name,
                       virStreamPtr st,
                       unsigned int flags)
{
    virDomainObjPtr vm = NULL;
    int ret = -1;
I
Ian Campbell 已提交
3960
    libxl_console_type console_type;
B
Bamvor Jian Zhang 已提交
3961 3962 3963 3964 3965 3966 3967 3968 3969 3970 3971 3972 3973
    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 已提交
3974
    if (!(vm = libxlDomObjFromDomain(dom)))
B
Bamvor Jian Zhang 已提交
3975 3976 3977 3978 3979 3980 3981 3982 3983 3984 3985 3986 3987
        goto cleanup;

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

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

    priv = vm->privateData;

I
Ian Campbell 已提交
3988 3989
    if (vm->def->nconsoles)
        chr = vm->def->consoles[0];
B
Bamvor Jian Zhang 已提交
3990 3991 3992 3993 3994 3995 3996 3997 3998 3999 4000 4001 4002 4003 4004

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

I
Ian Campbell 已提交
4005 4006 4007 4008 4009 4010
    console_type =
        (chr->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_SERIAL ?
                            LIBXL_CONSOLE_TYPE_SERIAL : LIBXL_CONSOLE_TYPE_PV);

    ret = libxl_console_get_tty(priv->ctx, vm->def->id, chr->target.port,
                                console_type, &console);
B
Bamvor Jian Zhang 已提交
4011 4012 4013 4014 4015 4016 4017 4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028
    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;
    }

4029
 cleanup:
B
Bamvor Jian Zhang 已提交
4030 4031 4032 4033 4034 4035
    VIR_FREE(console);
    if (vm)
        virObjectUnlock(vm);
    return ret;
}

4036 4037 4038 4039 4040 4041 4042
static int
libxlDomainSetSchedulerParameters(virDomainPtr dom, virTypedParameterPtr params,
                                  int nparams)
{
    return libxlDomainSetSchedulerParametersFlags(dom, params, nparams, 0);
}

4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059 4060 4061 4062 4063 4064 4065 4066 4067 4068 4069 4070 4071 4072
/* 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;

4073 4074
    libxl_bitmap_init(&nodemap);

J
Jim Fehlig 已提交
4075
    if (!(vm = libxlDomObjFromDomain(dom)))
4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096
        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;

    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];
4097
        int numnodes;
4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 4113 4114 4115

        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 */
4116 4117 4118 4119
            numnodes = libxl_get_max_nodes(priv->ctx);
            if (numnodes <= 0)
                goto cleanup;

J
Ján Tomko 已提交
4120
            if (libxl_node_bitmap_alloc(priv->ctx, &nodemap, 0)) {
4121 4122 4123
                virReportOOMError();
                goto cleanup;
            }
J
Ján Tomko 已提交
4124 4125
            if (!(nodes = virBitmapNew(numnodes)))
                goto cleanup;
4126 4127 4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146

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

4147
            if (!(nodeset = virBitmapFormat(nodes)))
4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 4161 4162 4163
                goto cleanup;

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

            nodeset = NULL;

            break;
        }
    }

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

4164
 cleanup:
4165 4166 4167 4168 4169 4170 4171 4172 4173
    VIR_FREE(nodeset);
    virBitmapFree(nodes);
    libxl_bitmap_dispose(&nodemap);
    if (vm)
        virObjectUnlock(vm);
    return ret;
}
#endif

J
Jim Fehlig 已提交
4174 4175 4176 4177 4178 4179
static int
libxlDomainIsActive(virDomainPtr dom)
{
    virDomainObjPtr obj;
    int ret = -1;

J
Jim Fehlig 已提交
4180
    if (!(obj = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
4181
        goto cleanup;
4182 4183 4184 4185

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

J
Jim Fehlig 已提交
4186 4187
    ret = virDomainObjIsActive(obj);

4188
 cleanup:
J
Jim Fehlig 已提交
4189
    if (obj)
4190
        virObjectUnlock(obj);
J
Jim Fehlig 已提交
4191 4192 4193 4194 4195 4196 4197 4198 4199
    return ret;
}

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

J
Jim Fehlig 已提交
4200
    if (!(obj = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
4201
        goto cleanup;
4202 4203 4204 4205

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

J
Jim Fehlig 已提交
4206 4207
    ret = obj->persistent;

4208
 cleanup:
J
Jim Fehlig 已提交
4209
    if (obj)
4210
        virObjectUnlock(obj);
J
Jim Fehlig 已提交
4211 4212 4213
    return ret;
}

4214 4215 4216 4217 4218 4219
static int
libxlDomainIsUpdated(virDomainPtr dom)
{
    virDomainObjPtr vm;
    int ret = -1;

J
Jim Fehlig 已提交
4220
    if (!(vm = libxlDomObjFromDomain(dom)))
4221
        goto cleanup;
4222 4223 4224 4225

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

4226 4227
    ret = vm->updated;

4228
 cleanup:
4229
    if (vm)
4230
        virObjectUnlock(vm);
4231 4232 4233
    return ret;
}

4234
static int
4235 4236 4237
libxlConnectDomainEventRegisterAny(virConnectPtr conn, virDomainPtr dom, int eventID,
                                   virConnectDomainEventGenericCallback callback,
                                   void *opaque, virFreeCallback freecb)
4238 4239 4240 4241
{
    libxlDriverPrivatePtr driver = conn->privateData;
    int ret;

4242 4243 4244
    if (virConnectDomainEventRegisterAnyEnsureACL(conn) < 0)
        return -1;

4245 4246 4247 4248
    if (virDomainEventStateRegisterID(conn,
                                      driver->domainEventState,
                                      dom, eventID, callback, opaque,
                                      freecb, &ret) < 0)
4249
        ret = -1;
4250 4251 4252 4253 4254 4255

    return ret;
}


static int
4256
libxlConnectDomainEventDeregisterAny(virConnectPtr conn, int callbackID)
4257 4258 4259
{
    libxlDriverPrivatePtr driver = conn->privateData;

4260 4261 4262
    if (virConnectDomainEventDeregisterAnyEnsureACL(conn) < 0)
        return -1;

4263 4264 4265 4266
    if (virObjectEventStateDeregisterID(conn,
                                        driver->domainEventState,
                                        callbackID) < 0)
        return -1;
4267

4268
    return 0;
4269 4270
}

J
Jim Fehlig 已提交
4271

4272
static int
4273
libxlConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED)
4274 4275 4276 4277
{
    return 1;
}

4278
static int
4279 4280 4281
libxlConnectListAllDomains(virConnectPtr conn,
                           virDomainPtr **domains,
                           unsigned int flags)
4282 4283 4284 4285
{
    libxlDriverPrivatePtr driver = conn->privateData;
    int ret = -1;

O
Osier Yang 已提交
4286
    virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
4287

4288 4289 4290
    if (virConnectListAllDomainsEnsureACL(conn) < 0)
        return -1;

4291 4292
    ret = virDomainObjListExport(driver->domains, conn, domains,
                                 virConnectListAllDomainsCheckACL, flags);
4293 4294 4295 4296

    return ret;
}

4297 4298 4299 4300 4301 4302 4303 4304 4305
/* Which features are supported by this driver? */
static int
libxlConnectSupportsFeature(virConnectPtr conn, int feature)
{
    if (virConnectSupportsFeatureEnsureACL(conn) < 0)
        return -1;

    switch (feature) {
    case VIR_DRV_FEATURE_TYPED_PARAM_STRING:
J
Jim Fehlig 已提交
4306
    case VIR_DRV_FEATURE_MIGRATION_PARAMS:
4307 4308 4309 4310 4311
        return 1;
    default:
        return 0;
    }
}
4312

4313 4314 4315 4316 4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328 4329 4330 4331 4332 4333 4334 4335 4336 4337
static int
libxlNodeDeviceGetPCIInfo(virNodeDeviceDefPtr def,
                          unsigned *domain,
                          unsigned *bus,
                          unsigned *slot,
                          unsigned *function)
{
    virNodeDevCapsDefPtr cap;

    cap = def->caps;
    while (cap) {
        if (cap->type == VIR_NODE_DEV_CAP_PCI_DEV) {
            *domain   = cap->data.pci_dev.domain;
            *bus      = cap->data.pci_dev.bus;
            *slot     = cap->data.pci_dev.slot;
            *function = cap->data.pci_dev.function;
            break;
        }

        cap = cap->next;
    }

    if (!cap) {
        virReportError(VIR_ERR_INVALID_ARG,
                       _("device %s is not a PCI device"), def->name);
C
Chunyan Liu 已提交
4338
        return -1;
4339 4340
    }

C
Chunyan Liu 已提交
4341
    return 0;
4342 4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357 4358 4359 4360 4361 4362 4363 4364 4365 4366 4367 4368 4369 4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389
}

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

    virCheckFlags(0, -1);

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

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

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

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

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

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

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

    ret = 0;
4390
 cleanup:
4391 4392 4393 4394 4395 4396 4397 4398 4399 4400 4401 4402 4403 4404 4405 4406 4407 4408 4409 4410 4411 4412 4413 4414 4415 4416 4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432
    virPCIDeviceFree(pci);
    virNodeDeviceDefFree(def);
    VIR_FREE(xml);
    return ret;
}

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

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

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

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

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

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

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

    if (virHostdevPCINodeDeviceReAttach(hostdev_mgr, pci) < 0)
C
Chunyan Liu 已提交
4433
        goto cleanup;
4434 4435

    ret = 0;
C
Chunyan Liu 已提交
4436

4437
 cleanup:
C
Chunyan Liu 已提交
4438
    virPCIDeviceFree(pci);
4439 4440 4441 4442 4443 4444 4445 4446
    virNodeDeviceDefFree(def);
    VIR_FREE(xml);
    return ret;
}

static int
libxlNodeDeviceReset(virNodeDevicePtr dev)
{
C
Chunyan Liu 已提交
4447
    virPCIDevicePtr pci = NULL;
4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473
    unsigned domain = 0, bus = 0, slot = 0, function = 0;
    int ret = -1;
    virNodeDeviceDefPtr def = NULL;
    char *xml = NULL;
    libxlDriverPrivatePtr driver = dev->conn->privateData;
    virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;

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

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

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

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

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

    if (virHostdevPCINodeDeviceReset(hostdev_mgr, pci) < 0)
C
Chunyan Liu 已提交
4474
        goto cleanup;
4475 4476

    ret = 0;
C
Chunyan Liu 已提交
4477

4478
 cleanup:
C
Chunyan Liu 已提交
4479
    virPCIDeviceFree(pci);
4480 4481 4482 4483 4484
    virNodeDeviceDefFree(def);
    VIR_FREE(xml);
    return ret;
}

J
Jim Fehlig 已提交
4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495
static char *
libxlDomainMigrateBegin3Params(virDomainPtr domain,
                               virTypedParameterPtr params,
                               int nparams,
                               char **cookieout ATTRIBUTE_UNUSED,
                               int *cookieoutlen ATTRIBUTE_UNUSED,
                               unsigned int flags)
{
    const char *xmlin = NULL;
    virDomainObjPtr vm = NULL;

4496 4497 4498 4499 4500
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
    virReportUnsupportedError();
    return NULL;
#endif

J
Jim Fehlig 已提交
4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511 4512 4513 4514 4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529 4530 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544
    virCheckFlags(LIBXL_MIGRATION_FLAGS, NULL);
    if (virTypedParamsValidate(params, nparams, LIBXL_MIGRATION_PARAMETERS) < 0)
        return NULL;

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

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

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

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

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

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

4545 4546 4547 4548 4549
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
    virReportUnsupportedError();
    return -1;
#endif

J
Jim Fehlig 已提交
4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571
    virCheckFlags(LIBXL_MIGRATION_FLAGS, -1);
    if (virTypedParamsValidate(params, nparams, LIBXL_MIGRATION_PARAMETERS) < 0)
        goto error;

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

        goto error;

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

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

4572
    if (libxlDomainMigrationPrepare(dconn, &def, uri_in, uri_out, flags) < 0)
J
Jim Fehlig 已提交
4573 4574 4575 4576 4577 4578 4579 4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599
        goto error;

    return 0;

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

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

4600 4601 4602 4603 4604
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
    virReportUnsupportedError();
    return -1;
#endif

J
Jim Fehlig 已提交
4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627
    virCheckFlags(LIBXL_MIGRATION_FLAGS, -1);
    if (virTypedParamsValidate(params, nparams, LIBXL_MIGRATION_PARAMETERS) < 0)
        goto cleanup;

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

        goto cleanup;

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

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

    if (libxlDomainMigrationPerform(driver, vm, dom_xml, dconnuri,
4628
                                    uri, dname, flags) < 0)
J
Jim Fehlig 已提交
4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652
        goto cleanup;

    ret = 0;

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

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

4655 4656 4657 4658 4659
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
    virReportUnsupportedError();
    return NULL;
#endif

J
Jim Fehlig 已提交
4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682 4683
    virCheckFlags(LIBXL_MIGRATION_FLAGS, NULL);
    if (virTypedParamsValidate(params, nparams, LIBXL_MIGRATION_PARAMETERS) < 0)
        return NULL;

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

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

    if (virDomainMigrateFinish3ParamsEnsureACL(dconn, vm->def) < 0) {
        virObjectUnlock(vm);
        return NULL;
    }

4684 4685 4686 4687 4688 4689 4690 4691 4692 4693 4694 4695 4696 4697
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0) {
        virObjectUnlock(vm);
        return NULL;
    }

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

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

    if (vm)
        virObjectUnlock(vm);

    return ret;
J
Jim Fehlig 已提交
4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711
}

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

4712 4713 4714 4715 4716
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
    virReportUnsupportedError();
    return -1;
#endif

J
Jim Fehlig 已提交
4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727 4728 4729 4730 4731
    virCheckFlags(LIBXL_MIGRATION_FLAGS, -1);
    if (virTypedParamsValidate(params, nparams, LIBXL_MIGRATION_PARAMETERS) < 0)
        return -1;

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

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

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

4732

4733
static virHypervisorDriver libxlDriver = {
4734
    .no = VIR_DRV_LIBXL,
4735
    .name = LIBXL_DRIVER_NAME,
4736 4737 4738 4739
    .connectOpen = libxlConnectOpen, /* 0.9.0 */
    .connectClose = libxlConnectClose, /* 0.9.0 */
    .connectGetType = libxlConnectGetType, /* 0.9.0 */
    .connectGetVersion = libxlConnectGetVersion, /* 0.9.0 */
4740
    .connectGetHostname = libxlConnectGetHostname, /* 0.9.0 */
4741
    .connectGetSysinfo = libxlConnectGetSysinfo, /* 1.1.0 */
4742
    .connectGetMaxVcpus = libxlConnectGetMaxVcpus, /* 0.9.0 */
4743
    .nodeGetInfo = libxlNodeGetInfo, /* 0.9.0 */
4744 4745 4746 4747
    .connectGetCapabilities = libxlConnectGetCapabilities, /* 0.9.0 */
    .connectListDomains = libxlConnectListDomains, /* 0.9.0 */
    .connectNumOfDomains = libxlConnectNumOfDomains, /* 0.9.0 */
    .connectListAllDomains = libxlConnectListAllDomains, /* 0.9.13 */
4748 4749 4750 4751 4752 4753 4754
    .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 */
4755
    .domainShutdownFlags = libxlDomainShutdownFlags, /* 0.9.10 */
4756 4757
    .domainReboot = libxlDomainReboot, /* 0.9.0 */
    .domainDestroy = libxlDomainDestroy, /* 0.9.0 */
4758
    .domainDestroyFlags = libxlDomainDestroyFlags, /* 0.9.4 */
4759 4760
    .domainGetOSType = libxlDomainGetOSType, /* 0.9.0 */
    .domainGetMaxMemory = libxlDomainGetMaxMemory, /* 0.9.0 */
4761
    .domainSetMaxMemory = libxlDomainSetMaxMemory, /* 0.9.2 */
4762 4763 4764 4765
    .domainSetMemory = libxlDomainSetMemory, /* 0.9.0 */
    .domainSetMemoryFlags = libxlDomainSetMemoryFlags, /* 0.9.0 */
    .domainGetInfo = libxlDomainGetInfo, /* 0.9.0 */
    .domainGetState = libxlDomainGetState, /* 0.9.2 */
4766
    .domainSave = libxlDomainSave, /* 0.9.2 */
4767
    .domainSaveFlags = libxlDomainSaveFlags, /* 0.9.4 */
4768
    .domainRestore = libxlDomainRestore, /* 0.9.2 */
4769
    .domainRestoreFlags = libxlDomainRestoreFlags, /* 0.9.4 */
4770
    .domainCoreDump = libxlDomainCoreDump, /* 0.9.2 */
4771 4772 4773 4774
    .domainSetVcpus = libxlDomainSetVcpus, /* 0.9.0 */
    .domainSetVcpusFlags = libxlDomainSetVcpusFlags, /* 0.9.0 */
    .domainGetVcpusFlags = libxlDomainGetVcpusFlags, /* 0.9.0 */
    .domainPinVcpu = libxlDomainPinVcpu, /* 0.9.0 */
4775
    .domainPinVcpuFlags = libxlDomainPinVcpuFlags, /* 1.2.1 */
4776
    .domainGetVcpus = libxlDomainGetVcpus, /* 0.9.0 */
4777
    .domainGetVcpuPinInfo = libxlDomainGetVcpuPinInfo, /* 1.2.1 */
4778
    .domainGetXMLDesc = libxlDomainGetXMLDesc, /* 0.9.0 */
4779 4780 4781 4782
    .connectDomainXMLFromNative = libxlConnectDomainXMLFromNative, /* 0.9.0 */
    .connectDomainXMLToNative = libxlConnectDomainXMLToNative, /* 0.9.0 */
    .connectListDefinedDomains = libxlConnectListDefinedDomains, /* 0.9.0 */
    .connectNumOfDefinedDomains = libxlConnectNumOfDefinedDomains, /* 0.9.0 */
4783 4784 4785 4786
    .domainCreate = libxlDomainCreate, /* 0.9.0 */
    .domainCreateWithFlags = libxlDomainCreateWithFlags, /* 0.9.0 */
    .domainDefineXML = libxlDomainDefineXML, /* 0.9.0 */
    .domainUndefine = libxlDomainUndefine, /* 0.9.0 */
4787
    .domainUndefineFlags = libxlDomainUndefineFlags, /* 0.9.4 */
4788 4789 4790 4791 4792
    .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 */
4793 4794 4795 4796
    .domainGetAutostart = libxlDomainGetAutostart, /* 0.9.0 */
    .domainSetAutostart = libxlDomainSetAutostart, /* 0.9.0 */
    .domainGetSchedulerType = libxlDomainGetSchedulerType, /* 0.9.0 */
    .domainGetSchedulerParameters = libxlDomainGetSchedulerParameters, /* 0.9.0 */
4797
    .domainGetSchedulerParametersFlags = libxlDomainGetSchedulerParametersFlags, /* 0.9.2 */
4798
    .domainSetSchedulerParameters = libxlDomainSetSchedulerParameters, /* 0.9.0 */
4799
    .domainSetSchedulerParametersFlags = libxlDomainSetSchedulerParametersFlags, /* 0.9.2 */
4800 4801 4802
#ifdef LIBXL_HAVE_DOMAIN_NODEAFFINITY
    .domainGetNumaParameters = libxlDomainGetNumaParameters, /* 1.1.1 */
#endif
4803
    .nodeGetFreeMemory = libxlNodeGetFreeMemory, /* 0.9.0 */
4804
    .nodeGetCellsFreeMemory = libxlNodeGetCellsFreeMemory, /* 1.1.1 */
4805 4806
    .connectDomainEventRegister = libxlConnectDomainEventRegister, /* 0.9.0 */
    .connectDomainEventDeregister = libxlConnectDomainEventDeregister, /* 0.9.0 */
4807 4808 4809
    .domainManagedSave = libxlDomainManagedSave, /* 0.9.2 */
    .domainHasManagedSaveImage = libxlDomainHasManagedSaveImage, /* 0.9.2 */
    .domainManagedSaveRemove = libxlDomainManagedSaveRemove, /* 0.9.2 */
B
Bamvor Jian Zhang 已提交
4810
    .domainOpenConsole = libxlDomainOpenConsole, /* 1.1.2 */
4811 4812 4813
    .domainIsActive = libxlDomainIsActive, /* 0.9.0 */
    .domainIsPersistent = libxlDomainIsPersistent, /* 0.9.0 */
    .domainIsUpdated = libxlDomainIsUpdated, /* 0.9.0 */
4814 4815 4816
    .connectDomainEventRegisterAny = libxlConnectDomainEventRegisterAny, /* 0.9.0 */
    .connectDomainEventDeregisterAny = libxlConnectDomainEventDeregisterAny, /* 0.9.0 */
    .connectIsAlive = libxlConnectIsAlive, /* 0.9.8 */
4817
    .connectSupportsFeature = libxlConnectSupportsFeature, /* 1.1.1 */
4818 4819 4820 4821
    .nodeDeviceDettach = libxlNodeDeviceDettach, /* 1.2.3 */
    .nodeDeviceDetachFlags = libxlNodeDeviceDetachFlags, /* 1.2.3 */
    .nodeDeviceReAttach = libxlNodeDeviceReAttach, /* 1.2.3 */
    .nodeDeviceReset = libxlNodeDeviceReset, /* 1.2.3 */
4822 4823 4824 4825 4826
    .domainMigrateBegin3Params = libxlDomainMigrateBegin3Params, /* 1.2.6 */
    .domainMigratePrepare3Params = libxlDomainMigratePrepare3Params, /* 1.2.6 */
    .domainMigratePerform3Params = libxlDomainMigratePerform3Params, /* 1.2.6 */
    .domainMigrateFinish3Params = libxlDomainMigrateFinish3Params, /* 1.2.6 */
    .domainMigrateConfirm3Params = libxlDomainMigrateConfirm3Params, /* 1.2.6 */
J
Jim Fehlig 已提交
4827 4828 4829 4830
};

static virStateDriver libxlStateDriver = {
    .name = "LIBXL",
4831
    .stateInitialize = libxlStateInitialize,
4832
    .stateAutoStart = libxlStateAutoStart,
4833 4834
    .stateCleanup = libxlStateCleanup,
    .stateReload = libxlStateReload,
J
Jim Fehlig 已提交
4835 4836 4837 4838 4839 4840
};


int
libxlRegister(void)
{
4841
    if (virRegisterHypervisorDriver(&libxlDriver) < 0)
J
Jim Fehlig 已提交
4842 4843 4844 4845 4846 4847
        return -1;
    if (virRegisterStateDriver(&libxlStateDriver) < 0)
        return -1;

    return 0;
}