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