@@ -59,6 +59,37 @@ def __init__(self, username, password, hostname, conn_mode):
5959 self .num_nics = 13
6060 self .nic_type = "rtl8139"
6161
62+ def wait_write_config (self , cmd , wait = "#" , retries = 30 , delay = 5 ):
63+ """Execute command with retry logic for 'configuration load' state.
64+
65+ EXOS can enter a 'configuration load' state during boot where config
66+ commands are rejected. This wrapper retries the command until success.
67+ """
68+ for attempt in range (retries ):
69+ self .tn .write (f"{ cmd } \r " .encode ())
70+ try :
71+ res = self .tn .read_until (wait .encode (), timeout = 30 )
72+ response_str = res .decode (errors = "ignore" )
73+
74+ # Check if we got the config load error
75+ if "configuration load" in response_str .lower ():
76+ if attempt < retries - 1 : # Don't log on last attempt
77+ self .logger .info (
78+ f"'configuration load' detected, retrying '{ cmd } ' in { delay } s..."
79+ )
80+ time .sleep (delay )
81+ continue
82+
83+ # Success - command completed
84+ return
85+ except Exception as e :
86+ self .logger .warning (f"Timeout waiting for prompt after '{ cmd } ': { e } " )
87+ if attempt < retries - 1 :
88+ time .sleep (delay )
89+ continue
90+
91+ self .logger .error (f"Command '{ cmd } ' failed after { retries } retries" )
92+
6293 def bootstrap_spin (self ):
6394 """ This function should be called periodically to do work.
6495 """
@@ -114,10 +145,10 @@ def bootstrap_spin(self):
114145 def bootstrap_config (self ):
115146 """ Do the actual bootstrap config
116147 """
117- self .wait_write (cmd = f"configure snmp sysName { self .hostname } " , wait = "# " )
118- self .wait_write (cmd = "unconfigure vlan Mgmt ipaddress" , wait = "# " )
119- self .wait_write (cmd = "configure vlan Mgmt ipaddress 10.0.0.15/24" , wait = "# " )
120- self .wait_write (cmd = "configure iproute add default 10.0.0.2 vr VR-Mgmt" , wait = "# " )
148+ self .wait_write_config (cmd = f"configure snmp sysName { self .hostname } " )
149+ self .wait_write_config (cmd = "unconfigure vlan Mgmt ipaddress" )
150+ self .wait_write_config (cmd = "configure vlan Mgmt ipaddress 10.0.0.15/24" )
151+ self .wait_write_config (cmd = "configure iproute add default 10.0.0.2 vr VR-Mgmt" )
121152 if self .username == "admin" :
122153 self .wait_write (cmd = "configure account admin password" , wait = "#" )
123154 self .wait_write (cmd = "" , wait = "Current user's password:" )
@@ -127,10 +158,10 @@ def bootstrap_config(self):
127158 self .wait_write (
128159 cmd = f"create account admin { self .username } { self .password } " , wait = "#"
129160 )
130- self .wait_write (cmd = "disable cli prompting" , wait = "# " )
131- self .wait_write (cmd = "configure ssh2 key" , wait = "# " )
132- self .wait_write (cmd = "enable ssh2" , wait = "# " )
133- self .wait_write (cmd = "save" , wait = "# " )
161+ self .wait_write_config (cmd = "disable cli prompting" )
162+ self .wait_write_config (cmd = "configure ssh2 key" )
163+ self .wait_write_config (cmd = "enable ssh2" )
164+ self .wait_write_config (cmd = "save" )
134165
135166 def startup_config (self ):
136167 if not os .path .exists (STARTUP_CONFIG_FILE ):
0 commit comments