ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-MP/bin/aemp
Revision: 1.21
Committed: Sun Aug 30 13:27:22 2009 UTC (14 years, 9 months ago) by root
Branch: MAIN
Changes since 1.20: +0 -19 lines
Log Message:
*** empty log message ***

File Contents

# User Rev Content
1 root 1.1 #!/opt/bin/perl
2    
3     =head1 NAME
4    
5     aemp - AnyEvent:MP utility
6    
7     =head1 SYNOPSIS
8    
9     aemp command args...
10    
11     # protocol commands
12 root 1.19 aemp snd <port> <arg...> # send a message
13     aemp mon <port> # wait till port is killed
14     aemp rpc <port> <arg...> # send message, append reply
15     aemp eval <node> <expr...> # evaluate expression
16 root 1.8
17     # run a node
18 root 1.19 aemp run initialise_args... # run a node
19 root 1.8
20     # node configuration: protocol endpoints
21 root 1.19 aemp setnodeid <nodeid> # configure the real node id
22     aemp delnodeid # reset node id to default (= inherit)
23 root 1.1
24     # node configuration: secret
25 root 1.19 aemp gensecret # generate a random shared secret
26     aemp setsecret <secret> # set the shared secret
27     aemp delsecret # remove the secret (= inherit)
28 root 1.1
29     # node configuration: TLS
30 root 1.19 aemp gencert # generate a random certificate
31     aemp setcert <file> # set a certificate (key.pem + certificate.pem)
32     aemp delcert # remove certificate (= inherit)
33 root 1.8
34 root 1.17 # node configuration: seed addresses for bootstrapping
35 root 1.19 aemp setseeds <host:port>,... # set seeds
36     aemp delseeds # clear all seeds (= inherit)
37     aemp addseed <host:port> # add a seed
38     aemp delseed <host:port> # remove seed
39 root 1.17
40     # node configuration: bind addresses
41 root 1.19 aemp setbinds <host:port>,... # set binds
42     aemp delbinds # clear all binds (= inherit)
43     aemp addbind <host:port> # add a bind address
44     aemp delbind <host:port> # remove a bind address
45 root 1.8
46     # node configuration: services
47 root 1.19 aemp setservices initfunc,... # set service functions
48     aemp delservices # clear all services (= inherit)
49     aemp addservice <initfunc> # add an instance of a service
50     aemp delservice <initfunc> # delete one instance of a service
51 root 1.6
52 root 1.10 # profile-specific configuration
53     aemp profile <name> <command>... # apply command to profile only
54 root 1.19 aemp delprofile <name> # eradicate the named profile
55     aemp showprofile <name> # display given profile
56     aemp showconfig <name> # display effective config
57 root 1.10
58 root 1.11 # debugging
59 root 1.19 aemp trace <nodeid> # trace the network topology
60 root 1.11
61 root 1.1 =head1 DESCRIPTION
62    
63 root 1.8 With aemp you can configure various aspects of AnyEvent::MP and its
64     protocol.
65    
66     You can also start a "default node", a node that only depends on the
67     static configuration.
68 root 1.1
69     =cut
70    
71     use common::sense;
72    
73 root 1.19 # should come before anything else, so all modules
74     # will be loaded on each restart
75 root 1.20 #BEGIN {
76 root 1.8 if ($ARGV[0] eq "run") {
77     shift;
78    
79 root 1.13 # d'oh
80 root 1.20 # require AnyEvent::Watchdog;
81 root 1.19 # now we can load extra modules
82    
83 root 1.20 # AnyEvent::Watchdog::autorestart (1);
84     # AnyEvent::Watchdog::heartbeat (300);
85 root 1.13
86 root 1.8 require AnyEvent;
87     require AnyEvent::MP;
88     AnyEvent::MP::initialise_node (@ARGV);
89    
90 root 1.16 AnyEvent::detect () eq "AnyEvent::Impl::EV"
91 root 1.8 ? EV::loop ()
92     : AE::cv ()->recv;
93     }
94 root 1.20 #}
95 root 1.8
96 root 1.1 use Carp ();
97    
98 root 1.17 use JSON::XS;
99    
100 root 1.1 use AnyEvent;
101 root 1.4 use AnyEvent::Util;
102    
103 root 1.8 use AnyEvent::MP;
104 root 1.1 use AnyEvent::MP::Config;
105    
106     sub my_run_cmd {
107     my ($cmd) = @_;
108    
109     my $cv = &run_cmd;
110     my $status = $cv->recv;
111    
112     $status
113     and die "@$cmd: command failed with exit status $status.";
114     }
115    
116     sub gen_cert {
117 root 1.2 my_run_cmd [qw(openssl req
118     -new -nodes -x509 -days 3650
119     -newkey rsa:2048 -keyout /dev/fd/3
120     -batch -subj /CN=AnyEvent::MP
121     )],
122 root 1.5 "<", "/dev/null",
123 root 1.1 ">" , \my $cert,
124     "3>", \my $key,
125 root 1.4 "2>", "/dev/null";
126 root 1.1
127     "$cert$key"
128     }
129    
130 root 1.10 our $cfg = AnyEvent::MP::Config::config;
131 root 1.8 our $profile = $cfg;
132 root 1.1
133 root 1.11 sub trace {
134     my ($node) = @_;
135     my $cv = AE::cv;
136     my %seen;
137    
138     my $to = AE::timer 15, 0, sub {
139     warn "timeout\n";
140     $cv->();
141     };
142    
143 root 1.19 initialise_node "anon/";
144 root 1.11
145     my $reply = port {
146 root 1.12 my ($node, @neigh) = @_;
147 root 1.11
148 root 1.12 @neigh = grep $_ ne $NODE, @neigh;
149    
150     print +(join " ", $node, @neigh), "\n";
151    
152     for (@neigh) {
153 root 1.11 unless ($seen{$_}++) {
154     $cv->begin;
155     snd $_, up_nodes => $SELF => $_;
156     }
157     }
158    
159     $cv->end;
160     };
161    
162     $cv->begin;
163     snd $reply, seed => $node;
164    
165     $cv->recv;
166     }
167    
168 root 1.10 sub docmd;
169    
170 root 1.1 our %CMD = (
171     snd => sub {
172 root 1.17 my $port = shift @ARGV;
173 root 1.19 initialise_node "anon/";
174 root 1.1
175 root 1.7 snd $port, @ARGV; @ARGV = ();
176 root 1.1
177     my $cv = AE::cv;
178 root 1.7 my $to = AE::timer 5, 0, sub { $cv->("timeout") };
179 root 1.1 mon $port, $cv;
180 root 1.19 my $reply = port sub { &$cv };
181     snd node_of $port, snd => $reply, "message sent successfully";
182 root 1.1
183     print join " ", $cv->recv, "\n";
184     },
185    
186 root 1.7 rpc => sub {
187 root 1.17 my $port = shift @ARGV;
188 root 1.19 initialise_node "anon/";
189 root 1.7
190     my $cv = AE::cv;
191     my $to = AE::timer 5, 0, sub { $cv->("timeout") };
192 root 1.19 snd $port, @ARGV, port { &$cv }; @ARGV = ();
193 root 1.7 mon $port, $cv;
194    
195     print join " ", $cv->recv, "\n";
196     },
197    
198 root 1.1 mon => sub {
199 root 1.17 my $port = shift @ARGV;
200 root 1.19 initialise_node "anon/";
201 root 1.1
202     mon $port, my $cv = AE::cv;
203     print join " ", $cv->recv, "\n";
204     },
205    
206 root 1.19 eval => sub {
207     my $node = node_of shift @ARGV;
208     my $expr = join " ", @ARGV; @ARGV = ();
209     initialise_node "anon/";
210    
211     my $cv = AE::cv;
212     my $to = AE::timer 5, 0, sub { $cv->("timeout") };
213     AnyEvent::MP::Kernel::eval_on $node, $expr, port { &$cv };
214     mon $node, $cv;
215    
216     my ($err, @res) = $cv->recv;
217    
218     die $err if length $err;
219    
220     print +(substr JSON::XS->new->encode (\@res), 1, -1), "\n";
221     },
222    
223 root 1.11 trace => sub {
224     @ARGV >= 1
225 root 1.17 or die "node id missing\n";
226 root 1.11
227 root 1.17 trace shift @ARGV;
228 root 1.11 },
229    
230 root 1.17 setnodeid => sub {
231 root 1.8 @ARGV >= 1
232     or die "shared secret missing\n";
233    
234 root 1.17 $profile->{nodeid} = shift @ARGV;
235 root 1.8 ++$cfg->{dirty};
236     },
237 root 1.17 delnodeid => sub {
238     delete $profile->{nodeid};
239 root 1.8 ++$cfg->{dirty};
240     },
241    
242 root 1.1 setsecret => sub {
243 root 1.8 @ARGV >= 1
244 root 1.1 or die "shared secret missing\n";
245    
246 root 1.8 $profile->{secret} = shift @ARGV;
247 root 1.1 ++$cfg->{dirty};
248     },
249     gensecret => sub {
250 root 1.18 $profile->{secret} = AnyEvent::MP::Kernel::alnumbits AnyEvent::MP::Kernel::nonce 64;
251 root 1.1 ++$cfg->{dirty};
252     },
253 root 1.17 delsecret => sub {
254 root 1.8 delete $profile->{secret};
255 root 1.1 ++$cfg->{dirty};
256     },
257    
258     setcert => sub {
259 root 1.8 @ARGV >= 1
260 root 1.1 or die "key+certificate pem filename missing\n";
261    
262     open my $fh, "<", $ARGV[0]
263     or die "$ARGV[0]: $!";
264    
265     local $/;
266 root 1.8 $profile->{cert} = <$fh>;
267 root 1.1 ++$cfg->{dirty};
268     },
269     gencert => sub {
270 root 1.8 $profile->{cert} = gen_cert;
271 root 1.1 ++$cfg->{dirty};
272     },
273 root 1.17 delcert => sub {
274 root 1.8 delete $profile->{cert};
275 root 1.1 ++$cfg->{dirty};
276     },
277 root 1.6
278 root 1.17 setbinds => sub {
279 root 1.19 @ARGV >= 1
280     or die "bind addresses missing\n";
281     $profile->{binds} = [split /,/, shift @ARGV];
282 root 1.17 ++$cfg->{dirty};
283     },
284     delbinds => sub {
285     delete $profile->{binds};
286     ++$cfg->{dirty};
287     },
288     addbind => sub {
289     @ARGV >= 1
290     or die "bind address missing\n";
291     my $bind = shift @ARGV;
292    
293     @{ $profile->{binds} } = grep $_ ne $bind, @{ $profile->{binds} };
294     push @{ $profile->{binds} }, $bind;
295     ++$cfg->{dirty};
296     },
297     delbind => sub {
298     @ARGV >= 1
299     or die "bind address missing\n";
300     my $bind = shift @ARGV;
301    
302     @{ $profile->{binds} } = grep $_ ne $bind, @{ $profile->{binds} };
303     ++$cfg->{dirty};
304     },
305    
306 root 1.6 setseeds => sub {
307 root 1.19 @ARGV >= 1
308     or die "seed addresses missing\n";
309     $profile->{seeds} = [split /,/, shift @ARGV];
310 root 1.6 ++$cfg->{dirty};
311     },
312 root 1.17 delseeds => sub {
313     delete $profile->{seeds};
314     ++$cfg->{dirty};
315     },
316 root 1.6 addseed => sub {
317 root 1.10 @ARGV >= 1
318 root 1.17 or die "seed address missing\n";
319 root 1.6 my $seed = shift @ARGV;
320 root 1.10
321 root 1.8 @{ $profile->{seeds} } = grep $_ ne $seed, @{ $profile->{seeds} };
322     push @{ $profile->{seeds} }, $seed;
323     ++$cfg->{dirty};
324     },
325     delseed => sub {
326 root 1.10 @ARGV >= 1
327 root 1.17 or die "seed address missing\n";
328 root 1.8 my $seed = shift @ARGV;
329 root 1.10
330 root 1.8 @{ $profile->{seeds} } = grep $_ ne $seed, @{ $profile->{seeds} };
331     ++$cfg->{dirty};
332     },
333    
334     setservices => sub {
335 root 1.19 @ARGV >= 1
336     or die "service specifications missing\n";
337     $profile->{services} = [split /,/, shift @ARGV];
338 root 1.8 @ARGV = ();
339 root 1.6 ++$cfg->{dirty};
340     },
341 root 1.17 delservices => sub {
342     delete $profile->{services};
343     ++$cfg->{dirty};
344     },
345 root 1.9 addservice => sub {
346 root 1.10 @ARGV >= 1
347     or die "service specification missing\n";
348 root 1.8 my $service = shift @ARGV;
349     push @{ $profile->{services} }, $service;
350     ++$cfg->{dirty};
351     },
352 root 1.9 delservice => sub {
353 root 1.10 @ARGV >= 1
354     or die "service specification missing\n";
355 root 1.8 my $service = shift @ARGV;
356     for (0 .. $#{ $profile->{services} }) {
357     next unless $profile->{services}[$_] eq $service;
358     splice @{ $profile->{services} }, $_, 1;
359     last;
360     }
361 root 1.6 ++$cfg->{dirty};
362     },
363 root 1.10
364     profile => sub {
365 root 1.19 @ARGV >= 1
366     or die "profile name is missing\n";
367 root 1.10 my $name = shift @ARGV;
368    
369     $profile = $cfg->{profile}{$name} ||= {};
370 root 1.14 ++$cfg->{dirty};
371 root 1.10 },
372     delprofile => sub {
373     @ARGV >= 1
374     or die "profile name is missing\n";
375     my $name = shift @ARGV;
376    
377     delete $cfg->{profile}{$name};
378 root 1.14 ++$cfg->{dirty};
379 root 1.10 },
380 root 1.17 showprofile => sub {
381     @ARGV >= 1
382     or die "profile name is missing\n";
383     my $name = shift @ARGV;
384    
385     print JSON::XS->new->pretty->encode ($cfg->{profile}{$name} || {});
386     },
387     showconfig => sub {
388     my $name = @ARGV ? shift @ARGV : AnyEvent::MP::Kernel::_nodename;
389    
390     print JSON::XS->new->pretty->encode (AnyEvent::MP::Config::find_profile $name);
391     },
392 root 1.1 );
393    
394     sub docmd {
395     my $cmd = shift @ARGV;
396    
397     $CMD{$cmd}
398     or die "$cmd: no such aemp command (try man aemp)";
399    
400     $CMD{$cmd}();
401     }
402    
403     @ARGV
404     or die "Usage: aemp subcommand ... (try man aemp)\n";
405    
406 root 1.19 docmd while @ARGV;
407 root 1.1
408