diff options
author | kraxel <kraxel> | 2006-07-03 12:00:31 +0000 |
---|---|---|
committer | kraxel <kraxel> | 2006-07-03 12:00:31 +0000 |
commit | 8f4db7fb5130a0b327154eddc62b161fb66af688 (patch) | |
tree | cb43a91e2fdd769e7285c8f7fa76e0a4e83173fb /xenscreen.c | |
parent | a27248c91a6a7a48ce794efc4ed51cc9a6e7172b (diff) | |
download | xenwatch-8f4db7fb5130a0b327154eddc62b161fb66af688.tar.gz |
xen screen management tool
Diffstat (limited to 'xenscreen.c')
-rw-r--r-- | xenscreen.c | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/xenscreen.c b/xenscreen.c new file mode 100644 index 0000000..e091976 --- /dev/null +++ b/xenscreen.c @@ -0,0 +1,273 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <signal.h> +#include <time.h> + +#include <xs.h> + +#include "list.h" +#include "xenstore.h" +#include "apps.h" + +/* ------------------------------------------------------------- */ + +#define BUFSIZE 64 + +struct dom { + int domid; + char name[BUFSIZE]; + char tty[BUFSIZE]; + int connected; + int destroyed; + struct list_head next; +}; +static LIST_HEAD(doms); +static int domcnt; + +//static char *screenrc = "/etc/xen/xenscreenrc"; +static char *screenrc = "/home/kraxel/projects/xenwatch/xenscreenrc"; +static char *screen_session = "xencon"; +static char *screen_title = "watch"; + +/* ------------------------------------------------------------- */ + +static struct dom *find_dom(int domid) +{ + struct dom *dom; + struct list_head *item; + + list_for_each(item, &doms) { + dom = list_entry(item, struct dom, next); + if (dom->domid == domid) + return dom; + } + return NULL; +} + +static struct dom *get_dom(int domid) +{ + struct dom *dom; + + dom = find_dom(domid); + if (!dom) { + dom = malloc(sizeof(*dom)); + memset(dom,0,sizeof(*dom)); + dom->domid = domid; + list_add_tail(&dom->next, &doms); + } + return dom; +} + +/* ------------------------------------------------------------- */ + +static int termsig; + +static void catchsig(int sig) +{ + termsig = sig; +} + +static void try_attach_screen(struct dom *dom) +{ + int rc; + + if (dom->connected) + return; + if (!strlen(dom->name)) + return; + if (!strlen(dom->tty)) + return; + + fprintf(stderr," conn: %s (%d) @ %s\n", + dom->name, dom->domid, dom->tty); + + if (0 != access(dom->tty, R_OK)) { + fprintf(stderr, " error: no access to tty %s\n", dom->tty); + return; + } + + rc = run_application(1, "fuser", "fuser", "-s", dom->tty, NULL); + if (0 == rc) { + fprintf(stderr," error: tty %s already in use\n", dom->tty); + return; + } + + rc = run_application(1, "screen", "screen", + "-X", "-S", screen_session, + "screen", "-t", dom->name, dom->tty, + NULL); + dom->connected = 1; + domcnt++; +} + +static void try_release_domain(struct dom *dom) +{ + if (!dom->destroyed) + return; + fprintf(stderr," gone: %s (%d)%s\n", dom->name, dom->domid, + dom->connected ? " [conn]" : ""); + if (dom->connected) + domcnt--; + list_del(&dom->next); + free(dom); +} + +/* ------------------------------------------------------------- */ + +int main(int argc, char *argv[]) +{ + struct sigaction act,old; + fd_set set; + struct xs_handle *xenstore = NULL; + xs_transaction_t xst; + char **vec = NULL; + int domid; + char path[BUFSIZE], value[BUFSIZE]; + unsigned int count, i, rc; + struct dom *dom; + time_t last_ctrl_c = 0; + + if (!have_application("screen")) { + fprintf(stderr, "screen not installed, exiting\n"); + exit(1); + } + + if (NULL == getenv("STY") || NULL == strstr(getenv("STY"),screen_session)) { + /* not running inside screen, try to attach */ + rc = run_application(1, "screen", "screen", + "-S", screen_session, + "-r", "-p", "=", + NULL); + if (0 == rc) + exit(0); + /* failing that, start a new screen session */ + rc = run_application(1,"screen", "screen", + "-d", "-m", + "-S", screen_session, + "-c", screenrc, + "-t", screen_title, argv[0], + NULL); + execlp("screen", "screen", + "-S", screen_session, + "-r", "-p", "=", + NULL); + perror("execlp(screen)"); + exit(1); + } + + /* setup signal handler */ + memset(&act,0,sizeof(act)); + sigemptyset(&act.sa_mask); + act.sa_handler = catchsig; + sigaction(SIGTERM,&act,&old); + sigaction(SIGINT,&act,&old); + + fprintf(stderr, + "###\n" + "### Xen consoles in screen\n" + "### This is the watch process\n" + "###\n" + "\n"); + + /* connect to xenstore */ + xenstore = xenstore_open(1,1,1,1); + if (NULL == xenstore) { + fprintf(stderr, "can't access xenstore, exiting\n"); + exit(1); + } + xs_watch(xenstore, "/local/domain", "token"); + + /* 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); + + 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_screen(dom); + } + + /* main loop */ + fprintf(stderr,"... done, watching for new ones appear\n"); + for (;;) { + if (termsig) { + if (!domcnt) + break; + if (time(NULL) - last_ctrl_c < 3) + break; + fprintf(stderr,"Still %d domain(s) active - not quitting.\n", domcnt); + fprintf(stderr,"Better try detach instead (Ctrl-A d).\n"); + fprintf(stderr,"Hit Ctrl-C within 3 secs again to quit nevertheless.\n"); + last_ctrl_c = time(NULL); + termsig = 0; + } + + FD_ZERO(&set); + FD_SET(xs_fileno(xenstore), &set); + switch (select(xs_fileno(xenstore)+1, &set, NULL, NULL, NULL)) { + case -1: + if (EINTR == errno) + continue; /* termsig check */ + perror("select"); + break; + case 0: + fprintf(stderr,"Huh, select() timeout?\n"); + exit(1); + break; + 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," boot: %s (%d)\n", dom->name, dom->domid); + + } else { + continue; + + } + + try_attach_screen(dom); + try_release_domain(dom); + } + return 0; +} |