github.com/vtorhonen/terraform@v0.9.0-beta2.0.20170307220345-5d894e4ffda7/builtin/providers/alicloud/resource_alicloud_disk_attachment.go (about)

     1  package alicloud
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  
     7  	"github.com/denverdino/aliyungo/common"
     8  	"github.com/denverdino/aliyungo/ecs"
     9  	"github.com/hashicorp/terraform/helper/resource"
    10  	"github.com/hashicorp/terraform/helper/schema"
    11  	"log"
    12  	"time"
    13  )
    14  
    15  func resourceAliyunDiskAttachment() *schema.Resource {
    16  	return &schema.Resource{
    17  		Create: resourceAliyunDiskAttachmentCreate,
    18  		Read:   resourceAliyunDiskAttachmentRead,
    19  		Delete: resourceAliyunDiskAttachmentDelete,
    20  
    21  		Schema: map[string]*schema.Schema{
    22  			"instance_id": &schema.Schema{
    23  				Type:     schema.TypeString,
    24  				Optional: true,
    25  				ForceNew: true,
    26  			},
    27  			"disk_id": &schema.Schema{
    28  				Type:     schema.TypeString,
    29  				Optional: true,
    30  				ForceNew: true,
    31  			},
    32  
    33  			"device_name": &schema.Schema{
    34  				Type:     schema.TypeString,
    35  				Optional: true,
    36  				Computed: true,
    37  				ForceNew: true,
    38  			},
    39  		},
    40  	}
    41  }
    42  
    43  func resourceAliyunDiskAttachmentCreate(d *schema.ResourceData, meta interface{}) error {
    44  
    45  	err := diskAttachment(d, meta)
    46  	if err != nil {
    47  		return err
    48  	}
    49  
    50  	d.SetId(d.Get("disk_id").(string) + ":" + d.Get("instance_id").(string))
    51  
    52  	return resourceAliyunDiskAttachmentRead(d, meta)
    53  }
    54  
    55  func resourceAliyunDiskAttachmentRead(d *schema.ResourceData, meta interface{}) error {
    56  	diskId, instanceId, err := getDiskIDAndInstanceID(d, meta)
    57  	if err != nil {
    58  		return err
    59  	}
    60  
    61  	conn := meta.(*AliyunClient).ecsconn
    62  	disks, _, err := conn.DescribeDisks(&ecs.DescribeDisksArgs{
    63  		RegionId:   getRegion(d, meta),
    64  		InstanceId: instanceId,
    65  		DiskIds:    []string{diskId},
    66  	})
    67  
    68  	if err != nil {
    69  		if notFoundError(err) {
    70  			d.SetId("")
    71  			return nil
    72  		}
    73  		return fmt.Errorf("Error DescribeDiskAttribute: %#v", err)
    74  	}
    75  
    76  	log.Printf("[DEBUG] DescribeDiskAttribute for instance: %#v", disks)
    77  	if disks == nil || len(disks) <= 0 {
    78  		return fmt.Errorf("No Disks Found.")
    79  	}
    80  
    81  	disk := disks[0]
    82  	d.Set("instance_id", disk.InstanceId)
    83  	d.Set("disk_id", disk.DiskId)
    84  	d.Set("device_name", disk.Device)
    85  
    86  	return nil
    87  }
    88  
    89  func resourceAliyunDiskAttachmentDelete(d *schema.ResourceData, meta interface{}) error {
    90  	conn := meta.(*AliyunClient).ecsconn
    91  	diskID, instanceID, err := getDiskIDAndInstanceID(d, meta)
    92  	if err != nil {
    93  		return err
    94  	}
    95  
    96  	return resource.Retry(5*time.Minute, func() *resource.RetryError {
    97  		err := conn.DetachDisk(instanceID, diskID)
    98  		if err != nil {
    99  			e, _ := err.(*common.Error)
   100  			if e.ErrorResponse.Code == DiskIncorrectStatus || e.ErrorResponse.Code == InstanceLockedForSecurity {
   101  				return resource.RetryableError(fmt.Errorf("Disk in use - trying again while it detaches"))
   102  			}
   103  		}
   104  
   105  		disks, _, descErr := conn.DescribeDisks(&ecs.DescribeDisksArgs{
   106  			RegionId: getRegion(d, meta),
   107  			DiskIds:  []string{diskID},
   108  		})
   109  
   110  		if descErr != nil {
   111  			log.Printf("[ERROR] Disk %s is not detached.", diskID)
   112  			return resource.NonRetryableError(err)
   113  		}
   114  
   115  		for _, disk := range disks {
   116  			if disk.Status != ecs.DiskStatusAvailable {
   117  				return resource.RetryableError(fmt.Errorf("Disk in use - trying again while it is deleted."))
   118  			}
   119  		}
   120  		return nil
   121  	})
   122  }
   123  
   124  func getDiskIDAndInstanceID(d *schema.ResourceData, meta interface{}) (string, string, error) {
   125  	parts := strings.Split(d.Id(), ":")
   126  
   127  	if len(parts) != 2 {
   128  		return "", "", fmt.Errorf("invalid resource id")
   129  	}
   130  	return parts[0], parts[1], nil
   131  }
   132  func diskAttachment(d *schema.ResourceData, meta interface{}) error {
   133  	conn := meta.(*AliyunClient).ecsconn
   134  
   135  	diskID := d.Get("disk_id").(string)
   136  	instanceID := d.Get("instance_id").(string)
   137  
   138  	deviceName := d.Get("device_name").(string)
   139  
   140  	args := &ecs.AttachDiskArgs{
   141  		InstanceId: instanceID,
   142  		DiskId:     diskID,
   143  		Device:     deviceName,
   144  	}
   145  
   146  	return resource.Retry(5*time.Minute, func() *resource.RetryError {
   147  		err := conn.AttachDisk(args)
   148  		log.Printf("error : %s", err)
   149  
   150  		if err != nil {
   151  			e, _ := err.(*common.Error)
   152  			if e.ErrorResponse.Code == DiskIncorrectStatus || e.ErrorResponse.Code == InstanceIncorrectStatus {
   153  				return resource.RetryableError(fmt.Errorf("Disk or Instance status is incorrect - trying again while it attaches"))
   154  			}
   155  			return resource.NonRetryableError(err)
   156  		}
   157  
   158  		disks, _, descErr := conn.DescribeDisks(&ecs.DescribeDisksArgs{
   159  			RegionId:   getRegion(d, meta),
   160  			InstanceId: instanceID,
   161  			DiskIds:    []string{diskID},
   162  		})
   163  
   164  		if descErr != nil {
   165  			log.Printf("[ERROR] Disk %s is not attached.", diskID)
   166  			return resource.NonRetryableError(err)
   167  		}
   168  
   169  		if disks == nil || len(disks) <= 0 {
   170  			return resource.RetryableError(fmt.Errorf("Disk in attaching - trying again while it is attached."))
   171  		}
   172  
   173  		return nil
   174  
   175  	})
   176  }