github.com/richardbowden/terraform@v0.6.12-0.20160901200758-30ea22c25211/builtin/providers/vsphere/resource_vsphere_virtual_disk.go (about) 1 package vsphere 2 3 import ( 4 "fmt" 5 "log" 6 7 "github.com/hashicorp/terraform/helper/schema" 8 "github.com/vmware/govmomi" 9 "github.com/vmware/govmomi/find" 10 "github.com/vmware/govmomi/object" 11 "github.com/vmware/govmomi/vim25/types" 12 "golang.org/x/net/context" 13 ) 14 15 type virtualDisk struct { 16 size int 17 vmdkPath string 18 initType string 19 adapterType string 20 datacenter string 21 datastore string 22 } 23 24 // Define VirtualDisk args 25 func resourceVSphereVirtualDisk() *schema.Resource { 26 return &schema.Resource{ 27 Create: resourceVSphereVirtualDiskCreate, 28 Read: resourceVSphereVirtualDiskRead, 29 Delete: resourceVSphereVirtualDiskDelete, 30 31 Schema: map[string]*schema.Schema{ 32 // Size in GB 33 "size": &schema.Schema{ 34 Type: schema.TypeInt, 35 Required: true, 36 ForceNew: true, //TODO Can this be optional (resize)? 37 }, 38 39 "vmdk_path": &schema.Schema{ 40 Type: schema.TypeString, 41 Required: true, 42 ForceNew: true, //TODO Can this be optional (move)? 43 }, 44 45 "type": &schema.Schema{ 46 Type: schema.TypeString, 47 Optional: true, 48 ForceNew: true, 49 Default: "eagerZeroedThick", 50 ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) { 51 value := v.(string) 52 if value != "thin" && value != "eagerZeroedThick" && value != "lazy" { 53 errors = append(errors, fmt.Errorf( 54 "only 'thin', 'eagerZeroedThick', and 'lazy' are supported values for 'type'")) 55 } 56 return 57 }, 58 }, 59 60 "adapter_type": &schema.Schema{ 61 Type: schema.TypeString, 62 Optional: true, 63 ForceNew: true, 64 Default: "ide", 65 ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) { 66 value := v.(string) 67 if value != "ide" && value != "busLogic" && value != "lsiLogic" { 68 errors = append(errors, fmt.Errorf( 69 "only 'ide', 'busLogic', and 'lsiLogic' are supported values for 'adapter_type'")) 70 } 71 return 72 }, 73 }, 74 75 "datacenter": &schema.Schema{ 76 Type: schema.TypeString, 77 Optional: true, 78 ForceNew: true, 79 }, 80 81 "datastore": &schema.Schema{ 82 Type: schema.TypeString, 83 Optional: true, 84 ForceNew: true, 85 }, 86 }, 87 } 88 } 89 90 func resourceVSphereVirtualDiskCreate(d *schema.ResourceData, meta interface{}) error { 91 log.Printf("[INFO] Creating Virtual Disk") 92 client := meta.(*govmomi.Client) 93 94 vDisk := virtualDisk{ 95 size: d.Get("size").(int), 96 } 97 98 if v, ok := d.GetOk("vmdk_path"); ok { 99 vDisk.vmdkPath = v.(string) 100 } 101 102 if v, ok := d.GetOk("type"); ok { 103 vDisk.initType = v.(string) 104 } 105 106 if v, ok := d.GetOk("adapter_type"); ok { 107 vDisk.adapterType = v.(string) 108 } 109 110 if v, ok := d.GetOk("datacenter"); ok { 111 vDisk.datacenter = v.(string) 112 } 113 114 if v, ok := d.GetOk("datastore"); ok { 115 vDisk.datastore = v.(string) 116 } 117 118 finder := find.NewFinder(client.Client, true) 119 120 dc, err := getDatacenter(client, d.Get("datacenter").(string)) 121 if err != nil { 122 return fmt.Errorf("Error finding Datacenter: %s: %s", vDisk.datacenter, err) 123 } 124 finder = finder.SetDatacenter(dc) 125 126 ds, err := getDatastore(finder, vDisk.datastore) 127 if err != nil { 128 return fmt.Errorf("Error finding Datastore: %s: %s", vDisk.datastore, err) 129 } 130 131 err = createHardDisk(client, vDisk.size, ds.Path(vDisk.vmdkPath), vDisk.initType, vDisk.adapterType, vDisk.datacenter) 132 if err != nil { 133 return err 134 } 135 136 d.SetId(ds.Path(vDisk.vmdkPath)) 137 log.Printf("[DEBUG] Virtual Disk id: %v", ds.Path(vDisk.vmdkPath)) 138 139 return resourceVSphereVirtualDiskRead(d, meta) 140 } 141 142 func resourceVSphereVirtualDiskRead(d *schema.ResourceData, meta interface{}) error { 143 log.Printf("[DEBUG] Reading virtual disk.") 144 client := meta.(*govmomi.Client) 145 146 vDisk := virtualDisk{ 147 size: d.Get("size").(int), 148 } 149 150 if v, ok := d.GetOk("vmdk_path"); ok { 151 vDisk.vmdkPath = v.(string) 152 } 153 154 if v, ok := d.GetOk("type"); ok { 155 vDisk.initType = v.(string) 156 } 157 158 if v, ok := d.GetOk("adapter_type"); ok { 159 vDisk.adapterType = v.(string) 160 } 161 162 if v, ok := d.GetOk("datacenter"); ok { 163 vDisk.datacenter = v.(string) 164 } 165 166 if v, ok := d.GetOk("datastore"); ok { 167 vDisk.datastore = v.(string) 168 } 169 170 dc, err := getDatacenter(client, d.Get("datacenter").(string)) 171 if err != nil { 172 return err 173 } 174 175 finder := find.NewFinder(client.Client, true) 176 finder = finder.SetDatacenter(dc) 177 178 ds, err := finder.Datastore(context.TODO(), d.Get("datastore").(string)) 179 if err != nil { 180 return err 181 } 182 183 fileInfo, err := ds.Stat(context.TODO(), vDisk.vmdkPath) 184 if err != nil { 185 log.Printf("[DEBUG] resourceVSphereVirtualDiskRead - stat failed on: %v", vDisk.vmdkPath) 186 d.SetId("") 187 188 _, ok := err.(object.DatastoreNoSuchFileError) 189 if !ok { 190 return err 191 } 192 return nil 193 } 194 fileInfo = fileInfo.GetFileInfo() 195 log.Printf("[DEBUG] resourceVSphereVirtualDiskRead - fileinfo: %#v", fileInfo) 196 size := fileInfo.(*types.FileInfo).FileSize / 1024 / 1024 / 1024 197 198 d.SetId(vDisk.vmdkPath) 199 200 d.Set("size", size) 201 d.Set("vmdk_path", vDisk.vmdkPath) 202 d.Set("datacenter", d.Get("datacenter")) 203 d.Set("datastore", d.Get("datastore")) 204 // Todo collect and write type info 205 206 return nil 207 208 } 209 210 func resourceVSphereVirtualDiskDelete(d *schema.ResourceData, meta interface{}) error { 211 client := meta.(*govmomi.Client) 212 213 vDisk := virtualDisk{} 214 215 if v, ok := d.GetOk("vmdk_path"); ok { 216 vDisk.vmdkPath = v.(string) 217 } 218 if v, ok := d.GetOk("datastore"); ok { 219 vDisk.datastore = v.(string) 220 } 221 222 dc, err := getDatacenter(client, d.Get("datacenter").(string)) 223 if err != nil { 224 return err 225 } 226 227 finder := find.NewFinder(client.Client, true) 228 finder = finder.SetDatacenter(dc) 229 230 ds, err := getDatastore(finder, vDisk.datastore) 231 if err != nil { 232 return err 233 } 234 235 diskPath := ds.Path(vDisk.vmdkPath) 236 237 virtualDiskManager := object.NewVirtualDiskManager(client.Client) 238 239 task, err := virtualDiskManager.DeleteVirtualDisk(context.TODO(), diskPath, dc) 240 if err != nil { 241 return err 242 } 243 244 _, err = task.WaitForResult(context.TODO(), nil) 245 if err != nil { 246 log.Printf("[INFO] Failed to delete disk: %v", err) 247 return err 248 } 249 250 log.Printf("[INFO] Deleted disk: %v", diskPath) 251 d.SetId("") 252 return nil 253 } 254 255 // createHardDisk creates a new Hard Disk. 256 func createHardDisk(client *govmomi.Client, size int, diskPath string, diskType string, adapterType string, dc string) error { 257 var vDiskType string 258 switch diskType { 259 case "thin": 260 vDiskType = "thin" 261 case "eagerZeroedThick": 262 vDiskType = "eagerZeroedThick" 263 case "lazy": 264 vDiskType = "preallocated" 265 } 266 267 virtualDiskManager := object.NewVirtualDiskManager(client.Client) 268 spec := &types.FileBackedVirtualDiskSpec{ 269 VirtualDiskSpec: types.VirtualDiskSpec{ 270 AdapterType: adapterType, 271 DiskType: vDiskType, 272 }, 273 CapacityKb: int64(1024 * 1024 * size), 274 } 275 datacenter, err := getDatacenter(client, dc) 276 if err != nil { 277 return err 278 } 279 log.Printf("[DEBUG] Disk spec: %v", spec) 280 281 task, err := virtualDiskManager.CreateVirtualDisk(context.TODO(), diskPath, datacenter, spec) 282 if err != nil { 283 return err 284 } 285 286 _, err = task.WaitForResult(context.TODO(), nil) 287 if err != nil { 288 log.Printf("[INFO] Failed to create disk: %v", err) 289 return err 290 } 291 log.Printf("[INFO] Created disk.") 292 293 return nil 294 }