#include "topology.h" char *ipa_topo_plugin_hostname; char *ipa_topo_plugin_shared_config_base; int ipa_topo_plugin_activated; static Slapi_PluginDesc pdesc = { PLUGIN_NAME, PLUGIN_VENDOR, PLUGIN_VERSION, IPA_TOPO_PLUGIN_SUBSYSTEM }; static int ipa_topo_start(Slapi_PBlock * pb); static int ipa_topo_close(Slapi_PBlock * pb); static int ipa_topo_preop_init(Slapi_PBlock *pb); static int ipa_topo_postop_init(Slapi_PBlock *pb); static int ipa_topo_internal_postop_init(Slapi_PBlock *pb); static int ipa_topo_apply_shared_replica_config(char *replica_root); static int ipa_topo_rootdse_init(Slapi_PBlock *pb); static int ipa_topo_rootdse_search(Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* entryAfter, int *returncode, char *returntext, void *arg); void ipa_topo_be_state_change(void *handle, char *be_name, int old_be_state, int new_be_state); int ipa_topo_init(Slapi_PBlock *pb) { int rc = 0; void *ipa_topo_plugin_identity = NULL; slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM, "--> ipa_topo_init\n"); /** * Store the plugin identity for later use. * Used for internal operations */ slapi_pblock_get(pb, SLAPI_PLUGIN_IDENTITY, &ipa_topo_plugin_identity); ipa_topo_set_plugin_id(ipa_topo_plugin_identity); if (slapi_pblock_set(pb, SLAPI_PLUGIN_VERSION, SLAPI_PLUGIN_VERSION_01) != 0 || slapi_pblock_set(pb, SLAPI_PLUGIN_START_FN, (void *)ipa_topo_start) != 0 || slapi_pblock_set(pb, SLAPI_PLUGIN_CLOSE_FN, (void *)ipa_topo_close) != 0 || slapi_pblock_set(pb, SLAPI_PLUGIN_DESCRIPTION, (void *) &pdesc) != 0) { slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM, "ipa_topo_init: failed to register plugin\n"); rc = 1; } if (rc == 0) { char *plugin_type = "bepreoperation"; if (slapi_register_plugin(plugin_type, 1, "ipa_topo_init", ipa_topo_preop_init, IPA_TOPO_PREOP_DESC, NULL, ipa_topo_get_plugin_id())) { slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM, "ipa_topo_init: failed to register preop plugin\n"); rc = 1; } } if (rc == 0) { char *plugin_type = "postoperation"; if (slapi_register_plugin(plugin_type, 1, "ipa_topo_init", ipa_topo_postop_init, IPA_TOPO_POSTOP_DESC, NULL, ipa_topo_get_plugin_id())) { slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM, "ipa_topo_init: failed to register postop plugin\n"); rc = 1; } } if (rc == 0) { char *plugin_type = "internalpostoperation"; if (slapi_register_plugin(plugin_type, 1, "ipa_topo_internal_init", ipa_topo_internal_postop_init, IPA_TOPO_INTERNAL_POSTOP_DESC, NULL, ipa_topo_get_plugin_id())) { slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM, "ipa_topo_init: failed to register internal postop plugin\n"); rc = 1; } } slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM, "<-- ipa_topo_init\n"); return(rc); } static int ipa_topo_preop_init(Slapi_PBlock *pb) { int rc; rc = slapi_pblock_set(pb, SLAPI_PLUGIN_BE_PRE_MODIFY_FN, (void *)ipa_topo_pre_mod); rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_BE_PRE_ADD_FN, (void *)ipa_topo_pre_add); rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_BE_PRE_DELETE_FN, (void *)ipa_topo_pre_del); return(rc); } static int ipa_topo_postop_init(Slapi_PBlock *pb) { int rc; rc = slapi_pblock_set(pb, SLAPI_PLUGIN_POST_ADD_FN, (void *)ipa_topo_post_add); rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_POST_DELETE_FN, (void *)ipa_topo_post_del); rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_POST_MODIFY_FN, (void *)ipa_topo_post_mod); return(rc); } static int ipa_topo_internal_postop_init(Slapi_PBlock *pb) { int rc; rc = slapi_pblock_set(pb, SLAPI_PLUGIN_INTERNAL_POST_ADD_FN, (void *)ipa_topo_post_add); rc |= slapi_pblock_set(pb, SLAPI_PLUGIN_INTERNAL_POST_DELETE_FN, (void *)ipa_topo_post_del); return(rc); } int ipa_topo_setup_managed_servers(void) { int rc = 0; /* initially only read the entries below cn=masters * and build the list of hostnames */ rc = ipa_topo_util_setup_servers(); return rc; } void ipa_topo_queue_apply_shared_config(time_t event_time, void *arg) { ipa_topo_apply_shared_config(); } int ipa_topo_apply_shared_config(void) { int i = 0; int rc = 0; char **shared_replica_root = NULL; while (0 == ipa_topo_acquire_startup_inprogress()) { DS_Sleep(1); } shared_replica_root = ipa_topo_get_plugin_replica_root(); while (rc == 0 && shared_replica_root[i]) { rc = ipa_topo_apply_shared_replica_config(shared_replica_root[i]); i++; } /* initialize the list of managed servers */ rc = ipa_topo_setup_managed_servers(); ipa_topo_release_startup_inprogress(); return (rc); } static int ipa_topo_apply_shared_replica_config(char *replica_root) { TopoReplica *replica_config = NULL; TopoReplicaSegmentList *replica_segments = NULL; int rc = 0; /* step 1. get replica onfig entry from shared tree * search replica entry for replcia root below shared config base */ replica_config = ipa_topo_util_get_replica_conf(replica_root); if (replica_config) { /* step 2. get all segments for the replica from the shared config */ replica_segments = ipa_topo_util_get_replica_segments(replica_config); /* step 3. get all replication agreements for replica root */ rc = ipa_topo_util_update_agmt_list(replica_config, replica_segments); } return (rc); } static int ipa_topo_start(Slapi_PBlock * pb) { int rc = 0; slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM, "--> ipa_topo_start\n"); /* expose info about the plugin via rootdse */ rc = ipa_topo_rootdse_init(pb); /* register callback to handle state changes of backends, * required to check changes in domain level after online initialization */ slapi_register_backend_state_change((void *)ipa_topo_be_state_change, ipa_topo_be_state_change); /* init plugin config data from the plugin entry in cn=config */ rc = ipa_topo_init_plugin_config(pb); if (rc != 0) { slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM, "unable to get configuration\n"); return (rc); } if (0 == ipa_topo_get_plugin_active()) { slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM, "plugin not activated, waiting for increase of domain level\n"); return rc; } rc = ipa_topo_util_start(1); slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM, "<-- ipa_topo_start\n"); return (rc); } static int ipa_topo_close(Slapi_PBlock * pb) { ipa_topo_set_plugin_active(0); slapi_config_remove_callback(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP, "", LDAP_SCOPE_BASE, "(objectclass=*)", ipa_topo_rootdse_search); slapi_unregister_backend_state_change((void *)ipa_topo_be_state_change); ipa_topo_free_plugin_config(); return 0; } static int ipa_topo_rootdse_init(Slapi_PBlock *pb) { int rc = SLAPI_PLUGIN_FAILURE; if (slapi_config_register_callback_plugin(SLAPI_OPERATION_SEARCH, DSE_FLAG_PREOP | DSE_FLAG_PLUGIN, "", LDAP_SCOPE_BASE, "(objectclass=*)", ipa_topo_rootdse_search, NULL, pb)) { rc = SLAPI_PLUGIN_SUCCESS; } return rc; } static int ipa_topo_rootdse_search(Slapi_PBlock *pb, Slapi_Entry* e, Slapi_Entry* entryAfter, int *returncode, char *returntext, void *arg) { char *version = slapi_ch_smprintf("%d.%d", ipa_topo_get_plugin_version_major(), ipa_topo_get_plugin_version_minor()); slapi_entry_attr_set_charptr(e, "ipaTopologyPluginVersion", version); if (ipa_topo_get_plugin_active()) { slapi_entry_attr_set_charptr(e, "ipaTopologyIsManaged", "on"); } else { slapi_entry_attr_set_charptr(e, "ipaTopologyIsManaged", "off"); } /* we expose temporarily the domain level in this function, should * finally be handled in a plugin managing the domain level */ char *level = slapi_ch_smprintf("%d", ipa_topo_get_domain_level_major()); slapi_entry_attr_set_charptr(e, "ipaDomainLevel", level); slapi_ch_free_string(&version); slapi_ch_free_string(&level); return SLAPI_DSE_CALLBACK_OK; } void ipa_topo_be_state_change(void *handle, char *be_name, int old_be_state, int new_be_state) { Slapi_Backend *be=NULL; const char *be_suffix; /* check if different backends require different actions */ be = slapi_be_select_by_instance_name(be_name); be_suffix = slapi_sdn_get_dn(slapi_be_getsuffix(be, 0)); if (0 == ipa_topo_cfg_plugin_suffix_is_managed(be_suffix)) { /* nothing to do */ return; } if (new_be_state == SLAPI_BE_STATE_ON) { /* backend came back online - check change in domain level */ slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM, "ipa_topo_be_state_change - " "backend %s is coming online; " "checking domain level and init shared topology\n", be_name); ipa_topo_util_set_domain_level(); ipa_topo_util_check_plugin_active(); if (ipa_topo_get_plugin_active()) { ipa_topo_util_start(1); } } else if (new_be_state == SLAPI_BE_STATE_OFFLINE) { /* backend is about to be taken down - inactivate plugin */ slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM, "ipa_topo_be_state_change" "backend %s is going offline; inactivate plugin\n", be_name); } else if (new_be_state == SLAPI_BE_STATE_DELETE) { /* backend is about to be removed - disable replication */ if (old_be_state == SLAPI_BE_STATE_ON) { slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM, "ipa_topo_be_state_change" "backend %s is about to be deleted; inactivate plugin\n", be_name); } } }