summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPetr Viktorin <pviktori@redhat.com>2014-09-19 15:57:44 +0200
committerPetr Viktorin <pviktori@redhat.com>2014-09-25 15:31:08 +0200
commit179423761eb297dd62f0fa9bc33a4aa849d8bb34 (patch)
tree8d027fed5805fc5df83c954ab891631c309dccda
parent6f100c50f0c9d125ae09fd7a84ae2f801a3707fd (diff)
downloadfreeipa-179423761eb297dd62f0fa9bc33a4aa849d8bb34.tar.gz
freeipa-179423761eb297dd62f0fa9bc33a4aa849d8bb34.tar.xz
freeipa-179423761eb297dd62f0fa9bc33a4aa849d8bb34.zip
ipa-replica-prepare: Wait for the DNS entry to be resolvable
It takes some time after the DNS record is added until it propagates to Bind. In automated installations, it might happen that replica-install is attempted before the hostname is resolvable; in that case the connection check would fail. Wait for the name to be resolvable at the end of replica-prepare. Mention that this can be interrupted (Ctrl+C). Provide an option to skip the wait. In case DNS is not managed by IPA, this reminds the admin of the necessary configuration and checks their work, but it's possible to skip (either by interrupting it interactively, or by the option). https://fedorahosted.org/freeipa/ticket/4551 Reviewed-By: Petr Spacek <pspacek@redhat.com>
-rw-r--r--ipaserver/install/ipa_replica_prepare.py53
1 files changed, 53 insertions, 0 deletions
diff --git a/ipaserver/install/ipa_replica_prepare.py b/ipaserver/install/ipa_replica_prepare.py
index c1ced3dcb..fe24f8885 100644
--- a/ipaserver/install/ipa_replica_prepare.py
+++ b/ipaserver/install/ipa_replica_prepare.py
@@ -21,9 +21,12 @@
import os
import shutil
import tempfile
+import time
from optparse import OptionGroup
from ConfigParser import SafeConfigParser
+import dns.resolver
+
from ipaserver.install import certs, installutils, bindinstance, dsinstance
from ipaserver.install.replication import enable_replication_version_checking
from ipaserver.plugins.ldap2 import ldap2
@@ -64,6 +67,9 @@ class ReplicaPrepare(admintool.AdminTool):
parser.add_option("--ca", dest="ca_file", default=paths.CACERT_P12,
metavar="FILE",
help="location of CA PKCS#12 file, default /root/cacert.p12")
+ parser.add_option('--no-wait-for-dns', dest='wait_for_dns',
+ action='store_false', default=True,
+ help="do not wait until the replica is resolvable in DNS")
group = OptionGroup(parser, "SSL certificate options",
"Only used if the server was installed using custom SSL certificates")
@@ -290,6 +296,9 @@ class ReplicaPrepare(admintool.AdminTool):
if options.ip_address:
self.add_dns_records()
+ if options.wait_for_dns:
+ self.wait_for_dns()
+
def copy_ds_certificate(self):
options = self.options
@@ -454,6 +463,50 @@ class ReplicaPrepare(admintool.AdminTool):
raise admintool.ScriptError(
"Could not add reverse DNS record for the replica: %s" % e)
+ def check_dns(self, replica_fqdn):
+ """Return true if the replica hostname is resolvable"""
+ resolver = dns.resolver.Resolver()
+ exceptions = (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer,
+ dns.resolver.Timeout, dns.resolver.NoNameservers)
+
+ try:
+ dns_answer = resolver.query(replica_fqdn, 'A', 'IN')
+ except exceptions:
+ try:
+ dns_answer = resolver.query(replica_fqdn, 'AAAA', 'IN')
+ except exceptions:
+ return False
+ except Exception as e:
+ self.log.warn('Exception while waiting for DNS record: %s: %s',
+ type(e).__name__, e)
+
+ return True
+
+ def wait_for_dns(self):
+ options = self.options
+
+ # Make sure replica_fqdn has a trailing dot, so the
+ # 'search' directive in /etc/resolv.conf doesn't apply
+ replica_fqdn = self.replica_fqdn
+ if not replica_fqdn.endswith('.'):
+ replica_fqdn += '.'
+
+ if self.check_dns(replica_fqdn):
+ self.log.debug('%s A/AAAA record resolvable', replica_fqdn)
+ return
+
+ self.log.info('Waiting for %s A or AAAA record to be resolvable',
+ replica_fqdn)
+ print 'This can be safely interrupted (Ctrl+C)'
+
+ try:
+ while not self.check_dns(replica_fqdn):
+ time.sleep(1)
+ except KeyboardInterrupt:
+ self.log.info('Interrupted')
+ else:
+ self.log.debug('%s A/AAAA record resolvable', replica_fqdn)
+
def copy_info_file(self, source, dest):
"""Copy a file into the info directory