Skip to content

Commit

Permalink
Merge pull request #63 from CiscoTestAutomation/release_22.9
Browse files Browse the repository at this point in the history
Releasing v22.9
  • Loading branch information
bastell authored Sep 27, 2022
2 parents d1a4ac5 + 55bb35d commit 7d80dc9
Show file tree
Hide file tree
Showing 26 changed files with 489 additions and 46 deletions.
17 changes: 17 additions & 0 deletions docs/changelog/2022/september.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
--------------------------------------------------------------------------------
New
--------------------------------------------------------------------------------

* connection base
* add option log_propagate to control whether logger for the connection propagates logs to parent
* add option no_pyats_tasklog to prevent Unicon from adding pyats tasklog handler


--------------------------------------------------------------------------------
Fix
--------------------------------------------------------------------------------

* mock_device
* Fixed issue with HA mode mock device when asyncssh package is not installed


2 changes: 2 additions & 0 deletions docs/changelog_plugins/2022/august.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,6 @@
* iosxe/cat9k
* Updated the container shell prompt pattern

* iosxe/cat8k
* Added Reload and HAReload

21 changes: 21 additions & 0 deletions docs/changelog_plugins/2022/september.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
--------------------------------------------------------------------------------
Fix
--------------------------------------------------------------------------------

* generic
* Added setting for state change prompt retries, default to 3 second wait
* Update sudo regex pattern
* Updated the session data to handle the reoccurring dialog issue
* Update copy error pattern to ignore self-signed certificate failure
* Add handlers for ping options extended_verbose, timestamp_count, record_hops, src_route_type

* iosxr/ncs5k
* Updated the mock data for ncs5k

* iosxe
* Added a RELOAD_WAIT to iosxe settings

* hvrp
* Updated the pattern and setting to support configuration and error detection.


7 changes: 7 additions & 0 deletions docs/user_guide/connection.rst
Original file line number Diff line number Diff line change
Expand Up @@ -815,6 +815,13 @@ Arguments:
* **log_stdout**: Boolean option to enable/disable logging to standard output. Default is True.
*(Optional)*

* **log_propagate**: Boolean option to enable/disable propagating logs from connection logger
to parent logger (e.g. whether logs for `unicon.N7K-BESTPROD2-SSR-P1.cli.1663541251` logger
should propagate to `unicon` logger). Default is False. *(Optional)*

* **no_pyats_tasklog**: Boolean option to enable/disable logging to pyats tasklog. Default is False.
*(Optional)*

* **debug**: Boolean option to enable/disable internal debug logging.
*(Optional)*

Expand Down
11 changes: 0 additions & 11 deletions setup.cfg

This file was deleted.

2 changes: 1 addition & 1 deletion src/unicon/plugins/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
__version__ = '22.8'
__version__ = '22.9'

