Statistics
| Branch: | Tag: | Revision:

root / ncclient / ssh.py @ 589b23e4

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._init()
66

    
67
    def _close(self):
68
        self._channel.close()
69
        Session._close(self)
70
    
71
    def run(self):
72
        
73
        chan = self._channel
74
        chan.setblocking(0)
75
        q = self._q
76
        
77
        while True:
78
            
79
            if chan.closed:
80
                break
81
            
82
            if chan.recv_ready():
83
                data = chan.recv(SSHSession.BUF_SIZE)
84
                if data:
85
                    self._in_buf += data
86
                    while True:
87
                        before, delim, after = self._in_buf.partition(SSHSession.MSG_DELIM)
88
                        if delim:
89
                            self.dispatch('reply', before)
90
                            self._in_buf = after
91
                        else:
92
                            break
93
                else:
94
                    break
95
            
96
            if chan.send_ready():
97
                if not q.empty():
98
                    msg = q.get()
99
                    self._out_buf += ( msg + SSHSession.MSG_DELIM )
100
                    while self._out_buf:
101
                        n = chan.send(self._out_buf)
102
                        if n <= 0:
103
                            break
104
                        self._out_buf = self._out_buf[n:]
105
        
106
        logger.debug('** broke out of main loop **')
107
        self.dispatch('close', SessionCloseError(self._in_buf, self._out_buf))
108

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