forum.bitel.ru http://forum.bitel.ru/ |
|
Управление manad linux в зависимости от типа правила http://forum.bitel.ru/viewtopic.php?f=7&t=2352 |
Страница 1 из 1 |
Автор: | stels [ 25 май 2009, 19:51 ] |
Заголовок сообщения: | Управление manad linux в зависимости от типа правила |
Конфигурация Код: user_rule.editor.class=bitel.billing.module.services.ipn.editor.ManadContractRuleEditor gate_manager.class=bitel.billing.server.ipn.ManadGateWorker use.script=1 Скрипт Код: import java.io.*;
import java.net.*; import java.util.*; import bitel.billing.common.module.ipn.*; import bitel.billing.server.ipn.bean.*; void doSync() { host = gate.getHost(); port = gate.getPort(); gid = gate.getId(); if ( log.isDebugEnabled() ) { log.debug( gid + " gate: " + host + ":" + port ); } socket = new Socket( host, port ); out = new PrintWriter( socket.getOutputStream(), true ); isr = new InputStreamReader( socket.getInputStream() ); in = new BufferedReader( isr ); out.println( "test" ); kods = in.readLine(); if ( log.isDebugEnabled() ) { log.debug( gid + " Test => " + kods + "\n" ); } // список открытых договоров с шлюза gateRules = new HashSet( 5, 5 ); st = new StringTokenizer( kods ); while ( st.hasMoreTokens() ) { gateRules.add( new Integer( st.nextToken() ) ); } for( i = 0; i < statusList.size(); i++ ) { status = statusList.get(i); cid = status.contractId; // флаг того то правило есть на шлюзе flag = false; // правило для этого договора есть на шлюзе if ( gateRules.contains( cid ) ) { // если правило есть и юзер открыт делаем проверку шейпера if ( status.status == IPNContractStatus.STATUS_OPEN ) { rule = getRule( status ); command = "check\t" + cid.intValue() + "\t" + rule; out.println( command ); if ( log.isDebugEnabled() ) { log.debug( gid + " " + command ); } } // если правило есть а юзер заблокирован - удаляем правило if ( status.status > 0 ) { rule = getRule( status ); command = "remove\t" + cid.intValue() + "\t" + rule; out.println( command ); if ( log.isDebugEnabled() ) { log.debug( gid + " " + command ); } } flag = true; gateRules.remove( cid ); } // правила нет, а юзер открыт if ( !flag && status.status == IPNContractStatus.STATUS_OPEN ) { rule = getRule( status ); command = "add\t" + cid.intValue() + "\t" + rule; out.println( command ); if ( log.isDebugEnabled() ) { log.debug( gid + " " + command ); } } } in.close(); out.close(); socket.close(); } getRule( status ) { rule = null; // пользовательское правило, без типа if( status.ruleType == null ) { rule = status.rule.getRuleText(); } // типизированное правило else { rule = generateRule( status.rule.getRuleText(), status.gateType, status.ruleType ); } rule = rule.replaceAll( "\r", "" ); rule = rule.replaceAll( "\n", "|" ); return rule; } generateRule( addresses, gateType, ruleType ) { ruleText = ManadUtils.getRule( gateType, ruleType ); return ManadUtils.generateRule( ruleText, addresses, null, ruleType ); } Сам манад чуть попозже, есть одна неоднозначость которую решить надо. |
Автор: | stels [ 26 май 2009, 17:09 ] |
Заголовок сообщения: | |
Код: #!/usr/bin/perl
use POSIX; use IO::Socket; use IO::Select; use Socket; use Fcntl; use Tie::RefHash; $debug = 1; $port = 4567; $iptables = "/sbin/iptables"; $rule_insert_index = 1; $| = 1; print "starting manad..\n"; # База данных правил клиентов %CLRULE = (); %NRULE = (); %RUL_NUMBERS = (); %DEL_RULES = (); %CHECK_RULES = (); %CONTRACT_INDEX = (); # Начать с пустыми буферами %inbuffer = (); %outbuffer = (); %ready = (); tie %ready, 'Tie::RefHash'; # Прослушивать порт $server = IO::Socket::INET->new( LocalPort => $port, Listen => 10 ) or die "Can`t make server socket: $@\n"; nonblock( $server ); $SIG{INT} = sub { $server->close(); exit( 0 ); }; $select = IO::Select->new( $server ); $pid = getpid(); open(FILE, ">/var/run/manad.pid"); print FILE $pid; close(FILE); # Устанавливаем новый root каталог для процесса # chroot( $homedir ) or die "Couldn`t chroot to $homedir: $!\n"; # Главный цикл: проверка чтения/принятия, проверка записи, # проверка готовности к работе while( 1 ) { my $client; my $rv; my $data; # Проверить наличие новой информации на имеющихся подключениях # Есть ли что-нибудь для чтения или подтверждения? foreach $client ( $select->can_read( 1 ) ) { if ( $client == $server ) { # Принять новое подключение $client = $server->accept(); $select->add( $client ); nonblock( $client ); } else { # Прочитать данные $data = ''; $rv = $client->recv( $data, POSIX::BUFSIZ, 0 ); unless( defined( $rv ) && length $data ) { # Это должен быть конец файла, поэтому закрываем клиента delete $inbuffer{$client}; delete $outbuffer{$client}; delete $ready{$client}; $select->remove( $client ); close $client; next; } $inbuffer{$client} .= $data; # Проверить, говорят ли данные в буфере или только что прочитанные # данные о наличии полного запроса, ожидающего выполнения. Если да - # заполнить $ready{$client} запросами, ожидающими обработки. while( $inbuffer{$client} =~ s/(.*\n)// ) { push( @{$ready{$client}}, $1 ) } } } # Есть ли полные запросы для обработки? foreach $client ( keys %ready ) { handle( $client ); } # Сбрасываем буферы? foreach $client ( $select->can_write( 1 ) ) { # Пропустить этого клиента, если нам нечего сказать next unless $outbuffer{$client}; $rv = $client->send( $outbuffer{$client}, 0 ); unless( defined $rv ) { # Пожаловаться, но следовать дальше warn "I was told I could write? but I can`t.\n"; next; } if ( $rv == length $outbuffer{$client} || $! == POSIX::EWOULDBLOCK ) { substr( $outbuffer{$client}, 0, $rv ) = ''; delete $outbuffer{$client} unless length $outbuffer{$client}; } else { # Не удалось записать все данные и не из-за блокировки. # Очистить буферы и следовать дальше. delete $inbuffer{$client}; delete $outbuffer{$client}; delete $ready{$client}; $select->remove($client); close($client); next; } } } # handle( $socket ) обрабатывает все необработанные запросы # для клиента $client sub handle { # Запрос находится в $ready{$client} # Отправить вывод в $outbuffer{$client} my $client = shift; my $request; foreach $request ( @{$ready{$client}} ) { print "\nrequest =".$request."\n" if ( $debug == 1 ); if ( $request =~ /^test/ ) { my $open_client = ""; foreach my $kod ( keys %CLRULE ) { $open_client .= $open_client eq "" ? $kod : " ".$kod; } $outbuffer{$client} .= $open_client."\n"; } elsif ( $request =~ /^add\t([0-9]+)\t(.*)/ ) { my ($kod, $rule) = ($1, $2); &delete_rule( $kod, $rule ) if ( exists $CLRULE{$kod} ); &add_rule( $kod, $rule ) if ( !exists $CLRULE{$kod} ); } elsif ( $request =~ /^remove\t([0-9]+)(\t(.*))?/ ) { my $kod = $1; &delete_rule( $kod ) if ( exists $CLRULE{$1} ); } elsif ( $request =~ /^check\t([0-9]+)\t(.*)/ ) { my ($kod, $rule) = ($1, $2); &check_rule( $kod, $rule ) if ( exists $CLRULE{$1} ); } } delete $ready{$client}; } # nonblock( $socket ) переводит сокет в неблокирующий режим sub nonblock { my $socket = shift; my $flags; $flags = fcntl( $socket, F_GETFL, 0 ) or die "Can`t get flags for socket: $!\n"; fcntl( $socket, F_SETFL, $flags | O_NONBLOCK ) or die "Can`t make socket nonblocking: $!\n"; } sub add_rule { my $kod = $_[0]; my $rule = $_[1]; #заменяем все контсрукции типа {N0} while ( $rule =~ /\[N([0-9]+)\]/ ) { my $n = $1; my $i = 20; #находим первый свободный номер while( 1 ) { $i++; last if ( !exists $RUL_NUMBERS{$i} ); } $RUL_NUMBERS{$i} = "1"; $rule =~ s/\[N$n\]/$i/g; $CONTRACT_INDEX{$kod}{$i}=$i; $NRULE{$kod}{$n} = $i; } $CLRULE{$kod} = $rule; #добавляем правило my $add_rule = $rule; $add_rule =~ s/\[OPEN\]((.|\n)+)\[\/OPEN\]((.|\n)*)/${1}/; print "commands:\n" if ( $debug == 1 ); my @rules = split( /\|/, $add_rule ); foreach $line ( @rules ) { print "$line\n" if ( $debug == 1 ); $err = `$line`; } #запоминаем правило на удаление в кэш my $del_rule = $rule; $del_rule =~ s/(?:(.|\n?:)*)\[CLOSE\]((.|\n)+)\[\/CLOSE\]((.|\n)*)/${2}/; print "\ndelete =".$del_rule."\n" if ( $debug == 1 ); $DEL_RULES{$kod}=$del_rule; my $check_rule = $rule; $check_rule =~ s/(?:(.|\n?:)*)\[CHECK\]((.|\n)+)\[\/CHECK\]((.|\n)*)/${2}/; print "\ncheck =".$check_rule."\n" if ( $debug == 1 ); $CHECK_RULES{$kod}=$check_rule; } sub check_rule { my $kod = $_[0]; my $rule = $_[1]; my $check_rule = $rule; $check_rule =~ s/(?:(.|\n?:)*)\[CHECK\]((.|\n)+)\[\/CHECK\]((.|\n)*)/${2}/; while ( $check_rule =~ /\[N([0-9]+)\]/ ) { my $n = $1; $check_rule =~ s/\[N$n\]/$NRULE{$kod}{$n}/g; } $CHECK_RULES{$kod}=$check_rule; print "rules\n"; print "$CHECK_RULES{$kod}"; my $rule = $CHECK_RULES{$kod}; my @rules = split( /\|/, $rule ); print "commands:\n" if ( $debug == 1 ); foreach $line ( @rules ) { print "$line\n" if ( $debug == 1 ); $err = `$line`; } } sub delete_rule { my $kod = $_[0]; my $rule = $DEL_RULES{$kod}; my @rules = split( /\|/, $rule ); print "commands:\n" if ( $debug == 1 ); foreach $line ( @rules ) { print "$line\n" if ( $debug == 1 ); $err = `$line`; } delete $DEL_RULES{$kod}; delete $CHECK_RULES{$kod}; delete $NRULE{$kod}; delete $CLRULE{$kod}; foreach my $idx ( keys %{$CONTRACT_INDEX{$kod}} ) { print "\n deleting rules with idx=".$CONTRACT_INDEX{$kod}{$idx}."\n"; delete $RUL_NUMBERS{$CONTRACT_INDEX{$kod}{$idx}}; } delete $CONTRACT_INDEX{$kod}; } Теперь в теги [CHECK]пишем все что угодно[/CHECK] |
Автор: | niceone [ 26 май 2009, 17:23 ] |
Заголовок сообщения: | |
Мужик, ну это реально круто. Скажи под какую версию эта вся телега у тебя работает ? |
Автор: | stels [ 26 май 2009, 17:47 ] |
Заголовок сообщения: | |
bgbilling 4.5, но насколько я понимаю особо разницы в версии нет, тут же все на скриптах |
Автор: | stels [ 26 май 2009, 17:52 ] |
Заголовок сообщения: | |
Ну и напоследок для совсем ленивых Команды: Код: [DEFAULT] [OPEN] [/OPEN] [CLOSE] [/CLOSE] [CHECK] /usr/local/manad/changetc.sh 1:[N1] ${speed} [/CHECK] [/DEFAULT] Сам скрипт Код: #!/bin/sh
if [ `tc class show dev eth0|awk '''$3=="'$1'"{print $11}'` != "$2" ]; then ( tc class change dev eth0 parent 1:1 classid $1 htb rate $2 burst 8k prio 1 ) fi Ну вот вроде все поправляйте где ошибся |
Страница 1 из 1 | Часовой пояс: UTC + 5 часов [ Летнее время ] |
Powered by phpBB® Forum Software © phpBB Group http://www.phpbb.com/ |