summaryrefslogtreecommitdiffstats
path: root/ipaserver/install/replication.py
diff options
context:
space:
mode:
Diffstat (limited to 'ipaserver/install/replication.py')
-rw-r--r--ipaserver/install/replication.py204
1 files changed, 106 insertions, 98 deletions
diff --git a/ipaserver/install/replication.py b/ipaserver/install/replication.py
index 38abfe210..8fe73ca77 100644
--- a/ipaserver/install/replication.py
+++ b/ipaserver/install/replication.py
@@ -28,17 +28,16 @@ from ipapython import services as ipaservices
from ldap import modlist
from ipalib import api, util, errors
from ipapython import ipautil
-from ipalib.dn import DN
+from ipapython.dn import DN
-DIRMAN_CN = "cn=directory manager"
CACERT = "/etc/ipa/ca.crt"
# the default container used by AD for user entries
-WIN_USER_CONTAINER = "cn=Users"
+WIN_USER_CONTAINER = DN(('cn', 'Users'))
# the default container used by IPA for user entries
-IPA_USER_CONTAINER = "cn=users,cn=accounts"
+IPA_USER_CONTAINER = DN(('cn', 'users'), ('cn', 'accounts'))
PORT = 636
TIMEOUT = 120
-REPL_MAN_DN = "cn=replication manager,cn=config"
+REPL_MAN_DN = DN(('cn', 'replication manager'), ('cn', 'config'))
IPA_REPLICA = 1
WINSYNC = 2
@@ -94,9 +93,10 @@ def enable_replication_version_checking(hostname, realm, dirman_passwd):
conn.do_simple_bind(bindpw=dirman_passwd)
else:
conn.do_sasl_gssapi_bind()
- entry = conn.search_s('cn=IPA Version Replication,cn=plugins,cn=config', ldap.SCOPE_BASE, 'objectclass=*')
- if entry[0].getValue('nsslapd-pluginenabled') == 'off':
- conn.modify_s(entry[0].dn, [(ldap.MOD_REPLACE, 'nsslapd-pluginenabled', 'on')])
+ entry = conn.getEntry(DN(('cn', 'IPA Version Replication'), ('cn', 'plugins'), ('cn', 'config')),
+ ldap.SCOPE_BASE, 'objectclass=*')
+ if entry.getValue('nsslapd-pluginenabled') == 'off':
+ conn.modify_s(entry.dn, [(ldap.MOD_REPLACE, 'nsslapd-pluginenabled', 'on')])
conn.unbind()
serverid = "-".join(realm.split("."))
ipaservices.knownservices.dirsrv.restart(instance_name=serverid)
@@ -112,8 +112,7 @@ class ReplicationManager(object):
self.dirman_passwd = dirman_passwd
self.realm = realm
self.starttls = starttls
- tmp = ipautil.realm_to_suffix(realm)
- self.suffix = str(DN(tmp)).lower()
+ self.suffix = ipautil.realm_to_suffix(realm)
self.need_memberof_fixup = False
# The caller is allowed to pass in an existing IPAdmin connection.
@@ -150,25 +149,28 @@ class ReplicationManager(object):
"""
# First see if there is already one set
dn = self.replica_dn()
+ assert isinstance(dn, DN)
try:
- replica = conn.search_s(dn, ldap.SCOPE_BASE, "objectclass=*")[0]
+ replica = conn.getEntry(dn, ldap.SCOPE_BASE, "objectclass=*")
+ except errors.NotFound:
+ pass
+ else:
if replica.getValue('nsDS5ReplicaId'):
return int(replica.getValue('nsDS5ReplicaId'))
- except ldap.NO_SUCH_OBJECT:
- pass
# Ok, either the entry doesn't exist or the attribute isn't set
# so get it from the other master
retval = -1
- dn = str(DN(('cn','replication'),('cn','etc'), self.suffix))
+ dn = DN(('cn','replication'),('cn','etc'), self.suffix)
try:
- replica = master_conn.search_s(dn, ldap.SCOPE_BASE, "objectclass=*")[0]
- if not replica.getValue('nsDS5ReplicaId'):
- root_logger.debug("Unable to retrieve nsDS5ReplicaId from remote server")
- raise RuntimeError("Unable to retrieve nsDS5ReplicaId from remote server")
- except ldap.NO_SUCH_OBJECT:
+ replica = master_conn.getEntry(dn, ldap.SCOPE_BASE, "objectclass=*")
+ except errors.NotFound:
root_logger.debug("Unable to retrieve nsDS5ReplicaId from remote server")
raise
+ else:
+ if replica.getValue('nsDS5ReplicaId') is None:
+ root_logger.debug("Unable to retrieve nsDS5ReplicaId from remote server")
+ raise RuntimeError("Unable to retrieve nsDS5ReplicaId from remote server")
# Now update the value on the master
retval = int(replica.getValue('nsDS5ReplicaId'))
@@ -195,8 +197,9 @@ class ReplicationManager(object):
"""
filt = "(|(objectclass=nsDSWindowsReplicationAgreement)(objectclass=nsds5ReplicationAgreement))"
try:
- ents = self.conn.search_s("cn=mapping tree,cn=config", ldap.SCOPE_SUBTREE, filt)
- except ldap.NO_SUCH_OBJECT:
+ ents = self.conn.getList(DN(('cn', 'mapping tree'), ('cn', 'config')),
+ ldap.SCOPE_SUBTREE, filt)
+ except errors.NotFound:
ents = []
return ents
@@ -212,13 +215,13 @@ class ReplicationManager(object):
filt = "(objectclass=nsds5ReplicationAgreement)"
try:
- ents = self.conn.search_s("cn=mapping tree,cn=config",
- ldap.SCOPE_SUBTREE, filt)
- except ldap.NO_SUCH_OBJECT:
+ ents = self.conn.getList(DN(('cn', 'mapping tree'), ('cn', 'config')),
+ ldap.SCOPE_SUBTREE, filt)
+ except errors.NotFound:
return res
for ent in ents:
- res.append(ent.nsds5replicahost)
+ res.append(ent.getValue('nsds5replicahost'))
return res
@@ -234,24 +237,23 @@ class ReplicationManager(object):
filt = "(&(|(objectclass=nsds5ReplicationAgreement)(objectclass=nsDSWindowsReplicationAgreement))(nsDS5ReplicaHost=%s))" % hostname
try:
- entry = self.conn.search_s("cn=mapping tree,cn=config",
- ldap.SCOPE_SUBTREE, filt)
- except ldap.NO_SUCH_OBJECT:
+ entries = self.conn.getList(DN(('cn', 'mapping tree'), ('cn', 'config')),
+ ldap.SCOPE_SUBTREE, filt)
+ except errors.NotFound:
return None
- if len(entry) == 0:
+ if len(entries) == 0:
return None
else:
- return entry[0] # There can be only one
+ return entries[0] # There can be only one
def add_replication_manager(self, conn, dn, pw):
"""
Create a pseudo user to use for replication.
"""
-
- edn = ldap.dn.str2dn(dn)
- rdn_attr = edn[0][0][0]
- rdn_val = edn[0][0][1]
+ assert isinstance(dn, DN)
+ rdn_attr = dn[0].attr
+ rdn_val = dn[0].value
ent = ipaldap.Entry(dn)
ent.setValues("objectclass", "top", "person")
@@ -266,6 +268,7 @@ class ReplicationManager(object):
pass
def delete_replication_manager(self, conn, dn=REPL_MAN_DN):
+ assert isinstance(dn, DN)
try:
conn.delete_s(dn)
except ldap.NO_SUCH_OBJECT:
@@ -278,16 +281,18 @@ class ReplicationManager(object):
return "2"
def replica_dn(self):
- return str(DN(('cn','replica'),('cn',self.suffix),('cn','mapping tree'),('cn','config')))
+ return DN(('cn','replica'),('cn',self.suffix),('cn','mapping tree'),('cn','config'))
def replica_config(self, conn, replica_id, replica_binddn):
+ assert isinstance(replica_binddn, DN)
dn = self.replica_dn()
+ assert isinstance(dn, DN)
try:
entry = conn.getEntry(dn, ldap.SCOPE_BASE)
managers = entry.getValues('nsDS5ReplicaBindDN')
for m in managers:
- if DN(replica_binddn) == DN(m):
+ if replica_binddn == DN(m):
return
# Add the new replication manager
mod = [(ldap.MOD_ADD, 'nsDS5ReplicaBindDN', replica_binddn)]
@@ -303,7 +308,7 @@ class ReplicationManager(object):
entry = ipaldap.Entry(dn)
entry.setValues('objectclass', "top", "nsds5replica", "extensibleobject")
entry.setValues('cn', "replica")
- entry.setValues('nsds5replicaroot', self.suffix)
+ entry.setValues('nsds5replicaroot', str(self.suffix))
entry.setValues('nsds5replicaid', str(replica_id))
entry.setValues('nsds5replicatype', replica_type)
entry.setValues('nsds5flags', "1")
@@ -313,7 +318,7 @@ class ReplicationManager(object):
conn.addEntry(entry)
def setup_changelog(self, conn):
- dn = "cn=changelog5, cn=config"
+ dn = DN(('cn', 'changelog5'), ('cn', 'config'))
dirpath = conn.dbdir + "/cldb"
entry = ipaldap.Entry(dn)
entry.setValues('objectclass', "top", "extensibleobject")
@@ -325,7 +330,7 @@ class ReplicationManager(object):
return
def setup_chaining_backend(self, conn):
- chaindn = "cn=chaining database, cn=plugins, cn=config"
+ chaindn = DN(('cn', 'chaining database'), ('cn', 'plugins'), ('cn', 'config'))
benamebase = "chaindb"
urls = [self.to_ldap_url(conn)]
cn = ""
@@ -334,11 +339,11 @@ class ReplicationManager(object):
while not done:
try:
cn = benamebase + str(benum) # e.g. localdb1
- dn = "cn=" + cn + ", " + chaindn
+ dn = DN(('cn', cn), chaindn)
entry = ipaldap.Entry(dn)
entry.setValues('objectclass', 'top', 'extensibleObject', 'nsBackendInstance')
entry.setValues('cn', cn)
- entry.setValues('nsslapd-suffix', self.suffix)
+ entry.setValues('nsslapd-suffix', str(self.suffix))
entry.setValues('nsfarmserverurl', urls)
entry.setValues('nsmultiplexorbinddn', self.repl_man_dn)
entry.setValues('nsmultiplexorcredentials', self.repl_man_passwd)
@@ -365,7 +370,7 @@ class ReplicationManager(object):
def get_mapping_tree_entry(self):
try:
- entry = self.conn.getEntry("cn=mapping tree,cn=config", ldap.SCOPE_ONELEVEL,
+ entry = self.conn.getEntry(DN(('cn', 'mapping tree'), ('cn', 'config')), ldap.SCOPE_ONELEVEL,
"(cn=\"%s\")" % (self.suffix))
except errors.NotFound, e:
root_logger.debug("failed to find mappting tree entry for %s" % self.suffix)
@@ -378,7 +383,7 @@ class ReplicationManager(object):
mtent = self.get_mapping_tree_entry()
dn = mtent.dn
- plgent = self.conn.getEntry("cn=Multimaster Replication Plugin,cn=plugins,cn=config",
+ plgent = self.conn.getEntry(DN(('cn', 'Multimaster Replication Plugin'), ('cn', 'plugins'), ('cn', 'config')),
ldap.SCOPE_BASE, "(objectclass=*)", ['nsslapd-pluginPath'])
path = plgent.getValue('nsslapd-pluginPath')
@@ -397,7 +402,7 @@ class ReplicationManager(object):
self.enable_chain_on_update(chainbe)
def add_passsync_user(self, conn, password):
- pass_dn = "uid=passsync,cn=sysaccounts,cn=etc,%s" % self.suffix
+ pass_dn = DN(('uid', 'passsync'), ('cn', 'sysaccounts'), ('cn', 'etc'), self.suffix)
print "The user for the Windows PassSync service is %s" % pass_dn
try:
conn.getEntry(pass_dn, ldap.SCOPE_BASE)
@@ -414,7 +419,7 @@ class ReplicationManager(object):
conn.addEntry(entry)
# Add it to the list of users allowed to bypass password policy
- extop_dn = "cn=ipa_pwd_extop,cn=plugins,cn=config"
+ extop_dn = DN(('cn', 'ipa_pwd_extop'), ('cn', 'plugins'), ('cn', 'config'))
entry = conn.getEntry(extop_dn, ldap.SCOPE_BASE)
pass_mgrs = entry.getValues('passSyncManagersDNs')
if not pass_mgrs:
@@ -435,9 +440,9 @@ class ReplicationManager(object):
def setup_winsync_agmt(self, entry, win_subtree=None):
if win_subtree is None:
- win_subtree = WIN_USER_CONTAINER + "," + self.ad_suffix
- ds_subtree = IPA_USER_CONTAINER + "," + self.suffix
- windomain = '.'.join(ldap.explode_dn(self.suffix, 1))
+ win_subtree = DN(WIN_USER_CONTAINER, self.ad_suffix)
+ ds_subtree = DN(IPA_USER_CONTAINER, self.suffix)
+ windomain = ipautil.suffix_to_realm(self.suffix)
entry.setValues("objectclass", "nsDSWindowsReplicationAgreement")
entry.setValues("nsds7WindowsReplicaSubtree", win_subtree)
@@ -454,7 +459,7 @@ class ReplicationManager(object):
tell which side we want.
"""
cn = "meTo%s" % (hostname)
- dn = "cn=%s, %s" % (cn, self.replica_dn())
+ dn = DN(('cn', cn), self.replica_dn())
return (cn, dn)
@@ -469,6 +474,9 @@ class ReplicationManager(object):
isn't a dogtag replication agreement.
"""
+ if repl_man_dn is not None:
+ assert isinstance(repl_man_dn, DN)
+
cn, dn = self.agreement_dn(b_hostname, master=master)
try:
a_conn.getEntry(dn, ldap.SCOPE_BASE)
@@ -482,7 +490,7 @@ class ReplicationManager(object):
entry.setValues('nsds5replicahost', b_hostname)
entry.setValues('nsds5replicaport', str(port))
entry.setValues('nsds5replicatimeout', str(TIMEOUT))
- entry.setValues('nsds5replicaroot', self.suffix)
+ entry.setValues('nsds5replicaroot', str(self.suffix))
if master is None:
entry.setValues('nsDS5ReplicatedAttributeList',
'(objectclass=*) $ EXCLUDE %s' % " ".join(EXCLUDES))
@@ -538,10 +546,15 @@ class ReplicationManager(object):
while (retries > 0 ):
root_logger.info('Getting ldap service principals for conversion: %s and %s' % (filter_a, filter_b))
- a_entry = b.search_s(self.suffix, ldap.SCOPE_SUBTREE,
- filterstr=filter_a)
- b_entry = a.search_s(self.suffix, ldap.SCOPE_SUBTREE,
- filterstr=filter_b)
+ try:
+ a_entry = b.search_s(self.suffix, ldap.SCOPE_SUBTREE, filterstr=filter_a)
+ except errors.NotFound:
+ pass
+
+ try:
+ b_entry = a.search_s(self.suffix, ldap.SCOPE_SUBTREE, filterstr=filter_b)
+ except errors.NotFound:
+ pass
if a_entry and b_entry:
root_logger.debug('Found both principals.')
@@ -578,7 +591,10 @@ class ReplicationManager(object):
"""
rep_dn = self.replica_dn()
+ assert isinstance(rep_dn, DN)
(a_dn, b_dn) = self.get_replica_principal_dns(a, b, retries=10)
+ assert isinstance(a_dn, DN)
+ assert isinstance(b_dn, DN)
# Add kerberos principal DNs as valid bindDNs for replication
try:
@@ -623,12 +639,10 @@ class ReplicationManager(object):
return self.conn.deleteEntry(dn)
def delete_referral(self, hostname):
- esc1_suffix = self.suffix.replace('=', '\\3D').replace(',', '\\2C')
- esc2_suffix = self.suffix.replace('=', '%3D').replace(',', '%2C')
- dn = 'cn=%s,cn=mapping tree,cn=config' % esc1_suffix
+ dn = DN(('cn', self.suffix), ('cn', 'mapping tree'), ('cn', 'config'))
# TODO: should we detect proto/port somehow ?
mod = [(ldap.MOD_DELETE, 'nsslapd-referral',
- 'ldap://%s/%s' % (ipautil.format_netloc(hostname, 389), esc2_suffix))]
+ 'ldap://%s/%s' % (ipautil.format_netloc(hostname, 389), self.suffix))]
try:
self.conn.modify_s(dn, mod)
@@ -648,9 +662,9 @@ class ReplicationManager(object):
print "Error reading status from agreement", agmtdn
hasError = 1
else:
- refresh = entry.nsds5BeginReplicaRefresh
- inprogress = entry.nsds5replicaUpdateInProgress
- status = entry.nsds5ReplicaLastInitStatus
+ refresh = entry.getValue('nsds5BeginReplicaRefresh')
+ inprogress = entry.getValue('nsds5replicaUpdateInProgress')
+ status = entry.getValue('nsds5ReplicaLastInitStatus')
if not refresh: # done - check status
if not status:
print "No status yet"
@@ -683,10 +697,10 @@ class ReplicationManager(object):
print "Error reading status from agreement", agmtdn
hasError = 1
else:
- inprogress = entry.nsds5replicaUpdateInProgress
- status = entry.nsds5ReplicaLastUpdateStatus
- start = entry.nsds5ReplicaLastUpdateStart
- end = entry.nsds5ReplicaLastUpdateEnd
+ inprogress = entry.getValue('nsds5replicaUpdateInProgress')
+ status = entry.getValue('nsds5ReplicaLastUpdateStatus')
+ start = entry.getValue('nsds5ReplicaLastUpdateStart')
+ end = entry.getValue('nsds5ReplicaLastUpdateEnd')
# incremental update is done if inprogress is false and end >= start
done = inprogress and inprogress.lower() == 'false' and start and end and (start <= end)
root_logger.info("Replication Update in progress: %s: status: %s: start: %s: end: %s" %
@@ -733,6 +747,7 @@ class ReplicationManager(object):
return self.wait_for_repl_init(conn, dn)
def basic_replication_setup(self, conn, replica_id, repldn, replpw):
+ assert isinstance(repldn, DN)
if replpw is not None:
self.add_replication_manager(conn, repldn, replpw)
self.replica_config(conn, replica_id, repldn)
@@ -741,6 +756,7 @@ class ReplicationManager(object):
def setup_replication(self, r_hostname, r_port=389, r_sslport=636,
r_binddn=None, r_bindpw=None, starttls=False,
is_cs_replica=False):
+ assert isinstance(r_binddn, DN)
# note - there appears to be a bug in python-ldap - it does not
# allow connections using two different CA certs
if starttls:
@@ -836,7 +852,7 @@ class ReplicationManager(object):
root_logger.info("Agreement is ready, starting replication . . .")
# Add winsync replica to the public DIT
- dn = str(DN(('cn',ad_dc_name),('cn','replicas'),('cn','ipa'),('cn','etc'), self.suffix))
+ dn = DN(('cn',ad_dc_name),('cn','replicas'),('cn','ipa'),('cn','etc'), self.suffix)
entry = ipaldap.Entry(dn)
entry.setValues("objectclass", ["nsContainer", "ipaConfigObject"])
entry.setValues("cn", ad_dc_name)
@@ -910,17 +926,17 @@ class ReplicationManager(object):
filter = '(&(nsDS5ReplicaHost=%s)' \
'(|(objectclass=nsDSWindowsReplicationAgreement)' \
'(objectclass=nsds5ReplicationAgreement)))' % hostname
- entry = conn.search_s("cn=config", ldap.SCOPE_SUBTREE, filter)
- if len(entry) == 0:
+ entries = conn.getList(DN(('cn', 'config')), ldap.SCOPE_SUBTREE, filter)
+ if len(entries) == 0:
root_logger.error("Unable to find replication agreement for %s" %
(hostname))
raise RuntimeError("Unable to proceed")
- if len(entry) > 1:
+ if len(entries) > 1:
root_logger.error("Found multiple agreements for %s" % hostname)
- root_logger.error("Using the first one only (%s)" % entry[0].dn)
+ root_logger.error("Using the first one only (%s)" % entries[0].dn)
- dn = entry[0].dn
- schedule = entry[0].nsds5replicaupdateschedule
+ dn = entries[0].dn
+ schedule = entries[0].getValue('nsds5replicaupdateschedule')
# On the remote chance of a match. We force a synch to happen right
# now by setting the schedule to something and quickly removing it.
@@ -965,16 +981,14 @@ class ReplicationManager(object):
# delete master kerberos key and all its svc principals
try:
filter='(krbprincipalname=*/%s@%s)' % (replica, realm)
- entries = self.conn.search_s(self.suffix, ldap.SCOPE_SUBTREE,
- filterstr=filter)
+ entries = self.conn.getList(self.suffix, ldap.SCOPE_SUBTREE,
+ filterstr=filter)
if len(entries) != 0:
dnset = self.conn.get_dns_sorted_by_length(entries,
reverse=True)
for dns in dnset:
for dn in dns:
self.conn.deleteEntry(dn)
- except ldap.NO_SUCH_OBJECT:
- pass
except errors.NotFound:
pass
except Exception, e:
@@ -984,18 +998,18 @@ class ReplicationManager(object):
err = e
# remove replica memberPrincipal from s4u2proxy configuration
- dn1 = DN(u'cn=ipa-http-delegation', api.env.container_s4u2proxy, self.suffix)
+ dn1 = DN(('cn', 'ipa-http-delegation'), api.env.container_s4u2proxy, self.suffix)
member_principal1 = "HTTP/%(fqdn)s@%(realm)s" % dict(fqdn=replica, realm=realm)
- dn2 = DN(u'cn=ipa-ldap-delegation-targets', api.env.container_s4u2proxy, self.suffix)
+ dn2 = DN(('cn', 'ipa-ldap-delegation-targets'), api.env.container_s4u2proxy, self.suffix)
member_principal2 = "ldap/%(fqdn)s@%(realm)s" % dict(fqdn=replica, realm=realm)
- dn3 = DN(u'cn=ipa-cifs-delegation-targets', api.env.container_s4u2proxy, self.suffix)
+ dn3 = DN(('cn', 'ipa-cifs-delegation-targets'), api.env.container_s4u2proxy, self.suffix)
member_principal3 = "cifs/%(fqdn)s@%(realm)s" % dict(fqdn=replica, realm=realm)
- for (dn, member_principal) in ((str(dn1), member_principal1),
- (str(dn2), member_principal2),
- (str(dn3), member_principal3)):
+ for (dn, member_principal) in ((dn1, member_principal1),
+ (dn2, member_principal2),
+ (dn3, member_principal3)):
try:
mod = [(ldap.MOD_DELETE, 'memberPrincipal', member_principal)]
self.conn.modify_s(dn, mod)
@@ -1010,16 +1024,14 @@ class ReplicationManager(object):
# delete master entry with all active services
try:
- dn = 'cn=%s,cn=masters,cn=ipa,cn=etc,%s' % (replica, self.suffix)
- entries = self.conn.search_s(dn, ldap.SCOPE_SUBTREE)
+ dn = DN(('cn', replica), ('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'), self.suffix)
+ entries = self.conn.getList(dn, ldap.SCOPE_SUBTREE)
if len(entries) != 0:
dnset = self.conn.get_dns_sorted_by_length(entries,
reverse=True)
for dns in dnset:
for dn in dns:
self.conn.deleteEntry(dn)
- except ldap.NO_SUCH_OBJECT:
- pass
except errors.NotFound:
pass
except Exception, e:
@@ -1029,15 +1041,13 @@ class ReplicationManager(object):
err = e
try:
- basedn = 'cn=etc,%s' % self.suffix
+ basedn = DN(('cn', 'etc'), self.suffix)
filter = '(dnaHostname=%s)' % replica
- entries = self.conn.search_s(basedn, ldap.SCOPE_SUBTREE,
- filterstr=filter)
+ entries = self.conn.getList(basedn, ldap.SCOPE_SUBTREE,
+ filterstr=filter)
if len(entries) != 0:
for e in entries:
self.conn.deleteEntry(e.dn)
- except ldap.NO_SUCH_OBJECT:
- pass
except errors.NotFound:
pass
except Exception, e:
@@ -1047,18 +1057,16 @@ class ReplicationManager(object):
err = e
try:
- dn = 'cn=default,ou=profile,%s' % self.suffix
- ret = self.conn.search_s(dn, ldap.SCOPE_BASE,
- '(objectclass=*)')[0]
- srvlist = ret.data.get('defaultServerList')
- if len(srvlist) > 0:
- srvlist = srvlist[0].split()
+ dn = DN(('cn', 'default'), ('ou', 'profile'), self.suffix)
+ ret = self.conn.getEntry(dn, ldap.SCOPE_BASE, '(objectclass=*)')
+ srvlist = ret.getValue('defaultServerList', '')
+ srvlist = srvlist[0].split()
if replica in srvlist:
srvlist.remove(replica)
attr = ' '.join(srvlist)
mod = [(ldap.MOD_REPLACE, 'defaultServerList', attr)]
self.conn.modify_s(dn, mod)
- except ldap.NO_SUCH_OBJECT:
+ except errors.NotFound:
pass
except ldap.NO_SUCH_ATTRIBUTE:
pass