bsl-thor 0.0.2
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/Gemfile +43 -0
- data/LICENSE.txt +20 -0
- data/Manifest +34 -0
- data/README +0 -0
- data/README.rdoc +18 -0
- data/Rakefile +12 -0
- data/app/amqp2sql.rb +107 -0
- data/bsl-thor.gemspec +29 -0
- data/lib/BslThor.rb +13 -0
- data/lib/ThorApplication.rb +139 -0
- data/lib/ThorClient.rb +319 -0
- data/lib/ThorCmd.rb +85 -0
- data/lib/ThorJob.rb +146 -0
- data/lib/ThorMaster.rb +226 -0
- data/lib/ThorNode.rb +203 -0
- data/lib/ThorUtils.rb +40 -0
- data/lib/ThorWorker.rb +58 -0
- data/lib/boot/Boot.rb +72 -0
- data/lib/boot/Client.rb +25 -0
- data/lib/boot/Master.rb +26 -0
- data/lib/boot/Node.rb +16 -0
- data/lib/config/ThorClient.yml.template +12 -0
- data/lib/config/ThorCmd.yml.template +4 -0
- data/lib/config/ThorMaster.yml.template +19 -0
- data/lib/config/ThorNode.yml.template +7 -0
- data/lib/config/ThorWorker.yml.template +4 -0
- data/lib/jobs/Client-0.0.1/main.rb +32 -0
- data/lib/jobs/Master-0.0.1/main.rb +32 -0
- data/lib/jobs/MonitorClient-0.0.1/main.rb +74 -0
- data/lib/jobs/MonitorMaster-0.0.1/main.rb +90 -0
- data/lib/jobs/Node-0.0.1/main.rb +56 -0
- data/lib/models/ThorModelClient.rb +9 -0
- data/lib/models/ThorModelJob.rb +9 -0
- data/lib/models/ThorModelWorker.rb +9 -0
- metadata +132 -0
data/lib/ThorMaster.rb
ADDED
@@ -0,0 +1,226 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$KCODE="UTF8"
|
4
|
+
|
5
|
+
# Options parsing gems
|
6
|
+
require 'optparse'
|
7
|
+
require 'pp'
|
8
|
+
|
9
|
+
# YAML
|
10
|
+
require 'yaml'
|
11
|
+
|
12
|
+
# Rubygems
|
13
|
+
require 'rubygems'
|
14
|
+
|
15
|
+
# Amqp Gems
|
16
|
+
require 'amqp'
|
17
|
+
#require 'mq'
|
18
|
+
|
19
|
+
# Event machine
|
20
|
+
require 'eventmachine'
|
21
|
+
|
22
|
+
# DB Related stuff
|
23
|
+
require 'active_record'
|
24
|
+
require 'pg'
|
25
|
+
|
26
|
+
# Custom gems
|
27
|
+
require File.join(File.dirname(__FILE__), 'ThorApplication.rb')
|
28
|
+
require 'Bsl'
|
29
|
+
|
30
|
+
module Thor
|
31
|
+
class AppMaster < Thor::Application
|
32
|
+
attr_accessor :options, :sql_connection, :request_exit
|
33
|
+
|
34
|
+
def initialize(opts = {})
|
35
|
+
super(opts)
|
36
|
+
|
37
|
+
@@AMQP_DEFAULT_RETRY_INTERVAL = 3
|
38
|
+
@@AMQP_MAX_RETRY_INTERVAL = (30)
|
39
|
+
@@AMQP_MAX_RETRY_ATTEMPS = -1
|
40
|
+
@@AMQP_RETRY_MULTIPLER = 1.5
|
41
|
+
|
42
|
+
@amqp_retry_interval = @@AMQP_DEFAULT_RETRY_INTERVAL
|
43
|
+
@amqp_retry_attempt = 0
|
44
|
+
|
45
|
+
# Signalizes that application wants exit for some reason
|
46
|
+
@request_exit = false
|
47
|
+
|
48
|
+
# AMQP options
|
49
|
+
@options[:amqp_host] = "localhost"
|
50
|
+
@options[:amqp_port] = 1234
|
51
|
+
@options[:amqp_user] = "user"
|
52
|
+
@options[:amqp_password] = "password"
|
53
|
+
@options[:amqp_vhost] = "my-vhost"
|
54
|
+
|
55
|
+
@options[:sql_adapter] = "postgresql"
|
56
|
+
@options[:sql_host] = "host"
|
57
|
+
@options[:sql_port] = 5432
|
58
|
+
@options[:sql_user] = "user"
|
59
|
+
@options[:sql_password] = "password"
|
60
|
+
@options[:sql_database] = "database"
|
61
|
+
|
62
|
+
@sql_connection = nil
|
63
|
+
|
64
|
+
initialize_optparser { |opts|
|
65
|
+
############################
|
66
|
+
# AMQP Section
|
67
|
+
############################
|
68
|
+
# AMQP Host
|
69
|
+
opts.on( '-H', '--amqp-host STRING', "AMQP Server hostname") do |host|
|
70
|
+
@options[:amqp_host] = host
|
71
|
+
end
|
72
|
+
|
73
|
+
# AMQP Port
|
74
|
+
opts.on( '-p', '--amqp-port NUM', "AMQP Server port number") do |port|
|
75
|
+
@options[:amqp_port] = port
|
76
|
+
end
|
77
|
+
|
78
|
+
# AMQP Username
|
79
|
+
opts.on( '-u', '--amqp-user STRING', "AMQP Username") do |user|
|
80
|
+
@options[:amqp_user] = user
|
81
|
+
end
|
82
|
+
|
83
|
+
# AMQP Password
|
84
|
+
opts.on( '-P', '--amqp-password STRING', "AMQP Password") do |password|
|
85
|
+
@options[:amqp_password] = password
|
86
|
+
end
|
87
|
+
|
88
|
+
# AMQP Vhost
|
89
|
+
opts.on( '-V', '--amqp-vhost STRING', "AMQP Virtual Host") do |vhost|
|
90
|
+
@options[:amqp_vhost] = vhost
|
91
|
+
end
|
92
|
+
|
93
|
+
############################
|
94
|
+
# Sql section
|
95
|
+
############################
|
96
|
+
# SQL Adapter
|
97
|
+
opts.on( '-sA', '--sql-adapter STRING', "SQL Adapter") do |adapter|
|
98
|
+
@options[:sql_adapter] = adapter
|
99
|
+
end
|
100
|
+
|
101
|
+
# SQL Host
|
102
|
+
opts.on( '-sH', '--sql-host STRING', "SQL Server hostname") do |host|
|
103
|
+
@options[:sql_host] = host
|
104
|
+
end
|
105
|
+
|
106
|
+
# SQL Port
|
107
|
+
opts.on( '-sp', '--sql-port NUM', "SQL Server port number") do |port|
|
108
|
+
@options[:sql_port] = port
|
109
|
+
end
|
110
|
+
|
111
|
+
# SQL Username
|
112
|
+
opts.on( '-su', '--sql-user STRING', "SQL Username") do |user|
|
113
|
+
@options[:sql_user] = user
|
114
|
+
end
|
115
|
+
|
116
|
+
# SQL Password
|
117
|
+
opts.on( '-sP', '--sql-password STRING', "SQL Password") do |password|
|
118
|
+
@options[:sql_password] = password
|
119
|
+
end
|
120
|
+
|
121
|
+
# SQL Database
|
122
|
+
opts.on( '-sD', '--sql-database STRING', "SQL Database") do |database|
|
123
|
+
@options[:sql_adapter] = database
|
124
|
+
end
|
125
|
+
}
|
126
|
+
end
|
127
|
+
|
128
|
+
# Resets internal AMQP connection failure counter/interval
|
129
|
+
def amqp_reset_retry_interval
|
130
|
+
@amqp_retry_interval = @@AMQP_DEFAULT_RETRY_INTERVAL
|
131
|
+
@amqp_retry_attempt = 0
|
132
|
+
end
|
133
|
+
|
134
|
+
# Starts AMQP connection
|
135
|
+
def amqp_start
|
136
|
+
Bsl::Logger::Log "Starting AMQP - Connecting #{options[:amqp_user]}@#{options[:amqp_host]}:#{options[:amqp_port]}#{options[:amqp_vhost]}"
|
137
|
+
AMQP.start(:host => options[:amqp_host], :port => options[:amqp_port], :vhost => options[:amqp_vhost], :user => options[:amqp_user], :password => options[:amqp_password] ) do
|
138
|
+
amqp_reset_retry_interval()
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
# Stops Running AMQP connection
|
143
|
+
def amqp_stop
|
144
|
+
AMQP.stop { EM.stop }
|
145
|
+
end
|
146
|
+
|
147
|
+
# Connects to SQL
|
148
|
+
def sql_start
|
149
|
+
Bsl::Logger::Log "Connecting to SQL - Connecting #{options[:sql_adapter]}://#{options[:sql_user]}@#{options[:sql_host]}:#{options[:sql_port]}"
|
150
|
+
|
151
|
+
|
152
|
+
begin
|
153
|
+
ActiveRecord::Base.establish_connection(
|
154
|
+
{
|
155
|
+
:adapter => options[:sql_adapter],
|
156
|
+
:host => options[:sql_host],
|
157
|
+
:username => options[:sql_user],
|
158
|
+
:password => options[:sql_password],
|
159
|
+
:database => options[:sql_database]
|
160
|
+
}
|
161
|
+
)
|
162
|
+
@sql_connection = ActiveRecord::Base.connection
|
163
|
+
rescue Exception => e
|
164
|
+
Bsl::Logger::Log "Could not connect to DB, reason: #{e.message}!"
|
165
|
+
return false
|
166
|
+
end
|
167
|
+
|
168
|
+
return @sql_connection != nil
|
169
|
+
end
|
170
|
+
|
171
|
+
# Stop SQL connection
|
172
|
+
def sql_stop
|
173
|
+
|
174
|
+
end
|
175
|
+
|
176
|
+
# Handles failure when connecting to AMQP
|
177
|
+
def amqp_handle_failure(e)
|
178
|
+
amqp_stop()
|
179
|
+
|
180
|
+
max_attempts_reached = false
|
181
|
+
if(@@AMQP_MAX_RETRY_ATTEMPS != nil && @@AMQP_MAX_RETRY_ATTEMPS >= 0)
|
182
|
+
@amqp_retry_attempt = @amqp_retry_attempt + 1
|
183
|
+
max_attempts_reached = @amqp_retry_attempt > @@AMQP_MAX_RETRY_ATTEMPS
|
184
|
+
end
|
185
|
+
|
186
|
+
if(max_attempts_reached == false)
|
187
|
+
Bsl::Logger::Log "Unable to connect to AMQP: #{e.to_s}"
|
188
|
+
Bsl::Logger::Log "Next attempt in #{@amqp_retry_interval} sec(s)."
|
189
|
+
|
190
|
+
sleep (@amqp_retry_interval)
|
191
|
+
@amqp_retry_interval = @amqp_retry_interval * @@AMQP_RETRY_MULTIPLER
|
192
|
+
@amqp_retry_interval = @@AMQP_MAX_RETRY_INTERVAL if @amqp_retry_interval > @@AMQP_MAX_RETRY_INTERVAL
|
193
|
+
else
|
194
|
+
if(@@AMQP_MAX_RETRY_ATTEMPS != nil)
|
195
|
+
Bsl::Logger::Log "Maximum AQMP reconnect attempts limit reached (#{@@AMQP_MAX_RETRY_ATTEMPS}), quitting."
|
196
|
+
end
|
197
|
+
@request_exit = true
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
# Main entry-point
|
202
|
+
def main
|
203
|
+
super()
|
204
|
+
|
205
|
+
if(sql_start() == false)
|
206
|
+
Bsl::Logger::Log "Unable to connect to DB, quitting!"
|
207
|
+
exit
|
208
|
+
end
|
209
|
+
|
210
|
+
# Run loop while exit is not requested
|
211
|
+
while(@request_exit == false)
|
212
|
+
begin
|
213
|
+
amqp_start()
|
214
|
+
rescue Exception => e
|
215
|
+
amqp_handle_failure(e)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
sql_stop()
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
if $0 == __FILE__
|
225
|
+
Thor::AppMaster.new.main
|
226
|
+
end
|
data/lib/ThorNode.rb
ADDED
@@ -0,0 +1,203 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$KCODE="UTF8"
|
4
|
+
|
5
|
+
# Options parsing gems
|
6
|
+
require 'optparse'
|
7
|
+
require 'pp'
|
8
|
+
|
9
|
+
# YAML
|
10
|
+
require 'yaml'
|
11
|
+
|
12
|
+
# Rubygems
|
13
|
+
require 'rubygems'
|
14
|
+
|
15
|
+
# Amqp Gems
|
16
|
+
require 'amqp'
|
17
|
+
#require 'mq'
|
18
|
+
|
19
|
+
# Event machine
|
20
|
+
require 'eventmachine'
|
21
|
+
|
22
|
+
require 'socket'
|
23
|
+
|
24
|
+
require 'digest/md5'
|
25
|
+
|
26
|
+
# Custom gems
|
27
|
+
require File.join(File.dirname(__FILE__), 'ThorApplication.rb')
|
28
|
+
require File.join(File.dirname(__FILE__), 'ThorUtils.rb')
|
29
|
+
require 'Bsl'
|
30
|
+
|
31
|
+
module Thor
|
32
|
+
class Node < Thor::Application
|
33
|
+
attr_accessor :request_exit, :jobs, :jobs_lock
|
34
|
+
|
35
|
+
StructJob = Struct.new(:klass, :path)
|
36
|
+
|
37
|
+
# C-tor
|
38
|
+
def initialize(opts = {})
|
39
|
+
super(opts)
|
40
|
+
|
41
|
+
@jobs = {}
|
42
|
+
@jobs_lock = Mutex.new
|
43
|
+
|
44
|
+
options[:jobs_dir] = File.join(File.dirname(__FILE__), 'jobs')
|
45
|
+
options[:boot_file] = ""
|
46
|
+
|
47
|
+
initialize_optparser { |opts|
|
48
|
+
############################
|
49
|
+
# AMQP Section
|
50
|
+
############################
|
51
|
+
# Jobs Dir
|
52
|
+
opts.on( '-j', '--jobs-dir STRING', "AMQP Virtual Host") do |jobs_dir|
|
53
|
+
options[:jobs_dir] = jobs_dir
|
54
|
+
end
|
55
|
+
|
56
|
+
# Boot file
|
57
|
+
opts.on( '-b', '--boot-file STRING', "Boot file specifying which jobs run automaticaly") do |boot_file|
|
58
|
+
options[:boot_file] = boot_file
|
59
|
+
end
|
60
|
+
}
|
61
|
+
end
|
62
|
+
|
63
|
+
def amqp_loop(amqp)
|
64
|
+
super(amqp)
|
65
|
+
|
66
|
+
# Start boot time jobs, move somewhere else!
|
67
|
+
boot_file = options[:boot_file]
|
68
|
+
if(boot_file != nil && boot_file != "")
|
69
|
+
boot_jobs = load_boot_file(boot_file)
|
70
|
+
if(boot_jobs != nil)
|
71
|
+
start_boot_time_jobs(boot_jobs, amqp)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
#amqp_exchange_create_direct(guid) # Create local direct exchange
|
76
|
+
#amqp_exchange_connect_master(options[:amqp_channel_master], guid)
|
77
|
+
end
|
78
|
+
|
79
|
+
# Enumerate existing jobs
|
80
|
+
def enumerate_jobs(dir, exclude = [])
|
81
|
+
res_jobs = {}
|
82
|
+
|
83
|
+
if(File.directory?(dir) == false)
|
84
|
+
return nil
|
85
|
+
end
|
86
|
+
|
87
|
+
Dir[dir + "/*"].each do |path|
|
88
|
+
next if (File.directory?(path) == false)
|
89
|
+
basename = File.basename(path)
|
90
|
+
dash_index = basename.index("-")
|
91
|
+
if(dash_index == nil || dash_index < 0 || (basename.length - dash_index - 1) < 5)
|
92
|
+
Bsl::Logger::Log "Invalid job dir name - #{path}"
|
93
|
+
next
|
94
|
+
end
|
95
|
+
|
96
|
+
job_name = basename.slice(0,dash_index)
|
97
|
+
job_name_version = basename.slice(dash_index+1, basename.length - dash_index)
|
98
|
+
|
99
|
+
job_main = File.join(path + "/main.rb")
|
100
|
+
if(File.exists?(job_main) == false)
|
101
|
+
Bsl::Logger::Log "Job entry point does not exists - #{job_main}"
|
102
|
+
next
|
103
|
+
end
|
104
|
+
|
105
|
+
require job_main
|
106
|
+
|
107
|
+
job = nil
|
108
|
+
begin
|
109
|
+
job = Thor::Jobs::const_get(job_name)
|
110
|
+
rescue
|
111
|
+
Bsl::Logger::Log "Unable to find class 'Thor::Jobs::#{job_name}' in file '#{job_main}'"
|
112
|
+
next
|
113
|
+
end
|
114
|
+
|
115
|
+
job_author = job.author
|
116
|
+
job_description = job.description
|
117
|
+
job_license = job.license
|
118
|
+
job_version = job.version
|
119
|
+
|
120
|
+
if(job_version != job_name_version)
|
121
|
+
Bsl::Logger::Log "Job '#{job_name}' inconsistent versions, filename: '#{job_name_version}', class: '#{job_version}, skipping.'"
|
122
|
+
next
|
123
|
+
end
|
124
|
+
|
125
|
+
Bsl::Logger::Log "Adding job, name: '#{job_name}', version: '#{job_version}', basename: '#{basename}'"
|
126
|
+
res_jobs[basename] = StructJob.new(job, job_main)
|
127
|
+
end
|
128
|
+
|
129
|
+
return res_jobs
|
130
|
+
end
|
131
|
+
|
132
|
+
# Load boot file if specified
|
133
|
+
def load_boot_file(boot_file)
|
134
|
+
Bsl::Logger::Log "Loading boot file '#{boot_file}'."
|
135
|
+
if(File.exists?(boot_file) == false)
|
136
|
+
Bsl::Logger::Log "Boot file '#{boot_file}' is not valid file path!"
|
137
|
+
return nil
|
138
|
+
end
|
139
|
+
|
140
|
+
require boot_file
|
141
|
+
basename = File.basename(boot_file, ".*")
|
142
|
+
return ThorBoot::const_get(basename)::boot_jobs
|
143
|
+
end
|
144
|
+
|
145
|
+
# Starts boot time jobs
|
146
|
+
def start_boot_time_jobs(boot_time_jobs, amqp)
|
147
|
+
boot_time_jobs.each do |boot_time_job|
|
148
|
+
@jobs_lock.synchronize {
|
149
|
+
job_name = boot_time_job[:name]
|
150
|
+
job = @jobs[job_name]
|
151
|
+
if(job != nil)
|
152
|
+
job_klass = job[:klass]
|
153
|
+
|
154
|
+
job_opts = options
|
155
|
+
job_opts = job_opts.merge(boot_time_job[:options])
|
156
|
+
job_opts = job_opts.merge({:amqp => {:conn => amqp}})
|
157
|
+
job_opts.merge!({:amqp => {:conn => amqp}}) # TODO: Use Thor::AmqpNode defaults
|
158
|
+
|
159
|
+
if(options[:verbose])
|
160
|
+
Bsl::Logger::Log "Starting boot job '#{job_klass.name}'."
|
161
|
+
#Bsl::Logger::Log "Job options '#{job_opts.inspect}'."
|
162
|
+
end
|
163
|
+
|
164
|
+
job_instance = job_klass.new(job_opts)
|
165
|
+
job_instance.start(job_opts)
|
166
|
+
Bsl::Logger::Log "Boot job '#{job_klass.name}' started."
|
167
|
+
else
|
168
|
+
Bsl::Logger::Log "Invalid boot job specified, name: '#{job_name}'"
|
169
|
+
end
|
170
|
+
}
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
# Main entry-point
|
175
|
+
def main
|
176
|
+
super()
|
177
|
+
|
178
|
+
# Refresh jobs
|
179
|
+
new_jobs = enumerate_jobs(options[:jobs_dir])
|
180
|
+
@jobs_lock. synchronize {
|
181
|
+
@jobs = new_jobs
|
182
|
+
}
|
183
|
+
|
184
|
+
# Run loop while exit is not requested
|
185
|
+
while(@request_exit == false)
|
186
|
+
begin
|
187
|
+
amqp_start()
|
188
|
+
rescue SystemExit, Interrupt
|
189
|
+
Bsl::Logger::Log "Received interrupt, quitting!"
|
190
|
+
@request_exit = true
|
191
|
+
amqp_stop()
|
192
|
+
rescue Exception => e
|
193
|
+
amqp_handle_failure(e)
|
194
|
+
end
|
195
|
+
puts "."
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
if $0 == __FILE__
|
202
|
+
Thor::Node.new.main
|
203
|
+
end
|
data/lib/ThorUtils.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'Bsl'
|
2
|
+
|
3
|
+
require 'sys/admin'
|
4
|
+
require 'sys/proctable'
|
5
|
+
require 'sys/uname'
|
6
|
+
require 'sys/cpu'
|
7
|
+
require 'sys/uptime'
|
8
|
+
require 'net/proto'
|
9
|
+
require 'sys/host'
|
10
|
+
require 'sys/filesystem'
|
11
|
+
|
12
|
+
module Thor
|
13
|
+
|
14
|
+
# Loads all ActiveRecord models
|
15
|
+
def self.require_all_models(logit = false)
|
16
|
+
dir = File.join(File.dirname(__FILE__), 'models/')
|
17
|
+
Dir[dir + '*.rb'].each do |file|
|
18
|
+
if(logit)
|
19
|
+
Bsl::Logger::Log "Including model '#{file}'"
|
20
|
+
end
|
21
|
+
require file
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Generates unique exchange name
|
26
|
+
# Format is following IP.HOSTNAME.PID.TID(INST_HASH)
|
27
|
+
# PID = Process ID
|
28
|
+
# TID = Thread ID
|
29
|
+
# INST_HASH = Hash from instance pointer if some instance is specified as param
|
30
|
+
def self.generate_guid(inst = nil)
|
31
|
+
res = ""
|
32
|
+
|
33
|
+
ip = Sys::Host.ip_addr.to_s.gsub(".", "-")
|
34
|
+
hostname = Sys::Host.hostname.gsub(".", "--")
|
35
|
+
pid = Process.pid
|
36
|
+
tid = Thread.current.object_id
|
37
|
+
instance = inst != nil ? ".#{instance.to_s}" : ""
|
38
|
+
return "#{ip.to_s}.#{hostname}.#{pid}.#{tid}#{instance}"
|
39
|
+
end
|
40
|
+
end
|
data/lib/ThorWorker.rb
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$KCODE="UTF8"
|
4
|
+
|
5
|
+
# Options parsing gems
|
6
|
+
require 'optparse'
|
7
|
+
require 'pp'
|
8
|
+
|
9
|
+
# YAML
|
10
|
+
require 'yaml'
|
11
|
+
|
12
|
+
# Rubygems
|
13
|
+
require 'rubygems'
|
14
|
+
|
15
|
+
# Event machine
|
16
|
+
require 'eventmachine'
|
17
|
+
|
18
|
+
# Custom gems
|
19
|
+
require File.join(File.dirname(__FILE__), 'ThorApplication.rb')
|
20
|
+
require 'Bsl'
|
21
|
+
|
22
|
+
module Thor
|
23
|
+
class AppWorker < Thor::Application
|
24
|
+
attr_accessor :options, :optpars
|
25
|
+
|
26
|
+
def initialize(opts = {})
|
27
|
+
super(opts)
|
28
|
+
|
29
|
+
# Event Machine options
|
30
|
+
options[:em_port] = 8467 # Thor on cell-phone keyboard
|
31
|
+
options[:em_auth_token] = ""
|
32
|
+
|
33
|
+
initialize_optparser { |opts|
|
34
|
+
############################
|
35
|
+
# EventMachine Section
|
36
|
+
############################
|
37
|
+
# EM Port
|
38
|
+
opts.on( '-ep', '--em-port NUM', "EventMachine port") do |port|
|
39
|
+
options[:em_port] = port
|
40
|
+
end
|
41
|
+
|
42
|
+
# EM Authentication token
|
43
|
+
opts.on( '-eat', '--em-auth-token STRING', "Authentication token used for communication with EM") do |token|
|
44
|
+
options[:em_auth_token] = token
|
45
|
+
end
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
# Main entry-point
|
50
|
+
def main
|
51
|
+
super()
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
if $0 == __FILE__
|
57
|
+
Thor::AppWorker.new.main
|
58
|
+
end
|
data/lib/boot/Boot.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$KCODE="UTF8"
|
4
|
+
|
5
|
+
module ThorBoot
|
6
|
+
class Boot
|
7
|
+
# Default AMQP Options
|
8
|
+
@@DEFAULT_AMQP = {
|
9
|
+
:amqp => {
|
10
|
+
:host => "amqp_host",
|
11
|
+
:port => 5672,
|
12
|
+
:user => "amqp_user",
|
13
|
+
:password => "amqp_password",
|
14
|
+
:vhost => "amqp_vhost"
|
15
|
+
}
|
16
|
+
}
|
17
|
+
|
18
|
+
# Default EventMachine Options
|
19
|
+
@@DEFAULT_EM = {
|
20
|
+
|
21
|
+
}
|
22
|
+
|
23
|
+
# Default SQL Options
|
24
|
+
@@DEFAULT_SQL = {
|
25
|
+
:sql => {
|
26
|
+
:host => "sql_host",
|
27
|
+
:port => 5432,
|
28
|
+
:user => "sql_user",
|
29
|
+
:password => "sql_password",
|
30
|
+
:schema => "public"
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
# Return default AMQP Options
|
35
|
+
def self.default_options_amqp
|
36
|
+
return @@DEFAULT_AMQP
|
37
|
+
end
|
38
|
+
|
39
|
+
# Returns default Event Machine Options
|
40
|
+
def self.default_options_em
|
41
|
+
return @@DEFAULT_EM
|
42
|
+
end
|
43
|
+
|
44
|
+
# Returns default SQL Options
|
45
|
+
def self.default_options_sql
|
46
|
+
return @@DEFAULT_SQL
|
47
|
+
end
|
48
|
+
|
49
|
+
# Return merged default Options
|
50
|
+
def self.default_options
|
51
|
+
res = {}
|
52
|
+
|
53
|
+
res.merge!(default_options_amqp)
|
54
|
+
res.merge!(default_options_em)
|
55
|
+
res.merge!(default_options_sql)
|
56
|
+
|
57
|
+
return res
|
58
|
+
end
|
59
|
+
|
60
|
+
# Merges options with default options
|
61
|
+
def self.merge_options(opts)
|
62
|
+
return default_options.merge(opts)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Default function for getting boot jobs
|
66
|
+
def self.boot_jobs
|
67
|
+
boot_jobs = []
|
68
|
+
return boot_jobs
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
data/lib/boot/Client.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$KCODE="UTF8"
|
4
|
+
|
5
|
+
require File.join(File.dirname(__FILE__), 'Node.rb')
|
6
|
+
|
7
|
+
module ThorBoot
|
8
|
+
class Client < Node
|
9
|
+
def self.boot_jobs
|
10
|
+
opts_node = {:channel_nodes => "clients"}
|
11
|
+
opts_client = {}
|
12
|
+
opts_monitor_client = {
|
13
|
+
:channel_request => "monitor.request",
|
14
|
+
:channel_response => "monitor.response"
|
15
|
+
}
|
16
|
+
boot_jobs = [
|
17
|
+
{:name => "Node-0.0.1", :options => merge_options(opts_node)},
|
18
|
+
{:name => "Client-0.0.1", :options => merge_options(opts_client)},
|
19
|
+
{:name => "MonitorClient-0.0.1", :options => merge_options(opts_monitor_client)}
|
20
|
+
]
|
21
|
+
return (super() + boot_jobs)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
data/lib/boot/Master.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$KCODE="UTF8"
|
4
|
+
|
5
|
+
require File.join(File.dirname(__FILE__), 'Node.rb')
|
6
|
+
|
7
|
+
module ThorBoot
|
8
|
+
class Master < Node
|
9
|
+
def self.boot_jobs
|
10
|
+
opts_node = {:channel_nodes => "masters"}
|
11
|
+
opts_master = {}
|
12
|
+
opts_monitor_master = {
|
13
|
+
:channel_request => "monitor.request",
|
14
|
+
:channel_response => "monitor.response",
|
15
|
+
:request_interval => 1
|
16
|
+
}
|
17
|
+
boot_jobs = [
|
18
|
+
{:name => "Node-0.0.1", :options => merge_options(opts_node)},
|
19
|
+
{:name => "Master-0.0.1", :options => merge_options(opts_master)},
|
20
|
+
{:name => "MonitorMaster-0.0.1", :options => merge_options(opts_monitor_master)}
|
21
|
+
]
|
22
|
+
return (super() + boot_jobs)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
data/lib/boot/Node.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$KCODE="UTF8"
|
4
|
+
|
5
|
+
require File.join(File.dirname(__FILE__), 'Boot.rb')
|
6
|
+
|
7
|
+
module ThorBoot
|
8
|
+
class Node < Boot
|
9
|
+
def self.boot_jobs
|
10
|
+
opts = {:channel_nodes => "nodes"}
|
11
|
+
boot_jobs = [{:name => "Node-0.0.1", :options => merge_options(opts)}]
|
12
|
+
return (super() + boot_jobs)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
verbose: false
|
2
|
+
|
3
|
+
amqp_host: "host"
|
4
|
+
amqp_port: 5672
|
5
|
+
amqp_user: "user"
|
6
|
+
amqp_password: "password"
|
7
|
+
amqp_vhost: "vhost"
|
8
|
+
|
9
|
+
sql_adapter: "postgresql"
|
10
|
+
sql_host: "host"
|
11
|
+
sql_port: 5432
|
12
|
+
sql_user: "user"
|
13
|
+
sql_password: "password"
|
14
|
+
sql_database: "db"
|
15
|
+
|
16
|
+
amqp_channel_master: "master"
|
17
|
+
|
18
|
+
em_port: 8467
|
19
|
+
em_auth_token: ""
|