libxl_driver.c 142.9 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 "xen_xl.h"
52
#include "virtypedparam.h"
M
Martin Kletzander 已提交
53
#include "viruri.h"
54
#include "virstring.h"
55
#include "virsysinfo.h"
56
#include "viraccessapicheck.h"
57
#include "viratomic.h"
58
#include "virhostdev.h"
59
#include "network/bridge_driver.h"
J
Jim Fehlig 已提交
60 61 62

#define VIR_FROM_THIS VIR_FROM_LIBXL

63 64
VIR_LOG_INIT("libxl.libxl_driver");

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

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

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

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

80

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

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

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

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

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

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

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

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

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

151
    virObjectLock(vm);
J
Jim Fehlig 已提交
152

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

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

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

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

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

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

    return -1;
J
Jim Fehlig 已提交
197 198 199 200 201
}

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

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

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

218
    virObjectEventStateFree(libxl_driver->domainEventState);
219
    virSysinfoDefFree(libxl_driver->hostsysinfo);
220

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

    return 0;
}

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

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

240 241 242
    if (!virFileExists(HYPERVISOR_CAPABILITIES)) {
        VIR_INFO("Disabling driver as " HYPERVISOR_CAPABILITIES
                 " does not exist");
243
        return ret;
244
    }
245 246 247 248 249
    /*
     * 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.
     */
250
    status = virFileReadAll(HYPERVISOR_CAPABILITIES, 10, &output);
251
    if (status >= 0)
252 253 254
        status = strncmp(output, "control_d", 9);
    VIR_FREE(output);
    if (status) {
255 256 257 258 259 260 261
        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 */
262 263 264 265 266 267 268 269 270 271 272
    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);
273 274
    } else {
        ret = true;
J
Jim Fehlig 已提交
275 276
    }

277 278 279 280 281 282 283 284
    return ret;
}

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

    if (!libxlDriverShouldLoad(privileged))
        return 0;

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

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

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

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

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

319 320 321
    if (!(libxl_driver->hostdevMgr = virHostdevManagerGetDefault()))
        goto error;

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

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

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

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

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

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

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

    libxlReconnectDomains(libxl_driver);

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

395 396
    virDomainObjListForEach(libxl_driver->domains, libxlDomainManagedSaveLoad,
                            libxl_driver);
397

J
Jim Fehlig 已提交
398 399
    return 0;

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

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

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

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

J
Jim Fehlig 已提交
420 421 422
    if (!libxl_driver)
        return 0;

423 424
    cfg = libxlDriverConfigGet(libxl_driver);

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

434 435
    virDomainObjListForEach(libxl_driver->domains, libxlAutostartDomain,
                            libxl_driver);
436

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


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

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

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

483 484 485
    if (virConnectOpenEnsureACL(conn) < 0)
        return VIR_DRV_OPEN_ERROR;

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

    return VIR_DRV_OPEN_SUCCESS;
};

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

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

J
Jim Fehlig 已提交
504
    return "Xen";
J
Jim Fehlig 已提交
505 506 507
}

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

513 514 515
    if (virConnectGetVersionEnsureACL(conn) < 0)
        return 0;

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

522

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

528 529 530
    return virGetHostname();
}

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

    virCheckFlags(0, NULL);

539 540 541
    if (virConnectGetSysinfoEnsureACL(conn) < 0)
        return NULL;

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

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

562 563 564
    if (virConnectGetMaxVcpusEnsureACL(conn) < 0)
        return -1;

565 566
    cfg = libxlDriverConfigGet(driver);
    ret = libxl_get_max_cpus(cfg->ctx);
567 568 569 570 571
    /* 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)
572
        ret = -1;
J
Jim Fehlig 已提交
573

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

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

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

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

594 595 596
    if (virConnectGetCapabilitiesEnsureACL(conn) < 0)
        return NULL;

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

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

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

610 611 612
    if (virConnectListDomainsEnsureACL(conn) < 0)
        return -1;

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

    return n;
}

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

625 626 627
    if (virConnectNumOfDomainsEnsureACL(conn) < 0)
        return -1;

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

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

645 646 647 648 649
    virCheckFlags(VIR_DOMAIN_START_PAUSED |
                  VIR_DOMAIN_START_VALIDATE, NULL);

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

651
    if (!(def = virDomainDefParseString(xml, cfg->caps, driver->xmlopt,
652
                                        1 << VIR_DOMAIN_VIRT_XEN,
653
                                        parse_flags)))
J
Jim Fehlig 已提交
654 655
        goto cleanup;

656 657 658
    if (virDomainCreateXMLEnsureACL(conn, def) < 0)
        goto cleanup;

659
    if (!(vm = virDomainObjListAdd(driver->domains, def,
660
                                   driver->xmlopt,
661 662
                                   VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                   NULL)))
J
Jim Fehlig 已提交
663 664 665
        goto cleanup;
    def = NULL;

666
    if (libxlDomainStart(driver, vm, (flags & VIR_DOMAIN_START_PAUSED) != 0,
667
                     -1) < 0) {
668
        virDomainObjListRemove(driver->domains, vm);
J
Jim Fehlig 已提交
669 670 671 672 673 674 675 676
        vm = NULL;
        goto cleanup;
    }

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

677
 cleanup:
J
Jim Fehlig 已提交
678 679
    virDomainDefFree(def);
    if (vm)
680
        virObjectUnlock(vm);
681
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
682 683 684 685 686 687 688 689 690 691
    return dom;
}

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

692
    vm = virDomainObjListFindByID(driver->domains, id);
J
Jim Fehlig 已提交
693
    if (!vm) {
694
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
J
Jim Fehlig 已提交
695 696 697
        goto cleanup;
    }

698 699 700
    if (virDomainLookupByIDEnsureACL(conn, vm->def) < 0)
        goto cleanup;

J
Jim Fehlig 已提交
701 702 703 704
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
    if (dom)
        dom->id = vm->def->id;

705
 cleanup:
J
Jim Fehlig 已提交
706
    if (vm)
707
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
708 709 710 711 712 713 714 715 716 717
    return dom;
}

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

718
    vm = virDomainObjListFindByUUID(driver->domains, uuid);
J
Jim Fehlig 已提交
719
    if (!vm) {
720
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
J
Jim Fehlig 已提交
721 722 723
        goto cleanup;
    }

724 725 726
    if (virDomainLookupByUUIDEnsureACL(conn, vm->def) < 0)
        goto cleanup;

J
Jim Fehlig 已提交
727 728 729 730
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
    if (dom)
        dom->id = vm->def->id;

731
 cleanup:
J
Jim Fehlig 已提交
732
    if (vm)
733
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
734 735 736 737 738 739 740 741 742 743
    return dom;
}

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

744
    vm = virDomainObjListFindByName(driver->domains, name);
J
Jim Fehlig 已提交
745
    if (!vm) {
746
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
J
Jim Fehlig 已提交
747 748 749
        goto cleanup;
    }

750 751 752
    if (virDomainLookupByNameEnsureACL(conn, vm->def) < 0)
        goto cleanup;

J
Jim Fehlig 已提交
753 754 755 756
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
    if (dom)
        dom->id = vm->def->id;

757
 cleanup:
J
Jim Fehlig 已提交
758
    if (vm)
759
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
760 761 762
    return dom;
}

763 764 765 766
static int
libxlDomainSuspend(virDomainPtr dom)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
767
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
768 769
    virDomainObjPtr vm;
    libxlDomainObjPrivatePtr priv;
770
    virObjectEventPtr event = NULL;
771 772
    int ret = -1;

J
Jim Fehlig 已提交
773
    if (!(vm = libxlDomObjFromDomain(dom)))
774
        goto cleanup;
775 776 777 778

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

779 780 781
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

782
    if (!virDomainObjIsActive(vm)) {
783
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
784
        goto endjob;
785 786 787 788
    }

    priv = vm->privateData;

J
Jiri Denemark 已提交
789
    if (virDomainObjGetState(vm, NULL) != VIR_DOMAIN_PAUSED) {
790
        if (libxl_domain_pause(priv->ctx, vm->def->id) != 0) {
791 792
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Failed to suspend domain '%d' with libxenlight"),
793
                           vm->def->id);
794
            goto endjob;
795 796
        }

J
Jiri Denemark 已提交
797
        virDomainObjSetState(vm, VIR_DOMAIN_PAUSED, VIR_DOMAIN_PAUSED_USER);
798

799
        event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_SUSPENDED,
800 801 802
                                         VIR_DOMAIN_EVENT_SUSPENDED_PAUSED);
    }

803
    if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
804
        goto endjob;
805 806 807

    ret = 0;

808
 endjob:
809 810 811
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

812
 cleanup:
813
    if (vm)
814
        virObjectUnlock(vm);
815
    if (event)
816
        libxlDomainEventQueue(driver, event);
817
    virObjectUnref(cfg);
818 819 820 821 822 823 824 825
    return ret;
}


static int
libxlDomainResume(virDomainPtr dom)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
826
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
827 828
    virDomainObjPtr vm;
    libxlDomainObjPrivatePtr priv;
829
    virObjectEventPtr event = NULL;
830 831
    int ret = -1;

J
Jim Fehlig 已提交
832
    if (!(vm = libxlDomObjFromDomain(dom)))
833 834
        goto cleanup;

835 836 837
    if (virDomainResumeEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

838 839 840
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

841
    if (!virDomainObjIsActive(vm)) {
842
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
843
        goto endjob;
844 845 846 847
    }

    priv = vm->privateData;

J
Jiri Denemark 已提交
848
    if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
849
        if (libxl_domain_unpause(priv->ctx, vm->def->id) != 0) {
850 851
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           _("Failed to resume domain '%d' with libxenlight"),
852
                           vm->def->id);
853
            goto endjob;
854 855
        }

J
Jiri Denemark 已提交
856 857
        virDomainObjSetState(vm, VIR_DOMAIN_RUNNING,
                             VIR_DOMAIN_RUNNING_UNPAUSED);
858

859
        event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_RESUMED,
860 861 862
                                         VIR_DOMAIN_EVENT_RESUMED_UNPAUSED);
    }

863
    if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
864
        goto endjob;
865 866 867

    ret = 0;

868
 endjob:
869 870 871
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

872
 cleanup:
873
    if (vm)
874
        virObjectUnlock(vm);
875
    if (event)
876
        libxlDomainEventQueue(driver, event);
877
    virObjectUnref(cfg);
878 879 880
    return ret;
}

J
Jim Fehlig 已提交
881
static int
882
libxlDomainShutdownFlags(virDomainPtr dom, unsigned int flags)
J
Jim Fehlig 已提交
883 884 885 886 887
{
    virDomainObjPtr vm;
    int ret = -1;
    libxlDomainObjPrivatePtr priv;

888 889 890 891 892
    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;
893

J
Jim Fehlig 已提交
894
    if (!(vm = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
895 896
        goto cleanup;

897
    if (virDomainShutdownFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
898 899
        goto cleanup;

J
Jim Fehlig 已提交
900
    if (!virDomainObjIsActive(vm)) {
901 902
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("Domain is not running"));
J
Jim Fehlig 已提交
903 904 905 906
        goto cleanup;
    }

    priv = vm->privateData;
907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927
    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;

928 929
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to shutdown domain '%d' with libxenlight"),
930
                       vm->def->id);
931
        ret = -1;
J
Jim Fehlig 已提交
932 933
    }

934
 cleanup:
J
Jim Fehlig 已提交
935
    if (vm)
936
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
937 938 939
    return ret;
}

940 941 942 943 944 945 946
static int
libxlDomainShutdown(virDomainPtr dom)
{
    return libxlDomainShutdownFlags(dom, 0);
}


J
Jim Fehlig 已提交
947
static int
E
Eric Blake 已提交
948
libxlDomainReboot(virDomainPtr dom, unsigned int flags)
J
Jim Fehlig 已提交
949 950 951 952 953
{
    virDomainObjPtr vm;
    int ret = -1;
    libxlDomainObjPrivatePtr priv;

J
Jim Fehlig 已提交
954 955 956
    virCheckFlags(VIR_DOMAIN_REBOOT_PARAVIRT, -1);
    if (flags == 0)
        flags = VIR_DOMAIN_REBOOT_PARAVIRT;
E
Eric Blake 已提交
957

J
Jim Fehlig 已提交
958
    if (!(vm = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
959 960
        goto cleanup;

961
    if (virDomainRebootEnsureACL(dom->conn, vm->def, flags) < 0)
962 963
        goto cleanup;

J
Jim Fehlig 已提交
964
    if (!virDomainObjIsActive(vm)) {
965 966
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("Domain is not running"));
J
Jim Fehlig 已提交
967 968 969 970
        goto cleanup;
    }

    priv = vm->privateData;
J
Jim Fehlig 已提交
971 972 973 974 975
    if (flags & VIR_DOMAIN_REBOOT_PARAVIRT) {
        ret = libxl_domain_reboot(priv->ctx, vm->def->id);
        if (ret == 0)
            goto cleanup;

976 977
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to reboot domain '%d' with libxenlight"),
978
                       vm->def->id);
J
Jim Fehlig 已提交
979
        ret = -1;
J
Jim Fehlig 已提交
980 981
    }

982
 cleanup:
J
Jim Fehlig 已提交
983
    if (vm)
984
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
985 986 987 988
    return ret;
}

static int
989 990
libxlDomainDestroyFlags(virDomainPtr dom,
                        unsigned int flags)
J
Jim Fehlig 已提交
991 992 993 994
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
995
    virObjectEventPtr event = NULL;
J
Jim Fehlig 已提交
996
    libxlDomainObjPrivatePtr priv;
J
Jim Fehlig 已提交
997

998 999
    virCheckFlags(0, -1);

J
Jim Fehlig 已提交
1000
    if (!(vm = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
1001 1002
        goto cleanup;

1003 1004 1005
    if (virDomainDestroyFlagsEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

J
Jim Fehlig 已提交
1006
    if (!virDomainObjIsActive(vm)) {
1007 1008
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("Domain is not running"));
J
Jim Fehlig 已提交
1009 1010 1011
        goto cleanup;
    }

1012
    event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
1013 1014
                                     VIR_DOMAIN_EVENT_STOPPED_DESTROYED);

J
Jim Fehlig 已提交
1015 1016
    priv = vm->privateData;
    if (libxl_domain_destroy(priv->ctx, vm->def->id, NULL) < 0) {
1017
        virReportError(VIR_ERR_INTERNAL_ERROR,
1018
                       _("Failed to destroy domain '%d'"), vm->def->id);
J
Jim Fehlig 已提交
1019 1020 1021
        goto cleanup;
    }

1022
    if (libxlDomainCleanupJob(driver, vm, VIR_DOMAIN_SHUTOFF_DESTROYED)) {
1023 1024 1025 1026
        if (!vm->persistent) {
            virDomainObjListRemove(driver->domains, vm);
            vm = NULL;
        }
J
Jim Fehlig 已提交
1027 1028 1029 1030
    }

    ret = 0;

1031
 cleanup:
J
Jim Fehlig 已提交
1032
    if (vm)
1033
        virObjectUnlock(vm);
1034 1035
    if (event)
        libxlDomainEventQueue(driver, event);
J
Jim Fehlig 已提交
1036 1037 1038
    return ret;
}

1039 1040 1041 1042 1043 1044
static int
libxlDomainDestroy(virDomainPtr dom)
{
    return libxlDomainDestroyFlags(dom, 0);
}

1045 1046 1047 1048 1049 1050
static char *
libxlDomainGetOSType(virDomainPtr dom)
{
    virDomainObjPtr vm;
    char *type = NULL;

J
Jim Fehlig 已提交
1051
    if (!(vm = libxlDomObjFromDomain(dom)))
1052 1053
        goto cleanup;

1054 1055 1056 1057 1058
    if (virDomainGetOSTypeEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

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

1060
 cleanup:
1061
    if (vm)
1062
        virObjectUnlock(vm);
1063 1064 1065
    return type;
}

1066
static unsigned long long
1067 1068 1069
libxlDomainGetMaxMemory(virDomainPtr dom)
{
    virDomainObjPtr vm;
1070
    unsigned long long ret = 0;
1071

J
Jim Fehlig 已提交
1072
    if (!(vm = libxlDomObjFromDomain(dom)))
1073
        goto cleanup;
1074 1075 1076 1077

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

1078
    ret = virDomainDefGetMemoryActual(vm->def);
1079

1080
 cleanup:
1081
    if (vm)
1082
        virObjectUnlock(vm);
1083 1084 1085 1086
    return ret;
}

static int
1087
libxlDomainSetMemoryFlags(virDomainPtr dom, unsigned long newmem,
1088 1089 1090
                          unsigned int flags)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
1091
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
1092 1093
    libxlDomainObjPrivatePtr priv;
    virDomainObjPtr vm;
1094 1095
    virDomainDefPtr persistentDef = NULL;
    bool isActive;
1096 1097 1098
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_MEM_LIVE |
1099 1100
                  VIR_DOMAIN_MEM_CONFIG |
                  VIR_DOMAIN_MEM_MAXIMUM, -1);
1101

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

1105 1106 1107
    if (virDomainSetMemoryFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
        goto cleanup;

1108 1109 1110
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123
    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;
1124 1125
    }

1126
    if (!isActive && (flags & VIR_DOMAIN_MEM_LIVE)) {
1127 1128
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("cannot set memory on an inactive domain"));
1129
        goto endjob;
1130 1131 1132 1133
    }

    if (flags & VIR_DOMAIN_MEM_CONFIG) {
        if (!vm->persistent) {
1134 1135
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                           _("cannot change persistent config of a transient domain"));
1136
            goto endjob;
1137
        }
1138
        if (!(persistentDef = virDomainObjGetPersistentDef(cfg->caps,
1139
                                                           driver->xmlopt,
1140
                                                           vm)))
1141
            goto endjob;
1142 1143
    }

1144 1145
    if (flags & VIR_DOMAIN_MEM_MAXIMUM) {
        /* resize the maximum memory */
