@@ -26,7 +26,6 @@ import (
26
26
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27
27
"k8s.io/apimachinery/pkg/labels"
28
28
"k8s.io/apimachinery/pkg/types"
29
- "k8s.io/apimachinery/pkg/util/wait"
30
29
"k8s.io/apimachinery/pkg/watch"
31
30
"sigs.k8s.io/controller-runtime/pkg/client"
32
31
@@ -83,6 +82,8 @@ type Monitor struct {
83
82
act actingManager
84
83
85
84
OnError func (error )
85
+
86
+ notifyPod map [string ]chan string
86
87
}
87
88
88
89
// CreateMonitor creates a new monitor
@@ -103,6 +104,8 @@ func (m *Manager) CreateMonitor() (*Monitor, error) {
103
104
OnError : func (err error ) {
104
105
log .WithError (err ).Error ("workspace monitor error" )
105
106
},
107
+
108
+ notifyPod : make (map [string ]chan string ),
106
109
}
107
110
res .eventpool = workpool .NewEventWorkerPool (res .handleEvent )
108
111
res .act = struct {
@@ -145,13 +148,47 @@ func (m *Monitor) handleEvent(evt watch.Event) {
145
148
switch evt .Object .(type ) {
146
149
case * corev1.Pod :
147
150
err = m .onPodEvent (evt )
151
+ case * volumesnapshotv1.VolumeSnapshot :
152
+ err = m .onVolumesnapshotEvent (evt )
148
153
}
149
154
150
155
if err != nil {
151
156
m .OnError (err )
152
157
}
153
158
}
154
159
160
+ func (m * Monitor ) onVolumesnapshotEvent (evt watch.Event ) error {
161
+ vs , ok := evt .Object .(* volumesnapshotv1.VolumeSnapshot )
162
+ if ! ok {
163
+ return xerrors .Errorf ("received non-volume-snapshot event" )
164
+ }
165
+
166
+ log := log .WithField ("volumesnapshot" , vs .Name )
167
+
168
+ if vs .Spec .Source .PersistentVolumeClaimName == nil {
169
+ // there is no pvc name within the VolumeSnapshot object
170
+ log .Warn ("the spec.source.persistentVolumeClaimName is empty" )
171
+ return nil
172
+ }
173
+
174
+ // the pod name is 1:1 mapping to pvc name
175
+ podName := * vs .Spec .Source .PersistentVolumeClaimName
176
+ log = log .WithField ("pod" , podName )
177
+
178
+ if vs .Status == nil || vs .Status .ReadyToUse == nil || ! * vs .Status .ReadyToUse || vs .Status .BoundVolumeSnapshotContentName == nil {
179
+ return nil
180
+ }
181
+
182
+ vsc := * vs .Status .BoundVolumeSnapshotContentName
183
+ log .Infof ("the vsc %s is ready" , vsc )
184
+ if m .notifyPod [podName ] == nil {
185
+ m .notifyPod [podName ] = make (chan string )
186
+ }
187
+ m .notifyPod [podName ] <- vsc
188
+
189
+ return nil
190
+ }
191
+
155
192
// onPodEvent interpretes Kubernetes events, translates and broadcasts them, and acts based on them
156
193
func (m * Monitor ) onPodEvent (evt watch.Event ) error {
157
194
// Beware: we patch running pods to add annotations. At the moment this is not a problem as do not attach
@@ -987,47 +1024,31 @@ func (m *Monitor) finalizeWorkspaceContent(ctx context.Context, wso *workspaceOb
987
1024
volumeSnapshotTime = time .Now ()
988
1025
}
989
1026
if createdVolumeSnapshot {
990
- backoff := wait.Backoff {
991
- Steps : 30 ,
992
- Duration : 100 * time .Millisecond ,
993
- Factor : 1.5 ,
994
- Jitter : 0.1 ,
995
- Cap : 10 * time .Minute ,
1027
+ if m .notifyPod [wso .Pod .Name ] == nil {
1028
+ m .notifyPod [wso .Pod .Name ] = make (chan string )
996
1029
}
997
- log = log .WithField ("VolumeSnapshot.Name" , pvcVolumeSnapshotName )
998
- err = wait .ExponentialBackoff (backoff , func () (bool , error ) {
999
- var volumeSnapshot volumesnapshotv1.VolumeSnapshot
1000
- err := m .manager .Clientset .Get (ctx , types.NamespacedName {Namespace : m .manager .Config .Namespace , Name : pvcVolumeSnapshotName }, & volumeSnapshot )
1001
- if err != nil {
1002
- if k8serr .IsNotFound (err ) {
1003
- // volumesnapshot doesn't exist yet, retry again
1004
- return false , nil
1005
- }
1006
- log .WithError (err ).Error ("was unable to get volume snapshot" )
1007
- return false , err
1008
- }
1009
- if volumeSnapshot .Status != nil {
1010
- if volumeSnapshot .Status .ReadyToUse != nil && * (volumeSnapshot .Status .ReadyToUse ) && volumeSnapshot .Status .BoundVolumeSnapshotContentName != nil {
1011
- pvcVolumeSnapshotContentName = * volumeSnapshot .Status .BoundVolumeSnapshotContentName
1012
- return true , nil
1013
- }
1014
- if volumeSnapshot .Status .Error != nil {
1015
- if volumeSnapshot .Status .Error .Message != nil {
1016
- err = xerrors .Errorf ("error during volume snapshot creation: %s" , * volumeSnapshot .Status .Error .Message )
1017
- log .WithError (err ).Error ("unable to create volume snapshot" )
1018
- return false , err
1019
- }
1020
- log .Error ("unknown error during volume snapshot creation" )
1021
- return false , xerrors .Errorf ("unknown error during volume snapshot creation" )
1022
- }
1030
+
1031
+ select {
1032
+ case pvcVolumeSnapshotContentName = <- m .notifyPod [wso .Pod .Name ]:
1033
+ readyVolumeSnapshot = true
1034
+ case <- ctx .Done ():
1035
+ // There might be a chance that the VolumeSnapshot is ready but somehow
1036
+ // we did not receive the notification.
1037
+ // For example, the ws-manager restarts before the VolumeSnapshot becomes ready.
1038
+ // Let's give it the last chance to check the VolumeSnapshot is ready.
1039
+ var vs volumesnapshotv1.VolumeSnapshot
1040
+ err := m .manager .Clientset .Get (ctx , types.NamespacedName {Namespace : m .manager .Config .Namespace , Name : pvcVolumeSnapshotName }, & vs )
1041
+ if err == nil && vs .Status != nil && vs .Status .ReadyToUse != nil && * vs .Status .ReadyToUse && vs .Status .BoundVolumeSnapshotContentName != nil {
1042
+ pvcVolumeSnapshotContentName = * vs .Status .BoundVolumeSnapshotContentName
1043
+ readyVolumeSnapshot = true
1044
+ break
1023
1045
}
1024
- return false , nil
1025
- })
1026
- if err != nil {
1027
- log .WithError (err ).Errorf ("failed while waiting for volume snapshot to get ready" )
1046
+
1047
+ err = xerrors .Errorf ("%s timed out while waiting for volume snapshot to get ready" , m .manager .Config .Timeouts .ContentFinalization .String ())
1048
+ log .Error (err .Error ())
1028
1049
return true , nil , err
1029
1050
}
1030
- readyVolumeSnapshot = true
1051
+
1031
1052
hist , err := m .manager .metrics .volumeSnapshotTimeHistVec .GetMetricWithLabelValues (wsType , wso .Pod .Labels [workspaceClassLabel ])
1032
1053
if err != nil {
1033
1054
log .WithError (err ).WithField ("type" , wsType ).Warn ("cannot get volume snapshot time histogram metric" )
0 commit comments