Statistics
| Branch: | Tag: | Revision:

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)