From adcce9080edbe8c1b733feb6490bf73c5d0def59 Mon Sep 17 00:00:00 2001 From: omid Date: Mon, 24 Jun 2024 14:44:10 -0400 Subject: [PATCH] Releasing v24.6 --- docs/changelog/2024/june.rst | 63 ++++ docs/changelog/index.rst | 1 + docs/changelog_plugins/2024/june.rst | 55 ++++ docs/changelog_plugins/index.rst | 1 + src/unicon/plugins/__init__.py | 2 +- src/unicon/plugins/generic/patterns.py | 2 +- src/unicon/plugins/iosxe/stack/exception.py | 10 + .../iosxe/stack/service_implementation.py | 89 +++--- .../plugins/iosxe/stack/service_patterns.py | 3 + .../plugins/iosxe/stack/service_statements.py | 64 ++++- src/unicon/plugins/iosxe/stack/utils.py | 90 +++++- src/unicon/plugins/iosxr/patterns.py | 2 + src/unicon/plugins/iosxr/statemachine.py | 4 + src/unicon/plugins/pid_tokens.csv | 272 +++++++++--------- .../mock_data/iosxe/iosxe_mock_data_c8kv.yaml | 5 + .../iosxe/iosxe_mock_data_sdwan.yaml | 234 ++++++++++++--- .../mock_data/iosxe/iosxe_mock_stack.yaml | 82 +++++- .../mock_data/iosxr/iosxr_mock_data.yaml | 34 ++- src/unicon/plugins/tests/test_plugin_iosxe.py | 9 + .../plugins/tests/test_plugin_iosxe_sdwan.py | 55 +++- .../plugins/tests/test_plugin_iosxe_stack.py | 20 ++ src/unicon/plugins/tests/test_plugin_iosxr.py | 10 + 22 files changed, 864 insertions(+), 243 deletions(-) create mode 100644 docs/changelog/2024/june.rst create mode 100644 docs/changelog_plugins/2024/june.rst create mode 100644 src/unicon/plugins/iosxe/stack/exception.py diff --git a/docs/changelog/2024/june.rst b/docs/changelog/2024/june.rst new file mode 100644 index 00000000..fe7ceafb --- /dev/null +++ b/docs/changelog/2024/june.rst @@ -0,0 +1,63 @@ +June 2024 +========== + + - Unicon v24.6 +------------------------ + + + +.. csv-table:: Module Versions + :header: "Modules", "Versions" + + ``unicon.plugins``, v24.6 + ``unicon``, v24.6 + +Install Instructions +^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: bash + + bash$ pip install unicon.plugins + bash$ pip install unicon + +Upgrade Instructions +^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: bash + + bash$ pip install --upgrade unicon.plugins + bash$ pip install --upgrade unicon + +Features and Bug Fixes: +^^^^^^^^^^^^^^^^^^^^^^^ + + + + +Changelogs +^^^^^^^^^^ +-------------------------------------------------------------------------------- + Fix +-------------------------------------------------------------------------------- + +* stackswitchover + * Modified to wait for known switch state before continuing to check all stack members + +* stackreload + * Modified to always check all stack memebers after reload + * Modified to work for newer platforms + +* iosxe/stack + * Reload Service + * fix the logic for reloading stack devices to wait for all the members to be ready. + + +-------------------------------------------------------------------------------- + New +-------------------------------------------------------------------------------- + +* iosxe.stack.utils + * Added new method wait_for_any_state + * wait for any known state to bypass possible timing issues + + diff --git a/docs/changelog/index.rst b/docs/changelog/index.rst index 24e1f86a..eaec7e87 100644 --- a/docs/changelog/index.rst +++ b/docs/changelog/index.rst @@ -4,6 +4,7 @@ Changelog .. toctree:: :maxdepth: 2 + 2024/june 2024/may 2024/april 2024/march diff --git a/docs/changelog_plugins/2024/june.rst b/docs/changelog_plugins/2024/june.rst new file mode 100644 index 00000000..cd7b898e --- /dev/null +++ b/docs/changelog_plugins/2024/june.rst @@ -0,0 +1,55 @@ +June 2024 +========== + + - Unicon.Plugins v24.6 +------------------------ + + + +.. csv-table:: Module Versions + :header: "Modules", "Versions" + + ``unicon.plugins``, v24.6 + ``unicon``, v24.6 + +Install Instructions +^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: bash + + bash$ pip install unicon.plugins + bash$ pip install unicon + +Upgrade Instructions +^^^^^^^^^^^^^^^^^^^^ + +.. code-block:: bash + + bash$ pip install --upgrade unicon.plugins + bash$ pip install --upgrade unicon + +Features and Bug Fixes: +^^^^^^^^^^^^^^^^^^^^^^^ + + + + +Changelogs +^^^^^^^^^^ +-------------------------------------------------------------------------------- + Fix +-------------------------------------------------------------------------------- + +* other + * Update os value to iosxe for model C1100 + * Updated os value to iosxe for ISR1100 submodel + + +-------------------------------------------------------------------------------- + Add +-------------------------------------------------------------------------------- + +* iosxr + * Added `admin_host` state support + + diff --git a/docs/changelog_plugins/index.rst b/docs/changelog_plugins/index.rst index 5e79066b..a4622231 100644 --- a/docs/changelog_plugins/index.rst +++ b/docs/changelog_plugins/index.rst @@ -4,6 +4,7 @@ Plugins Changelog .. toctree:: :maxdepth: 2 + 2024/june 2024/may 2024/april 2024/march diff --git a/src/unicon/plugins/__init__.py b/src/unicon/plugins/__init__.py index dc6b157f..840d1aac 100644 --- a/src/unicon/plugins/__init__.py +++ b/src/unicon/plugins/__init__.py @@ -1,4 +1,4 @@ -__version__ = '24.5' +__version__ = '24.6' supported_chassis = [ 'single_rp', diff --git a/src/unicon/plugins/generic/patterns.py b/src/unicon/plugins/generic/patterns.py index 3e358255..58618a3e 100644 --- a/src/unicon/plugins/generic/patterns.py +++ b/src/unicon/plugins/generic/patterns.py @@ -33,7 +33,7 @@ def __init__(self): # self.config_prompt = r'.*%N\(config.*\)#\s?$' self.config_prompt = r'^(.*)\(.*(con|cfg|ipsec-profile|ca-trustpoint|gkm-local-server)\S*\)#\s?$' - self.rommon_prompt = r'^(.*?)(rommon[\s\d]*>|switch:)\s?$' + self.rommon_prompt = r'^(.*?)(rommon[\s\d]*>|switch:|grub>)\s?$' # self.standby_enable_prompt = r'^(.*?)(RouterRP-standby|%N-standby|%N-sdby|%N\(standby\))#\s?$' # self.standby_disable_prompt = r'^(.*?)(RouterRP-standby|%N-standby|%N-sdby|%N\(standby\))>\s?$' self.standby_locked = r'^.*?([S|s]tandby console disabled|This \(D\)RP Node is not ready or active for login \/configuration.*)' diff --git a/src/unicon/plugins/iosxe/stack/exception.py b/src/unicon/plugins/iosxe/stack/exception.py new file mode 100644 index 00000000..6e305b93 --- /dev/null +++ b/src/unicon/plugins/iosxe/stack/exception.py @@ -0,0 +1,10 @@ +class StackException(Exception): + ''' base class ''' + pass + +class StackMemberReadyException(StackException): + """ + Exception for when all the member of stack device is configured + """ + pass + diff --git a/src/unicon/plugins/iosxe/stack/service_implementation.py b/src/unicon/plugins/iosxe/stack/service_implementation.py index 9b347d1f..70c717cb 100644 --- a/src/unicon/plugins/iosxe/stack/service_implementation.py +++ b/src/unicon/plugins/iosxe/stack/service_implementation.py @@ -4,9 +4,10 @@ from datetime import datetime, timedelta import re from unicon.eal.dialogs import Dialog -from unicon.core.errors import SubCommandFailure +from unicon.core.errors import SubCommandFailure, StateMachineError from unicon.bases.routers.services import BaseService +from .exception import StackMemberReadyException from .utils import StackUtils from unicon.plugins.generic.statements import custom_auth_statements, buffer_settled from unicon.plugins.generic.service_statements import standby_reset_rp_statement_list @@ -113,6 +114,8 @@ def call_service(self, command=None, connect_dialog = self.connection.connection_provider.get_connection_dialog() dialog += connect_dialog + start_time = datetime.now() + conn.log.info('Processing on active rp %s-%s' % (conn.hostname, conn.alias)) conn.sendline(switchover_cmd) try: @@ -141,10 +144,11 @@ def call_service(self, command=None, sleep(self.connection.settings.POST_SWITCHOVER_SLEEP) # check all members are ready - conn.state_machine.detect_state(conn.spawn, context=conn.context) + recheck_sleep_interval = self.connection.settings.SWITCHOVER_POSTCHECK_INTERVAL + recheck_max = timeout - (datetime.now() - start_time).seconds - interval = self.connection.settings.SWITCHOVER_POSTCHECK_INTERVAL - if utils.is_all_member_ready(conn, timeout=timeout, interval=interval): + self.connection.log.info('Wait for all members to be ready.') + if utils.is_all_member_ready(conn, timeout=recheck_max, interval=recheck_sleep_interval): self.connection.log.info('All members are ready.') else: self.connection.log.info('Timeout in %s secs. ' @@ -245,9 +249,10 @@ def call_service(self, reload_dialog += Dialog([switch_prompt]) + conn.context['post_reload_timeout'] = timedelta(seconds= self.post_reload_wait_time) + conn.log.info('Processing on active rp %s-%s' % (conn.hostname, conn.alias)) start_time = current_time = datetime.now() - timeout_time = timedelta(seconds=timeout) conn.sendline(reload_cmd) try: reload_cmd_output = reload_dialog.process(conn.spawn, @@ -256,6 +261,9 @@ def call_service(self, context=conn.context) self.result=reload_cmd_output.match_output self.get_service_result() + except StackMemberReadyException as e: + conn.log.debug('This is an expected exception for getting out of the dialog process') + pass except Exception as e: raise SubCommandFailure('Error during reload', e) from e @@ -273,59 +281,45 @@ def call_service(self, for subconn in self.connection.subconnections: self.connection.log.info('Processing on rp ' '%s-%s' % (conn.hostname, subconn.alias)) + subconn.context['post_reload_timeout'] = timedelta(seconds= self.post_reload_wait_time) utils.boot_process(subconn, timeout, self.prompt_recovery, reload_dialog) except Exception as e: self.connection.log.error(e) raise SubCommandFailure('Reload failed.', e) from e else: - conn.log.info('Waiting for boot messages to settle for {} seconds'.format( - self.post_reload_wait_time - )) - wait_time = timedelta(seconds=self.post_reload_wait_time) - settle_time = current_time = datetime.now() - while (current_time - settle_time) < wait_time: - if buffer_settled(conn.spawn, self.post_reload_wait_time): - conn.log.info('Buffer settled, accessing device..') - break - current_time = datetime.now() - if (current_time - start_time) > timeout_time: - conn.log.info('Time out, trying to acces device..') - break - try: - # bring device to enable mode - conn.state_machine.go_to('any', conn.spawn, timeout=timeout, - prompt_recovery=self.prompt_recovery, - context=conn.context) - conn.state_machine.go_to('enable', conn.spawn, timeout=timeout, - prompt_recovery=self.prompt_recovery, - context=conn.context) - except Exception as e: - raise SubCommandFailure('Failed to bring device to disable mode.', e) from e + self.connection.log.info('Processing autoboot on rp %s-%s' % (conn.hostname, conn.alias)) + + + self.connection.log.info('Sleeping for %s secs.' % \ + self.connection.settings.STACK_POST_RELOAD_SLEEP) + sleep(self.connection.settings.STACK_POST_RELOAD_SLEEP) + + # make sure detect_state is good to reduce the chance of timeout later + recheck_sleep_interval = self.connection.settings.RELOAD_POSTCHECK_INTERVAL + recheck_max = timeout - (datetime.now() - start_time).seconds + # check active and standby rp is ready self.connection.log.info('Wait for Standby RP to be ready.') - interval = self.connection.settings.RELOAD_POSTCHECK_INTERVAL - if utils.is_active_standby_ready(conn, timeout=timeout, interval=interval): + if utils.is_active_standby_ready(conn, timeout=recheck_max, interval=recheck_sleep_interval): self.connection.log.info('Active and Standby RPs are ready.') else: self.connection.log.info('Timeout in %s secs. ' 'Standby RP is not in Ready state. Reload failed' % timeout) self.result = False return + + self.connection.log.info('Start checking state of all members') + recheck_max = timeout - (datetime.now() - start_time).seconds + if utils.is_all_member_ready(conn, timeout=recheck_max, interval=recheck_sleep_interval): + self.connection.log.info('All Members are ready.') + else: + self.connection.log.info(f'Timeout in {recheck_max} secs. ' + f'Not all members are in Ready state. Reload failed') + self.result = False + return - if member: - if utils.is_all_member_ready(conn, timeout=timeout, interval=interval): - self.connection.log.info('All Members are ready.') - else: - self.connection.log.info(f'Timeout in {timeout} secs. ' - f'Member{member} is not in Ready state. Reload failed') - self.result = False - return - - self.connection.log.info('Sleeping for %s secs.' % \ - self.connection.settings.STACK_POST_RELOAD_SLEEP) - sleep(self.connection.settings.STACK_POST_RELOAD_SLEEP) self.connection.log.info('Disconnecting and reconnecting') self.connection.disconnect() @@ -578,10 +572,12 @@ def _check_invalid_mac(con): return True return False - from genie.utils.timeout import Timeout - exec_timeout = Timeout(timeout, 15) + chk_interval = con.settings.RELOAD_POSTCHECK_INTERVAL found_invalid_mac = False - while exec_timeout.iterate(): + start_time2 = time() + while (time() - start_time2) < timeout: + t_left = timeout - (time() - start_time2) + con.log.info('-- checking time left: %0.1f secs' % t_left) con.log.info('Make sure no invalid mac address 0000.0000.0000') if not _check_invalid_mac(con): con.log.info('Did not find invalid mac as 0000.0000.0000') @@ -590,7 +586,8 @@ def _check_invalid_mac(con): else: con.log.warning('Found 0000.0000.0000 mac address') found_invalid_mac = True - exec_timeout.sleep() + con.log.info(f'Sleep {chk_interval} secs') + sleep(chk_interval) continue else: if found_invalid_mac: diff --git a/src/unicon/plugins/iosxe/stack/service_patterns.py b/src/unicon/plugins/iosxe/stack/service_patterns.py index 551be85d..97769274 100644 --- a/src/unicon/plugins/iosxe/stack/service_patterns.py +++ b/src/unicon/plugins/iosxe/stack/service_patterns.py @@ -24,3 +24,6 @@ def __init__(self): super().__init__() self.reload_entire_shelf = r'^.*?Reload the entire shelf \[confirm\]' self.reload_fast = r'^.*Proceed with reload fast\? \[confirm\]' + self.apply_config = r'.*All switches in the stack have been discovered. Accelerating discovery.*' + self.bp_console = r'^.*sw\..*-bp>' + self.bp_console_enable = r'^.*sw\..*-bp#' diff --git a/src/unicon/plugins/iosxe/stack/service_statements.py b/src/unicon/plugins/iosxe/stack/service_statements.py index bfc241f5..fb69bebb 100644 --- a/src/unicon/plugins/iosxe/stack/service_statements.py +++ b/src/unicon/plugins/iosxe/stack/service_statements.py @@ -1,9 +1,14 @@ """ Generic IOS-XE Stack Service Statements """ -import time +from time import time, sleep +from datetime import datetime, timedelta from unicon.eal.dialogs import Statement + from unicon.plugins.generic.service_statements import reload_statement_list +from unicon.plugins.generic.statements import buffer_settled from unicon.plugins.iosxe.service_statements import factory_reset_confirm, are_you_sure_confirm from .service_patterns import StackIosXESwitchoverPatterns, StackIosXEReloadPatterns +from .exception import StackMemberReadyException + def update_curr_state(spawn, context, state): context['state'] = state @@ -21,10 +26,39 @@ def send_boot_cmd(spawn, context): if "image_to_boot" in context else "boot" spawn.sendline(cmd) -def stack_press_return(spawn, context): - spawn.log.info('Waiting for {} seconds'.format(spawn.timeout)) - time.sleep(spawn.timeout) - spawn.sendline() +def stack_press_return(spawn, context, session): + # for stack devices if we reload from a member console we will see 2 press return to continue. + # to make sure that we get out of the process dialog when all the members are ready we + # make sure first we match "All switches in the stack have been discovered. Accelerating discovery" in the + # buffer then we raise the StackMemberReadyException to end the process. + if session.get('apply_config_on_all_members') or session.get('bp_console'): + spawn.log.info('Waiting for buffer to settle') + timeout_time = context.get('post_reload_wait_time', 60) + if not isinstance(timeout_time, timedelta): + timeout_time = timedelta(seconds=timeout_time) + start_time = current_time = datetime.now() + while (current_time - start_time) < timeout_time: + if buffer_settled(spawn, wait_time=15): + spawn.log.info('Buffer settled, accessing device..') + break + current_time = datetime.now() + if (current_time - start_time) > timeout_time: + spawn.log.info('Time out, trying to access device..') + break + spawn.sendline() + raise StackMemberReadyException + +def apply_config_on_all_switch(spawn, session): + # we need to match theis pattern to make sure all the members are ready and we can access the device + """ Handles the number of apply configure message seen after install image """ + session["apply_config_on_all_members"] = True + +def bp_console_handler(spawn, session): + ''' strack_press_return will not wait for session["apply_config_on_all_members"] to be set + However, this pattern "All switches in the stack have been discovered. Accelerating discovery" + will never be seen for new stack design, which will cause the stack_press_return to wait forever. + Therefore, also checking bp-console prompt to make sure the reload process dialog will stop.''' + session["bp_console"] = True # switchover service statements @@ -85,10 +119,10 @@ def stack_press_return(spawn, context): loop_continue=False, continue_timer=False) -press_return = Statement(pattern=switchover_pat.press_return, +press_return_stack = Statement(pattern=switchover_pat.press_return, action=stack_press_return, args=None, - loop_continue=False, + loop_continue=True, continue_timer=False) found_return = Statement(pattern=switchover_pat.press_return, @@ -124,12 +158,26 @@ def stack_press_return(spawn, context): loop_continue=True, continue_timer=False) +apply_config = Statement(pattern=reload_pat.apply_config, + action=apply_config_on_all_switch, + loop_continue=True, + continue_timer=False) + + +bp_console = Statement(pattern=reload_pat.bp_console, + action=bp_console_handler, + loop_continue=True, + continue_timer=False) + stack_reload_stmt_list = list(reload_statement_list) stack_reload_stmt_list.extend([en_state, dis_state]) -stack_reload_stmt_list.insert(0, press_return) +stack_reload_stmt_list.insert(0, press_return_stack) stack_reload_stmt_list.insert(0, reload_shelf) stack_reload_stmt_list.insert(0, reload_fast) +stack_reload_stmt_list.insert(0, apply_config) +stack_reload_stmt_list.insert(0, bp_console) + stack_factory_reset_stmt_list = [factory_reset_confirm, are_you_sure_confirm] diff --git a/src/unicon/plugins/iosxe/stack/utils.py b/src/unicon/plugins/iosxe/stack/utils.py index 1392466f..313221f3 100644 --- a/src/unicon/plugins/iosxe/stack/utils.py +++ b/src/unicon/plugins/iosxe/stack/utils.py @@ -1,13 +1,18 @@ """ Stack utilities. """ import re +import logging from time import sleep, time from unicon.eal.dialogs import Dialog from unicon.utils import Utils, AttributeDict +from unicon.core.errors import StateMachineError +from .exception import StackMemberReadyException from .service_statements import send_boot +logger = logging.getLogger(__name__) + class StackUtils(Utils): @@ -83,9 +88,13 @@ def boot_process(self, connection, timeout, prompt_recovery, dialog=Dialog([])): None """ connection.spawn.sendline() - dialog.process(connection.spawn, timeout=timeout, - prompt_recovery=prompt_recovery, - context=connection.context) + try: + dialog.process(connection.spawn, timeout=timeout, + prompt_recovery=prompt_recovery, + context=connection.context) + except StackMemberReadyException as e: + logger.debug('This is an expected exception for getting out of the dialog proceess') + pass connection.state_machine.go_to('any', connection.spawn, timeout=timeout, prompt_recovery=prompt_recovery, context=connection.context) @@ -106,9 +115,23 @@ def is_active_standby_ready(self, connection, timeout=120, interval=30): """ active = standby = '' start_time = time() + end_time = start_time + timeout + + while (time() - start_time) < timeout: - details = self.get_redundancy_details(connection) + # double check the connection state + self.wait_for_any_state(connection, timeout=end_time - time(), interval=interval) + try: + # one connection reached a known state does not mean all connections are in the same state + # so cli execution can still fail + details = self.get_redundancy_details(connection) + except Exception as e: + connection.log.warning('Failed to get redundancy details. Stack might not be ready yet') + connection.log.info('Sleeping for %s secs.' % interval) + sleep(interval) + continue + for sw_num, info in details.items(): if info['role'] == 'Active': active = info.get('state') @@ -143,7 +166,7 @@ def is_active_ready(self, connection): return active == 'Ready' - def is_all_member_ready(self, connection, timeout=120, interval=30): + def is_all_member_ready(self, connection, timeout=270, interval=30): """ Check whether all rp are in ready state including active, standby and members @@ -157,9 +180,20 @@ def is_all_member_ready(self, connection, timeout=120, interval=30): """ ready = active = standby = False start_time = time() + end_time = start_time + timeout while (time() - start_time) < timeout: - details = self.get_redundancy_details(connection) + # double check the console state. + self.wait_for_any_state(connection, timeout=end_time - time(), interval=interval) + try: + # one connection reached a known state does not mean all connections are in the same state + # so cli execution can still fail + details = self.get_redundancy_details(connection) + except Exception as e: + connection.log.warning('Failed to get redundancy details. Stack might not be ready yet') + connection.log.info('Sleeping for %s secs.' % interval) + sleep(interval) + continue for sw_num, info in details.items(): state = info.get('state') if state != 'Ready': @@ -198,3 +232,47 @@ def get_standby_rp_sn(self, connection): standby = int(sw_num) return standby + + + def wait_for_any_state(self, connection, timeout=180, interval=15, auto_timeout_extend=True, auto_extend_secs=180): + ''' use this method to wait for any state or bypass possible timing issue which could cause state detection failure + use this where false failure is seen due to timing issue + Args: + connection (`obj`): connection object + timeout (`int`): timeout value, default is 180 secs + interval (`int`): check interval, default is 15 secs + auto_timeout_extend (`bool`): auto extend timeout if less than 0 + This is useful when the timeout is calculated based on an estimated total timeout + auto_extend_secs (`int`): Extend timeout to this vaule when auto_timeout_extend is True. Default is 180 secs + Returns: + None + raises StateMachineError if state detection fails and timeout is reached + + ''' + start_time = time() + good_state = False + if timeout <= 0 and auto_timeout_extend: + connection.log.warning(f'wait_for_any_state: given timeout is less than 0. Extend it to {auto_extend_secs} seconds') + timeout = auto_extend_secs + elif timeout <= 0: + connection.log.warning(f'wait_for_any_state: given timeout is less than 0. No auto extend. set timeout to 10 seconds') + timeout = 10 # set it to 10 seconds to check at least once + else: + connection.log.warning(f'wait_for_any_state: given timeout={timeout} seconds. No auto extend') + + connection.log.info(f'Looking for known state (detect_state) on {connection.alias} -- timeout={timeout} seconds') + while (time() - start_time) < timeout: + t_left = timeout - (time() - start_time) + connection.log.info('-- checking time left: %0.1f secs' % t_left) + try: + connection.state_machine.detect_state(connection.spawn, context=connection.context) + good_state = True + break + except Exception as e: + connection.log.warning(f'Fail to detect any state on {connection.alias}') + connection.log.info(f'Sleep {interval} secs') + sleep(interval) + if not good_state: + raise StateMachineError(f'wait_for_any_state: Timeout reached on {connection.alias}') + else: + connection.log.info(f'detect_state on {connection.alias} is successful') diff --git a/src/unicon/plugins/iosxr/patterns.py b/src/unicon/plugins/iosxr/patterns.py index 86bf7138..f866c199 100755 --- a/src/unicon/plugins/iosxr/patterns.py +++ b/src/unicon/plugins/iosxr/patterns.py @@ -31,6 +31,8 @@ def __init__(self): self.admin_prompt = r'^(.*?)(?:sysadmin-vm:0_(.*)\s?#\s?$|RP/\S+\(admin\)\s?#\s?)$' self.admin_conf_prompt = r'^(.*?)(?:sysadmin-vm:0_(.*)\(config.*\)\s?#\s?|RP/\S+\(admin-config(\S+)?\)\s?#\s?)$' self.admin_run_prompt = r'^(.*?)(?:\[sysadmin-vm:0_.*:([\s\S]+)?\]\s?\$\s?|[\r\n]+\s?#\s?)$' + # [host:0_RP0:~]$ + self.admin_host_prompt = r'^(.*?)(?:\[host:0_.*:([\s\S]+)?\]\s?\$\s?)$' self.unreachable_prompt = r'apples are green but oranges are red' self.configuration_failed_message = r'^.*Please issue \'show configuration failed \[inheritance\].*[\r\n]*' self.standby_prompt = r'^.*This \(D\)RP Node is not ready or active for login \/configuration.*' diff --git a/src/unicon/plugins/iosxr/statemachine.py b/src/unicon/plugins/iosxr/statemachine.py index 93fae1fc..45cc63e9 100755 --- a/src/unicon/plugins/iosxr/statemachine.py +++ b/src/unicon/plugins/iosxr/statemachine.py @@ -37,6 +37,7 @@ def create(self): admin = State('admin', patterns.admin_prompt) admin_conf = State('admin_conf', patterns.admin_conf_prompt) admin_run = State('admin_run', patterns.admin_run_prompt) + admin_host = State('admin_host', patterns.admin_host_prompt) self.add_state(enable) self.add_state(config) @@ -45,6 +46,7 @@ def create(self): self.add_state(admin) self.add_state(admin_conf) self.add_state(admin_run) + self.add_state(admin_host) config_dialog = Dialog([ [patterns.commit_changes_prompt, 'sendline(yes)', None, True, False], @@ -64,6 +66,7 @@ def create(self): run_to_enable = Path(run, enable, 'exit', None) config_to_enable = Path(config, enable, 'end', config_dialog) exclusive_to_enable = Path(exclusive, enable, 'end', config_dialog) + admin_host_to_admin_run = Path(admin_host, admin_run, 'exit', None) self.add_path(config_to_enable) self.add_path(enable_to_config) @@ -77,6 +80,7 @@ def create(self): self.add_path(admin_to_admin_run) self.add_path(admin_conf_to_admin) self.add_path(admin_run_to_admin) + self.add_path(admin_host_to_admin_run) self.add_default_statements(default_commands) diff --git a/src/unicon/plugins/pid_tokens.csv b/src/unicon/plugins/pid_tokens.csv index 92e4b817..97489ea6 100644 --- a/src/unicon/plugins/pid_tokens.csv +++ b/src/unicon/plugins/pid_tokens.csv @@ -62,134 +62,134 @@ C1000FE-24T-4G-L,iosxe,cat1k,c1000, C1000FE-48P-4G-L,iosxe,cat1k,c1000, C1000FE-48T-4G-L,iosxe,cat1k,c1000, C1100TG-1N32A,iosxe,isr,c1100, -C1101-4P,ios,c1k,c1100, -C1101-4PLTEP,ios,c1k,c1100, -C1101-4PLTEPWA,ios,c1k,c1100, -C1101-4PLTEPWB,ios,c1k,c1100, -C1101-4PLTEPWD,ios,c1k,c1100, -C1101-4PLTEPWE,ios,c1k,c1100, -C1101-4PLTEPWF,ios,c1k,c1100, -C1101-4PLTEPWH,ios,c1k,c1100, -C1101-4PLTEPWN,ios,c1k,c1100, -C1101-4PLTEPWQ,ios,c1k,c1100, -C1101-4PLTEPWR,ios,c1k,c1100, -C1101-4PLTEPWZ,ios,c1k,c1100, -C1109-2PLTEAU,ios,c1k,c1100, -C1109-2PLTEGB,ios,c1k,c1100, -C1109-2PLTEIN,ios,c1k,c1100, -C1109-2PLTEJN,ios,c1k,c1100, -C1109-2PLTEUS,ios,c1k,c1100, -C1109-2PLTEVZ,ios,c1k,c1100, -C1109-4PLTE2P,ios,c1k,c1100, -C1109-4PLTE2PWA,ios,c1k,c1100, -C1109-4PLTE2PWB,ios,c1k,c1100, -C1109-4PLTE2PWD,ios,c1k,c1100, -C1109-4PLTE2PWE,ios,c1k,c1100, -C1109-4PLTE2PWF,ios,c1k,c1100, -C1109-4PLTE2PWH,ios,c1k,c1100, -C1109-4PLTE2PWN,ios,c1k,c1100, -C1109-4PLTE2PWQ,ios,c1k,c1100, -C1109-4PLTE2PWR,ios,c1k,c1100, -C1109-4PLTE2PWZ,ios,c1k,c1100, -C1111-4P,ios,c1k,c1100, -C1111-4PLTEEA,ios,c1k,c1100, -C1111-4PLTELA,ios,c1k,c1100, -C1111-4PWA,ios,c1k,c1100, -C1111-4PWB,ios,c1k,c1100, -C1111-4PWD,ios,c1k,c1100, -C1111-4PWE,ios,c1k,c1100, -C1111-4PWF,ios,c1k,c1100, -C1111-4PWH,ios,c1k,c1100, -C1111-4PWN,ios,c1k,c1100, -C1111-4PWQ,ios,c1k,c1100, -C1111-4PWR,ios,c1k,c1100, -C1111-4PWZ,ios,c1k,c1100, -C1111-8P,ios,c1k,c1100, -C1111-8PLTEEA,ios,c1k,c1100, -C1111-8PLTEEAWA,ios,c1k,c1100, -C1111-8PLTEEAWB,ios,c1k,c1100, -C1111-8PLTEEAWE,ios,c1k,c1100, -C1111-8PLTEEAWR,ios,c1k,c1100, -C1111-8PLTELA,ios,c1k,c1100, -C1111-8PLTELAWD,ios,c1k,c1100, -C1111-8PLTELAWF,ios,c1k,c1100, -C1111-8PLTELAWH,ios,c1k,c1100, -C1111-8PLTELAWN,ios,c1k,c1100, -C1111-8PLTELAWQ,ios,c1k,c1100, -C1111-8PLTELAWS,ios,c1k,c1100, -C1111-8PLTELAWZ,ios,c1k,c1100, -C1111-8PWA,ios,c1k,c1100, -C1111-8PWB,ios,c1k,c1100, -C1111-8PWE,ios,c1k,c1100, -C1111-8PWF,ios,c1k,c1100, -C1111-8PWH,ios,c1k,c1100, -C1111-8PWN,ios,c1k,c1100, -C1111-8PWQ,ios,c1k,c1100, -C1111-8PWR,ios,c1k,c1100, -C1111-8PWS,ios,c1k,c1100, -C1111-8PWZ,ios,c1k,c1100, -C1111X-8P,ios,c1k,c1100, -C1112-8P,ios,c1k,c1100, -C1112-8PLTEEA,ios,c1k,c1100, -C1112-8PLTEEAWE,ios,c1k,c1100, -C1112-8PWE,ios,c1k,c1100, -C1113-8P,ios,c1k,c1100, -C1113-8PLTEEA,ios,c1k,c1100, -C1113-8PLTEEAWB,ios,c1k,c1100, -C1113-8PLTEEAWE,ios,c1k,c1100, -C1113-8PLTELA,ios,c1k,c1100, -C1113-8PLTELAWA,ios,c1k,c1100, -C1113-8PLTELAWZ,ios,c1k,c1100, -C1113-8PM,ios,c1k,c1100, -C1113-8PMLTEEA,ios,c1k,c1100, -C1113-8PMWE,ios,c1k,c1100, -C1113-8PWA,ios,c1k,c1100, -C1113-8PWB,ios,c1k,c1100, -C1113-8PWE,ios,c1k,c1100, -C1113-8PWZ,ios,c1k,c1100, -C1116-4P,ios,c1k,c1100, -C1116-4PLTEEA,ios,c1k,c1100, -C1116-4PLTEEAWE,ios,c1k,c1100, -C1116-4PWE,ios,c1k,c1100, -C1117-4P,ios,c1k,c1100, -C1117-4PLTEEA,ios,c1k,c1100, -C1117-4PLTEEAWA,ios,c1k,c1100, -C1117-4PLTEEAWE,ios,c1k,c1100, -C1117-4PLTELA,ios,c1k,c1100, -C1117-4PLTELAWZ,ios,c1k,c1100, -C1117-4PM,ios,c1k,c1100, -C1117-4PMLTEEA,ios,c1k,c1100, -C1117-4PMLTEEAWE,ios,c1k,c1100, -C1117-4PMWE,ios,c1k,c1100, -C1117-4PWA,ios,c1k,c1100, -C1117-4PWE,ios,c1k,c1100, -C1117-4PWZ,ios,c1k,c1100, -C1118-8P,ios,c1k,c1100, -C1121-4P,ios,c1k,c1100, -C1121-4PLTEP,ios,c1k,c1100, -C1121-8P,ios,c1k,c1100, -C1121-8PLTEP,ios,c1k,c1100, -C1121-8PLTEPWB,ios,c1k,c1100, -C1121-8PLTEPWE,ios,c1k,c1100, -C1121-8PLTEPWQ,ios,c1k,c1100, -C1121-8PLTEPWZ,ios,c1k,c1100, -C1121X-8P,ios,c1k,c1100, -C1121X-8PLTEP,ios,c1k,c1100, -C1121X-8PLTEPWA,ios,c1k,c1100, -C1121X-8PLTEPWB,ios,c1k,c1100, -C1121X-8PLTEPWE,ios,c1k,c1100, -C1121X-8PLTEPWZ,ios,c1k,c1100, -C1126-8PLTEP,ios,c1k,c1100, -C1126X-8PLTEP,ios,c1k,c1100, -C1127-8PLTEP,ios,c1k,c1100, -C1127-8PMLTEP,ios,c1k,c1100, -C1127X-8PLTEP,ios,c1k,c1100, -C1127X-8PMLTEP,ios,c1k,c1100, -C1128-8PLTEP,ios,c1k,c1100, -C1161-8P,ios,c1k,c1100, -C1161-8PLTEP,ios,c1k,c1100, -C1161X-8P,ios,c1k,c1100, -C1161X-8PLTEP,ios,c1k,c1100, +C1101-4P,iosxe,c1k,c1100, +C1101-4PLTEP,iosxe,c1k,c1100, +C1101-4PLTEPWA,iosxe,c1k,c1100, +C1101-4PLTEPWB,iosxe,c1k,c1100, +C1101-4PLTEPWD,iosxe,c1k,c1100, +C1101-4PLTEPWE,iosxe,c1k,c1100, +C1101-4PLTEPWF,iosxe,c1k,c1100, +C1101-4PLTEPWH,iosxe,c1k,c1100, +C1101-4PLTEPWN,iosxe,c1k,c1100, +C1101-4PLTEPWQ,iosxe,c1k,c1100, +C1101-4PLTEPWR,iosxe,c1k,c1100, +C1101-4PLTEPWZ,iosxe,c1k,c1100, +C1109-2PLTEAU,iosxe,c1k,c1100, +C1109-2PLTEGB,iosxe,c1k,c1100, +C1109-2PLTEIN,iosxe,c1k,c1100, +C1109-2PLTEJN,iosxe,c1k,c1100, +C1109-2PLTEUS,iosxe,c1k,c1100, +C1109-2PLTEVZ,iosxe,c1k,c1100, +C1109-4PLTE2P,iosxe,c1k,c1100, +C1109-4PLTE2PWA,iosxe,c1k,c1100, +C1109-4PLTE2PWB,iosxe,c1k,c1100, +C1109-4PLTE2PWD,iosxe,c1k,c1100, +C1109-4PLTE2PWE,iosxe,c1k,c1100, +C1109-4PLTE2PWF,iosxe,c1k,c1100, +C1109-4PLTE2PWH,iosxe,c1k,c1100, +C1109-4PLTE2PWN,iosxe,c1k,c1100, +C1109-4PLTE2PWQ,iosxe,c1k,c1100, +C1109-4PLTE2PWR,iosxe,c1k,c1100, +C1109-4PLTE2PWZ,iosxe,c1k,c1100, +C1111-4P,iosxe,c1k,c1100, +C1111-4PLTEEA,iosxe,c1k,c1100, +C1111-4PLTELA,iosxe,c1k,c1100, +C1111-4PWA,iosxe,c1k,c1100, +C1111-4PWB,iosxe,c1k,c1100, +C1111-4PWD,iosxe,c1k,c1100, +C1111-4PWE,iosxe,c1k,c1100, +C1111-4PWF,iosxe,c1k,c1100, +C1111-4PWH,iosxe,c1k,c1100, +C1111-4PWN,iosxe,c1k,c1100, +C1111-4PWQ,iosxe,c1k,c1100, +C1111-4PWR,iosxe,c1k,c1100, +C1111-4PWZ,iosxe,c1k,c1100, +C1111-8P,iosxe,c1k,c1100, +C1111-8PLTEEA,iosxe,c1k,c1100, +C1111-8PLTEEAWA,iosxe,c1k,c1100, +C1111-8PLTEEAWB,iosxe,c1k,c1100, +C1111-8PLTEEAWE,iosxe,c1k,c1100, +C1111-8PLTEEAWR,iosxe,c1k,c1100, +C1111-8PLTELA,iosxe,c1k,c1100, +C1111-8PLTELAWD,iosxe,c1k,c1100, +C1111-8PLTELAWF,iosxe,c1k,c1100, +C1111-8PLTELAWH,iosxe,c1k,c1100, +C1111-8PLTELAWN,iosxe,c1k,c1100, +C1111-8PLTELAWQ,iosxe,c1k,c1100, +C1111-8PLTELAWS,iosxe,c1k,c1100, +C1111-8PLTELAWZ,iosxe,c1k,c1100, +C1111-8PWA,iosxe,c1k,c1100, +C1111-8PWB,iosxe,c1k,c1100, +C1111-8PWE,iosxe,c1k,c1100, +C1111-8PWF,iosxe,c1k,c1100, +C1111-8PWH,iosxe,c1k,c1100, +C1111-8PWN,iosxe,c1k,c1100, +C1111-8PWQ,iosxe,c1k,c1100, +C1111-8PWR,iosxe,c1k,c1100, +C1111-8PWS,iosxe,c1k,c1100, +C1111-8PWZ,iosxe,c1k,c1100, +C1111X-8P,iosxe,c1k,c1100, +C1112-8P,iosxe,c1k,c1100, +C1112-8PLTEEA,iosxe,c1k,c1100, +C1112-8PLTEEAWE,iosxe,c1k,c1100, +C1112-8PWE,iosxe,c1k,c1100, +C1113-8P,iosxe,c1k,c1100, +C1113-8PLTEEA,iosxe,c1k,c1100, +C1113-8PLTEEAWB,iosxe,c1k,c1100, +C1113-8PLTEEAWE,iosxe,c1k,c1100, +C1113-8PLTELA,iosxe,c1k,c1100, +C1113-8PLTELAWA,iosxe,c1k,c1100, +C1113-8PLTELAWZ,iosxe,c1k,c1100, +C1113-8PM,iosxe,c1k,c1100, +C1113-8PMLTEEA,iosxe,c1k,c1100, +C1113-8PMWE,iosxe,c1k,c1100, +C1113-8PWA,iosxe,c1k,c1100, +C1113-8PWB,iosxe,c1k,c1100, +C1113-8PWE,iosxe,c1k,c1100, +C1113-8PWZ,iosxe,c1k,c1100, +C1116-4P,iosxe,c1k,c1100, +C1116-4PLTEEA,iosxe,c1k,c1100, +C1116-4PLTEEAWE,iosxe,c1k,c1100, +C1116-4PWE,iosxe,c1k,c1100, +C1117-4P,iosxe,c1k,c1100, +C1117-4PLTEEA,iosxe,c1k,c1100, +C1117-4PLTEEAWA,iosxe,c1k,c1100, +C1117-4PLTEEAWE,iosxe,c1k,c1100, +C1117-4PLTELA,iosxe,c1k,c1100, +C1117-4PLTELAWZ,iosxe,c1k,c1100, +C1117-4PM,iosxe,c1k,c1100, +C1117-4PMLTEEA,iosxe,c1k,c1100, +C1117-4PMLTEEAWE,iosxe,c1k,c1100, +C1117-4PMWE,iosxe,c1k,c1100, +C1117-4PWA,iosxe,c1k,c1100, +C1117-4PWE,iosxe,c1k,c1100, +C1117-4PWZ,iosxe,c1k,c1100, +C1118-8P,iosxe,c1k,c1100, +C1121-4P,iosxe,c1k,c1100, +C1121-4PLTEP,iosxe,c1k,c1100, +C1121-8P,iosxe,c1k,c1100, +C1121-8PLTEP,iosxe,c1k,c1100, +C1121-8PLTEPWB,iosxe,c1k,c1100, +C1121-8PLTEPWE,iosxe,c1k,c1100, +C1121-8PLTEPWQ,iosxe,c1k,c1100, +C1121-8PLTEPWZ,iosxe,c1k,c1100, +C1121X-8P,iosxe,c1k,c1100, +C1121X-8PLTEP,iosxe,c1k,c1100, +C1121X-8PLTEPWA,iosxe,c1k,c1100, +C1121X-8PLTEPWB,iosxe,c1k,c1100, +C1121X-8PLTEPWE,iosxe,c1k,c1100, +C1121X-8PLTEPWZ,iosxe,c1k,c1100, +C1126-8PLTEP,iosxe,c1k,c1100, +C1126X-8PLTEP,iosxe,c1k,c1100, +C1127-8PLTEP,iosxe,c1k,c1100, +C1127-8PMLTEP,iosxe,c1k,c1100, +C1127X-8PLTEP,iosxe,c1k,c1100, +C1127X-8PMLTEP,iosxe,c1k,c1100, +C1128-8PLTEP,iosxe,c1k,c1100, +C1161-8P,iosxe,c1k,c1100, +C1161-8PLTEP,iosxe,c1k,c1100, +C1161X-8P,iosxe,c1k,c1100, +C1161X-8PLTEP,iosxe,c1k,c1100, C1861-SRST-B/K9,ios,c1k,c1800, C1861-SRST-C-B/K9,ios,c1k,c1800, C1861-SRST-C-F/K9,ios,c1k,c1800, @@ -457,7 +457,7 @@ C9800-CL-K9,iosxe,cat9k,c9800,c9800cl C9800-L-C-K9,iosxe,cat9k,c9800,c9800l C9800-L-F-K9,iosxe,cat9k,c9800,c9800l CGR-2010/K9,ios,c2k,c2000, -CGR1120/K9,ios,c1k,c1100, +CGR1120/K9,iosxe,c1k,c1100, CGR1240/K9,ios,c1k,c1200, CHAS-7505,ios,c7k,c7500, CHAS-7505-DC,ios,c7k,c7500, @@ -658,13 +658,13 @@ IE-3400H-8FT-A,iosxe,ie3k,ie3400, IE-3400H-8FT-E,iosxe,ie3k,ie3400, IE-3400H-8T-A,iosxe,ie3k,ie3400, IE-3400H-8T-E,iosxe,ie3k,ie3400, -IR1101-K9,ios,c1k,c1100, -ISR1100-4G,ios,isr1k,isr1100, -ISR1100-4GLTEGB,ios,isr1k,isr1100, -ISR1100-4GLTENA,ios,isr1k,isr1100, -ISR1100-6G,ios,isr1k,isr1100, -ISR1100X-4G,ios,isr1k,isr1100, -ISR1100X-6G,ios,isr1k,isr1100, +IR1101-K9,iosxe,c1k,c1100, +ISR1100-4G,iosxe,isr1k,isr1100, +ISR1100-4GLTEGB,iosxe,isr1k,isr1100, +ISR1100-4GLTENA,iosxe,isr1k,isr1100, +ISR1100-6G,iosxe,isr1k,isr1100, +ISR1100X-4G,iosxe,isr1k,isr1100, +ISR1100X-6G,iosxe,isr1k,isr1100, ISR4221-B/K9,iosxe,isr4k,isr4200, ISR4221/K9,iosxe,isr4k,isr4200, ISR4221X/K9,iosxe,isr4k,isr4200, diff --git a/src/unicon/plugins/tests/mock_data/iosxe/iosxe_mock_data_c8kv.yaml b/src/unicon/plugins/tests/mock_data/iosxe/iosxe_mock_data_c8kv.yaml index 3fca391a..9232f26b 100644 --- a/src/unicon/plugins/tests/mock_data/iosxe/iosxe_mock_data_c8kv.yaml +++ b/src/unicon/plugins/tests/mock_data/iosxe/iosxe_mock_data_c8kv.yaml @@ -223,3 +223,8 @@ c8kv_exec: 'enable': new_state: 'c8kv_enable' +c8kv_rommon: + prompt: "grub>" + commands: + 'boot': + new_state: 'c8kv_enable' diff --git a/src/unicon/plugins/tests/mock_data/iosxe/iosxe_mock_data_sdwan.yaml b/src/unicon/plugins/tests/mock_data/iosxe/iosxe_mock_data_sdwan.yaml index 81930436..f8fd55c8 100644 --- a/src/unicon/plugins/tests/mock_data/iosxe/iosxe_mock_data_sdwan.yaml +++ b/src/unicon/plugins/tests/mock_data/iosxe/iosxe_mock_data_sdwan.yaml @@ -43,7 +43,45 @@ sdwan_enable: client count = 84 client_notification_TMR = 30000 milliseconds RF debug mask = 0x0 - + "show inventory": | + NAME: "Chassis", DESCR: "Cisco C8530-12X4QC Chassis" + PID: C8530-12X4QC , VID: V00 , SN: FLX273502YF + + NAME: "Fan Tray", DESCR: "Cisco C8500-FAN-1R Fan Tray" + PID: C8500-FAN-1R , VID: , SN: + + NAME: "module 0", DESCR: "Cisco C8530-12X4QC Modular Interface Processor" + PID: C8530-12X4QC , VID: , SN: + + NAME: "SPA subslot 0/0", DESCR: "8-port 10/1G SFP Ethernet Port Adapter" + PID: 8xSFP+ , VID: N/A , SN: JAE12345678 + + NAME: "subslot 0/0 transceiver 0", DESCR: "10GE SR" + PID: SFP-10G-SR-S , VID: V01 , SN: OPM25160UGU + + NAME: "subslot 0/0 transceiver 1", DESCR: "10GE SR" + PID: SFP-10G-SR , VID: V03 , SN: AGA15514DWD + + NAME: "subslot 0/0 transceiver 2", DESCR: "10GE SR" + PID: SFP-10G-SR-S , VID: V01 , SN: FNS26090JAL + + NAME: "subslot 0/0 transceiver 3", DESCR: "10GE SR" + PID: SFP-10G-SR-S , VID: V01 , SN: FNS26090L1M + + NAME: "subslot 0/0 transceiver 4", DESCR: "10GE SR" + PID: SFP-10G-SR-S , VID: V01 , SN: FNS26090JAW + + NAME: "SPA subslot 0/1", DESCR: "1-port 40/1-port 100/4-port 10 Gigabit QSFP Ethernet Port Adapter" + PID: 4xSFP+/1xQSFP , VID: N/A , SN: JAE12345678 + + NAME: "SPA subslot 0/2", DESCR: "3-port 40 / 1-port 100 Gigabit QSFP Ethernet Port Adapter" + PID: 3xQSFP , VID: N/A , SN: JAE12345678 + + NAME: "module R0", DESCR: "Cisco C8530-12X4QC Route Processor" + PID: C8530-12X4QC , VID: V00 , SN: JAE273709CU + + NAME: "module F0", DESCR: "Cisco C8530-12X4QC Embedded Services Processor" + PID: C8530-12X4QC , VID: , SN: "config-transaction": new_state: sdwan_config @@ -123,14 +161,14 @@ sdwan_config_commit_confirm: "yes": new_state: sdwan_config2 -sdwan_controller_mode: +sdwan_controller_mode_1: prompt: "%N>" commands: "show version | include operating mode": "Router operating mode: Controller-Managed" "enable": - new_state: sdwan_controller_mode_enable + new_state: sdwan_controller_mode_enable_1 -sdwan_controller_mode_enable: +sdwan_controller_mode_enable_1: prompt: "%N#" commands: <<: *sdwan_enable_cmds @@ -190,44 +228,176 @@ sdwan_controller_mode_enable: 464553984K bytes of NVMe SSD flash at bootflash:. Configuration register is 0x2102 - "show inventory": | - NAME: "Chassis", DESCR: "Cisco C8530-12X4QC Chassis" - PID: C8530-12X4QC , VID: V00 , SN: FLX273502YF + "uname -a": "" + "pnpa service discovery stop": "" - NAME: "Fan Tray", DESCR: "Cisco C8500-FAN-1R Fan Tray" - PID: C8500-FAN-1R , VID: , SN: +sdwan_controller_mode_2: + prompt: "%N>" + commands: + "show version | include operating mode": "Router operating mode: Controller-Managed" + "enable": + new_state: sdwan_controller_mode_enable_2 - NAME: "module 0", DESCR: "Cisco C8530-12X4QC Modular Interface Processor" - PID: C8530-12X4QC , VID: , SN: +sdwan_controller_mode_enable_2: + prompt: "%N#" + commands: + <<: *sdwan_enable_cmds + "show version": | + Cisco IOS XE Software, Version BLD_V179_THROTTLE_LATEST_20240404_152224 + Cisco IOS Software [Cupertino], isr1100be Software (X86_64_LINUX_IOSD-UNIVERSALK9-M), Experimental Version 17.9.20240404:174358 [BLD_V179_THROTTLE_LATEST_20240404_152224:/nobackup/mcpre/s2c-build-ws 101] + Copyright (c) 1986-2024 by Cisco Systems, Inc. + Compiled Thu 04-Apr-24 10:43 by mcpre - NAME: "SPA subslot 0/0", DESCR: "8-port 10/1G SFP Ethernet Port Adapter" - PID: 8xSFP+ , VID: N/A , SN: JAE12345678 - NAME: "subslot 0/0 transceiver 0", DESCR: "10GE SR" - PID: SFP-10G-SR-S , VID: V01 , SN: OPM25160UGU + Cisco IOS-XE software, Copyright (c) 2005-2024 by cisco Systems, Inc. + All rights reserved. Certain components of Cisco IOS-XE software are + licensed under the GNU General Public License ("GPL") Version 2.0. The + software code licensed under GPL Version 2.0 is free software that comes + with ABSOLUTELY NO WARRANTY. You can redistribute and/or modify such + GPL code under the terms of GPL Version 2.0. For more details, see the + documentation or "License Notice" file accompanying the IOS-XE software, + or the applicable URL provided on the flyer accompanying the IOS-XE + software. - NAME: "subslot 0/0 transceiver 1", DESCR: "10GE SR" - PID: SFP-10G-SR , VID: V03 , SN: AGA15514DWD - NAME: "subslot 0/0 transceiver 2", DESCR: "10GE SR" - PID: SFP-10G-SR-S , VID: V01 , SN: FNS26090JAL + ROM: 17.7(1r) - NAME: "subslot 0/0 transceiver 3", DESCR: "10GE SR" - PID: SFP-10G-SR-S , VID: V01 , SN: FNS26090L1M + ISR1100-6G-Type2-03 uptime is 6 weeks, 5 days, 13 hours, 22 minutes + Uptime for this control processor is 6 weeks, 5 days, 13 hours, 23 minutes + System returned to ROM by Image Install at 09:00:04 UTC Fri Jan 19 2024 + System image file is "bootflash:packages.conf" + Last reload reason: Image Install - NAME: "subslot 0/0 transceiver 4", DESCR: "10GE SR" - PID: SFP-10G-SR-S , VID: V01 , SN: FNS26090JAW - NAME: "SPA subslot 0/1", DESCR: "1-port 40/1-port 100/4-port 10 Gigabit QSFP Ethernet Port Adapter" - PID: 4xSFP+/1xQSFP , VID: N/A , SN: JAE12345678 - NAME: "SPA subslot 0/2", DESCR: "3-port 40 / 1-port 100 Gigabit QSFP Ethernet Port Adapter" - PID: 3xQSFP , VID: N/A , SN: JAE12345678 + This product contains cryptographic features and is subject to United + States and local country laws governing import, export, transfer and + use. Delivery of Cisco cryptographic products does not imply + third-party authority to import, export, distribute or use encryption. + Importers, exporters, distributors and users are responsible for + compliance with U.S. and local country laws. By using this product you + agree to comply with applicable laws and regulations. If you are unable + to comply with U.S. and local laws, return this product immediately. - NAME: "module R0", DESCR: "Cisco C8530-12X4QC Route Processor" - PID: C8530-12X4QC , VID: V00 , SN: JAE273709CU + A summary of U.S. laws governing Cisco cryptographic products may be found at: + http://www.cisco.com/wwl/export/crypto/tool/stqrg.html - NAME: "module F0", DESCR: "Cisco C8530-12X4QC Embedded Services Processor" - PID: C8530-12X4QC , VID: , SN: + If you require further assistance please contact us by sending email to + export@cisco.com. + + + Technology Package License Information: + Controller-managed + + The current throughput level is unthrottled + + + Smart Licensing Status: Smart Licensing Using Policy + + cisco ISR1100-6G (1RU) processor with 1325907K/6147K bytes of memory. + Processor board ID FGL2443LA48 + Router operating mode: Controller-Managed + 6 Gigabit Ethernet interfaces + 32768K bytes of non-volatile configuration memory. + 4194304K bytes of physical memory. + 5949439K bytes of flash memory at bootflash:. + + Configuration register is 0x1822 + "uname -a": "" + "pnpa service discovery stop": "" + +sdwan_controller_mode_3: + prompt: "%N>" + commands: + "show version | include operating mode": "Router operating mode: Controller-Managed" + "enable": + new_state: sdwan_controller_mode_enable_3 + +sdwan_controller_mode_enable_3: + prompt: "%N#" + commands: + <<: *sdwan_enable_cmds + "show version": | + Cisco IOS XE Software, Version BLD_V1711_THROTTLE_LATEST_20230402_072111 + Cisco IOS Software [Dublin], ISR Software (ARMV8EL_LINUX_IOSD-UNIVERSALK9-M), Experimental Version 17.11.20230402:074537 [BLD_V1711_THROTTLE_LATEST_20230402_072111:/nobackup/mcpre/s2c-build-ws 101] + Copyright (c) 1986-2023 by Cisco Systems, Inc. + Compiled Sun 02-Apr-23 00:45 by mcpre + + + Cisco IOS-XE software, Copyright (c) 2005-2023 by cisco Systems, Inc. + All rights reserved. Certain components of Cisco IOS-XE software are + licensed under the GNU General Public License ("GPL") Version 2.0. The + software code licensed under GPL Version 2.0 is free software that comes + with ABSOLUTELY NO WARRANTY. You can redistribute and/or modify such + GPL code under the terms of GPL Version 2.0. For more details, see the + documentation or "License Notice" file accompanying the IOS-XE software, + or the applicable URL provided on the flyer accompanying the IOS-XE + software. + + + ROM: 17.5(1r) + + BR1003-1-C1111-4P uptime is 6 days, 16 hours, 3 minutes + Uptime for this control processor is 6 days, 16 hours, 4 minutes + System returned to ROM by Image Install at 21:12:25 IST Wed Feb 14 2024 + System restarted at 17:53:56 IST Thu May 30 2024 + System image file is "bootflash:packages.conf" + Last reload reason: Image Install + + + + This product contains cryptographic features and is subject to United + States and local country laws governing import, export, transfer and + use. Delivery of Cisco cryptographic products does not imply + third-party authority to import, export, distribute or use encryption. + Importers, exporters, distributors and users are responsible for + compliance with U.S. and local country laws. By using this product you + agree to comply with applicable laws and regulations. If you are unable + to comply with U.S. and local laws, return this product immediately. + + A summary of U.S. laws governing Cisco cryptographic products may be found at: + http://www.cisco.com/wwl/export/crypto/tool/stqrg.html + + If you require further assistance please contact us by sending email to + export@cisco.com. + + + + Suite License Information for Module:'esg' + + -------------------------------------------------------------------------------- + Suite Suite Current Type Suite Next reboot + -------------------------------------------------------------------------------- + FoundationSuiteK9 None Smart License None + securityk9 + appxk9 + + + Technology Package License Information: + + ----------------------------------------------------------------- + Technology Technology-package Technology-package + Current Type Next reboot + ------------------------------------------------------------------ + appxk9 appxk9 Smart License appxk9 + uck9 uck9 Smart License uck9 + securityk9 securityk9 Smart License securityk9 + ipbase ipbasek9 Smart License ipbasek9 + + The current throughput level is unthrottled + + + Smart Licensing Status: Smart Licensing Using Policy + + cisco C1111-4P (1RU) processor with 1352820K/6147K bytes of memory. + Processor board ID FGL2402LKX6 + Router operating mode: Controller-Managed + 1 Virtual Ethernet interface + 8 Gigabit Ethernet interfaces + 32768K bytes of non-volatile configuration memory. + 4194304K bytes of physical memory. + 2863103K bytes of flash memory at bootflash:. + + Configuration register is 0x2102 "uname -a": "" - "pnpa service discovery stop": "" \ No newline at end of file + "pnpa service discovery stop": "" diff --git a/src/unicon/plugins/tests/mock_data/iosxe/iosxe_mock_stack.yaml b/src/unicon/plugins/tests/mock_data/iosxe/iosxe_mock_stack.yaml index e01c1aec..5761675a 100644 --- a/src/unicon/plugins/tests/mock_data/iosxe/iosxe_mock_stack.yaml +++ b/src/unicon/plugins/tests/mock_data/iosxe/iosxe_mock_stack.yaml @@ -336,7 +336,7 @@ reload_prompt2: boot - new_state: stack_rommon + new_state: stack_rommon_1 stack_rommon: prompt: "switch: " @@ -352,13 +352,81 @@ reload_prompt_1: commands: "": new_state: stack_exec + install_add_commit: preface: |2 - Copying image file: bootflash:asr1000rpx86-universalk9.BLD_V166_THROTTLE_LATEST_20171101_090919_2.SSA.bin to standby - rsync: write failed on "asr1000rpx86-universalk9.BLD_V166_THROTTLE_LATEST_20171101_090919_2.SSA.bin" (in bootflash): No space left on device (28) - rsync error: error in file IO (code 11) at ../rsync-3.1.2/receiver.c(393) [receiver=3.1.2] - rsync error: error in file IO (code 11) at ../rsync-3.1.2/io.c(1633) [generator=3.1.2] - rsync: read error: Connection reset by peer (104) - FAILED: install_add_activate_commit : Copy bootflash:asr1000rpx86-universalk9.BLD_V16 + Copying image file: bootflash:asr1000rpx86-universalk9.BLD_V166_THROTTLE_LATEST_20171101_090919_2.SSA.bin to standby + rsync: write failed on "asr1000rpx86-universalk9.BLD_V166_THROTTLE_LATEST_20171101_090919_2.SSA.bin" (in bootflash): No space left on device (28) + rsync error: error in file IO (code 11) at ../rsync-3.1.2/receiver.c(393) [receiver=3.1.2] + rsync error: error in file IO (code 11) at ../rsync-3.1.2/io.c(1633) [generator=3.1.2] + rsync: read error: Connection reset by peer (104) + FAILED: install_add_activate_commit : Copy bootflash:asr1000rpx86-universalk9.BLD_V16 new_state: stack_enable +stack_rommon_1: + prompt: "switch: " + commands: + "boot": + response: | + Booting...(use SKIP_POST)Up 1000 Mbps Full duplex (port 0) (SGMII) + + The system is not configured to boot automatically. The + following command will finish loading the operating system + software: + + boot + + + switch: boot + Reading full image into memory.............................................................................................................................................................................................................................................................................................................................................................................................................................................................................done + Bundle Image + -------------------------------------- + Kernel Address : 0x53778818 + Kernel Size : 0x438410/4424720 + Initramfs Address : 0x53bb0c28 + Initramfs Size : 0x1abc00f/28033039 + Compression Format: mzip + + Bootable image at @ ram:0x53778818 + Bootable image segment 0 address range [0x81100000, 0x81da5280] is in range [0x80180000, 0x90000000]. + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + File "tftp://10.1.7.250/auto/nostgAuto/USERS/ranautiy/nirmagup/IOSXE/cat3k_caa-universalk9.BLD_V1612_THROTTLE_LATEST_20200403_053502_V16_12_3_6.SSA.bin" uncompressed and installed, entry point: 0x81895bf0 + Loading Linux kernel with entry point 0x81895bf0 ... + Bootloader: Done loading app on core_mask: 0xf + + ### Launching Linux Kernel (flags = 0x5) + + Linux version 4.9.187 (xelinux@sjc-xelinux2) (gcc version 5.3.0 (GCC) ) #1 SMP Wed Dec 11 09:25:00 PST 2019 + CVMSEG size: 2 cache lines (256 bytes) + Cavium Inc. SDK-5.1.0 + bootconsole [early0] enabled + CPU0 revision is: 000d900a (Cavium Octeon II) + Checking for the multiply/shift bug... no. + Checking for the daddiu bug... no. + %IOSXEBOOT-c34ad91569d0f862504bc287a15afe2e-new_cksum: (rp/0): 4 + %IOSXEBOOT-c34ad91569d0f862504bc287a15afe2e-saved_cksum: (rp/0): 4 + + Final tar file: mcu_ucode_bundle_6_2_0.tar + + Waiting for 120 seconds for other switches to boot + ##### + Switch number is 2 + All switches in the stack have been discovered. Accelerating discovery + timing: + - 0:,0,0.005 + new_state: stack_press_return + + + +stack_press_return: + prompt: "This software version supports only Smart Licensing as the software licensing mechanism." + commands: + "": + new_state: stack_press_return_1 + + +stack_press_return_1: + prompt: "Press RETURN to get started!" + commands: + "": + new_state: stack_exec \ No newline at end of file diff --git a/src/unicon/plugins/tests/mock_data/iosxr/iosxr_mock_data.yaml b/src/unicon/plugins/tests/mock_data/iosxr/iosxr_mock_data.yaml index 1596c7f2..3f497ed8 100644 --- a/src/unicon/plugins/tests/mock_data/iosxr/iosxr_mock_data.yaml +++ b/src/unicon/plugins/tests/mock_data/iosxr/iosxr_mock_data.yaml @@ -442,7 +442,6 @@ admin: 0/PM4/SP A9K-3KW-AC READY PWR,NSHUT,MON 0/PM5/SP A9K-3KW-AC FAILED PWR,NSHUT,MON - config: prompt: "RP/0/RP0/CPU0:%N(config)#" commands: &config_cmds @@ -1395,3 +1394,36 @@ bash_console5: prompt: "[xr-vm_nodeD0_CB0_CPU0:~]$" commands: <<: *bash_commands + +enable6: + prompt: "RP/0/RP0/CPU0:%N#" + commands: + "admin": + new_state: bash_console6 + +bash_console6: + preface: | + Tue Jun 6 07:50:51.753 UTC + Last login: Mon Jun 5 15:09:57 2023 from 192.0.0.4 + admin connected from 192.0.0.4 using ssh on sysadmin-vm:0_RP0 + prompt: sysadmin-vm:0_RP0# + commands: + "run": + new_state: admin_bash_console6 + "exit": + new_state: enable6 + +admin_bash_console6: + preface: "Tue Jun 6 07:50:55.337 UTC+00:00" + prompt: "[sysadmin-vm:0_RP0:~]$" + commands: + "ssh 10.0.2.16": + new_state: admin_host6 + "exit": + new_state: bash_console6 + +admin_host6: + prompt: "[host:0_RP0:~]$" + commands: + "exit": + new_state: admin_bash_console6 \ No newline at end of file diff --git a/src/unicon/plugins/tests/test_plugin_iosxe.py b/src/unicon/plugins/tests/test_plugin_iosxe.py index 47ff6948..640a7f08 100644 --- a/src/unicon/plugins/tests/test_plugin_iosxe.py +++ b/src/unicon/plugins/tests/test_plugin_iosxe.py @@ -568,6 +568,15 @@ def test_config_transaction_sdwan_iosxe_confirm(self): d.configure('no logging console') d.disconnect() +class TestIosXEC8KVPlugin(unittest.TestCase): + def test_connect(self): + d = Connection(hostname="switch", + start=["mock_device_cli --os iosxe --state c8kv_rommon --hostname switch"], + os="iosxe", + platform="cat8k", + log_buffer=True) + d.connect() + d.disconnect() class TestIosXEC8KvPluginReload(unittest.TestCase): @classmethod diff --git a/src/unicon/plugins/tests/test_plugin_iosxe_sdwan.py b/src/unicon/plugins/tests/test_plugin_iosxe_sdwan.py index 18f07bd9..6a1a9442 100644 --- a/src/unicon/plugins/tests/test_plugin_iosxe_sdwan.py +++ b/src/unicon/plugins/tests/test_plugin_iosxe_sdwan.py @@ -1,12 +1,9 @@ import unittest -from unittest.mock import patch from pyats.topology import loader import unicon from unicon import Connection -from unicon.eal.dialogs import Dialog, Statement -from unicon.core.errors import SubCommandFailure, StateMachineError, UniconAuthenticationError, ConnectionError as UniconConnectionError from unicon.plugins.tests.mock.mock_device_iosxe import MockDeviceTcpWrapperIOSXE unicon.settings.Settings.POST_DISCONNECT_WAIT_SEC = 0 @@ -76,7 +73,7 @@ def test_iosxe_sdwan_connect(self): finally: d.disconnect() - def test_iosxe_sdwan_controller_mode_connect(self): + def test_iosxe_sdwan_controller_mode_connect_1(self): testbed = ''' devices: Router: @@ -91,7 +88,55 @@ def test_iosxe_sdwan_controller_mode_connect(self): defaults: class: 'unicon.Unicon' cli: - command: mock_device_cli --os iosxe --state sdwan_controller_mode + command: mock_device_cli --os iosxe --state sdwan_controller_mode_1 + ''' + t = loader.load(testbed) + d = t.devices.Router + try: + d.connect() + finally: + d.disconnect() + + def test_iosxe_sdwan_controller_mode_connect_2(self): + testbed = ''' + devices: + Router: + type: router + os: iosxe + platform: sdwan + credentials: + default: + username: cisco + password: cisco + connections: + defaults: + class: 'unicon.Unicon' + cli: + command: mock_device_cli --os iosxe --state sdwan_controller_mode_2 + ''' + t = loader.load(testbed) + d = t.devices.Router + try: + d.connect() + finally: + d.disconnect() + + def test_iosxe_sdwan_controller_mode_connect_3(self): + testbed = ''' + devices: + Router: + type: router + os: iosxe + platform: sdwan + credentials: + default: + username: cisco + password: cisco + connections: + defaults: + class: 'unicon.Unicon' + cli: + command: mock_device_cli --os iosxe --state sdwan_controller_mode_3 ''' t = loader.load(testbed) d = t.devices.Router diff --git a/src/unicon/plugins/tests/test_plugin_iosxe_stack.py b/src/unicon/plugins/tests/test_plugin_iosxe_stack.py index 88b7a156..5d7ae27c 100644 --- a/src/unicon/plugins/tests/test_plugin_iosxe_stack.py +++ b/src/unicon/plugins/tests/test_plugin_iosxe_stack.py @@ -385,6 +385,26 @@ def test_get_redundancy_details(self): "state": "Ready" } }, rd) + + def test_wait_for_any_state(self): + '''Test wait_for_any_state with positive timeout''' + su = StackUtils() + su.wait_for_any_state(connection=self.c, timeout=2, interval=1) + + def test_wait_for_any_state2(self): + '''Test wait_for_any_state with negative timeout and auto_timeout_extend=True''' + su = StackUtils() + su.wait_for_any_state(connection=self.c, timeout=-10, interval=1, auto_timeout_extend=True, auto_extend_secs=2) + + def test_is_all_member_ready(self): + '''Test is_all_member_ready''' + su = StackUtils() + self.assertTrue(su.is_all_member_ready(connection=self.c, timeout=2, interval=1)) + + def test_is_active_standby_ready(self): + '''Test is_active_standby_ready''' + su = StackUtils() + self.assertTrue(su.is_active_standby_ready(connection=self.c, timeout=2, interval=1)) if __name__ == "__main__": diff --git a/src/unicon/plugins/tests/test_plugin_iosxr.py b/src/unicon/plugins/tests/test_plugin_iosxr.py index 2b404d22..68150550 100644 --- a/src/unicon/plugins/tests/test_plugin_iosxr.py +++ b/src/unicon/plugins/tests/test_plugin_iosxr.py @@ -225,6 +225,16 @@ def test_admin(self): self.assertIn('exit', ret) self.assertIn('Router#', ret) + def test_admin_host(self): + conn = Connection(hostname='Router', + start=['mock_device_cli --os iosxr --state enable6'], + os='iosxr', + enable_password='cisco', + mit=True) + + conn.connect() + with conn.admin_bash_console() as console: + console.execute('ssh 10.0.2.16', allow_state_change=True) class TestIosXrPluginBashService(unittest.TestCase):