beaker 1.16.0 → 1.17.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +8 -8
  2. data/CONTRIBUTING.md +90 -0
  3. data/HISTORY.md +654 -2
  4. data/beaker.gemspec +1 -0
  5. data/lib/beaker/answers/version34.rb +4 -0
  6. data/lib/beaker/cli.rb +49 -2
  7. data/lib/beaker/dsl/helpers.rb +356 -196
  8. data/lib/beaker/dsl/install_utils.rb +135 -16
  9. data/lib/beaker/dsl/patterns.rb +37 -0
  10. data/lib/beaker/dsl/roles.rb +29 -0
  11. data/lib/beaker/dsl.rb +2 -1
  12. data/lib/beaker/host/unix.rb +14 -10
  13. data/lib/beaker/host/windows.rb +2 -0
  14. data/lib/beaker/host.rb +96 -1
  15. data/lib/beaker/host_prebuilt_steps.rb +41 -51
  16. data/lib/beaker/hypervisor/aws_sdk.rb +80 -16
  17. data/lib/beaker/hypervisor/ec2_helper.rb +1 -1
  18. data/lib/beaker/logger.rb +17 -0
  19. data/lib/beaker/options/command_line_parser.rb +3 -0
  20. data/lib/beaker/options/hosts_file_parser.rb +7 -4
  21. data/lib/beaker/options/options_hash.rb +2 -2
  22. data/lib/beaker/options/parser.rb +1 -1
  23. data/lib/beaker/options/presets.rb +128 -83
  24. data/lib/beaker/perf.rb +58 -0
  25. data/lib/beaker/shared/host_manager.rb +81 -0
  26. data/lib/beaker/shared.rb +2 -2
  27. data/lib/beaker/ssh_connection.rb +14 -7
  28. data/lib/beaker/test_case.rb +13 -0
  29. data/lib/beaker/test_suite.rb +23 -5
  30. data/lib/beaker/version.rb +1 -1
  31. data/lib/beaker.rb +1 -1
  32. data/spec/beaker/answers_spec.rb +13 -8
  33. data/spec/beaker/dsl/ezbake_utils_spec.rb +8 -9
  34. data/spec/beaker/dsl/helpers_spec.rb +299 -51
  35. data/spec/beaker/dsl/install_utils_spec.rb +75 -10
  36. data/spec/beaker/dsl/roles_spec.rb +36 -1
  37. data/spec/beaker/host_prebuilt_steps_spec.rb +21 -5
  38. data/spec/beaker/host_spec.rb +187 -23
  39. data/spec/beaker/hypervisor/ec2_helper_spec.rb +4 -4
  40. data/spec/beaker/hypervisor/vagrant_spec.rb +1 -1
  41. data/spec/beaker/options/hosts_file_parser_spec.rb +5 -0
  42. data/spec/beaker/options/options_hash_spec.rb +2 -2
  43. data/spec/beaker/options/parser_spec.rb +6 -0
  44. data/spec/beaker/options/presets_spec.rb +18 -2
  45. data/spec/beaker/perf_spec.rb +87 -0
  46. data/spec/beaker/shared/{host_role_parser_spec.rb → host_manager_spec.rb} +36 -5
  47. data/spec/beaker/test_suite_spec.rb +4 -3
  48. data/spec/matchers.rb +31 -3
  49. data/spec/mocks.rb +31 -25
  50. metadata +24 -5
  51. data/lib/beaker/shared/host_role_parser.rb +0 -36
@@ -1,16 +1,19 @@
1
- [ 'command' ].each do |lib|
1
+ [ 'command', "dsl/patterns" ].each do |lib|
2
2
  require "beaker/#{lib}"
3
3
  end
4
4
 
5
5
  module Beaker
6
6
  #Provides convienience methods for commonly run actions on hosts
7
7
  module HostPrebuiltSteps
8
+ include Beaker::DSL::Patterns
9
+
8
10
  NTPSERVER = 'pool.ntp.org'
