torque_rm 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|