1
0
Эх сурвалжийг харах

Ticket 47779 - Part of DNA shared configuration is deleted after server restart

Bug Description:  After a configuration change, like updating dnaNextVal,
                  the shared config entries are always rebuilt, but they do
                  preserve some of the configuration attributes like dnaRemoteBindMethod.

Fix Description:  Maintain a global linked list of all the shared config entries,
                  so when we go to rebuild the shared config entry we can restore
                  the dnaRemote attributes.

https://fedorahosted.org/389/ticket/47779

Reviewed by: nhosoi(Thanks!)
Mark Reynolds 11 жил өмнө
parent
commit
06a3d0a1a2
1 өөрчлөгдсөн 208 нэмэгдсэн , 10 устгасан
  1. 208 10
      ldap/servers/plugins/dna/dna.c

+ 208 - 10
ldap/servers/plugins/dna/dna.c

@@ -101,6 +101,7 @@
 #define DNA_HOSTNAME           "dnaHostname"
 #define DNA_PORTNUM            "dnaPortNum"
 #define DNA_SECURE_PORTNUM     "dnaSecurePortNum"
+#define DNA_REMOTE_BUFSIZ      15 /* max size for bind method & protocol */
 #define DNA_REMOTE_BIND_METHOD "dnaRemoteBindMethod"
 #define DNA_REMOTE_CONN_PROT   "dnaRemoteConnProtocol"
 
@@ -191,6 +192,9 @@ struct configEntry {
 static PRCList *dna_global_config = NULL;
 static Slapi_RWLock *g_dna_cache_lock;
 
+static struct dnaServer *dna_global_servers = NULL;
+static Slapi_RWLock *g_dna_cache_server_lock;
+
 static void *_PluginID = NULL;
 static const char *_PluginDN = NULL;
 
@@ -204,6 +208,7 @@ static char *secureportnum = NULL;
  */
 struct dnaServer {
     PRCList list;
+    Slapi_DN *sdn;
     char *host;
     unsigned int port;
     unsigned int secureport;
@@ -214,6 +219,7 @@ struct dnaServer {
     char *remote_conn_prot;
     char *remote_binddn; /* contains pointer to main config binddn */
     char *remote_bindpw; /* contains pointer to main config bindpw */
+    struct dnaServer *next; /* used for the global server list */
 };
 
 static char *dna_extend_exop_oid_list[] = {
@@ -262,7 +268,7 @@ static void dna_notice_allocation(struct configEntry *config_entry,
                                   PRUint64 new, PRUint64 last);
 static int dna_update_shared_config(struct configEntry * config_entry);
 static void dna_update_config_event(time_t event_time, void *arg);
-static int dna_get_shared_servers(struct configEntry *config_entry, PRCList **servers);
+static int dna_get_shared_servers(struct configEntry *config_entry, PRCList **servers, int get_all);
 static void dna_free_shared_server(struct dnaServer **server);
 static void dna_delete_shared_servers(PRCList **servers);
 static int dna_release_range(char *range_dn, PRUint64 *lower, PRUint64 *upper);
@@ -285,6 +291,9 @@ static void dna_create_valcheck_filter(struct configEntry *config_entry, PRUint6
 static int dna_isrepl(Slapi_PBlock *pb);
 static int dna_get_remote_config_info( struct dnaServer *server, char **bind_dn, char **bind_passwd,
                                        char **bind_method, int *is_ssl, int *port);
+static int dna_load_shared_servers();
+static void dna_delete_global_servers();
+static int dna_get_shared_config_attr_val(struct configEntry *config_entry, char *attr, char *value);
 
 /**
  *
@@ -338,6 +347,21 @@ void dna_unlock()
     slapi_rwlock_unlock(g_dna_cache_lock);
 }
 
+void dna_server_read_lock()
+{
+    slapi_rwlock_rdlock(g_dna_cache_server_lock);
+}
+
+void dna_server_write_lock()
+{
+    slapi_rwlock_wrlock(g_dna_cache_server_lock);
+}
+
+void dna_server_unlock()
+{
+    slapi_rwlock_unlock(g_dna_cache_server_lock);
+}
+
 /**
  *
  * Get the dna plug-in version
@@ -546,11 +570,16 @@ dna_start(Slapi_PBlock * pb)
                     "--> dna_start\n");
 
     g_dna_cache_lock = slapi_new_rwlock();
-
     if (!g_dna_cache_lock) {
         slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
-                        "dna_start: lock creation failed\n");
+                        "dna_start: global config lock creation failed\n");
+        return DNA_FAILURE;
+    }
 
+    g_dna_cache_server_lock = slapi_new_rwlock();
+    if (!g_dna_cache_server_lock) {
+        slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
+                        "dna_start: global server lock creation failed\n");
         return DNA_FAILURE;
     }
 
@@ -594,6 +623,15 @@ dna_start(Slapi_PBlock * pb)
         return DNA_FAILURE;
     }
 
+    /*
+     * Load all shared server configs
+     */
+    if (dna_load_shared_servers() ) {
+        slapi_log_error(SLAPI_LOG_FATAL, DNA_PLUGIN_SUBSYSTEM,
+                        "dna_start: shared config server initialization failed.\n");
+        return DNA_FAILURE;
+    }
+
     slapi_log_error(SLAPI_LOG_PLUGIN, DNA_PLUGIN_SUBSYSTEM,
                     "dna: ready for service\n");
     slapi_log_error(SLAPI_LOG_TRACE, DNA_PLUGIN_SUBSYSTEM,
@@ -618,6 +656,10 @@ dna_close(Slapi_PBlock * pb)
     slapi_destroy_rwlock(g_dna_cache_lock);
     g_dna_cache_lock = NULL;
 
+    dna_delete_global_servers();
+    slapi_destroy_rwlock(g_dna_cache_server_lock);
+    g_dna_cache_server_lock = NULL;
+
     slapi_ch_free_string(&hostname);
     slapi_ch_free_string(&portnum);
     slapi_ch_free_string(&secureportnum);
@@ -628,6 +670,82 @@ dna_close(Slapi_PBlock * pb)
     return DNA_SUCCESS;
 }
 
+/*
+ * Free the global linkedl ist of shared servers
+ */
+static void
+dna_delete_global_servers()
+{
+    struct dnaServer *server, *next;
+
+    if(dna_global_servers){
+        server = dna_global_servers;
+        while(server){
+            next = server->next;
+            dna_free_shared_server(&server);
+            server = next;
+        }
+        dna_global_servers = NULL;
+    }
+}
+
+/*
+ * Look through the global config entries, and build a global
+ * shared server config list.
+ */
+static int
+dna_load_shared_servers()
+{
+    struct configEntry *config_entry = NULL;
+    struct dnaServer *server = NULL, *global_servers = NULL;
+    PRCList *server_list = NULL;
+    PRCList *config_list = NULL;
+    int ret = 0;
+
+    /* First free the existing list. */
+    dna_delete_global_servers();
+
+    /* Now build the new list. */
+    dna_write_lock();
+    if (!PR_CLIST_IS_EMPTY(dna_global_config)) {
+        config_list = PR_LIST_HEAD(dna_global_config);
+        while (config_list != dna_global_config) {
+            PRCList *shared_list = NULL;
+            config_entry = (struct configEntry *) config_list;
+
+            if(dna_get_shared_servers(config_entry,
+                                      &shared_list,
+                                      1 /* get all the servers */))
+            {
+                dna_unlock();
+                return -1;
+            }
+
+            dna_server_write_lock();
+            if (shared_list) {
+                server_list = PR_LIST_HEAD(shared_list);
+                while (server_list != shared_list) {
+                    server = (struct dnaServer *)server_list;
+                    if(global_servers == NULL){
+                        dna_global_servers = global_servers = server;
+                    } else {
+                        global_servers->next = server;
+                        global_servers = server;
+                    }
+                    server_list = PR_NEXT_LINK(server_list);
+                }
+                slapi_ch_free((void **)&shared_list);
+            }
+            dna_server_unlock();
+
+            config_list = PR_NEXT_LINK(config_list);
+        }
+    }
+    dna_unlock();
+
+    return ret;
+}
+
 /*
  * config looks like this
  * - cn=myplugin
@@ -1233,6 +1351,7 @@ dna_free_shared_server(struct dnaServer **server)
         return;
     }
     s = *server;
+    slapi_sdn_free(&s->sdn);
     slapi_ch_free_string(&s->host);
     slapi_ch_free_string(&s->remote_bind_method);
     slapi_ch_free_string(&s->remote_conn_prot);
@@ -1330,6 +1449,7 @@ dna_update_config_event(time_t event_time, void *arg)
                 Slapi_PBlock *dna_pb = NULL;
                 Slapi_DN *sdn = slapi_sdn_new_normdn_byref(config_entry->shared_cfg_dn);
                 Slapi_Backend *be = slapi_be_select(sdn);
+
                 slapi_sdn_free(&sdn);
                 if (be) {
                     dna_pb = slapi_pblock_new();
@@ -1416,7 +1536,7 @@ static int dna_fix_maxval(struct configEntry *config_entry,
     } else if (!skip_range_request && config_entry->shared_cfg_base) {
         /* Find out if there are any other servers to request
          * range from. */
-        dna_get_shared_servers(config_entry, &servers);
+        dna_get_shared_servers(config_entry, &servers, 0 );
 
         if (servers) {
             /* We have other servers we can try to extend
@@ -1506,7 +1626,7 @@ dna_notice_allocation(struct configEntry *config_entry, PRUint64 new,
 }
 
 static int
-dna_get_shared_servers(struct configEntry *config_entry, PRCList **servers)
+dna_get_shared_servers(struct configEntry *config_entry, PRCList **servers, int get_all)
 {
     int ret = LDAP_SUCCESS;
     Slapi_PBlock *pb = NULL;
@@ -1556,13 +1676,14 @@ dna_get_shared_servers(struct configEntry *config_entry, PRCList **servers)
         /* We found some entries.  Go through them and
          * order them based off of remaining values. */
         for (i = 0; entries[i]; i++) {
-            /* skip our own shared config entry */
-            if (slapi_sdn_compare(cfg_sdn, slapi_entry_get_sdn(entries[i]))) {
+            /* skip our own shared config entry, unless we want all the servers */
+            if (get_all || slapi_sdn_compare(cfg_sdn, slapi_entry_get_sdn(entries[i]))) {
                 struct dnaServer *server = NULL;
 
                 /* set up the server list entry */
                 server = (struct dnaServer *) slapi_ch_calloc(1,
                          sizeof(struct dnaServer));
+                server->sdn = slapi_sdn_new_dn_byval(slapi_entry_get_ndn(entries[i]));
                 server->host = slapi_entry_attr_get_charptr(entries[i],
                                                             DNA_HOSTNAME);
                 server->port = slapi_entry_attr_get_uint(entries[i], DNA_PORTNUM);
@@ -1631,7 +1752,7 @@ dna_get_shared_servers(struct configEntry *config_entry, PRCList **servers)
                 } else {
                     /* Find the right slot for this entry. We
                      * want to order the entries based off of
-                     * the remaining number of values, higest
+                     * the remaining number of values, highest
                      * to lowest. */
                     struct dnaServer *sitem;
                     PRCList* item = PR_LIST_HEAD(*servers);
@@ -1908,6 +2029,36 @@ static int dna_dn_is_config(char *dn)
     return ret;
 }
 
+static int
+dna_dn_is_shared_config(Slapi_PBlock *pb, char *dn)
+{
+    struct configEntry *config_entry = NULL;
+    Slapi_Entry *entry = NULL;
+    Slapi_Attr *attr = NULL;
+    PRCList *list = NULL;
+    int ret = 0;
+
+    dna_read_lock();
+    if (!PR_CLIST_IS_EMPTY(dna_global_config)) {
+        list = PR_LIST_HEAD(dna_global_config);
+        while (list != dna_global_config) {
+            config_entry = (struct configEntry *) list;
+            if (slapi_dn_issuffix(dn, config_entry->shared_cfg_base)) {
+                slapi_pblock_get(pb, SLAPI_ENTRY_POST_OP, &entry);
+                /* If the entry has the dnaHost attribute, it is a shared entry */
+                if (slapi_entry_attr_find(entry, DNA_HOSTNAME, &attr) == 0) {
+                    ret = 1;
+                    break;
+                }
+            }
+            list = PR_NEXT_LINK(list);
+        }
+    }
+    dna_unlock();
+
+    return ret;
+}
+
 #define DNA_LDAP_TAG_SK_REVERSE 0x81L
 
 static LDAPControl *dna_build_sort_control(const char *attr)
@@ -2235,6 +2386,39 @@ static int dna_get_next_value(struct configEntry *config_entry,
     return ret;
 }
 
+/*
+ * Get a value from the global server list.  The dna_server_read_lock()
+ * should be held prior to calling this function.
+ */
+static int
+dna_get_shared_config_attr_val(struct configEntry *config_entry, char *attr, char *value)
+{
+    struct dnaServer *server = NULL;
+    Slapi_DN *server_sdn = NULL;
+    int found = 0;
+
+    server_sdn = slapi_sdn_new_dn_byref(config_entry->shared_cfg_dn);
+    if (dna_global_servers) {
+        server = dna_global_servers;
+        while (server) {
+            if(slapi_sdn_compare(server->sdn, server_sdn) == 0){
+                if(strcmp(attr, DNA_REMOTE_BIND_METHOD) == 0){
+                    PR_snprintf(value, DNA_REMOTE_BUFSIZ, "%s", server->remote_bind_method);
+                    found = 1;
+                    break;
+                } else if(strcmp(attr, DNA_REMOTE_CONN_PROT) == 0){
+                    PR_snprintf(value, DNA_REMOTE_BUFSIZ, "%s", server->remote_conn_prot);
+                    found = 1;
+                    break;
+                }
+            }
+            server = server->next;
+        }
+    }
+    slapi_sdn_free(&server_sdn);
+
+    return found;
+}
 /*
  * dna_update_shared_config()
  *
@@ -2287,8 +2471,9 @@ dna_update_shared_config(struct configEntry * config_entry)
              * already exist, we add it. */
             if (ret == LDAP_NO_SUCH_OBJECT) {
                 Slapi_Entry *e = NULL;
-                Slapi_DN *sdn = 
-                        slapi_sdn_new_normdn_byref(config_entry->shared_cfg_dn);
+                Slapi_DN *sdn = slapi_sdn_new_normdn_byref(config_entry->shared_cfg_dn);
+                char bind_meth[DNA_REMOTE_BUFSIZ];
+                char conn_prot[DNA_REMOTE_BUFSIZ];
 
                 /* Set up the new shared config entry */
                 e = slapi_entry_alloc();
@@ -2304,6 +2489,16 @@ dna_update_shared_config(struct configEntry * config_entry)
                 }
                 slapi_entry_add_string(e, DNA_REMAINING, remaining_vals);
 
+                /* Grab the remote server settings */
+                dna_server_read_lock();
+                if(dna_get_shared_config_attr_val(config_entry, DNA_REMOTE_BIND_METHOD, bind_meth)) {
+                    slapi_entry_add_string(e, DNA_REMOTE_BIND_METHOD, bind_meth);
+                }
+                if(dna_get_shared_config_attr_val(config_entry, DNA_REMOTE_CONN_PROT, conn_prot)){
+                    slapi_entry_add_string(e, DNA_REMOTE_CONN_PROT,conn_prot);
+                }
+                dna_server_unlock();
+
                 /* clear pb for re-use */
                 slapi_pblock_init(pb);
 
@@ -3893,6 +4088,9 @@ static int dna_config_check_post_op(Slapi_PBlock * pb)
             if (dna_dn_is_config(dn)) {
                 dna_load_plugin_config(pb, 0);
             }
+            if(dna_dn_is_shared_config(pb, dn) == 0){
+                dna_load_shared_servers();
+            }
         }
     }