summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--install/tools/ipa-upgradeconfig88
-rw-r--r--ipaserver/install/bindinstance.py94
2 files changed, 174 insertions, 8 deletions
diff --git a/install/tools/ipa-upgradeconfig b/install/tools/ipa-upgradeconfig
index 0cf59f293..07c8466cd 100644
--- a/install/tools/ipa-upgradeconfig
+++ b/install/tools/ipa-upgradeconfig
@@ -25,14 +25,18 @@ Upgrade configuration files to a newer template.
import sys
try:
- from ipapython import ipautil, sysrestore
+ from ipapython import ipautil, sysrestore, version
+ from ipapython.config import IPAOptionParser
+ from ipapython.ipa_log_manager import *
from ipaserver.install import installutils
from ipaserver.install import dsinstance
from ipaserver.install import httpinstance
from ipaserver.install import memcacheinstance
+ from ipaserver.install import bindinstance
from ipaserver.install import service
from ipaserver.install import cainstance
from ipaserver.install import certs
+ from ipaserver.install import sysupgrade
import ldap
import krbV
import re
@@ -49,6 +53,16 @@ error was:
""" % sys.exc_value
sys.exit(1)
+def parse_options():
+ parser = IPAOptionParser(version=version.VERSION)
+ parser.add_option("-d", "--debug", dest="debug", action="store_true",
+ default=False, help="print debugging information")
+
+ options, args = parser.parse_args()
+ safe_options = parser.get_safe_opts(options)
+
+ return safe_options, options
+
class KpasswdInstance(service.SimpleServiceInstance):
def __init__(self):
service.SimpleServiceInstance.__init__(self, "ipa_kpasswd")
@@ -249,6 +263,70 @@ def upgrade_httpd_selinux(fstore):
http = httpinstance.HTTPInstance(fstore)
http.configure_selinux_for_httpd()
+def enable_psearch_for_named():
+ """
+ From IPA 3.0, persistent search is a preferred mechanism for new DNS zone
+ detection and is also needed for other features (DNSSEC, SOA serial
+ updates). Enable psearch and make sure connections attribute is right.
+ This step is done just once for a case when user switched the persistent
+ search back to disabled.
+
+ When some change in named.conf is done, this functions returns True
+ """
+ changed = False
+
+ if not bindinstance.named_conf_exists():
+ # DNS service may not be configured
+ return
+
+ try:
+ psearch = bindinstance.named_conf_get_directive('psearch').lower()
+ except IOError, e:
+ root_logger.debug('Cannot retrieve psearch option from %s: %s',
+ bindinstance.NAMED_CONF, e)
+ return
+ if not sysupgrade.get_upgrade_state('named.conf', 'psearch_enabled'):
+ if psearch != "yes":
+ try:
+ bindinstance.named_conf_set_directive('zone_refresh', 0)
+ bindinstance.named_conf_set_directive('psearch', 'yes')
+ except IOError, e:
+ root_logger.error('Cannot enable psearch in %s: %s',
+ bindinstance.NAMED_CONF, e)
+ else:
+ changed = True
+ sysupgrade.set_upgrade_state('named.conf', 'psearch_enabled', True)
+
+ # make sure number of connections is right
+ minimum_connections = 2
+ if psearch == 'yes':
+ minimum_connections = 3
+ try:
+ connections = bindinstance.named_conf_get_directive('connections')
+ except IOError, e:
+ root_logger.debug('Cannot retrieve connections option from %s: %s',
+ bindinstance.NAMED_CONF, e)
+ return
+ if connections is not None:
+ try:
+ connections = int(connections)
+ except ValueError:
+ # this should not happend, but there is some bad value in
+ # "connections" option, bail out
+ pass
+ else:
+ if connections < minimum_connections:
+ try:
+ bindinstance.named_conf_set_directive('connections',
+ minimum_connections)
+ except IOError, e:
+ root_logger.error('Cannot update connections in %s: %s',
+ bindinstance.NAMED_CONF, e)
+ else:
+ changed = True
+
+ return changed
+
def main():
"""
Get some basics about the system. If getting those basics fail then
@@ -259,6 +337,10 @@ def main():
if not os.geteuid()==0:
sys.exit("\nYou must be root to run this script.\n")
+ safe_options, options = parse_options()
+
+ standard_logging_setup(None, debug=options.debug)
+
fstore = sysrestore.FileStore('/var/lib/ipa/sysrestore')
try:
@@ -304,6 +386,10 @@ def main():
cleanup_kdc(fstore)
upgrade_ipa_profile(krbctx.default_realm)
+ changed = enable_psearch_for_named()
+ if changed:
+ # configuration has changed, restart the name server
+ bindinstance.BindInstance(fstore).restart()
if __name__ == '__main__':
installutils.run_script(main, operation_name='ipa-upgradeconfig')
diff --git a/ipaserver/install/bindinstance.py b/ipaserver/install/bindinstance.py
index 623e39738..3ff593298 100644
--- a/ipaserver/install/bindinstance.py
+++ b/ipaserver/install/bindinstance.py
@@ -21,6 +21,7 @@ import tempfile
import os
import pwd
import netaddr
+import re
import installutils
import ldap
@@ -38,6 +39,12 @@ from ipapython.ipa_log_manager import *
import ipalib
from ipalib import api, util, errors
+NAMED_CONF = '/etc/named.conf'
+RESOLV_CONF = '/etc/resolv.conf'
+
+named_conf_ipa_re = re.compile(r'(?P<indent>\s*)arg\s+"(?P<name>\S+)\s(?P<value>[^"]+)";')
+named_conf_ipa_template = "%(indent)sarg \"%(name)s %(value)s\";\n"
+
def check_inst(unattended):
has_bind = True
# So far this file is always present in both RHEL5 and Fedora if all the necessary
@@ -57,7 +64,7 @@ def check_inst(unattended):
if not has_bind:
return False
- if not unattended and os.path.exists('/etc/named.conf'):
+ if not unattended and os.path.exists(NAMED_CONF):
msg = "Existing BIND configuration detected, overwrite?"
return ipautil.user_input(msg, False)
@@ -73,7 +80,10 @@ def create_reverse():
return ipautil.user_input("Do you want to configure the reverse zone?", True)
def named_conf_exists():
- named_fd = open('/etc/named.conf', 'r')
+ try:
+ named_fd = open(NAMED_CONF, 'r')
+ except IOError:
+ return False
lines = named_fd.readlines()
named_fd.close()
for line in lines:
@@ -81,6 +91,76 @@ def named_conf_exists():
return True
return False
+def named_conf_get_directive(name):
+ """Get a configuration option in bind-dyndb-ldap section of named.conf"""
+
+ with open(NAMED_CONF, 'r') as f:
+ ipa_section = False
+ for line in f:
+ if line.startswith('dynamic-db "ipa"'):
+ ipa_section = True
+ continue
+ if line.startswith('};'):
+ if ipa_section:
+ break
+
+ if ipa_section:
+ match = named_conf_ipa_re.match(line)
+
+ if match and name == match.group('name'):
+ return match.group('value')
+
+def named_conf_set_directive(name, value):
+ """
+ Set configuration option in bind-dyndb-ldap section of named.conf.
+
+ When the configuration option with given name does not exist, it
+ is added at the end of ipa section in named.conf.
+
+ If the value is set to None, the configuration option is removed
+ from named.conf.
+ """
+ new_lines = []
+
+ with open(NAMED_CONF, 'r') as f:
+ ipa_section = False
+ matched = False
+ last_indent = "\t"
+ for line in f:
+ if line.startswith('dynamic-db "ipa"'):
+ ipa_section = True
+ if line.startswith('};'):
+ if ipa_section and not matched:
+ # create a new conf
+ new_conf = named_conf_ipa_template \
+ % dict(indent=last_indent,
+ name=name,
+ value=value)
+ new_lines.append(new_conf)
+ ipa_section = False
+
+ if ipa_section and not matched:
+ match = named_conf_ipa_re.match(line)
+
+ if match:
+ last_indent = match.group('indent')
+ if name == match.group('name'):
+ matched = True
+ if value is not None:
+ if not isinstance(value, basestring):
+ value = str(value)
+ new_conf = named_conf_ipa_template \
+ % dict(indent=last_indent,
+ name=name,
+ value=value)
+ new_lines.append(new_conf)
+ continue
+ new_lines.append(line)
+
+ # write new configuration
+ with open(NAMED_CONF, 'w') as f:
+ f.write("".join(new_lines))
+
def dns_container_exists(fqdn, suffix, dm_password=None, ldapi=False, realm=None):
"""
Test whether the dns container exists.
@@ -610,18 +690,18 @@ class BindInstance(service.Service):
raise
def __setup_named_conf(self):
- self.fstore.backup_file('/etc/named.conf')
+ self.fstore.backup_file(NAMED_CONF)
named_txt = ipautil.template_file(ipautil.SHARE_DIR + "bind.named.conf.template", self.sub_dict)
- named_fd = open('/etc/named.conf', 'w')
+ named_fd = open(NAMED_CONF, 'w')
named_fd.seek(0)
named_fd.truncate(0)
named_fd.write(named_txt)
named_fd.close()
def __setup_resolv_conf(self):
- self.fstore.backup_file('/etc/resolv.conf')
+ self.fstore.backup_file(RESOLV_CONF)
resolv_txt = "search "+self.domain+"\nnameserver "+self.ip_address+"\n"
- resolv_fd = open('/etc/resolv.conf', 'w')
+ resolv_fd = open(RESOLV_CONF, 'w')
resolv_fd.seek(0)
resolv_fd.truncate(0)
resolv_fd.write(resolv_txt)
@@ -704,7 +784,7 @@ class BindInstance(service.Service):
if not running is None:
self.stop()
- for f in ["/etc/named.conf", "/etc/resolv.conf"]:
+ for f in [NAMED_CONF, RESOLV_CONF]:
try:
self.fstore.restore_file(f)
except ValueError, error: