Skip to content

Commit 2fa5da8

Browse files
author
Valeriy Khorunzhin
committed
resolve
Signed-off-by: Valeriy Khorunzhin <valeriy.khorunzhin@flant.com>
1 parent 4cba9e1 commit 2fa5da8

9 files changed

Lines changed: 60 additions & 451 deletions

File tree

api/core/v1alpha2/vmbdacondition/condition.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,6 @@ const (
6565
Conflict AttachedReason = "Conflict"
6666
// DeviceNotAvailableOnNode indicates that the block device's PersistentVolume is not available on the node where the virtual machine is running.
6767
DeviceNotAvailableOnNode AttachedReason = "DeviceNotAvailableOnNode"
68-
// HotPlugPodNotScheduled indicates that the hotplug pod cannot be scheduled on any node.
69-
HotPlugPodNotScheduled AttachedReason = "HotPlugPodNotScheduled"
70-
// FailedAttachVolume indicates that the hotplug pod failed to attach a volume.
71-
FailedAttachVolume AttachedReason = "FailedAttachVolume"
7268

7369
// CapacityAvailable signifies that the capacity not reached and attaching available.
7470
CapacityAvailable DiskAttachmentCapacityAvailableReason = "CapacityAvailable"

api/core/v1alpha2/vmcondition/condition.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,6 @@ const (
169169
ReasonVirtualMachineRunning RunningReason = "Running"
170170
ReasonInternalVirtualMachineError RunningReason = "InternalVirtualMachineError"
171171
ReasonPodNotStarted RunningReason = "PodNotStarted"
172-
ReasonPodVolumeErrors RunningReason = "PodVolumeErrors"
173172
ReasonPodTerminating RunningReason = "PodTerminating"
174173
ReasonPodNotFound RunningReason = "PodNotFound"
175174
ReasonPodConditionMissing RunningReason = "PodConditionMissing"

images/virtualization-artifact/pkg/common/pod/pod.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,14 @@ limitations under the License.
1717
package pod
1818

1919
import (
20+
"context"
21+
"slices"
22+
2023
corev1 "k8s.io/api/core/v1"
2124
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
25+
"k8s.io/apimachinery/pkg/fields"
2226
"k8s.io/utils/ptr"
27+
"sigs.k8s.io/controller-runtime/pkg/client"
2328
)
2429

2530
// MakeOwnerReference makes owner reference from a Pod
@@ -119,6 +124,46 @@ func IsPodComplete(pod *corev1.Pod) bool {
119124
return pod != nil && pod.Status.Phase == corev1.PodSucceeded
120125
}
121126

127+
func GetLastPodEvent(ctx context.Context, clientObject client.Client, pod *corev1.Pod) (*corev1.Event, error) {
128+
if pod == nil {
129+
return nil, nil
130+
}
131+
132+
eventList := &corev1.EventList{}
133+
err := clientObject.List(ctx, eventList, &client.ListOptions{
134+
Namespace: pod.Namespace,
135+
FieldSelector: fields.SelectorFromSet(fields.Set{
136+
"involvedObject.name": pod.Name,
137+
"involvedObject.kind": "Pod",
138+
}),
139+
})
140+
if err != nil {
141+
return nil, err
142+
}
143+
144+
if len(eventList.Items) == 0 {
145+
return nil, nil
146+
}
147+
148+
last := slices.MaxFunc(eventList.Items, func(a, b corev1.Event) int {
149+
return a.LastTimestamp.Compare(b.LastTimestamp.Time)
150+
})
151+
152+
return &last, nil
153+
}
154+
155+
func IsContainerCreating(pod *corev1.Pod) bool {
156+
if pod.Status.Phase != corev1.PodPending {
157+
return false
158+
}
159+
for _, cs := range pod.Status.ContainerStatuses {
160+
if cs.State.Waiting != nil && cs.State.Waiting.Reason == "ContainerCreating" {
161+
return true
162+
}
163+
}
164+
return false
165+
}
166+
122167
// QemuSubGID is the gid used as the qemu group in fsGroup
123168
const QemuSubGID = int64(107)
124169

images/virtualization-artifact/pkg/controller/vm/internal/lifecycle.go

Lines changed: 15 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,16 @@ import (
2020
"context"
2121
"fmt"
2222
"log/slog"
23-
"slices"
2423

2524
corev1 "k8s.io/api/core/v1"
2625
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27-
"k8s.io/apimachinery/pkg/fields"
2826
"k8s.io/apimachinery/pkg/labels"
2927
virtv1 "kubevirt.io/api/core/v1"
3028
"sigs.k8s.io/controller-runtime/pkg/client"
3129
"sigs.k8s.io/controller-runtime/pkg/reconcile"
3230

3331
"github.com/deckhouse/virtualization-controller/pkg/common/annotations"
32+
ccpod "github.com/deckhouse/virtualization-controller/pkg/common/pod"
3433
"github.com/deckhouse/virtualization-controller/pkg/controller/conditions"
3534
"github.com/deckhouse/virtualization-controller/pkg/controller/service"
3635
"github.com/deckhouse/virtualization-controller/pkg/controller/vm/internal/state"
@@ -55,11 +54,6 @@ type LifeCycleHandler struct {
5554
recorder eventrecord.EventRecorderLogger
5655
}
5756

58-
type podVolumeErrorEvent struct {
59-
Reason string
60-
Message string
61-
}
62-
6357
func (h *LifeCycleHandler) Handle(ctx context.Context, s state.VirtualMachineState) (reconcile.Result, error) {
6458
if s.VirtualMachine().IsEmpty() {
6559
return reconcile.Result{}, nil
@@ -109,19 +103,6 @@ func (h *LifeCycleHandler) Handle(ctx context.Context, s state.VirtualMachineSta
109103
}
110104

111105
log := logger.FromContext(ctx).With(logger.SlogHandler(nameLifeCycleHandler))
112-
// While the pod is not running, the VMI does not set the node and the method returns nil, so it is necessary to check if there are any issues with the pod
113-
if pod == nil {
114-
cb := conditions.NewConditionBuilder(vmcondition.TypeRunning).Generation(changed.GetGeneration())
115-
116-
if volumeErr := h.checkPodVolumeErrors(ctx, changed, log); volumeErr != nil {
117-
cb.Status(metav1.ConditionFalse).
118-
Reason(vmcondition.ReasonPodVolumeErrors).
119-
Message(fmt.Sprintf("Error attaching block devices to virtual machine: %s: %s", volumeErr.Reason, volumeErr.Message))
120-
conditions.SetCondition(cb, &changed.Status.Conditions)
121-
return reconcile.Result{}, nil
122-
}
123-
}
124-
125106
h.syncRunning(ctx, changed, kvvm, kvvmi, pod, log)
126107
return reconcile.Result{}, nil
127108
}
@@ -141,10 +122,10 @@ func (h *LifeCycleHandler) syncRunning(ctx context.Context, vm *v1alpha2.Virtual
141122
return
142123
}
143124

144-
if volumeError := h.checkPodVolumeErrors(ctx, vm, log); volumeError != nil {
125+
if volumeError := h.checkVMPodVolumeErrors(ctx, vm, log); volumeError != nil {
145126
cb.Status(metav1.ConditionFalse).
146-
Reason(vmcondition.ReasonPodVolumeErrors).
147-
Message(fmt.Sprintf("Error attaching block devices to virtual machine: %s: %s", volumeError.Reason, volumeError.Message))
127+
Reason(vmcondition.ReasonPodNotStarted).
128+
Message(fmt.Sprintf("Error attaching block devices to virtual machine: %s", volumeError.Error()))
148129
conditions.SetCondition(cb, &vm.Status.Conditions)
149130
return
150131
}
@@ -233,7 +214,7 @@ func (h *LifeCycleHandler) syncRunning(ctx context.Context, vm *v1alpha2.Virtual
233214
conditions.SetCondition(cb, &vm.Status.Conditions)
234215
}
235216

236-
func (h *LifeCycleHandler) checkPodVolumeErrors(ctx context.Context, vm *v1alpha2.VirtualMachine, log *slog.Logger) *podVolumeErrorEvent {
217+
func (h *LifeCycleHandler) checkVMPodVolumeErrors(ctx context.Context, vm *v1alpha2.VirtualMachine, log *slog.Logger) error {
237218
var podList corev1.PodList
238219
err := h.client.List(ctx, &podList, &client.ListOptions{
239220
Namespace: vm.Namespace,
@@ -243,62 +224,20 @@ func (h *LifeCycleHandler) checkPodVolumeErrors(ctx context.Context, vm *v1alpha
243224
})
244225
if err != nil {
245226
log.Error("Failed to list pods", "error", err)
246-
return nil
227+
return err
247228
}
248229

249-
for i := range podList.Items {
250-
if volumeErr := h.getPodVolumeError(ctx, &podList.Items[i], log); volumeErr != nil {
251-
return volumeErr
230+
for _, pod := range podList.Items {
231+
if !ccpod.IsContainerCreating(&pod) {
232+
continue
252233
}
253-
}
254-
255-
return nil
256-
}
257-
258-
func isContainerCreating(pod *corev1.Pod) bool {
259-
if pod == nil {
260-
return false
261-
}
262-
if pod.Status.Phase != corev1.PodPending {
263-
return false
264-
}
265-
for _, cs := range pod.Status.ContainerStatuses {
266-
if cs.State.Waiting != nil && cs.State.Waiting.Reason == "ContainerCreating" {
267-
return true
234+
lastEvent, err := ccpod.GetLastPodEvent(ctx, h.client, &pod)
235+
if err != nil {
236+
log.Error("Failed to get last pod event", "error", err)
237+
return err
268238
}
269-
}
270-
return false
271-
}
272-
273-
func (h *LifeCycleHandler) getPodVolumeError(ctx context.Context, pod *corev1.Pod, log *slog.Logger) *podVolumeErrorEvent {
274-
if !isContainerCreating(pod) {
275-
return nil
276-
}
277-
278-
eventList := &corev1.EventList{}
279-
err := h.client.List(ctx, eventList, &client.ListOptions{
280-
Namespace: pod.Namespace,
281-
FieldSelector: fields.SelectorFromSet(fields.Set{
282-
"involvedObject.name": pod.Name,
283-
"involvedObject.kind": "Pod",
284-
}),
285-
})
286-
if err != nil {
287-
log.Error("Failed to list pod events", "error", err)
288-
return nil
289-
}
290-
291-
if len(eventList.Items) == 0 {
292-
return nil
293-
}
294-
295-
last := slices.MaxFunc(eventList.Items, func(a, b corev1.Event) int {
296-
return a.LastTimestamp.Compare(b.LastTimestamp.Time)
297-
})
298-
if last.Reason == watcher.ReasonFailedAttachVolume || last.Reason == watcher.ReasonFailedMount {
299-
return &podVolumeErrorEvent{
300-
Reason: last.Reason,
301-
Message: last.Message,
239+
if lastEvent != nil && (lastEvent.Reason == watcher.ReasonFailedAttachVolume || lastEvent.Reason == watcher.ReasonFailedMount) {
240+
return fmt.Errorf("failed to attach volume: %s: %s", lastEvent.Reason, lastEvent.Message)
302241
}
303242
}
304243

images/virtualization-artifact/pkg/controller/vmbda/internal/life_cycle.go

Lines changed: 0 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,13 @@ import (
2222
"fmt"
2323
"time"
2424

25-
corev1 "k8s.io/api/core/v1"
2625
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2726
virtv1 "kubevirt.io/api/core/v1"
2827
"sigs.k8s.io/controller-runtime/pkg/reconcile"
2928

3029
"github.com/deckhouse/virtualization-controller/pkg/controller/conditions"
3130
"github.com/deckhouse/virtualization-controller/pkg/controller/service"
3231
intsvc "github.com/deckhouse/virtualization-controller/pkg/controller/vmbda/internal/service"
33-
"github.com/deckhouse/virtualization-controller/pkg/controller/vmbda/internal/watcher"
3432
"github.com/deckhouse/virtualization-controller/pkg/logger"
3533
"github.com/deckhouse/virtualization/api/core/v1alpha2"
3634
"github.com/deckhouse/virtualization/api/core/v1alpha2/vmbdacondition"
@@ -201,11 +199,6 @@ func (h LifeCycleHandler) Handle(ctx context.Context, vmbda *v1alpha2.VirtualMac
201199
if err != nil {
202200
if errors.Is(err, intsvc.ErrVolumeStatusNotReady) {
203201
vmbda.Status.Phase = v1alpha2.BlockDeviceAttachmentPhaseInProgress
204-
205-
if handled, podErr := h.handleHotPlugPodIssues(ctx, ad, kvvmi, vmbda, cb); podErr != nil || handled {
206-
return reconcile.Result{}, podErr
207-
}
208-
209202
cb.
210203
Status(metav1.ConditionFalse).
211204
Reason(vmbdacondition.AttachmentRequestSent).
@@ -307,58 +300,3 @@ func (h LifeCycleHandler) Handle(ctx context.Context, vmbda *v1alpha2.VirtualMac
307300
return reconcile.Result{}, err
308301
}
309302
}
310-
311-
func (h LifeCycleHandler) handleHotPlugPodIssues(
312-
ctx context.Context,
313-
ad *intsvc.AttachmentDisk,
314-
kvvmi *virtv1.VirtualMachineInstance,
315-
vmbda *v1alpha2.VirtualMachineBlockDeviceAttachment,
316-
cb *conditions.ConditionBuilder,
317-
) (bool, error) {
318-
hotPlugPod, err := h.attacher.GetHotPlugPod(ctx, ad, kvvmi)
319-
if err != nil {
320-
return false, err
321-
}
322-
if hotPlugPod == nil {
323-
return false, nil
324-
}
325-
326-
for _, c := range hotPlugPod.Status.Conditions {
327-
if c.Type == corev1.PodScheduled && c.Status == corev1.ConditionFalse && c.Message != "" {
328-
vmbda.Status.Phase = v1alpha2.BlockDeviceAttachmentPhasePending
329-
cb.
330-
Status(metav1.ConditionFalse).
331-
Reason(vmbdacondition.HotPlugPodNotScheduled).
332-
Message(fmt.Sprintf("Error attaching block device to virtual machine: %s: %s", c.Reason, c.Message))
333-
return true, nil
334-
}
335-
}
336-
337-
if isContainerCreating(hotPlugPod) {
338-
lastEvent, err := h.attacher.GetLastPodEvent(ctx, hotPlugPod)
339-
if err != nil {
340-
return false, err
341-
}
342-
if lastEvent != nil && (lastEvent.Reason == watcher.ReasonFailedAttachVolume || lastEvent.Reason == watcher.ReasonFailedMount) {
343-
cb.
344-
Status(metav1.ConditionFalse).
345-
Reason(vmbdacondition.FailedAttachVolume).
346-
Message(fmt.Sprintf("Error attaching block device to virtual machine: %s: %s", lastEvent.Reason, lastEvent.Message))
347-
return true, nil
348-
}
349-
}
350-
351-
return false, nil
352-
}
353-
354-
func isContainerCreating(pod *corev1.Pod) bool {
355-
if pod.Status.Phase != corev1.PodPending {
356-
return false
357-
}
358-
for _, cs := range pod.Status.ContainerStatuses {
359-
if cs.State.Waiting != nil && cs.State.Waiting.Reason == "ContainerCreating" {
360-
return true
361-
}
362-
}
363-
return false
364-
}

images/virtualization-artifact/pkg/controller/vmbda/internal/service/attachment_service.go

Lines changed: 0 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,9 @@ import (
2020
"context"
2121
"errors"
2222
"fmt"
23-
"slices"
2423
"strings"
2524

2625
corev1 "k8s.io/api/core/v1"
27-
"k8s.io/apimachinery/pkg/fields"
2826
"k8s.io/apimachinery/pkg/types"
2927
"k8s.io/component-helpers/scheduling/corev1/nodeaffinity"
3028
virtv1 "kubevirt.io/api/core/v1"
@@ -316,69 +314,6 @@ func (s AttachmentService) IsPVAvailableOnVMNode(ctx context.Context, pvc *corev
316314
return true, nil
317315
}
318316

319-
func (s AttachmentService) GetHotPlugPod(ctx context.Context, ad *AttachmentDisk, kvvmi *virtv1.VirtualMachineInstance) (*corev1.Pod, error) {
320-
if ad == nil || kvvmi == nil {
321-
return nil, nil
322-
}
323-
324-
for _, vs := range kvvmi.Status.VolumeStatus {
325-
if vs.HotplugVolume == nil || vs.Name != ad.GenerateName {
326-
continue
327-
}
328-
if vs.HotplugVolume.AttachPodName == "" {
329-
return nil, nil
330-
}
331-
332-
return object.FetchObject(ctx, types.NamespacedName{
333-
Namespace: kvvmi.Namespace,
334-
Name: vs.HotplugVolume.AttachPodName,
335-
}, s.client, &corev1.Pod{})
336-
}
337-
return nil, nil
338-
}
339-
340-
func (s AttachmentService) GetHotPlugPodCondition(ctx context.Context, ad *AttachmentDisk, kvvmi *virtv1.VirtualMachineInstance, condType corev1.PodConditionType) (*corev1.PodCondition, error) {
341-
pod, err := s.GetHotPlugPod(ctx, ad, kvvmi)
342-
if err != nil || pod == nil {
343-
return nil, err
344-
}
345-
346-
for i, c := range pod.Status.Conditions {
347-
if c.Type == condType {
348-
return &pod.Status.Conditions[i], nil
349-
}
350-
}
351-
return nil, nil
352-
}
353-
354-
func (s AttachmentService) GetLastPodEvent(ctx context.Context, pod *corev1.Pod) (*corev1.Event, error) {
355-
if pod == nil {
356-
return nil, nil
357-
}
358-
359-
eventList := &corev1.EventList{}
360-
err := s.client.List(ctx, eventList, &client.ListOptions{
361-
Namespace: pod.Namespace,
362-
FieldSelector: fields.SelectorFromSet(fields.Set{
363-
"involvedObject.name": pod.Name,
364-
"involvedObject.kind": "Pod",
365-
}),
366-
})
367-
if err != nil {
368-
return nil, err
369-
}
370-
371-
if len(eventList.Items) == 0 {
372-
return nil, nil
373-
}
374-
375-
last := slices.MaxFunc(eventList.Items, func(a, b corev1.Event) int {
376-
return a.LastTimestamp.Compare(b.LastTimestamp.Time)
377-
})
378-
379-
return &last, nil
380-
}
381-
382317
func isSameBlockDeviceRefs(a, b v1alpha2.VMBDAObjectRef) bool {
383318
return a.Kind == b.Kind && a.Name == b.Name
384319
}

0 commit comments

Comments
 (0)