Esempio n. 1
0
// CreateVolumeAttach will attach a volume to an instance. An error will be
// returned if the attachment failed.
func CreateVolumeAttach(t *testing.T, client *gophercloud.ServiceClient, volume *volumes.Volume, server *servers.Server) error {
	if testing.Short() {
		t.Skip("Skipping test that requires volume attachment in short mode.")
	}

	attachOpts := volumeactions.AttachOpts{
		MountPoint:   "/mnt",
		Mode:         "rw",
		InstanceUUID: server.ID,
	}

	t.Logf("Attempting to attach volume %s to server %s", volume.ID, server.ID)

	if err := volumeactions.Attach(client, volume.ID, attachOpts).ExtractErr(); err != nil {
		return err
	}

	if err := volumes.WaitForStatus(client, volume.ID, "in-use", 60); err != nil {
		return err
	}

	t.Logf("Attached volume %s to server %s", volume.ID, server.ID)

	return nil
}
Esempio n. 2
0
func TestAttach(t *testing.T) {
	th.SetupHTTP()
	defer th.TeardownHTTP()

	MockAttachResponse(t)

	options := &volumeactions.AttachOpts{
		MountPoint:   "/mnt",
		Mode:         "rw",
		InstanceUUID: "50902f4f-a974-46a0-85e9-7efc5e22dfdd",
	}
	err := volumeactions.Attach(client.ServiceClient(), "cd281d77-8217-4830-be95-9528227c105c", options).ExtractErr()
	th.AssertNoErr(t, err)
}
func resourceBlockStorageVolumeAttachV2Create(d *schema.ResourceData, meta interface{}) error {
	config := meta.(*Config)
	client, err := config.blockStorageV2Client(GetRegion(d))
	if err != nil {
		return fmt.Errorf("Error creating OpenStack block storage client: %s", err)
	}

	// Check if either instance_id or host_name was set.
	instanceId := d.Get("instance_id").(string)
	hostName := d.Get("host_name").(string)
	if instanceId == "" && hostName == "" {
		return fmt.Errorf("One of 'instance_id' or 'host_name' must be set.")
	}

	volumeId := d.Get("volume_id").(string)

	attachMode, err := blockStorageVolumeAttachV2AttachMode(d.Get("attach_mode").(string))
	if err != nil {
		return nil
	}

	attachOpts := &volumeactions.AttachOpts{
		InstanceUUID: d.Get("instance_id").(string),
		HostName:     d.Get("host_name").(string),
		MountPoint:   d.Get("device").(string),
		Mode:         attachMode,
	}

	log.Printf("[DEBUG] Attachment Options: %#v", attachOpts)

	if err := volumeactions.Attach(client, volumeId, attachOpts).ExtractErr(); err != nil {
		return err
	}

	// Wait for the volume to become available.
	log.Printf("[DEBUG] Waiting for volume (%s) to become available", volumeId)

	stateConf := &resource.StateChangeConf{
		Pending:    []string{"available", "attaching"},
		Target:     []string{"in-use"},
		Refresh:    VolumeV2StateRefreshFunc(client, volumeId),
		Timeout:    10 * time.Minute,
		Delay:      10 * time.Second,
		MinTimeout: 3 * time.Second,
	}

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

	volume, err := volumes.Get(client, volumeId).Extract()
	if err != nil {
		return err
	}

	var attachmentId string
	for _, attachment := range volume.Attachments {
		if instanceId != "" && instanceId == attachment.ServerID {
			attachmentId = attachment.AttachmentID
		}

		if hostName != "" && hostName == attachment.HostName {
			attachmentId = attachment.AttachmentID
		}
	}

	if attachmentId == "" {
		return fmt.Errorf("Unable to determine attachment ID.")
	}

	// The ID must be a combination of the volume and attachment ID
	// in order to import attachments.
	id := fmt.Sprintf("%s/%s", volumeId, attachmentId)
	d.SetId(id)

	return resourceBlockStorageVolumeAttachV2Read(d, meta)
}