Statistics
| Branch: | Tag: | Revision:

root / ncclient / operations / rpc.py @ 3e022b7b

History | View | Annotate | Download (3.9 kB)

1 589b23e4 Shikhar Bhushan
# Copyright 2009 Shikhar Bhushan
2 589b23e4 Shikhar Bhushan
#
3 589b23e4 Shikhar Bhushan
# Licensed under the Apache License, Version 2.0 (the "License");
4 589b23e4 Shikhar Bhushan
# you may not use this file except in compliance with the License.
5 589b23e4 Shikhar Bhushan
# You may obtain a copy of the License at
6 589b23e4 Shikhar Bhushan
#
7 589b23e4 Shikhar Bhushan
#    http://www.apache.org/licenses/LICENSE-2.0
8 589b23e4 Shikhar Bhushan
#
9 589b23e4 Shikhar Bhushan
# Unless required by applicable law or agreed to in writing, software
10 589b23e4 Shikhar Bhushan
# distributed under the License is distributed on an "AS IS" BASIS,
11 589b23e4 Shikhar Bhushan
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 589b23e4 Shikhar Bhushan
# See the License for the specific language governing permissions and
13 589b23e4 Shikhar Bhushan
# limitations under the License.
14 589b23e4 Shikhar Bhushan
15 38a9b062 Shikhar Bhushan
from threading import Event, Lock
16 38a9b062 Shikhar Bhushan
from uuid import uuid1
17 38a9b062 Shikhar Bhushan
18 5858a82c Shikhar Bhushan
from ncclient.content import TreeBuilder, BASE_NS
19 3e022b7b Shikhar Bhushan
from ncclient.glue import Listener
20 3e022b7b Shikhar Bhushan
21 3e022b7b Shikhar Bhushan
from . import logger
22 3e022b7b Shikhar Bhushan
from reply import RPCReply
23 3e022b7b Shikhar Bhushan
24 e91a5349 Shikhar Bhushan
25 5858a82c Shikhar Bhushan
class RPC(object):
26 5858a82c Shikhar Bhushan
    
27 11d9e642 Shikhar Bhushan
    def __init__(self, session, async=False):
28 38a9b062 Shikhar Bhushan
        self._session = session
29 11d9e642 Shikhar Bhushan
        self._id = uuid1().urn
30 5858a82c Shikhar Bhushan
        self._listener = RPCReplyListener(session)
31 5858a82c Shikhar Bhushan
        self._listener.register(self._id, self)
32 3e022b7b Shikhar Bhushan
        self._reply = None
33 11d9e642 Shikhar Bhushan
        self._reply_event = Event()
34 efed7d4c Shikhar Bhushan
    
35 11d9e642 Shikhar Bhushan
    def _build(self, op, encoding='utf-8'):
36 5858a82c Shikhar Bhushan
        if isinstance(op, dict):
37 5858a82c Shikhar Bhushan
            return self.build_from_spec(self._id, op, encoding)
38 11d9e642 Shikhar Bhushan
        else:
39 3e022b7b Shikhar Bhushan
            return self.build_from_string(self._id, op, encoding)
40 efed7d4c Shikhar Bhushan
    
41 e91a5349 Shikhar Bhushan
    def _request(self, op):
42 5858a82c Shikhar Bhushan
        req = self._build(op)
43 efed7d4c Shikhar Bhushan
        self._session.send(req)
44 3e022b7b Shikhar Bhushan
        if async:
45 ee4bb099 Shikhar Bhushan
            self._reply_event.wait()
46 efed7d4c Shikhar Bhushan
            self._reply.parse()
47 3e022b7b Shikhar Bhushan
            return self._reply
48 ee4bb099 Shikhar Bhushan
    
49 3e022b7b Shikhar Bhushan
    def deliver(self, raw):
50 3e022b7b Shikhar Bhushan
        self._reply = RPCReply(raw)
51 3e022b7b Shikhar Bhushan
        self._reply_event.set()
52 ee4bb099 Shikhar Bhushan
    
53 589b23e4 Shikhar Bhushan
    @property
54 35ad9d81 Shikhar Bhushan
    def has_reply(self):
55 3e022b7b Shikhar Bhushan
        return self._reply_event.isSet()
56 589b23e4 Shikhar Bhushan
    
57 589b23e4 Shikhar Bhushan
    @property
58 ee4bb099 Shikhar Bhushan
    def reply(self):
59 ee4bb099 Shikhar Bhushan
        return self._reply
60 ee4bb099 Shikhar Bhushan
    
61 ee4bb099 Shikhar Bhushan
    @property
62 38a9b062 Shikhar Bhushan
    def id(self):
63 ee4bb099 Shikhar Bhushan
        return self._id
64 ee4bb099 Shikhar Bhushan
    
65 ee4bb099 Shikhar Bhushan
    @property
66 ee4bb099 Shikhar Bhushan
    def session(self):
67 ee4bb099 Shikhar Bhushan
        return self._session
68 efed7d4c Shikhar Bhushan
    
69 3e022b7b Shikhar Bhushan
    @property
