Skip to content

Commit 46cdcc1

Browse files
authored
Merge pull request #101 from CiscoTestAutomation/release_24.6
Releasing v24.6
2 parents 4835c2e + adcce90 commit 46cdcc1

22 files changed

+864
-243
lines changed

docs/changelog/2024/june.rst

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
June 2024
2+
==========
3+
4+
- Unicon v24.6
5+
------------------------
6+
7+
8+
9+
.. csv-table:: Module Versions
10+
:header: "Modules", "Versions"
11+
12+
``unicon.plugins``, v24.6
13+
``unicon``, v24.6
14+
15+
Install Instructions
16+
^^^^^^^^^^^^^^^^^^^^
17+
18+
.. code-block:: bash
19+
20+
bash$ pip install unicon.plugins
21+
bash$ pip install unicon
22+
23+
Upgrade Instructions
24+
^^^^^^^^^^^^^^^^^^^^
25+
26+
.. code-block:: bash
27+
28+
bash$ pip install --upgrade unicon.plugins
29+
bash$ pip install --upgrade unicon
30+
31+
Features and Bug Fixes:
32+
^^^^^^^^^^^^^^^^^^^^^^^
33+
34+
35+
36+
37+
Changelogs
38+
^^^^^^^^^^
39+
--------------------------------------------------------------------------------
40+
Fix
41+
--------------------------------------------------------------------------------
42+
43+
* stackswitchover
44+
* Modified to wait for known switch state before continuing to check all stack members
45+
46+
* stackreload
47+
* Modified to always check all stack memebers after reload
48+
* Modified to work for newer platforms
49+
50+
* iosxe/stack
51+
* Reload Service
52+
* fix the logic for reloading stack devices to wait for all the members to be ready.
53+
54+
55+
--------------------------------------------------------------------------------
56+
New
57+
--------------------------------------------------------------------------------
58+
59+
* iosxe.stack.utils
60+
* Added new method wait_for_any_state
61+
* wait for any known state to bypass possible timing issues
62+
63+

docs/changelog/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Changelog
44
.. toctree::
55
:maxdepth: 2
66

7+
2024/june
78
2024/may
89
2024/april
910
2024/march

docs/changelog_plugins/2024/june.rst

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
June 2024
2+
==========
3+
4+
- Unicon.Plugins v24.6
5+
------------------------
6+
7+
8+
9+
.. csv-table:: Module Versions
10+
:header: "Modules", "Versions"
11+
12+
``unicon.plugins``, v24.6
13+
``unicon``, v24.6
14+
15+
Install Instructions
16+
^^^^^^^^^^^^^^^^^^^^
17+
18+
.. code-block:: bash
19+
20+
bash$ pip install unicon.plugins
21+
bash$ pip install unicon
22+
23+
Upgrade Instructions
24+
^^^^^^^^^^^^^^^^^^^^
25+
26+
.. code-block:: bash
27+
28+
bash$ pip install --upgrade unicon.plugins
29+
bash$ pip install --upgrade unicon
30+
31+
Features and Bug Fixes:
32+
^^^^^^^^^^^^^^^^^^^^^^^
33+
34+
35+
36+
37+
Changelogs
38+
^^^^^^^^^^
39+
--------------------------------------------------------------------------------
40+
Fix
41+
--------------------------------------------------------------------------------
42+
43+
* other
44+
* Update os value to iosxe for model C1100
45+
* Updated os value to iosxe for ISR1100 submodel
46+
47+
48+
--------------------------------------------------------------------------------
49+
Add
50+
--------------------------------------------------------------------------------
51+
52+
* iosxr
53+
* Added `admin_host` state support
54+
55+

docs/changelog_plugins/index.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ Plugins Changelog
44
.. toctree::
55
:maxdepth: 2
66

7+
2024/june
78
2024/may
89
2024/april
910
2024/march

src/unicon/plugins/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
__version__ = '24.5'
1+
__version__ = '24.6'
22