9
11
  SLEEPWAIT = 5
10
12
  TRIES = 5
11
13
  UNIX_PACKAGES = ['curl', 'ntpdate']
12
14
  WINDOWS_PACKAGES = ['curl']
13
15
  SLES_PACKAGES = ['curl', 'ntp']
16
+ DEBIAN_PACKAGES = ['curl', 'ntpdate', 'lsb-release']
14
17
  ETC_HOSTS_PATH = "/etc/hosts"
15
18
  ETC_HOSTS_PATH_SOLARIS = "/etc/inet/hosts"
16
19
  ROOT_KEYS_SCRIPT = "https://raw.githubusercontent.com/puppetlabs/puppetlabs-sshkeys/master/templates/scripts/manage_root_authorized_keys"
@@ -19,14 +22,12 @@ module Beaker
19
22
  IPS_PKG_REPO="http://solaris-11-internal-repo.delivery.puppetlabs.net"
20
23
 
21
24
  #Run timesync on the provided hosts
22
- # @param [Host, Array<Host>, String, Symbol] host One or more hosts to act upon
25
+ # @param [Host, Array<Host>] host One or more hosts to act upon
23
26
  # @param [Hash{Symbol=>String}] opts Options to alter execution.
24
27
  # @option opts [Beaker::Logger] :logger A {Beaker::Logger} object
25
28
  def timesync host, opts
26
29
  logger = opts[:logger]
27
- if host.is_a? Array
28
- host.map { |h| timesync(h, opts) }
29
- else
30
+ block_on host do |host|
30
31
  logger.notify "Update system time sync for '#{host.name}'"
31
32
  if host['platform'].include? 'windows'
32
33
  # The exit code of 5 is for Windows 2008 systems where the w32tm /register command
@@ -68,16 +69,19 @@ module Beaker
68
69
 
69
70
  #Validate that hosts are prepared to be used as SUTs, if packages are missing attempt to
70
71
  #install them. Verifies the presence of #{HostPrebuiltSteps::UNIX_PACKAGES} on unix platform hosts,
71
- #{HostPrebuiltSteps::SLES_PACKAGES} on SUSE platform hosts and {HostPrebuiltSteps::WINDOWS_PACKAGES} on windows
72
+ #{HostPrebuiltSteps::SLES_PACKAGES} on SUSE platform hosts, #{HostPrebuiltSteps::DEBIAN_PACKAGES on debian platform
73
+ #hosts and {HostPrebuiltSteps::WINDOWS_PACKAGES} on windows
72
74
  #platforms.
73
75
  # @param [Host, Array<Host>, String, Symbol] host One or more hosts to act upon
74
76
  # @param [Hash{Symbol=>String}] opts Options to alter execution.
75
77
  # @option opts [Beaker::Logger] :logger A {Beaker::Logger} object
76
78
  def validate_host host, opts
77
79
  logger = opts[:logger]
78
- if host.is_a? Array
79
- host.map { |h| validate_host(h, opts) }
80
- else
80
+ if opts[:collect_perf_data]
81
+ UNIX_PACKAGES << "sysstat" if !UNIX_PACKAGES.include? "sysstat"
82
+ SLES_PACKAGES << "sysstat" if !SLES_PACKAGES.include? "sysstat"
83
+ end
84
+ block_on host do |host|
81
85
  case
82
86
  when host['platform'] =~ /sles-/
83
87
  SLES_PACKAGES.each do |pkg|
@@ -85,13 +89,19 @@ module Beaker
85
89
  host.install_package pkg
86
90
  end
87
91
  end
92
+ when host['platform'] =~ /debian/
93
+ DEBIAN_PACKAGES.each do |pkg|
94
+ if not host.check_for_package pkg
95
+ host.install_package pkg
96
+ end
97
+ end
88
98
  when host['platform'] =~ /windows/
89
99
  WINDOWS_PACKAGES.each do |pkg|
