Statistics
| Branch: | Tag: | Revision:

root / ncclient / operations / rpc.py @ a956ef07

History | View | Annotate | Download (3.1 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
'Remote Procedure Call'
16

    
17
from threading import Event, Lock
18
from uuid import uuid1
19

    
20
_listeners = WeakValueDictionary()
21

    
22
def get_listener(session):
23
    try:
24
        return _listeners[session]
25
    except KeyError:
26
        _listeners[session] = MessageListener()
27
        return _listeners[session]
28

    
29
class RPC:
30
    
31
    def __init__(self, session, async=False, parse=True):
32
        self._session = session
33
        self._async = async
34
        self._id = uuid1().urn
35
        self._reply = None
36
        self._reply_event = Event()
37
        self.listener.register(self._id, self)
38
        session.add_listener(self.listener)
39

    
40
    def _response_cb(self, reply):
41
        self._reply = reply
42
        self._event.set()
43
    
44
    def _do_request(self, operation):
45
        'operation is xml string'
46
        self._session.send(content.RPC.make(self._id, operation))
47
        if not self._async:
48
            self._reply_event.wait()
49
        return self._reply
50
    
51
    def request(self):
52
        raise NotImplementedError
53
    
54
    def wait_for_reply(self, timeout=None):
55
        self._reply_event.wait(timeout)
56
    
57
    @property
58
    def has_reply(self):
59
        return self._reply_event.isSet()
60
    
61
    @property
62
    def is_async(self):
63
        return self._async
64
    
65
    @property
66
    def reply(self):
67
        return self._reply
68
    
69
    @property
70
    def id(self):
71
        return self._id
72
    
73
    @property
74
    def listener(self):
75
        listener = get_listener(self._session)
76

    
77
    @property
78
    def session(self):
79
        return self._session
80

    
81
class RPCReply:
82
    
83
    class RPCError:
84
        
85
        pass
86
    
87

    
88
class MessageListener:
89
    
90
    def __init__(self):
91
        # {message-id: RPC}
92
        self._rpc = WeakValueDictionary()
93
        # if the session gets closed by remote endpoint,
94
        # need to know if it is an error event or was requested through
95
        # a NETCONF operation i.e. CloseSession
96
        self._expecting_close = False
97
        # other recognized names and behavior on receiving them
98
        self._recognized = []
99
    
100
    def __str__(self):
101
        return 'MessageListener'
102
    
103
    def expect_close(self):
104
        self._expecting_close = True
105
    
106
    def register(self, id, op):
107
        self._id2rpc[id] = op
108
    
109
    ### Events
110
    
111
    def reply(self, raw):
112
        pass
113
    
114
    def error(self, err):
115
        from ncclient.session.session import SessionCloseError
116
        if err is SessionCloseError:
117
            logger.debug('session closed by remote endpoint, expecting_close=%s' %
118
                         self._expecting_close)
119
            if not self._expecting_close:
120
                raise err
121