You need to sign in or sign up before continuing.
vz_driver.c 38.0 KB
Newer Older
D
Dmitry Guryanov 已提交
1
/*
2
 * vz_driver.c: core driver functions for managing
D
Dmitry Guryanov 已提交
3 4
 * Parallels Cloud Server hosts
 *
5
 * Copyright (C) 2014-2015 Red Hat, Inc.
D
Dmitry Guryanov 已提交
6 7 8 9 10 11 12 13 14 15 16 17 18
 * Copyright (C) 2012 Parallels, Inc.
 *
 * 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
D
Dmitry Guryanov 已提交
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
 * <http://www.gnu.org/licenses/>.
 *
 */

#include <config.h>

#include <sys/types.h>
#include <sys/poll.h>
#include <limits.h>
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <paths.h>
#include <pwd.h>
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/statvfs.h>

#include "datatypes.h"
44
#include "virerror.h"
45
#include "viralloc.h"
46
#include "virlog.h"
47
#include "vircommand.h"
D
Dmitry Guryanov 已提交
48
#include "configmake.h"
49
#include "virfile.h"
50
#include "virstoragefile.h"
D
Dmitry Guryanov 已提交
51
#include "nodeinfo.h"
52
#include "virstring.h"
53
#include "cpu/cpu.h"
54
#include "virtypedparam.h"
D
Dmitry Guryanov 已提交
55

56 57 58
#include "vz_driver.h"
#include "vz_utils.h"
#include "vz_sdk.h"
D
Dmitry Guryanov 已提交
59 60 61

#define VIR_FROM_THIS VIR_FROM_PARALLELS

62 63
VIR_LOG_INIT("parallels.parallels_driver");

D
Dmitry Guryanov 已提交
64
#define PRLCTL                      "prlctl"
65
#define PRLSRVCTL                   "prlsrvctl"
D
Dmitry Guryanov 已提交
66

67
static int vzConnectClose(virConnectPtr conn);
D
Dmitry Guryanov 已提交
68

D
Dmitry Guryanov 已提交
69
void
70
vzDriverLock(vzConnPtr driver)
D
Dmitry Guryanov 已提交
71 72 73 74
{
    virMutexLock(&driver->lock);
}

D
Dmitry Guryanov 已提交
75
void
76
vzDriverUnlock(vzConnPtr driver)
D
Dmitry Guryanov 已提交
77 78 79 80
{
    virMutexUnlock(&driver->lock);
}

D
Dmitry Guryanov 已提交
81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
static int
vzCapsAddGuestDomain(virCapsPtr caps,
                     virDomainOSType ostype,
                     virArch arch,
                     const char * emulator,
                     virDomainVirtType virt_type)
{
    virCapsGuestPtr guest;

    if ((guest = virCapabilitiesAddGuest(caps, ostype, arch, emulator,
                                         NULL, 0, NULL)) == NULL)
        return -1;


    if (virCapabilitiesAddGuestDomain(guest, virt_type,
                                      NULL, NULL, 0, NULL) == NULL)
        return -1;

    return 0;
}

D
Dmitry Guryanov 已提交
102
static virCapsPtr
103
vzBuildCapabilities(void)
D
Dmitry Guryanov 已提交
104
{
105 106 107 108
    virCapsPtr caps = NULL;
    virCPUDefPtr cpu = NULL;
    virCPUDataPtr data = NULL;
    virNodeInfo nodeinfo;
D
Dmitry Guryanov 已提交
109 110 111 112 113 114 115 116 117 118 119
    virDomainOSType ostypes[] = {
        VIR_DOMAIN_OSTYPE_HVM,
        VIR_DOMAIN_OSTYPE_EXE
    };
    virArch archs[] = { VIR_ARCH_I686, VIR_ARCH_X86_64 };
    const char *const emulators[] = { "parallels", "vz" };
    virDomainVirtType virt_types[] = {
        VIR_DOMAIN_VIRT_PARALLELS,
        VIR_DOMAIN_VIRT_VZ
    };
    size_t i, j, k;
D
Dmitry Guryanov 已提交
120

121
    if ((caps = virCapabilitiesNew(virArchFromHost(),
122
                                   false, false)) == NULL)
123
        return NULL;
D
Dmitry Guryanov 已提交
124

125
    if (nodeCapsInitNUMA(NULL, caps) < 0)
126
        goto error;
D
Dmitry Guryanov 已提交
127

D
Dmitry Guryanov 已提交
128 129 130 131 132 133
    for (i = 0; i < 2; i++)
        for (j = 0; j < 2; j++)
            for (k = 0; k < 2; k++)
                if (vzCapsAddGuestDomain(caps, ostypes[i], archs[j],
                                         emulators[k], virt_types[k]) < 0)
                    goto error;
134

135
    if (nodeGetInfo(NULL, &nodeinfo))
136 137
        goto error;

138
    if (VIR_ALLOC(cpu) < 0)
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
        goto error;

    cpu->arch = caps->host.arch;
    cpu->type = VIR_CPU_TYPE_HOST;
    cpu->sockets = nodeinfo.sockets;
    cpu->cores = nodeinfo.cores;
    cpu->threads = nodeinfo.threads;

    caps->host.cpu = cpu;

    if (!(data = cpuNodeData(cpu->arch))
        || cpuDecode(cpu, data, NULL, 0, NULL) < 0) {
        goto cleanup;
    }

 cleanup:
    cpuDataFree(data);
D
Dmitry Guryanov 已提交
156 157
    return caps;

158
 error:
159
    virObjectUnref(caps);
160
    goto cleanup;
D
Dmitry Guryanov 已提交
161 162 163
}

static char *
164
vzConnectGetCapabilities(virConnectPtr conn)
D
Dmitry Guryanov 已提交
165
{
166
    vzConnPtr privconn = conn->privateData;
D
Dmitry Guryanov 已提交
167 168
    char *xml;

169
    vzDriverLock(privconn);
170
    xml = virCapabilitiesFormatXML(privconn->caps);
171
    vzDriverUnlock(privconn);
D
Dmitry Guryanov 已提交
172 173 174
    return xml;
}

175
static int
176
vzDomainDefPostParse(virDomainDefPtr def,
M
Michal Privoznik 已提交
177 178
                     virCapsPtr caps ATTRIBUTE_UNUSED,
                     void *opaque ATTRIBUTE_UNUSED)
179
{
180 181 182 183
    /* memory hotplug tunables are not supported by this driver */
    if (virDomainDefCheckUnsupportedMemoryHotplug(def) < 0)
        return -1;

184 185 186 187
    return 0;
}

