• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

k8snetworkplumbingwg / sriov-network-operator / 3751025296

pending completion
3751025296

Pull #365

github

GitHub
Merge 421284b55 into 788d76f7e
Pull Request #365: Implementation for new systemd configuration method

958 of 958 new or added lines in 18 files covered. (100.0%)

1971 of 8330 relevant lines covered (23.66%)

0.27 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

17.34
/pkg/host/host.go
1
package host
2

3
import (
4
        "fmt"
5
        "os"
6
        "strings"
7

8
        "github.com/golang/glog"
9

10
        "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/utils"
11
)
12

13
const (
14
        hostPathFromDaemon    = "/host"
15
        redhatReleaseFile     = "/etc/redhat-release"
16
        rhelRDMAConditionFile = "/usr/libexec/rdma-init-kernel"
17
        rhelRDMAServiceName   = "rdma"
18
        rhelPackageManager    = "yum"
19

20
        ubuntuRDMAConditionFile = "/usr/sbin/rdma-ndd"
21
        ubuntuRDMAServiceName   = "rdma-ndd"
22
        ubuntuPackageManager    = "apt-get"
23

24
        genericOSReleaseFile = "/etc/os-release"
25
)
26

27
//go:generate ../../bin/mockgen -destination mock/mock_host.go -source host.go
28
// Contains all the host manipulation functions
29
type HostManagerInterface interface {
30
        TryEnableTun()
31
        TryEnableVhostNet()
32
        TryEnableRdma() (bool, error)
33

34
        // private functions
35
        // part of the interface for the mock generation
36
        LoadKernelModule(name string, args ...string) error
37
        isRHELSystem() (bool, error)
38
        isUbuntuSystem() (bool, error)
39
        isCoreOS() (bool, error)
40
        rdmaIsLoaded() (bool, error)
41
        enableRDMA(string, string, string) (bool, error)
42
        installRDMA(string) error
43
        triggerUdevEvent() error
44
        enableRDMAOnRHELMachine() (bool, error)
45
        getOSPrettyName() (string, error)
46
}
47

48
type HostManager struct {
49
        RunOnHost bool
50
        cmd       utils.CommandInterface
51
}
52

53
func NewHostManager(runOnHost bool) HostManagerInterface {
1✔
54
        return &HostManager{
1✔
55
                RunOnHost: runOnHost,
1✔
56
                cmd:       &utils.Command{},
1✔
57
        }
1✔
58
}
1✔
59

60
func (h *HostManager) LoadKernelModule(name string, args ...string) error {
1✔
61
        glog.Infof("LoadKernelModule(): try to load kernel module %s with arguments '%s'", name, args)
1✔
62
        chrootDefinition := getChrootExtention(h.RunOnHost)
1✔
63
        cmdArgs := strings.Join(args, " ")
1✔
64

1✔
65
        // check if the driver is already loaded in to the system
1✔
66
        stdout, stderr, err := h.cmd.Run("/bin/sh", "-c", fmt.Sprintf("%s lsmod | grep \"^%s\"", chrootDefinition, name))
1✔
67
        if err != nil && stderr.Len() != 0 {
1✔
68
                glog.Errorf("LoadKernelModule(): failed to load kernel module %s with arguments '%s': error: %v stderr %s", name, args, err, stderr.String())
×
69
                return err
×
70
        }
×
71
        glog.V(2).Infof("LoadKernelModule(): %v", stdout.String())
1✔
72
        if stderr.Len() != 0 {
1✔
73
                glog.Errorf("LoadKernelModule(): failed to load kernel module %s with arguments '%s': %v", name, args, stderr.String())
×
74
                return fmt.Errorf(stderr.String())
×
75
        }
×
76

77
        if stdout.Len() != 0 {
1✔
78
                glog.Infof("LoadKernelModule(): kernel module %s already loaded", name)
×
79
                return nil
×
80
        }
×
81

82
        stdout, stderr, err = h.cmd.Run("/bin/sh", "-c", fmt.Sprintf("%s modprobe %s %s", chrootDefinition, name, cmdArgs))
1✔
83
        if err != nil {
2✔
84
                glog.Errorf("LoadKernelModule(): failed to load kernel module %s with arguments '%s': %v", name, args, err)
1✔
85
                return err
1✔
86
        }
1✔
87
        return nil
×
88
}
89

