File Coverage

blib/lib/Hadoop/Admin.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1 5     5   164247 use strict;
  5         13  
  5         11684  
2             package Hadoop::Admin;
3             {
4             $Hadoop::Admin::VERSION = '0.4';
5             }
6 5     5   39 use warnings;
  5         10  
  5         234  
7 5     5   7779 use Moose;
  0            
  0            
8             use LWP::UserAgent;
9             use JSON -support_by_pp;
10              
11             has 'namenode' => (
12             is => 'ro',
13             isa => 'Str',
14             reader => 'get_namenode',
15             predicate => 'has_namenode',
16             );
17              
18             has 'namenode_port' => (
19             is => 'ro',
20             isa => 'Int',
21             default => '50070',
22             reader => 'get_namenode_port',
23             predicate => 'has_namenode_port',
24             );
25              
26             has 'jobtracker' => (
27             is => 'ro',
28             isa => 'Str',
29             reader => 'get_jobtracker',
30             predicate => 'has_jobtracker',
31             );
32              
33             has 'jobtracker_port' => (
34             is => 'ro',
35             isa => 'Int',
36             default => '50030',
37             reader => 'get_jobtracker_port',
38             predicate => 'has_jobtracker_port',
39             );
40              
41             has 'secondarynamenode' => (
42             is => 'ro',
43             isa => 'Str',
44             reader => 'get_secondarynamenode',
45             predicate => 'has_secondarynamenode',
46             );
47              
48             has 'resourcemanager' => (
49             is => 'ro',
50             isa => 'Str',
51             reader => 'get_resourcemanager',
52             predicate => 'has_resourcemanager',
53             );
54              
55             has 'resourcemanager_port' => (
56             is => 'ro',
57             isa => 'Int',
58             default => '8088',
59             reader => 'get_resourcemanager_port',
60             predicate => 'has_resourcemanager_port',
61             );
62              
63             has 'socksproxy' => (
64             is => 'ro',
65             isa => 'Str',
66             reader => 'get_socksproxy',
67             predicate => 'has_socksproxy',
68             );
69              
70             has 'socksproxy_port' => (
71             is => 'ro',
72             isa => 'Int',
73             default => '1080',
74             reader => 'get_socksproxy_port',
75             predicate => 'has_socksproxy_port',
76             );
77              
78             has 'ua' => (
79             is => 'rw',
80             isa => 'Object',
81             predicate => 'has_ua',
82             );
83              
84             has '_test_namenodeinfo' => (
85             is => 'ro',
86             isa => 'Str',
87             );
88              
89             has '_test_jobtrackerinfo' => (
90             is => 'ro',
91             isa => 'Str',
92             );
93              
94             has '_test_resourcemanagerinfo' => (
95             is => 'ro',
96             isa => 'Str',
97             );
98              
99             # ABSTRACT: Module for administration of Hadoop clusters
100              
101              
102             sub BUILD{
103              
104             my $self=shift;
105              
106             if ( $self->has_resourcemanager && $self->has_jobtracker ){
107             die "Can't have both ResourceManager and JobTracker\n";
108             }
109              
110             $self->ua(new LWP::UserAgent());
111             if ( defined $self->get_socksproxy ){
112             $self->ua->proxy([qw(http https)] => 'socks://'.$self->get_socksproxy.':1080');
113             }
114             ## Hooks for testing during builds. Doesn't connect to a real cluster.
115             if ( defined $self->_test_namenodeinfo ){
116             my $test_nn_string;
117             {
118             local $/=undef;
119             open (my $fh, '<', $self->_test_namenodeinfo) or die "Couldn't open file: $!";
120             $test_nn_string = <$fh>;
121             close $fh;
122             }
123             $self->parse_nn_jmx($test_nn_string);
124             }else{
125             if ( defined $self->get_namenode ){
126             $self->gather_nn_jmx('NameNodeInfo');
127             }
128             }
129             ## Hooks for testing during builds. Doesn't connect to a real cluster.
130             if ( defined $self->_test_jobtrackerinfo ){
131             my $test_jt_string;
132             {
133             local $/=undef;
134             open(my $fh, '<', $self->_test_jobtrackerinfo) or die "Couldn't open file: $!";
135             $test_jt_string = <$fh>;
136             close $fh;
137             }
138             $self->parse_jt_jmx($test_jt_string);
139             }else{
140             if ( defined $self->get_jobtracker ){
141             $self->gather_jt_jmx('JobTrackerInfo');
142             }
143             }
144            
145             ## Hooks for testing during builds. Doesn't connect to a real cluster.
146             if ( defined $self->_test_resourcemanagerinfo ){
147             my $test_rm_string;
148             {
149             local $/=undef;
150             open(my $fh, '<', $self->_test_resourcemanagerinfo) or die "Couldn't open file: $!";
151             $test_rm_string = <$fh>;
152             close $fh;
153             }
154             $self->parse_rm_jmx($test_rm_string);
155             }else{
156             if ( defined $self->get_resourcemanager ){
157             $self->gather_rm_jmx('RMNMInfo');
158             }
159             }
160            
161             return $self;
162             }
163              
164             sub datanode_live_list{
165             my $self=shift;
166             return keys %{$self->{'NameNodeInfo_LiveNodes'}};
167             }
168              
169             sub datanode_dead_list{
170             my $self=shift;
171             return keys %{$self->{'NameNodeInfo_DeadNodes'}};
172             }
173              
174             sub datanode_decom_list{
175             my $self=shift;
176             return keys %{$self->{'NameNodeInfo_DecomNodes'}};
177             }
178              
179              
180             sub nodemanager_live_list{
181             my $self=shift;
182             my @returnValue=();
183             foreach my $hostref ( @{$self->{'RMNMInfo_LiveNodeManagers'}} ) {
184             push @returnValue, $hostref->{'HostName'};
185             }
186             return @returnValue;
187             }
188              
189             sub tasktracker_live_list{
190             my $self=shift;
191             my @returnValue=();
192             use Data::Dumper;
193             foreach my $hostref ( @{$self->{'JobTrackerInfo_AliveNodesInfoJson'}} ) {
194             push @returnValue, $hostref->{'hostname'};
195             }
196             return @returnValue;
197             }
198              
199             sub tasktracker_blacklist_list{
200             my $self=shift;
201             my @returnValue=();
202             foreach my $hostref ( @{$self->{'JobTrackerInfo_BlacklistedNodesInfoJson'}} ) {
203             push @returnValue, $hostref->{'hostname'};
204             }
205             return @returnValue;
206             }
207              
208             sub tasktracker_graylist_list{
209             my $self=shift;
210             my @returnValue=();
211             foreach my $hostref ( @{$self->{'JobTrackerInfo_BlacklistedNodesInfoJson'}} ) {
212             push @returnValue, $hostref->{'hostname'};
213             }
214             return @returnValue;
215             }
216              
217             sub gather_nn_jmx{
218             my $self=shift;
219             my $bean=shift;
220             my $qry;
221             if ($bean eq 'NameNodeInfo'){
222             $qry='Hadoop%3Aservice%3DNameNode%2Cname%3DNameNodeInfo';
223             }
224             my $jmx_url= "http://".$self->get_namenode.":".$self->get_namenode_port."/jmx?qry=$qry";
225             my $response = $self->{'ua'}->get($jmx_url);
226             if (! $response->is_success) {
227             print "Can't get JMX data from Namenode: $@";
228             exit(1);
229             }
230             $self->parse_nn_jmx($response->decoded_content);
231             }
232              
233             sub parse_nn_jmx{
234             my $self=shift;
235             my $nn_content=shift;
236             my $json=new JSON();
237             my $json_text = $json->allow_nonref->utf8->relaxed->escape_slash->loose->allow_singlequote->allow_barekey->pretty->decode($nn_content);
238             foreach my $bean (@{$json_text->{beans}}){
239             if ($bean->{name} eq "Hadoop:service=NameNode,name=NameNodeInfo"){
240             foreach my $var (keys %{$bean}){
241             $self->{"NameNodeInfo_$var"}=$bean->{$var};
242             }
243             $self->{'NameNodeInfo_LiveNodes'}=$json->allow_nonref->utf8->relaxed->escape_slash->loose->allow_singlequote->allow_barekey->pretty->decode($bean->{LiveNodes});
244             $self->{'NameNodeInfo_DeadNodes'}=$json->allow_nonref->utf8->relaxed->escape_slash->loose->allow_singlequote->allow_barekey->pretty->decode($bean->{DeadNodes});
245             $self->{'NameNodeInfo_DecomNodes'}=$json->allow_nonref->utf8->relaxed->escape_slash->loose->allow_singlequote->allow_barekey->pretty->decode($bean->{DecomNodes});
246             }
247            
248             }
249             }
250              
251             sub gather_jt_jmx{
252             my $self=shift;
253             my $bean=shift;
254             my $qry;
255             if ($bean eq "JobTrackerInfo"){
256             $qry='Hadoop%3Aservice%3DJobTracker%2Cname%3DJobTrackerInfo';
257             }
258             my $jmx_url= "http://".$self->get_jobtracker.":".$self->get_jobtracker_port."/jmx?qry=$qry";
259             my $response = $self->{'ua'}->get($jmx_url);
260             if (! $response->is_success) {
261             print "Can't get JMX data from JobTracker: $@";
262             exit(1);
263             }
264             $self->parse_jt_jmx($response->decoded_content);
265              
266             }
267              
268             sub parse_jt_jmx{
269             my $self=shift;
270             my $jt_content=shift;
271             my $json=JSON->new();
272             my $json_text = $json->allow_nonref->utf8->relaxed->escape_slash->loose->allow_singlequote->allow_barekey->pretty->decode($jt_content);
273             foreach my $bean (@{$json_text->{beans}}){
274             foreach my $var (keys %{$bean}){
275             $self->{"JobTrackerInfo_$var"}=$bean->{$var};
276             }
277             if ($bean->{name} eq "Hadoop:service=JobTracker,name=JobTrackerInfo"){
278             $self->{'JobTrackerInfo_AliveNodesInfoJson'}=$json->allow_nonref->utf8->relaxed->escape_slash->loose->allow_singlequote->allow_barekey->pretty->decode($bean->{AliveNodesInfoJson});
279             $self->{'JobTrackerInfo_BlacklistedNodesInfoJson'}=$json->allow_nonref->utf8->relaxed->escape_slash->loose->allow_singlequote->allow_barekey->pretty->decode($bean->{BlacklistedNodesInfoJson});
280             $self->{'JobTrackerInfo_GraylistedNodesInfoJson'}=$json->allow_nonref->utf8->relaxed->escape_slash->loose->allow_singlequote->allow_barekey->pretty->decode($bean->{GraylistedNodesInfoJson});
281             }
282            
283             }
284             }
285             sub gather_rm_jmx{
286             my $self=shift;
287             my $bean=shift;
288             my $qry;
289             if ($bean eq "RMNMInfo"){
290             $qry='Hadoop%3Aservice%3DResourceManager%2Cname%3DRMNMInfo';
291             }
292             my $jmx_url= "http://".$self->get_resourcemanager.":".$self->get_resourcemanager_port."/jmx?qry=$qry";
293             my $response = $self->{'ua'}->get($jmx_url);
294             if (! $response->is_success) {
295             print "Can't get JMX data from ResourceManager: $@";
296             exit(1);
297             }
298             $self->parse_rm_jmx($response->decoded_content);
299             }
300              
301             sub parse_rm_jmx{
302             my $self=shift;
303             my $rm_content=shift;
304             my $json=JSON->new();
305             my $json_text = $json->allow_nonref->utf8->relaxed->escape_slash->loose->allow_singlequote->allow_barekey->pretty->decode($rm_content);
306             foreach my $bean (@{$json_text->{beans}}){
307             foreach my $var (keys %{$bean}){
308             $self->{"RMNMInfo_$var"}=$bean->{$var};
309             }
310             if ($bean->{name} eq "Hadoop:service=ResourceManager,name=RMNMInfo"){
311             $self->{'RMNMInfo_LiveNodeManagers'}=$json->allow_nonref->utf8->relaxed->escape_slash->loose->allow_singlequote->allow_barekey->pretty->decode($bean->{LiveNodeManagers});
312             }
313            
314             }
315             }
316              
317             1;
318              
319              
320             __END__
321             =pod
322              
323             =head1 NAME
324              
325             Hadoop::Admin - Module for administration of Hadoop clusters
326              
327             =head1 VERSION
328              
329             version 0.4
330              
331             =head1 SYNOPSIS
332              
333             use Hadoop::Admin;
334              
335             my $cluster=Hadoop::Admin->new({
336             'namenode' => 'namenode.host.name',
337             'jobtracker' => 'jobtracker.host.name',
338             });
339              
340             print $cluster->datanode_live_list();
341              
342             =head1 DESCRIPTION
343              
344             This module connects to Hadoop servers using http. The JMX Proxy
345             Servlet is queried for specific mbeans.
346              
347             This module requires Hadoop the changes in
348             https://issues.apache.org/jira/browse/HADOOP-7144. They are available
349             in versions 0.20.204.0, 0.23.0 or later.
350              
351             =head1 INTERFACE FUNCTIONS
352              
353             =head2 new ()
354              
355             =over 4
356              
357             =item Description
358              
359             Create a new instance of the Hadoop::Admin class.
360              
361             The method requires a hash containing at minimum one of the
362             namenode's, the resourcemanager's, and the jobtracker's hostnames.
363             Optionally, you may provide a socksproxy for the http connection. Use
364             of both a jobtracker and resourcemanger is prohibited. It is not a
365             valid cluster configuration to have both a jobtracker and a
366             resourcemanager.
367              
368             Creation of this object will cause an immediate querry to servers
369             provided to the constructor.
370              
371             =item namenode => <hostname>
372              
373             =item namenode_port => <port number>
374              
375             =item jobtracker => <hostname>
376              
377             =item jobtracker_port => <port number>
378              
379             =item resourcemanager => <hostname>
380              
381             =item resourcemanager_port => <port number>
382              
383             =item socksproxy => <hostname>
384              
385             =item socksproxy_port => <port number>
386              
387             =back
388              
389             =head2 datanode_live_list ()
390              
391             =over 4
392              
393             =item Description
394              
395             Returns a list of the current live DataNodes.
396              
397             =item Return values
398              
399             Array containing hostnames.
400              
401             =back
402              
403             =head2 datanode_dead_list ()
404              
405             =over 4
406              
407             =item Description
408              
409             Returns a list of the current dead DataNodes.
410              
411             =item Return values
412              
413             Array containing hostnames.
414              
415             =back
416              
417             =head2 datanode_decom_list ()
418              
419             =over 4
420              
421             =item Description
422              
423             Returns a list of the currently decommissioning DataNodes.
424              
425             =item Return values
426              
427             Array containing hostnames.
428              
429             =back
430              
431             =head2 nodemanager_live_list ()
432              
433             =over 4
434              
435             =item Description
436              
437             Returns a list of the current live NodeManagers.
438              
439             =item Return values
440              
441             Array containing hostnames.
442              
443             =back
444              
445             =head2 tasktracker_live_list ()
446              
447             =over 4
448              
449             =item Description
450              
451             Returns a list of the current live TaskTrackers.
452              
453             =item Return values
454              
455             Array containing hostnames.
456              
457             =back
458              
459             =head2 tasktracker_blacklist_list ()
460              
461             =over 4
462              
463             =item Description
464              
465             Returns a list of the current blacklisted TaskTrackers.
466              
467             =item Return values
468              
469             Array containing hostnames.
470              
471             =back
472              
473             =head2 tasktracker_graylist_list ()
474              
475             =over 4
476              
477             =item Description
478              
479             Returns a list of the current graylisted TaskTrackers.
480              
481             =item Return values
482              
483             Array containing hostnames.
484              
485             =back
486              
487             =head1 KNOWN BUGS
488              
489             None known at this time. Please log issues at:
490              
491             https://github.com/cwimmer/hadoop-admin/issues
492              
493             =head1 AVAILABILITY
494              
495             Source code is available on GitHub:
496              
497             https://github.com/cwimmer/hadoop-admin
498              
499             Module available on CPAN as Hadoop::Admin:
500              
501             http://search.cpan.org/~cwimmer/
502              
503             =for Pod::Coverage gather_jt_jmx
504             gather_nn_jmx
505             gather_rm_jmx
506             parse_jt_jmx
507             parse_nn_jmx
508             parse_rm_jmx
509             BUILD
510              
511             =head1 AUTHOR
512              
513             Charles A. Wimmmer (charles@wimmer.net)
514              
515             =head1 COPYRIGHT AND LICENSE
516              
517             This software is Copyright (c) 2012 by Charles A. Wimmer.
518              
519             This is free software, licensed under:
520              
521             The (three-clause) BSD License
522              
523             =cut
524