ITS#10265 Allow runtime reconfig of olcBkLloadListen

This commit is contained in:
Ondřej Kuzník 2024-08-14 10:57:42 +01:00 committed by Quanah Gibson-Mount
parent f2cba910d8
commit 89e34fded3
8 changed files with 699 additions and 637 deletions

View file

@ -538,7 +538,7 @@ fail:
LloadConnection *
client_init(
ber_socket_t s,
struct berval *localname,
LloadListenerSocket *ls,
struct berval *peername,
struct event_base *base,
int flags )
@ -549,7 +549,7 @@ client_init(
write_cb = connection_write_cb;
if ( (c = lload_connection_init(
s, localname, peername, flags )) == NULL ) {
s, &ls->ls_name, peername, flags )) == NULL ) {
return NULL;
}
@ -559,6 +559,7 @@ client_init(
}
c->c_state = LLOAD_C_READY;
c->c_listener = ls;
if ( flags & CONN_IS_TLS ) {
#ifdef HAVE_TLS

View file

@ -276,7 +276,7 @@ static ConfigTable config_back_cf_table[] = {
"( OLcfgBkAt:13.5 "
"NAME 'olcBkLloadListen' "
"DESC 'A listener adress' "
/* We don't handle adding/removing a value, so no EQUALITY yet */
"EQUALITY caseExactMatch "
"SYNTAX OMsDirectoryString )",
NULL, NULL
},
@ -800,7 +800,6 @@ static ConfigOCs lloadocs[] = {
"SUP olcBackendConfig "
"MUST ( olcBkLloadBindconf "
"$ olcBkLloadIOThreads "
"$ olcBkLloadListen "
"$ olcBkLloadSockbufMaxClient "
"$ olcBkLloadSockbufMaxUpstream "
"$ olcBkLloadMaxPDUPerCycle "
@ -824,6 +823,7 @@ static ConfigOCs lloadocs[] = {
"$ olcBkLloadWriteCoherence "
"$ olcBkLloadRestrictExop "
"$ olcBkLloadRestrictControl "
"$ olcBkLloadListen "
") )",
Cft_Backend, config_back_cf_table,
NULL,
@ -884,12 +884,6 @@ config_generic( ConfigArgs *c )
struct berval bv = BER_BVNULL;
for ( ; ll && *ll; ll++ ) {
/* The same url could have spawned several consecutive
* listeners */
if ( !BER_BVISNULL( &bv ) &&
!ber_bvcmp( &bv, &(*ll)->sl_url ) ) {
continue;
}
ber_dupbv( &bv, &(*ll)->sl_url );
ber_bvarray_add( &c->rvalue_vals, &bv );
}
@ -918,8 +912,47 @@ config_generic( ConfigArgs *c )
} else if ( c->op == LDAP_MOD_DELETE ) {
/* We only need to worry about deletions to multi-value or MAY
* attributes that belong to the lloadd module - we don't have any at
* the moment */
* attributes that belong to the lloadd module */
switch ( c->type ) {
case CFG_LISTEN_URI: {
LloadListener **ll = lloadd_get_listeners();
int i;
lload_change.type = LLOAD_CHANGE_MODIFY;
lload_change.object = LLOAD_DAEMON;
lload_change.flags.daemon |= LLOAD_DAEMON_MOD_LISTENER;
/*
* Be as non-destructive as possible, the modify could be
* aborted later and if we can't open the socket again, the
* only alternative would be to stop the server.
*
* This prohibits changes where exchanging urls that aren't the
* same but overlap. People can always split them into multiple
* operations - make simple things easy and complex possible I
* guess?
*/
if ( c->valx == -1 ) {
for ( i = 0; ll[i]; i++ ) {
ll[i]->sl_removed = 1;
}
} else {
/* We don't keep listeners in the same order, need to check
* which one it is */
struct berval bv;
ber_str2bv( c->line, 0, 0, &bv );
for ( i = 0; ll[i]; i++ ) {
if ( ber_bvcmp( &ll[i]->sl_url, &bv ) == 0 ) break;
}
assert( ll[i] && !ll[i]->sl_removed );
ll[i]->sl_removed = 1;
}
} break;
default:
break;
}
return rc;
}
@ -948,7 +981,10 @@ config_generic( ConfigArgs *c )
break;
case CFG_LISTEN_URI: {
LDAPURLDesc *lud;
LloadListener *l;
LloadListener *l, **ll;
struct berval bv;
ber_str2bv( c->line, 0, 0, &bv );
if ( ldap_url_parse_ext(
c->line, &lud, LDAP_PVT_URL_PARSE_DEF_PORT ) ) {
@ -964,21 +1000,29 @@ config_generic( ConfigArgs *c )
"Load Balancer already configured to listen on %s "
"(while adding %s)",
l->sl_url.bv_val, c->line );
ldap_free_urldesc( lud );
goto fail;
}
if ( !lloadd_inited ) {
if ( lload_open_new_listener( c->line, lud ) ) {
snprintf( c->cr_msg, sizeof(c->cr_msg),
"could not open a listener for %s", c->line );
goto fail;
}
} else {
ll = lloadd_get_listeners();
for ( ; ll && *ll; ll++ ) {
if ( !(*ll)->sl_removed ||
ber_bvcmp( &(*ll)->sl_url, &bv ) ) continue;
/* Restoring a removed listener URL */
(*ll)->sl_removed = 0;
break;
}
l = lload_configure_listener( c->line, lud );
if ( !l ) {
snprintf( c->cr_msg, sizeof(c->cr_msg),
"listener changes will not take effect until restart: "
"%s",
c->line );
Debug( LDAP_DEBUG_ANY, "%s: %s\n", c->log, c->cr_msg );
"could not configure a listener for %s", c->line );
goto fail;
}
if ( lload_open_new_listener( l ) ) {
snprintf( c->cr_msg, sizeof(c->cr_msg),
"could not open a listener for %s", c->line );
goto fail;
}
} break;
case CFG_THREADS:

File diff suppressed because it is too large Load diff

View file

@ -104,6 +104,8 @@ typedef struct LloadPendingConnection LloadPendingConnection;
typedef struct LloadConnection LloadConnection;
typedef struct LloadOperation LloadOperation;
typedef struct LloadChange LloadChange;
typedef struct LloadListenerSocket LloadListenerSocket;
typedef struct LloadListener LloadListener;
/* end of forward declarations */
typedef LDAP_STAILQ_HEAD(TierSt, LloadTier) lload_t_head;
@ -149,9 +151,8 @@ enum lcf_daemon {
LLOAD_DAEMON_MOD_THREADS = 1 << 0,
LLOAD_DAEMON_MOD_FEATURES = 1 << 1,
LLOAD_DAEMON_MOD_TLS = 1 << 2,
LLOAD_DAEMON_MOD_LISTENER_ADD = 1 << 3,
LLOAD_DAEMON_MOD_LISTENER_REPLACE = 1 << 4,
LLOAD_DAEMON_MOD_BINDCONF = 1 << 5,
LLOAD_DAEMON_MOD_LISTENER = 1 << 3,
LLOAD_DAEMON_MOD_BINDCONF = 1 << 4,
};
enum lcf_tier {
@ -495,6 +496,7 @@ struct LloadConnection {
time_t c_restricted_at;
LloadBackend *c_backend;
LloadConnection *c_linked_upstream;
LloadListenerSocket *c_listener;
TAvlnode *c_linked;
@ -568,23 +570,18 @@ struct restriction_entry {
};
/*
* listener; need to access it from monitor backend
* listener, unlike slapd, we have exactly one per url, then bunch the sockets
* under it
*/
struct LloadListener {
struct berval sl_url;
struct berval sl_name;
mode_t sl_perms;
int sl_removed;
#ifdef HAVE_TLS
int sl_is_tls;
#endif
int sl_is_proxied;
struct event_base *base;
struct evconnlistener *listener;
int sl_mute; /* Listener is temporarily disabled due to emfile */
int sl_busy; /* Listener is busy (accept thread activated) */
ber_socket_t sl_sd;
Sockaddr sl_sa;
#define sl_addr sl_sa.sa_in_addr
LloadListenerSocket *sl_sockets;
#define LDAP_TCP_BUFFER
#ifdef LDAP_TCP_BUFFER
int sl_tcp_rmem; /* custom TCP read buffer size */
@ -592,6 +589,22 @@ struct LloadListener {
#endif
};
struct LloadListenerSocket {
LloadListener *ls_lr;
struct berval ls_name;
struct evconnlistener *listener;
struct event_base *base;
int ls_mute; /* listener is temporarily disabled due to emfile */
ber_socket_t ls_sd;
LloadListenerSocket *ls_next;
Sockaddr ls_sa;
#define ls_addr ls_sa.sa_in_addr
};
typedef int (*CONNCB)( LloadConnection *c, void *arg );
/* config requires a bi_private with configuration data - dummy for now */

View file

@ -827,12 +827,6 @@ unhandled_option:;
slapd_args_file_unlink = 1;
}
/*
* FIXME: moved here from lloadd_daemon_task()
* because back-monitor db_open() needs it
*/
time( &starttime );
Debug( LDAP_DEBUG_ANY, "lloadd starting\n" );
#ifndef HAVE_WINSOCK

View file

@ -106,8 +106,6 @@ lload_back_open( BackendInfo *bi )
return -1;
}
assert( lloadd_get_listeners() );
checked_lock( &lload_wait_mutex );
rc = ldap_pvt_thread_create( &lloadd_main_thread,
0, lload_start_daemon, NULL );

View file

@ -63,7 +63,7 @@ LDAP_SLAPD_F (int) request_process( LloadConnection *c, LloadOperation *op );
LDAP_SLAPD_F (int) handle_one_request( LloadConnection *c );
LDAP_SLAPD_F (void) client_tls_handshake_cb( evutil_socket_t s, short what, void *arg );
LDAP_SLAPD_F (LloadConnection *) client_init( ber_socket_t s,
struct berval *localname,
LloadListenerSocket *ls,
struct berval *peername,
struct event_base *base,
int use_tls );
@ -113,7 +113,8 @@ LDAP_SLAPD_F (void) connections_walk( ldap_pvt_thread_mutex_t *cq_mutex, lload_c
/*
* daemon.c
*/
LDAP_SLAPD_F (int) lload_open_new_listener( const char *urls, LDAPURLDesc *lud );
LDAP_SLAPD_F (LloadListener *) lload_configure_listener( const char *url, LDAPURLDesc *lud );
LDAP_SLAPD_F (int) lload_open_new_listener( LloadListener *lr );
LDAP_SLAPD_F (int) lloadd_listeners_init( const char *urls );
LDAP_SLAPD_F (int) lloadd_daemon_destroy( void );
LDAP_SLAPD_F (int) lloadd_daemon( struct event_base *daemon_base );

View file

@ -1299,22 +1299,17 @@ slap_free_listener_addresses( struct sockaddr **sal )
static int
get_url_perms(
char **exts,
mode_t *perms,
int *crit )
mode_t *perms )
{
int i;
assert( exts != NULL );
assert( perms != NULL );
assert( crit != NULL );
*crit = 0;
for ( i = 0; exts[ i ]; i++ ) {
char *type = exts[ i ];
int c = 0;
if ( type[ 0 ] == '!' ) {
c = 1;
type++;
}
@ -1365,7 +1360,6 @@ get_url_perms(
return LDAP_OTHER;
}
*crit = c;
*perms = p;
return LDAP_SUCCESS;
@ -1523,13 +1517,6 @@ slap_open_listener(
ber_socket_t s;
char ebuf[128];
#if defined(LDAP_PF_LOCAL) || defined(SLAP_X_LISTENER_MOD)
/*
* use safe defaults
*/
int crit = 1;
#endif /* LDAP_PF_LOCAL || SLAP_X_LISTENER_MOD */
rc = ldap_url_parse_ext( url, &lud, LDAP_PVT_URL_PARSE_DEF_PORT );
if( rc != LDAP_URL_SUCCESS ) {
@ -1596,7 +1583,7 @@ slap_open_listener(
#if defined(LDAP_PF_LOCAL) || defined(SLAP_X_LISTENER_MOD)
if ( lud->lud_exts ) {
err = get_url_perms( lud->lud_exts, &l.sl_perms, &crit );
err = get_url_perms( lud->lud_exts, &l.sl_perms );
} else {
l.sl_perms = S_IRWXU | S_IRWXO;
}