[libvirt] [PATCH] maint: update list of error function names and adapt
by Jim Meyering
I updated the list of error function names
in Makefile.maint, and exposed 3 more unmarked diagnostics.
Going through the old/new lists, I also found two
now-unused (#define'd) "functions".
I originally did this on top of Dan's patch series,
but it also applies to the trunk, modulo some offset differences
in xen_unified.c.
>From 8124c5ae693fdad477df6b38dc5b75b4cd8f36cf Mon Sep 17 00:00:00 2001
From: Jim Meyering <meyering(a)redhat.com>
Date: Mon, 19 Jan 2009 09:25:02 +0100
Subject: [PATCH] maint: update list of error function names and adapt
* Makefile.maint (msg_gen_function): Update list.
Remove some now-unused names, add some new ones.
* src/hash.c (virHashError): Remove unused definition.
* src/openvz_conf.h (openvzLog): Likewise.
* src/xen_unified.c: Mark newly-exposed diagnostics for translation.
---
Makefile.maint | 8 ++++----
src/hash.c | 5 -----
src/openvz_conf.h | 8 --------
src/xen_unified.c | 8 ++++----
4 files changed, 8 insertions(+), 21 deletions(-)
diff --git a/Makefile.maint b/Makefile.maint
index 2ac6dd7..35eddd1 100644
--- a/Makefile.maint
+++ b/Makefile.maint
@@ -390,6 +390,7 @@ msg_gen_function += ERROR0
msg_gen_function += REMOTE_DEBUG
msg_gen_function += ReportError
msg_gen_function += VIR_FREE
+msg_gen_function += VIR_INFO
msg_gen_function += VIR_USE_CPU
msg_gen_function += errorf
msg_gen_function += lxcError
@@ -401,9 +402,7 @@ msg_gen_function += qemudDispatchClientFailure
msg_gen_function += qemudLog
msg_gen_function += qemudReportError
msg_gen_function += regerror
-msg_gen_function += remoteDispatchError
msg_gen_function += remoteDispatchFormatError
-msg_gen_function += umlError
msg_gen_function += umlLog
msg_gen_function += umlReportError
msg_gen_function += virConfError
@@ -414,18 +413,19 @@ msg_gen_function += virLibDomainError
msg_gen_function += virLog
msg_gen_function += virNetworkReportError
msg_gen_function += virNodeDeviceReportError
+msg_gen_function += virProxyError
msg_gen_function += virRaiseError
msg_gen_function += virReportErrorHelper
+msg_gen_function += virReportSystemError
msg_gen_function += virSexprError
msg_gen_function += virStorageLog
msg_gen_function += virStorageReportError
-msg_gen_function += virTestError
msg_gen_function += virXMLError
msg_gen_function += virXenInotifyError
msg_gen_function += virXenStoreError
msg_gen_function += virXendError
-msg_gen_function += virxmlRpcError
msg_gen_function += vshCloseLogFile
+msg_gen_function += xenUnifiedError
msg_gen_function += xenXMError
# Uncomment the following and run "make syntax-check" to see diagnostics
diff --git a/src/hash.c b/src/hash.c
index b960640..bde3a0b 100644
--- a/src/hash.c
+++ b/src/hash.c
@@ -32,10 +32,6 @@
/* #define DEBUG_GROW */
-#define virHashError(conn, code, fmt...) \
- virReportErrorHelper(conn, VIR_FROM_NONE, code, __FILE__, \
- __FUNCTION__, __LINE__, fmt)
-
/*
* A single entry in the hash table
*/
@@ -593,4 +589,3 @@ void *virHashSearch(virHashTablePtr table, virHashSearcher iter, const void *dat
}
return (NULL);
}
-
diff --git a/src/openvz_conf.h b/src/openvz_conf.h
index 1030d17..8e02056 100644
--- a/src/openvz_conf.h
+++ b/src/openvz_conf.h
@@ -34,14 +34,6 @@
enum { OPENVZ_WARN, OPENVZ_ERR };
-#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"); }
-
#define openvzError(conn, code, fmt...) \
virReportErrorHelper(conn, VIR_FROM_OPENVZ, code, __FILE__, \
__FUNCTION__, __LINE__, fmt)
diff --git a/src/xen_unified.c b/src/xen_unified.c
index e0a446a..66d5fc2 100644
--- a/src/xen_unified.c
+++ b/src/xen_unified.c
@@ -1,7 +1,7 @@
/*
* xen_unified.c: Unified Xen driver.
*
- * Copyright (C) 2007, 2008 Red Hat, Inc.
+ * Copyright (C) 2007, 2008, 2009 Red Hat, Inc.
*
* See COPYING.LIB for the License of this software
*
@@ -235,7 +235,7 @@ xenUnifiedOpen (virConnectPtr conn, virConnectAuthPtr auth, int flags)
/* Allocate per-connection private data. */
if (VIR_ALLOC(priv) < 0) {
- xenUnifiedError (NULL, VIR_ERR_NO_MEMORY, "allocating private data");
+ xenUnifiedError (NULL, VIR_ERR_NO_MEMORY, _("allocating private data"));
return VIR_DRV_OPEN_ERROR;
}
if (virMutexInit(&priv->lock) < 0) {
@@ -247,7 +247,7 @@ xenUnifiedOpen (virConnectPtr conn, virConnectAuthPtr auth, int flags)
/* Allocate callback list */
if (VIR_ALLOC(cbList) < 0) {
- xenUnifiedError (NULL, VIR_ERR_NO_MEMORY, "allocating callback list");
+ xenUnifiedError (NULL, VIR_ERR_NO_MEMORY, _("allocating callback list"));
virMutexDestroy(&priv->lock);
VIR_FREE(priv);
return VIR_DRV_OPEN_ERROR;
@@ -1533,7 +1533,7 @@ xenUnifiedAddDomainInfo(xenUnifiedDomainInfoListPtr list,
list->count++;
return 0;
memory_error:
- xenUnifiedError (NULL, VIR_ERR_NO_MEMORY, "allocating domain info");
+ xenUnifiedError (NULL, VIR_ERR_NO_MEMORY, _("allocating domain info"));
if (info)
VIR_FREE(info->name);
VIR_FREE(info);
--
1.6.1.258.g7ff14
16 years, 1 month
[libvirt] Tiny additional RHEL patch
by Daniel Veillard
Small addition to the spec file, basically if on Fedora we should not
activate RHEL-5 Xen specific support, but on RHEL and possibly CentOS
the flag should be passed to %configure.
The test is somehow reversed because it's hard to detect building on
a RHEL platform from the spec file, and that should cope well with
CentOS too. Now for other rpm based environment, I welcome improvements!
Daniel
--
Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/
daniel(a)veillard.com | Rpmfind RPM search engine http://rpmfind.net/
http://veillard.com/ | virtualization library http://libvirt.org/
16 years, 1 month
[libvirt] [PATCH 3/4] use monitor fd for domain shutdown
by Guido Günther
This way we don't have to bother about stdin/stdout/stderr on reconnect.
Since we dup stdin/stderr on the logfile we need to reparse it for the
monitor path.
Cheers,
-- Guido
---
src/domain_conf.h | 1 +
src/qemu_driver.c | 155 +++++++++++++++++++++++++++--------------------------
2 files changed, 80 insertions(+), 76 deletions(-)
diff --git a/src/domain_conf.h b/src/domain_conf.h
index 45b3e10..c236a66 100644
--- a/src/domain_conf.h
+++ b/src/domain_conf.h
@@ -465,6 +465,7 @@ struct _virDomainObj {
int stderr_fd;
int stderr_watch;
int monitor;
+ int monitor_watch;
char *monitorpath;
int monitorWatch;
int logfile;
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index 06f444b..734a329 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -181,6 +181,45 @@ qemudLogFD(virConnectPtr conn, const char* logDir, const char* name)
}
+static int
+qemudLogReadFD(virConnectPtr conn, const char* logDir, const char* name, off_t pos)
+{
+ char logfile[PATH_MAX];
+ mode_t logmode = O_RDONLY;
+ int ret, fd = -1;
+
+ if ((ret = snprintf(logfile, sizeof(logfile), "%s/%s.log", logDir, name))
+ < 0 || ret >= sizeof(logfile)) {
+ qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+ _("failed to build logfile name %s/%s.log"),
+ logDir, name);
+ return -1;
+ }
+
+
+ if ((fd = open(logfile, logmode)) < 0) {
+ qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+ _("failed to create logfile %s: %s"),
+ logfile, strerror(errno));
+ return -1;
+ }
+ if (qemudSetCloseExec(fd) < 0) {
+ qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+ _("Unable to set VM logfile close-on-exec flag: %s"),
+ strerror(errno));
+ close(fd);
+ return -1;
+ }
+ if (lseek(fd, pos, SEEK_SET) < 0) {
+ qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
+ _("Unable to seek to %lld in %s: %s"),
+ pos, logfile, strerror(errno));
+ close(fd);
+ }
+ return fd;
+}
+
+
static void
qemudAutostartConfigs(struct qemud_driver *driver) {
unsigned int i;
@@ -516,11 +555,7 @@ qemudReadMonitorOutput(virConnectPtr conn,
int ret;
ret = read(fd, buf+got, buflen-got-1);
- if (ret == 0) {
- qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
- _("QEMU quit during %s startup\n%s"), what, buf);
- return -1;
- }
+
if (ret < 0) {
struct pollfd pfd = { .fd = fd, .events = POLLIN };
if (errno == EINTR)
@@ -584,6 +619,7 @@ qemudCheckMonitorPrompt(virConnectPtr conn ATTRIBUTE_UNUSED,
}
static int qemudOpenMonitor(virConnectPtr conn,
+ struct qemud_driver* driver,
virDomainObjPtr vm,
const char *monitor) {
int monfd;
@@ -618,6 +654,12 @@ static int qemudOpenMonitor(virConnectPtr conn,
goto error;
}
+ if ((vm->monitor_watch = virEventAddHandle(vm->monitor, 0,
+ qemudDispatchVMEvent,
+ driver, NULL)) < 0)
+ goto error;
+
+
/* Keep monitor open upon success */
if (ret == 0)
return ret;
@@ -677,6 +719,7 @@ qemudFindCharDevicePTYs(virConnectPtr conn,
const char *output,
int fd ATTRIBUTE_UNUSED)
{
+ struct qemud_driver* driver = conn->privateData;
char *monitor = NULL;
size_t offset = 0;
int ret, i;
@@ -711,7 +754,9 @@ qemudFindCharDevicePTYs(virConnectPtr conn,
}
/* Got them all, so now open the monitor console */
- ret = qemudOpenMonitor(conn, vm, monitor);
+ qemuDriverLock(driver);
+ ret = qemudOpenMonitor(conn, driver, vm, monitor, 0);
+ qemuDriverUnlock(driver);
cleanup:
VIR_FREE(monitor);
@@ -719,21 +764,23 @@ cleanup:
}
static int qemudWaitForMonitor(virConnectPtr conn,
- virDomainObjPtr vm) {
+ struct qemud_driver* driver,
+ virDomainObjPtr vm, off_t pos)
+{
char buf[1024]; /* Plenty of space to get startup greeting */
- int ret = qemudReadMonitorOutput(conn,
- vm, vm->stderr_fd,
- buf, sizeof(buf),
- qemudFindCharDevicePTYs,
- "console", 3000);
+ int logfd;
+ int ret;
- buf[sizeof(buf)-1] = '\0';
+ if ((logfd = qemudLogReadFD(conn, driver->logDir, vm->def->name, pos))
+ < 0)
+ return logfd;
- if (safewrite(vm->logfile, buf, strlen(buf)) < 0) {
- /* Log, but ignore failures to write logfile for VM */
- qemudLog(QEMUD_WARN, _("Unable to log VM console data: %s\n"),
+ ret = qemudReadMonitorOutput(conn, vm, logfd, buf, sizeof(buf),
+ qemudFindCharDevicePTYs,
+ "console", 3000);
+ if (close(logfd) < 0)
+ qemudLog(QEMUD_WARN, _("Unable to close logfile: %s\n"),
strerror(errno));
- }
return ret;
}
@@ -942,6 +989,7 @@ static int qemudStartVMDaemon(virConnectPtr conn,
fd_set keepfd;
const char *emulator;
pid_t child;
+ int pos = -1;
FD_ZERO(&keepfd);
@@ -1034,12 +1082,14 @@ static int qemudStartVMDaemon(virConnectPtr conn,
qemudLog(QEMUD_WARN, _("Unable to write argv to logfile %d: %s\n"),
errno, strerror(errno));
- vm->stdout_fd = -1;
- vm->stderr_fd = -1;
+ if ((pos = lseek(vm->logfile, 0, SEEK_END)) < 0)
+ qemudLog(QEMUD_WARN, _("Unable to seek to end of logfile %d: %s\n"),
+ errno, strerror(errno));
for (i = 0 ; i < ntapfds ; i++)
FD_SET(tapfds[i], &keepfd);
+ vm->stderr_fd = vm->stdout_fd = vm->logfile;
ret = virExec(conn, argv, progenv, &keepfd, &child,
vm->stdin_fd, &vm->stdout_fd, &vm->stderr_fd,
VIR_EXEC_NONBLOCK | VIR_EXEC_DAEMON);
@@ -1078,19 +1128,7 @@ static int qemudStartVMDaemon(virConnectPtr conn,
}
if (ret == 0) {
- if (((vm->stdout_watch = virEventAddHandle(vm->stdout_fd,
- VIR_EVENT_HANDLE_READABLE |
- VIR_EVENT_HANDLE_ERROR |
- VIR_EVENT_HANDLE_HANGUP,
- qemudDispatchVMEvent,
- driver, NULL)) < 0) ||
- ((vm->stderr_watch = virEventAddHandle(vm->stderr_fd,
- VIR_EVENT_HANDLE_READABLE |
- VIR_EVENT_HANDLE_ERROR |
- VIR_EVENT_HANDLE_HANGUP,
- qemudDispatchVMEvent,
- driver, NULL)) < 0) ||
- (qemudWaitForMonitor(conn, vm) < 0) ||
+ if ((qemudWaitForMonitor(conn, driver, vm, pos) < 0) ||
(qemudDetectVcpuPIDs(conn, vm) < 0) ||
(qemudInitCpus(conn, vm, migrateFrom) < 0)) {
qemudShutdownVMDaemon(conn, driver, vm);
@@ -1102,32 +1140,6 @@ static int qemudStartVMDaemon(virConnectPtr conn,
return ret;
}
-static int qemudVMData(struct qemud_driver *driver ATTRIBUTE_UNUSED,
- virDomainObjPtr vm, int fd) {
- char buf[4096];
- if (vm->pid < 0)
- return 0;
-
- for (;;) {
- int ret = read(fd, buf, sizeof(buf)-1);
- if (ret < 0) {
- if (errno == EAGAIN)
- return 0;
- return -1;
- }
- if (ret == 0) {
- return 0;
- }
- buf[ret] = '\0';
-
- if (safewrite(vm->logfile, buf, ret) < 0) {
- /* Log, but ignore failures to write logfile for VM */
- qemudLog(QEMUD_WARN, _("Unable to log VM console data: %s\n"),
- strerror(errno));
- }
- }
-}
-
static void qemudShutdownVMDaemon(virConnectPtr conn ATTRIBUTE_UNUSED,
struct qemud_driver *driver, virDomainObjPtr vm) {
@@ -1141,17 +1153,11 @@ static void qemudShutdownVMDaemon(virConnectPtr conn ATTRIBUTE_UNUSED,
qemudLog(QEMUD_ERROR, _("Failed to send SIGTERM to %s (%d): %s\n"),
vm->def->name, vm->pid, strerror(errno));
- qemudVMData(driver, vm, vm->stdout_fd);
- qemudVMData(driver, vm, vm->stderr_fd);
-
- virEventRemoveHandle(vm->stdout_watch);
- virEventRemoveHandle(vm->stderr_watch);
+ virEventRemoveHandle(vm->monitor_watch);
if (close(vm->logfile) < 0)
qemudLog(QEMUD_WARN, _("Unable to close logfile %d: %s\n"),
errno, strerror(errno));
- close(vm->stdout_fd);
- close(vm->stderr_fd);
if (vm->monitor != -1)
close(vm->monitor);
vm->logfile = -1;
@@ -1191,8 +1197,7 @@ qemudDispatchVMEvent(int watch, int fd, int events, void *opaque) {
virDomainObjPtr tmpvm = driver->domains.objs[i];
virDomainObjLock(tmpvm);
if (virDomainIsActive(tmpvm) &&
- (tmpvm->stdout_watch == watch ||
- tmpvm->stderr_watch == watch)) {
+ tmpvm->monitor_watch == watch) {
vm = tmpvm;
break;
}
@@ -1202,16 +1207,14 @@ qemudDispatchVMEvent(int watch, int fd, int events, void *opaque) {
if (!vm)
goto cleanup;
- if (vm->stdout_fd != fd &&
- vm->stderr_fd != fd) {
+ if (vm->monitor != fd) {
failed = 1;
} else {
- if (events & VIR_EVENT_HANDLE_READABLE) {
- if (qemudVMData(driver, vm, fd) < 0)
- failed = 1;
- } else {
+ if (events & (VIR_EVENT_HANDLE_HANGUP | VIR_EVENT_HANDLE_ERROR))
quit = 1;
- }
+ else
+ qemudLog(QEMUD_ERROR, _("unhandled fd event %d for %s"),
+ events, vm->def->name);
}
if (failed || quit) {
--
1.6.0.6
16 years, 1 month
[libvirt] [PATCH 4/4] read saved vm status on libvirtd startup
by Guido Günther
connect back to running vms.
changes:
* don't use proc
* don't bother about stdin
* don't use global qemu_driver directly
Cheer,
-- Guido
---
src/qemu_driver.c | 112 +++++++++++++++++++++++++++++++++++++++++++++--------
1 files changed, 96 insertions(+), 16 deletions(-)
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index 2dedca2..3b01fd4 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -297,6 +297,86 @@ cleanup:
}
+static int qemudOpenMonitor(virConnectPtr conn,
+ struct qemud_driver* driver,
+ virDomainObjPtr vm,
+ const char *monitor,
+ int reconnect);
+
+/**
+ * qemudReconnectVMs
+ *
+ * Reconnect running vms to the daemon process
+ */
+static int
+qemudReconnectVMs(struct qemud_driver *driver)
+{
+ int i;
+
+ for (i = 0 ; i < driver->domains.count ; i++) {
+ virDomainObjPtr vm = driver->domains.objs[i];
+ qemudDomainStatusPtr status = NULL;
+ char *config = NULL;
+ int rc;
+
+ virDomainObjLock(vm);
+ if ((rc = virFileReadPid(driver->stateDir, vm->def->name, &vm->pid)) == 0)
+ DEBUG("Found pid %d for '%s'", vm->pid, vm->def->name);
+ else
+ goto next;
+
+ if ((config = virDomainConfigFile(NULL,
+ driver->stateDir,
+ vm->def->name)) == NULL) {
+ qemudLog(QEMUD_ERR, _("Failed to read domain status for %s\n"),
+ vm->def->name);
+ goto next_error;
+ }
+
+ status = qemudDomainStatusParseFile(NULL, driver->caps, config, 0);
+ if (status) {
+ vm->newDef = vm->def;
+ vm->def = status->def;
+ } else {
+ qemudLog(QEMUD_ERR, _("Failed to parse domain status for %s\n"),
+ vm->def->name);
+ goto next_error;
+ }
+
+ if ((rc = qemudOpenMonitor(NULL, driver, vm, status->monitorpath, 1)) != 0) {
+ qemudLog(QEMUD_ERR, _("Failed to reconnect monitor for %s: %d\n"),
+ vm->def->name, rc);
+ goto next_error;
+ } else
+ vm->monitorpath = status->monitorpath;
+
+ if((vm->logfile = qemudLogFD(NULL, driver->logDir, vm->def->name)) < 0)
+ return -1;
+
+ vm->stdout_fd = vm->stderr_fd = vm->logfile;
+
+ if (vm->def->id >= driver->nextvmid)
+ driver->nextvmid = vm->def->id + 1;
+
+ vm->state = status->state;
+ goto next;
+
+next_error:
+ /* we failed to reconnect the vm so remove it's traces */
+ vm->def->id = -1;
+ qemudRemoveDomainStatus(NULL, driver, vm);
+ virDomainDefFree(vm->def);
+ vm->def = vm->newDef;
+ vm->newDef = NULL;
+next:
+ virDomainObjUnlock(vm);
+ VIR_FREE(status);
+ VIR_FREE(config);
+ }
+ return 0;
+}
+
+
/**
* qemudStartup:
*
@@ -396,6 +476,7 @@ qemudStartup(void) {
qemu_driver->autostartDir,
NULL, NULL) < 0)
goto error;
+ qemudReconnectVMs(qemu_driver);
qemudAutostartConfigs(qemu_driver);
qemuDriverUnlock(qemu_driver);
@@ -488,7 +569,6 @@ qemudActive(void) {
*/
static int
qemudShutdown(void) {
- unsigned int i;
if (!qemu_driver)
return -1;
@@ -496,15 +576,6 @@ qemudShutdown(void) {
qemuDriverLock(qemu_driver);
virCapabilitiesFree(qemu_driver->caps);
- /* shutdown active VMs */
- for (i = 0 ; i < qemu_driver->domains.count ; i++) {
- virDomainObjPtr dom = qemu_driver->domains.objs[i];
- virDomainObjLock(dom);
- if (virDomainIsActive(dom))
- qemudShutdownVMDaemon(NULL, qemu_driver, dom);
- virDomainObjUnlock(dom);
- }
-
virDomainObjListFree(&qemu_driver->domains);
VIR_FREE(qemu_driver->logDir);
@@ -621,7 +692,8 @@ qemudCheckMonitorPrompt(virConnectPtr conn ATTRIBUTE_UNUSED,
static int qemudOpenMonitor(virConnectPtr conn,
struct qemud_driver* driver,
virDomainObjPtr vm,
- const char *monitor) {
+ const char *monitor,
+ int reconnect) {
int monfd;
char buf[1024];
int ret = -1;
@@ -642,11 +714,19 @@ static int qemudOpenMonitor(virConnectPtr conn,
goto error;
}
- ret = qemudReadMonitorOutput(conn,
- vm, monfd,
- buf, sizeof(buf),
- qemudCheckMonitorPrompt,
- "monitor", 10000);
+ if (!reconnect) {
+ ret = qemudReadMonitorOutput(conn,
+ vm, monfd,
+ buf, sizeof(buf),
+ qemudCheckMonitorPrompt,
+ "monitor", 10000);
+ } else {
+ vm->monitor = monfd;
+ ret = 0;
+ }
+
+ if (ret != 0)
+ goto error;
if (!(vm->monitorpath = strdup(monitor))) {
qemudReportError(conn, NULL, NULL, VIR_ERR_NO_MEMORY,
--
1.6.0.6
16 years, 1 month
[libvirt] [PATCH] Solaris least privilege support
by john.levon@sun.com
# HG changeset patch
# User john.levon(a)sun.com
# Date 1232039546 28800
# Node ID b9d4d60bca87633897cb133461e1415d1223c823
# Parent 25a0c46588d5de1653b16dfed6bc357abf11db77
Solaris least privilege support
On Solaris dom0, virtd runs as a privilege barrier: all libvirt
connections are routed through it, and it performs the relevant
privilege checks for any clients.
Signed-off-by: John Levon <john.levon(a)sun.com>
diff --git a/qemud/qemud.c b/qemud/qemud.c
--- a/qemud/qemud.c
+++ b/qemud/qemud.c
@@ -84,6 +84,39 @@
#endif
+#ifdef __sun
+#include <ucred.h>
+#include <priv.h>
+
+#ifndef PRIV_VIRT_MANAGE
+#define PRIV_VIRT_MANAGE ((const char *)"virt_manage")
+#endif
+
+#ifndef PRIV_XVM_CONTROL
+#define PRIV_XVM_CONTROL ((const char *)"xvm_control")
+#endif
+
+#define PU_RESETGROUPS 0x0001 /* Remove supplemental groups */
+#define PU_CLEARLIMITSET 0x0008 /* L=0 */
+
+extern int __init_daemon_priv(int, uid_t, gid_t, ...);
+
+#define SYSTEM_UID 60
+
+static gid_t unix_sock_gid = 60; /* Not used */
+static int unix_sock_rw_mask = 0666;
+static int unix_sock_ro_mask = 0666;
+
+#else
+
+#define SYSTEM_UID 0
+
+static gid_t unix_sock_gid = 0; /* Only root by default */
+static int unix_sock_rw_mask = 0700; /* Allow user only */
+static int unix_sock_ro_mask = 0777; /* Allow world */
+
+#endif /* __sun */
+
static int godaemon = 0; /* -d: Be a daemon */
static int verbose = 0; /* -v: Verbose mode */
static int timeout = -1; /* -t: Shutdown timeout */
@@ -101,10 +134,6 @@ static char *listen_addr = (char *) LIB
static char *listen_addr = (char *) LIBVIRTD_LISTEN_ADDR;
static char *tls_port = (char *) LIBVIRTD_TLS_PORT;
static char *tcp_port = (char *) LIBVIRTD_TCP_PORT;
-
-static gid_t unix_sock_gid = 0; /* Only root by default */
-static int unix_sock_rw_mask = 0700; /* Allow user only */
-static int unix_sock_ro_mask = 0777; /* Allow world */
#if HAVE_POLKIT
static int auth_unix_rw = REMOTE_AUTH_POLKIT;
@@ -638,10 +667,11 @@ static int qemudInitPaths(struct qemud_s
static int qemudInitPaths(struct qemud_server *server,
char *sockname,
char *roSockname,
- int maxlen) {
+ int maxlen)
+{
uid_t uid = geteuid();
- if (!uid) {
+ if (uid == SYSTEM_UID) {
if (snprintf (sockname, maxlen, "%s/run/libvirt/libvirt-sock",
LOCAL_STATE_DIR) >= maxlen)
goto snprintf_error;
@@ -1105,6 +1135,29 @@ static int qemudDispatchServer(struct qe
return -1;
}
+#ifdef __sun
+ {
+ ucred_t *ucred = NULL;
+ const priv_set_t *privs;
+
+ if (getpeerucred (fd, &ucred) == -1 ||
+ (privs = ucred_getprivset (ucred, PRIV_EFFECTIVE)) == NULL) {
+ if (ucred != NULL)
+ ucred_free (ucred);
+ close (fd);
+ return -1;
+ }
+
+ if (!priv_ismember (privs, PRIV_VIRT_MANAGE)) {
+ ucred_free (ucred);
+ close (fd);
+ return -1;
+ }
+
+ ucred_free (ucred);
+ }
+#endif /* __sun */
+
/* Disable Nagle. Unix sockets will ignore this. */
setsockopt (fd, IPPROTO_TCP, TCP_NODELAY, (void *)&no_slow_start,
sizeof no_slow_start);
@@ -2239,6 +2292,29 @@ version (const char *argv0)
{
printf ("%s (%s) %s\n", argv0, PACKAGE_NAME, PACKAGE_VERSION);
}
+
+#ifdef __sun
+static void
+qemudSetupPrivs (struct qemud_server *server)
+{
+ chown ("/var/run/libvirt", SYSTEM_UID, SYSTEM_UID);
+ chown (server->logDir, SYSTEM_UID, SYSTEM_UID);
+
+ if (__init_daemon_priv (PU_RESETGROUPS | PU_CLEARLIMITSET,
+ SYSTEM_UID, SYSTEM_UID, PRIV_XVM_CONTROL, NULL)) {
+ fprintf (stderr, "additional privileges are required\n");
+ exit (1);
+ }
+
+ if (priv_set (PRIV_OFF, PRIV_ALLSETS, PRIV_FILE_LINK_ANY, PRIV_PROC_INFO,
+ PRIV_PROC_SESSION, PRIV_PROC_EXEC, PRIV_PROC_FORK, NULL)) {
+ fprintf (stderr, "failed to set reduced privileges\n");
+ exit (1);
+ }
+}
+#else
+#define qemudSetupPrivs(a)
+#endif
/* Print command-line usage. */
static void
@@ -2417,6 +2493,20 @@ int main(int argc, char **argv) {
sig_action.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &sig_action, NULL);
+ /* Change the group ownership of /var/run/libvirt to unix_sock_gid */
+ if (geteuid () == 0) {
+ const char *rundir = LOCAL_STATE_DIR "/run/libvirt";
+
+ if (mkdir (rundir, 0755)) {
+ if (errno != EEXIST) {
+ VIR_ERROR0 (_("unable to create rundir"));
+ return (-1);
+ }
+ }
+ }
+
+ qemudSetupPrivs(server);
+
if (!(server = qemudInitialize(sigpipe[0]))) {
ret = 2;
goto error2;
diff --git a/src/remote_internal.c b/src/remote_internal.c
--- a/src/remote_internal.c
+++ b/src/remote_internal.c
@@ -90,7 +90,7 @@
#define MAGIC 999 /* private_data->magic if OK */
#define DEAD 998 /* private_data->magic if dead/closed */
-static int inside_daemon = 0;
+int inside_daemon = 0;
struct private_data {
int magic; /* Should be MAGIC or DEAD. */
@@ -903,18 +903,21 @@ remoteOpen (virConnectPtr conn,
}
/*
- * If URI is NULL, then do a UNIX connection
- * possibly auto-spawning unprivileged server
- * and probe remote server for URI
+ * If URI is NULL, then do a UNIX connection possibly auto-spawning
+ * unprivileged server and probe remote server for URI. On Solaris,
+ * this isn't supported, but we may be privileged enough to connect
+ * to the UNIX socket anyway.
*/
if (!conn->uri) {
DEBUG0("Auto-probe remote URI");
rflags |= VIR_DRV_OPEN_REMOTE_UNIX;
+#ifndef __sun
if (getuid() > 0) {
DEBUG0("Auto-spawn user daemon instance");
rflags |= VIR_DRV_OPEN_REMOTE_USER;
rflags |= VIR_DRV_OPEN_REMOTE_AUTOSTART;
}
+#endif
}
priv->magic = DEAD;
diff --git a/src/xen_internal.c b/src/xen_internal.c
--- a/src/xen_internal.c
+++ b/src/xen_internal.c
@@ -26,6 +26,17 @@
#include <errno.h>
#include <sys/utsname.h>
+#ifdef __sun
+#include <sys/systeminfo.h>
+
+#include <priv.h>
+
+#ifndef PRIV_XVM_CONTROL
+#define PRIV_XVM_CONTROL ((const char *)"xvm_control")
+#endif
+
+#endif /* __sun */
+
/* required for dom0_getdomaininfo_t */
#include <xen/dom0_ops.h>
#include <xen/version.h>
@@ -35,10 +46,6 @@
#ifdef HAVE_XEN_SYS_PRIVCMD_H
#include <xen/sys/privcmd.h>
#endif
-#endif
-
-#ifdef __sun
-#include <sys/systeminfo.h>
#endif
/* required for shutdown flags */
@@ -3387,3 +3394,17 @@ xenHypervisorGetVcpuMax(virDomainPtr dom
return maxcpu;
}
+/**
+ * xenHavePrivilege()
+ *
+ * Return true if the current process should be able to connect to Xen.
+ */
+int
+xenHavePrivilege()
+{
+#ifdef __sun
+ return priv_ineffect (PRIV_XVM_CONTROL);
+#else
+ return getuid () == 0;
+#endif
+}
diff --git a/src/xen_internal.h b/src/xen_internal.h
--- a/src/xen_internal.h
+++ b/src/xen_internal.h
@@ -104,4 +104,6 @@ int xenHypervisorNodeGetCellsFreeMem
int startCell,
int maxCells);
+int xenHavePrivilege(void);
+
#endif /* __VIR_XEN_INTERNAL_H__ */
diff --git a/src/xen_unified.c b/src/xen_unified.c
--- a/src/xen_unified.c
+++ b/src/xen_unified.c
@@ -231,6 +231,16 @@ xenUnifiedOpen (virConnectPtr conn, virC
xenUnifiedPrivatePtr priv;
virDomainEventCallbackListPtr cbList;
+#ifdef __sun
+ extern int inside_daemon;
+ /*
+ * Only the libvirtd instance can open this driver.
+ * Everything else falls back to the remote driver.
+ */
+ if (!inside_daemon)
+ return VIR_DRV_OPEN_DECLINED;
+#endif
+
if (conn->uri == NULL) {
if (!xenUnifiedProbe())
return VIR_DRV_OPEN_DECLINED;
@@ -283,8 +293,8 @@ xenUnifiedOpen (virConnectPtr conn, virC
priv->proxy = -1;
- /* Hypervisor is only run as root & required to succeed */
- if (getuid() == 0) {
+ /* Hypervisor is only run with privilege & required to succeed */
+ if (xenHavePrivilege()) {
DEBUG0("Trying hypervisor sub-driver");
if (drivers[XEN_UNIFIED_HYPERVISOR_OFFSET]->open(conn, auth, flags) ==
VIR_DRV_OPEN_SUCCESS) {
@@ -293,7 +303,7 @@ xenUnifiedOpen (virConnectPtr conn, virC
}
}
- /* XenD is required to suceed if root.
+ /* XenD is required to succeed if privileged.
* If it fails as non-root, then the proxy driver may take over
*/
DEBUG0("Trying XenD sub-driver");
@@ -318,12 +328,12 @@ xenUnifiedOpen (virConnectPtr conn, virC
DEBUG0("Activated XS sub-driver");
priv->opened[XEN_UNIFIED_XS_OFFSET] = 1;
} else {
- if (getuid() == 0)
- goto fail; /* XS is mandatory as root */
+ if (xenHavePrivilege())
+ goto fail; /* XS is mandatory when privileged */
}
} else {
- if (getuid() == 0) {
- goto fail; /* XenD is mandatory as root */
+ if (xenHavePrivilege()) {
+ goto fail; /* XenD is mandatory when privileged */
} else {
#if WITH_PROXY
DEBUG0("Trying proxy sub-driver");
diff --git a/src/xend_internal.c b/src/xend_internal.c
--- a/src/xend_internal.c
+++ b/src/xend_internal.c
@@ -42,7 +42,7 @@
#include "buf.h"
#include "uuid.h"
#include "xen_unified.h"
-#include "xen_internal.h" /* for DOM0_INTERFACE_VERSION */
+#include "xen_internal.h"
#include "xs_internal.h" /* To extract VNC port & Serial console TTY */
#include "memory.h"
@@ -151,9 +151,10 @@ do_connect(virConnectPtr xend)
s = -1;
/*
- * Connecting to XenD as root is mandatory, so log this error
+ * Connecting to XenD when privileged is mandatory, so log this
+ * error
*/
- if (getuid() == 0) {
+ if (xenHavePrivilege()) {
virXendError(xend, VIR_ERR_INTERNAL_ERROR,
"%s", _("failed to connect to xend"));
}
diff --git a/src/xs_internal.c b/src/xs_internal.c
--- a/src/xs_internal.c
+++ b/src/xs_internal.c
@@ -35,7 +35,7 @@
#include "uuid.h"
#include "xen_unified.h"
#include "xs_internal.h"
-#include "xen_internal.h" /* for xenHypervisorCheckID */
+#include "xen_internal.h"
#ifdef __linux__
#define XEN_HYPERVISOR_SOCKET "/proc/xen/privcmd"
@@ -299,11 +299,11 @@ xenStoreOpen(virConnectPtr conn,
if (priv->xshandle == NULL) {
/*
- * not being able to connect via the socket as a normal user
- * is rather normal, this should fallback to the proxy (or
+ * not being able to connect via the socket as an unprivileged
+ * user is rather normal, this should fallback to the proxy (or
* remote) mechanism.
*/
- if (getuid() == 0) {
+ if (xenHavePrivilege()) {
virXenStoreError(NULL, VIR_ERR_NO_XEN,
"%s", _("failed to connect to Xen Store"));
}
16 years, 1 month
[libvirt] [PATCH 0/7 RFC] RHEL-5 support, and a few preparatory fixes
by Markus Armbruster
This patch series attempts to make libvirt just work on RHEL-5. Right
now it doesn't, mostly because libvirt relies on version number checks
in a couple of places, and RHEL-5's version numbers aren't the whole
truth due to various backports of later stuff.
The first two patches are plain bug fixes:
[PATCH 1/7] Fix network device inconsistency between xm and sxpr
[PATCH 2/7] Fix graphics configuration inconsistency between xm and sxpr
The next three add a few special cases for RHEL-5:
[PATCH 3/7] New configure option --with-rhel5-api
[PATCH 4/7] Fix HVM network device configuration for RHEL-5
[PATCH 5/7] Fix PVFB device configuration for RHEL-5
[PATCH 6/7] Enable NUMA support for RHEL-5
The last one drops a counter-productive error check:
[PATCH 7/7] Don't treat missing topology information as error
See the patches for more detailed descriptions.
I'm not proposing this for immediate commit, as I'm still testing.
But I'd appreciate review: is this the right way to do it?
Thanks,
Markus
16 years, 1 month
[libvirt] [PATCH 2/4] daemonize qemu processes
by Guido Günther
so they doen't get killed when the libvirtd quits unexpectedly
changes:
* longer timeouts when waiting for procs to show up
* check if process exists before killing it
* use virKill
this one basically got acked before but makes little sense without the
follow up patches.
Cheers,
-- Guido
---
src/qemu_driver.c | 39 ++++++++++++++++++++++++++-------------
1 files changed, 26 insertions(+), 13 deletions(-)
diff --git a/src/qemu_driver.c b/src/qemu_driver.c
index 1619154..06f444b 100644
--- a/src/qemu_driver.c
+++ b/src/qemu_driver.c
@@ -941,6 +941,7 @@ static int qemudStartVMDaemon(virConnectPtr conn,
unsigned int qemuCmdFlags;
fd_set keepfd;
const char *emulator;
+ pid_t child;
FD_ZERO(&keepfd);
@@ -1039,12 +1040,26 @@ static int qemudStartVMDaemon(virConnectPtr conn,
for (i = 0 ; i < ntapfds ; i++)
FD_SET(tapfds[i], &keepfd);
- ret = virExec(conn, argv, progenv, &keepfd, &vm->pid,
+ ret = virExec(conn, argv, progenv, &keepfd, &child,
vm->stdin_fd, &vm->stdout_fd, &vm->stderr_fd,
- VIR_EXEC_NONBLOCK);
- if (ret == 0)
+ VIR_EXEC_NONBLOCK | VIR_EXEC_DAEMON);
+
+ /* wait for qemu process to to show up */
+ if (ret == 0) {
+ int retries = 100;
+ while (retries) {
+ if ((ret = virFileReadPid(driver->stateDir, vm->def->name, &vm->pid)) == 0)
+ break;
+ usleep(100*1000);
+ retries--;
+ }
+ if (ret)
+ qemudLog(QEMUD_WARN, _("Domain %s didn't show up\n"), vm->def->name);
+ }
+
+ if (ret == 0) {
vm->state = migrateFrom ? VIR_DOMAIN_PAUSED : VIR_DOMAIN_RUNNING;
- else
+ } else
vm->def->id = -1;
for (i = 0 ; argv[i] ; i++)
@@ -1121,7 +1136,10 @@ static void qemudShutdownVMDaemon(virConnectPtr conn ATTRIBUTE_UNUSED,
qemudLog(QEMUD_INFO, _("Shutting down VM '%s'\n"), vm->def->name);
- kill(vm->pid, SIGTERM);
+ if (virKillProcess(vm->pid, 0) == 0 &&
+ virKillProcess(vm->pid, SIGTERM) < 0)
+ qemudLog(QEMUD_ERROR, _("Failed to send SIGTERM to %s (%d): %s\n"),
+ vm->def->name, vm->pid, strerror(errno));
qemudVMData(driver, vm, vm->stdout_fd);
qemudVMData(driver, vm, vm->stderr_fd);
@@ -1141,15 +1159,10 @@ static void qemudShutdownVMDaemon(virConnectPtr conn ATTRIBUTE_UNUSED,
vm->stderr_fd = -1;
vm->monitor = -1;
- if (waitpid(vm->pid, NULL, WNOHANG) != vm->pid) {
- kill(vm->pid, SIGKILL);
- if (waitpid(vm->pid, NULL, 0) != vm->pid) {
- qemudLog(QEMUD_WARN,
- "%s", _("Got unexpected pid, damn\n"));
- }
- }
- qemudRemoveDomainStatus(conn, driver, vm);
+ /* shut it off for sure */
+ virKillProcess(vm->pid, SIGKILL);
+ qemudRemoveDomainStatus(conn, driver, vm);
vm->pid = -1;
vm->def->id = -1;
vm->state = VIR_DOMAIN_SHUTOFF;
--
1.6.0.6
16 years, 1 month
[libvirt] [PATCH 1/4] save domstate as string in status file
by Guido Günther
This one is as posted before. Not really necessary, but makes things look
nicer.
-- Guido
---
src/domain_conf.c | 9 +++++++++
src/domain_conf.h | 2 ++
src/libvirt_private.syms | 2 ++
src/qemu_conf.c | 12 ++++++++----
4 files changed, 21 insertions(+), 4 deletions(-)
diff --git a/src/domain_conf.c b/src/domain_conf.c
index 94196e8..8deb992 100644
--- a/src/domain_conf.c
+++ b/src/domain_conf.c
@@ -142,6 +142,15 @@ VIR_ENUM_IMPL(virDomainHostdevSubsys, VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST,
"usb",
"pci")
+VIR_ENUM_IMPL(virDomainState, VIR_DOMAIN_CRASHED+1,
+ "nostate",
+ "running",
+ "blocked",
+ "paused",
+ "shutdown",
+ "shutoff",
+ "crashed")
+
#define virDomainReportError(conn, code, fmt...) \
virReportErrorHelper(conn, VIR_FROM_DOMAIN, code, __FILE__, \
__FUNCTION__, __LINE__, fmt)
diff --git a/src/domain_conf.h b/src/domain_conf.h
index 1e5c103..45b3e10 100644
--- a/src/domain_conf.h
+++ b/src/domain_conf.h
@@ -625,5 +625,7 @@ VIR_ENUM_DECL(virDomainHostdevSubsys)
VIR_ENUM_DECL(virDomainInput)
VIR_ENUM_DECL(virDomainInputBus)
VIR_ENUM_DECL(virDomainGraphics)
+/* from libvirt.h */
+VIR_ENUM_DECL(virDomainState)
#endif /* __DOMAIN_CONF_H */
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index c76b6c2..3f83a07 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -94,6 +94,8 @@ virDomainVirtTypeToString;
virDomainFSDefFree;
virDomainObjLock;
virDomainObjUnlock;
+virDomainStateTypeToString;
+virDomainStateTypeFromString;
# domain_event.h
diff --git a/src/qemu_conf.c b/src/qemu_conf.c
index faf1e12..45108f3 100644
--- a/src/qemu_conf.c
+++ b/src/qemu_conf.c
@@ -1375,12 +1375,14 @@ qemudDomainStatusParseFile(virConnectPtr conn,
}
ctxt->node = root;
- if((virXPathLong(conn, "string(./@state)", ctxt, &val)) < 0) {
+ if(!(tmp = virXPathString(conn, "string(./@state)", ctxt))) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
"%s", _("invalid domain state"));
goto error;
- } else
- status->state = (int)val;
+ } else {
+ status->state = virDomainStateTypeFromString(tmp);
+ VIR_FREE(tmp);
+ }
if((virXPathLong(conn, "string(./@pid)", ctxt, &val)) < 0) {
qemudReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
@@ -1433,7 +1435,9 @@ qemudDomainStatusFormat(virConnectPtr conn,
char *config_xml = NULL, *xml = NULL;
virBuffer buf = VIR_BUFFER_INITIALIZER;
- virBufferVSprintf(&buf, "<domstatus state='%d' pid='%d'>\n", vm->state, vm->pid);
+ virBufferVSprintf(&buf, "<domstatus state='%s' pid='%d'>\n",
+ virDomainStateTypeToString(vm->state),
+ vm->pid);
virBufferEscapeString(&buf, " <monitor path='%s'/>\n", vm->monitorpath);
if (!(config_xml = virDomainDefFormat(conn,
--
1.6.0.6
16 years, 1 month
[libvirt] [PATCH] don't ignore write failure [was PATCH: 10/25: ...
by Jim Meyering
"Daniel P. Berrange" <berrange(a)redhat.com> wrote:
> The strerror() method is not guarenteed to be re-entrant, which is
...
> @@ -759,8 +762,8 @@ static int networkStartNetworkDaemon(vir
>
> if (network->def->forwardType != VIR_NETWORK_FORWARD_NONE &&
> !networkEnableIpForwarding()) {
> - networkReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR,
> - _("failed to enable IP forwarding : %s"), strerror(err));
> + virReportSystemError(conn, errno, "%s",
> + _("failed to enable IP forwarding"));
> goto err_delbr2;
> }
>
Looking at this chunk and the s/err/errno/ change (that's a bug fix),
I spotted another small bug:
Any write error in networkEnableIpForwarding was ignored,
I added a check for failed close, too, just in case.
Jim
>From b4abd36014b56cdb33a91ab336eff6450a5d3c8a Mon Sep 17 00:00:00 2001
From: Jim Meyering <meyering(a)redhat.com>
Date: Mon, 19 Jan 2009 10:11:15 +0100
Subject: [PATCH] don't ignore write failure
* src/network_driver.c (networkEnableIpForwarding): This function
would always return 1 (success). Now it returns 0 upon write or
close failure, being careful to preserve any errno from a write failure.
Add comments.
---
src/network_driver.c | 20 ++++++++++++++------
1 files changed, 14 insertions(+), 6 deletions(-)
diff --git a/src/network_driver.c b/src/network_driver.c
index 695acfb..51cfbbd 100644
--- a/src/network_driver.c
+++ b/src/network_driver.c
@@ -1,7 +1,7 @@
/*
* driver.c: core driver methods for managing qemu guests
*
- * Copyright (C) 2006, 2007, 2008 Red Hat, Inc.
+ * Copyright (C) 2006-2009 Red Hat, Inc.
* Copyright (C) 2006 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
@@ -774,20 +774,29 @@ networkRemoveIptablesRules(struct network_driver *driver,
iptablesSaveRules(driver->iptables);
}
+/* Enable IP Forwarding.
+ Return 0 for success, nonzero for failure.
+ Be careful to preserve any errno value upon failure. */
static int
networkEnableIpForwarding(void)
{
#define PROC_IP_FORWARD "/proc/sys/net/ipv4/ip_forward"
- int fd, ret;
+ int fd;
if ((fd = open(PROC_IP_FORWARD, O_WRONLY|O_TRUNC)) == -1)
return 0;
- if (safewrite(fd, "1\n", 2) < 0)
- ret = 0;
+ if (safewrite(fd, "1\n", 2) < 0) {
+ int saved_errno = errno;
+ close (fd);
+ errno = saved_errno;
+ return 0;
+ }
- close (fd);
+ /* Use errno from failed close only if there was no write error. */
+ if (close (fd) != 0)
+ return 0;
return 1;
@@ -1429,4 +1438,3 @@ int networkRegister(void) {
virRegisterStateDriver(&networkStateDriver);
return 0;
}
-
--
1.6.1.258.g7ff14
16 years, 1 month