beaker 1.8.1 → 1.8.2

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.
Files changed (39) hide show
  1. checksums.yaml +8 -8
  2. data/bin/beaker +1 -1
  3. data/lib/beaker.rb +1 -1
  4. data/lib/beaker/cli.rb +15 -35
  5. data/lib/beaker/host_prebuilt_steps.rb +335 -0
  6. data/lib/beaker/hypervisor.rb +53 -4
  7. data/lib/beaker/hypervisor/aixer.rb +2 -2
  8. data/lib/beaker/hypervisor/blimper.rb +5 -5
  9. data/lib/beaker/hypervisor/fusion.rb +3 -3
  10. data/lib/beaker/hypervisor/solaris.rb +2 -2
  11. data/lib/beaker/hypervisor/vagrant.rb +6 -16
  12. data/lib/beaker/hypervisor/vcloud.rb +6 -6
  13. data/lib/beaker/hypervisor/vcloud_pooled.rb +4 -4
  14. data/lib/beaker/hypervisor/vsphere.rb +3 -3
  15. data/lib/beaker/network_manager.rb +51 -37
  16. data/lib/beaker/options/presets.rb +1 -0
  17. data/lib/beaker/shared.rb +2 -2
  18. data/lib/beaker/shared/host_role_parser.rb +36 -0
  19. data/lib/beaker/version.rb +1 -1
  20. data/spec/beaker/host_prebuilt_steps_spec.rb +421 -0
  21. data/spec/beaker/hypervisor/google_compute.rb +23 -0
  22. data/spec/beaker/hypervisor/vagrant_spec.rb +5 -4
  23. data/spec/beaker/hypervisor/vcloud_pooled_spec.rb +2 -2
  24. data/spec/beaker/hypervisor/vcloud_spec.rb +2 -2
  25. data/spec/beaker/hypervisor/vsphere_spec.rb +2 -2
  26. data/spec/beaker/options/parser_spec.rb +1 -1
  27. data/spec/beaker/shared/host_role_parser_spec.rb +58 -0
  28. metadata +10 -18
  29. data/lib/beaker/shared/host_handler.rb +0 -51
  30. data/lib/beaker/utils.rb +0 -7
  31. data/lib/beaker/utils/ntp_control.rb +0 -57
  32. data/lib/beaker/utils/repo_control.rb +0 -90
  33. data/lib/beaker/utils/setup_helper.rb +0 -66
  34. data/lib/beaker/utils/validator.rb +0 -36
  35. data/spec/beaker/shared/host_handler_spec.rb +0 -104
  36. data/spec/beaker/utils/ntp_control_spec.rb +0 -70
  37. data/spec/beaker/utils/repo_control_spec.rb +0 -168
  38. data/spec/beaker/utils/setup_helper_spec.rb +0 -82
  39. data/spec/beaker/utils/validator_spec.rb +0 -91
@@ -1,10 +1,22 @@
1
+ %w( host_prebuilt_steps ).each do |lib|
2
+ begin
3
+ require lib
4
+ rescue LoadError
5
+ require File.expand_path(File.join(File.dirname(__FILE__), lib))
6
+ end
7
+ end
8
+
1
9
  module Beaker
10
+ #The Beaker class that interacts to all the supported hypervisors
2
11
  class Hypervisor
12
+ include HostPrebuiltSteps
3
13
 
4
- def configure(hosts)
5
- @logger.debug "No post-provisioning configuration necessary for #{self.class.name} boxes"
6
- end
7
-
14
+ #Hypervisor creator method. Creates the appropriate hypervisor class object based upon
15
+ #the provided hypervisor type selected, then provisions hosts with hypervisor.
16
+ #@param [String] type The type of hypervisor to create - one of aix, solaris, vsphere, fusion,
17
+ # blimpy, vcloud or vagrant
18
+ #@param [Array<Host>] hosts_to_provision The hosts to be provisioned with the selected hypervisor
19
+ #@param [Hash] options options Options to alter execution
8
20
  def self.create(type, hosts_to_provision, options)
9
21
  @logger = options[:logger]
10
22
  @logger.notify("Beaker::Hypervisor, found some #{type} boxes to create")
@@ -27,17 +39,54 @@ module Beaker
27
39
  end
28
40
  when /vagrant/
29
41
  Beaker::Vagrant
42
+ when /none/
43
+ Beaker::Hypervisor
44
+ else
45
+ raise "Invalid hypervisor: #{type}"
30
46
  end
47
+
31
48
  hypervisor = hyper_class.new(hosts_to_provision, options)
32
49
  hypervisor.provision
33
50
 
34
51
  hypervisor
35
52
  end
36
53
 
54
+ def initialize(hosts, options)
55
+ @hosts = hosts
56
+ @options = options
57
+ end
58
+
59
+ #Provisioning steps for be run for a given hypervisor. Default is nil.
37
60
  def provision
38
61
  nil
39
62
  end
40
63
 
64
+ #Cleanup steps to be run for a given hypervisor. Default is nil.
65
+ def cleanup
66
+ nil
67
+ end
68
+
69
+ #Default configuration steps to be run for a given hypervisor
70
+ def configure
71
+ if @options[:timesync]
72
+ timesync(@hosts, @options)
73
+ end
74
+ if @options[:root_keys]
75
+ sync_root_keys(@hosts, @options)
76
+ end
77
+ if @options[:add_el_extras]
78
+ add_el_extras(@hosts, @options)
79
+ end
80
+ if @options[:add_master_entry]
81
+ add_master_entry(@hosts, @options)
82
+ end
83
+ end
84
+
85
+ #Default validation steps to be run for a given hypervisor
86
+ def validate
87
+ validate_host(@hosts, @options)
88
+ end
89
+
41
90
  end
42
91
  end
43
92
 
@@ -4,7 +4,7 @@ module Beaker
4
4
  def initialize(aix_hosts, options)
5
5
  @options = options
6
6
  @logger = options[:logger]
7
- @aix_hosts = aix_hosts
7
+ @hosts = aix_hosts
8
8
  #aix machines are reverted to known state, not a snapshot
9
9
  @fog_file = nil
10
10
  if File.exists?( @options[:dot_fog] )
@@ -27,7 +27,7 @@ module Beaker
27
27
  hypervisor[:user] = @fog_file[:default][:aix_hypervisor_username] || hypervisor[:user]
28
28
  hypervisor[:ssh][:keys] = [@fog_file[:default][:aix_hypervisor_keyfile]] || hypervisor[:ssh][:keys]
29
29
 
30
- @aix_hosts.each do |host|
30
+ @hosts.each do |host|
31
31
  vm_name = host['vmname'] || host.name
32
32
 
33
33
  @logger.notify "Reverting #{vm_name} to aix clean state"
@@ -27,7 +27,7 @@ module Beaker
27
27
  def initialize(blimpy_hosts, options)
28
28
  @options = options
29
29
  @logger = options[:logger]
30
- @blimpy_hosts = blimpy_hosts
30
+ @hosts = blimpy_hosts
31
31
  @blimpy = Blimpy
32
32
  end
33
33
 
@@ -35,7 +35,7 @@ module Beaker
35
35
  ami_spec= YAML.load_file(@options[:ec2_yaml])["AMI"]
36
36
 
37
37
  fleet = @blimpy.fleet do |fleet|
38
- @blimpy_hosts.each do |host|
38
+ @hosts.each do |host|
39
39
  amitype = host['vmname'] || host['platform']
40
40
  amisize = host['amisize'] || 'm1.small'
41
41
  #use snapshot provided for this host
@@ -90,7 +90,7 @@ module Beaker
90
90
  fleet.ships.each do |ship|
91
91
  ship.wait_for_sshd
92
92
  name = ship.name
93
- host = @blimpy_hosts.select { |host| host.name == name }[0]
93
+ host = @hosts.select { |host| host.name == name }[0]
94
94
  host['ip'] = ship.dns
