github.com/vtorhonen/terraform@v0.9.0-beta2.0.20170307220345-5d894e4ffda7/builtin/providers/alicloud/resource_alicloud_disk.go (about) 1 package alicloud 2 3 import ( 4 "fmt" 5 6 "github.com/denverdino/aliyungo/common" 7 "github.com/denverdino/aliyungo/ecs" 8 "github.com/hashicorp/terraform/helper/resource" 9 "github.com/hashicorp/terraform/helper/schema" 10 "log" 11 "time" 12 ) 13 14 func resourceAliyunDisk() *schema.Resource { 15 return &schema.Resource{ 16 Create: resourceAliyunDiskCreate, 17 Read: resourceAliyunDiskRead, 18 Update: resourceAliyunDiskUpdate, 19 Delete: resourceAliyunDiskDelete, 20 21 Schema: map[string]*schema.Schema{ 22 "availability_zone": &schema.Schema{ 23 Type: schema.TypeString, 24 Required: true, 25 ForceNew: true, 26 }, 27 "name": &schema.Schema{ 28 Type: schema.TypeString, 29 Optional: true, 30 ValidateFunc: validateDiskName, 31 }, 32 33 "description": &schema.Schema{ 34 Type: schema.TypeString, 35 Optional: true, 36 ValidateFunc: validateDiskDescription, 37 }, 38 39 "category": &schema.Schema{ 40 Type: schema.TypeString, 41 Optional: true, 42 ForceNew: true, 43 ValidateFunc: validateDiskCategory, 44 Default: "cloud", 45 }, 46 47 "size": &schema.Schema{ 48 Type: schema.TypeInt, 49 Optional: true, 50 }, 51 52 "snapshot_id": &schema.Schema{ 53 Type: schema.TypeString, 54 Optional: true, 55 }, 56 57 "status": &schema.Schema{ 58 Type: schema.TypeString, 59 Computed: true, 60 }, 61 62 "tags": tagsSchema(), 63 }, 64 } 65 } 66 67 func resourceAliyunDiskCreate(d *schema.ResourceData, meta interface{}) error { 68 client := meta.(*AliyunClient) 69 70 conn := client.ecsconn 71 72 availabilityZone, err := client.DescribeZone(d.Get("availability_zone").(string)) 73 if err != nil { 74 return err 75 } 76 77 args := &ecs.CreateDiskArgs{ 78 RegionId: getRegion(d, meta), 79 ZoneId: availabilityZone.ZoneId, 80 } 81 82 if v, ok := d.GetOk("category"); ok && v.(string) != "" { 83 category := ecs.DiskCategory(v.(string)) 84 if err := client.DiskAvailable(availabilityZone, category); err != nil { 85 return err 86 } 87 args.DiskCategory = category 88 } 89 90 if v, ok := d.GetOk("size"); ok { 91 size := v.(int) 92 if args.DiskCategory == ecs.DiskCategoryCloud && (size < 5 || size > 2000) { 93 return fmt.Errorf("the size of cloud disk must between 5 to 2000") 94 } 95 96 if (args.DiskCategory == ecs.DiskCategoryCloudEfficiency || 97 args.DiskCategory == ecs.DiskCategoryCloudSSD) && (size < 20 || size > 32768) { 98 return fmt.Errorf("the size of %s disk must between 20 to 32768", args.DiskCategory) 99 } 100 args.Size = size 101 102 d.Set("size", args.Size) 103 } 104 105 if v, ok := d.GetOk("snapshot_id"); ok && v.(string) != "" { 106 args.SnapshotId = v.(string) 107 } 108 109 if args.Size <= 0 && args.SnapshotId == "" { 110 return fmt.Errorf("One of size or snapshot_id is required when specifying an ECS disk.") 111 } 112 113 if v, ok := d.GetOk("name"); ok && v.(string) != "" { 114 args.DiskName = v.(string) 115 } 116 117 if v, ok := d.GetOk("description"); ok && v.(string) != "" { 118 args.Description = v.(string) 119 } 120 121 diskID, err := conn.CreateDisk(args) 122 if err != nil { 123 return fmt.Errorf("CreateDisk got a error: %#v", err) 124 } 125 126 d.SetId(diskID) 127 128 return resourceAliyunDiskUpdate(d, meta) 129 } 130 131 func resourceAliyunDiskRead(d *schema.ResourceData, meta interface{}) error { 132 conn := meta.(*AliyunClient).ecsconn 133 134 disks, _, err := conn.DescribeDisks(&ecs.DescribeDisksArgs{ 135 RegionId: getRegion(d, meta), 136 DiskIds: []string{d.Id()}, 137 }) 138 139 if err != nil { 140 if notFoundError(err) { 141 d.SetId("") 142 return nil 143 } 144 return fmt.Errorf("Error DescribeDiskAttribute: %#v", err) 145 } 146 147 log.Printf("[DEBUG] DescribeDiskAttribute for instance: %#v", disks) 148 149 if disks == nil || len(disks) <= 0 { 150 return fmt.Errorf("No disks found.") 151 } 152 153 disk := disks[0] 154 d.Set("availability_zone", disk.ZoneId) 155 d.Set("category", disk.Category) 156 d.Set("size", disk.Size) 157 d.Set("status", disk.Status) 158 d.Set("name", disk.DiskName) 159 d.Set("description", disk.Description) 160 d.Set("snapshot_id", disk.SourceSnapshotId) 161 162 tags, _, err := conn.DescribeTags(&ecs.DescribeTagsArgs{ 163 RegionId: getRegion(d, meta), 164 ResourceType: ecs.TagResourceDisk, 165 ResourceId: d.Id(), 166 }) 167 168 if err != nil { 169 log.Printf("[DEBUG] DescribeTags for disk got error: %#v", err) 170 } 171 172 d.Set("tags", tagsToMap(tags)) 173 174 return nil 175 } 176 177 func resourceAliyunDiskUpdate(d *schema.ResourceData, meta interface{}) error { 178 client := meta.(*AliyunClient) 179 conn := client.ecsconn 180 181 d.Partial(true) 182 183 if err := setTags(client, ecs.TagResourceDisk, d); err != nil { 184 log.Printf("[DEBUG] Set tags for instance got error: %#v", err) 185 return fmt.Errorf("Set tags for instance got error: %#v", err) 186 } else { 187 d.SetPartial("tags") 188 } 189 attributeUpdate := false 190 args := &ecs.ModifyDiskAttributeArgs{ 191 DiskId: d.Id(), 192 } 193 194 if d.HasChange("name") { 195 d.SetPartial("name") 196 val := d.Get("name").(string) 197 args.DiskName = val 198 199 attributeUpdate = true 200 } 201 202 if d.HasChange("description") { 203 d.SetPartial("description") 204 val := d.Get("description").(string) 205 args.Description = val 206 207 attributeUpdate = true 208 } 209 if attributeUpdate { 210 if err := conn.ModifyDiskAttribute(args); err != nil { 211 return err 212 } 213 } 214 215 d.Partial(false) 216 217 return resourceAliyunDiskRead(d, meta) 218 } 219 220 func resourceAliyunDiskDelete(d *schema.ResourceData, meta interface{}) error { 221 conn := meta.(*AliyunClient).ecsconn 222 223 return resource.Retry(5*time.Minute, func() *resource.RetryError { 224 err := conn.DeleteDisk(d.Id()) 225 if err != nil { 226 e, _ := err.(*common.Error) 227 if e.ErrorResponse.Code == DiskIncorrectStatus || e.ErrorResponse.Code == DiskCreatingSnapshot { 228 return resource.RetryableError(fmt.Errorf("Disk in use - trying again while it is deleted.")) 229 } 230 } 231 232 disks, _, descErr := conn.DescribeDisks(&ecs.DescribeDisksArgs{ 233 RegionId: getRegion(d, meta), 234 DiskIds: []string{d.Id()}, 235 }) 236 237 if descErr != nil { 238 log.Printf("[ERROR] Delete disk is failed.") 239 return resource.NonRetryableError(descErr) 240 } 241 if disks == nil || len(disks) < 1 { 242 return nil 243 } 244 245 return resource.RetryableError(fmt.Errorf("Disk in use - trying again while it is deleted.")) 246 }) 247 }