304 lines
8.3 KiB
Go
304 lines
8.3 KiB
Go
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
|
|
}
|