openvz_driver.c 37.1 KB
Newer Older
1 2 3 4 5
/*
 * openvz_driver.c: core driver methods for managing OpenVZ VEs
 *
 * Copyright (C) 2006, 2007 Binary Karma
 * Copyright (C) 2006 Shuveb Hussain
6
 * Copyright (C) 2007 Anoop Joe Cyriac
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
 *
 * 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
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
 *
22
 * Authors:
23 24 25
 * Shuveb Hussain <shuveb@binarykarma.com>
 * Anoop Joe Cyriac <anoop@binarykarma.com>
 *
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
 */

#include <config.h>

#include <sys/types.h>
#include <sys/poll.h>
#include <dirent.h>
#include <limits.h>
#include <string.h>
#include <stdio.h>
#include <strings.h>
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/utsname.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <paths.h>
#include <pwd.h>
#include <stdio.h>
#include <sys/wait.h>

50
#include "virterror_internal.h"
51
#include "datatypes.h"
52
#include "openvz_driver.h"
53 54
#include "event.h"
#include "buf.h"
55
#include "util.h"
56
#include "openvz_conf.h"
57
#include "nodeinfo.h"
58
#include "memory.h"
59
#include "bridge.h"
60

61 62 63
#define OPENVZ_MAX_ARG 28
#define CMDBUF_LEN 1488
#define CMDOP_LEN 288
64

D
Daniel Veillard 已提交
65
static int openvzGetProcessInfo(unsigned long long *cpuTime, int vpsid);
66 67 68
static int openvzGetMaxVCPUs(virConnectPtr conn, const char *type);
static int openvzDomainGetMaxVcpus(virDomainPtr dom);
static int openvzDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus);
69
static int openvzDomainSetVcpusInternal(virConnectPtr conn, virDomainObjPtr vm, unsigned int nvcpus);
D
Daniel Veillard 已提交
70

71 72
static void openvzDriverLock(struct openvz_driver *driver)
{
73
    virMutexLock(&driver->lock);
74 75 76 77
}

static void openvzDriverUnlock(struct openvz_driver *driver)
{
78
    virMutexUnlock(&driver->lock);
79 80
}

81 82
struct openvz_driver ovz_driver;

83
static void cmdExecFree(const char *cmdExec[])
84 85 86 87
{
    int i=-1;
    while(cmdExec[++i])
    {
88
        VIR_FREE(cmdExec[i]);
89 90 91
    }
}

92 93 94 95 96
/* generate arguments to create OpenVZ container
   return -1 - error
           0 - OK
*/
static int openvzDomainDefineCmd(virConnectPtr conn,
97
                                 const char *args[],
98
                                 int maxarg,
99
                                 virDomainDefPtr vmdef)
100 101 102 103 104 105 106 107
{
    int narg;

    for (narg = 0; narg < maxarg; narg++)
        args[narg] = NULL;

    if (vmdef == NULL){
        openvzError(conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
108
                   "%s", _("Container is not defined"));
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
        return -1;
    }

#define ADD_ARG(thisarg)                                                \
    do {                                                                \
        if (narg >= maxarg)                                             \
                 goto no_memory;                                        \
        args[narg++] = thisarg;                                         \
    } while (0)

#define ADD_ARG_LIT(thisarg)                                            \
    do {                                                                \
        if (narg >= maxarg)                                             \
                 goto no_memory;                                        \
        if ((args[narg++] = strdup(thisarg)) == NULL)                   \
            goto no_memory;                                             \
    } while (0)

    narg = 0;
    ADD_ARG_LIT(VZCTL);
    ADD_ARG_LIT("--quiet");
    ADD_ARG_LIT("create");
    ADD_ARG_LIT(vmdef->name);
132

133 134
    if (vmdef->nfss) {
        if (vmdef->fss[0]->type != VIR_DOMAIN_FS_TYPE_TEMPLATE) {
135 136 137 138
            openvzError(conn, VIR_ERR_INTERNAL_ERROR,
                        "%s", _("only filesystem templates are supported"));
            return -1;
        }
139

140
        if (vmdef->nfss > 1) {
141 142 143 144
            openvzError(conn, VIR_ERR_INTERNAL_ERROR,
                        "%s", _("only one filesystem supported"));
            return -1;
        }
145 146

        ADD_ARG_LIT("--ostemplate");
147
        ADD_ARG_LIT(vmdef->fss[0]->src);
148
    }
149
#if 0
150 151 152 153
    if ((vmdef->profile && *(vmdef->profile))) {
        ADD_ARG_LIT("--config");
        ADD_ARG_LIT(vmdef->profile);
    }
154
#endif
155 156 157 158 159 160 161 162 163 164 165 166

    ADD_ARG(NULL);
    return 0;
 no_memory:
    openvzError(conn, VIR_ERR_INTERNAL_ERROR,
                _("Could not put argument to %s"), VZCTL);
    return -1;
#undef ADD_ARG
#undef ADD_ARG_LIT
}


167
static virDomainPtr openvzDomainLookupByID(virConnectPtr conn,
168
                                           int id) {
169
    struct openvz_driver *driver = conn->privateData;
170
    virDomainObjPtr vm;
171
    virDomainPtr dom = NULL;
172

173
    openvzDriverLock(driver);
174
    vm = virDomainFindByID(&driver->domains, id);
175 176
    openvzDriverUnlock(driver);

177
    if (!vm) {
178
        openvzError(conn, VIR_ERR_NO_DOMAIN, NULL);
179
        goto cleanup;
180 181
    }

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

186
cleanup:
187 188
    if (vm)
        virDomainObjUnlock(vm);
189 190 191
    return dom;
}

192
static int openvzGetVersion(virConnectPtr conn, unsigned long *version) {
193
    struct  openvz_driver *driver = conn->privateData;
194
    openvzDriverLock(driver);
195
    *version = driver->version;
196
    openvzDriverUnlock(driver);
197 198 199
    return 0;
}

