Skip to content

Commit

Permalink
fix(vm): add stopping when vm have invalid spec
Browse files Browse the repository at this point in the history
Signed-off-by: dmitry.lopatin <[email protected]>
  • Loading branch information
LopatinDmitr committed Jan 29, 2025
1 parent 7992aef commit 2aff303
Showing 1 changed file with 86 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,19 @@ import (

corev1 "k8s.io/api/core/v1"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
virtv1 "kubevirt.io/api/core/v1"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/reconcile"

kvvmutil "github.com/deckhouse/virtualization-controller/pkg/common/kvvm"
"github.com/deckhouse/virtualization-controller/pkg/controller/conditions"
"github.com/deckhouse/virtualization-controller/pkg/controller/powerstate"
"github.com/deckhouse/virtualization-controller/pkg/controller/vm/internal/state"
"github.com/deckhouse/virtualization-controller/pkg/eventrecord"
"github.com/deckhouse/virtualization-controller/pkg/logger"
virtv2 "github.com/deckhouse/virtualization/api/core/v1alpha2"
"github.com/deckhouse/virtualization/api/core/v1alpha2/vmcondition"
)

const nameSyncPowerStateHandler = "SyncPowerStateHandler"
Expand Down Expand Up @@ -99,6 +102,12 @@ func (h *SyncPowerStateHandler) syncPowerState(ctx context.Context, s state.Virt
return fmt.Errorf("enforce runPolicy %s: %w", runPolicy, err)
}

canStartVM := true
confAppliedCondtion, _ := conditions.GetCondition(vmcondition.TypeConfigurationApplied, s.VirtualMachine().Changed().Status.Conditions)
if confAppliedCondtion.Status != metav1.ConditionTrue {
canStartVM = false
}

var shutdownInfo powerstate.ShutdownInfo
s.Shared(func(s *state.Shared) {
shutdownInfo = s.ShutdownInfo
Expand All @@ -120,18 +129,37 @@ func (h *SyncPowerStateHandler) syncPowerState(ctx context.Context, s state.Virt
}
case virtv2.AlwaysOnPolicy:
if kvvmi == nil {
h.recordStartEventf(ctx, s.VirtualMachine().Current(),
"Start initiated by controller for %v policy",
runPolicy,
)
if canStartVM {
h.recordStartEventf(ctx, s.VirtualMachine().Current(),
"Start initiated by controller for %v policy",
runPolicy,
)

if err = powerstate.StartVM(ctx, h.client, kvvm); err != nil {
return fmt.Errorf("failed to start VM: %w", err)
if err = powerstate.StartVM(ctx, h.client, kvvm); err != nil {
return fmt.Errorf("failed to start VM: %w", err)
}
} else {
h.recordStopEventf(ctx, s.VirtualMachine().Current(),
"Stop initiated by controller - invalid VirtualMachine's configuration",
)
}
}

if kvvmi != nil && kvvmi.DeletionTimestamp == nil {
if kvvmi.Status.Phase == virtv1.Succeeded {
if !canStartVM {
h.recordStopEventf(ctx, s.VirtualMachine().Current(),
"Stop initiated by controller - invalid VirtualMachine's configuration",
)

// Ensure KVVMI is absent.
err = h.client.Delete(ctx, kvvmi)
if err != nil && !k8serrors.IsNotFound(err) {
return fmt.Errorf("delete KVVMI: %w", err)
}
return nil
}

if shutdownInfo.PodCompleted {
// Treat completed Pod as restart if guest was restarted or as a start if guest was stopped.
switch shutdownInfo.Reason {
Expand All @@ -157,6 +185,19 @@ func (h *SyncPowerStateHandler) syncPowerState(ctx context.Context, s state.Virt
}

if kvvmi.Status.Phase == virtv1.Failed {
if !canStartVM {
h.recordStopEventf(ctx, s.VirtualMachine().Current(),
"Stop initiated by controller - invalid VirtualMachine's configuration",
)

// Ensure KVVMI is absent.
err = h.client.Delete(ctx, kvvmi)
if err != nil && !k8serrors.IsNotFound(err) {
return fmt.Errorf("delete KVVMI: %w", err)
}
return nil
}

h.recordRestartEventf(ctx, s.VirtualMachine().Current(),
"Restart initiated by controller for %s runPolicy after observing failed guest VM",
runPolicy,
Expand All @@ -170,6 +211,19 @@ func (h *SyncPowerStateHandler) syncPowerState(ctx context.Context, s state.Virt
case virtv2.AlwaysOnUnlessStoppedManually:
if kvvmi != nil && kvvmi.DeletionTimestamp == nil {
if kvvmi.Status.Phase == virtv1.Succeeded {
if !canStartVM {
h.recordStopEventf(ctx, s.VirtualMachine().Current(),
"Stop initiated by controller - invalid VirtualMachine's configuration",
)

// Ensure KVVMI is absent.
err = h.client.Delete(ctx, kvvmi)
if err != nil && !k8serrors.IsNotFound(err) {
return fmt.Errorf("delete KVVMI: %w", err)
}
return nil
}

if shutdownInfo.PodCompleted {
// Request to start new KVVMI if guest was restarted.
// Cleanup KVVMI is enough if VM was stopped from inside.
Expand Down Expand Up @@ -210,6 +264,19 @@ func (h *SyncPowerStateHandler) syncPowerState(ctx context.Context, s state.Virt
}
}
if kvvmi.Status.Phase == virtv1.Failed {
if !canStartVM {
h.recordStopEventf(ctx, s.VirtualMachine().Current(),
"Stop initiated by controller - invalid VirtualMachine's configuration",
)

// Ensure KVVMI is absent.
err = h.client.Delete(ctx, kvvmi)
if err != nil && !k8serrors.IsNotFound(err) {
return fmt.Errorf("delete KVVMI: %w", err)
}
return nil
}

h.recordRestartEventf(ctx, s.VirtualMachine().Current(),
"Restart initiated by controller for %s runPolicy after observing failed guest VM",
runPolicy,
Expand All @@ -225,6 +292,19 @@ func (h *SyncPowerStateHandler) syncPowerState(ctx context.Context, s state.Virt
// All types of shutdown are final states.
if kvvmi != nil && kvvmi.DeletionTimestamp == nil {
if kvvmi.Status.Phase == virtv1.Succeeded && shutdownInfo.PodCompleted {
if !canStartVM {
h.recordStopEventf(ctx, s.VirtualMachine().Current(),
"Stop initiated by controller - invalid VirtualMachine's configuration",
)

// Ensure KVVMI is absent.
err = h.client.Delete(ctx, kvvmi)
if err != nil && !k8serrors.IsNotFound(err) {
return fmt.Errorf("delete KVVMI: %w", err)
}
return nil
}

// Request to start new KVVMI (with updated settings).
switch shutdownInfo.Reason {
case powerstate.GuestResetReason:
Expand Down

0 comments on commit 2aff303

Please sign in to comment.