1146

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

        if (flags & VIR_DOMAIN_MEM_CONFIG) {
            /* Help clang 2.8 decipher the logic flow.  */
            sa_assert(persistentDef);
1160
            virDomainDefSetMemoryInitial(persistentDef, newmem);
1161 1162
            if (persistentDef->mem.cur_balloon > newmem)
                persistentDef->mem.cur_balloon = newmem;
1163
            ret = virDomainSaveConfig(cfg->configDir, persistentDef);
1164
            goto endjob;
1165 1166
        }

1167 1168
    } else {
        /* resize the current memory */
1169

1170
        if (newmem > virDomainDefGetMemoryActual(vm->def)) {
1171 1172
            virReportError(VIR_ERR_INVALID_ARG, "%s",
                           _("cannot set memory higher than max memory"));
1173
            goto endjob;
1174 1175 1176
        }

        if (flags & VIR_DOMAIN_MEM_LIVE) {
1177 1178
            int res;

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

        if (flags & VIR_DOMAIN_MEM_CONFIG) {
            sa_assert(persistentDef);
            persistentDef->mem.cur_balloon = newmem;
1196
            ret = virDomainSaveConfig(cfg->configDir, persistentDef);
1197
            goto endjob;
1198
        }
1199 1200
    }

1201 1202
    ret = 0;

1203
 endjob:
1204 1205 1206
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

1207
 cleanup:
1208
    if (vm)
1209
        virObjectUnlock(vm);
1210
    virObjectUnref(cfg);
1211 1212 1213 1214 1215 1216 1217 1218 1219
    return ret;
}

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

1220 1221 1222 1223 1224 1225
static int
libxlDomainSetMaxMemory(virDomainPtr dom, unsigned long memory)
{
    return libxlDomainSetMemoryFlags(dom, memory, VIR_DOMAIN_MEM_MAXIMUM);
}

J
Jim Fehlig 已提交
1226 1227 1228 1229
static int
libxlDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info)
{
    virDomainObjPtr vm;
1230
    libxl_dominfo d_info;
1231
    libxlDomainObjPrivatePtr priv;
J
Jim Fehlig 已提交
1232 1233
    int ret = -1;

J
Jim Fehlig 已提交
1234
    if (!(vm = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
1235 1236
        goto cleanup;

1237 1238 1239
    if (virDomainGetInfoEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

1240
    priv = vm->privateData;
1241 1242 1243
    if (!virDomainObjIsActive(vm)) {
        info->cpuTime = 0;
        info->memory = vm->def->mem.cur_balloon;
1244
        info->maxMem = virDomainDefGetMemoryActual(vm->def);
1245
    } else {
1246
        if (libxl_domain_info(priv->ctx, &d_info, vm->def->id) != 0) {
1247
            virReportError(VIR_ERR_INTERNAL_ERROR,
1248 1249
                           _("libxl_domain_info failed for domain '%d'"),
                           vm->def->id);
1250 1251 1252 1253
            goto cleanup;
        }
        info->cpuTime = d_info.cpu_time;
        info->memory = d_info.current_memkb;
1254
        info->maxMem = d_info.max_memkb;
1255 1256
    }

J
Jiri Denemark 已提交
1257
    info->state = virDomainObjGetState(vm, NULL);
J
Jim Fehlig 已提交
1258 1259 1260
    info->nrVirtCpu = vm->def->vcpus;
    ret = 0;

1261
 cleanup:
J
Jim Fehlig 已提交
1262
    if (vm)
1263
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
1264 1265 1266
    return ret;
}

1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277
static int
libxlDomainGetState(virDomainPtr dom,
                    int *state,
                    int *reason,
                    unsigned int flags)
{
    virDomainObjPtr vm;
    int ret = -1;

    virCheckFlags(0, -1);

J
Jim Fehlig 已提交
1278
    if (!(vm = libxlDomObjFromDomain(dom)))
1279 1280
        goto cleanup;

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

J
Jiri Denemark 已提交
1284
    *state = virDomainObjGetState(vm, reason);
1285 1286
    ret = 0;

1287
 cleanup:
1288
    if (vm)
1289
        virObjectUnlock(vm);
1290 1291 1292
    return ret;
}

1293 1294 1295
/*
 * virDomainObjPtr must be locked on invocation
 */
1296
static int
1297 1298
libxlDoDomainSave(libxlDriverPrivatePtr driver, virDomainObjPtr vm,
                  const char *to)
1299
{
1300
    libxlDomainObjPrivatePtr priv = vm->privateData;
1301
    libxlSavefileHeader hdr;
1302
    virObjectEventPtr event = NULL;
1303 1304
    char *xml = NULL;
    uint32_t xml_len;
1305
    int fd = -1;
1306 1307 1308
    int ret = -1;

    if (virDomainObjGetState(vm, NULL) == VIR_DOMAIN_PAUSED) {
1309 1310 1311
        virReportError(VIR_ERR_OPERATION_INVALID,
                       _("Domain '%d' has to be running because libxenlight will"
                         " suspend it"), vm->def->id);
1312 1313 1314 1315
        goto cleanup;
    }

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

    if (safewrite(fd, xml, xml_len) != xml_len) {
1338 1339
        virReportError(VIR_ERR_OPERATION_FAILED, "%s",
                       _("Failed to write xml description"));
1340 1341 1342
        goto cleanup;
    }

1343 1344 1345 1346 1347 1348
    /* Unlock virDomainObj while saving domain */
    virObjectUnlock(vm);
    ret = libxl_domain_suspend(priv->ctx, vm->def->id, fd, 0, NULL);
    virObjectLock(vm);

    if (ret != 0) {
1349 1350 1351
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to save domain '%d' with libxenlight"),
                       vm->def->id);
1352
        ret = -1;
1353 1354 1355
        goto cleanup;
    }

1356
    event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_STOPPED,
1357 1358
                                         VIR_DOMAIN_EVENT_STOPPED_SAVED);

J
Jim Fehlig 已提交
1359
    if (libxl_domain_destroy(priv->ctx, vm->def->id, NULL) < 0) {
1360 1361
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to destroy domain '%d'"), vm->def->id);
1362 1363 1364
        goto cleanup;
    }

1365
    libxlDomainCleanup(driver, vm, VIR_DOMAIN_SHUTOFF_SAVED);
1366
    vm->hasManagedSave = true;
1367 1368
    ret = 0;

1369
 cleanup:
1370 1371 1372 1373 1374 1375 1376 1377 1378
    VIR_FREE(xml);
    if (VIR_CLOSE(fd) < 0)
        virReportSystemError(errno, "%s", _("cannot close file"));
    if (event)
        libxlDomainEventQueue(driver, event);
    return ret;
}

static int
1379 1380
libxlDomainSaveFlags(virDomainPtr dom, const char *to, const char *dxml,
                     unsigned int flags)
1381
{
1382 1383
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    virDomainObjPtr vm;
1384
    int ret = -1;
1385
    bool remove_dom = false;
1386

1387 1388 1389 1390 1391
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
    virReportUnsupportedError();
    return -1;
#endif

1392 1393
    virCheckFlags(0, -1);
    if (dxml) {
1394 1395
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
1396 1397 1398
        return -1;
    }

J
Jim Fehlig 已提交
1399
    if (!(vm = libxlDomObjFromDomain(dom)))
1400 1401
        goto cleanup;

1402 1403 1404
    if (virDomainSaveFlagsEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

1405 1406 1407
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

1408
    if (!virDomainObjIsActive(vm)) {
1409
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
1410
        goto endjob;
1411 1412
    }

1413
    if (libxlDoDomainSave(driver, vm, to) < 0)
1414
        goto endjob;
1415

1416 1417
    if (!vm->persistent)
        remove_dom = true;
1418 1419

    ret = 0;
1420

1421
 endjob:
1422 1423 1424
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

1425
 cleanup:
1426 1427 1428 1429
    if (remove_dom && vm) {
        virDomainObjListRemove(driver->domains, vm);
        vm = NULL;
    }
1430
    if (vm)
1431
        virObjectUnlock(vm);
1432 1433
    return ret;
}
1434

1435
static int
1436 1437 1438 1439 1440 1441 1442 1443
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)
1444 1445
{
    libxlDriverPrivatePtr driver = conn->privateData;
1446
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
1447 1448 1449 1450 1451
    virDomainObjPtr vm = NULL;
    virDomainDefPtr def = NULL;
    libxlSavefileHeader hdr;
    int fd = -1;
    int ret = -1;
1452

1453 1454 1455 1456 1457
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
    virReportUnsupportedError();
    return -1;
#endif

1458
    virCheckFlags(VIR_DOMAIN_SAVE_PAUSED, -1);
1459
    if (dxml) {
1460 1461
        virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                       _("xml modification unsupported"));
1462 1463 1464
        return -1;
    }

1465
    fd = libxlDomainSaveImageOpen(driver, cfg, from, &def, &hdr);
1466
    if (fd < 0)
1467
        return -1;
1468

1469
    if (virDomainRestoreFlagsEnsureACL(conn, def) < 0)
1470
        goto cleanup;
1471

1472
    if (!(vm = virDomainObjListAdd(driver->domains, def,
1473
                                   driver->xmlopt,
1474 1475 1476
                                   VIR_DOMAIN_OBJ_LIST_ADD_LIVE |
                                   VIR_DOMAIN_OBJ_LIST_ADD_CHECK_LIVE,
                                   NULL)))
1477
        goto cleanup;
1478 1479 1480

    def = NULL;

1481
    ret = libxlDomainStart(driver, vm, (flags & VIR_DOMAIN_SAVE_PAUSED) != 0, fd);
1482
    if (ret < 0 && !vm->persistent) {
1483
        virDomainObjListRemove(driver->domains, vm);
1484 1485 1486
        vm = NULL;
    }

1487
 cleanup:
1488 1489
    if (VIR_CLOSE(fd) < 0)
        virReportSystemError(errno, "%s", _("cannot close file"));
1490 1491
    virDomainDefFree(def);
    if (vm)
1492
        virObjectUnlock(vm);
1493
    virObjectUnref(cfg);
1494 1495 1496
    return ret;
}