95
95
  host.exec(Command.new("hostname #{name}"))
96
96
  ip = get_ip(host)
@@ -99,7 +99,7 @@ module Beaker
99
99
  end
100
100
 
101
101
  # Send our hosts information to the nodes
102
- @blimpy_hosts.each do |host|
102
+ @hosts.each do |host|
103
103
  set_etc_hosts(host, etc_hosts)
104
104
  end
105
105
 
@@ -107,7 +107,7 @@ module Beaker
107
107
 
108
108
  def cleanup
109
109
  fleet = @blimpy.fleet do |fleet|
110
- @blimpy_hosts.each do |host|
110
+ @hosts.each do |host|
111
111
  fleet.add(:aws) do |ship|
112
112
  ship.name = host.name
113
113
  end
@@ -10,9 +10,9 @@ module Beaker
10
10
  end
11
11
  @logger = options[:logger]
12
12
  @options = options
13
- @fusion_hosts = fusion_hosts
13
+ @hosts = fusion_hosts
14
14
  #check preconditions for fusion
15
- @fusion_hosts.each do |host|
15
+ @hosts.each do |host|
16
16
  raise "You must specify a snapshot for Fusion instances, no snapshot defined for #{host.name}!" unless host["snapshot"]
17
17
  end
18
18
  @fission = Fission::VM
@@ -22,7 +22,7 @@ module Beaker
22
22
  available = @fission.all.data.collect{|vm| vm.name}.sort.join(", ")
23
23
  @logger.notify "Available VM names: #{available}"
24
24
 
25
- @fusion_hosts.each do |host|
25
+ @hosts.each do |host|
26
26
  vm_name = host["vmname"] || host.name
27
27
  vm = @fission.new vm_name
28
28
  raise "Could not find VM '#{vm_name}' for #{host.name}!" unless vm.exists?
@@ -4,7 +4,7 @@ module Beaker
4
4
  def initialize(solaris_hosts, options)
5
5
  @options = options
6
6
  @logger = options[:logger]
7
- @solaris_hosts = solaris_hosts
7
+ @hosts = solaris_hosts
8
8
  @fog_file = nil
9
9
  if File.exists?( @options[:dot_fog] )
10
10
  @fog_file = YAML.load_file( @options[:dot_fog] )
@@ -28,7 +28,7 @@ module Beaker
28
28
  hypervisor[:user] = @fog_file[:default][:solaris_hypervisor_username] || hypervisor[:user]
29
29
  hypervisor[:ssh][:keys] = [@fog_file[:default][:solaris_hypervisor_keyfile]] || hypervisor[:ssh][:keys]
30
30
 
31
- @solaris_hosts.each do |host|
31
+ @hosts.each do |host|
32
32
  vm_name = host['vmname'] || host.name
33
33
  #use the snapshot provided for this host
34
34
  snapshot = host['snapshot']
@@ -52,16 +52,6 @@ module Beaker
52
52
  end
53
53
  end
54
54
 
55
- def copy_ssh_to_root host
56
- #make is possible to log in as root by copying the ssh dir to root's account
57
- @logger.debug "Give root a copy of vagrant's keys"
58
- if host['platform'] =~ /windows/
59
- host.exec(Command.new('sudo su -c "cp -r .ssh /home/Administrator/."'))
60
- else
61
- host.exec(Command.new('sudo su -c "cp -r .ssh /root/."'))
62
- end
63
- end
64
-
65
55
  def set_ssh_config host, user
66
56
  f = Tempfile.new("#{host.name}")
67
57
  ssh_config = Dir.chdir(@vagrant_path) do
@@ -104,7 +94,7 @@ module Beaker
104
94
  @options = options
105
95
  @logger = options[:logger]
106
96
  @temp_files = []
107
- @vagrant_hosts = vagrant_hosts
97
+ @hosts = vagrant_hosts
108
98
  @vagrant_path = File.expand_path(File.join(File.basename(__FILE__), '..', '.vagrant', 'beaker_vagrant_files', File.basename(options[:hosts_file])))
109
99
  FileUtils.mkdir_p(@vagrant_path)
110
100
  @vagrant_file = File.expand_path(File.join(@vagrant_path, "Vagrantfile"))
@@ -117,29 +107,29 @@ module Beaker
117
107
  #make sure that any old boxes are dead dead dead
118
108
  vagrant_cmd("destroy --force") if File.file?(@vagrant_file)
119
109
 
120
- make_vfile @vagrant_hosts, @options
110
+ make_vfile @hosts, @options
121
111
 
122
112
  vagrant_cmd("up")
123
113
  else #set host ip of already up boxes
124
- @vagrant_hosts.each do |host|
114
+ @hosts.each do |host|
125
115
  host[:ip] = get_ip_from_vagrant_file(host.name)
126
116
  end
127
117
  end
128
118
 
129
119
  @logger.debug "configure vagrant boxes (set ssh-config, switch to root user, hack etc/hosts)"
130
- @vagrant_hosts.each do |host|
120
+ @hosts.each do |host|
131
121
  default_user = host['user']
132
122
 
133
123
  set_ssh_config host, 'vagrant'
134
124
 
135
- copy_ssh_to_root host
125
+ copy_ssh_to_root host, @options
136
126
  #shut down connection, will reconnect on next exec
137
127
  host.close
138
128
 
139
129
  set_ssh_config host, default_user
140
130
  end
141
131
 
142
- hack_etc_hosts @vagrant_hosts
132
+ hack_etc_hosts @hosts
143
133
 
144
134
  end
145
135
 
@@ -7,7 +7,7 @@ module Beaker
7
7
  def initialize(vcloud_hosts, options)
8
8
  @options = options
9
9
  @logger = options[:logger]
10
- @vcloud_hosts = vcloud_hosts
10
+ @hosts = vcloud_hosts
11
11
 
12
12
  raise 'You must specify a datastore for vCloud instances!' unless @options['datastore']
13
13
  raise 'You must specify a resource pool for vCloud instances!' unless @options['resourcepool']
@@ -101,7 +101,7 @@ module Beaker
101
101
 
102
102
  start = Time.now
103
103
  tasks = []
104
- @vcloud_hosts.each_with_index do |h, i|
104
+ @hosts.each_with_index do |h, i|
105
105
  # Generate a randomized hostname
106
106
  h['vmhostname'] = generate_host_name
107
107
 
@@ -135,7 +135,7 @@ module Beaker
135
135
 
136
136
  try = (Time.now - start) / 5
137
137
  duration = run_and_report_duration do
138
- @vcloud_hosts.each_with_index do |h, i|
138
+ @hosts.each_with_index do |h, i|
139
139
  booting_host(h, try, attempts)
140
140
  end
141
141
  end
@@ -143,7 +143,7 @@ module Beaker
143
143
 
144
144
  try = (Time.now - start) / 5
145
145
  duration = run_and_report_duration do
146
- @vcloud_hosts.each_with_index do |h, i|
146
+ @hosts.each_with_index do |h, i|
147
147
  wait_for_dns_resolution(h, try, attempts)
148
148
  end
149
149
  end
@@ -158,8 +158,8 @@ module Beaker
158
158
  @logger.notify "Destroying vCloud boxes"
159
159
  connect_to_vsphere
160
160
 
161
- vm_names = @vcloud_hosts.map {|h| h['vmhostname'] }.compact
162
- if @vcloud_hosts.length != vm_names.length
161
+ vm_names = @hosts.map {|h| h['vmhostname'] }.compact
162
+ if @hosts.length != vm_names.length
163
163
  @logger.warn "Some hosts did not have vmhostname set correctly! This likely means VM provisioning was not successful"
164
164
  end
165
165
  vms = @vsphere_helper.find_vms vm_names
@@ -19,7 +19,7 @@ module Beaker
19
19
  def initialize(vcloud_hosts, options)
20
20
  @options = options
21
21
  @logger = options[:logger]
