On 05.12.2012 15:01, Timo Aaltonen wrote:
On 17.10.2012 16:43, Petr Viktorin wrote:
On 09/21/2012 04:57 PM, Timo Aaltonen wrote:
Ok, so this is the first step before we can start to rewrite bits from
ipaserver/install to make them support other distros. There are no real
functional changes yet.

had some dependency issues installing the resulting rpm's, so didn't
test the install scripts but they should work :)



Hello,

I recommend giving the -M flag to git format-patch, so it's easier to
see changes in the patch.


Your split of the fedora16 code into two modules is unfortunate: each
tries to import the other one, and one is the other's parent. This would
need special care to get working correctly.

The best option here would probably be to put restore_context &
check_selinux_status into a separate submodule, so you don't need to
import fedora16 from services.

Furthermore, in fedora16/__init__.py, you have:
     from ipapython.platform.fedora16.service import *
This imports everything from that module, including e.g. "redhat" or
"os".
Please avoid star imports. List all the imported names explicitly, or
import the module and then use qualified names.


Other than that, after a trivial rebase the patch seems to work fine on
Fedora. Thanks!

And finally, here is version 2.

fixed all the above, I think.. make-lint passes, make rpms too.

Here's v3, thanks to your rebase to an even more current master :)

>From 0f2be82c20411c5db2627702715dda73d9ed3cb3 Mon Sep 17 00:00:00 2001
From: Timo Aaltonen <tjaal...@ubuntu.com>
Date: Wed, 5 Dec 2012 14:58:06 +0200
Subject: [PATCH] convert the base platform modules into packages

---
 freeipa.spec.in                                    |    8 +
 ipapython/platform/{base.py => base/__init__.py}   |    0
 ipapython/platform/{ => base}/systemd.py           |    5 +-
 ipapython/platform/fedora16/__init__.py            |   49 ++++
 ipapython/platform/fedora16/selinux.py             |   26 ++
 .../platform/{fedora16.py => fedora16/service.py}  |   42 +---
 .../platform/{fedora18.py => fedora18/__init__.py} |    0
 ipapython/platform/redhat.py                       |  258 --------------------
 ipapython/platform/redhat/__init__.py              |  129 ++++++++++
 ipapython/platform/redhat/auth.py                  |   49 ++++
 ipapython/platform/redhat/service.py               |  123 ++++++++++
 ipapython/setup.py.in                              |    7 +-
 12 files changed, 399 insertions(+), 297 deletions(-)
 rename ipapython/platform/{base.py => base/__init__.py} (100%)
 rename ipapython/platform/{ => base}/systemd.py (99%)
 create mode 100644 ipapython/platform/fedora16/__init__.py
 create mode 100644 ipapython/platform/fedora16/selinux.py
 rename ipapython/platform/{fedora16.py => fedora16/service.py} (81%)
 rename ipapython/platform/{fedora18.py => fedora18/__init__.py} (100%)
 delete mode 100644 ipapython/platform/redhat.py
 create mode 100644 ipapython/platform/redhat/__init__.py
 create mode 100644 ipapython/platform/redhat/auth.py
 create mode 100644 ipapython/platform/redhat/service.py

diff --git a/freeipa.spec.in b/freeipa.spec.in
index 8a095db..33fb678 100644
--- a/freeipa.spec.in
+++ b/freeipa.spec.in
@@ -724,8 +724,16 @@ fi
 %doc COPYING README Contributors.txt
 %dir %{python_sitelib}/ipapython
 %dir %{python_sitelib}/ipapython/platform
