most importantly: finally, code in trunk actually works
[ncclient] / ncclient / manager.py
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 "Thin layer of abstraction around NCClient"
16
17 import capabilities
18 import operations
19 import transport
20
21 import logging
22 logger = logging.getLogger('ncclient.manager')
23
24 def connect_ssh(*args, **kwds):
25     """Connect to NETCONF server over SSH. See :meth:`SSHSession.connect()
26     <ncclient.transport.SSHSession.connect>` for argument details.
27
28     :rtype: :class:`Manager`
29     """
30     session = transport.SSHSession(capabilities.CAPABILITIES)
31     session.load_known_hosts()
32     session.connect(*args, **kwds)
33     return Manager(session)
34
35 #: Same as :meth:`connect_ssh`
36 connect = connect_ssh
37
38 class Manager(object):
39
40     """API for NETCONF operations.
41
42     It is also a context manager, so a :class:`Manager` instance can be used
43     with the *with* statement. The session is closed when the context ends. """
44
45     def __init__(self, session):
46         self._session = session
47         self._async_mode = False
48         self._timeout = None
49         self._raise_mode = 'all'
50
51     def __enter__(self):
52         return self
53
54     def __exit__(self, *argss):
55         self.close()
56         return False
57
58     def __getattr__(self, name):
59         op = operations.INDEX.get(name, None)
60         if op is None:
61             raise AttributeError
62         else:
63             return op(self.session,
64                       async=self._async_mode,
65                       timeout=self._timeout,
66                       raise_mode=self._raise_mode).request
67     
68     def locked(self, target):
69         """Returns a context manager for the *with* statement.
70
71         :arg target: name of the datastore to lock
72         :type target: `string`
73         :rtype: :class:`~ncclient.operations.LockContext`
74         """
75         return operations.LockContext(self._session, target)
76
77     def close(self):
78         """Closes the NETCONF session. First does *<close-session>* RPC."""
79         try: # try doing it clean
80             self._async_mode = False
81             self.close_session()
82         except Exception as e:
83             logger.debug('error doing <close-session> -- %r' % e)
84         if self._session.connected: # if that didn't work, this sure will :)
85             self._session.close()
86
87     @property
88     def session(self):
89         ":class:`~ncclient.transport.Session` instance"
90         return self._session
91
92     @property
93     def client_capabilities(self):
94         ":class:`~ncclient.capabilities.Capabilities` object for client"
95         return self._session._client_capabilities
96
97     @property
98     def server_capabilities(self):
99         ":class:`~ncclient.capabilities.Capabilities` object for server"
100         return self._session._server_capabilities
101
102     @property
103     def session_id(self):
104         "*<session-id>* as assigned by NETCONF server"
105         return self._session.id
106
107     @property
108     def connected(self):
109         "Whether currently connected to NETCONF server"
110         return self._session.connected
111
112     def set_async_mode(self, bool=True):
113         self._async_mode = bool
114
115     def set_raise_mode(self, mode):
116         assert(choice in ('all', 'errors', 'none'))
117         self._raise_mode = mode
118
119     async_mode = property(fget=lambda self: self._async_mode, fset=set_async_mode)
120
121     raise_mode = property(fget=set_raise_mode, fset=set_raise_mode)