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.
- checksums.yaml +8 -8
- data/bin/beaker +1 -1
- data/lib/beaker.rb +1 -1
- data/lib/beaker/cli.rb +15 -35
- data/lib/beaker/host_prebuilt_steps.rb +335 -0
- data/lib/beaker/hypervisor.rb +53 -4
- data/lib/beaker/hypervisor/aixer.rb +2 -2
- data/lib/beaker/hypervisor/blimper.rb +5 -5
- data/lib/beaker/hypervisor/fusion.rb +3 -3
- data/lib/beaker/hypervisor/solaris.rb +2 -2
- data/lib/beaker/hypervisor/vagrant.rb +6 -16
- data/lib/beaker/hypervisor/vcloud.rb +6 -6
- data/lib/beaker/hypervisor/vcloud_pooled.rb +4 -4
- data/lib/beaker/hypervisor/vsphere.rb +3 -3
- data/lib/beaker/network_manager.rb +51 -37
- data/lib/beaker/options/presets.rb +1 -0
- data/lib/beaker/shared.rb +2 -2
- data/lib/beaker/shared/host_role_parser.rb +36 -0
- data/lib/beaker/version.rb +1 -1
- data/spec/beaker/host_prebuilt_steps_spec.rb +421 -0
- data/spec/beaker/hypervisor/google_compute.rb +23 -0
- data/spec/beaker/hypervisor/vagrant_spec.rb +5 -4
- data/spec/beaker/hypervisor/vcloud_pooled_spec.rb +2 -2
- data/spec/beaker/hypervisor/vcloud_spec.rb +2 -2
- data/spec/beaker/hypervisor/vsphere_spec.rb +2 -2
- data/spec/beaker/options/parser_spec.rb +1 -1
- data/spec/beaker/shared/host_role_parser_spec.rb +58 -0
- metadata +10 -18
- data/lib/beaker/shared/host_handler.rb +0 -51
- data/lib/beaker/utils.rb +0 -7
- data/lib/beaker/utils/ntp_control.rb +0 -57
- data/lib/beaker/utils/repo_control.rb +0 -90
- data/lib/beaker/utils/setup_helper.rb +0 -66
- data/lib/beaker/utils/validator.rb +0 -36
- data/spec/beaker/shared/host_handler_spec.rb +0 -104
- data/spec/beaker/utils/ntp_control_spec.rb +0 -70
- data/spec/beaker/utils/repo_control_spec.rb +0 -168
- data/spec/beaker/utils/setup_helper_spec.rb +0 -82
- data/spec/beaker/utils/validator_spec.rb +0 -91
data/lib/beaker/hypervisor.rb
CHANGED
@@ -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
|
-
|
5
|
-
|
6
|
-
|
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
|
-
@
|
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
|
-
@
|
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
|
-
@
|
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
|
-
@
|
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 = @
|
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
|
-
@
|
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
|
-
@
|
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
|
-
@
|
13
|
+
@hosts = fusion_hosts
|
14
14
|
#check preconditions for fusion
|
15
|
-
@
|
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
|
-
@
|
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
|
-
@
|
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
|
-
@
|
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
|
-
@
|
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 @
|
110
|
+
make_vfile @hosts, @options
|
121
111
|
|
122
112
|
vagrant_cmd("up")
|
123
113
|
else #set host ip of already up boxes
|
124
|
-
@
|
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
|
-
@
|
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 @
|
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
|
-
@
|
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
|
-
@
|
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
|
-
@
|
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
|
-
@
|
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 = @
|
162
|
-
if @
|
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
|
-
@
|
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
|
-
@
|
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 = @
|
101
|
-
if @
|
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
|
-
@
|
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
|
-
@
|
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 = @
|
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
|
-
@
|
29
|
-
@
|
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
|
-
|
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
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
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
|
-
@
|
49
|
-
|
50
|
-
|
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 @
|
71
|
-
@
|
72
|
-
|
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
|