beaker 1.19.1 → 1.20.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.
Files changed (44) hide show
  1. checksums.yaml +8 -8
  2. data/HISTORY.md +295 -4
  3. data/README.md +4 -0
  4. data/lib/beaker/answers/version20.rb +103 -107
  5. data/lib/beaker/answers/version28.rb +111 -115
  6. data/lib/beaker/answers/version30.rb +194 -192
  7. data/lib/beaker/answers/version32.rb +27 -22
  8. data/lib/beaker/answers/version34.rb +6 -6
  9. data/lib/beaker/answers.rb +55 -21
  10. data/lib/beaker/cli.rb +13 -11
  11. data/lib/beaker/dsl/helpers.rb +2 -2
  12. data/lib/beaker/dsl/install_utils.rb +2 -4
  13. data/lib/beaker/host.rb +9 -5
  14. data/lib/beaker/host_prebuilt_steps.rb +33 -20
  15. data/lib/beaker/hypervisor/aws_sdk.rb +12 -10
  16. data/lib/beaker/hypervisor/ec2_helper.rb +1 -0
  17. data/lib/beaker/hypervisor/google_compute.rb +0 -1
  18. data/lib/beaker/hypervisor/vagrant.rb +11 -16
  19. data/lib/beaker/hypervisor/vagrant_fusion.rb +17 -0
  20. data/lib/beaker/hypervisor/vagrant_virtualbox.rb +26 -0
  21. data/lib/beaker/hypervisor/vagrant_workstation.rb +13 -0
  22. data/lib/beaker/hypervisor/vcloud_pooled.rb +3 -1
  23. data/lib/beaker/hypervisor.rb +22 -13
  24. data/lib/beaker/logger.rb +29 -0
  25. data/lib/beaker/options/command_line_parser.rb +2 -0
  26. data/lib/beaker/options/parser.rb +5 -4
  27. data/lib/beaker/options/presets.rb +58 -35
  28. data/lib/beaker/version.rb +1 -1
  29. data/spec/beaker/answers_spec.rb +156 -135
  30. data/spec/beaker/cli_spec.rb +35 -2
  31. data/spec/beaker/dsl/install_utils_spec.rb +2 -3
  32. data/spec/beaker/host_prebuilt_steps_spec.rb +47 -24
  33. data/spec/beaker/host_spec.rb +6 -6
  34. data/spec/beaker/hypervisor/ec2_helper_spec.rb +2 -2
  35. data/spec/beaker/hypervisor/hypervisor_spec.rb +35 -0
  36. data/spec/beaker/hypervisor/vagrant_fusion_spec.rb +34 -0
  37. data/spec/beaker/hypervisor/vagrant_spec.rb +39 -2
  38. data/spec/beaker/hypervisor/vagrant_virtualbox_spec.rb +34 -0
  39. data/spec/beaker/hypervisor/vagrant_workstation_spec.rb +34 -0
  40. data/spec/beaker/logger_spec.rb +30 -0
  41. data/spec/beaker/options/presets_spec.rb +4 -4
  42. data/spec/helpers.rb +2 -1
  43. data/spec/mocks.rb +5 -1
  44. metadata +9 -60
@@ -1,31 +1,36 @@
1
1
  require 'beaker/answers/version30'
2
2
 
3
3
  module Beaker
4
- module Answers
5
- module Version32
6
- def self.answers(hosts, master_certname, options)
7
- dashboard = only_host_with_role(hosts, 'dashboard')
8
- database = only_host_with_role(hosts, 'database')
9
- master = only_host_with_role(hosts, 'master')
4
+ # This class provides answer file information for PE version 3.2
5
+ #
6
+ # @api private
7
+ class Version32 < Version30
8
+ # Return answer data for all hosts.
9
+ #
10
+ # @return [Hash] A hash (keyed from hosts) containing hashes of answer file
11
+ # data.
12
+ def generate_answers
13
+ dashboard = only_host_with_role(@hosts, 'dashboard')
14
+ database = only_host_with_role(@hosts, 'database')
15
+ master = only_host_with_role(@hosts, 'master')
10
16
 
11
- the_answers = Version30.answers(hosts, master_certname, options)
12
- if dashboard != master
13
- # in 3.2, dashboard needs the master certname
14
- the_answers[dashboard.name][:q_puppetmaster_certname] = master_certname
15
- end
17
+ the_answers = super
18
+ if dashboard != master
19
+ # in 3.2, dashboard needs the master certname
20
+ the_answers[dashboard.name][:q_puppetmaster_certname] = master
21
+ end
16
22
 
