8549ebee80baaeb0c7c000251379c99dcec99752
[APKPM.git] / lib / APKPM / CPE.pm
1 package APKPM::CPE;
2
3 use base qw(Gearman::Driver::Worker);
4 use Moose;
5 use Time::HiRes qw(time);
6 use Data::Dump qw(dump);
7 use Redis;
8 use Net::Ping;
9
10 with 'APKPM::Gearman::Client';
11 with 'APKPM::Gearman';
12
13 sub prefix { 'CPE_' }
14
15 sub poll : Job : Encode(e_json) {
16         my ( $self, $job, $workload ) = @_;
17
18         my $redis = Redis->new;
19         $redis->del( $_ ) foreach $redis->keys('CPE.*');
20
21         my $start = $self->datetime_now;
22
23         $redis->set( 'CPE.start' => $start );
24
25         my $entries = $self->do( 'LDAP_search' => "(&(cn=$workload*)(dhcpStatements=*))" );
26
27         my $taskset = $self->gc->new_task_set;
28         my $results;
29
30         foreach my $entry ( @$entries ) {
31
32                 my $username = $entry->{cn} || die "no cn in ", dump($entry);
33
34                 if ( $entry->{dhcpStatements} !~ m/fixed-address\s+(\S+)/ ) {
35                         $redis->sadd('CPE.error.no-ip' => $username);
36                         next;
37                 }
38                 my $ip = $1;
39
40                 if ( $entry->{dhcpOption} !~ m/vendor-class-identifier\s\"([^"]+)\"/ ) {
41                         $redis->sadd('CPE.error.vendor' => $username);
42                         next;
43                 }
44
45                 my $vendor = $1;
46
47                 $taskset->add_task('CPE_ping', "$ip $username $vendor", {
48                         on_complete => sub { push @$results, ${$_[0]} }
49                 });
50                 $redis->sadd('CPE.queued' => $ip);
51
52                 $vendor =~ s/\s+/_/g; # sadd dies on spaces in keys
53                 $redis->sadd("CPE.vendor.$vendor" => $ip); # FIXME
54         }
55
56         warn "# wait";
57         $taskset->wait;
58
59         my $finish = $self->datetime_now;
60         $redis->set( 'CPE.finish' => $finish );
61
62         my $poll;
63         foreach my $k ( $redis->keys('CPE.*') ) {
64                 my $n = $k;
65                 $n =~ s/^CPE\.//;
66                 $n =~ s/\./_/g;
67                 $poll->{$n} = eval { $redis->scard($k) } || $redis->get($k);
68         }
69
70         warn "# poll = ",dump $poll;
71         $self->do_background_json('Store_insert', { _table => 'CPE_poll', %$poll });
72
73         warn "# results = ", dump $results;
74         return $poll;
75 }
76
77 sub ping : Job : Decode(d_array) : Encode(e_json) {
78         my ( $self, $job, $workload ) = @_;
79
80         my ( $ip, $username, $vendor ) = @$workload;
81
82         my $redis = Redis->new;
83
84         return { error => "invalid workload", expected => "ip username" } unless $ip && $username;
85
86         my $p = Net::Ping->new;
87         $p->hires;
88
89         my ( $ok, $rtt, $ping_ip ) = $p->ping( $ip );
90
91         if ( $ok ) {
92                 $redis->sadd( 'CPE.ping.ok' => $ip );
93         } else {
94                 $redis->sadd( 'CPE.ping.error' => $ip );
95                 return { error => "ping $ip" };
96         }
97
98         $self->do_background_json( 'Store_insert', {
99                  _table => 'ping',
100                 username => $username,
101                 timestamp => $self->datetime_now,
102                 ip => $ping_ip,
103                 rtt => $rtt,
104         });
105
106         if ( $vendor =~ m/SAMSUNG/ ) {
107                 $redis->sadd( 'CPE.Davolink.queued' => $username );
108                 $self->do_background( 'Davolink_info', "$ip $username adsl" );
109         } elsif ( $vendor =~ m/zte/ ) {
110                 $redis->sadd( 'CPE.EasyGateway.queued' => $ip );
111                 $self->do_background( 'EasyGateway_info', $ip );
112         } else {
113                 $redis->sadd( 'CPE.skipped' => $username );
114         }
115
116         return { ip => $ip, rtt => $rtt };
117 }
118
119 1;