From bf9472c312ca47e4a8ea2b70ca5cf5c1c6f34d4e Mon Sep 17 00:00:00 2001
From: Ben Morrice <ben.morrice@cern.ch>
Date: Thu, 18 Mar 2021 15:16:00 +0100
Subject: [PATCH] Add support for CS8 - Fix broken C8 - use dnf-automatic on 8
 family systems

---
 cern-anaconda-addon.spec                      |   6 +-
 src/cern_customizations/constants.py          |   2 +-
 .../gui/spokes/cern_firstboot.py              |   6 +-
 src/cern_customizations/ks/cern.py            | 123 ++++++++++--------
 4 files changed, 78 insertions(+), 59 deletions(-)

diff --git a/cern-anaconda-addon.spec b/cern-anaconda-addon.spec
index 0a54041..3f598c0 100644
--- a/cern-anaconda-addon.spec
+++ b/cern-anaconda-addon.spec
@@ -1,5 +1,5 @@
 Name:       cern-anaconda-addon
-Version:    1.7
+Version:    1.8
 Release:    1%{?dist}
 Summary:    CERN configuration anaconda addon
 
@@ -31,6 +31,10 @@ install -p -m 644 data/cern.svg %{buildroot}/%{_datadir}/icons/hicolor/scalable/
 %doc LICENSE README.md
 
 %changelog
+* Thu Mar 18 2021 Ben Morrice <ben.morrice@cern.ch> - 1.8-1
+- Add support for CentOS Stream 8
+- Use dnf-automatic instead of yum-autoupdate on 8 family systems
+
 * Tue Jan 28 2020 Ben Morrice <ben.morrice@cern.ch> - 1.7-1
 - Add support for C8
 
diff --git a/src/cern_customizations/constants.py b/src/cern_customizations/constants.py
index 0b77abe..ae6ff50 100644
--- a/src/cern_customizations/constants.py
+++ b/src/cern_customizations/constants.py
@@ -1,4 +1,4 @@
-release=open('/etc/redhat-release','r').read().split(' ')[3].split('.')[0]
+release=open('/etc/redhat-release','r').read().split(' ')[3].split('.')[0].rstrip()
 if release == '8':
     # to be adjusted later, postfix and dnsmasq
     LOCMAP_CORE_MODULES = ["ssh", "sudo", "chrony", "kerberos", "lpadmin"]
diff --git a/src/cern_customizations/gui/spokes/cern_firstboot.py b/src/cern_customizations/gui/spokes/cern_firstboot.py
index a1b1610..91c863e 100644
--- a/src/cern_customizations/gui/spokes/cern_firstboot.py
+++ b/src/cern_customizations/gui/spokes/cern_firstboot.py
@@ -28,8 +28,8 @@ class CernSpoke(FirstbootOnlySpokeMixIn, NormalSpoke):
     icon = "applications-science-symbolic"
     title = N_("_CERN CUSTOMIZATIONS")
 
-    def __init__(self, data, storage, payload, instclass):
-        NormalSpoke.__init__(self, data, storage, payload, instclass)
+    def __init__(self, data, storage, payload):
+        NormalSpoke.__init__(self, data, storage, payload)
 
     def initialize(self):
         NormalSpoke.initialize(self)
@@ -143,4 +143,4 @@ class CernFirstbootDialog(GUIObject):
         ret = self.window.run()
         self.window.destroy()
 
-        return ret
\ No newline at end of file
+        return ret
diff --git a/src/cern_customizations/ks/cern.py b/src/cern_customizations/ks/cern.py
index 249e5c6..4c88c8c 100644
--- a/src/cern_customizations/ks/cern.py
+++ b/src/cern_customizations/ks/cern.py
@@ -7,12 +7,25 @@ import sys
 
 from pyanaconda.addons import AddonData
 
+from inspect import signature, Parameter
+AddonDataSetupArgs=[]
+for x, p in signature(AddonData.setup).parameters.items():
+  if p.default == Parameter.empty and p.kind != Parameter.VAR_POSITIONAL:
+    AddonDataSetupArgs.append(x)
+
 # C8
 if (sys.version_info > (3, 0)):
-  from pyanaconda.core.util import getSysroot
+  try:
+    from pyanaconda.core.configuration.anaconda import conf
+    system_root = conf.target.system_root
+  # older versions
+  except:
+    from pyanaconda.core.util import getSysroot
+    system_root = getSysroot()
 # CC7
 else:
   from pyanaconda.iutil import getSysroot
+  system_root = getSysroot()
 from cern_customizations.constants import SYSCONFIG_FILE_PATH, \
             AFS_IS_DEFAULT, EOS_IS_DEFAULT, CVMFS_IS_DEFAULT, \
             AUTOUPDATE_IS_DEFAULT, RUN_IS_DEFAULT, LOCMAP_BIN, \
