debuggers.hg

annotate tools/libxl/libxl.c @ 22082:ed717f785082

libxl: implement destroy for libxl_file_reference builtin type

As well as freeing data any file mappings need to be torn down so
implement an explicit destroy function.

Also the map and unmap function are internal to libxl so make that so.

[PATCH 09 of 16 of
libxl: autogenerate type definitions and destructor functions]

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