manband 0.4.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
data/bin/jobhandler.rb CHANGED
@@ -7,6 +7,13 @@ require 'mb-minion'
7
7
 
8
8
  include Minion
9
9
 
10
+ # The program manages job commands. Master nodes (workflow handler) sends
11
+ # messages to jobhandler instances. Each instance manages one and
12
+ # only one message at a time. Jobhnadlers are also in charge of storage to S3.
13
+ # Author: Olivier Sallou <olivier.sallou@irisa.fr>
14
+ # Copyright: 2012, IRISA
15
+
16
+
10
17
  if ENV["MYSQL_URL"]==nil
11
18
  puts "MYSQL_URL environment variable is not set exiting..."
12
19
  exit 1
data/bin/manband.rb CHANGED
@@ -14,6 +14,10 @@ require 'manband/flowconfig.rb'
14
14
  require 'manband/job.rb'
15
15
  require 'manband/bandmanager.rb'
16
16
 
17
+ # The program sends a workflow execution request to manband orchestrator.
18
+ # Author: Olivier Sallou <olivier.sallou@irisa.fr>
19
+ # Copyright: 2012, IRISA
20
+
17
21
  log = Logger.new(STDOUT)
18
22
  log.level = Logger::INFO
19
23
 
data/bin/remoteband.rb CHANGED
@@ -7,6 +7,11 @@ require 'mb-minion'
7
7
 
8
8
  include Minion
9
9
 
10
+ # The program sends a workflow execution request to manband orchestrator.
11
+ # This program does not need database credentials but does not get workflow id in return
12
+ # Author: Olivier Sallou <olivier.sallou@irisa.fr>
13
+ # Copyright: 2012, IRISA
14
+
10
15
 
11
16
  log = Logger.new(STDOUT)
12
17
  log.level = Logger::INFO
data/bin/userband.rb CHANGED
@@ -8,6 +8,12 @@ $:.push File.expand_path("../lib")
8
8
 
9
9
  require 'manband/flowconfig.rb'
10
10
 
11
+ # The program is used to manage users (add, update) in the database.
12
+ # Users are used for web interface authentification and S3 credentials.
13
+ # Author: Olivier Sallou <olivier.sallou@irisa.fr>
14
+ # Copyright: 2012, IRISA
15
+
16
+
11
17
  log = Logger.new(STDOUT)
12
18
  log.level = Logger::INFO
13
19
 
@@ -7,6 +7,15 @@ require 'mb-minion'
7
7
 
8
8
  include Minion
9
9
 
10
+ # The program s the main orchestrator of the workflow.
11
+ # It starts with a workflow execution request and sends messages to job
12
+ # handlers according to the input workflow.
13
+ # It is possible to have multipe workflow handler, sharing messages for
14
+ # the same workflow, or to handler a high number of workflow requests.
15
+ # Author: Olivier Sallou <olivier.sallou@irisa.fr>
16
+ # Copyright: 2012, IRISA
17
+
18
+
10
19
  if ENV["MYSQL_URL"]==nil
11
20
  puts "MYSQL_URL environment variable is not set exiting..."
12
21
  exit 1
@@ -52,7 +61,7 @@ optparse.parse!
52
61
 
53
62
  userconf = File.expand_path("~")+"/.manband"
54
63
  if @@options[:conf]==nil && File.exists?(userconf)
55
- options[:conf]=userconf
64
+ @@options[:conf]=userconf
56
65
  end
57
66
 
58
67
  if @@options[:conf]!=nil
@@ -11,14 +11,14 @@ include Minion
11
11
  require 'manband/workflow.rb'
12
12
  require 'manband/flowconfig.rb'
13
13
 
14
- # Library to launch new workflows
14
+ # This class is used to launch new workflows
15
15
  class BandManager
16
16
 
17
17
  @@log = Logger.new(STDOUT)
18
18
  @@log.level = Logger::DEBUG
19
19
 
20
20
 
21
- # Load workflow file
21
+ # Loads a workflow file
22
22
  def self.load(wfile)
23
23
  if !File.exists?(wfile)
24
24
  @@log.error "Workflow file "+wfile+" does not exist!"
@@ -143,7 +143,7 @@ class BandManager
143
143
  end
144
144
  end
145
145
 
146
- # Execute a workflow from an other one
146
+ # Execute a workflow from an other one (clone it)
147
147
  def self.launchclone(id)
