diff --git a/ipaclient/install/client.py b/ipaclient/install/client.py index 18a05e44f..be2788298 100644 --- a/ipaclient/install/client.py +++ b/ipaclient/install/client.py @@ -1987,19 +1987,19 @@ def install_check(options): "using 'ipa-client-install --uninstall'.") raise ScriptError(rval=CLIENT_ALREADY_CONFIGURED) - if options.conf_ntp and not options.on_master and not options.force_ntpd: + if options.conf_ntp and not options.on_master and not options.force_chrony: try: ntpconf.check_timedate_services() except ntpconf.NTPConflictingService as e: - print("WARNING: ntpd time&date synchronization service will not" + print("WARNING: chronyd time&date synchronization service will not" " be configured as") print("conflicting service ({}) is enabled".format( e.conflicting_service)) - print("Use --force-ntpd option to disable it and force " - "configuration of ntpd") + print("Use --force-chrony option to disable it and force " + "use of chronyd") print("") - # configuration of ntpd is disabled in this case + # configuration of chrony is disabled in this case options.conf_ntp = False except ntpconf.NTPConfigurationError: pass @@ -2390,7 +2390,6 @@ def _install(options): tasks.backup_hostname(fstore, statestore) tasks.set_hostname(options.hostname) - ntp_srv_servers = [] if not options.on_master and options.conf_ntp: # Attempt to sync time with IPA server. # If we're skipping NTP configuration, we also skip the time sync here. @@ -2398,31 +2397,35 @@ def _install(options): # in the DNS. # If that fails, we try to sync directly with IPA server, # assuming it runs NTP - logger.info('Synchronizing time with KDC...') - ds = ipadiscovery.IPADiscovery() - ntp_srv_servers = ds.ipadns_search_srv(cli_domain, '_ntp._udp', - None, break_on_first=False) - synced_ntp = False - ntp_servers = ntp_srv_servers - # use user specified NTP servers if there are any - if options.ntp_servers: + # disable other time&date services first + if options.force_chrony: + ntpconf.force_chrony(statestore) + + logger.info('Synchronizing time with KDC...') + + if not options.ntp_servers: + ds = ipadiscovery.IPADiscovery() + ntp_servers = ds.ipadns_search_srv(cli_domain, '_ntp._udp', + None, break_on_first=False) + + if not ntp_servers: + logger.warning("No SRV records of NTP servers found. IPA " + "server address will be used") + ntp_servers = cli_server + else: ntp_servers = options.ntp_servers - for s in ntp_servers: - synced_ntp = ntpconf.synconce_ntp(s, options.debug) - if synced_ntp: - break + synced_time = ntpconf.configure_chrony(ntp_servers, fstore, + statestore, options.debug) - if not synced_ntp and not options.ntp_servers: - synced_ntp = ntpconf.synconce_ntp(cli_server[0], options.debug) - if not synced_ntp: + if not synced_time: logger.warning( - "Unable to sync time with NTP " - "server, assuming the time is in sync. Please check " - "that 123 UDP port is opened.") + "Unable to sync time with chrony server, assuming the time " + "is in sync. Please check that 123 UDP port is opened, " + "and any time server is on network.") else: - logger.info('Skipping synchronizing time with NTP server.') + logger.info('Skipping synchronizing time with chrony server.') if not options.unattended: if (options.principal is None and options.password is None and @@ -2942,23 +2945,6 @@ def _install(options): "Adding hardcoded server name to " "/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: - ntpconf.force_ntpd(statestore) - - if options.ntp_servers: - ntp_servers = options.ntp_servers - elif ntp_srv_servers: - ntp_servers = ntp_srv_servers - else: - logger.warning("No SRV records of NTP servers found. IPA " - "server address will be used") - ntp_servers = cli_server - - ntpconf.config_ntp(ntp_servers, fstore, statestore) - logger.info("NTP enabled") - if options.conf_ssh: configure_ssh_config(fstore, options) @@ -3255,10 +3241,9 @@ def uninstall(options): service.service_name ) - ntp_configured = statestore.has_state('ntp') - if ntp_configured: - ntp_enabled = statestore.restore_state('ntp', 'enabled') - ntp_step_tickers = statestore.restore_state('ntp', 'step-tickers') + chrony_configured = statestore.has_state('ntp') + if chrony_configured: + chrony_enabled = statestore.restore_state('ntp', 'enabled') restored = False try: @@ -3266,24 +3251,21 @@ def uninstall(options): # the reason for it might be that freeipa-client was updated # to this version but not unenrolled/enrolled again # In such case it is OK to fail - restored = fstore.restore_file(paths.NTP_CONF) - restored |= fstore.restore_file(paths.SYSCONFIG_NTPD) - if ntp_step_tickers: - restored |= fstore.restore_file(paths.NTP_STEP_TICKERS) + restored = fstore.restore_file(paths.CHRONY_CONF) except Exception: pass - if not ntp_enabled: - services.knownservices.ntpd.stop() - services.knownservices.ntpd.disable() + if not chrony_enabled: + services.knownservices.chronyd.stop() + services.knownservices.chronyd.disable() else: if restored: - services.knownservices.ntpd.restart() + services.knownservices.chronyd.restart() try: - ntpconf.restore_forced_ntpd(statestore) + ntpconf.restore_forced_chronyd(statestore) except CalledProcessError as e: - logger.error('Failed to start chronyd: %s', e) + logger.error('Failed to restore time synchronization service: %s', e) if was_sshd_configured and services.knownservices.sshd.is_running(): services.knownservices.sshd.restart() @@ -3469,12 +3451,20 @@ class ClientInstallInterface(hostname_.HostNameInstallInterface, no_ntp = enroll_only(no_ntp) force_ntpd = knob( - None, + None, False, description="Stop and disable any time&date synchronization services " - "besides ntpd", + "besides ntpd.\n" + "This option has been obsoleted by --force-chrony", ) force_ntpd = enroll_only(force_ntpd) + force_chrony = knob( + None, + description="Stop and disable any time&date synchronization services " + "besides chrony", + ) + force_chrony = enroll_only(force_chrony) + nisdomain = knob( str, None, description="NIS domain name", @@ -3541,9 +3531,13 @@ class ClientInstallInterface(hostname_.HostNameInstallInterface, raise RuntimeError( "--server cannot be used without providing --domain") - if self.force_ntpd and self.no_ntp: + if self.force_ntpd: raise RuntimeError( - "--force-ntpd cannot be used together with --no-ntp") + "--force-ntpd has been obsoleted by --force-chrony") + + if self.force_chrony and self.no_ntp: + raise RuntimeError( + "--force-chrony cannot be used together with --no-ntp") if self.no_nisdomain and self.nisdomain: raise RuntimeError( diff --git a/ipaclient/install/ntpconf.py b/ipaclient/install/ntpconf.py index b2d514bdc..a9f05687d 100644 --- a/ipaclient/install/ntpconf.py +++ b/ipaclient/install/ntpconf.py @@ -20,6 +20,7 @@ import logging import os import shutil +from augeas import Augeas from ipalib import api from ipapython import ipautil from ipaplatform.tasks import tasks @@ -28,184 +29,120 @@ from ipaplatform.paths import paths logger = logging.getLogger(__name__) -ntp_conf = """# Permit time synchronization with our time source, but do not -# permit the source to query or modify the service on this system. -restrict default kod nomodify notrap nopeer noquery -restrict -6 default kod nomodify notrap nopeer noquery -# Permit all access over the loopback interface. This could -# be tightened as well, but to do so would effect some of -# the administrative functions. -restrict 127.0.0.1 -restrict -6 ::1 - -# Hosts on local network are less restricted. -#restrict 192.168.1.0 mask 255.255.255.0 nomodify notrap - -# Use public servers from the pool.ntp.org project. -# Please consider joining the pool (http://www.pool.ntp.org/join.html). -$SERVERS_BLOCK - -#broadcast 192.168.1.255 key 42 # broadcast server -#broadcastclient # broadcast client -#broadcast 224.0.1.1 key 42 # multicast server -#multicastclient 224.0.1.1 # multicast client -#manycastserver 239.255.254.254 # manycast server -#manycastclient 239.255.254.254 key 42 # manycast client - -# Undisciplined Local Clock. This is a fake driver intended for backup -# and when no outside source of synchronized time is available. -server 127.127.1.0 # local clock -#fudge 127.127.1.0 stratum 10 - -# Drift file. Put this in a directory which the daemon can write to. -# No symbolic links allowed, either, since the daemon updates the file -# by creating a temporary in the same directory and then rename()'ing -# it to the file. -driftfile /var/lib/ntp/drift - -# Key file containing the keys and key identifiers used when operating -# with symmetric key cryptography. -keys /etc/ntp/keys - -# Specify the key identifiers which are trusted. -#trustedkey 4 8 42 - -# Specify the key identifier to use with the ntpdc utility. -#requestkey 8 - -# Specify the key identifier to use with the ntpq utility. -#controlkey 8 -""" - -ntp_sysconfig = """OPTIONS="-x -p /var/run/ntpd.pid" - -# Set to 'yes' to sync hw clock after successful ntpdate -SYNC_HWCLOCK=yes - -# Additional options for ntpdate -NTPDATE_OPTIONS="" -""" -ntp_step_tickers = """# Use IPA-provided NTP server for initial time -$TICKER_SERVERS_BLOCK -""" -def __backup_config(path, fstore = None): +def __backup_config(path, fstore=None): if fstore: fstore.backup_file(path) else: shutil.copy(path, "%s.ipasave" % (path)) -def __write_config(path, content): - fd = open(path, "w") - fd.write(content) - fd.close() - -def config_ntp(ntp_servers, fstore = None, sysstore = None): - path_step_tickers = paths.NTP_STEP_TICKERS - path_ntp_conf = paths.NTP_CONF - path_ntp_sysconfig = paths.SYSCONFIG_NTPD - sub_dict = {} - sub_dict["SERVERS_BLOCK"] = "\n".join("server %s" % s for s in ntp_servers) - sub_dict["TICKER_SERVERS_BLOCK"] = "\n".join(ntp_servers) - - nc = ipautil.template_str(ntp_conf, sub_dict) - config_step_tickers = False - - - if os.path.exists(path_step_tickers): - config_step_tickers = True - ns = ipautil.template_str(ntp_step_tickers, sub_dict) - __backup_config(path_step_tickers, fstore) - __write_config(path_step_tickers, ns) - tasks.restore_context(path_step_tickers) +def configure_chrony(ntp_servers, fstore=None, sysstore=None, debug=False): if sysstore: - module = 'ntp' - sysstore.backup_state(module, "enabled", services.knownservices.ntpd.is_enabled()) - if config_step_tickers: - sysstore.backup_state(module, "step-tickers", True) + module = 'chrony' + sysstore.backup_state(module, "enabled", + services.knownservices.chronyd.is_enabled()) - __backup_config(path_ntp_conf, fstore) - __write_config(path_ntp_conf, nc) - tasks.restore_context(path_ntp_conf) + aug = Augeas(flags=Augeas.NO_LOAD | Augeas.NO_MODL_AUTOLOAD, + loadpath=paths.USR_SHARE_IPA_DIR) - __backup_config(path_ntp_sysconfig, fstore) - __write_config(path_ntp_sysconfig, ntp_sysconfig) - tasks.restore_context(path_ntp_sysconfig) - - # Set the ntpd to start on boot - services.knownservices.ntpd.enable() - - # Restart ntpd - services.knownservices.ntpd.restart() - - -def synconce_ntp(server_fqdn, debug=False): - """ - Syncs time with specified server using ntpd. - Primarily designed to be used before Kerberos setup - to get time following the KDC time - - Returns True if sync was successful - """ - ntpd = paths.NTPD - if not os.path.exists(ntpd): - return False - - # The ntpd command will never exit if it is unable to reach the - # server, so timeout after 15 seconds. - timeout = 15 - - tmp_ntp_conf = ipautil.write_tmp_file('server %s' % server_fqdn) - args = [paths.BIN_TIMEOUT, str(timeout), ntpd, '-qgc', tmp_ntp_conf.name] - if debug: - args.append('-d') try: - logger.info('Attempting to sync time using ntpd. ' - 'Will timeout after %d seconds', timeout) - ipautil.run(args) + logger.debug("Configuring chrony") + chrony_conf = os.path.abspath(paths.CHRONY_CONF) + aug.transform('chrony', chrony_conf) # loads lens file + aug.load() # loads augeas tree + # augeas needs to prepend path with '/files' + path = '/files{path}'.format(path=chrony_conf) + + # remove possible conflicting configuration of servers + aug.remove('{}/server'.format(path)) + aug.remove('{}/pool'.format(path)) + aug.remove('{}/peer'.format(path)) + + logger.debug("Setting time servers:") + for server in ntp_servers: + aug.set('{}/server[last()+1]'.format(path), server) + aug.set('{}/server[last()]/iburst'.format(path), None) + logger.debug("'%s'", server) + + # backup oginal conf file + logger.debug("Backing up '%s'", chrony_conf) + __backup_config(chrony_conf, fstore) + + logger.debug("Writing configuration to '%s'", chrony_conf) + + try: + aug.save() + except Exception as e: + logger.error("Augeas failed to configure file %s", chrony_conf) + + except Exception as e: + logger.error("Configuration failed with: %s", e) + finally: + aug.close() + + tasks.restore_context(chrony_conf) + + # Set the chronyd to start on boot + services.knownservices.chronyd.enable() + + # Restart chronyd + services.knownservices.chronyd.restart() + + sync_attempt_count = 3 + # chrony attempt count to sync with configiured servers + # each next attempt is tried after 10seconds of timeot + # 3 attempts means if first immidiate attempt fails + # there is 10s delay between next + + cmd = [paths.CHRONYC, 'waitsync', str(sync_attempt_count)] + + if debug: + cmd.append('-d') + + try: + logger.info('Attempting to sync time using chronyd.') + ipautil.run(cmd) return True except ipautil.CalledProcessError as e: - if e.returncode == 124: - logger.debug('Process did not complete before timeout') + if e.returncode is 1: + logger.debug('Process chronyc waitsync failed to sync time') 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 + As IPA server/client supports only chronyd, make sure that other services + are not enabled to prevent conflicts. """ for service in services.timedate_services: - if service == 'ntpd': + if service == 'chronyd': continue # Make sure that the service is not enabled instance = services.service(service, api) if instance.is_enabled() or instance.is_running(): - raise NTPConflictingService(conflicting_service=instance.service_name) + raise NTPConflictingService( + conflicting_service=instance.service_name) -def force_ntpd(statestore): + +def force_chrony(statestore): """ - Force ntpd configuration and disable and stop any other conflicting + Force chronyd configuration and disable and stop any other conflicting time&date service """ for service in services.timedate_services: - if service == 'ntpd': + if service == 'chronyd': continue instance = services.service(service, api) enabled = instance.is_enabled() @@ -221,18 +158,21 @@ def force_ntpd(statestore): if enabled: instance.disable() -def restore_forced_ntpd(statestore): + +def restore_forced_chronyd(statestore): """ - Restore from --force-ntpd installation and enable/start service that were - disabled/stopped during installation + Restore from --force-chronyd installation and enable/start service that + were disabled/stopped during installation """ for service in services.timedate_services: - if service == 'ntpd': + if service == 'chronyd': continue if statestore.has_state(service): instance = services.service(service, api) - enabled = statestore.restore_state(instance.service_name, 'enabled') - running = statestore.restore_state(instance.service_name, 'running') + enabled = statestore.restore_state(instance.service_name, + 'enabled') + running = statestore.restore_state(instance.service_name, + 'running') if enabled: instance.enable() if running: diff --git a/ipaplatform/base/services.py b/ipaplatform/base/services.py index 3cd2565ef..2757e8e72 100644 --- a/ipaplatform/base/services.py +++ b/ipaplatform/base/services.py @@ -512,6 +512,6 @@ def base_service_class_factory(name, api=None): service = base_service_class_factory knownservices = KnownServices({}) -# System may support more time&date services. FreeIPA supports ntpd only, other -# services will be disabled during IPA installation +# System may support more time&date services. FreeIPA supports chrony only. +# Other services will be disabled during IPA installation timedate_services = ['ntpd', 'chronyd'] diff --git a/ipaserver/install/installutils.py b/ipaserver/install/installutils.py index 0a21be4d5..6a7a19b31 100644 --- a/ipaserver/install/installutils.py +++ b/ipaserver/install/installutils.py @@ -74,8 +74,7 @@ logger = logging.getLogger(__name__) # Used to determine install status IPA_MODULES = [ - 'httpd', 'kadmin', 'dirsrv', 'pki-tomcatd', 'install', 'krb5kdc', 'ntpd', - 'named'] + 'httpd', 'kadmin', 'dirsrv', 'pki-tomcatd', 'install', 'krb5kdc', 'named'] class BadHostError(Exception): diff --git a/ipaserver/install/ipa_backup.py b/ipaserver/install/ipa_backup.py index 9892e6886..808516cce 100644 --- a/ipaserver/install/ipa_backup.py +++ b/ipaserver/install/ipa_backup.py @@ -131,7 +131,6 @@ class Backup(admintool.AdminTool): paths.RESOLV_CONF, paths.SYSCONFIG_PKI_TOMCAT, paths.SYSCONFIG_DIRSRV, - paths.SYSCONFIG_NTPD, paths.SYSCONFIG_KRB5KDC_DIR, paths.SYSCONFIG_IPA_DNSKEYSYNCD, paths.SYSCONFIG_IPA_ODS_EXPORTER, diff --git a/ipaserver/install/ntpinstance.py b/ipaserver/install/ntpinstance.py deleted file mode 100644 index f26ba1b1c..000000000 --- a/ipaserver/install/ntpinstance.py +++ /dev/null @@ -1,172 +0,0 @@ -# Authors: Karl MacMillan -# Authors: Simo Sorce -# -# Copyright (C) 2007-2010 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 . -# - -import logging - -from ipaserver.install import service -from ipaserver.install import sysupgrade -from ipaplatform.constants import constants -from ipaplatform.paths import paths - -logger = logging.getLogger(__name__) - -NTPD_OPTS_VAR = constants.NTPD_OPTS_VAR -NTPD_OPTS_QUOTE = constants.NTPD_OPTS_QUOTE - -NTP_EXPOSED_IN_LDAP = 'exposed_in_ldap' - - -def ntp_ldap_enable(fqdn, base_dn, realm): - ntp = NTPInstance(realm=realm) - is_exposed_in_ldap = sysupgrade.get_upgrade_state( - 'ntp', NTP_EXPOSED_IN_LDAP) - - was_running = ntp.is_running() - - if ntp.is_configured() and not is_exposed_in_ldap: - ntp.ldap_enable('NTP', fqdn, None, base_dn) - sysupgrade.set_upgrade_state('ntp', NTP_EXPOSED_IN_LDAP, True) - - if was_running: - ntp.start() - - -class NTPInstance(service.Service): - def __init__(self, realm=None, fstore=None): - super(NTPInstance, self).__init__( - "ntpd", - service_desc="NTP daemon", - realm_name=realm, - fstore=fstore - ) - - def __write_config(self): - - self.fstore.backup_file(paths.NTP_CONF) - self.fstore.backup_file(paths.SYSCONFIG_NTPD) - - local_srv = "127.127.1.0" - fudge = ["fudge", "127.127.1.0", "stratum", "10"] - - #read in memory, change it, then overwrite file - ntpconf = [] - fd = open(paths.NTP_CONF, "r") - for line in fd: - opt = line.split() - if len(opt) < 2: - ntpconf.append(line) - continue - - if opt[0] == "server" and opt[1] == local_srv: - line = "" - elif opt[0] == "fudge": - line = "" - - ntpconf.append(line) - - with open(paths.NTP_CONF, "w") as fd: - for line in ntpconf: - fd.write(line) - fd.write("\n### Added by IPA Installer ###\n") - fd.write("server {} iburst\n".format(local_srv)) - fd.write("{}\n".format(' '.join(fudge))) - - #read in memory, find OPTIONS, check/change it, then overwrite file - needopts = [ {'val':'-x', 'need':True}, - {'val':'-g', 'need':True} ] - fd = open(paths.SYSCONFIG_NTPD, "r") - lines = fd.readlines() - fd.close() - for line in lines: - sline = line.strip() - if not sline.startswith(NTPD_OPTS_VAR): - continue - sline = sline.replace(NTPD_OPTS_QUOTE, '') - for opt in needopts: - if sline.find(opt['val']) != -1: - opt['need'] = False - - newopts = [] - for opt in needopts: - if opt['need']: - newopts.append(opt['val']) - - done = False - if newopts: - fd = open(paths.SYSCONFIG_NTPD, "w") - for line in lines: - if not done: - sline = line.strip() - if not sline.startswith(NTPD_OPTS_VAR): - fd.write(line) - continue - sline = sline.replace(NTPD_OPTS_QUOTE, '') - (_variable, opts) = sline.split('=', 1) - fd.write(NTPD_OPTS_VAR + '="%s %s"\n' % (opts, ' '.join(newopts))) - done = True - else: - fd.write(line) - fd.close() - - def __stop(self): - self.backup_state("running", self.is_running()) - self.stop() - - def __start(self): - self.start() - - def __enable(self): - self.backup_state("enabled", self.is_enabled()) - self.enable() - - def create_instance(self): - - # we might consider setting the date manually using ntpd -qg in case - # the current time is very far off. - - self.step("stopping ntpd", self.__stop) - self.step("writing configuration", self.__write_config) - self.step("configuring ntpd to start on boot", self.__enable) - self.step("starting ntpd", self.__start) - - self.start_creation() - - def uninstall(self): - if self.is_configured(): - self.print_msg("Unconfiguring %s" % self.service_name) - - running = self.restore_state("running") - enabled = self.restore_state("enabled") - - # service is not in LDAP, stop and disable service - # before restoring configuration - self.stop() - self.disable() - - try: - self.fstore.restore_file(paths.NTP_CONF) - except ValueError as error: - logger.debug("%s", error) - - if enabled: - self.enable() - - if running: - self.restart() diff --git a/ipaserver/install/server/__init__.py b/ipaserver/install/server/__init__.py index b6c01d097..9b796899a 100644 --- a/ipaserver/install/server/__init__.py +++ b/ipaserver/install/server/__init__.py @@ -169,7 +169,7 @@ class ServerInstallInterface(ServerCertificateInstallInterface, kinit_attempts = 1 fixed_primary = True ntp_servers = None - force_ntpd = False + force_chrony = False permit = False enable_dns_updates = False no_krb5_offline_passwords = False diff --git a/ipaserver/install/server/install.py b/ipaserver/install/server/install.py index 8a009db7d..58aaedf5a 100644 --- a/ipaserver/install/server/install.py +++ b/ipaserver/install/server/install.py @@ -35,7 +35,7 @@ import ipaclient.install.ntpconf from ipaserver.install import ( adtrust, bindinstance, ca, dns, dsinstance, httpinstance, installutils, kra, krbinstance, - ntpinstance, otpdinstance, custodiainstance, replication, service, + otpdinstance, custodiainstance, replication, service, sysupgrade) from ipaserver.install.installutils import ( IPA_MODULES, BadHostError, get_fqdn, get_server_ip_address, @@ -386,7 +386,7 @@ def install_check(installer): print(" * Configure a stand-alone CA (dogtag) for certificate " "management") if not options.no_ntp: - print(" * Configure the Network Time Daemon (ntpd)") + print(" * Configure the NTP client (chronyd)") print(" * Create and configure an instance of Directory Server") print(" * Create and configure a Kerberos Key Distribution Center (KDC)") print(" * Configure Apache (httpd)") @@ -401,7 +401,7 @@ def install_check(installer): if options.no_ntp: print("") print("Excluded by options:") - print(" * Configure the Network Time Daemon (ntpd)") + print(" * Configure the NTP client (chronyd)") if installer.interactive: print("") print("To accept the default shown in brackets, press the Enter key.") @@ -415,9 +415,9 @@ def install_check(installer): try: ipaclient.install.ntpconf.check_timedate_services() except ipaclient.install.ntpconf.NTPConflictingService as e: - print(("WARNING: conflicting time&date synchronization service '%s'" - " will be disabled" % e.conflicting_service)) - print("in favor of ntpd") + print("WARNING: conflicting time&date synchronization service '%s'" + " will be disabled" % e.conflicting_service) + print("in favor of chronyd") print("") except ipaclient.install.ntpconf.NTPConfigurationError: pass @@ -761,13 +761,6 @@ def install(installer): # Create a directory server instance if not options.external_cert_files: - # Configure ntpd - if not options.no_ntp: - ipaclient.install.ntpconf.force_ntpd(sstore) - ntp = ntpinstance.NTPInstance(fstore) - if not ntp.is_configured(): - ntp.create_instance() - if options.dirsrv_cert_files: ds = dsinstance.DsInstance(fstore=fstore, domainlevel=options.domainlevel, @@ -793,8 +786,6 @@ def install(installer): hbac_allow=not options.no_hbac_allow, setup_pkinit=not options.no_pkinit) - ntpinstance.ntp_ldap_enable(host_name, ds.suffix, realm_name) - else: api.Backend.ldap2.connect() ds = dsinstance.DsInstance(fstore=fstore, @@ -963,10 +954,10 @@ def install(installer): "user-add)") print("\t and the web user interface.") - if not services.knownservices.ntpd.is_running(): + if not services.knownservices.chronyd.is_running(): print("\t3. Kerberos requires time synchronization between clients") print("\t and servers for correct operation. You should consider " - "enabling ntpd.") + "enabling chronyd.") print("") if setup_ca: @@ -1091,8 +1082,6 @@ def uninstall(installer): except Exception: pass - ntpinstance.NTPInstance(fstore).uninstall() - kra.uninstall() ca.uninstall() @@ -1121,7 +1110,7 @@ def uninstall(installer): sstore._load() - ipaclient.install.ntpconf.restore_forced_ntpd(sstore) + ipaclient.install.ntpconf.restore_forced_chronyd(sstore) # Clean up group_exists (unused since IPA 2.2, not being set since 4.1) sstore.restore_state("install", "group_exists") diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py index 028c0e6fb..5472f869e 100644 --- a/ipaserver/install/server/replicainstall.py +++ b/ipaserver/install/server/replicainstall.py @@ -39,8 +39,7 @@ from ipalib.util import no_matching_interface_for_ip_address_warning from ipaclient.install.client import configure_krb5_conf, purge_host_keytab from ipaserver.install import ( adtrust, bindinstance, ca, certs, dns, dsinstance, httpinstance, - installutils, kra, krbinstance, - ntpinstance, otpdinstance, custodiainstance, service) + installutils, kra, krbinstance, otpdinstance, custodiainstance, service) from ipaserver.install.installutils import ( create_replica_config, ReplicaConfig, load_pkcs12, is_ipa_configured) from ipaserver.install.replication import ( @@ -585,7 +584,7 @@ def common_check(no_ntp): ipaclient.install.ntpconf.check_timedate_services() except ipaclient.install.ntpconf.NTPConflictingService as e: print("WARNING: conflicting time&date synchronization service " - "'{svc}' will\nbe disabled in favor of ntpd\n" + "'{svc}' will\nbe disabled in favor of chronyd\n" .format(svc=e.conflicting_service)) except ipaclient.install.ntpconf.NTPConfigurationError: pass @@ -909,7 +908,7 @@ def install_check(installer): def ensure_enrolled(installer): - args = [paths.IPA_CLIENT_INSTALL, "--unattended", "--no-ntp"] + args = [paths.IPA_CLIENT_INSTALL, "--unattended"] stdin = None nolog = [] @@ -946,6 +945,10 @@ def ensure_enrolled(installer): args.append("--mkhomedir") if installer.force_join: args.append("--force-join") + if installer.no_ntp: + args.append("--no-ntp") + else: + args.append("--force-chrony") try: # Call client install script @@ -1386,11 +1389,9 @@ def install(installer): elif installer._update_hosts_file: installutils.update_hosts_file(config.ips, config.host_name, fstore) - # Configure ntpd - if not options.no_ntp: - ipaclient.install.ntpconf.force_ntpd(sstore) - ntp = ntpinstance.NTPInstance() - ntp.create_instance() + if not promote and not options.no_ntp: + # in DL1, chrony is already installed + ipaclient.install.ntpconf.force_chrony(sstore) try: if promote: @@ -1420,8 +1421,6 @@ def install(installer): # Always try to install DNS records install_dns_records(config, options, remote_api) - ntpinstance.ntp_ldap_enable(config.host_name, ds.suffix, - remote_api.env.realm) finally: if conn.isconnected(): conn.disconnect() diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py index 07d783445..cbf1417df 100644 --- a/ipaserver/install/server/upgrade.py +++ b/ipaserver/install/server/upgrade.py @@ -31,7 +31,6 @@ from ipaplatform.paths import paths from ipaserver.install import installutils from ipaserver.install import dsinstance from ipaserver.install import httpinstance -from ipaserver.install import ntpinstance from ipaserver.install import bindinstance from ipaserver.install import service from ipaserver.install import cainstance @@ -1735,8 +1734,6 @@ def upgrade_configuration(): ds.configure_dirsrv_ccache() - ntpinstance.ntp_ldap_enable(api.env.host, api.env.basedn, api.env.realm) - ds.stop(ds_serverid) fix_schema_file_syntax() remove_ds_ra_cert(subject_base) diff --git a/ipaserver/install/service.py b/ipaserver/install/service.py index 64776a498..45fdef9f9 100644 --- a/ipaserver/install/service.py +++ b/ipaserver/install/service.py @@ -51,7 +51,6 @@ SERVICE_LIST = { 'DNS': ('named', 30), 'HTTP': ('httpd', 40), 'KEYS': ('ipa-custodia', 41), - 'NTP': ('ntpd', 45), 'CA': ('pki-tomcatd', 50), 'KRA': ('pki-tomcatd', 51), 'ADTRUST': ('smb', 60), diff --git a/ipatests/man/ipa-test-task.1 b/ipatests/man/ipa-test-task.1 index 70024385d..2f295d2de 100644 --- a/ipatests/man/ipa-test-task.1 +++ b/ipatests/man/ipa-test-task.1 @@ -149,7 +149,7 @@ Sets up SSSD debugging. Restarts SSSD. .TP \fBipa\-test\-task sync\-time HOST SERVER\fR Syncs the time with the remote server. Please note that this function leaves -ntpd stopped. +chronyd stopped. .TP \fBipa\-test\-task add\-a\-records\-in\-master\-domain MASTER\fR diff --git a/ipatests/pytest_plugins/integration/tasks.py b/ipatests/pytest_plugins/integration/tasks.py index ce58eca55..59fb202e3 100644 --- a/ipatests/pytest_plugins/integration/tasks.py +++ b/ipatests/pytest_plugins/integration/tasks.py @@ -658,11 +658,12 @@ def clear_sssd_cache(host): def sync_time(host, server): """ Syncs the time with the remote server. Please note that this function - leaves ntpd stopped. + leaves chronyd stopped. """ - host.run_command(['systemctl', 'stop', 'ntpd']) - host.run_command(['ntpdate', server.hostname]) + host.run_command(['systemctl', 'stop', 'chronyd']) + host.run_command(['chronyd', '-q', + '"server {srv} iburst"'.format(srv=server.hostname)]) def connect_replica(master, replica, domain_level=None):