manband 0.5.1 → 0.6.0
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/README +5 -1
- data/bin/jobhandler.rb +32 -3
- data/bin/manband.rb +1 -0
- data/bin/remoteband.rb +15 -3
- data/bin/workflowhandler.rb +45 -10
- data/lib/manband/bandmanager.rb +6 -5
- data/lib/manband/flowconfig.rb +16 -0
- data/lib/manband/job.rb +11 -5
- data/lib/manband/util.rb +50 -0
- metadata +8 -21
data/README
CHANGED
@@ -102,7 +102,11 @@ By default, bucket used is "manband". It can be specified in command-line.
|
|
102
102
|
## Gem creation
|
103
103
|
|
104
104
|
Execute:
|
105
|
-
|
105
|
+
rake package
|
106
106
|
|
107
107
|
Gem is created in pkg directory
|
108
108
|
Webband may use this gem, or use current files with same hierarchy
|
109
|
+
|
110
|
+
## History
|
111
|
+
|
112
|
+
0.6.0: Remove mb-minion dependency. New bunny gem is incompatible now, code has been rewriten to remove the dependency and use only amqp.
|
data/bin/jobhandler.rb
CHANGED
@@ -3,9 +3,7 @@ require 'yaml'
|
|
3
3
|
require 'optparse'
|
4
4
|
require 'amqp'
|
5
5
|
require 'json'
|
6
|
-
require 'mb-minion'
|
7
6
|
|
8
|
-
include Minion
|
9
7
|
|
10
8
|
# The program manages job commands. Master nodes (workflow handler) sends
|
11
9
|
# messages to jobhandler instances. Each instance manages one and
|
@@ -93,7 +91,33 @@ end
|
|
93
91
|
|
94
92
|
log.info "Start handler "+handler
|
95
93
|
|
96
|
-
|
94
|
+
urlconfig = FlowConfig.config()
|
95
|
+
|
96
|
+
|
97
|
+
EventMachine.run do
|
98
|
+
connection = AMQP.connect(FlowConfig.config())
|
99
|
+
|
100
|
+
show_stopper = Proc.new do
|
101
|
+
$stdout.puts "Stopping..."
|
102
|
+
connection.close {
|
103
|
+
EventMachine.stop { exit }
|
104
|
+
}
|
105
|
+
end
|
106
|
+
|
107
|
+
Signal.trap 'INT', show_stopper
|
108
|
+
Signal.trap 'TERM', show_stopper
|
109
|
+
|
110
|
+
channel_exception_handler = Proc.new { |ch, channel_close| EventMachine.stop; raise "channel error: #{channel_close.reply_text}" }
|
111
|
+
|
112
|
+
channel = AMQP::Channel.new(connection)
|
113
|
+
#channel.on_error(&channel_exception_handler)
|
114
|
+
channel.prefetch(1)
|
115
|
+
|
116
|
+
exchange = channel.direct()
|
117
|
+
queue = channel.queue('manband.node'+options[:queue], :auto_delete => false, :durable => true)
|
118
|
+
queue.bind(exchange).subscribe(:ack => true) do |metadata, message|
|
119
|
+
puts "##DEBUG "+message
|
120
|
+
args = JSON.parse(message)
|
97
121
|
msg = JSON.parse(args["msg"])
|
98
122
|
if args["operation"] == OP_DESTROY
|
99
123
|
myworkflow = WorkFlow.get(msg["id"])
|
@@ -127,5 +151,10 @@ job "manband.node"+options[:queue] do |args|
|
|
127
151
|
end
|
128
152
|
end
|
129
153
|
end
|
154
|
+
|
155
|
+
|
156
|
+
channel.acknowledge(metadata.delivery_tag, false)
|
157
|
+
end
|
158
|
+
|
130
159
|
end
|
131
160
|
|
data/bin/manband.rb
CHANGED
@@ -13,6 +13,7 @@ require 'manband/workflow.rb'
|
|
13
13
|
require 'manband/flowconfig.rb'
|
14
14
|
require 'manband/job.rb'
|
15
15
|
require 'manband/bandmanager.rb'
|
16
|
+
require 'manband/util.rb'
|
16
17
|
|
17
18
|
# The program sends a workflow execution request to manband orchestrator.
|
18
19
|
# Author: Olivier Sallou <olivier.sallou@irisa.fr>
|
data/bin/remoteband.rb
CHANGED
@@ -3,9 +3,13 @@ require 'yaml'
|
|
3
3
|
require 'optparse'
|
4
4
|
require 'amqp'
|
5
5
|
require 'json'
|
6
|
-
require '
|
6
|
+
require 'logger'
|
7
|
+
|
8
|
+
$:.push File.expand_path("../lib")
|
9
|
+
|
10
|
+
require 'manband/flowconfig.rb'
|
11
|
+
require 'manband/util.rb'
|
7
12
|
|
8
|
-
include Minion
|
9
13
|
|
10
14
|
# The program sends a workflow execution request to manband orchestrator.
|
11
15
|
# This program does not need database credentials but does not get workflow id in return
|
@@ -78,4 +82,12 @@ msg["wfile"]=options[:workflow]
|
|
78
82
|
msg["var"]=options[:var]
|
79
83
|
msg["uid"]=options[:uid]
|
80
84
|
msg["bucket"]=options[:bucket]
|
81
|
-
|
85
|
+
|
86
|
+
|
87
|
+
Utils.publish('manband.master',{ "operation" => "new", "msg" => msg.to_json })
|
88
|
+
|
89
|
+
urlconfig = FlowConfig.config()
|
90
|
+
|
91
|
+
|
92
|
+
|
93
|
+
|
data/bin/workflowhandler.rb
CHANGED
@@ -3,9 +3,7 @@ require 'yaml'
|
|
3
3
|
require 'optparse'
|
4
4
|
require 'amqp'
|
5
5
|
require 'json'
|
6
|
-
require 'mb-minion'
|
7
6
|
|
8
|
-
include Minion
|
9
7
|
|
10
8
|
# The program s the main orchestrator of the workflow.
|
11
9
|
# It starts with a workflow execution request and sends messages to job
|
@@ -26,6 +24,7 @@ end
|
|
26
24
|
|
27
25
|
$:.push File.expand_path("../lib")
|
28
26
|
|
27
|
+
require 'manband/flowconfig.rb'
|
29
28
|
require 'manband/workflow.rb'
|
30
29
|
require 'manband/job.rb'
|
31
30
|
require 'manband/bandmanager.rb'
|
@@ -33,8 +32,17 @@ require 'manband/bandmanager.rb'
|
|
33
32
|
log = Logger.new(STDOUT)
|
34
33
|
log.level = Logger::INFO
|
35
34
|
|
35
|
+
|
36
36
|
@@options = {}
|
37
37
|
|
38
|
+
def savemessage(id,operation,msg)
|
39
|
+
if @@options[:debug] == false
|
40
|
+
return
|
41
|
+
end
|
42
|
+
bmsg = BandMessage.new(:wid => id, :message => '{ "operation" => '+operation+', "msg" => '+msg+' }' )
|
43
|
+
bmsg.save
|
44
|
+
end
|
45
|
+
|
38
46
|
optparse = OptionParser.new do|opts|
|
39
47
|
|
40
48
|
# This displays the help screen, all programs are
|
@@ -75,8 +83,37 @@ if @@options[:conf]!=nil
|
|
75
83
|
FlowConfig.setworkdir(conf["workdir"])
|
76
84
|
end
|
77
85
|
|
78
|
-
|
86
|
+
|
87
|
+
EventMachine.run do
|
88
|
+
connection = AMQP.connect(FlowConfig.config())
|
89
|
+
|
90
|
+
show_stopper = Proc.new do
|
91
|
+
$stdout.puts "Stopping..."
|
92
|
+
connection.close {
|
93
|
+
EventMachine.stop { exit }
|
94
|
+
}
|
95
|
+
end
|
96
|
+
|
97
|
+
Signal.trap 'INT', show_stopper
|
98
|
+
Signal.trap 'TERM', show_stopper
|
99
|
+
|
100
|
+
channel_exception_handler = Proc.new { |ch, channel_close| EventMachine.stop; raise "channel error: #{channel_close.reply_text}" }
|
101
|
+
|
102
|
+
channel = AMQP::Channel.new(connection)
|
103
|
+
#channel.on_error(&channel_exception_handler)
|
104
|
+
channel.prefetch(1)
|
105
|
+
|
106
|
+
exchange = channel.direct()
|
107
|
+
queue = channel.queue('manband.master', :auto_delete => false, :durable => true)
|
108
|
+
queue.bind(exchange).subscribe(:ack => true) do |metadata, message|
|
109
|
+
|
110
|
+
begin
|
111
|
+
args = JSON.parse(message)
|
79
112
|
msg = JSON.parse(args["msg"])
|
113
|
+
rescue Exception => e
|
114
|
+
log.error("Could not parse message "+args["msg"])
|
115
|
+
channel.acknowledge(metadata.delivery_tag, false)
|
116
|
+
end
|
80
117
|
if args["operation"] == OP_NEW
|
81
118
|
BandManager.launch(msg["wfile"],msg["var"],msg["uid"],msg["bucket"])
|
82
119
|
end
|
@@ -180,12 +217,10 @@ job "manband.master" do |args|
|
|
180
217
|
curjob.resume
|
181
218
|
end
|
182
219
|
end
|
183
|
-
end
|
184
220
|
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
bmsg = BandMessage.new(:wid => id, :message => '{ "operation" => '+operation+', "msg" => '+msg+' }' )
|
190
|
-
bmsg.save
|
221
|
+
|
222
|
+
channel.acknowledge(metadata.delivery_tag, false)
|
223
|
+
end
|
224
|
+
|
191
225
|
end
|
226
|
+
|
data/lib/manband/bandmanager.rb
CHANGED
@@ -3,10 +3,8 @@ require 'yaml'
|
|
3
3
|
require 'optparse'
|
4
4
|
require 'amqp'
|
5
5
|
require 'json'
|
6
|
-
require 'mb-minion'
|
7
6
|
require 'fileutils'
|
8
7
|
|
9
|
-
include Minion
|
10
8
|
|
11
9
|
require 'manband/workflow.rb'
|
12
10
|
require 'manband/flowconfig.rb'
|
@@ -136,9 +134,9 @@ class BandManager
|
|
136
134
|
# Request workflow management
|
137
135
|
msg = '{ "id" : "'+workflow.id.to_s+'", "root" : "'+rootjob.id.to_s+'"}'
|
138
136
|
if debug
|
139
|
-
|
137
|
+
Utils.publish("manband.master", { "operation" => OP_SKIP, "msg" => msg })
|
140
138
|
else
|
141
|
-
|
139
|
+
Utils.publish("manband.master", { "operation" => OP_START, "msg" => msg })
|
142
140
|
end
|
143
141
|
end
|
144
142
|
end
|
@@ -153,7 +151,10 @@ class BandManager
|
|
153
151
|
newworkflow.parse('root',rootjob.id)
|
154
152
|
jobmsg = '{ "id" : "'+newworkflow.id.to_s+'", "root" : "'+rootjob.id.to_s+'"}'
|
155
153
|
job = Job.new(:wid => newworkflow.id, :node => "fake", :command => "", :status => STATUS_FAKE, :instances => 0, :workdir => '')
|
156
|
-
|
154
|
+
|
155
|
+
Utils.publish('manband.master', { "operation" => OP_START, "msg" => jobmsg })
|
156
|
+
job.logMessage(OP_START,jobmsg)
|
157
|
+
|
157
158
|
return newworkflow.id
|
158
159
|
end
|
159
160
|
|
data/lib/manband/flowconfig.rb
CHANGED
@@ -113,6 +113,22 @@ class FlowConfig
|
|
113
113
|
end
|
114
114
|
end
|
115
115
|
|
116
|
+
def self.config
|
117
|
+
url ||= (ENV["AMQP_URL"] || "amqp://guest:guest@localhost/")
|
118
|
+
uri = URI.parse(url)
|
119
|
+
{
|
120
|
+
:vhost => uri.path,
|
121
|
+
:host => uri.host,
|
122
|
+
:user => uri.user,
|
123
|
+
:port => (uri.port || 5672),
|
124
|
+
:pass => uri.password,
|
125
|
+
:heartbeat => 0
|
126
|
+
}
|
127
|
+
rescue Object => e
|
128
|
+
raise("invalid AMQP_URL: #{uri.inspect} (#{e})")
|
129
|
+
end
|
130
|
+
|
131
|
+
|
116
132
|
|
117
133
|
end
|
118
134
|
|
data/lib/manband/job.rb
CHANGED
@@ -3,10 +3,9 @@ require 'dm-migrations'
|
|
3
3
|
require 'yaml'
|
4
4
|
require 'manband/workflow.rb'
|
5
5
|
require 'manband/flowconfig.rb'
|
6
|
-
require '
|
6
|
+
require 'manband/util.rb'
|
7
7
|
require 'logger'
|
8
8
|
|
9
|
-
include Minion
|
10
9
|
|
11
10
|
#DataMapper.setup(:default, 'sqlite:///home/osallou/Desktop/genflow/project.db')
|
12
11
|
DataMapper.setup(:default, ENV['MYSQL_URL'])
|
@@ -68,6 +67,7 @@ class Job
|
|
68
67
|
if instance>0
|
69
68
|
workdir = workdir + "/node" + instance.to_s
|
70
69
|
end
|
70
|
+
EventMachine.defer do
|
71
71
|
err = runcommand(workdir,instance)
|
72
72
|
if err == nil || err == false
|
73
73
|
# An error occured
|
@@ -82,6 +82,7 @@ class Job
|
|
82
82
|
jobmsg = '{ "workflow" : "'+@wid.to_s+'" , "node" : "'+@node+'", "id" : "'+@id.to_s+'", "handler" : "'+curhandler.to_s+'", "instance" : "'+instance.to_s+'" }'
|
83
83
|
sendmessage(OP_FINISH,jobmsg)
|
84
84
|
end
|
85
|
+
end # End EventMachine
|
85
86
|
end
|
86
87
|
|
87
88
|
# Skip treatment, just answer, for debug
|
@@ -117,7 +118,7 @@ class Job
|
|
117
118
|
cmd = "sudo -u "+wflow.uid+" '"+script+"'"
|
118
119
|
end
|
119
120
|
@@log.debug cmd
|
120
|
-
|
121
|
+
system(cmd)
|
121
122
|
end
|
122
123
|
|
123
124
|
# Change instance counter
|
@@ -292,12 +293,17 @@ class Job
|
|
292
293
|
queue = "manband.node"+jobqueue
|
293
294
|
end
|
294
295
|
if queue != nil
|
295
|
-
|
296
|
+
Utils.enqueue(queue, { "operation" => operation, "msg" => msg })
|
297
|
+
logMessage(operation,msg)
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
# If debug, log the message in the database
|
302
|
+
def logMessage(operation,msg)
|
296
303
|
if @@debug == true
|
297
304
|
bmsg = BandMessage.new(:wid => @wid, :message => '{ "operation" => '+operation+', "msg" => '+msg+' }' )
|
298
305
|
bmsg.save
|
299
306
|
end
|
300
|
-
end
|
301
307
|
end
|
302
308
|
|
303
309
|
end
|
data/lib/manband/util.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'manband/flowconfig.rb'
|
2
|
+
require 'amqp'
|
3
|
+
|
4
|
+
# Utility classes
|
5
|
+
class Utils
|
6
|
+
|
7
|
+
|
8
|
+
@@connection = nil
|
9
|
+
@@channel = nil
|
10
|
+
@@exchange = nil
|
11
|
+
|
12
|
+
def self.setcontext()
|
13
|
+
if(@@connection==nil)
|
14
|
+
@@connection = AMQP.connect(FlowConfig.config())
|
15
|
+
@@channel = AMQP::Channel.new(@@connection)
|
16
|
+
@@exchange = @@channel.direct()
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# Send a message in context
|
21
|
+
# args:
|
22
|
+
# dest name of destination queue
|
23
|
+
# msg message to send. Message is a hash with keys operation and msg.
|
24
|
+
def self.enqueue(dest,data= {})
|
25
|
+
Utils.setcontext()
|
26
|
+
msg = data.to_json
|
27
|
+
queue = @@channel.queue(dest, :auto_delete => false, :durable => true)
|
28
|
+
queue.bind(@@exchange)
|
29
|
+
@@exchange.publish(msg)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Creates a context and sends a message
|
33
|
+
# args:
|
34
|
+
# dest name of destination queue
|
35
|
+
# msg message to send. Message is a hash with keys operation and msg.
|
36
|
+
def self.publish(dest,data= {})
|
37
|
+
msg = data.to_json
|
38
|
+
EventMachine.run do
|
39
|
+
connection = AMQP.connect(FlowConfig.config())
|
40
|
+
channel = AMQP::Channel.new(connection)
|
41
|
+
exchange = channel.direct()
|
42
|
+
queue = channel.queue(dest, :auto_delete => false, :durable => true)
|
43
|
+
queue.bind(exchange)
|
44
|
+
exchange.publish(msg) do
|
45
|
+
connection.close { EventMachine.stop }
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: manband
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 7
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 6
|
9
|
+
- 0
|
10
|
+
version: 0.6.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Olivier Sallou
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-07-
|
18
|
+
date: 2012-07-17 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: amqp
|
@@ -88,7 +88,7 @@ dependencies:
|
|
88
88
|
type: :runtime
|
89
89
|
version_requirements: *id005
|
90
90
|
- !ruby/object:Gem::Dependency
|
91
|
-
name: mb-
|
91
|
+
name: mb-aws-s3
|
92
92
|
prerelease: false
|
93
93
|
requirement: &id006 !ruby/object:Gem::Requirement
|
94
94
|
none: false
|
@@ -102,7 +102,7 @@ dependencies:
|
|
102
102
|
type: :runtime
|
103
103
|
version_requirements: *id006
|
104
104
|
- !ruby/object:Gem::Dependency
|
105
|
-
name:
|
105
|
+
name: uuid
|
106
106
|
prerelease: false
|
107
107
|
requirement: &id007 !ruby/object:Gem::Requirement
|
108
108
|
none: false
|
@@ -115,20 +115,6 @@ dependencies:
|
|
115
115
|
version: "0"
|
116
116
|
type: :runtime
|
117
117
|
version_requirements: *id007
|
118
|
-
- !ruby/object:Gem::Dependency
|
119
|
-
name: uuid
|
120
|
-
prerelease: false
|
121
|
-
requirement: &id008 !ruby/object:Gem::Requirement
|
122
|
-
none: false
|
123
|
-
requirements:
|
124
|
-
- - ">="
|
125
|
-
- !ruby/object:Gem::Version
|
126
|
-
hash: 3
|
127
|
-
segments:
|
128
|
-
- 0
|
129
|
-
version: "0"
|
130
|
-
type: :runtime
|
131
|
-
version_requirements: *id008
|
132
118
|
description:
|
133
119
|
email: olivier.sallou@irisa.fr
|
134
120
|
executables: []
|
@@ -148,6 +134,7 @@ files:
|
|
148
134
|
- lib/manband/bandmanager.rb
|
149
135
|
- lib/manband/user.rb
|
150
136
|
- lib/manband/workflow.rb
|
137
|
+
- lib/manband/util.rb
|
151
138
|
- lib/manband/job.rb
|
152
139
|
- lib/manband/flowconfig.rb
|
153
140
|
- README
|