148
148
  workflow = WorkFlow.get(id)
149
149
  newworkflow = WorkFlow.new(:uid => workflow.uid , :name => workflow.name, :description => workflow.description, :created_at => Time.now, :file => workflow.file, :terminals => workflow.terminals, :status => STATUS_NEW, :workdir => FlowConfig.getjobdir(), :vars => workflow.vars, :bucket => workflow.bucket)
@@ -2,6 +2,9 @@ require 'uuid'
2
2
  require 'data_mapper'
3
3
  require 'dm-migrations'
4
4
 
5
+ # Configuration library
6
+
7
+ # Determines the workflow and node status
5
8
  STATUS_SKIP = -2
6
9
  STATUS_FAKE = -1
7
10
  STATUS_NEW = 0
@@ -10,12 +13,14 @@ STATUS_OVER = 2
10
13
  STATUS_SUSPEND = 3 # SUSPEND mode for a job means a job is over and paused
11
14
  STATUS_ERROR = 4
12
15
 
16
+ # Determines if a job must be stored to S3, and its current status
13
17
  STORE_NO = -1
14
18
  STORE_DO = 0
15
19
  STORE_RUN = 1
16
20
  STORE_OVER = 2
17
21
  STORE_ERROR = 4
18
22
 
23
+ # List of message operations
19
24
  OP_NEW = "new"
20
25
  OP_START = "start"
21
26
  OP_FINISH = "finish"
@@ -30,10 +35,10 @@ OP_CLEAN = "clean" # Delete work dirs of workflow
30
35
  OP_DESTROY = "destroy" # Delete workflow and its work dirs
31
36
  OP_STORE = "store" # Store result to S3
32
37
 
33
- # Base config
38
+ # This class holds the base config
34
39
  class FlowConfig
35
40
  @@workdir='/tmp'
36
- @@s3host = 'genokvm4.genouest.org'
41
+ @@s3host = 'localhost'
37
42
  @@s3port = '8773'
38
43
  @@s3path = '/services/Walrus'
39
44
 
@@ -47,6 +52,7 @@ class FlowConfig
47
52
  return @@s3host
48
53
  end
49
54
 
55
+ # Sets S3 storage parameters
50
56
  def self.sets3(host,port= '8773',path='/services/Walrus')
51
57
  @@s3host = host
52
58
  @@s3port = port
@@ -65,14 +71,21 @@ class FlowConfig
65
71
  return @@workdir
66
72
  end
67
73
 
74
+ # defines upload directory for webband
75
+ # It must be accessible by the handlers
68
76
  def self.setuploaddir(directory)
69
77
  @@uploaddir = directory
70
78
  end
71
79
 
80
+ # Defines the work directory. It must be shared between job
81
+ # and workflow handlers.
72
82
  def self.setworkdir(directory)
73
83
  @@workdir=directory
74
84
  end
75
85
 
86
+
87
+ # Returns a work directory for a job. Directory
88
+ # is based on a unique identifier.
76
89
  def self.getjobdir(workflowdir = nil)
77
90
  uuid = UUID.new
78
91
  if workflowdir == nil
data/lib/manband/job.rb CHANGED
@@ -11,10 +11,7 @@ include Minion
11
11
  #DataMapper.setup(:default, 'sqlite:///home/osallou/Desktop/genflow/project.db')
12
12
  DataMapper.setup(:default, ENV['MYSQL_URL'])
13
13
 
14
- #TODO manage IF operation and resutl.
15
- # Exit code = 0 selects first node, other code select second node
16
- # Should inform with a finish "code: exitcode" and manage it in workflowhandler to RUN selected node and SKIP other node
17
-
14
+ # This class defines the link between the nodes in the workflow
18
15
  class JobLink
19
16
  include DataMapper::Resource
20
17
 
@@ -25,11 +22,14 @@ class JobLink
25
22
 
26
23
  end
27
24
 
25
+ # This class manages the job execution and its status on a job handler.
28
26
  class Job
29
27
  include DataMapper::Resource
30
28
 
31
29
  @@debug = false
32
30
 
31
+ # Sets debug mode
32
+ # mode: boolean
33
33
  def self.debug(mode)
34
34
  @@debug = mode
35
35
  end
@@ -50,7 +50,10 @@ class Job
50
50
  property :error, Text, :default => "[]" # JSON Array of error, per instance
51
51
  property :store, Integer, :default => STORE_NO # Storage status
52
52
 
53
- # Update job status and launch the command
53
+ # Update job status and launch the command locally
54
+ # Sends a finish message or an error message according to the job status.
55
+ # if storage is needed, job will send a finish AND a store message. Storage
56
+ # will occur in parallel of the rest of the workflow.
54
57
  def run(curhandler,instance=0)
55
58
  # Send run command, possibly multiple ones according to pattern
56
59
  # Command would send a message when over
@@ -81,7 +84,7 @@ class Job
81
84
  end
82
85
  end
83
86
 
84
- # Skip treatment, just answer
87
+ # Skip treatment, just answer, for debug
85
88
  def skip(curhandler)
86
89
  curjob = Job.get(@id)
87
90
  curjob.update(:handler => curhandler.to_s)
@@ -89,7 +92,10 @@ class Job
89
92
  sendmessage(OP_FINISH,jobmsg)
90
93
  end
91
94
 
92
- # Execute locally the command
95
+ # Execute locally the command, creating directories and setting environment
96
+ # variables to empty string for security.
97
+ # wordir: job working directory
98
+ # instance: instance number in the list of commands
93
99
  def runcommand(workdir,instance)
94
100
  initcmd = "AMQP_URL="" && MYSQL_URL="" && mkdir -p "+workdir+" && cd "+workdir+" && WORKDIR="+workdir+" && "
95
101
  curjob = Job.get(@id)
@@ -102,7 +108,8 @@ class Job
102
108
  end
103
109
 
104
110
  # Change instance counter
105
- # If workflow is in suspend status, suspend the job at the end of its treatment
111
+ # If workflow is in suspend status, suspend the job at
112
+ # the end of its treatment
106
113
  def finish
107
114
  if @status == STATUS_SKIP
108
115
  return
@@ -133,7 +140,7 @@ class Job
133
140
  end
134
141
  end
135
142
 
136
- # Compare sintance counter to max instances
143
+ # Compares intance counter to max instances to determine if job is over.
137
144
  def isover?
138
145
  if @status == STATUS_OVER
139
146
  return true
@@ -179,7 +186,9 @@ class Job
179
186
  end
180
187
  end
181
188
  end
182
-
189
+
190
+ # Sets a job in ERROR status.
191
+ # instance: job instance number in fault
183
192
  def error!(instance = 0)
184
193
  @status= STATUS_ERROR
185
194
  curjob = Job.get(@id)
@@ -258,7 +267,12 @@ class Job
258
267
  end
259
268
  end
260
269
  end
261
-
270
+
271
+ # Sends a message. According to the operation, message will be
272
+ # sent to master or node queues.
273
+ # operation: kind of message
274
+ # msg: message to send
275
+ # jobqueue: optional specific queue
262
276
  def sendmessage(operation,msg,jobqueue='')
263
277
  queue = "manband.master"
264
278
  if operation == OP_RUN || operation == OP_SKIP || operation == OP_DESTROY || operation == OP_CLEAN|| operation == OP_STORE
data/lib/manband/store.rb CHANGED
@@ -7,7 +7,7 @@ require 'fileutils'
7
7
  require 'manband/flowconfig.rb'
8
8
  require 'manband/user.rb'
9
9
 
10
-
10
+ # this class manage the storage of a job directory to S3
11
11
  class Storeband
12
12
 
13
13
  @@log = Logger.new(STDOUT)
@@ -29,6 +29,11 @@ class Storeband
29
29
  end
30
30
 
31
31
  # Store a job workdir to S3
32
+ #
33
+ # job: current job
34
+ # uid: user identifier
35
+ # bucket: bucket name to store the zip file
36
+ # @return false in case of failure
32
37
  def store(job,uid,bucket="manband")
33
38
  user = User.get(uid)
34
39
  if user == nil
@@ -50,16 +55,21 @@ class Storeband
50
55
  compress(job.workdir, FlowConfig.workdir+"/"+zipfile)
51
56
  # Send file
52
57
  sends3(FlowConfig.workdir+"/"+zipfile,bucket,user.s3_access,user.s3_secret)
53
- rescue
54
- @@log.error "An error occured during S3 operation: "+job.id.to_s
58
+ rescue Exception => e
59
+ @@log.error "An error occured during S3 operation: "+job.id.to_s+" "+e.message
55
60
  job.update(:store => STORE_ERROR)
56
61
  return false
57
62
  end
58
63
  job.update(:store => STORE_OVER)
59
64
  end
60
65
 
66
+ # Sends the file to the S3 bucket
67
+ # name: file name
68
+ # bucket: destination bucket name
69
+ # access: user credential access
70
+ # secret: user credential secret
61
71
  def sends3(name,bucket,access,secret)
62
- @@log.debug "connect to s3"
72
+ @@log.debug "connect to s3: "+FlowConfig.s3host+":"+FlowConfig.s3port.to_s+FlowConfig.s3path
63
73
  AWS::S3::Base.establish_connection!(
64
74
  :access_key_id => access,
65
75
  :secret_access_key => secret,
data/lib/manband/user.rb CHANGED
@@ -7,6 +7,7 @@ require 'manband/flowconfig.rb'
7
7
  #DataMapper.setup(:default, 'sqlite:///tmp/project.db')
8
8
  DataMapper.setup(:default, ENV['MYSQL_URL'])
9
9
 
10
+ # This class manages users in the database
10
11
  class User
11
12
  include DataMapper::Resource
12
13
 
@@ -17,6 +18,8 @@ class User
17
18
  property :s3_access, String # User id key
18
19
  property :s3_secret, String # Secret key
19
20
 
21
+ # Creates a default admin account if it does not exists.
22
+ # Default password is <b>admin</b>
20
23
  def self.init
21
24
  admin = User.get(@@admin)
22
25
  if admin == nil
@@ -26,6 +29,9 @@ class User
26
29
  end
27
30
  end
28
31
 
32
+ # Check passwords
33
+ # password: user password
34
+ # @return: true if authentication is correct
29
35
  def authenticate(password)
30
36
  shapwd = Digest::SHA1.hexdigest(password)
31
37
  if self.password == shapwd
@@ -12,7 +12,9 @@ require 'manband/job.rb'
12
12
  DataMapper.setup(:default, ENV['MYSQL_URL'])
13
13
 
14
14
 
15
-
15
+ # This class orchestrator the workflow status and the workflow file
16
+ # analysis. It determines if workflow is over, what are the next jobs
17
+ # to execute, ...
16
18
  class WorkFlow
17
19
  include DataMapper::Resource
18
20
 
@@ -34,6 +36,8 @@ class WorkFlow
34
36
  property :parent, Integer, :default => 0 # Parent workflow id, none by default
35
37
  property :instances, Integer, :default => 0 # Number of sub workflows, if any
36
38
 
39
+ # Checks if a workflow is over, e.g. we have reached all the
40
+ # terminal nodes (leafs).
37
41
  def isover?
38
42
  # decrement terminals
39
43
  @terminals = @terminals - 1
@@ -54,7 +58,8 @@ class WorkFlow
54
58
  return false
55
59
  end
56
60
 
57
- # Return an array of node names
61
+ # Get the list of jobs to be run after current node
62
+ # @return an array of node names
58
63
  def getnextjobs(curnode)
59
64
  #fworkflow = YAML.load_file(@file)
60
65
  fworkflow = BandManager.load(@file)
@@ -75,6 +80,9 @@ class WorkFlow
75
80
  return nexts
76
81
  end
77
82
 
83
+ # Parse workflow file and create jobs and links in the database
84
+ # curnode: current node
85
+ # id: id of the node as link originator
78
86
  def parse(curnode, id = nil)
79
87
  #fworkflow = YAML.load_file(@file)
80
88
  fworkflow = BandManager.load(@file)
@@ -140,7 +148,9 @@ class WorkFlow
140
148
  return newcommand
141
149
  end
142
150
 
143
- # Return command for the node in the workflow
151
+ # Return a list of commands for the node in the workflow
152
+ # There is one command per input file matching regular expresssions,
153
+ # if any. Default is 1 command.
144
154
  def getnodecommand(curnode)
145
155
  #fworkflow = YAML.load_file(@file)
146
156
  fworkflow = BandManager.load(@file)
@@ -247,6 +257,7 @@ class WorkFlow
247
257
  return commands
248
258
  end
249
259
 
260
+ # Clean a workflow directory
250
261
  def clean
251
262
  workflow = WorkFlow.get(@id)
252
263
  if workflow.workdir == nil
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: 15
4
+ hash: 11
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 4
8
+ - 5
9
9
  - 0
10
- version: 0.4.0
10
+ version: 0.5.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Olivier Sallou