@@ -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