Allow multiple hosts to share the same client configuration

This commit is contained in:
Holger Obermaier 2022-08-26 11:55:53 +02:00
parent 7ccbf1ebe2
commit 503705d442
2 changed files with 83 additions and 47 deletions

View File

@ -630,10 +630,10 @@ func NewRedfishReceiver(name string, config json.RawMessage) (Receiver, error) {
ExcludeMetrics []string `json:"exclude_metrics,omitempty"` ExcludeMetrics []string `json:"exclude_metrics,omitempty"`
ClientConfigs []struct { ClientConfigs []struct {
Hostname *string `json:"hostname"` // Hostname the redfish service belongs to HostList []string `json:"host_list"` // List of hosts with the same client configuration
Username *string `json:"username"` // User name to authenticate with Username *string `json:"username"` // User name to authenticate with
Password *string `json:"password"` // Password to use for authentication Password *string `json:"password"` // Password to use for authentication
Endpoint *string `json:"endpoint"` // URL of the redfish service Endpoint *string `json:"endpoint"` // URL of the redfish service
// Per client disable collection of power,processor or thermal metrics // Per client disable collection of power,processor or thermal metrics
DisablePowerMetrics bool `json:"disable_power_metrics"` DisablePowerMetrics bool `json:"disable_power_metrics"`
@ -667,7 +667,7 @@ func NewRedfishReceiver(name string, config json.RawMessage) (Receiver, error) {
} }
} }
// interval duration // Convert interval string representation to duration
var err error var err error
r.config.Interval, err = time.ParseDuration(configJSON.IntervalString) r.config.Interval, err = time.ParseDuration(configJSON.IntervalString)
if err != nil { if err != nil {
@ -702,86 +702,121 @@ func NewRedfishReceiver(name string, config json.RawMessage) (Receiver, error) {
Transport: customTransport, Transport: customTransport,
} }
// Compute fanout to use // Initialize client configurations
numClients := len(configJSON.ClientConfigs) r.config.ClientConfigs = make([]RedfishReceiverClientConfig, 0)
r.config.fanout = configJSON.Fanout
if numClients < r.config.fanout {
r.config.fanout = numClients
}
// Initialize derived configuration // Create client config from JSON config
r.config.ClientConfigs = make([]RedfishReceiverClientConfig, numClients) for i := range configJSON.ClientConfigs {
// Create gofish client config
for i := 0; i < numClients; i++ {
clientConfig := &r.config.ClientConfigs[i]
clientConfigJSON := &configJSON.ClientConfigs[i] clientConfigJSON := &configJSON.ClientConfigs[i]
gofishConfig := &clientConfig.gofish
if clientConfigJSON.Hostname == nil { var endpoint_pattern string
err := fmt.Errorf("client config number %v requires hostname", i)
cclog.ComponentError(r.name, err)
return nil, err
}
clientConfig.Hostname = *clientConfigJSON.Hostname
var endpoint string
if clientConfigJSON.Endpoint != nil { if clientConfigJSON.Endpoint != nil {
endpoint = *clientConfigJSON.Endpoint endpoint_pattern = *clientConfigJSON.Endpoint
} else if configJSON.Endpoint != nil { } else if configJSON.Endpoint != nil {
endpoint = *configJSON.Endpoint endpoint_pattern = *configJSON.Endpoint
} else { } else {
err := fmt.Errorf("client config number %v requires endpoint", i) err := fmt.Errorf("client config number %v requires endpoint", i)
cclog.ComponentError(r.name, err) cclog.ComponentError(r.name, err)
return nil, err return nil, err
} }
gofishConfig.Endpoint = strings.Replace(endpoint, "%h", clientConfig.Hostname, -1)
var username string
if clientConfigJSON.Username != nil { if clientConfigJSON.Username != nil {
gofishConfig.Username = *clientConfigJSON.Username username = *clientConfigJSON.Username
} else if configJSON.Username != nil { } else if configJSON.Username != nil {
gofishConfig.Username = *configJSON.Username username = *configJSON.Username
} else { } else {
err := fmt.Errorf("client config number %v requires username", i) err := fmt.Errorf("client config number %v requires username", i)
cclog.ComponentError(r.name, err) cclog.ComponentError(r.name, err)
return nil, err return nil, err
} }
var password string
if clientConfigJSON.Password != nil { if clientConfigJSON.Password != nil {
gofishConfig.Password = *clientConfigJSON.Password password = *clientConfigJSON.Password
} else if configJSON.Password != nil { } else if configJSON.Password != nil {
gofishConfig.Password = *configJSON.Password password = *configJSON.Password
} else { } else {
err := fmt.Errorf("client config number %v requires password", i) err := fmt.Errorf("client config number %v requires password", i)
cclog.ComponentError(r.name, err) cclog.ComponentError(r.name, err)
return nil, err return nil, err
} }
// Reuse existing http client
gofishConfig.HTTPClient = httpClient
// Which metrics should be collected // Which metrics should be collected
clientConfig.doPowerMetric = doPowerMetric :=
!(configJSON.DisablePowerMetrics || !(configJSON.DisablePowerMetrics ||
clientConfigJSON.DisablePowerMetrics) clientConfigJSON.DisablePowerMetrics)
clientConfig.doProcessorMetrics = doProcessorMetrics :=
!(configJSON.DisableProcessorMetrics || !(configJSON.DisableProcessorMetrics ||
clientConfigJSON.DisableProcessorMetrics) clientConfigJSON.DisableProcessorMetrics)
clientConfig.doThermalMetrics = doThermalMetrics :=
!(configJSON.DisableThermalMetrics || !(configJSON.DisableThermalMetrics ||
clientConfigJSON.DisableThermalMetrics) clientConfigJSON.DisableThermalMetrics)
clientConfig.skipProcessorMetricsURL = make(map[string]bool)
// Is metrics excluded globally or per client // Is metrics excluded globally or per client
clientConfig.isExcluded = make(map[string]bool) isExcluded := make(map[string]bool)
for _, key := range clientConfigJSON.ExcludeMetrics { for _, key := range clientConfigJSON.ExcludeMetrics {
clientConfig.isExcluded[key] = true isExcluded[key] = true
} }
for _, key := range configJSON.ExcludeMetrics { for _, key := range configJSON.ExcludeMetrics {
clientConfig.isExcluded[key] = true isExcluded[key] = true
} }
for _, host := range clientConfigJSON.HostList {
// Endpoint of the redfish service
endpoint := strings.Replace(endpoint_pattern, "%h", host, -1)
r.config.ClientConfigs = append(
r.config.ClientConfigs,
RedfishReceiverClientConfig{
Hostname: host,
isExcluded: isExcluded,
doPowerMetric: doPowerMetric,
doProcessorMetrics: doProcessorMetrics,
doThermalMetrics: doThermalMetrics,
skipProcessorMetricsURL: make(map[string]bool),
gofish: gofish.ClientConfig{
Username: username,
Password: password,
Endpoint: endpoint,
HTTPClient: httpClient,
},
})
}
} }
// Compute parallel fanout to use
numClients := len(r.config.ClientConfigs)
r.config.fanout = configJSON.Fanout
if numClients < r.config.fanout {
r.config.fanout = numClients
}
if numClients == 0 {
err := fmt.Errorf("at least one client config is required")
cclog.ComponentError(r.name, err)
return nil, err
}
// Check for duplicate client configurations
isDuplicate := make(map[string]bool)
for i := range r.config.ClientConfigs {
host := r.config.ClientConfigs[i].Hostname
if isDuplicate[host] {
err := fmt.Errorf("Found duplicate client config for host %s", host)
cclog.ComponentError(r.name, err)
return nil, err
}
isDuplicate[host] = true
}
// Give some basic info about redfish receiver status
cclog.ComponentInfo(r.name, "Monitoring", numClients, "clients")
cclog.ComponentInfo(r.name, "Monitoring interval:", r.config.Interval)
cclog.ComponentInfo(r.name, "Monitoring parallel fanout:", r.config.fanout)
return r, nil return r, nil
} }

