Closed MarkRudenko closed 1 year ago
yeah I think you're bang on, wanna try updating scrapli platform here (or you can pass custom privilege levels if you dont wanna mess w/ editing scrapli directly) to confirm bumping that {0,32}
-> {0,63}
on line 34 works for ya? if that looks good I can add some quick test and get that merged this weekend prolly.
I'm almost sure that it would help =) Please try changing regex. Thanks a lot!
In [1]: import re In [2]: re.search(r"^[\w.-@()/: ]{1,63}(config[\w.-@/:]{0,63})#\s?$", "test-dcs7010t-6(config-s-scrapl-qos-profile-CORE-EGRESS-QUEUING-txq-5)#") Out[2]: <re.Match object; span=(0, 71), match='test-dcs7010t-6(config-s-scrapl-qos-profile-CORE->
sounds good -- will try to get that merged this weekend, will keep ya posted, thanks @MarkRudenko !
Hello Carl. I found that it also can't determine the privilege level when searching diff.
In [300]: conn = AsyncScrapli(**device)
...: conn.privilege_levels["configuration"].pattern = r"^[\w.\-@()/: ]{1,63}\(config[\w.\-@/:]{0,63}\)#\s?$"
...: await conn.open()
...: cfg_conn = AsyncScrapliCfg(conn=conn)
...: await cfg_conn.prepare()
...: loaded_cfg = await cfg_conn.load_config(qos_conf)
In [308]: await cfg_conn.diff_config()
INFO:scrapli_cfg.platform:diff_config requested
INFO:scrapli.channel:sending channel input: show session-config diffs; strip_prompt: True; eager: False
DEBUG:scrapli.channel:write: 'show session-config diffs'
DEBUG:scrapli.channel:read: b'show session-config diffs'
DEBUG:scrapli.channel:write: '\n'
DEBUG:scrapli.channel:read: b'\n'
DEBUG:scrapli.channel:read: b'\n'
DEBUG:scrapli.channel:read: b'eos_switch(config-s-scrapl-qos-profile-CORE-EGRESS-QUEUING-txq-6)#'
INFO:scrapli_cfg.platform:get_config for config source 'running' requested
DEBUG:scrapli.channel:write: '\n'
DEBUG:scrapli.channel:read: b'\n'
DEBUG:scrapli.channel:read: b'eos_switch(config-s-scrapl-qos-profile-CORE-EGRESS-QUEUING-txq-6)#'
INFO:scrapli.driver:attempting to acquire 'privilege_exec' privilege level
CRITICAL:scrapli.driver:could not determine privilege level from provided prompt: 'eos_switch(config-s-scrapl-qos-profile-CORE-EGRESS-QUEUING-txq-6)#'
---------------------------------------------------------------------------
ScrapliPrivilegeError Traceback (most recent call last)
<ipython-input-308-06b1126ae972> in <module>
----> 1 await cfg_conn.diff_config()
/opt/homebrew/lib/python3.9/site-packages/scrapli_cfg/platform/core/arista_eos/async_platform.py in diff_config(self, source)
263 device_diff = diff_result.result
264
--> 265 source_config_result = await self.get_config(source=source)
266 source_config = source_config_result.result
267
/opt/homebrew/lib/python3.9/site-packages/scrapli_cfg/platform/core/arista_eos/async_platform.py in get_config(self, source)
126 response = self._pre_get_config(source=source)
127
--> 128 config_result = await self.conn.send_command(
129 command=self._get_config_command(source=source)
130 )
/opt/homebrew/lib/python3.9/site-packages/scrapli/driver/network/async_driver.py in send_command(self, command, strip_prompt, failed_when_contains, timeout_ops)
236
237 """
--> 238 await self._acquire_appropriate_privilege_level()
239
240 if failed_when_contains is None:
/opt/homebrew/lib/python3.9/site-packages/scrapli/driver/network/async_driver.py in _acquire_appropriate_privilege_level(self, privilege_level)
206
207 if self._current_priv_level.name != resolved_privilege_level:
--> 208 await self.acquire_priv(desired_priv=resolved_privilege_level)
209
210 async def send_command(
/opt/homebrew/lib/python3.9/site-packages/scrapli/driver/network/async_driver.py in acquire_priv(self, desired_priv)
155 while True:
156 current_prompt = await self.channel.get_prompt()
--> 157 privilege_action, target_priv = self._process_acquire_priv(
158 destination_priv=desired_priv,
159 current_prompt=current_prompt,
/opt/homebrew/lib/python3.9/site-packages/scrapli/driver/network/base_driver.py in _process_acquire_priv(self, destination_priv, current_prompt)
333
334 # decide if we are already at the desired priv, then we don't need to do any thing!
--> 335 current_priv_patterns = self._determine_current_priv(current_prompt=current_prompt)
336
337 if self._current_priv_level.name in current_priv_patterns:
/opt/homebrew/lib/python3.9/site-packages/scrapli/driver/network/base_driver.py in _determine_current_priv(self, current_prompt)
148 msg = f"could not determine privilege level from provided prompt: '{current_prompt}'"
149 self.logger.critical(msg)
--> 150 raise ScrapliPrivilegeError(msg)
151
152 self.logger.debug(f"determined current privilege level is one of '{matching_priv_levels}'")
ScrapliPrivilegeError: could not determine privilege level from provided prompt: 'eos_switch(config-s-scrapl-qos-profile-CORE-EGRESS-QUEUING-txq-6)#'
It looks like that regex in EOSDriverBase should be changed also ({0,32} -> {0,63}):
rf"^[a-z0-9.\-@()/: ]{{1,63}}\(config\-s\-{sess_prompt}[a-z0-9_.\-@/:]{{0,32}}\)#\s?$"
Also, I noticed stupid EOS behavior. When you configure sessions in some cases the command
sh session-config diffs
won't show diff until you are at the top session.
test_eos(config-s-sess-2)#qos profile CORE-EGRESS-QUEUING
test_eos(config-s-sess-2-qos-profile-CORE-EGRESS-QUEUING)#qos trust dscp
test_eos(config-s-sess-2-qos-profile-CORE-EGRESS-QUEUING)#qos dscp 24
test_eos(config-s-sess-2-qos-profile-CORE-EGRESS-QUEUING)#tx-queue 5
test_eos(config-s-sess-2-qos-profile-CORE-EGRESS-QUEUING-txq-5)#bandwidth guaranteed percent 90
test_eos(config-s-sess-2-qos-profile-CORE-EGRESS-QUEUING-txq-5)#tx-queue 6
test_eos(config-s-sess-2-qos-profile-CORE-EGRESS-QUEUING-txq-6)# bandwidth guaranteed 100000
test_eos(config-s-sess-2-qos-profile-CORE-EGRESS-QUEUING-txq-6)#sh session-config diffs
test_eos(config-s-sess-2-qos-profile-CORE-EGRESS-QUEUING-txq-6)#ex
test_eos(config-s-sess-2-qos-profile-CORE-EGRESS-QUEUING)#sh session-config diffs
test_eos(config-s-sess-2-qos-profile-CORE-EGRESS-QUEUING)#ex
test_eos(config-s-sess-2)#sh session-config diffs
--- system:/running-config
+++ session:/sess-2349--957367488-0-session-config
@@ -27,6 +27,16 @@
!
ntp server vrf networkmanagement 10.144.2.253
ntp server vrf networkmanagement 10.144.2.254
+!
+qos profile CORE-EGRESS-QUEUING
+ qos trust dscp
+ qos dscp 24
+ !
+ tx-queue 5
+ bandwidth guaranteed percent 90
+ !
+ tx-queue 6
+ bandwidth guaranteed 100000
!
This is why diff will be empty. Unfortunately in EOS, there is no analog of the IOS XR root command, which would be useful here.
I made a workaround in my code by sending some exit commands until the current prompt equals to so-called target one:
In [489]: conn = AsyncScrapli(**device)
...: conn.privilege_levels["configuration"].pattern = r"^[\w.\-@()/: ]{1,63}\(config[\w.\-@/:]{0,63}\)#\s?$"
...: await conn.open()
...: cfg_conn = AsyncScrapliCfg(conn=conn)
...: await cfg_conn.prepare()
...: loaded_cfg = await cfg_conn.load_config(qos_conf)
...: session_name = cfg_conn.config_session_name
...: sess_prompt = re.escape(session_name[:6])
...: conn.privilege_levels[session_name].pattern = rf"^[a-z0-9.\-@()/: ]{{1,63}}\(config\-s\-{sess_prompt}[a-z0-9_.\-@/:]{{0,63}}\)#\s?$"
...: target_sessions_prompt = conn.host + f"(config-s-{sess_prompt})#"
...: for attempt in range(2):
...: print(await conn.channel.get_prompt(), "<<<<<"*50)
...: if conn.channel.get_prompt() != target_sessions_prompt:
...: conn.transport.write(b"exit\n")
...: diff = await cfg_conn.diff_config()
...: await cfg_conn.abort_config()
It works somehow but maybe you will invent more elegant solution =)
It looks like that regex in EOSDriverBase should be changed also ({0,32} -> {0,63}):
good catch, will get that updated too!
This is why diff will be empty. Unfortunately in EOS, there is no analog of the IOS XR root command, which would be useful here.
ahhh... I see what you mean. I looked quickly and there doesnt seem to be a "exit to root" (or something similar) option, but I am no eos expert so maybe that exists?
we could for sure make it work, but I wonder if its worth the effort? could you just include exit
exit
(or however many are needed) in the config you load? is that an option? not ideal for sure but seems like the simplest way to deal.
anyway, if you were interested in adding something like what you've got to scrapli-cfg im open to it, but I probably wont work that up myself.
regarding the prompt stuff, ive just pushed a commit to scrapli repo that has the changes here, you can see that in this commit -- so until the next release you can install from the repo!
I'll go ahead and close this out now but holler if that didn't fix things for some reason!
thanks for the help @MarkRudenko !
I think you are totally right it's much easier to send some additional exits. But yes scraply is a great lib thank you for your effort.
Describe the bug When configuring the following config on arista_eos execution stops:
qos profile CORE-EGRESS-QUEUING qos trust dscp qos dscp 24 tx-queue 5 bandwidth guaranteed percent 90 tx-queue 6 bandwidth guaranteed 100000
To Reproduce Steps to reproduce the behavior:
{'auth_password': 'password', 'auth_strict_key': False, 'auth_username': 'user', 'host': 'eos_switch', 'timeout_socket': 20, 'timeout_transport': 20}
with EOSDriver(**device_sync) as conn: cfg_conn = ScrapliCfg(conn=conn) cfg_conn.prepare() cfg_conn.load_config(config=qos_conf)
What you're connecting to (vendor, platform, version) Arista, arista_eos, 4.21.9M
Anything else relevant Most probably the issue is in regular expression which looks for prompts of config sessions
Expected behavior Succesful configuration.
Stack Trace Copy of your stack trace here, please format it properly using triple back ticks (top left key on US keyboards!)
DEBUG:scrapli.driver:load core transport requested DEBUG:scrapli.driver:core transport 'system' loaded successfully DEBUG:scrapli.driver:generating combined network comms prompt pattern DEBUG:scrapli.driver:setting 'comms_prompt_pattern' value to '(^[\w.-@()/: ]{1,63}>\s?$)|(^[\w.-@()/: ]{1,63}#\s?$)|(^[\w.-@()/: ]{1,63}(config[\w.-@/:]{0,32})#\s?$)' INFO:scrapli.driver:opening connection to 'eos_switch' on port '22' DEBUG:scrapli.transport:opening transport connection to 'eos_switch' on port '22' DEBUG:scrapli.transport:created transport 'open_cmd': '['ssh', 'eos_switch', '-p', '22', '-o', 'ConnectTimeout=20', '-o', 'ServerAliveInterval=20', '-l', 'user', '-o', 'StrictHostKeyChecking=no', '-o', 'UserKnownHostsFile=/dev/null', '-F', '/dev/null']' DEBUG:scrapli.transport:transport connection to 'eos_switch' on port '22' opened successfully DEBUG:scrapli.channel:attempting in channel ssh authentication DEBUG:scrapli.channel:read: b"Warning: Permanently added 'eos_switch' (ED25519) to the list of known hosts.\n" DEBUG:scrapli.channel:read: b'' DEBUG:scrapli.channel:read: b"user@eos_switch's password: " DEBUG:scrapli.channel:write: REDACTED DEBUG:scrapli.channel:write: '\n' DEBUG:scrapli.channel:read: b'\n' DEBUG:scrapli.channel:read: b'Last login: Fri Sep 8 07:07:37 2023 from 10.254.241.33\n' DEBUG:scrapli.channel:read: b'\x1b[5n' DEBUG:scrapli.channel:read: b'eos_switch#' DEBUG:scrapli.channel:write: '\n' DEBUG:scrapli.channel:read: b'\n' DEBUG:scrapli.channel:read: b'eos_switch#' INFO:scrapli.driver:attempting to acquire 'privilege_exec' privilege level DEBUG:scrapli.driver:determined current privilege level is one of '['privilege_exec']' DEBUG:scrapli.driver:determined current privilege level is target privilege level, no action needed INFO:scrapli.channel:sending channel input: terminal length 0; strip_prompt: True; eager: False DEBUG:scrapli.channel:write: 'terminal length 0' DEBUG:scrapli.channel:read: b'terminal length 0' DEBUG:scrapli.channel:write: '\n' DEBUG:scrapli.channel:read: b'\n' DEBUG:scrapli.channel:read: b'Pagination disabled.\n' DEBUG:scrapli.channel:read: b'eos_switch#' INFO:scrapli.channel:sending channel input: terminal width 32767; strip_prompt: True; eager: False DEBUG:scrapli.channel:write: 'terminal width 32767' DEBUG:scrapli.channel:read: b'terminal width 32767' DEBUG:scrapli.channel:write: '\n' DEBUG:scrapli.channel:read: b'\n' DEBUG:scrapli.channel:read: b'Width set to 32767 columns.\n' DEBUG:scrapli.channel:read: b'eos_switch#' INFO:scrapli.driver:connection to 'eos_switch' on port '22' opened successfully DEBUG:scrapli_cfg:ScrapliCfg factory initialized INFO:scrapli_cfg.platform:preparing scrapli_cfg connection DEBUG:scrapli_cfg.platform:ignore_version is False, fetching device version INFO:scrapli_cfg.platform:get_version requested INFO:scrapli.channel:sending channel input: show version | i Software image version; strip_prompt: True; eager: False DEBUG:scrapli.channel:write: 'show version | i Software image version' DEBUG:scrapli.channel:read: b'show version | i Software image version' DEBUG:scrapli.channel:write: '\n' DEBUG:scrapli.channel:read: b'\n' DEBUG:scrapli.channel:read: b'Software image version: 4.21.9M\n' DEBUG:scrapli.channel:read: b'eos_switch#' INFO:scrapli_cfg.platform:load_config requested DEBUG:scrapli_cfg.platform:configuration session name will be 'scrapli_cfg_1694157649' DEBUG:scrapli.driver:generating combined network comms prompt pattern DEBUG:scrapli.driver:setting 'comms_promptpattern' value to '(^[\w.-@()/: ]{1,63}>\s?$)|(^[\w.-@()/: ]{1,63}#\s?$)|(^[\w.-@()/: ]{1,63}(config[\w.-@/:]{0,32})#\s?$)|(^[a-z0-9.-@()/: ]{1,63}(config-s-scrapl[a-z0-9.-@/:]{0,32})#\s?$)' DEBUG:scrapli.channel:write: '\n' DEBUG:scrapli.channel:read: b'\neos_switch#' INFO:scrapli.driver:attempting to acquire 'scrapli_cfg_1694157649' privilege level DEBUG:scrapli.driver:determined current privilege level is one of '['privilege_exec']' DEBUG:scrapli.driver:determined privilege escalation necessary INFO:scrapli.channel:sending channel input: configure session scrapli_cfg_1694157649; strip_prompt: True; eager: False DEBUG:scrapli.channel:write: 'configure session scrapli_cfg_1694157649' DEBUG:scrapli.channel:read: b'configure session' DEBUG:scrapli.channel:read: b' scrapli_c' DEBUG:scrapli.channel:read: b'fg_1694157649' DEBUG:scrapli.channel:write: '\n' DEBUG:scrapli.channel:read: b'\n' DEBUG:scrapli.channel:read: b'eos_switch(config-s-scrapl)#' DEBUG:scrapli.channel:write: '\n' DEBUG:scrapli.channel:read: b'\neos_switch(config-s-scrapl)#' INFO:scrapli.driver:attempting to acquire 'scrapli_cfg_1694157649' privilege level DEBUG:scrapli.driver:determined current privilege level is one of '['scrapli_cfg_1694157649']' DEBUG:scrapli.driver:determined current privilege level is target privilege level, no action needed INFO:scrapli.channel:sending channel input: qos profile CORE-EGRESS-QUEUING; strip_prompt: True; eager: False DEBUG:scrapli.channel:write: 'qos profile CORE-EGRESS-QUEUING' DEBUG:scrapli.channel:read: b'qos profile CORE-EGRESS-QUEUING' DEBUG:scrapli.channel:write: '\n' DEBUG:scrapli.channel:read: b'\n' DEBUG:scrapli.channel:read: b'eos_switch(config-s-scrapl-qos-profile-CORE-EGRESS-QUEUING)#' INFO:scrapli.channel:sending channel input: qos trust dscp; strip_prompt: True; eager: False DEBUG:scrapli.channel:write: 'qos trust dscp' DEBUG:scrapli.channel:read: b'qos trust dscp' DEBUG:scrapli.channel:write: '\n' DEBUG:scrapli.channel:read: b'\n' DEBUG:scrapli.channel:read: b'eos_switch(config-s-scrapl-qos-profile-CORE-EGRESS-QUEUING)#' INFO:scrapli.channel:sending channel input: qos dscp 24; strip_prompt: True; eager: False DEBUG:scrapli.channel:write: 'qos dscp 24' DEBUG:scrapli.channel:read: b'qos dscp 24' DEBUG:scrapli.channel:write: '\n' DEBUG:scrapli.channel:read: b'\neos_switch(config-s-scrapl-qos-profile-CORE-EGRESS-QUEUING)#' INFO:scrapli.channel:sending channel input: tx-queue 5; strip_prompt: True; eager: False DEBUG:scrapli.channel:write: 'tx-queue 5' DEBUG:scrapli.channel:read: b'tx-queue 5' DEBUG:scrapli.channel:write: '\n' DEBUG:scrapli.channel:read: b'\n' DEBUG:scrapli.channel:read: b'eos_switch(config-s-scrapl-qos-profile-CORE-EGRESS-QUEUING-txq-5)#' CRITICAL:scrapli.transport:operation timed out, closing connection DEBUG:scrapli.transport:closing transport connection to 'eos_switch' on port '22' CRITICAL:scrapli.transport:encountered EOF reading from transport; typically means the device closed the connection DEBUG:scrapli.transport:transport connection to 'eos_switch' on port '22' closed successfully INFO:scrapli.driver:closing connection to 'eos_switch' on port '22' DEBUG:scrapli.channel:write: '\n'
ScrapliTimeout Traceback (most recent call last)