Revision 68006767

b/ncclient/transport/__init__.py
12 12
# See the License for the specific language governing permissions and
13 13
# limitations under the License.
14 14

  
15
"TODO: docstring"
16

  
15 17
import logging
16 18
logger = logging.getLogger('ncclient.transport')
b/ncclient/transport/errors.py
27 27
class SSHError(TransportError):
28 28
    pass
29 29

  
30
class SSHAuthenticationError(SSHError):
30
class AuthenticationError(TransportError):
31 31
    pass
32 32

  
33 33
class SSHUnknownHostError(SSHError):
b/ncclient/transport/hello.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
"All to do with NETCONF <hello> messages"
16

  
17
from xml.etree import cElementTree as ET
18

  
19
from ncclient.content import TreeBuilder
20
from ncclient.content import BASE_NS
21
from ncclient.content import qualify as _
22

  
23

  
24
def build(capabilities, encoding='utf-8'):
25
    "Given a list of capability URI's returns encoded <hello> message"
26
    spec = {
27
        'tag': _('hello', BASE_NS),
28
        'children': [{
29
            'tag': 'capabilities',
30
            'children': # this is fun :-)
31
                [{ 'tag': 'capability', 'text': uri} for uri in capabilities]
32
            }]
33
        }
34
    return TreeBuilder(spec).to_string(encoding)
35

  
36
def parse(raw):
37
    "Returns tuple of (session-id, ['capability_uri', ...])"
38
    sid, capabilities = 0, []
39
    root = ET.fromstring(raw)
40
    for child in root.getchildren():
41
        if __(child.tag) == 'session-id':
42
            sid = child.text
43
        elif __(child.tag) == 'capabilities':
44
            for cap in child.getiterator(_('capability', BASE_NS)):
45
                capabilities.append(cap.text)
46
            # cisco doesn't namespace hello message
47
            for cap in child.getiterator('capability'): 
48
                capabilities.append(cap.text)
49
    return sid, capabilities
50

  
51

  
52
class HelloListener(Listener):
53
    
54
    def __init__(self, init_cb, error_cb):
55
        self._init_cb, self._error_cb = init_cb, error_cb
56
    
57
    def __str__(self):
58
        return 'HelloListener'
59
    
60
    def callback(self, root, raw):
61
        if __(root[0]) == 'hello':
62
            try:
63
                id, capabilities = parse(raw)
64
            except Exception as e:
65
                self._error_cb(e)
66
            else:
67
                self._init_cb(id, capabilities)
68
    
69
    def errback(self, err):
70
        self._error_cb(err)
b/ncclient/transport/session.py
12 12
# See the License for the specific language governing permissions and
13 13
# limitations under the License.
14 14

  
15
from threading import Thread, Lock, Event
16
from Queue import Queue
17

  
18
from . import logger
15
from threading import Thread, Event
19 16
from ncclient.capabilities import Capabilities, CAPABILITIES
20 17

  
21

  
22
class Subject:
23

  
24
    def __init__(self):
25
        self._listeners = set([])
26
        self._lock = Lock()
27
        
28
    def has_listener(self, listener):
29
        with self._lock:
30
            return (listener in self._listeners)
31
    
32
    def add_listener(self, listener):
33
        with self._lock:
34
            self._listeners.add(listener)
35
    
36
    def remove_listener(self, listener):
37
        with self._lock:
38
            self._listeners.discard(listener)
39
    
40
    def dispatch(self, event, *args, **kwds):
41
        # holding the lock while doing callbacks could lead to a deadlock
42
        # if one of the above methods is called
43
        with self._lock:
44
            listeners = list(self._listeners)
45
        for l in listeners:
46
            logger.debug('dispatching [%s] to [%s]' % (event, l))
47
            try:
48
                getattr(l, event)(*args, **kwds)
49
            except AttributeError as e:
50
                logger.debug('Subject.dispatch: %r' % e)
51
            except Exception as e:
52
                logger.warning('Subject.dispatch: %r' % e)
53

  
18
import hello
19
from . import logger
20
from ncclient.glue import Subject
54 21

  
55 22
class Session(Thread, Subject):
56 23
    
24
    "TODO: docstring"
25
    
57 26
    def __init__(self):
58
        Thread.__init__(self, name='session')
27
        "TODO: docstring"
59 28
        Subject.__init__(self)
29
        Thread.__init__(self, name='session')
30
        self.setDaemon(True)
60 31
        self._client_capabilities = CAPABILITIES
61 32
        self._server_capabilities = None # yet
62 33
        self._id = None # session-id
63
        self._q = Queue()
64 34
        self._connected = False # to be set/cleared by subclass implementation
65 35
    
66 36
    def _post_connect(self):
67
        from ncclient.content.builders import HelloBuilder
68
        self.send(HelloBuilder.build(self._client_capabilities))
37
        "TODO: docstring"
38
        self.send(hello.build(self._client_capabilities))
69 39
        error = None
70 40
        init_event = Event()
71 41
        # callbacks
......
75 45
        def err_cb(err):
76 46
            error = err
77 47
            init_event.set()
78
        listener = HelloListener(ok_cb, err_cb)
48
        listener = hello.HelloListener(ok_cb, err_cb)
79 49
        self.add_listener(listener)
80 50
        # start the subclass' main loop
81 51
        self.start()
......
88 58
        logger.info('initialized: session-id=%s | server_capabilities=%s' %
89 59
                     (self.id, self.server_capabilities))
90 60
    
91
    def send(self, message):
92
        logger.debug('queueing:%s' % message)
93
        self._q.put(message)
94
    
95 61
    def connect(self, *args, **kwds):
62
        "TODO: docstring"
96 63
        raise NotImplementedError
97 64

  
98 65
    def run(self):
......
115 82
    @property
116 83
    def id(self):
117 84
        return self._id
118

  
119

  
120
class HelloListener:
121
    
122
    def __init__(self, init_cb, error_cb):
123
        self._init_cb, self._error_cb = init_cb, error_cb
124
    
125
    def __str__(self):
126
        return 'HelloListener'
127
    
128
    ### Events
129
    
130
    def received(self, raw):
131
        logger.debug(raw)
132
        from ncclient.content.parsers import HelloParser
133
        try:
134
            id, capabilities = HelloParser.parse(raw)
135
        except Exception as e:
136
            self._error_cb(e)
137
        else:
138
            self._init_cb(id, capabilities)
139
    
140
    def error(self, err):
141
        self._error_cb(err)

Also available in: Unified diff