Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-ncclient for openSUSE:Factory
checked in at 2024-11-11 14:58:22
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-ncclient (Old)
and /work/SRC/openSUSE:Factory/.python-ncclient.new.2017 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-ncclient"
Mon Nov 11 14:58:22 2024 rev:23 rq:1223349 version:0.6.16
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-ncclient/python-ncclient.changes
2024-10-27 11:26:19.465014436 +0100
+++
/work/SRC/openSUSE:Factory/.python-ncclient.new.2017/python-ncclient.changes
2024-11-11 14:58:25.567166739 +0100
@@ -1,0 +2,11 @@
+Sun Nov 10 19:50:09 UTC 2024 - Martin Hauke <[email protected]>
+
+- Update to version 0.6.16
+ * Add Ciena driver.
+ * Update session.py.
+ * call_home: timeout as argument.
+ * Introduce Unix Socket Transport.
+ * feat: Add support for Nokia SR OS private candidate mode.
+ * Fix support of .ssh/id_ed25519 keys.
+
+-------------------------------------------------------------------
Old:
----
ncclient-0.6.15.tar.gz
New:
----
ncclient-0.6.16.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-ncclient.spec ++++++
--- /var/tmp/diff_new_pack.5sh7Zx/_old 2024-11-11 14:58:27.323240211 +0100
+++ /var/tmp/diff_new_pack.5sh7Zx/_new 2024-11-11 14:58:27.351241382 +0100
@@ -17,7 +17,7 @@
Name: python-ncclient
-Version: 0.6.15
+Version: 0.6.16
Release: 0
Summary: Python library for NETCONF clients
License: Apache-2.0
@@ -75,7 +75,6 @@
%install
%python_install
-%python_expand rm -rf %{buildroot}%{$python_sitelib}/test
%fdupes %{buildroot}
%check
++++++ ncclient-0.6.15.tar.gz -> ncclient-0.6.16.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ncclient-0.6.15/README.md
new/ncclient-0.6.16/README.md
--- old/ncclient-0.6.15/README.md 2023-10-16 17:46:13.000000000 +0200
+++ new/ncclient-0.6.16/README.md 2024-10-09 10:17:14.000000000 +0200
@@ -19,6 +19,7 @@
| Date | Release | Description |
| :----: | :-----: | :---------- |
+| 10/18/23 | `0.6.15` | See [release
page](https://github.com/ncclient/ncclient/releases/tag/v0.6.15)|
| 04/10/22 | `0.6.13` | See [release
page](https://github.com/ncclient/ncclient/releases/tag/v0.6.13)|
| 05/29/21 | `0.6.12` | See [release
page](https://github.com/ncclient/ncclient/releases/tag/v0.6.12)|
| 05/27/21 | `0.6.11` | See [release
page](https://github.com/ncclient/ncclient/releases/tag/v0.6.11)|
@@ -96,18 +97,19 @@
When instantiating a connection to a known type of NETCONF server:
-* Juniper: `device_params={'name':'junos'}`
+* Alcatel Lucent: `device_params={'name':'alu'}`
+* Ciena: `device_params={'name':'ciena'}`
* Cisco:
- CSR: `device_params={'name':'csr'}`
- Nexus: `device_params={'name':'nexus'}`
- IOS XR: `device_params={'name':'iosxr'}`
- IOS XE: `device_params={'name':'iosxe'}`
+* H3C: `device_params={'name':'h3c'}`
+* HP Comware: `device_params={'name':'hpcomware'}`
* Huawei:
- `device_params={'name':'huawei'}`
- `device_params={'name':'huaweiyang'}`
-* Nokia SR OS: `device_params={'name':'sros'}`
-* H3C: `device_params={'name':'h3c'}`
-* HP Comware: `device_params={'name':'hpcomware'}`
+* Juniper: `device_params={'name':'junos'}`
* Server or anything not in above: `device_params={'name':'default'}`
@@ -132,13 +134,18 @@
1. Install testing dependencies:
```
- pip install nose rednose coverage coveralls mock
+ pip install pytest coverage coveralls mock
```
1. Finally, run the tests:
```
- nosetests test --rednose --verbosity=3
+ pytest test --verbosity=3
+ ```
+
+ For coverage, showing missing lines do:
+ ```
+ coverage run -m pytest test --verbosity=3 && coverage report -m
```
### Making a Release
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ncclient-0.6.15/README.rst
new/ncclient-0.6.16/README.rst
--- old/ncclient-0.6.15/README.rst 2023-10-16 17:46:13.000000000 +0200
+++ new/ncclient-0.6.16/README.rst 2024-10-09 10:17:14.000000000 +0200
@@ -87,18 +87,19 @@
Supported device handlers
'''''''''''''''''''''''''
-* Juniper: `device_params={'name':'junos'}`
+* Alcatel Lucent: `device_params={'name':'alu'}`
+* Ciena: `device_params={'name':'ciena'}`
* Cisco:
- CSR: `device_params={'name':'csr'}`
- Nexus: `device_params={'name':'nexus'}`
- IOS XR: `device_params={'name':'iosxr'}`
- IOS XE: `device_params={'name':'iosxe'}`
+* H3C: `device_params={'name':'h3c'}`
+* HP Comware: `device_params={'name':'hpcomware'}`
* Huawei:
- `device_params={'name':'huawei'}`
- `device_params={'name':'huaweiyang'}`
-* Nokia SR OS: `device_params={'name':'sros'}`
-* H3C: `device_params={'name':'h3c'}`
-* HP Comware: `device_params={'name':'hpcomware'}`
+* Juniper: `device_params={'name':'junos'}`
* Server or anything not in above: `device_params={'name':'default'}`
Changes \| brief
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ncclient-0.6.15/docs/source/index.rst
new/ncclient-0.6.16/docs/source/index.rst
--- old/ncclient-0.6.15/docs/source/index.rst 2023-10-16 17:46:13.000000000
+0200
+++ new/ncclient-0.6.16/docs/source/index.rst 2024-10-09 10:17:14.000000000
+0200
@@ -39,18 +39,19 @@
Supported device handlers
-------------------------
-* Juniper: `device_params={'name':'junos'}`
+* Alcatel Lucent: `device_params={'name':'alu'}`
+* Ciena: `device_params={'name':'ciena'}`
* Cisco:
- CSR: `device_params={'name':'csr'}`
- Nexus: `device_params={'name':'nexus'}`
- IOS XR: `device_params={'name':'iosxr'}`
- IOS XE: `device_params={'name':'iosxe'}`
+* H3C: `device_params={'name':'h3c'}`
+* HP Comware: `device_params={'name':'hpcomware'}`
* Huawei:
- `device_params={'name':'huawei'}`
- `device_params={'name':'huaweiyang'}`
-* Alcatel Lucent: `device_params={'name':'alu'}`
-* H3C: `device_params={'name':'h3c'}`
-* HP Comware: `device_params={'name':'hpcomware'}`
+* Juniper: `device_params={'name':'junos'}`
* Server or anything not in above: `device_params={'name':'default'}`
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ncclient-0.6.15/examples/base/nc10.py
new/ncclient-0.6.16/examples/base/nc10.py
--- old/ncclient-0.6.15/examples/base/nc10.py 1970-01-01 01:00:00.000000000
+0100
+++ new/ncclient-0.6.16/examples/base/nc10.py 2024-10-09 10:17:14.000000000
+0200
@@ -0,0 +1,24 @@
+#! /usr/bin/env python
+#
+# Connect to NETCONF server using unix socket passed on the command line.
+# Then display the servers capabilities. After connecting you can also use
+# all other operations supported by ncclient, example: get(), get_config()...
+#
+# To test against a example NETCONF server with unix socket support check out:
+# https://github.com/CESNET/libnetconf2
+# It contains an example server which can listen for connections using a unix
+# socket.
+#
+# $ ./nc10.py "/path/to/socket"
+
+import sys, warnings
+warnings.simplefilter("ignore", DeprecationWarning)
+from ncclient import manager
+
+def demo(path):
+ with manager.connect_uds(path) as m:
+ for c in m.server_capabilities:
+ print(c)
+
+if __name__ == '__main__':
+ demo(sys.argv[1])
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/ncclient-0.6.15/examples/vendor/nokia/sros/config_mode.py
new/ncclient-0.6.16/examples/vendor/nokia/sros/config_mode.py
--- old/ncclient-0.6.15/examples/vendor/nokia/sros/config_mode.py
1970-01-01 01:00:00.000000000 +0100
+++ new/ncclient-0.6.16/examples/vendor/nokia/sros/config_mode.py
2024-10-09 10:17:14.000000000 +0200
@@ -0,0 +1,118 @@
+import logging
+import sys
+import threading
+import time
+from ncclient import manager
+
+# Device connection details
+DEVICE_HOST = '62.40.111.58'
+DEVICE_PORT = 3830
+DEVICE_USER = 'admin'
+DEVICE_PASS = 'admin'
+
+# Configuration payload template for SNMP community string
+EDIT_CONFIG_PAYLOAD = """
+<config xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
+ <configure xmlns="urn:nokia.com:sros:ns:yang:sr:conf">
+ <system>
+ <security>
+ <snmp>
+ <community>
+ <community-string>TestCommunity-{}</community-string>
+ <access-permissions>r</access-permissions>
+ <version>v2c</version>
+ </community>
+ </snmp>
+ </security>
+ </system>
+ </configure>
+</config>
+"""
+
+
+def create_ncclient_session(host, port, username, password, config_mode=None):
+ """
+ Creates and returns an ncclient manager session for connecting to the
Nokia SR OS device.
+
+ :param host: Hostname or IP of the Nokia device
+ :param port: NETCONF port
+ :param username: Username for device authentication
+ :param password: Password for device authentication
+ :param config_mode: 'private' to use private candidate mode, None for
default mode
+ :return: NETCONF manager session
+ """
+ device_params = {'name': 'sros'}
+ if config_mode:
+ device_params['config_mode'] = config_mode
+
+ return manager.connect(
+ host=host,
+ port=port,
+ username=username,
+ password=password,
+ hostkey_verify=False,
+ device_params=device_params
+ )
+
+
+def configure_and_commit(session_id, config_mode=None):
+ """
+ Creates a NETCONF session, edits the configuration, and commits the
changes.
+
+ :param session_id: Unique session identifier for logging
+ :param config_mode: 'private' for private candidate mode, None for default
mode
+ """
+ try:
+ with create_ncclient_session(DEVICE_HOST, DEVICE_PORT, DEVICE_USER,
DEVICE_PASS, config_mode=config_mode) as nc_session:
+ logging.info(f"Session {session_id} started with config_mode:
{config_mode or 'default'}")
+
+ # Edit the device configuration using the payload
+ edit_payload = EDIT_CONFIG_PAYLOAD.format(session_id)
+ nc_session.edit_config(target='candidate', config=edit_payload)
+ logging.info(f"Session {session_id} successfully edited the
configuration.")
+
+ # Commit the changes to the device
+ nc_session.commit(comment=f"Session {session_id} commit in
{config_mode or 'default'} mode")
+ logging.info(f"Session {session_id} committed successfully in
{config_mode or 'default'} mode.")
+
+ except Exception as e:
+ logging.error(f"Session {session_id} encountered an error: {e}")
+
+
+def run_concurrent_sessions(session_ids, config_mode=None):
+ """
+ Runs multiple NETCONF sessions concurrently.
+
+ :param session_ids: List of session IDs to identify different threads
+ :param config_mode: 'private' to use private candidate mode, None for
default mode
+ """
+ threads = []
+ for session_id in session_ids:
+ thread = threading.Thread(target=configure_and_commit,
args=(session_id, config_mode))
+ threads.append(thread)
+ thread.start()
+
+ # Ensure all threads finish execution
+ for thread in threads:
+ thread.join()
+
+
+def main():
+ LOG_FORMAT = '%(asctime)s %(levelname)s %(filename)s:%(lineno)d
%(message)s'
+ logging.basicConfig(stream=sys.stdout, level=logging.INFO,
format=LOG_FORMAT)
+
+ logging.info("Starting test with concurrent sessions in default mode
(expecting conflicts)...")
+
+ # Run test with concurrent sessions in default mode
+ run_concurrent_sessions([1, 2, 3, 4, 5])
+
+ logging.info("Now testing with concurrent sessions in private mode (no
conflicts expected)...")
+
+ # Run test with concurrent sessions in private candidate mode
+ run_concurrent_sessions([6, 7, 8, 9], config_mode='private')
+
+ logging.info("Test completed.")
+
+
+if __name__ == '__main__':
+ main()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ncclient-0.6.15/ncclient/_version.py
new/ncclient-0.6.16/ncclient/_version.py
--- old/ncclient-0.6.15/ncclient/_version.py 2023-10-16 17:46:13.000000000
+0200
+++ new/ncclient-0.6.16/ncclient/_version.py 2024-10-09 10:17:14.000000000
+0200
@@ -26,9 +26,9 @@
# setup.py/versioneer.py will grep for the variable names, so they must
# each be defined on a line of their own. _version.py will just call
# get_keywords().
- git_refnames = " (tag: v0.6.15)"
- git_full = "f0f4d95ed8613f256f0972491d6c47f53246da0b"
- git_date = "2023-10-16 16:46:13 +0100"
+ git_refnames = " (tag: v0.6.16)"
+ git_full = "652ef67b266df0ee02bbbbc4cc6eb09ca01f4878"
+ git_date = "2024-10-09 09:17:14 +0100"
keywords = {"refnames": git_refnames, "full": git_full, "date": git_date}
return keywords
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ncclient-0.6.15/ncclient/devices/__init__.py
new/ncclient-0.6.16/ncclient/devices/__init__.py
--- old/ncclient-0.6.15/ncclient/devices/__init__.py 2023-10-16
17:46:13.000000000 +0200
+++ new/ncclient-0.6.16/ncclient/devices/__init__.py 2024-10-09
10:17:14.000000000 +0200
@@ -1,20 +1,24 @@
# supported devices config, add new device (eg: 'device name':'device label').
-supported_devices_cfg = {'junos':'Juniper',
- 'csr':'Cisco CSR1000v',
- 'nexus':'Cisco Nexus',
- 'iosxr':'Cisco IOS XR',
- 'iosxe':'Cisco IOS XE',
- 'huawei':'Huawei',
- 'huaweiyang':'Huawei',
- 'alu':'Alcatel Lucent',
- 'h3c':'H3C',
- 'hpcomware':'HP Comware',
- 'sros':'Nokia SR OS',
- 'default':'Server or anything not in above'}
+supported_devices_cfg = {
+ "alu": "Alcatel Lucent",
+ "ciena": "Ciena",
+ "csr": "Cisco CSR1000v",
+ "h3c": "H3C",
+ "hpcomware": "HP Comware",
+ "huawei": "Huawei",
+ "huaweiyang": "Huawei",
+ "iosxe": "Cisco IOS XE",
+ "iosxr": "Cisco IOS XR",
+ "junos": "Juniper",
+ "nexus": "Cisco Nexus",
+ "sros": "Nokia SR OS",
+ "default": "Server or anything not in above",
+}
+
def get_supported_devices():
return tuple(supported_devices_cfg.keys())
+
def get_supported_device_labels():
return supported_devices_cfg
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ncclient-0.6.15/ncclient/devices/ciena.py
new/ncclient-0.6.16/ncclient/devices/ciena.py
--- old/ncclient-0.6.15/ncclient/devices/ciena.py 1970-01-01
01:00:00.000000000 +0100
+++ new/ncclient-0.6.16/ncclient/devices/ciena.py 2024-10-09
10:17:14.000000000 +0200
@@ -0,0 +1,19 @@
+from .default import DefaultDeviceHandler
+from ncclient.xml_ import BASE_NS_1_0
+
+
+class CienaDeviceHandler(DefaultDeviceHandler):
+ """
+ Ciena handler for device specific information.
+ """
+
+ def __init__(self, device_params):
+ super(CienaDeviceHandler, self).__init__(device_params)
+
+ def get_xml_base_namespace_dict(self):
+ return {None: BASE_NS_1_0}
+
+ def get_xml_extra_prefix_kwargs(self):
+ d = {}
+ d.update(self.get_xml_base_namespace_dict())
+ return {"nsmap": d}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ncclient-0.6.15/ncclient/devices/sros.py
new/ncclient-0.6.16/ncclient/devices/sros.py
--- old/ncclient-0.6.15/ncclient/devices/sros.py 2023-10-16
17:46:13.000000000 +0200
+++ new/ncclient-0.6.16/ncclient/devices/sros.py 2024-10-09
10:17:14.000000000 +0200
@@ -1,10 +1,11 @@
-from lxml import etree
-
from .default import DefaultDeviceHandler
from ncclient.operations.third_party.sros.rpc import MdCliRawCommand, Commit
from ncclient.xml_ import BASE_NS_1_0
+class ConfigMode:
+ PRIVATE = 'private'
+
def passthrough(xml):
return xml
@@ -30,7 +31,11 @@
'urn:ietf:params:xml:ns:netconf:base:1.0',
'urn:ietf:params:xml:ns:yang:1',
'urn:ietf:params:netconf:capability:confirmed-commit:1.1',
- 'urn:ietf:params:netconf:capability:validate:1.1']
+ 'urn:ietf:params:netconf:capability:validate:1.1',
+ ]
+ if self.device_params.get('config_mode') == ConfigMode.PRIVATE:
+ additional.append('urn:nokia.com:nc:pc')
+
return base + additional
def get_xml_base_namespace_dict(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ncclient-0.6.15/ncclient/manager.py
new/ncclient-0.6.16/ncclient/manager.py
--- old/ncclient-0.6.15/ncclient/manager.py 2023-10-16 17:46:13.000000000
+0200
+++ new/ncclient-0.6.16/ncclient/manager.py 2024-10-09 10:17:14.000000000
+0200
@@ -158,6 +158,19 @@
return Manager(session, device_handler, **manager_params)
+def connect_uds(*args, **kwargs):
+ """Initialize a :class:`Manager` over the Unix Socket transport."""
+ device_params = _extract_device_params(kwargs)
+ manager_params = _extract_manager_params(kwargs)
+ nc_params = _extract_nc_params(kwargs)
+
+ device_handler = make_device_handler(device_params)
+ device_handler.add_additional_netconf_params(nc_params)
+ session = transport.UnixSocketSession(device_handler)
+
+ session.connect(*args, **kwargs)
+
+ return Manager(session, device_handler, **manager_params)
def connect_ioproc(*args, **kwds):
device_params = _extract_device_params(kwds)
@@ -191,7 +204,7 @@
port = kwds.get("port",4334)
srv_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
srv_socket.bind((host, port))
- srv_socket.settimeout(10)
+ srv_socket.settimeout(kwds.get("timeout", 10))
srv_socket.listen()
sock, remote_host = srv_socket.accept()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ncclient-0.6.15/ncclient/transport/__init__.py
new/ncclient-0.6.16/ncclient/transport/__init__.py
--- old/ncclient-0.6.15/ncclient/transport/__init__.py 2023-10-16
17:46:13.000000000 +0200
+++ new/ncclient-0.6.16/ncclient/transport/__init__.py 2024-10-09
10:17:14.000000000 +0200
@@ -17,6 +17,7 @@
from ncclient.transport.session import Session, SessionListener, NetconfBase
from ncclient.transport.ssh import SSHSession
from ncclient.transport.tls import TLSSession
+from ncclient.transport.unixSocket import UnixSocketSession
from ncclient.transport.errors import *
__all__ = [
@@ -24,6 +25,7 @@
'SessionListener',
'SSHSession',
'TLSSession',
+ 'UnixSocketSession',
'TransportError',
'AuthenticationError',
'SessionCloseError',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ncclient-0.6.15/ncclient/transport/errors.py
new/ncclient-0.6.16/ncclient/transport/errors.py
--- old/ncclient-0.6.15/ncclient/transport/errors.py 2023-10-16
17:46:13.000000000 +0200
+++ new/ncclient-0.6.16/ncclient/transport/errors.py 2024-10-09
10:17:14.000000000 +0200
@@ -53,3 +53,6 @@
class TLSError(TransportError):
pass
+
+class UnixSocketError (TransportError):
+ pass
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ncclient-0.6.15/ncclient/transport/session.py
new/ncclient-0.6.16/ncclient/transport/session.py
--- old/ncclient-0.6.15/ncclient/transport/session.py 2023-10-16
17:46:13.000000000 +0200
+++ new/ncclient-0.6.16/ncclient/transport/session.py 2024-10-09
10:17:14.000000000 +0200
@@ -218,6 +218,21 @@
self._transport_register(s, selectors.EVENT_READ)
self.logger.debug('selector type = %s', s.__class__.__name__)
while True:
+
+ if not q.empty() and self._send_ready():
+ self.logger.debug("Sending message")
+ data = q.get().encode()
+ if self._base == NetconfBase.BASE_11:
+ data = b"%s%s%s" % (start_delim(len(data)), data,
END_DELIM)
+ else:
+ data = b"%s%s" % (data, MSG_DELIM)
+ self.logger.info("Sending:\n%s", data)
+ while data:
+ n = self._transport_write(data)
+ if n <= 0:
+ raise SessionCloseError(self._buffer.getvalue(),
data)
+ data = data[n:]
+
events = s.select(timeout=TICK)
if events:
data = self._transport_read()
@@ -234,19 +249,6 @@
else:
# End of session, unexpected
raise SessionCloseError(self._buffer.getvalue())
- if not q.empty() and self._send_ready():
- self.logger.debug("Sending message")
- data = q.get().encode()
- if self._base == NetconfBase.BASE_11:
- data = b"%s%s%s" % (start_delim(len(data)), data,
END_DELIM)
- else:
- data = b"%s%s" % (data, MSG_DELIM)
- self.logger.info("Sending:\n%s", data)
- while data:
- n = self._transport_write(data)
- if n <= 0:
- raise SessionCloseError(self._buffer.getvalue(),
data)
- data = data[n:]
except Exception as e:
self.logger.debug("Broke out of main loop, error=%r", e)
self._dispatch_error(e)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ncclient-0.6.15/ncclient/transport/ssh.py
new/ncclient-0.6.16/ncclient/transport/ssh.py
--- old/ncclient-0.6.15/ncclient/transport/ssh.py 2023-10-16
17:46:13.000000000 +0200
+++ new/ncclient-0.6.16/ncclient/transport/ssh.py 2024-10-09
10:17:14.000000000 +0200
@@ -453,22 +453,28 @@
rsa_key = os.path.expanduser("~/.ssh/id_rsa")
dsa_key = os.path.expanduser("~/.ssh/id_dsa")
ecdsa_key = os.path.expanduser("~/.ssh/id_ecdsa")
+ ed25519_key = os.path.expanduser("~/.ssh/id_ed25519")
if os.path.isfile(rsa_key):
keyfiles.append((paramiko.RSAKey, rsa_key))
if os.path.isfile(dsa_key):
keyfiles.append((paramiko.DSSKey, dsa_key))
if os.path.isfile(ecdsa_key):
keyfiles.append((paramiko.ECDSAKey, ecdsa_key))
+ if os.path.isfile(ed25519_key):
+ keyfiles.append((paramiko.Ed25519Key, ed25519_key))
# look in ~/ssh/ for windows users:
rsa_key = os.path.expanduser("~/ssh/id_rsa")
dsa_key = os.path.expanduser("~/ssh/id_dsa")
ecdsa_key = os.path.expanduser("~/ssh/id_ecdsa")
+ ed25519_key = os.path.expanduser("~/ssh/id_ed25519")
if os.path.isfile(rsa_key):
keyfiles.append((paramiko.RSAKey, rsa_key))
if os.path.isfile(dsa_key):
keyfiles.append((paramiko.DSSKey, dsa_key))
if os.path.isfile(ecdsa_key):
keyfiles.append((paramiko.ECDSAKey, ecdsa_key))
+ if os.path.isfile(ed25519_key):
+ keyfiles.append((paramiko.Ed25519Key, ed25519_key))
for cls, filename in keyfiles:
try:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ncclient-0.6.15/ncclient/transport/unixSocket.py
new/ncclient-0.6.16/ncclient/transport/unixSocket.py
--- old/ncclient-0.6.15/ncclient/transport/unixSocket.py 1970-01-01
01:00:00.000000000 +0100
+++ new/ncclient-0.6.16/ncclient/transport/unixSocket.py 2024-10-09
10:17:14.000000000 +0200
@@ -0,0 +1,83 @@
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import logging
+import socket
+import threading
+from io import BytesIO as StringIO
+
+from socket import AF_UNIX, SOCK_STREAM
+
+from ncclient.capabilities import Capabilities
+from ncclient.logging_ import SessionLoggerAdapter
+from ncclient.transport.errors import UnixSocketError
+from ncclient.transport.session import Session
+from ncclient.transport.parser import DefaultXMLParser
+
+logger = logging.getLogger("ncclient.transport.unix")
+
+DEFAULT_TIMEOUT = 120
+
+BUF_SIZE = 4096
+
+class UnixSocketSession(Session):
+
+ "Implements a NETCONF Session over Unix Socket on local machine."
+
+ def __init__(self, device_handler):
+ capabilities = Capabilities(device_handler.get_capabilities())
+ Session.__init__(self, capabilities)
+ self._connected = False
+ self._socket = None
+ self._buffer = StringIO()
+ self._device_handler = device_handler
+ self._message_list = []
+ self._closing = threading.Event()
+ self.parser = DefaultXMLParser(self)
+ self.logger = SessionLoggerAdapter(logger, {'session': self})
+
+ def _dispatch_message(self, raw):
+ self.logger.info("Received message from host")
+ self.logger.debug("Received:\n%s", raw)
+ return super(UnixSocketSession, self)._dispatch_message(raw)
+
+ def close(self):
+ self._closing.set()
+ self._socket.close()
+ self._connected = False
+
+ def connect(self, path=None, timeout=DEFAULT_TIMEOUT):
+ sock = socket.socket(AF_UNIX, SOCK_STREAM)
+ sock.settimeout(timeout)
+
+ try:
+ sock.connect(path)
+ except Exception:
+ raise UnixSocketError("Could not connect to %s" % path)
+
+ self._socket = sock
+ self._connected = True
+ self._post_connect()
+
+ def _transport_read(self):
+ return self._socket.recv(BUF_SIZE)
+
+ def _transport_write(self, data):
+ return self._socket.send(data)
+
+ def _transport_register(self, selector, event):
+ selector.register(self._socket, event)
+
+ def _send_ready(self):
+ # In contrast to Paramiko's `Channel`, pure python sockets do not
+ # expose `send_ready()` function.
+ return True
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ncclient-0.6.15/test/unit/devices/test_ciena.py
new/ncclient-0.6.16/test/unit/devices/test_ciena.py
--- old/ncclient-0.6.15/test/unit/devices/test_ciena.py 1970-01-01
01:00:00.000000000 +0100
+++ new/ncclient-0.6.16/test/unit/devices/test_ciena.py 2024-10-09
10:17:14.000000000 +0200
@@ -0,0 +1,18 @@
+import unittest
+from ncclient.devices.ciena import *
+from ncclient.xml_ import *
+
+
+class TestCienaDevice(unittest.TestCase):
+
+ def setUp(self):
+ self.obj = CienaDeviceHandler({'name': 'ciena'})
+
+ def test_get_xml_base_namespace_dict(self):
+ expected = {None: BASE_NS_1_0}
+ self.assertDictEqual(expected, self.obj.get_xml_base_namespace_dict())
+
+ def test_get_xml_extra_prefix_kwargs(self):
+ expected = dict()
+ expected["nsmap"] = self.obj.get_xml_base_namespace_dict()
+ self.assertDictEqual(expected, self.obj.get_xml_extra_prefix_kwargs())
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/ncclient-0.6.15/test/unit/devices/test_get_supported_devices.py
new/ncclient-0.6.16/test/unit/devices/test_get_supported_devices.py
--- old/ncclient-0.6.15/test/unit/devices/test_get_supported_devices.py
2023-10-16 17:46:13.000000000 +0200
+++ new/ncclient-0.6.16/test/unit/devices/test_get_supported_devices.py
2024-10-09 10:17:14.000000000 +0200
@@ -7,6 +7,7 @@
supported_devices = devices.get_supported_devices()
self.assertEqual(sorted(supported_devices), sorted(('junos',
'csr',
+ 'ciena',
'nexus',
'iosxr',
'iosxe',
@@ -22,6 +23,7 @@
supported_device_labels = devices.get_supported_device_labels()
self.assertEqual(supported_device_labels, {'junos':'Juniper',
'csr':'Cisco CSR1000v',
+ 'ciena': 'Ciena',
'nexus':'Cisco Nexus',
'iosxr':'Cisco IOS XR',
'iosxe':'Cisco IOS XE',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/ncclient-0.6.15/test/unit/devices/test_sros.py
new/ncclient-0.6.16/test/unit/devices/test_sros.py
--- old/ncclient-0.6.15/test/unit/devices/test_sros.py 2023-10-16
17:46:13.000000000 +0200
+++ new/ncclient-0.6.16/test/unit/devices/test_sros.py 2024-10-09
10:17:14.000000000 +0200
@@ -1,7 +1,8 @@
import unittest
-from ncclient.devices.sros import *
-from ncclient.xml_ import *
+from ncclient.devices.sros import SrosDeviceHandler, ConfigMode
+from ncclient.xml_ import to_ele, to_xml, BASE_NS_1_0
+from ncclient.operations.third_party.sros.rpc import MdCliRawCommand, Commit
capabilities = ['urn:ietf:params:netconf:base:1.0',
'urn:ietf:params:netconf:base:1.1',
@@ -36,32 +37,39 @@
class TestSrosDevice(unittest.TestCase):
def setUp(self):
- self.obj = SrosDeviceHandler({'name': 'sros'})
+ self.device_handler = SrosDeviceHandler({'name': 'sros'})
def test_add_additional_operations(self):
expected = {
'md_cli_raw_command': MdCliRawCommand,
'commit': Commit,
}
- self.assertDictEqual(expected, self.obj.add_additional_operations())
+ self.assertDictEqual(expected,
self.device_handler.add_additional_operations())
def test_transform_reply(self):
expected = xml
- actual = self.obj.transform_reply()
+ actual = self.device_handler.transform_reply()
ele = to_ele(xml)
self.assertEqual(expected, to_xml(actual(ele)))
- def test_get_capabilities(self):
- self.assertListEqual(capabilities, self.obj.get_capabilities())
+ def test_get_capabilities_without_config_mode(self):
+ """Test capabilities without 'config_mode' set"""
+ self.assertListEqual(capabilities,
self.device_handler.get_capabilities())
+
+ def test_get_capabilities_with_config_mode_private(self):
+ """Test capabilities when 'config_mode' is set to 'private'"""
+ device_handler = SrosDeviceHandler({'name': 'sros', 'config_mode':
ConfigMode.PRIVATE})
+ expected_capabilities = capabilities + ['urn:nokia.com:nc:pc']
+ self.assertListEqual(expected_capabilities,
device_handler.get_capabilities())
def test_get_xml_base_namespace_dict(self):
expected = {None: BASE_NS_1_0}
- self.assertDictEqual(expected, self.obj.get_xml_base_namespace_dict())
+ self.assertDictEqual(expected,
self.device_handler.get_xml_base_namespace_dict())
def test_get_xml_extra_prefix_kwargs(self):
expected = dict()
- expected['nsmap'] = self.obj.get_xml_base_namespace_dict()
- self.assertDictEqual(expected, self.obj.get_xml_extra_prefix_kwargs())
+ expected['nsmap'] = self.device_handler.get_xml_base_namespace_dict()
+ self.assertDictEqual(expected,
self.device_handler.get_xml_extra_prefix_kwargs())
def test_perform_qualify_check(self):
- self.assertFalse(self.obj.perform_qualify_check())
+ self.assertFalse(self.device_handler.perform_qualify_check())
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/ncclient-0.6.15/test/unit/transport/test_UnixSocket.py
new/ncclient-0.6.16/test/unit/transport/test_UnixSocket.py
--- old/ncclient-0.6.15/test/unit/transport/test_UnixSocket.py 1970-01-01
01:00:00.000000000 +0100
+++ new/ncclient-0.6.16/test/unit/transport/test_UnixSocket.py 2024-10-09
10:17:14.000000000 +0200
@@ -0,0 +1,33 @@
+
+import sys
+import unittest
+import socket
+from ncclient.devices.junos import JunosDeviceHandler
+
+try:
+ from unittest.mock import MagicMock, patch, call
+except ImportError:
+ from mock import MagicMock, patch, call
+
+from ncclient.transport.errors import UnixSocketError
+from ncclient.transport.unixSocket import UnixSocketSession
+
+PATH = '/tmp/test_socket.sock'
+
+class TestUnixSocket(unittest.TestCase):
+
+ @patch('socket.socket.close')
+ def test_close_UnixSocket(self, mock_sock_close_fn):
+ session = UnixSocketSession(MagicMock())
+ session._socket = socket.socket()
+ session._connected = True
+ session.close()
+ mock_sock_close_fn.assert_called_once_with()
+ self.assertFalse(session.connected)
+
+ @patch('socket.socket')
+ @patch('ncclient.transport.Session._post_connect')
+ def test_connect_UnixSocket(self, mock_post_connect, mock_socket):
+ session = UnixSocketSession(MagicMock())
+ session.connect(path=PATH)
+ self.assertTrue(session.connected)