diff options
Diffstat (limited to 'tools')
44 files changed, 1144 insertions, 334 deletions
diff --git a/tools/Rules.mk b/tools/Rules.mk index af530ac65d..df3b231a1a 100644 --- a/tools/Rules.mk +++ b/tools/Rules.mk @@ -56,6 +56,6 @@ mk-symlinks-xen: ( cd xen/foreign && ln -sf ../../$(XEN_ROOT)/xen/include/public/foreign/Makefile . ) ( cd xen/foreign && ln -sf ../../$(XEN_ROOT)/xen/include/public/foreign/reference.size . ) ( cd xen/foreign && ln -sf ../../$(XEN_ROOT)/xen/include/public/foreign/*.py . ) - make -C xen/foreign + $(MAKE) -C xen/foreign mk-symlinks: mk-symlinks-xen mk-symlinks-$(XEN_OS) diff --git a/tools/libxc/xc_dom_boot.c b/tools/libxc/xc_dom_boot.c index d8bfe485d8..83b1abe1eb 100644 --- a/tools/libxc/xc_dom_boot.c +++ b/tools/libxc/xc_dom_boot.c @@ -144,7 +144,7 @@ static int x86_shadow(int xc, domid_t domid) return rc; } -static int arch_setup_early(struct xc_dom_image *dom) +static int arch_setup_meminit(struct xc_dom_image *dom) { int rc = 0; @@ -157,13 +157,13 @@ static int arch_setup_early(struct xc_dom_image *dom) return rc; } -static int arch_setup_middle(struct xc_dom_image *dom) +static int arch_setup_bootearly(struct xc_dom_image *dom) { xc_dom_printf("%s: doing nothing\n", __FUNCTION__); return 0; } -static int arch_setup_late(struct xc_dom_image *dom) +static int arch_setup_bootlate(struct xc_dom_image *dom) { static const struct { char *guest; @@ -263,13 +263,13 @@ static int arch_setup_late(struct xc_dom_image *dom) #elif defined(__ia64__) -static int arch_setup_early(struct xc_dom_image *dom) +static int arch_setup_meminit(struct xc_dom_image *dom) { xc_dom_printf("%s: doing nothing\n", __FUNCTION__); return 0; } -static int arch_setup_middle(struct xc_dom_image *dom) +static int arch_setup_bootearly(struct xc_dom_image *dom) { DECLARE_DOMCTL; int rc; @@ -281,10 +281,6 @@ static int arch_setup_middle(struct xc_dom_image *dom) domctl.domain = dom->guest_domid; domctl.u.arch_setup.flags = 0; - /* dom->start_info_pfn should be initialized by alloc_magic_pages(). - * However it is called later. So we initialize here. - */ - dom->start_info_pfn = dom->total_pages - 3; domctl.u.arch_setup.bp = (dom->start_info_pfn << PAGE_SHIFT) + sizeof(start_info_t); /* 3 = start info page, xenstore page and console page */ @@ -293,7 +289,7 @@ static int arch_setup_middle(struct xc_dom_image *dom) return rc; } -static int arch_setup_late(struct xc_dom_image *dom) +static int arch_setup_bootlate(struct xc_dom_image *dom) { unsigned int page_size = XC_DOM_PAGE_SIZE(dom); shared_info_t *shared_info; @@ -317,19 +313,19 @@ static int arch_setup_late(struct xc_dom_image *dom) #elif defined(__powerpc64__) -static int arch_setup_early(struct xc_dom_image *dom) +static int arch_setup_meminit(struct xc_dom_image *dom) { xc_dom_printf("%s: doing nothing\n", __FUNCTION__); return 0; } -static int arch_setup_middle(struct xc_dom_image *dom) +static int arch_setup_bootearly(struct xc_dom_image *dom) { xc_dom_printf("%s: doing nothing\n", __FUNCTION__); return 0; } -static int arch_setup_late(struct xc_dom_image *dom) +static int arch_setup_bootlate(struct xc_dom_image *dom) { start_info_t *si = xc_dom_pfn_to_ptr(dom, dom->start_info_pfn, 1); @@ -355,19 +351,19 @@ static int arch_setup_late(struct xc_dom_image *dom) #else -static int arch_setup_early(struct xc_dom_image *dom) +static int arch_setup_meminit(struct xc_dom_image *dom) { xc_dom_printf("%s: doing nothing\n", __FUNCTION__); return 0; } -static int arch_setup_middle(struct xc_dom_image *dom) +static int arch_setup_bootearly(struct xc_dom_image *dom) { xc_dom_printf("%s: doing nothing\n", __FUNCTION__); return 0; } -static int arch_setup_late(struct xc_dom_image *dom) +static int arch_setup_bootlate(struct xc_dom_image *dom) { xc_dom_printf("%s: doing nothing\n", __FUNCTION__); return 0; @@ -423,7 +419,7 @@ int xc_dom_boot_mem_init(struct xc_dom_image *dom) xc_dom_printf("%s: called\n", __FUNCTION__); - if (0 != (rc = arch_setup_early(dom))) + if (0 != (rc = arch_setup_meminit(dom))) return rc; /* allocate guest memory */ @@ -438,9 +434,6 @@ int xc_dom_boot_mem_init(struct xc_dom_image *dom) return rc; } - if (0 != (rc = arch_setup_middle(dom))) - return rc; - return 0; } @@ -497,6 +490,10 @@ int xc_dom_boot_image(struct xc_dom_image *dom) xc_dom_printf("%s: called\n", __FUNCTION__); + /* misc ia64 stuff*/ + if (0 != (rc = arch_setup_bootearly(dom))) + return rc; + /* collect some info */ domctl.cmd = XEN_DOMCTL_getdomaininfo; domctl.domain = dom->guest_domid; @@ -542,7 +539,7 @@ int xc_dom_boot_image(struct xc_dom_image *dom) xc_dom_log_memory_footprint(dom); /* misc x86 stuff */ - if (0 != (rc = arch_setup_late(dom))) + if (0 != (rc = arch_setup_bootlate(dom))) return rc; /* let the vm run */ diff --git a/tools/libxc/xc_dom_core.c b/tools/libxc/xc_dom_core.c index 8d329ae74f..ae64972ed5 100644 --- a/tools/libxc/xc_dom_core.c +++ b/tools/libxc/xc_dom_core.c @@ -717,6 +717,9 @@ int xc_dom_build_image(struct xc_dom_image *dom) } page_size = XC_DOM_PAGE_SIZE(dom); + /* 4MB align virtual base address */ + dom->parms.virt_base &= ~(((uint64_t)1<<22)-1); + /* load kernel */ if (0 != xc_dom_alloc_segment(dom, &dom->kernel_seg, "kernel", dom->kernel_seg.vstart, diff --git a/tools/libxc/xc_dom_ia64.c b/tools/libxc/xc_dom_ia64.c index c6e4424515..2ffce5a4d7 100644 --- a/tools/libxc/xc_dom_ia64.c +++ b/tools/libxc/xc_dom_ia64.c @@ -26,11 +26,7 @@ static int alloc_magic_pages(struct xc_dom_image *dom) /* allocate special pages */ dom->console_pfn = dom->total_pages -1; dom->xenstore_pfn = dom->total_pages -2; - - /* - * this is initialized by arch_setup_middle(). - * dom->start_info_pfn = dom->total_pages -3; - */ + dom->start_info_pfn = dom->total_pages -3; return 0; } diff --git a/tools/libxc/xc_dom_x86.c b/tools/libxc/xc_dom_x86.c index 9e489c320d..fdc3d4ba5e 100644 --- a/tools/libxc/xc_dom_x86.c +++ b/tools/libxc/xc_dom_x86.c @@ -66,11 +66,12 @@ static int count_pgtables(struct xc_dom_image *dom, int pae, extra_pages = dom->alloc_bootstack ? 1 : 0; extra_pages += dom->extra_pages; + extra_pages += 128; /* 512kB padding */ pages = extra_pages; for (;;) { try_virt_end = round_up(dom->virt_alloc_end + pages * PAGE_SIZE_X86, - bits_to_mask(l1_bits)); + bits_to_mask(22)); /* 4MB alignment */ dom->pg_l4 = nr_page_tables(dom->parms.virt_base, try_virt_end, l4_bits); dom->pg_l3 = @@ -313,6 +314,7 @@ static int alloc_magic_pages(struct xc_dom_image *dom) if (xc_dom_feature_translated(dom)) dom->shared_info_pfn = xc_dom_alloc_page(dom, "shared info"); dom->alloc_bootstack = 1; + return 0; } diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c index 6b67450261..e557f43f13 100644 --- a/tools/libxc/xc_domain.c +++ b/tools/libxc/xc_domain.c @@ -241,45 +241,49 @@ int xc_domain_getinfolist(int xc_handle, /* get info from hvm guest for save */ int xc_domain_hvm_getcontext(int xc_handle, uint32_t domid, - hvm_domain_context_t *hvm_ctxt) + uint8_t *ctxt_buf, + uint32_t size) { - int rc; + int ret; DECLARE_DOMCTL; domctl.cmd = XEN_DOMCTL_gethvmcontext; domctl.domain = (domid_t)domid; - set_xen_guest_handle(domctl.u.hvmcontext.ctxt, hvm_ctxt); + domctl.u.hvmcontext.size = size; + set_xen_guest_handle(domctl.u.hvmcontext.buffer, ctxt_buf); - if ( (rc = mlock(hvm_ctxt, sizeof(*hvm_ctxt))) != 0 ) - return rc; + if ( (ret = lock_pages(ctxt_buf, size)) != 0 ) + return ret; - rc = do_domctl(xc_handle, &domctl); + ret = do_domctl(xc_handle, &domctl); - safe_munlock(hvm_ctxt, sizeof(*hvm_ctxt)); + unlock_pages(ctxt_buf, size); - return rc; + return (ret < 0 ? -1 : domctl.u.hvmcontext.size); } /* set info to hvm guest for restore */ int xc_domain_hvm_setcontext(int xc_handle, uint32_t domid, - hvm_domain_context_t *hvm_ctxt) + uint8_t *ctxt_buf, + uint32_t size) { - int rc; + int ret; DECLARE_DOMCTL; domctl.cmd = XEN_DOMCTL_sethvmcontext; domctl.domain = domid; - set_xen_guest_handle(domctl.u.hvmcontext.ctxt, hvm_ctxt); + domctl.u.hvmcontext.size = size; + set_xen_guest_handle(domctl.u.hvmcontext.buffer, ctxt_buf); - if ( (rc = mlock(hvm_ctxt, sizeof(*hvm_ctxt))) != 0 ) - return rc; + if ( (ret = lock_pages(ctxt_buf, size)) != 0 ) + return ret; - rc = do_domctl(xc_handle, &domctl); + ret = do_domctl(xc_handle, &domctl); - safe_munlock(hvm_ctxt, sizeof(*hvm_ctxt)); + unlock_pages(ctxt_buf, size); - return rc; + return ret; } int xc_vcpu_getcontext(int xc_handle, diff --git a/tools/libxc/xc_hvm_restore.c b/tools/libxc/xc_hvm_restore.c index b2b9999fea..6622b49f79 100644 --- a/tools/libxc/xc_hvm_restore.c +++ b/tools/libxc/xc_hvm_restore.c @@ -87,7 +87,7 @@ int xc_hvm_restore(int xc_handle, int io_fd, xc_dominfo_t info; unsigned int rc = 1, n, i; uint32_t rec_len, nr_vcpus; - hvm_domain_context_t hvm_ctxt; + uint8_t *hvm_buf = NULL; unsigned long long v_end, memsize; unsigned long shared_page_nr; @@ -128,8 +128,7 @@ int xc_hvm_restore(int xc_handle, int io_fd, } - p2m = malloc(max_pfn * sizeof(xen_pfn_t)); - + p2m = malloc(max_pfn * sizeof(xen_pfn_t)); if (p2m == NULL) { ERROR("memory alloc failed"); errno = ENOMEM; @@ -297,18 +296,21 @@ int xc_hvm_restore(int xc_handle, int io_fd, ERROR("error read hvm context size!\n"); goto out; } - if (rec_len != sizeof(hvm_ctxt)) { - ERROR("hvm context size dismatch!\n"); + + hvm_buf = malloc(rec_len); + if (hvm_buf == NULL) { + ERROR("memory alloc for hvm context buffer failed"); + errno = ENOMEM; goto out; } - if (!read_exact(io_fd, &hvm_ctxt, sizeof(hvm_ctxt))) { - ERROR("error read hvm context!\n"); + if (!read_exact(io_fd, hvm_buf, rec_len)) { + ERROR("error read hvm buffer!\n"); goto out; } - if (( rc = xc_domain_hvm_setcontext(xc_handle, dom, &hvm_ctxt))) { - ERROR("error set hvm context!\n"); + if (( rc = xc_domain_hvm_setcontext(xc_handle, dom, hvm_buf, rec_len))) { + ERROR("error set hvm buffer!\n"); goto out; } @@ -361,6 +363,7 @@ int xc_hvm_restore(int xc_handle, int io_fd, if ( (rc != 0) && (dom != 0) ) xc_domain_destroy(xc_handle, dom); free(p2m); + free(hvm_buf); DPRINTF("Restore exit with rc=%d\n", rc); diff --git a/tools/libxc/xc_hvm_save.c b/tools/libxc/xc_hvm_save.c index 3d08a509d9..d9cca58d07 100644 --- a/tools/libxc/xc_hvm_save.c +++ b/tools/libxc/xc_hvm_save.c @@ -33,6 +33,12 @@ #include "xg_save_restore.h" /* + * Size of a buffer big enough to take the HVM state of a domain. + * Ought to calculate this a bit more carefully, or maybe ask Xen. + */ +#define HVM_CTXT_SIZE 8192 + +/* ** Default values for important tuning parameters. Can override by passing ** non-zero replacement values to xc_hvm_save(). ** @@ -279,8 +285,8 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, unsigned long *pfn_type = NULL; unsigned long *pfn_batch = NULL; - /* A copy of hvm domain context */ - hvm_domain_context_t hvm_ctxt; + /* A copy of hvm domain context buffer*/ + uint8_t *hvm_buf = NULL; /* Live mapping of shared info structure */ shared_info_t *live_shinfo = NULL; @@ -423,8 +429,12 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, to_send = malloc(BITMAP_SIZE); to_skip = malloc(BITMAP_SIZE); - if (!to_send ||!to_skip) { - ERROR("Couldn't allocate to_send array"); + page_array = (unsigned long *) malloc( sizeof(unsigned long) * max_pfn); + + hvm_buf = malloc(HVM_CTXT_SIZE); + + if (!to_send ||!to_skip ||!page_array ||!hvm_buf ) { + ERROR("Couldn't allocate memory"); goto out; } @@ -444,11 +454,6 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, analysis_phase(xc_handle, dom, max_pfn, to_skip, 0); /* get all the HVM domain pfns */ - if ( (page_array = (unsigned long *) malloc (sizeof(unsigned long) * max_pfn)) == NULL) { - ERROR("HVM:malloc fail!\n"); - goto out; - } - for ( i = 0; i < max_pfn; i++) page_array[i] = i; @@ -655,24 +660,18 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, goto out; } - /* save hvm hypervisor state including pic/pit/shpage */ - if (mlock(&hvm_ctxt, sizeof(hvm_ctxt))) { - ERROR("Unable to mlock ctxt"); - return 1; - } - - if (xc_domain_hvm_getcontext(xc_handle, dom, &hvm_ctxt)){ - ERROR("HVM:Could not get hvm context"); + if ( (rec_size = xc_domain_hvm_getcontext(xc_handle, dom, hvm_buf, + HVM_CTXT_SIZE)) == -1) { + ERROR("HVM:Could not get hvm buffer"); goto out; } - rec_size = sizeof(hvm_ctxt); if (!write_exact(io_fd, &rec_size, sizeof(uint32_t))) { - ERROR("error write hvm ctxt size"); + ERROR("error write hvm buffer size"); goto out; } - if ( !write_exact(io_fd, &hvm_ctxt, sizeof(hvm_ctxt)) ) { + if ( !write_exact(io_fd, hvm_buf, rec_size) ) { ERROR("write HVM info failed!\n"); } @@ -722,6 +721,7 @@ int xc_hvm_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters, } } + free(hvm_buf); free(page_array); free(pfn_type); diff --git a/tools/libxc/xc_linux_save.c b/tools/libxc/xc_linux_save.c index de1c605002..0d8f045951 100644 --- a/tools/libxc/xc_linux_save.c +++ b/tools/libxc/xc_linux_save.c @@ -536,8 +536,6 @@ static int canonicalize_pagetable(unsigned long type, unsigned long pfn, if (!MFN_IS_IN_PSEUDOPHYS_MAP(mfn)) { /* This will happen if the type info is stale which is quite feasible under live migration */ - DPRINTF("PT Race: [%08lx,%d] pte=%llx, mfn=%08lx\n", - type, i, (unsigned long long)pte, mfn); pfn = 0; /* zap it - we'll retransmit this page later */ race = 1; /* inform the caller of race; fatal if !live */ } else diff --git a/tools/libxc/xenctrl.h b/tools/libxc/xenctrl.h index 26cd638db5..14704e2e92 100644 --- a/tools/libxc/xenctrl.h +++ b/tools/libxc/xenctrl.h @@ -328,13 +328,15 @@ int xc_domain_getinfolist(int xc_handle, * This function returns information about the context of a hvm domain * @parm xc_handle a handle to an open hypervisor interface * @parm domid the domain to get information from - * @parm hvm_ctxt a pointer to a structure to store the execution context of the - * hvm domain + * @parm ctxt_buf a pointer to a structure to store the execution context of + * the hvm domain + * @parm size the size of ctxt_buf in bytes * @return 0 on success, -1 on failure */ int xc_domain_hvm_getcontext(int xc_handle, uint32_t domid, - hvm_domain_context_t *hvm_ctxt); + uint8_t *ctxt_buf, + uint32_t size); /** * This function will set the context for hvm domain @@ -342,11 +344,13 @@ int xc_domain_hvm_getcontext(int xc_handle, * @parm xc_handle a handle to an open hypervisor interface * @parm domid the domain to set the hvm domain context for * @parm hvm_ctxt pointer to the the hvm context with the values to set + * @parm size the size of hvm_ctxt in bytes * @return 0 on success, -1 on failure */ int xc_domain_hvm_setcontext(int xc_handle, uint32_t domid, - hvm_domain_context_t *hvm_ctxt); + uint8_t *hvm_ctxt, + uint32_t size); /** * This function returns information about the execution context of a diff --git a/tools/libxen/Makefile b/tools/libxen/Makefile index c72206442a..e2eeda74d8 100644 --- a/tools/libxen/Makefile +++ b/tools/libxen/Makefile @@ -51,6 +51,9 @@ libxenapi.a: $(LIBXENAPI_OBJS) test/test_bindings: test/test_bindings.o libxenapi.so $(CC) $(LDFLAGS) -o $@ $< -L . -lxenapi +test/test_hvm_bindings: test/test_hvm_bindings.o libxenapi.so + $(CC) $(LDFLAGS) -o $@ $< -L . -lxenapi + .PHONY: install install: all diff --git a/tools/libxen/include/xen_host.h b/tools/libxen/include/xen_host.h index e64390b89f..26ca29d592 100644 --- a/tools/libxen/include/xen_host.h +++ b/tools/libxen/include/xen_host.h @@ -394,6 +394,13 @@ xen_host_reboot(xen_session *session, xen_host host); /** + * Get the host xen dmesg. + */ +extern bool +xen_host_dmesg(xen_session *session, char **result, xen_host host); + + +/** * Return a list of all the hosts known to the system. */ extern bool diff --git a/tools/libxen/include/xen_vdi.h b/tools/libxen/include/xen_vdi.h index d72eceb001..8533df31a8 100644 --- a/tools/libxen/include/xen_vdi.h +++ b/tools/libxen/include/xen_vdi.h @@ -74,6 +74,7 @@ typedef struct xen_vdi_record int64_t virtual_size; int64_t physical_utilisation; int64_t sector_size; + char *location; enum xen_vdi_type type; bool sharable; bool read_only; diff --git a/tools/libxen/include/xen_vm.h b/tools/libxen/include/xen_vm.h index 7a56ba482e..3c23784cf5 100644 --- a/tools/libxen/include/xen_vm.h +++ b/tools/libxen/include/xen_vm.h @@ -42,9 +42,9 @@ * A virtual machine (or 'guest'). * * VM booting is controlled by setting one of the two mutually exclusive - * groups: "PV", and "HVM". If HVM.boot is the empty string, then paravirtual - * domain building and booting will be used; otherwise the VM will be loaded - * as an HVM domain, and booted using an emulated BIOS. + * groups: "PV", and "HVM". If HVM.boot_policy is the empty string, then + * paravirtual domain building and booting will be used; otherwise the VM will + * be loaded as an HVM domain, and booted using an emulated BIOS. * * When paravirtual booting is in use, the PV/bootloader field indicates the * bootloader to use. It may be "pygrub", in which case the platform's @@ -69,7 +69,10 @@ * PV/bootloader and PV/kernel are empty, then the behaviour is as if * PV/bootloader was specified as "pygrub". * - * When using HVM booting, HVM/boot specifies the order of the boot devices. + * When using HVM booting, HVM/boot_policy and HVM/boot_params specify the + * boot handling. Only one policy is currently defined: "BIOS order". In + * this case, HVM/boot_params should contain one key-value pair "order" = "N" + * where N is the string that will be passed to QEMU.. */ @@ -136,7 +139,8 @@ typedef struct xen_vm_record char *pv_ramdisk; char *pv_args; char *pv_bootloader_args; - char *hvm_boot; + char *hvm_boot_policy; + xen_string_string_map *hvm_boot_params; bool platform_std_vga; char *platform_serial; bool platform_localtime; @@ -490,10 +494,17 @@ xen_vm_get_pv_bootloader_args(xen_session *session, char **result, xen_vm vm); /** - * Get the HVM/boot field of the given VM. + * Get the HVM/boot_policy field of the given VM. */ extern bool -xen_vm_get_hvm_boot(xen_session *session, char **result, xen_vm vm); +xen_vm_get_hvm_boot_policy(xen_session *session, char **result, xen_vm vm); + + +/** + * Get the HVM/boot_params field of the given VM. + */ +extern bool +xen_vm_get_hvm_boot_params(xen_session *session, xen_string_string_map **result, xen_vm vm); /** @@ -731,10 +742,34 @@ xen_vm_set_pv_bootloader_args(xen_session *session, xen_vm vm, char *bootloader_ /** - * Set the HVM/boot field of the given VM. + * Set the HVM/boot_policy field of the given VM. + */ +extern bool +xen_vm_set_hvm_boot_policy(xen_session *session, xen_vm vm, char *boot_policy); + + +/** + * Set the HVM/boot_params field of the given VM. + */ +extern bool +xen_vm_set_hvm_boot_params(xen_session *session, xen_vm vm, xen_string_string_map *boot_params); + + +/** + * Add the given key-value pair to the HVM/boot_params field of the + * given VM. + */ +extern bool +xen_vm_add_to_hvm_boot_params(xen_session *session, xen_vm vm, char *key, char *value); + + +/** + * Remove the given key and its corresponding value from the + * HVM/boot_params field of the given VM. If the key is not in that Map, then + * do nothing. */ extern bool -xen_vm_set_hvm_boot(xen_session *session, xen_vm vm, char *boot); +xen_vm_remove_from_hvm_boot_params(xen_session *session, xen_vm vm, char *key); /** diff --git a/tools/libxen/include/xen_vm_power_state.h b/tools/libxen/include/xen_vm_power_state.h index 3e805ed671..c5404b89cf 100644 --- a/tools/libxen/include/xen_vm_power_state.h +++ b/tools/libxen/include/xen_vm_power_state.h @@ -46,11 +46,6 @@ enum xen_vm_power_state XEN_VM_POWER_STATE_SUSPENDED, /** - * Shutting Down - */ - XEN_VM_POWER_STATE_SHUTTINGDOWN, - - /** * Some other unknown state */ XEN_VM_POWER_STATE_UNKNOWN diff --git a/tools/libxen/src/xen_common.c b/tools/libxen/src/xen_common.c index 9834565ff0..8c5feeb33f 100644 --- a/tools/libxen/src/xen_common.c +++ b/tools/libxen/src/xen_common.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 XenSource, Inc. + * Copyright (c) 2006-2007 XenSource, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -86,6 +86,8 @@ static xmlNode * add_param_struct(xmlNode *); static xmlNode * add_struct_array(xmlNode *, const char *); +static xmlNode * +add_nested_struct(xmlNode *, const char *); static void add_struct_member(xmlNode *, const char *, const char *, const char *); static void @@ -107,6 +109,9 @@ parse_structmap_value(xen_session *, xmlNode *, const abstract_type *, static size_t size_of_member(const abstract_type *); +static const char * +get_val_as_string(const struct abstract_type *, void *, char *); + void xen_init(void) @@ -1174,37 +1179,12 @@ add_struct_value(const struct abstract_type *type, void *value, switch (type->typename) { case REF: - { - arbitrary_record_opt *val = *(arbitrary_record_opt **)value; - if (val != NULL) - { - if (val->is_record) - { - adder(node, key, "string", val->u.record->handle); - } - else - { - adder(node, key, "string", val->u.handle); - } - } - } - break; - case STRING: - { - char *val = *(char **)value; - if (val != NULL) - { - adder(node, key, "string", val); - } - } - break; - case INT: + case ENUM: { - int64_t val = *(int64_t *)value; - snprintf(buf, sizeof(buf), "%"PRId64, val); - adder(node, key, "string", buf); + const char *val_as_string = get_val_as_string(type, value, buf); + adder(node, key, "string", val_as_string); } break; @@ -1223,13 +1203,6 @@ add_struct_value(const struct abstract_type *type, void *value, } break; - case ENUM: - { - int val = *(int *)value; - adder(node, key, "string", type->enum_marshaller(val)); - } - break; - case SET: { const struct abstract_type *member_type = type->child; @@ -1251,12 +1224,95 @@ add_struct_value(const struct abstract_type *type, void *value, break; case STRUCT: - case MAP: { + assert(false); /* XXX Nested structures aren't supported yet, but fortunately we don't need them, because we don't have any "deep create" calls. This will need to be - fixed. We don't need maps either. */ + fixed. */ + } + break; + + case MAP: + { + size_t member_size = type->struct_size; + const struct abstract_type *l_type = type->members[0].type; + const struct abstract_type *r_type = type->members[1].type; + int l_offset = type->members[0].offset; + int r_offset = type->members[1].offset; + + arbitrary_map *map_val = *(arbitrary_map **)value; + + if (map_val != NULL) + { + xmlNode *struct_node = add_nested_struct(node, key); + + for (size_t i = 0; i < map_val->size; i++) + { + void *contents = (void *)map_val->contents; + void *l_value = contents + (i * member_size) + l_offset; + void *r_value = contents + (i * member_size) + r_offset; + + const char *l_value_as_string = + get_val_as_string(l_type, l_value, buf); + + add_struct_value(r_type, r_value, add_struct_member, + l_value_as_string, struct_node); + } + } + } + break; + + default: + assert(false); + } +} + + +static const char * +get_val_as_string(const struct abstract_type *type, void *value, char *buf) +{ + switch (type->typename) + { + case REF: + { + arbitrary_record_opt *val = *(arbitrary_record_opt **)value; + if (val != NULL) + { + if (val->is_record) + { + return val->u.record->handle; + } + else + { + return val->u.handle; + } + } + else + { + return NULL; + } + } + break; + + case STRING: + { + return *(char **)value; + } + break; + + case INT: + { + int64_t val = *(int64_t *)value; + snprintf(buf, sizeof(buf), "%"PRId64, val); + return buf; + } + break; + + case ENUM: + { + int val = *(int *)value; + return type->enum_marshaller(val); } break; @@ -1331,7 +1387,19 @@ add_struct_array(xmlNode *struct_node, const char *name) xmlNode *array_node = add_container(value_node, "array"); return add_container(array_node, "data"); +} + + +static xmlNode * +add_nested_struct(xmlNode *struct_node, const char *name) +{ + xmlNode *member_node = add_container(struct_node, "member"); + + xmlNewChild(member_node, NULL, BAD_CAST "name", BAD_CAST name); + + xmlNode *value_node = add_container(member_node, "value"); + return add_container(value_node, "struct"); } diff --git a/tools/libxen/src/xen_host.c b/tools/libxen/src/xen_host.c index 7968b96994..4a79daa90f 100644 --- a/tools/libxen/src/xen_host.c +++ b/tools/libxen/src/xen_host.c @@ -632,6 +632,23 @@ xen_host_reboot(xen_session *session, xen_host host) bool +xen_host_dmesg(xen_session *session, char **result, xen_host host) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = host } + }; + + abstract_type result_type = abstract_type_string; + + *result = NULL; + XEN_CALL_("host.dmesg"); + return session->ok; +} + + +bool xen_host_get_all(xen_session *session, struct xen_host_set **result) { diff --git a/tools/libxen/src/xen_int_float_map.c b/tools/libxen/src/xen_int_float_map.c index edfcb21ac2..33ff29de62 100644 --- a/tools/libxen/src/xen_int_float_map.c +++ b/tools/libxen/src/xen_int_float_map.c @@ -25,8 +25,10 @@ xen_int_float_map * xen_int_float_map_alloc(size_t size) { - return calloc(1, sizeof(xen_int_float_map) + - size * sizeof(struct xen_int_float_map_contents)); + xen_int_float_map *result = calloc(1, sizeof(xen_int_float_map) + + size * sizeof(struct xen_int_float_map_contents)); + result->size = size; + return result; } diff --git a/tools/libxen/src/xen_string_string_map.c b/tools/libxen/src/xen_string_string_map.c index 34f5ec4d70..b07acfbf7c 100644 --- a/tools/libxen/src/xen_string_string_map.c +++ b/tools/libxen/src/xen_string_string_map.c @@ -25,8 +25,10 @@ xen_string_string_map * xen_string_string_map_alloc(size_t size) { - return calloc(1, sizeof(xen_string_string_map) + - size * sizeof(struct xen_string_string_map_contents)); + xen_string_string_map *result = calloc(1, sizeof(xen_string_string_map) + + size * sizeof(struct xen_string_string_map_contents)); + result->size = size; + return result; } diff --git a/tools/libxen/src/xen_vdi.c b/tools/libxen/src/xen_vdi.c index b2eddbcafb..005425ebc1 100644 --- a/tools/libxen/src/xen_vdi.c +++ b/tools/libxen/src/xen_vdi.c @@ -67,6 +67,9 @@ static const struct_member xen_vdi_record_struct_members[] = { .key = "sector_size", .type = &abstract_type_int, .offset = offsetof(xen_vdi_record, sector_size) }, + { .key = "location", + .type = &abstract_type_string, + .offset = offsetof(xen_vdi_record, location) }, { .key = "type", .type = &xen_vdi_type_abstract_type_, .offset = offsetof(xen_vdi_record, type) }, diff --git a/tools/libxen/src/xen_vm.c b/tools/libxen/src/xen_vm.c index 6cbc3670b0..e3f82575bd 100644 --- a/tools/libxen/src/xen_vm.c +++ b/tools/libxen/src/xen_vm.c @@ -145,9 +145,12 @@ static const struct_member xen_vm_record_struct_members[] = { .key = "PV_bootloader_args", .type = &abstract_type_string, .offset = offsetof(xen_vm_record, pv_bootloader_args) }, - { .key = "HVM_boot", + { .key = "HVM_boot_policy", .type = &abstract_type_string, - .offset = offsetof(xen_vm_record, hvm_boot) }, + .offset = offsetof(xen_vm_record, hvm_boot_policy) }, + { .key = "HVM_boot_params", + .type = &abstract_type_string_string_map, + .offset = offsetof(xen_vm_record, hvm_boot_params) }, { .key = "platform_std_VGA", .type = &abstract_type_bool, .offset = offsetof(xen_vm_record, platform_std_vga) }, @@ -216,7 +219,8 @@ xen_vm_record_free(xen_vm_record *record) free(record->pv_ramdisk); free(record->pv_args); free(record->pv_bootloader_args); - free(record->hvm_boot); + free(record->hvm_boot_policy); + xen_string_string_map_free(record->hvm_boot_params); free(record->platform_serial); free(record->pci_bus); xen_string_string_map_free(record->tools_version); @@ -824,7 +828,7 @@ xen_vm_get_pv_bootloader_args(xen_session *session, char **result, xen_vm vm) bool -xen_vm_get_hvm_boot(xen_session *session, char **result, xen_vm vm) +xen_vm_get_hvm_boot_policy(xen_session *session, char **result, xen_vm vm) { abstract_value param_values[] = { @@ -835,7 +839,24 @@ xen_vm_get_hvm_boot(xen_session *session, char **result, xen_vm vm) abstract_type result_type = abstract_type_string; *result = NULL; - XEN_CALL_("VM.get_HVM_boot"); + XEN_CALL_("VM.get_HVM_boot_policy"); + return session->ok; +} + + +bool +xen_vm_get_hvm_boot_params(xen_session *session, xen_string_string_map **result, xen_vm vm) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = vm } + }; + + abstract_type result_type = abstract_type_string_string_map; + + *result = NULL; + XEN_CALL_("VM.get_HVM_boot_params"); return session->ok; } @@ -1376,17 +1397,67 @@ xen_vm_set_pv_bootloader_args(xen_session *session, xen_vm vm, char *bootloader_ bool -xen_vm_set_hvm_boot(xen_session *session, xen_vm vm, char *boot) +xen_vm_set_hvm_boot_policy(xen_session *session, xen_vm vm, char *boot_policy) { abstract_value param_values[] = { { .type = &abstract_type_string, .u.string_val = vm }, { .type = &abstract_type_string, - .u.string_val = boot } + .u.string_val = boot_policy } + }; + + xen_call_(session, "VM.set_HVM_boot_policy", param_values, 2, NULL, NULL); + return session->ok; +} + + +bool +xen_vm_set_hvm_boot_params(xen_session *session, xen_vm vm, xen_string_string_map *boot_params) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = vm }, + { .type = &abstract_type_string_string_map, + .u.set_val = (arbitrary_set *)boot_params } + }; + + xen_call_(session, "VM.set_HVM_boot_params", param_values, 2, NULL, NULL); + return session->ok; +} + + +bool +xen_vm_add_to_hvm_boot_params(xen_session *session, xen_vm vm, char *key, char *value) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = vm }, + { .type = &abstract_type_string, + .u.string_val = key }, + { .type = &abstract_type_string, + .u.string_val = value } + }; + + xen_call_(session, "VM.add_to_HVM_boot_params", param_values, 3, NULL, NULL); + return session->ok; +} + + +bool +xen_vm_remove_from_hvm_boot_params(xen_session *session, xen_vm vm, char *key) +{ + abstract_value param_values[] = + { + { .type = &abstract_type_string, + .u.string_val = vm }, + { .type = &abstract_type_string, + .u.string_val = key } }; - xen_call_(session, "VM.set_HVM_boot", param_values, 2, NULL, NULL); + xen_call_(session, "VM.remove_from_HVM_boot_params", param_values, 2, NULL, NULL); return session->ok; } diff --git a/tools/libxen/src/xen_vm_power_state.c b/tools/libxen/src/xen_vm_power_state.c index a9e2545c47..9f96f34f9b 100644 --- a/tools/libxen/src/xen_vm_power_state.c +++ b/tools/libxen/src/xen_vm_power_state.c @@ -32,7 +32,6 @@ static const char *lookup_table[] = "Paused", "Running", "Suspended", - "ShuttingDown", "Unknown" }; diff --git a/tools/libxen/test/test_bindings.c b/tools/libxen/test/test_bindings.c index 88fce8b35b..c1df98dcea 100644 --- a/tools/libxen/test/test_bindings.c +++ b/tools/libxen/test/test_bindings.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006 XenSource, Inc. + * Copyright (c) 2006-2007 XenSource, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -29,6 +29,7 @@ #include "xen_sr.h" #include "xen_vbd.h" #include "xen_vdi.h" +#include "xen_console.h" #include "xen_vm.h" @@ -58,7 +59,7 @@ typedef struct } xen_comms; -static xen_vm create_new_vm(xen_session *session); +static xen_vm create_new_vm(xen_session *session, bool hvm); static void print_vm_power_state(xen_session *session, xen_vm vm); @@ -205,6 +206,20 @@ int main(int argc, char **argv) return 1; } + char *dmesg; + if (!xen_host_dmesg(session, &dmesg, host)) + { + print_error(session); + xen_string_string_map_free(versions); + xen_host_free(host); + xen_vm_record_free(vm_record); + xen_uuid_bytes_free(vm_uuid_bytes); + xen_uuid_free(vm_uuid); + xen_vm_free(vm); + CLEANUP; + return 1; + } + printf("%s.\n", vm_uuid); fprintf(stderr, "In bytes, the VM UUID is "); @@ -222,6 +237,8 @@ int main(int argc, char **argv) versions->contents[i].val); } + printf("Host dmesg follows:\n%s\n\n", dmesg); + printf("%s.\n", vm_record->uuid); printf("Resident on %s.\n", (char *)vm_record->resident_on->u.handle); @@ -243,9 +260,10 @@ int main(int argc, char **argv) xen_host_free(host); xen_string_string_map_free(versions); + free(dmesg); - xen_vm new_vm = create_new_vm(session); + xen_vm new_vm = create_new_vm(session, true); if (!session->ok) { /* Error has been logged, just clean up. */ @@ -275,13 +293,28 @@ int main(int argc, char **argv) * allocation patterns can be used, as long as the allocation and free are * paired correctly. */ -static xen_vm create_new_vm(xen_session *session) +static xen_vm create_new_vm(xen_session *session, bool hvm) { xen_string_string_map *vcpus_params = xen_string_string_map_alloc(1); + vcpus_params->contents[0].key = strdup("weight"); + vcpus_params->contents[0].val = strdup("300"); + + xen_string_string_map *hvm_boot_params; + if (hvm) + { + hvm_boot_params = xen_string_string_map_alloc(1); + hvm_boot_params->contents[0].key = strdup("order"); + hvm_boot_params->contents[0].val = strdup("cd"); + } + else + { + hvm_boot_params = NULL; + } + xen_vm_record vm_record = { - .name_label = "NewVM", - .name_description = "New VM Description", + .name_label = hvm ? "NewHVM" : "NewPV", + .name_description = hvm ? "New HVM VM" : "New PV VM", .user_version = 1, .is_a_template = false, .memory_static_max = 256, @@ -294,18 +327,18 @@ static xen_vm create_new_vm(xen_session *session) .actions_after_shutdown = XEN_ON_NORMAL_EXIT_DESTROY, .actions_after_reboot = XEN_ON_NORMAL_EXIT_RESTART, .actions_after_crash = XEN_ON_CRASH_BEHAVIOUR_PRESERVE, - .hvm_boot = "", - .pv_bootloader = "pygrub", - .pv_kernel = "/boot/vmlinuz-2.6.16.33-xen", - .pv_ramdisk = "", - .pv_args = "", - .pv_bootloader_args = "" + .hvm_boot_policy = hvm ? "BIOS order" : NULL, + .hvm_boot_params = hvm ? hvm_boot_params : NULL, + .pv_bootloader = hvm ? NULL : "pygrub", + .pv_kernel = hvm ? NULL : "/boot/vmlinuz-2.6.16.33-xen", }; - xen_vm vm; xen_vm_create(session, &vm, &vm_record); + xen_string_string_map_free(vcpus_params); + xen_string_string_map_free(hvm_boot_params); + if (!session->ok) { fprintf(stderr, "VM creation failed.\n"); @@ -368,7 +401,8 @@ static xen_vm create_new_vm(xen_session *session) .vm = &vm_record_opt, .vdi = &vdi0_record_opt, .device = "xvda1", - .mode = XEN_VBD_MODE_RW + .mode = XEN_VBD_MODE_RW, + .bootable = 1, }; xen_vbd vbd0; @@ -383,13 +417,38 @@ static xen_vm create_new_vm(xen_session *session) return NULL; } + xen_console vnc_console = NULL; + if (hvm) { + xen_console_record vnc_console_record = + { + .protocol = XEN_CONSOLE_PROTOCOL_RFB, + .vm = &vm_record_opt, + }; + + if (!xen_console_create(session, &vnc_console, &vnc_console_record)) + { + fprintf(stderr, "VNC console creation failed.\n"); + print_error(session); + + xen_vbd_free(vbd0); + xen_vdi_free(vdi0); + xen_sr_set_free(srs); + xen_vm_free(vm); + return NULL; + } + } + char *vm_uuid; char *vdi0_uuid; char *vbd0_uuid; + char *vnc_uuid = NULL; xen_vm_get_uuid(session, &vm_uuid, vm); xen_vdi_get_uuid(session, &vdi0_uuid, vdi0); xen_vbd_get_uuid(session, &vbd0_uuid, vbd0); + if (hvm) { + xen_console_get_uuid(session, &vnc_uuid, vnc_console); + } if (!session->ok) { @@ -399,22 +458,35 @@ static xen_vm create_new_vm(xen_session *session) xen_uuid_free(vm_uuid); xen_uuid_free(vdi0_uuid); xen_uuid_free(vbd0_uuid); + xen_uuid_free(vnc_uuid); xen_vbd_free(vbd0); xen_vdi_free(vdi0); + xen_console_free(vnc_console); xen_sr_set_free(srs); xen_vm_free(vm); return NULL; } - fprintf(stderr, - "Created a new VM, with UUID %s, VDI UUID %s, and VBD UUID %s.\n", - vm_uuid, vdi0_uuid, vbd0_uuid); + if (hvm) { + fprintf(stderr, + "Created a new HVM VM, with UUID %s, VDI UUID %s, VBD " + "UUID %s, and VNC console UUID %s.\n", + vm_uuid, vdi0_uuid, vbd0_uuid, vnc_uuid); + } + else { + fprintf(stderr, + "Created a new PV VM, with UUID %s, VDI UUID %s, and VBD " + "UUID %s.\n", + vm_uuid, vdi0_uuid, vbd0_uuid); + } xen_uuid_free(vm_uuid); xen_uuid_free(vdi0_uuid); xen_uuid_free(vbd0_uuid); + xen_uuid_free(vnc_uuid); xen_vbd_free(vbd0); xen_vdi_free(vdi0); + xen_console_free(vnc_console); xen_sr_set_free(srs); return vm; diff --git a/tools/libxen/test/test_hvm_bindings.c b/tools/libxen/test/test_hvm_bindings.c new file mode 100644 index 0000000000..8bc8e7c347 --- /dev/null +++ b/tools/libxen/test/test_hvm_bindings.c @@ -0,0 +1,445 @@ +/* + * Copyright (c) 2006 XenSource, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#define _GNU_SOURCE +#include <inttypes.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include <libxml/parser.h> +#include <curl/curl.h> + +#include "xen_host.h" +#include "xen_sr.h" +#include "xen_vbd.h" +#include "xen_vdi.h" +#include "xen_vm.h" + + +static void usage() +{ + fprintf(stderr, +"Usage:\n" +"\n" +" test_bindings <url> <username> <password>\n" +"\n" +"where\n" +" <url> is a fragment of the server's URL, e.g. localhost:8005/RPC2;\n" +" <username> is the username to use at the server; and\n" +" <password> is the password.\n"); + + exit(EXIT_FAILURE); +} + + +static char *url; + + +typedef struct +{ + xen_result_func func; + void *handle; +} xen_comms; + + +static xen_vm create_new_vm(xen_session *session); +static void print_vm_power_state(xen_session *session, xen_vm vm); + + +static size_t +write_func(void *ptr, size_t size, size_t nmemb, xen_comms *comms) +{ + size_t n = size * nmemb; + return comms->func(ptr, n, comms->handle) ? n : 0; +} + + +static int +call_func(const void *data, size_t len, void *user_handle, + void *result_handle, xen_result_func result_func) +{ + (void)user_handle; + + CURL *curl = curl_easy_init(); + if (!curl) { + return -1; + } + + xen_comms comms = { + .func = result_func, + .handle = result_handle + }; + + curl_easy_setopt(curl, CURLOPT_URL, url); + curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1); + curl_easy_setopt(curl, CURLOPT_MUTE, 1); + curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &write_func); + curl_easy_setopt(curl, CURLOPT_WRITEDATA, &comms); + curl_easy_setopt(curl, CURLOPT_POST, 1); + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data); + curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, len); + + CURLcode result = curl_easy_perform(curl); + + curl_easy_cleanup(curl); + + return result; +} + + +static void print_error(xen_session *session) +{ + fprintf(stderr, "Error: %d", session->error_description_count); + for (int i = 0; i < session->error_description_count; i++) + { + fprintf(stderr, "%s ", session->error_description[i]); + } + fprintf(stderr, "\n"); +} + + +int main(int argc, char **argv) +{ + if (argc != 4) + { + usage(); + } + + url = argv[1]; + char *username = argv[2]; + char *password = argv[3]; + + xmlInitParser(); + xen_init(); + curl_global_init(CURL_GLOBAL_ALL); + +#define CLEANUP \ + do { \ + xen_session_logout(session); \ + curl_global_cleanup(); \ + xen_fini(); \ + xmlCleanupParser(); \ + } while(0) \ + + + xen_session *session = + xen_session_login_with_password(call_func, NULL, username, password); + + xen_vm vm; + if (!xen_vm_get_by_uuid(session, &vm, + "00000000-0000-0000-0000-000000000000")) + { + print_error(session); + CLEANUP; + return 1; + } + + char *vm_uuid; + if (!xen_vm_get_uuid(session, &vm_uuid, vm)) + { + print_error(session); + xen_vm_free(vm); + CLEANUP; + return 1; + } + + char *vm_uuid_bytes; + if (!xen_uuid_string_to_bytes(vm_uuid, &vm_uuid_bytes)) + { + fprintf(stderr, "xen_uuid_string_to_bytes failed.\n"); + xen_uuid_free(vm_uuid); + xen_vm_free(vm); + CLEANUP; + return 1; + } + + xen_vm_record *vm_record; + if (!xen_vm_get_record(session, &vm_record, vm)) + { + print_error(session); + xen_uuid_bytes_free(vm_uuid_bytes); + xen_uuid_free(vm_uuid); + xen_vm_free(vm); + CLEANUP; + return 1; + } + + xen_host host; + if (!xen_session_get_this_host(session, &host)) + { + print_error(session); + xen_vm_record_free(vm_record); + xen_uuid_bytes_free(vm_uuid_bytes); + xen_uuid_free(vm_uuid); + xen_vm_free(vm); + CLEANUP; + return 1; + } + + xen_string_string_map *versions; + if (!xen_host_get_software_version(session, &versions, host)) + { + print_error(session); + xen_host_free(host); + xen_vm_record_free(vm_record); + xen_uuid_bytes_free(vm_uuid_bytes); + xen_uuid_free(vm_uuid); + xen_vm_free(vm); + CLEANUP; + return 1; + } + + printf("%s.\n", vm_uuid); + + fprintf(stderr, "In bytes, the VM UUID is "); + for (int i = 0; i < 15; i++) + { + fprintf(stderr, "%x, ", (unsigned int)vm_uuid_bytes[i]); + } + fprintf(stderr, "%x.\n", (unsigned int)vm_uuid_bytes[15]); + + printf("%zd.\n", versions->size); + + for (size_t i = 0; i < versions->size; i++) + { + printf("%s -> %s.\n", versions->contents[i].key, + versions->contents[i].val); + } + + printf("%s.\n", vm_record->uuid); + + printf("Resident on %s.\n", (char *)vm_record->resident_on->u.handle); + + printf("%s.\n", xen_vm_power_state_to_string(vm_record->power_state)); + + for (size_t i = 0; i < vm_record->vcpus_utilisation->size; i++) + { + printf("%"PRId64" -> %lf.\n", + vm_record->vcpus_utilisation->contents[i].key, + vm_record->vcpus_utilisation->contents[i].val); + } + + xen_uuid_bytes_free(vm_uuid_bytes); + xen_uuid_free(vm_uuid); + xen_vm_free(vm); + + xen_vm_record_free(vm_record); + + xen_host_free(host); + xen_string_string_map_free(versions); + + + xen_vm new_vm = create_new_vm(session); + if (!session->ok) + { + /* Error has been logged, just clean up. */ + CLEANUP; + return 1; + } + + print_vm_power_state(session, new_vm); + if (!session->ok) + { + /* Error has been logged, just clean up. */ + xen_vm_free(new_vm); + CLEANUP; + return 1; + } + + xen_vm_free(new_vm); + CLEANUP; + + return 0; +} + + +/** + * Creation of a new VM, using the Named Parameters idiom. Allocate the + * xen_vm_record here, but the sets through the library. Either + * allocation patterns can be used, as long as the allocation and free are + * paired correctly. + */ +static xen_vm create_new_vm(xen_session *session) +{ + xen_string_string_map *vcpus_params = xen_string_string_map_alloc(1); + xen_vm_record vm_record = + { + .name_label = "NewHVM", + .name_description = "New HVM Description", + .user_version = 1, + .is_a_template = false, + .memory_static_max = 256, + .memory_dynamic_max = 256, + .memory_dynamic_min = 128, + .memory_static_min = 128, + .vcpus_policy = "credit", + .vcpus_params = vcpus_params, + .vcpus_number = 2, + .actions_after_shutdown = XEN_ON_NORMAL_EXIT_DESTROY, + .actions_after_reboot = XEN_ON_NORMAL_EXIT_RESTART, + .actions_after_crash = XEN_ON_CRASH_BEHAVIOUR_PRESERVE, + .hvm_boot = "cda", + }; + + + xen_vm vm; + xen_vm_create(session, &vm, &vm_record); + + if (!session->ok) + { + fprintf(stderr, "VM creation failed.\n"); + print_error(session); + return NULL; + } + + + /* + * Create a new disk for the new VM. + */ + xen_sr_set *srs; + if (!xen_sr_get_by_name_label(session, &srs, "Local") || + srs->size < 1) + { + fprintf(stderr, "SR lookup failed.\n"); + print_error(session); + xen_vm_free(vm); + return NULL; + } + + xen_sr_record_opt sr_record = + { + .u.handle = srs->contents[0] + }; + xen_vdi_record vdi0_record = + { + .name_label = "MyRootFS", + .name_description = "MyRootFS description", + .sr = &sr_record, + .virtual_size = (1 << 21), // 1GiB / 512 bytes/sector + .sector_size = 512, + .location = "file:/root/gentoo.amd64.hvm.img", + .type = XEN_VDI_TYPE_SYSTEM, + .sharable = false, + .read_only = false + }; + + xen_vdi vdi0; + if (!xen_vdi_create(session, &vdi0, &vdi0_record)) + { + fprintf(stderr, "VDI creation failed.\n"); + print_error(session); + + xen_sr_set_free(srs); + xen_vm_free(vm); + return NULL; + } + + + xen_vm_record_opt vm_record_opt = + { + .u.handle = vm + }; + xen_vdi_record_opt vdi0_record_opt = + { + .u.handle = vdi0 + }; + xen_vbd_record vbd0_record = + { + .vm = &vm_record_opt, + .vdi = &vdi0_record_opt, + .device = "xvda1", + .mode = XEN_VBD_MODE_RW + }; + + xen_vbd vbd0; + if (!xen_vbd_create(session, &vbd0, &vbd0_record)) + { + fprintf(stderr, "VBD creation failed.\n"); + print_error(session); + + xen_vdi_free(vdi0); + xen_sr_set_free(srs); + xen_vm_free(vm); + return NULL; + } + + char *vm_uuid; + char *vdi0_uuid; + char *vbd0_uuid; + + xen_vm_get_uuid(session, &vm_uuid, vm); + xen_vdi_get_uuid(session, &vdi0_uuid, vdi0); + xen_vbd_get_uuid(session, &vbd0_uuid, vbd0); + + if (!session->ok) + { + fprintf(stderr, "get_uuid call failed.\n"); + print_error(session); + + xen_uuid_free(vm_uuid); + xen_uuid_free(vdi0_uuid); + xen_uuid_free(vbd0_uuid); + xen_vbd_free(vbd0); + xen_vdi_free(vdi0); + xen_sr_set_free(srs); + xen_vm_free(vm); + return NULL; + } + + fprintf(stderr, + "Created a new VM, with UUID %s, VDI UUID %s, and VBD UUID %s.\n", + vm_uuid, vdi0_uuid, vbd0_uuid); + + xen_uuid_free(vm_uuid); + xen_uuid_free(vdi0_uuid); + xen_uuid_free(vbd0_uuid); + xen_vbd_free(vbd0); + xen_vdi_free(vdi0); + xen_sr_set_free(srs); + + return vm; +} + + +/** + * Print the power state for the given VM. + */ +static void print_vm_power_state(xen_session *session, xen_vm vm) +{ + char *vm_uuid; + enum xen_vm_power_state power_state; + + if (!xen_vm_get_uuid(session, &vm_uuid, vm)) + { + print_error(session); + return; + } + + if (!xen_vm_get_power_state(session, &power_state, vm)) + { + xen_uuid_free(vm_uuid); + print_error(session); + return; + } + + printf("VM %s power state is %s.\n", vm_uuid, + xen_vm_power_state_to_string(power_state)); + + xen_uuid_free(vm_uuid); +} diff --git a/tools/misc/Makefile b/tools/misc/Makefile index 13c95b56f7..80b52c0063 100644 --- a/tools/misc/Makefile +++ b/tools/misc/Makefile @@ -12,7 +12,7 @@ HDRS = $(wildcard *.h) TARGETS = xenperf xc_shadow INSTALL_BIN = $(TARGETS) xencons -INSTALL_SBIN = netfix xm xen-bugtool xend xenperf +INSTALL_SBIN = netfix xm xen-bugtool xen-python-path xend xenperf .PHONY: all all: build diff --git a/tools/misc/xen-python-path b/tools/misc/xen-python-path new file mode 100644 index 0000000000..03c572b8ef --- /dev/null +++ b/tools/misc/xen-python-path @@ -0,0 +1,41 @@ +#!/usr/bin/env python +# -*- mode: python; -*- +#============================================================================ +# This library is free software; you can redistribute it and/or +# modify it under the terms of version 2.1 of the GNU Lesser General Public +# License as published by the Free Software Foundation. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +#============================================================================ +# Copyright (C) 2007 XenSource Inc. +#============================================================================ + + +# Use the auxbin module in Xend to determine the correct Python path. We +# take the first installed instance of auxbin that we find, and then run it +# to determine the correct path, appending that to sys.path. + +AUXBIN = 'xen/util/auxbin.py' + +import os +import os.path +import sys + +for p in ['python%s' % sys.version[:3], 'python']: + for l in ['/usr/lib64', '/usr/lib']: + d = os.path.join(l, p) + if os.path.exists(os.path.join(d, AUXBIN)): + sys.path.append(d) + import xen.util.auxbin + print os.path.join(xen.util.auxbin.libpath(), p) + sys.exit(0) + +print >>sys.stderr, "Cannot find Xen Python modules." +sys.exit(1) diff --git a/tools/misc/xend b/tools/misc/xend index 0832f84010..860dcbcd25 100644 --- a/tools/misc/xend +++ b/tools/misc/xend @@ -31,23 +31,13 @@ import signal import time import commands +result = commands.getstatusoutput(os.path.join(os.path.dirname(sys.argv[0]), + 'xen-python-path')) +if result[0] != 0: + print >>sys.stderr, result[1] + sys.exit(1) -# Use the auxbin module in Xend to determine the correct Python path. We -# take the first installed instance of auxbin that we find, and then run it -# to determine the correct path, appending that to sys.path. - -AUXBIN = 'xen/util/auxbin.py' - -for p in ['python%s' % sys.version[:3], 'python']: - for l in ['/usr/lib64', '/usr/lib']: - d = os.path.join(l, p) - if os.path.exists(os.path.join(d, AUXBIN)): - sys.path.append(d) - import xen.util.auxbin - libpath = os.path.join(xen.util.auxbin.libpath(), p) - sys.path = sys.path[:-1] - sys.path.append(libpath) - break +sys.path.append(result[1]) from xen.xend.server import SrvDaemon diff --git a/tools/pygrub/src/pygrub b/tools/pygrub/src/pygrub index cf0efcb185..9b3d15f675 100644 --- a/tools/pygrub/src/pygrub +++ b/tools/pygrub/src/pygrub @@ -197,7 +197,10 @@ class Grub: self.screen = curses.initscr() self.screen.timeout(1000) if hasattr(curses, 'use_default_colors'): - curses.use_default_colors() + try: + curses.use_default_colors() + except: + pass # Not important if we can't use colour enable_cursor(False) self.entry_win = curses.newwin(10, 74, 2, 1) self.text_win = curses.newwin(10, 70, 12, 5) diff --git a/tools/python/scripts/test_hvm_create.py b/tools/python/scripts/test_hvm_create.py index 8effd42db9..7cae70539a 100644 --- a/tools/python/scripts/test_hvm_create.py +++ b/tools/python/scripts/test_hvm_create.py @@ -13,16 +13,11 @@ vm_cfg = { 'VCPUs_policy': 'credit', - 'VCPUs_params': '', + 'VCPUs_params': {}, 'VCPUs_number': 2, - 'VCPUs_features_required': '', - 'VCPUs_features_can_use': '', - 'VCPUs_features_force_on': '', - 'VCPUs_features_force_off': '', 'actions_after_shutdown': 'destroy', 'actions_after_reboot': 'restart', - 'actions_after_suspend': 'destroy', 'actions_after_crash': 'destroy', 'PV_bootloader': '', @@ -44,7 +39,7 @@ vm_cfg = { local_vdi_cfg = { 'name_label': 'gentoo.hvm', 'name_description': '', - 'uri': 'file:/root/gentoo.amd64.hvm.img', + 'location': 'file:/root/gentoo.amd64.hvm.img', 'virtual_size': 0, 'sector_size': 0, 'type': 'system', diff --git a/tools/python/scripts/test_vm_create.py b/tools/python/scripts/test_vm_create.py index 0d702aae69..84959c3e0d 100644 --- a/tools/python/scripts/test_vm_create.py +++ b/tools/python/scripts/test_vm_create.py @@ -15,14 +15,9 @@ vm_cfg = { 'VCPUs_policy': 'credit', 'VCPUs_params': '', 'VCPUs_number': 2, - 'VCPUs_features_required': '', - 'VCPUs_features_can_use': '', - 'VCPUs_features_force_on': '', - 'VCPUs_features_force_off': '', 'actions_after_shutdown': 'destroy', 'actions_after_reboot': 'restart', - 'actions_after_suspend': 'destroy', 'actions_after_crash': 'destroy', 'PV_bootloader': '', @@ -65,7 +60,7 @@ vbd_cfg = { local_vdi_cfg = { 'name_label': 'gentoo.amd64.img', 'name_description': '', - 'uri': 'file:/root/gentoo.amd64.img', + 'location': 'file:/root/gentoo.amd64.img', 'virtual_size': 0, 'sector_size': 0, 'type': 'system', @@ -183,13 +178,13 @@ def test_vm_create(): execute(server, 'VM.resume', (session, vm_uuid, False)) print 'Resumed VM.' + finally: # Wait for user to say we're good to shut it down while True: destroy = raw_input('destroy VM? ') if destroy[0] in ('y', 'Y'): break - - finally: + # Clean up if vif_uuid: execute(server, 'VIF.destroy', (session, vif_uuid)) diff --git a/tools/python/xen/xend/XendAPI.py b/tools/python/xen/xend/XendAPI.py index 0b249f9449..49f2082893 100644 --- a/tools/python/xen/xend/XendAPI.py +++ b/tools/python/xen/xend/XendAPI.py @@ -22,7 +22,7 @@ import sys import traceback import threading -from xen.xend import XendDomain, XendDomainInfo, XendNode +from xen.xend import XendDomain, XendDomainInfo, XendNode, XendDmesg from xen.xend import XendLogging, XendTaskManager from xen.xend.XendAuthSessions import instance as auth_manager @@ -615,7 +615,8 @@ class XendAPI(object): ('reboot', None), ('shutdown', None), ('add_to_other_config', None), - ('remove_from_other_config', None)] + ('remove_from_other_config', None), + ('dmesg', 'String')] host_funcs = [('get_by_name_label', 'Set(host)')] @@ -674,6 +675,9 @@ class XendAPI(object): return xen_api_error(XEND_ERROR_HOST_RUNNING) return xen_api_error(XEND_ERROR_UNSUPPORTED) + def host_dmesg(self, session, host_ref): + return xen_api_success(XendDmesg.instance().info()) + def host_get_record(self, session, host_ref): node = XendNode.instance() dom = XendDomain.instance() @@ -737,7 +741,7 @@ class XendAPI(object): 'memory_free', 'host'] host_metrics_attr_rw = [] - host_methods = [] + host_metrics_methods = [] def _host_metrics_get(self, ref, f): return xen_api_success(getattr(node, f)()) @@ -974,7 +978,8 @@ class XendAPI(object): 'PV_ramdisk', 'PV_args', 'PV_bootloader_args', - 'HVM_boot', + 'HVM_boot_policy', + 'HVM_boot_params', 'platform_std_VGA', 'platform_serial', 'platform_localtime', @@ -1020,7 +1025,8 @@ class XendAPI(object): 'PV_ramdisk', 'PV_args', 'PV_bootloader_args', - 'HVM_boot', + 'HVM_boot_policy', + 'HVM_boot_params', 'platform_std_VGA', 'platform_serial', 'platform_localtime', @@ -1121,11 +1127,11 @@ class XendAPI(object): def VM_get_VCPUs_policy(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return dom.get_vcpus_policy() + return xen_api_success(dom.get_vcpus_policy()) def VM_get_VCPUs_params(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) - return xen_api_todo() # need access to scheduler + return xen_api_success(dom.get_vcpus_params()) def VM_get_actions_after_shutdown(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) @@ -1158,8 +1164,11 @@ class XendAPI(object): def VM_get_PV_bootloader_args(self, session, vm_ref): return self.VM_get('PV_bootloader_args', session, vm_ref) - def VM_get_HVM_boot(self, session, vm_ref): - return self.VM_get('HVM_boot', session, vm_ref) + def VM_get_HVM_boot_policy(self, session, vm_ref): + return self.VM_get('HVM_boot_policy', session, vm_ref) + + def VM_get_HVM_boot_params(self, session, vm_ref): + return self.VM_get('HVM_boot_params', session, vm_ref) def VM_get_platform_std_VGA(self, session, vm_ref): dom = XendDomain.instance().get_vm_by_uuid(vm_ref) @@ -1186,7 +1195,7 @@ class XendAPI(object): return xen_api_success(dom.get_platform_keymap()) def VM_get_other_config(self, session, vm_ref): - return self.VM_get('otherconfig', session, vm_ref) + return self.VM_get('other_config', session, vm_ref) def VM_get_is_control_domain(self, session, vm_ref): xd = XendDomain.instance() @@ -1246,8 +1255,30 @@ class XendAPI(object): return xen_api_error(['VM_ON_CRASH_BEHAVIOUR_INVALID', vm_ref]) return self.VM_set('actions_after_crash', session, vm_ref, action) - def VM_set_HVM_boot(self, session, vm_ref, value): - return self.VM_set('HVM_boot', session, vm_ref, value) + def VM_set_HVM_boot_policy(self, session, vm_ref, value): + if value != "" and value != "BIOS order": + return xen_api_error( + ['VALUE_NOT_SUPPORTED', 'VM.HVM_boot_policy', value, + 'Xend supports only the "BIOS order" boot policy.']) + else: + return self.VM_set('HVM_boot_policy', session, vm_ref, value) + + def VM_set_HVM_boot_params(self, session, vm_ref, value): + return self.VM_set('HVM_boot_params', session, vm_ref, value) + + def VM_add_to_HVM_boot_params(self, session, vm_ref, key, value): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + if 'HVM_boot_params' not in dom.info: + dom.info['HVM_boot_params'] = {} + dom.info['HVM_boot_params'][key] = value + return xen_api_success_void() + + def VM_remove_from_HVM_boot_params(self, session, vm_ref, key): + dom = XendDomain.instance().get_vm_by_uuid(vm_ref) + if 'HVM_boot_params' in dom.info \ + and key in dom.info['HVM_boot_params']: + del dom.info['HVM_boot_params'][key] + return xen_api_success_void() def VM_set_PV_bootloader(self, session, vm_ref, value): return self.VM_set('PV_bootloader', session, vm_ref, value) @@ -1354,7 +1385,8 @@ class XendAPI(object): 'PV_ramdisk': xeninfo.info.get('PV_ramdisk'), 'PV_args': xeninfo.info.get('PV_args'), 'PV_bootloader_args': xeninfo.info.get('PV_bootloader_args'), - 'HVM_boot': xeninfo.info.get('HVM_boot'), + 'HVM_boot_policy': xeninfo.info.get('HVM_boot_policy'), + 'HVM_boot_params': xeninfo.info.get('HVM_boot_params'), 'platform_std_VGA': xeninfo.get_platform_std_vga(), 'platform_serial': xeninfo.get_platform_serial(), 'platform_localtime': xeninfo.get_platform_localtime(), @@ -1363,7 +1395,7 @@ class XendAPI(object): 'platform_keymap': xeninfo.get_platform_keymap(), 'PCI_bus': xeninfo.get_pci_bus(), 'tools_version': xeninfo.get_tools_version(), - 'other_config': xeninfo.info.get('otherconfig'), + 'other_config': xeninfo.info.get('other_config', {}), 'is_control_domain': xeninfo == xendom.privilegedDomain(), } return xen_api_success(record) @@ -1469,7 +1501,7 @@ class XendAPI(object): vdi = XendNode.instance().get_vdi_by_uuid(vdi_ref) if not vdi: return xen_api_error(['VDI_HANDLE_INVALID', vdi_ref]) - vdi_image = vdi.get_image_uri() + vdi_image = vdi.get_location() vbd_ref = XendTask.log_progress(0, 100, dom.create_vbd, vbd_struct, vdi_image) @@ -1622,7 +1654,7 @@ class XendAPI(object): xendom = XendDomain.instance() return xen_api_success(xendom.get_dev_property_by_uuid('vif', vif_ref, 'io_write_kbs')) - + def VIF_get_all(self, session): xendom = XendDomain.instance() vifs = [d.get_vifs() for d in XendDomain.instance().list('all')] diff --git a/tools/python/xen/xend/XendAPIConstants.py b/tools/python/xen/xend/XendAPIConstants.py index 9805cf02a7..41e212d495 100644 --- a/tools/python/xen/xend/XendAPIConstants.py +++ b/tools/python/xen/xend/XendAPIConstants.py @@ -12,7 +12,7 @@ # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #============================================================================ -# Copyright (C) 2006 XenSource Ltd. +# Copyright (C) 2006-2007 XenSource Ltd. #============================================================================ # @@ -24,7 +24,7 @@ XEN_API_VM_POWER_STATE = [ 'Paused', 'Running', 'Suspended', - 'ShuttingDown', + 'Halted', 'Unknown' ] @@ -49,16 +49,8 @@ XEN_API_ON_CRASH_BEHAVIOUR = [ 'rename_restart' ] -XEN_API_BOOT_TYPE = [ - 'bios', - 'grub', - 'kernel_external', - 'kernel_internal' -] - XEN_API_VBD_MODE = ['RO', 'RW'] XEN_API_VDI_TYPE = ['system', 'user', 'ephemeral'] -XEN_API_DRIVER_TYPE = ['ioemu', 'paravirtualised'] XEN_API_VBD_TYPE = ['CD', 'Disk'] XEN_API_TASK_STATUS_TYPE = ['pending', 'success', 'failure'] XEN_API_CONSOLE_PROTOCOL = ['vt100', 'rfb', 'rdp'] diff --git a/tools/python/xen/xend/XendBootloader.py b/tools/python/xen/xend/XendBootloader.py index 29644c5004..4220cde6eb 100644 --- a/tools/python/xen/xend/XendBootloader.py +++ b/tools/python/xen/xend/XendBootloader.py @@ -97,7 +97,9 @@ def bootloader(blexec, disk, dom, quiet = False, blargs = '', kernel = '', try: log.debug("Launching bootloader as %s." % str(args)) - os.execvp(args[0], args) + env = os.environ.copy() + env['TERM'] = 'vt100' + os.execvpe(args[0], args, env) except OSError, e: print e pass diff --git a/tools/python/xen/xend/XendConfig.py b/tools/python/xen/xend/XendConfig.py index f17a5a2295..223a90cf6e 100644 --- a/tools/python/xen/xend/XendConfig.py +++ b/tools/python/xen/xend/XendConfig.py @@ -28,7 +28,7 @@ from xen.xend.PrettyPrint import prettyprintstring from xen.xend.XendConstants import DOM_STATE_HALTED log = logging.getLogger("xend.XendConfig") -log.setLevel(logging.WARN) +log.setLevel(logging.DEBUG) """ @@ -125,8 +125,7 @@ XENAPI_HVM_CFG = { 'platform_std_vga': 'stdvga', 'platform_serial' : 'serial', 'platform_localtime': 'localtime', - 'platform_keymap' : 'keymap', - 'HVM_boot': 'boot', + 'platform_keymap' : 'keymap' } # List of XendConfig configuration keys that have no direct equivalent @@ -147,24 +146,19 @@ XENAPI_CFG_TYPES = { 'memory_actual': int, 'cpus': list, 'vcpus_policy': str, - 'vcpus_params': str, + 'vcpus_params': dict, 'vcpus_number': int, - 'vcpus_features_required': list, - 'vcpus_features_can_use': list, - 'vcpus_features_force_on': list, - 'vcpus_features_force_off': list, 'actions_after_shutdown': str, 'actions_after_reboot': str, - 'actions_after_suspend': str, 'actions_after_crash': str, - 'tpm_instance': int, 'tpm_backend': int, 'PV_bootloader': str, 'PV_kernel': str, 'PV_ramdisk': str, 'PV_args': str, 'PV_bootloader_args': str, - 'HVM_boot': str, + 'HVM_boot_policy': str, + 'HVM_boot_params': dict, 'platform_std_vga': bool0, 'platform_serial': str, 'platform_localtime': bool0, @@ -349,7 +343,6 @@ class XendConfig(dict): def _defaults(self): defaults = { - 'uuid': uuid.createString(), 'name_label': 'Domain-Unnamed', 'actions_after_shutdown': 'destroy', 'actions_after_reboot': 'restart', @@ -361,7 +354,8 @@ class XendConfig(dict): 'PV_ramdisk': '', 'PV_args': '', 'PV_bootloader_args': '', - 'HVM_boot': '', + 'HVM_boot_policy': '', + 'HVM_boot_params': {}, 'memory_static_min': 0, 'memory_dynamic_min': 0, 'shadow_memory': 0, @@ -377,6 +371,7 @@ class XendConfig(dict): 'cpu_weight': 256, 'cpu_cap': 0, 'vcpus_number': 1, + 'vcpus_params': {}, 'console_refs': [], 'vif_refs': [], 'vbd_refs': [], @@ -384,7 +379,6 @@ class XendConfig(dict): 'other_config': {}, } - defaults['name_label'] = 'Domain-' + defaults['uuid'] return defaults def _memory_sanity_check(self): @@ -414,13 +408,21 @@ class XendConfig(dict): def _uuid_sanity_check(self): """Make sure UUID is in proper string format with hyphens.""" - self['uuid'] = uuid.toString(uuid.fromString(self['uuid'])) + if 'uuid' not in self or not self['uuid']: + self['uuid'] = uuid.createString() + else: + self['uuid'] = uuid.toString(uuid.fromString(self['uuid'])) + + def _name_sanity_check(self): + if 'name_label' not in self: + self['name_label'] = 'Domain-' + self['uuid'] def validate(self): + self._uuid_sanity_check() + self._name_sanity_check() self._memory_sanity_check() self._actions_sanity_check() self._vcpus_sanity_check() - self._uuid_sanity_check() def _dominfo_to_xapi(self, dominfo): self['domid'] = dominfo['domid'] @@ -496,6 +498,12 @@ class XendConfig(dict): log.warn("Unable to parse key %s: %s: %s" % (key, str(val), e)) + # Compatibility hack -- can go soon. + boot_order = sxp.child_value(sxp_cfg, 'HVM_boot') + if boot_order: + cfg['HVM_boot_policy'] = 'BIOS order' + cfg['HVM_boot_params'] = { 'order' : boot_order } + # Parsing the device SXP's. In most cases, the SXP looks # like this: # @@ -671,6 +679,9 @@ class XendConfig(dict): if self['devices'][console_uuid][1].get('protocol') == 'rfb': has_rfb = True break + if self['devices'][console_uuid][0] == 'vfb': + has_rfb = True + break if not has_rfb: dev_config = ['vfb'] @@ -724,6 +735,7 @@ class XendConfig(dict): val = sxp.child_value(image_sxp, imgkey, None) if val != None: self[apikey] = val + self._hvm_boot_params_from_sxp(image_sxp) # extract backend value @@ -768,7 +780,7 @@ class XendConfig(dict): if 'image' in xapi_dict: self['image'].update(xapi_dict['image']) else: - hvm = self['HVM_boot'] != '' + hvm = self['HVM_boot_policy'] != '' self['image']['type'] = hvm and 'hvm' or 'linux' if hvm: self['image']['hvm'] = {'devices': {}} @@ -829,8 +841,6 @@ class XendConfig(dict): else: self[key] = val - self.validate() - def to_sxp(self, domain = None, ignore_devices = False, ignore = [], legacy_only = True): """ Get SXP representation of this config object. @@ -854,9 +864,13 @@ class XendConfig(dict): sxpr.append(['domid', domain.getDomid()]) if not legacy_only: - for name in XENAPI_CFG_TYPES.keys(): + for name, typ in XENAPI_CFG_TYPES.items(): if name in self and self[name] not in (None, []): - sxpr.append([name, str(self[name])]) + if typ == dict: + s = self[name].items() + else: + s = str(self[name]) + sxpr.append([name, s]) for xenapi, legacy in XENAPI_CFG_TO_LEGACY_CFG.items(): if self.has_key(xenapi) and self[xenapi] not in (None, []): @@ -905,7 +919,7 @@ class XendConfig(dict): # store as part of the device config. dev_uuid = sxp.child_value(config, 'uuid') dev_type, dev_cfg = self['devices'][dev_uuid] - is_bootable = dev_cfg.get('bootable', False) + is_bootable = dev_cfg.get('bootable', 0) config.append(['bootable', int(is_bootable)]) sxpr.append(['device', config]) @@ -978,14 +992,16 @@ class XendConfig(dict): pass if dev_type == 'vbd': - dev_info['bootable'] = False + dev_info['bootable'] = 0 if dev_info.get('dev', '').startswith('ioemu:'): dev_info['driver'] = 'ioemu' else: dev_info['driver'] = 'paravirtualised' # create uuid if it doesn't exist - dev_uuid = dev_info.get('uuid', uuid.createString()) + dev_uuid = dev_info.get('uuid', None) + if not dev_uuid: + dev_uuid = uuid.createString() dev_info['uuid'] = dev_uuid # store dev references by uuid for certain device types @@ -998,7 +1014,7 @@ class XendConfig(dict): if dev_type == 'vbd' and not target[param]: # Compat hack -- this is the first disk, so mark it # bootable. - dev_info['bootable'] = True + dev_info['bootable'] = 1 target[param].append(dev_uuid) elif dev_type == 'tap': if 'vbd_refs' not in target: @@ -1007,7 +1023,7 @@ class XendConfig(dict): if not target['vbd_refs']: # Compat hack -- this is the first disk, so mark it # bootable. - dev_info['bootable'] = True + dev_info['bootable'] = 1 target['vbd_refs'].append(dev_uuid) elif dev_type == 'vfb': @@ -1055,7 +1071,9 @@ class XendConfig(dict): if cfg_xenapi.get('name'): dev_info['name'] = cfg_xenapi.get('name') - dev_uuid = cfg_xenapi.get('uuid', uuid.createString()) + dev_uuid = cfg_xenapi.get('uuid', None) + if not dev_uuid: + dev_uuid = uuid.createString() dev_info['uuid'] = dev_uuid target['devices'][dev_uuid] = (dev_type, dev_info) target['vif_refs'].append(dev_uuid) @@ -1070,8 +1088,8 @@ class XendConfig(dict): dev_info['uname'] = cfg_xenapi.get('image', '') dev_info['dev'] = '%s:%s' % (cfg_xenapi.get('device'), old_vbd_type) - dev_info['bootable'] = cfg_xenapi.get('bootable', False) - dev_info['driver'] = cfg_xenapi.get('driver') + dev_info['bootable'] = int(cfg_xenapi.get('bootable', 0)) + dev_info['driver'] = cfg_xenapi.get('driver', '') dev_info['VDI'] = cfg_xenapi.get('VDI', '') if cfg_xenapi.get('mode') == 'RW': @@ -1079,7 +1097,9 @@ class XendConfig(dict): else: dev_info['mode'] = 'r' - dev_uuid = cfg_xenapi.get('uuid', uuid.createString()) + dev_uuid = cfg_xenapi.get('uuid', None) + if not dev_uuid: + dev_uuid = uuid.createString() dev_info['uuid'] = dev_uuid target['devices'][dev_uuid] = (dev_type, dev_info) target['vbd_refs'].append(dev_uuid) @@ -1088,13 +1108,17 @@ class XendConfig(dict): if cfg_xenapi.get('type'): dev_info['type'] = cfg_xenapi.get('type') - dev_uuid = cfg_xenapi.get('uuid', uuid.createString()) + dev_uuid = cfg_xenapi.get('uuid', None) + if not dev_uuid: + dev_uuid = uuid.createString() dev_info['uuid'] = dev_uuid target['devices'][dev_uuid] = (dev_type, dev_info) target['vtpm_refs'].append(dev_uuid) elif dev_type == 'console': - dev_uuid = cfg_xenapi.get('uuid', uuid.createString()) + dev_uuid = cfg_xenapi.get('uuid', None) + if not dev_uuid: + dev_uuid = uuid.createString() dev_info['uuid'] = dev_uuid dev_info['protocol'] = cfg_xenapi.get('protocol', 'rfb') dev_info['other_config'] = cfg_xenapi.get('other_config', {}) @@ -1223,7 +1247,12 @@ class XendConfig(dict): "configuration dictionary.") sxpr.append(dev_type) - config = [(opt, val) for opt, val in dev_info.items()] + if dev_type in ('console', 'vfb'): + config = [(opt, val) for opt, val in dev_info.items() + if opt != 'other_config'] + else: + config = [(opt, val) for opt, val in dev_info.items()] + sxpr += config return sxpr @@ -1356,11 +1385,18 @@ class XendConfig(dict): val = sxp.child_value(image_sxp, imgkey, None) if val != None: type_conv = XENAPI_CFG_TYPES[apikey] - if callable(conv): + if callable(type_conv): self[apikey] = type_conv(val) else: self[apikey] = val + self._hvm_boot_params_from_sxp(image_sxp) + + def _hvm_boot_params_from_sxp(self, image_sxp): + boot = sxp.child_value(image_sxp, 'boot', None) + if boot is not None: + self['HVM_boot_policy'] = 'BIOS order' + self['HVM_boot_params'] = { 'order' : boot } # diff --git a/tools/python/xen/xend/XendDomainInfo.py b/tools/python/xen/xend/XendDomainInfo.py index d657d4a1f1..ddc240b96b 100644 --- a/tools/python/xen/xend/XendDomainInfo.py +++ b/tools/python/xen/xend/XendDomainInfo.py @@ -1648,14 +1648,15 @@ class XendDomainInfo: kernel = self.info['PV_kernel'] ramdisk = self.info['PV_ramdisk'] args = self.info['PV_args'] - boot = self.info['HVM_boot'] + boot = self.info['HVM_boot_policy'] if boot: # HVM booting. self.info['image']['type'] = 'hvm' if not 'devices' in self.info['image']: self.info['image']['devices'] = {} - self.info['image']['devices']['boot'] = boot + self.info['image']['devices']['boot'] = \ + self.info['HVM_boot_params'].get('order', 'dc') elif not blexec and kernel: # Boot from dom0. Nothing left to do -- the kernel and ramdisk # will be picked up by image.py. @@ -1976,7 +1977,11 @@ class XendDomainInfo: else: return 'unknown' def get_vcpus_params(self): - return '' # TODO + if self.getDomid() is None: + return self.info['vcpus_params'] + + retval = xc.sched_credit_domain_get(self.getDomid()) + return retval def get_power_state(self): return XEN_API_VM_POWER_STATE[self.state] def get_platform_std_vga(self): diff --git a/tools/python/xen/xend/XendVDI.py b/tools/python/xen/xend/XendVDI.py index 0868814c8f..f0dda203a8 100644 --- a/tools/python/xen/xend/XendVDI.py +++ b/tools/python/xen/xend/XendVDI.py @@ -73,6 +73,7 @@ class XendVDI(AutoSaveObject): self.sharable = False self.read_only = False self.type = "system" + self.location = '' def load_config_dict(self, cfg): """Loads configuration into the object from a dict. @@ -147,9 +148,10 @@ class XendVDI(AutoSaveObject): 'sharable': False, 'readonly': False, 'SR': self.sr_uuid, + 'location': self.get_location(), 'VBDs': []} - def get_image_uri(self): + def get_location(self): raise NotImplementedError() @@ -163,9 +165,10 @@ class XendQCoWVDI(XendVDI): self.virtual_size = vsize self.sector_size = 512 self.auto_save = True + self.location = 'tap:qcow:%s' % self.qcow_path - def get_image_uri(self): - return 'tap:qcow:%s' % self.qcow_path + def get_location(self): + return self.location class XendLocalVDI(XendVDI): def __init__(self, vdi_struct): @@ -183,7 +186,7 @@ class XendLocalVDI(XendVDI): self.type = vdi_struct.get('type', '') self.sharable = vdi_struct.get('sharable', False) self.read_only = vdi_struct.get('read_only', False) - self.image_uri = vdi_struct.get('uri', 'file:/dev/null') + self.location = vdi_struct.get('location', 'file:/dev/null') - def get_image_uri(self): - return self.image_uri + def get_location(self): + return self.location diff --git a/tools/python/xen/xend/image.py b/tools/python/xen/xend/image.py index eeb8bd0ebd..7a20eae3c8 100644 --- a/tools/python/xen/xend/image.py +++ b/tools/python/xen/xend/image.py @@ -449,48 +449,50 @@ class HVMImageHandler(ImageHandler): return ret vnc_config = {} - has_vfb = False - has_vnc = int(vmConfig['image'].get('vnc')) != 0 + has_vnc = int(vmConfig['image'].get('vnc', 0)) != 0 + has_sdl = int(vmConfig['image'].get('sdl', 0)) != 0 for dev_uuid in vmConfig['console_refs']: - dev_type, dev_info = vmConfig['devices'][devuuid] - if dev_type == 'rfb': + dev_type, dev_info = vmConfig['devices'][dev_uuid] + if dev_type == 'vfb': vnc_config = dev_info.get('other_config', {}) - has_vfb = True + has_vnc = True break - if not vnc_config: - for key in ('vncunused', 'vnclisten', 'vncdisplay', 'vncpasswd'): - if key in vmConfig['image']: - vnc_config[key] = vmConfig['image'][key] - - if not has_vfb and not has_vnc: - ret.append('-nographic') - return ret - - - if not vnc_config.get('vncunused', 0) and \ - vnc_config.get('vncdisplay', 0): - ret.append('-vnc') - ret.append(str(vncdisplay)) + if has_vnc: + if not vnc_config: + for key in ('vncunused', 'vnclisten', 'vncdisplay', + 'vncpasswd'): + if key in vmConfig['image']: + vnc_config[key] = vmConfig['image'][key] + + if not vnc_config.get('vncunused', 0) and \ + vnc_config.get('vncdisplay', 0): + ret.append('-vnc') + ret.append(str(vncdisplay)) + else: + ret.append('-vncunused') + + vnclisten = vnc_config.get('vnclisten', + xenopts().get_vnclisten_address()) + ret.append('-vnclisten') + ret.append(str(vnclisten)) + + # Store vncpassword in xenstore + vncpasswd = vnc_config.get('vncpasswd') + if not vncpasswd: + vncpasswd = xenopts().get_vncpasswd_default() + + if vncpasswd is None: + raise VmError('vncpasswd is not setup in vmconfig or ' + 'xend-config.sxp') + + if vncpasswd != '': + self.vm.storeVm('vncpasswd', vncpasswd) + elif has_sdl: + # SDL is default in QEMU. + pass else: - ret.append('-vncunused') - - vnclisten = vnc_config.get('vnclisten', - xenopts().get_vnclisten_address()) - ret.append('-vnclisten') - ret.append(str(vnclisten)) - - # Store vncpassword in xenstore - vncpasswd = vnc_config.get('vncpasswd') - if not vncpasswd: - vncpasswd = xenopts().get_vncpasswd_default() - - if vncpasswd is None: - raise VmError('vncpasswd is not setup in vmconfig or ' - 'xend-config.sxp') - - if vncpasswd != '': - self.vm.storeVm('vncpasswd', vncpasswd) + ret.append('-nographic') return ret diff --git a/tools/python/xen/xend/server/vfbif.py b/tools/python/xen/xend/server/vfbif.py index 0bd1b92bf3..fb510de25f 100644 --- a/tools/python/xen/xend/server/vfbif.py +++ b/tools/python/xen/xend/server/vfbif.py @@ -46,7 +46,7 @@ class VfbifController(DevController): def createDevice(self, config): DevController.createDevice(self, config) - if self.vm.info.get('HVM_boot'): + if self.vm.info.get('HVM_boot_policy'): # is HVM, so qemu-dm will handle the vfb. return @@ -90,7 +90,7 @@ class VfbifController(DevController): def waitForDevice(self, devid): - if self.vm.info.get('HVM_boot'): + if self.vm.info.get('HVM_boot_policy'): log.debug('skip waiting for HVM vfb') # is a qemu-dm managed device, don't wait for hotplug for these. return @@ -110,7 +110,7 @@ class VfbifController(DevController): raise VmError('Refusing to reconfigure device vfb:%d' % devid) def destroyDevice(self, devid, force): - if self.vm.info.get('HVM_boot'): + if self.vm.info.get('HVM_boot_policy'): # remove the backend xenstore entries for HVM guests no matter # what DevController.destroyDevice(self, devid, True) @@ -119,7 +119,7 @@ class VfbifController(DevController): def migrate(self, deviceConfig, network, dst, step, domName): - if self.vm.info.get('HVM_boot'): + if self.vm.info.get('HVM_boot_policy'): return 0 return DevController.migrate(self, deviceConfig, network, dst, step, domName) @@ -136,14 +136,14 @@ class VkbdifController(DevController): return (devid, back, front) def waitForDevice(self, config): - if self.vm.info.get('HVM_boot'): + if self.vm.info.get('HVM_boot_policy'): # is a qemu-dm managed device, don't wait for hotplug for these. return DevController.waitForDevice(self, config) def destroyDevice(self, devid, force): - if self.vm.info.get('HVM_boot'): + if self.vm.info.get('HVM_boot_policy'): # remove the backend xenstore entries for HVM guests no matter # what DevController.destroyDevice(self, devid, True) @@ -151,7 +151,7 @@ class VkbdifController(DevController): DevController.destroyDevice(self, devid, force) def migrate(self, deviceConfig, network, dst, step, domName): - if self.vm.info.get('HVM_boot'): + if self.vm.info.get('HVM_boot_policy'): return 0 return DevController.migrate(self, deviceConfig, network, dst, step, domName) diff --git a/tools/python/xen/xm/messages/en/xen-xm.po b/tools/python/xen/xm/messages/en/xen-xm.po index d422b2e6b8..aca4aceafe 100644 --- a/tools/python/xen/xm/messages/en/xen-xm.po +++ b/tools/python/xen/xm/messages/en/xen-xm.po @@ -19,7 +19,7 @@ msgid "" msgstr "" "Project-Id-Version: Xen-xm 3.0\n" -"PO-Revision-Date: 2007-01-30 17:15+0000\n" +"PO-Revision-Date: 2007-01-31 12:34+0000\n" "Last-Translator: Ewan Mellor <ewan@xensource.com>\n" "Language-Team: xen-devel <xen-devel@lists.xensource.com>\n" "MIME-Version: 1.0\n" @@ -41,6 +41,9 @@ msgstr "The method %(1)s takes %(2)s argument(s) (%(3)s given)." msgid "SESSION_AUTHENTICATION_FAILED" msgstr "Permission denied." +msgid "VALUE_NOT_SUPPORTED" +msgstr "Value \"%(2)s\" for %(1)s is not supported by this server. The server said \"%(3)s\"." + msgid "HOST_CPU_HANDLE_INVALID" msgstr "The host_cpu handle %(1)s is invalid." diff --git a/tools/xcutils/readnotes.c b/tools/xcutils/readnotes.c index fac684014a..f3e412da4e 100644 --- a/tools/xcutils/readnotes.c +++ b/tools/xcutils/readnotes.c @@ -72,8 +72,8 @@ int main(int argc, char **argv) usize = xc_dom_check_gzip(image, st.st_size); if (usize) { - tmp = malloc(size); - xc_dom_do_gunzip(image, st.st_size, tmp, size); + tmp = malloc(usize); + xc_dom_do_gunzip(image, st.st_size, tmp, usize); image = tmp; size = usize; } diff --git a/tools/xm-test/configure.ac b/tools/xm-test/configure.ac index ffbf146f34..d3c651a250 100644 --- a/tools/xm-test/configure.ac +++ b/tools/xm-test/configure.ac @@ -11,10 +11,12 @@ AC_PROG_CC #AC_PROG_INSTALL AC_CHECK_PROG([LILO], lilo, lilo, "no", [$PATH]) +XEN_PYTHON_PATH=$(/usr/sbin/xen-python-path) + # Right now, we can assume that the lib/ directory # is two levels above the tests TESTLIB=../../lib -TENV="PYTHONPATH=$PYTHONPATH:$TESTLIB" +TENV="PYTHONPATH=$PYTHONPATH:$TESTLIB:$XEN_PYTHON_PATH" AC_ARG_ENABLE(hvm-support, [[ --enable-hvm-support enable hardware virtual machine assist]], diff --git a/tools/xm-test/lib/XmTestLib/XenDomain.py b/tools/xm-test/lib/XmTestLib/XenDomain.py index 3fcfcea4f1..09d6f4c764 100644 --- a/tools/xm-test/lib/XmTestLib/XenDomain.py +++ b/tools/xm-test/lib/XmTestLib/XenDomain.py @@ -33,6 +33,9 @@ from DomainTracking import * from acm import * +DOM0_UUID = "00000000-0000-0000-0000-000000000000" + + def getDefaultKernel(): return arch.getDefaultKernel() diff --git a/tools/xm-test/lib/XmTestLib/__init__.py b/tools/xm-test/lib/XmTestLib/__init__.py index f638003b08..40aacf7ecd 100644 --- a/tools/xm-test/lib/XmTestLib/__init__.py +++ b/tools/xm-test/lib/XmTestLib/__init__.py @@ -3,26 +3,6 @@ # Author: Dan Smith <danms@us.ibm.com> # -import os.path -import sys - -# Use the auxbin module in Xend to determine the correct Python path. We -# take the first installed instance of auxbin that we find, and then run it -# to determine the correct path, appending that to sys.path. - -AUXBIN = 'xen/util/auxbin.py' - -for p in ['python%s' % sys.version[:3], 'python']: - for l in ['/usr/lib64', '/usr/lib']: - d = os.path.join(l, p) - if os.path.exists(os.path.join(d, AUXBIN)): - sys.path.append(d) - import xen.util.auxbin - libpath = xen.util.auxbin.libpath() - sys.path = sys.path[:-1] - sys.path.append(libpath) - break - from Console import * from Test import * from Xm import * diff --git a/tools/xm-test/tests/vtpm/09_vtpm-xapi.py b/tools/xm-test/tests/vtpm/09_vtpm-xapi.py index 4798dc13c6..6a17c51045 100644 --- a/tools/xm-test/tests/vtpm/09_vtpm-xapi.py +++ b/tools/xm-test/tests/vtpm/09_vtpm-xapi.py @@ -13,7 +13,6 @@ from XmTestLib import xapi from XmTestLib.XenAPIDomain import XmTestAPIDomain from XmTestLib import * -from xen.xend import XendDomain from vtpm_utils import * import commands import os @@ -28,7 +27,7 @@ except Exception, e: vm_uuid = domain.get_uuid() vtpmcfg = {} -vtpmcfg['backend'] = XendDomain.DOM0_UUID +vtpmcfg['backend'] = DOM0_UUID vtpmcfg['VM'] = vm_uuid session = xapi.connect() |