static int
188
vzDomainDeviceDefPostParse(virDomainDeviceDefPtr dev,
M
Michal Privoznik 已提交
189 190 191
                           const virDomainDef *def,
                           virCapsPtr caps ATTRIBUTE_UNUSED,
                           void *opaque ATTRIBUTE_UNUSED)
192
{
193 194 195 196 197 198
    int ret = -1;

    if (dev->type == VIR_DOMAIN_DEVICE_NET &&
        (dev->data.net->type == VIR_DOMAIN_NET_TYPE_NETWORK ||
         dev->data.net->type == VIR_DOMAIN_NET_TYPE_BRIDGE) &&
        !dev->data.net->model &&
199
        def->os.type == VIR_DOMAIN_OSTYPE_HVM &&
200 201 202 203 204 205
        VIR_STRDUP(dev->data.net->model, "e1000") < 0)
        goto cleanup;

    ret = 0;
 cleanup:
    return ret;
206 207 208
}


209
virDomainDefParserConfig vzDomainDefParserConfig = {
210
    .macPrefix = {0x42, 0x1C, 0x00},
211 212
    .devicesPostParseCallback = vzDomainDeviceDefPostParse,
    .domainPostParseCallback = vzDomainDefPostParse,
213 214 215
};


D
Dmitry Guryanov 已提交
216
static int
217
vzOpenDefault(virConnectPtr conn)
D
Dmitry Guryanov 已提交
218
{
219
    vzConnPtr privconn;
D
Dmitry Guryanov 已提交
220

221
    if (VIR_ALLOC(privconn) < 0)
D
Dmitry Guryanov 已提交
222 223 224 225
        return VIR_DRV_OPEN_ERROR;
    if (virMutexInit(&privconn->lock) < 0) {
        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                       _("cannot initialize mutex"));
226 227 228
        goto err_free;
    }

229 230
    privconn->drivername = conn->driver->name;

231
    if (prlsdkInit()) {
232 233
        VIR_DEBUG("%s", _("Can't initialize Parallels SDK"));
        goto err_free;
D
Dmitry Guryanov 已提交
234 235
    }

236 237 238
    if (prlsdkConnect(privconn) < 0)
        goto err_free;

239
    if (!(privconn->caps = vzBuildCapabilities()))
D
Dmitry Guryanov 已提交
240 241
        goto error;

242
    if (!(privconn->xmlopt = virDomainXMLOptionNew(&vzDomainDefParserConfig,
M
Michal Privoznik 已提交
243
                                                   NULL, NULL)))
244 245
        goto error;

246
    if (!(privconn->domains = virDomainObjListNew()))
D
Dmitry Guryanov 已提交
247 248
        goto error;

249 250 251 252 253 254
    if (!(privconn->domainEventState = virObjectEventStateNew()))
        goto error;

    if (prlsdkSubscribeToPCSEvents(privconn))
        goto error;

D
Dmitry Guryanov 已提交
255 256
    conn->privateData = privconn;

257
    if (prlsdkLoadDomains(privconn))
258 259
        goto error;

D
Dmitry Guryanov 已提交
260 261
    return VIR_DRV_OPEN_SUCCESS;

262
 error:
263
    virObjectUnref(privconn->domains);
264
    virObjectUnref(privconn->caps);
D
Dmitry Guryanov 已提交
265
    virStoragePoolObjListFree(&privconn->pools);
266
    virObjectEventStateFree(privconn->domainEventState);
267 268 269
    prlsdkDisconnect(privconn);
    prlsdkDeinit();
 err_free:
D
Dmitry Guryanov 已提交
270 271 272 273 274
    VIR_FREE(privconn);
    return VIR_DRV_OPEN_ERROR;
}

static virDrvOpenStatus
275
vzConnectOpen(virConnectPtr conn,
M
Michal Privoznik 已提交
276 277
              virConnectAuthPtr auth ATTRIBUTE_UNUSED,
              unsigned int flags)
D
Dmitry Guryanov 已提交
278 279 280 281 282 283 284 285
{
    int ret;

    virCheckFlags(VIR_CONNECT_RO, VIR_DRV_OPEN_ERROR);

    if (!conn->uri)
        return VIR_DRV_OPEN_DECLINED;

286 287 288 289 290 291 292 293 294 295 296
    if (!conn->uri->scheme)
        return VIR_DRV_OPEN_DECLINED;

    if (STRNEQ(conn->uri->scheme, "vz") &&
        STRNEQ(conn->uri->scheme, "parallels"))
        return VIR_DRV_OPEN_DECLINED;

    if (STREQ(conn->uri->scheme, "vz") && STRNEQ(conn->driver->name, "vz"))
        return VIR_DRV_OPEN_DECLINED;

    if (STREQ(conn->uri->scheme, "parallels") && STRNEQ(conn->driver->name, "Parallels"))
D
Dmitry Guryanov 已提交
297 298 299 300 301 302 303
        return VIR_DRV_OPEN_DECLINED;

    /* Remote driver should handle these. */
    if (conn->uri->server)
        return VIR_DRV_OPEN_DECLINED;

    /* From this point on, the connection is for us. */
304 305
    if (!STREQ_NULLABLE(conn->uri->path, "/system")) {
        virReportError(VIR_ERR_INTERNAL_ERROR,
306
                       _("Unexpected Virtuozzo URI path '%s', try vz:///system"),
307
                       conn->uri->path);
D
Dmitry Guryanov 已提交
308 309 310
        return VIR_DRV_OPEN_ERROR;
    }

311
    if ((ret = vzOpenDefault(conn)) != VIR_DRV_OPEN_SUCCESS ||
312
        (ret = vzStorageOpen(conn, flags)) != VIR_DRV_OPEN_SUCCESS) {
313
        vzConnectClose(conn);
D
Dmitry Guryanov 已提交
314
        return ret;
315
    }
D
Dmitry Guryanov 已提交
316 317 318 319 320

    return VIR_DRV_OPEN_SUCCESS;
}

static int
321
vzConnectClose(virConnectPtr conn)
D
Dmitry Guryanov 已提交
322
{
323
    vzConnPtr privconn = conn->privateData;
D
Dmitry Guryanov 已提交
324

325 326 327
    if (!privconn)
        return 0;

328
    vzStorageClose(conn);
329

330
    vzDriverLock(privconn);
331
    prlsdkUnsubscribeFromPCSEvents(privconn);
332
    virObjectUnref(privconn->caps);
333
    virObjectUnref(privconn->xmlopt);
334
    virObjectUnref(privconn->domains);
335
    virObjectEventStateFree(privconn->domainEventState);
336
    prlsdkDisconnect(privconn);
D
Dmitry Guryanov 已提交
337
    conn->privateData = NULL;
338
    prlsdkDeinit();
D
Dmitry Guryanov 已提交
339

340
    vzDriverUnlock(privconn);
D
Dmitry Guryanov 已提交
341 342 343 344 345 346 347
    virMutexDestroy(&privconn->lock);

    VIR_FREE(privconn);
    return 0;
}

