Example #1
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;
}
Example #2
0
File: xslib.c Project: euanh/sm
char *getval(struct xs_handle *h, const char *path)
{
	char *p = NULL;
	xs_transaction_t xth;
	unsigned int len;

        if ((xth = xs_transaction_start(h)) == XBT_NULL) {
                printf("unable to start xs trasanction\n");
                return p;
        }
	p = xs_read(h, xth, path, &len);
	xs_transaction_end(h, xth, 0);
	return p;
}
Example #3
0
File: libxl_dm.c Project: jsgf/xen
static int libxl__write_stub_dmargs(libxl__gc *gc,
                                    int dm_domid, int guest_domid,
                                    char **args)
{
    libxl_ctx *ctx = libxl__gc_owner(gc);
    int i;
    char *vm_path;
    char *dmargs, *path;
    int dmargs_size;
    struct xs_permissions roperm[2];
    xs_transaction_t t;

    roperm[0].id = 0;
    roperm[0].perms = XS_PERM_NONE;
    roperm[1].id = dm_domid;
    roperm[1].perms = XS_PERM_READ;

    vm_path = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "/local/domain/%d/vm", guest_domid));

    i = 0;
    dmargs_size = 0;
    while (args[i] != NULL) {
        dmargs_size = dmargs_size + strlen(args[i]) + 1;
        i++;
    }
    dmargs_size++;
    dmargs = (char *) malloc(dmargs_size);
    i = 1;
    dmargs[0] = '\0';
    while (args[i] != NULL) {
        if (strcmp(args[i], "-sdl") && strcmp(args[i], "-M") && strcmp(args[i], "xenfv")) {
            strcat(dmargs, " ");
            strcat(dmargs, args[i]);
        }
        i++;
    }
    path = libxl__sprintf(gc, "%s/image/dmargs", vm_path);

retry_transaction:
    t = xs_transaction_start(ctx->xsh);
    xs_write(ctx->xsh, t, path, dmargs, strlen(dmargs));
    xs_set_permissions(ctx->xsh, t, path, roperm, ARRAY_SIZE(roperm));
    xs_set_permissions(ctx->xsh, t, libxl__sprintf(gc, "%s/rtc/timeoffset", vm_path), roperm, ARRAY_SIZE(roperm));
    if (!xs_transaction_end(ctx->xsh, t, 0))
        if (errno == EAGAIN)
            goto retry_transaction;
    free(dmargs);
    return 0;
}
Example #4
0
File: xslib.c Project: euanh/sm
int setval(struct xs_handle *h, const char *path, const char *val)
{
        int ret = 0;
	xs_transaction_t xth;
	unsigned int len;

        if ((xth = xs_transaction_start(h)) == XBT_NULL) {
                printf("unable to start xs trasanction\n");
                return ret;
        }
	len = strlen(val);
	ret = (xs_write(h, xth, path, val, len)? 1 : 0);
	xs_transaction_end(h, xth, 0);
	return ret;
}
Example #5
0
char *xenstore_read(const char *format, ...)
{
    char                *buff = NULL;
    char                *ret = NULL;
    va_list             arg;
    xs_transaction_t    t;

    va_start(arg, format);
    vasprintf(&buff, format, arg);
    va_end(arg);
    t = xs_transaction_start(xs);
    ret = xs_read(xs, t, buff, NULL);
    xs_transaction_end(xs, t, false);
    free(buff);
    return ret;
}
Example #6
0
/*
 * Start XenStore transaction.
 * If successful, return @true.
 * On error, return @false and log error message.     		      .
 */
static bool begin_xs(void)
{
	int nretries = 0;

	if (xst != XS_TRANSACTION_NULL)
		fatal_msg("bug: begin_xs inside a transaction");

	for (;;)
	{
		xst = xs_transaction_start(xs);
		if (xst != XS_TRANSACTION_NULL)
			break;

		/*
		 * ENOSPC means too many concurrent transactions from the domain
		 */
		if (errno == ENOSPC)
		{
			if (++nretries > max_xs_retries)
			{
				error_perror("unable to start xenstore transaction (retry limit exceeded)");
				break;
			}

			retry_wait(nretries);
			debug_msg(2, "retrying to start xenstore transaction");
		}
		else
		{
			error_perror("unable to start xenstore transaction");
			break;
		}
	}

	if (xst != XS_TRANSACTION_NULL)
	{
		debug_msg(15, "started transaction");
		return true;
	}
	else
	{
		return false;
	}
}
Example #7
0
int clickos_stop(int domid, int configid)
{
	char *statuspath = NULL;

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

	asprintf(&statuspath, "/local/domain/%d/clickos/%d/status", domid, configid);

retry_stop:
	th = xs_transaction_start(xs);
	xenstore_write(statuspath, "Halted");
	if (!xs_transaction_end(xs, th, 0)) {
		if (errno == EAGAIN)
			goto retry_stop;
	}
	return 0;
}
Example #8
0
File: xslib.c Project: euanh/sm
int xs_exists(struct xs_handle *h, const char *path)
{
        char **d;
        unsigned int num;
        xs_transaction_t xth;

        if ((xth = xs_transaction_start(h)) == XBT_NULL) {
                printf("unable to start xs trasanction\n");
                return 0;
        }

        d = xs_directory(h, xth, path, &num);
        xs_transaction_end(h, xth, 0);
        if (!d)
                return 0;

        free(d);
        return 1;
}
Example #9
0
File: xslib.c Project: euanh/sm
char *dirlist(struct xs_handle *h, const char *path)
{
        char **d, *p, *ptr;
        xs_transaction_t xth;
	unsigned int num, j=0, count = 0;

	if ((p = calloc(1,MAXDIRBUF))==NULL) {
		printf("unable to allocate memory\n");
		return NULL;
	}
        if ((xth = xs_transaction_start(h)) == XBT_NULL) {
                printf("unable to start xs trasanction\n");
                return p;
        }

        d = xs_directory(h, xth, path, &num);
        xs_transaction_end(h, xth, 0);
        if (!d)
                return p;

	ptr = p;	
        while(j < num) {
		ptr = p + count;
		if ((count + strlen(d[j]) + 1) > MAXDIRBUF) {
			printf("Reached max dir entry\n");
			return p;
		}
		if (j) {
			*ptr = '|';
			*ptr++;
			count++;
		}
		count += sprintf(ptr, d[j]);
		j++;
	}

        free(d);
        return p;	
}
Example #10
0
int
xenstore_init(void)
{
	unsigned int len, domid;
	char *buf;
	char *end;

	xs = xs_domain_open();
	if (xs == NULL) {
		RTE_LOG(ERR, PMD,"%s: xs_domain_open failed\n", __func__);
		return -1;
	}
	buf = xs_read(xs, XBT_NULL, "domid", &len);
	if (buf == NULL) {
		RTE_LOG(ERR, PMD, "%s: failed read domid\n", __func__);
		return -1;
	}
	errno = 0;
	domid = strtoul(buf, &end, 0);
	if (errno != 0 || end == NULL || end == buf ||  domid == 0)
		return -1;

	RTE_LOG(INFO, PMD, "retrieved dom ID = %d\n", domid);

	dompath = xs_get_domain_path(xs, domid);
	if (dompath == NULL)
		return -1;

	xs_transaction_start(xs); /* When to stop transaction */

	if (is_xenstore_cleaned_up == 0) {
		if (xenstore_cleanup())
			return -1;
		is_xenstore_cleaned_up = 1;
	}

	return 0;
}
Example #11
0
File: libxl_dm.c Project: jsgf/xen
void libxl__spawn_local_dm(libxl__egc *egc, libxl__dm_spawn_state *dmss)
{
    /* convenience aliases */
    const int domid = dmss->guest_domid;
    libxl__domain_build_state *const state = dmss->build_state;
    libxl__spawn_state *const spawn = &dmss->spawn;

    STATE_AO_GC(dmss->spawn.ao);

    libxl_ctx *ctx = CTX;
    libxl_domain_config *guest_config = dmss->guest_config;
    const libxl_domain_create_info *c_info = &guest_config->c_info;
    const libxl_domain_build_info *b_info = &guest_config->b_info;
    const libxl_vnc_info *vnc = libxl__dm_vnc(guest_config);
    char *path, *logfile;
    int logfile_w, null;
    int rc;
    char **args, **arg;
    xs_transaction_t t;
    char *vm_path;
    char **pass_stuff;
    const char *dm;

    if (libxl_defbool_val(b_info->device_model_stubdomain)) {
        abort();
    }

    dm = libxl__domain_device_model(gc, b_info);
    if (!dm) {
        rc = ERROR_FAIL;
        goto out;
    }
    if (access(dm, X_OK) < 0) {
        LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR,
                         "device model %s is not executable", dm);
        rc = ERROR_FAIL;
        goto out;
    }
    args = libxl__build_device_model_args(gc, dm, domid, guest_config, state);
    if (!args) {
        rc = ERROR_FAIL;
        goto out;
    }

    if (b_info->type == LIBXL_DOMAIN_TYPE_HVM) {
        path = xs_get_domain_path(ctx->xsh, domid);
        libxl__xs_write(gc, XBT_NULL,
                        libxl__sprintf(gc, "%s/hvmloader/bios", path),
                        "%s", libxl_bios_type_to_string(b_info->u.hvm.bios));
        /* Disable relocating memory to make the MMIO hole larger
         * unless we're running qemu-traditional */
        libxl__xs_write(gc, XBT_NULL,
                        libxl__sprintf(gc,
                                       "%s/hvmloader/allow-memory-relocate",
                                       path),
                        "%d",
                        b_info->device_model_version==LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL);
        free(path);
    }

    path = libxl__sprintf(gc, "/local/domain/0/device-model/%d", domid);
    xs_mkdir(ctx->xsh, XBT_NULL, path);

    if (b_info->type == LIBXL_DOMAIN_TYPE_HVM &&
        b_info->device_model_version
        == LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL)
        libxl__xs_write(gc, XBT_NULL, libxl__sprintf(gc, "%s/disable_pf", path),
                    "%d", !libxl_defbool_val(b_info->u.hvm.xen_platform_pci));

    libxl_create_logfile(ctx,
                         libxl__sprintf(gc, "qemu-dm-%s", c_info->name),
                         &logfile);
    logfile_w = open(logfile, O_WRONLY|O_CREAT|O_APPEND, 0644);
    free(logfile);
    null = open("/dev/null", O_RDONLY);

    const char *dom_path = libxl__xs_get_dompath(gc, domid);
    spawn->pidpath = GCSPRINTF("%s/%s", dom_path, "image/device-model-pid");

    if (vnc && vnc->passwd) {
        /* This xenstore key will only be used by qemu-xen-traditionnal.
         * The code to supply vncpasswd to qemu-xen is later. */
retry_transaction:
        /* Find uuid and the write the vnc password to xenstore for qemu. */
        t = xs_transaction_start(ctx->xsh);
        vm_path = libxl__xs_read(gc,t,libxl__sprintf(gc, "%s/vm", dom_path));
        if (vm_path) {
            /* Now write the vncpassword into it. */
            pass_stuff = libxl__calloc(gc, 3, sizeof(char *));
            pass_stuff[0] = "vncpasswd";
            pass_stuff[1] = vnc->passwd;
            libxl__xs_writev(gc,t,vm_path,pass_stuff);
            if (!xs_transaction_end(ctx->xsh, t, 0))
                if (errno == EAGAIN)
                    goto retry_transaction;
        }
    }

    LIBXL__LOG(CTX, XTL_DEBUG, "Spawning device-model %s with arguments:", dm);
    for (arg = args; *arg; arg++)
        LIBXL__LOG(CTX, XTL_DEBUG, "  %s", *arg);

    spawn->what = GCSPRINTF("domain %d device model", domid);
    spawn->xspath = GCSPRINTF("/local/domain/0/device-model/%d/state", domid);
    spawn->timeout_ms = LIBXL_DEVICE_MODEL_START_TIMEOUT * 1000;
    spawn->pidpath = GCSPRINTF("%s/image/device-model-pid", dom_path);
    spawn->midproc_cb = libxl__spawn_record_pid;
    spawn->confirm_cb = device_model_confirm;
    spawn->failure_cb = device_model_startup_failed;
    spawn->detached_cb = device_model_detached;

    rc = libxl__spawn_spawn(egc, spawn);
    if (rc < 0)
        goto out_close;
    if (!rc) { /* inner child */
        setsid();
        libxl__exec(gc, null, logfile_w, logfile_w, dm, args, NULL);
    }

    rc = 0;

