Skip to content

Commit 944efce

Browse files
committed
add code for retrieving kernel modules
1 parent 5953625 commit 944efce

File tree

3 files changed

+167
-0
lines changed

3 files changed

+167
-0
lines changed

pkg/util/metrics/system/common.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/*
2+
Copyright 2020 The Kubernetes Authors All rights reserved.
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
http://www.apache.org/licenses/LICENSE-2.0
7+
Unless required by applicable law or agreed to in writing, software
8+
distributed under the License is distributed on an "AS IS" BASIS,
9+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
See the License for the specific language governing permissions and
11+
limitations under the License.
12+
*/
13+
14+
package system
15+
16+
import (
17+
"bufio"
18+
"os"
19+
)
20+
21+
// ReadFile reads contents from a file and returns lines.
22+
func ReadFile(filename string) ([]string, error) {
23+
file, err := os.Open(filename)
24+
if err != nil {
25+
return nil, err
26+
}
27+
defer file.Close()
28+
29+
var result []string
30+
s := bufio.NewScanner(file)
31+
for s.Scan() {
32+
result = append(result, s.Text())
33+
}
34+
if s.Err() != nil {
35+
return nil, err
36+
}
37+
return result, nil
38+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*
2+
Copyright 2020 The Kubernetes Authors All rights reserved.
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
http://www.apache.org/licenses/LICENSE-2.0
7+
Unless required by applicable law or agreed to in writing, software
8+
distributed under the License is distributed on an "AS IS" BASIS,
9+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
See the License for the specific language governing permissions and
11+
limitations under the License.
12+
*/
13+
14+
package system
15+
16+
import (
17+
"encoding/json"
18+
"fmt"
19+
"strconv"
20+
"strings"
21+
)
22+
23+
type ModuleStat struct {
24+
ModuleName string `json:"moduleName"`
25+
Instances uint64 `json:"instances"`
26+
Proprietary bool `json:"proprietary"`
27+
OutOfTree bool `json:"outOfTree"`
28+
Unsigned bool `json:"unsigned"`
29+
}
30+
31+
func (d ModuleStat) String() string {
32+
s, _ := json.Marshal(d)
33+
return string(s)
34+
}
35+
36+
// Module returns all the kernel modules and their
37+
// usage. It is read from cat /proc/modules.
38+
func Modules() ([]ModuleStat, error) {
39+
filename := "/proc/modules"
40+
lines, err := ReadFile(filename)
41+
if err != nil {
42+
return nil, fmt.Errorf("Error reading the contents of %s: %s", filename, err)
43+
}
44+
var result = make([]ModuleStat, 0, len(lines))
45+
46+
/* a line of /proc/modules has the following structure
47+
nf_nat 61440 2 xt_MASQUERADE,iptable_nat, Live 0x0000000000000000 (O)
48+
(1) (2) (3) (4) (5) (6) (7)
49+
(1) name of the module
50+
(2) memory size of the module, in bytes
51+
(3) instances of the module are currently loaded
52+
(4) module dependencies
53+
(5) load state of the module: live, loading or unloading
54+
(6) memory offset for the loaded module.
55+
(7) return a string to represent the kernel taint state. (used here: "P" - Proprietary, "O" - out of tree kernel module, "E" - unsigned module
56+
*/
57+
for _, line := range lines {
58+
fields := strings.Fields(line)
59+
moduleName := fields[0] // name of the module
60+
numberOfInstances, err :=
61+
strconv.ParseUint((fields[1]), 10, 64) // instances of the module are currently loaded
62+
if err != nil {
63+
return nil, err
64+
}
65+
66+
var isProprietary = false
67+
var isOutofTree = false
68+
var isUnsigned = false
69+
// if the len of the fields is greater than 6, then the kernel taint state is available.
70+
if len(fields) > 6 {
71+
isProprietary = strings.Contains(fields[6], "P")
72+
isOutofTree = strings.Contains(fields[6], "O")
73+
isUnsigned = strings.Contains(fields[6], "E")
74+
}
75+
var stats = ModuleStat{
76+
ModuleName: moduleName,
77+
Instances: numberOfInstances,
78+
Proprietary: isProprietary,
79+
OutOfTree: isOutofTree,
80+
Unsigned: isUnsigned,
81+
}
82+
result = append(result, stats)
83+
}
84+
return result, nil
85+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/*
2+
Copyright 2019 The Kubernetes Authors All rights reserved.
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
http://www.apache.org/licenses/LICENSE-2.0
7+
Unless required by applicable law or agreed to in writing, software
8+
distributed under the License is distributed on an "AS IS" BASIS,
9+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
See the License for the specific language governing permissions and
11+
limitations under the License.
12+
*/
13+
14+
package system
15+
16+
import (
17+
"fmt"
18+
"testing"
19+
20+
"github.com/stretchr/testify/assert"
21+
)
22+
23+
func TestModules(t *testing.T) {
24+
modules, err := Modules()
25+
if err != nil {
26+
t.Errorf("error %v", err)
27+
}
28+
if modules == nil {
29+
t.Error("Error retrieving modules")
30+
}
31+
}
32+
33+
func TestModuleStat_String(t *testing.T) {
34+
v := ModuleStat{
35+
ModuleName: "test",
36+
Instances: 2,
37+
OutOfTree: false,
38+
Unsigned: false,
39+
}
40+
e := `{"moduleName":"test","instances":2,"proprietary":false,"outOfTree":false,"unsigned":false}`
41+
assert.Equal(t,
42+
e, fmt.Sprintf("%v", v), "ModuleStat string is invalid: %v", v)
43+
44+
}

0 commit comments

Comments
 (0)