Skip to content

Commit 7c29f0a

Browse files
committed
nfd-worker: Watch features.d changes
Signed-off-by: Oleg Zhurakivskyy <oleg.zhurakivskyy@intel.com>
1 parent 04d835d commit 7c29f0a

File tree

3 files changed

+79
-3
lines changed

3 files changed

+79
-3
lines changed

pkg/nfd-worker/nfd-worker.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ type nfdWorker struct {
121121
k8sClient k8sclient.Interface
122122
nfdClient nfdclient.Interface
123123
stop chan struct{} // channel for signaling stop
124+
sourceEvent chan struct{} // channel for events from soures
124125
featureSources []source.FeatureSource
125126
labelSources []source.LabelSource
126127
ownerReference []metav1.OwnerReference
@@ -304,6 +305,12 @@ func (w *nfdWorker) Run() error {
304305
labelTrigger.Reset(w.config.Core.SleepInterval.Duration)
305306
defer labelTrigger.Stop()
306307

308+
w.sourceEvent = make(chan struct{})
309+
eventSources := source.GetAllEventSources()
310+
for _, s := range eventSources {
311+
s.SetChannel(w.sourceEvent)
312+
}
313+
307314
httpMux := http.NewServeMux()
308315

309316
// Register to metrics server
@@ -341,6 +348,12 @@ func (w *nfdWorker) Run() error {
341348
return err
342349
}
343350

351+
case <-w.sourceEvent:
352+
err = w.runFeatureDiscovery()
353+
if err != nil {
354+
return err
355+
}
356+
344357
case <-w.stop:
345358
klog.InfoS("shutting down nfd-worker")
346359
return nil

source/local/local.go

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626

2727
"k8s.io/klog/v2"
2828

29+
"github.com/fsnotify/fsnotify"
2930
nfdv1alpha1 "sigs.k8s.io/node-feature-discovery/api/nfd/v1alpha1"
3031
"sigs.k8s.io/node-feature-discovery/pkg/utils"
3132
"sigs.k8s.io/node-feature-discovery/source"
@@ -65,10 +66,11 @@ var (
6566
featureFilesDir = "/etc/kubernetes/node-feature-discovery/features.d/"
6667
)
6768

68-
// localSource implements the FeatureSource and LabelSource interfaces.
69+
// localSource implements the FeatureSource, LabelSource, EventSource interfaces.
6970
type localSource struct {
70-
features *nfdv1alpha1.Features
71-
config *Config
71+
features *nfdv1alpha1.Features
72+
config *Config
73+
fsWatcher *fsnotify.Watcher
7274
}
7375

7476
type Config struct {
@@ -87,6 +89,7 @@ var (
8789
_ source.FeatureSource = &src
8890
_ source.LabelSource = &src
8991
_ source.ConfigurableSource = &src
92+
_ source.EventSource = &src
9093
)
9194

9295
// Name method of the LabelSource interface
@@ -318,6 +321,47 @@ func getFileContent(fileName string) ([][]byte, error) {
318321
return lines, nil
319322
}
320323

324+
func (s *localSource) runNotifier(ch chan struct{}) {
325+
for {
326+
select {
327+
case event := <-s.fsWatcher.Events:
328+
if event.Op&fsnotify.Create == fsnotify.Create || event.Op&fsnotify.Write == fsnotify.Write || event.Op&fsnotify.Remove == fsnotify.Remove || event.Op&fsnotify.Rename == fsnotify.Rename || event.Op&fsnotify.Chmod == fsnotify.Chmod {
329+
klog.InfoS("fsnotify event", event)
330+
ch <- struct{}{}
331+
}
332+
case err := <-s.fsWatcher.Errors:
333+
klog.ErrorS(err, "failed to to watch features.d changes")
334+
}
335+
}
336+
}
337+
338+
// SetChannel method of the EventSource Interface
339+
func (s *localSource) SetChannel(ch chan struct{}) error {
340+
info, err := os.Stat(featureFilesDir)
341+
if err != nil {
342+
if !os.IsNotExist(err) {
343+
return err
344+
}
345+
}
346+
347+
if info != nil && info.IsDir() {
348+
watcher, err := fsnotify.NewWatcher()
349+
if err != nil {
350+
return err
351+
}
352+
353+
err = watcher.Add(featureFilesDir)
354+
if err != nil {
355+
return fmt.Errorf("unable to access %v: %w", featureFilesDir, err)
356+
}
357+
s.fsWatcher = watcher
358+
}
359+
360+
go s.runNotifier(ch)
361+
362+
return nil
363+
}
364+
321365
func init() {
322366
source.Register(&src)
323367
}

source/source.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,14 @@ type SupplementalSource interface {
7777
DisableByDefault() bool
7878
}
7979

80+
// EventSource is an interface for a source that can send events
81+
type EventSource interface {
82+
Source
83+
84+
// SetChannel sets the channel
85+
SetChannel(chan struct{}) error
86+
}
87+
8088
// FeatureLabelValue represents the value of one feature label
8189
type FeatureLabelValue interface{}
8290

@@ -155,6 +163,17 @@ func GetAllConfigurableSources() map[string]ConfigurableSource {
155163
return all
156164
}
157165

166+
// GetAllEventSources returns all registered event sources
167+
func GetAllEventSources() map[string]EventSource {
168+
all := make(map[string]EventSource)
169+
for k, v := range sources {
170+
if s, ok := v.(EventSource); ok {
171+
all[k] = s
172+
}
173+
}
174+
return all
175+
}
176+
158177
// GetAllFeatures returns a combined set of all features from all feature
159178
// sources.
160179
func GetAllFeatures() *nfdv1alpha1.Features {

0 commit comments

Comments
 (0)