90
func (h *HostManager) TryEnableTun() {
1✔
91
        if err := h.LoadKernelModule("tun"); err != nil {
2✔
92
                glog.Errorf("tryEnableTun(): TUN kernel module not loaded: %v", err)
1✔
93
        }
1✔
94
}
95

96
func (h *HostManager) TryEnableVhostNet() {
1✔
97
        if err := h.LoadKernelModule("vhost_net"); err != nil {
2✔
98
                glog.Errorf("tryEnableVhostNet(): VHOST_NET kernel module not loaded: %v", err)
1✔
99
        }
1✔
100
}
101

102
func (h *HostManager) TryEnableRdma() (bool, error) {
1✔
103
        glog.V(2).Infof("tryEnableRdma()")
1✔
104
        chrootDefinition := getChrootExtention(h.RunOnHost)
1✔
105

1✔
106
        // check if the driver is already loaded in to the system
1✔
107
        _, stderr, mlx4Err := h.cmd.Run("/bin/sh", "-c", fmt.Sprintf("grep --quiet 'mlx4_en' <(%s lsmod)", chrootDefinition))
1✔
108
        if mlx4Err != nil && stderr.Len() != 0 {
1✔
109
                glog.Errorf("tryEnableRdma(): failed to check for kernel module 'mlx4_en': error: %v stderr %s", mlx4Err, stderr.String())
×
110
                return false, fmt.Errorf(stderr.String())
×
111
        }
×
112

113
        _, stderr, mlx5Err := h.cmd.Run("/bin/sh", "-c", fmt.Sprintf("grep --quiet 'mlx5_core' <(%s lsmod)", chrootDefinition))
1✔
114
        if mlx5Err != nil && stderr.Len() != 0 {
1✔
115
                glog.Errorf("tryEnableRdma(): failed to check for kernel module 'mlx5_core': error: %v stderr %s", mlx5Err, stderr.String())
×
116
                return false, fmt.Errorf(stderr.String())
×
117
        }
×
118

119
        if mlx4Err != nil && mlx5Err != nil {
2✔
120
                glog.Errorf("tryEnableRdma(): no RDMA capable devices")
1✔
121
                return false, nil
1✔
122
        }
1✔
123

124
        isRhelSystem, err := h.isRHELSystem()
×
125
        if err != nil {
×
126
                glog.Errorf("tryEnableRdma(): failed to check if the machine is base on RHEL: %v", err)
×
127
                return false, err
×
128
        }
×
129

130
        // RHEL check
131
        if isRhelSystem {
×
132
                return h.enableRDMAOnRHELMachine()
×
133
        }
×
134

135
        isUbuntuSystem, err := h.isUbuntuSystem()
×
136
        if err != nil {
×
137
                glog.Errorf("tryEnableRdma(): failed to check if the machine is base on Ubuntu: %v", err)
×
138
                return false, err
×
139
        }
×
140

141
        if isUbuntuSystem {
×
142
                return h.enableRDMAOnUbuntuMachine()
×
143
        }
×
144

145
        osName, err := h.getOSPrettyName()
×
146
        if err != nil {
×
147
                glog.Errorf("tryEnableRdma(): failed to check OS name: %v", err)
×
148
                return false, err
×
149
        }
×
150

151
        glog.Errorf("tryEnableRdma(): Unsupported OS: %s", osName)
×
152
        return false, fmt.Errorf("unable to load RDMA unsupported OS: %s", osName)
×
153
}
154

