improve device and function (subdevice) types

This commit is contained in:
Arthur Lu 2025-02-11 07:11:05 +00:00
parent bf5196763d
commit e99a9c8c79
4 changed files with 100 additions and 53 deletions

@ -101,6 +101,15 @@ func (cluster *Cluster) RebuildHost(hostName string) error {
} }
} }
// check node device reserved by iterating over each function, we will assume that a single reserved function means the device is also reserved
for _, device := range host.Devices {
reserved := false
for _, function := range device.Functions {
reserved = reserved || function.Reserved
}
device.Reserved = reserved
}
return nil return nil
} }
@ -113,7 +122,7 @@ func (host *Node) GetInstance(vmid uint) (*Instance, error) {
host.lock.Lock() host.lock.Lock()
defer host.lock.Unlock() defer host.lock.Unlock()
// get instance // get instance
instance, ok := host.Instances[vmid] instance, ok := host.Instances[InstanceID(vmid)]
if !ok { if !ok {
instance_ch <- nil instance_ch <- nil
err_ch <- fmt.Errorf("vmid %d not in host %s", vmid, host.Name) err_ch <- fmt.Errorf("vmid %d not in host %s", vmid, host.Name)
@ -153,7 +162,7 @@ func (host *Node) RebuildInstance(instancetype InstanceType, vmid uint) error {
instance.lock.Lock() instance.lock.Lock()
defer instance.lock.Unlock() defer instance.lock.Unlock()
host.Instances[vmid] = instance host.Instances[InstanceID(vmid)] = instance
for volid := range instance.configDisks { for volid := range instance.configDisks {
instance.RebuildVolume(host, volid) instance.RebuildVolume(host, volid)
@ -178,7 +187,7 @@ func (instance *Instance) RebuildVolume(host *Node, volid string) error {
return err return err
} }
instance.Volumes[volid] = volume instance.Volumes[VolumeID(volid)] = volume
return nil return nil
} }
@ -195,7 +204,7 @@ func (instance *Instance) RebuildNet(netid string) error {
return nil return nil
} }
instance.Nets[uint(idnum)] = netinfo instance.Nets[NetID(idnum)] = netinfo
return nil return nil
} }
@ -206,27 +215,21 @@ func (instance *Instance) RebuildDevice(host *Node, deviceid string) error {
return fmt.Errorf("%s not found in devices", deviceid) return fmt.Errorf("%s not found in devices", deviceid)
} }
hostDeviceBusID := strings.Split(instanceDevice, ",")[0] hostDeviceBusID := DeviceID(strings.Split(instanceDevice, ",")[0])
instanceDeviceBusID, err := strconv.ParseUint(strings.TrimPrefix(deviceid, "hostpci"), 10, 64) idbid, err := strconv.ParseUint(strings.TrimPrefix(deviceid, "hostpci"), 10, 64)
if err != nil { if err != nil {
return err return err
} }
instanceDeviceBusID := InstanceDeviceID(idbid)
if DeviceBusIDIsSuperDevice(hostDeviceBusID) { if DeviceBusIDIsSuperDevice(hostDeviceBusID) {
devices := []*Device{} instance.Devices[InstanceDeviceID(instanceDeviceBusID)] = host.Devices[DeviceID(hostDeviceBusID)]
for k, v := range host.Devices { for _, function := range instance.Devices[InstanceDeviceID(instanceDeviceBusID)].Functions {
if DeviceBusIDIsSubDevice(k, hostDeviceBusID) { function.Reserved = true
v.Reserved = true
devices = append(devices, v)
} }
}
instance.Devices[uint(instanceDeviceBusID)] = devices
} else { } else {
devices := []*Device{} // sub function assignment not supported yet
v := host.Devices[hostDeviceBusID]
v.Reserved = true
instance.Devices[uint(instanceDeviceBusID)] = devices
} }
return nil return nil

