Add 'get server <backend>/<request>' runtime api
Change-Id: Idc57f080703b5da7e6dac96874d20e2abf99e609
diff --git a/include/haproxy/backend.h b/include/haproxy/backend.h
index 4bfdf07..0a81fb3 100644
--- a/include/haproxy/backend.h
+++ b/include/haproxy/backend.h
@@ -48,6 +48,7 @@
void recount_servers(struct proxy *px);
void update_backend_weight(struct proxy *px);
int be_lastsession(const struct proxy *be);
+struct server *get_server_uh(struct proxy *px, char *uri, int uri_len, const struct server *avoid);
/* Returns number of usable servers in backend */
static inline int be_usable_srv(struct proxy *be)
diff --git a/include/haproxy/proxy.h b/include/haproxy/proxy.h
index f5c096c..8b7ec74 100644
--- a/include/haproxy/proxy.h
+++ b/include/haproxy/proxy.h
@@ -76,6 +76,8 @@
const struct proxy *defproxy);
int get_backend_server(const char *bk_name, const char *sv_name,
struct proxy **bk, struct server **sv);
+int test_backend_server(const char *bk_name, char *uri,
+ struct proxy **bk, struct server **sv);
void proxy_capture_error(struct proxy *proxy, int is_back,
struct proxy *other_end, enum obj_type *target,
const struct session *sess,
diff --git a/src/backend.c b/src/backend.c
index d80e552..92d812d 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -205,7 +205,7 @@
* algorithm out of a tens because it gave him the best results.
*
*/
-static struct server *get_server_uh(struct proxy *px, char *uri, int uri_len, const struct server *avoid)
+struct server *get_server_uh(struct proxy *px, char *uri, int uri_len, const struct server *avoid)
{
unsigned int hash = 0;
int c;
diff --git a/src/proxy.c b/src/proxy.c
index 709dc4a..c53ea02 100644
--- a/src/proxy.c
+++ b/src/proxy.c
@@ -466,6 +466,26 @@
return best_ptr;
}
+int test_backend_server(const char *bk_name, char *uri,
+ struct proxy **bk, struct server **sv)
+{
+ struct proxy *p;
+ struct server *s;
+ int uri_len = strlen(uri);
+ *sv = NULL;
+ p = proxy_be_by_name(bk_name);
+ if (bk)
+ *bk = p;
+ if (!p || (p->lbprm.algo & BE_LB_PARM) != BE_LB_HASH_URI)
+ return 0;
+ fprintf(stderr, "%s\n", uri);
+ s = get_server_uh(p, uri, uri_len, NULL);
+ *sv = s;
+ if (!s)
+ return 0;
+ return 1;
+}
+
/*
* This function scans the list of backends and servers to retrieve the first
* backend and the first server with the given names, and sets them in both
diff --git a/src/server.c b/src/server.c
index 9c7dc83..a5dbf42 100644
--- a/src/server.c
+++ b/src/server.c
@@ -4506,6 +4506,48 @@
return 1;
}
+static int cli_parse_get_server(char **args, char *payload, struct appctx *appctx, void *private)
+{
+ struct proxy *px;
+ struct server *sv;
+ char *line;
+ char pn[INET6_ADDRSTRLEN];
+ uint16_t port;
+ struct sockaddr_storage* addr;
+
+ /* split "backend/server" and make <line> point to server */
+ for (line = args[2]; *line; line++)
+ if (*line == '/') {
+ *line++ = '\0';
+ break;
+ }
+
+ if (!*line) {
+ return cli_err(appctx, "Require 'backend/server'.\n");
+ }
+
+ if (!test_backend_server(args[2], line, &px, &sv)) {
+ return cli_err(appctx, px ? "No such server.\n" : "No such backend.\n");
+ }
+ addr = &(sv->addr);
+ switch (addr_to_str(addr, pn, sizeof(pn))) {
+ case AF_INET:
+ port = ((struct sockaddr_in *)addr)->sin_port;
+ break;
+ case AF_INET6:
+ port = ((struct sockaddr_in6 *)addr)->sin6_port;
+ break;
+ default:
+ port = 0;
+ break;
+ }
+ snprintf(trash.area, trash.size, "%s,%s,%u\n", sv->id, pn, ntohs(port));
+ if (applet_putstr(appctx, trash.area) == -1) {
+ return 0;
+ }
+ return 1;
+}
+
static int cli_parse_get_weight(char **args, char *payload, struct appctx *appctx, void *private)
{
struct proxy *px;
@@ -5297,6 +5339,7 @@
{ { "enable", "server", NULL }, "enable server (DEPRECATED) : enable a disabled server (use 'set server' instead)", cli_parse_enable_server, NULL },
{ { "set", "maxconn", "server", NULL }, "set maxconn server <bk>/<srv> : change a server's maxconn setting", cli_parse_set_maxconn_server, NULL },
{ { "set", "server", NULL }, "set server <bk>/<srv> [opts] : change a server's state, weight, address or ssl", cli_parse_set_server },
+ { { "get", "server", NULL }, "get server <bk>/<req> : get target backend server by request", cli_parse_get_server },
{ { "get", "weight", NULL }, "get weight <bk>/<srv> : report a server's current weight", cli_parse_get_weight },
{ { "set", "weight", NULL }, "set weight <bk>/<srv> (DEPRECATED) : change a server's weight (use 'set server' instead)", cli_parse_set_weight },
{ { "add", "server", NULL }, "add server <bk>/<srv> : create a new server", cli_parse_add_server, NULL },