forked from achinnac/nanog66-dev
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathssh_helper.py
91 lines (75 loc) · 3.18 KB
/
ssh_helper.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#!/usr/local/bin/python3
# Copyright 2015-present, Facebook, Inc.
# All rights reserved.
#
# This source code is licensed under the license found in the
# LICENSE-examples file in the root directory of this source tree.
""" SSH Connection Handler for Network Devices
This module supports SSH-based communication natively from
Python using the Paramiko module. Interactive prompts and IPv6
are both supported here.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from __future__ import unicode_literals
import re
import time
# Third-party
import paramiko
class SSHSession(object):
""" Opens an SSH session to the device and returns a connection object. """
def __init__(self, device, username, passwd, debug=False):
self.device = device
self.username = username
self.passwd = passwd
self.debug = debug
self._connect()
def _connect(self):
""" Performs the initial SSH connection setup. This is an internal
method called when an instance of this class is created.
"""
self.ssh_conn = paramiko.SSHClient()
if self.debug:
self.ssh_conn.log = paramiko.common.logging.basicConfig(
level=paramiko.common.DEBUG)
# "known_hosts" is ignored, so there's no potential for mismatched keys
self.ssh_conn.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# The default for allow_agent (False) breaks SSH to some devices
self.ssh_conn.connect(self.device, username=self.username,
password=self.passwd, allow_agent=False)
self.ssh_shell = self.ssh_conn.invoke_shell()
self.ssh_shell.set_combine_stderr(True)
self.ssh_shell.setblocking(True)
def write(self, commands, delay=2, read_until='#', timeout=30,
wait_for_output=True):
""" Writes the commands provided and attempts to read the output
until the "read_until" value is found, or until the timeout
(seconds) is reached. The delay parameter is a sleep time
between commands.
"""
self.ssh_shell.settimeout(timeout)
for command in commands:
self.ssh_shell.send('{0}\n'.format(command))
time.sleep(delay)
self.output_buffer = ''
if wait_for_output:
while not re.search(read_until, self.output_buffer):
if self.ssh_shell.recv_ready():
try:
resp = self.ssh_shell.recv(8096)
except socket.timeout:
error = ('Timeout exceeded while attempting to read '
'response after issuing "{0}" to {1}.'.format(
command, self.device))
raise Exception(error)
self.output_buffer += resp
else:
time.sleep(1)
return self.output_buffer
def close(self):
self.ssh_conn.close()
### --- Begin Hacks for Nanog Demo --- ###
import socket
if socket.gethostname() in ['DEVBOX01', 'dswafford-mbp']:
from mock_outputs import SSHSession