1497 1498 1499 1500 1501 1502
static int
libxlDomainRestore(virConnectPtr conn, const char *from)
{
    return libxlDomainRestoreFlags(conn, from, NULL, 0);
}

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

    virCheckFlags(VIR_DUMP_LIVE | VIR_DUMP_CRASH, -1);

J
Jim Fehlig 已提交
1516
    if (!(vm = libxlDomObjFromDomain(dom)))
1517 1518
        goto cleanup;

1519 1520 1521
    if (virDomainCoreDumpEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

1522 1523 1524
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

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

    priv = vm->privateData;

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

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

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

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

    ret = 0;

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

1585
 endjob:
1586 1587 1588
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

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

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

    virCheckFlags(0, -1);

J
Jim Fehlig 已提交
1612
    if (!(vm = libxlDomObjFromDomain(dom)))
1613 1614
        goto cleanup;

1615 1616 1617
    if (virDomainManagedSaveEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

1618 1619 1620
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

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

    name = libxlDomainManagedSavePath(driver, vm);
    if (name == NULL)
1633
        goto endjob;
1634 1635 1636

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

1637
    if (libxlDoDomainSave(driver, vm, name) < 0)
1638
        goto endjob;
1639

1640 1641
    if (!vm->persistent)
        remove_dom = true;
1642 1643

    ret = 0;
1644

1645
 endjob:
1646 1647 1648
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

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

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

1668
    virObjectLock(vm);
1669 1670 1671 1672 1673 1674

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

    vm->hasManagedSave = virFileExists(name);

1675
    ret = 0;
1676
 cleanup:
1677
    virObjectUnlock(vm);
1678
    VIR_FREE(name);
1679
    return ret;
1680 1681
}

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

    virCheckFlags(0, -1);

J
Jim Fehlig 已提交
1690
    if (!(vm = libxlDomObjFromDomain(dom)))
1691 1692
        goto cleanup;

1693 1694 1695
    if (virDomainHasManagedSaveImageEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

1696
    ret = vm->hasManagedSave;
1697

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

1717 1718 1719
    if (virDomainManagedSaveRemoveEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

1720 1721 1722 1723 1724
    name = libxlDomainManagedSavePath(driver, vm);
    if (name == NULL)
        goto cleanup;

    ret = unlink(name);
1725
    vm->hasManagedSave = false;
1726

1727
 cleanup:
1728 1729
    VIR_FREE(name);
    if (vm)
1730
        virObjectUnlock(vm);
1731 1732 1733
    return ret;
}

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

    if (!nvcpus) {
1766
        virReportError(VIR_ERR_INVALID_ARG, "%s", _("nvcpus is zero"));
1767 1768 1769
        return -1;
    }

J
Jim Fehlig 已提交
1770
    if (!(vm = libxlDomObjFromDomain(dom)))
1771 1772
        goto cleanup;

1773 1774 1775
    if (virDomainSetVcpusFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
        goto cleanup;

1776 1777 1778
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

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

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

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

1797
    if (!(flags & VIR_DOMAIN_VCPU_MAXIMUM) && vm->def->maxvcpus < max)
1798 1799 1800
        max = vm->def->maxvcpus;

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

    priv = vm->privateData;

1809
    if (!(def = virDomainObjGetPersistentDef(cfg->caps, driver->xmlopt, vm)))
1810
        goto endjob;
1811

E
Eric Blake 已提交
1812
    maplen = VIR_CPU_MAPLEN(nvcpus);
1813
    if (VIR_ALLOC_N(bitmask, maplen) < 0)
1814
        goto endjob;
1815 1816

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

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

    ret = 0;

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

1860
 endjob:
1861 1862 1863
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

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

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

J
Jim Fehlig 已提交
1890
    if (!(vm = libxlDomObjFromDomain(dom)))
1891 1892
        goto cleanup;

1893
    if (virDomainGetVcpusFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
1894 1895
        goto cleanup;

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

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

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

1928
 cleanup:
1929
    if (vm)
1930
        virObjectUnlock(vm);
1931 1932 1933 1934
    return ret;
}

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

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);
1948

J
Jim Fehlig 已提交
1949
    if (!(vm = libxlDomObjFromDomain(dom)))
1950 1951
        goto cleanup;

1952
    if (virDomainPinVcpuFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
1953 1954
        goto cleanup;

1955 1956 1957
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

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

1964 1965
    if (virDomainLiveConfigHelperMethod(cfg->caps, driver->xmlopt, vm,
                                        &flags, &targetDef) < 0)
1966
        goto endjob;
1967

1968
    if (flags & VIR_DOMAIN_AFFECT_LIVE)
1969 1970 1971 1972 1973
        targetDef = vm->def;

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

1974 1975
    pcpumap = virBitmapNewData(cpumap, maplen);
    if (!pcpumap)
1976
        goto endjob;
1977

1978 1979 1980 1981 1982
    if (flags & VIR_DOMAIN_AFFECT_LIVE) {
        libxl_bitmap map = { .size = maplen, .map = cpumap };
        libxlDomainObjPrivatePtr priv;

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

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

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

2012
 done:
2013 2014
    ret = 0;

2015 2016 2017 2018 2019 2020
    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);
    }

2021
 endjob:
2022 2023 2024
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

2025
 cleanup:
2026
    if (vm)
2027
        virObjectUnlock(vm);
2028
    virBitmapFree(pcpumap);
2029
    virObjectUnref(cfg);
2030 2031 2032
    return ret;
}

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

2041 2042 2043 2044 2045 2046 2047 2048 2049
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;
2050
    virDomainPinDefPtr *vcpupin_list;
2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067
    virBitmapPtr cpumask = NULL;
    int maxcpu, hostcpus, vcpu, pcpu, n, ret = -1;
    unsigned char *cpumap;

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

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

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

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

2068
    if (flags & VIR_DOMAIN_AFFECT_LIVE)
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
        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;
2098
        vcpu = vcpupin_list[n]->id;
2099 2100 2101
        cpumask = vcpupin_list[n]->cpumask;
        cpumap = VIR_GET_CPUMAP(cpumaps, maplen, vcpu);
        for (pcpu = 0; pcpu < maxcpu; pcpu++) {
J
Ján Tomko 已提交
2102
            if (!virBitmapIsBitSet(cpumask, pcpu))
2103 2104 2105 2106 2107
                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;

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

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

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

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

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

2218 2219 2220 2221 2222 2223 2224 2225 2226 2227 2228
    if (STREQ(nativeFormat, LIBXL_CONFIG_FORMAT_XL)) {
        if (!(conf = virConfReadMem(nativeConfig, strlen(nativeConfig), 0)))
            goto cleanup;
        if (!(def = xenParseXL(conf,
                               cfg->caps,
                               cfg->verInfo->xen_version_major))) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("parsing xl config failed"));
            goto cleanup;
        }
    } else if (STREQ(nativeFormat, LIBXL_CONFIG_FORMAT_XM)) {
2229 2230 2231 2232 2233 2234 2235 2236 2237 2238 2239 2240 2241 2242 2243 2244 2245 2246 2247 2248 2249
        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 {
2250 2251
        virReportError(VIR_ERR_INVALID_ARG,
                       _("unsupported config type %s"), nativeFormat);
2252 2253 2254
        goto cleanup;
    }

2255
    xml = virDomainDefFormat(def, VIR_DOMAIN_DEF_FORMAT_INACTIVE);
2256

2257
 cleanup:
2258 2259 2260
    virDomainDefFree(def);
    if (conf)
        virConfFree(conf);
2261
    virObjectUnref(cfg);
2262 2263 2264 2265 2266
    return xml;
}

#define MAX_CONFIG_SIZE (1024 * 65)
static char *
2267 2268 2269
libxlConnectDomainXMLToNative(virConnectPtr conn, const char * nativeFormat,
                              const char * domainXml,
                              unsigned int flags)
2270 2271
{
    libxlDriverPrivatePtr driver = conn->privateData;
2272
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
2273 2274 2275 2276 2277
    virDomainDefPtr def = NULL;
    virConfPtr conf = NULL;
    int len = MAX_CONFIG_SIZE;
    char *ret = NULL;

E
Eric Blake 已提交
2278 2279
    virCheckFlags(0, NULL);

2280 2281 2282
    if (virConnectDomainXMLToNativeEnsureACL(conn) < 0)
        goto cleanup;

2283
    if (!(def = virDomainDefParseString(domainXml,
2284
                                        cfg->caps, driver->xmlopt,
2285
                                        1 << VIR_DOMAIN_VIRT_XEN,
2286
                                        VIR_DOMAIN_DEF_PARSE_INACTIVE)))
2287 2288
        goto cleanup;

2289 2290 2291 2292 2293 2294 2295 2296 2297 2298
    if (STREQ(nativeFormat, LIBXL_CONFIG_FORMAT_XL)) {
        if (!(conf = xenFormatXL(def, conn, cfg->verInfo->xen_version_major)))
            goto cleanup;
    } else if (STREQ(nativeFormat, LIBXL_CONFIG_FORMAT_XM)) {
        if (!(conf = xenFormatXM(conn, def, cfg->verInfo->xen_version_major)))
            goto cleanup;
    } else {

        virReportError(VIR_ERR_INVALID_ARG,
                       _("unsupported config type %s"), nativeFormat);
2299
        goto cleanup;
2300
    }
2301

2302
    if (VIR_ALLOC_N(ret, len) < 0)
2303 2304 2305 2306 2307 2308 2309
        goto cleanup;

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

2310
 cleanup:
2311 2312 2313
    virDomainDefFree(def);
    if (conf)
        virConfFree(conf);
2314
    virObjectUnref(cfg);
2315 2316 2317
    return ret;
}

J
Jim Fehlig 已提交
2318
static int
2319 2320
libxlConnectListDefinedDomains(virConnectPtr conn,
                               char **const names, int nnames)
J
Jim Fehlig 已提交
2321 2322 2323 2324
{
    libxlDriverPrivatePtr driver = conn->privateData;
    int n;

2325 2326 2327
    if (virConnectListDefinedDomainsEnsureACL(conn) < 0)
        return -1;

2328 2329
    n = virDomainObjListGetInactiveNames(driver->domains, names, nnames,
                                         virConnectListDefinedDomainsCheckACL, conn);
J
Jim Fehlig 已提交
2330 2331 2332 2333
    return n;
}

static int
2334
libxlConnectNumOfDefinedDomains(virConnectPtr conn)
J
Jim Fehlig 已提交
2335 2336 2337 2338
{
    libxlDriverPrivatePtr driver = conn->privateData;
    int n;

2339 2340 2341
    if (virConnectNumOfDefinedDomainsEnsureACL(conn) < 0)
        return -1;

2342
    n = virDomainObjListNumOfDomains(driver->domains, false,
2343 2344
                                     virConnectNumOfDefinedDomainsCheckACL,
                                     conn);
J
Jim Fehlig 已提交
2345 2346 2347 2348 2349
    return n;
}

