source: trunk/packages/xen-3.1/xen-3.1/tools/libxen/test/test_bindings.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 18 years ago

Add xen and xen-common

File size: 20.5 KB
Line 
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 */
18
19#define _GNU_SOURCE
20#include <assert.h>
21#include <inttypes.h>
22#include <stdlib.h>
23#include <stdio.h>
24#include <string.h>
25
26#include <libxml/parser.h>
27#include <curl/curl.h>
28#include <xen/api/xen_all.h>
29
30//#define PRINT_XML
31
32static 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");
43
44    exit(EXIT_FAILURE);
45}
46
47
48static char *url;
49
50
51typedef struct
52{
53    xen_result_func func;
54    void *handle;
55} xen_comms;
56
57
58static xen_vm create_new_vm(xen_session *session, bool hvm);
59static void print_session_info(xen_session *session);
60static void print_methods(xen_session *session);
61static void print_vm_power_state(xen_session *session, xen_vm vm);
62static void print_vm_metrics(xen_session *session, xen_vm vm);
63
64
65static size_t
66write_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}
76
77
78static int
79call_func(const void *data, size_t len, void *user_handle,
80          void *result_handle, xen_result_func result_func)
81{
82    (void)user_handle;
83
84#ifdef PRINT_XML
85    printf("\n\n---Data to server: -----------------------\n");
86    printf("%s\n",((char*) data));
87    fflush(stdout);
88#endif
89
90    CURL *curl = curl_easy_init();
91    if (!curl) {
92        return -1;
93    }
94
95    xen_comms comms = {
96        .func = result_func,
97        .handle = result_handle
98    };
99
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);
108
109    CURLcode result = curl_easy_perform(curl);
110
111    curl_easy_cleanup(curl);
112
113    return result;
114}
115
116
117static 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}
126
127
128int main(int argc, char **argv)
129{
130    if (argc != 4)
131    {
132        usage();
133    }
134
135    url = argv[1];
136    char *username = argv[2];
137    char *password = argv[3];
138
139    xmlInitParser();
140    xen_init();
141    curl_global_init(CURL_GLOBAL_ALL);
142
143#define CLEANUP                                 \
144    do {                                        \
145        xen_session_logout(session);            \
146        curl_global_cleanup();                  \
147        xen_fini();                             \
148        xmlCleanupParser();                     \
149    } while(0)                                  \
150
151   
152    xen_session *session =
153        xen_session_login_with_password(call_func, NULL, username, password);
154
155    print_session_info(session);
156    if (!session->ok)
157    {
158        /* Error has been logged, just clean up. */
159        CLEANUP;
160        return 1;
161    }
162
163    print_methods(session);
164    if (!session->ok)
165    {
166        /* Error has been logged, just clean up. */
167        CLEANUP;
168        return 1;
169    }
170
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    }
179
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    }
188
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    }
198
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    }
209
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    }
221
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    }
234
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    }
248
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    }
264
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    }
280
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    }
297
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    }
314
315    printf("%s.\n", vm_uuid);
316
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]);
323
324    printf("%zd.\n", versions->size);
325
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    }
331
332    printf("Host dmesg follows:\n%s\n\n", dmesg);
333
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");
340
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");
347
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    }
354
355    printf("Current scheduler policy: %s.\n\n", sched_policy);
356
357    printf("%s.\n", vm_record->uuid);
358
359    printf("Resident on %s.\n", (char *)vm_record->resident_on->u.handle);
360
361    printf("%s.\n", xen_vm_power_state_to_string(vm_record->power_state));
362
363    xen_uuid_bytes_free(vm_uuid_bytes);
364    xen_uuid_free(vm_uuid);
365
366    xen_vm_record_free(vm_record);
367
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);
375
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    }
384
385    xen_vm_free(vm);
386
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    }
394
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    }
403
404    xen_vm_free(new_vm);
405    CLEANUP;
406
407    return 0;
408}
409
410
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 */
417static 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");
422
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    }
434
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        };
456
457    xen_vm vm;
458    xen_vm_create(session, &vm, &vm_record);
459
460    xen_string_string_map_free(vcpus_params);
461    xen_string_string_map_free(hvm_boot_params);
462
463    if (!session->ok)
464    {
465        fprintf(stderr, "VM creation failed.\n");
466        print_error(session);
467        return NULL;
468    }
469
470
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    }
483
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        };
498   
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);
504
505        xen_sr_set_free(srs);
506        xen_vm_free(vm);
507        return NULL;
508    }
509
510
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        };
527
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);
533
534        xen_vdi_free(vdi0);
535        xen_sr_set_free(srs);
536        xen_vm_free(vm);
537        return NULL;
538    }
539
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            };
547
548        if (!xen_console_create(session, &vnc_console, &vnc_console_record))
549        {
550            fprintf(stderr, "VNC console creation failed.\n");
551            print_error(session);
552
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    }
560
561    char *vm_uuid;
562    char *vdi0_uuid;
563    char *vbd0_uuid;
564    char *vnc_uuid = NULL;
565
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    }
572
573    if (!session->ok)
574    {
575        fprintf(stderr, "get_uuid call failed.\n");
576        print_error(session);
577
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    }
589
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    }
600
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);
609
610    return vm;
611}
612
613
614/**
615 * Print the power state for the given VM.
616 */
617static void print_vm_power_state(xen_session *session, xen_vm vm)
618{
619    char *vm_uuid;
620    enum xen_vm_power_state power_state;
621
622    if (!xen_vm_get_uuid(session, &vm_uuid, vm))
623    {
624        print_error(session);
625        return;
626    }
627
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    }
634
635    printf("VM %s power state is %s.\n", vm_uuid,
636           xen_vm_power_state_to_string(power_state));
637
638    xen_uuid_free(vm_uuid);
639
640    fflush(stdout);
641}
642
643
644/**
645 * Workaround for whinging GCCs, as suggested by strftime(3).
646 */
647static 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}
652
653
654/**
655 * Print some session details.
656 */
657static 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    }
665
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);
672
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);
677
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    }
686
687    assert(!strcmp(record->uuid, uuid));
688    assert(!strcmp(record->this_user, this_user));
689
690    free(uuid);
691    free(this_user);
692    xen_session_record_free(record);
693
694    fflush(stdout);
695}
696
697
698static int pstrcmp(const void *p1, const void *p2)
699{
700    return strcmp(*(char **)p1, *(char **)p2);
701}
702
703
704/**
705 * Print the list of supported methods.
706 */
707static void print_methods(xen_session *session)
708{
709    xen_string_set *methods;
710
711    if (!xen_host_list_methods(session, &methods))
712    {
713        print_error(session);
714        goto done;
715    }
716
717    printf("%zd.\n", methods->size);
718    qsort(methods->contents, methods->size, sizeof(char *), pstrcmp);
719
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);
726
727done:
728    xen_string_set_free(methods);
729}
730
731
732/**
733 * Print the metrics for the given VM.
734 */
735static 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    }
743
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    }
751
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);
756
757    tm = localtime(&vm_metrics_record->start_time);
758    my_strftime(time, 256, "VM running since %c, local time.\n", tm);
759    printf(time);
760
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    }
767
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    }
775
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    }
783
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    }
799
800    xen_vm_metrics_record_free(vm_metrics_record);
801    xen_vm_metrics_free(vm_metrics);
802
803    fflush(stdout);
804}
Note: See TracBrowser for help on using the repository browser.