2007-07-17 13:27:26 +00:00
|
|
|
/*
|
|
|
|
* openvz_driver.c: core driver methods for managing OpenVZ VEs
|
|
|
|
*
|
|
|
|
* Copyright (C) 2006, 2007 Binary Karma
|
|
|
|
* Copyright (C) 2006 Shuveb Hussain
|
2007-09-03 15:37:07 +00:00
|
|
|
* Copyright (C) 2007 Anoop Joe Cyriac
|
2007-07-17 13:27:26 +00:00
|
|
|
*
|
|
|
|
* 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
|
|
|
|
*
|
2008-02-05 19:27:37 +00:00
|
|
|
* Authors:
|
2007-09-03 15:37:07 +00:00
|
|
|
* Shuveb Hussain <shuveb@binarykarma.com>
|
|
|
|
* Anoop Joe Cyriac <anoop@binarykarma.com>
|
|
|
|
*
|
2007-07-17 13:27:26 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#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>
|
|
|
|
|
2008-06-06 11:09:57 +00:00
|
|
|
#include "internal.h"
|
2007-09-03 15:37:07 +00:00
|
|
|
#include "openvz_driver.h"
|
2007-07-17 13:27:26 +00:00
|
|
|
#include "event.h"
|
|
|
|
#include "buf.h"
|
2007-07-19 16:22:40 +00:00
|
|
|
#include "util.h"
|
2007-07-17 13:27:26 +00:00
|
|
|
#include "openvz_conf.h"
|
2007-07-25 23:16:30 +00:00
|
|
|
#include "nodeinfo.h"
|
2008-07-16 14:45:55 +00:00
|
|
|
#include "memory.h"
|
2007-07-17 13:27:26 +00:00
|
|
|
|
2007-09-03 15:37:07 +00:00
|
|
|
#define OPENVZ_MAX_ARG 28
|
|
|
|
#define CMDBUF_LEN 1488
|
|
|
|
#define CMDOP_LEN 288
|
2007-07-17 13:27:26 +00:00
|
|
|
|
2008-07-21 08:08:25 +00:00
|
|
|
static int openvzGetProcessInfo(unsigned long long *cpuTime, int vpsid);
|
2008-08-20 13:44:03 +00:00
|
|
|
static int openvzGetMaxVCPUs(virConnectPtr conn, const char *type);
|
|
|
|
static int openvzDomainGetMaxVcpus(virDomainPtr dom);
|
|
|
|
static int openvzDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus);
|
2008-07-21 08:08:25 +00:00
|
|
|
|
2007-07-17 13:27:26 +00:00
|
|
|
struct openvz_driver ovz_driver;
|
|
|
|
|
2008-08-08 15:43:38 +00:00
|
|
|
static void cmdExecFree(const char *cmdExec[])
|
2007-09-03 15:37:07 +00:00
|
|
|
{
|
|
|
|
int i=-1;
|
|
|
|
while(cmdExec[++i])
|
|
|
|
{
|
2008-07-16 14:45:55 +00:00
|
|
|
VIR_FREE(cmdExec[i]);
|
2007-09-03 15:37:07 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-07-16 14:45:55 +00:00
|
|
|
/* generate arguments to create OpenVZ container
|
|
|
|
return -1 - error
|
|
|
|
0 - OK
|
|
|
|
*/
|
|
|
|
static int openvzDomainDefineCmd(virConnectPtr conn,
|
2008-08-08 15:43:38 +00:00
|
|
|
const char *args[],
|
2008-07-16 14:45:55 +00:00
|
|
|
int maxarg,
|
2008-09-05 14:10:58 +00:00
|
|
|
virDomainDefPtr vmdef)
|
2008-07-16 14:45:55 +00:00
|
|
|
{
|
|
|
|
int narg;
|
|
|
|
|
|
|
|
for (narg = 0; narg < maxarg; narg++)
|
|
|
|
args[narg] = NULL;
|
|
|
|
|
|
|
|
if (vmdef == NULL){
|
|
|
|
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Container is not defined"));
|
|
|
|
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);
|
2008-09-05 14:10:58 +00:00
|
|
|
|
|
|
|
if (vmdef->fss) {
|
|
|
|
if (vmdef->fss->type != VIR_DOMAIN_FS_TYPE_TEMPLATE) {
|
|
|
|
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("only filesystem templates are supported"));
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (vmdef->fss->next) {
|
|
|
|
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
"%s", _("only one filesystem supported"));
|
|
|
|
return -1;
|
|
|
|
}
|
2008-07-16 14:45:55 +00:00
|
|
|
|
|
|
|
ADD_ARG_LIT("--ostemplate");
|
2008-09-05 14:10:58 +00:00
|
|
|
ADD_ARG_LIT(vmdef->fss->src);
|
2008-07-16 14:45:55 +00:00
|
|
|
}
|
2008-09-05 14:10:58 +00:00
|
|
|
#if 0
|
2008-07-16 14:45:55 +00:00
|
|
|
if ((vmdef->profile && *(vmdef->profile))) {
|
|
|
|
ADD_ARG_LIT("--config");
|
|
|
|
ADD_ARG_LIT(vmdef->profile);
|
|
|
|
}
|
2008-09-05 14:10:58 +00:00
|
|
|
#endif
|
2008-07-16 14:45:55 +00:00
|
|
|
|
|
|
|
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
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-07-17 13:27:26 +00:00
|
|
|
static virDomainPtr openvzDomainLookupByID(virConnectPtr conn,
|
2008-09-05 14:10:58 +00:00
|
|
|
int id) {
|
2007-07-17 13:27:26 +00:00
|
|
|
struct openvz_driver *driver = (struct openvz_driver *)conn->privateData;
|
2008-09-05 14:10:58 +00:00
|
|
|
virDomainObjPtr vm;
|
2007-07-17 13:27:26 +00:00
|
|
|
virDomainPtr dom;
|
|
|
|
|
2008-09-05 14:10:58 +00:00
|
|
|
vm = virDomainFindByID(driver->domains, id);
|
2008-07-16 15:27:00 +00:00
|
|
|
|
2007-07-17 13:27:26 +00:00
|
|
|
if (!vm) {
|
2008-07-16 15:27:00 +00:00
|
|
|
openvzError(conn, VIR_ERR_NO_DOMAIN, NULL);
|
2007-07-17 13:27:26 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2008-09-05 14:10:58 +00:00
|
|
|
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
|
|
|
|
if (!dom)
|
2007-07-17 13:27:26 +00:00
|
|
|
return NULL;
|
|
|
|
|
2008-09-05 14:10:58 +00:00
|
|
|
dom->id = vm->def->id;
|
2007-07-17 13:27:26 +00:00
|
|
|
return dom;
|
|
|
|
}
|
|
|
|
|
2008-09-05 14:10:58 +00:00
|
|
|
static char *openvzGetOSType(virDomainPtr dom)
|
2007-07-17 13:27:26 +00:00
|
|
|
{
|
2008-09-05 14:10:58 +00:00
|
|
|
struct openvz_driver *driver = (struct openvz_driver *)dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
|
|
|
|
char *ret;
|
|
|
|
|
|
|
|
if (!vm) {
|
|
|
|
openvzError(dom->conn, VIR_ERR_NO_DOMAIN, NULL);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(ret = strdup(vm->def->os.type)))
|
|
|
|
openvzError(dom->conn, VIR_ERR_NO_MEMORY, NULL);
|
|
|
|
|
|
|
|
return ret;
|
2007-07-17 13:27:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static virDomainPtr openvzDomainLookupByUUID(virConnectPtr conn,
|
2008-09-05 14:10:58 +00:00
|
|
|
const unsigned char *uuid) {
|
2007-07-17 13:27:26 +00:00
|
|
|
struct openvz_driver *driver = (struct openvz_driver *)conn->privateData;
|
2008-09-05 14:10:58 +00:00
|
|
|
virDomainObjPtr vm = virDomainFindByUUID(driver->domains, uuid);
|
2007-07-17 13:27:26 +00:00
|
|
|
virDomainPtr dom;
|
|
|
|
|
|
|
|
if (!vm) {
|
2008-07-16 15:27:00 +00:00
|
|
|
openvzError(conn, VIR_ERR_NO_DOMAIN, NULL);
|
2007-07-17 13:27:26 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2008-09-05 14:10:58 +00:00
|
|
|
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
|
|
|
|
if (!dom)
|
2007-07-17 13:27:26 +00:00
|
|
|
return NULL;
|
|
|
|
|
2008-09-05 14:10:58 +00:00
|
|
|
dom->id = vm->def->id;
|
2007-07-17 13:27:26 +00:00
|
|
|
return dom;
|
|
|
|
}
|
|
|
|
|
|
|
|
static virDomainPtr openvzDomainLookupByName(virConnectPtr conn,
|
|
|
|
const char *name) {
|
|
|
|
struct openvz_driver *driver = (struct openvz_driver *)conn->privateData;
|
2008-09-05 14:10:58 +00:00
|
|
|
virDomainObjPtr vm = virDomainFindByName(driver->domains, name);
|
2007-07-17 13:27:26 +00:00
|
|
|
virDomainPtr dom;
|
|
|
|
|
|
|
|
if (!vm) {
|
2008-07-16 15:27:00 +00:00
|
|
|
openvzError(conn, VIR_ERR_NO_DOMAIN, NULL);
|
2007-07-17 13:27:26 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2008-09-05 14:10:58 +00:00
|
|
|
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
|
|
|
|
if (!dom)
|
2007-07-17 13:27:26 +00:00
|
|
|
return NULL;
|
2008-09-05 14:10:58 +00:00
|
|
|
|
|
|
|
dom->id = vm->def->id;
|
2007-07-17 13:27:26 +00:00
|
|
|
return dom;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int openvzDomainGetInfo(virDomainPtr dom,
|
2008-09-05 14:10:58 +00:00
|
|
|
virDomainInfoPtr info) {
|
2007-07-17 13:27:26 +00:00
|
|
|
struct openvz_driver *driver = (struct openvz_driver *)dom->conn->privateData;
|
2008-09-05 14:10:58 +00:00
|
|
|
virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
|
2007-09-03 15:37:07 +00:00
|
|
|
|
2007-07-17 13:27:26 +00:00
|
|
|
if (!vm) {
|
2008-07-10 12:21:09 +00:00
|
|
|
openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN,
|
2008-09-05 14:10:58 +00:00
|
|
|
_("no domain with matching uuid"));
|
2007-07-17 13:27:26 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2008-09-05 14:10:58 +00:00
|
|
|
info->state = vm->state;
|
|
|
|
|
|
|
|
if (!virDomainIsActive(vm)) {
|
2008-07-21 08:08:25 +00:00
|
|
|
info->cpuTime = 0;
|
|
|
|
} else {
|
|
|
|
if (openvzGetProcessInfo(&(info->cpuTime), dom->id) < 0) {
|
|
|
|
openvzError(dom->conn, VIR_ERR_OPERATION_FAILED,
|
2008-09-05 14:10:58 +00:00
|
|
|
_("cannot read cputime for domain %d"), dom->id);
|
2008-07-21 08:08:25 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-09-05 14:10:58 +00:00
|
|
|
info->maxMem = vm->def->maxmem;
|
|
|
|
info->memory = vm->def->memory;
|
|
|
|
info->nrVirtCpu = vm->def->vcpus;
|
2007-07-17 13:27:26 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-09-05 14:10:58 +00:00
|
|
|
static char *openvzDomainDumpXML(virDomainPtr dom, int flags) {
|
|
|
|
struct openvz_driver *driver = (struct openvz_driver *)dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
|
|
|
|
|
2007-07-17 13:27:26 +00:00
|
|
|
if (!vm) {
|
2008-07-10 12:21:09 +00:00
|
|
|
openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN,
|
2008-09-05 14:10:58 +00:00
|
|
|
_("no domain with matching uuid"));
|
|
|
|
return NULL;
|
2007-07-17 13:27:26 +00:00
|
|
|
}
|
2008-09-05 14:10:58 +00:00
|
|
|
|
|
|
|
return virDomainDefFormat(dom->conn, vm->def, flags);
|
|
|
|
}
|
2008-02-05 19:27:37 +00:00
|
|
|
|
2008-09-05 14:10:58 +00:00
|
|
|
|
|
|
|
|
|
|
|
static int openvzDomainShutdown(virDomainPtr dom) {
|
|
|
|
struct openvz_driver *driver = (struct openvz_driver *)dom->conn->privateData;
|
|
|
|
virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
|
|
|
|
const char *prog[] = {VZCTL, "--quiet", "stop", vm->def->name, NULL};
|
|
|
|
|
|
|
|
if (!vm) {
|
|
|
|
openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN,
|
|
|
|
_("no domain with matching uuid"));
|
2007-07-17 13:27:26 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2008-09-05 14:10:58 +00:00
|
|
|
|
|
|
|
if (vm->state != VIR_DOMAIN_RUNNING) {
|
2008-07-10 12:21:09 +00:00
|
|
|
openvzError(dom->conn, VIR_ERR_INTERNAL_ERROR,
|
2008-09-05 14:10:58 +00:00
|
|
|
_("domain is not in running state"));
|
2007-07-17 13:27:26 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2008-09-05 14:10:58 +00:00
|
|
|
|
|
|
|
if (virRun(dom->conn, prog, NULL) < 0)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
vm->def->id = -1;
|
|
|
|
vm->state = VIR_DOMAIN_SHUTOFF;
|
2008-02-05 19:27:37 +00:00
|
|
|
|
2008-07-16 14:45:55 +00:00
|
|
|
return 0;
|
2007-07-17 13:27:26 +00:00
|
|
|
}
|
|
|
|
|
2007-09-03 16:30:00 +00:00
|
|
|
static int openvzDomainReboot(virDomainPtr dom,
|
|
|
|
unsigned int flags ATTRIBUTE_UNUSED) {
|
2007-07-17 13:27:26 +00:00
|
|
|
struct openvz_driver *driver = (struct openvz_driver *)dom->conn->privateData;
|
2008-09-05 14:10:58 +00:00
|
|
|
virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
|
|
|
|
const char *prog[] = {VZCTL, "--quiet", "restart", vm->def->name, NULL};
|
2007-07-17 13:27:26 +00:00
|
|
|
|
|
|
|
if (!vm) {
|
2008-07-10 12:21:09 +00:00
|
|
|
openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN,
|
2008-09-05 14:10:58 +00:00
|
|
|
_("no domain with matching uuid"));
|
2007-07-17 13:27:26 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2008-02-05 19:27:37 +00:00
|
|
|
|
2008-09-05 14:10:58 +00:00
|
|
|
if (vm->state != VIR_DOMAIN_RUNNING) {
|
|
|
|
openvzError(dom->conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("domain is not in running state"));
|
2007-07-17 13:27:26 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2008-02-05 19:27:37 +00:00
|
|
|
|
2008-09-05 14:10:58 +00:00
|
|
|
if (virRun(dom->conn, prog, NULL) < 0)
|
2007-07-17 13:27:26 +00:00
|
|
|
return -1;
|
2008-02-05 19:27:37 +00:00
|
|
|
|
2008-07-16 14:45:55 +00:00
|
|
|
return 0;
|
2007-07-17 13:27:26 +00:00
|
|
|
}
|
|
|
|
|
2008-07-28 14:06:54 +00:00
|
|
|
static int
|
|
|
|
openvzDomainSetNetwork(virConnectPtr conn, const char *vpsid,
|
|
|
|
virDomainNetDefPtr net)
|
|
|
|
{
|
|
|
|
int rc = 0, narg;
|
2008-08-08 15:43:38 +00:00
|
|
|
const char *prog[OPENVZ_MAX_ARG];
|
2008-07-28 14:06:54 +00:00
|
|
|
char *mac = NULL;
|
|
|
|
|
|
|
|
#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,
|
|
|
|
_("Container ID is not specified"));
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (openvzCheckEmptyMac(net->mac) > 0)
|
|
|
|
mac = openvzMacToString(net->mac);
|
|
|
|
|
|
|
|
if (net->type == VIR_DOMAIN_NET_TYPE_BRIDGE &&
|
|
|
|
net->data.bridge.brname != NULL) {
|
|
|
|
char opt[1024];
|
|
|
|
//--netif_add ifname[,mac,host_ifname,host_mac]
|
|
|
|
ADD_ARG_LIT("--netif_add") ;
|
|
|
|
strncpy(opt, net->data.bridge.brname, 256);
|
|
|
|
if (mac != NULL) {
|
|
|
|
strcat(opt, ",");
|
|
|
|
strcat(opt, mac);
|
|
|
|
}
|
|
|
|
ADD_ARG_LIT(opt) ;
|
|
|
|
}else if (net->type == VIR_DOMAIN_NET_TYPE_ETHERNET &&
|
|
|
|
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");
|
2008-08-08 15:43:38 +00:00
|
|
|
if (virRun(conn, prog, NULL) < 0) {
|
2008-07-28 14:06:54 +00:00
|
|
|
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Could not exec %s"), VZCTL);
|
|
|
|
rc = -1;
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (net->next != NULL)
|
|
|
|
if (openvzDomainSetNetwork(conn, vpsid, net->next) < 0) {
|
|
|
|
rc = -1;
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
|
|
|
exit:
|
|
|
|
cmdExecFree(prog);
|
|
|
|
VIR_FREE(mac);
|
|
|
|
return rc;
|
|
|
|
|
|
|
|
no_memory:
|
|
|
|
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Could not put argument to %s"), VZCTL);
|
|
|
|
cmdExecFree(prog);
|
|
|
|
VIR_FREE(mac);
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
#undef ADD_ARG_LIT
|
|
|
|
}
|
|
|
|
|
2007-09-03 15:37:07 +00:00
|
|
|
static virDomainPtr
|
|
|
|
openvzDomainDefineXML(virConnectPtr conn, const char *xml)
|
|
|
|
{
|
|
|
|
struct openvz_driver *driver = (struct openvz_driver *) conn->privateData;
|
2008-09-05 14:10:58 +00:00
|
|
|
virDomainDefPtr vmdef = NULL;
|
|
|
|
virDomainObjPtr vm = NULL;
|
2008-07-16 14:45:55 +00:00
|
|
|
virDomainPtr dom = NULL;
|
2008-08-08 15:43:38 +00:00
|
|
|
const char *prog[OPENVZ_MAX_ARG];
|
2008-07-16 14:45:55 +00:00
|
|
|
prog[0] = NULL;
|
2007-09-03 15:37:07 +00:00
|
|
|
|
2008-09-05 14:10:58 +00:00
|
|
|
if ((vmdef = virDomainDefParseString(conn, driver->caps, xml)) == NULL)
|
2008-07-16 14:45:55 +00:00
|
|
|
return NULL;
|
2007-09-03 15:37:07 +00:00
|
|
|
|
2008-09-05 14:10:58 +00:00
|
|
|
if (vmdef->os.init == NULL &&
|
|
|
|
!(vmdef->os.init = strdup("/sbin/init"))) {
|
|
|
|
virDomainDefFree(vmdef);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
vm = virDomainFindByName(driver->domains, vmdef->name);
|
2007-09-03 15:37:07 +00:00
|
|
|
if (vm) {
|
2008-09-05 14:10:58 +00:00
|
|
|
virDomainDefFree(vmdef);
|
2008-03-27 14:00:28 +00:00
|
|
|
openvzLog(OPENVZ_ERR, _("Already an OPENVZ VM active with the id '%s'"),
|
|
|
|
vmdef->name);
|
2008-07-16 14:45:55 +00:00
|
|
|
return NULL;
|
2007-09-03 15:37:07 +00:00
|
|
|
}
|
2008-09-05 14:10:58 +00:00
|
|
|
if (!(vm = virDomainAssignDef(conn, &driver->domains, vmdef))) {
|
|
|
|
virDomainDefFree(vmdef);
|
|
|
|
return NULL;
|
2007-09-03 15:37:07 +00:00
|
|
|
}
|
|
|
|
|
2008-07-16 14:45:55 +00:00
|
|
|
if (openvzDomainDefineCmd(conn, prog, OPENVZ_MAX_ARG, vmdef) < 0) {
|
|
|
|
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Error creating command for container"));
|
|
|
|
goto exit;
|
2007-09-03 15:37:07 +00:00
|
|
|
}
|
|
|
|
|
2008-07-28 14:06:54 +00:00
|
|
|
//TODO: set quota
|
|
|
|
|
2008-08-08 15:43:38 +00:00
|
|
|
if (virRun(conn, prog, NULL) < 0) {
|
2008-07-10 12:21:09 +00:00
|
|
|
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
2008-07-09 11:55:27 +00:00
|
|
|
_("Could not exec %s"), VZCTL);
|
2008-07-16 14:45:55 +00:00
|
|
|
goto exit;
|
2007-09-03 15:37:07 +00:00
|
|
|
}
|
2008-02-05 19:27:37 +00:00
|
|
|
|
2008-08-05 10:53:05 +00:00
|
|
|
if (openvzSetDefinedUUID(strtoI(vmdef->name), vmdef->uuid) < 0) {
|
|
|
|
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Could not set UUID"));
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
2008-09-05 14:10:58 +00:00
|
|
|
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
|
2007-09-03 15:37:07 +00:00
|
|
|
if (dom)
|
2008-09-05 14:10:58 +00:00
|
|
|
dom->id = -1;
|
2008-07-28 14:06:54 +00:00
|
|
|
|
2008-09-05 14:10:58 +00:00
|
|
|
if (openvzDomainSetNetwork(conn, vmdef->name, vmdef->nets) < 0) {
|
2008-07-28 14:06:54 +00:00
|
|
|
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Could not configure network"));
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
2008-08-20 13:44:03 +00:00
|
|
|
if (vmdef->vcpus > 0) {
|
|
|
|
if (openvzDomainSetVcpus(dom, vmdef->vcpus) < 0) {
|
|
|
|
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Could not set number of virtual cpu"));
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-07-28 14:06:54 +00:00
|
|
|
exit:
|
2008-07-16 14:45:55 +00:00
|
|
|
cmdExecFree(prog);
|
2007-09-03 15:37:07 +00:00
|
|
|
return dom;
|
|
|
|
}
|
|
|
|
|
|
|
|
static virDomainPtr
|
|
|
|
openvzDomainCreateLinux(virConnectPtr conn, const char *xml,
|
|
|
|
unsigned int flags ATTRIBUTE_UNUSED)
|
|
|
|
{
|
2008-09-05 14:10:58 +00:00
|
|
|
virDomainDefPtr vmdef = NULL;
|
|
|
|
virDomainObjPtr vm = NULL;
|
2008-07-16 14:45:55 +00:00
|
|
|
virDomainPtr dom = NULL;
|
2007-09-03 15:37:07 +00:00
|
|
|
struct openvz_driver *driver = (struct openvz_driver *) conn->privateData;
|
2008-07-16 14:45:55 +00:00
|
|
|
const char *progstart[] = {VZCTL, "--quiet", "start", NULL, NULL};
|
2008-08-08 15:43:38 +00:00
|
|
|
const char *progcreate[OPENVZ_MAX_ARG];
|
2008-07-16 14:45:55 +00:00
|
|
|
progcreate[0] = NULL;
|
2007-09-03 15:37:07 +00:00
|
|
|
|
2008-09-05 14:10:58 +00:00
|
|
|
if ((vmdef = virDomainDefParseString(conn, driver->caps, xml)) == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
if (vmdef->os.init == NULL &&
|
|
|
|
!(vmdef->os.init = strdup("/sbin/init"))) {
|
|
|
|
virDomainDefFree(vmdef);
|
2007-09-03 15:37:07 +00:00
|
|
|
return NULL;
|
2008-09-05 14:10:58 +00:00
|
|
|
}
|
2007-09-03 15:37:07 +00:00
|
|
|
|
2008-09-05 14:10:58 +00:00
|
|
|
vm = virDomainFindByName(driver->domains, vmdef->name);
|
2007-09-03 15:37:07 +00:00
|
|
|
if (vm) {
|
2008-09-05 14:10:58 +00:00
|
|
|
virDomainDefFree(vmdef);
|
2008-03-27 14:00:28 +00:00
|
|
|
openvzLog(OPENVZ_ERR,
|
|
|
|
_("Already an OPENVZ VM defined with the id '%d'"),
|
2007-09-03 15:37:07 +00:00
|
|
|
strtoI(vmdef->name));
|
|
|
|
return NULL;
|
|
|
|
}
|
2008-09-05 14:10:58 +00:00
|
|
|
if (!(vm = virDomainAssignDef(conn, &driver->domains, vmdef))) {
|
|
|
|
virDomainDefFree(vmdef);
|
2007-09-03 15:37:07 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2008-07-16 14:45:55 +00:00
|
|
|
if (openvzDomainDefineCmd(conn, progcreate, OPENVZ_MAX_ARG, vmdef) < 0) {
|
|
|
|
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Error creating command for container"));
|
|
|
|
goto exit;
|
2007-09-03 15:37:07 +00:00
|
|
|
}
|
|
|
|
|
2008-08-08 15:43:38 +00:00
|
|
|
if (virRun(conn, progcreate, NULL) < 0) {
|
2008-07-10 12:21:09 +00:00
|
|
|
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
2008-07-09 11:55:27 +00:00
|
|
|
_("Could not exec %s"), VZCTL);
|
2008-07-16 14:45:55 +00:00
|
|
|
goto exit;
|
2007-09-03 15:37:07 +00:00
|
|
|
}
|
2008-02-05 19:27:37 +00:00
|
|
|
|
2008-08-05 10:53:05 +00:00
|
|
|
if (openvzSetDefinedUUID(strtoI(vmdef->name), vmdef->uuid) < 0) {
|
|
|
|
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Could not set UUID"));
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
2008-09-05 14:10:58 +00:00
|
|
|
if (openvzDomainSetNetwork(conn, vmdef->name, vmdef->nets) < 0) {
|
2008-07-28 14:06:54 +00:00
|
|
|
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Could not configure network"));
|
|
|
|
goto exit;
|
|
|
|
}
|
|
|
|
|
2008-07-16 14:45:55 +00:00
|
|
|
progstart[3] = vmdef->name;
|
2007-09-03 15:37:07 +00:00
|
|
|
|
2008-08-08 15:43:38 +00:00
|
|
|
if (virRun(conn, progstart, NULL) < 0) {
|
2008-07-10 12:21:09 +00:00
|
|
|
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
2008-07-09 11:55:27 +00:00
|
|
|
_("Could not exec %s"), VZCTL);
|
2008-07-16 14:45:55 +00:00
|
|
|
goto exit;
|
2007-09-03 15:37:07 +00:00
|
|
|
}
|
2008-02-05 19:27:37 +00:00
|
|
|
|
2008-09-05 14:10:58 +00:00
|
|
|
vm->pid = strtoI(vmdef->name);
|
|
|
|
vm->def->id = vm->pid;
|
|
|
|
vm->state = VIR_DOMAIN_RUNNING;
|
|
|
|
|
|
|
|
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
|
2007-09-03 15:37:07 +00:00
|
|
|
if (dom)
|
2008-09-05 14:10:58 +00:00
|
|
|
dom->id = vm->def->id;
|
2008-08-20 13:44:03 +00:00
|
|
|
|
|
|
|
if (vmdef->vcpus > 0) {
|
|
|
|
if (openvzDomainSetVcpus(dom, vmdef->vcpus) < 0) {
|
|
|
|
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
2008-09-05 14:10:58 +00:00
|
|
|
_("Could not set number of virtual cpu"));
|
|
|
|
goto exit;
|
2008-08-20 13:44:03 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-07-16 14:45:55 +00:00
|
|
|
exit:
|
|
|
|
cmdExecFree(progcreate);
|
2007-09-03 15:37:07 +00:00
|
|
|
return dom;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
openvzDomainCreate(virDomainPtr dom)
|
|
|
|
{
|
2007-07-17 13:27:26 +00:00
|
|
|
struct openvz_driver *driver = (struct openvz_driver *)dom->conn->privateData;
|
2008-09-05 14:10:58 +00:00
|
|
|
virDomainObjPtr vm = virDomainFindByName(driver->domains, dom->name);
|
|
|
|
const char *prog[] = {VZCTL, "--quiet", "start", vm->def->name, NULL };
|
2007-07-17 13:27:26 +00:00
|
|
|
|
|
|
|
if (!vm) {
|
2008-07-10 12:21:09 +00:00
|
|
|
openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN,
|
error: mark most string arguments for translation
Also mark some arguments to __virRaiseError.
* Makefile.maint (msg_gen_function): Add error.
* po/POTFILES.in: Add src/openvz_conf.c and src/openvz_driver.c.
* src/openvz_conf.c (openvzParseXML, openvzGetVPSInfo): Mark strings.
* src/openvz_driver.c (openvzDomainLookupByID): Likewise.
(openvzDomainLookupByUUID, openvzDomainLookupByName): Likewise.
(openvzDomainGetInfo, openvzDomainShutdown, openvzDomainReboot)
(openvzDomainCreate, openvzDomainUndefine): Likewise.
* src/remote_internal.c (check_cert_file): Likewise.
(negotiate_gnutls_on_connection, verify_certificate): Likewise.
(remoteAuthenticate, addrToString, remoteAuthSASL): Likewise.
(remoteAuthPolkit, call, really_read_buf): Likewise.
2008-03-27 13:58:56 +00:00
|
|
|
_("no domain with matching id"));
|
2007-07-17 13:27:26 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2008-02-05 19:27:37 +00:00
|
|
|
|
2008-09-05 14:10:58 +00:00
|
|
|
if (vm->state != VIR_DOMAIN_SHUTOFF) {
|
2008-07-10 12:21:09 +00:00
|
|
|
openvzError(dom->conn, VIR_ERR_OPERATION_DENIED,
|
error: mark most string arguments for translation
Also mark some arguments to __virRaiseError.
* Makefile.maint (msg_gen_function): Add error.
* po/POTFILES.in: Add src/openvz_conf.c and src/openvz_driver.c.
* src/openvz_conf.c (openvzParseXML, openvzGetVPSInfo): Mark strings.
* src/openvz_driver.c (openvzDomainLookupByID): Likewise.
(openvzDomainLookupByUUID, openvzDomainLookupByName): Likewise.
(openvzDomainGetInfo, openvzDomainShutdown, openvzDomainReboot)
(openvzDomainCreate, openvzDomainUndefine): Likewise.
* src/remote_internal.c (check_cert_file): Likewise.
(negotiate_gnutls_on_connection, verify_certificate): Likewise.
(remoteAuthenticate, addrToString, remoteAuthSASL): Likewise.
(remoteAuthPolkit, call, really_read_buf): Likewise.
2008-03-27 13:58:56 +00:00
|
|
|
_("domain is not in shutoff state"));
|
2007-07-17 13:27:26 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2008-08-08 15:43:38 +00:00
|
|
|
if (virRun(dom->conn, prog, NULL) < 0) {
|
2008-07-10 12:21:09 +00:00
|
|
|
openvzError(dom->conn, VIR_ERR_INTERNAL_ERROR,
|
2008-07-09 11:55:27 +00:00
|
|
|
_("Could not exec %s"), VZCTL);
|
2007-07-17 13:27:26 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2008-02-05 19:27:37 +00:00
|
|
|
|
2008-09-05 14:10:58 +00:00
|
|
|
vm->pid = strtoI(vm->def->name);
|
|
|
|
vm->def->id = vm->pid;
|
|
|
|
vm->state = VIR_DOMAIN_RUNNING;
|
2008-02-05 19:27:37 +00:00
|
|
|
|
2008-07-16 14:45:55 +00:00
|
|
|
return 0;
|
2007-09-03 15:37:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
openvzDomainUndefine(virDomainPtr dom)
|
|
|
|
{
|
|
|
|
virConnectPtr conn= dom->conn;
|
|
|
|
struct openvz_driver *driver = (struct openvz_driver *) conn->privateData;
|
2008-09-05 14:10:58 +00:00
|
|
|
virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
|
|
|
|
const char *prog[] = { VZCTL, "--quiet", "destroy", vm->def->name, NULL };
|
2007-09-03 15:37:07 +00:00
|
|
|
|
|
|
|
if (!vm) {
|
2008-07-10 12:21:09 +00:00
|
|
|
openvzError(conn, VIR_ERR_INVALID_DOMAIN, _("no domain with matching uuid"));
|
2007-09-03 15:37:07 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2007-07-17 13:27:26 +00:00
|
|
|
|
2008-09-05 14:10:58 +00:00
|
|
|
if (virDomainIsActive(vm)) {
|
2008-07-10 12:21:09 +00:00
|
|
|
openvzError(conn, VIR_ERR_INTERNAL_ERROR, _("cannot delete active domain"));
|
2007-09-03 15:37:07 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2008-02-05 19:27:37 +00:00
|
|
|
|
2008-08-08 15:43:38 +00:00
|
|
|
if (virRun(conn, prog, NULL) < 0) {
|
2008-07-10 12:21:09 +00:00
|
|
|
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
2008-07-09 11:55:27 +00:00
|
|
|
_("Could not exec %s"), VZCTL);
|
2007-09-03 15:37:07 +00:00
|
|
|
return -1;
|
|
|
|
}
|
2008-02-05 19:27:37 +00:00
|
|
|
|
2008-09-05 14:10:58 +00:00
|
|
|
virDomainRemoveInactive(&driver->domains, vm);
|
|
|
|
|
2008-07-16 14:45:55 +00:00
|
|
|
return 0;
|
2007-07-17 13:27:26 +00:00
|
|
|
}
|
|
|
|
|
2008-07-10 07:52:14 +00:00
|
|
|
static int
|
|
|
|
openvzDomainSetAutostart(virDomainPtr dom, int autostart)
|
|
|
|
{
|
|
|
|
virConnectPtr conn= dom->conn;
|
|
|
|
struct openvz_driver *driver = (struct openvz_driver *) conn->privateData;
|
2008-09-05 14:10:58 +00:00
|
|
|
virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
|
|
|
|
const char *prog[] = { VZCTL, "--quiet", "set", vm->def->name,
|
2008-07-10 12:21:09 +00:00
|
|
|
"--onboot", autostart ? "yes" : "no",
|
2008-07-10 07:52:14 +00:00
|
|
|
"--save", NULL };
|
|
|
|
|
|
|
|
if (!vm) {
|
2008-07-10 12:21:09 +00:00
|
|
|
openvzError(conn, VIR_ERR_INVALID_DOMAIN, _("no domain with matching uuid"));
|
2008-07-10 07:52:14 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2008-08-08 15:43:38 +00:00
|
|
|
if (virRun(conn, prog, NULL) < 0) {
|
2008-07-10 12:21:09 +00:00
|
|
|
openvzError(conn, VIR_ERR_INTERNAL_ERROR, _("Could not exec %s"), VZCTL);
|
2008-07-10 07:52:14 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
|
|
|
openvzDomainGetAutostart(virDomainPtr dom, int *autostart)
|
|
|
|
{
|
|
|
|
virConnectPtr conn= dom->conn;
|
|
|
|
struct openvz_driver *driver = (struct openvz_driver *) conn->privateData;
|
2008-09-05 14:10:58 +00:00
|
|
|
virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
|
2008-07-10 07:52:14 +00:00
|
|
|
char value[1024];
|
|
|
|
|
|
|
|
if (!vm) {
|
2008-07-10 12:21:09 +00:00
|
|
|
openvzError(conn, VIR_ERR_INVALID_DOMAIN, _("no domain with matching uuid"));
|
2008-07-10 07:52:14 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2008-09-05 14:10:58 +00:00
|
|
|
if (openvzReadConfigParam(strtoI(vm->def->name), "ONBOOT", value, sizeof(value)) < 0) {
|
2008-08-15 01:41:49 +00:00
|
|
|
openvzError(conn, VIR_ERR_INTERNAL_ERROR, _("Could not read container config"));
|
2008-07-10 07:52:14 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
*autostart = 0;
|
|
|
|
if (STREQ(value,"yes"))
|
2008-07-10 12:21:09 +00:00
|
|
|
*autostart = 1;
|
2008-07-10 07:52:14 +00:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-08-20 13:44:03 +00:00
|
|
|
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");
|
|
|
|
}
|
|
|
|
|
|
|
|
static int openvzDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus) {
|
|
|
|
virConnectPtr conn= dom->conn;
|
|
|
|
struct openvz_driver *driver = (struct openvz_driver *) conn->privateData;
|
2008-09-05 14:10:58 +00:00
|
|
|
virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
|
2008-08-20 13:44:03 +00:00
|
|
|
char str_vcpus[32];
|
2008-09-05 14:10:58 +00:00
|
|
|
const char *prog[] = { VZCTL, "--quiet", "set", vm->def->name,
|
2008-08-20 13:44:03 +00:00
|
|
|
"--cpus", str_vcpus, "--save", NULL };
|
|
|
|
snprintf(str_vcpus, 31, "%d", nvcpus);
|
|
|
|
str_vcpus[31] = '\0';
|
|
|
|
|
|
|
|
if (nvcpus <= 0) {
|
|
|
|
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
2008-09-05 14:10:58 +00:00
|
|
|
_("VCPUs should be >= 1"));
|
2008-08-20 13:44:03 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!vm) {
|
|
|
|
openvzError(conn, VIR_ERR_INVALID_DOMAIN,
|
2008-09-05 14:10:58 +00:00
|
|
|
_("no domain with matching uuid"));
|
2008-08-20 13:44:03 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (virRun(conn, prog, NULL) < 0) {
|
|
|
|
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
2008-09-05 14:10:58 +00:00
|
|
|
_("Could not exec %s"), VZCTL);
|
2008-08-20 13:44:03 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2008-09-05 14:10:58 +00:00
|
|
|
vm->def->vcpus = nvcpus;
|
2008-08-20 13:44:03 +00:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2008-02-26 07:05:18 +00:00
|
|
|
static const char *openvzProbe(void)
|
|
|
|
{
|
|
|
|
#ifdef __linux__
|
2008-09-05 14:10:58 +00:00
|
|
|
if ((geteuid() == 0) && (virFileExists("/proc/vz")))
|
2008-07-11 11:09:44 +00:00
|
|
|
return("openvz:///system");
|
2008-02-26 07:05:18 +00:00
|
|
|
#endif
|
|
|
|
return(NULL);
|
|
|
|
}
|
|
|
|
|
2007-07-17 13:27:26 +00:00
|
|
|
static virDrvOpenStatus openvzOpen(virConnectPtr conn,
|
2007-12-26 05:41:05 +00:00
|
|
|
xmlURIPtr uri,
|
|
|
|
virConnectAuthPtr auth ATTRIBUTE_UNUSED,
|
|
|
|
int flags ATTRIBUTE_UNUSED)
|
|
|
|
{
|
2008-09-05 14:10:58 +00:00
|
|
|
struct openvz_driver *driver;
|
2007-12-26 05:41:05 +00:00
|
|
|
/*Just check if the user is root. Nothing really to open for OpenVZ */
|
2008-09-05 14:10:58 +00:00
|
|
|
if (geteuid()) { // OpenVZ tools can only be used by r00t
|
|
|
|
return VIR_DRV_OPEN_DECLINED;
|
|
|
|
} else {
|
|
|
|
if (uri == NULL ||
|
|
|
|
uri->scheme == NULL ||
|
|
|
|
uri->path == NULL ||
|
|
|
|
STRNEQ (uri->scheme, "openvz") ||
|
|
|
|
STRNEQ (uri->path, "/system"))
|
|
|
|
return VIR_DRV_OPEN_DECLINED;
|
|
|
|
}
|
2007-07-19 16:22:40 +00:00
|
|
|
/* See if we are running an OpenVZ enabled kernel */
|
2008-09-05 14:10:58 +00:00
|
|
|
if(access("/proc/vz/veinfo", F_OK) == -1 ||
|
|
|
|
access("/proc/user_beancounters", F_OK) == -1) {
|
|
|
|
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;
|
2007-07-17 13:27:26 +00:00
|
|
|
|
2008-09-05 14:10:58 +00:00
|
|
|
if (openvzLoadDomains(driver) < 0)
|
|
|
|
goto cleanup;
|
2007-07-17 13:27:26 +00:00
|
|
|
|
2008-09-05 14:10:58 +00:00
|
|
|
conn->privateData = driver;
|
2008-08-27 11:19:45 +00:00
|
|
|
|
2008-09-05 14:10:58 +00:00
|
|
|
return VIR_DRV_OPEN_SUCCESS;
|
2007-07-17 13:27:26 +00:00
|
|
|
|
2008-09-05 14:10:58 +00:00
|
|
|
cleanup:
|
|
|
|
openvzFreeDriver(driver);
|
|
|
|
return VIR_DRV_OPEN_ERROR;
|
2007-12-26 05:41:05 +00:00
|
|
|
};
|
2007-07-17 13:27:26 +00:00
|
|
|
|
|
|
|
static int openvzClose(virConnectPtr conn) {
|
|
|
|
struct openvz_driver *driver = (struct openvz_driver *)conn->privateData;
|
2008-02-05 19:27:37 +00:00
|
|
|
|
2008-09-05 14:10:58 +00:00
|
|
|
openvzFreeDriver(driver);
|
2007-07-17 13:27:26 +00:00
|
|
|
conn->privateData = NULL;
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *openvzGetType(virConnectPtr conn ATTRIBUTE_UNUSED) {
|
|
|
|
return strdup("OpenVZ");
|
|
|
|
}
|
|
|
|
|
2007-07-25 23:16:30 +00:00
|
|
|
static int openvzGetNodeInfo(virConnectPtr conn,
|
|
|
|
virNodeInfoPtr nodeinfo) {
|
|
|
|
return virNodeInfoPopulate(conn, nodeinfo);
|
|
|
|
}
|
|
|
|
|
2008-09-05 14:10:58 +00:00
|
|
|
static char *openvzGetCapabilities(virConnectPtr conn) {
|
|
|
|
struct openvz_driver *driver = (struct openvz_driver *)conn->privateData;
|
|
|
|
|
|
|
|
return virCapabilitiesFormatXML(driver->caps);
|
|
|
|
}
|
|
|
|
|
2007-07-17 13:27:26 +00:00
|
|
|
static int openvzListDomains(virConnectPtr conn, int *ids, int nids) {
|
|
|
|
int got = 0;
|
2008-08-20 09:08:17 +00:00
|
|
|
int veid, pid;
|
|
|
|
int outfd = -1;
|
|
|
|
int errfd = -1;
|
2007-07-19 16:22:40 +00:00
|
|
|
int ret;
|
|
|
|
char buf[32];
|
2008-07-21 13:34:19 +00:00
|
|
|
char *endptr;
|
2007-07-19 16:22:40 +00:00
|
|
|
const char *cmd[] = {VZLIST, "-ovpsid", "-H" , NULL};
|
2007-07-17 13:27:26 +00:00
|
|
|
|
2008-08-27 11:19:45 +00:00
|
|
|
ret = virExec(conn, cmd, NULL, NULL,
|
|
|
|
&pid, -1, &outfd, &errfd, VIR_EXEC_NONE);
|
2007-07-19 16:22:40 +00:00
|
|
|
if(ret == -1) {
|
2008-07-10 12:21:09 +00:00
|
|
|
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
2008-07-09 11:55:27 +00:00
|
|
|
_("Could not exec %s"), VZLIST);
|
2008-07-07 11:48:40 +00:00
|
|
|
return -1;
|
2007-07-17 13:27:26 +00:00
|
|
|
}
|
|
|
|
|
2007-07-19 16:22:40 +00:00
|
|
|
while(got < nids){
|
|
|
|
ret = openvz_readline(outfd, buf, 32);
|
|
|
|
if(!ret) break;
|
2008-07-21 13:34:19 +00:00
|
|
|
if (virStrToLong_i(buf, &endptr, 10, &veid) < 0) {
|
|
|
|
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Could not parse VPS ID %s"), buf);
|
|
|
|
continue;
|
|
|
|
}
|
2007-07-17 13:27:26 +00:00
|
|
|
ids[got] = veid;
|
|
|
|
got ++;
|
|
|
|
}
|
2007-07-19 16:22:40 +00:00
|
|
|
waitpid(pid, NULL, 0);
|
2007-07-17 13:27:26 +00:00
|
|
|
|
|
|
|
return got;
|
|
|
|
}
|
|
|
|
|
2007-09-03 16:30:00 +00:00
|
|
|
static int openvzNumDomains(virConnectPtr conn ATTRIBUTE_UNUSED) {
|
2008-09-05 14:10:58 +00:00
|
|
|
struct openvz_driver *driver = conn->privateData;
|
|
|
|
int nactive = 0;
|
|
|
|
virDomainObjPtr vm = driver->domains;
|
|
|
|
while (vm) {
|
|
|
|
if (virDomainIsActive(vm))
|
|
|
|
nactive++;
|
|
|
|
vm = vm->next;
|
|
|
|
}
|
|
|
|
return nactive;
|
2007-07-17 13:27:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static int openvzListDefinedDomains(virConnectPtr conn,
|
2008-09-05 14:10:58 +00:00
|
|
|
char **const names, int nnames) {
|
2007-07-17 13:27:26 +00:00
|
|
|
int got = 0;
|
2008-08-20 09:08:17 +00:00
|
|
|
int veid, pid, outfd = -1, errfd = -1, ret;
|
2008-09-05 14:10:58 +00:00
|
|
|
char vpsname[32];
|
2007-07-19 16:22:40 +00:00
|
|
|
char buf[32];
|
2008-07-21 13:34:19 +00:00
|
|
|
char *endptr;
|
2007-09-03 15:37:07 +00:00
|
|
|
const char *cmd[] = {VZLIST, "-ovpsid", "-H", "-S", NULL};
|
2007-07-17 13:27:26 +00:00
|
|
|
|
|
|
|
/* the -S options lists only stopped domains */
|
2008-08-27 11:19:45 +00:00
|
|
|
ret = virExec(conn, cmd, NULL, NULL,
|
|
|
|
&pid, -1, &outfd, &errfd, VIR_EXEC_NONE);
|
2007-07-19 16:22:40 +00:00
|
|
|
if(ret == -1) {
|
2008-07-10 12:21:09 +00:00
|
|
|
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
2008-07-09 11:55:27 +00:00
|
|
|
_("Could not exec %s"), VZLIST);
|
2008-07-07 11:48:40 +00:00
|
|
|
return -1;
|
2007-07-17 13:27:26 +00:00
|
|
|
}
|
|
|
|
|
2007-07-19 16:22:40 +00:00
|
|
|
while(got < nnames){
|
|
|
|
ret = openvz_readline(outfd, buf, 32);
|
|
|
|
if(!ret) break;
|
2008-07-21 13:34:19 +00:00
|
|
|
if (virStrToLong_i(buf, &endptr, 10, &veid) < 0) {
|
|
|
|
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
|
|
|
_("Could not parse VPS ID %s"), buf);
|
|
|
|
continue;
|
|
|
|
}
|
2008-09-05 14:10:58 +00:00
|
|
|
snprintf(vpsname, sizeof(vpsname), "%d", veid);
|
|
|
|
if (!(names[got] = strdup(vpsname)))
|
|
|
|
goto no_memory;
|
2007-07-17 13:27:26 +00:00
|
|
|
got ++;
|
|
|
|
}
|
2007-07-19 16:22:40 +00:00
|
|
|
waitpid(pid, NULL, 0);
|
2007-07-17 13:27:26 +00:00
|
|
|
return got;
|
2008-09-05 14:10:58 +00:00
|
|
|
|
|
|
|
no_memory:
|
|
|
|
openvzError(conn, VIR_ERR_NO_MEMORY, NULL);
|
|
|
|
for ( ; got >= 0 ; got--)
|
|
|
|
VIR_FREE(names[got]);
|
|
|
|
return -1;
|
2007-07-17 13:27:26 +00:00
|
|
|
}
|
|
|
|
|
2008-07-21 08:08:25 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2008-09-05 14:10:58 +00:00
|
|
|
static int openvzNumDefinedDomains(virConnectPtr conn) {
|
|
|
|
struct openvz_driver *driver = (struct openvz_driver *) conn->privateData;
|
|
|
|
int ninactive = 0;
|
|
|
|
virDomainObjPtr vm = driver->domains;
|
|
|
|
while (vm) {
|
|
|
|
if (!virDomainIsActive(vm))
|
|
|
|
ninactive++;
|
|
|
|
vm = vm->next;
|
|
|
|
}
|
|
|
|
return ninactive;
|
2007-07-17 13:27:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static virDriver openvzDriver = {
|
|
|
|
VIR_DRV_OPENVZ,
|
|
|
|
"OPENVZ",
|
|
|
|
LIBVIR_VERSION_NUMBER,
|
2008-02-26 07:05:18 +00:00
|
|
|
openvzProbe, /* probe */
|
2007-07-17 13:27:26 +00:00
|
|
|
openvzOpen, /* open */
|
|
|
|
openvzClose, /* close */
|
2007-09-03 15:37:07 +00:00
|
|
|
NULL, /* supports_feature */
|
2007-07-17 13:27:26 +00:00
|
|
|
openvzGetType, /* type */
|
|
|
|
NULL, /* version */
|
|
|
|
NULL, /* hostname */
|
|
|
|
NULL, /* uri */
|
2008-08-20 13:44:03 +00:00
|
|
|
openvzGetMaxVCPUs, /* getMaxVcpus */
|
2007-07-25 23:16:30 +00:00
|
|
|
openvzGetNodeInfo, /* nodeGetInfo */
|
2008-09-05 14:10:58 +00:00
|
|
|
openvzGetCapabilities, /* getCapabilities */
|
2007-07-17 13:27:26 +00:00
|
|
|
openvzListDomains, /* listDomains */
|
|
|
|
openvzNumDomains, /* numOfDomains */
|
2007-09-03 15:37:07 +00:00
|
|
|
openvzDomainCreateLinux, /* domainCreateLinux */
|
2007-07-17 13:27:26 +00:00
|
|
|
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 */
|
2008-08-20 13:44:03 +00:00
|
|
|
openvzDomainSetVcpus, /* domainSetVcpus */
|
2007-07-17 13:27:26 +00:00
|
|
|
NULL, /* domainPinVcpu */
|
|
|
|
NULL, /* domainGetVcpus */
|
2008-08-20 13:44:03 +00:00
|
|
|
openvzDomainGetMaxVcpus, /* domainGetMaxVcpus */
|
2008-09-05 14:10:58 +00:00
|
|
|
openvzDomainDumpXML, /* domainDumpXML */
|
2007-07-17 13:27:26 +00:00
|
|
|
openvzListDefinedDomains, /* listDomains */
|
|
|
|
openvzNumDefinedDomains, /* numOfDomains */
|
|
|
|
openvzDomainCreate, /* domainCreate */
|
2007-09-03 15:37:07 +00:00
|
|
|
openvzDomainDefineXML, /* domainDefineXML */
|
|
|
|
openvzDomainUndefine, /* domainUndefine */
|
2007-07-17 13:27:26 +00:00
|
|
|
NULL, /* domainAttachDevice */
|
|
|
|
NULL, /* domainDetachDevice */
|
2008-07-10 07:52:14 +00:00
|
|
|
openvzDomainGetAutostart, /* domainGetAutostart */
|
|
|
|
openvzDomainSetAutostart, /* domainSetAutostart */
|
2007-07-17 13:27:26 +00:00
|
|
|
NULL, /* domainGetSchedulerType */
|
|
|
|
NULL, /* domainGetSchedulerParameters */
|
|
|
|
NULL, /* domainSetSchedulerParameters */
|
2007-09-03 16:30:00 +00:00
|
|
|
NULL, /* domainMigratePrepare */
|
|
|
|
NULL, /* domainMigratePerform */
|
|
|
|
NULL, /* domainMigrateFinish */
|
|
|
|
NULL, /* domainBlockStats */
|
|
|
|
NULL, /* domainInterfaceStats */
|
2008-06-12 13:48:29 +00:00
|
|
|
NULL, /* domainBlockPeek */
|
|
|
|
NULL, /* domainMemoryPeek */
|
2007-09-28 14:28:12 +00:00
|
|
|
NULL, /* nodeGetCellsFreeMemory */
|
2007-09-30 13:09:07 +00:00
|
|
|
NULL, /* nodeGetFreeMemory */
|
2007-07-17 13:27:26 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
int openvzRegister(void) {
|
|
|
|
virRegisterDriver(&openvzDriver);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|