openvz_driver.c 38.4 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
#define VIR_FROM_THIS VIR_FROM_OPENVZ

63 64 65
#define OPENVZ_MAX_ARG 28
#define CMDBUF_LEN 1488
#define CMDOP_LEN 288
66

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

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

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

83 84
struct openvz_driver ovz_driver;

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

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

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

    if (vmdef == NULL){
        openvzError(conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
110
                   "%s", _("Container is not defined"));
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
        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);
134

135 136 137
    if (vmdef->nfss == 1 &&
        vmdef->fss[0]->type == VIR_DOMAIN_FS_TYPE_TEMPLATE)
    {
138
        ADD_ARG_LIT("--ostemplate");
139
        ADD_ARG_LIT(vmdef->fss[0]->src);
140
    }
141
#if 0
142 143 144 145
    if ((vmdef->profile && *(vmdef->profile))) {
        ADD_ARG_LIT("--config");
        ADD_ARG_LIT(vmdef->profile);
    }
146
#endif
147 148 149 150 151 152 153 154 155 156 157 158

    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
}


159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
static int openvzSetInitialConfig(virConnectPtr conn,
                                  virDomainDefPtr vmdef)
{
    int ret = -1;
    int vpsid;
    char * confdir = NULL;
    const char *prog[OPENVZ_MAX_ARG];
    prog[0] = NULL;

    if (vmdef->nfss > 1) {
        openvzError(conn, VIR_ERR_INTERNAL_ERROR,
                    "%s", _("only one filesystem supported"));
        goto cleanup;
    }

    if (vmdef->nfss == 1 &&
        vmdef->fss[0]->type != VIR_DOMAIN_FS_TYPE_TEMPLATE &&
        vmdef->fss[0]->type != VIR_DOMAIN_FS_TYPE_MOUNT)
    {
        openvzError(conn, VIR_ERR_INTERNAL_ERROR,
                    "%s", _("filesystem is not of type 'template' or 'mount'"));
        goto cleanup;
    }


    if (vmdef->nfss == 1 &&
        vmdef->fss[0]->type == VIR_DOMAIN_FS_TYPE_MOUNT)
    {

        if(virStrToLong_i(vmdef->name, NULL, 10, &vpsid) < 0) {
            openvzError(conn, VIR_ERR_INTERNAL_ERROR,
                        "%s", _("Could not convert domain name to VEID"));
            goto cleanup;
        }

        if (openvzCopyDefaultConfig(vpsid) < 0) {
            openvzError(conn, VIR_ERR_INTERNAL_ERROR,
                        "%s", _("Could not copy default config"));
            goto cleanup;
        }

        if (openvzWriteVPSConfigParam(vpsid, "VE_PRIVATE", vmdef->fss[0]->src) < 0) {
            openvzError(conn, VIR_ERR_INTERNAL_ERROR,
                        "%s", _("Could not set the source dir for the filesystem"));
            goto cleanup;
        }
    }
    else
    {
        if (openvzDomainDefineCmd(conn, prog, OPENVZ_MAX_ARG, vmdef) < 0) {
            openvzError(conn, VIR_ERR_INTERNAL_ERROR,
                        "%s", _("Error creating command for container"));
            goto cleanup;
        }

        if (virRun(conn, prog, NULL) < 0) {
            openvzError(conn, VIR_ERR_INTERNAL_ERROR,
                   _("Could not exec %s"), VZCTL);
            goto cleanup;
        }
    }

    ret = 0;

cleanup:
  VIR_FREE(confdir);
  cmdExecFree(prog);
  return ret;
}


230
static virDomainPtr openvzDomainLookupByID(virConnectPtr conn,
231
                                           int id) {
232
    struct openvz_driver *driver = conn->privateData;
233
    virDomainObjPtr vm;
234
    virDomainPtr dom = NULL;
235

236
    openvzDriverLock(driver);
237
    vm = virDomainFindByID(&driver->domains, id);
238 239
    openvzDriverUnlock(driver);

240
    if (!vm) {
241
        openvzError(conn, VIR_ERR_NO_DOMAIN, NULL);
242
        goto cleanup;
243 244
    }

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

249
cleanup:
250 251
    if (vm)
        virDomainObjUnlock(vm);
252 253 254
    return dom;
}

255
static int openvzGetVersion(virConnectPtr conn, unsigned long *version) {
256
    struct  openvz_driver *driver = conn->privateData;
257
    openvzDriverLock(driver);
258
    *version = driver->version;
259
    openvzDriverUnlock(driver);
260 261 262
    return 0;
}

