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

k8snetworkplumbingwg / sriov-network-operator / 10194187385

01 Aug 2024 07:44AM UTC coverage: 45.22% (+1.3%) from 43.968%
10194187385

Pull #746

github

web-flow
Merge f8cc3364c into 57e1e9056
Pull Request #746: Remove logic that installs rdma-core package

13 of 38 new or added lines in 5 files covered. (34.21%)

3 existing lines in 1 file now uncovered.

6528 of 14436 relevant lines covered (45.22%)

0.5 hits per line

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

74.6
/cmd/sriov-network-config-daemon/service.go
1
/*
2
Copyright 2023.
3

4
Licensed under the Apache License, Version 2.0 (the "License");
5
you may not use this file except in compliance with the License.
6
You may obtain a copy of the License at
7

8
        http://www.apache.org/licenses/LICENSE-2.0
9

10
Unless required by applicable law or agreed to in writing, software
11
distributed under the License is distributed on an "AS IS" BASIS,
12
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
See the License for the specific language governing permissions and
14
limitations under the License.
15
*/
16
package main
17

18
import (
19
        "errors"
20
        "fmt"
21
        "os"
22

23
        "github.com/go-logr/logr"
24
        "github.com/spf13/cobra"
25
        "sigs.k8s.io/controller-runtime/pkg/log"
26

27
        sriovv1 "github.com/k8snetworkplumbingwg/sriov-network-operator/api/v1"
28
        "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/consts"
29
        "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/helper"
30
        snolog "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/log"
31
        "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/platforms"
32
        plugin "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/plugins"
33
        "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/plugins/generic"
34
        "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/plugins/virtual"
35
        "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/systemd"
36
        "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/vars"
37
        "github.com/k8snetworkplumbingwg/sriov-network-operator/pkg/version"
38
)
39

40
const (
41
        PhasePre  = "pre"
42
        PhasePost = "post"
43
)
44

45
var (
46
        serviceCmd = &cobra.Command{
47
                Use:   "service",
48
                Short: "Starts SR-IOV service Config",
49
                Long:  "",
50
                RunE:  runServiceCmd,
51
        }
52
        phaseArg string
53

54
        newGenericPluginFunc  = generic.NewGenericPlugin
55
        newVirtualPluginFunc  = virtual.NewVirtualPlugin
56
        newHostHelpersFunc    = helper.NewDefaultHostHelpers
57
        newPlatformHelperFunc = platforms.NewDefaultPlatformHelper
58
)
59

60
func init() {
1✔
61
        rootCmd.AddCommand(serviceCmd)
1✔
62
        serviceCmd.Flags().StringVarP(&phaseArg, "phase", "p", PhasePre, fmt.Sprintf("configuration phase, supported values are: %s, %s", PhasePre, PhasePost))
1✔
63
}
1✔
64

65
// The service supports two configuration phases:
66
// * pre(default) - before the NetworkManager or systemd-networkd
67
// * post - after the NetworkManager or systemd-networkd
68
// "sriov-config" systemd unit is responsible for starting the service in the "pre" phase mode.
69
// "sriov-config-post-network" systemd unit starts the service in the "post" phase mode.
70
// The service may use different plugins for each phase and call different initialization flows.
71
// The "post" phase checks the completion status of the "pre" phase by reading the sriov result file.
72
// The "pre" phase should set "InProgress" status if it succeeds or "Failed" otherwise.
73
// If the result of the "pre" phase is different than "InProgress", then the "post" phase will not be executed
74
// and the execution result will be forcefully set to "Failed".
75
func runServiceCmd(cmd *cobra.Command, args []string) error {
1✔
76
        if phaseArg != PhasePre && phaseArg != PhasePost {
1✔
77
                return fmt.Errorf("invalid value for \"--phase\" argument, valid values are: %s, %s", PhasePre, PhasePost)
×
78
        }
×
79
        // init logger
80
        snolog.InitLog()
1✔
81
        setupLog := log.Log.WithName("sriov-config-service").WithValues("phase", phaseArg)
1✔
82

1✔
83
        setupLog.V(0).Info("Starting sriov-config-service", "version", version.Version)
1✔
84

1✔
85
        // Mark that we are running on host
1✔
86
        vars.UsingSystemdMode = true
1✔
87
        vars.InChroot = true
1✔
88

1✔
89
        sriovConf, err := readConf(setupLog)
1✔
90
        if err != nil {
1✔
91
                return updateSriovResultErr(setupLog, phaseArg, err)
×
92
        }
×
93
        setupLog.V(2).Info("sriov-config-service", "config", sriovConf)
1✔
94
        vars.DevMode = sriovConf.UnsupportedNics
1✔
95
        vars.ManageSoftwareBridges = sriovConf.ManageSoftwareBridges
1✔
96

1✔
97
        if err := initSupportedNics(); err != nil {
1✔
98
                return updateSriovResultErr(setupLog, phaseArg, fmt.Errorf("failed to initialize list of supported NIC ids: %v", err))
×
99
        }
×
100

101
        hostHelpers, err := newHostHelpersFunc()
1✔
102
        if err != nil {
1✔
103
                return updateSriovResultErr(setupLog, phaseArg, fmt.Errorf("failed to create hostHelpers: %v", err))
×
104
        }
×
105

106
        if phaseArg == PhasePre {
2✔
107
                err = phasePre(setupLog, sriovConf, hostHelpers)
1✔
108
        } else {
2✔
109
                err = phasePost(setupLog, sriovConf, hostHelpers)
1✔
110
        }
1✔
111
        if err != nil {
2✔
112
                return updateSriovResultErr(setupLog, phaseArg, err)
1✔
113
        }
1✔
114
        return updateSriovResultOk(setupLog, phaseArg)
1✔
115
}
116