static int
libxlDomainCreateWithFlags(virDomainPtr dom,
E
Eric Blake 已提交
2350
                           unsigned int flags)
J
Jim Fehlig 已提交
2351 2352 2353 2354 2355 2356 2357
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_START_PAUSED, -1);

J
Jim Fehlig 已提交
2358
    if (!(vm = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
2359 2360
        goto cleanup;

2361 2362 2363
    if (virDomainCreateWithFlagsEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

J
Jim Fehlig 已提交
2364
    if (virDomainObjIsActive(vm)) {
2365 2366
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("Domain is already running"));
J
Jim Fehlig 已提交
2367 2368 2369
        goto cleanup;
    }

2370
    ret = libxlDomainStart(driver, vm, (flags & VIR_DOMAIN_START_PAUSED) != 0, -1);
2371 2372 2373
    if (ret < 0)
        goto cleanup;
    dom->id = vm->def->id;
J
Jim Fehlig 已提交
2374

2375
 cleanup:
J
Jim Fehlig 已提交
2376
    if (vm)
2377
        virObjectUnlock(vm);
J
Jim Fehlig 已提交
2378 2379 2380 2381 2382 2383 2384 2385 2386 2387
    return ret;
}

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

static virDomainPtr
2388
libxlDomainDefineXMLFlags(virConnectPtr conn, const char *xml, unsigned int flags)
J
Jim Fehlig 已提交
2389 2390
{
    libxlDriverPrivatePtr driver = conn->privateData;
2391
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
J
Jim Fehlig 已提交
2392 2393 2394
    virDomainDefPtr def = NULL;
    virDomainObjPtr vm = NULL;
    virDomainPtr dom = NULL;
2395
    virObjectEventPtr event = NULL;
2396
    virDomainDefPtr oldDef = NULL;
2397
    unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;
J
Jim Fehlig 已提交
2398

2399 2400 2401 2402
    virCheckFlags(VIR_DOMAIN_DEFINE_VALIDATE, NULL);

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

2404
    if (!(def = virDomainDefParseString(xml, cfg->caps, driver->xmlopt,
M
Matthias Bolte 已提交
2405
                                        1 << VIR_DOMAIN_VIRT_XEN,
2406
                                        parse_flags)))
2407
        goto cleanup;
J
Jim Fehlig 已提交
2408

2409
    if (virDomainDefineXMLFlagsEnsureACL(conn, def) < 0)
2410
        goto cleanup;
2411

2412
    if (!(vm = virDomainObjListAdd(driver->domains, def,
2413
                                   driver->xmlopt,
2414 2415
                                   0,
                                   &oldDef)))
2416
        goto cleanup;
2417

J
Jim Fehlig 已提交
2418 2419 2420
    def = NULL;
    vm->persistent = 1;

2421
    if (virDomainSaveConfig(cfg->configDir,
J
Jim Fehlig 已提交
2422
                            vm->newDef ? vm->newDef : vm->def) < 0) {
2423
        virDomainObjListRemove(driver->domains, vm);
J
Jim Fehlig 已提交
2424 2425 2426 2427 2428 2429 2430 2431
        vm = NULL;
        goto cleanup;
    }

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

2432
    event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_DEFINED,
2433
                                     !oldDef ?
2434 2435 2436
                                     VIR_DOMAIN_EVENT_DEFINED_ADDED :
                                     VIR_DOMAIN_EVENT_DEFINED_UPDATED);

2437
 cleanup:
J
Jim Fehlig 已提交
2438
    virDomainDefFree(def);
2439
    virDomainDefFree(oldDef);
J
Jim Fehlig 已提交
2440
    if (vm)
2441
        virObjectUnlock(vm);
2442 2443
    if (event)
        libxlDomainEventQueue(driver, event);
2444
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
2445 2446 2447
    return dom;
}

2448 2449 2450 2451 2452 2453
static virDomainPtr
libxlDomainDefineXML(virConnectPtr conn, const char *xml)
{
    return libxlDomainDefineXMLFlags(conn, xml, 0);
}

J
Jim Fehlig 已提交
2454
static int
2455 2456
libxlDomainUndefineFlags(virDomainPtr dom,
                         unsigned int flags)
J
Jim Fehlig 已提交
2457 2458
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
2459
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
J
Jim Fehlig 已提交
2460
    virDomainObjPtr vm;
2461
    virObjectEventPtr event = NULL;
2462
    char *name = NULL;
J
Jim Fehlig 已提交
2463 2464
    int ret = -1;

2465 2466
    virCheckFlags(VIR_DOMAIN_UNDEFINE_MANAGED_SAVE, -1);

J
Jim Fehlig 已提交
2467
    if (!(vm = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
2468 2469
        goto cleanup;

2470 2471 2472
    if (virDomainUndefineFlagsEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

J
Jim Fehlig 已提交
2473
    if (!vm->persistent) {
2474 2475
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("cannot undefine transient domain"));
J
Jim Fehlig 已提交
2476 2477 2478
        goto cleanup;
    }

2479 2480 2481 2482 2483 2484 2485
    name = libxlDomainManagedSavePath(driver, vm);
    if (name == NULL)
        goto cleanup;

    if (virFileExists(name)) {
        if (flags & VIR_DOMAIN_UNDEFINE_MANAGED_SAVE) {
            if (unlink(name) < 0) {
2486 2487
                virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                               _("Failed to remove domain managed save image"));
2488 2489 2490
                goto cleanup;
            }
        } else {
2491 2492 2493
            virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                           _("Refusing to undefine while domain managed "
                             "save image exists"));
2494 2495 2496 2497
            goto cleanup;
        }
    }

2498
    if (virDomainDeleteConfig(cfg->configDir, cfg->autostartDir, vm) < 0)
J
Jim Fehlig 已提交
2499 2500
        goto cleanup;

2501
    event = virDomainEventLifecycleNewFromObj(vm, VIR_DOMAIN_EVENT_UNDEFINED,
2502 2503
                                     VIR_DOMAIN_EVENT_UNDEFINED_REMOVED);

2504 2505 2506
    if (virDomainObjIsActive(vm)) {
        vm->persistent = 0;
    } else {
2507
        virDomainObjListRemove(driver->domains, vm);
2508 2509 2510
        vm = NULL;
    }

J
Jim Fehlig 已提交
2511 2512
    ret = 0;

2513
 cleanup:
2514
    VIR_FREE(name);
J
Jim Fehlig 已提交
2515
    if (vm)
2516
        virObjectUnlock(vm);
2517 2518
    if (event)
        libxlDomainEventQueue(driver, event);
2519
    virObjectUnref(cfg);
J
Jim Fehlig 已提交
2520 2521 2522
    return ret;
}

2523 2524 2525 2526 2527 2528
static int
libxlDomainUndefine(virDomainPtr dom)
{
    return libxlDomainUndefineFlags(dom, 0);
}

2529 2530 2531 2532 2533 2534
static int
libxlDomainChangeEjectableMedia(libxlDomainObjPrivatePtr priv,
                                virDomainObjPtr vm, virDomainDiskDefPtr disk)
{
    virDomainDiskDefPtr origdisk = NULL;
    libxl_device_disk x_disk;
2535
    size_t i;
2536 2537
    int ret = -1;

2538
    for (i = 0; i < vm->def->ndisks; i++) {
2539 2540 2541 2542 2543 2544 2545 2546
        if (vm->def->disks[i]->bus == disk->bus &&
            STREQ(vm->def->disks[i]->dst, disk->dst)) {
            origdisk = vm->def->disks[i];
            break;
        }
    }

    if (!origdisk) {
2547 2548 2549
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("No device with bus '%s' and target '%s'"),
                       virDomainDiskBusTypeToString(disk->bus), disk->dst);
2550 2551 2552 2553
        goto cleanup;
    }

    if (origdisk->device != VIR_DOMAIN_DISK_DEVICE_CDROM) {
2554 2555 2556
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Removable media not supported for %s device"),
                       virDomainDiskDeviceTypeToString(disk->device));
2557 2558 2559
        return -1;
    }

J
Jim Fehlig 已提交
2560
    if (libxlMakeDisk(disk, &x_disk) < 0)
2561 2562
        goto cleanup;

J
Jim Fehlig 已提交
2563
    if ((ret = libxl_cdrom_insert(priv->ctx, vm->def->id, &x_disk, NULL)) < 0) {
2564 2565 2566
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("libxenlight failed to change media for disk '%s'"),
                       disk->dst);
2567 2568 2569
        goto cleanup;
    }

2570 2571 2572
    if (virDomainDiskSetSource(origdisk, virDomainDiskGetSource(disk)) < 0)
        goto cleanup;
    virDomainDiskSetType(origdisk, virDomainDiskGetType(disk));
2573 2574 2575 2576 2577

    virDomainDiskDefFree(disk);

    ret = 0;

2578
 cleanup:
2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595
    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) {
2596
                if (virDomainDiskIndexByName(vm->def, l_disk->dst, true) >= 0) {
2597 2598
                    virReportError(VIR_ERR_OPERATION_FAILED,
                                   _("target %s already exists"), l_disk->dst);
2599 2600 2601
                    goto cleanup;
                }

2602
                if (!virDomainDiskGetSource(l_disk)) {
2603 2604
                    virReportError(VIR_ERR_INTERNAL_ERROR,
                                   "%s", _("disk source path is missing"));
2605 2606 2607
                    goto cleanup;
                }

2608
                if (VIR_REALLOC_N(vm->def->disks, vm->def->ndisks+1) < 0)
2609 2610
                    goto cleanup;

J
Jim Fehlig 已提交
2611
                if (libxlMakeDisk(l_disk, &x_disk) < 0)
2612 2613
                    goto cleanup;

J
Jim Fehlig 已提交
2614 2615
                if ((ret = libxl_device_disk_add(priv->ctx, vm->def->id,
                                                &x_disk, NULL)) < 0) {
2616 2617 2618
                    virReportError(VIR_ERR_INTERNAL_ERROR,
                                   _("libxenlight failed to attach disk '%s'"),
                                   l_disk->dst);
2619 2620 2621 2622 2623 2624
                    goto cleanup;
                }

                virDomainDiskInsertPreAlloced(vm->def, l_disk);

            } else {
2625 2626 2627
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("disk bus '%s' cannot be hotplugged."),
                               virDomainDiskBusTypeToString(l_disk->bus));
2628 2629 2630
            }
            break;
        default:
2631 2632 2633
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("disk device type '%s' cannot be hotplugged"),
                           virDomainDiskDeviceTypeToString(l_disk->device));
2634 2635 2636
            break;
    }

2637
 cleanup:
2638 2639 2640
    return ret;
}

2641 2642 2643 2644 2645 2646 2647 2648 2649
static int
libxlDomainAttachHostPCIDevice(libxlDriverPrivatePtr driver,
                               libxlDomainObjPrivatePtr priv,
                               virDomainObjPtr vm,
                               virDomainHostdevDefPtr hostdev)
{
    libxl_device_pci pcidev;
    virDomainHostdevDefPtr found;
    virHostdevManagerPtr hostdev_mgr = driver->hostdevMgr;
2650
    virDomainHostdevSubsysPCIPtr pcisrc = &hostdev->source.subsys.u.pci;
2651 2652 2653 2654 2655 2656 2657

    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"),
2658 2659
                       pcisrc->addr.domain, pcisrc->addr.bus,
                       pcisrc->addr.slot, pcisrc->addr.function);
2660 2661 2662 2663 2664 2665 2666 2667 2668
        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 已提交
2669
        return -1;
2670

2671
    if (libxlMakePCI(hostdev, &pcidev) < 0)
C
Chunyan Liu 已提交
2672
        goto error;
2673 2674 2675 2676

    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"),
2677 2678
                       pcisrc->addr.domain, pcisrc->addr.bus,
                       pcisrc->addr.slot, pcisrc->addr.function);
C
Chunyan Liu 已提交
2679
        goto error;
2680 2681 2682 2683 2684
    }

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

2685
 error:
2686 2687 2688 2689 2690 2691 2692 2693 2694
    virHostdevReAttachPCIDevices(hostdev_mgr, LIBXL_DRIVER_NAME,
                                 vm->def->name, &hostdev, 1, NULL);
    return -1;
}

static int
libxlDomainAttachHostDevice(libxlDriverPrivatePtr driver,
                            libxlDomainObjPrivatePtr priv,
                            virDomainObjPtr vm,
2695
                            virDomainHostdevDefPtr hostdev)
2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706
{
    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 已提交
2707
            return -1;
2708 2709 2710 2711 2712 2713
        break;

    default:
        virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                       _("hostdev subsys type '%s' not supported"),
                       virDomainHostdevSubsysTypeToString(hostdev->source.subsys.type));
C
Chunyan Liu 已提交
2714
        return -1;
2715 2716 2717 2718 2719
    }

    return 0;
}

2720 2721 2722 2723 2724 2725
static int
libxlDomainDetachDeviceDiskLive(libxlDomainObjPrivatePtr priv,
                                virDomainObjPtr vm, virDomainDeviceDefPtr dev)
{
    virDomainDiskDefPtr l_disk = NULL;
    libxl_device_disk x_disk;
2726
    int idx;
2727 2728 2729 2730 2731 2732
    int ret = -1;

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

2733 2734 2735
                if ((idx = virDomainDiskIndexByName(vm->def,
                                                    dev->data.disk->dst,
                                                    false)) < 0) {
2736 2737
                    virReportError(VIR_ERR_OPERATION_FAILED,
                                   _("disk %s not found"), dev->data.disk->dst);
2738 2739 2740
                    goto cleanup;
                }

2741
                l_disk = vm->def->disks[idx];
2742

J
Jim Fehlig 已提交
2743
                if (libxlMakeDisk(l_disk, &x_disk) < 0)
2744 2745
                    goto cleanup;

J
Jim Fehlig 已提交
2746 2747
                if ((ret = libxl_device_disk_remove(priv->ctx, vm->def->id,
                                                    &x_disk, NULL)) < 0) {
2748 2749 2750
                    virReportError(VIR_ERR_INTERNAL_ERROR,
                                   _("libxenlight failed to detach disk '%s'"),
                                   l_disk->dst);
2751 2752 2753
                    goto cleanup;
                }

2754
                virDomainDiskRemove(vm->def, idx);
2755 2756 2757
                virDomainDiskDefFree(l_disk);

            } else {
2758 2759 2760
                virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                               _("disk bus '%s' cannot be hot unplugged."),
                               virDomainDiskBusTypeToString(dev->data.disk->bus));
2761 2762 2763
            }
            break;
        default:
2764 2765 2766
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("device type '%s' cannot hot unplugged"),
                           virDomainDiskDeviceTypeToString(dev->data.disk->device));
2767 2768 2769
            break;
    }

2770
 cleanup:
2771 2772 2773
    return ret;
}

2774 2775 2776 2777 2778 2779 2780 2781 2782
static int
libxlDomainAttachNetDevice(libxlDriverPrivatePtr driver,
                           libxlDomainObjPrivatePtr priv,
                           virDomainObjPtr vm,
                           virDomainNetDefPtr net)
{
    int actualType;
    libxl_device_nic nic;
    int ret = -1;
2783
    char mac[VIR_MAC_STRING_BUFLEN];
2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797

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

2798 2799 2800 2801 2802 2803 2804
    if (virDomainHasNet(vm->def, net)) {
        virReportError(VIR_ERR_INVALID_ARG,
                       _("network device with mac %s already exists"),
                       virMacAddrFormat(&net->mac, mac));
        return -1;
    }

2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 2828 2829 2830 2831 2832 2833 2834 2835
    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;
}

2836
static int
2837 2838 2839
libxlDomainAttachDeviceLive(libxlDriverPrivatePtr driver,
                            libxlDomainObjPrivatePtr priv,
                            virDomainObjPtr vm,
2840 2841 2842 2843 2844 2845 2846 2847 2848 2849 2850
                            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;

2851 2852 2853 2854 2855 2856 2857
        case VIR_DOMAIN_DEVICE_NET:
            ret = libxlDomainAttachNetDevice(driver, priv, vm,
                                             dev->data.net);
            if (!ret)
                dev->data.net = NULL;
            break;

2858
        case VIR_DOMAIN_DEVICE_HOSTDEV:
2859 2860
            ret = libxlDomainAttachHostDevice(driver, priv, vm,
                                              dev->data.hostdev);
2861 2862 2863 2864
            if (!ret)
                dev->data.hostdev = NULL;
            break;

2865
        default:
2866 2867 2868
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("device type '%s' cannot be attached"),
                           virDomainDeviceTypeToString(dev->type));
2869 2870 2871 2872 2873 2874 2875 2876 2877 2878
            break;
    }

    return ret;
}

static int
libxlDomainAttachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev)
{
    virDomainDiskDefPtr disk;
2879
    virDomainNetDefPtr net;
2880 2881
    virDomainHostdevDefPtr hostdev;
    virDomainHostdevDefPtr found;
2882
    virDomainHostdevSubsysPCIPtr pcisrc;
2883
    char mac[VIR_MAC_STRING_BUFLEN];
2884 2885 2886 2887

    switch (dev->type) {
        case VIR_DOMAIN_DEVICE_DISK:
            disk = dev->data.disk;
2888
            if (virDomainDiskIndexByName(vmdef, disk->dst, true) >= 0) {
2889 2890
                virReportError(VIR_ERR_INVALID_ARG,
                               _("target %s already exists."), disk->dst);
2891 2892
                return -1;
            }
2893
            if (virDomainDiskInsert(vmdef, disk))
2894 2895 2896 2897
                return -1;
            /* vmdef has the pointer. Generic codes for vmdef will do all jobs */
            dev->data.disk = NULL;
            break;
2898 2899 2900

        case VIR_DOMAIN_DEVICE_NET:
            net = dev->data.net;
2901 2902 2903 2904 2905 2906
            if (virDomainHasNet(vmdef, net)) {
                virReportError(VIR_ERR_INVALID_ARG,
                               _("network device with mac %s already exists"),
                               virMacAddrFormat(&net->mac, mac));
                return -1;
            }
2907 2908 2909 2910 2911
            if (virDomainNetInsert(vmdef, net))
                return -1;
            dev->data.net = NULL;
            break;

2912 2913 2914 2915 2916 2917 2918
        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) {
2919
                pcisrc = &hostdev->source.subsys.u.pci;
2920 2921 2922
                virReportError(VIR_ERR_OPERATION_FAILED,
                               _("target pci device %.4x:%.2x:%.2x.%.1x\
                                  already exists"),
2923 2924
                               pcisrc->addr.domain, pcisrc->addr.bus,
                               pcisrc->addr.slot, pcisrc->addr.function);
2925 2926 2927
                return -1;
            }

2928 2929
            if (virDomainHostdevInsert(vmdef, hostdev) < 0)
                return -1;
2930
            break;
2931 2932

        default:
2933 2934
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("persistent attach of device is not supported"));
2935 2936 2937 2938 2939 2940
            return -1;
    }
    return 0;
}

static int
2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 2959 2960 2961 2962 2963 2964 2965 2966 2967 2968 2969 2970 2971 2972 2973 2974 2975
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;
2976
    virDomainHostdevSubsysPCIPtr pcisrc = &subsys->u.pci;
2977 2978 2979 2980 2981 2982 2983 2984 2985 2986 2987 2988
    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"),
2989 2990
                       pcisrc->addr.domain, pcisrc->addr.bus,
                       pcisrc->addr.slot, pcisrc->addr.function);
2991 2992 2993 2994 2995 2996
        return -1;
    }

    if (libxlIsMultiFunctionDevice(vm->def, detach->info)) {
        virReportError(VIR_ERR_OPERATION_FAILED,
                       _("cannot hot unplug multifunction PCI device: %.4x:%.2x:%.2x.%.1x"),
2997 2998
                       pcisrc->addr.domain, pcisrc->addr.bus,
                       pcisrc->addr.slot, pcisrc->addr.function);
C
Chunyan Liu 已提交
2999
        goto error;
3000 3001 3002 3003 3004
    }


    libxl_device_pci_init(&pcidev);

3005
    if (libxlMakePCI(detach, &pcidev) < 0)
C
Chunyan Liu 已提交
3006
        goto error;
3007 3008 3009 3010 3011

    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"),
3012 3013
                       pcisrc->addr.domain, pcisrc->addr.bus,
                       pcisrc->addr.slot, pcisrc->addr.function);
C
Chunyan Liu 已提交
3014
        goto error;
3015 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025
    }

    libxl_device_pci_dispose(&pcidev);

    virDomainHostdevRemove(vm->def, idx);

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

    return 0;

3026
 error:
3027 3028 3029 3030 3031 3032 3033 3034
    virDomainHostdevDefFree(detach);
    return -1;
}

static int
libxlDomainDetachHostDevice(libxlDriverPrivatePtr driver,
                            libxlDomainObjPrivatePtr priv,
                            virDomainObjPtr vm,
3035
                            virDomainHostdevDefPtr hostdev)
3036 3037 3038 3039 3040 3041 3042 3043 3044 3045 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058
{
    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;
}

3059 3060 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105
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;
}

3106 3107 3108 3109
static int
libxlDomainDetachDeviceLive(libxlDriverPrivatePtr driver,
                            libxlDomainObjPrivatePtr priv,
                            virDomainObjPtr vm,
3110 3111 3112 3113 3114 3115 3116 3117 3118
                            virDomainDeviceDefPtr dev)
{
    int ret = -1;

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

3119 3120 3121 3122 3123
        case VIR_DOMAIN_DEVICE_NET:
            ret = libxlDomainDetachNetDevice(driver, priv, vm,
                                             dev->data.net);
            break;

3124
        case VIR_DOMAIN_DEVICE_HOSTDEV:
3125 3126
            ret = libxlDomainDetachHostDevice(driver, priv, vm,
                                              dev->data.hostdev);
3127 3128
            break;

3129
        default:
3130 3131 3132
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("device type '%s' cannot be detached"),
                           virDomainDeviceTypeToString(dev->type));
3133 3134 3135 3136 3137 3138
            break;
    }

    return ret;
}

3139

3140 3141 3142
static int
libxlDomainDetachDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev)
{
3143
    virDomainDiskDefPtr disk, detach;
3144
    virDomainHostdevDefPtr hostdev, det_hostdev;
3145
    virDomainNetDefPtr net;
3146
    int idx;
3147 3148 3149 3150

    switch (dev->type) {
        case VIR_DOMAIN_DEVICE_DISK:
            disk = dev->data.disk;
3151
            if (!(detach = virDomainDiskRemoveByName(vmdef, disk->dst))) {
3152 3153
                virReportError(VIR_ERR_INVALID_ARG,
                               _("no target device %s"), disk->dst);
3154
                return -1;
3155
            }
3156
            virDomainDiskDefFree(detach);
3157
            break;
3158

3159 3160 3161 3162 3163 3164 3165 3166 3167
        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;

3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179
        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;
        }

3180
        default:
3181 3182
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("persistent detach of device is not supported"));
3183
            return -1;
3184 3185
    }

3186
    return 0;
3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205
}

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:
3206 3207 3208
                    virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                                   _("disk bus '%s' cannot be updated."),
                                   virDomainDiskBusTypeToString(disk->bus));
3209 3210 3211 3212
                    break;
            }
            break;
        default:
3213 3214 3215
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                           _("device type '%s' cannot be updated"),
                           virDomainDeviceTypeToString(dev->type));
3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226
            break;
    }

    return ret;
}

static int
libxlDomainUpdateDeviceConfig(virDomainDefPtr vmdef, virDomainDeviceDefPtr dev)
{
    virDomainDiskDefPtr orig;
    virDomainDiskDefPtr disk;
3227
    int idx;
3228 3229 3230 3231 3232
    int ret = -1;

    switch (dev->type) {
        case VIR_DOMAIN_DEVICE_DISK:
            disk = dev->data.disk;
3233
            if ((idx = virDomainDiskIndexByName(vmdef, disk->dst, false)) < 0) {
3234 3235
                virReportError(VIR_ERR_INVALID_ARG,
                               _("target %s doesn't exist."), disk->dst);
3236 3237
                goto cleanup;
            }
3238
            orig = vmdef->disks[idx];
3239
            if (!(orig->device == VIR_DOMAIN_DISK_DEVICE_CDROM)) {
3240 3241
                virReportError(VIR_ERR_INVALID_ARG, "%s",
                               _("this disk doesn't support update"));
3242 3243 3244
                goto cleanup;
            }

3245 3246 3247 3248 3249 3250
            if (virDomainDiskSetSource(orig, virDomainDiskGetSource(disk)) < 0)
                goto cleanup;
            virDomainDiskSetType(orig, virDomainDiskGetType(disk));
            virDomainDiskSetFormat(orig, virDomainDiskGetFormat(disk));
            if (virDomainDiskSetDriver(orig, virDomainDiskGetDriver(disk)) < 0)
                goto cleanup;
3251 3252
            break;
        default:
3253 3254
            virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                           _("persistent update of device is not supported"));
3255 3256 3257 3258 3259
            goto cleanup;
    }

    ret = 0;

3260
 cleanup:
3261 3262 3263 3264 3265
    return ret;
}


static int
3266 3267
libxlDomainAttachDeviceFlags(virDomainPtr dom, const char *xml,
                             unsigned int flags)
3268 3269
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
3270
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
3271 3272 3273 3274 3275 3276 3277 3278 3279
    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 已提交
3280
    if (!(vm = libxlDomObjFromDomain(dom)))
3281 3282
        goto cleanup;

3283 3284 3285
    if (virDomainAttachDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
        goto cleanup;

3286 3287 3288
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

3289 3290 3291 3292 3293 3294 3295 3296
    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) {
3297 3298
            virReportError(VIR_ERR_OPERATION_INVALID,
                           "%s", _("Domain is not running"));
3299
            goto endjob;
3300 3301 3302 3303
        }
    }

    if ((flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) && !vm->persistent) {
3304 3305
         virReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("cannot modify device on transient domain"));
3306
         goto endjob;
3307 3308 3309 3310 3311
    }

    priv = vm->privateData;

    if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
3312
        if (!(dev = virDomainDeviceDefParse(xml, vm->def,
3313
                                            cfg->caps, driver->xmlopt,
3314
                                            VIR_DOMAIN_DEF_PARSE_INACTIVE)))
3315
            goto endjob;
3316 3317

        /* Make a copy for updated domain. */
3318
        if (!(vmdef = virDomainObjCopyPersistentDef(vm, cfg->caps,
3319
                                                    driver->xmlopt)))
3320
            goto endjob;
3321

3322
        if (libxlDomainAttachDeviceConfig(vmdef, dev) < 0)
3323
            goto endjob;
3324
    }
3325 3326 3327 3328

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

3334
        if (libxlDomainAttachDeviceLive(driver, priv, vm, dev) < 0)
3335
            goto endjob;
3336

3337 3338 3339 3340
        /*
         * update domain status forcibly because the domain status may be
         * changed even if we attach the device failed.
         */
3341
        if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
3342
            goto endjob;
3343 3344
    }

3345 3346
    ret = 0;

3347
    /* Finally, if no error until here, we can save config. */
3348
    if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
3349
        ret = virDomainSaveConfig(cfg->configDir, vmdef);
3350
        if (!ret) {
3351
            virDomainObjAssignDef(vm, vmdef, false, NULL);
3352 3353 3354 3355
            vmdef = NULL;
        }
    }

3356
 endjob:
3357 3358 3359
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

3360
 cleanup:
3361 3362 3363
    virDomainDefFree(vmdef);
    virDomainDeviceDefFree(dev);
    if (vm)
3364
        virObjectUnlock(vm);
3365
    virObjectUnref(cfg);
3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379
    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)
{
3380
    libxlDriverPrivatePtr driver = dom->conn->privateData;
3381
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
3382 3383 3384 3385 3386 3387 3388 3389 3390
    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 已提交
3391
    if (!(vm = libxlDomObjFromDomain(dom)))
3392 3393
        goto cleanup;

3394 3395 3396
    if (virDomainDetachDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
        goto cleanup;

3397 3398 3399
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

3400 3401 3402 3403 3404 3405 3406 3407 3408 3409
    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"));
3410
            goto endjob;
3411 3412 3413 3414 3415 3416
        }
    }

    if ((flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) && !vm->persistent) {
         virReportError(VIR_ERR_OPERATION_INVALID,
                        "%s", _("cannot modify device on transient domain"));
3417
         goto endjob;
3418 3419 3420 3421 3422 3423
    }

    priv = vm->privateData;

    if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
        if (!(dev = virDomainDeviceDefParse(xml, vm->def,
3424
                                            cfg->caps, driver->xmlopt,
3425
                                            VIR_DOMAIN_DEF_PARSE_INACTIVE)))
3426
            goto endjob;
3427 3428

        /* Make a copy for updated domain. */
3429
        if (!(vmdef = virDomainObjCopyPersistentDef(vm, cfg->caps,
3430
                                                    driver->xmlopt)))
3431
            goto endjob;
3432

3433
        if (libxlDomainDetachDeviceConfig(vmdef, dev) < 0)
3434
            goto endjob;
3435 3436 3437 3438 3439 3440
    }

    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,
3441
                                            cfg->caps, driver->xmlopt,
3442
                                            VIR_DOMAIN_DEF_PARSE_INACTIVE)))
3443
            goto endjob;
3444

3445
        if (libxlDomainDetachDeviceLive(driver, priv, vm, dev) < 0)
3446
            goto endjob;
3447 3448 3449 3450 3451

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

3456 3457
    ret = 0;

3458
    /* Finally, if no error until here, we can save config. */
3459
    if (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG) {
3460
        ret = virDomainSaveConfig(cfg->configDir, vmdef);
3461 3462 3463 3464 3465 3466
        if (!ret) {
            virDomainObjAssignDef(vm, vmdef, false, NULL);
            vmdef = NULL;
        }
    }

3467
 endjob:
3468 3469 3470
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

3471
 cleanup:
3472 3473 3474 3475
    virDomainDefFree(vmdef);
    virDomainDeviceDefFree(dev);
    if (vm)
        virObjectUnlock(vm);
3476
    virObjectUnref(cfg);
3477
    return ret;
3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 3488 3489 3490
}

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)
{
3491
    libxlDriverPrivatePtr driver = dom->conn->privateData;
3492
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
3493 3494 3495 3496 3497 3498 3499 3500 3501
    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 已提交
3502
    if (!(vm = libxlDomObjFromDomain(dom)))
3503 3504
        goto cleanup;

3505 3506 3507
    if (virDomainUpdateDeviceFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
        goto cleanup;

3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531
    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,
3532
                                            cfg->caps, driver->xmlopt,
3533
                                            VIR_DOMAIN_DEF_PARSE_INACTIVE)))
3534 3535 3536
            goto cleanup;

        /* Make a copy for updated domain. */
3537
        if (!(vmdef = virDomainObjCopyPersistentDef(vm, cfg->caps,
3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550
                                                    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,
3551
                                            cfg->caps, driver->xmlopt,
3552
                                            VIR_DOMAIN_DEF_PARSE_INACTIVE)))
3553 3554 3555 3556 3557 3558 3559 3560 3561
            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.
         */
3562
        if (virDomainSaveStatus(driver->xmlopt, cfg->stateDir, vm) < 0)
3563 3564 3565 3566 3567
            ret = -1;
    }

    /* Finally, if no error until here, we can save config. */
    if (!ret && (flags & VIR_DOMAIN_DEVICE_MODIFY_CONFIG)) {
3568
        ret = virDomainSaveConfig(cfg->configDir, vmdef);
3569 3570 3571 3572 3573 3574
        if (!ret) {
            virDomainObjAssignDef(vm, vmdef, false, NULL);
            vmdef = NULL;
        }
    }

3575
 cleanup:
3576 3577 3578 3579
    virDomainDefFree(vmdef);
    virDomainDeviceDefFree(dev);
    if (vm)
        virObjectUnlock(vm);
3580
    virObjectUnref(cfg);
3581
    return ret;
3582 3583
}

3584 3585 3586 3587 3588
static unsigned long long
libxlNodeGetFreeMemory(virConnectPtr conn)
{
    libxl_physinfo phy_info;
    libxlDriverPrivatePtr driver = conn->privateData;
3589 3590
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
    unsigned long long ret = 0;
3591

3592
    if (virNodeGetFreeMemoryEnsureACL(conn) < 0)
3593
        goto cleanup;
3594

3595
    if (libxl_get_physinfo(cfg->ctx, &phy_info)) {
3596 3597
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("libxl_get_physinfo_info failed"));
3598
        goto cleanup;
3599 3600
    }

3601 3602
    ret = phy_info.free_pages * cfg->verInfo->pagesize;

3603
 cleanup:
3604 3605
    virObjectUnref(cfg);
    return ret;
3606 3607
}

3608 3609 3610 3611 3612 3613 3614 3615 3616 3617
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;
3618
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
3619 3620

    if (virNodeGetCellsFreeMemoryEnsureACL(conn) < 0)
3621
        goto cleanup;
3622

3623
    numa_info = libxl_get_numainfo(cfg->ctx, &nr_nodes);
3624
    if (numa_info == NULL || nr_nodes == 0) {
3625 3626 3627
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("libxl_get_numainfo failed"));
        goto cleanup;
3628 3629 3630
    }

    /* Check/sanitize the cell range */
3631
    if (startCell >= nr_nodes) {
3632 3633
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("start cell %d out of range (0-%d)"),
3634
                       startCell, nr_nodes - 1);
3635 3636 3637
        goto cleanup;
    }
    lastCell = startCell + maxCells - 1;
3638 3639
    if (lastCell >= nr_nodes)
        lastCell = nr_nodes - 1;
3640 3641 3642 3643 3644 3645 3646

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

3648 3649
    ret = numCells;

3650
 cleanup:
3651
    libxl_numainfo_list_free(numa_info, nr_nodes);
3652
    virObjectUnref(cfg);
3653 3654 3655
    return ret;
}

3656
static int
3657
libxlConnectDomainEventRegister(virConnectPtr conn,
3658 3659
                                virConnectDomainEventCallback callback,
                                void *opaque,
3660
                                virFreeCallback freecb)
3661 3662 3663
{
    libxlDriverPrivatePtr driver = conn->privateData;

3664 3665 3666
    if (virConnectDomainEventRegisterEnsureACL(conn) < 0)
        return -1;

3667 3668 3669 3670
    if (virDomainEventStateRegister(conn,
                                    driver->domainEventState,
                                    callback, opaque, freecb) < 0)
        return -1;
3671

3672
    return 0;
3673 3674 3675 3676
}


static int
3677 3678
libxlConnectDomainEventDeregister(virConnectPtr conn,
                                  virConnectDomainEventCallback callback)
3679 3680 3681
{
    libxlDriverPrivatePtr driver = conn->privateData;

3682 3683 3684
    if (virConnectDomainEventDeregisterEnsureACL(conn) < 0)
        return -1;

3685 3686 3687 3688
    if (virDomainEventStateDeregister(conn,
                                      driver->domainEventState,
                                      callback) < 0)
        return -1;
3689

3690
    return 0;
3691 3692
}

