ruby-cute 0.0.1 → 0.0.2
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/.gitignore +6 -0
- data/.yardopts +2 -0
- data/Gemfile +6 -0
- data/README.md +137 -6
- data/Rakefile +48 -0
- data/bin/cute +22 -0
- data/debian/changelog +5 -0
- data/debian/compat +1 -0
- data/debian/control +15 -0
- data/debian/copyright +33 -0
- data/debian/ruby-cute.docs +2 -0
- data/debian/ruby-tests.rb +2 -0
- data/debian/rules +19 -0
- data/debian/source/format +1 -0
- data/debian/watch +2 -0
- data/examples/distem-bootstrap +516 -0
- data/examples/g5k_exp1.rb +41 -0
- data/examples/g5k_exp_virt.rb +129 -0
- data/lib/cute.rb +7 -2
- data/lib/cute/bash.rb +337 -0
- data/lib/cute/configparser.rb +404 -0
- data/lib/cute/execute.rb +272 -0
- data/lib/cute/extensions.rb +38 -0
- data/lib/cute/g5k_api.rb +1190 -0
- data/lib/cute/net-ssh.rb +144 -0
- data/lib/cute/net.rb +29 -0
- data/lib/cute/synchronization.rb +89 -0
- data/lib/cute/taktuk.rb +554 -0
- data/lib/cute/version.rb +3 -0
- data/ruby-cute.gemspec +32 -0
- data/spec/extensions_spec.rb +17 -0
- data/spec/g5k_api_spec.rb +192 -0
- data/spec/spec_helper.rb +66 -0
- data/spec/taktuk_spec.rb +129 -0
- data/test/test_bash.rb +71 -0
- metadata +204 -47
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 134cb9d25b87efcffb16969273bc4485b79a6086
|
4
|
+
data.tar.gz: b2454f6b7878e1e7339bcfd412dd52e431e17f08
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 5e73cc26463f9eafe501ba6b01f9439dcb7cb6874ee35c8ea3692797dcb75f1a73fbef9adce8df8d2ea410267a6be34a3852f968d84db9ae19b5cf3c58a444f5
|
7
|
+
data.tar.gz: d5d5bf2fa5c5d0d99944bbe010fa6456356571487be772b4f9246213a5ade9d21f60ae29b3b4813091b94529c9ef1b5c44de948512c15fac2a7bdf086339ba79
|
data/.gitignore
ADDED
data/.yardopts
ADDED
data/Gemfile
ADDED
data/README.md
CHANGED
@@ -1,5 +1,4 @@
|
|
1
|
-
Ruby-Cute
|
2
|
-
=========
|
1
|
+
# Ruby-Cute
|
3
2
|
|
4
3
|
Ruby-Cute is a set of *Commonly Used Tools for Experiments*, or *Critically
|
5
4
|
Useful Tools for Experiments*, depending on who you ask. It is a library
|
@@ -7,14 +6,146 @@ aggregating various Ruby snippets useful in the context of (but not limited to)
|
|
7
6
|
development of experiment software on distributed systems testbeds such as
|
8
7
|
Grid'5000.
|
9
8
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
From sources:
|
12
|
+
|
13
|
+
```bash
|
14
|
+
$ git clone https://github.com/ruby-cute/ruby-cute
|
15
|
+
$ cd ruby-cute
|
16
|
+
$ gem build ruby-cute.gemspec
|
17
|
+
$ gem install ruby-cute-*.gem
|
18
|
+
```
|
19
|
+
|
20
|
+
In Grid'5000 the installation procedure goes as follows:
|
21
|
+
|
22
|
+
```bash
|
23
|
+
$ gem install --user-install ruby-cute
|
24
|
+
```
|
25
|
+
|
26
|
+
Then, type the following for having ruby cute in your path (this is only necessary if you want to use interactive mode).
|
27
|
+
|
28
|
+
```bash
|
29
|
+
$ export PATH=$PATH:$(ruby -e 'puts "#{Gem.user_dir}/bin"')
|
30
|
+
```
|
31
|
+
|
32
|
+
## Overview
|
33
|
+
|
34
|
+
Ruby-Cute is structured in different modules that allows you to:
|
35
|
+
|
36
|
+
- communicate with Grid'5000 through the G5K Module. For more details please refer to
|
37
|
+
[G5K Module](http://www.rubydoc.info/github/ruby-cute/ruby-cute/master/Cute/G5K/API).
|
38
|
+
|
39
|
+
- execute commands in several remote machines in parallel. Two modules are available for that:
|
40
|
+
|
41
|
+
- [Net::SSH::Multi](http://www.rubydoc.info/github/ruby-cute/ruby-cute/master/Net/SSH/Multi) that uses the SSH protocol.
|
42
|
+
- [TakTuk](http://www.rubydoc.info/github/ruby-cute/ruby-cute/master/Cute/TakTuk)
|
43
|
+
which is a wrapper of [taktuk](http://taktuk.gforge.inria.fr) parallel command executor.
|
44
|
+
|
45
|
+
An example of use of Ruby-Cute in a real use case is available in
|
46
|
+
[Virtualization on Grid'5000](http://www.rubydoc.info/github/ruby-cute/ruby-cute/master/file/examples/g5k_exp_virt.rb)
|
47
|
+
|
48
|
+
## Using pry -- an interactive ruby shell
|
49
|
+
|
50
|
+
Sometimes it may be useful to work in interactive mode. For this we can use an interactive ruby shell such as irb that is shipped by default with
|
51
|
+
Ruby, however, we highly recommend to use [pry](http://pryrepl.org/), it features syntax highlighting, method auto completion and command shell integration.
|
52
|
+
For installing pry type the following:
|
53
|
+
|
54
|
+
```bash
|
55
|
+
$ gem install pry
|
56
|
+
```
|
57
|
+
|
58
|
+
or, for installing in the user home directory:
|
59
|
+
|
60
|
+
```bash
|
61
|
+
$ gem install --user-install pry
|
62
|
+
```
|
63
|
+
|
64
|
+
When Ruby-Cute is installed, it provides a wrapper for an interactive shell that will
|
65
|
+
automatically load the necessary libraries. The following will get a *pry* prompt (if installed).
|
66
|
+
|
67
|
+
```bash
|
68
|
+
$ cute
|
69
|
+
[1] pry(main)>
|
70
|
+
```
|
71
|
+
|
72
|
+
The variable *$g5k* is available which can be used to access the Grid'5000 API through the
|
73
|
+
[G5K Module](http://www.rubydoc.info/github/ruby-cute/ruby-cute/master/Cute/G5K/API). For example,
|
74
|
+
let's request the name of the sites available in Grid'5000.
|
75
|
+
|
76
|
+
```bash
|
77
|
+
[2] pry(main)> $g5k.site_uids()
|
78
|
+
=> ["grenoble", "lille", "luxembourg", "lyon", "nancy", "nantes", "reims", "rennes", "sophia", "toulouse"]
|
79
|
+
```
|
80
|
+
|
81
|
+
We can get the status of nodes in a given site by using:
|
82
|
+
|
83
|
+
```bash
|
84
|
+
[8] pry(main)> $g5k.nodes_status("lyon")
|
85
|
+
=> {"taurus-2.lyon.grid5000.fr"=>"besteffort", "taurus-16.lyon.grid5000.fr"=>"besteffort", "taurus-15.lyon.grid5000.fr"=>"besteffort", ...}
|
86
|
+
```
|
87
|
+
|
88
|
+
Within this shell you have preloaded [G5K Module](http://www.rubydoc.info/github/ruby-cute/ruby-cute/master/Cute/G5K/API),
|
89
|
+
[Taktuk](http://www.rubydoc.info/github/ruby-cute/ruby-cute/master/Cute/TakTuk) and
|
90
|
+
[Net::SSH::Multi](http://www.rubydoc.info/github/ruby-cute/ruby-cute/master/Net/SSH/Multi),
|
91
|
+
you can go directly to their respective documentation to know how to take advantage of them.
|
92
|
+
|
93
|
+
### Experiment example
|
94
|
+
|
95
|
+
The following example shows how to use the [G5K Module](http://www.rubydoc.info/github/ruby-cute/ruby-cute/master/Cute/G5K/API) in an experiment.
|
96
|
+
This example implements the experiment described in
|
97
|
+
[MPI on Grid5000](https://www.grid5000.fr/mediawiki/index.php/Run_MPI_On_Grid%275000#Setting_up_and_starting_Open_MPI_to_use_high_performance_interconnect).
|
98
|
+
|
99
|
+
```ruby
|
100
|
+
require 'cute'
|
101
|
+
require 'net/scp'
|
102
|
+
|
103
|
+
g5k = Cute::G5K::API.new()
|
104
|
+
# We reuse a job if there is one available.
|
105
|
+
G5K_SITE = "nancy" # the chosen site has to have Infiniband 20G (e.g nancy, grenoble)
|
106
|
+
if g5k.get_my_jobs(G5K_SITE).empty?
|
107
|
+
job = g5k.reserve(:site => G5K_SITE, :resources => "{ib20g='YES'}/nodes=2/core=1",:walltime => '00:30:00', :keys => "~/my_ssh_jobkey" )
|
108
|
+
else
|
109
|
+
job = g5k.get_my_jobs(G5K_SITE).first
|
110
|
+
end
|
111
|
+
|
112
|
+
nodes = job["assigned_nodes"]
|
113
|
+
|
114
|
+
grid5000_opt = {:user => "oar", :keys => ["~/my_ssh_jobkey"], :port => 6667 }
|
115
|
+
|
116
|
+
machine_file = Tempfile.open('machine_file')
|
117
|
+
|
118
|
+
nodes.each{ |node| machine_file.puts node }
|
119
|
+
|
120
|
+
machine_file.close
|
121
|
+
|
122
|
+
netpipe ="http://pkgs.fedoraproject.org/repo/pkgs/NetPIPE/NetPIPE-3.7.1.tar.gz/5f720541387be065afdefc81d438b712/NetPIPE-3.7.1.tar.gz"
|
123
|
+
|
124
|
+
# We use the first node reserved.
|
125
|
+
Net::SCP.start(nodes.first, "oar", grid5000_opt) do |scp|
|
126
|
+
scp.upload! machine_file.path, "/tmp/machine_file"
|
127
|
+
end
|
128
|
+
|
129
|
+
Net::SSH.start(nodes.first, "oar", grid5000_opt) do |ssh|
|
130
|
+
ssh.exec!("mkdir -p netpipe_exp")
|
131
|
+
ssh.exec!("export http_proxy=\"http://proxy:3128\"; wget -O ~/netpipe_exp/NetPIPE.tar.gz #{netpipe}")
|
132
|
+
ssh.exec!("cd netpipe_exp && tar -zvxf NetPIPE.tar.gz")
|
133
|
+
ssh.exec!("cd netpipe_exp/NetPIPE-3.7.1 && make mpi")
|
134
|
+
ssh.exec("mpirun --mca plm_rsh_agent \"oarsh\" -machinefile /tmp/machine_file ~/netpipe_exp/NetPIPE-3.7.1/NPmpi")
|
135
|
+
end
|
136
|
+
|
137
|
+
g5k.release(job) # Frees resources.
|
138
|
+
```
|
139
|
+
|
140
|
+
## Contact information
|
141
|
+
|
142
|
+
Ruby-Cute is maintained by the Algorille team at LORIA/Inria Nancy - Grand Est, and specifically by:
|
143
|
+
|
14
144
|
* Sébastien Badia <sebastien.badia@inria.fr>
|
15
145
|
* Tomasz Buchert <tomasz.buchert@inria.fr>
|
16
146
|
* Emmanuel Jeanvoine <emmanuel.jeanvoine@inria.fr>
|
17
147
|
* Lucas Nussbaum <lucas.nussbaum@loria.fr>
|
18
148
|
* Luc Sarzyniec <luc.sarzyniec@inria.fr>
|
149
|
+
* Cristian Ruiz <cristian.ruiz@inria.fr>
|
19
150
|
|
20
151
|
Questions/comments should be directed to Lucas Nussbaum and Emmanuel Jeanvoine.
|
data/Rakefile
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
require 'rake/packagetask'
|
2
|
+
require 'rubygems/package_task'
|
3
|
+
require 'yard'
|
4
|
+
require 'rake'
|
5
|
+
require 'rspec/core/rake_task'
|
6
|
+
require 'bundler/gem_tasks'
|
7
|
+
|
8
|
+
Bundler::GemHelper.install_tasks
|
9
|
+
|
10
|
+
GEM='ruby-cute'
|
11
|
+
|
12
|
+
def get_version
|
13
|
+
Cute::VERSION
|
14
|
+
end # def:: get_version
|
15
|
+
|
16
|
+
desc "Run spec tests"
|
17
|
+
|
18
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
19
|
+
spec.ruby_opts = "-I lib:spec -w"
|
20
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
21
|
+
end
|
22
|
+
|
23
|
+
desc "Generate source tgz package"
|
24
|
+
Rake::PackageTask::new("ruby-cute",get_version) do |p|
|
25
|
+
p.need_tar_gz = true
|
26
|
+
p.package_files.include('lib/**/*')
|
27
|
+
p.package_files.include('ext/**/*')
|
28
|
+
p.package_files.include('bin/**/*')
|
29
|
+
p.package_files.include('test/**/*')
|
30
|
+
p.package_files.include('Rakefile', 'COPYING','README', 'README.md')
|
31
|
+
end
|
32
|
+
|
33
|
+
desc "Builds a Debian package"
|
34
|
+
task :debian do
|
35
|
+
sh 'dpkg-buildpackage -us -uc'
|
36
|
+
end
|
37
|
+
|
38
|
+
desc "Builds a git snapshot package"
|
39
|
+
task :snapshot do
|
40
|
+
sh 'cp debian/changelog debian/changelog.git'
|
41
|
+
date = `date --iso=seconds |sed 's/+.*//' |sed 's/[-T:]//g'`.chomp
|
42
|
+
sh "sed -i '1 s/)/+git#{date})/' debian/changelog"
|
43
|
+
sh 'dpkg-buildpackage -us -uc'
|
44
|
+
sh 'mv debian/changelog.git debian/changelog'
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
task :default => :spec
|
data/bin/cute
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/usr/bin/ruby -w
|
2
|
+
require 'tmpdir'
|
3
|
+
|
4
|
+
ROOT_DIR= File.expand_path('../..',__FILE__)
|
5
|
+
BIN_DIR= File.join(ROOT_DIR,"bin")
|
6
|
+
|
7
|
+
if `which pry` && $?.success? then
|
8
|
+
PRY_BIN="pry"
|
9
|
+
elsif File.exist?("~/.gem/bin/pry")
|
10
|
+
PRY_BIN="~/.gem/bin/pry"
|
11
|
+
else
|
12
|
+
# We use the default ruby interactive shell
|
13
|
+
PRY_BIN="irb"
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
cute_init_file = File.open("#{Dir.mktmpdir}/cute_init.rb",'w+')
|
18
|
+
cute_init_file.puts "require 'cute'\n$g5k = Cute::G5K::API.new()"
|
19
|
+
cute_init_file.close
|
20
|
+
|
21
|
+
|
22
|
+
exec("#{PRY_BIN} -r #{cute_init_file.path}")
|
data/debian/changelog
ADDED
data/debian/compat
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
8
|
data/debian/control
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
Source: ruby-cute
|
2
|
+
Section: ruby
|
3
|
+
Priority: optional
|
4
|
+
Maintainer: Lucas Nussbaum <lucas@debian.org>
|
5
|
+
Build-Depends: debhelper (>= 8~), gem2deb (>= 0.3.0~), rake, yard, ruby-redcloth, bc
|
6
|
+
Standards-Version: 3.9.3
|
7
|
+
Homepage: http://ruby-cute.gforge.inria.fr/
|
8
|
+
XS-Ruby-Versions: all
|
9
|
+
|
10
|
+
Package: ruby-cute
|
11
|
+
Architecture: all
|
12
|
+
XB-Ruby-Versions: ${ruby:Versions}
|
13
|
+
Depends: ${shlibs:Depends}, ${misc:Depends}, ruby | ruby-interpreter
|
14
|
+
Description: Critically Useful Tools for Experiments
|
15
|
+
|
data/debian/copyright
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
2
|
+
Upstream-Name: ruby-cute
|
3
|
+
Source: FIXME <http://example.com/>
|
4
|
+
|
5
|
+
Files: *
|
6
|
+
Copyright: <years> <put author's name and email here>
|
7
|
+
<years> <likewise for another author>
|
8
|
+
License: GPL-2+ (FIXME)
|
9
|
+
This program is free software; you can redistribute it
|
10
|
+
and/or modify it under the terms of the GNU General Public
|
11
|
+
License as published by the Free Software Foundation; either
|
12
|
+
version 2 of the License, or (at your option) any later
|
13
|
+
version.
|
14
|
+
.
|
15
|
+
This program is distributed in the hope that it will be
|
16
|
+
useful, but WITHOUT ANY WARRANTY; without even the implied
|
17
|
+
warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
18
|
+
PURPOSE. See the GNU General Public License for more
|
19
|
+
details.
|
20
|
+
.
|
21
|
+
You should have received a copy of the GNU General Public
|
22
|
+
License along with this package; if not, write to the Free
|
23
|
+
Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
24
|
+
Boston, MA 02110-1301 USA
|
25
|
+
.
|
26
|
+
On Debian systems, the full text of the GNU General Public
|
27
|
+
License version 2 can be found in the file
|
28
|
+
`/usr/share/common-licenses/GPL-2'.
|
29
|
+
|
30
|
+
Files: debian/*
|
31
|
+
Copyright: 2013 Lucas Nussbaum <lucas@debian.org>
|
32
|
+
License:
|
33
|
+
[LICENSE TEXT]
|
data/debian/rules
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
#!/usr/bin/make -f
|
2
|
+
#export DH_VERBOSE=1
|
3
|
+
#
|
4
|
+
# Uncomment to ignore all test failures (but the tests will run anyway)
|
5
|
+
#export DH_RUBY_IGNORE_TESTS=all
|
6
|
+
#
|
7
|
+
# Uncomment to ignore some test failures (but the tests will run anyway).
|
8
|
+
# Valid values:
|
9
|
+
#export DH_RUBY_IGNORE_TESTS=ruby1.8 ruby1.9.1 require-rubygems
|
10
|
+
#
|
11
|
+
# If you need to specify the .gemspec (eg there is more than one)
|
12
|
+
#export DH_RUBY_GEMSPEC=gem.gemspec
|
13
|
+
|
14
|
+
%:
|
15
|
+
dh $@ --buildsystem=ruby --with ruby
|
16
|
+
|
17
|
+
override_dh_auto_build:
|
18
|
+
dh_auto_build
|
19
|
+
yard
|
@@ -0,0 +1 @@
|
|
1
|
+
3.0 (native)
|
data/debian/watch
ADDED
@@ -0,0 +1,516 @@
|
|
1
|
+
#!/usr/bin/ruby
|
2
|
+
#
|
3
|
+
# distem-bootstrap is a script to configure a set of nodes as distem nodes
|
4
|
+
#
|
5
|
+
####
|
6
|
+
# distem-bootstrap is Copyright (C) 2011 Luc Sarzyniec <luc.sarzyniec@inria.fr>
|
7
|
+
# Secondary contact: Lucas Nussbaum <lucas.nussbaum@loria.fr>
|
8
|
+
#
|
9
|
+
# This program is free software: you can redistribute it and/or modify
|
10
|
+
# it under the terms of the GNU General Public License as published by
|
11
|
+
# the Free Software Foundation, either version 3 of the License, or
|
12
|
+
# (at your option) any later version.
|
13
|
+
#
|
14
|
+
# This program is distributed in the hope that it will be useful,
|
15
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
16
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
17
|
+
# GNU General Public License for more details.
|
18
|
+
#
|
19
|
+
# You should have received a copy of the GNU General Public License
|
20
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
21
|
+
######
|
22
|
+
require 'rubygems'
|
23
|
+
require 'socket'
|
24
|
+
require 'tmpdir'
|
25
|
+
require 'net/scp'
|
26
|
+
require 'etc'
|
27
|
+
require 'yaml'
|
28
|
+
require 'optparse'
|
29
|
+
require 'timeout'
|
30
|
+
require 'logger'
|
31
|
+
require 'cute'
|
32
|
+
|
33
|
+
logger = Logger.new(STDOUT)
|
34
|
+
|
35
|
+
def g5k?
|
36
|
+
`hostname --fqdn`.chomp =~ /grid5000\.fr$/
|
37
|
+
end
|
38
|
+
|
39
|
+
PKG_NAME = 'distem'
|
40
|
+
DEB_REPOSITORY = 'http://distem.gforge.inria.fr/deb'
|
41
|
+
HTTP_PROXY = 'proxy:3128'
|
42
|
+
SSH_KEYS_PATH = File.join(ENV['HOME'],'.ssh')
|
43
|
+
PATH_DISTEMD_LOGS = '/var/log/distem'
|
44
|
+
TMP_DIR = '/tmp/distem'
|
45
|
+
VAR_DISTEM_NODES = 'DISTEM_NODES'
|
46
|
+
VAR_DISTEM_COORD = 'DISTEM_COORDINATOR'
|
47
|
+
STATS_PORT = 12345
|
48
|
+
if g5k?
|
49
|
+
GIT_REPOSITORY = "https://gforge.inria.fr/git/distem/distem.git"
|
50
|
+
GERRIT_REPOSITORY = "http://gerrit.nancy.grid5000.fr:8080/gerrit/p/distem"
|
51
|
+
STATS_SERV = "carol.nancy.grid5000.fr"
|
52
|
+
else
|
53
|
+
GIT_REPOSITORY = "https://gforge.inria.fr/git/distem/distem.git"
|
54
|
+
GERRIT_REPOSITORY = "https://intranet.grid5000.fr/gerrit/p/distem"
|
55
|
+
STATS_SERV = ""
|
56
|
+
end
|
57
|
+
|
58
|
+
ULIMIT_OPEN_FILES = 65535 # to be removed
|
59
|
+
|
60
|
+
pkg_utils=[
|
61
|
+
'htop'
|
62
|
+
]
|
63
|
+
|
64
|
+
pkg_tmp_dependencies=[]
|
65
|
+
|
66
|
+
pkg_build=[
|
67
|
+
'git',
|
68
|
+
'rake'
|
69
|
+
]
|
70
|
+
|
71
|
+
pkg_build_gem=[
|
72
|
+
#'rake-compiler'
|
73
|
+
]
|
74
|
+
|
75
|
+
options = {}
|
76
|
+
@options = options
|
77
|
+
|
78
|
+
|
79
|
+
$startt = Time::now
|
80
|
+
|
81
|
+
options[:init_pnodes] = true
|
82
|
+
options[:coordinator] = nil
|
83
|
+
options[:node_list] = nil
|
84
|
+
options[:debpackages] = []
|
85
|
+
options[:gempackages] = []
|
86
|
+
options[:git] = nil
|
87
|
+
options[:gerrit] = nil
|
88
|
+
options[:ssh_key] = nil
|
89
|
+
options[:debug] = false
|
90
|
+
options[:distem_version] = nil
|
91
|
+
options[:debug_distem] = false
|
92
|
+
options[:stats] = true
|
93
|
+
options[:git_url] = GIT_REPOSITORY
|
94
|
+
options[:verbose] = false
|
95
|
+
options[:max_vifaces] = nil
|
96
|
+
options[:cow] = nil
|
97
|
+
options[:ci] = nil
|
98
|
+
options[:network_mode] = 'classical'
|
99
|
+
options[:network_interface] = nil
|
100
|
+
options[:num_nodes] = 2
|
101
|
+
options[:walltime] = "2:00:00"
|
102
|
+
|
103
|
+
args = ARGV.dup
|
104
|
+
|
105
|
+
optparse = OptionParser.new do |opts|
|
106
|
+
opts.banner = "Usage: #{$0} [options] [<script_to_execute>]"
|
107
|
+
opts.separator ""
|
108
|
+
opts.separator "distem-bootstrap automatically sets up a distem environment."
|
109
|
+
opts.separator "When run without options, it will create a distem environment with the latest"
|
110
|
+
opts.separator "released version of distem. It will perform a reservation as follows:"
|
111
|
+
opts.separator "slash_22=1+/nodes=2,walltime=02:00 --name=distem --type=deploy"
|
112
|
+
opts.separator "and deploy the environment: \"wheezy-x64-nfs\""
|
113
|
+
opts.separator ""
|
114
|
+
opts.separator "Options:"
|
115
|
+
|
116
|
+
opts.on( '--nodes <number of nodes>', Integer,'Number of nodes to reserve on Grid5000') do |n|
|
117
|
+
options[:num_nodes] = n.to_i
|
118
|
+
end
|
119
|
+
opts.on( '-t', '--time <walltime>', 'Walltime for the reservation on Grid5000') do |n|
|
120
|
+
options[:walltime] = n
|
121
|
+
end
|
122
|
+
opts.on( '-c', '--coordinator <coordinator_address>', 'Address of the coordinator (default: first node)' ) do |c|
|
123
|
+
options[:coordinator] = c || nil
|
124
|
+
end
|
125
|
+
opts.on( '-x', '--no-init-pnodes', 'Do not initialize all pnodes' ) do |c|
|
126
|
+
options[:init_pnodes] = false
|
127
|
+
end
|
128
|
+
opts.on( '--max-vifaces <nb>', 'Set the maximum number of vifaces on a physical node (used only without --no-init-pnodes)' ) do |n|
|
129
|
+
options[:max_vifaces] = n
|
130
|
+
end
|
131
|
+
opts.on( '-d', '--debug', 'Debug mode (display commands executed on nodes)' ) do
|
132
|
+
options[:debug] = true
|
133
|
+
end
|
134
|
+
opts.on( '-D', '--distem-debug', 'Show distem output when executing distem commands (script, node init)' ) do
|
135
|
+
options[:debug_distem] = true
|
136
|
+
end
|
137
|
+
opts.on( '-k', '--ssh-key [<ssh_key_file>]', 'Path of the ssh private key to use' ) do |k|
|
138
|
+
options[:ssh_key] = k
|
139
|
+
end
|
140
|
+
opts.on( '-p', '--debpackages <package1>,<package2>,<...>', Array, 'Additional debian packages to install on coordinator' ) do |p|
|
141
|
+
options[:debpackages] = p
|
142
|
+
end
|
143
|
+
opts.on( '-r', '--gempackages <package1>,<package2>,<...>', Array, 'Additional gem packages to install on coordinator' ) do |p|
|
144
|
+
options[:gempackages] = p
|
145
|
+
end
|
146
|
+
opts.on( '--distem-version <distem_version>', 'Version of distem to install (default: latest)' ) do |v|
|
147
|
+
options[:distem_version] = v
|
148
|
+
end
|
149
|
+
opts.on( '-g', '--git [<git_hash|git_tag>]', "Install a git snapshot of distem (default: master). Additional packages are installed on the coordinator to rebuild the Debian package" ) do |n|
|
150
|
+
options[:git] = n || :git_last
|
151
|
+
end
|
152
|
+
opts.on( '-U', '--git-url <git_repository>', "Overwrite the default distem git repository" ) do |repo|
|
153
|
+
options[:git_url] = repo
|
154
|
+
end
|
155
|
+
opts.on( '-G', '--gerrit <gerrit_ref>', "Checkout a gerrit ref (e.g refs/changes/94/94/1) and rebuild a Debian package" ) do |n|
|
156
|
+
options[:gerrit] = n
|
157
|
+
end
|
158
|
+
opts.on( '-S', '--stealth-mode', 'Do not report usage statistics (Grid\'5000 only)' ) do |c|
|
159
|
+
options[:stats] = false
|
160
|
+
end
|
161
|
+
opts.on( '--btrfs-format <tmp_device>', 'Format the device with btrfs support to allow COW on Vnodes (experimental)' ) do |d|
|
162
|
+
options[:cow] = d
|
163
|
+
end
|
164
|
+
opts.on( '--ci <path>', 'Path to the distem source directory (used only for CI purpose)' ) do |path|
|
165
|
+
options[:ci] = path
|
166
|
+
end
|
167
|
+
opts.on( '-n', '--network-mode <mode>', 'Define the network mode (classical or vxlan)') do |mode|
|
168
|
+
case mode
|
169
|
+
when 'classical'
|
170
|
+
when 'vxlan'
|
171
|
+
else
|
172
|
+
puts 'Invalid network mode'
|
173
|
+
exit 1
|
174
|
+
end
|
175
|
+
options[:network_mode] = mode
|
176
|
+
end
|
177
|
+
opts.on( '-i', '--network-interface <iface>', 'Define the root network interface for inter-pnode communication (use only with vxlan network mode)') do |iface|
|
178
|
+
options[:network_interface] = iface
|
179
|
+
end
|
180
|
+
opts.on( '--verbose', 'Activate the verbose mode on Distem servers' ) do
|
181
|
+
options[:verbose] = true
|
182
|
+
end
|
183
|
+
opts.on( '-h', '--help', 'Display this screen' ) do
|
184
|
+
puts opts
|
185
|
+
exit
|
186
|
+
end
|
187
|
+
opts.separator ""
|
188
|
+
opts.separator "When executing a script, the file containing the list of nodes is available in the #{VAR_DISTEM_NODES}"
|
189
|
+
opts.separator "environment variable, while the address of the coordinator is in #{VAR_DISTEM_COORD}."
|
190
|
+
opts.separator ""
|
191
|
+
opts.separator "Examples:"
|
192
|
+
opts.separator "# run script.rb against the latest git snapshot of distem"
|
193
|
+
opts.separator "distem-bootstrap --nodes=4 --no-init-pnodes --git -- script.rb"
|
194
|
+
opts.separator "# setup distem, installing additional packages"
|
195
|
+
opts.separator "distem-bootstrap --nodes=10 -t \"04:00:00\" -p htop -r restfully -f nodes"
|
196
|
+
|
197
|
+
end
|
198
|
+
|
199
|
+
begin
|
200
|
+
optparse.parse!
|
201
|
+
rescue OptionParser::InvalidOption => e
|
202
|
+
logger.error(e.to_s)
|
203
|
+
end
|
204
|
+
|
205
|
+
logger.level = Logger::INFO
|
206
|
+
logger.level = Logger::DEBUG if options[:debug]
|
207
|
+
|
208
|
+
g5k = Cute::G5K::API.new()
|
209
|
+
g5k.logger = logger
|
210
|
+
## performing reservation with ruby-cute
|
211
|
+
|
212
|
+
reserv_param = {:site => g5k.site, :nodes => options[:num_nodes], :name => 'distem',
|
213
|
+
:walltime => options[:walltime], :env =>'wheezy-x64-nfs', :subnets => [22,1]}
|
214
|
+
|
215
|
+
reserv_param[:keys] = options[:ssh_key] unless options[:ssh_key].nil?
|
216
|
+
|
217
|
+
|
218
|
+
# we verify if we have already submit a job
|
219
|
+
old_jobs = g5k.get_my_jobs(g5k.site).select{ |j| j["name"] == "distem"}
|
220
|
+
|
221
|
+
job = old_jobs.empty? ? g5k.reserve(reserv_param) : old_jobs.first
|
222
|
+
|
223
|
+
nodelist = job.resources["cores"].uniq
|
224
|
+
## wait for the deploy
|
225
|
+
|
226
|
+
g5k.wait_for_deploy(job)
|
227
|
+
|
228
|
+
allnodes = nodelist.dup
|
229
|
+
|
230
|
+
# Generating ssh keys"
|
231
|
+
|
232
|
+
key_dir = Dir.mktmpdir("keys")
|
233
|
+
system "ssh-keygen -P \'\' -f #{key_dir}/keys"
|
234
|
+
logger.info "Keys generated in #{key_dir}"
|
235
|
+
|
236
|
+
nodelist.each do |node|
|
237
|
+
|
238
|
+
Net::SCP.start(node, "root") do |scp|
|
239
|
+
logger.debug "Transfering key to #{node}"
|
240
|
+
scp.upload! "#{key_dir}/keys.pub", "/root/.ssh/id_rsa.pub"
|
241
|
+
scp.upload! "#{key_dir}/keys", "/root/.ssh/id_rsa"
|
242
|
+
end
|
243
|
+
|
244
|
+
end
|
245
|
+
|
246
|
+
# Deletating keys
|
247
|
+
FileUtils.rm_rf(key_dir)
|
248
|
+
|
249
|
+
if options[:coordinator]
|
250
|
+
coordinator = options[:coordinator]
|
251
|
+
else
|
252
|
+
coordinator = nodelist[0]
|
253
|
+
end
|
254
|
+
|
255
|
+
if nodelist.include?(coordinator)
|
256
|
+
nodelist.delete(coordinator)
|
257
|
+
else
|
258
|
+
tmp = nodelist.select { |node| node =~ /^#{coordinator}/ }
|
259
|
+
if tmp.empty?
|
260
|
+
logger.warn("Coordinator not present in <nodes_file>")
|
261
|
+
else
|
262
|
+
logger.warn("Coordinator '#{coordinator}' assumed to be '#{tmp[0]}' (which is present in <nodes_file>)")
|
263
|
+
coordinator = tmp[0]
|
264
|
+
end
|
265
|
+
end
|
266
|
+
|
267
|
+
|
268
|
+
logger.info("Establishing SSH connections to all nodes")
|
269
|
+
|
270
|
+
Net::SSH::Multi.logger = logger # setting the default logger.
|
271
|
+
|
272
|
+
Net::SSH::Multi.start do |session|
|
273
|
+
nodeobjlist = {}
|
274
|
+
begin
|
275
|
+
session.group :coord do
|
276
|
+
nodeobjlist[coordinator] = session.use("root@#{coordinator}")
|
277
|
+
end
|
278
|
+
#test connection
|
279
|
+
session.with(:coord).exec! "hostname"
|
280
|
+
rescue SocketError
|
281
|
+
logger.error("can't connect to #{coordinator}")
|
282
|
+
end
|
283
|
+
|
284
|
+
begin
|
285
|
+
session.group :nodes do
|
286
|
+
nodelist.each{ |node| session.use("root@#{node}")}
|
287
|
+
end
|
288
|
+
#test connection
|
289
|
+
session.with(:nodes).exec! "hostname"
|
290
|
+
rescue SocketError
|
291
|
+
logger.error("can't connect to #{node}")
|
292
|
+
end
|
293
|
+
|
294
|
+
|
295
|
+
# Check nfs paths ## comment: this is probably unnecessary given that now we are controlling the deployment with rubycute.
|
296
|
+
tmp = session.exec! "ls -a #{ENV['HOME']}"
|
297
|
+
nopath = allnodes - tmp.keys
|
298
|
+
nopath.each do |node|
|
299
|
+
logger.warn("NFS do not seems to be mounted on #{node} (check that you have deployed with NFS env")
|
300
|
+
end
|
301
|
+
|
302
|
+
# generating ssh password less connection
|
303
|
+
session.exec! "cat .ssh/id_rsa.pub >> .ssh/authorized_keys"
|
304
|
+
|
305
|
+
if options[:cow]
|
306
|
+
logger.infor("Format #{options[:cow]} to Btrfs")
|
307
|
+
session.exec! "(umount /tmp || true) && mkfs.btrfs #{options[:cow]} && mount -o compress=lzo #{options[:cow]} /tmp && chmod 1777 /tmp"
|
308
|
+
end
|
309
|
+
|
310
|
+
#setting up ulimit-open_files, to be removed
|
311
|
+
rule="root hard nofile"
|
312
|
+
session.exec! "grep -q '#{rule}' /etc/security/limits.conf; true || echo '#{rule} #{ULIMIT_OPEN_FILES}' >> /etc/security/limits.conf"
|
313
|
+
rule="root soft nofile"
|
314
|
+
session.exec! "grep -q '#{rule}' /etc/security/limits.conf; true || echo '#{rule} #{ULIMIT_OPEN_FILES}' >> /etc/security/limits.conf"
|
315
|
+
|
316
|
+
# setup Debian repo
|
317
|
+
session.exec! "grep -q '#{DEB_REPOSITORY}' /etc/apt/sources.list || echo 'deb #{DEB_REPOSITORY} ./\ndeb-src #{DEB_REPOSITORY} ./' >> /etc/apt/sources.list"
|
318
|
+
|
319
|
+
logger.info "Updating debian packages list"
|
320
|
+
session.exec! "apt-get update -q"
|
321
|
+
|
322
|
+
if options[:git] or options[:gerrit]
|
323
|
+
logger.info("Installing debian build packages on #{coordinator}")
|
324
|
+
session.with(:coord).exec! "apt-get build-dep -y --force-yes distem"
|
325
|
+
session.with(:coord).exec! "DEBIAN_FRONTEND=noninteractive apt-get install -q -y #{pkg_build * ' '}" unless pkg_build.empty?
|
326
|
+
unless pkg_build_gem.empty?
|
327
|
+
logger.info("Installing gems build packages on #{coordinator}")
|
328
|
+
session.with(:corrd).exec! "export http_proxy=#{HTTP_PROXY}; gem install #{pkg_build_gem * ' '}"
|
329
|
+
end
|
330
|
+
|
331
|
+
gitdir = "#{TMP_DIR}/git"
|
332
|
+
session.exec! "mkdir -p #{TMP_DIR}"
|
333
|
+
session.with(:coord).exec! "rm -Rf #{gitdir}"
|
334
|
+
|
335
|
+
if options[:git]
|
336
|
+
if options[:ci] != nil
|
337
|
+
logger.info("Syncing source repository on #{coordinator} with the current Gerrit repository")
|
338
|
+
system("rsync -rlut --delete #{options[:ci]}/* root@#{options[:coordinator]}:#{gitdir}")
|
339
|
+
else
|
340
|
+
logger.info("Retrieving '#{options[:git_url]}' repository on #{coordinator}")
|
341
|
+
if g5k?
|
342
|
+
session.with(:coord).exec! "https_proxy=#{HTTP_PROXY} GIT_SSL_NO_VERIFY=1 git clone #{options[:git_url]} #{gitdir}"
|
343
|
+
else
|
344
|
+
session.with(:coord).exec! "GIT_SSL_NO_VERIFY=1 git clone #{options[:git_url]} #{gitdir}"
|
345
|
+
end
|
346
|
+
unless options[:git] == :git_last
|
347
|
+
logger.info("Setting up git repository ref:#{options[:git]} on #{coordinator}")
|
348
|
+
session.with(:corrd).exec! "git --git-dir=#{gitdir}/.git reset --hard #{options[:git]}"
|
349
|
+
end
|
350
|
+
end
|
351
|
+
else # gerrit
|
352
|
+
logger.info("Setting up git repository from gerrit ref:#{options[:gerrit]} on #{coordinator}")
|
353
|
+
session.with(:coord).exec! "git clone #{GERRIT_REPOSITORY} #{gitdir}"
|
354
|
+
session.with(:coord).exec! "cd #{gitdir} && git fetch #{GERRIT_REPOSITORY} #{options[:gerrit]} && git checkout FETCH_HEAD"
|
355
|
+
end
|
356
|
+
logger.info("Building debian package of distem on #{coordinator}")
|
357
|
+
session.with(:coord).exec! "rm -f #{TMP_DIR}/*.deb #{TMP_DIR}/*.changes #{TMP_DIR}/*.dsc #{TMP_DIR}/*.tar.gz"
|
358
|
+
session.with(:coord).exec! "cd #{gitdir}; rake snapshot"
|
359
|
+
|
360
|
+
debarchivefile = session.with(:coord).exec! "find #{TMP_DIR} -maxdepth 1 -name *.deb"
|
361
|
+
|
362
|
+
session.with(:coord).exec! "Copying generated debian package #{File.basename(debarchivefile)}"
|
363
|
+
|
364
|
+
#exec(session,"cp #{debarchivefile} #{TMP_DIR}",:coord,true)
|
365
|
+
nodelist.each {|node| session.with(:coord).exec! "scp -o StrictHostKeyChecking=no #{debarchivefile} root@#{node}:#{TMP_DIR}"}
|
366
|
+
logger.info("Installing generated debian package #{File.basename(debarchivefile)}")
|
367
|
+
depends = session.with(:coord).exec! "dpkg -I #{debarchivefile} | grep 'Depends:'"
|
368
|
+
|
369
|
+
depends = depends.split("|").last.gsub!(' ','')
|
370
|
+
session.exec! "dpkg --ignore-depends #{depends} -i #{TMP_DIR}/#{File.basename(debarchivefile)}"
|
371
|
+
|
372
|
+
session.exec! "DEBIAN_FRONTEND=noninteractive apt-get install -q -y --force-yes -f"
|
373
|
+
logger.info("Cleaning installation files on #{coordinator}")
|
374
|
+
session.with(:coord).exec! "rm -Rf #{gitdir}"
|
375
|
+
session.with(:coord).exec! "rm -f #{TMP_DIR}/*.deb #{TMP_DIR}/*.changes #{TMP_DIR}/*.dsc #{TMP_DIR}/*.tar.gz"
|
376
|
+
else
|
377
|
+
logger.info("Installing debian distem packages")
|
378
|
+
distempkg = options[:distem_version] ? "#{PKG_NAME}=#{options[:distem_version]}":PKG_NAME
|
379
|
+
session.exec! "DEBIAN_FRONTEND=noninteractive apt-get install -q -y --allow-unauthenticated #{distempkg}"
|
380
|
+
end
|
381
|
+
|
382
|
+
logger.info("Installing debian misc packages")
|
383
|
+
session.exec! "DEBIAN_FRONTEND=noninteractive apt-get install -q -y #{pkg_tmp_dependencies * ' '}" unless pkg_tmp_dependencies.empty?
|
384
|
+
session.exec! "DEBIAN_FRONTEND=noninteractive apt-get install -q -y #{pkg_utils * ' '}" unless pkg_utils.empty?
|
385
|
+
options[:debpackages].each do |debpkg|
|
386
|
+
logger.info("Installing additional debian package '#{debpkg}'")
|
387
|
+
session.exec! "DEBIAN_FRONTEND=noninteractive apt-get install -q -y #{debpkg}"
|
388
|
+
end
|
389
|
+
options[:gempackages].each do |gempkg|
|
390
|
+
logger.info "Installing additional gem package '#{gempkg}'"
|
391
|
+
session.with(:coord).exec! "export http_proxy=#{HTTP_PROXY}; gem install #{gempkg}"
|
392
|
+
end
|
393
|
+
|
394
|
+
if options[:init_pnodes] or ARGV[0]
|
395
|
+
|
396
|
+
launched = session.exec! "lsof -Pnl -i4 | egrep ':4567 |:4568'"
|
397
|
+
launched_stdout = launched.values.select{ |x| x[:stdout] }
|
398
|
+
|
399
|
+
unless launched_stdout.empty?
|
400
|
+
tokill = launched.keys
|
401
|
+
|
402
|
+
session.group :tokill do
|
403
|
+
tokill.each{ |node| session.use "root@#{node}"
|
404
|
+
logger.debug("Distem detected on #{node}")
|
405
|
+
}
|
406
|
+
end
|
407
|
+
tokill.collect!{ |node| nodeobjlist[node] }
|
408
|
+
tokill.each { |node|
|
409
|
+
logger.info("Killing previous run of distem on #{node}")
|
410
|
+
}
|
411
|
+
session.with(:tokill).exec! "killall distemd"
|
412
|
+
time_start = Time.now
|
413
|
+
until !launched_stdout or launched_stdout.empty?
|
414
|
+
session.with(:tokill).exec! 'kill -9 `ps aux|grep "distemd"|grep -v grep|sed "s/ \{1,\}/ /g"|cut -f 2 -d" "`' if (Time.now - time_start) > 2
|
415
|
+
launched = session.with(:tokill).exec! "lsof -Pnl -i4 | egrep ':4567 |:4568 '"
|
416
|
+
launched_stdout = launched.values.select{ |x| x[:stdout] }
|
417
|
+
|
418
|
+
if launched_stdout and !launched_stdout.empty?
|
419
|
+
tokill = launched.keys
|
420
|
+
tokill.collect!{ |node| nodeobjlist[node] }
|
421
|
+
end
|
422
|
+
end
|
423
|
+
end
|
424
|
+
logger.info("Starting coordinator daemon on #{coordinator}")
|
425
|
+
session.with(:coord).exec! "mkdir -p #{PATH_DISTEMD_LOGS}"
|
426
|
+
begin
|
427
|
+
Timeout.timeout(10) do
|
428
|
+
root_iface_opt = options[:network_interface] ? "--network-interface #{options[:network_interface]}" : ''
|
429
|
+
distem_cmd = "LANG=C distemd #{options[:verbose] ? '--verbose' : ''} --network-mode "+
|
430
|
+
"#{options[:network_mode]} #{root_iface_opt} -d &>#{File.join(PATH_DISTEMD_LOGS,'distemd.log')}&"
|
431
|
+
|
432
|
+
session.with(:coord).exec! distem_cmd
|
433
|
+
|
434
|
+
[ '4567', '4568' ].each do |port|
|
435
|
+
launched = []
|
436
|
+
until launched and !launched.empty?
|
437
|
+
launched = session.with(:coord).exec! "lsof -Pnl -i4 | grep ':#{port} '"
|
438
|
+
launched[coordinator][:stdout]
|
439
|
+
sleep(1)
|
440
|
+
end
|
441
|
+
end
|
442
|
+
end
|
443
|
+
rescue Timeout::Error
|
444
|
+
logger.error("Timeout reached")
|
445
|
+
end
|
446
|
+
|
447
|
+
if options[:init_pnodes]
|
448
|
+
begin
|
449
|
+
Timeout.timeout(180) do
|
450
|
+
logger.info("Initializing node #{coordinator}")
|
451
|
+
if options[:max_vifaces]
|
452
|
+
session.with(:coord).exec! "distem --coordinator host=#{coordinator} --init-pnode #{coordinator} --max-vifaces #{options[:max_vifaces]}"
|
453
|
+
# options[:debug_distem],options[:debug_distem]) this would be controlled using the logger.
|
454
|
+
else
|
455
|
+
session.with(:coord).exec! "distem --coordinator host=#{coordinator} --init-pnode #{coordinator}" # the same for this I have to add debug
|
456
|
+
end
|
457
|
+
if nodelist.length > 0
|
458
|
+
logger.info("Initializing nodes #{nodelist.join(',')}")
|
459
|
+
if options[:max_vifaces]
|
460
|
+
session.with(:coord).exec! "distem --coordinator host=#{coordinator} --init-pnode #{nodelist.join(',')} --max-vifaces #{options[:max_vifaces]}"
|
461
|
+
else
|
462
|
+
session.with(:coord).exec! "distem --coordinator host=#{coordinator} --init-pnode #{nodelist.join(',')}"
|
463
|
+
end
|
464
|
+
end
|
465
|
+
end
|
466
|
+
rescue Timeout::Error
|
467
|
+
logger.error("Timeout reached")
|
468
|
+
end
|
469
|
+
end
|
470
|
+
|
471
|
+
end
|
472
|
+
|
473
|
+
logger.info('Install done')
|
474
|
+
|
475
|
+
if ARGV[0]
|
476
|
+
begin
|
477
|
+
File.open(ARGV[0], 'r') do |f|
|
478
|
+
filename = session.with(:coord).exec!('tempfile')[coordinator][0]
|
479
|
+
logger.info("Copying script file in '#{filename}' on #{coordinator}")
|
480
|
+
`scp #{ARGV[0]} root@#{coordinator}:#{filename}`
|
481
|
+
session.with(:coord).exec! "chmod +x #{filename}"
|
482
|
+
logger.info("Executing script file '#{filename}' on #{coordinator}")
|
483
|
+
|
484
|
+
argv_dup = ARGV.dup
|
485
|
+
argv_dup.shift
|
486
|
+
script_args = (argv_dup.length > 0 ? argv_dup.join(" ") : "")
|
487
|
+
session.with(:coord).exec! "export #{VAR_DISTEM_NODES}='#{(nodelist + [coordinator]) * "\n"}'; export #{VAR_DISTEM_COORD}='#{coordinator}';#{filename} #{script_args}"
|
488
|
+
session.with(:coord).exec! "rm #{filename}"
|
489
|
+
end
|
490
|
+
logger.info 'Script execution done'
|
491
|
+
rescue Errno::ENOENT
|
492
|
+
logger.error "script file '#{ARGV[0]}' not found"
|
493
|
+
end
|
494
|
+
end
|
495
|
+
|
496
|
+
logger.info("Coordinator: #{coordinator}") if options[:init_pnodes] or ARGV[0]
|
497
|
+
|
498
|
+
# Send stats record to stats server
|
499
|
+
if g5k? and options[:stats]
|
500
|
+
begin
|
501
|
+
stats = {
|
502
|
+
:time => Time.now.to_i,
|
503
|
+
:site => Socket.gethostname,
|
504
|
+
:user => ENV['USER'],
|
505
|
+
:oar => ENV['OAR_JOB_ID'].to_i,
|
506
|
+
:nodes => allnodes,
|
507
|
+
:params => args * ' ',
|
508
|
+
:length => (Time.now - $startt).to_i
|
509
|
+
}
|
510
|
+
sock = TCPSocket.open(STATS_SERV, STATS_PORT)
|
511
|
+
sock.send(stats.to_yaml,0)
|
512
|
+
sock.close
|
513
|
+
rescue SocketError, Errno::ECONNREFUSED, Errno::ECONNRESET, Errno::ETIMEDOUT, Errno::EHOSTUNREACH
|
514
|
+
end
|
515
|
+
end
|
516
|
+
end
|