Dne 3.3.2015 v 16:11 Martin Kosek napsal(a):
On 03/03/2015 04:09 PM, Jan Cholasta wrote:
Dne 3.3.2015 v 16:04 Tomas Babej napsal(a):
On 03/03/2015 04:01 PM, Martin Kosek wrote:
On 03/03/2015 03:49 PM, Jan Cholasta wrote:
Hi,
the attached patches provide an attempt to fix
<https://fedorahosted.org/freeipa/ticket/3090>.
Patch 401 serves as an example and modifies ipa-advise to use its own
API
instance for Advice plugins.
Honza
Thanks. At least patches 399 and 400 look reasonable short for 4.2.
So with these patches, could we also get rid of
temporary_ldap2_connection we
have in ipa-replica-install? Petr3 may have other examples he met in
the past...
I think we can. Shall I prepare a patch?
If it is reasonable simple, I would go for it. It would be another selling
point for your patches.
Done.
--
Jan Cholasta
>From 2d92312d314569b9d5acdfb45b1cae54421e62f9 Mon Sep 17 00:00:00 2001
From: Jan Cholasta <jchol...@redhat.com>
Date: Wed, 4 Mar 2015 09:32:44 +0000
Subject: [PATCH 4/5] ldap2: Use self API instance instead of ipalib.api
---
ipaserver/plugins/ldap2.py | 45 ++++++++++++++++++++++++++++++++-------------
1 file changed, 32 insertions(+), 13 deletions(-)
diff --git a/ipaserver/plugins/ldap2.py b/ipaserver/plugins/ldap2.py
index ec491e9..3211b33 100644
--- a/ipaserver/plugins/ldap2.py
+++ b/ipaserver/plugins/ldap2.py
@@ -63,21 +63,40 @@ class ldap2(LDAPClient, CrudBackend):
def __init__(self, shared_instance=True, ldap_uri=None, base_dn=None,
schema=None):
- try:
- ldap_uri = ldap_uri or api.env.ldap_uri
- except AttributeError:
- ldap_uri = 'ldap://example.com'
+ self.__ldap_uri = None
CrudBackend.__init__(self, shared_instance=shared_instance)
LDAPClient.__init__(self, ldap_uri)
+ self.__base_dn = base_dn
+
+ @property
+ def api(self):
+ self_api = super(ldap2, self).api
+ if self_api is None:
+ self_api = api
+ return self_api
+
+ @property
+ def ldap_uri(self):
+ try:
+ return self.__ldap_uri or self.api.env.ldap_uri
+ except AttributeError:
+ return 'ldap://example.com'
+
+ @ldap_uri.setter
+ def ldap_uri(self, value):
+ self.__ldap_uri = value
+
+ @property
+ def base_dn(self):
try:
- if base_dn is not None:
- self.base_dn = DN(base_dn)
+ if self.__base_dn is not None:
+ return DN(self.__base_dn)
else:
- self.base_dn = DN(api.env.basedn)
+ return DN(self.api.env.basedn)
except AttributeError:
- self.base_dn = DN()
+ return DN()
def _init_connection(self):
# Connectible.conn is a proxy to thread-local storage;
@@ -124,11 +143,11 @@ class ldap2(LDAPClient, CrudBackend):
_ldap.set_option(_ldap.OPT_DEBUG_LEVEL, debug_level)
with self.error_handler():
- force_updates = api.env.context in ('installer', 'updates')
+ force_updates = self.api.env.context in ('installer', 'updates')
conn = IPASimpleLDAPObject(
self.ldap_uri, force_schema_updates=force_updates)
if self.ldap_uri.startswith('ldapi://') and ccache:
- conn.set_option(_ldap.OPT_HOST_NAME, api.env.host)
+ conn.set_option(_ldap.OPT_HOST_NAME, self.api.env.host)
minssf = conn.get_option(_ldap.OPT_X_SASL_SSF_MIN)
maxssf = conn.get_option(_ldap.OPT_X_SASL_SSF_MAX)
# Always connect with at least an SSF of 56, confidentiality
@@ -297,7 +316,7 @@ class ldap2(LDAPClient, CrudBackend):
def get_ipa_config(self, attrs_list=None):
"""Returns the IPA configuration entry (dn, entry_attrs)."""
- dn = api.Object.config.get_dn()
+ dn = self.api.Object.config.get_dn()
assert isinstance(dn, DN)
try:
@@ -334,7 +353,7 @@ class ldap2(LDAPClient, CrudBackend):
"""
upg_dn = DN(('cn', 'UPG Definition'), ('cn', 'Definitions'), ('cn', 'Managed Entries'),
- ('cn', 'etc'), api.env.basedn)
+ ('cn', 'etc'), self.api.env.basedn)
try:
upg_entries = self.conn.search_s(upg_dn, _ldap.SCOPE_BASE,
@@ -359,7 +378,7 @@ class ldap2(LDAPClient, CrudBackend):
principal = getattr(context, 'principal')
entry = self.find_entry_by_attr("krbprincipalname", principal,
- "krbPrincipalAux", base_dn=api.env.basedn)
+ "krbPrincipalAux", base_dn=self.api.env.basedn)
sctrl = [GetEffectiveRightsControl(True, "dn: " + str(entry.dn))]
self.conn.set_option(_ldap.OPT_SERVER_CONTROLS, sctrl)
try:
--
2.1.0
>From 4982e5dfaab377eb438c7adda9314937a71931ca Mon Sep 17 00:00:00 2001
From: Jan Cholasta <jchol...@redhat.com>
Date: Wed, 4 Mar 2015 09:35:06 +0000
Subject: [PATCH 5/5] replica-install: Use different API instance for the
remote server
---
install/tools/ipa-replica-install | 237 +++++++++++++++++---------------------
ipaserver/install/bindinstance.py | 53 ++++-----
2 files changed, 133 insertions(+), 157 deletions(-)
diff --git a/install/tools/ipa-replica-install b/install/tools/ipa-replica-install
index 20d833d..8693129 100755
--- a/install/tools/ipa-replica-install
+++ b/install/tools/ipa-replica-install
@@ -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)
-
- 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))
+ 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))
+
+ # 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
- 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)
-
- # 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)
+ # 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.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 conn and conn.isconnected():
- conn.disconnect()
- if replman and replman.conn:
- replman.conn.unbind()
+ cainstance.replica_ca_install_check(config)
- 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 ntpd
- if options.conf_ntp:
- ipaclient.ntpconf.force_ntpd(sstore)
- ntp = ntpinstance.NTPInstance()
- ntp.create_instance()
+ # Configure dirsrv
+ ds = install_replica_ds(config)
- # Configure dirsrv
- ds = install_replica_ds(config)
+ # Configure the CA if necessary
+ CA = cainstance.install_replica_ca(config)
- # Configure the CA if necessary
- CA = cainstance.install_replica_ca(config)
-
- # Always try to install DNS records
- install_dns_records(config, options)
+ # Always try to install DNS records
+ install_dns_records(config, options, remote_api)
+ finally:
+ if conn.isconnected():
+ conn.disconnect()
# We need to ldap_enable the CA now that DS is up and running
if CA and config.setup_ca:
diff --git a/ipaserver/install/bindinstance.py b/ipaserver/install/bindinstance.py
index d487666..52aea74 100644
--- a/ipaserver/install/bindinstance.py
+++ b/ipaserver/install/bindinstance.py
@@ -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)
--
2.1.0
_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel