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