summaryrefslogtreecommitdiffstats
path: root/daemons/ipa-slapi-plugins/topology/topology_util.c
diff options
context:
space:
mode:
Diffstat (limited to 'daemons/ipa-slapi-plugins/topology/topology_util.c')
-rw-r--r--daemons/ipa-slapi-plugins/topology/topology_util.c159
1 files changed, 132 insertions, 27 deletions
diff --git a/daemons/ipa-slapi-plugins/topology/topology_util.c b/daemons/ipa-slapi-plugins/topology/topology_util.c
index cd97827b1..9851df059 100644
--- a/daemons/ipa-slapi-plugins/topology/topology_util.c
+++ b/daemons/ipa-slapi-plugins/topology/topology_util.c
@@ -319,20 +319,38 @@ ipa_topo_util_agmt_from_entry(Slapi_Entry *entry, char *replRoot, char *fromHost
}
return agmt;
}
+
+int
+ipa_topo_util_segm_dir(char *direction)
+{
+ int dir = -1;
+ if (strcasecmp(direction,SEGMENT_DIR_BOTH) == 0){
+ dir = SEGMENT_BIDIRECTIONAL;
+ } else if (strcasecmp(direction,SEGMENT_DIR_LEFT_ORIGIN) == 0) {
+ dir = SEGMENT_LEFT_RIGHT;
+ } else if (strcasecmp(direction,SEGMENT_DIR_RIGHT_ORIGIN) == 0) {
+ dir = SEGMENT_RIGHT_LEFT;
+ }
+ return dir;
+}
+
TopoReplicaSegment *
ipa_topo_util_find_segment(TopoReplica *conf, Slapi_Entry *entry)
{
char *leftHost;
char *rightHost;
+ char *direction;
TopoReplicaSegment *segment = NULL;
leftHost = slapi_entry_attr_get_charptr(entry,"ipaReplTopoSegmentLeftNode");
rightHost = slapi_entry_attr_get_charptr(entry,"ipaReplTopoSegmentRightNode");
+ direction = slapi_entry_attr_get_charptr(entry,"ipaReplTopoSegmentDirection");
- segment = ipa_topo_cfg_segment_find(conf->repl_root, leftHost, rightHost);
+ segment = ipa_topo_cfg_segment_find(conf->repl_root, leftHost, rightHost, ipa_topo_util_segm_dir(direction));
slapi_ch_free((void **)&leftHost);
slapi_ch_free((void **)&rightHost);
+ slapi_ch_free((void **)&direction);
return segment;
}
@@ -450,13 +468,63 @@ ipa_topo_util_conf_from_entry(Slapi_Entry *entry)
}
}
+void
+ipa_topo_util_set_agmt_rdn(TopoReplicaAgmt *topo_agmt, Slapi_Entry *repl_agmt)
+{
+ const Slapi_DN *agmt_dn = slapi_entry_get_sdn_const(repl_agmt);
+ Slapi_RDN *agmt_rdn = slapi_rdn_new();
+ slapi_sdn_get_rdn(agmt_dn, agmt_rdn);
+ const char *agmt_rdn_str = slapi_rdn_get_rdn(agmt_rdn);
+ if (strcasecmp(agmt_rdn_str, topo_agmt->rdn)) {
+ slapi_ch_free_string(&topo_agmt->rdn);
+ topo_agmt->rdn = slapi_ch_strdup(agmt_rdn_str);
+ }
+ slapi_rdn_free(&agmt_rdn);
+}
+
+int
+ipa_topo_util_update_agmt_rdn(TopoReplica *conf, TopoReplicaAgmt *agmt,
+ char *toHost)
+{
+ int rc = 0;
+ Slapi_PBlock *pb = NULL;
+ Slapi_Entry **entries = NULL;
+ char *filter;
+
+ pb = slapi_pblock_new();
+ filter = slapi_ch_smprintf("(&(objectclass=nsds5replicationagreement)"
+ "(nsds5replicaroot=%s)(nsds5replicahost=%s))",
+ conf->repl_root, toHost);
+ slapi_search_internal_set_pb(pb, "cn=config", LDAP_SCOPE_SUB,
+ filter, NULL, 0, NULL, NULL,
+ ipa_topo_get_plugin_id(), 0);
+ slapi_search_internal_pb(pb);
+ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &rc);
+ if (rc == 0) {
+ slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
+ }
+
+ if (NULL == entries || NULL == entries[0]) {
+ slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
+ "ipa_topo_util_update_agmt_rdn: "
+ "no agreements found\n");
+ } else {
+ ipa_topo_util_set_agmt_rdn(agmt, entries[0]);
+ }
+
+ slapi_free_search_results_internal(pb);
+ slapi_ch_free_string(&filter);
+ slapi_pblock_destroy(pb);
+ return rc;
+}
+
int
ipa_topo_util_update_agmt_list(TopoReplica *conf, TopoReplicaSegmentList *repl_segments)
{
int rc = 0;
int i;
int nentries;
- Slapi_Entry **entries;
+ Slapi_Entry **entries = NULL;
Slapi_Entry *repl_agmt;
Slapi_PBlock *pb = NULL;
char *filter;
@@ -482,7 +550,7 @@ ipa_topo_util_update_agmt_list(TopoReplica *conf, TopoReplicaSegmentList *repl_s
if (NULL == entries || NULL == entries[0]) {
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
"ipa_topo_util_update_agmts_list: "
- "no agrements found\n");
+ "no agreements found\n");
goto update_only;
}
}
@@ -511,15 +579,7 @@ ipa_topo_util_update_agmt_list(TopoReplica *conf, TopoReplicaSegmentList *repl_s
targetHost);
if (topo_agmt) {
/* compare rdns, use rdn of existing agreement */
- const Slapi_DN *agmt_dn = slapi_entry_get_sdn_const(repl_agmt);
- Slapi_RDN *agmt_rdn = slapi_rdn_new();
- slapi_sdn_get_rdn(agmt_dn, agmt_rdn);
- const char *agmt_rdn_str = slapi_rdn_get_rdn(agmt_rdn);
- if (strcasecmp(agmt_rdn_str, topo_agmt->rdn)) {
- slapi_ch_free_string(&topo_agmt->rdn);
- topo_agmt->rdn = slapi_ch_strdup(agmt_rdn_str);
- }
- slapi_rdn_free(&agmt_rdn);
+ ipa_topo_util_set_agmt_rdn(topo_agmt, repl_agmt);
/* update agreement params which are different in the segment*/
char *segm_attr_val;
@@ -742,10 +802,29 @@ ipa_topo_util_segment_update(TopoReplica *repl_conf,
case LDAP_MOD_REPLACE:
if (0 == strcasecmp(mods[i]->mod_type,"ipaReplTopoSegmentDirection")) {
if (0 == strcasecmp(mods[i]->mod_bvalues[0]->bv_val,"both")) {
+ TopoReplicaSegment *ex_segm;
if (segment->direct == SEGMENT_LEFT_RIGHT) {
- segment->right = ipa_topo_cfg_agmt_dup_reverse(segment->left);
+ ex_segm = ipa_topo_cfg_replica_segment_find(repl_conf, segment->from, segment->to,
+ SEGMENT_RIGHT_LEFT, 1);
+ if (ex_segm) {
+ segment->right = ipa_topo_cfg_agmt_dup(ex_segm->left?ex_segm->left:ex_segm->right);
+ } else {
+ segment->right = ipa_topo_cfg_agmt_dup_reverse(segment->left);
+ if(0 == strcasecmp(fromHost,segment->right->origin)) {
+ ipa_topo_util_update_agmt_rdn(repl_conf, segment->right, segment->right->target);
+ }
+ }
} else if (segment->direct == SEGMENT_RIGHT_LEFT) {
- segment->left = ipa_topo_cfg_agmt_dup_reverse(segment->right);
+ ex_segm = ipa_topo_cfg_replica_segment_find(repl_conf, segment->from, segment->to,
+ SEGMENT_LEFT_RIGHT, 1);
+ if (ex_segm) {
+ segment->left = ipa_topo_cfg_agmt_dup(ex_segm->left?ex_segm->left:ex_segm->right);
+ } else {
+ segment->left = ipa_topo_cfg_agmt_dup_reverse(segment->right);
+ if(0 == strcasecmp(fromHost,segment->left->origin)) {
+ ipa_topo_util_update_agmt_rdn(repl_conf, segment->left, segment->left->target);
+ }
+ }
}
segment->direct = SEGMENT_BIDIRECTIONAL;
} else {
@@ -983,6 +1062,32 @@ ipa_topo_util_segm_order(TopoReplicaSegment *l, TopoReplicaSegment *r)
}
void
+ipa_topo_util_segment_do_merge(TopoReplica *tconf,
+ TopoReplicaSegment *ex_segm, TopoReplicaSegment *tsegm)
+{
+ /* we are merging two one directional segments, tehy can have been created in
+ * several ways and we need to find the agreeemnt to copy
+ */
+ if (NULL == tsegm->right) {
+ if(ex_segm->left) {
+ tsegm->right = ipa_topo_cfg_agmt_dup(ex_segm->left);
+ } else {
+ tsegm->right = ipa_topo_cfg_agmt_dup(ex_segm->right);
+ }
+ } else {
+ if(ex_segm->left) {
+ tsegm->left = ipa_topo_cfg_agmt_dup(ex_segm->left);
+ } else {
+ tsegm->left = ipa_topo_cfg_agmt_dup(ex_segm->right);
+ }
+ }
+ ipa_topo_util_segm_update(tconf,ex_segm, SEGMENT_OBSOLETE);
+ ipa_topo_util_segm_remove(tconf, ex_segm);
+ ipa_topo_util_segm_update(tconf,tsegm, SEGMENT_BIDIRECTIONAL);
+}
+
+
+void
ipa_topo_util_segment_merge(TopoReplica *tconf,
TopoReplicaSegment *tsegm)
{
@@ -996,7 +1101,13 @@ ipa_topo_util_segment_merge(TopoReplica *tconf,
return;
}
- ex_segm = ipa_topo_cfg_replica_segment_find(tconf, tsegm->to, tsegm->from, 1 /*lock*/);
+ if (tsegm->direct == SEGMENT_LEFT_RIGHT) {
+ ex_segm = ipa_topo_cfg_replica_segment_find(tconf, tsegm->from, tsegm->to,
+ SEGMENT_RIGHT_LEFT, 1 /*lock*/);
+ } else {
+ ex_segm = ipa_topo_cfg_replica_segment_find(tconf, tsegm->from, tsegm->to,
+ SEGMENT_LEFT_RIGHT, 1 /*lock*/);
+ }
if (ex_segm == NULL) return;
/* to avoid conflicts merging has to be done only once and
@@ -1005,17 +1116,11 @@ ipa_topo_util_segment_merge(TopoReplica *tconf,
*/
if (ipa_topo_util_segm_order(ex_segm, tsegm) > 0) {
if (0 == strcasecmp(tsegm->from,ipa_topo_get_plugin_hostname())) {
- tsegm->right = ipa_topo_cfg_agmt_dup(ex_segm->left);
- ipa_topo_util_segm_update(tconf,ex_segm, SEGMENT_OBSOLETE);
- ipa_topo_util_segm_remove(tconf, ex_segm);
- ipa_topo_util_segm_update(tconf,tsegm, SEGMENT_BIDIRECTIONAL);
+ ipa_topo_util_segment_do_merge(tconf, ex_segm, tsegm);
}
} else {
if (0 == strcasecmp(ex_segm->from,ipa_topo_get_plugin_hostname())) {
- ex_segm->right = ipa_topo_cfg_agmt_dup(tsegm->left);
- ipa_topo_util_segm_update(tconf,tsegm, SEGMENT_OBSOLETE);
- ipa_topo_util_segm_remove(tconf, tsegm);
- ipa_topo_util_segm_update(tconf,ex_segm, SEGMENT_BIDIRECTIONAL);
+ ipa_topo_util_segment_do_merge(tconf, tsegm, ex_segm);
}
}
@@ -1221,8 +1326,8 @@ ipa_topo_util_delete_segments_for_host(char *repl_root, char *delhost)
int check_reverse = 1;
/* first check if a segment originating at localhost exists */
- segm = ipa_topo_cfg_segment_find(repl_root,
- ipa_topo_get_plugin_hostname(), delhost);
+ segm = ipa_topo_cfg_segment_find(repl_root, ipa_topo_get_plugin_hostname(),
+ delhost, SEGMENT_LEFT_RIGHT);
if (segm) {
/* mark segment as removable, bypass connectivity check when replicated */
if (segm->direct == SEGMENT_BIDIRECTIONAL) check_reverse = 0;
@@ -1233,8 +1338,8 @@ ipa_topo_util_delete_segments_for_host(char *repl_root, char *delhost)
}
/* check if one directional segment in reverse direction exists */
if (check_reverse) {
- segm = ipa_topo_cfg_segment_find(repl_root,
- delhost, ipa_topo_get_plugin_hostname());
+ segm = ipa_topo_cfg_segment_find(repl_root, delhost,
+ ipa_topo_get_plugin_hostname(), SEGMENT_LEFT_RIGHT);
if (segm) {
ipa_topo_util_segm_update(tconf,segm, SEGMENT_REMOVED);
/* mark and delete, no repl agmt on this server */