117
func readConf(setupLog logr.Logger) (*systemd.SriovConfig, error) {
1✔
118
        nodeStateSpec, err := systemd.ReadConfFile()
1✔
119
        if err != nil {
1✔
120
                if _, err := os.Stat(systemd.SriovSystemdConfigPath); !errors.Is(err, os.ErrNotExist) {
×
121
                        return nil, fmt.Errorf("failed to read the sriov configuration file in path %s: %v", systemd.SriovSystemdConfigPath, err)
×
122
                }
×
123
                setupLog.Info("configuration file not found, use default config")
×
124
                nodeStateSpec = &systemd.SriovConfig{
×
125
                        Spec:            sriovv1.SriovNetworkNodeStateSpec{},
×
126
                        UnsupportedNics: false,
×
127
                        PlatformType:    consts.Baremetal,
×
128
                }
×
129
        }
130
        return nodeStateSpec, nil
1✔
131
}
132

133
func initSupportedNics() error {
1✔
134
        supportedNicIds, err := systemd.ReadSriovSupportedNics()
1✔
135
        if err != nil {
1✔
136
                return fmt.Errorf("failed to read list of supported nic ids: %v", err)
×
137
        }
×
138
        sriovv1.InitNicIDMapFromList(supportedNicIds)
1✔
139
        return nil
1✔
140
}
141

142
func phasePre(setupLog logr.Logger, conf *systemd.SriovConfig, hostHelpers helper.HostHelpersInterface) error {
1✔
143
        // make sure there is no stale result file to avoid situation when we
1✔
144
        // read outdated info in the Post phase when the Pre silently failed (should not happen)
1✔
145
        if err := systemd.RemoveSriovResult(); err != nil {
1✔
146
                return fmt.Errorf("failed to remove sriov result file: %v", err)
×
147
        }
×
148

149
        _, err := hostHelpers.CheckRDMAEnabled()
1✔
150
        if err != nil {
1✔
NEW
151
                setupLog.Error(err, "warning, failed to check RDMA state")
×
152
        }
×
153
        hostHelpers.TryEnableTun()
1✔
154
        hostHelpers.TryEnableVhostNet()
1✔
155

1✔
156
        return callPlugin(setupLog, PhasePre, conf, hostHelpers)
1✔
157
}
158

159
func phasePost(setupLog logr.Logger, conf *systemd.SriovConfig, hostHelpers helper.HostHelpersInterface) error {
1✔
160
        setupLog.V(0).Info("check result of the Pre phase")
1✔
161
        prePhaseResult, err := systemd.ReadSriovResult()
1✔
162
        if err != nil {
1✔
163
                return fmt.Errorf("failed to read result of the pre phase: %v", err)
×
164
        }
×
165
        if prePhaseResult.SyncStatus != consts.SyncStatusInProgress {
2✔
166
                return fmt.Errorf("unexpected result of the pre phase: %s, syncError: %s", prePhaseResult.SyncStatus, prePhaseResult.LastSyncError)
1✔
167
        }
1✔
168
        setupLog.V(0).Info("Pre phase succeed, continue execution")
1✔
169

1✔
170
        return callPlugin(setupLog, PhasePost, conf, hostHelpers)
1✔
171
}
172

173
func callPlugin(setupLog logr.Logger, phase string, conf *systemd.SriovConfig, hostHelpers helper.HostHelpersInterface) error {
1✔
174
        configPlugin, err := getPlugin(setupLog, phase, conf, hostHelpers)
1✔
175
        if err != nil {
1✔
176
                return err
×
177
        }
×
178

179
        if configPlugin == nil {
2✔
180
                setupLog.V(0).Info("no plugin for the platform for the current phase, skip calling", "platform", conf.PlatformType)
1✔
181
                return nil
1✔
182
        }
1✔
183

184
        nodeState, err := getNetworkNodeState(setupLog, conf, hostHelpers)
1✔
185
        if err != nil {
1✔
186
                return err
×
187
        }
×
188
        _, _, err = configPlugin.OnNodeStateChange(nodeState)
1✔
189
        if err != nil {
1✔
190
                return fmt.Errorf("failed to run OnNodeStateChange to update the plugin status %v", err)
×
191
        }
×
192

193
        if err = configPlugin.Apply(); err != nil {
2✔
194
                return fmt.Errorf("failed to apply configuration: %v", err)
1✔
195
        }
1✔
196
        setupLog.V(0).Info("plugin call succeed")
1✔
197
        return nil
1✔
198
}
199

