@@ -11,6 +11,7 @@ import (
1111 "encoding/base64"
1212 "errors"
1313 "fmt"
14+ "path/filepath"
1415 "regexp"
1516 "sort"
1617 "strconv"
@@ -225,6 +226,7 @@ const (
225226 mkInitialization = "initialization"
226227 mkInitializationDatastoreID = "datastore_id"
227228 mkInitializationInterface = "interface"
229+ mkInitializationFileFormat = "file_format"
228230 mkInitializationDNS = "dns"
229231 mkInitializationDNSDomain = "domain"
230232 mkInitializationDNSServers = "servers"
@@ -840,6 +842,13 @@ func VM() *schema.Resource {
840842 return newValue == ""
841843 },
842844 },
845+ mkInitializationFileFormat : {
846+ Type : schema .TypeString ,
847+ Description : "The file format" ,
848+ Optional : true ,
849+ Computed : true ,
850+ ValidateDiagFunc : validators .FileFormat (),
851+ },
843852 mkInitializationDNS : {
844853 Type : schema .TypeList ,
845854 Description : "The DNS configuration" ,
@@ -1769,16 +1778,16 @@ func vmCreate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnosti
17691778}
17701779
17711780// Check for an existing CloudInit IDE drive. If no such drive is found, return the specified `defaultValue`.
1772- func findExistingCloudInitDrive (vmConfig * vms.GetResponseData , vmID int , defaultValue string ) string {
1781+ func findExistingCloudInitDrive (vmConfig * vms.GetResponseData , vmID int , defaultValue string ) ( string , * vms. CustomStorageDevice ) {
17731782 devs := vmConfig .StorageDevices .Filter (func (device * vms.CustomStorageDevice ) bool {
17741783 return device .IsCloudInitDrive (vmID )
17751784 })
17761785
1777- for iface := range devs {
1778- return iface
1786+ for iface , device := range devs {
1787+ return iface , device
17791788 }
17801789
1781- return defaultValue
1790+ return defaultValue , nil
17821791}
17831792
17841793// Return a pointer to the storage device configuration based on a name. The device name is assumed to be a
@@ -2203,21 +2212,27 @@ func vmCreateClone(ctx context.Context, d *schema.ResourceData, m any) diag.Diag
22032212 initializationBlock := initialization [0 ].(map [string ]any )
22042213 initializationDatastoreID := initializationBlock [mkInitializationDatastoreID ].(string )
22052214 initializationInterface := initializationBlock [mkInitializationInterface ].(string )
2215+ initializationFileFormat := initializationBlock [mkInitializationFileFormat ].(string )
22062216
2207- existingInterface := findExistingCloudInitDrive (vmConfig , vmID , "ide2" )
2217+ existingInterface , _ := findExistingCloudInitDrive (vmConfig , vmID , "ide2" )
22082218 if initializationInterface == "" {
22092219 initializationInterface = existingInterface
22102220 }
22112221
22122222 tflog .Trace (ctx , fmt .Sprintf ("CloudInit IDE interface is '%s'" , initializationInterface ))
22132223
2214- cdromCloudInitFileID := fmt .Sprintf ("%s:cloudinit" , initializationDatastoreID )
2215- cdromCloudInitMedia := "cdrom"
2216- ideDevices [initializationInterface ] = & vms.CustomStorageDevice {
2217- FileVolume : cdromCloudInitFileID ,
2218- Media : & cdromCloudInitMedia ,
2224+ initializationFileVolume := fmt .Sprintf ("%s:cloudinit" , initializationDatastoreID )
2225+
2226+ device := & vms.CustomStorageDevice {
2227+ FileVolume : initializationFileVolume ,
22192228 }
22202229
2230+ if initializationFileFormat != "" {
2231+ device .Format = & initializationFileFormat
2232+ }
2233+
2234+ ideDevices [initializationInterface ] = device
2235+
22212236 if err := deleteIdeDrives (ctx , vmAPI , initializationInterface , existingInterface ); err != nil {
22222237 return err
22232238 }
@@ -2594,8 +2609,9 @@ func vmCreateCustom(ctx context.Context, d *schema.ResourceData, m any) diag.Dia
25942609 }
25952610 }
25962611
2597- cdromCloudInitFileID := ""
2598- cdromCloudInitInterface := ""
2612+ initializationFileVolume := ""
2613+ initializationInterface := ""
2614+ initializationFileFormat := ""
25992615
26002616 cpuBlock , err := structure .GetSchemaBlock (
26012617 resource ,
@@ -2659,12 +2675,13 @@ func vmCreateCustom(ctx context.Context, d *schema.ResourceData, m any) diag.Dia
26592675
26602676 initializationBlock := initialization [0 ].(map [string ]any )
26612677 initializationDatastoreID := initializationBlock [mkInitializationDatastoreID ].(string )
2678+ initializationFileFormat = initializationBlock [mkInitializationFileFormat ].(string )
26622679
2663- cdromCloudInitFileID = fmt .Sprintf ("%s:cloudinit" , initializationDatastoreID )
2680+ initializationFileVolume = fmt .Sprintf ("%s:cloudinit" , initializationDatastoreID )
26642681
2665- cdromCloudInitInterface = initializationBlock [mkInitializationInterface ].(string )
2666- if cdromCloudInitInterface == "" {
2667- cdromCloudInitInterface = "ide2"
2682+ initializationInterface = initializationBlock [mkInitializationInterface ].(string )
2683+ if initializationInterface == "" {
2684+ initializationInterface = "ide2"
26682685 }
26692686 }
26702687
@@ -2794,19 +2811,24 @@ func vmCreateCustom(ctx context.Context, d *schema.ResourceData, m any) diag.Dia
27942811 cpuFlagsConverted [fi ] = flag .(string )
27952812 }
27962813
2797- ideDevice2Media := "cdrom"
2814+ cdromMedia := "cdrom"
27982815
2799- if cdromCloudInitInterface != "" {
2800- diskDeviceObjects [cdromCloudInitInterface ] = & vms.CustomStorageDevice {
2801- FileVolume : cdromCloudInitFileID ,
2802- Media : & ideDevice2Media ,
2816+ if initializationInterface != "" {
2817+ device := & vms.CustomStorageDevice {
2818+ FileVolume : initializationFileVolume ,
28032819 }
2820+
2821+ if initializationFileFormat != "" {
2822+ device .Format = & initializationFileFormat
2823+ }
2824+
2825+ diskDeviceObjects [initializationInterface ] = device
28042826 }
28052827
28062828 if cdromInterface != "" {
28072829 diskDeviceObjects [cdromInterface ] = & vms.CustomStorageDevice {
28082830 FileVolume : cdromFileID ,
2809- Media : & ideDevice2Media ,
2831+ Media : & cdromMedia ,
28102832 }
28112833 }
28122834
@@ -4384,13 +4406,28 @@ func vmReadCustom(
43844406 // Compare the initialization configuration to the one stored in the state.
43854407 initialization := map [string ]any {}
43864408
4387- initializationInterface := findExistingCloudInitDrive (vmConfig , vmID , "" )
4409+ initializationInterface , initializationDevice := findExistingCloudInitDrive (vmConfig , vmID , "" )
43884410 if initializationInterface != "" {
4389- initializationDevice := getStorageDevice (vmConfig , initializationInterface )
4390- fileVolumeParts := strings .Split (initializationDevice .FileVolume , ":" )
4411+ parts := strings .Split (initializationDevice .FileVolume , "," )
4412+
4413+ fileVolume := parts [0 ]
4414+ fileVolumeParts := strings .Split (fileVolume , ":" )
4415+
4416+ datastoreId := fileVolumeParts [0 ]
4417+ pathInDatastore := fileVolumeParts [1 ]
43914418
43924419 initialization [mkInitializationInterface ] = initializationInterface
4393- initialization [mkInitializationDatastoreID ] = fileVolumeParts [0 ]
4420+ initialization [mkInitializationDatastoreID ] = datastoreId
4421+
4422+ if initializationDevice .Format != nil && * initializationDevice .Format != "" {
4423+ initialization [mkInitializationFileFormat ] = * initializationDevice .Format
4424+ } else {
4425+ fileFormat := filepath .Ext (pathInDatastore )
4426+
4427+ if fileFormat != "" {
4428+ initialization [mkInitializationFileFormat ] = fileFormat [1 :]
4429+ }
4430+ }
43944431 }
43954432
43964433 if vmConfig .CloudInitDNSDomain != nil || vmConfig .CloudInitDNSServer != nil {
@@ -5631,35 +5668,43 @@ func vmUpdate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnosti
56315668 initializationBlock := initialization [0 ].(map [string ]any )
56325669 initializationDatastoreID := initializationBlock [mkInitializationDatastoreID ].(string )
56335670 initializationInterface := initializationBlock [mkInitializationInterface ].(string )
5634- cdromMedia := "cdrom"
5671+ initializationFileFormat := initializationBlock [ mkInitializationFileFormat ].( string )
56355672
5636- existingInterface := findExistingCloudInitDrive (vmConfig , vmID , "" )
5673+ existingInterface , existingDevice := findExistingCloudInitDrive (vmConfig , vmID , "" )
56375674 if initializationInterface == "" && existingInterface == "" {
56385675 initializationInterface = "ide2"
56395676 } else if initializationInterface == "" {
56405677 initializationInterface = existingInterface
56415678 }
56425679
5643- mustMove := existingInterface != "" && initializationInterface != existingInterface
5644- if mustMove {
5680+ mustChangeInterface := existingInterface != "" && initializationInterface != existingInterface
5681+ if mustChangeInterface {
56455682 tflog .Debug (ctx , fmt .Sprintf ("CloudInit must be moved from %s to %s" , existingInterface , initializationInterface ))
56465683 }
56475684
56485685 mustChangeDatastore := false
5686+ mustChangeFileFormat := false
56495687
56505688 oldInit , _ := d .GetChange (mkInitialization )
56515689 if len (oldInit .([]any )) > 0 {
56525690 oldInitBlock := oldInit .([]any )[0 ].(map [string ]any )
56535691 prevDatastoreID := oldInitBlock [mkInitializationDatastoreID ].(string )
5692+ prevFileFormat := oldInitBlock [mkInitializationFileFormat ].(string )
56545693
56555694 mustChangeDatastore = prevDatastoreID != initializationDatastoreID
56565695 if mustChangeDatastore {
56575696 tflog .Debug (ctx , fmt .Sprintf ("CloudInit must be moved from datastore %s to datastore %s" ,
56585697 prevDatastoreID , initializationDatastoreID ))
56595698 }
5699+
5700+ mustChangeFileFormat = prevFileFormat != initializationFileFormat
5701+ if mustChangeFileFormat {
5702+ tflog .Debug (ctx , fmt .Sprintf ("CloudInit must be moved from file format %s to file format %s" ,
5703+ prevFileFormat , initializationFileFormat ))
5704+ }
56605705 }
56615706
5662- if mustMove || mustChangeDatastore || existingInterface == "" {
5707+ if mustChangeInterface || mustChangeDatastore || mustChangeFileFormat || existingInterface == "" {
56635708 // CloudInit must be moved, either from a device to another or from a datastore
56645709 // to another (or both). This requires the VM to be stopped.
56655710 if ! stoppedBeforeUpdate {
@@ -5675,14 +5720,18 @@ func vmUpdate(ctx context.Context, d *schema.ResourceData, m any) diag.Diagnosti
56755720 stoppedBeforeUpdate = true
56765721 fileVolume = fmt .Sprintf ("%s:cloudinit" , initializationDatastoreID )
56775722 } else {
5678- ideDevice := getStorageDevice (vmConfig , existingInterface )
5679- fileVolume = ideDevice .FileVolume
5723+ fileVolume = existingDevice .FileVolume
56805724 }
56815725
5682- updateBody . AddCustomStorageDevice ( initializationInterface , vms.CustomStorageDevice {
5726+ device := vms.CustomStorageDevice {
56835727 FileVolume : fileVolume ,
5684- Media : & cdromMedia ,
5685- })
5728+ }
5729+
5730+ if initializationFileFormat != "" {
5731+ device .Format = & initializationFileFormat
5732+ }
5733+
5734+ updateBody .AddCustomStorageDevice (initializationInterface , device )
56865735 }
56875736
56885737 cloudInitRebuildRequired = true
0 commit comments