github.com/gabrielperezs/terraform@v0.7.0-rc2.0.20160715084931-f7da2612946f/builtin/providers/vsphere/resource_vsphere_file.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/soap"
    12  	"golang.org/x/net/context"
    13  )
    14  
    15  type file struct {
    16  	datacenter      string
    17  	datastore       string
    18  	sourceFile      string
    19  	destinationFile string
    20  }
    21  
    22  func resourceVSphereFile() *schema.Resource {
    23  	return &schema.Resource{
    24  		Create: resourceVSphereFileCreate,
    25  		Read:   resourceVSphereFileRead,
    26  		Update: resourceVSphereFileUpdate,
    27  		Delete: resourceVSphereFileDelete,
    28  
    29  		Schema: map[string]*schema.Schema{
    30  			"datacenter": {
    31  				Type:     schema.TypeString,
    32  				Optional: true,
    33  				ForceNew: true,
    34  			},
    35  
    36  			"datastore": {
    37  				Type:     schema.TypeString,
    38  				Optional: true,
    39  				ForceNew: true,
    40  			},
    41  
    42  			"source_file": {
    43  				Type:     schema.TypeString,
    44  				Required: true,
    45  				ForceNew: true,
    46  			},
    47  
    48  			"destination_file": {
    49  				Type:     schema.TypeString,
    50  				Required: true,
    51  			},
    52  		},
    53  	}
    54  }
    55  
    56  func resourceVSphereFileCreate(d *schema.ResourceData, meta interface{}) error {
    57  
    58  	log.Printf("[DEBUG] creating file: %#v", d)
    59  	client := meta.(*govmomi.Client)
    60  
    61  	f := file{}
    62  
    63  	if v, ok := d.GetOk("datacenter"); ok {
    64  		f.datacenter = v.(string)
    65  	}
    66  
    67  	if v, ok := d.GetOk("datastore"); ok {
    68  		f.datastore = v.(string)
    69  	} else {
    70  		return fmt.Errorf("datastore argument is required")
    71  	}
    72  
    73  	if v, ok := d.GetOk("source_file"); ok {
    74  		f.sourceFile = v.(string)
    75  	} else {
    76  		return fmt.Errorf("source_file argument is required")
    77  	}
    78  
    79  	if v, ok := d.GetOk("destination_file"); ok {
    80  		f.destinationFile = v.(string)
    81  	} else {
    82  		return fmt.Errorf("destination_file argument is required")
    83  	}
    84  
    85  	err := createFile(client, &f)
    86  	if err != nil {
    87  		return err
    88  	}
    89  
    90  	d.SetId(fmt.Sprintf("[%v] %v/%v", f.datastore, f.datacenter, f.destinationFile))
    91  	log.Printf("[INFO] Created file: %s", f.destinationFile)
    92  
    93  	return resourceVSphereFileRead(d, meta)
    94  }
    95  
    96  func createFile(client *govmomi.Client, f *file) error {
    97  
    98  	finder := find.NewFinder(client.Client, true)
    99  
   100  	dc, err := finder.Datacenter(context.TODO(), f.datacenter)
   101  	if err != nil {
   102  		return fmt.Errorf("error %s", err)
   103  	}
   104  	finder = finder.SetDatacenter(dc)
   105  
   106  	ds, err := getDatastore(finder, f.datastore)
   107  	if err != nil {
   108  		return fmt.Errorf("error %s", err)
   109  	}
   110  
   111  	dsurl, err := ds.URL(context.TODO(), dc, f.destinationFile)
   112  	if err != nil {
   113  		return err
   114  	}
   115  
   116  	p := soap.DefaultUpload
   117  	err = client.Client.UploadFile(f.sourceFile, dsurl, &p)
   118  	if err != nil {
   119  		return fmt.Errorf("error %s", err)
   120  	}
   121  	return nil
   122  }
   123  
   124  func resourceVSphereFileRead(d *schema.ResourceData, meta interface{}) error {
   125  
   126  	log.Printf("[DEBUG] reading file: %#v", d)
   127  	f := file{}
   128  
   129  	if v, ok := d.GetOk("datacenter"); ok {
   130  		f.datacenter = v.(string)
   131  	}
   132  
   133  	if v, ok := d.GetOk("datastore"); ok {
   134  		f.datastore = v.(string)
   135  	} else {
   136  		return fmt.Errorf("datastore argument is required")
   137  	}
   138  
   139  	if v, ok := d.GetOk("source_file"); ok {
   140  		f.sourceFile = v.(string)
   141  	} else {
   142  		return fmt.Errorf("source_file argument is required")
   143  	}
   144  
   145  	if v, ok := d.GetOk("destination_file"); ok {
   146  		f.destinationFile = v.(string)
   147  	} else {
   148  		return fmt.Errorf("destination_file argument is required")
   149  	}
   150  
   151  	client := meta.(*govmomi.Client)
   152  	finder := find.NewFinder(client.Client, true)
   153  
   154  	dc, err := finder.Datacenter(context.TODO(), f.datacenter)
   155  	if err != nil {
   156  		return fmt.Errorf("error %s", err)
   157  	}
   158  	finder = finder.SetDatacenter(dc)
   159  
   160  	ds, err := getDatastore(finder, f.datastore)
   161  	if err != nil {
   162  		return fmt.Errorf("error %s", err)
   163  	}
   164  
   165  	_, err = ds.Stat(context.TODO(), f.destinationFile)
   166  	if err != nil {
   167  		log.Printf("[DEBUG] resourceVSphereFileRead - stat failed on: %v", f.destinationFile)
   168  		d.SetId("")
   169  
   170  		_, ok := err.(object.DatastoreNoSuchFileError)
   171  		if !ok {
   172  			return err
   173  		}
   174  	}
   175  
   176  	return nil
   177  }
   178  
   179  func resourceVSphereFileUpdate(d *schema.ResourceData, meta interface{}) error {
   180  
   181  	log.Printf("[DEBUG] updating file: %#v", d)
   182  	if d.HasChange("destination_file") {
   183  		oldDestinationFile, newDestinationFile := d.GetChange("destination_file")
   184  		f := file{}
   185  
   186  		if v, ok := d.GetOk("datacenter"); ok {
   187  			f.datacenter = v.(string)
   188  		}
   189  
   190  		if v, ok := d.GetOk("datastore"); ok {
   191  			f.datastore = v.(string)
   192  		} else {
   193  			return fmt.Errorf("datastore argument is required")
   194  		}
   195  
   196  		if v, ok := d.GetOk("source_file"); ok {
   197  			f.sourceFile = v.(string)
   198  		} else {
   199  			return fmt.Errorf("source_file argument is required")
   200  		}
   201  
   202  		if v, ok := d.GetOk("destination_file"); ok {
   203  			f.destinationFile = v.(string)
   204  		} else {
   205  			return fmt.Errorf("destination_file argument is required")
   206  		}
   207  
   208  		client := meta.(*govmomi.Client)
   209  		dc, err := getDatacenter(client, f.datacenter)
   210  		if err != nil {
   211  			return err
   212  		}
   213  
   214  		finder := find.NewFinder(client.Client, true)
   215  		finder = finder.SetDatacenter(dc)
   216  
   217  		ds, err := getDatastore(finder, f.datastore)
   218  		if err != nil {
   219  			return fmt.Errorf("error %s", err)
   220  		}
   221  
   222  		fm := object.NewFileManager(client.Client)
   223  		task, err := fm.MoveDatastoreFile(context.TODO(), ds.Path(oldDestinationFile.(string)), dc, ds.Path(newDestinationFile.(string)), dc, true)
   224  		if err != nil {
   225  			return err
   226  		}
   227  
   228  		_, err = task.WaitForResult(context.TODO(), nil)
   229  		if err != nil {
   230  			return err
   231  		}
   232  
   233  	}
   234  
   235  	return nil
   236  }
   237  
   238  func resourceVSphereFileDelete(d *schema.ResourceData, meta interface{}) error {
   239  
   240  	log.Printf("[DEBUG] deleting file: %#v", d)
   241  	f := file{}
   242  
   243  	if v, ok := d.GetOk("datacenter"); ok {
   244  		f.datacenter = v.(string)
   245  	}
   246  
   247  	if v, ok := d.GetOk("datastore"); ok {
   248  		f.datastore = v.(string)
   249  	} else {
   250  		return fmt.Errorf("datastore argument is required")
   251  	}
   252  
   253  	if v, ok := d.GetOk("source_file"); ok {
   254  		f.sourceFile = v.(string)
   255  	} else {
   256  		return fmt.Errorf("source_file argument is required")
   257  	}
   258  
   259  	if v, ok := d.GetOk("destination_file"); ok {
   260  		f.destinationFile = v.(string)
   261  	} else {
   262  		return fmt.Errorf("destination_file argument is required")
   263  	}
   264  
   265  	client := meta.(*govmomi.Client)
   266  
   267  	err := deleteFile(client, &f)
   268  	if err != nil {
   269  		return err
   270  	}
   271  
   272  	d.SetId("")
   273  	return nil
   274  }
   275  
   276  func deleteFile(client *govmomi.Client, f *file) error {
   277  
   278  	dc, err := getDatacenter(client, f.datacenter)
   279  	if err != nil {
   280  		return err
   281  	}
   282  
   283  	finder := find.NewFinder(client.Client, true)
   284  	finder = finder.SetDatacenter(dc)
   285  
   286  	ds, err := getDatastore(finder, f.datastore)
   287  	if err != nil {
   288  		return fmt.Errorf("error %s", err)
   289  	}
   290  
   291  	fm := object.NewFileManager(client.Client)
   292  	task, err := fm.DeleteDatastoreFile(context.TODO(), ds.Path(f.destinationFile), dc)
   293  	if err != nil {
   294  		return err
   295  	}
   296  
   297  	_, err = task.WaitForResult(context.TODO(), nil)
   298  	if err != nil {
   299  		return err
   300  	}
   301  	return nil
   302  }
   303  
   304  // getDatastore gets datastore object
   305  func getDatastore(f *find.Finder, ds string) (*object.Datastore, error) {
   306  
   307  	if ds != "" {
   308  		dso, err := f.Datastore(context.TODO(), ds)
   309  		return dso, err
   310  	} else {
   311  		dso, err := f.DefaultDatastore(context.TODO())
   312  		return dso, err
   313  	}
   314  }