/* * openvz_driver.c: core driver methods for managing OpenVZ VEs * * Copyright (C) 2006, 2007 Binary Karma * Copyright (C) 2006 Shuveb Hussain * Copyright (C) 2007 Anoop Joe Cyriac * * 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 * * Authors: * Shuveb Hussain * Anoop Joe Cyriac * */ #ifdef WITH_OPENVZ #include #define _GNU_SOURCE /* for asprintf */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "openvz_driver.h" #include "event.h" #include "buf.h" #include "util.h" #include "openvz_conf.h" #include "nodeinfo.h" #define OPENVZ_MAX_ARG 28 #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, const char *name, 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 int openvzStartup(void); static int openvzShutdown(void); static int openvzReload(void); static int openvzActive(void); static int openvzCloseNetwork(virConnectPtr conn); static virDrvOpenStatus openvzOpenNetwork(virConnectPtr conn, const char *name ATTRIBUTE_UNUSED, int flags ATTRIBUTE_UNUSED); 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 int convCmdbufExec(char cmdbuf[], char *cmdExec[]); static void cmdExecFree(char *cmdExec[]); struct openvz_driver ovz_driver; static int convCmdbufExec(char cmdbuf[], char *cmdExec[]) { int i=0, limit = OPENVZ_MAX_ARG - 1; char cmdWord[CMDOP_LEN]; while(*cmdbuf) { if(i >= limit) { cmdExec[i] = NULL; return -1; } sscanf(cmdbuf, "%s", cmdWord); cmdbuf += strlen(cmdWord); while(*cmdbuf == ' ') cmdbuf++; cmdExec[i++] = strdup(cmdWord); } cmdExec[i] = NULL; return i; } static void cmdExecFree(char *cmdExec[]) { int i=-1; while(cmdExec[++i]) { free(cmdExec[i]); cmdExec[i] = NULL; } } /* For errors internal to this library. */ static void error (virConnectPtr conn, virErrorNumber code, const char *info) { const char *errmsg; errmsg = __virErrorMsg (code, info); __virRaiseError (conn, NULL, NULL, VIR_FROM_OPENVZ, code, VIR_ERR_ERROR, errmsg, info, NULL, 0, 0, errmsg, info); } static virDomainPtr openvzDomainLookupByID(virConnectPtr conn, int id) { struct openvz_driver *driver = (struct openvz_driver *)conn->privateData; struct openvz_vm *vm = openvzFindVMByID(driver, id); virDomainPtr dom; if (!vm) { error(conn, VIR_ERR_INTERNAL_ERROR, "no domain with matching id"); return NULL; } dom = virGetDomain(conn, vm->vmdef->name, vm->vmdef->uuid); if (!dom) { error(conn, VIR_ERR_NO_MEMORY, "virDomainPtr"); return NULL; } dom->id = vm->vpsid; return dom; } static char *openvzGetOSType(virDomainPtr dom ATTRIBUTE_UNUSED) { /* OpenVZ runs on Linux and runs only Linux */ return strdup("linux"); } static virDomainPtr openvzDomainLookupByUUID(virConnectPtr conn, const unsigned char *uuid) { struct openvz_driver *driver = (struct openvz_driver *)conn->privateData; struct openvz_vm *vm = openvzFindVMByUUID(driver, uuid); virDomainPtr dom; if (!vm) { error(conn, VIR_ERR_INVALID_DOMAIN, "no domain with matching uuid"); return NULL; } dom = virGetDomain(conn, vm->vmdef->name, vm->vmdef->uuid); if (!dom) { error(conn, VIR_ERR_NO_MEMORY, "virDomainPtr"); return NULL; } dom->id = vm->vpsid; 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); virDomainPtr dom; if (!vm) { error(conn, VIR_ERR_INTERNAL_ERROR, "no domain with matching name"); return NULL; } dom = virGetDomain(conn, vm->vmdef->name, vm->vmdef->uuid); if (!dom) { error(conn, VIR_ERR_NO_MEMORY, "virDomainPtr"); return NULL; } dom->id = vm->vpsid; return dom; } static int openvzDomainGetInfo(virDomainPtr dom, virDomainInfoPtr info) { struct openvz_driver *driver = (struct openvz_driver *)dom->conn->privateData; struct openvz_vm *vm = openvzFindVMByUUID(driver, dom->uuid); if (!vm) { error(dom->conn, VIR_ERR_INVALID_DOMAIN, "no domain with matching uuid"); return -1; } info->state = vm->status; /* TODO These need to be calculated differently for OpenVZ */ //info->cpuTime = //info->maxMem = vm->def->maxmem; //info->memory = vm->def->memory; //info->nrVirtCpu = vm->def->vcpus; return 0; } static int openvzDomainShutdown(virDomainPtr dom) { char cmdbuf[CMDBUF_LEN]; int ret; char *cmdExec[OPENVZ_MAX_ARG]; int pid, outfd, errfd; struct openvz_driver *driver = (struct openvz_driver *)dom->conn->privateData; struct openvz_vm *vm = openvzFindVMByID(driver, dom->id); if (!vm) { error(dom->conn, VIR_ERR_INVALID_DOMAIN, "no domain with matching id"); return -1; } if (vm->status != VIR_DOMAIN_RUNNING) { error(dom->conn, VIR_ERR_OPERATION_DENIED, "domain is not in running state"); return -1; } snprintf(cmdbuf, CMDBUF_LEN - 1, VZCTL " stop %d ", dom->id); if((ret = convCmdbufExec(cmdbuf, cmdExec)) == -1) { openvzLog(OPENVZ_ERR, "Error in parsing Options to OPENVZ"); goto bail_out; } ret = virExec(dom->conn, (char **)cmdExec, &pid, -1, &outfd, &errfd); if(ret == -1) { error(dom->conn, VIR_ERR_INTERNAL_ERROR, "Could not exec " VZLIST); return -1; } vm->vpsid = -1; vm->status = VIR_DOMAIN_SHUTOFF; ovz_driver.num_inactive ++; ovz_driver.num_active --; bail_out: cmdExecFree(cmdExec); return ret; } static int openvzDomainReboot(virDomainPtr dom, unsigned int flags ATTRIBUTE_UNUSED) { char cmdbuf[CMDBUF_LEN]; int ret; char *cmdExec[OPENVZ_MAX_ARG]; int pid, outfd, errfd; struct openvz_driver *driver = (struct openvz_driver *)dom->conn->privateData; struct openvz_vm *vm = openvzFindVMByID(driver, dom->id); if (!vm) { error(dom->conn, VIR_ERR_INVALID_DOMAIN, "no domain with matching id"); return -1; } if (vm->status != VIR_DOMAIN_RUNNING) { error(dom->conn, VIR_ERR_OPERATION_DENIED, "domain is not in running state"); return -1; } snprintf(cmdbuf, CMDBUF_LEN - 1, VZCTL " restart %d ", dom->id); if((ret = convCmdbufExec(cmdbuf, cmdExec)) == -1) { openvzLog(OPENVZ_ERR, "Error in parsing Options to OPENVZ"); goto bail_out1; } ret = virExec(dom->conn, (char **)cmdExec, &pid, -1, &outfd, &errfd); if(ret == -1) { error(dom->conn, VIR_ERR_INTERNAL_ERROR, "Could not exec " VZLIST); return -1; } bail_out1: cmdExecFree(cmdExec); return ret; } 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; virDomainPtr dom; char cmdbuf[CMDBUF_LEN], cmdOption[CMDOP_LEN], *cmdExec[OPENVZ_MAX_ARG]; int ret, pid, outfd, errfd; if (!(vmdef = openvzParseVMDef(conn, xml, NULL))) goto bail_out2; vm = openvzFindVMByID(driver, strtoI(vmdef->name)); if (vm) { openvzLog(OPENVZ_ERR, "Already an OPENVZ VM active with the id '%s'", vmdef->name); goto bail_out2; } if (!(vm = openvzAssignVMDef(conn, driver, vmdef))) { openvzFreeVMDef(vmdef); openvzLog(OPENVZ_ERR, "Error creating OPENVZ VM"); } snprintf(cmdbuf, CMDBUF_LEN - 1, VZCTL " create %s", vmdef->name); if ((vmdef->fs.tmpl && *(vmdef->fs.tmpl))) { snprintf(cmdOption, CMDOP_LEN - 1, " --ostemplate %s", vmdef->fs.tmpl); strcat(cmdbuf, cmdOption); } if ((vmdef->profile && *(vmdef->profile))) { snprintf(cmdOption, CMDOP_LEN - 1, " --config %s", vmdef->profile); strcat(cmdbuf, cmdOption); } if ((vmdef->net.ips->ip && *(vmdef->net.ips->ip))) { snprintf(cmdOption, CMDOP_LEN - 1, " --ipadd %s", vmdef->net.ips->ip); strcat(cmdbuf, cmdOption); } if ((vmdef->net.hostname && *(vmdef->net.hostname))) { snprintf(cmdOption, CMDOP_LEN - 1, " --hostname %s", vmdef->net.hostname); strcat(cmdbuf, cmdOption); } if((ret = convCmdbufExec(cmdbuf, cmdExec)) == -1) { openvzLog(OPENVZ_ERR, "Error in parsing Options to OPENVZ"); goto bail_out2; } ret = virExec(conn, (char **)cmdExec, &pid, -1, &outfd, &errfd); if(ret == -1) { error(conn, VIR_ERR_INTERNAL_ERROR, "Could not exec " VZLIST); goto bail_out2; } waitpid(pid, NULL, 0); cmdExecFree(cmdExec); dom = virGetDomain(conn, vm->vmdef->name, vm->vmdef->uuid); if (dom) dom->id = vm->vpsid; return dom; bail_out2: cmdExecFree(cmdExec); return NULL; } static virDomainPtr openvzDomainCreateLinux(virConnectPtr conn, const char *xml, unsigned int flags ATTRIBUTE_UNUSED) { struct openvz_vm_def *vmdef = NULL; struct openvz_vm *vm = NULL; virDomainPtr dom; struct openvz_driver *driver = (struct openvz_driver *) conn->privateData; char cmdbuf[CMDBUF_LEN], cmdOption[CMDOP_LEN], *cmdExec[OPENVZ_MAX_ARG]; int ret, pid, outfd, errfd; if (!(vmdef = openvzParseVMDef(conn, xml, NULL))) return NULL; vm = openvzFindVMByID(driver, strtoI(vmdef->name)); if (vm) { openvzFreeVMDef(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, "Error creating OPENVZ VM"); return NULL; } snprintf(cmdbuf, CMDBUF_LEN - 1, VZCTL " create %s", vmdef->name); if ((vmdef->fs.tmpl && *(vmdef->fs.tmpl))) { snprintf(cmdOption, CMDOP_LEN - 1, " --ostemplate %s", vmdef->fs.tmpl); strcat(cmdbuf, cmdOption); } if ((vmdef->profile && *(vmdef->profile))) { snprintf(cmdOption, CMDOP_LEN - 1, " --config %s", vmdef->profile); strcat(cmdbuf, cmdOption); } if ((vmdef->net.ips->ip && *(vmdef->net.ips->ip))) { snprintf(cmdOption, CMDOP_LEN - 1, " --ipadd %s", vmdef->net.ips->ip); strcat(cmdbuf, cmdOption); } if ((vmdef->net.hostname && *(vmdef->net.hostname))) { snprintf(cmdOption, CMDOP_LEN - 1, " --hostname %s", vmdef->net.hostname); strcat(cmdbuf, cmdOption); } if((ret = convCmdbufExec(cmdbuf, cmdExec)) == -1) { openvzLog(OPENVZ_ERR, "Error in parsing Options to OPENVZ"); goto bail_out3; } ret = virExec(conn, (char **)cmdExec, &pid, -1, &outfd, &errfd); if(ret == -1) { error(conn, VIR_ERR_INTERNAL_ERROR, "Could not exec " VZLIST); return NULL; } waitpid(pid, NULL, 0); cmdExecFree(cmdExec); snprintf(cmdbuf, CMDBUF_LEN - 1, VZCTL " start %s ", vmdef->name); if((ret = convCmdbufExec(cmdbuf, cmdExec)) == -1) { openvzLog(OPENVZ_ERR, "Error in parsing Options to OPENVZ"); goto bail_out3; } ret = virExec(conn, (char **)cmdExec, &pid, -1, &outfd, &errfd); if(ret == -1) { error(conn, VIR_ERR_INTERNAL_ERROR, "Could not exec " VZLIST); return NULL; } sscanf(vmdef->name, "%d", &vm->vpsid); vm->status = VIR_DOMAIN_RUNNING; ovz_driver.num_inactive--; ovz_driver.num_active++; waitpid(pid, NULL, 0); cmdExecFree(cmdExec); dom = virGetDomain(conn, vm->vmdef->name, vm->vmdef->uuid); if (dom) dom->id = vm->vpsid; return dom; bail_out3: cmdExecFree(cmdExec); return NULL; } static int openvzDomainCreate(virDomainPtr dom) { char cmdbuf[CMDBUF_LEN]; int ret; char *cmdExec[OPENVZ_MAX_ARG] ; int pid, outfd, errfd; struct openvz_driver *driver = (struct openvz_driver *)dom->conn->privateData; struct openvz_vm *vm = openvzFindVMByName(driver, dom->name); struct openvz_vm_def *vmdef; if (!vm) { error(dom->conn, VIR_ERR_INVALID_DOMAIN, "no domain with matching id"); return -1; } if (vm->status != VIR_DOMAIN_SHUTOFF) { error(dom->conn, VIR_ERR_OPERATION_DENIED, "domain is not in shutoff state"); return -1; } vmdef = vm->vmdef; snprintf(cmdbuf, CMDBUF_LEN - 1, VZCTL " start %s ", vmdef->name); if((ret = convCmdbufExec(cmdbuf, cmdExec)) == -1) { openvzLog(OPENVZ_ERR, "Error in parsing Options to OPENVZ"); goto bail_out4; } ret = virExec(dom->conn, (char **)cmdExec, &pid, -1, &outfd, &errfd); if(ret == -1) { error(dom->conn, VIR_ERR_INTERNAL_ERROR, "Could not exec " VZLIST); return -1; } sscanf(vmdef->name, "%d", &vm->vpsid); vm->status = VIR_DOMAIN_RUNNING; ovz_driver.num_inactive --; ovz_driver.num_active ++; waitpid(pid, NULL, 0); bail_out4: cmdExecFree(cmdExec); return ret; } static int openvzDomainUndefine(virDomainPtr dom) { char cmdbuf[CMDBUF_LEN], *cmdExec[OPENVZ_MAX_ARG]; int ret, pid, outfd, errfd; virConnectPtr conn= dom->conn; struct openvz_driver *driver = (struct openvz_driver *) conn->privateData; struct openvz_vm *vm = openvzFindVMByUUID(driver, dom->uuid); if (!vm) { error(conn, VIR_ERR_INVALID_DOMAIN, "no domain with matching uuid"); return -1; } if (openvzIsActiveVM(vm)) { error(conn, VIR_ERR_INTERNAL_ERROR, "cannot delete active domain"); return -1; } snprintf(cmdbuf, CMDBUF_LEN - 1, VZCTL " destroy %s ", vm->vmdef->name); if((ret = convCmdbufExec(cmdbuf, cmdExec)) == -1) { openvzLog(OPENVZ_ERR, "Error in parsing Options to OPENVZ"); goto bail_out5; } ret = virExec(conn, (char **)cmdExec, &pid, -1, &outfd, &errfd); if(ret == -1) { error(conn, VIR_ERR_INTERNAL_ERROR, "Could not exec " VZLIST); return -1; } waitpid(pid, NULL, 0); openvzRemoveInactiveVM(driver, vm); bail_out5: cmdExecFree(cmdExec); return ret; } static virDrvOpenStatus openvzOpen(virConnectPtr conn, const char *name, int flags ATTRIBUTE_UNUSED) { struct openvz_vm *vms; /* Just check if the guy 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 (strcmp(name, "openvz:///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; } conn->privateData = &ovz_driver; virStateInitialize(); vms = openvzGetVPSInfo(conn); ovz_driver.vms = vms; return VIR_DRV_OPEN_SUCCESS; } 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); } conn->privateData = NULL; return 0; } static const char *openvzGetType(virConnectPtr conn ATTRIBUTE_UNUSED) { return strdup("OpenVZ"); } static int openvzGetNodeInfo(virConnectPtr conn, virNodeInfoPtr nodeinfo) { return virNodeInfoPopulate(conn, nodeinfo); } static int openvzListDomains(virConnectPtr conn, int *ids, int nids) { int got = 0; int veid, pid, outfd, errfd; int ret; char buf[32]; const char *cmd[] = {VZLIST, "-ovpsid", "-H" , NULL}; ret = virExec(conn, (char **)cmd, &pid, -1, &outfd, &errfd); if(ret == -1) { error(conn, VIR_ERR_INTERNAL_ERROR, "Could not exec " VZLIST); return (int)NULL; } while(got < nids){ ret = openvz_readline(outfd, buf, 32); if(!ret) break; sscanf(buf, "%d", &veid); ids[got] = veid; got ++; } waitpid(pid, NULL, 0); return got; } static int openvzNumDomains(virConnectPtr conn ATTRIBUTE_UNUSED) { return ovz_driver.num_active; } static int openvzListDefinedDomains(virConnectPtr conn, char **const names, int nnames) { int got = 0; int veid, pid, outfd, errfd, ret; char vpsname[OPENVZ_NAME_MAX]; char buf[32]; const char *cmd[] = {VZLIST, "-ovpsid", "-H", "-S", NULL}; /* the -S options lists only stopped domains */ ret = virExec(conn, (char **)cmd, &pid, -1, &outfd, &errfd); if(ret == -1) { error(conn, VIR_ERR_INTERNAL_ERROR, "Could not exec " VZLIST); return (int)NULL; } while(got < nnames){ ret = openvz_readline(outfd, buf, 32); if(!ret) break; sscanf(buf, "%d\n", &veid); sprintf(vpsname, "%d", veid); names[got] = strdup(vpsname); got ++; } waitpid(pid, NULL, 0); return got; } static int openvzNumDefinedDomains(virConnectPtr conn ATTRIBUTE_UNUSED) { return ovz_driver.num_inactive; } static int openvzStartup(void) { openvzAssignUUIDs(); return 0; } static int openvzShutdown(void) { return 0; } static int openvzReload(void) { return 0; } static int openvzActive(void) { return 1; } static int openvzCloseNetwork(virConnectPtr conn ATTRIBUTE_UNUSED) { return 0; } static virDrvOpenStatus openvzOpenNetwork(virConnectPtr conn ATTRIBUTE_UNUSED, const char *name ATTRIBUTE_UNUSED, int flags ATTRIBUTE_UNUSED) { return VIR_DRV_OPEN_SUCCESS; } static virDriver openvzDriver = { VIR_DRV_OPENVZ, "OPENVZ", LIBVIR_VERSION_NUMBER, openvzOpen, /* open */ openvzClose, /* close */ NULL, /* supports_feature */ openvzGetType, /* type */ NULL, /* version */ NULL, /* hostname */ NULL, /* uri */ NULL, /* getMaxVcpus */ openvzGetNodeInfo, /* nodeGetInfo */ NULL, /* getCapabilities */ openvzListDomains, /* listDomains */ openvzNumDomains, /* numOfDomains */ openvzDomainCreateLinux, /* domainCreateLinux */ 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 */ NULL, /* domainSetVcpus */ NULL, /* domainPinVcpu */ NULL, /* domainGetVcpus */ NULL, /* domainGetMaxVcpus */ NULL, /* domainDumpXML */ openvzListDefinedDomains, /* listDomains */ openvzNumDefinedDomains, /* numOfDomains */ openvzDomainCreate, /* domainCreate */ openvzDomainDefineXML, /* domainDefineXML */ openvzDomainUndefine, /* domainUndefine */ NULL, /* domainAttachDevice */ NULL, /* domainDetachDevice */ NULL, /* domainGetAutostart */ NULL, /* domainSetAutostart */ NULL, /* domainGetSchedulerType */ NULL, /* domainGetSchedulerParameters */ NULL, /* domainSetSchedulerParameters */ NULL, /* domainMigratePrepare */ NULL, /* domainMigratePerform */ NULL, /* domainMigrateFinish */ NULL, /* domainBlockStats */ NULL, /* domainInterfaceStats */ NULL, /* nodeGetCellsFreeMemory */ NULL, /* nodeGetFreeMemory */ }; static virNetworkDriver openvzNetworkDriver = { NULL, /* name */ openvzOpenNetwork, /* open */ openvzCloseNetwork, /* close */ NULL, /* numOfNetworks */ NULL, /* listNetworks */ NULL, /* numOfDefinedNetworks */ NULL, /* listDefinedNetworks */ NULL, /* networkLookupByUUID */ NULL, /* networkLookupByName */ NULL, /* networkCreateXML */ NULL, /* networkDefineXML */ NULL, /* networkUndefine */ NULL, /* networkCreate */ NULL, /* networkDestroy */ NULL, /* networkDumpXML */ NULL, /* networkGetBridgeName */ NULL, /* networkGetAutostart */ NULL, /* networkSetAutostart */ }; static virStateDriver openvzStateDriver = { openvzStartup, openvzShutdown, openvzReload, openvzActive, }; int openvzRegister(void) { virRegisterDriver(&openvzDriver); virRegisterNetworkDriver(&openvzNetworkDriver); virRegisterStateDriver(&openvzStateDriver); return 0; } #endif /* WITH_OPENVZ */ /* * Local variables: * indent-tabs-mode: nil * c-indent-level: 4 * c-basic-offset: 4 * tab-width: 4 * End: */