Exemple #1
0
// automatically generated. Do not modify
static void testVMs(xen_session *session) {
	printf("\nGet all the  VM Records\n");

	xen_vm_set *vm_set;
	bool d = xen_vm_get_all(session, &vm_set);
	if (d) {
		size_t i = 0;
		for (; i < vm_set->size; ++i) {
			xen_vm_record *vm_record;
			xen_vm_get_record(session, &vm_record, vm_set->contents[i]);
			char *handle = (char*) vm_record->handle;
			char *opaque = (char*) vm_set->contents[i];
			if (strcmp(handle, opaque) == 0)
				printf("identical: %s\n", opaque);
			else
				printf("record->handle[%s] v.s. set->contents[%d][%s]\n",
						opaque, i, handle);
			xen_vm_record_free(vm_record);
		}
	} else {
		print_error(session);
	}
	xen_vm_set_free(vm_set);

#if 0
	printf("== Get All VM Records ============================\n\n");

	xen_vm_xen_vm_record_map *result;
	bool ok = xen_vm_get_all_records(session, &result);
	if(!ok) {
		print_error(session);
	}
	size_t i=0;
	for(;i<result->size;++i) {
		xen_vm key = result->contents[i].key;
		struct xen_vm_record *val = result->contents[i].val;
		if(strcmp((char*)key, (char*)val->handle)==0) {

		} else {
			printf("%s v.s. %s", (char*)key, (char*)val->handle);
		}
		xen_vm_record_free(val);
		xen_vm_free(key);
	}
	free(result);
#endif

	printf("\n==============================================\n\n");
}
void
xen_vm_xen_vm_record_map_free(xen_vm_xen_vm_record_map *map)
{
    if (map == NULL)
    {
        return;
    }

    size_t n = map->size;
    for (size_t i = 0; i < n; i++)
    {
        xen_vm_free(map->contents[i].key);
        xen_vm_record_free(map->contents[i].val);
    }

    free(map);
}
Exemple #3
0
/* Create a VM record from the XML description */
int
createVMRecordFromXml(virConnectPtr conn, virDomainDefPtr def,
                      xen_vm_record **record, xen_vm *vm)
{
    char uuidStr[VIR_UUID_STRING_BUFLEN];
    xen_string_string_map *strings = NULL;
    int device_number = 0;
    size_t i;

    *record = xen_vm_record_alloc();
    if (VIR_STRDUP((*record)->name_label, def->name) < 0)
        goto error;
    if (def->uuid) {
        virUUIDFormat(def->uuid, uuidStr);
        if (VIR_STRDUP((*record)->uuid, uuidStr) < 0)
            goto error;
    }
    if (STREQ(def->os.type, "hvm")) {
        char *boot_order = NULL;
        if (VIR_STRDUP((*record)->hvm_boot_policy, "BIOS order") < 0)
            goto error;
        if (def->os.nBootDevs != 0)
            boot_order = createXenAPIBootOrderString(def->os.nBootDevs, &def->os.bootDevs[0]);
        if (boot_order != NULL) {
            xen_string_string_map *hvm_boot_params = NULL;
            allocStringMap(&hvm_boot_params, (char *)"order", boot_order);
            (*record)->hvm_boot_params = hvm_boot_params;
            VIR_FREE(boot_order);
        }
    } else if (STREQ(def->os.type, "xen")) {
        if (VIR_STRDUP((*record)->pv_bootloader, "pygrub") < 0)
            goto error;
        if (def->os.kernel) {
            if (VIR_STRDUP((*record)->pv_kernel, def->os.kernel) < 0)
                goto error;
        }
        if (def->os.initrd) {
            if (VIR_STRDUP((*record)->pv_ramdisk, def->os.initrd) < 0)
                goto error;
        }
        if (def->os.cmdline) {
            if (VIR_STRDUP((*record)->pv_args, def->os.cmdline) < 0)
                goto error;
        }
        (*record)->hvm_boot_params = xen_string_string_map_alloc(0);
    }
    if (def->os.bootloaderArgs)
        if (VIR_STRDUP((*record)->pv_bootloader_args, def->os.bootloaderArgs) < 0)
            goto error;

    if (def->mem.cur_balloon)
        (*record)->memory_static_max = (int64_t) (def->mem.cur_balloon * 1024);
    if (def->mem.max_balloon)
        (*record)->memory_dynamic_max = (int64_t) (def->mem.max_balloon * 1024);
    else
        (*record)->memory_dynamic_max = (*record)->memory_static_max;

    if (def->maxvcpus) {
        (*record)->vcpus_max = (int64_t) def->maxvcpus;
        (*record)->vcpus_at_startup = (int64_t) def->vcpus;
    }
    if (def->onPoweroff)
        (*record)->actions_after_shutdown = actionShutdownLibvirt2XenapiEnum(def->onPoweroff);
    if (def->onReboot)
        (*record)->actions_after_reboot = actionShutdownLibvirt2XenapiEnum(def->onReboot);
    if (def->onCrash)
        (*record)->actions_after_crash = actionCrashLibvirt2XenapiEnum(def->onCrash);

    if (def->features[VIR_DOMAIN_FEATURE_ACPI] == VIR_DOMAIN_FEATURE_STATE_ON)
        allocStringMap(&strings, (char *)"acpi", (char *)"true");
    if (def->features[VIR_DOMAIN_FEATURE_APIC] == VIR_DOMAIN_FEATURE_STATE_ON)
        allocStringMap(&strings, (char *)"apic", (char *)"true");
    if (def->features[VIR_DOMAIN_FEATURE_PAE] == VIR_DOMAIN_FEATURE_STATE_ON)
        allocStringMap(&strings, (char *)"pae", (char *)"true");
    if (def->features[VIR_DOMAIN_FEATURE_HAP] == VIR_DOMAIN_FEATURE_STATE_ON)
        allocStringMap(&strings, (char *)"hap", (char *)"true");
    if (def->features[VIR_DOMAIN_FEATURE_VIRIDIAN] == VIR_DOMAIN_FEATURE_STATE_ON)
        allocStringMap(&strings, (char *)"viridian", (char *)"true");
    if (strings != NULL)
        (*record)->platform = strings;

    (*record)->vcpus_params = xen_string_string_map_alloc(0);
    (*record)->other_config = xen_string_string_map_alloc(0);
    (*record)->last_boot_cpu_flags = xen_string_string_map_alloc(0);
    (*record)->xenstore_data = xen_string_string_map_alloc(0);
    (*record)->hvm_shadow_multiplier = 1.000;
    if (!xen_vm_create(((struct _xenapiPrivate *)(conn->privateData))->session,
                        vm, *record)) {
        xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, NULL);
        return -1;
    }

    for (i = 0; i < def->nnets; i++) {
        if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_BRIDGE &&
            def->nets[i]->data.bridge.brname) {
            char *mac;

            if (VIR_ALLOC_N(mac, VIR_MAC_STRING_BUFLEN) < 0)
                goto error;
            virMacAddrFormat(&def->nets[i]->mac, mac);

            if (createVifNetwork(conn, *vm, device_number,
                                 def->nets[i]->data.bridge.brname,
                                 mac) < 0) {
                VIR_FREE(mac);
                virReportOOMError();
                goto error;
            }
            device_number++;
        }
    }
    return 0;

  error:
    xen_vm_record_free(*record);
    return -1;
}
Exemple #4
0
/* Create a VM record from the XML description */
int
createVMRecordFromXml (virConnectPtr conn, virDomainDefPtr def,
                       xen_vm_record **record, xen_vm *vm)
{
    char uuidStr[VIR_UUID_STRING_BUFLEN];
    *record = xen_vm_record_alloc();
    if (!((*record)->name_label = strdup(def->name)))
        goto error_cleanup;
    if (def->uuid) {
        virUUIDFormat(def->uuid, uuidStr);
        if (!((*record)->uuid = strdup(uuidStr)))
            goto error_cleanup;
    }
    if (STREQ(def->os.type, "hvm")) {
        char *boot_order = NULL;
        if (!((*record)->hvm_boot_policy = strdup("BIOS order")))
            goto error_cleanup;
        if (def->os.nBootDevs != 0)
            boot_order = createXenAPIBootOrderString(def->os.nBootDevs, &def->os.bootDevs[0]);
        if (boot_order != NULL) {
            xen_string_string_map *hvm_boot_params = NULL;
            allocStringMap(&hvm_boot_params, (char *)"order", boot_order);
            (*record)->hvm_boot_params = hvm_boot_params;
            VIR_FREE(boot_order);
        }
    } else if (STREQ(def->os.type, "xen")) {
        if (!((*record)->pv_bootloader = strdup("pygrub")))
            goto error_cleanup;
        if (def->os.kernel) {
            if (!((*record)->pv_kernel = strdup(def->os.kernel)))
                goto error_cleanup;
        }
        if (def->os.initrd) {
            if (!((*record)->pv_ramdisk = strdup(def->os.initrd)))
                goto error_cleanup;
        }
        if (def->os.cmdline) {
            if (!((*record)->pv_args = strdup(def->os.cmdline)))
                goto error_cleanup;
        }
        (*record)->hvm_boot_params = xen_string_string_map_alloc(0);
    }
    if (def->os.bootloaderArgs)
        if (!((*record)->pv_bootloader_args = strdup(def->os.bootloaderArgs)))
            goto error_cleanup;

    if (def->memory)
        (*record)->memory_static_max = (int64_t) (def->memory * 1024);
    if (def->maxmem)
        (*record)->memory_dynamic_max = (int64_t) (def->maxmem * 1024);
    else
        (*record)->memory_dynamic_max = (*record)->memory_static_max;

    if (def->vcpus) {
        (*record)->vcpus_max = (int64_t) def->vcpus;
        (*record)->vcpus_at_startup = (int64_t) def->vcpus;
    }
    if (def->onPoweroff)
        (*record)->actions_after_shutdown = actionShutdownLibvirt2XenapiEnum(def->onPoweroff);
    if (def->onReboot)
        (*record)->actions_after_reboot = actionShutdownLibvirt2XenapiEnum(def->onReboot);
    if (def->onCrash)
        (*record)->actions_after_crash = actionCrashLibvirt2XenapiEnum(def->onCrash);

    xen_string_string_map *strings = NULL;
    if (def->features) {
        if (def->features & (1 << VIR_DOMAIN_FEATURE_ACPI))
            allocStringMap(&strings, (char *)"acpi", (char *)"true");
        if (def->features & (1 << VIR_DOMAIN_FEATURE_APIC))
            allocStringMap(&strings, (char *)"apic", (char *)"true");
        if (def->features & (1 << VIR_DOMAIN_FEATURE_PAE))
            allocStringMap(&strings, (char *)"pae", (char *)"true");
    }
    if (strings != NULL)
        (*record)->platform = strings;

    (*record)->vcpus_params = xen_string_string_map_alloc(0);
    (*record)->other_config = xen_string_string_map_alloc(0);
    (*record)->last_boot_cpu_flags = xen_string_string_map_alloc(0);
    (*record)->xenstore_data = xen_string_string_map_alloc(0);
    (*record)->hvm_shadow_multiplier = 1.000;
    if (!xen_vm_create(((struct _xenapiPrivate *)(conn->privateData))->session,
                        vm, *record)) {
        xenapiSessionErrorHandler(conn, VIR_ERR_INTERNAL_ERROR, NULL);
        return -1;
    }

    int device_number = 0;
    char *bridge = NULL, *mac = NULL;
    int i;
    for (i = 0; i < def->nnets; i++) {
        if (def->nets[i]->type == VIR_DOMAIN_NET_TYPE_BRIDGE) {
            if (def->nets[i]->data.bridge.brname)
                if (!(bridge = strdup(def->nets[i]->data.bridge.brname)))
                    goto error_cleanup;
            if (def->nets[i]->mac) {
                char macStr[VIR_MAC_STRING_BUFLEN];
                virFormatMacAddr(def->nets[i]->mac, macStr);
                if (!(mac = strdup(macStr))) {
                    VIR_FREE(bridge);
                    goto error_cleanup;
                }
            }
            if (mac != NULL && bridge != NULL) {
                char device[NETWORK_DEVID_SIZE] = "\0";
                sprintf(device, "%d", device_number);
                createVifNetwork(conn, *vm, device, bridge, mac);
                VIR_FREE(bridge);
                device_number++;
            }
            VIR_FREE(bridge);
        }
    }
    return 0;

  error_cleanup:
    virReportOOMError();
    xen_vm_record_free(*record);
    return -1;
}
Exemple #5
0
int main(int argc, char **argv)
{

    if (argc != 5)
    {
        usage();
    }

    url = argv[1];
    char *sr_name = argv[2];
    char *username = argv[3];
    char *password = argv[4];

    xmlInitParser();
    xmlKeepBlanksDefault(0);
    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_api_latest_version);

    /* ---------------------------------------------------------------------
       Read host, capabilities and API vsn
       --------------------------------------------------------------------- */

    printf("\n\nQuerying host...\n");

    xen_host host;
    if (!xen_session_get_this_host(session, &host, session))
    {
        print_error(session);
        CLEANUP;
        return 1;
    }

    xen_string_string_map *versions;
    if (!xen_host_get_software_version(session, &versions, host))
    {
        print_error(session);
        xen_host_free(host);
        CLEANUP;
        return 1;
    }

    xen_string_set *supported_bootloaders;
    if (!xen_host_get_supported_bootloaders(session, &supported_bootloaders,
                                            host))
    {
        print_error(session);
        xen_string_string_map_free(versions);
        xen_host_free(host);
        CLEANUP;
        return 1;
    }

    xen_string_set *capabilities;
    if (!xen_host_get_capabilities(session, &capabilities, host))
    {
        print_error(session);
        xen_string_set_free(supported_bootloaders);
        xen_string_string_map_free(versions);
        xen_host_free(host);
        CLEANUP;
        return 1;
    }


    for (size_t i = 0; i < versions->size; i++)
    {
        printf("%s -> %s.\n", versions->contents[i].key,
               versions->contents[i].val);
    }

    printf("Host supports the following bootloaders:");
    for (size_t i = 0; i < supported_bootloaders->size; i++)
    {
        printf(" %s", supported_bootloaders->contents[i]);
    }
    printf("\n");

    printf("Host has the following capabilities:");
    for (size_t i = 0; i < capabilities->size; i++)
    {
        printf(" %s", capabilities->contents[i]);
    }
    printf("\n");

    xen_host_free(host);
    xen_string_string_map_free(versions);
    xen_string_set_free(supported_bootloaders);
    xen_string_set_free(capabilities);

    /* ---------------------------------------------------------------------
       Create a new VM with a blank disk:
       --------------------------------------------------------------------- */

    printf("\n\nCreating new HVM VM...\n");
    xen_vm hvm_vm = create_new_vm(session, "Other install media", sr_name, false);
    if (!session->ok)
    {
        /* Error has been logged, just clean up. */
        CLEANUP;
        return 1;
    }

    print_vm_power_state(session, hvm_vm);

    /* Blob handling used to crash when we tried to free the VM record:
     * CA-38872. */
    xen_blob blob;
    xen_blob_create(session, &blob, "hello", false);
    xen_vm_create_new_blob(session, &blob, hvm_vm, "test", "test", false);
    printf("\nBlob created.\n");
    xen_blob_record *blob_record;
    xen_blob_get_record(session, &blob_record, blob);
    printf("Blob record retrieved.\n");

    printf("\nGetting VM record...\n");
    xen_vm_record *vm_record;
    xen_vm_get_record(session, &vm_record, hvm_vm);
    printf("VM record: %s blob: %s\n",
           (char *)vm_record->handle,
           (char *)blob_record->handle);
    printf("Freeing VM record...\n");
    xen_vm_record_free(vm_record);
    printf("VM record freed.\n");
    printf("Freeing blob record...\n");
    xen_blob_record_free(blob_record);
    printf("Blob record freed.\n");
    
    if (!session->ok)
    {
        /* Error has been logged, just clean up. */
        xen_vm_free(hvm_vm);
        CLEANUP;
        return 1;
    }

    /*
       Test Enum parsing by setting actions after shutdown
     */

    xen_vm_set_actions_after_shutdown(session, hvm_vm, XEN_ON_NORMAL_EXIT_RESTART);

    /*
      Test getting a map and having a play
     */
    xen_string_string_map *hvm_boot_params;

    if (!xen_vm_get_hvm_boot_params(session, &hvm_boot_params, hvm_vm))
    {
        print_error(session);
        CLEANUP;
        return 1;
    }

    printf("HVM_boot_params contains:\n");

    for (size_t i = 0; i < hvm_boot_params->size; i++)
    {
        printf("%s -> %s.\n", hvm_boot_params->contents[i].key,
               hvm_boot_params->contents[i].val);
    }

    xen_string_string_map_free(hvm_boot_params);

    cycle_vm(session, hvm_vm);

    xen_vm_free(hvm_vm);

    /* TODO uncomment this when we test against real
            hosts, as SDK doesn't have debian template
    
    printf("\n\nCreating new PV VM...\n");
    xen_vm pv_vm = create_new_vm(session, "Debian Etch 4.0", sr_name, true);
    if (!session->ok)
    {
        CLEANUP;
        return 1;
    }

    if (!xen_vm_get_hvm_boot_params(session, &hvm_boot_params, pv_vm))
    {
        print_error(session);
        CLEANUP;
        return 1;
    }

    for (size_t i = 0; i < hvm_boot_params->size; i++)
    {
        printf("%s -> %s.\n", hvm_boot_params->contents[i].key,
               hvm_boot_params->contents[i].val);
    }

    cycle_vm(session, pv_vm);

    xen_vm_free(pv_vm);
    */

    CLEANUP;
}
Exemple #6
0
/******************************************************************************
 * Function to enumerate a xen resource
 *
 * @param session - handle to a xen_utils_session object
 * @param resources - pointer to the provider_resource_list
 * @return CMPIrc error codes
 *****************************************************************************/
