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