@@ -24,6 +37,8 @@ from cern_customizations.constants import SYSCONFIG_FILE_PATH, \
 from pykickstart.options import KSOptionParser
 from pykickstart.errors import KickstartParseError, formatErrorMsg
 
+from pykickstart.version import versionToLongString, RHEL8
+
 # export CernData class to prevent Anaconda's collect method from taking
 # # AddonData class instead of the CernData class
 # # :see: pyanaconda.kickstart.AnacondaKSHandler.__init__
@@ -91,39 +106,33 @@ class CernData(AddonData):
         :type args: list
         """
 
-        opc = KSOptionParser()
-        opc.add_option("--afs-client", action="store_true", default=True,
-                       dest="afs", help="Install and configure Openafs client")
-
-        opc.add_option("--auto-update", action="store_true", default=True,
-                       dest="autoupdate", help="Enable automatic system updates")
-
-        opc.add_option("--auto-update-boot", action="store_true", default=False,
-                       dest="autoupdateboot", help="Enable automatic system updates at boot")
+        opc = KSOptionParser(version=RHEL8, description='CERN addon',prog='CERN')
+        opc.add_argument("--afs-client", action="store_true", default=True,
+                       dest="afs", help="Install and configure Openafs client",
+                       version=RHEL8)
 
-        #opc.add_option("--eos-client", action="store_true", default=False,
-        #               dest="eos", help="Install and configure Fuse EOS client")
+        opc.add_argument("--auto-update", action="store_true", default=True,
+                       dest="autoupdate", help="Enable automatic system updates",
+                       version=RHEL8)
 
-        opc.add_option("--cvmfs-client", action="store_true", default=False,
-                       dest="cvmfs", help="Install and configure Fuse CVMFS client")
+        opc.add_argument("--auto-update-boot", action="store_true", default=False,
+                       dest="autoupdateboot", help="Enable automatic system updates at boot",
+                       version=RHEL8)
 
-        opc.add_option("--gnome-initial-setup", action="store_true", default=False,
-                       dest="gnomeinit", help="Run Gnome initial setup after first login")
+        opc.add_argument("--cvmfs-client", action="store_true", default=False,
+                       dest="cvmfs", help="Install and configure Fuse CVMFS client",
+                       version=RHEL8)
 
-        opc.add_option("--run-locmap", action="store_true", default=True,
-                       dest="run", help="Run locmap at firstboot")
-        (opts, extra) = opc.parse_args(args=args, lineno=lineno)
+        opc.add_argument("--gnome-initial-setup", action="store_true", default=False,
+                       dest="gnomeinit", help="Run Gnome initial setup after first login",
+                       version=RHEL8)
 
-        # Reject any additional arguments.
-        if extra:
-            msg = "Unhandled arguments on %s %%addon line for %s" % (self.name, extra)
-            if lineno is not None:
-                raise KickstartParseError(formatErrorMsg(lineno, msg=msg))
-            else:
-                raise KickstartParseError(msg)
+        opc.add_argument("--run-locmap", action="store_true", default=True,
+                       dest="run", help="Run locmap at firstboot",
+                       version=RHEL8)
+        opts = opc.parse_args(args=args, lineno=lineno)
 
         self.afs = opts.afs
-        #self.eos = opts.eos
         self.run = opts.run
         self.cvmfs = opts.cvmfs
         self.autoupdate = opts.autoupdate
@@ -150,7 +159,7 @@ class CernData(AddonData):
         """
         pass
 
-    def setup(self, storage, ksdata, instclass, payload):
+    def setup(AddonDataSetupArgs):
         """
         The setup method that should make changes to the runtime environment
         according to the data stored in this object.
@@ -183,7 +192,8 @@ class CernData(AddonData):
         # this is a mandatory spoke, user must check it
         return True
 
-    def execute(self, storage, ksdata, instclass, users, payload):
+    def execute(self, storage, ksdata, users, payload):
+
         """
         The execute method that should make changes to the installed system. It
         is called only once in the post-install setup phase.
