Revision 41e2ed46

b/ncclient/glue.py
46 46
        self._listeners = set() # TODO(?) weakref
47 47
        self._lock = Lock()
48 48
    
49
    def _dispatch_received(self, raw):
49
    def _dispatch_message(self, raw):
50 50
        "TODO: docstring"
51 51
        root = parse_root(raw)
52 52
        with self._lock:
53 53
            listeners = list(self._listeners)
54 54
        for l in listeners:
55
            logger.debug('[dispatching] message to %s' % l)
56
            l.callback(root, raw)
55
            logger.debug('dispatching message to %r' % l)
56
            try:
57
                l.callback(root, raw)
58
            except Exception as e:
59
                logger.warning('[error] %r' % e)
57 60
    
58 61
    def _dispatch_error(self, err):
59 62
        "TODO: docstring"
60 63
        with self._lock:
61 64
            listeners = list(self._listeners)
62 65
        for l in listeners:
63
            logger.debug('[dispatching] error to %s' % l)
64
            l.errback(err)
66
            logger.debug('dispatching error to %r' % l)
67
            try:
68
                l.errback(err)
69
            except Exception as e:
70
                logger.warning('error %r' % e)
65 71
    
66 72
    def add_listener(self, listener):
67 73
        "TODO: docstring"
68
        logger.debug('[installing listener] %r' % listener)
74
        logger.debug('installing listener %r' % listener)
69 75
        with self._lock:
70 76
            self._listeners.add(listener)
71 77
    
72 78
    def remove_listener(self, listener):
73 79
        "TODO: docstring"
74
        logger.debug('[discarding listener] %r' % listener)
80
        logger.debug('discarding listener %r' % listener)
75 81
        with self._lock:
76 82
            self._listeners.discard(listener)
77 83
    
......
86 92
    
87 93
    def send(self, message):
88 94
        "TODO: docstring"
89
        logger.debug('[queueing] %s' % message)
95
        logger.debug('queueing %s' % message)
90 96
        self._q.put(message)
91 97

  
92 98

  
b/ncclient/operations/reply.py
17 17
from ncclient.content import multiqualify as _
18 18
from ncclient.content import unqualify as __
19 19

  
20
import logging
21
logger = logging.getLogger('ncclient.operations.reply')
22

  
20 23
class RPCReply:
21 24
    
22 25
    def __init__(self, raw):
23
        self._raw = None
26
        self._raw = raw
24 27
        self._parsed = False
25 28
        self._errors = []
26 29
    
......
28 31
        return self._raw
29 32
    
30 33
    def parse(self):
31
        root = ET.fromstring(raw) # <rpc-reply> element
34
        root = ET.fromstring(self._raw) # <rpc-reply> element
32 35
        
33 36
        # per rfc 4741 an <ok/> tag is sent when there are no errors or warnings
34 37
        oktags = _('ok')
35 38
        for oktag in oktags:
36 39
            if root.find(oktag) is not None:
40
                logger.debug('found %s' % oktag)
41
                self._parsed = True
37 42
                return
38 43
        
39 44
        # create RPCError objects from <rpc-error> elements
......
46 51
                self._errors.append(RPCError(d))
47 52
            if self._errors:
48 53
                break
54
        self._parsed = True
49 55
    
50 56
    @property
51 57
    def raw(self):
......
53 59
    
54 60
    @property
55 61
    def ok(self):
56
        if not self._parsed:
57
            self.parse()
58
        return bool(self._errors) # empty list = false
62
        if not self._parsed: self.parse()
63
        return not bool(self._errors) # empty list = false
59 64
    
60 65
    @property
61 66
    def errors(self):
62 67
        'List of RPCError objects. Will be empty if no <rpc-error> elements in reply.'
63
        if not self._parsed:
64
            self.parse()
68
        if not self._parsed: self.parse()
65 69
        return self._errors
66 70

  
67 71

  
b/ncclient/operations/rpc.py
46 46
        req = self._build(op)
47 47
        self._session.send(req)
48 48
        if self._async:
49
            return self._reply_event
50
        else:
49 51
            self._reply_event.wait()
50 52
            self._reply.parse()
51 53
            return self._reply
52 54
    
53
    def deliver(self, raw):
55
    def _set_reply(self, raw):
54 56
        self._reply = RPCReply(raw)
57
    
58
    def _set_reply_event(self):
55 59
        self._reply_event.set()
56 60
    
61
    def _delivery_hook(self):
62
        'For subclasses'
