summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xinstall/tools/ipa-dns-install71
-rwxr-xr-xinstall/tools/ipa-replica-install59
-rwxr-xr-xinstall/tools/ipa-server-install56
-rw-r--r--ipaserver/install/bindinstance.py110
-rw-r--r--ipaserver/install/installutils.py124
-rw-r--r--ipaserver/install/ipa_replica_prepare.py82
6 files changed, 255 insertions, 247 deletions
diff --git a/install/tools/ipa-dns-install b/install/tools/ipa-dns-install
index c9ea63ce3..ae60f211a 100755
--- a/install/tools/ipa-dns-install
+++ b/install/tools/ipa-dns-install
@@ -42,13 +42,16 @@ def parse_options():
sensitive=True, help="admin password")
parser.add_option("-d", "--debug", dest="debug", action="store_true",
default=False, help="print debugging information")
- parser.add_option("--ip-address", dest="ip_address",
+ parser.add_option("--ip-address", dest="ip_addresses",
+ default=[], action="append",
type="ip", ip_local=True, help="Master Server IP Address")
parser.add_option("--forwarder", dest="forwarders", action="append",
type="ip", help="Add a DNS forwarder")
parser.add_option("--no-forwarders", dest="no_forwarders", action="store_true",
default=False, help="Do not add any DNS forwarders, use root servers instead")
- parser.add_option("--reverse-zone", dest="reverse_zone", help="The reverse DNS zone to use")
+ parser.add_option("--reverse-zone", dest="reverse_zones",
+ default=[], action="append",
+ help="The reverse DNS zone to use")
parser.add_option("--no-reverse", dest="no_reverse", action="store_true",
default=False, help="Do not create new reverse DNS zone")
parser.add_option("--zonemgr", action="callback", callback=bindinstance.zonemgr_callback,
@@ -62,7 +65,7 @@ def parse_options():
if options.forwarders and options.no_forwarders:
parser.error("You cannot specify a --forwarder option together with --no-forwarders")
- elif options.reverse_zone and options.no_reverse:
+ elif options.reverse_zones and options.no_reverse:
parser.error("You cannot specify a --reverse-zone option together with --no-reverse")
if options.unattended:
@@ -130,46 +133,8 @@ def main():
except errors.ACIError:
sys.exit("Password is not valid!")
- # Check we have a public IP that is associated with the hostname
- if options.ip_address:
- ip = options.ip_address
- else:
- hostaddr = resolve_host(api.env.host)
- try:
- if len(hostaddr) > 1:
- print >> sys.stderr, "The server hostname resolves to more than one address:"
- for addr in hostaddr:
- print >> sys.stderr, " %s" % addr
-
- if options.ip_address:
- if str(options.ip_address) not in hostaddr:
- print >> sys.stderr, "Address passed in --ip-address did not match any resolved"
- print >> sys.stderr, "address!"
- sys.exit(1)
- print "Selected IP address:", str(options.ip_address)
- ip = options.ip_address
- else:
- if options.unattended:
- print >> sys.stderr, "Please use --ip-address option to specify the address"
- sys.exit(1)
- else:
- ip = read_ip_address(api.env.host, fstore)
- else:
- ip = hostaddr and ipautil.CheckedIPAddress(hostaddr[0], match_local=True)
- except Exception, e:
- print "Error: Invalid IP Address %s: %s" % (ip, e)
- ip = None
-
- if not ip:
- if options.unattended:
- sys.exit("Unable to resolve IP address for host name")
- else:
- ip = read_ip_address(api.env.host, fstore)
- ip_address = str(ip)
- root_logger.debug("will use ip_address: %s\n", ip_address)
-
- if options.reverse_zone and not bindinstance.verify_reverse_zone(options.reverse_zone, ip):
- sys.exit(1)
+ ip_addresses = get_server_ip_address(api.env.host, fstore,
+ options.unattended, True, options.ip_addresses)
if options.no_forwarders:
dns_forwarders = ()
@@ -186,19 +151,11 @@ def main():
ccache = krbV.default_context().default_ccache()
api.Backend.ldap2.connect(ccache)
- if options.reverse_zone:
- reverse_zone = bindinstance.normalize_zone(options.reverse_zone)
- else:
- reverse_zone = bindinstance.find_reverse_zone(ip)
- if reverse_zone is None and not options.no_reverse:
- if options.unattended:
- reverse_zone = util.get_reverse_zone_default(ip)
- elif bindinstance.create_reverse():
- reverse_zone = util.get_reverse_zone_default(ip)
- reverse_zone = bindinstance.read_reverse_zone(reverse_zone, ip)
+ reverse_zones = bindinstance.check_reverse_zones(ip_addresses,
+ options.reverse_zones, options, options.unattended, True)
- if reverse_zone is not None:
- print "Using reverse zone %s" % reverse_zone
+ if reverse_zones is not None:
+ print "Using reverse zone %s" % ', '.join(reverse_zones)
conf_ntp = ntpinstance.NTPInstance(fstore).is_enabled()
@@ -208,8 +165,8 @@ def main():
print "Please wait until the prompt is returned."
print ""
- bind.setup(api.env.host, ip_address, api.env.realm, api.env.domain,
- dns_forwarders, conf_ntp, reverse_zone, zonemgr=options.zonemgr)
+ bind.setup(api.env.host, ip_addresses, api.env.realm, api.env.domain,
+ dns_forwarders, conf_ntp, reverse_zones, zonemgr=options.zonemgr)
bind.create_instance()
# Restart http instance to make sure that python-dns has the right resolver
diff --git a/install/tools/ipa-replica-install b/install/tools/ipa-replica-install
index 2986685d0..74781d00d 100755
--- a/install/tools/ipa-replica-install
+++ b/install/tools/ipa-replica-install
@@ -67,8 +67,8 @@ def parse_options():
default=False, help="configure a dogtag CA")
basic_group.add_option("--setup-kra", dest="setup_kra", action="store_true",
default=False, help="configure a dogtag KRA")
- basic_group.add_option("--ip-address", dest="ip_address",
- type="ip", ip_local=True,
+ basic_group.add_option("--ip-address", dest="ip_addresses",
+ type="ip", ip_local=True, action="append", default=[],
help="Replica server IP Address")
basic_group.add_option("-p", "--password", dest="password", sensitive=True,
help="Directory Manager (existing master) password")
@@ -112,7 +112,8 @@ def parse_options():
type="ip", help="Add a DNS forwarder")
dns_group.add_option("--no-forwarders", dest="no_forwarders", action="store_true",
default=False, help="Do not add any DNS forwarders, use root servers instead")
- dns_group.add_option("--reverse-zone", dest="reverse_zone", help="The reverse DNS zone to use")
+ dns_group.add_option("--reverse-zone", dest="reverse_zones", default=[],
+ action="append", help="The reverse DNS zone to use")
dns_group.add_option("--no-reverse", dest="no_reverse", action="store_true",
default=False, help="Do not create new reverse DNS zone")
dns_group.add_option("--no-host-dns", dest="no_host_dns", action="store_true",
@@ -133,7 +134,7 @@ def parse_options():
parser.error("You cannot specify a --forwarder option without the --setup-dns option")
if options.no_forwarders:
parser.error("You cannot specify a --no-forwarders option without the --setup-dns option")
- if options.reverse_zone:
+ if options.reverse_zones:
parser.error("You cannot specify a --reverse-zone option without the --setup-dns option")
if options.no_reverse:
parser.error("You cannot specify a --no-reverse option without the --setup-dns option")
@@ -141,7 +142,7 @@ def parse_options():
parser.error("You cannot specify a --forwarder option together with --no-forwarders")
elif not options.forwarders and not options.no_forwarders:
parser.error("You must specify at least one --forwarder option or --no-forwarders option")
- elif options.reverse_zone and options.no_reverse:
+ elif options.reverse_zones and options.no_reverse:
parser.error("You cannot specify a --reverse-zone option together with --no-reverse")
return safe_options, options, args[0]
@@ -264,23 +265,9 @@ def install_bind(config, options):
forwarders = ()
bind = bindinstance.BindInstance(dm_password=config.dirman_password)
- if options.reverse_zone:
- if not bindinstance.verify_reverse_zone(options.reverse_zone, config.ip):
- sys.exit(1)
- reverse_zone = bindinstance.normalize_zone(options.reverse_zone)
- else:
- reverse_zone = bindinstance.find_reverse_zone(config.ip)
- if reverse_zone is None and not options.no_reverse:
- reverse_zone = util.get_reverse_zone_default(config.ip)
- if not options.unattended and bindinstance.create_reverse():
- reverse_zone = bindinstance.read_reverse_zone(reverse_zone, config.ip)
-
- if reverse_zone is not None:
- print "Using reverse zone %s" % reverse_zone
-
- bind.setup(config.host_name, config.ip_address, config.realm_name,
- config.domain_name, forwarders, options.conf_ntp, reverse_zone,
- ca_configured=options.setup_ca)
+ bind.setup(config.host_name, config.ips, config.realm_name,
+ config.domain_name, forwarders, options.conf_ntp,
+ config.reverse_zones, ca_configured=options.setup_ca)
bind.create_instance()
print ""
@@ -326,12 +313,16 @@ def install_dns_records(config, options):
config.master_host_name, config.dirman_password):
try:
bind = bindinstance.BindInstance(dm_password=config.dirman_password)
- reverse_zone = bindinstance.find_reverse_zone(config.ip)
-
- bind.add_master_dns_records(config.host_name, config.ip_address,
- config.realm_name, config.domain_name,
- reverse_zone, options.conf_ntp,
- options.setup_ca)
+ for ip in config.ips:
+ reverse_zone = bindinstance.find_reverse_zone(ip)
+
+ bind.add_master_dns_records(config.host_name,
+ str(ip),
+ config.realm_name,
+ config.domain_name,
+ reverse_zone,
+ options.conf_ntp,
+ options.setup_ca)
except errors.NotFound, e:
root_logger.debug('Replica DNS records could not be added '
'on master: %s', str(e))
@@ -534,8 +525,16 @@ def main():
# check replica host IP resolution
- config.ip = installutils.get_server_ip_address(config.host_name, fstore, True, options)
- config.ip_address = str(config.ip)
+ config.ips = installutils.get_server_ip_address(config.host_name, fstore,
+ options.unattended, options.setup_dns, options.ip_addresses)
+
+ ip_addresses = [str(ip) for ip in config.ips]
+ config.reverse_zones = bindinstance.check_reverse_zones(ip_addresses,
+ options.reverse_zones, options, True)
+
+ if config.reverse_zones is not None:
+ print "Using reverse zone(s) %s" % ', '.join(config.reverse_zones)
+
# Create the management framework config file
# Note: We must do this before bootstraping and finalizing ipalib.api
diff --git a/install/tools/ipa-server-install b/install/tools/ipa-server-install
index 86422e332..533023f2e 100755
--- a/install/tools/ipa-server-install
+++ b/install/tools/ipa-server-install
@@ -175,8 +175,8 @@ def parse_options():
help="create home directories for users "
"on their first login")
basic_group.add_option("--hostname", dest="host_name", help="fully qualified name of server")
- basic_group.add_option("--ip-address", dest="ip_address",
- type="ip", ip_local=True,
+ basic_group.add_option("--ip-address", dest="ip_addresses",
+ type="ip", ip_local=True, action="append", default=[],
help="Master Server IP Address")
basic_group.add_option("-N", "--no-ntp", dest="conf_ntp", action="store_false",
help="do not configure ntp", default=True)
@@ -236,7 +236,8 @@ def parse_options():
type="ip", help="Add a DNS forwarder")
dns_group.add_option("--no-forwarders", dest="no_forwarders", action="store_true",
default=False, help="Do not add any DNS forwarders, use root servers instead")
- dns_group.add_option("--reverse-zone", dest="reverse_zone", help="The reverse DNS zone to use")
+ dns_group.add_option("--reverse-zone", dest="reverse_zones", help="The reverse DNS zone to use",
+ action="append", default=[])
dns_group.add_option("--no-reverse", dest="no_reverse", action="store_true",
default=False, help="Do not create reverse DNS zone")
dns_group.add_option("--zonemgr", action="callback", callback=bindinstance.zonemgr_callback,
@@ -280,13 +281,13 @@ def parse_options():
parser.error("You cannot specify a --forwarder option without the --setup-dns option")
if options.no_forwarders:
parser.error("You cannot specify a --no-forwarders option without the --setup-dns option")
- if options.reverse_zone:
+ if options.reverse_zones:
parser.error("You cannot specify a --reverse-zone option without the --setup-dns option")
if options.no_reverse:
parser.error("You cannot specify a --no-reverse option without the --setup-dns option")
elif options.forwarders and options.no_forwarders:
parser.error("You cannot specify a --forwarder option together with --no-forwarders")
- elif options.reverse_zone and options.no_reverse:
+ elif options.reverse_zones and options.no_reverse:
parser.error("You cannot specify a --reverse-zone option together with --no-reverse")
if options.uninstall:
@@ -829,11 +830,11 @@ def main():
realm_name = ""
host_name = ""
domain_name = ""
- ip_address = ""
+ ip_addresses = []
master_password = ""
dm_password = ""
admin_password = ""
- reverse_zone = None
+ reverse_zones = []
if not options.setup_dns and not options.unattended:
if ipautil.user_input("Do you want to configure integrated DNS (BIND)?", False):
@@ -892,11 +893,8 @@ def main():
domain_name = domain_name.lower()
- ip = get_server_ip_address(host_name, fstore, options.unattended, options)
- ip_address = str(ip)
-
- if options.reverse_zone and not bindinstance.verify_reverse_zone(options.reverse_zone, ip):
- sys.exit(1)
+ ip_addresses = get_server_ip_address(host_name, fstore,
+ options.unattended, options.setup_dns, options.ip_addresses)
if not options.realm_name:
realm_name = read_realm_name(domain_name, options.unattended)
@@ -973,35 +971,29 @@ def main():
else:
dns_forwarders = read_dns_forwarders()
- if options.reverse_zone:
- reverse_zone = bindinstance.normalize_zone(options.reverse_zone)
- elif not options.no_reverse:
- if options.unattended:
- reverse_zone = util.get_reverse_zone_default(ip)
- elif bindinstance.create_reverse():
- reverse_zone = util.get_reverse_zone_default(ip)
- reverse_zone = bindinstance.read_reverse_zone(reverse_zone, ip)
-
- if reverse_zone is not None:
- print "Using reverse zone %s" % reverse_zone
+ reverse_zones = bindinstance.check_reverse_zones(ip_addresses,
+ options.reverse_zones, options, options.unattended)
+
+ if reverse_zones:
+ print "Using reverse zone(s) %s" % ", ".join(str(rz) for rz in reverse_zones)
else:
dns_forwarders = ()
root_logger.debug("will use dns_forwarders: %s\n" % str(dns_forwarders))
print
print "The IPA Master Server will be configured with:"
- print "Hostname: %s" % host_name
- print "IP address: %s" % ip_address
- print "Domain name: %s" % domain_name
- print "Realm name: %s" % realm_name
+ print "Hostname: %s" % host_name
+ print "IP address(es): %s" % ", ".join(str(ip) for ip in ip_addresses)
+ print "Domain name: %s" % domain_name
+ print "Realm name: %s" % realm_name
print
if options.setup_dns:
print "BIND DNS server will be configured to serve IPA domain with:"
print "Forwarders: %s" % ("No forwarders" if not dns_forwarders \
else ", ".join([str(ip) for ip in dns_forwarders]))
- print "Reverse zone: %s" % ("No reverse zone" if options.no_reverse \
- or reverse_zone is None else reverse_zone)
+ print "Reverse zone(s): %s" % ("No reverse zone" if options.no_reverse \
+ or reverse_zones is None else ", ".join(str(rz) for rz in reverse_zones))
print
# If domain name and realm does not match, IPA server will not be able
@@ -1112,7 +1104,7 @@ def main():
options.host_name = host_name
options.unattended = True
options.forwarders = dns_forwarders
- options.reverse_zone = reverse_zone
+ options.reverse_zones = reverse_zones
write_cache(vars(options))
ca.configure_instance(host_name, domain_name, dm_password,
dm_password, csr_file=paths.ROOT_IPA_CSR,
@@ -1206,8 +1198,8 @@ def main():
# Create a BIND instance
bind = bindinstance.BindInstance(fstore, dm_password)
- bind.setup(host_name, ip_address, realm_name, domain_name, dns_forwarders,
- options.conf_ntp, reverse_zone, zonemgr=options.zonemgr,
+ bind.setup(host_name, ip_addresses, realm_name, domain_name, dns_forwarders,
+ options.conf_ntp, reverse_zones, zonemgr=options.zonemgr,
ca_configured=setup_ca)
if options.setup_dns:
api.Backend.ldap2.connect(bind_dn=DN(('cn', 'Directory Manager')), bind_pw=dm_password)
diff --git a/ipaserver/install/bindinstance.py b/ipaserver/install/bindinstance.py
index cece85ec6..2e8836ec6 100644
--- a/ipaserver/install/bindinstance.py
+++ b/ipaserver/install/bindinstance.py
@@ -22,6 +22,7 @@ import os
import pwd
import netaddr
import re
+import sys
import ldap
@@ -250,7 +251,6 @@ def verify_reverse_zone(zone, ip_address):
try:
get_reverse_record_name(zone, ip_address)
except ValueError:
- print "Invalid reverse zone %s" % zone
return False
return True
@@ -276,6 +276,8 @@ def read_reverse_zone(default, ip_address):
return None
if verify_reverse_zone(zone, ip_address):
break
+ else:
+ print "Invalid reverse zone %s for IP address %s" % (zone, ip_address)
return normalize_zone(zone)
@@ -378,6 +380,48 @@ def zonemgr_callback(option, opt_str, value, parser):
parser.values.zonemgr = value
+def check_reverse_zones(ip_addresses, reverse_zones, options, unattended, search_reverse_zones=False):
+ reverse_asked = False
+
+ ret_reverse_zones = []
+ # check that there is IP address in every reverse zone
+ if reverse_zones:
+ for rz in reverse_zones:
+ for ip in ip_addresses:
+ if verify_reverse_zone(rz, ip):
+ ret_reverse_zones.append(normalize_zone(rz))
+ break
+ else:
+ # no ip matching reverse zone found
+ sys.exit("There is no IP address matching reverse zone %s." % rz)
+ if not options.no_reverse:
+ # check that there is reverse zone for every IP
+ for ip in ip_addresses:
+ if search_reverse_zones and find_reverse_zone(str(ip)):
+ # reverse zone is already in LDAP
+ continue
+ for rz in ret_reverse_zones:
+ if verify_reverse_zone(rz, ip):
+ # reverse zone was entered by user
+ break
+ else:
+ # no reverse zone for ip found
+ if not reverse_asked:
+ if not unattended and not reverse_zones:
+ # user did not specify reverse_zone nor no_reverse
+ options.no_reverse = not create_reverse()
+ if options.no_reverse:
+ # user decided not to create reverse zone
+ return []
+ reverse_asked = True
+ rz = get_reverse_zone_default(str(ip))
+ if not unattended:
+ rz = read_reverse_zone(rz, str(ip))
+ ret_reverse_zones.append(rz)
+
+ return ret_reverse_zones
+
+
class DnsBackup(object):
def __init__(self, service):
self.service = service
@@ -437,11 +481,11 @@ class BindInstance(service.Service):
self.named_user = None
self.domain = None
self.host = None
- self.ip_address = None
+ self.ip_addresses = []
self.realm = None
self.forwarders = None
self.sub_dict = None
- self.reverse_zone = None
+ self.reverse_zones = []
self.dm_password = dm_password
if fstore:
@@ -451,19 +495,19 @@ class BindInstance(service.Service):
suffix = ipautil.dn_attribute_property('_suffix')
- def setup(self, fqdn, ip_address, realm_name, domain_name, forwarders, ntp,
- reverse_zone, named_user="named", zonemgr=None,
+ def setup(self, fqdn, ip_addresses, realm_name, domain_name, forwarders, ntp,
+ reverse_zones, named_user="named", zonemgr=None,
ca_configured=None):
self.named_user = named_user
self.fqdn = fqdn
- self.ip_address = ip_address
+ self.ip_addresses = ip_addresses
self.realm = realm_name
self.domain = domain_name
self.forwarders = forwarders
self.host = fqdn.split(".")[0]
self.suffix = ipautil.realm_to_suffix(self.realm)
self.ntp = ntp
- self.reverse_zone = reverse_zone
+ self.reverse_zones = reverse_zones
self.ca_configured = ca_configured
if not zonemgr:
@@ -509,8 +553,9 @@ class BindInstance(service.Service):
# get a connection to the DS
self.ldap_connect()
- if installutils.record_in_hosts(self.ip_address, self.fqdn) is None:
- installutils.add_record_to_hosts(self.ip_address, self.fqdn)
+ for ip_address in self.ip_addresses:
+ if installutils.record_in_hosts(str(ip_address), self.fqdn) is None:
+ installutils.add_record_to_hosts(str(ip_address), self.fqdn)
# Make sure generate-rndc-key.sh runs before named restart
self.step("generating rndc key file", self.__generate_rndc_key)
@@ -520,8 +565,7 @@ class BindInstance(service.Service):
if not dns_zone_exists(self.domain):
self.step("setting up our zone", self.__setup_zone)
-
- if self.reverse_zone is not None:
+ if self.reverse_zones:
self.step("setting up reverse zone", self.__setup_reverse_zone)
self.step("setting up our own record", self.__add_self)
@@ -574,18 +618,17 @@ class BindInstance(service.Service):
else:
optional_ntp = ""
- addr = netaddr.IPAddress(self.ip_address)
- if addr.version in (4, 6):
- ipa_ca = "%s\t\t\tIN %s\t\t\t%s\n" % (
- IPA_CA_RECORD,
- "A" if addr.version == 4 else "AAAA",
- self.ip_address)
- else:
- ipa_ca = ""
+ ipa_ca = ""
+ for addr in self.ip_addresses:
+ if addr.version in (4, 6):
+ ipa_ca += "%s\t\t\tIN %s\t\t\t%s\n" % (
+ IPA_CA_RECORD,
+ "A" if addr.version == 4 else "AAAA",
+ str(addr))
self.sub_dict = dict(
FQDN=self.fqdn,
- IP=self.ip_address,
+ IP=[str(ip) for ip in self.ip_addresses],
DOMAIN=self.domain,
HOST=self.host,
REALM=self.realm,
@@ -618,7 +661,8 @@ class BindInstance(service.Service):
def __setup_reverse_zone(self):
# Always use force=True as named is not set up yet
- add_zone(self.reverse_zone, self.zonemgr, ns_hostname=api.env.host,
+ for reverse_zone in self.reverse_zones:
+ add_zone(reverse_zone, self.zonemgr, ns_hostname=api.env.host,
dns_backup=self.dns_backup, force=True)
def __add_master_records(self, fqdn, addrs):
@@ -665,7 +709,7 @@ class BindInstance(service.Service):
add_ptr_rr(reverse_zone, addr, fqdn)
def __add_self(self):
- self.__add_master_records(self.fqdn, [self.ip_address])
+ self.__add_master_records(self.fqdn, self.ip_addresses)
def __add_others(self):
entries = self.admin_conn.get_entries(
@@ -710,7 +754,7 @@ class BindInstance(service.Service):
pass
def __add_ipa_ca_record(self):
- self.__add_ipa_ca_records(self.fqdn, [self.ip_address],
+ self.__add_ipa_ca_records(self.fqdn, self.ip_addresses,
self.ca_configured)
if self.first_instance:
@@ -798,7 +842,17 @@ class BindInstance(service.Service):
def __setup_resolv_conf(self):
self.fstore.backup_file(RESOLV_CONF)
- resolv_txt = "search "+self.domain+"\nnameserver "+self.ip_address+"\n"
+ resolv_txt = "search "+self.domain+"\n"
+
+ for ip_address in self.ip_addresses:
+ if ip_address.version == 4:
+ resolv_txt += "nameserver 127.0.0.1\n"
+ break
+
+ for ip_address in self.ip_addresses:
+ if ip_address.version == 6:
+ resolv_txt += "nameserver ::1\n"
+ break
try:
resolv_fd = open(RESOLV_CONF, 'w')
resolv_fd.seek(0)
@@ -812,16 +866,16 @@ class BindInstance(service.Service):
installutils.check_entropy()
ipautil.run(['/usr/libexec/generate-rndc-key.sh'])
- def add_master_dns_records(self, fqdn, ip_address, realm_name, domain_name,
- reverse_zone, ntp=False, ca_configured=None):
+ def add_master_dns_records(self, fqdn, ip_addresses, realm_name, domain_name,
+ reverse_zones, ntp=False, ca_configured=None):
self.fqdn = fqdn
- self.ip_address = ip_address
+ self.ip_addresses = ip_addresses
self.realm = realm_name
self.domain = domain_name
self.host = fqdn.split(".")[0]
self.suffix = ipautil.realm_to_suffix(self.realm)
self.ntp = ntp
- self.reverse_zone = reverse_zone
+ self.reverse_zones = reverse_zones
self.ca_configured = ca_configured
self.first_instance = False
self.zonemgr = 'hostmaster.%s' % self.domain
diff --git a/ipaserver/install/installutils.py b/ipaserver/install/installutils.py
index 34ae30624..c8e1a8de9 100644
--- a/ipaserver/install/installutils.py
+++ b/ipaserver/install/installutils.py
@@ -222,6 +222,7 @@ def add_record_to_hosts(ip, host_name, conf_file=paths.HOSTS):
hosts_fd.write(ip+'\t'+host_name+' '+host_name.split('.')[0]+'\n')
hosts_fd.close()
+# TODO: Remove when removing usage from ipa-adtrust-install
def read_ip_address(host_name, fstore):
while True:
ip = ipautil.user_input("Please provide the IP address to be used for this host name", allow_empty = False)
@@ -235,6 +236,22 @@ def read_ip_address(host_name, fstore):
return ip_parsed
+def read_ip_addresses(host_name, fstore):
+ ips = []
+ print "Enter the IP address to use, or press Enter to finish."
+ while True:
+ ip = ipautil.user_input("Please provide the IP address to be used for this host name", allow_empty = True)
+ if not ip:
+ break
+ try:
+ ip_parsed = ipautil.CheckedIPAddress(ip, match_local=True)
+ except Exception, e:
+ print "Error: Invalid IP Address %s: %s" % (ip, e)
+ continue
+ ips.append(ip)
+
+ return ips
+
def read_dns_forwarders():
addrs = []
if ipautil.user_input("Do you want to configure DNS forwarders?", True):
@@ -426,7 +443,7 @@ def get_host_name(no_host_dns):
verify_fqdn(hostname, no_host_dns)
return hostname
-def get_server_ip_address(host_name, fstore, unattended, options):
+def get_server_ip_address(host_name, fstore, unattended, setup_dns, ip_addresses):
# Check we have a public IP that is associated with the hostname
try:
hostaddr = resolve_host(host_name)
@@ -441,74 +458,59 @@ def get_server_ip_address(host_name, fstore, unattended, options):
ip_add_to_hosts = False
- if len(hostaddr) > 1:
- print >> sys.stderr, "The server hostname resolves to more than one address:"
- for addr in hostaddr:
- print >> sys.stderr, " %s" % addr
+ ips = []
+ if len(hostaddr):
+ for ha in hostaddr:
+ try:
+ ips.append(ipautil.CheckedIPAddress(ha, match_local=True))
+ except ValueError, e:
+ root_logger.warning("Invalid IP address %s for %s: %s", ha, host_name, unicode(e))
- if options.ip_address:
- if str(options.ip_address) not in hostaddr:
- print >> sys.stderr, "Address passed in --ip-address did not match any resolved"
- print >> sys.stderr, "address!"
- sys.exit(1)
- print "Selected IP address:", str(options.ip_address)
- ip = options.ip_address
+ if not ips and not ip_addresses:
+ if not unattended:
+ ip_addresses = read_ip_addresses(host_name, fstore)
+
+ if ip_addresses:
+ if setup_dns:
+ ips = ip_addresses
else:
- if unattended:
- print >> sys.stderr, "Please use --ip-address option to specify the address"
- sys.exit(1)
+ # all specified addresses was resolved for this host
+ if set(ip_addresses) <= set(ips):
+ ips = ip_addresses
else:
- ip = read_ip_address(host_name, fstore)
- elif len(hostaddr) == 1:
- try:
- ip = ipautil.CheckedIPAddress(hostaddr[0], match_local=True)
- except ValueError, e:
- sys.exit("Invalid IP Address %s for %s: %s" % (hostaddr[0], host_name, unicode(e)))
- else:
- # hostname is not resolvable
- ip = options.ip_address
+ print >>sys.stderr, "Error: the hostname resolves to IP address(es) that are different"
+ print >>sys.stderr, "from those provided on the command line. Please fix your DNS"
+ print >>sys.stderr, "or /etc/hosts file and restart the installation."
+ print >>sys.stderr, "Provided but not resolved address(es): %s" % \
+ ", ".join(str(ip) for ip in (set(ip_addresses) - set(ips)))
+ sys.exit(1)
ip_add_to_hosts = True
- if ip is None:
- print "Unable to resolve IP address for host name"
- if unattended:
- sys.exit(1)
-
- if options.ip_address:
- if options.ip_address != ip and not options.setup_dns:
- print >>sys.stderr, "Error: the hostname resolves to an IP address that is different"
- print >>sys.stderr, "from the one provided on the command line. Please fix your DNS"
- print >>sys.stderr, "or /etc/hosts file and restart the installation."
- sys.exit(1)
-
- ip = options.ip_address
-
- if ip is None:
- ip = read_ip_address(host_name, fstore)
- root_logger.debug("read ip_address: %s\n" % str(ip))
+ if not ips:
+ print >> sys.stderr, "No usable IP address provided nor resolved."
+ sys.exit(1)
- ip_address = str(ip)
+ for ip_address in ips:
+ # check /etc/hosts sanity, add a record when needed
+ hosts_record = record_in_hosts(str(ip_address))
- # check /etc/hosts sanity, add a record when needed
- hosts_record = record_in_hosts(ip_address)
+ if hosts_record is None:
+ if ip_add_to_hosts:
+ print "Adding ["+str(ip_address)+" "+host_name+"] to your /etc/hosts file"
+ fstore.backup_file(paths.HOSTS)
+ add_record_to_hosts(str(ip_address), host_name)
+ else:
+ primary_host = hosts_record[1][0]
+ if primary_host != host_name:
+ print >>sys.stderr, "Error: there is already a record in /etc/hosts for IP address %s:" \
+ % ip_address
+ print >>sys.stderr, hosts_record[0], " ".join(hosts_record[1])
+ print >>sys.stderr, "Chosen hostname %s does not match configured canonical hostname %s" \
+ % (host_name, primary_host)
+ print >>sys.stderr, "Please fix your /etc/hosts file and restart the installation."
+ sys.exit(1)
- if hosts_record is None:
- if ip_add_to_hosts or options.setup_dns:
- print "Adding ["+ip_address+" "+host_name+"] to your /etc/hosts file"
- fstore.backup_file(paths.HOSTS)
- add_record_to_hosts(ip_address, host_name)
- else:
- primary_host = hosts_record[1][0]
- if primary_host != host_name:
- print >>sys.stderr, "Error: there is already a record in /etc/hosts for IP address %s:" \
- % ip_address
- print >>sys.stderr, hosts_record[0], " ".join(hosts_record[1])
- print >>sys.stderr, "Chosen hostname %s does not match configured canonical hostname %s" \
- % (host_name, primary_host)
- print >>sys.stderr, "Please fix your /etc/hosts file and restart the installation."
- sys.exit(1)
-
- return ip
+ return ips
def expand_replica_info(filename, password):
"""
diff --git a/ipaserver/install/ipa_replica_prepare.py b/ipaserver/install/ipa_replica_prepare.py
index 7768fd311..e27eb6dd4 100644
--- a/ipaserver/install/ipa_replica_prepare.py
+++ b/ipaserver/install/ipa_replica_prepare.py
@@ -54,9 +54,11 @@ class ReplicaPrepare(admintool.AdminTool):
parser.add_option("-p", "--password", dest="password",
help="Directory Manager password (for the existing master)")
- parser.add_option("--ip-address", dest="ip_address", type="ip",
+ parser.add_option("--ip-address", dest="ip_addresses", type="ip",
+ action="append", default=[],
help="add A and PTR records of the future replica")
- parser.add_option("--reverse-zone", dest="reverse_zone",
+ parser.add_option("--reverse-zone", dest="reverse_zones",
+ action="append", default=[],
help="the reverse DNS zone to use")
parser.add_option("--no-reverse", dest="no_reverse",
action="store_true", default=False,
@@ -95,14 +97,14 @@ class ReplicaPrepare(admintool.AdminTool):
super(ReplicaPrepare, self).validate_options(needs_root=True)
installutils.check_server_configuration()
- if not options.ip_address:
- if options.reverse_zone:
+ if not options.ip_addresses:
+ if options.reverse_zones:
self.option_parser.error("You cannot specify a --reverse-zone "
"option without the --ip-address option")
if options.no_reverse:
self.option_parser.error("You cannot specify a --no-reverse "
"option without the --ip-address option")
- elif options.reverse_zone and options.no_reverse:
+ elif options.reverse_zones and options.no_reverse:
self.option_parser.error("You cannot specify a --reverse-zone "
"option together with --no-reverse")
@@ -192,7 +194,7 @@ class ReplicaPrepare(admintool.AdminTool):
except installutils.BadHostError, e:
msg = str(e)
if isinstance(e, installutils.HostLookupError):
- if options.ip_address is None:
+ if not options.ip_addresses:
if dns_container_exists(
api.env.host, api.env.basedn,
dm_password=self.dirman_password,
@@ -206,7 +208,7 @@ class ReplicaPrepare(admintool.AdminTool):
else:
raise
- if options.ip_address:
+ if options.ip_addresses:
if not dns_container_exists(api.env.host, api.env.basedn,
dm_password=self.dirman_password,
ldapi=True, realm=api.env.realm):
@@ -215,9 +217,19 @@ class ReplicaPrepare(admintool.AdminTool):
"because DNS is not managed by IPA. Please create DNS "
"record manually and then omit --ip-address option.")
raise admintool.ScriptError("Cannot add DNS record")
- if options.reverse_zone and not bindinstance.verify_reverse_zone(
- options.reverse_zone, options.ip_address):
- raise admintool.ScriptError("Invalid reverse zone")
+
+ disconnect = False
+ if not api.Backend.ldap2.isconnected():
+ api.Backend.ldap2.connect(
+ bind_dn=DN(('cn', 'Directory Manager')),
+ bind_pw=self.dirman_password)
+ disconnect = True
+
+ options.reverse_zones = bindinstance.check_reverse_zones(
+ options.ip_addresses, options.reverse_zones, options, False,
+ True)
+ if disconnect:
+ api.Backend.ldap2.disconnect()
if options.http_pkcs12:
if options.http_pin is None:
@@ -293,7 +305,7 @@ class ReplicaPrepare(admintool.AdminTool):
finally:
shutil.rmtree(self.top_dir)
- if options.ip_address:
+ if options.ip_addresses:
self.add_dns_records()
if options.wait_for_dns:
@@ -420,46 +432,38 @@ class ReplicaPrepare(admintool.AdminTool):
options = self.options
self.log.info("Adding DNS records for %s", self.replica_fqdn)
- api.Backend.ldap2.connect(
- bind_dn=DN(('cn', 'Directory Manager')),
- bind_pw=self.dirman_password)
-
name, domain = self.replica_fqdn.split(".", 1)
- ip = options.ip_address
- ip_address = str(ip)
-
- if options.reverse_zone:
- reverse_zone = bindinstance.normalize_zone(options.reverse_zone)
- else:
- reverse_zone = bindinstance.find_reverse_zone(ip)
- if reverse_zone is None and not options.no_reverse:
- reverse_zone = bindinstance.get_reverse_zone_default(ip)
-
+ if not api.Backend.ldap2.isconnected():
+ api.Backend.ldap2.connect(
+ bind_dn=DN(('cn', 'Directory Manager')),
+ bind_pw=self.dirman_password)
try:
add_zone(domain)
except errors.PublicError, e:
raise admintool.ScriptError(
"Could not create forward DNS zone for the replica: %s" % e)
- try:
- add_fwd_rr(domain, name, ip_address)
- except errors.PublicError, e:
- raise admintool.ScriptError(
- "Could not add forward DNS record for the replica: %s" % e)
+ for reverse_zone in options.reverse_zones:
+ self.log.info("Adding reverse zone %s", reverse_zone)
+ add_zone(reverse_zone)
- if reverse_zone is not None:
- self.log.info("Using reverse zone %s", reverse_zone)
+ for ip in options.ip_addresses:
+ ip_address = str(ip)
try:
- add_zone(reverse_zone)
+ add_fwd_rr(domain, name, ip_address)
except errors.PublicError, e:
raise admintool.ScriptError(
- "Could not create reverse DNS zone for replica: %s" % e)
- try:
- add_ptr_rr(reverse_zone, ip_address, self.replica_fqdn)
- except errors.PublicError, e:
- raise admintool.ScriptError(
- "Could not add reverse DNS record for the replica: %s" % e)
+ "Could not add forward DNS record for the replica: %s" % e)
+
+ if not options.no_reverse:
+ reverse_zone = bindinstance.find_reverse_zone(ip)
+ try:
+ add_ptr_rr(reverse_zone, ip_address, self.replica_fqdn)
+ except errors.PublicError, e:
+ 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"""