Statistics
| Branch: | Tag: | Revision:

root / ncclient / ssh.py @ 35ad9d81

History | View | Annotate | Download (3.9 kB)

1
# Copyright 2009 Shikhar Bhushan
2
#
3
# Licensed under the Apache License, Version 2.0 (the "License");
4
# you may not use this file except in compliance with the License.
5
# You may obtain a copy of the License at
6
#
7
#    http://www.apache.org/licenses/LICENSE-2.0
8
#
9
# Unless required by applicable law or agreed to in writing, software
10
# distributed under the License is distributed on an "AS IS" BASIS,
11
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
# See the License for the specific language governing permissions and
13
# limitations under the License.
14

    
15
import logging
16
import paramiko
17

    
18
from session import Session, SessionError
19

    
20
logger = logging.getLogger('ncclient.ssh')
21

    
22
class SessionCloseError(SessionError):
23
    
24
    def __str__(self):
25
        return 'RECEIVED: %s | UNSENT: %s' % (self._in_buf, self._out_buf)
26
    
27
    def __init__(self, in_buf, out_buf):
28
        SessionError.__init__(self)
29
        self._in_buf, self._out_buf = in_buf, out_buf
30

    
31
class SSHSession(Session):
32

    
33
    BUF_SIZE = 4096
34
    MSG_DELIM = ']]>]]>'
35
    
36
    def __init__(self, load_known_hosts=True,
37
                 missing_host_key_policy=paramiko.RejectPolicy):
38
        Session.__init__(self)
39
        self._in_buf = ''
40
        self._out_buf = ''
41
        self._client = paramiko.SSHClient()
42
        if load_known_hosts:
43
            self._client.load_system_host_keys()
44
        self._client.set_missing_host_key_policy(missing_host_key_policy)
45
    
46
    def load_host_keys(self, filename):
47
        self._client.load_host_keys(filename)
48
    
49
    def set_missing_host_key_policy(self, policy):
50
        self._client.set_missing_host_key_policy(policy)
51
    
52
    # paramiko exceptions ok?
53
    # user might be looking for ClientError
54
    def connect(self, hostname, port=830, username=None, password=None,
55
                key_filename=None, timeout=None, allow_agent=True,
56
                look_for_keys=True):
57
        self._client.connect(hostname, port=port, username=username,
58
                            password=password, key_filename=key_filename,
59
                            timeout=timeout, allow_agent=allow_agent,
60
                            look_for_keys=look_for_keys)    
61
        transport = self._client.get_transport()
62
        self._channel = transport.open_session()
63
        self._channel.invoke_subsystem('netconf')
64
        self._channel.set_name('netconf')
65
        self._connect()
66
    
67
    def run(self):
68
        
69
        chan = self._channel
70
        chan.setblocking(0)
71
        q = self._q
72
        
73
        while True:
74
            
75
            if chan.closed:
76
                break
77
            
78
            if chan.recv_ready():
79
                data = chan.recv(SSHSession.BUF_SIZE)
80
                if data:
81
                    self._in_buf += data
82
                    while True:
83
                        before, delim, after = self._in_buf.partition(SSHSession.MSG_DELIM)
84
                        if delim:
85
                            self.dispatch('reply', before)
86
                            self._in_buf = after
87
                        else:
88
                            break
89
                else:
90
                    break
91
            
92
            if chan.send_ready():
93
                if not q.empty():
94
                    msg = q.get()
95
                    self._out_buf += ( msg + SSHSession.MSG_DELIM )
96
                    while self._out_buf:
97
                        n = chan.send(self._out_buf)
98
                        if n <= 0:
99
                            break
100
                        self._out_buf = self._out_buf[n:]
101
        
102
        logger.debug('** broke out of main loop **')
103
        self.dispatch('close', SessionCloseError(self._in_buf, self._out_buf))
104
    
105
    def _close(self):
106
        self._channel.close()
107
        Session._close(self)
108

    
109

    
110
class MissingHostKeyPolicy(paramiko.MissingHostKeyPolicy):
111
    
112
    def __init__(self, cb):
113
        self._cb = cb
114
    
115
    def missing_host_key(self, client, hostname, key):
116
        if not self._cb(hostname, key):
117
            raise SSHError