0
0
mirror of https://github.com/bpg/terraform-provider-proxmox.git synced 2025-08-22 19:38:35 +00:00

Merge pull request #16 from danitso/bugfix-vm-id-uniqueness

Bugfix vm id uniqueness
This commit is contained in:
Dan R. Petersen 2020-04-03 22:29:54 +02:00 committed by GitHub
commit bbdc197609
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 109 additions and 13 deletions

View File

@ -3,6 +3,8 @@
BUG FIXES:
* library/virtual_environment_nodes: Fix node IP address format
* resource/virtual_environment_container: Fix VM ID collision when `vm_id` is not specified
* resource/virtual_environment_vm: Fix VM ID collision when `vm_id` is not specified
WORKAROUNDS:

1
go.sum
View File

@ -78,6 +78,7 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee
github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=

View File

@ -18,6 +18,9 @@ type CustomBool bool
// CustomCommaSeparatedList allows a JSON string to also be a string array.
type CustomCommaSeparatedList []string
// CustomInt allows a JSON integer value to also be a string.
type CustomInt int
// CustomLineBreakSeparatedList allows a multiline JSON string to also be a string array.
type CustomLineBreakSeparatedList []string
@ -70,6 +73,25 @@ func (r *CustomCommaSeparatedList) UnmarshalJSON(b []byte) error {
return nil
}
// UnmarshalJSON converts a JSON value to an integer.
func (r *CustomInt) UnmarshalJSON(b []byte) error {
s := string(b)
if strings.HasPrefix(s, "\"") && strings.HasSuffix(s, "\"") {
s = s[1 : len(s)-1]
}
i, err := strconv.ParseInt(s, 10, 32)
if err != nil {
return err
}
*r = CustomInt(i)
return nil
}
// MarshalJSON converts a boolean to a JSON value.
func (r *CustomLineBreakSeparatedList) MarshalJSON() ([]byte, error) {
s := strings.Join(*r, "\n")

View File

@ -0,0 +1,29 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
package proxmox
import (
"errors"
)
// GetClusterNextID retrieves the next free VM identifier for the cluster.
func (c *VirtualEnvironmentClient) GetClusterNextID(vmID *int) (*int, error) {
reqBody := &VirtualEnvironmentClusterNextIDRequestBody{
VMID: vmID,
}
resBody := &VirtualEnvironmentClusterNextIDResponseBody{}
err := c.DoRequest(hmGET, "cluster/nextid", reqBody, resBody)
if err != nil {
return nil, err
}
if resBody.Data == nil {
return nil, errors.New("The server did not include a data object in the response")
}
return (*int)(resBody.Data), nil
}

View File

@ -0,0 +1,15 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
package proxmox
// VirtualEnvironmentClusterNextIDRequestBody contains the data for a cluster next id request.
type VirtualEnvironmentClusterNextIDRequestBody struct {
VMID *int `json:"vmid,omitempty" url:"vmid,omitempty"`
}
// VirtualEnvironmentClusterNextIDResponseBody contains the body from a cluster next id response.
type VirtualEnvironmentClusterNextIDResponseBody struct {
Data *CustomInt `json:"data,omitempty"`
}

View File

@ -7,11 +7,22 @@ package proxmox
import (
"errors"
"fmt"
"log"
"net/url"
"strings"
"sync"
"time"
)
const (
getVMIDStep = 1
)
var (
getVMIDCounter = -1
getVMIDCounterMutex = &sync.Mutex{}
)
// CloneVM clones a virtual machine.
func (c *VirtualEnvironmentClient) CloneVM(nodeName string, vmID int, d *VirtualEnvironmentVMCloneRequestBody) error {
return c.DoRequest(hmPOST, fmt.Sprintf("nodes/%s/qemu/%d/clone", url.PathEscape(nodeName), vmID), d, nil)
@ -45,30 +56,46 @@ func (c *VirtualEnvironmentClient) GetVM(nodeName string, vmID int) (*VirtualEnv
// GetVMID retrieves the next available VM identifier.
func (c *VirtualEnvironmentClient) GetVMID() (*int, error) {
nodes, err := c.ListNodes()
getVMIDCounterMutex.Lock()
defer getVMIDCounterMutex.Unlock()
if err != nil {
return nil, err
if getVMIDCounter < 0 {
nextVMID, err := c.GetClusterNextID(nil)
if err != nil {
return nil, err
}
if nextVMID == nil {
return nil, errors.New("Unable to retrieve the next available VM identifier")
}
getVMIDCounter = *nextVMID + getVMIDStep
log.Printf("[DEBUG] Determined next available VM identifier to be %d", *nextVMID)
return nextVMID, nil
}
vmID := 100
vmID := getVMIDCounter
VMID:
for vmID <= 2147483637 {
for _, n := range nodes {
err := c.DoRequest(hmGET, fmt.Sprintf("nodes/%s/qemu/%d/status/current", url.PathEscape(n.Name), vmID), nil, nil)
_, err := c.GetClusterNextID(&vmID)
if err == nil {
vmID += 5
if err != nil {
vmID += getVMIDStep
continue VMID
}
continue
}
getVMIDCounter = vmID + getVMIDStep
log.Printf("[DEBUG] Determined next available VM identifier to be %d", vmID)
return &vmID, nil
}
return nil, errors.New("Unable to retrieve the next available VM identifier")
return nil, errors.New("Unable to determine the next available VM identifier")
}
// GetVMNetworkInterfacesFromAgent retrieves the network interfaces reported by the QEMU agent.

View File

@ -349,7 +349,7 @@ func getVLANIDsValidator() schema.SchemaValidateFunc {
func getVMIDValidator() schema.SchemaValidateFunc {
return func(i interface{}, k string) (ws []string, es []error) {
min := 1
min := 100
max := 2147483647
v, ok := i.(int)