@ -59,22 +59,41 @@ func (pve ProxmoxClient) Nodes() ([]string, error) {
// Gets a Node's resources but does not recursively expand instances // Gets a Node's resources but does not recursively expand instances
func (pve ProxmoxClient) Node(nodeName string) (*Node, error) { func (pve ProxmoxClient) Node(nodeName string) (*Node, error) {
host := Node{} host := Node{}
host.Devices = make(map[string]*Device) host.Devices = make(map[DeviceID]*Device)
host.Instances = make(map[uint]*Instance) host.Instances = make(map[InstanceID]*Instance)
node, err := pve.client.Node(context.Background(), nodeName) node, err := pve.client.Node(context.Background(), nodeName)
if err != nil { if err != nil {
return &host, err return &host, err
} }
devices := []Device{} devices := []PVEDevice{}
err = pve.client.Get(context.Background(), fmt.Sprintf("/nodes/%s/hardware/pci", nodeName), &devices) err = pve.client.Get(context.Background(), fmt.Sprintf("/nodes/%s/hardware/pci", nodeName), &devices)
if err != nil { if err != nil {
return &host, err return &host, err
} }
for _, device := range devices { for _, device := range devices {
host.Devices[device.BusID] = &device x := strings.Split(device.ID, ".")
if len(x) != 2 { // this should always be true, but skip if not
continue
}
deviceid := DeviceID(x[0])
functionid := FunctionID(x[1])
if _, ok := host.Devices[deviceid]; !ok {
host.Devices[deviceid] = &Device{
DeviceID: deviceid,
DeviceName: device.DeviceName,
VendorName: device.VendorName,
Functions: make(map[FunctionID]*Function),
}
}
host.Devices[deviceid].Functions[functionid] = &Function{
FunctionID: functionid,
FunctionName: device.SubsystemDeviceName,
VendorName: device.SubsystemVendorName,
Reserved: false,
}
} }
host.Name = node.Name host.Name = node.Name
@ -119,9 +138,9 @@ func (host *Node) VirtualMachine(VMID uint) (*Instance, error) {
instance.Proctype = vm.VirtualMachineConfig.CPU instance.Proctype = vm.VirtualMachineConfig.CPU
instance.Cores = uint64(vm.VirtualMachineConfig.Cores) instance.Cores = uint64(vm.VirtualMachineConfig.Cores)
instance.Memory = uint64(vm.VirtualMachineConfig.Memory) * MiB instance.Memory = uint64(vm.VirtualMachineConfig.Memory) * MiB
instance.Volumes = make(map[string]*Volume) instance.Volumes = make(map[VolumeID]*Volume)
instance.Nets = make(map[uint]*Net) instance.Nets = make(map[NetID]*Net)
instance.Devices = make(map[uint][]*Device) instance.Devices = make(map[InstanceDeviceID]*Device)
return &instance, nil return &instance, nil
} }
@ -167,8 +186,8 @@ func (host *Node) Container(VMID uint) (*Instance, error) {
instance.Cores = uint64(ct.ContainerConfig.Cores) instance.Cores = uint64(ct.ContainerConfig.Cores)
instance.Memory = uint64(ct.ContainerConfig.Memory) * MiB instance.Memory = uint64(ct.ContainerConfig.Memory) * MiB
instance.Swap = uint64(ct.ContainerConfig.Swap) * MiB instance.Swap = uint64(ct.ContainerConfig.Swap) * MiB
instance.Volumes = make(map[string]*Volume) instance.Volumes = make(map[VolumeID]*Volume)
instance.Nets = make(map[uint]*Net) instance.Nets = make(map[NetID]*Net)
return &instance, nil return &instance, nil
} }
@ -206,7 +225,7 @@ func GetVolumeInfo(host *Node, volume string) (*Volume, error) {
volumeData.Storage = storageID volumeData.Storage = storageID
volumeData.Format = c.Format volumeData.Format = c.Format
volumeData.Size = uint64(c.Size) volumeData.Size = uint64(c.Size)
volumeData.Volid = volumeID volumeData.Volid = VolumeID(volumeID)
} }
} }
@ -232,5 +251,7 @@ func GetNetInfo(net string) (*Net, error) {
} }
} }
n.Value = net
return &n, nil return &n, nil
} }