22
- @vcloud_hosts = vcloud_hosts
22
+ @hosts = vcloud_hosts
23
23
 
24
24
  raise 'You must specify a datastore for vCloud instances!' unless @options['datastore']
25
25
  raise 'You must specify a resource pool for vCloud instances!' unless @options['resourcepool']
@@ -54,7 +54,7 @@ module Beaker
54
54
  def provision
55
55
  start = Time.now
56
56
  try = 1
57
- @vcloud_hosts.each_with_index do |h, i|
57
+ @hosts.each_with_index do |h, i|
58
58
  if not h['template']
59
59
  raise ArgumentError, "You must specify a template name for #{h}"
60
60
  end
@@ -97,8 +97,8 @@ module Beaker
97
97
  end
98
98
 
99
99
  def cleanup
100
- vm_names = @vcloud_hosts.map {|h| h['vmhostname'] }.compact
101
- if @vcloud_hosts.length != vm_names.length
100
+ vm_names = @hosts.map {|h| h['vmhostname'] }.compact
101
+ if @hosts.length != vm_names.length
102
102
  @logger.warn "Some hosts did not have vmhostname set correctly! This likely means VM provisioning was not successful"
103
103
  end
104
104
 
@@ -6,7 +6,7 @@ module Beaker
6
6
  def initialize(vsphere_hosts, options)
7
7
  @options = options
8
8
  @logger = options[:logger]
9
- @vsphere_hosts = vsphere_hosts
9
+ @hosts = vsphere_hosts
10
10
  end
11
11
 
12
12
  def provision
@@ -18,7 +18,7 @@ module Beaker
18
18
  vsphere_helper = VsphereHelper.new( vsphere_credentials )
19
19
 
20
20
  vsphere_vms = {}
21
- @vsphere_hosts.each do |h|
21
+ @hosts.each do |h|
22
22
  name = h["vmname"] || h.name
23
23
  vsphere_vms[name] = h["snapshot"]
24
24
  end
@@ -60,7 +60,7 @@ module Beaker
60
60
 
61
61
  vsphere_helper = VsphereHelper.new( vsphere_credentials )
62
62
 
63
- vm_names = @vsphere_hosts.map {|h| h['vmname'] || h.name }
63
+ vm_names = @hosts.map {|h| h['vmname'] || h.name }
64
64
  vms = vsphere_helper.find_vms vm_names
65
65
  vm_names.each do |name|
66
66
  unless vm = vms[name]
@@ -7,15 +7,17 @@
7
7
  end
8
8
 
9
9
  module Beaker
10
+ #Object that holds all the provisioned and non-provisioned virtual machines.
11
+ #Controls provisioning, configuration, validation and cleanup of those virtual machines.
10
12
  class NetworkManager
11
- HYPERVISOR_TYPES = ['solaris', 'blimpy', 'vsphere', 'fusion', 'aix', 'vcloud', 'vagrant']
12
13
 
14
+ #Determine if a given host should be provisioned.
15
+ #Provision if:
16
+ # - only if we are running with ---provision
17
+ # - only if we have a hypervisor
18
+ # - only if either the specific hosts has no specification or has 'provision' in its config
19
+ # - always if it is a vagrant box (vagrant boxes are always provisioned as they always need ssh key hacking)
13
20
  def provision? options, host
14
- #provision this box
15
- # - only if we are running with --provision
16
- # - only if we have a hypervisor
17
- # - only if either the specific hosts has no specification or has 'provision' in its config
18
- # - always if it is a vagrant box (vagrant boxes are always provisioned as they always need ssh key hacking)
19
21
  command_line_says = options[:provision]
20
22
  host_says = host['hypervisor'] && (host.has_key?('provision') ? host['provision'] : true)
21
23
  (command_line_says && host_says) or (host['hypervisor'] =~/vagrant/)
@@ -25,55 +27,67 @@ module Beaker
25
27
  @logger = logger
26
28
  @options = options
27
29
  @hosts = []
