summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorA. Wilcox <AWilcox@Wilcox-Tech.com>2020-12-02 20:36:24 -0600
committerA. Wilcox <AWilcox@Wilcox-Tech.com>2020-12-02 20:36:24 -0600
commitb3ca4b49ef72724a6fc1eb13453cb7aee9960756 (patch)
tree915348d4318dc302aab076951cbb11700e8791e6
parenta3957e1ec655462fabcfa39399fbe83cb8a44cb4 (diff)
downloadnetconfapk-b3ca4b49ef72724a6fc1eb13453cb7aee9960756.tar.gz
netconfapk-b3ca4b49ef72724a6fc1eb13453cb7aee9960756.tar.bz2
netconfapk-b3ca4b49ef72724a6fc1eb13453cb7aee9960756.tar.xz
netconfapk-b3ca4b49ef72724a6fc1eb13453cb7aee9960756.zip
ietf-ip: Add WIP module
-rw-r--r--ncserver/module/ip.py207
1 files changed, 207 insertions, 0 deletions
diff --git a/ncserver/module/ip.py b/ncserver/module/ip.py
new file mode 100644
index 0000000..065a4d4
--- /dev/null
+++ b/ncserver/module/ip.py
@@ -0,0 +1,207 @@
+"""
+NETCONF for APK Distributions server:
+ ietf-ip module
+
+Copyright © 2020 Adélie Software in the Public Benefit, Inc.
+
+Released under the terms of the NCSA license. See the LICENSE file included
+with this source distribution for more information.
+
+SPDX-License-Identifier: NCSA
+"""
+
+import logging
+
+from lxml import etree
+from netconf import util
+
+from ncserver.base.modman import MODMAN
+from ncserver.base.util import _
+
+
+QName = etree.QName # pylint: disable=I1101
+
+
+LOGGER = logging.getLogger(__name__)
+"""The object used for logging informational messages."""
+
+
+M_ABI_VERSION = 1
+"""The ABI version of this NETCONF module."""
+
+
+M_PREFIX = "ip"
+"""The XML tag prefix for this module's tags."""
+
+
+M_NS = "urn:ietf:params:xml:ns:yang:ietf-ip"
+"""The XML namespace for this module."""
+
+
+M_NAME = "ietf-ip"
+"""The YANG model name for this module."""
+
+
+M_REVISION = "2018-02-22"
+"""The YANG revision date for this module."""
+
+
+M_IMPORTS = {
+ 'ietf-interfaces@2018-02-20': {
+ 'ns': "urn:ietf:params:xml:ns:yang:ietf-interfaces", 'prefix': "if"
+ },
+ 'iana-inet-types@2013-07-15': {
+ 'ns': "urn:ietf:params:xml:ns:yang:iana-inet-types", 'prefix': "inet"
+ },
+ 'ietf-yang-types@2013-07-15': {
+ 'ns': "urn:ietf:params:xml:ns:yang:ietf-yang-types", 'prefix': "yang"
+ }
+}
+"""The imported YANG modules for this module."""
+
+
+M_FEATURES = ('ipv6-privacy-autoconf',)
+"""The supported features declared in YANG for this module."""
+
+
+IF_NS = "urn:ietf:params:xml:ns:yang:ietf-interfaces"
+"""The namespace of the ietf-interfaces module."""
+
+
+M_AUGMENTS = (IF_NS,)
+"""The namespaces that this YANG module augments."""
+
+
+def _get_ifaces(node):
+ """Retrieve the /if:interfaces node."""
+ ifaces = node.find('{'+IF_NS+'}interfaces')
+ if ifaces is None:
+ LOGGER.error(_("interfaces node not found: "
+ "This module requires ietf-interfaces to be loaded"))
+
+ return ifaces
+
+
+def _get_nmsa():
+ """Retrieve our NMSA module handle."""
+ nmsa_ns = "http://netconf.adelielinux.org/ns/netmgmt"
+ nmsa = MODMAN._module_for_ns(nmsa_ns) # pylint: disable=W0212
+
+ return nmsa
+
+
+def from_bool(value: bool) -> str:
+ """Turn a Python bool into an XML bool."""
+ return str(value).lower()
+
+
+def _add_ipv4(iface, getter):
+ """Add IPv4 configuration nodes."""
+ name = iface.find('{'+IF_NS+'}name').text
+ ipv4 = util.subelm(iface, 'ip:ipv4')
+ ipv4.append(util.leaf_elm('ip:enabled',
+ from_bool(getter(name, 'ipv4_enabled'))))
+ ipv4.append(util.leaf_elm('ip:forwarding',
+ from_bool(getter(name, 'ipv4_forwarding'))))
+ v4mtu = getter(name, 'ipv4_mtu')
+ if v4mtu is not None:
+ ipv4.append(util.leaf_elm('ip:mtu', v4mtu))
+
+ return ipv4
+
+
+def _add_ipv6(iface, getter):
+ """Add IPv6 configuration nodes."""
+ name = iface.find('{'+IF_NS+'}name').text
+ ipv6 = util.subelm(iface, 'ip:ipv6')
+ ipv6.append(util.leaf_elm('ip:enabled',
+ from_bool(getter(name, 'ipv6_enabled'))))
+ ipv6.append(util.leaf_elm('ip:forwarding',
+ from_bool(getter(name, 'ipv6_forwarding'))))
+ v6mtu = getter(name, 'ipv6_mtu')
+ if v6mtu is not None:
+ ipv6.append(util.leaf_elm('ip:mtu', v6mtu))
+ ipv6.append(
+ util.leaf_elm('ip:dup-addr-detect-transmits',
+ getter(name, 'ipv6_dad_xmit'))
+ )
+ if any((getter(name, 'ipv6_slaac_globaladdr'),
+ getter(name, 'ipv6_slaac_tempaddr'))):
+ autoconf = util.subelm(ipv6, 'ip:autoconf')
+ autoconf.append(util.leaf_elm('ip:create-global-addresses',
+ from_bool(
+ getter(name, 'ipv6_slaac_globaladdr')
+ )))
+ autoconf.append(util.leaf_elm('ip:create-temporary-addresses',
+ from_bool(
+ getter(name, 'ipv6_slaac_tempaddr')
+ )))
+ autoconf.append(util.leaf_elm('ip:temporary-valid-lifetime',
+ getter(name, 'ipv6_slaac_validlft')))
+ autoconf.append(util.leaf_elm('ip:temporary-preferred-lifetime',
+ getter(name, 'ipv6_slaac_preflft')))
+
+ return ipv6
+
+
+def running(node):
+ """Retrieve the IP configuration for this device."""
+ ifaces = _get_ifaces(node)
+ nmsa = _get_nmsa()
+
+ if None in (ifaces, nmsa):
+ # We can't retrieve configuration unless both the ietf-interfaces and
+ # the NMSA module is loaded.
+ return
+
+ for iface in ifaces.iterchildren():
+ name = iface.find('{'+IF_NS+'}name').text
+
+ # IPv4
+ ipv4 = _add_ipv4(iface, nmsa.get_param)
+ for address in nmsa.list_addresses(name):
+ # Only IPv4 addresses count.
+ if '.' not in address:
+ continue
+
+ ipaddr, subnet = address.split('/')
+
+ addr = util.subelm(ipv4, 'ip:address')
+ addr.append(util.leaf_elm('ip:ip', ipaddr))
+ addr.append(util.leaf_elm('ip:prefix-length', subnet))
+ # No neighbor support.
+
+ # IPv6
+ ipv6 = _add_ipv6(iface, nmsa.get_param)
+ for address in nmsa.list_addresses(name):
+ # Only IPv6 addesses count.
+ if ':' not in address:
+ continue
+
+ ipaddr, length = address.split('/')
+
+ addr = util.subelm(ipv6, 'ip:address')
+ addr.append(util.leaf_elm('ip:ip', ipaddr))
+ addr.append(util.leaf_elm('ip:prefix-length', length))
+ # No neighbor support.
+
+
+def operational(node):
+ """Retrieve the IP state for this device."""
+ ifaces = _get_ifaces(node)
+ nmsa = _get_nmsa()
+
+ if None in (ifaces, nmsa):
+ # We can't retrieve configuration unless both the ietf-interfaces and
+ # the NMSA module is loaded.
+ return
+
+ for iface in ifaces.iterchildren():
+ # IPv4
+ _add_ipv4(iface, nmsa.curr_param)
+ # IPv6
+ _add_ipv6(iface, nmsa.curr_param)
+
+
+def edit(session, rpc, node, def_op):
+ """Edit the IP configuration for this device."""