200
func getPlugin(setupLog logr.Logger, phase string,
201
        conf *systemd.SriovConfig, hostHelpers helper.HostHelpersInterface) (plugin.VendorPlugin, error) {
1✔
202
        var (
1✔
203
                configPlugin plugin.VendorPlugin
1✔
204
                err          error
1✔
205
        )
1✔
206
        switch conf.PlatformType {
1✔
207
        case consts.Baremetal:
1✔
208
                switch phase {
1✔
209
                case PhasePre:
1✔
210
                        configPlugin, err = newGenericPluginFunc(hostHelpers, generic.WithSkipVFConfiguration())
1✔
211
                case PhasePost:
1✔
212
                        configPlugin, err = newGenericPluginFunc(hostHelpers)
1✔
213
                }
214
                if err != nil {
1✔
215
                        return nil, fmt.Errorf("failed to create generic plugin for %v", err)
×
216
                }
×
217
        case consts.VirtualOpenStack:
1✔
218
                switch phase {
1✔
219
                case PhasePre:
1✔
220
                        configPlugin, err = newVirtualPluginFunc(hostHelpers)
1✔
221
                        if err != nil {
1✔
222
                                return nil, fmt.Errorf("failed to create virtual plugin %v", err)
×
223
                        }
×
224
                case PhasePost:
1✔
225
                        setupLog.Info("skip post configuration phase for virtual cluster")
1✔
226
                        return nil, nil
1✔
227
                }
228
        }
229
        return configPlugin, nil
1✔
230
}
231

232
func getNetworkNodeState(setupLog logr.Logger, conf *systemd.SriovConfig,
233
        hostHelpers helper.HostHelpersInterface) (*sriovv1.SriovNetworkNodeState, error) {
1✔
234
        var (
1✔
235
                ifaceStatuses []sriovv1.InterfaceExt
1✔
236
                err           error
1✔
237
        )
1✔
238
        switch conf.PlatformType {
1✔
239
        case consts.Baremetal:
1✔
240
                ifaceStatuses, err = hostHelpers.DiscoverSriovDevices(hostHelpers)
1✔
241
                if err != nil {
1✔
242
                        return nil, fmt.Errorf("failed to discover sriov devices on the host:  %v", err)
×
243
                }
×
244
        case consts.VirtualOpenStack:
1✔
245
                platformHelper, err := newPlatformHelperFunc()
1✔
246
                if err != nil {
1✔
247
                        return nil, fmt.Errorf("failed to create platformHelpers")
×
248
                }
×
249
                err = platformHelper.CreateOpenstackDevicesInfo()
1✔
250
                if err != nil {
1✔
251
                        return nil, fmt.Errorf("failed to read OpenStack data: %v", err)
×
252
                }
×
253
                ifaceStatuses, err = platformHelper.DiscoverSriovDevicesVirtual()
1✔
254
                if err != nil {
1✔
255
                        return nil, fmt.Errorf("failed to discover devices: %v", err)
×
256
                }
×
257
        }
258
        return &sriovv1.SriovNetworkNodeState{
1✔
259
                Spec:   conf.Spec,
1✔
260
                Status: sriovv1.SriovNetworkNodeStateStatus{Interfaces: ifaceStatuses},
1✔
261
        }, nil
1✔
262
}
263

264
func updateSriovResultErr(setupLog logr.Logger, phase string, origErr error) error {
1✔
265
        setupLog.Error(origErr, "service call failed")
1✔
266
        err := updateResult(setupLog, consts.SyncStatusFailed, fmt.Sprintf("%s: %v", phase, origErr))
1✔
267
        if err != nil {
1✔
268
                return err
×
269
        }
×
270
        return origErr
1✔
271
}
272

273
func updateSriovResultOk(setupLog logr.Logger, phase string) error {
1✔
274
        setupLog.V(0).Info("service call succeed")
1✔
275
        syncStatus := consts.SyncStatusSucceeded
1✔
276
        if phase == PhasePre {
2✔
277
                syncStatus = consts.SyncStatusInProgress
1✔
278
        }
1✔
279
        return updateResult(setupLog, syncStatus, "")
1✔
280
}
281

282
func updateResult(setupLog logr.Logger, result, msg string) error {
1✔
283
        sriovResult := &systemd.SriovResult{
1✔
284
                SyncStatus:    result,
1✔
285
                LastSyncError: msg,
1✔
286
        }
1✔
287
        err := systemd.WriteSriovResult(sriovResult)
1✔
288
        if err != nil {
1✔
289
                setupLog.Error(err, "failed to write sriov result file", "content", *sriovResult)
×
290
                return fmt.Errorf("sriov-config-service failed to write sriov result file with content %v error: %v", *sriovResult, err)
×
291
        }
×
292
        setupLog.V(0).Info("result file updated", "SyncStatus", sriovResult.SyncStatus, "LastSyncError", msg)
1✔
293
        return nil
1✔
294
}
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