263
static char *openvzGetOSType(virDomainPtr dom)
264
{
265 266 267
    struct  openvz_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    char *ret = NULL;
268

269
    openvzDriverLock(driver);
270
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
271 272
    openvzDriverUnlock(driver);

273 274
    if (!vm) {
        openvzError(dom->conn, VIR_ERR_NO_DOMAIN, NULL);
275
        goto cleanup;
276 277 278
    }

    if (!(ret = strdup(vm->def->os.type)))
279
        virReportOOMError(dom->conn);
280

281
cleanup:
282 283
    if (vm)
        virDomainObjUnlock(vm);
284
    return ret;
285 286 287 288
}


static virDomainPtr openvzDomainLookupByUUID(virConnectPtr conn,
289
                                             const unsigned char *uuid) {
290 291 292
    struct  openvz_driver *driver = conn->privateData;
    virDomainObjPtr vm;
    virDomainPtr dom = NULL;
293

294
    openvzDriverLock(driver);
295
    vm = virDomainFindByUUID(&driver->domains, uuid);
296 297
    openvzDriverUnlock(driver);

298
    if (!vm) {
299
        openvzError(conn, VIR_ERR_NO_DOMAIN, NULL);
300
        goto cleanup;
301 302
    }

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

307
cleanup:
308 309
    if (vm)
        virDomainObjUnlock(vm);
310 311 312 313
    return dom;
}

static virDomainPtr openvzDomainLookupByName(virConnectPtr conn,
314 315 316 317
                                             const char *name) {
    struct openvz_driver *driver = conn->privateData;
    virDomainObjPtr vm;
    virDomainPtr dom = NULL;
318

319
    openvzDriverLock(driver);
320
    vm = virDomainFindByName(&driver->domains, name);
321 322
    openvzDriverUnlock(driver);

323
    if (!vm) {
324
        openvzError(conn, VIR_ERR_NO_DOMAIN, NULL);
325
        goto cleanup;
326 327
    }

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

332
cleanup:
333 334
    if (vm)
        virDomainObjUnlock(vm);
335 336 337 338
    return dom;
}

static int openvzDomainGetInfo(virDomainPtr dom,
339
                               virDomainInfoPtr info) {
340 341 342
    struct openvz_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    int ret = -1;
343

344
    openvzDriverLock(driver);
345
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
346 347
    openvzDriverUnlock(driver);

348
    if (!vm) {
D
Daniel Veillard 已提交
349
        openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN,
J
Jim Meyering 已提交
350
                    "%s", _("no domain with matching uuid"));
351
        goto cleanup;
352 353
    }

354
    info->state = vm->state;
355

356
    if (!virDomainIsActive(vm)) {
D
Daniel Veillard 已提交
357 358 359 360
        info->cpuTime = 0;
    } else {
        if (openvzGetProcessInfo(&(info->cpuTime), dom->id) < 0) {
            openvzError(dom->conn, VIR_ERR_OPERATION_FAILED,
361
                        _("cannot read cputime for domain %d"), dom->id);
362
            goto cleanup;
D
Daniel Veillard 已提交
363 364 365
        }
    }

366 367 368
    info->maxMem = vm->def->maxmem;
    info->memory = vm->def->memory;
    info->nrVirtCpu = vm->def->vcpus;
369 370 371
    ret = 0;

cleanup:
372 373
    if (vm)
        virDomainObjUnlock(vm);
374
    return ret;
375 376 377
}


378
static char *openvzDomainDumpXML(virDomainPtr dom, int flags) {
379 380 381
    struct openvz_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    char *ret = NULL;
382

383
    openvzDriverLock(driver);
384
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
385 386
    openvzDriverUnlock(driver);

387
    if (!vm) {
D
Daniel Veillard 已提交
388
        openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN,
J
Jim Meyering 已提交
389
                    "%s", _("no domain with matching uuid"));
390
        goto cleanup;
391
    }
392

393 394 395
    ret = virDomainDefFormat(dom->conn, vm->def, flags);

cleanup:
396 397
    if (vm)
        virDomainObjUnlock(vm);
398
    return ret;
399
}
400

401

