ispunity 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- data/README +11 -2
- data/bin/ispunity +19 -5
- data/config/configuration.json.example +20 -8
- data/doc/algorithm.txt +18 -0
- data/isp_unity.gemspec +3 -2
- data/ispunity.sh +53 -0
- data/lib/isp_unity.rb +27 -8
- data/lib/isp_unity/isp.rb +13 -10
- data/lib/isp_unity/routing_table.rb +46 -41
- data/lib/isp_unity/version.rb +1 -1
- data/lib/load_balance/load_balance.rb +3 -2
- data/lib/sticky_session.rb +39 -0
- metadata +20 -2
data/README
CHANGED
@@ -40,7 +40,6 @@ install the additional dependencies as mentioned.
|
|
40
40
|
|
41
41
|
7. Usage
|
42
42
|
ispunity clear_rules # Clear the rules setup by the routing policy
|
43
|
-
ispunity configfile # Uses the config file provided/passed to the application
|
44
43
|
ispunity help [TASK] # Describe available tasks or one specific task
|
45
44
|
ispunity license # Displays the license
|
46
45
|
ispunity monitor # Start monitoring the isp connections.
|
@@ -48,4 +47,14 @@ install the additional dependencies as mentioned.
|
|
48
47
|
ispunity version # Displays the version of Ispunity
|
49
48
|
|
50
49
|
|
51
|
-
|
50
|
+
8. Starting with Ispunity
|
51
|
+
- Follow the following process after successful installation of ispunity
|
52
|
+
|
53
|
+
i. ispunity setup : This will setup your load balancing using the ispunity configuration file.
|
54
|
+
Whenever you will change the configuration file, you need to run this command to take effect.
|
55
|
+
|
56
|
+
ii. ispunity monitor : This will check for the availability of isp connections. If any connection any network connection is down then it will load balance the network traffic on available connections.
|
57
|
+
|
58
|
+
|
59
|
+
Note : We recommend to add cron job for checking the available network connections. Add following into the crontab :
|
60
|
+
*/5 * * * * bash -c 'source /etc/profile.d/rvm.sh && /usr/bin/env ruby /usr/local/rvm/gems/ruby-1.9.3-p125/bin/ispunity monitor'
|
data/bin/ispunity
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
$LOAD_PATH << File.join(File.dirname(__FILE__),'..','lib')
|
3
3
|
require 'thor'
|
4
4
|
require 'isp_unity'
|
5
|
+
require 'fileutils'
|
5
6
|
|
6
7
|
class Ispunity < Thor
|
7
8
|
|
@@ -12,16 +13,16 @@ class Ispunity < Thor
|
|
12
13
|
|
13
14
|
desc "setup","Setup the application"
|
14
15
|
def setup
|
15
|
-
puts "Starting the setup application"
|
16
|
+
# puts "Starting the setup application"
|
16
17
|
IspUnity.setup
|
17
18
|
end
|
18
19
|
|
19
20
|
desc "monitor","Start monitoring the isp connections."
|
20
21
|
def monitor
|
21
|
-
puts "Starting to monitor the application"
|
22
|
+
# puts "Starting to monitor the application"
|
22
23
|
IspUnity.monitor
|
23
24
|
end
|
24
|
-
|
25
|
+
=begin
|
25
26
|
desc "configfile","Uses the config file provided/passed to the application"
|
26
27
|
method_option :configfile, :aliases => "-c", :desc => "Config file"
|
27
28
|
def configfile(file)
|
@@ -32,14 +33,27 @@ class Ispunity < Thor
|
|
32
33
|
def clear_rules
|
33
34
|
puts 'Clearing the rules.'
|
34
35
|
end
|
35
|
-
|
36
|
+
=end
|
36
37
|
desc "license","Displays the license"
|
37
38
|
def license
|
38
|
-
File.open("
|
39
|
+
File.open("license",'r') do |f|
|
39
40
|
puts f.readlines
|
40
41
|
end
|
41
42
|
end
|
42
43
|
|
44
|
+
desc "copy", "Copies configuration.json.example file under /etc directory as ispunity.json"
|
45
|
+
def copy
|
46
|
+
puts "\t Configuration.json.example file copied under /etc directory as ispunity.json \n"
|
47
|
+
FileUtils.cp(File.join([File.expand_path(File.dirname(__FILE__)), '..', 'config', 'configuration.json.example']), File.join("/etc"))
|
48
|
+
File.rename(File.join('/etc', 'configuration.json.example'), File.join('/etc', 'ispunity.json'))
|
49
|
+
end
|
50
|
+
|
51
|
+
desc "cron", "Displays entry for cron tab"
|
52
|
+
def cron
|
53
|
+
path = `/usr/bin/which ispunity`.chomp
|
54
|
+
puts "#Add following line to your crontab to monitor your ISP's for every 5 minutes"
|
55
|
+
puts "*/5 * * * * bash -c 'source /etc/profile.d/rvm.sh && /usr/bin/env ruby #{path} monitor"
|
56
|
+
end
|
43
57
|
end
|
44
58
|
|
45
59
|
Ispunity.start
|
@@ -1,23 +1,23 @@
|
|
1
1
|
{
|
2
|
-
"no_of_isp":3,
|
3
|
-
"status":"balancing",
|
4
|
-
"interval":300,
|
5
2
|
"public_dns":["8.8.8.8","8.8.4.4","4.2.2.2","4.2.2.1"],
|
6
3
|
"log_level":1,
|
7
4
|
"isp": [
|
8
5
|
{
|
9
|
-
"id":"isp1",
|
10
6
|
"name":"tata",
|
11
7
|
"interface":"eth0",
|
12
|
-
"gateway":"
|
8
|
+
"gateway":"192.168.3.6",
|
13
9
|
"subnet":"255.255.255.0",
|
14
10
|
"network":"61.17.193.0/24",
|
15
11
|
"weight":1,
|
16
12
|
"enabled":"true",
|
17
13
|
"online":"true"
|
14
|
+
"protocol":"tcp",
|
15
|
+
"port":"80",
|
16
|
+
"network_ip":"",
|
17
|
+
"skip_sticky_session":true,
|
18
|
+
"priority":1
|
18
19
|
},
|
19
20
|
{
|
20
|
-
"id":"isp2",
|
21
21
|
"name":"ttml",
|
22
22
|
"interface":"eth2",
|
23
23
|
"gateway":"192.168.0.2",
|
@@ -26,9 +26,13 @@
|
|
26
26
|
"weight":1,
|
27
27
|
"enabled":"true",
|
28
28
|
"online":"true"
|
29
|
+
"protocol":"tcp",
|
30
|
+
"port":"80",
|
31
|
+
"network_ip":"",
|
32
|
+
"skip_sticky_session":true,
|
33
|
+
"priority":1
|
29
34
|
},
|
30
35
|
{
|
31
|
-
"id":"isp3",
|
32
36
|
"name":"bsnl",
|
33
37
|
"interface":"wlan0",
|
34
38
|
"gateway":"192.168.2.1",
|
@@ -37,6 +41,14 @@
|
|
37
41
|
"weight":1,
|
38
42
|
"enabled":"false",
|
39
43
|
"online":"true"
|
44
|
+
"protocol":"tcp",
|
45
|
+
"port":"80",
|
46
|
+
"network_ip":"",
|
47
|
+
"skip_sticky_session":true,
|
48
|
+
"priority":1
|
49
|
+
|
40
50
|
}
|
41
|
-
]
|
51
|
+
],
|
52
|
+
"skip_sticky_session":false,
|
53
|
+
"priority_for_sticky":"tata,ttml"
|
42
54
|
}
|
data/doc/algorithm.txt
CHANGED
@@ -31,3 +31,21 @@ dev eth0 weight 1 nexthop via "ip gateway" dev "interface name" weight "weighta
|
|
31
31
|
ip route flush table cache
|
32
32
|
# If there is only one ISP
|
33
33
|
ip route replace default via "ip gateway" dev "interface name"
|
34
|
+
|
35
|
+
Commands for Sticky Session:
|
36
|
+
|
37
|
+
1) iptables -t mangle -A PREROUTING -s #{source network} -p #{protocol} --dport #{dport} -j MARK --set-mark #{dport}
|
38
|
+
|
39
|
+
mangle : Table will be used for packet aleternation
|
40
|
+
PREROUTING : altering outgoing packets before routing
|
41
|
+
source_network : To which network should we need to run the sticky session
|
42
|
+
protocol : sticky protocols or non-sticky protocols (either TCP or UDP)
|
43
|
+
dport : Destination port (on which destination port that sticky session is working) and we have mark the packet with some value(prefer to use to use dport value as they would be unique)
|
44
|
+
|
45
|
+
2) ip rule add fwmark #{port} lookup #{table_name}
|
46
|
+
|
47
|
+
Depends on port value it tells which ISP will need to lookup
|
48
|
+
|
49
|
+
3) ip rule del fwmark #{port} lookup #{table_name}
|
50
|
+
|
51
|
+
Deletes the rule. After delete the rule we have to add the rule again.
|
data/isp_unity.gemspec
CHANGED
@@ -5,7 +5,7 @@ require "isp_unity/version"
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "ispunity"
|
8
|
-
s.version = IspUnity::VERSION
|
8
|
+
s.version = IspUnity::VERSION
|
9
9
|
s.authors = ["Pratik Shah", "Siva Gollapalli", "Arun Tomar"]
|
10
10
|
s.email = ["pratik14shah@gmail.com", "sivagollapalli@yahoo.com", "arun@solutionenterprises.co.in"]
|
11
11
|
s.homepage = "http://www.ispunity.com"
|
@@ -15,7 +15,8 @@ Gem::Specification.new do |s|
|
|
15
15
|
s.add_dependency("i18n")
|
16
16
|
s.add_dependency("json")
|
17
17
|
s.add_dependency("thor")
|
18
|
-
|
18
|
+
# rspec dependency are added
|
19
|
+
s.add_dependency("rspec")
|
19
20
|
|
20
21
|
s.rubyforge_project = "ispunity"
|
21
22
|
|
data/ispunity.sh
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
#------------------------------------------------------------------------------------------
|
3
|
+
# Author : Swati A. Rananaware
|
4
|
+
# Date : 30-04-2012
|
5
|
+
# Purpose : Install Ispunity gem.
|
6
|
+
# Description : Install rvm and then ruby 1.9.3. Finally install Ispunity gem.
|
7
|
+
# For : Ispunity
|
8
|
+
#------------------------------------------------------------------------------------------
|
9
|
+
|
10
|
+
CYAN="\033[0;36m"
|
11
|
+
GREEN="\033[1;34m"
|
12
|
+
NOCOLOR="\033[0m"
|
13
|
+
|
14
|
+
echo -en "$CYAN Please run this script as root user so that all dependencies will be installed through script$NOCOLOR\n\n"
|
15
|
+
|
16
|
+
if [ -f /etc/redhat-release ]
|
17
|
+
then
|
18
|
+
yum install -y gcc-c++ patch readline readline-devel zlib zlib-devel libyaml-devel libffi-devel openssl-devel make bzip2 autoconf automake libtool bison iconv-devel
|
19
|
+
else
|
20
|
+
apt-get install build-essential openssl libreadline6 libreadline6-dev curl git-core zlib1g zlib1g-dev libssl-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt-dev autoconf libc6-dev ncurses-dev automake libtool bison subversion
|
21
|
+
fi
|
22
|
+
|
23
|
+
if [ "$1" != "--without-rvm" ]
|
24
|
+
then
|
25
|
+
echo -en "\n$CYAN Gem Ispunity requires ruby 1.9.3.\
|
26
|
+
\n By default, this script will install RVM with ruby 1.9.3\
|
27
|
+
\n If you have ruby 1.9.3 installed, you can chose to install gem ispunity directly.\
|
28
|
+
\n Using $GREEN./ispunity --without-rvm$NOCOLUR $CYAN or Say no for rvm installation below $NOCOLOR\n\n"
|
29
|
+
read -p "Do you want to continue to install rvm ?? (y|n) : " ch
|
30
|
+
case $ch in
|
31
|
+
'y'|'Y')
|
32
|
+
# Install RVM
|
33
|
+
echo -en "\n\n$CYAN Installing rvm.........$NOCOLOR\n\n"
|
34
|
+
curl -L get.rvm.io | bash -s stable
|
35
|
+
source /etc/profile.d/rvm.sh
|
36
|
+
#Install ruby 1.9.3
|
37
|
+
rvm install 1.9.3-p125
|
38
|
+
rvm use 1.9.3-p125;;
|
39
|
+
|
40
|
+
'n'|'N')
|
41
|
+
;;
|
42
|
+
*)
|
43
|
+
echo -en "\n\n$CYAN Wrong Option. Should be 'y' or 'n'"
|
44
|
+
echo -en " Exiting the scipt execution$NOCOLOR\n"
|
45
|
+
exit;;
|
46
|
+
esac
|
47
|
+
fi
|
48
|
+
|
49
|
+
echo -en "\n\n$CYAN Installing ispunity $NOCOLOR\n\n"
|
50
|
+
|
51
|
+
# Install gem ispunity
|
52
|
+
gem install ispunity
|
53
|
+
|
data/lib/isp_unity.rb
CHANGED
@@ -2,6 +2,7 @@ $LOAD_PATH << File.expand_path(File.dirname(__FILE__))
|
|
2
2
|
require 'json'
|
3
3
|
require 'yaml'
|
4
4
|
require 'isp_unity_log'
|
5
|
+
require 'sticky_session'
|
5
6
|
require 'route/route'
|
6
7
|
require 'load_balance/load_balance'
|
7
8
|
require 'system_call'
|
@@ -38,33 +39,51 @@ module IspUnity
|
|
38
39
|
IspUnityLog.debug("Route Command: #{route_command}")
|
39
40
|
if SystemCall.execute(route_command)
|
40
41
|
IspUnityLog.info(I18n.t('system_call.execute.route.success'))
|
42
|
+
|
43
|
+
#RULE COMMAND
|
41
44
|
Rule.build_commands(isp_lists)
|
42
|
-
|
45
|
+
rule_command = Rule.commands
|
43
46
|
IspUnityLog.info(I18n.t('rule.build_commands'))
|
44
|
-
|
47
|
+
IspUnityLog.debug("Rule Command: #{rule_command}")
|
45
48
|
SystemCall.execute(rule_command)
|
46
49
|
IspUnityLog.info(I18n.t('system_call.execute.rule.success'))
|
50
|
+
|
51
|
+
#LOAD BALANCE
|
47
52
|
LoadBalance.build_commands(isp_lists)
|
48
|
-
|
53
|
+
load_balance_command = LoadBalance.commands
|
49
54
|
IspUnityLog.info(I18n.t('load_balance.build_commands'))
|
50
|
-
|
55
|
+
IspUnityLog.debug("Load Balance Command: #{load_balance_command}")
|
51
56
|
SystemCall.execute(load_balance_command)
|
52
57
|
IspUnityLog.info(I18n.t('system_call.execute.load_balance.success'))
|
58
|
+
|
59
|
+
#Sticky Session
|
60
|
+
StickySession.execute(isp_lists) if $skip_sticky_session
|
53
61
|
end
|
54
62
|
end
|
55
63
|
|
56
64
|
def monitor
|
57
65
|
IspUnity.config
|
58
|
-
|
66
|
+
online_isps = []
|
59
67
|
IspUnity.isp_config_list.each do |isp|
|
60
|
-
|
68
|
+
online_isps << isp if LoadBalance.is_alive(isp)
|
61
69
|
end
|
62
|
-
|
70
|
+
|
71
|
+
#Failover case
|
72
|
+
unless online_isps == isp_config_list
|
73
|
+
|
74
|
+
#LOAD BALANCE
|
63
75
|
LoadBalance.build_commands(IspUnity.isp_config_list)
|
64
76
|
IspUnityLog.info(I18n.t('load_balance.build_commands'))
|
65
77
|
SystemCall.execute(LoadBalance.commands)
|
66
78
|
IspUnityLog.info(I18n.t('system_call.execute.load_balance.success'))
|
67
|
-
|
79
|
+
|
80
|
+
#Flush route
|
81
|
+
SystemCall.execute('/sbin/ip route flush cache')
|
82
|
+
|
83
|
+
#Change sticky session
|
84
|
+
offline_isps = isp_lists - online_isps
|
85
|
+
StickySession.change_rule(offline_isps, online_isps)
|
86
|
+
|
68
87
|
end
|
69
88
|
end
|
70
89
|
end
|
data/lib/isp_unity/isp.rb
CHANGED
@@ -1,18 +1,21 @@
|
|
1
1
|
class Isp
|
2
2
|
|
3
|
-
attr_accessor :
|
3
|
+
attr_accessor :name, :interface, :gateway, :subnet, :network, :online, :enabled, :ip_address, :weight, :protocol, :port, :network_ip, :priority
|
4
4
|
|
5
5
|
def initialize(config_isp)
|
6
|
-
@
|
7
|
-
@
|
8
|
-
@
|
9
|
-
@
|
10
|
-
@
|
11
|
-
@
|
12
|
-
@
|
13
|
-
@enabled = config_isp['enabled']
|
6
|
+
@name = config_isp['name']
|
7
|
+
@interface = config_isp['interface']
|
8
|
+
@gateway = config_isp['gateway']
|
9
|
+
@subnet = config_isp['subnet']
|
10
|
+
@network = config_isp['network']
|
11
|
+
@online = config_isp["online"]
|
12
|
+
@enabled = config_isp['enabled']
|
14
13
|
@ip_address = config_isp['ip_address']
|
15
|
-
@weight
|
14
|
+
@weight = config_isp['weight']
|
15
|
+
@protocol = config_isp['protocol']
|
16
|
+
@port = config_isp['port']
|
17
|
+
@network_ip = config_isp['network_ip']
|
18
|
+
@priority = config_isp['priority']
|
16
19
|
end
|
17
20
|
|
18
21
|
end
|
@@ -10,56 +10,61 @@ module IspUnity
|
|
10
10
|
attr_reader :isp_config_list
|
11
11
|
|
12
12
|
def config
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
13
|
+
# If file is exists then it reads that otherwise log an error
|
14
|
+
if File.exist?(ConfigFilePath)
|
15
|
+
begin
|
16
|
+
configurations = JSON.parse(File.read(ConfigFilePath))
|
17
|
+
IspUnityLog.info(I18n.t('file.read.success'))
|
18
|
+
rescue Exception => e
|
19
|
+
IspUnityLog.debug("#{e}")
|
20
|
+
IspUnityLog.error(I18n.t('file.read.error'))
|
21
|
+
raise IspUnityException.new(I18n.t('file.read.error'))
|
22
|
+
end
|
21
23
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
24
|
+
@isp_config_list = []
|
25
|
+
isp_list = configurations['isp']
|
26
|
+
$ip_cluster = configurations['public_dns']
|
27
|
+
$skip_sticky_session = configurations['skip_sticky_session']
|
28
|
+
$priority_for_sticky = configurations['priority_for_sticky'].split(',') if configurations['priority_for_sticky']
|
26
29
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
30
|
+
if isp_list
|
31
|
+
isp_list.each do|data|
|
32
|
+
if data['enabled'] == 'true'
|
33
|
+
ip_addr = SystemCall.get_ip(data['interface'].to_s)
|
34
|
+
if ip_addr
|
35
|
+
data['ip_address'] = SystemCall.get_ip(data['interface'])
|
36
|
+
@isp_config_list.push(Isp.new(data))
|
37
|
+
else
|
38
|
+
puts I18n.t('no_ip_addr') + data['name']
|
39
|
+
IspUnityLog.error(I18n.t('no_ip_addr') + data['name'] )
|
40
|
+
end
|
37
41
|
end
|
38
42
|
end
|
43
|
+
IspUnityLog.info('Isp Object succesfully created!')
|
44
|
+
else
|
45
|
+
raise IspUnityException.new(I18n.t('file.enter_isp'))
|
46
|
+
IspUnityLog.error(I18n.t('file.read.no_isp_found'))
|
39
47
|
end
|
40
|
-
IspUnityLog.info('Isp Object succesfully created!')
|
41
|
-
else
|
42
|
-
raise IspUnityException.new(I18n.t('file.enter_isp'))
|
43
|
-
IspUnityLog.error(I18n.t('file.read.no_isp_found'))
|
44
|
-
end
|
45
|
-
|
46
48
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
49
|
+
routing_table = File.read(RoutingTablePath)
|
50
|
+
IspUnityLog.info(I18n.t('routing_table.read.success'))
|
51
|
+
begin
|
52
|
+
@isp_config_list.each do|isp_list|
|
53
|
+
unless routing_table.include?(isp_list.name)
|
54
|
+
File.open(RoutingTablePath, 'a') {|f| f.write("#{rand(100)} #{isp_list.name} \n")}
|
55
|
+
end
|
56
|
+
IspUnityLog.info(I18n.t('isp.created'))
|
53
57
|
end
|
54
|
-
|
58
|
+
rescue Exception => e
|
59
|
+
IspUnityLog.debug("#{e}")
|
60
|
+
IspUnityLog.error(I18n.t('routing_table.read.error'))
|
61
|
+
raise IspUnityException.new(I18n.t('routing_table.read.error'))
|
55
62
|
end
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
63
|
+
else
|
64
|
+
@isp_config_list = []
|
65
|
+
puts "Please make ensure that configuration file has copied on /etc dir"
|
66
|
+
IspUnityLog.error('Please make ensure that configuration file has copied on /etc dir')
|
60
67
|
end
|
61
|
-
|
62
68
|
end
|
63
69
|
end
|
64
70
|
end
|
65
|
-
|
data/lib/isp_unity/version.rb
CHANGED
@@ -33,11 +33,12 @@ class LoadBalance
|
|
33
33
|
result = `/bin/ping -c 3 -I #{isp.ip_address} #{$ip_cluster.sample}`
|
34
34
|
if result.match("100% packet loss")
|
35
35
|
IspUnityLog.info("100% packet loss for #{isp.name}")
|
36
|
-
|
36
|
+
isp.online = false
|
37
37
|
else
|
38
38
|
IspUnityLog.info("0% packet loss for #{isp.name}")
|
39
|
-
|
39
|
+
isp.online = true
|
40
40
|
end
|
41
|
+
return isp.online
|
41
42
|
end
|
42
43
|
|
43
44
|
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
class StickySession
|
2
|
+
|
3
|
+
class << self
|
4
|
+
|
5
|
+
def execute(isps=[])
|
6
|
+
isps.each do |isp|
|
7
|
+
if isp.skip_sticky_session
|
8
|
+
# Mark the outgoing packet with port value
|
9
|
+
command = "iptables -t mangle -A PREROUTING -s #{isp.network_ip} -p #{isp.protocol} --dport #{isp.dport} -j MARK --set-mark #{isp.dport}"
|
10
|
+
SystemCall.execute(command)
|
11
|
+
# Lookup the ISP depends on marked value
|
12
|
+
command = "ip rule add fwmark #{isp.port} lookup #{isp.name}"
|
13
|
+
SystemCall.execute(command)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def change_rule(offline_isps=[], online_isps=[])
|
19
|
+
#online_isps consist of online isps
|
20
|
+
online_isps.sort! { |a,b| a.priority <=> b.priority }
|
21
|
+
|
22
|
+
# Remove rule of failed(offline) isp
|
23
|
+
offline_isps.each do |isp|
|
24
|
+
if isp.skip_sticky_session
|
25
|
+
command = "ip rule del fwmark #{isp.port} lookup #{isp.name}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Add new rule to online isp with high priority
|
30
|
+
offline_isps.each do |isp|
|
31
|
+
if isp.skip_sticky_session
|
32
|
+
command = "ip rule add fwmark #{isp.port} lookup #{online_isps[0].name}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ispunity
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.5
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2012-
|
14
|
+
date: 2012-06-08 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: log4r
|
@@ -77,6 +77,22 @@ dependencies:
|
|
77
77
|
- - ! '>='
|
78
78
|
- !ruby/object:Gem::Version
|
79
79
|
version: '0'
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: rspec
|
82
|
+
requirement: !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ! '>='
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: '0'
|
88
|
+
type: :runtime
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: !ruby/object:Gem::Requirement
|
91
|
+
none: false
|
92
|
+
requirements:
|
93
|
+
- - ! '>='
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
80
96
|
description: With IspUnity, you can 1.Use multiple internet connections simultaneously
|
81
97
|
and get all their throughput. 2.Automatic failover on working net connection if
|
82
98
|
any on of the internet connection goes down.
|
@@ -100,6 +116,7 @@ files:
|
|
100
116
|
- config/settings.yml
|
101
117
|
- doc/algorithm.txt
|
102
118
|
- isp_unity.gemspec
|
119
|
+
- ispunity.sh
|
103
120
|
- lib/isp_unity.rb
|
104
121
|
- lib/isp_unity/isp.rb
|
105
122
|
- lib/isp_unity/routing_table.rb
|
@@ -108,6 +125,7 @@ files:
|
|
108
125
|
- lib/load_balance/load_balance.rb
|
109
126
|
- lib/route/route.rb
|
110
127
|
- lib/rule/rule.rb
|
128
|
+
- lib/sticky_session.rb
|
111
129
|
- lib/system_call.rb
|
112
130
|
- license
|
113
131
|
- log/isp_unity.log
|