@ -18,11 +18,12 @@ type Node struct {
Cores uint64 `json:"cores"` Cores uint64 `json:"cores"`
Memory uint64 `json:"memory"` Memory uint64 `json:"memory"`
Swap uint64 `json:"swap"` Swap uint64 `json:"swap"`
Devices map[string]*Device `json:"devices"` Devices map[DeviceID]*Device `json:"devices"`
Instances map[uint]*Instance `json:"instances"` Instances map[InstanceID]*Instance `json:"instances"`
pvenode *proxmox.Node pvenode *proxmox.Node
} }
type InstanceID uint64
type InstanceType string type InstanceType string
const ( const (
@ -38,32 +39,52 @@ type Instance struct {
Cores uint64 `json:"cores"` Cores uint64 `json:"cores"`
Memory uint64 `json:"memory"` Memory uint64 `json:"memory"`
Swap uint64 `json:"swap"` Swap uint64 `json:"swap"`
Volumes map[string]*Volume `json:"volumes"` Volumes map[VolumeID]*Volume `json:"volumes"`
Nets map[uint]*Net `json:"nets"` Nets map[NetID]*Net `json:"nets"`
Devices map[uint][]*Device `json:"devices"` Devices map[InstanceDeviceID]*Device `json:"devices"`
pveconfig interface{} pveconfig interface{}
configDisks map[string]string configDisks map[string]string
configNets map[string]string configNets map[string]string
configHostPCIs map[string]string configHostPCIs map[string]string
} }
type VolumeID string
type Volume struct { type Volume struct {
Storage string `json:"storage"` Storage string `json:"storage"`
Format string `json:"format"` Format string `json:"format"`
Size uint64 `json:"size"` Size uint64 `json:"size"`
Volid string `json:"volid"` Volid VolumeID `json:"volid"`
} }
type NetID uint64
type Net struct { type Net struct {
Value string `json:"value"`
Rate uint64 `json:"rate"` Rate uint64 `json:"rate"`
VLAN uint64 `json:"vlan"` VLAN uint64 `json:"vlan"`
} }
type Device struct { type PVEDevice struct {
BusID string `json:"id"` ID string `json:"id"`
DeviceName string `json:"device_name"` DeviceName string `json:"device_name"`
VendorName string `json:"vendor_name"` VendorName string `json:"vendor_name"`
SubsystemDeviceName string `json:"subsystem_device_name"` SubsystemDeviceName string `json:"subsystem_device_name"`
SubsystemVendorName string `json:"subsystem_vendor_name"` SubsystemVendorName string `json:"subsystem_vendor_name"`
}
type DeviceID string
type InstanceDeviceID uint64
type Device struct {
DeviceID DeviceID `json:"device_id"`
DeviceName string `json:"device_name"`
VendorName string `json:"vendor_name"`
Functions map[FunctionID]*Function `json:"functions"`
Reserved bool `json:"reserved"`
}
type FunctionID string
type Function struct {
FunctionID FunctionID `json:"function_id"`
FunctionName string `json:"subsystem_device_name"`
VendorName string `json:"subsystem_vendor_name"`
Reserved bool `json:"reserved"` Reserved bool `json:"reserved"`
} }

@ -41,8 +41,8 @@ func GetConfig(configPath string) Config {
// subsystem devices always has the format xxxx:yy.z, whereas super devices have the format xxxx:yy // subsystem devices always has the format xxxx:yy.z, whereas super devices have the format xxxx:yy
// //
// returns true if BusID has format xxxx:yy // returns true if BusID has format xxxx:yy
func DeviceBusIDIsSuperDevice(BusID string) bool { func DeviceBusIDIsSuperDevice(BusID DeviceID) bool {
return !strings.ContainsRune(BusID, '.') return !strings.ContainsRune(string(BusID), '.')
} }
// returns if a device pcie bus id is a subdevice of specified super device // returns if a device pcie bus id is a subdevice of specified super device
@ -50,6 +50,8 @@ func DeviceBusIDIsSuperDevice(BusID string) bool {
// subsystem devices always has the format xxxx:yy.z, whereas super devices have the format xxxx:yy // subsystem devices always has the format xxxx:yy.z, whereas super devices have the format xxxx:yy
// //
// returns true if BusID has prefix SuperDeviceBusID and SuperDeviceBusID is a Super Device // returns true if BusID has prefix SuperDeviceBusID and SuperDeviceBusID is a Super Device
/*
func DeviceBusIDIsSubDevice(BusID string, SuperDeviceBusID string) bool { func DeviceBusIDIsSubDevice(BusID string, SuperDeviceBusID string) bool {
return DeviceBusIDIsSuperDevice(SuperDeviceBusID) && strings.HasPrefix(BusID, SuperDeviceBusID) return DeviceBusIDIsSuperDevice(SuperDeviceBusID) && strings.HasPrefix(BusID, SuperDeviceBusID)
} }
*/