* src/Makefile.am src/openvz_conf.c src/openvz_conf.h

src/openvz_driver.c src/qemu_driver.c src/util.c src/util.h:
  cleanup patches from Shuveb Hussain, with new util module for
  common code shared between drivers.
Daniel
This commit is contained in:
Daniel Veillard 2007-07-19 16:22:40 +00:00
parent e2ea955881
commit 68ef3443d4
9 changed files with 289 additions and 129 deletions

View File

@ -1,3 +1,10 @@
Thu Jul 19 18:21:47 CEST 2007 Daniel Veillard <veillard@redhat.com>
* src/Makefile.am src/openvz_conf.c src/openvz_conf.h
src/openvz_driver.c src/qemu_driver.c src/util.c src/util.h:
cleanup patches from Shuveb Hussain, with new util module for
common code shared between drivers.
Thu Jul 19 16:35:00 BST 2007 Richard W.M. Jones <rjones@redhat.com>
* configure.in, src/xen_internal.c: Newer Xen uses

View File

@ -51,6 +51,7 @@ typedef enum {
VIR_FROM_NET, /* Error when operating on a network */
VIR_FROM_TEST, /* Error from test driver */
VIR_FROM_REMOTE, /* Error from remote driver */
VIR_FROM_OPENVZ, /* Error from OpenVZ driver */
} virErrorDomain;

View File

@ -49,7 +49,8 @@ CLIENT_SOURCES = \
qemu_driver.c qemu_driver.h \
qemu_conf.c qemu_conf.h \
openvz_conf.c openvz_conf.h \
openvz_driver.c openvz_driver.h
openvz_driver.c openvz_driver.h \
util.c util.h
SERVER_SOURCES = \
../qemud/protocol.h ../qemud/protocol.c \

View File

@ -57,7 +57,8 @@ error (virConnectPtr conn, virErrorNumber code, const char *info)
errmsg, info);
}
struct openvz_vm *openvzFindVMByID(const struct openvz_driver *driver, int id) {
struct openvz_vm
*openvzFindVMByID(const struct openvz_driver *driver, int id) {
struct openvz_vm *vm = driver->vms;
while (vm) {
@ -69,7 +70,8 @@ struct openvz_vm *openvzFindVMByID(const struct openvz_driver *driver, int id) {
return NULL;
}
struct openvz_vm *openvzFindVMByUUID(const struct openvz_driver *driver,
struct openvz_vm
*openvzFindVMByUUID(const struct openvz_driver *driver,
const unsigned char *uuid) {
struct openvz_vm *vm = driver->vms;
@ -82,7 +84,8 @@ struct openvz_vm *openvzFindVMByUUID(const struct openvz_driver *driver,
return NULL;
}
struct openvz_vm *openvzFindVMByName(const struct openvz_driver *driver,
struct openvz_vm
*openvzFindVMByName(const struct openvz_driver *driver,
const char *name) {
struct openvz_vm *vm = driver->vms;
@ -96,7 +99,8 @@ struct openvz_vm *openvzFindVMByName(const struct openvz_driver *driver,
}
/* Free all memory associated with a struct openvz_vm object */
void openvzFreeVMDef(struct openvz_vm_def *def) {
void
openvzFreeVMDef(struct openvz_vm_def *def) {
struct ovz_quota *quota = def->fs.quota;
struct ovz_ip *ip = def->net.ips;
struct ovz_ns *ns = def->net.ns;
@ -124,8 +128,9 @@ void openvzFreeVMDef(struct openvz_vm_def *def) {
* 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) {
static struct openvz_vm_def
*openvzParseXML(virConnectPtr conn,
xmlDocPtr xml) {
xmlNodePtr root = NULL;
xmlChar *prop = NULL;
xmlXPathContextPtr ctxt = NULL;
@ -249,7 +254,7 @@ openvzGetVPSInfo(virConnectPtr conn) {
FILE *fp;
int veid, ret;
char status[16];
char uuidstr[(VIR_UUID_BUFLEN * 2) + 1];
char uuidstr[VIR_UUID_STRING_BUFLEN];
struct openvz_vm *vm;
struct openvz_vm **pnext;
struct openvz_driver *driver;
@ -296,15 +301,9 @@ openvzGetVPSInfo(virConnectPtr conn) {
snprintf(vmdef->name, OPENVZ_NAME_MAX, "%i", veid);
openvzGetVPSUUID(veid, uuidstr);
ret = sscanf(uuidstr, "%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
(unsigned int *)&vmdef->uuid[0], (unsigned int *)&vmdef->uuid[1], (unsigned int *)&vmdef->uuid[2],
(unsigned int *)&vmdef->uuid[3], (unsigned int *)&vmdef->uuid[4], (unsigned int *)&vmdef->uuid[5],
(unsigned int *)&vmdef->uuid[6], (unsigned int *)&vmdef->uuid[7], (unsigned int *)&vmdef->uuid[8],
(unsigned int *)&vmdef->uuid[9], (unsigned int *)&vmdef->uuid[10], (unsigned int *)&vmdef->uuid[11],
(unsigned int *)&vmdef->uuid[12], (unsigned int *)&vmdef->uuid[13], (unsigned int *)&vmdef->uuid[14],
(unsigned int *)&vmdef->uuid[15]);
ret = virUUIDParse(uuidstr, vmdef->uuid);
if(ret != 16) {
if(ret == -1) {
error(conn, VIR_ERR_INTERNAL_ERROR, "UUID in config file malformed");
return NULL;
}
@ -315,7 +314,8 @@ openvzGetVPSInfo(virConnectPtr conn) {
return vm;
}
char *openvzLocateConfDir(void)
static char
*openvzLocateConfDir(void)
{
const char *conf_dir_list[] = {"/etc/vz/conf", "/usr/local/etc/conf", NULL};
int i=0;
@ -330,9 +330,8 @@ char *openvzLocateConfDir(void)
}
/* Richard Steven's classic readline() function */
static
int openvz_readline(int fd, char *ptr, int maxlen)
int
openvz_readline(int fd, char *ptr, int maxlen)
{
int n, rc;
char c;
@ -356,7 +355,8 @@ int openvz_readline(int fd, char *ptr, int maxlen)
return n;
}
int openvzGetVPSUUID(int vpsid, char *uuidbuf)
static int
openvzGetVPSUUID(int vpsid, char *uuidbuf)
{
char conf_file[PATH_MAX];
char line[1024];
@ -385,7 +385,7 @@ int openvzGetVPSUUID(int vpsid, char *uuidbuf)
sscanf(line, "%s %s\n", iden, uuid);
if(!strcmp(iden, "#UUID:")) {
strncpy(uuidbuf, uuid, (VIR_UUID_BUFLEN * 2) +1);
strncpy(uuidbuf, uuid, VIR_UUID_STRING_BUFLEN);
break;
}
}
@ -396,10 +396,11 @@ int openvzGetVPSUUID(int vpsid, char *uuidbuf)
* assign if not present.
*/
int openvzSetUUID(int vpsid)
static int
openvzSetUUID(int vpsid)
{
char conf_file[PATH_MAX];
char uuid[(VIR_UUID_BUFLEN * 2) + 1];
char uuid[VIR_UUID_STRING_BUFLEN];
unsigned char new_uuid[VIR_UUID_BUFLEN];
char *conf_dir;
int fd, ret, i;
@ -418,7 +419,7 @@ int openvzSetUUID(int vpsid)
if(uuid[0] == (int)NULL) {
virUUIDGenerate(new_uuid);
bzero(uuid, (VIR_UUID_BUFLEN * 2) + 1);
bzero(uuid, VIR_UUID_STRING_BUFLEN);
for(i = 0; i < VIR_UUID_BUFLEN; i ++)
sprintf(uuid + (i * 2), "%02x", (unsigned char)new_uuid[i]);

View File

@ -94,8 +94,8 @@ struct openvz_vm {
struct openvz_vm *next;
};
char *openvzLocateConfDir(void);
int readline(int fd, char *ptr, int maxlen);
static char *openvzLocateConfDir(void);
int openvz_readline(int fd, char *ptr, int maxlen);
static void error (virConnectPtr conn, virErrorNumber code, const char *info);
struct openvz_vm *openvzFindVMByID(const struct openvz_driver *driver, int id);
struct openvz_vm *openvzFindVMByUUID(const struct openvz_driver *driver,
@ -108,7 +108,7 @@ struct openvz_vm_def *openvzParseVMDef(virConnectPtr conn, const char *xmlStr,
const char *displayName);
struct openvz_vm *openvzGetVPSInfo(virConnectPtr conn);
void openvzGenerateUUID(unsigned char *uuid);
int openvzGetVPSUUID(int vpsid, char *uuidbuf);
int openvzSetUUID(int vpsid);
static int openvzGetVPSUUID(int vpsid, char *uuidbuf);
static int openvzSetUUID(int vpsid);
int openvzAssignUUIDs(void);
#endif /* OPENVZ_CONF_H */

View File

@ -52,6 +52,7 @@
#include "event.h"
#include "buf.h"
#include "util.h"
#include "openvz_driver.h"
#include "openvz_conf.h"
@ -284,6 +285,11 @@ static virDrvOpenStatus openvzOpen(virConnectPtr conn,
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;
@ -323,19 +329,25 @@ static const char *openvzGetType(virConnectPtr conn ATTRIBUTE_UNUSED) {
static int openvzListDomains(virConnectPtr conn, int *ids, int nids) {
int got = 0;
int veid;
FILE *fp;
int veid, pid, outfd, errfd;
int ret;
char buf[32];
const char *cmd[] = {VZLIST, "-ovpsid", "-H" , NULL};
if((fp = popen(VZLIST " -o vpsid -H 2> /dev/null", "r")) == NULL){
error(conn, VIR_ERR_INTERNAL_ERROR, "Could not popen " VZLIST);
ret = virExec(conn, (char **)cmd, &pid, &outfd, &errfd);
if(ret == -1) {
error(conn, VIR_ERR_INTERNAL_ERROR, "Could not exec " VZLIST);
return (int)NULL;
}
while(!(feof(fp)) && got < nids){
fscanf(fp, "%d\n", &veid);
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;
}
@ -347,23 +359,27 @@ static int openvzNumDomains(virConnectPtr conn) {
static int openvzListDefinedDomains(virConnectPtr conn,
char **const names, int nnames) {
int got = 0;
FILE *fp;
int veid;
int veid, pid, outfd, errfd, ret;
char vpsname[OPENVZ_NAME_MAX];
char buf[32];
const char *cmd[] = {VZLIST, "-ovpsid", "-H", NULL};
/* the -S options lists only stopped domains */
if((fp = popen(VZLIST " -S -o vpsid -H 2> /dev/null", "r")) == NULL){
error(conn, VIR_ERR_INTERNAL_ERROR, "Could not popen " VZLIST);
ret = virExec(conn, (char **)cmd, &pid, &outfd, &errfd);
if(ret == -1) {
error(conn, VIR_ERR_INTERNAL_ERROR, "Could not exec " VZLIST);
return (int)NULL;
}
while(!(feof(fp)) && got < nnames){
fscanf(fp, "%d\n", &veid);
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;
}

View File

@ -50,6 +50,7 @@
#include "event.h"
#include "buf.h"
#include "util.h"
#include "qemu_driver.h"
#include "qemu_conf.h"
@ -330,91 +331,6 @@ qemudShutdown(void) {
return 0;
}
static int
qemudExec(virConnectPtr conn,
char **argv,
int *retpid, int *outfd, int *errfd) {
int pid, null;
int pipeout[2] = {-1,-1};
int pipeerr[2] = {-1,-1};
if ((null = open(_PATH_DEVNULL, O_RDONLY)) < 0) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "cannot open %s : %s",
_PATH_DEVNULL, strerror(errno));
goto cleanup;
}
if ((outfd != NULL && pipe(pipeout) < 0) ||
(errfd != NULL && pipe(pipeerr) < 0)) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "cannot create pipe : %s",
strerror(errno));
goto cleanup;
}
if ((pid = fork()) < 0) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "cannot fork child process : %s",
strerror(errno));
goto cleanup;
}
if (pid) { /* parent */
close(null);
if (outfd) {
close(pipeout[1]);
qemudSetNonBlock(pipeout[0]);
qemudSetCloseExec(pipeout[0]);
*outfd = pipeout[0];
}
if (errfd) {
close(pipeerr[1]);
qemudSetNonBlock(pipeerr[0]);
qemudSetCloseExec(pipeerr[0]);
*errfd = pipeerr[0];
}
*retpid = pid;
return 0;
}
/* child */
if (pipeout[0] > 0 && close(pipeout[0]) < 0)
_exit(1);
if (pipeerr[0] > 0 && close(pipeerr[0]) < 0)
_exit(1);
if (dup2(null, STDIN_FILENO) < 0)
_exit(1);
if (dup2(pipeout[1] > 0 ? pipeout[1] : null, STDOUT_FILENO) < 0)
_exit(1);
if (dup2(pipeerr[1] > 0 ? pipeerr[1] : null, STDERR_FILENO) < 0)
_exit(1);
close(null);
if (pipeout[1] > 0)
close(pipeout[1]);
if (pipeerr[1] > 0)
close(pipeerr[1]);
execvp(argv[0], argv);
_exit(1);
return 0;
cleanup:
if (pipeerr[0] > 0)
close(pipeerr[0]);
if (pipeerr[1] > 0)
close(pipeerr[1]);
if (pipeout[0] > 0)
close(pipeout[0]);
if (pipeout[1] > 0)
close(pipeout[1]);
if (null > 0)
close(null);
return -1;
}
/* Return -1 for error, 1 to continue reading and 0 for success */
typedef int qemudHandlerMonitorOutput(virConnectPtr conn,
struct qemud_driver *driver,
@ -722,7 +638,7 @@ static int qemudStartVMDaemon(virConnectPtr conn,
qemudLog(QEMUD_WARN, "Unable to write argv to logfile %d: %s",
errno, strerror(errno));
if (qemudExec(conn, argv, &vm->pid, &vm->stdout, &vm->stderr) == 0) {
if (virExecNonBlock(conn, argv, &vm->pid, &vm->stdout, &vm->stderr) == 0) {
vm->id = driver->nextvmid++;
vm->state = VIR_DOMAIN_RUNNING;
@ -981,7 +897,7 @@ dhcpStartDhcpDaemon(virConnectPtr conn,
if (qemudBuildDnsmasqArgv(conn, network, &argv) < 0)
return -1;
ret = qemudExec(conn, argv, &network->dnsmasqPid, NULL, NULL);
ret = virExecNonBlock(conn, argv, &network->dnsmasqPid, NULL, NULL);
for (i = 0; argv[i]; i++)
free(argv[i]);

192
src/util.c Normal file
View File

@ -0,0 +1,192 @@
/*
* utils.c: common, generic utility functions
*
* Copyright (C) 2006, 2007 Red Hat, Inc.
* Copyright (C) 2006 Daniel P. Berrange
* Copyright (C) 2006, 2007 Binary Karma
* Copyright (C) 2006 Shuveb Hussain
*
* 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
*
* Author: Daniel P. Berrange <berrange@redhat.com>
* File created Jul 18, 2007 - Shuveb Hussain <shuveb@binarykarma.com>
*/
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
#include <fcntl.h>
#include <paths.h>
#include <errno.h>
#include <libvirt/virterror.h>
#include "event.h"
#include "buf.h"
#define MAX_ERROR_LEN 1024
static void
ReportError(virConnectPtr conn,
virDomainPtr dom,
virNetworkPtr net,
int code, const char *fmt, ...) {
va_list args;
char errorMessage[MAX_ERROR_LEN];
if (fmt) {
va_start(args, fmt);
vsnprintf(errorMessage, MAX_ERROR_LEN-1, fmt, args);
va_end(args);
} else {
errorMessage[0] = '\0';
}
__virRaiseError(conn, dom, net, VIR_FROM_NONE, code, VIR_ERR_ERROR,
NULL, NULL, NULL, -1, -1, errorMessage);
}
static int virSetCloseExec(int fd) {
int flags;
if ((flags = fcntl(fd, F_GETFD)) < 0)
return -1;
flags |= FD_CLOEXEC;
if ((fcntl(fd, F_SETFD, flags)) < 0)
return -1;
return 0;
}
static int virSetNonBlock(int fd) {
int flags;
if ((flags = fcntl(fd, F_GETFL)) < 0)
return -1;
flags |= O_NONBLOCK;
if ((fcntl(fd, F_SETFL, flags)) < 0)
return -1;
return 0;
}
static int
_virExec(virConnectPtr conn,
char **argv,
int *retpid, int *outfd, int *errfd, int non_block) {
int pid, null;
int pipeout[2] = {-1,-1};
int pipeerr[2] = {-1,-1};
if ((null = open(_PATH_DEVNULL, O_RDONLY)) < 0) {
ReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "cannot open %s : %s",
_PATH_DEVNULL, strerror(errno));
goto cleanup;
}
if ((outfd != NULL && pipe(pipeout) < 0) ||
(errfd != NULL && pipe(pipeerr) < 0)) {
ReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "cannot create pipe : %s",
strerror(errno));
goto cleanup;
}
if ((pid = fork()) < 0) {
ReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, "cannot fork child process : %s",
strerror(errno));
goto cleanup;
}
if (pid) { /* parent */
close(null);
if (outfd) {
close(pipeout[1]);
if(non_block)
if(virSetNonBlock(pipeout[0]) == -1)
ReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
"Failed to set non-blocking file descriptor flag");
if(virSetCloseExec(pipeout[0]) == -1)
ReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
"Failed to set close-on-exec file descriptor flag");
*outfd = pipeout[0];
}
if (errfd) {
close(pipeerr[1]);
if(non_block)
if(virSetNonBlock(pipeerr[0]) == -1)
ReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
"Failed to set non-blocking file descriptor flag");
if(virSetCloseExec(pipeerr[0]) == -1)
ReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
"Failed to set close-on-exec file descriptor flag");
*errfd = pipeerr[0];
}
*retpid = pid;
return 0;
}
/* child */
if (pipeout[0] > 0 && close(pipeout[0]) < 0)
_exit(1);
if (pipeerr[0] > 0 && close(pipeerr[0]) < 0)
_exit(1);
if (dup2(null, STDIN_FILENO) < 0)
_exit(1);
if (dup2(pipeout[1] > 0 ? pipeout[1] : null, STDOUT_FILENO) < 0)
_exit(1);
if (dup2(pipeerr[1] > 0 ? pipeerr[1] : null, STDERR_FILENO) < 0)
_exit(1);
close(null);
if (pipeout[1] > 0)
close(pipeout[1]);
if (pipeerr[1] > 0)
close(pipeerr[1]);
execvp(argv[0], argv);
_exit(1);
return 0;
cleanup:
if (pipeerr[0] > 0)
close(pipeerr[0]);
if (pipeerr[1] > 0)
close(pipeerr[1]);
if (pipeout[0] > 0)
close(pipeout[0]);
if (pipeout[1] > 0)
close(pipeout[1]);
if (null > 0)
close(null);
return -1;
}
int
virExec(virConnectPtr conn,
char **argv,
int *retpid, int *outfd, int *errfd) {
_virExec(conn, argv, retpid, outfd, errfd, 0);
}
int
virExecNonBlock(virConnectPtr conn,
char **argv,
int *retpid, int *outfd, int *errfd) {
_virExec(conn, argv, retpid, outfd, errfd, 1);
}

26
src/util.h Normal file
View File

@ -0,0 +1,26 @@
/*
* utils.h: common, generic utility functions
*
* Copyright (C) 2006, 2007 Binary Karma
* Copyright (C) 2006 Shuveb Hussain
*
* 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
*
* File created Jul 18, 2007 - Shuveb Hussain <shuveb@binarykarma.com>
*/
int virExec(virConnectPtr conn, char **argv, int *retpid, int *outfd, int *errfd);
int virExecNonBlock(virConnectPtr conn, char **argv, int *retpid, int *outfd, int *errfd);