[PATCH] Add support for the realm command

Martin Kolman mkolman at gmail.com
Thu May 9 15:09:18 UTC 2013


This patch adds support for the realm command directly to Anaconda,
so that realm can be specified directly with the realm command without
the addon data notation.

The realm command enables joining a domain during installation.
Only the join command is currently supported.

This patch is based on the original Stef's patch and the Vratislav's realm
addon.

Signed-off-by: Martin Kolman <mkolman at gmail.com>
---
 anaconda.spec.in        |  3 +-
 pyanaconda/install.py   | 26 ++++++++++++++---
 pyanaconda/kickstart.py | 77 +++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 101 insertions(+), 5 deletions(-)

diff --git a/anaconda.spec.in b/anaconda.spec.in
index 34c580e..b07831b 100644
--- a/anaconda.spec.in
+++ b/anaconda.spec.in
@@ -21,7 +21,7 @@ Source0: %{name}-%{version}.tar.bz2
 %define gconfversion 2.28.1
 %define intltoolver 0.31.2-3
 %define libnlver 1.0
-%define pykickstartver 1.99.28
+%define pykickstartver 1.99.29
 %define yumver 3.4.3-32
 %define partedver 1.8.1
 %define pypartedver 2.5-2
@@ -102,6 +102,7 @@ Requires: tigervnc-server-minimal
 Requires: pytz
 Requires: libxklavier
 Requires: libgnomekbd
+Requires: realmd
 %ifarch %livearches
 Requires: usermode
 Requires: zenity
diff --git a/pyanaconda/install.py b/pyanaconda/install.py
index 79b7b6b..48691c0 100644
--- a/pyanaconda/install.py
+++ b/pyanaconda/install.py
@@ -49,7 +49,13 @@ def _writeKS(ksdata):
 def doConfiguration(storage, payload, ksdata, instClass):
     from pyanaconda.kickstart import runPostScripts
 
-    progressQ.send_init(5)
+    step_count = 5
+    # if a realm was discovered,
+    # increment the counter as the
+    # real joining step will be executed
+    if ksdata.realm.discovered:
+        step_count = 6
+    progressQ.send_init(step_count)
 
     # Now run the execute methods of ksdata that require an installed system
     # to be present first.
@@ -79,7 +85,11 @@ def doConfiguration(storage, payload, ksdata, instClass):
     with progress_report(_("Configuring addons")):
         ksdata.addons.execute(storage, ksdata, instClass, u)
         ksdata.configured_spokes.execute(storage, ksdata, instClass, u)
-        
+
+    if ksdata.realm.discovered:
+        with progress_report(_("Joining realm: %s") % ksdata.realm.discovered):
+            ksdata.realm.execute(storage, ksdata, instClass)
+
     with progress_report(_("Running post-installation scripts")):
         runPostScripts(ksdata.scripts)
 
@@ -105,7 +115,9 @@ def doInstall(storage, payload, ksdata, instClass):
     # those are the ones that take the most time.
     steps = len(storage.devicetree.findActions(type="create", object="format")) + \
             len(storage.devicetree.findActions(type="resize", object="format"))
-    steps += 5  # pre setup phase, packages setup, packages, bootloader, post install
+    steps += 6
+    # pre setup phase, packages setup, packages, bootloader, realmd,
+    # post install
     progressQ.send_init(steps)
 
     with progress_report(_("Setting up the installation environment")):
@@ -120,10 +132,16 @@ def doInstall(storage, payload, ksdata, instClass):
 
     # Do packaging.
 
+    # Discover information about realms to join,
+    # to determine additional packages
+    if ksdata.realm.join_realm:
+        with progress_report(_("Discovering realm to join")):
+            ksdata.realm.setup()
+
     # anaconda requires storage packages in order to make sure the target
     # system is bootable and configurable, and some other packages in order
     # to finish setting up the system.
-    packages = storage.packages + ["authconfig", "firewalld"]
+    packages = storage.packages + ["authconfig", "firewalld"] + ksdata.realm.packages
     payload.preInstall(packages=packages, groups=payload.languageGroups())
     payload.install()
 
diff --git a/pyanaconda/kickstart.py b/pyanaconda/kickstart.py
index 32cddb9..7ebcf04 100644
--- a/pyanaconda/kickstart.py
+++ b/pyanaconda/kickstart.py
@@ -37,6 +37,7 @@ import iutil
 import os
 import os.path
 import tempfile
+import subprocess
 import flags as flags_module
 from flags import flags
 from constants import *
@@ -368,6 +369,81 @@ class BTRFSData(commands.btrfs.F17_BTRFSData):
 
             storage.createDevice(request)
 
+
+class Realm(commands.realm.F19_Realm):
+    def __init__(self, *args):
+        commands.realm.F19_Realm.__init__(self, *args)
+        self.packages = []
+        self.discovered = ""
+
+    def setup(self):
+        if not self.join_realm:
+            return
+
+        try:
+            argv = ["realm", "discover", "--verbose"] + \
+                    self.discover_options + [self.join_realm]
+            proc = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+            output, stderr = proc.communicate()
+            # might contain useful information for users who use
+            # use the realm kickstart command
+            log.info("Realm discover stderr:\n%s" % stderr)
+        except OSError as msg:
+            # TODO: A lousy way of propagating what will usually be
+            # 'no such realm'
+            log.error("Error running realm %s: %s", argv, msg)
+            return
+
+        # Now parse the output for the required software. First line is the
+        # realm name, and following lines are information as "name: value"
+        self.packages = ["realmd"]
+        self.discovered = ""
+
+        lines = output.split("\n")
+        if not lines:
+            return
+        self.discovered = lines.pop(0).strip()
+        log.info("Realm discovered: %s" % self.discovered)
+        for line in lines:
+            parts = line.split(":", 1)
+            if len(parts) == 2 and parts[0].strip() == "required-package":
+                self.packages.append(parts[1].strip())
+
+        log.info("Realm %s needs packages %s" %
+                 (self.discovered, ", ".join(self.packages)))
+
+    def execute(self, *args):
+        if not self.discovered:
+            return
+        for arg in self.join_args:
+            if arg.startswith("--no-password") or arg.startswith("--one-time-password"):
+                pw_args = []
+                break
+        else:
+            # no explicit password arg using implicit --no-password
+            pw_args = ["--no-password"]
+
+        argv = ["realm", "join", "--install", ROOT_PATH, "--verbose"] + \
+               pw_args + self.join_args
+        rc = -1
+        try:
+            proc = subprocess.Popen(argv, stdout=subprocess.PIPE,
+                                    stderr=subprocess.PIPE)
+            output, stderr = proc.communicate()
+            # might contain useful information for users who use
+            # use the realm kickstart command
+            log.info("Realm join stderr:\n%s" % stderr)
+            rc = proc.returncode
+        except OSError as msg:
+            log.error("Error running %s: %s", argv, msg)
+
+        if rc != 0:
+            log.error("Command failure: %s: %d", argv, rc)
+            return
+
+        log.info("Joined realm %s", self.join_realm)
+
+
 class ClearPart(commands.clearpart.F17_ClearPart):
     def parse(self, args):
         retval = commands.clearpart.F17_ClearPart.parse(self, args)
@@ -1372,6 +1448,7 @@ commandMap = {
         "part": Partition,
         "partition": Partition,
         "raid": Raid,
+        "realm": Realm,
         "rootpw": RootPw,
         "selinux": SELinux,
         "services": Services,
-- 
1.8.1.4



More information about the anaconda-patches mailing list