Skip to content

Commit bdb3500

Browse files
author
Sander van Harmelen
committed
Fix several bugs in different resources
- Make sure attaching a disk or a NIC is tried a couple of times as this only works after the OS has fully booted; - Stop using the device name instead of ID as the names differ depending on the hypervisor that you are using; - VPC’s do not always have a source NAT IP;
1 parent 9ddeb70 commit bdb3500

4 files changed

Lines changed: 30 additions & 162 deletions

File tree

builtin/providers/cloudstack/resource_cloudstack_disk.go

Lines changed: 11 additions & 151 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ func resourceCloudStackDisk() *schema.Resource {
2828
Default: false,
2929
},
3030

31-
"device": &schema.Schema{
32-
Type: schema.TypeString,
31+
"device_id": &schema.Schema{
32+
Type: schema.TypeInt,
3333
Optional: true,
3434
Computed: true,
3535
},
@@ -116,7 +116,7 @@ func resourceCloudStackDiskCreate(d *schema.ResourceData, meta interface{}) erro
116116
// Set the volume ID and partials
117117
d.SetId(r.Id)
118118
d.SetPartial("name")
119-
d.SetPartial("device")
119+
d.SetPartial("device_id")
120120
d.SetPartial("disk_offering")
121121
d.SetPartial("size")
122122
d.SetPartial("virtual_machine_id")
@@ -163,28 +163,7 @@ func resourceCloudStackDiskRead(d *schema.ResourceData, meta interface{}) error
163163
setValueOrID(d, "zone", v.Zonename, v.Zoneid)
164164

165165
if v.Attached != "" {
166-
// Get the virtual machine details
167-
vm, _, err := cs.VirtualMachine.GetVirtualMachineByID(
168-
v.Virtualmachineid,
169-
cloudstack.WithProject(d.Get("project").(string)),
170-
)
171-
if err != nil {
172-
return err
173-
}
174-
175-
// Get the guest OS type details
176-
os, _, err := cs.GuestOS.GetOsTypeByID(vm.Guestosid)
177-
if err != nil {
178-
return err
179-
}
180-
181-
// Get the guest OS category details
182-
c, _, err := cs.GuestOS.GetOsCategoryByID(os.Oscategoryid)
183-
if err != nil {
184-
return err
185-
}
186-
187-
d.Set("device", retrieveDeviceName(v.Deviceid, c.Name))
166+
d.Set("device_id", int(v.Deviceid))
188167
d.Set("virtual_machine_id", v.Virtualmachineid)
189168
}
190169

@@ -235,9 +214,9 @@ func resourceCloudStackDiskUpdate(d *schema.ResourceData, meta interface{}) erro
235214
d.SetPartial("size")
236215
}
237216

