func TestMultiEphemeral(t *testing.T) {
	client, err := newClient()
	th.AssertNoErr(t, err)

	if testing.Short() {
		t.Skip("Skipping test that requires server creation in short mode.")
	}

	choices, err := ComputeChoicesFromEnv()
	if err != nil {
		t.Fatal(err)
	}

	name := tools.RandomString("Gophercloud-", 8)
	t.Logf("Creating server [%s].", name)

	bd := []bootfromvolume.BlockDevice{
		bootfromvolume.BlockDevice{
			BootIndex:           0,
			UUID:                choices.ImageID,
			SourceType:          bootfromvolume.Image,
			DestinationType:     "local",
			DeleteOnTermination: true,
		},
		bootfromvolume.BlockDevice{
			BootIndex:           -1,
			SourceType:          bootfromvolume.Blank,
			DestinationType:     "local",
			DeleteOnTermination: true,
			GuestFormat:         "ext4",
			VolumeSize:          1,
		},
		bootfromvolume.BlockDevice{
			BootIndex:           -1,
			SourceType:          bootfromvolume.Blank,
			DestinationType:     "local",
			DeleteOnTermination: true,
			GuestFormat:         "ext4",
			VolumeSize:          1,
		},
	}

	serverCreateOpts := servers.CreateOpts{
		Name:      name,
		FlavorRef: choices.FlavorID,
		ImageRef:  choices.ImageID,
	}
	server, err := bootfromvolume.Create(client, bootfromvolume.CreateOptsExt{
		serverCreateOpts,
		bd,
	}).Extract()
	th.AssertNoErr(t, err)
	if err = waitForStatus(client, server, "ACTIVE"); err != nil {
		t.Fatal(err)
	}

	t.Logf("Created server: %+v\n", server)
	defer servers.Delete(client, server.ID)
	t.Logf("Deleting server [%s]...", name)
}
func TestBootFromVolume(t *testing.T) {
	client, err := newClient()
	th.AssertNoErr(t, err)

	if testing.Short() {
		t.Skip("Skipping test that requires server creation in short mode.")
	}

	choices, err := ComputeChoicesFromEnv()
	if err != nil {
		t.Fatal(err)
	}

	name := tools.RandomString("Gophercloud-", 8)
	t.Logf("Creating server [%s].", name)

	bd := []bootfromvolume.BlockDevice{
		bootfromvolume.BlockDevice{
			UUID:       choices.ImageID,
			SourceType: bootfromvolume.Image,
			VolumeSize: 10,
		},
	}

	serverCreateOpts := servers.CreateOpts{
		Name:      name,
		FlavorRef: "3",
	}
	server, err := bootfromvolume.Create(client, bootfromvolume.CreateOptsExt{
		serverCreateOpts,
		bd,
	}).Extract()
	th.AssertNoErr(t, err)
	t.Logf("Created server: %+v\n", server)
	//defer deleteServer(t, client, server)
	t.Logf("Deleting server [%s]...", name)
}
func resourceComputeInstanceV2Create(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)
	computeClient, err := config.computeV2Client(d.Get("region").(string))
	if err != nil {
		return fmt.Errorf("Error creating OpenStack compute client: %s", err)
	}

	var createOpts servers.CreateOptsBuilder

	// Determines the Image ID using the following rules:
	// If a bootable block_device was specified, ignore the image altogether.
	// If an image_id was specified, use it.
	// If an image_name was specified, look up the image ID, report if error.
	imageId, err := getImageIDFromConfig(computeClient, d)
	if err != nil {
		return err
	}

	flavorId, err := getFlavorID(computeClient, d)
	if err != nil {
		return err
	}

	// determine if volume/block_device configuration is correct
	// this includes ensuring volume_ids are set
	// and if only one block_device was specified.
	if err := checkVolumeConfig(d); err != nil {
		return err
	}

	// check if floating IP configuration is correct
	if err := checkInstanceFloatingIPs(d); err != nil {
		return err
	}

	// Build a list of networks with the information given upon creation.
	// Error out if an invalid network configuration was used.
	networkDetails, err := getInstanceNetworks(computeClient, d)
	if err != nil {
		return err
	}

	networks := make([]servers.Network, len(networkDetails))
	for i, net := range networkDetails {
		networks[i] = servers.Network{
			UUID:    net["uuid"].(string),
			Port:    net["port"].(string),
			FixedIP: net["fixed_ip_v4"].(string),
		}
	}

	createOpts = &servers.CreateOpts{
		Name:             d.Get("name").(string),
		ImageRef:         imageId,
		FlavorRef:        flavorId,
		SecurityGroups:   resourceInstanceSecGroupsV2(d),
		AvailabilityZone: d.Get("availability_zone").(string),
		Networks:         networks,
		Metadata:         resourceInstanceMetadataV2(d),
		ConfigDrive:      d.Get("config_drive").(bool),
		AdminPass:        d.Get("admin_pass").(string),
		UserData:         []byte(d.Get("user_data").(string)),
		Personality:      resourceInstancePersonalityV2(d),
	}

	if keyName, ok := d.Get("key_pair").(string); ok && keyName != "" {
		createOpts = &keypairs.CreateOptsExt{
			createOpts,
			keyName,
		}
	}

	if vL, ok := d.GetOk("block_device"); ok {
		for _, v := range vL.([]interface{}) {
			blockDeviceRaw := v.(map[string]interface{})
			blockDevice := resourceInstanceBlockDeviceV2(d, blockDeviceRaw)
			createOpts = &bootfromvolume.CreateOptsExt{
				createOpts,
				blockDevice,
			}
			log.Printf("[DEBUG] Create BFV Options: %+v", createOpts)
		}
	}

	schedulerHintsRaw := d.Get("scheduler_hints").(*schema.Set).List()
	if len(schedulerHintsRaw) > 0 {
		log.Printf("[DEBUG] schedulerhints: %+v", schedulerHintsRaw)
		schedulerHints := resourceInstanceSchedulerHintsV2(d, schedulerHintsRaw[0].(map[string]interface{}))
		createOpts = &schedulerhints.CreateOptsExt{
			createOpts,
			schedulerHints,
		}
	}

	log.Printf("[DEBUG] Create Options: %#v", createOpts)

	// If a block_device is used, use the bootfromvolume.Create function as it allows an empty ImageRef.
	// Otherwise, use the normal servers.Create function.
	var server *servers.Server
	if _, ok := d.GetOk("block_device"); ok {
		server, err = bootfromvolume.Create(computeClient, createOpts).Extract()
	} else {
		server, err = servers.Create(computeClient, createOpts).Extract()
	}

	if err != nil {
		return fmt.Errorf("Error creating OpenStack server: %s", err)
	}
	log.Printf("[INFO] Instance ID: %s", server.ID)

	// Store the ID now
	d.SetId(server.ID)

	// Wait for the instance to become running so we can get some attributes
	// that aren't available until later.
	log.Printf(
		"[DEBUG] Waiting for instance (%s) to become running",
		server.ID)

	stateConf := &resource.StateChangeConf{
		Pending:    []string{"BUILD"},
		Target:     []string{"ACTIVE"},
		Refresh:    ServerV2StateRefreshFunc(computeClient, server.ID),
		Timeout:    30 * time.Minute,
		Delay:      10 * time.Second,
		MinTimeout: 3 * time.Second,
	}

	_, err = stateConf.WaitForState()
	if err != nil {
		return fmt.Errorf(
			"Error waiting for instance (%s) to become ready: %s",
			server.ID, err)
	}

	// Now that the instance has been created, we need to do an early read on the
	// networks in order to associate floating IPs
	_, err = getInstanceNetworksAndAddresses(computeClient, d)

	// If floating IPs were specified, associate them after the instance has launched.
	err = associateFloatingIPsToInstance(computeClient, d)
	if err != nil {
		return err
	}

	// if volumes were specified, attach them after the instance has launched.
	if v, ok := d.GetOk("volume"); ok {
		vols := v.(*schema.Set).List()
		if blockClient, err := config.blockStorageV1Client(d.Get("region").(string)); err != nil {
			return fmt.Errorf("Error creating OpenStack block storage client: %s", err)
		} else {
			if err := attachVolumesToInstance(computeClient, blockClient, d.Id(), vols); err != nil {
				return err
			}
		}
	}

	return resourceComputeInstanceV2Read(d, meta)
}
Beispiel #4
0
// Create requests the creation of a server from the given block device mapping.
func Create(client *gophercloud.ServiceClient, opts osServers.CreateOptsBuilder) osServers.CreateResult {
	return osBFV.Create(client, opts)
}