Stop and disable conflicting time&date services

Fedora 16 introduced chrony as default client time&date synchronization
service:
http://fedoraproject.org/wiki/Features/ChronyDefaultNTP
Thus, there may be people already using chrony as their time and date
synchronization service before installing IPA.

However, installing IPA server or client on such machine may lead to
unexpected behavior, as the IPA installer would configure ntpd and leave
the machine with both ntpd and chronyd enabled. However, since the OS
does not allow both chronyd and ntpd to be running concurrently and chronyd
has the precedence, ntpd would not be run on that system at all.

Make sure, that user is warned when trying to install IPA on such
system and is given a possibility to either not to let IPA configure
ntpd at all or to let the installer stop and disable chronyd.

https://fedorahosted.org/freeipa/ticket/2974
This commit is contained in:
Martin Kosek 2012-12-07 16:44:32 +01:00 committed by Rob Crittenden
parent 867f7691e9
commit 211f6c9046
9 changed files with 146 additions and 5 deletions

View File

@ -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()

View File

@ -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()

View File

@ -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:

View File

@ -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()

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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()

View File

@ -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=""):