github.com/recobe182/terraform@v0.8.5-0.20170117231232-49ab22a935b7/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  }