From 255433db2d3d92c22dca183f59f2bcee9b000419 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pavel=20B=C5=99ezina?= <pbrezina@redhat.com>
Date: Mon, 20 Jun 2016 18:09:39 +0200
Subject: [PATCH 23/25] DP: Add org.freedesktop.sssd.DataProvider.Failover

---
 Makefile.am                                      |  1 +
 src/providers/backend.h                          | 23 ++++++++-
 src/providers/data_provider/dp_iface.c           |  6 +++
 src/providers/data_provider/dp_iface.h           |  5 ++
 src/providers/data_provider/dp_iface.xml         |  8 +++
 src/providers/data_provider/dp_iface_failover.c  | 66 ++++++++++++++++++++++++
 src/providers/data_provider/dp_iface_generated.c | 40 ++++++++++++++
 src/providers/data_provider/dp_iface_generated.h | 16 ++++++
 src/providers/data_provider_fo.c                 | 23 ---------
 9 files changed, 164 insertions(+), 24 deletions(-)
 create mode 100644 src/providers/data_provider/dp_iface_failover.c

diff --git a/Makefile.am b/Makefile.am
index 31e6ab574d05abf545061c74dbb1780a33186d7e..46b934dbd67c440a5f49b5f9e34e4c08d3067de4 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1347,6 +1347,7 @@ sssd_be_SOURCES = \
     src/providers/data_provider/dp_builtin.c \
     src/providers/data_provider/dp_iface.c \
     src/providers/data_provider/dp_iface_backend.c \
+    src/providers/data_provider/dp_iface_failover.c \
     src/providers/data_provider/dp_client.c \
     src/providers/data_provider/dp_iface_generated.c \
     src/providers/data_provider/dp_request.c \
diff --git a/src/providers/backend.h b/src/providers/backend.h
index ba0bc5927e3e37dd903595072094452e64c7d5c5..30541366033ad621bf59ac67a264a87cc29c2df4 100644
--- a/src/providers/backend.h
+++ b/src/providers/backend.h
@@ -50,7 +50,28 @@ struct be_resolv_ctx {
     enum restrict_family family_order;
 };
 
-struct be_failover_ctx;
+struct be_svc_data {
+    struct be_svc_data *prev;
+    struct be_svc_data *next;
+
+    const char *name;
+    struct fo_service *fo_service;
+
+    struct fo_server *last_good_srv;
+    time_t last_status_change;
+    bool run_callbacks;
+
+    struct be_svc_callback *callbacks;
+    struct fo_server *first_resolved;
+};
+
+struct be_failover_ctx {
+    struct fo_ctx *fo_ctx;
+    struct be_resolv_ctx *be_res;
+
+    struct be_svc_data *svcs;
+    struct tevent_timer *primary_server_handler;
+};
 
 struct be_cb;
 
diff --git a/src/providers/data_provider/dp_iface.c b/src/providers/data_provider/dp_iface.c
index 7bd740ad60bb8bad1a2a10e7f20546c7c670ec76..1270c8b96a84315101593157d0b16e8b4673a011 100644
--- a/src/providers/data_provider/dp_iface.c
+++ b/src/providers/data_provider/dp_iface.c
@@ -41,9 +41,15 @@ struct iface_dp_backend iface_dp_backend = {
     .IsOnline = dp_backend_is_online
 };
 
+struct iface_dp_failover iface_dp_failover = {
+    {&iface_dp_backend_meta, 0},
+    .ListServices = dp_failover_list_services
+};
+
 static struct sbus_iface_map dp_map[] = {
     { DP_PATH, &iface_dp.vtable },
     { DP_PATH, &iface_dp_backend.vtable },
+    { DP_PATH, &iface_dp_failover.vtable },
     { NULL, NULL }
 };
 
diff --git a/src/providers/data_provider/dp_iface.h b/src/providers/data_provider/dp_iface.h
index 8354b1d3a21092f823ba7cab62c0466f7348e3ff..76e623d21c413fd68f8f3c9a91ea32fd707dc54d 100644
--- a/src/providers/data_provider/dp_iface.h
+++ b/src/providers/data_provider/dp_iface.h
@@ -64,4 +64,9 @@ errno_t dp_backend_is_online(struct sbus_request *sbus_req,
                              void *dp_cli,
                              const char *domain);
 
+/* org.freedesktop.sssd.DataProvider.Failover */
+errno_t dp_failover_list_services(struct sbus_request *sbus_req,
+                                  void *dp_cli,
+                                  const char *domname);
+
 #endif /* DP_IFACE_H_ */
