+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
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;
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 \
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) {
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;
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;
}
/* 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;
* 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;
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;
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]);
-
- if(ret != 16) {
+ ret = virUUIDParse(uuidstr, vmdef->uuid);
+
+ if(ret == -1) {
error(conn, VIR_ERR_INTERNAL_ERROR, "UUID in config file malformed");
return NULL;
}
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;
}
/* 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;
return n;
}
-int openvzGetVPSUUID(int vpsid, char *uuidbuf)
+static int
+openvzGetVPSUUID(int vpsid, char *uuidbuf)
{
char conf_file[PATH_MAX];
char line[1024];
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;
}
}
* 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;
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]);
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,
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 */
#include "event.h"
#include "buf.h"
+#include "util.h"
#include "openvz_driver.h"
#include "openvz_conf.h"
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;
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;
}
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;
}
#include "event.h"
#include "buf.h"
+#include "util.h"
#include "qemu_driver.h"
#include "qemu_conf.h"
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,
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;
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]);
--- /dev/null
+/*
+ * 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);
+
+}
+
--- /dev/null
+/*
+ * 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);
+