static int
348
vzConnectGetVersion(virConnectPtr conn ATTRIBUTE_UNUSED, unsigned long *hvVer)
D
Dmitry Guryanov 已提交
349
{
350 351 352 353
    char *output, *sVer, *tmp;
    const char *searchStr = "prlsrvctl version ";
    int ret = -1;

354
    output = vzGetOutput(PRLSRVCTL, "--help", NULL);
355 356

    if (!output) {
357
        vzParseError();
358 359 360 361
        goto cleanup;
    }

    if (!(sVer = strstr(output, searchStr))) {
362
        vzParseError();
363 364 365 366 367 368 369 370
        goto cleanup;
    }

    sVer = sVer + strlen(searchStr);

    /* parallels server has versions number like 6.0.17977.782218,
     * so libvirt can handle only first two numbers. */
    if (!(tmp = strchr(sVer, '.'))) {
371
        vzParseError();
372 373 374 375
        goto cleanup;
    }

    if (!(tmp = strchr(tmp + 1, '.'))) {
376
        vzParseError();
377 378 379 380 381
        goto cleanup;
    }

    tmp[0] = '\0';
    if (virParseVersionString(sVer, hvVer, true) < 0) {
382
        vzParseError();
383 384 385 386 387
        goto cleanup;
    }

    ret = 0;

388
 cleanup:
389 390 391 392
    VIR_FREE(output);
    return ret;
}

393

394
static char *vzConnectGetHostname(virConnectPtr conn ATTRIBUTE_UNUSED)
395 396 397 398 399
{
    return virGetHostname();
}


400
static int
401
vzConnectListDomains(virConnectPtr conn, int *ids, int maxids)
402
{
403
    vzConnPtr privconn = conn->privateData;
404 405
    int n;

406
    vzDriverLock(privconn);
407 408
    n = virDomainObjListGetActiveIDs(privconn->domains, ids, maxids,
                                     NULL, NULL);
409
    vzDriverUnlock(privconn);
410 411 412 413 414

    return n;
}

static int
415
vzConnectNumOfDomains(virConnectPtr conn)
416
{
417
    vzConnPtr privconn = conn->privateData;
418 419
    int count;

420
    vzDriverLock(privconn);
421 422
    count = virDomainObjListNumOfDomains(privconn->domains, true,
                                         NULL, NULL);
423
    vzDriverUnlock(privconn);
424 425 426 427 428

    return count;
}

static int
429
vzConnectListDefinedDomains(virConnectPtr conn, char **const names, int maxnames)
430
{
431
    vzConnPtr privconn = conn->privateData;
432 433
    int n;

434
    vzDriverLock(privconn);
435
    memset(names, 0, sizeof(*names) * maxnames);
436
    n = virDomainObjListGetInactiveNames(privconn->domains, names,
437
                                         maxnames, NULL, NULL);
438
    vzDriverUnlock(privconn);
439 440 441 442 443

    return n;
}

static int
444
vzConnectNumOfDefinedDomains(virConnectPtr conn)
445
{
446
    vzConnPtr privconn = conn->privateData;
447 448
    int count;

449
    vzDriverLock(privconn);
450 451
    count = virDomainObjListNumOfDomains(privconn->domains, false,
                                         NULL, NULL);
452
    vzDriverUnlock(privconn);
453 454 455 456 457

    return count;
}

static int
458
vzConnectListAllDomains(virConnectPtr conn,
M
Michal Privoznik 已提交
459 460
                        virDomainPtr **domains,
                        unsigned int flags)
461
{
462
    vzConnPtr privconn = conn->privateData;
463 464
    int ret = -1;

O
Osier Yang 已提交
465
    virCheckFlags(VIR_CONNECT_LIST_DOMAINS_FILTERS_ALL, -1);
466
    vzDriverLock(privconn);
467 468
    ret = virDomainObjListExport(privconn->domains, conn, domains,
                                 NULL, flags);
469
    vzDriverUnlock(privconn);
470 471 472 473 474

    return ret;
}

static virDomainPtr
475
vzDomainLookupByID(virConnectPtr conn, int id)
476
{
477
    vzConnPtr privconn = conn->privateData;
478 479 480
    virDomainPtr ret = NULL;
    virDomainObjPtr dom;

481
    vzDriverLock(privconn);
482
    dom = virDomainObjListFindByID(privconn->domains, id);
483
    vzDriverUnlock(privconn);
484 485 486 487 488 489 490 491 492 493

    if (dom == NULL) {
        virReportError(VIR_ERR_NO_DOMAIN, NULL);
        goto cleanup;
    }

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

494
 cleanup:
495
    if (dom)
496
        virObjectUnlock(dom);
497 498 499 500
    return ret;
}

static virDomainPtr
501
vzDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid)
502
{
503
    vzConnPtr privconn = conn->privateData;
504 505 506
    virDomainPtr ret = NULL;
    virDomainObjPtr dom;

507
    vzDriverLock(privconn);
508
    dom = virDomainObjListFindByUUID(privconn->domains, uuid);
509
    vzDriverUnlock(privconn);
510 511 512 513 514 515 516 517 518 519 520 521 522

    if (dom == NULL) {
        char uuidstr[VIR_UUID_STRING_BUFLEN];
        virUUIDFormat(uuid, uuidstr);
        virReportError(VIR_ERR_NO_DOMAIN,
                       _("no domain with matching uuid '%s'"), uuidstr);
        goto cleanup;
    }

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

523
 cleanup:
524
    if (dom)
525
        virObjectUnlock(dom);
526 527 528 529
    return ret;
}

static virDomainPtr
530
vzDomainLookupByName(virConnectPtr conn, const char *name)
531
{
532
    vzConnPtr privconn = conn->privateData;
533 534 535
    virDomainPtr ret = NULL;
    virDomainObjPtr dom;

536
    vzDriverLock(privconn);
537
    dom = virDomainObjListFindByName(privconn->domains, name);
538
    vzDriverUnlock(privconn);
539 540 541 542 543 544 545 546 547 548 549

    if (dom == NULL) {
        virReportError(VIR_ERR_NO_DOMAIN,
                       _("no domain with matching name '%s'"), name);
        goto cleanup;
    }

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

550
 cleanup:
551
    virDomainObjEndAPI(&dom);
552 553 554 555
    return ret;
}

