Skip to content

Commit de822d9

Browse files
authored
Merge pull request hashicorp#7952 from dagnello/vsphere-file-copy
vSphere file resource: extending functionality to copy files in vSphere
2 parents f3a06c0 + 895383a commit de822d9

3 files changed

Lines changed: 308 additions & 49 deletions

File tree

builtin/providers/vsphere/resource_vsphere_file.go

Lines changed: 129 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package vsphere
33
import (
44
"fmt"
55
"log"
6+
"strings"
67

78
"github.com/hashicorp/terraform/helper/schema"
89
"github.com/vmware/govmomi"
@@ -13,10 +14,14 @@ import (
1314
)
1415

1516
type file struct {
16-
datacenter string
17-
datastore string
18-
sourceFile string
19-
destinationFile string
17+
sourceDatacenter string
18+
datacenter string
19+
sourceDatastore string
20+
datastore string
21+
sourceFile string
22+
destinationFile string
23+
createDirectories bool
24+
copyFile bool
2025
}
2126

2227
func resourceVSphereFile() *schema.Resource {
@@ -30,10 +35,20 @@ func resourceVSphereFile() *schema.Resource {
3035
"datacenter": {
3136
Type: schema.TypeString,
3237
Optional: true,
38+
},
39+
40+
"source_datacenter": {
41+
Type: schema.TypeString,
42+
Optional: true,
3343
ForceNew: true,
3444
},
3545

3646
"datastore": {
47+
Type: schema.TypeString,
48+
Required: true,
49+
},
50+
51+
"source_datastore": {
3752
Type: schema.TypeString,
3853
Optional: true,
3954
ForceNew: true,
@@ -49,6 +64,11 @@ func resourceVSphereFile() *schema.Resource {
4964
Type: schema.TypeString,
5065
Required: true,
5166
},
67+
68+
"create_directories": {
69+
Type: schema.TypeBool,
70+
Optional: true,
71+
},
5272
},
5373
}
5474
}
@@ -60,10 +80,20 @@ func resourceVSphereFileCreate(d *schema.ResourceData, meta interface{}) error {
6080

6181
f := file{}
6282

83+
if v, ok := d.GetOk("source_datacenter"); ok {
84+
f.sourceDatacenter = v.(string)
85+
f.copyFile = true
86+
}
87+
6388
if v, ok := d.GetOk("datacenter"); ok {
6489
f.datacenter = v.(string)
6590
}
6691

92+
if v, ok := d.GetOk("source_datastore"); ok {
93+
f.sourceDatastore = v.(string)
94+
f.copyFile = true
95+
}
96+
6797
if v, ok := d.GetOk("datastore"); ok {
6898
f.datastore = v.(string)
6999
} else {
@@ -82,6 +112,10 @@ func resourceVSphereFileCreate(d *schema.ResourceData, meta interface{}) error {
82112
return fmt.Errorf("destination_file argument is required")
83113
}
84114

115+
if v, ok := d.GetOk("create_directories"); ok {
116+
f.createDirectories = v.(bool)
117+
}
118+
85119
err := createFile(client, &f)
86120
if err != nil {
87121
return err
@@ -108,16 +142,53 @@ func createFile(client *govmomi.Client, f *file) error {
108142
return fmt.Errorf("error %s", err)
109143
}
110144

111-
dsurl, err := ds.URL(context.TODO(), dc, f.destinationFile)
112-
if err != nil {
113-
return err
114-
}
145+
if f.copyFile {
146+
// Copying file from withing vSphere
147+
source_dc, err := finder.Datacenter(context.TODO(), f.sourceDatacenter)
148+
if err != nil {
149+
return fmt.Errorf("error %s", err)
150+
}
151+
finder = finder.SetDatacenter(dc)
115152

116-
p := soap.DefaultUpload
117-
err = client.Client.UploadFile(f.sourceFile, dsurl, &p)
118-
if err != nil {
119-
return fmt.Errorf("error %s", err)
153+
source_ds, err := getDatastore(finder, f.sourceDatastore)
154+
if err != nil {
155+
return fmt.Errorf("error %s", err)
156+
}
157+
158+
fm := object.NewFileManager(client.Client)
159+
if f.createDirectories {
160+
directoryPathIndex := strings.LastIndex(f.destinationFile, "/")
161+
path := f.destinationFile[0:directoryPathIndex]
162+
err = fm.MakeDirectory(context.TODO(), ds.Path(path), dc, true)
163+
if err != nil {
164+
return fmt.Errorf("error %s", err)
165+
}
166+
}
167+
task, err := fm.CopyDatastoreFile(context.TODO(), source_ds.Path(f.sourceFile), source_dc, ds.Path(f.destinationFile), dc, true)
168+
169+
if err != nil {
170+
return fmt.Errorf("error %s", err)
171+
}
172+
173+
_, err = task.WaitForResult(context.TODO(), nil)
174+
if err != nil {
175+
return fmt.Errorf("error %s", err)
176+
}
177+
178+
} else {
179+
// Uploading file to vSphere
180+
dsurl, err := ds.URL(context.TODO(), dc, f.destinationFile)
181+
if err != nil {
182+
return fmt.Errorf("error %s", err)
183+
}
184+
185+
p := soap.DefaultUpload
186+
err = client.Client.UploadFile(f.sourceFile, dsurl, &p)
187+
if err != nil {
188+
return fmt.Errorf("error %s", err)
189+
}
120190
}
191+
121192
return nil
122193
}
123194

@@ -126,10 +197,18 @@ func resourceVSphereFileRead(d *schema.ResourceData, meta interface{}) error {
126197
log.Printf("[DEBUG] reading file: %#v", d)
127198
f := file{}
128199

200+
if v, ok := d.GetOk("source_datacenter"); ok {
201+
f.sourceDatacenter = v.(string)
202+
}
203+
129204
if v, ok := d.GetOk("datacenter"); ok {
130205
f.datacenter = v.(string)
131206
}
132207

208+
if v, ok := d.GetOk("source_datastore"); ok {
209+
f.sourceDatastore = v.(string)
210+
}
211+
133212
if v, ok := d.GetOk("datastore"); ok {
134213
f.datastore = v.(string)
135214
} else {
@@ -179,57 +258,69 @@ func resourceVSphereFileRead(d *schema.ResourceData, meta interface{}) error {
179258
func resourceVSphereFileUpdate(d *schema.ResourceData, meta interface{}) error {
180259

181260
log.Printf("[DEBUG] updating file: %#v", d)
182-
if d.HasChange("destination_file") {
183-
oldDestinationFile, newDestinationFile := d.GetChange("destination_file")
184-
f := file{}
185261

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)
262+
if d.HasChange("destination_file") || d.HasChange("datacenter") || d.HasChange("datastore") {
263+
// File needs to be moved, get old and new destination changes
264+
var oldDataceneter, newDatacenter, oldDatastore, newDatastore, oldDestinationFile, newDestinationFile string
265+
if d.HasChange("datacenter") {
266+
tmpOldDataceneter, tmpNewDatacenter := d.GetChange("datacenter")
267+
oldDataceneter = tmpOldDataceneter.(string)
268+
newDatacenter = tmpNewDatacenter.(string)
192269
} else {
193-
return fmt.Errorf("datastore argument is required")
270+
if v, ok := d.GetOk("datacenter"); ok {
271+
oldDataceneter = v.(string)
272+
newDatacenter = oldDataceneter
273+
}
194274
}
195-
196-
if v, ok := d.GetOk("source_file"); ok {
197-
f.sourceFile = v.(string)
275+
if d.HasChange("datastore") {
276+
tmpOldDatastore, tmpNewDatastore := d.GetChange("datastore")
277+
oldDatastore = tmpOldDatastore.(string)
278+
newDatastore = tmpNewDatastore.(string)
198279
} else {
199-
return fmt.Errorf("source_file argument is required")
280+
oldDatastore = d.Get("datastore").(string)
281+
newDatastore = oldDatastore
200282
}
201-
202-
if v, ok := d.GetOk("destination_file"); ok {
203-
f.destinationFile = v.(string)
283+
if d.HasChange("destination_file") {
284+
tmpOldDestinationFile, tmpNewDestinationFile := d.GetChange("destination_file")
285+
oldDestinationFile = tmpOldDestinationFile.(string)
286+
newDestinationFile = tmpNewDestinationFile.(string)
204287
} else {
205-
return fmt.Errorf("destination_file argument is required")
288+
oldDestinationFile = d.Get("destination_file").(string)
289+
newDestinationFile = oldDestinationFile
206290
}
207291

292+
// Get old and new dataceter and datastore
208293
client := meta.(*govmomi.Client)
209-
dc, err := getDatacenter(client, f.datacenter)
294+
dcOld, err := getDatacenter(client, oldDataceneter)
295+
if err != nil {
296+
return err
297+
}
298+
dcNew, err := getDatacenter(client, newDatacenter)
210299
if err != nil {
211300
return err
212301
}
213-
214302
finder := find.NewFinder(client.Client, true)
215-
finder = finder.SetDatacenter(dc)
216-
217-
ds, err := getDatastore(finder, f.datastore)
303+
finder = finder.SetDatacenter(dcOld)
304+
dsOld, err := getDatastore(finder, oldDatastore)
305+
if err != nil {
306+
return fmt.Errorf("error %s", err)
307+
}
308+
finder = finder.SetDatacenter(dcNew)
309+
dsNew, err := getDatastore(finder, newDatastore)
218310
if err != nil {
219311
return fmt.Errorf("error %s", err)
220312
}
221313

314+
// Move file between old/new dataceter, datastore and path (destination_file)
222315
fm := object.NewFileManager(client.Client)
223-
task, err := fm.MoveDatastoreFile(context.TODO(), ds.Path(oldDestinationFile.(string)), dc, ds.Path(newDestinationFile.(string)), dc, true)
316+
task, err := fm.MoveDatastoreFile(context.TODO(), dsOld.Path(oldDestinationFile), dcOld, dsNew.Path(newDestinationFile), dcNew, true)
224317
if err != nil {
225318
return err
226319
}
227-
228320
_, err = task.WaitForResult(context.TODO(), nil)
229321
if err != nil {
230322
return err
231323
}
232-
233324
}
234325

235326
return nil

0 commit comments

Comments
 (0)