int ipa_topo_check_topology_disconnect(Slapi_PBlock *pb) { int rc = 1; Slapi_Entry *del_entry; struct node_fanout *fanout = NULL; char *pi; /* we have to check if the operation is triggered by the * topology plugin itself - allow it */ slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY,&pi); if (pi && 0 == strcasecmp(pi, ipa_topo_get_plugin_id())) { return 0; } slapi_pblock_get(pb,SLAPI_DELETE_EXISTING_ENTRY,&del_entry); if (TOPO_SEGMENT_ENTRY != ipa_topo_check_entry_type(del_entry)) { return 0; } else { TopoReplica *tconf = ipa_topo_util_get_conf_for_segment(del_entry); if (tconf == NULL) { slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM, "topology not configured for segment\n"); rc = 0; /* this segment is not controlled by the plugin */ goto done; } TopoReplicaSegment *tsegm = NULL; tsegm = ipa_topo_util_find_segment(tconf, del_entry); if (tsegm == NULL) { slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM, "segment to be deleted does not exist\n"); goto done; } if (!ipa_topo_util_segment_is_managed(tconf,tsegm)) { /* not both endpoints are managed servers, delete is ok */ rc = 0; goto done; } /* check if removal of segment would break connectivity */ fanout = ipa_topo_connection_fanout(tconf, tsegm); if (fanout == NULL) goto done; if (ipa_topo_connection_exists(fanout, tsegm->from, tsegm->to) && ipa_topo_connection_exists(fanout, tsegm->to, tsegm->from)) { rc = 0; } ipa_topo_connection_fanout_free(fanout); } done: return rc; }
int ipa_topo_check_host_updates(Slapi_PBlock *pb) { int rc = 0; Slapi_Entry *mod_entry; char *pi; /* we have to check if the operation is triggered by the * topology plugin itself - allow it */ slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY,&pi); if (pi && 0 == strcasecmp(pi, ipa_topo_get_plugin_id())) { return 0; } slapi_pblock_get(pb,SLAPI_MODIFY_EXISTING_ENTRY,&mod_entry); if (TOPO_HOST_ENTRY == ipa_topo_check_entry_type(mod_entry) && (ipa_topo_is_invalid_managed_suffix(pb))) { rc = 1; } return rc; }
int ipa_topo_check_entry_move(Slapi_PBlock *pb) { int rc = 0; int entry_type = TOPO_IGNORE_ENTRY; Slapi_Entry *modrdn_entry; slapi_pblock_get(pb,SLAPI_MODRDN_TARGET_ENTRY,&modrdn_entry); entry_type = ipa_topo_check_entry_type(modrdn_entry); switch (entry_type) { case TOPO_SEGMENT_ENTRY: case TOPO_CONFIG_ENTRY: { Slapi_DN *newsuperior = NULL; slapi_pblock_get(pb, SLAPI_MODRDN_NEWSUPERIOR_SDN, &newsuperior); if (newsuperior && slapi_sdn_get_dn(newsuperior)) rc = 1; break; } default: rc = 0; break; } return rc; }
int ipa_topo_check_segment_is_valid(Slapi_PBlock *pb, char **errtxt) { int rc = 0; Slapi_Entry *add_entry; char *pi; /* we have to check if the operation is triggered by the * topology plugin itself - allow it */ slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY,&pi); if (pi && 0 == strcasecmp(pi, ipa_topo_get_plugin_id())) { return 0; } slapi_pblock_get(pb,SLAPI_ADD_ENTRY,&add_entry); if (TOPO_SEGMENT_ENTRY != ipa_topo_check_entry_type(add_entry)) { return 0; } else { /* a new segment is added * verify that the segment does not yet exist */ char *leftnode = slapi_entry_attr_get_charptr(add_entry,"ipaReplTopoSegmentLeftNode"); char *rightnode = slapi_entry_attr_get_charptr(add_entry,"ipaReplTopoSegmentRightNode"); char *dir = slapi_entry_attr_get_charptr(add_entry,"ipaReplTopoSegmentDirection"); if (leftnode == NULL || rightnode == NULL || dir == NULL) { *errtxt = slapi_ch_smprintf("Segment definition is incomplete" ". Add rejected.\n"); rc = 1; } else if (strcasecmp(dir,SEGMENT_DIR_BOTH) && strcasecmp(dir,SEGMENT_DIR_LEFT_ORIGIN) && strcasecmp(dir,SEGMENT_DIR_RIGHT_ORIGIN)) { *errtxt = slapi_ch_smprintf("Segment has unsupported direction" ". Add rejected.\n"); slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM, "segment has unknown direction: %s\n", dir); rc = 1; } else if (0 == strcasecmp(leftnode,rightnode)) { *errtxt = slapi_ch_smprintf("Segment is self referential" ". Add rejected.\n"); slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM, "segment is self referential\n"); rc = 1; } else { TopoReplicaSegment *tsegm = NULL; TopoReplica *tconf = ipa_topo_util_get_conf_for_segment(add_entry); if (tconf == NULL ) { *errtxt = slapi_ch_smprintf("Segment configuration suffix not found" ". Add rejected.\n"); slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM, "topology not configured for segment\n"); rc = 1; } else { tsegm = ipa_topo_util_find_segment(tconf, add_entry); } if (tsegm) { *errtxt = slapi_ch_smprintf("Segment already exists in topology" ". Add rejected.\n"); slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM, "segment to be added does already exist\n"); rc = 1; } } slapi_ch_free_string(&leftnode); slapi_ch_free_string(&rightnode); slapi_ch_free_string(&dir); } return rc; }
int ipa_topo_post_add(Slapi_PBlock *pb) { int result = SLAPI_PLUGIN_SUCCESS; int entry_type; Slapi_Entry *add_entry = NULL; slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM, "--> ipa_topo_post_add\n"); /* 1. get entry */ slapi_pblock_get(pb,SLAPI_ENTRY_POST_OP,&add_entry); if (add_entry == NULL) { slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM, "no entry\n"); return 1; } /* 2. check if it is in scope and type * and if plugin is active */ entry_type = ipa_topo_check_entry_type(add_entry); if (0 == ipa_topo_get_plugin_active() && entry_type != TOPO_DOMLEVEL_ENTRY) { slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM, "<-- ipa_topo_post_add - plugin not active\n"); return 0; } switch (entry_type) { case TOPO_CONFIG_ENTRY: /* initialize the shared topology data for a replica */ break; case TOPO_SEGMENT_ENTRY: { TopoReplicaSegment *tsegm; TopoReplica *tconf = ipa_topo_util_get_conf_for_segment(add_entry); char *status; /* TBD check that one node is the current server and * that the other node is also managed by the * shared config. * If all checks pass create the replication agreement */ tsegm = ipa_topo_util_segment_from_entry(tconf, add_entry); status = slapi_entry_attr_get_charptr(add_entry, "ipaReplTopoSegmentStatus"); if (status == NULL || strcasecmp(status,"autogen")) { ipa_topo_util_missing_agmts_add(tconf, tsegm, ipa_topo_get_plugin_hostname()); } /* keep the new segment in tconf data */ ipa_topo_cfg_segment_add(tconf, tsegm); /* TBD: do we know if the replica already has been initialized ? * should the agreement be enabled ? * For now assume everything is ok and enable */ /* check if it is unidirectional and if other direction exists */ ipa_topo_util_segment_merge(tconf, tsegm); slapi_ch_free_string(&status); break; } case TOPO_HOST_ENTRY: { /* add to list of managed hosts */ ipa_topo_cfg_host_add(add_entry); /* we are adding a new master, there could be * a segment which so far was inactive since * the host was not managed */ ipa_topo_util_update_segments_for_host(add_entry); break; } case TOPO_DOMLEVEL_ENTRY: { /* the domain level entry was just added * check and set the level, if plugin gets activated * do initialization. */ char *domlevel = slapi_entry_attr_get_charptr(add_entry, "ipaDomainLevel"); ipa_topo_set_domain_level(domlevel); ipa_topo_util_check_plugin_active(); if (ipa_topo_get_plugin_active()) { ipa_topo_util_start(0); } slapi_ch_free_string(&domlevel); break; } case TOPO_IGNORE_ENTRY: break; } slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM, "<-- ipa_topo_post_add\n"); return result; }
int ipa_topo_post_del(Slapi_PBlock *pb) { int result = SLAPI_PLUGIN_SUCCESS; int entry_type; Slapi_Entry *del_entry = NULL; slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM, "--> ipa_topo_post_del\n"); /* 1. get entry */ slapi_pblock_get(pb,SLAPI_ENTRY_PRE_OP,&del_entry); if (del_entry == NULL) { slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM, "no entry\n"); return 1; } /* 2. check if it is in scope */ entry_type = ipa_topo_check_entry_type(del_entry); if (0 == ipa_topo_get_plugin_active() && entry_type != TOPO_DOMLEVEL_ENTRY) { slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM, "<-- ipa_topo_post_del - plugin not active\n"); return 0; } switch (entry_type) { case TOPO_CONFIG_ENTRY: break; case TOPO_SEGMENT_ENTRY: { /* check if corresponding agreement exists and delete */ TopoReplica *tconf = ipa_topo_util_get_conf_for_segment(del_entry); TopoReplicaSegment *tsegm; char *status; tsegm = ipa_topo_util_find_segment(tconf, del_entry); if (tsegm == NULL) { slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM, "segment to be deleted does not exist\n"); break; } status = slapi_entry_attr_get_charptr(del_entry, "ipaReplTopoSegmentStatus"); if (status == NULL || strcasecmp(status, SEGMENT_OBSOLETE_STR)) { /* obsoleted segments are a result of merge, do not remove repl agmt */ ipa_topo_util_existing_agmts_del(tconf, tsegm, ipa_topo_get_plugin_hostname()); } /* also remove segment from local topo conf */ ipa_topo_cfg_segment_del(tconf, tsegm); slapi_ch_free_string(&status); break; } case TOPO_DOMLEVEL_ENTRY: { /* the domain level entry was just deleted * this should not happen, but it is identical * to setting domlevel to 0 * log an error and inactivate plugin */ slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM, "postop_del: domainlevel entry deleted - " "plugin will be inactivated \n"); break; } case TOPO_HOST_ENTRY: /* deleting an host entry means that the host becomes * unmanaged, probably because a replica is removed. * remove all marked replication agreements connecting * this host. */ ipa_topo_util_delete_host(del_entry); ipa_topo_cfg_host_del(del_entry); break; case TOPO_IGNORE_ENTRY: break; } slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM, "<-- ipa_topo_post_del\n"); return result; }
int ipa_topo_post_mod(Slapi_PBlock *pb) { int result = SLAPI_PLUGIN_SUCCESS; int entry_type; Slapi_Entry *mod_entry = NULL; slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM, "--> ipa_topo_post_mod\n"); /* 1. get entry */ slapi_pblock_get(pb,SLAPI_ENTRY_POST_OP,&mod_entry); if (mod_entry == NULL) { slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM, "no entry\n"); return (1); } /* 2. check if it is in scope */ entry_type = ipa_topo_check_entry_type(mod_entry); if (0 == ipa_topo_get_plugin_active() && entry_type != TOPO_DOMLEVEL_ENTRY) { slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM, "<-- ipa_topo_post_mod - plugin not active\n"); return 0; } switch (entry_type) { case TOPO_CONFIG_ENTRY: break; case TOPO_SEGMENT_ENTRY: { LDAPMod **mods; TopoReplica *tconf = ipa_topo_util_get_conf_for_segment(mod_entry); TopoReplicaSegment *tsegm; tsegm = ipa_topo_util_find_segment(tconf, mod_entry); if (tsegm == NULL) { slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM, "ipa_topo_post_mod - segment to be modified does not exist\n"); break; } slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods); ipa_topo_util_segment_update(tconf, tsegm, mods,ipa_topo_get_plugin_hostname()); ipa_topo_util_existing_agmts_update(tconf, tsegm, mods, ipa_topo_get_plugin_hostname()); /* also update local segment in tconf */ break; } case TOPO_DOMLEVEL_ENTRY: { /* the domain level entry was just modified * check and set the level, if plugin gets activated * do initialization. */ char *domlevel = slapi_entry_attr_get_charptr(mod_entry, "ipaDomainLevel"); int already_active = ipa_topo_get_plugin_active(); ipa_topo_set_domain_level(domlevel); ipa_topo_util_check_plugin_active(); if (!already_active && ipa_topo_get_plugin_active()) { ipa_topo_util_start(0); } slapi_ch_free_string(&domlevel); break; } case TOPO_HOST_ENTRY: case TOPO_IGNORE_ENTRY: break; } slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM, "<-- ipa_topo_post_mod\n"); return result; }