static int
556
vzDomainGetInfo(virDomainPtr domain, virDomainInfoPtr info)
557 558 559 560
{
    virDomainObjPtr privdom;
    int ret = -1;

561
    if (!(privdom = vzDomObjFromDomain(domain)))
562 563 564 565
        goto cleanup;

    info->state = virDomainObjGetState(privdom, NULL);
    info->memory = privdom->def->mem.cur_balloon;
566
    info->maxMem = virDomainDefGetMemoryActual(privdom->def);
567 568 569 570
    info->nrVirtCpu = privdom->def->vcpus;
    info->cpuTime = 0;
    ret = 0;

571
 cleanup:
572
    if (privdom)
573
        virObjectUnlock(privdom);
574 575 576 577
    return ret;
}

static char *
578
vzDomainGetOSType(virDomainPtr domain)
579 580 581 582 583
{
    virDomainObjPtr privdom;

    char *ret = NULL;

584
    if (!(privdom = vzDomObjFromDomain(domain)))
585 586
        goto cleanup;

587
    ignore_value(VIR_STRDUP(ret, virDomainOSTypeToString(privdom->def->os.type)));
588

589
 cleanup:
590
    if (privdom)
591
        virObjectUnlock(privdom);
592 593 594 595
    return ret;
}

static int
596
vzDomainIsPersistent(virDomainPtr domain)
597 598 599 600
{
    virDomainObjPtr privdom;
    int ret = -1;

601
    if (!(privdom = vzDomObjFromDomain(domain)))
602 603 604 605
        goto cleanup;

    ret = 1;

606
 cleanup:
607
    if (privdom)
608
        virObjectUnlock(privdom);
609 610 611 612
    return ret;
}

static int
613
vzDomainGetState(virDomainPtr domain,
M
Michal Privoznik 已提交
614
                 int *state, int *reason, unsigned int flags)
615 616 617 618 619
{
    virDomainObjPtr privdom;
    int ret = -1;
    virCheckFlags(0, -1);

620
    if (!(privdom = vzDomObjFromDomain(domain)))
621 622 623 624 625
        goto cleanup;

    *state = virDomainObjGetState(privdom, reason);
    ret = 0;

626
 cleanup:
627
    if (privdom)
628
        virObjectUnlock(privdom);
629 630 631 632
    return ret;
}

static char *
633
vzDomainGetXMLDesc(virDomainPtr domain, unsigned int flags)
634 635 636 637 638 639 640
{
    virDomainDefPtr def;
    virDomainObjPtr privdom;
    char *ret = NULL;

    /* Flags checked by virDomainDefFormat */

641
    if (!(privdom = vzDomObjFromDomain(domain)))
642 643 644 645 646 647 648
        goto cleanup;

    def = (flags & VIR_DOMAIN_XML_INACTIVE) &&
        privdom->newDef ? privdom->newDef : privdom->def;

    ret = virDomainDefFormat(def, flags);

649
 cleanup:
650
    if (privdom)
651
        virObjectUnlock(privdom);
652 653 654 655
    return ret;
}

static int
656
vzDomainGetAutostart(virDomainPtr domain, int *autostart)
657 658 659 660
{
    virDomainObjPtr privdom;
    int ret = -1;

661
    if (!(privdom = vzDomObjFromDomain(domain)))
662 663 664 665 666
        goto cleanup;

    *autostart = privdom->autostart;
    ret = 0;

667
 cleanup:
668
    if (privdom)
669
        virObjectUnlock(privdom);
670
    return ret;
D
Dmitry Guryanov 已提交
671 672
}

673
static virDomainPtr
674
vzDomainDefineXMLFlags(virConnectPtr conn, const char *xml, unsigned int flags)
675
{
676
    vzConnPtr privconn = conn->privateData;
677
    virDomainPtr retdom = NULL;
678
    virDomainDefPtr def;
679
    virDomainObjPtr olddom = NULL;
680
    unsigned int parse_flags = VIR_DOMAIN_DEF_PARSE_INACTIVE;
681

682 683 684 685
    virCheckFlags(VIR_DOMAIN_DEFINE_VALIDATE, NULL);

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

687
    vzDriverLock(privconn);
688
    if ((def = virDomainDefParseString(xml, privconn->caps, privconn->xmlopt,
689
                                       parse_flags)) == NULL)
690 691
        goto cleanup;

692 693 694
    olddom = virDomainObjListFindByUUID(privconn->domains, def->uuid);
    if (olddom == NULL) {
        virResetLastError();
695
        if (def->os.type == VIR_DOMAIN_OSTYPE_HVM) {
696
            if (prlsdkCreateVm(conn, def))
697
                goto cleanup;
698
        } else if (def->os.type == VIR_DOMAIN_OSTYPE_EXE) {
699
            if (prlsdkCreateCt(conn, def))
700 701 702
                goto cleanup;
        } else {
            virReportError(VIR_ERR_INVALID_ARG,
703 704
                           _("Unsupported OS type: %s"),
                           virDomainOSTypeToString(def->os.type));
705
            goto cleanup;
706
        }
707 708 709

        olddom = prlsdkAddDomain(privconn, def->uuid);
        if (!olddom)
710
            goto cleanup;
711
    } else {
712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736
        int state, reason;

        state = virDomainObjGetState(olddom, &reason);

        if (state == VIR_DOMAIN_SHUTOFF &&
            reason == VIR_DOMAIN_SHUTOFF_SAVED) {

            /* PCS doesn't store domain config in managed save state file.
             * It's forbidden to change config for VMs in this state.
             * It's possible to change config for containers, but after
             * restoring domain will have that new config, not a config,
             * which domain had at the moment of virDomainManagedSave.
             *
             * So forbid this operation, if config is changed. If it's
             * not changed - just do nothing. */

            if (!virDomainDefCheckABIStability(olddom->def, def)) {
                virReportError(VIR_ERR_ARGUMENT_UNSUPPORTED, "%s",
                               _("Can't change domain configuration "
                                 "in managed save state"));
                goto cleanup;
            }
        } else {
            if (prlsdkApplyConfig(conn, olddom, def))
                goto cleanup;
737

738 739 740
            if (prlsdkUpdateDomain(privconn, olddom))
                goto cleanup;
        }
741 742
    }

743 744 745
    retdom = virGetDomain(conn, def->name, def->uuid);
    if (retdom)
        retdom->id = def->id;
746

747
 cleanup:
748 749
    if (olddom)
        virObjectUnlock(olddom);
750
    virDomainDefFree(def);
751
    vzDriverUnlock(privconn);
752
    return retdom;
753 754
}

755
static virDomainPtr
756
vzDomainDefineXML(virConnectPtr conn, const char *xml)
757
{
758
    return vzDomainDefineXMLFlags(conn, xml, 0);
759 760 761
}