17
- if options[:type] == :upgrade && dashboard != database
18
- # In a split configuration, there is no way for the upgrader
19
- # to know how much disk space is available for the database
20
- # migration. We tell it to continue on, because we're
21
- # awesome.
22
- the_answers[dashboard.name][:q_upgrade_with_unknown_disk_space] = 'y'
23
- end
24
- hosts.each do |h|
25
- h[:answers] = the_answers[h.name]
26
- end
27
- return the_answers
23
+ if @options[:type] == :upgrade && dashboard != database
24
+ # In a split configuration, there is no way for the upgrader
25
+ # to know how much disk space is available for the database
26
+ # migration. We tell it to continue on, because we're
27
+ # awesome.
28
+ the_answers[dashboard.name][:q_upgrade_with_unknown_disk_space] = 'y'
29
+ end
30
+ @hosts.each do |h|
31
+ h[:answers] = the_answers[h.name]
28
32
  end
33
+ return the_answers
29
34
  end
30
35
  end
31
36
  end
@@ -1,12 +1,12 @@
1
1
  require 'beaker/answers/version32'
2
2
 
3
3
  module Beaker
4
- module Answers
5
- module Version34
6
- def self.answers(hosts, master_certname, options)
7
- the_answers = Version32.answers(hosts, master_certname, options)
8
- return the_answers
9
- end
4
+ # This class provides answer file information for PE version 3.4
5
+ #
6
+ # @api private
7
+ class Version34 < Version32
8
+ def generate_answers
9
+ super
10
10
  end
11
11
  end
12
12
  end
@@ -1,58 +1,92 @@
1
- [ 'version34', 'version32', 'version30', 'version28', 'version20' ].each do |lib|
2
- require "beaker/answers/#{lib}"
3
- end
4
-
5
1
  module Beaker
6
- # This module provides static methods for accessing PE answer file
2
+ # This class provides methods for generating PE answer file
7
3
  # information.
8
- module Answers
4
+ class Answers
9
5
 
10
6
  # When given a Puppet Enterprise version, a list of hosts and other
11
- # qualifying data this method will return a hash (keyed from the hosts)
12
- # of default Puppet Enterprise answer file data hashes.
7
+ # qualifying data this method will return the appropriate object that can be used
8
+ # to generate answer file data.
13
9
  #
14
10
  # @param [String] version Puppet Enterprise version to generate answer data for
15
11
  # @param [Array<Beaker::Host>] hosts An array of host objects.
16
- # @param [String] master_certname Hostname of the puppet master.
17
12
  # @param [Hash] options options for answer files
18
13
  # @option options [Symbol] :type Should be one of :upgrade or :install.
19
14
  # @return [Hash] A hash (keyed from hosts) containing hashes of answer file
20
15
  # data.
21
- def self.answers(version, hosts, master_certname, options)
22
-
16
+ def self.create version, hosts, options
23
17
  case version
24
18
  when /\A3\.4/
25
- Version34.answers(hosts, master_certname, options)
19
+ return Version34.new(version, hosts, options)
26
20
  when /\A3\.[2-3]/
27
- Version32.answers(hosts, master_certname, options)
21
+ return Version32.new(version, hosts, options)
28
22
  when /\A3\.1/
29
- Version30.answers(hosts, master_certname, options)
23
+ return Version30.new(version, hosts, options)
30
24
  when /\A3\.0/
31
- Version30.answers(hosts, master_certname, options)
25
+ return Version30.new(version, hosts, options)
32
26
  when /\A2\.8/
33
- Version28.answers(hosts, master_certname, options)
27
+ return Version28.new(version, hosts, options)
34
28
  when /\A2\.0/
35
- Version20.answers(hosts, master_certname, options)
29
+ return Version20.new(version, hosts, options)
36
30
  else
37
31
  raise NotImplementedError, "Don't know how to generate answers for #{version}"
38
32
  end
39
33
  end
40
34
 
35
+ # The answer value for a provided question. Use the user answer when available, otherwise return the default
36
+ # @param [Hash] options options for answer file
37
+ # @option options [Symbol] :answer Contains a hash of user provided question name and answer value pairs.
38
+ # @param [String] default Should there be no user value for the provided question name return this default
39
+ # @return [String] The answer value
40
+ def answer_for(options, q, default = nil)
41
+ options[:answers][q] ? options[:answers][q] : default
42
+ end
43
+
44
+ # When given a Puppet Enterprise version, a list of hosts and other
45
+ # qualifying data this method will return a hash (keyed from the hosts)
46
+ # of default Puppet Enterprise answer file data hashes.
47
+ #
48
+ # @param [String] version Puppet Enterprise version to generate answer data for
49
+ # @param [Array<Beaker::Host>] hosts An array of host objects.
50
+ # @param [Hash] options options for answer files
51
+ # @option options [Symbol] :type Should be one of :upgrade or :install.
52
+ # @return [Hash] A hash (keyed from hosts) containing hashes of answer file
53
+ # data.
54
+ def initialize(version, hosts, options)
55
+ @version = version
56
+ @hosts = hosts
57
+ @options = options
58
+ end
59
+
60
+ # Generate the answers hash based upon version, host and option information
61
+ def generate_answers
62
+ raise "This should be handled by subclasses!"
63
+ end
64
+
65
+ # Access the answers hash for this version, host and option information. If the answers
66
+ # have not yet been calculated, generate them.
67
+ # @return [Hash] A hash of answers keyed by host.name
68
+ def answers
69
+ @answers ||= generate_answers
70
+ end
71
+
41
72
  # This converts a data hash provided by answers, and returns a Puppet
42
73
  # Enterprise compatible answer file ready for use.
43
74
  #
44
75
  # @param [Beaker::Host] host Host object in question to generate the answer
45
76
  # file for.
46
- # @param [Hash] answers Answers hash as returned by #answers
47
77
  # @return [String] a string of answers
48
78
  # @example Generating an answer file for a series of hosts
49
79
  # hosts.each do |host|
50
- # answers = Beaker::Answers.answers("2.0", hosts, "master")
51
- # create_remote_file host, "/mypath/answer", Beaker::Answers.answer_string(host, answers)
80
+ # answers = Beaker::Answers.new("2.0", hosts, "master")
81
+ # create_remote_file host, "/mypath/answer", answers.answer_string(host, answers)
52
82
  # end
53
- def self.answer_string(host, answers)
83
+ def answer_string(host)
54
84
  answers[host.name].map { |k,v| "#{k}=#{v}" }.join("\n")
55
85
  end
56
86
 
57
87
  end
88
+
89
+ [ 'version34', 'version32', 'version30', 'version28', 'version20' ].each do |lib|
90
+ require "beaker/answers/#{lib}"
91
+ end
58
92
  end
data/lib/beaker/cli.rb CHANGED
@@ -104,7 +104,7 @@ module Beaker
104
104
  #cleanup phase
105
105
  rescue => e
106
106
  #cleanup on error
107
- if @options[:preserve_hosts].to_s =~ /(never)/
107
+ if @options[:preserve_hosts].to_s =~ /(never)|(onpass)/
108
108
  @logger.notify "Cleanup: cleaning up after failed run"
109
109
  if @network_manager
110
110
  @network_manager.cleanup
@@ -161,21 +161,25 @@ module Beaker
161
161
  #
162
162
  # @return nil
163
163
  def print_env_vars_affecting_beaker( log_level )
164
- beaker_env_vars = Beaker::Options::Presets::ENVIRONMENT_SPEC.values
165
164
  non_beaker_env_vars = [ 'BUNDLE_PATH', 'BUNDLE_BIN', 'GEM_HOME', 'GEM_PATH', 'RUBYLIB', 'PATH']
166
- important_env_vars = beaker_env_vars + non_beaker_env_vars
167
- env_var_map = important_env_vars.inject({}) do |memo, possibly_set_vars|
165
+ env_var_map = non_beaker_env_vars.inject({}) do |memo, possibly_set_vars|
168
166
  set_var = Array(possibly_set_vars).detect {|possible_var| ENV[possible_var] }
169
167
  memo[set_var] = ENV[set_var] if set_var
170
168
  memo
171
169
  end
172
170
 
173
- puts ''
174
- @logger.send( log_level, "Important ENV variables that may have affected your run:" )
171
+ env_var_map = env_var_map.merge(Beaker::Options::Presets.new.env_vars)
172
+
173
+ @logger.send( log_level, "\nImportant ENV variables that may have affected your run:" )
175
174
  env_var_map.each_pair do |var, value|
176
- @logger.send( log_level, " #{var}\t\t#{value}" )
175
+ if value.is_a?(Hash)
176
+ value.each_pair do | subvar, subvalue |
177
+ @logger.send( log_level, " #{subvar}\t\t#{subvalue}" )
178
+ end
179
+ else
180
+ @logger.send( log_level, " #{var}\t\t#{value}" )
181
+ end
177
182
  end
178
- puts ''
179
183
  end
180
184
 
181
185
  # Prints the command line that can be called to reproduce this run
@@ -186,10 +190,8 @@ module Beaker
186
190
  #
