// 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 }
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) }