summaryrefslogtreecommitdiffstats
path: root/ipaplatform/fedora
diff options
context:
space:
mode:
Diffstat (limited to 'ipaplatform/fedora')
-rw-r--r--ipaplatform/fedora/authconfig.py86
-rw-r--r--ipaplatform/fedora/paths.py5
-rw-r--r--ipaplatform/fedora/services.py197
-rw-r--r--ipaplatform/fedora/tasks.py230
4 files changed, 18 insertions, 500 deletions
diff --git a/ipaplatform/fedora/authconfig.py b/ipaplatform/fedora/authconfig.py
deleted file mode 100644
index 524d76929..000000000
--- a/ipaplatform/fedora/authconfig.py
+++ /dev/null
@@ -1,86 +0,0 @@
-# Authors: Simo Sorce <ssorce@redhat.com>
-# Alexander Bokovoy <abokovoy@redhat.com>
-# Tomas Babej <tbabej@redhat.com>
-#
-# Copyright (C) 2007-2014 Red Hat
-# see file 'COPYING' for use and warranty information
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-from ipapython import ipautil
-
-
-class FedoraAuthConfig(object):
- """
- AuthConfig class implements system-independent interface to configure
- system authentication resources. In Red Hat systems this is done with
- authconfig(8) utility.
-
- AuthConfig class is nothing more than a tool to gather configuration
- options and execute their processing. These options then converted by
- an actual implementation to series of a system calls to appropriate
- utilities performing real configuration.
-
- If you need to re-use existing AuthConfig instance for multiple runs,
- make sure to call 'AuthConfig.reset()' between the runs.
- """
-
- def __init__(self):
- self.parameters = {}
-
- def enable(self, option):
- self.parameters[option] = True
- return self
-
- def disable(self, option):
- self.parameters[option] = False
- return self
-
- def add_option(self, option):
- self.parameters[option] = None
- return self
-
- def add_parameter(self, option, value):
- self.parameters[option] = [value]
- return self
-
- def reset(self):
- self.parameters = {}
- return self
-
- def build_args(self):
- args = []
-
- for (option, value) in self.parameters.items():
- if type(value) is bool:
- if value:
- args.append("--enable%s" % (option))
- else:
- args.append("--disable%s" % (option))
- elif type(value) in (tuple, list):
- args.append("--%s" % (option))
- args.append("%s" % (value[0]))
- elif value is None:
- args.append("--%s" % (option))
- else:
- args.append("--%s%s" % (option, value))
-
- return args
-
- def execute(self, update=True):
- if update:
- self.add_option("update")
-
- args = self.build_args()
- ipautil.run(["/usr/sbin/authconfig"] + args)
diff --git a/ipaplatform/fedora/paths.py b/ipaplatform/fedora/paths.py
index af3e47d82..49a904f2f 100644
--- a/ipaplatform/fedora/paths.py
+++ b/ipaplatform/fedora/paths.py
@@ -23,10 +23,11 @@ in Fedora-based systems.
'''
# Fallback to default path definitions
-from ipaplatform.base.paths import BasePathNamespace
+from ipaplatform.redhat.paths import RedHatPathNamespace
-class FedoraPathNamespace(BasePathNamespace):
+class FedoraPathNamespace(RedHatPathNamespace):
pass
+
paths = FedoraPathNamespace()
diff --git a/ipaplatform/fedora/services.py b/ipaplatform/fedora/services.py
index d98c2d6d7..33becc219 100644
--- a/ipaplatform/fedora/services.py
+++ b/ipaplatform/fedora/services.py
@@ -22,213 +22,40 @@
Contains Fedora-specific service class implementations.
"""
-import os
-import time
-
-from ipaplatform.tasks import tasks
-from ipaplatform.base import services as base_services
-
-from ipapython import ipautil, dogtag
-from ipapython.ipa_log_manager import root_logger
-from ipalib import api
-from ipaplatform.paths import paths
+from ipaplatform.redhat import services as redhat_services
# Mappings from service names as FreeIPA code references to these services
# to their actual systemd service names
+fedora_system_units = redhat_services.redhat_system_units
-# 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
-system_units = dict((x, "%s.service" % x)
- for x in base_services.wellknownservices)
-
-system_units['rpcgssd'] = 'nfs-secure.service'
-system_units['rpcidmapd'] = 'nfs-idmap.service'
-
-# Rewrite dirsrv and pki-tomcatd services as they support instances via separate
-# service generator. To make this working, one needs to have both foo@.servic
-# and foo.target -- the latter is used when request should be coming for
-# all instances (like stop). systemd, unfortunately, does not allow one
-# to request action for all service instances at once if only foo@.service
-# unit is available. To add more, if any of those services need to be
-# started/stopped automagically, one needs to manually create symlinks in
-# /etc/systemd/system/foo.target.wants/ (look into systemd.py's enable()
-# code).
-
-system_units['dirsrv'] = 'dirsrv@.service'
-# Our directory server instance for PKI is dirsrv@PKI-IPA.service
-system_units['pkids'] = 'dirsrv@PKI-IPA.service'
-# Old style PKI instance
-system_units['pki-cad'] = 'pki-cad@pki-ca.service'
-system_units['pki_cad'] = system_units['pki-cad']
-# Our PKI instance is pki-tomcatd@pki-tomcat.service
-system_units['pki-tomcatd'] = 'pki-tomcatd@pki-tomcat.service'
-system_units['pki_tomcatd'] = system_units['pki-tomcatd']
-system_units['ipa-otpd'] = 'ipa-otpd.socket'
# Service that sets domainname on Fedora is called fedora-domainname.service
-system_units['domainname'] = 'fedora-domainname.service'
+fedora_system_units['domainname'] = 'fedora-domainname.service'
# Service classes that implement Fedora-specific behaviour
-class FedoraService(base_services.SystemdService):
- def __init__(self, service_name):
- systemd_name = service_name
- if service_name in system_units:
- systemd_name = system_units[service_name]
- else:
- if '.' not in service_name:
- # if service_name does not have a dot, it is not foo.service
- # and not a foo.target. Thus, not correct service name for
- # systemd, default to foo.service style then
- systemd_name = "%s.service" % (service_name)
- super(FedoraService, self).__init__(service_name, systemd_name)
-
-
-class FedoraDirectoryService(FedoraService):
-
- def tune_nofile_platform(self, num=8192, fstore=None):
- """
- Increase the number of files descriptors available to directory server
- from the default 1024 to 8192. This will allow to support a greater
- number of clients out of the box.
-
- This is a part of the implementation that is systemd-specific.
-
- Returns False if the setting of the nofile limit needs to be skipped.
- """
-
- if os.path.exists(paths.SYSCONFIG_DIRSRV_SYSTEMD):
- # We need to enable LimitNOFILE=8192 in the dirsrv@.service
- # Since 389-ds-base-1.2.10-0.8.a7 the configuration of the
- # service parameters is performed via
- # /etc/sysconfig/dirsrv.systemd file which is imported by systemd
- # into dirsrv@.service unit
-
- replacevars = {'LimitNOFILE': str(num)}
- ipautil.inifile_replace_variables(paths.SYSCONFIG_DIRSRV_SYSTEMD,
- 'service',
- replacevars=replacevars)
- tasks.restore_context(paths.SYSCONFIG_DIRSRV_SYSTEMD)
- ipautil.run(["/bin/systemctl", "--system", "daemon-reload"],
- raiseonerr=False)
-
- return True
-
- def restart(self, instance_name="", capture_output=True, wait=True):
- # We need to explicitly enable instances to install proper symlinks as
- # dirsrv.target.wants/ dependencies. Standard systemd service class does it
- # on enable() method call. Unfortunately, ipa-server-install does not do
- # explicit dirsrv.enable() because the service startup is handled by ipactl.
- #
- # If we wouldn't do this, our instances will not be started as systemd would
- # not have any clue about instances (PKI-IPA and the domain we serve)
- # at all. Thus, hook into dirsrv.restart().
-
- if instance_name:
- elements = self.systemd_name.split("@")
-
- srv_etc = os.path.join(paths.ETC_SYSTEMD_SYSTEM_DIR,
- self.systemd_name)
- srv_tgt = os.path.join(paths.ETC_SYSTEMD_SYSTEM_DIR,
- self.SYSTEMD_SRV_TARGET % (elements[0]))
- srv_lnk = os.path.join(srv_tgt,
- self.service_instance(instance_name))
-
- if not os.path.exists(srv_etc):
- self.enable(instance_name)
- elif not os.path.samefile(srv_etc, srv_lnk):
- os.unlink(srv_lnk)
- os.symlink(srv_etc, srv_lnk)
-
- super(FedoraDirectoryService, self).restart(instance_name,
- capture_output=capture_output, wait=wait)
-
-
-class FedoraIPAService(FedoraService):
- # Enforce restart of IPA services when we do enable it
- # This gets around the fact that after ipa-server-install systemd thinks
- # ipa.service is not yet started but all services were actually started
- # already.
- def enable(self, instance_name=""):
- super(FedoraIPAService, self).enable(instance_name)
- self.restart(instance_name)
-
-
-class FedoraSSHService(FedoraService):
- def get_config_dir(self, instance_name=""):
- return '/etc/ssh'
-
-
-class FedoraCAService(FedoraService):
- def wait_until_running(self):
- # We must not wait for the httpd proxy if httpd is not set up yet.
- # Unfortunately, knownservices.httpd.is_installed() can return
- # false positives, so check for existence of our configuration file.
- # TODO: Use a cleaner solution
- use_proxy = True
- if not (os.path.exists('/etc/httpd/conf.d/ipa.conf') and
- os.path.exists(paths.HTTPD_IPA_PKI_PROXY_CONF)):
- root_logger.debug(
- 'The httpd proxy is not installed, wait on local port')
- use_proxy = False
- root_logger.debug('Waiting until the CA is running')
- timeout = float(api.env.startup_timeout)
- op_timeout = time.time() + timeout
- while time.time() < op_timeout:
- try:
- status = dogtag.ca_status(use_proxy=use_proxy)
- except Exception:
- status = 'check interrupted'
- root_logger.debug('The CA status is: %s' % status)
- if status == 'running':
- break
- root_logger.debug('Waiting for CA to start...')
- time.sleep(1)
- else:
- raise RuntimeError('CA did not start in %ss' % timeout)
-
- def start(self, instance_name="", capture_output=True, wait=True):
- super(FedoraCAService, self).start(
- instance_name, capture_output=capture_output, wait=wait)
- if wait:
- self.wait_until_running()
-
- def restart(self, instance_name="", capture_output=True, wait=True):
- super(FedoraCAService, self).restart(
- instance_name, capture_output=capture_output, wait=wait)
- if wait:
- self.wait_until_running()
+class FedoraService(redhat_services.RedHatService):
+ system_units = fedora_system_units
# Function that constructs proper Fedora-specific server classes for services
# of specified name
def fedora_service_class_factory(name):
- if name == 'dirsrv':
- return FedoraDirectoryService(name)
- if name == 'ipa':
- return FedoraIPAService(name)
- if name == 'sshd':
- return FedoraSSHService(name)
- if name in ('pki-cad', 'pki_cad', 'pki-tomcatd', 'pki_tomcatd'):
- return FedoraCAService(name)
- return FedoraService(name)
+ if name == 'domainname':
+ return FedoraService(name)
+ return redhat_services.redhat_service_class_factory(name)
# Magicdict containing FedoraService instances.
-class FedoraServices(base_services.KnownServices):
- def __init__(self):
- services = dict()
- for s in base_services.wellknownservices:
- services[s] = fedora_service_class_factory(s)
- # Call base class constructor. This will lock services to read-only
- super(FedoraServices, self).__init__(services)
+class FedoraServices(redhat_services.RedHatServices):
+ def service_class_factory(self, name):
+ return fedora_service_class_factory(name)
# Objects below are expected to be exported by platform module
-from ipaplatform.base.services import timedate_services
+from ipaplatform.redhat.services import timedate_services
service = fedora_service_class_factory
knownservices = FedoraServices()
diff --git a/ipaplatform/fedora/tasks.py b/ipaplatform/fedora/tasks.py
index e7583f7bd..903bb9211 100644
--- a/ipaplatform/fedora/tasks.py
+++ b/ipaplatform/fedora/tasks.py
@@ -23,235 +23,11 @@
This module contains default Fedora-specific implementations of system tasks.
'''
-import os
-import shutil
-import stat
-import socket
-import sys
+from ipaplatform.redhat.tasks import RedHatTaskNamespace
-from subprocess import CalledProcessError
-from ipapython.ipa_log_manager import root_logger
-from ipapython import ipautil
+class FedoraTaskNamespace(RedHatTaskNamespace):
+ pass
-from ipaplatform.paths import paths
-from ipaplatform.fedora.authconfig import FedoraAuthConfig
-from ipaplatform.base.tasks import BaseTaskNamespace
-
-
-class FedoraTaskNamespace(BaseTaskNamespace):
-
- def restore_context(self, filepath, restorecon=paths.SBIN_RESTORECON):
- """
- restore security context on the file path
- SELinux equivalent is /path/to/restorecon <filepath>
- restorecon's return values are not reliable so we have to
- ignore them (BZ #739604).
-
- ipautil.run() will do the logging.
- """
- try:
- if os.path.exists(paths.SELINUXENABLED):
- ipautil.run([paths.SELINUXENABLED])
- else:
- # No selinuxenabled, no SELinux
- return
- except ipautil.CalledProcessError:
- # selinuxenabled returns 1 if not enabled
- return
-
- if (os.path.exists(restorecon)):
- ipautil.run([restorecon, filepath], raiseonerr=False)
-
- def check_selinux_status(self, restorecon=paths.RESTORECON):
- """
- We don't have a specific package requirement for policycoreutils
- which provides restorecon. This is because we don't require
- SELinux on client installs. However if SELinux is enabled then
- this package is required.
-
- This function returns nothing but may raise a Runtime exception
- if SELinux is enabled but restorecon is not available.
- """
- try:
- if os.path.exists(paths.SELINUXENABLED):
- ipautil.run([paths.SELINUXENABLED])
- else:
- # No selinuxenabled, no SELinux
- return
- except ipautil.CalledProcessError:
- # selinuxenabled returns 1 if not enabled
- return
-
- if not os.path.exists(restorecon):
- raise RuntimeError('SELinux is enabled but %s does not exist.\n'
- 'Install the policycoreutils package and start '
- 'the installation again.' % restorecon)
-
- def restore_pre_ipa_client_configuration(self, fstore, statestore,
- was_sssd_installed,
- was_sssd_configured):
-
- auth_config = FedoraAuthConfig()
- if statestore.has_state('authconfig'):
- # disable only those configurations that we enabled during install
- for conf in ('ldap', 'krb5', 'sssd', 'sssdauth', 'mkhomedir'):
- cnf = statestore.restore_state('authconfig', conf)
- # Do not disable sssd, as this can cause issues with its later
- # uses. Remove it from statestore however, so that it becomes
- # empty at the end of uninstall process.
- if cnf and conf != 'sssd':
- auth_config.disable(conf)
- else:
- # There was no authconfig status store
- # It means the code was upgraded after original install
- # Fall back to old logic
- auth_config.disable("ldap")
- auth_config.disable("krb5")
- if not(was_sssd_installed and was_sssd_configured):
- # Only disable sssdauth. Disabling sssd would cause issues
- # with its later uses.
- auth_config.disable("sssdauth")
- auth_config.disable("mkhomedir")
-
- auth_config.execute()
-
- def set_nisdomain(self, nisdomain):
- # Let authconfig setup the permanent configuration
- auth_config = FedoraAuthConfig()
- auth_config.add_parameter("nisdomain", nisdomain)
- auth_config.execute()
-
- def modify_nsswitch_pam_stack(self, sssd, mkhomedir, statestore):
- auth_config = FedoraAuthConfig()
-
- if sssd:
- statestore.backup_state('authconfig', 'sssd', True)
- statestore.backup_state('authconfig', 'sssdauth', True)
- auth_config.enable("sssd")
- auth_config.enable("sssdauth")
- else:
- statestore.backup_state('authconfig', 'ldap', True)
- auth_config.enable("ldap")
- auth_config.enable("forcelegacy")
-
- if mkhomedir:
- statestore.backup_state('authconfig', 'mkhomedir', True)
- auth_config.enable("mkhomedir")
-
- auth_config.execute()
-
- def modify_pam_to_use_krb5(self, statestore):
- auth_config = FedoraAuthConfig()
- statestore.backup_state('authconfig', 'krb5', True)
- auth_config.enable("krb5")
- auth_config.add_option("nostart")
- auth_config.execute()
-
- def insert_ca_cert_into_systemwide_ca_store(self, cacert_path):
- # Add the 'ipa-' prefix to cert name to avoid name collisions
- cacert_name = os.path.basename(cacert_path)
- new_cacert_path = os.path.join(paths.SYSTEMWIDE_CA_STORE,
- 'ipa-%s' % cacert_name)
-
- # Add the CA to the systemwide CA trust database
- try:
- shutil.copy(cacert_path, new_cacert_path)
- ipautil.run([paths.UPDATE_CA_TRUST])
- except OSError, e:
- root_logger.info("Failed to copy %s to %s" % (cacert_path,
- new_cacert_path))
- except CalledProcessError, e:
- root_logger.info("Failed to add CA to the systemwide "
- "CA trust database: %s" % str(e))
- else:
- root_logger.info('Added the CA to the systemwide CA trust '
- 'database.')
- return True
-
- return False
-
- def remove_ca_cert_from_systemwide_ca_store(self, cacert_path):
- # Derive the certificate name in the store
- cacert_name = os.path.basename(cacert_path)
- new_cacert_path = os.path.join(paths.SYSTEMWIDE_CA_STORE,
- 'ipa-%s' % cacert_name)
-
- # Remove CA cert from systemwide store
- if os.path.exists(new_cacert_path):
- try:
- os.remove(new_cacert_path)
- ipautil.run([paths.UPDATE_CA_TRUST])
- except OSError, e:
- root_logger.error('Could not remove: %s, %s'
- % (new_cacert_path, str(e)))
- return False
- except CalledProcessError, e:
- root_logger.error('Could not update systemwide CA trust '
- 'database: %s' % str(e))
- return False
- else:
- root_logger.info('Systemwide CA database updated.')
-
- return True
-
- def backup_and_replace_hostname(self, fstore, statestore, hostname):
- old_hostname = socket.gethostname()
- try:
- ipautil.run([paths.BIN_HOSTNAME, hostname])
- except ipautil.CalledProcessError, e:
- print >>sys.stderr, ("Failed to set this machine hostname to "
- "%s (%s)." % (hostname, str(e)))
-
- filepath = paths.ETC_HOSTNAME
- if os.path.exists(filepath):
- # read old hostname
- with open(filepath, 'r') as f:
- for line in f.readlines():
- line = line.strip()
- if not line or line.startswith('#'):
- # skip comment or empty line
- continue
- old_hostname = line
- break
- fstore.backup_file(filepath)
-
- with open(filepath, 'w') as f:
- f.write("%s\n" % hostname)
- os.chmod(filepath,
- stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH)
- os.chown(filepath, 0, 0)
- self.restore_context(filepath)
-
- # store old hostname
- statestore.backup_state('network', 'hostname', old_hostname)
-
- def restore_network_configuration(self, fstore, statestore):
- old_filepath = paths.SYSCONFIG_NETWORK
- old_hostname = statestore.get_state('network', 'hostname')
- hostname_was_configured = False
-
- if fstore.has_file(old_filepath):
- # This is Fedora >=18 instance that was upgraded from previous
- # Fedora version which held network configuration
- # in /etc/sysconfig/network
- old_filepath_restore = paths.SYSCONFIG_NETWORK_IPABKP
- fstore.restore_file(old_filepath, old_filepath_restore)
- print "Deprecated configuration file '%s' was restored to '%s'" \
- % (old_filepath, old_filepath_restore)
- hostname_was_configured = True
-
- filepath = paths.ETC_HOSTNAME
- if fstore.has_file(filepath):
- fstore.restore_file(filepath)
- hostname_was_configured = True
-
- if not hostname_was_configured and old_hostname:
- # hostname was not configured before but was set by IPA. Delete
- # /etc/hostname to restore previous configuration
- try:
- os.remove(filepath)
- except OSError:
- pass
tasks = FedoraTaskNamespace()