static CMPIrc xen_resource_list_enum(
       xen_utils_session *session, 
       provider_resource_list *resources
)
{
  enum domain_choice choice = vms_only;
  xen_domain_resources *domain_set = NULL;

  if(!xen_utils_get_domain_resources(session, &domain_set, choice))
    return CMPI_RC_ERR_FAILED;

  xen_vm resource_handle;
  xen_vm_record *resource_rec = NULL;

  kvp_set *complete_set;
  
  initialise_kvp_set(&complete_set);

  for(domain_set->currentdomain=0; domain_set->currentdomain < domain_set->numdomains; domain_set->currentdomain++){

    _SBLIM_TRACE(_SBLIM_TRACE_LEVEL_INFO, ("Current Domain: %d", domain_set->currentdomain));

    resource_handle = domain_set->domains->contents[domain_set->currentdomain];
    _SBLIM_TRACE(_SBLIM_TRACE_LEVEL_INFO, ("Current resource handle = %s", resource_handle));
    
    if(!xen_vm_get_record(session->xen, &resource_rec, resource_handle)) {
      _SBLIM_TRACE(_SBLIM_TRACE_LEVEL_ERROR,
		   ("--- xen_vm_get_record failed: \"%s\" \"%s\"",
		    session->xen->error_description[0], resource_handle));
      char *error = xen_utils_get_xen_error(session->xen);
      _SBLIM_TRACE(_SBLIM_TRACE_LEVEL_ERROR, ("%s", error));
      RESET_XEN_ERROR(session->xen);
      if (error)
	free(error);
      continue;
    }

    char *res = xen_utils_get_from_string_string_map(resource_rec->other_config, "kvp_enabled");
    _SBLIM_TRACE(_SBLIM_TRACE_LEVEL_INFO, ("result = %s", res));
    if(res) {
      /* Result is not NULL - therefore the VM is counted as being 'enabled' for KVP */
      
      xen_host_record_opt *host = resource_rec->resident_on;

      _SBLIM_TRACE(_SBLIM_TRACE_LEVEL_INFO, ("VM is resident on host '%s'",host->u.handle));

      if (host->u.handle){

	char *address = NULL;
	
	if(!xen_host_get_address(session->xen, &address, host->u.handle))
	{
	    _SBLIM_TRACE(_SBLIM_TRACE_LEVEL_ERROR,("Host address not found"));
	} else {
	  /* Make remote call for store */
	  char *plugin = "services/plugin/xscim";
	  char *xenref = (char *)((session->xen)->session_id);
	  /* Add overhead of 15 characters */

	  int len = sizeof(char) * (25 + strlen(plugin) + strlen(address) + strlen(resource_rec->uuid) + strlen(xenref));

	  char *url = (char *)malloc(len);

	  sprintf(url, "http://%s/%s/vm/%s?session_id=%s", address, plugin, resource_rec->uuid, xenref);
	  
	  _SBLIM_TRACE(_SBLIM_TRACE_LEVEL_INFO, ("Fetch store from URL '%s'", url));
	  
	  kvp_set *set;
	  Xen_KVP_RC rc = xen_utils_get_kvp_store(url, (char *)resource_rec->uuid,&set);
	  if (rc != Xen_KVP_RC_OK) {
	    _SBLIM_TRACE(_SBLIM_TRACE_LEVEL_ERROR, ("Unable to retrieve KVP store for VM %s",
						   resource_rec->uuid));
	    _SBLIM_TRACE(_SBLIM_TRACE_LEVEL_INFO, ("Continuing on to the next domain"));
	  } else {
          _SBLIM_TRACE(_SBLIM_TRACE_LEVEL_INFO, ("sets so far %d", set->size));

	  /* Append the contents of the returned set */
	  xen_utils_append_kvp_set(complete_set, set);

	  
	  if (set)
	    xen_utils_free_kvpset(set);	  
	  	  
	  if(url)
	    free(url);

	  /* Free the host address */
	  if (address)
	    free(address);

	  }
	
	}
      } else {
	/* VM is not started, and so may not be resident on any host. */
      }
      
    }
    
    xen_vm_record_free(resource_rec);
  }
  xen_utils_free_domain_resources(domain_set);

  _SBLIM_TRACE(_SBLIM_TRACE_LEVEL_INFO, ("all in %d keys", complete_set->size));
    /* Return the set of KVPs */
    resources->ctx = complete_set;

    return CMPI_RC_OK;
}
int main(int argc, char **argv)
{

    if (argc != 6)
    {
        usage();
    }

    url = argv[1];
    char *username = argv[2];
    char *password = argv[3];
    
    source_url = argv[4];
    target_url = argv[5];

    xmlInitParser();
    xmlKeepBlanksDefault(0);
    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_api_latest_version);

    printf("\n\nQuerying host...\n");
    xen_host host;
    if (!xen_session_get_this_host(session, &host, session))
    {
        print_error(session);
        CLEANUP;
        return 1;
    }
    
    /* Read in the source host and target host using their name labels
     */
    xen_host_set *source_hosts;
    
    int rc = 0;
 
    rc = get_host_names(session, &source_hosts, source_url );
    if (rc !=0 )
    {
        fprintf(stderr, "source host lookup failed.\n");
	print_error(session);
        return 1;
    }
    
    
    xen_host_set *target_hosts;
    rc = 0;
    rc = get_host_names(session, &target_hosts, target_url );
    if (rc !=0 )
    {
        fprintf(stderr, "target host lookup failed.\n");
	print_error(session);
        return 1;
    }
    
            
    struct xen_vm_set *all_vms_in_pool;
    xen_vm_get_all(session, &all_vms_in_pool);
    
    
    bool *vm_to_be_migrated = calloc(all_vms_in_pool->size, sizeof(bool));
    int num_vms_to_migrate = 0;
    enum xen_task_status_type task_status;
   
    xen_vm_record* result;
    
    for (size_t i = 0; i < all_vms_in_pool->size; i++ )
    {
        xen_vm a_vm = all_vms_in_pool->contents[i];
        xen_vm_get_record(session, &result, a_vm);
        
        /*
         * we can only migrate VMs that are
         * -not templates 
         * -not control domains
         * -and are running 
         * 
         * resident_on is used to identify the eligible VMs on the user
         * requested source_host 
         */
        
        if ( !result->is_a_template 
              && !result->is_control_domain
              && (result->power_state ==  XEN_VM_POWER_STATE_RUNNING)
              && (strcmp(result->resident_on->u.handle, 
                         (char*)source_hosts->contents[0]) == 0) )
        {
            // flag this VM as one suitable to migrate
            vm_to_be_migrated[i] = true;
            num_vms_to_migrate++; 
        }
        else 
        {
            vm_to_be_migrated[i] = false;
        }
    }
   
    
    if (!session->ok)
    {
        /* Error has been logged, just clean up. */
        xen_host_set_free(source_hosts);
        xen_host_set_free(target_hosts);
        xen_vm_set_free(all_vms_in_pool);       
        xen_vm_record_free(result);
        free(vm_to_be_migrated);
        CLEANUP;
        return 1;
    }

    xen_task* task_list = calloc(num_vms_to_migrate, sizeof(xen_task));
    xen_string_string_map* options = xen_string_string_map_alloc(0);    
    xen_string_set *error_msgs = NULL;
    
    int idx = 0;
    for (size_t i = 0; i < all_vms_in_pool->size; i++ )
    {
     
        if (vm_to_be_migrated[i] == true)
        {
            xen_vm_pool_migrate_async(session, &task_list[idx], all_vms_in_pool->contents[i], 
                                        target_hosts->contents[0], options );
            
            idx++;
            printf(" Migrating VM %zd \n", i);
        }
    
    }
    
    // time out after certain number of iterations
    int max_iter = 50; 
    int iter = 0;
    int pause_interval_secs = 4;
    int tasks_running = 0;
    int tasks_completed = 0;
    xen_task a_task;
    bool tasks_still_pending = true;

    /* Poll how many of the migration tasks have completed. 
     * 
     * The task querying below isn't is intended to provide a sample of useful 
     * syntax. In practice a user would probably consider using functions such 
     * as xen_task_cancel or indeed the asynchronous equivalent 
     * xen_task_cancel_async.
     * These functions and other task handling ones are defined in xen_task.c
     */
    
    while ( iter < max_iter && tasks_still_pending )
    {
        tasks_running = 0;
        tasks_completed = 0;
        for (int j = 0; j < num_vms_to_migrate; j++)
        {
            a_task = task_list[j];
           
            xen_task_get_status(session, &task_status, a_task);
            
            if (task_status == XEN_TASK_STATUS_TYPE_PENDING)
            {
                tasks_running++;
            }
            else
            {
                /* See the xen_task_status_type enum definitions
                 * defined in xen_task_status_type.h a task can have
                 * failed, or be cancelled or in the process of being cancelled
                 * amongst others.
                 * The definition of tasks_completed in this context is tasks
                 * not pending.
                 */
                           
                if (task_status == XEN_TASK_STATUS_TYPE_FAILURE)
                {
                    if (xen_task_get_error_info(session, &error_msgs, task_list[j] ))
                    {
                        /* VMs may need to meet certain criteria for migration to be 
                         * possible between hosts; such as shared storage between
                         * hosts. It is advisable to check the criteria needed for 
                         * migration on the particular version of XenServer. 
                         * The error messages output below should give information
                         * that allows the identification of an unsupported
                         * operation
                         */
                        printf("-------------------------------------\n");
                        printf("Failed while trying to migrate VM: \n");
                        for(size_t k=0; k<error_msgs->size; k++)
                        {
                            printf("error_msg %zu : %s \n",  k, error_msgs->contents[k]); 
                        }
                    }
                }
                
                tasks_completed++;
            }

        }

        if (tasks_running == 0) 
        {
            tasks_still_pending = false; // stop the iteration early
            printf("All tasks completed \n");
        }
        printf("*********************************************\n");
        printf("VM migration progress, poll number %d \n", iter);
        printf("----------------------------------------\n");
        printf(" Tasks pending : %d \n", tasks_running);
        printf("       ended   : %d \n", tasks_completed);
        printf("*********************************************\n");    
        
        iter++;
        sleep(pause_interval_secs); 
        
    }
    

    xen_string_set_free(error_msgs);
    xen_string_string_map_free(options);
    xen_host_set_free(source_hosts);
    xen_host_set_free(target_hosts);
    free(task_list);
    free(vm_to_be_migrated);
    xen_vm_set_free(all_vms_in_pool);
    
    CLEANUP;
}