out_close:
    close(null);
    close(logfile_w);
out:
    if (rc)
        device_model_spawn_outcome(egc, dmss, rc);
}
Example #12
0
main(int argc, char **argv)
{
	int ret;
	pthread_t rcv_thread;
	uint64_t  threadid;
	uint32_t  redirect_input = 0;
	char      *parse_string;
	char send_buf[RSH_BUF_SIZE];
	char input_file_name[MAX_FILE_STRING];
	int option = 0;
	int target_endpoint = 0;
	int input_commands;
	int i,j;


	if (argc < 2) {
		printf("\n\nusage ... \n\n");
		printf("\tvxt_rsh <name>\n\n");
		return -1;
	}


	i = 1;
	j = 0;
	input_commands = 0;
	input_file_name[0] = '\0';
	parse_string = NULL;
	while(i < argc) {
		/*
		 * We may parse multiple flags or options into
		 * one token if there are no spaces.  Hence
		 * the while loop below.
		 */
		while ((i < argc) && (argv[i][j] != '\0')) {
			VXTPRINT(4, "switch on, %c\n", argv[i][j]);
			switch(argv[i][j]) {
			case '-': {
				if (option) {
					VXTPRINT(4, "double option \"-\"\n");
					return command_line_error();
				}
				option = 1;
				j++;
                                break;
                        }
			case 'I': {
				if (option == 1) {
					VXTPRINT(4, "case I, "
					         "Input redirection\n");
					parse_string = input_file_name;
				}
				/*
				 * We are now in an option parse
				 * for a string, go to the option
				 * string reader, we may not have a
				 * space to separate the option letter from
				 * its string.
				 */
				ret = vxtdb_parse_option_parm(argv, argc, 
				                              parse_string,
				                              &option,
				                              &i, &j);
				if (ret != 0) {
					return ret;
				}

				if (option == 0) {
					parse_string = NULL;
				}

				break;
			}
			default:
			{
				VXTPRINT(4, "default, i %d, j %d\n",i,j);
				if (option) {
					VXTPRINT(4, "in option parsing\n");
					if (parse_string == input_file_name) {
						VXTPRINT(4, "in filestring "
						         "aquisition\n");
						strncpy(parse_string,
						        &(argv[i][j]),
						        MAX_FILE_STRING);
						option = 0;
						j=0;
						i++;
						parse_string
						   [MAX_FILE_STRING - 1] = 0;
						parse_string = NULL;
						VXTPRINT(4, "finished getting "
						         "filename after "
							 "space\n");
						break;
					} else {
						printf("\n\nUnknown Option\n");
						return command_line_error();
					}
				} else {
					if (j != 0) {
						VXTPRINT(4, "starting in the"
						         "middle of default "
						         "string\n");
						return command_line_error();
					}
					if (target_endpoint != 0) {
						return command_line_error();
					}
					target_endpoint = 1;
					target_domain = atoi(&argv[i][j]);
					i++;
				}
			}
			if (i >= argc) {
				break;
			}
			}
		}
		option = 0;
			j = 0;
			i++;

	}


 	pthread_mutex_init(&rcv_sync_lock, NULL);
	pthread_cond_init(&rcv_sync_var, NULL);
					
	VXTPRINT(4, "redirect file name: %s\n", input_file_name);

	if (target_domain == 0) {
		/*
		 * Default connection to the HUB
		 */
		strncpy(target_uuid, VXTDB_DOM0_ENDPOINT, MAX_VXT_UUID); 
	} else {
		vxt_db_query_arg_t query_arg;
		int                authdev;

		VXTPRINT(3, "Open VxT Authorization Database\n");
		authdev = open("/dev/vxtdb-auth", O_RDWR);
		if(authdev < 0) {
			VXTPRINT(0, "\n\nFailed to open the Vxt authorization "
			         "database device\n\n");
			return -1;
		}
		query_arg.hub = 1;
		ioctl(authdev, VXT_AUTH_DB_QUERY, (void *)(long)&query_arg);
		if (!query_arg.hub) {
			/*
			 * Get the routing and authorization through the
			 * auth db intermediary.
			 */
			VXTPRINT(3, "We are not a hub, use default routing."
			         " If in future we utilize a physical device"
			         " With internal routing, code may go here\n");
			strncpy(target_uuid,
				VXTDB_DOM0_ENDPOINT, MAX_VXT_UUID); 
		} else {
#ifdef XSTOOLS
			struct xs_handle *xs;
			xs_transaction_t th;
			int len;
			char ep_id_path[32];
			char *xenstore_uuid_path;
	
			xs = xs_domain_open();
			if (!xs) {
				perror("xs_domain_open failure");
				return -1;
			}

			sprintf(ep_id_path, "/local/domain/%d/vm",
			        target_domain);
			th = xs_transaction_start(xs);
			xenstore_uuid_path = 
			   (char *) xs_read(xs, th, ep_id_path, &len);
			if (!xenstore_uuid_path) {
				VXTPRINT(0, "Target domain %d not valid. "
				         "Exiting...\n", target_domain);
				return -1;
			}
			strncpy(target_uuid,
			        &(xenstore_uuid_path[4]), MAX_VXT_UUID-4);
			free(xenstore_uuid_path);
			target_uuid[MAX_VXT_UUID-1] = 0;
			if(!xs_transaction_end(xs, th, 0)) {
	       	        	VXTPRINT(0,
				         "Could not read xenstore database\n");
				return -1;
			}
#else
			strncpy(target_uuid,
				VXTDB_DOM0_ENDPOINT, MAX_VXT_UUID); 
#endif
		}
        }



	vrsh_set_sig_handler();

	ret = vrsh_create_device(&vsock);
	if (ret != VXT_SUCCESS) {
		return -1;
	}

	vxt_mb();

        ret = pthread_create(&rcv_thread, NULL, 
	                     (void *) &rsh_rcv_thread, (void *)&vsock);

	if (ret == -1) {
		endwin();
		return -1;
	}


	/*
	 * Starting local interpreter
	 */
	while(TRUE) {
		char buf[1024];
		int vxt_send_len;
		int read_len;
		size_t len = 0;
		ssize_t read_size;
		
/*
		char *line = NULL;
		read_size = getline(&line, &len, stdin);
		VXTPRINT(4, "Picked up command: %s of length %d\n",
		         line, read_size);
*/

		if (strnlen(input_file_name, MAX_FILE_STRING) != 0) {
			input_commands = open(input_file_name, O_RDWR);
			if(input_commands < 0) {
				VXTPRINT(0, "\n\n\tFailed to open the Vxt "
				         "input redirection command file\n\n");
				return -1;
			}
			while ((read_len =
			        read(input_commands, &buf, 1024)) > 0) {
				vxt_send_len = read_len;
				while (vxt_send_len != 0) {
					ret =
					   vxt_send(vsock, buf,
					            &vxt_send_len,
					            VXT_SOCK_SIGNAL
					               | VXT_SOCK_WAIT);
					read_len -= vxt_send_len;
					vxt_send_len = read_len;
					
				}
			}

			pthread_mutex_lock(&rcv_sync_lock);
			pthread_cond_wait(&rcv_sync_var, &rcv_sync_lock);
			pthread_mutex_unlock(&rcv_sync_lock);
			return 0;
		}
		while ((read_len = read(STDOUT_FILENO, &buf, 1024)) > 0) {
		 	/*
			 * Local debug trace, writes stream bound for
			 * remote to stdout
	  		 *  write(STDOUT_FILENO, &buf, sendlen);
			 */
			vxt_send_len = read_len;
			while (vxt_send_len != 0) {
				ret = vxt_send(vsock, buf, &vxt_send_len,
				               VXT_SOCK_SIGNAL | VXT_SOCK_WAIT);
				read_len -= vxt_send_len;
				vxt_send_len = read_len;
				
			}
	 	}
	}


}
Example #13
0
int libxl__domain_make(libxl__gc *gc, libxl_domain_create_info *info,
                       uint32_t *domid)
{
    libxl_ctx *ctx = libxl__gc_owner(gc);
    int flags, ret, rc, nb_vm;
    char *uuid_string;
    char *dom_path, *vm_path, *libxl_path;
    struct xs_permissions roperm[2];
    struct xs_permissions rwperm[1];
    struct xs_permissions noperm[1];
    xs_transaction_t t = 0;
    xen_domain_handle_t handle;
    libxl_vminfo *vm_list;


    assert(!libxl_domid_valid_guest(*domid));

    uuid_string = libxl__uuid2string(gc, info->uuid);
    if (!uuid_string) {
        rc = ERROR_NOMEM;
        goto out;
    }

    flags = 0;
    if (info->type == LIBXL_DOMAIN_TYPE_HVM) {
        flags |= XEN_DOMCTL_CDF_hvm_guest;
        flags |= libxl_defbool_val(info->hap) ? XEN_DOMCTL_CDF_hap : 0;
        flags |= libxl_defbool_val(info->oos) ? 0 : XEN_DOMCTL_CDF_oos_off;
    }
    *domid = -1;

    /* Ultimately, handle is an array of 16 uint8_t, same as uuid */
    libxl_uuid_copy((libxl_uuid *)handle, &info->uuid);

    ret = xc_domain_create(ctx->xch, info->ssidref, handle, flags, domid);
    if (ret < 0) {
        LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, ret, "domain creation fail");
        rc = ERROR_FAIL;
        goto out;
    }

    ret = xc_cpupool_movedomain(ctx->xch, info->poolid, *domid);
    if (ret < 0) {
        LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, ret, "domain move fail");
        rc = ERROR_FAIL;
        goto out;
    }

    dom_path = libxl__xs_get_dompath(gc, *domid);
    if (!dom_path) {
        rc = ERROR_FAIL;
        goto out;
    }

    vm_path = libxl__sprintf(gc, "/vm/%s", uuid_string);
    if (!vm_path) {
        LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "cannot allocate create paths");
        rc = ERROR_FAIL;
        goto out;
    }

    libxl_path = libxl__xs_libxl_path(gc, *domid);
    if (!libxl_path) {
        rc = ERROR_FAIL;
        goto out;
    }

    noperm[0].id = 0;
    noperm[0].perms = XS_PERM_NONE;

    roperm[0].id = 0;
    roperm[0].perms = XS_PERM_NONE;
    roperm[1].id = *domid;
    roperm[1].perms = XS_PERM_READ;

    rwperm[0].id = *domid;
    rwperm[0].perms = XS_PERM_NONE;

