mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
ds plugin - manage replication topology in the shared tree
Implementation of ticket: https://fedorahosted.org/freeipa/ticket/4302 Design page: http://www.freeipa.org/page/V4/Manage_replication_topology Reviewed-By: Thierry Bordaz <tbordaz@redhat.com>
This commit is contained in:
parent
c5f319d3e8
commit
25bf0c6e78
@ -362,6 +362,7 @@ AC_CONFIG_FILES([
|
||||
ipa-slapi-plugins/ipa-modrdn/Makefile
|
||||
ipa-slapi-plugins/ipa-sidgen/Makefile
|
||||
ipa-slapi-plugins/ipa-range-check/Makefile
|
||||
ipa-slapi-plugins/topology/Makefile
|
||||
])
|
||||
|
||||
AC_OUTPUT
|
||||
|
@ -16,6 +16,7 @@ SUBDIRS = \
|
||||
ipa-winsync \
|
||||
ipa-sidgen \
|
||||
ipa-range-check \
|
||||
topology \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_DIST = \
|
||||
|
51
daemons/ipa-slapi-plugins/topology/Makefile.am
Normal file
51
daemons/ipa-slapi-plugins/topology/Makefile.am
Normal file
@ -0,0 +1,51 @@
|
||||
NULL =
|
||||
|
||||
PLUGIN_COMMON_DIR=../common
|
||||
|
||||
AM_CPPFLAGS = \
|
||||
-I. \
|
||||
-I$(srcdir) \
|
||||
-I$(PLUGIN_COMMON_DIR) \
|
||||
-I/usr/include/dirsrv \
|
||||
-DPREFIX=\""$(prefix)"\" \
|
||||
-DBINDIR=\""$(bindir)"\" \
|
||||
-DLIBDIR=\""$(libdir)"\" \
|
||||
-DLIBEXECDIR=\""$(libexecdir)"\" \
|
||||
-DDATADIR=\""$(datadir)"\" \
|
||||
$(LDAP_CFLAGS) \
|
||||
$(WARN_CFLAGS) \
|
||||
$(NULL)
|
||||
|
||||
plugindir = $(libdir)/dirsrv/plugins
|
||||
plugin_LTLIBRARIES = \
|
||||
libtopology.la \
|
||||
$(NULL)
|
||||
|
||||
libtopology_la_SOURCES = \
|
||||
topology_agmt.c \
|
||||
topology_init.c \
|
||||
topology_cfg.c \
|
||||
topology_post.c \
|
||||
topology_pre.c \
|
||||
topology_util.c \
|
||||
$(NULL)
|
||||
|
||||
libtopology_la_LDFLAGS = -avoid-version
|
||||
|
||||
#libtopology_la_LIBADD = \
|
||||
# $(LDAP_LIBS) \
|
||||
# $(NULL)
|
||||
|
||||
appdir = $(IPA_DATA_DIR)
|
||||
app_DATA = \
|
||||
ipa-topology-conf.ldif \
|
||||
$(NULL)
|
||||
|
||||
EXTRA_DIST = \
|
||||
README \
|
||||
$(app_DATA) \
|
||||
$(NULL)
|
||||
|
||||
MAINTAINERCLEANFILES = \
|
||||
*~ \
|
||||
Makefile.in
|
20
daemons/ipa-slapi-plugins/topology/ipa-topology-conf.ldif
Executable file
20
daemons/ipa-slapi-plugins/topology/ipa-topology-conf.ldif
Executable file
@ -0,0 +1,20 @@
|
||||
dn: cn=IPA Topology Configuration,cn=plugins,cn=config
|
||||
changetype: add
|
||||
objectClass: top
|
||||
objectClass: nsSlapdPlugin
|
||||
objectClass: extensibleObject
|
||||
cn: IPA Topology Configuration
|
||||
nsslapd-pluginPath: libtopology
|
||||
nsslapd-pluginInitfunc: ipa_topo_init
|
||||
nsslapd-pluginType: object
|
||||
nsslapd-pluginEnabled: on
|
||||
nsslapd-topo-plugin-shared-config-base: cn=ipa,cn=etc,$SUFFIX
|
||||
nsslapd-topo-plugin-shared-replica-root: $SUFFIX
|
||||
nsslapd-topo-plugin-shared-binddngroup: cn=replication managers,cn=etc,$SUFFIX
|
||||
nsslapd-topo-plugin-startup-delay: 20
|
||||
nsslapd-pluginId: none
|
||||
nsslapd-plugin-depends-on-named: ldbm database
|
||||
nsslapd-plugin-depends-on-named: Multimaster Replication Plugin
|
||||
nsslapd-pluginVersion: 1.0
|
||||
nsslapd-pluginVendor: none
|
||||
nsslapd-pluginDescription: none
|
302
daemons/ipa-slapi-plugins/topology/topology.h
Normal file
302
daemons/ipa-slapi-plugins/topology/topology.h
Normal file
@ -0,0 +1,302 @@
|
||||
|
||||
/**
|
||||
* IPA Replication Topology Plugin
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include "slapi-plugin.h"
|
||||
|
||||
#define PLUGIN_NAME "ipa-topology-plugin"
|
||||
#define PLUGIN_VENDOR "freeipa"
|
||||
#define PLUGIN_VERSION "1.0"
|
||||
|
||||
#define IPA_TOPO_PLUGIN_SUBSYSTEM "ipa-topology-plugin"
|
||||
#define IPA_TOPO_PREOP_DESC "ipa-topology-preop-subplugin"
|
||||
#define IPA_TOPO_POSTOP_DESC "ipa-topology-postop-subplugin"
|
||||
#define IPA_TOPO_INTERNAL_POSTOP_DESC "ipa-topology-internal-postop-subplugin"
|
||||
|
||||
#define AGMT_TIMEOUT "300"
|
||||
#define REPL_MAN_DN "cn=replman,cn=config"
|
||||
#define REPL_MAN_PASSWD "replman"
|
||||
#define REPL_ATTR_LIST "(objectclass=*) $ EXCLUDE memberof idnssoaserial " \
|
||||
"entryusn krblastsuccessfulauth krblastfailedauth "\
|
||||
"krbloginfailedcount"
|
||||
#define REPL_ATTR_STRIP "modifiersName modifyTimestamp internalModifiersName "\
|
||||
"internalModifyTimestamp"
|
||||
#define REPL_ATTR_LIST_TOTAL "(objectclass=*) $ EXCLUDE entryusn "\
|
||||
"krblastsuccessfulauth krblastfailedauth "\
|
||||
"krbloginfailedcount"
|
||||
|
||||
#define SEGMENT_DIR_BOTH "both"
|
||||
#define SEGMENT_DIR_LEFT_ORIGIN "left-right"
|
||||
#define SEGMENT_DIR_RIGHT_ORIGIN "right-left"
|
||||
#define SEGMENT_LEFT_RIGHT 0x01
|
||||
#define SEGMENT_RIGHT_LEFT 0x02
|
||||
#define SEGMENT_BIDIRECTIONAL 0x03
|
||||
#define SEGMENT_OBSOLETE 0x04
|
||||
#define SEGMENT_AUTOGEN 0x05
|
||||
#define SEGMENT_REMOVED 0x06
|
||||
#define SEGMENT_OBSOLETE_STR "obsolete"
|
||||
#define SEGMENT_AUTOGEN_STR "autogen"
|
||||
#define SEGMENT_REMOVED_STR "removed"
|
||||
#define TOPO_IGNORE_ENTRY 0
|
||||
#define TOPO_CONFIG_ENTRY 1
|
||||
#define TOPO_SEGMENT_ENTRY 2
|
||||
#define TOPO_HOST_ENTRY 3
|
||||
#define TOPO_DOMLEVEL_ENTRY 4
|
||||
|
||||
typedef struct topo_replica_agmt {
|
||||
char *rdn;
|
||||
char *origin; /* supplier side of agmt */
|
||||
char *target; /* consumer side of agmt */
|
||||
char *enabled;
|
||||
char *repl_root;
|
||||
char *strip_attrs;
|
||||
char *total_attrs;
|
||||
char *repl_attrs;
|
||||
char *repl_pause;
|
||||
char *repl_timeout;
|
||||
char *repl_refresh;
|
||||
char *repl_transport;
|
||||
char *repl_bind_dn;
|
||||
char *repl_bind_cred;
|
||||
char *repl_bind_method;
|
||||
} TopoReplicaAgmt;
|
||||
|
||||
typedef struct topo_replica_segment {
|
||||
char *name;
|
||||
int direct;
|
||||
char *from;
|
||||
char *to;
|
||||
int state;
|
||||
TopoReplicaAgmt *left;
|
||||
TopoReplicaAgmt *right;
|
||||
} TopoReplicaSegment;
|
||||
|
||||
typedef struct topo_replica_segment_list {
|
||||
struct topo_replica_segment_list *next;
|
||||
TopoReplicaSegment *segm;
|
||||
int visited;
|
||||
} TopoReplicaSegmentList;
|
||||
|
||||
typedef struct topo_replica_host {
|
||||
struct topo_replica_host *next;
|
||||
char *hostname;
|
||||
} TopoReplicaHost;
|
||||
|
||||
typedef struct topo_replica {
|
||||
struct topo_replica *next;
|
||||
Slapi_Mutex *repl_lock;
|
||||
char *shared_config_base;
|
||||
Slapi_DN *shared_config_sdn;
|
||||
char *repl_root;
|
||||
TopoReplicaSegmentList *repl_segments;
|
||||
TopoReplicaHost *hosts;
|
||||
} TopoReplica;
|
||||
|
||||
typedef struct topo_replica_conf {
|
||||
Slapi_Mutex *conf_lock;
|
||||
int startup_inprogress;
|
||||
TopoReplica *replicas;
|
||||
TopoReplicaHost *allhosts; /* maybe not needed */
|
||||
} TopoReplicaConf;
|
||||
|
||||
typedef struct topo_plugin_config {
|
||||
Slapi_Mutex *plg_lock;
|
||||
void *identity;
|
||||
int version_major;
|
||||
int version_minor;
|
||||
int startup_delay;
|
||||
char *hostname;
|
||||
char *shared_config_base;
|
||||
char *shared_topo;
|
||||
Slapi_DN *shared_topo_sdn;
|
||||
char *shared_hosts;
|
||||
Slapi_DN *shared_hosts_sdn;
|
||||
char *shared_bindgroup;
|
||||
Slapi_DN *shared_bindgroup_sdn;
|
||||
char *domain_level;
|
||||
Slapi_DN *domain_level_sdn;
|
||||
char **shared_replica_root;
|
||||
char **managed_attrs;
|
||||
char **restricted_attrs;
|
||||
int activated;
|
||||
} TopoPluginConf;
|
||||
|
||||
typedef struct ipa_domain_level {
|
||||
int major;
|
||||
int minor;
|
||||
} IpaDomainLevel;
|
||||
|
||||
#define CONFIG_ATTR_SHARED_BASE "nsslapd-topo-plugin-shared-config-base"
|
||||
#define CONFIG_ATTR_REPLICA_ROOT "nsslapd-topo-plugin-shared-replica-root"
|
||||
#define CONFIG_ATTR_SHARED_BINDDNGROUP "nsslapd-topo-plugin-shared-binddngroup"
|
||||
#define CONFIG_ATTR_STARTUP_DELAY "nsslapd-topo-plugin-startup-delay"
|
||||
#define CONFIG_ATTR_PLUGIN_ACTIVE "nsslapd-topo-plugin-activated"
|
||||
#define CONFIG_ATTR_PLUGIN_VERSION "nsslapd-pluginVersion"
|
||||
|
||||
/* functions to manage config and global variables */
|
||||
int ipa_topo_init_plugin_config(Slapi_PBlock *pb);
|
||||
void ipa_topo_init_shared_config(void);
|
||||
int ipa_topo_init_config(Slapi_PBlock *pb);
|
||||
void *ipa_topo_get_plugin_id(void);
|
||||
int ipa_topo_get_plugin_active(void);
|
||||
char *ipa_topo_get_plugin_shared_config(void);
|
||||
Slapi_DN *ipa_topo_get_plugin_shared_topo_dn(void);
|
||||
Slapi_DN *ipa_topo_get_plugin_shared_hosts_dn(void);
|
||||
Slapi_DN *ipa_topo_get_plugin_shared_bindgroup_dn(void);
|
||||
char *ipa_topo_get_plugin_shared_topo(void);
|
||||
char *ipa_topo_get_plugin_shared_hosts(void);
|
||||
char *ipa_topo_get_plugin_shared_bindgroup(void);
|
||||
char *ipa_topo_get_plugin_hostname(void);
|
||||
char **ipa_topo_get_plugin_replica_root(void);
|
||||
char **ipa_topo_get_plugin_managed_attrs(void);
|
||||
char **ipa_topo_get_plugin_restricted_attrs(void);
|
||||
int ipa_topo_get_plugin_version_major(void);
|
||||
int ipa_topo_get_plugin_version_minor(void);
|
||||
char *ipa_topo_get_domain_level_entry(void);
|
||||
Slapi_DN *ipa_topo_get_domain_level_entry_dn(void);
|
||||
int ipa_topo_get_domain_level_major(void);
|
||||
int ipa_topo_get_domain_level_minor(void);
|
||||
int ipa_topo_get_plugin_startup_delay(void);
|
||||
void ipa_topo_set_plugin_id(void *plg_id);
|
||||
void ipa_topo_set_plugin_active(int state);
|
||||
void ipa_topo_set_plugin_shared_config(char *);
|
||||
void ipa_topo_set_plugin_hostname(char *hostname);
|
||||
void ipa_topo_set_plugin_replica_root(char **roots);
|
||||
void ipa_topo_set_plugin_managed_attrs(char **mattrs);
|
||||
void ipa_topo_set_plugin_restricted_attrs(char **mattrs);
|
||||
void ipa_topo_set_plugin_startup_delay(char *delay);
|
||||
void ipa_topo_set_plugin_version(char *version);
|
||||
int ipa_topo_cfg_plugin_suffix_is_managed(const char *be_suffix);
|
||||
void ipa_topo_free_plugin_config(void);
|
||||
void ipa_topo_set_domain_level(char *level);
|
||||
void ipa_topo_util_check_plugin_active(void);
|
||||
void ipa_topo_lock_conf(void);
|
||||
void ipa_topo_unlock_conf(void);
|
||||
int ipa_topo_acquire_startup_inprogress(void);
|
||||
void ipa_topo_release_startup_inprogress(void);
|
||||
void ipa_topo_cfg_host_add(Slapi_Entry *hostentry);
|
||||
void ipa_topo_cfg_host_del(Slapi_Entry *hostentry);
|
||||
TopoReplicaHost *ipa_topo_cfg_host_find(TopoReplica *tconf, char *host, int lock);
|
||||
TopoReplicaHost *ipa_topo_cfg_host_new(char *newhost);
|
||||
TopoReplicaSegment *
|
||||
ipa_topo_cfg_segment_find(char *repl_root, char *leftHost, char *rightHost);
|
||||
TopoReplicaSegment *
|
||||
ipa_topo_cfg_replica_segment_find(TopoReplica *tconf, char *leftHost,
|
||||
char *rightHost, int lock);
|
||||
void ipa_topo_cfg_segment_set_visited(TopoReplica *tconf, TopoReplicaSegment *tsegm);
|
||||
void ipa_topo_cfg_segment_add(TopoReplica *tconf, TopoReplicaSegment *tsegm);
|
||||
void ipa_topo_cfg_segment_del(TopoReplica *tconf, TopoReplicaSegment *tsegm);
|
||||
void ipa_topo_cfg_segment_free(TopoReplicaSegment *tsegm);
|
||||
TopoReplicaSegment *ipa_topo_cfg_segment_dup(TopoReplicaSegment *orig);
|
||||
TopoReplicaAgmt *ipa_topo_cfg_agmt_dup(TopoReplicaAgmt *agmt);
|
||||
TopoReplicaAgmt *ipa_topo_cfg_agmt_dup_reverse(TopoReplicaAgmt *agmt);
|
||||
TopoReplica *ipa_topo_cfg_replica_new(void);
|
||||
int ipa_topo_cfg_replica_add(TopoReplica *tconf);
|
||||
void ipa_topo_cfg_replica_del(TopoReplica *tconf);
|
||||
void ipa_topo_cfg_replica_free(TopoReplica *tconf);
|
||||
TopoReplica *ipa_topo_cfg_replica_find(char *repl_root, int lock);
|
||||
|
||||
/* pre and postop plugin functions */
|
||||
int ipa_topo_check_entry_type(Slapi_Entry *entry);
|
||||
/* postop plugin functions */
|
||||
int ipa_topo_post_add(Slapi_PBlock *pb);
|
||||
int ipa_topo_post_mod(Slapi_PBlock *pb);
|
||||
int ipa_topo_post_del(Slapi_PBlock *pb);
|
||||
|
||||
/* preop plugin functions */
|
||||
int ipa_topo_pre_add(Slapi_PBlock *pb);
|
||||
int ipa_topo_pre_mod(Slapi_PBlock *pb);
|
||||
int ipa_topo_pre_del(Slapi_PBlock *pb);
|
||||
|
||||
/* functions to modify agreements */
|
||||
int ipa_topo_agmt_new(char *hostname, TopoReplica *repl_conf,
|
||||
TopoReplicaAgmt *agmt);
|
||||
int ipa_topo_agmt_del_dn(char *dn);
|
||||
int ipa_topo_agmt_del(char *hostname, TopoReplica *conf,
|
||||
TopoReplicaAgmt *agmt);
|
||||
int ipa_topo_agmt_mod(TopoReplica *conf, TopoReplicaAgmt *agmt,
|
||||
LDAPMod **mod, char *direction);
|
||||
int ipa_topo_agmt_setup(char *hostname, TopoReplica *repl_conf,
|
||||
TopoReplicaAgmt *agmt, int isgssapi);
|
||||
int ipa_topo_setup_std_agmt(char *hostname, TopoReplica *repl_conf,
|
||||
TopoReplicaAgmt *agmt);
|
||||
int ipa_topo_setup_gssapi_agmt(char *hostname, TopoReplica *repl_conf,
|
||||
TopoReplicaAgmt *agmt);
|
||||
void ipa_topo_queue_apply_shared_config(time_t event_time, void *arg);
|
||||
int ipa_topo_apply_shared_config(void);
|
||||
int ipa_topo_setup_managed_servers(void);
|
||||
int ipa_topo_util_start(int delay);
|
||||
int ipa_topo_util_update_agmt_list(TopoReplica *repl_conf,
|
||||
TopoReplicaSegmentList *repl_segments);
|
||||
char *ipa_topo_agmt_gen_rdn(char *from, char *to);
|
||||
char *ipa_topo_agmt_std_rdn(char *to);
|
||||
char *ipa_topo_agreement_dn(TopoReplica *conf, TopoReplicaAgmt *agmt, char *rdn);
|
||||
char *ipa_topo_segment_dn(TopoReplica *tconf, char *segname);
|
||||
void ipa_topo_util_segment_update(TopoReplica *repl_conf,
|
||||
TopoReplicaSegment *repl_segment,
|
||||
LDAPMod **mods ,char *fromHost);
|
||||
void ipa_topo_util_missing_agmts_add(TopoReplica *repl_conf,
|
||||
TopoReplicaSegment *repl_segment,
|
||||
char *fromHost);
|
||||
void ipa_topo_util_existing_agmts_del(TopoReplica *repl_conf,
|
||||
TopoReplicaSegment *repl_segment,
|
||||
char *fromHost);
|
||||
void ipa_topo_util_existing_agmts_update(TopoReplica *repl_conf,
|
||||
TopoReplicaSegment *repl_segment,
|
||||
LDAPMod **mods ,char *fromHost);
|
||||
void ipa_topo_util_missing_agmts_add_list(TopoReplica *repl_conf,
|
||||
TopoReplicaSegmentList *repl_segments,
|
||||
char *fromHost);
|
||||
void ipa_topo_util_existing_agmts_del_list(TopoReplica *repl_conf,
|
||||
TopoReplicaSegmentList *repl_segments,
|
||||
char *fromHost);
|
||||
void ipa_topo_util_existing_agmts_update_list(TopoReplica *repl_conf,
|
||||
TopoReplicaSegmentList *repl_segments,
|
||||
LDAPMod **mods ,char *fromHost);
|
||||
TopoReplicaAgmt *ipa_topo_util_agmt_from_entry(Slapi_Entry *entry,
|
||||
char* replRoot, char *fromHost,
|
||||
char *toHost, char *direction);
|
||||
TopoReplicaAgmt *
|
||||
ipa_topo_util_find_segment_agmt(TopoReplicaSegmentList *repl_segments,
|
||||
char *fromHost, char *toHost);
|
||||
void ipa_topo_util_segm_update(TopoReplica *tconf, TopoReplicaSegment *tsegm,
|
||||
int property);
|
||||
int ipa_topo_util_segment_write(TopoReplica *tconf, TopoReplicaSegment *tsegm);
|
||||
void ipa_topo_util_segm_remove(TopoReplica *tconf, TopoReplicaSegment *tsegm);
|
||||
void ipa_topo_util_segment_merge(TopoReplica *tconf,
|
||||
TopoReplicaSegment *tsegm);
|
||||
int ipa_topo_util_agmt_mark(TopoReplica *tconf, Slapi_Entry * repl_agmt,
|
||||
TopoReplicaSegment *tsegm);
|
||||
int ipa_topo_util_agmt_is_marked(Slapi_Entry * repl_agmt);
|
||||
char *ipa_topo_agmt_attr_is_managed(char *type, char *direction);
|
||||
int ipa_topo_cfg_attr_is_restricted(char *type);
|
||||
int ipa_topo_util_setup_servers(void);
|
||||
void ipa_topo_util_update_segments_for_host(Slapi_Entry *hostentry);
|
||||
char *ipa_topo_util_get_ldap_principal(char *repl_root, char *hostname);
|
||||
void ipa_topo_util_disable_repl_for_principal(char *repl_root, char *principal);
|
||||
void ipa_topo_util_delete_host(Slapi_Entry *hostentry);
|
||||
void ipa_topo_util_disable_repl_from_host(char *repl_root, char *delhost);
|
||||
void ipa_topo_util_delete_segments_for_host(char *repl_root, char *delhost);
|
||||
|
||||
int ipa_topo_util_entry_is_candidate(Slapi_Entry *e);
|
||||
int ipa_topo_util_target_is_managed(Slapi_Entry *e);
|
||||
char * ipa_topo_util_get_segm_attr(TopoReplicaAgmt *agmt, char *attr_type);
|
||||
void ipa_topo_util_set_segm_attr(TopoReplicaAgmt *agmt, char *attr_type,
|
||||
char *attr_val);
|
||||
TopoReplicaSegment *ipa_topo_util_segm_from_agmt(Slapi_Entry *repl_agmt);
|
||||
TopoReplicaSegment *ipa_topo_util_segment_from_entry(TopoReplica *conf,
|
||||
Slapi_Entry *entry);
|
||||
TopoReplicaSegment *ipa_topo_util_find_segment(TopoReplica *conf,
|
||||
Slapi_Entry *entry);
|
||||
TopoReplica *ipa_topo_util_conf_from_entry(Slapi_Entry *entry);
|
||||
TopoReplica *ipa_topo_util_get_conf_for_segment(Slapi_Entry *segment_entry);
|
||||
Slapi_Entry *ipa_topo_util_get_entry(char *dn);
|
||||
int ipa_topo_util_modify(Slapi_DN *entrySDN, Slapi_Mods *smods);
|
||||
char *ipa_topo_util_get_pluginhost(void);
|
||||
TopoReplica *ipa_topo_util_get_replica_conf(char *repl_root);
|
||||
TopoReplicaSegmentList *ipa_topo_util_get_replica_segments(TopoReplica *replica);
|
||||
void ipa_topo_util_set_domain_level(void);
|
314
daemons/ipa-slapi-plugins/topology/topology_agmt.c
Normal file
314
daemons/ipa-slapi-plugins/topology/topology_agmt.c
Normal file
@ -0,0 +1,314 @@
|
||||
#include "topology.h"
|
||||
|
||||
/* generate the dn for a topology segment by providing replroot and segment name */
|
||||
char *
|
||||
ipa_topo_segment_dn(TopoReplica *tconf, char *segname)
|
||||
{
|
||||
char *dn = NULL;
|
||||
|
||||
dn = slapi_ch_smprintf("cn=%s,%s", segname, tconf->shared_config_base);
|
||||
return dn;
|
||||
}
|
||||
|
||||
/* generate the rdn for a replication agreement by providing connected nodes */
|
||||
char *
|
||||
ipa_topo_agmt_gen_rdn(char *from, char *to)
|
||||
{
|
||||
char *agmt_rdn = slapi_ch_smprintf("cn=%s-to-%s", from, to);
|
||||
|
||||
return agmt_rdn;
|
||||
}
|
||||
|
||||
/* generate the rdn for a replication agreement by providing target node */
|
||||
char *
|
||||
ipa_topo_agmt_std_rdn(char *to)
|
||||
{
|
||||
char *agmt_rdn = slapi_ch_smprintf("cn=meTo%s", to);
|
||||
|
||||
return agmt_rdn;
|
||||
}
|
||||
|
||||
/* generate the dn for a replication agreement by providing replroot and host */
|
||||
char *
|
||||
ipa_topo_agreement_dn(TopoReplica *conf, TopoReplicaAgmt *agmt, char *rdn)
|
||||
{
|
||||
char *dn;
|
||||
char *filter;
|
||||
Slapi_PBlock *pb;
|
||||
Slapi_Entry **entries;
|
||||
int ret;
|
||||
|
||||
pb = slapi_pblock_new();
|
||||
filter = slapi_ch_smprintf("(&(objectclass=nsds5replica)(nsds5replicaroot=%s))",
|
||||
conf->repl_root);
|
||||
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, &ret);
|
||||
if (ret != 0) {
|
||||
dn = NULL;
|
||||
} else {
|
||||
slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
|
||||
if (NULL == entries || NULL == entries[0]) {
|
||||
slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"ipa_topo_agreement_dn: no replica found\n");
|
||||
dn = NULL;
|
||||
} else if (rdn) {
|
||||
dn = slapi_ch_smprintf("%s,%s", rdn,
|
||||
slapi_entry_get_dn_const(entries[0]));
|
||||
} else {
|
||||
dn = slapi_ch_smprintf("cn=meTo%s,%s", agmt->target,
|
||||
slapi_entry_get_dn_const(entries[0]));
|
||||
}
|
||||
}
|
||||
slapi_free_search_results_internal(pb);
|
||||
slapi_pblock_destroy(pb);
|
||||
return dn;
|
||||
}
|
||||
int
|
||||
ipa_topo_agmt_new(char *hostname, TopoReplica *conf, TopoReplicaAgmt *agmt)
|
||||
{
|
||||
int ret = 0;
|
||||
if (strcasecmp(agmt->repl_bind_method,"SASL/GSSAPI") == 0) {
|
||||
ret = ipa_topo_agmt_setup(hostname, conf, agmt, 1);
|
||||
} else {
|
||||
ret = ipa_topo_agmt_setup(hostname, conf, agmt, 0);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ipa_topo_agmt_mod(TopoReplica *conf, TopoReplicaAgmt *agmt, LDAPMod **mods,
|
||||
char *direction)
|
||||
{
|
||||
int ret;
|
||||
Slapi_PBlock *pb;
|
||||
char *dn = NULL;
|
||||
Slapi_Entry **entries;
|
||||
int i;
|
||||
LDAPMod *tmp;
|
||||
Slapi_Mods *smods = NULL;
|
||||
|
||||
dn = ipa_topo_agreement_dn(conf, agmt, agmt->rdn);
|
||||
if (dn == NULL)
|
||||
return 1;
|
||||
|
||||
pb = slapi_pblock_new();
|
||||
slapi_search_internal_set_pb(pb, dn, LDAP_SCOPE_BASE,
|
||||
"objectclass=*", NULL, 0, NULL, NULL,
|
||||
ipa_topo_get_plugin_id(), 0);
|
||||
slapi_search_internal_pb(pb);
|
||||
slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &ret);
|
||||
if (ret != 0) {
|
||||
/* search failed */
|
||||
slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"ipa_topo_agmt_mod: agreement not found: %s\n", dn);
|
||||
goto done;
|
||||
}
|
||||
slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_SEARCH_ENTRIES, &entries);
|
||||
if (NULL == entries || NULL == entries[0]) {
|
||||
/* no entry */
|
||||
ret = 1;
|
||||
goto done;
|
||||
}
|
||||
/* apply mods to entry */
|
||||
|
||||
smods = slapi_mods_new();
|
||||
for (i = 0; (mods != NULL) && (mods[i] != NULL); i++) {
|
||||
char *type = ipa_topo_agmt_attr_is_managed(mods[i]->mod_type,direction);
|
||||
if (type) {
|
||||
tmp = mods[i];
|
||||
switch (tmp->mod_op & ~LDAP_MOD_BVALUES) {
|
||||
case LDAP_MOD_DELETE:
|
||||
break;
|
||||
case LDAP_MOD_ADD:
|
||||
case LDAP_MOD_REPLACE:
|
||||
slapi_mods_add_modbvps(smods, LDAP_MOD_REPLACE,
|
||||
type, tmp->mod_bvalues);
|
||||
break;
|
||||
}
|
||||
slapi_ch_free_string(&type);
|
||||
}
|
||||
}
|
||||
if (slapi_mods_get_num_mods(smods) > 0) {
|
||||
Slapi_DN *sdn = slapi_sdn_new_normdn_byref(dn);
|
||||
ipa_topo_util_modify(sdn, smods);
|
||||
slapi_sdn_free(&sdn);
|
||||
} else {
|
||||
slapi_ch_free_string(&dn);
|
||||
}
|
||||
slapi_mods_free(&smods);
|
||||
done:
|
||||
if (ret) slapi_ch_free_string(&dn);
|
||||
slapi_free_search_results_internal(pb);
|
||||
slapi_pblock_destroy(pb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
ipa_topo_agmt_del(char *hostname, TopoReplica *conf, TopoReplicaAgmt *agmt)
|
||||
{
|
||||
char *dn = NULL;
|
||||
int rc;
|
||||
|
||||
dn = ipa_topo_agreement_dn(conf, agmt, agmt->rdn);
|
||||
slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"ipa_topo_agmt_del: %s\n", agmt->rdn?agmt->rdn:"RDN missing");
|
||||
if (dn == NULL)
|
||||
return (-1);
|
||||
|
||||
rc = ipa_topo_agmt_del_dn(dn);
|
||||
slapi_ch_free_string(&dn);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
ipa_topo_agmt_del_dn(char *dn)
|
||||
{
|
||||
int ret = 0;
|
||||
Slapi_PBlock *pb;
|
||||
pb = slapi_pblock_new();
|
||||
slapi_delete_internal_set_pb(pb, dn, NULL, NULL,
|
||||
ipa_topo_get_plugin_id(), 0);
|
||||
|
||||
slapi_delete_internal_pb(pb);
|
||||
slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &ret);
|
||||
slapi_pblock_destroy(pb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
int
|
||||
ipa_topo_agmt_setup(char *hostname, TopoReplica *conf,
|
||||
TopoReplicaAgmt *agmt, int isgssapi)
|
||||
{
|
||||
Slapi_Entry *e = NULL;
|
||||
Slapi_PBlock *pb;
|
||||
char *dn = NULL;
|
||||
Slapi_DN *sdn = NULL;
|
||||
char *cn;
|
||||
char port[] = "389";
|
||||
char *description;
|
||||
int ret;
|
||||
/* Set up the new replication agreement entry */
|
||||
agmt->rdn = ipa_topo_agmt_gen_rdn(agmt->origin, agmt->target);
|
||||
dn = ipa_topo_agreement_dn(conf, agmt, agmt->rdn);
|
||||
if (dn == NULL)
|
||||
return -1;
|
||||
sdn = slapi_sdn_new_normdn_byref(dn);
|
||||
e = slapi_entry_alloc();
|
||||
/* the entry now owns the dup'd dn */
|
||||
slapi_entry_init_ext(e, sdn, NULL); /* sdn is copied into e */
|
||||
slapi_sdn_free(&sdn);
|
||||
|
||||
slapi_entry_add_string(e, SLAPI_ATTR_OBJECTCLASS, "nsds5replicationagreement");
|
||||
slapi_entry_add_string(e, SLAPI_ATTR_OBJECTCLASS, "ipaReplTopoManagedAgreement");
|
||||
cn = slapi_ch_smprintf("%s-to-%s", agmt->origin, agmt->target);
|
||||
slapi_entry_add_string(e, "cn",cn);
|
||||
slapi_ch_free_string(&cn);
|
||||
slapi_entry_add_string(e, "nsds5replicahost",hostname);
|
||||
slapi_entry_add_string(e, "nsds5replicaport",port);
|
||||
slapi_entry_add_string(e, "nsds5replicatimeout",AGMT_TIMEOUT);
|
||||
slapi_entry_add_string(e, "nsds5replicaroot",agmt->repl_root);
|
||||
description = slapi_ch_smprintf("%s to %s", ipa_topo_get_plugin_hostname(), hostname);
|
||||
slapi_entry_add_string(e, "description",description);
|
||||
slapi_ch_free_string(&description);
|
||||
slapi_entry_add_string(e, "ipaReplTopoManagedAgreementState",
|
||||
"managed agreement - generated by topology plugin");
|
||||
|
||||
if (isgssapi) {
|
||||
slapi_entry_add_string(e, "nsds5replicatransportinfo","LDAP");
|
||||
slapi_entry_add_string(e, "nsds5replicabindmethod","SASL/GSSAPI");
|
||||
} else {
|
||||
slapi_entry_add_string(e, "nsds5replicabinddn",REPL_MAN_DN);
|
||||
slapi_entry_add_string(e, "nsds5replicacredentials",REPL_MAN_PASSWD);
|
||||
slapi_entry_add_string(e, "nsds5replicatransportinfo","TLS");
|
||||
slapi_entry_add_string(e, "nsds5replicabindmethod","simple");
|
||||
}
|
||||
if (agmt->repl_attrs) {
|
||||
slapi_entry_add_string(e, "nsDS5ReplicatedAttributeList",agmt->repl_attrs);
|
||||
} else {
|
||||
slapi_entry_add_string(e, "nsDS5ReplicatedAttributeList", REPL_ATTR_LIST);
|
||||
}
|
||||
if (agmt->strip_attrs) {
|
||||
slapi_entry_add_string(e, "nsds5ReplicaStripAttrs", agmt->strip_attrs);
|
||||
} else {
|
||||
slapi_entry_add_string(e, "nsds5ReplicaStripAttrs", REPL_ATTR_STRIP);
|
||||
}
|
||||
if (agmt->total_attrs) {
|
||||
slapi_entry_add_string(e, "nsDS5ReplicatedAttributeListTotal",
|
||||
agmt->total_attrs);
|
||||
} else {
|
||||
slapi_entry_add_string(e, "nsDS5ReplicatedAttributeListTotal",
|
||||
REPL_ATTR_LIST_TOTAL);
|
||||
}
|
||||
|
||||
pb = slapi_pblock_new();
|
||||
slapi_pblock_init(pb);
|
||||
|
||||
/* e will be consumed by slapi_add_internal() */
|
||||
slapi_add_entry_internal_set_pb(pb, e, NULL, ipa_topo_get_plugin_id(), 0);
|
||||
slapi_add_internal_pb(pb);
|
||||
slapi_pblock_get(pb, SLAPI_PLUGIN_INTOP_RESULT, &ret);
|
||||
slapi_pblock_destroy(pb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
ipa_topo_agmt_initialize_replication(char *hostname,
|
||||
TopoReplica *conf, TopoReplicaAgmt *agmt)
|
||||
{
|
||||
int ret = 0;
|
||||
char *dn;
|
||||
Slapi_Mods *smods = slapi_mods_new();
|
||||
|
||||
slapi_mods_add_string(smods, LDAP_MOD_REPLACE,
|
||||
"nsds5ReplicaEnabled", "on");
|
||||
slapi_mods_add_string(smods, LDAP_MOD_ADD,
|
||||
"nsds5BeginReplicaRefresh", "start");
|
||||
if (slapi_mods_get_num_mods(smods) > 0) {
|
||||
dn = ipa_topo_agreement_dn(conf, agmt, agmt->rdn);
|
||||
Slapi_DN *sdn = slapi_sdn_new_normdn_byref(dn);
|
||||
ipa_topo_util_modify(sdn, smods);
|
||||
slapi_sdn_free(&sdn);
|
||||
}
|
||||
slapi_mods_free(&smods);
|
||||
return ret;
|
||||
}
|
||||
|
||||
char *
|
||||
ipa_topo_agmt_attr_is_managed(char *type, char *direction)
|
||||
{
|
||||
char *mtype = NULL;
|
||||
char **mattrs = NULL;
|
||||
char *subtype;
|
||||
char *ctype = slapi_ch_strdup(type);
|
||||
int i;
|
||||
|
||||
/* segment attrs have the form
|
||||
* attrtype od attrtype;direction
|
||||
* find the attrtype and return the corresponding
|
||||
* repl agreeement attribute type
|
||||
*/
|
||||
subtype = strchr(ctype,';');
|
||||
if (subtype) {
|
||||
/* attr is handling specific direction,
|
||||
* check if interested
|
||||
*/
|
||||
if (strstr(ctype,direction)) {
|
||||
*subtype = '\0';
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
mattrs = ipa_topo_get_plugin_managed_attrs();
|
||||
for (i=0; mattrs[i]; i++) {
|
||||
if(0 == strcasecmp(mattrs[i], ctype)) {
|
||||
mtype = slapi_ch_strdup(mattrs[i]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return mtype;
|
||||
}
|
888
daemons/ipa-slapi-plugins/topology/topology_cfg.c
Normal file
888
daemons/ipa-slapi-plugins/topology/topology_cfg.c
Normal file
@ -0,0 +1,888 @@
|
||||
|
||||
#include "topology.h"
|
||||
|
||||
/* two static data structures to hold the
|
||||
* plugin configuration and the information
|
||||
* stored in the shared tree.
|
||||
* They will be initialized at plugin init/start,
|
||||
* updated when the shared config is modified
|
||||
* and accessed via set/get functions
|
||||
*/
|
||||
static TopoPluginConf topo_plugin_conf = {0};
|
||||
static TopoReplicaConf topo_shared_conf = {0};
|
||||
static IpaDomainLevel ipa_domain_level = {0,0};
|
||||
|
||||
char *ipa_topo_plugin_managed_attrs[] = {
|
||||
"nsds5ReplicaStripAttrs",
|
||||
"nsds5ReplicatedAttributeList",
|
||||
"nsDS5ReplicatedAttributeListTotal",
|
||||
"nsds5BeginReplicaRefresh",
|
||||
"nsds5replicaTimeout",
|
||||
"nsds5ReplicaEnabled",
|
||||
"nsds5replicaSessionPauseTime",
|
||||
"nsds5replicabinddn",
|
||||
"nsds5replicacredentials",
|
||||
"nsds5replicatransportinfo",
|
||||
"nsds5replicabindmethod",
|
||||
NULL };
|
||||
|
||||
/* subset of attrs which can only be modified via
|
||||
* modification of segments in the shared tree.
|
||||
* Other attributes still can be directly modified
|
||||
* eg to reinit a replica or change bind method and
|
||||
* credentials.
|
||||
* This is currently needed to make ipa-replica-install work
|
||||
*/
|
||||
char *ipa_topo_plugin_restricted_attrs[] = {
|
||||
"nsds5ReplicaStripAttrs",
|
||||
"nsds5ReplicatedAttributeList",
|
||||
"nsDS5ReplicatedAttributeListTotal",
|
||||
"nsds5replicaTimeout",
|
||||
"nsds5replicaSessionPauseTime",
|
||||
NULL };
|
||||
|
||||
void *
|
||||
ipa_topo_get_plugin_id(void)
|
||||
{
|
||||
return topo_plugin_conf.identity;
|
||||
}
|
||||
|
||||
char *
|
||||
ipa_topo_get_plugin_hostname(void)
|
||||
{
|
||||
return topo_plugin_conf.hostname;
|
||||
}
|
||||
|
||||
char **
|
||||
ipa_topo_get_plugin_managed_attrs(void)
|
||||
{
|
||||
return topo_plugin_conf.managed_attrs;
|
||||
}
|
||||
|
||||
char **
|
||||
ipa_topo_get_plugin_restricted_attrs(void)
|
||||
{
|
||||
return topo_plugin_conf.restricted_attrs;
|
||||
}
|
||||
|
||||
char *
|
||||
ipa_topo_get_plugin_shared_config(void)
|
||||
{
|
||||
return topo_plugin_conf.shared_config_base;
|
||||
}
|
||||
char *
|
||||
ipa_topo_get_plugin_shared_topo(void)
|
||||
{
|
||||
return topo_plugin_conf.shared_topo;
|
||||
}
|
||||
|
||||
Slapi_DN *
|
||||
ipa_topo_get_plugin_shared_topo_dn(void)
|
||||
{
|
||||
return topo_plugin_conf.shared_topo_sdn;
|
||||
}
|
||||
|
||||
char *
|
||||
ipa_topo_get_domain_level_entry(void)
|
||||
{
|
||||
return topo_plugin_conf.domain_level;
|
||||
}
|
||||
|
||||
Slapi_DN *
|
||||
ipa_topo_get_domain_level_entry_dn(void)
|
||||
{
|
||||
return topo_plugin_conf.domain_level_sdn;
|
||||
}
|
||||
|
||||
int
|
||||
ipa_topo_get_domain_level_major(void)
|
||||
{
|
||||
return ipa_domain_level.major;
|
||||
}
|
||||
|
||||
int
|
||||
ipa_topo_get_domain_level_minor(void)
|
||||
{
|
||||
return ipa_domain_level.minor;
|
||||
}
|
||||
|
||||
char *
|
||||
ipa_topo_get_plugin_shared_hosts(void)
|
||||
{
|
||||
return topo_plugin_conf.shared_hosts;
|
||||
}
|
||||
|
||||
Slapi_DN *
|
||||
ipa_topo_get_plugin_shared_hosts_dn(void)
|
||||
{
|
||||
return topo_plugin_conf.shared_hosts_sdn;
|
||||
}
|
||||
|
||||
char *
|
||||
ipa_topo_get_plugin_shared_bindgroup(void)
|
||||
{
|
||||
return topo_plugin_conf.shared_bindgroup;
|
||||
}
|
||||
|
||||
Slapi_DN *
|
||||
ipa_topo_get_plugin_shared_bindgroup_dn(void)
|
||||
{
|
||||
return topo_plugin_conf.shared_bindgroup_sdn;
|
||||
}
|
||||
char **
|
||||
ipa_topo_get_plugin_replica_root(void)
|
||||
{
|
||||
return topo_plugin_conf.shared_replica_root;
|
||||
}
|
||||
|
||||
int
|
||||
ipa_topo_get_plugin_version_major(void)
|
||||
{
|
||||
return topo_plugin_conf.version_major;
|
||||
}
|
||||
|
||||
int
|
||||
ipa_topo_get_plugin_version_minor(void)
|
||||
{
|
||||
return topo_plugin_conf.version_minor;
|
||||
}
|
||||
|
||||
int
|
||||
ipa_topo_get_plugin_startup_delay(void)
|
||||
{
|
||||
return topo_plugin_conf.startup_delay;
|
||||
}
|
||||
|
||||
void
|
||||
ipa_topo_set_plugin_id(void *plg_id)
|
||||
{
|
||||
topo_plugin_conf.identity = plg_id;
|
||||
}
|
||||
|
||||
void
|
||||
ipa_topo_set_plugin_active(int state)
|
||||
{
|
||||
topo_plugin_conf.activated = state;
|
||||
}
|
||||
int
|
||||
ipa_topo_get_plugin_active(void)
|
||||
{
|
||||
return topo_plugin_conf.activated;
|
||||
}
|
||||
|
||||
void
|
||||
ipa_topo_set_plugin_shared_config(char *cfg)
|
||||
{
|
||||
char *topo;
|
||||
char *hosts;
|
||||
char *domain_level;
|
||||
topo_plugin_conf.shared_config_base = cfg;
|
||||
topo = slapi_ch_smprintf("%s,%s","cn=topology",cfg);
|
||||
hosts = slapi_ch_smprintf("%s,%s","cn=masters",cfg);
|
||||
domain_level = slapi_ch_smprintf("%s,%s","cn=domain level",cfg);
|
||||
topo_plugin_conf.shared_topo = topo;
|
||||
topo_plugin_conf.shared_topo_sdn = slapi_sdn_new_normdn_byref(topo);
|
||||
topo_plugin_conf.shared_hosts = hosts;
|
||||
topo_plugin_conf.shared_hosts_sdn = slapi_sdn_new_normdn_byref(hosts);
|
||||
topo_plugin_conf.domain_level = domain_level;
|
||||
topo_plugin_conf.domain_level_sdn = slapi_sdn_new_normdn_byref(domain_level);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
ipa_topo_set_plugin_shared_bindgroup(char *bindgroup)
|
||||
{
|
||||
topo_plugin_conf.shared_bindgroup = bindgroup;
|
||||
topo_plugin_conf.shared_bindgroup_sdn = slapi_sdn_new_normdn_byref(bindgroup);
|
||||
}
|
||||
|
||||
void
|
||||
ipa_topo_set_domain_level(char *level)
|
||||
{
|
||||
char *minor;
|
||||
|
||||
if (level == NULL) {
|
||||
ipa_domain_level.major = 0;
|
||||
ipa_domain_level.minor = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
minor = strchr(level,'.');
|
||||
if (minor) {
|
||||
*minor = '\0';
|
||||
ipa_domain_level.minor = atoi(++minor);
|
||||
} else {
|
||||
ipa_domain_level.minor = 0;
|
||||
}
|
||||
ipa_domain_level.major = atoi(level);
|
||||
}
|
||||
|
||||
void
|
||||
ipa_topo_set_plugin_hostname(char *hostname)
|
||||
{
|
||||
topo_plugin_conf.hostname = hostname;
|
||||
}
|
||||
|
||||
#define TOPO_PLUGIN_DEFAULT_STARTUP_DELAY 20
|
||||
void
|
||||
ipa_topo_set_plugin_startup_delay(char *delay)
|
||||
{
|
||||
if (delay) {
|
||||
topo_plugin_conf.startup_delay = atoi(delay);
|
||||
} else {
|
||||
topo_plugin_conf.startup_delay = TOPO_PLUGIN_DEFAULT_STARTUP_DELAY;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ipa_topo_set_plugin_version(char *version)
|
||||
{
|
||||
char *minor;
|
||||
|
||||
if ( version == NULL) {
|
||||
topo_plugin_conf.version_major = 0;
|
||||
topo_plugin_conf.version_minor = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
minor = strchr(version,'.');
|
||||
if (minor) {
|
||||
*minor = '\0';
|
||||
topo_plugin_conf.version_minor = atoi(++minor);
|
||||
} else {
|
||||
topo_plugin_conf.version_minor = 0;
|
||||
}
|
||||
topo_plugin_conf.version_major = atoi(version);
|
||||
}
|
||||
|
||||
void
|
||||
ipa_topo_init_shared_config(void)
|
||||
{
|
||||
topo_shared_conf.allhosts = NULL;
|
||||
topo_shared_conf.replicas = NULL;
|
||||
topo_shared_conf.conf_lock = slapi_new_mutex();
|
||||
}
|
||||
|
||||
void
|
||||
ipa_topo_set_plugin_managed_attrs(char **attrs)
|
||||
{
|
||||
if (attrs) {
|
||||
topo_plugin_conf.managed_attrs = attrs;
|
||||
} else {
|
||||
topo_plugin_conf.managed_attrs = ipa_topo_plugin_managed_attrs;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ipa_topo_set_plugin_restricted_attrs(char **attrs)
|
||||
{
|
||||
if (attrs) {
|
||||
topo_plugin_conf.restricted_attrs = attrs;
|
||||
} else {
|
||||
topo_plugin_conf.restricted_attrs = ipa_topo_plugin_restricted_attrs;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ipa_topo_cfg_plugin_suffix_is_managed(const char *be_suffix) {
|
||||
|
||||
int i = 0;
|
||||
char **shared_replica_root = ipa_topo_get_plugin_replica_root();
|
||||
|
||||
while (shared_replica_root[i]) {
|
||||
if (0 == strcasecmp(shared_replica_root[i], be_suffix)) return 1;
|
||||
i++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
ipa_topo_cfg_attr_is_restricted(char *type)
|
||||
{
|
||||
int i;
|
||||
int rc = 0;
|
||||
char **rattrs = ipa_topo_get_plugin_restricted_attrs();
|
||||
for (i=0; rattrs[i]; i++) {
|
||||
if(0 == strcasecmp(rattrs[i], type)) {
|
||||
rc = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
void
|
||||
ipa_topo_set_plugin_replica_root(char **root)
|
||||
{
|
||||
topo_plugin_conf.shared_replica_root = root;
|
||||
}
|
||||
|
||||
int
|
||||
ipa_topo_init_plugin_config(Slapi_PBlock * pb)
|
||||
{
|
||||
Slapi_Entry *plugin_entry = NULL;
|
||||
char *hostname;
|
||||
char *config_base;
|
||||
char *startup_delay;
|
||||
char *plugin_version;
|
||||
char *bindgroup;
|
||||
char **replica_root;
|
||||
|
||||
/* get the local hostname */
|
||||
hostname = ipa_topo_util_get_pluginhost();
|
||||
if (hostname == NULL) {
|
||||
/* log error */
|
||||
return -1;
|
||||
} else {
|
||||
ipa_topo_set_plugin_hostname(hostname);
|
||||
}
|
||||
/* get the args */
|
||||
/* slapi_pblock_get(pb, SLAPI_PLUGIN_CONFIG_ENTRY, &plugin_entry); */
|
||||
slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &plugin_entry);
|
||||
|
||||
if(plugin_entry == NULL){
|
||||
return -1;
|
||||
}
|
||||
|
||||
ipa_topo_set_plugin_active(0);
|
||||
|
||||
config_base = slapi_entry_attr_get_charptr(plugin_entry,
|
||||
CONFIG_ATTR_SHARED_BASE);
|
||||
if(config_base){
|
||||
ipa_topo_set_plugin_shared_config(config_base);
|
||||
}
|
||||
|
||||
replica_root = slapi_entry_attr_get_charray(plugin_entry,
|
||||
CONFIG_ATTR_REPLICA_ROOT);
|
||||
if(replica_root){
|
||||
ipa_topo_set_plugin_replica_root(replica_root);
|
||||
}
|
||||
|
||||
bindgroup = slapi_entry_attr_get_charptr(plugin_entry,
|
||||
CONFIG_ATTR_SHARED_BINDDNGROUP);
|
||||
if(bindgroup){
|
||||
ipa_topo_set_plugin_shared_bindgroup(bindgroup);
|
||||
}
|
||||
|
||||
startup_delay = slapi_entry_attr_get_charptr(plugin_entry,
|
||||
CONFIG_ATTR_STARTUP_DELAY);
|
||||
ipa_topo_set_plugin_startup_delay(startup_delay);
|
||||
slapi_ch_free_string(&startup_delay);
|
||||
|
||||
plugin_version = slapi_entry_attr_get_charptr(plugin_entry,
|
||||
CONFIG_ATTR_PLUGIN_VERSION);
|
||||
ipa_topo_set_plugin_version(plugin_version);
|
||||
slapi_ch_free_string(&plugin_version);
|
||||
|
||||
ipa_topo_util_set_domain_level();
|
||||
|
||||
ipa_topo_util_check_plugin_active();
|
||||
|
||||
|
||||
ipa_topo_set_plugin_managed_attrs(NULL); /* use defaults */
|
||||
ipa_topo_set_plugin_restricted_attrs(NULL); /* use defaults */
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
ipa_topo_free_plugin_config(void)
|
||||
{
|
||||
slapi_destroy_mutex(topo_plugin_conf.plg_lock);
|
||||
slapi_ch_free((void **)topo_plugin_conf.identity);
|
||||
slapi_ch_free_string(&topo_plugin_conf.hostname);
|
||||
slapi_ch_free_string(&topo_plugin_conf.shared_config_base);
|
||||
slapi_ch_free_string(&topo_plugin_conf.shared_topo);
|
||||
slapi_sdn_free(&topo_plugin_conf.shared_topo_sdn);
|
||||
slapi_ch_free_string(&topo_plugin_conf.shared_hosts);
|
||||
slapi_sdn_free(&topo_plugin_conf.shared_hosts_sdn);
|
||||
slapi_ch_free_string(&topo_plugin_conf.shared_bindgroup);
|
||||
slapi_sdn_free(&topo_plugin_conf.shared_bindgroup_sdn);
|
||||
slapi_ch_free_string(&topo_plugin_conf.domain_level);
|
||||
slapi_sdn_free(&topo_plugin_conf.domain_level_sdn);
|
||||
slapi_ch_array_free(topo_plugin_conf.shared_replica_root);
|
||||
if (ipa_topo_plugin_managed_attrs != topo_plugin_conf.managed_attrs)
|
||||
slapi_ch_array_free(topo_plugin_conf.managed_attrs);
|
||||
if (ipa_topo_plugin_restricted_attrs != topo_plugin_conf.restricted_attrs)
|
||||
slapi_ch_array_free(topo_plugin_conf.restricted_attrs);
|
||||
}
|
||||
|
||||
void
|
||||
ipa_topo_lock_conf(void)
|
||||
{
|
||||
slapi_lock_mutex(topo_shared_conf.conf_lock);
|
||||
}
|
||||
|
||||
void
|
||||
ipa_topo_unlock_conf(void)
|
||||
{
|
||||
slapi_unlock_mutex(topo_shared_conf.conf_lock);
|
||||
}
|
||||
|
||||
int
|
||||
ipa_topo_acquire_startup_inprogress(void)
|
||||
{
|
||||
int acquired = 0;
|
||||
slapi_lock_mutex(topo_shared_conf.conf_lock);
|
||||
if (topo_shared_conf.startup_inprogress == 0 ) {
|
||||
topo_shared_conf.startup_inprogress = 1;
|
||||
acquired = 1;
|
||||
}
|
||||
slapi_unlock_mutex(topo_shared_conf.conf_lock);
|
||||
return acquired;
|
||||
}
|
||||
|
||||
void
|
||||
ipa_topo_release_startup_inprogress(void)
|
||||
{
|
||||
slapi_lock_mutex(topo_shared_conf.conf_lock);
|
||||
topo_shared_conf.startup_inprogress = 0;
|
||||
slapi_unlock_mutex(topo_shared_conf.conf_lock);
|
||||
}
|
||||
|
||||
TopoReplicaHost *
|
||||
ipa_topo_cfg_host_find(TopoReplica *tconf, char *findhost, int lock)
|
||||
{
|
||||
TopoReplicaHost *host = NULL;
|
||||
|
||||
if (tconf->hosts == NULL) return NULL;
|
||||
|
||||
if (lock) slapi_lock_mutex(tconf->repl_lock);
|
||||
for (host=tconf->hosts;host;host=host->next) {
|
||||
if (!strcasecmp(host->hostname,findhost)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (lock) slapi_unlock_mutex(tconf->repl_lock);
|
||||
return host;
|
||||
}
|
||||
|
||||
TopoReplicaHost *
|
||||
ipa_topo_cfg_host_new(char *newhost)
|
||||
{
|
||||
TopoReplicaHost *newnode;
|
||||
newnode = (TopoReplicaHost *)slapi_ch_malloc(sizeof(TopoReplicaHost));
|
||||
newnode->next = NULL;
|
||||
newnode->hostname = newhost;
|
||||
return newnode;
|
||||
}
|
||||
|
||||
void
|
||||
ipa_topo_cfg_host_add(Slapi_Entry *hostentry)
|
||||
{
|
||||
char *newhost;
|
||||
char **repl_root = NULL;
|
||||
TopoReplicaHost *hostnode = NULL;
|
||||
TopoReplica *replica = NULL;
|
||||
int i;
|
||||
|
||||
newhost = slapi_entry_attr_get_charptr(hostentry,"cn");
|
||||
if (newhost == NULL) return;
|
||||
|
||||
repl_root = slapi_entry_attr_get_charray(hostentry,"ipaReplTopoManagedSuffix");
|
||||
if (repl_root == NULL || *repl_root == NULL) return;
|
||||
|
||||
for (i=0; repl_root[i];i++) {
|
||||
replica = ipa_topo_cfg_replica_find(repl_root[i], 1);
|
||||
if (replica == NULL) continue;
|
||||
|
||||
slapi_lock_mutex(replica->repl_lock);
|
||||
if (ipa_topo_cfg_host_find(replica, newhost, 0)) {
|
||||
/* log error */
|
||||
slapi_unlock_mutex(replica->repl_lock);
|
||||
continue;
|
||||
}
|
||||
hostnode = ipa_topo_cfg_host_new(slapi_ch_strdup(newhost));
|
||||
hostnode->next = replica->hosts;
|
||||
replica->hosts = hostnode;
|
||||
slapi_unlock_mutex(replica->repl_lock);
|
||||
}
|
||||
|
||||
slapi_ch_array_free(repl_root);
|
||||
slapi_ch_free_string(&newhost);
|
||||
return;
|
||||
}
|
||||
|
||||
void
|
||||
ipa_topo_cfg_host_free(TopoReplicaHost **node)
|
||||
{
|
||||
slapi_ch_free((void **)&((*node)->hostname));
|
||||
slapi_ch_free((void **)node);
|
||||
}
|
||||
|
||||
void
|
||||
ipa_topo_cfg_host_del(Slapi_Entry *hostentry)
|
||||
{
|
||||
char *delhost;
|
||||
TopoReplicaHost *hostnode = NULL;
|
||||
TopoReplicaHost *prevnode = NULL;
|
||||
char **repl_root = NULL;
|
||||
TopoReplica *replica = NULL;
|
||||
int i;
|
||||
|
||||
delhost = slapi_entry_attr_get_charptr(hostentry,"cn");
|
||||
if (delhost == NULL) return;
|
||||
|
||||
repl_root = slapi_entry_attr_get_charray(hostentry,"ipaReplTopoManagedSuffix");
|
||||
if (repl_root == NULL || *repl_root == NULL) return;
|
||||
|
||||
for (i=0; repl_root[i];i++) {
|
||||
replica = ipa_topo_cfg_replica_find(repl_root[i], 1);
|
||||
if (replica == NULL) continue;
|
||||
|
||||
slapi_lock_mutex(replica->repl_lock);
|
||||
hostnode = replica->hosts;
|
||||
while (hostnode) {
|
||||
if (!strcasecmp(hostnode->hostname,delhost)) {
|
||||
/*remove from list and free*/
|
||||
if (prevnode) {
|
||||
prevnode->next = hostnode->next;
|
||||
} else {
|
||||
replica->hosts = hostnode->next;
|
||||
}
|
||||
ipa_topo_cfg_host_free(&hostnode);
|
||||
break;
|
||||
} else {
|
||||
prevnode = hostnode;
|
||||
hostnode = hostnode->next;
|
||||
}
|
||||
}
|
||||
slapi_unlock_mutex(replica->repl_lock);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
TopoReplicaSegment *
|
||||
ipa_topo_cfg_replica_segment_find(TopoReplica *replica, char *leftHost, char *rightHost, int lock)
|
||||
{
|
||||
TopoReplicaSegment *tsegm = NULL;
|
||||
TopoReplicaSegmentList *segments = NULL;
|
||||
|
||||
if (lock) slapi_lock_mutex(replica->repl_lock);
|
||||
segments = replica->repl_segments;
|
||||
while (segments) {
|
||||
tsegm = segments->segm;
|
||||
if ( (!strcasecmp(leftHost,tsegm->from) && !strcasecmp(rightHost,tsegm->to) &&
|
||||
(tsegm->direct == SEGMENT_BIDIRECTIONAL || tsegm->direct == SEGMENT_LEFT_RIGHT)) ||
|
||||
(!strcasecmp(leftHost,tsegm->to) && !strcasecmp(rightHost,tsegm->from) &&
|
||||
(tsegm->direct == SEGMENT_BIDIRECTIONAL || tsegm->direct == SEGMENT_RIGHT_LEFT))) {
|
||||
break;
|
||||
}
|
||||
tsegm = NULL;
|
||||
segments = segments->next;
|
||||
}
|
||||
if (lock) slapi_unlock_mutex(replica->repl_lock);
|
||||
|
||||
return tsegm;
|
||||
}
|
||||
|
||||
TopoReplicaAgmt *
|
||||
ipa_topo_cfg_agmt_dup(TopoReplicaAgmt *agmt)
|
||||
{
|
||||
TopoReplicaAgmt *dup = NULL;
|
||||
|
||||
if (agmt == NULL) return NULL;
|
||||
|
||||
dup = (TopoReplicaAgmt *) slapi_ch_calloc(1,sizeof(TopoReplicaAgmt));
|
||||
dup->rdn = slapi_ch_strdup(agmt->rdn);
|
||||
dup->origin = slapi_ch_strdup(agmt->origin);
|
||||
dup->target = slapi_ch_strdup(agmt->target);
|
||||
dup->enabled = slapi_ch_strdup(agmt->enabled);
|
||||
dup->repl_root = slapi_ch_strdup(agmt->repl_root);
|
||||
dup->strip_attrs = slapi_ch_strdup(agmt->strip_attrs);
|
||||
dup->total_attrs = slapi_ch_strdup(agmt->total_attrs);
|
||||
dup->repl_attrs = slapi_ch_strdup(agmt->repl_attrs);
|
||||
dup->repl_pause = slapi_ch_strdup(agmt->repl_pause);
|
||||
dup->repl_timeout = slapi_ch_strdup(agmt->repl_timeout);
|
||||
dup->repl_refresh = slapi_ch_strdup(agmt->repl_refresh);
|
||||
dup->repl_transport = slapi_ch_strdup(agmt->repl_transport);
|
||||
dup->repl_bind_dn = slapi_ch_strdup(agmt->repl_bind_dn);
|
||||
dup->repl_bind_cred = slapi_ch_strdup(agmt->repl_bind_cred);
|
||||
dup->repl_bind_method = slapi_ch_strdup(agmt->repl_bind_method);
|
||||
|
||||
return dup;
|
||||
}
|
||||
|
||||
TopoReplicaAgmt *
|
||||
ipa_topo_cfg_agmt_dup_reverse(TopoReplicaAgmt *agmt)
|
||||
{
|
||||
char *tmp;
|
||||
TopoReplicaAgmt *dup = NULL;
|
||||
dup = ipa_topo_cfg_agmt_dup(agmt);
|
||||
|
||||
if (dup == NULL) return NULL;
|
||||
|
||||
tmp = dup->origin;
|
||||
dup->origin = dup->target;
|
||||
dup->target = tmp;
|
||||
|
||||
/* this is not enough, if a reverse agmt is
|
||||
* created because segment becomes bidirectional
|
||||
* we don't really know the rdn of the other direction
|
||||
* As long as this info is not in the segment,
|
||||
* assume std agmt naming and do best effort.
|
||||
*/
|
||||
|
||||
slapi_ch_free_string(&dup->rdn);
|
||||
dup->rdn = ipa_topo_agmt_std_rdn(dup->target);
|
||||
return dup;
|
||||
}
|
||||
static void
|
||||
ipa_topo_cfg_agmt_done(TopoReplicaAgmt *agmt)
|
||||
{
|
||||
if (agmt == NULL) return;
|
||||
|
||||
slapi_ch_free_string(&agmt->origin);
|
||||
slapi_ch_free_string(&agmt->target);
|
||||
slapi_ch_free_string(&agmt->enabled);
|
||||
slapi_ch_free_string(&agmt->repl_root);
|
||||
slapi_ch_free_string(&agmt->strip_attrs);
|
||||
slapi_ch_free_string(&agmt->total_attrs);
|
||||
slapi_ch_free_string(&agmt->repl_attrs);
|
||||
slapi_ch_free_string(&agmt->repl_pause);
|
||||
slapi_ch_free_string(&agmt->repl_timeout);
|
||||
slapi_ch_free_string(&agmt->repl_refresh);
|
||||
slapi_ch_free_string(&agmt->repl_transport);
|
||||
slapi_ch_free_string(&agmt->repl_bind_dn);
|
||||
slapi_ch_free_string(&agmt->repl_bind_cred);
|
||||
slapi_ch_free_string(&agmt->repl_bind_method);
|
||||
}
|
||||
|
||||
static void
|
||||
ipa_topo_cfg_segment_done(TopoReplicaSegment *tsegm)
|
||||
{
|
||||
if (tsegm == NULL) return;
|
||||
|
||||
slapi_ch_free_string(&tsegm->name);
|
||||
slapi_ch_free_string(&tsegm->from);
|
||||
slapi_ch_free_string(&tsegm->to);
|
||||
ipa_topo_cfg_agmt_done(tsegm->left);
|
||||
ipa_topo_cfg_agmt_done(tsegm->right);
|
||||
slapi_ch_free((void **)&tsegm->left);
|
||||
slapi_ch_free((void **)&tsegm->right);
|
||||
}
|
||||
|
||||
void
|
||||
ipa_topo_cfg_segment_free(TopoReplicaSegment *tsegm)
|
||||
{
|
||||
ipa_topo_cfg_segment_done(tsegm);
|
||||
slapi_ch_free((void **)&tsegm);
|
||||
}
|
||||
|
||||
TopoReplicaSegment *
|
||||
ipa_topo_cfg_segment_dup(TopoReplicaSegment *orig)
|
||||
{
|
||||
TopoReplicaSegment *dup = NULL;
|
||||
|
||||
if (orig == NULL) return NULL;
|
||||
|
||||
dup = (TopoReplicaSegment *) slapi_ch_calloc(1,sizeof(TopoReplicaSegment));
|
||||
dup->name = slapi_ch_strdup(orig->name);
|
||||
dup->from = slapi_ch_strdup(orig->from);
|
||||
dup->to = slapi_ch_strdup(orig->to);
|
||||
dup->left = ipa_topo_cfg_agmt_dup(orig->left);
|
||||
dup->left = ipa_topo_cfg_agmt_dup(orig->left);
|
||||
dup->direct = orig->direct;
|
||||
dup->state = orig->state;
|
||||
return dup;
|
||||
}
|
||||
|
||||
TopoReplicaSegment *
|
||||
ipa_topo_cfg_segment_find(char *repl_root, char *leftHost, char *rightHost)
|
||||
{
|
||||
TopoReplicaSegment *tsegm = NULL;
|
||||
TopoReplica *replica = NULL;
|
||||
|
||||
slapi_lock_mutex(topo_shared_conf.conf_lock);
|
||||
|
||||
replica = ipa_topo_cfg_replica_find(repl_root, 0);
|
||||
if (replica) {
|
||||
tsegm = ipa_topo_cfg_replica_segment_find(replica,leftHost,rightHost, 1);
|
||||
}
|
||||
slapi_unlock_mutex(topo_shared_conf.conf_lock);
|
||||
return tsegm;
|
||||
}
|
||||
|
||||
void
|
||||
ipa_topo_cfg_segment_set_visited(TopoReplica *replica, TopoReplicaSegment *vsegm)
|
||||
{
|
||||
TopoReplicaSegmentList *segments = NULL;
|
||||
TopoReplicaSegment *tsegm = NULL;
|
||||
char *leftHost = vsegm->from;
|
||||
char *rightHost = vsegm->to;
|
||||
|
||||
slapi_lock_mutex(replica->repl_lock);
|
||||
segments = replica->repl_segments;
|
||||
while (segments) {
|
||||
tsegm = segments->segm;
|
||||
if ( (!strcasecmp(leftHost,tsegm->from) && !strcasecmp(rightHost,tsegm->to) &&
|
||||
(tsegm->direct == SEGMENT_BIDIRECTIONAL || tsegm->direct == SEGMENT_LEFT_RIGHT)) ||
|
||||
(!strcasecmp(leftHost,tsegm->to) && !strcasecmp(rightHost,tsegm->from) &&
|
||||
(tsegm->direct == SEGMENT_BIDIRECTIONAL || tsegm->direct == SEGMENT_RIGHT_LEFT))) {
|
||||
segments->visited = 1;
|
||||
break;
|
||||
}
|
||||
tsegm = NULL;
|
||||
segments = segments->next;
|
||||
}
|
||||
slapi_unlock_mutex(replica->repl_lock);
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
ipa_topo_cfg_segment_add(TopoReplica *replica, TopoReplicaSegment *tsegm)
|
||||
{
|
||||
TopoReplicaSegmentList *seglist = NULL;
|
||||
|
||||
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"ipa_topo_cfg_segment_add: %s\n", tsegm->name);
|
||||
slapi_lock_mutex(replica->repl_lock);
|
||||
if (ipa_topo_cfg_replica_segment_find(replica,
|
||||
tsegm->from,
|
||||
tsegm->to, 0)){
|
||||
/* already exists: log error */
|
||||
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"ipa_topo_cfg_segment_add: error: segment exists: %s\n",
|
||||
tsegm->name);
|
||||
goto done;
|
||||
}
|
||||
seglist = (TopoReplicaSegmentList *)
|
||||
slapi_ch_calloc(1,sizeof(TopoReplicaSegmentList));
|
||||
seglist->visited = 0;
|
||||
seglist->segm = tsegm;
|
||||
if (replica->repl_segments == NULL) {
|
||||
replica->repl_segments = seglist;
|
||||
} else {
|
||||
seglist->next = replica->repl_segments;
|
||||
replica->repl_segments = seglist;
|
||||
}
|
||||
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"ipa_topo_cfg_segment_added: %s\n", tsegm->name);
|
||||
done:
|
||||
slapi_unlock_mutex(replica->repl_lock);
|
||||
}
|
||||
|
||||
void
|
||||
ipa_topo_cfg_segment_del(TopoReplica *tconf, TopoReplicaSegment *tsegm)
|
||||
{
|
||||
TopoReplicaSegmentList *segment = NULL;
|
||||
TopoReplicaSegmentList *prev = NULL;
|
||||
|
||||
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"ipa_topo_cfg_segment_del: %s\n", tsegm->name);
|
||||
slapi_lock_mutex(tconf->repl_lock);
|
||||
segment = tconf->repl_segments;
|
||||
while (segment) {
|
||||
if (segment->segm == tsegm) {
|
||||
if (prev == NULL) {
|
||||
tconf->repl_segments = segment->next;
|
||||
} else {
|
||||
prev->next = segment->next;
|
||||
}
|
||||
/* free segment */
|
||||
ipa_topo_cfg_segment_free(tsegm);
|
||||
slapi_ch_free((void **)&segment);
|
||||
break;
|
||||
}
|
||||
prev = segment;
|
||||
segment = segment->next;
|
||||
}
|
||||
slapi_unlock_mutex(tconf->repl_lock);
|
||||
}
|
||||
|
||||
TopoReplica *
|
||||
ipa_topo_cfg_replica_new(void)
|
||||
{
|
||||
TopoReplica *topoRepl;
|
||||
topoRepl = (TopoReplica *)slapi_ch_malloc(sizeof(TopoReplica));
|
||||
if (topoRepl) {
|
||||
topoRepl->next = NULL;
|
||||
topoRepl->repl_segments = NULL;
|
||||
topoRepl->repl_root = NULL;
|
||||
topoRepl->shared_config_base = NULL;
|
||||
topoRepl->hosts = NULL;
|
||||
topoRepl->repl_lock = slapi_new_mutex();
|
||||
}
|
||||
return topoRepl;
|
||||
|
||||
}
|
||||
|
||||
int
|
||||
ipa_topo_cfg_replica_add(TopoReplica *tconf)
|
||||
{
|
||||
int rc = 0;
|
||||
slapi_lock_mutex(topo_shared_conf.conf_lock);
|
||||
if (topo_shared_conf.replicas == NULL) {
|
||||
topo_shared_conf.replicas = tconf;
|
||||
} else if (ipa_topo_cfg_replica_find(tconf->repl_root,0)) {
|
||||
/* log error: already exists */
|
||||
rc = -1;
|
||||
} else {
|
||||
tconf->next = topo_shared_conf.replicas;
|
||||
topo_shared_conf.replicas = tconf;
|
||||
}
|
||||
slapi_unlock_mutex(topo_shared_conf.conf_lock);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
void
|
||||
ipa_topo_cfg_replica_del(TopoReplica *tconf)
|
||||
{
|
||||
/* TBD */
|
||||
}
|
||||
|
||||
void
|
||||
ipa_topo_cfg_replica_free(TopoReplica *tconf)
|
||||
{
|
||||
TopoReplicaSegmentList *seg, *seg_next;
|
||||
TopoReplicaHost *host, *host_next;
|
||||
if (tconf) {
|
||||
slapi_destroy_mutex(tconf->repl_lock);
|
||||
slapi_ch_free_string(&tconf->shared_config_base);
|
||||
slapi_ch_free_string(&tconf->repl_root);
|
||||
slapi_sdn_free(&tconf->shared_config_sdn);
|
||||
seg = tconf->repl_segments;
|
||||
while (seg) {
|
||||
seg_next = seg->next;
|
||||
ipa_topo_cfg_segment_free(seg->segm);
|
||||
slapi_ch_free((void **)&seg);
|
||||
seg = seg_next;
|
||||
}
|
||||
host = tconf->hosts;
|
||||
while (host) {
|
||||
host_next = host->next;
|
||||
slapi_ch_free_string(&host->hostname);
|
||||
host = host_next;
|
||||
slapi_ch_free((void **)&host);
|
||||
}
|
||||
slapi_ch_free((void **)&tconf);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
TopoReplica *
|
||||
ipa_topo_cfg_replica_find(char *repl_root, int lock)
|
||||
{
|
||||
TopoReplica *tconf = NULL;
|
||||
|
||||
if (lock) {
|
||||
slapi_lock_mutex(topo_shared_conf.conf_lock);
|
||||
}
|
||||
if (topo_shared_conf.replicas == NULL) goto done;
|
||||
|
||||
tconf = topo_shared_conf.replicas;
|
||||
while (tconf) {
|
||||
if (!strcasecmp(repl_root,tconf->repl_root)) {
|
||||
break;
|
||||
}
|
||||
tconf = tconf->next;
|
||||
}
|
||||
|
||||
done:
|
||||
if (lock) {
|
||||
slapi_unlock_mutex(topo_shared_conf.conf_lock);
|
||||
}
|
||||
return tconf;
|
||||
}
|
313
daemons/ipa-slapi-plugins/topology/topology_init.c
Normal file
313
daemons/ipa-slapi-plugins/topology/topology_init.c
Normal file
@ -0,0 +1,313 @@
|
||||
|
||||
#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)
|
||||
{
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
272
daemons/ipa-slapi-plugins/topology/topology_post.c
Normal file
272
daemons/ipa-slapi-plugins/topology/topology_post.c
Normal file
@ -0,0 +1,272 @@
|
||||
#include "topology.h"
|
||||
|
||||
/*
|
||||
* detect if the plugin should handle this entry and return the entry type
|
||||
*/
|
||||
int
|
||||
ipa_topo_check_entry_type(Slapi_Entry *entry)
|
||||
{
|
||||
int ret = TOPO_IGNORE_ENTRY;
|
||||
Slapi_DN *add_dn = NULL;
|
||||
char **ocs;
|
||||
|
||||
add_dn = slapi_entry_get_sdn(entry);
|
||||
if (slapi_sdn_issuffix(add_dn,ipa_topo_get_plugin_shared_topo_dn())) {
|
||||
/* check if it is a toplogy or a segment */
|
||||
/* check if segment's left or right node is the local server*/
|
||||
int i;
|
||||
ocs = slapi_entry_attr_get_charray(entry,"objectclass");
|
||||
|
||||
for (i=0; ocs && ocs[i]; i++) {
|
||||
if (strcasecmp(ocs[i],"ipaReplTopoConf") == 0) {
|
||||
ret = TOPO_CONFIG_ENTRY;
|
||||
break;
|
||||
} else if (strcasecmp(ocs[i],"ipaReplTopoSegment") == 0) {
|
||||
ret = TOPO_SEGMENT_ENTRY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (slapi_sdn_isparent(ipa_topo_get_plugin_shared_hosts_dn(),add_dn)) {
|
||||
ret = TOPO_HOST_ENTRY;
|
||||
} else if (slapi_sdn_issuffix(add_dn,ipa_topo_get_domain_level_entry_dn())) {
|
||||
ret = TOPO_DOMLEVEL_ENTRY;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
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_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;
|
||||
}
|
||||
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;
|
||||
}
|
458
daemons/ipa-slapi-plugins/topology/topology_pre.c
Normal file
458
daemons/ipa-slapi-plugins/topology/topology_pre.c
Normal file
@ -0,0 +1,458 @@
|
||||
#include "topology.h"
|
||||
|
||||
/* the preoperation plugins check if the managed replication config
|
||||
* is attempted to be directly modified.
|
||||
* This is only allowed for internal operations triggerd by the
|
||||
* topology plugin itself
|
||||
*/
|
||||
|
||||
static int ipa_topo_pre_entry_in_scope(Slapi_PBlock *pb)
|
||||
{
|
||||
Slapi_DN *dn;
|
||||
static Slapi_DN *config_dn = NULL;;
|
||||
|
||||
slapi_pblock_get(pb, SLAPI_TARGET_SDN, &dn);
|
||||
if (config_dn == NULL) {
|
||||
config_dn = slapi_sdn_new_dn_byval("cn=mapping tree,cn=config");
|
||||
/* this rules out entries in regular backends and most of
|
||||
* cn=config entries.
|
||||
*/
|
||||
}
|
||||
return slapi_sdn_issuffix(dn,config_dn);
|
||||
|
||||
}
|
||||
int ipa_topo_is_entry_managed(Slapi_PBlock *pb)
|
||||
{
|
||||
Slapi_Entry *e;
|
||||
char *pi;
|
||||
int op_type;
|
||||
|
||||
if (!ipa_topo_pre_entry_in_scope(pb)) {
|
||||
/* we don't care for general mods, only specific
|
||||
* entries in the mapping tree
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
slapi_pblock_get(pb, SLAPI_OPERATION_TYPE, &op_type);
|
||||
if (op_type == SLAPI_OPERATION_ADD) {
|
||||
slapi_pblock_get(pb, SLAPI_ADD_ENTRY, &e);
|
||||
} else {
|
||||
slapi_pblock_get(pb, SLAPI_ENTRY_PRE_OP, &e);
|
||||
}
|
||||
if (!ipa_topo_util_entry_is_candidate(e)) {
|
||||
/* entry has no objectclass the plugin controls */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
/* last check: is the endpoint of the agreement amanaged host ? */
|
||||
if (ipa_topo_util_target_is_managed(e)) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
int
|
||||
ipa_topo_is_modattr_restricted(Slapi_PBlock *pb)
|
||||
{
|
||||
LDAPMod **mods;
|
||||
int i;
|
||||
int rc = 0;
|
||||
|
||||
slapi_pblock_get(pb, SLAPI_MODIFY_MODS, &mods);
|
||||
for (i = 0; (mods != NULL) && (mods[i] != NULL); i++) {
|
||||
if (ipa_topo_cfg_attr_is_restricted(mods[i]->mod_type)) {
|
||||
rc = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* connectivity check for topology
|
||||
* checks if the nodes of a segment would still be connected after
|
||||
* removal of the segments.
|
||||
* For description of the algorithm see design page
|
||||
*/
|
||||
struct node_list {
|
||||
struct node_list *next;
|
||||
char *node;
|
||||
};
|
||||
|
||||
struct node_fanout {
|
||||
struct node_fanout *next;
|
||||
char *node;
|
||||
struct node_list *targets;
|
||||
int visited;
|
||||
};
|
||||
struct node_list *
|
||||
node_list_dup (struct node_list *orig)
|
||||
{
|
||||
struct node_list *dup = NULL;
|
||||
struct node_list *cursor = orig;
|
||||
struct node_list *start_dup = NULL;
|
||||
while (cursor) {
|
||||
if (dup) {
|
||||
dup->next = (struct node_list *)slapi_ch_malloc(sizeof(struct node_list));
|
||||
dup = dup->next;
|
||||
} else {
|
||||
dup = (struct node_list *)slapi_ch_malloc(sizeof(struct node_list));
|
||||
start_dup = dup;
|
||||
}
|
||||
dup->next = NULL;
|
||||
dup->node = slapi_ch_strdup(cursor->node);
|
||||
cursor = cursor->next;
|
||||
}
|
||||
return start_dup;
|
||||
}
|
||||
|
||||
void
|
||||
node_list_free(struct node_list *orig)
|
||||
{
|
||||
struct node_list *cursor = orig;
|
||||
struct node_list *cur_next = NULL;
|
||||
while (cursor) {
|
||||
cur_next = cursor->next;
|
||||
slapi_ch_free_string(&cursor->node);
|
||||
slapi_ch_free((void **)&cursor);
|
||||
cursor = cur_next;
|
||||
}
|
||||
}
|
||||
|
||||
struct node_fanout *
|
||||
ipa_topo_connection_fanout_new (char *from, char *to)
|
||||
{
|
||||
struct node_fanout *new_fanout = (struct node_fanout *)
|
||||
slapi_ch_malloc(sizeof(struct node_fanout));
|
||||
struct node_list *targets = (struct node_list *)
|
||||
slapi_ch_malloc(sizeof(struct node_list));
|
||||
targets->next = NULL;
|
||||
targets->node = slapi_ch_strdup(to);
|
||||
new_fanout->next = NULL;
|
||||
new_fanout->node = slapi_ch_strdup(from);
|
||||
new_fanout->targets = targets;
|
||||
new_fanout->visited = 0;
|
||||
return new_fanout;
|
||||
}
|
||||
|
||||
void
|
||||
ipa_topo_connection_fanout_free (struct node_fanout *fanout)
|
||||
{
|
||||
struct node_fanout *cursor = fanout;
|
||||
struct node_fanout *cur_next = NULL;
|
||||
while (cursor) {
|
||||
cur_next = cursor->next;
|
||||
slapi_ch_free_string(&cursor->node);
|
||||
node_list_free(cursor->targets);
|
||||
slapi_ch_free((void **)&cursor);
|
||||
cursor = cur_next;
|
||||
}
|
||||
}
|
||||
|
||||
struct node_fanout *
|
||||
ipa_topo_connection_fanout_extend (struct node_fanout *fanout_in, char *from, char *to)
|
||||
{
|
||||
struct node_fanout *cursor;
|
||||
if (fanout_in == NULL) {
|
||||
/* init fanout */
|
||||
return ipa_topo_connection_fanout_new(from,to);
|
||||
}
|
||||
/* extend existing fanout struct */
|
||||
cursor = fanout_in;
|
||||
while (cursor) {
|
||||
if (strcasecmp(cursor->node, from) == 0) break;
|
||||
cursor = cursor->next;
|
||||
}
|
||||
if (cursor) {
|
||||
struct node_list *target = (struct node_list *)
|
||||
slapi_ch_malloc(sizeof(struct node_list));
|
||||
target->next = cursor->targets;
|
||||
target->node = slapi_ch_strdup(to);
|
||||
cursor->targets = target;
|
||||
return fanout_in;
|
||||
} else {
|
||||
cursor = ipa_topo_connection_fanout_new(from,to);
|
||||
cursor->next = fanout_in;
|
||||
return cursor;
|
||||
}
|
||||
}
|
||||
struct node_fanout *
|
||||
ipa_topo_connection_fanout(TopoReplica *tconf, TopoReplicaSegment *tseg)
|
||||
{
|
||||
struct node_fanout *fout = NULL;
|
||||
TopoReplicaSegment *segm;
|
||||
|
||||
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"ipa_topo_connection_fanout for segment: %s\n",tseg->name);
|
||||
/* lock it */
|
||||
TopoReplicaSegmentList *seglist = tconf->repl_segments;
|
||||
while (seglist) {
|
||||
segm = seglist->segm;
|
||||
if (strcasecmp(segm->name, tseg->name)) {
|
||||
if (segm->direct == SEGMENT_LEFT_RIGHT ||
|
||||
segm->direct == SEGMENT_BIDIRECTIONAL ) {
|
||||
fout = ipa_topo_connection_fanout_extend(fout, segm->from, segm->to);
|
||||
}
|
||||
if (segm->direct == SEGMENT_RIGHT_LEFT ||
|
||||
segm->direct == SEGMENT_BIDIRECTIONAL) {
|
||||
fout = ipa_topo_connection_fanout_extend(fout, segm->to, segm->from);
|
||||
}
|
||||
}
|
||||
seglist = seglist->next;
|
||||
}
|
||||
return fout;
|
||||
}
|
||||
|
||||
void
|
||||
ipa_topo_connection_append(struct node_fanout *fanout, struct node_list *reachable)
|
||||
{
|
||||
struct node_fanout *cursor = fanout;
|
||||
|
||||
while (cursor) {
|
||||
if (strcasecmp(reachable->node, cursor->node) == 0 &&
|
||||
cursor->visited == 0) {
|
||||
struct node_list *tail;
|
||||
struct node_list *extend;
|
||||
cursor->visited = 1;
|
||||
extend = node_list_dup(cursor->targets);
|
||||
tail = reachable;
|
||||
while (tail->next) {
|
||||
tail = tail->next;
|
||||
}
|
||||
tail->next = extend;
|
||||
break;
|
||||
}
|
||||
cursor = cursor->next;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ipa_topo_connection_exists(struct node_fanout *fanout, char* from, char *to)
|
||||
{
|
||||
struct node_list *reachable = NULL;
|
||||
struct node_fanout *cursor = fanout;
|
||||
int connected = 0;
|
||||
/* init reachable nodes */
|
||||
while (cursor) {
|
||||
if (strcasecmp(cursor->node, from) == 0) {
|
||||
cursor->visited = 1;
|
||||
reachable = node_list_dup(cursor->targets);
|
||||
} else {
|
||||
cursor->visited = 0;
|
||||
}
|
||||
cursor = cursor->next;
|
||||
}
|
||||
/* check if target is in reachable nodes, if
|
||||
* not, expand reachables
|
||||
*/
|
||||
if (reachable == NULL) return 0;
|
||||
while (reachable) {
|
||||
if (strcasecmp(reachable->node, to) == 0) {
|
||||
connected = 1;
|
||||
break;
|
||||
}
|
||||
ipa_topo_connection_append(fanout, reachable);
|
||||
reachable = reachable->next;
|
||||
}
|
||||
node_list_free(reachable);
|
||||
return connected;
|
||||
}
|
||||
|
||||
int
|
||||
ipa_topo_check_connect_reject(Slapi_PBlock *pb)
|
||||
{
|
||||
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_DELETE_EXISTING_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
|
||||
*/
|
||||
TopoReplicaSegment *tsegm;
|
||||
TopoReplica *tconf = ipa_topo_util_get_conf_for_segment(add_entry);
|
||||
tsegm = ipa_topo_util_find_segment(tconf, add_entry);
|
||||
if (tsegm) {
|
||||
slapi_log_error(SLAPI_LOG_FATAL, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"segment to be added does already exist\n");
|
||||
rc = 1;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
ipa_topo_check_disconnect_reject(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);
|
||||
TopoReplicaSegment *tsegm;
|
||||
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;
|
||||
}
|
||||
/* 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;
|
||||
}
|
||||
|
||||
static int
|
||||
ipa_topo_pre_ignore_op(Slapi_PBlock *pb)
|
||||
{
|
||||
int repl_op = 0;
|
||||
/* changes to cn=config aren't replicated, for changes to
|
||||
* shared topology area checks have been done on master
|
||||
* accepting the operation
|
||||
*/
|
||||
slapi_pblock_get (pb, SLAPI_IS_REPLICATED_OPERATION, &repl_op);
|
||||
return repl_op;
|
||||
}
|
||||
|
||||
int ipa_topo_pre_add(Slapi_PBlock *pb)
|
||||
{
|
||||
int result = SLAPI_PLUGIN_SUCCESS;
|
||||
|
||||
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"--> ipa_topo_pre_add\n");
|
||||
|
||||
if (0 == ipa_topo_get_plugin_active()) {
|
||||
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"<-- ipa_topo_pre_add - plugin not active\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ipa_topo_pre_ignore_op(pb)) return result;
|
||||
|
||||
if (ipa_topo_is_entry_managed(pb)) {
|
||||
int rc = LDAP_UNWILLING_TO_PERFORM;
|
||||
char *errtxt;
|
||||
errtxt = slapi_ch_smprintf("Entry is managed by topology plugin."
|
||||
" Adding of entry not allowed.\n");
|
||||
slapi_pblock_set(pb, SLAPI_PB_RESULT_TEXT, errtxt);
|
||||
slapi_pblock_set(pb, SLAPI_RESULT_CODE, &rc);
|
||||
result = SLAPI_PLUGIN_FAILURE;
|
||||
} else if (ipa_topo_check_connect_reject(pb)) {
|
||||
int rc = LDAP_UNWILLING_TO_PERFORM;
|
||||
char *errtxt;
|
||||
errtxt = slapi_ch_smprintf("Segment already exists in topology."
|
||||
"Add rejected.\n");
|
||||
slapi_pblock_set(pb, SLAPI_PB_RESULT_TEXT, errtxt);
|
||||
slapi_pblock_set(pb, SLAPI_RESULT_CODE, &rc);
|
||||
result = SLAPI_PLUGIN_FAILURE;
|
||||
}
|
||||
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"<-- ipa_topo_pre_add\n");
|
||||
return result;
|
||||
}
|
||||
int
|
||||
ipa_topo_pre_mod(Slapi_PBlock *pb)
|
||||
{
|
||||
|
||||
int result = SLAPI_PLUGIN_SUCCESS;
|
||||
|
||||
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"--> ipa_topo_pre_mod\n");
|
||||
|
||||
if (0 == ipa_topo_get_plugin_active()) {
|
||||
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"<-- ipa_topo_pre_mod - plugin not active\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ipa_topo_pre_ignore_op(pb)) return result;
|
||||
|
||||
if (ipa_topo_is_entry_managed(pb) && ipa_topo_is_modattr_restricted(pb)) {
|
||||
int rc = LDAP_UNWILLING_TO_PERFORM;
|
||||
char *errtxt;
|
||||
errtxt = slapi_ch_smprintf("Entry and attributes are managed by topology plugin."
|
||||
"No direct modifications allowed.\n");
|
||||
slapi_pblock_set(pb, SLAPI_PB_RESULT_TEXT, errtxt);
|
||||
slapi_pblock_set(pb, SLAPI_RESULT_CODE, &rc);
|
||||
result = SLAPI_PLUGIN_FAILURE;
|
||||
}
|
||||
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"<-- ipa_topo_pre_mod\n");
|
||||
return result;
|
||||
}
|
||||
|
||||
int
|
||||
ipa_topo_pre_del(Slapi_PBlock *pb)
|
||||
{
|
||||
int result = SLAPI_PLUGIN_SUCCESS;
|
||||
|
||||
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"--> ipa_topo_pre_del\n");
|
||||
|
||||
if (0 == ipa_topo_get_plugin_active()) {
|
||||
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"<-- ipa_topo_pre_del - plugin not active\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (ipa_topo_pre_ignore_op(pb)) return result;
|
||||
|
||||
if (ipa_topo_is_entry_managed(pb)) {
|
||||
int rc = LDAP_UNWILLING_TO_PERFORM;
|
||||
char *errtxt;
|
||||
errtxt = slapi_ch_smprintf("Entry is managed by topology plugin."
|
||||
"Deletion not allowed.\n");
|
||||
slapi_pblock_set(pb, SLAPI_PB_RESULT_TEXT, errtxt);
|
||||
slapi_pblock_set(pb, SLAPI_RESULT_CODE, &rc);
|
||||
result = SLAPI_PLUGIN_FAILURE;
|
||||
} else if (ipa_topo_check_disconnect_reject(pb)) {
|
||||
int rc = LDAP_UNWILLING_TO_PERFORM;
|
||||
char *errtxt;
|
||||
errtxt = slapi_ch_smprintf("Removal of Segment disconnects topology."
|
||||
"Deletion not allowed.\n");
|
||||
slapi_pblock_set(pb, SLAPI_PB_RESULT_TEXT, errtxt);
|
||||
slapi_pblock_set(pb, SLAPI_RESULT_CODE, &rc);
|
||||
result = SLAPI_PLUGIN_FAILURE;
|
||||
}
|
||||
slapi_log_error(SLAPI_LOG_PLUGIN, IPA_TOPO_PLUGIN_SUBSYSTEM,
|
||||
"<-- ipa_topo_pre_del\n");
|
||||
return result;
|
||||
}
|
1441
daemons/ipa-slapi-plugins/topology/topology_util.c
Normal file
1441
daemons/ipa-slapi-plugins/topology/topology_util.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -405,6 +405,7 @@ rm %{buildroot}/%{plugin_dir}/libipa_extdom_extop.la
|
||||
rm %{buildroot}/%{plugin_dir}/libipa_range_check.la
|
||||
rm %{buildroot}/%{plugin_dir}/libipa_otp_counter.la
|
||||
rm %{buildroot}/%{plugin_dir}/libipa_otp_lasttoken.la
|
||||
rm %{buildroot}/%{plugin_dir}/libtopology.la
|
||||
rm %{buildroot}/%{_libdir}/krb5/plugins/kdb/ipadb.la
|
||||
rm %{buildroot}/%{_libdir}/samba/pdb/ipasam.la
|
||||
|
||||
@ -798,6 +799,7 @@ fi
|
||||
%attr(755,root,root) %{plugin_dir}/libipa_range_check.so
|
||||
%attr(755,root,root) %{plugin_dir}/libipa_otp_counter.so
|
||||
%attr(755,root,root) %{plugin_dir}/libipa_otp_lasttoken.so
|
||||
%attr(755,root,root) %{plugin_dir}/libtopology.so
|
||||
%dir %{_localstatedir}/lib/ipa
|
||||
%attr(700,root,root) %dir %{_localstatedir}/lib/ipa/backup
|
||||
%attr(700,root,root) %dir %{_localstatedir}/lib/ipa/sysrestore
|
||||
|
15
install/share/70topology.ldif
Normal file
15
install/share/70topology.ldif
Normal file
@ -0,0 +1,15 @@
|
||||
# IPA Topology Plugin schema
|
||||
# BaseOID: 2.16.840.1.113730.3.8.20
|
||||
dn: cn=schema
|
||||
attributetypes: ( 2.16.840.1.113730.3.8.20.2.1 NAME 'ipaReplTopoConfRoot' DESC 'IPA defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'FreeIPA' )
|
||||
attributetypes: ( 2.16.840.1.113730.3.8.20.2.2 NAME 'ipaReplTopoSegmentDirection' DESC 'IPA defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'FreeIPA' )
|
||||
attributetypes: ( 2.16.840.1.113730.3.8.20.2.3 NAME 'ipaReplTopoSegmentLeftNode' DESC 'IPA defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'FreeIPA' )
|
||||
attributetypes: ( 2.16.840.1.113730.3.8.20.2.4 NAME 'ipaReplTopoSegmentRightNode' DESC 'IPA defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'FreeIPA' )
|
||||
attributetypes: ( 2.16.840.1.113730.3.8.20.2.5 NAME 'ipaReplTopoSegmentStatus' DESC 'IPA defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'FreeIPA' )
|
||||
attributetypes: ( 2.16.840.1.113730.3.8.20.2.6 NAME 'ipaReplTopoSegmentGenerated' DESC 'IPA defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'FreeIPA' )
|
||||
attributetypes: ( 2.16.840.1.113730.3.8.20.2.7 NAME 'ipaReplTopoManagedAgreementState' DESC 'IPA defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'FreeIPA' )
|
||||
attributetypes: ( 2.16.840.1.113730.3.8.20.2.8 NAME 'ipaReplTopoManagedSuffix' DESC 'IPA defined attribute type' SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'FreeIPA' )
|
||||
objectclasses: ( 2.16.840.1.113730.3.8.20.1.1 NAME 'ipaReplTopoConf' DESC 'IPA defined objectclass' SUP top STRUCTURAL MUST ipaReplTopoConfRoot MAY ( cn $ nsDS5ReplicaRoot $ nsDS5ReplicatedAttributeList $ nsDS5ReplicatedAttributeListTotal ) X-ORIGIN 'Free IPA' )
|
||||
objectclasses: ( 2.16.840.1.113730.3.8.20.1.2 NAME 'ipaReplTopoSegment' DESC 'IPA defined objectclass' SUP top STRUCTURAL MUST ( ipaReplTopoSegmentDirection $ ipaReplTopoSegmentLeftNode $ ipaReplTopoSegmentRightNode) MAY ( cn $ ipaReplTopoSegmentStatus $ ipaReplTopoSegmentGenerated $ nsDS5ReplicatedAttributeList $ nsDS5ReplicatedAttributeListTotal $ nsds5BeginReplicaRefresh $ description $ nsds5replicaTimeout $ nsds5ReplicaEnabled $ nsds5ReplicaStripAttrs $ nsds5replicaSessionPauseTime $ nsds5ReplicaProtocolTimeout ) X-ORIGIN 'Free IPA' )
|
||||
objectclasses: ( 2.16.840.1.113730.3.8.20.1.3 NAME 'ipaReplTopoManagedAgreement' DESC 'marker objectclass for managed replication agreements' SUP top AUXILIARY MAY ( ipaReplTopoManagedAgreementState ) X-ORIGIN 'Free IPA' )
|
||||
objectclasses: ( 2.16.840.1.113730.3.8.20.1.4 NAME 'ipaReplTopoManagedServer' DESC 'part of managed replication topology' SUP top AUXILIARY MAY ( ipaReplTopoManagedSuffix ) X-ORIGIN 'Free IPA' )
|
@ -20,6 +20,7 @@ app_DATA = \
|
||||
65ipacertstore.ldif \
|
||||
65ipasudo.ldif \
|
||||
70ipaotp.ldif \
|
||||
70topology.ldif \
|
||||
71idviews.ldif \
|
||||
anonymous-vlv.ldif \
|
||||
bootstrap-template.ldif \
|
||||
|
Loading…
Reference in New Issue
Block a user