[SSSD] [PATCH] Reset all failover services when going online

Sumit Bose sbose at redhat.com
Thu Nov 25 12:05:42 UTC 2010


On Mon, Nov 22, 2010 at 11:35:04AM -0500, Stephen Gallagher wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> On 11/22/2010 05:57 AM, Sumit Bose wrote:
> > Hi,
> > 
> > this patch resets the status of all failover services and the
> > went_offline time if we receive a reset_offline request. Before the
> > request was introduced we waited until all the timeouts were over and
> > tried an online operation with the next request. After a reset_offline
> > request is received it is expected that the next request will
> > immediately goes online. To achieve this all timeouts and status must be
> > reset.
> > 
> > This patch should fix the scenario from trac ticket #655.
> > 
> 
> Nack. This doesn't actually resolve #655.
> 
> The problem is that firing the delayed auth immediately after connecting
> to the VPN isn't providing time for NetworkManager to update the
> resolv.conf, so the resolver is still unable to find any of the
> addresses and it goes back offline.

I have extended this patch. Now it includes a call to a check_online
method of the providers and an implementation for the LDAP provider.
Also the online checks are called during a res_init request, because a
change in /etc/resolv.conf might help to resolve servers which were not
found before.

bye,
Sumit

> 
> - -- 
> Stephen Gallagher
> RHCE 804006346421761
> 
> Delivering value year after year.
> Red Hat ranks #1 in value among software vendors.
> http://www.redhat.com/promo/vendor/
> -----BEGIN PGP SIGNATURE-----
> Version: GnuPG v1.4.11 (GNU/Linux)
> Comment: Using GnuPG with Fedora - http://enigmail.mozdev.org/
> 
> iEYEARECAAYFAkzqm7gACgkQeiVVYja6o6MClwCfdPkv0D0ARKmKqIryy0bFOjSH
> FJQAn1O22+tdeI4uwbpyfUlLQjnZ6lsQ
> =AcPd
> -----END PGP SIGNATURE-----
> _______________________________________________
> sssd-devel mailing list
> sssd-devel at lists.fedorahosted.org
> https://fedorahosted.org/mailman/listinfo/sssd-devel
-------------- next part --------------
>From 00dbabb4c8d5044bd48943ca78e6f4060f27a4dd Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Fri, 19 Nov 2010 21:11:26 +0100
Subject: [PATCH 1/3] Run checks before resetting offline state

Before setting the backend to online during a reset offline request the
check_online method if the ID provider is called. If the check_online
method returns that the ID provider is still not reachable the backend
stays offline. Otherwise the backend is switched to online and the
related callbacks are run.

Additionally the check online test is called during the res_init request
because a change in /etc/resolve.conf might also make a server reachable
which was assumed offline before.
---
 src/providers/data_provider_be.c |  119 ++++++++++++++++++++++++++++++++++++-
 src/providers/data_provider_fo.c |    5 ++
 src/providers/dp_backend.h       |    3 +
 src/providers/fail_over.c        |   17 ++++++
 src/providers/fail_over.h        |    1 +
 src/providers/proxy/proxy_init.c |    3 +-
 6 files changed, 143 insertions(+), 5 deletions(-)

diff --git a/src/providers/data_provider_be.c b/src/providers/data_provider_be.c
index e094c65..98c3f39 100644
--- a/src/providers/data_provider_be.c
+++ b/src/providers/data_provider_be.c
@@ -173,10 +173,9 @@ void be_mark_offline(struct be_ctx *ctx)
     be_run_offline_cb(ctx);
 }
 
-void be_reset_offline(struct be_ctx *ctx)
+static void be_reset_offline(struct be_ctx *ctx)
 {
-    DEBUG(8, ("Going back online!\n"));
-
+    ctx->offstat.went_offline = 0;
     ctx->offstat.offline = false;
     be_run_online_cb(ctx);
 }
@@ -728,6 +727,114 @@ static int client_registration(DBusMessage *message,
     return EOK;
 }
 
+static errno_t be_file_check_online_request(struct be_req *req)
+{
+    int ret;
+
+    req->be_ctx->offstat.went_offline = time(NULL);
+    reset_fo(req->be_ctx);
+
+    ret = be_file_request(req->be_ctx,
+              req->be_ctx->bet_info[BET_ID].bet_ops->check_online, req);
+    if (ret != EOK) {
+        DEBUG(1, ("be_file_request failed.\n"));
+    }
+
+    return ret;
+}
+
+static void check_online_callback(struct be_req *req, int dp_err_type,
+                                  int errnum, const char *errstr)
+{
+    int ret;
+
+    DEBUG(4, ("Backend returned: (%d, %d, %s) [%s]\n",
+              dp_err_type, errnum, errstr?errstr:"<NULL>",
+              dp_pam_err_to_string(req, dp_err_type, errnum)));
+
+    req->be_ctx->check_online_ref_count--;
+
+    if (dp_err_type != DP_ERR_OK && req->be_ctx->check_online_ref_count > 0) {
+        ret = be_file_check_online_request(req);
+        if (ret != EOK) {
+            DEBUG(1, ("be_file_check_online_request failed.\n"));
+            goto done;
+        }
+        return;
+    }
+
+done:
+    req->be_ctx->check_online_ref_count = 0;
+    if (dp_err_type != DP_ERR_OFFLINE) {
+        if (dp_err_type != DP_ERR_OK) {
+            reset_fo(req->be_ctx);
+        }
+        be_reset_offline(req->be_ctx);
+    }
+
+    talloc_free(req);
+
+    return;
+}
+
+static void check_if_online(struct be_ctx *ctx)
+{
+    int ret;
+    struct be_req *be_req = NULL;
+
+    if (ctx->offstat.offline == false) {
+        DEBUG(8, ("Backend is already online, nothing to do.\n"));
+        return;
+    }
+
+    /* Make sure nobody tries to go online while we are checking */
+    ctx->offstat.went_offline = time(NULL);
+
+    DEBUG(8, ("Trying to go back online!\n"));
+
+    ctx->check_online_ref_count++;
+
+    if (ctx->check_online_ref_count != 1) {
+        DEBUG(8, ("There is an online check already running.\n"));
+        return;
+    }
+
+    if (ctx->bet_info[BET_ID].bet_ops->check_online == NULL) {
+        DEBUG(8, ("ID providers does not provide a check_online method.\n"));
+        goto failed;
+    }
+
+    be_req = talloc_zero(ctx, struct be_req);
+    if (be_req == NULL) {
+        DEBUG(1, ("talloc_zero failed.\n"));
+        goto failed;
+    }
+
+    be_req->be_ctx = ctx;
+    be_req->fn = check_online_callback;
+
+    ret = be_file_check_online_request(be_req);
+    if (ret != EOK) {
+        DEBUG(1, ("be_file_check_online_request failed.\n"));
+        goto failed;
+    }
+
+    return;
+
+failed:
+    ctx->check_online_ref_count--;
+    DEBUG(1, ("Failed to run a check_online test.\n"));
+
+    talloc_free(be_req);
+
+    if (ctx->check_online_ref_count == 0) {
+        reset_fo(ctx);
+        be_reset_offline(ctx);
+    }
+
+    return;
+}
+
 static void init_timeout(struct tevent_context *ev,
                          struct tevent_timer *te,
                          struct timeval t, void *ptr)
@@ -1228,7 +1335,11 @@ int main(int argc, const char *argv[])
 static int data_provider_res_init(DBusMessage *message,
                                   struct sbus_connection *conn)
 {
+    struct be_ctx *be_ctx;
+    be_ctx = talloc_get_type(sbus_conn_get_private_data(conn), struct be_ctx);
+
     resolv_reread_configuration();
+    check_if_online(be_ctx);
 
     return monitor_common_res_init(message, conn);
 }
