Statistics
| Branch: | Tag: | Revision:

root / ncclient / manager.py @ b2d60e49

History | View | Annotate | Download (7 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
"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)