90
100
  if not host.check_for_package pkg
91
101
  host.install_package pkg
92
102
  end
93
103
  end
94
- when host['platform'] !~ /aix|solaris|windows|sles-|osx-/
104
+ when host['platform'] !~ /debian|aix|solaris|windows|sles-|osx-/
95
105
  UNIX_PACKAGES.each do |pkg|
96
106
  if not host.check_for_package pkg
97
107
  host.install_package pkg
@@ -106,7 +116,7 @@ module Beaker
106
116
  #Install a set of authorized keys using {HostPrebuiltSteps::ROOT_KEYS_SCRIPT}. This is a
107
117
  #convenience method to allow for easy login to hosts after they have been provisioned with
108
118
  #Beaker.
109
- # @param [Host, Array<Host>, String, Symbol] host One or more hosts to act upon
119
+ # @param [Host, Array<Host>] host One or more hosts to act upon
110
120
  # @param [Hash{Symbol=>String}] opts Options to alter execution.
111
121
  # @option opts [Beaker::Logger] :logger A {Beaker::Logger} object
112
122
  def sync_root_keys host, opts
@@ -115,9 +125,7 @@ module Beaker
115
125
  # but we're deliberately taking the approach of "assume it will work, fix it
116
126
  # when reality dictates otherwise"
117
127
  logger = opts[:logger]
118
- if host.is_a? Array
119
- host.map { |h| sync_root_keys(h, opts) }
120
- else
128
+ block_on host do |host|
121
129
  logger.notify "Sync root authorized_keys from github on #{host.name}"
122
130
  # Allow all exit code, as this operation is unlikely to cause problems if it fails.
123
131
  if host['platform'].include? 'solaris'
@@ -154,11 +162,9 @@ module Beaker
154
162
 
155
163
  #Run 'apt-get update' on the provided host or hosts. If the platform of the provided host is not
156
164
  #ubuntu or debian do nothing.
157
- # @param [Host, Array<Host>, String, Symbol] host One or more hosts to act upon
158
- def apt_get_update host
159
- if host.is_a? Array
160
- host.map { |h| apt_get_update(h) }
161
- else
165
+ # @param [Host, Array<Host>] hosts One or more hosts to act upon
166
+ def apt_get_update hosts
167
+ block_on hosts do |host|
162
168
  if host[:platform] =~ /(ubuntu)|(debian)/
163
169
  host.exec(Command.new("apt-get update"))
164
170
  end
@@ -166,13 +172,11 @@ module Beaker
166
172
  end
167
173
 
168
174
  #Create a file on host or hosts at the provided file path with the provided file contents.
169
- # @param [Host, Array<Host>, String, Symbol] host One or more hosts to act upon
175
+ # @param [Host, Array<Host>] host One or more hosts to act upon
170
176
  # @param [String] file_path The path at which the new file will be created on the host or hosts.
171
177
  # @param [String] file_content The contents of the file to be created on the host or hosts.
172
178
  def copy_file_to_remote(host, file_path, file_content)
173
- if host.is_a? Array
174
- host.map { |h| copy_file_to_remote(h, file_path, file_contents) }
175
- else
179
+ block_on host do |host|
176
180
  Tempfile.open 'beaker' do |tempfile|
177
181
  File.open(tempfile.path, 'w') {|file| file.puts file_content }
178
182
 
@@ -185,16 +189,14 @@ module Beaker
185
189
  # proxy {HostPrebuiltSteps::APT_CFG} proxy, alter pkg on solaris-11 host or hosts
186
190
  # to point to interal Puppetlabs proxy {HostPrebuiltSteps::IPS_PKG_REPO}. Do nothing
187
191
  # on non-ubuntu, debian or solaris-11 platform host or hosts.
188
- # @param [Host, Array<Host>, String, Symbol] host One or more hosts to act upon
192
+ # @param [Host, Array<Host>] host One or more hosts to act upon
189
193
  # @param [Hash{Symbol=>String}] opts Options to alter execution.