402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419
/*
 * 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++;
    }
}
420 421

static int openvzDomainShutdown(virDomainPtr dom) {
422 423 424 425
    struct openvz_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    const char *prog[] = {VZCTL, "--quiet", "stop", PROGRAM_SENTINAL, NULL};
    int ret = -1;
426

427
    openvzDriverLock(driver);
428
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
429 430
    openvzDriverUnlock(driver);

431 432
    if (!vm) {
        openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN,
J
Jim Meyering 已提交
433
                    "%s", _("no domain with matching uuid"));
434
        goto cleanup;
435
    }
436

437
    openvzSetProgramSentinal(prog, vm->def->name);
438
    if (vm->state != VIR_DOMAIN_RUNNING) {
D
Daniel Veillard 已提交
439
        openvzError(dom->conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
440
                    "%s", _("domain is not in running state"));
441
        goto cleanup;
442
    }
443

444
    if (virRun(dom->conn, prog, NULL) < 0)
445
        goto cleanup;
446

447 448
    vm->def->id = -1;
    vm->state = VIR_DOMAIN_SHUTOFF;
449
    ret = 0;
450

451
cleanup:
452 453
    if (vm)
        virDomainObjUnlock(vm);
454
    return ret;
455 456
}

457 458
static int openvzDomainReboot(virDomainPtr dom,
                              unsigned int flags ATTRIBUTE_UNUSED) {
459 460 461 462
    struct openvz_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    const char *prog[] = {VZCTL, "--quiet", "restart", PROGRAM_SENTINAL, NULL};
    int ret = -1;
463

464
    openvzDriverLock(driver);
465
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
466 467
    openvzDriverUnlock(driver);

468
    if (!vm) {
D
Daniel Veillard 已提交
469
        openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN,
J
Jim Meyering 已提交
470
                    "%s", _("no domain with matching uuid"));
471
        goto cleanup;
472
    }
473

474
    openvzSetProgramSentinal(prog, vm->def->name);
475 476
    if (vm->state != VIR_DOMAIN_RUNNING) {
        openvzError(dom->conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
477
                    "%s", _("domain is not in running state"));
478
        goto cleanup;
479
    }
480

481
    if (virRun(dom->conn, prog, NULL) < 0)
482 483
        goto cleanup;
    ret = 0;
484

485
cleanup:
486 487
    if (vm)
        virDomainObjUnlock(vm);
488
    return ret;
489 490
}

491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510
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 */
511
    if ( (ret = openvzReadVPSConfigParam(veid, "NETIF", temp, sizeof(temp))) <= 0) {
512 513
        snprintf(temp, sizeof(temp), "eth0");
    } else {
514
        char *saveptr;
515 516 517 518
        char   *s;
        int     max = 0;

        /* get maximum interface number (actually, it is the last one) */
519
        for (s=strtok_r(temp, ";", &saveptr); s; s=strtok_r(NULL, ";", &saveptr)) {
520 521 522 523 524 525 526 527 528 529 530 531
            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 已提交
532 533
static int
openvzDomainSetNetwork(virConnectPtr conn, const char *vpsid,
534 535
                       virDomainNetDefPtr net,
                       virBufferPtr configBuf)
D
Daniel Veillard 已提交
536 537
{
    int rc = 0, narg;
538
    const char *prog[OPENVZ_MAX_ARG];
539
    char macaddr[VIR_MAC_STRING_BUFLEN];
540 541
    unsigned char host_mac[VIR_MAC_BUFLEN];
    char host_macaddr[VIR_MAC_STRING_BUFLEN];
542
    struct openvz_driver *driver =  conn->privateData;
543
    char *opt = NULL;
D
Daniel Veillard 已提交
544 545 546 547 548 549 550 551 552 553 554 555 556 557

#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 已提交
558
                    "%s", _("Container ID is not specified"));
D
Daniel Veillard 已提交
559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574
        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);
    }

575
    virFormatMacAddr(net->mac, macaddr);
576 577
    virCapabilitiesGenerateMac(driver->caps, host_mac);
    virFormatMacAddr(host_mac, host_macaddr);
578 579 580 581 582

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

        //--netif_add ifname[,mac,host_ifname,host_mac]
        ADD_ARG_LIT("--netif_add") ;
586 587 588 589 590

        /* 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 已提交
591
                       "%s", _("Could not generate eth name for container"));
592 593 594 595 596 597 598 599 600 601
           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 已提交
602
                           "%s", _("Could not generate veth name"));
603 604 605 606 607 608 609 610 611
               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 */
612
        virBufferVSprintf(&buf, ",%s", host_macaddr); /* Host dev mac */
613 614 615 616 617 618 619

        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 */
620
            virBufferVSprintf(configBuf, ",host_mac=%s", host_macaddr); /* Host dev mac */
621
            virBufferVSprintf(configBuf, ",bridge=%s", net->data.bridge.brname); /* Host bridge */
D
Daniel Veillard 已提交
622
        }
623 624 625 626 627 628

        VIR_FREE(dev_name_ve);

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

D
Daniel Veillard 已提交
629
        ADD_ARG_LIT(opt) ;
