summaryrefslogtreecommitdiff
path: root/ncserver/module/nms_ifupdownng.py
diff options
context:
space:
mode:
authorA. Wilcox <AWilcox@Wilcox-Tech.com>2020-11-18 12:50:53 -0600
committerA. Wilcox <AWilcox@Wilcox-Tech.com>2020-11-18 12:50:53 -0600
commitb6098ddf2e634b95f0255fbba78ae047199da4d4 (patch)
tree8c639535d9a9aa221a3fd7888dce9da47c3ec0f0 /ncserver/module/nms_ifupdownng.py
parent340a6a9c4198ff0d2907768580088fa6486c1a08 (diff)
downloadnetconfapk-b6098ddf2e634b95f0255fbba78ae047199da4d4.tar.gz
netconfapk-b6098ddf2e634b95f0255fbba78ae047199da4d4.tar.bz2
netconfapk-b6098ddf2e634b95f0255fbba78ae047199da4d4.tar.xz
netconfapk-b6098ddf2e634b95f0255fbba78ae047199da4d4.zip
ncserver: Add draft NMSA mod for ifupdown-ng
Diffstat (limited to 'ncserver/module/nms_ifupdownng.py')
-rw-r--r--ncserver/module/nms_ifupdownng.py201
1 files changed, 201 insertions, 0 deletions
diff --git a/ncserver/module/nms_ifupdownng.py b/ncserver/module/nms_ifupdownng.py
new file mode 100644
index 0000000..9066a18
--- /dev/null
+++ b/ncserver/module/nms_ifupdownng.py
@@ -0,0 +1,201 @@
+"""
+NETCONF for APK Distributions server:
+ Network Management System abstraction module for ifupdown-ng
+
+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
+import subprocess
+import yaml
+
+from ncserver.base.util import _
+
+
+LOGGER = logging.getLogger(__name__)
+"""The object used for logging informational messages."""
+
+
+M_ABI_VERSION = 1
+"""The ABI version of this NETCONF module."""
+
+
+M_PREFIX = "nmsa"
+"""The XML tag prefix for this module's tags."""
+
+
+M_NS = "http://netconf.adelielinux.org/ns/netmgmt"
+"""The XML namespace for this module."""
+
+
+M_NAME = "adelie-nms-abstract"
+"""The YANG model name for this module."""
+
+
+M_REVISION = "2020-11-18"
+"""The YANG revision date for this module."""
+
+
+_CONFIG = dict()
+"""The internal configuration handle."""
+
+
+_TRANSACTION = False
+"""Determines if a transaction is in progress."""
+
+
+def _load_config():
+ """Load the current active configuration from /e/n/i."""
+ global _CONFIG # pylint: disable=W0603
+
+ # Won't load during a transaction.
+ if _TRANSACTION:
+ LOGGER.warning(_("attempted to load eni config during transaction"))
+ return
+
+ result = None
+ try:
+ result = subprocess.run(['/sbin/ifupdown', 'ifparse', '-AF',
+ 'yaml-raw'],
+ stdout=subprocess.PIPE, check=False)
+ except OSError:
+ LOGGER.error(_("ifupdown-ng may not be installed properly"))
+ return
+
+ if result.returncode != 0:
+ LOGGER.error(_("ifparse returned error %d"), result.returncode)
+ return
+
+ rawyaml = result.stdout.decode('utf-8')
+ _CONFIG = yaml.safe_load(rawyaml)
+
+
+def _save():
+ """Save changes to the configuration."""
+ eni = ""
+ for iface in _CONFIG.keys():
+ buf = "iface " + iface + "\n"
+ for item in _CONFIG[iface]:
+ for key, val in item.items():
+ if key == 'auto' and \
+ val == True or val.lower()[0] == 't':
+ buf = "auto " + iface + "\n" + buf
+ continue
+ if isinstance(val, bool):
+ val = str(val).lower()
+ buf += " "
+ buf += str(key) + " " + str(val)
+ buf += "\n"
+ eni += buf + "\n"
+
+ with open('/etc/network/interfaces', 'w') as conf_file:
+ # snip last double-\n off
+ conf_file.write(eni[:-1])
+
+
+def interface_list():
+ """Return a list of configured interfaces."""
+ _load_config()
+ return tuple(_CONFIG.keys())
+
+
+def begin_transaction():
+ """Begin a transaction."""
+ global _TRANSACTION # pylint: disable=W0603
+
+ if _TRANSACTION:
+ LOGGER.error(_("attempt to nest transactions"))
+ return
+
+ _TRANSACTION = True
+
+
+def commit():
+ """Commit any outstanding operations."""
+ global _TRANSACTION # pylint: disable=W0603
+
+ if not _TRANSACTION:
+ LOGGER.warning(_("commit when no transaction is in progress"))
+
+ _save()
+ _TRANSACTION = False
+
+
+def get_param(iface: str, parameter: str):
+ """Retrieve the parameter for the specified interface."""
+ if iface not in _CONFIG.keys():
+ LOGGER.warning(
+ _("requested parameter %s for non-existant interface %s"),
+ parameter, iface
+ )
+ return None
+
+ # implement this.
+ raise NotImplementedError
+
+
+def set_param(iface: str, parameter: str, value):
+ """Set the parameter for the specified interface."""
+ if iface not in _CONFIG.keys():
+ LOGGER.warning(
+ _("attempted to set parameter %s for non-existant interface %s"),
+ parameter, iface
+ )
+ return
+
+ # implement this.
+ raise NotImplementedError
+
+
+def unset_param(iface: str, parameter: str):
+ """Unset the parameter for the specified interface."""
+ if iface not in _CONFIG.keys():
+ LOGGER.warning(
+ _("attempted to unset parameter %s for non-existant interface %s"),
+ parameter, iface
+ )
+ return
+
+ # implement this.
+ raise NotImplementedError
+
+
+def list_addresses(iface: str) -> list:
+ """Retrieve all configured addresses for the specified interface."""
+ if iface not in _CONFIG.keys():
+ LOGGER.warning(_("requested addresses for non-existant interface %s"),
+ iface)
+ return list()
+
+ # implement this.
+ raise NotImplementedError
+
+
+def add_address(iface: str, _type, addr: str, prefix):
+ """Add an address of the specified ``type`` to the specified interface."""
+ if iface not in _CONFIG.keys():
+ LOGGER.warning(
+ _("attempted to add address to non-existant interface %s"), iface
+ )
+ return
+
+ # implement this.
+ raise NotImplementedError
+
+
+def remove_address(iface: str, addr: str):
+ """Remove an address from the specified interface."""
+ if iface not in _CONFIG.keys():
+ LOGGER.warning(
+ _("attempted to remove address from non-existant interface %s"),
+ iface
+ )
+ return
+
+ # implement this.
+ raise NotImplementedError