root / ncclient / operations / rpc.py @ 6625258b
History | View | Annotate | Download (4 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 |
from threading import Event, Lock |
16 |
from uuid import uuid1 |
17 |
from weakref import WeakKeyDictionary |
18 |
|
19 |
from listener import SessionListener |
20 |
from ncclient.content.builders import RPCBuilder |
21 |
|
22 |
class RPC: |
23 |
|
24 |
_listeners = WeakKeyDictionary() |
25 |
_lock = Lock() |
26 |
|
27 |
def __init__(self, session): |
28 |
self._session = session
|
29 |
self._id = None |
30 |
self._reply = None # RPCReply |
31 |
self._reply_event = None |
32 |
|
33 |
@property
|
34 |
def _listener(self): |
35 |
with self._lock: |
36 |
return self._listeners.setdefault(self._session, SessionListener()) |
37 |
|
38 |
def deliver(self, raw): |
39 |
self._reply = RPCReply(raw)
|
40 |
self._reply_event.set()
|
41 |
|
42 |
def _do_request(self, op, reply_event=None): |
43 |
self._id = uuid1().urn
|
44 |
# get the listener instance for this session
|
45 |
# <rpc-reply> with message id will reach response_cb
|
46 |
self._listener.register(self._id, self) |
47 |
# only effective the first time, transport.session.Subject internally
|
48 |
# uses a set type for listeners
|
49 |
self._session.add_listener(self._listener) |
50 |
req = RPCBuilder.build(self._id, op)
|
51 |
self._session.send(req)
|
52 |
if reply_event is not None: # if we were provided an Event to use |
53 |
self._reply_event = reply_event
|
54 |
else: # otherwise, block till response received and return it |
55 |
self._reply_event = Event()
|
56 |
self._reply_event.wait()
|
57 |
self._reply.parse()
|
58 |
return self._reply |
59 |
|
60 |
def request(self, *args, **kwds): |
61 |
raise NotImplementedError |
62 |
|
63 |
@property
|
64 |
def has_reply(self): |
65 |
try:
|
66 |
return self._reply_event.isSet() |
67 |
except TypeError: # reply_event is None |
68 |
return False |
69 |
|
70 |
@property
|
71 |
def reply(self): |
72 |
return self._reply |
73 |
|
74 |
@property
|
75 |
def id(self): |
76 |
return self._id |
77 |
|
78 |
@property
|
79 |
def session(self): |
80 |
return self._session |
81 |
|
82 |
class RPCReply: |
83 |
|
84 |
def __init__(self, raw): |
85 |
self._raw = raw
|
86 |
self._parsed = False |
87 |
self._ok = None |
88 |
self._errs = []
|
89 |
|
90 |
def __str__(self): |
91 |
return self._raw |
92 |
|
93 |
def parse(self): |
94 |
#errs = RPCParser.parse(self._raw)
|
95 |
#for raw, err_dict in errs:
|
96 |
# self._errs.append(RPCError(raw, err_dict))
|
97 |
self._parsed = True |
98 |
|
99 |
@property
|
100 |
def raw(self): |
101 |
return self._raw |
102 |
|
103 |
@property
|
104 |
def parsed(self): |
105 |
return self._parsed |
106 |
|
107 |
@property
|
108 |
def ok(self): |
109 |
return True if self._parsed and not self._errs else False |
110 |
|
111 |
@property
|
112 |
def errors(self): |
113 |
return self._errs |
114 |
|
115 |
@property
|
116 |
def raw(self): |
117 |
return self._raw |
118 |
|
119 |
class RPCError(Exception): # raise it if you like |
120 |
|
121 |
def __init__(self, raw, err_dict): |
122 |
self._raw = raw
|
123 |
self._dict = err_dict
|
124 |
|
125 |
def __str__(self): |
126 |
# TODO
|
127 |
return self._raw |
128 |
|
129 |
def __dict__(self): |
130 |
return self._dict |
131 |
|
132 |
@property
|
133 |
def raw(self): |
134 |
return self._raw |
135 |
|
136 |
@property
|
137 |
def type(self): |
138 |
return self._dict.get('type', None) |
139 |
|
140 |
@property
|
141 |
def severity(self): |
142 |
return self._dict.get('severity', None) |
143 |
|
144 |
@property
|
145 |
def tag(self): |
146 |
return self._dict.get('tag', None) |
147 |
|
148 |
@property
|
149 |
def path(self): |
150 |
return self._dict.get('path', None) |
151 |
|
152 |
@property
|
153 |
def message(self): |
154 |
return self._dict.get('message', None) |
155 |
|
156 |
@property
|
157 |
def info(self): |
158 |
return self._dict.get('info', None) |