From 944efce3a68a39649f1276a553ad131dcc92f33b Mon Sep 17 00:00:00 2001 From: varsha teratipally Date: Fri, 13 Nov 2020 03:16:14 +0000 Subject: [PATCH] add code for retrieving kernel modules --- pkg/util/metrics/system/common.go | 38 +++++++++ pkg/util/metrics/system/module_stats.go | 85 ++++++++++++++++++++ pkg/util/metrics/system/module_stats_test.go | 44 ++++++++++ 3 files changed, 167 insertions(+) create mode 100644 pkg/util/metrics/system/common.go create mode 100644 pkg/util/metrics/system/module_stats.go create mode 100644 pkg/util/metrics/system/module_stats_test.go diff --git a/pkg/util/metrics/system/common.go b/pkg/util/metrics/system/common.go new file mode 100644 index 00000000..a2e31dc8 --- /dev/null +++ b/pkg/util/metrics/system/common.go @@ -0,0 +1,38 @@ +/* +Copyright 2020 The Kubernetes Authors All rights reserved. +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 system + +import ( + "bufio" + "os" +) + +// ReadFile reads contents from a file and returns lines. +func ReadFile(filename string) ([]string, error) { + file, err := os.Open(filename) + if err != nil { + return nil, err + } + defer file.Close() + + var result []string + s := bufio.NewScanner(file) + for s.Scan() { + result = append(result, s.Text()) + } + if s.Err() != nil { + return nil, err + } + return result, nil +} diff --git a/pkg/util/metrics/system/module_stats.go b/pkg/util/metrics/system/module_stats.go new file mode 100644 index 00000000..80a114fd --- /dev/null +++ b/pkg/util/metrics/system/module_stats.go @@ -0,0 +1,85 @@ +/* +Copyright 2020 The Kubernetes Authors All rights reserved. +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 system + +import ( + "encoding/json" + "fmt" + "strconv" + "strings" +) + +type ModuleStat struct { + ModuleName string `json:"moduleName"` + Instances uint64 `json:"instances"` + Proprietary bool `json:"proprietary"` + OutOfTree bool `json:"outOfTree"` + Unsigned bool `json:"unsigned"` +} + +func (d ModuleStat) String() string { + s, _ := json.Marshal(d) + return string(s) +} + +// Module returns all the kernel modules and their +// usage. It is read from cat /proc/modules. +func Modules() ([]ModuleStat, error) { + filename := "/proc/modules" + lines, err := ReadFile(filename) + if err != nil { + return nil, fmt.Errorf("Error reading the contents of %s: %s", filename, err) + } + var result = make([]ModuleStat, 0, len(lines)) + + /* a line of /proc/modules has the following structure + nf_nat 61440 2 xt_MASQUERADE,iptable_nat, Live 0x0000000000000000 (O) + (1) (2) (3) (4) (5) (6) (7) + (1) name of the module + (2) memory size of the module, in bytes + (3) instances of the module are currently loaded + (4) module dependencies + (5) load state of the module: live, loading or unloading + (6) memory offset for the loaded module. + (7) return a string to represent the kernel taint state. (used here: "P" - Proprietary, "O" - out of tree kernel module, "E" - unsigned module + */ + for _, line := range lines { + fields := strings.Fields(line) + moduleName := fields[0] // name of the module + numberOfInstances, err := + strconv.ParseUint((fields[1]), 10, 64) // instances of the module are currently loaded + if err != nil { + return nil, err + } + + var isProprietary = false + var isOutofTree = false + var isUnsigned = false + // if the len of the fields is greater than 6, then the kernel taint state is available. + if len(fields) > 6 { + isProprietary = strings.Contains(fields[6], "P") + isOutofTree = strings.Contains(fields[6], "O") + isUnsigned = strings.Contains(fields[6], "E") + } + var stats = ModuleStat{ + ModuleName: moduleName, + Instances: numberOfInstances, + Proprietary: isProprietary, + OutOfTree: isOutofTree, + Unsigned: isUnsigned, + } + result = append(result, stats) + } + return result, nil +} diff --git a/pkg/util/metrics/system/module_stats_test.go b/pkg/util/metrics/system/module_stats_test.go new file mode 100644 index 00000000..717c94d0 --- /dev/null +++ b/pkg/util/metrics/system/module_stats_test.go @@ -0,0 +1,44 @@ +/* +Copyright 2019 The Kubernetes Authors All rights reserved. +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 system + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestModules(t *testing.T) { + modules, err := Modules() + if err != nil { + t.Errorf("error %v", err) + } + if modules == nil { + t.Error("Error retrieving modules") + } +} + +func TestModuleStat_String(t *testing.T) { + v := ModuleStat{ + ModuleName: "test", + Instances: 2, + OutOfTree: false, + Unsigned: false, + } + e := `{"moduleName":"test","instances":2,"proprietary":false,"outOfTree":false,"unsigned":false}` + assert.Equal(t, + e, fmt.Sprintf("%v", v), "ModuleStat string is invalid: %v", v) + +}