github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/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 }