URL: https://github.com/freeipa/freeipa/pull/373
Author: tjaalton
 Title: #373: ipaplatform: Add Debian platform module.
Action: synchronized

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/373/head:pr373
git checkout pr373
From 6b490e2c4165215f0d6b9b08676661c4c9d4abd6 Mon Sep 17 00:00:00 2001
From: Timo Aaltonen <tjaal...@debian.org>
Date: Thu, 5 Jan 2017 12:41:08 +0200
Subject: [PATCH] ipaplatform: Add Debian platform module.

v2:
- use redhat_services.redhat_system_units.copy
- don't use wildcard imports
- add some empty lines to make pep8 happy

v3:
- make parse_ipa_version static

v4:
- make more methods static

v5:
- fix pylint issues
- use syntax that doesn't break with python3

v6:
- remove IPA_GETKEYTAB from paths, it's the same across distros
---
 ipaplatform/base/tasks.py       |   3 +-
 ipaplatform/debian/__init__.py  |   7 ++
 ipaplatform/debian/constants.py |  25 ++++++
 ipaplatform/debian/paths.py     |  96 +++++++++++++++++++++
 ipaplatform/debian/services.py  | 184 ++++++++++++++++++++++++++++++++++++++++
 ipaplatform/debian/tasks.py     |  50 +++++++++++
 ipaplatform/setup.py            |   1 +
 7 files changed, 365 insertions(+), 1 deletion(-)
 create mode 100644 ipaplatform/debian/__init__.py
 create mode 100644 ipaplatform/debian/constants.py
 create mode 100644 ipaplatform/debian/paths.py
 create mode 100644 ipaplatform/debian/services.py
 create mode 100644 ipaplatform/debian/tasks.py

