From 175643f0be1ebf8ea7159110b9fe910e04220875 Mon Sep 17 00:00:00 2001 From: Daniil Loktev Date: Fri, 28 Nov 2025 13:58:38 +0300 Subject: [PATCH 1/7] wip Signed-off-by: Daniil Loktev --- .../pkg/controller/vm/internal/lifecycle.go | 58 ++++++++++++++++++- .../pkg/controller/vm/internal/network.go | 2 +- 2 files changed, 57 insertions(+), 3 deletions(-) diff --git a/images/virtualization-artifact/pkg/controller/vm/internal/lifecycle.go b/images/virtualization-artifact/pkg/controller/vm/internal/lifecycle.go index 699ef35652..d6249c682e 100644 --- a/images/virtualization-artifact/pkg/controller/vm/internal/lifecycle.go +++ b/images/virtualization-artifact/pkg/controller/vm/internal/lifecycle.go @@ -23,6 +23,7 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/fields" virtv1 "kubevirt.io/api/core/v1" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/reconcile" @@ -101,7 +102,7 @@ func (h *LifeCycleHandler) Handle(ctx context.Context, s state.VirtualMachineSta log := logger.FromContext(ctx).With(logger.SlogHandler(nameLifeCycleHandler)) - h.syncRunning(changed, kvvm, kvvmi, pod, log) + h.syncRunning(ctx, changed, kvvm, kvvmi, pod, log) return reconcile.Result{}, nil } @@ -109,7 +110,7 @@ func (h *LifeCycleHandler) Name() string { return nameLifeCycleHandler } -func (h *LifeCycleHandler) syncRunning(vm *v1alpha2.VirtualMachine, kvvm *virtv1.VirtualMachine, kvvmi *virtv1.VirtualMachineInstance, pod *corev1.Pod, log *slog.Logger) { +func (h *LifeCycleHandler) syncRunning(ctx context.Context, vm *v1alpha2.VirtualMachine, kvvm *virtv1.VirtualMachine, kvvmi *virtv1.VirtualMachineInstance, pod *corev1.Pod, log *slog.Logger) { cb := conditions.NewConditionBuilder(vmcondition.TypeRunning).Generation(vm.GetGeneration()) if pod != nil && pod.Status.Message != "" { @@ -120,6 +121,16 @@ func (h *LifeCycleHandler) syncRunning(vm *v1alpha2.VirtualMachine, kvvm *virtv1 return } + if pod != nil { + if volumeError := h.checkPodVolumeErrors(ctx, pod, log); volumeError != nil { + cb.Status(metav1.ConditionFalse). + Reason(vmcondition.ReasonPodNotStarted). + Message(volumeError.Error()) + conditions.SetCondition(cb, &vm.Status.Conditions) + return + } + } + if kvvm != nil { podScheduled := service.GetKVVMCondition(string(corev1.PodScheduled), kvvm.Status.Conditions) if podScheduled != nil && podScheduled.Status == corev1.ConditionFalse { @@ -202,3 +213,46 @@ func (h *LifeCycleHandler) syncRunning(vm *v1alpha2.VirtualMachine, kvvm *virtv1 cb.Reason(vmcondition.ReasonVmIsNotRunning).Status(metav1.ConditionFalse) conditions.SetCondition(cb, &vm.Status.Conditions) } + +func (h *LifeCycleHandler) checkPodVolumeErrors(ctx context.Context, pod *corev1.Pod, log *slog.Logger) error { + if pod.Status.Phase != corev1.PodPending { + return nil + } + + hasContainerCreating := false + for _, cs := range pod.Status.ContainerStatuses { + if cs.State.Waiting != nil && cs.State.Waiting.Reason == "ContainerCreating" { + hasContainerCreating = true + break + } + } + + if !hasContainerCreating { + return nil + } + + eventList := &corev1.EventList{} + err := h.client.List(ctx, eventList, &client.ListOptions{ + Namespace: pod.Namespace, + FieldSelector: fields.SelectorFromSet(fields.Set{ + "involvedObject.name": pod.Name, + "involvedObject.kind": "Pod", + }), + }) + if err != nil { + log.Error("Failed to list pod events", "error", err) + return nil + } + + for _, event := range eventList.Items { + if event.Type != corev1.EventTypeWarning { + continue + } + + if event.Reason == "FailedAttachVolume" || event.Reason == "FailedMount" { + return fmt.Errorf("%s: %s", event.Reason, event.Message) + } + } + + return nil +} diff --git a/images/virtualization-artifact/pkg/controller/vm/internal/network.go b/images/virtualization-artifact/pkg/controller/vm/internal/network.go index e50ff5b0b0..c321981eb5 100644 --- a/images/virtualization-artifact/pkg/controller/vm/internal/network.go +++ b/images/virtualization-artifact/pkg/controller/vm/internal/network.go @@ -167,7 +167,7 @@ func extractNetworkStatusFromPods(pods *corev1.PodList) (string, error) { } networkStatusAnnotation, found := pod.Annotations[annotations.AnnNetworksStatus] - if !found { + if !found && pod.Status.Phase == corev1.PodRunning { errorMessages = append(errorMessages, "Cannot determine the status of additional interfaces, waiting for a response from the SDN module") continue } From c88e8fabd8547dd91adbbd220019d4c20efa729f Mon Sep 17 00:00:00 2001 From: Daniil Loktev Date: Fri, 28 Nov 2025 15:02:00 +0300 Subject: [PATCH 2/7] wip Signed-off-by: Daniil Loktev --- .../pkg/controller/vm/internal/network.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/images/virtualization-artifact/pkg/controller/vm/internal/network.go b/images/virtualization-artifact/pkg/controller/vm/internal/network.go index c321981eb5..f573ffef84 100644 --- a/images/virtualization-artifact/pkg/controller/vm/internal/network.go +++ b/images/virtualization-artifact/pkg/controller/vm/internal/network.go @@ -167,8 +167,10 @@ func extractNetworkStatusFromPods(pods *corev1.PodList) (string, error) { } networkStatusAnnotation, found := pod.Annotations[annotations.AnnNetworksStatus] - if !found && pod.Status.Phase == corev1.PodRunning { - errorMessages = append(errorMessages, "Cannot determine the status of additional interfaces, waiting for a response from the SDN module") + if !found { + if pod.Status.Phase == corev1.PodRunning { + errorMessages = append(errorMessages, "Cannot determine the status of additional interfaces, waiting for a response from the SDN module") + } continue } From 5c89d651d771f5ebdb83f3f2df0010c529ee4be6 Mon Sep 17 00:00:00 2001 From: Daniil Loktev Date: Fri, 28 Nov 2025 16:00:35 +0300 Subject: [PATCH 3/7] wip Signed-off-by: Daniil Loktev --- .mirrord/security-policy-exception.yaml | 33 ++++++ .../internal/watcher/volumeevent_watcher.go | 101 ++++++++++++++++++ .../pkg/controller/vm/vm_reconciler.go | 1 + .../rbac-for-us.yaml | 2 + 4 files changed, 137 insertions(+) create mode 100644 .mirrord/security-policy-exception.yaml create mode 100644 images/virtualization-artifact/pkg/controller/vm/internal/watcher/volumeevent_watcher.go diff --git a/.mirrord/security-policy-exception.yaml b/.mirrord/security-policy-exception.yaml new file mode 100644 index 0000000000..ccdfb1c6b1 --- /dev/null +++ b/.mirrord/security-policy-exception.yaml @@ -0,0 +1,33 @@ +apiVersion: deckhouse.io/v1alpha1 +kind: SecurityPolicyException +metadata: + name: mirrord-agent-exception + namespace: default +spec: + network: + hostPID: + allowedValue: true + metadata: + description: "Required for mirrord agent to attach to target container" + securityContext: + capabilities: + allowedValues: + add: + - NET_ADMIN + - NET_RAW + - SYS_ADMIN + - SYS_PTRACE + - SYS_RESOURCE + drop: + - ALL + volumes: + hostPath: + allowedValues: + - path: /run + readOnly: false + metadata: + description: "Required for mirrord agent container runtime access" + - path: /var + readOnly: false + metadata: + description: "Required for mirrord agent container runtime access" diff --git a/images/virtualization-artifact/pkg/controller/vm/internal/watcher/volumeevent_watcher.go b/images/virtualization-artifact/pkg/controller/vm/internal/watcher/volumeevent_watcher.go new file mode 100644 index 0000000000..e64384cbe9 --- /dev/null +++ b/images/virtualization-artifact/pkg/controller/vm/internal/watcher/volumeevent_watcher.go @@ -0,0 +1,101 @@ +/* +Copyright 2025 Flant JSC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package watcher + +import ( + "context" + "fmt" + + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/types" + virtv1 "kubevirt.io/api/core/v1" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/controller" + "sigs.k8s.io/controller-runtime/pkg/event" + "sigs.k8s.io/controller-runtime/pkg/handler" + "sigs.k8s.io/controller-runtime/pkg/manager" + "sigs.k8s.io/controller-runtime/pkg/predicate" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + "sigs.k8s.io/controller-runtime/pkg/source" +) + +func NewVolumeEventWatcher(client client.Client) *VolumeEventWatcher { + return &VolumeEventWatcher{ + client: client, + } +} + +type VolumeEventWatcher struct { + client client.Client +} + +func (w *VolumeEventWatcher) Watch(mgr manager.Manager, ctr controller.Controller) error { + if err := ctr.Watch( + source.Kind( + mgr.GetCache(), + &corev1.Event{}, + handler.TypedEnqueueRequestsFromMapFunc(func(ctx context.Context, e *corev1.Event) []reconcile.Request { + if e.InvolvedObject.Kind != "Pod" { + return nil + } + + if e.Reason != "FailedAttachVolume" && e.Reason != "FailedMount" { + return nil + } + + pod := &corev1.Pod{} + if err := w.client.Get(ctx, types.NamespacedName{ + Name: e.InvolvedObject.Name, + Namespace: e.InvolvedObject.Namespace, + }, pod); err != nil { + return nil + } + + vmName, hasLabel := pod.GetLabels()[virtv1.VirtualMachineNameLabel] + if !hasLabel { + return nil + } + + return []reconcile.Request{ + { + NamespacedName: types.NamespacedName{ + Name: vmName, + Namespace: pod.GetNamespace(), + }, + }, + } + }), + predicate.TypedFuncs[*corev1.Event]{ + CreateFunc: func(e event.TypedCreateEvent[*corev1.Event]) bool { + return e.Object.Type == corev1.EventTypeWarning && + (e.Object.Reason == "FailedAttachVolume" || e.Object.Reason == "FailedMount") + }, + UpdateFunc: func(e event.TypedUpdateEvent[*corev1.Event]) bool { + return e.ObjectNew.Type == corev1.EventTypeWarning && + (e.ObjectNew.Reason == "FailedAttachVolume" || e.ObjectNew.Reason == "FailedMount") && + e.ObjectOld.Count != e.ObjectNew.Count + }, + DeleteFunc: func(e event.TypedDeleteEvent[*corev1.Event]) bool { + return false + }, + }, + ), + ); err != nil { + return fmt.Errorf("error setting watch on Event: %w", err) + } + return nil +} diff --git a/images/virtualization-artifact/pkg/controller/vm/vm_reconciler.go b/images/virtualization-artifact/pkg/controller/vm/vm_reconciler.go index 92d0baaa20..aa5c4488a9 100644 --- a/images/virtualization-artifact/pkg/controller/vm/vm_reconciler.go +++ b/images/virtualization-artifact/pkg/controller/vm/vm_reconciler.go @@ -65,6 +65,7 @@ func (r *Reconciler) SetupController(_ context.Context, mgr manager.Manager, ctr watcher.NewKVVMWatcher(), watcher.NewKVVMIWatcher(), watcher.NewPodWatcher(), + watcher.NewVolumeEventWatcher(mgr.GetClient()), watcher.NewVirtualImageWatcher(mgr.GetClient()), watcher.NewClusterVirtualImageWatcher(mgr.GetClient()), watcher.NewVirtualDiskWatcher(mgr.GetClient()), diff --git a/templates/virtualization-controller/rbac-for-us.yaml b/templates/virtualization-controller/rbac-for-us.yaml index 73acbabd5a..cb742ce14b 100644 --- a/templates/virtualization-controller/rbac-for-us.yaml +++ b/templates/virtualization-controller/rbac-for-us.yaml @@ -101,6 +101,8 @@ rules: verbs: - create - patch + - list + - watch - apiGroups: - cdi.internal.virtualization.deckhouse.io resources: From 964dd92035e8cff9c76239bd6babdc9ce722549a Mon Sep 17 00:00:00 2001 From: Daniil Loktev Date: Sun, 30 Nov 2025 15:45:20 +0300 Subject: [PATCH 4/7] wip Signed-off-by: Daniil Loktev --- images/virtualization-artifact/Taskfile.yaml | 3 +- .../pkg/controller/vm/internal/lifecycle.go | 101 ++++++++++++------ .../internal/watcher/volumeevent_watcher.go | 9 +- .../pkg/controller/vm/vm_controller.go | 24 +++++ 4 files changed, 98 insertions(+), 39 deletions(-) diff --git a/images/virtualization-artifact/Taskfile.yaml b/images/virtualization-artifact/Taskfile.yaml index 122ad42a16..d96716bfd6 100644 --- a/images/virtualization-artifact/Taskfile.yaml +++ b/images/virtualization-artifact/Taskfile.yaml @@ -75,7 +75,8 @@ tasks: TMPDIR=/tmp ./hack/mirrord.sh run --app=$PWD/cmd/virtualization-controller/main.go \ --deployment=virtualization-controller \ --namespace={{ .BaseNamespace }} \ - --container-name=virtualization-controller + --container-name=virtualization-controller \ + --flags="--leader-election=false" mirrord:wipe:controller: desc: "wipe up Mirrord's trash" diff --git a/images/virtualization-artifact/pkg/controller/vm/internal/lifecycle.go b/images/virtualization-artifact/pkg/controller/vm/internal/lifecycle.go index d6249c682e..d394dde7d9 100644 --- a/images/virtualization-artifact/pkg/controller/vm/internal/lifecycle.go +++ b/images/virtualization-artifact/pkg/controller/vm/internal/lifecycle.go @@ -24,6 +24,7 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/fields" + "k8s.io/apimachinery/pkg/labels" virtv1 "kubevirt.io/api/core/v1" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/reconcile" @@ -121,14 +122,12 @@ func (h *LifeCycleHandler) syncRunning(ctx context.Context, vm *v1alpha2.Virtual return } - if pod != nil { - if volumeError := h.checkPodVolumeErrors(ctx, pod, log); volumeError != nil { - cb.Status(metav1.ConditionFalse). - Reason(vmcondition.ReasonPodNotStarted). - Message(volumeError.Error()) - conditions.SetCondition(cb, &vm.Status.Conditions) - return - } + if volumeError := h.checkPodVolumeErrors(ctx, vm, log); volumeError != nil { + cb.Status(metav1.ConditionFalse). + Reason(vmcondition.ReasonPodNotStarted). + Message(volumeError.Error()) + conditions.SetCondition(cb, &vm.Status.Conditions) + return } if kvvm != nil { @@ -214,45 +213,79 @@ func (h *LifeCycleHandler) syncRunning(ctx context.Context, vm *v1alpha2.Virtual conditions.SetCondition(cb, &vm.Status.Conditions) } -func (h *LifeCycleHandler) checkPodVolumeErrors(ctx context.Context, pod *corev1.Pod, log *slog.Logger) error { - if pod.Status.Phase != corev1.PodPending { +func (h *LifeCycleHandler) checkPodVolumeErrors(ctx context.Context, vm *v1alpha2.VirtualMachine, log *slog.Logger) error { + var podList corev1.PodList + err := h.client.List(ctx, &podList, &client.ListOptions{ + Namespace: vm.Namespace, + LabelSelector: labels.SelectorFromSet(map[string]string{ + virtv1.VirtualMachineNameLabel: vm.Name, + }), + }) + if err != nil { + log.Error("Failed to list pods", "error", err) return nil } - hasContainerCreating := false - for _, cs := range pod.Status.ContainerStatuses { - if cs.State.Waiting != nil && cs.State.Waiting.Reason == "ContainerCreating" { - hasContainerCreating = true - break - } - } + log.Info("checkPodVolumeErrors", "podCount", len(podList.Items)) - if !hasContainerCreating { + if len(podList.Items) == 0 { return nil } + for _, pod := range podList.Items { + log.Info("checkPodVolumeErrors pod", "name", pod.Name, "phase", pod.Status.Phase, "containerStatuses", len(pod.Status.ContainerStatuses)) - eventList := &corev1.EventList{} - err := h.client.List(ctx, eventList, &client.ListOptions{ - Namespace: pod.Namespace, - FieldSelector: fields.SelectorFromSet(fields.Set{ - "involvedObject.name": pod.Name, - "involvedObject.kind": "Pod", - }), - }) - if err != nil { - log.Error("Failed to list pod events", "error", err) - return nil - } + if pod.Status.Phase != corev1.PodPending { + continue + } + + hasContainerCreating := false + for _, cs := range pod.Status.ContainerStatuses { + log.Info("checkPodVolumeErrors container", "name", cs.Name, "waiting", cs.State.Waiting != nil, "reason", func() string { + if cs.State.Waiting != nil { + return cs.State.Waiting.Reason + } + return "" + }()) + if cs.State.Waiting != nil && cs.State.Waiting.Reason == "ContainerCreating" { + hasContainerCreating = true + break + } + } - for _, event := range eventList.Items { - if event.Type != corev1.EventTypeWarning { + log.Info("checkPodVolumeErrors", "hasContainerCreating", hasContainerCreating) + + if !hasContainerCreating { + continue + } + + eventList := &corev1.EventList{} + err := h.client.List(ctx, eventList, &client.ListOptions{ + Namespace: pod.Namespace, + FieldSelector: fields.SelectorFromSet(fields.Set{ + "involvedObject.name": pod.Name, + "involvedObject.kind": "Pod", + }), + }) + if err != nil { + log.Error("Failed to list pod events", "error", err) continue } - if event.Reason == "FailedAttachVolume" || event.Reason == "FailedMount" { - return fmt.Errorf("%s: %s", event.Reason, event.Message) + log.Info("checkPodVolumeErrors events", "count", len(eventList.Items)) + + for _, event := range eventList.Items { + log.Info("checkPodVolumeErrors event", "type", event.Type, "reason", event.Reason, "message", event.Message) + if event.Type != corev1.EventTypeWarning { + continue + } + + if event.Reason == "FailedAttachVolume" || event.Reason == "FailedMount" { + log.Info("checkPodVolumeErrors FOUND ERROR", "reason", event.Reason, "message", event.Message) + return fmt.Errorf("%s: %s", event.Reason, event.Message) + } } } + log.Info("checkPodVolumeErrors returning nil") return nil } diff --git a/images/virtualization-artifact/pkg/controller/vm/internal/watcher/volumeevent_watcher.go b/images/virtualization-artifact/pkg/controller/vm/internal/watcher/volumeevent_watcher.go index e64384cbe9..63a391fc24 100644 --- a/images/virtualization-artifact/pkg/controller/vm/internal/watcher/volumeevent_watcher.go +++ b/images/virtualization-artifact/pkg/controller/vm/internal/watcher/volumeevent_watcher.go @@ -70,6 +70,8 @@ func (w *VolumeEventWatcher) Watch(mgr manager.Manager, ctr controller.Controlle return nil } + fmt.Printf("VolumeEventWatcher: TRIGGERING reconciliation for VM %s, event count=%d, reason=%s\n", vmName, e.Count, e.Reason) + return []reconcile.Request{ { NamespacedName: types.NamespacedName{ @@ -82,12 +84,11 @@ func (w *VolumeEventWatcher) Watch(mgr manager.Manager, ctr controller.Controlle predicate.TypedFuncs[*corev1.Event]{ CreateFunc: func(e event.TypedCreateEvent[*corev1.Event]) bool { return e.Object.Type == corev1.EventTypeWarning && - (e.Object.Reason == "FailedAttachVolume" || e.Object.Reason == "FailedMount") + (e.Object.Reason == "FailedAttachVolume" || e.Object.Reason == "FailedMount") && + e.Object.Count == 1 }, UpdateFunc: func(e event.TypedUpdateEvent[*corev1.Event]) bool { - return e.ObjectNew.Type == corev1.EventTypeWarning && - (e.ObjectNew.Reason == "FailedAttachVolume" || e.ObjectNew.Reason == "FailedMount") && - e.ObjectOld.Count != e.ObjectNew.Count + return false }, DeleteFunc: func(e event.TypedDeleteEvent[*corev1.Event]) bool { return false diff --git a/images/virtualization-artifact/pkg/controller/vm/vm_controller.go b/images/virtualization-artifact/pkg/controller/vm/vm_controller.go index 1cd2ad4433..f86a3a6fe9 100644 --- a/images/virtualization-artifact/pkg/controller/vm/vm_controller.go +++ b/images/virtualization-artifact/pkg/controller/vm/vm_controller.go @@ -20,8 +20,10 @@ import ( "context" "time" + corev1 "k8s.io/api/core/v1" "k8s.io/utils/ptr" "sigs.k8s.io/controller-runtime/pkg/builder" + "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/manager" "sigs.k8s.io/controller-runtime/pkg/metrics" @@ -43,6 +45,24 @@ const ( ControllerName = "vm-controller" ) +func setupEventIndexes(ctx context.Context, mgr manager.Manager) error { + if err := mgr.GetFieldIndexer().IndexField(ctx, &corev1.Event{}, "involvedObject.name", func(obj client.Object) []string { + event := obj.(*corev1.Event) + return []string{event.InvolvedObject.Name} + }); err != nil { + return err + } + + if err := mgr.GetFieldIndexer().IndexField(ctx, &corev1.Event{}, "involvedObject.kind", func(obj client.Object) []string { + event := obj.(*corev1.Event) + return []string{event.InvolvedObject.Kind} + }); err != nil { + return err + } + + return nil +} + func SetupController( ctx context.Context, mgr manager.Manager, @@ -50,6 +70,10 @@ func SetupController( dvcrSettings *dvcr.Settings, firmwareImage string, ) error { + if err := setupEventIndexes(ctx, mgr); err != nil { + return err + } + recorder := eventrecord.NewEventRecorderLogger(mgr, ControllerName) mgrCache := mgr.GetCache() client := mgr.GetClient() From 96097c88ca584dacdf3e781106825a8704943855 Mon Sep 17 00:00:00 2001 From: Daniil Loktev Date: Sun, 30 Nov 2025 16:23:14 +0300 Subject: [PATCH 5/7] wip Signed-off-by: Daniil Loktev --- .../pkg/controller/vm/internal/lifecycle.go | 18 +----------------- .../vm/internal/watcher/volumeevent_watcher.go | 5 +---- 2 files changed, 2 insertions(+), 21 deletions(-) diff --git a/images/virtualization-artifact/pkg/controller/vm/internal/lifecycle.go b/images/virtualization-artifact/pkg/controller/vm/internal/lifecycle.go index d394dde7d9..b95e5295ad 100644 --- a/images/virtualization-artifact/pkg/controller/vm/internal/lifecycle.go +++ b/images/virtualization-artifact/pkg/controller/vm/internal/lifecycle.go @@ -226,34 +226,23 @@ func (h *LifeCycleHandler) checkPodVolumeErrors(ctx context.Context, vm *v1alpha return nil } - log.Info("checkPodVolumeErrors", "podCount", len(podList.Items)) - if len(podList.Items) == 0 { return nil } - for _, pod := range podList.Items { - log.Info("checkPodVolumeErrors pod", "name", pod.Name, "phase", pod.Status.Phase, "containerStatuses", len(pod.Status.ContainerStatuses)) + for _, pod := range podList.Items { if pod.Status.Phase != corev1.PodPending { continue } hasContainerCreating := false for _, cs := range pod.Status.ContainerStatuses { - log.Info("checkPodVolumeErrors container", "name", cs.Name, "waiting", cs.State.Waiting != nil, "reason", func() string { - if cs.State.Waiting != nil { - return cs.State.Waiting.Reason - } - return "" - }()) if cs.State.Waiting != nil && cs.State.Waiting.Reason == "ContainerCreating" { hasContainerCreating = true break } } - log.Info("checkPodVolumeErrors", "hasContainerCreating", hasContainerCreating) - if !hasContainerCreating { continue } @@ -271,21 +260,16 @@ func (h *LifeCycleHandler) checkPodVolumeErrors(ctx context.Context, vm *v1alpha continue } - log.Info("checkPodVolumeErrors events", "count", len(eventList.Items)) - for _, event := range eventList.Items { - log.Info("checkPodVolumeErrors event", "type", event.Type, "reason", event.Reason, "message", event.Message) if event.Type != corev1.EventTypeWarning { continue } if event.Reason == "FailedAttachVolume" || event.Reason == "FailedMount" { - log.Info("checkPodVolumeErrors FOUND ERROR", "reason", event.Reason, "message", event.Message) return fmt.Errorf("%s: %s", event.Reason, event.Message) } } } - log.Info("checkPodVolumeErrors returning nil") return nil } diff --git a/images/virtualization-artifact/pkg/controller/vm/internal/watcher/volumeevent_watcher.go b/images/virtualization-artifact/pkg/controller/vm/internal/watcher/volumeevent_watcher.go index 63a391fc24..79ae2d2f45 100644 --- a/images/virtualization-artifact/pkg/controller/vm/internal/watcher/volumeevent_watcher.go +++ b/images/virtualization-artifact/pkg/controller/vm/internal/watcher/volumeevent_watcher.go @@ -70,8 +70,6 @@ func (w *VolumeEventWatcher) Watch(mgr manager.Manager, ctr controller.Controlle return nil } - fmt.Printf("VolumeEventWatcher: TRIGGERING reconciliation for VM %s, event count=%d, reason=%s\n", vmName, e.Count, e.Reason) - return []reconcile.Request{ { NamespacedName: types.NamespacedName{ @@ -84,8 +82,7 @@ func (w *VolumeEventWatcher) Watch(mgr manager.Manager, ctr controller.Controlle predicate.TypedFuncs[*corev1.Event]{ CreateFunc: func(e event.TypedCreateEvent[*corev1.Event]) bool { return e.Object.Type == corev1.EventTypeWarning && - (e.Object.Reason == "FailedAttachVolume" || e.Object.Reason == "FailedMount") && - e.Object.Count == 1 + (e.Object.Reason == "FailedAttachVolume" || e.Object.Reason == "FailedMount") }, UpdateFunc: func(e event.TypedUpdateEvent[*corev1.Event]) bool { return false From a991b8d915872d2310cfd2192327a57eff4f0487 Mon Sep 17 00:00:00 2001 From: Daniil Loktev Date: Sun, 30 Nov 2025 16:56:45 +0300 Subject: [PATCH 6/7] wip Signed-off-by: Daniil Loktev --- .mirrord/security-policy-exception.yaml | 33 -------------------- images/virtualization-artifact/Taskfile.yaml | 3 +- 2 files changed, 1 insertion(+), 35 deletions(-) delete mode 100644 .mirrord/security-policy-exception.yaml diff --git a/.mirrord/security-policy-exception.yaml b/.mirrord/security-policy-exception.yaml deleted file mode 100644 index ccdfb1c6b1..0000000000 --- a/.mirrord/security-policy-exception.yaml +++ /dev/null @@ -1,33 +0,0 @@ -apiVersion: deckhouse.io/v1alpha1 -kind: SecurityPolicyException -metadata: - name: mirrord-agent-exception - namespace: default -spec: - network: - hostPID: - allowedValue: true - metadata: - description: "Required for mirrord agent to attach to target container" - securityContext: - capabilities: - allowedValues: - add: - - NET_ADMIN - - NET_RAW - - SYS_ADMIN - - SYS_PTRACE - - SYS_RESOURCE - drop: - - ALL - volumes: - hostPath: - allowedValues: - - path: /run - readOnly: false - metadata: - description: "Required for mirrord agent container runtime access" - - path: /var - readOnly: false - metadata: - description: "Required for mirrord agent container runtime access" diff --git a/images/virtualization-artifact/Taskfile.yaml b/images/virtualization-artifact/Taskfile.yaml index d96716bfd6..122ad42a16 100644 --- a/images/virtualization-artifact/Taskfile.yaml +++ b/images/virtualization-artifact/Taskfile.yaml @@ -75,8 +75,7 @@ tasks: TMPDIR=/tmp ./hack/mirrord.sh run --app=$PWD/cmd/virtualization-controller/main.go \ --deployment=virtualization-controller \ --namespace={{ .BaseNamespace }} \ - --container-name=virtualization-controller \ - --flags="--leader-election=false" + --container-name=virtualization-controller mirrord:wipe:controller: desc: "wipe up Mirrord's trash" From 4a4ecdd66e1c90c6a5713dd8821645e52593ae66 Mon Sep 17 00:00:00 2001 From: Daniil Loktev Date: Mon, 1 Dec 2025 11:16:18 +0300 Subject: [PATCH 7/7] wip Signed-off-by: Daniil Loktev --- .../pkg/controller/vm/internal/network.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/images/virtualization-artifact/pkg/controller/vm/internal/network.go b/images/virtualization-artifact/pkg/controller/vm/internal/network.go index f573ffef84..bcceb918a6 100644 --- a/images/virtualization-artifact/pkg/controller/vm/internal/network.go +++ b/images/virtualization-artifact/pkg/controller/vm/internal/network.go @@ -170,6 +170,8 @@ func extractNetworkStatusFromPods(pods *corev1.PodList) (string, error) { if !found { if pod.Status.Phase == corev1.PodRunning { errorMessages = append(errorMessages, "Cannot determine the status of additional interfaces, waiting for a response from the SDN module") + } else { + errorMessages = append(errorMessages, "Waiting for virt-launcher pod to start") } continue }