Esempio n. 1
0
/**
 * Creation of a new VM by cloning from an existing template (looked up by name)
 */
static xen_vm create_new_vm(xen_session *session, char* template_name, char* sr_name, bool PV)
{

    /*
     * Lookup template by name
     */
    xen_vm_set *vms;
    if (!xen_vm_get_by_name_label(session, &vms, template_name) ||
	vms->size < 1)
      {
	fprintf(stderr, "VM lookup failed.\n");
	print_error(session);
	return NULL;
      }
    
    /*
     * Create VM by cloning from template
     */
    xen_vm vm;
    char *name_before = "NewVM <&>"; //using xml sensitive characters
    int name_length = 9;
    xen_vm_clone(session, &vm, vms->contents[0], name_before);
    char *name_after;
    xen_vm_get_name_label(session, &name_after, vm);
    int result = strncmp(name_before, name_after, name_length);

    if (result != 0){
      fprintf(stderr, "Error: The VM name failed to be encoded/decoded correctly\n");
      fprintf(stderr, "Before:%s\nAfter:%s\n", name_before, name_after);
      return NULL;
    }
    
	xen_vm_set_free(vms);
   
    if (!session->ok) {
      fprintf(stderr, "VM clone failed.\n");
      print_error(session);
      return NULL;
    }

    if (PV) {

      xen_string_string_map *other_config;
      if (!xen_vm_get_other_config(session, &other_config, vm)) {
 
        fprintf(stderr, "VM get other_config failed.\n");
        print_error(session);
        return NULL;
      }
      
      char *disks = NULL;
      
      for (size_t i=0; i < other_config->size; i++) {
        
        printf("%s -> %s.\n", other_config->contents[i].key,
               other_config->contents[i].val);
        
        if (strcmp(other_config->contents[i].key, "disks") == 0) {          
          disks = other_config->contents[i].val;
          break;
        }
      }
      
      if (disks == NULL) {
        fprintf(stderr, "Did not find provision XML in other_config.\n");
        xen_string_string_map_free(other_config);
        return NULL;
      }
      
      xen_sr_set *srs;
      if (!xen_sr_get_by_name_label(session, &srs, sr_name) ||
          srs->size < 1) {
        
        fprintf(stderr, "SR lookup failed.\n");
        print_error(session);
        xen_vm_free(vm);
        return NULL;
      }

      xen_sr sr = srs->contents[0];

      char *sr_uuid;

      if(!xen_sr_get_uuid(session, &sr_uuid, sr)){
        //TODO free...?

        return NULL;
      }

      char *new_str;
      if(asprintf(&new_str, "sr=\"%s\"", sr_uuid) < 0) {
        return NULL;
      }

      char *new_disks = replace_str(disks, "sr=\"\"", new_str);

      free(new_str);

      xen_string_string_map_free(other_config);

      if (new_disks == NULL) {
        fprintf(stderr, "Error replacing SR in provision XML.\n");
        return NULL;
      }

      fprintf(stdout, "New provisions XML: %s\n", new_disks);

      if (!xen_vm_remove_from_other_config(session, vm, "disks")) {
        fprintf(stderr, "Error removing old value from other_config.\n");
        print_error(session);
        free(new_disks);
        return NULL;
      }
      
      if (!xen_vm_add_to_other_config(session, vm, "disks", new_disks)) {
        fprintf(stderr, "Error adding new value to other_config.\n");
        print_error(session);
        free(new_disks);
        return NULL;
      }

      free(new_disks);
    }
    
    xen_vm_set_name_description(session, vm, "An example VM created via C bindings");
    if (!session->ok)
      {
	fprintf(stderr, "Failed to set VM description.\n");
	print_error(session);
	return NULL;
      }
    
    xen_vm_provision(session, vm);
    if (!session->ok)
      {
	fprintf(stderr, "Failed to provision VM.\n");
	print_error(session);
	return NULL;
      }
 
    if (PV)
      return vm;

    /*
     * Create a new disk for the new VM.
     */
    printf("Creating new (blank) disk image in 'Shared SR'\n");
    xen_sr_set *srs;
    if (!xen_sr_get_by_name_label(session, &srs, sr_name) ||
        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_string_string_map* other_config = xen_string_string_map_alloc(0);    
    xen_vdi_record vdi0_record =
        {
            .name_label = "MyRootFS",
            .name_description = "MyRootFS description",
            .sr = &sr_record,
            .virtual_size = (1024 * 1024 * 1024), /* 1 GiB in bytes */
            .type = XEN_VDI_TYPE_SYSTEM,
            .sharable = false,
            .read_only = false,
	    .other_config = other_config
        };

    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_string_string_map* qos_algorithm_params = xen_string_string_map_alloc(0);    
    xen_string_string_map* vbd_other_config = xen_string_string_map_alloc(0);    

    enum xen_vbd_type vbd_type_disk = xen_vbd_type_from_string(session, "Disk");

    printf("Attaching disk image to newly created VM\n");
    xen_vbd_record vbd0_record =
        {
            .vm = &vm_record_opt,
            .vdi = &vdi0_record_opt,
            .userdevice = "xvda",
	    .type = vbd_type_disk,
            .mode = XEN_VBD_MODE_RW,
            .bootable = 1,
	    .qos_algorithm_params = qos_algorithm_params,
	    .other_config = vbd_other_config
        };

    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, 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);
}

