63 changed files with 789 additions and 1315 deletions
-
12abonapp/forms.py
-
64abonapp/locale/ru/LC_MESSAGES/django.po
-
7abonapp/migrations/0001_initial.py
-
21abonapp/migrations/0019_abon_ip_address.py
-
25abonapp/migrations/0020_auto_20170517_1655.py
-
33abonapp/models.py
-
1abonapp/templates/abonapp/buy_tariff.html
-
49abonapp/templates/abonapp/charts.html
-
49abonapp/templates/abonapp/editAbon.html
-
18abonapp/templates/abonapp/ext.htm
-
3abonapp/templates/abonapp/modal_abonamount.html
-
45abonapp/templates/abonapp/modal_extra_field.html
-
1abonapp/templates/abonapp/passport_view.html
-
23abonapp/templates/abonapp/peoples.html
-
3abonapp/tests.py
-
2abonapp/urls.py
-
4abonapp/urls_abon.py
-
200abonapp/views.py
-
9agent/core.py
-
15agent/mod_mikrotik.py
-
6agent/netflow/netflow_handler.sh
-
2agent/netflow/start_netflow.sh
-
125agent/netflow/to_mysql.c
-
66agent/netflow/to_mysql.py
-
1bugs.txt
-
4clientsideapp/templates/clientsideapp/ext.html
-
4clientsideapp/views.py
-
3cron.py
-
2devapp/dev_types.py
-
2devapp/forms.py
-
19dhcp_lever.py
-
1djing/settings_example.py
-
1djing/urls.py
-
1ip_pool/__init__.py
-
6ip_pool/admin.py
-
6ip_pool/apps.py
-
22ip_pool/forms.py
-
23ip_pool/migrations/0001_initial.py
-
0ip_pool/migrations/__init__.py
-
59ip_pool/models.py
-
48ip_pool/templates/ip_pool/add_pool.html
-
73ip_pool/templates/ip_pool/index.html
-
59ip_pool/templates/ip_pool/ips.html
-
15ip_pool/urls.py
-
81ip_pool/views.py
-
17mydefs.py
-
16searchapp/views.py
-
4static/css/all.min.css
-
8static/css/custom.css
-
31static/js/all.min.js
-
2static/js/bootstrap-datetimepicker.min.js
-
562static/js/datetime_with_moment.min.js
-
20static/js/my.js
-
6statistics/admin.py
-
53statistics/fields.py
-
18statistics/migrations/0002_delete_statelem.py
-
64statistics/models.py
-
12systemd_units/djing_rotate.service
-
11systemd_units/djing_rotate.timer
-
1taskapp/templates/taskapp/add_edit_task.html
-
1templates/404.html
-
11templates/base.html
-
4templates/message_block.html
@ -0,0 +1,21 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Generated by Django 1.9 on 2017-05-10 23:17 |
||||
|
from __future__ import unicode_literals |
||||
|
|
||||
|
from django.db import migrations |
||||
|
import mydefs |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('abonapp', '0018_auto_20170418_1236'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.AddField( |
||||
|
model_name='abon', |
||||
|
name='ip_address', |
||||
|
field=mydefs.MyGenericIPAddressField(blank=True, max_length=8, null=True, protocol='ipv4'), |
||||
|
), |
||||
|
] |
||||
@ -0,0 +1,25 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Generated by Django 1.9 on 2017-05-17 13:55 |
||||
|
from __future__ import unicode_literals |
||||
|
|
||||
|
from django.db import migrations, models |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('abonapp', '0019_abon_ip_address'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.AddField( |
||||
|
model_name='extrafieldsmodel', |
||||
|
name='title', |
||||
|
field=models.CharField(default='no title', max_length=16), |
||||
|
), |
||||
|
migrations.AlterField( |
||||
|
model_name='extrafieldsmodel', |
||||
|
name='field_type', |
||||
|
field=models.CharField(choices=[('int', 'Цифровое поле'), ('str', 'Текстовое поле'), ('dbl', 'Дробное с плавающей точкой'), ('ipa', 'IP Адрес')], default='str', max_length=3), |
||||
|
), |
||||
|
] |
||||
@ -0,0 +1,49 @@ |
|||||
|
{% extends request.is_ajax|yesno:'nullcont.htm,abonapp/ext.htm' %} |
||||
|
{% load i18n %} |
||||
|
{% block content %} |
||||
|
|
||||
|
<div class="row"> |
||||
|
<div class="col-sm-12"> |
||||
|
<div class="panel panel-default"> |
||||
|
<div class="panel-heading"> |
||||
|
<h3 class="panel-title">График использования</h3> |
||||
|
</div> |
||||
|
<div class="panel-body"> |
||||
|
{% if charts_data %} |
||||
|
<div id="chrt"></div> |
||||
|
<script type="text/javascript"> |
||||
|
$(document).ready(function ($) { |
||||
|
new Chartist.Line('#chrt', { |
||||
|
series: [ |
||||
|
{ |
||||
|
name: 'График траффика', |
||||
|
data: [ |
||||
|
{{ charts_data }} |
||||
|
] |
||||
|
} |
||||
|
] |
||||
|
}, { |
||||
|
height: '600px', |
||||
|
showArea: true, |
||||
|
showLine: false, |
||||
|
showPoint: false, |
||||
|
high: {{ high }}, |
||||
|
axisX: { |
||||
|
type: Chartist.FixedScaleAxis, |
||||
|
divisor: 12, |
||||
|
labelInterpolationFnc: function (value) { |
||||
|
return moment(value).format('HH:mm:ss'); |
||||
|
} |
||||
|
} |
||||
|
}); |
||||
|
}); |
||||
|
</script> |
||||
|
{% else %} |
||||
|
<h2>Траффик не найден</h2> |
||||
|
{% endif %} |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
{% endblock %} |
||||
@ -0,0 +1,45 @@ |
|||||
|
{% load i18n %} |
||||
|
|
||||
|
<form role="form" action="{% url 'abonapp:extra_field' gid abon.pk %}" method="post"> {% csrf_token %} |
||||
|
<div class="modal-header primary"> |
||||
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> |
||||
|
<h4 class="modal-title"><span class="glyphicon glyphicon-plus"></span> {% trans 'Add extra field' %}</h4> |
||||
|
</div> |
||||
|
|
||||
|
<div class="modal-body"> |
||||
|
<div class="form-group"> |
||||
|
<label for="id_title">{% trans 'Field title' %}</label> |
||||
|
|
||||
|
<div class="input-group"> |
||||
|
<span class="input-group-addon"><span class="glyphicon glyphicon-text-background"></span></span> |
||||
|
{{ frm.title }}{{ frm.title.errors }} |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="form-group"> |
||||
|
<label for="id_field_type">{% trans 'Field type' %}</label> |
||||
|
<div class="input-group"> |
||||
|
<span class="input-group-addon"><span class="glyphicon glyphicon-ice-lolly"></span></span> |
||||
|
{{ frm.field_type }}{{ frm.field_type.errors }} |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="form-group"> |
||||
|
<label for="id_data">{% trans 'Field content' %}</label> |
||||
|
<div class="input-group"> |
||||
|
<span class="input-group-addon"><span class="glyphicon glyphicon-paperclip"></span></span> |
||||
|
{{ frm.data }}{{ frm.data.errors }} |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
<div class="btn-group"> |
||||
|
<button type="submit" class="btn btn-success"> |
||||
|
<span class="glyphicon glyphicon-plus"></span> {% trans 'Add' %} |
||||
|
</button> |
||||
|
<button type="reset" class="btn btn-default"> |
||||
|
<span class="glyphicon glyphicon-remove-circle"></span> {% trans 'Reset' %} |
||||
|
</button> |
||||
|
</div> |
||||
|
</div> |
||||
|
|
||||
|
</form> |
||||
@ -1,125 +0,0 @@ |
|||||
#define _GNU_SOURCE |
|
||||
#include <stdio.h> |
|
||||
#include <stdlib.h> |
|
||||
#include <arpa/inet.h> |
|
||||
#include <string.h> |
|
||||
#include <stdint.h> |
|
||||
#include <stdbool.h> |
|
||||
#include <time.h> |
|
||||
|
|
||||
|
|
||||
#define FLOW_COLS 8 |
|
||||
#define uint unsigned int |
|
||||
|
|
||||
|
|
||||
uint32_t ip2int(const char* ip) |
|
||||
{ |
|
||||
uint32_t res = 0; |
|
||||
inet_pton(AF_INET, ip, &res); |
|
||||
return htonl(res); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
uint str_split(char* str, const char* delimiter, char** pInChunks) |
|
||||
{ |
|
||||
char* dat = strtok(str, " "); |
|
||||
register uint n=0; |
|
||||
while(dat) |
|
||||
{ |
|
||||
pInChunks[n++] = dat; |
|
||||
dat = strtok(NULL, " "); |
|
||||
} |
|
||||
return n; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
void curtime(char* pInStrTime, const uint maxlen) |
|
||||
{ |
|
||||
time_t rawtime; |
|
||||
time( &rawtime ); |
|
||||
strftime(pInStrTime, maxlen, "flowstat_%d%m%Y", localtime( &rawtime )); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
void convert(char* query, char* pInRes) |
|
||||
{ |
|
||||
char* chunks[FLOW_COLS] = {NULL}; |
|
||||
|
|
||||
int chunk_count = str_split(query, " ", chunks); |
|
||||
|
|
||||
if(chunk_count < 7) |
|
||||
{ |
|
||||
printf("Too short input line\n"); |
|
||||
exit(1); |
|
||||
} |
|
||||
|
|
||||
uint32_t src_ip = ip2int(chunks[0]); |
|
||||
uint32_t dst_ip = ip2int(chunks[1]); |
|
||||
uint proto = atoi(chunks[2]); |
|
||||
uint16_t src_port = ip2int(chunks[3]); |
|
||||
uint16_t dst_port = ip2int(chunks[4]); |
|
||||
uint octets = atoi(chunks[5]); |
|
||||
uint packets = atoi(chunks[6]); |
|
||||
|
|
||||
sprintf(pInRes, ",(%u,%u,%u,%u,%u,%u,%u)\0", |
|
||||
src_ip, dst_ip, proto, src_port, dst_port, octets, packets); |
|
||||
} |
|
||||
|
|
||||
|
|
||||
int main() |
|
||||
{ |
|
||||
char buf_result_convert[0xff] = {0}; |
|
||||
FILE* f = stdin; |
|
||||
char* input_line = malloc(0xff); |
|
||||
size_t input_line_len = 0; |
|
||||
ssize_t read_len = 0; |
|
||||
char table_name[19] = {0}; |
|
||||
|
|
||||
curtime(table_name, 19); |
|
||||
|
|
||||
printf("CREATE TABLE IF NOT EXISTS %s (\n", table_name); |
|
||||
printf("`id` int(10) AUTO_INCREMENT NOT NULL,\n"); |
|
||||
printf("`src_ip` INT(10) UNSIGNED NOT NULL,\n"); |
|
||||
printf("`dst_ip` INT(10) UNSIGNED NOT NULL,\n"); |
|
||||
printf("`proto` smallint(2) unsigned NOT NULL DEFAULT 0,\n"); |
|
||||
printf("`src_port` smallint(5) unsigned NOT NULL DEFAULT 0,\n"); |
|
||||
printf("`dst_port` smallint(5) unsigned NOT NULL DEFAULT 0,\n"); |
|
||||
printf("`octets` INT unsigned NOT NULL DEFAULT 0,\n"); |
|
||||
printf("`packets` INT unsigned NOT NULL DEFAULT 0,\n"); |
|
||||
printf("PRIMARY KEY (`id`)\n"); |
|
||||
printf(") ENGINE=MyISAM DEFAULT CHARSET=utf8;\n"); |
|
||||
|
|
||||
char ins_sql[0xff] = {0}; |
|
||||
sprintf(ins_sql, "INSERT INTO %s(`src_ip`, `dst_ip`, `proto`, `src_port`, `dst_port`, `octets`, `packets`) VALUES", table_name); |
|
||||
|
|
||||
// always none |
|
||||
read_len = getline(&input_line, &input_line_len, f); |
|
||||
|
|
||||
while(true) |
|
||||
{ |
|
||||
register uint n=0xfff; |
|
||||
read_len = getline(&input_line, &input_line_len, f); |
|
||||
if(read_len <= 0) |
|
||||
break; |
|
||||
convert(input_line, buf_result_convert); |
|
||||
|
|
||||
printf("%s\n", ins_sql); |
|
||||
|
|
||||
// without first comma |
|
||||
printf("%s\n", buf_result_convert+1); |
|
||||
|
|
||||
while(n>0) |
|
||||
{ |
|
||||
read_len = getline(&input_line, &input_line_len, f); |
|
||||
if(read_len <= 0) |
|
||||
break; |
|
||||
convert(input_line, buf_result_convert); |
|
||||
printf("%s\n", buf_result_convert); |
|
||||
n--; |
|
||||
} |
|
||||
putc(';', stdout); |
|
||||
} |
|
||||
|
|
||||
free(input_line); |
|
||||
return 0; |
|
||||
} |
|
||||
@ -1,66 +0,0 @@ |
|||||
#!/bin/env python3 |
|
||||
import sys |
|
||||
import socket |
|
||||
import struct |
|
||||
from re import sub |
|
||||
from django.utils import timezone |
|
||||
|
|
||||
|
|
||||
def ip2int(strip): |
|
||||
return struct.unpack("!I", socket.inet_aton(strip))[0] |
|
||||
|
|
||||
|
|
||||
def convert(query): |
|
||||
dat = sub(r'\s+', ' ', query.strip('\n')).split(' ') |
|
||||
|
|
||||
if len(dat) == 1: |
|
||||
return |
|
||||
|
|
||||
src_ip = ip2int(dat[0]) |
|
||||
dst_ip = ip2int(dat[1]) |
|
||||
proto = int(dat[2]) |
|
||||
src_port = int(dat[3]) |
|
||||
dst_port = int(dat[4]) |
|
||||
octets = int(dat[5]) |
|
||||
packets = int(dat[6]) |
|
||||
|
|
||||
sql = ",(%d,%d,%d,%d,%d,%d,%d)" % ( |
|
||||
src_ip, dst_ip, proto, src_port, dst_port, octets, packets |
|
||||
) |
|
||||
return sql |
|
||||
|
|
||||
|
|
||||
if __name__ == '__main__': |
|
||||
f = sys.stdin |
|
||||
table_name = "flowstat_%s" % timezone.now().strftime("%d%m%Y") |
|
||||
print(("CREATE TABLE IF NOT EXISTS %s (" % table_name)) |
|
||||
print("`id` int(10) AUTO_INCREMENT NOT NULL,") |
|
||||
print("`src_ip` INT(10) UNSIGNED NOT NULL,") |
|
||||
print("`dst_ip` INT(10) UNSIGNED NOT NULL,") |
|
||||
print("`proto` smallint(2) unsigned NOT NULL DEFAULT 0,") |
|
||||
print("`src_port` smallint(5) unsigned NOT NULL DEFAULT 0,") |
|
||||
print("`dst_port` smallint(5) unsigned NOT NULL DEFAULT 0,") |
|
||||
print("`octets` INT unsigned NOT NULL DEFAULT 0,") |
|
||||
print("`packets` INT unsigned NOT NULL DEFAULT 0,") |
|
||||
print("PRIMARY KEY (`id`)") |
|
||||
print(") ENGINE=MyISAM DEFAULT CHARSET=utf8;") |
|
||||
ins_sql = r"INSERT INTO %s(`src_ip`, `dst_ip`, `proto`, `src_port`, `dst_port`, `octets`, `packets`) VALUES" % table_name |
|
||||
|
|
||||
# always none |
|
||||
f.readline() |
|
||||
|
|
||||
while True: |
|
||||
n = 0xfff |
|
||||
rs = convert(f.readline()) |
|
||||
if not rs: exit() |
|
||||
# without first comma |
|
||||
print(ins_sql) |
|
||||
print((rs[1:])) |
|
||||
while n > 0: |
|
||||
rs = convert(f.readline()) |
|
||||
if not rs: exit() |
|
||||
print(rs) |
|
||||
n -= 1 |
|
||||
print(';') |
|
||||
|
|
||||
f.close() |
|
||||
@ -1 +0,0 @@ |
|||||
default_app_config = 'ip_pool.apps.IpPoolConfig' |
|
||||
@ -1,6 +0,0 @@ |
|||||
from django.contrib import admin |
|
||||
|
|
||||
from . import models |
|
||||
|
|
||||
|
|
||||
admin.site.register(models.IpPoolItem) |
|
||||
@ -1,6 +0,0 @@ |
|||||
from django.apps import AppConfig |
|
||||
|
|
||||
|
|
||||
class IpPoolConfig(AppConfig): |
|
||||
name = 'ip_pool' |
|
||||
verbose_name = "Ip pool" |
|
||||
@ -1,22 +0,0 @@ |
|||||
# -*- coding: utf-8 -*- |
|
||||
from django import forms |
|
||||
|
|
||||
from mydefs import ip_addr_regex |
|
||||
|
|
||||
|
|
||||
class PoolForm(forms.Form): |
|
||||
start_ip = forms.GenericIPAddressField(protocol='ipv4', widget=forms.TextInput(attrs={ |
|
||||
'pattern': ip_addr_regex, |
|
||||
'placeholder': '127.0.0.1', |
|
||||
'id': 'start_ip', |
|
||||
'class': 'form-control', |
|
||||
'required': '' |
|
||||
}), required=True) |
|
||||
|
|
||||
end_ip = forms.GenericIPAddressField(protocol='ipv4', widget=forms.TextInput(attrs={ |
|
||||
'pattern': ip_addr_regex, |
|
||||
'placeholder': '127.0.0.1', |
|
||||
'id': 'end_ip', |
|
||||
'class': 'form-control', |
|
||||
'required': '' |
|
||||
}), required=True) |
|
||||
@ -1,23 +0,0 @@ |
|||||
# -*- coding: utf-8 -*- |
|
||||
# Generated by Django 1.9 on 2016-06-28 23:51 |
|
||||
|
|
||||
from django.db import migrations, models |
|
||||
|
|
||||
import mydefs |
|
||||
|
|
||||
|
|
||||
class Migration(migrations.Migration): |
|
||||
initial = True |
|
||||
|
|
||||
dependencies = [ |
|
||||
] |
|
||||
|
|
||||
operations = [ |
|
||||
migrations.CreateModel( |
|
||||
name='IpPoolItem', |
|
||||
fields=[ |
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), |
|
||||
('ip', mydefs.MyGenericIPAddressField(max_length=8, protocol='ipv4')), |
|
||||
], |
|
||||
), |
|
||||
] |
|
||||
@ -1,59 +0,0 @@ |
|||||
from django.db import models, connection |
|
||||
|
|
||||
from mydefs import ip2int, MyGenericIPAddressField |
|
||||
|
|
||||
|
|
||||
class IpPoolItemManager(models.Manager): |
|
||||
def get_pools(self): |
|
||||
ips = self.raw(r'SELECT id, ip FROM ip_pool_ippoolitem ORDER BY id') |
|
||||
ips_len = len(list(ips)) |
|
||||
if ips_len < 1: |
|
||||
return |
|
||||
last_dg = ip2int(ips[0].ip) |
|
||||
start_pool = last_dg |
|
||||
res = list() |
|
||||
cnt = 0 |
|
||||
for ip in ips: |
|
||||
ipnt = ip2int(ip.ip) |
|
||||
if ipnt > last_dg + 1 or ipnt < last_dg - 1: |
|
||||
res.append((start_pool, last_dg, cnt)) |
|
||||
start_pool = ipnt |
|
||||
cnt = 0 |
|
||||
last_dg = ipnt |
|
||||
cnt += 1 |
|
||||
res.append((start_pool, last_dg, cnt)) |
|
||||
return res |
|
||||
|
|
||||
def add_pool(self, start_ip, end_ip): |
|
||||
start_ip = ip2int(start_ip) |
|
||||
end_ip = ip2int(end_ip) |
|
||||
|
|
||||
if (end_ip - start_ip) > 5000: |
|
||||
raise Exception('Not add over 5000 ip\'s') |
|
||||
|
|
||||
sql_strs = [r"(%d)" % tip for tip in range(start_ip, end_ip + 1)] |
|
||||
sql = r'INSERT INTO ip_pool_ippoolitem (ip) VALUES %s' % r",".join(sql_strs) |
|
||||
|
|
||||
cursor = connection.cursor() |
|
||||
cursor.execute(sql) |
|
||||
|
|
||||
def get_free_ip(self): |
|
||||
sql = r'SELECT ip_pool_ippoolitem.id as id, ip_pool_ippoolitem.ip as ip FROM ip_pool_ippoolitem ' \ |
|
||||
r'LEFT JOIN abonent ON abonent.ip_address_id = ip_pool_ippoolitem.id WHERE ' \ |
|
||||
r'abonent.ip_address_id IS NULL LIMIT 1' |
|
||||
|
|
||||
rs = self.raw(sql) |
|
||||
rs_len = len(list(rs)) |
|
||||
return None if rs_len is 0 else rs[0] |
|
||||
|
|
||||
|
|
||||
class IpPoolItem(models.Model): |
|
||||
ip = MyGenericIPAddressField() |
|
||||
|
|
||||
objects = IpPoolItemManager() |
|
||||
|
|
||||
def int_ip(self): |
|
||||
return ip2int(self.ip) |
|
||||
|
|
||||
def __str__(self): |
|
||||
return self.ip |
|
||||
@ -1,48 +0,0 @@ |
|||||
{% extends 'base.html' %} |
|
||||
{% block main %} |
|
||||
|
|
||||
|
|
||||
<ol class="breadcrumb"> |
|
||||
<li><span class="glyphicon glyphicon-home"></span></li> |
|
||||
<li><a href="{% url 'ip_pool:home' %}">IP Пул</a></li> |
|
||||
<li class="active">Добавить</li> |
|
||||
</ol> |
|
||||
|
|
||||
{% include 'message_block.html' %} |
|
||||
|
|
||||
<div class="panel panel-default"> |
|
||||
<div class="panel-heading"> |
|
||||
<h3 class="panel-title">Добавить IP пул</h3> |
|
||||
</div> |
|
||||
<div class="panel-body"> |
|
||||
|
|
||||
<form role="form" action="{% url 'ip_pool:add' %}" method="post">{% csrf_token %} |
|
||||
<div class="form-group"> |
|
||||
<label for="start_ip">Начальный ip</label> |
|
||||
|
|
||||
<div class="input-group"> |
|
||||
<span class="input-group-addon"><span class="glyphicon glyphicon-cutlery"></span></span> |
|
||||
{{ form.start_ip }}{{ form.start_ip.errors }} |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="form-group"> |
|
||||
<label for="">Конечный ip</label> |
|
||||
|
|
||||
<div class="input-group"> |
|
||||
<span class="input-group-addon"><span class="glyphicon glyphicon-gbp"></span></span> |
|
||||
{{ form.end_ip }}{{ form.end_ip.errors }} |
|
||||
</div> |
|
||||
</div> |
|
||||
<div class="btn-group"> |
|
||||
<button type="submit" class="btn btn-sm btn-primary"> |
|
||||
<span class="glyphicon glyphicon-save"></span> Сохранить |
|
||||
</button> |
|
||||
<button type="reset" class="btn btn-sm btn-default"> |
|
||||
<span class="glyphicon glyphicon-remove-circle"></span> Сбросить |
|
||||
</button> |
|
||||
</div> |
|
||||
</form> |
|
||||
</div> |
|
||||
</div> |
|
||||
|
|
||||
{% endblock %} |
|
||||
@ -1,73 +0,0 @@ |
|||||
{% extends 'base.html' %} |
|
||||
{% block main %} |
|
||||
|
|
||||
|
|
||||
<ol class="breadcrumb"> |
|
||||
<li><span class="glyphicon glyphicon-home"></span></li> |
|
||||
<li class="active">IP Пул</li> |
|
||||
</ol> |
|
||||
|
|
||||
{% include 'message_block.html' %} |
|
||||
|
|
||||
<h3>Пулы ip адресов</h3> |
|
||||
<div class="table-responsive"> |
|
||||
<table class="table table-striped table-bordered"> |
|
||||
<thead> |
|
||||
<tr> |
|
||||
<th>Начальный IP</th> |
|
||||
<th>Конечный IP</th> |
|
||||
<th>Количество</th> |
|
||||
<th width="50">Ред.</th> |
|
||||
<th width="50">Уд.</th> |
|
||||
</tr> |
|
||||
</thead> |
|
||||
<tbody> |
|
||||
{% for pl in pools %} |
|
||||
<tr> |
|
||||
<td>{{ pl.0 }}</td> |
|
||||
<td>{{ pl.1 }}</td> |
|
||||
<td>{{ pl.2 }}</td> |
|
||||
<td colspan="2" class="btn-group btn-group-sm btn-group-justified"> |
|
||||
|
|
||||
<a href="{% url 'ip_pool:ips' %}?ips={{ pl.0 }}&ipe={{ pl.1 }}" |
|
||||
class="btn btn-primary"> |
|
||||
<span class="glyphicon glyphicon-edit"></span> |
|
||||
</a> |
|
||||
|
|
||||
{% if perms.ip_pool.delete_ippoolitem %} |
|
||||
<a href="{% url 'ip_pool:ips_del' %}?ips={{ pl.0 }}&ipe={{ pl.1 }}" class="btn btn-danger"> |
|
||||
<span class="glyphicon glyphicon-remove-circle"></span> |
|
||||
</a> |
|
||||
{% endif %} |
|
||||
|
|
||||
</td> |
|
||||
</tr> |
|
||||
{% empty %} |
|
||||
<tr> |
|
||||
<td colspan="5">Нет ни одного пула зарезервированных ip адресов. |
|
||||
{% if perms.ip_pool.add_ippoolitem %} |
|
||||
<a href="{% url 'ip_pool:add' %}">Создать</a> |
|
||||
{% endif %} |
|
||||
</td> |
|
||||
</tr> |
|
||||
{% endfor %} |
|
||||
</tbody> |
|
||||
|
|
||||
{% if perms.ip_pool.add_ippoolitem %} |
|
||||
<tfoot> |
|
||||
<tr> |
|
||||
<td colspan="5"> |
|
||||
<a href="{% url 'ip_pool:add' %}" class="btn btn-sm btn-success"> |
|
||||
<span class="glyphicon glyphicon-plus"></span> |
|
||||
</a> |
|
||||
</td> |
|
||||
</tr> |
|
||||
</tfoot> |
|
||||
{% endif %} |
|
||||
|
|
||||
</table> |
|
||||
</div> |
|
||||
|
|
||||
{% include 'toolbar_page.html' with pag=pools %} |
|
||||
|
|
||||
{% endblock %} |
|
||||
@ -1,59 +0,0 @@ |
|||||
{% extends 'base.html' %} |
|
||||
{% block main %} |
|
||||
|
|
||||
|
|
||||
<ol class="breadcrumb"> |
|
||||
<li><span class="glyphicon glyphicon-home"></span></li> |
|
||||
<li><a href="{% url 'ip_pool:home' %}">IP Пул</a></li> |
|
||||
<li class="active">Редактировать/Просмотреть</li> |
|
||||
</ol> |
|
||||
|
|
||||
|
|
||||
<h3>История абонента</h3> |
|
||||
<div class="table-responsive"> |
|
||||
<table class="table table-striped table-bordered"> |
|
||||
<thead> |
|
||||
<tr> |
|
||||
<th width="30">Id</th> |
|
||||
<th>Ip</th> |
|
||||
<th>Клиент</th> |
|
||||
<th width="50">Уд.</th> |
|
||||
</tr> |
|
||||
</thead> |
|
||||
<tbody> |
|
||||
{% for pi in pool_ips %} |
|
||||
<tr> |
|
||||
<td>{{ pi.id }}</td> |
|
||||
<td>{{ pi.ip }}</td> |
|
||||
<td>{% if pi.abon %} |
|
||||
<a href="{% url 'abonapp:abon_home' pi.abon.group.id pi.abon.id %}">{{ pi.abon.username }}</a> |
|
||||
{% else %}---{% endif %} |
|
||||
</td> |
|
||||
<td> |
|
||||
{% if pi.abon %} |
|
||||
<button class="btn btn-sm btn-danger disabled"> |
|
||||
<span class="glyphicon glyphicon-remove-circle"></span> |
|
||||
</button> |
|
||||
{% elif perms.ip_pool.delete_ippoolitem %} |
|
||||
<a href="{% url 'ip_pool:del_ip' %}?id={{ pi.id }}" class="btn btn-sm btn-danger"> |
|
||||
<span class="glyphicon glyphicon-remove-circle"></span> |
|
||||
</a> |
|
||||
{% endif %} |
|
||||
</td> |
|
||||
</tr> |
|
||||
{% empty %} |
|
||||
<tr> |
|
||||
<td colspan="4">Нет ни одного пула зарезервированных ip адресов. |
|
||||
{% if perms.ip_pool.add_ippoolitem %} |
|
||||
<a href="{% url 'ip_pool:add' %}">Создать</a> |
|
||||
{% endif %} |
|
||||
</td> |
|
||||
</tr> |
|
||||
{% endfor %} |
|
||||
</tbody> |
|
||||
</table> |
|
||||
</div> |
|
||||
|
|
||||
{% include 'toolbar_page.html' with pag=pool_ips %} |
|
||||
|
|
||||
{% endblock %} |
|
||||
@ -1,15 +0,0 @@ |
|||||
# -*- coding:utf-8 -*- |
|
||||
from django.conf.urls import url |
|
||||
|
|
||||
from . import views |
|
||||
|
|
||||
|
|
||||
urlpatterns = [ |
|
||||
|
|
||||
url(r'^$', views.home, name='home'), |
|
||||
url(r'^range$', views.ips, name='ips'), |
|
||||
url(r'^del$', views.del_pool, name='ips_del'), |
|
||||
url(r'^add$', views.add_pool, name='add'), |
|
||||
|
|
||||
url(r'^delip$', views.delip, name='del_ip') |
|
||||
] |
|
||||
@ -1,81 +0,0 @@ |
|||||
# -*- coding: utf-8 -*- |
|
||||
from django.contrib.auth.decorators import login_required, permission_required |
|
||||
from django.shortcuts import render, redirect, get_object_or_404 |
|
||||
from django.contrib import messages |
|
||||
|
|
||||
from .forms import PoolForm |
|
||||
from .models import IpPoolItem |
|
||||
import mydefs |
|
||||
|
|
||||
|
|
||||
@login_required |
|
||||
@mydefs.only_admins |
|
||||
def home(request): |
|
||||
pools = IpPoolItem.objects.get_pools() |
|
||||
|
|
||||
if pools: |
|
||||
pools = [(mydefs.int2ip(ip[0]), mydefs.int2ip(ip[1]), ip[2]) for ip in pools] |
|
||||
pools = mydefs.pag_mn(request, pools) |
|
||||
|
|
||||
return render(request, 'ip_pool/index.html', { |
|
||||
'pools': pools |
|
||||
}) |
|
||||
|
|
||||
|
|
||||
@login_required |
|
||||
@mydefs.only_admins |
|
||||
def ips(request): |
|
||||
ip_start = request.GET.get('ips') |
|
||||
ip_end = request.GET.get('ipe') |
|
||||
|
|
||||
pool_ips = IpPoolItem.objects.filter(ip__gte=ip_start) |
|
||||
pool_ips = pool_ips.filter(ip__lte=ip_end) |
|
||||
|
|
||||
pool_ips = mydefs.pag_mn(request, pool_ips) |
|
||||
|
|
||||
return render(request, 'ip_pool/ips.html', { |
|
||||
'pool_ips': pool_ips, |
|
||||
'ips': ip_start, |
|
||||
'ipe': ip_end |
|
||||
}) |
|
||||
|
|
||||
|
|
||||
@login_required |
|
||||
@permission_required('ip_pool.delete_ippoolitem') |
|
||||
def del_pool(request): |
|
||||
ip_start = request.GET.get('ips') |
|
||||
ip_end = request.GET.get('ipe') |
|
||||
|
|
||||
pool_ips = IpPoolItem.objects.filter(ip__gte=ip_start) |
|
||||
pool_ips = pool_ips.filter(ip__lte=ip_end) |
|
||||
pool_ips = pool_ips.filter() |
|
||||
|
|
||||
pool_ips.delete() |
|
||||
|
|
||||
return mydefs.res_success(request, 'ip_pool:home') |
|
||||
|
|
||||
|
|
||||
@login_required |
|
||||
@permission_required('ip_pool.add_ippoolitem') |
|
||||
def add_pool(request): |
|
||||
if request.method == 'POST': |
|
||||
frm = PoolForm(request.POST) |
|
||||
if frm.is_valid(): |
|
||||
cd = frm.cleaned_data |
|
||||
IpPoolItem.objects.add_pool(cd['start_ip'], cd['end_ip']) |
|
||||
return redirect('ip_pool:home') |
|
||||
else: |
|
||||
messages.error(request, 'Исправьте ошибки') |
|
||||
else: |
|
||||
frm = PoolForm() |
|
||||
return render(request, 'ip_pool/add_pool.html', { |
|
||||
'form': frm |
|
||||
}) |
|
||||
|
|
||||
|
|
||||
@login_required |
|
||||
@permission_required('ip_pool.delete_ippoolitem') |
|
||||
def delip(request): |
|
||||
ipid = request.GET.get('id') |
|
||||
get_object_or_404(IpPoolItem, id=ipid).delete() |
|
||||
return mydefs.res_success(request, 'ip_pool:home') |
|
||||
4
static/css/all.min.css
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
31
static/js/all.min.js
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
2
static/js/bootstrap-datetimepicker.min.js
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
562
static/js/datetime_with_moment.min.js
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -1,6 +0,0 @@ |
|||||
from django.contrib import admin |
|
||||
|
|
||||
from . import models |
|
||||
|
|
||||
|
|
||||
admin.site.register(models.StatElem) |
|
||||
@ -0,0 +1,53 @@ |
|||||
|
# |
||||
|
# Get from https://github.com/Niklas9/django-unixdatetimefield |
||||
|
# |
||||
|
import datetime |
||||
|
import time |
||||
|
|
||||
|
import django.db.models as models |
||||
|
|
||||
|
|
||||
|
class UnixDateTimeField(models.DateTimeField): |
||||
|
|
||||
|
# TODO(niklas9): |
||||
|
# * should we take care of transforming between time zones in any way here ? |
||||
|
# * get default datetime format from settings ? |
||||
|
DEFAULT_DATETIME_FMT = '%Y-%m-%d %H:%M:%S' |
||||
|
TZ_CONST = '+' |
||||
|
# TODO(niklas9): |
||||
|
# * metaclass below just for Django < 1.9, fix a if stmt for it? |
||||
|
#__metaclass__ = models.SubfieldBase |
||||
|
description = "Unix timestamp integer to datetime object" |
||||
|
|
||||
|
def get_internal_type(self): |
||||
|
return 'PositiveIntegerField' |
||||
|
|
||||
|
def to_python(self, val): |
||||
|
if val is None or isinstance(val, datetime.datetime): |
||||
|
return val |
||||
|
if isinstance(val, datetime.date): |
||||
|
return datetime.datetime(val.year, val.month, val.day) |
||||
|
elif self._is_string(val): |
||||
|
# TODO(niklas9): |
||||
|
# * not addressing time zone support as todo above for now |
||||
|
if self.TZ_CONST in val: |
||||
|
val = val.split(self.TZ_CONST)[0] |
||||
|
return datetime.datetime.strptime(val, self.DEFAULT_DATETIME_FMT) |
||||
|
else: |
||||
|
return datetime.datetime.fromtimestamp(float(val)) |
||||
|
|
||||
|
def _is_string(value, val): |
||||
|
return isinstance(val, str) |
||||
|
|
||||
|
def get_db_prep_value(self, val, *args, **kwargs): |
||||
|
if val is None: |
||||
|
if self.default == models.fields.NOT_PROVIDED: return None |
||||
|
return self.default |
||||
|
return int(time.mktime(val.timetuple())) |
||||
|
|
||||
|
def value_to_string(self, obj): |
||||
|
val = self._get_val_from_obj(obj) |
||||
|
return self.to_python(val).strftime(self.DEFAULT_DATETIME_FMT) |
||||
|
|
||||
|
def from_db_value(self, val, expression, connection, context): |
||||
|
return self.to_python(val) |
||||
@ -0,0 +1,18 @@ |
|||||
|
# -*- coding: utf-8 -*- |
||||
|
# Generated by Django 1.9 on 2017-04-25 13:27 |
||||
|
from __future__ import unicode_literals |
||||
|
|
||||
|
from django.db import migrations |
||||
|
|
||||
|
|
||||
|
class Migration(migrations.Migration): |
||||
|
|
||||
|
dependencies = [ |
||||
|
('statistics', '0001_initial'), |
||||
|
] |
||||
|
|
||||
|
operations = [ |
||||
|
migrations.DeleteModel( |
||||
|
name='StatElem', |
||||
|
), |
||||
|
] |
||||
@ -1,18 +1,66 @@ |
|||||
|
import math |
||||
|
from datetime import datetime, timedelta |
||||
|
from django.db import models, ProgrammingError |
||||
|
from django.utils import timezone |
||||
|
from mydefs import MyGenericIPAddressField |
||||
|
from .fields import UnixDateTimeField |
||||
|
from mydefs import LogicError |
||||
|
|
||||
|
|
||||
from django.db import models |
|
||||
|
class StatManager(models.Manager): |
||||
|
|
||||
from mydefs import MyGenericIPAddressField |
|
||||
|
def traffic_by_ip(self, ip): |
||||
|
try: |
||||
|
traf = self.order_by('-cur_time').filter(ip=ip, octets__gt=524288)[0] |
||||
|
now = datetime.now() |
||||
|
if traf.cur_time < now - timedelta(minutes=55): |
||||
|
return False, traf |
||||
|
else: |
||||
|
return True, traf |
||||
|
except IndexError: |
||||
|
return False, None |
||||
|
except ProgrammingError as e: |
||||
|
raise LogicError(e) |
||||
|
|
||||
|
|
||||
class StatElem(models.Model): |
class StatElem(models.Model): |
||||
src_ip = MyGenericIPAddressField() |
|
||||
dst_ip = MyGenericIPAddressField() |
|
||||
proto = models.PositiveSmallIntegerField(default=0) |
|
||||
src_port = models.PositiveIntegerField(default=0) |
|
||||
dst_port = models.PositiveIntegerField(default=0) |
|
||||
|
cur_time = UnixDateTimeField(primary_key=True) |
||||
|
ip = MyGenericIPAddressField() |
||||
octets = models.PositiveIntegerField(default=0) |
octets = models.PositiveIntegerField(default=0) |
||||
packets = models.PositiveIntegerField(default=0) |
packets = models.PositiveIntegerField(default=0) |
||||
|
|
||||
|
objects = StatManager() |
||||
|
|
||||
|
@staticmethod |
||||
|
def percentile(N, percent, key=lambda x:x): |
||||
|
""" |
||||
|
Find the percentile of a list of values. |
||||
|
|
||||
|
@parameter N - is a list of values. Note N MUST BE already sorted. |
||||
|
@parameter percent - a float value from 0.0 to 1.0. |
||||
|
@parameter key - optional key function to compute value from each element of N. |
||||
|
|
||||
|
@return - the percentile of the values |
||||
|
""" |
||||
|
if not N: |
||||
|
return None |
||||
|
k = (len(N)-1) * percent |
||||
|
f = math.floor(k) |
||||
|
c = math.ceil(k) |
||||
|
if f == c: |
||||
|
return key(N[int(k)]) |
||||
|
d0 = key(N[int(f)]) * (c-k) |
||||
|
d1 = key(N[int(c)]) * (k-f) |
||||
|
return d0+d1 |
||||
|
|
||||
|
class Meta: |
||||
|
abstract = True |
||||
|
|
||||
|
|
||||
|
def getModel(): |
||||
|
|
||||
|
class DynamicStatElem(StatElem): |
||||
class Meta: |
class Meta: |
||||
db_table = 'flowstat' |
|
||||
|
db_table = 'flowstat_%s' % timezone.now().strftime("%d%m%Y") |
||||
|
abstract = False |
||||
|
return DynamicStatElem |
||||
@ -0,0 +1,12 @@ |
|||||
|
[Unit] |
||||
|
Description=A job for rotate djing netflow data |
||||
|
|
||||
|
[Service] |
||||
|
Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/bin" |
||||
|
Type=oneshot |
||||
|
ExecStart=/bin/bash -c "kill -HUP `cat /run/flow.pid.6343`" |
||||
|
User=root |
||||
|
Group=root |
||||
|
|
||||
|
[Install] |
||||
|
WantedBy=multi-user.target |
||||
@ -0,0 +1,11 @@ |
|||||
|
[Unit] |
||||
|
Description=Run every one minute rotate flows for djing |
||||
|
|
||||
|
[Timer] |
||||
|
OnCalendar=*-*-* *:*:59 |
||||
|
Persistent=true |
||||
|
RandomizedDelaySec=5 |
||||
|
Unit=djing_rotate.service |
||||
|
|
||||
|
[Install] |
||||
|
WantedBy=timers.target |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue