[libvirt] [PATCH] Solaris least privilege support
by john.levon@sun.com
# HG changeset patch
# User john.levon(a)sun.com
# Date 1231990064 28800
# Node ID 629c101c9ec11f3eb5cb56eb9548c96c33c8daf6
# Parent 0f488fb716b1ab0a1379509b8b3594f32f0ea980
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,25 @@
#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, ...);
+
+#endif
+
static int godaemon = 0; /* -d: Be a daemon */
static int verbose = 0; /* -v: Verbose mode */
static int timeout = -1; /* -t: Shutdown timeout */
@@ -638,10 +657,32 @@ 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();
-
+#ifdef __sun
+ char *base = NULL;
+
+ if (virAsprintf (&base, "%s/run/libvirt", LOCAL_STATE_DIR) == -1) {
+ VIR_ERROR0(_("Out of memory"));
+ return -1;
+ }
+ if (mkdir (base, 0755)) {
+ if (errno != EEXIST) {
+ VIR_ERROR0(_("unable to create rundir"));
+ free (base);
+ exit(-1);
+ }
+ }
+
+ free (base);
+#endif
+
+#ifdef __sun
+ if (uid == 60) {
+#else
if (!uid) {
+#endif
if (snprintf (sockname, maxlen, "%s/run/libvirt/libvirt-sock",
LOCAL_STATE_DIR) >= maxlen)
goto snprintf_error;
@@ -1105,6 +1146,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);
@@ -2140,6 +2204,10 @@ remoteReadConfigFile (struct qemud_serve
if (auth_unix_rw == REMOTE_AUTH_POLKIT)
unix_sock_rw_mask = 0777;
#endif
+#ifdef __sun
+ unix_sock_rw_mask = 0666;
+#endif
+
if (remoteConfigGetAuth(conf, "auth_unix_ro", &auth_unix_ro, filename) < 0)
goto free_and_fail;
if (remoteConfigGetAuth(conf, "auth_tcp", &auth_tcp, filename) < 0)
@@ -2239,6 +2307,31 @@ 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", 60, 60);
+ chown ("/var/run/libvirt/libvirt-sock", 60, 60);
+ chmod ("/var/run/libvirt/libvirt-sock", 0666);
+ chown (server->logDir, 60, 60);
+
+ if (__init_daemon_priv (PU_RESETGROUPS | PU_CLEARLIMITSET,
+ 60, 60, 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 +2510,8 @@ int main(int argc, char **argv) {
sig_action.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &sig_action, NULL);
+ qemudSetupPrivs(server);
+
if (!(server = qemudInitialize(sigpipe[0]))) {
ret = 2;
goto error2;
diff --git a/qemud/remote.c b/qemud/remote.c
--- a/qemud/remote.c
+++ b/qemud/remote.c
@@ -424,6 +424,15 @@ remoteDispatchOpen (struct qemud_server
flags = args->flags;
if (client->readonly) flags |= VIR_CONNECT_RO;
+#ifdef __sun
+ /*
+ * On Solaris, all clients are forced to go via virtd. As a result,
+ * virtd must indicate it really does want to connect to the
+ * hypervisor.
+ */
+ name = "xen:///";
+#endif
+
client->conn =
flags & VIR_CONNECT_RO
? virConnectOpenReadOnly (name)
diff --git a/src/libvirt.c b/src/libvirt.c
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -46,6 +46,7 @@
#include "test.h"
#endif
#ifdef WITH_XEN
+#include "xen_internal.h"
#include "xen_unified.h"
#endif
#ifdef WITH_REMOTE
@@ -825,6 +826,17 @@ do_open (const char *name,
}
}
+#ifdef __sun
+ /*
+ * If we're not libvirtd, force us to go via the daemon, unless we
+ * want the test hypervisor.
+ */
+ if (name == NULL || !STRCASEEQLEN (name, "test://", 7)) {
+ if (geteuid() == 0 || !xenHavePrivilege())
+ name = "remote+unix:///";
+ }
+#endif
+
if (name) {
/* Convert xen -> xen:/// for back compat */
if (STRCASEEQ(name, "xen"))
diff --git a/src/remote_internal.c b/src/remote_internal.c
--- a/src/remote_internal.c
+++ b/src/remote_internal.c
@@ -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;
@@ -5086,8 +5089,7 @@ really_read_buf (virConnectPtr conn, str
return -1;
}
if (err == 0) {
- error (in_open ? NULL : conn,
- VIR_ERR_RPC, _("socket closed unexpectedly"));
+ DEBUG("conn %p: socket closed unexpectedly", conn);
return -1;
}
} else {
@@ -5101,8 +5103,7 @@ really_read_buf (virConnectPtr conn, str
return -1;
}
if (err == 0) {
- error (in_open ? NULL : conn,
- VIR_ERR_RPC, _("socket closed unexpectedly"));
+ DEBUG("conn %p: socket closed unexpectedly", conn);
return -1;
}
}
diff --git a/src/virsh.c b/src/virsh.c
--- a/src/virsh.c
+++ b/src/virsh.c
@@ -28,6 +28,7 @@
#include <limits.h>
#include <assert.h>
#include <errno.h>
+#include <signal.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <inttypes.h>
@@ -46,6 +47,7 @@
#include "util.h"
static char *progname;
+static int sigpipe;
#ifndef TRUE
#define TRUE 1
@@ -6984,12 +6986,22 @@ vshParseArgv(vshControl *ctl, int argc,
return TRUE;
}
+static void sigpipe_handler(int sig ATTRIBUTE_UNUSED)
+{
+ sigpipe = 1;
+ /*
+ * Force readline() to exit.
+ */
+ close(STDIN_FILENO);
+}
+
int
main(int argc, char **argv)
{
vshControl _ctl, *ctl = &_ctl;
char *defaultConn;
int ret = TRUE;
+ struct sigaction sig_action;
if (!setlocale(LC_ALL, "")) {
perror("setlocale");
@@ -7021,6 +7033,12 @@ main(int argc, char **argv)
vshDeinit(ctl);
exit(EXIT_FAILURE);
}
+
+ sig_action.sa_handler = sigpipe_handler;
+ sig_action.sa_flags = 0;
+ sigemptyset(&sig_action.sa_mask);
+
+ sigaction(SIGPIPE, &sig_action, NULL);
if (!vshInit(ctl)) {
vshDeinit(ctl);
@@ -7061,6 +7079,13 @@ main(int argc, char **argv)
fputc('\n', stdout); /* line break after alone prompt */
}
+ /*
+ * If the connection over a socket failed abruptly, it's probably
+ * due to not having the right privileges.
+ */
+ if (sigpipe)
+ vshError(ctl, TRUE, _("failed to connect (insufficient privileges?)"));
+
vshDeinit(ctl);
exit(ret ? EXIT_SUCCESS : EXIT_FAILURE);
}
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
@@ -283,8 +283,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 +293,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 +318,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"));
}
15 years, 11 months
[libvirt] [PATCH] Introduce virt-console
by john.levon@sun.com
# HG changeset patch
# User John Levon <john.levon(a)sun.com>
# Date 1231946128 28800
# Node ID dd17b3062611925baa2698ff5923579d0f2cd34e
# Parent a0d98d39955f4f304d318c7c780742ab929eb351
Introduce virt-console
Separate console handling out into a separate binary to allow management
of privileges.
Signed-off-by: John Levon <john.levon(a)sun.com>
diff --git a/src/Makefile.am b/src/Makefile.am
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -479,12 +479,16 @@ libvirt_test_la_LDFLAGS = $(test_LDFLAGS
libvirt_test_la_LDFLAGS = $(test_LDFLAGS)
libvirt_test_la_CFLAGS = $(COVERAGE_CFLAGS)
+libexec_PROGRAMS = virt-console
+
+virt_console_SOURCES = console.c
+virt_console_CFLAGS = $(COVERAGE_CFLAGS)
+virt_console_LDFLAGS = $(WARN_CFLAGS) $(COVERAGE_LDFLAGS)
+virt_console_LDADD = libvirt.la ../gnulib/lib/libgnu.la $(VIRSH_LIBS)
+
bin_PROGRAMS = virsh
-virsh_SOURCES = \
- console.c console.h \
- virsh.c
-
+virsh_SOURCES = virsh.c
virsh_LDFLAGS = $(WARN_CFLAGS) $(COVERAGE_LDFLAGS)
virsh_LDADD = \
$(STATIC_BINARIES) \
@@ -554,8 +558,6 @@ virsh_win_icon.$(OBJEXT): virsh_win_icon
--output-format coff --output $@
endif
-libexec_PROGRAMS =
-
if WITH_STORAGE_DISK
if WITH_LIBVIRTD
libexec_PROGRAMS += libvirt_parthelper
diff --git a/src/console.c b/src/console.c
--- a/src/console.c
+++ b/src/console.c
@@ -1,7 +1,10 @@
/*
- * console.c: A dumb serial console client
+ * virt-console: client for connecting to domain consoles.
*
* Copyright (C) 2007, 2008 Red Hat, Inc.
+ *
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -22,34 +25,65 @@
#include <config.h>
-#ifndef __MINGW32__
-
#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <termios.h>
+#include <signal.h>
#include <sys/types.h>
-#include <sys/stat.h>
+#include <unistd.h>
#include <fcntl.h>
-#include <termios.h>
#include <poll.h>
-#include <string.h>
-#include <errno.h>
-#include <unistd.h>
-#include <signal.h>
-
-#include "console.h"
+#include <getopt.h>
+#include <locale.h>
+
+#include <libxml/parser.h>
+#include <libxml/tree.h>
+#include <libxml/xpath.h>
+
#include "internal.h"
+#include "memory.h"
#include "util.h"
+#include "xml.h"
/* ie Ctrl-] as per telnet */
#define CTRL_CLOSE_BRACKET '\35'
-static int got_signal = 0;
-static void do_signal(int sig ATTRIBUTE_UNUSED) {
+static int got_signal;
+static int verbose;
+static const char *dom_name;
+static const char *conn_name;
+
+#ifdef __sun
+#include <stropts.h>
+#include <priv.h>
+
+#define PU_RESETGROUPS 0x0001 /* Remove supplemental groups */
+#define PU_LIMITPRIVS 0x0002 /* L=P */
+#define PU_INHERITPRIVS 0x0004 /* I=P */
+#define PU_CLEARLIMITSET 0x0008 /* L=0 */
+
+extern int __init_suid_priv(int, ...);
+extern int __priv_bracket(priv_op_t);
+
+#ifndef PRIV_XVM_CONTROL
+#define PRIV_XVM_CONTROL ((const char *)"xvm_control")
+#endif
+#ifndef PRIV_VIRT_MANAGE
+#define PRIV_VIRT_MANAGE ((const char *)"virt_manage")
+#endif
+
+#endif /* __sun */
+
+static void
+do_signal(int sig ATTRIBUTE_UNUSED)
+{
got_signal = 1;
}
#ifndef HAVE_CFMAKERAW
static void
-cfmakeraw (struct termios *attr)
+cfmakeraw(struct termios *attr)
{
attr->c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
| INLCR | IGNCR | ICRNL | IXON);
@@ -57,46 +91,432 @@ cfmakeraw (struct termios *attr)
attr->c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
attr->c_cflag &= ~(CSIZE | PARENB);
attr->c_cflag |= CS8;
+
+#ifdef __sun
+ attr->c_cc[VMIN] = 0;
+ attr->c_cc[VTIME] = 0;
+#endif
}
#endif /* !HAVE_CFMAKERAW */
-int vshRunConsole(const char *tty) {
- int ttyfd, ret = -1;
- struct termios ttyattr, rawattr;
+static void make_tty_raw(int fd, struct termios *attr)
+{
+ struct termios ttyattr;
+ struct termios rawattr;
+
+ if (attr == NULL)
+ attr = &ttyattr;
+
+ if (tcgetattr(fd, attr) < 0) {
+ fprintf(stderr, _("Unable to get tty attributes: %s\n"),
+ strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ rawattr = *attr;
+ cfmakeraw(&rawattr);
+
+ if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &rawattr) < 0) {
+ fprintf(stderr, _("Unable to set tty attributes: %s\n"),
+ strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+}
+
+#ifdef __sun
+
+/*
+ * Verify that the real user invoking this setuid-root executable has
+ * the needed privilege, then drop root and all the privileges we don't
+ * need before continuing.
+ */
+static void
+setup_perms(void)
+{
+ if (seteuid(getuid()) == -1) {
+ perror("seteuid failed");
+ exit(1);
+ }
+
+ if (!priv_ineffect(PRIV_VIRT_MANAGE)) {
+ fprintf(stderr, "virt-console: permission denied\n");
+ exit(1);
+ }
+
+ if (seteuid(0) == -1) {
+ perror("seteuid failed");
+ exit(1);
+ }
+
+ /*
+ * We need to be able to talk to libvirt and open pty's.
+ */
+ __init_suid_priv(PU_RESETGROUPS | PU_CLEARLIMITSET,
+ PRIV_VIRT_MANAGE, PRIV_FILE_DAC_READ,
+ PRIV_FILE_DAC_WRITE, NULL);
+}
+
+#else
+#define setup_perms()
+#define __priv_bracket(a)
+#endif
+
+static void
+usage(int exitval)
+{
+ FILE *f = stderr;
+
+ if (exitval == EXIT_SUCCESS)
+ f = stdout;
+
+ fprintf(f, _("usage: virt-console [options] domain\n\n"
+ " options:\n"
+ " -c | --connect <uri> hypervisor connection URI\n"
+ " -h | --help this help\n"
+ " -v | --verbose be verbose\n\n"));
+
+ exit(exitval);
+}
+
+static void
+parse_args(int argc, char *argv[])
+{
+ int idx = 0;
+ int arg;
+
+ struct option opt[] = {
+ { "connect", 1, 0, 'c' },
+ { "help", 0, 0, 'h' },
+ { "verbose", 0, 0, 'v' },
+ { 0, 0, 0, 0 }
+ };
+
+ while ((arg = getopt_long(argc, argv, "c:hv", opt, &idx)) != -1) {
+ switch (arg) {
+ case 'c':
+ conn_name = optarg;
+ break;
+ case 'h':
+ usage(EXIT_SUCCESS);
+ break;
+ case 'v':
+ verbose = 1;
+ break;
+ default:
+ usage(EXIT_FAILURE);
+ break;
+ }
+ }
+
+ if ((argc - optind) != 1)
+ usage(EXIT_FAILURE);
+
+ dom_name = argv[optind];
+
+ if (conn_name == NULL)
+ conn_name = getenv("VIRSH_DEFAULT_CONNECT_URI");
+}
+
+static int
+get_domain(virConnectPtr *conn, virDomainPtr *dom,
+ virDomainInfo *info, int lookup_by_id)
+{
+ int ret = 0;
+ int id;
+
+ __priv_bracket(PRIV_ON);
+
+ printf("1\n");
+ *conn = virConnectOpenAuth(conn_name, virConnectAuthPtrDefault,
+ VIR_CONNECT_RO);
+ printf("2\n");
+ if (*conn == NULL) {
+ fprintf(stderr, _("Failed to connect to the hypervisor"));
+ exit(EXIT_FAILURE);
+ }
+
+ *dom = virDomainLookupByName(*conn, dom_name);
+
+ if (*dom == NULL)
+ *dom = virDomainLookupByUUIDString(*conn, dom_name);
+ if (*dom == NULL && lookup_by_id &&
+ virStrToLong_i(dom_name, NULL, 10, &id) == 0 && id >= 0)
+ *dom = virDomainLookupByID(*conn, id);
+
+ if (*dom == NULL)
+ goto out;
+
+ if (info != NULL) {
+ if (virDomainGetInfo(*dom, info) < 0)
+ goto out;
+ }
+
+ ret = 1;
+
+out:
+ if (ret == 0) {
+ if (*dom != NULL)
+ virDomainFree(*dom);
+ virConnectClose(*conn);
+ }
+ __priv_bracket(PRIV_OFF);
+ return ret;
+}
+
+static void
+put_domain(virConnectPtr conn, virDomainPtr dom)
+{
+ __priv_bracket(PRIV_ON);
+ if (dom != NULL)
+ virDomainFree(dom);
+ virConnectClose(conn);
+ __priv_bracket(PRIV_OFF);
+}
+
+static char *
+get_domain_tty(void)
+{
+ xmlXPathContextPtr ctxt = NULL;
+ xmlDocPtr xml = NULL;
+ virConnectPtr conn = NULL;
+ virDomainPtr dom = NULL;
+ char *doc = NULL;
+ char *tty = NULL;
+
+ if (!get_domain(&conn, &dom, NULL, 1)) {
+ fprintf(stderr, _("Couldn't find domain \"%s\".\n"), dom_name);
+ exit(EXIT_FAILURE);
+ }
+
+ __priv_bracket(PRIV_ON);
+ doc = virDomainGetXMLDesc(dom, 0);
+ __priv_bracket(PRIV_OFF);
+
+ put_domain(conn, dom);
+ conn = NULL;
+ dom = NULL;
+
+ if (doc == NULL)
+ goto cleanup;
+
+ xml = xmlReadDoc((const xmlChar *) doc, "domain.xml", NULL,
+ XML_PARSE_NOENT | XML_PARSE_NONET |
+ XML_PARSE_NOWARNING);
+ if (xml == NULL)
+ goto cleanup;
+
+ ctxt = xmlXPathNewContext(xml);
+ if (ctxt == NULL)
+ goto cleanup;
+
+ tty = virXPathString(conn, "string(/domain/devices/console/@tty)", ctxt);
+
+cleanup:
+ VIR_FREE(doc);
+ xmlXPathFreeContext(ctxt);
+ if (xml != NULL)
+ xmlFreeDoc(xml);
+ return tty;
+}
+
+static int
+domain_is_running(void)
+{
+ virConnectPtr conn = NULL;
+ virDomainPtr dom = NULL;
+ virDomainInfo info;
+ int ret = -1;
+
+ if (!get_domain(&conn, &dom, &info, 1))
+ return -1;
+
+ switch (info.state) {
+ case VIR_DOMAIN_RUNNING:
+ case VIR_DOMAIN_BLOCKED:
+ case VIR_DOMAIN_PAUSED:
+ ret = 1;
+ break;
+
+ case VIR_DOMAIN_NOSTATE:
+ case VIR_DOMAIN_CRASHED:
+ case VIR_DOMAIN_SHUTDOWN:
+ case VIR_DOMAIN_SHUTOFF:
+ ret = 0;
+ break;
+
+ default:
+ break;
+ }
+
+ put_domain(conn, dom);
+ return ret;
+}
+
+static int
+check_for_reboot(void)
+{
+ virConnectPtr conn = NULL;
+ virDomainPtr dom = NULL;
+ virDomainInfo info;
+ int tries = 0;
+ int ret = 0;
+
+retry:
+ if (dom != NULL)
+ put_domain(conn, dom);
+
+ /*
+ * Domain ID will vary across reboot, so don't lookup by a given ID.
+ */
+ if (!get_domain(&conn, &dom, &info, 0))
+ return 0;
+
+ switch (info.state) {
+ case VIR_DOMAIN_RUNNING:
+ case VIR_DOMAIN_BLOCKED:
+ case VIR_DOMAIN_PAUSED:
+ ret = 1;
+ goto out;
+ break;
+
+ case VIR_DOMAIN_CRASHED:
+ if (verbose)
+ fprintf(stderr, _("Domain \"%s\" has crashed."), dom_name);
+ goto out;
+ break;
+
+ case VIR_DOMAIN_NOSTATE:
+ default:
+ break;
+
+ case VIR_DOMAIN_SHUTDOWN:
+ if (verbose)
+ fprintf(stderr, _("Domain \"%s\" is shutting down.\n"), dom_name);
+ tries = 0;
+ break;
+
+ case VIR_DOMAIN_SHUTOFF:
+ if (verbose)
+ fprintf(stderr, _("Domain \"%s\" has shut down."), dom_name);
+ goto out;
+ break;
+ }
+
+ tries++;
+ if (tries == 1) {
+ goto retry;
+ } else if (tries < 6) {
+ sleep(1);
+ goto retry;
+ }
+
+out:
+ put_domain(conn, dom);
+ return ret;
+}
+
+static int
+open_tty(void)
+{
+ struct termios ttyattr;
+ char *tty;
+ int ttyfd;
+
+ if ((tty = get_domain_tty()) == NULL) {
+ if (domain_is_running() != 1) {
+ fprintf(stderr, _("Domain \"%s\" is not running.\n"), dom_name);
+ exit(EXIT_FAILURE);
+ }
+
+ fprintf(stderr,
+ _("Couldn't get console for domain \"%s\"\n"), dom_name);
+ exit(EXIT_FAILURE);
+ }
+
+ __priv_bracket(PRIV_ON);
+ if ((ttyfd = open(tty, O_NOCTTY | O_RDWR)) < 0) {
+ fprintf(stderr, _("Unable to open tty %s: %s\n"),
+ tty, strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ if (lockf(ttyfd, F_TLOCK, 0) == -1) {
+ if (errno == EACCES || errno == EAGAIN) {
+ fprintf(stderr,
+ _("Console for domain \"%s\" is in use.\n"), dom_name);
+ } else {
+ fprintf(stderr, _("Unable to lock tty %s: %s\n"),
+ tty, strerror(errno));
+ }
+ exit(EXIT_FAILURE);
+ }
+ __priv_bracket(PRIV_OFF);
+
+ VIR_FREE(tty);
+
+#ifdef __sun
+ /*
+ * The pty may come from either xend (with pygrub) or xenconsoled.
+ * It may have tty semantics set up, or not. While it isn't
+ * strictly necessary to have those semantics here, it is good to
+ * have a consistent state that is the same as under Linux.
+ *
+ * If tcgetattr fails, they have not been set up, so go ahead and
+ * set them up now, by pushing the ptem and ldterm streams modules.
+ */
+ if (tcgetattr(ttyfd, &ttyattr) < 0) {
+ ioctl(ttyfd, I_PUSH, "ptem");
+ ioctl(ttyfd, I_PUSH, "ldterm");
+ tcgetattr(ttyfd, &ttyattr);
+ }
+
+ cfmakeraw(&ttyattr);
+ tcsetattr(ttyfd, TCSANOW, &ttyattr);
+#endif
+
+ return ttyfd;
+}
+
+static void
+close_tty(int ttyfd)
+{
+ while (lockf(ttyfd, F_ULOCK, 0) && errno == EINTR)
+ ;
+ close(ttyfd);
+}
+
+int
+main(int argc, char *argv[])
+{
+ struct termios ttyattr;
+ struct termios rawattr;
void (*old_sigquit)(int);
void (*old_sigterm)(int);
void (*old_sigint)(int);
void (*old_sighup)(int);
void (*old_sigpipe)(int);
-
-
- /* We do not want this to become the controlling TTY */
- if ((ttyfd = open(tty, O_NOCTTY | O_RDWR)) < 0) {
- fprintf(stderr, _("unable to open tty %s: %s\n"),
- tty, strerror(errno));
+ int ret = EXIT_FAILURE;
+ int retrying = 0;
+ int ttyfd;
+
+ setup_perms();
+
+ if (!setlocale(LC_ALL, "")) {
+ perror("setlocale");
return -1;
}
- /* Put STDIN into raw mode so that stuff typed
- does not echo to the screen (the TTY reads will
- result in it being echoed back already), and
- also ensure Ctrl-C, etc is blocked, and misc
- other bits */
- if (tcgetattr(STDIN_FILENO, &ttyattr) < 0) {
- fprintf(stderr, _("unable to get tty attributes: %s\n"),
- strerror(errno));
- goto closetty;
- }
-
- rawattr = ttyattr;
- cfmakeraw(&rawattr);
-
- if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &rawattr) < 0) {
- fprintf(stderr, _("unable to set tty attributes: %s\n"),
- strerror(errno));
- goto closetty;
- }
-
+ if (!bindtextdomain(GETTEXT_PACKAGE, LOCALEBASEDIR)) {
+ perror("bindtextdomain");
+ return -1;
+ }
+
+ if (!textdomain(GETTEXT_PACKAGE)) {
+ perror("textdomain");
+ return -1;
+ }
+
+ parse_args(argc, argv);
/* Trap all common signals so that we can safely restore
the original terminal settings on STDIN before the
@@ -107,8 +527,36 @@ int vshRunConsole(const char *tty) {
old_sigint = signal(SIGINT, do_signal);
old_sighup = signal(SIGHUP, do_signal);
old_sigpipe = signal(SIGPIPE, do_signal);
- got_signal = 0;
-
+
+retry:
+
+ ttyfd = open_tty();
+
+ if (!retrying && verbose) {
+ printf("Connected to domain %s\n", dom_name);
+ printf("Escape character is '^]'\n");
+ }
+
+ /*
+ * Put STDIN into raw mode so that stuff typed does not echo to the
+ * screen (the TTY reads will result in it being echoed back
+ * already), and also ensure Ctrl-C, etc is blocked, and misc other
+ * bits
+ */
+ if (tcgetattr(STDIN_FILENO, &ttyattr) < 0) {
+ fprintf(stderr, _("unable to get tty attributes: %s\n"),
+ strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+
+ rawattr = ttyattr;
+ cfmakeraw(&rawattr);
+
+ if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &rawattr) < 0) {
+ fprintf(stderr, _("unable to set tty attributes: %s\n"),
+ strerror(errno));
+ exit(EXIT_FAILURE);
+ }
/* Now lets process STDIN & tty forever.... */
for (; !got_signal ;) {
@@ -127,7 +575,7 @@ int vshRunConsole(const char *tty) {
if (errno == EINTR || errno == EAGAIN)
continue;
- fprintf(stderr, _("failure waiting for I/O: %s\n"),
+ fprintf(stderr, _("Failure waiting for I/O: %s\n"),
strerror(errno));
goto cleanup;
}
@@ -142,15 +590,21 @@ int vshRunConsole(const char *tty) {
int got, sent = 0, destfd;
if ((got = read(fds[i].fd, buf, sizeof(buf))) < 0) {
- fprintf(stderr, _("failure reading input: %s\n"),
+ fprintf(stderr, _("Failure reading input: %s\n"),
strerror(errno));
goto cleanup;
}
- /* Quit if end of file, or we got the Ctrl-] key */
- if (!got ||
- (got == 1 &&
- buf[0] == CTRL_CLOSE_BRACKET))
+ if (!got) {
+ tcsetattr(STDIN_FILENO, TCSAFLUSH, &ttyattr);
+ if (!check_for_reboot())
+ goto done;
+ close_tty(ttyfd);
+ retrying = 1;
+ goto retry;
+ }
+
+ if (got == 1 && buf[0] == CTRL_CLOSE_BRACKET)
goto done;
/* Data from stdin goes to the TTY,
@@ -162,23 +616,31 @@ int vshRunConsole(const char *tty) {
while (sent < got) {
int done;
- if ((done = safewrite(destfd, buf + sent, got - sent))
- <= 0) {
- fprintf(stderr, _("failure writing output: %s\n"),
+ if ((done = safewrite(destfd, buf + sent, got - sent)) <= 0) {
+ fprintf(stderr, _("Failure writing output: %s\n"),
strerror(errno));
goto cleanup;
}
sent += done;
}
+ } else if (fds[i].revents & POLLHUP) {
+ tcsetattr(STDIN_FILENO, TCSAFLUSH, &ttyattr);
+ if (!check_for_reboot())
+ goto done;
+ close_tty(ttyfd);
+ retrying = 1;
+ goto retry;
} else { /* Any other flag from poll is an error condition */
goto cleanup;
}
}
}
- done:
- ret = 0;
-
- cleanup:
+
+done:
+ ret = EXIT_SUCCESS;
+cleanup:
+ tcsetattr(STDIN_FILENO, TCSANOW, &ttyattr);
+ close_tty(ttyfd);
/* Restore original signal handlers */
signal(SIGQUIT, old_sigpipe);
@@ -187,14 +649,18 @@ int vshRunConsole(const char *tty) {
signal(SIGQUIT, old_sigterm);
signal(SIGQUIT, old_sigquit);
- /* Put STDIN back into the (sane?) state we found
- it in before starting */
- tcsetattr(STDIN_FILENO, TCSAFLUSH, &ttyattr);
-
- closetty:
- close(ttyfd);
-
- return ret;
-}
-
-#endif /* !__MINGW32__ */
+ if (verbose)
+ printf("\nConnection to domain %s closed.", dom_name);
+ printf("\n");
+
+ exit(ret);
+}
+
+/*
+ * Local variables:
+ * indent-tabs-mode: nil
+ * c-indent-level: 4
+ * c-basic-offset: 4
+ * tab-width: 4
+ * End:
+ */
diff --git a/src/console.h b/src/console.h
deleted file mode 100644
--- a/src/console.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * console.c: A dumb serial console client
- *
- * Copyright (C) 2007 Red Hat, Inc.
- *
- * 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
- *
- * Daniel Berrange <berrange(a)redhat.com>
- */
-
-#ifndef __VIR_CONSOLE_H__
-#define __VIR_CONSOLE_H__
-
-#ifndef __MINGW32__
-
-int vshRunConsole(const char *tty);
-
-#endif /* !__MINGW32__ */
-
-#endif /* __VIR_CONSOLE_H__ */
diff --git a/src/util.c b/src/util.c
--- a/src/util.c
+++ b/src/util.c
@@ -240,7 +240,7 @@ __virExec(virConnectPtr conn,
childout = *outfd;
}
#ifndef ENABLE_DEBUG
- } else {
+ } else if (!(flags & VIR_EXEC_NO_PIPE)) {
childout = null;
#endif
}
@@ -271,7 +271,7 @@ __virExec(virConnectPtr conn,
childerr = *errfd;
}
#ifndef ENABLE_DEBUG
- } else {
+ } else if (!(flags & VIR_EXEC_NO_PIPE)) {
childerr = null;
#endif
}
@@ -652,6 +652,15 @@ virExec(virConnectPtr conn,
return -1;
}
+int
+virExecNoPipe(virConnectPtr conn,
+ char **argv ATTRIBUTE_UNUSED,
+ pid_t *retpid ATTRIBUTE_UNUSED)
+{
+ ReportError(conn, NULL, NULL, VIR_ERR_INTERNAL_ERROR, __FUNCTION__);
+ return -1;
+}
+
#endif /* __MINGW32__ */
/* Like gnulib's fread_file, but read no more than the specified maximum
diff --git a/src/util.h b/src/util.h
--- a/src/util.h
+++ b/src/util.h
@@ -36,6 +36,7 @@ enum {
VIR_EXEC_NONE = 0,
VIR_EXEC_NONBLOCK = (1 << 0),
VIR_EXEC_DAEMON = (1 << 1),
+ VIR_EXEC_NO_PIPE = (1 << 2)
};
int virExec(virConnectPtr conn,
diff --git a/src/virsh.c b/src/virsh.c
--- a/src/virsh.c
+++ b/src/virsh.c
@@ -29,6 +29,7 @@
#include <assert.h>
#include <errno.h>
#include <sys/stat.h>
+#include <sys/wait.h>
#include <inttypes.h>
#include <libxml/parser.h>
@@ -42,7 +43,6 @@
#include "internal.h"
#include "buf.h"
-#include "console.h"
#include "util.h"
static char *progname;
@@ -469,6 +469,7 @@ static const vshCmdInfo info_console[] =
static const vshCmdOptDef opts_console[] = {
{"domain", VSH_OT_DATA, VSH_OFLAG_REQ, gettext_noop("domain name, id or uuid")},
+ {"verbose", VSH_OT_BOOL, 0, gettext_noop("verbose console")},
{NULL, 0, 0, NULL}
};
@@ -477,49 +478,39 @@ static int
static int
cmdConsole(vshControl *ctl, const vshCmd *cmd)
{
- xmlDocPtr xml = NULL;
- xmlXPathObjectPtr obj = NULL;
- xmlXPathContextPtr ctxt = NULL;
- virDomainPtr dom;
+ const char *argv[] = { BINDIR "/virt-console", NULL, NULL, NULL, NULL };
+ int verbose = vshCommandOptBool(cmd, "verbose");
int ret = FALSE;
- char *doc;
-
- if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
- return FALSE;
-
- if (!(dom = vshCommandOptDomain(ctl, cmd, NULL)))
- return FALSE;
-
- doc = virDomainGetXMLDesc(dom, 0);
- if (!doc)
- goto cleanup;
-
- xml = xmlReadDoc((const xmlChar *) doc, "domain.xml", NULL,
- XML_PARSE_NOENT | XML_PARSE_NONET |
- XML_PARSE_NOWARNING);
- free(doc);
- if (!xml)
- goto cleanup;
- ctxt = xmlXPathNewContext(xml);
- if (!ctxt)
- goto cleanup;
-
- obj = xmlXPathEval(BAD_CAST "string(/domain/devices/console/@tty)", ctxt);
- if ((obj != NULL) && ((obj->type == XPATH_STRING) &&
- (obj->stringval != NULL) && (obj->stringval[0] != 0))) {
- if (vshRunConsole((const char *)obj->stringval) == 0)
- ret = TRUE;
- } else {
- vshPrintExtra(ctl, "%s", _("No console available for domain\n"));
- }
- xmlXPathFreeObject(obj);
-
- cleanup:
- xmlXPathFreeContext(ctxt);
- if (xml)
- xmlFreeDoc(xml);
- virDomainFree(dom);
- return ret;
+ pid_t pid;
+ int argpos = 1;
+
+ if (!vshConnectionUsability(ctl, ctl->conn, TRUE))
+ return FALSE;
+
+ if (verbose)
+ argv[argpos++] = "--verbose";
+
+ if (ctl->name != NULL) {
+ argv[argpos++] = "--connect";
+ argv[argpos++] = ctl->name;
+ }
+
+ if (!(argv[argpos] = vshCommandOptString(cmd, "domain", NULL))) {
+ vshError(ctl, FALSE, _("Undefined domain name or id."));
+ return FALSE;
+ }
+
+ ret = virExec(ctl->conn, argv, NULL, 0, &pid, STDIN_FILENO, NULL,
+ NULL, VIR_EXEC_NO_PIPE);
+
+ if (ret == -1) {
+ vshError(ctl, FALSE, _("Couldn't execute virt-console."));
+ return FALSE;
+ }
+
+ waitpid(pid, NULL, 0);
+
+ return TRUE;
}
#else /* __MINGW32__ */
@@ -4583,6 +4574,7 @@ cmdTTYConsole(vshControl *ctl, const vsh
goto cleanup;
}
vshPrint(ctl, "%s\n", (const char *)obj->stringval);
+ ret = TRUE;
cleanup:
xmlXPathFreeObject(obj);
15 years, 11 months
[libvirt] PATCH: Don't stop storage pools on daemon shutdown
by Daniel P. Berrange
Tearing a guest's storage out from under its feet on libvirtd shutdown
is just as bad as tearing out its network :-) This patch removes the
code which shuts down storage pool when the daemon shuts down. So NFS
mounts stay around, LVM VGs remain active, and iSCSI connections remain
logged in. When we then start up again, we happily detect that these
resources are already running, and mark the pool as such
Daniel
diff --git a/src/storage_backend_iscsi.c b/src/storage_backend_iscsi.c
--- a/src/storage_backend_iscsi.c
+++ b/src/storage_backend_iscsi.c
@@ -573,6 +573,7 @@ virStorageBackendISCSIStartPool(virConne
virStoragePoolObjPtr pool)
{
char *portal = NULL;
+ char *session;
if (pool->def->source.host.name == NULL) {
virStorageReportError(conn, VIR_ERR_INTERNAL_ERROR,
@@ -587,13 +588,17 @@ virStorageBackendISCSIStartPool(virConne
return -1;
}
- if ((portal = virStorageBackendISCSIPortal(conn, pool)) == NULL)
- return -1;
- if (virStorageBackendISCSILogin(conn, pool, portal) < 0) {
+ if ((session = virStorageBackendISCSISession(conn, pool)) == NULL) {
+ if ((portal = virStorageBackendISCSIPortal(conn, pool)) == NULL)
+ return -1;
+ if (virStorageBackendISCSILogin(conn, pool, portal) < 0) {
+ VIR_FREE(portal);
+ return -1;
+ }
VIR_FREE(portal);
- return -1;
+ } else {
+ VIR_FREE(session);
}
- VIR_FREE(portal);
return 0;
}
diff --git a/src/storage_driver.c b/src/storage_driver.c
--- a/src/storage_driver.c
+++ b/src/storage_driver.c
@@ -241,32 +241,10 @@ storageDriverActive(void) {
*/
static int
storageDriverShutdown(void) {
- unsigned int i;
-
if (!driverState)
return -1;
storageDriverLock(driverState);
- /* shutdown active pools */
- for (i = 0 ; i < driverState->pools.count ; i++) {
- virStoragePoolObjPtr pool = driverState->pools.objs[i];
-
- if (virStoragePoolObjIsActive(pool)) {
- virStorageBackendPtr backend;
- if ((backend = virStorageBackendForType(pool->def->type)) == NULL) {
- storageLog("Missing backend");
- continue;
- }
-
- if (backend->stopPool &&
- backend->stopPool(NULL, pool) < 0) {
- virErrorPtr err = virGetLastError();
- storageLog("Failed to stop storage pool '%s': %s",
- pool->def->name, err ? err->message : NULL);
- }
- virStoragePoolObjClearVols(pool);
- }
- }
/* free inactive pools */
virStoragePoolObjListFree(&driverState->pools);
--
|: Red Hat, Engineering, London -o- http://people.redhat.com/berrange/ :|
|: http://libvirt.org -o- http://virt-manager.org -o- http://ovirt.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: GnuPG: 7D3B9505 -o- F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505 :|
15 years, 11 months
Re: [libvirt] Compiling on Windows with MinGW/MSYS
by Richard W.M. Jones
On Thu, Jan 15, 2009 at 01:23:38PM +0100, Brecht Sanders wrote:
> I know I'm outside the envelope. But envelopes need to be pushed
> sometimes in order to get things ported.
I didn't mean to discourage you, just to note that you're likely the
first to try this.
> I'm not looking to run Xen on Windows at all.
> However, I have implementations with Xen on Linux server where all the
> other systems in the network run Windows. So I am looking for a Xen
> manager that runs on Windows purely to manage Xen running on another
> system.
>
> How would the remote driver work then exactly? Does it need some sort of
> proxy on a Linux system?
Right, so you want libvirtd running on the managed target system!
This is exactly the scenario that we support on Windows.
When you use a connection URI such as xen://somehost/, the connection
is routed through the remote driver to the libvirtd daemon listening
on the target ('somehost'). There is no need to configure the Xen
driver in the Windows client libvirt for this, since everything
involving Xen is done on the target.
There's lots more to say about this, such as security, port numbers,
transports etc. but it's better for you just to read the documentation
here:
http://libvirt.org/remote.html
(Not all transports are supported on Windows -- in particular, ssh
transport, and SASL probably don't work at the moment, although we
will try to make both work at some point in the future).
Rich.
--
Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones
virt-top is 'top' for virtual machines. Tiny program with many
powerful monitoring features, net stats, disk stats, logging, etc.
http://et.redhat.com/~rjones/virt-top
15 years, 11 months
[libvirt] [PATCH] Avoid passing NULL to printf %s specifier
by john.levon@sun.com
# HG changeset patch
# User john.levon(a)sun.com
# Date 1231985011 28800
# Node ID 2766ee91dd5ea8e99dac27ce730af0dc46a1d107
# Parent 082e0f7d5de236e69bea177c8d4c4204350144c1
Avoid passing NULL to printf %s specifier
This is non-portable.
Signed-off-by: John Levon <john.levon(a)sun.com>
diff --git a/src/internal.h b/src/internal.h
--- a/src/internal.h
+++ b/src/internal.h
@@ -115,6 +115,8 @@
#define ATTRIBUTE_RETURN_CHECK
#endif /* __GNUC__ */
+#define NULLSTR(a) ((a) ? (a) : "(null)")
+
/**
* TODO:
*
diff --git a/src/libvirt.c b/src/libvirt.c
--- a/src/libvirt.c
+++ b/src/libvirt.c
@@ -874,10 +874,10 @@ do_open (const char *name,
" port %d\n"
" path %s\n",
name,
- ret->uri->scheme, ret->uri->opaque,
- ret->uri->authority, ret->uri->server,
- ret->uri->user, ret->uri->port,
- ret->uri->path);
+ NULLSTR(ret->uri->scheme), NULLSTR(ret->uri->opaque),
+ NULLSTR(ret->uri->authority), NULLSTR(ret->uri->server),
+ NULLSTR(ret->uri->user), ret->uri->port,
+ NULLSTR(ret->uri->path));
} else {
DEBUG0("no name, allowing driver auto-select");
}
15 years, 11 months
[libvirt] Compiling on Windows with MinGW/MSYS
by Brecht Sanders
Hi,
It's been a long time since I tried to compile libvirt on Windows using
the MinGW/MSYS environment.
I tried it again and I have good news and bad news.
The good news is thet when I disable support for most things
(--without-xen --without-qemu --without-openvz --without-uml
--without-test --without-libvirtd --with-remote-pid-file=none
--with-init-scripts=none --with-depends --without-sasl --without-polkit)
it now builds fine and even the DLL was built (libvirt-0.dll).
The bad news is that when I enable Xen support, it now depends on the
xenstore library.
Unfortunately I wasn't able to build this library on Windows.
Is this dependancy necessary?
Does anyone know of xenstore on Windows?
Regards
Brecht Sanders
15 years, 11 months
[libvirt] [ANN] sVirt v0.30
by James Morris
This is to announce the release of v0.30 of sVirt, a project to add
security labeling support to Linux-based virtualization.
Project page:
http://www.selinuxproject.org/page/SVirt
Download:
http://namei.org/svirt/svirt-0.30.tar.bz2
This release is an update in response to feedback received on the v0.20
release, per the discussion thread at:
https://www.redhat.com/archives/libvir-list/2008-December/msg00260.html
Also see the TODO page:
http://selinuxproject.org/page/SVirt/TODO
Change log for v0.30:
---------------------
* Fix SELinux build configuration
* Simplify qemudNodeGetSecurityModel
* Add "test" security driver
* Fix security driver probe logic
* Ensure VIR_CONNECT_RO checked where appropriate
* Move security model/doi to last fields in virsh dominfo
* Change virDomainSecLabel -> virSecurityLabel
* similar change to API calls
* Change virDomainSecModel -> virSecurityModel
* similar change to API calls
* general renaming then of seclabel to security
* Use CHECK_LIB/HEADER to detect libselinux (and fix build system in general)
* Rename virDomainGetSecModel to virNodeGetSecurityModel
* Change -2 error returns to -1
* Use remoteDispatchOOMError() for OOM errors
* Create virXPathStringLimit() from virDomainSecLabelDefParseXMLString()
Comments welcome.
- James
--
James Morris
<jmorris(a)namei.org>
15 years, 11 months
[libvirt] [PATCH] Improve xend_get error message
by john.levon@sun.com
# HG changeset patch
# User john.levon(a)sun.com
# Date 1231982481 28800
# Node ID 082e0f7d5de236e69bea177c8d4c4204350144c1
# Parent 1a16d4b76232845091c1f800569ec462860cb1fb
Improve xend_get error message
Signed-off-by: John Levon <john.levon(a)sun.com>
diff --git a/src/xend_internal.c b/src/xend_internal.c
--- a/src/xend_internal.c
+++ b/src/xend_internal.c
@@ -394,7 +394,8 @@ xend_get(virConnectPtr xend, const char
if (((ret < 0) || (ret >= 300)) &&
((ret != 404) || (!STRPREFIX(path, "/xend/domain/")))) {
virXendError(xend, VIR_ERR_GET_FAILED,
- _("xend_get: error from xen daemon: %s"), content);
+ _("%d status from xen daemon: %s:%s"),
+ ret, path, content);
}
return ret;
15 years, 11 months
[libvirt] [PATCH] Invoke PortableXDR's rpcgen if available
by Richard W.M. Jones
We discovered over the new year that the XDR code in glibc, which was
derived from some original Sun code, doesn't have an unambiguously
free license[1]. Furthermore the rpcgen in glibc is unmaintained and
produces such bad code that we have to run a Perl script over it in
order to correct some egregious errors. Sun/glibc rpcgen code also
contains all sorts of strange micro-optimizations that were probably
good back in 1988, but don't make so much sense now. Also rpcgen was
implemented directly in C, so we took this chance to use flex/bison
for more accurate and faster parsing.
For these reasons we are rewriting the XDR code and the rpcgen tool
with a free license[2]. I'm pleased to say that as a result of this
effort we've rewritten rpcgen already:
http://git.et.redhat.com/?p=portablexdr.git;a=summary
To avoid conflicts, the new rpcgen will be installed as
'portable-rpcgen'.
The attached patch changes libvirt's configure so that if it finds
'portable-rpcgen' on the path, it uses it in preference to 'rpcgen'.
Also attached are the updated remote_protocol.[ch] files (ie. the
files which are generated from remote_protocol.x by portable-rpcgen).
I'm not suggesting we use these quite yet, because (a) they still
generate some warnings, and (b) they need a lot more testing.
However I think the patch is safe enough.
Rich.
[1] For more about this, see this message and the reply:
https://www.redhat.com/archives/fedora-legal-list/2008-December/msg00022....
[2] LGPLv2+ for the library parts and GPLv2+ for the rpcgen program.
--
Richard Jones, Emerging Technologies, Red Hat http://et.redhat.com/~rjones
virt-p2v converts physical machines to virtual machines. Boot with a
live CD or over the network (PXE) and turn machines into Xen guests.
http://et.redhat.com/~rjones/virt-p2v
15 years, 11 months