galerab 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/bin/galerab ADDED
@@ -0,0 +1,67 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'galerab'
4
+
5
+ path = ARGV.include?('-c') && ARGV[ARGV.index('-c') + 1]
6
+
7
+ unless path
8
+ path = ENV['GALERAB_CONFIG_PATH']
9
+
10
+ unless path
11
+ puts "Missing path for configuration file"
12
+ puts "Usage: command -c path/file.yml"
13
+ abort
14
+ end
15
+ end
16
+
17
+
18
+ puts "[#{Process.pid}] galerab starting with config file at #{ARGV[1]}"
19
+
20
+ confs = Configuration.new(path).conf
21
+
22
+ confs.each do |conf|
23
+ backend = Backend.new(conf[1])
24
+ conf = conf[1]
25
+
26
+ fork do
27
+ t = Thread.new do
28
+ while true
29
+ # Here we check if the backend is ready
30
+ next_backend = backend.get_next
31
+ puts "\nChecking if (wsrep_ready == ON) #{next_backend}\n"
32
+
33
+ begin
34
+ Sequel.connect(
35
+ "mysql://#{conf["user"]}:#{conf["password"]}@#{next_backend}/#{conf["database"]}"
36
+ ).fetch("show status like 'wsrep_ready'") do |row|
37
+ #row[:Value] = "OFF"
38
+ if row[:Value] == "OFF"
39
+ puts "#{next_backend} is not ready"
40
+ backend.not_ready.push(next_backend) unless backend.not_ready.include?(next_backend)
41
+ elsif row[:Value] == "ON"
42
+ puts "#{next_backend} is ready"
43
+ backend.not_ready.delete(next_backend) if backend.not_ready
44
+ end
45
+ end
46
+ rescue
47
+ puts "#{next_backend} is not ready"
48
+ backend.not_ready.push(next_backend) unless backend.not_ready.include?(next_backend)
49
+ end
50
+
51
+ sleep conf["check_every"]
52
+ end
53
+ end
54
+
55
+ t.join
56
+ BalancingProxy::Server.run(backend)
57
+ end
58
+ end
59
+
60
+ trap (:SIGHUP) do
61
+ $stdout.puts "Received SIGHUP, reloading config file"
62
+ backend.conf = YAML.load_file(ARGV[1])
63
+ $stdout.puts backend.conf["balancer_ports"].inspect
64
+ end
65
+
66
+ # release child processes before exit
67
+ confs.each { |conf| Process.wait }
data/files/galerab ADDED
@@ -0,0 +1,22 @@
1
+ #! /bin/sh
2
+
3
+ # Carry out specific functions when asked to by the system
4
+ case "$1" in
5
+ start)
6
+ echo "Starting script galerab "
7
+ nohup /usr/sbin/balancer </dev/null >/dev/null 2>&1 &
8
+ ;;
9
+ stop)
10
+ echo "Stopping script galerab"
11
+ kill `ps -ef | grep balancer | grep -v grep | awk '{print $2}'`
12
+ reload)
13
+ echo "reloading script galerab"
14
+ kill -s SIGHUP `ps -ef | grep balancer | grep -v grep | awk '{print $2}'`
15
+ ;;
16
+ *)
17
+ echo "Usage: /etc/init.d/galerab {start|stop}"
18
+ exit 1
19
+ ;;
20
+ esac
21
+
22
+ exit 0
data/files/galerab.yml ADDED
@@ -0,0 +1,17 @@
1
+ 1:
2
+ backends: ["localhost"]
3
+ check_every: 10
4
+ user: root
5
+ password: root
6
+ database: mysql
7
+ balancer_port: 3307
8
+ backend_port: 3306
9
+
10
+ 2:
11
+ backends: ["192.168.1.11"]
12
+ check_every: 10
13
+ user: root
14
+ password: root
15
+ database: mysql
16
+ balancer_port: 3308
17
+ backend_port: 3306
data/lib/galerab.rb ADDED
@@ -0,0 +1,10 @@
1
+ require "rubygems"
2
+ require "thread"
3
+ require 'yaml'
4
+ require 'mysql2'
5
+ require 'sequel'
6
+ require 'em-proxy'
7
+ require 'ansi/code'
8
+ require 'galerab/backend'
9
+ require 'galerab/configuration'
10
+ require 'galerab/balancing_proxy'
@@ -0,0 +1,25 @@
1
+ class Backend
2
+ attr_accessor :not_ready, :conf
3
+
4
+ def initialize(conf)
5
+ @next_host = 0
6
+ @list = conf['backends']
7
+ @conf = conf
8
+ @not_ready = Array.new
9
+ end
10
+
11
+ # round robin load-balancing
12
+ def get_next
13
+ @next_host = @next_host + 1
14
+ @next_host = 0 if @next_host >= @list.size
15
+ unless @not_ready.include?(@list[@next_host])
16
+ @list[@next_host]
17
+ else
18
+ begin
19
+ get_next
20
+ rescue SystemStackError
21
+ nil
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,68 @@
1
+ module BalancingProxy
2
+ extend self
3
+
4
+ # Callbacks for em-proxy events
5
+ #
6
+ module Callbacks
7
+ include ANSI::Code
8
+ extend self
9
+
10
+ def on_select
11
+ lambda do |backend|
12
+ puts black_on_white { 'on_select'.ljust(12) } + " #{backend.inspect}"
13
+ backend.increment_counter if Backend.strategy == :balanced
14
+ end
15
+ end
16
+
17
+ def on_connect
18
+ lambda do |backend|
19
+ puts black_on_magenta { 'on_connect'.ljust(12) } + ' ' + bold { backend }
20
+ end
21
+ end
22
+
23
+ def on_data
24
+ lambda do |data|
25
+ puts black_on_yellow { 'on_data'.ljust(12) }, data
26
+ data
27
+ end
28
+ end
29
+
30
+ def on_response
31
+ lambda do |backend, resp|
32
+ puts black_on_green { 'on_response'.ljust(12) } + " from #{backend}", resp
33
+ resp
34
+ end
35
+ end
36
+
37
+ def on_finish
38
+ lambda do |backend|
39
+ puts black_on_cyan { 'on_finish'.ljust(12) } + " for #{backend}", ''
40
+ end
41
+ end
42
+
43
+ end
44
+
45
+ module Server
46
+ def run(backend)
47
+ # run the proxy server and wait for connections
48
+ balancer_port = backend.conf["balancer_port"]
49
+ backend_port = backend.conf["backend_port"]
50
+ puts ANSI::Code.bold { "Launching proxy at 0.0.0.0:#{balancer_port}...\n" }
51
+
52
+ Proxy.start(:host => '0.0.0.0', :port => balancer_port, :debug => false) do |conn|
53
+ backend_host = backend.get_next
54
+ if backend_host
55
+ conn.server backend_host, :host => backend_host, :port => backend_port
56
+ puts ANSI::Code.bold { "Farwarding to #{backend_host}\n" }
57
+
58
+ conn.on_connect &Callbacks.on_connect
59
+ conn.on_data &Callbacks.on_data
60
+ conn.on_response &Callbacks.on_response
61
+ conn.on_finish &Callbacks.on_finish
62
+ end
63
+ end
64
+ end
65
+
66
+ module_function :run
67
+ end
68
+ end
@@ -0,0 +1,7 @@
1
+ class Configuration
2
+ attr_accessor :conf
3
+
4
+ def initialize(path)
5
+ @conf = YAML.load_file(path)
6
+ end
7
+ end
@@ -0,0 +1,16 @@
1
+ class Proxy
2
+ def self.stop
3
+ puts "Terminating ProxyServer"
4
+ EventMachine.stop
5
+ end
6
+
7
+ # this is not used
8
+ def self.kill_childs(servers, signal)
9
+ servers.each do |server|
10
+ puts "Killing process #{server[:pid]} with #{signal} signal."
11
+ Process.kill(signal, server[:pid])
12
+ end
13
+
14
+ Process.kill(signal, Process.pid)
15
+ end
16
+ end
@@ -0,0 +1,55 @@
1
+ require 'spec_helper'
2
+
3
+ describe Configuration do
4
+ before(:each) do
5
+ @conf = Configuration.new(ENV['GALERAB_CONFIG_PATH']).conf
6
+ end
7
+
8
+ context "when loading the file" do
9
+ it "should load the YAML file" do
10
+ @conf.should be_true
11
+ end
12
+
13
+ it "should find two balancers in the config file" do
14
+ @conf.size.should be == 2
15
+ end
16
+
17
+ it "gets the backends for balancer 1" do
18
+ @conf[1]['backends'].size.should be == 3
19
+ @conf[1]['backends'][0].should be == "192.168.10.101"
20
+ @conf[1]['backends'][1].should be == "192.168.10.102"
21
+ @conf[1]['backends'][2].should be == "192.168.10.103"
22
+ end
23
+
24
+ it "loads the other parameters" do
25
+ @conf[1]['check_every'].size.should be == 8
26
+ @conf[1]['user'].should be == "your_user"
27
+ @conf[1]['password'].should be == "your_password"
28
+ @conf[1]['database'].should be == "your_db"
29
+ @conf[1]['balancer_port'].should be == 3307
30
+ @conf[1]['backend_port'].should be == 3306
31
+ end
32
+ end
33
+ end
34
+
35
+ describe Backend do
36
+ before(:each) do
37
+ @conf = Configuration.new(ENV['GALERAB_CONFIG_PATH']).conf.first
38
+ @backend = Backend.new(@conf[1])
39
+ end
40
+
41
+ context "round robin load balancing" do
42
+ it "returns the next backend" do
43
+ @backend.get_next.should be == "192.168.10.102"
44
+ @backend.get_next.should be == "192.168.10.103"
45
+ @backend.get_next.should be == "192.168.10.101"
46
+ @backend.get_next.should be == "192.168.10.102" # and again... that's why it is called round robin
47
+ end
48
+
49
+ it "does not return a backend that is not ready" do
50
+ @backend.not_ready.push("192.168.10.103")
51
+ @backend.get_next.should be == "192.168.10.102"
52
+ @backend.get_next.should be == "192.168.10.101"
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ describe Configuration do
4
+ before(:each) do
5
+ @conf = Configuration.new(ENV['GALERAB_CONFIG_PATH']).conf
6
+ end
7
+
8
+ context "when loading the file" do
9
+ it "should load the YAML file" do
10
+ @conf.should be_true
11
+ end
12
+
13
+ it "should find two balancers in the config file" do
14
+ @conf.size.should be == 2
15
+ end
16
+
17
+ it "gets the backends for balancer 1" do
18
+ @conf[1]['backends'].size.should be == 3
19
+ @conf[1]['backends'][0].should be == "192.168.10.101"
20
+ @conf[1]['backends'][1].should be == "192.168.10.102"
21
+ @conf[1]['backends'][2].should be == "192.168.10.103"
22
+ end
23
+
24
+ it "loads the other parameters" do
25
+ @conf[1]['check_every'].size.should be == 8
26
+ @conf[1]['user'].should be == "your_user"
27
+ @conf[1]['password'].should be == "your_password"
28
+ @conf[1]['database'].should be == "your_db"
29
+ @conf[1]['balancer_port'].should be == 3307
30
+ @conf[1]['backend_port'].should be == 3306
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,8 @@
1
+ require 'rspec'
2
+ ENV['GALERAB_CONFIG_PATH'] = File.dirname(__FILE__) + '/galerab.yml'
3
+ require 'galerab'
4
+
5
+ RSpec.configure do |config|
6
+ config.color_enabled = true
7
+ config.formatter = 'documentation'
8
+ end
metadata ADDED
@@ -0,0 +1,160 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: galerab
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Riccardo Tacconi
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-01-09 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: mysql2
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 0.3.11
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 0.3.11
30
+ - !ruby/object:Gem::Dependency
31
+ name: sequel
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: 3.40.0
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: 3.40.0
46
+ - !ruby/object:Gem::Dependency
47
+ name: em-proxy
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: 0.1.7
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: 0.1.7
62
+ - !ruby/object:Gem::Dependency
63
+ name: ansi
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: 1.4.3
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 1.4.3
78
+ - !ruby/object:Gem::Dependency
79
+ name: rake
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: rspec
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ~>
100
+ - !ruby/object:Gem::Version
101
+ version: '2.5'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ~>
108
+ - !ruby/object:Gem::Version
109
+ version: '2.5'
110
+ description: This load balancer is a transparent proxy to route r/w requests to MySql
111
+ backends
112
+ email: rtacconi@virtuelogic.net
113
+ executables:
114
+ - galerab
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - lib/galerab.rb
119
+ - lib/galerab/backend.rb
120
+ - lib/galerab/balancing_proxy.rb
121
+ - lib/galerab/configuration.rb
122
+ - lib/galerab/proxy.rb
123
+ - bin/galerab
124
+ - files/galerab
125
+ - files/galerab.yml
126
+ - spec/lib/backend_spec.rb
127
+ - spec/lib/configuration_spec.rb
128
+ - spec/spec_helper.rb
129
+ homepage: http://github.com/rtacconi/galerab
130
+ licenses:
131
+ - MIT
132
+ post_install_message:
133
+ rdoc_options: []
134
+ require_paths:
135
+ - lib
136
+ - lib
137
+ - lib/galera
138
+ required_ruby_version: !ruby/object:Gem::Requirement
139
+ none: false
140
+ requirements:
141
+ - - ! '>='
142
+ - !ruby/object:Gem::Version
143
+ version: '0'
144
+ required_rubygems_version: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ! '>='
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ requirements: []
151
+ rubyforge_project:
152
+ rubygems_version: 1.8.24
153
+ signing_key:
154
+ specification_version: 3
155
+ summary: Load balancer for galera cluster
156
+ test_files:
157
+ - spec/lib/backend_spec.rb
158
+ - spec/lib/configuration_spec.rb
159
+ - spec/spec_helper.rb
160
+ has_rdoc: