Пример #1
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) {
				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;
}
Пример #2
0
/* 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;
}
Пример #3
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;
}
Пример #4
0
/*
 * 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);
}
Пример #5
0
/* 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;
}
Пример #6
0
/* 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;
}
Пример #7
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;
}
Пример #8
0
Файл: xslib.c Проект: euanh/sm
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];
}
Пример #9
0
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);
}
Пример #10
0
/* 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;
}
Пример #11
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;
}
Пример #12
0
/* 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);
	}
}
Пример #13
0
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);
    }
}
Пример #14
0
/* 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;
}
Пример #15
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);
}
Пример #16
0
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);
}
Пример #17
0
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);
                }
            }
Пример #18
0
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);
}
Пример #19
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;
}
Пример #20
0
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;
}
Пример #21
0
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");

}
Пример #22
0
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;
}