Skip to content

Commit 1e32af4

Browse files
committed
Add the ability to attach disks to VMs on creation, to prevent timing issues
1 parent a653531 commit 1e32af4

File tree

2 files changed

+104
-5
lines changed

2 files changed

+104
-5
lines changed

cloudstack/resource_cloudstack_disk.go

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,12 @@ func resourceCloudStackDisk() *schema.Resource {
9292
ForceNew: true,
9393
},
9494

95+
"data_disk_scan": {
96+
Type: schema.TypeBool,
97+
Optional: true,
98+
Default: true,
99+
},
100+
95101
"tags": tagsSchema(),
96102

97103
"reattach_on_change": {
@@ -195,9 +201,12 @@ func resourceCloudStackDiskRead(d *schema.ResourceData, meta interface{}) error
195201
setValueOrID(d, "project", v.Project, v.Projectid)
196202
setValueOrID(d, "zone", v.Zonename, v.Zoneid)
197203

198-
if v.Virtualmachineid != "" {
199-
d.Set("device_id", int(v.Deviceid))
200-
d.Set("virtual_machine_id", v.Virtualmachineid)
204+
if d.Get("data_disk_scan").(bool) {
205+
d.Set("attach", v.Virtualmachineid != "") // If attached this contains a virtual machine ID
206+
if v.Virtualmachineid != "" {
207+
d.Set("device_id", int(v.Deviceid))
208+
d.Set("virtual_machine_id", v.Virtualmachineid)
209+
}
201210
}
202211

203212
return nil

cloudstack/resource_cloudstack_instance.go

Lines changed: 92 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,14 @@ func resourceCloudStackInstance() *schema.Resource {
175175
ForceNew: true,
176176
},
177177

178+
"data_disks": {
179+
Type: schema.TypeSet,
180+
Optional: true,
181+
ForceNew: true,
182+
Elem: &schema.Schema{Type: schema.TypeString},
183+
Set: schema.HashString,
184+
},
185+
178186
"user_data": {
179187
Type: schema.TypeString,
180188
Optional: true,
@@ -215,6 +223,12 @@ func resourceCloudStackInstance() *schema.Resource {
215223
Optional: true,
216224
},
217225

226+
"data_disk_scan": {
227+
Type: schema.TypeBool,
228+
Optional: true,
229+
Default: false,
230+
},
231+
218232
"tags": tagsSchema(),
219233
},
220234
}
@@ -405,6 +419,17 @@ func resourceCloudStackInstanceCreate(d *schema.ResourceData, meta interface{})
405419

406420
d.SetId(r.Id)
407421

422+
// If there are data disk IDs supplied, attach them
423+
if dataDiskIDs := d.Get("data_disks").(*schema.Set); dataDiskIDs.Len() > 0 {
424+
for _, dataDisk := range dataDiskIDs.List() {
425+
pv := cs.Volume.NewAttachVolumeParams(dataDisk.(string), r.Id)
426+
_, err := Retry(10, retryableAttachVolumeFunc(cs, pv))
427+
if err != nil {
428+
return fmt.Errorf("Error attaching volume to VM: %s", err)
429+
}
430+
}
431+
}
432+
408433
// Set tags if necessary
409434
if err = setTags(cs, d, "userVm"); err != nil {
410435
return fmt.Errorf("Error setting tags on the new instance %s: %s", name, err)
@@ -467,6 +492,27 @@ func resourceCloudStackInstanceRead(d *schema.ResourceData, meta interface{}) er
467492
d.Set("root_disk_size", l.Volumes[0].Size>>30) // B to GiB
468493
}
469494

495+
if d.Get("data_disk_scan").(bool) {
496+
p = cs.Volume.NewListVolumesParams()
497+
p.SetType("DATADISK")
498+
p.SetVirtualmachineid(d.Id())
499+
p.SetProjectid(d.Get("project").(string))
500+
501+
// Get the data disks of the instance.
502+
volumes, err := cs.Volume.ListVolumes(p)
503+
if err != nil {
504+
return err
505+
}
506+
507+
if _, ok := d.GetOk("data_disks"); !ok {
508+
dataDisks := &schema.Set{F: schema.HashString}
509+
for _, v := range volumes.Volumes {
510+
dataDisks.Add(v.Id)
511+
}
512+
d.Set("data_disks", dataDisks)
513+
}
514+
}
515+
470516
if _, ok := d.GetOk("affinity_group_ids"); ok {
471517
groups := &schema.Set{F: schema.HashString}
472518
for _, group := range vm.Affinitygroup {
@@ -553,9 +599,31 @@ func resourceCloudStackInstanceUpdate(d *schema.ResourceData, meta interface{})
553599

554600
}
555601

602+
var keypairTrigger bool
603+
var keypairsTrigger bool
604+
var userdataTrigger bool
605+
606+
// Import doesn't get user_data, so just use it if is "import"
607+
oldUD, _ := d.GetChange("user_data")
608+
if oldUD != nil && oldUD.(string) == "import" {
609+
userdataTrigger = false
610+
} else {
611+
userdataTrigger = d.HasChange("user_data")
612+
}
613+
614+
// Import doesn't get keypair, so just use it if is "import"
615+
oldKP, _ := d.GetChange("keypair")
616+
if oldKP != nil && oldKP.(string) == "import" {
617+
keypairTrigger = false
618+
keypairsTrigger = false
619+
} else {
620+
keypairTrigger = d.HasChange("keypair")
621+
keypairsTrigger = d.HasChange("keypairs")
622+
}
623+
556624
// Attributes that require reboot to update
557625
if d.HasChange("name") || d.HasChange("service_offering") || d.HasChange("affinity_group_ids") ||
558-
d.HasChange("affinity_group_names") || d.HasChange("keypair") || d.HasChange("keypairs") || d.HasChange("user_data") {
626+
d.HasChange("affinity_group_names") || keypairTrigger || keypairsTrigger || userdataTrigger {
559627

560628
// Before we can actually make these changes, the virtual machine must be stopped
561629
_, err := cs.VirtualMachine.StopVirtualMachine(
@@ -768,7 +836,29 @@ func resourceCloudStackInstanceImport(d *schema.ResourceData, meta interface{})
768836
// We set start_vm to true as that matches the default and we assume that
769837
// when you need to import an instance it means it is already running.
770838
d.Set("start_vm", true)
771-
return importStatePassthrough(d, meta)
839+
s := strings.SplitN(d.Id(), "/", 4)
840+
if len(s) >= 2 {
841+
d.Set("project", s[0])
842+
}
843+
844+
// We need to determine if we should scan for data disks, but if it doesn't exist, just leave it as the default
845+
if len(s) >= 3 {
846+
d.Set("data_disk_scan", s[1] == "true")
847+
if len(s) >= 4 {
848+
dataDisks := &schema.Set{F: schema.HashString}
849+
for _, disk := range strings.Split(s[2], ",") {
850+
dataDisks.Add(disk)
851+
}
852+
d.Set("data_disks", dataDisks)
853+
}
854+
}
855+
856+
d.Set("keypair", "import")
857+
d.Set("user_data", "import")
858+
859+
d.SetId(s[len(s)-1])
860+
861+
return []*schema.ResourceData{d}, nil
772862
}
773863

774864
// getUserData returns the user data as a base64 encoded string

0 commit comments

Comments
 (0)