URL: https://github.com/freeipa/freeipa/pull/1563
Author: stlaz
 Title: #1563: Support the 1.4.x python installer tools in 389-ds
Action: opened

PR body:
"""
Opened on behalf of https://github.com/Firstyear
"""

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/1563/head:pr1563
git checkout pr1563
From 06c24ae5112000874cf81ca27ebbc65855377230 Mon Sep 17 00:00:00 2001
From: William Brown <firsty...@redhat.com>
Date: Fri, 1 Dec 2017 16:33:45 +0100
Subject: [PATCH] Support the 1.4.x python installer tools in 389-ds

---
 install/share/ldapi.ldif        |   4 ++
 ipaplatform/base/paths.py       |  48 +++++++++-------
 ipaserver/install/dsinstance.py | 119 ++++++++++++++++++++++++++++++++++++++--
 3 files changed, 145 insertions(+), 26 deletions(-)

diff --git a/install/share/ldapi.ldif b/install/share/ldapi.ldif
index 607506fd16..47f3f2caa8 100644
--- a/install/share/ldapi.ldif
+++ b/install/share/ldapi.ldif
@@ -3,4 +3,8 @@ dn: cn=config
 changetype: modify
 replace: nsslapd-ldapilisten
 nsslapd-ldapilisten: on
+-
+replace: nsslapd-ldapifilepath
+nsslapd-ldapifilepath: /var/run/slapd-$SERVERID.socket
+-
 
diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py
index 189506d897..98592fbf79 100644
--- a/ipaplatform/base/paths.py
+++ b/ipaplatform/base/paths.py
@@ -32,9 +32,6 @@ class BasePathNamespace(object):
     SYSTEMCTL = "/bin/systemctl"
     TAR = "/bin/tar"
     AUTOFS_LDAP_AUTH_CONF = "/etc/autofs_ldap_auth.conf"
-    ETC_DIRSRV = "/etc/dirsrv"
-    DS_KEYTAB = "/etc/dirsrv/ds.keytab"
-    ETC_DIRSRV_SLAPD_INSTANCE_TEMPLATE = "/etc/dirsrv/slapd-%s"
     ETC_FEDORA_RELEASE = "/etc/fedora-release"
     GROUP = "/etc/group"
     ETC_HOSTNAME = "/etc/hostname"
@@ -189,13 +186,11 @@ class BasePathNamespace(object):
     BIND_LDAP_SO = "/usr/lib/bind/ldap.so"
     BIND_LDAP_DNS_IPA_WORKDIR = "/var/named/dyndb-ldap/ipa/"
     BIND_LDAP_DNS_ZONE_WORKDIR = "/var/named/dyndb-ldap/ipa/master/"
-    USR_LIB_DIRSRV = "/usr/lib/dirsrv"
     LIB_FIREFOX = "/usr/lib/firefox"
     LIBSOFTHSM2_SO = "/usr/lib/pkcs11/libsofthsm2.so"
     PAM_KRB5_SO = "/usr/lib/security/pam_krb5.so"
     LIB_SYSTEMD_SYSTEMD_DIR = "/usr/lib/systemd/system/"
     BIND_LDAP_SO_64 = "/usr/lib64/bind/ldap.so"
-    USR_LIB_DIRSRV_64 = "/usr/lib64/dirsrv"
     LIB64_FIREFOX = "/usr/lib64/firefox"
     LIBSOFTHSM2_SO_64 = "/usr/lib64/pkcs11/libsofthsm2.so"
     PAM_KRB5_SO_64 = "/usr/lib64/security/pam_krb5.so"
@@ -226,11 +221,9 @@ class BasePathNamespace(object):
     PKIDESTROY = "/usr/sbin/pkidestroy"
     PKISPAWN = "/usr/sbin/pkispawn"
     PKI = "/usr/bin/pki"
-    REMOVE_DS_PL = "/usr/sbin/remove-ds.pl"
     RESTORECON = "/usr/sbin/restorecon"
     SELINUXENABLED = "/usr/sbin/selinuxenabled"
     SETSEBOOL = "/usr/sbin/setsebool"
-    SETUP_DS_PL = "/usr/sbin/setup-ds.pl"
     SMBD = "/usr/sbin/smbd"
     USERADD = "/usr/sbin/useradd"
     FONTS_DIR = "/usr/share/fonts"