630 631
        VIR_FREE(opt);
    } else if (net->type == VIR_DOMAIN_NET_TYPE_ETHERNET &&
D
Daniel Veillard 已提交
632 633 634 635 636 637 638 639 640 641
              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");
642
        if (virRun(conn, prog, NULL) < 0) {
D
Daniel Veillard 已提交
643 644 645 646 647 648 649 650 651 652 653 654
           openvzError(conn, VIR_ERR_INTERNAL_ERROR,
                    _("Could not exec %s"), VZCTL);
           rc = -1;
           goto exit;
        }
    }

 exit:
    cmdExecFree(prog);
    return rc;

 no_memory:
655
    VIR_FREE(opt);
D
Daniel Veillard 已提交
656 657 658 659 660 661 662 663
    openvzError(conn, VIR_ERR_INTERNAL_ERROR,
                _("Could not put argument to %s"), VZCTL);
    cmdExecFree(prog);
    return -1;

#undef ADD_ARG_LIT
}

664 665 666 667 668 669 670 671 672

static int
openvzDomainSetNetworkConfig(virConnectPtr conn,
                             virDomainDefPtr def)
{
    unsigned int i;
    virBuffer buf = VIR_BUFFER_INITIALIZER;
    char *param;
    int first = 1;
673
    struct openvz_driver *driver =  conn->privateData;
674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693

    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) {
694
            if (openvzWriteVPSConfigParam(strtoI(def->name), "NETIF", param) < 0) {
695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712
                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;
}


713 714 715
static virDomainPtr
openvzDomainDefineXML(virConnectPtr conn, const char *xml)
{
716
    struct openvz_driver *driver =  conn->privateData;
717 718
    virDomainDefPtr vmdef = NULL;
    virDomainObjPtr vm = NULL;
719
    virDomainPtr dom = NULL;
720

721
    openvzDriverLock(driver);
722 723
    if ((vmdef = virDomainDefParseString(conn, driver->caps, xml,
                                         VIR_DOMAIN_XML_INACTIVE)) == NULL)
724
        goto cleanup;
725

726 727
    if (vmdef->os.init == NULL &&
        !(vmdef->os.init = strdup("/sbin/init"))) {
728
        goto cleanup;
729 730
    }

731
    vm = virDomainFindByName(&driver->domains, vmdef->name);
732
    if (vm) {
733 734
        openvzError(conn, VIR_ERR_OPERATION_FAILED,
                  _("Already an OPENVZ VM active with the id '%s'"),
735
                  vmdef->name);
736
        goto cleanup;
737
    }
738 739 740
    if (!(vm = virDomainAssignDef(conn, &driver->domains, vmdef)))
        goto cleanup;
    vmdef = NULL;
741

742
    if (openvzSetInitialConfig(conn, vm->def) < 0) {
743
        openvzError(conn, VIR_ERR_INTERNAL_ERROR,
744
                "%s", _("Error creating intial configuration"));
745
        goto cleanup;
746 747
    }

D
Daniel Veillard 已提交
748 749
    //TODO: set quota

750
    if (openvzSetDefinedUUID(strtoI(vm->def->name), vm->def->uuid) < 0) {
751
        openvzError(conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
752
               "%s", _("Could not set UUID"));
753
        goto cleanup;
754 755
    }

756 757
    if (openvzDomainSetNetworkConfig(conn, vm->def) < 0)
        goto cleanup;
D
Daniel Veillard 已提交
758

759
    if (vm->def->vcpus > 0) {
760
        if (openvzDomainSetVcpusInternal(conn, vm, vm->def->vcpus) < 0) {
761
            openvzError(conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
762
                     "%s", _("Could not set number of virtual cpu"));
763
             goto cleanup;
764 765 766
        }
    }

767 768 769 770 771 772
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
    if (dom)
        dom->id = -1;

cleanup:
    virDomainDefFree(vmdef);
773 774 775
    if (vm)
        virDomainObjUnlock(vm);
    openvzDriverUnlock(driver);
776 777 778 779
    return dom;
}

static virDomainPtr
780
openvzDomainCreateXML(virConnectPtr conn, const char *xml,
781
                      unsigned int flags ATTRIBUTE_UNUSED)
782
{
783
    struct openvz_driver *driver =  conn->privateData;
784 785
    virDomainDefPtr vmdef = NULL;
    virDomainObjPtr vm = NULL;
786
    virDomainPtr dom = NULL;
787
    const char *progstart[] = {VZCTL, "--quiet", "start", PROGRAM_SENTINAL, NULL};
788

789
    openvzDriverLock(driver);
790 791
    if ((vmdef = virDomainDefParseString(conn, driver->caps, xml,
                                         VIR_DOMAIN_XML_INACTIVE)) == NULL)
792
        goto cleanup;
793 794

    if (vmdef->os.init == NULL &&
795 796
        !(vmdef->os.init = strdup("/sbin/init")))
        goto cleanup;
797

798
    vm = virDomainFindByName(&driver->domains, vmdef->name);
799
    if (vm) {
800 801 802
        openvzError(conn, VIR_ERR_OPERATION_FAILED,
                  _("Already an OPENVZ VM defined with the id '%s'"),
                  vmdef->name);
803
        goto cleanup;
804
    }
805 806 807
    if (!(vm = virDomainAssignDef(conn, &driver->domains, vmdef)))
        goto cleanup;
    vmdef = NULL;
808

809
    if (openvzSetInitialConfig(conn, vm->def) < 0) {
D
Daniel Veillard 已提交
810
        openvzError(conn, VIR_ERR_INTERNAL_ERROR,
811
                "%s", _("Error creating intial configuration"));
812
        goto cleanup;
813
    }
814

815
    if (openvzSetDefinedUUID(strtoI(vm->def->name), vm->def->uuid) < 0) {
816
        openvzError(conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
817
               "%s", _("Could not set UUID"));
818
        goto cleanup;
819 820
    }

821 822
    if (openvzDomainSetNetworkConfig(conn, vm->def) < 0)
        goto cleanup;
D
Daniel Veillard 已提交
823

824
    openvzSetProgramSentinal(progstart, vm->def->name);
825

826
    if (virRun(conn, progstart, NULL) < 0) {
D
Daniel Veillard 已提交
827
        openvzError(conn, VIR_ERR_INTERNAL_ERROR,
828
               _("Could not exec %s"), VZCTL);
829
        goto cleanup;
830
    }
831

832
    vm->pid = strtoI(vm->def->name);
833 834
    vm->def->id = vm->pid;
    vm->state = VIR_DOMAIN_RUNNING;
835

836
    if (vm->def->vcpus > 0) {
837
        if (openvzDomainSetVcpusInternal(conn, vm, vm->def->vcpus) < 0) {
838
            openvzError(conn, VIR_ERR_INTERNAL_ERROR,
839
                    "%s", _("Could not set number of virtual cpu"));
840
            goto cleanup;
841 842 843
        }
    }

844 845 846 847 848 849
    dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
    if (dom)
        dom->id = vm->def->id;

cleanup:
    virDomainDefFree(vmdef);
850 851 852
    if (vm)
        virDomainObjUnlock(vm);
    openvzDriverUnlock(driver);
853 854 855 856 857 858
    return dom;
}

static int
openvzDomainCreate(virDomainPtr dom)
{
859 860 861 862
    struct openvz_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    const char *prog[] = {VZCTL, "--quiet", "start", PROGRAM_SENTINAL, NULL };
    int ret = -1;
863

864
    openvzDriverLock(driver);
865
    vm = virDomainFindByName(&driver->domains, dom->name);
866 867
    openvzDriverUnlock(driver);

868
    if (!vm) {
D
Daniel Veillard 已提交
869
        openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN,
870 871
                    "%s", _("no domain with matching id"));
        goto cleanup;
872
    }
873

874
    if (vm->state != VIR_DOMAIN_SHUTOFF) {
D
Daniel Veillard 已提交
875
        openvzError(dom->conn, VIR_ERR_OPERATION_DENIED,
876 877
                    "%s", _("domain is not in shutoff state"));
        goto cleanup;
878 879
    }

880
    openvzSetProgramSentinal(prog, vm->def->name);
881
    if (virRun(dom->conn, prog, NULL) < 0) {
D
Daniel Veillard 已提交
882
        openvzError(dom->conn, VIR_ERR_INTERNAL_ERROR,
883 884
                    _("Could not exec %s"), VZCTL);
        goto cleanup;
885
    }
886

887 888 889
    vm->pid = strtoI(vm->def->name);
    vm->def->id = vm->pid;
    vm->state = VIR_DOMAIN_RUNNING;
890
    ret = 0;
891

892
cleanup:
893 894
    if (vm)
        virDomainObjUnlock(vm);
895
    return ret;
896 897 898 899 900
}

