From e99a9c8c7985f2c5f87627652b0be793dc061750 Mon Sep 17 00:00:00 2001 From: Arthur Lu <root@tronnet.net> Date: Tue, 11 Feb 2025 07:11:05 +0000 Subject: [PATCH] improve device and function (subdevice) types --- app/model.go | 37 ++++++++++++++------------- app/proxmox.go | 41 ++++++++++++++++++++++-------- app/types.go | 69 ++++++++++++++++++++++++++++++++------------------ app/utils.go | 6 +++-- 4 files changed, 100 insertions(+), 53 deletions(-) diff --git a/app/model.go b/app/model.go index 8c4e06b..f25c617 100644 --- a/app/model.go +++ b/app/model.go @@ -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 } @@ -113,7 +122,7 @@ func (host *Node) GetInstance(vmid uint) (*Instance, error) { host.lock.Lock() defer host.lock.Unlock() // get instance - instance, ok := host.Instances[vmid] + instance, ok := host.Instances[InstanceID(vmid)] if !ok { instance_ch <- nil 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() defer instance.lock.Unlock() - host.Instances[vmid] = instance + host.Instances[InstanceID(vmid)] = instance for volid := range instance.configDisks { instance.RebuildVolume(host, volid) @@ -178,7 +187,7 @@ func (instance *Instance) RebuildVolume(host *Node, volid string) error { return err } - instance.Volumes[volid] = volume + instance.Volumes[VolumeID(volid)] = volume return nil } @@ -195,7 +204,7 @@ func (instance *Instance) RebuildNet(netid string) error { return nil } - instance.Nets[uint(idnum)] = netinfo + instance.Nets[NetID(idnum)] = netinfo return nil } @@ -206,27 +215,21 @@ func (instance *Instance) RebuildDevice(host *Node, deviceid string) error { 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 { return err } + instanceDeviceBusID := InstanceDeviceID(idbid) if DeviceBusIDIsSuperDevice(hostDeviceBusID) { - devices := []*Device{} - for k, v := range host.Devices { - if DeviceBusIDIsSubDevice(k, hostDeviceBusID) { - v.Reserved = true - devices = append(devices, v) - } + instance.Devices[InstanceDeviceID(instanceDeviceBusID)] = host.Devices[DeviceID(hostDeviceBusID)] + for _, function := range instance.Devices[InstanceDeviceID(instanceDeviceBusID)].Functions { + function.Reserved = true } - instance.Devices[uint(instanceDeviceBusID)] = devices } else { - devices := []*Device{} - v := host.Devices[hostDeviceBusID] - v.Reserved = true - instance.Devices[uint(instanceDeviceBusID)] = devices + // sub function assignment not supported yet } return nil diff --git a/app/proxmox.go b/app/proxmox.go index 3793d7c..d9cf799 100644 --- a/app/proxmox.go +++ b/app/proxmox.go @@ -59,22 +59,41 @@ func (pve ProxmoxClient) Nodes() ([]string, error) { // Gets a Node's resources but does not recursively expand instances func (pve ProxmoxClient) Node(nodeName string) (*Node, error) { host := Node{} - host.Devices = make(map[string]*Device) - host.Instances = make(map[uint]*Instance) + host.Devices = make(map[DeviceID]*Device) + host.Instances = make(map[InstanceID]*Instance) node, err := pve.client.Node(context.Background(), nodeName) if err != nil { return &host, err } - devices := []Device{} + devices := []PVEDevice{} err = pve.client.Get(context.Background(), fmt.Sprintf("/nodes/%s/hardware/pci", nodeName), &devices) if err != nil { return &host, err } 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 @@ -119,9 +138,9 @@ func (host *Node) VirtualMachine(VMID uint) (*Instance, error) { instance.Proctype = vm.VirtualMachineConfig.CPU instance.Cores = uint64(vm.VirtualMachineConfig.Cores) instance.Memory = uint64(vm.VirtualMachineConfig.Memory) * MiB - instance.Volumes = make(map[string]*Volume) - instance.Nets = make(map[uint]*Net) - instance.Devices = make(map[uint][]*Device) + instance.Volumes = make(map[VolumeID]*Volume) + instance.Nets = make(map[NetID]*Net) + instance.Devices = make(map[InstanceDeviceID]*Device) return &instance, nil } @@ -167,8 +186,8 @@ func (host *Node) Container(VMID uint) (*Instance, error) { instance.Cores = uint64(ct.ContainerConfig.Cores) instance.Memory = uint64(ct.ContainerConfig.Memory) * MiB instance.Swap = uint64(ct.ContainerConfig.Swap) * MiB - instance.Volumes = make(map[string]*Volume) - instance.Nets = make(map[uint]*Net) + instance.Volumes = make(map[VolumeID]*Volume) + instance.Nets = make(map[NetID]*Net) return &instance, nil } @@ -206,7 +225,7 @@ func GetVolumeInfo(host *Node, volume string) (*Volume, error) { volumeData.Storage = storageID volumeData.Format = c.Format 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 } diff --git a/app/types.go b/app/types.go index 1ced31f..f10b0c5 100644 --- a/app/types.go +++ b/app/types.go @@ -14,15 +14,16 @@ type Cluster struct { type Node struct { lock sync.Mutex - Name string `json:"name"` - Cores uint64 `json:"cores"` - Memory uint64 `json:"memory"` - Swap uint64 `json:"swap"` - Devices map[string]*Device `json:"devices"` - Instances map[uint]*Instance `json:"instances"` + Name string `json:"name"` + Cores uint64 `json:"cores"` + Memory uint64 `json:"memory"` + Swap uint64 `json:"swap"` + Devices map[DeviceID]*Device `json:"devices"` + Instances map[InstanceID]*Instance `json:"instances"` pvenode *proxmox.Node } +type InstanceID uint64 type InstanceType string const ( @@ -32,38 +33,58 @@ const ( type Instance struct { lock sync.Mutex - Type InstanceType `json:"type"` - Name string `json:"name"` - Proctype string `json:"cpu"` - Cores uint64 `json:"cores"` - Memory uint64 `json:"memory"` - Swap uint64 `json:"swap"` - Volumes map[string]*Volume `json:"volumes"` - Nets map[uint]*Net `json:"nets"` - Devices map[uint][]*Device `json:"devices"` + Type InstanceType `json:"type"` + Name string `json:"name"` + Proctype string `json:"cpu"` + Cores uint64 `json:"cores"` + Memory uint64 `json:"memory"` + Swap uint64 `json:"swap"` + Volumes map[VolumeID]*Volume `json:"volumes"` + Nets map[NetID]*Net `json:"nets"` + Devices map[InstanceDeviceID]*Device `json:"devices"` pveconfig interface{} configDisks map[string]string configNets map[string]string configHostPCIs map[string]string } +type VolumeID string type Volume struct { - Storage string `json:"storage"` - Format string `json:"format"` - Size uint64 `json:"size"` - Volid string `json:"volid"` + Storage string `json:"storage"` + Format string `json:"format"` + Size uint64 `json:"size"` + Volid VolumeID `json:"volid"` } +type NetID uint64 type Net struct { - Rate uint64 `json:"rate"` - VLAN uint64 `json:"vlan"` + Value string `json:"value"` + Rate uint64 `json:"rate"` + VLAN uint64 `json:"vlan"` } -type Device struct { - BusID string `json:"id"` +type PVEDevice struct { + ID string `json:"id"` DeviceName string `json:"device_name"` VendorName string `json:"vendor_name"` SubsystemDeviceName string `json:"subsystem_device_name"` SubsystemVendorName string `json:"subsystem_vendor_name"` - Reserved bool `json:"reserved"` +} + +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"` } diff --git a/app/utils.go b/app/utils.go index 7f3e552..2c4658d 100644 --- a/app/utils.go +++ b/app/utils.go @@ -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 // // returns true if BusID has format xxxx:yy -func DeviceBusIDIsSuperDevice(BusID string) bool { - return !strings.ContainsRune(BusID, '.') +func DeviceBusIDIsSuperDevice(BusID DeviceID) bool { + return !strings.ContainsRune(string(BusID), '.') } // 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 // // returns true if BusID has prefix SuperDeviceBusID and SuperDeviceBusID is a Super Device +/* func DeviceBusIDIsSubDevice(BusID string, SuperDeviceBusID string) bool { return DeviceBusIDIsSuperDevice(SuperDeviceBusID) && strings.HasPrefix(BusID, SuperDeviceBusID) } +*/