osc_machete_rails 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG.md +76 -0
- data/LICENSE.txt +22 -0
- data/README.md +14 -0
- data/Rakefile +34 -0
- data/app/assets/javascripts/osc_machete_rails/application.js +13 -0
- data/app/assets/stylesheets/osc_machete_rails/application.css +13 -0
- data/app/controllers/osc_machete_rails/application_controller.rb +4 -0
- data/app/helpers/osc_machete_rails/application_helper.rb +4 -0
- data/app/views/layouts/osc_machete_rails/application.html.erb +14 -0
- data/config/routes.rb +2 -0
- data/lib/generators/active_record/job_model_generator.rb +13 -0
- data/lib/generators/active_record/orm_helpers.rb +6 -0
- data/lib/generators/active_record/templates/job_model.rb +17 -0
- data/lib/generators/active_record/templates/migration.rb +19 -0
- data/lib/generators/active_record/templates/module.rb +7 -0
- data/lib/generators/active_record/templates/workflow_model.rb +34 -0
- data/lib/generators/active_record/workflow_model_generator.rb +30 -0
- data/lib/generators/osc_machete_rails/USAGE +36 -0
- data/lib/generators/osc_machete_rails/erb/erb_generator.rb +5 -0
- data/lib/generators/osc_machete_rails/erb/templates/_form.html.erb +21 -0
- data/lib/generators/osc_machete_rails/erb/templates/edit.html.erb +5 -0
- data/lib/generators/osc_machete_rails/erb/templates/index.html.erb +41 -0
- data/lib/generators/osc_machete_rails/erb/templates/new.html.erb +5 -0
- data/lib/generators/osc_machete_rails/erb/templates/show.html.erb +13 -0
- data/lib/generators/osc_machete_rails/job_helpers.rb +10 -0
- data/lib/generators/osc_machete_rails/job_model/USAGE +28 -0
- data/lib/generators/osc_machete_rails/job_model/job_model_generator.rb +13 -0
- data/lib/generators/osc_machete_rails/resource_route/USAGE +3 -0
- data/lib/generators/osc_machete_rails/resource_route/resource_route_generator.rb +57 -0
- data/lib/generators/osc_machete_rails/scaffold_controller/USAGE +17 -0
- data/lib/generators/osc_machete_rails/scaffold_controller/scaffold_controller_generator.rb +24 -0
- data/lib/generators/osc_machete_rails/scaffold_controller/templates/controller.rb +120 -0
- data/lib/generators/osc_machete_rails/scaffold_generator.rb +35 -0
- data/lib/generators/osc_machete_rails/workflow_model/USAGE +38 -0
- data/lib/generators/osc_machete_rails/workflow_model/workflow_model_generator.rb +12 -0
- data/lib/generators/osc_machete_rails/workflow_template/USAGE +19 -0
- data/lib/generators/osc_machete_rails/workflow_template/templates/main.sh.mustache +18 -0
- data/lib/generators/osc_machete_rails/workflow_template/workflow_template_generator.rb +9 -0
- data/lib/osc_machete_rails/engine.rb +24 -0
- data/lib/osc_machete_rails/helper.rb +25 -0
- data/lib/osc_machete_rails/statusable.rb +199 -0
- data/lib/osc_machete_rails/version.rb +3 -0
- data/lib/osc_machete_rails/workflow.rb +249 -0
- data/lib/osc_machete_rails.rb +12 -0
- data/lib/tasks/osc_machete_rails_tasks.rake +4 -0
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/javascripts/simulations.js +2 -0
- data/test/dummy/app/assets/stylesheets/application.css +13 -0
- data/test/dummy/app/assets/stylesheets/simulations.css +4 -0
- data/test/dummy/app/controllers/application_controller.rb +5 -0
- data/test/dummy/app/controllers/simulations_controller.rb +103 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/helpers/simulations_helper.rb +2 -0
- data/test/dummy/app/models/simulation.rb +26 -0
- data/test/dummy/app/models/simulation_job.rb +15 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/app/views/simulations/_form.html.erb +15 -0
- data/test/dummy/app/views/simulations/edit.html.erb +5 -0
- data/test/dummy/app/views/simulations/index.html.erb +35 -0
- data/test/dummy/app/views/simulations/new.html.erb +5 -0
- data/test/dummy/app/views/simulations/show.html.erb +16 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/config/application.rb +23 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +29 -0
- data/test/dummy/config/environments/production.rb +80 -0
- data/test/dummy/config/environments/test.rb +36 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +12 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +11 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/migrate/20151230193910_create_simulations.rb +11 -0
- data/test/dummy/db/migrate/20151230193911_create_simulation_jobs.rb +15 -0
- data/test/dummy/db/schema.rb +38 -0
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/jobs/simulation/main.sh.mustache +17 -0
- data/test/dummy/log/development.log +0 -0
- data/test/dummy/log/test.log +31198 -0
- data/test/dummy/public/404.html +58 -0
- data/test/dummy/public/422.html +58 -0
- data/test/dummy/public/500.html +57 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/0ff4cb4a6c217771a1336b307c51cf4e +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/13fe41fee1fe35b49d145bcc06610705 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/2f5173deea6c795b8fdde723bb4b63af +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/357970feca3ac29060c1e3861e2c0953 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/57261b7c75c19be33229517e39e47528 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/9e1e594361ba2561e5f6011db99503bb +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/cffd775d018f68ce5dba1ee0d951a994 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/d771ace226fc8215a3572e0aa35bb0d6 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/dc292ec300d07016ebcc2de4806208c3 +0 -0
- data/test/dummy/tmp/cache/assets/test/sprockets/f7cbd26ba1d28d48de824f0e94586655 +0 -0
- data/test/integration/error_handling_test.rb +166 -0
- data/test/integration/statusable_update_status_test.rb +47 -0
- data/test/models/simulation_test.rb +4 -0
- data/test/osc_machete_rails_test.rb +7 -0
- data/test/test_helper.rb +19 -0
- data/test/unit/statusable_test.rb +124 -0
- metadata +320 -0
@@ -0,0 +1,249 @@
|
|
1
|
+
module OscMacheteRails
|
2
|
+
# A plugin to maintain a workflow for Jobs.
|
3
|
+
module Workflow
|
4
|
+
|
5
|
+
# Registers a workflow relationship and sets up a hook to additional builder methods.
|
6
|
+
#
|
7
|
+
# @param [Symbol] jobs_active_record_relation_symbol The Job Identifier
|
8
|
+
def has_machete_workflow_of(jobs_active_record_relation_symbol)
|
9
|
+
# yes, this is magic mimicked from http://guides.rubyonrails.org/plugins.html
|
10
|
+
# and http://yehudakatz.com/2009/11/12/better-ruby-idioms/
|
11
|
+
cattr_accessor :jobs_active_record_relation_symbol
|
12
|
+
self.jobs_active_record_relation_symbol = jobs_active_record_relation_symbol
|
13
|
+
|
14
|
+
# separate modules to group common methods for readability purposes
|
15
|
+
# both builder methods and status methods need the jobs relation so
|
16
|
+
# we include that first
|
17
|
+
self.send :include, OscMacheteRails::Workflow::JobsRelation
|
18
|
+
self.send :include, OscMacheteRails::Workflow::BuilderMethods
|
19
|
+
self.send :include, OscMacheteRails::Workflow::StatusMethods
|
20
|
+
end
|
21
|
+
|
22
|
+
# The module defining the active record relation of the jobs
|
23
|
+
module JobsRelation
|
24
|
+
# Assign the active record relation of this instance to the
|
25
|
+
def jobs_active_record_relation
|
26
|
+
self.send self.class.jobs_active_record_relation_symbol
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# depends on jobs_active_record_relation being defined
|
31
|
+
module BuilderMethods
|
32
|
+
# Methods run when this module is included
|
33
|
+
def self.included(obj)
|
34
|
+
# before we destroy ActiveRecord we stop all jobs and delete staging dir
|
35
|
+
# prepend: true tells this to run before any of the jobs are destroyed
|
36
|
+
# so we can stop them first and recover if there is a problem
|
37
|
+
if obj.respond_to?(:before_destroy)
|
38
|
+
obj.before_destroy prepend: true do |sim|
|
39
|
+
sim.stop ? sim.delete_staging : false
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def ood_dataroot
|
45
|
+
if defined? OodAppkit
|
46
|
+
OodAppkit.dataroot
|
47
|
+
elsif ENV['OOD_DATAROOT'] || ENV['RAILS_DATAROOT']
|
48
|
+
Pathname.new(ENV['OOD_DATAROOT'] || ENV['RAILS_DATAROOT'])
|
49
|
+
else
|
50
|
+
raise "no ood_dataroot specified"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
#
|
55
|
+
# @example Underscore a class
|
56
|
+
# FlowratePerformanceRun => flowrate_performance_run
|
57
|
+
#
|
58
|
+
# @return [String] The template name
|
59
|
+
def staging_template_name
|
60
|
+
self.class.name.underscore
|
61
|
+
end
|
62
|
+
|
63
|
+
# Returns the name of a staging directory that has been underscored and pluralized.
|
64
|
+
#
|
65
|
+
# @example
|
66
|
+
# Simulation => simulations
|
67
|
+
# @example
|
68
|
+
# FlowratePerformanceRun => flowrate_performance_runs
|
69
|
+
#
|
70
|
+
# @return [String] The staging template directory name
|
71
|
+
def staging_target_dir_name
|
72
|
+
staging_template_name.pluralize
|
73
|
+
end
|
74
|
+
|
75
|
+
# Gets the staging target directory path.
|
76
|
+
# Joins the AwesimRails.dataroot and the staging target directory name.
|
77
|
+
#
|
78
|
+
# @raise [Exception] "override staging_target_dir or include awesim_rails gem"
|
79
|
+
#
|
80
|
+
# @return [String] The staging target directory path.
|
81
|
+
def staging_target_dir(dataroot: ood_dataroot)
|
82
|
+
Pathname.new(dataroot).join(staging_target_dir_name)
|
83
|
+
end
|
84
|
+
|
85
|
+
# Gets the staging template directory path.
|
86
|
+
# Joins the { rails root }/jobs/{ staging_template_name } into a path.
|
87
|
+
#
|
88
|
+
# @return [String] The staging template directory path.
|
89
|
+
def staging_template_dir
|
90
|
+
Rails.root.join("jobs", staging_template_name)
|
91
|
+
end
|
92
|
+
|
93
|
+
# Creates a new staging target job directory on the system
|
94
|
+
# Copies the staging template directory to the staging target job directory
|
95
|
+
#
|
96
|
+
# @return [Pathname] The staged directory path.
|
97
|
+
def stage
|
98
|
+
staged_dir = OSC::Machete::JobDir.new(staging_target_dir).new_jobdir
|
99
|
+
FileUtils.mkdir_p staged_dir
|
100
|
+
FileUtils.cp_r staging_template_dir.to_s + "/.", staged_dir
|
101
|
+
|
102
|
+
staged_dir
|
103
|
+
end
|
104
|
+
|
105
|
+
# Deletes the staged directory if it exists
|
106
|
+
def delete_staging
|
107
|
+
FileUtils.rm_rf(staged_dir) if respond_to?(:staged_dir) && staged_dir
|
108
|
+
end
|
109
|
+
|
110
|
+
# Stops all jobs, updating each active job to status "failed"
|
111
|
+
# returns true if all jobs were stopped, false otherwise
|
112
|
+
def stop
|
113
|
+
jobs_active_record_relation.to_a.each(&:stop)
|
114
|
+
|
115
|
+
true
|
116
|
+
rescue PBS::Error => e
|
117
|
+
msg = "A PBS::Error occurred when trying to stop jobs for simulation #{id}: #{e.message}"
|
118
|
+
errors[:base] << msg
|
119
|
+
Rails.logger.error(msg)
|
120
|
+
|
121
|
+
false
|
122
|
+
end
|
123
|
+
|
124
|
+
# Creates a new location and renders the mustache files
|
125
|
+
#
|
126
|
+
# @param [String] staged_dir The staging target directory path.
|
127
|
+
# @param [Hash] template_view The template options to be rendered.
|
128
|
+
#
|
129
|
+
# @return [Location] The location of the staged and rendered template.
|
130
|
+
def render_mustache_files(staged_dir, template_view)
|
131
|
+
OSC::Machete::Location.new(staged_dir).render(template_view)
|
132
|
+
end
|
133
|
+
|
134
|
+
# Actions to perform after staging
|
135
|
+
#
|
136
|
+
# @param [String] staged_dir The staged directory path.
|
137
|
+
def after_stage(staged_dir)
|
138
|
+
end
|
139
|
+
|
140
|
+
# Unimplemented method for building jobs.
|
141
|
+
#
|
142
|
+
# @param [String] staged_dir The staged directory path.
|
143
|
+
# @param [Array, Nil] jobs An array of jobs to be built.
|
144
|
+
#
|
145
|
+
# @raise [NotImplementedError] The method is currently not implemented
|
146
|
+
def build_jobs(staged_dir, jobs = [])
|
147
|
+
raise NotImplementedError, "Objects including OSC::Machete::SimpleJob::Workflow must implement build_jobs"
|
148
|
+
end
|
149
|
+
|
150
|
+
# Call the #submit method on each job in a hash.
|
151
|
+
#
|
152
|
+
# @param [Hash] jobs A Hash of Job objects to be submitted.
|
153
|
+
def submit_jobs(jobs)
|
154
|
+
jobs.each(&:submit)
|
155
|
+
true
|
156
|
+
rescue OSC::Machete::Job::ScriptMissingError => e
|
157
|
+
stop_machete_jobs(jobs)
|
158
|
+
|
159
|
+
msg = "A OSC::Machete::Job::ScriptMissingError occurred when submitting jobs for simulation #{id}: #{e.message}"
|
160
|
+
errors[:base] << msg
|
161
|
+
Rails.logger.error(msg)
|
162
|
+
false
|
163
|
+
rescue PBS::Error => e
|
164
|
+
stop_machete_jobs(jobs)
|
165
|
+
|
166
|
+
msg = "A PBS::Error occurred when submitting jobs for simulation #{id}: #{e.message}"
|
167
|
+
errors[:base] << msg
|
168
|
+
Rails.logger.error(msg)
|
169
|
+
|
170
|
+
false
|
171
|
+
end
|
172
|
+
|
173
|
+
# given an array of OSC::Machete::Job objects, qdel them all and handle
|
174
|
+
# any errors. not to be confused with #stop which stops all actual jobs of
|
175
|
+
# the workflow
|
176
|
+
def stop_machete_jobs(jobs)
|
177
|
+
jobs.each do |job|
|
178
|
+
begin
|
179
|
+
job.delete
|
180
|
+
rescue PBS::Error
|
181
|
+
msg = "A PBS::Error occurred when deleting a job from the batch system with pbsid: #{job.pbsid} and message: #{e.message}"
|
182
|
+
errors[:base] << msg
|
183
|
+
Rails.logger.error(msg)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
# Saves a Hash of jobs to a staged directory
|
189
|
+
#
|
190
|
+
# @param [Hash] jobs A Hash of Job objects to be saved.
|
191
|
+
# @param [Location] staged_dir The staged directory as Location object.
|
192
|
+
def save_jobs(jobs, staged_dir)
|
193
|
+
self.staged_dir = staged_dir.to_s if self.respond_to?(:staged_dir=)
|
194
|
+
self.save if self.id.nil? || self.respond_to?(:staged_dir=)
|
195
|
+
|
196
|
+
jobs.each do |job|
|
197
|
+
self.jobs_active_record_relation.create(job: job)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
# Perform the submit actions.
|
202
|
+
#
|
203
|
+
# Sets the staged_dir
|
204
|
+
# Renders the mustache files.
|
205
|
+
# Calls after_stage.
|
206
|
+
# Calls build_jobs.
|
207
|
+
# Submits the jobs.
|
208
|
+
# Saves the jobs.
|
209
|
+
#
|
210
|
+
# @param [Hash, nil] template_view (self) The template options to be rendered.
|
211
|
+
def submit(template_view=self)
|
212
|
+
staged_dir = stage
|
213
|
+
render_mustache_files(staged_dir, template_view)
|
214
|
+
after_stage(staged_dir)
|
215
|
+
jobs = build_jobs(staged_dir)
|
216
|
+
if submit_jobs(jobs)
|
217
|
+
save_jobs(jobs, staged_dir)
|
218
|
+
else
|
219
|
+
FileUtils.rm_rf staged_dir.to_s
|
220
|
+
false
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
# depends on jobs_active_record_relation being defined
|
226
|
+
module StatusMethods
|
227
|
+
delegate :not_submitted?, :submitted?, :completed?, :passed?, :failed?, :active?, to: :status
|
228
|
+
|
229
|
+
# Reduce the jobs to a single OSC::Machete:Status value
|
230
|
+
#
|
231
|
+
# Assumes `jobs_active_record_relation` is a Statusable ActiveRecord
|
232
|
+
# model. Get array of status values (one for each job) and then add them
|
233
|
+
# together to get one value. OSC::Machete::Status#+ is overridden to
|
234
|
+
# return the highest precendent status value when adding two together.
|
235
|
+
#
|
236
|
+
# FIXME: it might be clearer in code to use `max` instead of `+` i.e.
|
237
|
+
# statuses.reduce(&:max) and rename OSC::Machete::Status#+.
|
238
|
+
#
|
239
|
+
# @return [OSC::Machete::Status] a single value representing the status
|
240
|
+
def status
|
241
|
+
statuses = jobs_active_record_relation.to_a.map(&:status)
|
242
|
+
statuses.empty? ? OSC::Machete::Status.not_submitted : statuses.reduce(&:+)
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
246
|
+
# extend Active Record with the has_workflow_of method
|
247
|
+
ActiveRecord::Base.extend OscMacheteRails::Workflow if defined? ActiveRecord::Base
|
248
|
+
end
|
249
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require "osc/machete"
|
2
|
+
require "osc_machete_rails/engine"
|
3
|
+
require "osc_machete_rails/statusable"
|
4
|
+
require "osc_machete_rails/workflow"
|
5
|
+
require "osc_machete_rails/helper"
|
6
|
+
|
7
|
+
module OscMacheteRails
|
8
|
+
mattr_accessor :update_status_of_all_active_jobs_on_each_request
|
9
|
+
|
10
|
+
# make OSC::Machete::SimpleJob an alias of this module for backwards compatibility
|
11
|
+
OSC::Machete::SimpleJob = self
|
12
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
== README
|
2
|
+
|
3
|
+
This README would normally document whatever steps are necessary to get the
|
4
|
+
application up and running.
|
5
|
+
|
6
|
+
Things you may want to cover:
|
7
|
+
|
8
|
+
* Ruby version
|
9
|
+
|
10
|
+
* System dependencies
|
11
|
+
|
12
|
+
* Configuration
|
13
|
+
|
14
|
+
* Database creation
|
15
|
+
|
16
|
+
* Database initialization
|
17
|
+
|
18
|
+
* How to run the test suite
|
19
|
+
|
20
|
+
* Services (job queues, cache servers, search engines, etc.)
|
21
|
+
|
22
|
+
* Deployment instructions
|
23
|
+
|
24
|
+
* ...
|
25
|
+
|
26
|
+
|
27
|
+
Please feel free to use a different markup language if you do not plan to run
|
28
|
+
<tt>rake doc:app</tt>.
|
data/test/dummy/Rakefile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
2
|
+
// listed below.
|
3
|
+
//
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
5
|
+
// or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
|
6
|
+
//
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
8
|
+
// compiled file.
|
9
|
+
//
|
10
|
+
// Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
|
11
|
+
// about supported directives.
|
12
|
+
//
|
13
|
+
//= require_tree .
|
@@ -0,0 +1,13 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the top of the
|
9
|
+
* compiled file, but it's generally better to create a new file per style scope.
|
10
|
+
*
|
11
|
+
*= require_self
|
12
|
+
*= require_tree .
|
13
|
+
*/
|
@@ -0,0 +1,103 @@
|
|
1
|
+
class SimulationsController < ApplicationController
|
2
|
+
before_action :set_simulation, only: [:show, :edit, :update, :destroy, :submit, :copy]
|
3
|
+
|
4
|
+
# GET /simulations
|
5
|
+
# GET /simulations.json
|
6
|
+
def index
|
7
|
+
@simulations = Simulation.preload(:simulation_jobs).all
|
8
|
+
end
|
9
|
+
|
10
|
+
# GET /simulations/1
|
11
|
+
# GET /simulations/1.json
|
12
|
+
def show
|
13
|
+
end
|
14
|
+
|
15
|
+
# GET /simulations/new
|
16
|
+
def new
|
17
|
+
@simulation = Simulation.new
|
18
|
+
end
|
19
|
+
|
20
|
+
# GET /simulations/1/edit
|
21
|
+
def edit
|
22
|
+
end
|
23
|
+
|
24
|
+
# POST /simulations
|
25
|
+
# POST /simulations.json
|
26
|
+
def create
|
27
|
+
@simulation = Simulation.new(simulation_params)
|
28
|
+
|
29
|
+
respond_to do |format|
|
30
|
+
if @simulation.save
|
31
|
+
format.html { redirect_to @simulation, notice: 'Simulation was successfully created.' }
|
32
|
+
format.json { render :show, status: :created, location: @simulation }
|
33
|
+
else
|
34
|
+
format.html { render :new }
|
35
|
+
format.json { render json: @simulation.errors, status: :unprocessable_entity }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# PATCH/PUT /simulations/1
|
41
|
+
# PATCH/PUT /simulations/1.json
|
42
|
+
def update
|
43
|
+
respond_to do |format|
|
44
|
+
if @simulation.update(simulation_params)
|
45
|
+
format.html { redirect_to @simulation, notice: 'Simulation was successfully updated.' }
|
46
|
+
format.json { render :show, status: :ok, location: @simulation }
|
47
|
+
else
|
48
|
+
format.html { render :edit }
|
49
|
+
format.json { render json: @simulation.errors, status: :unprocessable_entity }
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# DELETE /simulations/1
|
55
|
+
# DELETE /simulations/1.json
|
56
|
+
def destroy
|
57
|
+
respond_to do |format|
|
58
|
+
if @simulation.destroy
|
59
|
+
format.html { redirect_to simulations_url, notice: 'Simulation was successfully destroyed.' }
|
60
|
+
format.json { head :no_content }
|
61
|
+
else
|
62
|
+
format.html { render :show, status: 500, alert: 'A problem occurred when trying to destroy the simulation.' }
|
63
|
+
format.json { render json: @simulation.errors, status: 500 }
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
# PUT /simulations/1/submit
|
69
|
+
# PUT /simulations/1/submit.json
|
70
|
+
def submit
|
71
|
+
respond_to do |format|
|
72
|
+
|
73
|
+
if @simulation.submitted?
|
74
|
+
format.html { redirect_to simulations_url, alert: 'Simulation has already been submitted.' }
|
75
|
+
format.json { head :no_content }
|
76
|
+
elsif @simulation.submit
|
77
|
+
format.html { redirect_to simulations_url, notice: 'Simulation was successfully submitted.' }
|
78
|
+
format.json { head :no_content }
|
79
|
+
else
|
80
|
+
format.html { render :show, status: 500, alert: 'A problem occurred when trying to submit the simulation.' }
|
81
|
+
format.json { render json: @simulation.errors, status: 500 }
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# PUT /simulations/1/copy
|
87
|
+
def copy
|
88
|
+
@simulation = @simulation.copy
|
89
|
+
|
90
|
+
render template: "simulations/edit"
|
91
|
+
end
|
92
|
+
|
93
|
+
private
|
94
|
+
# Use callbacks to share common setup or constraints between actions.
|
95
|
+
def set_simulation
|
96
|
+
@simulation = Simulation.preload(:simulation_jobs).find(params[:id])
|
97
|
+
end
|
98
|
+
|
99
|
+
# Only allow a trusted parameter "white list" through.
|
100
|
+
def simulation_params
|
101
|
+
params.require(:simulation).permit!
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class Simulation < ActiveRecord::Base
|
2
|
+
has_many :simulation_jobs, dependent: :destroy
|
3
|
+
has_machete_workflow_of :simulation_jobs
|
4
|
+
|
5
|
+
|
6
|
+
# Name that defines the template/target dirs
|
7
|
+
def staging_template_name
|
8
|
+
"simulation"
|
9
|
+
end
|
10
|
+
|
11
|
+
# Define tasks to do after staging template directory typically copy over
|
12
|
+
# uploaded files here
|
13
|
+
# def after_stage(staged_dir)
|
14
|
+
# # CODE HERE
|
15
|
+
# end
|
16
|
+
|
17
|
+
# Build an array of Machete jobs that are then submitted to the batch server
|
18
|
+
def build_jobs(staged_dir, job_list = [])
|
19
|
+
job_list << OSC::Machete::Job.new(script: staged_dir.join("main.sh"))
|
20
|
+
end
|
21
|
+
|
22
|
+
# Make copy of workflow
|
23
|
+
def copy
|
24
|
+
self.dup
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class SimulationJob < ActiveRecord::Base
|
2
|
+
# Here we test the deprecated include method instead of the new
|
3
|
+
# OscMacheteRails::Statusable
|
4
|
+
# We will want both to work...
|
5
|
+
include OSC::Machete::SimpleJob::Statusable
|
6
|
+
|
7
|
+
belongs_to :simulation
|
8
|
+
|
9
|
+
before_destroy { |j| j.job.delete(rmdir: true) if j.job }
|
10
|
+
|
11
|
+
# Determine if the results are valid
|
12
|
+
# def results_valid?
|
13
|
+
# # CODE GOES HERE
|
14
|
+
# end
|
15
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>Dummy</title>
|
5
|
+
<%= stylesheet_link_tag "application", media: "all", "data-turbolinks-track" => true %>
|
6
|
+
<%= javascript_include_tag "application", "data-turbolinks-track" => true %>
|
7
|
+
<%= csrf_meta_tags %>
|
8
|
+
</head>
|
9
|
+
<body>
|
10
|
+
|
11
|
+
<%= yield %>
|
12
|
+
|
13
|
+
</body>
|
14
|
+
</html>
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<%# Uses rails_bootstrap_form gem. API at: https://github.com/bootstrap-ruby/rails-bootstrap-forms %>
|
2
|
+
<%= bootstrap_form_for(simulation) do |f| %>
|
3
|
+
<%= f.alert_message "Please fix the errors below." %>
|
4
|
+
|
5
|
+
<%= f.text_field :name %>
|
6
|
+
<%= f.text_field :pressure %>
|
7
|
+
|
8
|
+
<%= f.submit 'Save', class: 'btn btn-primary' %>
|
9
|
+
<%= f.button 'Reset', type: :reset, class: 'btn btn-default' %>
|
10
|
+
|
11
|
+
<hr>
|
12
|
+
|
13
|
+
<%= link_to 'Back', simulations_path, class: 'btn btn-default' %>
|
14
|
+
<%= link_to 'Show', simulation, class: 'btn btn-primary' unless simulation.new_record? %>
|
15
|
+
<% end %>
|
@@ -0,0 +1,35 @@
|
|
1
|
+
<div class="page-header">
|
2
|
+
<h2>Listing Simulations</h2>
|
3
|
+
</div>
|
4
|
+
|
5
|
+
<table class="table">
|
6
|
+
<thead>
|
7
|
+
<tr>
|
8
|
+
<th>#</th>
|
9
|
+
<th>Status</th>
|
10
|
+
<th>Name</th>
|
11
|
+
<th>Pressure</th>
|
12
|
+
<th colspan="4"></th>
|
13
|
+
</tr>
|
14
|
+
</thead>
|
15
|
+
|
16
|
+
<tbody>
|
17
|
+
<% @simulations.each do |simulation| %>
|
18
|
+
<tr>
|
19
|
+
<td><%= simulation.id %></td>
|
20
|
+
<td><%= status_label(simulation) %></td>
|
21
|
+
<td><%= simulation.name %></td>
|
22
|
+
<td><%= simulation.pressure %></td>
|
23
|
+
<td><%= link_to 'Submit', submit_simulation_path(simulation), method: :put, class: 'btn btn-success btn-sm' unless simulation.submitted? %></td>
|
24
|
+
<td><%= link_to 'Show', simulation, class: 'btn btn-primary btn-sm' %></td>
|
25
|
+
<td><%= link_to 'Edit', edit_simulation_path(simulation), class: 'btn btn-default btn-sm' unless simulation.submitted? %></td>
|
26
|
+
<td><%= link_to 'Copy', copy_simulation_path(simulation), method: :put, class: 'btn btn-default btn-sm' %></td>
|
27
|
+
<td><%= link_to 'Destroy', simulation, method: :delete, class: 'btn btn-danger btn-sm', data: { confirm: 'Are you sure?' } %></td>
|
28
|
+
</tr>
|
29
|
+
<% end %>
|
30
|
+
</tbody>
|
31
|
+
</table>
|
32
|
+
|
33
|
+
<br>
|
34
|
+
|
35
|
+
<%= link_to 'New Simulation', new_simulation_path %>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<div class="page-header">
|
2
|
+
<h2>Showing Simulation</h2>
|
3
|
+
</div>
|
4
|
+
|
5
|
+
<p>
|
6
|
+
<strong>Name:</strong>
|
7
|
+
<%= @simulation.name %>
|
8
|
+
</p>
|
9
|
+
|
10
|
+
<p>
|
11
|
+
<strong>Pressure:</strong>
|
12
|
+
<%= @simulation.pressure %>
|
13
|
+
</p>
|
14
|
+
|
15
|
+
<%= link_to 'Back', simulations_path, class: 'btn btn-default' %>
|
16
|
+
<%= link_to 'Edit', edit_simulation_path(@simulation), class: 'btn btn-default' %>
|
data/test/dummy/bin/rake
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require File.expand_path('../boot', __FILE__)
|
2
|
+
|
3
|
+
require 'rails/all'
|
4
|
+
|
5
|
+
Bundler.require(*Rails.groups)
|
6
|
+
require "osc_machete_rails"
|
7
|
+
|
8
|
+
module Dummy
|
9
|
+
class Application < Rails::Application
|
10
|
+
# Settings in config/environments/* take precedence over those specified here.
|
11
|
+
# Application configuration should go into files in config/initializers
|
12
|
+
# -- all .rb files in that directory are automatically loaded.
|
13
|
+
|
14
|
+
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
|
15
|
+
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
|
16
|
+
# config.time_zone = 'Central Time (US & Canada)'
|
17
|
+
|
18
|
+
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
|
19
|
+
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
|
20
|
+
# config.i18n.default_locale = :de
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|