Date: Tue, 16 Nov 2010 23:39:26 +0200 From: Mikolaj Golub <to.my.trociny@gmail.com> To: freebsd-fs@freebsd.org Subject: HAST: more than one remote nodes, is it possible? Message-ID: <86eial2bjl.fsf@kopusha.home.net>
next in thread | raw e-mail | index | archive | help
--=-=-= Hi, So is it possible to have several remote (secondary) nodes with HAST? Although current version of hastd supports only one remote node, it looks like it is possible building HAST devices in stack :-) I tried this under VirtulBox and it worked for me. Having 2 pairs of hosts I built lower HAST devise on both pairs and then upper resource using lower as a provider for upper. Any host can be used as primary for upper in this configuration. To make things more interesting I installed jail (VIMAGE) on upper device so vm can be moved between 4 hosts. Below is hast.conf: ---------------------------------------------------------------------- # Stacked HAST -- data are written to 4 nodes (lolek, bolek, chuk and # gek) and are accessible on one of the nodes as /dev/hast/upper # # /dev/hast/upper # | # P------------upper-------------S # | 172.20.68.30 | # /dev/hast/lower /dev/hast/lower # | | # P-----lower----S P----lower-----S # | 172.20.68.31 | | 172.20.68.32 | # /dev/ad4 /dev/ad4 /dev/ad4 /dev/ad4 # # lolek bolek chuk gek exec /etc/vip.sh resource lower { local /dev/ad4 on lolek { remote bolek } on bolek { remote lolek } on chuk { remote gek } on gek { remote chuk } } resource upper { local /dev/hast/lower # XXX: HAST should be patched to know friends friends lolek bolek chuk gek on lolek { remote 172.20.68.32 } on bolek { remote 172.20.68.32 } on chuk { remote 172.20.68.31 } on gek { remote 172.20.68.31 } } ---------------------------------------------------------------------- As it is noted in the comments above hastd should be patched: current version of hastd allows only connections from addresses specified as remote. The patch is attached. /etc/vip.sh is used to switch IP addresses between hosts. Details can be found here: http://code.google.com/p/hastmon/wiki/StackedHAST -- Mikolaj Golub --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=hastd.friends.patch Index: sbin/hastd/parse.y =================================================================== --- sbin/hastd/parse.y (revision 214604) +++ sbin/hastd/parse.y (working copy) @@ -209,8 +209,13 @@ void yy_config_free(struct hastd_config *config) { struct hast_resource *res; + struct hast_address *addr; while ((res = TAILQ_FIRST(&config->hc_resources)) != NULL) { + while ((addr = TAILQ_FIRST(&res->hr_friends)) != NULL) { + TAILQ_REMOVE(&res->hr_friends, addr, ha_next); + free(addr); + } TAILQ_REMOVE(&config->hc_resources, res, hr_next); free(res); } @@ -218,7 +223,8 @@ yy_config_free(struct hastd_config *config) } %} -%token CONTROL LISTEN PORT REPLICATION TIMEOUT EXEC EXTENTSIZE RESOURCE NAME LOCAL REMOTE ON +%token CONTROL LISTEN PORT REPLICATION TIMEOUT EXEC EXTENTSIZE +%token RESOURCE NAME LOCAL REMOTE FRIENDS ON %token FULLSYNC MEMSYNC ASYNC %token NUM STR OB CB @@ -418,6 +424,8 @@ node_entry: control_statement | listen_statement + | + friends_statement ; resource_statement: RESOURCE resource_start OB resource_entries CB @@ -513,6 +521,7 @@ resource_start: STR curres->hr_localpath[0] = '\0'; curres->hr_localfd = -1; curres->hr_remoteaddr[0] = '\0'; + TAILQ_INIT(&curres->hr_friends); curres->hr_ggateunit = -1; } ; @@ -533,6 +542,8 @@ resource_entry: | local_statement | + friends_statement + | resource_node_statement ; @@ -598,6 +609,40 @@ local_statement: LOCAL STR } ; +friends_statement: FRIENDS friend_addresses + ; + +friend_addresses: + | + friend_addresses friend_address + ; + +friend_address: STR + { + struct hast_address *addr; + + assert(depth == 1 || depth == 2); + + if (depth == 1 || mynode) { + assert(curres != NULL); + addr = calloc(1, sizeof(*addr)); + if (addr == NULL) { + errx(EX_TEMPFAIL, + "cannot allocate memory for resource"); + } + if (strlcpy(addr->ha_addr, $1, + sizeof(addr->ha_addr)) >= + sizeof(addr->ha_addr)) { + pjdlog_error("address argument too long"); + free($1); + return (1); + } + free($1); + TAILQ_INSERT_TAIL(&curres->hr_friends, addr, ha_next); + } + } + ; + resource_node_statement:ON resource_node_start OB resource_node_entries CB { mynode = false; Index: sbin/hastd/hastd.c =================================================================== --- sbin/hastd/hastd.c (revision 214604) +++ sbin/hastd/hastd.c (working copy) @@ -156,6 +156,29 @@ child_exit(void) } } +static int +friendscmp(const struct hast_resource *res0, const struct hast_resource *res1) +{ + struct hast_address *friend0, *friend1; + int nfriends0, nfriends1; + + nfriends0 = nfriends1 = 0; + + TAILQ_FOREACH(friend0, &res0->hr_friends, ha_next) { + TAILQ_FOREACH(friend1, &res1->hr_friends, ha_next) { + if (strcmp(friend0->ha_addr, friend1->ha_addr) == 0) + break; + } + if (friend1 == NULL) + return (1); + nfriends0++; + } + TAILQ_FOREACH(friend1, &res1->hr_friends, ha_next) { + nfriends1++; + } + return (nfriends0 - nfriends1); +} + static bool resource_needs_restart(const struct hast_resource *res0, const struct hast_resource *res1) @@ -177,6 +200,8 @@ resource_needs_restart(const struct hast_resource return (true); if (strcmp(res0->hr_exec, res1->hr_exec) != 0) return (true); + if (friendscmp(res0, res1) != 0) + return (true); } return (false); } @@ -201,6 +226,7 @@ resource_needs_reload(const struct hast_resource * return (true); if (strcmp(res0->hr_exec, res1->hr_exec) != 0) return (true); + return (false); } @@ -384,6 +410,7 @@ listen_accept(void) struct hast_resource *res; struct proto_conn *conn; struct nv *nvin, *nvout, *nverr; + struct hast_address *friend; const char *resname; const unsigned char *token; char laddr[256], raddr[256]; @@ -416,6 +443,12 @@ listen_accept(void) TAILQ_FOREACH(res, &cfg->hc_resources, hr_next) { if (proto_address_match(conn, res->hr_remoteaddr)) break; + TAILQ_FOREACH(friend, &res->hr_friends, ha_next) { + if (proto_address_match(conn, friend->ha_addr)) + break; + } + if (friend != NULL) + break; } if (res == NULL) { pjdlog_error("Client %s isn't known.", raddr); @@ -469,9 +502,15 @@ listen_accept(void) /* Does the remote host have access to this resource? */ if (!proto_address_match(conn, res->hr_remoteaddr)) { - pjdlog_error("Client %s has no access to the resource.", raddr); - nv_add_stringf(nverr, "errmsg", "No access to the resource."); - goto fail; + TAILQ_FOREACH(friend, &res->hr_friends, ha_next) { + if (proto_address_match(conn, friend->ha_addr)) + break; + } + if (friend == NULL) { + pjdlog_error("Client %s has no access to the resource.", raddr); + nv_add_stringf(nverr, "errmsg", "No access to the resource."); + goto fail; + } } /* Is the resource marked as secondary? */ if (res->hr_role != HAST_ROLE_SECONDARY) { Index: sbin/hastd/hast.h =================================================================== --- sbin/hastd/hast.h (revision 214604) +++ sbin/hastd/hast.h (working copy) @@ -150,6 +150,8 @@ struct hast_resource { /* Address of the remote component. */ char hr_remoteaddr[HAST_ADDRSIZE]; + /* Hosts that can connect to us. */ + TAILQ_HEAD(, hast_address) hr_friends; /* Connection for incoming data. */ struct proto_conn *hr_remotein; /* Connection for outgoing data. */ @@ -193,6 +195,11 @@ struct hast_resource { TAILQ_ENTRY(hast_resource) hr_next; }; +struct hast_address { + char ha_addr[HAST_ADDRSIZE]; + TAILQ_ENTRY(hast_address) ha_next; +}; + struct hastd_config *yy_config_parse(const char *config, bool exitonerror); void yy_config_free(struct hastd_config *config); Index: sbin/hastd/hast.conf.5 =================================================================== --- sbin/hastd/hast.conf.5 (revision 214604) +++ sbin/hastd/hast.conf.5 (working copy) @@ -81,6 +81,7 @@ resource <name> { local <path> timeout <seconds> exec <path> + friends <addr ...> on <node> { # Resource-node section @@ -89,6 +90,7 @@ resource <name> { local <path> # Required remote <addr> + friends <addr ...> } on <node> { # Resource-node section @@ -97,6 +99,7 @@ resource <name> { local <path> # Required remote <addr> + friends <addr ...> } } .Ed @@ -155,6 +158,13 @@ tcp4://0.0.0.0:8457 .Pp The default value is .Pa tcp4://0.0.0.0:8457 . +.It Ic friends Aq addr ... +.Pp +List of addresses (separated by space) of hosts that can connect to +the node. +Format is the same as for the +.Ic listen +statement. .It Ic replication Aq mode .Pp Replication mode should be one of the following: Index: sbin/hastd/token.l =================================================================== --- sbin/hastd/token.l (revision 214604) +++ sbin/hastd/token.l (working copy) @@ -53,6 +53,7 @@ exec { DP; return EXEC; } resource { DP; return RESOURCE; } name { DP; return NAME; } local { DP; return LOCAL; } +friends { DP; return FRIENDS; } remote { DP; return REMOTE; } on { DP; return ON; } fullsync { DP; return FULLSYNC; } --=-=-=--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?86eial2bjl.fsf>