debuggers.hg

annotate tools/libxl/libxl.c @ 22062:e5a9221bdd3f

tools/libxl: compile with -Wmissing-declarations

Since the recent build error caused by mismatch of symbol types due to
missing declarations, build libxl with -Wmissing-declarations.

The patch is mostly straightforward, a one liner in the makefile enables
the flag, a lot of functions in xl_cmdimpl.c needed to be made static
and libxl_paths.c needed to include libxl.h.

The one wart on the patch-set is that flex has a bug where it emits code
with missing declarations for yy(set|get)_column. This can be worked
around by providing the declarations ourselves regardless.

Signed-off-by: Gianni Tedesco <gianni.tedesco@citrix.com>
Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
author Ian Jackson <Ian.Jackson@eu.citrix.com>
date Tue Aug 17 17:20:53 2010 +0100 (2010-08-17)
parents 251dae6ee4a9
children 9a4acc688e9f
rev   line source
keir@20462 1 /*
keir@20462 2 * Copyright (C) 2009 Citrix Ltd.
keir@20462 3 * Author Vincent Hanquez <vincent.hanquez@eu.citrix.com>
keir@20462 4 * Author Stefano Stabellini <stefano.stabellini@eu.citrix.com>
keir@20462 5 *
keir@20462 6 * This program is free software; you can redistribute it and/or modify
keir@20462 7 * it under the terms of the GNU Lesser General Public License as published
keir@20462 8 * by the Free Software Foundation; version 2.1 only. with the special
keir@20462 9 * exception on linking described in file LICENSE.
keir@20462 10 *
keir@20462 11 * This program is distributed in the hope that it will be useful,
keir@20462 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
keir@20462 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
keir@20462 14 * GNU Lesser General Public License for more details.
keir@20462 15 */
keir@20462 16
keir@20513 17 #include "libxl_osdeps.h"
keir@20513 18
keir@20462 19 #include <stdio.h>
keir@20462 20 #include <string.h>
keir@20462 21 #include <stdlib.h>
keir@20462 22 #include <sys/types.h>
zhigang@21941 23 #include <sys/stat.h>
keir@20462 24 #include <fcntl.h>
keir@20462 25 #include <sys/select.h>
Ian@21848 26 #include <sys/mman.h>
keir@20514 27 #include <sys/wait.h>
ian@22032 28 #include <sys/time.h>
keir@20462 29 #include <signal.h>
keir@20468 30 #include <unistd.h> /* for write, unlink and close */
keir@20509 31 #include <stdint.h>
keir@20509 32 #include <inttypes.h>
keir@20514 33 #include <assert.h>
keir@20513 34
keir@20462 35 #include "libxl.h"
keir@20462 36 #include "libxl_utils.h"
keir@20462 37 #include "libxl_internal.h"
keir@20462 38 #include "flexarray.h"
keir@20462 39
keir@20860 40 #define PAGE_TO_MEMKB(pages) ((pages) * 4)
keir@20860 41
ian@21930 42 int libxl_ctx_init(libxl_ctx *ctx, int version, xentoollog_logger *lg)
keir@20462 43 {
keir@20788 44 if (version != LIBXL_VERSION)
keir@20788 45 return ERROR_VERSION;
ian@21930 46 memset(ctx, 0, sizeof(libxl_ctx));
keir@21532 47 ctx->lg = lg;
keir@21266 48 memset(&ctx->version_info, 0, sizeof(libxl_version_info));
keir@20462 49
keir@21532 50 ctx->xch = xc_interface_open(lg,lg,0);
keir@21529 51 if (!ctx->xch) {
keir@21681 52 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, errno,
keir@21681 53 "cannot open libxc handle");
keir@20819 54 return ERROR_FAIL;
keir@20819 55 }
keir@20819 56
keir@20462 57 ctx->xsh = xs_daemon_open();
keir@20819 58 if (!ctx->xsh) {
keir@21681 59 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, errno,
keir@21681 60 "cannot connect to xenstore");
keir@20819 61 xc_interface_close(ctx->xch);
keir@20819 62 return ERROR_FAIL;
keir@20819 63 }
keir@20462 64 return 0;
keir@20462 65 }
keir@20462 66
gianni@22008 67 static void do_free_version_info(libxl_version_info *info);
ian@21930 68 int libxl_ctx_free(libxl_ctx *ctx)
keir@20462 69 {
keir@20462 70 xc_interface_close(ctx->xch);
gianni@22008 71 do_free_version_info(&ctx->version_info);
keir@21186 72 if (ctx->xsh) xs_daemon_close(ctx->xsh);
keir@20462 73 return 0;
keir@20462 74 }
keir@20462 75
keir@20462 76 /******************************************************************************/
keir@20462 77
ian@21930 78 int libxl_domain_make(libxl_ctx *ctx, libxl_domain_create_info *info,
keir@20462 79 uint32_t *domid)
keir@20462 80 {
gianni@22023 81 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@21184 82 int flags, ret, i, rc;
keir@20468 83 char *uuid_string;
keir@20646 84 char *rw_paths[] = { "device", "device/suspend/event-channel" , "data"};
keir@20462 85 char *ro_paths[] = { "cpu", "memory", "device", "error", "drivers",
keir@20646 86 "control", "attr", "messages" };
ian@21894 87 char *dom_path, *vm_path;
keir@20462 88 struct xs_permissions roperm[2];
keir@20462 89 struct xs_permissions rwperm[1];
keir@20462 90 xs_transaction_t t;
keir@20468 91 xen_domain_handle_t handle;
keir@20462 92
gianni@22047 93 uuid_string = libxl_uuid2string(&gc, info->uuid);
gianni@22023 94 if (!uuid_string) {
gianni@22023 95 libxl_free_all(&gc);
gianni@22023 96 return ERROR_NOMEM;
gianni@22023 97 }
keir@20462 98
keir@20462 99 flags = info->hvm ? XEN_DOMCTL_CDF_hvm_guest : 0;
keir@20462 100 flags |= info->hap ? XEN_DOMCTL_CDF_hap : 0;
keir@21274 101 flags |= info->oos ? 0 : XEN_DOMCTL_CDF_oos_off;
keir@20824 102 *domid = -1;
keir@20462 103
keir@20580 104 /* Ultimately, handle is an array of 16 uint8_t, same as uuid */
keir@20580 105 memcpy(handle, info->uuid, sizeof(xen_domain_handle_t));
keir@20468 106
keir@20468 107 ret = xc_domain_create(ctx->xch, info->ssidref, handle, flags, domid);
keir@20462 108 if (ret < 0) {
keir@20512 109 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, ret, "domain creation fail");
gianni@22023 110 libxl_free_all(&gc);
keir@20462 111 return ERROR_FAIL;
keir@20462 112 }
keir@20462 113
keir@21368 114 ret = xc_cpupool_movedomain(ctx->xch, info->poolid, *domid);
keir@21368 115 if (ret < 0) {
keir@21368 116 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, ret, "domain move fail");
gianni@22023 117 libxl_free_all(&gc);
keir@21368 118 return ERROR_FAIL;
keir@21368 119 }
keir@21368 120
gianni@22023 121 dom_path = libxl_xs_get_dompath(&gc, *domid);
gianni@22023 122 if (!dom_path) {
gianni@22023 123 libxl_free_all(&gc);
keir@20512 124 return ERROR_FAIL;
gianni@22023 125 }
gianni@22023 126
gianni@22023 127 vm_path = libxl_sprintf(&gc, "/vm/%s", uuid_string);
ian@21894 128 if (!vm_path) {
keir@20462 129 XL_LOG(ctx, XL_LOG_ERROR, "cannot allocate create paths");
gianni@22023 130 libxl_free_all(&gc);
keir@20462 131 return ERROR_FAIL;
keir@20462 132 }
keir@20462 133
keir@20462 134 roperm[0].id = 0;
keir@20462 135 roperm[0].perms = XS_PERM_NONE;
keir@20462 136 roperm[1].id = *domid;
keir@20462 137 roperm[1].perms = XS_PERM_READ;
keir@20462 138 rwperm[0].id = *domid;
keir@20462 139 rwperm[0].perms = XS_PERM_NONE;
keir@20462 140
keir@20462 141 retry_transaction:
keir@20462 142 t = xs_transaction_start(ctx->xsh);
keir@20462 143 xs_rm(ctx->xsh, t, dom_path);
keir@20462 144 xs_mkdir(ctx->xsh, t, dom_path);
keir@20462 145 xs_set_permissions(ctx->xsh, t, dom_path, roperm, ARRAY_SIZE(roperm));
keir@20462 146
keir@20462 147 xs_rm(ctx->xsh, t, vm_path);
keir@20462 148 xs_mkdir(ctx->xsh, t, vm_path);
keir@20462 149 xs_set_permissions(ctx->xsh, t, vm_path, roperm, ARRAY_SIZE(roperm));
keir@20462 150
gianni@22023 151 xs_write(ctx->xsh, t, libxl_sprintf(&gc, "%s/vm", dom_path), vm_path, strlen(vm_path));
keir@21184 152 rc = libxl_domain_rename(ctx, *domid, 0, info->name, t);
gianni@22023 153 if (rc) {
gianni@22023 154 libxl_free_all(&gc);
gianni@22023 155 return rc;
gianni@22023 156 }
keir@20462 157
keir@20462 158 for (i = 0; i < ARRAY_SIZE(rw_paths); i++) {
gianni@22023 159 char *path = libxl_sprintf(&gc, "%s/%s", dom_path, rw_paths[i]);
keir@20462 160 xs_mkdir(ctx->xsh, t, path);
keir@20462 161 xs_set_permissions(ctx->xsh, t, path, rwperm, ARRAY_SIZE(rwperm));
keir@20462 162 }
keir@20462 163 for (i = 0; i < ARRAY_SIZE(ro_paths); i++) {
gianni@22023 164 char *path = libxl_sprintf(&gc, "%s/%s", dom_path, ro_paths[i]);
keir@20462 165 xs_mkdir(ctx->xsh, t, path);
keir@20462 166 xs_set_permissions(ctx->xsh, t, path, roperm, ARRAY_SIZE(roperm));
keir@20462 167 }
keir@20462 168
gianni@22023 169 xs_write(ctx->xsh, t, libxl_sprintf(&gc, "%s/uuid", vm_path), uuid_string, strlen(uuid_string));
gianni@22023 170 xs_write(ctx->xsh, t, libxl_sprintf(&gc, "%s/name", vm_path), info->name, strlen(info->name));
keir@21389 171 if (info->poolname)
gianni@22023 172 xs_write(ctx->xsh, t, libxl_sprintf(&gc, "%s/pool_name", vm_path), info->poolname, strlen(info->poolname));
gianni@22023 173
gianni@22023 174 libxl_xs_writev(&gc, t, dom_path, info->xsdata);
gianni@22023 175 libxl_xs_writev(&gc, t, libxl_sprintf(&gc, "%s/platform", dom_path), info->platformdata);
gianni@22023 176
gianni@22023 177 xs_write(ctx->xsh, t, libxl_sprintf(&gc, "%s/control/platform-feature-multiprocessor-suspend", dom_path), "1", 1);
keir@20462 178
keir@20462 179 if (!xs_transaction_end(ctx->xsh, t, 0))
keir@20462 180 if (errno == EAGAIN)
keir@20462 181 goto retry_transaction;
gianni@22023 182
gianni@22023 183 libxl_free_all(&gc);
keir@20462 184 return 0;
keir@20462 185 }
keir@20462 186
ian@21930 187 int libxl_domain_rename(libxl_ctx *ctx, uint32_t domid,
keir@21184 188 const char *old_name, const char *new_name,
gianni@22023 189 xs_transaction_t trans)
gianni@22023 190 {
gianni@22023 191 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@21184 192 char *dom_path = 0;
keir@21184 193 const char *name_path;
keir@21184 194 char *got_old_name;
keir@21184 195 unsigned int got_old_len;
keir@21184 196 xs_transaction_t our_trans = 0;
keir@21184 197 int rc;
keir@21184 198
gianni@22023 199 dom_path = libxl_xs_get_dompath(&gc, domid);
keir@21184 200 if (!dom_path) goto x_nomem;
keir@21184 201
gianni@22023 202 name_path= libxl_sprintf(&gc, "%s/name", dom_path);
keir@21184 203 if (!name_path) goto x_nomem;
keir@21184 204
keir@21184 205 retry_transaction:
keir@21184 206 if (!trans) {
keir@21184 207 trans = our_trans = xs_transaction_start(ctx->xsh);
keir@21184 208 if (!our_trans) {
keir@21184 209 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, errno,
keir@21184 210 "create xs transaction for domain (re)name");
keir@21184 211 goto x_fail;
keir@21184 212 }
keir@21184 213 }
keir@21184 214
keir@21184 215 if (old_name) {
keir@21184 216 got_old_name = xs_read(ctx->xsh, trans, name_path, &got_old_len);
keir@21184 217 if (!got_old_name) {
keir@21184 218 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, errno, "check old name"
keir@21184 219 " for domain %"PRIu32" allegedly named `%s'",
keir@21184 220 domid, old_name);
keir@21184 221 goto x_fail;
keir@21184 222 }
keir@21184 223 if (strcmp(old_name, got_old_name)) {
keir@21184 224 XL_LOG(ctx, XL_LOG_ERROR, "domain %"PRIu32" allegedly named "
keir@21184 225 "`%s' is actually named `%s' - racing ?",
keir@21184 226 domid, old_name, got_old_name);
keir@21184 227 free(got_old_name);
keir@21184 228 goto x_fail;
keir@21184 229 }
keir@21184 230 free(got_old_name);
keir@21184 231 }
keir@21184 232 if (!xs_write(ctx->xsh, trans, name_path,
keir@21184 233 new_name, strlen(new_name))) {
keir@21184 234 XL_LOG(ctx, XL_LOG_ERROR, "failed to write new name `%s'"
keir@21184 235 " for domain %"PRIu32" previously named `%s'",
keir@21531 236 new_name, domid, old_name);
keir@21184 237 goto x_fail;
keir@21184 238 }
keir@21184 239
keir@21184 240 if (our_trans) {
keir@21184 241 if (!xs_transaction_end(ctx->xsh, our_trans, 0)) {
keir@21184 242 trans = our_trans = 0;
keir@21184 243 if (errno != EAGAIN) {
keir@21184 244 XL_LOG(ctx, XL_LOG_ERROR, "failed to commit new name `%s'"
keir@21184 245 " for domain %"PRIu32" previously named `%s'",
keir@21531 246 new_name, domid, old_name);
keir@21184 247 goto x_fail;
keir@21184 248 }
keir@21184 249 XL_LOG(ctx, XL_LOG_DEBUG, "need to retry rename transaction"
keir@21184 250 " for domain %"PRIu32" (name_path=\"%s\", new_name=\"%s\")",
keir@21184 251 domid, name_path, new_name);
keir@21184 252 goto retry_transaction;
keir@21184 253 }
keir@21184 254 our_trans = 0;
keir@21184 255 }
keir@21184 256
keir@21184 257 rc = 0;
keir@21184 258 x_rc:
keir@21184 259 if (our_trans) xs_transaction_end(ctx->xsh, our_trans, 1);
gianni@22023 260 libxl_free_all(&gc);
keir@21184 261 return rc;
keir@21184 262
keir@21184 263 x_fail: rc = ERROR_FAIL; goto x_rc;
keir@21184 264 x_nomem: rc = ERROR_NOMEM; goto x_rc;
keir@21184 265 }
keir@21184 266
ian@21930 267 int libxl_domain_build(libxl_ctx *ctx, libxl_domain_build_info *info, uint32_t domid, libxl_domain_build_state *state)
keir@20462 268 {
gianni@22023 269 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@20462 270 char **vments = NULL, **localents = NULL;
keir@21438 271 struct timeval start_time;
keir@20829 272 int i, ret;
keir@20829 273
keir@20829 274 ret = build_pre(ctx, domid, info, state);
gianni@22023 275 if (ret)
gianni@22023 276 goto out;
keir@20462 277
keir@21438 278 gettimeofday(&start_time, NULL);
keir@21438 279
keir@20462 280 if (info->hvm) {
keir@20829 281 ret = build_hvm(ctx, domid, info, state);
gianni@22023 282 if (ret)
gianni@22023 283 goto out;
gianni@22023 284
gianni@22023 285 vments = libxl_calloc(&gc, 7, sizeof(char *));
keir@20516 286 vments[0] = "rtc/timeoffset";
keir@20516 287 vments[1] = (info->u.hvm.timeoffset) ? info->u.hvm.timeoffset : "";
keir@20516 288 vments[2] = "image/ostype";
keir@20516 289 vments[3] = "hvm";
keir@21438 290 vments[4] = "start_time";
gianni@22023 291 vments[5] = libxl_sprintf(&gc, "%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000);
keir@20462 292 } else {
keir@20829 293 ret = build_pv(ctx, domid, info, state);
gianni@22023 294 if (ret)
gianni@22023 295 goto out;
gianni@22023 296
gianni@22023 297 vments = libxl_calloc(&gc, 11, sizeof(char *));
keir@20578 298 i = 0;
keir@20578 299 vments[i++] = "image/ostype";
keir@20578 300 vments[i++] = "linux";
keir@20578 301 vments[i++] = "image/kernel";
Ian@21848 302 vments[i++] = (char*) info->kernel.path;
keir@21438 303 vments[i++] = "start_time";
gianni@22023 304 vments[i++] = libxl_sprintf(&gc, "%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000);
Ian@21848 305 if (info->u.pv.ramdisk.path) {
keir@20578 306 vments[i++] = "image/ramdisk";
Ian@21848 307 vments[i++] = (char*) info->u.pv.ramdisk.path;
keir@20578 308 }
keir@20578 309 if (info->u.pv.cmdline) {
keir@20578 310 vments[i++] = "image/cmdline";
keir@20578 311 vments[i++] = (char*) info->u.pv.cmdline;
keir@20578 312 }
keir@20462 313 }
keir@20829 314 ret = build_post(ctx, domid, info, state, vments, localents);
keir@20829 315 out:
Ian@21848 316 libxl_file_reference_unmap(ctx, &info->kernel);
Ian@21848 317 if (!info->hvm)
Ian@21848 318 libxl_file_reference_unmap(ctx, &info->u.pv.ramdisk);
Ian@21848 319
gianni@22023 320 libxl_free_all(&gc);
keir@20829 321 return ret;
keir@20462 322 }
keir@20462 323
ian@21930 324 int libxl_domain_restore(libxl_ctx *ctx, libxl_domain_build_info *info,
keir@20565 325 uint32_t domid, int fd, libxl_domain_build_state *state,
keir@20565 326 libxl_device_model_info *dm_info)
keir@20462 327 {
gianni@22023 328 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@20462 329 char **vments = NULL, **localents = NULL;
keir@21438 330 struct timeval start_time;
keir@21183 331 int i, ret, esave, flags;
keir@20462 332
keir@20829 333 ret = build_pre(ctx, domid, info, state);
gianni@22023 334 if (ret)
gianni@22023 335 goto out;
keir@20829 336
keir@20829 337 ret = restore_common(ctx, domid, info, state, fd);
gianni@22023 338 if (ret)
gianni@22023 339 goto out;
keir@20829 340
keir@21438 341 gettimeofday(&start_time, NULL);
keir@21438 342
keir@20462 343 if (info->hvm) {
gianni@22023 344 vments = libxl_calloc(&gc, 7, sizeof(char *));
keir@20516 345 vments[0] = "rtc/timeoffset";
keir@20516 346 vments[1] = (info->u.hvm.timeoffset) ? info->u.hvm.timeoffset : "";
keir@20565 347 vments[2] = "image/ostype";
keir@20565 348 vments[3] = "hvm";
keir@21438 349 vments[4] = "start_time";
gianni@22023 350 vments[5] = libxl_sprintf(&gc, "%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000);
keir@20462 351 } else {
gianni@22023 352 vments = libxl_calloc(&gc, 11, sizeof(char *));
keir@20627 353 i = 0;
keir@20627 354 vments[i++] = "image/ostype";
keir@20627 355 vments[i++] = "linux";
keir@20627 356 vments[i++] = "image/kernel";
Ian@21848 357 vments[i++] = (char*) info->kernel.path;
keir@21438 358 vments[i++] = "start_time";
gianni@22023 359 vments[i++] = libxl_sprintf(&gc, "%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000);
Ian@21848 360 if (info->u.pv.ramdisk.path) {
keir@20627 361 vments[i++] = "image/ramdisk";
Ian@21848 362 vments[i++] = (char*) info->u.pv.ramdisk.path;
keir@20627 363 }
keir@20627 364 if (info->u.pv.cmdline) {
keir@20627 365 vments[i++] = "image/cmdline";
keir@20627 366 vments[i++] = (char*) info->u.pv.cmdline;
keir@20627 367 }
keir@20462 368 }
keir@20829 369 ret = build_post(ctx, domid, info, state, vments, localents);
gianni@22023 370 if (ret)
gianni@22023 371 goto out;
keir@20829 372
keir@21417 373 dm_info->saved_state = NULL;
keir@21417 374 if (info->hvm) {
keir@21417 375 ret = asprintf(&dm_info->saved_state,
keir@21417 376 "/var/lib/xen/qemu-save.%d", domid);
keir@21417 377 ret = (ret < 0) ? ERROR_FAIL : 0;
keir@21417 378 }
keir@21417 379
keir@20829 380 out:
Ian@21848 381 libxl_file_reference_unmap(ctx, &info->kernel);
Ian@21848 382 if (!info->hvm)
Ian@21848 383 libxl_file_reference_unmap(ctx, &info->u.pv.ramdisk);
Ian@21848 384
keir@21183 385 esave = errno;
keir@21183 386
keir@21183 387 flags = fcntl(fd, F_GETFL);
keir@21183 388 if (flags == -1) {
keir@21183 389 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "unable to get flags on restore fd");
keir@21183 390 } else {
keir@21183 391 flags &= ~O_NONBLOCK;
keir@21183 392 if (fcntl(fd, F_SETFL, flags) == -1)
keir@21183 393 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "unable to put restore fd"
keir@21183 394 " back to blocking mode");
keir@21183 395 }
keir@21183 396
keir@21183 397 errno = esave;
gianni@22023 398 libxl_free_all(&gc);
keir@20829 399 return ret;
keir@20462 400 }
keir@20462 401
ian@21930 402 int libxl_domain_resume(libxl_ctx *ctx, uint32_t domid)
keir@20629 403 {
gianni@22023 404 libxl_gc gc = LIBXL_INIT_GC(ctx);
gianni@22023 405 int rc = 0;
gianni@22023 406
keir@20629 407 if (is_hvm(ctx, domid)) {
keir@20629 408 XL_LOG(ctx, XL_LOG_DEBUG, "Called domain_resume on "
keir@20629 409 "non-cooperative hvm domain %u", domid);
gianni@22023 410 rc = ERROR_NI;
gianni@22023 411 goto out;
keir@20629 412 }
keir@20629 413 if (xc_domain_resume(ctx->xch, domid, 1)) {
keir@20629 414 XL_LOG_ERRNO(ctx, XL_LOG_ERROR,
keir@20629 415 "xc_domain_resume failed for domain %u",
keir@20629 416 domid);
gianni@22023 417 rc = ERROR_FAIL;
gianni@22023 418 goto out;
keir@20629 419 }
keir@20629 420 if (!xs_resume_domain(ctx->xsh, domid)) {
keir@20629 421 XL_LOG_ERRNO(ctx, XL_LOG_ERROR,
keir@20629 422 "xs_resume_domain failed for domain %u",
keir@20629 423 domid);
gianni@22023 424 rc = ERROR_FAIL;
keir@20629 425 }
gianni@22023 426 out:
gianni@22023 427 libxl_free_all(&gc);
keir@20629 428 return 0;
keir@20629 429 }
keir@20629 430
ian@21920 431 /*
ian@21920 432 * Preserves a domain but rewrites xenstore etc to make it unique so
ian@21920 433 * that the domain can be restarted.
ian@21920 434 *
ian@21920 435 * Does not modify info so that it may be reused.
ian@21920 436 */
ian@21930 437 int libxl_domain_preserve(libxl_ctx *ctx, uint32_t domid,
Ian@21969 438 libxl_domain_create_info *info, const char *name_suffix, libxl_uuid new_uuid)
ian@21920 439 {
gianni@22023 440 libxl_gc gc = LIBXL_INIT_GC(ctx);
ian@21920 441 struct xs_permissions roperm[2];
ian@21920 442 xs_transaction_t t;
ian@21920 443 char *preserved_name;
ian@21920 444 char *uuid_string;
ian@21920 445 char *vm_path;
ian@21920 446 char *dom_path;
ian@21920 447
ian@21920 448 int rc;
ian@21920 449
gianni@22023 450 preserved_name = libxl_sprintf(&gc, "%s%s", info->name, name_suffix);
gianni@22023 451 if (!preserved_name) {
gianni@22023 452 libxl_free_all(&gc);
gianni@22023 453 return ERROR_NOMEM;
gianni@22023 454 }
ian@21920 455
gianni@22047 456 uuid_string = libxl_uuid2string(&gc, new_uuid);
gianni@22023 457 if (!uuid_string) {
gianni@22023 458 libxl_free_all(&gc);
gianni@22023 459 return ERROR_NOMEM;
gianni@22023 460 }
gianni@22023 461
gianni@22023 462 dom_path = libxl_xs_get_dompath(&gc, domid);
gianni@22023 463 if (!dom_path) {
gianni@22023 464 libxl_free_all(&gc);
gianni@22023 465 return ERROR_FAIL;
gianni@22023 466 }
gianni@22023 467
gianni@22023 468 vm_path = libxl_sprintf(&gc, "/vm/%s", uuid_string);
gianni@22023 469 if (!vm_path) {
gianni@22023 470 libxl_free_all(&gc);
gianni@22023 471 return ERROR_FAIL;
gianni@22023 472 }
ian@21920 473
ian@21920 474 roperm[0].id = 0;
ian@21920 475 roperm[0].perms = XS_PERM_NONE;
ian@21920 476 roperm[1].id = domid;
ian@21920 477 roperm[1].perms = XS_PERM_READ;
ian@21920 478
ian@21920 479 retry_transaction:
ian@21920 480 t = xs_transaction_start(ctx->xsh);
ian@21920 481
ian@21920 482 xs_rm(ctx->xsh, t, vm_path);
ian@21920 483 xs_mkdir(ctx->xsh, t, vm_path);
ian@21920 484 xs_set_permissions(ctx->xsh, t, vm_path, roperm, ARRAY_SIZE(roperm));
ian@21920 485
gianni@22023 486 xs_write(ctx->xsh, t, libxl_sprintf(&gc, "%s/vm", dom_path), vm_path, strlen(vm_path));
ian@21920 487 rc = libxl_domain_rename(ctx, domid, info->name, preserved_name, t);
ian@21920 488 if (rc) return rc;
ian@21920 489
gianni@22023 490 xs_write(ctx->xsh, t, libxl_sprintf(&gc, "%s/uuid", vm_path), uuid_string, strlen(uuid_string));
ian@21920 491
ian@21920 492 if (!xs_transaction_end(ctx->xsh, t, 0))
ian@21920 493 if (errno == EAGAIN)
ian@21920 494 goto retry_transaction;
ian@21920 495
gianni@22023 496 libxl_free_all(&gc);
ian@21920 497 return 0;
ian@21920 498 }
ian@21920 499
keir@21189 500 static void xcinfo2xlinfo(const xc_domaininfo_t *xcinfo,
ian@21930 501 libxl_dominfo *xlinfo)
ian@21895 502 {
keir@21189 503 memcpy(&(xlinfo->uuid), xcinfo->handle, sizeof(xen_domain_handle_t));
keir@21189 504 xlinfo->domid = xcinfo->domain;
keir@21189 505
ian@21895 506 xlinfo->dying = !!(xcinfo->flags&XEN_DOMINF_dying);
ian@21895 507 xlinfo->shutdown = !!(xcinfo->flags&XEN_DOMINF_shutdown);
ian@21895 508 xlinfo->paused = !!(xcinfo->flags&XEN_DOMINF_paused);
ian@21895 509 xlinfo->blocked = !!(xcinfo->flags&XEN_DOMINF_blocked);
ian@21895 510 xlinfo->running = !!(xcinfo->flags&XEN_DOMINF_running);
ian@21914 511
ian@21914 512 if (xlinfo->shutdown || xlinfo->dying)
ian@21914 513 xlinfo->shutdown_reason = (xcinfo->flags>>XEN_DOMINF_shutdownshift) & XEN_DOMINF_shutdownmask;
ian@21914 514 else
ian@21914 515 xlinfo->shutdown_reason = ~0;
ian@21895 516
keir@21189 517 xlinfo->max_memkb = PAGE_TO_MEMKB(xcinfo->tot_pages);
keir@21189 518 xlinfo->cpu_time = xcinfo->cpu_time;
keir@21189 519 xlinfo->vcpu_max_id = xcinfo->max_vcpu_id;
keir@21189 520 xlinfo->vcpu_online = xcinfo->nr_online_vcpus;
keir@21189 521 }
keir@21189 522
ian@21930 523 libxl_dominfo * libxl_list_domain(libxl_ctx *ctx, int *nb_domain)
keir@20462 524 {
ian@21930 525 libxl_dominfo *ptr;
keir@20867 526 int i, ret;
keir@20822 527 xc_domaininfo_t info[1024];
keir@20822 528 int size = 1024;
keir@20462 529
ian@21930 530 ptr = calloc(size, sizeof(libxl_dominfo));
gianni@21892 531 if (!ptr) {
gianni@21892 532 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "allocating domain info");
gianni@21892 533 return NULL;
gianni@21892 534 }
keir@20822 535
keir@20860 536 ret = xc_domain_getinfolist(ctx->xch, 0, 1024, info);
gianni@21892 537 if (ret<0) {
gianni@21892 538 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "geting domain info list");
gianni@21892 539 return NULL;
gianni@21892 540 }
keir@20784 541
keir@21189 542 for (i = 0; i < ret; i++) {
keir@21189 543 xcinfo2xlinfo(&info[i], &ptr[i]);
keir@20462 544 }
keir@20867 545 *nb_domain = ret;
keir@20462 546 return ptr;
keir@20462 547 }
keir@20462 548
ian@21930 549 int libxl_domain_info(libxl_ctx *ctx, libxl_dominfo *info_r,
keir@21189 550 uint32_t domid) {
keir@21189 551 xc_domaininfo_t xcinfo;
keir@21189 552 int ret;
keir@21189 553
keir@21189 554 ret = xc_domain_getinfolist(ctx->xch, domid, 1, &xcinfo);
gianni@21892 555 if (ret<0) {
gianni@21892 556 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "geting domain info list");
gianni@21892 557 return ERROR_FAIL;
gianni@21892 558 }
keir@21189 559 if (ret==0 || xcinfo.domain != domid) return ERROR_INVAL;
keir@21189 560
keir@21189 561 xcinfo2xlinfo(&xcinfo, info_r);
keir@21189 562 return 0;
keir@21189 563 }
keir@21189 564
ian@21930 565 libxl_poolinfo * libxl_list_pool(libxl_ctx *ctx, int *nb_pool)
keir@21368 566 {
ian@21930 567 libxl_poolinfo *ptr;
keir@21368 568 int i, ret;
keir@21368 569 xc_cpupoolinfo_t info[256];
keir@21368 570 int size = 256;
keir@21368 571
ian@21930 572 ptr = calloc(size, sizeof(libxl_poolinfo));
gianni@21892 573 if (!ptr) {
gianni@21892 574 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "allocating cpupool info");
gianni@21892 575 return NULL;
gianni@21892 576 }
keir@21368 577
keir@21368 578 ret = xc_cpupool_getinfo(ctx->xch, 0, 256, info);
gianni@21892 579 if (ret<0) {
gianni@21892 580 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "getting cpupool info");
gianni@21892 581 return NULL;
gianni@21892 582 }
keir@21368 583
keir@21368 584 for (i = 0; i < ret; i++) {
keir@21368 585 ptr[i].poolid = info[i].cpupool_id;
keir@21368 586 }
keir@21368 587 *nb_pool = ret;
keir@21368 588 return ptr;
keir@21368 589 }
keir@21368 590
keir@20860 591 /* this API call only list VM running on this host. a VM can be an aggregate of multiple domains. */
ian@21930 592 libxl_vminfo * libxl_list_vm(libxl_ctx *ctx, int *nb_vm)
keir@20860 593 {
ian@21930 594 libxl_vminfo *ptr;
keir@20860 595 int index, i, ret;
keir@20860 596 xc_domaininfo_t info[1024];
keir@20860 597 int size = 1024;
keir@20860 598
ian@21930 599 ptr = calloc(size, sizeof(libxl_dominfo));
keir@20860 600 if (!ptr)
keir@20860 601 return NULL;
keir@20860 602
keir@20860 603 ret = xc_domain_getinfolist(ctx->xch, 1, 1024, info);
gianni@21892 604 if (ret<0) {
gianni@21892 605 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "geting domain info list");
gianni@21892 606 return NULL;
gianni@21892 607 }
keir@20860 608 for (index = i = 0; i < ret; i++) {
keir@20860 609 if (libxl_is_stubdom(ctx, info[i].domain, NULL))
keir@20860 610 continue;
keir@20860 611 memcpy(&(ptr[index].uuid), info[i].handle, sizeof(xen_domain_handle_t));
keir@20860 612 ptr[index].domid = info[i].domain;
keir@20860 613
keir@20860 614 index++;
keir@20860 615 }
keir@20860 616 *nb_vm = index;
keir@20860 617 return ptr;
keir@20860 618 }
keir@20860 619
ian@21930 620 int libxl_domain_suspend(libxl_ctx *ctx, libxl_domain_suspend_info *info,
keir@20462 621 uint32_t domid, int fd)
keir@20462 622 {
keir@20565 623 int hvm = is_hvm(ctx, domid);
keir@20565 624 int live = info != NULL && info->flags & XL_SUSPEND_LIVE;
keir@21543 625 int debug = info != NULL && info->flags & XL_SUSPEND_DEBUG;
gianni@22023 626 int rc = 0;
keir@20462 627
keir@20462 628 core_suspend(ctx, domid, fd, hvm, live, debug);
keir@20565 629 if (hvm)
gianni@22023 630 rc = save_device_model(ctx, domid, fd);
gianni@22023 631 return rc;
keir@20462 632 }
keir@20462 633
ian@21930 634 int libxl_domain_pause(libxl_ctx *ctx, uint32_t domid)
keir@20462 635 {
gianni@21892 636 int ret;
gianni@21892 637 ret = xc_domain_pause(ctx->xch, domid);
gianni@21892 638 if (ret<0) {
gianni@21892 639 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "pausing domain %d", domid);
gianni@21892 640 return ERROR_FAIL;
gianni@21892 641 }
Ian@21888 642 return 0;
keir@20462 643 }
keir@20462 644
ian@21930 645 int libxl_domain_core_dump(libxl_ctx *ctx, uint32_t domid,
gianni@21892 646 const char *filename)
sstabellini@21870 647 {
gianni@21892 648 int ret;
gianni@21892 649 ret = xc_domain_dumpcore(ctx->xch, domid, filename);
gianni@21892 650 if (ret<0) {
gianni@21892 651 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "core dumping domain %d to %s",
gianni@21892 652 domid, filename);
Ian@21888 653 return ERROR_FAIL;
gianni@21892 654 }
Ian@21888 655 return 0;
sstabellini@21870 656 }
sstabellini@21870 657
ian@21930 658 int libxl_domain_unpause(libxl_ctx *ctx, uint32_t domid)
keir@20462 659 {
gianni@22023 660 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@20779 661 char *path;
keir@20565 662 char *state;
gianni@22023 663 int ret, rc = 0;
keir@20565 664
keir@20565 665 if (is_hvm(ctx, domid)) {
gianni@22023 666 path = libxl_sprintf(&gc, "/local/domain/0/device-model/%d/state", domid);
gianni@22023 667 state = libxl_xs_read(&gc, XBT_NULL, path);
keir@20565 668 if (state != NULL && !strcmp(state, "paused")) {
gianni@22023 669 libxl_xs_write(&gc, XBT_NULL, libxl_sprintf(&gc, "/local/domain/0/device-model/%d/command", domid), "continue");
keir@20565 670 libxl_wait_for_device_model(ctx, domid, "running", NULL, NULL);
keir@20565 671 }
keir@20565 672 }
gianni@21892 673 ret = xc_domain_unpause(ctx->xch, domid);
gianni@21892 674 if (ret<0) {
gianni@21892 675 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "unpausing domain %d", domid);
gianni@22023 676 rc = ERROR_FAIL;
gianni@21892 677 }
gianni@22023 678 libxl_free_all(&gc);
gianni@22023 679 return rc;
keir@20462 680 }
keir@20462 681
keir@20462 682 static char *req_table[] = {
keir@20462 683 [0] = "poweroff",
keir@20462 684 [1] = "reboot",
keir@20462 685 [2] = "suspend",
keir@20462 686 [3] = "crash",
keir@20462 687 [4] = "halt",
keir@20462 688 };
keir@20462 689
ian@21930 690 int libxl_domain_shutdown(libxl_ctx *ctx, uint32_t domid, int req)
keir@20462 691 {
gianni@22023 692 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@20462 693 char *shutdown_path;
keir@20462 694 char *dom_path;
keir@20462 695
gianni@22023 696 if (req > ARRAY_SIZE(req_table)) {
gianni@22023 697 libxl_free_all(&gc);
keir@20462 698 return ERROR_INVAL;
gianni@22023 699 }
gianni@22023 700
gianni@22023 701 dom_path = libxl_xs_get_dompath(&gc, domid);
gianni@22023 702 if (!dom_path) {
gianni@22023 703 libxl_free_all(&gc);
keir@20512 704 return ERROR_FAIL;
gianni@22023 705 }
gianni@22023 706
gianni@22023 707 shutdown_path = libxl_sprintf(&gc, "%s/control/shutdown", dom_path);
keir@20462 708
keir@20462 709 xs_write(ctx->xsh, XBT_NULL, shutdown_path, req_table[req], strlen(req_table[req]));
keir@21552 710 if (is_hvm(ctx,domid)) {
keir@20462 711 unsigned long acpi_s_state = 0;
keir@20462 712 unsigned long pvdriver = 0;
gianni@21892 713 int ret;
gianni@21892 714 ret = xc_get_hvm_param(ctx->xch, domid, HVM_PARAM_ACPI_S_STATE, &acpi_s_state);
gianni@21892 715 if (ret<0) {
gianni@21892 716 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "getting ACPI S-state");
gianni@21892 717 return ERROR_FAIL;
gianni@21892 718 }
gianni@21892 719 ret = xc_get_hvm_param(ctx->xch, domid, HVM_PARAM_CALLBACK_IRQ, &pvdriver);
gianni@21892 720 if (ret<0) {
gianni@21892 721 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "getting HVM callback IRQ");
gianni@21892 722 return ERROR_FAIL;
gianni@21892 723 }
gianni@21892 724 if (!pvdriver || acpi_s_state != 0) {
gianni@21892 725 ret = xc_domain_shutdown(ctx->xch, domid, req);
gianni@21892 726 if (ret<0) {
gianni@21892 727 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "unpausing domain");
gianni@21892 728 return ERROR_FAIL;
gianni@21892 729 }
gianni@21892 730 }
keir@20462 731 }
gianni@22023 732 libxl_free_all(&gc);
Ian@21888 733 return 0;
keir@20462 734 }
keir@20462 735
ian@21930 736 int libxl_get_wait_fd(libxl_ctx *ctx, int *fd)
keir@20545 737 {
keir@20545 738 *fd = xs_fileno(ctx->xsh);
keir@20545 739 return 0;
keir@20545 740 }
keir@20545 741
ian@21930 742 int libxl_wait_for_domain_death(libxl_ctx *ctx, uint32_t domid, libxl_waiter *waiter)
keir@20637 743 {
keir@20637 744 waiter->path = strdup("@releaseDomain");
ian@21913 745 if (asprintf(&(waiter->token), "%d", LIBXL_EVENT_DOMAIN_DEATH) < 0)
keir@21417 746 return -1;
keir@20637 747 if (!xs_watch(ctx->xsh, waiter->path, waiter->token))
keir@20637 748 return -1;
keir@20637 749 return 0;
keir@20637 750 }
keir@20637 751
ian@21930 752 int libxl_wait_for_disk_ejects(libxl_ctx *ctx, uint32_t guest_domid, libxl_device_disk *disks, int num_disks, libxl_waiter *waiter)
keir@20637 753 {
gianni@22023 754 libxl_gc gc = LIBXL_INIT_GC(ctx);
gianni@22023 755 int i, rc = -1;
keir@20637 756 uint32_t domid = libxl_get_stubdom_id(ctx, guest_domid);
keir@20637 757
keir@20637 758 if (!domid)
keir@20637 759 domid = guest_domid;
keir@20637 760
keir@20637 761 for (i = 0; i < num_disks; i++) {
keir@21417 762 if (asprintf(&(waiter[i].path), "%s/device/vbd/%d/eject",
gianni@22023 763 libxl_xs_get_dompath(&gc, domid),
keir@21417 764 device_disk_dev_number(disks[i].virtpath)) < 0)
gianni@22023 765 goto out;
ian@21913 766 if (asprintf(&(waiter[i].token), "%d", LIBXL_EVENT_DISK_EJECT) < 0)
gianni@22023 767 goto out;
keir@20637 768 xs_watch(ctx->xsh, waiter->path, waiter->token);
keir@20637 769 }
gianni@22023 770 rc = 0;
gianni@22023 771 out:
gianni@22023 772 libxl_free_all(&gc);
gianni@22023 773 return rc;
keir@20637 774 }
keir@20637 775
ian@21930 776 int libxl_get_event(libxl_ctx *ctx, libxl_event *event)
keir@20545 777 {
keir@20545 778 unsigned int num;
keir@20637 779 char **events = xs_read_watch(ctx->xsh, &num);
keir@20637 780 if (num != 2) {
keir@20637 781 free(events);
gianni@21892 782 return ERROR_FAIL;
keir@20637 783 }
keir@20637 784 event->path = strdup(events[XS_WATCH_PATH]);
keir@20637 785 event->token = strdup(events[XS_WATCH_TOKEN]);
keir@20637 786 event->type = atoi(event->token);
keir@20637 787 free(events);
keir@20637 788 return 0;
keir@20637 789 }
keir@20637 790
ian@21930 791 int libxl_stop_waiting(libxl_ctx *ctx, libxl_waiter *waiter)
keir@20637 792 {
keir@20637 793 if (!xs_unwatch(ctx->xsh, waiter->path, waiter->token))
gianni@21892 794 return ERROR_FAIL;
keir@20637 795 else
keir@20637 796 return 0;
keir@20637 797 }
keir@20637 798
keir@20637 799 int libxl_free_event(libxl_event *event)
keir@20637 800 {
keir@20637 801 free(event->path);
keir@20637 802 free(event->token);
keir@20637 803 return 0;
keir@20637 804 }
keir@20637 805
keir@20637 806 int libxl_free_waiter(libxl_waiter *waiter)
keir@20637 807 {
keir@20637 808 free(waiter->path);
keir@20637 809 free(waiter->token);
keir@20637 810 return 0;
keir@20637 811 }
keir@20637 812
ian@21930 813 int libxl_event_get_domain_death_info(libxl_ctx *ctx, uint32_t domid, libxl_event *event, libxl_dominfo *info)
keir@20637 814 {
ian@21916 815 if (libxl_domain_info(ctx, info, domid) < 0)
ian@21916 816 return 0;
ian@21916 817
ian@21916 818 if (info->running || (!info->shutdown && !info->dying))
ian@21916 819 return ERROR_INVAL;
ian@21916 820
ian@21916 821 return 1;
keir@20545 822 }
keir@20545 823
ian@21930 824 int libxl_event_get_disk_eject_info(libxl_ctx *ctx, uint32_t domid, libxl_event *event, libxl_device_disk *disk)
keir@20637 825 {
gianni@22023 826 libxl_gc gc = LIBXL_INIT_GC(ctx);
ian@21916 827 char *path;
ian@21916 828 char *backend;
ian@21916 829 char *value;
ian@21916 830
gianni@22023 831 value = libxl_xs_read(&gc, XBT_NULL, event->path);
gianni@22023 832
gianni@22023 833 if (!value || strcmp(value, "eject")) {
gianni@22023 834 libxl_free_all(&gc);
ian@21916 835 return 0;
gianni@22023 836 }
ian@21916 837
ian@21916 838 path = strdup(event->path);
ian@21916 839 path[strlen(path) - 6] = '\0';
gianni@22023 840 backend = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/backend", path));
ian@21916 841
ian@21916 842 disk->backend_domid = 0;
ian@21916 843 disk->domid = domid;
ian@21916 844 disk->physpath = NULL;
ian@21916 845 disk->phystype = 0;
ian@21916 846 /* this value is returned to the user: do not free right away */
gianni@22023 847 disk->virtpath = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/dev", backend));
ian@21916 848 disk->unpluggable = 1;
ian@21916 849 disk->readwrite = 0;
ian@21916 850 disk->is_cdrom = 1;
ian@21916 851
ian@21916 852 free(path);
gianni@22023 853 libxl_free_all(&gc);
ian@21916 854 return 1;
keir@20637 855 }
keir@20637 856
ian@21930 857 static int libxl_destroy_device_model(libxl_ctx *ctx, uint32_t domid)
keir@20462 858 {
gianni@22023 859 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@20462 860 char *pid;
keir@20462 861 int ret;
keir@20462 862
gianni@22023 863 pid = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "/local/domain/%d/image/device-model-pid", domid));
keir@20462 864 if (!pid) {
keir@20542 865 int stubdomid = libxl_get_stubdom_id(ctx, domid);
keir@20542 866 if (!stubdomid) {
keir@20542 867 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "Couldn't find device model's pid");
gianni@22023 868 ret = ERROR_INVAL;
gianni@22023 869 goto out;
keir@20542 870 }
keir@20542 871 XL_LOG(ctx, XL_LOG_ERROR, "Device model is a stubdom, domid=%d\n", stubdomid);
gianni@22023 872 ret = libxl_domain_destroy(ctx, stubdomid, 0);
gianni@22023 873 goto out;
keir@20462 874 }
gianni@22023 875 xs_rm(ctx->xsh, XBT_NULL, libxl_sprintf(&gc, "/local/domain/0/device-model/%d", domid));
keir@20462 876
keir@20462 877 ret = kill(atoi(pid), SIGHUP);
keir@20462 878 if (ret < 0 && errno == ESRCH) {
keir@20512 879 XL_LOG(ctx, XL_LOG_DEBUG, "Device Model already exited");
keir@20462 880 ret = 0;
keir@20462 881 } else if (ret == 0) {
keir@20512 882 XL_LOG(ctx, XL_LOG_DEBUG, "Device Model signaled");
keir@20462 883 ret = 0;
keir@20462 884 } else {
keir@20512 885 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "failed to kill Device Model [%d]",
keir@20512 886 atoi(pid));
keir@20462 887 }
gianni@22023 888 out:
gianni@22023 889 libxl_free_all(&gc);
keir@20462 890 return ret;
keir@20462 891 }
keir@20462 892
ian@21930 893 int libxl_domain_destroy(libxl_ctx *ctx, uint32_t domid, int force)
keir@20462 894 {
gianni@22023 895 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@20801 896 char *dom_path;
ian@21894 897 char *vm_path;
keir@20628 898 int rc, dm_present;
keir@20628 899
keir@20628 900 if (is_hvm(ctx, domid)) {
keir@20628 901 dm_present = 1;
keir@20628 902 } else {
keir@20628 903 char *pid;
gianni@22023 904 pid = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "/local/domain/%d/image/device-model-pid", domid));
keir@20628 905 dm_present = (pid != NULL);
keir@20628 906 }
keir@20462 907
gianni@22023 908 dom_path = libxl_xs_get_dompath(&gc, domid);
gianni@22023 909 if (!dom_path) {
gianni@22023 910 rc = ERROR_FAIL;
gianni@22023 911 goto out;
gianni@22023 912 }
keir@20512 913
keir@20482 914 if (libxl_device_pci_shutdown(ctx, domid) < 0)
keir@20512 915 XL_LOG(ctx, XL_LOG_ERROR, "pci shutdown failed for domid %d", domid);
keir@20628 916 if (dm_present) {
keir@20628 917 xs_write(ctx->xsh, XBT_NULL,
gianni@22023 918 libxl_sprintf(&gc, "/local/domain/0/device-model/%d/command", domid),
keir@20628 919 "shutdown", strlen("shutdown"));
keir@20628 920 }
keir@20512 921 rc = xc_domain_pause(ctx->xch, domid);
keir@20512 922 if (rc < 0) {
keir@20512 923 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_domain_pause failed for %d", domid);
keir@20462 924 }
keir@20628 925 if (dm_present) {
keir@20628 926 if (libxl_destroy_device_model(ctx, domid) < 0)
keir@20628 927 XL_LOG(ctx, XL_LOG_ERROR, "libxl_destroy_device_model failed for %d", domid);
keir@20628 928 }
keir@20462 929 if (libxl_devices_destroy(ctx, domid, force) < 0)
keir@20512 930 XL_LOG(ctx, XL_LOG_ERROR, "libxl_destroy_devices failed for %d", domid);
ian@21891 931
gianni@22023 932 vm_path = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/vm", dom_path));
keir@20823 933 if (vm_path)
keir@20823 934 if (!xs_rm(ctx->xsh, XBT_NULL, vm_path))
keir@20823 935 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xs_rm failed for %s", vm_path);
keir@20779 936
ian@21891 937 if (!xs_rm(ctx->xsh, XBT_NULL, dom_path))
ian@21891 938 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xs_rm failed for %s", dom_path);
ian@21891 939
keir@21190 940 libxl__userdata_destroyall(ctx, domid);
keir@21190 941
keir@20545 942 rc = xc_domain_destroy(ctx->xch, domid);
keir@20545 943 if (rc < 0) {
keir@20545 944 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc, "xc_domain_destroy failed for %d", domid);
gianni@22023 945 rc = ERROR_FAIL;
gianni@22023 946 goto out;
keir@20545 947 }
gianni@22023 948 rc = 0;
gianni@22023 949 out:
gianni@22023 950 libxl_free_all(&gc);
keir@20462 951 return 0;
keir@20462 952 }
keir@20462 953
stefano@22040 954 int libxl_console_exec(libxl_ctx *ctx, uint32_t domid, int cons_num, libxl_console_constype type)
keir@20564 955 {
gianni@22023 956 libxl_gc gc = LIBXL_INIT_GC(ctx);
gianni@22023 957 char *p = libxl_sprintf(&gc, "%s/xenconsole", libxl_private_bindir_path());
gianni@22023 958 char *domid_s = libxl_sprintf(&gc, "%d", domid);
gianni@22023 959 char *cons_num_s = libxl_sprintf(&gc, "%d", cons_num);
stefano@22040 960 char *cons_type_s;
stefano@22040 961
stefano@22040 962 if (type == LIBXL_CONSTYPE_PV)
stefano@22040 963 cons_type_s = "pv";
stefano@22040 964 else
stefano@22040 965 cons_type_s = "serial";
stefano@22040 966
stefano@22040 967 execl(p, p, domid_s, "--num", cons_num_s, "--type", cons_type_s, (void *)NULL);
gianni@22023 968 libxl_free_all(&gc);
gianni@22023 969 return ERROR_FAIL;
keir@20564 970 }
keir@20564 971
ian@21930 972 int libxl_primary_console_exec(libxl_ctx *ctx, uint32_t domid_vm)
sstabellini@21867 973 {
sstabellini@21867 974 uint32_t stubdomid = libxl_get_stubdom_id(ctx, domid_vm);
sstabellini@21867 975 if (stubdomid)
stefano@22040 976 return libxl_console_exec(ctx, stubdomid, 1, LIBXL_CONSTYPE_PV);
stefano@22040 977 else {
stefano@22040 978 if (is_hvm(ctx, domid_vm))
stefano@22040 979 return libxl_console_exec(ctx, domid_vm, 0, LIBXL_CONSTYPE_SERIAL);
stefano@22040 980 else
stefano@22040 981 return libxl_console_exec(ctx, domid_vm, 0, LIBXL_CONSTYPE_PV);
stefano@22040 982 }
sstabellini@21867 983 }
sstabellini@21867 984
ian@21930 985 int libxl_vncviewer_exec(libxl_ctx *ctx, uint32_t domid, int autopass)
sstabellini@21879 986 {
gianni@22023 987 libxl_gc gc = LIBXL_INIT_GC(ctx);
sstabellini@21879 988 const char *vnc_port, *vfb_back;
sstabellini@21879 989 const char *vnc_listen = NULL, *vnc_pass = NULL;
sstabellini@21879 990 int port = 0, autopass_fd = -1;
sstabellini@21879 991 char *vnc_bin, *args[] = {
sstabellini@21879 992 "vncviewer",
sstabellini@21879 993 NULL, /* hostname:display */
sstabellini@21879 994 NULL, /* -autopass */
sstabellini@21879 995 NULL,
sstabellini@21879 996 };
sstabellini@21879 997
gianni@22023 998 vnc_port = libxl_xs_read(&gc, XBT_NULL,
gianni@22023 999 libxl_sprintf(&gc,
sstabellini@21879 1000 "/local/domain/%d/console/vnc-port", domid));
sstabellini@21879 1001 if ( vnc_port )
sstabellini@21879 1002 port = atoi(vnc_port) - 5900;
sstabellini@21879 1003
gianni@22023 1004 vfb_back = libxl_xs_read(&gc, XBT_NULL,
gianni@22023 1005 libxl_sprintf(&gc,
sstabellini@21879 1006 "/local/domain/%d/device/vfb/0/backend", domid));
sstabellini@21879 1007 if ( vfb_back ) {
gianni@22023 1008 vnc_listen = libxl_xs_read(&gc, XBT_NULL,
gianni@22023 1009 libxl_sprintf(&gc,
sstabellini@21879 1010 "/local/domain/%d/console/vnc-listen", domid));
sstabellini@21879 1011 if ( autopass )
gianni@22023 1012 vnc_pass = libxl_xs_read(&gc, XBT_NULL,
gianni@22023 1013 libxl_sprintf(&gc,
sstabellini@21879 1014 "/local/domain/%d/console/vnc-pass", domid));
sstabellini@21879 1015 }
sstabellini@21879 1016
sstabellini@21879 1017 if ( NULL == vnc_listen )
sstabellini@21879 1018 vnc_listen = "localhost";
sstabellini@21879 1019
sstabellini@21879 1020 if ( (vnc_bin = getenv("VNCVIEWER")) )
sstabellini@21879 1021 args[0] = vnc_bin;
sstabellini@21879 1022
gianni@22023 1023 args[1] = libxl_sprintf(&gc, "%s:%d", vnc_listen, port);
sstabellini@21879 1024
sstabellini@21879 1025 if ( vnc_pass ) {
sstabellini@21879 1026 char tmpname[] = "/tmp/vncautopass.XXXXXX";
sstabellini@21879 1027 autopass_fd = mkstemp(tmpname);
sstabellini@21879 1028 if ( autopass_fd < 0 )
sstabellini@21879 1029 goto skip_autopass;
sstabellini@21879 1030
sstabellini@21879 1031 if ( unlink(tmpname) )
sstabellini@21879 1032 /* should never happen */
sstabellini@21879 1033 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "unlink %s failed", tmpname);
sstabellini@21879 1034
sstabellini@21879 1035 if ( libxl_write_exactly(ctx, autopass_fd, vnc_pass, strlen(vnc_pass),
sstabellini@21879 1036 tmpname, "vnc password") ) {
sstabellini@21879 1037 do { close(autopass_fd); } while(errno == EINTR);
sstabellini@21879 1038 goto skip_autopass;
sstabellini@21879 1039 }
sstabellini@21879 1040
sstabellini@21879 1041 args[2] = "-autopass";
sstabellini@21879 1042 }
sstabellini@21879 1043
sstabellini@21879 1044 skip_autopass:
gianni@22023 1045 libxl_free_all(&gc);
sstabellini@21879 1046 libxl_exec(autopass_fd, -1, -1, args[0], args);
sstabellini@21879 1047 return 0;
sstabellini@21879 1048 }
sstabellini@21879 1049
gianni@22023 1050 static char ** libxl_build_device_model_args_old(libxl_gc *gc,
keir@20462 1051 libxl_device_model_info *info,
keir@20462 1052 libxl_device_nic *vifs,
keir@20462 1053 int num_vifs)
keir@20462 1054 {
keir@20462 1055 int num = 0, i;
keir@20462 1056 flexarray_t *dm_args;
keir@20462 1057 dm_args = flexarray_make(16, 1);
gianni@22023 1058
keir@20462 1059 if (!dm_args)
keir@20462 1060 return NULL;
keir@20462 1061
keir@20516 1062 flexarray_set(dm_args, num++, "qemu-dm");
keir@20516 1063 flexarray_set(dm_args, num++, "-d");
keir@20462 1064
gianni@22023 1065 flexarray_set(dm_args, num++, libxl_sprintf(gc, "%d", info->domid));
keir@20462 1066
keir@20462 1067 if (info->dom_name) {
keir@20516 1068 flexarray_set(dm_args, num++, "-domain-name");
keir@20516 1069 flexarray_set(dm_args, num++, info->dom_name);
keir@20462 1070 }
keir@20462 1071 if (info->vnc || info->vncdisplay || info->vnclisten || info->vncunused) {
keir@20516 1072 flexarray_set(dm_args, num++, "-vnc");
keir@20462 1073 if (info->vncdisplay) {
keir@20462 1074 if (info->vnclisten && strchr(info->vnclisten, ':') == NULL) {
keir@21362 1075 flexarray_set(
keir@21362 1076 dm_args, num++,
gianni@22023 1077 libxl_sprintf(gc, "%s:%d%s",
keir@21362 1078 info->vnclisten,
keir@21362 1079 info->vncdisplay,
keir@21362 1080 info->vncpasswd ? ",password" : ""));
keir@20462 1081 } else {
gianni@22023 1082 flexarray_set(dm_args, num++, libxl_sprintf(gc, "127.0.0.1:%d", info->vncdisplay));
keir@20462 1083 }
keir@20462 1084 } else if (info->vnclisten) {
keir@20462 1085 if (strchr(info->vnclisten, ':') != NULL) {
keir@20516 1086 flexarray_set(dm_args, num++, info->vnclisten);
keir@20462 1087 } else {
gianni@22023 1088 flexarray_set(dm_args, num++, libxl_sprintf(gc, "%s:0", info->vnclisten));
keir@20462 1089 }
keir@20462 1090 } else {
keir@20516 1091 flexarray_set(dm_args, num++, "127.0.0.1:0");
keir@20462 1092 }
keir@20462 1093 if (info->vncunused) {
keir@20516 1094 flexarray_set(dm_args, num++, "-vncunused");
keir@20462 1095 }
keir@20462 1096 }
keir@21378 1097 if (info->sdl) {
keir@20516 1098 flexarray_set(dm_args, num++, "-sdl");
keir@20462 1099 if (info->opengl) {
keir@20516 1100 flexarray_set(dm_args, num++, "-disable-opengl");
keir@20462 1101 }
keir@20462 1102 }
keir@20462 1103 if (info->keymap) {
keir@20516 1104 flexarray_set(dm_args, num++, "-k");
keir@20516 1105 flexarray_set(dm_args, num++, info->keymap);
keir@20462 1106 }
keir@20462 1107 if (info->nographic && (!info->sdl && !info->vnc)) {
keir@20516 1108 flexarray_set(dm_args, num++, "-nographic");
keir@20462 1109 }
keir@20462 1110 if (info->serial) {
keir@20516 1111 flexarray_set(dm_args, num++, "-serial");
keir@20516 1112 flexarray_set(dm_args, num++, info->serial);
keir@20462 1113 }
keir@20509 1114 if (info->type == XENFV) {
Ian@21733 1115 int ioemu_vifs = 0;
Ian@21733 1116
keir@20509 1117 if (info->videoram) {
keir@20516 1118 flexarray_set(dm_args, num++, "-videoram");
gianni@22023 1119 flexarray_set(dm_args, num++, libxl_sprintf(gc, "%d", info->videoram));
keir@20509 1120 }
keir@20509 1121 if (info->stdvga) {
keir@20516 1122 flexarray_set(dm_args, num++, "-std-vga");
keir@20509 1123 }
keir@20509 1124
keir@20509 1125 if (info->boot) {
keir@20516 1126 flexarray_set(dm_args, num++, "-boot");
keir@20516 1127 flexarray_set(dm_args, num++, info->boot);
keir@20509 1128 }
stefano@21890 1129 if (info->usb || info->usbdevice) {
keir@20516 1130 flexarray_set(dm_args, num++, "-usb");
keir@20509 1131 if (info->usbdevice) {
keir@20516 1132 flexarray_set(dm_args, num++, "-usbdevice");
keir@20516 1133 flexarray_set(dm_args, num++, info->usbdevice);
keir@20509 1134 }
keir@20509 1135 }
Ian@21801 1136 if (info->soundhw) {
Ian@21801 1137 flexarray_set(dm_args, num++, "-soundhw");
Ian@21801 1138 flexarray_set(dm_args, num++, info->soundhw);
Ian@21801 1139 }
keir@20509 1140 if (info->apic) {
keir@20516 1141 flexarray_set(dm_args, num++, "-acpi");
keir@20509 1142 }
keir@21570 1143 if (info->vcpus > 1) {
keir@21570 1144 flexarray_set(dm_args, num++, "-vcpus");
gianni@22023 1145 flexarray_set(dm_args, num++, libxl_sprintf(gc, "%d", info->vcpus));
keir@21570 1146 }
keir@21570 1147 if (info->vcpu_avail) {
keir@21570 1148 flexarray_set(dm_args, num++, "-vcpu_avail");
gianni@22023 1149 flexarray_set(dm_args, num++, libxl_sprintf(gc, "0x%x", info->vcpu_avail));
keir@21570 1150 }
keir@20509 1151 for (i = 0; i < num_vifs; i++) {
keir@20509 1152 if (vifs[i].nictype == NICTYPE_IOEMU) {
gianni@22023 1153 char *smac = libxl_sprintf(gc, "%02x:%02x:%02x:%02x:%02x:%02x",
keir@20780 1154 vifs[i].mac[0], vifs[i].mac[1], vifs[i].mac[2],
keir@20780 1155 vifs[i].mac[3], vifs[i].mac[4], vifs[i].mac[5]);
keir@20781 1156 if (!vifs[i].ifname)
gianni@22023 1157 vifs[i].ifname = libxl_sprintf(gc, "tap%d.%d", info->domid, vifs[i].devid);
keir@20516 1158 flexarray_set(dm_args, num++, "-net");
gianni@22023 1159 flexarray_set(dm_args, num++, libxl_sprintf(gc, "nic,vlan=%d,macaddr=%s,model=%s",
keir@20780 1160 vifs[i].devid, smac, vifs[i].model));
keir@20516 1161 flexarray_set(dm_args, num++, "-net");
gianni@22023 1162 flexarray_set(dm_args, num++, libxl_sprintf(gc, "tap,vlan=%d,ifname=%s,bridge=%s,script=no",
keir@20509 1163 vifs[i].devid, vifs[i].ifname, vifs[i].bridge));
Ian@21733 1164 ioemu_vifs++;
keir@20509 1165 }
keir@20462 1166 }
Ian@21733 1167 /* If we have no emulated nics, tell qemu not to create any */
Ian@21733 1168 if ( ioemu_vifs == 0 ) {
Ian@21733 1169 flexarray_set(dm_args, num++, "-net");
Ian@21733 1170 flexarray_set(dm_args, num++, "none");
Ian@21733 1171 }
keir@20462 1172 }
keir@20565 1173 if (info->saved_state) {
keir@20565 1174 flexarray_set(dm_args, num++, "-loadvm");
keir@20565 1175 flexarray_set(dm_args, num++, info->saved_state);
keir@20565 1176 }
keir@20509 1177 for (i = 0; info->extra && info->extra[i] != NULL; i++)
keir@20509 1178 flexarray_set(dm_args, num++, info->extra[i]);
keir@20516 1179 flexarray_set(dm_args, num++, "-M");
keir@20509 1180 if (info->type == XENPV)
keir@20516 1181 flexarray_set(dm_args, num++, "xenpv");
keir@20509 1182 else
keir@20516 1183 flexarray_set(dm_args, num++, "xenfv");
keir@20462 1184 flexarray_set(dm_args, num++, NULL);
keir@20462 1185 return (char **) flexarray_contents(dm_args);
keir@20462 1186 }
keir@20462 1187
gianni@22023 1188 static char ** libxl_build_device_model_args_new(libxl_gc *gc,
anthony@21989 1189 libxl_device_model_info *info,
anthony@21989 1190 libxl_device_nic *vifs,
anthony@21989 1191 int num_vifs)
anthony@21989 1192 {
anthony@21989 1193 int num = 0, i;
anthony@21989 1194 flexarray_t *dm_args;
anthony@21989 1195 int nb;
anthony@21989 1196 libxl_device_disk *disks;
anthony@21989 1197
anthony@21989 1198 dm_args = flexarray_make(16, 1);
anthony@21989 1199 if (!dm_args)
anthony@21989 1200 return NULL;
anthony@21989 1201
anthony@21989 1202 flexarray_set(dm_args, num++, "qemu-system-xen");
anthony@21989 1203 flexarray_set(dm_args, num++, "-xen-domid");
anthony@21989 1204
gianni@22023 1205 flexarray_set(dm_args, num++, libxl_sprintf(gc, "%d", info->domid));
anthony@21989 1206
anthony@21989 1207 if (info->dom_name) {
anthony@21989 1208 flexarray_set(dm_args, num++, "-name");
anthony@21989 1209 flexarray_set(dm_args, num++, info->dom_name);
anthony@21989 1210 }
anthony@21989 1211 if (info->vnc || info->vncdisplay || info->vnclisten || info->vncunused) {
anthony@21989 1212 int display = 0;
anthony@21989 1213 const char *listen = "127.0.0.1";
anthony@21989 1214
anthony@21989 1215 flexarray_set(dm_args, num++, "-vnc");
anthony@21989 1216
anthony@21989 1217 if (info->vncdisplay) {
anthony@21989 1218 display = info->vncdisplay;
anthony@21989 1219 if (info->vnclisten && strchr(info->vnclisten, ':') == NULL) {
anthony@21989 1220 listen = info->vnclisten;
anthony@21989 1221 }
anthony@21989 1222 } else if (info->vnclisten) {
anthony@21989 1223 listen = info->vnclisten;
anthony@21989 1224 }
anthony@21989 1225
anthony@21989 1226 if (strchr(listen, ':') != NULL)
anthony@21989 1227 flexarray_set(dm_args, num++,
gianni@22023 1228 libxl_sprintf(gc, "%s%s", listen,
anthony@21989 1229 info->vncunused ? ",to=99" : ""));
anthony@21989 1230 else
anthony@21989 1231 flexarray_set(dm_args, num++,
gianni@22023 1232 libxl_sprintf(gc, "%s:%d%s", listen, display,
anthony@21989 1233 info->vncunused ? ",to=99" : ""));
anthony@21989 1234 }
anthony@21989 1235 if (info->sdl) {
anthony@21989 1236 flexarray_set(dm_args, num++, "-sdl");
anthony@21989 1237 }
anthony@21989 1238 if (info->keymap) {
anthony@21989 1239 flexarray_set(dm_args, num++, "-k");
anthony@21989 1240 flexarray_set(dm_args, num++, info->keymap);
anthony@21989 1241 }
anthony@21989 1242 if (info->nographic && (!info->sdl && !info->vnc)) {
anthony@21989 1243 flexarray_set(dm_args, num++, "-nographic");
anthony@21989 1244 }
anthony@21989 1245 if (info->serial) {
anthony@21989 1246 flexarray_set(dm_args, num++, "-serial");
anthony@21989 1247 flexarray_set(dm_args, num++, info->serial);
anthony@21989 1248 }
anthony@21989 1249 if (info->type == XENFV) {
anthony@21989 1250 int ioemu_vifs = 0;
anthony@21989 1251
anthony@21989 1252 if (info->stdvga) {
anthony@21989 1253 flexarray_set(dm_args, num++, "-vga");
anthony@21989 1254 flexarray_set(dm_args, num++, "std");
anthony@21989 1255 }
anthony@21989 1256
anthony@21989 1257 if (info->boot) {
anthony@21989 1258 flexarray_set(dm_args, num++, "-boot");
gianni@22023 1259 flexarray_set(dm_args, num++, libxl_sprintf(gc, "order=%s", info->boot));
anthony@21989 1260 }
anthony@21989 1261 if (info->usb || info->usbdevice) {
anthony@21989 1262 flexarray_set(dm_args, num++, "-usb");
anthony@21989 1263 if (info->usbdevice) {
anthony@21989 1264 flexarray_set(dm_args, num++, "-usbdevice");
anthony@21989 1265 flexarray_set(dm_args, num++, info->usbdevice);
anthony@21989 1266 }
anthony@21989 1267 }
anthony@21989 1268 if (info->soundhw) {
anthony@21989 1269 flexarray_set(dm_args, num++, "-soundhw");
anthony@21989 1270 flexarray_set(dm_args, num++, info->soundhw);
anthony@21989 1271 }
anthony@21989 1272 if (!info->apic) {
anthony@21989 1273 flexarray_set(dm_args, num++, "-no-acpi");
anthony@21989 1274 }
anthony@21989 1275 if (info->vcpus > 1) {
anthony@21989 1276 flexarray_set(dm_args, num++, "-smp");
anthony@21989 1277 if (info->vcpu_avail)
gianni@22023 1278 flexarray_set(dm_args, num++, libxl_sprintf(gc, "%d,maxcpus=%d", info->vcpus, info->vcpu_avail));
anthony@21989 1279 else
gianni@22023 1280 flexarray_set(dm_args, num++, libxl_sprintf(gc, "%d", info->vcpus));
anthony@21989 1281 }
anthony@21989 1282 for (i = 0; i < num_vifs; i++) {
anthony@21989 1283 if (vifs[i].nictype == NICTYPE_IOEMU) {
gianni@22023 1284 char *smac = libxl_sprintf(gc, "%02x:%02x:%02x:%02x:%02x:%02x",
anthony@21989 1285 vifs[i].mac[0], vifs[i].mac[1], vifs[i].mac[2],
anthony@21989 1286 vifs[i].mac[3], vifs[i].mac[4], vifs[i].mac[5]);
anthony@21989 1287 if (!vifs[i].ifname)
gianni@22023 1288 vifs[i].ifname = libxl_sprintf(gc, "tap%d.%d", info->domid, vifs[i].devid);
anthony@21989 1289 flexarray_set(dm_args, num++, "-net");
gianni@22023 1290 flexarray_set(dm_args, num++, libxl_sprintf(gc, "nic,vlan=%d,macaddr=%s,model=%s",
anthony@21989 1291 vifs[i].devid, smac, vifs[i].model));
anthony@21989 1292 flexarray_set(dm_args, num++, "-net");
gianni@22023 1293 flexarray_set(dm_args, num++, libxl_sprintf(gc, "tap,vlan=%d,ifname=%s,script=no",
anthony@21990 1294 vifs[i].devid, vifs[i].ifname));
anthony@21989 1295 ioemu_vifs++;
anthony@21989 1296 }
anthony@21989 1297 }
anthony@21989 1298 /* If we have no emulated nics, tell qemu not to create any */
anthony@21989 1299 if ( ioemu_vifs == 0 ) {
anthony@21989 1300 flexarray_set(dm_args, num++, "-net");
anthony@21989 1301 flexarray_set(dm_args, num++, "none");
anthony@21989 1302 }
anthony@21989 1303 }
anthony@21989 1304 if (info->saved_state) {
anthony@21989 1305 flexarray_set(dm_args, num++, "-loadvm");
anthony@21989 1306 flexarray_set(dm_args, num++, info->saved_state);
anthony@21989 1307 }
anthony@21989 1308 for (i = 0; info->extra && info->extra[i] != NULL; i++)
anthony@21989 1309 flexarray_set(dm_args, num++, info->extra[i]);
anthony@21989 1310 flexarray_set(dm_args, num++, "-M");
anthony@21989 1311 if (info->type == XENPV)
anthony@21989 1312 flexarray_set(dm_args, num++, "xenpv");
anthony@21989 1313 else
anthony@21989 1314 flexarray_set(dm_args, num++, "xenfv");
anthony@21989 1315
gianni@22023 1316 disks = libxl_device_disk_list(libxl_gc_owner(gc), info->domid, &nb);
gianni@22042 1317 for (i; i < nb; i++) {
gianni@22042 1318 if ( disks[i].is_cdrom ) {
anthony@21989 1319 flexarray_set(dm_args, num++, "-cdrom");
gianni@22042 1320 flexarray_set(dm_args, num++, disks[i].physpath);
anthony@21989 1321 }else{
gianni@22042 1322 flexarray_set(dm_args, num++, libxl_sprintf(gc, "-%s", disks[i].virtpath));
gianni@22042 1323 flexarray_set(dm_args, num++, disks[i].physpath);
anthony@21989 1324 }
anthony@21989 1325 }
gianni@22042 1326 /* FIXME: leaks disk paths */
gianni@22023 1327 free(disks);
anthony@21989 1328 flexarray_set(dm_args, num++, NULL);
anthony@21989 1329 return (char **) flexarray_contents(dm_args);
anthony@21989 1330 }
anthony@21989 1331
gianni@22023 1332 static char ** libxl_build_device_model_args(libxl_gc *gc,
anthony@21989 1333 libxl_device_model_info *info,
anthony@21989 1334 libxl_device_nic *vifs,
anthony@21989 1335 int num_vifs)
anthony@21989 1336 {
gianni@22023 1337 libxl_ctx *ctx = libxl_gc_owner(gc);
anthony@21989 1338 int new_qemu;
anthony@21989 1339
anthony@21989 1340 new_qemu = libxl_check_device_model_version(ctx, info->device_model);
anthony@21989 1341
anthony@21989 1342 if (new_qemu == 1) {
gianni@22023 1343 return libxl_build_device_model_args_new(gc, info, vifs, num_vifs);
anthony@21989 1344 } else {
gianni@22023 1345 return libxl_build_device_model_args_old(gc, info, vifs, num_vifs);
anthony@21989 1346 }
anthony@21989 1347 }
anthony@21989 1348
Ian@22062 1349 static void dm_xenstore_record_pid(void *for_spawn, pid_t innerchild)
keir@20834 1350 {
ian@21930 1351 libxl_device_model_starting *starting = for_spawn;
keir@20514 1352 char *kvs[3];
keir@20820 1353 int rc;
keir@20820 1354 struct xs_handle *xsh;
keir@20514 1355
keir@20820 1356 xsh = xs_daemon_open();
keir@20514 1357 /* we mustn't use the parent's handle in the child */
keir@20514 1358
keir@20514 1359 kvs[0] = "image/device-model-pid";
keir@21417 1360 if (asprintf(&kvs[1], "%d", innerchild) < 0)
keir@21417 1361 return;
keir@20514 1362 kvs[2] = NULL;
keir@20820 1363
keir@20820 1364 rc = xs_writev(xsh, XBT_NULL, starting->dom_path, kvs);
keir@20820 1365 if (rc)
keir@20820 1366 return;
keir@20820 1367 xs_daemon_close(xsh);
keir@20514 1368 }
keir@20514 1369
ian@21930 1370 static int libxl_vfb_and_vkb_from_device_model_info(libxl_ctx *ctx,
keir@20542 1371 libxl_device_model_info *info,
keir@20542 1372 libxl_device_vfb *vfb,
keir@20542 1373 libxl_device_vkb *vkb)
keir@20542 1374 {
keir@20542 1375 memset(vfb, 0x00, sizeof(libxl_device_vfb));
keir@20542 1376 memset(vkb, 0x00, sizeof(libxl_device_vkb));
keir@20542 1377
keir@20542 1378 vfb->backend_domid = 0;
keir@20542 1379 vfb->devid = 0;
keir@20542 1380 vfb->vnc = info->vnc;
keir@20542 1381 vfb->vnclisten = info->vnclisten;
keir@20542 1382 vfb->vncdisplay = info->vncdisplay;
keir@20542 1383 vfb->vncunused = info->vncunused;
keir@21362 1384 vfb->vncpasswd = info->vncpasswd;
keir@20542 1385 vfb->keymap = info->keymap;
keir@20542 1386 vfb->sdl = info->sdl;
keir@20542 1387 vfb->opengl = info->opengl;
keir@20542 1388
keir@20542 1389 vkb->backend_domid = 0;
keir@20542 1390 vkb->devid = 0;
keir@20542 1391 return 0;
keir@20542 1392 }
keir@20542 1393
ian@21930 1394 static int libxl_write_dmargs(libxl_ctx *ctx, int domid, int guest_domid, char **args)
keir@20542 1395 {
gianni@22023 1396 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@20542 1397 int i;
keir@20542 1398 char *vm_path;
keir@20542 1399 char *dmargs, *path;
keir@20542 1400 int dmargs_size;
keir@20542 1401 struct xs_permissions roperm[2];
keir@20542 1402 xs_transaction_t t;
keir@20542 1403
keir@20542 1404 roperm[0].id = 0;
keir@20542 1405 roperm[0].perms = XS_PERM_NONE;
keir@20542 1406 roperm[1].id = domid;
keir@20542 1407 roperm[1].perms = XS_PERM_READ;
keir@20542 1408
gianni@22023 1409 vm_path = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "/local/domain/%d/vm", guest_domid));
keir@20542 1410
keir@20542 1411 i = 0;
keir@20542 1412 dmargs_size = 0;
keir@20542 1413 while (args[i] != NULL) {
keir@20542 1414 dmargs_size = dmargs_size + strlen(args[i]) + 1;
keir@20542 1415 i++;
keir@20542 1416 }
keir@20542 1417 dmargs_size++;
keir@20542 1418 dmargs = (char *) malloc(dmargs_size);
keir@20542 1419 i = 1;
keir@20542 1420 dmargs[0] = '\0';
keir@20542 1421 while (args[i] != NULL) {
keir@20542 1422 if (strcmp(args[i], "-sdl") && strcmp(args[i], "-M") && strcmp(args[i], "xenfv")) {
keir@20542 1423 strcat(dmargs, " ");
keir@20542 1424 strcat(dmargs, args[i]);
keir@20542 1425 }
keir@20542 1426 i++;
keir@20542 1427 }
gianni@22023 1428 path = libxl_sprintf(&gc, "%s/image/dmargs", vm_path);
keir@20542 1429
keir@20542 1430 retry_transaction:
keir@20542 1431 t = xs_transaction_start(ctx->xsh);
keir@20542 1432 xs_write(ctx->xsh, t, path, dmargs, strlen(dmargs));
keir@20542 1433 xs_set_permissions(ctx->xsh, t, path, roperm, ARRAY_SIZE(roperm));
gianni@22023 1434 xs_set_permissions(ctx->xsh, t, libxl_sprintf(&gc, "%s/rtc/timeoffset", vm_path), roperm, ARRAY_SIZE(roperm));
keir@20542 1435 if (!xs_transaction_end(ctx->xsh, t, 0))
keir@20542 1436 if (errno == EAGAIN)
keir@20542 1437 goto retry_transaction;
keir@20542 1438 free(dmargs);
gianni@22023 1439 libxl_free_all(&gc);
keir@20542 1440 return 0;
keir@20542 1441 }
keir@20542 1442
ian@21930 1443 static int libxl_create_stubdom(libxl_ctx *ctx,
keir@20542 1444 libxl_device_model_info *info,
keir@20542 1445 libxl_device_disk *disks, int num_disks,
keir@20542 1446 libxl_device_nic *vifs, int num_vifs,
keir@20542 1447 libxl_device_vfb *vfb,
keir@20542 1448 libxl_device_vkb *vkb,
keir@20542 1449 libxl_device_model_starting **starting_r)
keir@20542 1450 {
gianni@22023 1451 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@20843 1452 int i, num_console = 1, ret;
keir@20570 1453 libxl_device_console *console;
keir@20542 1454 libxl_domain_create_info c_info;
keir@20542 1455 libxl_domain_build_info b_info;
keir@20542 1456 libxl_domain_build_state state;
keir@20542 1457 uint32_t domid;
keir@20542 1458 char **args;
keir@20542 1459 struct xs_permissions perm[2];
keir@20542 1460 xs_transaction_t t;
keir@20594 1461 libxl_device_model_starting *dm_starting = 0;
keir@20542 1462
gianni@22023 1463 args = libxl_build_device_model_args(&gc, info, vifs, num_vifs);
gianni@22023 1464 if (!args) {
gianni@22023 1465 ret = ERROR_FAIL;
gianni@22023 1466 goto out;
gianni@22023 1467 }
keir@20542 1468
keir@20542 1469 memset(&c_info, 0x00, sizeof(libxl_domain_create_info));
keir@20542 1470 c_info.hvm = 0;
gianni@22023 1471 c_info.name = libxl_sprintf(&gc, "%s-dm", _libxl_domid_to_name(&gc, info->domid));
keir@20801 1472 for (i = 0; i < 16; i++)
keir@20801 1473 c_info.uuid[i] = info->uuid[i];
keir@20542 1474
keir@20542 1475 memset(&b_info, 0x00, sizeof(libxl_domain_build_info));
keir@20542 1476 b_info.max_vcpus = 1;
keir@20542 1477 b_info.max_memkb = 32 * 1024;
keir@20647 1478 b_info.target_memkb = b_info.max_memkb;
gianni@22023 1479 b_info.kernel.path = libxl_abs_path(&gc, "ioemu-stubdom.gz", libxl_xenfirmwaredir_path());
gianni@22023 1480 b_info.u.pv.cmdline = libxl_sprintf(&gc, " -d %d", info->domid);
Ian@21848 1481 b_info.u.pv.ramdisk.path = "";
keir@20542 1482 b_info.u.pv.features = "";
keir@20542 1483 b_info.hvm = 0;
keir@20542 1484
keir@20843 1485 ret = libxl_domain_make(ctx, &c_info, &domid);
gianni@22023 1486 if (ret)
gianni@22023 1487 goto out_free;
keir@20843 1488 ret = libxl_domain_build(ctx, &b_info, domid, &state);
gianni@22023 1489 if (ret)
gianni@22023 1490 goto out_free;
keir@20542 1491
keir@20542 1492 libxl_write_dmargs(ctx, domid, info->domid, args);
gianni@22023 1493 libxl_xs_write(&gc, XBT_NULL,
gianni@22023 1494 libxl_sprintf(&gc, "%s/image/device-model-domid", libxl_xs_get_dompath(&gc, info->domid)),
keir@20843 1495 "%d", domid);
gianni@22023 1496 libxl_xs_write(&gc, XBT_NULL,
gianni@22023 1497 libxl_sprintf(&gc, "%s/target", libxl_xs_get_dompath(&gc, domid)),
keir@20843 1498 "%d", info->domid);
gianni@21892 1499 ret = xc_domain_set_target(ctx->xch, domid, info->domid);
gianni@21892 1500 if (ret<0) {
gianni@21892 1501 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "setting target domain %d -> %d", domid, info->domid);
gianni@22023 1502 ret = ERROR_FAIL;
gianni@22023 1503 goto out_free;
gianni@21892 1504 }
keir@20542 1505 xs_set_target(ctx->xsh, domid, info->domid);
keir@20542 1506
keir@20542 1507 perm[0].id = domid;
keir@20542 1508 perm[0].perms = XS_PERM_NONE;
keir@20542 1509 perm[1].id = info->domid;
keir@20542 1510 perm[1].perms = XS_PERM_READ;
keir@20542 1511 retry_transaction:
keir@20542 1512 t = xs_transaction_start(ctx->xsh);
gianni@22023 1513 xs_mkdir(ctx->xsh, t, libxl_sprintf(&gc, "/local/domain/0/device-model/%d", info->domid));
gianni@22023 1514 xs_set_permissions(ctx->xsh, t, libxl_sprintf(&gc, "/local/domain/0/device-model/%d", info->domid), perm, ARRAY_SIZE(perm));
gianni@22023 1515 xs_mkdir(ctx->xsh, t, libxl_sprintf(&gc, "/local/domain/%d/device/vfs", domid));
gianni@22023 1516 xs_set_permissions(ctx->xsh, t, libxl_sprintf(&gc, "/local/domain/%d/device/vfs",domid), perm, ARRAY_SIZE(perm));
keir@20542 1517 if (!xs_transaction_end(ctx->xsh, t, 0))
keir@20542 1518 if (errno == EAGAIN)
keir@20542 1519 goto retry_transaction;
keir@20542 1520
keir@20542 1521 for (i = 0; i < num_disks; i++) {
keir@20781 1522 disks[i].domid = domid;
keir@20843 1523 ret = libxl_device_disk_add(ctx, domid, &disks[i]);
gianni@22023 1524 if (ret)
gianni@22023 1525 goto out_free;
keir@20542 1526 }
keir@20542 1527 for (i = 0; i < num_vifs; i++) {
keir@20781 1528 vifs[i].domid = domid;
keir@20843 1529 ret = libxl_device_nic_add(ctx, domid, &vifs[i]);
gianni@22023 1530 if (ret)
gianni@22023 1531 goto out_free;
keir@20542 1532 }
keir@20781 1533 vfb->domid = domid;
keir@20843 1534 ret = libxl_device_vfb_add(ctx, domid, vfb);
gianni@22023 1535 if (ret)
gianni@22023 1536 goto out_free;
keir@20781 1537 vkb->domid = domid;
keir@20843 1538 ret = libxl_device_vkb_add(ctx, domid, vkb);
gianni@22023 1539 if (ret)
gianni@22023 1540 goto out_free;
keir@20542 1541
keir@20570 1542 if (info->serial)
keir@20570 1543 num_console++;
keir@20843 1544
gianni@22023 1545 console = libxl_calloc(&gc, num_console, sizeof(libxl_device_console));
gianni@22023 1546 if (!console) {
gianni@22023 1547 ret = ERROR_NOMEM;
gianni@22023 1548 goto out_free;
gianni@22023 1549 }
keir@20843 1550
keir@20570 1551 for (i = 0; i < num_console; i++) {
keir@20781 1552 console[i].devid = i;
stefano@22040 1553 console[i].consback = LIBXL_CONSBACK_IOEMU;
keir@20781 1554 console[i].domid = domid;
stefano@22040 1555 if (!i) {
stefano@22040 1556 char *filename;
stefano@22040 1557 char *name = libxl_sprintf(&gc, "qemu-dm-%s", libxl_domid_to_name(ctx, info->domid));
stefano@22040 1558 libxl_create_logfile(ctx, name, &filename);
stefano@22040 1559 console[i].output = libxl_sprintf(&gc, "file:%s", filename);
keir@20781 1560 console[i].build_state = &state;
stefano@22040 1561 free(filename);
stefano@22040 1562 } else
stefano@22040 1563 console[i].output = "pty";
keir@20843 1564 ret = libxl_device_console_add(ctx, domid, &console[i]);
gianni@22023 1565 if (ret)
gianni@22023 1566 goto out_free;
keir@20570 1567 }
stefano@22040 1568 if (libxl_create_xenpv_qemu(ctx, domid, vfb, &dm_starting) < 0) {
gianni@22023 1569 ret = ERROR_FAIL;
gianni@22023 1570 goto out_free;
keir@20594 1571 }
keir@20594 1572 if (libxl_confirm_device_model_startup(ctx, dm_starting) < 0) {
gianni@22023 1573 ret = ERROR_FAIL;
gianni@22023 1574 goto out_free;
keir@20594 1575 }
keir@20542 1576
keir@20542 1577 libxl_domain_unpause(ctx, domid);
keir@20542 1578
keir@20594 1579 if (starting_r) {
gianni@22023 1580 *starting_r = calloc(sizeof(libxl_device_model_starting), 1);
keir@20598 1581 (*starting_r)->domid = info->domid;
gianni@22023 1582 (*starting_r)->dom_path = libxl_xs_get_dompath(&gc, info->domid);
keir@20594 1583 (*starting_r)->for_spawn = NULL;
keir@20594 1584 }
keir@20594 1585
gianni@22023 1586 ret = 0;
gianni@22023 1587
gianni@22023 1588 out_free:
keir@20542 1589 free(args);
gianni@22023 1590 out:
gianni@22023 1591 libxl_free_all(&gc);
gianni@22023 1592 return ret;
keir@20542 1593 }
keir@20542 1594
ian@21930 1595 int libxl_create_device_model(libxl_ctx *ctx,
keir@20462 1596 libxl_device_model_info *info,
keir@20542 1597 libxl_device_disk *disks, int num_disks,
keir@20514 1598 libxl_device_nic *vifs, int num_vifs,
keir@20514 1599 libxl_device_model_starting **starting_r)
keir@20462 1600 {
gianni@22023 1601 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@20546 1602 char *path, *logfile;
keir@20514 1603 int logfile_w, null;
keir@20546 1604 int rc;
keir@20462 1605 char **args;
ian@21930 1606 libxl_device_model_starting buf_starting, *p;
keir@21362 1607 xs_transaction_t t;
keir@21362 1608 char *vm_path;
keir@21362 1609 char **pass_stuff;
keir@20514 1610
keir@20542 1611 if (strstr(info->device_model, "stubdom-dm")) {
keir@20542 1612 libxl_device_vfb vfb;
keir@20542 1613 libxl_device_vkb vkb;
keir@20542 1614
keir@20542 1615 libxl_vfb_and_vkb_from_device_model_info(ctx, info, &vfb, &vkb);
gianni@22023 1616 rc = libxl_create_stubdom(ctx, info, disks, num_disks, vifs, num_vifs, &vfb, &vkb, starting_r);
gianni@22023 1617 goto out;
keir@20542 1618 }
keir@20542 1619
gianni@22023 1620 args = libxl_build_device_model_args(&gc, info, vifs, num_vifs);
gianni@22023 1621 if (!args) {
gianni@22023 1622 rc = ERROR_FAIL;
gianni@22023 1623 goto out;
gianni@22023 1624 }
gianni@22023 1625
gianni@22023 1626 path = libxl_sprintf(&gc, "/local/domain/0/device-model/%d", info->domid);
keir@20462 1627 xs_mkdir(ctx->xsh, XBT_NULL, path);
gianni@22023 1628 libxl_xs_write(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/disable_pf", path), "%d", !info->xen_platform_pci);
gianni@22023 1629
gianni@22023 1630 libxl_create_logfile(ctx, libxl_sprintf(&gc, "qemu-dm-%s", info->dom_name), &logfile);
keir@20467 1631 logfile_w = open(logfile, O_WRONLY|O_CREAT, 0644);
keir@20546 1632 free(logfile);
keir@20462 1633 null = open("/dev/null", O_RDONLY);
keir@20514 1634
keir@20514 1635 if (starting_r) {
keir@20516 1636 rc = ERROR_NOMEM;
gianni@22023 1637 *starting_r = calloc(sizeof(libxl_device_model_starting), 1);
gianni@22023 1638 if (!*starting_r)
gianni@22023 1639 goto out_close;
keir@20594 1640 p = *starting_r;
gianni@22023 1641 p->for_spawn = calloc(sizeof(libxl_spawn_starting), 1);
keir@20594 1642 } else {
keir@20594 1643 p = &buf_starting;
keir@20594 1644 p->for_spawn = NULL;
keir@20594 1645 }
keir@20514 1646
keir@20594 1647 p->domid = info->domid;
gianni@22023 1648 p->dom_path = libxl_xs_get_dompath(&gc, info->domid);
gianni@22023 1649 if (!p->dom_path) {
gianni@22023 1650 rc = ERROR_FAIL;
gianni@22023 1651 goto out_close;
gianni@22023 1652 }
keir@20594 1653
keir@21362 1654 if (info->vncpasswd) {
gianni@22023 1655 retry_transaction:
keir@21362 1656 /* Find uuid and the write the vnc password to xenstore for qemu. */
keir@21362 1657 t = xs_transaction_start(ctx->xsh);
gianni@22023 1658 vm_path = libxl_xs_read(&gc,t,libxl_sprintf(&gc, "%s/vm", p->dom_path));
keir@21362 1659 if (vm_path) {
keir@21362 1660 /* Now write the vncpassword into it. */
gianni@22023 1661 pass_stuff = libxl_calloc(&gc, 2, sizeof(char *));
keir@21362 1662 pass_stuff[0] = "vncpasswd";
keir@21362 1663 pass_stuff[1] = info->vncpasswd;
gianni@22023 1664 libxl_xs_writev(&gc,t,vm_path,pass_stuff);
keir@21362 1665 if (!xs_transaction_end(ctx->xsh, t, 0))
keir@21362 1666 if (errno == EAGAIN)
keir@21362 1667 goto retry_transaction;
keir@21362 1668 }
keir@21362 1669 }
keir@21362 1670
keir@20594 1671 rc = libxl_spawn_spawn(ctx, p, "device model", dm_xenstore_record_pid);
gianni@22023 1672 if (rc < 0)
gianni@22023 1673 goto out_close;
keir@20514 1674 if (!rc) { /* inner child */
keir@20833 1675 libxl_exec(null, logfile_w, logfile_w,
gianni@22023 1676 libxl_abs_path(&gc, info->device_model, libxl_private_bindir_path()),
keir@21353 1677 args);
keir@20514 1678 }
keir@20514 1679
keir@20514 1680 rc = 0;
gianni@22023 1681
gianni@22023 1682 out_close:
keir@20462 1683 close(null);
keir@20462 1684 close(logfile_w);
gianni@22023 1685 free(args);
gianni@22023 1686 out:
gianni@22023 1687 libxl_free_all(&gc);
keir@20514 1688 return rc;
keir@20514 1689 }
keir@20514 1690
ian@21930 1691 int libxl_detach_device_model(libxl_ctx *ctx,
keir@20779 1692 libxl_device_model_starting *starting)
keir@20779 1693 {
keir@20514 1694 int rc;
keir@20594 1695 rc = libxl_spawn_detach(ctx, starting->for_spawn);
gianni@22023 1696 if (starting->for_spawn)
gianni@22023 1697 free(starting->for_spawn);
gianni@22023 1698 free(starting);
keir@20514 1699 return rc;
keir@20514 1700 }
keir@20462 1701
keir@20514 1702
ian@21930 1703 int libxl_confirm_device_model_startup(libxl_ctx *ctx,
keir@20779 1704 libxl_device_model_starting *starting)
keir@20779 1705 {
gianni@21965 1706 int problem = libxl_wait_for_device_model(ctx, starting->domid, "running", NULL, NULL);
gianni@21965 1707 int detach;
gianni@21965 1708 if ( !problem )
gianni@21965 1709 problem = libxl_spawn_check(ctx, starting->for_spawn);
gianni@21965 1710 detach = libxl_detach_device_model(ctx, starting);
keir@20514 1711 return problem ? problem : detach;
keir@20462 1712 }
keir@20462 1713
keir@20514 1714
keir@20462 1715 /******************************************************************************/
keir@20566 1716
ian@21930 1717 int libxl_device_disk_add(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk)
keir@20462 1718 {
gianni@22023 1719 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@20462 1720 flexarray_t *front;
keir@20462 1721 flexarray_t *back;
keir@20462 1722 char *backend_type;
keir@20462 1723 unsigned int boffset = 0;
keir@20462 1724 unsigned int foffset = 0;
keir@20462 1725 int devid;
keir@20462 1726 libxl_device device;
gianni@22023 1727 int major, minor, rc;
keir@20462 1728
keir@20462 1729 front = flexarray_make(16, 1);
gianni@22023 1730 if (!front) {
gianni@22023 1731 rc = ERROR_NOMEM;
gianni@22023 1732 goto out;
gianni@22023 1733 }
keir@20462 1734 back = flexarray_make(16, 1);
gianni@22023 1735 if (!back) {
gianni@22023 1736 rc = ERROR_NOMEM;
gianni@22023 1737 goto out_free;
gianni@22023 1738 }
keir@20462 1739
keir@20462 1740 backend_type = device_disk_backend_type_of_phystype(disk->phystype);
keir@20462 1741 devid = device_disk_dev_number(disk->virtpath);
keir@20947 1742 if (devid==-1) {
Christoph@21953 1743 XL_LOG(ctx, XL_LOG_ERROR, "Invalid or unsupported"
keir@20947 1744 " virtual disk identifier %s", disk->virtpath);
gianni@22023 1745 rc = ERROR_INVAL;
gianni@22023 1746 goto out_free;
keir@20947 1747 }
keir@20462 1748
keir@20462 1749 device.backend_devid = devid;
keir@20462 1750 device.backend_domid = disk->backend_domid;
keir@20462 1751 device.devid = devid;
keir@20462 1752 device.domid = disk->domid;
keir@20462 1753 device.kind = DEVICE_VBD;
keir@20462 1754
keir@20462 1755 switch (disk->phystype) {
keir@20462 1756 case PHYSTYPE_PHY: {
keir@20462 1757
keir@20509 1758 device_physdisk_major_minor(disk->physpath, &major, &minor);
keir@20516 1759 flexarray_set(back, boffset++, "physical-device");
gianni@22023 1760 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%x:%x", major, minor));
keir@20462 1761
keir@20516 1762 flexarray_set(back, boffset++, "params");
keir@20516 1763 flexarray_set(back, boffset++, disk->physpath);
keir@20462 1764
keir@20462 1765 device.backend_kind = DEVICE_VBD;
keir@20462 1766 break;
keir@20462 1767 }
keir@20566 1768 case PHYSTYPE_FILE:
keir@20566 1769 /* let's pretend is tap:aio for the moment */
keir@20566 1770 disk->phystype = PHYSTYPE_AIO;
Christoph@22044 1771 case PHYSTYPE_AIO:
Christoph@22044 1772 case PHYSTYPE_QCOW:
Christoph@22044 1773 case PHYSTYPE_QCOW2:
Christoph@22044 1774 case PHYSTYPE_VHD:
Christoph@22044 1775 if (libxl_blktap_enabled(&gc)) {
Christoph@22044 1776 const char *dev = libxl_blktap_devpath(&gc,
Christoph@22044 1777 disk->physpath, disk->phystype);
gianni@22023 1778 if (!dev) {
gianni@22023 1779 rc = ERROR_FAIL;
gianni@22023 1780 goto out_free;
gianni@22023 1781 }
keir@20566 1782 flexarray_set(back, boffset++, "tapdisk-params");
gianni@22023 1783 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%s:%s", device_disk_string_of_phystype(disk->phystype), disk->physpath));
keir@20566 1784 flexarray_set(back, boffset++, "params");
gianni@22023 1785 flexarray_set(back, boffset++, libxl_strdup(&gc, dev));
keir@20566 1786 backend_type = "phy";
keir@20566 1787 device_physdisk_major_minor(dev, &major, &minor);
keir@20566 1788 flexarray_set(back, boffset++, "physical-device");
gianni@22023 1789 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%x:%x", major, minor));
keir@20566 1790 device.backend_kind = DEVICE_VBD;
keir@20566 1791
keir@20566 1792 break;
keir@20566 1793 }
keir@20516 1794 flexarray_set(back, boffset++, "params");
gianni@22023 1795 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%s:%s",
keir@20462 1796 device_disk_string_of_phystype(disk->phystype), disk->physpath));
keir@20462 1797
keir@20462 1798 device.backend_kind = DEVICE_TAP;
keir@20462 1799 break;
Christoph@22044 1800
keir@20846 1801 default:
keir@20846 1802 XL_LOG(ctx, XL_LOG_ERROR, "unrecognized disk physical type: %d\n", disk->phystype);
gianni@22023 1803 rc = ERROR_INVAL;
gianni@22023 1804 goto out_free;
keir@20462 1805 }
keir@20462 1806
keir@20516 1807 flexarray_set(back, boffset++, "frontend-id");
gianni@22023 1808 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", disk->domid));
keir@20516 1809 flexarray_set(back, boffset++, "online");
keir@20516 1810 flexarray_set(back, boffset++, "1");
keir@20516 1811 flexarray_set(back, boffset++, "removable");
gianni@22023 1812 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", (disk->unpluggable) ? 1 : 0));
keir@20516 1813 flexarray_set(back, boffset++, "bootable");
gianni@22023 1814 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", 1));
keir@20516 1815 flexarray_set(back, boffset++, "state");
gianni@22023 1816 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", 1));
keir@20516 1817 flexarray_set(back, boffset++, "dev");
keir@20516 1818 flexarray_set(back, boffset++, disk->virtpath);
keir@20516 1819 flexarray_set(back, boffset++, "type");
keir@20516 1820 flexarray_set(back, boffset++, backend_type);
keir@20516 1821 flexarray_set(back, boffset++, "mode");
keir@20516 1822 flexarray_set(back, boffset++, disk->readwrite ? "w" : "r");
keir@20462 1823
keir@20516 1824 flexarray_set(front, foffset++, "backend-id");
gianni@22023 1825 flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", disk->backend_domid));
keir@20516 1826 flexarray_set(front, foffset++, "state");
gianni@22023 1827 flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", 1));
keir@20516 1828 flexarray_set(front, foffset++, "virtual-device");
gianni@22023 1829 flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", devid));
keir@20516 1830 flexarray_set(front, foffset++, "device-type");
keir@20516 1831 flexarray_set(front, foffset++, disk->is_cdrom ? "cdrom" : "disk");
keir@20462 1832
keir@20462 1833 if (0 /* protocol != native*/) {
keir@20516 1834 flexarray_set(front, foffset++, "protocol");
keir@20516 1835 flexarray_set(front, foffset++, "x86_32-abi"); /* hardcoded ! */
keir@20462 1836 }
keir@20462 1837
keir@20462 1838 libxl_device_generic_add(ctx, &device,
gianni@22023 1839 libxl_xs_kvs_of_flexarray(&gc, back, boffset),
gianni@22023 1840 libxl_xs_kvs_of_flexarray(&gc, front, foffset));
gianni@22023 1841
gianni@22023 1842 rc = 0;
gianni@22023 1843
gianni@22023 1844 out_free:
keir@20516 1845 flexarray_free(back);
keir@20516 1846 flexarray_free(front);
gianni@22023 1847 out:
gianni@22023 1848 libxl_free_all(&gc);
gianni@22023 1849 return rc;
keir@20462 1850 }
keir@20462 1851
ian@21930 1852 int libxl_device_disk_del(libxl_ctx *ctx,
keir@20626 1853 libxl_device_disk *disk, int wait)
keir@20462 1854 {
keir@20626 1855 libxl_device device;
keir@20626 1856 int devid;
keir@20462 1857
keir@20626 1858 devid = device_disk_dev_number(disk->virtpath);
keir@20626 1859 device.backend_domid = disk->backend_domid;
keir@20626 1860 device.backend_devid = devid;
keir@20626 1861 device.backend_kind =
keir@20626 1862 (disk->phystype == PHYSTYPE_PHY) ? DEVICE_VBD : DEVICE_TAP;
keir@20626 1863 device.domid = disk->domid;
keir@20626 1864 device.devid = devid;
keir@20626 1865 device.kind = DEVICE_VBD;
keir@20626 1866 return libxl_device_del(ctx, &device, wait);
keir@20462 1867 }
keir@20462 1868
gianni@22023 1869 char * libxl_device_disk_local_attach(libxl_ctx *ctx, libxl_device_disk *disk)
Ian@21849 1870 {
gianni@22023 1871 libxl_gc gc = LIBXL_INIT_GC(ctx);
Christoph@22044 1872 const char *dev = NULL;
Christoph@22044 1873 char *ret;
Ian@21849 1874 int phystype = disk->phystype;
Ian@21849 1875 switch (phystype) {
Ian@21849 1876 case PHYSTYPE_PHY: {
Ian@21849 1877 fprintf(stderr, "attaching PHY disk %s to domain 0\n", disk->physpath);
Ian@21849 1878 dev = disk->physpath;
Ian@21849 1879 break;
Ian@21849 1880 }
Ian@21849 1881 case PHYSTYPE_FILE:
Ian@21849 1882 /* let's pretend is tap:aio for the moment */
Ian@21849 1883 phystype = PHYSTYPE_AIO;
Christoph@22044 1884 case PHYSTYPE_AIO:
Christoph@22044 1885 case PHYSTYPE_QCOW:
Christoph@22044 1886 case PHYSTYPE_QCOW2:
Christoph@22044 1887 case PHYSTYPE_VHD:
Christoph@22044 1888 if (libxl_blktap_enabled(&gc))
Christoph@22044 1889 dev = libxl_blktap_devpath(&gc, disk->physpath, phystype);
Ian@21849 1890 break;
Christoph@22044 1891
Ian@21849 1892 default:
Ian@21849 1893 XL_LOG(ctx, XL_LOG_ERROR, "unrecognized disk physical type: %d\n", phystype);
Ian@21849 1894 break;
Ian@21849 1895 }
gianni@22023 1896 ret = strdup(dev);
gianni@22023 1897 libxl_free_all(&gc);
gianni@22023 1898 return ret;
Ian@21849 1899 }
Ian@21849 1900
ian@21930 1901 int libxl_device_disk_local_detach(libxl_ctx *ctx, libxl_device_disk *disk)
Ian@21849 1902 {
Ian@21849 1903 /* Nothing to do for PHYSTYPE_PHY. */
Ian@21849 1904
Ian@21849 1905 /*
Ian@21849 1906 * For other device types assume that the blktap2 process is
Ian@21849 1907 * needed by the soon to be started domain and do nothing.
Ian@21849 1908 */
Ian@21849 1909
Ian@21849 1910 return 0;
Ian@21849 1911 }
Ian@21849 1912
keir@20462 1913 /******************************************************************************/
ian@21930 1914 int libxl_device_nic_add(libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic)
keir@20462 1915 {
gianni@22023 1916 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@20462 1917 flexarray_t *front;
keir@20462 1918 flexarray_t *back;
keir@20462 1919 unsigned int boffset = 0;
keir@20462 1920 unsigned int foffset = 0;
keir@20462 1921 libxl_device device;
keir@21407 1922 char *dompath, **l;
gianni@22023 1923 unsigned int nb, rc;
keir@20462 1924
keir@20462 1925 front = flexarray_make(16, 1);
gianni@22023 1926 if (!front) {
gianni@22023 1927 rc = ERROR_NOMEM;
gianni@22023 1928 goto out;
gianni@22023 1929 }
keir@20462 1930 back = flexarray_make(16, 1);
gianni@22023 1931 if (!back) {
gianni@22023 1932 rc = ERROR_NOMEM;
gianni@22023 1933 goto out_free;
gianni@22023 1934 }
keir@20462 1935
keir@21407 1936 if (nic->devid == -1) {
gianni@22023 1937 if (!(dompath = libxl_xs_get_dompath(&gc, domid))) {
gianni@22023 1938 rc = ERROR_FAIL;
gianni@22023 1939 goto out_free;
keir@21407 1940 }
gianni@22023 1941 if (!(l = libxl_xs_directory(&gc, XBT_NULL,
gianni@22023 1942 libxl_sprintf(&gc, "%s/device/vif", dompath), &nb))) {
keir@21407 1943 nic->devid = 0;
keir@21407 1944 } else {
keir@21407 1945 nic->devid = strtoul(l[nb - 1], NULL, 10) + 1;
keir@21407 1946 }
keir@21407 1947 }
keir@21407 1948
keir@20462 1949 device.backend_devid = nic->devid;
keir@20462 1950 device.backend_domid = nic->backend_domid;
keir@20462 1951 device.backend_kind = DEVICE_VIF;
keir@20462 1952 device.devid = nic->devid;
keir@20462 1953 device.domid = nic->domid;
keir@20462 1954 device.kind = DEVICE_VIF;
keir@20462 1955
keir@20516 1956 flexarray_set(back, boffset++, "frontend-id");
gianni@22023 1957 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", nic->domid));
keir@20516 1958 flexarray_set(back, boffset++, "online");
keir@20516 1959 flexarray_set(back, boffset++, "1");
keir@20516 1960 flexarray_set(back, boffset++, "state");
gianni@22023 1961 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", 1));
keir@20516 1962 flexarray_set(back, boffset++, "script");
keir@20516 1963 flexarray_set(back, boffset++, nic->script);
keir@20516 1964 flexarray_set(back, boffset++, "mac");
gianni@22023 1965 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%02x:%02x:%02x:%02x:%02x:%02x",
keir@20462 1966 nic->mac[0], nic->mac[1], nic->mac[2],
keir@20462 1967 nic->mac[3], nic->mac[4], nic->mac[5]));
Ian@21732 1968 flexarray_set(back, boffset++, "bridge");
gianni@22023 1969 flexarray_set(back, boffset++, libxl_strdup(&gc, nic->bridge));
keir@20516 1970 flexarray_set(back, boffset++, "handle");
gianni@22023 1971 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", nic->devid));
keir@20462 1972
keir@20516 1973 flexarray_set(front, foffset++, "backend-id");
gianni@22023 1974 flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", nic->backend_domid));
keir@20516 1975 flexarray_set(front, foffset++, "state");
gianni@22023 1976 flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", 1));
keir@20516 1977 flexarray_set(front, foffset++, "handle");
gianni@22023 1978 flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", nic->devid));
keir@20516 1979 flexarray_set(front, foffset++, "mac");
gianni@22023 1980 flexarray_set(front, foffset++, libxl_sprintf(&gc, "%02x:%02x:%02x:%02x:%02x:%02x",
keir@20462 1981 nic->mac[0], nic->mac[1], nic->mac[2],
keir@20462 1982 nic->mac[3], nic->mac[4], nic->mac[5]));
keir@20462 1983 if (0 /* protocol != native*/) {
keir@20516 1984 flexarray_set(front, foffset++, "protocol");
keir@20516 1985 flexarray_set(front, foffset++, "x86_32-abi"); /* hardcoded ! */
keir@20462 1986 }
keir@20462 1987
keir@20462 1988 libxl_device_generic_add(ctx, &device,
gianni@22023 1989 libxl_xs_kvs_of_flexarray(&gc, back, boffset),
gianni@22023 1990 libxl_xs_kvs_of_flexarray(&gc, front, foffset));
keir@20462 1991
keir@20462 1992 /* FIXME: wait for plug */
gianni@22023 1993 rc = 0;
gianni@22023 1994 out_free:
keir@20516 1995 flexarray_free(back);
keir@20516 1996 flexarray_free(front);
gianni@22023 1997 out:
gianni@22023 1998 libxl_free_all(&gc);
gianni@22023 1999 return rc;
keir@20462 2000 }
keir@20462 2001
ian@21930 2002 int libxl_device_nic_del(libxl_ctx *ctx,
keir@20626 2003 libxl_device_nic *nic, int wait)
keir@20462 2004 {
keir@20626 2005 libxl_device device;
keir@20462 2006
keir@20626 2007 device.backend_devid = nic->devid;
keir@20626 2008 device.backend_domid = nic->backend_domid;
keir@20626 2009 device.backend_kind = DEVICE_VIF;
keir@20626 2010 device.devid = nic->devid;
keir@20626 2011 device.domid = nic->domid;
keir@20626 2012 device.kind = DEVICE_VIF;
keir@20626 2013
keir@20626 2014 return libxl_device_del(ctx, &device, wait);
keir@20462 2015 }
keir@20462 2016
gianni@22009 2017 void libxl_free_nics_list(libxl_nicinfo *nics, unsigned int nb)
gianni@22009 2018 {
gianni@22009 2019 unsigned int i;
gianni@22009 2020 for(i = 0; i < nb; i++) {
gianni@22009 2021 free(nics[i].backend);
gianni@22009 2022 free(nics[i].frontend);
gianni@22009 2023 free(nics[i].script);
gianni@22009 2024 }
gianni@22009 2025 free(nics);
gianni@22009 2026 }
gianni@22009 2027
ian@21930 2028 libxl_nicinfo *libxl_list_nics(libxl_ctx *ctx, uint32_t domid, unsigned int *nb)
keir@21408 2029 {
gianni@22023 2030 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@21408 2031 char *dompath, *nic_path_fe;
gianni@22009 2032 char **l, **list;
keir@21408 2033 char *val, *tok;
keir@21408 2034 unsigned int nb_nics, i;
keir@21408 2035 libxl_nicinfo *res, *nics;
keir@21408 2036
gianni@22023 2037 dompath = libxl_xs_get_dompath(&gc, domid);
gianni@22023 2038 if (!dompath)
gianni@22023 2039 goto err;
gianni@22023 2040 list = l = libxl_xs_directory(&gc, XBT_NULL,
gianni@22023 2041 libxl_sprintf(&gc, "%s/device/vif", dompath), &nb_nics);
gianni@22023 2042 if (!l)
gianni@22023 2043 goto err;
gianni@22009 2044 nics = res = calloc(nb_nics, sizeof (libxl_device_nic));
gianni@22023 2045 if (!res)
gianni@22023 2046 goto err;
keir@21408 2047 for (*nb = nb_nics; nb_nics > 0; --nb_nics, ++l, ++nics) {
gianni@22023 2048 nic_path_fe = libxl_sprintf(&gc, "%s/device/vif/%s", dompath, *l);
keir@21408 2049
gianni@22009 2050 nics->backend = xs_read(ctx->xsh, XBT_NULL,
gianni@22023 2051 libxl_sprintf(&gc, "%s/backend", nic_path_fe), NULL);
gianni@22023 2052 val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/backend-id", nic_path_fe));
keir@21408 2053 nics->backend_id = val ? strtoul(val, NULL, 10) : -1;
keir@21408 2054
keir@21408 2055 nics->devid = strtoul(*l, NULL, 10);
gianni@22023 2056 val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/state", nic_path_fe));
keir@21408 2057 nics->state = val ? strtoul(val, NULL, 10) : -1;
gianni@22023 2058 val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/mac", nic_path_fe));
keir@21408 2059 for (i = 0, tok = strtok(val, ":"); tok && (i < 6);
keir@21408 2060 ++i, tok = strtok(NULL, ":")) {
keir@21408 2061 nics->mac[i] = strtoul(tok, NULL, 16);
keir@21408 2062 }
gianni@22023 2063 val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/event-channel", nic_path_fe));
keir@21408 2064 nics->evtch = val ? strtol(val, NULL, 10) : -1;
gianni@22023 2065 val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/tx-ring-ref", nic_path_fe));
keir@21408 2066 nics->rref_tx = val ? strtol(val, NULL, 10) : -1;
gianni@22023 2067 val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/rx-ring-ref", nic_path_fe));
keir@21408 2068 nics->rref_rx = val ? strtol(val, NULL, 10) : -1;
gianni@22009 2069 nics->frontend = xs_read(ctx->xsh, XBT_NULL,
gianni@22023 2070 libxl_sprintf(&gc, "%s/frontend", nics->backend), NULL);
gianni@22023 2071 val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/frontend-id", nics->backend));
keir@21408 2072 nics->frontend_id = val ? strtoul(val, NULL, 10) : -1;
gianni@22009 2073 nics->script = xs_read(ctx->xsh, XBT_NULL,
gianni@22023 2074 libxl_sprintf(&gc, "%s/script", nics->backend), NULL);
keir@21408 2075 }
keir@21408 2076
gianni@22023 2077 libxl_free_all(&gc);
keir@21408 2078 return res;
gianni@22023 2079 err:
gianni@22023 2080 libxl_free_all(&gc);
gianni@22023 2081 return NULL;
keir@21408 2082 }
keir@21408 2083
keir@21580 2084 /******************************************************************************/
ian@21930 2085 int libxl_device_net2_add(libxl_ctx *ctx, uint32_t domid, libxl_device_net2 *net2)
keir@21580 2086 {
gianni@22023 2087 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@21580 2088 flexarray_t *front, *back;
keir@21580 2089 unsigned int boffset = 0, foffset = 0;
keir@21580 2090 libxl_device device;
keir@21580 2091 char *dompath, *dom, **l;
keir@21580 2092 unsigned int nb;
gianni@22023 2093 int rc;
keir@21580 2094
keir@21580 2095 front = flexarray_make(16, 1);
gianni@22023 2096 if (!front) {
gianni@22023 2097 rc = ERROR_NOMEM;
gianni@22023 2098 goto err;
gianni@22023 2099 }
keir@21580 2100 back = flexarray_make(16, 1);
gianni@22023 2101 if (!back) {
gianni@22023 2102 rc = ERROR_NOMEM;
gianni@22023 2103 goto err_free;
keir@21580 2104 }
gianni@22023 2105
gianni@22023 2106 if (!(dompath = libxl_xs_get_dompath(&gc, domid))) {
gianni@22023 2107 rc = ERROR_FAIL;
gianni@22023 2108 goto err_free;
gianni@22023 2109 }
gianni@22023 2110 dom = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/name", dompath));
keir@21580 2111
keir@21580 2112 if (net2->devid == -1) {
gianni@22023 2113 if (!(l = libxl_xs_directory(&gc, XBT_NULL,
gianni@22023 2114 libxl_sprintf(&gc, "%s/device/vif2", dompath), &nb))) {
keir@21580 2115 net2->devid = 0;
keir@21580 2116 } else {
keir@21580 2117 net2->devid = strtoul(l[nb - 1], NULL, 10) + 1;
keir@21580 2118 }
keir@21580 2119 }
keir@21580 2120
keir@21580 2121 device.backend_devid = net2->devid;
keir@21580 2122 device.backend_domid = net2->backend_domid;
keir@21580 2123 device.backend_kind = DEVICE_VIF2;
keir@21580 2124 device.devid = net2->devid;
keir@21580 2125 device.domid = net2->domid;
keir@21580 2126 device.kind = DEVICE_VIF2;
keir@21580 2127
keir@21580 2128 flexarray_set(back, boffset++, "domain");
keir@21580 2129 flexarray_set(back, boffset++, dom);
keir@21580 2130 flexarray_set(back, boffset++, "frontend-id");
gianni@22023 2131 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", net2->domid));
keir@21580 2132
keir@21580 2133 flexarray_set(back, boffset++, "local-trusted");
gianni@22023 2134 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", net2->back_trusted));
keir@21580 2135 flexarray_set(back, boffset++, "mac");
gianni@22023 2136 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%02x:%02x:%02x:%02x:%02x:%02x",
keir@21580 2137 net2->back_mac[0], net2->back_mac[1],
keir@21580 2138 net2->back_mac[2], net2->back_mac[3],
keir@21580 2139 net2->back_mac[4], net2->back_mac[5]));
keir@21580 2140
keir@21580 2141 flexarray_set(back, boffset++, "remote-trusted");
gianni@22023 2142 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", net2->trusted));
keir@21580 2143 flexarray_set(back, boffset++, "remote-mac");
gianni@22023 2144 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%02x:%02x:%02x:%02x:%02x:%02x",
keir@21580 2145 net2->front_mac[0], net2->front_mac[1],
keir@21580 2146 net2->front_mac[2], net2->front_mac[3],
keir@21580 2147 net2->front_mac[4], net2->front_mac[5]));
keir@21580 2148
keir@21580 2149 flexarray_set(back, boffset++, "max-bypasses");
gianni@22023 2150 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", net2->max_bypasses));
keir@21580 2151 flexarray_set(back, boffset++, "filter-mac");
gianni@22023 2152 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", !!(net2->filter_mac)));
keir@21580 2153 flexarray_set(back, boffset++, "handle");
gianni@22023 2154 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", net2->devid));
keir@21580 2155 flexarray_set(back, boffset++, "online");
keir@21580 2156 flexarray_set(back, boffset++, "1");
keir@21580 2157 flexarray_set(back, boffset++, "state");
keir@21580 2158 flexarray_set(back, boffset++, "1");
keir@21580 2159
keir@21580 2160 flexarray_set(front, foffset++, "backend-id");
gianni@22023 2161 flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", net2->backend_domid));
keir@21580 2162
keir@21580 2163 flexarray_set(front, foffset++, "local-trusted");
gianni@22023 2164 flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", net2->trusted));
keir@21580 2165 flexarray_set(front, foffset++, "mac");
gianni@22023 2166 flexarray_set(front, foffset++, libxl_sprintf(&gc, "%02x:%02x:%02x:%02x:%02x:%02x",
keir@21580 2167 net2->front_mac[0], net2->front_mac[1],
keir@21580 2168 net2->front_mac[2], net2->front_mac[3],
keir@21580 2169 net2->front_mac[4], net2->front_mac[5]));
keir@21580 2170
keir@21580 2171 flexarray_set(front, foffset++, "remote-trusted");
gianni@22023 2172 flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", net2->back_trusted));
keir@21580 2173 flexarray_set(front, foffset++, "remote-mac");
gianni@22023 2174 flexarray_set(front, foffset++, libxl_sprintf(&gc, "%02x:%02x:%02x:%02x:%02x:%02x",
keir@21580 2175 net2->back_mac[0], net2->back_mac[1],
keir@21580 2176 net2->back_mac[2], net2->back_mac[3],
keir@21580 2177 net2->back_mac[4], net2->back_mac[5]));
keir@21580 2178
keir@21580 2179 flexarray_set(front, foffset++, "filter-mac");
gianni@22023 2180 flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", !!(net2->filter_mac)));
keir@21580 2181 flexarray_set(front, foffset++, "state");
keir@21580 2182 flexarray_set(front, foffset++, "1");
keir@21580 2183
keir@21580 2184 libxl_device_generic_add(ctx, &device,
gianni@22023 2185 libxl_xs_kvs_of_flexarray(&gc, back, boffset),
gianni@22023 2186 libxl_xs_kvs_of_flexarray(&gc, front, foffset));
keir@21580 2187
keir@21580 2188 /* FIXME: wait for plug */
gianni@22023 2189 rc = 0;
gianni@22023 2190 err_free:
keir@21580 2191 flexarray_free(back);
keir@21580 2192 flexarray_free(front);
gianni@22023 2193 err:
gianni@22023 2194 libxl_free_all(&gc);
gianni@22023 2195 return rc;
keir@21580 2196 }
keir@21408 2197
ian@21930 2198 libxl_net2info *libxl_device_net2_list(libxl_ctx *ctx, uint32_t domid, unsigned int *nb)
keir@21581 2199 {
gianni@22023 2200 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@21581 2201 char *dompath, *net2_path_fe;
keir@21581 2202 char **l;
keir@21581 2203 char *val, *tok;
keir@21581 2204 unsigned int nb_net2s, i;
keir@21581 2205 libxl_net2info *res, *net2s;
keir@21581 2206
gianni@22023 2207 dompath = libxl_xs_get_dompath(&gc, domid);
gianni@22023 2208 if (!dompath)
gianni@22023 2209 goto err;
gianni@22023 2210 l = libxl_xs_directory(&gc, XBT_NULL,
gianni@22023 2211 libxl_sprintf(&gc, "%s/device/vif2", dompath), &nb_net2s);
gianni@22023 2212 if (!l)
gianni@22023 2213 goto err;
gianni@22023 2214 res = calloc(nb_net2s, sizeof (libxl_net2info));
gianni@22023 2215 if (!res)
gianni@22023 2216 goto err;
keir@21581 2217 net2s = res;
keir@21581 2218 for (*nb = nb_net2s; nb_net2s > 0; --nb_net2s, ++l, ++net2s) {
gianni@22023 2219 net2_path_fe = libxl_sprintf(&gc, "%s/device/vif2/%s", dompath, *l);
gianni@22023 2220
gianni@22023 2221 net2s->backend = libxl_xs_read(&gc, XBT_NULL,
gianni@22023 2222 libxl_sprintf(&gc, "%s/backend", net2_path_fe));
gianni@22023 2223 val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/backend-id", net2_path_fe));
keir@21581 2224 net2s->backend_id = val ? strtoul(val, NULL, 10) : -1;
keir@21581 2225
keir@21581 2226 net2s->devid = strtoul(*l, NULL, 10);
gianni@22023 2227 val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/state", net2_path_fe));
keir@21581 2228 net2s->state = val ? strtoul(val, NULL, 10) : -1;
keir@21581 2229
gianni@22023 2230 val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/mac", net2_path_fe));
keir@21581 2231 for (i = 0, tok = strtok(val, ":"); tok && (i < 6);
keir@21581 2232 ++i, tok = strtok(NULL, ":")) {
keir@21581 2233 net2s->mac[i] = strtoul(tok, NULL, 16);
keir@21581 2234 }
gianni@22023 2235 val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/remote-trusted", net2_path_fe));
keir@21581 2236 net2s->trusted = val ? strtoul(val, NULL, 10) : -1;
keir@21581 2237
gianni@22023 2238 val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/remote-mac", net2_path_fe));
keir@21581 2239 for (i = 0, tok = strtok(val, ":"); tok && (i < 6);
keir@21581 2240 ++i, tok = strtok(NULL, ":")) {
keir@21581 2241 net2s->back_mac[i] = strtoul(tok, NULL, 16);
keir@21581 2242 }
gianni@22023 2243 val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/filter-mac", net2_path_fe));
keir@21581 2244 net2s->filter_mac = val ? strtoul(val, NULL, 10) : -1;
keir@21581 2245
gianni@22023 2246 net2s->frontend = libxl_xs_read(&gc, XBT_NULL,
gianni@22023 2247 libxl_sprintf(&gc, "%s/frontend", net2s->backend));
gianni@22023 2248 val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/frontend-id", net2s->backend));
keir@21581 2249 net2s->frontend_id = val ? strtoul(val, NULL, 10) : -1;
keir@21581 2250 }
keir@21581 2251
gianni@22023 2252 libxl_free_all(&gc);
keir@21581 2253 return res;
gianni@22023 2254 err:
gianni@22023 2255 libxl_free_all(&gc);
gianni@22023 2256 return NULL;
keir@21581 2257 }
keir@21581 2258
ian@21930 2259 int libxl_device_net2_del(libxl_ctx *ctx, libxl_device_net2 *net2, int wait)
keir@21582 2260 {
keir@21582 2261 libxl_device device;
keir@21582 2262
keir@21582 2263 device.backend_devid = net2->devid;
keir@21582 2264 device.backend_domid = net2->backend_domid;
keir@21582 2265 device.backend_kind = DEVICE_VIF2;
keir@21582 2266 device.devid = net2->devid;
keir@21582 2267 device.domid = net2->domid;
keir@21582 2268 device.kind = DEVICE_VIF2;
keir@21582 2269
keir@21582 2270 return libxl_device_del(ctx, &device, wait);
keir@21582 2271 }
keir@21582 2272
keir@21581 2273
keir@20462 2274 /******************************************************************************/
ian@21930 2275 int libxl_device_console_add(libxl_ctx *ctx, uint32_t domid, libxl_device_console *console)
keir@20462 2276 {
gianni@22023 2277 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@20509 2278 flexarray_t *front;
keir@20509 2279 flexarray_t *back;
keir@20509 2280 unsigned int boffset = 0;
keir@20509 2281 unsigned int foffset = 0;
keir@20509 2282 libxl_device device;
gianni@22023 2283 int rc;
keir@20509 2284
keir@20509 2285 if (console->build_state) {
keir@20509 2286 xs_transaction_t t;
stefano@22040 2287 char **ents = (char **) libxl_calloc(&gc, 11, sizeof(char *));
keir@20516 2288 ents[0] = "console/port";
gianni@22023 2289 ents[1] = libxl_sprintf(&gc, "%"PRIu32, console->build_state->console_port);
keir@20516 2290 ents[2] = "console/ring-ref";
gianni@22023 2291 ents[3] = libxl_sprintf(&gc, "%lu", console->build_state->console_mfn);
keir@20516 2292 ents[4] = "console/limit";
gianni@22023 2293 ents[5] = libxl_sprintf(&gc, "%d", LIBXL_XENCONSOLE_LIMIT);
keir@20516 2294 ents[6] = "console/type";
stefano@22040 2295 if (console->consback == LIBXL_CONSBACK_XENCONSOLED)
keir@20509 2296 ents[7] = "xenconsoled";
keir@20509 2297 else
keir@20509 2298 ents[7] = "ioemu";
stefano@22040 2299 ents[8] = "console/output";
stefano@22040 2300 ents[9] = console->output;
keir@20509 2301 retry_transaction:
keir@20509 2302 t = xs_transaction_start(ctx->xsh);
gianni@22023 2303 libxl_xs_writev(&gc, t, libxl_xs_get_dompath(&gc, console->domid), ents);
keir@20509 2304 if (!xs_transaction_end(ctx->xsh, t, 0))
keir@20509 2305 if (errno == EAGAIN)
keir@20509 2306 goto retry_transaction;
keir@20509 2307 }
keir@20509 2308
keir@20509 2309 front = flexarray_make(16, 1);
gianni@22023 2310 if (!front) {
gianni@22023 2311 rc = ERROR_NOMEM;
gianni@22023 2312 goto out;
gianni@22023 2313 }
keir@20509 2314 back = flexarray_make(16, 1);
gianni@22023 2315 if (!back) {
gianni@22023 2316 rc = ERROR_NOMEM;
gianni@22023 2317 goto out_free;
gianni@22023 2318 }
keir@20509 2319
keir@20509 2320 device.backend_devid = console->devid;
keir@20509 2321 device.backend_domid = console->backend_domid;
keir@20509 2322 device.backend_kind = DEVICE_CONSOLE;
keir@20509 2323 device.devid = console->devid;
keir@20509 2324 device.domid = console->domid;
keir@20509 2325 device.kind = DEVICE_CONSOLE;
keir@20509 2326
keir@20516 2327 flexarray_set(back, boffset++, "frontend-id");
gianni@22023 2328 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", console->domid));
keir@20516 2329 flexarray_set(back, boffset++, "online");
keir@20516 2330 flexarray_set(back, boffset++, "1");
keir@20516 2331 flexarray_set(back, boffset++, "state");
gianni@22023 2332 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", 1));
keir@20516 2333 flexarray_set(back, boffset++, "domain");
gianni@22023 2334 flexarray_set(back, boffset++, _libxl_domid_to_name(&gc, domid));
keir@20516 2335 flexarray_set(back, boffset++, "protocol");
keir@20516 2336 flexarray_set(back, boffset++, LIBXL_XENCONSOLE_PROTOCOL);
keir@20509 2337
stefano@22040 2338 /* if devid == 0 do not add the frontend to device/console/ because
stefano@22040 2339 * it has already been added to console/ */
stefano@22040 2340 if (device.devid > 0) {
stefano@22040 2341 flexarray_set(front, foffset++, "backend-id");
stefano@22040 2342 flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", console->backend_domid));
stefano@22040 2343 flexarray_set(front, foffset++, "state");
stefano@22040 2344 flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", 1));
stefano@22040 2345 flexarray_set(front, foffset++, "limit");
stefano@22040 2346 flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", LIBXL_XENCONSOLE_LIMIT));
stefano@22040 2347 flexarray_set(front, foffset++, "protocol");
stefano@22040 2348 flexarray_set(front, foffset++, LIBXL_XENCONSOLE_PROTOCOL);
stefano@22040 2349 flexarray_set(front, foffset++, "type");
stefano@22040 2350 if (console->consback == LIBXL_CONSBACK_XENCONSOLED)
stefano@22040 2351 flexarray_set(front, foffset++, "xenconsoled");
stefano@22040 2352 else
stefano@22040 2353 flexarray_set(front, foffset++, "ioemu");
stefano@22040 2354 flexarray_set(front, foffset++, "output");
stefano@22040 2355 flexarray_set(front, foffset++, console->output);
stefano@22040 2356 }
keir@20509 2357
keir@20509 2358 libxl_device_generic_add(ctx, &device,
gianni@22023 2359 libxl_xs_kvs_of_flexarray(&gc, back, boffset),
gianni@22023 2360 libxl_xs_kvs_of_flexarray(&gc, front, foffset));
gianni@22023 2361 rc = 0;
gianni@22023 2362 out_free:
keir@20516 2363 flexarray_free(back);
keir@20516 2364 flexarray_free(front);
gianni@22023 2365 out:
gianni@22023 2366 libxl_free_all(&gc);
gianni@22023 2367 return rc;
keir@20509 2368 }
keir@20509 2369
keir@20509 2370 /******************************************************************************/
ian@21930 2371 int libxl_device_vkb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vkb *vkb)
keir@20509 2372 {
gianni@22023 2373 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@20509 2374 flexarray_t *front;
keir@20509 2375 flexarray_t *back;
keir@20509 2376 unsigned int boffset = 0;
keir@20509 2377 unsigned int foffset = 0;
keir@20509 2378 libxl_device device;
gianni@22023 2379 int rc;
keir@20509 2380
keir@20509 2381 front = flexarray_make(16, 1);
gianni@22023 2382 if (!front) {
gianni@22023 2383 rc = ERROR_NOMEM;
gianni@22023 2384 goto out;
gianni@22023 2385 }
keir@20509 2386 back = flexarray_make(16, 1);
gianni@22023 2387 if (!back) {
gianni@22023 2388 rc = ERROR_NOMEM;
gianni@22023 2389 goto out_free;
gianni@22023 2390 }
keir@20509 2391
keir@20509 2392 device.backend_devid = vkb->devid;
keir@20509 2393 device.backend_domid = vkb->backend_domid;
keir@20509 2394 device.backend_kind = DEVICE_VKBD;
keir@20509 2395 device.devid = vkb->devid;
keir@20509 2396 device.domid = vkb->domid;
keir@20509 2397 device.kind = DEVICE_VKBD;
keir@20509 2398
keir@20516 2399 flexarray_set(back, boffset++, "frontend-id");
gianni@22023 2400 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", vkb->domid));
keir@20516 2401 flexarray_set(back, boffset++, "online");
keir@20516 2402 flexarray_set(back, boffset++, "1");
keir@20516 2403 flexarray_set(back, boffset++, "state");
gianni@22023 2404 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", 1));
keir@20516 2405 flexarray_set(back, boffset++, "domain");
gianni@22023 2406 flexarray_set(back, boffset++, _libxl_domid_to_name(&gc, domid));
keir@20509 2407
keir@20516 2408 flexarray_set(front, foffset++, "backend-id");
gianni@22023 2409 flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", vkb->backend_domid));
keir@20516 2410 flexarray_set(front, foffset++, "state");
gianni@22023 2411 flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", 1));
keir@20509 2412
keir@20509 2413 libxl_device_generic_add(ctx, &device,
gianni@22023 2414 libxl_xs_kvs_of_flexarray(&gc, back, boffset),
gianni@22023 2415 libxl_xs_kvs_of_flexarray(&gc, front, foffset));
gianni@22023 2416 rc = 0;
gianni@22023 2417 out_free:
keir@20516 2418 flexarray_free(back);
keir@20516 2419 flexarray_free(front);
gianni@22023 2420 out:
gianni@22023 2421 libxl_free_all(&gc);
gianni@22023 2422 return rc;
keir@20462 2423 }
keir@20462 2424
ian@21930 2425 int libxl_device_vkb_clean_shutdown(libxl_ctx *ctx, uint32_t domid)
keir@20462 2426 {
keir@20462 2427 return ERROR_NI;
keir@20462 2428 }
keir@20462 2429
ian@21930 2430 int libxl_device_vkb_hard_shutdown(libxl_ctx *ctx, uint32_t domid)
keir@20462 2431 {
keir@20462 2432 return ERROR_NI;
keir@20462 2433 }
keir@20462 2434
ian@21930 2435 libxl_device_disk *libxl_device_disk_list(libxl_ctx *ctx, uint32_t domid, int *num)
keir@20637 2436 {
gianni@22023 2437 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@20637 2438 char *be_path_tap, *be_path_vbd;
keir@21411 2439 libxl_device_disk *dend, *disks, *ret = NULL;
keir@21411 2440 char **b, **l = NULL;
gianni@22042 2441 unsigned int numl, len;
keir@20637 2442 char *type;
keir@20637 2443
gianni@22023 2444 be_path_vbd = libxl_sprintf(&gc, "%s/backend/vbd/%d", libxl_xs_get_dompath(&gc, 0), domid);
gianni@22023 2445 be_path_tap = libxl_sprintf(&gc, "%s/backend/tap/%d", libxl_xs_get_dompath(&gc, 0), domid);
gianni@22023 2446
gianni@22023 2447 b = l = libxl_xs_directory(&gc, XBT_NULL, be_path_vbd, &numl);
keir@20637 2448 if (l) {
keir@21411 2449 ret = realloc(ret, sizeof(libxl_device_disk) * numl);
keir@21411 2450 disks = ret;
keir@21411 2451 *num = numl;
keir@21411 2452 dend = ret + *num;
keir@21411 2453 for (; disks < dend; ++disks, ++l) {
keir@21411 2454 disks->backend_domid = 0;
keir@21411 2455 disks->domid = domid;
gianni@22042 2456 disks->physpath = xs_read(ctx->xsh, XBT_NULL, libxl_sprintf(&gc, "%s/%s/params", be_path_vbd, *l), &len);
gianni@22023 2457 libxl_string_to_phystype(ctx, libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/%s/type", be_path_vbd, *l)), &(disks->phystype));
gianni@22042 2458 disks->virtpath = xs_read(ctx->xsh, XBT_NULL, libxl_sprintf(&gc, "%s/%s/dev", be_path_vbd, *l), &len);
gianni@22023 2459 disks->unpluggable = atoi(libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/%s/removable", be_path_vbd, *l)));
gianni@22023 2460 if (!strcmp(libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/%s/mode", be_path_vbd, *l)), "w"))
keir@21411 2461 disks->readwrite = 1;
keir@20637 2462 else
keir@21411 2463 disks->readwrite = 0;
gianni@22023 2464 type = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/device-type", libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/%s/frontend", be_path_vbd, *l))));
keir@21411 2465 disks->is_cdrom = !strcmp(type, "cdrom");
keir@20637 2466 }
keir@20637 2467 }
gianni@22023 2468 b = l = libxl_xs_directory(&gc, XBT_NULL, be_path_tap, &numl);
keir@20637 2469 if (l) {
keir@21411 2470 ret = realloc(ret, sizeof(libxl_device_disk) * (*num + numl));
keir@21411 2471 disks = ret + *num;
keir@21411 2472 *num += numl;
keir@21411 2473 for (dend = ret + *num; disks < dend; ++disks, ++l) {
keir@21411 2474 disks->backend_domid = 0;
keir@21411 2475 disks->domid = domid;
gianni@22042 2476 disks->physpath = xs_read(ctx->xsh, XBT_NULL, libxl_sprintf(&gc, "%s/%s/params", be_path_tap, *l), &len);
gianni@22023 2477 libxl_string_to_phystype(ctx, libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/%s/type", be_path_tap, *l)), &(disks->phystype));
gianni@22042 2478 disks->virtpath = xs_read(ctx->xsh, XBT_NULL, libxl_sprintf(&gc, "%s/%s/dev", be_path_tap, *l), &len);
gianni@22023 2479 disks->unpluggable = atoi(libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/%s/removable", be_path_tap, *l)));
gianni@22023 2480 if (!strcmp(libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/%s/mode", be_path_tap, *l)), "w"))
keir@21411 2481 disks->readwrite = 1;
keir@20637 2482 else
keir@21411 2483 disks->readwrite = 0;
gianni@22023 2484 type = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/device-type", libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/%s/frontend", be_path_tap, *l))));
keir@21411 2485 disks->is_cdrom = !strcmp(type, "cdrom");
keir@20637 2486 }
keir@20637 2487 }
gianni@22023 2488 libxl_free_all(&gc);
keir@21411 2489 return ret;
keir@21411 2490 }
keir@21411 2491
ian@21930 2492 int libxl_device_disk_getinfo(libxl_ctx *ctx, uint32_t domid,
keir@21411 2493 libxl_device_disk *disk, libxl_diskinfo *diskinfo)
keir@21411 2494 {
gianni@22023 2495 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@21411 2496 char *dompath, *diskpath;
keir@21411 2497 char *val;
keir@21411 2498
gianni@22023 2499 dompath = libxl_xs_get_dompath(&gc, domid);
keir@21411 2500 diskinfo->devid = device_disk_dev_number(disk->virtpath);
keir@21411 2501
keir@21411 2502 /* tap devices entries in xenstore are written as vbd devices. */
gianni@22023 2503 diskpath = libxl_sprintf(&gc, "%s/device/vbd/%d", dompath, diskinfo->devid);
ian@22059 2504 diskinfo->backend = xs_read(ctx->xsh, XBT_NULL,
ian@22059 2505 libxl_sprintf(&gc, "%s/backend", diskpath), NULL);
keir@21411 2506 if (!diskinfo->backend) {
gianni@22023 2507 libxl_free_all(&gc);
keir@21411 2508 return ERROR_FAIL;
keir@21411 2509 }
gianni@22023 2510 val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/backend-id", diskpath));
keir@21411 2511 diskinfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
gianni@22023 2512 val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/state", diskpath));
keir@21411 2513 diskinfo->state = val ? strtoul(val, NULL, 10) : -1;
gianni@22023 2514 val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/event-channel", diskpath));
keir@21411 2515 diskinfo->evtch = val ? strtoul(val, NULL, 10) : -1;
gianni@22023 2516 val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/ring-ref", diskpath));
keir@21411 2517 diskinfo->rref = val ? strtoul(val, NULL, 10) : -1;
ian@22059 2518 diskinfo->frontend = xs_read(ctx->xsh, XBT_NULL,
ian@22059 2519 libxl_sprintf(&gc, "%s/frontend", diskinfo->backend), NULL);
gianni@22023 2520 val = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/frontend-id", diskinfo->backend));
keir@21411 2521 diskinfo->frontend_id = val ? strtoul(val, NULL, 10) : -1;
keir@21411 2522
gianni@22023 2523 libxl_free_all(&gc);
keir@21411 2524 return 0;
keir@20637 2525 }
keir@20637 2526
ian@21930 2527 int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk)
keir@20637 2528 {
keir@20637 2529 int num, i;
keir@20637 2530 uint32_t stubdomid;
keir@20637 2531 libxl_device_disk *disks;
keir@20637 2532
keir@20637 2533 if (!disk->physpath) {
keir@20637 2534 disk->physpath = "";
keir@20637 2535 disk->phystype = PHYSTYPE_PHY;
keir@20637 2536 }
keir@20637 2537 disks = libxl_device_disk_list(ctx, domid, &num);
keir@20637 2538 for (i = 0; i < num; i++) {
keir@20637 2539 if (disks[i].is_cdrom && !strcmp(disk->virtpath, disks[i].virtpath))
keir@20637 2540 /* found */
keir@20637 2541 break;
keir@20637 2542 }
keir@20637 2543 if (i == num) {
keir@20637 2544 XL_LOG(ctx, XL_LOG_ERROR, "Virtual device not found");
gianni@22023 2545 free(disks);
gianni@21892 2546 return ERROR_FAIL;
keir@20637 2547 }
keir@20637 2548 libxl_device_disk_del(ctx, disks + i, 1);
keir@20637 2549 libxl_device_disk_add(ctx, domid, disk);
keir@20637 2550 stubdomid = libxl_get_stubdom_id(ctx, domid);
keir@20637 2551 if (stubdomid) {
keir@20781 2552 disks[i].domid = stubdomid;
keir@20637 2553 libxl_device_disk_del(ctx, disks + i, 1);
keir@20781 2554 disk->domid = stubdomid;
keir@20637 2555 libxl_device_disk_add(ctx, stubdomid, disk);
keir@20781 2556 disk->domid = domid;
keir@20637 2557 }
gianni@22042 2558 /* FIXME: leaks disk paths */
gianni@22023 2559 free(disks);
keir@20637 2560 return 0;
keir@20637 2561 }
keir@20637 2562
keir@20462 2563 /******************************************************************************/
gianni@22023 2564 static int libxl_build_xenpv_qemu_args(libxl_gc *gc,
stefano@22040 2565 uint32_t domid,
keir@20509 2566 libxl_device_vfb *vfb,
keir@20860 2567 libxl_device_model_info *info)
keir@20860 2568 {
gianni@22023 2569 libxl_ctx *ctx = libxl_gc_owner(gc);
keir@20509 2570 memset(info, 0x00, sizeof(libxl_device_model_info));
keir@20509 2571
stefano@22041 2572 if (vfb != NULL) {
stefano@22041 2573 info->vnc = vfb->vnc;
stefano@22041 2574 if (vfb->vnclisten)
stefano@22041 2575 info->vnclisten = libxl_strdup(gc, vfb->vnclisten);
stefano@22041 2576 info->vncdisplay = vfb->vncdisplay;
stefano@22041 2577 info->vncunused = vfb->vncunused;
stefano@22041 2578 if (vfb->vncpasswd)
stefano@22041 2579 info->vncpasswd = vfb->vncpasswd;
stefano@22041 2580 if (vfb->keymap)
stefano@22041 2581 info->keymap = libxl_strdup(gc, vfb->keymap);
stefano@22041 2582 info->sdl = vfb->sdl;
stefano@22041 2583 info->opengl = vfb->opengl;
stefano@22041 2584 } else
stefano@22041 2585 info->nographic = 1;
stefano@22040 2586 info->domid = domid;
stefano@22040 2587 info->dom_name = libxl_domid_to_name(ctx, domid);
gianni@22023 2588 info->device_model = libxl_abs_path(gc, "qemu-dm", libxl_libexec_path());
keir@20509 2589 info->type = XENPV;
keir@20509 2590 return 0;
keir@20509 2591 }
keir@20509 2592
stefano@22040 2593 int libxl_create_xenpv_qemu(libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb,
ian@21930 2594 libxl_device_model_starting **starting_r)
keir@20509 2595 {
gianni@22023 2596 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@20509 2597 libxl_device_model_info info;
keir@20509 2598
stefano@22040 2599 libxl_build_xenpv_qemu_args(&gc, domid, vfb, &info);
keir@20542 2600 libxl_create_device_model(ctx, &info, NULL, 0, NULL, 0, starting_r);
gianni@22023 2601 libxl_free_all(&gc);
keir@20509 2602 return 0;
keir@20509 2603 }
keir@20509 2604
ian@21930 2605 int libxl_device_vfb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb)
keir@20462 2606 {
gianni@22023 2607 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@20509 2608 flexarray_t *front;
keir@20509 2609 flexarray_t *back;
keir@20509 2610 unsigned int boffset = 0;
keir@20509 2611 unsigned int foffset = 0;
keir@20509 2612 libxl_device device;
gianni@22023 2613 int rc;
keir@20509 2614
keir@20509 2615 front = flexarray_make(16, 1);
gianni@22023 2616 if (!front) {
gianni@22023 2617 rc = ERROR_NOMEM;
gianni@22023 2618 goto out;
gianni@22023 2619 }
keir@20509 2620 back = flexarray_make(16, 1);
gianni@22023 2621 if (!back) {
gianni@22023 2622 rc = ERROR_NOMEM;
gianni@22023 2623 goto out_free;
gianni@22023 2624 }
keir@20509 2625
keir@20509 2626 device.backend_devid = vfb->devid;
keir@20509 2627 device.backend_domid = vfb->backend_domid;
keir@20509 2628 device.backend_kind = DEVICE_VFB;
keir@20509 2629 device.devid = vfb->devid;
keir@20509 2630 device.domid = vfb->domid;
keir@20509 2631 device.kind = DEVICE_VFB;
keir@20509 2632
keir@20516 2633 flexarray_set(back, boffset++, "frontend-id");
gianni@22023 2634 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", vfb->domid));
keir@20516 2635 flexarray_set(back, boffset++, "online");
keir@20516 2636 flexarray_set(back, boffset++, "1");
keir@20516 2637 flexarray_set(back, boffset++, "state");
gianni@22023 2638 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", 1));
keir@20516 2639 flexarray_set(back, boffset++, "domain");
gianni@22023 2640 flexarray_set(back, boffset++, _libxl_domid_to_name(&gc, domid));
keir@20516 2641 flexarray_set(back, boffset++, "vnc");
gianni@22023 2642 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", vfb->vnc));
keir@20516 2643 flexarray_set(back, boffset++, "vnclisten");
keir@20516 2644 flexarray_set(back, boffset++, vfb->vnclisten);
keir@21362 2645 flexarray_set(back, boffset++, "vncpasswd");
keir@21362 2646 flexarray_set(back, boffset++, vfb->vncpasswd);
keir@20516 2647 flexarray_set(back, boffset++, "vncdisplay");
gianni@22023 2648 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", vfb->vncdisplay));
keir@20516 2649 flexarray_set(back, boffset++, "vncunused");
gianni@22023 2650 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", vfb->vncunused));
keir@20516 2651 flexarray_set(back, boffset++, "sdl");
gianni@22023 2652 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", vfb->sdl));
keir@20516 2653 flexarray_set(back, boffset++, "opengl");
gianni@22023 2654 flexarray_set(back, boffset++, libxl_sprintf(&gc, "%d", vfb->opengl));
keir@20509 2655 if (vfb->xauthority) {
keir@20516 2656 flexarray_set(back, boffset++, "xauthority");
keir@20516 2657 flexarray_set(back, boffset++, vfb->xauthority);
keir@20509 2658 }
keir@20509 2659 if (vfb->display) {
keir@20516 2660 flexarray_set(back, boffset++, "display");
keir@20516 2661 flexarray_set(back, boffset++, vfb->display);
keir@20509 2662 }
keir@20509 2663
keir@20516 2664 flexarray_set(front, foffset++, "backend-id");
gianni@22023 2665 flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", vfb->backend_domid));
keir@20516 2666 flexarray_set(front, foffset++, "state");
gianni@22023 2667 flexarray_set(front, foffset++, libxl_sprintf(&gc, "%d", 1));
keir@20509 2668
keir@20509 2669 libxl_device_generic_add(ctx, &device,
gianni@22023 2670 libxl_xs_kvs_of_flexarray(&gc, back, boffset),
gianni@22023 2671 libxl_xs_kvs_of_flexarray(&gc, front, foffset));
gianni@22023 2672 rc = 0;
gianni@22023 2673 out_free:
keir@20509 2674 flexarray_free(front);
keir@20509 2675 flexarray_free(back);
gianni@22023 2676 out:
gianni@22023 2677 libxl_free_all(&gc);
gianni@22023 2678 return rc;
keir@20462 2679 }
keir@20462 2680
ian@21930 2681 int libxl_device_vfb_clean_shutdown(libxl_ctx *ctx, uint32_t domid)
keir@20462 2682 {
keir@20462 2683 return ERROR_NI;
keir@20462 2684 }
keir@20462 2685
ian@21930 2686 int libxl_device_vfb_hard_shutdown(libxl_ctx *ctx, uint32_t domid)
keir@20462 2687 {
keir@20462 2688 return ERROR_NI;
keir@20462 2689 }
keir@20462 2690
keir@20462 2691 /******************************************************************************/
keir@20482 2692
ian@21930 2693 int libxl_domain_setmaxmem(libxl_ctx *ctx, uint32_t domid, uint32_t max_memkb)
keir@21404 2694 {
gianni@22023 2695 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@21404 2696 char *mem, *endptr;
keir@21404 2697 uint32_t memorykb;
gianni@22023 2698 char *dompath = libxl_xs_get_dompath(&gc, domid);
gianni@22023 2699 int rc = 1;
gianni@22023 2700
gianni@22023 2701 mem = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/memory/target", dompath));
keir@21404 2702 if (!mem) {
keir@21404 2703 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "cannot get memory info from %s/memory/target\n", dompath);
gianni@22023 2704 goto out;
keir@21404 2705 }
keir@21404 2706 memorykb = strtoul(mem, &endptr, 10);
keir@21404 2707 if (*endptr != '\0') {
keir@21404 2708 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "invalid memory %s from %s/memory/target\n", mem, dompath);
gianni@22023 2709 goto out;
keir@21404 2710 }
keir@21404 2711
keir@21404 2712 if (max_memkb < memorykb) {
keir@21404 2713 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "memory_static_max must be greater than or or equal to memory_dynamic_max\n");
gianni@22023 2714 goto out;
keir@21404 2715 }
keir@21404 2716
keir@21404 2717 if (domid != 0)
gianni@22023 2718 libxl_xs_write(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/memory/static-max", dompath), "%"PRIu32, max_memkb);
gianni@22023 2719
gianni@22023 2720 rc = 0;
gianni@22023 2721 out:
gianni@22023 2722 libxl_free_all(&gc);
gianni@22023 2723 return rc;
keir@21404 2724 }
keir@21404 2725
ian@21930 2726 int libxl_set_memory_target(libxl_ctx *ctx, uint32_t domid, uint32_t target_memkb, int enforce)
keir@20647 2727 {
gianni@22023 2728 libxl_gc gc = LIBXL_INIT_GC(ctx);
gianni@22023 2729 int rc = 1;
keir@21422 2730 uint32_t memorykb = 0, videoram = 0;
keir@21405 2731 char *memmax, *endptr, *videoram_s = NULL;
gianni@22023 2732 char *dompath = libxl_xs_get_dompath(&gc, domid);
keir@21374 2733 xc_domaininfo_t info;
ian@21930 2734 libxl_dominfo ptr;
keir@21374 2735 char *uuid;
keir@20542 2736
keir@21405 2737 if (domid) {
gianni@22023 2738 memmax = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/memory/static-max", dompath));
keir@21405 2739 if (!memmax) {
keir@21405 2740 XL_LOG_ERRNO(ctx, XL_LOG_ERROR,
keir@21405 2741 "cannot get memory info from %s/memory/static-max\n", dompath);
gianni@22023 2742 goto out;
keir@21405 2743 }
keir@21405 2744 memorykb = strtoul(memmax, &endptr, 10);
keir@21405 2745 if (*endptr != '\0') {
keir@21405 2746 XL_LOG_ERRNO(ctx, XL_LOG_ERROR,
keir@21405 2747 "invalid max memory %s from %s/memory/static-max\n", memmax, dompath);
gianni@22023 2748 goto out;
keir@21405 2749 }
keir@21405 2750
keir@21405 2751 if (target_memkb > memorykb) {
keir@21504 2752 XL_LOG(ctx, XL_LOG_ERROR,
keir@21405 2753 "memory_dynamic_max must be less than or equal to memory_static_max\n");
gianni@22023 2754 goto out;
keir@21405 2755 }
keir@21405 2756 }
keir@21405 2757
gianni@22023 2758 videoram_s = libxl_xs_read(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/memory/videoram", dompath));
keir@21314 2759 videoram = videoram_s ? atoi(videoram_s) : 0;
keir@20647 2760
gianni@22023 2761 libxl_xs_write(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/memory/target", dompath), "%"PRIu32, target_memkb);
keir@21374 2762
keir@21374 2763 rc = xc_domain_getinfolist(ctx->xch, domid, 1, &info);
keir@21374 2764 if (rc != 1 || info.domain != domid)
gianni@22023 2765 goto out;
keir@21374 2766 xcinfo2xlinfo(&info, &ptr);
gianni@22047 2767 uuid = libxl_uuid2string(&gc, ptr.uuid);
gianni@22023 2768 libxl_xs_write(&gc, XBT_NULL, libxl_sprintf(&gc, "/vm/%s/memory", uuid), "%"PRIu32, target_memkb / 1024);
keir@21374 2769
keir@21422 2770 if (enforce || !domid)
keir@21422 2771 memorykb = target_memkb;
keir@21422 2772 rc = xc_domain_setmaxmem(ctx->xch, domid, memorykb + LIBXL_MAXMEM_CONSTANT);
keir@21422 2773 if (rc != 0)
gianni@22023 2774 goto out;
keir@20647 2775 rc = xc_domain_memory_set_pod_target(ctx->xch, domid, (target_memkb - videoram) / 4, NULL, NULL, NULL);
gianni@22023 2776
gianni@22023 2777 out:
gianni@22023 2778 libxl_free_all(&gc);
keir@20647 2779 return rc;
keir@20647 2780 }
keir@20875 2781
ian@21930 2782 int libxl_button_press(libxl_ctx *ctx, uint32_t domid, libxl_button button)
keir@20875 2783 {
keir@20875 2784 int rc = -1;
keir@20875 2785
keir@20875 2786 switch (button) {
keir@20875 2787 case POWER_BUTTON:
keir@20875 2788 rc = xc_domain_send_trigger(ctx->xch, domid, XEN_DOMCTL_SENDTRIGGER_POWER, 0);
keir@20875 2789 break;
keir@20875 2790 case SLEEP_BUTTON:
keir@20875 2791 rc = xc_domain_send_trigger(ctx->xch, domid, XEN_DOMCTL_SENDTRIGGER_SLEEP, 0);
keir@20875 2792 break;
keir@20875 2793 default:
keir@20875 2794 break;
keir@20875 2795 }
keir@20875 2796
keir@20875 2797 return rc;
keir@20875 2798 }
keir@21141 2799
ian@21930 2800 int libxl_get_physinfo(libxl_ctx *ctx, libxl_physinfo *physinfo)
keir@21141 2801 {
keir@21141 2802 xc_physinfo_t xcphysinfo = { 0 };
keir@21141 2803 int rc;
keir@21141 2804
keir@21141 2805 rc = xc_physinfo(ctx->xch, &xcphysinfo);
keir@21141 2806 if (rc != 0) {
gianni@21892 2807 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "getting physinfo");
gianni@21892 2808 return ERROR_FAIL;
keir@21141 2809 }
keir@21141 2810 physinfo->threads_per_core = xcphysinfo.threads_per_core;
keir@21141 2811 physinfo->cores_per_socket = xcphysinfo.cores_per_socket;
keir@21142 2812 physinfo->max_cpu_id = xcphysinfo.max_cpu_id;
keir@21141 2813 physinfo->nr_cpus = xcphysinfo.nr_cpus;
keir@21141 2814 physinfo->cpu_khz = xcphysinfo.cpu_khz;
keir@21141 2815 physinfo->total_pages = xcphysinfo.total_pages;
keir@21141 2816 physinfo->free_pages = xcphysinfo.free_pages;
keir@21141 2817 physinfo->scrub_pages = xcphysinfo.scrub_pages;
keir@21264 2818 physinfo->nr_nodes = xcphysinfo.nr_nodes;
keir@21264 2819 memcpy(physinfo->hw_cap,xcphysinfo.hw_cap, sizeof(physinfo->hw_cap));
keir@21264 2820 physinfo->phys_cap = xcphysinfo.capabilities;
keir@21264 2821
keir@21141 2822 return 0;
keir@21141 2823 }
keir@21141 2824
gianni@22008 2825 static void do_free_version_info(libxl_version_info *info)
gianni@22008 2826 {
gianni@22008 2827 free(info->xen_version_extra);
gianni@22008 2828 free(info->compiler);
gianni@22008 2829 free(info->compile_by);
gianni@22008 2830 free(info->compile_domain);
gianni@22008 2831 free(info->compile_date);
gianni@22008 2832 free(info->capabilities);
gianni@22008 2833 free(info->changeset);
gianni@22008 2834 free(info->commandline);
gianni@22008 2835 }
gianni@22008 2836
ian@21930 2837 const libxl_version_info* libxl_get_version_info(libxl_ctx *ctx)
keir@21266 2838 {
keir@21266 2839 union {
keir@21266 2840 xen_extraversion_t xen_extra;
keir@21266 2841 xen_compile_info_t xen_cc;
keir@21266 2842 xen_changeset_info_t xen_chgset;
keir@21266 2843 xen_capabilities_info_t xen_caps;
keir@21266 2844 xen_platform_parameters_t p_parms;
keir@21266 2845 xen_commandline_t xen_commandline;
keir@21266 2846 } u;
keir@21266 2847 long xen_version;
keir@21266 2848 libxl_version_info *info = &ctx->version_info;
keir@21266 2849
keir@21266 2850 if (info->xen_version_extra != NULL)
keir@21266 2851 return info;
keir@21266 2852
keir@21266 2853 xen_version = xc_version(ctx->xch, XENVER_version, NULL);
keir@21266 2854 info->xen_version_major = xen_version >> 16;
keir@21266 2855 info->xen_version_minor = xen_version & 0xFF;
gianni@22008 2856
keir@21266 2857 xc_version(ctx->xch, XENVER_extraversion, &u.xen_extra);
gianni@22008 2858 info->xen_version_extra = strdup(u.xen_extra);
keir@21266 2859
keir@21266 2860 xc_version(ctx->xch, XENVER_compile_info, &u.xen_cc);
gianni@22008 2861 info->compiler = strdup(u.xen_cc.compiler);
gianni@22008 2862 info->compile_by = strdup(u.xen_cc.compile_by);
gianni@22008 2863 info->compile_domain = strdup(u.xen_cc.compile_domain);
gianni@22008 2864 info->compile_date = strdup(u.xen_cc.compile_date);
keir@21266 2865
keir@21266 2866 xc_version(ctx->xch, XENVER_capabilities, &u.xen_caps);
gianni@22008 2867 info->capabilities = strdup(u.xen_caps);
keir@21266 2868
keir@21266 2869 xc_version(ctx->xch, XENVER_changeset, &u.xen_chgset);
gianni@22008 2870 info->changeset = strdup(u.xen_chgset);
keir@21266 2871
keir@21266 2872 xc_version(ctx->xch, XENVER_platform_parameters, &u.p_parms);
keir@21266 2873 info->virt_start = u.p_parms.virt_start;
keir@21266 2874
keir@21266 2875 info->pagesize = xc_version(ctx->xch, XENVER_pagesize, NULL);
keir@21266 2876
keir@21266 2877 xc_version(ctx->xch, XENVER_commandline, &u.xen_commandline);
gianni@22008 2878 info->commandline = strdup(u.xen_commandline);
keir@21266 2879
keir@21266 2880 return info;
keir@21266 2881 }
keir@21266 2882
ian@21930 2883 libxl_vcpuinfo *libxl_list_vcpu(libxl_ctx *ctx, uint32_t domid,
sstabellini@22000 2884 int *nb_vcpu, int *nrcpus)
keir@21141 2885 {
ian@21930 2886 libxl_vcpuinfo *ptr, *ret;
keir@21141 2887 xc_domaininfo_t domaininfo;
keir@21141 2888 xc_vcpuinfo_t vcpuinfo;
keir@21141 2889 xc_physinfo_t physinfo = { 0 };
gianni@22015 2890 uint64_t *cpumaps;
gianni@22015 2891 unsigned num_cpuwords;
keir@21141 2892
keir@21141 2893 if (xc_domain_getinfolist(ctx->xch, domid, 1, &domaininfo) != 1) {
gianni@21892 2894 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "getting infolist");
keir@21141 2895 return NULL;
keir@21141 2896 }
keir@21141 2897 if (xc_physinfo(ctx->xch, &physinfo) == -1) {
gianni@21892 2898 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "getting physinfo");
keir@21141 2899 return NULL;
keir@21141 2900 }
sstabellini@22000 2901 *nrcpus = physinfo.max_cpu_id + 1;
gianni@22015 2902 ret = ptr = calloc(domaininfo.max_vcpu_id + 1, sizeof (libxl_vcpuinfo));
keir@21141 2903 if (!ptr) {
keir@21141 2904 return NULL;
keir@21141 2905 }
keir@21141 2906
gianni@22015 2907 num_cpuwords = ((physinfo.max_cpu_id + 64) / 64);
gianni@22015 2908 cpumaps = calloc(num_cpuwords * sizeof(*cpumaps), domaininfo.max_vcpu_id + 1);
keir@21141 2909 for (*nb_vcpu = 0; *nb_vcpu <= domaininfo.max_vcpu_id; ++*nb_vcpu, ++ptr) {
gianni@22015 2910 ptr->cpumap = cpumaps + (num_cpuwords * *nb_vcpu);
keir@21141 2911 if (!ptr->cpumap) {
keir@21141 2912 return NULL;
keir@21141 2913 }
keir@21141 2914 if (xc_vcpu_getinfo(ctx->xch, domid, *nb_vcpu, &vcpuinfo) == -1) {
gianni@21892 2915 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "getting vcpu info");
keir@21141 2916 return NULL;
keir@21141 2917 }
sstabellini@22000 2918 if (xc_vcpu_getaffinity(ctx->xch, domid, *nb_vcpu,
sstabellini@22000 2919 ptr->cpumap, ((*nrcpus) + 7) / 8) == -1) {
gianni@21892 2920 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "getting vcpu affinity");
keir@21141 2921 return NULL;
keir@21141 2922 }
keir@21141 2923 ptr->vcpuid = *nb_vcpu;
keir@21141 2924 ptr->cpu = vcpuinfo.cpu;
keir@21141 2925 ptr->online = !!vcpuinfo.online;
keir@21141 2926 ptr->blocked = !!vcpuinfo.blocked;
keir@21141 2927 ptr->running = !!vcpuinfo.running;
keir@21141 2928 ptr->vcpu_time = vcpuinfo.cpu_time;
keir@21141 2929 }
keir@21141 2930 return ret;
keir@21141 2931 }
keir@21142 2932
gianni@22015 2933 void libxl_free_vcpu_list(libxl_vcpuinfo *vcpu)
gianni@22015 2934 {
gianni@22015 2935 if ( vcpu )
gianni@22015 2936 free(vcpu[0].cpumap);
gianni@22015 2937 free(vcpu);
gianni@22015 2938 }
gianni@22015 2939
ian@21930 2940 int libxl_set_vcpuaffinity(libxl_ctx *ctx, uint32_t domid, uint32_t vcpuid,
sstabellini@22000 2941 uint64_t *cpumap, int nrcpus)
keir@21142 2942 {
sstabellini@22000 2943 if (xc_vcpu_setaffinity(ctx->xch, domid, vcpuid, cpumap, (nrcpus + 7) / 8)) {
gianni@21892 2944 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "setting vcpu affinity");
gianni@21892 2945 return ERROR_FAIL;
gianni@21892 2946 }
gianni@21892 2947 return 0;
keir@21142 2948 }
keir@21143 2949
ian@21930 2950 int libxl_set_vcpucount(libxl_ctx *ctx, uint32_t domid, uint32_t count)
keir@21143 2951 {
gianni@22023 2952 libxl_gc gc = LIBXL_INIT_GC(ctx);
keir@21143 2953 xc_domaininfo_t domaininfo;
keir@21143 2954 char *dompath;
gianni@22023 2955 int i, rc = ERROR_FAIL;
keir@21143 2956
keir@21143 2957 if (xc_domain_getinfolist(ctx->xch, domid, 1, &domaininfo) != 1) {
gianni@21892 2958 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "getting domain info list");
gianni@22023 2959 goto out;
keir@21143 2960 }
keir@21143 2961 if (!count || ((domaininfo.max_vcpu_id + 1) < count)) {
gianni@22023 2962 rc = ERROR_INVAL;
gianni@22023 2963 goto out;
keir@21143 2964 }
gianni@22023 2965 if (!(dompath = libxl_xs_get_dompath(&gc, domid)))
gianni@22023 2966 goto out;
keir@21143 2967
keir@21143 2968 for (i = 0; i <= domaininfo.max_vcpu_id; ++i) {
gianni@22023 2969 libxl_xs_write(&gc, XBT_NULL,
gianni@22023 2970 libxl_sprintf(&gc, "%s/cpu/%u/availability", dompath, i),
keir@21143 2971 "%s", ((1 << i) & ((1 << count) - 1)) ? "online" : "offline");
keir@21143 2972 }
gianni@22023 2973 rc = 0;
gianni@22023 2974 out:
gianni@22023 2975 libxl_free_all(&gc);
gianni@22023 2976 return rc;
keir@21143 2977 }
keir@21265 2978
keir@21265 2979 /*
keir@21265 2980 * returns one of the XEN_SCHEDULER_* constants from public/domctl.h
keir@21265 2981 */
ian@21930 2982 int libxl_get_sched_id(libxl_ctx *ctx)
keir@21265 2983 {
keir@21265 2984 int sched, ret;
keir@21265 2985
gianni@21892 2986 if ((ret = xc_sched_id(ctx->xch, &sched)) != 0) {
gianni@21892 2987 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "getting domain info list");
gianni@21892 2988 return ERROR_FAIL;
gianni@21892 2989 }
keir@21265 2990 return sched;
keir@21265 2991 }
keir@21292 2992
ian@21930 2993 int libxl_sched_credit_domain_get(libxl_ctx *ctx, uint32_t domid, libxl_sched_credit *scinfo)
keir@21292 2994 {
keir@21292 2995 struct xen_domctl_sched_credit sdom;
keir@21292 2996 int rc;
keir@21292 2997
keir@21292 2998 rc = xc_sched_credit_domain_get(ctx->xch, domid, &sdom);
gianni@21892 2999 if (rc != 0) {
gianni@21892 3000 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "setting domain sched credit");
gianni@21892 3001 return ERROR_FAIL;
gianni@21892 3002 }
keir@21292 3003
keir@21292 3004 scinfo->weight = sdom.weight;
keir@21292 3005 scinfo->cap = sdom.cap;
keir@21292 3006
keir@21292 3007 return 0;
keir@21292 3008 }
keir@21292 3009
ian@21930 3010 int libxl_sched_credit_domain_set(libxl_ctx *ctx, uint32_t domid, libxl_sched_credit *scinfo)
keir@21292 3011 {
keir@21292 3012 struct xen_domctl_sched_credit sdom;
keir@21292 3013 xc_domaininfo_t domaininfo;
keir@21292 3014 int rc;
keir@21292 3015
keir@21292 3016 rc = xc_domain_getinfolist(ctx->xch, domid, 1, &domaininfo);
gianni@21892 3017 if (rc < 0) {
gianni@21892 3018 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "getting domain info list");
gianni@21892 3019 return ERROR_FAIL;
gianni@21892 3020 }
keir@21292 3021 if (rc != 1 || domaininfo.domain != domid)
gianni@21892 3022 return ERROR_INVAL;
keir@21292 3023
keir@21292 3024
keir@21292 3025 if (scinfo->weight < 1 || scinfo->weight > 65535) {
keir@21292 3026 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
keir@21292 3027 "Cpu weight out of range, valid values are within range from 1 to 65535");
gianni@21892 3028 return ERROR_INVAL;
keir@21292 3029 }
keir@21292 3030
keir@21292 3031 if (scinfo->cap < 0 || scinfo->cap > (domaininfo.max_vcpu_id + 1) * 100) {
keir@21292 3032 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
keir@21292 3033 "Cpu cap out of range, valid range is from 0 to %d for specified number of vcpus",
keir@21292 3034 ((domaininfo.max_vcpu_id + 1) * 100));
gianni@21892 3035 return ERROR_INVAL;
keir@21292 3036 }
keir@21292 3037
keir@21292 3038 sdom.weight = scinfo->weight;
keir@21292 3039 sdom.cap = scinfo->cap;
keir@21292 3040
keir@21292 3041 rc = xc_sched_credit_domain_set(ctx->xch, domid, &sdom);
gianni@21892 3042 if ( rc < 0 ) {
gianni@21892 3043 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "setting domain sched credit");
gianni@21892 3044 return ERROR_FAIL;
gianni@21892 3045 }
keir@21292 3046
keir@21292 3047 return 0;
keir@21292 3048 }
keir@21292 3049
keir@21393 3050 static int trigger_type_from_string(char *trigger_name)
keir@21393 3051 {
keir@21393 3052 if (!strcmp(trigger_name, "nmi"))
keir@21393 3053 return XEN_DOMCTL_SENDTRIGGER_NMI;
keir@21393 3054 else if (!strcmp(trigger_name, "reset"))
keir@21393 3055 return XEN_DOMCTL_SENDTRIGGER_RESET;
keir@21393 3056 else if (!strcmp(trigger_name, "init"))
keir@21393 3057 return XEN_DOMCTL_SENDTRIGGER_INIT;
keir@21393 3058 else if (!strcmp(trigger_name, "power"))
keir@21393 3059 return XEN_DOMCTL_SENDTRIGGER_POWER;
keir@21393 3060 else if (!strcmp(trigger_name, "sleep"))
keir@21393 3061 return XEN_DOMCTL_SENDTRIGGER_SLEEP;
keir@21393 3062 else
keir@21393 3063 return -1;
keir@21393 3064 }
keir@21393 3065
ian@21930 3066 int libxl_send_trigger(libxl_ctx *ctx, uint32_t domid, char *trigger_name, uint32_t vcpuid)
keir@21393 3067 {
keir@21393 3068 int rc = -1;
keir@21393 3069 int trigger_type = trigger_type_from_string(trigger_name);
keir@21393 3070
keir@21393 3071 if (trigger_type == -1) {
keir@21393 3072 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, -1,
keir@21393 3073 "Invalid trigger, valid triggers are <nmi|reset|init|power|sleep>");
gianni@21892 3074 return ERROR_INVAL;
keir@21393 3075 }
keir@21393 3076
keir@21393 3077 rc = xc_domain_send_trigger(ctx->xch, domid, trigger_type, vcpuid);
gianni@21892 3078 if (rc != 0) {
keir@21393 3079 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
keir@21393 3080 "Send trigger '%s' failed", trigger_name);
gianni@21892 3081 return ERROR_FAIL;
gianni@21892 3082 }
gianni@21892 3083
gianni@21892 3084 return 0;
keir@21393 3085 }
keir@21402 3086
ian@21930 3087 int libxl_send_sysrq(libxl_ctx *ctx, uint32_t domid, char sysrq)
keir@21402 3088 {
gianni@22023 3089 libxl_gc gc = LIBXL_INIT_GC(ctx);
gianni@22023 3090 char *dompath = libxl_xs_get_dompath(&gc, domid);
gianni@22023 3091
gianni@22023 3092 libxl_xs_write(&gc, XBT_NULL, libxl_sprintf(&gc, "%s/control/sysrq", dompath), "%c", sysrq);
gianni@22023 3093
gianni@22023 3094 libxl_free_all(&gc);
keir@21402 3095 return 0;
keir@21402 3096 }
keir@21402 3097
ian@21930 3098 int libxl_send_debug_keys(libxl_ctx *ctx, char *keys)
keir@21472 3099 {
gianni@21892 3100 int ret;
gianni@21892 3101 ret = xc_send_debug_keys(ctx->xch, keys);
gianni@21892 3102 if ( ret < 0 ) {
gianni@21892 3103 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "sending debug keys");
gianni@21892 3104 return ERROR_FAIL;
gianni@21892 3105 }
gianni@21892 3106 return 0;
keir@21472 3107 }
keir@21472 3108
ian@21930 3109 libxl_xen_console_reader *
ian@21930 3110 libxl_xen_console_read_start(libxl_ctx *ctx, int clear)
keir@21496 3111 {
ian@21930 3112 libxl_xen_console_reader *cr;
keir@21496 3113 unsigned int size = 16384;
keir@21496 3114 char *buf = malloc(size);
keir@21496 3115
keir@21496 3116 if (!buf) {
keir@21496 3117 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "cannot malloc buffer for libxl_xen_console_reader,"
keir@21496 3118 " size is %u", size);
keir@21496 3119 return NULL;
keir@21496 3120 }
keir@21496 3121
ian@21930 3122 cr = malloc(sizeof(libxl_xen_console_reader));
keir@21496 3123 if (!cr) {
keir@21496 3124 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "cannot malloc libxl_xen_console_reader");
keir@21496 3125 return NULL;
keir@21496 3126 }
keir@21496 3127
ian@21930 3128 memset(cr, 0, sizeof(libxl_xen_console_reader));
keir@21496 3129 cr->buffer = buf;
keir@21496 3130 cr->size = size;
keir@21496 3131 cr->count = size;
keir@21496 3132 cr->clear = clear;
keir@21496 3133 cr->incremental = 1;
keir@21496 3134
keir@21496 3135 return cr;
keir@21496 3136 }
keir@21496 3137
keir@21496 3138 /* return values: *line_r
keir@21496 3139 * 1 success, whole line obtained from buffer non-0
keir@21496 3140 * 0 no more lines available right now 0
keir@21496 3141 * negative error code ERROR_* 0
keir@21496 3142 * On success *line_r is updated to point to a nul-terminated
keir@21496 3143 * string which is valid until the next call on the same console
keir@21496 3144 * reader. The libxl caller may overwrite parts of the string
keir@21496 3145 * if it wishes. */
ian@21930 3146 int libxl_xen_console_read_line(libxl_ctx *ctx,
ian@21930 3147 libxl_xen_console_reader *cr,
keir@21496 3148 char **line_r)
keir@21496 3149 {
keir@21496 3150 int ret;
keir@21496 3151
keir@21496 3152 memset(cr->buffer, 0, cr->size);
keir@21496 3153 ret = xc_readconsolering(ctx->xch, &cr->buffer, &cr->count,
keir@21496 3154 cr->clear, cr->incremental, &cr->index);
gianni@21892 3155 if (ret < 0) {
gianni@21892 3156 XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "reading console ring buffer");
gianni@21892 3157 return ERROR_FAIL;
gianni@21892 3158 }
keir@21496 3159 if (!ret) {
keir@21496 3160 if (cr->count) {
keir@21496 3161 *line_r = cr->buffer;
keir@21496 3162 ret = 1;
keir@21496 3163 } else {
keir@21496 3164 *line_r = NULL;
keir@21496 3165 ret = 0;
keir@21496 3166 }
keir@21496 3167 }
keir@21496 3168
keir@21496 3169 return ret;
keir@21496 3170 }
keir@21496 3171
ian@21930 3172 void libxl_xen_console_read_finish(libxl_ctx *ctx,
ian@21930 3173 libxl_xen_console_reader *cr)
keir@21496 3174 {
keir@21496 3175 free(cr->buffer);
keir@21496 3176 free(cr);
keir@21496 3177 }
keir@21496 3178
ian@21930 3179 uint32_t libxl_vm_get_start_time(libxl_ctx *ctx, uint32_t domid)
keir@21425 3180 {
gianni@22023 3181 libxl_gc gc = LIBXL_INIT_GC(ctx);
gianni@22023 3182 char *dompath = libxl_xs_get_dompath(&gc, domid);
keir@21425 3183 char *vm_path, *start_time;
gianni@22023 3184 uint32_t ret;
keir@21425 3185
keir@21425 3186 vm_path = libxl_xs_read(
gianni@22023 3187 &gc, XBT_NULL, libxl_sprintf(&gc, "%s/vm", dompath));
keir@21425 3188 start_time = libxl_xs_read(
gianni@22023 3189 &gc, XBT_NULL, libxl_sprintf(&gc, "%s/start_time", vm_path));
keir@21425 3190 if (start_time == NULL) {
keir@21425 3191 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, -1,
keir@21425 3192 "Can't get start time of domain '%d'", domid);
gianni@22023 3193 ret = -1;
gianni@22023 3194 }else{
gianni@22023 3195 ret = strtoul(start_time, NULL, 10);
keir@21425 3196 }
gianni@22023 3197 libxl_free_all(&gc);
gianni@22023 3198 return ret;
keir@21425 3199 }
keir@21425 3200
ian@21930 3201 char *libxl_tmem_list(libxl_ctx *ctx, uint32_t domid, int use_long)
keir@21471 3202 {
keir@21471 3203 int rc;
keir@21471 3204 char _buf[32768];
keir@21471 3205
keir@21471 3206 rc = xc_tmem_control(ctx->xch, -1, TMEMC_LIST, domid, 32768, use_long,
keir@21471 3207 0, _buf);
keir@21471 3208 if (rc < 0) {
keir@21471 3209 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
keir@21471 3210 "Can not get tmem list");
keir@21471 3211 return NULL;
keir@21471 3212 }
keir@21471 3213
keir@21471 3214 return strdup(_buf);
keir@21471 3215 }
keir@21471 3216
ian@21930 3217 int libxl_tmem_freeze(libxl_ctx *ctx, uint32_t domid)
keir@21471 3218 {
keir@21471 3219 int rc;
keir@21471 3220
keir@21471 3221 rc = xc_tmem_control(ctx->xch, -1, TMEMC_FREEZE, domid, 0, 0,
keir@21471 3222 0, NULL);
keir@21471 3223 if (rc < 0) {
keir@21471 3224 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
keir@21471 3225 "Can not freeze tmem pools");
gianni@21892 3226 return ERROR_FAIL;
keir@21471 3227 }
keir@21471 3228
keir@21471 3229 return rc;
keir@21471 3230 }
keir@21471 3231
ian@21930 3232 int libxl_tmem_destroy(libxl_ctx *ctx, uint32_t domid)
keir@21471 3233 {
keir@21471 3234 int rc;
keir@21471 3235
keir@21471 3236 rc = xc_tmem_control(ctx->xch, -1, TMEMC_DESTROY, domid, 0, 0,
keir@21471 3237 0, NULL);
keir@21471 3238 if (rc < 0) {
keir@21471 3239 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
keir@21471 3240 "Can not destroy tmem pools");
gianni@21892 3241 return ERROR_FAIL;
keir@21471 3242 }
keir@21471 3243
keir@21471 3244 return rc;
keir@21471 3245 }
keir@21471 3246
ian@21930 3247 int libxl_tmem_thaw(libxl_ctx *ctx, uint32_t domid)
keir@21471 3248 {
keir@21471 3249 int rc;
keir@21471 3250
keir@21471 3251 rc = xc_tmem_control(ctx->xch, -1, TMEMC_THAW, domid, 0, 0,
keir@21471 3252 0, NULL);
keir@21471 3253 if (rc < 0) {
keir@21471 3254 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
keir@21471 3255 "Can not thaw tmem pools");
gianni@21892 3256 return ERROR_FAIL;
keir@21471 3257 }
keir@21471 3258
keir@21471 3259 return rc;
keir@21471 3260 }
keir@21471 3261
keir@21471 3262 static int32_t tmem_setop_from_string(char *set_name)
keir@21471 3263 {
keir@21471 3264 if (!strcmp(set_name, "weight"))
keir@21471 3265 return TMEMC_SET_WEIGHT;
keir@21471 3266 else if (!strcmp(set_name, "cap"))
keir@21471 3267 return TMEMC_SET_CAP;
keir@21471 3268 else if (!strcmp(set_name, "compress"))
keir@21471 3269 return TMEMC_SET_COMPRESS;
keir@21471 3270 else
keir@21471 3271 return -1;
keir@21471 3272 }
keir@21471 3273
ian@21930 3274 int libxl_tmem_set(libxl_ctx *ctx, uint32_t domid, char* name, uint32_t set)
keir@21471 3275 {
keir@21471 3276 int rc;
keir@21471 3277 int32_t subop = tmem_setop_from_string(name);
keir@21471 3278
keir@21471 3279 if (subop == -1) {
keir@21471 3280 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, -1,
keir@21471 3281 "Invalid set, valid sets are <weight|cap|compress>");
gianni@21892 3282 return ERROR_INVAL;
keir@21471 3283 }
keir@21471 3284 rc = xc_tmem_control(ctx->xch, -1, subop, domid, set, 0, 0, NULL);
keir@21471 3285 if (rc < 0) {
keir@21471 3286 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
keir@21471 3287 "Can not set tmem %s", name);
gianni@21892 3288 return ERROR_FAIL;
keir@21471 3289 }
keir@21471 3290
keir@21471 3291 return rc;
keir@21471 3292 }
keir@21471 3293
ian@21930 3294 int libxl_tmem_shared_auth(libxl_ctx *ctx, uint32_t domid,
keir@21471 3295 char* uuid, int auth)
keir@21471 3296 {
keir@21471 3297 int rc;
keir@21471 3298
keir@21471 3299 rc = xc_tmem_auth(ctx->xch, domid, uuid, auth);
keir@21471 3300 if (rc < 0) {
keir@21471 3301 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
keir@21471 3302 "Can not set tmem shared auth");
gianni@21892 3303 return ERROR_FAIL;
keir@21471 3304 }
keir@21471 3305
keir@21471 3306 return rc;
keir@21471 3307 }
keir@21471 3308
ian@21930 3309 int libxl_tmem_freeable(libxl_ctx *ctx)
sstabellini@21863 3310 {
sstabellini@21863 3311 int rc;
sstabellini@21863 3312
sstabellini@21863 3313 rc = xc_tmem_control(ctx->xch, -1, TMEMC_QUERY_FREEABLE_MB, -1, 0, 0, 0, 0);
sstabellini@21863 3314 if (rc < 0) {
sstabellini@21863 3315 XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, rc,
sstabellini@21863 3316 "Can not get tmem freeable memory");