Skip to content

Commit b9cfa13

Browse files
committed
Add event to the workspace pod related to the restoration of the PVC
Signed-off-by: JenTing Hsiao <[email protected]>
1 parent ef13986 commit b9cfa13

File tree

1 file changed

+46
-19
lines changed

1 file changed

+46
-19
lines changed

components/ws-manager/pkg/manager/manager.go

Lines changed: 46 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,12 @@ import (
3030
k8serr "k8s.io/apimachinery/pkg/api/errors"
3131
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3232
"k8s.io/apimachinery/pkg/labels"
33+
"k8s.io/apimachinery/pkg/runtime"
3334
"k8s.io/apimachinery/pkg/types"
3435
"k8s.io/apimachinery/pkg/util/wait"
3536
"k8s.io/client-go/kubernetes"
37+
covev1client "k8s.io/client-go/kubernetes/typed/core/v1"
38+
"k8s.io/client-go/tools/record"
3639
"k8s.io/client-go/util/retry"
3740
"sigs.k8s.io/controller-runtime/pkg/client"
3841

@@ -69,6 +72,8 @@ type Manager struct {
6972

7073
metrics *metrics
7174

75+
eventRecorder record.EventRecorder
76+
7277
api.UnimplementedWorkspaceManagerServer
7378
regapi.UnimplementedSpecProviderServer
7479
}
@@ -127,14 +132,19 @@ func New(config config.Configuration, client client.Client, rawClient kubernetes
127132
return nil, err
128133
}
129134

135+
broadcaster := record.NewBroadcaster()
136+
broadcaster.StartRecordingToSink(&covev1client.EventSinkImpl{Interface: rawClient.CoreV1().Events("")})
137+
eventRecorder := broadcaster.NewRecorder(runtime.NewScheme(), corev1.EventSource{Component: "ws-manager"})
138+
130139
m := &Manager{
131-
Config: config,
132-
Clientset: client,
133-
RawClient: rawClient,
134-
Content: cp,
135-
clock: clock.System(),
136-
subscribers: make(map[string]chan *api.SubscribeResponse),
137-
wsdaemonPool: grpcpool.New(wsdaemonConnfactory, checkWSDaemonEndpoint(config.Namespace, client)),
140+
Config: config,
141+
Clientset: client,
142+
RawClient: rawClient,
143+
Content: cp,
144+
clock: clock.System(),
145+
subscribers: make(map[string]chan *api.SubscribeResponse),
146+
wsdaemonPool: grpcpool.New(wsdaemonConnfactory, checkWSDaemonEndpoint(config.Namespace, client)),
147+
eventRecorder: eventRecorder,
138148
}
139149
m.metrics = newMetrics(m)
140150
m.OnChange = m.onChange
@@ -310,20 +320,37 @@ func (m *Manager) StartWorkspace(ctx context.Context, req *api.StartWorkspaceReq
310320
}
311321

312322
// we only calculate the time that PVC restoring from VolumeSnapshot
313-
if createPVC && startContext.VolumeSnapshot != nil && startContext.VolumeSnapshot.VolumeSnapshotName != "" {
314-
err := wait.PollWithContext(ctx, 100*time.Millisecond, 5*time.Minute, pvcRunning(m.Clientset, pvc.Name, pvc.Namespace))
315-
if err == nil {
316-
wsType := api.WorkspaceType_name[int32(req.Type)]
317-
hist, err := m.metrics.volumeRestoreTimeHistVec.GetMetricWithLabelValues(wsType, req.Spec.Class)
318-
if err != nil {
319-
log.WithError(err).WithField("type", wsType).Warn("cannot get volume restore time histogram metric")
320-
} else if endTime.IsZero() {
321-
endTime = time.Now()
322-
hist.Observe(endTime.Sub(startTime).Seconds())
323-
}
323+
if createPVC {
324+
err = m.Clientset.Get(ctx, types.NamespacedName{Namespace: pod.Namespace, Name: pod.Name}, pod)
325+
if err != nil {
326+
return nil, xerrors.Errorf("unable to get workspace pod %s: %w", pod.Name, err)
324327
}
325328

326-
log.WithError(err).Warn("unexpected error waiting for PVC")
329+
err = wait.PollWithContext(ctx, 100*time.Millisecond, 5*time.Minute, pvcRunning(m.Clientset, pvc.Name, pvc.Namespace))
330+
if err != nil {
331+
if startContext.VolumeSnapshot != nil && startContext.VolumeSnapshot.VolumeSnapshotName != "" {
332+
m.eventRecorder.Eventf(pod, corev1.EventTypeWarning, "PVC", "PVC %q restored from volume snapshot %s failed %v", pvc.Name, startContext.VolumeSnapshot.VolumeSnapshotName, err)
333+
log.WithError(err).Warnf("unexpected error waiting for PVC %s volume snapshot %s/%s", pvc.Name, startContext.VolumeSnapshot.VolumeSnapshotName)
334+
} else {
335+
m.eventRecorder.Eventf(pod, corev1.EventTypeWarning, "PVC", "PVC %q created failed %v", pvc.Name, err)
336+
log.WithError(err).Warnf("unexpected error waiting for PVC %s", pvc.Name)
337+
}
338+
} else {
339+
if startContext.VolumeSnapshot != nil && startContext.VolumeSnapshot.VolumeSnapshotName != "" {
340+
m.eventRecorder.Eventf(pod, corev1.EventTypeNormal, "PVC", "PVC %q restored from volume snapshot %s successfully", pvc.Name, startContext.VolumeSnapshot.VolumeSnapshotName)
341+
342+
wsType := api.WorkspaceType_name[int32(req.Type)]
343+
hist, err := m.metrics.volumeRestoreTimeHistVec.GetMetricWithLabelValues(wsType, req.Spec.Class)
344+
if err != nil {
345+
log.WithError(err).WithField("type", wsType).Warn("cannot get volume restore time histogram metric")
346+
} else if endTime.IsZero() {
347+
endTime = time.Now()
348+
hist.Observe(endTime.Sub(startTime).Seconds())
349+
}
350+
} else {
351+
m.eventRecorder.Eventf(pod, corev1.EventTypeNormal, "PVC", "PVC %q created successfully", pvc.Name)
352+
}
353+
}
327354
}
328355

329356
// remove annotation to signal that workspace pod was indeed created and scheduled on the node

0 commit comments

Comments
 (0)