diff --git a/src/providers/data_provider/dp_iface.xml b/src/providers/data_provider/dp_iface.xml
index da16eb6396e1a70623c73b9107d2adf41f6e4e1c..eab7fc0f1500bf8890030352421da62c134115b9 100644
--- a/src/providers/data_provider/dp_iface.xml
+++ b/src/providers/data_provider/dp_iface.xml
@@ -16,6 +16,14 @@
         </method>
     </interface>
 
+    <interface name="org.freedesktop.sssd.DataProvider.Failover">
+        <annotation value="iface_dp_failover" name="org.freedesktop.DBus.GLib.CSymbol"/>
+        <method name="ListServices">
+            <arg name="domain_name" type="s" direction="in" />
+            <arg name="services" type="as" direction="out" />
+        </method>
+    </interface>
+
     <interface name="org.freedesktop.sssd.dataprovider">
         <annotation value="iface_dp" name="org.freedesktop.DBus.GLib.CSymbol"/>
         <method name="pamHandler">
diff --git a/src/providers/data_provider/dp_iface_failover.c b/src/providers/data_provider/dp_iface_failover.c
new file mode 100644
index 0000000000000000000000000000000000000000..038791088eeab7e9c5923996db77d2a107ff067d
--- /dev/null
+++ b/src/providers/data_provider/dp_iface_failover.c
@@ -0,0 +1,66 @@
+/*
+    Authors:
+        Pavel Březina <pbrezina@redhat.com>
+
+    Copyright (C) 2016 Red Hat
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <talloc.h>
+#include <tevent.h>
+
+#include "sbus/sssd_dbus.h"
+#include "sbus/sssd_dbus_errors.h"
+#include "providers/data_provider/dp_private.h"
+#include "providers/data_provider/dp_iface.h"
+#include "providers/backend.h"
+#include "util/util.h"
+
+errno_t dp_failover_list_services(struct sbus_request *sbus_req,
+                                  void *dp_cli,
+                                  const char *domname)
+{
+    struct be_ctx *be_ctx;
+    struct be_svc_data *svc;
+    const char **services;
+    int num_services;
+
+    be_ctx = dp_client_be(dp_cli);
+
+    num_services = 0;
+    DLIST_FOR_EACH(svc, be_ctx->be_fo->svcs) {
+        num_services++;
+    }
+
+    services = talloc_zero_array(sbus_req, const char *, num_services);
+    if (services == NULL) {
+        DEBUG(SSSDBG_CRIT_FAILURE, "talloc_zero_array() failed\n");
+        return ENOMEM;
+    }
+
+    num_services = 0;
+    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;
+        }
+        num_services++;
+    }
+
+    iface_dp_failover_ListServices_finish(sbus_req, services, num_services);
+    return EOK;
+}
diff --git a/src/providers/data_provider/dp_iface_generated.c b/src/providers/data_provider/dp_iface_generated.c
index 388aa39d20dfe38973f8bfdb800ae1bc61b46226..7b36fd8aaeebb976a511c5592b1dd0ae28e9bb8a 100644
--- a/src/providers/data_provider/dp_iface_generated.c
+++ b/src/providers/data_provider/dp_iface_generated.c
@@ -92,6 +92,46 @@ const struct sbus_interface_meta iface_dp_backend_meta = {
     sbus_invoke_get_all, /* GetAll invoker */
 };
 