187
191
  # @return nil
188
192
  def print_command_line( log_level = :debug )
189
- puts ''
190
- @logger.send(log_level, "You can reproduce this run with:\n")
193
+ @logger.send(log_level, "\nYou can reproduce this run with:\n")
191
194
  @logger.send(log_level, @options[:command_line])
192
- puts ''
193
195
  end
194
196
  end
195
197
  end
@@ -1219,7 +1219,7 @@ module Beaker
1219
1219
  #wait for a given host to appear in the dashboard
1220
1220
  def wait_for_host_in_dashboard(host)
1221
1221
  hostname = host.node_name
1222
- retry_command("Wait for #{hostname} to be in the console", dashboard, "! curl --sslv3 -k -I https://#{dashboard}/nodes/#{hostname} | grep '404 Not Found'")
1222
+ retry_command("Wait for #{hostname} to be in the console", dashboard, "! curl --tlsv1 -k -I https://#{dashboard}/nodes/#{hostname} | grep '404 Not Found'")
1223
1223
  end
1224
1224
 
1225
1225
  # Ensure the host has requested a cert, then sign it
@@ -1295,7 +1295,7 @@ module Beaker
1295
1295
  #
1296
1296
  def curl_on(host, cmd, opts = {}, &block)
1297
1297
  if options.is_pe? #check global options hash
1298
- on host, "curl --sslv3 %s" % cmd, opts, &block
1298
+ on host, "curl --tlsv1 %s" % cmd, opts, &block
1299
1299
  else
1300
1300
  on host, "curl %s" % cmd, opts, &block
1301
1301
  end
@@ -428,8 +428,6 @@ module Beaker
428
428
  #
429
429
  def do_install hosts, opts = {}
430
430
  opts[:type] = opts[:type] || :install
431
- hostcert='uname | grep -i sunos > /dev/null && hostname || hostname -s'
432
- master_certname = on(master, hostcert).stdout.strip
433
431
  pre30database = version_is_less(opts[:pe_ver] || database['pe_ver'], '3.0')
434
432
  pre30master = version_is_less(opts[:pe_ver] || master['pe_ver'], '3.0')
435
433
 
@@ -479,8 +477,8 @@ module Beaker
479
477
  # We only need answers if we're using the classic installer
480
478
  version = host['pe_ver'] || opts[:pe_ver]
481
479
  if (! host['roles'].include? 'frictionless') || version_is_less(version, '3.2.0')
482
- answers = Beaker::Answers.answers(opts[:pe_ver] || host['pe_ver'], hosts, master_certname, opts)
483
- create_remote_file host, "#{host['working_dir']}/answers", Beaker::Answers.answer_string(host, answers)
480
+ answers = Beaker::Answers.create(opts[:pe_ver] || host['pe_ver'], hosts, opts)
481
+ create_remote_file host, "#{host['working_dir']}/answers", answers.answer_string(host)
484
482
  else
485
483
  # If We're *not* running the classic installer, we want
486
484
  # to make sure the master has packages for us.
data/lib/beaker/host.rb CHANGED
@@ -268,8 +268,8 @@ module Beaker
268
268
  # @param target [String] The destination path on the host
269
269
  # @param [Hash{Symbol=>String}] options Options to alter execution
270
270
  # @option options [Array<String>] :ignore An array of file/dir paths that will not be copied to the host
271
- def do_scp_to source, target, options = {}
272
- @logger.debug "localhost $ scp #{source} #{@name}:#{target}"
271
+ def do_scp_to source, target, options
272
+ @logger.notify "localhost $ scp #{source} #{@name}:#{target} {:ignore => #{options[:ignore]}}"
273
273
 
274
274
  result = Result.new(@name, [source, target])
275
275
  has_ignore = options[:ignore] and not options[:ignore].empty?
@@ -286,21 +286,24 @@ module Beaker
286
286
  if File.file?(source) or (File.directory?(source) and not has_ignore)
287
287
  source_file = source
288
288
  if has_ignore and (source =~ ignore_re)
289
- @logger.debug "After rejecting ignored files/dirs, there is no file to copy"
289
+ @logger.trace "After rejecting ignored files/dirs, there is no file to copy"
290
290
  source_file = nil
291
291
  result.stdout = "No files to copy"
292
292
  result.exit_code = 1
293
293
  end
294
294
  if source_file
295
295
  result = connection.scp_to(source_file, target, options, $dry_run)
296
+ @logger.trace result.stdout
296
297
  end
297
298
  else # a directory with ignores
298
299
  dir_source = Dir.glob("#{source}/**/*").reject do |f|