retry_transaction:
    t = xs_transaction_start(ctx->xsh);

    xs_rm(ctx->xsh, t, dom_path);
    libxl__xs_mkdir(gc, t, dom_path, roperm, ARRAY_SIZE(roperm));

    xs_rm(ctx->xsh, t, vm_path);
    libxl__xs_mkdir(gc, t, vm_path, roperm, ARRAY_SIZE(roperm));

    xs_rm(ctx->xsh, t, libxl_path);
    libxl__xs_mkdir(gc, t, libxl_path, noperm, ARRAY_SIZE(noperm));

    xs_write(ctx->xsh, t, libxl__sprintf(gc, "%s/vm", dom_path), vm_path, strlen(vm_path));
    rc = libxl__domain_rename(gc, *domid, 0, info->name, t);
    if (rc)
        goto out;

    libxl__xs_mkdir(gc, t,
                    libxl__sprintf(gc, "%s/cpu", dom_path),
                    roperm, ARRAY_SIZE(roperm));
    libxl__xs_mkdir(gc, t,
                    libxl__sprintf(gc, "%s/memory", dom_path),
                    roperm, ARRAY_SIZE(roperm));
    libxl__xs_mkdir(gc, t,
                    libxl__sprintf(gc, "%s/device", dom_path),
                    roperm, ARRAY_SIZE(roperm));
    libxl__xs_mkdir(gc, t,
                    libxl__sprintf(gc, "%s/control", dom_path),
                    roperm, ARRAY_SIZE(roperm));
    if (info->type == LIBXL_DOMAIN_TYPE_HVM)
        libxl__xs_mkdir(gc, t,
                        libxl__sprintf(gc, "%s/hvmloader", dom_path),
                        roperm, ARRAY_SIZE(roperm));

    libxl__xs_mkdir(gc, t,
                    libxl__sprintf(gc, "%s/control/shutdown", dom_path),
                    rwperm, ARRAY_SIZE(rwperm));
    libxl__xs_mkdir(gc, t,
                    libxl__sprintf(gc, "%s/device/suspend/event-channel", dom_path),
                    rwperm, ARRAY_SIZE(rwperm));
    libxl__xs_mkdir(gc, t,
                    libxl__sprintf(gc, "%s/data", dom_path),
                    rwperm, ARRAY_SIZE(rwperm));
    if (info->type == LIBXL_DOMAIN_TYPE_HVM)
        libxl__xs_mkdir(gc, t,
            libxl__sprintf(gc, "%s/hvmloader/generation-id-address", dom_path),
                        rwperm, ARRAY_SIZE(rwperm));

                    vm_list = libxl_list_vm(ctx, &nb_vm);
    if (!vm_list) {
        LOG(ERROR, "cannot get number of running guests");
        rc = ERROR_FAIL;
        goto out;
    }
    libxl_vminfo_list_free(vm_list, nb_vm);
    int hotplug_setting = libxl__hotplug_settings(gc, t);
    if (hotplug_setting < 0) {
        LOG(ERROR, "unable to get current hotplug scripts execution setting");
        rc = ERROR_FAIL;
        goto out;
    }
    if (libxl_defbool_val(info->run_hotplug_scripts) != hotplug_setting &&
        (nb_vm - 1)) {
        LOG(ERROR, "cannot change hotplug execution option once set, "
                    "please shutdown all guests before changing it");
        rc = ERROR_FAIL;
        goto out;
    }

    if (libxl_defbool_val(info->run_hotplug_scripts)) {
        rc = libxl__xs_write_checked(gc, t, DISABLE_UDEV_PATH, "1");
        if (rc) {
            LOGE(ERROR, "unable to write %s = 1", DISABLE_UDEV_PATH);
            goto out;
        }
    } else {
        rc = libxl__xs_rm_checked(gc, t, DISABLE_UDEV_PATH);
        if (rc) {
            LOGE(ERROR, "unable to delete %s", DISABLE_UDEV_PATH);
            goto out;
        }
    }

    xs_write(ctx->xsh, t, libxl__sprintf(gc, "%s/uuid", vm_path), uuid_string, strlen(uuid_string));
    xs_write(ctx->xsh, t, libxl__sprintf(gc, "%s/name", vm_path), info->name, strlen(info->name));

    libxl__xs_writev(gc, t, dom_path, info->xsdata);
    libxl__xs_writev(gc, t, libxl__sprintf(gc, "%s/platform", dom_path), info->platformdata);

    xs_write(ctx->xsh, t, libxl__sprintf(gc, "%s/control/platform-feature-multiprocessor-suspend", dom_path), "1", 1);
    xs_write(ctx->xsh, t, libxl__sprintf(gc, "%s/control/platform-feature-xs_reset_watches", dom_path), "1", 1);
    if (!xs_transaction_end(ctx->xsh, t, 0)) {
        if (errno == EAGAIN) {
            t = 0;
            goto retry_transaction;
        }
        LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "domain creation "
                         "xenstore transaction commit failed");
        rc = ERROR_FAIL;
        goto out;
    }
    t = 0;

    rc = 0;
 out:
    if (t) xs_transaction_end(ctx->xsh, t, 1);
    return rc;
}
Example #14
0
/**
 * Returns 0 on success, a negative error code otherwise.
 */
static inline int
connect_frontend(vbd_t *device) {

    int err = 0;
    xs_transaction_t xst = XBT_NULL;
    bool abort_transaction = false;

    ASSERT(device);

    do {
        if (!(xst = xs_transaction_start(device->backend->xs))) {
            err = -errno;
            WARN(device, "failed to start transaction: %s\n", strerror(err));
            goto out;
        }

        abort_transaction = true;

        /*
         * FIXME blkback writes discard-granularity, discard-alignment,
         * discard-secure, feature-discard, feature-barrier but we don't.
         */

        /*
         * Write the number of sectors, sector size, and info to the
         * back-end path in XenStore so that the front-end creates a VBD
         * with the appropriate characteristics.
         */
        if ((err = tapback_device_printf(device, xst, "sector-size", true,
                        "%u", device->sector_size))) {
            WARN(device, "failed to write sector-size: %s\n", strerror(-err));
            break;
        }

        if ((err = tapback_device_printf(device, xst, "sectors", true, "%llu",
                        device->sectors))) {
            WARN(device, "failed to write sectors: %s\n", strerror(-err));
            break;
        }

        if ((err = tapback_device_printf(device, xst, "info", true, "%u",
                        device->info))) {
            WARN(device, "failed to write info: %s\n", strerror(-err));
            break;
        }

		abort_transaction = false;
        if (!xs_transaction_end(device->backend->xs, xst, 0)) {
            err = -errno;
            ASSERT(err);
        }
    } while (err == -EAGAIN);

    if (abort_transaction) {
        if (!xs_transaction_end(device->backend->xs, xst, 1)) {
            int err2 = errno;
            WARN(device, "failed to abort transaction: %s\n", strerror(err2));
        }
        goto out;
    }

    if (err) {
        WARN(device, "failed to end transaction: %s\n", strerror(-err));
        goto out;
    }

    err = -xenbus_switch_state(device, XenbusStateConnected);
    if (err)
        WARN(device, "failed to switch back-end state to connected: %s\n",
                strerror(-err));
out:
    return err;
}
Example #15
0
static int libxl__fill_dom0_memory_info(libxl__gc *gc, uint64_t *target_memkb,
                                        uint64_t *max_memkb)
{
    int rc;
    libxl_dominfo info;
    libxl_physinfo physinfo;
    char *target = NULL, *staticmax = NULL, *endptr = NULL;
    char *target_path = "/local/domain/0/memory/target";
    char *max_path = "/local/domain/0/memory/static-max";
    xs_transaction_t t;
    libxl_ctx *ctx = libxl__gc_owner(gc);

    libxl_dominfo_init(&info);

retry_transaction:
    t = xs_transaction_start(ctx->xsh);

    target = libxl__xs_read(gc, t, target_path);
    staticmax = libxl__xs_read(gc, t, max_path);
    if (target && staticmax) {
        rc = 0;
        goto out;
    }

    if (target) {
        *target_memkb = strtoull(target, &endptr, 10);
        if (*endptr != '\0') {
            LOGED(ERROR, 0, "Invalid memory target %s from %s\n", target,
                 target_path);
            rc = ERROR_FAIL;
            goto out;
        }
    }

    if (staticmax) {
        *max_memkb = strtoull(staticmax, &endptr, 10);
        if (*endptr != '\0') {
            LOGED(ERROR, 0, "Invalid memory static-max %s from %s\n",
                 staticmax,
                 max_path);
            rc = ERROR_FAIL;
            goto out;
        }
    }

    libxl_dominfo_dispose(&info);
    libxl_dominfo_init(&info);
    rc = libxl_domain_info(ctx, &info, 0);
    if (rc < 0)
        goto out;

    rc = libxl_get_physinfo(ctx, &physinfo);
    if (rc < 0)
        goto out;

    if (target == NULL) {
        libxl__xs_printf(gc, t, target_path, "%"PRIu64, info.current_memkb);
        *target_memkb = info.current_memkb;
    }
    if (staticmax == NULL) {
        libxl__xs_printf(gc, t, max_path, "%"PRIu64, info.max_memkb);
        *max_memkb = info.max_memkb;
    }

    rc = 0;

out:
    if (!xs_transaction_end(ctx->xsh, t, 0)) {
        if (errno == EAGAIN)
            goto retry_transaction;
        else
            rc = ERROR_FAIL;
    }

    libxl_dominfo_dispose(&info);
    return rc;
}
Example #16
0
int
main(int argc, char **argv)
{
    struct xs_handle *xsh;
    xs_transaction_t xth = XBT_NULL;
    int ret = 0, socket = 0;
    int prefix = 0;
    int tidy = 0;
    int upto = 0;
    int recurse = 0;
    int nr_watches = -1;
    int transaction;
    struct winsize ws;
    enum mode mode;

    const char *_command = strrchr(argv[0], '/');
    const char *command = _command ? &_command[1] : argv[0];
    int switch_argv = -1; /* which element of argv did we switch on */

    if (strncmp(command, "xenstore-", strlen("xenstore-")) == 0)
    {
	switch_argv = 0;
	command = command + strlen("xenstore-");
    }
    else if (argc < 2)
	usage(MODE_unknown, 0, argv[0]);
    else
    {
	command = argv[1];
	switch_argv = 1;
    }

    mode = lookup_mode(command);

    while (1) {
	int c, index = 0;
	static struct option long_options[] = {
	    {"help",    0, 0, 'h'},
	    {"flat",    0, 0, 'f'}, /* MODE_ls */
	    {"socket",  0, 0, 's'},
	    {"prefix",  0, 0, 'p'}, /* MODE_read || MODE_list || MODE_ls */
	    {"tidy",    0, 0, 't'}, /* MODE_rm */
	    {"upto",    0, 0, 'u'}, /* MODE_chmod */
	    {"recurse", 0, 0, 'r'}, /* MODE_chmod */
	    {"number",  1, 0, 'n'}, /* MODE_watch */
	    {0, 0, 0, 0}
	};

	c = getopt_long(argc - switch_argv, argv + switch_argv, "hfspturn:",
			long_options, &index);
	if (c == -1)
	    break;

	switch (c) {
	case 'h':
	    usage(mode, switch_argv, argv[0]);
	    /* NOTREACHED */
        case 'f':
	    if ( mode == MODE_ls ) {
		max_width = INT_MAX/2;
		desired_width = 0;
		show_whole_path = 1;
	    } else {
		usage(mode, switch_argv, argv[0]);
	    }
            break;
        case 's':
            socket = 1;
            break;
	case 'p':
	    if ( mode == MODE_read || mode == MODE_list || mode == MODE_ls )
		prefix = 1;
	    else
		usage(mode, switch_argv, argv[0]);
	    break;
	case 't':
	    if ( mode == MODE_rm )
		tidy = 1;
	    else
		usage(mode, switch_argv, argv[0]);
	    break;
	case 'u':
	    if ( mode == MODE_chmod )
		upto = 1;
	    else
		usage(mode, switch_argv, argv[0]);
	    break;
	case 'r':
	    if ( mode == MODE_chmod )
		recurse = 1;
	    else
		usage(mode, switch_argv, argv[0]);
	    break;
	case 'n':
	    if ( mode == MODE_watch )
		nr_watches = atoi(optarg);
	    else
		usage(mode, switch_argv, argv[0]);
	    break;
	}
    }

    switch (mode) {
    case MODE_ls:
	break;
    case MODE_write:
	if ((argc - switch_argv - optind) % 2 == 1) {
	    usage(mode, switch_argv, argv[0]);
	    /* NOTREACHED */
	}
	/* DROP-THRU */
    default:
	if (optind == argc - switch_argv) {
	    usage(mode, switch_argv, argv[0]);
	    /* NOTREACHED */
	}
    }

    switch (mode) {
    case MODE_read:
	transaction = (argc - switch_argv - optind) > 1;
	break;
    case MODE_write:
	transaction = (argc - switch_argv - optind) > 2;
	break;
    case MODE_ls:
    case MODE_watch:
	transaction = 0;
	break;
    default:
	transaction = 1;
	break;
    }

    if ( mode == MODE_ls )
    {
	memset(&ws, 0, sizeof(ws));
	ret = ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws);
	if (!ret)
	    max_width = ws.ws_col - 2;
    }

    xsh = xs_open(socket ? XS_OPEN_SOCKETONLY : 0);
    if (xsh == NULL) err(1, "xs_open");

again:
    if (transaction) {
	xth = xs_transaction_start(xsh);
	if (xth == XBT_NULL)
	    errx(1, "couldn't start transaction");
    }

    ret = perform(mode, optind, argc - switch_argv, argv + switch_argv, xsh, xth, prefix, tidy, upto, recurse, nr_watches);

    if (transaction && !xs_transaction_end(xsh, xth, ret)) {
	if (ret == 0 && errno == EAGAIN) {
	    output_pos = 0;
	    goto again;
	}
	errx(1, "couldn't end transaction");
    }

    if (output_pos)
	printf("%s", output_buf);

    return ret;
}
Example #17
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);
}
Example #18
0
/*
 * Populate Xenstore with the information about a usb device for this domain
 */
int
xenstore_create_usb(dominfo_t *domp, usbinfo_t *usbp)
{
  char *bepath, *fepath;
  char value[32];
  xs_transaction_t trans;

  xd_log(LOG_DEBUG, "Creating VUSB node for %d.%d",
	 usbp->usb_bus, usbp->usb_device);

  /*
   * Construct Xenstore paths for both the front and back ends.
   */
  fepath = xs_dev_fepath(domp, "vusb", usbp->usb_virtid);
  bepath = xs_dev_bepath(domp, "vusb", usbp->usb_virtid);

  for (;;) {
    trans = xs_transaction_start(xs_handle);

    /*
     * Make directories for both front and back ends
     */
    if (xs_add_dir(trans, bepath, 0, XS_PERM_NONE, domp->di_domid,
		   XS_PERM_READ))
      break;
    if (xs_add_dir(trans, fepath, domp->di_domid, XS_PERM_NONE, 0,
		   XS_PERM_READ))
      break;

    /*
     * Populate frontend device info
     */
    if (xs_set_keyval(trans, fepath, "backend-id", "0"))
      break;
    snprintf(value, sizeof (value), "%d", usbp->usb_virtid);
    if (xs_set_keyval(trans, fepath, "virtual-device", value))
      break;
    if (xs_set_keyval(trans, fepath, "backend", bepath))
      break;
    snprintf(value, sizeof (value), "%d", XB_INITTING);
    if (xs_set_keyval(trans, fepath, "state", value))
      break;

    /*
     * Populate backend device info
     */
    if (xs_set_keyval(trans, bepath, "domain", domp->di_name))
      break;
    if (xs_set_keyval(trans, bepath, "frontend", fepath))
      break;
    snprintf(value, sizeof (value), "%d", XB_INITTING);
    if (xs_set_keyval(trans, bepath, "state", value))
      break;
    if (xs_set_keyval(trans, bepath, "online", "1"))
      break;
    snprintf(value, sizeof (value), "%d", domp->di_domid);
    if (xs_set_keyval(trans, bepath, "frontend-id", value))
      break;
    snprintf(value, sizeof (value), "%d.%d", usbp->usb_bus,
	     usbp->usb_device);
    if (xs_set_keyval(trans, bepath, "physical-device", value))
      break;

    if (xs_transaction_end(xs_handle, trans, false) == false) {
      if (errno == EAGAIN)
	continue;
      break;
    }
    free(fepath);
    free(bepath);

    xd_log(LOG_DEBUG, "Finished creating VUSB node for %d.%d",
	   usbp->usb_bus, usbp->usb_device);

    return (0);
  }

  xs_transaction_end(xs_handle, trans, true);
  xd_log(LOG_ERR, "Failed to write usb info to XenStore");
  free(fepath);
  free(bepath);
  return (-1);
}
Example #19
0
static int libxl_create_stubdom(libxl_ctx *ctx,
                                libxl_device_model_info *info,
                                libxl_device_disk *disks, int num_disks,
                                libxl_device_nic *vifs, int num_vifs,
                                libxl_device_vfb *vfb,
                                libxl_device_vkb *vkb,
                                libxl__device_model_starting **starting_r)
{
    libxl__gc gc = LIBXL_INIT_GC(ctx);
    int i, num_console = STUBDOM_SPECIAL_CONSOLES, ret;
    libxl_device_console *console;
    libxl_domain_create_info c_info;
    libxl_domain_build_info b_info;
    libxl_domain_build_state state;
    uint32_t domid;
    char **args;
    struct xs_permissions perm[2];
    xs_transaction_t t;
    libxl__device_model_starting *dm_starting = 0;

    args = libxl_build_device_model_args(&gc, info, vifs, num_vifs);
    if (!args) {
        ret = ERROR_FAIL;
        goto out;
    }

    memset(&c_info, 0x00, sizeof(libxl_domain_create_info));
    c_info.hvm = 0;
    c_info.name = libxl__sprintf(&gc, "%s-dm", libxl__domid_to_name(&gc, info->domid));

    libxl_uuid_copy(&c_info.uuid, &info->uuid);

    memset(&b_info, 0x00, sizeof(libxl_domain_build_info));
    b_info.max_vcpus = 1;
    b_info.max_memkb = 32 * 1024;
    b_info.target_memkb = b_info.max_memkb;
    b_info.kernel.path = libxl__abs_path(&gc, "ioemu-stubdom.gz", libxl_xenfirmwaredir_path());
    b_info.u.pv.cmdline = libxl__sprintf(&gc, " -d %d", info->domid);
    b_info.u.pv.ramdisk.path = "";
    b_info.u.pv.features = "";
    b_info.hvm = 0;

    /* fixme: this function can leak the stubdom if it fails */

    ret = libxl__domain_make(ctx, &c_info, &domid);
    if (ret)
        goto out_free;
    ret = libxl__domain_build(ctx, &b_info, domid, &state);
    if (ret)
        goto out_free;

    libxl_write_dmargs(ctx, domid, info->domid, args);
    libxl__xs_write(&gc, XBT_NULL,
                   libxl__sprintf(&gc, "%s/image/device-model-domid", libxl__xs_get_dompath(&gc, info->domid)),
                   "%d", domid);
    libxl__xs_write(&gc, XBT_NULL,
                   libxl__sprintf(&gc, "%s/target", libxl__xs_get_dompath(&gc, domid)),
                   "%d", info->domid);
    ret = xc_domain_set_target(ctx->xch, domid, info->domid);
    if (ret<0) {
        LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "setting target domain %d -> %d", domid, info->domid);
        ret = ERROR_FAIL;
        goto out_free;
    }
    xs_set_target(ctx->xsh, domid, info->domid);

    perm[0].id = domid;
    perm[0].perms = XS_PERM_NONE;
    perm[1].id = info->domid;
    perm[1].perms = XS_PERM_READ;
retry_transaction:
    t = xs_transaction_start(ctx->xsh);
    xs_mkdir(ctx->xsh, t, libxl__sprintf(&gc, "/local/domain/0/device-model/%d", info->domid));
    xs_set_permissions(ctx->xsh, t, libxl__sprintf(&gc, "/local/domain/0/device-model/%d", info->domid), perm, ARRAY_SIZE(perm));
    xs_mkdir(ctx->xsh, t, libxl__sprintf(&gc, "/local/domain/%d/device/vfs", domid));
    xs_set_permissions(ctx->xsh, t, libxl__sprintf(&gc, "/local/domain/%d/device/vfs",domid), perm, ARRAY_SIZE(perm));
    if (!xs_transaction_end(ctx->xsh, t, 0))
        if (errno == EAGAIN)
            goto retry_transaction;

    for (i = 0; i < num_disks; i++) {
        disks[i].domid = domid;
        ret = libxl_device_disk_add(ctx, domid, &disks[i]);
        if (ret)
            goto out_free;
    }
    for (i = 0; i < num_vifs; i++) {
        vifs[i].domid = domid;
        ret = libxl_device_nic_add(ctx, domid, &vifs[i]);
        if (ret)
            goto out_free;
    }
    vfb->domid = domid;
    ret = libxl_device_vfb_add(ctx, domid, vfb);
    if (ret)
        goto out_free;
    vkb->domid = domid;
    ret = libxl_device_vkb_add(ctx, domid, vkb);
    if (ret)
        goto out_free;

    if (info->serial)
        num_console++;

    console = libxl__calloc(&gc, num_console, sizeof(libxl_device_console));
    if (!console) {
        ret = ERROR_NOMEM;
        goto out_free;
    }

    for (i = 0; i < num_console; i++) {
        console[i].devid = i;
        console[i].consback = LIBXL_CONSBACK_IOEMU;
        console[i].domid = domid;
        /* STUBDOM_CONSOLE_LOGGING (console 0) is for minios logging
         * STUBDOM_CONSOLE_SAVE (console 1) is for writing the save file
         * STUBDOM_CONSOLE_RESTORE (console 2) is for reading the save file
         */
        switch (i) {
            char *filename;
            char *name;
            case STUBDOM_CONSOLE_LOGGING:
                name = libxl__sprintf(&gc, "qemu-dm-%s", libxl_domid_to_name(ctx, info->domid));
                libxl_create_logfile(ctx, name, &filename);
                console[i].output = libxl__sprintf(&gc, "file:%s", filename);
                console[i].build_state = &state;
                free(filename);
                break;
            case STUBDOM_CONSOLE_SAVE:
                console[i].output = libxl__sprintf(&gc, "file:"SAVEFILE".%d", info->domid);
                break;
            case STUBDOM_CONSOLE_RESTORE:
                if (info->saved_state)
                    console[i].output = libxl__sprintf(&gc, "pipe:%s", info->saved_state);
                break;
            default:
                console[i].output = "pty";
                break;
        }
        ret = libxl_device_console_add(ctx, domid, &console[i]);
        if (ret)
            goto out_free;
    }
    if (libxl__create_xenpv_qemu(ctx, domid, vfb, &dm_starting) < 0) {
        ret = ERROR_FAIL;
        goto out_free;
    }
    if (libxl__confirm_device_model_startup(ctx, dm_starting) < 0) {
        ret = ERROR_FAIL;
        goto out_free;
    }

    libxl_domain_unpause(ctx, domid);

    if (starting_r) {
        *starting_r = calloc(sizeof(libxl__device_model_starting), 1);
        (*starting_r)->domid = info->domid;
        (*starting_r)->dom_path = libxl__xs_get_dompath(&gc, info->domid);
        (*starting_r)->for_spawn = NULL;
    }

    ret = 0;

out_free:
    free(args);
