Skip to content

Commit

Permalink
Merge pull request #734 from rootfs/redfish
Browse files Browse the repository at this point in the history
Support redfish
  • Loading branch information
husky-parul authored Jul 18, 2023
2 parents 4522f61 + 12c16cf commit 6a9d195
Show file tree
Hide file tree
Showing 15 changed files with 894 additions and 13 deletions.
11 changes: 10 additions & 1 deletion cmd/exporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import (
"github.com/sustainable-computing-io/kepler/pkg/model"
"github.com/sustainable-computing-io/kepler/pkg/power/accelerator"
"github.com/sustainable-computing-io/kepler/pkg/power/components"
"github.com/sustainable-computing-io/kepler/pkg/power/platform"
kversion "github.com/sustainable-computing-io/kepler/pkg/version"

"github.com/prometheus/client_golang/prometheus"
Expand Down Expand Up @@ -63,6 +64,7 @@ var (
kubeconfig = flag.String("kubeconfig", "", "absolute path to the kubeconfig file, if empty we use the in-cluster configuration")
apiserverEnabled = flag.Bool("apiserver", true, "if apiserver is disabled, we collect pod information from kubelet")
kernelSourceDirPath = flag.String("kernel-source-dir", "", "path to the kernel source directory")
redfishCredFilePath = flag.String("redfish-cred-file-path", "", "path to the redfish credential file")
)

func healthProbe(w http.ResponseWriter, req *http.Request) {
Expand Down Expand Up @@ -154,9 +156,10 @@ func main() {
config.SetEnabledHardwareCounterMetrics(*exposeHardwareCounterMetrics)
config.SetEnabledGPU(*enableGPU)
config.EnabledMSR = *enabledMSR

config.SetKubeConfig(*kubeconfig)
config.SetEnableAPIServer(*apiserverEnabled)
if *kernelSourceDirPath != "" {
if kernelSourceDirPath != nil && len(*kernelSourceDirPath) > 0 {
if err := config.SetKernelSourceDir(*kernelSourceDirPath); err != nil {
klog.Warningf("failed to set kernel source dir to %q: %v", *kernelSourceDirPath, err)
}
Expand All @@ -170,9 +173,15 @@ func main() {
}
klog.Infof("EnabledBPFBatchDelete: %v", config.EnabledBPFBatchDelete)

// set redfish credential file path
if *redfishCredFilePath != "" {
config.SetRedfishCredFilePath(*redfishCredFilePath)
}

config.LogConfigs()

components.InitPowerImpl()
platform.InitPowerImpl()

collector_metric.InitAvailableParamAndMetrics()

Expand Down
10 changes: 9 additions & 1 deletion manifests/config/exporter/exporter.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ data:
ENABLE_PROCESS_METRICS: "false"
CPU_ARCH_OVERRIDE: ""
CGROUP_METRICS: '*'
REDFISH_PROBE_INTERVAL_IN_SECONDS: "60"
REDFISH_SKIP_SSL_VERIFY: "true"
MODEL_CONFIG: |
CONTAINER_COMPONENTS_ESTIMATOR=false
# by default we use buildin weight file
Expand Down Expand Up @@ -67,7 +69,7 @@ spec:
- /bin/sh
- -c
args:
- /usr/bin/kepler -v=$(KEPLER_LOG_LEVEL) -kernel-source-dir=/usr/share/kepler/kernel_sources
- /usr/bin/kepler -v=$(KEPLER_LOG_LEVEL) -kernel-source-dir=/usr/share/kepler/kernel_sources -redfish-cred-file-path=/etc/redfish/redfish.csv
ports:
- containerPort: 9102
name: http
Expand All @@ -91,6 +93,9 @@ spec:
- name: cfm
mountPath: /etc/kepler/kepler.config
readOnly: true
- name: redfish
mountPath: /etc/redfish
readOnly: true
env:
- name: NODE_IP
valueFrom:
Expand All @@ -116,6 +121,9 @@ spec:
- name: cfm
configMap:
name: kepler-cfm
- name: redfish
secret:
secretName: redfish
---
kind: Service
apiVersion: v1
Expand Down
6 changes: 5 additions & 1 deletion manifests/config/exporter/kustomization.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ patchesStrategicMerge: []
# add this line for rootless patch
# - ./patch/patch-rootless.yaml

secretGenerator:
- name: redfish
files:
- ./redfish.csv

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
Expand Down Expand Up @@ -47,4 +51,4 @@ vars:
fieldpath: data.KEPLER_LOG_LEVEL

configurations:
- ./kustomizeconfig.yaml
- ./kustomizeconfig.yaml
1 change: 1 addition & 0 deletions manifests/config/exporter/redfish.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
your_kubelet_node_name,redfish_username,redfish_password,https://redfish_ip_or_hostname
2 changes: 1 addition & 1 deletion pkg/collector/metric/node_metric.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ const (
)

var (
NodeName = getNodeName()
NodeName = GetNodeName()
NodeCPUArchitecture = getCPUArch()
NodeCPUPackageMap = getCPUPackageMap()

Expand Down
2 changes: 1 addition & 1 deletion pkg/collector/metric/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ func isCounterStatEnabled(label string) bool {
return false
}

func getNodeName() string {
func GetNodeName() string {
if nodeName := os.Getenv("NODE_NAME"); nodeName != "" {
return nodeName
}
Expand Down
8 changes: 5 additions & 3 deletions pkg/collector/prometheus_collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/sustainable-computing-io/kepler/pkg/bpfassets/attacher"
collector_metric "github.com/sustainable-computing-io/kepler/pkg/collector/metric"
"github.com/sustainable-computing-io/kepler/pkg/config"
"github.com/sustainable-computing-io/kepler/pkg/power/platform"
)

const (
Expand Down Expand Up @@ -210,6 +211,7 @@ func (p *PrometheusCollector) Describe(ch chan<- *prometheus.Desc) {
ch <- p.nodeDesc.nodePackageJoulesTotal
ch <- p.nodeDesc.nodePlatformJoulesTotal
ch <- p.nodeDesc.nodeOtherComponentsJoulesTotal

if config.EnabledGPU {
ch <- p.nodeDesc.nodeGPUJoulesTotal
}
Expand Down Expand Up @@ -646,20 +648,20 @@ func (p *PrometheusCollector) updateNodeMetrics(wg *sync.WaitGroup, ch chan<- pr
idlePower,
collector_metric.NodeName, "idle",
)

powerSource := platform.GetPowerSource()
dynPower = (float64(p.NodeMetrics.GetSumAggrDynEnergyFromAllSources(collector_metric.PLATFORM)) / miliJouleToJoule)
ch <- prometheus.MustNewConstMetric(
p.nodeDesc.nodePlatformJoulesTotal,
prometheus.CounterValue,
dynPower,
collector_metric.NodeName, "acpi", "dynamic",
collector_metric.NodeName, powerSource, "dynamic",
)
idlePower = (float64(p.NodeMetrics.GetSumAggrIdleEnergyromAllSources(collector_metric.PLATFORM)) / miliJouleToJoule)
ch <- prometheus.MustNewConstMetric(
p.nodeDesc.nodePlatformJoulesTotal,
prometheus.CounterValue,
idlePower,
collector_metric.NodeName, "acpi", "idle",
collector_metric.NodeName, powerSource, "idle",
)

if config.EnabledGPU {
Expand Down
34 changes: 34 additions & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@ var (
// dir of kernel sources for bcc
kernelSourceDirs = []string{}

// redfish cred file path
redfishCredFilePath string
redfishProbeIntervalInSeconds = getConfig("REDFISH_PROBE_INTERVAL_IN_SECONDS", "60")
redfishSkipSSLVerify = getBoolConfig("REDFISH_SKIP_SSL_VERIFY", true)

////////////////////////////////////
ModelServerEnable = getBoolConfig("MODEL_SERVER_ENABLE", false)
ModelServerEndpoint = SetModelServerReqEndpoint()
Expand Down Expand Up @@ -189,6 +194,35 @@ func GetKernelSourceDirs() []string {
return kernelSourceDirs
}

func SetRedfishCredFilePath(credFilePath string) {
redfishCredFilePath = credFilePath
}

func GetRedfishCredFilePath() string {
return redfishCredFilePath
}

func SetRedfishProbeIntervalInSeconds(interval string) {
redfishProbeIntervalInSeconds = interval
}

func GetRedfishProbeIntervalInSeconds() int {
// convert string "redfishProbeIntervalInSeconds" to int
probeInterval, err := strconv.Atoi(redfishProbeIntervalInSeconds)
if err != nil {
klog.Warning("failed to convert redfishProbeIntervalInSeconds to int", err)
return 60
}
return probeInterval
}
func SetRedfishSkipSSLVerify(skipSSLVerify bool) {
redfishSkipSSLVerify = skipSSLVerify
}

func GetRedfishSkipSSLVerify() bool {
return redfishSkipSSLVerify
}

func SetModelServerReqEndpoint() (modelServerReqEndpoint string) {
modelServerURL := getConfig("MODEL_SERVER_URL", modelServerService)
if modelServerURL == modelServerService {
Expand Down
110 changes: 110 additions & 0 deletions pkg/nodecred/csv_cred.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
Copyright 2023.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package nodecred

import (
"encoding/csv"
"fmt"
"os"

metric_util "github.com/sustainable-computing-io/kepler/pkg/collector/metric"

"k8s.io/klog/v2"
)

// csvNodeCredImpl is the implementation of NodeCred using on disk file
// the file is in the format of
// node1,admin,password,localhost
// node2,admin,password,localhost
// node3,admin,password,localhost
type csvNodeCred struct {
}

var (
credMap map[string]string
)

func (c csvNodeCred) GetNodeCredByNodeName(nodeName, target string) (map[string]string, error) {
if credMap == nil {
return nil, fmt.Errorf("credential is not set")
} else if target == "redfish" {
cred := make(map[string]string)
cred["redfish_username"] = credMap["redfish_username"]
cred["redfish_password"] = credMap["redfish_password"]
cred["redfish_host"] = credMap["redfish_host"]
if cred["redfish_username"] == "" || cred["redfish_password"] == "" || cred["redfish_host"] == "" {
return nil, fmt.Errorf("no credential found")
}
return cred, nil
}

return nil, fmt.Errorf("no credential found for target %s", target)
}

func (c csvNodeCred) IsSupported(info map[string]string) bool {
// read redfish_cred_file_path from info
filePath := info["redfish_cred_file_path"]
if filePath == "" {
return false
} else {
nodeName := metric_util.GetNodeName()
// read file from filePath
userName, password, host, err := readCSVFile(filePath, nodeName)
if err != nil {
klog.V(5).Infof("failed to read csv file: %v", err)
return false
}
klog.V(5).Infof("read csv file successfully")
credMap = make(map[string]string)
credMap["redfish_username"] = userName
credMap["redfish_password"] = password
credMap["redfish_host"] = host
}
return true
}

func readCSVFile(filePath, nodeName string) (userName, password, host string, err error) {
// Open the CSV file
file, err := os.Open(filePath)
if err != nil {
fmt.Println("Error opening the file:", err)
return
}
defer file.Close()

// Create a new CSV reader
reader := csv.NewReader(file)

// Read all rows from the CSV file
rows, err := reader.ReadAll()
if err != nil {
fmt.Println("Error reading CSV:", err)
return
}

// Iterate over each row and check if the node name matches
for _, row := range rows {
if row[0] == nodeName && len(row) >= 4 {
userName = row[1]
password = row[2]
host = row[3]
return userName, password, host, nil
}
}
err = fmt.Errorf("node name %s not found in file %s", nodeName, filePath)
return
}
Loading

0 comments on commit 6a9d195

Please sign in to comment.