@@ -265,11 +258,6 @@ class BasePathNamespace(object):
     CERTMONGER_REQUESTS_DIR = "/var/lib/certmonger/requests/"
     VAR_LIB_DIRSRV = "/var/lib/dirsrv"
     DIRSRV_BOOT_LDIF = "/var/lib/dirsrv/boot.ldif"
-    VAR_LIB_DIRSRV_INSTANCE_SCRIPTS_TEMPLATE = "/var/lib/dirsrv/scripts-%s"
-    VAR_LIB_SLAPD_INSTANCE_DIR_TEMPLATE = "/var/lib/dirsrv/slapd-%s"
-    SLAPD_INSTANCE_BACKUP_DIR_TEMPLATE = "/var/lib/dirsrv/slapd-%s/bak/%s"
-    SLAPD_INSTANCE_DB_DIR_TEMPLATE = "/var/lib/dirsrv/slapd-%s/db/%s"
-    SLAPD_INSTANCE_LDIF_DIR_TEMPLATE = "/var/lib/dirsrv/slapd-%s/ldif"
     VAR_LIB_IPA = "/var/lib/ipa"
     IPA_CLIENT_SYSRESTORE = "/var/lib/ipa-client/sysrestore"
     SYSRESTORE_INDEX = "/var/lib/ipa-client/sysrestore/sysrestore.index"
@@ -304,10 +292,6 @@ class BasePathNamespace(object):
     SSSD_PUBCONF_KNOWN_HOSTS = "/var/lib/sss/pubconf/known_hosts"
     SSSD_PUBCONF_KRB5_INCLUDE_D_DIR = "/var/lib/sss/pubconf/krb5.include.d/"
     VAR_LOG_AUDIT = "/var/log/audit/audit.log"
-    DIRSRV_LOCK_DIR = "/var/lock/dirsrv"
-    VAR_LOG_DIRSRV_INSTANCE_TEMPLATE = "/var/log/dirsrv/slapd-%s"
-    SLAPD_INSTANCE_ACCESS_LOG_TEMPLATE = "/var/log/dirsrv/slapd-%s/access"
-    SLAPD_INSTANCE_ERROR_LOG_TEMPLATE = "/var/log/dirsrv/slapd-%s/errors"
     VAR_LOG_HTTPD_DIR = "/var/log/httpd"
     VAR_LOG_HTTPD_ERROR = "/var/log/httpd/error_log"
     IPABACKUP_LOG = "/var/log/ipabackup.log"
@@ -347,13 +331,8 @@ class BasePathNamespace(object):
     SVC_LIST_FILE = "/var/run/ipa/services.list"
     KRB5CC_SAMBA = "/var/run/samba/krb5cc_samba"
     SLAPD_INSTANCE_SOCKET_TEMPLATE = "/var/run/slapd-%s.socket"
-    ALL_SLAPD_INSTANCE_SOCKETS = "/var/run/slapd-*.socket"
     ADMIN_CERT_PATH = '/root/.dogtag/pki-tomcat/ca_admin.cert'
     ENTROPY_AVAIL = '/proc/sys/kernel/random/entropy_avail'
-    LDIF2DB = '/usr/sbin/ldif2db'
-    DB2LDIF = '/usr/sbin/db2ldif'
-    BAK2DB = '/usr/sbin/bak2db'
-    DB2BAK = '/usr/sbin/db2bak'
     KDCPROXY_CONFIG = '/etc/ipa/kdcproxy/kdcproxy.conf'
     CERTMONGER = '/usr/sbin/certmonger'
     NETWORK_MANAGER_CONFIG_DIR = '/etc/NetworkManager/conf.d'
@@ -369,6 +348,33 @@ class BasePathNamespace(object):
     IF_INET6 = '/proc/net/if_inet6'
     WSGI_PREFIX_DIR = "/run/httpd/wsgi"
     AUTHCONFIG = None