200
static char *openvzGetOSType(virDomainPtr dom)
201
{
202 203 204
    struct  openvz_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    char *ret = NULL;
205

206
    openvzDriverLock(driver);
207
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
208 209
    openvzDriverUnlock(driver);

210 211
    if (!vm) {
        openvzError(dom->conn, VIR_ERR_NO_DOMAIN, NULL);
212
        goto cleanup;
213 214 215 216 217
    }

    if (!(ret = strdup(vm->def->os.type)))
        openvzError(dom->conn, VIR_ERR_NO_MEMORY, NULL);

218
cleanup:
219 220
    if (vm)
        virDomainObjUnlock(vm);
221
    return ret;
222 223 224 225
}


static virDomainPtr openvzDomainLookupByUUID(virConnectPtr conn,
226
                                             const unsigned char *uuid) {
227 228 229
    struct  openvz_driver *driver = conn->privateData;
    virDomainObjPtr vm;
    virDomainPtr dom = NULL;
230

231
    openvzDriverLock(driver);
232
    vm = virDomainFindByUUID(&driver->domains, uuid);
233 234
    openvzDriverUnlock(driver);

235
    if (!vm) {
236
        openvzError(conn, VIR_ERR_NO_DOMAIN, NULL);
237
        goto cleanup;
238 239
    }

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

244
cleanup:
245 246
    if (vm)
        virDomainObjUnlock(vm);
247 248 249 250
    return dom;
}

static virDomainPtr openvzDomainLookupByName(virConnectPtr conn,
251 252 253 254
                                             const char *name) {
    struct openvz_driver *driver = conn->privateData;
    virDomainObjPtr vm;
    virDomainPtr dom = NULL;
255

256
    openvzDriverLock(driver);
257
    vm = virDomainFindByName(&driver->domains, name);
258 259
    openvzDriverUnlock(driver);

260
    if (!vm) {
261
        openvzError(conn, VIR_ERR_NO_DOMAIN, NULL);
262
        goto cleanup;
263 264
    }

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

269
cleanup:
270 271
    if (vm)
        virDomainObjUnlock(vm);
272 273 274 275
    return dom;
}

static int openvzDomainGetInfo(virDomainPtr dom,
276
                               virDomainInfoPtr info) {
277 278 279
    struct openvz_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
280

281
    openvzDriverLock(driver);
282
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
283 284
    openvzDriverUnlock(driver);

285
    if (!vm) {
D
Daniel Veillard 已提交
286
        openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN,
J
Jim Meyering 已提交
287
                    "%s", _("no domain with matching uuid"));
288
        goto cleanup;
289 290
    }

291
    info->state = vm->state;
292

293
    if (!virDomainIsActive(vm)) {
D
Daniel Veillard 已提交
294 295 296 297
        info->cpuTime = 0;
    } else {
        if (openvzGetProcessInfo(&(info->cpuTime), dom->id) < 0) {
            openvzError(dom->conn, VIR_ERR_OPERATION_FAILED,
298
                        _("cannot read cputime for domain %d"), dom->id);
299
            goto cleanup;
D
Daniel Veillard 已提交
300 301 302
        }
    }

303 304 305
    info->maxMem = vm->def->maxmem;
    info->memory = vm->def->memory;
    info->nrVirtCpu = vm->def->vcpus;
306 307 308
    ret = 0;

cleanup:
309 310
    if (vm)
        virDomainObjUnlock(vm);
311
    return ret;
312 313 314
}


315
static char *openvzDomainDumpXML(virDomainPtr dom, int flags) {
316 317 318
    struct openvz_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    char *ret = NULL;
319

320
    openvzDriverLock(driver);
321
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
322 323
    openvzDriverUnlock(driver);

324
    if (!vm) {
D
Daniel Veillard 已提交
325
        openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN,
J
Jim Meyering 已提交
326
                    "%s", _("no domain with matching uuid"));
327
        goto cleanup;
328
    }
329

330 331 332
    ret = virDomainDefFormat(dom->conn, vm->def, flags);

cleanup:
333 334
    if (vm)
        virDomainObjUnlock(vm);
335
    return ret;
336
}
337

338

339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356
/*
 * Convenient helper to target a command line argv
 * and fill in an empty slot with the supplied
 * key value. This lets us declare the argv on the
 * stack and just splice in the domain name after
 */
#define PROGRAM_SENTINAL ((char *)0x1)
static void openvzSetProgramSentinal(const char **prog, const char *key)
{
    const char **tmp = prog;
    while (tmp && *tmp) {
        if (*tmp == PROGRAM_SENTINAL) {
            *tmp = key;
            break;
        }
        tmp++;
    }
}
357 358

static int openvzDomainShutdown(virDomainPtr dom) {
359 360 361 362
    struct openvz_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    const char *prog[] = {VZCTL, "--quiet", "stop", PROGRAM_SENTINAL, NULL};
    int ret = -1;
363

364
    openvzDriverLock(driver);
365
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
366 367
    openvzDriverUnlock(driver);

368 369
    if (!vm) {
        openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN,
J
Jim Meyering 已提交
370
                    "%s", _("no domain with matching uuid"));
371
        goto cleanup;
372
    }
373

374
    openvzSetProgramSentinal(prog, vm->def->name);
375
    if (vm->state != VIR_DOMAIN_RUNNING) {
D
Daniel Veillard 已提交
376
        openvzError(dom->conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
377
                    "%s", _("domain is not in running state"));
378
        goto cleanup;
379
    }
380

381
    if (virRun(dom->conn, prog, NULL) < 0)
382
        goto cleanup;
383

384 385
    vm->def->id = -1;
    vm->state = VIR_DOMAIN_SHUTOFF;
386
    ret = 0;
387

388
cleanup:
389 390
    if (vm)
        virDomainObjUnlock(vm);
391
    return ret;
392 393
}

