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.
- checksums.yaml +8 -8
- data/HISTORY.md +295 -4
- data/README.md +4 -0
- data/lib/beaker/answers/version20.rb +103 -107
- data/lib/beaker/answers/version28.rb +111 -115
- data/lib/beaker/answers/version30.rb +194 -192
- data/lib/beaker/answers/version32.rb +27 -22
- data/lib/beaker/answers/version34.rb +6 -6
- data/lib/beaker/answers.rb +55 -21
- data/lib/beaker/cli.rb +13 -11
- data/lib/beaker/dsl/helpers.rb +2 -2
- data/lib/beaker/dsl/install_utils.rb +2 -4
- data/lib/beaker/host.rb +9 -5
- data/lib/beaker/host_prebuilt_steps.rb +33 -20
- data/lib/beaker/hypervisor/aws_sdk.rb +12 -10
- data/lib/beaker/hypervisor/ec2_helper.rb +1 -0
- data/lib/beaker/hypervisor/google_compute.rb +0 -1
- data/lib/beaker/hypervisor/vagrant.rb +11 -16
- data/lib/beaker/hypervisor/vagrant_fusion.rb +17 -0
- data/lib/beaker/hypervisor/vagrant_virtualbox.rb +26 -0
- data/lib/beaker/hypervisor/vagrant_workstation.rb +13 -0
- data/lib/beaker/hypervisor/vcloud_pooled.rb +3 -1
- data/lib/beaker/hypervisor.rb +22 -13
- data/lib/beaker/logger.rb +29 -0
- data/lib/beaker/options/command_line_parser.rb +2 -0
- data/lib/beaker/options/parser.rb +5 -4
- data/lib/beaker/options/presets.rb +58 -35
- data/lib/beaker/version.rb +1 -1
- data/spec/beaker/answers_spec.rb +156 -135
- data/spec/beaker/cli_spec.rb +35 -2
- data/spec/beaker/dsl/install_utils_spec.rb +2 -3
- data/spec/beaker/host_prebuilt_steps_spec.rb +47 -24
- data/spec/beaker/host_spec.rb +6 -6
- data/spec/beaker/hypervisor/ec2_helper_spec.rb +2 -2
- data/spec/beaker/hypervisor/hypervisor_spec.rb +35 -0
- data/spec/beaker/hypervisor/vagrant_fusion_spec.rb +34 -0
- data/spec/beaker/hypervisor/vagrant_spec.rb +39 -2
- data/spec/beaker/hypervisor/vagrant_virtualbox_spec.rb +34 -0
- data/spec/beaker/hypervisor/vagrant_workstation_spec.rb +34 -0
- data/spec/beaker/logger_spec.rb +30 -0
- data/spec/beaker/options/presets_spec.rb +4 -4
- data/spec/helpers.rb +2 -1
- data/spec/mocks.rb +5 -1
- metadata +9 -60
@@ -1,31 +1,36 @@
|
|
1
1
|
require 'beaker/answers/version30'
|
2
2
|
|
3
3
|
module Beaker
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
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
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
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
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
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
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
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
|
data/lib/beaker/answers.rb
CHANGED
@@ -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
|
2
|
+
# This class provides methods for generating PE answer file
|
7
3
|
# information.
|
8
|
-
|
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
|
12
|
-
#
|
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.
|
22
|
-
|
16
|
+
def self.create version, hosts, options
|
23
17
|
case version
|
24
18
|
when /\A3\.4/
|
25
|
-
Version34.
|
19
|
+
return Version34.new(version, hosts, options)
|
26
20
|
when /\A3\.[2-3]/
|
27
|
-
Version32.
|
21
|
+
return Version32.new(version, hosts, options)
|
28
22
|
when /\A3\.1/
|
29
|
-
Version30.
|
23
|
+
return Version30.new(version, hosts, options)
|
30
24
|
when /\A3\.0/
|
31
|
-
Version30.
|
25
|
+
return Version30.new(version, hosts, options)
|
32
26
|
when /\A2\.8/
|
33
|
-
Version28.
|
27
|
+
return Version28.new(version, hosts, options)
|
34
28
|
when /\A2\.0/
|
35
|
-
Version20.
|
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.
|
51
|
-
# create_remote_file host, "/mypath/answer",
|
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
|
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
|
-
|
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
|
-
|
174
|
-
|
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
|
-
|
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
|
-
|
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
|
data/lib/beaker/dsl/helpers.rb
CHANGED
@@ -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 --
|
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 --
|
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.
|
483
|
-
create_remote_file host, "#{host['working_dir']}/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.
|
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.
|
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.
|
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:#{
|
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 #{
|
44
|
+
ntp_command = "sntp #{ntp_server}"
|
46
45
|
else
|
47
|
-
ntp_command = "ntpdate -t 20 #{
|
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
|
139
|
-
#
|
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
|
142
|
-
version = host['platform'].
|
146
|
+
def epel_info_for host, opts
|
147
|
+
version = host['platform'].version
|
143
148
|
if not version
|
144
|
-
raise "epel_info_for
|
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
|
-
|
149
|
-
|
152
|
+
url = "#{host[:epel_url] || opts[:epel_url]}/#{version}"
|
153
|
+
pkg = host[:epel_pkg] || opts[:epel_6_pkg]
|
150
154
|
elsif version == '5'
|
151
|
-
|
152
|
-
|
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
|
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
|
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
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
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.
|
@@ -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
|
-
|
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
|