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

Prod: Added hooks to trap and report backup and restore status of KubeVirt VMs #12

Merged
merged 1 commit into from
Nov 12, 2024
Merged
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
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ HUGO_IMAGE := hugo-builder
local : ARCH ?= $(shell go env GOOS)-$(shell go env GOARCH)
ARCH ?= linux-amd64

VERSION ?= v1.14.0.6
VERSION ?= v1.14.0.6-1

TAG_LATEST ?= false

Expand Down
45 changes: 43 additions & 2 deletions pkg/backup/item_backupper.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import (
"github.com/vmware-tanzu/velero/pkg/podvolume"
"github.com/vmware-tanzu/velero/pkg/util/boolptr"
csiutil "github.com/vmware-tanzu/velero/pkg/util/csi"
kubevirtutil "github.com/vmware-tanzu/velero/pkg/util/kubevirt"
)

const (
Expand Down Expand Up @@ -92,7 +93,28 @@ type FileForArchive struct {
// In addition to the error return, backupItem also returns a bool indicating whether the item
// was actually backed up.
func (ib *itemBackupper) backupItem(logger logrus.FieldLogger, obj runtime.Unstructured, groupResource schema.GroupResource, preferredGVR schema.GroupVersionResource, mustInclude, finalize bool) (bool, []FileForArchive, error) {
metadata, err := meta.Accessor(obj)
if err != nil {
return false, nil, err
}
name := metadata.GetName()
namespace := metadata.GetNamespace()

// Check if this is a KubeVirt VM resource
isKubeVirtVM := kubevirtutil.IsKubeVirtVMResource(groupResource)

// Call KubeVirt VM start reporting only if this is a KubeVirt VM resource
if isKubeVirtVM {
kubevirtutil.KubeVirtVMStartOp(logger, name, namespace, ib.backupRequest.Backup, ib.kbClient)
}

selectedForBackup, files, err := ib.backupItemInternal(logger, obj, groupResource, preferredGVR, mustInclude, finalize)

// Report result of the primary KubeVirt VM resource backup if it's a KubeVirt VM
if isKubeVirtVM {
kubevirtutil.KubeVirtVMOpResult(logger, groupResource, name, namespace, ib.backupRequest.Backup, selectedForBackup && err == nil, err, ib.kbClient)
}

// return if not selected, an error occurred, there are no files to add, or for finalize
if !selectedForBackup || err != nil || len(files) == 0 || finalize {
return selectedForBackup, files, err
Expand Down Expand Up @@ -387,10 +409,15 @@ func (ib *itemBackupper) executeActions(
finalize bool,
) (runtime.Unstructured, []FileForArchive, error) {
var itemFiles []FileForArchive

// Check if this is a KubeVirt VM resource
isKubeVirtVM := kubevirtutil.IsKubeVirtVMResource(groupResource)

for _, action := range ib.backupRequest.ResolvedActions {
if !action.ShouldUse(groupResource, namespace, metadata, log) {
continue
}

log.Info("Executing custom action")
actionName := action.Name()
if act, err := ib.getMatchAction(obj, groupResource, actionName); err != nil {
Expand Down Expand Up @@ -494,7 +521,6 @@ func (ib *itemBackupper) executeActions(
}

item, err := client.Get(additionalItem.Name, metav1.GetOptions{})

if apierrors.IsNotFound(err) {
log.WithFields(logrus.Fields{
"groupResource": additionalItem.GroupResource,
Expand All @@ -507,7 +533,22 @@ func (ib *itemBackupper) executeActions(
return nil, itemFiles, errors.WithStack(err)
}

_, additionalItemFiles, err := ib.backupItem(log, item, gvr.GroupResource(), gvr, mustInclude, finalize)
// Back up the additional item and report its result for KubeVirt VM
backedUp, additionalItemFiles, err := ib.backupItem(log, item, gvr.GroupResource(), gvr, mustInclude, finalize)
// Record and report the additional item with its backup result for KubeVirt VM
if isKubeVirtVM {
kubevirtutil.KubeVirtVMAdditionalResourceOpResult(
log,
gvr.GroupResource(),
name, namespace,
additionalItem.Name, additionalItem.Namespace,
ib.backupRequest.Backup,
backedUp && err == nil,
err,
ib.kbClient,
)
}

if err != nil {
return nil, itemFiles, err
}
Expand Down
53 changes: 53 additions & 0 deletions pkg/restore/restore.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ import (
csiutil "github.com/vmware-tanzu/velero/pkg/util/csi"
"github.com/vmware-tanzu/velero/pkg/util/filesystem"
"github.com/vmware-tanzu/velero/pkg/util/kube"
kubevirtutil "github.com/vmware-tanzu/velero/pkg/util/kubevirt"
"github.com/vmware-tanzu/velero/pkg/util/results"
)

Expand Down Expand Up @@ -368,6 +369,7 @@ type restoreContext struct {
backupVolumeInfoMap map[string]volume.BackupVolumeInfo
restoreVolumeInfoTracker *volume.RestoreVolumeInfoTracker
hooksWaitExecutor *hooksWaitExecutor
vmRelatedAdditionalItems map[kubevirtutil.ItemKey]kubevirtutil.ItemKey // Map to track VM's additional items
}

type resourceClientKey struct {
Expand Down Expand Up @@ -415,6 +417,8 @@ type progressUpdate struct {
}

func (ctx *restoreContext) execute() (results.Result, results.Result) {
ctx.vmRelatedAdditionalItems = make(map[kubevirtutil.ItemKey]kubevirtutil.ItemKey)

warnings, errs := results.Result{}, results.Result{}

ctx.log.Infof("Starting restore of backup %s", kube.NamespaceAndName(ctx.backup))
Expand Down Expand Up @@ -1326,6 +1330,23 @@ func (ctx *restoreContext) restoreItem(obj *unstructured.Unstructured, groupReso
return warnings, errs, itemExists
}

// After restore actions, check if it's a KubeVirt VM and track additional items
if kubevirtutil.IsKubeVirtVMResource(groupResource) {
// Log the start of the VM restore
kubevirtutil.KubeVirtVMStartOp(ctx.log, obj.GetName(), obj.GetNamespace(), ctx.restore, ctx.kbClient)

// Save the VM's name and namespace for tracking additional items
vmName := obj.GetName()
vmNamespace := obj.GetNamespace()

// Store additional items in the context's tracking map
for _, additionalItem := range executeOutput.AdditionalItems {
vmKey := kubevirtutil.ItemKey{Resource: groupResource.String(), Namespace: vmNamespace, Name: vmName}
additionalKey := kubevirtutil.ItemKey{Resource: additionalItem.GroupResource.String(), Namespace: additionalItem.Namespace, Name: additionalItem.Name}
ctx.vmRelatedAdditionalItems[additionalKey] = vmKey
}
}

// If async plugin started async operation, add it to the ItemOperations list
if executeOutput.OperationID != "" {
resourceIdentifier := velero.ResourceIdentifier{
Expand Down Expand Up @@ -1395,6 +1416,22 @@ func (ctx *restoreContext) restoreItem(obj *unstructured.Unstructured, groupReso
filteredAdditionalItems = append(filteredAdditionalItems, additionalItem)
}

additionalKey := kubevirtutil.ItemKey{Resource: additionalItem.GroupResource.String(), Namespace: additionalItem.Namespace, Name: additionalItem.Name}
if vmKey, ok := ctx.vmRelatedAdditionalItems[additionalKey]; ok {
kubevirtutil.KubeVirtVMAdditionalResourceOpResult(
ctx.log,
additionalItem.GroupResource,
vmKey.Name,
vmKey.Namespace,
additionalItem.Name,
additionalItem.Namespace,
ctx.restore,
additionalItemExists,
nil,
ctx.kbClient,
)
}

warnings.Merge(&w)
errs.Merge(&e)
}
Expand Down Expand Up @@ -1737,6 +1774,22 @@ func (ctx *restoreContext) restoreItem(obj *unstructured.Unstructured, groupReso
}
}

// Call kubeVirtVMOpResult only if this is the primary KubeVirt VM resource
if kubevirtutil.IsKubeVirtVMResource(groupResource) {
// Determine success status based on the presence of errors
success := errs.IsEmpty()

kubevirtutil.KubeVirtVMOpResult(
ctx.log,
groupResource,
obj.GetName(),
obj.GetNamespace(),
ctx.restore,
success, // Success status based on error presence
kubevirtutil.ToError(errs), // Convert errs to an error if applicable
ctx.kbClient,
)
}
return warnings, errs, itemExists
}

Expand Down
Loading
Loading