394 395
static int openvzDomainReboot(virDomainPtr dom,
                              unsigned int flags ATTRIBUTE_UNUSED) {
396 397 398 399
    struct openvz_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    const char *prog[] = {VZCTL, "--quiet", "restart", PROGRAM_SENTINAL, NULL};
    int ret = -1;
400

401
    openvzDriverLock(driver);
402
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
403 404
    openvzDriverUnlock(driver);

405
    if (!vm) {
D
Daniel Veillard 已提交
406
        openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN,
J
Jim Meyering 已提交
407
                    "%s", _("no domain with matching uuid"));
408
        goto cleanup;
409
    }
410

411
    openvzSetProgramSentinal(prog, vm->def->name);
412 413
    if (vm->state != VIR_DOMAIN_RUNNING) {
        openvzError(dom->conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
414
                    "%s", _("domain is not in running state"));
415
        goto cleanup;
416
    }
417

418
    if (virRun(dom->conn, prog, NULL) < 0)
419 420
        goto cleanup;
    ret = 0;
421

422
cleanup:
423 424
    if (vm)
        virDomainObjUnlock(vm);
425
    return ret;
426 427
}

428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450
static char *
openvzGenerateVethName(int veid, char *dev_name_ve)
{
    char    dev_name[32];
    int     ifNo = 0;

    if (sscanf(dev_name_ve, "%*[^0-9]%d", &ifNo) != 1)
        return NULL;
    if (snprintf(dev_name, sizeof(dev_name), "veth%d.%d", veid, ifNo) < 7)
        return NULL;
    return strdup(dev_name);
}

static char *
openvzGenerateContainerVethName(int veid)
{
    int     ret;
    char    temp[1024];

    /* try to get line "^NETIF=..." from config */
    if ( (ret = openvzReadConfigParam(veid, "NETIF", temp, sizeof(temp))) <= 0) {
        snprintf(temp, sizeof(temp), "eth0");
    } else {
451
        char *saveptr;
452 453 454 455
        char   *s;
        int     max = 0;

        /* get maximum interface number (actually, it is the last one) */
456
        for (s=strtok_r(temp, ";", &saveptr); s; s=strtok_r(NULL, ";", &saveptr)) {
457 458 459 460 461 462 463 464 465 466 467 468
            int x;

            if (sscanf(s, "ifname=eth%d", &x) != 1) return NULL;
            if (x > max) max = x;
        }

        /* set new name */
        snprintf(temp, sizeof(temp), "eth%d", max+1);
    }
    return strdup(temp);
}

D
Daniel Veillard 已提交
469 470
static int
openvzDomainSetNetwork(virConnectPtr conn, const char *vpsid,
471 472
                       virDomainNetDefPtr net,
                       virBufferPtr configBuf)
D
Daniel Veillard 已提交
473 474
{
    int rc = 0, narg;
475
    const char *prog[OPENVZ_MAX_ARG];
476
    char macaddr[VIR_MAC_STRING_BUFLEN];
477 478
    unsigned char host_mac[VIR_MAC_BUFLEN];
    char host_macaddr[VIR_MAC_STRING_BUFLEN];
479
    struct openvz_driver *driver =  conn->privateData;
480
    char *opt = NULL;
D
Daniel Veillard 已提交
481 482 483 484 485 486 487 488 489 490 491 492 493 494

#define ADD_ARG_LIT(thisarg)                                            \
    do {                                                                \
        if (narg >= OPENVZ_MAX_ARG)                                             \
                 goto no_memory;                                        \
        if ((prog[narg++] = strdup(thisarg)) == NULL)                   \
            goto no_memory;                                             \
    } while (0)


    if (net == NULL)
       return 0;
    if (vpsid == NULL) {
        openvzError(conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
495
                    "%s", _("Container ID is not specified"));
D
Daniel Veillard 已提交
496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511
        return -1;
    }

    for (narg = 0; narg < OPENVZ_MAX_ARG; narg++)
        prog[narg] = NULL;

    narg = 0;

    if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE ||
        net->type == VIR_DOMAIN_NET_TYPE_ETHERNET) {
        ADD_ARG_LIT(VZCTL);
        ADD_ARG_LIT("--quiet");
        ADD_ARG_LIT("set");
        ADD_ARG_LIT(vpsid);
    }

512
    virFormatMacAddr(net->mac, macaddr);
513 514
    virCapabilitiesGenerateMac(driver->caps, host_mac);
    virFormatMacAddr(host_mac, host_macaddr);
515 516 517 518 519

    if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
        virBuffer buf = VIR_BUFFER_INITIALIZER;
        char *dev_name_ve;
        int veid = strtoI(vpsid);
D
Daniel Veillard 已提交
520 521 522

        //--netif_add ifname[,mac,host_ifname,host_mac]
        ADD_ARG_LIT("--netif_add") ;
523 524 525 526 527

        /* generate interface name in ve and copy it to options */
        dev_name_ve = openvzGenerateContainerVethName(veid);
        if (dev_name_ve == NULL) {
           openvzError(conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
528
                       "%s", _("Could not generate eth name for container"));
529 530 531 532 533 534 535 536 537 538
           rc = -1;
           goto exit;
        }

        /* if user doesn't specified host interface name,
         * than we need to generate it */
        if (net->ifname == NULL) {
            net->ifname = openvzGenerateVethName(veid, dev_name_ve);
            if (net->ifname == NULL) {
               openvzError(conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
539
                           "%s", _("Could not generate veth name"));
540 541 542 543 544 545 546 547 548
               rc = -1;
               VIR_FREE(dev_name_ve);
               goto exit;
            }
        }

        virBufferAdd(&buf, dev_name_ve, -1); /* Guest dev */
        virBufferVSprintf(&buf, ",%s", macaddr); /* Guest dev mac */
        virBufferVSprintf(&buf, ",%s", net->ifname); /* Host dev */
549
        virBufferVSprintf(&buf, ",%s", host_macaddr); /* Host dev mac */
