package app import ( "context" "crypto/tls" "fmt" "net/http" "strings" "github.com/luthermonson/go-proxmox" ) type ProxmoxClient struct { client *proxmox.Client } func NewClient(token string, secret string) ProxmoxClient { HTTPClient := http.Client{ Transport: &http.Transport{ TLSClientConfig: &tls.Config{ InsecureSkipVerify: true, }, }, } println(token, secret) client := proxmox.NewClient("https://pve.tronnet.net/api2/json", proxmox.WithHTTPClient(&HTTPClient), proxmox.WithAPIToken(token, secret), ) return ProxmoxClient{client: client} } // Gets and returns the PVE API version func (pve ProxmoxClient) Version() (proxmox.Version, error) { version, err := pve.client.Version(context.Background()) if err != nil { return *version, err } return *version, err } // Gets and returns a Node's CPU, memory, swap, and Hardware (PCI) resources func (pve ProxmoxClient) Node(nodeName string) (Host, error) { host := Host{} host.Hardware = make(map[string]Device) node, err := pve.client.Node(context.Background(), nodeName) if err != nil { return host, err } devices := []Device{} err = pve.client.Get(context.Background(), fmt.Sprintf("/nodes/%s/hardware/pci", nodeName), &devices) if err != nil { return host, err } vms, err := node.VirtualMachines(context.Background()) if err != nil { return host, err } cts, err := node.Containers(context.Background()) if err != nil { return host, err } // temporary helper which maps supersystem devices to each contained subsystem // eg 0000:00:05 -> [0000:00:05.0, 0000:00:05.1, 0000:00:05.2, 0000:00:05.3, ...] DeviceSubsystemMap := make(map[string][]string) for _, device := range devices { host.Hardware[device.BusID] = device SupersystemID := strings.Split(device.BusID, ".")[0] DeviceSubsystemMap[SupersystemID] = append(DeviceSubsystemMap[SupersystemID], device.BusID) } host.Name = node.Name host.Cores.Total = int64(node.CPUInfo.CPUs) host.Memory.Total = int64(node.Memory.Total) host.Swap.Total = int64(node.Swap.Total) for _, vm := range vms { vm, err := node.VirtualMachine(context.Background(), int(vm.VMID)) if err != nil { return host, err } host.Cores.Reserved += int64(vm.VirtualMachineConfig.Cores) host.Memory.Reserved += int64(vm.VirtualMachineConfig.Memory * MiB) MarshallVirtualMachineConfig(vm.VirtualMachineConfig) for _, v := range vm.VirtualMachineConfig.HostPCIs { HostPCIBusID := strings.Split(v, ",")[0] if device, ok := host.Hardware[HostPCIBusID]; ok { // is a specific subsystem of device device.Reserved = true host.Hardware[HostPCIBusID] = device } else if SubsystemBusIDs, ok := DeviceSubsystemMap[HostPCIBusID]; ok { // is a supersystem device containing multiple subsystems for _, SubsystemBusID := range SubsystemBusIDs { device := host.Hardware[SubsystemBusID] device.Reserved = true host.Hardware[SubsystemBusID] = device } } } } for _, ct := range cts { ct, err := node.Container(context.Background(), int(ct.VMID)) if err != nil { return host, err } host.Cores.Reserved += int64(ct.ContainerConfig.Cores) host.Memory.Reserved += int64(ct.ContainerConfig.Memory * MiB) host.Swap.Reserved += int64(ct.ContainerConfig.Swap * MiB) } host.Cores.Free = host.Cores.Total - host.Cores.Reserved host.Memory.Free = host.Memory.Total - host.Memory.Reserved host.Swap.Free = host.Swap.Total - host.Swap.Reserved return host, err }