70 3e022b7b Shikhar Bhushan
    def reply_event(self):
71 3e022b7b Shikhar Bhushan
        return self._reply_event
72 3e022b7b Shikhar Bhushan
    
73 11d9e642 Shikhar Bhushan
    @staticmethod
74 11d9e642 Shikhar Bhushan
    def build_from_spec(msgid, opspec, encoding='utf-8'):
75 11d9e642 Shikhar Bhushan
        "TODO: docstring"
76 11d9e642 Shikhar Bhushan
        spec = {
77 11d9e642 Shikhar Bhushan
            'tag': _('rpc', BASE_NS),
78 11d9e642 Shikhar Bhushan
            'attributes': {'message-id': msgid},
79 11d9e642 Shikhar Bhushan
            'children': opspec
80 11d9e642 Shikhar Bhushan
            }
81 11d9e642 Shikhar Bhushan
        return TreeBuilder(spec).to_string(encoding)
82 11d9e642 Shikhar Bhushan
    
83 11d9e642 Shikhar Bhushan
    @staticmethod
84 11d9e642 Shikhar Bhushan
    def build_from_string(msgid, opstr, encoding='utf-8'):
85 11d9e642 Shikhar Bhushan
        "TODO: docstring"
86 11d9e642 Shikhar Bhushan
        decl = '<?xml version="1.0" encoding="%s"?>' % encoding
87 5858a82c Shikhar Bhushan
        doc = (u'<rpc message-id="%s" xmlns="%s">%s</rpc>' %
88 11d9e642 Shikhar Bhushan
               (msgid, BASE_NS, opstr)).encode(encoding)
89 5858a82c Shikhar Bhushan
        return '%s%s' % (decl, doc)
90 3e022b7b Shikhar Bhushan
91 3e022b7b Shikhar Bhushan
92 3e022b7b Shikhar Bhushan
class RPCReplyListener(Listener):
93 3e022b7b Shikhar Bhushan
    
94 3e022b7b Shikhar Bhushan
    # TODO - determine if need locking
95 3e022b7b Shikhar Bhushan
    
96 3e022b7b Shikhar Bhushan
    # one instance per subject    
97 3e022b7b Shikhar Bhushan
    def __new__(cls, subject):
98 3e022b7b Shikhar Bhushan
        instance = subject.get_listener_instance(cls)
99 3e022b7b Shikhar Bhushan
        if instance is None:
100 3e022b7b Shikhar Bhushan
            instance = object.__new__(cls)
101 3e022b7b Shikhar Bhushan
            instance._id2rpc = WeakValueDictionary()
102 3e022b7b Shikhar Bhushan
            instance._errback = None
103 3e022b7b Shikhar Bhushan
            subject.add_listener(instance)
104 3e022b7b Shikhar Bhushan
        return instance
105 3e022b7b Shikhar Bhushan
    
106 3e022b7b Shikhar Bhushan
    def __str__(self):
107 3e022b7b Shikhar Bhushan
        return 'RPCReplyListener'
108 3e022b7b Shikhar Bhushan
    
109 3e022b7b Shikhar Bhushan
    def set_errback(self, errback):
110 3e022b7b Shikhar Bhushan
        self._errback = errback
111 3e022b7b Shikhar Bhushan
112 3e022b7b Shikhar Bhushan
    def register(self, msgid, rpc):
113 3e022b7b Shikhar Bhushan
        self._id2rpc[msgid] = rpc
114 3e022b7b Shikhar Bhushan
    
115 3e022b7b Shikhar Bhushan
    def callback(self, root, raw):
116 3e022b7b Shikhar Bhushan
        tag, attrs = root
117 3e022b7b Shikhar Bhushan
        if __(tag) != 'rpc-reply':
118 3e022b7b Shikhar Bhushan
            return
119 3e022b7b Shikhar Bhushan
        for key in attrs:
120 3e022b7b Shikhar Bhushan
            if __(key) == 'message-id':
121 3e022b7b Shikhar Bhushan
                id = attrs[key]
122 3e022b7b Shikhar Bhushan
                try:
123 3e022b7b Shikhar Bhushan
                    rpc = self._id2rpc[id]
124 3e022b7b Shikhar Bhushan
                    rpc.deliver(raw)
125 3e022b7b Shikhar Bhushan
                except:
126 3e022b7b Shikhar Bhushan
                    logger.warning('RPCReplyListener.callback: no RPC '
127 3e022b7b Shikhar Bhushan
                                   + 'registered for message-id: [%s]' % id)
128 3e022b7b Shikhar Bhushan
                break
129 3e022b7b Shikhar Bhushan
        else:
130 3e022b7b Shikhar Bhushan
            logger.warning('<rpc-reply> without message-id received: %s' % raw)
131 3e022b7b Shikhar Bhushan
    
132 3e022b7b Shikhar Bhushan
    def errback(self, err):
133 3e022b7b Shikhar Bhushan
        logger.error('RPCReplyListener.errback: %r' % err)
134 3e022b7b Shikhar Bhushan
        if self._errback is not None:
135 3e022b7b Shikhar Bhushan
            self._errback(err)