762
static int
763
vzNodeGetInfo(virConnectPtr conn ATTRIBUTE_UNUSED,
M
Michal Privoznik 已提交
764
              virNodeInfoPtr nodeinfo)
765
{
766
    return nodeGetInfo(NULL, nodeinfo);
767 768
}

769
static int vzConnectIsEncrypted(virConnectPtr conn ATTRIBUTE_UNUSED)
770 771 772 773 774
{
    /* Encryption is not relevant / applicable to way we talk to PCS */
    return 0;
}

775
static int vzConnectIsSecure(virConnectPtr conn ATTRIBUTE_UNUSED)
776 777 778 779 780
{
    /* We run CLI tools directly so this is secure */
    return 1;
}

781
static int vzConnectIsAlive(virConnectPtr conn ATTRIBUTE_UNUSED)
782 783 784 785
{
    return 1;
}

786

787
static char *
788
vzConnectBaselineCPU(virConnectPtr conn ATTRIBUTE_UNUSED,
M
Michal Privoznik 已提交
789 790 791
                     const char **xmlCPUs,
                     unsigned int ncpus,
                     unsigned int flags)
792 793 794 795 796 797 798
{
    virCheckFlags(VIR_CONNECT_BASELINE_CPU_EXPAND_FEATURES, NULL);

    return cpuBaselineXML(xmlCPUs, ncpus, NULL, 0, flags);
}


799
static int
800
vzDomainGetVcpus(virDomainPtr domain,
M
Michal Privoznik 已提交
801 802 803 804
                 virVcpuInfoPtr info,
                 int maxinfo,
                 unsigned char *cpumaps,
                 int maplen)
805 806 807 808 809
{
    virDomainObjPtr privdom = NULL;
    size_t i;
    int ret = -1;

N
Nikolay Shirokovskiy 已提交
810
    if (!(privdom = vzDomObjFromDomainRef(domain)))
811 812 813 814 815 816 817 818 819 820 821 822 823 824 825
        goto cleanup;

    if (!virDomainObjIsActive(privdom)) {
        virReportError(VIR_ERR_OPERATION_INVALID,
                       "%s",
                       _("cannot list vcpu pinning for an inactive domain"));
        goto cleanup;
    }

    if (maxinfo >= 1) {
        if (info != NULL) {
            memset(info, 0, sizeof(*info) * maxinfo);
            for (i = 0; i < maxinfo; i++) {
                info[i].number = i;
                info[i].state = VIR_VCPU_RUNNING;
N
Nikolay Shirokovskiy 已提交
826 827
                if (prlsdkGetVcpuStats(privdom, i, &info[i].cpuTime) < 0)
                    goto cleanup;
828 829 830 831
            }
        }
        if (cpumaps != NULL) {
            memset(cpumaps, 0, maplen * maxinfo);
832 833 834 835
            for (i = 0; i < maxinfo; i++)
                virBitmapToDataBuf(privdom->def->cpumask,
                                   VIR_GET_CPUMAP(cpumaps, maplen, i),
                                   maplen);
836 837 838 839 840 841
        }
    }
    ret = maxinfo;

 cleanup:
    if (privdom)
N
Nikolay Shirokovskiy 已提交
842
        virDomainObjEndAPI(&privdom);
843 844 845 846
    return ret;
}


847
static int
848
vzNodeGetCPUMap(virConnectPtr conn ATTRIBUTE_UNUSED,
M
Michal Privoznik 已提交
849 850 851
                unsigned char **cpumap,
                unsigned int *online,
                unsigned int flags)
852
{
853
    return nodeGetCPUMap(NULL, cpumap, online, flags);
854 855
}

856
static int
857
vzConnectDomainEventRegisterAny(virConnectPtr conn,
M
Michal Privoznik 已提交
858 859 860 861 862
                                virDomainPtr domain,
                                int eventID,
                                virConnectDomainEventGenericCallback callback,
                                void *opaque,
                                virFreeCallback freecb)
863 864
{
    int ret = -1;
865
    vzConnPtr privconn = conn->privateData;
866 867 868 869 870 871 872 873 874
    if (virDomainEventStateRegisterID(conn,
                                      privconn->domainEventState,
                                      domain, eventID,
                                      callback, opaque, freecb, &ret) < 0)
        ret = -1;
    return ret;
}

static int
875
vzConnectDomainEventDeregisterAny(virConnectPtr conn,
M
Michal Privoznik 已提交
876
                                  int callbackID)
877
{
878
    vzConnPtr privconn = conn->privateData;
879 880 881 882 883 884 885 886 887 888 889 890
    int ret = -1;

    if (virObjectEventStateDeregisterID(conn,
                                        privconn->domainEventState,
                                        callbackID) < 0)
        goto cleanup;

    ret = 0;

 cleanup:
    return ret;
}
891

892
static int vzDomainSuspend(virDomainPtr domain)
893 894 895 896
{
    return prlsdkDomainChangeState(domain, prlsdkPause);
}

897
static int vzDomainResume(virDomainPtr domain)
898 899 900 901
{
    return prlsdkDomainChangeState(domain, prlsdkResume);
}

902
static int vzDomainCreate(virDomainPtr domain)
903 904 905 906
{
    return prlsdkDomainChangeState(domain, prlsdkStart);
}

907
static int vzDomainDestroy(virDomainPtr domain)
908 909 910 911
{
    return prlsdkDomainChangeState(domain, prlsdkKill);
}

912
static int vzDomainShutdown(virDomainPtr domain)
913 914 915 916
{
    return prlsdkDomainChangeState(domain, prlsdkStop);
}

917
static int vzDomainIsActive(virDomainPtr domain)
918 919 920 921
{
    virDomainObjPtr dom = NULL;
    int ret = -1;

922
    if (!(dom = vzDomObjFromDomain(domain)))
923 924 925 926 927 928 929 930
        return -1;

    ret = virDomainObjIsActive(dom);
    virObjectUnlock(dom);

    return ret;
}

931
static int
932
vzDomainCreateWithFlags(virDomainPtr domain, unsigned int flags)
933 934 935 936
{
    /* we don't support any create flags */
    virCheckFlags(0, -1);

937
    return vzDomainCreate(domain);
938 939
}

940
static int
941
vzDomainUndefineFlags(virDomainPtr domain,
M
Michal Privoznik 已提交
942
                      unsigned int flags)
943
{
944
    vzConnPtr privconn = domain->conn->privateData;
945
    virDomainObjPtr dom = NULL;
946
    int ret;
947 948 949

    virCheckFlags(0, -1);

950
    if (!(dom = vzDomObjFromDomain(domain)))
951 952
        return -1;

953 954
    ret = prlsdkUnregisterDomain(privconn, dom);
    if (ret)
M
Michal Privoznik 已提交
955
        virObjectUnlock(dom);
956 957

    return ret;
958 959 960
}

