aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkraxel <kraxel>2007-08-07 11:21:07 +0000
committerkraxel <kraxel>2007-08-07 11:21:07 +0000
commit01b527cee6a6446ad5e8fa094ce7c9ff4a0525dc (patch)
tree064e7d87e9af9f0a78904a5ef2e26ea9e0ffa7de
parent06a112c48180fa14a170ce666ed187c485ab2e3c (diff)
downloadxenwatch-01b527cee6a6446ad5e8fa094ce7c9ff4a0525dc.tar.gz
some libvirt bits
-rw-r--r--GNUmakefile28
-rw-r--r--mk/Autoconf.mk9
-rw-r--r--xenscreen.c303
3 files changed, 258 insertions, 82 deletions
diff --git a/GNUmakefile b/GNUmakefile
index fff18b9..79ef2b7 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -8,13 +8,14 @@ CFLAGS += -DVERSION='"$(VERSION)"' -DLIB='"$(LIB)"'
# build
TARGETS := xenlog xenscreen
BUILD_GTK := xenwatch mdns-browser
-BUILD_MDNS := mdns-publish-xendom mdns-publish-vnc
-BUILD_VNC := vnc-client
+BUILD_AVAHI := mdns-publish-xendom mdns-publish-vnc
+BUILD_VNCCLIENT := vnc-client
NEEDS_XENSTORE := xenlog xenscreen xenwatch mdns-publish-xendom mdns-publish-vnc
+NEEDS_LIBVIRT := xenscreen
NEEDS_GTK := xenwatch mdns-browser vnc-client
-NEEDS_MDNS := xenwatch mdns-browser mdns-publish-xendom mdns-publish-vnc
-NEEDS_VNC := xenwatch mdns-browser vnc-client
+NEEDS_AVAHI := xenwatch mdns-browser mdns-publish-xendom mdns-publish-vnc
+NEEDS_VNCCLIENT := xenwatch mdns-browser vnc-client
# default target
all: build
@@ -30,6 +31,7 @@ LIB := $(LIB)
HAVE_GTK := $(call ac_pkg_config,gtk+-x11-2.0)
HAVE_AVAHI := $(call ac_pkg_config,avahi-glib)
HAVE_LIBVIRT := $(call ac_pkg_config,libvirt)
+HAVE_XENSTORE := $(call ac_lib,xs_daemon_open,xenstore)
HAVE_VNCCLIENT := $(call ac_lib,rfbGetClient,vncclient,-lz -ljpeg)
HAVE_VNC_TEXT := $(call ac_lib,TextChatSend,vncclient,-lz -ljpeg)
endef
@@ -41,20 +43,26 @@ ifeq ($(HAVE_GTK),yes)
$(NEEDS_GTK) : pkglst += gtk+-x11-2.0
TARGETS += $(BUILD_GTK)
ifeq ($(HAVE_VNCCLIENT),yes)
- TARGETS += $(BUILD_VNC)
- $(NEEDS_VNC) : LDLIBS += -lvncclient -lz -ljpeg -lGL
+ TARGETS += $(BUILD_VNCCLIENT)
+ $(NEEDS_VNCCLIENT) : LDLIBS += -lvncclient -lz -ljpeg -lGL
endif
endif
# avahi stuff
ifeq ($(HAVE_AVAHI),yes)
- $(NEEDS_MDNS) : pkglst += avahi-client
- $(NEEDS_GTK) : pkglst += avahi-glib
- TARGETS += $(BUILD_MDNS)
+ $(NEEDS_AVAHI) : pkglst += avahi-client
+ $(NEEDS_GTK) : pkglst += avahi-glib
+ TARGETS += $(BUILD_AVAHI)
+endif
+
+# libvirt stuff
+ifeq ($(HAVE_LIBVIRT),yes)
+ $(NEEDS_LIBVIRT) : pkglst += libvirt libxml-2.0
+ TARGETS += $(BUILD_LIBVIRT)
endif
# compile flags
-CFLAGS += $(call ac_inc_cflags,AVAHI VNCCLIENT VNC_TEXT)
+CFLAGS += $(call ac_inc_cflags,XENSTORE LIBVIRT AVAHI VNCCLIENT VNC_TEXT)
CFLAGS += $(shell test "$(pkglst)" != "" && pkg-config --cflags $(pkglst))
LDLIBS += $(shell test "$(pkglst)" != "" && pkg-config --libs $(pkglst))
diff --git a/mk/Autoconf.mk b/mk/Autoconf.mk
index aea4900..65cd915 100644
--- a/mk/Autoconf.mk
+++ b/mk/Autoconf.mk
@@ -106,8 +106,13 @@ ac_lib64 = $(shell \
# check for x11 ressource dir prefix
ac_resdir = $(shell \
$(call ac_init,for X11 app-defaults prefix);\
- $(call ac_s_cmd, test -d /etc/X11/app-defaults &&\
- echo "/etc/X11" || echo "/usr/X11R6/lib/X11");\
+ $(call ac_s_cmd, for dir in \
+ /etc/X11/app-defaults \
+ /usr/X11R6/lib/X11/app-defaults \
+ /usr/share/X11/app-defaults \
+ /usr/lib/X11/app-defaults \
+ ; do test -d "$$dir" || continue;\
+ dirname "$$dir"; break; done);\
$(call ac_fini))
# check if package is installed, via pkg-config
diff --git a/xenscreen.c b/xenscreen.c
index 1aeea52..c7f0ddf 100644
--- a/xenscreen.c
+++ b/xenscreen.c
@@ -7,7 +7,15 @@
#include <time.h>
#include <sys/utsname.h>
-#include <xs.h>
+#ifdef HAVE_LIBVIRT
+# include <libvirt/libvirt.h>
+# include <libxml/parser.h>
+# include <libxml/tree.h>
+# include <libxml/xpath.h>
+#endif
+#ifdef HAVE_XENSTORE
+# include <xs.h>
+#endif
#include "list.h"
#include "xenstore.h"
@@ -218,6 +226,159 @@ static void builtin_screen_setup(void)
}
/* ------------------------------------------------------------- */
+/* libvirt bits */
+
+#ifdef HAVE_LIBVIRT
+
+static int
+libvirt_xml_xpath_str(const char *doc, char *xpath, char *dest, int len)
+{
+ xmlDocPtr xml = NULL;
+ xmlXPathObjectPtr obj = NULL;
+ xmlXPathContextPtr ctxt = NULL;
+ int ret = -1;
+
+ xml = xmlReadDoc((const xmlChar *) doc, "domain.xml", NULL,
+ XML_PARSE_NOENT | XML_PARSE_NONET |
+ XML_PARSE_NOWARNING);
+ if (!xml)
+ goto cleanup;
+ ctxt = xmlXPathNewContext(xml);
+ if (!ctxt)
+ goto cleanup;
+
+ obj = xmlXPathEval(BAD_CAST xpath, ctxt);
+ if ((obj == NULL) || (obj->type != XPATH_STRING) ||
+ (obj->stringval == NULL) || (obj->stringval[0] == 0)) {
+ goto cleanup;
+ }
+ snprintf(dest, len, "%s", obj->stringval);
+ ret = 0;
+
+ cleanup:
+ if (obj)
+ xmlXPathFreeObject(obj);
+ if (ctxt)
+ xmlXPathFreeContext(ctxt);
+ if (xml)
+ xmlFreeDoc(xml);
+ return ret;
+}
+
+static void libvirt_scan(virConnectPtr conn)
+{
+ int i, count, *ids;
+ virDomainPtr vdom;
+ struct dom *dom;
+ const char *name, *xml;
+
+ count = virConnectNumOfDomains(conn) + 4;
+ ids = malloc(count * sizeof(int));
+ count = virConnectListDomains(conn, ids, count);
+ for (i = 0; i < count; i++) {
+ vdom = virDomainLookupByID(conn, ids[i]);
+ name = virDomainGetName(vdom);
+ xml = virDomainGetXMLDesc(vdom, 0);
+ if (!name || !xml)
+ continue;
+ dom = get_dom(ids[i]);
+ snprintf(dom->name, sizeof(dom->name), "%s", name);
+ libvirt_xml_xpath_str(xml, "string(/domain/devices/console/@tty)",
+ dom->tty, sizeof(dom->tty));
+ fprintf(stderr, "%s: tty=\"%s\"\n", dom->name, dom->tty);
+ try_attach_domain(dom, 1);
+ }
+ free(ids);
+}
+#endif
+
+/* ------------------------------------------------------------- */
+/* xenstore bits */
+
+#ifdef HAVE_XENSTORE
+static void xenstore_scan(struct xs_handle *xenstore)
+{
+ xs_transaction_t xst;
+ char **vec = NULL;
+ int domid;
+ unsigned int count, i;
+ char path[BUFSIZE];
+ struct dom *dom;
+
+ /* look for running domains */
+ if (!(xst = xs_transaction_start(xenstore))) {
+ fprintf(stderr,"Oops, can't start xenstore transaction\n");
+ exit(1);
+ }
+ vec = xs_directory(xenstore, xst, "/local/domain", &count);
+ xs_transaction_end(xenstore, xst, 0);
+
+ for (i = 0; i < count; i++) {
+ domid = atoi(vec[i]);
+ dom = get_dom(domid);
+ snprintf(path, sizeof(path), "/local/domain/%d/name", domid);
+ xenstore_read(xenstore, path, dom->name, sizeof(dom->name));
+ snprintf(path, sizeof(path), "/local/domain/%d/console/tty", domid);
+ xenstore_read(xenstore, path, dom->tty, sizeof(dom->tty));
+ try_attach_domain(dom, 1);
+ }
+ if (vec)
+ free(vec);
+}
+
+static void xenstore_update(struct xs_handle *xenstore)
+{
+ char **vec = NULL;
+ int domid;
+ unsigned int count, rc;
+ char path[BUFSIZE], value[BUFSIZE];
+ struct dom *dom;
+
+ vec = xs_read_watch(xenstore, &count);
+ if (NULL == vec) {
+ fprintf(stderr,"xs_read_watch() failed\n");
+ exit(1);
+ }
+ if (2 != sscanf(vec[XS_WATCH_PATH], "/local/domain/%d/%64s", &domid, path)) {
+ if (1 != sscanf(vec[XS_WATCH_PATH], "/local/domain/%d", &domid))
+ goto cleanup;
+ strcpy(path, "");
+ }
+ dom = get_dom(domid);
+
+ if (0 == strcmp(path,"")) {
+ rc = xenstore_read(xenstore, vec[XS_WATCH_PATH], value, sizeof(value));
+ if (0 != rc)
+ dom->destroyed = 1;
+
+ } else if (0 == strcmp(path, "console/tty")) {
+ rc = xenstore_read(xenstore, vec[XS_WATCH_PATH], value, sizeof(value));
+ if (0 != rc)
+ goto cleanup;
+ strcpy(dom->tty, value);
+
+ } else if (0 == strcmp(path, "name")) {
+ rc = xenstore_read(xenstore, vec[XS_WATCH_PATH], value, sizeof(value));
+ if (0 != rc)
+ goto cleanup;
+ strcpy(dom->name, value);
+ fprintf(stderr, PRE_STATE "%s (%d)\n", "new domain", dom->name, dom->domid);
+
+ } else {
+ goto cleanup;
+
+ }
+
+ try_attach_domain(dom, 0);
+ try_release_domain(dom);
+
+cleanup:
+ if (vec)
+ free(vec);
+}
+#endif
+
+/* ------------------------------------------------------------- */
static void usage(FILE *fp)
{
@@ -236,7 +397,7 @@ static void usage(FILE *fp)
" -p window preselect screen window\n"
"\n"
"-- \n"
- "(c) 2006 Gerd Hoffmann <kraxel@suse.de>\n",
+ "(c) 2006,07 Gerd Hoffmann <kraxel@redhat.com>\n",
screen_rc, screen_session);
}
@@ -244,17 +405,27 @@ int main(int argc, char *argv[])
{
struct sigaction act,old;
struct utsname uts;
+ int maxfd;
fd_set set;
- struct xs_handle *xenstore = NULL;
- xs_transaction_t xst;
- char **vec = NULL, *window = NULL;
- int domid, nac, c;
- char path[BUFSIZE], value[BUFSIZE];
- unsigned int count, i, rc;
- struct dom *dom;
+ char *window = NULL;
+ int nac, c;
+ unsigned int rc, i;
time_t last_ctrl_c = 0;
char **nav;
+#ifdef HAVE_LIBVIRT
+ char *vir_url = getenv("VIRSH_DEFAULT_CONNECT_URI");
+ virConnectPtr vir_conn = NULL;
+#else
+ void *vir_conn = NULL;
+#endif
+
+#ifdef HAVE_XENSTORE
+ struct xs_handle *xenstore = NULL;
+#else
+ void *xenstore = NULL;
+#endif
+
for (;;) {
if (-1 == (c = getopt(argc, argv, "hdbLzc:S:u:p:")))
break;
@@ -304,6 +475,9 @@ int main(int argc, char *argv[])
memset(&uts, 0, sizeof(uts));
if (0 == uname(&uts)) {
+ char *h;
+ if (NULL != (h = strstr(uts.nodename, ".")))
+ *h = 0;
screen_title = malloc(strlen(uts.nodename) +4);
sprintf(screen_title, "[%s]", uts.nodename);
}
@@ -373,32 +547,46 @@ int main(int argc, char *argv[])
if (screen_shell)
screen_command("screen", "-t", "[shell]", "/bin/bash", NULL);
- /* connect to xenstore */
- xenstore = xenstore_open(1,1,1,1);
- if (NULL == xenstore) {
- fprintf(stderr, "can't access xenstore, exiting\n");
- exit(1);
+#ifdef HAVE_LIBVIRT
+ if (vir_url) {
+ fprintf(stderr, "trying libvirt (%s) ...\n", vir_url);
+ vir_conn = virConnectOpenReadOnly(vir_url);
+ if (vir_conn)
+ fprintf(stderr, "using libvirt\n");
+ else
+ fprintf(stderr, "libvirt: can't connect\n");
}
- xs_watch(xenstore, "/local/domain", "token");
+#endif
- /* look for running domains */
- if (!(xst = xs_transaction_start(xenstore))) {
- fprintf(stderr,"Oops, can't start xenstore transaction\n");
+#ifdef HAVE_XENSTORE
+ if (!vir_conn) {
+ /* connect to xenstore */
+ fprintf(stderr, "trying xenstore ...\n");
+ xenstore = xenstore_open(1,1,1,1);
+ if (xenstore) {
+ fprintf(stderr, "using xenstore\n");
+ xs_watch(xenstore, "/local/domain", "token");
+ } else
+ fprintf(stderr, "xenstore: can't connect\n");
+ }
+#endif
+
+ if (!vir_conn && !xenstore) {
+ fprintf(stderr, "Failed to establish VM management connection.\n");
+ fprintf(stderr, "Exiting in 10 seconds ...\n");
+ sleep(10); /* give the user the chance to see the error */
exit(1);
}
- vec = xs_directory(xenstore, xst, "/local/domain", &count);
- xs_transaction_end(xenstore, xst, 0);
fprintf(stderr,"looking for existing domains\n");
- for (i = 0; i < count; i++) {
- domid = atoi(vec[i]);
- dom = get_dom(domid);
- snprintf(path, sizeof(path), "/local/domain/%d/name", domid);
- xenstore_read(xenstore, path, dom->name, sizeof(dom->name));
- snprintf(path, sizeof(path), "/local/domain/%d/console/tty", domid);
- xenstore_read(xenstore, path, dom->tty, sizeof(dom->tty));
- try_attach_domain(dom, 1);
- }
+#ifdef HAVE_LIBVIRT
+ if (vir_conn)
+ libvirt_scan(vir_conn);
+#endif
+#ifdef HAVE_XENSTORE
+ if (xenstore)
+ xenstore_scan(xenstore);
+#endif
/* main loop */
fprintf(stderr,"ok, watching out for changes now\n");
@@ -424,8 +612,18 @@ int main(int argc, char *argv[])
}
FD_ZERO(&set);
- FD_SET(xs_fileno(xenstore), &set);
- switch (select(xs_fileno(xenstore)+1, &set, NULL, NULL, NULL)) {
+ maxfd = 0;
+
+#ifdef HAVE_XENSTORE
+ if (xenstore) {
+ int fd = xs_fileno(xenstore);
+ FD_SET(fd, &set);
+ if (maxfd < fd)
+ maxfd = fd;
+ }
+#endif
+
+ switch (select(maxfd+1, &set, NULL, NULL, NULL)) {
case -1:
if (EINTR == errno)
continue; /* termsig check */
@@ -438,46 +636,11 @@ int main(int argc, char *argv[])
default:
break;
}
-
- if (vec)
- free(vec);
- vec = xs_read_watch(xenstore, &count);
- if (NULL == vec) {
- fprintf(stderr,"xs_read_watch() failed\n");
- exit(1);
- }
- if (2 != sscanf(vec[XS_WATCH_PATH], "/local/domain/%d/%64s", &domid, path)) {
- if (1 != sscanf(vec[XS_WATCH_PATH], "/local/domain/%d", &domid))
- continue;
- strcpy(path, "");
- }
- dom = get_dom(domid);
-
- if (0 == strcmp(path,"")) {
- rc = xenstore_read(xenstore, vec[XS_WATCH_PATH], value, sizeof(value));
- if (0 != rc)
- dom->destroyed = 1;
-
- } else if (0 == strcmp(path, "console/tty")) {
- rc = xenstore_read(xenstore, vec[XS_WATCH_PATH], value, sizeof(value));
- if (0 != rc)
- continue;
- strcpy(dom->tty, value);
-
- } else if (0 == strcmp(path, "name")) {
- rc = xenstore_read(xenstore, vec[XS_WATCH_PATH], value, sizeof(value));
- if (0 != rc)
- continue;
- strcpy(dom->name, value);
- fprintf(stderr, PRE_STATE "%s (%d)\n", "new domain", dom->name, dom->domid);
- } else {
- continue;
-
- }
-
- try_attach_domain(dom, 0);
- try_release_domain(dom);
+#ifdef HAVE_XENSTORE
+ if (xenstore && FD_ISSET(xs_fileno(xenstore), &set))
+ xenstore_update(xenstore);
+#endif
}
if (screen_unlink)