leopoul/ncclient — pull request #1 by vbajpai (2012-12-27 10:14:33+00:00)
Title: ncclient supports v1.1 [RFC 6242]

NETCONF v1.1 support has been added to `ncclient` to allow it to handle
chunked frames (RFC 6242). This gives it the capability to talk to
NETCONF v1.1 servers. However, `ncclient` can always fallsback to
NETCONF v1.0 end of message frames (RFC 4742) for legacy servers that do
not advertise NETCONF v1.1 capability.

NETCONF v1.1 is advertised by adding it in `CAPABILITES` list in `manager.py`

CAPABILITIES = [
"urn:ietf:params:netconf:base:1.0",
"urn:ietf:params:netconf:base:1.1",
...
]

The sources were changed in `transport/ssh.py`. The NETCONF v1.1 chunked
frames parsing state machine is defined in `_parse11(...)`, which is
called in the `run(...)` loop after each time `select(...)` returns.

def _parse11(self):
logger.debug("parsing netconf v1.1")
...

def run(self):
...
r,w,e = select([chan], [], [], TICK)
if r: ...
if not q.empty() and chan.send_read(): ...

Example scripts have also been updated to replace the hard coded values
with optional and positional arguments using argparse (1) to allow the
same script to work for multiple server implementations. For example:

$ python examples/nc01.py -h
usage: nc01.py [-h] [--port PORT] [--logging LEVEL_NAME] [--username USERNAME]
[--password PASSWORD]
hostname

positional arguments:
hostname hostname or IP address

optional arguments:
-h, --help show this help message and exit
--port PORT port number [default: 830]
--logging LEVEL_NAME debug/info/warning/error/critical [default: critical]
--username USERNAME username [default: vbajpai]
--password PASSWORD password

`ncclient` participated at the NETCONF interoperability testing event at
IETF 85, Atlanta (4). The implementation was tested with `confd`, `yuma`
and `libnetconf` servers. Test-runs indicate that `confd` (2) advertises
NETCONF v1.1, however `yuma` (3) does not advertise NETCONF v1.1, even
though the source code supports it. `libnetconf` (4) advertises NETCONF
v1.1, however it seems that ssh, `chan.recv` delivers first only the
framing characters, `\n#123\n` but not the whole frame. This required
the state machine in `_parse11(...)` to not assume that the whole
message is in the buffer but instead do multiple reads via `chan.recv`
to handle this situation.

(1) [argparse →](http://docs.python.org/2/library/argparse.html#module-argparse)
(2) [confd →](http://www.tail-f.com/products-and-services/confd)
(3) [yuma →](http://www.yumaworks.com/yuma/)
(4) [libnetconf →](http://code.google.com/p/libnetconf/)
(5) [IETF 85 →](http://www.ietf.org/meeting/85/)