Revision 19e7c7f6 ncclient/manager.py
b/ncclient/manager.py | ||
---|---|---|
12 | 12 |
# See the License for the specific language governing permissions and |
13 | 13 |
# limitations under the License. |
14 | 14 |
|
15 |
"This module is a thin layer of abstraction around the library. It exposes all core functionality."
|
|
15 |
"""This module is a thin layer of abstraction around the library. It exposes all core functionality."""
|
|
16 | 16 |
|
17 | 17 |
import capabilities |
18 | 18 |
import operations |
... | ... | |
35 | 35 |
"urn:liberouter:params:netconf:capability:power-control:1.0" |
36 | 36 |
"urn:ietf:params:netconf:capability:interleave:1.0" |
37 | 37 |
] |
38 |
"A list of URI's representing the client's capabilities. This is used during the initial capability exchange. Modify this if you need to announce some capability not already included."
|
|
38 |
"""A list of URI's representing the client's capabilities. This is used during the initial capability exchange. Modify this if you need to announce some capability not already included."""
|
|
39 | 39 |
|
40 | 40 |
OPERATIONS = { |
41 | 41 |
"get": operations.Get, |
... | ... | |
53 | 53 |
"poweroff_machine": operations.PoweroffMachine, |
54 | 54 |
"reboot_machine": operations.RebootMachine |
55 | 55 |
} |
56 |
"""Dictionary of method names and corresponding `~ncclient.operations.RPC` subclasses. It is used to lookup operations, e.g. "get_config" is mapped to `~ncclient.operations.GetConfig`. It is thus possible to add additional operations to the `Manager` API."""
|
|
56 |
"""Dictionary of method names and corresponding :class:`~ncclient.operations.RPC` subclasses. It is used to lookup operations, e.g. `get_config` is mapped to :class:`~ncclient.operations.GetConfig`. It is thus possible to add additional operations to the :class:`Manager` API."""
|
|
57 | 57 |
|
58 | 58 |
def connect_ssh(*args, **kwds): |
59 |
"""Initializes a NETCONF session over SSH, and creates a connected `Manager` instance. *host* must be specified, all the other arguments are optional and depend on the kind of host key verification and user authentication you want to complete. |
|
60 |
|
|
61 |
For the purpose of host key verification, on -NIX systems a user's :file:`~/.ssh/known_hosts` file is automatically considered. The *unknown_host_cb* argument specifies a callback that will be invoked when the server's host key cannot be verified. See :func:`~ncclient.transport.ssh.default_unknown_host_cb` for function signature. |
|
62 |
|
|
63 |
First, ``publickey`` authentication is attempted. If a specific *key_filename* is specified, it |
|
64 |
will be loaded and authentication attempted using it. If *allow_agent* is :const:`True` and an |
|
65 |
SSH agent is running, the keys provided by the agent will be tried. If *look_for_keys* is |
|
66 |
:const:`True`, keys in the :file:`~/.ssh/id_rsa` and :file:`~.ssh/id_dsa` will be tried. In case |
|
67 |
an encrypted key file is encountered, the *password* argument will be used as a decryption |
|
68 |
passphrase. |
|
69 |
|
|
70 |
If ``publickey`` authentication fails and the *password* argument has been supplied, ``password`` / ``keyboard-interactive`` SSH authentication will be attempted. |
|
71 |
|
|
72 |
:param host: hostname or address on which to connect |
|
73 |
:type host: `string` |
|
74 |
|
|
75 |
:param port: port on which to connect |
|
76 |
:type port: `int` |
|
77 |
|
|
78 |
:param timeout: timeout for socket connect |
|
79 |
:type timeout: `int` |
|
80 |
|
|
81 |
:param unknown_host_cb: optional; callback that is invoked when host key verification fails |
|
82 |
:type unknown_host_cb: `function` |
|
83 |
|
|
84 |
:param username: username to authenticate with, if not specified the username of the logged-in user is used |
|
85 |
:type username: `string` |
|
86 |
|
|
87 |
:param password: password for ``password`` authentication or passphrase for decrypting private key files |
|
88 |
:type password: `string` |
|
89 |
|
|
90 |
:param key_filename: location of a private key file on the file system |
|
91 |
:type key_filename: `string` |
|
92 |
|
|
93 |
:param allow_agent: whether to try connecting to SSH agent for keys |
|
94 |
:type allow_agent: `bool` |
|
95 |
|
|
96 |
:param look_for_keys: whether to look in usual locations for keys |
|
97 |
:type look_for_keys: `bool` |
|
98 |
|
|
99 |
:raises: :exc:`~ncclient.transport.SSHUnknownHostError` |
|
100 |
:raises: :exc:`~ncclient.transport.AuthenticationError` |
|
101 |
|
|
102 |
:rtype: `Manager` |
|
59 |
"""Initialize a :class:`Manager` over the SSH transport. For documentation of arguments see :meth:`ncclient.transport.SSHSession.connect`. |
|
60 |
|
|
61 |
The underlying :class:`ncclient.transport.SSHSession` is created with :data:`CAPABILITIES`. It is first instructed to :meth:`~ncclient.transport.SSHSession.load_known_hosts` and then all the provided arguments are passed directly to its implementation of :meth:`~ncclient.transport.SSHSession.connect`. |
|
103 | 62 |
""" |
104 | 63 |
session = transport.SSHSession(capabilities.Capabilities(CAPABILITIES)) |
105 | 64 |
session.load_known_hosts() |
... | ... | |
110 | 69 |
"Same as :func:`connect_ssh`, since SSH is the default (and currently, the only) transport." |
111 | 70 |
|
112 | 71 |
class OpExecutor(type): |
72 |
|
|
113 | 73 |
def __new__(cls, name, bases, attrs): |
114 | 74 |
def make_wrapper(op_cls): |
115 | 75 |
def wrapper(self, *args, **kwds): |
... | ... | |
122 | 82 |
|
123 | 83 |
class Manager(object): |
124 | 84 |
|
125 |
__metaclass__ = OpExecutor |
|
85 |
"""For details on the expected behavior of the operations and their parameters refer to :rfc:`4741`. |
|
86 |
|
|
87 |
Manager instances are also context managers so you can use it like this:: |
|
88 |
|
|
89 |
with manager.connect("host") as m: |
|
90 |
# do your stuff |
|
126 | 91 |
|
127 |
RAISE_NONE = 0 |
|
128 |
RAISE_ERRORS = 1 |
|
129 |
RAISE_ALL = 2 |
|
92 |
... or like this:: |
|
130 | 93 |
|
131 |
def __init__(self, session): |
|
94 |
m = manager.connect("host") |
|
95 |
try: |
|
96 |
# do your stuff |
|
97 |
finally: |
|
98 |
m.close_session() |
|
99 |
""" |
|
100 |
|
|
101 |
__metaclass__ = OpExecutor |
|
102 |
|
|
103 |
def __init__(self, session, timeout=30): |
|
132 | 104 |
self._session = session |
133 | 105 |
self._async_mode = False |
134 |
self._timeout = None
|
|
135 |
self._raise_mode = self.RAISE_ALL
|
|
106 |
self._timeout = timeout
|
|
107 |
self._raise_mode = operations.RaiseMode.ALL
|
|
136 | 108 |
|
137 | 109 |
def __enter__(self): |
138 | 110 |
return self |
... | ... | |
141 | 113 |
self.close_session() |
142 | 114 |
return False |
143 | 115 |
|
116 |
def __set_async_mode(self, mode): |
|
117 |
self._async_mode = mode |
|
118 |
|
|
119 |
def __set_raise_mode(self, mode): |
|
120 |
assert(choice in (operations.RaiseMode.NONE, operations.RaiseMode.ERRORS, operations.RaiseMode.ALL)) |
|
121 |
self._raise_mode = mode |
|
122 |
|
|
144 | 123 |
def execute(self, cls, *args, **kwds): |
145 | 124 |
return cls(self._session, |
146 | 125 |
async=self._async_mode, |
... | ... | |
148 | 127 |
raise_mode=self._raise_mode).request(*args, **kwds) |
149 | 128 |
|
150 | 129 |
def locked(self, target): |
130 |
"""Returns a context manager for a lock on a datastore, where *target* is the name of the configuration datastore to lock, e.g.:: |
|
131 |
|
|
132 |
with m.locked("running"): |
|
133 |
# do your stuff |
|
134 |
|
|
135 |
... instead of:: |
|
136 |
|
|
137 |
m.lock("running") |
|
138 |
try: |
|
139 |
# do your stuff |
|
140 |
finally: |
|
141 |
m.unlock("running") |
|
142 |
""" |
|
151 | 143 |
return operations.LockContext(self._session, target) |
152 | 144 |
|
153 | 145 |
@property |
154 | 146 |
def client_capabilities(self): |
147 |
":class:`~ncclient.capabilities.Capabilities` object representing the client's capabilities." |
|
155 | 148 |
return self._session._client_capabilities |
156 | 149 |
|
157 | 150 |
@property |
158 | 151 |
def server_capabilities(self): |
152 |
":class:`~ncclient.capabilities.Capabilities` object representing the server's capabilities." |
|
159 | 153 |
return self._session._server_capabilities |
160 | 154 |
|
161 | 155 |
@property |
162 | 156 |
def session_id(self): |
157 |
"`session-id` assigned by the NETCONF server." |
|
163 | 158 |
return self._session.id |
164 | 159 |
|
165 | 160 |
@property |
166 | 161 |
def connected(self): |
162 |
"Whether currently connected to the NETCONF server." |
|
167 | 163 |
return self._session.connected |
168 | 164 |
|
169 |
def set_async_mode(self, mode): |
|
170 |
self._async_mode = mode |
|
171 |
|
|
172 |
def set_raise_mode(self, mode): |
|
173 |
assert(choice in (self.RAISE_NONE, self.RAISE_ERRORS, self.RAISE_ALL)) |
|
174 |
self._raise_mode = mode |
|
165 |
async_mode = property(fget=lambda self: self._async_mode, fset=__set_async_mode) |
|
166 |
"Specify whether operations are executed asynchronously (`True`) or synchronously (`False`) (the default)." |
|
175 | 167 |
|
176 |
async_mode = property(fget=lambda self: self._async_mode, fset=set_async_mode) |
|
177 | 168 |
|
178 |
raise_mode = property(fget=lambda self: self._raise_mode, fset=set_raise_mode) |
|
169 |
raise_mode = property(fget=lambda self: self._raise_mode, fset=__set_raise_mode) |
|
170 |
"Specify which errors are raised as :exc:`~ncclient.operations.RPCError` exceptions. Valid values are the constants defined in :class:`~ncclient.operations.RaiseMode`. The default value is :attr:`~ncclient.operations.RaiseMode.ALL`." |
Also available in: Unified diff