44 "context"
55 "fmt"
66 "path/filepath"
7+ "strings"
78 "time"
89
910 "github.com/go-logr/logr"
@@ -71,32 +72,21 @@ func createStartupConfigVolumesAndMounts(s *srlinuxv1.Srlinux, pod *corev1.Pod,
7172}
7273
7374// handleSrlinuxStartupConfig handles the startup config provisioning.
74- func (r * SrlinuxReconciler ) handleSrlinuxStartupConfig (
75+ func (r * SrlinuxReconciler ) handleSrlinuxStartupConfig ( //nolint:funlen
7576 ctx context.Context ,
7677 log logr.Logger ,
7778 update * bool ,
7879 srlinux * srlinuxv1.Srlinux ,
7980) {
80- if srlinux .Status .StartupConfig .Phase == "loaded" ||
81- srlinux .Status .StartupConfig .Phase == "failed" {
82- log .Info ("startup config load already tried, skipping" )
81+ if srlinux .Status .StartupConfig .Phase != "" {
82+ log .Info ("startup config already processed, skipping" )
8383
8484 return
8585 }
8686
87- // if startup config data is not provided and the state is not "not-provided", set the state to "not-provided"
88- // so that we only log the message once
89- if ! srlinux .Spec .GetConfig ().ConfigDataPresent {
90- log .Info ("no startup config data provided" )
91-
92- srlinux .Status .StartupConfig .Phase = "not-provided"
93- * update = true
94-
95- return
96- }
97-
98- log .Info ("startup config provided, starting config provisioning..." )
99-
87+ // we need to wait for podIP to be ready as well as the network to be ready
88+ // we do this before even checking if the startup config is provided
89+ // because we need to create a checkpoing in any case
10090 ip := r .waitPodIPReady (ctx , log , srlinux )
10191
10292 // even though the SR Linux management server is ready, the network might not be ready yet
@@ -108,6 +98,22 @@ func (r *SrlinuxReconciler) handleSrlinuxStartupConfig(
10898 }
10999 defer driver .Close ()
110100
101+ // if startup config data is not provided and Phase hasn't been set yet, set the Startup Config state to "not-provided"
102+ // and create a checkpoint
103+ if ! srlinux .Spec .GetConfig ().ConfigDataPresent && srlinux .Status .StartupConfig .Phase == "" {
104+ log .Info ("no startup config data provided" )
105+
106+ srlinux .Status .StartupConfig .Phase = "not-provided"
107+ * update = true
108+
109+ err := createInitCheckpoint (ctx , driver , log )
110+ if err != nil {
111+ log .Error (err , "failed to create initial checkpoint" )
112+ }
113+
114+ return
115+ }
116+
111117 log .Info ("Loading provided startup configuration..." , "filename" ,
112118 srlinux .Spec .GetConfig ().ConfigFile , "path" , defaultConfigPath )
113119
@@ -123,15 +129,13 @@ func (r *SrlinuxReconciler) handleSrlinuxStartupConfig(
123129
124130 log .Info ("Loaded provided startup configuration..." )
125131
132+ srlinux .Status .StartupConfig .Phase = "loaded"
133+ * update = true
134+
126135 err = createInitCheckpoint (ctx , driver , log )
127136 if err != nil {
128137 log .Error (err , "failed to create initial checkpoint after loading startup config" )
129-
130- return
131138 }
132-
133- srlinux .Status .StartupConfig .Phase = "loaded"
134- * update = true
135139}
136140
137141// loadStartupConfig loads the provided startup config into the SR Linux device.
@@ -161,16 +165,36 @@ func loadStartupConfig(
161165}
162166
163167// createInitCheckpoint creates a checkpoint named "initial".
164- // This checkpoint is used to reset the device to the initial state, which is the state after
165- // applying the startup config.
168+ // This checkpoint is used to reset the device to the initial state, which is the state
169+ // node booted with and (if present) with applied startup config.
166170func createInitCheckpoint (
167171 _ context.Context ,
168172 d * network.Driver ,
169173 log logr.Logger ,
170174) error {
175+ log .Info ("Creating initial checkpoint..." )
176+
177+ // sometimes status of srlinux cr is not updated immediately,
178+ // resulting in several attempts to load configuration and create checkpoint
179+ // so we need to check if the checkpoint already exists and bail out if so
180+ checkCheckpointCmd := "info from state system configuration checkpoint *"
181+
182+ r , err := d .SendCommand (checkCheckpointCmd )
183+ if err != nil {
184+ log .Error (err , "failed to send command" )
185+
186+ return err
187+ }
188+
189+ if strings .Contains (r .Result , "initial" ) {
190+ log .Info ("initial checkpoint already exists, skipping" )
191+
192+ return nil
193+ }
194+
171195 cmd := "/tools system configuration generate-checkpoint name initial"
172196
173- r , err : = d .SendCommand (cmd )
197+ r , err = d .SendCommand (cmd )
174198 if err != nil {
175199 log .Error (err , "failed to send command" )
176200
@@ -226,7 +250,7 @@ func (r *SrlinuxReconciler) waitPodIPReady(
226250 case <- tick .C :
227251 ip := r .getPodIP (ctx , srlinux )
228252 if ip != "" {
229- log .Info ("pod IP assigned, provisioning configuration " , "pod-ip" , ip )
253+ log .Info ("pod IP assigned" , "pod-ip" , ip )
230254
231255 return ip
232256 }
0 commit comments