supported_chassis = [
'single_rp',
Expand Down
2 changes: 1 addition & 1 deletion src/unicon/plugins/generic/patterns.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def __init__(self):

self.learn_os_prompt = r'^(.*?([>\$~%]|[^#\s]#|~ #|~/|^admin:|^#)\s?(\x1b\S+)?)$|(^.*This \(D\)RP Node is not ready or active for login \/configuration.*)'

self.sudo_password_prompt = r'^.*\[sudo\] password for .*?:\s*?'
self.sudo_password_prompt = r'^.*(\[sudo\] password for .*?:|This is your UNIX password:)\s*$'

# *Sep 6 23:13:38.188: %PNP-6-PNP_SDWAN_STARTED: PnP SDWAN started (7) via (pnp-sdwan-abort-on-cli) by (pid=3, pname=Exec)
# *Sep 6 23:18:11.702: %ENVIRONMENTAL-1-ALERT: Temp: Inlet 1, Location: R0, State: Warning, Reading: 45 Celsius
Expand Down
12 changes: 8 additions & 4 deletions src/unicon/plugins/generic/service_implementation.py
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,8 @@ def __init__(self, connection, context, **kwargs):
self.dialog = Dialog(execution_statement_list)
self.matched_retries = connection.settings.EXECUTE_MATCHED_RETRIES
self.matched_retry_sleep = connection.settings.EXECUTE_MATCHED_RETRY_SLEEP
self.state_change_matched_retries = connection.settings.EXECUTE_STATE_CHANGE_MATCH_RETRIES
self.state_change_matched_retry_sleep = connection.settings.EXECUTE_STATE_CHANGE_MATCH_RETRY_SLEEP

def log_service_call(self):
pass
Expand Down Expand Up @@ -684,16 +686,16 @@ def call_service(self, command=[], # noqa: C901
if allow_state_change:
dialog.append(Statement(
pattern=state.pattern,
matched_retries=matched_retries,
matched_retry_sleep=matched_retry_sleep
matched_retries=self.state_change_matched_retries,
matched_retry_sleep=self.state_change_matched_retry_sleep
))
else:
dialog.append(Statement(
pattern=state.pattern,
action=invalid_state_change_action,
args={'err_state': state, 'sm': sm},
matched_retries=matched_retries,
matched_retry_sleep=matched_retry_sleep
matched_retries=self.state_change_matched_retries,
matched_retry_sleep=self.state_change_matched_retry_sleep
))

# store the last used dialog, used by unittest
Expand Down Expand Up @@ -950,11 +952,13 @@ def call_service(self, # noqa: C901
sp.sendline(cmd)
self.update_hostname_if_needed([cmd])
self.process_dialog_on_handle(handle, dialog, timeout)
# To handle the session
if handle.context.get('config_session_locked'):
self.connection.log.warning('Config locked, waiting {} seconds'.format(
self.connection.settings.CONFIG_LOCK_RETRY_SLEEP))
sleep(self.connection.settings.CONFIG_LOCK_RETRY_SLEEP)
config_transition(handle.state_machine, handle.spawn, handle.context)
handle.context['config_session_locked'] = False
sp.sendline(cmd)
self.process_dialog_on_handle(handle, dialog, timeout)

Expand Down
15 changes: 8 additions & 7 deletions src/unicon/plugins/generic/service_patterns.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ def __init__(self):
self.data_pattern = r'^.*Data pattern \[.+\]\s?: $'
self.dfbit_header = r'^.*Set DF bit in IP header(\?)? \[.+\]\s?: $'
self.dscp = r'^.*DSCP .*\[.+\]\s?: $'
self.lsrtv = r'^.*Loose, Strict, Record, Timestamp, Verbose\s?\[.+\]\s?: $'
self.lsrtv = r'^.*Loose, Strict, Record, Timestamp, Verbose\s?\[(.+)\]\s?: $'
self.qos = r'^.*Include global QOS option\? \[.+\]\s?: $'
self.packet = r'^.*Pad packet\? \[.+\]\s?: $'
# Range internal dialogs
Expand All @@ -115,10 +115,11 @@ def __init__(self):
self.others = r'^.*\[.+\]\s?: $'
# extd_LSRTV patterns
self.lsrtv_source = r'^.*Source route: $'
self.lsrtv_hot_count = r'^.*Number of hops \[.*\]: $'
self.lsrtv_timestamp_count = r'^.*Number of timestamps \[.*\]: $}'
self.lsrtv_noroom = r'^.*No room for that option$'
self.lsrtv_invalid_hop = r'^.*Invalid number of hops$'
self.lsrtv_hop_count = r'^.*Number of hops \[.*\]: $'
self.lsrtv_timestamp_count = r'^.*Number of timestamps \[.*\]: $'
self.lsrtv_noroom = r'^.*No room for that option'
self.lsrtv_invalid_hop = r'^.*Invalid number of hops'
self.lsrtv_one_allowed = r'^.*% Only one source route option allowed'
# Invalid commands
self.invalid_command = r'^.*% *Invalid.*'

Expand Down Expand Up @@ -155,10 +156,10 @@ def __init__(self):
self.tftp_addr =r'^.*Address.*$'
self.copy_complete = r'^.*bank [0-9]+'
self.copy_error_message = r'fail|timed out|Timed out|Error|Login incorrect|denied|Problem' \
r'|NOT|Invalid|No memory|Failed|mismatch|Bad|bogus|lose|abort' \
r'|NOT|Invalid|No memory|Failed(?! to generate persistent self-signed certificate)|mismatch|Bad|bogus|lose|abort' \
r'|Not |too big|exceeds|detected|[Nn]o route to host' \
r'|image is not allowed|Could not resolve|No such'
self.copy_retry_message = r'fail|[Tt]imed out|Error|Problem|NOT|Failed|Bad|bogus|lose|abort|Not |too big|exceeds|detected'
self.copy_retry_message = r'fail|[Tt]imed out|Error|Problem|NOT|Failed(?! to generate persistent self-signed certificate)|Bad|bogus|lose|abort|Not |too big|exceeds|detected'
self.copy_continue = r'Are you sure you want to continue connecting ((yes/no)|\((yes/no(/\[fingerprint\])?)?\))?'
self.copy_other = r'^.*\[yes\/no\]\s*\?*\s*$'
self.remote_param ='ftp:|tftp:|http:|rcp:|scp:'
Expand Down
58 changes: 58 additions & 0 deletions src/unicon/plugins/generic/service_statements.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,26 @@ def ping_handler_1(spawn, context, send_key):
spawn.sendline(context[send_key])


def lsrtv_handler(spawn, context):
selection = spawn.match.last_match.group(1)
if context.get('extended_verbose') and 'V' not in selection:
spawn.sendline('v')
return
if context.get('timestamp_count') and 'T' not in selection:
spawn.sendline('t')
return
if context.get('record_hops') and 'R' not in selection:
spawn.sendline('r')
return
if context.get('src_route_type', '').lower() == 'loose' and 'L' not in selection:
spawn.sendline('l')
return
if context.get('src_route_type', '').lower() == 'strict' and 'S' not in selection:
spawn.sendline('s')
return
spawn.sendline()


def send_multicast(spawn, context):
if context.get('multicast'):
spawn.sendline(context['multicast'])
Expand Down Expand Up @@ -603,6 +623,39 @@ def config_session_locked_handler(context):
loop_continue=True,
continue_timer=False)

lsrtv_stmt = Statement(pattern=pat.lsrtv,
action=lsrtv_handler,
loop_continue=True,
continue_timer=False)

lsrtv_timestamp = Statement(pattern=pat.lsrtv_timestamp_count,
action=ping_handler,
args={'send_key': 'timestamp_count'},
loop_continue=True,
continue_timer=False)

lsrtv_hop_count = Statement(pattern=pat.lsrtv_hop_count,
action=ping_handler,
args={'send_key': 'record_hops'},
loop_continue=True,
continue_timer=False)

lsrtv_source = Statement(pattern=pat.lsrtv_source,
action=ping_handler,
args={'send_key': 'src_route_addr'},
loop_continue=True,
continue_timer=False)

lsrtv_one_allowed = Statement(pattern=pat.lsrtv_one_allowed,
action=ping_invalid_input_handler,
loop_continue=True,
continue_timer=False)

lsrtv_noroom = Statement(pattern=pat.lsrtv_noroom,
action=ping_invalid_input_handler,
loop_continue=True,
continue_timer=False)

####################################################################
# Traceroute Statements
####################################################################
Expand Down Expand Up @@ -728,6 +781,11 @@ def config_session_locked_handler(context):
extended_ping_dialog_list = [invalid_input, unkonwn_protocol, protocol, transport,
mask, address, vcid, tunnel, repeat, size, verbose,
interval, packet_timeout, sending_interval,
# error patterns:
lsrtv_noroom, lsrtv_one_allowed,
# the error patterns need to come before lsrtv_stmt
lsrtv_stmt,
lsrtv_timestamp, lsrtv_hop_count, lsrtv_source,
output_interface, novell_echo_type, vrf, ext_cmds,
sweep_range, range_interval, range_max, range_min,
dest_start, interface, dest_end, increment,
Expand Down
10 changes: 5 additions & 5 deletions src/unicon/plugins/generic/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,10 +136,14 @@ def __init__(self):
self.BULK_CONFIG_CHUNK_LINES = 50
self.BULK_CONFIG_CHUNK_SLEEP = 0.5

# for execute matched retry on state pattern
# for execute matched retry on statement pattern
self.EXECUTE_MATCHED_RETRIES = 1
self.EXECUTE_MATCHED_RETRY_SLEEP = 0.05

# execute statement match retry for state change patterns
self.EXECUTE_STATE_CHANGE_MATCH_RETRIES = 1
self.EXECUTE_STATE_CHANGE_MATCH_RETRY_SLEEP = 3

# User defined login and password prompt pattern.
self.LOGIN_PROMPT = None
self.PASSWORD_PROMPT = None
Expand Down Expand Up @@ -275,7 +279,3 @@ def __init__(self):
},
}

#TODO
#take addtional dialogs for all service
#move all commands to settings
#
5 changes: 3 additions & 2 deletions src/unicon/plugins/hvrp/patterns.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ def __init__(self):
self.password = r'^.*[Pp]assword:'

# <HOSTNAME-01> | <HOSTNAME>#
self.enable_prompt = r'^(.*)\<.*\>$'
self.enable_prompt = r'^(.*)\<%N.*\>$'


# [~HOSTNAME] | <HOSTNAME-01> # # breaks on [\y\n] # Warning: All the configuration will be saved to the next startup configuration. Continue? [y/n]:
self.config_prompt = r'^\[.*\]'
self.config_prompt = r'^.*\[(~|\*)%N.*\]'

# Exit with uncommitted changes? [yes,no] (yes)
self.commit_changes_prompt = r'Exit with uncommitted changes? [yes,no] (yes)\s*'
Expand Down
2 changes: 2 additions & 0 deletions src/unicon/plugins/hvrp/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,5 @@ def __init__(self):
]

