Skip to content

Commit b593d69

Browse files
jtopjianstack72
authored andcommitted
provider/openstack: Volume Attachment Updates (hashicorp#11285)
This commit adds a StateRefresh func for volume attachments. Mostly this is to add a buffer of time between the request and the return of the attachment to give time for the volume to become attached, however, in some cases the refresh function could work as specified. Docs have also been updated to reflect that a device could be specified, but to use with caution.
1 parent 82441ac commit b593d69

3 files changed

Lines changed: 92 additions & 7 deletions

File tree

builtin/providers/openstack/resource_openstack_compute_volume_attach_v2.go

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,19 @@ func resourceComputeVolumeAttachV2Create(d *schema.ResourceData, meta interface{
7878
return err
7979
}
8080

81+
stateConf := &resource.StateChangeConf{
82+
Pending: []string{"ATTACHING"},
83+
Target: []string{"ATTACHED"},
84+
Refresh: resourceComputeVolumeAttachV2AttachFunc(computeClient, instanceId, attachment.ID),
85+
Timeout: 10 * time.Minute,
86+
Delay: 30 * time.Second,
87+
MinTimeout: 15 * time.Second,
88+
}
89+
90+
if _, err = stateConf.WaitForState(); err != nil {
91+
return fmt.Errorf("Error attaching OpenStack volume: %s", err)
92+
}
93+
8194
log.Printf("[DEBUG] Created volume attachment: %#v", attachment)
8295

8396
// Use the instance ID and attachment ID as the resource ID.
@@ -131,7 +144,7 @@ func resourceComputeVolumeAttachV2Delete(d *schema.ResourceData, meta interface{
131144
stateConf := &resource.StateChangeConf{
132145
Pending: []string{""},
133146
Target: []string{"DETACHED"},
134-
Refresh: volumeDetachRefreshFunc(computeClient, instanceId, attachmentId),
147+
Refresh: resourceComputeVolumeAttachV2DetachFunc(computeClient, instanceId, attachmentId),
135148
Timeout: 10 * time.Minute,
136149
Delay: 15 * time.Second,
137150
MinTimeout: 15 * time.Second,
@@ -144,9 +157,26 @@ func resourceComputeVolumeAttachV2Delete(d *schema.ResourceData, meta interface{
144157
return nil
145158
}
146159

147-
func volumeDetachRefreshFunc(computeClient *gophercloud.ServiceClient, instanceId, attachmentId string) resource.StateRefreshFunc {
160+
func resourceComputeVolumeAttachV2AttachFunc(
161+
computeClient *gophercloud.ServiceClient, instanceId, attachmentId string) resource.StateRefreshFunc {
162+
return func() (interface{}, string, error) {
163+
va, err := volumeattach.Get(computeClient, instanceId, attachmentId).Extract()
164+
if err != nil {
165+
if _, ok := err.(gophercloud.ErrDefault404); ok {
166+
return va, "ATTACHING", nil
167+
}
168+
return va, "", err
169+
}
170+
171+
return va, "ATTACHED", nil
172+
}
173+
}
174+
175+
func resourceComputeVolumeAttachV2DetachFunc(
176+
computeClient *gophercloud.ServiceClient, instanceId, attachmentId string) resource.StateRefreshFunc {
148177
return func() (interface{}, string, error) {
149-
log.Printf("[DEBUG] Attempting to detach OpenStack volume %s from instance %s", attachmentId, instanceId)
178+
log.Printf("[DEBUG] Attempting to detach OpenStack volume %s from instance %s",
179+
attachmentId, instanceId)
150180

151181
va, err := volumeattach.Get(computeClient, instanceId, attachmentId).Extract()
152182
if err != nil {

builtin/providers/openstack/resource_openstack_compute_volume_attach_v2_test.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,25 @@ func TestAccComputeV2VolumeAttach_basic(t *testing.T) {
2828
})
2929
}
3030

31+
func TestAccComputeV2VolumeAttach_device(t *testing.T) {
32+
var va volumeattach.VolumeAttachment
33+
34+
resource.Test(t, resource.TestCase{
35+
PreCheck: func() { testAccPreCheck(t) },
36+
Providers: testAccProviders,
37+
CheckDestroy: testAccCheckComputeV2VolumeAttachDestroy,
38+
Steps: []resource.TestStep{
39+
resource.TestStep{
40+
Config: testAccComputeV2VolumeAttach_device,
41+
Check: resource.ComposeTestCheckFunc(
42+
testAccCheckComputeV2VolumeAttachExists("openstack_compute_volume_attach_v2.va_1", &va),
43+
testAccCheckComputeV2VolumeAttachDevice(&va, "/dev/vdc"),
44+
),
45+
},
46+
},
47+
})
48+
}
49+
3150
func testAccCheckComputeV2VolumeAttachDestroy(s *terraform.State) error {
3251
config := testAccProvider.Meta().(*Config)
3352
computeClient, err := config.computeV2Client(OS_REGION_NAME)
@@ -91,6 +110,18 @@ func testAccCheckComputeV2VolumeAttachExists(n string, va *volumeattach.VolumeAt
91110
}
92111
}
93112

113+
func testAccCheckComputeV2VolumeAttachDevice(
114+
va *volumeattach.VolumeAttachment, device string) resource.TestCheckFunc {
115+
return func(s *terraform.State) error {
116+
if va.Device != device {
117+
return fmt.Errorf("Requested device of volume attachment (%s) does not match: %s",
118+
device, va.Device)
119+
}
120+
121+
return nil
122+
}
123+
}
124+
94125
const testAccComputeV2VolumeAttach_basic = `
95126
resource "openstack_blockstorage_volume_v2" "volume_1" {
96127
name = "volume_1"
@@ -107,3 +138,21 @@ resource "openstack_compute_volume_attach_v2" "va_1" {
107138
volume_id = "${openstack_blockstorage_volume_v2.volume_1.id}"
108139
}
109140
`
141+
142+
const testAccComputeV2VolumeAttach_device = `
143+
resource "openstack_blockstorage_volume_v2" "volume_1" {
144+
name = "volume_1"
145+
size = 1
146+
}
147+
148+
resource "openstack_compute_instance_v2" "instance_1" {
149+
name = "instance_1"
150+
security_groups = ["default"]
151+
}
152+
153+
resource "openstack_compute_volume_attach_v2" "va_1" {
154+
instance_id = "${openstack_compute_instance_v2.instance_1.id}"
155+
volume_id = "${openstack_blockstorage_volume_v2.volume_1.id}"
156+
device = "/dev/vdc"
157+
}
158+
`

website/source/docs/providers/openstack/r/compute_volume_attach_v2.html.markdown

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,17 +43,23 @@ The following arguments are supported:
4343

4444
* `volume_id` - (Required) The ID of the Volume to attach to an Instance.
4545

46+
* `device` - (Optional) The device of the volume attachment (ex: `/dev/vdc`).
47+
_NOTE_: Being able to specify a device is dependent upon the hypervisor in
48+
use. There is a chance that the device specified in Terraform will not be
49+
the same device the hypervisor chose. If this happens, Terraform will wish
50+
to update the device upon subsequent applying which will cause the volume
51+
to be detached and reattached indefinitely. Please use with caution.
52+
4653
## Attributes Reference
4754

4855
The following attributes are exported:
4956

5057
* `region` - See Argument Reference above.
5158
* `instance_id` - See Argument Reference above.
5259
* `volume_id` - See Argument Reference above.
53-
* `device` - The device of the volume attachment (ex: `/dev/vdc`).
54-
_NOTE_: This is the device reported by the Compute API and the real device
55-
might actually differ depending on the hypervisor being used. This should
56-
not be used as an authoritative piece of information.
60+
* `device` - See Argument Reference above. _NOTE_: The correctness of this
61+
information is dependent upon the hypervisor in use. In some cases, this
62+
should not be used as an authoritative piece of information.
5763

5864
## Import
5965

0 commit comments

Comments
 (0)