static int
961
vzDomainUndefine(virDomainPtr domain)
962
{
963
    return vzDomainUndefineFlags(domain, 0);
964 965
}

966
static int
967
vzDomainHasManagedSaveImage(virDomainPtr domain, unsigned int flags)
968 969
{
    virDomainObjPtr dom = NULL;
970 971
    int state, reason;
    int ret = 0;
972 973 974

    virCheckFlags(0, -1);

975
    if (!(dom = vzDomObjFromDomain(domain)))
976 977
        return -1;

978 979 980
    state = virDomainObjGetState(dom, &reason);
    if (state == VIR_DOMAIN_SHUTOFF && reason == VIR_DOMAIN_SHUTOFF_SAVED)
        ret = 1;
981 982
    virObjectUnlock(dom);

983 984 985 986
    return ret;
}

static int
987
vzDomainManagedSave(virDomainPtr domain, unsigned int flags)
988
{
989
    vzConnPtr privconn = domain->conn->privateData;
990 991 992 993 994 995 996
    virDomainObjPtr dom = NULL;
    int state, reason;
    int ret = -1;

    virCheckFlags(VIR_DOMAIN_SAVE_RUNNING |
                  VIR_DOMAIN_SAVE_PAUSED, -1);

997
    if (!(dom = vzDomObjFromDomain(domain)))
998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015
        return -1;

    state = virDomainObjGetState(dom, &reason);

    if (state == VIR_DOMAIN_RUNNING && (flags & VIR_DOMAIN_SAVE_PAUSED)) {
        ret = prlsdkDomainChangeStateLocked(privconn, dom, prlsdkPause);
        if (ret)
            goto cleanup;
    }

    ret = prlsdkDomainChangeStateLocked(privconn, dom, prlsdkSuspend);

 cleanup:
    virObjectUnlock(dom);
    return ret;
}

static int
1016
vzDomainManagedSaveRemove(virDomainPtr domain, unsigned int flags)
1017 1018 1019 1020 1021 1022 1023
{
    virDomainObjPtr dom = NULL;
    int state, reason;
    int ret = -1;

    virCheckFlags(0, -1);

1024
    if (!(dom = vzDomObjFromDomain(domain)))
1025 1026 1027 1028 1029 1030 1031
        return -1;

    state = virDomainObjGetState(dom, &reason);

    if (!(state == VIR_DOMAIN_SHUTOFF && reason == VIR_DOMAIN_SHUTOFF_SAVED))
        goto cleanup;

1032
    ret = prlsdkDomainManagedSaveRemove(dom);
1033 1034 1035 1036

 cleanup:
    virObjectUnlock(dom);
    return ret;
1037 1038
}

1039
static int vzDomainAttachDeviceFlags(virDomainPtr dom, const char *xml,
M
Michal Privoznik 已提交
1040
                                     unsigned int flags)
1041 1042
{
    int ret = -1;
1043
    vzConnPtr privconn = dom->conn->privateData;
1044 1045 1046 1047 1048 1049 1050
    virDomainDeviceDefPtr dev = NULL;
    virDomainObjPtr privdom = NULL;
    bool domactive = false;

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

1051
    if (!(privdom = vzDomObjFromDomain(dom)))
1052
        return -1;
1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080

    if (!(flags & VIR_DOMAIN_AFFECT_CONFIG)) {
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("device attach needs VIR_DOMAIN_AFFECT_CONFIG "
                         "flag to be set"));
        goto cleanup;
    }

    domactive = virDomainObjIsActive(privdom);
    if (!domactive && (flags & VIR_DOMAIN_AFFECT_LIVE)) {
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("cannot do live update a device on "
                         "inactive domain"));
        goto cleanup;
    }
    if (domactive && !(flags & VIR_DOMAIN_AFFECT_LIVE)) {
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("Updates on a running domain need "
                         "VIR_DOMAIN_AFFECT_LIVE flag"));
    }

    dev = virDomainDeviceDefParse(xml, privdom->def, privconn->caps,
                                  privconn->xmlopt, VIR_DOMAIN_XML_INACTIVE);
    if (dev == NULL)
        goto cleanup;

    switch (dev->type) {
    case VIR_DOMAIN_DEVICE_DISK:
1081
        ret = prlsdkAttachVolume(privdom, dev->data.disk);
1082 1083 1084 1085 1086 1087
        if (ret) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("disk attach failed"));
            goto cleanup;
        }
        break;
1088 1089 1090 1091 1092 1093 1094 1095
    case VIR_DOMAIN_DEVICE_NET:
        ret = prlsdkAttachNet(privdom, privconn, dev->data.net);
        if (ret) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("network attach failed"));
            goto cleanup;
        }
        break;
1096 1097
    default:
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
1098
                       _("device type '%s' cannot be attached"),
1099 1100 1101 1102 1103 1104
                       virDomainDeviceTypeToString(dev->type));
        break;
    }

    ret = 0;
 cleanup:
1105
    virObjectUnlock(privdom);
1106 1107 1108
    return ret;
}

1109
static int vzDomainAttachDevice(virDomainPtr dom, const char *xml)
1110
{
1111
    return vzDomainAttachDeviceFlags(dom, xml,
M
Michal Privoznik 已提交
1112
                                     VIR_DOMAIN_AFFECT_CONFIG | VIR_DOMAIN_AFFECT_LIVE);
1113 1114
}

1115
static int vzDomainDetachDeviceFlags(virDomainPtr dom, const char *xml,
M
Michal Privoznik 已提交
1116
                                     unsigned int flags)
1117 1118
{
    int ret = -1;
1119
    vzConnPtr privconn = dom->conn->privateData;
1120 1121 1122 1123 1124 1125 1126
    virDomainDeviceDefPtr dev = NULL;
    virDomainObjPtr privdom = NULL;
    bool domactive = false;

    virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
                  VIR_DOMAIN_AFFECT_CONFIG, -1);

1127
    privdom = vzDomObjFromDomain(dom);
