ia64/xen-unstable

view tools/libxen/test/test_bindings.c @ 14551:5987388630f4

Create the new VM with the default crash behaviour set.

Signed-off-by: Ewan Mellor <ewan@xensource.com>
author Ewan Mellor <ewan@xensource.com>
date Mon Mar 26 00:40:34 2007 +0100 (2007-03-26)
parents ae81e49219a8
children 5dcb272de7e4
line source
1 /*
2 * Copyright (c) 2006-2007 XenSource, Inc.
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
19 #define _GNU_SOURCE
20 #include <assert.h>
21 #include <inttypes.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
26 #include <libxml/parser.h>
27 #include <curl/curl.h>
29 #include "xen_host.h"
30 #include "xen_sr.h"
31 #include "xen_vbd.h"
32 #include "xen_vdi.h"
33 #include "xen_console.h"
34 #include "xen_vm.h"
35 #include "xen_vm_metrics.h"
37 //#define PRINT_XML
39 static void usage()
40 {
41 fprintf(stderr,
42 "Usage:\n"
43 "\n"
44 " test_bindings <url> <username> <password>\n"
45 "\n"
46 "where\n"
47 " <url> is a fragment of the server's URL, e.g. localhost:8005/RPC2;\n"
48 " <username> is the username to use at the server; and\n"
49 " <password> is the password.\n");
51 exit(EXIT_FAILURE);
52 }
55 static char *url;
58 typedef struct
59 {
60 xen_result_func func;
61 void *handle;
62 } xen_comms;
65 static xen_vm create_new_vm(xen_session *session, bool hvm);
66 static void print_session_info(xen_session *session);
67 static void print_vm_power_state(xen_session *session, xen_vm vm);
68 static void print_vm_metrics(xen_session *session, xen_vm vm);
71 static size_t
72 write_func(void *ptr, size_t size, size_t nmemb, xen_comms *comms)
73 {
74 size_t n = size * nmemb;
75 #ifdef PRINT_XML
76 printf("\n\n---Result from server -----------------------\n");
77 printf("%s\n",((char*) ptr));
78 fflush(stdout);
79 #endif
80 return comms->func(ptr, n, comms->handle) ? n : 0;
81 }
84 static int
85 call_func(const void *data, size_t len, void *user_handle,
86 void *result_handle, xen_result_func result_func)
87 {
88 (void)user_handle;
90 #ifdef PRINT_XML
91 printf("\n\n---Data to server: -----------------------\n");
92 printf("%s\n",((char*) data));
93 fflush(stdout);
94 #endif
96 CURL *curl = curl_easy_init();
97 if (!curl) {
98 return -1;
99 }
101 xen_comms comms = {
102 .func = result_func,
103 .handle = result_handle
104 };
106 curl_easy_setopt(curl, CURLOPT_URL, url);
107 curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
108 curl_easy_setopt(curl, CURLOPT_MUTE, 1);
109 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &write_func);
110 curl_easy_setopt(curl, CURLOPT_WRITEDATA, &comms);
111 curl_easy_setopt(curl, CURLOPT_POST, 1);
112 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
113 curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, len);
115 CURLcode result = curl_easy_perform(curl);
117 curl_easy_cleanup(curl);
119 return result;
120 }
123 static void print_error(xen_session *session)
124 {
125 fprintf(stderr, "Error: %d", session->error_description_count);
126 for (int i = 0; i < session->error_description_count; i++)
127 {
128 fprintf(stderr, "%s ", session->error_description[i]);
129 }
130 fprintf(stderr, "\n");
131 }
134 int main(int argc, char **argv)
135 {
136 if (argc != 4)
137 {
138 usage();
139 }
141 url = argv[1];
142 char *username = argv[2];
143 char *password = argv[3];
145 xmlInitParser();
146 xen_init();
147 curl_global_init(CURL_GLOBAL_ALL);
149 #define CLEANUP \
150 do { \
151 xen_session_logout(session); \
152 curl_global_cleanup(); \
153 xen_fini(); \
154 xmlCleanupParser(); \
155 } while(0) \
158 xen_session *session =
159 xen_session_login_with_password(call_func, NULL, username, password);
161 print_session_info(session);
162 if (!session->ok)
163 {
164 /* Error has been logged, just clean up. */
165 CLEANUP;
166 return 1;
167 }
169 xen_vm vm;
170 if (!xen_vm_get_by_uuid(session, &vm,
171 "00000000-0000-0000-0000-000000000000"))
172 {
173 print_error(session);
174 CLEANUP;
175 return 1;
176 }
178 char *vm_uuid;
179 if (!xen_vm_get_uuid(session, &vm_uuid, vm))
180 {
181 print_error(session);
182 xen_vm_free(vm);
183 CLEANUP;
184 return 1;
185 }
187 char *vm_uuid_bytes;
188 if (!xen_uuid_string_to_bytes(vm_uuid, &vm_uuid_bytes))
189 {
190 fprintf(stderr, "xen_uuid_string_to_bytes failed.\n");
191 xen_uuid_free(vm_uuid);
192 xen_vm_free(vm);
193 CLEANUP;
194 return 1;
195 }
197 xen_vm_record *vm_record;
198 if (!xen_vm_get_record(session, &vm_record, vm))
199 {
200 print_error(session);
201 xen_uuid_bytes_free(vm_uuid_bytes);
202 xen_uuid_free(vm_uuid);
203 xen_vm_free(vm);
204 CLEANUP;
205 return 1;
206 }
208 xen_host host;
209 if (!xen_session_get_this_host(session, &host, session))
210 {
211 print_error(session);
212 xen_vm_record_free(vm_record);
213 xen_uuid_bytes_free(vm_uuid_bytes);
214 xen_uuid_free(vm_uuid);
215 xen_vm_free(vm);
216 CLEANUP;
217 return 1;
218 }
220 xen_string_string_map *versions;
221 if (!xen_host_get_software_version(session, &versions, host))
222 {
223 print_error(session);
224 xen_host_free(host);
225 xen_vm_record_free(vm_record);
226 xen_uuid_bytes_free(vm_uuid_bytes);
227 xen_uuid_free(vm_uuid);
228 xen_vm_free(vm);
229 CLEANUP;
230 return 1;
231 }
233 char *dmesg;
234 if (!xen_host_dmesg(session, &dmesg, host))
235 {
236 print_error(session);
237 xen_string_string_map_free(versions);
238 xen_host_free(host);
239 xen_vm_record_free(vm_record);
240 xen_uuid_bytes_free(vm_uuid_bytes);
241 xen_uuid_free(vm_uuid);
242 xen_vm_free(vm);
243 CLEANUP;
244 return 1;
245 }
247 xen_string_set *supported_bootloaders;
248 if (!xen_host_get_supported_bootloaders(session, &supported_bootloaders,
249 host))
250 {
251 print_error(session);
252 free(dmesg);
253 xen_string_string_map_free(versions);
254 xen_host_free(host);
255 xen_vm_record_free(vm_record);
256 xen_uuid_bytes_free(vm_uuid_bytes);
257 xen_uuid_free(vm_uuid);
258 xen_vm_free(vm);
259 CLEANUP;
260 return 1;
261 }
263 xen_string_set *capabilities;
264 if (!xen_host_get_capabilities(session, &capabilities, host))
265 {
266 print_error(session);
267 free(dmesg);
268 xen_string_set_free(supported_bootloaders);
269 xen_string_string_map_free(versions);
270 xen_host_free(host);
271 xen_vm_record_free(vm_record);
272 xen_uuid_bytes_free(vm_uuid_bytes);
273 xen_uuid_free(vm_uuid);
274 xen_vm_free(vm);
275 CLEANUP;
276 return 1;
277 }
279 printf("%s.\n", vm_uuid);
281 printf("In bytes, the VM UUID is ");
282 for (int i = 0; i < 15; i++)
283 {
284 printf("%x, ", (unsigned int)vm_uuid_bytes[i]);
285 }
286 printf("%x.\n", (unsigned int)vm_uuid_bytes[15]);
288 printf("%zd.\n", versions->size);
290 for (size_t i = 0; i < versions->size; i++)
291 {
292 printf("%s -> %s.\n", versions->contents[i].key,
293 versions->contents[i].val);
294 }
296 printf("Host dmesg follows:\n%s\n\n", dmesg);
298 printf("Host supports the following bootloaders:");
299 for (size_t i = 0; i < supported_bootloaders->size; i++)
300 {
301 printf(" %s", supported_bootloaders->contents[i]);
302 }
303 printf("\n");
305 printf("Host has the following capabilities:");
306 for (size_t i = 0; i < capabilities->size; i++)
307 {
308 printf(" %s", capabilities->contents[i]);
309 }
310 printf("\n");
312 printf("%s.\n", vm_record->uuid);
314 printf("Resident on %s.\n", (char *)vm_record->resident_on->u.handle);
316 printf("%s.\n", xen_vm_power_state_to_string(vm_record->power_state));
318 xen_uuid_bytes_free(vm_uuid_bytes);
319 xen_uuid_free(vm_uuid);
321 xen_vm_record_free(vm_record);
323 xen_host_free(host);
324 xen_string_string_map_free(versions);
325 free(dmesg);
326 xen_string_set_free(supported_bootloaders);
327 xen_string_set_free(capabilities);
329 print_vm_metrics(session, vm);
330 if (!session->ok)
331 {
332 /* Error has been logged, just clean up. */
333 xen_vm_free(vm);
334 CLEANUP;
335 return 1;
336 }
338 xen_vm_free(vm);
340 xen_vm new_vm = create_new_vm(session, true);
341 if (!session->ok)
342 {
343 /* Error has been logged, just clean up. */
344 CLEANUP;
345 return 1;
346 }
348 print_vm_power_state(session, new_vm);
349 if (!session->ok)
350 {
351 /* Error has been logged, just clean up. */
352 xen_vm_free(new_vm);
353 CLEANUP;
354 return 1;
355 }
357 xen_vm_free(new_vm);
358 CLEANUP;
360 return 0;
361 }
364 /**
365 * Creation of a new VM, using the Named Parameters idiom. Allocate the
366 * xen_vm_record here, but the sets through the library. Either
367 * allocation patterns can be used, as long as the allocation and free are
368 * paired correctly.
369 */
370 static xen_vm create_new_vm(xen_session *session, bool hvm)
371 {
372 xen_string_string_map *vcpus_params = xen_string_string_map_alloc(1);
373 vcpus_params->contents[0].key = strdup("weight");
374 vcpus_params->contents[0].val = strdup("300");
376 xen_string_string_map *hvm_boot_params;
377 if (hvm)
378 {
379 hvm_boot_params = xen_string_string_map_alloc(1);
380 hvm_boot_params->contents[0].key = strdup("order");
381 hvm_boot_params->contents[0].val = strdup("cd");
382 }
383 else
384 {
385 hvm_boot_params = NULL;
386 }
388 xen_vm_record vm_record =
389 {
390 .name_label = hvm ? "NewHVM" : "NewPV",
391 .name_description = hvm ? "New HVM VM" : "New PV VM",
392 .user_version = 1,
393 .is_a_template = false,
394 .memory_static_max = 256 * 1024 * 1024,
395 .memory_dynamic_max = 256 * 1024 * 1024,
396 .memory_dynamic_min = 128 * 1024 * 1024,
397 .memory_static_min = 128 * 1024 * 1024,
398 .vcpus_params = vcpus_params,
399 .vcpus_max = 4,
400 .vcpus_at_startup = 2,
401 .actions_after_shutdown = XEN_ON_NORMAL_EXIT_DESTROY,
402 .actions_after_reboot = XEN_ON_NORMAL_EXIT_RESTART,
403 .actions_after_crash = XEN_ON_CRASH_BEHAVIOUR_RESTART,
404 .hvm_boot_policy = hvm ? "BIOS order" : NULL,
405 .hvm_boot_params = hvm ? hvm_boot_params : NULL,
406 .pv_bootloader = hvm ? NULL : "pygrub",
407 .pv_kernel = hvm ? NULL : "/boot/vmlinuz-2.6.16.33-xen",
408 };
410 xen_vm vm;
411 xen_vm_create(session, &vm, &vm_record);
413 xen_string_string_map_free(vcpus_params);
414 xen_string_string_map_free(hvm_boot_params);
416 if (!session->ok)
417 {
418 fprintf(stderr, "VM creation failed.\n");
419 print_error(session);
420 return NULL;
421 }
424 /*
425 * Create a new disk for the new VM.
426 */
427 xen_sr_set *srs;
428 if (!xen_sr_get_by_name_label(session, &srs, "QCoW") ||
429 srs->size < 1)
430 {
431 fprintf(stderr, "SR lookup failed.\n");
432 print_error(session);
433 xen_vm_free(vm);
434 return NULL;
435 }
437 xen_sr_record_opt sr_record =
438 {
439 .u.handle = srs->contents[0]
440 };
441 xen_vdi_record vdi0_record =
442 {
443 .name_label = "MyRootFS",
444 .name_description = "MyRootFS description",
445 .sr = &sr_record,
446 .virtual_size = (INT64_C(1) << 30), // 1GiB
447 .type = XEN_VDI_TYPE_SYSTEM,
448 .sharable = false,
449 .read_only = false
450 };
452 xen_vdi vdi0;
453 if (!xen_vdi_create(session, &vdi0, &vdi0_record))
454 {
455 fprintf(stderr, "VDI creation failed.\n");
456 print_error(session);
458 xen_sr_set_free(srs);
459 xen_vm_free(vm);
460 return NULL;
461 }
464 xen_vm_record_opt vm_record_opt =
465 {
466 .u.handle = vm
467 };
468 xen_vdi_record_opt vdi0_record_opt =
469 {
470 .u.handle = vdi0
471 };
472 xen_vbd_record vbd0_record =
473 {
474 .vm = &vm_record_opt,
475 .vdi = &vdi0_record_opt,
476 .device = "xvda1",
477 .mode = XEN_VBD_MODE_RW,
478 .bootable = 1,
479 };
481 xen_vbd vbd0;
482 if (!xen_vbd_create(session, &vbd0, &vbd0_record))
483 {
484 fprintf(stderr, "VBD creation failed.\n");
485 print_error(session);
487 xen_vdi_free(vdi0);
488 xen_sr_set_free(srs);
489 xen_vm_free(vm);
490 return NULL;
491 }
493 xen_console vnc_console = NULL;
494 if (hvm) {
495 xen_console_record vnc_console_record =
496 {
497 .protocol = XEN_CONSOLE_PROTOCOL_RFB,
498 .vm = &vm_record_opt,
499 };
501 if (!xen_console_create(session, &vnc_console, &vnc_console_record))
502 {
503 fprintf(stderr, "VNC console creation failed.\n");
504 print_error(session);
506 xen_vbd_free(vbd0);
507 xen_vdi_free(vdi0);
508 xen_sr_set_free(srs);
509 xen_vm_free(vm);
510 return NULL;
511 }
512 }
514 char *vm_uuid;
515 char *vdi0_uuid;
516 char *vbd0_uuid;
517 char *vnc_uuid = NULL;
519 xen_vm_get_uuid(session, &vm_uuid, vm);
520 xen_vdi_get_uuid(session, &vdi0_uuid, vdi0);
521 xen_vbd_get_uuid(session, &vbd0_uuid, vbd0);
522 if (hvm) {
523 xen_console_get_uuid(session, &vnc_uuid, vnc_console);
524 }
526 if (!session->ok)
527 {
528 fprintf(stderr, "get_uuid call failed.\n");
529 print_error(session);
531 xen_uuid_free(vm_uuid);
532 xen_uuid_free(vdi0_uuid);
533 xen_uuid_free(vbd0_uuid);
534 xen_uuid_free(vnc_uuid);
535 xen_vbd_free(vbd0);
536 xen_vdi_free(vdi0);
537 xen_console_free(vnc_console);
538 xen_sr_set_free(srs);
539 xen_vm_free(vm);
540 return NULL;
541 }
543 if (hvm) {
544 printf("Created a new HVM VM, with UUID %s, VDI UUID %s, VBD "
545 "UUID %s, and VNC console UUID %s.\n",
546 vm_uuid, vdi0_uuid, vbd0_uuid, vnc_uuid);
547 }
548 else {
549 printf("Created a new PV VM, with UUID %s, VDI UUID %s, and VBD "
550 "UUID %s.\n",
551 vm_uuid, vdi0_uuid, vbd0_uuid);
552 }
554 xen_uuid_free(vm_uuid);
555 xen_uuid_free(vdi0_uuid);
556 xen_uuid_free(vbd0_uuid);
557 xen_uuid_free(vnc_uuid);
558 xen_vbd_free(vbd0);
559 xen_vdi_free(vdi0);
560 xen_console_free(vnc_console);
561 xen_sr_set_free(srs);
563 return vm;
564 }
567 /**
568 * Print the power state for the given VM.
569 */
570 static void print_vm_power_state(xen_session *session, xen_vm vm)
571 {
572 char *vm_uuid;
573 enum xen_vm_power_state power_state;
575 if (!xen_vm_get_uuid(session, &vm_uuid, vm))
576 {
577 print_error(session);
578 return;
579 }
581 if (!xen_vm_get_power_state(session, &power_state, vm))
582 {
583 xen_uuid_free(vm_uuid);
584 print_error(session);
585 return;
586 }
588 printf("VM %s power state is %s.\n", vm_uuid,
589 xen_vm_power_state_to_string(power_state));
591 xen_uuid_free(vm_uuid);
593 fflush(stdout);
594 }
597 /**
598 * Workaround for whinging GCCs, as suggested by strftime(3).
599 */
600 static size_t my_strftime(char *s, size_t max, const char *fmt,
601 const struct tm *tm)
602 {
603 return strftime(s, max, fmt, tm);
604 }
607 /**
608 * Print some session details.
609 */
610 static void print_session_info(xen_session *session)
611 {
612 xen_session_record *record;
613 if (!xen_session_get_record(session, &record, session))
614 {
615 print_error(session);
616 return;
617 }
619 printf("Session UUID: %s.\n", record->uuid);
620 printf("Session user: %s.\n", record->this_user);
621 char time[256];
622 struct tm *tm = localtime(&record->last_active);
623 my_strftime(time, 256, "Session last active: %c, local time.\n", tm);
624 printf(time);
626 char *uuid = NULL;
627 char *this_user = NULL;
628 xen_session_get_uuid(session, &uuid, session);
629 xen_session_get_this_user(session, &this_user, session);
631 if (!session->ok)
632 {
633 xen_session_record_free(record);
634 print_error(session);
635 return;
636 }
638 assert(!strcmp(record->uuid, uuid));
639 assert(!strcmp(record->this_user, this_user));
641 xen_session_record_free(record);
643 fflush(stdout);
644 }
647 /**
648 * Print the metrics for the given VM.
649 */
650 static void print_vm_metrics(xen_session *session, xen_vm vm)
651 {
652 xen_vm_metrics vm_metrics;
653 if (!xen_vm_get_metrics(session, &vm_metrics, vm))
654 {
655 print_error(session);
656 return;
657 }
659 xen_vm_metrics_record *vm_metrics_record;
660 if (!xen_vm_metrics_get_record(session, &vm_metrics_record, vm_metrics))
661 {
662 xen_vm_metrics_free(vm_metrics);
663 print_error(session);
664 return;
665 }
667 char time[256];
668 struct tm *tm = localtime(&vm_metrics_record->last_updated);
669 my_strftime(time, 256, "Metrics updated at %c, local time.\n", tm);
670 printf(time);
672 for (size_t i = 0; i < vm_metrics_record->vcpus_utilisation->size; i++)
673 {
674 printf("%"PRId64" -> %lf.\n",
675 vm_metrics_record->vcpus_utilisation->contents[i].key,
676 vm_metrics_record->vcpus_utilisation->contents[i].val);
677 }
679 xen_vm_metrics_record_free(vm_metrics_record);
680 xen_vm_metrics_free(vm_metrics);
682 fflush(stdout);
683 }