github.com/pmcatominey/terraform@v0.7.0-rc2.0.20160708105029-1401a52a5cc5/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 }