From d91f1e3f5d70fd25f2f3598f84a71f1bda3f950b Mon Sep 17 00:00:00 2001 From: Jean-Marc ANDRE Date: Mon, 27 Feb 2023 00:54:43 +0100 Subject: [PATCH] Reworked the scheduling. Tasks are run by SessionState now and not by Target --- controllers/backupsession_controller.go | 148 ++++++++++-------- .../backupsession_controller_helpers.go | 11 +- formol | 2 +- 3 files changed, 91 insertions(+), 70 deletions(-) diff --git a/controllers/backupsession_controller.go b/controllers/backupsession_controller.go index 13f7cf8..4b29a1c 100644 --- a/controllers/backupsession_controller.go +++ b/controllers/backupsession_controller.go @@ -53,77 +53,93 @@ func (r *BackupSessionReconciler) Reconcile(ctx context.Context, req ctrl.Reques return ctrl.Result{}, err } - targetName := os.Getenv(formolv1alpha1.TARGET_NAME) + // targetName := os.Getenv(formolv1alpha1.TARGET_NAME) // we don't want a copy because we will modify and update it. - currentTargetStatus := &(backupSession.Status.Targets[len(backupSession.Status.Targets)-1]) - currentTarget := backupConf.Spec.Targets[len(backupSession.Status.Targets)-1] + var target formolv1alpha1.Target + var targetStatus *formolv1alpha1.TargetStatus var result error - if currentTargetStatus.TargetName == targetName { - // The current task is for us - var newSessionState formolv1alpha1.SessionState - switch currentTargetStatus.SessionState { - case formolv1alpha1.New: - r.Log.V(0).Info("New session, move to Initializing state") - newSessionState = formolv1alpha1.Init - case formolv1alpha1.Init: - r.Log.V(0).Info("Start to run the backup initializing steps is any") - // Runs the Steps functions in chroot env - if result = r.runInitializeBackupSteps(currentTarget); result != nil { - r.Log.Error(result, "unable to run the initialization steps") - newSessionState = formolv1alpha1.Finalize - } else { - newSessionState = formolv1alpha1.Running - } - case formolv1alpha1.Running: - r.Log.V(0).Info("Running state. Do the backup") - // Actually do the backup with restic - switch currentTarget.BackupType { - case formolv1alpha1.JobKind: - if backupResult, err := r.backupJob(backupSession.Name, currentTarget); err != nil { - r.Log.Error(err, "unable to run backup job", "target", targetName) - } else { - r.Log.V(0).Info("Backup Job is over", "target", targetName, "snapshotID", backupResult.SnapshotId, "duration", backupResult.Duration) - currentTargetStatus.SnapshotId = backupResult.SnapshotId - currentTargetStatus.Duration = &metav1.Duration{Duration: time.Now().Sub(currentTargetStatus.StartTime.Time)} - } - case formolv1alpha1.OnlineKind: - backupPaths := strings.Split(os.Getenv(formolv1alpha1.BACKUP_PATHS), string(os.PathListSeparator)) - if backupResult, result := r.backupPaths(backupSession.Name, backupPaths); result != nil { - r.Log.Error(result, "unable to backup paths", "target name", targetName, "paths", backupPaths) - } else { - r.Log.V(0).Info("Backup of the paths is over", "target name", targetName, "paths", backupPaths, - "snapshotID", backupResult.SnapshotId, "duration", backupResult.Duration) - currentTargetStatus.SnapshotId = backupResult.SnapshotId - currentTargetStatus.Duration = &metav1.Duration{Duration: time.Now().Sub(currentTargetStatus.StartTime.Time)} - } - } - newSessionState = formolv1alpha1.Finalize - case formolv1alpha1.Finalize: - r.Log.V(0).Info("Backup is over. Run the finalize steps is any") - // Runs the finalize Steps functions in chroot env - if result = r.runFinalizeBackupSteps(currentTarget); result != nil { - r.Log.Error(err, "unable to run finalize steps") - } - if currentTargetStatus.SnapshotId == "" { - newSessionState = formolv1alpha1.Failure - } else { - newSessionState = formolv1alpha1.Success - } - case formolv1alpha1.Success: - r.Log.V(0).Info("Backup is over") - case formolv1alpha1.Failure: - r.Log.V(0).Info("Backup is over") - } - if newSessionState != "" { - currentTargetStatus.SessionState = newSessionState - err := r.Status().Update(ctx, &backupSession) - if err != nil { - r.Log.Error(err, "unable to update BackupSession status") - } - return ctrl.Result{}, err + targetName := os.Getenv(formolv1alpha1.TARGET_NAME) + for i, t := range backupConf.Spec.Targets { + if t.TargetName == targetName { + target = t + targetStatus = &(backupSession.Status.Targets[i]) + break } } + + var newSessionState formolv1alpha1.SessionState + switch targetStatus.SessionState { + case formolv1alpha1.New: + // New session move to Initializing + r.Log.V(0).Info("New session. Move to Initializing state") + newSessionState = formolv1alpha1.Initializing + case formolv1alpha1.Initializing: + // Run the initializing Steps and then move to Initialized or Failure + r.Log.V(0).Info("Start to run the backup initializing steps is any") + // Runs the Steps functions in chroot env + if err := r.runInitializeBackupSteps(target); err != nil { + r.Log.Error(err, "unable to run the initialization steps") + newSessionState = formolv1alpha1.Failure + } else { + r.Log.V(0).Info("Done with the initializing Steps. Move to Initialized state") + newSessionState = formolv1alpha1.Initialized + } + case formolv1alpha1.Running: + // Actually do the backup and move to Waiting or Failure + r.Log.V(0).Info("Running state. Do the backup") + // Actually do the backup with restic + newSessionState = formolv1alpha1.Waiting + switch target.BackupType { + case formolv1alpha1.JobKind: + if backupResult, err := r.backupJob(backupSession.Name, target); err != nil { + r.Log.Error(err, "unable to run backup job", "target", targetName) + newSessionState = formolv1alpha1.Failure + } else { + r.Log.V(0).Info("Backup Job is over", "target", targetName, "snapshotID", backupResult.SnapshotId, "duration", backupResult.Duration) + targetStatus.SnapshotId = backupResult.SnapshotId + targetStatus.Duration = &metav1.Duration{Duration: time.Now().Sub(targetStatus.StartTime.Time)} + } + case formolv1alpha1.OnlineKind: + backupPaths := strings.Split(os.Getenv(formolv1alpha1.BACKUP_PATHS), string(os.PathListSeparator)) + if backupResult, result := r.backupPaths(backupSession.Name, backupPaths); result != nil { + r.Log.Error(result, "unable to backup paths", "target name", targetName, "paths", backupPaths) + newSessionState = formolv1alpha1.Failure + } else { + r.Log.V(0).Info("Backup of the paths is over", "target name", targetName, "paths", backupPaths, + "snapshotID", backupResult.SnapshotId, "duration", backupResult.Duration) + targetStatus.SnapshotId = backupResult.SnapshotId + targetStatus.Duration = &metav1.Duration{Duration: time.Now().Sub(targetStatus.StartTime.Time)} + } + } + r.Log.V(0).Info("Backup is over and is a success. Move to Waiting state") + case formolv1alpha1.Finalize: + // Run the finalize Steps and move to Success or Failure + r.Log.V(0).Info("Backup is over. Run the finalize steps is any") + // Runs the finalize Steps functions in chroot env + if result = r.runFinalizeBackupSteps(target); result != nil { + r.Log.Error(err, "unable to run finalize steps") + } + if targetStatus.SnapshotId == "" { + newSessionState = formolv1alpha1.Failure + } else { + newSessionState = formolv1alpha1.Success + } + case formolv1alpha1.Success: + // Target backup is a success + r.Log.V(0).Info("Backup was a success") + case formolv1alpha1.Failure: + // Target backup is a failure + } + if newSessionState != "" { + targetStatus.SessionState = newSessionState + err := r.Status().Update(ctx, &backupSession) + if err != nil { + r.Log.Error(err, "unable to update BackupSession status") + } + return ctrl.Result{}, err + } + return ctrl.Result{}, result } diff --git a/controllers/backupsession_controller_helpers.go b/controllers/backupsession_controller_helpers.go index d0321e1..fb03a4d 100644 --- a/controllers/backupsession_controller_helpers.go +++ b/controllers/backupsession_controller_helpers.go @@ -6,6 +6,7 @@ import ( "encoding/json" formolv1alpha1 "github.com/desmo999r/formol/api/v1alpha1" "io" + "io/fs" "io/ioutil" corev1 "k8s.io/api/core/v1" "os" @@ -181,7 +182,7 @@ func (r *BackupSessionReconciler) runInitializeBackupSteps(target formolv1alpha1 // Runs the given command in the target container chroot func (r *BackupSessionReconciler) runTargetContainerChroot(runCmd string, args ...string) error { env := regexp.MustCompile(`/proc/[0-9]+/environ`) - if err := filepath.Walk("/proc", func(path string, info os.FileInfo, err error) error { + if err := filepath.WalkDir("/proc", func(path string, info fs.DirEntry, err error) error { if err != nil { return nil } @@ -194,7 +195,7 @@ func (r *BackupSessionReconciler) runTargetContainerChroot(runCmd string, args . content, err := ioutil.ReadFile(path) // cannot read environ file. not the process we want to backup if err != nil { - return filepath.SkipDir + return fs.SkipDir } // Loops over the process environement variable looking for TARGETCONTAINER_TAG for _, env := range bytes.Split(content, []byte{'\000'}) { @@ -223,7 +224,11 @@ func (r *BackupSessionReconciler) runTargetContainerChroot(runCmd string, args . r.Log.V(0).Info("cmd output", "output", scanner.Text()) } - return cmd.Wait() + if err := cmd.Wait(); err != nil { + return err + } else { + return filepath.SkipAll + } } } } diff --git a/formol b/formol index b42bd46..b5a217b 160000 --- a/formol +++ b/formol @@ -1 +1 @@ -Subproject commit b42bd46efe822ddad250448d7ed2578efe5460f7 +Subproject commit b5a217bc3a536095084b48e19f935bc1508baedf