3693 3694 3695 3696 3697 3698
static int
libxlDomainGetAutostart(virDomainPtr dom, int *autostart)
{
    virDomainObjPtr vm;
    int ret = -1;

J
Jim Fehlig 已提交
3699
    if (!(vm = libxlDomObjFromDomain(dom)))
3700 3701
        goto cleanup;

3702 3703 3704
    if (virDomainGetAutostartEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

3705 3706 3707
    *autostart = vm->autostart;
    ret = 0;

3708
 cleanup:
3709
    if (vm)
3710
        virObjectUnlock(vm);
3711 3712 3713 3714 3715 3716 3717
    return ret;
}

static int
libxlDomainSetAutostart(virDomainPtr dom, int autostart)
{
    libxlDriverPrivatePtr driver = dom->conn->privateData;
3718
    libxlDriverConfigPtr cfg = libxlDriverConfigGet(driver);
3719 3720 3721 3722
    virDomainObjPtr vm;
    char *configFile = NULL, *autostartLink = NULL;
    int ret = -1;

J
Jim Fehlig 已提交
3723
    if (!(vm = libxlDomObjFromDomain(dom)))
3724 3725
        goto cleanup;

3726 3727 3728
    if (virDomainSetAutostartEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

3729 3730 3731
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

3732
    if (!vm->persistent) {
3733 3734
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s", _("cannot set autostart for transient domain"));
3735
        goto endjob;
3736 3737 3738 3739 3740
    }

    autostart = (autostart != 0);

    if (vm->autostart != autostart) {
3741
        if (!(configFile = virDomainConfigFile(cfg->configDir, vm->def->name)))
3742
            goto endjob;
3743
        if (!(autostartLink = virDomainConfigFile(cfg->autostartDir, vm->def->name)))
3744
            goto endjob;
3745 3746

        if (autostart) {
3747
            if (virFileMakePath(cfg->autostartDir) < 0) {
3748
                virReportSystemError(errno,
3749
                                     _("cannot create autostart directory %s"),
3750
                                     cfg->autostartDir);
3751
                goto endjob;
3752 3753 3754 3755 3756 3757
            }

            if (symlink(configFile, autostartLink) < 0) {
                virReportSystemError(errno,
                                     _("Failed to create symlink '%s to '%s'"),
                                     autostartLink, configFile);
3758
                goto endjob;
3759 3760 3761 3762 3763 3764
            }
        } else {
            if (unlink(autostartLink) < 0 && errno != ENOENT && errno != ENOTDIR) {
                virReportSystemError(errno,
                                     _("Failed to delete symlink '%s'"),
                                     autostartLink);
3765
                goto endjob;
3766 3767 3768 3769 3770 3771 3772
            }
        }

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

3773
 endjob:
3774 3775 3776
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

3777
 cleanup:
3778 3779 3780
    VIR_FREE(configFile);
    VIR_FREE(autostartLink);
    if (vm)
3781
        virObjectUnlock(vm);
3782
    virObjectUnref(cfg);
3783 3784 3785
    return ret;
}

3786 3787 3788 3789 3790 3791
static char *
libxlDomainGetSchedulerType(virDomainPtr dom, int *nparams)
{
    libxlDomainObjPrivatePtr priv;
    virDomainObjPtr vm;
    char * ret = NULL;
3792
    const char *name = NULL;
J
Jim Fehlig 已提交
3793
    libxl_scheduler sched_id;
3794

J
Jim Fehlig 已提交
3795
    if (!(vm = libxlDomObjFromDomain(dom)))
3796 3797
        goto cleanup;

3798 3799 3800
    if (virDomainGetSchedulerTypeEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

3801
    if (!virDomainObjIsActive(vm)) {
3802
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
3803 3804 3805 3806
        goto cleanup;
    }

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

3809 3810
    if (nparams)
        *nparams = 0;
3811
    switch (sched_id) {
J
Jim Fehlig 已提交
3812
    case LIBXL_SCHEDULER_SEDF:
3813
        name = "sedf";
3814
        break;
J
Jim Fehlig 已提交
3815
    case LIBXL_SCHEDULER_CREDIT:
3816
        name = "credit";
3817 3818
        if (nparams)
            *nparams = XEN_SCHED_CREDIT_NPARAM;
3819
        break;
J
Jim Fehlig 已提交
3820
    case LIBXL_SCHEDULER_CREDIT2:
3821
        name = "credit2";
3822
        break;
J
Jim Fehlig 已提交
3823
    case LIBXL_SCHEDULER_ARINC653:
3824
        name = "arinc653";
3825 3826
        break;
    default:
J
Jim Fehlig 已提交
3827 3828
        virReportError(VIR_ERR_INTERNAL_ERROR,
                   _("Failed to get scheduler id for domain '%d'"
3829
                     " with libxenlight"), vm->def->id);
3830 3831 3832
        goto cleanup;
    }

3833
    ignore_value(VIR_STRDUP(ret, name));
3834

3835
 cleanup:
3836
    if (vm)
3837
        virObjectUnlock(vm);
3838 3839 3840
    return ret;
}

3841
static int
3842 3843 3844 3845
libxlDomainGetSchedulerParametersFlags(virDomainPtr dom,
                                       virTypedParameterPtr params,
                                       int *nparams,
                                       unsigned int flags)
3846 3847 3848
{
    libxlDomainObjPrivatePtr priv;
    virDomainObjPtr vm;
J
Jim Fehlig 已提交
3849 3850
    libxl_domain_sched_params sc_info;
    libxl_scheduler sched_id;
3851 3852
    int ret = -1;

3853 3854 3855 3856
    virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);

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

J
Jim Fehlig 已提交
3858
    if (!(vm = libxlDomObjFromDomain(dom)))
3859 3860
        goto cleanup;

3861 3862 3863
    if (virDomainGetSchedulerParametersFlagsEnsureACL(dom->conn, vm->def) < 0)
        goto cleanup;

3864
    if (!virDomainObjIsActive(vm)) {
J
Jim Fehlig 已提交
3865 3866
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("Domain is not running"));
3867 3868 3869 3870 3871
        goto cleanup;
    }

    priv = vm->privateData;

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

J
Jim Fehlig 已提交
3874
    if (sched_id != LIBXL_SCHEDULER_CREDIT) {
3875 3876
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Only 'credit' scheduler is supported"));
3877 3878 3879
        goto cleanup;
    }

3880
    if (libxl_domain_sched_params_get(priv->ctx, vm->def->id, &sc_info) != 0) {
3881 3882
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to get scheduler parameters for domain '%d'"
3883
                         " with libxenlight"), vm->def->id);
3884 3885 3886
        goto cleanup;
    }

3887 3888
    if (virTypedParameterAssign(&params[0], VIR_DOMAIN_SCHEDULER_WEIGHT,
                                VIR_TYPED_PARAM_UINT, sc_info.weight) < 0)
3889 3890
        goto cleanup;

3891
    if (*nparams > 1) {
3892 3893
        if (virTypedParameterAssign(&params[0], VIR_DOMAIN_SCHEDULER_CAP,
                                    VIR_TYPED_PARAM_UINT, sc_info.cap) < 0)
3894
            goto cleanup;
3895 3896
    }

3897 3898
    if (*nparams > XEN_SCHED_CREDIT_NPARAM)
        *nparams = XEN_SCHED_CREDIT_NPARAM;
3899 3900
    ret = 0;

3901
 cleanup:
3902
    if (vm)
3903
        virObjectUnlock(vm);
3904 3905 3906 3907
    return ret;
}

static int
3908 3909 3910 3911 3912 3913 3914 3915 3916 3917 3918
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)
3919
{
3920
    libxlDriverPrivatePtr driver = dom->conn->privateData;
3921 3922
    libxlDomainObjPrivatePtr priv;
    virDomainObjPtr vm;
J
Jim Fehlig 已提交
3923
    libxl_domain_sched_params sc_info;
3924
    int sched_id;
3925
    size_t i;
3926 3927
    int ret = -1;

3928
    virCheckFlags(0, -1);
3929 3930 3931 3932 3933 3934
    if (virTypedParamsValidate(params, nparams,
                               VIR_DOMAIN_SCHEDULER_WEIGHT,
                               VIR_TYPED_PARAM_UINT,
                               VIR_DOMAIN_SCHEDULER_CAP,
                               VIR_TYPED_PARAM_UINT,
                               NULL) < 0)
3935
        return -1;
3936

J
Jim Fehlig 已提交
3937
    if (!(vm = libxlDomObjFromDomain(dom)))
3938 3939
        goto cleanup;

3940 3941 3942
    if (virDomainSetSchedulerParametersFlagsEnsureACL(dom->conn, vm->def, flags) < 0)
        goto cleanup;

3943 3944 3945
    if (libxlDomainObjBeginJob(driver, vm, LIBXL_JOB_MODIFY) < 0)
        goto cleanup;

3946
    if (!virDomainObjIsActive(vm)) {
3947
        virReportError(VIR_ERR_OPERATION_INVALID, "%s", _("Domain is not running"));
3948
        goto endjob;
3949 3950 3951 3952
    }

    priv = vm->privateData;

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

J
Jim Fehlig 已提交
3955
    if (sched_id != LIBXL_SCHEDULER_CREDIT) {
3956 3957
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("Only 'credit' scheduler is supported"));
3958
        goto endjob;
3959 3960
    }

3961
    if (libxl_domain_sched_params_get(priv->ctx, vm->def->id, &sc_info) != 0) {
3962 3963
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to get scheduler parameters for domain '%d'"
3964
                         " with libxenlight"), vm->def->id);
3965
        goto endjob;
3966 3967 3968
    }

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

3971
        if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_WEIGHT))
3972
            sc_info.weight = params[i].value.ui;
3973
        else if (STREQ(param->field, VIR_DOMAIN_SCHEDULER_CAP))
3974 3975 3976
            sc_info.cap = params[i].value.ui;
    }

3977
    if (libxl_domain_sched_params_set(priv->ctx, vm->def->id, &sc_info) != 0) {
3978 3979
        virReportError(VIR_ERR_INTERNAL_ERROR,
                       _("Failed to set scheduler parameters for domain '%d'"
3980
                         " with libxenlight"), vm->def->id);
3981
        goto endjob;
3982 3983 3984 3985
    }

    ret = 0;

3986
 endjob:
3987 3988 3989
    if (!libxlDomainObjEndJob(driver, vm))
        vm = NULL;

3990
 cleanup:
3991
    if (vm)
3992
        virObjectUnlock(vm);
3993 3994 3995
    return ret;
}

B
Bamvor Jian Zhang 已提交
3996 3997 3998 3999 4000 4001 4002 4003 4004 4005 4006 4007 4008 4009 4010 4011 4012 4013 4014 4015 4016

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

    virCheckFlags(VIR_DOMAIN_CONSOLE_FORCE, -1);

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

J
Jim Fehlig 已提交
4017
    if (!(vm = libxlDomObjFromDomain(dom)))
B
Bamvor Jian Zhang 已提交
4018 4019 4020 4021 4022 4023 4024 4025 4026 4027 4028 4029 4030
        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 已提交
4031 4032
    if (vm->def->nconsoles)
        chr = vm->def->consoles[0];
B
Bamvor Jian Zhang 已提交
4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 4048 4049 4050 4051 4052 4053 4054 4055 4056 4057 4058 4059

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

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

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

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

4060
 cleanup:
B
Bamvor Jian Zhang 已提交
4061 4062 4063 4064 4065
    if (vm)
        virObjectUnlock(vm);
    return ret;
}

4066 4067 4068 4069 4070 4071 4072
static int
libxlDomainSetSchedulerParameters(virDomainPtr dom, virTypedParameterPtr params,
                                  int nparams)
{
    return libxlDomainSetSchedulerParametersFlags(dom, params, nparams, 0);
}

4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102
/* 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;

4103 4104
    libxl_bitmap_init(&nodemap);

J
Jim Fehlig 已提交
4105
    if (!(vm = libxlDomObjFromDomain(dom)))
4106 4107 4108 4109 4110 4111 4112 4113 4114 4115 4116 4117 4118 4119 4120 4121 4122 4123 4124 4125 4126
        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];
4127
        int numnodes;
4128 4129 4130 4131 4132 4133 4134 4135 4136 4137 4138 4139 4140 4141 4142 4143 4144 4145

        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 */
4146 4147 4148 4149
            numnodes = libxl_get_max_nodes(priv->ctx);
            if (numnodes <= 0)
                goto cleanup;

J
Ján Tomko 已提交
4150
            if (libxl_node_bitmap_alloc(priv->ctx, &nodemap, 0)) {
4151 4152 4153
                virReportOOMError();
                goto cleanup;
            }
J
Ján Tomko 已提交
4154 4155
            if (!(nodes = virBitmapNew(numnodes)))
                goto cleanup;
4156 4157 4158 4159 4160 4161 4162 4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176

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

4177
            if (!(nodeset = virBitmapFormat(nodes)))
4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 4192 4193
                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;

4194
 cleanup:
4195 4196 4197 4198 4199 4200 4201 4202 4203
    VIR_FREE(nodeset);
    virBitmapFree(nodes);
    libxl_bitmap_dispose(&nodemap);
    if (vm)
        virObjectUnlock(vm);
    return ret;
}
#endif

J
Jim Fehlig 已提交
4204 4205 4206 4207 4208 4209
static int
libxlDomainIsActive(virDomainPtr dom)
{
    virDomainObjPtr obj;
    int ret = -1;

J
Jim Fehlig 已提交
4210
    if (!(obj = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
4211
        goto cleanup;
4212 4213 4214 4215

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

J
Jim Fehlig 已提交
4216 4217
    ret = virDomainObjIsActive(obj);

4218
 cleanup:
J
Jim Fehlig 已提交
4219
    if (obj)
4220
        virObjectUnlock(obj);
J
Jim Fehlig 已提交
4221 4222 4223 4224 4225 4226 4227 4228 4229
    return ret;
}

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

J
Jim Fehlig 已提交
4230
    if (!(obj = libxlDomObjFromDomain(dom)))
J
Jim Fehlig 已提交
4231
        goto cleanup;
4232 4233 4234 4235

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

J
Jim Fehlig 已提交
4236 4237
    ret = obj->persistent;

4238
 cleanup:
J
Jim Fehlig 已提交
4239
    if (obj)
4240
        virObjectUnlock(obj);
J
Jim Fehlig 已提交
4241 4242 4243
    return ret;
}

4244 4245 4246 4247 4248 4249
static int
libxlDomainIsUpdated(virDomainPtr dom)
{
    virDomainObjPtr vm;
    int ret = -1;

J
Jim Fehlig 已提交
4250
    if (!(vm = libxlDomObjFromDomain(dom)))
4251
        goto cleanup;
4252 4253 4254 4255

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

4256 4257
    ret = vm->updated;

4258
 cleanup:
4259
    if (vm)
4260
        virObjectUnlock(vm);
4261 4262 4263
    return ret;
}

4264
static int
4265 4266 4267
libxlConnectDomainEventRegisterAny(virConnectPtr conn, virDomainPtr dom, int eventID,
                                   virConnectDomainEventGenericCallback callback,
                                   void *opaque, virFreeCallback freecb)
4268 4269 4270 4271
{
    libxlDriverPrivatePtr driver = conn->privateData;
    int ret;

4272 4273 4274
    if (virConnectDomainEventRegisterAnyEnsureACL(conn) < 0)
        return -1;

4275 4276 4277 4278
    if (virDomainEventStateRegisterID(conn,
                                      driver->domainEventState,
                                      dom, eventID, callback, opaque,
                                      freecb, &ret) < 0)
4279
        ret = -1;
4280 4281 4282 4283 4284 4285

    return ret;
}


static int
4286
libxlConnectDomainEventDeregisterAny(virConnectPtr conn, int callbackID)
4287 4288 4289
{
    libxlDriverPrivatePtr driver = conn->privateData;

4290 4291 4292
    if (virConnectDomainEventDeregisterAnyEnsureACL(conn) < 0)
        return -1;

4293 4294 4295 4296
    if (virObjectEventStateDeregisterID(conn,
                                        driver->domainEventState,
                                        callbackID) < 0)
        return -1;
4297

4298
    return 0;
4299 4300
}

J
Jim Fehlig 已提交
4301

4302
static int
4303
libxlConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED)
4304 4305 4306 4307
{
    return 1;
}

4308
static int
4309 4310 4311
libxlConnectListAllDomains(virConnectPtr conn,
                           virDomainPtr **domains,
                           unsigned int flags)
