758d1d93efd31cf3bec92ee8aab9426f1e0ef04e
[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 "This module is a thin layer of abstraction around the library. It exposes all core functionality."
16
17 import capabilities
18 import operations
19 import transport
20
21 import logging
22
23 logger = logging.getLogger('ncclient.manager')
24
25 CAPABILITIES = [
26     "urn:ietf:params:netconf:base:1.0",
27     "urn:ietf:params:netconf:capability:writable-running:1.0",
28     "urn:ietf:params:netconf:capability:candidate:1.0",
29     "urn:ietf:params:netconf:capability:confirmed-commit:1.0",
30     "urn:ietf:params:netconf:capability:rollback-on-error:1.0",
31     "urn:ietf:params:netconf:capability:startup:1.0",
32     "urn:ietf:params:netconf:capability:url:1.0?scheme=http,ftp,file,https,sftp",
33     "urn:ietf:params:netconf:capability:validate:1.0",
34     "urn:ietf:params:netconf:capability:xpath:1.0",
35     "urn:liberouter:params:netconf:capability:power-control:1.0"
36     "urn:ietf:params:netconf:capability:interleave:1.0"
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."
39
40 OPERATIONS = {
41     "get": operations.Get,
42     "get_config": operations.GetConfig,
43     "edit_config": operations.EditConfig,
44     "copy_config": operations.CopyConfig,
45     "validate": operations.Validate,
46     "commit": operations.Commit,
47     "discard_changes": operations.DiscardChanges,
48     "delete_config": operations.DeleteConfig,
49     "lock": operations.Lock,
50     "unlock": operations.Unlock,
51     "close_session": operations.CloseSession,
52     "kill_session": operations.KillSession,
53     "poweroff_machine": operations.PoweroffMachine,
54     "reboot_machine": operations.RebootMachine
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."""
57
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`
103     """
104     session = transport.SSHSession(capabilities.Capabilities(CAPABILITIES))
105     session.load_known_hosts()
106     session.connect(*args, **kwds)
107     return Manager(session)
108
109 connect = connect_ssh
110 "Same as :func:`connect_ssh`, since SSH is the default (and currently, the only) transport."
111
112 class OpExecutor(type):
113     def __new__(cls, name, bases, attrs):
114         def make_wrapper(op_cls):
115             def wrapper(self, *args, **kwds):
116                 return self.execute(op_cls, *args, **kwds)
117             wrapper.func_doc = op_cls.request.func_doc
118             return wrapper
119         for op_name, op_cls in OPERATIONS.iteritems():
120             attrs[op_name] = make_wrapper(op_cls)
121         return super(OpExecutor, cls).__new__(cls, name, bases, attrs)
122
123 class Manager(object):
124
125     __metaclass__ = OpExecutor
126
127     RAISE_NONE = 0
128     RAISE_ERRORS = 1
129     RAISE_ALL = 2
130
131     def __init__(self, session):
132         self._session = session
133         self._async_mode = False
134         self._timeout = None
135         self._raise_mode = self.RAISE_ALL
136
137     def __enter__(self):
138         return self
139
140     def __exit__(self, *args):
141         self.close_session()
142         return False
143
144     def execute(self, cls, *args, **kwds):
145         return cls(self._session,
146                    async=self._async_mode,
147                    timeout=self._timeout,
148                    raise_mode=self._raise_mode).request(*args, **kwds)
149
150     def locked(self, target):
151         return operations.LockContext(self._session, target)
152
153     @property
154     def client_capabilities(self):
155         return self._session._client_capabilities
156
157     @property
158     def server_capabilities(self):
159         return self._session._server_capabilities
160
161     @property
162     def session_id(self):
163         return self._session.id
164
165     @property
166     def connected(self):
167         return self._session.connected
168
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
175
176     async_mode = property(fget=lambda self: self._async_mode, fset=set_async_mode)
177
178     raise_mode = property(fget=lambda self: self._raise_mode, fset=set_raise_mode)