mirror of
https://github.com/bpg/terraform-provider-proxmox.git
synced 2025-08-27 05:45:38 +00:00
more disk management refactoring
Signed-off-by: Pavel Boldyrev <627562+bpg@users.noreply.github.com>
This commit is contained in:
parent
98f16fc97c
commit
87ff97ca58
@ -262,44 +262,75 @@ func (c *Client) RebootVMAsync(ctx context.Context, d *RebootRequestBody) (*stri
|
|||||||
return resBody.Data, nil
|
return resBody.Data, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// // ResizeVMDisk resizes a virtual machine disk.
|
||||||
|
// func (c *Client) ResizeVMDisk(ctx context.Context, d *ResizeDiskRequestBody) error {
|
||||||
|
// var err error
|
||||||
|
|
||||||
|
// tflog.Debug(ctx, "resize disk", map[string]interface{}{
|
||||||
|
// "disk": d.Disk,
|
||||||
|
// "size": d.Size,
|
||||||
|
// })
|
||||||
|
|
||||||
|
// for i := 0; i < 5; i++ {
|
||||||
|
// err = c.DoRequest(
|
||||||
|
// ctx,
|
||||||
|
// http.MethodPut,
|
||||||
|
// c.ExpandPath("resize"),
|
||||||
|
// d,
|
||||||
|
// nil,
|
||||||
|
// )
|
||||||
|
// if err == nil {
|
||||||
|
// return nil
|
||||||
|
// }
|
||||||
|
|
||||||
|
// tflog.Debug(ctx, "resize disk failed", map[string]interface{}{
|
||||||
|
// "retry": i,
|
||||||
|
// })
|
||||||
|
// time.Sleep(5 * time.Second)
|
||||||
|
|
||||||
|
// if ctx.Err() != nil {
|
||||||
|
// return fmt.Errorf("error resizing VM disk: %w", ctx.Err())
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if err != nil {
|
||||||
|
// return fmt.Errorf("error resizing VM disk: %w", err)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return nil
|
||||||
|
// }
|
||||||
|
|
||||||
// ResizeVMDisk resizes a virtual machine disk.
|
// ResizeVMDisk resizes a virtual machine disk.
|
||||||
func (c *Client) ResizeVMDisk(ctx context.Context, d *ResizeDiskRequestBody) error {
|
func (c *Client) ResizeVMDisk(ctx context.Context, d *ResizeDiskRequestBody, timeout int) error {
|
||||||
var err error
|
taskID, err := c.ResizeVMDiskAsync(ctx, d)
|
||||||
|
if err != nil {
|
||||||
tflog.Debug(ctx, "resize disk", map[string]interface{}{
|
return err
|
||||||
"disk": d.Disk,
|
|
||||||
"size": d.Size,
|
|
||||||
})
|
|
||||||
|
|
||||||
for i := 0; i < 5; i++ {
|
|
||||||
err = c.DoRequest(
|
|
||||||
ctx,
|
|
||||||
http.MethodPut,
|
|
||||||
c.ExpandPath("resize"),
|
|
||||||
d,
|
|
||||||
nil,
|
|
||||||
)
|
|
||||||
if err == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
tflog.Debug(ctx, "resize disk failed", map[string]interface{}{
|
|
||||||
"retry": i,
|
|
||||||
})
|
|
||||||
time.Sleep(5 * time.Second)
|
|
||||||
|
|
||||||
if ctx.Err() != nil {
|
|
||||||
return fmt.Errorf("error resizing VM disk: %w", ctx.Err())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = c.Tasks().WaitForTask(ctx, *taskID, timeout, 5)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error resizing VM disk: %w", err)
|
return fmt.Errorf("error waiting for VM disk resize: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ResizeVMDiskAsync resizes a virtual machine disk asynchronously.
|
||||||
|
func (c *Client) ResizeVMDiskAsync(ctx context.Context, d *ResizeDiskRequestBody) (*string, error) {
|
||||||
|
resBody := &MoveDiskResponseBody{}
|
||||||
|
|
||||||
|
err := c.DoRequest(ctx, http.MethodPut, c.ExpandPath("resize"), d, resBody)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error moving VM disk: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if resBody.Data == nil {
|
||||||
|
return nil, api.ErrNoDataObjectInResponse
|
||||||
|
}
|
||||||
|
|
||||||
|
return resBody.Data, nil
|
||||||
|
}
|
||||||
|
|
||||||
// ShutdownVM shuts down a virtual machine.
|
// ShutdownVM shuts down a virtual machine.
|
||||||
func (c *Client) ShutdownVM(ctx context.Context, d *ShutdownRequestBody, timeout int) error {
|
func (c *Client) ShutdownVM(ctx context.Context, d *ShutdownRequestBody, timeout int) error {
|
||||||
taskID, err := c.ShutdownVMAsync(ctx, d)
|
taskID, err := c.ShutdownVMAsync(ctx, d)
|
||||||
|
@ -14,6 +14,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"unicode"
|
||||||
|
|
||||||
"github.com/bpg/terraform-provider-proxmox/proxmox/types"
|
"github.com/bpg/terraform-provider-proxmox/proxmox/types"
|
||||||
)
|
)
|
||||||
@ -242,8 +243,32 @@ func (d CustomStorageDevice) IsCloudInitDrive(vmID int) bool {
|
|||||||
strings.Contains(d.FileVolume, fmt.Sprintf("vm-%d-cloudinit", vmID))
|
strings.Contains(d.FileVolume, fmt.Sprintf("vm-%d-cloudinit", vmID))
|
||||||
}
|
}
|
||||||
|
|
||||||
// CustomStorageDevices handles QEMU SATA device parameters.
|
// StorageInterface returns the storage interface of the CustomStorageDevice, e.g. "virtio" or "scsi" for "virtio0" or "scsi2".
|
||||||
type CustomStorageDevices map[string]CustomStorageDevice
|
func (d CustomStorageDevice) StorageInterface() string {
|
||||||
|
for i, r := range *d.Interface {
|
||||||
|
if unicode.IsDigit(r) {
|
||||||
|
return (*d.Interface)[:i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
panic(fmt.Sprintf("cannot determine storage interface for disk interface '%s'", *d.Interface))
|
||||||
|
}
|
||||||
|
|
||||||
|
// CustomStorageDevices handles map of QEMU storage device per disk interface.
|
||||||
|
type CustomStorageDevices map[string]*CustomStorageDevice
|
||||||
|
|
||||||
|
// ByStorageInterface returns a map of CustomStorageDevices filtered by the given storage interface.
|
||||||
|
func (d CustomStorageDevices) ByStorageInterface(storageInterface string) CustomStorageDevices {
|
||||||
|
result := make(CustomStorageDevices)
|
||||||
|
|
||||||
|
for k, v := range d {
|
||||||
|
if v.StorageInterface() == storageInterface {
|
||||||
|
result[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
// CustomTPMState handles QEMU TPM state parameters.
|
// CustomTPMState handles QEMU TPM state parameters.
|
||||||
type CustomTPMState struct {
|
type CustomTPMState struct {
|
||||||
|
@ -120,6 +120,102 @@ func TestCustomStorageDevice_IsCloudInitDrive(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCustomStorageDevice_StorageInterface(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
device CustomStorageDevice
|
||||||
|
want string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "virtio0",
|
||||||
|
device: CustomStorageDevice{
|
||||||
|
Interface: types.StrPtr("virtio0"),
|
||||||
|
},
|
||||||
|
want: "virtio",
|
||||||
|
}, {
|
||||||
|
name: "scsi13",
|
||||||
|
device: CustomStorageDevice{
|
||||||
|
Interface: types.StrPtr("scsi13"),
|
||||||
|
},
|
||||||
|
want: "scsi",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
tt := tt
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
got := tt.device.StorageInterface()
|
||||||
|
assert.Equal(t, tt.want, got)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCustomStorageDevices_ByStorageInterface(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
iface string
|
||||||
|
devices CustomStorageDevices
|
||||||
|
want CustomStorageDevices
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "empty",
|
||||||
|
iface: "virtio",
|
||||||
|
devices: CustomStorageDevices{},
|
||||||
|
want: CustomStorageDevices{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "not in the list",
|
||||||
|
iface: "sata",
|
||||||
|
devices: CustomStorageDevices{
|
||||||
|
"virtio0": CustomStorageDevice{
|
||||||
|
Interface: types.StrPtr("virtio0"),
|
||||||
|
},
|
||||||
|
"scsi13": CustomStorageDevice{
|
||||||
|
Interface: types.StrPtr("scsi13"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: CustomStorageDevices{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "not in the list",
|
||||||
|
iface: "virtio",
|
||||||
|
devices: CustomStorageDevices{
|
||||||
|
"virtio0": CustomStorageDevice{
|
||||||
|
Interface: types.StrPtr("virtio0"),
|
||||||
|
},
|
||||||
|
"scsi13": CustomStorageDevice{
|
||||||
|
Interface: types.StrPtr("scsi13"),
|
||||||
|
},
|
||||||
|
"virtio1": CustomStorageDevice{
|
||||||
|
Interface: types.StrPtr("virtio1"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
want: CustomStorageDevices{
|
||||||
|
"virtio0": CustomStorageDevice{
|
||||||
|
Interface: types.StrPtr("virtio0"),
|
||||||
|
},
|
||||||
|
"virtio1": CustomStorageDevice{
|
||||||
|
Interface: types.StrPtr("virtio1"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
tt := tt
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
got := tt.devices.ByStorageInterface(tt.iface)
|
||||||
|
assert.Equal(t, tt.want, got)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestCustomPCIDevice_UnmarshalJSON(t *testing.T) {
|
func TestCustomPCIDevice_UnmarshalJSON(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
|
@ -2,7 +2,6 @@ package vm
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@ -17,7 +16,6 @@ import (
|
|||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
|
||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
|
||||||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
|
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
|
||||||
"golang.org/x/exp/maps"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -203,143 +201,100 @@ func createDisks(
|
|||||||
ctx context.Context, vmConfig *vms.GetResponseData, d *schema.ResourceData, vmAPI *vms.Client,
|
ctx context.Context, vmConfig *vms.GetResponseData, d *schema.ResourceData, vmAPI *vms.Client,
|
||||||
) (map[string]*vms.CustomStorageDevice, error) {
|
) (map[string]*vms.CustomStorageDevice, error) {
|
||||||
// this is what VM has at the moment: map of interface name (virtio1) -> disk object
|
// this is what VM has at the moment: map of interface name (virtio1) -> disk object
|
||||||
currentStorageDevices := populateFileIDs(mapStorageDevices(vmConfig), d)
|
currentDisks := populateFileIDs(mapStorageDevices(vmConfig), d)
|
||||||
|
|
||||||
// map of interface type (virtio|sata|scsi|...) -> map of interface name (virtio1) -> disk object
|
// map of interface name (virtio1) -> disk object
|
||||||
planStorageDevices, e := getStorageDevicesFromResource(d)
|
planDisks, e := getStorageDevicesFromResource(d)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
return nil, e
|
return nil, e
|
||||||
}
|
}
|
||||||
|
|
||||||
// create disks that are not present in the current configuration
|
for diskInterface, planDisk := range planDisks {
|
||||||
for prefix, disks := range planStorageDevices {
|
currentDisk := currentDisks[diskInterface]
|
||||||
for diskInterface, disk := range disks {
|
if currentDisk == nil {
|
||||||
if currentStorageDevices[diskInterface] == nil {
|
// create disks that are not present in the current configuration
|
||||||
diskUpdateBody := &vms.UpdateRequestBody{}
|
err := createDisk(ctx, planDisk, vmAPI)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// disk is present, i.e. when cloned a template, but we need to check if it needs to be resized
|
||||||
|
if planDisk.Size.InGigabytes() < currentDisk.Size.InGigabytes() {
|
||||||
|
return nil, fmt.Errorf("disk resize fails requests size (%dG) is lower than current size (%s)",
|
||||||
|
planDisk.Size.InGigabytes(),
|
||||||
|
*currentDisk.Size,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
switch prefix {
|
moveDisk := false
|
||||||
case "virtio":
|
if *planDisk.ID != "" {
|
||||||
if diskUpdateBody.VirtualIODevices == nil {
|
fileIDParts := strings.Split(currentDisk.FileVolume, ":")
|
||||||
diskUpdateBody.VirtualIODevices = vms.CustomStorageDevices{}
|
moveDisk = *planDisk.ID != fileIDParts[0]
|
||||||
}
|
}
|
||||||
diskUpdateBody.VirtualIODevices[diskInterface] = disk
|
|
||||||
case "sata":
|
if moveDisk {
|
||||||
if diskUpdateBody.SATADevices == nil {
|
moveDiskTimeout := d.Get(mkTimeoutMoveDisk).(int)
|
||||||
diskUpdateBody.SATADevices = vms.CustomStorageDevices{}
|
deleteOriginalDisk := types.CustomBool(true)
|
||||||
}
|
|
||||||
diskUpdateBody.SATADevices[diskInterface] = disk
|
diskMoveBody := &vms.MoveDiskRequestBody{
|
||||||
case "scsi":
|
DeleteOriginalDisk: &deleteOriginalDisk,
|
||||||
if diskUpdateBody.SCSIDevices == nil {
|
Disk: diskInterface,
|
||||||
diskUpdateBody.SCSIDevices = vms.CustomStorageDevices{}
|
TargetStorage: *planDisk.ID,
|
||||||
}
|
|
||||||
diskUpdateBody.SCSIDevices[diskInterface] = disk
|
|
||||||
}
|
}
|
||||||
|
|
||||||
e = vmAPI.UpdateVM(ctx, diskUpdateBody)
|
err := vmAPI.MoveVMDisk(ctx, diskMoveBody, moveDiskTimeout)
|
||||||
if e != nil {
|
if err != nil {
|
||||||
return nil, e
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if planDisk.Size.InGigabytes() > currentDisk.Size.InGigabytes() {
|
||||||
|
moveDiskTimeout := d.Get(mkTimeoutMoveDisk).(int)
|
||||||
|
|
||||||
|
diskResizeBody := &vms.ResizeDiskRequestBody{
|
||||||
|
Disk: diskInterface,
|
||||||
|
Size: *types.DiskSizeFromGigabytes(planDisk.Size.InGigabytes()),
|
||||||
|
}
|
||||||
|
|
||||||
|
err := vmAPI.ResizeVMDisk(ctx, diskResizeBody, moveDiskTimeout)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return currentDisks, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func createDisk(ctx context.Context, disk *vms.CustomStorageDevice, vmAPI *vms.Client) error {
|
||||||
|
addToDevices := func(ds vms.CustomStorageDevices, disk *vms.CustomStorageDevice) vms.CustomStorageDevices {
|
||||||
disk := d.Get(mkDisk).([]interface{})
|
if ds == nil {
|
||||||
for i := range disk {
|
ds = vms.CustomStorageDevices{}
|
||||||
diskBlock := disk[i].(map[string]interface{})
|
|
||||||
|
|
||||||
diskInterface := diskBlock[mkDiskInterface].(string)
|
|
||||||
dataStoreID := diskBlock[mkDiskDatastoreID].(string)
|
|
||||||
diskSize := int64(diskBlock[mkDiskSize].(int))
|
|
||||||
|
|
||||||
prefix := diskDigitPrefix(diskInterface)
|
|
||||||
|
|
||||||
currentDiskInfo := currentStorageDevices[diskInterface]
|
|
||||||
configuredDiskInfo := planStorageDevices[prefix][diskInterface]
|
|
||||||
|
|
||||||
if currentDiskInfo == nil {
|
|
||||||
diskUpdateBody := &vms.UpdateRequestBody{}
|
|
||||||
|
|
||||||
switch prefix {
|
|
||||||
case "virtio":
|
|
||||||
if diskUpdateBody.VirtualIODevices == nil {
|
|
||||||
diskUpdateBody.VirtualIODevices = vms.CustomStorageDevices{}
|
|
||||||
}
|
|
||||||
|
|
||||||
diskUpdateBody.VirtualIODevices[diskInterface] = configuredDiskInfo
|
|
||||||
case "sata":
|
|
||||||
if diskUpdateBody.SATADevices == nil {
|
|
||||||
diskUpdateBody.SATADevices = vms.CustomStorageDevices{}
|
|
||||||
}
|
|
||||||
|
|
||||||
diskUpdateBody.SATADevices[diskInterface] = configuredDiskInfo
|
|
||||||
case "scsi":
|
|
||||||
if diskUpdateBody.SCSIDevices == nil {
|
|
||||||
diskUpdateBody.SCSIDevices = vms.CustomStorageDevices{}
|
|
||||||
}
|
|
||||||
|
|
||||||
diskUpdateBody.SCSIDevices[diskInterface] = configuredDiskInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
e = vmAPI.UpdateVM(ctx, diskUpdateBody)
|
|
||||||
if e != nil {
|
|
||||||
return nil, e
|
|
||||||
}
|
|
||||||
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if diskSize < currentDiskInfo.Size.InGigabytes() {
|
ds[*disk.Interface] = disk
|
||||||
return nil, fmt.Errorf("disk resize fails requests size (%dG) is lower than current size (%s)",
|
|
||||||
diskSize,
|
|
||||||
*currentDiskInfo.Size,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteOriginalDisk := types.CustomBool(true)
|
return ds
|
||||||
|
|
||||||
diskMoveBody := &vms.MoveDiskRequestBody{
|
|
||||||
DeleteOriginalDisk: &deleteOriginalDisk,
|
|
||||||
Disk: diskInterface,
|
|
||||||
TargetStorage: dataStoreID,
|
|
||||||
}
|
|
||||||
|
|
||||||
diskResizeBody := &vms.ResizeDiskRequestBody{
|
|
||||||
Disk: diskInterface,
|
|
||||||
Size: *types.DiskSizeFromGigabytes(diskSize),
|
|
||||||
}
|
|
||||||
|
|
||||||
moveDisk := false
|
|
||||||
|
|
||||||
if dataStoreID != "" {
|
|
||||||
moveDisk = true
|
|
||||||
|
|
||||||
if currentStorageDevices[diskInterface] != nil {
|
|
||||||
fileIDParts := strings.Split(currentStorageDevices[diskInterface].FileVolume, ":")
|
|
||||||
moveDisk = dataStoreID != fileIDParts[0]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if moveDisk {
|
|
||||||
moveDiskTimeout := d.Get(mkTimeoutMoveDisk).(int)
|
|
||||||
|
|
||||||
e = vmAPI.MoveVMDisk(ctx, diskMoveBody, moveDiskTimeout)
|
|
||||||
if e != nil {
|
|
||||||
return nil, e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if diskSize > currentDiskInfo.Size.InGigabytes() {
|
|
||||||
e = vmAPI.ResizeVMDisk(ctx, diskResizeBody)
|
|
||||||
if e != nil {
|
|
||||||
return nil, e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return currentStorageDevices, nil
|
diskUpdateBody := &vms.UpdateRequestBody{}
|
||||||
|
|
||||||
|
switch disk.StorageInterface() {
|
||||||
|
case "virtio":
|
||||||
|
diskUpdateBody.VirtualIODevices = addToDevices(diskUpdateBody.VirtualIODevices, disk)
|
||||||
|
case "sata":
|
||||||
|
diskUpdateBody.SATADevices = addToDevices(diskUpdateBody.SATADevices, disk)
|
||||||
|
case "scsi":
|
||||||
|
diskUpdateBody.SCSIDevices = addToDevices(diskUpdateBody.SCSIDevices, disk)
|
||||||
|
}
|
||||||
|
|
||||||
|
err := vmAPI.UpdateVM(ctx, diskUpdateBody)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func vmCreateCustomDisks(ctx context.Context, d *schema.ResourceData, m interface{}) error {
|
func vmCreateCustomDisks(ctx context.Context, d *schema.ResourceData, m interface{}) error {
|
||||||
@ -503,15 +458,12 @@ func vmCreateCustomDisks(ctx context.Context, d *schema.ResourceData, m interfac
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getStorageDevicesFromResource(d *schema.ResourceData) (map[string]map[string]vms.CustomStorageDevice, error) {
|
func getStorageDevicesFromResource(d *schema.ResourceData) (vms.CustomStorageDevices, error) {
|
||||||
return getDiskDeviceObjects1(d, d.Get(mkDisk).([]interface{}))
|
return getDiskDeviceObjects1(d, d.Get(mkDisk).([]interface{}))
|
||||||
}
|
}
|
||||||
|
|
||||||
func getDiskDeviceObjects1(
|
func getDiskDeviceObjects1(d *schema.ResourceData, disks []interface{}) (vms.CustomStorageDevices, error) {
|
||||||
d *schema.ResourceData,
|
diskDeviceObjects := vms.CustomStorageDevices{}
|
||||||
disks []interface{},
|
|
||||||
) (map[string]map[string]vms.CustomStorageDevice, error) {
|
|
||||||
diskDeviceObjects := map[string]map[string]vms.CustomStorageDevice{}
|
|
||||||
resource := VM()
|
resource := VM()
|
||||||
|
|
||||||
for _, diskEntry := range disks {
|
for _, diskEntry := range disks {
|
||||||
@ -601,23 +553,16 @@ func getDiskDeviceObjects1(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
baseDiskInterface := diskDigitPrefix(diskInterface)
|
storageInterface := diskDevice.StorageInterface()
|
||||||
|
|
||||||
if baseDiskInterface != "virtio" && baseDiskInterface != "scsi" &&
|
if storageInterface != "virtio" && storageInterface != "scsi" && storageInterface != "sata" {
|
||||||
baseDiskInterface != "sata" {
|
return diskDeviceObjects, fmt.Errorf(
|
||||||
errorMsg := fmt.Sprintf(
|
"Defined disk interface not supported. Interface was '%s', but only 'virtio', 'sata' and 'scsi' are supported",
|
||||||
"Defined disk interface not supported. Interface was %s, but only virtio, sata and scsi are supported",
|
|
||||||
diskInterface,
|
diskInterface,
|
||||||
)
|
)
|
||||||
|
|
||||||
return diskDeviceObjects, errors.New(errorMsg)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, present := diskDeviceObjects[baseDiskInterface]; !present {
|
diskDeviceObjects[diskInterface] = &diskDevice
|
||||||
diskDeviceObjects[baseDiskInterface] = map[string]vms.CustomStorageDevice{}
|
|
||||||
}
|
|
||||||
|
|
||||||
diskDeviceObjects[baseDiskInterface][diskInterface] = diskDevice
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return diskDeviceObjects, nil
|
return diskDeviceObjects, nil
|
||||||
@ -756,63 +701,53 @@ func updateDisk(d *schema.ResourceData, vmConfig *vms.GetResponseData, updateBod
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
diskDeviceObjects, err := getStorageDevicesFromResource(d)
|
currentDisks := populateFileIDs(mapStorageDevices(vmConfig), d)
|
||||||
|
|
||||||
|
planDisks, err := getStorageDevicesFromResource(d)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
diskDeviceInfo := populateFileIDs(mapStorageDevices(vmConfig), d)
|
addToDevices := func(ds vms.CustomStorageDevices, disk *vms.CustomStorageDevice) vms.CustomStorageDevices {
|
||||||
|
if ds == nil {
|
||||||
for prefix, diskMap := range diskDeviceObjects {
|
ds = vms.CustomStorageDevices{}
|
||||||
if diskMap == nil {
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for key, value := range diskMap {
|
ds[*disk.Interface] = disk
|
||||||
if diskDeviceInfo[key] == nil {
|
|
||||||
// TODO: create a new disk here
|
return ds
|
||||||
return fmt.Errorf("missing %s device %s", prefix, key)
|
}
|
||||||
}
|
|
||||||
|
for diskInterface, disk := range planDisks {
|
||||||
tmp := *diskDeviceInfo[key]
|
if currentDisks[diskInterface] == nil {
|
||||||
tmp.BurstableReadSpeedMbps = value.BurstableReadSpeedMbps
|
// TODO: create a new disk here
|
||||||
tmp.BurstableWriteSpeedMbps = value.BurstableWriteSpeedMbps
|
return fmt.Errorf("missing device %s", diskInterface)
|
||||||
tmp.MaxReadSpeedMbps = value.MaxReadSpeedMbps
|
}
|
||||||
tmp.MaxWriteSpeedMbps = value.MaxWriteSpeedMbps
|
|
||||||
tmp.Cache = value.Cache
|
// copy the current disk and update the fields
|
||||||
|
tmp := *currentDisks[diskInterface]
|
||||||
switch prefix {
|
tmp.BurstableReadSpeedMbps = disk.BurstableReadSpeedMbps
|
||||||
case "virtio":
|
tmp.BurstableWriteSpeedMbps = disk.BurstableWriteSpeedMbps
|
||||||
{
|
tmp.MaxReadSpeedMbps = disk.MaxReadSpeedMbps
|
||||||
if updateBody.VirtualIODevices == nil {
|
tmp.MaxWriteSpeedMbps = disk.MaxWriteSpeedMbps
|
||||||
updateBody.VirtualIODevices = vms.CustomStorageDevices{}
|
tmp.Cache = disk.Cache
|
||||||
}
|
tmp.Discard = disk.Discard
|
||||||
|
tmp.IOThread = disk.IOThread
|
||||||
updateBody.VirtualIODevices[key] = tmp
|
tmp.SSD = disk.SSD
|
||||||
}
|
|
||||||
case "sata":
|
switch disk.StorageInterface() {
|
||||||
{
|
case "virtio":
|
||||||
if updateBody.SATADevices == nil {
|
updateBody.VirtualIODevices = addToDevices(updateBody.VirtualIODevices, &tmp)
|
||||||
updateBody.SATADevices = vms.CustomStorageDevices{}
|
case "sata":
|
||||||
}
|
updateBody.SATADevices = addToDevices(updateBody.SATADevices, &tmp)
|
||||||
|
case "scsi":
|
||||||
updateBody.SATADevices[key] = tmp
|
updateBody.SCSIDevices = addToDevices(updateBody.SCSIDevices, &tmp)
|
||||||
}
|
case "ide":
|
||||||
case "scsi":
|
{
|
||||||
{
|
// Investigate whether to support IDE mapping.
|
||||||
if updateBody.SCSIDevices == nil {
|
|
||||||
updateBody.SCSIDevices = vms.CustomStorageDevices{}
|
|
||||||
}
|
|
||||||
|
|
||||||
updateBody.SCSIDevices[key] = tmp
|
|
||||||
}
|
|
||||||
case "ide":
|
|
||||||
{
|
|
||||||
// Investigate whether to support IDE mapping.
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("device prefix %s not supported", prefix)
|
|
||||||
}
|
}
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("device storage interface %s not supported", disk.StorageInterface())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -942,22 +877,3 @@ func getDiskDatastores(vm *vms.GetResponseData, d *schema.ResourceData) []string
|
|||||||
|
|
||||||
return datastores
|
return datastores
|
||||||
}
|
}
|
||||||
|
|
||||||
type customStorageDeviceMap struct {
|
|
||||||
// map of interface type (virtio|sata|scsi|...) -> map of interface name (virtio1) -> disk object
|
|
||||||
devices map[string]map[string]vms.CustomStorageDevice
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *customStorageDeviceMap) byInterfaceType(interfaceType string) []vms.CustomStorageDevice {
|
|
||||||
return maps.Values[map[string]vms.CustomStorageDevice](c.devices[interfaceType])
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *customStorageDeviceMap) byInterfaceName(interfaceName string) (*vms.CustomStorageDevice, bool) {
|
|
||||||
for _, devices := range c.devices {
|
|
||||||
if device, ok := devices[interfaceName]; ok {
|
|
||||||
return &device, true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
@ -15,7 +15,6 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"unicode"
|
|
||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
@ -357,16 +356,16 @@ func vmCreateClone(ctx context.Context, d *schema.ResourceData, m interface{}) d
|
|||||||
|
|
||||||
if len(cdrom) > 0 || len(initialization) > 0 {
|
if len(cdrom) > 0 || len(initialization) > 0 {
|
||||||
ideDevices = vms.CustomStorageDevices{
|
ideDevices = vms.CustomStorageDevices{
|
||||||
"ide0": vms.CustomStorageDevice{
|
"ide0": &vms.CustomStorageDevice{
|
||||||
Enabled: false,
|
Enabled: false,
|
||||||
},
|
},
|
||||||
"ide1": vms.CustomStorageDevice{
|
"ide1": &vms.CustomStorageDevice{
|
||||||
Enabled: false,
|
Enabled: false,
|
||||||
},
|
},
|
||||||
"ide2": vms.CustomStorageDevice{
|
"ide2": &vms.CustomStorageDevice{
|
||||||
Enabled: false,
|
Enabled: false,
|
||||||
},
|
},
|
||||||
"ide3": vms.CustomStorageDevice{
|
"ide3": &vms.CustomStorageDevice{
|
||||||
Enabled: false,
|
Enabled: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -385,7 +384,7 @@ func vmCreateClone(ctx context.Context, d *schema.ResourceData, m interface{}) d
|
|||||||
|
|
||||||
cdromMedia := "cdrom"
|
cdromMedia := "cdrom"
|
||||||
|
|
||||||
ideDevices[cdromInterface] = vms.CustomStorageDevice{
|
ideDevices[cdromInterface] = &vms.CustomStorageDevice{
|
||||||
Enabled: cdromEnabled,
|
Enabled: cdromEnabled,
|
||||||
FileVolume: cdromFileID,
|
FileVolume: cdromFileID,
|
||||||
Media: &cdromMedia,
|
Media: &cdromMedia,
|
||||||
@ -458,7 +457,7 @@ func vmCreateClone(ctx context.Context, d *schema.ResourceData, m interface{}) d
|
|||||||
|
|
||||||
cdromCloudInitFileID := fmt.Sprintf("%s:cloudinit", initializationDatastoreID)
|
cdromCloudInitFileID := fmt.Sprintf("%s:cloudinit", initializationDatastoreID)
|
||||||
cdromCloudInitMedia := "cdrom"
|
cdromCloudInitMedia := "cdrom"
|
||||||
ideDevices[initializationInterface] = vms.CustomStorageDevice{
|
ideDevices[initializationInterface] = &vms.CustomStorageDevice{
|
||||||
Enabled: cdromCloudInitEnabled,
|
Enabled: cdromCloudInitEnabled,
|
||||||
FileVolume: cdromCloudInitFileID,
|
FileVolume: cdromCloudInitFileID,
|
||||||
Media: &cdromCloudInitMedia,
|
Media: &cdromCloudInitMedia,
|
||||||
@ -784,11 +783,6 @@ func vmCreateCustom(ctx context.Context, d *schema.ResourceData, m interface{})
|
|||||||
|
|
||||||
description := d.Get(mkDescription).(string)
|
description := d.Get(mkDescription).(string)
|
||||||
|
|
||||||
diskDeviceObjects, err := getStorageDevicesFromResource(d)
|
|
||||||
if err != nil {
|
|
||||||
return diag.FromErr(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var efiDisk *vms.CustomEFIDisk
|
var efiDisk *vms.CustomEFIDisk
|
||||||
|
|
||||||
efiDiskBlock := d.Get(mkEFIDisk).([]interface{})
|
efiDiskBlock := d.Get(mkEFIDisk).([]interface{})
|
||||||
@ -831,11 +825,6 @@ func vmCreateCustom(ctx context.Context, d *schema.ResourceData, m interface{})
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
virtioDeviceObjects := diskDeviceObjects["virtio"]
|
|
||||||
scsiDeviceObjects := diskDeviceObjects["scsi"]
|
|
||||||
// ideDeviceObjects := getOrderedDiskDeviceList(diskDeviceObjects, "ide")
|
|
||||||
sataDeviceObjects := diskDeviceObjects["sata"]
|
|
||||||
|
|
||||||
initializationConfig := vmGetCloudInitConfig(d)
|
initializationConfig := vmGetCloudInitConfig(d)
|
||||||
|
|
||||||
if initializationConfig != nil {
|
if initializationConfig != nil {
|
||||||
@ -935,19 +924,25 @@ func vmCreateCustom(ctx context.Context, d *schema.ResourceData, m interface{})
|
|||||||
bootOrderConverted = []string{cdromInterface}
|
bootOrderConverted = []string{cdromInterface}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
planDisks, err := getStorageDevicesFromResource(d)
|
||||||
|
if err != nil {
|
||||||
|
return diag.FromErr(err)
|
||||||
|
}
|
||||||
|
|
||||||
bootOrder := d.Get(mkBootOrder).([]interface{})
|
bootOrder := d.Get(mkBootOrder).([]interface{})
|
||||||
//nolint:nestif
|
|
||||||
if len(bootOrder) == 0 {
|
if len(bootOrder) == 0 {
|
||||||
if sataDeviceObjects != nil {
|
for _, disk := range planDisks {
|
||||||
bootOrderConverted = append(bootOrderConverted, "sata0")
|
if *disk.Interface == "sata0" {
|
||||||
}
|
bootOrderConverted = append(bootOrderConverted, "sata0")
|
||||||
|
}
|
||||||
|
|
||||||
if scsiDeviceObjects != nil {
|
if *disk.Interface == "scsi0" {
|
||||||
bootOrderConverted = append(bootOrderConverted, "scsi0")
|
bootOrderConverted = append(bootOrderConverted, "scsi0")
|
||||||
}
|
}
|
||||||
|
|
||||||
if virtioDeviceObjects != nil {
|
if *disk.Interface == "virtio0" {
|
||||||
bootOrderConverted = append(bootOrderConverted, "virtio0")
|
bootOrderConverted = append(bootOrderConverted, "virtio0")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if networkDeviceObjects != nil {
|
if networkDeviceObjects != nil {
|
||||||
@ -967,12 +962,12 @@ func vmCreateCustom(ctx context.Context, d *schema.ResourceData, m interface{})
|
|||||||
|
|
||||||
ideDevice2Media := "cdrom"
|
ideDevice2Media := "cdrom"
|
||||||
ideDevices := vms.CustomStorageDevices{
|
ideDevices := vms.CustomStorageDevices{
|
||||||
cdromCloudInitInterface: vms.CustomStorageDevice{
|
cdromCloudInitInterface: &vms.CustomStorageDevice{
|
||||||
Enabled: cdromCloudInitEnabled,
|
Enabled: cdromCloudInitEnabled,
|
||||||
FileVolume: cdromCloudInitFileID,
|
FileVolume: cdromCloudInitFileID,
|
||||||
Media: &ideDevice2Media,
|
Media: &ideDevice2Media,
|
||||||
},
|
},
|
||||||
cdromInterface: vms.CustomStorageDevice{
|
cdromInterface: &vms.CustomStorageDevice{
|
||||||
Enabled: cdromEnabled,
|
Enabled: cdromEnabled,
|
||||||
FileVolume: cdromFileID,
|
FileVolume: cdromFileID,
|
||||||
Media: &ideDevice2Media,
|
Media: &ideDevice2Media,
|
||||||
@ -1028,15 +1023,18 @@ func vmCreateCustom(ctx context.Context, d *schema.ResourceData, m interface{})
|
|||||||
VMID: &vmID,
|
VMID: &vmID,
|
||||||
}
|
}
|
||||||
|
|
||||||
if sataDeviceObjects != nil {
|
sataDeviceObjects := planDisks.ByStorageInterface("sata")
|
||||||
|
if len(sataDeviceObjects) > 0 {
|
||||||
createBody.SATADevices = sataDeviceObjects
|
createBody.SATADevices = sataDeviceObjects
|
||||||
}
|
}
|
||||||
|
|
||||||
if scsiDeviceObjects != nil {
|
scsiDeviceObjects := planDisks.ByStorageInterface("scsi")
|
||||||
|
if len(scsiDeviceObjects) > 0 {
|
||||||
createBody.SCSIDevices = scsiDeviceObjects
|
createBody.SCSIDevices = scsiDeviceObjects
|
||||||
}
|
}
|
||||||
|
|
||||||
if virtioDeviceObjects != nil {
|
virtioDeviceObjects := planDisks.ByStorageInterface("virtio")
|
||||||
|
if len(virtioDeviceObjects) > 0 {
|
||||||
createBody.VirtualIODevices = virtioDeviceObjects
|
createBody.VirtualIODevices = virtioDeviceObjects
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3266,16 +3264,16 @@ func vmUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D
|
|||||||
|
|
||||||
updateBody := &vms.UpdateRequestBody{
|
updateBody := &vms.UpdateRequestBody{
|
||||||
IDEDevices: vms.CustomStorageDevices{
|
IDEDevices: vms.CustomStorageDevices{
|
||||||
"ide0": vms.CustomStorageDevice{
|
"ide0": &vms.CustomStorageDevice{
|
||||||
Enabled: false,
|
Enabled: false,
|
||||||
},
|
},
|
||||||
"ide1": vms.CustomStorageDevice{
|
"ide1": &vms.CustomStorageDevice{
|
||||||
Enabled: false,
|
Enabled: false,
|
||||||
},
|
},
|
||||||
"ide2": vms.CustomStorageDevice{
|
"ide2": &vms.CustomStorageDevice{
|
||||||
Enabled: false,
|
Enabled: false,
|
||||||
},
|
},
|
||||||
"ide3": vms.CustomStorageDevice{
|
"ide3": &vms.CustomStorageDevice{
|
||||||
Enabled: false,
|
Enabled: false,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -3462,7 +3460,7 @@ func vmUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D
|
|||||||
|
|
||||||
cdromMedia := "cdrom"
|
cdromMedia := "cdrom"
|
||||||
|
|
||||||
updateBody.IDEDevices[cdromInterface] = vms.CustomStorageDevice{
|
updateBody.IDEDevices[cdromInterface] = &vms.CustomStorageDevice{
|
||||||
Enabled: cdromEnabled,
|
Enabled: cdromEnabled,
|
||||||
FileVolume: cdromFileID,
|
FileVolume: cdromFileID,
|
||||||
Media: &cdromMedia,
|
Media: &cdromMedia,
|
||||||
@ -3609,7 +3607,7 @@ func vmUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D
|
|||||||
fileVolume = ideDevice.FileVolume
|
fileVolume = ideDevice.FileVolume
|
||||||
}
|
}
|
||||||
|
|
||||||
updateBody.IDEDevices[initializationInterface] = vms.CustomStorageDevice{
|
updateBody.IDEDevices[initializationInterface] = &vms.CustomStorageDevice{
|
||||||
Enabled: true,
|
Enabled: true,
|
||||||
FileVolume: fileVolume,
|
FileVolume: fileVolume,
|
||||||
Media: &cdromMedia,
|
Media: &cdromMedia,
|
||||||
@ -3854,13 +3852,11 @@ func vmUpdateDiskLocationAndSize(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if oldEfiDisk != nil {
|
if oldEfiDisk != nil {
|
||||||
baseDiskInterface := diskDigitPrefix(*oldEfiDisk.Interface)
|
diskOldEntries[*oldEfiDisk.Interface] = oldEfiDisk
|
||||||
diskOldEntries[baseDiskInterface][*oldEfiDisk.Interface] = *oldEfiDisk
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if newEfiDisk != nil {
|
if newEfiDisk != nil {
|
||||||
baseDiskInterface := diskDigitPrefix(*newEfiDisk.Interface)
|
diskNewEntries[*newEfiDisk.Interface] = newEfiDisk
|
||||||
diskNewEntries[baseDiskInterface][*newEfiDisk.Interface] = *newEfiDisk
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if oldEfiDisk != nil && newEfiDisk != nil && oldEfiDisk.Size != newEfiDisk.Size {
|
if oldEfiDisk != nil && newEfiDisk != nil && oldEfiDisk.Size != newEfiDisk.Size {
|
||||||
@ -3878,13 +3874,11 @@ func vmUpdateDiskLocationAndSize(
|
|||||||
newTPMState := vmGetTPMStateAsStorageDevice(d, diskNew.([]interface{}))
|
newTPMState := vmGetTPMStateAsStorageDevice(d, diskNew.([]interface{}))
|
||||||
|
|
||||||
if oldTPMState != nil {
|
if oldTPMState != nil {
|
||||||
baseDiskInterface := diskDigitPrefix(*oldTPMState.Interface)
|
diskOldEntries[*oldTPMState.Interface] = oldTPMState
|
||||||
diskOldEntries[baseDiskInterface][*oldTPMState.Interface] = *oldTPMState
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if newTPMState != nil {
|
if newTPMState != nil {
|
||||||
baseDiskInterface := diskDigitPrefix(*newTPMState.Interface)
|
diskNewEntries[*newTPMState.Interface] = newTPMState
|
||||||
diskNewEntries[baseDiskInterface][*newTPMState.Interface] = *newTPMState
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if oldTPMState != nil && newTPMState != nil && oldTPMState.Size != newTPMState.Size {
|
if oldTPMState != nil && newTPMState != nil && oldTPMState.Size != newTPMState.Size {
|
||||||
@ -3894,64 +3888,64 @@ func vmUpdateDiskLocationAndSize(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: move to disks.go
|
||||||
|
|
||||||
var diskMoveBodies []*vms.MoveDiskRequestBody
|
var diskMoveBodies []*vms.MoveDiskRequestBody
|
||||||
|
|
||||||
var diskResizeBodies []*vms.ResizeDiskRequestBody
|
var diskResizeBodies []*vms.ResizeDiskRequestBody
|
||||||
|
|
||||||
shutdownForDisksRequired := false
|
shutdownForDisksRequired := false
|
||||||
|
|
||||||
for prefix, diskMap := range diskOldEntries {
|
for oldKey, oldDisk := range diskOldEntries {
|
||||||
for oldKey, oldDisk := range diskMap {
|
if _, present := diskNewEntries[oldKey]; !present {
|
||||||
if _, present := diskNewEntries[prefix][oldKey]; !present {
|
return diag.Errorf(
|
||||||
|
"deletion of disks not supported. Please delete disk by hand. Old Interface was %s",
|
||||||
|
*oldDisk.Interface,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
if *oldDisk.ID != *diskNewEntries[oldKey].ID {
|
||||||
|
if oldDisk.IsOwnedBy(vmID) {
|
||||||
|
deleteOriginalDisk := types.CustomBool(true)
|
||||||
|
|
||||||
|
diskMoveBodies = append(
|
||||||
|
diskMoveBodies,
|
||||||
|
&vms.MoveDiskRequestBody{
|
||||||
|
DeleteOriginalDisk: &deleteOriginalDisk,
|
||||||
|
Disk: *oldDisk.Interface,
|
||||||
|
TargetStorage: *diskNewEntries[oldKey].ID,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
// Cannot be done while VM is running.
|
||||||
|
shutdownForDisksRequired = true
|
||||||
|
} else {
|
||||||
return diag.Errorf(
|
return diag.Errorf(
|
||||||
"deletion of disks not supported. Please delete disk by hand. Old Interface was %s",
|
"Cannot move %s:%s to datastore %s in VM %d configuration, it is not owned by this VM!",
|
||||||
*oldDisk.Interface,
|
*oldDisk.ID,
|
||||||
|
*oldDisk.PathInDatastore(),
|
||||||
|
*diskNewEntries[oldKey].ID,
|
||||||
|
vmID,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if *oldDisk.ID != *diskNewEntries[prefix][oldKey].ID {
|
if *oldDisk.Size < *diskNewEntries[oldKey].Size {
|
||||||
if oldDisk.IsOwnedBy(vmID) {
|
if oldDisk.IsOwnedBy(vmID) {
|
||||||
deleteOriginalDisk := types.CustomBool(true)
|
diskResizeBodies = append(
|
||||||
|
diskResizeBodies,
|
||||||
diskMoveBodies = append(
|
&vms.ResizeDiskRequestBody{
|
||||||
diskMoveBodies,
|
Disk: *oldDisk.Interface,
|
||||||
&vms.MoveDiskRequestBody{
|
Size: *diskNewEntries[oldKey].Size,
|
||||||
DeleteOriginalDisk: &deleteOriginalDisk,
|
},
|
||||||
Disk: *oldDisk.Interface,
|
)
|
||||||
TargetStorage: *diskNewEntries[prefix][oldKey].ID,
|
} else {
|
||||||
},
|
return diag.Errorf(
|
||||||
)
|
"Cannot resize %s:%s in VM %d configuration, it is not owned by this VM!",
|
||||||
|
*oldDisk.ID,
|
||||||
// Cannot be done while VM is running.
|
*oldDisk.PathInDatastore(),
|
||||||
shutdownForDisksRequired = true
|
vmID,
|
||||||
} else {
|
)
|
||||||
return diag.Errorf(
|
|
||||||
"Cannot move %s:%s to datastore %s in VM %d configuration, it is not owned by this VM!",
|
|
||||||
*oldDisk.ID,
|
|
||||||
*oldDisk.PathInDatastore(),
|
|
||||||
*diskNewEntries[prefix][oldKey].ID,
|
|
||||||
vmID,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if *oldDisk.Size < *diskNewEntries[prefix][oldKey].Size {
|
|
||||||
if oldDisk.IsOwnedBy(vmID) {
|
|
||||||
diskResizeBodies = append(
|
|
||||||
diskResizeBodies,
|
|
||||||
&vms.ResizeDiskRequestBody{
|
|
||||||
Disk: *oldDisk.Interface,
|
|
||||||
Size: *diskNewEntries[prefix][oldKey].Size,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
return diag.Errorf(
|
|
||||||
"Cannot resize %s:%s in VM %d configuration, it is not owned by this VM!",
|
|
||||||
*oldDisk.ID,
|
|
||||||
*oldDisk.PathInDatastore(),
|
|
||||||
vmID,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3972,7 +3966,9 @@ func vmUpdateDiskLocationAndSize(
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, reqBody := range diskResizeBodies {
|
for _, reqBody := range diskResizeBodies {
|
||||||
err = vmAPI.ResizeVMDisk(ctx, reqBody)
|
moveDiskTimeout := d.Get(mkTimeoutMoveDisk).(int)
|
||||||
|
|
||||||
|
err = vmAPI.ResizeVMDisk(ctx, reqBody, moveDiskTimeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return diag.FromErr(err)
|
return diag.FromErr(err)
|
||||||
}
|
}
|
||||||
@ -4075,16 +4071,6 @@ func vmDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.D
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func diskDigitPrefix(s string) string {
|
|
||||||
for i, r := range s {
|
|
||||||
if unicode.IsDigit(r) {
|
|
||||||
return s[:i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return s
|
|
||||||
}
|
|
||||||
|
|
||||||
func getPCIInfo(resp *vms.GetResponseData, _ *schema.ResourceData) map[string]*vms.CustomPCIDevice {
|
func getPCIInfo(resp *vms.GetResponseData, _ *schema.ResourceData) map[string]*vms.CustomPCIDevice {
|
||||||
pciDevices := map[string]*vms.CustomPCIDevice{}
|
pciDevices := map[string]*vms.CustomPCIDevice{}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user