mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2024-12-22 17:34:18 +03:00
Convert openvz driver to generic domain XML APIs
This commit is contained in:
parent
542039fab0
commit
1cc9f9b3d8
@ -1,3 +1,8 @@
|
||||
Fri Sep 5 15:09:26 BST 2008 Daniel P. Berrange <berrange@redhat.com>
|
||||
|
||||
* src/openvz_conf.c, src/openvz_conf.h, src/openvz_driver.c,
|
||||
src/openvz_driver.h: Convert to generic domain XML apis
|
||||
|
||||
Fri Sep 5 13:02:26 BST 2008 Daniel P. Berrange <berrange@redhat.com>
|
||||
|
||||
Fully support mingw builds
|
||||
|
@ -40,39 +40,29 @@
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/utsname.h>
|
||||
|
||||
#include <libxml/parser.h>
|
||||
#include <libxml/tree.h>
|
||||
#include <libxml/xpath.h>
|
||||
#include <libxml/uri.h>
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
#include "openvz_driver.h"
|
||||
#include "openvz_conf.h"
|
||||
#include "uuid.h"
|
||||
#include "buf.h"
|
||||
#include "memory.h"
|
||||
#include "util.h"
|
||||
#include "xml.h"
|
||||
#include "domain_conf.h"
|
||||
|
||||
static char *openvzLocateConfDir(void);
|
||||
static struct openvz_vm_def *openvzParseXML(virConnectPtr conn, xmlDocPtr xml);
|
||||
static int openvzGetVPSUUID(int vpsid, char *uuidstr);
|
||||
static int openvzSetUUID(int vpsid);
|
||||
static int openvzLocateConfFile(int vpsid, char *conffile, int maxlen);
|
||||
static int openvzAssignUUIDs(void);
|
||||
|
||||
void
|
||||
openvzError (virConnectPtr conn, virErrorNumber code, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
char errorMessage[OPENVZ_MAX_ERROR_LEN];
|
||||
char errorMessage[1024];
|
||||
const char *errmsg;
|
||||
|
||||
if (fmt) {
|
||||
va_start(args, fmt);
|
||||
vsnprintf(errorMessage, OPENVZ_MAX_ERROR_LEN-1, fmt, args);
|
||||
vsnprintf(errorMessage, sizeof(errorMessage)-1, fmt, args);
|
||||
va_end(args);
|
||||
} else {
|
||||
errorMessage[0] = '\0';
|
||||
@ -84,46 +74,6 @@ openvzError (virConnectPtr conn, virErrorNumber code, const char *fmt, ...)
|
||||
errmsg, errorMessage);
|
||||
}
|
||||
|
||||
struct openvz_vm
|
||||
*openvzFindVMByID(const struct openvz_driver *driver, int id) {
|
||||
struct openvz_vm *vm = driver->vms;
|
||||
|
||||
while (vm) {
|
||||
if (vm->vpsid == id)
|
||||
return vm;
|
||||
vm = vm->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct openvz_vm
|
||||
*openvzFindVMByUUID(const struct openvz_driver *driver,
|
||||
const unsigned char *uuid) {
|
||||
struct openvz_vm *vm = driver->vms;
|
||||
|
||||
while (vm) {
|
||||
if (!memcmp(vm->vmdef->uuid, uuid, VIR_UUID_BUFLEN))
|
||||
return vm;
|
||||
vm = vm->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct openvz_vm
|
||||
*openvzFindVMByName(const struct openvz_driver *driver,
|
||||
const char *name) {
|
||||
struct openvz_vm *vm = driver->vms;
|
||||
|
||||
while (vm) {
|
||||
if (STREQ(vm->vmdef->name, name))
|
||||
return vm;
|
||||
vm = vm->next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int
|
||||
strtoI(const char *str)
|
||||
@ -136,6 +86,43 @@ strtoI(const char *str)
|
||||
return val;
|
||||
}
|
||||
|
||||
virCapsPtr openvzCapsInit(void)
|
||||
{
|
||||
struct utsname utsname;
|
||||
virCapsPtr caps;
|
||||
virCapsGuestPtr guest;
|
||||
|
||||
uname(&utsname);
|
||||
|
||||
if ((caps = virCapabilitiesNew(utsname.machine,
|
||||
0, 0)) == NULL)
|
||||
goto no_memory;
|
||||
|
||||
if ((guest = virCapabilitiesAddGuest(caps,
|
||||
"exe",
|
||||
utsname.machine,
|
||||
sizeof(int) == 4 ? 32 : 8,
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
NULL)) == NULL)
|
||||
goto no_memory;
|
||||
|
||||
if (virCapabilitiesAddGuestDomain(guest,
|
||||
"openvz",
|
||||
NULL,
|
||||
NULL,
|
||||
0,
|
||||
NULL) == NULL)
|
||||
goto no_memory;
|
||||
return caps;
|
||||
|
||||
no_memory:
|
||||
virCapabilitiesFree(caps);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* function checks MAC address is empty
|
||||
return 0 - empty
|
||||
1 - not
|
||||
@ -164,438 +151,117 @@ char *openvzMacToString(const unsigned char *mac)
|
||||
return strdup(str);
|
||||
}
|
||||
|
||||
void
|
||||
openvzRemoveInactiveVM(struct openvz_driver *driver, struct openvz_vm *vm)
|
||||
{
|
||||
driver->num_inactive--;
|
||||
openvzFreeVM(driver, vm, 1);
|
||||
}
|
||||
|
||||
/* Free all memory associated with a openvz_vm_def structure */
|
||||
void
|
||||
openvzFreeVMDef(struct openvz_vm_def *def)
|
||||
{
|
||||
if (def) {
|
||||
virDomainNetDefFree(def->net);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free all memory associated with a openvz_vm structure
|
||||
* @checkCallee == 0 then openvzFreeDriver() is callee else some other function
|
||||
*/
|
||||
void
|
||||
openvzFreeVM(struct openvz_driver *driver, struct openvz_vm *vm,
|
||||
int checkCallee)
|
||||
{
|
||||
struct openvz_vm *vms;
|
||||
|
||||
if (!vm && !driver)
|
||||
return;
|
||||
vms = driver->vms;
|
||||
if (checkCallee) {
|
||||
if (vms == vm)
|
||||
driver->vms = vm->next;
|
||||
else {
|
||||
while (vms) {
|
||||
struct openvz_vm *prev = vms;
|
||||
|
||||
vms = vms->next;
|
||||
if (vms == vm) {
|
||||
prev->next = vms->next;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (vms) {
|
||||
openvzFreeVMDef(vm->vmdef);
|
||||
VIR_FREE(vm);
|
||||
}
|
||||
}
|
||||
|
||||
/* Free all memory associated with a openvz_driver structure */
|
||||
void
|
||||
openvzFreeDriver(struct openvz_driver *driver)
|
||||
{
|
||||
struct openvz_vm *next;
|
||||
|
||||
virDomainObjPtr dom;
|
||||
|
||||
if (!driver)
|
||||
return;
|
||||
if (driver->vms)
|
||||
for(next = driver->vms->next; driver->vms; driver->vms = next)
|
||||
openvzFreeVM(driver, driver->vms, 0);
|
||||
VIR_FREE(driver);
|
||||
}
|
||||
|
||||
struct openvz_vm *
|
||||
openvzAssignVMDef(virConnectPtr conn,
|
||||
struct openvz_driver *driver, struct openvz_vm_def *def)
|
||||
{
|
||||
struct openvz_vm *vm = NULL;
|
||||
|
||||
if (!driver || !def)
|
||||
return NULL;
|
||||
|
||||
if ((vm = openvzFindVMByName(driver, def->name))) {
|
||||
if (!openvzIsActiveVM(vm)) {
|
||||
openvzFreeVMDef(vm->vmdef);
|
||||
vm->vmdef = def;
|
||||
}
|
||||
else
|
||||
{
|
||||
openvzLog(OPENVZ_ERR,
|
||||
_("Error already an active OPENVZ VM having id '%s'"),
|
||||
def->name);
|
||||
openvzFreeVMDef(def);
|
||||
return NULL; /* can't redefine an active domain */
|
||||
}
|
||||
|
||||
return vm;
|
||||
|
||||
dom = driver->domains;
|
||||
while (dom) {
|
||||
virDomainObjPtr tmp = dom->next;
|
||||
virDomainObjFree(dom);
|
||||
dom = tmp;
|
||||
}
|
||||
|
||||
if (VIR_ALLOC(vm) < 0) {
|
||||
openvzFreeVMDef(def);
|
||||
openvzError(conn, VIR_ERR_NO_MEMORY, _("vm"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vm->vpsid = -1; /* -1 needed for to represent inactiveness of domain before 'start' */
|
||||
vm->status = VIR_DOMAIN_SHUTOFF;
|
||||
vm->vmdef = def;
|
||||
vm->next = driver->vms;
|
||||
|
||||
driver->vms = vm;
|
||||
driver->num_inactive++;
|
||||
|
||||
return vm;
|
||||
}
|
||||
|
||||
struct openvz_vm_def
|
||||
*openvzParseVMDef(virConnectPtr conn,
|
||||
const char *xmlStr, const char *displayName)
|
||||
{
|
||||
xmlDocPtr xml;
|
||||
struct openvz_vm_def *def = NULL;
|
||||
|
||||
xml = xmlReadDoc(BAD_CAST xmlStr, displayName ? displayName : "domain.xml", NULL,
|
||||
XML_PARSE_NOENT | XML_PARSE_NONET | XML_PARSE_NOERROR | XML_PARSE_NOWARNING);
|
||||
if (!xml) {
|
||||
openvzError(conn, VIR_ERR_XML_ERROR, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
def = openvzParseXML(conn, xml);
|
||||
xmlFreeDoc(xml);
|
||||
|
||||
return def;
|
||||
}
|
||||
|
||||
/* Parse filesystem section
|
||||
Sample:
|
||||
<filesystem type="template">
|
||||
<source name="fedora-core-5-i386"/>
|
||||
<quota type="size" max="10000"/>
|
||||
<quota type="inodes" max="100"/>
|
||||
</filesystem>
|
||||
*/
|
||||
static int openvzParseDomainFS(virConnectPtr conn,
|
||||
struct openvz_fs_def *fs,
|
||||
xmlXPathContextPtr ctxt)
|
||||
{
|
||||
xmlNodePtr cur, obj;
|
||||
char *type = NULL;
|
||||
int n;
|
||||
xmlNodePtr *nodes = NULL;
|
||||
|
||||
virCapabilitiesFree(driver->caps);
|
||||
}
|
||||
|
||||
|
||||
if ((n = virXPathNodeSet(conn, "/domain/devices/filesystem",
|
||||
ctxt, &nodes)) < 0) {
|
||||
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||
_("missing filesystem tag"));
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (n > 1) {
|
||||
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||
_("There should be only one filesystem tag"));
|
||||
goto error;
|
||||
}
|
||||
|
||||
obj = nodes[0];
|
||||
|
||||
/*check template type*/
|
||||
type = virXMLPropString(obj, "type");
|
||||
if (type == NULL) {
|
||||
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||
_("missing type attribute"));
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (STRNEQ(type, "template")) {
|
||||
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||
_("Unknown type attribute %s"), type);
|
||||
goto error;
|
||||
}
|
||||
VIR_FREE(type);
|
||||
|
||||
cur = obj->children;
|
||||
while(cur != NULL)
|
||||
{
|
||||
if (cur->type == XML_ELEMENT_NODE) {
|
||||
if (xmlStrEqual(cur->name, BAD_CAST "source")) {
|
||||
char * name = virXMLPropString(cur, "name");
|
||||
|
||||
if (name != NULL) {
|
||||
strncpy(fs->tmpl, name,sizeof(fs->tmpl));
|
||||
fs->tmpl[sizeof(fs->tmpl) - 1] = '\0';
|
||||
}
|
||||
VIR_FREE(name);
|
||||
} else if (xmlStrEqual(cur->name, BAD_CAST "quota")) {
|
||||
char * qtype = virXMLPropString(cur, "type");
|
||||
char * max = virXMLPropString(cur, "max");
|
||||
|
||||
if (qtype != NULL && STREQ(qtype, "size") && max != NULL)
|
||||
fs->disksize = strtoI(max);
|
||||
else if (qtype != NULL && STREQ(qtype, "inodes") && max != NULL)
|
||||
fs->diskinodes = strtoI(max);
|
||||
VIR_FREE(qtype);
|
||||
VIR_FREE(max);
|
||||
}
|
||||
}
|
||||
cur = cur->next;
|
||||
}
|
||||
VIR_FREE(nodes);
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
VIR_FREE(nodes);
|
||||
VIR_FREE(type);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Parses a libvirt XML definition of a guest, and populates the
|
||||
* the openvz_vm struct with matching data about the guests config
|
||||
*/
|
||||
static struct openvz_vm_def
|
||||
*openvzParseXML(virConnectPtr conn,
|
||||
xmlDocPtr xml) {
|
||||
xmlNodePtr root = NULL;
|
||||
char *prop = NULL;
|
||||
xmlXPathContextPtr ctxt = NULL;
|
||||
xmlXPathObjectPtr obj = NULL;
|
||||
struct openvz_vm_def *def = NULL;
|
||||
xmlNodePtr *nodes = NULL;
|
||||
int i, n;
|
||||
|
||||
if (VIR_ALLOC(def) < 0) {
|
||||
openvzError(conn, VIR_ERR_NO_MEMORY, _("xmlXPathContext"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Prepare parser / xpath context */
|
||||
root = xmlDocGetRootElement(xml);
|
||||
if ((root == NULL) || (!xmlStrEqual(root->name, BAD_CAST "domain"))) {
|
||||
openvzError(conn, VIR_ERR_INTERNAL_ERROR, _("incorrect root element"));
|
||||
goto bail_out;
|
||||
}
|
||||
|
||||
ctxt = xmlXPathNewContext(xml);
|
||||
if (ctxt == NULL) {
|
||||
openvzError(conn, VIR_ERR_NO_MEMORY, _("xmlXPathContext"));
|
||||
goto bail_out;
|
||||
}
|
||||
ctxt->node = root;
|
||||
|
||||
/* Find out what type of OPENVZ virtualization to use */
|
||||
if (!(prop = virXMLPropString(root, "type"))) {
|
||||
openvzError(conn, VIR_ERR_INTERNAL_ERROR, _("missing domain type attribute"));
|
||||
goto bail_out;
|
||||
}
|
||||
|
||||
if (STRNEQ(prop, "openvz")){
|
||||
openvzError(conn, VIR_ERR_INTERNAL_ERROR, _("invalid domain type attribute"));
|
||||
goto bail_out;
|
||||
}
|
||||
VIR_FREE(prop);
|
||||
|
||||
/* Extract domain name */
|
||||
obj = xmlXPathEval(BAD_CAST "string(/domain/name[1])", ctxt);
|
||||
if ((obj == NULL) || (obj->type != XPATH_STRING) ||
|
||||
(obj->stringval == NULL) || (obj->stringval[0] == 0)) {
|
||||
openvzError(conn, VIR_ERR_INTERNAL_ERROR, _("invalid domain name"));
|
||||
goto bail_out;
|
||||
}
|
||||
|
||||
/* rejecting VPS ID <= OPENVZ_RSRV_VM_LIMIT for they are reserved */
|
||||
if (strtoI((const char *) obj->stringval) <= OPENVZ_RSRV_VM_LIMIT) {
|
||||
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||
_("VPS ID Error (must be an integer greater than 100"));
|
||||
goto bail_out;
|
||||
}
|
||||
strncpy(def->name, (const char *) obj->stringval, OPENVZ_NAME_MAX);
|
||||
xmlXPathFreeObject(obj);
|
||||
obj = NULL;
|
||||
|
||||
/* Extract domain uuid */
|
||||
prop = virXPathString(conn, "string(./uuid[1])", ctxt);
|
||||
if (!prop) {
|
||||
int err;
|
||||
if ((err = virUUIDGenerate(def->uuid))) {
|
||||
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||
_("Failed to generate UUID: %s"),
|
||||
strerror(err));
|
||||
goto bail_out;
|
||||
}
|
||||
} else {
|
||||
if (virUUIDParse(prop, def->uuid) < 0) {
|
||||
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||
_("malformed uuid element"));
|
||||
goto bail_out;
|
||||
}
|
||||
VIR_FREE(prop);
|
||||
}
|
||||
|
||||
/* extract virtual CPUs */
|
||||
if (virXPathULong(conn, "string(./vcpu[1])", ctxt, &def->vcpus) < 0)
|
||||
def->vcpus = 0; //use default CPUs count
|
||||
|
||||
/* Extract filesystem info */
|
||||
if (openvzParseDomainFS(conn, &(def->fs), ctxt)) {
|
||||
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||
_("malformed filesystem tag"));
|
||||
goto bail_out;
|
||||
}
|
||||
|
||||
/* analysis of the network devices */
|
||||
if ((n = virXPathNodeSet(conn, "/domain/devices/interface",
|
||||
ctxt, &nodes)) < 0) {
|
||||
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||
"%s", _("cannot extract network devices"));
|
||||
goto bail_out;
|
||||
}
|
||||
|
||||
for (i = n - 1 ; i >= 0 ; i--) {
|
||||
virDomainNetDefPtr net = virDomainNetDefParseXML(conn,
|
||||
nodes[i]);
|
||||
if (!net)
|
||||
goto bail_out;
|
||||
|
||||
net->next = def->net;
|
||||
def->net = net;
|
||||
}
|
||||
VIR_FREE(nodes);
|
||||
|
||||
xmlXPathFreeContext(ctxt);
|
||||
return def;
|
||||
|
||||
bail_out:
|
||||
VIR_FREE(prop);
|
||||
xmlXPathFreeObject(obj);
|
||||
xmlXPathFreeContext(ctxt);
|
||||
openvzFreeVMDef(def);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct openvz_vm *
|
||||
openvzGetVPSInfo(virConnectPtr conn) {
|
||||
int openvzLoadDomains(struct openvz_driver *driver) {
|
||||
FILE *fp;
|
||||
int veid, ret;
|
||||
char status[16];
|
||||
char uuidstr[VIR_UUID_STRING_BUFLEN];
|
||||
struct openvz_vm *vm;
|
||||
struct openvz_vm **pnext;
|
||||
struct openvz_driver *driver;
|
||||
struct openvz_vm_def *vmdef;
|
||||
char temp[124];
|
||||
virDomainObjPtr dom = NULL, prev = NULL;
|
||||
char temp[50];
|
||||
|
||||
vm = NULL;
|
||||
driver = conn->privateData;
|
||||
driver->num_active = 0;
|
||||
driver->num_inactive = 0;
|
||||
if (openvzAssignUUIDs() < 0)
|
||||
return -1;
|
||||
|
||||
if((fp = popen(VZLIST " -a -ovpsid,status -H 2>/dev/null", "r")) == NULL) {
|
||||
openvzError(conn, VIR_ERR_INTERNAL_ERROR, _("popen failed"));
|
||||
return NULL;
|
||||
if ((fp = popen(VZLIST " -a -ovpsid,status -H 2>/dev/null", "r")) == NULL) {
|
||||
openvzError(NULL, VIR_ERR_INTERNAL_ERROR, _("popen failed"));
|
||||
return -1;
|
||||
}
|
||||
pnext = &vm;
|
||||
|
||||
while(!feof(fp)) {
|
||||
if (VIR_ALLOC(*pnext) < 0) {
|
||||
openvzError(conn, VIR_ERR_INTERNAL_ERROR, _("calloc failed"));
|
||||
goto error;
|
||||
}
|
||||
|
||||
if(!vm)
|
||||
vm = *pnext;
|
||||
|
||||
if (fscanf(fp, "%d %s\n", &veid, status) != 2) {
|
||||
if (feof(fp))
|
||||
break;
|
||||
|
||||
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||
_("Failed to parse vzlist output"));
|
||||
goto error;
|
||||
|
||||
openvzError(NULL, VIR_ERR_INTERNAL_ERROR,
|
||||
_("Failed to parse vzlist output"));
|
||||
goto cleanup;
|
||||
}
|
||||
if(STRNEQ(status, "stopped")) {
|
||||
(*pnext)->status = VIR_DOMAIN_RUNNING;
|
||||
driver->num_active ++;
|
||||
(*pnext)->vpsid = veid;
|
||||
|
||||
if (VIR_ALLOC(dom) < 0 ||
|
||||
VIR_ALLOC(dom->def) < 0)
|
||||
goto no_memory;
|
||||
|
||||
if (STREQ(status, "stopped"))
|
||||
dom->state = VIR_DOMAIN_SHUTOFF;
|
||||
else
|
||||
dom->state = VIR_DOMAIN_RUNNING;
|
||||
|
||||
dom->pid = veid;
|
||||
dom->def->id = dom->state == VIR_DOMAIN_SHUTOFF ? -1 : veid;
|
||||
|
||||
if (asprintf(&dom->def->name, "%i", veid) < 0) {
|
||||
dom->def->name = NULL;
|
||||
goto no_memory;
|
||||
}
|
||||
else {
|
||||
(*pnext)->status = VIR_DOMAIN_SHUTOFF;
|
||||
driver->num_inactive ++;
|
||||
/*
|
||||
* inactive domains don't have their ID set in libvirt,
|
||||
* thought this doesn't make sense for OpenVZ
|
||||
*/
|
||||
(*pnext)->vpsid = -1;
|
||||
}
|
||||
|
||||
if (VIR_ALLOC(vmdef) < 0) {
|
||||
openvzError(conn, VIR_ERR_INTERNAL_ERROR, _("calloc failed"));
|
||||
goto error;
|
||||
}
|
||||
|
||||
snprintf(vmdef->name, OPENVZ_NAME_MAX, "%i", veid);
|
||||
|
||||
openvzGetVPSUUID(veid, uuidstr);
|
||||
ret = virUUIDParse(uuidstr, vmdef->uuid);
|
||||
|
||||
if(ret == -1) {
|
||||
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||
_("UUID in config file malformed"));
|
||||
VIR_FREE(vmdef);
|
||||
goto error;
|
||||
ret = virUUIDParse(uuidstr, dom->def->uuid);
|
||||
|
||||
if (ret == -1) {
|
||||
openvzError(NULL, VIR_ERR_INTERNAL_ERROR,
|
||||
_("UUID in config file malformed"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (!(dom->def->os.type = strdup("exe")))
|
||||
goto no_memory;
|
||||
if (!(dom->def->os.init = strdup("/sbin/init")))
|
||||
goto no_memory;
|
||||
|
||||
/*get VCPU*/
|
||||
ret = openvzReadConfigParam(veid, "CPUS", temp, sizeof(temp));
|
||||
if (ret < 0) {
|
||||
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||
_("Cound not read config for container %d"), veid);
|
||||
goto error;
|
||||
openvzError(NULL, VIR_ERR_INTERNAL_ERROR,
|
||||
_("Cound not read config for container %d"),
|
||||
veid);
|
||||
goto cleanup;
|
||||
} else if (ret > 0) {
|
||||
vmdef->vcpus = strtoI(temp);
|
||||
dom->def->vcpus = strtoI(temp);
|
||||
} else {
|
||||
dom->def->vcpus = 1;
|
||||
}
|
||||
|
||||
|
||||
(*pnext)->vmdef = vmdef;
|
||||
pnext = &(*pnext)->next;
|
||||
/* XXX load rest of VM config data .... */
|
||||
|
||||
if (prev) {
|
||||
prev->next = dom;
|
||||
} else {
|
||||
driver->domains = dom;
|
||||
}
|
||||
prev = dom;
|
||||
}
|
||||
return vm;
|
||||
error:
|
||||
while (vm != NULL) {
|
||||
struct openvz_vm *next;
|
||||
|
||||
next = vm->next;
|
||||
VIR_FREE(vm->vmdef);
|
||||
VIR_FREE(vm);
|
||||
vm = next;
|
||||
}
|
||||
return NULL;
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return 0;
|
||||
|
||||
no_memory:
|
||||
openvzError(NULL, VIR_ERR_NO_MEMORY, NULL);
|
||||
|
||||
cleanup:
|
||||
fclose(fp);
|
||||
virDomainObjFree(dom);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -797,7 +463,7 @@ openvzSetUUID(int vpsid){
|
||||
*
|
||||
*/
|
||||
|
||||
int openvzAssignUUIDs(void)
|
||||
static int openvzAssignUUIDs(void)
|
||||
{
|
||||
DIR *dp;
|
||||
struct dirent *dent;
|
||||
|
@ -28,94 +28,35 @@
|
||||
#ifndef OPENVZ_CONF_H
|
||||
#define OPENVZ_CONF_H
|
||||
|
||||
#include "openvz_driver.h"
|
||||
#include "internal.h"
|
||||
#include "domain_conf.h"
|
||||
|
||||
enum { OPENVZ_WARN, OPENVZ_ERR };
|
||||
|
||||
#define OPENVZ_NAME_MAX 8
|
||||
#define OPENVZ_TMPL_MAX 256
|
||||
#define OPENVZ_UNAME_MAX 32
|
||||
#define OPENVZ_IP_MAX 16
|
||||
#define OPENVZ_HOSTNAME_MAX 256
|
||||
#define OPENVZ_PROFILE_MAX 256
|
||||
#define OPENVZ_MAX_ERROR_LEN 1024
|
||||
#define OPENVZ_MAX_XML_LEN 4096
|
||||
#define OPENVZ_MAX_QUOTA 8
|
||||
#define OPENVZ_MAX_XPathEval_LEN 256
|
||||
#define OPENVZ_RSRV_VM_LIMIT 100
|
||||
#define openvzLog(level, msg...) { if(level == OPENVZ_WARN) \
|
||||
fprintf(stderr, "\nWARNING: ");\
|
||||
else \
|
||||
fprintf(stderr, "\nERROR: ");\
|
||||
fprintf(stderr, "\n\t");\
|
||||
fprintf(stderr, msg);\
|
||||
fprintf(stderr, "\n"); }
|
||||
|
||||
enum openvz_quota{
|
||||
VM_LEVEL = 0,
|
||||
USER_LEVEL = 1,
|
||||
/* OpenVZ commands - Replace with wrapper scripts later? */
|
||||
#define VZLIST "vzlist"
|
||||
#define VZCTL "vzctl"
|
||||
|
||||
struct openvz_driver {
|
||||
virCapsPtr caps;
|
||||
virDomainObjPtr domains;
|
||||
};
|
||||
|
||||
/* TODO Add more properties here */
|
||||
struct vps_props {
|
||||
int kmemsize; /* currently held */
|
||||
int kmemsize_m; /* max held */
|
||||
int kmemsize_b; /* barrier */
|
||||
int kmemsize_l; /* limit */
|
||||
int kmemsize_f; /* fail count */
|
||||
|
||||
};
|
||||
|
||||
struct openvz_fs_def {
|
||||
char tmpl[OPENVZ_TMPL_MAX];
|
||||
long int disksize, diskinodes;
|
||||
};
|
||||
|
||||
struct openvz_vm_def {
|
||||
char name[OPENVZ_NAME_MAX];
|
||||
unsigned char uuid[VIR_UUID_BUFLEN];
|
||||
char profile[OPENVZ_PROFILE_MAX];
|
||||
unsigned long vcpus;
|
||||
struct openvz_fs_def fs;
|
||||
virDomainNetDefPtr net;
|
||||
};
|
||||
|
||||
struct ovz_quota {
|
||||
enum openvz_quota type;
|
||||
unsigned int size;
|
||||
char uname[OPENVZ_UNAME_MAX];
|
||||
struct ovz_quota *next;
|
||||
};
|
||||
|
||||
struct openvz_vm {
|
||||
int vpsid;
|
||||
int status;
|
||||
struct openvz_vm_def *vmdef;
|
||||
struct openvz_vm *next;
|
||||
};
|
||||
|
||||
static inline int
|
||||
openvzIsActiveVM(struct openvz_vm *vm)
|
||||
{
|
||||
return vm->vpsid != -1;
|
||||
}
|
||||
|
||||
void openvzError (virConnectPtr conn, virErrorNumber code, const char *fmt, ...)
|
||||
ATTRIBUTE_FORMAT(printf, 3, 4);
|
||||
int openvz_readline(int fd, char *ptr, int maxlen);
|
||||
int openvzReadConfigParam(int vpsid ,const char * param, char *value, int maxlen);
|
||||
struct openvz_vm *openvzFindVMByID(const struct openvz_driver *driver, int id);
|
||||
struct openvz_vm *openvzFindVMByUUID(const struct openvz_driver *driver,
|
||||
const unsigned char *uuid);
|
||||
|
||||
struct openvz_vm *openvzFindVMByName(const struct openvz_driver *driver, const char *name);
|
||||
struct openvz_vm_def *openvzParseVMDef(virConnectPtr conn, const char *xmlStr,
|
||||
const char *displayName);
|
||||
|
||||
struct openvz_vm *openvzAssignVMDef(virConnectPtr conn, struct openvz_driver *driver,
|
||||
struct openvz_vm_def *def);
|
||||
|
||||
struct openvz_vm *openvzGetVPSInfo(virConnectPtr conn);
|
||||
void openvzGenerateUUID(unsigned char *uuid);
|
||||
int openvzAssignUUIDs(void);
|
||||
void openvzRemoveInactiveVM(struct openvz_driver *driver, struct openvz_vm *vm);
|
||||
virCapsPtr openvzCapsInit(void);
|
||||
int openvzLoadDomains(struct openvz_driver *driver);
|
||||
void openvzFreeDriver(struct openvz_driver *driver);
|
||||
void openvzFreeVM(struct openvz_driver *driver, struct openvz_vm *vm, int checkCallee);
|
||||
void openvzFreeVMDef(struct openvz_vm_def *def);
|
||||
int strtoI(const char *str);
|
||||
int openvzCheckEmptyMac(const unsigned char *mac);
|
||||
char *openvzMacToString(const unsigned char *mac);
|
||||
|
@ -60,33 +60,6 @@
|
||||
#define CMDBUF_LEN 1488
|
||||
#define CMDOP_LEN 288
|
||||
|
||||
static virDomainPtr openvzDomainLookupByID(virConnectPtr conn, int id);
|
||||
static char *openvzGetOSType(virDomainPtr dom);
|
||||
static int openvzGetNodeInfo(virConnectPtr conn, virNodeInfoPtr nodeinfo);
|
||||
static virDomainPtr openvzDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid);
|
||||
static virDomainPtr openvzDomainLookupByName(virConnectPtr conn, const char *name);
|
||||
static int openvzDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info);
|
||||
static int openvzDomainShutdown(virDomainPtr dom);
|
||||
static int openvzDomainReboot(virDomainPtr dom, unsigned int flags);
|
||||
static int openvzDomainCreate(virDomainPtr dom);
|
||||
static virDrvOpenStatus openvzOpen(virConnectPtr conn,
|
||||
xmlURIPtr uri,
|
||||
virConnectAuthPtr auth ATTRIBUTE_UNUSED,
|
||||
int flags ATTRIBUTE_UNUSED);
|
||||
static int openvzClose(virConnectPtr conn);
|
||||
static const char *openvzGetType(virConnectPtr conn ATTRIBUTE_UNUSED);
|
||||
static int openvzListDomains(virConnectPtr conn, int *ids, int nids);
|
||||
static int openvzNumDomains(virConnectPtr conn);
|
||||
static int openvzListDefinedDomains(virConnectPtr conn, char **const names, int nnames);
|
||||
static int openvzNumDefinedDomains(virConnectPtr conn);
|
||||
|
||||
static virDomainPtr openvzDomainDefineXML(virConnectPtr conn, const char *xml);
|
||||
static virDomainPtr openvzDomainCreateLinux(virConnectPtr conn, const char *xml,
|
||||
unsigned int flags ATTRIBUTE_UNUSED);
|
||||
|
||||
static int openvzDomainUndefine(virDomainPtr dom);
|
||||
static void cmdExecFree(const char *cmdExec[]);
|
||||
|
||||
static int openvzGetProcessInfo(unsigned long long *cpuTime, int vpsid);
|
||||
static int openvzGetMaxVCPUs(virConnectPtr conn, const char *type);
|
||||
static int openvzDomainGetMaxVcpus(virDomainPtr dom);
|
||||
@ -110,7 +83,7 @@ static void cmdExecFree(const char *cmdExec[])
|
||||
static int openvzDomainDefineCmd(virConnectPtr conn,
|
||||
const char *args[],
|
||||
int maxarg,
|
||||
struct openvz_vm_def *vmdef)
|
||||
virDomainDefPtr vmdef)
|
||||
{
|
||||
int narg;
|
||||
|
||||
@ -143,15 +116,29 @@ static int openvzDomainDefineCmd(virConnectPtr conn,
|
||||
ADD_ARG_LIT("--quiet");
|
||||
ADD_ARG_LIT("create");
|
||||
ADD_ARG_LIT(vmdef->name);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
if ((vmdef->fs.tmpl && *(vmdef->fs.tmpl))) {
|
||||
ADD_ARG_LIT("--ostemplate");
|
||||
ADD_ARG_LIT(vmdef->fs.tmpl);
|
||||
ADD_ARG_LIT(vmdef->fss->src);
|
||||
}
|
||||
#if 0
|
||||
if ((vmdef->profile && *(vmdef->profile))) {
|
||||
ADD_ARG_LIT("--config");
|
||||
ADD_ARG_LIT(vmdef->profile);
|
||||
}
|
||||
#endif
|
||||
|
||||
ADD_ARG(NULL);
|
||||
return 0;
|
||||
@ -165,39 +152,48 @@ static int openvzDomainDefineCmd(virConnectPtr conn,
|
||||
|
||||
|
||||
static virDomainPtr openvzDomainLookupByID(virConnectPtr conn,
|
||||
int id) {
|
||||
int id) {
|
||||
struct openvz_driver *driver = (struct openvz_driver *)conn->privateData;
|
||||
struct openvz_vm *vm;
|
||||
virDomainObjPtr vm;
|
||||
virDomainPtr dom;
|
||||
|
||||
vm = openvzFindVMByID(driver, id);
|
||||
vm = virDomainFindByID(driver->domains, id);
|
||||
|
||||
if (!vm) {
|
||||
openvzError(conn, VIR_ERR_NO_DOMAIN, NULL);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dom = virGetDomain(conn, vm->vmdef->name, vm->vmdef->uuid);
|
||||
if (!dom) {
|
||||
openvzError(conn, VIR_ERR_NO_MEMORY, _("virDomainPtr"));
|
||||
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
|
||||
if (!dom)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dom->id = vm->vpsid;
|
||||
dom->id = vm->def->id;
|
||||
return dom;
|
||||
}
|
||||
|
||||
static char *openvzGetOSType(virDomainPtr dom ATTRIBUTE_UNUSED)
|
||||
static char *openvzGetOSType(virDomainPtr dom)
|
||||
{
|
||||
/* OpenVZ runs on Linux and runs only Linux */
|
||||
return strdup("linux");
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
static virDomainPtr openvzDomainLookupByUUID(virConnectPtr conn,
|
||||
const unsigned char *uuid) {
|
||||
const unsigned char *uuid) {
|
||||
struct openvz_driver *driver = (struct openvz_driver *)conn->privateData;
|
||||
struct openvz_vm *vm = openvzFindVMByUUID(driver, uuid);
|
||||
virDomainObjPtr vm = virDomainFindByUUID(driver->domains, uuid);
|
||||
virDomainPtr dom;
|
||||
|
||||
if (!vm) {
|
||||
@ -205,20 +201,18 @@ static virDomainPtr openvzDomainLookupByUUID(virConnectPtr conn,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dom = virGetDomain(conn, vm->vmdef->name, vm->vmdef->uuid);
|
||||
if (!dom) {
|
||||
openvzError(conn, VIR_ERR_NO_MEMORY, _("virDomainPtr"));
|
||||
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
|
||||
if (!dom)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dom->id = vm->vpsid;
|
||||
dom->id = vm->def->id;
|
||||
return dom;
|
||||
}
|
||||
|
||||
static virDomainPtr openvzDomainLookupByName(virConnectPtr conn,
|
||||
const char *name) {
|
||||
struct openvz_driver *driver = (struct openvz_driver *)conn->privateData;
|
||||
struct openvz_vm *vm = openvzFindVMByName(driver, name);
|
||||
virDomainObjPtr vm = virDomainFindByName(driver->domains, name);
|
||||
virDomainPtr dom;
|
||||
|
||||
if (!vm) {
|
||||
@ -226,74 +220,81 @@ static virDomainPtr openvzDomainLookupByName(virConnectPtr conn,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dom = virGetDomain(conn, vm->vmdef->name, vm->vmdef->uuid);
|
||||
if (!dom) {
|
||||
openvzError(conn, VIR_ERR_NO_MEMORY, _("virDomainPtr"));
|
||||
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
|
||||
if (!dom)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dom->id = vm->vpsid;
|
||||
|
||||
dom->id = vm->def->id;
|
||||
return dom;
|
||||
}
|
||||
|
||||
static int openvzDomainGetInfo(virDomainPtr dom,
|
||||
virDomainInfoPtr info) {
|
||||
virDomainInfoPtr info) {
|
||||
struct openvz_driver *driver = (struct openvz_driver *)dom->conn->privateData;
|
||||
struct openvz_vm *vm = openvzFindVMByUUID(driver, dom->uuid);
|
||||
virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
|
||||
|
||||
if (!vm) {
|
||||
openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN,
|
||||
_("no domain with matching uuid"));
|
||||
_("no domain with matching uuid"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
info->state = vm->status;
|
||||
|
||||
if (!openvzIsActiveVM(vm)) {
|
||||
info->state = vm->state;
|
||||
|
||||
if (!virDomainIsActive(vm)) {
|
||||
info->cpuTime = 0;
|
||||
} else {
|
||||
if (openvzGetProcessInfo(&(info->cpuTime), dom->id) < 0) {
|
||||
openvzError(dom->conn, VIR_ERR_OPERATION_FAILED,
|
||||
_("cannot read cputime for domain %d"), dom->id);
|
||||
_("cannot read cputime for domain %d"), dom->id);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO These need to be calculated differently for OpenVZ */
|
||||
//info->cpuTime =
|
||||
//info->maxMem = vm->def->maxmem;
|
||||
//info->memory = vm->def->memory;
|
||||
info->nrVirtCpu = vm->vmdef->vcpus;
|
||||
info->maxMem = vm->def->maxmem;
|
||||
info->memory = vm->def->memory;
|
||||
info->nrVirtCpu = vm->def->vcpus;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static char *openvzDomainDumpXML(virDomainPtr dom, int flags) {
|
||||
struct openvz_driver *driver = (struct openvz_driver *)dom->conn->privateData;
|
||||
virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
|
||||
|
||||
if (!vm) {
|
||||
openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN,
|
||||
_("no domain with matching uuid"));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return virDomainDefFormat(dom->conn, vm->def, flags);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int openvzDomainShutdown(virDomainPtr dom) {
|
||||
struct openvz_driver *driver = (struct openvz_driver *)dom->conn->privateData;
|
||||
struct openvz_vm *vm = openvzFindVMByUUID(driver, dom->uuid);
|
||||
const char *prog[] = {VZCTL, "--quiet", "stop", vm->vmdef->name, NULL};
|
||||
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 id"));
|
||||
_("no domain with matching uuid"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (vm->status != VIR_DOMAIN_RUNNING) {
|
||||
openvzError(dom->conn, VIR_ERR_OPERATION_DENIED,
|
||||
_("domain is not in running state"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (virRun(dom->conn, prog, NULL) < 0) {
|
||||
|
||||
if (vm->state != VIR_DOMAIN_RUNNING) {
|
||||
openvzError(dom->conn, VIR_ERR_INTERNAL_ERROR,
|
||||
_("Could not exec %s"), VZCTL);
|
||||
_("domain is not in running state"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
vm->vpsid = -1;
|
||||
vm->status = VIR_DOMAIN_SHUTOFF;
|
||||
ovz_driver.num_inactive ++;
|
||||
ovz_driver.num_active --;
|
||||
|
||||
if (virRun(dom->conn, prog, NULL) < 0)
|
||||
return -1;
|
||||
|
||||
vm->def->id = -1;
|
||||
vm->state = VIR_DOMAIN_SHUTOFF;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -301,27 +302,24 @@ static int openvzDomainShutdown(virDomainPtr dom) {
|
||||
static int openvzDomainReboot(virDomainPtr dom,
|
||||
unsigned int flags ATTRIBUTE_UNUSED) {
|
||||
struct openvz_driver *driver = (struct openvz_driver *)dom->conn->privateData;
|
||||
struct openvz_vm *vm = openvzFindVMByUUID(driver, dom->uuid);
|
||||
const char *prog[] = {VZCTL, "--quiet", "restart", vm->vmdef->name, NULL};
|
||||
virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
|
||||
const char *prog[] = {VZCTL, "--quiet", "restart", vm->def->name, NULL};
|
||||
|
||||
if (!vm) {
|
||||
openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN,
|
||||
_("no domain with matching id"));
|
||||
_("no domain with matching uuid"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (vm->status != VIR_DOMAIN_RUNNING) {
|
||||
openvzError(dom->conn, VIR_ERR_OPERATION_DENIED,
|
||||
_("domain is not in running state"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (virRun(dom->conn, prog, NULL) < 0) {
|
||||
if (vm->state != VIR_DOMAIN_RUNNING) {
|
||||
openvzError(dom->conn, VIR_ERR_INTERNAL_ERROR,
|
||||
_("Could not exec %s"), VZCTL);
|
||||
_("domain is not in running state"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (virRun(dom->conn, prog, NULL) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -421,24 +419,31 @@ static virDomainPtr
|
||||
openvzDomainDefineXML(virConnectPtr conn, const char *xml)
|
||||
{
|
||||
struct openvz_driver *driver = (struct openvz_driver *) conn->privateData;
|
||||
struct openvz_vm_def *vmdef = NULL;
|
||||
struct openvz_vm *vm = NULL;
|
||||
virDomainDefPtr vmdef = NULL;
|
||||
virDomainObjPtr vm = NULL;
|
||||
virDomainPtr dom = NULL;
|
||||
const char *prog[OPENVZ_MAX_ARG];
|
||||
prog[0] = NULL;
|
||||
|
||||
if ((vmdef = openvzParseVMDef(conn, xml, NULL)) == NULL)
|
||||
if ((vmdef = virDomainDefParseString(conn, driver->caps, xml)) == NULL)
|
||||
return NULL;
|
||||
|
||||
vm = openvzFindVMByName(driver, vmdef->name);
|
||||
if (vmdef->os.init == NULL &&
|
||||
!(vmdef->os.init = strdup("/sbin/init"))) {
|
||||
virDomainDefFree(vmdef);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vm = virDomainFindByName(driver->domains, vmdef->name);
|
||||
if (vm) {
|
||||
virDomainDefFree(vmdef);
|
||||
openvzLog(OPENVZ_ERR, _("Already an OPENVZ VM active with the id '%s'"),
|
||||
vmdef->name);
|
||||
return NULL;
|
||||
}
|
||||
if (!(vm = openvzAssignVMDef(conn, driver, vmdef))) {
|
||||
openvzFreeVMDef(vmdef);
|
||||
openvzLog(OPENVZ_ERR, "%s", _("Error creating OPENVZ VM"));
|
||||
if (!(vm = virDomainAssignDef(conn, &driver->domains, vmdef))) {
|
||||
virDomainDefFree(vmdef);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (openvzDomainDefineCmd(conn, prog, OPENVZ_MAX_ARG, vmdef) < 0) {
|
||||
@ -461,11 +466,11 @@ openvzDomainDefineXML(virConnectPtr conn, const char *xml)
|
||||
goto exit;
|
||||
}
|
||||
|
||||
dom = virGetDomain(conn, vm->vmdef->name, vm->vmdef->uuid);
|
||||
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
|
||||
if (dom)
|
||||
dom->id = vm->vpsid;
|
||||
dom->id = -1;
|
||||
|
||||
if (openvzDomainSetNetwork(conn, vmdef->name, vmdef->net) < 0) {
|
||||
if (openvzDomainSetNetwork(conn, vmdef->name, vmdef->nets) < 0) {
|
||||
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||
_("Could not configure network"));
|
||||
goto exit;
|
||||
@ -488,27 +493,33 @@ static virDomainPtr
|
||||
openvzDomainCreateLinux(virConnectPtr conn, const char *xml,
|
||||
unsigned int flags ATTRIBUTE_UNUSED)
|
||||
{
|
||||
struct openvz_vm_def *vmdef = NULL;
|
||||
struct openvz_vm *vm = NULL;
|
||||
virDomainDefPtr vmdef = NULL;
|
||||
virDomainObjPtr vm = NULL;
|
||||
virDomainPtr dom = NULL;
|
||||
struct openvz_driver *driver = (struct openvz_driver *) conn->privateData;
|
||||
const char *progstart[] = {VZCTL, "--quiet", "start", NULL, NULL};
|
||||
const char *progcreate[OPENVZ_MAX_ARG];
|
||||
progcreate[0] = NULL;
|
||||
|
||||
if (!(vmdef = openvzParseVMDef(conn, xml, NULL)))
|
||||
if ((vmdef = virDomainDefParseString(conn, driver->caps, xml)) == NULL)
|
||||
return NULL;
|
||||
|
||||
vm = openvzFindVMByName(driver, vmdef->name);
|
||||
if (vmdef->os.init == NULL &&
|
||||
!(vmdef->os.init = strdup("/sbin/init"))) {
|
||||
virDomainDefFree(vmdef);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
vm = virDomainFindByName(driver->domains, vmdef->name);
|
||||
if (vm) {
|
||||
openvzFreeVMDef(vmdef);
|
||||
virDomainDefFree(vmdef);
|
||||
openvzLog(OPENVZ_ERR,
|
||||
_("Already an OPENVZ VM defined with the id '%d'"),
|
||||
strtoI(vmdef->name));
|
||||
return NULL;
|
||||
}
|
||||
if (!(vm = openvzAssignVMDef(conn, driver, vmdef))) {
|
||||
openvzLog(OPENVZ_ERR, "%s", _("Error creating OPENVZ VM"));
|
||||
if (!(vm = virDomainAssignDef(conn, &driver->domains, vmdef))) {
|
||||
virDomainDefFree(vmdef);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -530,7 +541,7 @@ openvzDomainCreateLinux(virConnectPtr conn, const char *xml,
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (openvzDomainSetNetwork(conn, vmdef->name, vmdef->net) < 0) {
|
||||
if (openvzDomainSetNetwork(conn, vmdef->name, vmdef->nets) < 0) {
|
||||
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||
_("Could not configure network"));
|
||||
goto exit;
|
||||
@ -544,20 +555,19 @@ openvzDomainCreateLinux(virConnectPtr conn, const char *xml,
|
||||
goto exit;
|
||||
}
|
||||
|
||||
vm->vpsid = strtoI(vmdef->name);
|
||||
vm->status = VIR_DOMAIN_RUNNING;
|
||||
ovz_driver.num_inactive--;
|
||||
ovz_driver.num_active++;
|
||||
|
||||
dom = virGetDomain(conn, vm->vmdef->name, vm->vmdef->uuid);
|
||||
vm->pid = strtoI(vmdef->name);
|
||||
vm->def->id = vm->pid;
|
||||
vm->state = VIR_DOMAIN_RUNNING;
|
||||
|
||||
dom = virGetDomain(conn, vm->def->name, vm->def->uuid);
|
||||
if (dom)
|
||||
dom->id = vm->vpsid;
|
||||
dom->id = vm->def->id;
|
||||
|
||||
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;
|
||||
_("Could not set number of virtual cpu"));
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
@ -570,8 +580,8 @@ static int
|
||||
openvzDomainCreate(virDomainPtr dom)
|
||||
{
|
||||
struct openvz_driver *driver = (struct openvz_driver *)dom->conn->privateData;
|
||||
struct openvz_vm *vm = openvzFindVMByName(driver, dom->name);
|
||||
const char *prog[] = {VZCTL, "--quiet", "start", vm->vmdef->name, NULL };
|
||||
virDomainObjPtr vm = virDomainFindByName(driver->domains, dom->name);
|
||||
const char *prog[] = {VZCTL, "--quiet", "start", vm->def->name, NULL };
|
||||
|
||||
if (!vm) {
|
||||
openvzError(dom->conn, VIR_ERR_INVALID_DOMAIN,
|
||||
@ -579,7 +589,7 @@ openvzDomainCreate(virDomainPtr dom)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (vm->status != VIR_DOMAIN_SHUTOFF) {
|
||||
if (vm->state != VIR_DOMAIN_SHUTOFF) {
|
||||
openvzError(dom->conn, VIR_ERR_OPERATION_DENIED,
|
||||
_("domain is not in shutoff state"));
|
||||
return -1;
|
||||
@ -591,10 +601,9 @@ openvzDomainCreate(virDomainPtr dom)
|
||||
return -1;
|
||||
}
|
||||
|
||||
vm->vpsid = strtoI(vm->vmdef->name);
|
||||
vm->status = VIR_DOMAIN_RUNNING;
|
||||
ovz_driver.num_inactive --;
|
||||
ovz_driver.num_active ++;
|
||||
vm->pid = strtoI(vm->def->name);
|
||||
vm->def->id = vm->pid;
|
||||
vm->state = VIR_DOMAIN_RUNNING;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -604,15 +613,15 @@ openvzDomainUndefine(virDomainPtr dom)
|
||||
{
|
||||
virConnectPtr conn= dom->conn;
|
||||
struct openvz_driver *driver = (struct openvz_driver *) conn->privateData;
|
||||
struct openvz_vm *vm = openvzFindVMByUUID(driver, dom->uuid);
|
||||
const char *prog[] = { VZCTL, "--quiet", "destroy", vm->vmdef->name, NULL };
|
||||
virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
|
||||
const char *prog[] = { VZCTL, "--quiet", "destroy", vm->def->name, NULL };
|
||||
|
||||
if (!vm) {
|
||||
openvzError(conn, VIR_ERR_INVALID_DOMAIN, _("no domain with matching uuid"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (openvzIsActiveVM(vm)) {
|
||||
if (virDomainIsActive(vm)) {
|
||||
openvzError(conn, VIR_ERR_INTERNAL_ERROR, _("cannot delete active domain"));
|
||||
return -1;
|
||||
}
|
||||
@ -623,7 +632,8 @@ openvzDomainUndefine(virDomainPtr dom)
|
||||
return -1;
|
||||
}
|
||||
|
||||
openvzRemoveInactiveVM(driver, vm);
|
||||
virDomainRemoveInactive(&driver->domains, vm);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -632,8 +642,8 @@ openvzDomainSetAutostart(virDomainPtr dom, int autostart)
|
||||
{
|
||||
virConnectPtr conn= dom->conn;
|
||||
struct openvz_driver *driver = (struct openvz_driver *) conn->privateData;
|
||||
struct openvz_vm *vm = openvzFindVMByUUID(driver, dom->uuid);
|
||||
const char *prog[] = { VZCTL, "--quiet", "set", vm->vmdef->name,
|
||||
virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
|
||||
const char *prog[] = { VZCTL, "--quiet", "set", vm->def->name,
|
||||
"--onboot", autostart ? "yes" : "no",
|
||||
"--save", NULL };
|
||||
|
||||
@ -655,7 +665,7 @@ openvzDomainGetAutostart(virDomainPtr dom, int *autostart)
|
||||
{
|
||||
virConnectPtr conn= dom->conn;
|
||||
struct openvz_driver *driver = (struct openvz_driver *) conn->privateData;
|
||||
struct openvz_vm *vm = openvzFindVMByUUID(driver, dom->uuid);
|
||||
virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
|
||||
char value[1024];
|
||||
|
||||
if (!vm) {
|
||||
@ -663,7 +673,7 @@ openvzDomainGetAutostart(virDomainPtr dom, int *autostart)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (openvzReadConfigParam(strtoI(vm->vmdef->name), "ONBOOT", value, sizeof(value)) < 0) {
|
||||
if (openvzReadConfigParam(strtoI(vm->def->name), "ONBOOT", value, sizeof(value)) < 0) {
|
||||
openvzError(conn, VIR_ERR_INTERNAL_ERROR, _("Could not read container config"));
|
||||
return -1;
|
||||
}
|
||||
@ -692,39 +702,39 @@ static int openvzDomainGetMaxVcpus(virDomainPtr dom) {
|
||||
static int openvzDomainSetVcpus(virDomainPtr dom, unsigned int nvcpus) {
|
||||
virConnectPtr conn= dom->conn;
|
||||
struct openvz_driver *driver = (struct openvz_driver *) conn->privateData;
|
||||
struct openvz_vm *vm = openvzFindVMByUUID(driver, dom->uuid);
|
||||
virDomainObjPtr vm = virDomainFindByUUID(driver->domains, dom->uuid);
|
||||
char str_vcpus[32];
|
||||
const char *prog[] = { VZCTL, "--quiet", "set", vm->vmdef->name,
|
||||
const char *prog[] = { VZCTL, "--quiet", "set", vm->def->name,
|
||||
"--cpus", str_vcpus, "--save", NULL };
|
||||
snprintf(str_vcpus, 31, "%d", nvcpus);
|
||||
str_vcpus[31] = '\0';
|
||||
|
||||
if (nvcpus <= 0) {
|
||||
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||
_("VCPUs should be >= 1"));
|
||||
_("VCPUs should be >= 1"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!vm) {
|
||||
openvzError(conn, VIR_ERR_INVALID_DOMAIN,
|
||||
_("no domain with matching uuid"));
|
||||
_("no domain with matching uuid"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (virRun(conn, prog, NULL) < 0) {
|
||||
openvzError(conn, VIR_ERR_INTERNAL_ERROR,
|
||||
_("Could not exec %s"), VZCTL);
|
||||
_("Could not exec %s"), VZCTL);
|
||||
return -1;
|
||||
}
|
||||
|
||||
vm->vmdef->vcpus = nvcpus;
|
||||
vm->def->vcpus = nvcpus;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const char *openvzProbe(void)
|
||||
{
|
||||
#ifdef __linux__
|
||||
if ((getuid() == 0) && (virFileExists("/proc/vz")))
|
||||
if ((geteuid() == 0) && (virFileExists("/proc/vz")))
|
||||
return("openvz:///system");
|
||||
#endif
|
||||
return(NULL);
|
||||
@ -735,51 +745,48 @@ static virDrvOpenStatus openvzOpen(virConnectPtr conn,
|
||||
virConnectAuthPtr auth ATTRIBUTE_UNUSED,
|
||||
int flags ATTRIBUTE_UNUSED)
|
||||
{
|
||||
struct openvz_vm *vms;
|
||||
|
||||
struct openvz_driver *driver;
|
||||
/*Just check if the user is root. Nothing really to open for OpenVZ */
|
||||
if (getuid()) { // OpenVZ tools can only be used by r00t
|
||||
return VIR_DRV_OPEN_DECLINED;
|
||||
} else {
|
||||
if (uri == NULL || uri->scheme == NULL || uri->path == NULL)
|
||||
return VIR_DRV_OPEN_DECLINED;
|
||||
if (STRNEQ (uri->scheme, "openvz"))
|
||||
return VIR_DRV_OPEN_DECLINED;
|
||||
if (STRNEQ (uri->path, "/system"))
|
||||
return VIR_DRV_OPEN_DECLINED;
|
||||
}
|
||||
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;
|
||||
}
|
||||
/* See if we are running an OpenVZ enabled kernel */
|
||||
if(access("/proc/vz/veinfo", F_OK) == -1 ||
|
||||
access("/proc/user_beancounters", F_OK) == -1) {
|
||||
return VIR_DRV_OPEN_DECLINED;
|
||||
}
|
||||
if(access("/proc/vz/veinfo", F_OK) == -1 ||
|
||||
access("/proc/user_beancounters", F_OK) == -1) {
|
||||
return VIR_DRV_OPEN_DECLINED;
|
||||
}
|
||||
|
||||
conn->privateData = &ovz_driver;
|
||||
if (VIR_ALLOC(driver) < 0) {
|
||||
openvzError(conn, VIR_ERR_NO_MEMORY, NULL);
|
||||
return VIR_DRV_OPEN_ERROR;
|
||||
}
|
||||
|
||||
openvzAssignUUIDs();
|
||||
if (!(driver->caps = openvzCapsInit()))
|
||||
goto cleanup;
|
||||
|
||||
vms = openvzGetVPSInfo(conn);
|
||||
ovz_driver.vms = vms;
|
||||
if (openvzLoadDomains(driver) < 0)
|
||||
goto cleanup;
|
||||
|
||||
return VIR_DRV_OPEN_SUCCESS;
|
||||
conn->privateData = driver;
|
||||
|
||||
return VIR_DRV_OPEN_SUCCESS;
|
||||
|
||||
cleanup:
|
||||
openvzFreeDriver(driver);
|
||||
return VIR_DRV_OPEN_ERROR;
|
||||
};
|
||||
|
||||
static int openvzClose(virConnectPtr conn) {
|
||||
|
||||
struct openvz_driver *driver = (struct openvz_driver *)conn->privateData;
|
||||
struct openvz_vm *vm = driver->vms;
|
||||
|
||||
while(vm) {
|
||||
openvzFreeVMDef(vm->vmdef);
|
||||
vm = vm->next;
|
||||
}
|
||||
vm = driver->vms;
|
||||
while (vm) {
|
||||
struct openvz_vm *prev = vm;
|
||||
vm = vm->next;
|
||||
free(prev);
|
||||
}
|
||||
|
||||
openvzFreeDriver(driver);
|
||||
conn->privateData = NULL;
|
||||
|
||||
return 0;
|
||||
@ -794,6 +801,12 @@ static int openvzGetNodeInfo(virConnectPtr conn,
|
||||
return virNodeInfoPopulate(conn, nodeinfo);
|
||||
}
|
||||
|
||||
static char *openvzGetCapabilities(virConnectPtr conn) {
|
||||
struct openvz_driver *driver = (struct openvz_driver *)conn->privateData;
|
||||
|
||||
return virCapabilitiesFormatXML(driver->caps);
|
||||
}
|
||||
|
||||
static int openvzListDomains(virConnectPtr conn, int *ids, int nids) {
|
||||
int got = 0;
|
||||
int veid, pid;
|
||||
@ -829,14 +842,22 @@ static int openvzListDomains(virConnectPtr conn, int *ids, int nids) {
|
||||
}
|
||||
|
||||
static int openvzNumDomains(virConnectPtr conn ATTRIBUTE_UNUSED) {
|
||||
return ovz_driver.num_active;
|
||||
struct openvz_driver *driver = conn->privateData;
|
||||
int nactive = 0;
|
||||
virDomainObjPtr vm = driver->domains;
|
||||
while (vm) {
|
||||
if (virDomainIsActive(vm))
|
||||
nactive++;
|
||||
vm = vm->next;
|
||||
}
|
||||
return nactive;
|
||||
}
|
||||
|
||||
static int openvzListDefinedDomains(virConnectPtr conn,
|
||||
char **const names, int nnames) {
|
||||
char **const names, int nnames) {
|
||||
int got = 0;
|
||||
int veid, pid, outfd = -1, errfd = -1, ret;
|
||||
char vpsname[OPENVZ_NAME_MAX];
|
||||
char vpsname[32];
|
||||
char buf[32];
|
||||
char *endptr;
|
||||
const char *cmd[] = {VZLIST, "-ovpsid", "-H", "-S", NULL};
|
||||
@ -858,12 +879,19 @@ static int openvzListDefinedDomains(virConnectPtr conn,
|
||||
_("Could not parse VPS ID %s"), buf);
|
||||
continue;
|
||||
}
|
||||
sprintf(vpsname, "%d", veid);
|
||||
names[got] = strdup(vpsname);
|
||||
snprintf(vpsname, sizeof(vpsname), "%d", veid);
|
||||
if (!(names[got] = strdup(vpsname)))
|
||||
goto no_memory;
|
||||
got ++;
|
||||
}
|
||||
waitpid(pid, NULL, 0);
|
||||
return got;
|
||||
|
||||
no_memory:
|
||||
openvzError(conn, VIR_ERR_NO_MEMORY, NULL);
|
||||
for ( ; got >= 0 ; got--)
|
||||
VIR_FREE(names[got]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int openvzGetProcessInfo(unsigned long long *cpuTime, int vpsid) {
|
||||
@ -911,8 +939,16 @@ Version: 2.2
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int openvzNumDefinedDomains(virConnectPtr conn ATTRIBUTE_UNUSED) {
|
||||
return ovz_driver.num_inactive;
|
||||
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;
|
||||
}
|
||||
|
||||
static virDriver openvzDriver = {
|
||||
@ -929,7 +965,7 @@ static virDriver openvzDriver = {
|
||||
NULL, /* uri */
|
||||
openvzGetMaxVCPUs, /* getMaxVcpus */
|
||||
openvzGetNodeInfo, /* nodeGetInfo */
|
||||
NULL, /* getCapabilities */
|
||||
openvzGetCapabilities, /* getCapabilities */
|
||||
openvzListDomains, /* listDomains */
|
||||
openvzNumDomains, /* numOfDomains */
|
||||
openvzDomainCreateLinux, /* domainCreateLinux */
|
||||
@ -953,7 +989,7 @@ static virDriver openvzDriver = {
|
||||
NULL, /* domainPinVcpu */
|
||||
NULL, /* domainGetVcpus */
|
||||
openvzDomainGetMaxVcpus, /* domainGetMaxVcpus */
|
||||
NULL, /* domainDumpXML */
|
||||
openvzDomainDumpXML, /* domainDumpXML */
|
||||
openvzListDefinedDomains, /* listDomains */
|
||||
openvzNumDefinedDomains, /* numOfDomains */
|
||||
openvzDomainCreate, /* domainCreate */
|
||||
|
@ -31,24 +31,6 @@
|
||||
|
||||
#include "internal.h"
|
||||
|
||||
/* OpenVZ commands - Replace with wrapper scripts later? */
|
||||
#define VZLIST "vzlist"
|
||||
#define VZCTL "vzctl"
|
||||
|
||||
struct openvz_driver {
|
||||
struct openvz_vm *vms;
|
||||
int num_active;
|
||||
int num_inactive;
|
||||
};
|
||||
|
||||
int openvzRegister(void);
|
||||
|
||||
#define openvzLog(level, msg...) { if(level == OPENVZ_WARN) \
|
||||
fprintf(stderr, "\nWARNING: ");\
|
||||
else \
|
||||
fprintf(stderr, "\nERROR: ");\
|
||||
fprintf(stderr, "\n\t");\
|
||||
fprintf(stderr, msg);\
|
||||
fprintf(stderr, "\n"); }
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user