static int
openvzDomainUndefine(virDomainPtr dom)
{
901 902 903 904
    struct openvz_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    const char *prog[] = { VZCTL, "--quiet", "destroy", PROGRAM_SENTINAL, NULL };
    int ret = -1;
905

906
    openvzDriverLock(driver);
907
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
908
    if (!vm) {
909 910
        openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid"));
        goto cleanup;
911
    }
912

913
    if (virDomainIsActive(vm)) {
914 915
        openvzError(dom->conn, VIR_ERR_INTERNAL_ERROR, "%s", _("cannot delete active domain"));
        goto cleanup;
916
    }
917

918 919 920 921 922
    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;
923
    }
924

925
    virDomainRemoveInactive(&driver->domains, vm);
926
    vm = NULL;
927
    ret = 0;
928

929
cleanup:
930 931 932
    if (vm)
        virDomainObjUnlock(vm);
    openvzDriverUnlock(driver);
933
    return ret;
934 935
}

936 937 938
static int
openvzDomainSetAutostart(virDomainPtr dom, int autostart)
{
939 940 941
    struct openvz_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
    const char *prog[] = { VZCTL, "--quiet", "set", PROGRAM_SENTINAL,
D
Daniel Veillard 已提交
942
                           "--onboot", autostart ? "yes" : "no",
943
                           "--save", NULL };
944
    int ret = -1;
945

946
    openvzDriverLock(driver);
947
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
948 949
    openvzDriverUnlock(driver);

950
    if (!vm) {
951 952
        openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN, "%s", _("no domain with matching uuid"));
        goto cleanup;
953 954
    }

