torque_rm 0.1.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/.document +5 -0
- data/.rspec +1 -0
- data/Gemfile +25 -0
- data/LICENSE.txt +20 -0
- data/README.html +230 -0
- data/README.md +231 -0
- data/Rakefile +52 -0
- data/VERSION +1 -0
- data/bin/torque_rm_rest +147 -0
- data/features/step_definitions/common_steps.rb +21 -0
- data/features/step_definitions/qsub_steps.rb +47 -0
- data/features/step_definitions/torque_rm_steps.rb +0 -0
- data/features/support/env.rb +13 -0
- data/features/torque_rm.feature +9 -0
- data/features/torque_rm/common.feature +22 -0
- data/features/torque_rm/qsub.feature +52 -0
- data/lib/torque_rm.rb +11 -0
- data/lib/torque_rm/common.rb +74 -0
- data/lib/torque_rm/qdel.rb +13 -0
- data/lib/torque_rm/qstat.rb +308 -0
- data/lib/torque_rm/qsub.rb +342 -0
- data/spec/spec_helper.rb +12 -0
- data/spec/torque_rm_spec.rb +7 -0
- data/torque_rm.gemspec +106 -0
- data/web/helpers/qstat.rb +19 -0
- data/web/views/qstat.haml +19 -0
- data/web/views/qstat_job.haml +14 -0
- metadata +271 -0
data/Rakefile
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
require 'rake'
|
13
|
+
|
14
|
+
require 'jeweler'
|
15
|
+
Jeweler::Tasks.new do |gem|
|
16
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
17
|
+
gem.name = "torque_rm"
|
18
|
+
gem.homepage = "http://github.com/helios/torque_rm"
|
19
|
+
gem.license = "MIT"
|
20
|
+
gem.summary = %Q{TORQUE Resource Manager wrapper for Ruby}
|
21
|
+
gem.description = %Q{TORQUE Resource Manager for Ruby. Submit, check and control your job directly from Ruby.}
|
22
|
+
gem.email = "ilpuccio.febo@gmail.com"
|
23
|
+
gem.authors = ["Raoul Jean Pierre Bonnal"]
|
24
|
+
# dependencies defined in Gemfile
|
25
|
+
end
|
26
|
+
Jeweler::RubygemsDotOrgTasks.new
|
27
|
+
|
28
|
+
require 'rspec/core'
|
29
|
+
require 'rspec/core/rake_task'
|
30
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
31
|
+
spec.pattern = FileList['spec/**/*_spec.rb']
|
32
|
+
end
|
33
|
+
|
34
|
+
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
35
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
36
|
+
spec.rcov = true
|
37
|
+
end
|
38
|
+
|
39
|
+
require 'cucumber/rake/task'
|
40
|
+
Cucumber::Rake::Task.new(:features)
|
41
|
+
|
42
|
+
task :default => :spec
|
43
|
+
|
44
|
+
require 'rdoc/task'
|
45
|
+
Rake::RDocTask.new do |rdoc|
|
46
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
47
|
+
|
48
|
+
rdoc.rdoc_dir = 'rdoc'
|
49
|
+
rdoc.title = "torque_rm #{version}"
|
50
|
+
rdoc.rdoc_files.include('README*')
|
51
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
52
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/bin/torque_rm_rest
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'haml'
|
4
|
+
require 'sinatra'
|
5
|
+
require 'torque_rm'
|
6
|
+
require 'sinatra/twitter-bootstrap'
|
7
|
+
require 'sinatra/json'
|
8
|
+
require 'sinatra/respond_with'
|
9
|
+
# require 'ap'
|
10
|
+
require "#{File.dirname(__FILE__)}/../web/helpers/qstat.rb"
|
11
|
+
|
12
|
+
|
13
|
+
set :run, true
|
14
|
+
enable :run
|
15
|
+
|
16
|
+
register Sinatra::Twitter::Bootstrap::Assets
|
17
|
+
|
18
|
+
set :root, File.join(File.dirname(__FILE__),"..","web")
|
19
|
+
|
20
|
+
|
21
|
+
helpers TORQUE::Qstat::Sinatra::Helpers
|
22
|
+
|
23
|
+
get '/' do
|
24
|
+
'Welcome to our gorgeous TORQUE/PBS web interface.'.to_json
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
get '/qstat', :provides => [:json, :html] do
|
29
|
+
jobs = TORQUE::Qstat.new.query
|
30
|
+
respond_to do |format|
|
31
|
+
format.json do
|
32
|
+
jobs.to_json
|
33
|
+
end
|
34
|
+
format.html { haml :qstat, :format => :html5, :locals => {:jobs => jobs}}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
get '/qstat/fields', :provides => [:json] do
|
39
|
+
|
40
|
+
json TORQUE::Qstat::FIELDS
|
41
|
+
end
|
42
|
+
|
43
|
+
get '/qstat/all/:field', :provides => [:json] do |field|
|
44
|
+
if TORQUE::Qstat::FIELDS.include? field
|
45
|
+
jobs = TORQUE::Qstat.new.query
|
46
|
+
json jobs.map{|job| job[field.to_sym]}
|
47
|
+
else
|
48
|
+
return status 404
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
### JOBS
|
54
|
+
|
55
|
+
get '/qstat/:job_id', :provides => [:json] do |job_id|
|
56
|
+
respond_to do |format|
|
57
|
+
format.json do
|
58
|
+
job = TORQUE::Qstat.new.query job_id: job_id
|
59
|
+
# q = TORQUE::Qstat.new
|
60
|
+
# p = TORQUE::Qstat::Parser.new
|
61
|
+
# t = TORQUE::Qstat::Trans.new
|
62
|
+
|
63
|
+
# s= "Job Id: 2770.deep.space.nine\n Job_Name = STDIN\n Job_Owner = johndoe@deep.space.nine\n resources_used.cput = 00:00:00\n resources_used.mem = 3148kb\n resources_used.vmem = 32528kb\n resources_used.walltime = 00:28:05\n job_state = R\n queue = bio\n server = deep.space.nine\n Checkpoint = u\n ctime = Mon Sep 2 18:43:10 2013\n Error_Path = deep.space.nine:/mnt/bio/ngs/data/home/johndoe/STDIN.e2770\n exec_host = scrapper/0\n exec_port = 15003\n Hold_Types = n\n Join_Path = n\n Keep_Files = n\n Mail_Points = a\n mtime = Mon Sep 2 18:43:11 2013\n Output_Path = deep.space.nine:/mnt/bio/ngs/data/home/johndoe/STDIN.o2770\n\t\n Priority = 0\n qtime = Mon Sep 2 18:43:10 2013\n Rerunable = True\n Resource_List.ncpus = 2\n Resource_List.nice = 0\n session_id = 16963\n Variable_List = PBS_O_QUEUE=bio,PBS_O_HOST=deep.space.nine,\n\tPBS_O_HOME=/mnt/bio/ngs/data/home/johndoe,PBS_O_LANG=it_IT.UTF-8,\n\tPBS_O_LOGNAME=johndoe,\n\tPBS_O_PATH=/mnt/bio/ngs/data/opt/fastx_toolkit/bin:/mnt/bio/ngs/data/\n\topt/bedtools/bin:/mnt/bio/ngs/data/opt/fuseki:/mnt/bio/ngs/data/opt/je\n\tna/bin:/mnt/bio/ngs/data/opt/CASAVA/bin:/mnt/bio/ngs/data/bin/cloaked-\n\thipster/utils:/mnt/bio/ngs/data/bin/cloaked-hipster/utils/ngs/pipeline\n\ts:/mnt/bio/ngs/data/bin/cloaked-hipster/utils/db:/mnt/bio/ngs/data/opt\n\t/trimmomatic:/mnt/bio/ngs/data/opt/PHYLOCSF/hmmer-3.0-linux-intel-x86_\n\t64/binaries:/mnt/bio/ngs/data/opt/PHYLOCSF/mlin-PhyloCSF-983a652/:/mnt\n\t/bio/ngs/data/bin/cloaked-hipster/ncrnapp/PBS_pipeline/:/mnt/bio/ngs/d\n\tata/opt/bowtie-0.12.9:/mnt/bio/ngs/data/opt/bowtie_current:/mnt/bio/ng\n\ts/data/opt/STAR_current:/mnt/bio/ngs/data/opt/RSeQC-2.3.5/RQC/usr/loca\n\tl/bin:/mnt/bio/ngs/data/opt/tophat_current:/mnt/bio/ngs/data/opt/PASA/\n\tscripts:/mnt/bio/ngs/data/opt/PASA/bin:/mnt/bio/ngs/data/opt/fasta/bin\n\t:/mnt/bio/ngs/data/opt/cufflinks:/mnt/bio/ngs/data/opt/samtools:/mnt/b\n\tio/ngs/data/opt/samtools/bcftools:/mnt/bio/ngs/data/opt/samtools/misc:\n\t/mnt/bio/ngs/data/opt/STAR_current/bin:/mnt/bio/ngs/data/opt/gmap/bin:\n\t/mnt/bio/ngs/data/opt/velvet:/mnt/bio/ngs/data/opt/velvet/contrib/colu\n\tmbus_scripts:/opt/blat:/mnt/bio/ngs/data/opt/oases/:/mnt/bio/ngs/data/\n\topt/oases/scripts:/mnt/bio/ngs/data/opt/trinityrnaseq:/mnt/bio/ngs/dat\n\ta/opt/trinityrnaseq/util:/usr/local/bin/:/mnt/bio/ngs/data/home/bonnal\n\traoul/.rbenv/bin:/mnt/bio/ngs/data/home/johndoe/.rbenv/shims:/mnt/\n\tbio/ngs/data/home/johndoe/.rbenv/bin:/usr/local/sbin:/usr/local/bi\n\tn:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games,\n\tPBS_O_MAIL=/var/mail/johndoe,PBS_O_SHELL=/bin/bash,\n\tPBS_SERVER=spark,PBS_O_WORKDIR=/mnt/bio/ngs/data/home/johndoe\n etime = Mon Sep 2 18:43:10 2013\n submit_args = -l ncpus=2 -l nice=0\n start_time = Mon Sep 2 18:43:11 2013\n start_count = 1\n fault_tolerant = False\n submit_host = deep.space.nine"
|
64
|
+
# job = job_id == "2770" ? q.mock(t.apply(p.parse(s.gsub(/\n\t/,'')))) : []
|
65
|
+
if job.empty?
|
66
|
+
return status 404
|
67
|
+
else
|
68
|
+
json :job => job.first
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
# if job.empty?
|
73
|
+
# "There is no job running with id #{job_id}"
|
74
|
+
# else
|
75
|
+
|
76
|
+
# haml :qstat_job, :format => :html5, :locals => {:job => job.first} #get the first and unique elment if the array is not empty
|
77
|
+
# end
|
78
|
+
end
|
79
|
+
|
80
|
+
get '/qstat/job/fields', :provides => [:json] do
|
81
|
+
json :job_fields => TORQUE::Qstat::Job.fields
|
82
|
+
end
|
83
|
+
|
84
|
+
get '/qstat/:job_id/:field', :provides => [:json] do |job_id, field|
|
85
|
+
|
86
|
+
|
87
|
+
# puts TORQUE::Qstat::Job.fields
|
88
|
+
if TORQUE::Qstat::Job.fields.include? field
|
89
|
+
# q = TORQUE::Qstat.new
|
90
|
+
# p = TORQUE::Qstat::Parser.new
|
91
|
+
# t = TORQUE::Qstat::Trans.new
|
92
|
+
# s= "Job Id: 2770.deep.space.nine\n Job_Name = STDIN\n Job_Owner = johndoe@deep.space.nine\n resources_used.cput = 00:00:00\n resources_used.mem = 3148kb\n resources_used.vmem = 32528kb\n resources_used.walltime = 00:28:05\n job_state = R\n queue = bio\n server = deep.space.nine\n Checkpoint = u\n ctime = Mon Sep 2 18:43:10 2013\n Error_Path = deep.space.nine:/mnt/bio/ngs/data/home/johndoe/STDIN.e2770\n exec_host = scrapper/0\n exec_port = 15003\n Hold_Types = n\n Join_Path = n\n Keep_Files = n\n Mail_Points = a\n mtime = Mon Sep 2 18:43:11 2013\n Output_Path = deep.space.nine:/mnt/bio/ngs/data/home/johndoe/STDIN.o2770\n\t\n Priority = 0\n qtime = Mon Sep 2 18:43:10 2013\n Rerunable = True\n Resource_List.ncpus = 2\n Resource_List.nice = 0\n session_id = 16963\n Variable_List = PBS_O_QUEUE=bio,PBS_O_HOST=deep.space.nine,\n\tPBS_O_HOME=/mnt/bio/ngs/data/home/johndoe,PBS_O_LANG=it_IT.UTF-8,\n\tPBS_O_LOGNAME=johndoe,\n\tPBS_O_PATH=/mnt/bio/ngs/data/opt/fastx_toolkit/bin:/mnt/bio/ngs/data/\n\topt/bedtools/bin:/mnt/bio/ngs/data/opt/fuseki:/mnt/bio/ngs/data/opt/je\n\tna/bin:/mnt/bio/ngs/data/opt/CASAVA/bin:/mnt/bio/ngs/data/bin/cloaked-\n\thipster/utils:/mnt/bio/ngs/data/bin/cloaked-hipster/utils/ngs/pipeline\n\ts:/mnt/bio/ngs/data/bin/cloaked-hipster/utils/db:/mnt/bio/ngs/data/opt\n\t/trimmomatic:/mnt/bio/ngs/data/opt/PHYLOCSF/hmmer-3.0-linux-intel-x86_\n\t64/binaries:/mnt/bio/ngs/data/opt/PHYLOCSF/mlin-PhyloCSF-983a652/:/mnt\n\t/bio/ngs/data/bin/cloaked-hipster/ncrnapp/PBS_pipeline/:/mnt/bio/ngs/d\n\tata/opt/bowtie-0.12.9:/mnt/bio/ngs/data/opt/bowtie_current:/mnt/bio/ng\n\ts/data/opt/STAR_current:/mnt/bio/ngs/data/opt/RSeQC-2.3.5/RQC/usr/loca\n\tl/bin:/mnt/bio/ngs/data/opt/tophat_current:/mnt/bio/ngs/data/opt/PASA/\n\tscripts:/mnt/bio/ngs/data/opt/PASA/bin:/mnt/bio/ngs/data/opt/fasta/bin\n\t:/mnt/bio/ngs/data/opt/cufflinks:/mnt/bio/ngs/data/opt/samtools:/mnt/b\n\tio/ngs/data/opt/samtools/bcftools:/mnt/bio/ngs/data/opt/samtools/misc:\n\t/mnt/bio/ngs/data/opt/STAR_current/bin:/mnt/bio/ngs/data/opt/gmap/bin:\n\t/mnt/bio/ngs/data/opt/velvet:/mnt/bio/ngs/data/opt/velvet/contrib/colu\n\tmbus_scripts:/opt/blat:/mnt/bio/ngs/data/opt/oases/:/mnt/bio/ngs/data/\n\topt/oases/scripts:/mnt/bio/ngs/data/opt/trinityrnaseq:/mnt/bio/ngs/dat\n\ta/opt/trinityrnaseq/util:/usr/local/bin/:/mnt/bio/ngs/data/home/bonnal\n\traoul/.rbenv/bin:/mnt/bio/ngs/data/home/johndoe/.rbenv/shims:/mnt/\n\tbio/ngs/data/home/johndoe/.rbenv/bin:/usr/local/sbin:/usr/local/bi\n\tn:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games,\n\tPBS_O_MAIL=/var/mail/johndoe,PBS_O_SHELL=/bin/bash,\n\tPBS_SERVER=spark,PBS_O_WORKDIR=/mnt/bio/ngs/data/home/johndoe\n etime = Mon Sep 2 18:43:10 2013\n submit_args = -l ncpus=2 -l nice=0\n start_time = Mon Sep 2 18:43:11 2013\n start_count = 1\n fault_tolerant = False\n submit_host = deep.space.nine"
|
93
|
+
job = TORQUE::Qstat.new.query job_id: job_id
|
94
|
+
# job = q.mock(t.apply(p.parse(query.gsub(/\n\t/,''))))
|
95
|
+
json field.to_sym => job.first[field.to_sym]
|
96
|
+
else
|
97
|
+
return status 404
|
98
|
+
end
|
99
|
+
# if job.empty?
|
100
|
+
# "There is no job running with id #{job_id}"
|
101
|
+
# else
|
102
|
+
|
103
|
+
# haml :qstat_job, :format => :html5, :locals => {:job => job.first} #get the first and unique elment if the array is not empty
|
104
|
+
# end
|
105
|
+
end
|
106
|
+
|
107
|
+
post '/qstat/:job_id/del', :provides => [:json] do |job_id|
|
108
|
+
job = TORQUE::Qstat.new.query job_id: job_id
|
109
|
+
if job.empty?
|
110
|
+
return status 404
|
111
|
+
else
|
112
|
+
json job.first.del
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
|
117
|
+
|
118
|
+
|
119
|
+
__END__
|
120
|
+
|
121
|
+
@@ layout
|
122
|
+
%html
|
123
|
+
%head
|
124
|
+
= bootstrap_assets
|
125
|
+
%body
|
126
|
+
- container :fluid do
|
127
|
+
.navbar
|
128
|
+
.navbar-inner
|
129
|
+
%a{class:"brand", href:"#"} TORQUE PBS
|
130
|
+
%ul{class:"nav"}
|
131
|
+
%li{class:"active"}
|
132
|
+
%a{href:"#"} Getting Started
|
133
|
+
%li
|
134
|
+
%a{href:"#"} Documentation
|
135
|
+
%li
|
136
|
+
%a{href:"#"} REST Api
|
137
|
+
%li
|
138
|
+
%a{href:"#"} About
|
139
|
+
%li
|
140
|
+
%a{href:"#"} Contact
|
141
|
+
|
142
|
+
|
143
|
+
- row do
|
144
|
+
- span8 do
|
145
|
+
= yield
|
146
|
+
- span4 :offset => 4 do
|
147
|
+
footer
|
@@ -0,0 +1,21 @@
|
|
1
|
+
Given(/^the server "(.*?)"$/) do |server_name|
|
2
|
+
TORQUE.server = server_name # express the regexp above with the code you wish you had
|
3
|
+
end
|
4
|
+
|
5
|
+
|
6
|
+
When(/^I request the server name without specify the hostname$/) do
|
7
|
+
@server = TORQUE.server
|
8
|
+
end
|
9
|
+
|
10
|
+
When(/^I request the server name$/) do
|
11
|
+
@server = TORQUE.server # express the regexp above with the code you wish you had
|
12
|
+
end
|
13
|
+
|
14
|
+
# Then(/^I should get a "(.*?)"$/) do |reply|
|
15
|
+
# @server.should be_an_instance_of(Rye::Box) # express the regexp above with the code you wish you had
|
16
|
+
# end
|
17
|
+
|
18
|
+
Then(/^I should get a "(.*?)" on "(.*?)"$/) do |ssh_manager_object, hostname|
|
19
|
+
@server.should be_an_instance_of(Object.const_get(ssh_manager_object)) # express the regexp above with the code you wish you had
|
20
|
+
@server.host.should == hostname
|
21
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
Before do
|
2
|
+
@qsub = TORQUE::Qsub.new
|
3
|
+
end
|
4
|
+
|
5
|
+
Given /^I want to be notified if the job begins$/ do
|
6
|
+
@qsub.m << "b"
|
7
|
+
end
|
8
|
+
|
9
|
+
Given /^I want to be notified if the job ends$/ do
|
10
|
+
@qsub.m << "e"
|
11
|
+
end
|
12
|
+
|
13
|
+
Given /^I want to be notified if the job aborts$/ do
|
14
|
+
@qsub.m << "a"
|
15
|
+
end
|
16
|
+
|
17
|
+
Given(/^the name "(.*?)"$/) do |job_name|
|
18
|
+
@qsub.name = job_name
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
Given(/^I want to use the "(.*?)" shell$/) do |job_shell|
|
23
|
+
@qsub.shell = job_shell
|
24
|
+
end
|
25
|
+
|
26
|
+
Given(/^I want to set the "(.*?)" to "(.*?)"$/) do |qsub_parameter, value|
|
27
|
+
@qsub.send "#{qsub_parameter}=", value # express the regexp above with the code you wish you had
|
28
|
+
end
|
29
|
+
|
30
|
+
Given(/^I want to use (\d+) cpus for a single node$/) do |n_cpus|
|
31
|
+
@qsub.cpus = n_cpus # express the regexp above with the code you wish you had
|
32
|
+
end
|
33
|
+
|
34
|
+
|
35
|
+
Given(/^the command "(.*?)"$/) do |job_command|
|
36
|
+
@qsub.script = job_command # express the regexp above with the code you wish you had
|
37
|
+
end
|
38
|
+
|
39
|
+
Then(/^I should get a configuration like$/) do |pbs_script|
|
40
|
+
@qsub.to_s.should == pbs_script # express the regexp above with the code you wish you had
|
41
|
+
end
|
42
|
+
|
43
|
+
Then(/^I should get the pbs script$/) do |pbs_script|
|
44
|
+
@qsub.to_s.should == pbs_script # express the regexp above with the code you wish you had
|
45
|
+
end
|
46
|
+
|
47
|
+
|
File without changes
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
begin
|
3
|
+
Bundler.setup(:default, :development)
|
4
|
+
rescue Bundler::BundlerError => e
|
5
|
+
$stderr.puts e.message
|
6
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
7
|
+
exit e.status_code
|
8
|
+
end
|
9
|
+
|
10
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__) + '/../../lib')
|
11
|
+
require 'torque_rm'
|
12
|
+
|
13
|
+
require 'rspec/expectations'
|
@@ -0,0 +1,9 @@
|
|
1
|
+
#Feature: something something
|
2
|
+
# In order to something something
|
3
|
+
# A user something something
|
4
|
+
# something something something
|
5
|
+
|
6
|
+
# Scenario: something something
|
7
|
+
# Given inspiration
|
8
|
+
# When I create a sweet new gem
|
9
|
+
# Then everyone should see how awesome I am
|
@@ -0,0 +1,22 @@
|
|
1
|
+
Feature: Configure torque_rm
|
2
|
+
In order to interact with the Torque server
|
3
|
+
As a user I must configure the system
|
4
|
+
|
5
|
+
Scenario: Torque is the localhost
|
6
|
+
When I request the server name without specify the hostname
|
7
|
+
Then I should get a "Rye::Box" on "localhost"
|
8
|
+
|
9
|
+
Scenario: Torque is a remote machine
|
10
|
+
Given the server "torque.remote.net"
|
11
|
+
When I request the server name
|
12
|
+
Then I should get a "Rye::Box" on "torque.remote.net"
|
13
|
+
|
14
|
+
Scenario: Torque binary are installed in the default location
|
15
|
+
Given the server "torque.remote.net"
|
16
|
+
When I try to get a qstat
|
17
|
+
Then the server tell me it can execute the command
|
18
|
+
|
19
|
+
Scenario: Torque binary are not installed in the default location
|
20
|
+
Given the server "torque.remote.net"
|
21
|
+
When I try to get a qstat
|
22
|
+
Then the server tell me it can not execute the command
|
@@ -0,0 +1,52 @@
|
|
1
|
+
Feature: Submit jobs
|
2
|
+
In order to submit a job
|
3
|
+
A user should be able to create a batch job
|
4
|
+
prividing multiple PBS options
|
5
|
+
attaching a shell script
|
6
|
+
|
7
|
+
Scenario: Configure a batch job
|
8
|
+
Given the name "MyBatch"
|
9
|
+
And I want to use the "/bin/bash" shell
|
10
|
+
And I want to be notified if the job begins
|
11
|
+
And I want to be notified if the job ends
|
12
|
+
And I want to be notified if the job aborts
|
13
|
+
Then I should get a configuration like
|
14
|
+
"""
|
15
|
+
#PBS -m bea
|
16
|
+
#PBS -N MyBatch
|
17
|
+
#PBS -S /bin/bash
|
18
|
+
|
19
|
+
"""
|
20
|
+
|
21
|
+
Scenario: Prepare a script to get the hostname from a node
|
22
|
+
Given the name "MyBatch"
|
23
|
+
And I want to use the "/bin/bash" shell
|
24
|
+
And I want to be notified if the job begins
|
25
|
+
And I want to be notified if the job ends
|
26
|
+
And I want to be notified if the job aborts
|
27
|
+
And I want to set the "working_directory" to "/home/submitter/test_cluster"
|
28
|
+
And I want to set the "stdout" to "/home/submitter/test_cluster"
|
29
|
+
And I want to set the "stderr" to "/home/submitter/test_cluster"
|
30
|
+
And I want to use 4 cpus for a single node
|
31
|
+
And the command "echo `hostname`"
|
32
|
+
Then I should get the pbs script
|
33
|
+
"""
|
34
|
+
#PBS -d /home/submitter/test_cluster
|
35
|
+
#PBS -e /home/submitter/test_cluster
|
36
|
+
#PBS -l nodes=1:ppn=4
|
37
|
+
#PBS -m bea
|
38
|
+
#PBS -N MyBatch
|
39
|
+
#PBS -o /home/submitter/test_cluster
|
40
|
+
#PBS -S /bin/bash
|
41
|
+
echo `hostname`
|
42
|
+
"""
|
43
|
+
|
44
|
+
|
45
|
+
Scenario: Get the hostname from a node
|
46
|
+
Given the name "MyBatch"
|
47
|
+
And I want to use the "/bin/bash" shell
|
48
|
+
And I want to be notified if the job begins
|
49
|
+
And I want to be notified if the job ends
|
50
|
+
And I want to be notified if the job aborts
|
51
|
+
And the command "echo `hostname`"
|
52
|
+
Then I should get the name of the execution node
|
data/lib/torque_rm.rb
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'parslet'
|
2
|
+
require 'yaml'
|
3
|
+
require 'colorize'
|
4
|
+
require 'terminal-table'
|
5
|
+
require 'torque_rm/common'
|
6
|
+
require 'torque_rm/qsub'
|
7
|
+
require 'torque_rm/qstat'
|
8
|
+
require 'torque_rm/qdel'
|
9
|
+
|
10
|
+
# Try to laod the default configuration
|
11
|
+
TORQUE.load_config
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'rye'
|
2
|
+
require 'etc'
|
3
|
+
|
4
|
+
module TORQUE
|
5
|
+
@@username = Etc.getlogin
|
6
|
+
@@qcommands_path = '/usr/bin'
|
7
|
+
@@master = Rye::Box.new("localhost")
|
8
|
+
@@conf = {}
|
9
|
+
def self.server=(hostname)
|
10
|
+
if hostname
|
11
|
+
@@master = Rye::Box.new(hostname, @@conf)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.server
|
16
|
+
@@master
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.username=(username)
|
20
|
+
@@username = username
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
def self.qcommands_path=(path)
|
25
|
+
@@qcommands_path = path
|
26
|
+
%w(qstat qsub qdel).each do |command|
|
27
|
+
Rye::Cmd.remove_command command if Rye::Cmd.can? command
|
28
|
+
Rye::Cmd.add_command command, File.join(qcommands_path, command)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.qcommands_path
|
33
|
+
@@qcommands_path
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.path
|
37
|
+
self.qcommands_path
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.read_config(file)
|
41
|
+
if File.exists?(file)
|
42
|
+
conf = YAML::load( File.open( file) )
|
43
|
+
@@conf = conf.dup
|
44
|
+
@@conf.delete(:hostname)
|
45
|
+
@@conf.delete(:path)
|
46
|
+
self.qcommands_path = conf[:path]
|
47
|
+
self.username = conf[:user] unless conf[:user].nil?
|
48
|
+
# self.port = conf[:port] unless conf[:port].nil?
|
49
|
+
# self.password = conf[:password] unless conf[:password].nil?
|
50
|
+
self.server = conf[:hostname]
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# Load configuration, default from file in user home with name .toruqe_rm.yaml
|
55
|
+
def self.load_config(file=nil)
|
56
|
+
self.read_config File.expand_path(file.nil? ? "~/.torque_rm.yaml" : file)
|
57
|
+
self
|
58
|
+
end
|
59
|
+
|
60
|
+
# Save configuration, default in user home with name .toruqe_rm.yaml
|
61
|
+
def self.save_config(file=nil)
|
62
|
+
File.write File.expand_path(file.nil? ? "~/.torque_rm.yaml" : file), {hostname: @@master.host, path: @@qcommands_path, user: @@username}.to_yaml
|
63
|
+
end
|
64
|
+
|
65
|
+
# Get the host name/ip of the local/remote server user as submitter/interface to PBS
|
66
|
+
def self.host
|
67
|
+
self.server.host
|
68
|
+
end
|
69
|
+
|
70
|
+
# Get the hostname, this may require an internet connection and fully qualified name
|
71
|
+
def self.hostname
|
72
|
+
self.server.hostname
|
73
|
+
end
|
74
|
+
end
|