28
- @virtual_machines = {}
29
- @noprovision_machines = []
30
+ @machines = {}
31
+ @hypervisors = nil
30
32
  end
31
33
 
34
+ #Provision all virtual machines. Provision machines according to their set hypervisor, if no hypervisor
35
+ #is selected assume that the described hosts are already up and reachable and do no provisioning.
32
36
  def provision
33
- #sort hosts into those to be provisioned and those to use non-provisioned
37
+ if @hypervisors
38
+ cleanup
39
+ end
40
+ @hypervisors = {}
41
+ #sort hosts by their hypervisor, use hypervisor 'none' if no hypervisor is specified
34
42
  @options['HOSTS'].each_key do |name|
35
43
  host = @options['HOSTS'][name]
36
- hypervisor = host['hypervisor']
37
- if provision?(@options, host)
38
- raise "Invalid hypervisor: #{hypervisor} (#{name})" unless HYPERVISOR_TYPES.include? hypervisor
39
- @logger.debug "Hypervisor for #{name} is #{hypervisor}"
40
- @virtual_machines[hypervisor] = [] unless @virtual_machines[hypervisor]
41
- @virtual_machines[hypervisor] << name
42
- else #this is a non-provisioned machine, deal with it without hypervisors
43
- @logger.debug "No hypervisor for #{name}, connecting to host without provisioning"
44
- @noprovision_machines << name
45
- end
44
+ hypervisor = host['hypervisor']
45
+ hypervisor = provision?(@options, host) ? host['hypervisor'] : 'none'
46
+ @logger.debug "Hypervisor for #{name} is #{hypervisor}"
47
+ @machines[hypervisor] = [] unless @machines[hypervisor]
48
+ @machines[hypervisor] << Beaker::Host.create(name, @options)
46
49
  end
47
50
 
48
- @provisioned_set = {}
49
- @virtual_machines.each do |type, names|
50
- hosts_for_type = []
51
- #set up host objects for provisioned provisioned_set
52
- names.each do |name|
53
- host = Beaker::Host.create(name, @options)
54
- hosts_for_type << host
55
- end
56
- @provisioned_set[type] = Beaker::Hypervisor.create(type, hosts_for_type, @options)
57
- @hosts << hosts_for_type
58
- end
59
- @noprovision_machines.each do |name|
60
- @hosts << Beaker::Host.create(name, @options)
51
+ @machines.each_key do |type|
52
+ @hypervisors[type] = Beaker::Hypervisor.create(type, @machines[type], @options)
53
+ @hosts << @machines[type]
61
54
  end
62
55
  @hosts = @hosts.flatten
63
56
  @hosts
64
57
  end
65
58
 
59
+ #Validate all provisioned machines, ensure that required packages are installed - if they are missing
60
+ #attempt to add them.
61
+ #@raise [Exception] Raise an exception if virtual machines fail to be validated
62
+ def validate
63
+ if @hypervisors
64
+ @hypervisors.each_key do |type|
65
+ @hypervisors[type].validate
66
+ end
67
+ end
68
+ end
69
+
70
+ #Configure all provisioned machines, adding any packages or settings required for SUTs
71
+ #@raise [Exception] Raise an exception if virtual machines fail to be configured
72
+ def configure
73
+ if @hypervisors
74
+ @hypervisors.each_key do |type|
75
+ @hypervisors[type].configure
76
+ end
77
+ end
78
+ end
79
+
80
+ #Shut down network connections and revert all provisioned virtual machines
66
81
  def cleanup
67
82
  #shut down connections
68
83
  @hosts.each {|host| host.close }
69
84
 
70
- if @provisioned_set
71
- @provisioned_set.each_key do |type|
72
- if @provisioned_set[type]
73
- @provisioned_set[type].cleanup
74
- end
85
+ if @hypervisors
86
+ @hypervisors.each_key do |type|
87
+ @hypervisors[type].cleanup
75
88
  end
76
89
  end
90
+ @hypervisors = nil
77
91
  end
78
92
 
79
93
  end