debuggers.hg

annotate tools/libxl/libxl.c @ 22165:d6663c62524a

libxl: Ensure all _hidden functions use libxl__ prefix (manual part)

This patch covers the remaining functions identified by:
rgrep _hidden tools/libxl/*.h | grep -v libxl__

sed -i -e 's/XL_LOG/LIBXL__LOG/g' tools/libxl/*.[ch]
sed -i -e 's/xl_log/libxl__log/g' tools/libxl/*.[ch]
sed -i -e 's/\(build_\(pre\|post\|pv\|hvm\)\)/libxl__\1/g' tools/libxl/*.[ch]
sed -i -e 's/is_hvm/libxl__domain_is_hvm/g' tools/libxl/*.[ch]
sed -i -e 's/get_shutdown_reason/libxl__domain_shutdown_reason/g' tools/libxl/*.[ch]
sed -i -e 's/restore_common/libxl__domain_restore_common/g' tools/libxl/*.[ch]
sed -i -e 's/core_suspend/libxl__domain_suspend_common/g' tools/libxl/*.[ch]
sed -i -e 's/save_device_model/libxl__domain_save_device_model/g' tools/libxl/*.[ch]
sed -i -e 's/device_disk_backend_type_of_phystype/libxl__device_disk_backend_type_of_phystype/g' tools/libxl/*.[ch]
sed -i -e 's/\<libxl_blktap_enabled\>/libxl__blktap_enabled/g' tools/libxl/*.[ch]
sed -i -e 's/\<libxl_blktap_devpath\>/libxl__blktap_devpath/g' tools/libxl/*.[ch]

Add _hidden to libxl__blktap_enabled and libxl__blktap_devpath

Inline dominfo_libxl__domain_shutdown_reason(info) into
libxl__domain_shutdown_reason, its only caller.

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