Skip to content

Commit

Permalink
sssctl: print active server and server list
Browse files Browse the repository at this point in the history
Resolves:
https://fedorahosted.org/sssd/ticket/3069

Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
  • Loading branch information
pbrezina authored and Lukas Slebodnik committed Aug 16, 2016
1 parent 778f241 commit bd4c2ed
Show file tree
Hide file tree
Showing 15 changed files with 721 additions and 18 deletions.
6 changes: 4 additions & 2 deletions src/providers/data_provider/dp_iface.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,10 @@ struct iface_dp_backend iface_dp_backend = {
};

struct iface_dp_failover iface_dp_failover = {
{&iface_dp_failover_meta, 0},
.ListServices = dp_failover_list_services
{ &iface_dp_failover_meta, 0 },
.ListServices = dp_failover_list_services,
.ActiveServer = dp_failover_active_server,
.ListServers = dp_failover_list_servers
};

static struct sbus_iface_map dp_map[] = {
Expand Down
8 changes: 8 additions & 0 deletions src/providers/data_provider/dp_iface.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,4 +69,12 @@ errno_t dp_failover_list_services(struct sbus_request *sbus_req,
void *dp_cli,
const char *domname);

errno_t dp_failover_active_server(struct sbus_request *sbus_req,
void *dp_cli,
const char *service_name);

errno_t dp_failover_list_servers(struct sbus_request *sbus_req,
void *dp_cli,
const char *service_name);

#endif /* DP_IFACE_H_ */
8 changes: 8 additions & 0 deletions src/providers/data_provider/dp_iface.xml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,14 @@
<arg name="domain_name" type="s" direction="in" />
<arg name="services" type="as" direction="out" />
</method>
<method name="ActiveServer">
<arg name="service_name" type="s" direction="in" />
<arg name="server" type="s" direction="out" />
</method>
<method name="ListServers">
<arg name="service_name" type="s" direction="in" />
<arg name="servers" type="as" direction="out" />
</method>
</interface>

<interface name="org.freedesktop.sssd.dataprovider">
Expand Down
295 changes: 287 additions & 8 deletions src/providers/data_provider/dp_iface_failover.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,208 @@
#include "providers/backend.h"
#include "util/util.h"

static errno_t
dp_failover_list_services_ldap(struct be_ctx *be_ctx,
const char **services,
int *_count)
{
struct be_svc_data *svc;
int count;

count = 0;
DLIST_FOR_EACH(svc, be_ctx->be_fo->svcs) {
services[count] = talloc_strdup(services, svc->name);
if (services[count] == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup() failed\n");
return ENOMEM;
}
count++;
}

*_count = count;

return EOK;
}

static errno_t
dp_failover_list_services_ad(struct be_ctx *be_ctx,
struct sss_domain_info *domain,
const char **services,
int *_count)
{
char *fo_svc_name = NULL;
struct be_svc_data *svc;
errno_t ret;
int count;

fo_svc_name = talloc_asprintf(services, "sd_%s", domain->name);
if (fo_svc_name == NULL) {
ret = ENOMEM;
goto done;
}

count = 0;
DLIST_FOR_EACH(svc, be_ctx->be_fo->svcs) {
/* Drop each sd_gc_* since this service is not used with AD at all,
* we only connect to AD_GC for global catalog. */
if (strncasecmp(svc->name, "sd_gc_", strlen("sd_gc_")) == 0) {
continue;
}

/* Drop all subdomain services for different domain. */
if (strncasecmp(svc->name, "sd_", strlen("sd_")) == 0) {
if (!IS_SUBDOMAIN(domain)) {
continue;
}

if (strcasecmp(svc->name, fo_svc_name) != 0) {
continue;
}
}

if (IS_SUBDOMAIN(domain)) {
/* Drop AD since we connect to subdomain.com for LDAP. */
if (strcasecmp(svc->name, "AD") == 0) {
continue;
}
}

services[count] = talloc_strdup(services, svc->name);
if (services[count] == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup() failed\n");
ret = ENOMEM;
goto done;
}
count++;
}

*_count = count;

ret = EOK;

done:
talloc_free(fo_svc_name);
return ret;
}

static errno_t
dp_failover_list_services_ipa(struct be_ctx *be_ctx,
struct sss_domain_info *domain,
const char **services,
int *_count)
{
struct be_svc_data *svc;
char *fo_svc_name = NULL;
char *fo_gc_name = NULL;
errno_t ret;
int count;

fo_svc_name = talloc_asprintf(services, "sd_%s", domain->name);
if (fo_svc_name == NULL) {
ret = ENOMEM;
goto done;
}

fo_gc_name = talloc_asprintf(services, "sd_gc_%s", domain->name);
if (fo_gc_name == NULL) {
ret = ENOMEM;
goto done;
}

count = 0;
DLIST_FOR_EACH(svc, be_ctx->be_fo->svcs) {
/* Drop all subdomain services for different domain. */
if (strncasecmp(svc->name, "sd_", strlen("sd_")) == 0) {
if (!IS_SUBDOMAIN(domain)) {
continue;
}

if (strcasecmp(svc->name, fo_svc_name) != 0
&& strcasecmp(svc->name, fo_gc_name) != 0) {
continue;
}
}

services[count] = talloc_strdup(services, svc->name);
if (services[count] == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup() failed\n");
return ENOMEM;
}
count++;
}

*_count = count;

ret = EOK;

done:
talloc_free(fo_svc_name);
talloc_free(fo_gc_name);

return ret;
}

enum dp_fo_svc_type {
DP_FO_SVC_LDAP = 0,
DP_FO_SVC_AD = 1,
DP_FO_SVC_IPA = 1 << 1,
DP_FO_SVC_MIXED = DP_FO_SVC_AD | DP_FO_SVC_IPA
};

errno_t dp_failover_list_services(struct sbus_request *sbus_req,
void *dp_cli,
const char *domname)
{
enum dp_fo_svc_type svc_type = DP_FO_SVC_LDAP;
struct sss_domain_info *domain;
struct be_ctx *be_ctx;
struct be_svc_data *svc;
const char **services;
int num_services;
errno_t ret;

be_ctx = dp_client_be(dp_cli);

if (SBUS_IS_STRING_EMPTY(domname)) {
domain = be_ctx->domain;
} else {
domain = find_domain_by_name(be_ctx->domain, domname, false);
if (domain == NULL) {
sbus_request_reply_error(sbus_req, SBUS_ERROR_UNKNOWN_DOMAIN,
"Unknown domain %s", domname);
return EOK;
}
}

/**
* Returning list of failover services is currently rather difficult
* since there is only one failover context for the whole backend.
*
* The list of services for the given domain depends on whether it is
* a master domain or a subdomain and whether we are using IPA, AD or
* LDAP backend.
*
* For LDAP we just return everything we have.
* For AD master domain we return AD, AD_GC.
* For AD subdomain we return subdomain.com, AD_GC.
* For IPA in client mode we return IPA.
* For IPA in server mode we return IPA for master domain and
* subdomain.com, gc_subdomain.com for subdomain.
*
* We also return everything else for all cases if any other service
* such as kerberos is configured separately.
*/

/* Allocate enough space. */
num_services = 0;
DLIST_FOR_EACH(svc, be_ctx->be_fo->svcs) {
num_services++;

if (strcasecmp(svc->name, "AD") == 0) {
svc_type |= DP_FO_SVC_AD;
} else if (strcasecmp(svc->name, "IPA") == 0) {
svc_type |= DP_FO_SVC_IPA;
}
}

services = talloc_zero_array(sbus_req, const char *, num_services);
Expand All @@ -50,17 +238,108 @@ errno_t dp_failover_list_services(struct sbus_request *sbus_req,
return ENOMEM;
}

num_services = 0;
/* Fill the list. */
switch (svc_type) {
case DP_FO_SVC_LDAP:
case DP_FO_SVC_MIXED:
ret = dp_failover_list_services_ldap(be_ctx, services, &num_services);
break;
case DP_FO_SVC_AD:
ret = dp_failover_list_services_ad(be_ctx, domain,
services, &num_services);
break;
case DP_FO_SVC_IPA:
ret = dp_failover_list_services_ipa(be_ctx, domain,
services, &num_services);
break;
default:
ret = ERR_INTERNAL;
break;
}

if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to create service list [%d]: %s\n",
ret, sss_strerror(ret));
talloc_free(services);
return ret;
}