155
func (h *HostManager) enableRDMAOnRHELMachine() (bool, error) {
×
156
        glog.Infof("enableRDMAOnRHELMachine()")
×
157
        isCoreOsSystem, err := h.isCoreOS()
×
158
        if err != nil {
×
159
                glog.Errorf("enableRDMAOnRHELMachine(): failed to check if the machine runs CoreOS: %v", err)
×
160
                return false, err
×
161
        }
×
162

163
        // CoreOS check
164
        if isCoreOsSystem {
×
165
                isRDMALoaded, err := h.rdmaIsLoaded()
×
166
                if err != nil {
×
167
                        glog.Errorf("enableRDMAOnRHELMachine(): failed to check if RDMA kernel modules are loaded: %v", err)
×
168
                        return false, err
×
169
                }
×
170

171
                return isRDMALoaded, nil
×
172
        }
173

174
        // RHEL
175
        glog.Infof("enableRDMAOnRHELMachine(): enabling RDMA on RHEL machine")
×
176
        isRDMAEnable, err := h.enableRDMA(rhelRDMAConditionFile, rhelRDMAServiceName, rhelPackageManager)
×
177
        if err != nil {
×
178
                glog.Errorf("enableRDMAOnRHELMachine(): failed to enable RDMA on RHEL machine: %v", err)
×
179
                return false, err
×
180
        }
×
181

182
        // check if we need to install rdma-core package
183
        if isRDMAEnable {
×
184
                isRDMALoaded, err := h.rdmaIsLoaded()
×
185
                if err != nil {
×
186
                        glog.Errorf("enableRDMAOnRHELMachine(): failed to check if RDMA kernel modules are loaded: %v", err)
×
187
                        return false, err
×
188
                }
×
189

190
                // if ib kernel module is not loaded trigger a loading
191
                if isRDMALoaded {
×
192
                        err = h.triggerUdevEvent()
×
193
                        if err != nil {
×
194
                                glog.Errorf("enableRDMAOnRHELMachine() failed to trigger udev event: %v", err)
×
195
                                return false, err
×
196
                        }
×
197
                }
198
        }
199

200
        return true, nil
×
201
}
202

203
func (h *HostManager) enableRDMAOnUbuntuMachine() (bool, error) {
×
204
        glog.Infof("enableRDMAOnUbuntuMachine(): enabling RDMA on RHEL machine")
×
205
        isRDMAEnable, err := h.enableRDMA(ubuntuRDMAConditionFile, ubuntuRDMAServiceName, ubuntuPackageManager)
×
206
        if err != nil {
×
207
                glog.Errorf("enableRDMAOnUbuntuMachine(): failed to enable RDMA on Ubuntu machine: %v", err)
×
208
                return false, err
×
209
        }
×
210

211
        // check if we need to install rdma-core package
212
        if isRDMAEnable {
×
213
                isRDMALoaded, err := h.rdmaIsLoaded()
×
214
                if err != nil {
×
215
                        glog.Errorf("enableRDMAOnUbuntuMachine(): failed to check if RDMA kernel modules are loaded: %v", err)
×
216
                        return false, err
×
217
                }
×
218

219
                // if ib kernel module is not loaded trigger a loading
220
                if isRDMALoaded {
×
221
                        err = h.triggerUdevEvent()
×
222
                        if err != nil {
×
223
                                glog.Errorf("enableRDMAOnUbuntuMachine() failed to trigger udev event: %v", err)
×
224
                                return false, err
×
225
                        }
×
226
                }
227
        }
228

229
        return true, nil
×
230
}
231

232
func (h *HostManager) isRHELSystem() (bool, error) {
×
233
        glog.Infof("isRHELSystem(): checking for RHEL machine")
×
234
        path := redhatReleaseFile
×
235
        if !h.RunOnHost {
×
236
                path = hostPathFromDaemon + path
×
237
        }
×
238
        if _, err := os.Stat(path); err != nil {
×
239
                if os.IsNotExist(err) {
×
240
                        glog.V(2).Infof("isRHELSystem() not a RHEL machine")
×
241
                        return false, nil
×
242
                }
×
243

244
                glog.Errorf("isRHELSystem() failed to check for os release file on path %s: %v", path, err)
×
245
                return false, err
×
246
        }
247

248
        return true, nil
×
249
}
250