@@ -1247,6 +1358,6 @@ static int data_provider_reset_offline(DBusMessage *message,
 {
     struct be_ctx *be_ctx;
     be_ctx = talloc_get_type(sbus_conn_get_private_data(conn), struct be_ctx);
-    be_reset_offline(be_ctx);
+    check_if_online(be_ctx);
     return monitor_common_pong(message, conn);
 }
diff --git a/src/providers/data_provider_fo.c b/src/providers/data_provider_fo.c
index dff0aef..61bc938 100644
--- a/src/providers/data_provider_fo.c
+++ b/src/providers/data_provider_fo.c
@@ -493,3 +493,8 @@ int be_fo_run_callbacks_at_next_request(struct be_ctx *ctx,
     return EOK;
 }
 
+void reset_fo(struct be_ctx *be_ctx)
+{
+    fo_reset_services(be_ctx->be_fo->fo_ctx);
+}
+
diff --git a/src/providers/dp_backend.h b/src/providers/dp_backend.h
index a31e458..1d040d4 100644
--- a/src/providers/dp_backend.h
+++ b/src/providers/dp_backend.h
@@ -111,6 +111,8 @@ struct be_ctx {
 
     struct loaded_be loaded_be[BET_MAX];
     struct bet_info bet_info[BET_MAX];
+
+    size_t check_online_ref_count;
 };
 
 struct bet_ops {
@@ -187,4 +189,5 @@ void be_fo_try_next_server(struct be_ctx *ctx, const char *service_name);
 int be_fo_run_callbacks_at_next_request(struct be_ctx *ctx,
                                         const char *service_name);
 
+void reset_fo(struct be_ctx *be_ctx);
 #endif /* __DP_BACKEND_H___ */
diff --git a/src/providers/fail_over.c b/src/providers/fail_over.c
index fa91aec..125dfe5 100644
--- a/src/providers/fail_over.c
+++ b/src/providers/fail_over.c
@@ -1329,3 +1329,20 @@ fo_get_server_hostent(struct fo_server *server)
     }
     return server->common->hostent;
 }
+
+void fo_reset_services(struct fo_ctx *fo_ctx)
+{
+    struct fo_service *service;
+    struct fo_server *server;
+
+    DLIST_FOR_EACH(service, fo_ctx->service_list) {
+        DLIST_FOR_EACH(server, service->server_list) {
+            fo_set_server_status(server, SERVER_NAME_NOT_RESOLVED);
+            fo_set_port_status(server, PORT_NEUTRAL);
+            if (server->srv_data != NULL) {
+                set_srv_data_status(server->srv_data, SRV_NOT_RESOLVED);
+            }
+        }
+    }
+}
+
diff --git a/src/providers/fail_over.h b/src/providers/fail_over.h
index f1a071d..dce02dc 100644
--- a/src/providers/fail_over.h
+++ b/src/providers/fail_over.h
@@ -172,4 +172,5 @@ struct hostent *fo_get_server_hostent(struct fo_server *server);
 
 int fo_is_srv_lookup(struct fo_server *s);
 
+void fo_reset_services(struct fo_ctx *fo_ctx);
 #endif /* !__FAIL_OVER_H__ */
diff --git a/src/providers/proxy/proxy_init.c b/src/providers/proxy/proxy_init.c
index de1904c..0993fee 100644
--- a/src/providers/proxy/proxy_init.c
+++ b/src/providers/proxy/proxy_init.c
@@ -54,7 +54,8 @@ static void proxy_auth_shutdown(struct be_req *req)
 
 struct bet_ops proxy_id_ops = {
     .handler = proxy_get_account_info,
-    .finalize = proxy_shutdown
+    .finalize = proxy_shutdown,
+    .check_online = NULL
 };
 
 struct bet_ops proxy_auth_ops = {
-- 
1.7.3.2

-------------- next part --------------
>From db58c887f39b4f72daefe519678921465ccb81a9 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Wed, 24 Nov 2010 18:22:08 +0100
Subject: [PATCH 2/3] Fix offline detection in sdap_cli_connect request

sdap_cli_connect_recv_ext() checks if the failover server is not set to
determine if the backend is offline. To make this work properly if
multiple servers are defined the failover server must be set to NULL if
all servers are checked.
---
 src/providers/ldap/sdap_async_connection.c |    1 +
 1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/src/providers/ldap/sdap_async_connection.c b/src/providers/ldap/sdap_async_connection.c
index 0cb9162..f143a01 100644
--- a/src/providers/ldap/sdap_async_connection.c
+++ b/src/providers/ldap/sdap_async_connection.c
@@ -1137,6 +1137,7 @@ static void sdap_cli_resolve_done(struct tevent_req *subreq)
     ret = be_resolve_server_recv(subreq, &state->srv);
     talloc_zfree(subreq);
     if (ret) {
+        state->srv = NULL;
         /* all servers have been tried and none
          * was found good, go offline */
         tevent_req_error(req, EIO);
-- 
1.7.3.2

-------------- next part --------------
>From 2463d66d1cd84d3abb48ac5bb2780dc619ea699d Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose at redhat.com>
Date: Wed, 24 Nov 2010 14:17:36 +0100
Subject: [PATCH 3/3] Add check_online method to LDAP ID provider

---
 src/providers/ipa/ipa_init.c     |    3 +-
 src/providers/ldap/ldap_common.h |    1 +
 src/providers/ldap/ldap_id.c     |   41 ++++++++++++++++++++++++++++++++++++++
 src/providers/ldap/ldap_init.c   |    3 +-
 4 files changed, 46 insertions(+), 2 deletions(-)

diff --git a/src/providers/ipa/ipa_init.c b/src/providers/ipa/ipa_init.c
index 2a63ac8..f6769ee 100644
--- a/src/providers/ipa/ipa_init.c
+++ b/src/providers/ipa/ipa_init.c
@@ -40,7 +40,8 @@ struct ipa_options *ipa_options = NULL;
 /* Id Handler */
 struct bet_ops ipa_id_ops = {
     .handler = sdap_account_info_handler,
-    .finalize = NULL
+    .finalize = NULL,
+    .check_online = sdap_check_online
 };
 
 struct bet_ops ipa_auth_ops = {
diff --git a/src/providers/ldap/ldap_common.h b/src/providers/ldap/ldap_common.h
index 63192fb..5c298d1 100644
--- a/src/providers/ldap/ldap_common.h
+++ b/src/providers/ldap/ldap_common.h
@@ -67,6 +67,7 @@ struct sdap_auth_ctx {
     struct sdap_service *service;
 };
 
+void sdap_check_online(struct be_req *breq);
 /* id */
 void sdap_account_info_handler(struct be_req *breq);
 int sdap_id_setup_tasks(struct sdap_id_ctx *ctx);
diff --git a/src/providers/ldap/ldap_id.c b/src/providers/ldap/ldap_id.c
index 07e3ae1..1a9b2e0 100644
--- a/src/providers/ldap/ldap_id.c
+++ b/src/providers/ldap/ldap_id.c
@@ -650,7 +650,48 @@ int groups_by_user_recv(struct tevent_req *req, int *dp_error_out)
     return EOK;
 }
 
+static void sdap_check_online_done(struct tevent_req *req);
+void sdap_check_online(struct be_req *be_req)
+{
+    struct sdap_id_ctx *ctx;
+    struct tevent_req *req;
+
+    ctx = talloc_get_type(be_req->be_ctx->bet_info[BET_ID].pvt_bet_data,
+                          struct sdap_id_ctx);
+
+    req = sdap_cli_connect_send(be_req, be_req->be_ctx->ev, ctx->opts,
+                                be_req->be_ctx, ctx->service, false);
+    if (req == NULL) {
+        DEBUG(1, ("sdap_cli_connect_send failed.\n"));
+        goto done;
+    }
+    tevent_req_set_callback(req, sdap_check_online_done, be_req);
+
+    return;
+done:
+    sdap_handler_done(be_req, DP_ERR_FATAL, 0, NULL);
+}
 
+static void sdap_check_online_done(struct tevent_req *req)
+{
+    struct be_req *be_req = tevent_req_callback_data(req, struct be_req);
+    int ret;
+    int dp_err = DP_ERR_FATAL;
+    bool can_retry;
+
+    ret = sdap_cli_connect_recv_ext(req, NULL, &can_retry, NULL);
+    talloc_zfree(req);
+
+    if (ret != EOK) {
+        if (!can_retry) {
+            dp_err = DP_ERR_OFFLINE;
+        }
+    } else {
+        dp_err = DP_ERR_OK;
+    }
+
+    sdap_handler_done(be_req, dp_err, 0, NULL);
+}
 
 /* =Get-Account-Info-Call================================================= */
 
diff --git a/src/providers/ldap/ldap_init.c b/src/providers/ldap/ldap_init.c
index dcfb553..b6176a9 100644
--- a/src/providers/ldap/ldap_init.c
+++ b/src/providers/ldap/ldap_init.c
@@ -32,7 +32,8 @@ static void sdap_shutdown(struct be_req *req);
 /* Id Handler */
 struct bet_ops sdap_id_ops = {
     .handler = sdap_account_info_handler,
-    .finalize = sdap_shutdown
+    .finalize = sdap_shutdown,
+    .check_online = sdap_check_online
 };
 
 /* Auth Handler */
-- 
1.7.3.2



More information about the sssd-devel mailing list