out:
    libxl__free_all(&gc);
    return ret;
}
Example #20
0
int clickos_start(int domid, const char *name, const char *script)
{
	const char *clickos_config_path_tail = "/config/";
	char clickos_script_chunk[1501];

	char *clickos_root_path = NULL;
	char *clickos_elem_path = NULL;
	char *clickos_ctl_path = NULL;
	char *clickos_config_name_path = NULL;
	char *clickos_config_path = NULL;
	char *clickos_status_path = NULL;
	char *clickos_router_path = NULL;
	int clickos_config_id = 0;
	default_domain_perms.id = domid;
	default_domain_perms.perms = XS_PERM_READ | XS_PERM_WRITE;

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

retry_clickos:
	// Transaction for ClickOS
	th = xs_transaction_start(xs);

	asprintf(&domain_root_path, "/local/domain/%d", domid);

	do {
		asprintf(&clickos_root_path, "%s/clickos/%d", domain_root_path, clickos_config_id);
		clickos_router_path = xenstore_read(clickos_root_path);
		if (clickos_router_path)
			clickos_config_id++;
	} while (clickos_router_path != NULL);

	asprintf(&clickos_elem_path, "%s/elements", clickos_root_path);
	asprintf(&clickos_ctl_path, "%s/control", clickos_root_path);
	asprintf(&clickos_config_name_path, "%s/config_name", clickos_root_path);
	asprintf(&clickos_status_path, "%s/status", clickos_root_path);

	xenstore_write(clickos_elem_path, "");
	xenstore_write(clickos_ctl_path, "");

	xenstore_chmod(clickos_elem_path, &default_domain_perms);
	xenstore_chmod(clickos_ctl_path, &default_domain_perms);

	xenstore_write(clickos_config_name_path, name);

	// we need one character for each chunk
	int config_path_len = strlen(clickos_root_path)
						  + strlen(clickos_config_path_tail) + 1;
	clickos_config_path = malloc(config_path_len + 1);
	int chunk = 0;
	int scriptSize = strlen(script);
	int remainingScriptSize = scriptSize;
	do {
		snprintf(clickos_config_path, config_path_len + 1, "%s%s%d",
				 clickos_root_path, clickos_config_path_tail, chunk);
		int chunkSize = MAX_CHUNK_LENGTH;
		if (remainingScriptSize < MAX_CHUNK_LENGTH) {
			chunkSize = remainingScriptSize;
		}
		memcpy(clickos_script_chunk, script + (chunk * MAX_CHUNK_LENGTH), chunkSize);
		clickos_script_chunk[chunkSize] = '\0';
		xenstore_write(clickos_config_path, clickos_script_chunk);
		chunk++;
		remainingScriptSize -= chunkSize;
	} while (remainingScriptSize > 0);

	if (!xs_transaction_end(xs, th, 0)) {
		if (errno == EAGAIN)
			goto retry_clickos;
	}

retry_status:
	// Transaction for ClickOS state
	th = xs_transaction_start(xs);

	xenstore_write(clickos_status_path, "Running");

	if (!xs_transaction_end(xs, th, 0)) {
		if (errno == EAGAIN)
			goto retry_status;
	}

	return 0;
}
Example #21
0
int libxl_set_memory_target(libxl_ctx *ctx, uint32_t domid,
        int64_t target_memkb, int relative, int enforce)
{
    GC_INIT(ctx);
    int rc, r, lrc, abort_transaction = 0;
    uint64_t memorykb, size;
    uint64_t videoram = 0;
    uint64_t current_target_memkb = 0, new_target_memkb = 0;
    uint64_t current_max_memkb = 0;
    char *memmax, *endptr, *videoram_s = NULL, *target = NULL;
    char *dompath = libxl__xs_get_dompath(gc, domid);
    xc_domaininfo_t info;
    libxl_dominfo ptr;
    char *uuid;
    xs_transaction_t t;
    libxl__domain_userdata_lock *lock;
    libxl_domain_config d_config;

    libxl_domain_config_init(&d_config);

    CTX_LOCK;

    lock = libxl__lock_domain_userdata(gc, domid);
    if (!lock) {
        rc = ERROR_LOCK_FAIL;
        goto out_no_transaction;
    }

    rc = libxl__get_domain_configuration(gc, domid, &d_config);
    if (rc < 0) {
        LOGE(ERROR, "unable to retrieve domain configuration");
        goto out_no_transaction;
    }

    rc = libxl__arch_extra_memory(gc, &d_config.b_info, &size);
    if (rc < 0) {
        LOGE(ERROR, "Couldn't get arch extra constant memory size");
        goto out_no_transaction;
    }

retry_transaction:
    t = xs_transaction_start(ctx->xsh);

    target = libxl__xs_read(gc, t, GCSPRINTF("%s/memory/target", dompath));
    if (!target && !domid) {
        if (!xs_transaction_end(ctx->xsh, t, 1)) {
            rc = ERROR_FAIL;
            goto out_no_transaction;
        }
        lrc = libxl__fill_dom0_memory_info(gc, &current_target_memkb,
                                           &current_max_memkb);
        if (lrc < 0) { rc = ERROR_FAIL; goto out_no_transaction; }
        goto retry_transaction;
    } else if (!target) {
        LOGED(ERROR, domid, "Cannot get target memory info from %s/memory/target",
              dompath);
        abort_transaction = 1;
        rc = ERROR_FAIL;
        goto out;
    } else {
        current_target_memkb = strtoull(target, &endptr, 10);
        if (*endptr != '\0') {
            LOGED(ERROR, domid, "Invalid memory target %s from %s/memory/target\n",
                  target, dompath);
            abort_transaction = 1;
            rc = ERROR_FAIL;
            goto out;
        }
    }
    memmax = libxl__xs_read(gc, t, GCSPRINTF("%s/memory/static-max", dompath));
    if (!memmax) {
        LOGED(ERROR, domid, "Cannot get memory info from %s/memory/static-max",
              dompath);
        abort_transaction = 1;
        rc = ERROR_FAIL;
        goto out;
    }
    memorykb = strtoull(memmax, &endptr, 10);
    if (*endptr != '\0') {
        LOGED(ERROR, domid, "Invalid max memory %s from %s/memory/static-max\n",
             memmax, dompath);
        abort_transaction = 1;
        rc = ERROR_FAIL;
        goto out;
    }

    videoram_s = libxl__xs_read(gc, t, GCSPRINTF("%s/memory/videoram",
                                                 dompath));
    videoram = videoram_s ? atoi(videoram_s) : 0;

    if (relative) {
        if (target_memkb < 0 && llabs(target_memkb) > current_target_memkb)
            new_target_memkb = 0;
        else
            new_target_memkb = current_target_memkb + target_memkb;
    } else
        new_target_memkb = target_memkb - videoram;
    if (new_target_memkb > memorykb) {
        LOGD(ERROR, domid,
             "memory_dynamic_max must be less than or equal to"
             " memory_static_max\n");
        abort_transaction = 1;
        rc = ERROR_INVAL;
        goto out;
    }

    if (!domid && new_target_memkb < LIBXL_MIN_DOM0_MEM) {
        LOGD(ERROR, domid,
             "New target %"PRIu64" for dom0 is below the minimum threshold",
             new_target_memkb);
        abort_transaction = 1;
        rc = ERROR_INVAL;
        goto out;
    }

    if (enforce) {
        memorykb = new_target_memkb + videoram;
        r = xc_domain_setmaxmem(ctx->xch, domid, memorykb + size);
        if (r != 0) {
            LOGED(ERROR, domid,
                  "xc_domain_setmaxmem memkb=%"PRIu64" failed ""rc=%d\n",
                  memorykb + size,
                  r);
            abort_transaction = 1;
            rc = ERROR_FAIL;
            goto out;
        }
    }

    r = xc_domain_set_pod_target(ctx->xch, domid,
            (new_target_memkb + size) / 4, NULL, NULL, NULL);
    if (r != 0) {
        LOGED(ERROR, domid,
              "xc_domain_set_pod_target memkb=%"PRIu64" failed rc=%d\n",
              (new_target_memkb + size) / 4,
              r);
        abort_transaction = 1;
        rc = ERROR_FAIL;
        goto out;
    }

    libxl__xs_printf(gc, t, GCSPRINTF("%s/memory/target", dompath),
                     "%"PRIu64, new_target_memkb);

    r = xc_domain_getinfolist(ctx->xch, domid, 1, &info);
    if (r != 1 || info.domain != domid) {
        abort_transaction = 1;
        rc = ERROR_FAIL;
        goto out;
    }

    libxl_dominfo_init(&ptr);
    libxl__xcinfo2xlinfo(ctx, &info, &ptr);
    uuid = libxl__uuid2string(gc, ptr.uuid);
    libxl__xs_printf(gc, t, GCSPRINTF("/vm/%s/memory", uuid),
                     "%"PRIu64, new_target_memkb / 1024);
    libxl_dominfo_dispose(&ptr);

    rc = 0;
out:
    if (!xs_transaction_end(ctx->xsh, t, abort_transaction)
        && !abort_transaction)
        if (errno == EAGAIN)
            goto retry_transaction;

out_no_transaction:
    libxl_domain_config_dispose(&d_config);
    if (lock) libxl__unlock_domain_userdata(lock);
    CTX_UNLOCK;
    GC_FREE;
    return rc;
}
Example #22
0
int libxl__create_device_model(libxl_ctx *ctx,
                              libxl_device_model_info *info,
                              libxl_device_disk *disks, int num_disks,
                              libxl_device_nic *vifs, int num_vifs,
                              libxl__device_model_starting **starting_r)
{
    libxl__gc gc = LIBXL_INIT_GC(ctx);
    char *path, *logfile;
    int logfile_w, null;
    int rc;
    char **args;
    libxl__device_model_starting buf_starting, *p;
    xs_transaction_t t; 
    char *vm_path;
    char **pass_stuff;

    if (strstr(info->device_model, "stubdom-dm")) {
        libxl_device_vfb vfb;
        libxl_device_vkb vkb;

        libxl_vfb_and_vkb_from_device_model_info(ctx, info, &vfb, &vkb);
        rc = libxl_create_stubdom(ctx, info, disks, num_disks, vifs, num_vifs, &vfb, &vkb, starting_r);
        goto out;
    }

    args = libxl_build_device_model_args(&gc, info, vifs, num_vifs);
    if (!args) {
        rc = ERROR_FAIL;
        goto out;
    }

    path = libxl__sprintf(&gc, "/local/domain/0/device-model/%d", info->domid);
    xs_mkdir(ctx->xsh, XBT_NULL, path);
    libxl__xs_write(&gc, XBT_NULL, libxl__sprintf(&gc, "%s/disable_pf", path), "%d", !info->xen_platform_pci);

    libxl_create_logfile(ctx, libxl__sprintf(&gc, "qemu-dm-%s", info->dom_name), &logfile);
    logfile_w = open(logfile, O_WRONLY|O_CREAT, 0644);
    free(logfile);
    null = open("/dev/null", O_RDONLY);

    if (starting_r) {
        rc = ERROR_NOMEM;
        *starting_r = calloc(sizeof(libxl__device_model_starting), 1);
        if (!*starting_r)
            goto out_close;
        p = *starting_r;
        p->for_spawn = calloc(sizeof(libxl__spawn_starting), 1);
    } else {
        p = &buf_starting;
        p->for_spawn = NULL;
    }

    p->domid = info->domid;
    p->dom_path = libxl__xs_get_dompath(&gc, info->domid);
    if (!p->dom_path) {
        rc = ERROR_FAIL;
        goto out_close;
    }

    if (info->vncpasswd) {
retry_transaction:
        /* Find uuid and the write the vnc password to xenstore for qemu. */
        t = xs_transaction_start(ctx->xsh);
        vm_path = libxl__xs_read(&gc,t,libxl__sprintf(&gc, "%s/vm", p->dom_path));
        if (vm_path) {
            /* Now write the vncpassword into it. */
            pass_stuff = libxl__calloc(&gc, 3, sizeof(char *));
            pass_stuff[0] = "vncpasswd";
            pass_stuff[1] = info->vncpasswd;
            libxl__xs_writev(&gc,t,vm_path,pass_stuff);
            if (!xs_transaction_end(ctx->xsh, t, 0))
                if (errno == EAGAIN)
                    goto retry_transaction;
        }
    }

    rc = libxl__spawn_spawn(ctx, p, "device model", dm_xenstore_record_pid);
    if (rc < 0)
        goto out_close;
    if (!rc) { /* inner child */
        setsid();
        libxl__exec(null, logfile_w, logfile_w,
                   libxl__abs_path(&gc, info->device_model, libxl_libexec_path()),
                   args);
    }

    rc = 0;

out_close:
    close(null);
    close(logfile_w);
    free(args);
out:
    libxl__free_all(&gc);
    return rc;
}
Example #23
0
/*
 * Preserves a domain but rewrites xenstore etc to make it unique so
 * that the domain can be restarted.
 *
 * Does not modify info so that it may be reused.
 */
