From 19599b1f8b320dcef2eef656dd35d1a625536fab Mon Sep 17 00:00:00 2001 From: Roman Dodin Date: Thu, 30 Mar 2023 13:24:13 +0200 Subject: [PATCH 1/2] generate checkpoint for nodes without startup config as well as for those with it --- controllers/startup_config.go | 73 +++++++++++++++++++++++------------ 1 file changed, 48 insertions(+), 25 deletions(-) diff --git a/controllers/startup_config.go b/controllers/startup_config.go index 598d002..22bcdf1 100644 --- a/controllers/startup_config.go +++ b/controllers/startup_config.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "path/filepath" + "strings" "time" "github.com/go-logr/logr" @@ -77,26 +78,15 @@ func (r *SrlinuxReconciler) handleSrlinuxStartupConfig( update *bool, srlinux *srlinuxv1.Srlinux, ) { - if srlinux.Status.StartupConfig.Phase == "loaded" || - srlinux.Status.StartupConfig.Phase == "failed" { - log.Info("startup config load already tried, skipping") + if srlinux.Status.StartupConfig.Phase != "" { + log.Info("startup config already processed, skipping") return } - // if startup config data is not provided and the state is not "not-provided", set the state to "not-provided" - // so that we only log the message once - if !srlinux.Spec.GetConfig().ConfigDataPresent { - log.Info("no startup config data provided") - - srlinux.Status.StartupConfig.Phase = "not-provided" - *update = true - - return - } - - log.Info("startup config provided, starting config provisioning...") - + // we need to wait for podIP to be ready as well as the network to be ready + // we do this before even checking if the startup config is provided + // because we need to create a checkpoing in any case ip := r.waitPodIPReady(ctx, log, srlinux) // even though the SR Linux management server is ready, the network might not be ready yet @@ -108,6 +98,22 @@ func (r *SrlinuxReconciler) handleSrlinuxStartupConfig( } defer driver.Close() + // if startup config data is not provided and Phase hasn't been set yet, set the Startup Config state to "not-provided" + // and create a checkpoint + if !srlinux.Spec.GetConfig().ConfigDataPresent && srlinux.Status.StartupConfig.Phase == "" { + log.Info("no startup config data provided") + + srlinux.Status.StartupConfig.Phase = "not-provided" + *update = true + + err := createInitCheckpoint(ctx, driver, log) + if err != nil { + log.Error(err, "failed to create initial checkpoint") + } + + return + } + log.Info("Loading provided startup configuration...", "filename", srlinux.Spec.GetConfig().ConfigFile, "path", defaultConfigPath) @@ -123,15 +129,13 @@ func (r *SrlinuxReconciler) handleSrlinuxStartupConfig( log.Info("Loaded provided startup configuration...") + srlinux.Status.StartupConfig.Phase = "loaded" + *update = true + err = createInitCheckpoint(ctx, driver, log) if err != nil { log.Error(err, "failed to create initial checkpoint after loading startup config") - - return } - - srlinux.Status.StartupConfig.Phase = "loaded" - *update = true } // loadStartupConfig loads the provided startup config into the SR Linux device. @@ -161,16 +165,35 @@ func loadStartupConfig( } // createInitCheckpoint creates a checkpoint named "initial". -// This checkpoint is used to reset the device to the initial state, which is the state after -// applying the startup config. +// This checkpoint is used to reset the device to the initial state, which is the state +// node booted with and (if present) with applied startup config. func createInitCheckpoint( _ context.Context, d *network.Driver, log logr.Logger, ) error { + log.Info("Creating initial checkpoint...") + + // sometimes status of srlinux cr is not updated immediately, + // resulting in several attempts to load configuration and create checkpoint + // so we need to check if the checkpoint already exists and bail out if so + checkCheckpointCmd := "info from state system configuration checkpoint *" + r, err := d.SendCommand(checkCheckpointCmd) + if err != nil { + log.Error(err, "failed to send command") + + return err + } + + if strings.Contains(r.Result, "initial") { + log.Info("initial checkpoint already exists, skipping") + + return nil + } + cmd := "/tools system configuration generate-checkpoint name initial" - r, err := d.SendCommand(cmd) + r, err = d.SendCommand(cmd) if err != nil { log.Error(err, "failed to send command") @@ -226,7 +249,7 @@ func (r *SrlinuxReconciler) waitPodIPReady( case <-tick.C: ip := r.getPodIP(ctx, srlinux) if ip != "" { - log.Info("pod IP assigned, provisioning configuration", "pod-ip", ip) + log.Info("pod IP assigned", "pod-ip", ip) return ip } From 15d7f58ef82e8888bea4e0c707af5ec048f09a21 Mon Sep 17 00:00:00 2001 From: Roman Dodin Date: Thu, 30 Mar 2023 13:32:21 +0200 Subject: [PATCH 2/2] lint --- controllers/startup_config.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/controllers/startup_config.go b/controllers/startup_config.go index 22bcdf1..673b428 100644 --- a/controllers/startup_config.go +++ b/controllers/startup_config.go @@ -72,7 +72,7 @@ func createStartupConfigVolumesAndMounts(s *srlinuxv1.Srlinux, pod *corev1.Pod, } // handleSrlinuxStartupConfig handles the startup config provisioning. -func (r *SrlinuxReconciler) handleSrlinuxStartupConfig( +func (r *SrlinuxReconciler) handleSrlinuxStartupConfig( //nolint:funlen ctx context.Context, log logr.Logger, update *bool, @@ -178,6 +178,7 @@ func createInitCheckpoint( // resulting in several attempts to load configuration and create checkpoint // so we need to check if the checkpoint already exists and bail out if so checkCheckpointCmd := "info from state system configuration checkpoint *" + r, err := d.SendCommand(checkCheckpointCmd) if err != nil { log.Error(err, "failed to send command")