190
194
  # @option opts [Beaker::Logger] :logger A {Beaker::Logger} object
191
195
  def proxy_config( host, opts )
192
196
  # repo_proxy
193
197
  # supports ubuntu, debian and solaris platforms
194
198
  logger = opts[:logger]
195
- if host.is_a? Array
196
- host.map { |h| proxy_config(h, opts) }
197
- else
199
+ block_on host do |host|
198
200
  case
199
201
  when host['platform'] =~ /ubuntu/
200
202
  host.exec(Command.new("if test -f /etc/apt/apt.conf; then mv /etc/apt/apt.conf /etc/apt/apt.conf.bk; fi"))
@@ -216,7 +218,7 @@ module Beaker
216
218
  end
217
219
 
218
220
  #Install EPEL on host or hosts with platform = /el-(5|6)/. Do nothing on host or hosts of other platforms.
219
- # @param [Host, Array<Host>, String, Symbol] host One or more hosts to act upon
221
+ # @param [Host, Array<Host>] host One or more hosts to act upon
220
222
  # @param [Hash{Symbol=>String}] opts Options to alter execution.
221
223
  # @option opts [Boolean] :debug If true, print verbose rpm information when installing EPEL
222
224
  # @option opts [Beaker::Logger] :logger A {Beaker::Logger} object
@@ -225,9 +227,7 @@ module Beaker
225
227
  #only supports el-* platforms
226
228
  logger = opts[:logger]
227
229
  debug_opt = opts[:debug] ? 'vh' : ''
228
- if host.is_a? Array
229
- host.map { |h| add_el_extras(h, opts) }
230
- else
230
+ block_on host do |host|
231
231
  case
232
232
  when host['platform'] =~ /el-(5|6)/
233
233
  result = host.exec(Command.new('rpm -qa | grep epel-release'), :acceptable_exit_codes => [0,1])
@@ -276,14 +276,12 @@ module Beaker
276
276
  end
277
277
 
278
278
  #Make it possible to log in as root by copying the current users ssh keys to the root account
279
- # @param [Host, Array<Host>, String, Symbol] host One or more hosts to act upon
279
+ # @param [Host, Array<Host>] host One or more hosts to act upon
280
280
  # @param [Hash{Symbol=>String}] opts Options to alter execution.
281
281
  # @option opts [Beaker::Logger] :logger A {Beaker::Logger} object
282
282
  def copy_ssh_to_root host, opts
283
283
  logger = opts[:logger]
284
- if host.is_a? Array
285
- host.map { |h| copy_ssh_to_root(h, opts) }
286
- else
284
+ block_on host do |host|
287
285
  logger.debug "Give root a copy of current user's keys, on #{host.name}"
288
286
  if host['platform'] =~ /windows/
289
287
  host.exec(Command.new('cp -r .ssh /cygdrive/c/Users/Administrator/.'))
@@ -296,7 +294,7 @@ module Beaker
296
294
 
297
295
  #Update /etc/hosts to make it possible for each provided host to reach each other host by name.
298
296
  #Assumes that each provided host has host[:ip] set.
299
- # @param [Host, Array<Host>, String, Symbol] hosts An array of hosts to act upon
297
+ # @param [Host, Array<Host>] hosts An array of hosts to act upon
300
298
  # @param [Hash{Symbol=>String}] opts Options to alter execution.
301
299
  # @option opts [Beaker::Logger] :logger A {Beaker::Logger} object
302
300
  def hack_etc_hosts hosts, opts
@@ -310,14 +308,12 @@ module Beaker
310
308
  end
311
309
 
312
310
  #Update sshd_config on debian, ubuntu, centos, el, redhat and fedora boxes to allow for root login, does nothing on other platfoms
313
- # @param [Host, Array<Host>, String, Symbol] host One or more hosts to act upon
311
+ # @param [Host, Array<Host>] host One or more hosts to act upon
314
312
  # @param [Hash{Symbol=>String}] opts Options to alter execution.
