mirror of
https://github.com/ClusterCockpit/cc-metric-collector.git
synced 2024-11-12 21:17:25 +01:00
162cce0fda
* InfiniBandCollector: Scale raw readings from octets to bytes * Fix clock frequency coming from LikwidCollector and update docs * Build DEB package for Ubuntu 20.04 for releases * Fix memstat collector with numa_stats option * Remove useless prints from MemstatCollector * Replace ioutils with os and io (#87) * Use lower case for error strings in RocmSmiCollector * move maybe-usable-by-other-cc-components to pkg. Fix all files to use the new paths (#88) * Add collector for monitoring the execution of cc-metric-collector itself (#81) * Add collector to monitor execution of cc-metric-collector itself * Register SelfCollector * Fix import paths for moved packages * Check if at least one CPU with frequency information was detected * Correct type: /proc/stats -> /proc/stat * Update README.md * Run ipmitool asynchron. Improved error handling. * Corrected some typos * Add running average power limit (RAPL) metric collector * Add running average power limit (RAPL) metric collector * Do not mess up with the orignal configuration * * Corrected json config in numastatsMetric.md * Added some debug output to numastatsMetric.go * Fixed computing number of physical packages for non continous physical package IDs (e.g. on Ampere Altra Q80-30) * Fix kernel panic for receiver config with missing receiver type * Add receiver to gather remote IPMI sensor metrics * Added config option to add ipmi-sensors command line options * Add documentaion for IPMI receiver * Update to latest version of included go modules * Add go.mod to App dependency * Try to use common metric tags across hardware vendors * Add IPMI metric: current * remove prefix enumeration like 01-... * Add IPMI receiver example configuration to receivers.json * Minimal formating changes * Add hostlist package * Added tests for hostlist Expand() * Use package hostlist to expand a host list * Use package hostlist to expand a host list * Some servers return "ConsumedPowerWatt":65535 instead of "ConsumedPowerWatt":null * Updated to latest package versions * Do not allow unknown fields in JSON configuration file * Add workflow to customize packages to docs * NFS I/O Stats Collector (#91) * Initial version * Delete values for vanished mount points and comments * Fix for Likwid collector (#95) * Run LIKWID in separate thread and check metric type * Change LIKWID collector documentation to use 'type' instead of 'scope' * Re-initialize LIKWID after one read is missing due to lock toggle * Register cc-metric-collector at Zenodo (#93) * Add initial version of Zenodo project file * Orcid ID added * Update .zenodo.json Co-authored-by: Holger Obermaier <holger.obermaier@kit.edu> * Update ipmiMetric.go Co-authored-by: Holger Obermaier <40787752+ho-ob@users.noreply.github.com> Co-authored-by: Holger Obermaier <Holger.Obermaier@kit.edu>
126 lines
3.1 KiB
Go
126 lines
3.1 KiB
Go
package hostlist
|
|
|
|
import (
|
|
"fmt"
|
|
"regexp"
|
|
"sort"
|
|
"strconv"
|
|
"strings"
|
|
)
|
|
|
|
func Expand(in string) (result []string, err error) {
|
|
|
|
// Create ranges regular expression
|
|
reStNumber := "[[:digit:]]+"
|
|
reStRange := reStNumber + "-" + reStNumber
|
|
reStOptionalNumberOrRange := "(" + reStNumber + ",|" + reStRange + ",)*"
|
|
reStNumberOrRange := "(" + reStNumber + "|" + reStRange + ")"
|
|
reStBraceLeft := "[[]"
|
|
reStBraceRight := "[]]"
|
|
reStRanges := reStBraceLeft +
|
|
reStOptionalNumberOrRange +
|
|
reStNumberOrRange +
|
|
reStBraceRight
|
|
reRanges := regexp.MustCompile(reStRanges)
|
|
|
|
// Create host list regular expression
|
|
reStDNSChars := "[a-zA-Z0-9-]+"
|
|
reStPrefix := "^(" + reStDNSChars + ")"
|
|
reStOptionalSuffix := "(" + reStDNSChars + ")?"
|
|
re := regexp.MustCompile(reStPrefix + "([[][0-9,-]+[]])?" + reStOptionalSuffix)
|
|
|
|
// Remove all delimiters from the input
|
|
in = strings.TrimLeft(in, ", ")
|
|
|
|
for len(in) > 0 {
|
|
if v := re.FindStringSubmatch(in); v != nil {
|
|
|
|
// Remove matched part from the input
|
|
lenPrefix := len(v[0])
|
|
in = in[lenPrefix:]
|
|
|
|
// Remove all delimiters from the input
|
|
in = strings.TrimLeft(in, ", ")
|
|
|
|
// matched prefix, range and suffix
|
|
hlPrefix := v[1]
|
|
hlRanges := v[2]
|
|
hlSuffix := v[3]
|
|
|
|
// Single node without ranges
|
|
if hlRanges == "" {
|
|
result = append(result, hlPrefix)
|
|
continue
|
|
}
|
|
|
|
// Node with ranges
|
|
if v := reRanges.FindStringSubmatch(hlRanges); v != nil {
|
|
|
|
// Remove braces
|
|
hlRanges = hlRanges[1 : len(hlRanges)-1]
|
|
|
|
// Split host ranges at ,
|
|
for _, hlRange := range strings.Split(hlRanges, ",") {
|
|
|
|
// Split host range at -
|
|
RangeStartEnd := strings.Split(hlRange, "-")
|
|
|
|
// Range is only a single number
|
|
if len(RangeStartEnd) == 1 {
|
|
result = append(result, hlPrefix+RangeStartEnd[0]+hlSuffix)
|
|
continue
|
|
}
|
|
|
|
// Range has a start and an end
|
|
widthRangeStart := len(RangeStartEnd[0])
|
|
widthRangeEnd := len(RangeStartEnd[1])
|
|
iStart, _ := strconv.ParseUint(RangeStartEnd[0], 10, 64)
|
|
iEnd, _ := strconv.ParseUint(RangeStartEnd[1], 10, 64)
|
|
if iStart > iEnd {
|
|
return nil, fmt.Errorf("single range start is greater than end: %s", hlRange)
|
|
}
|
|
|
|
// Create print format string for range numbers
|
|
doPadding := widthRangeStart == widthRangeEnd
|
|
widthPadding := widthRangeStart
|
|
var formatString string
|
|
if doPadding {
|
|
formatString = "%0" + fmt.Sprint(widthPadding) + "d"
|
|
} else {
|
|
formatString = "%d"
|
|
}
|
|
formatString = hlPrefix + formatString + hlSuffix
|
|
|
|
// Add nodes from this range
|
|
for i := iStart; i <= iEnd; i++ {
|
|
result = append(result, fmt.Sprintf(formatString, i))
|
|
}
|
|
}
|
|
} else {
|
|
return nil, fmt.Errorf("not at hostlist range: %s", hlRanges)
|
|
}
|
|
} else {
|
|
return nil, fmt.Errorf("not a hostlist: %s", in)
|
|
}
|
|
}
|
|
|
|
if result != nil {
|
|
// sort
|
|
sort.Strings(result)
|
|
|
|
// uniq
|
|
previous := 1
|
|
for current := 1; current < len(result); current++ {
|
|
if result[current-1] != result[current] {
|
|
if previous != current {
|
|
result[previous] = result[current]
|
|
}
|
|
previous++
|
|
}
|
|
}
|
|
result = result[:previous]
|
|
}
|
|
|
|
return
|
|
}
|