int libxl_domain_preserve(libxl_ctx *ctx, uint32_t domid,
                          libxl_domain_create_info *info, const char *name_suffix, libxl_uuid new_uuid)
{
    GC_INIT(ctx);
    struct xs_permissions roperm[2];
    xs_transaction_t t;
    char *preserved_name;
    char *uuid_string;
    char *vm_path;
    char *dom_path;

    int rc;

    preserved_name = GCSPRINTF("%s%s", info->name, name_suffix);
    if (!preserved_name) {
        GC_FREE;
        return ERROR_NOMEM;
    }

    uuid_string = libxl__uuid2string(gc, new_uuid);
    if (!uuid_string) {
        GC_FREE;
        return ERROR_NOMEM;
    }

    dom_path = libxl__xs_get_dompath(gc, domid);
    if (!dom_path) {
        GC_FREE;
        return ERROR_FAIL;
    }

    vm_path = GCSPRINTF("/vm/%s", uuid_string);
    if (!vm_path) {
        GC_FREE;
        return ERROR_FAIL;
    }

    roperm[0].id = 0;
    roperm[0].perms = XS_PERM_NONE;
    roperm[1].id = domid;
    roperm[1].perms = XS_PERM_READ;

 retry_transaction:
    t = xs_transaction_start(ctx->xsh);

    xs_rm(ctx->xsh, t, vm_path);
    xs_mkdir(ctx->xsh, t, vm_path);
    xs_set_permissions(ctx->xsh, t, vm_path, roperm, ARRAY_SIZE(roperm));

    xs_write(ctx->xsh, t, GCSPRINTF("%s/vm", dom_path), vm_path, strlen(vm_path));
    rc = libxl__domain_rename(gc, domid, info->name, preserved_name, t);
    if (rc) {
        GC_FREE;
        return rc;
    }

    xs_write(ctx->xsh, t, GCSPRINTF("%s/uuid", vm_path), uuid_string, strlen(uuid_string));

    if (!xs_transaction_end(ctx->xsh, t, 0))
        if (errno == EAGAIN)
            goto retry_transaction;

    GC_FREE;
    return 0;
}
Example #24
0
File: libxl_dm.c Project: jsgf/xen
void libxl__spawn_stub_dm(libxl__egc *egc, libxl__stub_dm_spawn_state *sdss)
{
    STATE_AO_GC(sdss->dm.spawn.ao);
    libxl_ctx *ctx = libxl__gc_owner(gc);
    int ret;
    libxl_device_vfb *vfb;
    libxl_device_vkb *vkb;
    char **args;
    struct xs_permissions perm[2];
    xs_transaction_t t;

    /* convenience aliases */
    libxl_domain_config *const dm_config = &sdss->dm_config;
    libxl_domain_config *const guest_config = sdss->dm.guest_config;
    const int guest_domid = sdss->dm.guest_domid;
    libxl__domain_build_state *const d_state = sdss->dm.build_state;
    libxl__domain_build_state *const stubdom_state = &sdss->dm_state;

    if (guest_config->b_info.device_model_version !=
        LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL) {
        ret = ERROR_INVAL;
        goto out;
    }

    sdss->pvqemu.guest_domid = 0;

    libxl_domain_create_info_init(&dm_config->c_info);
    dm_config->c_info.type = LIBXL_DOMAIN_TYPE_PV;
    dm_config->c_info.name = libxl__stub_dm_name(gc,
                                    libxl__domid_to_name(gc, guest_domid));
    dm_config->c_info.ssidref = guest_config->b_info.device_model_ssidref;

    libxl_uuid_generate(&dm_config->c_info.uuid);

    libxl_domain_build_info_init(&dm_config->b_info);
    libxl_domain_build_info_init_type(&dm_config->b_info, LIBXL_DOMAIN_TYPE_PV);

    dm_config->b_info.max_vcpus = 1;
    dm_config->b_info.max_memkb = 32 * 1024;
    dm_config->b_info.target_memkb = dm_config->b_info.max_memkb;

    dm_config->b_info.u.pv.features = "";

    dm_config->b_info.device_model_version =
        guest_config->b_info.device_model_version;
    dm_config->b_info.device_model =
        guest_config->b_info.device_model;
    dm_config->b_info.extra = guest_config->b_info.extra;
    dm_config->b_info.extra_pv = guest_config->b_info.extra_pv;
    dm_config->b_info.extra_hvm = guest_config->b_info.extra_hvm;

    dm_config->disks = guest_config->disks;
    dm_config->num_disks = guest_config->num_disks;

    libxl__dm_vifs_from_hvm_guest_config(gc, guest_config, dm_config);

    dm_config->c_info.run_hotplug_scripts =
        guest_config->c_info.run_hotplug_scripts;

    ret = libxl__domain_create_info_setdefault(gc, &dm_config->c_info);
    if (ret) goto out;
    ret = libxl__domain_build_info_setdefault(gc, &dm_config->b_info);
    if (ret) goto out;

    GCNEW(vfb);
    GCNEW(vkb);
    libxl__vfb_and_vkb_from_hvm_guest_config(gc, guest_config, vfb, vkb);
    dm_config->vfbs = vfb;
    dm_config->num_vfbs = 1;
    dm_config->vkbs = vkb;
    dm_config->num_vkbs = 1;

    stubdom_state->pv_kernel.path
        = libxl__abs_path(gc, "ioemu-stubdom.gz", libxl__xenfirmwaredir_path());
    stubdom_state->pv_cmdline = libxl__sprintf(gc, " -d %d", guest_domid);
    stubdom_state->pv_ramdisk.path = "";

    /* fixme: this function can leak the stubdom if it fails */
    ret = libxl__domain_make(gc, &dm_config->c_info, &sdss->pvqemu.guest_domid);
    if (ret)
        goto out;
    uint32_t dm_domid = sdss->pvqemu.guest_domid;
    ret = libxl__domain_build(gc, dm_config, dm_domid, stubdom_state);
    if (ret)
        goto out;

    args = libxl__build_device_model_args(gc, "stubdom-dm", guest_domid,
                                          guest_config, d_state);
    if (!args) {
        ret = ERROR_FAIL;
        goto out;
    }

    libxl__write_stub_dmargs(gc, dm_domid, guest_domid, args);
    libxl__xs_write(gc, XBT_NULL,
                   libxl__sprintf(gc, "%s/image/device-model-domid",
                                  libxl__xs_get_dompath(gc, guest_domid)),
                   "%d", dm_domid);
    libxl__xs_write(gc, XBT_NULL,
                   libxl__sprintf(gc, "%s/target",
                                  libxl__xs_get_dompath(gc, dm_domid)),
                   "%d", guest_domid);
    ret = xc_domain_set_target(ctx->xch, dm_domid, guest_domid);
    if (ret<0) {
        LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR,
                         "setting target domain %d -> %d",
                         dm_domid, guest_domid);
        ret = ERROR_FAIL;
        goto out;
    }
    xs_set_target(ctx->xsh, dm_domid, guest_domid);

    perm[0].id = dm_domid;
    perm[0].perms = XS_PERM_NONE;
    perm[1].id = guest_domid;
    perm[1].perms = XS_PERM_READ;
retry_transaction:
    t = xs_transaction_start(ctx->xsh);
    xs_mkdir(ctx->xsh, t,
        libxl__sprintf(gc, "/local/domain/0/device-model/%d", guest_domid));
    xs_set_permissions(ctx->xsh, t,
        libxl__sprintf(gc, "/local/domain/0/device-model/%d", guest_domid),
                       perm, ARRAY_SIZE(perm));
    if (!xs_transaction_end(ctx->xsh, t, 0))
        if (errno == EAGAIN)
            goto retry_transaction;

    libxl__multidev_begin(ao, &sdss->multidev);
    sdss->multidev.callback = spawn_stub_launch_dm;
    libxl__add_disks(egc, ao, dm_domid, dm_config, &sdss->multidev);
    libxl__multidev_prepared(egc, &sdss->multidev, 0);

    return;