299
300
  f =~ ignore_re
300
301
  end
301
- @logger.debug "After rejecting ignored files/dirs, going to scp [#{dir_source.join(", ")}]"
302
+ @logger.trace "After rejecting ignored files/dirs, going to scp [#{dir_source.join(", ")}]"
302
303
 
303
304
  # create necessary directory structure on host
305
+ # run this quietly (no STDOUT)
306
+ @logger.quiet(true)
304
307
  required_dirs = (dir_source.map{ | dir | File.dirname(dir) }).uniq
305
308
  require 'pathname'
306
309
  source_path = Pathname.new(source)
@@ -312,6 +315,7 @@ module Beaker
312
315
  mkdir_p( File.join(target, dir) )
313
316
  end
314
317
  end
318
+ @logger.quiet(false)
315
319
 
316
320
  # copy each file to the host
317
321
  dir_source.each do |s|
@@ -322,10 +326,10 @@ module Beaker
322
326
  file_path = File.join(target, s)
323
327
  end
324
328
  result = connection.scp_to(s, file_path, options, $dry_run)
329
+ @logger.trace result.stdout
325
330
  end
326
331
  end
327
332
 
328
- @logger.debug result.stdout
329
333
  return result
330
334
  end
331
335
 
@@ -27,6 +27,7 @@ module Beaker
27
27
  # @option opts [Beaker::Logger] :logger A {Beaker::Logger} object
28
28
  def timesync host, opts
29
29
  logger = opts[:logger]
30
+ ntp_server = opts[:ntp_server] ? opts[:ntp_server] : NTPSERVER
30
31
  block_on host do |host|
31
32
  logger.notify "Update system time sync for '#{host.name}'"
32
33
  if host['platform'].include? 'windows'
@@ -34,17 +35,15 @@ module Beaker
34
35
  # is not actually necessary.
35
36
  host.exec(Command.new("w32tm /register"), :acceptable_exit_codes => [0,5])
36
37
  host.exec(Command.new("net start w32time"), :acceptable_exit_codes => [0,2])
37
- host.exec(Command.new("w32tm /config /manualpeerlist:#{NTPSERVER} /syncfromflags:manual /update"))
38
+ host.exec(Command.new("w32tm /config /manualpeerlist:#{ntp_server} /syncfromflags:manual /update"))
38
39
  host.exec(Command.new("w32tm /resync"))
39
40
  logger.notify "NTP date succeeded on #{host}"
40
41
  else
41
42
  case
42
- when host['platform'] =~ /solaris-10/
43
- ntp_command = "sleep 10 && ntpdate -w #{NTPSERVER}"
44
43
  when host['platform'] =~ /sles-/
45
- ntp_command = "sntp #{NTPSERVER}"
44
+ ntp_command = "sntp #{ntp_server}"
46
45
  else
47
- ntp_command = "ntpdate -t 20 #{NTPSERVER}"
46
+ ntp_command = "ntpdate -t 20 #{ntp_server}"
48
47
  end
49
48
  success=false
50
49
  try = 0
@@ -135,25 +134,30 @@ module Beaker
135
134
  end
136
135
 
137
136
  #Determine the Extra Packages for Enterprise Linux URL for the provided Enterprise Linux host.
138
- # @param [Host] host One host to act upon
139
- # @return [String] The URL for EPL for the provided host
137
+ # @param [Host, Array<Host>] host One host to act on. Will use host epel_url, epel_arch and epel_pkg
138
+ # before using defaults provided in opts.
139
+ # @return [String, String, String] The URL, arch and package name for EPL for the provided host
140
+ # @param [Hash{Symbol=>String}] opts Options to alter execution.
141
+ # @option opts [String] :epel_url Link to download
142
+ # @option opts [String] :epel_arch Architecture to download (i386, x86_64, etc), defaults to i386
143
+ # @option opts [String] :epel_6_pkg Package to download from provided link for el-6
144
+ # @option opts [String] :epel_5_pkg Package to download from provided link for el-5
140
145
  # @raise [Exception] Raises an error if the host provided's platform != /el-(5|6)/
141
- def epel_info_for! host
142
- version = host['platform'].match(/el-(\d+)/)
146
+ def epel_info_for host, opts
147
+ version = host['platform'].version
143
148
  if not version
144
- raise "epel_info_for! not available for #{host.name} on platform #{host['platform']}"
149
+ raise "epel_info_for not available for #{host.name} on platform #{host['platform']}"
145
150
  end
146
- version = version[1]
147
151
  if version == '6'