diff --git a/ipaplatform/base/tasks.py b/ipaplatform/base/tasks.py
index 702da6b..8cf6fde 100644
--- a/ipaplatform/base/tasks.py
+++ b/ipaplatform/base/tasks.py
@@ -227,7 +227,8 @@ def create_system_user(self, name, group, homedir, shell, uid=None, gid=None, co
         else:
             log.debug('user %s exists', name)
 
-    def parse_ipa_version(self, version):
+    @staticmethod
+    def parse_ipa_version(version):
         """
         :param version: textual version
         :return: object implementing proper __cmp__ method for version compare
diff --git a/ipaplatform/debian/__init__.py b/ipaplatform/debian/__init__.py
new file mode 100644
index 0000000..6305270
--- /dev/null
+++ b/ipaplatform/debian/__init__.py
@@ -0,0 +1,7 @@
+#
+# Copyright (C) 2017  FreeIPA Contributors see COPYING for license
+#
+
+"""
+This module contains Debian specific platform files.
+"""
diff --git a/ipaplatform/debian/constants.py b/ipaplatform/debian/constants.py
new file mode 100644
index 0000000..1edcb5a
--- /dev/null
+++ b/ipaplatform/debian/constants.py
@@ -0,0 +1,25 @@
+#
+# Copyright (C) 2017  FreeIPA Contributors see COPYING for license
+#
+
+'''
+This Debian family platform module exports platform dependant constants.
+'''
+
+# Fallback to default path definitions
+from ipaplatform.base.constants import BaseConstantsNamespace
+
+
+class DebianConstantsNamespace(BaseConstantsNamespace):
+    HTTPD_USER = "www-data"
+    NAMED_USER = "bind"
+    NAMED_GROUP = "bind"
+    # ntpd init variable used for daemon options
+    NTPD_OPTS_VAR = "NTPD_OPTS"
+    # quote used for daemon options
+    NTPD_OPTS_QUOTE = "\'"
+    ODS_USER = "opendnssec"
+    ODS_GROUP = "opendnssec"
+    SECURE_NFS_VAR = "NEED_GSSD"
+
+constants = DebianConstantsNamespace()
diff --git a/ipaplatform/debian/paths.py b/ipaplatform/debian/paths.py
new file mode 100644
index 0000000..5cbe9b8
--- /dev/null
+++ b/ipaplatform/debian/paths.py
@@ -0,0 +1,96 @@
+#
+# Copyright (C) 2017  FreeIPA Contributors see COPYING for license
+#
+
+"""
+This Debian base platform module exports default filesystem paths as common
+in Debian-based systems.
+"""
+
+# Fallback to default path definitions
+from ipaplatform.base.paths import BasePathNamespace
+import sysconfig
+
+MULTIARCH = sysconfig.get_config_var('MULTIARCH')
+
+class DebianPathNamespace(BasePathNamespace):
+    BIN_HOSTNAMECTL = "/usr/bin/hostnamectl"
+    AUTOFS_LDAP_AUTH_CONF = "/etc/autofs_ldap_auth.conf"
+    ETC_HTTPD_DIR = "/etc/apache2"
+    HTTPD_ALIAS_DIR = "/etc/apache2/nssdb"
+    ALIAS_CACERT_ASC = "/etc/apache2/nssdb/cacert.asc"
+    ALIAS_PWDFILE_TXT = "/etc/apache2/nssdb/pwdfile.txt"
+    HTTPD_CONF_D_DIR = "/etc/apache2/conf-enabled/"
+    HTTPD_IPA_KDCPROXY_CONF_SYMLINK = "/etc/apache2/conf-enabled/ipa-kdc-proxy.conf"
+    HTTPD_IPA_PKI_PROXY_CONF = "/etc/apache2/conf-enabled/ipa-pki-proxy.conf"
+    HTTPD_IPA_REWRITE_CONF = "/etc/apache2/conf-available/ipa-rewrite.conf"
+    HTTPD_IPA_CONF = "/etc/apache2/conf-enabled/ipa.conf"
+    HTTPD_NSS_CONF = "/etc/apache2/mods-available/nss.conf"
+    IPA_KEYTAB = "/etc/apache2/ipa.keytab"
+    HTTPD_PASSWORD_CONF = "/etc/apache2/password.conf"
+    NAMED_CONF = "/etc/bind/named.conf"
+    NAMED_VAR_DIR = "/var/cache/bind"
+    NAMED_KEYTAB = "/etc/bind/named.keytab"
+    NAMED_RFC1912_ZONES = "/etc/bind/named.conf.default-zones"
+    NAMED_ROOT_KEY = "/etc/bind/bind.keys"
+    NAMED_BINDKEYS_FILE = "/etc/bind/bind.keys"
+    NAMED_MANAGED_KEYS_DIR = "/var/cache/bind/dynamic"
+    OPENLDAP_LDAP_CONF = "/etc/ldap/ldap.conf"
+    ETC_DEBIAN_VERSION = "/etc/debian_version"
+    IPA_P11_KIT = "/usr/local/share/ca-certificates/ipa-ca.crt"
+    ETC_SYSCONFIG_DIR = "/etc/default"
+    SYSCONFIG_AUTOFS = "/etc/default/autofs"
+    SYSCONFIG_DIRSRV = "/etc/default/dirsrv"
+    SYSCONFIG_DIRSRV_INSTANCE = "/etc/default/dirsrv-%s"
+    SYSCONFIG_DIRSRV_SYSTEMD = "/etc/default/dirsrv.systemd"
+    SYSCONFIG_IPA_DNSKEYSYNCD = "/etc/default/ipa-dnskeysyncd"
+    SYSCONFIG_IPA_ODS_EXPORTER = "/etc/default/ipa-ods-exporter"
+    SYSCONFIG_KRB5KDC_DIR = "/etc/default/krb5-kdc"
+    SYSCONFIG_NAMED = "/etc/default/bind9"
+    SYSCONFIG_NFS = "/etc/default/nfs-common"
+    SYSCONFIG_NTPD = "/etc/default/ntp"
+    SYSCONFIG_ODS = "/etc/default/opendnssec"
+    SYSCONFIG_PKI = "/etc/dogtag/"
+    SYSCONFIG_PKI_TOMCAT = "/etc/default/pki-tomcat"
+    SYSCONFIG_PKI_TOMCAT_PKI_TOMCAT_DIR = "/etc/dogtag/tomcat/pki-tomcat"
+    SYSTEMD_SYSTEM_HTTPD_D_DIR = "/etc/systemd/system/apache2.service.d/"
+    SYSTEMD_SYSTEM_HTTPD_IPA_CONF = "/etc/systemd/system/apache2.service.d/ipa.conf"
+    DNSSEC_TRUSTED_KEY = "/etc/bind/trusted-key.key"
+    KRA_AGENT_PEM = "/etc/apache2/nssdb/kra-agent.pem"
+    SBIN_SERVICE = "/usr/sbin/service"
+    CERTMONGER_COMMAND_TEMPLATE = "/usr/lib/ipa/certmonger/%s"
+    UPDATE_CA_TRUST = "/usr/sbin/update-ca-certificates"
+    BIND_LDAP_DNS_IPA_WORKDIR = "/var/cache/bind/dyndb-ldap/ipa/"
+    BIND_LDAP_DNS_ZONE_WORKDIR = "/var/cache/bind/dyndb-ldap/ipa/master/"
+    LIBSOFTHSM2_SO = "/usr/lib/softhsm/libsofthsm2.so"
+    PAM_KRB5_SO = "/usr/lib/{0}/security/pam_krb5.so".format(MULTIARCH)
+    LIB_SYSTEMD_SYSTEMD_DIR = "/lib/systemd/system/"
+    DOGTAG_IPA_CA_RENEW_AGENT_SUBMIT = "/usr/lib/certmonger/dogtag-ipa-ca-renew-agent-submit"
+    DOGTAG_IPA_RENEW_AGENT_SUBMIT = "/usr/lib/certmonger/dogtag-ipa-renew-agent-submit"
+    IPA_SERVER_GUARD = "/usr/lib/certmonger/ipa-server-guard"
+    GENERATE_RNDC_KEY = "/bin/true"
+    IPA_DNSKEYSYNCD_REPLICA = "/usr/lib/ipa/ipa-dnskeysync-replica"
+    IPA_DNSKEYSYNCD = "/usr/lib/ipa/ipa-dnskeysyncd"
+    IPA_ODS_EXPORTER = "/usr/lib/ipa/ipa-ods-exporter"
+    HTTPD = "/usr/sbin/apache2ctl"
+    REMOVE_DS_PL = "/usr/sbin/remove-ds"
+    SETUP_DS_PL = "/usr/sbin/setup-ds"
+    VAR_KERBEROS_KRB5KDC_DIR = "/var/lib/krb5kdc/"
+    VAR_KRB5KDC_K5_REALM = "/var/lib/krb5kdc/.k5."
+    CACERT_PEM = "/var/lib/krb5kdc/cacert.pem"
+    KRB5KDC_KADM5_ACL = "/etc/krb5kdc/kadm5.acl"
+    KRB5KDC_KADM5_KEYTAB = "/etc/krb5kdc/kadm5.keytab"
+    KRB5KDC_KDC_CONF = "/etc/krb5kdc/kdc.conf"
+    KDC_CERT = "/var/lib/krb5kdc/kdc.crt"
+    KDC_KEY = "/var/lib/krb5kdc/kdc.key"
+    VAR_LOG_HTTPD_DIR = "/var/log/apache2"
+    VAR_LOG_HTTPD_ERROR = "/var/log/apache2/error.log"
+    NAMED_RUN = "/var/cache/bind/named.run"
+    VAR_OPENDNSSEC_DIR = "/var/lib/opendnssec"
+    OPENDNSSEC_KASP_DB = "/var/lib/opendnssec/db/kasp.db"
+    IPA_ODS_EXPORTER_CCACHE = "/var/lib/opendnssec/tmp/ipa-ods-exporter.ccache"
+    KRB5CC_HTTPD = "/var/run/apache2/ipa/krbcache/krb5ccache"
+    IPA_CUSTODIA_SOCKET = "/run/apache2/ipa-custodia.sock"
+    IPA_CUSTODIA_AUDIT_LOG = '/var/log/ipa-custodia.audit.log'
+
+paths = DebianPathNamespace()
diff --git a/ipaplatform/debian/services.py b/ipaplatform/debian/services.py
new file mode 100644
index 0000000..82a74e2
--- /dev/null
+++ b/ipaplatform/debian/services.py
@@ -0,0 +1,184 @@
+#
+# Copyright (C) 2017  FreeIPA Contributors see COPYING for license
+#
+
+"""
+Contains Debian-specific service class implementations.
+"""
+
+from ipaplatform.base import services as base_services
+from ipaplatform.redhat import services as redhat_services
+from ipapython import ipautil
+from ipaplatform.paths import paths
+
+# Mappings from service names as FreeIPA code references to these services
+# to their actual systemd service names
+debian_system_units = redhat_services.redhat_system_units.copy()
+
+# For beginning just remap names to add .service
+# As more services will migrate to systemd, unit names will deviate and
+# mapping will be kept in this dictionary
+debian_system_units['httpd'] = 'apache2.service'
+debian_system_units['kadmin'] = 'krb5-admin-server.service'
+debian_system_units['krb5kdc'] = 'krb5-kdc.service'
+debian_system_units['named-regular'] = 'bind9.service'
+debian_system_units['named-pkcs11'] = 'bind9-pkcs11.service'
+debian_system_units['named'] = debian_system_units['named-pkcs11']
+debian_system_units['pki-tomcatd'] = 'pki-tomcatd.service'
+debian_system_units['pki_tomcatd'] = debian_system_units['pki-tomcatd']
+debian_system_units['ods-enforcerd'] = 'opendnssec-enforcer.service'
+debian_system_units['ods_enforcerd'] = debian_system_units['ods-enforcerd']
+debian_system_units['ods-signerd'] = 'opendnssec-signer.service'
+debian_system_units['ods_signerd'] = debian_system_units['ods-signerd']
+debian_system_units['rpcgssd'] = 'rpc-gssd.service'
+debian_system_units['rpcidmapd'] = 'nfs-idmapd.service'
+debian_system_units['smb'] = 'smbd.service'
+
+# Service classes that implement Debian family-specific behaviour
+
+class DebianService(redhat_services.RedHatService):
+    system_units = debian_system_units
+
+
+class DebianSysvService(base_services.PlatformService):
+    def __wait_for_open_ports(self, instance_name=""):
+        """
+        If this is a service we need to wait for do so.
+        """
+        ports = None
+        if instance_name in base_services.wellknownports:
+            ports = base_services.wellknownports[instance_name]
+        else:
+            if self.service_name in base_services.wellknownports:
+                ports = base_services.wellknownports[self.service_name]
+        if ports:
+            ipautil.wait_for_open_ports('localhost', ports, self.api.env.startup_timeout)
+
+    def stop(self, instance_name='', capture_output=True):
+        ipautil.run([paths.SBIN_SERVICE, self.service_name, "stop",
+                     instance_name], capture_output=capture_output)
+        super(DebianSysvService, self).stop(instance_name)
+
+    def start(self, instance_name='', capture_output=True, wait=True):
+        ipautil.run([paths.SBIN_SERVICE, self.service_name, "start",
+                     instance_name], capture_output=capture_output)
+        if wait and self.is_running(instance_name):
+            self.__wait_for_open_ports(instance_name)
+        super(DebianSysvService, self).start(instance_name)
+
+    def restart(self, instance_name='', capture_output=True, wait=True):
+        ipautil.run([paths.SBIN_SERVICE, self.service_name, "restart",
+                     instance_name], capture_output=capture_output)
+        if wait and self.is_running(instance_name):
+            self.__wait_for_open_ports(instance_name)
+
+    def is_running(self, instance_name=""):
+        ret = True
+        try:
+            result = ipautil.run([paths.SBIN_SERVICE,
+                                  self.service_name, "status",
+                                  instance_name],
+                                  capture_output=True)
+            sout = result.output
+            if sout.find("NOT running") >= 0:
+                ret = False
+            if sout.find("stop") >= 0:
+                ret = False
+            if sout.find("inactive") >= 0:
+                ret = False
+        except ipautil.CalledProcessError:
+                ret = False
+        return ret
+
+    def is_installed(self):
+        installed = True
+        try:
+            ipautil.run([paths.SBIN_SERVICE, self.service_name, "status"])
+        except ipautil.CalledProcessError as e:
+            if e.returncode == 1:
+                # service is not installed or there is other serious issue
+                installed = False
+        return installed
+
+    @staticmethod
+    def is_enabled(instance_name=""):
+        # Services are always assumed to be enabled when installed
+        return True
+
+    @staticmethod
+    def enable():
+        return True
+
+    @staticmethod
+    def disable():
+        return True
+
+    @staticmethod
+    def install():
+        return True
+
+    @staticmethod
+    def remove():
+        return True
+
+    @staticmethod
+    def tune_nofile_platform():
+        return True
+
+
+# For services which have no Debian counterpart
+class DebianNoService(base_services.PlatformService):
+    @staticmethod
+    def start():
+        return True
+
+    @staticmethod
+    def stop():
+        return True
+
+    @staticmethod
+    def restart():
+        return True
+
+    @staticmethod
+    def disable():
+        return True
+
+
+# Function that constructs proper Debian-specific server classes for services
+# of specified name
+
+def debian_service_class_factory(name, api=None):
+    if name == 'dirsrv':
+        return redhat_services.RedHatDirectoryService(name, api)
+    if name == 'domainname':
+        return DebianNoService(name, api)
+    if name == 'ipa':
+        return redhat_services.RedHatIPAService(name, api)
+    if name == 'messagebus':
+        return DebianNoService(name, api)
+    if name == 'ntpd':
+        return DebianSysvService("ntp", api)
+    return DebianService(name, api)
+
+
+# Magicdict containing DebianService instances.
+
+class DebianServices(base_services.KnownServices):
+    def __init__(self):
+        import ipalib  # FixMe: break import cycle
+        services = dict()
+        for s in base_services.wellknownservices:
+            services[s] = self.service_class_factory(s, ipalib.api)
+        # Call base class constructor. This will lock services to read-only
+        super(DebianServices, self).__init__(services)
+
+    @staticmethod
+    def service_class_factory(name, api=None):
+        return debian_service_class_factory(name, api)
+
+# Objects below are expected to be exported by platform module
+
+timedate_services = base_services.timedate_services
+service = debian_service_class_factory
+knownservices = DebianServices()
diff --git a/ipaplatform/debian/tasks.py b/ipaplatform/debian/tasks.py
new file mode 100644
index 0000000..6c41a35
--- /dev/null
+++ b/ipaplatform/debian/tasks.py
@@ -0,0 +1,50 @@
+#
+# Copyright (C) 2017  FreeIPA Contributors see COPYING for license
+#
+
+"""
+This module contains default Debian-specific implementations of system tasks.
+"""
+
+from ipaplatform.base.tasks import BaseTaskNamespace
+from ipaplatform.redhat.tasks import RedHatTaskNamespace
+
+
+class DebianTaskNamespace(RedHatTaskNamespace):
+    @staticmethod
+    def restore_pre_ipa_client_configuration(fstore, statestore,
+                                             was_sssd_installed,
+                                             was_sssd_configured):
+        # Debian doesn't use authconfig, nothing to restore
+        return True
+
+    @staticmethod
+    def set_nisdomain(nisdomain):
+        # Debian doesn't use authconfig, nothing to set
+        return True
+
+    @staticmethod
+    def modify_nsswitch_pam_stack(sssd, mkhomedir, statestore):
+        # Debian doesn't use authconfig, this is handled by pam-auth-update
+        return True
+
+    @staticmethod
+    def modify_pam_to_use_krb5(statestore):
+        # Debian doesn't use authconfig, this is handled by pam-auth-update
+        return True
+
+    @staticmethod
+    def backup_auth_configuration(path):
+        # Debian doesn't use authconfig, nothing to backup
+        return True
+
+    @staticmethod
+    def restore_auth_configuration(path):
+        # Debian doesn't use authconfig, nothing to restore
+        return True
+
+    @staticmethod
+    def parse_ipa_version(version):
+        return BaseTaskNamespace.parse_ipa_version(version)
+
+tasks = DebianTaskNamespace()
diff --git a/ipaplatform/setup.py b/ipaplatform/setup.py
index 9c47da7..6637830 100644
--- a/ipaplatform/setup.py
+++ b/ipaplatform/setup.py
@@ -35,6 +35,7 @@
         packages=[
             "ipaplatform",
             "ipaplatform.base",
+            "ipaplatform.debian",
             "ipaplatform.fedora",
             "ipaplatform.redhat",
             "ipaplatform.rhel"
-- 
Manage your subscription for the Freeipa-devel mailing list:
https://www.redhat.com/mailman/listinfo/freeipa-devel
Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code

Reply via email to