1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157
    if (privdom == NULL)
        return -1;

    if (!(flags & VIR_DOMAIN_AFFECT_CONFIG)) {
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("device detach needs VIR_DOMAIN_AFFECT_CONFIG "
                         "flag to be set"));
        goto cleanup;
    }

    domactive = virDomainObjIsActive(privdom);
    if (!domactive && (flags & VIR_DOMAIN_AFFECT_LIVE)) {
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("cannot do live update a device on "
                         "inactive domain"));
        goto cleanup;
    }
    if (domactive && !(flags & VIR_DOMAIN_AFFECT_LIVE)) {
        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
                       _("Updates on a running domain need "
                         "VIR_DOMAIN_AFFECT_LIVE flag"));
    }

    dev = virDomainDeviceDefParse(xml, privdom->def, privconn->caps,
                                  privconn->xmlopt, VIR_DOMAIN_XML_INACTIVE);
    if (dev == NULL)
        goto cleanup;

    switch (dev->type) {
    case VIR_DOMAIN_DEVICE_DISK:
1158
        ret = prlsdkDetachVolume(privdom, dev->data.disk);
1159 1160 1161 1162 1163 1164
        if (ret) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("disk detach failed"));
            goto cleanup;
        }
        break;
1165 1166 1167 1168 1169 1170 1171 1172
    case VIR_DOMAIN_DEVICE_NET:
        ret = prlsdkDetachNet(privdom, privconn, dev->data.net);
        if (ret) {
            virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
                           _("network detach failed"));
            goto cleanup;
        }
        break;
1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185
    default:
        virReportError(VIR_ERR_OPERATION_UNSUPPORTED,
                       _("device type '%s' cannot be detached"),
                       virDomainDeviceTypeToString(dev->type));
        break;
    }

    ret = 0;
 cleanup:
    virObjectUnlock(privdom);
    return ret;
}

1186
static int vzDomainDetachDevice(virDomainPtr dom, const char *xml)
1187
{
1188
    return vzDomainDetachDeviceFlags(dom, xml,
M
Michal Privoznik 已提交
1189
                                     VIR_DOMAIN_AFFECT_CONFIG | VIR_DOMAIN_AFFECT_LIVE);
1190 1191
}

1192
static unsigned long long
1193
vzDomainGetMaxMemory(virDomainPtr domain)
1194 1195 1196 1197
{
    virDomainObjPtr dom = NULL;
    int ret = -1;

1198
    if (!(dom = vzDomObjFromDomain(domain)))
1199 1200
        return -1;

1201
    ret = virDomainDefGetMemoryActual(dom->def);
1202 1203 1204 1205
    virObjectUnlock(dom);
    return ret;
}

1206
static int
1207
vzDomainBlockStats(virDomainPtr domain, const char *path,
M
Michal Privoznik 已提交
1208
                   virDomainBlockStatsPtr stats)
1209 1210 1211 1212 1213 1214
{
    virDomainObjPtr dom = NULL;
    int ret = -1;
    size_t i;
    int idx;

1215
    if (!(dom = vzDomObjFromDomainRef(domain)))
1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227
        return -1;

    if (*path) {
        if ((idx = virDomainDiskIndexByName(dom->def, path, false)) < 0) {
            virReportError(VIR_ERR_INVALID_ARG, _("invalid path: %s"), path);
            goto cleanup;
        }
        if (prlsdkGetBlockStats(dom, dom->def->disks[idx], stats) < 0)
            goto cleanup;
    } else {
        virDomainBlockStatsStruct s;

M
Michal Privoznik 已提交
1228
#define PARALLELS_ZERO_STATS(VAR, TYPE, NAME)      \
1229 1230 1231 1232 1233 1234 1235 1236 1237 1238
        stats->VAR = 0;

        PARALLELS_BLOCK_STATS_FOREACH(PARALLELS_ZERO_STATS)

#undef PARALLELS_ZERO_STATS

        for (i = 0; i < dom->def->ndisks; i++) {
            if (prlsdkGetBlockStats(dom, dom->def->disks[i], &s) < 0)
                goto cleanup;

1239
#define PARALLELS_SUM_STATS(VAR, TYPE, NAME)        \
M
Michal Privoznik 已提交
1240 1241
    if (s.VAR != -1)                                \
        stats->VAR += s.VAR;
1242

M
Michal Privoznik 已提交
1243
        PARALLELS_BLOCK_STATS_FOREACH(PARALLELS_SUM_STATS)
1244

1245
#undef PARALLELS_SUM_STATS
1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258
        }
    }
    stats->errs = -1;
    ret = 0;

 cleanup:
    if (dom)
        virDomainObjEndAPI(&dom);

    return ret;
}

static int
1259
vzDomainBlockStatsFlags(virDomainPtr domain,
M
Michal Privoznik 已提交
1260 1261 1262 1263
                        const char *path,
                        virTypedParameterPtr params,
                        int *nparams,
                        unsigned int flags)
1264 1265 1266 1267 1268 1269 1270 1271 1272
{
    virDomainBlockStatsStruct stats;
    int ret = -1;
    size_t i;

    virCheckFlags(VIR_TYPED_PARAM_STRING_OKAY, -1);
    /* We don't return strings, and thus trivially support this flag.  */
    flags &= ~VIR_TYPED_PARAM_STRING_OKAY;

1273
    if (vzDomainBlockStats(domain, path, &stats) < 0)
1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307
        goto cleanup;

    if (*nparams == 0) {
#define PARALLELS_COUNT_STATS(VAR, TYPE, NAME)       \
        if ((stats.VAR) != -1)                       \
            ++*nparams;

        PARALLELS_BLOCK_STATS_FOREACH(PARALLELS_COUNT_STATS)

#undef PARALLELS_COUNT_STATS
        ret = 0;
        goto cleanup;
    }

    i = 0;
#define PARALLELS_BLOCK_STATS_ASSIGN_PARAM(VAR, TYPE, NAME)                    \
    if (i < *nparams && (stats.VAR) != -1) {                                   \
        if (virTypedParameterAssign(params + i, TYPE,                          \
                                    VIR_TYPED_PARAM_LLONG, (stats.VAR)) < 0)   \
            goto cleanup;                                                      \
        i++;                                                                   \
    }

    PARALLELS_BLOCK_STATS_FOREACH(PARALLELS_BLOCK_STATS_ASSIGN_PARAM)

#undef PARALLELS_BLOCK_STATS_ASSIGN_PARAM

    *nparams = i;
    ret = 0;

 cleanup:
    return ret;
}

1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323
static int
vzDomainInterfaceStats(virDomainPtr domain,
                         const char *path,
                         virDomainInterfaceStatsPtr stats)
{
    virDomainObjPtr dom = NULL;
    int ret;

    if (!(dom = vzDomObjFromDomainRef(domain)))
        return -1;

    ret = prlsdkGetNetStats(dom, path, stats);
    virDomainObjEndAPI(&dom);

    return ret;
}
1324