251
func (h *HostManager) isCoreOS() (bool, error) {
×
252
        glog.Infof("isCoreOS(): checking for CoreOS machine")
×
253
        path := redhatReleaseFile
×
254
        if !h.RunOnHost {
×
255
                path = hostPathFromDaemon + path
×
256
        }
×
257
        data, err := os.ReadFile(path)
×
258
        if err != nil {
×
259
                glog.Errorf("isCoreOS(): failed to read RHEL release file on path %s: %v", path, err)
×
260
                return false, err
×
261
        }
×
262

263
        if strings.Contains(string(data), "CoreOS") {
×
264
                return true, nil
×
265
        }
×
266

267
        return false, nil
×
268
}
269

270
func (h *HostManager) isUbuntuSystem() (bool, error) {
×
271
        glog.Infof("isUbuntuSystem(): checking for Ubuntu machine")
×
272
        path := genericOSReleaseFile
×
273
        if !h.RunOnHost {
×
274
                path = hostPathFromDaemon + path
×
275
        }
×
276
        if _, err := os.Stat(path); err != nil {
×
277
                if os.IsNotExist(err) {
×
278
                        glog.Errorf("isUbuntuSystem() os-release on path %s doesn't exist: %v", path, err)
×
279
                        return false, err
×
280
                }
×
281

282
                glog.Errorf("isUbuntuSystem() failed to check for os release file on path %s: %v", path, err)
×
283
                return false, err
×
284
        }
285

286
        stdout, stderr, err := h.cmd.Run("/bin/sh", "-c", fmt.Sprintf("grep -i --quiet 'ubuntu' %s", path))
×
287
        if err != nil && stderr.Len() != 0 {
×
288
                glog.Errorf("isUbuntuSystem(): failed to check for ubuntu operating system name in os-releasae file: error: %v stderr %s", err, stderr.String())
×
289
                return false, fmt.Errorf(stderr.String())
×
290
        }
×
291

292
        if stdout.Len() > 0 {
×
293
                return true, nil
×
294
        }
×
295

296
        return false, nil
×
297
}
298

299
func (h *HostManager) rdmaIsLoaded() (bool, error) {
×
300
        glog.V(2).Infof("rdmaIsLoaded()")
×
301
        chrootDefinition := getChrootExtention(h.RunOnHost)
×
302

×
303
        // check if the driver is already loaded in to the system
×
304
        _, stderr, err := h.cmd.Run("/bin/sh", "-c", fmt.Sprintf("grep --quiet '\\(^ib\\|^rdma\\)' <(%s lsmod)", chrootDefinition))
×
305
        if err != nil && stderr.Len() != 0 {
×
306
                glog.Errorf("rdmaIsLoaded(): fail to check if ib and rdma kernel modules are loaded: error: %v stderr %s", err, stderr.String())
×
307
                return false, fmt.Errorf(stderr.String())
×
308
        }
×
309

310
        if err != nil {
×
311
                return false, nil
×
312
        }
×
313

314
        return true, nil
×
315
}
316

