Hello community, here is the log from the commit of package python-ncclient for openSUSE:Factory checked in at 2019-05-15 12:35:29 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-ncclient (Old) and /work/SRC/openSUSE:Factory/.python-ncclient.new.5148 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-ncclient" Wed May 15 12:35:29 2019 rev:9 rq:703087 version:0.6.4 Changes: -------- --- /work/SRC/openSUSE:Factory/python-ncclient/python-ncclient.changes 2019-03-20 13:22:50.361291737 +0100 +++ /work/SRC/openSUSE:Factory/.python-ncclient.new.5148/python-ncclient.changes 2019-05-15 12:35:30.216352539 +0200 @@ -1,0 +2,9 @@ +Wed Apr 10 06:59:10 UTC 2019 - Dirk Mueller <dmuel...@suse.com> + +- update to v0.6.4: + * Use os.path.expanduser() on paths read from ssh_config. + * Proxycommand can be a list. Identityfile already performs ~ expansion in + * Enhance Alcatel-Lucent -support +- add sphinx-use-imgmath-extension.patch + +------------------------------------------------------------------- Old: ---- ncclient-0.6.3.tar.gz New: ---- ncclient-0.6.4.tar.gz sphinx-use-imgmath-extension.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-ncclient.spec ++++++ --- /var/tmp/diff_new_pack.SXCBYe/_old 2019-05-15 12:35:31.104350185 +0200 +++ /var/tmp/diff_new_pack.SXCBYe/_new 2019-05-15 12:35:31.108350175 +0200 @@ -19,20 +19,23 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} %bcond_without test Name: python-ncclient -Version: 0.6.3 +Version: 0.6.4 Release: 0 Summary: Python library for NETCONF clients License: Apache-2.0 Group: Development/Languages/Python Url: http://ncclient.org Source: https://files.pythonhosted.org/packages/source/n/ncclient/ncclient-%{version}.tar.gz +Patch0: sphinx-use-imgmath-extension.patch BuildRequires: %{python_module devel} BuildRequires: %{python_module setuptools} BuildRequires: fdupes BuildRequires: python-rpm-macros Requires: python-lxml >= 3.3.0 Requires: python-paramiko >= 1.15.0 +%ifpython2 Requires: python-selectors2 >= 2.0.1 +%endif Requires: python-setuptools > 0.6 Requires: python-six BuildArch: noarch @@ -51,7 +54,9 @@ %package -n python-ncclient-doc Summary: Python NETCONF protocol library - Documentation Group: Documentation/HTML +BuildRequires: %{python_module Sphinx-latex} BuildRequires: %{python_module Sphinx} +BuildRequires: texlive-dvipng Provides: %{python_module python-ncclient-doc = %{version}} %description -n python-ncclient-doc @@ -59,6 +64,7 @@ %prep %setup -q -n ncclient-%{version} +%patch0 %build %python_build ++++++ ncclient-0.6.3.tar.gz -> ncclient-0.6.4.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ncclient-0.6.3/PKG-INFO new/ncclient-0.6.4/PKG-INFO --- old/ncclient-0.6.3/PKG-INFO 2018-09-26 20:17:34.000000000 +0200 +++ new/ncclient-0.6.4/PKG-INFO 2019-04-07 19:45:30.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.2 Name: ncclient -Version: 0.6.3 +Version: 0.6.4 Summary: Python library for NETCONF clients Home-page: https://github.com/ncclient/ncclient Author: Shikhar Bhushan, Leonidas Poulopoulos, Ebben Aries, Einar Nilsen-Nygaard diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ncclient-0.6.3/examples/alu/edit_config.py new/ncclient-0.6.4/examples/alu/edit_config.py --- old/ncclient-0.6.3/examples/alu/edit_config.py 1970-01-01 01:00:00.000000000 +0100 +++ new/ncclient-0.6.4/examples/alu/edit_config.py 2019-04-07 15:39:58.000000000 +0200 @@ -0,0 +1,39 @@ +#!/usr/bin/env python +import logging + +from ncclient import manager +from ncclient.xml_ import * + + +def connect(host, port, user, password): + conn = manager.connect(host=host, + port=port, + username=user, + password=password, + timeout=10, + device_params={'name': 'alu'}, + hostkey_verify=False) + + print('Set CLI -config -block') + + config = """ + configure port 1/1/1 + description \"Loaded as CLI -block\" + exit""" + + conn.load_configuration(format='cli', config=config) + + + print('Load XML -config') + config = new_ele('configure', attrs={'xmlns': ALU_CONFIG}) + port = sub_ele(config, 'port') + sub_ele(port, 'port-id').text = '1/1/1' + desc = sub_ele(port, 'description') + sub_ele(desc, 'long-description-string').text = "Loaded using XML" + + conn.load_configuration(config=config, format='xml') + + conn.close_session() + +if __name__ == '__main__': + connect('router', 830, 'admin', 'admin') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ncclient-0.6.3/examples/alu/get_config.py new/ncclient-0.6.4/examples/alu/get_config.py --- old/ncclient-0.6.3/examples/alu/get_config.py 1970-01-01 01:00:00.000000000 +0100 +++ new/ncclient-0.6.4/examples/alu/get_config.py 2019-04-07 15:39:58.000000000 +0200 @@ -0,0 +1,55 @@ +#!/usr/bin/env python + +import logging + +from lxml import etree +from ncclient import manager +from ncclient.xml_ import * + + +def connect(host, port, user, password): + conn = manager.connect(host=host, + port=port, + username=user, + password=password, + timeout=10, + device_params={'name': 'alu'}, + hostkey_verify=False) + + + logging.info('Retrieving full config, please wait ...') + + result = conn.get_configuration() + logging.info(result) + + logging.info('Here is the chassis configuration') + output = result.xpath('data/configure/system/chassis')[0] + logging.info(to_xml(output)) + + logging.info('Retrieving service config') + + # specify filter to pass to get_config + filter = new_ele('configure', attrs={'xmlns': ALU_CONFIG}) + sub_ele(filter, 'service') + result = conn.get_configuration(filter=filter) + epipes = result.xpath('data/configure/service/epipe') + + for i in epipes: + logging.info(etree.tostring(i, pretty_print=True).decode('utf-8')) + + logging.info('Getting CLI -config') + cli_cfg = conn.get_configuration(content='cli', filter=['port 1/1/11']) + logging.info(cli_cfg) + + logging.info('Get detailed CLI -config') + cli_cfg = conn.get_configuration(content='cli', filter=['port 1/1/11'], detail=True) + logging.info(cli_cfg) + + conn.close_session() + + +if __name__ == '__main__': + LOG_FORMAT = '%(asctime)s %(levelname)s %(filename)s:%(lineno)d %(message)s' + logging.basicConfig(stream=sys.stdout, level=logging.INFO, format=LOG_FORMAT) + + connect('localhost', 830, 'admin', 'admin') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ncclient-0.6.3/examples/nc04.py new/ncclient-0.6.4/examples/nc04.py --- old/ncclient-0.6.3/examples/nc04.py 2018-07-02 19:49:57.000000000 +0200 +++ new/ncclient-0.6.4/examples/nc04.py 2019-04-07 15:39:58.000000000 +0200 @@ -10,12 +10,12 @@ from ncclient import manager def demo(host, user, name, uid, gid): - snippet = """<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0"> + snippet = """<nc:config xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"> <aaa xmlns="http://tail-f.com/ns/aaa/1.1"> - <authentication> <users> <user xc:operation="create"> + <authentication> <users> <user nc:operation="create"> <name>%s</name> <uid>%s</uid> <gid>%s</gid> <password>*</password> <ssh_keydir/> <homedir/> - </user></users></authentication></aaa></config>""" % (name, uid, gid) + </user></users></authentication></aaa></nc:config>""" % (name, uid, gid) with manager.connect(host=host, port=22, username=user) as m: assert(":validate" in m.server_capabilities) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ncclient-0.6.3/examples/nc05.py new/ncclient-0.6.4/examples/nc05.py --- old/ncclient-0.6.3/examples/nc05.py 2018-07-02 19:49:57.000000000 +0200 +++ new/ncclient-0.6.4/examples/nc05.py 2019-04-07 15:39:58.000000000 +0200 @@ -11,11 +11,11 @@ from ncclient import manager def demo(host, user, name): - snippet = """<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0"> + snippet = """<nc:config xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"> <aaa xmlns="http://tail-f.com/ns/aaa/1.1"> - <authentication> <users> <user xc:operation="delete"> + <authentication> <users> <user nc:operation="delete"> <name>%s</name> - </user></users></authentication></aaa></config>""" % name + </user></users></authentication></aaa></nc:config>""" % name with manager.connect(host=host, port=22, username=user) as m: assert(":validate" in m.server_capabilities) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ncclient-0.6.3/examples/nc06.py new/ncclient-0.6.4/examples/nc06.py --- old/ncclient-0.6.3/examples/nc06.py 2018-07-02 19:49:57.000000000 +0200 +++ new/ncclient-0.6.4/examples/nc06.py 2019-04-07 15:39:58.000000000 +0200 @@ -9,10 +9,10 @@ warnings.simplefilter("ignore", DeprecationWarning) from ncclient import manager -template = """<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0"> +template = """<nc:config xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"> <aaa xmlns="http://tail-f.com/ns/aaa/1.1"> - <authentication> <users> <user xc:operation="delete"> - <name>%s</name> </user></users></authentication></aaa></config>""" + <authentication> <users> <user nc:operation="delete"> + <name>%s</name> </user></users></authentication></aaa></nc:config>""" def demo(host, user, names): with manager.connect(host=host, port=22, username=user) as m: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ncclient-0.6.3/examples/nc07.py new/ncclient-0.6.4/examples/nc07.py --- old/ncclient-0.6.3/examples/nc07.py 2018-07-02 19:49:57.000000000 +0200 +++ new/ncclient-0.6.4/examples/nc07.py 2019-04-07 15:39:58.000000000 +0200 @@ -9,10 +9,10 @@ warnings.simplefilter("ignore", DeprecationWarning) from ncclient import manager -template = """<config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0"> +template = """<nc:config xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"> <aaa xmlns="http://tail-f.com/ns/aaa/1.1"> - <authentication> <users> <user xc:operation="delete"> - <name>%s</name> </user></users></authentication></aaa></config>""" + <authentication> <users> <user nc:operation="delete"> + <name>%s</name> </user></users></authentication></aaa></nc:config>""" def demo(host, user, names): with manager.connect(host=host, port=22, username=user) as m: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ncclient-0.6.3/examples/nxosapi.py new/ncclient-0.6.4/examples/nxosapi.py --- old/ncclient-0.6.3/examples/nxosapi.py 2018-07-02 19:49:57.000000000 +0200 +++ new/ncclient-0.6.4/examples/nxosapi.py 2019-04-07 15:39:58.000000000 +0200 @@ -13,7 +13,7 @@ from ncclient import manager exec_conf_prefix = """ - <config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0"> + <nc:config xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"> <configure xmlns="http://www.cisco.com/nxos:1.0:vlan_mgr_cli"> <__XML__MODE__exec_configure> """ @@ -21,7 +21,7 @@ exec_conf_postfix = """ </__XML__MODE__exec_configure> </configure> - </config> + </nc:config> """ cmd_vlan_conf_snippet= """ @@ -67,7 +67,7 @@ """ cmd_no_vlan_int_snippet = """ - <config xmlns:xc="urn:ietf:params:xml:ns:netconf:base:1.0"> + <nc:config xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"> <configure xmlns="http://www.cisco.com/nxos:1.0:vlan_mgr_cli"> <__XML__MODE__exec_configure> <interface> @@ -92,7 +92,7 @@ </interface> </__XML__MODE__exec_configure> </configure> - </config> + </nc:config> """ filter_show_vlan_brief_snippet = """ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ncclient-0.6.3/ncclient/_version.py new/ncclient-0.6.4/ncclient/_version.py --- old/ncclient-0.6.3/ncclient/_version.py 2018-09-26 20:17:34.000000000 +0200 +++ new/ncclient-0.6.4/ncclient/_version.py 2019-04-07 19:45:30.000000000 +0200 @@ -8,11 +8,11 @@ version_json = ''' { - "date": "2018-09-26T19:09:51+0100", + "date": "2019-04-07T18:43:24+0100", "dirty": false, "error": null, - "full-revisionid": "d647a9ee3f600d027d7396ac181b4d7df41191fd", - "version": "0.6.3" + "full-revisionid": "2420a81396e50c075f022be5cd27768d13aa0898", + "version": "0.6.4" } ''' # END VERSION_JSON diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ncclient-0.6.3/ncclient/capabilities.py new/ncclient-0.6.4/ncclient/capabilities.py --- old/ncclient-0.6.3/ncclient/capabilities.py 2018-07-02 19:49:57.000000000 +0200 +++ new/ncclient-0.6.4/ncclient/capabilities.py 2019-04-07 19:42:01.000000000 +0200 @@ -12,9 +12,14 @@ # See the License for the specific language governing permissions and # limitations under the License. +import logging import sys import six + +logger = logging.getLogger("ncclient.capabilities") + + def _abbreviate(uri): if uri.startswith("urn:ietf:params") and ":netconf:" in uri: splitted = uri.split(":") @@ -42,15 +47,25 @@ def __init__(self, capabilities): self._dict = {} for uri in capabilities: - self._dict[uri] = _abbreviate(uri) + self.add(uri) def __contains__(self, key): - if key in self._dict: + try: + self.__getitem__(key) + except KeyError: + return False + else: return True - for abbrs in six.itervalues(self._dict): - if key in abbrs: - return True - return False + + def __getitem__(self, key): + try: + return self._dict[key] + except KeyError: + for capability in six.itervalues(self._dict): + if key in capability.get_abbreviations(): + return capability + + raise KeyError(key) def __len__(self): return len(self._dict) @@ -64,9 +79,81 @@ def add(self, uri): "Add a capability." - self._dict[uri] = _abbreviate(uri) + self._dict[uri] = Capability.from_uri(uri) def remove(self, uri): "Remove a capability." if uri in self._dict: del self._dict[uri] + + +class Capability(object): + + """Represents a single capability""" + + def __init__(self, namespace_uri, parameters=None): + self.namespace_uri = namespace_uri + self.parameters = parameters or {} + + @classmethod + def from_uri(cls, uri): + split_uri = uri.split("?") + namespace_uri = split_uri[0] + capability = cls(namespace_uri) + + try: + param_string = split_uri[1] + except IndexError: + return capability + + capability.parameters = { + param.key: param.value + for param in _parse_parameter_string(param_string, uri) + } + + return capability + + def __eq__(self, other): + return ( + self.namespace_uri == other.namespace_uri and + self.parameters == other.parameters + ) + + def get_abbreviations(self): + return _abbreviate(self.namespace_uri) + + +def _parse_parameter_string(string, uri): + for param_string in string.split("&"): + try: + yield _Parameter.from_string(param_string) + except _InvalidParameter: + logger.error( + "Invalid parameter '{param}' in capability URI '{uri}'".format( + param=param_string, + uri=uri, + ) + ) + + +class _Parameter(object): + + """Represents a parameter to a capability""" + + def __init__(self, key, value): + self.key = key + self.value = value + + @classmethod + def from_string(cls, string): + try: + key, value = string.split("=") + except ValueError: + raise _InvalidParameter + + return cls(key, value) + + +class _InvalidParameter(Exception): + + pass diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ncclient-0.6.3/ncclient/devices/alu.py new/ncclient-0.6.4/ncclient/devices/alu.py --- old/ncclient-0.6.3/ncclient/devices/alu.py 2018-07-02 19:49:57.000000000 +0200 +++ new/ncclient-0.6.4/ncclient/devices/alu.py 2019-04-07 15:39:58.000000000 +0200 @@ -1,10 +1,28 @@ +from lxml import etree + from .default import DefaultDeviceHandler +from ncclient.operations.third_party.alu.rpc import GetConfiguration, LoadConfiguration, ShowCLI +from ncclient.xml_ import BASE_NS_1_0 + + +def remove_namespaces(xml): + + for elem in xml.getiterator(): + if elem.tag is etree.Comment: + continue + i = elem.tag.find('}') + if i > 0: + elem.tag = elem.tag[i + 1:] + + etree.cleanup_namespaces(xml) + return xml + class AluDeviceHandler(DefaultDeviceHandler): """ Alcatel-Lucent 7x50 handler for device specific information. """ - + def __init__(self, device_params): super(AluDeviceHandler, self).__init__(device_params) @@ -12,3 +30,21 @@ return [ "urn:ietf:params:netconf:base:1.0", ] + + 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} + + def add_additional_operations(self): + dict = {} + dict["get_configuration"] = GetConfiguration + dict["show_cli"] = ShowCLI + dict["load_configuration"] = LoadConfiguration + return dict + + def transform_reply(self): + return remove_namespaces diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ncclient-0.6.3/ncclient/operations/retrieve.py new/ncclient-0.6.4/ncclient/operations/retrieve.py --- old/ncclient-0.6.3/ncclient/operations/retrieve.py 2018-07-02 19:49:57.000000000 +0200 +++ new/ncclient-0.6.4/ncclient/operations/retrieve.py 2019-04-07 19:42:01.000000000 +0200 @@ -20,25 +20,11 @@ from ncclient.operations import util -_VALID_WITH_DEFAULTS = [ - "explicit", - "report-all", - "report-all-tagged", - "trim" -] class WithDefaultsError(OperationError): - """Raised when an invalid "with-defaults" option is specified in a Get or - GetConfig request""" + """Invalid 'with-defaults' mode or capability URI""" - def __init__(self, invalid_mode): - super(WithDefaultsError, self).__init__( - "Invalid 'with-defaults' mode '{provided}', must be one of the " - "following: {options}".format( - provided=invalid_mode, - options=', '.join(_VALID_WITH_DEFAULTS) - )) class GetReply(RPCReply): @@ -97,14 +83,57 @@ node.append(util.build_filter(filter)) if with_defaults is not None: self._assert(":with-defaults") - _append_with_defaults(node, with_defaults) + _append_with_defaults_mode( + node, + with_defaults, + self._session.server_capabilities, + ) return self._request(node) -def _append_with_defaults(node, with_defaults): - if with_defaults.strip().lower() not in _VALID_WITH_DEFAULTS: - raise WithDefaultsError(with_defaults) - with_defaults_ele = sub_ele_ns(node, "with-defaults", NETCONF_WITH_DEFAULTS_NS) - with_defaults_ele.text = with_defaults + +def _append_with_defaults_mode(node, mode, capabilities): + _validate_with_defaults_mode(mode, capabilities) + with_defaults_element = sub_ele_ns( + node, + "with-defaults", + NETCONF_WITH_DEFAULTS_NS, + ) + with_defaults_element.text = mode + + +def _validate_with_defaults_mode(mode, capabilities): + valid_modes = _get_valid_with_defaults_modes(capabilities) + if mode.strip().lower() not in valid_modes: + raise WithDefaultsError( + "Invalid 'with-defaults' mode '{provided}'; the server only " + "supports the following: {options}".format( + provided=mode, + options=', '.join(valid_modes) + ) + ) + + +def _get_valid_with_defaults_modes(capabilities): + """Reference: https://tools.ietf.org/html/rfc6243#section-4.3""" + capability = capabilities[":with-defaults"] + + try: + valid_modes = [capability.parameters["basic-mode"]] + except KeyError: + raise WithDefaultsError( + "Invalid 'with-defaults' capability URI advertised by the server; " + "missing 'basic-mode' parameter" + ) + + try: + also_supported = capability.parameters["also-supported"] + except KeyError: + return valid_modes + + valid_modes.extend(also_supported.split(",")) + + return valid_modes + class GetConfig(RPC): @@ -129,7 +158,11 @@ node.append(util.build_filter(filter)) if with_defaults is not None: self._assert(":with-defaults") - _append_with_defaults(node, with_defaults) + _append_with_defaults_mode( + node, + with_defaults, + self._session.server_capabilities, + ) return self._request(node) class GetSchema(RPC): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ncclient-0.6.3/ncclient/operations/third_party/alu/rpc.py new/ncclient-0.6.4/ncclient/operations/third_party/alu/rpc.py --- old/ncclient-0.6.3/ncclient/operations/third_party/alu/rpc.py 1970-01-01 01:00:00.000000000 +0100 +++ new/ncclient-0.6.4/ncclient/operations/third_party/alu/rpc.py 2019-04-07 15:39:58.000000000 +0200 @@ -0,0 +1,80 @@ +# by Pasi Sikala <pasi.sik...@elisa.fi> + +from ncclient.xml_ import * + +from ncclient.operations.rpc import RPC +from ncclient.operations import util + + +class ShowCLI(RPC): + def request(self, command=None): + """Run CLI -show commands + *command* (show) command to run + + """ + node = new_ele('get') + filter = sub_ele(node, 'filter') + block = sub_ele(filter, 'oper-data-format-cli-block') + sub_ele(block, 'cli-show').text = command + + return self._request(node) + + +class GetConfiguration(RPC): + + def request(self, content='xml', filter=None, detail=False): + """Get config from Alu router + *content* Content layer. cli or xml + *filter* specifies the portion of the configuration to retrieve (by default entire configuration is retrieved) + *detail* Show detailed config in CLI -layer""" + + node = new_ele('get-config') + node.append(util.datastore_or_url('source', 'running', self._assert)) + + if filter is not None: + + if content == 'xml': + node.append(util.build_filter(('subtree', filter))) + + elif content == 'cli': + rep = new_ele('filter') + sub_filter = sub_ele(rep, 'config-format-cli-block') + + if filter is not None: + for item in filter: + if detail: + sub_ele(sub_filter, 'cli-info-detail').text = item + else: + sub_ele(sub_filter, 'cli-info').text = item + else: + if detail: + sub_ele(sub_filter, 'cli-info-detail') + else: + sub_ele(sub_filter, 'cli-info') + + node.append(validated_element(rep)) + + return self._request(node) + + +class LoadConfiguration(RPC): + + def request(self, format='xml', default_operation=None, target='running', config=None): + node = new_ele('edit-config') + config_node = new_ele('config') + + if default_operation is not None: + # TODO: check if it is a valid default-operation + sub_ele(node, "default-operation").text = default_operation + + if config is not None: + if format == 'xml': + node.append(util.datastore_or_url('target', target, self._assert)) + config_node.append(config) + + if format == 'cli': + node.append(util.datastore_or_url('target', 'running', self._assert)) + sub_ele(config_node, 'config-format-cli-block').text = config + + node.append(config_node) + return self._request(node) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ncclient-0.6.3/ncclient/operations/third_party/juniper/rpc.py new/ncclient-0.6.4/ncclient/operations/third_party/juniper/rpc.py --- old/ncclient-0.6.3/ncclient/operations/third_party/juniper/rpc.py 2018-07-02 19:49:57.000000000 +0200 +++ new/ncclient-0.6.4/ncclient/operations/third_party/juniper/rpc.py 2019-04-07 15:39:58.000000000 +0200 @@ -35,8 +35,8 @@ return self._request(node) class CompareConfiguration(RPC): - def request(self, rollback=0): - node = new_ele('get-configuration', {'compare':'rollback', 'rollback':str(rollback)}) + def request(self, rollback=0, format='text'): + node = new_ele('get-configuration', {'compare':'rollback', 'format':format, 'rollback':str(rollback)}) return self._request(node) class ExecuteRpc(RPC): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ncclient-0.6.3/ncclient/operations/util.py new/ncclient-0.6.4/ncclient/operations/util.py --- old/ncclient-0.6.3/ncclient/operations/util.py 2018-07-02 19:49:57.000000000 +0200 +++ new/ncclient-0.6.4/ncclient/operations/util.py 2019-04-07 15:39:58.000000000 +0200 @@ -58,7 +58,8 @@ raise OperationError("Invalid filter type") else: - rep = validated_element(spec, ("filter", qualify("filter"))) + rep = validated_element(spec, ("filter", qualify("filter"), + qualify("filter", ns=NETCONF_NOTIFICATION_NS))) # results in XMLError: line 105 ncclient/xml_.py - commented by earies - 5/10/13 #rep = validated_element(spec, ("filter", qualify("filter")), # attrs=("type",)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ncclient-0.6.3/ncclient/transport/ssh.py new/ncclient-0.6.4/ncclient/transport/ssh.py --- old/ncclient-0.6.3/ncclient/transport/ssh.py 2018-09-26 20:11:09.000000000 +0200 +++ new/ncclient-0.6.4/ncclient/transport/ssh.py 2019-04-07 15:39:58.000000000 +0200 @@ -13,13 +13,14 @@ # See the License for the specific language governing permissions and # limitations under the License. +import base64 +import getpass import os +import re +import six import sys import socket -import getpass -import re import threading -import base64 from binascii import hexlify try: @@ -59,7 +60,7 @@ # * result.group(1) will contain the digit string for a chunk # * result.group(2) will be defined if '##' found # -RE_NC11_DELIM = re.compile(r'\n(?:#([0-9]+)|(##))\n') +RE_NC11_DELIM = re.compile(br'\n(?:#([0-9]+)|(##))\n') def default_unknown_host_cb(host, fingerprint): @@ -190,7 +191,7 @@ while True and start < data_len: # match to see if we found at least some kind of delimiter self.logger.debug('_parse11: matching from %d bytes from start of buffer', start) - re_result = RE_NC11_DELIM.match(data[start:].decode('utf-8')) + re_result = RE_NC11_DELIM.match(data[start:]) if not re_result: # not found any kind of delimiter just break; this should only @@ -349,7 +350,21 @@ if ssh_config is not None: config = paramiko.SSHConfig() config.parse(open(os.path.expanduser(ssh_config))) + + # Save default Paramiko SSH port so it can be reverted + paramiko_default_ssh_port = paramiko.config.SSH_PORT + + # Change the default SSH port to the port specified by the user so expand_variables + # replaces %p with the passed in port rather than 22 (the defauld paramiko.config.SSH_PORT) + + paramiko.config.SSH_PORT = port + config = config.lookup(host) + + # paramiko.config.SSHconfig::expand_variables is called by lookup so we can set the SSH port + # back to the default + paramiko.config.SSH_PORT = paramiko_default_ssh_port + host = config.get("hostname", host) if username is None: username = config.get("user") @@ -364,8 +379,14 @@ username = getpass.getuser() if sock_fd is None: - if config.get("proxycommand"): - sock = paramiko.proxy.ProxyCommand(config.get("proxycommand")) + proxycommand = config.get("proxycommand") + if proxycommand: + self.logger.debug("Configuring Proxy. %s", proxycommand) + if not isinstance(proxycommand, six.string_types): + proxycommand = [os.path.expanduser(elem) for elem in proxycommand] + else: + proxycommand = os.path.expanduser(proxycommand) + sock = paramiko.proxy.ProxyCommand(proxycommand) else: for res in socket.getaddrinfo(host, port, socket.AF_UNSPEC, socket.SOCK_STREAM): af, socktype, proto, canonname, sa = res diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ncclient-0.6.3/ncclient/xml_.py new/ncclient-0.6.4/ncclient/xml_.py --- old/ncclient-0.6.3/ncclient/xml_.py 2018-09-19 10:52:16.000000000 +0200 +++ new/ncclient-0.6.4/ncclient/xml_.py 2019-04-07 15:39:58.000000000 +0200 @@ -69,6 +69,8 @@ NETCONF_NOTIFICATION_NS = "urn:ietf:params:xml:ns:netconf:notification:1.0" #: Namespace for netconf with-defaults (RFC 6243) NETCONF_WITH_DEFAULTS_NS = "urn:ietf:params:xml:ns:yang:ietf-netconf-with-defaults" +#: Namespace for Alcatel-Lucent +ALU_CONFIG = "urn:alcatel-lucent.com:sros:ns:yang:conf-r13" # try: register_namespace = etree.register_namespace diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ncclient-0.6.3/ncclient.egg-info/PKG-INFO new/ncclient-0.6.4/ncclient.egg-info/PKG-INFO --- old/ncclient-0.6.3/ncclient.egg-info/PKG-INFO 2018-09-26 20:17:34.000000000 +0200 +++ new/ncclient-0.6.4/ncclient.egg-info/PKG-INFO 2019-04-07 19:45:29.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 1.2 Name: ncclient -Version: 0.6.3 +Version: 0.6.4 Summary: Python library for NETCONF clients Home-page: https://github.com/ncclient/ncclient Author: Shikhar Bhushan, Leonidas Poulopoulos, Ebben Aries, Einar Nilsen-Nygaard diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ncclient-0.6.3/ncclient.egg-info/SOURCES.txt new/ncclient-0.6.4/ncclient.egg-info/SOURCES.txt --- old/ncclient-0.6.3/ncclient.egg-info/SOURCES.txt 2018-09-26 20:17:34.000000000 +0200 +++ new/ncclient-0.6.4/ncclient.egg-info/SOURCES.txt 2019-04-07 19:45:29.000000000 +0200 @@ -28,6 +28,8 @@ examples/nc07.py examples/nc08.py examples/nxosapi.py +examples/alu/edit_config.py +examples/alu/get_config.py examples/juniper/command-jnpr.py examples/juniper/compare-config-jnpr.py examples/juniper/delete-config-jnpr.py @@ -90,6 +92,8 @@ ncclient/operations/subscribe.py ncclient/operations/util.py ncclient/operations/third_party/__init__.py +ncclient/operations/third_party/alu/__init__.py +ncclient/operations/third_party/alu/rpc.py ncclient/operations/third_party/h3c/__init__.py ncclient/operations/third_party/h3c/rpc.py ncclient/operations/third_party/hpcomware/__init__.py diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ncclient-0.6.3/ncclient.egg-info/requires.txt new/ncclient-0.6.4/ncclient.egg-info/requires.txt --- old/ncclient-0.6.3/ncclient.egg-info/requires.txt 2018-09-26 20:17:34.000000000 +0200 +++ new/ncclient-0.6.4/ncclient.egg-info/requires.txt 2019-04-07 19:45:29.000000000 +0200 @@ -1,5 +1,7 @@ setuptools>0.6 paramiko>=1.15.0 lxml>=3.3.0 -selectors2>=2.0.1 six + +[:python_version <= "3.4"] +selectors2>=2.0.1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ncclient-0.6.3/requirements.txt new/ncclient-0.6.4/requirements.txt --- old/ncclient-0.6.3/requirements.txt 2018-08-17 19:52:37.000000000 +0200 +++ new/ncclient-0.6.4/requirements.txt 2019-04-07 15:39:58.000000000 +0200 @@ -1,5 +1,5 @@ setuptools>0.6 paramiko>=1.15.0 lxml>=3.3.0 -selectors2>=2.0.1 +selectors2>=2.0.1; python_version <= '3.4' six ++++++ sphinx-use-imgmath-extension.patch ++++++ --- docs/source/conf.py +++ docs/source/conf.py @@ -22,7 +22,7 @@ # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.pngmath', 'sphinx.ext.ifconfig'] +extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.imgmath', 'sphinx.ext.ifconfig'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates']