mirror of
https://github.com/bpg/terraform-provider-proxmox.git
synced 2025-08-23 03:48:35 +00:00
Merge pull request #16 from danitso/bugfix-vm-id-uniqueness
Bugfix vm id uniqueness
This commit is contained in:
commit
bbdc197609
@ -3,6 +3,8 @@
|
|||||||
BUG FIXES:
|
BUG FIXES:
|
||||||
|
|
||||||
* library/virtual_environment_nodes: Fix node IP address format
|
* 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:
|
WORKAROUNDS:
|
||||||
|
|
||||||
|
1
go.sum
1
go.sum
@ -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/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/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.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/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/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=
|
github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8=
|
||||||
|
@ -18,6 +18,9 @@ type CustomBool bool
|
|||||||
// CustomCommaSeparatedList allows a JSON string to also be a string array.
|
// CustomCommaSeparatedList allows a JSON string to also be a string array.
|
||||||
type CustomCommaSeparatedList []string
|
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.
|
// CustomLineBreakSeparatedList allows a multiline JSON string to also be a string array.
|
||||||
type CustomLineBreakSeparatedList []string
|
type CustomLineBreakSeparatedList []string
|
||||||
|
|
||||||
@ -70,6 +73,25 @@ func (r *CustomCommaSeparatedList) UnmarshalJSON(b []byte) error {
|
|||||||
return nil
|
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.
|
// MarshalJSON converts a boolean to a JSON value.
|
||||||
func (r *CustomLineBreakSeparatedList) MarshalJSON() ([]byte, error) {
|
func (r *CustomLineBreakSeparatedList) MarshalJSON() ([]byte, error) {
|
||||||
s := strings.Join(*r, "\n")
|
s := strings.Join(*r, "\n")
|
||||||
|
29
proxmox/virtual_environment_cluster.go
Normal file
29
proxmox/virtual_environment_cluster.go
Normal 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
|
||||||
|
}
|
15
proxmox/virtual_environment_cluster_types.go
Normal file
15
proxmox/virtual_environment_cluster_types.go
Normal 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"`
|
||||||
|
}
|
@ -7,11 +7,22 @@ package proxmox
|
|||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log"
|
||||||
"net/url"
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
getVMIDStep = 1
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
getVMIDCounter = -1
|
||||||
|
getVMIDCounterMutex = &sync.Mutex{}
|
||||||
|
)
|
||||||
|
|
||||||
// CloneVM clones a virtual machine.
|
// CloneVM clones a virtual machine.
|
||||||
func (c *VirtualEnvironmentClient) CloneVM(nodeName string, vmID int, d *VirtualEnvironmentVMCloneRequestBody) error {
|
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)
|
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.
|
// GetVMID retrieves the next available VM identifier.
|
||||||
func (c *VirtualEnvironmentClient) GetVMID() (*int, error) {
|
func (c *VirtualEnvironmentClient) GetVMID() (*int, error) {
|
||||||
nodes, err := c.ListNodes()
|
getVMIDCounterMutex.Lock()
|
||||||
|
defer getVMIDCounterMutex.Unlock()
|
||||||
|
|
||||||
|
if getVMIDCounter < 0 {
|
||||||
|
nextVMID, err := c.GetClusterNextID(nil)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
vmID := 100
|
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 := getVMIDCounter
|
||||||
|
|
||||||
VMID:
|
|
||||||
for vmID <= 2147483637 {
|
for vmID <= 2147483637 {
|
||||||
for _, n := range nodes {
|
_, err := c.GetClusterNextID(&vmID)
|
||||||
err := c.DoRequest(hmGET, fmt.Sprintf("nodes/%s/qemu/%d/status/current", url.PathEscape(n.Name), vmID), nil, nil)
|
|
||||||
|
|
||||||
if err == nil {
|
if err != nil {
|
||||||
vmID += 5
|
vmID += getVMIDStep
|
||||||
|
|
||||||
continue VMID
|
continue
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getVMIDCounter = vmID + getVMIDStep
|
||||||
|
|
||||||
|
log.Printf("[DEBUG] Determined next available VM identifier to be %d", vmID)
|
||||||
|
|
||||||
return &vmID, nil
|
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.
|
// GetVMNetworkInterfacesFromAgent retrieves the network interfaces reported by the QEMU agent.
|
||||||
|
@ -349,7 +349,7 @@ func getVLANIDsValidator() schema.SchemaValidateFunc {
|
|||||||
|
|
||||||
func getVMIDValidator() schema.SchemaValidateFunc {
|
func getVMIDValidator() schema.SchemaValidateFunc {
|
||||||
return func(i interface{}, k string) (ws []string, es []error) {
|
return func(i interface{}, k string) (ws []string, es []error) {
|
||||||
min := 1
|
min := 100
|
||||||
max := 2147483647
|
max := 2147483647
|
||||||
|
|
||||||
v, ok := i.(int)
|
v, ok := i.(int)
|
||||||
|
Loading…
Reference in New Issue
Block a user