gosen 0.1.7 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -5,13 +5,14 @@ It relies on the [Restfully library](http://github.com/crohr/restfully) for inte
5
5
 
6
6
  ## Features
7
7
 
8
- Currently, it allows to submit deployments that retry automatically when too many nodes failed, similarly to [Katapult](http://www.loria.fr/~lnussbau/katapult.html).
8
+ Currently, this library allows to submit deployments that retry automatically when too many nodes fail.
9
+ A clone of the [Katapult](http://www.loria.fr/~lnussbau/katapult.html) script, called Trebuchet, is also included and can be used on the command line.
9
10
 
10
11
  ## Installation
11
12
 
12
13
  $ gem install gosen
13
14
 
14
- ## Usage
15
+ ## Library Usage
15
16
 
16
17
  The following example deploys the latest version of the Lenny-x64-big environment on the paramount-1 and paramount-2 nodes.
17
18
  If both nodes are not successfully deployed, Gosen retries again (in this case, at most 5 deployment are submitted).
@@ -43,6 +44,24 @@ The logger allows to print information about the deployment, in a style similar
43
44
  I, [2010-04-21T11:37:11.817323 #21673] INFO -- : Nodes deployed: paramount-1.rennes.grid5000.fr paramount-2.rennes.grid5000.fr
44
45
  I, [2010-04-21T11:37:11.817440 #21673] INFO -- : Had to run 1 kadeploy runs, deployed 2 nodes
45
46
 
47
+ The Gosen specific options accepted by Gosen::Deployment.new() are:
48
+
49
+ * :logger, a Ruby Logger object,
50
+ * :min_deployed_nodes, the minimal number of successfully deployed nodes (defaults to 1),
51
+ * :max_deploy_runs, the maximal number of deploy runs to perform (defaults to 1),
52
+ * :continue_if_error, a boolean allowing to retry if a deployment returned with an error (defaults to false),
53
+ * :ssh_public_key, an SSH public key to be installed in the deployed environment.
54
+
55
+ It is also possible to pass options accepted by the [Deployments API](https://api.grid5000.fr/sid/deployments/help/index.html), such as version, block_device, partition_number, etc.
56
+
57
+ ## Script usage
58
+
59
+ Trebuchet was designed to be used like Katapult:
60
+
61
+ $ trebuchet -e lenny-x64-base --env-version 3 --min-deployed-nodes 4 --max-deploy-runs 2 -c
62
+
63
+ Run `trebuchet --help` to get usage information.
64
+
46
65
  ## Note on Patches/Pull Requests
47
66
 
48
67
  * Fork the project.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.7
1
+ 0.2.0
@@ -0,0 +1,123 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'gosen'
4
+ require 'logger'
5
+ require 'optparse'
6
+ require 'ostruct'
7
+
8
+ trap('INT') {
9
+ deployment_resource = @deployment.deployment_resource rescue nil
10
+ if deployment_resource && deployment_resource['status'] == 'processing'
11
+ deployment_resource.delete
12
+ puts "Cancelled deployment #{deployment_resource['uid']}"
13
+ end
14
+ exit
15
+ }
16
+
17
+ config = OpenStruct.new
18
+ deployment_options = {}
19
+ config.nodes = []
20
+
21
+ logger = Logger.new(STDOUT)
22
+ logger.level = Logger::INFO
23
+ deployment_options[:logger] = logger
24
+
25
+ options = OptionParser.new do |opts|
26
+ opts.banner = 'Usage: trebuchet [options]'
27
+ opts.separator ''
28
+ opts.separator 'Specific options:'
29
+ opts.on('-b', '--block-device BLOCKDEVICE', 'Specify the block device to use') do |p|
30
+ deployment_options[:block_device] = p
31
+ end
32
+ opts.on('-c', '--copy-ssh-key', 'Copy SSH keys to nodes') do
33
+ config.copy_ssh_key = true
34
+ end
35
+ opts.on('--disable_bootloader_install', 'Disable the automatic installation of a bootloader for a Linux based environnment') do
36
+ deployment_options[:disable_bootloader_install] = true
37
+ end
38
+ opts.on('--disable_disk_partitioning', 'Disable the disk partitioning') do
39
+ deployment_options[:disable_disk_partitioning] = true
40
+ end
41
+ opts.on('-e', '--deploy-env ENV', 'Environment to deploy') do |env|
42
+ config.deploy_env = env
43
+ end
44
+ opts.on('--env-version NUMBER', 'Number of version of the environment to deploy') do |v|
45
+ deployment_options[:version] = v
46
+ end
47
+ opts.on('-f', '--file MACHINELIST', 'Files containing the list of nodes') do |f|
48
+ config.nodefile = f
49
+ end
50
+ opts.on('-i', '--ssh-key-file FILE', "File containing keys to copy (defaults to #{config.ssh_keyfile})") do |f|
51
+ config.ssh_keyfile = f
52
+ end
53
+ opts.on('--ignore-nodes-deploying', 'Allow to deploy even on the nodes tagged as "currently deploying" (use this only if you know what you do)') do
54
+ deployment_options[:ignore_nodes_deploying] = true
55
+ end
56
+ opts.on('-l', '--deploy-user USER', 'User owning the deployment environment') do |u|
57
+ config.deploy_user = u
58
+ end
59
+ opts.on('-m', '--machine MACHINE', 'Node to run on') do |n|
60
+ config.nodes << n
61
+ end
62
+ opts.on('--max-deploy-runs NB', 'Maximum number of deployment runs before we admit we cannot get enough nodes deployed') do |n|
63
+ deployment_options[:max_deploy_runs] = n.to_i
64
+ end
65
+ opts.on('--min-deployed-nodes NB', 'Minimum number of nodes that must be correctly deployed before continuing') do |n|
66
+ deployment_options[:min_deployed_nodes] = n.to_i
67
+ end
68
+ opts.on('-p', '--partition-number NUMBER', 'Specify the partition number to use') do |p|
69
+ deployment_options[:partition_number] = p
70
+ end
71
+ opts.on('-r', '--reformat-tmp FSTYPE', 'Reformat the /tmp partition') do |fs|
72
+ fstypes = [ "ext2", "ext3", "ext4" ]
73
+ abort "FSTYPE must be one of #{fstypes.join(', ')}" unless fstypes.include?(fs)
74
+ deployment_options[:reformat_tmp] = fs
75
+ end
76
+ end
77
+
78
+ begin
79
+ options.parse!(ARGV)
80
+ rescue OptionParser::ParseError => e
81
+ $stderr.puts e
82
+ exit 1
83
+ end
84
+
85
+ if config.nodes.empty?
86
+ config.nodefile ||= ENV['OAR_NODEFILE']
87
+ config.nodes = File.open(File.expand_path(config.nodefile)).readlines.collect { |l| l.chomp }.sort.uniq
88
+ end
89
+
90
+ if config.nodes.empty?
91
+ abort "No nodes specified, and no OAR_NODEFILE variable, exiting.\nRun trebuchet --help if you need help."
92
+ end
93
+
94
+ if config.deploy_env.nil?
95
+ abort "Error: an environment to deploy is required.\nRun trebuchet --help if you need help."
96
+ end
97
+
98
+ if config.deploy_user
99
+ config.deploy_env += "@#{config.deploy_user}"
100
+ end
101
+
102
+ if config.ssh_keyfile
103
+ abort 'Error: the --ssh-keyfile option only makes sense with --copy-ssh-key.\nRun trebuchet --help if you need help.' if config.copy_ssh_key.nil?
104
+ end
105
+
106
+ if config.copy_ssh_key
107
+ config.ssh_keyfile ||= '~/.ssh/authorized_keys'
108
+ deployment_options[:ssh_public_key] = File.open(File.expand_path(config.ssh_keyfile)).read
109
+ end
110
+
111
+ if ENV['RESTFULLY_CONFIG'].nil?
112
+ abort "No RESTFULLY_CONFIG environment variable, exiting.\nRun trebuchet --help if you need help."
113
+ end
114
+
115
+ Restfully::Session.new({ :configuration_file => ENV['RESTFULLY_CONFIG'] }) do |grid, session|
116
+ indexed_nodes = Gosen::index_nodes_by_site(config.nodes)
117
+ if indexed_nodes.keys.length > 1
118
+ raise StandardError.new("The node list needs to be specific to a single site\nRun trebuchet --help if you need help.")
119
+ end
120
+ site = grid.sites[indexed_nodes.keys.first.to_sym].load
121
+ @deployment = Gosen::Deployment.new(site, config.deploy_env, config.nodes, deployment_options)
122
+ @deployment.join
123
+ end
@@ -4,7 +4,7 @@ require 'gosen/deployment'
4
4
  require 'gosen/error'
5
5
 
6
6
  module Gosen
7
- VERSION = "0.1.7"
7
+ VERSION = "0.2.0"
8
8
 
9
9
  # Extracts the site part of a Grid'5000 node hostname, and returns a hash indexing the nodes by their site
10
10
  # Example:
@@ -80,6 +80,10 @@ module Gosen
80
80
  raise Gosen::Error.new("Not enough nodes deployed after #{@max_deploy_runs} deployment(s): needed #{@min_deployed_nodes} nodes, got only #{@good_nodes.length}")
81
81
  end
82
82
 
83
+ def deployment_resource
84
+ @deployment_run.deployment_resource rescue nil
85
+ end
86
+
83
87
  def no_more_required?
84
88
  @good_nodes.length >= @min_deployed_nodes
85
89
  end
@@ -126,6 +126,23 @@ class TestDeployment < Test::Unit::TestCase
126
126
  @deployment_resource.stubs(:[]).with('status').returns('processing', 'processing', 'terminated')
127
127
  end
128
128
 
129
+ should 'have a reader on the deployment resource' do
130
+ @deployment_result = {
131
+ 'paramount-1.rennes.grid5000.fr' => { 'state' => 'OK' },
132
+ 'paramount-2.rennes.grid5000.fr' => { 'state' => 'OK' }
133
+ }
134
+ @deployment_resource.expects(:[]).with('result').returns(@deployment_result)
135
+ @site_deployments.expects(:submit).with({ :environment => @environment, :nodes => @nodes }).returns(@deployment_resource)
136
+ @min_deployed_nodes = 2
137
+ @logger.expects(:info).with("Kadeploy run 1 with #{@nodes.length} nodes (0 already deployed, need #{@min_deployed_nodes} more)")
138
+ @logger.expects(:info).with("Nodes deployed: paramount-1.rennes.grid5000.fr paramount-2.rennes.grid5000.fr")
139
+ @logger.expects(:info).with("Had to run 1 kadeploy runs, deployed #{@deployment_result.length} nodes")
140
+
141
+ @deployment = Gosen::Deployment.new(@site, @environment, @nodes, { :logger => @logger, :min_deployed_nodes => @min_deployed_nodes })
142
+ @deployment.join
143
+ assert_equal(@deployment_resource, @deployment.deployment_resource)
144
+ end
145
+
129
146
  should 'submit a deployment run and wait for the result' do
130
147
  @deployment_result = {
131
148
  'paramount-1.rennes.grid5000.fr' => { 'state' => 'OK' },
@@ -81,6 +81,11 @@ class TestDeploymentRun < Test::Unit::TestCase
81
81
  @deployment = Gosen::DeploymentRun.new(@site, @environment, @nodes, { :ssh_public_key => @ssh_public_key })
82
82
  end
83
83
 
84
+ should 'have a reader on the deployment resource' do
85
+ @deployment.join
86
+ assert_equal(@resource, @deployment.deployment_resource)
87
+ end
88
+
84
89
  should 'wait for deployment completion and give access to the results' do
85
90
  assert_nothing_raised(Exception) {
86
91
  @deployment.join
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 1
8
- - 7
9
- version: 0.1.7
7
+ - 2
8
+ - 0
9
+ version: 0.2.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Pierre Riteau
@@ -14,8 +14,8 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-10-26 00:00:00 +02:00
18
- default_executable:
17
+ date: 2010-10-28 00:00:00 +02:00
18
+ default_executable: trebuchet
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: restfully
@@ -64,8 +64,8 @@ dependencies:
64
64
  version_requirements: *id003
65
65
  description: Gosen is a Ruby library providing high-level operations using the Grid'5000 RESTful API, such as Kadeploy deployments.
66
66
  email: priteau@gmail.com
67
- executables: []
68
-
67
+ executables:
68
+ - trebuchet
69
69
  extensions: []
70
70
 
71
71
  extra_rdoc_files:
@@ -78,6 +78,7 @@ files:
78
78
  - README.md
79
79
  - Rakefile
80
80
  - VERSION
81
+ - bin/trebuchet
81
82
  - lib/gosen.rb
82
83
  - lib/gosen/deployment.rb
83
84
  - lib/gosen/deployment_run.rb