955 956 957 958
    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;
959
    }
960
    ret = 0;
961

962
cleanup:
963 964
    if (vm)
        virDomainObjUnlock(vm);
965
    return ret;
966 967 968 969 970
}

static int
openvzDomainGetAutostart(virDomainPtr dom, int *autostart)
{
971 972
    struct openvz_driver *driver = dom->conn->privateData;
    virDomainObjPtr vm;
973
    char value[1024];
974
    int ret = -1;
975

976
    openvzDriverLock(driver);
977
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
978 979
    openvzDriverUnlock(driver);

980
    if (!vm) {
981 982 983
        openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN,
                    "%s", _("no domain with matching uuid"));
        goto cleanup;
984 985
    }

986
    if (openvzReadVPSConfigParam(strtoI(vm->def->name), "ONBOOT", value, sizeof(value)) < 0) {
987 988 989
        openvzError(dom->conn, VIR_ERR_INTERNAL_ERROR,
                    "%s", _("Could not read container config"));
        goto cleanup;
990 991 992 993
    }

    *autostart = 0;
    if (STREQ(value,"yes"))
D
Daniel Veillard 已提交
994
        *autostart = 1;
995
    ret = 0;
996

997
cleanup:
998 999
    if (vm)
        virDomainObjUnlock(vm);
1000
    return ret;
1001 1002
}

1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016
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");
}

1017 1018 1019 1020
static int openvzDomainSetVcpusInternal(virConnectPtr conn, virDomainObjPtr vm,
    unsigned int nvcpus)
{
    char        str_vcpus[32];
1021
    const char *prog[] = { VZCTL, "--quiet", "set", PROGRAM_SENTINAL,
1022
                           "--cpus", str_vcpus, "--save", NULL };
1023
    unsigned int pcpus;
1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046
    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;
1047

1048
    openvzDriverLock(driver);
1049
    vm = virDomainFindByUUID(&driver->domains, dom->uuid);
1050 1051
    openvzDriverUnlock(driver);

1052
    if (!vm) {
1053
        openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN,
J
Jim Meyering 已提交
1054
                    "%s", _("no domain with matching uuid"));
1055
        goto cleanup;
1056 1057
    }

1058
    if (nvcpus <= 0) {
1059
        openvzError(dom->conn, VIR_ERR_INTERNAL_ERROR,
J
Jim Meyering 已提交
1060
                    "%s", _("VCPUs should be >= 1"));
1061
        goto cleanup;
1062 1063
    }

1064
    openvzDomainSetVcpusInternal(dom->conn, vm, nvcpus);
1065 1066 1067
    ret = 0;

cleanup:
1068 1069
    if (vm)
        virDomainObjUnlock(vm);
1070
    return ret;
1071 1072
}

1073
static int openvzProbe(void)
1074
{
1075 1076 1077 1078 1079
    if (geteuid() == 0 &&
        virFileExists("/proc/vz"))
        return 1;

    return 0;
1080 1081
}

1082
static virDrvOpenStatus openvzOpen(virConnectPtr conn,
1083 1084
                                   virConnectAuthPtr auth ATTRIBUTE_UNUSED,
                                   int flags ATTRIBUTE_UNUSED)