148
- pkg = 'epel-release-6-8.noarch.rpm'
149
- url = "http://mirror.itc.virginia.edu/fedora-epel/6/i386/#{pkg}"
152
+ url = "#{host[:epel_url] || opts[:epel_url]}/#{version}"
153
+ pkg = host[:epel_pkg] || opts[:epel_6_pkg]
150
154
  elsif version == '5'
151
- pkg = 'epel-release-5-4.noarch.rpm'
152
- url = "http://archive.linux.duke.edu/pub/epel/5/i386/#{pkg}"
155
+ url = "#{host[:epel_url] || opts[:epel_url]}/#{version}"
156
+ pkg = host[:epel_pkg] || opts[:epel_5_pkg]
153
157
  else
154
- raise "epel_info_for! does not support el version #{version}, on #{host.name}"
158
+ raise "epel_info_for does not support el version #{version}, on #{host.name}"
155
159
  end
156
- return url
160
+ return url, host[:epel_arch] || opts[:epel_arch] || 'i386', pkg
157
161
  end
158
162
 
159
163
  #Run 'apt-get update' on the provided host or hosts. If the platform of the provided host is not
@@ -214,10 +218,15 @@ module Beaker
214
218
  end
215
219
 
216
220
  #Install EPEL on host or hosts with platform = /el-(5|6)/. Do nothing on host or hosts of other platforms.
217
- # @param [Host, Array<Host>] host One or more hosts to act upon
221
+ # @param [Host, Array<Host>] host One or more hosts to act upon. Will use individual host epel_url, epel_arch
222
+ # and epel_pkg before using defaults provided in opts.
218
223
  # @param [Hash{Symbol=>String}] opts Options to alter execution.
219
224
  # @option opts [Boolean] :debug If true, print verbose rpm information when installing EPEL
220
225
  # @option opts [Beaker::Logger] :logger A {Beaker::Logger} object
226
+ # @option opts [String] :epel_url Link to download from
227
+ # @option opts [String] :epel_arch Architecture of epel to download (i386, x86_64, etc)
228
+ # @option opts [String] :epel_6_pkg Package to download from provided link for el-6
229
+ # @option opts [String] :epel_5_pkg Package to download from provided link for el-5
221
230
  def add_el_extras( host, opts )
222
231
  #add_el_extras
223
232
  #only supports el-* platforms
@@ -228,8 +237,12 @@ module Beaker
228
237
  when host['platform'] =~ /el-(5|6)/
229
238
  result = host.exec(Command.new('rpm -qa | grep epel-release'), :acceptable_exit_codes => [0,1])
230
239
  if result.exit_code == 1
231
- url = epel_info_for! host
232
- host.exec(Command.new("rpm -i#{debug_opt} #{url}"))
240
+ url, arch, pkg = epel_info_for host, opts
241
+ host.exec(Command.new("rpm -i#{debug_opt} #{url}/#{arch}/#{pkg}"))
242
+ #update /etc/yum.repos.d/epel.repo for new baseurl
243
+ host.exec(Command.new("sed -i -e 's;#baseurl.*$;baseurl=#{Regexp.escape(url)}/\$basearch;' /etc/yum.repos.d/epel.repo"))
244
+ #remove mirrorlist
245
+ host.exec(Command.new("sed -i -e '/mirrorlist/d' /etc/yum.repos.d/epel.repo"))
233
246
  host.exec(Command.new('yum clean all && yum makecache'))
234
247
  end
235
248
  else
@@ -121,18 +121,20 @@ module Beaker
121
121
  time_now = Time.now.getgm #ec2 uses GM time
122
122
  @ec2.regions.each do |region|
123
123
  @logger.debug "Reviewing: #{region.name}"
