...
1 package events
2
3 import (
4 "context"
5 "path/filepath"
6 "strings"
7 "time"
8
9 "github.com/containerd/containerd/containers"
10
11 "edge-infra.dev/pkg/lib/kernel/devices"
12 "edge-infra.dev/pkg/lib/kernel/udev"
13 cc "edge-infra.dev/pkg/sds/devices/agent/common"
14 "edge-infra.dev/pkg/sds/devices/class"
15 dsv1 "edge-infra.dev/pkg/sds/devices/k8s/apis/v1"
16 "edge-infra.dev/pkg/sds/devices/logger"
17 )
18
19 type DeviceEvent interface {
20 Containers() map[string]*containers.Container
21 PosthookFunc() func(context.Context)
22 Timestamp() time.Time
23 }
24
25
26 type event struct {
27
28 containers map[string]*containers.Container
29
30 postHookFn func(context.Context)
31
32 timestamp time.Time
33 }
34
35 type udevEvent struct{ *event }
36 type containerEvent struct{ *event }
37 type classEvent struct{ *event }
38 type kubeletEvent struct{ *event }
39
40 var (
41 requested = "requested"
42 deviceExistsInClassFn = deviceExistsInClass
43 )
44
45
46
47 func NewKubeletEvent() DeviceEvent {
48 return &kubeletEvent{
49 event: &event{
50 containers: map[string]*containers.Container{},
51 postHookFn: func(context.Context) {},
52 timestamp: time.Now(),
53 },
54 }
55 }
56
57 func (e *event) Containers() map[string]*containers.Container {
58 return e.containers
59 }
60
61 func (e *event) PosthookFunc() func(context.Context) {
62 return e.postHookFn
63 }
64
65 func (e *event) Timestamp() time.Time {
66 return e.timestamp
67 }
68
69
70
71 func ueventMatchesContainer(ctx context.Context, udevEvent *udev.UEvent, ctr *containers.Container, deviceClasses map[string]*dsv1.DeviceClass) bool {
72 log := logger.FromContext(ctx)
73 for classLabel := range ctr.Labels {
74 if !class.IsDeviceClass(classLabel) {
75 continue
76 }
77
78 deviceClass, ok := deviceClasses[classLabel]
79 if !ok || deviceClass == nil {
80 continue
81 }
82
83 devicePath := prefixSysPath(udevEvent.SysPath)
84 existsInClass := deviceExistsInClassFn(deviceClass, devicePath)
85 log.Log(ctx, logger.LevelTrace, "evaluating uevent matches device class", "class", classLabel, "container", ctr.Labels[cc.AnnContainerName], "event", udevEvent.SysPath, "matches class", existsInClass)
86 if existsInClass {
87 return true
88 }
89 }
90 return false
91 }
92
93 func deviceExistsInClass(deviceClass *dsv1.DeviceClass, devicePath string) bool {
94 return deviceClass.DeviceExistsInClass(devicePath)
95 }
96
97 func prefixSysPath(path string) string {
98 if strings.HasPrefix(path, devices.SysPath) {
99 return path
100 }
101 return filepath.Join(devices.SysPath, path)
102 }
103
View as plain text