1085
{
1086
    struct openvz_driver *driver;
1087
    if (!openvzProbe())
1088
        return VIR_DRV_OPEN_DECLINED;
1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099

    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")) {
1100 1101 1102 1103
        return VIR_DRV_OPEN_DECLINED;
    }

    if (VIR_ALLOC(driver) < 0) {
1104
        virReportOOMError(conn);
1105 1106 1107 1108 1109
        return VIR_DRV_OPEN_ERROR;
    }

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

1111 1112
    if (openvzLoadDomains(driver) < 0)
        goto cleanup;
1113

1114 1115 1116
    if (openvzExtractVersion(conn, driver) < 0)
        goto cleanup;

1117
    conn->privateData = driver;
1118

1119
    return VIR_DRV_OPEN_SUCCESS;
1120

1121 1122 1123
cleanup:
    openvzFreeDriver(driver);
    return VIR_DRV_OPEN_ERROR;
1124
};
1125 1126

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

1129
    openvzFreeDriver(driver);
1130 1131 1132 1133 1134 1135 1136 1137 1138
    conn->privateData = NULL;

    return 0;
}

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

1139 1140 1141 1142 1143
static int openvzGetNodeInfo(virConnectPtr conn,
                             virNodeInfoPtr nodeinfo) {
    return virNodeInfoPopulate(conn, nodeinfo);
}

1144
static char *openvzGetCapabilities(virConnectPtr conn) {
1145 1146 1147
    struct openvz_driver *driver = conn->privateData;
    char *ret;

1148
    openvzDriverLock(driver);
1149
    ret = virCapabilitiesFormatXML(driver->caps);
1150
    openvzDriverUnlock(driver);
1151

1152
    return ret;
1153 1154
}

1155 1156
static int openvzListDomains(virConnectPtr conn, int *ids, int nids) {
    int got = 0;
1157 1158
    int veid;
    pid_t pid;
1159 1160
    int outfd = -1;
    int errfd = -1;
1161 1162
    int ret;
    char buf[32];
1163
    char *endptr;
1164
    const char *cmd[] = {VZLIST, "-ovpsid", "-H" , NULL};
1165

1166 1167
    ret = virExec(conn, cmd, NULL, NULL,
                  &pid, -1, &outfd, &errfd, VIR_EXEC_NONE);
1168
    if(ret == -1) {
D
Daniel Veillard 已提交
1169
        openvzError(conn, VIR_ERR_INTERNAL_ERROR,
1170
               _("Could not exec %s"), VZLIST);
D
Daniel P. Berrange 已提交
1171
        return -1;
1172 1173
    }

1174 1175 1176
    while(got < nids){
        ret = openvz_readline(outfd, buf, 32);
        if(!ret) break;
1177 1178 1179 1180 1181
        if (virStrToLong_i(buf, &endptr, 10, &veid) < 0) {
            openvzError(conn, VIR_ERR_INTERNAL_ERROR,
                    _("Could not parse VPS ID %s"), buf);
            continue;
        }
1182 1183 1184
        ids[got] = veid;
        got ++;
    }
1185
    waitpid(pid, NULL, 0);
1186 1187 1188 1189

    return got;
}

1190
static int openvzNumDomains(virConnectPtr conn) {
1191
    struct openvz_driver *driver = conn->privateData;
1192 1193
    int nactive = 0, i;

1194 1195 1196
    openvzDriverLock(driver);
    for (i = 0 ; i < driver->domains.count ; i++) {
        virDomainObjLock(driver->domains.objs[i]);
1197
        if (virDomainIsActive(driver->domains.objs[i]))
1198
            nactive++;
1199 1200 1201
        virDomainObjUnlock(driver->domains.objs[i]);
    }
    openvzDriverUnlock(driver);
1202

1203
    return nactive;
1204 1205 1206
}

static int openvzListDefinedDomains(virConnectPtr conn,
1207
                                    char **const names, int nnames) {
1208
    int got = 0;
1209 1210
    int veid, outfd = -1, errfd = -1, ret;
    pid_t pid;
1211
    char vpsname[32];
1212
    char buf[32];
1213
    char *endptr;
1214
    const char *cmd[] = {VZLIST, "-ovpsid", "-H", "-S", NULL};
1215 1216

    /* the -S options lists only stopped domains */
1217 1218
    ret = virExec(conn, cmd, NULL, NULL,
                  &pid, -1, &outfd, &errfd, VIR_EXEC_NONE);
1219
    if(ret == -1) {
D
Daniel Veillard 已提交
1220
        openvzError(conn, VIR_ERR_INTERNAL_ERROR,
1221
               _("Could not exec %s"), VZLIST);
D
Daniel P. Berrange 已提交
1222
        return -1;
1223 1224
    }

1225 1226 1227
    while(got < nnames){
        ret = openvz_readline(outfd, buf, 32);
        if(!ret) break;
1228 1229 1230 1231 1232
        if (virStrToLong_i(buf, &endptr, 10, &veid) < 0) {
            openvzError(conn, VIR_ERR_INTERNAL_ERROR,
                    _("Could not parse VPS ID %s"), buf);
            continue;
        }
1233 1234 1235
        snprintf(vpsname, sizeof(vpsname), "%d", veid);
        if (!(names[got] = strdup(vpsname)))
            goto no_memory;
1236 1237
        got ++;
    }
1238
    waitpid(pid, NULL, 0);
1239
    return got;
1240 1241

no_memory:
1242
    virReportOOMError(conn);
1243 1244 1245
    for ( ; got >= 0 ; got--)
        VIR_FREE(names[got]);
    return -1;
1246 1247
}

D
Daniel Veillard 已提交
1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292
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;
}

1293
static int openvzNumDefinedDomains(virConnectPtr conn) {
1294
    struct openvz_driver *driver =  conn->privateData;
1295 1296
    int ninactive = 0, i;

1297 1298 1299
    openvzDriverLock(driver);
    for (i = 0 ; i < driver->domains.count ; i++) {
        virDomainObjLock(driver->domains.objs[i]);
1300
        if (!virDomainIsActive(driver->domains.objs[i]))
1301
            ninactive++;
1302 1303 1304
        virDomainObjUnlock(driver->domains.objs[i]);
    }
    openvzDriverUnlock(driver);
1305

1306
    return ninactive;
1307 1308 1309 1310 1311 1312 1313
}

static virDriver openvzDriver = {
    VIR_DRV_OPENVZ,
    "OPENVZ",
    openvzOpen, /* open */
    openvzClose, /* close */
1314
    NULL, /* supports_feature */
1315
    openvzGetType, /* type */
1316
    openvzGetVersion, /* version */
1317 1318
    NULL, /* hostname */
    NULL, /* uri */
1319
    openvzGetMaxVCPUs, /* getMaxVcpus */
1320
    openvzGetNodeInfo, /* nodeGetInfo */
1321
    openvzGetCapabilities, /* getCapabilities */
1322 1323
    openvzListDomains, /* listDomains */
    openvzNumDomains, /* numOfDomains */
1324
    openvzDomainCreateXML, /* domainCreateXML */
1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340
    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 */
1341
    openvzDomainSetVcpus, /* domainSetVcpus */
1342 1343
    NULL, /* domainPinVcpu */
    NULL, /* domainGetVcpus */
1344
    openvzDomainGetMaxVcpus, /* domainGetMaxVcpus */
1345 1346
    NULL, /* domainGetSecurityLabel */
    NULL, /* nodeGetSecurityModel */
1347
    openvzDomainDumpXML, /* domainDumpXML */
1348 1349 1350
    openvzListDefinedDomains, /* listDomains */
    openvzNumDefinedDomains, /* numOfDomains */
    openvzDomainCreate, /* domainCreate */
1351 1352
    openvzDomainDefineXML, /* domainDefineXML */
    openvzDomainUndefine, /* domainUndefine */
1353 1354
    NULL, /* domainAttachDevice */
    NULL, /* domainDetachDevice */
1355 1356
    openvzDomainGetAutostart, /* domainGetAutostart */
    openvzDomainSetAutostart, /* domainSetAutostart */
1357 1358 1359
    NULL, /* domainGetSchedulerType */
    NULL, /* domainGetSchedulerParameters */
    NULL, /* domainSetSchedulerParameters */
1360 1361 1362 1363 1364
    NULL, /* domainMigratePrepare */
    NULL, /* domainMigratePerform */
    NULL, /* domainMigrateFinish */
    NULL, /* domainBlockStats */
    NULL, /* domainInterfaceStats */
D
Daniel P. Berrange 已提交
1365 1366
    NULL, /* domainBlockPeek */
    NULL, /* domainMemoryPeek */
1367
    NULL, /* nodeGetCellsFreeMemory */
1368
    NULL, /* nodeGetFreeMemory */
1369 1370
    NULL, /* domainEventRegister */
    NULL, /* domainEventDeregister */
D
Daniel Veillard 已提交
1371 1372
    NULL, /* domainMigratePrepare2 */
    NULL, /* domainMigrateFinish2 */
1373 1374 1375
    NULL, /* nodeDeviceAttach */
    NULL, /* nodeDeviceReAttach */
    NULL, /* nodeDeviceReset */
1376 1377 1378 1379 1380 1381
};

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