N
Nikolay Shirokovskiy 已提交
1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343
static int
vzDomainMemoryStats(virDomainPtr domain,
                    virDomainMemoryStatPtr stats,
                    unsigned int nr_stats,
                    unsigned int flags)
{
    virDomainObjPtr dom = NULL;
    int ret = -1;

    virCheckFlags(0, -1);
    if (!(dom = vzDomObjFromDomainRef(domain)))
        return -1;

    ret = prlsdkGetMemoryStats(dom, stats, nr_stats);
    virDomainObjEndAPI(&dom);

    return ret;
}

1344 1345
static virHypervisorDriver vzDriver = {
    .name = "vz",
1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392
    .connectOpen = vzConnectOpen,            /* 0.10.0 */
    .connectClose = vzConnectClose,          /* 0.10.0 */
    .connectGetVersion = vzConnectGetVersion,   /* 0.10.0 */
    .connectGetHostname = vzConnectGetHostname,      /* 0.10.0 */
    .nodeGetInfo = vzNodeGetInfo,      /* 0.10.0 */
    .connectGetCapabilities = vzConnectGetCapabilities,      /* 0.10.0 */
    .connectBaselineCPU = vzConnectBaselineCPU, /* 1.2.6 */
    .connectListDomains = vzConnectListDomains,      /* 0.10.0 */
    .connectNumOfDomains = vzConnectNumOfDomains,    /* 0.10.0 */
    .connectListDefinedDomains = vzConnectListDefinedDomains,        /* 0.10.0 */
    .connectNumOfDefinedDomains = vzConnectNumOfDefinedDomains,      /* 0.10.0 */
    .connectListAllDomains = vzConnectListAllDomains, /* 0.10.0 */
    .domainLookupByID = vzDomainLookupByID,    /* 0.10.0 */
    .domainLookupByUUID = vzDomainLookupByUUID,        /* 0.10.0 */
    .domainLookupByName = vzDomainLookupByName,        /* 0.10.0 */
    .domainGetOSType = vzDomainGetOSType,    /* 0.10.0 */
    .domainGetInfo = vzDomainGetInfo,  /* 0.10.0 */
    .domainGetState = vzDomainGetState,        /* 0.10.0 */
    .domainGetXMLDesc = vzDomainGetXMLDesc,    /* 0.10.0 */
    .domainIsPersistent = vzDomainIsPersistent,        /* 0.10.0 */
    .domainGetAutostart = vzDomainGetAutostart,        /* 0.10.0 */
    .domainGetVcpus = vzDomainGetVcpus, /* 1.2.6 */
    .domainSuspend = vzDomainSuspend,    /* 0.10.0 */
    .domainResume = vzDomainResume,    /* 0.10.0 */
    .domainDestroy = vzDomainDestroy,  /* 0.10.0 */
    .domainShutdown = vzDomainShutdown, /* 0.10.0 */
    .domainCreate = vzDomainCreate,    /* 0.10.0 */
    .domainCreateWithFlags = vzDomainCreateWithFlags, /* 1.2.10 */
    .domainDefineXML = vzDomainDefineXML,      /* 0.10.0 */
    .domainDefineXMLFlags = vzDomainDefineXMLFlags, /* 1.2.12 */
    .domainUndefine = vzDomainUndefine, /* 1.2.10 */
    .domainUndefineFlags = vzDomainUndefineFlags, /* 1.2.10 */
    .domainAttachDevice = vzDomainAttachDevice, /* 1.2.15 */
    .domainAttachDeviceFlags = vzDomainAttachDeviceFlags, /* 1.2.15 */
    .domainDetachDevice = vzDomainDetachDevice, /* 1.2.15 */
    .domainDetachDeviceFlags = vzDomainDetachDeviceFlags, /* 1.2.15 */
    .domainIsActive = vzDomainIsActive, /* 1.2.10 */
    .connectDomainEventRegisterAny = vzConnectDomainEventRegisterAny, /* 1.2.10 */
    .connectDomainEventDeregisterAny = vzConnectDomainEventDeregisterAny, /* 1.2.10 */
    .nodeGetCPUMap = vzNodeGetCPUMap, /* 1.2.8 */
    .connectIsEncrypted = vzConnectIsEncrypted, /* 1.2.5 */
    .connectIsSecure = vzConnectIsSecure, /* 1.2.5 */
    .connectIsAlive = vzConnectIsAlive, /* 1.2.5 */
    .domainHasManagedSaveImage = vzDomainHasManagedSaveImage, /* 1.2.13 */
    .domainManagedSave = vzDomainManagedSave, /* 1.2.14 */
    .domainManagedSaveRemove = vzDomainManagedSaveRemove, /* 1.2.14 */
    .domainGetMaxMemory = vzDomainGetMaxMemory, /* 1.2.15 */
1393 1394 1395 1396
    .domainBlockStats = vzDomainBlockStats, /* 1.2.17 */
    .domainBlockStatsFlags = vzDomainBlockStatsFlags, /* 1.2.17 */
    .domainInterfaceStats = vzDomainInterfaceStats, /* 1.2.17 */
    .domainMemoryStats = vzDomainMemoryStats, /* 1.2.17 */
D
Dmitry Guryanov 已提交
1397 1398
};

1399 1400
static virConnectDriver vzConnectDriver = {
    .hypervisorDriver = &vzDriver,
1401
    .storageDriver = &vzStorageDriver,
1402 1403
};

1404 1405 1406 1407
/* Parallels domain type backward compatibility*/
static virHypervisorDriver parallelsDriver;
static virConnectDriver parallelsConnectDriver;

D
Dmitry Guryanov 已提交
1408
/**
1409
 * vzRegister:
D
Dmitry Guryanov 已提交
1410
 *
1411
 * Registers the vz driver
D
Dmitry Guryanov 已提交
1412 1413
 */
int
1414
vzRegister(void)
D
Dmitry Guryanov 已提交
1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425
{
    char *prlctl_path;

    prlctl_path = virFindFileInPath(PRLCTL);
    if (!prlctl_path) {
        VIR_DEBUG("%s", _("Can't find prlctl command in the PATH env"));
        return 0;
    }

    VIR_FREE(prlctl_path);

1426 1427 1428 1429 1430
    /* Backward compatibility with Parallels domain type */
    parallelsDriver = vzDriver;
    parallelsDriver.name = "Parallels";
    parallelsConnectDriver = vzConnectDriver;
    parallelsConnectDriver.hypervisorDriver = &parallelsDriver;
1431
    if (virRegisterConnectDriver(&parallelsConnectDriver, false) < 0)
D
Dmitry Guryanov 已提交
1432
        return -1;
D
Dmitry Guryanov 已提交
1433

1434 1435 1436
    if (virRegisterConnectDriver(&vzConnectDriver, false) < 0)
        return -1;

D
Dmitry Guryanov 已提交
1437 1438
    return 0;
}