Adding method to ipa-server-upgrade to cleanup ntpd

Removing ntpd configuration files and entry from LDAP.

Add parameter and rename method for restoring forced time
services. Addressing some requests for change too.

Remove unused path for chrony-helper.

Resolves: https://pagure.io/freeipa/issue/7024
Reviewed-By: Rob Crittenden <rcritten@redhat.com>
This commit is contained in:
Tibor Dudlák 2018-03-13 14:41:20 +01:00 committed by Rob Crittenden
parent 194518f11f
commit 5d9c749e83
7 changed files with 106 additions and 64 deletions

View File

@ -60,7 +60,7 @@ from ipapython.ipautil import (
)
from ipapython.ssh import SSHPublicKey
from . import automount, ipadiscovery, ntpconf, sssd
from . import automount, ipadiscovery, timeconf, sssd
from .ipachangeconf import IPAChangeConf
NoneType = type(None)
@ -1989,8 +1989,8 @@ def install_check(options):
if options.conf_ntp and not options.force_chrony:
try:
ntpconf.check_timedate_services()
except ntpconf.NTPConflictingService as e:
timeconf.check_timedate_services()
except timeconf.NTPConflictingService as e:
print("WARNING: chronyd time&date synchronization service will not"
" be configured as")
print("conflicting service ({}) is enabled".format(
@ -1998,10 +1998,10 @@ def install_check(options):
print("Use --force-chrony option to disable it and force "
"use of chronyd")
print("")
# TODO decide what to do if there is conflicting service
# configuration of chrony is disabled in this case
options.conf_ntp = False
except ntpconf.NTPConfigurationError:
except timeconf.NTPConfigurationError:
pass
if options.unattended and (
@ -2345,18 +2345,21 @@ def update_ipa_nssdb():
(nickname, sys_db.secdir, e))
def sync_time(options, fstore, statestore):
# We assume that NTP servers are discoverable through SRV records
# in the DNS.
# If that fails, we try to sync directly with IPA server,
# assuming it runs NTP
def sync_time(options, fstore, statestore, force):
"""
Will disable any other time synchronization service if there is
--force-chrony option set, and configure chrony with given ntp(chrony)
server and/or pool using Augeas in configure_chrony method.
If there is no option --ntp-server set IPADiscovery will try to find ntp
server in DNS records.
"""
# We assume that NTP servers are discoverable through SRV records in DNS.
# disable other time&date services first
if options.force_chrony:
ntpconf.force_chrony(statestore)
if force:
timeconf.force_chrony(statestore)
print("Synchronizing time")
print(" [1/1]: Configuring chrony client")
logger.info('Synchronizing time with KDC...')
if not options.ntp_servers:
@ -2367,37 +2370,37 @@ def sync_time(options, fstore, statestore):
ntp_servers = options.ntp_servers
if ntp_servers:
synced_time = ntpconf.configure_chrony(ntp_servers, options.ntp_pool,
fstore, statestore)
if timeconf.configure_chrony(ntp_servers, options.ntp_pool,
fstore, statestore):
print("Done Configuring chrony.")
else:
print("Warning: IPA Server was unable to sync time with chrony!")
print(" Time synchronization is required for IPA Server "
"to work correctly")
logger.warning(
"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:
synced_time = False
print("Warning: chrony not configured, using default configuration.")
logger.warning("No SRV records of NTP servers found nor NTP server "
"address was privided. Skipping chrony configuration")
if not synced_time:
print("Warning: IPA Server was unable to sync time with chrony!")
print(" Time synchronization is required "
"for IPA Server to work correctly")
logger.warning(
"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.")
"address was provided. Skipping chrony configuration, "
"default configuration will be used")
def restore_time_sync(statestore, fstore):
chrony_configured = statestore.has_state('ntp')
if chrony_configured:
chrony_enabled = statestore.restore_state('ntp', 'enabled')
if statestore.has_state('chrony'):
chrony_enabled = statestore.restore_state('chrony', 'enabled')
restored = False
try:
# Restore might fail due to file missing in backup
# 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
# Restore might fail due to missing file(s) in backup.
# One example is if the client was updated from a previous version
# not configured with chrony. In such a cast it is OK to fail.
restored = fstore.restore_file(paths.CHRONY_CONF)
except Exception:
pass
except ValueError: # this will not handle possivble IOError
logger.debug("Configuration file %s was not restored.",
paths.CHRONY_CONF)
if not chrony_enabled:
services.knownservices.chronyd.stop()
@ -2406,7 +2409,7 @@ def restore_time_sync(statestore, fstore):
services.knownservices.chronyd.restart()
try:
ntpconf.restore_forced_chronyd(statestore)
timeconf.restore_forced_timeservices(statestore)
except CalledProcessError as e:
logger.error('Failed to restore time synchronization service: %s', e)
@ -2458,7 +2461,7 @@ def _install(options):
if options.conf_ntp:
# Attempt to sync time with NTP server (chrony).
sync_time(options, fstore, statestore)
sync_time(options, fstore, statestore, options.force_chrony)
elif options.on_master:
# If we're on master skipping the time sync here because it was done
# in ipa-server-install
@ -3472,6 +3475,7 @@ class ClientInstallInterface(hostname_.HostNameInstallInterface,
force_ntpd = knob(
None, False,
deprecated=True,
description="Stop and disable any time&date synchronization services "
"besides ntpd.\n"
"This option has been obsoleted by --force-chrony",

View File

@ -79,10 +79,10 @@ def configure_chrony(ntp_servers, ntp_pool=None,
try:
aug.save()
except Exception as e:
except IOError as e:
logger.error("Augeas failed to configure file %s", chrony_conf)
except Exception as e:
except RuntimeError as e:
logger.error("Configuration failed with: %s", e)
finally:
aug.close()
@ -101,20 +101,19 @@ def configure_chrony(ntp_servers, ntp_pool=None,
# 3 attempts means if first immidiate attempt fails
# there is 10s delay between next
cmd = [paths.CHRONYC, 'waitsync', str(sync_attempt_count)]
args = [paths.CHRONYC, 'waitsync', str(sync_attempt_count)]
if debug:
cmd.append('-d')
args.append('-d')
try:
logger.info('Attempting to sync time using chronyd.')
ipautil.run(cmd)
logger.info('Time is in sync.')
ipautil.run(args)
logger.info('Time synchronization was successful.')
return True
except ipautil.CalledProcessError as e:
if e.returncode is 1:
logger.warning('Process chronyc waitsync failed to sync time!')
logger.warning('Configuration of chrony was changed by installer.')
except ipautil.CalledProcessError:
logger.warning('Process chronyc waitsync failed to sync time!')
logger.warning('Configuration of chrony was changed by installer.')
return False
@ -167,13 +166,13 @@ def force_chrony(statestore):
instance.disable()
def restore_forced_chronyd(statestore):
def restore_forced_timeservices(statestore, skip_service='chronyd'):
"""
Restore from --force-chronyd installation and enable/start service that
were disabled/stopped during installation
"""
for service in services.timedate_services:
if service == 'chronyd':
if service == skip_service:
continue
if statestore.has_state(service):
instance = services.service(service, api)

View File

@ -230,7 +230,6 @@ class BasePathNamespace(object):
NAMED_PKCS11 = "/usr/sbin/named-pkcs11"
CHRONYC = "/usr/bin/chronyc"
CHRONYD = "/usr/sbin/chronyd"
CHRONY_HELPER = "/usr/libexec/chrony-helper"
PKIDESTROY = "/usr/sbin/pkidestroy"
PKISPAWN = "/usr/sbin/pkispawn"
PKI = "/usr/bin/pki"

View File

@ -162,7 +162,7 @@ class Backup(admintool.AdminTool):
paths.IPA_CA_CRT,
paths.IPA_DEFAULT_CONF,
paths.DS_KEYTAB,
paths.NTP_CONF,
paths.CHRONY_CONF,
paths.SMB_CONF,
paths.SAMBA_KEYTAB,
paths.DOGTAG_ADMIN_P12,

View File

@ -31,7 +31,7 @@ from ipalib.util import (
validate_domain_name,
no_matching_interface_for_ip_address_warning,
)
import ipaclient.install.ntpconf
import ipaclient.install.timeconf
from ipaserver.install import (
adtrust, bindinstance, ca, dns, dsinstance,
httpinstance, installutils, kra, krbinstance,
@ -413,13 +413,13 @@ def install_check(installer):
if not options.no_ntp:
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)
ipaclient.install.timeconf.check_timedate_services()
except ipaclient.install.timeconf.NTPConflictingService as e:
print("WARNING: conflicting time&date synchronization service '{}'"
" will be disabled".format(e.conflicting_service))
print("in favor of chronyd")
print("")
except ipaclient.install.ntpconf.NTPConfigurationError:
except ipaclient.install.timeconf.NTPConfigurationError:
pass
if not options.setup_dns and installer.interactive:
@ -766,7 +766,8 @@ def install(installer):
# chrony will be handled here in uninstall() method as well by invoking
# the ipa-server-install --uninstall
if not options.no_ntp:
ipaclient.install.client.sync_time(options, fstore, sstore)
ipaclient.install.client.sync_time(
options, fstore, sstore, force=True)
if options.dirsrv_cert_files:
ds = dsinstance.DsInstance(fstore=fstore,
@ -1119,7 +1120,7 @@ def uninstall(installer):
sstore._load()
ipaclient.install.ntpconf.restore_forced_chronyd(sstore)
ipaclient.install.timeconf.restore_forced_timeservices(sstore)
# Clean up group_exists (unused since IPA 2.2, not being set since 4.1)
sstore.restore_state("install", "group_exists")

View File

@ -23,7 +23,7 @@ from pkg_resources import parse_version
import six
from ipaclient.install.ipachangeconf import IPAChangeConf
import ipaclient.install.ntpconf
import ipaclient.install.timeconf
from ipalib.install import certstore, sysrestore
from ipalib.install.kinit import kinit_keytab
from ipapython import ipaldap, ipautil
@ -581,12 +581,12 @@ def common_check(no_ntp):
if not no_ntp:
try:
ipaclient.install.ntpconf.check_timedate_services()
except ipaclient.install.ntpconf.NTPConflictingService as e:
ipaclient.install.timeconf.check_timedate_services()
except ipaclient.install.timeconf.NTPConflictingService as e:
print("WARNING: conflicting time&date synchronization service "
"'{svc}' will\nbe disabled in favor of chronyd\n"
.format(svc=e.conflicting_service))
except ipaclient.install.ntpconf.NTPConfigurationError:
except ipaclient.install.timeconf.NTPConfigurationError:
pass
@ -1391,7 +1391,7 @@ def install(installer):
if not promote and not options.no_ntp:
# in DL1, chrony is already installed
ipaclient.install.ntpconf.force_chrony(sstore)
ipaclient.install.timeconf.force_chrony(sstore)
try:
if promote:

View File

@ -20,6 +20,7 @@ from ipalib.install import certmonger, sysrestore
import SSSDConfig
import ipalib.util
import ipalib.errors
from ipaclient.install import timeconf
from ipaclient.install.client import sssd_enable_service
from ipaplatform import services
from ipaplatform.tasks import tasks
@ -1593,6 +1594,41 @@ def enable_certauth(krb):
aug.close()
def ntpd_cleanup(fqdn, fstore):
sstore = sysrestore.StateFile(paths.SYSRESTORE)
timeconf.restore_forced_timeservices(sstore, 'ntpd')
if sstore.has_state('ntp'):
instance = services.service('ntpd', api)
sstore.restore_state(instance.service_name, 'enabled')
sstore.restore_state(instance.service_name, 'running')
sstore.restore_state(instance.service_name, 'step-tickers')
try:
instance.disable()
instance.stop()
except Exception as e:
logger.info("Service ntpd was not disabled or stopped")
ntpd_files = [paths.NTP_CONF, paths.NTP_STEP_TICKERS, paths.SYSCONFIG_NTPD]
for ntpd_file in ntpd_files:
try:
fstore.untrack_file(ntpd_file)
os.remove(ntpd_file)
except IOError:
logger.warning(
"No access to the %s, file could not be deleted.", ntpd_file)
except ValueError as e:
logger.warning("Error: %s", e)
connection = api.Backend.ldap2
try:
connection.delete_entry(DN(('cn', 'NTP'), ('cn', fqdn),
api.env.container_masters))
except ipalib.errors.NotFound:
logger.warning("Warning: NTP service entry was not found in LDAP.")
sysupgrade.set_upgrade_state('ntpd', 'ntpd_cleaned', True)
def upgrade_configuration():
"""
Execute configuration upgrade of the IPA services
@ -1613,6 +1649,9 @@ def upgrade_configuration():
if not ds_running:
ds.start(ds_serverid)
if not sysupgrade.get_upgrade_state('ntpd', 'ntpd_cleaned'):
ntpd_cleanup(fqdn, fstore)
check_certs()
auto_redirect = find_autoredirect(fqdn)