315
313
  # @option opts [Beaker::Logger] :logger A {Beaker::Logger} object
316
314
  def enable_root_login host, opts
317
315
  logger = opts[:logger]
318
- if host.is_a? Array
319
- host.map { |h| copy_ssh_to_root(h, opts) }
320
- else
316
+ block_on host do |host|
321
317
  logger.debug "Update /etc/ssh/sshd_config to allow root login"
322
318
  host.exec(Command.new("sudo su -c \"sed -i 's/PermitRootLogin no/PermitRootLogin yes/' /etc/ssh/sshd_config\""), {:pty => true}
323
319
  )
@@ -333,14 +329,12 @@ module Beaker
333
329
  end
334
330
 
335
331
  #Disable SELinux on centos, does nothing on other platforms
336
- # @param [Host, Array<Host>, String, Symbol] host One or more hosts to act upon
332
+ # @param [Host, Array<Host>] host One or more hosts to act upon
337
333
  # @param [Hash{Symbol=>String}] opts Options to alter execution.
338
334
  # @option opts [Beaker::Logger] :logger A {Beaker::Logger} object
339
335
  def disable_se_linux host, opts
340
336
  logger = opts[:logger]
341
- if host.is_a? Array
342
- host.map { |h| copy_ssh_to_root(h, opts) }
343
- else
337
+ block_on host do |host|
344
338
  if host['platform'] =~ /centos|el-|redhat|fedora/
345
339
  @logger.debug("Disabling se_linux on #{host.name}")
346
340
  host.exec(Command.new("sudo su -c \"setenforce 0\""), {:pty => true})
@@ -351,14 +345,12 @@ module Beaker
351
345
  end
352
346
 
353
347
  #Disable iptables on centos, does nothing on other platforms
354
- # @param [Host, Array<Host>, String, Symbol] host One or more hosts to act upon
348
+ # @param [Host, Array<Host>] host One or more hosts to act upon
355
349
  # @param [Hash{Symbol=>String}] opts Options to alter execution.
356
350
  # @option opts [Beaker::Logger] :logger A {Beaker::Logger} object
357
351
  def disable_iptables host, opts
358
352
  logger = opts[:logger]
359
- if host.is_a? Array
360
- host.map { |h| copy_ssh_to_root(h, opts) }
361
- else
353
+ block_on host do |host|
362
354
  if host['platform'] =~ /centos|el-|redhat|fedora/
363
355
  logger.debug("Disabling iptables on #{host.name}")
364
356
  host.exec(Command.new("sudo su -c \"/etc/init.d/iptables stop\""), {:pty => true})
@@ -377,9 +369,7 @@ module Beaker
377
369
  def package_proxy host, opts
378
370
  logger = opts[:logger]
379
371
 
380
- if host.is_a? Array
381
- host.map { |h| package_proxy(h, opts) }
382
- else
372
+ block_on host do |host|
383
373
  logger.debug("enabling proxy support on #{host.name}")
384
374
  case host['platform']
385
375
  when /ubuntu/, /debian/
@@ -10,6 +10,8 @@ module Beaker
10
10
  # It is built for full control, to reduce any other layers beyond the pure
11
11
  # vendor API.
12
12
  class AwsSdk < Beaker::Hypervisor
13
+ ZOMBIE = 3 #anything older than 3 hours is considered a zombie
14
+
13
15
  # Initialize AwsSdk hypervisor driver
14
16
  #
15
17
  # @param [Array<Beaker::Host>] hosts Array of Beaker::Host objects
@@ -47,6 +49,9 @@ module Beaker
47
49
  # Wait for each node to reach status :running
48
50
  wait_for_status(:running)
49
51
 
52
+ # Add metadata tags to each instance
53
+ add_tags()
54
+
50
55
  # Grab the ip addresses and dns from EC2 for each instance to use for ssh
51
56
  populate_dns()
