diff --git a/app/model.go b/app/model.go index 56515c8..7e2cafc 100644 --- a/app/model.go +++ b/app/model.go @@ -3,7 +3,6 @@ package app import ( "fmt" "log" - "strconv" "strings" ) @@ -179,6 +178,10 @@ func (host *Node) RebuildInstance(instancetype InstanceType, vmid uint) error { instance.RebuildDevice(host, deviceid) } + if instance.Type == VM { + instance.RebuildBoot() + } + return nil } @@ -192,7 +195,7 @@ func (instance *Instance) RebuildVolume(host *Node, volid string) error { voltype := AnyPrefixes(volid, VolumeTypes) volume.Type = voltype - + volume.Volume_ID = VolumeID(volid) instance.Volumes[VolumeID(volid)] = volume return nil @@ -200,17 +203,14 @@ func (instance *Instance) RebuildVolume(host *Node, volid string) error { func (instance *Instance) RebuildNet(netid string) error { net := instance.configNets[netid] - idnum, err := strconv.ParseUint(strings.TrimPrefix(netid, "net"), 10, 64) - if err != nil { - return err - } netinfo, err := GetNetInfo(net) + netinfo.Net_ID = NetID(netid) if err != nil { return nil } - instance.Nets[NetID(idnum)] = netinfo + instance.Nets[NetID(netid)] = netinfo return nil } @@ -222,23 +222,64 @@ func (instance *Instance) RebuildDevice(host *Node, deviceid string) error { } hostDeviceBusID := DeviceID(strings.Split(instanceDevice, ",")[0]) - - idbid, err := strconv.ParseUint(strings.TrimPrefix(deviceid, "hostpci"), 10, 64) - if err != nil { - return err - } - instanceDeviceBusID := InstanceDeviceID(idbid) + instanceDeviceBusID := DeviceID(deviceid) if DeviceBusIDIsSuperDevice(hostDeviceBusID) { - instance.Devices[InstanceDeviceID(instanceDeviceBusID)] = host.Devices[DeviceID(hostDeviceBusID)] - for _, function := range instance.Devices[InstanceDeviceID(instanceDeviceBusID)].Functions { + instance.Devices[DeviceID(instanceDeviceBusID)] = host.Devices[DeviceBus(hostDeviceBusID)] + for _, function := range instance.Devices[DeviceID(instanceDeviceBusID)].Functions { function.Reserved = true } } else { // sub function assignment not supported yet } - instance.Devices[InstanceDeviceID(instanceDeviceBusID)].Value = instanceDevice + instance.Devices[DeviceID(instanceDeviceBusID)].Device_ID = DeviceID(deviceid) + instance.Devices[DeviceID(instanceDeviceBusID)].Value = instanceDevice return nil } + +func (instance *Instance) RebuildBoot() { + instance.Boot = BootOrder{} + + eligibleBoot := map[string]bool{} + for k := range instance.Volumes { + eligiblePrefix := AnyPrefixes(string(k), []string{"sata", "scsi", "ide"}) + if eligiblePrefix != "" { + eligibleBoot[string(k)] = true + } + } + for k := range instance.Nets { + eligibleBoot[string(k)] = true + } + + log.Println(eligibleBoot) + + x := strings.Split(instance.configBoot, "order=") // should be a;b;c;d ... + if len(x) == 2 { + y := strings.Split(x[1], ";") + for _, bootTarget := range y { + _, isEligible := eligibleBoot[bootTarget] + if val, ok := instance.Volumes[VolumeID(bootTarget)]; ok && isEligible { // if the item is eligible and is in volumes + instance.Boot.Enabled = append(instance.Boot.Enabled, val) + eligibleBoot[bootTarget] = false + } else if val, ok := instance.Nets[NetID(bootTarget)]; ok && isEligible { // if the item is eligible and is in nets + instance.Boot.Enabled = append(instance.Boot.Enabled, val) + eligibleBoot[bootTarget] = false + } else { + log.Printf("Encountered non-eligible boot target %s in instance %s\n", bootTarget, instance.Name) + eligibleBoot[bootTarget] = false + } + } + } + + for bootTarget, isEligible := range eligibleBoot { + if val, ok := instance.Volumes[VolumeID(bootTarget)]; ok && isEligible { // if the item is eligible and is in volumes + instance.Boot.Disabled = append(instance.Boot.Disabled, val) + } else if val, ok := instance.Nets[NetID(bootTarget)]; ok && isEligible { // if the item is eligible and is in nets + instance.Boot.Disabled = append(instance.Boot.Disabled, val) + } else { + log.Printf("Encountered non-eligible boot target %s in instance %s\n", bootTarget, instance.Name) + } + } +} diff --git a/app/proxmox.go b/app/proxmox.go index 4287e97..174a64e 100644 --- a/app/proxmox.go +++ b/app/proxmox.go @@ -15,6 +15,14 @@ type ProxmoxClient struct { client *proxmox.Client } +type PVEDevice struct { // used only for requests to PVE + ID string `json:"id"` + Device_Name string `json:"device_name"` + Vendor_Name string `json:"vendor_name"` + Subsystem_Device_Name string `json:"subsystem_device_name"` + Subsystem_Vendor_Name string `json:"subsystem_vendor_name"` +} + func NewClient(url string, token string, secret string) ProxmoxClient { HTTPClient := http.Client{ Transport: &http.Transport{ @@ -59,7 +67,7 @@ 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[DeviceID]*Device) + host.Devices = make(map[DeviceBus]*Device) host.Instances = make(map[InstanceID]*Instance) node, err := pve.client.Node(context.Background(), nodeName) @@ -78,11 +86,11 @@ func (pve ProxmoxClient) Node(nodeName string) (*Node, error) { if len(x) != 2 { // this should always be true, but skip if not continue } - deviceid := DeviceID(x[0]) + deviceid := DeviceBus(x[0]) functionid := FunctionID(x[1]) if _, ok := host.Devices[deviceid]; !ok { host.Devices[deviceid] = &Device{ - Device_ID: deviceid, + Device_Bus: deviceid, Device_Name: device.Device_Name, Vendor_Name: device.Vendor_Name, Functions: make(map[FunctionID]*Function), @@ -130,6 +138,7 @@ func (host *Node) VirtualMachine(VMID uint) (*Instance, error) { instance.configHostPCIs = config.MergeHostPCIs() instance.configNets = config.MergeNets() instance.configDisks = MergeVMDisksAndUnused(config) + instance.configBoot = config.Boot instance.pveconfig = config instance.Type = VM @@ -140,7 +149,7 @@ func (host *Node) VirtualMachine(VMID uint) (*Instance, error) { instance.Memory = uint64(vm.VirtualMachineConfig.Memory) * MiB instance.Volumes = make(map[VolumeID]*Volume) instance.Nets = make(map[NetID]*Net) - instance.Devices = make(map[InstanceDeviceID]*Device) + instance.Devices = make(map[DeviceID]*Device) return &instance, nil } diff --git a/app/types.go b/app/types.go index 52d4e0c..719d778 100644 --- a/app/types.go +++ b/app/types.go @@ -18,7 +18,7 @@ type Node struct { Cores uint64 `json:"cores"` Memory uint64 `json:"memory"` Swap uint64 `json:"swap"` - Devices map[DeviceID]*Device `json:"devices"` + Devices map[DeviceBus]*Device `json:"devices"` Instances map[InstanceID]*Instance `json:"instances"` pvenode *proxmox.Node } @@ -33,19 +33,21 @@ 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[VolumeID]*Volume `json:"volumes"` - Nets map[NetID]*Net `json:"nets"` - Devices map[InstanceDeviceID]*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[DeviceID]*Device `json:"devices"` + Boot BootOrder `json:"boot"` pveconfig any configDisks map[string]string configNets map[string]string configHostPCIs map[string]string + configBoot string } var VolumeTypes = []string{ @@ -59,32 +61,27 @@ var VolumeTypes = []string{ type VolumeID string type Volume struct { - Type string `json:"type"` - Storage string `json:"storage"` - Format string `json:"format"` - Size uint64 `json:"size"` - File string `json:"file"` + Volume_ID VolumeID `json:"volume_id"` + Type string `json:"type"` + Storage string `json:"storage"` + Format string `json:"format"` + Size uint64 `json:"size"` + File string `json:"file"` } -type NetID uint64 +type NetID string type Net struct { - Value string `json:"value"` - Rate uint64 `json:"rate"` - VLAN uint64 `json:"vlan"` -} - -type PVEDevice struct { - ID string `json:"id"` - Device_Name string `json:"device_name"` - Vendor_Name string `json:"vendor_name"` - Subsystem_Device_Name string `json:"subsystem_device_name"` - Subsystem_Vendor_Name string `json:"subsystem_vendor_name"` + Net_ID NetID `json:"net_id"` + Value string `json:"value"` + Rate uint64 `json:"rate"` + VLAN uint64 `json:"vlan"` } type DeviceID string -type InstanceDeviceID uint64 +type DeviceBus string type Device struct { Device_ID DeviceID `json:"device_id"` + Device_Bus DeviceBus `json:"device_bus"` Device_Name string `json:"device_name"` Vendor_Name string `json:"vendor_name"` Functions map[FunctionID]*Function `json:"functions"` @@ -99,3 +96,8 @@ type Function struct { Vendor_Name string `json:"subsystem_vendor_name"` Reserved bool `json:"reserved"` } + +type BootOrder struct { + Enabled []any `json:"enabled"` + Disabled []any `json:"disabled"` +}