self.HA_INIT_CONFIG_COMMANDS = []
self.ERROR_PATTERN.append("Error:.*")
self.CONFIGURE_ERROR_PATTERN.append(r'^Error:.*')
2 changes: 2 additions & 0 deletions src/unicon/plugins/iosxe/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ def __init__(self):
self.EXECUTE_MATCHED_RETRIES = 1
self.EXECUTE_MATCHED_RETRY_SLEEP = 0.1

self.RELOAD_WAIT = 300

self.CONFIG_LOCK_RETRY_SLEEP = 30
self.CONFIG_LOCK_RETRIES = 10

Expand Down
1 change: 1 addition & 0 deletions src/unicon/plugins/tests/mock/mock_device_hvrp.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class MockDeviceHuaweiVrp(MockDevice):

def __init__(self, *args, **kwargs):
super().__init__(*args, device_os='hvrp', **kwargs)
self.invalid_command_response = "Error: Unrecognized command found "


class MockDeviceTcpWrapperHuaweiVrp(MockDeviceTcpWrapper):
Expand Down
45 changes: 42 additions & 3 deletions src/unicon/plugins/tests/mock_data/hvrp/hvrp_mock_data.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ exec:
prompt: "<ooo-gg-9999zz-99>"
commands:
"display version" : |
"Huawei Versatile Routing Platform Software
Huawei Versatile Routing Platform Software
VRP (R) software, Version 5.170 (AR650 V300R019C11SPC200)
Copyright (C) 2011-2020 HUAWEI TECH CO., LTD
Huawei AR657W Router uptime is 0 week, 0 day, 0 hour, 4 minutes
Expand All @@ -28,8 +28,14 @@ exec:
4. CPLD0 Version : 103
5. BootROM Version : 1
"
"screen-length 0 temporary": "Info: The configuration takes effect on the current user terminal interface only."
"undo terminal alarm": "Info: Current alarm terminal is off."
"undo terminal logging": "Info: Current terminal logging is off."
"undo terminal debugging": "Info: Current terminal debugging is off."
"undo terminal monitor": "Info: Current terminal monitor is off."
"system-view":
new_state: config

