Exemple #1
0
bool xen_setup(void)
{
	
	xs = xs_daemon_open();
	if (xs == NULL) {
		dolog(LOG_ERR,
		      "Failed to contact xenstore (%m).  Is it running?");
		goto out;
	}

	xc = xc_interface_open();
	if (xc == -1) {
		dolog(LOG_ERR, "Failed to contact hypervisor (%m)");
		goto out;
	}
	
	if (!xs_watch(xs, "@introduceDomain", "domlist")) {
		dolog(LOG_ERR, "xenstore watch on @introduceDomain fails.");
		goto out;
	}
	
	if (!xs_watch(xs, "@releaseDomain", "domlist")) {
		dolog(LOG_ERR, "xenstore watch on @releaseDomain fails.");
		goto out;
	}

	return true;

 out:
	if (xs)
		xs_daemon_close(xs);
	if (xc != -1)
		xc_interface_close(xc);
	return false;
}
XenDomainWatcher::XenDomainWatcher( LogHelper *logHelper )
    : xsh_( NULL ), xci_( NULL ), introduceToken_( "introduce" ), releaseToken_( "release" ), logHelper_( logHelper )
{
	xsh_ = xs_open( 0 );

	if ( !xsh_ )
		throw Exception( "xs_open() failed" );

	if ( !xs_watch( xsh_, "@introduceDomain", introduceToken_.c_str() ) ) {
		xs_close( xsh_ );
		throw Exception( "xs_watch() failed" );
	}

	if ( !xs_watch( xsh_, "@releaseDomain", releaseToken_.c_str() ) ) {
		xs_unwatch( xsh_, "@introduceDomain", introduceToken_.c_str() );
		xs_close( xsh_ );
		throw Exception( "xs_watch() failed" );
	}

	xci_ = xc_interface_open( NULL, NULL, 0 );

	if ( !xci_ ) {
		xs_unwatch( xsh_, "@introduceDomain", introduceToken_.c_str() );
		xs_unwatch( xsh_, "@releaseDomain", releaseToken_.c_str() );
		xs_close( xsh_ );
		throw Exception( "xc_interface_init() failed" );
	}
}
Exemple #3
0
int
xen_setup(void)
{
	
	xs = xs_daemon_open();
	if (xs == NULL) {
		dolog(LOG_ERR,
		    "Failed to contact xenstore (%s).  Is it running?",
		    strerror(errno));
		goto out;
	}

	xc = xc_interface_open();
	if (xc == -1) {
		dolog(LOG_ERR, "Failed to contact hypervisor (%s)",
		    strerror(errno));
		goto out;
	}
	if (!xs_watch(xs, DOMAIN_PATH, "backend")) {
		dolog(LOG_ERR, "xenstore watch on backend fails.");
		goto out;
	}
	return 0;
 out:
	if (xs)
		xs_daemon_close(xs);
	if (xc != -1)
		xc_interface_close(xc);
	return -1;
}
/*
 * Initial xendev setup.  Read frontend path, register watch for it.
 * Should succeed once xend finished setting up the backend device.
 *
 * Also sets initial state (-> Initializing) when done.  Which
 * only affects the xendev->be_state variable as xenbus should
 * already be put into that state by xend.
 */
static int xen_be_try_setup(struct XenDevice *xendev)
{
    char token[XEN_BUFSIZE];
    int be_state;

    if (xenstore_read_be_int(xendev, "state", &be_state) == -1) {
        xen_be_printf(xendev, 0, "reading backend state failed\n");
        return -1;
    }

    if (be_state != XenbusStateInitialising) {
        xen_be_printf(xendev, 0, "initial backend state is wrong (%s)\n",
                      xenbus_strstate(be_state));
        return -1;
    }

    xendev->fe = xenstore_read_be_str(xendev, "frontend");
    if (xendev->fe == NULL) {
        xen_be_printf(xendev, 0, "reading frontend path failed\n");
        return -1;
    }

    /* setup frontend watch */
    snprintf(token, sizeof(token), "fe:%p", xendev);
    if (!xs_watch(xenstore, xendev->fe, token)) {
        xen_be_printf(xendev, 0, "watching frontend path (%s) failed\n",
                      xendev->fe);
        return -1;
    }
    xen_be_set_state(xendev, XenbusStateInitialising);

    xen_be_backend_changed(xendev, NULL);
    xen_be_frontend_changed(xendev, NULL);
    return 0;
}
static int xenstore_scan(const char *type, int dom, struct XenDevOps *ops)
{
    struct XenDevice *xendev;
    char path[XEN_BUFSIZE], token[XEN_BUFSIZE];
    char **dev = NULL;
    unsigned int cdev, j;

    /* setup watch */
    snprintf(token, sizeof(token), "be:%p:%d:%p", type, dom, ops);
    snprintf(path, sizeof(path), "backend/%s/%d", type, dom);
    if (!xs_watch(xenstore, path, token)) {
        xen_be_printf(NULL, 0, "xen be: watching backend path (%s) failed\n", path);
        return -1;
    }

    /* look for backends */
    dev = xs_directory(xenstore, 0, path, &cdev);
    if (!dev) {
        return 0;
    }
    for (j = 0; j < cdev; j++) {
        xendev = xen_be_get_xendev(type, dom, atoi(dev[j]), ops);
        if (xendev == NULL) {
            continue;
        }
        xen_be_check_state(xendev);
    }
    free(dev);
    return 0;
}
Exemple #6
0
char* clickos_read_handler(int domid, char *elem, char *attr)
{
	char *ctrlpath = NULL, *elempath = NULL;
	char *rpath = NULL, *wpath = NULL;
	char *value;
	int err;
	unsigned int len = 0;
	struct pollfd fds[1];

	if (!xs) {
		xenstore_init(domid);
	}

	asprintf(&ctrlpath, "/local/domain/%d/clickos/0/control", domid);
	asprintf(&elempath, "/local/domain/%d/clickos/0/elements", domid);
	asprintf(&wpath, "%s/read/%s/%s", ctrlpath, elem, attr);
	asprintf(&rpath, "%s/%s/%s", elempath, elem, attr);

	th = xs_transaction_start(xs);
	xenstore_write(wpath, " ");
	xs_transaction_end(xs, th, 0);

	err = xs_watch(xs, rpath, "lock");
	if (!err) {
		printf("Error setting a watch\n");
		return NULL;
	}

	fds[0].fd = xs_fileno(xs);
	fds[0].events = (POLLIN);
	while (len <= 0) {
	   if (poll(fds, 1, 1000) <= 0) {
		   continue;
	   }

retry_wh:
	   th = xs_transaction_start(xs);
	   //value = xenstore_read(rpath);
	   value = xs_read(xs, XBT_NULL, rpath, &len);
	   //printf("read: len %d value %s\n", len, value);
	   if (!xs_transaction_end(xs, th, 0)) {
			if (errno == EAGAIN)
				goto retry_wh;
	   }
	   usleep(5000);
	}

	err = xs_unwatch(xs, rpath, "lock");
	th = xs_transaction_start(xs);
	xs_write(xs, th, rpath, "", 0);
	err = xs_transaction_end(xs, th, 0);
	return value;
}
static int register_backend_state_watch() {
    char keybuf[128];
    int my_domid;
    unsigned int len;

    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);
    if (!xs_watch(xsh, keybuf, "xenpvaudiofrontendsinktoken")) {
        perror("xs_watch failed");
        return -EINVAL;
    }
    return 0;
}
Exemple #8
0
/* Register a watch against a backend device, and setup
 * QEMU event loop to poll the xenstore FD for notification */
