debuggers.hg

view tools/libxen/test/test_bindings.c @ 0:7d21f7218375

Exact replica of unstable on 051908 + README-this
author Mukesh Rathor
date Mon May 19 15:34:57 2008 -0700 (2008-05-19)
parents
children
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>
28 #include <xen/api/xen_all.h>
30 //#define PRINT_XML
32 static void usage()
33 {
34 fprintf(stderr,
35 "Usage:\n"
36 "\n"
37 " test_bindings <url> <username> <password>\n"
38 "\n"
39 "where\n"
40 " <url> is a fragment of the server's URL, e.g. localhost:8005/RPC2;\n"
41 " <username> is the username to use at the server; and\n"
42 " <password> is the password.\n");
44 exit(EXIT_FAILURE);
45 }
48 static char *url;
51 typedef struct
52 {
53 xen_result_func func;
54 void *handle;
55 } xen_comms;
58 static xen_vm create_new_vm(xen_session *session, bool hvm);
59 static void print_session_info(xen_session *session);
60 static void print_methods(xen_session *session);
61 static void print_vm_power_state(xen_session *session, xen_vm vm);
62 static void print_vm_metrics(xen_session *session, xen_vm vm);
65 static size_t
66 write_func(void *ptr, size_t size, size_t nmemb, xen_comms *comms)
67 {
68 size_t n = size * nmemb;
69 #ifdef PRINT_XML
70 printf("\n\n---Result from server -----------------------\n");
71 printf("%s\n",((char*) ptr));
72 fflush(stdout);
73 #endif
74 return comms->func(ptr, n, comms->handle) ? n : 0;
75 }
78 static int
79 call_func(const void *data, size_t len, void *user_handle,
80 void *result_handle, xen_result_func result_func)
81 {
82 (void)user_handle;
84 #ifdef PRINT_XML
85 printf("\n\n---Data to server: -----------------------\n");
86 printf("%s\n",((char*) data));
87 fflush(stdout);
88 #endif
90 CURL *curl = curl_easy_init();
91 if (!curl) {
92 return -1;
93 }
95 xen_comms comms = {
96 .func = result_func,
97 .handle = result_handle
98 };
100 curl_easy_setopt(curl, CURLOPT_URL, url);
101 curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
102 curl_easy_setopt(curl, CURLOPT_MUTE, 1);
103 curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &write_func);
104 curl_easy_setopt(curl, CURLOPT_WRITEDATA, &comms);
105 curl_easy_setopt(curl, CURLOPT_POST, 1);
106 curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
107 curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, len);
109 CURLcode result = curl_easy_perform(curl);
111 curl_easy_cleanup(curl);
113 return result;
114 }
117 static void print_error(xen_session *session)
118 {
119 fprintf(stderr, "Error: %d", session->error_description_count);
120 for (int i = 0; i < session->error_description_count; i++)
121 {
122 fprintf(stderr, "%s ", session->error_description[i]);
123 }
124 fprintf(stderr, "\n");
125 }
128 int main(int argc, char **argv)
129 {
130 if (argc != 4)
131 {
132 usage();
133 }
135 url = argv[1];
136 char *username = argv[2];
137 char *password = argv[3];
139 xmlInitParser();
140 xen_init();
141 curl_global_init(CURL_GLOBAL_ALL);
143 #define CLEANUP \
144 do { \
145 xen_session_logout(session); \
146 curl_global_cleanup(); \
147 xen_fini(); \
148 xmlCleanupParser(); \
149 } while(0) \
152 xen_session *session =
153 xen_session_login_with_password(call_func, NULL, username, password);
155 print_session_info(session);
156 if (!session->ok)
157 {
158 /* Error has been logged, just clean up. */
159 CLEANUP;
160 return 1;
161 }
163 print_methods(session);
164 if (!session->ok)
165 {
166 /* Error has been logged, just clean up. */
167 CLEANUP;
168 return 1;
169 }
171 xen_vm vm;
172 if (!xen_vm_get_by_uuid(session, &vm,
173 "00000000-0000-0000-0000-000000000000"))
174 {
175 print_error(session);
176 CLEANUP;
177 return 1;
178 }
180 char *vm_uuid;
181 if (!xen_vm_get_uuid(session, &vm_uuid, vm))
182 {
183 print_error(session);
184 xen_vm_free(vm);
185 CLEANUP;
186 return 1;
187 }
189 char *vm_uuid_bytes;
190 if (!xen_uuid_string_to_bytes(vm_uuid, &vm_uuid_bytes))
191 {
192 fprintf(stderr, "xen_uuid_string_to_bytes failed.\n");
193 xen_uuid_free(vm_uuid);
194 xen_vm_free(vm);
195 CLEANUP;
196 return 1;
197 }
199 xen_vm_record *vm_record;
200 if (!xen_vm_get_record(session, &vm_record, vm))
201 {
202 print_error(session);
203 xen_uuid_bytes_free(vm_uuid_bytes);
204 xen_uuid_free(vm_uuid);
205 xen_vm_free(vm);
206 CLEANUP;
207 return 1;
208 }
210 xen_host host;
211 if (!xen_session_get_this_host(session, &host, session))
212 {
213 print_error(session);
214 xen_vm_record_free(vm_record);
215 xen_uuid_bytes_free(vm_uuid_bytes);
216 xen_uuid_free(vm_uuid);
217 xen_vm_free(vm);
218 CLEANUP;
219 return 1;
220 }
222 xen_string_string_map *versions;
223 if (!xen_host_get_software_version(session, &versions, host))
224 {
225 print_error(session);
226 xen_host_free(host);
227 xen_vm_record_free(vm_record);
228 xen_uuid_bytes_free(vm_uuid_bytes);
229 xen_uuid_free(vm_uuid);
230 xen_vm_free(vm);
231 CLEANUP;
232 return 1;
233 }
235 char *dmesg;
236 if (!xen_host_dmesg(session, &dmesg, host))
237 {
238 print_error(session);
239 xen_string_string_map_free(versions);
240 xen_host_free(host);
241 xen_vm_record_free(vm_record);
242 xen_uuid_bytes_free(vm_uuid_bytes);
243 xen_uuid_free(vm_uuid);
244 xen_vm_free(vm);
245 CLEANUP;
246 return 1;
247 }
249 xen_string_set *supported_bootloaders;
250 if (!xen_host_get_supported_bootloaders(session, &supported_bootloaders,
251 host))
252 {
253 print_error(session);
254 free(dmesg);
255 xen_string_string_map_free(versions);
256 xen_host_free(host);
257 xen_vm_record_free(vm_record);
258 xen_uuid_bytes_free(vm_uuid_bytes);
259 xen_uuid_free(vm_uuid);
260 xen_vm_free(vm);
261 CLEANUP;
262 return 1;
263 }
265 xen_string_set *capabilities;
266 if (!xen_host_get_capabilities(session, &capabilities, host))
267 {
268 print_error(session);
269 free(dmesg);
270 xen_string_set_free(supported_bootloaders);
271 xen_string_string_map_free(versions);
272 xen_host_free(host);
273 xen_vm_record_free(vm_record);
274 xen_uuid_bytes_free(vm_uuid_bytes);
275 xen_uuid_free(vm_uuid);
276 xen_vm_free(vm);
277 CLEANUP;
278 return 1;
279 }
281 xen_string_string_map *cpu_configuration;
282 if (!xen_host_get_cpu_configuration(session, &cpu_configuration, host))
283 {
284 print_error(session);
285 free(dmesg);
286 xen_string_set_free(capabilities);
287 xen_string_set_free(supported_bootloaders);
288 xen_string_string_map_free(versions);
289 xen_host_free(host);
290 xen_vm_record_free(vm_record);
291 xen_uuid_bytes_free(vm_uuid_bytes);
292 xen_uuid_free(vm_uuid);
293 xen_vm_free(vm);
294 CLEANUP;
295 return 1;
296 }
298 char *sched_policy;
299 if (!xen_host_get_sched_policy(session, &sched_policy, host))
300 {
301 print_error(session);
302 xen_string_string_map_free(cpu_configuration);
303 xen_string_set_free(capabilities);
304 xen_string_set_free(supported_bootloaders);
305 xen_string_string_map_free(versions);
306 xen_host_free(host);
307 xen_vm_record_free(vm_record);
308 xen_uuid_bytes_free(vm_uuid_bytes);
309 xen_uuid_free(vm_uuid);
310 xen_vm_free(vm);
311 CLEANUP;
312 return 1;
313 }
315 printf("%s.\n", vm_uuid);
317 printf("In bytes, the VM UUID is ");
318 for (int i = 0; i < 15; i++)
319 {
320 printf("%x, ", (unsigned int)vm_uuid_bytes[i]);
321 }
322 printf("%x.\n", (unsigned int)vm_uuid_bytes[15]);
324 printf("%zd.\n", versions->size);
326 for (size_t i = 0; i < versions->size; i++)
327 {
328 printf("%s -> %s.\n", versions->contents[i].key,
329 versions->contents[i].val);
330 }
332 printf("Host dmesg follows:\n%s\n\n", dmesg);
334 printf("Host supports the following bootloaders:");
335 for (size_t i = 0; i < supported_bootloaders->size; i++)
336 {
337 printf(" %s", supported_bootloaders->contents[i]);
338 }
339 printf("\n");
341 printf("Host has the following capabilities:");
342 for (size_t i = 0; i < capabilities->size; i++)
343 {
344 printf(" %s", capabilities->contents[i]);
345 }
346 printf("\n");
348 printf("Host has the following CPU configuration:\n");
349 for (size_t i = 0; i < cpu_configuration->size; i++)
350 {
351 printf(" %s -> %s.\n", cpu_configuration->contents[i].key,
352 cpu_configuration->contents[i].val);
353 }
355 printf("Current scheduler policy: %s.\n\n", sched_policy);
357 printf("%s.\n", vm_record->uuid);
359 printf("Resident on %s.\n", (char *)vm_record->resident_on->u.handle);
361 printf("%s.\n", xen_vm_power_state_to_string(vm_record->power_state));
363 xen_uuid_bytes_free(vm_uuid_bytes);
364 xen_uuid_free(vm_uuid);
366 xen_vm_record_free(vm_record);
368 xen_host_free(host);
369 xen_string_string_map_free(versions);
370 free(dmesg);
371 xen_string_set_free(supported_bootloaders);
372 xen_string_set_free(capabilities);
373 xen_string_string_map_free(cpu_configuration);
374 free(sched_policy);
376 print_vm_metrics(session, vm);
377 if (!session->ok)
378 {
379 /* Error has been logged, just clean up. */
380 xen_vm_free(vm);
381 CLEANUP;
382 return 1;
383 }
385 xen_vm_free(vm);
387 xen_vm new_vm = create_new_vm(session, true);
388 if (!session->ok)
389 {
390 /* Error has been logged, just clean up. */
391 CLEANUP;
392 return 1;
393 }
395 print_vm_power_state(session, new_vm);
396 if (!session->ok)
397 {
398 /* Error has been logged, just clean up. */
399 xen_vm_free(new_vm);
400 CLEANUP;
401 return 1;
402 }
404 xen_vm_free(new_vm);
405 CLEANUP;
407 return 0;
408 }
411 /**
412 * Creation of a new VM, using the Named Parameters idiom. Allocate the
413 * xen_vm_record here, but the sets through the library. Either
414 * allocation patterns can be used, as long as the allocation and free are
415 * paired correctly.
416 */
417 static xen_vm create_new_vm(xen_session *session, bool hvm)
418 {
419 xen_string_string_map *vcpus_params = xen_string_string_map_alloc(1);
420 vcpus_params->contents[0].key = strdup("weight");
421 vcpus_params->contents[0].val = strdup("300");
423 xen_string_string_map *hvm_boot_params;
424 if (hvm)
425 {
426 hvm_boot_params = xen_string_string_map_alloc(1);
427 hvm_boot_params->contents[0].key = strdup("order");
428 hvm_boot_params->contents[0].val = strdup("cd");
429 }
430 else
431 {
432 hvm_boot_params = NULL;
433 }
435 xen_vm_record vm_record =
436 {
437 .name_label = hvm ? "NewHVM" : "NewPV",
438 .name_description = hvm ? "New HVM VM" : "New PV VM",
439 .user_version = 1,
440 .is_a_template = false,
441 .memory_static_max = 256 * 1024 * 1024,
442 .memory_dynamic_max = 256 * 1024 * 1024,
443 .memory_dynamic_min = 128 * 1024 * 1024,
444 .memory_static_min = 128 * 1024 * 1024,
445 .vcpus_params = vcpus_params,
446 .vcpus_max = 4,
447 .vcpus_at_startup = 2,
448 .actions_after_shutdown = XEN_ON_NORMAL_EXIT_DESTROY,
449 .actions_after_reboot = XEN_ON_NORMAL_EXIT_RESTART,
450 .actions_after_crash = XEN_ON_CRASH_BEHAVIOUR_RESTART,
451 .hvm_boot_policy = hvm ? "BIOS order" : NULL,
452 .hvm_boot_params = hvm ? hvm_boot_params : NULL,
453 .pv_bootloader = hvm ? NULL : "pygrub",
454 .pv_kernel = hvm ? NULL : "/boot/vmlinuz-2.6.16.33-xen",
455 };
457 xen_vm vm;
458 xen_vm_create(session, &vm, &vm_record);
460 xen_string_string_map_free(vcpus_params);
461 xen_string_string_map_free(hvm_boot_params);
463 if (!session->ok)
464 {
465 fprintf(stderr, "VM creation failed.\n");
466 print_error(session);
467 return NULL;
468 }
471 /*
472 * Create a new disk for the new VM.
473 */
474 xen_sr_set *srs;
475 if (!xen_sr_get_by_name_label(session, &srs, "QCoW") ||
476 srs->size < 1)
477 {
478 fprintf(stderr, "SR lookup failed.\n");
479 print_error(session);
480 xen_vm_free(vm);
481 return NULL;
482 }
484 xen_sr_record_opt sr_record =
485 {
486 .u.handle = srs->contents[0]
487 };
488 xen_vdi_record vdi0_record =
489 {
490 .name_label = "MyRootFS",
491 .name_description = "MyRootFS description",
492 .sr = &sr_record,
493 .virtual_size = (INT64_C(1) << 30), // 1GiB
494 .type = XEN_VDI_TYPE_SYSTEM,
495 .sharable = false,
496 .read_only = false
497 };
499 xen_vdi vdi0;
500 if (!xen_vdi_create(session, &vdi0, &vdi0_record))
501 {
502 fprintf(stderr, "VDI creation failed.\n");
503 print_error(session);
505 xen_sr_set_free(srs);
506 xen_vm_free(vm);
507 return NULL;
508 }
511 xen_vm_record_opt vm_record_opt =
512 {
513 .u.handle = vm
514 };
515 xen_vdi_record_opt vdi0_record_opt =
516 {
517 .u.handle = vdi0
518 };
519 xen_vbd_record vbd0_record =
520 {
521 .vm = &vm_record_opt,
522 .vdi = &vdi0_record_opt,
523 .device = "xvda1",
524 .mode = XEN_VBD_MODE_RW,
525 .bootable = 1,
526 };
528 xen_vbd vbd0;
529 if (!xen_vbd_create(session, &vbd0, &vbd0_record))
530 {
531 fprintf(stderr, "VBD creation failed.\n");
532 print_error(session);
534 xen_vdi_free(vdi0);
535 xen_sr_set_free(srs);
536 xen_vm_free(vm);
537 return NULL;
538 }
540 xen_console vnc_console = NULL;
541 if (hvm) {
542 xen_console_record vnc_console_record =
543 {
544 .protocol = XEN_CONSOLE_PROTOCOL_RFB,
545 .vm = &vm_record_opt,
546 };
548 if (!xen_console_create(session, &vnc_console, &vnc_console_record))
549 {
550 fprintf(stderr, "VNC console creation failed.\n");
551 print_error(session);
553 xen_vbd_free(vbd0);
554 xen_vdi_free(vdi0);
555 xen_sr_set_free(srs);
556 xen_vm_free(vm);
557 return NULL;
558 }
559 }
561 char *vm_uuid;
562 char *vdi0_uuid;
563 char *vbd0_uuid;
564 char *vnc_uuid = NULL;
566 xen_vm_get_uuid(session, &vm_uuid, vm);
567 xen_vdi_get_uuid(session, &vdi0_uuid, vdi0);
568 xen_vbd_get_uuid(session, &vbd0_uuid, vbd0);
569 if (hvm) {
570 xen_console_get_uuid(session, &vnc_uuid, vnc_console);
571 }
573 if (!session->ok)
574 {
575 fprintf(stderr, "get_uuid call failed.\n");
576 print_error(session);
578 xen_uuid_free(vm_uuid);
579 xen_uuid_free(vdi0_uuid);
580 xen_uuid_free(vbd0_uuid);
581 xen_uuid_free(vnc_uuid);
582 xen_vbd_free(vbd0);
583 xen_vdi_free(vdi0);
584 xen_console_free(vnc_console);
585 xen_sr_set_free(srs);
586 xen_vm_free(vm);
587 return NULL;
588 }
590 if (hvm) {
591 printf("Created a new HVM VM, with UUID %s, VDI UUID %s, VBD "
592 "UUID %s, and VNC console UUID %s.\n",
593 vm_uuid, vdi0_uuid, vbd0_uuid, vnc_uuid);
594 }
595 else {
596 printf("Created a new PV VM, with UUID %s, VDI UUID %s, and VBD "
597 "UUID %s.\n",
598 vm_uuid, vdi0_uuid, vbd0_uuid);
599 }
601 xen_uuid_free(vm_uuid);
602 xen_uuid_free(vdi0_uuid);
603 xen_uuid_free(vbd0_uuid);
604 xen_uuid_free(vnc_uuid);
605 xen_vbd_free(vbd0);
606 xen_vdi_free(vdi0);
607 xen_console_free(vnc_console);
608 xen_sr_set_free(srs);
610 return vm;
611 }
614 /**
615 * Print the power state for the given VM.
616 */
617 static void print_vm_power_state(xen_session *session, xen_vm vm)
618 {
619 char *vm_uuid;
620 enum xen_vm_power_state power_state;
622 if (!xen_vm_get_uuid(session, &vm_uuid, vm))
623 {
624 print_error(session);
625 return;
626 }
628 if (!xen_vm_get_power_state(session, &power_state, vm))
629 {
630 xen_uuid_free(vm_uuid);
631 print_error(session);
632 return;
633 }
635 printf("VM %s power state is %s.\n", vm_uuid,
636 xen_vm_power_state_to_string(power_state));
638 xen_uuid_free(vm_uuid);
640 fflush(stdout);
641 }
644 /**
645 * Workaround for whinging GCCs, as suggested by strftime(3).
646 */
647 static size_t my_strftime(char *s, size_t max, const char *fmt,
648 const struct tm *tm)
649 {
650 return strftime(s, max, fmt, tm);
651 }
654 /**
655 * Print some session details.
656 */
657 static void print_session_info(xen_session *session)
658 {
659 xen_session_record *record;
660 if (!xen_session_get_record(session, &record, session))
661 {
662 print_error(session);
663 return;
664 }
666 printf("Session UUID: %s.\n", record->uuid);
667 printf("Session user: %s.\n", record->this_user);
668 char time[256];
669 struct tm *tm = localtime(&record->last_active);
670 my_strftime(time, 256, "Session last active: %c, local time.\n", tm);
671 printf(time);
673 char *uuid = NULL;
674 char *this_user = NULL;
675 xen_session_get_uuid(session, &uuid, session);
676 xen_session_get_this_user(session, &this_user, session);
678 if (!session->ok)
679 {
680 free(uuid);
681 free(this_user);
682 xen_session_record_free(record);
683 print_error(session);
684 return;
685 }
687 assert(!strcmp(record->uuid, uuid));
688 assert(!strcmp(record->this_user, this_user));
690 free(uuid);
691 free(this_user);
692 xen_session_record_free(record);
694 fflush(stdout);
695 }
698 static int pstrcmp(const void *p1, const void *p2)
699 {
700 return strcmp(*(char **)p1, *(char **)p2);
701 }
704 /**
705 * Print the list of supported methods.
706 */
707 static void print_methods(xen_session *session)
708 {
709 xen_string_set *methods;
711 if (!xen_host_list_methods(session, &methods))
712 {
713 print_error(session);
714 goto done;
715 }
717 printf("%zd.\n", methods->size);
718 qsort(methods->contents, methods->size, sizeof(char *), pstrcmp);
720 printf("Supported methods:\n");
721 for (size_t i = 0; i < methods->size; i++)
722 {
723 printf(" %s\n", methods->contents[i]);
724 }
725 fflush(stdout);
727 done:
728 xen_string_set_free(methods);
729 }
732 /**
733 * Print the metrics for the given VM.
734 */
735 static void print_vm_metrics(xen_session *session, xen_vm vm)
736 {
737 xen_vm_metrics vm_metrics;
738 if (!xen_vm_get_metrics(session, &vm_metrics, vm))
739 {
740 print_error(session);
741 return;
742 }
744 xen_vm_metrics_record *vm_metrics_record;
745 if (!xen_vm_metrics_get_record(session, &vm_metrics_record, vm_metrics))
746 {
747 xen_vm_metrics_free(vm_metrics);
748 print_error(session);
749 return;
750 }
752 char time[256];
753 struct tm *tm = localtime(&vm_metrics_record->last_updated);
754 my_strftime(time, 256, "Metrics updated at %c, local time.\n", tm);
755 printf(time);
757 tm = localtime(&vm_metrics_record->start_time);
758 my_strftime(time, 256, "VM running since %c, local time.\n", tm);
759 printf(time);
761 for (size_t i = 0; i < vm_metrics_record->vcpus_utilisation->size; i++)
762 {
763 printf("%"PRId64" -> %lf.\n",
764 vm_metrics_record->vcpus_utilisation->contents[i].key,
765 vm_metrics_record->vcpus_utilisation->contents[i].val);
766 }
768 printf("VCPU -> PCPU mapping:\n");
769 for (size_t i = 0; i < vm_metrics_record->vcpus_cpu->size; i++)
770 {
771 printf(" %"PRId64" -> %"PRId64".\n",
772 vm_metrics_record->vcpus_cpu->contents[i].key,
773 vm_metrics_record->vcpus_cpu->contents[i].val);
774 }
776 printf("Live scheduling parameters:\n");
777 for (size_t i = 0; i < vm_metrics_record->vcpus_params->size; i++)
778 {
779 printf(" %s -> %s.\n",
780 vm_metrics_record->vcpus_params->contents[i].key,
781 vm_metrics_record->vcpus_params->contents[i].val);
782 }
784 for (size_t i = 0; i < vm_metrics_record->vcpus_flags->size; i++)
785 {
786 printf("%"PRId64" -> ",
787 vm_metrics_record->vcpus_flags->contents[i].key);
788 xen_string_set *s = vm_metrics_record->vcpus_flags->contents[i].val;
789 for (size_t j = 0; j < s->size; j++)
790 {
791 printf("%s", s->contents[j]);
792 if (j + 1 != s->size)
793 {
794 printf(", ");
795 }
796 }
797 printf("\n");
798 }
800 xen_vm_metrics_record_free(vm_metrics_record);
801 xen_vm_metrics_free(vm_metrics);
803 fflush(stdout);
804 }