beaker 1.8.1 → 1.8.2

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