diff options
author | kraxel <kraxel> | 2007-08-07 11:21:07 +0000 |
---|---|---|
committer | kraxel <kraxel> | 2007-08-07 11:21:07 +0000 |
commit | 01b527cee6a6446ad5e8fa094ce7c9ff4a0525dc (patch) | |
tree | 064e7d87e9af9f0a78904a5ef2e26ea9e0ffa7de | |
parent | 06a112c48180fa14a170ce666ed187c485ab2e3c (diff) | |
download | xenwatch-01b527cee6a6446ad5e8fa094ce7c9ff4a0525dc.tar.gz |
some libvirt bits
-rw-r--r-- | GNUmakefile | 28 | ||||
-rw-r--r-- | mk/Autoconf.mk | 9 | ||||
-rw-r--r-- | xenscreen.c | 303 |
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) |