550 551 552 553 554 555 556

        if (driver->version >= VZCTL_BRIDGE_MIN_VERSION) {
            virBufferVSprintf(&buf, ",%s", net->data.bridge.brname); /* Host bridge */
        } else {
            virBufferVSprintf(configBuf, "ifname=%s", dev_name_ve);
            virBufferVSprintf(configBuf, ",mac=%s", macaddr); /* Guest dev mac */
            virBufferVSprintf(configBuf, ",host_ifname=%s", net->ifname); /* Host dev */
557
            virBufferVSprintf(configBuf, ",host_mac=%s", host_macaddr); /* Host dev mac */
558
            virBufferVSprintf(configBuf, ",bridge=%s", net->data.bridge.brname); /* Host bridge */
D
Daniel Veillard 已提交
559
        }
560 561 562 563 564 565

        VIR_FREE(dev_name_ve);

        if (!(opt = virBufferContentAndReset(&buf)))
            goto no_memory;

D
Daniel Veillard 已提交
566
        ADD_ARG_LIT(opt) ;
567 568
        VIR_FREE(opt);
    } else if (net->type == VIR_DOMAIN_NET_TYPE_ETHERNET &&
D
Daniel Veillard 已提交
569 570 571 572 573 574 575 576 577 578
              net->data.ethernet.ipaddr != NULL) {
        //--ipadd ip
        ADD_ARG_LIT("--ipadd") ;
        ADD_ARG_LIT(net->data.ethernet.ipaddr) ;
    }

    //TODO: processing NAT and physical device

    if (prog[0] != NULL){
        ADD_ARG_LIT("--save");
579
        if (virRun(conn, prog, NULL) < 0) {
D
Daniel Veillard 已提交
580 581 582 583 584 585 586 587 588 589 590 591
           openvzError(conn, VIR_ERR_INTERNAL_ERROR,
                    _("Could not exec %s"), VZCTL);
           rc = -1;
           goto exit;
        }
    }

 exit:
    cmdExecFree(prog);
    return rc;

 no_memory:
592
    VIR_FREE(opt);
D
Daniel Veillard 已提交
593 594 595 596 597 598 599 600
    openvzError(conn, VIR_ERR_INTERNAL_ERROR,
                _("Could not put argument to %s"), VZCTL);
    cmdExecFree(prog);
    return -1;

#undef ADD_ARG_LIT
}

601 602 603 604 605 606 607 608 609

static int
openvzDomainSetNetworkConfig(virConnectPtr conn,
                             virDomainDefPtr def)
{
    unsigned int i;
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    char *param;
    int first = 1;
610
    struct openvz_driver *driver =  conn->privateData;
611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649

    for (i = 0 ; i < def->nnets ; i++) {
        if (driver->version < VZCTL_BRIDGE_MIN_VERSION &&
            def->nets[i]->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
            if (first)
                first = 0;
            else
                virBufferAddLit(&buf, ";");
        }

        if (openvzDomainSetNetwork(conn, def->name, def->nets[i], &buf) < 0) {
            openvzError(conn, VIR_ERR_INTERNAL_ERROR,
                        "%s", _("Could not configure network"));
            goto exit;
        }
    }

    if (driver->version < VZCTL_BRIDGE_MIN_VERSION && def->nnets) {
        param = virBufferContentAndReset(&buf);
        if (param) {
            if (openvzWriteConfigParam(strtoI(def->name), "NETIF", param) < 0) {
                VIR_FREE(param);
                openvzError(conn, VIR_ERR_INTERNAL_ERROR,
                            "%s", _("cannot replace NETIF config"));
                return -1;
            }
            VIR_FREE(param);
        }
    }

    return 0;

exit:
    param = virBufferContentAndReset(&buf);
    VIR_FREE(param);
    return -1;
}


650 651 652
static virDomainPtr
openvzDomainDefineXML(virConnectPtr conn, const char *xml)
{
653
    struct openvz_driver *driver =  conn->privateData;
654 655
    virDomainDefPtr vmdef = NULL;
    virDomainObjPtr vm = NULL;
656
    virDomainPtr dom = NULL;
657
    const char *prog[OPENVZ_MAX_ARG];
658
    prog[0] = NULL;
659

660
    openvzDriverLock(driver);
661 662
    if ((vmdef = virDomainDefParseString(conn, driver->caps, xml,
                                         VIR_DOMAIN_XML_INACTIVE)) == NULL)
663
        goto cleanup;
664

665 666
    if (vmdef->os.init == NULL &&
        !(vmdef->os.init = strdup("/sbin/init"))) {
667
        goto cleanup;
668 669
    }

670
    vm = virDomainFindByName(&driver->domains, vmdef->name);
671
    if (vm) {
672 673
        openvzError(conn, VIR_ERR_OPERATION_FAILED,
                  _("Already an OPENVZ VM active with the id '%s'"),
674
                  vmdef->name);
675
        goto cleanup;
676
    }
677 678 679
    if (!(vm = virDomainAssignDef(conn, &driver->domains, vmdef)))
        goto cleanup;
    vmdef = NULL;
680

681
    if (openvzDomainDefineCmd(conn, prog, OPENVZ_MAX_ARG, vm->def) < 0) {
682
        openvzError(conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
683
                "%s", _("Error creating command for container"));
684
        goto cleanup;
685 686
    }

D
Daniel Veillard 已提交
687 688
    //TODO: set quota

689
    if (virRun(conn, prog, NULL) < 0) {
D
Daniel Veillard 已提交
690
        openvzError(conn, VIR_ERR_INTERNAL_ERROR,
691
               _("Could not exec %s"), VZCTL);
692
        goto cleanup;
693
    }
694

695
    if (openvzSetDefinedUUID(strtoI(vm->def->name), vm->def->uuid) < 0) {
696
        openvzError(conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
697
               "%s", _("Could not set UUID"));
698
        goto cleanup;
699 700
    }

701 702
    if (openvzDomainSetNetworkConfig(conn, vm->def) < 0)
        goto cleanup;
D
Daniel Veillard 已提交
703

704
    if (vm->def->vcpus > 0) {
705
        if (openvzDomainSetVcpusInternal(conn, vm, vm->def->vcpus) < 0) {
706
            openvzError(conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
707
                     "%s", _("Could not set number of virtual cpu"));
708
             goto cleanup;
709 710 711
        }
    }

712 713 714 715 716 717
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
    if (dom)
        dom->id = -1;

cleanup:
    virDomainDefFree(vmdef);
718
    cmdExecFree(prog);
719 720 721
    if (vm)
        virDomainObjUnlock(vm);
    openvzDriverUnlock(driver);
722 723 724 725
    return dom;
}

static virDomainPtr
726
openvzDomainCreateXML(virConnectPtr conn, const char *xml,
727
                      unsigned int flags ATTRIBUTE_UNUSED)
728
{
729
    struct openvz_driver *driver =  conn->privateData;
730 731
    virDomainDefPtr vmdef = NULL;
    virDomainObjPtr vm = NULL;
732
    virDomainPtr dom = NULL;
733
    const char *progstart[] = {VZCTL, "--quiet", "start", PROGRAM_SENTINAL, NULL};
734
    const char *progcreate[OPENVZ_MAX_ARG];
735
    progcreate[0] = NULL;
736

737
    openvzDriverLock(driver);
738 739
    if ((vmdef = virDomainDefParseString(conn, driver->caps, xml,
                                         VIR_DOMAIN_XML_INACTIVE)) == NULL)
740
        goto cleanup;
741 742

    if (vmdef->os.init == NULL &&
743 744
        !(vmdef->os.init = strdup("/sbin/init")))
        goto cleanup;
745

746
    vm = virDomainFindByName(&driver->domains, vmdef->name);
747
    if (vm) {
748 749 750
        openvzError(conn, VIR_ERR_OPERATION_FAILED,
                  _("Already an OPENVZ VM defined with the id '%s'"),
                  vmdef->name);
751
        goto cleanup;
752
    }
753 754 755
    if (!(vm = virDomainAssignDef(conn, &driver->domains, vmdef)))
        goto cleanup;
    vmdef = NULL;
756

757
    if (openvzDomainDefineCmd(conn, progcreate, OPENVZ_MAX_ARG, vm->def) < 0) {
758
        openvzError(conn, VIR_ERR_INTERNAL_ERROR,
759 760
                    "%s", _("Error creating command for container"));
        goto cleanup;
761 762
    }

763
    if (virRun(conn, progcreate, NULL) < 0) {
D
Daniel Veillard 已提交
764
        openvzError(conn, VIR_ERR_INTERNAL_ERROR,
765
               _("Could not exec %s"), VZCTL);
766
        goto cleanup;
767
    }
768

769
    if (openvzSetDefinedUUID(strtoI(vm->def->name), vm->def->uuid) < 0) {
770
        openvzError(conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
771
               "%s", _("Could not set UUID"));
772
        goto cleanup;
773 774
    }

775 776
    if (openvzDomainSetNetworkConfig(conn, vm->def) < 0)
        goto cleanup;
D
Daniel Veillard 已提交
777

778
    openvzSetProgramSentinal(progstart, vm->def->name);
779

780
    if (virRun(conn, progstart, NULL) < 0) {
D
Daniel Veillard 已提交
781
        openvzError(conn, VIR_ERR_INTERNAL_ERROR,
782
               _("Could not exec %s"), VZCTL);
783
        goto cleanup;
784
    }
785

786
    vm->pid = strtoI(vm->def->name);
787 788
    vm->def->id = vm->pid;
    vm->state = VIR_DOMAIN_RUNNING;
789

790
    if (vm->def->vcpus > 0) {
791
        if (openvzDomainSetVcpusInternal(conn, vm, vm->def->vcpus) < 0) {
792
            openvzError(conn, VIR_ERR_INTERNAL_ERROR,
793
                    "%s", _("Could not set number of virtual cpu"));
794
            goto cleanup;
795 796 797
        }
    }

798 799 800 801 802 803
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
    if (dom)
        dom->id = vm->def->id;

cleanup:
    virDomainDefFree(vmdef);
804
    cmdExecFree(progcreate);
805 806 807
    if (vm)
        virDomainObjUnlock(vm);
    openvzDriverUnlock(driver);
808 809 810 811 812 813
    return dom;
}

static int
openvzDomainCreate(virDomainPtr dom)
{
814 815 816 817
    struct openvz_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    const char *prog[] = {VZCTL, "--quiet", "start", PROGRAM_SENTINAL, NULL };
    int ret = -1;
818

819
    openvzDriverLock(driver);
820
    vm = virDomainFindByName(&driver->domains, dom->name);
821 822
    openvzDriverUnlock(driver);

823
    if (!vm) {
D
Daniel Veillard 已提交
824
        openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN,
825 826
                    "%s", _("no domain with matching id"));
        goto cleanup;
827
    }
828

829
    if (vm->state != VIR_DOMAIN_SHUTOFF) {
D
Daniel Veillard 已提交
830
        openvzError(dom->conn, VIR_ERR_OPERATION_DENIED,
831 832
                    "%s", _("domain is not in shutoff state"));
        goto cleanup;
833 834
    }

835
    openvzSetProgramSentinal(prog, vm->def->name);
836
    if (virRun(dom->conn, prog, NULL) < 0) {
D
Daniel Veillard 已提交
837
        openvzError(dom->conn, VIR_ERR_INTERNAL_ERROR,
838 839
                    _("Could not exec %s"), VZCTL);
        goto cleanup;
840
    }
841

842 843 844
    vm->pid = strtoI(vm->def->name);
    vm->def->id = vm->pid;
    vm->state = VIR_DOMAIN_RUNNING;
845
    ret = 0;
846

847
cleanup:
848 849
    if (vm)
        virDomainObjUnlock(vm);
850
    return ret;
851 852 853 854 855
}

static int
openvzDomainUndefine(virDomainPtr dom)
{
856 857 858 859
    struct openvz_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    const char *prog[] = { VZCTL, "--quiet", "destroy", PROGRAM_SENTINAL, NULL };
    int ret = -1;
860

861
    openvzDriverLock(driver);
862
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
863
    if (!vm) {
864 865
        openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid"));
        goto cleanup;
866
    }
867

868
    if (virDomainIsActive(vm)) {
869 870
        openvzError(dom->conn, VIR_ERR_INTERNAL_ERROR, "%s", _("cannot delete active domain"));
        goto cleanup;
871
    }
872

873 874 875 876 877
    openvzSetProgramSentinal(prog, vm->def->name);
    if (virRun(dom->conn, prog, NULL) < 0) {
        openvzError(dom->conn, VIR_ERR_INTERNAL_ERROR,
                    _("Could not exec %s"), VZCTL);
        goto cleanup;
878
    }
879

880
    virDomainRemoveInactive(&driver->domains, vm);
881
    vm = NULL;
882
    ret = 0;
883

884
cleanup:
885 886 887
    if (vm)
        virDomainObjUnlock(vm);
    openvzDriverUnlock(driver);
888
    return ret;
889 890
}

891 892 893
static int
openvzDomainSetAutostart(virDomainPtr dom, int autostart)
{
894 895 896
    struct openvz_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    const char *prog[] = { VZCTL, "--quiet", "set", PROGRAM_SENTINAL,
D
Daniel Veillard 已提交
897
                           "--onboot", autostart ? "yes" : "no",
898
                           "--save", NULL };
899
    int ret = -1;
900

901
    openvzDriverLock(driver);
902
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
903 904
    openvzDriverUnlock(driver);

905
    if (!vm) {
906 907
        openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid"));
        goto cleanup;
908 909
    }

910 911 912 913
    openvzSetProgramSentinal(prog, vm->def->name);
    if (virRun(dom->conn, prog, NULL) < 0) {
        openvzError(dom->conn, VIR_ERR_INTERNAL_ERROR, _("Could not exec %s"), VZCTL);
        goto cleanup;
914
    }
915
    ret = 0;
916

917
cleanup:
918 919
    if (vm)
        virDomainObjUnlock(vm);
920
    return ret;
921 922 923 924 925
}

static int
openvzDomainGetAutostart(virDomainPtr dom, int *autostart)
{
926 927
    struct openvz_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
928
    char value[1024];
929
    int ret = -1;
930

931
    openvzDriverLock(driver);
932
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
933 934
    openvzDriverUnlock(driver);

935
    if (!vm) {
936 937 938
        openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN,
                    "%s", _("no domain with matching uuid"));
        goto cleanup;
939 940
    }

941
    if (openvzReadConfigParam(strtoI(vm->def->name), "ONBOOT", value, sizeof(value)) < 0) {
942 943 944
        openvzError(dom->conn, VIR_ERR_INTERNAL_ERROR,
                    "%s", _("Could not read container config"));
        goto cleanup;
945 946 947 948
    }

    *autostart = 0;
    if (STREQ(value,"yes"))
D
Daniel Veillard 已提交
949
        *autostart = 1;
950
    ret = 0;
951

952
cleanup:
953 954
    if (vm)
        virDomainObjUnlock(vm);
955
    return ret;
956 957
}

958 959 960 961 962 963 964 965 966 967 968 969 970 971
static int openvzGetMaxVCPUs(virConnectPtr conn, const char *type) {
    if (STRCASEEQ(type, "openvz"))
        return 1028; //OpenVZ has no limitation

    openvzError(conn, VIR_ERR_INVALID_ARG,
                     _("unknown type '%s'"), type);
    return -1;
}


static int openvzDomainGetMaxVcpus(virDomainPtr dom) {
    return openvzGetMaxVCPUs(dom->conn, "openvz");
}

972 973 974 975
static int openvzDomainSetVcpusInternal(virConnectPtr conn, virDomainObjPtr vm,
    unsigned int nvcpus)
{
    char        str_vcpus[32];
976
    const char *prog[] = { VZCTL, "--quiet", "set", PROGRAM_SENTINAL,
977
                           "--cpus", str_vcpus, "--save", NULL };
978
    unsigned int pcpus;
979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001
    pcpus = openvzGetNodeCPUs();
    if (pcpus > 0 && pcpus < nvcpus)
        nvcpus = pcpus;

    snprintf(str_vcpus, 31, "%d", nvcpus);
    str_vcpus[31] = '\0';

    openvzSetProgramSentinal(prog, vm->def->name);
    if (virRun(conn, prog, NULL) < 0) {
        openvzError(conn, VIR_ERR_INTERNAL_ERROR,
                _("Could not exec %s"), VZCTL);
        return -1;
    }

    vm->def->vcpus = nvcpus;
    return 0;
}

static int openvzDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus)
{
    virDomainObjPtr         vm;
    struct openvz_driver   *driver = dom->conn->privateData;
    int                     ret = -1;
1002

1003
    openvzDriverLock(driver);
1004
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
1005 1006
    openvzDriverUnlock(driver);

1007
    if (!vm) {
1008
        openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN,
J
Jim Meyering 已提交
1009
                    "%s", _("no domain with matching uuid"));
1010
        goto cleanup;
1011 1012
    }

1013
    if (nvcpus <= 0) {
1014
        openvzError(dom->conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
1015
                    "%s", _("VCPUs should be >= 1"));
1016
        goto cleanup;
1017 1018
    }

1019
    openvzDomainSetVcpusInternal(dom->conn, vm, nvcpus);
1020 1021 1022
    ret = 0;

cleanup:
1023 1024
    if (vm)
        virDomainObjUnlock(vm);
1025
    return ret;
1026 1027
}

1028
static int openvzProbe(void)
1029
{
1030 1031 1032 1033 1034
    if (geteuid() == 0 &&
        virFileExists("/proc/vz"))
        return 1;

    return 0;
1035 1036
}

1037
static virDrvOpenStatus openvzOpen(virConnectPtr conn,
1038 1039
                                   virConnectAuthPtr auth ATTRIBUTE_UNUSED,
                                   int flags ATTRIBUTE_UNUSED)