+    # 389 DS related commands.
+    DSCREATE = '/usr/sbin/dscreate'
+    DSCTL = '/usr/sbin/dsctl'
+    DSCONF = '/usr/sbin/dsconf'
+    # DS related constants
+    ETC_DIRSRV = "/etc/dirsrv"
+    DS_KEYTAB = "/etc/dirsrv/ds.keytab"
+    ETC_DIRSRV_SLAPD_INSTANCE_TEMPLATE = "/etc/dirsrv/slapd-%s"
+    USR_LIB_DIRSRV = "/usr/lib/dirsrv"
+    USR_LIB_DIRSRV_64 = "/usr/lib64/dirsrv"
+    VAR_LIB_DIRSRV_INSTANCE_SCRIPTS_TEMPLATE = "/var/lib/dirsrv/scripts-%s"
+    VAR_LIB_SLAPD_INSTANCE_DIR_TEMPLATE = "/var/lib/dirsrv/slapd-%s"
+    SLAPD_INSTANCE_BACKUP_DIR_TEMPLATE = "/var/lib/dirsrv/slapd-%s/bak/%s"
+    SLAPD_INSTANCE_DB_DIR_TEMPLATE = "/var/lib/dirsrv/slapd-%s/db/%s"
+    SLAPD_INSTANCE_LDIF_DIR_TEMPLATE = "/var/lib/dirsrv/slapd-%s/ldif"
+    DIRSRV_LOCK_DIR = "/var/lock/dirsrv"
+    ALL_SLAPD_INSTANCE_SOCKETS = "/var/run/slapd-*.socket"
+    VAR_LOG_DIRSRV_INSTANCE_TEMPLATE = "/var/log/dirsrv/slapd-%s"
+    SLAPD_INSTANCE_ACCESS_LOG_TEMPLATE = "/var/log/dirsrv/slapd-%s/access"
+    SLAPD_INSTANCE_ERROR_LOG_TEMPLATE = "/var/log/dirsrv/slapd-%s/errors"
+    # Legacy 389 commands
+    LDIF2DB = '/usr/sbin/ldif2db'
+    DB2LDIF = '/usr/sbin/db2ldif'
+    BAK2DB = '/usr/sbin/bak2db'
+    DB2BAK = '/usr/sbin/db2bak'
+    SETUP_DS_PL = "/usr/sbin/setup-ds.pl"
+    REMOVE_DS_PL = "/usr/sbin/remove-ds.pl"
     IPA_SERVER_UPGRADE = '/usr/sbin/ipa-server-upgrade'
     KEYCTL = '/usr/bin/keyctl'
     GETENT = '/usr/bin/getent'
diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py
index 2493b8a54e..a98dee1411 100644
--- a/ipaserver/install/dsinstance.py
+++ b/ipaserver/install/dsinstance.py
@@ -96,7 +96,7 @@ def schema_dirname(serverid):
     return config_dirname(serverid) + "/schema/"
 
 
-def remove_ds_instance(serverid, force=False):
+def __remove_instance_legacy(serverid, force=False):
     """A wrapper around the 'remove-ds.pl' script used by
     389ds to remove a single directory server instance. In case of error
     additional call with the '-f' flag is performed (forced removal). If this
@@ -118,6 +118,36 @@ def remove_ds_instance(serverid, force=False):
                      "Attempting to force removal", paths.REMOVE_DS_PL)
         remove_ds_instance(serverid, force=True)
 
+def __remove_instance_python(serverid):
+    """Call the lib389 api to remove the instance. Because of the
+    design of the api, there is no "force" command. Provided a marker
+    file exists, it will attempt the removal, and the marker is the *last*
+    file to be removed. IE just run this multiple times til it works (if
+    you even need multiple times ....)
+    """
+
+    from lib389.instance.remove import remove_ds_instance
+    from lib389 import DirSrv
+
+    logger.debug("Attempting to remove instance %s" % serverid)
+    # Alloc the local instance by name (no creds needed!)
+    inst = DirSrv(verbose=True, external_log=logger)
+    inst.local_simple_allocate(serverid)
+
+    # Remove it
+    remove_ds_instance(instance)
+    logger.debug("Instance removed correctly.")
+
+def remove_ds_instance(serverid, force=False):
+    if os.path.exists(paths.REMOVE_DS_PL):
+        # We still have legacy tools. Lets use them.
+        self.__remove_instance_legacy(serverid, force)
+    else:
+        # Okay, 389 have removed their perl tools. Great! Use the api driven installer
+        self.__remove_instance_python(serverid)
+
+
+
 
 def get_ds_instances():
     '''
@@ -537,7 +567,7 @@ def __setup_sub_dict(self):
                              ' '.join(replication.TOTAL_EXCLUDES),
                          )
 
-    def __create_instance(self):
+    def __create_instance_legacy(self):
         pent = pwd.getpwnam(DS_USER)
 
         self.backup_state("serverid", self.serverid)
@@ -579,6 +609,68 @@ def __create_instance(self):
         inf_fd.close()
         os.remove(paths.DIRSRV_BOOT_LDIF)
 
+    def __create_instance_python(self):
+        # We only import lib389 now, because we can't always guarantee it's presence
+        # yet. After f28, this can be made a dependency proper.
+        from lib389.instance.setup import SetupDs
+        from lib389.instance.options import General2Base, Slapd2Base
+        from lib389.idm.ipadomain import IpaDomain
+        from lib389 import DirSrv
+
+        # The new installer is api driven. We can pass it a log function
+        # and it will use it. Because of this, we can pass verbose true,
+        # and allow our logger to control the display based on level.
+        sds = SetupDs(verbose=True, dryrun=False, log=logger)
+
+        # General environmental options.
+        general_options = General2Base(logger)
+        general_options.set('strict_host_checking', False)
+        # Check that our requested configuration is actually valid ...
+        general_options.verify()
+        general = general_options.collect()
+
+        # Slapd options, ie instance name.
+        slapd_options = Slapd2Base(logger)
+        slapd_options.set('instance_name', self.serverid)
+        slapd_options.set('root_password', self.dm_password)
+        slapd_options.verify()
+        slapd = slapd_options.collect()
+
+        # Create userroot. Note that the new install does NOT
+        # create sample entries, so this is *empty*.
+        userroot = {
+            'cn': 'userRoot',
+            'nsslapd-suffix': self.suffix.ldap_text()
+        }
+
+        backends = [userroot,]
+
+        sds.create_from_args(general, slapd, backends, None)
+
+        # Now create the new domain root object in the format that IPA expects.
+        # Get the instance ....
+
+        inst = DirSrv(verbose=True, external_log=logger)
+        inst.remote_simple_allocate(ldapuri=ipaldap.get_ldap_uri(self.fqdn), password=self.dm_password)
+        # This actually opens the conn and binds.
+        inst.open()
+
+        ipadomain = IpaDomain(inst, dn=self.suffix.ldap_text())
+        ipadomain.create(properties={
+            'dc' : self.realm.split('.')[0].lower(),
+            'info': 'IPA V2.0',
+        })
+        # Done!
+        logger.debug("completed creating DS instance")
+
+    def __create_instance(self):
+        if os.path.exists(paths.SETUP_DS_PL):
+            # We still have legacy tools. Lets use them.
+            self.__create_instance_legacy()
+        else:
+            # Okay, 389 have removed their perl tools. Great! Use the api driven installer
+            self.__create_instance_python()
+
     def __update_dse_ldif(self):
         """
         This method updates dse.ldif right after instance creation. This is
@@ -1039,25 +1131,42 @@ def uninstall(self):
 
         try:
             self.fstore.restore_file(paths.LIMITS_CONF)
+        except ValueError as error:
+            logger.debug("%s: %s" % (paths.LIMITS_CONF , error))
+
+        try:
             self.fstore.restore_file(paths.SYSCONFIG_DIRSRV)
         except ValueError as error:
-            logger.debug("%s", error)
+            logger.debug("%s: %s" % (paths.SYSCONFIG_DIRSRV , error))
 
         # disabled during IPA installation
         if enabled:
+            logger.debug("Re-enabling instance of Directory Server")
             self.enable()
 
         serverid = self.restore_state("serverid")
         if serverid is not None:
+            # What if this fails? Then what?
             self.stop_tracking_certificates(serverid)
             logger.debug("Removing DS instance %s", serverid)
             try:
                 remove_ds_instance(serverid)
-                installutils.remove_keytab(paths.DS_KEYTAB)
-                installutils.remove_ccache(run_as=DS_USER)
             except ipautil.CalledProcessError:
                 logger.error("Failed to remove DS instance. You may "
                              "need to remove instance data manually")
+            try:
+                installutils.remove_keytab(paths.DS_KEYTAB)
+            except ipautil.CalledProcessError:
+                logger.error("Failed to remove DS keytab. You may "
+                             "need to remove keytab data manually")
+            try:
+                installutils.remove_ccache(run_as=DS_USER)
+            except:
+                logger.error("Failed to remove DS ccache. You may "
+                             "need to remove ccache data manually")
+        else:
+            logger.error("Failed to remove DS instance. No serverid present"
+                         "in sysrestore file.")
 
         # Just eat this state
         self.restore_state("user_exists")
_______________________________________________
FreeIPA-devel mailing list -- freeipa-devel@lists.fedorahosted.org
To unsubscribe send an email to freeipa-devel-le...@lists.fedorahosted.org

Reply via email to