summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJakub Hrozek <jhrozek@redhat.com>2015-09-02 15:52:51 +0200
committerJakub Hrozek <jhrozek@redhat.com>2015-09-21 17:04:10 +0200
commit64d4b1e5fd4a3c99ef8d8fef6ad0db52c5152c1c (patch)
treefac899921342cfc3bdbe0a4d3e3a9963334aef06
parentdd0a21738e1b71940bba11134734b5999e9fd8e9 (diff)
downloadsssd-64d4b1e5fd4a3c99ef8d8fef6ad0db52c5152c1c.tar.gz
sssd-64d4b1e5fd4a3c99ef8d8fef6ad0db52c5152c1c.tar.xz
sssd-64d4b1e5fd4a3c99ef8d8fef6ad0db52c5152c1c.zip
AD: Do not mark the whole back end as offline if subdomain lookup fails
Required for: https://fedorahosted.org/sssd/ticket/2637 Rather mark the domain as inactive. It will be marked as active later, in the meantime the main domain can continue to work online and subdomain requests will be answered from cache. The lookup request itself just returns a special error code and lets the caller handle the error code as appropriate (normally by disabling the subdomain temporarily). Reviewed-by: Pavel Březina <pbrezina@redhat.com>
-rw-r--r--src/providers/ad/ad_id.c81
1 files changed, 67 insertions, 14 deletions
diff --git a/src/providers/ad/ad_id.c b/src/providers/ad/ad_id.c
index 4f327f823..ecaf6c993 100644
--- a/src/providers/ad/ad_id.c
+++ b/src/providers/ad/ad_id.c
@@ -91,17 +91,27 @@ ad_handle_acct_info_send(TALLOC_CTX *mem_ctx,
state->ad_options = ad_options;
state->cindex = 0;
+ if (sss_domain_get_state(sdom->dom) == DOM_INACTIVE) {
+ ret = ERR_SUBDOM_INACTIVE;
+ goto immediate;
+ }
+
ret = ad_handle_acct_info_step(req);
- if (ret == EOK) {
- tevent_req_done(req);
- tevent_req_post(req, be_ctx->ev);
- } else if (ret != EAGAIN) {
- tevent_req_error(req, ret);
- tevent_req_post(req, be_ctx->ev);
+ if (ret != EAGAIN) {
+ goto immediate;
}
/* Lookup in progress */
return req;
+
+immediate:
+ if (ret != EOK) {
+ tevent_req_error(req, ret);
+ } else {
+ tevent_req_done(req);
+ }
+ tevent_req_post(req, be_ctx->ev);
+ return req;
}
static errno_t
@@ -160,8 +170,7 @@ ad_handle_acct_info_done(struct tevent_req *subreq)
state->dp_error = dp_error;
state->err = err;
- tevent_req_error(req, ret);
- return;
+ goto fail;
}
if (sdap_err == EOK) {
@@ -170,8 +179,8 @@ ad_handle_acct_info_done(struct tevent_req *subreq)
} else if (sdap_err == ERR_NO_POSIX) {
disable_gc(state->ad_options);
} else if (sdap_err != ENOENT) {
- tevent_req_error(req, EIO);
- return;
+ ret = EIO;
+ goto fail;
}
/* Ret is only ENOENT or ERR_NO_POSIX now. Try the next connection */
@@ -188,12 +197,27 @@ ad_handle_acct_info_done(struct tevent_req *subreq)
/* No more connections */
tevent_req_done(req);
} else {
- tevent_req_error(req, ret);
+ goto fail;
}
return;
}
/* Another lookup in progress */
+ return;
+
+fail:
+ if (IS_SUBDOMAIN(state->sdom->dom)) {
+ /* Deactivate subdomain on lookup errors instead of going
+ * offline completely.
+ * This is a stopgap, until our failover is per-domain,
+ * not per-backend. Unfortunately, we can't rewrite the error
+ * code on some reported codes only, because sdap_id_op code
+ * encapsulated the failover as well..
+ */
+ ret = ERR_SUBDOM_INACTIVE;
+ }
+ tevent_req_error(req, ret);
+ return;
}
errno_t
@@ -258,6 +282,16 @@ get_conn_list(struct be_req *breq, struct ad_id_ctx *ad_ctx,
break;
}
+ /* Regardless of connection types, a subdomain error must not be allowed
+ * to set the whole back end offline, rather report an error and let the
+ * caller deal with it (normally disable the subdomain
+ */
+ if (IS_SUBDOMAIN(dom)) {
+ for (cindex = 0; clist[cindex] != NULL; cindex++) {
+ clist[cindex]->ignore_mark_offline = true;
+ }
+ }
+
return clist;
}
@@ -328,6 +362,11 @@ done:
static void ad_account_info_complete(struct tevent_req *req);
+struct ad_account_info_state {
+ struct be_req *be_req;
+ struct sss_domain_info *dom;
+};
+
void
ad_account_info_handler(struct be_req *be_req)
{
@@ -341,6 +380,7 @@ ad_account_info_handler(struct be_req *be_req)
struct sdap_id_conn_ctx **clist;
bool shortcut;
errno_t ret;
+ struct ad_account_info_state *state;
ad_ctx = talloc_get_type(be_ctx->bet_info[BET_ID].pvt_bet_data,
struct ad_id_ctx);
@@ -391,13 +431,21 @@ ad_account_info_handler(struct be_req *be_req)
goto fail;
}
+ state = talloc(be_req, struct ad_account_info_state);
+ if (state == NULL) {
+ ret = ENOMEM;
+ goto fail;
+ }
+ state->dom = sdom->dom;
+ state->be_req = be_req;
+
req = ad_handle_acct_info_send(be_req, be_req, ar, sdap_id_ctx,
ad_ctx->ad_options, sdom, clist);
if (req == NULL) {
ret = ENOMEM;
goto fail;
}
- tevent_req_set_callback(req, ad_account_info_complete, be_req);
+ tevent_req_set_callback(req, ad_account_info_complete, state);
return;
fail:
@@ -412,12 +460,17 @@ ad_account_info_complete(struct tevent_req *req)
int dp_error;
const char *error_text = "Internal error";
const char *req_error_text;
+ struct ad_account_info_state *state;
- be_req = tevent_req_callback_data(req, struct be_req);
+ state = tevent_req_callback_data(req, struct ad_account_info_state);
+ be_req = state->be_req;
ret = ad_handle_acct_info_recv(req, &dp_error, &req_error_text);
talloc_zfree(req);
- if (dp_error == DP_ERR_OK) {
+ if (ret == ERR_SUBDOM_INACTIVE) {
+ be_mark_dom_offline(state->dom, be_req_get_be_ctx(be_req));
+ return be_req_terminate(be_req, DP_ERR_OFFLINE, EAGAIN, "Offline");
+ } else if (dp_error == DP_ERR_OK) {
if (ret == EOK) {
error_text = NULL;
} else {