Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement SSH keepalives, default 30-second interval, for NETCONF over SSH sessions. #668

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
18 changes: 18 additions & 0 deletions lib/jnpr/junos/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

# 3rd-party packages
from lxml import etree
import ncclient
from ncclient import manager as netconf_ssh
import ncclient.transport.errors as NcErrors
from ncclient.transport.session import SessionListener
Expand Down Expand Up @@ -1189,6 +1190,16 @@ def __init__(self, *vargs, **kvargs):
This can be used to load SSH information from a configuration file.
By default ~/.ssh/config is queried.

:param int ssh_keepalives:
*OPTIONAL* The interval, in seconds, at which to send SSH
keepalives for the NETCONF over SSH session. Without SSH
keepalives, a NAT or stateful firewall along the network
path between the PyEZ host and the target Junos device,
may timeout an inactive TCP flow and cause the NETCONF over SSH
session to hang. Sending SSH keepalives avoids this situation. The
default value is 30 seconds. Setting this parameter to a value of 0
disables SSH keepalives.

:param bool normalize:
*OPTIONAL* default is ``False``. If ``True`` then the
XML returned by :meth:`execute` will have whitespace normalized
Expand Down Expand Up @@ -1233,6 +1244,7 @@ def __init__(self, *vargs, **kvargs):
self._hostname = "localhost"
self._ssh_private_key_file = None
self._ssh_config = None
self._ssh_keepalives = None
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Setting this to None does not make sense. This value is initialized to zero in the underlying module.

Help on method set_keepalive in module paramiko.transport:

set_keepalive(self, interval) method of paramiko.transport.Transport instance
Turn on/off keepalive packets (default is off). If this is set, after
interval seconds without sending any data over the connection, a
"keepalive" packet will be sent (and ignored by the remote host). This
can be useful to keep connections alive over a NAT, for example.

:param int interval:
    seconds to wait before sending a keepalive packet (or
    0 to disable keepalives).  

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None is set for on-box python, where it won't use ssh connection. So this should be OK

else:
# --------------------------
# making a remote connection
Expand All @@ -1248,6 +1260,8 @@ def __init__(self, *vargs, **kvargs):
self._conf_ssh_private_key_file = None
# user can get updated by ssh_config
self._ssh_config = kvargs.get("ssh_config")
self._ssh_keepalives = kvargs.get("ssh_keepalives", 30)

self._sshconf_lkup()
# but if user or private key is explicit from call, then use it.
self._auth_user = (
Expand Down Expand Up @@ -1361,6 +1375,10 @@ def open(self, *vargs, **kvargs):
},
)
self._conn._session.add_listener(DeviceSessionListener(self))
if isinstance(self._conn, ncclient.manager.Manager) and isinstance(
self._conn._session, ncclient.transport.ssh.SSHSession
):
self._conn._session.transport.set_keepalive(int(self._ssh_keepalives))
except NcErrors.AuthenticationError as err:
# bad authentication credentials
raise EzErrors.ConnectAuthError(self)
Expand Down