317
func (h *HostManager) enableRDMA(conditionFilePath, serviceName, packageManager string) (bool, error) {
×
318
        path := conditionFilePath
×
319
        if !h.RunOnHost {
×
320
                path = hostPathFromDaemon + path
×
321
        }
×
322
        glog.Infof("enableRDMA(): checking for service file on path %s", path)
×
323

×
324
        if _, err := os.Stat(path); err != nil {
×
325
                if os.IsNotExist(err) {
×
326
                        glog.V(2).Infof("enableRDMA(): RDMA server doesn't exist")
×
327
                        err = h.installRDMA(packageManager)
×
328
                        if err != nil {
×
329
                                glog.Errorf("enableRDMA() failed to install RDMA package: %v", err)
×
330
                                return false, err
×
331
                        }
×
332

333
                        err = h.triggerUdevEvent()
×
334
                        if err != nil {
×
335
                                glog.Errorf("enableRDMA() failed to trigger udev event: %v", err)
×
336
                                return false, err
×
337
                        }
×
338

339
                        return false, nil
×
340
                }
341

342
                glog.Errorf("enableRDMA() failed to check for os release file on path %s: %v", path, err)
×
343
                return false, err
×
344
        }
345

346
        glog.Infof("enableRDMA(): service %s.service installed", serviceName)
×
347
        return true, nil
×
348
}
349

350
func (h *HostManager) installRDMA(packageManager string) error {
×
351
        glog.Infof("installRDMA(): installing RDMA")
×
352
        chrootDefinition := getChrootExtention(h.RunOnHost)
×
353

×
354
        stdout, stderr, err := h.cmd.Run("/bin/sh", "-c", fmt.Sprintf("%s %s install -y rdma-core", chrootDefinition, packageManager))
×
355
        if err != nil && stderr.Len() != 0 {
×
356
                glog.Errorf("installRDMA(): failed to install RDMA package output %s: error %v stderr %s", stdout.String(), err, stderr.String())
×
357
                return err
×
358
        }
×
359

360
        return nil
×
361
}
362

363
func (h *HostManager) triggerUdevEvent() error {
×
364
        glog.Infof("triggerUdevEvent(): installing RDMA")
×
365
        chrootDefinition := getChrootExtention(h.RunOnHost)
×
366

×
367
        _, stderr, err := h.cmd.Run("/bin/sh", "-c", fmt.Sprintf("%s modprobe -r mlx4_en && %s modprobe mlx4_en", chrootDefinition, chrootDefinition))
×
368
        if err != nil && stderr.Len() != 0 {
×
369
                glog.Errorf("installRDMA(): failed to reload mlx4_en kernel module: error %v stderr %s", err, stderr.String())
×
370
                return err
×
371
        }
×
372

373
        _, stderr, err = h.cmd.Run("/bin/sh", "-c", fmt.Sprintf("%s modprobe -r mlx5_core && %s modprobe mlx5_core", chrootDefinition, chrootDefinition))
×
374
        if err != nil && stderr.Len() != 0 {
×
375
                glog.Errorf("installRDMA(): failed to reload mlx5_core kernel module: error %v stderr %s", err, stderr.String())
×
376
                return err
×
377
        }
×
378

379
        return nil
×
380
}
381

382
func (h *HostManager) getOSPrettyName() (string, error) {
×
383
        path := genericOSReleaseFile
×
384
        if !h.RunOnHost {
×
385
                path = hostPathFromDaemon + path
×
386
        }
×
387
        glog.Infof("getOSPrettyName(): getting os name from os-release file")
×
388

×
389
        stdout, stderr, err := h.cmd.Run("/bin/sh", "-c", fmt.Sprintf("cat %s | grep PRETTY_NAME | cut -c 13-", path))
×
390
        if err != nil && stderr.Len() != 0 {
×
391
                glog.Errorf("isUbuntuSystem(): failed to check for ubuntu operating system name in os-releasae file: error: %v stderr %s", err, stderr.String())
×
392
                return "", fmt.Errorf(stderr.String())
×
393
        }
×
394

395
        if stdout.Len() > 0 {
×
396
                return stdout.String(), nil
×
397
        }
×
398

399
        return "", fmt.Errorf("failed to find pretty operating system name")
×
400
}
401

402
func getChrootExtention(runOnHost bool) string {
1✔
403
        if !runOnHost {
2✔
404
                return "chroot /host/"
1✔
405
        }
1✔
406
        return ""
×
407
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc