package cluster import "git.staur.ca/stobbsm/clustvirt/lib/storagepool" // 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 { // CPU Statistics including number of CPUs CPU CPUStats // Memory provides information about the amount of memory, including free and // allocated memory Memory MemoryStats // Storage provides information about storage pools, Only get's stats for active // pools, and will not activate pools that are not already active. // Trys to sort out shared file systems from local filesystems using the Type parameter // of Host.StoragePoolInfo Storage StorageStats // Volume provides information on allocated volumes used in the cluster Volume VolumeStats // VM provides VM specific counters for the cluster VM VMStats // Host provides Host information for the cluster Host HostStats // Network provices available networks, and how many are shared between hosts Network NetworkStats // NetIF provides information about Libvirt allocated networks, usable by the // libvirt cluster NetIF NetIFStats old *ClusterStats 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 // All sizes are in Bytes 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 type StatDiff struct { CPU CPUDiff Memory MemoryDiff Storage StorageDiff Volume VolumeDiff VM VMDiff Host HostDiff Network NetworkDiff } type CPUDiff struct { Sockets int Cores int Threads int Allocated int } type MemoryDiff struct { Total int64 Free int64 Buffers int64 Cached int64 Allocated int64 } type StorageDiff struct { Total int64 Used int64 Free int64 Active int64 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 // Does not close connections, but uses the host connections available to the // cluster to add statistics together. func InitStats(c *Cluster) *ClusterStats { cs := &ClusterStats{ c: c, } return cs } // Update triggers the stats collector to refresh it's statistics func (cs *ClusterStats) Update() { cs.old = cs.copy() cs.reset() // Start looping through each host in the cluster, adding to the total for _, h := range cs.c.hosts { cs.Host.Count++ cs.Host.Available++ cs.CPU.Sockets += uint32(h.HostInfo.CPU.Topology.Sockets) cs.CPU.Cores += uint32(h.HostInfo.CPU.Topology.Cores) cs.CPU.Threads += uint32(h.HostInfo.CPU.Topology.Threads) cs.Memory.Total += h.NodeMemory.Total cs.Memory.Free += h.NodeMemory.Free cs.Memory.Buffers += h.NodeMemory.Buffers cs.Memory.Cached += h.NodeMemory.Cached // Storage Pool counting cs.Storage.Pools += uint32(len(h.StoragePoolList)) countedSharedPools := map[string]struct{}{} // Loop through available storage pools for _, sp := range h.StoragePoolList { if _, ok := countedSharedPools[sp.Name]; ok { // Already counted this shared pool, move on continue } if isNetworkPool(sp.Type) { countedSharedPools[sp.Name] = struct{}{} } cs.Storage.Active++ cs.Storage.Total += sp.Capacity.Value cs.Storage.Used += sp.Allocation.Value cs.Storage.Free += sp.Capacity.Value - sp.Allocation.Value } // VM Count cs.VM.Count += uint32(len(h.VMList)) for _, vm := range h.VMList { cs.CPU.Allocated += uint32(len(vm.VCPUs.VCPU)) cs.Memory.Allocated += uint64(vm.Memory.Value) } // Network count cs.Network.Count += uint32(len(h.NetworkList)) cs.Network.Inactive++ } } // Diff returns a map of all the field and how they changed func (cs *ClusterStats) Diff() StatDiff { return StatDiff{ CPU: CPUDiff{ Sockets: int(cs.CPU.Sockets) - int(cs.old.CPU.Sockets), Cores: int(cs.CPU.Cores) - int(cs.old.CPU.Cores), Threads: int(cs.CPU.Threads) - int(cs.old.CPU.Threads), Allocated: int(cs.CPU.Allocated) - int(cs.old.CPU.Allocated), }, Memory: MemoryDiff{ Total: int64(cs.old.Memory.Total) - int64(cs.Memory.Total), Free: int64(cs.old.Memory.Free) - int64(cs.Memory.Free), Buffers: int64(cs.old.Memory.Buffers) - int64(cs.Memory.Buffers), Cached: int64(cs.old.Memory.Cached) - int64(cs.Memory.Cached), Allocated: int64(cs.old.Memory.Allocated) - int64(cs.Memory.Allocated), }, Storage: StorageDiff{ Total: int64(cs.old.Storage.Total) - int64(cs.Storage.Total), Used: int64(cs.old.Storage.Used) - int64(cs.Storage.Used), Free: int64(cs.old.Storage.Free) - int64(cs.Storage.Free), Active: int64(cs.old.Storage.Active) - int64(cs.Storage.Active), Inactive: int64(cs.old.Storage.Inactive) - int64(cs.Storage.Inactive), Pools: int(cs.old.Storage.Pools) - int(cs.Storage.Pools), }, Volume: VolumeDiff{ Total: int(cs.old.Volume.Total) - int(cs.Volume.Total), Active: int(cs.old.Volume.Active) - int(cs.Volume.Active), Inactive: int(cs.old.Volume.Inactive) - int(cs.Volume.Inactive), }, VM: VMDiff{ Count: int(cs.old.VM.Count) - int(cs.VM.Count), Started: int(cs.old.VM.Started) - int(cs.VM.Started), Stopped: int(cs.old.VM.Stopped) - int(cs.VM.Stopped), }, Host: HostDiff{ Count: int(cs.old.Host.Count) - int(cs.Host.Count), Available: int(cs.old.Host.Available) - int(cs.Host.Available), }, Network: NetworkDiff{ Count: int(cs.old.Network.Count) - int(cs.Network.Count), Active: int(cs.old.Network.Active) - int(cs.Network.Active), Inactive: int(cs.old.Network.Inactive) - int(cs.Network.Inactive), }, } } // copy the clusterstats into a new clusterstatus object for comparison purposes func (cs *ClusterStats) copy() *ClusterStats { ncs := *cs return &ncs } // reset all values to zero value func (cs *ClusterStats) reset() { cs.CPU.Sockets = 0 cs.CPU.Cores = 0 cs.CPU.Threads = 0 cs.CPU.Allocated = 0 cs.Memory.Total = 0 cs.Memory.Free = 0 cs.Memory.Buffers = 0 cs.Memory.Cached = 0 cs.Storage.Total = 0 cs.Storage.Used = 0 cs.Storage.Free = 0 cs.Storage.Active = 0 cs.Storage.Inactive = 0 cs.Storage.Pools = 0 cs.VM.Count = 0 cs.VM.Started = 0 cs.VM.Stopped = 0 cs.Host.Count = 0 cs.Host.Available = 0 cs.Network.Count = 0 cs.Network.Active = 0 cs.Network.Inactive = 0 } func isNetworkPool(pooltype string) bool { for _, t := range storagepool.NetTypes { if t == pooltype { return true } } return false }