1040
{
1041
    struct openvz_driver *driver;
1042
    if (!openvzProbe())
1043
        return VIR_DRV_OPEN_DECLINED;
1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054

    if (conn->uri == NULL) {
        conn->uri = xmlParseURI("openvz:///system");
        if (conn->uri == NULL) {
            openvzError(conn, VIR_ERR_NO_DOMAIN, NULL);
            return VIR_DRV_OPEN_ERROR;
        }
    } else if (conn->uri->scheme == NULL ||
               conn->uri->path == NULL ||
               STRNEQ (conn->uri->scheme, "openvz") ||
               STRNEQ (conn->uri->path, "/system")) {
1055 1056 1057 1058 1059 1060 1061 1062 1063 1064
        return VIR_DRV_OPEN_DECLINED;
    }

    if (VIR_ALLOC(driver) < 0) {
        openvzError(conn, VIR_ERR_NO_MEMORY, NULL);
        return VIR_DRV_OPEN_ERROR;
    }

    if (!(driver->caps = openvzCapsInit()))
        goto cleanup;
1065

1066 1067
    if (openvzLoadDomains(driver) < 0)
        goto cleanup;
1068

1069 1070 1071
    if (openvzExtractVersion(conn, driver) < 0)
        goto cleanup;

1072
    conn->privateData = driver;
1073

1074
    return VIR_DRV_OPEN_SUCCESS;
1075

1076 1077 1078
cleanup:
    openvzFreeDriver(driver);
    return VIR_DRV_OPEN_ERROR;
1079
};
1080 1081

static int openvzClose(virConnectPtr conn) {
1082
    struct openvz_driver *driver = conn->privateData;
1083

1084
    openvzFreeDriver(driver);
1085 1086 1087 1088 1089 1090 1091 1092 1093
    conn->privateData = NULL;

    return 0;
}

static const char *openvzGetType(virConnectPtr conn ATTRIBUTE_UNUSED) {
    return strdup("OpenVZ");
}

1094 1095 1096 1097 1098
static int openvzGetNodeInfo(virConnectPtr conn,
                             virNodeInfoPtr nodeinfo) {
    return virNodeInfoPopulate(conn, nodeinfo);
}

1099
static char *openvzGetCapabilities(virConnectPtr conn) {
1100 1101 1102
    struct openvz_driver *driver = conn->privateData;
    char *ret;

1103
    openvzDriverLock(driver);
1104
    ret = virCapabilitiesFormatXML(driver->caps);
1105
    openvzDriverUnlock(driver);
1106

1107
    return ret;
1108 1109
}

1110 1111
static int openvzListDomains(virConnectPtr conn, int *ids, int nids) {
    int got = 0;
1112 1113
    int veid;
    pid_t pid;
1114 1115
    int outfd = -1;
    int errfd = -1;
1116 1117
    int ret;
    char buf[32];
1118
    char *endptr;
1119
    const char *cmd[] = {VZLIST, "-ovpsid", "-H" , NULL};
1120

1121 1122
    ret = virExec(conn, cmd, NULL, NULL,
                  &pid, -1, &outfd, &errfd, VIR_EXEC_NONE);
1123
    if(ret == -1) {
D
Daniel Veillard 已提交
1124
        openvzError(conn, VIR_ERR_INTERNAL_ERROR,
1125
               _("Could not exec %s"), VZLIST);
D
Daniel P. Berrange 已提交
1126
        return -1;
1127 1128
    }

1129 1130 1131
    while(got < nids){
        ret = openvz_readline(outfd, buf, 32);
        if(!ret) break;
1132 1133 1134 1135 1136
        if (virStrToLong_i(buf, &endptr, 10, &veid) < 0) {
            openvzError(conn, VIR_ERR_INTERNAL_ERROR,
                    _("Could not parse VPS ID %s"), buf);
            continue;
        }
1137 1138 1139
        ids[got] = veid;
        got ++;
    }
1140
    waitpid(pid, NULL, 0);
1141 1142 1143 1144

    return got;
}

1145
static int openvzNumDomains(virConnectPtr conn) {
1146
    struct openvz_driver *driver = conn->privateData;
1147 1148
    int nactive = 0, i;

1149 1150 1151
    openvzDriverLock(driver);
    for (i = 0 ; i < driver->domains.count ; i++) {
        virDomainObjLock(driver->domains.objs[i]);
1152
        if (virDomainIsActive(driver->domains.objs[i]))
1153
            nactive++;
1154 1155 1156
        virDomainObjUnlock(driver->domains.objs[i]);
    }
    openvzDriverUnlock(driver);
1157

1158
    return nactive;
1159 1160 1161
}

static int openvzListDefinedDomains(virConnectPtr conn,
1162
                                    char **const names, int nnames) {
1163
    int got = 0;
1164 1165
    int veid, outfd = -1, errfd = -1, ret;
    pid_t pid;
1166
    char vpsname[32];
1167
    char buf[32];
1168
    char *endptr;
1169
    const char *cmd[] = {VZLIST, "-ovpsid", "-H", "-S", NULL};
1170 1171

    /* the -S options lists only stopped domains */
1172 1173
    ret = virExec(conn, cmd, NULL, NULL,
                  &pid, -1, &outfd, &errfd, VIR_EXEC_NONE);
1174
    if(ret == -1) {
D
Daniel Veillard 已提交
1175
        openvzError(conn, VIR_ERR_INTERNAL_ERROR,
1176
               _("Could not exec %s"), VZLIST);
D
Daniel P. Berrange 已提交
1177
        return -1;
1178 1179
    }

1180 1181 1182
    while(got < nnames){
        ret = openvz_readline(outfd, buf, 32);
        if(!ret) break;
1183 1184 1185 1186 1187
        if (virStrToLong_i(buf, &endptr, 10, &veid) < 0) {
            openvzError(conn, VIR_ERR_INTERNAL_ERROR,
                    _("Could not parse VPS ID %s"), buf);
            continue;
        }
1188 1189 1190
        snprintf(vpsname, sizeof(vpsname), "%d", veid);
        if (!(names[got] = strdup(vpsname)))
            goto no_memory;
1191 1192
        got ++;
    }
1193
    waitpid(pid, NULL, 0);
1194
    return got;
1195 1196 1197 1198 1199 1200

no_memory:
    openvzError(conn, VIR_ERR_NO_MEMORY, NULL);
    for ( ; got >= 0 ; got--)
        VIR_FREE(names[got]);
    return -1;
1201 1202
}