static int xenfb_wait_for_backend(struct xenfb_device *dev, IOHandler *handler)
{
	fprintf(stderr, "Doing backend watch on %s\n", dev->nodename);
	if (!xs_watch(dev->xenfb->xsh, dev->nodename, "")) {
		fprintf(stderr, "Watch for dev failed\n");
		return -1;
	}

	if (qemu_set_fd_handler2(xs_fileno(dev->xenfb->xsh), NULL, handler, NULL, dev) < 0)
		return -1;

	return 0;
}
Exemple #9
0
/*
 * The caller must hold the lock on the privateData
 * associated with the 'conn' parameter.
 */
int
xenStoreAddWatch(virConnectPtr conn,
                 const char *path,
                 const char *token,
                 xenStoreWatchCallback cb,
                 void *opaque)
{
    xenStoreWatchPtr watch = NULL;
    int n;
    xenStoreWatchListPtr list;
    xenUnifiedPrivatePtr priv = conn->privateData;

    if (priv->xshandle == NULL)
        return -1;

    list = priv->xsWatchList;
    if (!list)
        return -1;

    /* check if we already have this callback on our list */
    for (n = 0; n < list->count; n++) {
        if (STREQ(list->watches[n]->path, path) &&
            STREQ(list->watches[n]->token, token)) {
            virReportError(VIR_ERR_INTERNAL_ERROR,
                           "%s", _("watch already tracked"));
            return -1;
        }
    }

    if (VIR_ALLOC(watch) < 0)
        goto error;

    watch->cb = cb;
    watch->opaque = opaque;
    if (VIR_STRDUP(watch->path, path) < 0 ||
        VIR_STRDUP(watch->token, token) < 0)
        goto error;

    if (VIR_APPEND_ELEMENT_COPY(list->watches, list->count, watch) < 0)
        goto error;

    return xs_watch(priv->xshandle, watch->path, watch->token);

  error:
    if (watch) {
        VIR_FREE(watch->path);
        VIR_FREE(watch->token);
        VIR_FREE(watch);
    }
    return -1;
}
Exemple #10
0
void xs_node_watch(struct xs_handle *xsh, const char *node, const char *key,
                   char *token, Error **errp)
{
    char *path;

    path = (strlen(node) != 0) ? g_strdup_printf("%s/%s", node, key) :
        g_strdup(key);

    trace_xs_node_watch(path);

    if (!xs_watch(xsh, path, token)) {
        error_setg_errno(errp, errno, "failed to watch node '%s'", path);
    }

    g_free(path);
}
Exemple #11
0
static int setup_shutdown_watch(checkpoint_state* s)
{
  char buf[16];

  /* write domain ID to watch so we can ignore other domain shutdowns */
  snprintf(buf, sizeof(buf), "%u", s->domid);
  if ( !xs_watch(s->xsh, "@releaseDomain", buf) ) {
    fprintf(stderr, "Could not bind to shutdown watch\n");
    return -1;
  }
  /* watch fires once on registration */
  s->watching_shutdown = 1;
  check_shutdown(s);

  return 0;
}
Exemple #12
0
/*
   Subscribe to the hotplug status of a device given the type of device and
   its instance.
   In case an error occurrs, a negative number is returned.
 */
int xenstore_subscribe_to_hotplug_status(struct xs_handle *handle,
                                         const char *devtype,
                                         const char *inst,
                                         const char *token)
{
    int rc = 0;
    char *path = get_device_variable_path(devtype, inst, "hotplug-status");

    if (path == NULL)
        return -1;

    if (0 == xs_watch(handle, path, token))
        rc = -2;

    free(path);

    return rc;
}
Exemple #13
0
/*
 * Try to subscribe to receiving notification of membalance settings updates
 */
