debuggers.hg

annotate tools/libxl/libxl.c @ 22086:597da2edfe30

libxl/xl: use libxl_diskinfo_destroy and libxl_device_disk_destroy

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