osc_machete_rails 1.2.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.
- 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
|
+
|