From 01b527cee6a6446ad5e8fa094ce7c9ff4a0525dc Mon Sep 17 00:00:00 2001 From: kraxel Date: Tue, 7 Aug 2007 11:21:07 +0000 Subject: some libvirt bits --- xenscreen.c | 303 ++++++++++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 233 insertions(+), 70 deletions(-) (limited to 'xenscreen.c') diff --git a/xenscreen.c b/xenscreen.c index 1aeea52..c7f0ddf 100644 --- a/xenscreen.c +++ b/xenscreen.c @@ -7,7 +7,15 @@ #include #include -#include +#ifdef HAVE_LIBVIRT +# include +# include +# include +# include +#endif +#ifdef HAVE_XENSTORE +# include +#endif #include "list.h" #include "xenstore.h" @@ -217,6 +225,159 @@ static void builtin_screen_setup(void) return; } +/* ------------------------------------------------------------- */ +/* 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 \n", + "(c) 2006,07 Gerd Hoffmann \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) -- cgit