@@ -193,10 +203,10 @@ class CernData(AddonData):
         :type users: pyanaconda.users.Users instance
         """
 
-        yumupdate_file = os.path.normpath(getSysroot() + SYSCONFIG_YUM_PATH)
+        yumupdate_file = os.path.normpath(system_root + SYSCONFIG_YUM_PATH)
 
         # Data is persisted in /root/initial-setup-ks.cfg
-        sysconfig_file = os.path.normpath(getSysroot() + SYSCONFIG_FILE_PATH)
+        sysconfig_file = os.path.normpath(system_root + SYSCONFIG_FILE_PATH)
         with open(sysconfig_file, "w") as fobj:
             fobj.write("LOCMAP_FIRSTBOOT_START=%s\n" % self.run)
             # For compatibility but can be dropped in >= 7.5
@@ -207,8 +217,8 @@ class CernData(AddonData):
             fobj.close()
 
         # Allow to disable gnome-initial-setup
-        gdmconfig_file = os.path.normpath(getSysroot() + GDMCONFIG_FILE_PATH)
-        xdgconfig_file = os.path.normpath(getSysroot() + XDGCONFIG_FILE_PATH)
+        gdmconfig_file = os.path.normpath(system_root + GDMCONFIG_FILE_PATH)
+        xdgconfig_file = os.path.normpath(system_root + XDGCONFIG_FILE_PATH)
         if not self.gnomeinit:
             # C8
             if (sys.version_info > (3, 0)):
@@ -238,31 +248,40 @@ class CernData(AddonData):
             except NoOptionError:
                 print("Unexpected error:", sys.exc_info()[0])
 
+        # we will need this for later
+        release=open('/etc/redhat-release','r').read().split(' ')[3].split('.')[0].rstrip()
+
         # Configure yum-autoupdate
         if self.autoupdate:
-            yumautoupdate_installed=os.path.isfile('/usr/sbin/yum-autoupdate')
-            if yumautoupdate_installed == False:
-                # 'yum' will work for both 7 and 8
-                subprocess.check_call(["yum", "-y", "install", "yum-autoupdate"])
-            subprocess.check_call([SYSTEMCTL_BIN, "enable", "yum-autoupdate"])
-            try:
-                with open(yumupdate_file, "a") as fobj:
-                    fobj.write("\n# initial-setup [cern-anaconda-cern] values\n")
-                    fobj.write("YUMUPDATE=%d\n" % int(self.autoupdate))
-                    fobj.write("YUMONBOOT=%d\n" % int(self.autoupdateboot))
-                    fobj.close()
-            except IOError:
-                print("I/O Error couldn't write %s" % (yumupdate_file))
-            except:
-                print("Unexpected error:", sys.exc_info()[0])
+            if release == '8':
+                # install dnf-automatic instead of custom yum-autoupdate
+                subprocess.check_call(["dnf", "-y", "install", "dnf-automatic"])
+                subprocess.check_call([SYSTEMCTL_BIN, "enable", "--now", "dnf-automatic-install.timer"])
+            else:
+                yumautoupdate_installed=os.path.isfile('/usr/sbin/yum-autoupdate')
+                if yumautoupdate_installed == False:
+                    subprocess.check_call(["yum", "-y", "install", "yum-autoupdate"])
+                subprocess.check_call([SYSTEMCTL_BIN, "enable", "yum-autoupdate"])
+                try:
+                    with open(yumupdate_file, "a") as fobj:
+                        fobj.write("\n# initial-setup [cern-anaconda-cern] values\n")
+                        fobj.write("YUMUPDATE=%d\n" % int(self.autoupdate))
+                        fobj.write("YUMONBOOT=%d\n" % int(self.autoupdateboot))
+                        fobj.close()
+                except IOError:
+                    print("I/O Error couldn't write %s" % (yumupdate_file))
+                except:
+                    print("Unexpected error:", sys.exc_info()[0])
         else:
             # we use call rather than check_call as we don't care if this fails
             # due to yumautoupdate not being installed
-            subprocess.call([SYSTEMCTL_BIN, "disable", "yum-autoupdate"])
+            if release == '8':
+                subprocess.call([SYSTEMCTL_BIN, "disable", "dnf-automatic-install.timer"])
+            else:
+                subprocess.call([SYSTEMCTL_BIN, "disable", "yum-autoupdate"])
 
         # locmap may not be installed - force install if it's not
         locmap_installed=os.path.isfile('/usr/bin/locmap')
-        release=open('/etc/redhat-release','r').read().split(' ')[3].split('.')[0]
         if locmap_installed == False:
             # locmap does not reside in CERN repo on 8, install locmap-release
             if release == '8':
@@ -282,10 +301,6 @@ class CernData(AddonData):
                     subprocess.check_call([LOCMAP_BIN, "--enable", "afs"])
                 else:
                     subprocess.check_call([LOCMAP_BIN, "--disable", "afs"])
-                #if self.eos:
-                #    subprocess.check_call([LOCMAP_BIN, "--enable", "eosclient"])
-                #else:
-                #    subprocess.check_call([LOCMAP_BIN, "--disable", "eosclient"])
                 if self.cvmfs:
                     subprocess.check_call([LOCMAP_BIN, "--enable", "cvmfs"])
                 else:
-- 
GitLab