33
supported_chassis = [
44
'single_rp',

src/unicon/plugins/generic/patterns.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ def __init__(self):
3333

3434
# self.config_prompt = r'.*%N\(config.*\)#\s?$'
3535
self.config_prompt = r'^(.*)\(.*(con|cfg|ipsec-profile|ca-trustpoint|gkm-local-server)\S*\)#\s?$'
36-
self.rommon_prompt = r'^(.*?)(rommon[\s\d]*>|switch:)\s?$'
36+
self.rommon_prompt = r'^(.*?)(rommon[\s\d]*>|switch:|grub>)\s?$'
3737
# self.standby_enable_prompt = r'^(.*?)(RouterRP-standby|%N-standby|%N-sdby|%N\(standby\))#\s?$'
3838
# self.standby_disable_prompt = r'^(.*?)(RouterRP-standby|%N-standby|%N-sdby|%N\(standby\))>\s?$'
3939
self.standby_locked = r'^.*?([S|s]tandby console disabled|This \(D\)RP Node is not ready or active for login \/configuration.*)'
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
class StackException(Exception):
2+
''' base class '''
3+
pass
4+
5+
class StackMemberReadyException(StackException):
6+
"""
7+
Exception for when all the member of stack device is configured
8+
"""
9+
pass
10+

src/unicon/plugins/iosxe/stack/service_implementation.py

Lines changed: 43 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@
44
from datetime import datetime, timedelta
55
import re
66
from unicon.eal.dialogs import Dialog
7-
from unicon.core.errors import SubCommandFailure
7+
from unicon.core.errors import SubCommandFailure, StateMachineError
88
from unicon.bases.routers.services import BaseService
99

10+
from .exception import StackMemberReadyException
1011
from .utils import StackUtils
1112
from unicon.plugins.generic.statements import custom_auth_statements, buffer_settled
1213
from unicon.plugins.generic.service_statements import standby_reset_rp_statement_list
@@ -113,6 +114,8 @@ def call_service(self, command=None,
113114
connect_dialog = self.connection.connection_provider.get_connection_dialog()
114115
dialog += connect_dialog
115116

117+
start_time = datetime.now()
118+
116119
conn.log.info('Processing on active rp %s-%s' % (conn.hostname, conn.alias))
117120
conn.sendline(switchover_cmd)
118121
try:
@@ -141,10 +144,11 @@ def call_service(self, command=None,
141144
sleep(self.connection.settings.POST_SWITCHOVER_SLEEP)
142145

143146
# check all members are ready
144-
conn.state_machine.detect_state(conn.spawn, context=conn.context)
147+
recheck_sleep_interval = self.connection.settings.SWITCHOVER_POSTCHECK_INTERVAL
148+
recheck_max = timeout - (datetime.now() - start_time).seconds
145149

146-
interval = self.connection.settings.SWITCHOVER_POSTCHECK_INTERVAL
147-
if utils.is_all_member_ready(conn, timeout=timeout, interval=interval):
150+
self.connection.log.info('Wait for all members to be ready.')
151+
if utils.is_all_member_ready(conn, timeout=recheck_max, interval=recheck_sleep_interval):
148152
self.connection.log.info('All members are ready.')
149153
else:
150154
self.connection.log.info('Timeout in %s secs. '
@@ -245,9 +249,10 @@ def call_service(self,
245249

246250
reload_dialog += Dialog([switch_prompt])
247251

252+
conn.context['post_reload_timeout'] = timedelta(seconds= self.post_reload_wait_time)
253+
248254
conn.log.info('Processing on active rp %s-%s' % (conn.hostname, conn.alias))
249255
start_time = current_time = datetime.now()
250-
timeout_time = timedelta(seconds=timeout)
251256
conn.sendline(reload_cmd)
252257
try:
253258
reload_cmd_output = reload_dialog.process(conn.spawn,
@@ -256,6 +261,9 @@ def call_service(self,
256261
context=conn.context)
257262
self.result=reload_cmd_output.match_output
258263
self.get_service_result()
264+
except StackMemberReadyException as e:
265+
conn.log.debug('This is an expected exception for getting out of the dialog process')
266+
pass
259267
except Exception as e:
260268
raise SubCommandFailure('Error during reload', e) from e
261269

@@ -273,59 +281,45 @@ def call_service(self,
273281
for subconn in self.connection.subconnections:
274282
self.connection.log.info('Processing on rp '
275283
'%s-%s' % (conn.hostname, subconn.alias))
284+
subconn.context['post_reload_timeout'] = timedelta(seconds= self.post_reload_wait_time)
276285
utils.boot_process(subconn, timeout, self.prompt_recovery, reload_dialog)
277286

278287
except Exception as e:
279288
self.connection.log.error(e)
280289
raise SubCommandFailure('Reload failed.', e) from e
281290
else:
282-
conn.log.info('Waiting for boot messages to settle for {} seconds'.format(
283-
self.post_reload_wait_time
284-
))
285-
wait_time = timedelta(seconds=self.post_reload_wait_time)
286-
settle_time = current_time = datetime.now()
287-
while (current_time - settle_time) < wait_time:
288-
if buffer_settled(conn.spawn, self.post_reload_wait_time):
289-
conn.log.info('Buffer settled, accessing device..')
290-
break
291-
current_time = datetime.now()
292-
if (current_time - start_time) > timeout_time:
293-
conn.log.info('Time out, trying to acces device..')
294-
break
295-
try:
296-
# bring device to enable mode
297-
conn.state_machine.go_to('any', conn.spawn, timeout=timeout,
298-
prompt_recovery=self.prompt_recovery,
299-
context=conn.context)
300-
conn.state_machine.go_to('enable', conn.spawn, timeout=timeout,
301-
prompt_recovery=self.prompt_recovery,
302-
context=conn.context)
303-
except Exception as e:
304-
raise SubCommandFailure('Failed to bring device to disable mode.', e) from e
291+
self.connection.log.info('Processing autoboot on rp %s-%s' % (conn.hostname, conn.alias))
292+
293+
294+
self.connection.log.info('Sleeping for %s secs.' % \
295+
self.connection.settings.STACK_POST_RELOAD_SLEEP)
296+
sleep(self.connection.settings.STACK_POST_RELOAD_SLEEP)
297+
298+
# make sure detect_state is good to reduce the chance of timeout later
299+
recheck_sleep_interval = self.connection.settings.RELOAD_POSTCHECK_INTERVAL
300+
recheck_max = timeout - (datetime.now() - start_time).seconds
301+
305302
# check active and standby rp is ready
306303
self.connection.log.info('Wait for Standby RP to be ready.')
307304

308-
interval = self.connection.settings.RELOAD_POSTCHECK_INTERVAL
309-
if utils.is_active_standby_ready(conn, timeout=timeout, interval=interval):
305+
if utils.is_active_standby_ready(conn, timeout=recheck_max, interval=recheck_sleep_interval):
310306
self.connection.log.info('Active and Standby RPs are ready.')
311307
else:
312308
self.connection.log.info('Timeout in %s secs. '
313309
'Standby RP is not in Ready state. Reload failed' % timeout)
314310
self.result = False
315311
return
312+
313+
self.connection.log.info('Start checking state of all members')
314+
recheck_max = timeout - (datetime.now() - start_time).seconds
315+
if utils.is_all_member_ready(conn, timeout=recheck_max, interval=recheck_sleep_interval):
316+
self.connection.log.info('All Members are ready.')
317+
else:
318+
self.connection.log.info(f'Timeout in {recheck_max} secs. '
319+
f'Not all members are in Ready state. Reload failed')
320+
self.result = False
321+
return
316322

317-
if member:
318-
if utils.is_all_member_ready(conn, timeout=timeout, interval=interval):
319-
self.connection.log.info('All Members are ready.')
320-
else:
321-
self.connection.log.info(f'Timeout in {timeout} secs. '
322-
f'Member{member} is not in Ready state. Reload failed')
323-
self.result = False
324-
return
325-
326-
self.connection.log.info('Sleeping for %s secs.' % \
327-
self.connection.settings.STACK_POST_RELOAD_SLEEP)
328-
sleep(self.connection.settings.STACK_POST_RELOAD_SLEEP)
329323

330324
self.connection.log.info('Disconnecting and reconnecting')
331325
self.connection.disconnect()
@@ -578,10 +572,12 @@ def _check_invalid_mac(con):
578572
return True
579573
return False
580574

581-
from genie.utils.timeout import Timeout
582-
exec_timeout = Timeout(timeout, 15)
575+
chk_interval = con.settings.RELOAD_POSTCHECK_INTERVAL
583576
found_invalid_mac = False
584-
while exec_timeout.iterate():
577+
start_time2 = time()
578+
while (time() - start_time2) < timeout:
579+
t_left = timeout - (time() - start_time2)
580+
con.log.info('-- checking time left: %0.1f secs' % t_left)
585581
con.log.info('Make sure no invalid mac address 0000.0000.0000')
586582
if not _check_invalid_mac(con):
587583
con.log.info('Did not find invalid mac as 0000.0000.0000')
@@ -590,7 +586,8 @@ def _check_invalid_mac(con):
590586
else:
591587
con.log.warning('Found 0000.0000.0000 mac address')
592588
found_invalid_mac = True
593-
exec_timeout.sleep()
589+
con.log.info(f'Sleep {chk_interval} secs')
590+
sleep(chk_interval)
594591
continue
595592
else:
596593
if found_invalid_mac:

src/unicon/plugins/iosxe/stack/service_patterns.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,6 @@ def __init__(self):
2424
super().__init__()
2525
self.reload_entire_shelf = r'^.*?Reload the entire shelf \[confirm\]'
2626
self.reload_fast = r'^.*Proceed with reload fast\? \[confirm\]'
27+
self.apply_config = r'.*All switches in the stack have been discovered. Accelerating discovery.*'
28+
self.bp_console = r'^.*sw\..*-bp>'
29+
self.bp_console_enable = r'^.*sw\..*-bp#'

0 commit comments

Comments
 (0)