Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(vmsnapshot): add new events #634

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions api/core/v1alpha2/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,19 @@ const (

// ReasonDataSourceDiskProvisioningFailed is event reason that DataSource disk provisioning is failed.
ReasonDataSourceDiskProvisioningFailed = "DataSourceImportDiskProvisioningFailed"

// ReasonVMSnapshottingStarted is event reason that VirtualMachine snapshotting is started.
ReasonVMSnapshottingStarted = "VirtualMachineSnapshottingStarted"

// ReasonVMSnapshottingInProgress is event reason that VirtualMachine snapshotting is in progress.
ReasonVMSnapshottingInProgress = "VirtualMachineSnapshottingInProgress"

// ReasonVMSnapshottingPending is event reason that VirtualMachine is not ready for snapshotting.
ReasonVMSnapshottingPending = "VirtualMachineSnapshottingPending"

// ReasonVMSnapshottingCompleted is event reason that VirtualMachine snapshotting is completed.
ReasonVMSnapshottingCompleted = "VirtualMachineSnapshottingCompleted"

// ReasonVMSnapshottingFailed is event reason that VirtualMachine snapshotting is failed.
ReasonVMSnapshottingFailed = "VirtualMachineSnapshottingFailed"
)
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (

"github.com/deckhouse/virtualization-controller/pkg/controller/conditions"
"github.com/deckhouse/virtualization-controller/pkg/controller/service"
"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/vdcondition"
Expand All @@ -38,12 +39,14 @@ import (
)

type LifeCycleHandler struct {
recorder eventrecord.EventRecorderLogger
snapshotter Snapshotter
storer Storer
}

func NewLifeCycleHandler(snapshotter Snapshotter, storer Storer) *LifeCycleHandler {
func NewLifeCycleHandler(recorder eventrecord.EventRecorderLogger, snapshotter Snapshotter, storer Storer) *LifeCycleHandler {
return &LifeCycleHandler{
recorder: recorder,
snapshotter: snapshotter,
storer: storer,
}
Expand All @@ -61,7 +64,7 @@ func (h LifeCycleHandler) Handle(ctx context.Context, vmSnapshot *virtv2.Virtual

vm, err := h.snapshotter.GetVirtualMachine(ctx, vmSnapshot.Spec.VirtualMachineName, vmSnapshot.Namespace)
if err != nil {
setPhaseConditionToFailed(cb, &vmSnapshot.Status.Phase, err)
setPhaseConditionToFailed(h, cb, vmSnapshot, err)
return reconcile.Result{}, err
}

Expand All @@ -74,7 +77,7 @@ func (h LifeCycleHandler) Handle(ctx context.Context, vmSnapshot *virtv2.Virtual

_, err = h.unfreezeVirtualMachineIfCan(ctx, vmSnapshot, vm)
if err != nil {
setPhaseConditionToFailed(cb, &vmSnapshot.Status.Phase, err)
setPhaseConditionToFailed(h, cb, vmSnapshot, err)
return reconcile.Result{}, err
}

Expand All @@ -97,7 +100,7 @@ func (h LifeCycleHandler) Handle(ctx context.Context, vmSnapshot *virtv2.Virtual
for _, vdSnapshotName := range vmSnapshot.Status.VirtualDiskSnapshotNames {
vdSnapshot, err := h.snapshotter.GetVirtualDiskSnapshot(ctx, vdSnapshotName, vmSnapshot.Namespace)
if err != nil {
setPhaseConditionToFailed(cb, &vmSnapshot.Status.Phase, err)
setPhaseConditionToFailed(h, cb, vmSnapshot, err)
return reconcile.Result{}, err
}

Expand All @@ -113,14 +116,19 @@ func (h LifeCycleHandler) Handle(ctx context.Context, vmSnapshot *virtv2.Virtual
vmSnapshot.Status.Phase = virtv2.VirtualMachineSnapshotPhaseFailed
cb.Status(metav1.ConditionFalse).Reason(vmscondition.VirtualDiskSnapshotLost)
if len(lostVDSnapshots) == 1 {
cb.Message(fmt.Sprintf("The underlieng virtual disk snapshot (%s) is lost.", lostVDSnapshots[0]))
msg := fmt.Sprintf("The underlieng virtual disk snapshot (%s) is lost.", lostVDSnapshots[0])
h.recorder.Event(vmSnapshot, corev1.EventTypeWarning, virtv2.ReasonVMSnapshottingFailed, msg)
cb.Message(msg)
} else {
cb.Message(fmt.Sprintf("The underlieng virtual disk snapshots (%s) are lost.", strings.Join(lostVDSnapshots, ", ")))
msg := fmt.Sprintf("The underlieng virtual disk snapshots (%s) are lost.", strings.Join(lostVDSnapshots, ", "))
h.recorder.Event(vmSnapshot, corev1.EventTypeWarning, virtv2.ReasonVMSnapshottingFailed, msg)
cb.Message(msg)
}
return reconcile.Result{}, nil
}

vmSnapshot.Status.Phase = virtv2.VirtualMachineSnapshotPhaseReady
h.recorder.Event(vmSnapshot, corev1.EventTypeNormal, virtv2.ReasonVMSnapshottingCompleted, "Virtual machine snapshotting process is completed")
cb.
Status(metav1.ConditionTrue).
Reason(vmscondition.VirtualMachineSnapshotReady).
Expand All @@ -131,10 +139,12 @@ func (h LifeCycleHandler) Handle(ctx context.Context, vmSnapshot *virtv2.Virtual
virtualMachineReadyCondition, _ := conditions.GetCondition(vmscondition.VirtualMachineReadyType, vmSnapshot.Status.Conditions)
if vm == nil || virtualMachineReadyCondition.Status != metav1.ConditionTrue {
vmSnapshot.Status.Phase = virtv2.VirtualMachineSnapshotPhasePending
msg := fmt.Sprintf("Waiting for the virtual machine %q to be ready for snapshotting.", vmSnapshot.Spec.VirtualMachineName)
h.recorder.Event(vmSnapshot, corev1.EventTypeWarning, virtv2.ReasonVMSnapshottingPending, msg)
cb.
Status(metav1.ConditionFalse).
Reason(vmscondition.WaitingForTheVirtualMachine).
Message(fmt.Sprintf("Waiting for the virtual machine %q to be ready for snapshotting.", vmSnapshot.Spec.VirtualMachineName))
Message(msg)
return reconcile.Result{}, nil
}

Expand All @@ -144,26 +154,29 @@ func (h LifeCycleHandler) Handle(ctx context.Context, vmSnapshot *virtv2.Virtual
case err == nil:
case errors.Is(err, ErrBlockDevicesNotReady), errors.Is(err, ErrVirtualDiskNotReady), errors.Is(err, ErrVirtualDiskResizing):
vmSnapshot.Status.Phase = virtv2.VirtualMachineSnapshotPhasePending
msg := service.CapitalizeFirstLetter(err.Error() + ".")
h.recorder.Event(vmSnapshot, corev1.EventTypeWarning, virtv2.ReasonVMSnapshottingPending, msg)
cb.
Status(metav1.ConditionFalse).
Reason(vmscondition.BlockDevicesNotReady).
Message(service.CapitalizeFirstLetter(err.Error() + "."))
Message(msg)
return reconcile.Result{}, nil
default:
setPhaseConditionToFailed(cb, &vmSnapshot.Status.Phase, err)
setPhaseConditionToFailed(h, cb, vmSnapshot, err)
return reconcile.Result{}, err
}

// 2. Ensure there are no RestartAwaitingChanges.
if len(vm.Status.RestartAwaitingChanges) > 0 {
vmSnapshot.Status.Phase = virtv2.VirtualMachineSnapshotPhasePending
msg := fmt.Sprintf(
"Waiting for the restart and approval of changes to virtual machine %q before taking the snapshot.",
vm.Name,
)
h.recorder.Event(vmSnapshot, corev1.EventTypeNormal, virtv2.ReasonVMSnapshottingPending, msg)
cb.
Status(metav1.ConditionFalse).
Reason(vmscondition.RestartAwaitingChanges).Message(
fmt.Sprintf(
"Waiting for the restart and approval of changes to virtual machine %q before taking the snapshot.",
vm.Name,
))
Reason(vmscondition.RestartAwaitingChanges).Message(msg)
return reconcile.Result{}, nil
}

Expand All @@ -172,14 +185,16 @@ func (h LifeCycleHandler) Handle(ctx context.Context, vmSnapshot *virtv2.Virtual
isAwaitingConsistency := needToFreeze && !h.snapshotter.CanFreeze(vm) && vmSnapshot.Spec.RequiredConsistency
if isAwaitingConsistency {
vmSnapshot.Status.Phase = virtv2.VirtualMachineSnapshotPhasePending
msg := fmt.Sprintf(
"The snapshotting of virtual machine %q might result in an inconsistent snapshot: "+
"waiting for the virtual machine to be %s",
vm.Name, virtv2.MachineStopped,
)
h.recorder.Event(vmSnapshot, corev1.EventTypeNormal, virtv2.ReasonVMSnapshottingPending, msg)
cb.
Status(metav1.ConditionFalse).
Reason(vmscondition.PotentiallyInconsistent).
Message(fmt.Sprintf(
"The snapshotting of virtual machine %q might result in an inconsistent snapshot: "+
"waiting for the virtual machine to be %s",
vm.Name, virtv2.MachineStopped,
))
Message(msg)
return reconcile.Result{}, nil
}

Expand All @@ -198,24 +213,26 @@ func (h LifeCycleHandler) Handle(ctx context.Context, vmSnapshot *virtv2.Virtual
if needToFreeze {
hasFrozen, err = h.freezeVirtualMachine(ctx, vm)
if err != nil {
setPhaseConditionToFailed(cb, &vmSnapshot.Status.Phase, err)
setPhaseConditionToFailed(h, cb, vmSnapshot, err)
return reconcile.Result{}, err
}
}

if hasFrozen {
vmSnapshot.Status.Phase = virtv2.VirtualMachineSnapshotPhaseInProgress
msg := fmt.Sprintf("The virtual machine %q is in the process of being frozen for taking a snapshot.", vm.Name)
h.recorder.Event(vmSnapshot, corev1.EventTypeNormal, virtv2.ReasonVMSnapshottingInProgress, msg)
cb.
Status(metav1.ConditionFalse).
Reason(vmscondition.FileSystemFreezing).
Message(fmt.Sprintf("The virtual machine %q is in the process of being frozen for taking a snapshot.", vm.Name))
Message(msg)
return reconcile.Result{}, nil
}

// 4. Create secret.
err = h.ensureSecret(ctx, vm, vmSnapshot)
if err != nil {
setPhaseConditionToFailed(cb, &vmSnapshot.Status.Phase, err)
setPhaseConditionToFailed(h, cb, vmSnapshot, err)
return reconcile.Result{}, err
}

Expand All @@ -229,6 +246,7 @@ func (h LifeCycleHandler) Handle(ctx context.Context, vmSnapshot *virtv2.Virtual
case errors.Is(err, ErrVolumeSnapshotClassNotFound), errors.Is(err, ErrCannotTakeSnapshot):
vmSnapshot.Status.Phase = virtv2.VirtualMachineSnapshotPhaseFailed
msg := service.CapitalizeFirstLetter(err.Error())
h.recorder.Event(vmSnapshot, corev1.EventTypeWarning, virtv2.ReasonVMSnapshottingFailed, msg)
if !strings.HasSuffix(msg, ".") {
msg += "."
}
Expand All @@ -238,7 +256,7 @@ func (h LifeCycleHandler) Handle(ctx context.Context, vmSnapshot *virtv2.Virtual
Message(msg)
return reconcile.Result{}, nil
default:
setPhaseConditionToFailed(cb, &vmSnapshot.Status.Phase, err)
setPhaseConditionToFailed(h, cb, vmSnapshot, err)
return reconcile.Result{}, err
}

Expand All @@ -249,14 +267,16 @@ func (h LifeCycleHandler) Handle(ctx context.Context, vmSnapshot *virtv2.Virtual
log.Debug("Waiting for the virtual disk snapshots to be taken for the block devices of the virtual machine")

vmSnapshot.Status.Phase = virtv2.VirtualMachineSnapshotPhaseInProgress
msg := fmt.Sprintf(
"Waiting for the virtual disk snapshots to be taken for "+
"the block devices of the virtual machine %q (%d/%d).",
vm.Name, readyCount, len(vdSnapshots),
)
h.recorder.Event(vmSnapshot, corev1.EventTypeNormal, virtv2.ReasonVMSnapshottingInProgress, msg)
cb.
Status(metav1.ConditionFalse).
Reason(vmscondition.Snapshotting).
Message(fmt.Sprintf(
"Waiting for the virtual disk snapshots to be taken for "+
"the block devices of the virtual machine %q (%d/%d).",
vm.Name, readyCount, len(vdSnapshots),
))
Message(msg)
return reconcile.Result{}, nil
}

Expand All @@ -268,14 +288,15 @@ func (h LifeCycleHandler) Handle(ctx context.Context, vmSnapshot *virtv2.Virtual
// 8. Unfreeze VirtualMachine if can.
unfrozen, err := h.unfreezeVirtualMachineIfCan(ctx, vmSnapshot, vm)
if err != nil {
setPhaseConditionToFailed(cb, &vmSnapshot.Status.Phase, err)
setPhaseConditionToFailed(h, cb, vmSnapshot, err)
return reconcile.Result{}, err
}

// 9. Move to Ready phase.
log.Debug("The virtual disk snapshots are taken: the virtual machine snapshot is Ready now", "unfrozen", unfrozen)

vmSnapshot.Status.Phase = virtv2.VirtualMachineSnapshotPhaseReady
h.recorder.Event(vmSnapshot, corev1.EventTypeNormal, virtv2.ReasonVMSnapshottingCompleted, "Virtual machine snapshotting process is completed")
cb.
Status(metav1.ConditionTrue).
Reason(vmscondition.VirtualMachineReady).
Expand All @@ -284,8 +305,9 @@ func (h LifeCycleHandler) Handle(ctx context.Context, vmSnapshot *virtv2.Virtual
return reconcile.Result{}, nil
}

func setPhaseConditionToFailed(cb *conditions.ConditionBuilder, phase *virtv2.VirtualMachineSnapshotPhase, err error) {
*phase = virtv2.VirtualMachineSnapshotPhaseFailed
func setPhaseConditionToFailed(h LifeCycleHandler, cb *conditions.ConditionBuilder, vmSnapshot *virtv2.VirtualMachineSnapshot, err error) {
vmSnapshot.Status.Phase = virtv2.VirtualMachineSnapshotPhaseFailed
h.recorder.Event(vmSnapshot, corev1.EventTypeWarning, virtv2.ReasonVMSnapshottingFailed, err.Error())
cb.
Status(metav1.ConditionFalse).
Reason(vmscondition.VirtualMachineSnapshotFailed).
Expand Down Expand Up @@ -510,6 +532,7 @@ func (h LifeCycleHandler) ensureSecret(ctx context.Context, vm *virtv2.VirtualMa
}

if secret == nil {
h.recorder.Event(vmSnapshot, corev1.EventTypeNormal, virtv2.ReasonVMSnapshottingStarted, "Virtual machine snapshotting process is started")
secret, err = h.storer.Store(ctx, vm, vmSnapshot)
if err != nil {
return err
Expand Down
Loading
Loading