238-
// If the device changed, just detach here so we can re-attach the
217+
// If the device ID changed, just detach here so we can re-attach the
239218
// volume at the end of this function
240-
if d.HasChange("device") || d.HasChange("virtual_machine") {
219+
if d.HasChange("device_id") || d.HasChange("virtual_machine") {
241220
// Detach the volume
242221
if err := resourceCloudStackDiskDetach(d, meta); err != nil {
243222
return fmt.Errorf("Error detaching disk %s from virtual machine: %s", name, err)
@@ -253,7 +232,7 @@ func resourceCloudStackDiskUpdate(d *schema.ResourceData, meta interface{}) erro
253232

254233
// Set the additional partials
255234
d.SetPartial("attach")
256-
d.SetPartial("device")
235+
d.SetPartial("device_id")
257236
d.SetPartial("virtual_machine_id")
258237
} else {
259238
// Detach the volume
@@ -304,21 +283,14 @@ func resourceCloudStackDiskAttach(d *schema.ResourceData, meta interface{}) erro
304283
// Create a new parameter struct
305284
p := cs.Volume.NewAttachVolumeParams(d.Id(), virtualmachineid.(string))
306285

307-
if device, ok := d.GetOk("device"); ok {
308-
// Retrieve the device ID
309-
deviceid := retrieveDeviceID(device.(string))
310-
if deviceid == -1 {
311-
return fmt.Errorf("Device %s is not a valid device", device.(string))
312-
}
313-
314-
// Set the device ID
315-
p.SetDeviceid(deviceid)
286+
if deviceid, ok := d.GetOk("device_id"); ok {
287+
p.SetDeviceid(int64(deviceid.(int)))
316288
}
317289

318290
// Attach the new volume
319-
r, err := Retry(4, retryableAttachVolumeFunc(cs, p))
291+
r, err := Retry(10, retryableAttachVolumeFunc(cs, p))
320292
if err != nil {
321-
return err
293+
return fmt.Errorf("Error attaching volume to VM: %s", err)
322294
}
323295

324296
d.SetId(r.(*cloudstack.AttachVolumeResponse).Id)
@@ -397,115 +369,3 @@ func retryableAttachVolumeFunc(
397369
return r, nil
398370
}
399371
}
400-
401-
func retrieveDeviceID(device string) int64 {
402-
switch device {
403-
case "/dev/xvdb", "D:":
404-
return 1
405-
case "/dev/xvdc", "E:":
406-
return 2
407-
case "/dev/xvde", "F:":
408-
return 4
409-
case "/dev/xvdf", "G:":
410-
return 5
411-
case "/dev/xvdg", "H:":
412-
return 6
413-
case "/dev/xvdh", "I:":
414-
return 7
415-
case "/dev/xvdi", "J:":
416-
return 8
417-
case "/dev/xvdj", "K:":
418-
return 9
419-
case "/dev/xvdk", "L:":
420-
return 10
421-
case "/dev/xvdl", "M:":
422-
return 11
423-
case "/dev/xvdm", "N:":
424-
return 12
425-
case "/dev/xvdn", "O:":
426-
return 13
427-
case "/dev/xvdo", "P:":
428-
return 14
429-
case "/dev/xvdp", "Q:":
430-
return 15
431-
default:
432-
return -1
433-
}
434-
}
435-
436-
func retrieveDeviceName(device int64, os string) string {
437-
switch device {
438-
case 1:
439-
if os == "Windows" {
440-
return "D:"
441-
}
442-
return "/dev/xvdb"
443-
case 2:
444-
if os == "Windows" {
445-
return "E:"
446-
}
447-
return "/dev/xvdc"
448-
case 4:
449-
if os == "Windows" {
450-
return "F:"
451-
}
452-
return "/dev/xvde"
453-
case 5:
454-
if os == "Windows" {
455-
return "G:"
456-
}
457-
return "/dev/xvdf"
458-
case 6:
459-
if os == "Windows" {
460-
return "H:"
461-
}
462-
return "/dev/xvdg"
463-
case 7:
464-
if os == "Windows" {
465-
return "I:"
466-
}
467-
return "/dev/xvdh"
468-
case 8:
469-
if os == "Windows" {
470-
return "J:"
471-
}
472-
return "/dev/xvdi"
473-
case 9:
474-
if os == "Windows" {
475-
return "K:"
476-
}
477-
return "/dev/xvdj"
478-
case 10:
479-
if os == "Windows" {
480-
return "L:"
481-
}
482-
return "/dev/xvdk"
483-
case 11:
484-
if os == "Windows" {
485-
return "M:"
486-
}
487-
return "/dev/xvdl"
488-
case 12:
489-
if os == "Windows" {
490-
return "N:"
491-
}
492-
return "/dev/xvdm"
493-
case 13:
494-
if os == "Windows" {
495-
return "O:"
496-
}
497-
return "/dev/xvdn"
498-
case 14:
499-
if os == "Windows" {
500-
return "P:"
501-
}
502-
return "/dev/xvdo"
503-
case 15:
504-
if os == "Windows" {
505-
return "Q:"
506-
}
507-
return "/dev/xvdp"
508-
default:
509-
return "unknown"
510-
}
511-
}

builtin/providers/cloudstack/resource_cloudstack_disk_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ func TestAccCloudStackDisk_basic(t *testing.T) {
2929
})
3030
}
3131

32-
func TestAccCloudStackDisk_device(t *testing.T) {
32+
func TestAccCloudStackDisk_deviceID(t *testing.T) {
3333
var disk cloudstack.Volume
3434

3535
resource.Test(t, resource.TestCase{
@@ -38,13 +38,13 @@ func TestAccCloudStackDisk_device(t *testing.T) {
3838
CheckDestroy: testAccCheckCloudStackDiskDestroy,
3939
Steps: []resource.TestStep{
4040
resource.TestStep{
41-
Config: testAccCloudStackDisk_device,
41+
Config: testAccCloudStackDisk_deviceID,
4242
Check: resource.ComposeTestCheckFunc(
4343
testAccCheckCloudStackDiskExists(
4444
"cloudstack_disk.foo", &disk),
4545
testAccCheckCloudStackDiskAttributes(&disk),
4646
resource.TestCheckResourceAttr(
47-
"cloudstack_disk.foo", "device", "/dev/xvde"),
47+
"cloudstack_disk.foo", "device_id", "4"),
4848
),
4949
},
5050
},
@@ -170,7 +170,7 @@ resource "cloudstack_disk" "foo" {
170170
CLOUDSTACK_DISK_OFFERING_1,
171171
CLOUDSTACK_ZONE)
172172

173-
var testAccCloudStackDisk_device = fmt.Sprintf(`
173+
var testAccCloudStackDisk_deviceID = fmt.Sprintf(`
174174
resource "cloudstack_instance" "foobar" {
175175
name = "terraform-test"
176176
display_name = "terraform"
@@ -184,7 +184,7 @@ resource "cloudstack_instance" "foobar" {
184184
resource "cloudstack_disk" "foo" {
185185
name = "terraform-disk"
186186
attach = true
187-
device = "/dev/xvde"
187+
device_id = 4
188188
disk_offering = "%s"
189189
virtual_machine_id = "${cloudstack_instance.foobar.id}"
190190
zone = "${cloudstack_instance.foobar.zone}"

builtin/providers/cloudstack/resource_cloudstack_nic.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,13 @@ func resourceCloudStackNICCreate(d *schema.ResourceData, meta interface{}) error
5353
}
5454

5555
// Create and attach the new NIC
56-
r, err := cs.VirtualMachine.AddNicToVirtualMachine(p)
56+
r, err := Retry(10, retryableAddNicFunc(cs, p))
5757
if err != nil {
5858
return fmt.Errorf("Error creating the new NIC: %s", err)
5959
}
6060

6161
found := false
62-
for _, n := range r.Nic {
62+
for _, n := range r.(*cloudstack.AddNicToVirtualMachineResponse).Nic {
6363
if n.Networkid == d.Get("network_id").(string) {
6464
d.SetId(n.Id)
6565
found = true
@@ -133,3 +133,13 @@ func resourceCloudStackNICDelete(d *schema.ResourceData, meta interface{}) error
133133

134134
return nil
135135
}
136+
137+
func retryableAddNicFunc(cs *cloudstack.CloudStackClient, p *cloudstack.AddNicToVirtualMachineParams) func() (interface{}, error) {
138+
return func() (interface{}, error) {
139+
r, err := cs.VirtualMachine.AddNicToVirtualMachine(p)
140+
if err != nil {
141+
return nil, err
142+
}
143+
return r, nil
144+
}
145+
}

builtin/providers/cloudstack/resource_cloudstack_vpc.go

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -171,12 +171,10 @@ func resourceCloudStackVPCRead(d *schema.ResourceData, meta interface{}) error {
171171
return err
172172
}
173173

174-
if l.Count != 1 {
175-
return fmt.Errorf("Unexpected number (%d) of source NAT IPs returned", l.Count)
174+
if l.Count == 1 {
175+
d.Set("source_nat_ip", l.PublicIpAddresses[0].Ipaddress)
176176
}
177177

178-
d.Set("source_nat_ip", l.PublicIpAddresses[0].Ipaddress)
179-
180178
return nil
181179
}
182180

0 commit comments

Comments
 (0)