Revision 541247ba
b/ncclient/operations/reply.py | ||
---|---|---|
31 | 31 |
return self._raw |
32 | 32 |
|
33 | 33 |
def parse(self): |
34 |
if self._parsed: return |
|
34 | 35 |
root = ET.fromstring(self._raw) # <rpc-reply> element |
35 | 36 |
|
36 | 37 |
# per rfc 4741 an <ok/> tag is sent when there are no errors or warnings |
37 | 38 |
oktags = _('ok') |
38 | 39 |
for oktag in oktags: |
39 | 40 |
if root.find(oktag) is not None: |
40 |
logger.debug('found %s' % oktag)
|
|
41 |
logger.debug('parsed [%s]' % oktag)
|
|
41 | 42 |
self._parsed = True |
42 | 43 |
return |
43 | 44 |
|
... | ... | |
45 | 46 |
errtags = _('rpc-error') |
46 | 47 |
for errtag in errtags: |
47 | 48 |
for err in root.getiterator(errtag): # a particular <rpc-error> |
49 |
logger.debug('parsed [%s]' % errtag) |
|
48 | 50 |
d = {} |
49 | 51 |
for err_detail in err.getchildren(): # <error-type> etc.. |
50 |
d[__(err_detail)] = err_detail.text |
|
52 |
d[__(err_detail.tag)] = err_detail.text
|
|
51 | 53 |
self._errors.append(RPCError(d)) |
52 | 54 |
if self._errors: |
53 | 55 |
break |
... | ... | |
128 | 130 |
|
129 | 131 |
items = lambda self: self._dict.items() |
130 | 132 |
|
131 |
__repr__ = lambda self: repr(self._dict) |
|
133 |
__repr__ = lambda self: repr(self._dict) |
b/ncclient/operations/rpc.py | ||
---|---|---|
24 | 24 |
from . import logger |
25 | 25 |
from reply import RPCReply |
26 | 26 |
|
27 |
# Cisco does not include message-id attribute in <rpc-reply> in case of an error. |
|
28 |
# This is messed up however we have to deal with it. |
|
29 |
# So essentially, there can be only one operation at a time if we are talking to |
|
30 |
# a Cisco device. |
|
27 | 31 |
|
28 | 32 |
class RPC(object): |
29 | 33 |
|
30 | 34 |
def __init__(self, session, async=False): |
35 |
if session.is_remote_cisco and async: |
|
36 |
raise UserWarning('Asynchronous mode not supported for Cisco devices') |
|
31 | 37 |
self._session = session |
32 | 38 |
self._async = async |
33 | 39 |
self._id = uuid1().urn |
... | ... | |
114 | 120 |
|
115 | 121 |
# TODO - determine if need locking |
116 | 122 |
|
117 |
# one instance per subject
|
|
118 |
def __new__(cls, subject):
|
|
119 |
instance = subject.get_listener_instance(cls)
|
|
123 |
# one instance per session
|
|
124 |
def __new__(cls, session):
|
|
125 |
instance = session.get_listener_instance(cls)
|
|
120 | 126 |
if instance is None: |
121 | 127 |
instance = object.__new__(cls) |
122 | 128 |
instance._id2rpc = WeakValueDictionary() |
129 |
instance._cisco = session.is_remote_cisco |
|
123 | 130 |
instance._errback = None |
124 |
subject.add_listener(instance)
|
|
131 |
session.add_listener(instance)
|
|
125 | 132 |
return instance |
126 | 133 |
|
127 | 134 |
def __str__(self): |
... | ... | |
137 | 144 |
tag, attrs = root |
138 | 145 |
if __(tag) != 'rpc-reply': |
139 | 146 |
return |
147 |
rpc = None |
|
140 | 148 |
for key in attrs: |
141 | 149 |
if __(key) == 'message-id': |
142 | 150 |
id = attrs[key] |
143 | 151 |
try: |
144 |
rpc = self._id2rpc[id] |
|
145 |
rpc.deliver(raw) |
|
152 |
rpc = self._id2rpc.pop(id) |
|
146 | 153 |
except KeyError: |
147 |
logger.warning('[RPCReplyListener.callback] no RPC '
|
|
154 |
logger.warning('[RPCReplyListener.callback] no object '
|
|
148 | 155 |
+ 'registered for message-id: [%s]' % id) |
149 |
logger.debug('[RPCReplyListener.callback] registered: %r ' |
|
150 |
% dict(self._id2rpc)) |
|
151 | 156 |
except Exception as e: |
152 | 157 |
logger.debug('[RPCReplyListener.callback] error - %r' % e) |
153 | 158 |
break |
154 | 159 |
else: |
155 |
logger.warning('<rpc-reply> without message-id received: %s' % raw) |
|
160 |
if self._cisco: |
|
161 |
assert(len(self._id2rpc) == 1) |
|
162 |
rpc = self._id2rpc.values()[0] |
|
163 |
self._id2rpc.clear() |
|
164 |
else: |
|
165 |
logger.warning('<rpc-reply> without message-id received: %s' % raw) |
|
166 |
logger.debug('[RPCReplyListener.callback] delivering to %r' % rpc) |
|
167 |
rpc.deliver(raw) |
|
156 | 168 |
|
157 | 169 |
def errback(self, err): |
158 | 170 |
if self._errback is not None: |
b/ncclient/operations/session.py | ||
---|---|---|
27 | 27 |
def _delivery_hook(self): |
28 | 28 |
if self.reply.ok: |
29 | 29 |
self.session.expect_close() |
30 |
self.session.close() |
|
30 | 31 |
|
31 | 32 |
def request(self): |
32 | 33 |
return self._request(self.spec) |
b/ncclient/transport/ssh.py | ||
---|---|---|
241 | 241 |
logger.debug(e) |
242 | 242 |
|
243 | 243 |
if saved_exception is not None: |
244 |
# need pep-3134 to do this right |
|
244 | 245 |
raise SSHAuthenticationError(repr(saved_exception)) |
245 | 246 |
|
246 | 247 |
raise SSHAuthenticationError('No authentication methods available') |
... | ... | |
286 | 287 |
documentation for details. |
287 | 288 |
''' |
288 | 289 |
return self._transport |
290 |
|
|
291 |
@property |
|
292 |
def is_remote_cisco(self): |
|
293 |
return 'Cisco' in self._transport.remote_version |
b/ncclient/util.py | ||
---|---|---|
20 | 20 |
class PrintListener(Listener): |
21 | 21 |
|
22 | 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)
|
|
23 |
print('\n# RECEIVED MESSAGE with root=[tag=%r, attrs=%r] #\n%r\n' %
|
|
24 |
(root[0], root[1], raw))
|
|
25 | 25 |
|
26 | 26 |
def errback(self, err): |
27 |
print '\n$ RECEIVED ERROR:\n%r\n' % err |
|
27 |
print('\n# RECEIVED ERROR #\n%r\n' % err) |
Also available in: Unified diff