Closed OliElli closed 2 years ago
Was testing this use case of sending literal \n
over SSH to Juniper devices, tried netmiko, scrapli and napalm plugins against vSRX I have in my lab - none of them worked, all of them threat \n
as a new line.
Also tried to send config with literal \n using netmiko directly using this script:
from netmiko import ConnectHandler
device = {
"device_type": "juniper",
"host": "192.168.1.220",
"username": "nornir",
"password": "nornir123",
}
commands = ['set system login message "test\nbanner\nstring\n"']
with ConnectHandler(**device) as net_connect:
print(net_connect.find_prompt())
output = net_connect.send_config_set(commands)
print(output)
it did not work either returning timeout exception:
[root@salt-minion-nrp2 ~]# python3 jun_test.py
nornir@vSRX-1>
Traceback (most recent call last):
File "/root/jun_test.py", line 13, in <module>
output = net_connect.send_config_set(commands)
File "/usr/local/lib/python3.9/site-packages/netmiko/base_connection.py", line 2170, in send_config_set
output += self.read_until_pattern(pattern=re.escape(cmd.strip()))
File "/usr/local/lib/python3.9/site-packages/netmiko/base_connection.py", line 651, in read_until_pattern
raise ReadTimeout(msg)
netmiko.exceptions.ReadTimeout:
Pattern not detected: 'set\\ system\\ login\\ message\\ "test\\\nbanner\\\nstring\\\n"' in output.
Things you might try to fix this:
1. Adjust the regex pattern to better identify the terminating string. Note, in
many situations the pattern is automatically based on the network device's prompt.
2. Increase the read_timeout to a larger value.
You can also look at the Netmiko session_log or debug log for more information.
What worked for me is using nr.cli with netmiko use_ps function, use_ps is a function that intorduces promptless mode support for netmiko and capable of sending multiline strings over ssh, here is a file with config on salt master:
[root@salt-master pytest]# cat /etc/salt/templates/juniper_jinja_multiline_test.j2
configure
set system login message "test\nbanner\nstring\n"
set system host-name {{ host.name }}
commit
exit
running above template using this command produces desired results:
[root@salt-master pytest]# salt nrp2 nr.cli salt://templates/juniper_jinja_multiline_test.j2 FB=vSRX-1 plugin=netmiko use_ps=True
nrp2:
----------
vSRX-1:
----------
configure:
configure
Entering configuration mode
[edit]
[edit]
nornir@vSRX-1# set system login message "test\nbanner\nstring\n"
[edit]
nornir@vSRX-1# set system host-name vSRX-1
[edit]
nornir@vSRX-1# commit
commit complete
[edit]
nornir@vSRX-1# exit
Exiting configuration mode
[root@salt-master pytest]#
Another workaround that I found is to use NETCONF to configure junos devices, e.g. this is RPC content:
[root@salt-master pytest]# cat /etc/salt/rpc/edit_config_junos_multline_banner.xml
<config>
<configuration>
<system>
<login>
<message>test\nbanner\nstring\nnew</message>
</login>
</system>
</configuration>
</config>
running this command produces desired results as well:
[root@salt-master pytest]# salt nrp2 nr.nc edit_config config="salt://rpc/edit_config_junos_multline_banner.xml" FC=SRX
nrp2:
----------
vSRX-1:
----------
edit_config:
<rpc-reply message-id="urn:uuid:a645d4f4-7062-4cb0-993e-d692a9484aca">
<ok/>
</rpc-reply>
[root@salt-master pytest]# salt nrp2 nr.cli "show configuration system login message | display xml" FC=SRX
nrp2:
----------
vSRX-1:
----------
show configuration system login message | display xml:
<rpc-reply xmlns:junos="http://xml.juniper.net/junos/22.1R0/junos">
<configuration junos:commit-seconds="1660518139" junos:commit-localtime="2022-08-14 19:02:19 EDT" junos:commit-user="nornir">
<system>
<login>
<message>test\nbanner\nstring\n</message>
</login>
</system>
</configuration>
<cli>
<banner></banner>
</cli>
</rpc-reply>
[root@salt-master pytest]#
So, all in all tested 5 methods to send configuration to device with literal newline, 2 of them worked so far.
Have you been able to apply config like 'set system login message "test\nbanner\nstring\n"'
to Junos over SSH CLI by using any other methods?
Regarding "I suspect some point in the salt -> nornir rendering pipeline the escapes are nullified." - this only seems to be true for cases when \n is given within inline command argument, referencing file content instead, does work fine.
I.e. this does not work as expected:
salt nornirproxy nr.cfg_gen test\nstring\n
while this works fine:
salt nornirproxy nr.cfg_gen salt://configs/test.cfg
where salt://configs/test.cfg content is:
test\nstring\n
Ok, was able to fix the behaviour, now this command
salt nrp2 nr.cfg 'set system login message "test\n\string\n1234"' FM='*jun*' plugin=netmiko
works as expected, will include fix in next release.
Should be addressed in 0.15.0 release
Confirmed fixed in 0.15.0, thanks @dmulyalin !!
I am trying to render configuration to junos that contains literal newlines (used internally by Junos) but they are rendered as newlines no matter how I try to escape them.
Example of what I want to render to the switch:
I have been testing using nr.cfg_gen like this:
Escaping the newline renders the same way as above, ie
'{{ "test\\nstring\\n" }}'
Escaping the escape renders an escaped backslash and a newline:
I suspect some point in the salt -> nornir rendering pipeline the escapes are nullified.