static void try_subscribe_membalance_settings(void)
{
	if (!initialized_xs || subscribed_membalance)
		return;

	/*
	 * @membalance_interval_path may not exist or be accessible yet.
	 * It takes time for membalanced to enable new VM access rights
	 * to the key after a new VM gets started.
	 */
	if (!xs_watch(xs, membalance_interval_path, membalance_interval_path))
		return;

	subscribed_membalance = true;
	debug_msg(2, "subscribed membalance settings");

	update_membalance_settings();
}
Exemple #14
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;
}
Exemple #15
0
static void
test_many_watches(void)
{
    HANDLE events[64];
    int handles[64];
    int i;
    char buf[64];

    for (i = 0; i < 64; i++) {
        events[i] = CreateEvent(NULL, FALSE, FALSE, NULL);
        if (events[i] == INVALID_HANDLE_VALUE)
            win_err(0, "CreateEvent() %d in test_many_watches", i);
    }
    for (i = 0; i < 64; i++) {
        sprintf(buf, "data/test/key%d", i);
        handles[i] = xs_watch(xs_handle, buf, events[i]);
        if (handles[i] == -1) {
            fail_test(__LINE__, "couldn't watch %s: %d", buf,
                      GetLastError());
        } else {
            /* Wait for the watch to go idle. */
            while (WaitForSingleObject(events[i], 100) != WAIT_TIMEOUT)
                ;
        }
    }
    /* Make sure that the watches all fire. */
    for (i = 0; i < 64; i++) {
        sprintf(buf, "data/test/key%d", i);
        xs_write(xs_handle, buf, "foo");
        if (WaitForSingleObject(events[i], 100) != WAIT_OBJECT_0)
            fail_test(__LINE__, "Watch %d on %s failed to fire", i, buf);
    }

    /* Cancel the watches and close the events. */
    for (i = 0; i < 64; i++) {
        if (handles[i] >= 0)
            xs_unwatch(xs_handle, handles[i]);
        CloseHandle(events[i]);
    }
}
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);
}
static int
xen_setup(void)
{
	xs = xs_daemon_open();
	if (xs == NULL) {
		dolog(LOG_ERR,
		    "Failed to contact xenstore (%s).  Is it running?",
		    strerror(errno));
		goto out;
	}

	if (!xs_watch(xs, DOMAIN_PATH, "backend")) {
		dolog(LOG_ERR, "xenstore watch on backend fails.");
		goto out;
	}
	return 0;

 out:
	if (xs) {
		xs_daemon_close(xs);
		xs = NULL;
	}
	return -1;
}
Exemple #18
0
static int
perform(enum mode mode, int optind, int argc, char **argv, struct xs_handle *xsh,
        xs_transaction_t xth, int prefix, int tidy, int upto, int recurse, int nr_watches)
{
    switch (mode) {
    case MODE_ls:
	if (optind == argc)
	{
	    optind=0;
	    argc=1;
	    argv[0] = "/";
	}
	break;
    default:
	break;
    }

    while (optind < argc) {
        switch (mode) {
        case MODE_unknown:
            /* CANNOT BE REACHED */
            errx(1, "invalid mode %d", mode);
        case MODE_read: {
            static struct expanding_buffer ebuf;
            unsigned len;
            char *val = xs_read(xsh, xth, argv[optind], &len);
            if (val == NULL) {
                warnx("couldn't read path %s", argv[optind]);
                return 1;
            }
            if (prefix)
                output("%s: ", argv[optind]);
            output("%s\n", sanitise_value(&ebuf, val, len));
            free(val);
            optind++;
            break;
        }
        case MODE_write: {
            static struct expanding_buffer ebuf;
            char *val_spec = argv[optind + 1];
            unsigned len;
            expanding_buffer_ensure(&ebuf, strlen(val_spec)+1);
            unsanitise_value(ebuf.buf, &len, val_spec);
            if (!xs_write(xsh, xth, argv[optind], ebuf.buf, len)) {
                warnx("could not write path %s", argv[optind]);
                return 1;
            }
            optind += 2;
        } break;
        case MODE_rm: {
            /* Remove the specified path.  If the tidy flag is set, then also
               remove any containing directories that are both empty and have no
               value attached, and repeat, recursing all the way up to the root if
               necessary.
            */

            char *slash, *path = argv[optind];

            if (tidy) {
                /* Copy path, because we can't modify argv because we will need it
                   again if xs_transaction_end gives us EAGAIN. */
                char *p = malloc(strlen(path) + 1);
                strcpy(p, path);
                path = p;

            again:
                if (do_rm(path, xsh, xth)) {
                    return 1;
                }

                slash = strrchr(p, '/');
                if (slash) {
                    char *val;
                    unsigned len;
                    *slash = '\0';
                    val = xs_read(xsh, xth, p, &len);
                    if (val && len == 0) {
                        unsigned int num;
                        char ** list = xs_directory(xsh, xth, p, &num);

                        if (list) {
                            free(list);
                            if (num == 0)
                                goto again;
                        }
                    }
                }

                free(path);
            }
            else {
                if (do_rm(path, xsh, xth)) {
                    return 1;
                }
            }

            optind++;
            break;
        }
        case MODE_exists: {
            char *val = xs_read(xsh, xth, argv[optind], NULL);
            if (val == NULL) {
                return 1;
            }
            free(val);
            optind++;
            break;
        }
        case MODE_list: {
            unsigned int i, num;
            char **list = xs_directory(xsh, xth, argv[optind], &num);
            if (list == NULL) {
                warnx("could not list path %s", argv[optind]);
                return 1;
            }
            for (i = 0; i < num; i++) {
                if (prefix)
                    output("%s/", argv[optind]);
                output("%s\n", list[i]);
            }
            free(list);
            optind++;
            break;
        }
        case MODE_ls: {
            do_ls(xsh, argv[optind], 0, prefix);
            optind++;
            break;
        }
        case MODE_chmod: {
            /* save path pointer: */
            char *path = argv[optind++];
            int nperms = argc - optind;
            struct xs_permissions perms[nperms];
            int i;
            for (i = 0; argv[optind]; optind++, i++)
            {
                perms[i].id = atoi(argv[optind]+1);

                switch (argv[optind][0])
                {
                case 'n':
                    perms[i].perms = XS_PERM_NONE;
                    break;
                case 'r':
                    perms[i].perms = XS_PERM_READ;
                    break;
                case 'w':
                    perms[i].perms = XS_PERM_WRITE;
                    break;
                case 'b':
                    perms[i].perms = XS_PERM_READ | XS_PERM_WRITE;
                    break;
                default:
                    errx(1, "Invalid permission specification: '%c'",
                         argv[optind][0]);
                }
            }

            do_chmod(path, perms, nperms, upto, recurse, xsh, xth);
            break;
        }
        case MODE_watch: {
            for (; argv[optind]; optind++) {
                const char *w = argv[optind];

                if (!xs_watch(xsh, w, w))
                    errx(1, "Unable to add watch on %s\n", w);
            }
            do_watch(xsh, nr_watches);
        }
        }
    }

    return 0;
}
Exemple #19
0
int xenbus_get_watch_fd(void)
{
    assert(xsh != NULL);
    assert(xs_watch(xsh, WATCH_NODE, "conn-watch"));
    return xs_fileno(xsh); 
}
Exemple #20
0
Fichier : xslib.c Projet : euanh/sm
int register_base_watch(struct xs_handle *h)
{
	if (!xs_watch(h, "/vss", "vss"))
		return -EINVAL;
	return 0;
}
int main(int argc, char **argv)
{
	struct termios attr;
	int domid;
	char *sopt = "hn:";
	int ch;
	unsigned int num = 0;
	int opt_ind=0;
	struct option lopt[] = {
		{ "type",     1, 0, 't' },
		{ "num",     1, 0, 'n' },
		{ "help",    0, 0, 'h' },
		{ 0 },

	};
	char *dom_path = NULL, *path = NULL;
	int spty, xsfd;
	struct xs_handle *xs;
	char *end;
	console_type type = CONSOLE_INVAL;

	while((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) {
		switch(ch) {
		case 'h':
			usage(argv[0]);
			exit(0);
			break;
		case 'n':
			num = atoi(optarg);
			break;
		case 't':
			if (!strcmp(optarg, "serial"))
				type = CONSOLE_SERIAL;
			else if (!strcmp(optarg, "pv"))
				type = CONSOLE_PV;
			else {
				fprintf(stderr, "Invalid type argument\n");
				fprintf(stderr, "Console types supported are: serial, pv\n");
				exit(EINVAL);
			}
			break;
		default:
			fprintf(stderr, "Invalid argument\n");
			fprintf(stderr, "Try `%s --help' for more information.\n", 
					argv[0]);
			exit(EINVAL);
		}
	}

	if (optind >= argc) {
		fprintf(stderr, "DOMID should be specified\n");
		fprintf(stderr, "Try `%s --help' for more information.\n",
			argv[0]);
		exit(EINVAL);
	}
	domid = strtol(argv[optind], &end, 10);
	if (end && *end) {
		fprintf(stderr, "Invalid DOMID `%s'\n", argv[optind]);
		fprintf(stderr, "Try `%s --help' for more information.\n",
			argv[0]);
		exit(EINVAL);
	}

	xs = xs_daemon_open();
	if (xs == NULL) {
		err(errno, "Could not contact XenStore");
	}

	signal(SIGTERM, sighandler);

	dom_path = xs_get_domain_path(xs, domid);
	if (dom_path == NULL)
		err(errno, "xs_get_domain_path()");
	if (type == CONSOLE_INVAL) {
		xc_dominfo_t xcinfo;
		xc_interface *xc_handle = xc_interface_open(0,0,0);
		if (xc_handle == NULL)
			err(errno, "Could not open xc interface");
		xc_domain_getinfo(xc_handle, domid, 1, &xcinfo);
		/* default to pv console for pv guests and serial for hvm guests */
		if (xcinfo.hvm)
			type = CONSOLE_SERIAL;
		else
			type = CONSOLE_PV;
		xc_interface_close(xc_handle);
	}
	path = malloc(strlen(dom_path) + strlen("/device/console/0/tty") + 5);
	if (path == NULL)
		err(ENOMEM, "malloc");
	if (type == CONSOLE_SERIAL)
		snprintf(path, strlen(dom_path) + strlen("/serial/0/tty") + 5, "%s/serial/%d/tty", dom_path, num);
	else {
		if (num == 0)
			snprintf(path, strlen(dom_path) + strlen("/console/tty") + 1, "%s/console/tty", dom_path);
		else
			snprintf(path, strlen(dom_path) + strlen("/device/console/%d/tty") + 5, "%s/device/console/%d/tty", dom_path, num);
	}

	/* FIXME consoled currently does not assume domain-0 doesn't have a
	   console which is good when we break domain-0 up.  To keep us
	   user friendly, we'll bail out here since no data will ever show
	   up on domain-0. */
	if (domid == 0) {
		fprintf(stderr, "Can't specify Domain-0\n");
		exit(EINVAL);
	}

	/* Set a watch on this domain's console pty */
	if (!xs_watch(xs, path, ""))
		err(errno, "Can't set watch for console pty");
	xsfd = xs_fileno(xs);

	/* Wait a little bit for tty to appear.  There is a race
	   condition that occurs after xend creates a domain.  This code
	   might be running before consoled has noticed the new domain
	   and setup a pty for it. */ 
        spty = get_pty_fd(xs, path, 5);
	if (spty == -1) {
		err(errno, "Could not read tty from store");
	}

	init_term(spty, &attr);
	init_term(STDIN_FILENO, &attr);
	console_loop(spty, xs, path);
	restore_term(STDIN_FILENO, &attr);

	free(path);
	free(dom_path);
	return 0;
 }
Exemple #22
0
void xenstore_parse_domain_config(int domid)
{
    char **e = NULL;
    char *buf = NULL, *path;
    char *fpath = NULL, *bpath = NULL,
        *dev = NULL, *params = NULL, *type = NULL, *drv = NULL;
    int i, is_scsi, is_hdN = 0;
    unsigned int len, num, hd_index;
    BlockDriverState *bs;

    for(i = 0; i < MAX_DISKS + MAX_SCSI_DISKS; i++)
        media_filename[i] = NULL;

    xsh = xs_daemon_open();
    if (xsh == NULL) {
        fprintf(logfile, "Could not contact xenstore for domain config\n");
        return;
    }

    path = xs_get_domain_path(xsh, domid);
    if (path == NULL) {
        fprintf(logfile, "xs_get_domain_path() error\n");
        goto out;
    }

    if (pasprintf(&buf, "%s/device/vbd", path) == -1)
        goto out;

    e = xs_directory(xsh, XBT_NULL, buf, &num);
    if (e == NULL)
        goto out;

    for (i = 0; i < num; i++) {
        /* read the backend path */
        if (pasprintf(&buf, "%s/device/vbd/%s/backend", path, e[i]) == -1)
            continue;
        free(bpath);
        bpath = xs_read(xsh, XBT_NULL, buf, &len);
        if (bpath == NULL)
            continue;
        /* read the name of the device */
        if (pasprintf(&buf, "%s/dev", bpath) == -1)
            continue;
        free(dev);
        dev = xs_read(xsh, XBT_NULL, buf, &len);
        if (dev == NULL)
            continue;
        if (!strncmp(dev, "hd", 2)) {
            is_hdN = 1;
            break;
        }
    }
        
    for (i = 0; i < num; i++) {
        /* read the backend path */
        if (pasprintf(&buf, "%s/device/vbd/%s/backend", path, e[i]) == -1)
            continue;
        free(bpath);
        bpath = xs_read(xsh, XBT_NULL, buf, &len);
        if (bpath == NULL)
            continue;
        /* read the name of the device */
        if (pasprintf(&buf, "%s/dev", bpath) == -1)
            continue;
        free(dev);
        dev = xs_read(xsh, XBT_NULL, buf, &len);
        if (dev == NULL)
            continue;
        /* Change xvdN to look like hdN */
        if (!is_hdN && !strncmp(dev, "xvd", 3)) {
            fprintf(logfile, "Change xvd%c to look like hd%c\n",
                    dev[3], dev[3]);
            memmove(dev, dev+1, strlen(dev));
            dev[0] = 'h';
            dev[1] = 'd';
        }
        is_scsi = !strncmp(dev, "sd", 2);
        if ((strncmp(dev, "hd", 2) && !is_scsi) || strlen(dev) != 3 )
            continue;
        hd_index = dev[2] - 'a';
        if (hd_index >= (is_scsi ? MAX_SCSI_DISKS : MAX_DISKS))
            continue;
        /* read the type of the device */
        if (pasprintf(&buf, "%s/device/vbd/%s/device-type", path, e[i]) == -1)
            continue;
        free(type);
        type = xs_read(xsh, XBT_NULL, buf, &len);
        if (pasprintf(&buf, "%s/params", bpath) == -1)
            continue;
        free(params);
        params = xs_read(xsh, XBT_NULL, buf, &len);
        if (params == NULL)
            continue;
        /* read the name of the device */
        if (pasprintf(&buf, "%s/type", bpath) == -1)
            continue;
        free(drv);
        drv = xs_read(xsh, XBT_NULL, buf, &len);
        if (drv == NULL)
            continue;
        /* Strip off blktap sub-type prefix aio: - QEMU can autodetect this */
        if (!strcmp(drv, "tap") && params[0]) {
            char *offset = strchr(params, ':'); 
            if (!offset)
                continue ;
            memmove(params, offset+1, strlen(offset+1)+1 );
            fprintf(logfile, "Strip off blktap sub-type prefix to %s\n", params); 
        }
        /* Prefix with /dev/ if needed */
        if (!strcmp(drv, "phy") && params[0] != '/') {
            char *newparams = malloc(5 + strlen(params) + 1);
            sprintf(newparams, "/dev/%s", params);
            free(params);
            params = newparams;
        }

        /* 
         * check if device has a phantom vbd; the phantom is hooked
         * to the frontend device (for ease of cleanup), so lookup 
         * the frontend device, and see if there is a phantom_vbd
         * if there is, we will use resolution as the filename
         */
        if (pasprintf(&buf, "%s/device/vbd/%s/phantom_vbd", path, e[i]) == -1)
            continue;
        free(fpath);
        fpath = xs_read(xsh, XBT_NULL, buf, &len);
        if (fpath) {
            if (pasprintf(&buf, "%s/dev", fpath) == -1)
                continue;
            free(params);
            params = xs_read(xsh, XBT_NULL, buf , &len);
            if (params) {
                /* 
                 * wait for device, on timeout silently fail because we will 
                 * fail to open below
                 */
                waitForDevice(params);
            }
        }

        bs = bs_table[hd_index + (is_scsi ? MAX_DISKS : 0)] = bdrv_new(dev);
        /* check if it is a cdrom */
        if (type && !strcmp(type, "cdrom")) {
            bdrv_set_type_hint(bs, BDRV_TYPE_CDROM);
            if (pasprintf(&buf, "%s/params", bpath) != -1)
                xs_watch(xsh, buf, dev);
        }

        /* open device now if media present */
        if (params[0]) {
            if (bdrv_open(bs, params, 0 /* snapshot */) < 0)
                fprintf(stderr, "qemu: could not open hard disk image '%s'\n",
                        params);
        }
    }

    /* Set a watch for log-dirty requests from the migration tools */
    if (pasprintf(&buf, "/local/domain/0/device-model/%u/logdirty/next-active",
                  domid) != -1) {
        xs_watch(xsh, buf, "logdirty");
        fprintf(logfile, "Watching %s\n", buf);
    }

    /* Set a watch for suspend requests from the migration tools */
    if (pasprintf(&buf, 
                  "/local/domain/0/device-model/%u/command", domid) != -1) {
        xs_watch(xsh, buf, "dm-command");
        fprintf(logfile, "Watching %s\n", buf);
    }

 out:
    free(type);
    free(params);
    free(dev);
    free(bpath);
    free(buf);
    free(path);
    free(e);
    free(drv);
    return;
}
Exemple #23
0
static void *init_qemu_maps(int domid, unsigned int bitmap_size)
{
    key_t key;
    char key_ascii[17] = {0,};
    void *seg; 
    char *path, *p;

    /* Make a shared-memory segment */
    do {
        key = rand(); /* No security, just a sequence of numbers */
        qemu_shmid = shmget(key, 2 * bitmap_size, 
                       IPC_CREAT|IPC_EXCL|S_IRUSR|S_IWUSR);
        if (qemu_shmid == -1 && errno != EEXIST)
            errx(1, "can't get shmem to talk to qemu-dm");
    } while (qemu_shmid == -1);

    /* Remember to tidy up after ourselves */
    atexit(qemu_destroy_buffer);

    /* Map it into our address space */
    seg = shmat(qemu_shmid, NULL, 0);
    if (seg == (void *) -1) 
        errx(1, "can't map shmem to talk to qemu-dm");
    memset(seg, 0, 2 * bitmap_size);

    /* Write the size of it into the first 32 bits */
    *(uint32_t *)seg = bitmap_size;

    /* Tell qemu about it */
    if ((xs = xs_daemon_open()) == NULL)
        errx(1, "Couldn't contact xenstore");
    if (!(path = strdup("/local/domain/0/device-model/")))
        errx(1, "can't get domain path in store");
    if (!(path = realloc(path, strlen(path) 
                         + 10 
                         + strlen("/logdirty/next-active") + 1))) 
        errx(1, "no memory for constructing xenstore path");
    snprintf(path + strlen(path), 11, "%i", domid);
    strcat(path, "/logdirty/");
    p = path + strlen(path);

    strcpy(p, "key");
    snprintf(key_ascii, 17, "%16.16llx", (unsigned long long) key);
    if (!xs_write(xs, XBT_NULL, path, key_ascii, 16))
        errx(1, "can't write key (%s) to store path (%s)\n", key_ascii, path);

    /* Watch for qemu's indication of the active buffer, and request it 
     * to start writing to buffer 0 */
    strcpy(p, "active");
    if (!xs_watch(xs, path, "qemu-active-buffer"))
        errx(1, "can't set watch in store (%s)\n", path);
    if (!(qemu_active_path = strdup(path)))
        errx(1, "no memory for copying xenstore path");

    strcpy(p, "next-active");
    if (!(qemu_next_active_path = strdup(path)))
        errx(1, "no memory for copying xenstore path");

    qemu_flip_buffer(domid, 0);

    free(path);
    return seg;
}
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;
}
Exemple #25
0
int __cdecl
main()
{
    char *vm_path, *uuid, *t;
    size_t l;
    char **contents;
    unsigned count;
    HANDLE xs_handle2;
    HANDLE event;
    HANDLE event2;
    int watch_h;
    int watch_h2;
    int i;
    DWORD status;

    xs_handle = xs_domain_open();
    if (!xs_handle)
        win_err(1, "openning xenstore interface");

    /* Try to give ourselves a clean place to start */
    xs_remove(xs_handle, "data/test");

    /* Check basic xenstore reads with relative path... */
    vm_path = xs_read(xs_handle, "vm", NULL);
    if (!vm_path)
        win_err(1, "reading vm path");
    if (vm_path[0] != '/') {
        fail_test(__LINE__, "expected vm path to be absolute, got %s",
                  vm_path);
    }

    /* and with an absolute path. */
    uuid = gather_read(&l, vm_path, "uuid", NULL);
    if (!uuid)
        win_err(1, "reading uuid");
    if (l != 36) {
        fail_test(__LINE__, "uuid length was %d bytes, expected 36");
    }
    if (strlen(uuid) != 36) {
        fail_test(__LINE__,
                  "uuid was %s, not right length (%d, should be 36), returned length %d",
                  uuid,
                  strlen(uuid),
                  l);
    }

    /* Make sure read error sets a suitable code. */
    xs_read_expected_error(__LINE__, "non_existent", ERROR_FILE_NOT_FOUND);
    xs_read_expected_error(__LINE__, "invalid\\path",
                           ERROR_INVALID_PARAMETER);
    xs_read_expected_error(__LINE__, "/local/domain/0/name",
                           ERROR_ACCESS_DENIED);

    /* Test basic xs_write functionality. */
    if (!xs_write(xs_handle, "data/test/key1", "data1")) {
        fail_test(__LINE__, "write data/test/key1 failed with %lx",
                  GetLastError());
    } else {
        t = xs_read(xs_handle, "data/test/key1", &l);
        if (!t) {
            fail_test(__LINE__, "error reading from data/test/key1: %lx",
                      GetLastError());
        } else {
            if (l != 5) {
                fail_test(__LINE__,
                          "manifest length wrong reading data/test/key1: %d should be 5.",
                          l);
            }
            if (strcmp(t, "data1")) {
                fail_test(__LINE__,
                          "got wrong data reading data/test/key1: %s should be data1.",
                          t);
            }
            free(t);
        }
    }

    xs_write_expected_error(__LINE__, "foo", "bar", ERROR_ACCESS_DENIED);
    xs_write_expected_error(__LINE__, "/foo", "bar", ERROR_ACCESS_DENIED);

    /* Try a very large write and make sure that it fails in the
       expected way. */
    t = malloc(65536);
    memset(t, 'a', 65536);
    t[65535] = 0;
    xs_write_expected_error(__LINE__,"data/test/key1", t,
                            ERROR_DISK_FULL);
    free(t);

    /* Test that read and write work for keys containing nul bytes. */
    if (!xs_write_bin(xs_handle, "data/test/key1", "xxx\0yyy", 7)) {
        fail_test(__LINE__, "failed to write nul bytes (%d)",
                  GetLastError());
    }
    t = xs_read(xs_handle, "data/test/key1", &l);
    if (!t) {
        fail_test(__LINE__, "failed to read nul bytes (%d)",
                  GetLastError());
    } else {
        if (l != 7) {
            fail_test(__LINE__, "read with nuls: expected 7, got %d.\n", l);
        } else if (memcmp(t, "xxx\0yyy", 7)) {
            fail_test(__LINE__, "bad data from read with nuls: %s",
                      t);
        }
        free(t);
    }

    if (!xs_remove(xs_handle, "data/test/key1")) {
        fail_test(__LINE__, "failed to remove data/test/key1 (%d)",
                  GetLastError());
    }

    xs_read_expected_error(__LINE__, "data/test/key1", ERROR_FILE_NOT_FOUND);

    xs_ls_expected_error(__LINE__, "data/test/key1", ERROR_FILE_NOT_FOUND);

    if (!xs_write(xs_handle, "data/test/key1", "data1")) {
        fail_test(__LINE__, "failed to rewrite data/test/key1");
    }

    contents = xs_directory(xs_handle, "data/test/key1", &count);
    if (!contents) {
        fail_test(__LINE__, "failed to ls data/test/key1: %x",
                  GetLastError());
    } else if (count != 0) {
        fail_test(__LINE__, "ls data/test/key1 had %d items", count);
        free(contents);
    } else {
        free(contents);
    }

    if (!xs_write(xs_handle, "data/test/key1/key2", "data2")) {
        fail_test(__LINE__, "failed to rewrite data/test/key1/key2");
    }

    contents = xs_directory(xs_handle, "data/test/key1", &count);
    if (!contents) {
        fail_test(__LINE__, "failed to ls data/test/key1: %x",
                  GetLastError());
    } else if (count != 1) {
        fail_test(__LINE__, "ls data/test/key1 had %d items", count);
        free(contents);
    } else if (strcmp(contents[0], "key2")) {
        fail_test(__LINE__, "ls data/test/key1 gave unexpected result %s",
                  contents[0]);
    }

    xs_remove(xs_handle, "data/test");

    /* Looks like most of the basic functionality works.  Try
     * transactions. */
    xs_handle2 = xs_domain_open();
    if (!xs_handle2) win_err(1, "couldn't re-open domain interface");

    if (!xs_write(xs_handle, "data/test/key1", "before"))
        fail_test(__LINE__, "failed to write to data/test/key1: %x",
                  GetLastError());
    if (!xs_transaction_start(xs_handle2))
        win_err(1, "couldn't open a transaction on second handle");
    if (!xs_write(xs_handle2, "data/test/key1", "after"))
        fail_test(__LINE__, "failed to write to data/test/key1 under transaction: %x",
                  GetLastError());
    if (!xs_transaction_end(xs_handle2, FALSE))
        fail_test(__LINE__, "failed to write to end transaction: %x",
                  GetLastError());
    if (strcmp(xs_read(xs_handle, "data/test/key1", NULL), "after"))
        fail_test(__LINE__, "transaction didn't stick");

    /* Now try aborting the transaction. */
    if (!xs_write(xs_handle, "data/test/key1", "before"))
        fail_test(__LINE__, "failed to write to data/test/key1: %x",
                  GetLastError());
    if (!xs_transaction_start(xs_handle2))
        win_err(1, "couldn't open a transaction on second handle");
    if (!xs_write(xs_handle2, "data/test/key1", "after"))
        fail_test(__LINE__, "failed to write to data/test/key1 under transaction: %x",
                  GetLastError());
    if (!xs_transaction_end(xs_handle2, TRUE))
        fail_test(__LINE__, "failed to write to end transaction: %x",
                  GetLastError());
    if (strcmp(xs_read(xs_handle, "data/test/key1", NULL), "before"))
        fail_test(__LINE__, "transaction didn't abort");

    /* Try to arrange that the transaction fails. */
    if (!xs_write(xs_handle, "data/test/key1", "before"))
        fail_test(__LINE__, "failed to write to data/test/key1: %x",
                  GetLastError());
    if (!xs_transaction_start(xs_handle2))
        win_err(1, "couldn't open a transaction on second handle");
    if (!xs_write(xs_handle2, "data/test/key1", "after"))
        fail_test(__LINE__, "failed to write to data/test/key1 under transaction: %x",
                  GetLastError());
    if (!xs_write(xs_handle, "data/test/key1", "other"))
        fail_test(__LINE__, "failed to write to data/test/key1: %x",
                  GetLastError());
    if (xs_transaction_end(xs_handle2, FALSE))
        fail_test(__LINE__, "transaction succeeded when it shouldn't",
                  GetLastError());
    if (strcmp(xs_read(xs_handle, "data/test/key1", NULL), "other"))
        fail_test(__LINE__, "transaction did something strange");


    if (!xs_write(xs_handle, "data/test/key1", "before1"))
        fail_test(__LINE__, "failed to write to data/test/key1: %x",
                  GetLastError());
    if (!xs_write(xs_handle, "data/test/key2", "before2"))
        fail_test(__LINE__, "failed to write to data/test/key2: %x",
                  GetLastError());
    if (!xs_transaction_start(xs_handle2))
        win_err(1, "couldn't open a transaction on second handle");
    if (!xs_write(xs_handle2, "data/test/key1", "after"))
        fail_test(__LINE__, "failed to write to data/test/key1 under transaction: %x",
                  GetLastError());
    t = xs_read(xs_handle2, "data/test/key2", NULL);
    if (!t) {
        fail_test(__LINE__,
                  "failed to read data/test/key2 under transaction: %x",
                  GetLastError());
    } else {
        if (strcmp(t, "before2"))
            fail_test(__LINE__,
                      "got wrong thing reading dtaa/test/key2 (%s)",
                      t);
        free(t);
    }
    if (!xs_write(xs_handle, "data/test/key2", "other"))
        fail_test(__LINE__, "failed to write to data/test/key1: %x",
                  GetLastError());
    if (xs_transaction_end(xs_handle2, FALSE))
        fail_test(__LINE__, "transaction succeeded when it shouldn't",
                  GetLastError());
    if (strcmp(xs_read(xs_handle, "data/test/key1", NULL), "before1"))
        fail_test(__LINE__, "transaction did something strange");

    xs_daemon_close(xs_handle2);

    /* Try a couple of transaction error cases. */
    xs_handle2 = xs_domain_open();
    if (!xs_handle2) win_err(1, "couldn't re-open domain interface a second time");
    if (!xs_transaction_start(xs_handle2))
        win_err(1, "couldn't open a transaction for re-test");
    if (xs_transaction_start(xs_handle2)) {
        fail_test(__LINE__, "openned two transactions on same handle");
    }
    xs_daemon_close(xs_handle2);

    xs_handle2 = xs_domain_open();
    if (!xs_handle2) win_err(1, "couldn't re-open domain interface a third time");
    if (xs_transaction_end(xs_handle2, FALSE)) {
        fail_test(__LINE__, "ended transaction without starting it");
    }
    if (!xs_transaction_start(xs_handle2))
        win_err(1, "couldn't open a transaction for re-test");
    if (!xs_transaction_end(xs_handle2, FALSE))
        fail_test(__LINE__, "failed to end transaction");
    if (xs_transaction_end(xs_handle2, FALSE)) {
        fail_test(__LINE__, "double-ended transaction");
    }
    xs_daemon_close(xs_handle2);


    /* Transactions appear to be working, at least in their most basic
       form.  Have a go at watches. */
    event = CreateEvent(NULL, FALSE, FALSE, NULL);
    watch_h = xs_watch(xs_handle, "data/test/key1", event);
    if (watch_h < 0) {
        fail_test(__LINE__, "couldn't watch data/test/key1");
    } else {
        while (WaitForSingleObject(event, 100) != WAIT_TIMEOUT)
            ;
        xs_write(xs_handle, "data/test/key1", "foo");
        if (WaitForSingleObject(event, INFINITE) != WAIT_OBJECT_0)
            fail_test(__LINE__, "failed wait for data/test/key1: %x",
                      GetLastError());
        xs_write(xs_handle, "data/test/key1", "foo");
        if (WaitForSingleObject(event, INFINITE) != WAIT_OBJECT_0)
            fail_test(__LINE__, "failed wait for data/test/key1: %x",
                      GetLastError());
        xs_write(xs_handle, "data/test/key1", "foo");
        if (WaitForSingleObject(event, INFINITE) != WAIT_OBJECT_0)
            fail_test(__LINE__, "failed wait for data/test/key1: %x",
                      GetLastError());
        status = WaitForSingleObject(event, 2000);
        if (status != WAIT_TIMEOUT)
            fail_test(__LINE__,
                      "should have timed out waiting for data/test/key1 (%d, %d)",
                      status,
                      GetLastError());

        if (!xs_unwatch(xs_handle, watch_h))
            fail_test(__LINE__, "failed to unwatch");
    }

    /* Create two watches on the same key, kill one of them, and then
       make sure that the other one still works. */
    watch_h = xs_watch(xs_handle, "data/test/key1/subkey", event);
    if (watch_h < 0) {
        fail_test(__LINE__, "couldn't watch data/test/key1/subkey");
    } else {
        event2 = CreateEvent(NULL, FALSE, FALSE, NULL);
        watch_h2 = xs_watch(xs_handle, "data/test/key1/subkey", event);
        if (watch_h2 < 0) {
            fail_test(__LINE__, "couldn't double watch data/test/key1/subkey");
        } else {
            if (!xs_unwatch(xs_handle, watch_h2))
                fail_test(__LINE__, "failed to unwatch h2");
            ResetEvent(event);
            xs_remove(xs_handle, "data/test/key1");
            if (WaitForSingleObject(event, 5000) != WAIT_OBJECT_0)
                fail_test(__LINE__, "failed wait for data/test/key1: %x",
                          GetLastError());
            if (!xs_unwatch(xs_handle, watch_h))
                fail_test(__LINE__, "failed to unwatch");
        }
    }

    /* Watch a node, then modify it in a transaction, and check that
       the watch fires. */
    watch_h = xs_watch(xs_handle, "data/test/key1", event);
    if (watch_h < 0) {
        fail_test(__LINE__, "couldn't watch data/test/key1");
    } else {
        for (i = 0; i < 100; i++) {
            ResetEvent(event);
            do {
                if (!xs_transaction_start(xs_handle))
                    win_err(1, "couldn't open a transaction for watch test");
                xs_write(xs_handle, "data/test/key1", "foo");
            } while (!xs_transaction_end(xs_handle, FALSE));
            if (WaitForSingleObject(event, 5000) != WAIT_OBJECT_0)
                fail_test(__LINE__, "failed wait for data/test/key1(%d): %x",
                          i, GetLastError());
        }
        if (!xs_unwatch(xs_handle, watch_h))
            fail_test(__LINE__, "failed to unwatch");
    }

    /* Make a lot of watches, make sure they all work. */
    test_many_watches();

    /* Try some different sized requests */
    test_write_sizes(4096);

    xs_daemon_close(xs_handle);

    run_stress();

    if (failed) {
        printf("failed\n");
        return 1;
    } else {
        printf("passed\n");
        return 0;
    }
}
Exemple #26
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;
}
Exemple #27
0
int main(int argc, char **argv)
{
	struct termios attr;
	int domid;
	char *sopt = "h";
	int ch;
	int opt_ind=0;
	struct option lopt[] = {
		{ "help",    0, 0, 'h' },
		{ 0 },

	};
	char *path;
	int spty, xsfd;
	struct xs_handle *xs;
	char *end;

	while((ch = getopt_long(argc, argv, sopt, lopt, &opt_ind)) != -1) {
		switch(ch) {
		case 'h':
			usage(argv[0]);
			exit(0);
			break;
		}
	}
	
	if ((argc - optind) != 1) {
		fprintf(stderr, "Invalid number of arguments\n");
		fprintf(stderr, "Try `%s --help' for more information.\n", 
			argv[0]);
		exit(EINVAL);
	}
	
	domid = strtol(argv[optind], &end, 10);
	if (end && *end) {
		fprintf(stderr, "Invalid DOMID `%s'\n", argv[optind]);
		fprintf(stderr, "Try `%s --help' for more information.\n",
			argv[0]);
		exit(EINVAL);
	}

	xs = xs_daemon_open();
	if (xs == NULL) {
		err(errno, "Could not contact XenStore");
	}

	signal(SIGTERM, sighandler);

	path = xs_get_domain_path(xs, domid);
	if (path == NULL)
		err(errno, "xs_get_domain_path()");
	path = realloc(path, strlen(path) + strlen("/console/tty") + 1);
	if (path == NULL)
		err(ENOMEM, "realloc");
	strcat(path, "/console/tty");

	/* FIXME consoled currently does not assume domain-0 doesn't have a
	   console which is good when we break domain-0 up.  To keep us
	   user friendly, we'll bail out here since no data will ever show
	   up on domain-0. */
	if (domid == 0) {
		fprintf(stderr, "Can't specify Domain-0\n");
		exit(EINVAL);
	}

	/* Set a watch on this domain's console pty */
	if (!xs_watch(xs, path, ""))
		err(errno, "Can't set watch for console pty");
	xsfd = xs_fileno(xs);

	/* Wait a little bit for tty to appear.  There is a race
	   condition that occurs after xend creates a domain.  This code
	   might be running before consoled has noticed the new domain
	   and setup a pty for it. */ 
        spty = get_pty_fd(xs, path, 5);
	if (spty == -1) {
		err(errno, "Could not read tty from store");
	}

	init_term(spty, &attr);
	init_term(STDIN_FILENO, &attr);
	console_loop(spty, xs, path);
	restore_term(STDIN_FILENO, &attr);

	free(path);
	return 0;
 }
Exemple #28
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");

}
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);
}