/*
 * Replace all occurrences of orig in str with rep
 *
 * @returns newly malloc'd string - you must free it
 */
static char *replace_str(char *str, char *orig, char *rep)
{
  int occurrences = 0;
  int i = 0, k = 0;
  char *p = str;

  while ((p = strstr(p, orig)) != NULL) {
    
    ++occurrences;

    p += strlen(orig);
  }

  char *buffer = malloc(strlen(str) + 1 - (occurrences * (strlen(orig) - strlen(rep)))); 
  if(buffer == NULL)
    return NULL;  

  p = str;
  
  while ((p = strstr(p, orig)) != NULL) {

    int j = p - str - k;

    strncpy(buffer + i, str + k, j);
    
    i += j;
    
    strcpy(buffer + i, rep);

    i += strlen(rep);
    
    p += strlen(orig);
    k += j + strlen(orig);
  }

  strncpy(buffer + i, str + k, strlen(str + k));

  buffer[i + strlen(str + k)] = '\0';

  return buffer;
}
Esempio n. 2
0
/*
 * Callback received when the hotplug scripts have placed the physical-device
 * node.  Read it and the mode node, and create a vbd.  If the frontend is
 * ready, connect.
 */
static void backend_changed(struct xenbus_watch *watch,
			    const char **vec, unsigned int len)
{
	int err;
	unsigned major;
	unsigned minor;
	struct backend_info *be
		= container_of(watch, struct backend_info, backend_watch);
	struct xenbus_device *dev = be->dev;
	int cdrom = 0;
	unsigned long handle;
	char *device_type;

	DPRINTK("");

	err = xenbus_scanf(XBT_NIL, dev->nodename, "physical-device", "%x:%x",
			   &major, &minor);
	if (XENBUS_EXIST_ERR(err)) {
		/*
		 * Since this watch will fire once immediately after it is
		 * registered, we expect this.  Ignore it, and wait for the
		 * hotplug scripts.
		 */
		return;
	}
	if (err != 2) {
		xenbus_dev_fatal(dev, err, "reading physical-device");
		return;
	}

	if (be->major | be->minor) {
		if (be->major != major || be->minor != minor)
			pr_warn(DRV_PFX "changing physical device (from %x:%x to %x:%x) not supported.\n",
				be->major, be->minor, major, minor);
		return;
	}

	be->mode = xenbus_read(XBT_NIL, dev->nodename, "mode", NULL);
	if (IS_ERR(be->mode)) {
		err = PTR_ERR(be->mode);
		be->mode = NULL;
		xenbus_dev_fatal(dev, err, "reading mode");
		return;
	}

	device_type = xenbus_read(XBT_NIL, dev->otherend, "device-type", NULL);
	if (!IS_ERR(device_type)) {
		cdrom = strcmp(device_type, "cdrom") == 0;
		kfree(device_type);
	}

	/* Front end dir is a number, which is used as the handle. */
	err = strict_strtoul(strrchr(dev->otherend, '/') + 1, 0, &handle);
	if (err)
		return;

	be->major = major;
	be->minor = minor;

	err = xen_vbd_create(be->blkif, handle, major, minor,
			     !strchr(be->mode, 'w'), cdrom);

	if (err)
		xenbus_dev_fatal(dev, err, "creating vbd structure");
	else {
		err = xenvbd_sysfs_addif(dev);
		if (err) {
			xen_vbd_free(&be->blkif->vbd);
			xenbus_dev_fatal(dev, err, "creating sysfs entries");
		}
	}

	if (err) {
		kfree(be->mode);
		be->mode = NULL;
		be->major = 0;
		be->minor = 0;
	} else {
		/* We're potentially connected now */
		xen_update_blkif_status(be->blkif);
	}
}