summaryrefslogtreecommitdiff
path: root/cloudinit/config/cc_refresh_rmc_and_interface.py
diff options
context:
space:
mode:
authorAman306 <45781773+Aman306@users.noreply.github.com>2020-10-28 23:36:09 +0530
committerGitHub <noreply@github.com>2020-10-28 14:06:09 -0400
commitf99d4f96b00a9cfec1c721d364cbfd728674e5dc (patch)
tree22ec9e84009de46348b3df681007ec1f94de51f1 /cloudinit/config/cc_refresh_rmc_and_interface.py
parent29f0d136e24826a9b1c2c541755c64c4e51d5847 (diff)
downloadvyos-cloud-init-f99d4f96b00a9cfec1c721d364cbfd728674e5dc.tar.gz
vyos-cloud-init-f99d4f96b00a9cfec1c721d364cbfd728674e5dc.zip
Add config modules for controlling IBM PowerVM RMC. (#584)
Reliable Scalable Cluster Technology (RSCT) is a set of software components that together provide a comprehensive clustering environment(RAS features) for IBM PowerVM based virtual machines. RSCT includes the Resource Monitoring and Control (RMC) subsystem. RMC is a generalized framework used for managing, monitoring, and manipulating resources. RMC runs as a daemon process on individual machines and needs creation of unique node id and restarts during VM boot. LP: #1895979 Co-authored-by: Scott Moser <smoser@brickies.net>
Diffstat (limited to 'cloudinit/config/cc_refresh_rmc_and_interface.py')
-rw-r--r--cloudinit/config/cc_refresh_rmc_and_interface.py159
1 files changed, 159 insertions, 0 deletions
diff --git a/cloudinit/config/cc_refresh_rmc_and_interface.py b/cloudinit/config/cc_refresh_rmc_and_interface.py
new file mode 100644
index 00000000..146758ad
--- /dev/null
+++ b/cloudinit/config/cc_refresh_rmc_and_interface.py
@@ -0,0 +1,159 @@
+# (c) Copyright IBM Corp. 2020 All Rights Reserved
+#
+# Author: Aman Kumar Sinha <amansi26@in.ibm.com>
+#
+# This file is part of cloud-init. See LICENSE file for license information.
+
+"""
+Refresh IPv6 interface and RMC
+------------------------------
+**Summary:** Ensure Network Manager is not managing IPv6 interface
+
+This module is IBM PowerVM Hypervisor specific
+
+Reliable Scalable Cluster Technology (RSCT) is a set of software components
+that together provide a comprehensive clustering environment(RAS features)
+for IBM PowerVM based virtual machines. RSCT includes the Resource
+Monitoring and Control (RMC) subsystem. RMC is a generalized framework used
+for managing, monitoring, and manipulating resources. RMC runs as a daemon
+process on individual machines and needs creation of unique node id and
+restarts during VM boot.
+More details refer
+https://www.ibm.com/support/knowledgecenter/en/SGVKBA_3.2/admin/bl503_ovrv.htm
+
+This module handles
+- Refreshing RMC
+- Disabling NetworkManager from handling IPv6 interface, as IPv6 interface
+ is used for communication between RMC daemon and PowerVM hypervisor.
+
+**Internal name:** ``cc_refresh_rmc_and_interface``
+
+**Module frequency:** per always
+
+**Supported distros:** RHEL
+
+"""
+
+from cloudinit import log as logging
+from cloudinit.settings import PER_ALWAYS
+from cloudinit import util
+from cloudinit import subp
+from cloudinit import netinfo
+
+import errno
+
+frequency = PER_ALWAYS
+
+LOG = logging.getLogger(__name__)
+# Ensure that /opt/rsct/bin has been added to standard PATH of the
+# distro. The symlink to rmcctrl is /usr/sbin/rsct/bin/rmcctrl .
+RMCCTRL = 'rmcctrl'
+
+
+def handle(name, _cfg, _cloud, _log, _args):
+ if not subp.which(RMCCTRL):
+ LOG.debug("No '%s' in path, disabled", RMCCTRL)
+ return
+
+ LOG.debug(
+ 'Making the IPv6 up explicitly. '
+ 'Ensuring IPv6 interface is not being handled by NetworkManager '
+ 'and it is restarted to re-establish the communication with '
+ 'the hypervisor')
+
+ ifaces = find_ipv6_ifaces()
+
+ # Setting NM_CONTROLLED=no for IPv6 interface
+ # making it down and up
+
+ if len(ifaces) == 0:
+ LOG.debug("Did not find any interfaces with ipv6 addresses.")
+ else:
+ for iface in ifaces:
+ refresh_ipv6(iface)
+ disable_ipv6(sysconfig_path(iface))
+ restart_network_manager()
+
+
+def find_ipv6_ifaces():
+ info = netinfo.netdev_info()
+ ifaces = []
+ for iface, data in info.items():
+ if iface == "lo":
+ LOG.debug('Skipping localhost interface')
+ if len(data.get("ipv4", [])) != 0:
+ # skip this interface, as it has ipv4 addrs
+ continue
+ ifaces.append(iface)
+ return ifaces
+
+
+def refresh_ipv6(interface):
+ # IPv6 interface is explicitly brought up, subsequent to which the
+ # RMC services are restarted to re-establish the communication with
+ # the hypervisor.
+ subp.subp(['ip', 'link', 'set', interface, 'down'])
+ subp.subp(['ip', 'link', 'set', interface, 'up'])
+
+
+def sysconfig_path(iface):
+ return '/etc/sysconfig/network-scripts/ifcfg-' + iface
+
+
+def restart_network_manager():
+ subp.subp(['systemctl', 'restart', 'NetworkManager'])
+
+
+def disable_ipv6(iface_file):
+ # Ensuring that the communication b/w the hypervisor and VM is not
+ # interrupted due to NetworkManager. For this purpose, as part of
+ # this function, the NM_CONTROLLED is explicitly set to No for IPV6
+ # interface and NetworkManager is restarted.
+ try:
+ contents = util.load_file(iface_file)
+ except IOError as e:
+ if e.errno == errno.ENOENT:
+ LOG.debug("IPv6 interface file %s does not exist\n",
+ iface_file)
+ else:
+ raise e
+
+ if 'IPV6INIT' not in contents:
+ LOG.debug("Interface file %s did not have IPV6INIT", iface_file)
+ return
+
+ LOG.debug("Editing interface file %s ", iface_file)
+
+ # Dropping any NM_CONTROLLED or IPV6 lines from IPv6 interface file.
+ lines = contents.splitlines()
+ lines = [line for line in lines if not search(line)]
+ lines.append("NM_CONTROLLED=no")
+
+ with open(iface_file, "w") as fp:
+ fp.write("\n".join(lines) + "\n")
+
+
+def search(contents):
+ # Search for any NM_CONTROLLED or IPV6 lines in IPv6 interface file.
+ return(
+ contents.startswith("IPV6ADDR") or
+ contents.startswith("IPADDR6") or
+ contents.startswith("IPV6INIT") or
+ contents.startswith("NM_CONTROLLED"))
+
+
+def refresh_rmc():
+ # To make a healthy connection between RMC daemon and hypervisor we
+ # refresh RMC. With refreshing RMC we are ensuring that making IPv6
+ # down and up shouldn't impact communication between RMC daemon and
+ # hypervisor.
+ # -z : stop Resource Monitoring & Control subsystem and all resource
+ # managers, but the command does not return control to the user
+ # until the subsystem and all resource managers are stopped.
+ # -s : start Resource Monitoring & Control subsystem.
+ try:
+ subp.subp([RMCCTRL, '-z'])
+ subp.subp([RMCCTRL, '-s'])
+ except Exception:
+ util.logexc(LOG, 'Failed to refresh the RMC subsystem.')
+ raise