+/* arguments for org.freedesktop.sssd.DataProvider.Failover.ListServices */
+const struct sbus_arg_meta iface_dp_failover_ListServices__in[] = {
+    { "domain_name", "s" },
+    { NULL, }
+};
+
+/* arguments for org.freedesktop.sssd.DataProvider.Failover.ListServices */
+const struct sbus_arg_meta iface_dp_failover_ListServices__out[] = {
+    { "services", "as" },
+    { NULL, }
+};
+
+int iface_dp_failover_ListServices_finish(struct sbus_request *req, const char *arg_services[], int len_services)
+{
+   return sbus_request_return_and_finish(req,
+                                         DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &arg_services, len_services,
+                                         DBUS_TYPE_INVALID);
+}
+
+/* methods for org.freedesktop.sssd.DataProvider.Failover */
+const struct sbus_method_meta iface_dp_failover__methods[] = {
+    {
+        "ListServices", /* name */
+        iface_dp_failover_ListServices__in,
+        iface_dp_failover_ListServices__out,
+        offsetof(struct iface_dp_failover, ListServices),
+        invoke_s_method,
+    },
+    { NULL, }
+};
+
+/* interface info for org.freedesktop.sssd.DataProvider.Failover */
+const struct sbus_interface_meta iface_dp_failover_meta = {
+    "org.freedesktop.sssd.DataProvider.Failover", /* name */
+    iface_dp_failover__methods,
+    NULL, /* no signals */
+    NULL, /* no properties */
+    sbus_invoke_get_all, /* GetAll invoker */
+};
+
 /* arguments for org.freedesktop.sssd.dataprovider.autofsHandler */
 const struct sbus_arg_meta iface_dp_autofsHandler__in[] = {
     { "dp_flags", "u" },
diff --git a/src/providers/data_provider/dp_iface_generated.h b/src/providers/data_provider/dp_iface_generated.h
index 28b0183546eaf9174d598f967cf303ec67c973af..977ab3bae803ca002162b02d0c3d9677779983f4 100644
--- a/src/providers/data_provider/dp_iface_generated.h
+++ b/src/providers/data_provider/dp_iface_generated.h
@@ -19,6 +19,10 @@
 #define IFACE_DP_BACKEND "org.freedesktop.sssd.DataProvider.Backend"
 #define IFACE_DP_BACKEND_ISONLINE "IsOnline"
 
+/* constants for org.freedesktop.sssd.DataProvider.Failover */
+#define IFACE_DP_FAILOVER "org.freedesktop.sssd.DataProvider.Failover"
+#define IFACE_DP_FAILOVER_LISTSERVICES "ListServices"
+
 /* constants for org.freedesktop.sssd.dataprovider */
 #define IFACE_DP "org.freedesktop.sssd.dataprovider"
 #define IFACE_DP_PAMHANDLER "pamHandler"
@@ -64,6 +68,15 @@ struct iface_dp_backend {
 /* finish function for IsOnline */
 int iface_dp_backend_IsOnline_finish(struct sbus_request *req, bool arg_status);
 
+/* vtable for org.freedesktop.sssd.DataProvider.Failover */
+struct iface_dp_failover {
+    struct sbus_vtable vtable; /* derive from sbus_vtable */
+    int (*ListServices)(struct sbus_request *req, void *data, const char *arg_domain_name);
+};
+
+/* finish function for ListServices */
+int iface_dp_failover_ListServices_finish(struct sbus_request *req, const char *arg_services[], int len_services);
+
 /* vtable for org.freedesktop.sssd.dataprovider */
 struct iface_dp {
     struct sbus_vtable vtable; /* derive from sbus_vtable */
@@ -103,6 +116,9 @@ extern const struct sbus_interface_meta iface_dp_client_meta;
 /* interface info for org.freedesktop.sssd.DataProvider.Backend */
 extern const struct sbus_interface_meta iface_dp_backend_meta;
 
+/* interface info for org.freedesktop.sssd.DataProvider.Failover */
+extern const struct sbus_interface_meta iface_dp_failover_meta;
+
 /* interface info for org.freedesktop.sssd.dataprovider */
 extern const struct sbus_interface_meta iface_dp_meta;
 
diff --git a/src/providers/data_provider_fo.c b/src/providers/data_provider_fo.c
index 1e858c354130400ede423b745dbf1b62b1c4edd6..332174e34c91e553b52c26de1c68257320fa38b3 100644
--- a/src/providers/data_provider_fo.c
+++ b/src/providers/data_provider_fo.c
@@ -34,29 +34,6 @@ struct be_svc_callback {
     void *private_data;
 };
 
-struct be_svc_data {
-    struct be_svc_data *prev;
-    struct be_svc_data *next;
-
-    const char *name;
-    struct fo_service *fo_service;
-
-    struct fo_server *last_good_srv;
-    time_t last_status_change;
-    bool run_callbacks;
-
-    struct be_svc_callback *callbacks;
-    struct fo_server *first_resolved;
-};
-
-struct be_failover_ctx {
-    struct fo_ctx *fo_ctx;
-    struct be_resolv_ctx *be_res;
-
-    struct be_svc_data *svcs;
-    struct tevent_timer *primary_server_handler;
-};
-
 static const char *proto_table[] = { FO_PROTO_TCP, FO_PROTO_UDP, NULL };
 
 int be_fo_is_srv_identifier(const char *server)
-- 
2.1.0

