beaker 0.0.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 +15 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.simplecov +14 -0
- data/DOCUMENTING.md +167 -0
- data/Gemfile +3 -0
- data/LICENSE +17 -0
- data/README.md +332 -0
- data/Rakefile +121 -0
- data/beaker.gemspec +42 -0
- data/beaker.rb +10 -0
- data/bin/beaker +9 -0
- data/lib/beaker.rb +36 -0
- data/lib/beaker/answers.rb +29 -0
- data/lib/beaker/answers/version28.rb +104 -0
- data/lib/beaker/answers/version30.rb +194 -0
- data/lib/beaker/cli.rb +113 -0
- data/lib/beaker/command.rb +241 -0
- data/lib/beaker/command_factory.rb +21 -0
- data/lib/beaker/dsl.rb +85 -0
- data/lib/beaker/dsl/assertions.rb +87 -0
- data/lib/beaker/dsl/helpers.rb +625 -0
- data/lib/beaker/dsl/install_utils.rb +299 -0
- data/lib/beaker/dsl/outcomes.rb +99 -0
- data/lib/beaker/dsl/roles.rb +97 -0
- data/lib/beaker/dsl/structure.rb +63 -0
- data/lib/beaker/dsl/wrappers.rb +100 -0
- data/lib/beaker/host.rb +193 -0
- data/lib/beaker/host/aix.rb +15 -0
- data/lib/beaker/host/aix/file.rb +16 -0
- data/lib/beaker/host/aix/group.rb +35 -0
- data/lib/beaker/host/aix/user.rb +32 -0
- data/lib/beaker/host/unix.rb +54 -0
- data/lib/beaker/host/unix/exec.rb +15 -0
- data/lib/beaker/host/unix/file.rb +16 -0
- data/lib/beaker/host/unix/group.rb +40 -0
- data/lib/beaker/host/unix/pkg.rb +22 -0
- data/lib/beaker/host/unix/user.rb +32 -0
- data/lib/beaker/host/windows.rb +44 -0
- data/lib/beaker/host/windows/exec.rb +18 -0
- data/lib/beaker/host/windows/file.rb +15 -0
- data/lib/beaker/host/windows/group.rb +36 -0
- data/lib/beaker/host/windows/pkg.rb +26 -0
- data/lib/beaker/host/windows/user.rb +32 -0
- data/lib/beaker/hypervisor.rb +37 -0
- data/lib/beaker/hypervisor/aixer.rb +52 -0
- data/lib/beaker/hypervisor/blimper.rb +123 -0
- data/lib/beaker/hypervisor/fusion.rb +56 -0
- data/lib/beaker/hypervisor/solaris.rb +65 -0
- data/lib/beaker/hypervisor/vagrant.rb +118 -0
- data/lib/beaker/hypervisor/vcloud.rb +175 -0
- data/lib/beaker/hypervisor/vsphere.rb +80 -0
- data/lib/beaker/hypervisor/vsphere_helper.rb +200 -0
- data/lib/beaker/logger.rb +167 -0
- data/lib/beaker/network_manager.rb +73 -0
- data/lib/beaker/options_parsing.rb +323 -0
- data/lib/beaker/result.rb +55 -0
- data/lib/beaker/shared.rb +15 -0
- data/lib/beaker/shared/error_handler.rb +17 -0
- data/lib/beaker/shared/host_handler.rb +46 -0
- data/lib/beaker/shared/repetition.rb +28 -0
- data/lib/beaker/ssh_connection.rb +198 -0
- data/lib/beaker/test_case.rb +225 -0
- data/lib/beaker/test_config.rb +148 -0
- data/lib/beaker/test_suite.rb +288 -0
- data/lib/beaker/utils.rb +7 -0
- data/lib/beaker/utils/ntp_control.rb +42 -0
- data/lib/beaker/utils/repo_control.rb +92 -0
- data/lib/beaker/utils/setup_helper.rb +77 -0
- data/lib/beaker/utils/validator.rb +27 -0
- data/spec/beaker/command_spec.rb +94 -0
- data/spec/beaker/dsl/assertions_spec.rb +104 -0
- data/spec/beaker/dsl/helpers_spec.rb +230 -0
- data/spec/beaker/dsl/install_utils_spec.rb +70 -0
- data/spec/beaker/dsl/outcomes_spec.rb +43 -0
- data/spec/beaker/dsl/roles_spec.rb +86 -0
- data/spec/beaker/dsl/structure_spec.rb +60 -0
- data/spec/beaker/dsl/wrappers_spec.rb +52 -0
- data/spec/beaker/host_spec.rb +95 -0
- data/spec/beaker/logger_spec.rb +117 -0
- data/spec/beaker/options_parsing_spec.rb +37 -0
- data/spec/beaker/puppet_command_spec.rb +128 -0
- data/spec/beaker/ssh_connection_spec.rb +39 -0
- data/spec/beaker/test_case_spec.rb +6 -0
- data/spec/beaker/test_suite_spec.rb +44 -0
- data/spec/mocks_and_helpers.rb +34 -0
- data/spec/spec_helper.rb +15 -0
- metadata +359 -0
@@ -0,0 +1,148 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
module Beaker
|
5
|
+
# Config was taken by Ruby.
|
6
|
+
class TestConfig
|
7
|
+
|
8
|
+
attr_accessor :logger
|
9
|
+
def initialize(config_file, options)
|
10
|
+
@options = options
|
11
|
+
@logger = options[:logger]
|
12
|
+
@config = load_file(config_file)
|
13
|
+
end
|
14
|
+
|
15
|
+
def [](key)
|
16
|
+
@config[key]
|
17
|
+
end
|
18
|
+
|
19
|
+
def ssh_defaults
|
20
|
+
{
|
21
|
+
:config => false,
|
22
|
+
:paranoid => false,
|
23
|
+
:timeout => 300,
|
24
|
+
:auth_methods => ["publickey"],
|
25
|
+
:keys => [@options[:keyfile]],
|
26
|
+
:port => 22,
|
27
|
+
:user_known_hosts_file => "#{ENV['HOME']}/.ssh/known_hosts",
|
28
|
+
:forward_agent => true
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
32
|
+
def load_file(config_file)
|
33
|
+
if config_file.is_a? Hash
|
34
|
+
config = config_file
|
35
|
+
else
|
36
|
+
config = YAML.load_file(config_file)
|
37
|
+
|
38
|
+
# Make sure the roles array is present for all hosts
|
39
|
+
config['HOSTS'].each_key do |host|
|
40
|
+
config['HOSTS'][host]['roles'] ||= []
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Merge some useful date into the config hash
|
45
|
+
config['CONFIG'] ||= {}
|
46
|
+
consoleport = ENV['consoleport'] || config['CONFIG']['consoleport'] || 443
|
47
|
+
config['CONFIG']['consoleport'] = consoleport.to_i
|
48
|
+
config['CONFIG']['ssh'] = ssh_defaults.merge(config['CONFIG']['ssh'] || {})
|
49
|
+
config['CONFIG']['modules'] = @options[:modules] || []
|
50
|
+
|
51
|
+
if is_pe?
|
52
|
+
config['CONFIG']['pe_dir'] = puppet_enterprise_dir
|
53
|
+
config['CONFIG']['pe_ver'] = puppet_enterprise_version
|
54
|
+
config['CONFIG']['pe_ver_win'] = puppet_enterprise_version_win
|
55
|
+
else
|
56
|
+
config['CONFIG']['puppet_ver'] = @options[:puppet]
|
57
|
+
config['CONFIG']['facter_ver'] = @options[:facter]
|
58
|
+
config['CONFIG']['hiera_ver'] = @options[:hiera]
|
59
|
+
config['CONFIG']['hiera_puppet_ver'] = @options[:hiera_puppet]
|
60
|
+
end
|
61
|
+
# need to load expect versions of PE binaries
|
62
|
+
config
|
63
|
+
end
|
64
|
+
|
65
|
+
def is_pe?
|
66
|
+
@is_pe ||= @options[:type] =~ /pe/ ? true : false
|
67
|
+
unless ENV['IS_PE'].nil?
|
68
|
+
@is_pe ||= ENV['IS_PE'] == 'true'
|
69
|
+
end
|
70
|
+
@is_pe
|
71
|
+
end
|
72
|
+
|
73
|
+
def puppet_enterprise_dir
|
74
|
+
@pe_dir ||= ENV['pe_dist_dir'] || '/opt/enterprise/dists'
|
75
|
+
end
|
76
|
+
|
77
|
+
def load_pe_version
|
78
|
+
dist_dir = puppet_enterprise_dir
|
79
|
+
version_file = ENV['pe_version_file'] || 'LATEST'
|
80
|
+
version = ""
|
81
|
+
begin
|
82
|
+
open("#{dist_dir}/#{version_file}") do |file|
|
83
|
+
while line = file.gets
|
84
|
+
if /(\w.*)/ =~ line then
|
85
|
+
version = $1.strip
|
86
|
+
@logger.debug "Found LATEST: Puppet Enterprise Version #{version}"
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
rescue
|
91
|
+
version = 'unknown'
|
92
|
+
end
|
93
|
+
return version
|
94
|
+
end
|
95
|
+
|
96
|
+
def puppet_enterprise_version
|
97
|
+
@pe_ver ||= load_pe_version if is_pe?
|
98
|
+
end
|
99
|
+
|
100
|
+
def load_pe_version_win
|
101
|
+
dist_dir = puppet_enterprise_dir
|
102
|
+
version_file = ENV['pe_version_file'] || 'LATEST-win'
|
103
|
+
version = ""
|
104
|
+
begin
|
105
|
+
open("#{dist_dir}/#{version_file}") do |file|
|
106
|
+
while line = file.gets
|
107
|
+
if /(\w.*)/ =~ line then
|
108
|
+
version=$1.strip
|
109
|
+
@logger.debug "Found LATEST: Puppet Enterprise Windows Version #{version}"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
rescue
|
114
|
+
version = 'unknown'
|
115
|
+
end
|
116
|
+
return version
|
117
|
+
end
|
118
|
+
|
119
|
+
def puppet_enterprise_version_win
|
120
|
+
@pe_ver_win ||= load_pe_version_win if is_pe?
|
121
|
+
end
|
122
|
+
|
123
|
+
# Print out test configuration
|
124
|
+
def dump
|
125
|
+
# Access "platform" for each host
|
126
|
+
@config["HOSTS"].each_key do|host|
|
127
|
+
@logger.notify "Platform for #{host} #{@config["HOSTS"][host]['platform']}"
|
128
|
+
end
|
129
|
+
|
130
|
+
# Access "roles" for each host
|
131
|
+
@config["HOSTS"].each_key do|host|
|
132
|
+
@config["HOSTS"][host]['roles'].each do |role|
|
133
|
+
@logger.notify "Role for #{host} #{role}"
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
# Print out Ruby versions
|
138
|
+
@config["HOSTS"].each_key do|host|
|
139
|
+
@logger.notify "Ruby version for #{host} #{@config["HOSTS"][host][:ruby_ver]}"
|
140
|
+
end
|
141
|
+
|
142
|
+
# Access @config keys/values
|
143
|
+
@config["CONFIG"].each_key do|cfg|
|
144
|
+
@logger.notify "Config Key|Val: #{cfg} #{@config["CONFIG"][cfg].inspect}"
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
@@ -0,0 +1,288 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
require 'rexml/document'
|
3
|
+
require 'fileutils'
|
4
|
+
%w(test_case logger).each do |lib|
|
5
|
+
begin
|
6
|
+
require "beaker/#{lib}"
|
7
|
+
rescue LoadError
|
8
|
+
require File.expand_path(File.join(File.dirname(__FILE__), lib))
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module Beaker
|
13
|
+
# This Class is in need of some cleaning up beyond what can be quickly done.
|
14
|
+
# Things to keep in mind:
|
15
|
+
# * Global State Change
|
16
|
+
# * File Creation Relative to CWD -- Should be a config option
|
17
|
+
# * Better Method Documentation
|
18
|
+
class TestSuite
|
19
|
+
attr_reader :name, :options, :config, :fail_mode
|
20
|
+
|
21
|
+
def initialize(name, hosts, options, config, fail_mode = nil)
|
22
|
+
@name = name.gsub(/\s+/, '-')
|
23
|
+
@hosts = hosts
|
24
|
+
@run = false
|
25
|
+
@options = options
|
26
|
+
@config = config
|
27
|
+
@fail_mode = @options[:fail_mode] || fail_mode
|
28
|
+
@logger = options[:logger]
|
29
|
+
|
30
|
+
@test_cases = []
|
31
|
+
@test_files = []
|
32
|
+
|
33
|
+
options[:tests].each do |root|
|
34
|
+
if File.file? root then
|
35
|
+
@test_files << root
|
36
|
+
else
|
37
|
+
@test_files += Dir.glob(
|
38
|
+
File.join(root, "**/*.rb")
|
39
|
+
).select { |f| File.file?(f) }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
report_and_raise(@logger, RuntimeError.new("#{@name}: no test files found..."), "TestSuite: initialize") if @test_files.empty?
|
43
|
+
|
44
|
+
@test_files = @test_files.sort
|
45
|
+
rescue => e
|
46
|
+
report_and_raise(@logger, e, "TestSuite: initialize")
|
47
|
+
end
|
48
|
+
|
49
|
+
def run
|
50
|
+
@run = true
|
51
|
+
@start_time = Time.now
|
52
|
+
|
53
|
+
configure_logging
|
54
|
+
|
55
|
+
@test_files.each do |test_file|
|
56
|
+
@logger.notify
|
57
|
+
@logger.notify "Begin #{test_file}"
|
58
|
+
start = Time.now
|
59
|
+
test_case = TestCase.new(@hosts, @logger, config, options, test_file).run_test
|
60
|
+
duration = Time.now - start
|
61
|
+
@test_cases << test_case
|
62
|
+
|
63
|
+
state = test_case.test_status == :skip ? 'skipp' : test_case.test_status
|
64
|
+
msg = "#{test_file} #{state}ed in %.2f seconds" % duration.to_f
|
65
|
+
case test_case.test_status
|
66
|
+
when :pass
|
67
|
+
@logger.success msg
|
68
|
+
when :skip
|
69
|
+
@logger.debug msg
|
70
|
+
when :fail
|
71
|
+
@logger.error msg
|
72
|
+
break if fail_mode #all failure modes cause us to kick out early on failure
|
73
|
+
when :error
|
74
|
+
@logger.warn msg
|
75
|
+
break if fail_mode #all failure modes cause use to kick out early on error
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
# REVISIT: This changes global state, breaking logging in any future runs
|
80
|
+
# of the suite – or, at least, making them highly confusing for anyone who
|
81
|
+
# has not studied the implementation in detail. --daniel 2011-03-14
|
82
|
+
summarize
|
83
|
+
write_junit_xml if options[:xml]
|
84
|
+
|
85
|
+
# Allow chaining operations...
|
86
|
+
return self
|
87
|
+
end
|
88
|
+
|
89
|
+
def run_and_raise_on_failure
|
90
|
+
begin
|
91
|
+
run
|
92
|
+
return self if success?
|
93
|
+
rescue => e
|
94
|
+
#failed during run
|
95
|
+
report_and_raise(@logger, e, "TestSuite :run_and_raise_on_failure")
|
96
|
+
else
|
97
|
+
#failed during test
|
98
|
+
report_and_raise(@logger, RuntimeError.new("Failed while running the #{name} suite"), "TestSuite: report_and_raise_on_failure")
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def fail_without_test_run
|
103
|
+
report_and_raise(@logger, RuntimeError.new("#{@name}: you have not run the tests yet"), "TestSuite: fail_without_test_run") unless @run
|
104
|
+
end
|
105
|
+
|
106
|
+
def success?
|
107
|
+
fail_without_test_run
|
108
|
+
sum_failed == 0
|
109
|
+
end
|
110
|
+
|
111
|
+
def failed?
|
112
|
+
!success?
|
113
|
+
end
|
114
|
+
|
115
|
+
def test_count
|
116
|
+
@test_count ||= @test_cases.length
|
117
|
+
end
|
118
|
+
|
119
|
+
def passed_tests
|
120
|
+
@passed_tests ||= @test_cases.select { |c| c.test_status == :pass }.length
|
121
|
+
end
|
122
|
+
|
123
|
+
def errored_tests
|
124
|
+
@errored_tests ||= @test_cases.select { |c| c.test_status == :error }.length
|
125
|
+
end
|
126
|
+
|
127
|
+
def failed_tests
|
128
|
+
@failed_tests ||= @test_cases.select { |c| c.test_status == :fail }.length
|
129
|
+
end
|
130
|
+
|
131
|
+
def skipped_tests
|
132
|
+
@skipped_tests ||= @test_cases.select { |c| c.test_status == :skip }.length
|
133
|
+
end
|
134
|
+
|
135
|
+
def pending_tests
|
136
|
+
@pending_tests ||= @test_cases.select {|c| c.test_status == :pending}.length
|
137
|
+
end
|
138
|
+
|
139
|
+
private
|
140
|
+
|
141
|
+
def sum_failed
|
142
|
+
@sum_failed ||= failed_tests + errored_tests
|
143
|
+
end
|
144
|
+
|
145
|
+
def write_junit_xml
|
146
|
+
# This should be a configuration option
|
147
|
+
File.directory?('junit') or FileUtils.mkdir('junit')
|
148
|
+
|
149
|
+
begin
|
150
|
+
doc = REXML::Document.new
|
151
|
+
doc.add(REXML::XMLDecl.new(1.0))
|
152
|
+
|
153
|
+
suite = REXML::Element.new('testsuite', doc)
|
154
|
+
suite.add_attribute('name', name)
|
155
|
+
suite.add_attribute('tests', test_count)
|
156
|
+
suite.add_attribute('errors', errored_tests)
|
157
|
+
suite.add_attribute('failures', failed_tests)
|
158
|
+
suite.add_attribute('skip', skipped_tests)
|
159
|
+
suite.add_attribute('pending', pending_tests)
|
160
|
+
|
161
|
+
@test_cases.each do |test|
|
162
|
+
item = REXML::Element.new('testcase', suite)
|
163
|
+
item.add_attribute('classname', File.dirname(test.path))
|
164
|
+
item.add_attribute('name', File.basename(test.path))
|
165
|
+
item.add_attribute('time', test.runtime)
|
166
|
+
|
167
|
+
# Did we fail? If so, report that.
|
168
|
+
# We need to remove the escape character from colorized text, the
|
169
|
+
# substitution of other entities is handled well by Rexml
|
170
|
+
if test.test_status == :fail || test.test_status == :error then
|
171
|
+
status = REXML::Element.new('failure', item)
|
172
|
+
status.add_attribute('type', test.test_status.to_s)
|
173
|
+
if test.exception then
|
174
|
+
status.add_attribute('message', test.exception.to_s.gsub(/\e/, ''))
|
175
|
+
status.text = test.exception.backtrace.join("\n")
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
if test.stdout then
|
180
|
+
REXML::Element.new('system-out', item).text =
|
181
|
+
test.stdout.gsub(/\e/, '')
|
182
|
+
end
|
183
|
+
|
184
|
+
if test.stderr then
|
185
|
+
text = REXML::Element.new('system-err', item)
|
186
|
+
text.text = test.stderr.gsub(/\e/, '')
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
# junit/name.xml will be created in a directory relative to the CWD
|
191
|
+
# -- JLS 2/12
|
192
|
+
File.open("junit/#{name}.xml", 'w') { |fh| doc.write(fh) }
|
193
|
+
rescue Exception => e
|
194
|
+
@logger.error "failure in XML output:\n#{e.to_s}\n" + e.backtrace.join("\n")
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
def summarize
|
199
|
+
fail_without_test_run
|
200
|
+
|
201
|
+
summary_logger = Logger.new(log_path("#{name}-summary.txt"), STDOUT)
|
202
|
+
|
203
|
+
summary_logger.notify <<-HEREDOC
|
204
|
+
Test Suite: #{name} @ #{@start_time}
|
205
|
+
|
206
|
+
- Host Configuration Summary -
|
207
|
+
HEREDOC
|
208
|
+
|
209
|
+
config.dump
|
210
|
+
|
211
|
+
elapsed_time = @test_cases.inject(0.0) {|r, t| r + t.runtime.to_f }
|
212
|
+
average_test_time = elapsed_time / test_count
|
213
|
+
|
214
|
+
summary_logger.notify %Q[
|
215
|
+
|
216
|
+
- Test Case Summary for suite '#{name}' -
|
217
|
+
Total Suite Time: %.2f seconds
|
218
|
+
Average Test Time: %.2f seconds
|
219
|
+
Attempted: #{test_count}
|
220
|
+
Passed: #{passed_tests}
|
221
|
+
Failed: #{failed_tests}
|
222
|
+
Errored: #{errored_tests}
|
223
|
+
Skipped: #{skipped_tests}
|
224
|
+
Pending: #{pending_tests}
|
225
|
+
|
226
|
+
- Specific Test Case Status -
|
227
|
+
] % [elapsed_time, average_test_time]
|
228
|
+
|
229
|
+
grouped_summary = @test_cases.group_by{|test_case| test_case.test_status }
|
230
|
+
|
231
|
+
summary_logger.notify "Failed Tests Cases:"
|
232
|
+
(grouped_summary[:fail] || []).each do |test_case|
|
233
|
+
print_test_failure(test_case)
|
234
|
+
end
|
235
|
+
|
236
|
+
summary_logger.notify "Errored Tests Cases:"
|
237
|
+
(grouped_summary[:error] || []).each do |test_case|
|
238
|
+
print_test_failure(test_case)
|
239
|
+
end
|
240
|
+
|
241
|
+
summary_logger.notify "Skipped Tests Cases:"
|
242
|
+
(grouped_summary[:skip] || []).each do |test_case|
|
243
|
+
print_test_failure(test_case)
|
244
|
+
end
|
245
|
+
|
246
|
+
summary_logger.notify "Pending Tests Cases:"
|
247
|
+
(grouped_summary[:pending] || []).each do |test_case|
|
248
|
+
print_test_failure(test_case)
|
249
|
+
end
|
250
|
+
|
251
|
+
summary_logger.notify("\n\n")
|
252
|
+
end
|
253
|
+
|
254
|
+
def print_test_failure(test_case)
|
255
|
+
test_reported = if test_case.exception
|
256
|
+
"reported: #{test_case.exception.inspect}"
|
257
|
+
else
|
258
|
+
test_case.test_status
|
259
|
+
end
|
260
|
+
@logger.notify " Test Case #{test_case.path} #{test_reported}"
|
261
|
+
end
|
262
|
+
|
263
|
+
def log_path(name)
|
264
|
+
@@log_dir ||= File.join("log", @start_time.strftime("%F_%T"))
|
265
|
+
unless File.directory?(@@log_dir) then
|
266
|
+
FileUtils.mkdir_p(@@log_dir)
|
267
|
+
FileUtils.cp(options[:config],(File.join(@@log_dir,"config.yml")))
|
268
|
+
|
269
|
+
latest = File.join("log", "latest")
|
270
|
+
if !File.exist?(latest) or File.symlink?(latest) then
|
271
|
+
File.delete(latest) if File.exist?(latest)
|
272
|
+
File.symlink(File.basename(@@log_dir), latest)
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
File.join('log', 'latest', name)
|
277
|
+
end
|
278
|
+
|
279
|
+
# Setup log dir
|
280
|
+
def configure_logging
|
281
|
+
@logger.add_destination(log_path("#{@name}-run.log"))
|
282
|
+
#
|
283
|
+
# This is an awful hack to maintain backward compatibility until tests
|
284
|
+
# are ported to use logger.
|
285
|
+
Beaker.const_set(:Log, @logger) unless defined?( Log )
|
286
|
+
end
|
287
|
+
end
|
288
|
+
end
|
data/lib/beaker/utils.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
module Beaker
|
2
|
+
module Utils
|
3
|
+
class NTPControl
|
4
|
+
NTPSERVER = 'pool.ntp.org'
|
5
|
+
def initialize(options, hosts)
|
6
|
+
@options = options.dup
|
7
|
+
@hosts = hosts
|
8
|
+
@logger = options[:logger]
|
9
|
+
end
|
10
|
+
|
11
|
+
def timesync
|
12
|
+
@logger.notify "Update system time sync"
|
13
|
+
@logger.notify "run ntpdate against NTP pool systems"
|
14
|
+
@hosts.each do |host|
|
15
|
+
success=FALSE
|
16
|
+
if host['platform'].include? 'solaris-10'
|
17
|
+
host.exec(Command.new("sleep 10 && ntpdate -w #{NTPSERVER}"))
|
18
|
+
elsif host['platform'].include? 'windows'
|
19
|
+
# The exit code of 5 is for Windows 2008 systems where the w32tm /register command
|
20
|
+
# is not actually necessary.
|
21
|
+
host.exec(Command.new("w32tm /register"), :acceptable_exit_codes => [0,5])
|
22
|
+
host.exec(Command.new("net start w32time"), :acceptable_exit_codes => [0,2])
|
23
|
+
host.exec(Command.new("w32tm /config /manualpeerlist:#{NTPSERVER} /syncfromflags:manual /update"))
|
24
|
+
host.exec(Command.new("w32tm /resync"))
|
25
|
+
else
|
26
|
+
count=0
|
27
|
+
until success do
|
28
|
+
count+=1
|
29
|
+
raise "ntp time sync failed after #{count} tries" and break if count > 3
|
30
|
+
if host.exec(Command.new("ntpdate -t 20 #{NTPSERVER}")).exit_code == 0
|
31
|
+
success=TRUE
|
32
|
+
end
|
33
|
+
end
|
34
|
+
@logger.notify "NTP date succeeded after #{count} tries"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
rescue => e
|
38
|
+
report_and_raise(@logger, e, "timesync (--ntp)")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|