功能:扩展云管资源运维、账号授权及监控管理
这个提交包含在:
1 父节点
eef485306f
当前提交
6134d49c16
87 个文件已更改
+29498
-126
没有与搜索条件相匹配的文件
@@ -0,0 +1,78 @@
|
||||
package proxmox
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPCIAddressAndHostPCIParsing(t *testing.T) {
|
||||
for _, value := range []string{"01:00.0", "0000:01:00.0", " 0000:01:00.0 "} {
|
||||
got, ok := NormalizePCIAddress(value)
|
||||
if !ok || got != "0000:01:00.0" {
|
||||
t.Fatalf("normalization %q: %q %v", value, got, ok)
|
||||
}
|
||||
}
|
||||
for _, value := range []string{"01:20.0", "01:00.8", "../../config", "01:00.0,pcie=1", "000000:01:00.0"} {
|
||||
if _, ok := NormalizePCIAddress(value); ok {
|
||||
t.Fatalf("accepted invalid address %q", value)
|
||||
}
|
||||
}
|
||||
if !PCIAddressMatches("01:00", "0000:01:00.1") || PCIAddressMatches("01:00.0", "0000:01:00.1") || PCIAddressMatches("0001:01:00", "0000:01:00.0") {
|
||||
t.Fatal("function/domain matching incorrect")
|
||||
}
|
||||
parsed, err := ParseHostPCI("host=01:00;0001:02:00.0,pcie=1,x-vga=1")
|
||||
if err != nil || len(parsed.Addresses) != 2 || parsed.Addresses[0] != "0000:01:00" {
|
||||
t.Fatalf("parse multi-function PCI: %+v %v", parsed, err)
|
||||
}
|
||||
parsed, err = ParseHostPCI("mapping=gpu-pool,mdev=nvidia-1")
|
||||
if err != nil || parsed.Mapping != "gpu-pool" || !parsed.Mediated {
|
||||
t.Fatalf("parse mediated mapping: %+v %v", parsed, err)
|
||||
}
|
||||
for _, value := range []string{"", "mapping=x,host=01:00", "host=01:00,host=02:00", "host=invalid", "mapping=", "pcie=1"} {
|
||||
if _, err := ParseHostPCI(value); err == nil {
|
||||
t.Fatalf("accepted invalid hostpci %q", value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGPUReadOnlyPVEContract(t *testing.T) {
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != "GET" {
|
||||
t.Errorf("unexpected write: %s", r.Method)
|
||||
}
|
||||
var data any
|
||||
switch r.URL.Path {
|
||||
case "/api2/json/nodes/node-a/hardware/pci":
|
||||
if r.URL.Query().Get("verbose") != "1" {
|
||||
t.Error("missing verbose PCI properties")
|
||||
}
|
||||
data = []map[string]any{{"id": "0000:00:02.0", "class": "0x030000", "iommugroup": 0}, {"id": "0000:01:00.1", "class": "0x040300", "iommugroup": 2}}
|
||||
case "/api2/json/nodes/node-a/qemu/8000/pending":
|
||||
data = []map[string]any{{"key": "hostpci0", "value": "01:00.0", "pending": "02:00.0", "delete": 1}}
|
||||
case "/api2/json/cluster/mapping/pci":
|
||||
data = []map[string]any{{"id": "gpu-map", "map": []string{"node=node-a,path=0000:01:00.0,id=10de:1234"}}}
|
||||
default:
|
||||
t.Errorf("unexpected path: %s", r.URL.Path)
|
||||
http.NotFound(w, r)
|
||||
return
|
||||
}
|
||||
_ = json.NewEncoder(w).Encode(map[string]any{"data": data})
|
||||
}))
|
||||
defer srv.Close()
|
||||
c := &Client{BaseURL: srv.URL, HTTP: srv.Client()}
|
||||
devices, err := c.PCIDevices(context.Background(), "node-a")
|
||||
if err != nil || len(devices) != 2 || !devices[0].IsGPU() || devices[1].IsGPU() || devices[0].IOMMUGroup == nil || *devices[0].IOMMUGroup != 0 {
|
||||
t.Fatalf("PCI decode: %+v %v", devices, err)
|
||||
}
|
||||
pending, err := c.VMPending(context.Background(), "node-a", 8000)
|
||||
if err != nil || len(pending) != 1 || string(pending[0].Delete) != "1" {
|
||||
t.Fatalf("pending decode: %+v %v", pending, err)
|
||||
}
|
||||
mappings, err := c.PCIMappings(context.Background())
|
||||
if err != nil || len(mappings) != 1 || len(mappings[0].Map) != 1 {
|
||||
t.Fatalf("mapping decode: %+v %v", mappings, err)
|
||||
}
|
||||
}
|
||||
在新工单中引用
屏蔽一个用户