4312 4313 4314 4315
{
    libxlDriverPrivatePtr driver = conn->privateData;
    int ret = -1;

O
Osier Yang 已提交
4316
    virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
4317

4318 4319 4320
    if (virConnectListAllDomainsEnsureACL(conn) < 0)
        return -1;

4321 4322
    ret = virDomainObjListExport(driver->domains, conn, domains,
                                 virConnectListAllDomainsCheckACL, flags);
4323 4324 4325 4326

    return ret;
}

4327 4328 4329 4330 4331 4332 4333 4334 4335
/* 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 已提交
4336
    case VIR_DRV_FEATURE_MIGRATION_PARAMS:
4337 4338 4339 4340 4341
        return 1;
    default:
        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
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 已提交
4368
        return -1;
4369 4370
    }

C
Chunyan Liu 已提交
4371
    return 0;
4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383 4384 4385 4386 4387 4388 4389 4390 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
}

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;
4420
 cleanup:
4421 4422 4423 4424 4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437 4438 4439 4440 4441 4442 4443 4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454 4455 4456 4457 4458 4459 4460 4461 4462
    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 已提交
4463
        goto cleanup;
4464 4465

    ret = 0;
C
Chunyan Liu 已提交
4466

4467
 cleanup:
C
Chunyan Liu 已提交
4468
    virPCIDeviceFree(pci);
4469 4470 4471 4472 4473 4474 4475 4476
    virNodeDeviceDefFree(def);
    VIR_FREE(xml);
    return ret;
}

static int
libxlNodeDeviceReset(virNodeDevicePtr dev)
{
C
Chunyan Liu 已提交
4477
    virPCIDevicePtr pci = NULL;
4478 4479 4480 4481 4482 4483 4484 4485 4486 4487 4488 4489 4490 4491 4492 4493 4494 4495 4496 4497 4498 4499 4500 4501 4502 4503
    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 已提交
4504
        goto cleanup;
4505 4506

    ret = 0;
C
Chunyan Liu 已提交
4507

4508
 cleanup:
C
Chunyan Liu 已提交
4509
    virPCIDeviceFree(pci);
4510 4511 4512 4513 4514
    virNodeDeviceDefFree(def);
    VIR_FREE(xml);
    return ret;
}

J
Jim Fehlig 已提交
4515 4516 4517 4518 4519 4520 4521 4522 4523 4524 4525
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;

4526 4527 4528 4529 4530
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
    virReportUnsupportedError();
    return NULL;
#endif

J
Jim Fehlig 已提交
4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 4565 4566 4567 4568 4569 4570 4571 4572 4573 4574
    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;

4575 4576 4577 4578 4579
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
    virReportUnsupportedError();
    return -1;
#endif

J
Jim Fehlig 已提交
4580 4581 4582 4583 4584 4585 4586 4587 4588 4589 4590 4591 4592 4593 4594 4595 4596 4597 4598 4599 4600 4601
    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;

4602
    if (libxlDomainMigrationPrepare(dconn, &def, uri_in, uri_out, flags) < 0)
J
Jim Fehlig 已提交
4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616 4617 4618 4619 4620 4621 4622 4623 4624 4625 4626 4627 4628 4629
        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;

4630 4631 4632 4633 4634
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
    virReportUnsupportedError();
    return -1;
#endif

J
Jim Fehlig 已提交
4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657
    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,
4658
                                    uri, dname, flags) < 0)
J
Jim Fehlig 已提交
4659 4660 4661 4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672 4673 4674 4675 4676 4677 4678 4679 4680 4681 4682
        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;
4683
    virDomainPtr ret = NULL;
J
Jim Fehlig 已提交
4684

4685 4686 4687 4688 4689
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
    virReportUnsupportedError();
    return NULL;
#endif

J
Jim Fehlig 已提交
4690 4691 4692 4693 4694 4695 4696 4697 4698 4699 4700 4701 4702 4703 4704 4705 4706 4707 4708 4709 4710 4711 4712 4713
    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;
    }

4714 4715 4716 4717 4718 4719 4720 4721 4722 4723 4724 4725 4726 4727
    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 已提交
4728 4729 4730 4731 4732 4733 4734 4735 4736 4737 4738 4739 4740 4741
}

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;

4742 4743 4744 4745 4746
#ifdef LIBXL_HAVE_NO_SUSPEND_RESUME
    virReportUnsupportedError();
    return -1;
#endif

J
Jim Fehlig 已提交
4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761
    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);
}

4762

4763
static virHypervisorDriver libxlHypervisorDriver = {
4764
    .name = LIBXL_DRIVER_NAME,
4765 4766 4767 4768
    .connectOpen = libxlConnectOpen, /* 0.9.0 */
    .connectClose = libxlConnectClose, /* 0.9.0 */
    .connectGetType = libxlConnectGetType, /* 0.9.0 */
    .connectGetVersion = libxlConnectGetVersion, /* 0.9.0 */
4769
    .connectGetHostname = libxlConnectGetHostname, /* 0.9.0 */
4770
    .connectGetSysinfo = libxlConnectGetSysinfo, /* 1.1.0 */
4771
    .connectGetMaxVcpus = libxlConnectGetMaxVcpus, /* 0.9.0 */
4772
    .nodeGetInfo = libxlNodeGetInfo, /* 0.9.0 */
4773 4774 4775 4776
    .connectGetCapabilities = libxlConnectGetCapabilities, /* 0.9.0 */
    .connectListDomains = libxlConnectListDomains, /* 0.9.0 */
    .connectNumOfDomains = libxlConnectNumOfDomains, /* 0.9.0 */
    .connectListAllDomains = libxlConnectListAllDomains, /* 0.9.13 */
4777 4778 4779 4780 4781 4782 4783
    .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 */
4784
    .domainShutdownFlags = libxlDomainShutdownFlags, /* 0.9.10 */
4785 4786
    .domainReboot = libxlDomainReboot, /* 0.9.0 */
    .domainDestroy = libxlDomainDestroy, /* 0.9.0 */
4787
    .domainDestroyFlags = libxlDomainDestroyFlags, /* 0.9.4 */
4788 4789
    .domainGetOSType = libxlDomainGetOSType, /* 0.9.0 */
    .domainGetMaxMemory = libxlDomainGetMaxMemory, /* 0.9.0 */
4790
    .domainSetMaxMemory = libxlDomainSetMaxMemory, /* 0.9.2 */
4791 4792 4793 4794
    .domainSetMemory = libxlDomainSetMemory, /* 0.9.0 */
    .domainSetMemoryFlags = libxlDomainSetMemoryFlags, /* 0.9.0 */
    .domainGetInfo = libxlDomainGetInfo, /* 0.9.0 */
    .domainGetState = libxlDomainGetState, /* 0.9.2 */
4795
    .domainSave = libxlDomainSave, /* 0.9.2 */
4796
    .domainSaveFlags = libxlDomainSaveFlags, /* 0.9.4 */
4797
    .domainRestore = libxlDomainRestore, /* 0.9.2 */
4798
    .domainRestoreFlags = libxlDomainRestoreFlags, /* 0.9.4 */
4799
    .domainCoreDump = libxlDomainCoreDump, /* 0.9.2 */
4800 4801 4802 4803
    .domainSetVcpus = libxlDomainSetVcpus, /* 0.9.0 */
    .domainSetVcpusFlags = libxlDomainSetVcpusFlags, /* 0.9.0 */
    .domainGetVcpusFlags = libxlDomainGetVcpusFlags, /* 0.9.0 */
    .domainPinVcpu = libxlDomainPinVcpu, /* 0.9.0 */
4804
    .domainPinVcpuFlags = libxlDomainPinVcpuFlags, /* 1.2.1 */
4805
    .domainGetVcpus = libxlDomainGetVcpus, /* 0.9.0 */
4806
    .domainGetVcpuPinInfo = libxlDomainGetVcpuPinInfo, /* 1.2.1 */
4807
    .domainGetXMLDesc = libxlDomainGetXMLDesc, /* 0.9.0 */
4808 4809 4810 4811
    .connectDomainXMLFromNative = libxlConnectDomainXMLFromNative, /* 0.9.0 */
    .connectDomainXMLToNative = libxlConnectDomainXMLToNative, /* 0.9.0 */
    .connectListDefinedDomains = libxlConnectListDefinedDomains, /* 0.9.0 */
    .connectNumOfDefinedDomains = libxlConnectNumOfDefinedDomains, /* 0.9.0 */
4812 4813 4814
    .domainCreate = libxlDomainCreate, /* 0.9.0 */
    .domainCreateWithFlags = libxlDomainCreateWithFlags, /* 0.9.0 */
    .domainDefineXML = libxlDomainDefineXML, /* 0.9.0 */
4815
    .domainDefineXMLFlags = libxlDomainDefineXMLFlags, /* 1.2.12 */
4816
    .domainUndefine = libxlDomainUndefine, /* 0.9.0 */
4817
    .domainUndefineFlags = libxlDomainUndefineFlags, /* 0.9.4 */
4818 4819 4820 4821 4822
    .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 */
4823 4824 4825 4826
    .domainGetAutostart = libxlDomainGetAutostart, /* 0.9.0 */
    .domainSetAutostart = libxlDomainSetAutostart, /* 0.9.0 */
    .domainGetSchedulerType = libxlDomainGetSchedulerType, /* 0.9.0 */
    .domainGetSchedulerParameters = libxlDomainGetSchedulerParameters, /* 0.9.0 */
4827
    .domainGetSchedulerParametersFlags = libxlDomainGetSchedulerParametersFlags, /* 0.9.2 */
4828
    .domainSetSchedulerParameters = libxlDomainSetSchedulerParameters, /* 0.9.0 */
4829
    .domainSetSchedulerParametersFlags = libxlDomainSetSchedulerParametersFlags, /* 0.9.2 */
4830 4831 4832
#ifdef LIBXL_HAVE_DOMAIN_NODEAFFINITY
    .domainGetNumaParameters = libxlDomainGetNumaParameters, /* 1.1.1 */
#endif
4833
    .nodeGetFreeMemory = libxlNodeGetFreeMemory, /* 0.9.0 */
4834
    .nodeGetCellsFreeMemory = libxlNodeGetCellsFreeMemory, /* 1.1.1 */
4835 4836
    .connectDomainEventRegister = libxlConnectDomainEventRegister, /* 0.9.0 */
    .connectDomainEventDeregister = libxlConnectDomainEventDeregister, /* 0.9.0 */
4837 4838 4839
    .domainManagedSave = libxlDomainManagedSave, /* 0.9.2 */
    .domainHasManagedSaveImage = libxlDomainHasManagedSaveImage, /* 0.9.2 */
    .domainManagedSaveRemove = libxlDomainManagedSaveRemove, /* 0.9.2 */
B
Bamvor Jian Zhang 已提交
4840
    .domainOpenConsole = libxlDomainOpenConsole, /* 1.1.2 */
4841 4842 4843
    .domainIsActive = libxlDomainIsActive, /* 0.9.0 */
    .domainIsPersistent = libxlDomainIsPersistent, /* 0.9.0 */
    .domainIsUpdated = libxlDomainIsUpdated, /* 0.9.0 */
4844 4845 4846
    .connectDomainEventRegisterAny = libxlConnectDomainEventRegisterAny, /* 0.9.0 */
    .connectDomainEventDeregisterAny = libxlConnectDomainEventDeregisterAny, /* 0.9.0 */
    .connectIsAlive = libxlConnectIsAlive, /* 0.9.8 */
4847
    .connectSupportsFeature = libxlConnectSupportsFeature, /* 1.1.1 */
4848 4849 4850 4851
    .nodeDeviceDettach = libxlNodeDeviceDettach, /* 1.2.3 */
    .nodeDeviceDetachFlags = libxlNodeDeviceDetachFlags, /* 1.2.3 */
    .nodeDeviceReAttach = libxlNodeDeviceReAttach, /* 1.2.3 */
    .nodeDeviceReset = libxlNodeDeviceReset, /* 1.2.3 */
4852 4853 4854 4855 4856
    .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 已提交
4857 4858
};

4859 4860 4861 4862
static virConnectDriver libxlConnectDriver = {
    .hypervisorDriver = &libxlHypervisorDriver,
};

J
Jim Fehlig 已提交
4863 4864
static virStateDriver libxlStateDriver = {
    .name = "LIBXL",
4865
    .stateInitialize = libxlStateInitialize,
4866
    .stateAutoStart = libxlStateAutoStart,
4867 4868
    .stateCleanup = libxlStateCleanup,
    .stateReload = libxlStateReload,
J
Jim Fehlig 已提交
4869 4870 4871 4872 4873 4874
};


int
libxlRegister(void)
{
4875 4876
    if (virRegisterConnectDriver(&libxlConnectDriver,
                                 true) < 0)
J
Jim Fehlig 已提交
4877 4878 4879 4880 4881 4882
        return -1;
    if (virRegisterStateDriver(&libxlStateDriver) < 0)
        return -1;

    return 0;
}