out:
    assert(ret);
    spawn_stubdom_pvqemu_cb(egc, &sdss->pvqemu, ret);
}
Example #25
0
int libxl__domain_rename(libxl__gc *gc, uint32_t domid,
                         const char *old_name, const char *new_name,
                         xs_transaction_t trans)
{
    libxl_ctx *ctx = libxl__gc_owner(gc);
    char *dom_path = 0;
    const char *name_path;
    char *got_old_name;
    unsigned int got_old_len;
    xs_transaction_t our_trans = 0;
    uint32_t stub_dm_domid;
    const char *stub_dm_old_name = NULL, *stub_dm_new_name = NULL;
    int rc;
    libxl_dominfo info;
    char *uuid;
    const char *vm_name_path;

    libxl_dominfo_init(&info);

    dom_path = libxl__xs_get_dompath(gc, domid);
    if (!dom_path) goto x_nomem;

    name_path= GCSPRINTF("%s/name", dom_path);
    if (!name_path) goto x_nomem;

    stub_dm_domid = libxl_get_stubdom_id(CTX, domid);
    if (stub_dm_domid) {
        stub_dm_old_name = libxl__stub_dm_name(gc, old_name);
        stub_dm_new_name = libxl__stub_dm_name(gc, new_name);
    }

 retry_transaction:
    if (!trans) {
        trans = our_trans = xs_transaction_start(ctx->xsh);
        if (!our_trans) {
            LOGEVD(ERROR, errno, domid, "Create xs transaction for domain (re)name");
            goto x_fail;
        }
    }

    if (!new_name) {
        LOGD(ERROR, domid, "New domain name not specified");
        rc = ERROR_INVAL;
        goto x_rc;
    }

    if (new_name[0]) {
        /* nonempty names must be unique */
        uint32_t domid_e;
        rc = libxl_name_to_domid(ctx, new_name, &domid_e);
        if (rc == ERROR_INVAL) {
            /* no such domain, good */
        } else if (rc != 0) {
            LOGD(ERROR, domid, "Unexpected error checking for existing domain");
            goto x_rc;
        } else if (domid_e == domid) {
            /* domain already has this name, ok (but we do still
             * need the rest of the code as we may need to check
             * old_name, for example). */
        } else {
            LOGD(ERROR, domid, "Domain with name \"%s\" already exists.", new_name);
            rc = ERROR_INVAL;
            goto x_rc;
        }
    }

    if (old_name) {
        got_old_name = xs_read(ctx->xsh, trans, name_path, &got_old_len);
        if (!got_old_name) {
            LOGEVD(ERROR, errno, domid,
                   "Check old name for domain allegedly named `%s'",
                   old_name);
            goto x_fail;
        }
        if (strcmp(old_name, got_old_name)) {
            LOGD(ERROR, domid,
                 "Allegedly named `%s' is actually named `%s' - racing ?",
                 old_name,
                 got_old_name);
            free(got_old_name);
            goto x_fail;
        }
        free(got_old_name);
    }
    if (!xs_write(ctx->xsh, trans, name_path,
                  new_name, strlen(new_name))) {
        LOGD(ERROR, domid,
             "Failed to write new name `%s'"
             " for domain previously named `%s'",
             new_name,
             old_name);
        goto x_fail;
    }

    /* update /vm/<uuid>/name */
    rc = libxl_domain_info(ctx, &info, domid);
    if (rc)
        goto x_rc;

    uuid = GCSPRINTF(LIBXL_UUID_FMT, LIBXL_UUID_BYTES(info.uuid));
    vm_name_path = GCSPRINTF("/vm/%s/name", uuid);
    if (libxl__xs_write_checked(gc, trans, vm_name_path, new_name))
        goto x_fail;

    if (stub_dm_domid) {
        rc = libxl__domain_rename(gc, stub_dm_domid,
                                  stub_dm_old_name,
                                  stub_dm_new_name,
                                  trans);
        if (rc) {
            LOGED(ERROR, domid, "Unable to rename stub-domain");
            goto x_rc;
        }
    }

    if (our_trans) {
        if (!xs_transaction_end(ctx->xsh, our_trans, 0)) {
            trans = our_trans = 0;
            if (errno != EAGAIN) {
                LOGD(ERROR, domid,
                     "Failed to commit new name `%s'"
                     " for domain previously named `%s'",
                     new_name,
                     old_name);
                goto x_fail;
            }
            LOGD(DEBUG, domid,
                 "Need to retry rename transaction"
                 " for domain (name_path=\"%s\", new_name=\"%s\")",
                 name_path,
                 new_name);
            goto retry_transaction;
        }
        our_trans = 0;
    }

    rc = 0;
 x_rc:
    if (our_trans) xs_transaction_end(ctx->xsh, our_trans, 1);
    libxl_dominfo_dispose(&info);
    return rc;

 x_fail:  rc = ERROR_FAIL;  goto x_rc;
 x_nomem: rc = ERROR_NOMEM; goto x_rc;
}
Example #26
0
int
xsd_provision_controller(struct xs_handle *xs, int domid) 
{
	xs_transaction_t t;

	struct xs_permissions xsperms[2];
	xsperms[0].id = domid;
	xsperms[0].perms = XS_PERM_READ | XS_PERM_WRITE;
	struct stat buf;
	char s[MAX_PATH];
	char s2[MAX_PATH];
	char domname[20];
	char backend[MAX_PATH];
	char frontend[MAX_PATH];
	int devno = 0;
	int result;
	char* home;
	char* dom0_home;
	int provision_status = 0;


	home = xs_get_domain_path(xs,domid);
	dom0_home = xs_get_domain_path(xs,0);

retry_provision:

	/* 
	printf("xsd_provision_controller Domain-%d, home %s, dom0_home %s\n",
	       domid, home, dom0_home);
	*/

	/*
	 *
	 * Create the vxtcom_controller records Dom0 and the
	 * target domain.  The code that follows will:
	 *
	 *
	 * Write the backend vxt controller entry and place it
	 * in Dom-0.  i.e. /local/domain/0 ..
 	 *
	 * backend = ""
	 *    vxtcom_ctrlr = ""
	 *       <Domain-id> (9) = ""
	 *          <Device-id> (0) = ""
	 *             domain = <Domain name> "Domain-9"
	 *             frontend = "/local/domain/9/device/vxtcom_ctrlr/0"
	 *             frontend-id = "9"
	 *             state = "3"
	 *             version = "1"
	 * 
	 *
	 * Write the front end record in the target domain device
	 * subdirectory:  ... e.g.
	 *
   	 * device = ""
	 *     vxtcom_ctrlr = ""
	 *      0 = ""
	 *       backend = "/local/domain/0/backend/vxtcom_ctrlr/9/0"
	 *       backend-id = "0"
	 *       state = "1"
	 */

	t = xs_transaction_start(xs);
	/*
	printf("xsd_provision_controller Domain-%d, transaction token %d\n",
	       domid, t);
	*/
	sprintf(backend, "%s/backend/vxtcom_ctrlr/%d/%d", dom0_home,
		    domid, devno);
	sprintf(frontend, "%s/device/vxtcom_ctrlr/%d", home, devno);

	/*
	 * Create Dom0 device directory for target domain:
	 * ../device/vxtcom_ctrlr/
	 */
	xs_mkdir(xs, t, backend);
	result = xs_set_permissions(xs, t, backend, xsperms, 1);
	/*
	printf("xsd_privision_controller: xs_set_permissions result %d\n",
	       result);
	*/

	/*
	 * create the target domain device record 
	 * /local/domain/<domain #>/device/vxtcom_ctrlr/<domain #>/backend = 
	 *              "/local/domain/0/backend/vxtcom_ctrlr/<domain #>/0"
	 *
	 */
	sprintf(s, "%s/backend", frontend);
	xs_write(xs, t, s, backend, strlen(backend));

	/*
	 * create target domian backend-id record: 
	 * /local/domain/<domain #>/device/vxtcom_ctrlr/<domain #>/backend = 0
	 *
	 */
	sprintf(s, "%s/backend-id", frontend);
	xs_write(xs, t, s, "0", 1);




	/*
	 * create target domian state record: 
	 * /local/domain/<domain #>/device/vxtcom_ctrlr/<domain #>/state = 1
	 *
	 */

	sprintf(s, "%s/state", frontend);
	xs_write(xs, t, s, "1", 1);

	/*
	 * create Dom0 domname (domain-name) record for target domain:
	 * /local/domain/0/backend/vxtcom_ctrlr/<domain#>/0/domname
	 *                                                = Domain-<domain#>
	 */
	sprintf(domname, "Domain-%d", domid);
	sprintf(s, "%s/domain", backend);
	xs_write(xs, t, s, domname, strlen(domname));

	/*
	 * Create Dom0 target vxtctlr device record - "frontend"
	 *
	 * /local/domain/0/device/vxtcom_ctrlr/9/0/frontend = 
	 *           /local/domain/<domain #>/device/vxtcom_ctrlr/0
	 *
	 */
	sprintf(s, "%s/frontend", backend);
	xs_write(xs, t, s, frontend, strlen(frontend));

	/*
	 * Create Dom0 target vxtctlr device record - "frontend-id"
	 *
	 * /local/domain/0/device/vxtcom_ctrlr/9/0/frontend-id = 
	 *           <domid>  e.g. 9
	 *
	 */
	sprintf(s, "%s/frontend-id", backend);
	sprintf(s2,"%d",domid);
	xs_write(xs, t, s, s2, strlen(s2));


	/*
	 * Create Dom0 target vxtctlr device record - "state"
	 *
	 * /local/domain/0/device/vxtcom_ctrlr/9/0/state = 1
	 *
	 */
	sprintf(s, "%s/state", backend);
	xs_write(xs, t, s, "1", 1);

	/*
	 * Create Dom0 target vxtctlr device record - "frontend"
	 *
	 * /local/domain/0/device/vxtcom_ctrlr/<domain #>/0/frontend = 
	 *                      /local/domain/<domain #>/device/vxtcom_ctrlr/0
	 *
	 */
	sprintf(s, "%s/frontend", backend);
	xs_write(xs, t, s, frontend, strlen(frontend));

	if(!xs_transaction_end(xs, t, 0)) {
		printf("xsd_privision_controller: xs_transaction_end failed\n");
		goto retry_provision;
	} else {
		provision_status = 1;
	}
	free(home);
	free(dom0_home);
	return (provision_status);
}
Example #27
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;
    }
}