vagrant-grid5000 0.0.3 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 613f9417d67cd5678dea8bd2ccfb3614a77074b4
4
- data.tar.gz: 24d2c93783aa39a57b5b2156143b3969116f40a8
3
+ metadata.gz: 049b3239e51d78bc2e7278a79807d4dfa83347fa
4
+ data.tar.gz: 6f46fa07a915340c8875fe652f5d277afaedbf7d
5
5
  SHA512:
6
- metadata.gz: cc15abf4ef72d1bdc9f45a43395192884101c0fb6575fe1fc2fd5e1b1403cba75a4dd752509d3333424a9e35bee261e56b329534843afe76b9ff6fab1b613240
7
- data.tar.gz: f15092b80f70ef5553fb3c28b99555503bb6eb991624c4ab0145f5e962304262054fb75f40ceaad8669f3e543fc438913a6de95443db0bac19ec57b5e31ecefa
6
+ metadata.gz: f5923379e403ca03bf5ab71099a0770a8909d5d056c3c5bb41fe61da8040a37747c4af3145c72aaa5e6bf32efd8dbf2b3a16501377489a1eb0f813a54fd3700a
7
+ data.tar.gz: 3ae45922886bc50362a8acd708c3398cec35d7da6a3a307622a2ef124776df333e5b5f9904491dfcfff025971f809c589921fcac6859f95542f507e2792d2173
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/README.md CHANGED
@@ -10,19 +10,7 @@ This is a [Vagrant](http://www.vagrantup.com) plugin that adds a provider for
10
10
  machines running on the [Grid'5000](https://www.grid5000.fr) testbed to
11
11
  Vagrant.
12
12
 
13
- This is still at an early state of development.
14
-
15
- ## What works
16
- * vagrant up --provider=grid5000
17
- * vagrant status
18
- * vagrant ssh
19
- * vagrant destroy
20
-
21
- ## What doesn't work
22
-
23
- * everything else
24
-
25
- ## Installation
13
+ ## Installation and usage
26
14
 
27
15
  ```
28
16
  $ vagrant plugin install vagrant-grid5000
@@ -33,16 +21,16 @@ Each provider needs at least one ''box''. This does not really make sense here,
33
21
  $ vagrant box add --name dummy https://github.com/lnussbaum/vagrant-grid5000/raw/master/dummy.box
34
22
  ```
35
23
 
36
- Example Vagrantfile:
24
+ Example basic Vagrantfile:
37
25
  ```ruby
38
26
  Vagrant.configure("2") do |config|
39
27
 
40
- # Global configuration for Grid'5000 access
28
+ # Global configuration for Grid'5000
41
29
  config.vm.provider "grid5000" do |g5k|
42
- # cute_parameters = { :conf_file =>"config file path" }
30
+ # Ruby-Cute's authentication parameters
31
+ #g5k.cute_parameters = { :conf_file => "config file path" }
43
32
  # For details about allowed parameters see
44
33
  # https://github.com/lnussbaum/vagrant-grid5000/blob/master/lib/vagrant-grid5000/config.rb
45
-
46
34
  end
47
35
 
48
36
  config.vm.define :my_g5k_box do |g5k|
@@ -51,6 +39,24 @@ Vagrant.configure("2") do |config|
51
39
  end
52
40
  ```
53
41
 
42
+ Then try
43
+ ```
44
+ $ vagrant up --provider=grid5000
45
+ $ vagrant ssh
46
+ $ vagrant provision
47
+ $ vagrant destroy
48
+ ```
49
+
50
+ For more details about Vagrantfile configuration parameters, see
51
+ https://github.com/lnussbaum/vagrant-grid5000/blob/master/Vagrantfile
52
+
53
+ ### Synced folders
54
+
55
+ Synced folders are a bit tricky. You need to install 'rsync' (which is not
56
+ installed on jessie-x64-min), and then issue a ''vagrant reload'' to reload the
57
+ configuration. Note that you can also use 'rsync-auto' to auto-synchronize
58
+ changes.
59
+
54
60
  ## License
55
61
 
56
62
  The gem is available as free software under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -71,3 +77,5 @@ execute Vagrant.
71
77
  $ bundle exec vagrant up --provider=grid5000
72
78
  ```
73
79
  etc.
80
+
81
+ To debug stuff, use vagrant --debug.
@@ -3,13 +3,65 @@
3
3
 
4
4
  Vagrant.configure("2") do |config|
5
5
 
6
- # Global configuration for Grid'5000 access
6
+ # Global parameters for the Grid'5000 provider
7
7
  config.vm.provider "grid5000" do |g5k|
8
- # cute_parameters = { :conf_file =>"config file path" }
8
+
9
+ # Grid'5000 authentification parameters for Ruby-Cute
10
+ # see http://www.rubydoc.info/github/ruby-cute/ruby-cute/master/Cute%2FG5K%2FAPI%3Ainitialize
11
+ # default: use ~/.grid5000_api.yml
12
+ #g5k.cute_parameters = { :username => 'jdoe', :password => 'foo' }
13
+
14
+ # Site to reserve on (default: nancy)
15
+ #g5k.site = rennes
16
+
17
+ # OAR queue to use (default: default)
18
+ #g5k.queue = 'default'
9
19
 
20
+ # OAR properties to use (default: none)
21
+ #g5k.properties = "cluster='griffon'"
22
+
23
+ # Walltime (default: reserve until the next end of day (18:55))
24
+ #g5k.walltime = '02:30'
25
+
26
+ # Environment to deploy (default: jessie-x64-min)
27
+ #g5k.env = 'jessie-x64-base'
10
28
  end
11
29
 
12
- config.vm.define :my_g5k_box do |g5k|
13
- g5k.vm.box = "dummy"
30
+ config.vm.define :testbox do |tb|
31
+ # All providers need to provide a box. This is a dummy, empty box for the grid5000 provider.
32
+ tb.vm.box = "dummy"
33
+
34
+ # VM-specific overrides
35
+ tb.vm.provider 'grid5000' do |g5k|
36
+ g5k.site = 'rennes'
37
+ g5k.walltime = '0:15'
38
+ end
14
39
  end
40
+
41
+ config.vm.define :testbox2 do |tb2|
42
+ tb2.vm.box = "dummy"
43
+
44
+ # VM-specific overrides
45
+ tb2.vm.provider 'grid5000' do |g5k|
46
+ g5k.site = 'lyon'
47
+ g5k.walltime = '0:15'
48
+ end
49
+
50
+ # Synced folders configuration, using rsync (you need to install it if you use -min or -base, see below)
51
+ tb2.vm.synced_folder ".", "/vagrant", type: "rsync", rsync__exclude: ".git/"
52
+ end
53
+
54
+ # Since we connect as root directly, we don't need to set 'privileged' to true
55
+ # However, it is a good idea to install sudo so that normal provisioning scripts
56
+ # work.
57
+ # rsync is needed for synced folders.
58
+ config.vm.provision "shell", privileged: false, inline: 'apt-get update && apt-get -y install sudo rsync'
59
+
60
+ # privileged: false is no longer required
61
+ config.vm.provision "shell", inline: <<-SHELL
62
+ #!/bin/bash -x
63
+ apt-get -y install less vim ruby
64
+ apt-get -y install git pv
65
+ SHELL
66
+
15
67
  end
@@ -9,50 +9,111 @@ module VagrantPlugins
9
9
  # Include the built-in modules so we can use them as top-level things.
10
10
  include Vagrant::Action::Builtin
11
11
 
12
- def self.action_up
12
+ # TODO def self.action_halt
13
+
14
+ def self.action_destroy
15
+ Vagrant::Action::Builder.new.tap do |b|
16
+ b.use Call, DestroyConfirm do |env, b2|
17
+ if env[:result]
18
+ b2.use ConfigValidate
19
+ b2.use Call, IsCreated do |env2, b3|
20
+ if !env2[:result]
21
+ b3.use MessageNotCreated
22
+ next
23
+ end
24
+ b3.use ConnectGrid5000
25
+ b3.use ReadState
26
+ b3.use DestroyInstance
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ # This action is called when `vagrant provision` is called.
34
+ def self.action_provision
13
35
  Vagrant::Action::Builder.new.tap do |b|
14
36
  b.use ConfigValidate
15
- b.use ConnectGrid5000
16
- b.use ReserveAndDeploy
37
+ b.use Call, IsCreated do |env, b2|
38
+ if !env[:result]
39
+ b2.use MessageNotCreated
40
+ next
41
+ end
42
+ b2.use Provision
43
+ end
17
44
  end
18
45
  end
19
46
 
20
- def self.action_ssh
47
+ # This action is called to read the state of the machine. The
48
+ # resulting state is expected to be put into the `:machine_state_id`
49
+ # key.
50
+ def self.action_read_state
21
51
  Vagrant::Action::Builder.new.tap do |b|
52
+ b.use ConfigValidate
22
53
  b.use ConnectGrid5000
23
54
  b.use ReadState
24
- b.use SSHExec
55
+ end
56
+ end
57
+
58
+ def self.action_ssh
59
+ Vagrant::Action::Builder.new.tap do |b|
60
+ b.use ConfigValidate
61
+ b.use Call, IsCreated do |env, b2|
62
+ if !env[:result]
63
+ b2.use MessageNotCreated
64
+ next
65
+ end
66
+ b2.use ConnectGrid5000
67
+ b2.use ReadState
68
+ b2.use SSHExec
69
+ end
25
70
  end
26
71
  end
27
72
 
28
73
  def self.action_ssh_run
29
- return Vagrant::Action::Builder.new.tap do |b|
30
- b.use ConnectGrid5000
31
- b.use ReadState
32
- b.use SSHRun
74
+ Vagrant::Action::Builder.new.tap do |b|
75
+ b.use ConfigValidate
76
+ b.use Call, IsCreated do |env, b2|
77
+ if !env[:result]
78
+ b2.use MessageNotCreated
79
+ next
80
+ end
81
+ b2.use ConnectGrid5000
82
+ b2.use ReadState
83
+ b2.use SSHRun
84
+ end
33
85
  end
34
86
  end
35
87
 
36
- def self.action_destroy
88
+ def self.action_up
37
89
  Vagrant::Action::Builder.new.tap do |b|
90
+ b.use HandleBox
91
+ b.use ConfigValidate
92
+ b.use BoxCheckOutdated
38
93
  b.use ConnectGrid5000
39
- b.use ReadState
40
- b.use Call, DestroyConfirm do |env, b2|
41
- if env[:result]
42
- b2.use DestroyInstance
94
+ b.use Call, IsCreated do |env1, b1|
95
+ if env1[:result]
96
+ b1.use MessageAlreadyCreated # TODO write a better message
97
+ else
98
+ b1.use ReserveAndDeploy
43
99
  end
44
100
  end
45
101
  end
46
102
  end
47
103
 
48
- # This action is called to read the state of the machine. The
49
- # resulting state is expected to be put into the `:machine_state_id`
50
- # key.
51
- def self.action_read_state
104
+ def self.action_reload
52
105
  Vagrant::Action::Builder.new.tap do |b|
53
106
  b.use ConfigValidate
54
107
  b.use ConnectGrid5000
55
- b.use ReadState
108
+ b.use Call, IsCreated do |env, b2|
109
+ if !env[:result]
110
+ b2.use MessageNotCreated
111
+ next
112
+ end
113
+
114
+ # We do almost nothing during reload
115
+ b2.use SyncedFolders
116
+ end
56
117
  end
57
118
  end
58
119
 
@@ -62,6 +123,9 @@ module VagrantPlugins
62
123
  autoload :ReadState, action_root.join("read_state")
63
124
  autoload :ConnectGrid5000, action_root.join("connect_grid5000")
64
125
  autoload :DestroyInstance, action_root.join("destroy_instance")
126
+ autoload :IsCreated, action_root.join("is_created")
127
+ autoload :MessageAlreadyCreated, action_root.join("message_already_created")
128
+ autoload :MessageNotCreated, action_root.join("message_not_created")
65
129
  end
66
130
  end
67
131
  end
@@ -1,5 +1,7 @@
1
1
  require "log4r"
2
2
 
3
+ $last_check_time = nil
4
+
3
5
  module VagrantPlugins
4
6
  module Grid5000
5
7
  module Action
@@ -13,8 +15,13 @@ module VagrantPlugins
13
15
 
14
16
  def call(env)
15
17
  env[:g5k] = Cute::G5K::API.new(env[:machine].provider_config.cute_parameters || {})
16
- # FIXME customize logger to make it clear that ruby-cute is the one displaying messages
17
- raise "Unable to retrieve the list of sites and find nancy in it" if not env[:g5k].site_uids.include?('nancy')
18
+ env[:g5k].logger = Logger.new(STDOUT)
19
+ env[:g5k].logger.progname = 'ruby-cute'
20
+ env[:g5k].logger.datetime_format = "%Y-%m-%d %H:%M:%S "
21
+ if $last_check_time.nil? or $last_check_time + 60 < Time::now
22
+ raise "Unable to retrieve the list of sites and find nancy in it" if not env[:g5k].site_uids.include?('nancy')
23
+ $last_check_time = Time::now
24
+ end
18
25
  @app.call(env)
19
26
  end
20
27
  end
@@ -0,0 +1,18 @@
1
+ module VagrantPlugins
2
+ module Grid5000
3
+ module Action
4
+ # This can be used with "Call" built-in to check if the machine
5
+ # is created and branch in the middleware.
6
+ class IsCreated
7
+ def initialize(app, env)
8
+ @app = app
9
+ end
10
+
11
+ def call(env)
12
+ env[:result] = env[:machine].state.id != :not_created
13
+ @app.call(env)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,16 @@
1
+ module VagrantPlugins
2
+ module Grid5000
3
+ module Action
4
+ class MessageAlreadyCreated
5
+ def initialize(app, env)
6
+ @app = app
7
+ end
8
+
9
+ def call(env)
10
+ env[:ui].info('Machine already created.')
11
+ @app.call(env)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ module VagrantPlugins
2
+ module Grid5000
3
+ module Action
4
+ class MessageNotCreated
5
+ def initialize(app, env)
6
+ @app = app
7
+ end
8
+
9
+ def call(env)
10
+ env[:ui].info('Machine not created.')
11
+ @app.call(env)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -1,5 +1,8 @@
1
1
  require "log4r"
2
2
 
3
+ $job_cache_data = {}
4
+ $job_cache_time = {}
5
+
3
6
  module VagrantPlugins
4
7
  module Grid5000
5
8
  module Action
@@ -18,19 +21,19 @@ module VagrantPlugins
18
21
  @app.call(env)
19
22
  end
20
23
 
21
- $last_state_read = nil
22
24
  def read_state(env)
23
-
24
25
  return :not_created if not env[:g5k] or not env[:machine]
25
26
  id = env[:machine].id
26
27
  return :not_created if id.nil?
27
28
  site, jobid, node = id.split(':')
28
29
 
29
- if $last_state_read != nil and env[:job] and Time::now < $last_state_read + 60
30
- # skip
30
+ # Very basic caching
31
+ if $job_cache_time.has_key?([site, jobid]) and $job_cache_time[[site, jobid]] + 60 > Time::now
32
+ env[:job] = $job_cache_data[[site, jobid]]
31
33
  else
32
34
  env[:job] = env[:g5k].get_job(site, jobid)
33
- $last_state_read = Time::now
35
+ $job_cache_data[[site, jobid]] = env[:job]
36
+ $job_cache_time[[site, jobid]] = Time::now
34
37
  end
35
38
  env[:machine_ssh_info] = { :host => node, :port => 22, :username => 'root', :proxy_command => "ssh -W #{node}:22 #{env[:g5k].g5k_user}@access.grid5000.fr" }
36
39
  return :running if env[:job]['state'] == 'running'
@@ -1,5 +1,10 @@
1
1
  require "log4r"
2
2
  require 'time'
3
+ require 'fileutils'
4
+
5
+ VAGRANT_INSECURE_PUBLIC_KEY = <<EOF
6
+ ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA6NF8iallvQVp22WDkTkyrtvp9eWW6A8YVr+kz4TjGYe7gHzIw+niNltGEFHzD8+v1I2YJ6oXevct1YeS0o9HZyN1Q9qgCgzUFtdOKLv6IedplqoPkcmF0aYet2PkEDo3MlTBckFXPITAMzF8dJSIFo9D8HfdOV0IAdx4O7PtixWKn5y2hMNG0zQPyUecp4pzC6kivAIhyfHilFR61RGL+GPXQ2MWZWFYbAGjyiYJnAmCP3NOTd0jMZEnDkbUvxhMmBYSdETk1rRgm+R4LOzFUGaHqHDLKLX+FIPKcF96hrucXzcWyLbIbEgE98OHlnVYCzRdK8jlqm8tehUc9c9WhQ== vagrant insecure public key
7
+ EOF
3
8
 
4
9
  module VagrantPlugins
5
10
  module Grid5000
@@ -14,24 +19,29 @@ module VagrantPlugins
14
19
  cfg = env[:machine].provider_config
15
20
  walltime = cfg.walltime
16
21
  if walltime.nil? # slightly broken: what if the local time doesn't switch DST at the same time as Europe/Paris?
17
- if Time::now.dst?
18
- target = '18:55:00 CEST'
19
- else
20
- target = '18:55:00 CET'
21
- end
22
- walltime = (Time::parse(target) - Time::now).to_i
23
- walltime = format("%02d:%02d:%02d", walltime / (60*60), walltime / 60 % 60, walltime % 60)
22
+ if Time::now.dst?
23
+ target = '18:55:00 CEST'
24
+ else
25
+ target = '18:55:00 CET'
26
+ end
27
+ walltime = (Time::parse(target) - Time::now).to_i
28
+ walltime += 86400 if walltime < 0 # if we are after the deadline, target the next day
29
+ walltime = format("%02d:%02d:%02d", walltime / (60*60), walltime / 60 % 60, walltime % 60)
24
30
  end
25
31
  if ENV['VAGRANT_DEBUG'] == 'REUSE_JOB'
26
- job = env[:g5k].get_my_jobs(cfg.site).first
32
+ job = env[:g5k].get_my_jobs(cfg.site).first
27
33
  else
28
- job = env[:g5k].reserve(:site => cfg.site, :walltime => walltime,
29
- :properties => cfg.properties, :env => cfg.env, :keys => cfg.keys,
30
- :name => "vagrant-grid5000")
34
+ # hack: create a temporary file that holds the Vagrant public key, so that ruby-cute is happy.
35
+ f = `mktemp /tmp/vagrant-grid5000-public-key.XXXXXX.pub`.chomp
36
+ File::open(f, 'w') { |fd| fd.print VAGRANT_INSECURE_PUBLIC_KEY }
37
+ params = { :site => cfg.site, :walltime => walltime, :properties => cfg.properties, :queue => cfg.queue, :env => cfg.env, :keys => f.gsub('.pub', ''), :name => "vagrant-g5k" }
38
+ env[:ui].info("Initiating reservation and deployment with #{params.inspect}")
39
+ job = env[:g5k].reserve(params)
40
+ FileUtils::rm(f)
31
41
  end
32
42
  env[:node] = job['assigned_nodes'].first
33
43
  env[:machine_state_id] = :running
34
- @logger.info("Node #{env[:node]} successfully started.")
44
+ env[:ui].info("Node #{env[:node]} successfully started.")
35
45
  env[:job] = job
36
46
  env[:machine].id = "#{cfg.site}:#{job['uid']}:#{env[:node]}"
37
47
  @app.call(env)
@@ -20,6 +20,10 @@ module VagrantPlugins
20
20
  # @return [String]
21
21
  attr_accessor :properties
22
22
 
23
+ # OAR queue to use when reserving resources. (default: 'default'; other values: production, besteffort)
24
+ # @return [String]
25
+ attr_accessor :queue
26
+
23
27
  # Walltime to use when reserving resources. (default: reserve resources until today at 6:55pm)
24
28
  # @return [String]
25
29
  attr_accessor :walltime
@@ -29,18 +33,12 @@ module VagrantPlugins
29
33
  # @return [String]
30
34
  attr_accessor :env
31
35
 
32
- # SSH keys to copy to the deployed machine. (default: use Ruby-Cute's default, which is to copy
33
- # the public keys found in ~/.ssh/
34
- # @return [String]
35
- attr_accessor :keys
36
-
37
-
38
36
  def initialize()
39
37
  @cute_parameters = UNSET_VALUE
40
38
  @env = UNSET_VALUE
41
39
  @site = UNSET_VALUE
42
- @keys = UNSET_VALUE
43
40
  @properties = UNSET_VALUE
41
+ @queue = UNSET_VALUE
44
42
  @walltime = UNSET_VALUE
45
43
  end
46
44
 
@@ -48,8 +46,8 @@ module VagrantPlugins
48
46
  @cute_parameters = nil if @cute_parameters == UNSET_VALUE
49
47
  @site = 'nancy' if @site == UNSET_VALUE
50
48
  @env = 'jessie-x64-min' if @env == UNSET_VALUE
51
- @keys = nil if @keys == UNSET_VALUE
52
49
  @properties = '' if @properties == UNSET_VALUE
50
+ @queue = 'default' if @queue == UNSET_VALUE
53
51
  @walltime = nil if @walltime == UNSET_VALUE
54
52
  end
55
53
 
@@ -1,5 +1,5 @@
1
1
  module VagrantPlugins
2
2
  module Grid5000
3
- VERSION = "0.0.3"
3
+ VERSION = "0.1.0"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vagrant-grid5000
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lucas Nussbaum
@@ -59,6 +59,7 @@ executables: []
59
59
  extensions: []
60
60
  extra_rdoc_files: []
61
61
  files:
62
+ - ".gitignore"
62
63
  - Gemfile
63
64
  - LICENSE.txt
64
65
  - README.md
@@ -74,6 +75,9 @@ files:
74
75
  - lib/vagrant-grid5000/action.rb
75
76
  - lib/vagrant-grid5000/action/connect_grid5000.rb
76
77
  - lib/vagrant-grid5000/action/destroy_instance.rb
78
+ - lib/vagrant-grid5000/action/is_created.rb
79
+ - lib/vagrant-grid5000/action/message_already_created.rb
80
+ - lib/vagrant-grid5000/action/message_not_created.rb
77
81
  - lib/vagrant-grid5000/action/read_state.rb
78
82
  - lib/vagrant-grid5000/action/reserve_and_deploy.rb
79
83
  - lib/vagrant-grid5000/config.rb