Initial commit

This commit is contained in:
Jan Lošťák
2024-05-27 21:27:07 +02:00
commit a1ab163804
22 changed files with 2920 additions and 0 deletions

303
proxmox/pve_api_client.go Normal file
View File

@@ -0,0 +1,303 @@
package proxmox
import (
"encoding/json"
"errors"
"fmt"
"time"
"github.com/mitchellh/mapstructure"
log "github.com/sirupsen/logrus"
)
// PVE API client.
type PveApiClient struct {
apiClient *ApiClient // Instance of API client.
}
// Create new instance of PVE API client.
func NewPveApiClient(endpoints []string, tokenId string, secret string) *PveApiClient {
client := PveApiClient{}
client.apiClient = NewApiClient(endpoints, tokenId, secret, 5*time.Second)
client.apiClient.Start()
return &client
}
// Get PVE version.
func (instance *PveApiClient) GetVersion() (*PveVersion, error) {
res, err := instance.apiClient.PerformRequest("GET", "/version", nil)
if err != nil {
return nil, err
}
version := PveVersion{}
err = json.Unmarshal(res.Data, &version)
if err != nil {
return nil, err
}
return &version, nil
}
// Get PVE cluster status.
func (instance *PveApiClient) GetClusterStatus() (*PveClusterStatus, error) {
res, err := instance.apiClient.PerformRequest("GET", "/cluster/status", nil)
if err != nil {
return nil, err
}
var objects []map[string]interface{}
err = json.Unmarshal(res.Data, &objects)
if err != nil {
return nil, err
}
// If data returned is empty array then there is possible issue with permissions.
if len(objects) == 0 {
return nil, errors.New("Unable to fetch cluster status from API. Please make sure you have valid token and 'PVEAuditor' permission on token and user.")
}
var cluster PveClusterStatus
for _, obj := range objects {
switch obj["type"] {
case "cluster":
if err := mapstructure.Decode(obj, &cluster); err != nil {
log.Errorf("Unable to decode cluster status object. Error:", err)
continue
}
case "node":
var node PveNodeStatus
if err := mapstructure.Decode(obj, &node); err != nil {
log.Errorf("Unable to decode node status object. Error:", err)
continue
}
cluster.NodeStatuses = append(cluster.NodeStatuses, node)
default:
log.Errorf("Unable to decode cluster status object. Unknown type:", obj["type"])
}
}
return &cluster, nil
}
// Get PVE cluster resources.
func (instance *PveApiClient) GetClusterResources() (*PveResources, error) {
res, err := instance.apiClient.PerformRequest("GET", "/cluster/resources", nil)
if err != nil {
return nil, err
}
var objects []map[string]interface{}
err = json.Unmarshal(res.Data, &objects)
if err != nil {
return nil, err
}
// If data returned is empty array then there is possible issue with permissions.
if len(objects) == 0 {
return nil, errors.New("Unable to fetch cluster status from API. Please make sure you have valid token and 'PVEAuditor' permission on token and user.")
}
resources := PveResources{}
for _, obj := range objects {
switch obj["type"] {
case "lxc":
var resource PveLxcResource
if err := mapstructure.Decode(obj, &resource); err != nil {
log.Errorf("Unable to decode cluster resource object. Error:", err)
continue
}
if err := mapstructure.Decode(obj, &resource.PveResource); err != nil {
log.Errorf("Unable to decode cluster resource object. Error:", err)
continue
}
resources.CTs = append(resources.CTs, resource)
case "qemu":
var resource PveQemuResource
if err := mapstructure.Decode(obj, &resource); err != nil {
log.Errorf("Unable to decode cluster resource object. Error:", err)
continue
}
if err := mapstructure.Decode(obj, &resource.PveResource); err != nil {
log.Errorf("Unable to decode cluster resource object. Error:", err)
continue
}
resources.VMs = append(resources.VMs, resource)
case "node":
var resource PveNodeResource
if err := mapstructure.Decode(obj, &resource); err != nil {
log.Errorf("Unable to decode cluster resource object. Error:", err)
continue
}
if err := mapstructure.Decode(obj, &resource.PveResource); err != nil {
log.Errorf("Unable to decode cluster resource object. Error:", err)
continue
}
resources.Nodes = append(resources.Nodes, resource)
case "storage":
var resource PveStorageResource
if err := mapstructure.Decode(obj, &resource); err != nil {
log.Errorf("Unable to decode cluster resource object. Error:", err)
continue
}
if err := mapstructure.Decode(obj, &resource.PveResource); err != nil {
log.Errorf("Unable to decode cluster resource object. Error:", err)
continue
}
resources.Storages = append(resources.Storages, resource)
case "sdn":
var resource PveSdnResource
if err := mapstructure.Decode(obj, &resource); err != nil {
log.Errorf("Unable to decode cluster resource object. Error:", err)
continue
}
if err := mapstructure.Decode(obj, &resource.PveResource); err != nil {
log.Errorf("Unable to decode cluster resource object. Error:", err)
continue
}
resources.SDNs = append(resources.SDNs, resource)
default:
log.Errorf("Unable to decode cluster resource object. Unknown type:", obj["type"])
}
}
return &resources, nil
}
// Get PVE cluster node stats.
func (instance *PveApiClient) GetNodeStatusDetail(node string) (*PveNodeStatusDetail, error) {
res, err := instance.apiClient.PerformRequest("GET", "/nodes/"+node+"/status", nil)
if err != nil {
return nil, err
}
var status PveNodeStatusDetail
err = json.Unmarshal(res.Data, &status)
if err != nil {
return nil, err
}
return &status, nil
}
// Get PVE cluster node subscription info.
func (instance *PveApiClient) GetNodeSubscription(node string) (*PveSubscription, error) {
res, err := instance.apiClient.PerformRequest("GET", "/nodes/"+node+"/subscription", nil)
if err != nil {
return nil, err
}
var subscription PveSubscription
err = json.Unmarshal(res.Data, &subscription)
if err != nil {
return nil, err
}
return &subscription, nil
}
// Get PVE cluster node disks info.
func (instance *PveApiClient) GetNodeDisksList(node string) (*[]PveDisk, error) {
res, err := instance.apiClient.PerformRequest("GET", "/nodes/"+node+"/disks/list", nil)
if err != nil {
return nil, err
}
var disks []PveDisk
err = json.Unmarshal(res.Data, &disks)
if err != nil {
return nil, err
}
return &disks, nil
}
// Get PVE node time info.
func (instance *PveApiClient) GetNodeTime(node string) (*PveNodeTime, error) {
res, err := instance.apiClient.PerformRequest("GET", "/nodes/"+node+"/time", nil)
if err != nil {
return nil, err
}
var time PveNodeTime
err = json.Unmarshal(res.Data, &time)
if err != nil {
return nil, err
}
return &time, nil
}
// Get PVE node storage time info.
func (instance *PveApiClient) GetNodeStorages(node string) (*[]PveStorage, error) {
res, err := instance.apiClient.PerformRequest("GET", "/nodes/"+node+"/storage", nil)
if err != nil {
return nil, err
}
var storages []PveStorage
err = json.Unmarshal(res.Data, &storages)
if err != nil {
return nil, err
}
return &storages, nil
}
// Get PVE node LXC containers.
func (instance *PveApiClient) GetNodeContainerList(node string) (*[]PveLxcStatus, error) {
res, err := instance.apiClient.PerformRequest("GET", fmt.Sprintf("/nodes/%s/lxc/", node), nil)
if err != nil {
return nil, err
}
var status []PveLxcStatus
err = json.Unmarshal(res.Data, &status)
if err != nil {
return nil, err
}
return &status, nil
}
// Get PVE LXC container status.
func (instance *PveApiClient) GetContainerStatus(node string, vmid int) (*PveLxcStatus, error) {
res, err := instance.apiClient.PerformRequest("GET", fmt.Sprintf("/nodes/%s/lxc/%d/status/current", node, vmid), nil)
if err != nil {
return nil, err
}
var status PveLxcStatus
err = json.Unmarshal(res.Data, &status)
if err != nil {
return nil, err
}
return &status, nil
}
// Get PVE node VM list.
func (instance *PveApiClient) GetNodeQemuList(node string) (*[]PveQemuStatus, error) {
res, err := instance.apiClient.PerformRequest("GET", fmt.Sprintf("/nodes/%s/qemu/", node), nil)
if err != nil {
return nil, err
}
var status []PveQemuStatus
err = json.Unmarshal(res.Data, &status)
if err != nil {
return nil, err
}
return &status, nil
}
// Get PVE node VM detail.
func (instance *PveApiClient) GetNodeQemu(node string, vmid string) (*PveQemuStatusDetail, error) {
res, err := instance.apiClient.PerformRequest("GET", fmt.Sprintf("/nodes/%s/qemu/%s/status/current", node, vmid), nil)
if err != nil {
return nil, err
}
var status PveQemuStatusDetail
err = json.Unmarshal(res.Data, &status)
if err != nil {
return nil, err
}
return &status, nil
}