ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-MP/bin/aemp
Revision: 1.16
Committed: Thu Aug 20 17:35:22 2009 UTC (14 years, 9 months ago) by root
Branch: MAIN
Changes since 1.15: +1 -1 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.8 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    
16     # run a node
17     aemp run initialise_args... # run a node
18    
19     # node configuration: protocol endpoints
20     aemp setnoderef <noderef> # configure the real noderef
21     aemp clrnoderef # reset noderef to default
22 root 1.1
23     # node configuration: secret
24 root 1.8 aemp gensecret # generate a random shared secret
25     aemp setsecret <secret> # set the shared secret
26     aemp clrsecret # remove the secret
27 root 1.1
28     # node configuration: TLS
29 root 1.8 aemp setcert <file> # set a certificate (key.pem + certificate.pem)
30     aemp clrcert # remove certificate
31     aemp gencert # generate a random certificate
32    
33     # node configuration: seed nodes for bootstrapping
34     aemp setseeds <noderef>... # set seednodes
35     aemp addseed <noderef> # add a seednode
36     aemp delseed <noderef> # remove seednode
37    
38     # node configuration: services
39     aemp setservices initfunc... # set service functions
40     aemp addservice <initfunc> # add an instance of a service
41     aemp delservice <initfunc> # delete one instance of a service
42 root 1.6
43 root 1.10 # profile-specific configuration
44     aemp profile <name> <command>... # apply command to profile only
45     aemp delprofile <name> # eradicate the named profile
46    
47 root 1.11 # debugging
48     aemp trace <noderef> # trace the network topology
49    
50 root 1.1 =head1 DESCRIPTION
51    
52 root 1.8 With aemp you can configure various aspects of AnyEvent::MP and its
53     protocol.
54    
55     You can also start a "default node", a node that only depends on the
56     static configuration.
57 root 1.1
58     =cut
59    
60     use common::sense;
61    
62 root 1.15 # must come before anything else
63 root 1.8 BEGIN {
64     if ($ARGV[0] eq "run") {
65     shift;
66    
67 root 1.13 # d'oh
68 root 1.15 require AnyEvent::Watchdog;
69     AnyEvent::Watchdog::autorestart (1);
70     AnyEvent::Watchdog::heartbeat (300);
71 root 1.13
72 root 1.8 require AnyEvent;
73     require AnyEvent::MP;
74     AnyEvent::MP::initialise_node (@ARGV);
75    
76 root 1.16 AnyEvent::detect () eq "AnyEvent::Impl::EV"
77 root 1.8 ? EV::loop ()
78     : AE::cv ()->recv;
79     }
80     }
81    
82 root 1.1 use Carp ();
83    
84     use AnyEvent;
85 root 1.4 use AnyEvent::Util;
86    
87 root 1.8 use AnyEvent::MP;
88 root 1.1 use AnyEvent::MP::Config;
89    
90     sub my_run_cmd {
91     my ($cmd) = @_;
92    
93     my $cv = &run_cmd;
94     my $status = $cv->recv;
95    
96     $status
97     and die "@$cmd: command failed with exit status $status.";
98     }
99    
100     sub gen_cert {
101 root 1.2 my_run_cmd [qw(openssl req
102     -new -nodes -x509 -days 3650
103     -newkey rsa:2048 -keyout /dev/fd/3
104     -batch -subj /CN=AnyEvent::MP
105     )],
106 root 1.5 "<", "/dev/null",
107 root 1.1 ">" , \my $cert,
108     "3>", \my $key,
109 root 1.4 "2>", "/dev/null";
110 root 1.1
111     "$cert$key"
112     }
113    
114 root 1.10 our $cfg = AnyEvent::MP::Config::config;
115 root 1.8 our $profile = $cfg;
116 root 1.1
117     sub resolve_port {
118     my ($node, $port) = split /#/, $_[0], 2;
119    
120     $node = (resolve_node $node)->recv;
121     "$node#$port"
122     }
123    
124 root 1.11 sub trace {
125     my ($node) = @_;
126     my $cv = AE::cv;
127     my %seen;
128    
129     my $to = AE::timer 15, 0, sub {
130     warn "timeout\n";
131     $cv->();
132     };
133    
134     initialise_node "slave/", $node;
135    
136     my $reply = port {
137 root 1.12 my ($node, @neigh) = @_;
138 root 1.11
139 root 1.12 @neigh = grep $_ ne $NODE, @neigh;
140    
141     print +(join " ", $node, @neigh), "\n";
142    
143     for (@neigh) {
144 root 1.11 unless ($seen{$_}++) {
145     $cv->begin;
146     snd $_, up_nodes => $SELF => $_;
147     }
148     }
149    
150     $cv->end;
151     };
152    
153     $cv->begin;
154     snd $reply, seed => $node;
155    
156     $cv->recv;
157     }
158    
159 root 1.10 sub docmd;
160    
161 root 1.1 our %CMD = (
162     snd => sub {
163     my $port = resolve_port shift @ARGV;
164     initialise_node "slave/", node_of $port;
165    
166 root 1.7 snd $port, @ARGV; @ARGV = ();
167 root 1.1
168     my $cv = AE::cv;
169 root 1.7 my $to = AE::timer 5, 0, sub { $cv->("timeout") };
170 root 1.1 mon $port, $cv;
171 root 1.7 my $reply = port { &$cv; 1 };
172 root 1.15 snd node_of $port, snd => $reply, "ok";
173 root 1.1
174     print join " ", $cv->recv, "\n";
175     },
176    
177 root 1.7 rpc => sub {
178     my $port = resolve_port shift @ARGV;
179     initialise_node "slave/", node_of $port;
180    
181     my $cv = AE::cv;
182     my $to = AE::timer 5, 0, sub { $cv->("timeout") };
183     my $reply = port { &$cv; 1 };
184     snd $port, @ARGV, $reply; @ARGV = ();
185     mon $port, $cv;
186    
187     print join " ", $cv->recv, "\n";
188     },
189    
190 root 1.1 mon => sub {
191     my $port = resolve_port shift @ARGV;
192     initialise_node "slave/", node_of $port;
193    
194     mon $port, my $cv = AE::cv;
195     print join " ", $cv->recv, "\n";
196     },
197    
198 root 1.11 trace => sub {
199     @ARGV >= 1
200     or die "noderef missing\n";
201    
202     trace +(resolve_node shift @ARGV)->recv;
203     },
204    
205 root 1.8 setnoderef => sub {
206     @ARGV >= 1
207     or die "shared secret missing\n";
208    
209     $profile->{noderef} = shift @ARGV;
210     ++$cfg->{dirty};
211     },
212     clrnoderef => sub {
213     delete $profile->{noderef};
214     ++$cfg->{dirty};
215     },
216    
217 root 1.1 setsecret => sub {
218 root 1.8 @ARGV >= 1
219 root 1.1 or die "shared secret missing\n";
220    
221 root 1.8 $profile->{secret} = shift @ARGV;
222 root 1.1 ++$cfg->{dirty};
223     },
224     gensecret => sub {
225 root 1.8 $profile->{secret} = AnyEvent::MP::Base::asciibits AnyEvent::MP::Base::nonce 64;
226 root 1.1 ++$cfg->{dirty};
227     },
228     clrsecret => sub {
229 root 1.8 delete $profile->{secret};
230 root 1.1 ++$cfg->{dirty};
231     },
232    
233     setcert => sub {
234 root 1.8 @ARGV >= 1
235 root 1.1 or die "key+certificate pem filename missing\n";
236    
237     open my $fh, "<", $ARGV[0]
238     or die "$ARGV[0]: $!";
239    
240     local $/;
241 root 1.8 $profile->{cert} = <$fh>;
242 root 1.1 ++$cfg->{dirty};
243     },
244     gencert => sub {
245 root 1.8 $profile->{cert} = gen_cert;
246 root 1.1 ++$cfg->{dirty};
247     },
248     clrcert => sub {
249 root 1.8 delete $profile->{cert};
250 root 1.1 ++$cfg->{dirty};
251     },
252 root 1.6
253     setseeds => sub {
254 root 1.8 $profile->{seeds} = [@ARGV];
255 root 1.6 @ARGV = ();
256     ++$cfg->{dirty};
257     },
258     addseed => sub {
259 root 1.10 @ARGV >= 1
260     or die "seed noderef missing\n";
261 root 1.6 my $seed = shift @ARGV;
262 root 1.10
263 root 1.8 @{ $profile->{seeds} } = grep $_ ne $seed, @{ $profile->{seeds} };
264     push @{ $profile->{seeds} }, $seed;
265     ++$cfg->{dirty};
266     },
267     delseed => sub {
268 root 1.10 @ARGV >= 1
269     or die "seed noderef missing\n";
270 root 1.8 my $seed = shift @ARGV;
271 root 1.10
272 root 1.8 @{ $profile->{seeds} } = grep $_ ne $seed, @{ $profile->{seeds} };
273     ++$cfg->{dirty};
274     },
275    
276     setservices => sub {
277     $profile->{services} = [@ARGV];
278     @ARGV = ();
279 root 1.6 ++$cfg->{dirty};
280     },
281 root 1.9 addservice => sub {
282 root 1.10 @ARGV >= 1
283     or die "service specification missing\n";
284 root 1.8 my $service = shift @ARGV;
285     push @{ $profile->{services} }, $service;
286     ++$cfg->{dirty};
287     },
288 root 1.9 delservice => sub {
289 root 1.10 @ARGV >= 1
290     or die "service specification missing\n";
291 root 1.8 my $service = shift @ARGV;
292     for (0 .. $#{ $profile->{services} }) {
293     next unless $profile->{services}[$_] eq $service;
294     splice @{ $profile->{services} }, $_, 1;
295     last;
296     }
297 root 1.6 ++$cfg->{dirty};
298     },
299 root 1.10
300     profile => sub {
301     @ARGV >= 2
302     or die "profile name or subcommand are missing\n";
303     my $name = shift @ARGV;
304    
305     $profile = $cfg->{profile}{$name} ||= {};
306 root 1.14 ++$cfg->{dirty};
307 root 1.10
308     docmd;
309     },
310     delprofile => sub {
311     @ARGV >= 1
312     or die "profile name is missing\n";
313     my $name = shift @ARGV;
314    
315     delete $cfg->{profile}{$name};
316 root 1.14 ++$cfg->{dirty};
317 root 1.10 },
318 root 1.1 );
319    
320     sub docmd {
321     my $cmd = shift @ARGV;
322    
323     $CMD{$cmd}
324     or die "$cmd: no such aemp command (try man aemp)";
325    
326     $CMD{$cmd}();
327     }
328    
329     @ARGV
330     or die "Usage: aemp subcommand ... (try man aemp)\n";
331    
332     docmd;
333    
334