View File

@ -14,14 +14,14 @@ The Redfish receiver uses the [Redfish (specification)](https://www.dmtf.org/sta
"exclude_metrics": [ "min_consumed_watts" ], "exclude_metrics": [ "min_consumed_watts" ],
"client_config": [ "client_config": [
{ {
"hostname": "<host 1>" "host_list": [ "<host 1>", "<host 2>" ]
}, },
{ {
"hostname": "<host 2>", "host_list": [ "<host 3>", "<host 4>" ]
"disable_power_metrics": true "disable_power_metrics": true
}, },
{ {
"hostname": "<host 3>", "host_list": [ "<host 5>" ],
"username": "<user B>", "username": "<user B>",
"password": "<password B>", "password": "<password B>",
"endpoint": "https://%h-BMC", "endpoint": "https://%h-BMC",
@ -42,6 +42,7 @@ Global settings:
Global and per redfish device settings (per redfish device settings overwrite the global settings): Global and per redfish device settings (per redfish device settings overwrite the global settings):
- `disable_power_metrics`: disable collection of power metrics - `disable_power_metrics`: disable collection of power metrics
- `disable_processor_metrics`: disable collection of processor metrics
- `disable_thermal_metrics`: disable collection of thermal metrics - `disable_thermal_metrics`: disable collection of thermal metrics
- `exclude_metrics`: list of excluded metrics - `exclude_metrics`: list of excluded metrics
- `username`: User name to authenticate with - `username`: User name to authenticate with
@ -50,4 +51,4 @@ Global and per redfish device settings (per redfish device settings overwrite th
Per redfish device settings: Per redfish device settings:
- `hostname`: hostname the redfish service belongs to - `host_list`: List of hosts with the same client configuration