From 30bd34c5226488582fb21f0a0677c887de190fa4 Mon Sep 17 00:00:00 2001 From: Rich Megginson <rmeggins@xxxxxxxxxx> Date: Wed, 20 Nov 2013 19:14:51 -0700 Subject: [PATCH 1/7] do not print ERROR message every time creating an instance --- lib389/__init__.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/lib389/__init__.py b/lib389/__init__.py index d034d07..217136c 100644 --- a/lib389/__init__.py +++ b/lib389/__init__.py @@ -244,7 +244,7 @@ class DirSrv(SimpleLDAPObject): self.simple_bind_s(self.binddn, self.bindpw) except ldap.SERVER_DOWN, e: # TODO add server info in exception - log.error("Cannot connect to %r" % uri) + log.debug("Cannot connect to %r" % uri) raise e break except ldap.CONFIDENTIALITY_REQUIRED: -- 1.7.1
From 91164f5adedb6b24066a8010511ec47110036008 Mon Sep 17 00:00:00 2001 From: Rich Megginson <rmeggins@xxxxxxxxxx> Date: Wed, 20 Nov 2013 19:15:42 -0700 Subject: [PATCH 2/7] need time and datetime - add str method for RUV to format RUV in a readable format --- lib389/_replication.py | 9 +++++++++ 1 files changed, 9 insertions(+), 0 deletions(-) diff --git a/lib389/_replication.py b/lib389/_replication.py index fc9e8cb..2eade30 100644 --- a/lib389/_replication.py +++ b/lib389/_replication.py @@ -1,3 +1,5 @@ +import time +import datetime class CSN(object): """CSN is Change Sequence Number @@ -144,6 +146,13 @@ class RUV(object): def __eq__(self, oth): return cmp(self, oth) == 0 + def __str__(self): + ret = 'generation: %s\n' % self.gen + for rid in self.rid.keys(): + ret = ret + 'rid: %s url: %s min: [%s] max: [%s]\n' % \ + (rid, self.rid[rid]['url'], self.rid[rid].get('min', ''), self. rid[rid].get('max', '')) + return ret + def getdiffs(self, oth): """Compare two ruvs and return the differences returns a tuple - the first element is the -- 1.7.1
From e6442025eadcdd7ed59c9e6eb9d68069f8293419 Mon Sep 17 00:00:00 2001 From: Rich Megginson <rmeggins@xxxxxxxxxx> Date: Wed, 20 Nov 2013 19:18:02 -0700 Subject: [PATCH 3/7] cannot modify passed in args - make a deepcopy to avoid side effects --- lib389/brooker.py | 41 +++++++++++++++++++++++------------------ 1 files changed, 23 insertions(+), 18 deletions(-) diff --git a/lib389/brooker.py b/lib389/brooker.py index fd8a8bd..fe54d01 100644 --- a/lib389/brooker.py +++ b/lib389/brooker.py @@ -300,34 +300,39 @@ class Agreement(object): }) # prepare the properties to set in the agreement - args = args or {} - if 'transport-info' not in args : + # we make a copy here because we cannot change + # the passed in args dict + argscopy = {} + if args: + import copy + argscopy = copy.deepcopy(args) + if 'transport-info' not in argscopy : if starttls: - args['transport-info'] = 'TLS' + argscopy['transport-info'] = 'TLS' elif othsslport: - args['transport-info'] = 'SSL' + argscopy['transport-info'] = 'SSL' else: - args['transport-info'] = 'LDAP' - if 'consumer-port' not in args: + argscopy['transport-info'] = 'LDAP' + if 'consumer-port' not in argscopy: if starttls: - args['consumer-port'] = str(othport) + argscopy['consumer-port'] = str(othport) elif othsslport: - args['consumer-port'] = str(othsslport) + argscopy['consumer-port'] = str(othsslport) elif othport: - args['consumer-port'] = str(othport) + argscopy['consumer-port'] = str(othport) else: - args['consumer-port'] = '389' - if 'consumer-total-init' not in args: + argscopy['consumer-port'] = '389' + if 'consumer-total-init' not in argscopy: if auto_init: - args['consumer-total-init'] = 'start' + argscopy['consumer-total-init'] = 'start' # now check and set the properties in the entry - self.checkProperties(entry, args) + self.checkProperties(entry, argscopy) # further arguments - if 'winsync' in args: # state it clearly! - self.conn.setupWinSyncAgmt(args, entry) + if 'winsync' in argscopy: # state it clearly! + self.conn.setupWinSyncAgmt(argscopy, entry) try: self.log.debug("Adding replica agreement: [%s]" % entry) @@ -339,7 +344,7 @@ class Agreement(object): entry = self.conn.waitForEntry(dn_agreement) if entry: # More verbose but shows what's going on - if 'chain' in args: + if 'chain' in argscopy: chain_args = { 'suffix': suffix, 'binddn': binddn, @@ -354,14 +359,14 @@ class Agreement(object): chain_args.update({ 'isIntermediate': 0, 'urls': self.conn.toLDAPURL(), - 'args': args['chainargs'] + 'args': argscopy['chainargs'] }) consumer.setupConsumerChainOnUpdate(**chain_args) elif replica.nsds5replicatype == HUB_TYPE: chain_args.update({ 'isIntermediate': 1, 'urls': self.conn.toLDAPURL(), - 'args': args['chainargs'] + 'args': argscopy['chainargs'] }) consumer.setupConsumerChainOnUpdate(**chain_args) -- 1.7.1
From 5765523f9fee24859aa0fc75b0492b8cbf9bf351 Mon Sep 17 00:00:00 2001 From: Rich Megginson <rmeggins@xxxxxxxxxx> Date: Wed, 20 Nov 2013 19:18:30 -0700 Subject: [PATCH 4/7] added agreement stop and restart methods --- lib389/brooker.py | 38 ++++++++++++++++++++++++++++++++++++++ 1 files changed, 38 insertions(+), 0 deletions(-) diff --git a/lib389/brooker.py b/lib389/brooker.py index fe54d01..a51a92b 100644 --- a/lib389/brooker.py +++ b/lib389/brooker.py @@ -425,6 +425,8 @@ class Agreement(object): class Replica(object): proxied_methods = 'search_s getEntry'.split() + STOP = '2358-2359 0' + START = '0000-2359 0123456' def __init__(self, conn): """@param conn - a DirSrv instance""" @@ -591,6 +593,42 @@ class Replica(object): self.log.info("Setting agreement for continuous replication") raise NotImplementedError("Check nsds5replicaupdateschedule before writing!") + def stop(self, agmtdn): + """Stop replication. + @param agmtdn - agreement dn + """ + self.log.info("Stopping replication %s" % agmtdn) + mod = [( + ldap.MOD_REPLACE, 'nsds5ReplicaEnabled', ['off'])] + try: + self.conn.modify_s(agmtdn, mod) + except LDAPError, e: + # before 1.2.11, no support for nsds5ReplicaEnabled + # use schedule hack + mod = [( + ldap.MOD_REPLACE, 'nsds5replicaupdateschedule', [ + Replica.STOP])] + self.conn.modify_s(agmtdn, mod) + + def restart(self, agmtdn, schedule=START): + """Schedules a new replication. + @param agmtdn - + @param schedule - default START + `schedule` allows to customize the replication instant. + see 389 documentation for further info + """ + self.log.info("Restarting replication %s" % agmtdn) + mod = [( + ldap.MOD_REPLACE, 'nsds5ReplicaEnabled', ['on'])] + try: + self.conn.modify_s(agmtdn, mod) + except LDAPError, e: + # before 1.2.11, no support for nsds5ReplicaEnabled + # use schedule hack + mod = [(ldap.MOD_REPLACE, 'nsds5replicaupdateschedule', [ + schedule])] + self.conn.modify_s(agmtdn, mod) + def add(self, suffix, binddn, bindpw=None, rtype=REPLICA_RDONLY_TYPE, rid=None, tombstone_purgedelay=None, purgedelay=None, referrals=None, legacy=False): -- 1.7.1
From 2bef30c7f1012f84d80cfe06020997cbe91a7ca8 Mon Sep 17 00:00:00 2001 From: Rich Megginson <rmeggins@xxxxxxxxxx> Date: Wed, 20 Nov 2013 19:19:09 -0700 Subject: [PATCH 5/7] need to set correct replica type --- lib389/brooker.py | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/lib389/brooker.py b/lib389/brooker.py index a51a92b..e067fba 100644 --- a/lib389/brooker.py +++ b/lib389/brooker.py @@ -656,6 +656,10 @@ class Replica(object): TODO: this method does not update replica type """ # set default values + if rtype == MASTER_TYPE: + rtype = REPLICA_RDWR_TYPE + else: + rtype = REPLICA_RDONLY_TYPE if legacy: legacy = 'on' -- 1.7.1
From dab3a9d3f799f6133e1dd72a6bf64c4a5b712030 Mon Sep 17 00:00:00 2001 From: Rich Megginson <rmeggins@xxxxxxxxxx> Date: Wed, 20 Nov 2013 19:19:41 -0700 Subject: [PATCH 6/7] add convenience agreement_dn method to get a single replication agreement dn --- lib389/brooker.py | 17 +++++++++++++++++ 1 files changed, 17 insertions(+), 0 deletions(-) diff --git a/lib389/brooker.py b/lib389/brooker.py index e067fba..58d4ffe 100644 --- a/lib389/brooker.py +++ b/lib389/brooker.py @@ -763,6 +763,23 @@ class Replica(object): return [ent.dn for ent in ents] return ents + def agreement_dn(self, basedn, oth): + '''get the replication agreement to the dirsrv object + specified by oth for the suffix basedn + this returns the replication agreement handle in a form suitable + for passing to agreement_changes, start_async, etc.''' + filt = '(nsds5replicahost=%s)(nsds5replicaport=%d)(nsds5replicaroot=%s)' % \ + (oth.host, oth.port, normalizeDN(basedn)) + dns = self.agreements(filt, None, True) + if not dns: + self.log.error('no agreement found for host %s port %d suffix %s', oth.host, oth.port, basedn) + return None + elif len(dns) > 1: + self.log.error('%d agreements found for host %s port %d suffix %s', len(dns), oth.host, oth.port, basedn) + return None + else: + return dns[0] + -- 1.7.1
From 5f0a6889513072284a5b0f98112d55004690acc8 Mon Sep 17 00:00:00 2001 From: Rich Megginson <rmeggins@xxxxxxxxxx> Date: Wed, 20 Nov 2013 19:20:03 -0700 Subject: [PATCH 7/7] file did not end with newline --- lib389/brooker.py | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/lib389/brooker.py b/lib389/brooker.py index 58d4ffe..da3d0c2 100644 --- a/lib389/brooker.py +++ b/lib389/brooker.py @@ -1182,4 +1182,4 @@ class Index(object): # Then delete the top index entry self.log.debug("Delete head index entry %s" % (dn)) - self.conn.delete_s(dn) \ No newline at end of file + self.conn.delete_s(dn) -- 1.7.1
-- 389-devel mailing list 389-devel@xxxxxxxxxxxxxxxxxxxxxxx https://admin.fedoraproject.org/mailman/listinfo/389-devel