mirror of
https://github.com/outbackdingo/proxmox-cloud-controller-manager.git
synced 2026-01-27 10:20:13 +00:00
feat: custom instance type
Now, we can set a custom instance type using the smbios1[sku] argument Signed-off-by: Serge Logvinov <serge.logvinov@sinextra.dev>
This commit is contained in:
@@ -180,7 +180,7 @@ func (c *Cluster) FindVMByUUID(ctx context.Context, uuid string) (*pxapi.VmRef,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if config["smbios1"] != nil {
|
if config["smbios1"] != nil {
|
||||||
if c.getUUID(config["smbios1"].(string)) == uuid { //nolint:errcheck
|
if c.getSMBSetting(config, "uuid") == uuid {
|
||||||
return vmr, region, nil
|
return vmr, region, nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -202,13 +202,27 @@ func (c *Cluster) GetVMName(vmInfo map[string]interface{}) string {
|
|||||||
// GetVMUUID returns the VM UUID.
|
// GetVMUUID returns the VM UUID.
|
||||||
func (c *Cluster) GetVMUUID(vmInfo map[string]interface{}) string {
|
func (c *Cluster) GetVMUUID(vmInfo map[string]interface{}) string {
|
||||||
if vmInfo["smbios1"] != nil {
|
if vmInfo["smbios1"] != nil {
|
||||||
return c.getUUID(vmInfo["smbios1"].(string)) //nolint:errcheck
|
return c.getSMBSetting(vmInfo, "uuid")
|
||||||
}
|
}
|
||||||
|
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cluster) getUUID(smbios string) string {
|
// GetVMSKU returns the VM instance type name.
|
||||||
|
func (c *Cluster) GetVMSKU(vmInfo map[string]interface{}) string {
|
||||||
|
if vmInfo["smbios1"] != nil {
|
||||||
|
return c.getSMBSetting(vmInfo, "sku")
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Cluster) getSMBSetting(vmInfo map[string]interface{}, name string) string {
|
||||||
|
smbios, ok := vmInfo["smbios1"].(string)
|
||||||
|
if !ok {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
for _, l := range strings.Split(smbios, ",") {
|
for _, l := range strings.Split(smbios, ",") {
|
||||||
if l == "" || l == "base64=1" {
|
if l == "" || l == "base64=1" {
|
||||||
continue
|
continue
|
||||||
@@ -220,7 +234,7 @@ func (c *Cluster) getUUID(smbios string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for k, v := range parsedParameter {
|
for k, v := range parsedParameter {
|
||||||
if k == "uuid" {
|
if k == name {
|
||||||
decodedString, err := base64.StdEncoding.DecodeString(v[0])
|
decodedString, err := base64.StdEncoding.DecodeString(v[0])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
decodedString = []byte(v[0])
|
decodedString = []byte(v[0])
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ package proxmox
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
pxapi "github.com/Telmate/proxmox-api-go/proxmox"
|
pxapi "github.com/Telmate/proxmox-api-go/proxmox"
|
||||||
@@ -38,6 +40,8 @@ type instances struct {
|
|||||||
provider cluster.Provider
|
provider cluster.Provider
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var instanceTypeNameRegexp = regexp.MustCompile(`(^[a-zA-Z0-9_.-]+)$`)
|
||||||
|
|
||||||
func newInstances(client *cluster.Cluster, provider cluster.Provider) *instances {
|
func newInstances(client *cluster.Cluster, provider cluster.Provider) *instances {
|
||||||
return &instances{
|
return &instances{
|
||||||
c: client,
|
c: client,
|
||||||
@@ -225,7 +229,7 @@ func (i *instances) getInstance(ctx context.Context, node *v1.Node) (*pxapi.VmRe
|
|||||||
|
|
||||||
mc := metrics.NewMetricContext("getVmInfo")
|
mc := metrics.NewMetricContext("getVmInfo")
|
||||||
|
|
||||||
vmInfo, err := px.GetVmInfo(ctx, vmRef)
|
vmConfig, err := px.GetVmConfig(ctx, vmRef)
|
||||||
if mc.ObserveRequest(err) != nil {
|
if mc.ObserveRequest(err) != nil {
|
||||||
if strings.Contains(err.Error(), "not found") {
|
if strings.Contains(err.Error(), "not found") {
|
||||||
return nil, "", cloudprovider.InstanceNotFound
|
return nil, "", cloudprovider.InstanceNotFound
|
||||||
@@ -234,13 +238,13 @@ func (i *instances) getInstance(ctx context.Context, node *v1.Node) (*pxapi.VmRe
|
|||||||
return nil, "", err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
if i.c.GetVMName(vmInfo) != node.Name && i.c.GetVMUUID(vmInfo) != node.Status.NodeInfo.SystemUUID {
|
if i.c.GetVMName(vmConfig) != node.Name || i.c.GetVMUUID(vmConfig) != node.Status.NodeInfo.SystemUUID {
|
||||||
klog.Errorf("instances.getInstance() vm.name(%s) != node.name(%s) with uuid=%s", i.c.GetVMName(vmInfo), node.Name, node.Status.NodeInfo.SystemUUID)
|
klog.Errorf("instances.getInstance() vm.name(%s) != node.name(%s) with uuid=%s", i.c.GetVMName(vmConfig), node.Name, node.Status.NodeInfo.SystemUUID)
|
||||||
|
|
||||||
return nil, "", cloudprovider.InstanceNotFound
|
return nil, "", cloudprovider.InstanceNotFound
|
||||||
}
|
}
|
||||||
|
|
||||||
klog.V(5).Infof("instances.getInstance() vmInfo %+v", vmInfo)
|
klog.V(5).Infof("instances.getInstance() vmConfig %+v", vmConfig)
|
||||||
|
|
||||||
return vmRef, region, nil
|
return vmRef, region, nil
|
||||||
}
|
}
|
||||||
@@ -253,16 +257,26 @@ func (i *instances) getInstanceType(ctx context.Context, vmRef *pxapi.VmRef, reg
|
|||||||
|
|
||||||
mc := metrics.NewMetricContext("getVmInfo")
|
mc := metrics.NewMetricContext("getVmInfo")
|
||||||
|
|
||||||
vmInfo, err := px.GetVmInfo(ctx, vmRef)
|
vmConfig, err := px.GetVmConfig(ctx, vmRef)
|
||||||
if mc.ObserveRequest(err) != nil {
|
if mc.ObserveRequest(err) != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
if vmInfo["maxcpu"] == nil || vmInfo["maxmem"] == nil {
|
sku := i.c.GetVMSKU(vmConfig)
|
||||||
|
if sku != "" && instanceTypeNameRegexp.MatchString(sku) {
|
||||||
|
return sku, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if vmConfig["cores"] == nil || vmConfig["memory"] == nil {
|
||||||
return "", fmt.Errorf("instances.getInstanceType() failed to get instance type")
|
return "", fmt.Errorf("instances.getInstanceType() failed to get instance type")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memory, err := strconv.Atoi(vmConfig["memory"].(string)) //nolint:errcheck
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
return fmt.Sprintf("%.0fVCPU-%.0fGB",
|
return fmt.Sprintf("%.0fVCPU-%.0fGB",
|
||||||
vmInfo["maxcpu"].(float64), //nolint:errcheck
|
vmConfig["cores"].(float64), //nolint:errcheck
|
||||||
vmInfo["maxmem"].(float64)/1024/1024/1024), nil //nolint:errcheck
|
float64(memory)/1024), nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,7 +72,6 @@ clusters:
|
|||||||
"name": "cluster-1-node-1",
|
"name": "cluster-1-node-1",
|
||||||
"maxcpu": 4,
|
"maxcpu": 4,
|
||||||
"maxmem": 10 * 1024 * 1024 * 1024,
|
"maxmem": 10 * 1024 * 1024 * 1024,
|
||||||
"smbios1": "uuid=8af7110d-bfad-407a-a663-9527d10a6583",
|
|
||||||
},
|
},
|
||||||
map[string]interface{}{
|
map[string]interface{}{
|
||||||
"node": "pve-2",
|
"node": "pve-2",
|
||||||
@@ -81,7 +80,6 @@ clusters:
|
|||||||
"name": "cluster-1-node-2",
|
"name": "cluster-1-node-2",
|
||||||
"maxcpu": 2,
|
"maxcpu": 2,
|
||||||
"maxmem": 5 * 1024 * 1024 * 1024,
|
"maxmem": 5 * 1024 * 1024 * 1024,
|
||||||
"smbios1": "uuid=5d04cb23-ea78-40a3-af2e-dd54798dc887",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -99,7 +97,6 @@ clusters:
|
|||||||
"name": "cluster-2-node-1",
|
"name": "cluster-2-node-1",
|
||||||
"maxcpu": 1,
|
"maxcpu": 1,
|
||||||
"maxmem": 2 * 1024 * 1024 * 1024,
|
"maxmem": 2 * 1024 * 1024 * 1024,
|
||||||
"smbios1": "uuid=3d3db687-89dd-473e-8463-6599f25b36a8",
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -110,9 +107,12 @@ clusters:
|
|||||||
func(_ *http.Request) (*http.Response, error) {
|
func(_ *http.Request) (*http.Response, error) {
|
||||||
return httpmock.NewJsonResponse(200, map[string]interface{}{
|
return httpmock.NewJsonResponse(200, map[string]interface{}{
|
||||||
"data": map[string]interface{}{
|
"data": map[string]interface{}{
|
||||||
|
"name": "cluster-1-node-1",
|
||||||
"node": "pve-1",
|
"node": "pve-1",
|
||||||
"type": "qemu",
|
"type": "qemu",
|
||||||
"vmid": 100,
|
"vmid": 100,
|
||||||
|
"cores": 4,
|
||||||
|
"memory": "10240",
|
||||||
"smbios1": "uuid=8af7110d-bfad-407a-a663-9527d10a6583",
|
"smbios1": "uuid=8af7110d-bfad-407a-a663-9527d10a6583",
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -123,9 +123,12 @@ clusters:
|
|||||||
func(_ *http.Request) (*http.Response, error) {
|
func(_ *http.Request) (*http.Response, error) {
|
||||||
return httpmock.NewJsonResponse(200, map[string]interface{}{
|
return httpmock.NewJsonResponse(200, map[string]interface{}{
|
||||||
"data": map[string]interface{}{
|
"data": map[string]interface{}{
|
||||||
|
"name": "cluster-1-node-2",
|
||||||
"node": "pve-2",
|
"node": "pve-2",
|
||||||
"type": "qemu",
|
"type": "qemu",
|
||||||
"vmid": 101,
|
"vmid": 101,
|
||||||
|
"cores": 2,
|
||||||
|
"memory": "5120",
|
||||||
"smbios1": "uuid=5d04cb23-ea78-40a3-af2e-dd54798dc887",
|
"smbios1": "uuid=5d04cb23-ea78-40a3-af2e-dd54798dc887",
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -136,10 +139,13 @@ clusters:
|
|||||||
func(_ *http.Request) (*http.Response, error) {
|
func(_ *http.Request) (*http.Response, error) {
|
||||||
return httpmock.NewJsonResponse(200, map[string]interface{}{
|
return httpmock.NewJsonResponse(200, map[string]interface{}{
|
||||||
"data": map[string]interface{}{
|
"data": map[string]interface{}{
|
||||||
|
"name": "cluster-2-node-1",
|
||||||
"node": "pve-3",
|
"node": "pve-3",
|
||||||
"type": "qemu",
|
"type": "qemu",
|
||||||
"vmid": 100,
|
"vmid": 100,
|
||||||
"smbios1": "uuid=3d3db687-89dd-473e-8463-6599f25b36a8",
|
"cores": 1,
|
||||||
|
"memory": "2048",
|
||||||
|
"smbios1": "uuid=3d3db687-89dd-473e-8463-6599f25b36a8,sku=YzEubWVkaXVt",
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@@ -237,6 +243,11 @@ func (ts *ccmTestSuite) TestInstanceExists() {
|
|||||||
Spec: v1.NodeSpec{
|
Spec: v1.NodeSpec{
|
||||||
ProviderID: "proxmox://cluster-1/100",
|
ProviderID: "proxmox://cluster-1/100",
|
||||||
},
|
},
|
||||||
|
Status: v1.NodeStatus{
|
||||||
|
NodeInfo: v1.NodeSystemInfo{
|
||||||
|
SystemUUID: "8af7110d-bfad-407a-a663-9527d10a6583",
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
expected: true,
|
expected: true,
|
||||||
},
|
},
|
||||||
@@ -255,7 +266,24 @@ func (ts *ccmTestSuite) TestInstanceExists() {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expected: true,
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
msg: "NodeExistsWithDifferentUUID",
|
||||||
|
node: &v1.Node{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "cluster-1-node-1",
|
||||||
|
},
|
||||||
|
Spec: v1.NodeSpec{
|
||||||
|
ProviderID: "proxmox://cluster-1/100",
|
||||||
|
},
|
||||||
|
Status: v1.NodeStatus{
|
||||||
|
NodeInfo: v1.NodeSystemInfo{
|
||||||
|
SystemUUID: "8af7110d-0000-0000-0000-9527d10a6583",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
msg: "NodeExistsWithDifferentNameAndUUID",
|
msg: "NodeExistsWithDifferentNameAndUUID",
|
||||||
@@ -405,6 +433,23 @@ func (ts *ccmTestSuite) TestInstanceShutdown() {
|
|||||||
},
|
},
|
||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
msg: "NodeExistsWithDifferentNameAndUUID",
|
||||||
|
node: &v1.Node{
|
||||||
|
ObjectMeta: metav1.ObjectMeta{
|
||||||
|
Name: "cluster-1-node-3",
|
||||||
|
},
|
||||||
|
Spec: v1.NodeSpec{
|
||||||
|
ProviderID: "proxmox://cluster-1/100",
|
||||||
|
},
|
||||||
|
Status: v1.NodeStatus{
|
||||||
|
NodeInfo: v1.NodeSystemInfo{
|
||||||
|
SystemUUID: "8af7110d-0000-0000-0000-9527d10a6583",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, testCase := range tests {
|
for _, testCase := range tests {
|
||||||
@@ -586,7 +631,7 @@ func (ts *ccmTestSuite) TestInstanceMetadata() {
|
|||||||
Address: "cluster-2-node-1",
|
Address: "cluster-2-node-1",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
InstanceType: "1VCPU-2GB",
|
InstanceType: "c1.medium",
|
||||||
Region: "cluster-2",
|
Region: "cluster-2",
|
||||||
Zone: "pve-3",
|
Zone: "pve-3",
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user