+%dir %{python_sitelib}/ipapython/platform/base
+%dir %{python_sitelib}/ipapython/platform/fedora16
+%dir %{python_sitelib}/ipapython/platform/fedora18
+%dir %{python_sitelib}/ipapython/platform/redhat
 %{python_sitelib}/ipapython/*.py*
 %{python_sitelib}/ipapython/platform/*.py*
+%{python_sitelib}/ipapython/platform/base/*.py*
+%{python_sitelib}/ipapython/platform/fedora16/*.py*
+%{python_sitelib}/ipapython/platform/fedora18/*.py*
+%{python_sitelib}/ipapython/platform/redhat/*.py*
 %dir %{python_sitelib}/ipalib
 %{python_sitelib}/ipalib/*
 %{python_sitearch}/default_encoding_utf8.so
diff --git a/ipapython/platform/base.py b/ipapython/platform/base/__init__.py
similarity index 100%
rename from ipapython/platform/base.py
rename to ipapython/platform/base/__init__.py
diff --git a/ipapython/platform/systemd.py b/ipapython/platform/base/systemd.py
similarity index 99%
rename from ipapython/platform/systemd.py
rename to ipapython/platform/base/systemd.py
index bb6c009..9846560 100644
--- a/ipapython/platform/systemd.py
+++ b/ipapython/platform/base/systemd.py
@@ -17,9 +17,12 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
+import os
+import shutil
+import sys
+
 from ipapython import ipautil
 from ipapython.platform import base
-import sys, os, shutil
 from ipalib import api
 
 class SystemdService(base.PlatformService):
diff --git a/ipapython/platform/fedora16/__init__.py b/ipapython/platform/fedora16/__init__.py
new file mode 100644
index 0000000..c730348
--- /dev/null
+++ b/ipapython/platform/fedora16/__init__.py
@@ -0,0 +1,49 @@
+# Author: Alexander Bokovoy <aboko...@redhat.com>
+#
+# Copyright (C) 2011   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.platform import base, redhat
+from ipapython.platform.fedora16 import selinux
+from ipapython.platform.fedora16.service import f16_service, Fedora16Services
+
+# All what we allow exporting directly from this module
+# Everything else is made available through these symbols when they are
+# directly imported into ipapython.services:
+# authconfig -- class reference for platform-specific implementation of
+#               authconfig(8)
+# service    -- class reference for platform-specific implementation of a
+#               PlatformService class
+# knownservices -- factory instance to access named services IPA cares about,
+#                  names are ipapython.services.wellknownservices
+# backup_and_replace_hostname -- platform-specific way to set hostname and
+#                                make it persistent over reboots
+# restore_context -- platform-sepcific way to restore security context, if
+#                    applicable
+# check_selinux_status -- platform-specific way to see if SELinux is enabled
+#                         and restorecon is installed.
+__all__ = ['authconfig', 'service', 'knownservices',
+    'backup_and_replace_hostname', 'restore_context', 'check_selinux_status',
+    'restore_network_configuration']
+
+authconfig = redhat.authconfig
+service = f16_service
+knownservices = Fedora16Services()
+backup_and_replace_hostname = redhat.backup_and_replace_hostname
+restore_context = selinux.restore_context
+check_selinux_status = selinux.check_selinux_status
+restore_network_configuration = redhat.restore_network_configuration
diff --git a/ipapython/platform/fedora16/selinux.py b/ipapython/platform/fedora16/selinux.py
new file mode 100644
index 0000000..cf71a38
--- /dev/null
+++ b/ipapython/platform/fedora16/selinux.py
@@ -0,0 +1,26 @@
+# Author: Alexander Bokovoy <aboko...@redhat.com>
+#
+# Copyright (C) 2011   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.platform import redhat
+
+def restore_context(filepath, restorecon='/usr/sbin/restorecon'):
+    return redhat.restore_context(filepath, restorecon)
+
+def check_selinux_status(restorecon='/usr/sbin/restorecon'):
+    return redhat.check_selinux_status(restorecon)
diff --git a/ipapython/platform/fedora16.py b/ipapython/platform/fedora16/service.py
similarity index 81%
rename from ipapython/platform/fedora16.py
rename to ipapython/platform/fedora16/service.py
index 8609e4c..c2e35d3 100644
--- a/ipapython/platform/fedora16.py
+++ b/ipapython/platform/fedora16/service.py
@@ -21,31 +21,12 @@ import os
 import time
 
 from ipapython import ipautil, dogtag
-from ipapython.platform import base, redhat, systemd
+from ipapython.platform import base, redhat
+from ipapython.platform.base import systemd
+from ipapython.platform.fedora16 import selinux
 from ipapython.ipa_log_manager import root_logger
 from ipalib import api
 
-# All what we allow exporting directly from this module
-# Everything else is made available through these symbols when they are
-# directly imported into ipapython.services:
-# authconfig -- class reference for platform-specific implementation of
-#               authconfig(8)
-# service    -- class reference for platform-specific implementation of a
-#               PlatformService class
-# knownservices -- factory instance to access named services IPA cares about,
-#                  names are ipapython.services.wellknownservices
-# backup_and_replace_hostname -- platform-specific way to set hostname and
-#                                make it persistent over reboots
-# restore_network_configuration -- platform-specific way of restoring network
-#                                  configuration (e.g. static hostname)
-# restore_context -- platform-sepcific way to restore security context, if
-#                    applicable
-# check_selinux_status -- platform-specific way to see if SELinux is enabled
-#                         and restorecon is installed.
-__all__ = ['authconfig', 'service', 'knownservices',
-    'backup_and_replace_hostname', 'restore_context', 'check_selinux_status',
-    'restore_network_configuration']
-
 # 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
@@ -85,6 +66,7 @@ class Fedora16Service(systemd.SystemdService):
                 # systemd, default to foo.service style then
                 systemd_name = "%s.service" % (service_name)
         super(Fedora16Service, self).__init__(service_name, systemd_name)
+
 # Special handling of directory server service
 #
 # We need to explicitly enable instances to install proper symlinks as
@@ -107,7 +89,7 @@ class Fedora16DirectoryService(Fedora16Service):
             # into dirsrv@.service unit
             replacevars = {'LimitNOFILE':'8192'}
             ipautil.inifile_replace_variables(dirsrv_systemd, 'service', replacevars=replacevars)
-            restore_context(dirsrv_systemd)
+            selinux.restore_context(dirsrv_systemd)
             ipautil.run(["/bin/systemctl", "--system", "daemon-reload"],raiseonerr=False)
 
     def restart(self, instance_name="", capture_output=True, wait=True):
@@ -136,7 +118,6 @@ class Fedora16SSHService(Fedora16Service):
     def get_config_dir(self, instance_name=""):
         return '/etc/ssh'
 
-
 class Fedora16CAService(Fedora16Service):
     def __wait_until_running(self):
         # We must not wait for the httpd proxy if httpd is not set up yet.
@@ -176,7 +157,6 @@ class Fedora16CAService(Fedora16Service):
         if wait:
             self.__wait_until_running()
 
-
 # Redirect directory server service through special sub-class due to its
 # special handling of instances
 def f16_service(name):
@@ -197,15 +177,3 @@ class Fedora16Services(base.KnownServices):
             services[s] = f16_service(s)
         # Call base class constructor. This will lock services to read-only
         super(Fedora16Services, self).__init__(services)
-
-def restore_context(filepath, restorecon='/usr/sbin/restorecon'):
-    return redhat.restore_context(filepath, restorecon)
-
-def check_selinux_status(restorecon='/usr/sbin/restorecon'):
-    return redhat.check_selinux_status(restorecon)
-
-authconfig = redhat.authconfig
-service = f16_service
-knownservices = Fedora16Services()
-backup_and_replace_hostname = redhat.backup_and_replace_hostname
-restore_network_configuration = redhat.restore_network_configuration
diff --git a/ipapython/platform/fedora18.py b/ipapython/platform/fedora18/__init__.py
similarity index 100%
rename from ipapython/platform/fedora18.py
rename to ipapython/platform/fedora18/__init__.py
diff --git a/ipapython/platform/redhat.py b/ipapython/platform/redhat.py
deleted file mode 100644
index 389785c..0000000
--- a/ipapython/platform/redhat.py
+++ /dev/null
@@ -1,258 +0,0 @@
-# Authors: Simo Sorce <sso...@redhat.com>
-#          Alexander Bokovoy <aboko...@redhat.com>
-#
-# Copyright (C) 2007-2011   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/>.
-#
-
-import tempfile
-import re
-import os
-import stat
-import sys
-import socket
-import stat
-import time
-
-from ipapython import ipautil
-from ipapython.platform import base
-from ipapython.ipa_log_manager import root_logger
-from ipalib import api
-
-# All what we allow exporting directly from this module
-# Everything else is made available through these symbols when they are
-# directly imported into ipapython.services:
-#
-# authconfig -- class reference for platform-specific implementation of
-#               authconfig(8)
-# service    -- class reference for platform-specific implementation of a
-#               PlatformService class
-# knownservices -- factory instance to access named services IPA cares about,
-#                  names are ipapython.services.wellknownservices
-# backup_and_replace_hostname -- platform-specific way to set hostname and
-#                                make it persistent over reboots
-# restore_network_configuration -- platform-specific way of restoring network
-#                                  configuration (e.g. static hostname)
-# restore_context -- platform-sepcific way to restore security context, if
-#                    applicable
-# check_selinux_status -- platform-specific way to see if SELinux is enabled
-#                         and restorecon is installed.
-__all__ = ['authconfig', 'service', 'knownservices',
-    'backup_and_replace_hostname', 'restore_context', 'check_selinux_status',
-    'restore_network_configuration']
-
-class RedHatService(base.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.wellknownports:
-            ports = base.wellknownports[instance_name]
-        else:
-            if self.service_name in base.wellknownports:
-                ports = base.wellknownports[self.service_name]
-        if ports:
-            ipautil.wait_for_open_ports('localhost', ports, api.env.startup_timeout)
-
-    def stop(self, instance_name="", capture_output=True):
-        ipautil.run(["/sbin/service", self.service_name, "stop", instance_name], capture_output=capture_output)
-        super(RedHatService, self).stop(instance_name)
-
-    def start(self, instance_name="", capture_output=True, wait=True):
-        ipautil.run(["/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(RedHatService, self).start(instance_name)
-
-    def restart(self, instance_name="", capture_output=True, wait=True):
-        ipautil.run(["/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:
-            (sout,serr,rcode) = ipautil.run(["/sbin/service", self.service_name, "status", instance_name])
-            if sout.find("is stopped") >= 0:
-                ret = False
-        except ipautil.CalledProcessError:
-                ret = False
-        return ret
-
-    def is_installed(self):
-        installed = True
-        try:
-            ipautil.run(["/sbin/service", self.service_name, "status"])
-        except ipautil.CalledProcessError, e:
-            if e.returncode == 1:
-                # service is not installed or there is other serious issue
-                installed = False
-        return installed
-
-    def is_enabled(self, instance_name=""):
-        (stdout, stderr, returncode) = ipautil.run(["/sbin/chkconfig", self.service_name],raiseonerr=False)
-        return (returncode == 0)
-
-    def enable(self, instance_name=""):
-        ipautil.run(["/sbin/chkconfig", self.service_name, "on"])
-
-    def disable(self, instance_name=""):
-        ipautil.run(["/sbin/chkconfig", self.service_name, "off"])
-
-    def install(self, instance_name=""):
-        ipautil.run(["/sbin/chkconfig", "--add", self.service_name])
-
-    def remove(self, instance_name=""):
-        ipautil.run(["/sbin/chkconfig", "--del", self.service_name])
-
-class RedHatSSHService(RedHatService):
-    def get_config_dir(self, instance_name=""):
-        return '/etc/ssh'
-
-class RedHatHTTPDService(RedHatService):
-    def restart(self, instance_name="", capture_output=True, wait=True):
-        try:
-            super(RedHatHTTPDService, self).restart(instance_name, capture_output, wait)
-        except ipautil.CalledProcessError:
-            # http may have issues with binding to ports, try to fallback
-            # https://bugzilla.redhat.com/show_bug.cgi?id=845405
-            root_logger.debug("%s restart failed, try to stop&start again", self.service_name)
-            time.sleep(5)
-            self.stop(instance_name, capture_output)
-            time.sleep(5)
-            self.start(instance_name, capture_output, wait)
-
-class RedHatAuthConfig(base.AuthConfig):
-    """
-    AuthConfig class implements system-independent interface to configure
-    system authentication resources. In Red Hat-produced systems this is done with
-    authconfig(8) utility.
-    """
-    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):
-        args = self.__build_args()
-        ipautil.run(["/usr/sbin/authconfig"]+args)
-
-def redhat_service(name):
-    if name == 'sshd':
-        return RedHatSSHService(name)
-    elif name == 'httpd':
-        return RedHatHTTPDService(name)
-    return RedHatService(name)
-
-class RedHatServices(base.KnownServices):
-    def __init__(self):
-        services = dict()
-        for s in base.wellknownservices:
-            services[s] = redhat_service(s)
-        # Call base class constructor. This will lock services to read-only
-        super(RedHatServices, self).__init__(services)
-
-authconfig = RedHatAuthConfig
-service = redhat_service
-knownservices = RedHatServices()
-
-def restore_context(filepath, restorecon='/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('/usr/sbin/selinuxenabled')):
-            ipautil.run(["/usr/sbin/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 backup_and_replace_hostname(fstore, statestore, hostname):
-    old_hostname = socket.gethostname()
-    try:
-        ipautil.run(['/bin/hostname', hostname])
-    except ipautil.CalledProcessError, e:
-        print >>sys.stderr, "Failed to set this machine hostname to %s (%s)." % (hostname, str(e))
-    replacevars = {'HOSTNAME':hostname}
-
-    filepath = '/etc/sysconfig/network'
-    if not os.path.exists(filepath):
-        # file doesn't exist; create it with correct ownership & mode
-        open(filepath, 'a').close()
-        os.chmod(filepath,
-            stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH)
-        os.chown(filepath, 0, 0)
-    old_values = ipautil.backup_config_and_replace_variables(
-        fstore, filepath, replacevars=replacevars)
-    restore_context("/etc/sysconfig/network")
-
-    if 'HOSTNAME' in old_values:
-        statestore.backup_state('network', 'hostname', old_values['HOSTNAME'])
-    else:
-        statestore.backup_state('network', 'hostname', old_hostname)
-
-def restore_network_configuration(fstore, statestore):
-    filepath = '/etc/sysconfig/network'
-    if fstore.has_file(filepath):
-        fstore.restore_file(filepath)
-
-def check_selinux_status(restorecon='/sbin/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('/usr/sbin/selinuxenabled')):
-            ipautil.run(["/usr/sbin/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.\nInstall the policycoreutils package and start the installation again.' % restorecon)
diff --git a/ipapython/platform/redhat/__init__.py b/ipapython/platform/redhat/__init__.py
new file mode 100644
index 0000000..d0ef17b
--- /dev/null
+++ b/ipapython/platform/redhat/__init__.py
@@ -0,0 +1,129 @@
+# Authors: Simo Sorce <sso...@redhat.com>
+#          Alexander Bokovoy <aboko...@redhat.com>
+#
+# Copyright (C) 2007-2011   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/>.
+#
+
+import os
+import socket
+import stat
+import sys
+
+from ipapython import ipautil
+from ipapython.platform.redhat.auth import RedHatAuthConfig
+from ipapython.platform.redhat.service import redhat_service, RedHatServices
+
+# All what we allow exporting directly from this module
+# Everything else is made available through these symbols when they are
+# directly imported into ipapython.services:
+#
+# authconfig -- class reference for platform-specific implementation of
+#               authconfig(8)
+# service    -- class reference for platform-specific implementation of a
+#               PlatformService class
+# knownservices -- factory instance to access named services IPA cares about,
+#                  names are ipapython.services.wellknownservices
+# backup_and_replace_hostname -- platform-specific way to set hostname and
+#                                make it persistent over reboots
+# restore_network_configuration -- platform-specific way of restoring network
+#                                  configuration (e.g. static hostname)
+# restore_context -- platform-sepcific way to restore security context, if
+#                    applicable
+# check_selinux_status -- platform-specific way to see if SELinux is enabled
+#                         and restorecon is installed.
+__all__ = ['authconfig', 'service', 'knownservices',
+    'backup_and_replace_hostname', 'restore_context', 'check_selinux_status',
+    'restore_network_configuration']
+
+authconfig = RedHatAuthConfig
+service = redhat_service
+knownservices = RedHatServices()
+
+def restore_context(filepath, restorecon='/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('/usr/sbin/selinuxenabled')):
+            ipautil.run(["/usr/sbin/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 backup_and_replace_hostname(fstore, statestore, hostname):
+    old_hostname = socket.gethostname()
+    try:
+        ipautil.run(['/bin/hostname', hostname])
+    except ipautil.CalledProcessError, e:
+        print >>sys.stderr, "Failed to set this machine hostname to %s (%s)." % (hostname, str(e))
+    replacevars = {'HOSTNAME':hostname}
+
+    filepath = '/etc/sysconfig/network'
+    if not os.path.exists(filepath):
+        # file doesn't exist; create it with correct ownership & mode
+        open(filepath, 'a').close()
+        os.chmod(filepath,
+            stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH)
+        os.chown(filepath, 0, 0)
+    old_values = ipautil.backup_config_and_replace_variables(
+        fstore, filepath, replacevars=replacevars)
+    restore_context("/etc/sysconfig/network")
+
+    if 'HOSTNAME' in old_values:
+        statestore.backup_state('network', 'hostname', old_values['HOSTNAME'])
+    else:
+        statestore.backup_state('network', 'hostname', old_hostname)
+
+def check_selinux_status(restorecon='/sbin/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('/usr/sbin/selinuxenabled')):
+            ipautil.run(["/usr/sbin/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.\nInstall the policycoreutils package and start the installation again.' % restorecon)
+
+def restore_network_configuration(fstore, statestore):
+    filepath = '/etc/sysconfig/network'
+    if fstore.has_file(filepath):
+        fstore.restore_file(filepath)
diff --git a/ipapython/platform/redhat/auth.py b/ipapython/platform/redhat/auth.py
new file mode 100644
index 0000000..93c3c5e
--- /dev/null
+++ b/ipapython/platform/redhat/auth.py
@@ -0,0 +1,49 @@
+# Authors: Simo Sorce <sso...@redhat.com>
+#          Alexander Bokovoy <aboko...@redhat.com>
+#
+# Copyright (C) 2007-2011   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
+from ipapython.platform import base
+
+class RedHatAuthConfig(base.AuthConfig):
+    """
+    AuthConfig class implements system-independent interface to configure
+    system authentication resources. In Red Hat-produced systems this is done with
+    authconfig(8) utility.
+    """
+    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):
+        args = self.__build_args()
+        ipautil.run(["/usr/sbin/authconfig"]+args)
diff --git a/ipapython/platform/redhat/service.py b/ipapython/platform/redhat/service.py
new file mode 100644
index 0000000..61511b4
--- /dev/null
+++ b/ipapython/platform/redhat/service.py
@@ -0,0 +1,123 @@
+# Authors: Simo Sorce <sso...@redhat.com>
+#          Alexander Bokovoy <aboko...@redhat.com>
+#
+# Copyright (C) 2007-2011   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/>.
+#
+
+import time
+
+from ipapython import ipautil
+from ipapython.ipa_log_manager import root_logger
+from ipapython.platform import base
+from ipalib import api
+
+class RedHatService(base.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.wellknownports:
+            ports = base.wellknownports[instance_name]
+        else:
+            if self.service_name in base.wellknownports:
+                ports = base.wellknownports[self.service_name]
+        if ports:
+            ipautil.wait_for_open_ports('localhost', ports, api.env.startup_timeout)
+
+    def stop(self, instance_name="", capture_output=True):
+        ipautil.run(["/sbin/service", self.service_name, "stop", instance_name], capture_output=capture_output)
+        super(RedHatService, self).stop(instance_name)
+
+    def start(self, instance_name="", capture_output=True, wait=True):
+        ipautil.run(["/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(RedHatService, self).start(instance_name)
+
+    def restart(self, instance_name="", capture_output=True, wait=True):
+        ipautil.run(["/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:
+            (sout,serr,rcode) = ipautil.run(["/sbin/service", self.service_name, "status", instance_name])
+            if sout.find("is stopped") >= 0:
+                ret = False
+        except ipautil.CalledProcessError:
+                ret = False
+        return ret
+
+    def is_installed(self):
+        installed = True
+        try:
+            ipautil.run(["/sbin/service", self.service_name, "status"])
+        except ipautil.CalledProcessError, e:
+            if e.returncode == 1:
+                # service is not installed or there is other serious issue
+                installed = False
+        return installed
+
+    def is_enabled(self, instance_name=""):
+        (stdout, stderr, returncode) = ipautil.run(["/sbin/chkconfig", self.service_name],raiseonerr=False)
+        return (returncode == 0)
+
+    def enable(self, instance_name=""):
+        ipautil.run(["/sbin/chkconfig", self.service_name, "on"])
+
+    def disable(self, instance_name=""):
+        ipautil.run(["/sbin/chkconfig", self.service_name, "off"])
+
+    def install(self, instance_name=""):
+        ipautil.run(["/sbin/chkconfig", "--add", self.service_name])
+
+    def remove(self, instance_name=""):
+        ipautil.run(["/sbin/chkconfig", "--del", self.service_name])
+
+class RedHatSSHService(RedHatService):
+    def get_config_dir(self, instance_name=""):
+        return '/etc/ssh'
+
+class RedHatHTTPDService(RedHatService):
+    def restart(self, instance_name="", capture_output=True, wait=True):
+        try:
+            super(RedHatHTTPDService, self).restart(instance_name, capture_output, wait)
+        except ipautil.CalledProcessError:
+            # http may have issues with binding to ports, try to fallback
+            # https://bugzilla.redhat.com/show_bug.cgi?id=845405
+            root_logger.debug("%s restart failed, try to stop&start again", self.service_name)
+            time.sleep(5)
+            self.stop(instance_name, capture_output)
+            time.sleep(5)
+            self.start(instance_name, capture_output, wait)
+
+def redhat_service(name):
+    if name == 'sshd':
+        return RedHatSSHService(name)
+    elif name == 'httpd':
+        return RedHatHTTPDService(name)
+    return RedHatService(name)
+
+class RedHatServices(base.KnownServices):
+    def __init__(self):
+        services = dict()
+        for s in base.wellknownservices:
+            services[s] = redhat_service(s)
+        # Call base class constructor. This will lock services to read-only
+        super(RedHatServices, self).__init__(services)
diff --git a/ipapython/setup.py.in b/ipapython/setup.py.in
index df1cacf..d3bbcaf 100644
--- a/ipapython/setup.py.in
+++ b/ipapython/setup.py.in
@@ -65,7 +65,12 @@ def setup_package():
             classifiers=filter(None, CLASSIFIERS.split('\n')),
             platforms = ["Linux", "Solaris", "Unix"],
             package_dir = {'ipapython': ''},
-            packages = [ "ipapython", "ipapython.platform" ],
+            packages = [ "ipapython",
+                         "ipapython.platform",
+                         "ipapython.platform.base",
+                         "ipapython.platform.fedora16",
+                         "ipapython.platform.fedora18",
+                         "ipapython.platform.redhat" ],
         )
     finally:
         del sys.path[0]
-- 
1.7.10.4

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to