replica-install: warn when there is only one CA in topology

For redundancy and security against catastrophic failure of a CA
master, there must be more than one CA master in a topology.
Replica installation is a good time to warn about this situation.
Print a warning at the end of ipa-replica-install, if there is only
one CA replica in the topology.

Fixes: https://pagure.io/freeipa/issue/7459
Reviewed-By: Christian Heimes <cheimes@redhat.com>
This commit is contained in:
Fraser Tweedale 2018-03-19 12:23:15 +11:00 committed by Christian Heimes
parent 5f87b9c3e5
commit 5afbe1d261
2 changed files with 36 additions and 12 deletions

View File

@ -14,7 +14,9 @@ import dns.reversename as dnsreversename
import os
import shutil
import socket
import sys
import tempfile
import textwrap
import traceback
from pkg_resources import parse_version
@ -1517,6 +1519,7 @@ def install(installer):
if options.setup_adtrust:
adtrust.install(False, options, fstore, api)
ca_servers = service.find_providing_servers('CA', api.Backend.ldap2, api)
api.Backend.ldap2.disconnect()
if not promote:
@ -1549,6 +1552,15 @@ def install(installer):
# Everything installed properly, activate ipa service.
services.knownservices.ipa.enable()
# Print a warning if CA role is only installed on one server
if len(ca_servers) == 1:
msg = textwrap.dedent(u'''
WARNING: The CA service is only installed on one server ({}).
It is strongly recommended to install it on another server.
Run ipa-ca-install(1) on another master to accomplish this.
'''.format(ca_servers[0]))
print(msg, file=sys.stderr)
def init(installer):
installer.unattended = not installer.interactive

View File

@ -112,14 +112,14 @@ def add_principals_to_group(admin_conn, group, member_attr, principals):
pass
def find_providing_server(svcname, conn, host_name=None, api=api):
def find_providing_servers(svcname, conn, api):
"""
Find servers that provide the given service.
:param svcname: The service to find
:param conn: a connection to the LDAP server
:param host_name: the preferred server
:return: the selected host name
:return: list of host names (possibly empty)
Find a server that is a CA.
"""
dn = DN(('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'), api.env.basedn)
query_filter = conn.make_filter({'objectClass': 'ipaConfigObject',
@ -128,15 +128,27 @@ def find_providing_server(svcname, conn, host_name=None, api=api):
try:
entries, _trunc = conn.find_entries(filter=query_filter, base_dn=dn)
except errors.NotFound:
return []
else:
return [entry.dn[1].value for entry in entries]
def find_providing_server(svcname, conn, host_name=None, api=api):
"""
Find a server that provides the given service.
:param svcname: The service to find
:param conn: a connection to the LDAP server
:param host_name: the preferred server
:return: the selected host name
"""
servers = find_providing_servers(svcname, conn, api)
if len(servers) == 0:
return None
if len(entries):
if host_name is not None:
for entry in entries:
if entry.dn[1].value == host_name:
return host_name
# if the preferred is not found, return the first in the list
return entries[0].dn[1].value
return None
if host_name in servers:
return host_name
return servers[0]
def case_insensitive_attr_has_value(attr, value):