blob: 3a859c9d2cccd68c7dece88fd2160a8f315874f6 [file] [log] [blame]
Joe Topjian68bed5f2016-08-10 15:30:57 -06001// Package extensions contains common functions for creating block storage
2// resources that are extensions of the block storage API. See the `*_test.go`
3// files for example usages.
4package extensions
5
6import (
7 "testing"
8
9 "github.com/gophercloud/gophercloud"
Joe Topjian48f36ae2017-02-20 14:36:44 -070010 "github.com/gophercloud/gophercloud/acceptance/tools"
jrperritt18a8bcc2016-10-11 15:23:03 -050011 "github.com/gophercloud/gophercloud/openstack/blockstorage/extensions/volumeactions"
Joe Topjian68bed5f2016-08-10 15:30:57 -060012 "github.com/gophercloud/gophercloud/openstack/blockstorage/v2/volumes"
Joe Topjian48f36ae2017-02-20 14:36:44 -070013 "github.com/gophercloud/gophercloud/openstack/compute/v2/images"
Joe Topjian68bed5f2016-08-10 15:30:57 -060014 "github.com/gophercloud/gophercloud/openstack/compute/v2/servers"
15)
16
Joe Topjian48f36ae2017-02-20 14:36:44 -070017// CreateUploadImage will upload volume it as volume-baked image. An name of new image or err will be
18// returned
19func CreateUploadImage(t *testing.T, client *gophercloud.ServiceClient, volume *volumes.Volume) (string, error) {
20 if testing.Short() {
21 t.Skip("Skipping test that requires volume-backed image uploading in short mode.")
22 }
23
24 imageName := tools.RandomString("ACPTTEST", 16)
25 uploadImageOpts := volumeactions.UploadImageOpts{
26 ImageName: imageName,
27 Force: true,
28 }
29
30 if err := volumeactions.UploadImage(client, volume.ID, uploadImageOpts).ExtractErr(); err != nil {
31 return "", err
32 }
33
34 t.Logf("Uploading volume %s as volume-backed image %s", volume.ID, imageName)
35
36 if err := volumes.WaitForStatus(client, volume.ID, "available", 60); err != nil {
37 return "", err
38 }
39
40 t.Logf("Uploaded volume %s as volume-backed image %s", volume.ID, imageName)
41
42 return imageName, nil
43
44}
45
46// DeleteUploadedImage deletes uploaded image. An error will be returned
47// if the deletion request failed.
48func DeleteUploadedImage(t *testing.T, client *gophercloud.ServiceClient, imageName string) error {
49 if testing.Short() {
50 t.Skip("Skipping test that requires volume-backed image removing in short mode.")
51 }
52
53 t.Logf("Getting image id for image name %s", imageName)
54
55 imageID, err := images.IDFromName(client, imageName)
56 if err != nil {
57 return err
58 }
59
60 t.Logf("Removing image %s", imageID)
61
62 err = images.Delete(client, imageID).ExtractErr()
63 if err != nil {
64 return err
65 }
66
67 return nil
68}
69
Joe Topjian68bed5f2016-08-10 15:30:57 -060070// CreateVolumeAttach will attach a volume to an instance. An error will be
71// returned if the attachment failed.
72func CreateVolumeAttach(t *testing.T, client *gophercloud.ServiceClient, volume *volumes.Volume, server *servers.Server) error {
73 if testing.Short() {
74 t.Skip("Skipping test that requires volume attachment in short mode.")
75 }
76
77 attachOpts := volumeactions.AttachOpts{
78 MountPoint: "/mnt",
79 Mode: "rw",
80 InstanceUUID: server.ID,
81 }
82
83 t.Logf("Attempting to attach volume %s to server %s", volume.ID, server.ID)
84
85 if err := volumeactions.Attach(client, volume.ID, attachOpts).ExtractErr(); err != nil {
86 return err
87 }
88
89 if err := volumes.WaitForStatus(client, volume.ID, "in-use", 60); err != nil {
90 return err
91 }
92
93 t.Logf("Attached volume %s to server %s", volume.ID, server.ID)
94
95 return nil
96}
97
98// CreateVolumeReserve creates a volume reservation. An error will be returned
99// if the reservation failed.
100func CreateVolumeReserve(t *testing.T, client *gophercloud.ServiceClient, volume *volumes.Volume) error {
101 if testing.Short() {
102 t.Skip("Skipping test that requires volume reservation in short mode.")
103 }
104
105 t.Logf("Attempting to reserve volume %s", volume.ID)
106
107 if err := volumeactions.Reserve(client, volume.ID).ExtractErr(); err != nil {
108 return err
109 }
110
111 t.Logf("Reserved volume %s", volume.ID)
112
113 return nil
114}
115
116// DeleteVolumeAttach will detach a volume from an instance. A fatal error will
117// occur if the snapshot failed to be deleted. This works best when used as a
118// deferred function.
119func DeleteVolumeAttach(t *testing.T, client *gophercloud.ServiceClient, volume *volumes.Volume) {
120 t.Logf("Attepting to detach volume volume: %s", volume.ID)
121
122 detachOpts := volumeactions.DetachOpts{
123 AttachmentID: volume.Attachments[0].AttachmentID,
124 }
125
126 if err := volumeactions.Detach(client, volume.ID, detachOpts).ExtractErr(); err != nil {
127 t.Fatalf("Unable to detach volume %s: %v", volume.ID, err)
128 }
129
130 if err := volumes.WaitForStatus(client, volume.ID, "available", 60); err != nil {
131 t.Fatalf("Volume %s failed to become unavailable in 60 seconds: %v", volume.ID, err)
132 }
133
134 t.Logf("Detached volume: %s", volume.ID)
135}
136
137// DeleteVolumeReserve deletes a volume reservation. A fatal error will occur
138// if the deletion request failed. This works best when used as a deferred
139// function.
140func DeleteVolumeReserve(t *testing.T, client *gophercloud.ServiceClient, volume *volumes.Volume) {
141 if testing.Short() {
142 t.Skip("Skipping test that requires volume reservation in short mode.")
143 }
144
145 t.Logf("Attempting to unreserve volume %s", volume.ID)
146
147 if err := volumeactions.Unreserve(client, volume.ID).ExtractErr(); err != nil {
148 t.Fatalf("Unable to unreserve volume %s: %v", volume.ID, err)
149 }
150
151 t.Logf("Unreserved volume %s", volume.ID)
152}