static int get_pty_fd(struct xs_handle *xs, char *path, int seconds) /* Check for a pty in xenstore, open it and return its fd. * Assumes there is already a watch set in the store for this path. */ { struct timeval tv; fd_set watch_fdset; int xs_fd = xs_fileno(xs), pty_fd = -1; int start, now; unsigned int len = 0; char *pty_path, **watch_paths;; start = now = time(NULL); do { tv.tv_usec = 0; tv.tv_sec = (start + seconds) - now; FD_ZERO(&watch_fdset); FD_SET(xs_fd, &watch_fdset); if (select(xs_fd + 1, &watch_fdset, NULL, NULL, &tv)) { /* Read the watch to drain the buffer */ watch_paths = xs_read_watch(xs, &len); free(watch_paths); /* We only watch for one thing, so no need to * disambiguate: just read the pty path */ pty_path = xs_read(xs, XBT_NULL, path, &len); if (pty_path != NULL) { pty_fd = open(pty_path, O_RDWR | O_NOCTTY); if (pty_fd == -1) err(errno, "Could not open tty `%s'", pty_path); free(pty_path); } } } while (pty_fd == -1 && (now = time(NULL)) < start + seconds); return pty_fd; }
/* Helper to determine if a frontend device is in Connected state */ static int xenfb_frontend_connected(struct xenfb_device *dev) { unsigned int state; unsigned int dummy; char **vec; vec = xs_read_watch(dev->xenfb->xsh, &dummy); if (!vec) return -1; free(vec); state = xenfb_read_state(dev->xenfb->xsh, dev->otherend); if (!((1 <<state) & ((1 << XenbusStateUnknown) | (1 << XenbusStateConnected)))) { fprintf(stderr, "FB: Carry on waiting\n"); return 1; } /* Don't unwatch frontend - we need to detect shutdown */ /*xs_unwatch(dev->xenfb->xsh, dev->otherend, "");*/ switch (state) { case XenbusStateConnected: break; default: return -1; } return 0; }
static int get_pty_fd(struct xs_handle *xs, char *path, int seconds) /* Check for a pty in xenstore, open it and return its fd. * Assumes there is already a watch set in the store for this path. */ { struct timeval tv; fd_set watch_fdset; int xs_fd = xs_fileno(xs), pty_fd = -1; int start, now; unsigned int len = 0; char *pty_path, **watch_paths; start = now = time(NULL); do { tv.tv_usec = 0; tv.tv_sec = (start + seconds) - now; FD_ZERO(&watch_fdset); FD_SET(xs_fd, &watch_fdset); if (select(xs_fd + 1, &watch_fdset, NULL, NULL, &tv)) { /* Read the watch to drain the buffer */ watch_paths = xs_read_watch(xs, &len); free(watch_paths); /* We only watch for one thing, so no need to * disambiguate: just read the pty path */ pty_path = xs_read(xs, XBT_NULL, path, &len); if (pty_path != NULL) { if (access(pty_path, R_OK|W_OK) != 0) continue; pty_fd = open(pty_path, O_RDWR | O_NOCTTY); if (pty_fd == -1) err(errno, "Could not open tty `%s'", pty_path); free(pty_path); } } } while (pty_fd == -1 && (now = time(NULL)) < start + seconds); #ifdef __sun__ if (pty_fd != -1) { struct termios term; /* * 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(pty_fd, &term) < 0) { ioctl(pty_fd, I_PUSH, "ptem"); ioctl(pty_fd, I_PUSH, "ldterm"); } } #endif return pty_fd; }
/* * Called when a watched value in xenstore has been changed */ static void handle_xs_watch(void) { char *path, *token, **vec; unsigned int k, num; vec = xs_read_watch(xs, &num); if (vec == NULL) { /* we currently watch only for one thing, so check it anyway */ update_membalance_settings(); return; } for (k = 0; k < num; k += 2) { path = vec[k + XS_WATCH_PATH]; token = vec[k + XS_WATCH_TOKEN]; if (0 == strcmp(path, membalance_interval_path)) update_membalance_settings(); } free(vec); }
/* Get qemu to change buffers. */ static void qemu_flip_buffer(int domid, int next_active) { char digit = '0' + next_active; unsigned int len; char *active_str, **watch; struct timeval tv; fd_set fdset; /* Tell qemu that we want it to start writing log-dirty bits to the * other buffer */ if (!xs_write(xs, XBT_NULL, qemu_next_active_path, &digit, 1)) errx(1, "can't write next-active to store path (%s)\n", qemu_next_active_path); /* Wait a while for qemu to signal that it has switched to the new * active buffer */ read_again: tv.tv_sec = 5; tv.tv_usec = 0; FD_ZERO(&fdset); FD_SET(xs_fileno(xs), &fdset); if ((select(xs_fileno(xs) + 1, &fdset, NULL, NULL, &tv)) != 1) errx(1, "timed out waiting for qemu to switch buffers\n"); watch = xs_read_watch(xs, &len); free(watch); active_str = xs_read(xs, XBT_NULL, qemu_active_path, &len); if (active_str == NULL || active_str[0] - '0' != next_active) /* Watch fired but value is not yet right */ goto read_again; }
/* adapted from the eponymous function in xc_save */ static int switch_qemu_logdirty(checkpoint_state *s, int enable) { char path[128]; char *tail, *cmd, *response; char **vec; unsigned int len; sprintf(path, "/local/domain/0/device-model/%u/logdirty/", s->domid); tail = path + strlen(path); strcpy(tail, "ret"); if (!xs_watch(s->xsh, path, "qemu-logdirty-ret")) { s->errstr = "error watching qemu logdirty return"; return -1; } /* null fire. XXX unify with shutdown watch! */ vec = xs_read_watch(s->xsh, &len); free(vec); strcpy(tail, "cmd"); cmd = enable ? "enable" : "disable"; if (!xs_write(s->xsh, XBT_NULL, path, cmd, strlen(cmd))) { s->errstr = "error signalling qemu logdirty"; return -1; } vec = xs_read_watch(s->xsh, &len); free(vec); strcpy(tail, "ret"); xs_unwatch(s->xsh, path, "qemu-logdirty-ret"); response = xs_read(s->xsh, XBT_NULL, path, &len); if (!len || strcmp(response, cmd)) { if (len) free(response); s->errstr = "qemu logdirty command failed"; return -1; } free(response); fprintf(stderr, "qemu logdirty mode: %s\n", cmd); return 0; }
static int wait_for_backend_state_change() { char keybuf[128]; int my_domid; unsigned int len; int backend_state; int seconds; char *buf, **vec; int ret; int xs_fd; struct timeval tv; fd_set watch_fdset; int start, now; backend_state = STATE_UNDEFINED; xs_fd = xs_fileno(xsh); start = now = time(NULL); my_domid = atoi(xs_read(xsh, 0, "domid", &len)); snprintf(keybuf, sizeof(keybuf), "/local/domain/0/backend/audio/%d/%d/state", my_domid, device_id); /*XXX: hardcoded */ seconds = 10; do { tv.tv_usec = 0; tv.tv_sec = (start + seconds) - now; FD_ZERO(&watch_fdset); FD_SET(xs_fd, &watch_fdset); ret=select(xs_fd + 1, &watch_fdset, NULL, NULL, &tv); if (ret==-1) /* error */ return -1; else if (ret) { /* Read the watch to drain the buffer */ vec = xs_read_watch(xsh, &len); buf = xs_read(xsh, XBT_NULL, vec[0], &len); if (buf == 0) { /* usually means that the backend isn't there yet */ continue; }; backend_state = atoi(buf); free(buf); free(vec); } /* else: timeout */ } while (backend_state == STATE_UNDEFINED && \ (now = time(NULL)) < start + seconds); return backend_state; }
char * control_handle_event(struct xs_handle *h) { unsigned int num; char **res, *path; res = xs_read_watch(h, &num); if (!res) return NULL; return res[XS_WATCH_PATH]; }
main(int argc, char **argv) { struct xs_handle *xs; unsigned int count; char **vec; char dummy; if (argc != 2) { fprintf(stderr, "usage: %s xenstore_path\n", argv[0]); exit(1); } xs = xs_domain_open(); if (!xs) { perror("xs_domain_open"); exit(1); } if (!xs_watch(xs, argv[1], &dummy)) { perror("xs_watch"); exit(1); } vec = xs_read_watch(xs, &count); free(vec); vec = xs_read_watch(xs, &count); free(vec); }
/* Helper to determine if a backend device is in Created state */ static int xenfb_backend_created(struct xenfb_device *dev) { unsigned int state; unsigned int dummy; char **vec; vec = xs_read_watch(dev->xenfb->xsh, &dummy); if (!vec) return -1; free(vec); state = xenfb_read_state(dev->xenfb->xsh, dev->nodename); if (!((1 <<state) & ((1 << XenbusStateUnknown) | (1 << XenbusStateInitialising) | (1 << XenbusStateClosed) #if 1 /* TODO fudging state to permit restarting; to be removed */ | (1 << XenbusStateInitWait) | (1 << XenbusStateConnected) | (1 << XenbusStateClosing) #endif ))) { fprintf(stderr, "FB: Carry on waiting\n"); return 1; } xs_unwatch(dev->xenfb->xsh, dev->nodename, ""); switch (state) { #if 1 case XenbusStateInitWait: case XenbusStateConnected: printf("Fudging state to %d\n", XenbusStateInitialising); /* FIXME */ #endif case XenbusStateInitialising: case XenbusStateClosing: case XenbusStateClosed: break; default: fprintf(stderr, "Wrong state %d\n", state); return -1; } xenfb_switch_state(dev, XenbusStateInitWait); if (xenfb_hotplug(dev) < 0) return -1; return 0; }
/* returns -1 on error or death, 0 if domain is running, 1 if suspended */ static int check_shutdown(checkpoint_state* s) { unsigned int count; int xsfd; char **vec; char buf[16]; xc_dominfo_t info; xsfd = xs_fileno(s->xsh); /* loop on watch if it fires for another domain */ while (1) { if (pollfd(s, xsfd) < 0) return -1; vec = xs_read_watch(s->xsh, &count); if (s->watching_shutdown == 1) { s->watching_shutdown = 2; return 0; } if (!vec) { fprintf(stderr, "empty watch fired\n"); continue; } snprintf(buf, sizeof(buf), "%d", s->domid); if (!strcmp(vec[XS_WATCH_TOKEN], buf)) break; } if (xc_domain_getinfo(s->xch, s->domid, 1, &info) != 1 || info.domid != s->domid) { snprintf(errbuf, sizeof(errbuf), "error getting info for domain %u", s->domid); s->errstr = errbuf; return -1; } if (!info.shutdown) { snprintf(errbuf, sizeof(errbuf), "domain %u not shut down", s->domid); s->errstr = errbuf; return 0; } if (info.shutdown_reason != SHUTDOWN_suspend) return -1; return 1; }
/* Process ongoing events from the frontend devices */ static void xenfb_dispatch_store(void *opaque) { struct xenfb *xenfb = (struct xenfb *)opaque; unsigned dummy; char **vec; int r; vec = xs_read_watch(xenfb->xsh, &dummy); free(vec); r = xenfb_on_state_change(&xenfb->fb); if (r == 0) r = xenfb_on_state_change(&xenfb->kbd); if (r < 0) { xenfb_shutdown(xenfb); exit(1); } }
static void do_watch(struct xs_handle *xsh, int max_events) { int count = 0; char **vec = NULL; for ( count = 0; max_events == -1 || count < max_events; count++ ) { unsigned int num; vec = xs_read_watch(xsh, &num); if (vec == NULL) continue; printf("%s\n", vec[XS_WATCH_PATH]); fflush(stdout); free(vec); } }
/* Helper to determine if a frontend device is in Initialized state */ static int xenfb_frontend_initialized(struct xenfb_device *dev) { unsigned int state; unsigned int dummy; char **vec; vec = xs_read_watch(dev->xenfb->xsh, &dummy); if (!vec) return -1; free(vec); state = xenfb_read_state(dev->xenfb->xsh, dev->otherend); if (!((1 << state) & ((1 << XenbusStateUnknown) | (1 << XenbusStateInitialised) #if 1 /* TODO fudging state to permit restarting; to be removed */ | (1 << XenbusStateConnected) #endif ))) { fprintf(stderr, "FB: Carry on waiting\n"); return 1; } xs_unwatch(dev->xenfb->xsh, dev->otherend, ""); switch (state) { #if 1 case XenbusStateConnected: printf("Fudging state to %d\n", XenbusStateInitialised); /* FIXME */ #endif case XenbusStateInitialised: break; default: return -1; } if (xenfb_bind(dev) < 0) return -1; return 0; }
static void xenStoreWatchEvent(int watch ATTRIBUTE_UNUSED, int fd ATTRIBUTE_UNUSED, int events, void *data) { char **event; char *path; char *token; unsigned int stringCount; xenStoreWatchPtr sw; virConnectPtr conn = data; xenUnifiedPrivatePtr priv = conn->privateData; if (!priv) return; /* only set a watch on read and write events */ if (events & (VIR_EVENT_HANDLE_ERROR | VIR_EVENT_HANDLE_HANGUP)) return; xenUnifiedLock(priv); if (!priv->xshandle) goto cleanup; event = xs_read_watch(priv->xshandle, &stringCount); if (!event) goto cleanup; path = event[XS_WATCH_PATH]; token = event[XS_WATCH_TOKEN]; sw = xenStoreFindWatch(priv->xsWatchList, path, token); if (sw) sw->cb(conn, path, token, sw->opaque); VIR_FREE(event); cleanup: xenUnifiedUnlock(priv); }
void xenstore_process_event(void *opaque) { char **vec, *offset, *bpath = NULL, *buf = NULL, *drv = NULL, *image = NULL; unsigned int len, num, hd_index; vec = xs_read_watch(xsh, &num); if (!vec) return; if (!strcmp(vec[XS_WATCH_TOKEN], "logdirty")) { xenstore_process_logdirty_event(); goto out; } if (!strcmp(vec[XS_WATCH_TOKEN], "dm-command")) { xenstore_process_dm_command_event(); goto out; } if (strncmp(vec[XS_WATCH_TOKEN], "hd", 2) || strlen(vec[XS_WATCH_TOKEN]) != 3) goto out; hd_index = vec[XS_WATCH_TOKEN][2] - 'a'; image = xs_read(xsh, XBT_NULL, vec[XS_WATCH_PATH], &len); if (image == NULL) goto out; /* gone */ /* Strip off blktap sub-type prefix */ bpath = strdup(vec[XS_WATCH_PATH]); if (bpath == NULL) goto out; if ((offset = strrchr(bpath, '/')) != NULL) *offset = '\0'; if (pasprintf(&buf, "%s/type", bpath) == -1) goto out; drv = xs_read(xsh, XBT_NULL, buf, &len); if (drv && !strcmp(drv, "tap") && ((offset = strchr(image, ':')) != NULL)) memmove(image, offset+1, strlen(offset+1)+1); if (!strcmp(image, bs_table[hd_index]->filename)) goto out; /* identical */ do_eject(0, vec[XS_WATCH_TOKEN]); bs_table[hd_index]->filename[0] = 0; if (media_filename[hd_index]) { free(media_filename[hd_index]); media_filename[hd_index] = NULL; } if (image[0]) { media_filename[hd_index] = strdup(image); xenstore_check_new_media_present(5000); } out: free(drv); free(buf); free(bpath); free(image); free(vec); }
static int xenpaging_wait_for_event_or_timeout(struct xenpaging *paging) { xc_interface *xch = paging->xc_handle; xc_evtchn *xce = paging->vm_event.xce_handle; char **vec, *val; unsigned int num; struct pollfd fd[2]; int port; int rc; int timeout; /* Wait for event channel and xenstore */ fd[0].fd = xc_evtchn_fd(xce); fd[0].events = POLLIN | POLLERR; fd[1].fd = xs_fileno(paging->xs_handle); fd[1].events = POLLIN | POLLERR; /* No timeout while page-out is still in progress */ timeout = paging->use_poll_timeout ? 100 : 0; rc = poll(fd, 2, timeout); if ( rc < 0 ) { if (errno == EINTR) return 0; PERROR("Poll exited with an error"); return -1; } /* First check for guest shutdown */ if ( rc && fd[1].revents & POLLIN ) { DPRINTF("Got event from xenstore\n"); vec = xs_read_watch(paging->xs_handle, &num); if ( vec ) { DPRINTF("path '%s' token '%s'\n", vec[XS_WATCH_PATH], vec[XS_WATCH_TOKEN]); if ( strcmp(vec[XS_WATCH_TOKEN], watch_token) == 0 ) { /* If our guest disappeared, set interrupt flag and fall through */ if ( xs_is_domain_introduced(paging->xs_handle, paging->vm_event.domain_id) == false ) { xs_unwatch(paging->xs_handle, "@releaseDomain", watch_token); interrupted = SIGQUIT; /* No further poll result processing */ rc = 0; } } else if ( strcmp(vec[XS_WATCH_PATH], watch_target_tot_pages) == 0 ) { int ret, target_tot_pages; val = xs_read(paging->xs_handle, XBT_NULL, vec[XS_WATCH_PATH], NULL); if ( val ) { ret = sscanf(val, "%d", &target_tot_pages); if ( ret > 0 ) { /* KiB to pages */ target_tot_pages >>= 2; if ( target_tot_pages < 0 || target_tot_pages > paging->max_pages ) target_tot_pages = paging->max_pages; paging->target_tot_pages = target_tot_pages; /* Disable poll() delay while new target is not yet reached */ paging->use_poll_timeout = 0; DPRINTF("new target_tot_pages %d\n", target_tot_pages); } free(val); } }
int main (int argc, char **argv) { int i; struct xs_handle *xs; xs_transaction_t th; char *path; int fd; fd_set set; int er; char **vec; unsigned int num_strings; char * buf; unsigned int len; char *program; char **arguments; int arguments_count; pid_t pid; int j; char *last_value = NULL; int status; program_name = argv[0]; i = decode_switches (argc, argv); if (argc - i < 1) usage(1); path = argv[i++]; if (argc - i > 0) { program = argv[i++]; arguments_count = argc - i; arguments = malloc(sizeof(char*) * (argc - i + 2)); arguments[0] = program; for (j=0; j<arguments_count; j++) arguments[j + 1] = argv[i + j]; arguments[j + 1] = NULL; } else { program = NULL; arguments = NULL; arguments_count = 0; } if (want_verbose) { printf("Path: %s\n", path); if (program) { printf("Program: %s", program); for (i=1; i<arguments_count + 1; i++) printf(" %s", arguments[i]); printf("\n"); } } /* Get a connection to the daemon */ xs = xs_daemon_open(); if ( xs == NULL ) xs = xs_domain_open(); if ( xs == NULL ) { error("Unable to connect to XenStore"); exit(1); } /* Create a watch on /local/domain/0/mynode. */ er = xs_watch(xs, path, "token"); if ( er == 0 ) { error("Unable to create watch"); exit(1); } /* We are notified of read availability on the watch via the * file descriptor. */ fd = xs_fileno(xs); while (1) { FD_ZERO(&set); FD_SET(fd, &set); /* Poll for data. */ if ( select(fd + 1, &set, NULL, NULL, NULL) > 0 && FD_ISSET(fd, &set)) { /* num_strings will be set to the number of elements in vec * (typically, 2 - the watched path and the token) */ vec = xs_read_watch(xs, &num_strings); if ( !vec ) { error("Unable to read watch"); continue; } if (want_verbose) printf("Path changed: %s\n", vec[XS_WATCH_PATH]); /* Prepare a transaction and do a read. */ th = xs_transaction_start(xs); buf = xs_read(xs, th, vec[XS_WATCH_PATH], &len); xs_transaction_end(xs, th, false); if (buf) { if (last_value && strcmp(buf, last_value) == 0) { if (want_verbose) printf("Value did not change\n"); continue; } if (want_verbose) printf("New value: %s\n", buf); if (program) { pid = fork(); if (pid == 0) { setenv("XENSTORE_WATCH_PATH", vec[XS_WATCH_PATH], 1); setenv("XENSTORE_WATCH_VALUE", buf, 1); for (i=0; arguments[i]; i++) { if (strcmp(arguments[i], "%v") == 0) arguments[i] = buf; else if (strcmp(arguments[i], "%p") == 0) arguments[i] = vec[XS_WATCH_PATH]; } execvp(program, arguments); error("Unable to start program"); exit(1); } else { waitpid(pid, &status, 0); } } else { if (!want_verbose) printf("%s\n", buf); } if (last_value) free(last_value); last_value = buf; } } } /* Cleanup */ close(fd); xs_daemon_close(xs); free(path); exit(0); }
libvchan_t *libvchan_client_init(int domain, int port) { char xs_path[255]; char xs_path_watch[255]; libvchan_t *ctrl; xc_interface *xc_handle; struct xs_handle *xs; char **vec; unsigned int count, len; char *dummy = NULL; char *own_domid = NULL; xc_handle = xc_interface_open(NULL, NULL, 0); if (!xc_handle) { /* error already logged by xc_interface_open */ goto err; } /* wait for server to appear */ xs = xs_open(0); if (!xs) { perror("xs_open"); goto err_xc; } len = 0; if (!xs_watch(xs, "domid", "domid")) { fprintf(stderr, "Cannot setup xenstore watch\n"); goto err_xs; } if (!xs_watch(xs, "@releaseDomain", "release")) { fprintf(stderr, "Cannot setup xenstore watch\n"); goto err_xs; } while (!dummy || !len) { vec = xs_read_watch(xs, &count); if (vec) { if (strcmp(vec[XS_WATCH_TOKEN], "domid") == 0) { /* domid have changed */ if (own_domid) { free(own_domid); own_domid = NULL; xs_unwatch(xs, xs_path_watch, xs_path_watch); } } free(vec); } if (!own_domid) { /* construct xenstore path on first iteration and on every domid * change detected (save+restore case) */ own_domid = xs_read(xs, 0, "domid", &len); if (!own_domid) { fprintf(stderr, "Cannot get own domid\n"); goto err_xs; } if (atoi(own_domid) == domain) { fprintf(stderr, "Loopback vchan connection not supported\n"); free(own_domid); goto err_xs; } snprintf(xs_path, sizeof(xs_path), "/local/domain/%d/data/vchan/%s/%d", domain, own_domid, port); /* watch on this key as we might not have access to the whole directory */ snprintf(xs_path_watch, sizeof(xs_path_watch), "%s/event-channel", xs_path); if (!xs_watch(xs, xs_path_watch, xs_path_watch)) { fprintf(stderr, "Cannot setup watch on %s\n", xs_path_watch); free(own_domid); goto err_xs; } } dummy = xs_read(xs, 0, xs_path_watch, &len); if (dummy) free(dummy); else { if (!libvchan__check_domain_alive(xc_handle, domain)) { fprintf(stderr, "domain dead\n"); goto err_xs; } } } if (own_domid) free(own_domid); xs_close(xs); ctrl = malloc(sizeof(*ctrl)); if (!ctrl) return NULL; ctrl->xs_path = NULL; ctrl->xenvchan = libxenvchan_client_init(NULL, domain, xs_path); if (!ctrl->xenvchan) { free(ctrl); return NULL; } ctrl->xenvchan->blocking = 1; /* notify server */ xc_evtchn_notify(ctrl->xenvchan->event, ctrl->xenvchan->event_port); ctrl->remote_domain = domain; ctrl->xc_handle = xc_handle; return ctrl; err_xs: xs_close(xs); err_xc: xc_interface_close(xc_handle); err: return NULL; }
bool XenDomainWatcher::waitForDomainsOrTimeout( std::list<DomainInfo> &domains, int ms ) { struct pollfd fd; bool ret = false; fd.revents = 0; fd.fd = xs_fileno( xsh_ ); fd.events = POLLIN | POLLERR; int rc = poll( &fd, 1, ms ); domains.clear(); if ( rc == 0 ) return false; // timeout if ( fd.revents & POLLIN ) { unsigned int num; char **vec = xs_read_watch( xsh_, &num ); if ( vec && introduceToken_ == vec[XS_WATCH_TOKEN] ) { int domid = 1; xc_dominfo_t dominfo; int err = -1; while ( ( err = xc_domain_getinfo( xci_, domid, 1, &dominfo ) ) == 1 ) { domid = dominfo.domid + 1; if ( xs_is_domain_introduced( xsh_, dominfo.domid ) ) { // New domain if ( domIds_.find( dominfo.domid ) == domIds_.end() ) { domIds_.insert( dominfo.domid ); std::stringstream ss; ss << "/local/domain/" << dominfo.domid << "/name"; std::string path = ss.str(); errno = 0; char *name = static_cast<char *>( xs_read_timeout( xsh_, XBT_NULL, path.c_str(), NULL, 1 ) ); if ( !name && errno && logHelper_ ) logHelper_->error( std::string( "xs_read() error reading " ) + ss.str() + ": " + strerror( errno ) ); if ( name ) { // domain running or new domain w name set ss.str( "" ); ss << "/local/domain/" << dominfo.domid << "/console/tty"; path = ss.str(); DomainInfo domain; errno = 0; void *console = xs_read_timeout( xsh_, XBT_NULL, path.c_str(), NULL, 1 ); if ( !console && errno && logHelper_ ) logHelper_->error( std::string( "xs_read() error reading " ) + ss.str() + ": " + strerror( errno ) ); if ( console ) { free( console ); domain.isAlreadyRunning = true; } else { domain.isAlreadyRunning = false; } domain.name = name; free( name ); domains.push_back( domain ); ret = true; } else { // new domain, name not yet set ss.str( "" ); ss << "dom" << dominfo.domid; xs_watch( xsh_, path.c_str(), ss.str().c_str() ); } } } } if ( err == -1 && ( errno == EACCES || errno == EPERM ) ) throw Exception( "access denied for xc_domain_getinfo()" ); } if ( vec && releaseToken_ == vec[XS_WATCH_TOKEN] ) { int domid = 1; xc_dominfo_t dominfo; while ( xc_domain_getinfo( xci_, domid, 1, &dominfo ) == 1 ) { domid = dominfo.domid + 1; if ( !xs_is_domain_introduced( xsh_, dominfo.domid ) ) domIds_.erase( dominfo.domid ); } } if ( vec && !strncmp( vec[XS_WATCH_TOKEN], "dom", 3 ) ) { int domid = 1; if ( sscanf( vec[XS_WATCH_TOKEN], "dom%u", &domid ) == 1 ) { char *name = static_cast<char *>( xs_read_timeout( xsh_, XBT_NULL, vec[XS_WATCH_PATH], NULL, 1 ) ); if ( name ) { DomainInfo domain; domain.isAlreadyRunning = false; domain.name = name; free( name ); domains.push_back( domain ); xs_unwatch( xsh_, vec[XS_WATCH_PATH], vec[XS_WATCH_TOKEN] ); ret = true; } } } free( vec ); } return ret; }
main( int argc, char **argv) { vxt_db_start_arg_t start_db_args; struct xs_handle *xs; char token; char **vec; char *tail; int ret; int parse_result; int num; int domid; int auth_dev; fd_set set; int fd; char target_uuid[MAX_VXT_UUID] = " "; int is_provision = 0; if (daemon(0, 0) < 0) { perror("daemon"); } auth_dev = open(VXT_AUTH_DEVICE_NAME, O_RDWR); if(auth_dev < 0) { printf("main: Failed to open the Vxt authorization" " database device\n"); } /* * Start the database if it hasn't already been * started */ strncpy(start_db_args.db_file_name, VXT_DB_DEFAULT_FILE_NAME, VXT_DB_NAME_MAX); ioctl(auth_dev, VXT_AUTH_DB_START, (void *)(long)&start_db_args); /* printf("The domain device %s\n", xs_domain_dev()); */ xs = xs_domain_open(); if (!xs) { perror("xs_domain_open failure"); exit(1); } ret = xs_watch(xs, "/vm", "vxtToken"); if (ret == 0) { perror("xs_watch failed\n"); exit(1); } fd = xs_fileno(xs); while (1) { FD_ZERO(&set); FD_SET(fd, &set); /* * Poll for data * printf("Poll for data, 0x%x\n", fd); */ if ((ret = select(fd+1, &set, NULL, NULL, NULL)) >= 0) { /* printf("Watch point triggered ret = 0x%x\n", ret); */ vec = xs_read_watch(xs, &num); printf("\n after read watch "); if (!vec) error(); parse_result = xsd_vm_name(vec[XS_WATCH_PATH], target_uuid); if (parse_result == 1) { char **list; char path[64]; int entry_cnt; int i; /* * get a list of all the domain ids, * then check the name of each one * to find the id for the specified domain */ list = xs_directory(xs, XBT_NULL, "/local/domain", &entry_cnt); for (i = (entry_cnt-1); i > 0; i--) { char *rec_uuid; sprintf(path, "/local/domain/%s/vm", list[i]); rec_uuid = xs_read(xs, XBT_NULL, path, NULL); if ( rec_uuid == NULL ) { continue; } if (strcmp(&(rec_uuid[4]), target_uuid) == 0) { free(rec_uuid); domid = atoi(list[i]); break; } free(rec_uuid); } free(list); if (i == 0) { free(vec); continue; } xsd_write_auth_record(auth_dev, target_uuid); /* printf("main: call vxt_auth_db on uuid = %s\n", target_uuid); */ xsd_provision_controller(xs, domid); is_provision = 1; update_vm_state(target_uuid, is_provision); } else if (parse_result == 2) { /* treating this case as deprovision */ is_provision = 0; update_vm_state(target_uuid, is_provision); } else { /* target_uuid is undefined * don't call update_vm_state */ } free(vec); } else { break; } } printf("returned from xs_watch, xenstore exited\n"); }
int main(int argc, char * const argv[]) { char **vec; unsigned int num; char *s; int state; char *sstate; char *p; char buf[80]; int type = DEVTYPE_UNKNOWN; int ch; int debug_fd; FILE *pidfile_f; while ((ch = getopt(argc, argv, "dfl:p:s:")) != -1) { switch (ch) { case 'd': dflag = 1; break; case 'f': fflag = 1; break; case 'l': log_file = optarg; break; case 'p': pidfile = pidfile; case 's': vbd_script = optarg; break; default: usage(); } } if (vbd_script == NULL) vbd_script = VBD_SCRIPT; if (pidfile == NULL) pidfile = PID_FILE; if (log_file == NULL) log_file = LOG_FILE; openlog("xenbackendd", LOG_PID | LOG_NDELAY, LOG_DAEMON); if (fflag == 0) { /* open log file */ debug_fd = open(log_file, O_RDWR | O_CREAT | O_TRUNC, 0644); if (debug_fd == -1) { dolog(LOG_ERR, "can't open %s: %s", log_file, strerror(errno)); exit(EXIT_FAILURE); } } if (fflag == 0) { /* daemonize */ pidfile_f = fopen(pidfile, "w"); if (pidfile_f == NULL) { dolog(LOG_ERR, "can't open %s: %s", pidfile, strerror(errno)); exit(EXIT_FAILURE); } if (daemon(0, 0) < 0) { dolog(LOG_ERR, "can't daemonize: %s", strerror(errno)); exit(EXIT_FAILURE); } fprintf(pidfile_f, "%d\n", (int)getpid()); fclose(pidfile_f); /* redirect stderr to log file */ if (dup2(debug_fd, STDERR_FILENO) < 0) { dolog(LOG_ERR, "can't redirect stderr to %s: %s\n", log_file, strerror(errno)); exit(EXIT_FAILURE); } /* also redirect stdout if we're in debug mode */ if (dflag) { if (dup2(debug_fd, STDOUT_FILENO) < 0) { dolog(LOG_ERR, "can't redirect stdout to %s: %s\n", log_file, strerror(errno)); exit(EXIT_FAILURE); } } close(debug_fd); debug_fd = -1; } if (xen_setup() < 0) exit(EXIT_FAILURE); for (;;) { vec = xs_read_watch(xs, &num); if (!vec) { dolog(LOG_ERR, "xs_read_watch: NULL\n"); continue; } if (strlen(vec[XS_WATCH_PATH]) < sizeof("state")) goto next1; /* find last component of path, check if it's "state" */ p = &vec[XS_WATCH_PATH][ strlen(vec[XS_WATCH_PATH]) - sizeof("state")]; if (p[0] != '/') goto next1; p[0] = '\0'; p++; if (strcmp(p, "state") != 0) goto next1; snprintf(buf, sizeof(buf), "%s/state", vec[XS_WATCH_PATH]); sstate = xs_read(xs, XBT_NULL, buf, 0); if (sstate == NULL) { dolog(LOG_ERR, "Failed to read %s (%s)", buf, strerror(errno)); goto next1; } state = atoi(sstate); snprintf(buf, sizeof(buf), "%s/hotplug-status", vec[XS_WATCH_PATH]); s = xs_read(xs, XBT_NULL, buf, 0); if (s != NULL && state != 6 /* XenbusStateClosed */) goto next2; if (strncmp(vec[XS_WATCH_PATH], DOMAIN_PATH "/backend/vif", strlen(DOMAIN_PATH "/backend/vif")) == 0) type = DEVTYPE_VIF; if (strncmp(vec[XS_WATCH_PATH], DOMAIN_PATH "/backend/vbd", strlen(DOMAIN_PATH "/backend/vbd")) == 0) type = DEVTYPE_VBD; switch(type) { case DEVTYPE_VIF: if (s) free(s); snprintf(buf, sizeof(buf), "%s/script", vec[XS_WATCH_PATH]); s = xs_read(xs, XBT_NULL, buf, 0); if (s == NULL) { dolog(LOG_ERR, "Failed to read %s (%s)", buf, strerror(errno)); goto next2; } doexec(s, vec[XS_WATCH_PATH], sstate); break; case DEVTYPE_VBD: doexec(vbd_script, vec[XS_WATCH_PATH], sstate); break; default: break; } next2: if (s) free(s); free(sstate); next1: free(vec); } return 0; }