52
57
 
@@ -83,6 +88,43 @@ module Beaker
83
88
  nil #void
84
89
  end
85
90
 
91
+ #Shutdown and destroy ec2 instances idenfitied by key that have been alive longer than ZOMBIE hours.
92
+ #@param [Integer] max_age The age in hours that a machine needs to be older than to be considered a zombie
93
+ #@param [String] key The key_name to match for
94
+ def kill_zombies(max_age = ZOMBIE, key = key_name)
95
+ @logger.notify("aws-sdk: Kill Zombies!")
96
+ #examine all available regions
97
+ @ec2.regions.each do |region|
98
+ @logger.debug "Reviewing: #{region.name}"
99
+ @ec2.regions[region.name].instances.each do |instance|
100
+ if (instance.key_name =~ /#{key}/) and (instance.launch_time + (ZOMBIE*60*60)) < Time.now and instance.status.to_s !~ /terminated/
101
+ @logger.debug "Kill! #{instance.id}: #{instance.key_name} (Current status: #{instance.status})"
102
+ begin
103
+ instance.terminate()
104
+ rescue AWS::EC2::Errors => e
105
+ @logger.debug "Failed to remove instance: #{instance.id}, #{e}"
106
+ end
107
+ end
108
+ end
109
+ # Occasionaly, tearing down ec2 instances leaves orphaned EBS volumes behind -- these stack up quickly.
110
+ # This simply looks for EBS volumes that are not in use
111
+ # Note: don't use volumes.each here as that funtion doesn't allow proper rescue from error states
112
+ volumes = @ec2.regions[region.name].volumes.map { |vol| vol.id }
113
+ volumes.each do |vol|
114
+ begin
115
+ vol = @ec2.regions[region.name].volumes[vol]
116
+ if ( vol.status.to_s =~ /available/ )
117
+ @logger.debug "Tear down available volume: #{vol.id}"
118
+ vol.delete()
119
+ end
120
+ rescue AWS::EC2::Errors::InvalidVolume::NotFound => e
121
+ @logger.debug "Failed to remove volume: #{vol.id}, #{e}"
122
+ end
123
+ end
124
+ end
125
+
126
+ end
127
+
86
128
  # Launch all nodes
87
129
  #
88
130
  # This is where the main launching work occurs for each node. Here we take
@@ -157,13 +199,6 @@ module Beaker
157
199
  # manipulated by 'cleanup' for example.
158
200
  host['instance'] = instance
159
201
 
160
- # Define tags for the instance
161
- @logger.notify("aws-sdk: Add tags")
162
- instance.add_tag("jenkins_build_url", :value => @options[:jenkins_build_url])
163
- instance.add_tag("Name", :value => host.name)
164
- instance.add_tag("department", :value => @options[:department])
165
- instance.add_tag("project", :value => @options[:project])
166
-
167
202
  @logger.notify("aws-sdk: Launched #{host.name} (#{amitype}:#{amisize}) using snapshot/image_type #{image_type}")
168
203
  end
169
204
 
@@ -198,23 +233,41 @@ module Beaker
198
233
  backoff_sleep(tries)
199
234
  end
200
235
 
201
- # Set the IP to be the dns_name of the host, yes I know its not an IP.
202
- host['ip'] = instance.dns_name
203
236
  end
204
237
  end
205
238
 
206
- # Populate the hosts IP address and vmhostname entry from the EC2 dns_name
239
+ #Add metadata tags to all instances
240
+ #
241
+ # @return [void]
242
+ # @api private
243
+ def add_tags
244
+ @hosts.each do |host|
245
+ instance = host['instance']
246
+
247
+ # Define tags for the instance
248
+ @logger.notify("aws-sdk: Add tags for #{host.name}")
249
+ instance.add_tag("jenkins_build_url", :value => @options[:jenkins_build_url])
250
+ instance.add_tag("Name", :value => host.name)
251
+ instance.add_tag("department", :value => @options[:department])
252
+ instance.add_tag("project", :value => @options[:project])
253
+ end
254
+
255
+ nil
256
+ end
257
+
258
+ # Populate the hosts IP address from the EC2 dns_name
207
259
  #
208
260
  # @return [void]
209
261
  # @api private
210
262
  def populate_dns
211
263
  # Obtain the IP addresses and dns_name for each host
212
264
  @hosts.each do |host|
265
+ @logger.notify("aws-sdk: Populate DNS for #{host.name}")
213
266
  instance = host['instance']
214
- host['vmhostname'] = instance.dns_name
215
267
  host['ip'] = instance.ip_address
216
268
  host['private_ip'] = instance.private_ip_address
217
- @logger.notify("aws-sdk: name: #{host.name} vmhostname: #{host['vmhostname']} ip: #{host['ip']} private_ip: #{host['private_ip']}")
269
+ host['dns_name'] = instance.dns_name
270
+ @logger.notify("aws-sdk: name: #{host.name} ip: #{host['ip']} private_ip: #{host['private_ip']} dns_name: #{instance.dns_name}")
218
271
  end
219
272
 
220
273
  nil
@@ -225,10 +278,21 @@ module Beaker
225
278
  # @return [void]
226
279
  # @api private
227
280
  def configure_hosts
228
- base = "127.0.0.1\tlocalhost localhost.localdomain\n"
229
281
  @hosts.each do |host|
230
- hn = host.hostname
231
- etc_hosts = base + "#{host['private_ip']}\t#{hn} #{hn.split(".")[0]}\n"
282
+ etc_hosts = "127.0.0.1\tlocalhost localhost.localdomain\n"
283
+ name = host.name
284
+ domain = get_domain_name(host)
285
+ ip = host['private_ip']
286
+ etc_hosts += "#{ip}\t#{name} #{name}.#{domain} #{host['dns_name']}\n"
287
+ @hosts.each do |neighbor|
288
+ if neighbor == host
289
+ next
290
+ end
291
+ name = neighbor.name
292
+ domain = get_domain_name(neighbor)
293
+ ip = neighbor['ip']
294
+ etc_hosts += "#{ip}\t#{name} #{name}.#{domain} #{neighbor['dns_name']}\n"
295
+ end
232
296
  set_etc_hosts(host, etc_hosts)
233
297
  end
234
298
  end
@@ -240,7 +304,7 @@ module Beaker
240
304
  # @api private
241
305
  def set_hostnames
242
306
  @hosts.each do |host|
243
- host.exec(Command.new("hostname #{host['vmhostname']}"))
307
+ host.exec(Command.new("hostname #{host.name}"))
244
308
  end
245
309
  end
246
310
 
@@ -7,7 +7,7 @@ module Beaker
7
7
  # @return [Array<Number>] array of port numbers
8
8
  # @api private
9
9
  def self.amiports(roles)
10
- ports = [22]
10
+ ports = [22, 61613, 8139]
11
11
 
12
12
  if roles.include? 'database'
13
13
  ports << 8080
data/lib/beaker/logger.rb CHANGED
@@ -4,6 +4,10 @@ module Beaker
4
4
  # to a given destination (be it a string or file)
5
5
  #
6
6
  class Logger
7
+
8
+ #The results of the most recently run command
9
+ attr_accessor :last_result
10
+
7
11
  NORMAL = "\e[00;00m"
8
12
  BRIGHT_NORMAL = "\e[00;01m"
9
13
  BLACK = "\e[00;30m"
@@ -65,6 +69,9 @@ module Beaker
65
69
  else
66
70
  @log_level = :verbose
67
71
  end
72
+
73
+ @last_result = nil
74
+
68
75
  @destinations = []
69
76
 
70
77
  dests = args
@@ -164,6 +171,16 @@ module Beaker
164
171
  optionally_color GREY, string, false
165
172
  end
166
173
 
174
+ # Custom reporting for performance/sysstat messages
175
+ # Will not print unless we are at {LOG_LEVELS} 'debug' or higher.
176
+ # @param args[Array<String>] Strings to be reported
177
+ def perf_output *args
178
+ return unless is_debug?
179
+ strings = strip_colors_from args
180
+ string = strings.join
181
+ optionally_color MAGENTA, string, false
182
+ end
183
+
167
184
  # Report a debug message.
168
185
  # Will not print unless we are at {LOG_LEVELS} 'debug' or higher.
169
186
  # @param args[Array<String>] Strings to be reported
@@ -201,6 +201,9 @@ module Beaker
201
201
  #noop
202
202
  end
203
203
 
204
+ opts.on '--collect-perf-data', 'Use sysstat on linux hosts to collect performance and load data' do
205
+ @cmd_options[:collect_perf_data] = true
206
+ end
204
207
  end
205
208
 
206
209
  end
@@ -12,12 +12,16 @@ module Beaker
12
12
  #
13
13
  # @return [OptionsHash] The contents of the hosts file as an OptionsHash
14
14
  # @raise [ArgumentError] Raises if hosts_file_path is not a path to a file, or is not a valid YAML file
15
- def self.parse_hosts_file(hosts_file_path)
15
+ def self.parse_hosts_file(hosts_file_path = nil)
16
+ host_options = Beaker::Options::OptionsHash.new
17
+ host_options['HOSTS'] ||= {}
18
+ unless hosts_file_path
19
+ return host_options
20
+ end
16
21
  hosts_file_path = File.expand_path(hosts_file_path)
17
22
  unless File.exists?(hosts_file_path)
18
- raise ArgumentError, "Required host file '#{hosts_file_path}' does not exist!"
23
+ raise ArgumentError, "Host file '#{hosts_file_path}' does not exist!"
19
24
  end
20
- host_options = Beaker::Options::OptionsHash.new
21
25
  begin
22
26
  host_options = host_options.merge(YAML.load_file(hosts_file_path))
23
27
  rescue Psych::SyntaxError => e
@@ -25,7 +29,6 @@ module Beaker
25
29
  end
26
30
 
27
31
  # Make sure the roles array is present for all hosts
28
- host_options['HOSTS'] ||= {}
29
32
  host_options['HOSTS'].each_key do |host|
30
33
  host_options['HOSTS'][host]['roles'] ||= []
31
34
  end
@@ -42,7 +42,7 @@ module Beaker
42
42
 
43
43
  # Determine if type of ObjectHash is pe, defaults to true
44
44
  #
45
- # @example Use this method to return the value for a given key
45
+ # @example Use this method to test if the :type setting is pe
46
46
  # a['type'] = 'pe'
47
47
  # a.is_pe? == true
48
48
  #
@@ -98,7 +98,7 @@ module Beaker
98
98
  def rmerge base, hash
99
99
  return base unless hash.is_a?(Hash) || hash.is_a?(OptionsHash)
100
100
  hash.each do |key, v|
101
- if (base[key].is_a?(Hash) || base[key].is_a?(OptionsHash)) && (hash[key].is_a?(Hash) || has[key].is_a?(OptionsHash))
101
+ if (base[key].is_a?(Hash) || base[key].is_a?(OptionsHash)) && (hash[key].is_a?(Hash) || hash[key].is_a?(OptionsHash))
102
102
  rmerge(base[key], hash[key])
103
103
  elsif hash[key].is_a?(Hash)
104
104
  base[key] = OptionsHash.new.merge(hash[key])
@@ -149,7 +149,7 @@ module Beaker
149
149
  if not master.empty? and master.length == 1
150
150
  default_host_name = master[0]
151
151
  elsif hosts.length == 1
152
- default_host_name = hosts[0].keys[0]
152
+ default_host_name = hosts.keys[0]
153
153
  end
154
154
  if default_host_name
155
155
  hosts[default_host_name][:roles] << 'default'