0
0
mirror of https://github.com/bpg/terraform-provider-proxmox.git synced 2025-07-04 21:14:05 +00:00

Initial support for container cloning

This commit is contained in:
Dan Petersen 2020-01-26 05:13:26 +01:00
parent 1f96d6851a
commit 1efe8019e4
32 changed files with 718 additions and 205 deletions

View File

@ -2,7 +2,9 @@
ENHANCEMENTS:
* resource/virtual_environment_container: Add `clone` argument
* resource/virtual_environment_container: Add `disk` argument
* resource/virtual_environment_container: Add `template` argument
* resource/virtual_environment_vm: Add `audio_device` argument
* resource/virtual_environment_vm: Add `clone` argument
* resource/virtual_environment_vm: Add `serial_device` argument
@ -10,6 +12,7 @@ ENHANCEMENTS:
BUG FIXES:
* resource/virtual_environment_container: Fix `network_interface` deletion issue
* resource/virtual_environment_vm: Fix `network_device` deletion issue
* resource/virtual_environment_vm: Fix slow refresh when VM is stopped and agent is enabled

View File

@ -288,6 +288,10 @@ This data source doesn't accept arguments.
##### Container (proxmox_virtual_environment_container)
###### Arguments
* `clone` - (Optional) The cloning configuration
* `datastore_id` - (Optional) The ID of the target datastore
* `node_name` - (Optional) The name of the source node (leave blank, if equal to the `node_name` argument)
* `vm_id` - (Required) The ID of the source container
* `console` - (Optional) The console configuration
* `enabled` - (Optional) Whether to enable the console device (defaults to `true`)
* `mode` - (Optional) The console mode (defaults to `tty`)
@ -346,6 +350,7 @@ This data source doesn't accept arguments.
* `unmanaged` - Unmanaged
* `pool_id` - (Optional) The ID of a pool to assign the container to
* `started` - (Optional) Whether to start the container (defaults to `true`)
* `template` - (Optional) Whether to create a template (defaults to `false`)
* `vm_id` - (Optional) The ID
###### Attributes

View File

