use Modern::Perl; use utf8; use telnet; use Mojo::AsyncAwait; use Data::Dumper; our $log; sub bdcom_extract_onu_num { my $onu_name = shift; $onu_name =~ m|EPON0/\d+:(\d+)|; return $1; } sub bdcom_extract_onu_info { my @lines = @_; return map([substr($_, 0, 11), split(' ', substr($_, 11, -1))], @lines[3..@lines-3]); } async bdcom_login => sub { my $t = shift; my $login = shift; my $password = shift; await $t->connect; await $t->reply(qr/Username:/, $login); await $t->reply(qr/Password:/, $password); my @greeting = await $t->waitfor(qr/>/); my $version = "C"; for (@greeting) { $version = $1 if /Welcome to BDCOM P3310(\w)/; } $t->print("enable"); my @next = await $t->waitfor(qr/#|password:/); if (grep {$_ =~ /password:/} @next) { $t->print($password); await $t->waitfor(qr/#/); } $t->prompt(qr/#/); await $t->cmd("terminal length 0"); await $t->cmd("terminal width 200"); }; async bdcom_get_onu_info => sub { my $t = shift; my $tree = shift; my @inactive_onu = await $t->cmd("show epon inactive-onu interface ePON 0/$tree"); $inactive_onu[0] =~ m|Interface EPON0/\d+ has bound (\d+)|; my $inactive_count = $1 || "?"; if (@inactive_onu <= 1) { $inactive_count = 0; } my @active_onu = await $t->cmd("show epon active-onu interface ePON 0/$tree"); $active_onu[0] =~ m|Interface EPON0/\d+ has bound (\d+)|; my $active_count = $1 || "?"; if (@active_onu <= 1) { $active_count = 0; } my $total_count = $active_count + $inactive_count; my @in_onu_info = bdcom_extract_onu_info(@inactive_onu); my @compact_in_onu_info = map( [bdcom_extract_onu_num(@$_[0]), @$_[1]], @in_onu_info ); #@compact_in_onu_info = map( join(" ", @$_), @compact_in_onu_info); # say Dumper @active_onu; my @a_onu_info = bdcom_extract_onu_info(@active_onu); # say "test2"; my @compact_a_onu_info = map( [bdcom_extract_onu_num(@$_[0]), @$_[1]], @a_onu_info ); #@compact_a_onu_info = map( join(" ", @$_), @compact_a_onu_info); my %res = ( 'total_cnt' => $total_count, 'active_cnt' => $active_count, 'inactive_cnt' => $inactive_count, 'active' => [ @compact_a_onu_info ], 'inactive' => [ @compact_in_onu_info ], ); return %res; }; async bdcom_fun_purge_tree => sub { my $t = shift; my $tree = shift; my $onu_info = shift; my %onu_info = %{$onu_info}; await $t->cmd("config"); await $t->cmd("interface EPON0/$tree"); # say Dumper %onu_info; foreach my $i ( @{$onu_info{'inactive'}} ) { # say Dumper @$i[1]; my $onu_mac = @$i[1]; # say Dumper $onu_mac; my @tmp = await $t->cmd("no epon bind-onu mac $onu_mac"); # say ADumper @tmp; } my @deleted_onu = map { sprintf("%2d %s", $_->[0], $_->[1]) } @{$onu_info{inactive}}; await $t->cmd("exit"); return @deleted_onu; }; async bdcom_inspect => sub { my $ip = shift; my $login = shift; my $password = shift; my $tree = shift; ############################ my $t = new telnet($ip); # $t->debug(1); await bdcom_login($t, $login, $password); ####################### my %onu_info = await bdcom_get_onu_info($t, $tree); $t->close; my $res = "Всего: $onu_info{'total_cnt'}; Количество активных ONU: $onu_info{'active_cnt'}; Количество неактивных ONU: $onu_info{'inactive_cnt'}; \n"; $res = $res . "Неактивные ONU:\n" . join("\n", map( join(" ", @$_), @{$onu_info{'inactive'}} ) ) . "\n\n"; $res = $res . "Активные ONU:\n" . join("\n", map( join(" ", @$_), @{$onu_info{'active'}} ) ); return $res; }; async bdcom_onu => sub { my $ip = shift; my $login = shift; my $password = shift; my $tree = shift; ############################ my $t = new telnet($ip); # $t->debug(1); await bdcom_login($t, $login, $password); ####################### my %onu_info = await bdcom_get_onu_info($t, $tree); $t->close; my $res = "Всего: $onu_info{'total_cnt'}; Количество активных ONU: $onu_info{'active_cnt'}; Количество неактивных ONU: $onu_info{'inactive_cnt'}; \n"; return $res; }; async bdcom_purge => sub { my $ip = shift; my $login = shift; my $password = shift; my $tree = shift; my $save = shift; ############################ my $t = new telnet($ip); # $t->debug(1); await bdcom_login($t, $login, $password); ####################### my %onu_info = await bdcom_get_onu_info($t, $tree); if ($onu_info{'inactive_cnt'} == 0) { $t->close; return "Нечего чистить"; } my @deleted_onu = await bdcom_fun_purge_tree($t, $tree, \%onu_info); %onu_info = await bdcom_get_onu_info($t, $tree); if ($save) { await $t->cmd("write all"); } $t->close; my $res = "Осталось ONU: $onu_info{'total_cnt'}\n"; if ( $onu_info{'active_cnt'} != $onu_info{'total_cnt'} ) { $res = $res . "Общее количество ONU и количество активных ONU не совпадает. Лучше обратиться к Вашему системному администратору\n"; } $res = $res . "Удалённые ONU: " . scalar @deleted_onu . "\n"; $log->info("IP $ip TREE $tree\n" . join("\n", @deleted_onu)); return $res; }; async bdcom_purgeall => sub { my $ip = shift; my $login = shift; my $password = shift; my $tree_count = shift; my $save = shift; ############################ my @res; my $t = new telnet($ip); # $t->debug(1); await bdcom_login($t, $login, $password); ####################### for (my $tree=1; $tree <= $tree_count; $tree++) { my $res = "Дерево $tree\n"; my %onu_info = await bdcom_get_onu_info($t, $tree); if ($onu_info{'inactive_cnt'} == 0) { $res = $res . "Не имеет неактивных ONU\n"; push @res, $res; next; } my @deleted_onu = await bdcom_fun_purge_tree($t, $tree, \%onu_info); # say Dumper @deleted_onu; %onu_info = await bdcom_get_onu_info($t, $tree); $res = $res . "Осталось ONU: $onu_info{'total_cnt'}\n"; $res = $res . "Удалённые ONU: " . scalar @deleted_onu . "\n"; $log->info("IP $ip TREE $tree\n" . join("\n", @deleted_onu)); push @res, $res; } if ($save) { await $t->cmd("write all"); } $t->close; return \@res; }; async bdcom_save => sub { my $ip = shift; my $login = shift; my $password = shift; ############################ my $t = new telnet($ip); # $t->debug(1); await bdcom_login($t, $login, $password); ####################### await $t->cmd("write all"); $t->close; my $res = "Сохранено\n"; return $res; }; 1;