replica-install: Use different API instance for the remote server

Reviewed-By: Tomas Babej <tbabej@redhat.com>
This commit is contained in:
Jan Cholasta 2015-03-04 09:35:06 +00:00 committed by Tomas Babej
parent d7ef7e1ca0
commit 8713c5a695
2 changed files with 129 additions and 153 deletions

View File

@ -41,7 +41,7 @@ from ipaserver.install.installutils import (
from ipaserver.plugins.ldap2 import ldap2
from ipaserver.install import cainstance
from ipaserver.install import krainstance
from ipalib import api, errors, util, certstore, x509
from ipalib import api, create_api, errors, util, certstore, x509
from ipalib.constants import CACERT
from ipapython import version
from ipapython.config import IPAOptionParser
@ -287,62 +287,34 @@ def install_bind(config, options):
print ""
@contextmanager
def temporary_ldap2_connection(host_name, bind_pw, bind_dn=DIRMAN_DN):
"""Context in which the ldap2 backend is connected to the given host
When the context is entered, forcefully change the ldap2's URI and connect
with the given password.
When it's exited, disconnect and restore ldap2 to previous configuration.
Needed to use the standard IPA tools on the remote master, before the
DS on localhost is installed.
"""
# TODO: We shouldn't have to resort to such hacks
cur_uri = api.Backend.ldap2.ldap_uri
# ldap2 is finalized at this point, so use __setattr__ directly
object.__setattr__(api.Backend.ldap2, 'ldap_uri',
'ldaps://%s' % ipautil.format_netloc(host_name))
api.Backend.ldap2.connect(bind_dn=DIRMAN_DN, bind_pw=bind_pw,
tls_cacertfile=CACERT)
yield
api.Backend.ldap2.disconnect()
#set it back to the default
object.__setattr__(api.Backend.ldap2, 'ldap_uri', cur_uri)
def install_dns_records(config, options):
def install_dns_records(config, options, remote_api):
if not bindinstance.dns_container_exists(config.master_host_name,
ipautil.realm_to_suffix(config.realm_name),
dm_password=config.dirman_password):
return
# We have to force to connect to the remote master because we do this step
# before our DS server is installed.
with temporary_ldap2_connection(
config.master_host_name, config.dirman_password):
try:
bind = bindinstance.BindInstance(dm_password=config.dirman_password)
for ip in config.ips:
reverse_zone = bindinstance.find_reverse_zone(ip)
try:
bind = bindinstance.BindInstance(dm_password=config.dirman_password,
api=remote_api)
for ip in config.ips:
reverse_zone = bindinstance.find_reverse_zone(ip, remote_api)
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))
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))
# we should not fail here no matter what
except Exception, e:
root_logger.info('Replica DNS records could not be added '
'on master: %s', str(e))
# we should not fail here no matter what
except Exception, e:
root_logger.info('Replica DNS records could not be added '
'on master: %s', str(e))
def check_dirsrv():
@ -604,93 +576,96 @@ def main():
"ipa-replica-prepare to create a new replica file.")
ldapuri = 'ldaps://%s' % ipautil.format_netloc(config.master_host_name)
replman = conn = None
remote_api = create_api(mode=None)
remote_api.bootstrap(in_server=True, context='installer',
ldap_uri=ldapuri, basedn=DN())
remote_api.finalize()
conn = remote_api.Backend.ldap2
replman = None
try:
# Try out the password
conn = ldap2(shared_instance=False, ldap_uri=ldapuri, base_dn='')
conn.connect(bind_dn=DIRMAN_DN, bind_pw=config.dirman_password,
tls_cacertfile=cafile)
replman = ReplicationManager(config.realm_name, config.master_host_name,
config.dirman_password)
# Check that we don't already have a replication agreement
try:
(agreement_cn, agreement_dn) = replman.agreement_dn(config.host_name)
entry = conn.get_entry(agreement_dn, ['*'])
except errors.NotFound:
pass
# Try out the password
conn.connect(bind_dn=DIRMAN_DN, bind_pw=config.dirman_password,
tls_cacertfile=cafile)
replman = ReplicationManager(config.realm_name, config.master_host_name,
config.dirman_password)
# Check that we don't already have a replication agreement
try:
(agreement_cn, agreement_dn) = replman.agreement_dn(config.host_name)
entry = conn.get_entry(agreement_dn, ['*'])
except errors.NotFound:
pass
else:
root_logger.info('Error: A replication agreement for this host '
'already exists.')
print ('A replication agreement for this host already exists. '
'It needs to be removed.')
print "Run this on the master that generated the info file:"
print " %% ipa-replica-manage del %s --force" % config.host_name
exit(3)
# Check pre-existing host entry
try:
entry = conn.find_entries(u'fqdn=%s' % config.host_name, ['fqdn'], DN(api.env.container_host, api.env.basedn))
except errors.NotFound:
pass
else:
root_logger.info(
'Error: Host %s already exists on the master server.' % config.host_name)
print 'The host %s already exists on the master server.' % config.host_name
print "You should remove it before proceeding:"
print " %% ipa host-del %s" % config.host_name
exit(3)
# Install CA cert so that we can do SSL connections with ldap
install_ca_cert(conn, api.env.basedn, api.env.realm, cafile)
dns_masters = remote_api.Object['dnsrecord'].get_dns_masters()
if dns_masters:
if not options.no_host_dns:
master = config.master_host_name
root_logger.debug('Check forward/reverse DNS resolution')
resolution_ok = (
check_dns_resolution(master, dns_masters) and
check_dns_resolution(config.host_name, dns_masters))
if not resolution_ok and not options.unattended:
if not ipautil.user_input("Continue?", False):
sys.exit(0)
else:
root_logger.debug('No IPA DNS servers, '
'skipping forward/reverse resolution check')
except errors.ACIError:
sys.exit("\nThe password provided is incorrect for LDAP server %s" % config.master_host_name)
except errors.LDAPError:
sys.exit("\nUnable to connect to LDAP server %s" % config.master_host_name)
finally:
if replman and replman.conn:
replman.conn.unbind()
if options.skip_schema_check:
root_logger.info("Skipping CA DS schema check")
else:
root_logger.info('Error: A replication agreement for this host '
'already exists.')
print ('A replication agreement for this host already exists. '
'It needs to be removed.')
print "Run this on the master that generated the info file:"
print " %% ipa-replica-manage del %s --force" % config.host_name
exit(3)
cainstance.replica_ca_install_check(config)
# Check pre-existing host entry
try:
entry = conn.find_entries(u'fqdn=%s' % config.host_name, ['fqdn'], DN(api.env.container_host, api.env.basedn))
except errors.NotFound:
pass
else:
root_logger.info(
'Error: Host %s already exists on the master server.' % config.host_name)
print 'The host %s already exists on the master server.' % config.host_name
print "You should remove it before proceeding:"
print " %% ipa host-del %s" % config.host_name
exit(3)
# Configure ntpd
if options.conf_ntp:
ipaclient.ntpconf.force_ntpd(sstore)
ntp = ntpinstance.NTPInstance()
ntp.create_instance()
# Install CA cert so that we can do SSL connections with ldap
install_ca_cert(conn, api.env.basedn, api.env.realm, cafile)
# Configure dirsrv
ds = install_replica_ds(config)
# If remote host has DNS, check forward/reverse resolution
with temporary_ldap2_connection(
config.master_host_name, config.dirman_password):
dns_masters = api.Object['dnsrecord'].get_dns_masters()
if dns_masters:
if not options.no_host_dns:
master = config.master_host_name
root_logger.debug('Check forward/reverse DNS resolution')
resolution_ok = (
check_dns_resolution(master, dns_masters) and
check_dns_resolution(config.host_name, dns_masters))
if not resolution_ok and not options.unattended:
if not ipautil.user_input("Continue?", False):
sys.exit(0)
else:
root_logger.debug('No IPA DNS servers, '
'skipping forward/reverse resolution check')
# Configure the CA if necessary
CA = cainstance.install_replica_ca(config)
except errors.ACIError:
sys.exit("\nThe password provided is incorrect for LDAP server %s" % config.master_host_name)
except errors.LDAPError:
sys.exit("\nUnable to connect to LDAP server %s" % config.master_host_name)
# Always try to install DNS records
install_dns_records(config, options, remote_api)
finally:
if conn and conn.isconnected():
if conn.isconnected():
conn.disconnect()
if replman and replman.conn:
replman.conn.unbind()
if options.skip_schema_check:
root_logger.info("Skipping CA DS schema check")
else:
cainstance.replica_ca_install_check(config)
# Configure ntpd
if options.conf_ntp:
ipaclient.ntpconf.force_ntpd(sstore)
ntp = ntpinstance.NTPInstance()
ntp.create_instance()
# Configure dirsrv
ds = install_replica_ds(config)
# Configure the CA if necessary
CA = cainstance.install_replica_ca(config)
# Always try to install DNS records
install_dns_records(config, options)
# We need to ldap_enable the CA now that DS is up and running
if CA and config.setup_ca:

View File

@ -255,7 +255,7 @@ def dns_container_exists(fqdn, suffix, dm_password=None, ldapi=False, realm=None
return ret
def dns_zone_exists(name):
def dns_zone_exists(name, api=api):
try:
zone = api.Command.dnszone_show(unicode(name))
except ipalib.errors.NotFound:
@ -284,12 +284,12 @@ def verify_reverse_zone(zone, ip_address):
return True
def find_reverse_zone(ip_address):
def find_reverse_zone(ip_address, api=api):
ip = netaddr.IPAddress(ip_address)
zone = normalize_zone(ip.reverse_dns)
while len(zone) > 0:
if dns_zone_exists(zone):
if dns_zone_exists(zone, api):
return zone
foo, bar, zone = zone.partition('.')
@ -311,7 +311,7 @@ def read_reverse_zone(default, ip_address):
return normalize_zone(zone)
def add_zone(name, zonemgr=None, dns_backup=None, ns_hostname=None,
update_policy=None, force=False):
update_policy=None, force=False, api=api):
# always normalize zones
name = normalize_zone(name)
@ -341,7 +341,7 @@ def add_zone(name, zonemgr=None, dns_backup=None, ns_hostname=None,
except (errors.DuplicateEntry, errors.EmptyModlist):
pass
def add_rr(zone, name, type, rdata, dns_backup=None, **kwargs):
def add_rr(zone, name, type, rdata, dns_backup=None, api=api, **kwargs):
addkw = { '%srecord' % str(type.lower()) : unicode(rdata) }
addkw.update(kwargs)
try:
@ -351,16 +351,16 @@ def add_rr(zone, name, type, rdata, dns_backup=None, **kwargs):
if dns_backup:
dns_backup.add(zone, type, name, rdata)
def add_fwd_rr(zone, host, ip_address):
def add_fwd_rr(zone, host, ip_address, api=api):
addr = netaddr.IPAddress(ip_address)
if addr.version == 4:
add_rr(zone, host, "A", ip_address)
add_rr(zone, host, "A", ip_address, None, api)
elif addr.version == 6:
add_rr(zone, host, "AAAA", ip_address)
add_rr(zone, host, "AAAA", ip_address, None, api)
def add_ptr_rr(zone, ip_address, fqdn, dns_backup=None):
def add_ptr_rr(zone, ip_address, fqdn, dns_backup=None, api=api):
name = get_reverse_record_name(zone, ip_address)
add_rr(zone, name, "PTR", normalize_zone(fqdn), dns_backup)
add_rr(zone, name, "PTR", normalize_zone(fqdn), dns_backup, api)
def add_ns_rr(zone, hostname, dns_backup=None, force=True):
hostname = normalize_zone(hostname)
@ -384,7 +384,7 @@ def del_fwd_rr(zone, host, ip_address):
def del_ns_rr(zone, name, rdata):
del_rr(zone, name, 'NS', rdata)
def get_rr(zone, name, type):
def get_rr(zone, name, type, api=api):
rectype = '%srecord' % unicode(type.lower())
ret = api.Command.dnsrecord_find(unicode(zone), unicode(name))
if ret['count'] > 0:
@ -394,8 +394,8 @@ def get_rr(zone, name, type):
return []
def get_fwd_rr(zone, host):
return [x for t in ("A", "AAAA") for x in get_rr(zone, host, t)]
def get_fwd_rr(zone, host, api=api):
return [x for t in ("A", "AAAA") for x in get_rr(zone, host, t, api)]
def zonemgr_callback(option, opt_str, value, parser):
"""
@ -533,7 +533,7 @@ class DnsBackup(object):
class BindInstance(service.Service):
def __init__(self, fstore=None, dm_password=None):
def __init__(self, fstore=None, dm_password=None, api=api):
service.Service.__init__(self, "named",
service_desc="DNS",
dm_password=dm_password,
@ -550,6 +550,7 @@ class BindInstance(service.Service):
self.sub_dict = None
self.reverse_zones = []
self.dm_password = dm_password
self.api = api
self.named_regular = services.service('named-regular')
if fstore:
@ -815,9 +816,9 @@ class BindInstance(service.Service):
)
for (rname, rdata) in srv_records:
add_rr(self.domain, rname, "SRV", rdata, self.dns_backup)
add_rr(self.domain, rname, "SRV", rdata, self.dns_backup, self.api)
if not dns_zone_exists(zone):
if not dns_zone_exists(zone, self.api):
# add DNS domain for host first
root_logger.debug(
"Host domain (%s) is different from DNS domain (%s)!" % (
@ -825,15 +826,15 @@ class BindInstance(service.Service):
root_logger.debug("Add DNS zone for host first.")
add_zone(zone, self.zonemgr, dns_backup=self.dns_backup,
ns_hostname=self.fqdn, force=True)
ns_hostname=self.fqdn, force=True, api=self.api)
# Add forward and reverse records to self
for addr in addrs:
add_fwd_rr(zone, host, addr)
add_fwd_rr(zone, host, addr, self.api)
reverse_zone = find_reverse_zone(addr)
reverse_zone = find_reverse_zone(addr, self.api)
if reverse_zone:
add_ptr_rr(reverse_zone, addr, fqdn)
add_ptr_rr(reverse_zone, addr, fqdn, None, self.api)
def __add_self(self):
self.__add_master_records(self.fqdn, self.ip_addresses)
@ -863,10 +864,10 @@ class BindInstance(service.Service):
# add the CA record. So we need to find out
root_logger.debug("Check if CA is enabled for this host")
base_dn = DN(('cn', fqdn), ('cn', 'masters'), ('cn', 'ipa'),
('cn', 'etc'), api.env.basedn)
('cn', 'etc'), self.api.env.basedn)
ldap_filter = '(&(objectClass=ipaConfigObject)(cn=CA))'
try:
api.Backend.ldap2.find_entries(filter=ldap_filter, base_dn=base_dn)
self.api.Backend.ldap2.find_entries(filter=ldap_filter, base_dn=base_dn)
except ipalib.errors.NotFound:
root_logger.debug("CA is not configured")
return
@ -875,7 +876,7 @@ class BindInstance(service.Service):
try:
for addr in addrs:
add_fwd_rr(self.domain, IPA_CA_RECORD, addr)
add_fwd_rr(self.domain, IPA_CA_RECORD, addr, self.api)
except errors.ValidationError:
# there is a CNAME record in ipa-ca, we can't add A/AAAA records
pass
@ -885,7 +886,7 @@ class BindInstance(service.Service):
self.ca_configured)
if self.first_instance:
ldap = api.Backend.ldap2
ldap = self.api.Backend.ldap2
try:
entries = ldap.get_entries(
DN(('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'),
@ -902,8 +903,8 @@ class BindInstance(service.Service):
continue
host, zone = fqdn.split('.', 1)
if dns_zone_exists(zone):
addrs = get_fwd_rr(zone, host)
if dns_zone_exists(zone, self.api):
addrs = get_fwd_rr(zone, host, self.api)
else:
addrs = installutils.resolve_host(fqdn)