debuggers.hg

annotate tools/libxl/libxl.c @ 20467:494ad84ad38c

libxl: Call to open() must specify mode with O_CREAT.

Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
author Keir Fraser <keir.fraser@citrix.com>
date Mon Nov 09 22:41:23 2009 +0000 (2009-11-09)
parents 8a91056bea81
children 50d33023051d
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@20462 17 #include <stdio.h>
keir@20462 18 #include <string.h>
keir@20462 19 #include <stdlib.h>
keir@20462 20 #include <sys/stat.h>
keir@20462 21 #include <sys/types.h>
keir@20462 22 #include <fcntl.h>
keir@20462 23 #include <sys/select.h>
keir@20462 24 #include <signal.h>
keir@20462 25 #include "libxl.h"
keir@20462 26 #include "libxl_utils.h"
keir@20462 27 #include "libxl_internal.h"
keir@20462 28 #include "flexarray.h"
keir@20462 29
keir@20462 30 int libxl_ctx_init(struct libxl_ctx *ctx)
keir@20462 31 {
keir@20462 32 memset(ctx, 0, sizeof(struct libxl_ctx));
keir@20462 33 ctx->alloc_maxsize = 256;
keir@20462 34 ctx->alloc_ptrs = calloc(ctx->alloc_maxsize, sizeof(void *));
keir@20462 35 if (!ctx->alloc_ptrs)
keir@20462 36 return ERROR_NOMEM;
keir@20462 37
keir@20462 38 ctx->xch = xc_interface_open();
keir@20462 39 ctx->xsh = xs_daemon_open();
keir@20462 40 return 0;
keir@20462 41 }
keir@20462 42
keir@20462 43 int libxl_ctx_free(struct libxl_ctx *ctx)
keir@20462 44 {
keir@20462 45 libxl_free_all(ctx);
keir@20462 46 free(ctx->alloc_ptrs);
keir@20462 47 ctx->alloc_ptrs = NULL;
keir@20462 48 xc_interface_close(ctx->xch);
keir@20462 49 xs_daemon_close(ctx->xsh);
keir@20462 50 return 0;
keir@20462 51 }
keir@20462 52
keir@20462 53 int libxl_ctx_set_log(struct libxl_ctx *ctx, libxl_log_callback log_callback, void *log_data)
keir@20462 54 {
keir@20462 55 ctx->log_callback = log_callback;
keir@20462 56 ctx->log_userdata = log_data;
keir@20462 57 return 0;
keir@20462 58 }
keir@20462 59
keir@20462 60 /******************************************************************************/
keir@20462 61
keir@20462 62 int libxl_domain_make(struct libxl_ctx *ctx, libxl_domain_create_info *info,
keir@20462 63 uint32_t *domid)
keir@20462 64 {
keir@20462 65 int flags, ret, i;
keir@20462 66 char *uuid_string;
keir@20462 67 char *rw_paths[] = { "device" };
keir@20462 68 char *ro_paths[] = { "cpu", "memory", "device", "error", "drivers",
keir@20462 69 "control", "attr", "data", "messages" };
keir@20462 70 char *dom_path, *vm_path, *vss_path;
keir@20462 71 struct xs_permissions roperm[2];
keir@20462 72 struct xs_permissions rwperm[1];
keir@20462 73 xs_transaction_t t;
keir@20462 74
keir@20462 75 uuid_string = uuid_to_string(ctx, info->uuid);
keir@20462 76 if (!uuid_string) {
keir@20462 77 XL_LOG(ctx, XL_LOG_ERROR, "missing uuid");
keir@20462 78 return ERROR_FAIL;
keir@20462 79 }
keir@20462 80
keir@20462 81 flags = info->hvm ? XEN_DOMCTL_CDF_hvm_guest : 0;
keir@20462 82 flags |= info->hap ? XEN_DOMCTL_CDF_hap : 0;
keir@20462 83 *domid = 0;
keir@20462 84
keir@20462 85 ret = xc_domain_create(ctx->xch, info->ssidref, info->uuid, flags, domid);
keir@20462 86 if (ret < 0) {
keir@20462 87 XL_LOG(ctx, XL_LOG_ERROR, "domain creation fail: %d", ret);
keir@20462 88 return ERROR_FAIL;
keir@20462 89 }
keir@20462 90
keir@20462 91 dom_path = libxl_xs_get_dompath(ctx, *domid);
keir@20462 92 vm_path = libxl_sprintf(ctx, "/vm/%s", uuid_string);
keir@20462 93 vss_path = libxl_sprintf(ctx, "/vss/%s", uuid_string);
keir@20462 94 if (!dom_path || !vm_path || !vss_path) {
keir@20462 95 XL_LOG(ctx, XL_LOG_ERROR, "cannot allocate create paths");
keir@20462 96 return ERROR_FAIL;
keir@20462 97 }
keir@20462 98
keir@20462 99 roperm[0].id = 0;
keir@20462 100 roperm[0].perms = XS_PERM_NONE;
keir@20462 101 roperm[1].id = *domid;
keir@20462 102 roperm[1].perms = XS_PERM_READ;
keir@20462 103 rwperm[0].id = *domid;
keir@20462 104 rwperm[0].perms = XS_PERM_NONE;
keir@20462 105
keir@20462 106 retry_transaction:
keir@20462 107 t = xs_transaction_start(ctx->xsh);
keir@20462 108 xs_rm(ctx->xsh, t, dom_path);
keir@20462 109 xs_mkdir(ctx->xsh, t, dom_path);
keir@20462 110 xs_set_permissions(ctx->xsh, t, dom_path, roperm, ARRAY_SIZE(roperm));
keir@20462 111
keir@20462 112 xs_rm(ctx->xsh, t, vm_path);
keir@20462 113 xs_mkdir(ctx->xsh, t, vm_path);
keir@20462 114 xs_set_permissions(ctx->xsh, t, vm_path, roperm, ARRAY_SIZE(roperm));
keir@20462 115
keir@20462 116 xs_rm(ctx->xsh, t, vss_path);
keir@20462 117 xs_mkdir(ctx->xsh, t, vss_path);
keir@20462 118 xs_set_permissions(ctx->xsh, t, vss_path, rwperm, ARRAY_SIZE(rwperm));
keir@20462 119
keir@20462 120 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/vm", dom_path), vm_path, strlen(vm_path));
keir@20462 121 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/vss", dom_path), vss_path, strlen(vss_path));
keir@20462 122 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/name", dom_path), info->name, strlen(info->name));
keir@20462 123
keir@20462 124 for (i = 0; i < ARRAY_SIZE(rw_paths); i++) {
keir@20462 125 char *path = libxl_sprintf(ctx, "%s/%s", dom_path, rw_paths[i]);
keir@20462 126 xs_mkdir(ctx->xsh, t, path);
keir@20462 127 xs_set_permissions(ctx->xsh, t, path, rwperm, ARRAY_SIZE(rwperm));
keir@20462 128 libxl_free(ctx, path);
keir@20462 129 }
keir@20462 130 for (i = 0; i < ARRAY_SIZE(ro_paths); i++) {
keir@20462 131 char *path = libxl_sprintf(ctx, "%s/%s", dom_path, ro_paths[i]);
keir@20462 132 xs_mkdir(ctx->xsh, t, path);
keir@20462 133 xs_set_permissions(ctx->xsh, t, path, roperm, ARRAY_SIZE(roperm));
keir@20462 134 libxl_free(ctx, path);
keir@20462 135 }
keir@20462 136
keir@20462 137 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/uuid", vm_path), uuid_string, strlen(uuid_string));
keir@20462 138 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/name", vm_path), info->name, strlen(info->name));
keir@20462 139
keir@20462 140 libxl_xs_writev(ctx, t, dom_path, info->xsdata);
keir@20462 141 libxl_xs_writev(ctx, t, libxl_sprintf(ctx, "%s/platform", dom_path), info->platformdata);
keir@20462 142
keir@20462 143 xs_write(ctx->xsh, t, libxl_sprintf(ctx, "%s/control/platform-feature-multiprocessor-suspend", dom_path), "1", 1);
keir@20462 144
keir@20462 145 if (!xs_transaction_end(ctx->xsh, t, 0))
keir@20462 146 if (errno == EAGAIN)
keir@20462 147 goto retry_transaction;
keir@20462 148 return 0;
keir@20462 149 }
keir@20462 150
keir@20462 151 int libxl_domain_build(struct libxl_ctx *ctx, libxl_domain_build_info *info, uint32_t domid)
keir@20462 152 {
keir@20462 153 libxl_domain_build_state state;
keir@20462 154 char **vments = NULL, **localents = NULL;
keir@20462 155
keir@20462 156 memset(&state, '\0', sizeof(state));
keir@20462 157
keir@20462 158 build_pre(ctx, domid, info, &state);
keir@20462 159 if (info->hvm) {
keir@20462 160 build_hvm(ctx, domid, info, &state);
keir@20462 161 vments = libxl_calloc(ctx, 4, sizeof(char *));
keir@20462 162 vments[0] = libxl_sprintf(ctx, "rtc/timeoffset");
keir@20462 163 vments[1] = libxl_sprintf(ctx, "%s", (info->u.hvm.timeoffset) ? info->u.hvm.timeoffset : "");
keir@20462 164 } else {
keir@20462 165 build_pv(ctx, domid, info, &state);
keir@20462 166 }
keir@20462 167 build_post(ctx, domid, info, &state, vments, localents);
keir@20462 168 return 0;
keir@20462 169 }
keir@20462 170
keir@20462 171 int libxl_domain_restore(struct libxl_ctx *ctx, libxl_domain_build_info *info,
keir@20462 172 uint32_t domid, int fd)
keir@20462 173 {
keir@20462 174 libxl_domain_build_state state;
keir@20462 175 char **vments = NULL, **localents = NULL;
keir@20462 176
keir@20462 177 memset(&state, '\0', sizeof(state));
keir@20462 178
keir@20462 179 build_pre(ctx, domid, info, &state);
keir@20462 180 restore_common(ctx, domid, info, &state, fd);
keir@20462 181 if (info->hvm) {
keir@20462 182 vments = libxl_calloc(ctx, 4, sizeof(char *));
keir@20462 183 vments[0] = libxl_sprintf(ctx, "rtc/timeoffset");
keir@20462 184 vments[1] = libxl_sprintf(ctx, "%s", (info->u.hvm.timeoffset) ? info->u.hvm.timeoffset : "");
keir@20462 185 } else {
keir@20462 186 localents = libxl_calloc(ctx, 4 * 2, sizeof(char *));
keir@20462 187 localents[0] = libxl_sprintf(ctx, "serial/0/limit");
keir@20462 188 localents[1] = libxl_sprintf(ctx, "%d", 65536);
keir@20462 189 localents[2] = libxl_sprintf(ctx, "console/port");
keir@20462 190 localents[3] = libxl_sprintf(ctx, "%d", state.console_port);
keir@20462 191 localents[4] = libxl_sprintf(ctx, "console/ring-ref");
keir@20462 192 localents[5] = libxl_sprintf(ctx, "%ld", state.console_mfn);
keir@20462 193 }
keir@20462 194 build_post(ctx, domid, info, &state, vments, localents);
keir@20462 195 return 0;
keir@20462 196 }
keir@20462 197
keir@20462 198 struct libxl_dominfo * libxl_domain_list(struct libxl_ctx *ctx, int *nb_domain)
keir@20462 199 {
keir@20462 200 struct libxl_dominfo *ptr;
keir@20462 201 int index, i, ret, first_domain;
keir@20462 202 xc_domaininfo_t info[16];
keir@20462 203 int size = 16;
keir@20462 204
keir@20462 205 first_domain = 1;
keir@20462 206 index = 0;
keir@20462 207 ptr = libxl_calloc(ctx, size, sizeof(struct libxl_dominfo));
keir@20462 208 if (!ptr)
keir@20462 209 return NULL;
keir@20462 210 redo:
keir@20462 211 ret = xc_domain_getinfolist(ctx->xch, first_domain, 16, info);
keir@20462 212 for (i = 0; i < ret; i++) {
keir@20462 213 if (index == size) {
keir@20462 214 struct libxl_dominfo *ptr2;
keir@20462 215
keir@20462 216 ptr2 = libxl_calloc(ctx, size * 2, sizeof(struct libxl_dominfo));
keir@20462 217 if (!ptr2) {
keir@20462 218 libxl_free(ctx, ptr);
keir@20462 219 return NULL;
keir@20462 220 }
keir@20462 221 memcpy(ptr2, ptr, sizeof(struct libxl_dominfo) * size);
keir@20462 222 libxl_free(ctx, ptr);
keir@20462 223 ptr = ptr2;
keir@20462 224 size *= 2;
keir@20462 225 }
keir@20462 226 memcpy(ptr[index].uuid, info[i].handle, 16 * sizeof(uint8_t));
keir@20462 227 ptr[index].domid = info[i].domain;
keir@20462 228 first_domain = info[i].domain + 1;
keir@20462 229 index++;
keir@20462 230 }
keir@20462 231 if (ret == 16)
keir@20462 232 goto redo;
keir@20462 233 *nb_domain = index;
keir@20462 234 return ptr;
keir@20462 235 }
keir@20462 236
keir@20462 237 xc_dominfo_t * libxl_domain_infolist(struct libxl_ctx *ctx, int *nb_domain)
keir@20462 238 {
keir@20462 239 int index, first_domain;
keir@20462 240 xc_dominfo_t *info;
keir@20462 241 int size = 1024;
keir@20462 242
keir@20462 243 first_domain = 0;
keir@20462 244 index = 0;
keir@20462 245 info = (xc_dominfo_t *) libxl_calloc(ctx, size, sizeof(xc_dominfo_t));
keir@20462 246 if (!info) {
keir@20462 247 *nb_domain = 0;
keir@20462 248 return NULL;
keir@20462 249 }
keir@20462 250 *nb_domain = xc_domain_getinfo(ctx->xch, first_domain, 1024, info);
keir@20462 251 return info;
keir@20462 252 }
keir@20462 253
keir@20462 254 int libxl_domain_suspend(struct libxl_ctx *ctx, libxl_domain_suspend_info *info,
keir@20462 255 uint32_t domid, int fd)
keir@20462 256 {
keir@20462 257 int hvm = 1;
keir@20462 258 int live = 0;
keir@20462 259 int debug = 0;
keir@20462 260 char savesig[] = "XenSavedDomain\n";
keir@20462 261
keir@20462 262 write(fd, savesig, strlen(savesig));
keir@20462 263
keir@20462 264 core_suspend(ctx, domid, fd, hvm, live, debug);
keir@20462 265
keir@20462 266 return 0;
keir@20462 267 }
keir@20462 268
keir@20462 269 int libxl_domain_pause(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 270 {
keir@20462 271 xc_domain_pause(ctx->xch, domid);
keir@20462 272 return 0;
keir@20462 273 }
keir@20462 274
keir@20462 275 int libxl_domain_unpause(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 276 {
keir@20462 277 xc_domain_unpause(ctx->xch, domid);
keir@20462 278 return 0;
keir@20462 279 }
keir@20462 280
keir@20462 281 static char *req_table[] = {
keir@20462 282 [0] = "poweroff",
keir@20462 283 [1] = "reboot",
keir@20462 284 [2] = "suspend",
keir@20462 285 [3] = "crash",
keir@20462 286 [4] = "halt",
keir@20462 287 };
keir@20462 288
keir@20462 289 int libxl_domain_shutdown(struct libxl_ctx *ctx, uint32_t domid, int req)
keir@20462 290 {
keir@20462 291 char *shutdown_path;
keir@20462 292 char *dom_path;
keir@20462 293
keir@20462 294 if (req > ARRAY_SIZE(req_table))
keir@20462 295 return ERROR_INVAL;
keir@20462 296
keir@20462 297 dom_path = libxl_xs_get_dompath(ctx, domid);
keir@20462 298 shutdown_path = libxl_sprintf(ctx, "%s/control/shutdown", dom_path);
keir@20462 299
keir@20462 300 xs_write(ctx->xsh, XBT_NULL, shutdown_path, req_table[req], strlen(req_table[req]));
keir@20462 301 if (/* hvm */ 0) {
keir@20462 302 unsigned long acpi_s_state = 0;
keir@20462 303 unsigned long pvdriver = 0;
keir@20462 304 xc_get_hvm_param(ctx->xch, domid, HVM_PARAM_ACPI_S_STATE, &acpi_s_state);
keir@20462 305 xc_get_hvm_param(ctx->xch, domid, HVM_PARAM_CALLBACK_IRQ, &pvdriver);
keir@20462 306 if (!pvdriver && acpi_s_state != 0)
keir@20462 307 xc_domain_shutdown(ctx->xch, domid, req);
keir@20462 308 }
keir@20462 309 return 0;
keir@20462 310 }
keir@20462 311
keir@20462 312 static int libxl_destroy_device_model(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 313 {
keir@20462 314 char *pid;
keir@20462 315 int ret;
keir@20462 316
keir@20462 317 pid = libxl_xs_read(ctx, XBT_NULL, libxl_sprintf(ctx, "/local/domain/%d/image/device-model-pid", domid));
keir@20462 318 if (!pid) {
keir@20462 319 XL_LOG(ctx, XL_LOG_ERROR, "Couldn't find device model's pid\n");
keir@20462 320 return -1;
keir@20462 321 }
keir@20462 322 xs_rm(ctx->xsh, XBT_NULL, libxl_sprintf(ctx, "/local/domain/0/device-model/%d", domid));
keir@20462 323
keir@20462 324 ret = kill(atoi(pid), SIGHUP);
keir@20462 325 if (ret < 0 && errno == ESRCH) {
keir@20462 326 XL_LOG(ctx, XL_LOG_DEBUG, "Device Model already exited\n");
keir@20462 327 ret = 0;
keir@20462 328 } else if (ret == 0) {
keir@20462 329 XL_LOG(ctx, XL_LOG_DEBUG, "Device Model signaled\n");
keir@20462 330 ret = 0;
keir@20462 331 } else {
keir@20462 332 XL_LOG(ctx, XL_LOG_ERROR, "kill %d returned %d errno=%d\n", atoi(pid), ret, errno);
keir@20462 333 }
keir@20462 334 return ret;
keir@20462 335 }
keir@20462 336
keir@20462 337 int libxl_domain_destroy(struct libxl_ctx *ctx, uint32_t domid, int force)
keir@20462 338 {
keir@20462 339 char *dom_path, vm_path[41];
keir@20462 340 uint8_t *uuid;
keir@20462 341
keir@20462 342 dom_path = libxl_xs_get_dompath(ctx, domid);
keir@20462 343 if (!dom_path) {
keir@20462 344 XL_LOG(ctx, XL_LOG_ERROR, "dompath doesn't exist for %d\n", domid);
keir@20462 345 return -1;
keir@20462 346 }
keir@20462 347 if (libxl_domid_to_uuid(ctx, &uuid, domid) < 0) {
keir@20462 348 XL_LOG(ctx, XL_LOG_ERROR, "failed ot get uuid for %d\n", domid);
keir@20462 349 return -1;
keir@20462 350 }
keir@20462 351 xs_write(ctx->xsh, XBT_NULL,
keir@20462 352 libxl_sprintf(ctx, "/local/domain/0/device-model/%d/command", domid),
keir@20462 353 "shutdown", strlen("shutdown"));
keir@20462 354 if (xc_domain_pause(ctx->xch, domid) < 0) {
keir@20462 355 XL_LOG(ctx, XL_LOG_ERROR, "xc_domain_pause failed for %d\n", domid);
keir@20462 356 return -1;
keir@20462 357 }
keir@20462 358 /* do_FLR */
keir@20462 359 if (xc_domain_destroy(ctx->xch, domid) < 0) {
keir@20462 360 XL_LOG(ctx, XL_LOG_ERROR, "xc_domain_destroy failed for %d\n", domid);
keir@20462 361 return -1;
keir@20462 362 }
keir@20462 363 if (libxl_devices_destroy(ctx, domid, force) < 0)
keir@20462 364 XL_LOG(ctx, XL_LOG_ERROR, "libxl_destroy_devices failed for %d\n", domid);
keir@20462 365 if (libxl_destroy_device_model(ctx, domid) < 0)
keir@20462 366 XL_LOG(ctx, XL_LOG_ERROR, "libxl_destroy_device_model failed for %d\n", domid);
keir@20462 367 if (!xs_rm(ctx->xsh, XBT_NULL, dom_path))
keir@20462 368 XL_LOG(ctx, XL_LOG_ERROR, "xs_rm failed for %s\n", dom_path);
keir@20462 369 snprintf(vm_path, sizeof(vm_path), "/vm/%s", uuid_to_string(ctx, uuid));
keir@20462 370 if (!xs_rm(ctx->xsh, XBT_NULL, vm_path))
keir@20462 371 XL_LOG(ctx, XL_LOG_ERROR, "xs_rm failed for %s\n", vm_path);
keir@20462 372 return 0;
keir@20462 373 }
keir@20462 374
keir@20462 375 static char ** libxl_build_device_model_args(struct libxl_ctx *ctx,
keir@20462 376 libxl_device_model_info *info,
keir@20462 377 libxl_device_nic *vifs,
keir@20462 378 int num_vifs)
keir@20462 379 {
keir@20462 380 int num = 0, i;
keir@20462 381 flexarray_t *dm_args;
keir@20462 382 dm_args = flexarray_make(16, 1);
keir@20462 383 if (!dm_args)
keir@20462 384 return NULL;
keir@20462 385
keir@20462 386 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "qemu-dm"));
keir@20462 387 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-d"));
keir@20462 388
keir@20462 389 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%d", info->domid));
keir@20462 390
keir@20462 391 if (info->dom_name) {
keir@20462 392 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-domain-name"));
keir@20462 393 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%s", info->dom_name));
keir@20462 394 }
keir@20462 395 if (info->videoram) {
keir@20462 396 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-videoram"));
keir@20462 397 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%d", info->videoram));
keir@20462 398 }
keir@20462 399 if (info->stdvga) {
keir@20462 400 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-std-vga"));
keir@20462 401 }
keir@20462 402 if (info->vnc || info->vncdisplay || info->vnclisten || info->vncunused) {
keir@20462 403 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-vnc"));
keir@20462 404 if (info->vncdisplay) {
keir@20462 405 if (info->vnclisten && strchr(info->vnclisten, ':') == NULL) {
keir@20462 406 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%s:%d", info->vnclisten, info->vncdisplay));
keir@20462 407 } else {
keir@20462 408 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "127.0.0.1:%d", info->vncdisplay));
keir@20462 409 }
keir@20462 410 } else if (info->vnclisten) {
keir@20462 411 if (strchr(info->vnclisten, ':') != NULL) {
keir@20462 412 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%s", info->vnclisten));
keir@20462 413 } else {
keir@20462 414 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%s:0", info->vnclisten));
keir@20462 415 }
keir@20462 416 } else {
keir@20462 417 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "127.0.0.1:0"));
keir@20462 418 }
keir@20462 419 if (info->vncunused) {
keir@20462 420 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-vncunused"));
keir@20462 421 }
keir@20462 422 }
keir@20462 423 if (info->sdl || info->opengl) {
keir@20462 424 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-sdl"));
keir@20462 425 if (info->opengl) {
keir@20462 426 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-disable-opengl"));
keir@20462 427 }
keir@20462 428 }
keir@20462 429 if (info->keymap) {
keir@20462 430 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-k"));
keir@20462 431 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%s", info->keymap));
keir@20462 432 }
keir@20462 433 if (info->nographic && (!info->sdl && !info->vnc)) {
keir@20462 434 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-nographic"));
keir@20462 435 }
keir@20462 436 if (info->serial) {
keir@20462 437 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-serial"));
keir@20462 438 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%s", info->serial));
keir@20462 439 }
keir@20462 440 if (info->boot) {
keir@20462 441 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-boot"));
keir@20462 442 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%s", info->boot));
keir@20462 443 }
keir@20462 444 if (info->usb) {
keir@20462 445 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-usb"));
keir@20462 446 if (info->usbdevice) {
keir@20462 447 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-usbdevice"));
keir@20462 448 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%s", info->usbdevice));
keir@20462 449 }
keir@20462 450 }
keir@20462 451 if (info->apic) {
keir@20462 452 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-acpi"));
keir@20462 453 }
keir@20462 454 if (info->extra) {
keir@20462 455 int i = 0;
keir@20462 456 while (info->extra[i] != NULL) {
keir@20462 457 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "%s", info->extra[i]));
keir@20462 458 }
keir@20462 459 }
keir@20462 460 for (i = 0; i < num_vifs; i++) {
keir@20462 461 if (vifs[i].nictype == NICTYPE_IOEMU) {
keir@20462 462 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-net"));
keir@20462 463 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "nic,vlan=%d,macaddr=%s,model=%s",
keir@20462 464 vifs[i].devid, vifs[i].smac, vifs[i].model));
keir@20462 465 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-net"));
keir@20462 466 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "tap,vlan=%d,ifname=%s,bridge=%s",
keir@20462 467 vifs[i].devid, vifs[i].ifname, vifs[i].bridge));
keir@20462 468 }
keir@20462 469 }
keir@20462 470 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "-M"));
keir@20462 471 flexarray_set(dm_args, num++, libxl_sprintf(ctx, "xenfv"));
keir@20462 472 flexarray_set(dm_args, num++, NULL);
keir@20462 473
keir@20462 474 return (char **) flexarray_contents(dm_args);
keir@20462 475 }
keir@20462 476
keir@20462 477 int libxl_create_device_model(struct libxl_ctx *ctx,
keir@20462 478 libxl_device_model_info *info,
keir@20462 479 libxl_device_nic *vifs, int num_vifs)
keir@20462 480 {
keir@20462 481 char *dom_path, *path, *logfile, *logfile_new;
keir@20462 482 char *kvs[3];
keir@20462 483 struct stat stat_buf;
keir@20462 484 int logfile_w, null, pid;
keir@20462 485 int i;
keir@20462 486 char **args;
keir@20462 487
keir@20462 488 args = libxl_build_device_model_args(ctx, info, vifs, num_vifs);
keir@20462 489 if (!args)
keir@20462 490 return ERROR_FAIL;
keir@20462 491
keir@20462 492 dom_path = libxl_xs_get_dompath(ctx, info->domid);
keir@20462 493
keir@20462 494 path = libxl_sprintf(ctx, "/local/domain/0/device-model/%d", info->domid);
keir@20462 495 xs_mkdir(ctx->xsh, XBT_NULL, path);
keir@20462 496
keir@20462 497 logfile = libxl_sprintf(ctx, "/var/log/xen/qemu-dm-%s.log", info->dom_name);
keir@20462 498 if (stat(logfile, &stat_buf) == 0) {
keir@20462 499 /* file exists, rotate */
keir@20462 500 logfile = libxl_sprintf(ctx, "/var/log/xen/qemu-dm-%s.log.10", info->dom_name);
keir@20462 501 unlink(logfile);
keir@20462 502 for (i = 9; i > 0; i--) {
keir@20462 503 logfile = libxl_sprintf(ctx, "/var/log/xen/qemu-dm-%s.log.%d", info->dom_name, i);
keir@20462 504 logfile_new = libxl_sprintf(ctx, "/var/log/xen/qemu-dm-%s.log.%d", info->dom_name, i + 1);
keir@20462 505 rename(logfile, logfile_new);
keir@20462 506 }
keir@20462 507 logfile = libxl_sprintf(ctx, "/var/log/xen/qemu-dm-%s.log", info->dom_name);
keir@20462 508 logfile_new = libxl_sprintf(ctx, "/var/log/xen/qemu-dm-%s.log.1", info->dom_name);
keir@20462 509 rename(logfile, logfile_new);
keir@20462 510 }
keir@20462 511 logfile = libxl_sprintf(ctx, "/var/log/xen/qemu-dm-%s.log", info->dom_name);
keir@20467 512 logfile_w = open(logfile, O_WRONLY|O_CREAT, 0644);
keir@20462 513 null = open("/dev/null", O_RDONLY);
keir@20462 514 pid = libxl_exec(ctx, null, logfile_w, logfile_w, info->device_model, args);
keir@20462 515 close(null);
keir@20462 516 close(logfile_w);
keir@20462 517
keir@20462 518 kvs[0] = libxl_sprintf(ctx, "image/device-model-pid");
keir@20462 519 kvs[1] = libxl_sprintf(ctx, "%d", pid);
keir@20462 520 kvs[2] = NULL;
keir@20462 521 libxl_xs_writev(ctx, XBT_NULL, dom_path, kvs);
keir@20462 522
keir@20462 523 return 0;
keir@20462 524 }
keir@20462 525
keir@20462 526 /******************************************************************************/
keir@20462 527 int libxl_device_disk_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk)
keir@20462 528 {
keir@20462 529 flexarray_t *front;
keir@20462 530 flexarray_t *back;
keir@20462 531 char *backend_type;
keir@20462 532 unsigned int boffset = 0;
keir@20462 533 unsigned int foffset = 0;
keir@20462 534 int devid;
keir@20462 535 libxl_device device;
keir@20462 536
keir@20462 537 front = flexarray_make(16, 1);
keir@20462 538 if (!front)
keir@20462 539 return ERROR_NOMEM;
keir@20462 540 back = flexarray_make(16, 1);
keir@20462 541 if (!back) /* leaks front if error */
keir@20462 542 return ERROR_NOMEM;
keir@20462 543
keir@20462 544 backend_type = device_disk_backend_type_of_phystype(disk->phystype);
keir@20462 545 devid = device_disk_dev_number(disk->virtpath);
keir@20462 546
keir@20462 547 device.backend_devid = devid;
keir@20462 548 device.backend_domid = disk->backend_domid;
keir@20462 549 device.devid = devid;
keir@20462 550 device.domid = disk->domid;
keir@20462 551 device.kind = DEVICE_VBD;
keir@20462 552
keir@20462 553 switch (disk->phystype) {
keir@20462 554 case PHYSTYPE_FILE:
keir@20462 555 return ERROR_NI; /* FIXME */
keir@20462 556 break;
keir@20462 557 case PHYSTYPE_PHY: {
keir@20462 558 int major, minor;
keir@20462 559
keir@20462 560 device_disk_major_minor(disk->virtpath, &major, &minor);
keir@20462 561 flexarray_set(back, boffset++, libxl_sprintf(ctx, "physical-device"));
keir@20462 562 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%x:%x", major, minor));
keir@20462 563
keir@20462 564 flexarray_set(back, boffset++, libxl_sprintf(ctx, "params"));
keir@20462 565 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s", disk->physpath));
keir@20462 566
keir@20462 567 device.backend_kind = DEVICE_VBD;
keir@20462 568 break;
keir@20462 569 }
keir@20462 570 case PHYSTYPE_AIO: case PHYSTYPE_QCOW: case PHYSTYPE_QCOW2: case PHYSTYPE_VHD:
keir@20462 571 flexarray_set(back, boffset++, libxl_sprintf(ctx, "params"));
keir@20462 572 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s:%s",
keir@20462 573 device_disk_string_of_phystype(disk->phystype), disk->physpath));
keir@20462 574
keir@20462 575 device.backend_kind = DEVICE_TAP;
keir@20462 576 break;
keir@20462 577 }
keir@20462 578
keir@20462 579 flexarray_set(back, boffset++, libxl_sprintf(ctx, "frontend-id"));
keir@20462 580 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", disk->domid));
keir@20462 581 flexarray_set(back, boffset++, libxl_sprintf(ctx, "online"));
keir@20462 582 flexarray_set(back, boffset++, libxl_sprintf(ctx, "1"));
keir@20462 583 flexarray_set(back, boffset++, libxl_sprintf(ctx, "removable"));
keir@20462 584 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", (disk->unpluggable) ? 1 : 0));
keir@20462 585 flexarray_set(back, boffset++, libxl_sprintf(ctx, "state"));
keir@20462 586 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
keir@20462 587 flexarray_set(back, boffset++, libxl_sprintf(ctx, "dev"));
keir@20462 588 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s", disk->virtpath));
keir@20462 589 flexarray_set(back, boffset++, libxl_sprintf(ctx, "type"));
keir@20462 590 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s", backend_type));
keir@20462 591 flexarray_set(back, boffset++, libxl_sprintf(ctx, "mode"));
keir@20462 592 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s", (disk->readwrite) ? "w" : "r"));
keir@20462 593
keir@20462 594 flexarray_set(front, foffset++, libxl_sprintf(ctx, "backend-id"));
keir@20462 595 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", disk->backend_domid));
keir@20462 596 flexarray_set(front, foffset++, libxl_sprintf(ctx, "state"));
keir@20462 597 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1));
keir@20462 598 flexarray_set(front, foffset++, libxl_sprintf(ctx, "virtual-device"));
keir@20462 599 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", devid));
keir@20462 600 flexarray_set(front, foffset++, libxl_sprintf(ctx, "device-type"));
keir@20462 601 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%s", (disk->is_cdrom) ? "cdrom" : "disk"));
keir@20462 602
keir@20462 603 if (0 /* protocol != native*/) {
keir@20462 604 flexarray_set(front, foffset++, libxl_sprintf(ctx, "protocol"));
keir@20462 605 flexarray_set(front, foffset++, libxl_sprintf(ctx, "x86_32-abi")); /* hardcoded ! */
keir@20462 606 }
keir@20462 607
keir@20462 608 libxl_device_generic_add(ctx, &device,
keir@20462 609 libxl_xs_kvs_of_flexarray(ctx, back, boffset),
keir@20462 610 libxl_xs_kvs_of_flexarray(ctx, front, foffset));
keir@20462 611 /* leaks both flexarray here */
keir@20462 612 return 0;
keir@20462 613 }
keir@20462 614
keir@20462 615 int libxl_device_disk_clean_shutdown(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 616 {
keir@20462 617 return ERROR_NI;
keir@20462 618 }
keir@20462 619
keir@20462 620 int libxl_device_disk_hard_shutdown(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 621 {
keir@20462 622 return ERROR_NI;
keir@20462 623 }
keir@20462 624
keir@20462 625 /******************************************************************************/
keir@20462 626 int libxl_device_nic_add(struct libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic)
keir@20462 627 {
keir@20462 628 flexarray_t *front;
keir@20462 629 flexarray_t *back;
keir@20462 630 unsigned int boffset = 0;
keir@20462 631 unsigned int foffset = 0;
keir@20462 632 libxl_device device;
keir@20462 633
keir@20462 634 front = flexarray_make(16, 1);
keir@20462 635 if (!front)
keir@20462 636 return ERROR_NOMEM;
keir@20462 637 back = flexarray_make(16, 1);
keir@20462 638 if (!back)
keir@20462 639 return ERROR_NOMEM;
keir@20462 640
keir@20462 641 device.backend_devid = nic->devid;
keir@20462 642 device.backend_domid = nic->backend_domid;
keir@20462 643 device.backend_kind = DEVICE_VIF;
keir@20462 644 device.devid = nic->devid;
keir@20462 645 device.domid = nic->domid;
keir@20462 646 device.kind = DEVICE_VIF;
keir@20462 647
keir@20462 648 flexarray_set(back, boffset++, libxl_sprintf(ctx, "frontend-id"));
keir@20462 649 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", nic->domid));
keir@20462 650 flexarray_set(back, boffset++, libxl_sprintf(ctx, "online"));
keir@20462 651 flexarray_set(back, boffset++, libxl_sprintf(ctx, "1"));
keir@20462 652 flexarray_set(back, boffset++, libxl_sprintf(ctx, "state"));
keir@20462 653 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", 1));
keir@20462 654 flexarray_set(back, boffset++, libxl_sprintf(ctx, "script"));
keir@20462 655 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%s", nic->script));
keir@20462 656 flexarray_set(back, boffset++, libxl_sprintf(ctx, "mac"));
keir@20462 657 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%02x:%02x:%02x:%02x:%02x:%02x",
keir@20462 658 nic->mac[0], nic->mac[1], nic->mac[2],
keir@20462 659 nic->mac[3], nic->mac[4], nic->mac[5]));
keir@20462 660 flexarray_set(back, boffset++, libxl_sprintf(ctx, "handle"));
keir@20462 661 flexarray_set(back, boffset++, libxl_sprintf(ctx, "%d", nic->devid));
keir@20462 662
keir@20462 663 flexarray_set(front, foffset++, libxl_sprintf(ctx, "backend-id"));
keir@20462 664 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", nic->backend_domid));
keir@20462 665 flexarray_set(front, foffset++, libxl_sprintf(ctx, "state"));
keir@20462 666 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", 1));
keir@20462 667 flexarray_set(front, foffset++, libxl_sprintf(ctx, "handle"));
keir@20462 668 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%d", nic->devid));
keir@20462 669 flexarray_set(front, foffset++, libxl_sprintf(ctx, "mac"));
keir@20462 670 flexarray_set(front, foffset++, libxl_sprintf(ctx, "%02x:%02x:%02x:%02x:%02x:%02x",
keir@20462 671 nic->mac[0], nic->mac[1], nic->mac[2],
keir@20462 672 nic->mac[3], nic->mac[4], nic->mac[5]));
keir@20462 673 if (0 /* protocol != native*/) {
keir@20462 674 flexarray_set(front, foffset++, libxl_sprintf(ctx, "protocol"));
keir@20462 675 flexarray_set(front, foffset++, libxl_sprintf(ctx, "x86_32-abi")); /* hardcoded ! */
keir@20462 676 }
keir@20462 677
keir@20462 678 libxl_device_generic_add(ctx, &device,
keir@20462 679 libxl_xs_kvs_of_flexarray(ctx, back, boffset),
keir@20462 680 libxl_xs_kvs_of_flexarray(ctx, front, foffset));
keir@20462 681
keir@20462 682 /* FIXME: wait for plug */
keir@20462 683 return 0;
keir@20462 684 }
keir@20462 685
keir@20462 686 int libxl_device_nic_clean_shutdown(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 687 {
keir@20462 688 return ERROR_NI;
keir@20462 689 }
keir@20462 690
keir@20462 691 int libxl_device_nic_hard_shutdown(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 692 {
keir@20462 693 return ERROR_NI;
keir@20462 694 }
keir@20462 695
keir@20462 696 /******************************************************************************/
keir@20462 697 int libxl_device_vkb_add(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 698 {
keir@20462 699 return ERROR_NI;
keir@20462 700 }
keir@20462 701
keir@20462 702 int libxl_device_vkb_clean_shutdown(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 703 {
keir@20462 704 return ERROR_NI;
keir@20462 705 }
keir@20462 706
keir@20462 707 int libxl_device_vkb_hard_shutdown(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 708 {
keir@20462 709 return ERROR_NI;
keir@20462 710 }
keir@20462 711
keir@20462 712 /******************************************************************************/
keir@20462 713 int libxl_device_vfb_add(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 714 {
keir@20462 715 return ERROR_NI;
keir@20462 716 }
keir@20462 717
keir@20462 718 int libxl_device_vfb_clean_shutdown(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 719 {
keir@20462 720 return ERROR_NI;
keir@20462 721 }
keir@20462 722
keir@20462 723 int libxl_device_vfb_hard_shutdown(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 724 {
keir@20462 725 return ERROR_NI;
keir@20462 726 }
keir@20462 727
keir@20462 728 /******************************************************************************/
keir@20462 729 int libxl_device_pci_add(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 730 {
keir@20462 731 return ERROR_NI;
keir@20462 732 }
keir@20462 733
keir@20462 734 int libxl_device_pci_clean_shutdown(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 735 {
keir@20462 736 return ERROR_NI;
keir@20462 737 }
keir@20462 738
keir@20462 739 int libxl_device_pci_hard_shutdown(struct libxl_ctx *ctx, uint32_t domid)
keir@20462 740 {
keir@20462 741 return ERROR_NI;
keir@20462 742 }