63
        pass
64
    
65
    def deliver(self, raw):
66
        self._set_reply(raw)
67
        self._delivery_hook()
68
        self._set_reply_event()
69
    
57 70
    @property
58 71
    def has_reply(self):
59 72
        return self._reply_event.isSet()
......
63 76
        return self._reply
64 77
    
65 78
    @property
79
    def is_async(self):
80
        return self._async
81
    
82
    @property
66 83
    def id(self):
67 84
        return self._id
68 85
    
......
113 130
    def set_errback(self, errback):
114 131
        self._errback = errback
115 132

  
116
    def register(self, msgid, rpc):
117
        self._id2rpc[msgid] = rpc
133
    def register(self, id, rpc):
134
        self._id2rpc[id] = rpc
118 135
    
119 136
    def callback(self, root, raw):
120 137
        tag, attrs = root
......
126 143
                try:
127 144
                    rpc = self._id2rpc[id]
128 145
                    rpc.deliver(raw)
129
                except:
130
                    logger.warning('RPCReplyListener.callback: no RPC '
146
                except KeyError:
147
                    logger.warning('[RPCReplyListener.callback] no RPC '
131 148
                                   + 'registered for message-id: [%s]' % id)
149
                    logger.debug('[RPCReplyListener.callback] registered: %r '
150
                                 % dict(self._id2rpc))
151
                except Exception as e:
152
                    logger.debug('[RPCReplyListener.callback] error - %r' % e)
132 153
                break
133 154
        else:
134 155
            logger.warning('<rpc-reply> without message-id received: %s' % raw)
135 156
    
136 157
    def errback(self, err):
137
        logger.error('RPCReplyListener.errback: %r' % err)
138 158
        if self._errback is not None:
139 159
            self._errback(err)
b/ncclient/operations/session.py
16 16

  
17 17
from rpc import RPC
18 18

  
19

  
20 19
class CloseSession(RPC):
21 20
    
21
    'CloseSession is always synchronous'
22
    
22 23
    def __init__(self, *args, **kwds):
23 24
        RPC.__init__(self, *args, **kwds)
24 25
        self.spec = { 'tag': 'close-session' }
25 26
    
26
    def deliver(self, reply):
27
        RPC.deliver(self, reply)
28
        # can't be too huge, should be ok to parse in callback
29
        if self._reply.ok: # (implicitly parse)
30
            self._session.expect_close()
31
        self._session.close()
27
    def _delivery_hook(self):
28
        if self.reply.ok:
29
            self.session.expect_close()
32 30
    
33 31
    def request(self):
34
        self._request(self.spec)
32
        return self._request(self.spec)
35 33

  
36 34

  
37 35
class KillSession(RPC):
......
47 45
        if not isinstance(session_id, basestring): # just make sure...
48 46
            session_id = str(session_id)
49 47
        self.spec['children'][0]['text'] = session_id
50
        self._request(self.spec)
48
        return self._request(self.spec)
b/ncclient/transport/__init__.py
14 14

  
15 15
"TODO: docstring"
16 16

  
17
import logging
18
logger = logging.getLogger('ncclient.transport')
17
from ssh import SSHSession
18

  
19
__all__ = ['SSHSession']
b/ncclient/transport/hello.py
24 24
class HelloHandler(Listener):
25 25
    
26 26
    def __init__(self, init_cb, error_cb):
27
        self._init_cb, self._error_cb = init_cb, error_cb
27
        self._init_cb = init_cb
28
        self._error_cb = error_cb
28 29
    
29 30
    def __str__(self):
30 31
        return 'HelloListener'
b/ncclient/transport/session.py
17 17
from ncclient.capabilities import Capabilities, CAPABILITIES
18 18
from ncclient.glue import Subject
19 19

  
20
from . import logger
21 20
from hello import HelloHandler
22 21

  
22
import logging
23
logger = logging.getLogger('ncclient.transport.session')
24

  
23 25
class Session(Subject):
24 26
    
25 27
    "TODO: docstring"
26 28
    
27 29
    def __init__(self):
28
        "TODO: docstring"
30
        "Subclass constructor should call this"
29 31
        Subject.__init__(self)
30 32
        self.setName('session')
31
        self.setDaemon(True) #hmm
32 33
        self._client_capabilities = CAPABILITIES
33 34
        self._server_capabilities = None # yet
34 35
        self._id = None # session-id
35 36
        self._connected = False # to be set/cleared by subclass implementation
36
        logger.debug('[session object created] client_capabilities=%r' %
37
                     self._client_capabilities)
37
        logger.debug('%r created: client_capabilities=%r' %
38
                     (self, self._client_capabilities))
38 39
    
39 40
    def _post_connect(self):
40
        "TODO: docstring"
41
        "Greeting stuff"
41 42
        init_event = Event()
42 43
        error = [None] # so that err_cb can bind error[0]. just how it is.
43 44
        # callbacks
......
51 52
        listener = HelloHandler(ok_cb, err_cb)
52 53
        self.add_listener(listener)
53 54
        self.send(HelloHandler.build(self._client_capabilities))
54
        logger.debug('[starting main loop]')
55
        logger.debug('starting main loop')
55 56
        self.start()
56 57
        # we expect server's hello message
57 58
        init_event.wait()
......
63 64
                     (self._id, self._server_capabilities))
