summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRob Crittenden <rcritten@redhat.com>2008-10-29 13:37:15 -0400
committerRob Crittenden <rcritten@redhat.com>2008-10-29 17:09:48 -0400
commitb7f338f2c939c3c145bb440b4d469097c795699c (patch)
treee506e8036ed649ff40382f968d358f55113a6deb
parenta05f57f528c733f687eaf27d0cbd9b182867b24a (diff)
downloadfreeipa-b7f338f2c939c3c145bb440b4d469097c795699c.tar.gz
freeipa-b7f338f2c939c3c145bb440b4d469097c795699c.tar.xz
freeipa-b7f338f2c939c3c145bb440b4d469097c795699c.zip
Ensure that every replica gets a unique replication ID. Otherwise changes won't propogate between all replicas.
468732
-rw-r--r--ipa-server/ipa-install/ipa-replica-install3
-rw-r--r--ipa-server/ipa-install/updates/replication.update9
-rw-r--r--ipa-server/ipaserver/replication.py48
3 files changed, 57 insertions, 3 deletions
diff --git a/ipa-server/ipa-install/ipa-replica-install b/ipa-server/ipa-install/ipa-replica-install
index 0b6727e22..ce598853c 100644
--- a/ipa-server/ipa-install/ipa-replica-install
+++ b/ipa-server/ipa-install/ipa-replica-install
@@ -249,7 +249,8 @@ def main():
try:
repl = replication.ReplicationManager(config.host_name, config.dirman_password)
ret = repl.setup_replication(config.master_host_name, config.realm_name)
- except:
+ except Exception, e:
+ logging.debug("Connection error: %s" % e)
raise RuntimeError("Unable to connect to LDAP server %s." % config.host_name)
if ret != 0:
raise RuntimeError("Failed to start replication")
diff --git a/ipa-server/ipa-install/updates/replication.update b/ipa-server/ipa-install/updates/replication.update
new file mode 100644
index 000000000..29823a6fa
--- /dev/null
+++ b/ipa-server/ipa-install/updates/replication.update
@@ -0,0 +1,9 @@
+#
+# Counter used to store the next replica id
+#
+# Start at 3 to avoid conflicts with v1.0 replica ids. The value itself
+# isn't important but each replica needs a unique id.
+dn: cn=replication,cn=etc,$SUFFIX
+add: objectclass: nsDS5Replica
+add: nsDS5ReplicaId: 3
+add: nsDS5ReplicaRoot: '$SUFFIX'
diff --git a/ipa-server/ipaserver/replication.py b/ipa-server/ipaserver/replication.py
index 8fdbed19c..75dd416b1 100644
--- a/ipa-server/ipaserver/replication.py
+++ b/ipa-server/ipaserver/replication.py
@@ -49,6 +49,47 @@ class ReplicationManager:
self.repl_man_cn = "replication manager"
self.suffix = ""
+ def _get_replica_id(self, conn, master_conn):
+ """
+ Returns the replica ID which is unique for each backend.
+
+ conn is the connection we are trying to get the replica ID for.
+ master_conn is the master we are going to replicate with.
+ """
+ # First see if there is already one set
+ dn = self.replica_dn()
+ try:
+ replica = conn.search_s(dn, ldap.SCOPE_BASE, "objectclass=*")[0]
+ 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 = "cn=replication, cn=etc, %s" % self.suffix
+ try:
+ replica = master_conn.search_s(dn, ldap.SCOPE_BASE, "objectclass=*")[0]
+ if not replica.getValue('nsDS5ReplicaId'):
+ logging.debug("Unable to retrieve nsDS5ReplicaId from remote server")
+ raise RuntimeError("Unable to retrieve nsDS5ReplicaId from remote server")
+ except ldap.NO_SUCH_OBJECT:
+ logging.debug("Unable to retrieve nsDS5ReplicaId from remote server")
+ raise
+
+ # Now update the value on the master
+ retval = int(replica.getValue('nsDS5ReplicaId'))
+ mod = [(ldap.MOD_REPLACE, 'nsDS5ReplicaId', str(retval + 1))]
+
+ try:
+ master_conn.modify_s(dn, mod)
+ except Exception, e:
+ logging.debug("Problem updating nsDS5ReplicaID %s" % e)
+ raise
+
+ return retval
+
def find_replication_dns(self, conn):
filt = "(|(objectclass=nsDSWindowsReplicationAgreement)(objectclass=nsds5ReplicationAgreement))"
try:
@@ -347,11 +388,14 @@ class ReplicationManager:
self.suffix = ipaldap.IPAdmin.normalizeDN(dsinstance.realm_to_suffix(realm_name))
- self.basic_replication_setup(self.conn, 1)
+ local_id = self._get_replica_id(self.conn, other_conn)
+ self.basic_replication_setup(self.conn, local_id)
if not iswinsync:
- self.basic_replication_setup(other_conn, 2)
+ other_id = self._get_replica_id(other_conn, other_conn)
+ self.basic_replication_setup(other_conn, other_id)
self.setup_agreement(other_conn, self.conn)
+ self.setup_agreement(self.conn, other_conn)
return self.start_replication(other_conn)
else:
self.setup_agreement(self.conn, other_conn, **kargs)