D
Daniel Veillard 已提交
1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247
static int openvzGetProcessInfo(unsigned long long *cpuTime, int vpsid) {
    int fd;
    char line[1024] ;
    unsigned long long usertime, systime, nicetime;
    int readvps = 0, ret;

/* read statistic from /proc/vz/vestat.
sample:
Version: 2.2
      VEID     user      nice     system     uptime                 idle   other..
        33       78         0       1330   59454597      142650441835148   other..
        55      178         0       5340   59424597      542650441835148   other..
*/

    if ((fd = open("/proc/vz/vestat", O_RDONLY)) == -1)
        return -1;

    /*search line with VEID=vpsid*/
    while(1) {
        ret = openvz_readline(fd, line, sizeof(line));
        if(ret <= 0)
            break;

        if (sscanf(line, "%d %llu %llu %llu",
                          &readvps, &usertime, &nicetime, &systime) != 4)
            continue;

        if (readvps == vpsid)
            break; /*found vpsid*/
    }

    close(fd);
    if (ret < 0)
        return -1;

    if (readvps != vpsid) /*not found*/
        return -1;

    /* convert jiffies to nanoseconds */
    *cpuTime = 1000ull * 1000ull * 1000ull * (usertime + nicetime  + systime)
                                     / (unsigned long long)sysconf(_SC_CLK_TCK);

    return 0;
}

1248
static int openvzNumDefinedDomains(virConnectPtr conn) {
1249
    struct openvz_driver *driver =  conn->privateData;
1250 1251
    int ninactive = 0, i;

1252 1253 1254
    openvzDriverLock(driver);
    for (i = 0 ; i < driver->domains.count ; i++) {
        virDomainObjLock(driver->domains.objs[i]);
1255
        if (!virDomainIsActive(driver->domains.objs[i]))
1256
            ninactive++;
1257 1258 1259
        virDomainObjUnlock(driver->domains.objs[i]);
    }
    openvzDriverUnlock(driver);
1260

1261
    return ninactive;
1262 1263 1264 1265 1266 1267 1268
}

static virDriver openvzDriver = {
    VIR_DRV_OPENVZ,
    "OPENVZ",
    openvzOpen, /* open */
    openvzClose, /* close */
1269
    NULL, /* supports_feature */
1270
    openvzGetType, /* type */
1271
    openvzGetVersion, /* version */
1272 1273
    NULL, /* hostname */
    NULL, /* uri */
1274
    openvzGetMaxVCPUs, /* getMaxVcpus */
1275
    openvzGetNodeInfo, /* nodeGetInfo */
1276
    openvzGetCapabilities, /* getCapabilities */
1277 1278
    openvzListDomains, /* listDomains */
    openvzNumDomains, /* numOfDomains */
1279
    openvzDomainCreateXML, /* domainCreateXML */
1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295
    openvzDomainLookupByID, /* domainLookupByID */
    openvzDomainLookupByUUID, /* domainLookupByUUID */
    openvzDomainLookupByName, /* domainLookupByName */
    NULL, /* domainSuspend */
    NULL, /* domainResume */
    openvzDomainShutdown, /* domainShutdown */
    openvzDomainReboot, /* domainReboot */
    openvzDomainShutdown, /* domainDestroy */
    openvzGetOSType, /* domainGetOSType */
    NULL, /* domainGetMaxMemory */
    NULL, /* domainSetMaxMemory */
    NULL, /* domainSetMemory */
    openvzDomainGetInfo, /* domainGetInfo */
    NULL, /* domainSave */
    NULL, /* domainRestore */
    NULL, /* domainCoreDump */
1296
    openvzDomainSetVcpus, /* domainSetVcpus */
1297 1298
    NULL, /* domainPinVcpu */
    NULL, /* domainGetVcpus */
1299
    openvzDomainGetMaxVcpus, /* domainGetMaxVcpus */
1300
    openvzDomainDumpXML, /* domainDumpXML */
1301 1302 1303
    openvzListDefinedDomains, /* listDomains */
    openvzNumDefinedDomains, /* numOfDomains */
    openvzDomainCreate, /* domainCreate */
1304 1305
    openvzDomainDefineXML, /* domainDefineXML */
    openvzDomainUndefine, /* domainUndefine */
1306 1307
    NULL, /* domainAttachDevice */
    NULL, /* domainDetachDevice */
1308 1309
    openvzDomainGetAutostart, /* domainGetAutostart */
    openvzDomainSetAutostart, /* domainSetAutostart */
1310 1311 1312
    NULL, /* domainGetSchedulerType */
    NULL, /* domainGetSchedulerParameters */
    NULL, /* domainSetSchedulerParameters */
1313 1314 1315 1316 1317
    NULL, /* domainMigratePrepare */
    NULL, /* domainMigratePerform */
    NULL, /* domainMigrateFinish */
    NULL, /* domainBlockStats */
    NULL, /* domainInterfaceStats */
D
Daniel P. Berrange 已提交
1318 1319
    NULL, /* domainBlockPeek */
    NULL, /* domainMemoryPeek */
1320
    NULL, /* nodeGetCellsFreeMemory */
1321
    NULL, /* nodeGetFreeMemory */
1322 1323
    NULL, /* domainEventRegister */
    NULL, /* domainEventDeregister */
D
Daniel Veillard 已提交
1324 1325
    NULL, /* domainMigratePrepare2 */
    NULL, /* domainMigrateFinish2 */
1326 1327 1328 1329 1330 1331 1332
};

int openvzRegister(void) {
    virRegisterDriver(&openvzDriver);
    return 0;
}