aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSree Harsha Totakura <totakura@in.tum.de>2013-02-27 14:22:24 +0000
committerSree Harsha Totakura <totakura@in.tum.de>2013-02-27 14:22:24 +0000
commitd6353593a73706c2bdbaac7fbb111fca6bdab9a5 (patch)
treeb0d90b7b24fb82c4583d048b3fae0c6f3d35f505 /src
parente9a65d965436f0233a30951e89b01503cf88be35 (diff)
downloadgnunet-d6353593a73706c2bdbaac7fbb111fca6bdab9a5.tar.gz
gnunet-d6353593a73706c2bdbaac7fbb111fca6bdab9a5.zip
Parsing LoadLeveler allocated hosts and creating testbed hosts from them
Diffstat (limited to 'src')
-rw-r--r--src/include/gnunet_testbed_service.h18
-rw-r--r--src/testbed/gnunet_testbed_mpi_spawn.c218
-rw-r--r--src/testbed/testbed_api_hosts.c200
3 files changed, 229 insertions, 207 deletions
diff --git a/src/include/gnunet_testbed_service.h b/src/include/gnunet_testbed_service.h
index 25378e890..4ffcde76f 100644
--- a/src/include/gnunet_testbed_service.h
+++ b/src/include/gnunet_testbed_service.h
@@ -132,6 +132,24 @@ GNUNET_TESTBED_hosts_load_from_file (const char *filename,
132 132
133 133
134/** 134/**
135 * Loads the set of host allocated by the LoadLeveler Job Scheduler. This
136 * function is only available when compiled with support for LoadLeveler and is
137 * used for running on the SuperMUC
138 *
139 * @param cfg the configuration to use as a template while starting a controller
140 * on any of the loaded hosts. Operation queue sizes specific to a host
141 * are also read from this configuration handle
142 * @param hosts set to the hosts found in the file; caller must free this if
143 * number of hosts returned is greater than 0
144 * @return number of hosts returned in 'hosts', 0 on error
145 */
146unsigned int
147GNUNET_TESTBED_hosts_load_from_loadleveler (const struct
148 GNUNET_CONFIGURATION_Handle *cfg,
149 struct GNUNET_TESTBED_Host
150 ***hosts);
151
152/**
135 * Destroy a host handle. Must only be called once everything 153 * Destroy a host handle. Must only be called once everything
136 * running on that host has been stopped. 154 * running on that host has been stopped.
137 * 155 *
diff --git a/src/testbed/gnunet_testbed_mpi_spawn.c b/src/testbed/gnunet_testbed_mpi_spawn.c
index c147d460b..2ff1972a6 100644
--- a/src/testbed/gnunet_testbed_mpi_spawn.c
+++ b/src/testbed/gnunet_testbed_mpi_spawn.c
@@ -1,6 +1,7 @@
1#include "platform.h" 1#include "platform.h"
2#include "gnunet_util_lib.h" 2#include "gnunet_util_lib.h"
3#include "gnunet_resolver_service.h" 3#include "gnunet_resolver_service.h"
4#include "gnunet_testbed_service.h"
4#include <mpi.h> 5#include <mpi.h>
5 6
6/** 7/**
@@ -22,216 +23,21 @@
22 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30) 23 GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_SECONDS, 30)
23 24
24/** 25/**
25 * Log an error message at log-level 'level' that indicates
26 * a failure of the command 'cmd' with the message given
27 * by gcry_strerror(rc).
28 */
29#define LOG_GAI(level, cmd, rc) do { LOG(level, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, gai_strerror(rc)); } while(0)
30
31/**
32 * Global result 26 * Global result
33 */ 27 */
34static int ret; 28static int ret;
35 29
36/** 30/**
37 * The array of hostnames 31 * The host list
38 */
39static char **hostnames;
40
41/**
42 * The array of host's addresses
43 */
44static char **hostaddrs;
45
46/**
47 * The resolution request handles; one per each hostname resolution
48 */ 32 */
49struct GNUNET_RESOLVER_RequestHandle **rhs; 33static struct GNUNET_TESTBED_Host **hosts;
50 34
51/** 35/**
52 * Number of hosts in the hostname array 36 * Number of hosts in the host list
53 */ 37 */
54static unsigned int nhosts; 38static unsigned int nhosts;
55 39
56/** 40/**
57 * Number of addresses in the hostaddr array
58 */
59static unsigned int nhostaddrs;
60
61/**
62 * Did we connect to the resolver service
63 */
64static unsigned int resolver_connected;
65
66/**
67 * Task for resolving ips
68 */
69static GNUNET_SCHEDULER_TaskIdentifier resolve_task_id;
70
71
72/**
73 * Resolves the hostnames array
74 *
75 * @param cls NULL
76 * @param tc the scheduler task context
77 */
78static void
79resolve_task (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
80{
81 struct addrinfo hint;
82 const struct sockaddr_in *in_addr;
83 struct addrinfo *res;
84 char *hostip;
85 unsigned int host;
86 unsigned int rc;
87
88 resolve_task_id = GNUNET_SCHEDULER_NO_TASK;
89 hint.ai_family = AF_INET; /* IPv4 */
90 hint.ai_socktype = 0;
91 hint.ai_protocol = 0;
92 hint.ai_addrlen = 0;
93 hint.ai_addr = NULL;
94 hint.ai_canonname = NULL;
95 hint.ai_next = NULL;
96 hint.ai_flags = AI_NUMERICSERV;
97 for (host = 0; host < nhosts; host++)
98 {
99 res = NULL;
100 LOG_DEBUG ("Resolving: %s host\n", hostnames[host]);
101 if (0 != (rc = getaddrinfo (hostnames[host], "22", &hint, &res)))
102 {
103 LOG_GAI (GNUNET_ERROR_TYPE_ERROR, "getaddrinfo", rc);
104 ret = GNUNET_SYSERR;
105 return;
106 }
107 GNUNET_assert (NULL != res);
108 GNUNET_assert (NULL != res->ai_addr);
109 GNUNET_assert (sizeof (struct sockaddr_in) == res->ai_addrlen);
110 in_addr = (const struct sockaddr_in *) res->ai_addr;
111 hostip = inet_ntoa (in_addr->sin_addr);
112 GNUNET_assert (NULL != hostip);
113 GNUNET_array_append (hostaddrs, nhostaddrs, GNUNET_strdup (hostip));
114 LOG_DEBUG ("%s --> %s\n", hostnames[host], hostaddrs[host]);
115 freeaddrinfo (res);
116 }
117 ret = GNUNET_OK;
118}
119
120
121/**
122 * Loads the set of host allocated by the LoadLeveler Job Scheduler. This
123 * function is only available when compiled with support for LoadLeveler and is
124 * used for running on the SuperMUC
125 *
126 * @param hostlist set to the hosts found in the file; caller must free this if
127 * number of hosts returned is greater than 0
128 * @return number of hosts returned in 'hosts', 0 on error
129 */
130unsigned int
131get_loadleveler_hosts ()
132{
133 const char *hostfile;
134 char *buf;
135 char *hostname;
136 struct addrinfo *ret;
137 struct addrinfo hint;
138 ssize_t rsize;
139 uint64_t size;
140 uint64_t offset;
141 enum {
142 SCAN,
143 SKIP,
144 TRIM,
145 READHOST
146 } pstep;
147 unsigned int host;
148
149 if (NULL == (hostfile = getenv ("MP_SAVEHOSTFILE")))
150 {
151 GNUNET_break (0);
152 return 0;
153 }
154 if (GNUNET_SYSERR == GNUNET_DISK_file_size (hostfile, &size, GNUNET_YES,
155 GNUNET_YES))
156 {
157 GNUNET_break (0);
158 return 0;
159 }
160 if (0 == size)
161 {
162 GNUNET_break (0);
163 return 0;
164 }
165 buf = GNUNET_malloc (size + 1);
166 rsize = GNUNET_DISK_fn_read (hostfile, buf, (size_t) size);
167 if ( (GNUNET_SYSERR == rsize) || ((ssize_t) size != rsize) )
168 {
169 GNUNET_free (buf);
170 GNUNET_break (0);
171 return 0;
172 }
173 size++;
174 offset = 0;
175 pstep = SCAN;
176 hostname = NULL;
177 while (offset < size)
178 {
179 switch (pstep)
180 {
181 case SCAN:
182 if ('!' == buf[offset])
183 pstep = SKIP;
184 else
185 pstep = TRIM;
186 break;
187 case SKIP:
188 if ('\n' == buf[offset])
189 pstep = SCAN;
190 break;
191 case TRIM:
192 if ('!' == buf[offset])
193 {
194 pstep = SKIP;
195 break;
196 }
197 if ( (' ' == buf[offset])
198 || ('\t' == buf[offset])
199 || ('\r' == buf[offset]) )
200 pstep = TRIM;
201 else
202 {
203 pstep = READHOST;
204 hostname = &buf[offset];
205 }
206 break;
207 case READHOST:
208 if (isspace (buf[offset]))
209 {
210 buf[offset] = '\0';
211 for (host = 0; host < nhosts; host++)
212 if (0 == strcmp (hostnames[host], hostname))
213 break;
214 if (host == nhosts)
215 {
216 LOG_DEBUG ("Adding host: %s\n", hostname);
217 hostname = GNUNET_strdup (hostname);
218 GNUNET_array_append (hostnames, nhosts, hostname);
219 }
220 else
221 LOG_DEBUG ("Not adding host %s as it is already included\n", hostname);
222 hostname = NULL;
223 pstep = SCAN;
224 }
225 break;
226 }
227 offset++;
228 }
229 GNUNET_free_non_null (buf);
230 return nhosts;
231}
232
233
234/**
235 * Main function that will be run by the scheduler. 41 * Main function that will be run by the scheduler.
236 * 42 *
237 * @param cls closure 43 * @param cls closure
@@ -247,7 +53,7 @@ run (void *cls, char *const *args, const char *cfgfile,
247 unsigned long code; 53 unsigned long code;
248 enum GNUNET_OS_ProcessStatusType proc_status; 54 enum GNUNET_OS_ProcessStatusType proc_status;
249 int rank; 55 int rank;
250 int msg_size; 56 unsigned int host;
251 57
252 if (MPI_SUCCESS != MPI_Comm_rank (MPI_COMM_WORLD, &rank)) 58 if (MPI_SUCCESS != MPI_Comm_rank (MPI_COMM_WORLD, &rank))
253 { 59 {
@@ -291,13 +97,17 @@ run (void *cls, char *const *args, const char *cfgfile,
291 GNUNET_break (0); 97 GNUNET_break (0);
292 return; 98 return;
293 } 99 }
294 if (0 == get_loadleveler_hosts()) 100 if (0 == (nhosts = GNUNET_TESTBED_hosts_load_from_loadleveler (config, &hosts)))
295 { 101 {
296 GNUNET_break (0); 102 GNUNET_break (0);
297 ret = GNUNET_SYSERR; 103 ret = GNUNET_SYSERR;
298 return; 104 return;
299 } 105 }
300 resolve_task_id = GNUNET_SCHEDULER_add_now (&resolve_task, NULL); 106 for (host = 0; host < nhosts; host++)
107 GNUNET_TESTBED_host_destroy (hosts[host]);
108 GNUNET_free (hosts);
109 hosts = NULL;
110 ret = GNUNET_OK;
301} 111}
302 112
303 113
@@ -330,12 +140,6 @@ main (int argc, char *argv[])
330 _("Spawns cmd after starting my the MPI run-time"), 140 _("Spawns cmd after starting my the MPI run-time"),
331 options, &run, NULL); 141 options, &run, NULL);
332 (void) MPI_Finalize (); 142 (void) MPI_Finalize ();
333 for (host = 0; host < nhosts; host++)
334 GNUNET_free (hostnames[host]);
335 for (host = 0; host < nhostaddrs; host++)
336 GNUNET_free (hostaddrs[host]);
337 GNUNET_free_non_null (hostnames);
338 GNUNET_free_non_null (hostaddrs);
339 if ((GNUNET_OK == rres) && (GNUNET_OK == ret)) 143 if ((GNUNET_OK == rres) && (GNUNET_OK == ret))
340 return 0; 144 return 0;
341 printf ("Something went wrong\n"); 145 printf ("Something went wrong\n");
diff --git a/src/testbed/testbed_api_hosts.c b/src/testbed/testbed_api_hosts.c
index 198e72c0e..d0349c4b3 100644
--- a/src/testbed/testbed_api_hosts.c
+++ b/src/testbed/testbed_api_hosts.c
@@ -63,6 +63,12 @@
63 } while (0) 63 } while (0)
64 64
65/** 65/**
66 * Log an error message at log-level 'level' that indicates a failure of the
67 * command 'cmd' with the message given by gai_strerror(rc).
68 */
69#define LOG_GAI(level, cmd, rc) do { LOG(level, _("`%s' failed at %s:%d with error: %s\n"), cmd, __FILE__, __LINE__, gai_strerror(rc)); } while(0)
70
71/**
66 * Number of extra elements we create space for when we grow host list 72 * Number of extra elements we create space for when we grow host list
67 */ 73 */
68#define HOST_LIST_GROW_STEP 10 74#define HOST_LIST_GROW_STEP 10
@@ -525,6 +531,200 @@ GNUNET_TESTBED_hosts_load_from_file (const char *filename,
525 531
526 532
527/** 533/**
534 * Resolves a hostname using getaddrinfo
535 *
536 * @param host the hostname
537 * @return the string representing the IPv4 address of the given host; NULL upon error
538 */
539const char *
540simple_resolve (const char *host)
541{
542 struct addrinfo *res;
543 const struct sockaddr_in *in_addr;
544 char *hostip;
545 struct addrinfo hint;
546 unsigned int rc;
547
548 hint.ai_family = AF_INET; /* IPv4 */
549 hint.ai_socktype = 0;
550 hint.ai_protocol = 0;
551 hint.ai_addrlen = 0;
552 hint.ai_addr = NULL;
553 hint.ai_canonname = NULL;
554 hint.ai_next = NULL;
555 hint.ai_flags = AI_NUMERICSERV;
556 res = NULL;
557 LOG_DEBUG ("Resolving [%s]\n", host);
558 if (0 != (rc = getaddrinfo (host, "22", &hint, &res)))
559 {
560 LOG_GAI (GNUNET_ERROR_TYPE_ERROR, "getaddrinfo", rc);
561 return NULL;
562 }
563 GNUNET_assert (NULL != res);
564 GNUNET_assert (NULL != res->ai_addr);
565 GNUNET_assert (sizeof (struct sockaddr_in) == res->ai_addrlen);
566 in_addr = (const struct sockaddr_in *) res->ai_addr;
567 hostip = inet_ntoa (in_addr->sin_addr);
568 GNUNET_assert (NULL != hostip);
569 LOG_DEBUG ("Resolved [%s] to [%s]\n", host, hostip);
570 return hostip;
571}
572
573
574/**
575 * Loads the set of host allocated by the LoadLeveler Job Scheduler. This
576 * function is only available when compiled with support for LoadLeveler and is
577 * used for running on the SuperMUC
578 *
579 * @param cfg the configuration to use as a template while starting a controller
580 * on any of the loaded hosts. Operation queue sizes specific to a host
581 * are also read from this configuration handle
582 * @param hosts set to the hosts found in the file; caller must free this if
583 * number of hosts returned is greater than 0
584 * @return number of hosts returned in 'hosts', 0 on error
585 */
586unsigned int
587GNUNET_TESTBED_hosts_load_from_loadleveler (const struct
588 GNUNET_CONFIGURATION_Handle *cfg,
589 struct GNUNET_TESTBED_Host ***hosts)
590{
591 const char *hostfile;
592 char *buf;
593 char *hostname;
594 char **hostnames;
595 char **hostaddrs;
596 char *hostip;
597 struct GNUNET_TESTBED_Host **host_list;
598 ssize_t rsize;
599 uint64_t size;
600 uint64_t offset;
601 enum {
602 SCAN,
603 SKIP,
604 TRIM,
605 READHOST
606 } pstep;
607 unsigned int host;
608 unsigned int nhosts;
609 unsigned int nhostaddrs;
610
611 if (NULL == (hostfile = getenv ("MP_SAVEHOSTFILE")))
612 {
613 GNUNET_break (0);
614 return 0;
615 }
616 if (GNUNET_SYSERR == GNUNET_DISK_file_size (hostfile, &size, GNUNET_YES,
617 GNUNET_YES))
618 {
619 GNUNET_break (0);
620 return 0;
621 }
622 if (0 == size)
623 {
624 GNUNET_break (0);
625 return 0;
626 }
627 buf = GNUNET_malloc (size + 1);
628 rsize = GNUNET_DISK_fn_read (hostfile, buf, (size_t) size);
629 if ( (GNUNET_SYSERR == rsize) || ((ssize_t) size != rsize) )
630 {
631 GNUNET_free (buf);
632 GNUNET_break (0);
633 return 0;
634 }
635 size++;
636 offset = 0;
637 pstep = SCAN;
638 hostname = NULL;
639 hostnames = NULL;
640 hostaddrs = NULL;
641 nhosts = 0;
642 nhostaddrs = 0;
643 while (offset < size)
644 {
645 switch (pstep)
646 {
647 case SCAN:
648 if ('!' == buf[offset])
649 pstep = SKIP;
650 else
651 pstep = TRIM;
652 break;
653 case SKIP:
654 if ('\n' == buf[offset])
655 pstep = SCAN;
656 break;
657 case TRIM:
658 if ('!' == buf[offset])
659 {
660 pstep = SKIP;
661 break;
662 }
663 if ( (' ' == buf[offset])
664 || ('\t' == buf[offset])
665 || ('\r' == buf[offset]) )
666 pstep = TRIM;
667 else
668 {
669 pstep = READHOST;
670 hostname = &buf[offset];
671 }
672 break;
673 case READHOST:
674 if (isspace (buf[offset]))
675 {
676 buf[offset] = '\0';
677 for (host = 0; host < nhosts; host++)
678 if (0 == strcmp (hostnames[host], hostname))
679 break;
680 if (host == nhosts)
681 {
682 LOG_DEBUG ("Adding host [%s]\n", hostname);
683 hostname = GNUNET_strdup (hostname);
684 GNUNET_array_append (hostnames, nhosts, hostname);
685 }
686 else
687 LOG_DEBUG ("Not adding host [%s] as it is already included\n", hostname);
688 hostname = NULL;
689 pstep = SCAN;
690 }
691 break;
692 }
693 offset++;
694 }
695 GNUNET_free_non_null (buf);
696 if (NULL == hostnames)
697 return 0;
698 for (host = 0; host < nhosts; host++)
699 {
700 hostip = simple_resolve (hostnames[host]);
701 if (NULL == hostip)
702 {
703 nhosts = 0;
704 goto cleanup;
705 }
706 GNUNET_array_append (hostaddrs, nhostaddrs, GNUNET_strdup (hostip));
707 }
708 GNUNET_assert (nhostaddrs == nhosts);
709 if (NULL == hosts)
710 goto cleanup;
711 host_list = GNUNET_malloc (sizeof (struct GNUNET_TESTBED_Host *) * nhostaddrs);
712 for (host = 0; host < nhosts; host++)
713 host_list[host] = GNUNET_TESTBED_host_create (hostaddrs[host], NULL, cfg, 0);
714 *hosts = host_list;
715
716 cleanup:
717 for (host = 0; host < nhosts; host++)
718 GNUNET_free (hostnames[host]);
719 GNUNET_free(hostnames);
720 for (host = 0; (NULL != hostaddrs) && (host < nhostaddrs); host++)
721 GNUNET_free (hostaddrs[host]);
722 GNUNET_free (hostaddrs);
723 return nhosts;
724}
725
726
727/**
528 * Destroy a host handle. Must only be called once everything 728 * Destroy a host handle. Must only be called once everything
529 * running on that host has been stopped. 729 * running on that host has been stopped.
530 * 730 *