功能:扩展云管资源运维、账号授权及监控管理
This commit is contained in:
1 parent
eef485306f
commit
6134d49c16
87 files changed
+29498
-126
No files matched your search
@@ -0,0 +1,128 @@
|
||||
package proxmox
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type PCIDevice struct {
|
||||
ID string `json:"id"`
|
||||
Class string `json:"class"`
|
||||
Vendor string `json:"vendor"`
|
||||
VendorName string `json:"vendor_name"`
|
||||
Device string `json:"device"`
|
||||
DeviceName string `json:"device_name"`
|
||||
IOMMUGroup *int `json:"iommugroup"`
|
||||
}
|
||||
|
||||
type PCIMapping struct {
|
||||
ID string `json:"id"`
|
||||
Map []string `json:"map"`
|
||||
}
|
||||
|
||||
type PendingOption struct {
|
||||
Key string `json:"key"`
|
||||
Value json.RawMessage `json:"value"`
|
||||
Pending json.RawMessage `json:"pending"`
|
||||
Delete json.RawMessage `json:"delete"`
|
||||
}
|
||||
|
||||
func (c *Client) PCIDevices(ctx context.Context, node string) ([]PCIDevice, error) {
|
||||
var items []PCIDevice
|
||||
err := c.request(ctx, "GET", "/nodes/"+url.PathEscape(node)+"/hardware/pci?verbose=1", nil, &items)
|
||||
return items, err
|
||||
}
|
||||
|
||||
func (c *Client) PCIMappings(ctx context.Context) ([]PCIMapping, error) {
|
||||
var items []PCIMapping
|
||||
err := c.request(ctx, "GET", "/cluster/mapping/pci", nil, &items)
|
||||
return items, err
|
||||
}
|
||||
|
||||
func (c *Client) VMPending(ctx context.Context, node string, vmid int) ([]PendingOption, error) {
|
||||
var items []PendingOption
|
||||
err := c.request(ctx, "GET", fmt.Sprintf("/nodes/%s/qemu/%d/pending", url.PathEscape(node), vmid), nil, &items)
|
||||
return items, err
|
||||
}
|
||||
|
||||
var pciAddressPattern = regexp.MustCompile(`^(?:[0-9a-f]{4}:)?[0-9a-f]{2}:[0-1][0-9a-f](?:\.[0-7])?$`)
|
||||
var hostPCIKeyPattern = regexp.MustCompile(`^hostpci[0-9]+$`)
|
||||
|
||||
// A functionless address selects every function in that PCI slot.
|
||||
func NormalizePCIAddress(value string) (string, bool) {
|
||||
value = strings.ToLower(strings.TrimSpace(value))
|
||||
if !pciAddressPattern.MatchString(value) {
|
||||
return "", false
|
||||
}
|
||||
if strings.Count(value, ":") == 1 {
|
||||
value = "0000:" + value
|
||||
}
|
||||
return value, true
|
||||
}
|
||||
|
||||
func PCIAddressMatches(selector, address string) bool {
|
||||
selector, ok := NormalizePCIAddress(selector)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
address, ok = NormalizePCIAddress(address)
|
||||
return ok && (selector == address || !strings.Contains(selector, ".") && strings.HasPrefix(address, selector+"."))
|
||||
}
|
||||
|
||||
func (d PCIDevice) IsGPU() bool {
|
||||
class := strings.TrimPrefix(strings.ToLower(d.Class), "0x")
|
||||
return len(class) == 6 && strings.HasPrefix(class, "03")
|
||||
}
|
||||
|
||||
type HostPCI struct {
|
||||
Addresses []string
|
||||
Mapping string
|
||||
Mediated bool
|
||||
}
|
||||
|
||||
func IsHostPCIKey(key string) bool { return hostPCIKeyPattern.MatchString(key) }
|
||||
|
||||
func PCIProperties(value string) (map[string]string, error) {
|
||||
properties := map[string]string{}
|
||||
for i, part := range strings.Split(value, ",") {
|
||||
key, val, found := strings.Cut(strings.TrimSpace(part), "=")
|
||||
if !found && i == 0 {
|
||||
key, val = "host", key
|
||||
} else if !found {
|
||||
return nil, errors.New("invalid PCI property")
|
||||
}
|
||||
if _, duplicate := properties[key]; key == "" || val == "" || duplicate {
|
||||
return nil, errors.New("invalid PCI property")
|
||||
}
|
||||
properties[key] = val
|
||||
}
|
||||
return properties, nil
|
||||
}
|
||||
|
||||
func ParseHostPCI(value string) (HostPCI, error) {
|
||||
var out HostPCI
|
||||
properties, err := PCIProperties(value)
|
||||
if err != nil {
|
||||
return out, err
|
||||
}
|
||||
out.Mapping = properties["mapping"]
|
||||
out.Mediated = properties["mdev"] != ""
|
||||
if (properties["host"] == "") == (out.Mapping == "") {
|
||||
return out, errors.New("expected a host or mapping")
|
||||
}
|
||||
if properties["host"] != "" {
|
||||
for _, address := range strings.Split(properties["host"], ";") {
|
||||
normalized, ok := NormalizePCIAddress(address)
|
||||
if !ok {
|
||||
return out, errors.New("invalid PCI address")
|
||||
}
|
||||
out.Addresses = append(out.Addresses, normalized)
|
||||
}
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
Reference in new issue
Block a user