File Coverage

blib/lib/Ubic/Service/ZooKeeper.pm
Criterion Covered Total %
statement 92 129 71.3
branch 12 40 30.0
condition n/a
subroutine 17 24 70.8
pod 11 12 91.6
total 132 205 64.3


line stmt bran cond sub pod time code
1             package Ubic::Service::ZooKeeper;
2             BEGIN {
3 1     1   160127 $Ubic::Service::ZooKeeper::VERSION = '0.02';
4             }
5              
6 1     1   10 use strict;
  1         1  
  1         35  
7 1     1   6 use warnings;
  1         2  
  1         28  
8              
9             # ABSTRACT: running ZooKeeper as Ubic service
10              
11              
12 1     1   10 use parent qw(Ubic::Service::Common);
  1         2  
  1         6  
13              
14 1     1   34464 use File::Copy qw(move);
  1         2196  
  1         70  
15 1     1   7 use File::Spec::Functions qw(catfile);
  1         3  
  1         42  
16 1     1   6 use IO::Socket::INET;
  1         1  
  1         11  
17 1     1   758 use Params::Validate qw(:all);
  1         2  
  1         194  
18 1     1   6 use Storable qw(dclone);
  1         2  
  1         39  
19 1     1   5 use Time::HiRes qw();
  1         2  
  1         16  
20 1     1   887 use Ubic::Daemon qw(:all);
  1         63978  
  1         11  
21 1     1   5603 use Ubic::Result qw(:all);
  1         2  
  1         1540  
