@@ -3,6 +3,7 @@ package vsphere
33import (
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
1516type 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
2227func 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 {
179258func 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