64 65
    
65 66
    def connect(self, *args, **kwds):
66
        "TODO: docstring"
67
        "Subclass implements"
67 68
        raise NotImplementedError
68 69

  
69 70
    def run(self):
71
        "Subclass implements"
70 72
        raise NotImplementedError
71 73
    
72 74
    ### Properties
b/ncclient/transport/ssh.py
20 20

  
21 21
import paramiko
22 22

  
23
from . import logger
24 23
from errors import AuthenticationError, SessionCloseError, SSHError, SSHUnknownHostError
25 24
from session import Session
26 25

  
26
import logging
27
logger = logging.getLogger('ncclient.transport.ssh')
28

  
27 29
BUF_SIZE = 4096
28 30
MSG_DELIM = ']]>]]>'
29 31
TICK = 0.1
......
42 44
        # parsing-related, see _parse()
43 45
        self._parsing_state = 0 
44 46
        self._parsing_pos = 0
45
        logger.debug('[SSHSession object created]')
46 47
    
47 48
    def _parse(self):
48 49
        '''Messages ae delimited by MSG_DELIM. The buffer could have grown by a
......
76 77
            else: # if we didn't break out of the loop, full delim was parsed
77 78
                msg_till = buf.tell() - n
78 79
                buf.seek(0)
79
                self._dispatch_received(buf.read(msg_till).strip())
80
                logger.debug('parsed new message')
81
                self._dispatch_message(buf.read(msg_till).strip())
80 82
                buf.seek(n+1, os.SEEK_CUR)
81 83
                rest = buf.read()
82 84
                buf = StringIO()
......
170 172
        self._connected = True # there was no error authenticating
171 173
        
172 174
        c = self._channel = self._transport.open_session()
173
        c.invoke_subsystem('netconf')
174 175
        c.set_name('netconf')
176
        c.invoke_subsystem('netconf')
175 177
        
176 178
        self._post_connect()
177 179
    
......
264 266
                    else:
265 267
                        raise SessionCloseError(self._buffer.getvalue())
266 268
                if not q.empty() and chan.send_ready():
269
                    logger.debug('sending message')
267 270
                    data = q.get() + MSG_DELIM
268 271
                    while data:
269 272
                        n = chan.send(data)
......
271 274
                            raise SessionCloseError(self._buffer.getvalue(), data)
272 275
                        data = data[n:]
273 276
        except Exception as e:
274
            logger.debug('*** broke out of main loop ***')
277
            logger.debug('broke out of main loop')
275 278
            self.close()
276 279
            if not (isinstance(e, SessionCloseError) and self._expecting_close):
277 280
                self._dispatch_error(e)
/dev/null
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
from ncclient.glue import Listener
16

  
17
import logging
18
logger = logging.getLogger('DebugListener')
19

  
20
class DebugListener(Listener):
21
    
22
    def __str__(self):
23
        return 'DebugListener'
24
    
25
    def received(self, raw):
26
        logger.debug('[received]:||%s||' % raw)
27
    
28
    def errback(self, err):
29
        logger.debug('[error]:%r' % err)
b/ncclient/util.py
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
from ncclient.glue import Listener
16

  
17
import logging
18
logger = logging.getLogger('PrintListener')
19

  
20
class PrintListener(Listener):
21
    
22
    def callback(self, root, raw):
23
        tag, attrs = root
24
        print '\n$ RECEIVED MESSAGE with root=[tag=%r, attrs=%r]:\n%r\n' % (tag, attrs, raw)
25
    
26
    def errback(self, err):
27
        print '\n$ RECEIVED ERROR:\n%r\n' % err

Also available in: Unified diff