user_access_veri:
preface: User Access Verification
Expand All @@ -42,4 +48,37 @@ user_password:
prompt: "Password: "
commands:
"kpn":
new_state: exec
new_state: exec

config:
preface: |
Enter system view, return user view with return command.
prompt: "[~ooo-gg-9999zz-99]"
commands:
"bgp 65000":
new_state: bgp_config
"commit": ""
"return":
new_state: exec

bgp_config:
prompt: "[~ooo-gg-9999zz-99-bgp]"
commands:
"peer 1.1.1.1 as-number 64666":
new_state: bgp_config_uncommitted_change
"commit": ""
"exit":
new_state: config
"return":
new_state: exec

bgp_config_uncommitted_change:
prompt: "[*ooo-gg-9999zz-99-bgp]"
commands:
"commit":
response: "Committing....done."
timing:
- "0:,0,2,0"
new_state: bgp_config


2 changes: 2 additions & 0 deletions src/unicon/plugins/tests/mock_data/ios/ios_mock_data.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,8 @@ enable:
- "3:,0.5"
"ping vrf management":
new_state: ping_proto_ios_vrf
"ping vrf mgmt":
new_state: ping_proto_ios_verbose
"sh redundancy stat | inc my state":
my state = 13 -ACTIVE
"show redundancy sta | in my": |
Expand Down
Loading

0 comments on commit 7d80dc9

Please sign in to comment.