@ -1,4 +1,4 @@
resource "proxmox_virtual_environment_container" "example" {
resource "proxmox_virtual_environment_container" "example_template" {
description = "Managed by Terraform"
initialization {
@ -6,7 +6,7 @@ resource "proxmox_virtual_environment_container" "example" {
server = "1.1.1.1"
}
hostname = "terraform-provider-proxmox-example-lxc"
hostname = "terraform-provider-proxmox-example-lxc-template"
ip_config {
ipv4 {
@ -31,8 +31,23 @@ resource "proxmox_virtual_environment_container" "example" {
type = "ubuntu"
}
pool_id = "${proxmox_virtual_environment_pool.example.id}"
vm_id = 2039
pool_id = "${proxmox_virtual_environment_pool.example.id}"
template = true
vm_id = 2042
}
resource "proxmox_virtual_environment_container" "example" {
clone {
vm_id = proxmox_virtual_environment_container.example_template.id
}
initialization {
hostname = "terraform-provider-proxmox-example-lxc"
}
node_name = "${data.proxmox_virtual_environment_nodes.example.names[0]}"
pool_id = "${proxmox_virtual_environment_pool.example.id}"
vm_id = 2043
}
output "resource_proxmox_virtual_environment_container_example_id" {

View File

@ -12,6 +12,11 @@ import (
"time"
)
// CloneContainer clones a container.
func (c *VirtualEnvironmentClient) CloneContainer(nodeName string, vmID int, d *VirtualEnvironmentContainerCloneRequestBody) error {
return c.DoRequest(hmPOST, fmt.Sprintf("nodes/%s/lxc/%d/clone", url.PathEscape(nodeName), vmID), d, nil)
}
// CreateContainer creates a container.
func (c *VirtualEnvironmentClient) CreateContainer(nodeName string, d *VirtualEnvironmentContainerCreateRequestBody) error {
return c.DoRequest(hmPOST, fmt.Sprintf("nodes/%s/lxc", url.PathEscape(nodeName)), d, nil)
@ -112,7 +117,7 @@ func (c *VirtualEnvironmentClient) WaitForContainerState(nodeName string, vmID i
}
// WaitForContainerLock waits for a container lock to be released.
func (c *VirtualEnvironmentClient) WaitForContainerLock(nodeName string, vmID int, timeout int, delay int) error {
func (c *VirtualEnvironmentClient) WaitForContainerLock(nodeName string, vmID int, timeout int, delay int, ignoreErrorResponse bool) error {
timeDelay := int64(delay)
timeMax := float64(timeout)
timeStart := time.Now()
@ -123,10 +128,10 @@ func (c *VirtualEnvironmentClient) WaitForContainerLock(nodeName string, vmID in
data, err := c.GetContainerStatus(nodeName, vmID)
if err != nil {
return err
}
if data.Lock == nil || *data.Lock == "" {
if !ignoreErrorResponse {
return err
}
} else if data.Lock == nil || *data.Lock == "" {
return nil
}

View File

@ -12,6 +12,19 @@ import (
"strings"
)
// VirtualEnvironmentContainerCloneRequestBody contains the data for an container clone request.
type VirtualEnvironmentContainerCloneRequestBody struct {
BandwidthLimit *int `json:"bwlimit,omitempty" url:"bwlimit,omitempty"`
Description *string `json:"description,omitempty" url:"description,omitempty"`
FullCopy *CustomBool `json:"full,omitempty" url:"full,omitempty,int"`
Hostname *string `json:"hostname,omitempty" url:"hostname,omitempty"`
PoolID *string `json:"pool,omitempty" url:"pool,omitempty"`
SnapshotName *string `json:"snapname,omitempty" url:"snapname,omitempty"`
TargetNodeName *string `json:"target,omitempty" url:"target,omitempty"`
TargetStorage *string `json:"storage,omitempty" url:"storage,omitempty"`
VMIDNew int `json:"newid" url:"newid"`
}
// VirtualEnvironmentContainerCreateRequestBody contains the data for an user create request.
type VirtualEnvironmentContainerCreateRequestBody struct {
BandwidthLimit *float64 `json:"bwlimit,omitempty" url:"bwlimit,omitempty"`

View File

@ -38,7 +38,7 @@ func TestDataSourceVirtualEnvironmentDatastoresSchema(t *testing.T) {
mkDataSourceVirtualEnvironmentDatastoresTypes,
})
testSchemaValueTypes(t, s, map[string]schema.ValueType{
testValueTypes(t, s, map[string]schema.ValueType{
mkDataSourceVirtualEnvironmentDatastoresActive: schema.TypeList,
mkDataSourceVirtualEnvironmentDatastoresContentTypes: schema.TypeList,
mkDataSourceVirtualEnvironmentDatastoresDatastoreIDs: schema.TypeList,

View File

@ -31,7 +31,7 @@ func TestDataSourceVirtualEnvironmentDNSSchema(t *testing.T) {
mkDataSourceVirtualEnvironmentDNSServers,
})
testSchemaValueTypes(t, s, map[string]schema.ValueType{
testValueTypes(t, s, map[string]schema.ValueType{
mkDataSourceVirtualEnvironmentDNSDomain: schema.TypeString,
mkDataSourceVirtualEnvironmentDNSNodeName: schema.TypeString,
mkDataSourceVirtualEnvironmentDNSServers: schema.TypeList,

View File

@ -33,7 +33,7 @@ func TestDataSourceVirtualEnvironmentGroupSchema(t *testing.T) {
mkDataSourceVirtualEnvironmentGroupMembers,
})
testSchemaValueTypes(t, s, map[string]schema.ValueType{
testValueTypes(t, s, map[string]schema.ValueType{
mkDataSourceVirtualEnvironmentGroupACL: schema.TypeSet,
mkDataSourceVirtualEnvironmentGroupID: schema.TypeString,
mkDataSourceVirtualEnvironmentGroupComment: schema.TypeString,
@ -48,7 +48,7 @@ func TestDataSourceVirtualEnvironmentGroupSchema(t *testing.T) {
mkDataSourceVirtualEnvironmentGroupACLRoleID,
})
testSchemaValueTypes(t, aclSchema, map[string]schema.ValueType{
testValueTypes(t, aclSchema, map[string]schema.ValueType{
mkDataSourceVirtualEnvironmentGroupACLPath: schema.TypeString,
mkDataSourceVirtualEnvironmentGroupACLPropagate: schema.TypeBool,
mkDataSourceVirtualEnvironmentGroupACLRoleID: schema.TypeString,

View File

@ -27,7 +27,7 @@ func TestDataSourceVirtualEnvironmentGroupsSchema(t *testing.T) {
mkDataSourceVirtualEnvironmentGroupsGroupIDs,
})
testSchemaValueTypes(t, s, map[string]schema.ValueType{
testValueTypes(t, s, map[string]schema.ValueType{
mkDataSourceVirtualEnvironmentGroupsComments: schema.TypeList,
mkDataSourceVirtualEnvironmentGroupsGroupIDs: schema.TypeList,
})

View File

@ -33,7 +33,7 @@ func TestDataSourceVirtualEnvironmentHostsSchema(t *testing.T) {
mkDataSourceVirtualEnvironmentHostsHostnames,
})
testSchemaValueTypes(t, s, map[string]schema.ValueType{
testValueTypes(t, s, map[string]schema.ValueType{
mkDataSourceVirtualEnvironmentHostsAddresses: schema.TypeList,
mkDataSourceVirtualEnvironmentHostsDigest: schema.TypeString,
mkDataSourceVirtualEnvironmentHostsEntries: schema.TypeList,
@ -48,7 +48,7 @@ func TestDataSourceVirtualEnvironmentHostsSchema(t *testing.T) {
mkDataSourceVirtualEnvironmentHostsEntriesHostnames,
})
testSchemaValueTypes(t, entriesSchema, map[string]schema.ValueType{
testValueTypes(t, entriesSchema, map[string]schema.ValueType{
mkDataSourceVirtualEnvironmentHostsEntriesAddress: schema.TypeString,
mkDataSourceVirtualEnvironmentHostsEntriesHostnames: schema.TypeList,
})

View File

@ -35,7 +35,7 @@ func TestDataSourceVirtualEnvironmentNodesSchema(t *testing.T) {
mkDataSourceVirtualEnvironmentNodesUptime,
})
testSchemaValueTypes(t, s, map[string]schema.ValueType{
testValueTypes(t, s, map[string]schema.ValueType{
mkDataSourceVirtualEnvironmentNodesCPUCount: schema.TypeList,
mkDataSourceVirtualEnvironmentNodesCPUUtilization: schema.TypeList,
mkDataSourceVirtualEnvironmentNodesMemoryAvailable: schema.TypeList,

View File

@ -32,7 +32,7 @@ func TestDataSourceVirtualEnvironmentPoolSchema(t *testing.T) {
mkDataSourceVirtualEnvironmentPoolMembers,
})
testSchemaValueTypes(t, s, map[string]schema.ValueType{
testValueTypes(t, s, map[string]schema.ValueType{
mkDataSourceVirtualEnvironmentPoolComment: schema.TypeString,
mkDataSourceVirtualEnvironmentPoolMembers: schema.TypeList,
mkDataSourceVirtualEnvironmentPoolPoolID: schema.TypeString,
@ -48,7 +48,7 @@ func TestDataSourceVirtualEnvironmentPoolSchema(t *testing.T) {
mkDataSourceVirtualEnvironmentPoolMembersVMID,
})
testSchemaValueTypes(t, membersSchema, map[string]schema.ValueType{
testValueTypes(t, membersSchema, map[string]schema.ValueType{
mkDataSourceVirtualEnvironmentPoolMembersDatastoreID: schema.TypeString,
mkDataSourceVirtualEnvironmentPoolMembersID: schema.TypeString,
mkDataSourceVirtualEnvironmentPoolMembersNodeName: schema.TypeString,

View File

@ -27,7 +27,7 @@ func TestDataSourceVirtualEnvironmentPoolsSchema(t *testing.T) {
mkDataSourceVirtualEnvironmentPoolsPoolIDs,
})
testSchemaValueTypes(t, s, map[string]schema.ValueType{
testValueTypes(t, s, map[string]schema.ValueType{
mkDataSourceVirtualEnvironmentPoolsPoolIDs: schema.TypeList,
})
}

View File

@ -31,7 +31,7 @@ func TestDataSourceVirtualEnvironmentRoleSchema(t *testing.T) {
mkDataSourceVirtualEnvironmentRolePrivileges,
})
testSchemaValueTypes(t, s, map[string]schema.ValueType{
testValueTypes(t, s, map[string]schema.ValueType{
mkDataSourceVirtualEnvironmentRoleID: schema.TypeString,
mkDataSourceVirtualEnvironmentRolePrivileges: schema.TypeSet,
})

View File

@ -28,7 +28,7 @@ func TestDataSourceVirtualEnvironmentRolesSchema(t *testing.T) {
mkDataSourceVirtualEnvironmentRolesSpecial,
})
testSchemaValueTypes(t, s, map[string]schema.ValueType{
testValueTypes(t, s, map[string]schema.ValueType{
mkDataSourceVirtualEnvironmentRolesPrivileges: schema.TypeList,
mkDataSourceVirtualEnvironmentRolesRoleIDs: schema.TypeList,
mkDataSourceVirtualEnvironmentRolesSpecial: schema.TypeList,

View File

@ -39,7 +39,7 @@ func TestDataSourceVirtualEnvironmentUserSchema(t *testing.T) {
mkDataSourceVirtualEnvironmentUserLastName,
})
testSchemaValueTypes(t, s, map[string]schema.ValueType{
testValueTypes(t, s, map[string]schema.ValueType{
mkDataSourceVirtualEnvironmentUserACL: schema.TypeSet,
mkDataSourceVirtualEnvironmentUserComment: schema.TypeString,
mkDataSourceVirtualEnvironmentUserEmail: schema.TypeString,
@ -59,7 +59,7 @@ func TestDataSourceVirtualEnvironmentUserSchema(t *testing.T) {
mkDataSourceVirtualEnvironmentUserACLRoleID,
})
testSchemaValueTypes(t, aclSchema, map[string]schema.ValueType{
testValueTypes(t, aclSchema, map[string]schema.ValueType{
mkDataSourceVirtualEnvironmentUserACLPath: schema.TypeString,
mkDataSourceVirtualEnvironmentUserACLPropagate: schema.TypeBool,
mkDataSourceVirtualEnvironmentUserACLRoleID: schema.TypeString,

View File

@ -35,7 +35,7 @@ func TestDataSourceVirtualEnvironmentUsersSchema(t *testing.T) {
mkDataSourceVirtualEnvironmentUsersUserIDs,
})
testSchemaValueTypes(t, s, map[string]schema.ValueType{
testValueTypes(t, s, map[string]schema.ValueType{
mkDataSourceVirtualEnvironmentUsersComments: schema.TypeList,
mkDataSourceVirtualEnvironmentUsersEmails: schema.TypeList,
mkDataSourceVirtualEnvironmentUsersEnabled: schema.TypeList,

View File

@ -30,7 +30,7 @@ func TestDataSourceVirtualEnvironmentVersionSchema(t *testing.T) {
mkDataSourceVirtualEnvironmentVersionVersion,
})
testSchemaValueTypes(t, s, map[string]schema.ValueType{
testValueTypes(t, s, map[string]schema.ValueType{
mkDataSourceVirtualEnvironmentVersionKeyboardLayout: schema.TypeString,
mkDataSourceVirtualEnvironmentVersionRelease: schema.TypeString,
mkDataSourceVirtualEnvironmentVersionRepositoryID: schema.TypeString,

View File

@ -29,7 +29,7 @@ func TestProviderSchema(t *testing.T) {
mkProviderVirtualEnvironment,
})
testSchemaValueTypes(t, s, map[string]schema.ValueType{
testValueTypes(t, s, map[string]schema.ValueType{
mkProviderVirtualEnvironment: schema.TypeList,
})
@ -42,7 +42,7 @@ func TestProviderSchema(t *testing.T) {
mkProviderVirtualEnvironmentUsername,
})
testSchemaValueTypes(t, veSchema, map[string]schema.ValueType{
testValueTypes(t, veSchema, map[string]schema.ValueType{
mkProviderVirtualEnvironmentEndpoint: schema.TypeString,
mkProviderVirtualEnvironmentInsecure: schema.TypeBool,
mkProviderVirtualEnvironmentPassword: schema.TypeString,

View File

@ -45,7 +45,7 @@ func TestResourceVirtualEnvironmentCertificateSchema(t *testing.T) {
mkResourceVirtualEnvironmentCertificateSubjectAlternativeNames,
})
testSchemaValueTypes(t, s, map[string]schema.ValueType{
testValueTypes(t, s, map[string]schema.ValueType{
mkResourceVirtualEnvironmentCertificateCertificate: schema.TypeString,
mkResourceVirtualEnvironmentCertificateCertificateChain: schema.TypeString,
mkResourceVirtualEnvironmentCertificateExpirationDate: schema.TypeString,

View File

@ -15,6 +15,8 @@ import (
)
const (
dvResourceVirtualEnvironmentContainerCloneDatastoreID = ""
dvResourceVirtualEnvironmentContainerCloneNodeName = ""
dvResourceVirtualEnvironmentContainerConsoleEnabled = true
dvResourceVirtualEnvironmentContainerConsoleMode = "tty"
dvResourceVirtualEnvironmentContainerConsoleTTYCount = 2
@ -41,8 +43,15 @@ const (
dvResourceVirtualEnvironmentContainerOperatingSystemType = "unmanaged"
dvResourceVirtualEnvironmentContainerPoolID = ""
dvResourceVirtualEnvironmentContainerStarted = true
dvResourceVirtualEnvironmentContainerTemplate = false
dvResourceVirtualEnvironmentContainerVMID = -1
maxResourceVirtualEnvironmentContainerNetworkInterfaces = 8
mkResourceVirtualEnvironmentContainerClone = "clone"
mkResourceVirtualEnvironmentContainerCloneDatastoreID = "datastore_id"
mkResourceVirtualEnvironmentContainerCloneNodeName = "node_name"
mkResourceVirtualEnvironmentContainerCloneVMID = "vm_id"
mkResourceVirtualEnvironmentContainerConsole = "console"
mkResourceVirtualEnvironmentContainerConsoleEnabled = "enabled"
mkResourceVirtualEnvironmentContainerConsoleMode = "type"
@ -86,12 +95,48 @@ const (
mkResourceVirtualEnvironmentContainerOperatingSystemType = "type"
mkResourceVirtualEnvironmentContainerPoolID = "pool_id"
mkResourceVirtualEnvironmentContainerStarted = "started"
mkResourceVirtualEnvironmentContainerTemplate = "template"
mkResourceVirtualEnvironmentContainerVMID = "vm_id"
)
func resourceVirtualEnvironmentContainer() *schema.Resource {
return &schema.Resource{
Schema: map[string]*schema.Schema{
mkResourceVirtualEnvironmentContainerClone: &schema.Schema{
Type: schema.TypeList,
Description: "The cloning configuration",
Optional: true,
DefaultFunc: func() (interface{}, error) {
return []interface{}{}, nil
},
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
mkResourceVirtualEnvironmentContainerCloneDatastoreID: {
Type: schema.TypeString,
Description: "The ID of the target datastore",
Optional: true,
ForceNew: true,
Default: dvResourceVirtualEnvironmentContainerCloneDatastoreID,
},
mkResourceVirtualEnvironmentContainerCloneNodeName: {
Type: schema.TypeString,
Description: "The name of the source node",
Optional: true,
ForceNew: true,
Default: dvResourceVirtualEnvironmentContainerCloneNodeName,
},
mkResourceVirtualEnvironmentContainerCloneVMID: {
Type: schema.TypeInt,
Description: "The ID of the source container",
Required: true,
ForceNew: true,
ValidateFunc: getVMIDValidator(),
},
},
},
MaxItems: 1,
MinItems: 0,
},
mkResourceVirtualEnvironmentContainerConsole: &schema.Schema{
Type: schema.TypeList,
Description: "The console configuration",
@ -436,7 +481,7 @@ func resourceVirtualEnvironmentContainer() *schema.Resource {
},
},
},
MaxItems: 8,
MaxItems: maxResourceVirtualEnvironmentContainerNetworkInterfaces,
MinItems: 0,
},
mkResourceVirtualEnvironmentContainerNodeName: &schema.Schema{
@ -448,7 +493,8 @@ func resourceVirtualEnvironmentContainer() *schema.Resource {
mkResourceVirtualEnvironmentContainerOperatingSystem: &schema.Schema{
Type: schema.TypeList,
Description: "The operating system configuration",
Required: true,
Optional: true,
ForceNew: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
mkResourceVirtualEnvironmentContainerOperatingSystemTemplateFileID: {
@ -482,6 +528,16 @@ func resourceVirtualEnvironmentContainer() *schema.Resource {
Description: "Whether to start the container",
Optional: true,
Default: dvResourceVirtualEnvironmentContainerStarted,
DiffSuppressFunc: func(k, old, new string, d *schema.ResourceData) bool {
return d.Get(mkResourceVirtualEnvironmentContainerTemplate).(bool)
},
},
mkResourceVirtualEnvironmentContainerTemplate: {
Type: schema.TypeBool,
Description: "Whether to create a template",
Optional: true,
ForceNew: true,
Default: dvResourceVirtualEnvironmentContainerTemplate,
},
mkResourceVirtualEnvironmentContainerVMID: {
Type: schema.TypeInt,
@ -500,6 +556,326 @@ func resourceVirtualEnvironmentContainer() *schema.Resource {
}
func resourceVirtualEnvironmentContainerCreate(d *schema.ResourceData, m interface{}) error {
clone := d.Get(mkResourceVirtualEnvironmentContainerClone).([]interface{})
if len(clone) > 0 {
return resourceVirtualEnvironmentContainerCreateClone(d, m)
}
return resourceVirtualEnvironmentContainerCreateCustom(d, m)
}
func resourceVirtualEnvironmentContainerCreateClone(d *schema.ResourceData, m interface{}) error {
config := m.(providerConfiguration)
veClient, err := config.GetVEClient()
if err != nil {
return err
}
clone := d.Get(mkResourceVirtualEnvironmentContainerClone).([]interface{})
cloneBlock := clone[0].(map[string]interface{})
cloneDatastoreID := cloneBlock[mkResourceVirtualEnvironmentContainerCloneDatastoreID].(string)
cloneNodeName := cloneBlock[mkResourceVirtualEnvironmentContainerCloneNodeName].(string)
cloneVMID := cloneBlock[mkResourceVirtualEnvironmentContainerCloneVMID].(int)
description := d.Get(mkResourceVirtualEnvironmentContainerDescription).(string)
initialization := d.Get(mkResourceVirtualEnvironmentContainerInitialization).([]interface{})
initializationHostname := ""
if len(initialization) > 0 {
initializationBlock := initialization[0].(map[string]interface{})
initializationHostname = initializationBlock[mkResourceVirtualEnvironmentContainerInitializationHostname].(string)
}
nodeName := d.Get(mkResourceVirtualEnvironmentContainerNodeName).(string)
poolID := d.Get(mkResourceVirtualEnvironmentContainerPoolID).(string)
vmID := d.Get(mkResourceVirtualEnvironmentContainerVMID).(int)
if vmID == -1 {
vmIDNew, err := veClient.GetVMID()
if err != nil {
return err
}
vmID = *vmIDNew
}
fullCopy := proxmox.CustomBool(true)
cloneBody := &proxmox.VirtualEnvironmentContainerCloneRequestBody{
FullCopy: &fullCopy,
VMIDNew: vmID,
}
if cloneDatastoreID != "" {
cloneBody.TargetStorage = &cloneDatastoreID
}
if description != "" {
cloneBody.Description = &description
}
if initializationHostname != "" {
cloneBody.Hostname = &initializationHostname
}
if poolID != "" {
cloneBody.PoolID = &poolID
}
if cloneNodeName != "" && cloneNodeName != nodeName {
cloneBody.TargetNodeName = &nodeName
err = veClient.CloneContainer(cloneNodeName, cloneVMID, cloneBody)
} else {
err = veClient.CloneContainer(nodeName, cloneVMID, cloneBody)
}
if err != nil {
return err
}
d.SetId(strconv.Itoa(vmID))
// Wait for the container to be created and its configuration lock to be released.
err = veClient.WaitForContainerLock(nodeName, vmID, 600, 5, true)
if err != nil {
return err
}
// Now that the virtual machine has been cloned, we need to perform some modifications.
updateBody := &proxmox.VirtualEnvironmentContainerUpdateRequestBody{}
console := d.Get(mkResourceVirtualEnvironmentContainerConsole).([]interface{})
if len(console) > 0 {
consoleBlock := console[0].(map[string]interface{})
consoleEnabled := proxmox.CustomBool(consoleBlock[mkResourceVirtualEnvironmentContainerConsoleEnabled].(bool))
consoleMode := consoleBlock[mkResourceVirtualEnvironmentContainerConsoleMode].(string)
consoleTTYCount := consoleBlock[mkResourceVirtualEnvironmentContainerConsoleTTYCount].(int)
updateBody.ConsoleEnabled = &consoleEnabled
updateBody.ConsoleMode = &consoleMode
updateBody.TTY = &consoleTTYCount
}
cpu := d.Get(mkResourceVirtualEnvironmentContainerCPU).([]interface{})
if len(cpu) > 0 {
cpuBlock := cpu[0].(map[string]interface{})
cpuArchitecture := cpuBlock[mkResourceVirtualEnvironmentContainerCPUArchitecture].(string)
cpuCores := cpuBlock[mkResourceVirtualEnvironmentContainerCPUCores].(int)
cpuUnits := cpuBlock[mkResourceVirtualEnvironmentContainerCPUUnits].(int)
updateBody.CPUArchitecture = &cpuArchitecture
updateBody.CPUCores = &cpuCores
updateBody.CPUUnits = &cpuUnits
}
initializationIPConfigIPv4Address := []string{}
initializationIPConfigIPv4Gateway := []string{}
initializationIPConfigIPv6Address := []string{}
initializationIPConfigIPv6Gateway := []string{}
if len(initialization) > 0 {
initializationBlock := initialization[0].(map[string]interface{})
initializationDNS := initializationBlock[mkResourceVirtualEnvironmentContainerInitializationDNS].([]interface{})
if len(initializationDNS) > 0 {
initializationDNSBlock := initializationDNS[0].(map[string]interface{})
initializationDNSDomain := initializationDNSBlock[mkResourceVirtualEnvironmentContainerInitializationDNSDomain].(string)
initializationDNSServer := initializationDNSBlock[mkResourceVirtualEnvironmentContainerInitializationDNSServer].(string)
updateBody.DNSDomain = &initializationDNSDomain
updateBody.DNSServer = &initializationDNSServer
}
initializationHostname := initializationBlock[mkResourceVirtualEnvironmentContainerInitializationHostname].(string)
if initializationHostname != dvResourceVirtualEnvironmentContainerInitializationHostname {
updateBody.Hostname = &initializationHostname
}
initializationUserAccount := initializationBlock[mkResourceVirtualEnvironmentContainerInitializationUserAccount].([]interface{})
if len(initializationUserAccount) > 0 {
initializationUserAccountBlock := initializationUserAccount[0].(map[string]interface{})
keys := initializationUserAccountBlock[mkResourceVirtualEnvironmentContainerInitializationUserAccountKeys].([]interface{})
if len(keys) > 0 {
initializationUserAccountKeys := make(proxmox.VirtualEnvironmentContainerCustomSSHKeys, len(keys))
for ki, kv := range keys {
initializationUserAccountKeys[ki] = kv.(string)
}
updateBody.SSHKeys = &initializationUserAccountKeys
} else {
updateBody.Delete = append(updateBody.Delete, "ssh-public-keys")
}
initializationIPConfig := initializationBlock[mkResourceVirtualEnvironmentContainerInitializationIPConfig].([]interface{})
for _, c := range initializationIPConfig {
configBlock := c.(map[string]interface{})
ipv4 := configBlock[mkResourceVirtualEnvironmentContainerInitializationIPConfigIPv4].([]interface{})
if len(ipv4) > 0 {
ipv4Block := ipv4[0].(map[string]interface{})
initializationIPConfigIPv4Address = append(initializationIPConfigIPv4Address, ipv4Block[mkResourceVirtualEnvironmentContainerInitializationIPConfigIPv4Address].(string))
initializationIPConfigIPv4Gateway = append(initializationIPConfigIPv4Gateway, ipv4Block[mkResourceVirtualEnvironmentContainerInitializationIPConfigIPv4Gateway].(string))
} else {
initializationIPConfigIPv4Address = append(initializationIPConfigIPv4Address, "")
initializationIPConfigIPv4Gateway = append(initializationIPConfigIPv4Gateway, "")
}
ipv6 := configBlock[mkResourceVirtualEnvironmentContainerInitializationIPConfigIPv6].([]interface{})
if len(ipv6) > 0 {
ipv6Block := ipv6[0].(map[string]interface{})
initializationIPConfigIPv6Address = append(initializationIPConfigIPv6Address, ipv6Block[mkResourceVirtualEnvironmentContainerInitializationIPConfigIPv6Address].(string))
initializationIPConfigIPv6Gateway = append(initializationIPConfigIPv6Gateway, ipv6Block[mkResourceVirtualEnvironmentContainerInitializationIPConfigIPv6Gateway].(string))
} else {
initializationIPConfigIPv6Address = append(initializationIPConfigIPv6Address, "")
initializationIPConfigIPv6Gateway = append(initializationIPConfigIPv6Gateway, "")
}
}
initializationUserAccountPassword := initializationUserAccountBlock[mkResourceVirtualEnvironmentContainerInitializationUserAccountPassword].(string)
if initializationUserAccountPassword != dvResourceVirtualEnvironmentContainerInitializationUserAccountPassword {
updateBody.Password = &initializationUserAccountPassword
} else {
updateBody.Delete = append(updateBody.Delete, "password")
}
}
}
memory := d.Get(mkResourceVirtualEnvironmentContainerMemory).([]interface{})
if len(memory) > 0 {
memoryBlock := memory[0].(map[string]interface{})
memoryDedicated := memoryBlock[mkResourceVirtualEnvironmentContainerMemoryDedicated].(int)
memorySwap := memoryBlock[mkResourceVirtualEnvironmentContainerMemorySwap].(int)
updateBody.DedicatedMemory = &memoryDedicated
updateBody.Swap = &memorySwap
}
networkInterface := d.Get(mkResourceVirtualEnvironmentContainerNetworkInterface).([]interface{})
if len(networkInterface) > 0 {
networkInterfaceArray := make(proxmox.VirtualEnvironmentContainerCustomNetworkInterfaceArray, len(networkInterface))
for ni, nv := range networkInterface {
networkInterfaceMap := nv.(map[string]interface{})
networkInterfaceObject := proxmox.VirtualEnvironmentContainerCustomNetworkInterface{}
bridge := networkInterfaceMap[mkResourceVirtualEnvironmentContainerNetworkInterfaceBridge].(string)
enabled := networkInterfaceMap[mkResourceVirtualEnvironmentContainerNetworkInterfaceEnabled].(bool)
macAddress := networkInterfaceMap[mkResourceVirtualEnvironmentContainerNetworkInterfaceMACAddress].(string)
name := networkInterfaceMap[mkResourceVirtualEnvironmentContainerNetworkInterfaceName].(string)
rateLimit := networkInterfaceMap[mkResourceVirtualEnvironmentContainerNetworkInterfaceRateLimit].(float64)
vlanID := networkInterfaceMap[mkResourceVirtualEnvironmentContainerNetworkInterfaceVLANID].(int)
if bridge != "" {
networkInterfaceObject.Bridge = &bridge
}
networkInterfaceObject.Enabled = enabled
if len(initializationIPConfigIPv4Address) > ni {
if initializationIPConfigIPv4Address[ni] != "" {
networkInterfaceObject.IPv4Address = &initializationIPConfigIPv4Address[ni]
}
if initializationIPConfigIPv4Gateway[ni] != "" {
networkInterfaceObject.IPv4Gateway = &initializationIPConfigIPv4Gateway[ni]
}
if initializationIPConfigIPv6Address[ni] != "" {
networkInterfaceObject.IPv6Address = &initializationIPConfigIPv6Address[ni]
}
if initializationIPConfigIPv6Gateway[ni] != "" {
networkInterfaceObject.IPv6Gateway = &initializationIPConfigIPv6Gateway[ni]
}
}
if macAddress != "" {
networkInterfaceObject.MACAddress = &macAddress
}
networkInterfaceObject.Name = name
if rateLimit != 0 {
networkInterfaceObject.RateLimit = &rateLimit
}
if vlanID != 0 {
networkInterfaceObject.Tag = &vlanID
}
networkInterfaceArray[ni] = networkInterfaceObject
}
updateBody.NetworkInterfaces = networkInterfaceArray
for i := 0; i < len(updateBody.NetworkInterfaces); i++ {
if !updateBody.NetworkInterfaces[i].Enabled {
updateBody.Delete = append(updateBody.Delete, fmt.Sprintf("net%d", i))
}
}
for i := len(updateBody.NetworkInterfaces); i < maxResourceVirtualEnvironmentContainerNetworkInterfaces; i++ {
updateBody.Delete = append(updateBody.Delete, fmt.Sprintf("net%d", i))
}
}
operatingSystem := d.Get(mkResourceVirtualEnvironmentContainerOperatingSystem).([]interface{})
if len(operatingSystem) > 0 {
operatingSystemBlock := operatingSystem[0].(map[string]interface{})
operatingSystemTemplateFileID := operatingSystemBlock[mkResourceVirtualEnvironmentContainerOperatingSystemTemplateFileID].(string)
operatingSystemType := operatingSystemBlock[mkResourceVirtualEnvironmentContainerOperatingSystemType].(string)
updateBody.OSTemplateFileVolume = &operatingSystemTemplateFileID
updateBody.OSType = &operatingSystemType
}
template := proxmox.CustomBool(d.Get(mkResourceVirtualEnvironmentContainerTemplate).(bool))
if template != dvResourceVirtualEnvironmentContainerTemplate {
updateBody.Template = &template
}
err = veClient.UpdateContainer(nodeName, vmID, updateBody)
if err != nil {
return err
}
// Wait for the container's lock to be released.
err = veClient.WaitForContainerLock(nodeName, vmID, 600, 5, true)
if err != nil {
return err
}
return resourceVirtualEnvironmentContainerCreateStart(d, m)
}
func resourceVirtualEnvironmentContainerCreateCustom(d *schema.ResourceData, m interface{}) error {
config := m.(providerConfiguration)
veClient, err := config.GetVEClient()
@ -671,17 +1047,19 @@ func resourceVirtualEnvironmentContainerCreate(d *schema.ResourceData, m interfa
networkInterfaceArray[ni] = networkInterfaceObject
}
operatingSystem, err := getSchemaBlock(resource, d, m, []string{mkResourceVirtualEnvironmentContainerOperatingSystem}, 0, true)
operatingSystem := d.Get(mkResourceVirtualEnvironmentContainerOperatingSystem).([]interface{})
if err != nil {
return err
if len(operatingSystem) == 0 {
return fmt.Errorf("\"%s\": required field is not set", mkResourceVirtualEnvironmentContainerOperatingSystem)
}
operatingSystemTemplateFileID := operatingSystem[mkResourceVirtualEnvironmentContainerOperatingSystemTemplateFileID].(string)
operatingSystemType := operatingSystem[mkResourceVirtualEnvironmentContainerOperatingSystemType].(string)
operatingSystemBlock := operatingSystem[0].(map[string]interface{})
operatingSystemTemplateFileID := operatingSystemBlock[mkResourceVirtualEnvironmentContainerOperatingSystemTemplateFileID].(string)
operatingSystemType := operatingSystemBlock[mkResourceVirtualEnvironmentContainerOperatingSystemType].(string)
poolID := d.Get(mkResourceVirtualEnvironmentContainerPoolID).(string)
started := proxmox.CustomBool(d.Get(mkResourceVirtualEnvironmentContainerStarted).(bool))
template := proxmox.CustomBool(d.Get(mkResourceVirtualEnvironmentContainerTemplate).(bool))
vmID := d.Get(mkResourceVirtualEnvironmentContainerVMID).(int)
if vmID == -1 {
@ -695,7 +1073,7 @@ func resourceVirtualEnvironmentContainerCreate(d *schema.ResourceData, m interfa
}
// Attempt to create the resource using the retrieved values.
body := proxmox.VirtualEnvironmentContainerCreateRequestBody{
createBody := proxmox.VirtualEnvironmentContainerCreateRequestBody{
ConsoleEnabled: &consoleEnabled,
ConsoleMode: &consoleMode,
CPUArchitecture: &cpuArchitecture,
@ -708,39 +1086,40 @@ func resourceVirtualEnvironmentContainerCreate(d *schema.ResourceData, m interfa
OSType: &operatingSystemType,
StartOnBoot: &started,
Swap: &memorySwap,
Template: &template,
TTY: &consoleTTYCount,
VMID: &vmID,
}
if description != "" {
body.Description = &description
createBody.Description = &description
}
if initializationDNSDomain != "" {
body.DNSDomain = &initializationDNSDomain
createBody.DNSDomain = &initializationDNSDomain
}
if initializationDNSServer != "" {
body.DNSServer = &initializationDNSServer
createBody.DNSServer = &initializationDNSServer
}
if initializationHostname != "" {
body.Hostname = &initializationHostname
createBody.Hostname = &initializationHostname
}
if len(initializationUserAccountKeys) > 0 {
body.SSHKeys = &initializationUserAccountKeys
createBody.SSHKeys = &initializationUserAccountKeys
}
if initializationUserAccountPassword != "" {
body.Password = &initializationUserAccountPassword
createBody.Password = &initializationUserAccountPassword
}
if poolID != "" {
body.PoolID = &poolID
createBody.PoolID = &poolID
}
err = veClient.CreateContainer(nodeName, &body)
err = veClient.CreateContainer(nodeName, &createBody)
if err != nil {
return err
@ -749,7 +1128,7 @@ func resourceVirtualEnvironmentContainerCreate(d *schema.ResourceData, m interfa
d.SetId(strconv.Itoa(vmID))
// Wait for the container's lock to be released.
err = veClient.WaitForContainerLock(nodeName, vmID, 300, 5)
err = veClient.WaitForContainerLock(nodeName, vmID, 600, 5, true)
if err != nil {
return err
@ -760,8 +1139,9 @@ func resourceVirtualEnvironmentContainerCreate(d *schema.ResourceData, m interfa
func resourceVirtualEnvironmentContainerCreateStart(d *schema.ResourceData, m interface{}) error {
started := d.Get(mkResourceVirtualEnvironmentContainerStarted).(bool)
template := d.Get(mkResourceVirtualEnvironmentContainerTemplate).(bool)
if !started {
if !started || template {
return resourceVirtualEnvironmentContainerRead(d, m)
}
@ -855,11 +1235,17 @@ func resourceVirtualEnvironmentContainerRead(d *schema.ResourceData, m interface
return err
}
clone := d.Get(mkResourceVirtualEnvironmentVMClone).([]interface{})
// Compare the primitive values to those stored in the state.
if containerConfig.Description != nil {
d.Set(mkResourceVirtualEnvironmentContainerDescription, strings.TrimSpace(*containerConfig.Description))
} else {
d.Set(mkResourceVirtualEnvironmentContainerDescription, "")
currentDescription := d.Get(mkResourceVirtualEnvironmentContainerDescription).(string)
if len(clone) == 0 || currentDescription != dvResourceVirtualEnvironmentContainerDescription {
if containerConfig.Description != nil {
d.Set(mkResourceVirtualEnvironmentContainerDescription, strings.TrimSpace(*containerConfig.Description))
} else {
d.Set(mkResourceVirtualEnvironmentContainerDescription, "")
}
}
// Compare the console configuration to the one stored in the state.
@ -888,7 +1274,11 @@ func resourceVirtualEnvironmentContainerRead(d *schema.ResourceData, m interface
currentConsole := d.Get(mkResourceVirtualEnvironmentContainerConsole).([]interface{})
if len(currentConsole) > 0 ||
if len(clone) > 0 {
if len(currentConsole) > 0 {
d.Set(mkResourceVirtualEnvironmentContainerConsole, []interface{}{console})
}
} else if len(currentConsole) > 0 ||
console[mkResourceVirtualEnvironmentContainerConsoleEnabled] != proxmox.CustomBool(dvResourceVirtualEnvironmentContainerConsoleEnabled) ||
console[mkResourceVirtualEnvironmentContainerConsoleMode] != dvResourceVirtualEnvironmentContainerConsoleMode ||
console[mkResourceVirtualEnvironmentContainerConsoleTTYCount] != dvResourceVirtualEnvironmentContainerConsoleTTYCount {
@ -921,7 +1311,11 @@ func resourceVirtualEnvironmentContainerRead(d *schema.ResourceData, m interface
currentCPU := d.Get(mkResourceVirtualEnvironmentContainerCPU).([]interface{})
if len(currentCPU) > 0 ||
if len(clone) > 0 {
if len(currentCPU) > 0 {
d.Set(mkResourceVirtualEnvironmentContainerCPU, []interface{}{cpu})
}
} else if len(currentCPU) > 0 ||
cpu[mkResourceVirtualEnvironmentContainerCPUArchitecture] != dvResourceVirtualEnvironmentContainerCPUArchitecture ||
cpu[mkResourceVirtualEnvironmentContainerCPUCores] != dvResourceVirtualEnvironmentContainerCPUCores ||
cpu[mkResourceVirtualEnvironmentContainerCPUUnits] != dvResourceVirtualEnvironmentContainerCPUUnits {
@ -942,7 +1336,11 @@ func resourceVirtualEnvironmentContainerRead(d *schema.ResourceData, m interface
currentDisk := d.Get(mkResourceVirtualEnvironmentContainerDisk).([]interface{})
if len(currentDisk) > 0 ||
if len(clone) > 0 {
if len(currentDisk) > 0 {
d.Set(mkResourceVirtualEnvironmentContainerDiskDatastoreID, []interface{}{disk})
}
} else if len(currentDisk) > 0 ||
disk[mkResourceVirtualEnvironmentContainerDiskDatastoreID] != dvResourceVirtualEnvironmentContainerDiskDatastoreID {
d.Set(mkResourceVirtualEnvironmentContainerDiskDatastoreID, []interface{}{disk})
}
@ -964,7 +1362,11 @@ func resourceVirtualEnvironmentContainerRead(d *schema.ResourceData, m interface
currentMemory := d.Get(mkResourceVirtualEnvironmentContainerMemory).([]interface{})
if len(currentMemory) > 0 ||
if len(clone) > 0 {
if len(currentMemory) > 0 {
d.Set(mkResourceVirtualEnvironmentContainerMemory, []interface{}{memory})
}
} else if len(currentMemory) > 0 ||
memory[mkResourceVirtualEnvironmentContainerMemoryDedicated] != dvResourceVirtualEnvironmentContainerMemoryDedicated ||
memory[mkResourceVirtualEnvironmentContainerMemorySwap] != dvResourceVirtualEnvironmentContainerMemorySwap {
d.Set(mkResourceVirtualEnvironmentContainerMemory, []interface{}{memory})
@ -1104,13 +1506,48 @@ func resourceVirtualEnvironmentContainerRead(d *schema.ResourceData, m interface
initialization[mkResourceVirtualEnvironmentContainerInitializationUserAccount] = currentInitializationMap[mkResourceVirtualEnvironmentContainerInitializationUserAccount].([]interface{})
}
if len(initialization) > 0 {
d.Set(mkResourceVirtualEnvironmentContainerInitialization, []interface{}{initialization})
} else {
d.Set(mkResourceVirtualEnvironmentContainerInitialization, []interface{}{})
}
if len(clone) > 0 {
if len(currentInitialization) > 0 {
currentInitializationBlock := currentInitialization[0].(map[string]interface{})
currentInitializationDNS := currentInitializationBlock[mkResourceVirtualEnvironmentContainerInitializationDNS].([]interface{})
d.Set(mkResourceVirtualEnvironmentContainerNetworkInterface, networkInterfaceList)
if len(currentInitializationDNS) == 0 {
initialization[mkResourceVirtualEnvironmentContainerInitializationDNS] = []interface{}{}
}
currentInitializationIPConfig := currentInitializationBlock[mkResourceVirtualEnvironmentContainerInitializationIPConfig].([]interface{})
if len(currentInitializationIPConfig) == 0 {
initialization[mkResourceVirtualEnvironmentContainerInitializationIPConfig] = []interface{}{}
}
currentInitializationUserAccount := currentInitializationBlock[mkResourceVirtualEnvironmentContainerInitializationUserAccount].([]interface{})
if len(currentInitializationUserAccount) == 0 {
initialization[mkResourceVirtualEnvironmentContainerInitializationUserAccount] = []interface{}{}
}
if len(initialization) > 0 {
d.Set(mkResourceVirtualEnvironmentContainerInitialization, []interface{}{initialization})
} else {
d.Set(mkResourceVirtualEnvironmentContainerInitialization, []interface{}{})
}
}
currentNetworkInterface := d.Get(mkResourceVirtualEnvironmentContainerNetworkInterface).([]interface{})
if len(currentNetworkInterface) > 0 {
d.Set(mkResourceVirtualEnvironmentContainerNetworkInterface, networkInterfaceList)
}
} else {
if len(initialization) > 0 {
d.Set(mkResourceVirtualEnvironmentContainerInitialization, []interface{}{initialization})
} else {
d.Set(mkResourceVirtualEnvironmentContainerInitialization, []interface{}{})
}
d.Set(mkResourceVirtualEnvironmentContainerNetworkInterface, networkInterfaceList)
}
// Compare the operating system configuration to the one stored in the state.
operatingSystem := map[string]interface{}{}
@ -1130,11 +1567,25 @@ func resourceVirtualEnvironmentContainerRead(d *schema.ResourceData, m interface
operatingSystem[mkResourceVirtualEnvironmentContainerOperatingSystemTemplateFileID] = currentOperatingSystemMap[mkResourceVirtualEnvironmentContainerOperatingSystemTemplateFileID]
}
if len(currentOperatingSystem) > 0 ||
if len(clone) > 0 {
if len(currentMemory) > 0 {
d.Set(mkResourceVirtualEnvironmentContainerOperatingSystem, []interface{}{operatingSystem})
}
} else if len(currentOperatingSystem) > 0 ||
operatingSystem[mkResourceVirtualEnvironmentContainerOperatingSystemType] != dvResourceVirtualEnvironmentContainerOperatingSystemType {
d.Set(mkResourceVirtualEnvironmentContainerOperatingSystem, []interface{}{operatingSystem})
}
currentTemplate := d.Get(mkResourceVirtualEnvironmentContainerTemplate).(bool)
if len(clone) == 0 || currentTemplate != dvResourceVirtualEnvironmentContainerTemplate {
if containerConfig.Template != nil {
d.Set(mkResourceVirtualEnvironmentContainerTemplate, bool(*containerConfig.Template))
} else {
d.Set(mkResourceVirtualEnvironmentContainerTemplate, false)
}
}
// Determine the state of the container in order to update the "started" argument.
status, err := veClient.GetContainerStatus(nodeName, vmID)
@ -1163,9 +1614,10 @@ func resourceVirtualEnvironmentContainerUpdate(d *schema.ResourceData, m interfa
}
// Prepare the new request object.
body := proxmox.VirtualEnvironmentContainerUpdateRequestBody{
updateBody := proxmox.VirtualEnvironmentContainerUpdateRequestBody{
Delete: []string{},
}
rebootRequired := false
resource := resourceVirtualEnvironmentContainer()
@ -1173,7 +1625,13 @@ func resourceVirtualEnvironmentContainerUpdate(d *schema.ResourceData, m interfa
if d.HasChange(mkResourceVirtualEnvironmentContainerDescription) {
description := d.Get(mkResourceVirtualEnvironmentContainerDescription).(string)
body.Description = &description
updateBody.Description = &description
}
template := proxmox.CustomBool(d.Get(mkResourceVirtualEnvironmentContainerTemplate).(bool))
if d.HasChange(mkResourceVirtualEnvironmentContainerTemplate) {
updateBody.Template = &template
}
// Prepare the new console configuration.
@ -1188,9 +1646,9 @@ func resourceVirtualEnvironmentContainerUpdate(d *schema.ResourceData, m interfa
consoleMode := consoleBlock[mkResourceVirtualEnvironmentContainerConsoleMode].(string)
consoleTTYCount := consoleBlock[mkResourceVirtualEnvironmentContainerConsoleTTYCount].(int)
body.ConsoleEnabled = &consoleEnabled
body.ConsoleMode = &consoleMode
body.TTY = &consoleTTYCount
updateBody.ConsoleEnabled = &consoleEnabled
updateBody.ConsoleMode = &consoleMode
updateBody.TTY = &consoleTTYCount
rebootRequired = true
}
@ -1207,9 +1665,9 @@ func resourceVirtualEnvironmentContainerUpdate(d *schema.ResourceData, m interfa
cpuCores := cpuBlock[mkResourceVirtualEnvironmentContainerCPUCores].(int)
cpuUnits := cpuBlock[mkResourceVirtualEnvironmentContainerCPUUnits].(int)
body.CPUArchitecture = &cpuArchitecture
body.CPUCores = &cpuCores
body.CPUUnits = &cpuUnits
updateBody.CPUArchitecture = &cpuArchitecture
updateBody.CPUCores = &cpuCores
updateBody.CPUUnits = &cpuUnits
rebootRequired = true
}
@ -1266,9 +1724,9 @@ func resourceVirtualEnvironmentContainerUpdate(d *schema.ResourceData, m interfa
}
if d.HasChange(mkResourceVirtualEnvironmentContainerInitialization) {
body.DNSDomain = &initializationDNSDomain
body.DNSServer = &initializationDNSServer
body.Hostname = &initializationHostname
updateBody.DNSDomain = &initializationDNSDomain
updateBody.DNSServer = &initializationDNSServer
updateBody.Hostname = &initializationHostname
rebootRequired = true
}
@ -1284,8 +1742,8 @@ func resourceVirtualEnvironmentContainerUpdate(d *schema.ResourceData, m interfa
memoryDedicated := memoryBlock[mkResourceVirtualEnvironmentContainerMemoryDedicated].(int)
memorySwap := memoryBlock[mkResourceVirtualEnvironmentContainerMemorySwap].(int)
body.DedicatedMemory = &memoryDedicated
body.Swap = &memorySwap
updateBody.DedicatedMemory = &memoryDedicated
updateBody.Swap = &memorySwap
rebootRequired = true
}
@ -1347,13 +1805,16 @@ func resourceVirtualEnvironmentContainerUpdate(d *schema.ResourceData, m interfa
networkInterfaceArray[ni] = networkInterfaceObject
}
body.NetworkInterfaces = networkInterfaceArray
updateBody.NetworkInterfaces = networkInterfaceArray
index := len(networkInterface)
for i := 0; i < len(updateBody.NetworkInterfaces); i++ {
if !updateBody.NetworkInterfaces[i].Enabled {
updateBody.Delete = append(updateBody.Delete, fmt.Sprintf("net%d", i))
}
}
for index < 8 {
body.Delete = append(body.Delete, fmt.Sprintf("net%d", index))
index++
for i := len(updateBody.NetworkInterfaces); i < maxResourceVirtualEnvironmentContainerNetworkInterfaces; i++ {
updateBody.Delete = append(updateBody.Delete, fmt.Sprintf("net%d", i))
}
rebootRequired = true
@ -1369,22 +1830,22 @@ func resourceVirtualEnvironmentContainerUpdate(d *schema.ResourceData, m interfa
operatingSystemType := operatingSystem[mkResourceVirtualEnvironmentContainerOperatingSystemType].(string)
body.OSType = &operatingSystemType
updateBody.OSType = &operatingSystemType
rebootRequired = true
}
// Update the configuration now that everything has been prepared.
err = veClient.UpdateContainer(nodeName, vmID, &body)
err = veClient.UpdateContainer(nodeName, vmID, &updateBody)
if err != nil {
return err
}
// Determine if the state of the container needs to be changed.
if d.HasChange(mkResourceVirtualEnvironmentContainerStarted) {
started := d.Get(mkResourceVirtualEnvironmentContainerStarted).(bool)
started := d.Get(mkResourceVirtualEnvironmentContainerStarted).(bool)
if d.HasChange(mkResourceVirtualEnvironmentContainerStarted) && !bool(template) {
if started {
err = veClient.StartContainer(nodeName, vmID)
@ -1420,8 +1881,8 @@ func resourceVirtualEnvironmentContainerUpdate(d *schema.ResourceData, m interfa
}
}
// As a final step in the update procedure, we might need to reboot the virtual machine.
if rebootRequired {
// As a final step in the update procedure, we might need to reboot the container.
if !bool(template) && rebootRequired {
rebootTimeout := 300
err = veClient.RebootContainer(nodeName, vmID, &proxmox.VirtualEnvironmentContainerRebootRequestBody{

View File

@ -25,7 +25,6 @@ func TestResourceVirtualEnvironmentContainerSchema(t *testing.T) {
testRequiredArguments(t, s, []string{
mkResourceVirtualEnvironmentContainerNodeName,
mkResourceVirtualEnvironmentContainerOperatingSystem,
})
testOptionalArguments(t, s, []string{
@ -34,12 +33,14 @@ func TestResourceVirtualEnvironmentContainerSchema(t *testing.T) {
mkResourceVirtualEnvironmentContainerDisk,
mkResourceVirtualEnvironmentContainerInitialization,
mkResourceVirtualEnvironmentContainerMemory,
mkResourceVirtualEnvironmentContainerOperatingSystem,
mkResourceVirtualEnvironmentContainerPoolID,
mkResourceVirtualEnvironmentContainerStarted,
mkResourceVirtualEnvironmentContainerTemplate,
mkResourceVirtualEnvironmentContainerVMID,
})
testSchemaValueTypes(t, s, map[string]schema.ValueType{
testValueTypes(t, s, map[string]schema.ValueType{
mkResourceVirtualEnvironmentContainerCPU: schema.TypeList,
mkResourceVirtualEnvironmentContainerDescription: schema.TypeString,
mkResourceVirtualEnvironmentContainerDisk: schema.TypeList,
@ -48,9 +49,27 @@ func TestResourceVirtualEnvironmentContainerSchema(t *testing.T) {
mkResourceVirtualEnvironmentContainerOperatingSystem: schema.TypeList,
mkResourceVirtualEnvironmentContainerPoolID: schema.TypeString,
mkResourceVirtualEnvironmentContainerStarted: schema.TypeBool,
mkResourceVirtualEnvironmentContainerTemplate: schema.TypeBool,
mkResourceVirtualEnvironmentContainerVMID: schema.TypeInt,
})
cloneSchema := testNestedSchemaExistence(t, s, mkResourceVirtualEnvironmentContainerClone)
testRequiredArguments(t, cloneSchema, []string{
mkResourceVirtualEnvironmentContainerCloneVMID,
})
testOptionalArguments(t, cloneSchema, []string{
mkResourceVirtualEnvironmentContainerCloneDatastoreID,
mkResourceVirtualEnvironmentContainerCloneNodeName,
})
testValueTypes(t, cloneSchema, map[string]schema.ValueType{
mkResourceVirtualEnvironmentContainerCloneDatastoreID: schema.TypeString,
mkResourceVirtualEnvironmentContainerCloneNodeName: schema.TypeString,
mkResourceVirtualEnvironmentContainerCloneVMID: schema.TypeInt,
})
cpuSchema := testNestedSchemaExistence(t, s, mkResourceVirtualEnvironmentContainerCPU)
testOptionalArguments(t, cpuSchema, []string{
@ -59,7 +78,7 @@ func TestResourceVirtualEnvironmentContainerSchema(t *testing.T) {
mkResourceVirtualEnvironmentContainerCPUUnits,
})
testSchemaValueTypes(t, cpuSchema, map[string]schema.ValueType{
testValueTypes(t, cpuSchema, map[string]schema.ValueType{
mkResourceVirtualEnvironmentContainerCPUArchitecture: schema.TypeString,
mkResourceVirtualEnvironmentContainerCPUCores: schema.TypeInt,
mkResourceVirtualEnvironmentContainerCPUUnits: schema.TypeInt,
@ -71,7 +90,7 @@ func TestResourceVirtualEnvironmentContainerSchema(t *testing.T) {
mkResourceVirtualEnvironmentContainerDiskDatastoreID,
})
testSchemaValueTypes(t, diskSchema, map[string]schema.ValueType{
testValueTypes(t, diskSchema, map[string]schema.ValueType{
mkResourceVirtualEnvironmentContainerDiskDatastoreID: schema.TypeString,
})
@ -84,7 +103,7 @@ func TestResourceVirtualEnvironmentContainerSchema(t *testing.T) {
mkResourceVirtualEnvironmentContainerInitializationUserAccount,
})
testSchemaValueTypes(t, initializationSchema, map[string]schema.ValueType{
testValueTypes(t, initializationSchema, map[string]schema.ValueType{
mkResourceVirtualEnvironmentContainerInitializationDNS: schema.TypeList,
mkResourceVirtualEnvironmentContainerInitializationHostname: schema.TypeString,
mkResourceVirtualEnvironmentContainerInitializationIPConfig: schema.TypeList,
@ -98,7 +117,7 @@ func TestResourceVirtualEnvironmentContainerSchema(t *testing.T) {
mkResourceVirtualEnvironmentContainerInitializationDNSServer,
})
testSchemaValueTypes(t, initializationDNSSchema, map[string]schema.ValueType{
testValueTypes(t, initializationDNSSchema, map[string]schema.ValueType{
mkResourceVirtualEnvironmentContainerInitializationDNSDomain: schema.TypeString,
mkResourceVirtualEnvironmentContainerInitializationDNSServer: schema.TypeString,
})
@ -110,7 +129,7 @@ func TestResourceVirtualEnvironmentContainerSchema(t *testing.T) {
mkResourceVirtualEnvironmentContainerInitializationIPConfigIPv6,
})
testSchemaValueTypes(t, initializationIPConfigSchema, map[string]schema.ValueType{
testValueTypes(t, initializationIPConfigSchema, map[string]schema.ValueType{
mkResourceVirtualEnvironmentContainerInitializationIPConfigIPv4: schema.TypeList,
mkResourceVirtualEnvironmentContainerInitializationIPConfigIPv6: schema.TypeList,
})
@ -122,7 +141,7 @@ func TestResourceVirtualEnvironmentContainerSchema(t *testing.T) {
mkResourceVirtualEnvironmentContainerInitializationIPConfigIPv4Gateway,
})
testSchemaValueTypes(t, initializationIPConfigIPv4Schema, map[string]schema.ValueType{
testValueTypes(t, initializationIPConfigIPv4Schema, map[string]schema.ValueType{
mkResourceVirtualEnvironmentContainerInitializationIPConfigIPv4Address: schema.TypeString,
mkResourceVirtualEnvironmentContainerInitializationIPConfigIPv4Gateway: schema.TypeString,
})
@ -134,7 +153,7 @@ func TestResourceVirtualEnvironmentContainerSchema(t *testing.T) {
mkResourceVirtualEnvironmentContainerInitializationIPConfigIPv6Gateway,
})
testSchemaValueTypes(t, initializationIPConfigIPv6Schema, map[string]schema.ValueType{
testValueTypes(t, initializationIPConfigIPv6Schema, map[string]schema.ValueType{
mkResourceVirtualEnvironmentContainerInitializationIPConfigIPv6Address: schema.TypeString,
mkResourceVirtualEnvironmentContainerInitializationIPConfigIPv6Gateway: schema.TypeString,
})
@ -146,7 +165,7 @@ func TestResourceVirtualEnvironmentContainerSchema(t *testing.T) {
mkResourceVirtualEnvironmentContainerInitializationUserAccountPassword,
})
testSchemaValueTypes(t, initializationUserAccountSchema, map[string]schema.ValueType{
testValueTypes(t, initializationUserAccountSchema, map[string]schema.ValueType{
mkResourceVirtualEnvironmentContainerInitializationUserAccountKeys: schema.TypeList,
mkResourceVirtualEnvironmentContainerInitializationUserAccountPassword: schema.TypeString,
})
@ -158,7 +177,7 @@ func TestResourceVirtualEnvironmentContainerSchema(t *testing.T) {
mkResourceVirtualEnvironmentContainerMemorySwap,
})
testSchemaValueTypes(t, memorySchema, map[string]schema.ValueType{
testValueTypes(t, memorySchema, map[string]schema.ValueType{
mkResourceVirtualEnvironmentContainerMemoryDedicated: schema.TypeInt,
mkResourceVirtualEnvironmentContainerMemorySwap: schema.TypeInt,
})
@ -177,7 +196,7 @@ func TestResourceVirtualEnvironmentContainerSchema(t *testing.T) {
mkResourceVirtualEnvironmentContainerNetworkInterfaceVLANID,
})
testSchemaValueTypes(t, networkInterfaceSchema, map[string]schema.ValueType{
testValueTypes(t, networkInterfaceSchema, map[string]schema.ValueType{
mkResourceVirtualEnvironmentContainerNetworkInterfaceBridge: schema.TypeString,
mkResourceVirtualEnvironmentContainerNetworkInterfaceEnabled: schema.TypeBool,
mkResourceVirtualEnvironmentContainerNetworkInterfaceMACAddress: schema.TypeString,
@ -196,7 +215,7 @@ func TestResourceVirtualEnvironmentContainerSchema(t *testing.T) {
mkResourceVirtualEnvironmentContainerOperatingSystemType,
})
testSchemaValueTypes(t, operatingSystemSchema, map[string]schema.ValueType{
testValueTypes(t, operatingSystemSchema, map[string]schema.ValueType{
mkResourceVirtualEnvironmentContainerOperatingSystemTemplateFileID: schema.TypeString,
mkResourceVirtualEnvironmentContainerOperatingSystemType: schema.TypeString,
})

View File

@ -32,7 +32,7 @@ func TestResourceVirtualEnvironmentDNSSchema(t *testing.T) {
mkResourceVirtualEnvironmentDNSServers,
})
testSchemaValueTypes(t, s, map[string]schema.ValueType{
testValueTypes(t, s, map[string]schema.ValueType{
mkResourceVirtualEnvironmentDNSDomain: schema.TypeString,
mkResourceVirtualEnvironmentDNSNodeName: schema.TypeString,
mkResourceVirtualEnvironmentDNSServers: schema.TypeList,

View File

@ -41,7 +41,7 @@ func TestResourceVirtualEnvironmentFileSchema(t *testing.T) {
mkResourceVirtualEnvironmentFileFileTag,
})
testSchemaValueTypes(t, s, map[string]schema.ValueType{
testValueTypes(t, s, map[string]schema.ValueType{
mkResourceVirtualEnvironmentFileContentType: schema.TypeString,
mkResourceVirtualEnvironmentFileDatastoreID: schema.TypeString,
mkResourceVirtualEnvironmentFileFileModificationDate: schema.TypeString,
@ -66,7 +66,7 @@ func TestResourceVirtualEnvironmentFileSchema(t *testing.T) {
mkResourceVirtualEnvironmentFileSourceFileInsecure,
})
testSchemaValueTypes(t, sourceFileSchema, map[string]schema.ValueType{
testValueTypes(t, sourceFileSchema, map[string]schema.ValueType{
mkResourceVirtualEnvironmentFileSourceFileChanged: schema.TypeBool,
mkResourceVirtualEnvironmentFileSourceFileChecksum: schema.TypeString,
mkResourceVirtualEnvironmentFileSourceFileFileName: schema.TypeString,
@ -85,7 +85,7 @@ func TestResourceVirtualEnvironmentFileSchema(t *testing.T) {
mkResourceVirtualEnvironmentFileSourceRawResize,
})
testSchemaValueTypes(t, sourceRawSchema, map[string]schema.ValueType{
testValueTypes(t, sourceRawSchema, map[string]schema.ValueType{
mkResourceVirtualEnvironmentFileSourceRawData: schema.TypeString,
mkResourceVirtualEnvironmentFileSourceRawFileName: schema.TypeString,
mkResourceVirtualEnvironmentFileSourceRawResize: schema.TypeInt,

View File

@ -36,7 +36,7 @@ func TestResourceVirtualEnvironmentGroupSchema(t *testing.T) {
mkResourceVirtualEnvironmentGroupMembers,
})
testSchemaValueTypes(t, s, map[string]schema.ValueType{
testValueTypes(t, s, map[string]schema.ValueType{
mkResourceVirtualEnvironmentGroupACL: schema.TypeSet,
mkResourceVirtualEnvironmentGroupComment: schema.TypeString,
mkResourceVirtualEnvironmentGroupID: schema.TypeString,
@ -54,7 +54,7 @@ func TestResourceVirtualEnvironmentGroupSchema(t *testing.T) {
mkResourceVirtualEnvironmentGroupACLPropagate,
})
testSchemaValueTypes(t, aclSchema, map[string]schema.ValueType{
testValueTypes(t, aclSchema, map[string]schema.ValueType{
mkResourceVirtualEnvironmentGroupACLPath: schema.TypeString,
mkResourceVirtualEnvironmentGroupACLPropagate: schema.TypeBool,
mkResourceVirtualEnvironmentGroupACLRoleID: schema.TypeString,

View File

@ -35,7 +35,7 @@ func TestResourceVirtualEnvironmentHostsSchema(t *testing.T) {
mkResourceVirtualEnvironmentHostsHostnames,
})
testSchemaValueTypes(t, s, map[string]schema.ValueType{
testValueTypes(t, s, map[string]schema.ValueType{
mkResourceVirtualEnvironmentHostsAddresses: schema.TypeList,
mkResourceVirtualEnvironmentHostsDigest: schema.TypeString,
mkResourceVirtualEnvironmentHostsEntries: schema.TypeList,
@ -51,7 +51,7 @@ func TestResourceVirtualEnvironmentHostsSchema(t *testing.T) {
mkResourceVirtualEnvironmentHostsEntriesHostnames,
})
testSchemaValueTypes(t, entriesSchema, map[string]schema.ValueType{
testValueTypes(t, entriesSchema, map[string]schema.ValueType{
mkResourceVirtualEnvironmentHostsEntriesAddress: schema.TypeString,
mkResourceVirtualEnvironmentHostsEntriesHostnames: schema.TypeList,
})
@ -63,7 +63,7 @@ func TestResourceVirtualEnvironmentHostsSchema(t *testing.T) {
mkResourceVirtualEnvironmentHostsEntryHostnames,
})
testSchemaValueTypes(t, entrySchema, map[string]schema.ValueType{
testValueTypes(t, entrySchema, map[string]schema.ValueType{
mkResourceVirtualEnvironmentHostsEntryAddress: schema.TypeString,
mkResourceVirtualEnvironmentHostsEntryHostnames: schema.TypeList,
})

View File

@ -45,7 +45,7 @@ func TestResourceVirtualEnvironmentPoolSchema(t *testing.T) {
mkResourceVirtualEnvironmentPoolMembersVMID,
})
testSchemaValueTypes(t, membersSchema, map[string]schema.ValueType{
testValueTypes(t, membersSchema, map[string]schema.ValueType{
mkResourceVirtualEnvironmentPoolMembersDatastoreID: schema.TypeString,
mkResourceVirtualEnvironmentPoolMembersID: schema.TypeString,
mkResourceVirtualEnvironmentPoolMembersNodeName: schema.TypeString,

View File

@ -28,7 +28,7 @@ func TestResourceVirtualEnvironmentRoleSchema(t *testing.T) {
mkResourceVirtualEnvironmentRoleRoleID,
})
testSchemaValueTypes(t, s, map[string]schema.ValueType{
testValueTypes(t, s, map[string]schema.ValueType{
mkResourceVirtualEnvironmentRolePrivileges: schema.TypeSet,
mkResourceVirtualEnvironmentRoleRoleID: schema.TypeString,
})

View File

@ -40,7 +40,7 @@ func TestResourceVirtualEnvironmentUserSchema(t *testing.T) {
mkResourceVirtualEnvironmentUserLastName,
})
testSchemaValueTypes(t, s, map[string]schema.ValueType{
testValueTypes(t, s, map[string]schema.ValueType{
mkResourceVirtualEnvironmentUserACL: schema.TypeSet,
mkResourceVirtualEnvironmentUserComment: schema.TypeString,
mkResourceVirtualEnvironmentUserEmail: schema.TypeString,
@ -65,7 +65,7 @@ func TestResourceVirtualEnvironmentUserSchema(t *testing.T) {
mkResourceVirtualEnvironmentUserACLPropagate,
})
testSchemaValueTypes(t, aclSchema, map[string]schema.ValueType{
testValueTypes(t, aclSchema, map[string]schema.ValueType{
mkResourceVirtualEnvironmentUserACLPath: schema.TypeString,
mkResourceVirtualEnvironmentUserACLPropagate: schema.TypeBool,
mkResourceVirtualEnvironmentUserACLRoleID: schema.TypeString,

View File

@ -16,10 +16,6 @@ import (
)
const (
maxAudioDevices = 1
maxNetworkDevices = 8
maxSerialDevices = 4
dvResourceVirtualEnvironmentVMACPI = true
dvResourceVirtualEnvironmentVMAgentEnabled = false
dvResourceVirtualEnvironmentVMAgentTrim = false
@ -77,6 +73,10 @@ const (
dvResourceVirtualEnvironmentVMVGAType = "std"
dvResourceVirtualEnvironmentVMVMID = -1
maxResourceVirtualEnvironmentVMAudioDevices = 1
maxResourceVirtualEnvironmentVMNetworkDevices = 8
maxResourceVirtualEnvironmentVMSerialDevices = 4
mkResourceVirtualEnvironmentVMACPI = "acpi"
mkResourceVirtualEnvironmentVMAgent = "agent"
mkResourceVirtualEnvironmentVMAgentEnabled = "enabled"
@ -241,7 +241,7 @@ func resourceVirtualEnvironmentVM() *schema.Resource {
},
},
},
MaxItems: maxAudioDevices,
MaxItems: maxResourceVirtualEnvironmentVMAudioDevices,
MinItems: 0,
},
mkResourceVirtualEnvironmentVMBIOS: {
@ -780,7 +780,7 @@ func resourceVirtualEnvironmentVM() *schema.Resource {
},
},
},
MaxItems: maxNetworkDevices,
MaxItems: maxResourceVirtualEnvironmentVMNetworkDevices,
MinItems: 0,
},
mkResourceVirtualEnvironmentVMNetworkInterfaceNames: {
@ -849,7 +849,7 @@ func resourceVirtualEnvironmentVM() *schema.Resource {
},
},
},
MaxItems: maxSerialDevices,
MaxItems: maxResourceVirtualEnvironmentVMSerialDevices,
MinItems: 0,
},
mkResourceVirtualEnvironmentVMStarted: {
@ -972,33 +972,33 @@ func resourceVirtualEnvironmentVMCreateClone(d *schema.ResourceData, m interface
fullCopy := proxmox.CustomBool(true)
body := &proxmox.VirtualEnvironmentVMCloneRequestBody{
cloneBody := &proxmox.VirtualEnvironmentVMCloneRequestBody{
FullCopy: &fullCopy,
VMIDNew: vmID,
}
if cloneDatastoreID != "" {
body.TargetStorage = &cloneDatastoreID
cloneBody.TargetStorage = &cloneDatastoreID
}
if description != "" {
body.Description = &description
cloneBody.Description = &description
}
if name != "" {
body.Name = &name
cloneBody.Name = &name
}
if poolID != "" {
body.PoolID = &poolID
cloneBody.PoolID = &poolID
}
if cloneNodeName != "" && cloneNodeName != nodeName {
body.TargetNodeName = &nodeName
cloneBody.TargetNodeName = &nodeName
err = veClient.CloneVM(cloneNodeName, cloneVMID, body)
err = veClient.CloneVM(cloneNodeName, cloneVMID, cloneBody)
} else {
err = veClient.CloneVM(nodeName, cloneVMID, body)
err = veClient.CloneVM(nodeName, cloneVMID, cloneBody)
}
if err != nil {
@ -1180,7 +1180,7 @@ func resourceVirtualEnvironmentVMCreateClone(d *schema.ResourceData, m interface
}
}
for i := len(updateBody.NetworkDevices); i < maxNetworkDevices; i++ {
for i := len(updateBody.NetworkDevices); i < maxResourceVirtualEnvironmentVMNetworkDevices; i++ {
delete = append(delete, fmt.Sprintf("net%d", i))
}
}
@ -1199,7 +1199,7 @@ func resourceVirtualEnvironmentVMCreateClone(d *schema.ResourceData, m interface
return err
}
for i := len(updateBody.SerialDevices); i < maxSerialDevices; i++ {
for i := len(updateBody.SerialDevices); i < maxResourceVirtualEnvironmentVMSerialDevices; i++ {
delete = append(delete, fmt.Sprintf("serial%d", i))
}
}
@ -1411,7 +1411,7 @@ func resourceVirtualEnvironmentVMCreateCustom(d *schema.ResourceData, m interfac
scsiHardware := "virtio-scsi-pci"
body := &proxmox.VirtualEnvironmentVMCreateRequestBody{
createBody := &proxmox.VirtualEnvironmentVMCreateRequestBody{
ACPI: &acpi,
Agent: &proxmox.CustomAgent{
Enabled: &agentEnabled,
@ -1450,18 +1450,18 @@ func resourceVirtualEnvironmentVMCreateCustom(d *schema.ResourceData, m interfac
}
if cpuHotplugged > 0 {
body.VirtualCPUCount = &cpuHotplugged
createBody.VirtualCPUCount = &cpuHotplugged
}
if description != "" {
body.Description = &description
createBody.Description = &description
}
if name != "" {
body.Name = &name
createBody.Name = &name
}
err = veClient.CreateVM(nodeName, body)
err = veClient.CreateVM(nodeName, createBody)
if err != nil {
return err
@ -1992,14 +1992,6 @@ func resourceVirtualEnvironmentVMRead(d *schema.ResourceData, m interface{}) err
return err
}
/*
clone := d.Get(mkResourceVirtualEnvironmentVMClone).([]interface{})
if len(clone) > 0 {
return resourceVirtualEnvironmentVMReadClone(d, m, vmID, vmConfig, vmStatus)
}
*/
return resourceVirtualEnvironmentVMReadCustom(d, m, vmID, vmConfig, vmStatus)
}
@ -2831,7 +2823,7 @@ func resourceVirtualEnvironmentVMUpdate(d *schema.ResourceData, m interface{}) e
return err
}
body := &proxmox.VirtualEnvironmentVMUpdateRequestBody{
updateBody := &proxmox.VirtualEnvironmentVMUpdateRequestBody{
IDEDevices: proxmox.CustomStorageDevices{
proxmox.CustomStorageDevice{
Enabled: false,
@ -2858,42 +2850,42 @@ func resourceVirtualEnvironmentVMUpdate(d *schema.ResourceData, m interface{}) e
// Prepare the new primitive configuration values.
if d.HasChange(mkResourceVirtualEnvironmentVMACPI) {
acpi := proxmox.CustomBool(d.Get(mkResourceVirtualEnvironmentVMACPI).(bool))
body.ACPI = &acpi
updateBody.ACPI = &acpi
rebootRequired = true
}
if d.HasChange(mkResourceVirtualEnvironmentVMBIOS) {
bios := d.Get(mkResourceVirtualEnvironmentVMBIOS).(string)
body.BIOS = &bios
updateBody.BIOS = &bios
rebootRequired = true
}
if d.HasChange(mkResourceVirtualEnvironmentVMDescription) {
description := d.Get(mkResourceVirtualEnvironmentVMDescription).(string)
body.Description = &description
updateBody.Description = &description
}
if d.HasChange(mkResourceVirtualEnvironmentVMKeyboardLayout) {
keyboardLayout := d.Get(mkResourceVirtualEnvironmentVMKeyboardLayout).(string)
body.KeyboardLayout = &keyboardLayout
updateBody.KeyboardLayout = &keyboardLayout
rebootRequired = true
}
if d.HasChange(mkResourceVirtualEnvironmentVMName) {
name := d.Get(mkResourceVirtualEnvironmentVMName).(string)
body.Name = &name
updateBody.Name = &name
}
if d.HasChange(mkResourceVirtualEnvironmentVMTabletDevice) {
tabletDevice := proxmox.CustomBool(d.Get(mkResourceVirtualEnvironmentVMTabletDevice).(bool))
body.TabletDeviceEnabled = &tabletDevice
updateBody.TabletDeviceEnabled = &tabletDevice
rebootRequired = true
}
template := proxmox.CustomBool(d.Get(mkResourceVirtualEnvironmentVMTemplate).(bool))
if d.HasChange(mkResourceVirtualEnvironmentVMTemplate) {
body.Template = &template
updateBody.Template = &template
rebootRequired = true
}
@ -2909,7 +2901,7 @@ func resourceVirtualEnvironmentVMUpdate(d *schema.ResourceData, m interface{}) e
agentTrim := proxmox.CustomBool(agentBlock[mkResourceVirtualEnvironmentVMAgentTrim].(bool))
agentType := agentBlock[mkResourceVirtualEnvironmentVMAgentType].(string)
body.Agent = &proxmox.CustomAgent{
updateBody.Agent = &proxmox.CustomAgent{
Enabled: &agentEnabled,
TrimClonedDisks: &agentTrim,
Type: &agentType,
@ -2920,19 +2912,19 @@ func resourceVirtualEnvironmentVMUpdate(d *schema.ResourceData, m interface{}) e
// Prepare the new audio devices.
if d.HasChange(mkResourceVirtualEnvironmentVMAudioDevice) {
body.AudioDevices, err = resourceVirtualEnvironmentVMGetAudioDeviceList(d, m)
updateBody.AudioDevices, err = resourceVirtualEnvironmentVMGetAudioDeviceList(d, m)
if err != nil {
return err
}
for i := 0; i < len(body.AudioDevices); i++ {
if !body.AudioDevices[i].Enabled {
for i := 0; i < len(updateBody.AudioDevices); i++ {
if !updateBody.AudioDevices[i].Enabled {
delete = append(delete, fmt.Sprintf("audio%d", i))
}
}
for i := len(body.AudioDevices); i < maxAudioDevices; i++ {
for i := len(updateBody.AudioDevices); i < maxResourceVirtualEnvironmentVMAudioDevices; i++ {
delete = append(delete, fmt.Sprintf("audio%d", i))
}
@ -2956,7 +2948,7 @@ func resourceVirtualEnvironmentVMUpdate(d *schema.ResourceData, m interface{}) e
cdromMedia := "cdrom"
body.IDEDevices[2] = proxmox.CustomStorageDevice{
updateBody.IDEDevices[2] = proxmox.CustomStorageDevice{
Enabled: cdromEnabled,
FileVolume: cdromFileID,
Media: &cdromMedia,
@ -2979,13 +2971,13 @@ func resourceVirtualEnvironmentVMUpdate(d *schema.ResourceData, m interface{}) e
cpuType := cpuBlock[mkResourceVirtualEnvironmentVMCPUType].(string)
cpuUnits := cpuBlock[mkResourceVirtualEnvironmentVMCPUUnits].(int)
body.CPUArchitecture = &cpuArchitecture
body.CPUCores = &cpuCores
body.CPUSockets = &cpuSockets
body.CPUUnits = &cpuUnits
updateBody.CPUArchitecture = &cpuArchitecture
updateBody.CPUCores = &cpuCores
updateBody.CPUSockets = &cpuSockets
updateBody.CPUUnits = &cpuUnits
if cpuHotplugged > 0 {
body.VirtualCPUCount = &cpuHotplugged
updateBody.VirtualCPUCount = &cpuHotplugged
} else {
delete = append(delete, "vcpus")
}
@ -2996,7 +2988,7 @@ func resourceVirtualEnvironmentVMUpdate(d *schema.ResourceData, m interface{}) e
cpuFlagsConverted[fi] = flag.(string)
}
body.CPUEmulation = &proxmox.CustomCPUEmulation{
updateBody.CPUEmulation = &proxmox.CustomCPUEmulation{
Flags: &cpuFlagsConverted,
Type: cpuType,
}
@ -3029,18 +3021,18 @@ func resourceVirtualEnvironmentVMUpdate(d *schema.ResourceData, m interface{}) e
vmConfig.SCSIDevice13,
}
body.SCSIDevices = make(proxmox.CustomStorageDevices, len(diskDeviceObjects))
updateBody.SCSIDevices = make(proxmox.CustomStorageDevices, len(diskDeviceObjects))
for di, do := range diskDeviceObjects {
if scsiDevices[di] == nil {
return fmt.Errorf("Missing SCSI device %d (scsi%d)", di, di)
}
body.SCSIDevices[di] = *scsiDevices[di]
body.SCSIDevices[di].BurstableReadSpeedMbps = do.BurstableReadSpeedMbps
body.SCSIDevices[di].BurstableWriteSpeedMbps = do.BurstableWriteSpeedMbps
body.SCSIDevices[di].MaxReadSpeedMbps = do.MaxReadSpeedMbps
body.SCSIDevices[di].MaxWriteSpeedMbps = do.MaxWriteSpeedMbps
updateBody.SCSIDevices[di] = *scsiDevices[di]
updateBody.SCSIDevices[di].BurstableReadSpeedMbps = do.BurstableReadSpeedMbps
updateBody.SCSIDevices[di].BurstableWriteSpeedMbps = do.BurstableWriteSpeedMbps
updateBody.SCSIDevices[di].MaxReadSpeedMbps = do.MaxReadSpeedMbps
updateBody.SCSIDevices[di].MaxWriteSpeedMbps = do.MaxWriteSpeedMbps
}
rebootRequired = true
@ -3054,12 +3046,12 @@ func resourceVirtualEnvironmentVMUpdate(d *schema.ResourceData, m interface{}) e
return err
}
body.CloudInitConfig = initializationConfig
updateBody.CloudInitConfig = initializationConfig
if body.CloudInitConfig != nil {
if updateBody.CloudInitConfig != nil {
cdromMedia := "cdrom"
body.IDEDevices[2] = proxmox.CustomStorageDevice{
updateBody.IDEDevices[2] = proxmox.CustomStorageDevice{
Enabled: true,
FileVolume: "local-lvm:cloudinit",
Media: &cdromMedia,
@ -3067,7 +3059,7 @@ func resourceVirtualEnvironmentVMUpdate(d *schema.ResourceData, m interface{}) e
if vmConfig.IDEDevice2 != nil {
if strings.Contains(vmConfig.IDEDevice2.FileVolume, fmt.Sprintf("vm-%d-cloudinit", vmID)) {
body.IDEDevices[2].Enabled = false
updateBody.IDEDevices[2].Enabled = false
}
}
}
@ -3087,13 +3079,13 @@ func resourceVirtualEnvironmentVMUpdate(d *schema.ResourceData, m interface{}) e
memoryFloating := memoryBlock[mkResourceVirtualEnvironmentVMMemoryFloating].(int)
memoryShared := memoryBlock[mkResourceVirtualEnvironmentVMMemoryShared].(int)
body.DedicatedMemory = &memoryDedicated
body.FloatingMemory = &memoryFloating
updateBody.DedicatedMemory = &memoryDedicated
updateBody.FloatingMemory = &memoryFloating
if memoryShared > 0 {
memorySharedName := fmt.Sprintf("vm-%d-ivshmem", vmID)
body.SharedMemory = &proxmox.CustomSharedMemory{
updateBody.SharedMemory = &proxmox.CustomSharedMemory{
Name: &memorySharedName,
Size: memoryShared,
}
@ -3104,19 +3096,19 @@ func resourceVirtualEnvironmentVMUpdate(d *schema.ResourceData, m interface{}) e
// Prepare the new network device configuration.
if d.HasChange(mkResourceVirtualEnvironmentVMNetworkDevice) {
body.NetworkDevices, err = resourceVirtualEnvironmentVMGetNetworkDeviceObjects(d, m)
updateBody.NetworkDevices, err = resourceVirtualEnvironmentVMGetNetworkDeviceObjects(d, m)
if err != nil {
return err
}
for i := 0; i < len(body.NetworkDevices); i++ {
if !body.NetworkDevices[i].Enabled {
for i := 0; i < len(updateBody.NetworkDevices); i++ {
if !updateBody.NetworkDevices[i].Enabled {
delete = append(delete, fmt.Sprintf("net%d", i))
}
}
for i := len(body.NetworkDevices); i < maxNetworkDevices; i++ {
for i := len(updateBody.NetworkDevices); i < maxResourceVirtualEnvironmentVMNetworkDevices; i++ {
delete = append(delete, fmt.Sprintf("net%d", i))
}
@ -3133,20 +3125,20 @@ func resourceVirtualEnvironmentVMUpdate(d *schema.ResourceData, m interface{}) e
operatingSystemType := operatingSystem[mkResourceVirtualEnvironmentVMOperatingSystemType].(string)
body.OSType = &operatingSystemType
updateBody.OSType = &operatingSystemType
rebootRequired = true
}
// Prepare the new serial devices.
if d.HasChange(mkResourceVirtualEnvironmentVMSerialDevice) {
body.SerialDevices, err = resourceVirtualEnvironmentVMGetSerialDeviceList(d, m)
updateBody.SerialDevices, err = resourceVirtualEnvironmentVMGetSerialDeviceList(d, m)
if err != nil {
return err
}
for i := len(body.SerialDevices); i < maxSerialDevices; i++ {
for i := len(updateBody.SerialDevices); i < maxResourceVirtualEnvironmentVMSerialDevices; i++ {
delete = append(delete, fmt.Sprintf("serial%d", i))
}
@ -3155,7 +3147,7 @@ func resourceVirtualEnvironmentVMUpdate(d *schema.ResourceData, m interface{}) e
// Prepare the new VGA configuration.
if d.HasChange(mkResourceVirtualEnvironmentVMVGA) {
body.VGADevice, err = resourceVirtualEnvironmentVMGetVGADeviceObject(d, m)
updateBody.VGADevice, err = resourceVirtualEnvironmentVMGetVGADeviceObject(d, m)
if err != nil {
return err
@ -3165,9 +3157,9 @@ func resourceVirtualEnvironmentVMUpdate(d *schema.ResourceData, m interface{}) e
}
// Update the configuration now that everything has been prepared.
body.Delete = delete
updateBody.Delete = delete
err = veClient.UpdateVM(nodeName, vmID, body)
err = veClient.UpdateVM(nodeName, vmID, updateBody)
if err != nil {
return err

View File

@ -58,7 +58,7 @@ func TestResourceVirtualEnvironmentVMSchema(t *testing.T) {
mkResourceVirtualEnvironmentVMNetworkInterfaceNames,
})
testSchemaValueTypes(t, s, map[string]schema.ValueType{
testValueTypes(t, s, map[string]schema.ValueType{
mkResourceVirtualEnvironmentVMACPI: schema.TypeBool,
mkResourceVirtualEnvironmentVMAgent: schema.TypeList,
mkResourceVirtualEnvironmentVMAudioDevice: schema.TypeList,
@ -93,7 +93,7 @@ func TestResourceVirtualEnvironmentVMSchema(t *testing.T) {
mkResourceVirtualEnvironmentVMAgentType,
})
testSchemaValueTypes(t, agentSchema, map[string]schema.ValueType{
testValueTypes(t, agentSchema, map[string]schema.ValueType{
mkResourceVirtualEnvironmentVMAgentEnabled: schema.TypeBool,
mkResourceVirtualEnvironmentVMAgentTrim: schema.TypeBool,
mkResourceVirtualEnvironmentVMAgentType: schema.TypeString,
@ -106,7 +106,7 @@ func TestResourceVirtualEnvironmentVMSchema(t *testing.T) {
mkResourceVirtualEnvironmentVMAudioDeviceDriver,
})
testSchemaValueTypes(t, audioDeviceSchema, map[string]schema.ValueType{
testValueTypes(t, audioDeviceSchema, map[string]schema.ValueType{
mkResourceVirtualEnvironmentVMAudioDeviceDevice: schema.TypeString,
mkResourceVirtualEnvironmentVMAudioDeviceDriver: schema.TypeString,
})
@ -118,7 +118,7 @@ func TestResourceVirtualEnvironmentVMSchema(t *testing.T) {
mkResourceVirtualEnvironmentVMCDROMFileID,
})
testSchemaValueTypes(t, cdromSchema, map[string]schema.ValueType{
testValueTypes(t, cdromSchema, map[string]schema.ValueType{
mkResourceVirtualEnvironmentVMCDROMEnabled: schema.TypeBool,
mkResourceVirtualEnvironmentVMCDROMFileID: schema.TypeString,
})
@ -134,7 +134,7 @@ func TestResourceVirtualEnvironmentVMSchema(t *testing.T) {
mkResourceVirtualEnvironmentVMCloneNodeName,
})
testSchemaValueTypes(t, cloneSchema, map[string]schema.ValueType{
testValueTypes(t, cloneSchema, map[string]schema.ValueType{
mkResourceVirtualEnvironmentVMCloneDatastoreID: schema.TypeString,
mkResourceVirtualEnvironmentVMCloneNodeName: schema.TypeString,
mkResourceVirtualEnvironmentVMCloneVMID: schema.TypeInt,
@ -152,7 +152,7 @@ func TestResourceVirtualEnvironmentVMSchema(t *testing.T) {
mkResourceVirtualEnvironmentVMCPUUnits,
})
testSchemaValueTypes(t, cpuSchema, map[string]schema.ValueType{
testValueTypes(t, cpuSchema, map[string]schema.ValueType{
mkResourceVirtualEnvironmentVMCPUArchitecture: schema.TypeString,
mkResourceVirtualEnvironmentVMCPUCores: schema.TypeInt,
mkResourceVirtualEnvironmentVMCPUFlags: schema.TypeList,
@ -171,7 +171,7 @@ func TestResourceVirtualEnvironmentVMSchema(t *testing.T) {
mkResourceVirtualEnvironmentVMDiskSize,
})
testSchemaValueTypes(t, diskSchema, map[string]schema.ValueType{
testValueTypes(t, diskSchema, map[string]schema.ValueType{
mkResourceVirtualEnvironmentVMDiskDatastoreID: schema.TypeString,
mkResourceVirtualEnvironmentVMDiskFileFormat: schema.TypeString,
mkResourceVirtualEnvironmentVMDiskFileID: schema.TypeString,
@ -187,7 +187,7 @@ func TestResourceVirtualEnvironmentVMSchema(t *testing.T) {
mkResourceVirtualEnvironmentVMDiskSpeedWriteBurstable,
})
testSchemaValueTypes(t, diskSpeedSchema, map[string]schema.ValueType{
testValueTypes(t, diskSpeedSchema, map[string]schema.ValueType{
mkResourceVirtualEnvironmentVMDiskSpeedRead: schema.TypeInt,
mkResourceVirtualEnvironmentVMDiskSpeedReadBurstable: schema.TypeInt,
mkResourceVirtualEnvironmentVMDiskSpeedWrite: schema.TypeInt,
@ -202,7 +202,7 @@ func TestResourceVirtualEnvironmentVMSchema(t *testing.T) {
mkResourceVirtualEnvironmentVMInitializationUserAccount,
})
testSchemaValueTypes(t, initializationSchema, map[string]schema.ValueType{
testValueTypes(t, initializationSchema, map[string]schema.ValueType{
mkResourceVirtualEnvironmentVMInitializationDNS: schema.TypeList,
mkResourceVirtualEnvironmentVMInitializationIPConfig: schema.TypeList,
mkResourceVirtualEnvironmentVMInitializationUserAccount: schema.TypeList,
@ -215,7 +215,7 @@ func TestResourceVirtualEnvironmentVMSchema(t *testing.T) {
mkResourceVirtualEnvironmentVMInitializationDNSServer,
})
testSchemaValueTypes(t, initializationDNSSchema, map[string]schema.ValueType{
testValueTypes(t, initializationDNSSchema, map[string]schema.ValueType{
mkResourceVirtualEnvironmentVMInitializationDNSDomain: schema.TypeString,
mkResourceVirtualEnvironmentVMInitializationDNSServer: schema.TypeString,
})
@ -227,7 +227,7 @@ func TestResourceVirtualEnvironmentVMSchema(t *testing.T) {
mkResourceVirtualEnvironmentVMInitializationIPConfigIPv6,
})
testSchemaValueTypes(t, initializationIPConfigSchema, map[string]schema.ValueType{
testValueTypes(t, initializationIPConfigSchema, map[string]schema.ValueType{
mkResourceVirtualEnvironmentVMInitializationIPConfigIPv4: schema.TypeList,
mkResourceVirtualEnvironmentVMInitializationIPConfigIPv6: schema.TypeList,
})
@ -239,7 +239,7 @@ func TestResourceVirtualEnvironmentVMSchema(t *testing.T) {
mkResourceVirtualEnvironmentVMInitializationIPConfigIPv4Gateway,
})
testSchemaValueTypes(t, initializationIPConfigIPv4Schema, map[string]schema.ValueType{
testValueTypes(t, initializationIPConfigIPv4Schema, map[string]schema.ValueType{
mkResourceVirtualEnvironmentVMInitializationIPConfigIPv4Address: schema.TypeString,
mkResourceVirtualEnvironmentVMInitializationIPConfigIPv4Gateway: schema.TypeString,
})
@ -251,7 +251,7 @@ func TestResourceVirtualEnvironmentVMSchema(t *testing.T) {
mkResourceVirtualEnvironmentVMInitializationIPConfigIPv6Gateway,
})
testSchemaValueTypes(t, initializationIPConfigIPv6Schema, map[string]schema.ValueType{
testValueTypes(t, initializationIPConfigIPv6Schema, map[string]schema.ValueType{
mkResourceVirtualEnvironmentVMInitializationIPConfigIPv6Address: schema.TypeString,
mkResourceVirtualEnvironmentVMInitializationIPConfigIPv6Gateway: schema.TypeString,
})
@ -264,7 +264,7 @@ func TestResourceVirtualEnvironmentVMSchema(t *testing.T) {
mkResourceVirtualEnvironmentVMInitializationUserAccountUsername,
})
testSchemaValueTypes(t, initializationUserAccountSchema, map[string]schema.ValueType{
testValueTypes(t, initializationUserAccountSchema, map[string]schema.ValueType{
mkResourceVirtualEnvironmentVMInitializationUserAccountKeys: schema.TypeList,
mkResourceVirtualEnvironmentVMInitializationUserAccountPassword: schema.TypeString,
mkResourceVirtualEnvironmentVMInitializationUserAccountUsername: schema.TypeString,
@ -278,7 +278,7 @@ func TestResourceVirtualEnvironmentVMSchema(t *testing.T) {
mkResourceVirtualEnvironmentVMMemoryShared,
})
testSchemaValueTypes(t, memorySchema, map[string]schema.ValueType{
testValueTypes(t, memorySchema, map[string]schema.ValueType{
mkResourceVirtualEnvironmentVMMemoryDedicated: schema.TypeInt,
mkResourceVirtualEnvironmentVMMemoryFloating: schema.TypeInt,
mkResourceVirtualEnvironmentVMMemoryShared: schema.TypeInt,
@ -295,7 +295,7 @@ func TestResourceVirtualEnvironmentVMSchema(t *testing.T) {
mkResourceVirtualEnvironmentVMNetworkDeviceVLANID,
})
testSchemaValueTypes(t, networkDeviceSchema, map[string]schema.ValueType{
testValueTypes(t, networkDeviceSchema, map[string]schema.ValueType{
mkResourceVirtualEnvironmentVMNetworkDeviceBridge: schema.TypeString,
mkResourceVirtualEnvironmentVMNetworkDeviceEnabled: schema.TypeBool,
mkResourceVirtualEnvironmentVMNetworkDeviceMACAddress: schema.TypeString,
@ -310,7 +310,7 @@ func TestResourceVirtualEnvironmentVMSchema(t *testing.T) {
mkResourceVirtualEnvironmentVMOperatingSystemType,
})
testSchemaValueTypes(t, operatingSystemSchema, map[string]schema.ValueType{
testValueTypes(t, operatingSystemSchema, map[string]schema.ValueType{
mkResourceVirtualEnvironmentVMOperatingSystemType: schema.TypeString,
})
@ -320,7 +320,7 @@ func TestResourceVirtualEnvironmentVMSchema(t *testing.T) {
mkResourceVirtualEnvironmentVMSerialDeviceDevice,
})
testSchemaValueTypes(t, serialDeviceSchema, map[string]schema.ValueType{
testValueTypes(t, serialDeviceSchema, map[string]schema.ValueType{
mkResourceVirtualEnvironmentVMSerialDeviceDevice: schema.TypeString,
})
@ -332,7 +332,7 @@ func TestResourceVirtualEnvironmentVMSchema(t *testing.T) {
mkResourceVirtualEnvironmentVMVGAType,
})
testSchemaValueTypes(t, vgaSchema, map[string]schema.ValueType{
testValueTypes(t, vgaSchema, map[string]schema.ValueType{
mkResourceVirtualEnvironmentVMVGAEnabled: schema.TypeBool,
mkResourceVirtualEnvironmentVMVGAMemory: schema.TypeInt,
mkResourceVirtualEnvironmentVMVGAType: schema.TypeString,

View File

@ -397,7 +397,7 @@ func testRequiredArguments(t *testing.T, s *schema.Resource, keys []string) {
}
}
func testSchemaValueTypes(t *testing.T, s *schema.Resource, f map[string]schema.ValueType) {
func testValueTypes(t *testing.T, s *schema.Resource, f map[string]schema.ValueType) {
for fn, ft := range f {
if s.Schema[fn] == nil {
t.Fatalf("Error in Schema: Missing definition for \"%s\"", fn)