migrate data gathering to libvirtxml parsing
- instead of getting all the data the hard way, use libvirtxml to parse the XML from libvirt - this makes it more accurate, and more future proof when schema changes occur - add pcidb to query devices better
This commit is contained in:
parent
48bdc94351
commit
de93204e3d
19
cluster/lock/lock.go
Normal file
19
cluster/lock/lock.go
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
// Package lock implements a locking mechanism on shared resources to ensure
|
||||||
|
// they don't get used at the same time. There needs to be a lock for the following:
|
||||||
|
// - VM on Host: A VM must only exist on one host at a time
|
||||||
|
// - Storage attached to VM: Block storage can only be attached to one VM at a time
|
||||||
|
package lock
|
||||||
|
|
||||||
|
// Locker interface used to lock and unlock Lockable resources
|
||||||
|
type Locker interface {
|
||||||
|
Lock(Lockable) error
|
||||||
|
Unlock(Lockable) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lockable interface must be attached to lockable resources, such as
|
||||||
|
// Virtual Machines, block devices, and host devices that can be attached
|
||||||
|
// to virtual machines.
|
||||||
|
type Lockable interface {
|
||||||
|
Locked() bool
|
||||||
|
HeldBy() Locker
|
||||||
|
}
|
1
cluster/lock/volume.go
Normal file
1
cluster/lock/volume.go
Normal file
@ -0,0 +1 @@
|
|||||||
|
package lock
|
244
cluster/stats.go
244
cluster/stats.go
@ -1,96 +1,168 @@
|
|||||||
package cluster
|
package cluster
|
||||||
|
|
||||||
// ClusterStats is used to gather stats for the entire cluster
|
// ClusterStats is used to gather stats for the entire cluster
|
||||||
|
// Combined with StatsDiff, we can get some basic cluster wide stats tracking
|
||||||
type ClusterStats struct {
|
type ClusterStats struct {
|
||||||
CPU struct {
|
// CPU Statistics including number of CPUs
|
||||||
Sockets uint32
|
CPU CPUStats
|
||||||
Cores uint32
|
// Memory provides information about the amount of memory, including free and
|
||||||
Threads uint32
|
// allocated memory
|
||||||
Allocated uint32
|
Memory MemoryStats
|
||||||
}
|
// Storage provides information about storage pools, Only get's stats for active
|
||||||
Memory struct {
|
// pools, and will not activate pools that are not already active.
|
||||||
Total uint64
|
// Trys to sort out shared file systems from local filesystems using the Type parameter
|
||||||
Free uint64
|
// of Host.StoragePoolInfo
|
||||||
Buffers uint64
|
Storage StorageStats
|
||||||
Cached uint64
|
// Volume provides information on allocated volumes used in the cluster
|
||||||
Allocated uint64
|
Volume VolumeStats
|
||||||
}
|
// VM provides VM specific counters for the cluster
|
||||||
Storage struct {
|
VM VMStats
|
||||||
Total uint64
|
// Host provides Host information for the cluster
|
||||||
Used uint64
|
Host HostStats
|
||||||
Free uint64
|
// Network provices available networks, and how many are shared between hosts
|
||||||
Active uint32
|
Network NetworkStats
|
||||||
Inactive uint32
|
// NetIF provides information about Libvirt allocated networks, usable by the
|
||||||
Pools uint32
|
// libvirt cluster
|
||||||
|
NetIF NetIFStats
|
||||||
Volumes struct {
|
|
||||||
Total uint32
|
|
||||||
Active uint32
|
|
||||||
Inactive uint32
|
|
||||||
}
|
|
||||||
}
|
|
||||||
VM struct {
|
|
||||||
Count uint32
|
|
||||||
Started uint32
|
|
||||||
Stopped uint32
|
|
||||||
}
|
|
||||||
Host struct {
|
|
||||||
Count uint32
|
|
||||||
Available uint32
|
|
||||||
}
|
|
||||||
Network struct {
|
|
||||||
Count uint32
|
|
||||||
Active uint32
|
|
||||||
Inactive uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
old *ClusterStats
|
old *ClusterStats
|
||||||
c *Cluster
|
c *Cluster
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CPUStats provides information about the number of CPUs, Cores,
|
||||||
|
// Threads, and Speed available to the cluster.
|
||||||
|
type CPUStats struct {
|
||||||
|
Sockets uint32
|
||||||
|
Cores uint32
|
||||||
|
Threads uint32
|
||||||
|
Allocated uint32
|
||||||
|
MHz uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// MemoryStats provies information about the amount of memory, including free and
|
||||||
|
// allocated memory. Allocated is the total allocated to Guests
|
||||||
|
type MemoryStats struct {
|
||||||
|
Total uint64
|
||||||
|
Free uint64
|
||||||
|
Buffers uint64
|
||||||
|
Cached uint64
|
||||||
|
Allocated uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
// StorageStats provides information about the available storage pools in the cluster,
|
||||||
|
// including the amount of space available, allocated, and how many pools are shared
|
||||||
|
// between hosts
|
||||||
|
type StorageStats struct {
|
||||||
|
Total uint64
|
||||||
|
Used uint64
|
||||||
|
Free uint64
|
||||||
|
Active uint32
|
||||||
|
Inactive uint32
|
||||||
|
Pools uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// VolumeStats provides information about the number of volumes on the cluster.
|
||||||
|
// Counts volumes in shared storage (as detmermined by StorageStats) only once
|
||||||
|
type VolumeStats struct {
|
||||||
|
Total uint32
|
||||||
|
Active uint32
|
||||||
|
Inactive uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// VMStats provides information about the defined Virtual Machines on the cluster
|
||||||
|
type VMStats struct {
|
||||||
|
Count uint32
|
||||||
|
Started uint32
|
||||||
|
Stopped uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// HostStats provides informatoin about the number of hosts defined, and how many
|
||||||
|
// are currently available. An unavailable host will not have it's statistics counted
|
||||||
|
type HostStats struct {
|
||||||
|
Count uint32
|
||||||
|
Available uint32
|
||||||
|
Nodes uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetworkStats provides informatoin about the available Host network connections,
|
||||||
|
// including bridges and ethernet devices.
|
||||||
|
type NetworkStats struct {
|
||||||
|
Count uint32
|
||||||
|
Active uint32
|
||||||
|
Inactive uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// NetIFStats provides information about Libvirt defined networks
|
||||||
|
type NetIFStats struct {
|
||||||
|
Count uint32
|
||||||
|
Common uint32
|
||||||
|
Active uint32
|
||||||
|
Inactive uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// DeviceStats provides information about the number of allocatable devices in the
|
||||||
|
// cluster. These are PCI and USB devices.
|
||||||
|
type DeviceStats struct {
|
||||||
|
Count uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
// SecretStats provides the number of secrets defined throughout the cluster.
|
||||||
|
// Shared secrets are only counted once, and are recognized by their UUID
|
||||||
|
type SecretStats struct {
|
||||||
|
Count uint32
|
||||||
|
Shared uint32
|
||||||
|
}
|
||||||
|
|
||||||
// ClusterStats is used to gather stats for the entire cluster
|
// ClusterStats is used to gather stats for the entire cluster
|
||||||
type StatDiff struct {
|
type StatDiff struct {
|
||||||
CPU struct {
|
CPU CPUDiff
|
||||||
Sockets int
|
Memory MemoryDiff
|
||||||
Cores int
|
Storage StorageStats
|
||||||
Threads int
|
Volume VolumeDiff
|
||||||
Allocated int
|
VM VMDiff
|
||||||
}
|
Host HostDiff
|
||||||
Memory struct {
|
Network NetworkDiff
|
||||||
Total int
|
}
|
||||||
Free int
|
|
||||||
Buffers int
|
|
||||||
Cached int
|
|
||||||
Allocated int
|
|
||||||
}
|
|
||||||
Storage struct {
|
|
||||||
Total int
|
|
||||||
Used int
|
|
||||||
Free int
|
|
||||||
Active int
|
|
||||||
Inactive int
|
|
||||||
Pools int
|
|
||||||
|
|
||||||
Volumes struct {
|
type CPUDiff struct {
|
||||||
Total int
|
Sockets int
|
||||||
Active int
|
Cores int
|
||||||
Inactive int
|
Threads int
|
||||||
}
|
Allocated int
|
||||||
}
|
}
|
||||||
VM struct {
|
type MemoryDiff struct {
|
||||||
Count int
|
Total int64
|
||||||
Started int
|
Free int64
|
||||||
Stopped int
|
Buffers int64
|
||||||
}
|
Cached int64
|
||||||
Host struct {
|
Allocated int64
|
||||||
Count int
|
}
|
||||||
Available int
|
type StorageDiff struct {
|
||||||
}
|
Total int64
|
||||||
Network struct {
|
Used int64
|
||||||
Count int
|
Free int64
|
||||||
Active int
|
Active int64
|
||||||
Inactive int
|
Inactive int64
|
||||||
}
|
Pools int
|
||||||
|
}
|
||||||
|
type VolumeDiff struct {
|
||||||
|
Total int
|
||||||
|
Active int
|
||||||
|
Inactive int
|
||||||
|
}
|
||||||
|
type VMDiff struct {
|
||||||
|
Count int
|
||||||
|
Started int
|
||||||
|
Stopped int
|
||||||
|
}
|
||||||
|
type HostDiff struct {
|
||||||
|
Count int
|
||||||
|
Available int
|
||||||
|
}
|
||||||
|
type NetworkDiff struct {
|
||||||
|
Count int
|
||||||
|
Active int
|
||||||
|
Inactive int
|
||||||
}
|
}
|
||||||
|
|
||||||
// InitStats is given a cluster, which it then uses to load the initial statistics
|
// InitStats is given a cluster, which it then uses to load the initial statistics
|
||||||
@ -144,9 +216,9 @@ func (cs *ClusterStats) Update() {
|
|||||||
cs.Storage.Used += sp.Allocation
|
cs.Storage.Used += sp.Allocation
|
||||||
cs.Storage.Free += sp.Capacity - sp.Allocation
|
cs.Storage.Free += sp.Capacity - sp.Allocation
|
||||||
// Volumes in the pool
|
// Volumes in the pool
|
||||||
cs.Storage.Volumes.Total += uint32(len(sp.Volumes))
|
cs.Volume.Total += uint32(len(sp.Volumes))
|
||||||
for range sp.Volumes {
|
for range sp.Volumes {
|
||||||
cs.Storage.Volumes.Active++
|
cs.Volume.Active++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -225,9 +297,9 @@ func (cs *ClusterStats) Diff() StatDiff {
|
|||||||
Active int
|
Active int
|
||||||
Inactive int
|
Inactive int
|
||||||
}{
|
}{
|
||||||
Total: int(cs.old.Storage.Volumes.Total - cs.Storage.Volumes.Total),
|
Total: int(cs.old.Volume.Total - cs.Volume.Total),
|
||||||
Active: int(cs.old.Storage.Volumes.Active - cs.Storage.Volumes.Active),
|
Active: int(cs.old.Volume.Active - cs.Volume.Active),
|
||||||
Inactive: int(cs.old.Storage.Volumes.Inactive - cs.Storage.Volumes.Inactive),
|
Inactive: int(cs.old.Volume.Inactive - cs.Volume.Inactive),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
VM: struct {
|
VM: struct {
|
||||||
|
2
go.mod
2
go.mod
@ -14,5 +14,7 @@ require (
|
|||||||
require (
|
require (
|
||||||
github.com/blend/go-sdk v1.20220411.3 // indirect
|
github.com/blend/go-sdk v1.20220411.3 // indirect
|
||||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
|
||||||
|
github.com/jaypipes/pcidb v1.0.0 // indirect
|
||||||
|
github.com/mitchellh/go-homedir v1.0.0 // indirect
|
||||||
golang.org/x/image v0.11.0 // indirect
|
golang.org/x/image v0.11.0 // indirect
|
||||||
)
|
)
|
||||||
|
4
go.sum
4
go.sum
@ -8,6 +8,10 @@ github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF0
|
|||||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
|
||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
|
github.com/jaypipes/pcidb v1.0.0 h1:vtZIfkiCUE42oYbJS0TAq9XSfSmcsgo9IdxSm9qzYU8=
|
||||||
|
github.com/jaypipes/pcidb v1.0.0/go.mod h1:TnYUvqhPBzCKnH34KrIX22kAeEbDCSRJ9cqLRCuNDfk=
|
||||||
|
github.com/mitchellh/go-homedir v1.0.0 h1:vKb8ShqSby24Yrqr/yDYkuFz8d0WUjys40rvnGC8aR0=
|
||||||
|
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||||
github.com/wcharczuk/go-chart/v2 v2.1.1 h1:2u7na789qiD5WzccZsFz4MJWOJP72G+2kUuJoSNqWnE=
|
github.com/wcharczuk/go-chart/v2 v2.1.1 h1:2u7na789qiD5WzccZsFz4MJWOJP72G+2kUuJoSNqWnE=
|
||||||
github.com/wcharczuk/go-chart/v2 v2.1.1/go.mod h1:CyCAUt2oqvfhCl6Q5ZvAZwItgpQKZOkCJGb+VGv6l14=
|
github.com/wcharczuk/go-chart/v2 v2.1.1/go.mod h1:CyCAUt2oqvfhCl6Q5ZvAZwItgpQKZOkCJGb+VGv6l14=
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
|
208
lib/host/lib.go
208
lib/host/lib.go
@ -14,7 +14,6 @@ import (
|
|||||||
"git.staur.ca/stobbsm/clustvirt/lib/secret"
|
"git.staur.ca/stobbsm/clustvirt/lib/secret"
|
||||||
"git.staur.ca/stobbsm/clustvirt/lib/storagepool"
|
"git.staur.ca/stobbsm/clustvirt/lib/storagepool"
|
||||||
"git.staur.ca/stobbsm/clustvirt/lib/storagevol"
|
"git.staur.ca/stobbsm/clustvirt/lib/storagevol"
|
||||||
"git.staur.ca/stobbsm/clustvirt/util"
|
|
||||||
"libvirt.org/go/libvirt"
|
"libvirt.org/go/libvirt"
|
||||||
"libvirt.org/go/libvirtxml"
|
"libvirt.org/go/libvirtxml"
|
||||||
)
|
)
|
||||||
@ -27,20 +26,8 @@ type Host struct {
|
|||||||
HostName string
|
HostName string
|
||||||
// SystemHostName is the hostname as reported by the system itself
|
// SystemHostName is the hostname as reported by the system itself
|
||||||
SystemHostName string
|
SystemHostName string
|
||||||
// FreeMemory is the available free memory
|
|
||||||
FreeMemory uint64
|
|
||||||
// LibVersion is the version of Libvirt on the host
|
// LibVersion is the version of Libvirt on the host
|
||||||
LibVersion uint32
|
LibVersion uint32
|
||||||
// HostInfo provides basic HW information about a host
|
|
||||||
HostInfo NodeInfo
|
|
||||||
// HostSEVInfo provides informatoin about AMD SEV extentions available on the host
|
|
||||||
HostSEVInfo SEVInfo
|
|
||||||
// AvailableCPUTypes are the available types of CPUs that can be used for VM creation
|
|
||||||
AvailableCPUTypes []string
|
|
||||||
// NodeMemory provides basic memory information about the Host
|
|
||||||
NodeMemory NodeMemoryInfo
|
|
||||||
// StorageCapabilities is the XML representation of the hosts storage capabilities
|
|
||||||
StorageCapabilities string
|
|
||||||
// SysInfo is the XML representation of the host system information
|
// SysInfo is the XML representation of the host system information
|
||||||
SysInfo string
|
SysInfo string
|
||||||
// Alive indicates if the connection is alive
|
// Alive indicates if the connection is alive
|
||||||
@ -49,18 +36,24 @@ type Host struct {
|
|||||||
Encrypted bool
|
Encrypted bool
|
||||||
// Secure indicates if the connection is secure
|
// Secure indicates if the connection is secure
|
||||||
Secure bool
|
Secure bool
|
||||||
|
// HostInfo provides basic HW information about a host
|
||||||
|
HostInfo libvirtxml.CapsHost
|
||||||
|
// NodeMemory provides basic memory information about the Host
|
||||||
|
NodeMemory NodeMemoryInfo
|
||||||
// VMList is the list of virtual machines available to the host
|
// VMList is the list of virtual machines available to the host
|
||||||
VMList []VMInfo
|
VMList []libvirtxml.Domain
|
||||||
// NetIfList is the list of network interfaces on the host
|
// NetIfList is the list of network interfaces on the host
|
||||||
NetIfFList []NetIfInfo
|
NetIfFList []libvirtxml.Interface
|
||||||
// NetworkList is the list of defined networks on the host
|
// NetworkList is the list of defined networks on the host
|
||||||
NetworkList []NetworkInfo
|
NetworkList []libvirtxml.Network
|
||||||
// DeviceList is the list of devices on the host
|
// DeviceList is the list of devices on the host
|
||||||
DeviceList []DeviceInfo
|
DeviceList []libvirtxml.NodeDevice
|
||||||
// SecretList provides a list of secrets available to the host
|
// SecretList provides a list of secrets available to the host
|
||||||
SecretList []SecretInfo
|
SecretList []libvirtxml.Secret
|
||||||
// StoragePoolList provides the list of stoarge ppols available to the host
|
// StoragePoolList provides the list of stoarge ppols available to the host
|
||||||
StoragePoolList []StoragePoolInfo
|
StoragePoolList []libvirtxml.StoragePool
|
||||||
|
// VolumeList is the list of volumes available on the host
|
||||||
|
VolumeList []libvirtxml.StorageVolume
|
||||||
|
|
||||||
uri *URI
|
uri *URI
|
||||||
conn *libvirt.Connect
|
conn *libvirt.Connect
|
||||||
@ -68,108 +61,6 @@ type Host struct {
|
|||||||
closeErr chan error
|
closeErr chan error
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeviceInfo holds basic information for host devices
|
|
||||||
type DeviceInfo struct {
|
|
||||||
Name string
|
|
||||||
Capabilities []string
|
|
||||||
XML string
|
|
||||||
}
|
|
||||||
|
|
||||||
// VMInfo holds basic VM information, like the name and ID
|
|
||||||
type VMInfo struct {
|
|
||||||
Name string
|
|
||||||
ID uint
|
|
||||||
UUID []byte
|
|
||||||
XML string
|
|
||||||
Active bool
|
|
||||||
VCPUs uint
|
|
||||||
Memory uint
|
|
||||||
// States are the current states active on the host
|
|
||||||
States []guest.VMState
|
|
||||||
}
|
|
||||||
|
|
||||||
// SecretInfo doesn't let you see the contents of secrets, but does let you see what secrets have
|
|
||||||
// been defined in a simple format.
|
|
||||||
type SecretInfo struct {
|
|
||||||
UUID string
|
|
||||||
XML string
|
|
||||||
Type string
|
|
||||||
}
|
|
||||||
|
|
||||||
// StoragePoolInfo holds basic information on storage pools
|
|
||||||
type StoragePoolInfo struct {
|
|
||||||
Name string
|
|
||||||
UUID []byte
|
|
||||||
Type string
|
|
||||||
XML string
|
|
||||||
Active bool
|
|
||||||
Persistent bool
|
|
||||||
AutoStart bool
|
|
||||||
State string
|
|
||||||
Capacity uint64
|
|
||||||
Allocation uint64
|
|
||||||
Available uint64
|
|
||||||
IsNet bool
|
|
||||||
// HAEnabled indicates if the storage pool has High Availability
|
|
||||||
HAEnabled bool
|
|
||||||
// Volumes defined in the storage pool
|
|
||||||
Volumes []VolumeInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
// VolumeInfo holds basic information about Volumes available in storage pools
|
|
||||||
type VolumeInfo struct {
|
|
||||||
Name string
|
|
||||||
Key string
|
|
||||||
Path string
|
|
||||||
Type string
|
|
||||||
Capacity uint64
|
|
||||||
Allocation uint64
|
|
||||||
XML string
|
|
||||||
}
|
|
||||||
|
|
||||||
// NetIfInfo holds basic information about available network interfaces (not their connections, the devices themselves)
|
|
||||||
type NetIfInfo struct {
|
|
||||||
Name string
|
|
||||||
MacAddr string
|
|
||||||
XML string
|
|
||||||
}
|
|
||||||
|
|
||||||
// NetworkInfo holds basic information about network connections
|
|
||||||
type NetworkInfo struct {
|
|
||||||
Name string
|
|
||||||
UUID []byte
|
|
||||||
XML string
|
|
||||||
Active bool
|
|
||||||
// NetIf is the network interface this connection is applied to
|
|
||||||
NetIf NetIfInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
// NodeInfo represents the basic HW info for a host node
|
|
||||||
type NodeInfo struct {
|
|
||||||
// livirt.NodeInfo section
|
|
||||||
Model string
|
|
||||||
Memory uint64
|
|
||||||
Cpus uint
|
|
||||||
MHz uint
|
|
||||||
Nodes uint32
|
|
||||||
Sockets uint32
|
|
||||||
Cores uint32
|
|
||||||
Threads uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
// SEVInfo provides information about AMD SEV support
|
|
||||||
type SEVInfo struct {
|
|
||||||
// livirt.NodeSEVParameters section
|
|
||||||
SEVEnabled bool
|
|
||||||
PDH string
|
|
||||||
CertChain string
|
|
||||||
CBitPos uint
|
|
||||||
ReducedPhysBits uint
|
|
||||||
MaxGuests uint
|
|
||||||
MaxEsGuests uint
|
|
||||||
CPU0ID string
|
|
||||||
}
|
|
||||||
|
|
||||||
// NodeMemoryInfo provides statistis about node memory usage from libvirt.NodeMemoryStats
|
// NodeMemoryInfo provides statistis about node memory usage from libvirt.NodeMemoryStats
|
||||||
type NodeMemoryInfo struct {
|
type NodeMemoryInfo struct {
|
||||||
Total uint64
|
Total uint64
|
||||||
@ -234,7 +125,7 @@ func (h *Host) Close() error {
|
|||||||
// private methods that load the different informational parts
|
// private methods that load the different informational parts
|
||||||
|
|
||||||
func (h *Host) getInfo() {
|
func (h *Host) getInfo() {
|
||||||
var wg = new(sync.WaitGroup)
|
wg := new(sync.WaitGroup)
|
||||||
|
|
||||||
infoFuncs := []func(){
|
infoFuncs := []func(){
|
||||||
h.getDevicesInfo,
|
h.getDevicesInfo,
|
||||||
@ -242,7 +133,6 @@ func (h *Host) getInfo() {
|
|||||||
h.getIfaceInfo,
|
h.getIfaceInfo,
|
||||||
h.getNetsInfo,
|
h.getNetsInfo,
|
||||||
h.getNodeInfo,
|
h.getNodeInfo,
|
||||||
// h.getSEVInfo,
|
|
||||||
// h.getSecretsInfo,
|
// h.getSecretsInfo,
|
||||||
// h.getStoragePools,
|
// h.getStoragePools,
|
||||||
}
|
}
|
||||||
@ -298,13 +188,13 @@ func (h *Host) getStoragePools() {
|
|||||||
log.Println(err)
|
log.Println(err)
|
||||||
}
|
}
|
||||||
h.StoragePoolList[i].Type = spoolXML.Type
|
h.StoragePoolList[i].Type = spoolXML.Type
|
||||||
for _, t := range storagepool.NetTypes {
|
for _, t := range storagepool.NetTypes {
|
||||||
if h.StoragePoolList[i].Type == t {
|
if h.StoragePoolList[i].Type == t {
|
||||||
h.StoragePoolList[i].IsNet = true
|
h.StoragePoolList[i].IsNet = true
|
||||||
h.StoragePoolList[i].HAEnabled = true
|
h.StoragePoolList[i].HAEnabled = true
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
svols, err := s.ListAllStorageVolumes(0)
|
svols, err := s.ListAllStorageVolumes(0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -432,34 +322,6 @@ func (h *Host) getNodeInfo() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Host) getSEVInfo() {
|
|
||||||
// getSEVInfo
|
|
||||||
h.HostSEVInfo.SEVEnabled = true
|
|
||||||
ns, err := h.conn.GetSEVInfo(0)
|
|
||||||
if err != nil {
|
|
||||||
log.Println(err)
|
|
||||||
lverr, ok := err.(libvirt.Error)
|
|
||||||
if ok {
|
|
||||||
switch lverr.Code {
|
|
||||||
case 84:
|
|
||||||
log.Println("SEV functions not supported")
|
|
||||||
h.HostSEVInfo.SEVEnabled = false
|
|
||||||
default:
|
|
||||||
log.Println("Error encountered", lverr.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if h.HostSEVInfo.SEVEnabled {
|
|
||||||
h.HostSEVInfo.PDH = util.SetNotSet(ns.PDH, ns.PDHSet)
|
|
||||||
h.HostSEVInfo.CertChain = util.SetNotSet(ns.CertChain, ns.CertChainSet)
|
|
||||||
h.HostSEVInfo.CBitPos = ns.CBitPos
|
|
||||||
h.HostSEVInfo.ReducedPhysBits = ns.ReducedPhysBits
|
|
||||||
h.HostSEVInfo.MaxGuests = ns.MaxGuests
|
|
||||||
h.HostSEVInfo.MaxEsGuests = ns.MaxEsGuests
|
|
||||||
h.HostSEVInfo.CPU0ID = util.SetNotSet(ns.CPU0ID, ns.CPU0IDSet)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (h *Host) getDomainInfo() {
|
func (h *Host) getDomainInfo() {
|
||||||
// getDomainInfo
|
// getDomainInfo
|
||||||
doms, err := h.conn.ListAllDomains(0)
|
doms, err := h.conn.ListAllDomains(0)
|
||||||
@ -482,15 +344,15 @@ func (h *Host) getDomainInfo() {
|
|||||||
if h.VMList[i].XML, err = d.GetXMLDesc(0); err != nil {
|
if h.VMList[i].XML, err = d.GetXMLDesc(0); err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
}
|
}
|
||||||
vmXML := &libvirtxml.Domain{}
|
vmXML := &libvirtxml.Domain{}
|
||||||
if err = vmXML.Unmarshal(h.VMList[i].XML); err != nil {
|
if err = vmXML.Unmarshal(h.VMList[i].XML); err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
}
|
}
|
||||||
h.VMList[i].VCPUs = vmXML.VCPU.Value
|
h.VMList[i].VCPUs = vmXML.VCPU.Value
|
||||||
h.VMList[i].Memory = vmXML.CurrentMemory.Value
|
h.VMList[i].Memory = vmXML.CurrentMemory.Value
|
||||||
if h.VMList[i].Active, err = d.IsActive(); err != nil {
|
if h.VMList[i].Active, err = d.IsActive(); err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
d.Free()
|
d.Free()
|
||||||
}
|
}
|
||||||
@ -545,9 +407,9 @@ func (h *Host) getNetsInfo() {
|
|||||||
if h.NetworkList[i].XML, err = net.GetXMLDesc(0); err != nil {
|
if h.NetworkList[i].XML, err = net.GetXMLDesc(0); err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
}
|
}
|
||||||
if h.NetworkList[i].Active, err = net.IsActive(); err != nil {
|
if h.NetworkList[i].Active, err = net.IsActive(); err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
net.Free()
|
net.Free()
|
||||||
}
|
}
|
||||||
@ -571,6 +433,12 @@ func (h *Host) getDevicesInfo() {
|
|||||||
if h.DeviceList[i].XML, err = dev.GetXMLDesc(0); err != nil {
|
if h.DeviceList[i].XML, err = dev.GetXMLDesc(0); err != nil {
|
||||||
log.Println(err)
|
log.Println(err)
|
||||||
}
|
}
|
||||||
|
dx := &libvirtxml.NodeDevice{}
|
||||||
|
if err != dx.Unmarshal(h.DeviceList[i].XML); err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
h.DeviceList[i].Driver = dx.Driver.Name
|
||||||
|
dx.Capability.PCI.Class
|
||||||
|
|
||||||
dev.Free()
|
dev.Free()
|
||||||
}
|
}
|
||||||
|
48
util/pcidb.go
Normal file
48
util/pcidb.go
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
package util
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/jaypipes/pcidb"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
pcidbInitDone = false
|
||||||
|
db *pcidb.PCIDB
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
pcidbNOTFOUND string = `NOTFOUND`
|
||||||
|
pcidbNODB string = `NODBFOUND`
|
||||||
|
)
|
||||||
|
|
||||||
|
func initPCIDB() {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
// Attempt to use local sources first, fallback to network if
|
||||||
|
// local sources aren't found
|
||||||
|
db, err = pcidb.New()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("warning: couldn't use local pcidb cache: %s", err)
|
||||||
|
log.Println("falling back to downloading database")
|
||||||
|
db, err = pcidb.New(pcidb.WithEnableNetworkFetch())
|
||||||
|
if err != nil {
|
||||||
|
log.Println("error: couldn't get pcidb. no more fallbacks available, will not be able to query the pcidb")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pcidbInitDone = true
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetPCIClass(id string) string {
|
||||||
|
if !pcidbInitDone {
|
||||||
|
initPCIDB()
|
||||||
|
}
|
||||||
|
if pcidbInitDone && db == nil {
|
||||||
|
log.Println("unable to access pcidb")
|
||||||
|
return pcidbNODB
|
||||||
|
}
|
||||||
|
if class, ok := db.Classes[id]; ok {
|
||||||
|
return class.Name
|
||||||
|
}
|
||||||
|
return pcidbNOTFOUND
|
||||||
|
}
|
@ -10,48 +10,58 @@ import (
|
|||||||
templ ClusterInfo(cs *cluster.ClusterStats, diff cluster.StatDiff, navbar []components.NavItem) {
|
templ ClusterInfo(cs *cluster.ClusterStats, diff cluster.StatDiff, navbar []components.NavItem) {
|
||||||
@layouts.Manager("ClustVirt", "Cluster Manager", navbar) {
|
@layouts.Manager("ClustVirt", "Cluster Manager", navbar) {
|
||||||
<h3>Cluster Stats</h3>
|
<h3>Cluster Stats</h3>
|
||||||
<table class={ "table-auto", "w-full" }>
|
|
||||||
<caption class={ "caption-top" }>
|
|
||||||
CPU stats
|
|
||||||
</caption>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>Sockets</th>
|
|
||||||
<th>Cores</th>
|
|
||||||
<th>Threads</th>
|
|
||||||
<th>Allocated</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
{ fmt.Sprint(cs.CPU.Sockets) }
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{ fmt.Sprint(cs.CPU.Cores) }
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{ fmt.Sprint(cs.CPU.Threads) }
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{ fmt.Sprint(cs.CPU.Allocated) }
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>
|
|
||||||
{ fmt.Sprint(diff.CPU.Sockets) }
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{ fmt.Sprint(diff.CPU.Cores) }
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{ fmt.Sprint(diff.CPU.Threads) }
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
{ fmt.Sprint(diff.CPU.Allocated) }
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
templ CPUStats() {
|
||||||
|
<table class={ "table-auto", "w-full" }>
|
||||||
|
<caption class={ "caption-top" }>
|
||||||
|
CPU stats
|
||||||
|
</caption>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th></th>
|
||||||
|
<th>Sockets</th>
|
||||||
|
<th>Cores</th>
|
||||||
|
<th>Threads</th>
|
||||||
|
<th>Allocated</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
Latest
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{ fmt.Sprint(cs.CPU.Sockets) }
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{ fmt.Sprint(cs.CPU.Cores) }
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{ fmt.Sprint(cs.CPU.Threads) }
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{ fmt.Sprint(cs.CPU.Allocated) }
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
Change
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{ fmt.Sprint(diff.CPU.Sockets) }
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{ fmt.Sprint(diff.CPU.Cores) }
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{ fmt.Sprint(diff.CPU.Threads) }
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{ fmt.Sprint(diff.CPU.Allocated) }
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user