iface_dp_failover_ListServices_finish(sbus_req, services, num_services);
return EOK;
}

errno_t dp_failover_active_server(struct sbus_request *sbus_req,
void *dp_cli,
const char *service_name)
{
struct be_ctx *be_ctx;
struct be_svc_data *svc;
const char *server;
bool found = false;

be_ctx = dp_client_be(dp_cli);

DLIST_FOR_EACH(svc, be_ctx->be_fo->svcs) {
services[num_services] = talloc_strdup(services, svc->name);
if (services[num_services] == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "talloc_strdup() failed\n");
talloc_free(services);
return ENOMEM;
if (strcmp(svc->name, service_name) == 0) {
found = true;
break;
}
num_services++;
}

iface_dp_failover_ListServices_finish(sbus_req, services, num_services);
if (!found) {
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get server name\n");
sbus_request_reply_error(sbus_req, SBUS_ERROR_NOT_FOUND,
"Unknown service name");
return EOK;
}

if (svc->last_good_srv == NULL) {
server = "";
} else {
server = fo_get_server_name(svc->last_good_srv);
if (server == NULL) {
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get server name\n");
sbus_request_reply_error(sbus_req, SBUS_ERROR_INTERNAL,
"Unable to get server name");
return EOK;
}
}

iface_dp_failover_ActiveServer_finish(sbus_req, server);
return EOK;
}

errno_t dp_failover_list_servers(struct sbus_request *sbus_req,
void *dp_cli,
const char *service_name)
{
struct be_ctx *be_ctx;
struct be_svc_data *svc;
const char **servers;
bool found = false;
size_t count;

be_ctx = dp_client_be(dp_cli);

DLIST_FOR_EACH(svc, be_ctx->be_fo->svcs) {
if (strcmp(svc->name, service_name) == 0) {
found = true;
break;
}
}

if (!found) {
DEBUG(SSSDBG_CRIT_FAILURE, "Unable to get server list\n");
sbus_request_reply_error(sbus_req, SBUS_ERROR_NOT_FOUND,
"Unknown service name");
return EOK;
}

servers = fo_svc_server_list(sbus_req, svc->fo_service, &count);
if (servers == NULL) {
return ENOMEM;
}

iface_dp_failover_ListServers_finish(sbus_req, servers, (int)count);
return EOK;
}

0 comments on commit bd4c2ed

Please sign in to comment.