124
- @ec2.regions[region.name].instances.each do |instance|
125
- if (instance.key_name =~ /#{key}/)
126
- @logger.debug "Examining #{instance.id} (keyname: #{instance.key_name}, launch time: #{instance.launch_time}, status: #{instance.status})"
127
- if ((time_now - instance.launch_time) > max_age*60*60) and instance.status.to_s !~ /terminated/
128
- @logger.debug "Kill! #{instance.id}: #{instance.key_name} (Current status: #{instance.status})"
129
- begin
130
- instance.terminate()
131
- kill_count += 1
132
- rescue AWS::EC2::Errors => e
133
- @logger.debug "Failed to remove instance: #{instance.id}, #{e}"
124
+ # Note: don't use instances.each here as that funtion doesn't allow proper rescue from error states
125
+ instances = @ec2.regions[region.name].instances
126
+ instances.each do |instance|
127
+ begin
128
+ if (instance.key_name =~ /#{key}/)
129
+ @logger.debug "Examining #{instance.id} (keyname: #{instance.key_name}, launch time: #{instance.launch_time}, status: #{instance.status})"
130
+ if ((time_now - instance.launch_time) > max_age*60*60) and instance.status.to_s !~ /terminated/
131
+ @logger.debug "Kill! #{instance.id}: #{instance.key_name} (Current status: #{instance.status})"
132
+ instance.terminate()
133
+ kill_count += 1
134
134
  end
135
135
  end
136
+ rescue AWS::Core::Resource::NotFound, AWS::EC2::Errors => e
137
+ @logger.debug "Failed to remove instance: #{instance.id}, #{e}"
136
138
  end
137
139
  end
138
140
  # Occasionaly, tearing down ec2 instances leaves orphaned EBS volumes behind -- these stack up quickly.
@@ -20,6 +20,7 @@ module Beaker
20
20
 
21
21
  if roles.include? 'dashboard'
22
22
  ports << 443
23
+ ports << 4435
23
24
  end
24
25
 
25
26
  ports
@@ -83,7 +83,6 @@ module Beaker
83
83
  host['user'] = 'google_compute'
84
84
 
85
85
  disable_se_linux(host, @options)
86
- disable_iptables(host, @options)
87
86
  copy_ssh_to_root(host, @options)
88
87
  enable_root_login(host, @options)
89
88
  host['user'] = default_user
@@ -28,38 +28,33 @@ module Beaker
28
28
  v_file << " v.vm.hostname = '#{host.name}'\n"
29
29
  v_file << " v.vm.box = '#{host['box']}'\n"
30
30
  v_file << " v.vm.box_url = '#{host['box_url']}'\n" unless host['box_url'].nil?
31
+ v_file << " v.vm.box_version = '#{host['box_version']}'\n" unless host['box_version'].nil?
32
+ v_file << " v.vm.box_check_update = '#{host['box_check_update'] ||= 'true'}'\n"
31
33
  v_file << " v.vm.base_mac = '#{randmac}'\n"
32
34
  v_file << " v.vm.network :private_network, ip: \"#{host['ip'].to_s}\", :netmask => \"#{host['netmask'] ||= "255.255.0.0"}\"\n"
33
35
 
34
- if host['disk_path']
35
- v_file << " v.vm.provider :virtualbox do |vb|\n"
36
- v_file << " vb.name = '#{host.name}'\n"
37
- unless File.exist?(host['disk_path'])
38
- host['disk_path'] = File.join(host['disk_path'], "#{host.name}.vmdk")
39
- v_file << " vb.customize ['createhd', '--filename', '#{host['disk_path']}', '--size', #{host['disk_size'] ||= 5 * 1024}, '--format', 'vmdk']\n"
40
- end
41
- v_file << " vb.customize ['storageattach', :id, '--storagectl', 'SATA Controller', '--port', 1, '--device', 0, '--type', 'hdd', '--medium','#{host['disk_path']}']\n"
42
- v_file << " end\n"
43
- end
44
-
45
36
  if /windows/i.match(host['platform'])
46
37
  v_file << " v.vm.network :forwarded_port, guest: 3389, host: 3389\n"
47
38
  v_file << " v.vm.network :forwarded_port, guest: 5985, host: 5985, id: 'winrm', auto_correct: true\n"
48
39
  v_file << " v.vm.guest = :windows"
49
40
  end
50
41
 
42
+ v_file << self.class.provider_vfile_section(host, options)
43
+
51
44
  v_file << " end\n"
52
45
  @logger.debug "created Vagrantfile for VagrantHost #{host.name}"
53
46
  end
54
- v_file << " c.vm.provider :virtualbox do |vb|\n"
55
- v_file << " vb.customize [\"modifyvm\", :id, \"--memory\", \"#{options['vagrant_memsize'] ||= '1024'}\"]\n"
56
- v_file << " end\n"
57
47
  v_file << "end\n"
58
48
  File.open(@vagrant_file, 'w') do |f|
59
49
  f.write(v_file)
60
50
  end
61
51
  end
62
52
 
53
+ def self.provider_vfile_section host, options
54
+ # Backwards compatibility; default to virtualbox
55
+ Beaker::VagrantVirtualbox.provider_vfile_section(host, options)
56
+ end
57
+
63
58
  def set_ssh_config host, user
64
59
  f = Tempfile.new("#{host.name}")
65
60
  ssh_config = Dir.chdir(@vagrant_path) do
@@ -109,7 +104,7 @@ module Beaker
109
104
 
110
105
  end
111
106
 
112
- def provision
107
+ def provision(provider = nil)
113
108
  if !@options[:provision] and !File.file?(@vagrant_file)
114
109
  raise "Beaker is configured with provision = false but no vagrant file was found at #{@vagrant_file}. You need to enable provision"
115
110
  end
@@ -120,7 +115,7 @@ module Beaker
120
115
 
121
116
  make_vfile @hosts, @options
122
117
 
123
- vagrant_cmd("up")
118
+ vagrant_cmd("up#{" --provider #{provider}" if provider}")
124
119
  else #set host ip of already up boxes
125
120
  @hosts.each do |host|
126
121
  host[:ip] = get_ip_from_vagrant_file(host.name)
@@ -0,0 +1,17 @@
1
+ require 'beaker/hypervisor/vagrant'
2
+
3
+ class Beaker::VagrantFusion < Beaker::Vagrant
4
+ def provision(provider = 'vmware_fusion')
5
+ # By default vmware_fusion creates a .vagrant directory relative to the
6
+ # Vagrantfile path. That means beaker tries to scp the VM to itself unless
7
+ # we move the VM files elsewhere.
8
+ ENV['VAGRANT_VMWARE_CLONE_DIRECTORY'] = '~/.vagrant/vmware_fusion'
9
+ super
10
+ end
11
+
12
+ def self.provider_vfile_section(host, options)
13
+ " v.vm.provider :vmware_fusion do |v|\n" +
14
+ " v.vmx['memsize'] = '#{options['vagrant_memsize'] ||= '1024'}'\n" +
15
+ " end\n"
16
+ end
17
+ end
@@ -0,0 +1,26 @@
1
+ require 'beaker/hypervisor/vagrant'
2
+
3
+ class Beaker::VagrantVirtualbox < Beaker::Vagrant
4
+ def provision(provider = 'virtualbox')
5
+ super
6
+ end
7
+
8
+ def self.provider_vfile_section(host, options)
9
+ provider_section = ""
10
+ provider_section << " v.vm.provider :virtualbox do |vb|\n"
11
+ provider_section << " vb.customize ['modifyvm', :id, '--memory', '#{options['vagrant_memsize'] ||= '1024'}']\n"
12
+ if host['disk_path']
13
+ unless File.exist?(host['disk_path'])
14
+ host['disk_path'] = File.join(host['disk_path'], "#{host.name}.vmdk")
15
+ provider_section << " vb.customize ['createhd', '--filename', '#{host['disk_path']}', '--size', #{host['disk_size'] ||= 5 * 1024}, '--format', 'vmdk']\n"
16
+ end
17
+ provider_section << " vb.customize ['storageattach', :id, '--storagectl', 'SATA Controller', '--port', 1, '--device', 0, '--type', 'hdd', '--medium','#{host['disk_path']}']\n"
18
+ provider_section << " vb.customize [\"modifyvm\", :id, \"--natdnshostresolver1\", \"#{host['natdns']}\"]\n" unless host['natdns'].nil?
19
+ provider_section << " vb.customize [\"modifyvm\", :id, \"--natdnsproxy1\", \"#{host['natdns']}\"]\n" unless host['natdns'].nil?
20
+ provider_section << " end\n"
21
+ end
22
+ provider_section << " end\n"
23
+
24
+ provider_section
25
+ end
26
+ end
@@ -0,0 +1,13 @@
1
+ require 'beaker/hypervisor/vagrant'
2
+
3
+ class Beaker::VagrantWorkstation < Beaker::Vagrant
4
+ def provision(provider = 'vmware_workstation')
5
+ super
6
+ end
7
+
8
+ def self.provider_vfile_section(host, options)
9
+ " v.vm.provider :vmware_workstation do |v|\n" +
10
+ " v.vmx['memsize'] = '#{options['vagrant_memsize'] ||= '1024'}'\n" +
11
+ " end\n"
12
+ end
13
+ end
@@ -76,7 +76,9 @@ module Beaker
76
76
  response = http.request(request)
77
77
  parsed_response = JSON.parse(response.body)
78
78
  if parsed_response[h['template']] && parsed_response[h['template']]['ok'] && parsed_response[h['template']]['hostname']
79
- h['vmhostname'] = parsed_response[h['template']]['hostname']
79
+ hostname = parsed_response[h['template']]['hostname']
80
+ domain = parsed_response['domain']
81
+ h['vmhostname'] = domain ? "#{hostname}.#{domain}" : hostname
80
82
  else
81
83
  raise "VcloudPooled.provision - no vCloud host free for #{h.name} in pool"
82
84
  end