Statistics
| Branch: | Tag: | Revision:

root / src / ssh.py @ fd40449b

History | View | Annotate | Download (3.7 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 select import select as select
19

    
20
from session import Session, SessionError
21

    
22
logger = logging.getLogger('ncclient.ssh')
23

    
24
class SSHError(SessionError): pass
25

    
26
class SSHSession(Session):
27
    
28
    BUF_SIZE = 4096
29
    
30
    MSG_DELIM = ']]>>]]>'
31
    
32
    def __init__(self, capabilities, reply_cb=None,
33
                 load_known_hosts=True,
34
                 missing_host_key_policy=paramiko.RejectPolicy):
35
        Session.__init__(self, capabilities)
36
        self._inBuf = ''
37
        self._outBuf = ''
38
        self._client = SSHClient()
39
        if load_known_hosts:
40
            self._client.load_system_host_keys()
41
        self._client.set_missing_host_key_policy(host_key_policy)
42
        
43
    def _greet_cb(self, reply):
44
        self._init(reply)
45
        self._cb = self._real_cb
46
        
47
    def _greet(self):
48
        self._real_cb = self._cb
49
        self._cb = self._greet_cb
50
        self._q.add(self._make_hello())
51
        
52
    def load_host_keys(self, filename):
53
        self._client.load_host_keys(filename)
54
        
55
    def set_missing_host_key_policy(self, policy):
56
        self._client.set_missing_host_key_policy(policy)
57
        
58
    def set_reply_callback(self, cb):
59
        self._cb = cb
60
    
61
    def connect(self, hostname, port=830, username=None, password=None,
62
                key_filename=None, timeout=None, allow_agent=True,
63
                look_for_keys=True):
64
        self._client.connect(hostname, port=port, username=username,
65
                             password=password, key_filename=key_filename,
66
                             timeout=timeout, allow_agent=allow_agent,
67
                             look_for_keys=look_for_keys)
68
        transport = self._client.get_transport()
69
        self._channel = transport.open_session()
70
        self._channel.invoke_subsystem('netconf')
71
        self._greet()
72
        Session.connect(self) # starts thread
73
    
74
    def run(self):
75
        sock = self._channel
76
        sock.setblocking(0)
77
        q = self._q
78
        while True:
79
            (r, w, e) = select([sock], [sock], [], 60)
80
            if w:
81
                if not q.empty():
82
                   self._outBuffer += ( q.get() + MSG_DELIM )
83
                if self._outBuffer:
84
                    n = sock.send(self._outBuffer)
85
                    self._outBuffer = self._outBuffer[n:]
86
            if r:
87
                data = sock.recv(BUF_SIZE)
88
                if data:
89
                    self._inBuf += data
90
                    # probably not very efficient:
91
                    pos = self._inBuf.find(DELIM)
92
                    if pos != -1:
93
                        msg = self._inBuf[:pos]
94
                        self._inBuf = self._inBuf[(pos + len(DELIM)):]
95
                        self._reply_cb(msg)
96
                else:
97
                    connected = False
98
                    # it's not an error if we asked for it
99
                    # via CloseSession -- need a way to know this
100
                    raise SessionError
101
                    
102
class CallbackPolicy(paramiko.MissingHostKeyPolicy):
103
    
104
    def __init__(self, cb):
105
        self._cb = cb
106
    
107
    def missing_host_key(self, client, hostname, key):
108
        if not self._cb(hostname, key):
109
            raise SSHError