beaker 1.19.1 → 1.20.0

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