beaker 0.0.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/.travis.yml +8 -0
- data/README.md +6 -6
- data/beaker.gemspec +6 -2
- data/lib/beaker.rb +1 -1
- data/lib/beaker/answers.rb +34 -7
- data/lib/beaker/answers/version20.rb +124 -0
- data/lib/beaker/answers/version28.rb +21 -0
- data/lib/beaker/answers/version30.rb +24 -5
- data/lib/beaker/cli.rb +55 -41
- data/lib/beaker/command.rb +2 -2
- data/lib/beaker/dsl/helpers.rb +320 -106
- data/lib/beaker/dsl/install_utils.rb +202 -81
- data/lib/beaker/dsl/roles.rb +40 -0
- data/lib/beaker/host.rb +28 -20
- data/lib/beaker/host/unix.rb +7 -4
- data/lib/beaker/host/unix/pkg.rb +42 -12
- data/lib/beaker/host/windows.rb +9 -5
- data/lib/beaker/host/windows/group.rb +1 -1
- data/lib/beaker/host/windows/pkg.rb +41 -8
- data/lib/beaker/hypervisor.rb +23 -10
- data/lib/beaker/hypervisor/aixer.rb +15 -19
- data/lib/beaker/hypervisor/blimper.rb +71 -72
- data/lib/beaker/hypervisor/fusion.rb +11 -10
- data/lib/beaker/hypervisor/solaris.rb +17 -23
- data/lib/beaker/hypervisor/vagrant.rb +27 -12
- data/lib/beaker/hypervisor/vcloud.rb +154 -138
- data/lib/beaker/hypervisor/vcloud_pooled.rb +97 -0
- data/lib/beaker/hypervisor/vsphere.rb +8 -5
- data/lib/beaker/hypervisor/vsphere_helper.rb +43 -33
- data/lib/beaker/network_manager.rb +16 -12
- data/lib/beaker/options/command_line_parser.rb +199 -0
- data/lib/beaker/options/hosts_file_parser.rb +39 -0
- data/lib/beaker/options/options_file_parser.rb +45 -0
- data/lib/beaker/options/options_hash.rb +294 -0
- data/lib/beaker/options/parser.rb +288 -0
- data/lib/beaker/options/pe_version_scraper.rb +35 -0
- data/lib/beaker/options/presets.rb +70 -0
- data/lib/beaker/shared.rb +2 -1
- data/lib/beaker/shared/host_handler.rb +7 -2
- data/lib/beaker/shared/repetition.rb +1 -0
- data/lib/beaker/shared/timed.rb +14 -0
- data/lib/beaker/test_case.rb +2 -38
- data/lib/beaker/test_suite.rb +11 -25
- data/lib/beaker/utils/repo_control.rb +6 -8
- data/lib/beaker/utils/setup_helper.rb +9 -20
- data/spec/beaker/answers_spec.rb +109 -0
- data/spec/beaker/command_spec.rb +2 -2
- data/spec/beaker/dsl/assertions_spec.rb +1 -3
- data/spec/beaker/dsl/helpers_spec.rb +519 -84
- data/spec/beaker/dsl/install_utils_spec.rb +265 -16
- data/spec/beaker/dsl/roles_spec.rb +31 -10
- data/spec/beaker/host/windows/group_spec.rb +55 -0
- data/spec/beaker/host_spec.rb +130 -40
- data/spec/beaker/hypervisor/aixer_spec.rb +34 -0
- data/spec/beaker/hypervisor/blimper_spec.rb +77 -0
- data/spec/beaker/hypervisor/fusion_spec.rb +26 -0
- data/spec/beaker/hypervisor/hypervisor_spec.rb +66 -0
- data/spec/beaker/hypervisor/solaris_spec.rb +39 -0
- data/spec/beaker/hypervisor/vagrant_spec.rb +105 -0
- data/spec/beaker/hypervisor/vcloud_pooled_spec.rb +60 -0
- data/spec/beaker/hypervisor/vcloud_spec.rb +70 -0
- data/spec/beaker/hypervisor/vsphere_helper_spec.rb +162 -0
- data/spec/beaker/hypervisor/vsphere_spec.rb +76 -0
- data/spec/beaker/options/command_line_parser_spec.rb +25 -0
- data/spec/beaker/options/data/LATEST +1 -0
- data/spec/beaker/options/data/badyaml.cfg +21 -0
- data/spec/beaker/options/data/hosts.cfg +21 -0
- data/spec/beaker/options/data/opts.txt +6 -0
- data/spec/beaker/options/hosts_file_parser_spec.rb +30 -0
- data/spec/beaker/options/options_file_parser_spec.rb +23 -0
- data/spec/beaker/options/options_hash_spec.rb +111 -0
- data/spec/beaker/options/parser_spec.rb +172 -0
- data/spec/beaker/options/pe_version_scaper_spec.rb +15 -0
- data/spec/beaker/options/presets_spec.rb +24 -0
- data/spec/beaker/puppet_command_spec.rb +54 -21
- data/spec/beaker/shared/error_handler_spec.rb +40 -0
- data/spec/beaker/shared/host_handler_spec.rb +104 -0
- data/spec/beaker/shared/repetition_spec.rb +72 -0
- data/spec/beaker/test_suite_spec.rb +3 -16
- data/spec/beaker/utils/ntp_control_spec.rb +42 -0
- data/spec/beaker/utils/repo_control_spec.rb +168 -0
- data/spec/beaker/utils/setup_helper_spec.rb +82 -0
- data/spec/beaker/utils/validator_spec.rb +58 -0
- data/spec/helpers.rb +97 -0
- data/spec/matchers.rb +39 -0
- data/spec/mock_blimpy.rb +48 -0
- data/spec/mock_fission.rb +60 -0
- data/spec/mock_vsphere.rb +310 -0
- data/spec/mock_vsphere_helper.rb +183 -0
- data/spec/mocks.rb +83 -0
- data/spec/spec_helper.rb +8 -1
- metadata +106 -13
- data/beaker.rb +0 -10
- data/lib/beaker/options_parsing.rb +0 -323
- data/lib/beaker/test_config.rb +0 -148
- data/spec/beaker/options_parsing_spec.rb +0 -37
- data/spec/mocks_and_helpers.rb +0 -34
@@ -1,7 +1,7 @@
|
|
1
1
|
module Beaker
|
2
2
|
class Fusion < Beaker::Hypervisor
|
3
3
|
|
4
|
-
|
4
|
+
def initialize(fusion_hosts, options)
|
5
5
|
require 'rubygems' unless defined?(Gem)
|
6
6
|
begin
|
7
7
|
require 'fission'
|
@@ -10,16 +10,17 @@ module Beaker
|
|
10
10
|
end
|
11
11
|
@logger = options[:logger]
|
12
12
|
@options = options
|
13
|
-
@config = config['CONFIG'].dup
|
14
13
|
@fusion_hosts = fusion_hosts
|
14
|
+
@fission = Fission::VM
|
15
|
+
end
|
15
16
|
|
16
|
-
|
17
|
-
available =
|
17
|
+
def provision
|
18
|
+
available = @fission.all.data.collect{|vm| vm.name}.sort.join(", ")
|
18
19
|
@logger.notify "Available VM names: #{available}"
|
19
20
|
|
20
21
|
@fusion_hosts.each do |host|
|
21
22
|
vm_name = host["vmname"] || host.name
|
22
|
-
vm =
|
23
|
+
vm = @fission.new vm_name
|
23
24
|
raise "Could not find VM '#{vm_name}' for #{host.name}!" unless vm.exists?
|
24
25
|
|
25
26
|
available_snapshots = vm.snapshots.data.sort.join(", ")
|
@@ -46,11 +47,11 @@ module Beaker
|
|
46
47
|
time = Time.now - start
|
47
48
|
@logger.notify "Spent %.2f seconds resuming VM" % time
|
48
49
|
end
|
49
|
-
|
50
|
+
end #revert_fusion
|
50
51
|
|
51
|
-
|
52
|
-
|
53
|
-
|
52
|
+
def cleanup
|
53
|
+
@logger.notify "No cleanup for fusion boxes"
|
54
|
+
end
|
54
55
|
|
55
|
-
end
|
56
|
+
end
|
56
57
|
end
|
@@ -1,44 +1,38 @@
|
|
1
|
-
module Beaker
|
1
|
+
module Beaker
|
2
2
|
class Solaris < Beaker::Hypervisor
|
3
3
|
|
4
|
-
def initialize(solaris_hosts, options
|
4
|
+
def initialize(solaris_hosts, options)
|
5
5
|
@options = options
|
6
|
-
@config = config['CONFIG'].dup
|
7
6
|
@logger = options[:logger]
|
8
7
|
@solaris_hosts = solaris_hosts
|
9
|
-
fog_file = nil
|
10
|
-
if File.exists?(
|
11
|
-
fog_file = YAML.load_file(
|
8
|
+
@fog_file = nil
|
9
|
+
if File.exists?( @options[:dot_fog] )
|
10
|
+
@fog_file = YAML.load_file( @options[:dot_fog] )
|
12
11
|
end
|
13
|
-
raise "Cant load
|
12
|
+
raise "Cant load #{@options[:dot_fog]} config" unless @fog_file
|
14
13
|
|
15
|
-
|
16
|
-
|
17
|
-
|
14
|
+
end
|
15
|
+
|
16
|
+
def provision
|
17
|
+
hypername = @fog_file[:default][:solaris_hypervisor_server]
|
18
|
+
vmpath = @fog_file[:default][:solaris_hypervisor_vmpath]
|
19
|
+
snappaths = @fog_file[:default][:solaris_hypervisor_snappaths]
|
18
20
|
|
19
|
-
|
20
|
-
|
21
|
+
hyperopts = @options.dup
|
22
|
+
hyperopts['HOSTS'] = {
|
21
23
|
hypername => { 'platform' => 'solaris-11-sparc' }
|
22
|
-
},
|
23
|
-
'CONFIG' => {
|
24
|
-
'user' => fog_file[:default][:solaris_hypervisor_username] || ENV['USER'],
|
25
|
-
'ssh' => {
|
26
|
-
:keys => fog_file[:default][:solaris_hypervisor_keyfile] || "#{ENV['HOME']}/.ssh/id_rsa"
|
27
|
-
}
|
28
|
-
}
|
29
24
|
}
|
30
25
|
|
31
|
-
hyperconfig = Beaker::TestConfig.new( hyperconf, @options )
|
32
|
-
|
33
26
|
@logger.notify "Connecting to hypervisor at #{hypername}"
|
34
|
-
hypervisor = Beaker::Host.create( hypername,
|
27
|
+
hypervisor = Beaker::Host.create( hypername, hyperopts )
|
28
|
+
hypervisor[:user] = @fog_file[:default][:solaris_hypervisor_username] || hypervisor[:user]
|
29
|
+
hypervisor[:ssh][:keys] = [@fog_file[:default][:solaris_hypervisor_keyfile]] || hypervisor[:ssh][:keys]
|
35
30
|
|
36
31
|
@solaris_hosts.each do |host|
|
37
32
|
vm_name = host['vmname'] || host.name
|
38
33
|
#use the snapshot provided for this host
|
39
34
|
snapshot = host['snapshot']
|
40
35
|
|
41
|
-
|
42
36
|
@logger.notify "Reverting #{vm_name} to snapshot #{snapshot}"
|
43
37
|
start = Time.now
|
44
38
|
hypervisor.exec(Command.new("sudo /sbin/zfs rollback -Rf #{vmpath}/#{vm_name}@#{snapshot}"))
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'open3'
|
2
|
+
|
1
3
|
module Beaker
|
2
4
|
class Vagrant < Beaker::Hypervisor
|
3
5
|
|
@@ -9,11 +11,11 @@ module Beaker
|
|
9
11
|
end
|
10
12
|
|
11
13
|
def rand_chunk
|
12
|
-
(
|
14
|
+
(2 + rand(252)).to_s #don't want a 0, 1, or a 255
|
13
15
|
end
|
14
16
|
|
15
17
|
def randip
|
16
|
-
"
|
18
|
+
"10.255.#{rand_chunk}.#{rand_chunk}"
|
17
19
|
end
|
18
20
|
|
19
21
|
def make_vfile hosts
|
@@ -27,7 +29,7 @@ module Beaker
|
|
27
29
|
vagrant_file << " v.vm.box = '#{host['box']}'\n"
|
28
30
|
vagrant_file << " v.vm.box_url = '#{host['box_url']}'\n" unless host['box_url'].nil?
|
29
31
|
vagrant_file << " v.vm.base_mac = '#{randmac}'\n"
|
30
|
-
vagrant_file << " v.vm.network :private_network, ip: \"#{host['ip'].to_s}\"\n"
|
32
|
+
vagrant_file << " v.vm.network :private_network, ip: \"#{host['ip'].to_s}\", :netmask => \"255.255.0.0\"\n"
|
31
33
|
vagrant_file << " end\n"
|
32
34
|
@logger.debug "created Vagrantfile for VagrantHost #{host.name}"
|
33
35
|
end
|
@@ -35,9 +37,10 @@ module Beaker
|
|
35
37
|
vagrant_file << " vb.customize [\"modifyvm\", :id, \"--memory\", \"1024\"]\n"
|
36
38
|
vagrant_file << " end\n"
|
37
39
|
vagrant_file << "end\n"
|
38
|
-
|
39
|
-
|
40
|
-
|
40
|
+
FileUtils.mkdir_p(@vagrant_path)
|
41
|
+
File.open(File.expand_path(File.join(@vagrant_path, "Vagrantfile")), 'w') do |f|
|
42
|
+
f.write(vagrant_file)
|
43
|
+
end
|
41
44
|
end
|
42
45
|
|
43
46
|
def hack_etc_hosts hosts
|
@@ -62,7 +65,10 @@ module Beaker
|
|
62
65
|
|
63
66
|
def set_ssh_config host, user
|
64
67
|
f = Tempfile.new("#{host.name}")
|
65
|
-
ssh_config =
|
68
|
+
ssh_config = Dir.chdir(@vagrant_path) do
|
69
|
+
stdin, stdout = Open3.popen3('vagrant', 'ssh-config', host.name)
|
70
|
+
stdout.read
|
71
|
+
end
|
66
72
|
#replace hostname with ip
|
67
73
|
ssh_config = ssh_config.gsub(/#{host.name}/, host['ip'])
|
68
74
|
#set the user
|
@@ -74,19 +80,22 @@ module Beaker
|
|
74
80
|
@temp_files << f
|
75
81
|
end
|
76
82
|
|
77
|
-
def initialize(vagrant_hosts, options
|
83
|
+
def initialize(vagrant_hosts, options)
|
78
84
|
require 'tempfile'
|
79
85
|
@options = options
|
80
|
-
@config = config['CONFIG'].dup
|
81
86
|
@logger = options[:logger]
|
82
87
|
@temp_files = []
|
83
88
|
@vagrant_hosts = vagrant_hosts
|
89
|
+
@vagrant_path = File.expand_path(File.join(File.basename(__FILE__), '..', 'vagrant_files', options[:hosts_file]))
|
90
|
+
|
91
|
+
end
|
84
92
|
|
93
|
+
def provision
|
85
94
|
make_vfile @vagrant_hosts
|
86
95
|
|
87
96
|
#stop anything currently running, that way vagrant up will re-do networking on existing boxes
|
88
|
-
|
89
|
-
|
97
|
+
vagrant_cmd("halt")
|
98
|
+
vagrant_cmd("up")
|
90
99
|
|
91
100
|
@logger.debug "configure vagrant boxes (set ssh-config, switch to root user, hack etc/hosts)"
|
92
101
|
@vagrant_hosts.each do |host|
|
@@ -111,7 +120,13 @@ module Beaker
|
|
111
120
|
f.close()
|
112
121
|
end
|
113
122
|
@logger.notify "Destroying vagrant boxes"
|
114
|
-
|
123
|
+
vagrant_cmd("destroy --force")
|
124
|
+
end
|
125
|
+
|
126
|
+
def vagrant_cmd(args)
|
127
|
+
Dir.chdir(@vagrant_path) do
|
128
|
+
system("vagrant #{args}")
|
129
|
+
end
|
115
130
|
end
|
116
131
|
|
117
132
|
end
|
@@ -1,174 +1,190 @@
|
|
1
|
+
require 'yaml' unless defined?(YAML)
|
2
|
+
|
1
3
|
module Beaker
|
2
4
|
class Vcloud < Beaker::Hypervisor
|
5
|
+
CHARMAP = [('a'..'z'),('0'..'9')].map{|r| r.to_a}.flatten
|
3
6
|
|
4
|
-
def initialize(vcloud_hosts, options
|
7
|
+
def initialize(vcloud_hosts, options)
|
5
8
|
@options = options
|
6
|
-
@config = config['CONFIG'].dup
|
7
9
|
@logger = options[:logger]
|
8
10
|
@vcloud_hosts = vcloud_hosts
|
9
|
-
require 'yaml' unless defined?(YAML)
|
10
|
-
|
11
|
-
raise 'You must specify a datastore for vCloud instances!' unless @config['datastore']
|
12
|
-
raise 'You must specify a resource pool for vCloud instances!' unless @config['resourcepool']
|
13
|
-
raise 'You must specify a folder for vCloud instances!' unless @config['folder']
|
14
|
-
|
15
|
-
vsphere_credentials = VsphereHelper.load_config
|
16
|
-
|
17
|
-
@logger.notify "Connecting to vSphere at #{vsphere_credentials[:server]}" +
|
18
|
-
" with credentials for #{vsphere_credentials[:user]}"
|
19
|
-
|
20
|
-
vsphere_helper = VsphereHelper.new( vsphere_credentials )
|
21
|
-
vsphere_vms = {}
|
22
|
-
|
23
|
-
attempts = 10
|
24
11
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
12
|
+
raise 'You must specify a datastore for vCloud instances!' unless @options['datastore']
|
13
|
+
raise 'You must specify a resource pool for vCloud instances!' unless @options['resourcepool']
|
14
|
+
raise 'You must specify a folder for vCloud instances!' unless @options['folder']
|
15
|
+
@vsphere_credentials = VsphereHelper.load_config(@options[:dot_fog])
|
16
|
+
end
|
30
17
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
end
|
18
|
+
def connect_to_vsphere
|
19
|
+
@logger.notify "Connecting to vSphere at #{@vsphere_credentials[:server]}" +
|
20
|
+
" with credentials for #{@vsphere_credentials[:user]}"
|
35
21
|
|
36
|
-
|
22
|
+
@vsphere_helper = VsphereHelper.new( @vsphere_credentials )
|
23
|
+
end
|
37
24
|
|
38
|
-
|
25
|
+
def wait_for_dns_resolution host, try, attempts
|
26
|
+
@logger.notify "Waiting for #{host['vmhostname']} DNS resolution"
|
27
|
+
begin
|
28
|
+
Socket.getaddrinfo(host['vmhostname'], nil)
|
29
|
+
rescue
|
30
|
+
if try <= attempts
|
31
|
+
sleep 5
|
32
|
+
try += 1
|
39
33
|
|
40
|
-
|
41
|
-
vm[h['template']] = vsphere_helper.find_folder(templatefolders.join('/')).find(h['template'])
|
34
|
+
retry
|
42
35
|
else
|
43
|
-
|
36
|
+
raise "DNS resolution failed after #{@options[:timeout].to_i} seconds"
|
44
37
|
end
|
38
|
+
end
|
39
|
+
end
|
45
40
|
|
46
|
-
|
47
|
-
|
41
|
+
def booting_host host, try, attempts
|
42
|
+
@logger.notify "Booting #{host['vmhostname']} (#{host.name}) and waiting for it to register with vSphere"
|
43
|
+
until
|
44
|
+
@vsphere_helper.find_vms(host['vmhostname'])[host['vmhostname']].summary.guest.toolsRunningStatus == 'guestToolsRunning' and
|
45
|
+
@vsphere_helper.find_vms(host['vmhostname'])[host['vmhostname']].summary.guest.ipAddress != nil
|
46
|
+
if try <= attempts
|
47
|
+
sleep 5
|
48
|
+
try += 1
|
49
|
+
else
|
50
|
+
raise "vSphere registration failed after #{@options[:timeout].to_i} seconds"
|
48
51
|
end
|
52
|
+
end
|
53
|
+
end
|
49
54
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
'Base template: ' + h['template'] + "\n" +
|
54
|
-
'Creation time: ' + Time.now.strftime("%Y-%m-%d %H:%M") + "\n\n" +
|
55
|
-
'CI build link: ' + ( ENV['BUILD_URL'] || 'Deployed independently of CI' )
|
56
|
-
)
|
57
|
-
|
58
|
-
# Are we using a customization spec?
|
59
|
-
customizationSpec = vsphere_helper.find_customization( h['template'] )
|
60
|
-
|
61
|
-
if customizationSpec
|
62
|
-
# Print a logger message if using a customization spec
|
63
|
-
@logger.notify "Found customization spec for '#{h['template']}', will apply after boot"
|
64
|
-
|
65
|
-
# Using a customization spec takes longer, set a longer timeout
|
66
|
-
attempts = attempts * 2
|
67
|
-
end
|
55
|
+
def generate_host_name
|
56
|
+
CHARMAP[rand(25)] + (0...14).map{CHARMAP[rand(CHARMAP.length)]}.join
|
57
|
+
end
|
68
58
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
:
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
# Deploy from specified template
|
86
|
-
if (@vcloud_hosts.length == 1) or (i == @vcloud_hosts.length - 1)
|
87
|
-
vm[h['template']].CloneVM_Task( :folder => vsphere_helper.find_folder(@config['folder']), :name => h['vmhostname'], :spec => spec ).wait_for_completion
|
88
|
-
else
|
89
|
-
vm[h['template']].CloneVM_Task( :folder => vsphere_helper.find_folder(@config['folder']), :name => h['vmhostname'], :spec => spec )
|
90
|
-
end
|
59
|
+
def create_clone_spec host
|
60
|
+
# Add VM annotation
|
61
|
+
configSpec = RbVmomi::VIM.VirtualMachineConfigSpec(
|
62
|
+
:annotation =>
|
63
|
+
'Base template: ' + host['template'] + "\n" +
|
64
|
+
'Creation time: ' + Time.now.strftime("%Y-%m-%d %H:%M") + "\n\n" +
|
65
|
+
'CI build link: ' + ( ENV['BUILD_URL'] || 'Deployed independently of CI' )
|
66
|
+
)
|
67
|
+
|
68
|
+
# Are we using a customization spec?
|
69
|
+
customizationSpec = @vsphere_helper.find_customization( host['template'] )
|
70
|
+
|
71
|
+
if customizationSpec
|
72
|
+
# Print a logger message if using a customization spec
|
73
|
+
@logger.notify "Found customization spec for '#{host['template']}', will apply after boot"
|
91
74
|
end
|
92
|
-
@logger.notify 'Spent %.2f seconds deploying VMs' % (Time.now - start)
|
93
75
|
|
94
|
-
|
95
|
-
|
96
|
-
@
|
76
|
+
# Put the VM in the specified folder and resource pool
|
77
|
+
relocateSpec = RbVmomi::VIM.VirtualMachineRelocateSpec(
|
78
|
+
:datastore => @vsphere_helper.find_datastore(@options['datastore']),
|
79
|
+
:pool => @vsphere_helper.find_pool(@options['resourcepool']),
|
80
|
+
:diskMoveType => :moveChildMostDiskBacking
|
81
|
+
)
|
82
|
+
|
83
|
+
# Create a clone spec
|
84
|
+
spec = RbVmomi::VIM.VirtualMachineCloneSpec(
|
85
|
+
:config => configSpec,
|
86
|
+
:location => relocateSpec,
|
87
|
+
:customization => customizationSpec,
|
88
|
+
:powerOn => true,
|
89
|
+
:template => false
|
90
|
+
)
|
91
|
+
spec
|
92
|
+
end
|
93
|
+
|
94
|
+
def provision
|
95
|
+
connect_to_vsphere
|
96
|
+
begin
|
97
|
+
vsphere_vms = {}
|
98
|
+
|
97
99
|
try = 1
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
100
|
+
attempts = @options[:timeout].to_i / 5
|
101
|
+
|
102
|
+
start = Time.now
|
103
|
+
tasks = []
|
104
|
+
@vcloud_hosts.each_with_index do |h, i|
|
105
|
+
# Generate a randomized hostname
|
106
|
+
h['vmhostname'] = generate_host_name
|
107
|
+
|
108
|
+
if h['template'] =~ /\//
|
109
|
+
templatefolders = h['template'].split('/')
|
110
|
+
h['template'] = templatefolders.pop
|
111
|
+
end
|
112
|
+
|
113
|
+
@logger.notify "Deploying #{h['vmhostname']} (#{h.name}) to #{@options['folder']} from template '#{h['template']}'"
|
114
|
+
|
115
|
+
vm = {}
|
116
|
+
|
117
|
+
if templatefolders
|
118
|
+
vm[h['template']] = @vsphere_helper.find_folder(templatefolders.join('/')).find(h['template'])
|
107
119
|
else
|
108
|
-
|
120
|
+
vm = @vsphere_helper.find_vms(h['template'])
|
109
121
|
end
|
122
|
+
|
123
|
+
if vm.length == 0
|
124
|
+
raise "Unable to find template '#{h['template']}'!"
|
125
|
+
end
|
126
|
+
|
127
|
+
spec = create_clone_spec(h)
|
128
|
+
|
129
|
+
# Deploy from specified template
|
130
|
+
tasks << vm[h['template']].CloneVM_Task( :folder => @vsphere_helper.find_folder(@options['folder']), :name => h['vmhostname'], :spec => spec )
|
110
131
|
end
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
wait = 3
|
120
|
-
|
121
|
-
begin
|
122
|
-
Socket.getaddrinfo(h['vmhostname'], nil)
|
123
|
-
rescue
|
124
|
-
if try <= attempts
|
125
|
-
sleep wait
|
126
|
-
(last_wait, wait) = wait, last_wait + wait
|
127
|
-
try += 1
|
128
|
-
|
129
|
-
retry
|
130
|
-
else
|
131
|
-
raise "DNS resolution failed after #{wait} seconds"
|
132
|
+
try = (Time.now - start) / 5
|
133
|
+
@vsphere_helper.wait_for_tasks(tasks, try, attempts)
|
134
|
+
@logger.notify 'Spent %.2f seconds deploying VMs' % (Time.now - start)
|
135
|
+
|
136
|
+
try = (Time.now - start) / 5
|
137
|
+
duration = run_and_report_duration do
|
138
|
+
@vcloud_hosts.each_with_index do |h, i|
|
139
|
+
booting_host(h, try, attempts)
|
132
140
|
end
|
133
141
|
end
|
142
|
+
@logger.notify "Spent %.2f seconds booting and waiting for vSphere registration" % duration
|
143
|
+
|
144
|
+
try = (Time.now - start) / 5
|
145
|
+
duration = run_and_report_duration do
|
146
|
+
@vcloud_hosts.each_with_index do |h, i|
|
147
|
+
wait_for_dns_resolution(h, try, attempts)
|
148
|
+
end
|
149
|
+
end
|
150
|
+
@logger.notify "Spent %.2f seconds waiting for DNS resolution" % duration
|
151
|
+
rescue => e
|
152
|
+
@vsphere_helper.close
|
153
|
+
report_and_raise(@logger, e, "Vcloud.provision")
|
134
154
|
end
|
135
|
-
@logger.notify "Spent %.2f seconds waiting for DNS resolution" % (Time.now - start)
|
136
|
-
|
137
|
-
vsphere_helper.close
|
138
155
|
end
|
139
156
|
|
140
157
|
def cleanup
|
141
158
|
@logger.notify "Destroying vCloud boxes"
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
vsphere_helper = VsphereHelper.new( vsphere_credentials )
|
148
|
-
|
149
|
-
vm_names = @vcloud_hosts.map {|h| h['vmhostname'] }.compact
|
150
|
-
if @vcloud_hosts.length != vm_names.length
|
151
|
-
@logger.warn "Some hosts did not have vmhostname set correctly! This likely means VM provisioning was not successful"
|
152
|
-
end
|
153
|
-
vms = vsphere_helper.find_vms vm_names
|
154
|
-
vm_names.each do |name|
|
155
|
-
unless vm = vms[name]
|
156
|
-
raise "Couldn't find VM #{name} in vSphere!"
|
159
|
+
connect_to_vsphere
|
160
|
+
begin
|
161
|
+
vm_names = @vcloud_hosts.map {|h| h['vmhostname'] }.compact
|
162
|
+
if @vcloud_hosts.length != vm_names.length
|
163
|
+
@logger.warn "Some hosts did not have vmhostname set correctly! This likely means VM provisioning was not successful"
|
157
164
|
end
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
165
|
+
vms = @vsphere_helper.find_vms vm_names
|
166
|
+
vm_names.each do |name|
|
167
|
+
unless vm = vms[name]
|
168
|
+
raise "Couldn't find VM #{name} in vSphere!"
|
169
|
+
end
|
170
|
+
|
171
|
+
if vm.runtime.powerState == 'poweredOn'
|
172
|
+
@logger.notify "Shutting down #{vm.name}"
|
173
|
+
duration = run_and_report_duration do
|
174
|
+
vm.PowerOffVM_Task.wait_for_completion
|
175
|
+
end
|
176
|
+
@logger.notify "Spent %.2f seconds halting #{vm.name}" % duration
|
177
|
+
end
|
178
|
+
|
179
|
+
duration = run_and_report_duration do
|
180
|
+
vm.Destroy_Task
|
181
|
+
end
|
182
|
+
@logger.notify "Spent %.2f seconds destroying #{vm.name}" % duration
|
164
183
|
end
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
@logger.notify "Spent %.2f seconds destroying #{vm.name}" % (Time.now - start)
|
184
|
+
rescue => e
|
185
|
+
@vsphere_helper.close
|
186
|
+
report_and_raise(@logger, e, "Vcloud.cleanup")
|
169
187
|
end
|
170
|
-
|
171
|
-
vsphere_helper.close
|
172
188
|
end
|
173
189
|
|
174
190
|
end
|