diff options
-rwxr-xr-x | install/tools/ipa-replica-install | 13 | ||||
-rwxr-xr-x | install/tools/ipa-server-install | 17 | ||||
-rwxr-xr-x | ipa-client/ipa-install/ipa-client-install | 27 | ||||
-rw-r--r-- | ipa-client/ipaclient/ntpconf.py | 68 | ||||
-rw-r--r-- | ipa-client/man/ipa-client-install.1 | 3 | ||||
-rw-r--r-- | ipapython/platform/base.py | 6 | ||||
-rw-r--r-- | ipapython/platform/fedora16.py | 5 | ||||
-rw-r--r-- | ipapython/platform/fedora18.py | 7 | ||||
-rw-r--r-- | ipapython/platform/redhat.py | 5 |
9 files changed, 146 insertions, 5 deletions
diff --git a/install/tools/ipa-replica-install b/install/tools/ipa-replica-install index 7d7115cfd..b09cbca43 100755 --- a/install/tools/ipa-replica-install +++ b/install/tools/ipa-replica-install @@ -49,6 +49,7 @@ from ipapython import services as ipaservices from ipapython.ipa_log_manager import * from ipapython import dogtag from ipapython.dn import DN +import ipaclient.ntpconf log_file_name = "/var/log/ipareplica-install.log" CACERT = "/etc/ipa/ca.crt" @@ -438,6 +439,17 @@ def main(): check_dirsrv() + if options.conf_ntp: + try: + ipaclient.ntpconf.check_timedate_services() + except ipaclient.ntpconf.NTPConflictingService, e: + print "WARNING: conflicting time&date synchronization service '%s'" \ + " will" % e.conflicting_service + print "be disabled in favor of ntpd" + print "" + except ipaclient.ntpconf.NTPConfigurationError: + pass + # get the directory manager password dirman_password = options.password if not dirman_password: @@ -613,6 +625,7 @@ def main(): # Configure ntpd if options.conf_ntp: + ipaclient.ntpconf.force_ntpd(sstore) ntp = ntpinstance.NTPInstance() ntp.create_instance() diff --git a/install/tools/ipa-server-install b/install/tools/ipa-server-install index 306d1e07b..dcf751904 100755 --- a/install/tools/ipa-server-install +++ b/install/tools/ipa-server-install @@ -68,6 +68,8 @@ from ipapython import services as ipaservices from ipapython.ipa_log_manager import * from ipapython.dn import DN +import ipaclient.ntpconf + pw_name = None uninstalling = False installation_cleanup = True @@ -507,6 +509,9 @@ def uninstall(): # ipa-client-install removes /etc/ipa/default.conf sstore._load() + + ipaclient.ntpconf.restore_forced_ntpd(sstore) + group_exists = sstore.restore_state("install", "group_exists") ipaservices.knownservices.ipa.disable() @@ -715,6 +720,17 @@ def main(): # Make sure the 389-ds ports are available check_dirsrv(options.unattended) + if options.conf_ntp: + try: + ipaclient.ntpconf.check_timedate_services() + except ipaclient.ntpconf.NTPConflictingService, e: + print "WARNING: conflicting time&date synchronization service '%s'" \ + " will be disabled" % e.conflicting_service + print "in favor of ntpd" + print "" + except ipaclient.ntpconf.NTPConfigurationError: + pass + realm_name = "" host_name = "" domain_name = "" @@ -907,6 +923,7 @@ def main(): # Configure ntpd if options.conf_ntp: + ipaclient.ntpconf.force_ntpd(sstore) ntp = ntpinstance.NTPInstance(fstore) if not ntp.is_configured(): ntp.create_instance() diff --git a/ipa-client/ipa-install/ipa-client-install b/ipa-client/ipa-install/ipa-client-install index 9e45589b8..975759169 100755 --- a/ipa-client/ipa-install/ipa-client-install +++ b/ipa-client/ipa-install/ipa-client-install @@ -89,6 +89,9 @@ def parse_options(): basic_group.add_option("--ntp-server", dest="ntp_server", help="ntp server to use") basic_group.add_option("-N", "--no-ntp", action="store_false", help="do not configure ntp", default=True, dest="conf_ntp") + basic_group.add_option("", "--force-ntpd", dest="force_ntpd", + action="store_true", default=False, + help="Stop and disable any time&date synchronization services besides ntpd") basic_group.add_option("--ssh-trust-dns", dest="trust_sshfp", default=False, action="store_true", help="configure OpenSSH client to trust DNS SSHFP records") basic_group.add_option("--no-ssh", dest="conf_ssh", default=True, action="store_false", @@ -142,6 +145,9 @@ def parse_options(): if (options.server and not options.domain): parser.error("--server cannot be used without providing --domain") + if options.force_ntpd and not options.conf_ntp: + parser.error("--force-ntpd cannot be used together with --no-ntp") + return safe_opts, options def logging_setup(options): @@ -519,6 +525,8 @@ def uninstall(options, env): if restored: ipaservices.knownservices.ntpd.restart() + ipaclient.ntpconf.restore_forced_ntpd(statestore) + if was_sshd_configured and ipaservices.knownservices.sshd.is_running(): ipaservices.knownservices.sshd.restart() @@ -1270,6 +1278,22 @@ def install(options, env, fstore, statestore): cli_domain_source = 'Unknown source' cli_server_source = 'Unknown source' + if options.conf_ntp and not options.on_master and not options.force_ntpd: + try: + ipaclient.ntpconf.check_timedate_services() + except ipaclient.ntpconf.NTPConflictingService, e: + print "WARNING: ntpd time&date synchronization service will not" \ + " be configured as" + print "conflicting service (%s) is enabled" % e.conflicting_service + print "Use --force-ntpd option to disable it and force configuration" \ + " of ntpd" + print "" + + # configuration of ntpd is disabled in this case + options.conf_ntp = False + except ipaclient.ntpconf.NTPConfigurationError: + pass + if options.unattended and (options.password is None and options.principal is None and options.prompt_password is False) and not options.on_master: root_logger.error("One of password and principal are required.") return CLIENT_INSTALL_ERROR @@ -1884,6 +1908,9 @@ def install(options, env, fstore, statestore): "/etc/ldap.conf failed: %s", str(e)) if options.conf_ntp and not options.on_master: + # disable other time&date services first + if options.force_ntpd: + ipaclient.ntpconf.force_ntpd(statestore) if options.ntp_server: ntp_server = options.ntp_server else: diff --git a/ipa-client/ipaclient/ntpconf.py b/ipa-client/ipaclient/ntpconf.py index 6e4173145..eb9afdeee 100644 --- a/ipa-client/ipaclient/ntpconf.py +++ b/ipa-client/ipaclient/ntpconf.py @@ -21,6 +21,7 @@ from ipapython import ipautil from ipapython import services as ipaservices import shutil import os +import sys ntp_conf = """# Permit time synchronization with our time source, but do not # permit the source to query or modify the service on this system. @@ -154,3 +155,70 @@ def synconce_ntp(server_fqdn): except: pass return False + +class NTPConfigurationError(Exception): + pass + +class NTPConflictingService(NTPConfigurationError): + def __init__(self, message='', conflicting_service=None): + super(NTPConflictingService, self).__init__(self, message) + self.conflicting_service = conflicting_service + +def check_timedate_services(): + """ + System may contain conflicting services used for time&date synchronization. + As IPA server/client supports only ntpd, make sure that other services are + not enabled to prevent conflicts. For example when both chronyd and ntpd + are enabled, systemd would always start only chronyd to manage system + time&date which would make IPA configuration of ntpd ineffective. + + Reference links: + https://fedorahosted.org/freeipa/ticket/2974 + http://fedoraproject.org/wiki/Features/ChronyDefaultNTP + """ + for service in ipaservices.timedate_services: + if service == 'ntpd': + continue + # Make sure that the service is not enabled + service = ipaservices.service(service) + if service.is_enabled() or service.is_running(): + raise NTPConflictingService(conflicting_service=service.service_name) + +def force_ntpd(statestore): + """ + Force ntpd configuration and disable and stop any other conflicting + time&date service + """ + for service in ipaservices.timedate_services: + if service == 'ntpd': + continue + service = ipaservices.service(service) + enabled = service.is_enabled() + running = service.is_running() + + if enabled or running: + statestore.backup_state(service.service_name, 'enabled', enabled) + statestore.backup_state(service.service_name, 'running', running) + + if running: + service.stop() + + if enabled: + service.disable() + +def restore_forced_ntpd(statestore): + """ + Restore from --force-ntpd installation and enable/start service that were + disabled/stopped during installation + """ + for service in ipaservices.timedate_services: + if service == 'ntpd': + continue + if statestore.has_state(service): + service = ipaservices.service(service) + enabled = statestore.restore_state(service.service_name, 'enabled') + running = statestore.restore_state(service.service_name, 'running') + if enabled: + service.enable() + if running: + service.start() diff --git a/ipa-client/man/ipa-client-install.1 b/ipa-client/man/ipa-client-install.1 index 382d4872f..abd74666e 100644 --- a/ipa-client/man/ipa-client-install.1 +++ b/ipa-client/man/ipa-client-install.1 @@ -71,6 +71,9 @@ Configure ntpd to use this NTP server. \fB\-N\fR, \fB\-\-no\-ntp\fR Do not configure or enable NTP. .TP +\fB\-\-force\-ntpd\fR +Stop and disable any time&date synchronization services besides ntpd. +.TP \fB\-\-ssh\-trust\-dns\fR Configure OpenSSH client to trust DNS SSHFP records. .TP diff --git a/ipapython/platform/base.py b/ipapython/platform/base.py index 41a9c83e7..e2aa33faf 100644 --- a/ipapython/platform/base.py +++ b/ipapython/platform/base.py @@ -27,7 +27,11 @@ import os wellknownservices = ['certmonger', 'dirsrv', 'httpd', 'ipa', 'krb5kdc', 'messagebus', 'nslcd', 'nscd', 'ntpd', 'portmap', 'rpcbind', 'kadmin', 'sshd', 'autofs', 'rpcgssd', - 'rpcidmapd', 'pki_tomcatd', 'pki-cad'] + 'rpcidmapd', 'pki_tomcatd', 'pki-cad', 'chronyd'] + +# System may support more time&date services. FreeIPA supports ntpd only, other +# services will be disabled during IPA installation +timedate_services = ['ntpd', 'chronyd'] # The common ports for these services. This is used to wait for the diff --git a/ipapython/platform/fedora16.py b/ipapython/platform/fedora16.py index 8609e4c4b..628cad13d 100644 --- a/ipapython/platform/fedora16.py +++ b/ipapython/platform/fedora16.py @@ -44,7 +44,10 @@ from ipalib import api # and restorecon is installed. __all__ = ['authconfig', 'service', 'knownservices', 'backup_and_replace_hostname', 'restore_context', 'check_selinux_status', - 'restore_network_configuration'] + 'restore_network_configuration', 'timedate_services'] + +# Just copy a referential list of timedate services +timedate_services = list(base.timedate_services) # For beginning just remap names to add .service # As more services will migrate to systemd, unit names will deviate and diff --git a/ipapython/platform/fedora18.py b/ipapython/platform/fedora18.py index c6d32866f..d12bdcad5 100644 --- a/ipapython/platform/fedora18.py +++ b/ipapython/platform/fedora18.py @@ -23,7 +23,7 @@ import socket import os from ipapython import ipautil -from ipapython.platform import fedora16 +from ipapython.platform import fedora16, base # All what we allow exporting directly from this module # Everything else is made available through these symbols when they are @@ -44,7 +44,10 @@ from ipapython.platform import fedora16 # and restorecon is installed. __all__ = ['authconfig', 'service', 'knownservices', 'backup_and_replace_hostname', 'restore_context', 'check_selinux_status', - 'restore_network_configuration'] + 'restore_network_configuration', 'timedate_services'] + +# Just copy a referential list of timedate services +timedate_services = list(base.timedate_services) def backup_and_replace_hostname(fstore, statestore, hostname): old_hostname = socket.gethostname() diff --git a/ipapython/platform/redhat.py b/ipapython/platform/redhat.py index 389785c7b..274062e46 100644 --- a/ipapython/platform/redhat.py +++ b/ipapython/platform/redhat.py @@ -52,7 +52,10 @@ from ipalib import api # and restorecon is installed. __all__ = ['authconfig', 'service', 'knownservices', 'backup_and_replace_hostname', 'restore_context', 'check_selinux_status', - 'restore_network_configuration'] + 'restore_network_configuration', 'timedate_services'] + +# Just copy a referential list of timedate services +timedate_services = list(base.timedate_services) class RedHatService(base.PlatformService): def __wait_for_open_ports(self, instance_name=""): |