22              
23              
24             sub new {
25 4     4 1 11699 my $class = shift;
26              
27 4         28 my $opt_num = { type => SCALAR, regex => qr/^\d+$/o, optional => 1 };
28 4         13 my $opt_str = { type => SCALAR, optional => 1 };
29              
30 4         255 my $params = validate(@_, {
31             config => { type => HASHREF, default => {} },
32             myid => { %$opt_num, default => 1 },
33              
34             # ubic specific options
35             status => { type => CODEREF, optional => 1 },
36             user => $opt_str,
37             ubic_log => $opt_str,
38             stdout => $opt_str,
39             stderr => $opt_str,
40             pidfile => $opt_str,
41             port => $opt_num,
42              
43             gen_cfg => $opt_str,
44             java => { %$opt_str, default => 'java' },
45             java_cp => { %$opt_str, default => '' },
46             jmx_enable => { type => BOOLEAN, default => 1 },
47             jmx_local_only => { type => BOOLEAN, default => 0 },
48             zoo_log_dir => { %$opt_str, default => '/var/log/zookeeper' },
49             zoo_log4j_prop => { %$opt_str, default => 'INFO,ROLLINGFILE' },
50             zoo_main_class => {
51             %$opt_str,
52             default => 'org.apache.zookeeper.server.quorum.QuorumPeerMain'
53             },
54             java_opts => { type => SCALAR, default => '' },
55             });
56              
57 4         76 my $config = $params->{config};
58 4         29 %$config = (
59             clientPort => 2181,
60             dataDir => '/var/lib/zookeeper',
61             tickTime => 2000,
62             %$config,
63             );
64              
65 4         10 my $clientPort = $config->{clientPort};
66              
67 4 50       14 if (!$params->{pidfile}) {
68 4         25 $params->{pidfile} = catfile('/tmp', 'zookeeper.' . $clientPort . '.pid');
69             }
70 4 100       13 if (!$params->{gen_cfg}) {
71 2         12 $params->{gen_cfg} = catfile('/tmp', 'zoo.' . $clientPort . '.cfg');
72             }
73              
74 4         28 return bless $params => $class;
75             }
76              
77              
78             sub bin {
79 1     1 0 6 my $self = shift;
80              
81 1         3 my $cmd = '';
82 1         16 $cmd = $self->{java} . " " . $self->{java_opts} . " " .
83             "-cp " . $self->{java_cp} . " ";
84 1 50       5 if ($self->{jmx_enable}) {
85 1         3 $cmd .= "-Dcom.sun.management.jmxremote ";
86 1 50       3 unless ($self->{jmx_local_only}) {
87 1         3 $cmd .= "-Dcom.sun.management.jmxremote.local.only=false ";
88             }
89             }
90 1         2 $cmd .= "-Dzookeeper.log.dir=$self->{zoo_log_dir} ";
91 1         3 $cmd .= "-Dzookeeper.root.logger=$self->{zoo_log4j_prop} ";
92 1         2 $cmd .= $self->{zoo_main_class} . " ";
93 1         4 $cmd .= $self->gen_cfg;
94              
95 1         3 return [ $cmd ];
96             }
97              
98              
99             sub create_cfg_file {
100 1     1 1 6 my $self = shift;
101              
102 1         3 my $fname = $self->gen_cfg;
103 1         3 my $tmp_fname = $fname . ".tmp";
104              
105              
106 1         54 my $params = dclone($self->{config});
107 1         5 my $servers = delete $params->{servers};
108 1         2 my $groups = delete $params->{groups};
109              
110 1 50       134 open(my $tmp_fh, '>', $tmp_fname) or die "Can't open file [$tmp_fname]: $!";
111              
112 1         13 foreach my $p (sort keys %$params) {
113 19         18 my $v = $params->{$p};
114 19         33 print $tmp_fh "$p=$v\n";
115             }
116 1         23 print $tmp_fh "\n";
117              
118 1         7 foreach my $server_num (sort {$a <=> $b} keys %$servers) {
  17         19  
119 9         11 my $s = $servers->{$server_num};
120 9         9 my $server = $s->{server};
121 9         15 print $tmp_fh "server.${server_num}=$server\n";
122              
123 9 50       16 if ($s->{weight}) {
124 9         19 print $tmp_fh "weight.${server_num}=$s->{weight}\n";
125             }
126             }
127 1         2 print $tmp_fh "\n";
128              
129 1         4 foreach my $group_num (sort {$a <=> $b} keys %$groups) {
  2         5  
130 3         5 my $group_servers = $groups->{$group_num};
131 3         9 print $tmp_fh "group.${group_num}=" . join(":", @$group_servers) . "\n";
132             }
133              
134 1 50       57 close($tmp_fh) or die "Can't close file [$tmp_fname]: $!";
135 1 50       7 move($tmp_fname, $fname) or die "Can't move file [${tmp_fname}] to [$fname]: $!";
136             }
137              
138              
139              
140             sub create_myid_file {
141 1     1 1 7 my $self = shift;
142              
143 1         5 my $fname = catfile($self->{config}->{dataDir}, 'myid');
144 1         4 my $tmp_fname = $fname . ".tmp";
145              
146 1 50       130 open(my $tmp_fh, '>', $tmp_fname) or die "Can't open file [$tmp_fname]: $!";
147 1         13 print $tmp_fh $self->{myid}, "\n";
148 1 50       49 close($tmp_fh) or die "Can't close file [$tmp_fname]: $!";
149 1 50       7 move($tmp_fname, $fname) or die "Can't move file [${tmp_fname} to [$fname]: $!";
150             }
151              
152             sub start_impl {
153 0     0 1 0 my $self = shift;
154              
155 0         0 $self->create_cfg_file;
156 0         0 $self->create_myid_file;
157              
158 0         0 my $daemon_opts = { bin => $self->bin, pidfile => $self->pidfile, term_timeout => 5 };
159 0         0 for (qw/ubic_log stdout stderr/) {
160 0 0       0 $daemon_opts->{$_} = $self->{$_} if defined $self->{$_};
161             }
162 0         0 start_daemon($daemon_opts);
163              
164 0         0 return;
165             }
166              
167             sub stop_impl {
168 0     0 1 0 my $self = shift;
169              
170 0         0 return stop_daemon($self->pidfile, { timeout => 7 });
171             }
172              
173             sub status_impl {
174 0     0 1 0 my $self = shift;
175              
176 0         0 my $running = check_daemon($self->pidfile);
177 0 0       0 return result('not running') unless ($running);
178              
179 0 0       0 if ($self->{status}) {
180 0         0 return $self->{status}->($self);
181             }
182              
183 0         0 my $sock = IO::Socket::INET->new(
184             PeerAddr => "localhost",
185             PeerPort => $self->port,
186             Proto => "tcp",
187             Timeout => 1,
188             Blocking => 0,
189             );
190 0 0       0 return result('broken') unless ($sock);
191              
192 0         0 $sock->print('ruok');
193 0         0 my $resp = '';
194 0         0 for (1..10) {
195 0         0 my $buff;
196 0         0 $sock->sysread($buff, 4);
197 0 0       0 $resp .= $buff if defined($buff);
198 0 0       0 last if (length($resp) >= 4);
199 0         0 Time::HiRes::sleep(0.1);
200             }
201              
202 0 0       0 if ($resp eq 'imok') {
203 0         0 return result('running');
204             } else {
205 0         0 return result('broken');
206             }
207             }
208              
209             sub user {
210 0     0 1 0 my $self = shift;
211              
212 0 0       0 return $self->{user} if defined $self->{user};
213 0         0 return $self->SUPER::user;
214             }
215              
216              
217             sub pidfile {
218 0     0 1 0 my $self = shift;
219              
220 0         0 return $self->{pidfile};
221             }
222              
223             sub gen_cfg {
224 2     2 1 3 my $self = shift;
225              
226 2         5 return $self->{gen_cfg};
227             }
228              
229             sub port {
230 0     0 1   my $self = shift;
231              
232 0 0         return $self->{port} if defined $self->{port};
233 0           return $self->{config}->{clientPort};
234             }
235              
236             sub timeout_options {
237             return {
238 0     0 1   start => { trials => 15, step => 0.1 },
239             stop => { trials => 15, step => 0.1 }
240             };
241             }
242              
243              
244             1;
245              
246             __END__