beaker-vcloud 1.1.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/bin/beaker-vcloud CHANGED
@@ -4,7 +4,7 @@ require 'rubygems' unless defined?(Gem)
4
4
  require 'beaker-vcloud'
5
5
 
6
6
  VERSION_STRING =
7
- "
7
+ "
8
8
  _ .--.
9
9
  ( ` )
10
10
  beaker-vcloud .-' `--,
@@ -25,8 +25,6 @@ VERSION_STRING =
25
25
  '=='
26
26
  "
27
27
 
28
-
29
-
30
28
  puts BeakerVcloud::VERSION
31
29
 
32
30
  exit 0
@@ -4,13 +4,12 @@ require 'rbvmomi'
4
4
 
5
5
  module Beaker
6
6
  class Vcloud < Beaker::Hypervisor
7
-
8
7
  def self.new(vcloud_hosts, options)
9
8
  # Warning for pre-vmpooler style hosts configuration. TODO: remove this eventually.
10
9
  if options['pooling_api'] && !options['datacenter']
11
- options[:logger].warn "It looks like you may be trying to access vmpooler with `hypervisor: vcloud`. "\
12
- "This functionality has been removed. Change your hosts to `hypervisor: vmpooler` "\
13
- "and remove unused :datacenter, :folder, and :datastore from CONFIG."
10
+ options[:logger].warn 'It looks like you may be trying to access vmpooler with `hypervisor: vcloud`. ' \
11
+ 'This functionality has been removed. Change your hosts to `hypervisor: vmpooler` ' \
12
+ 'and remove unused :datacenter, :folder, and :datastore from CONFIG.'
14
13
  end
15
14
  super
16
15
  end
@@ -23,76 +22,71 @@ module Beaker
23
22
  raise 'You must specify a datastore for vCloud instances!' unless @options['datastore']
24
23
  raise 'You must specify a folder for vCloud instances!' unless @options['folder']
25
24
  raise 'You must specify a datacenter for vCloud instances!' unless @options['datacenter']
25
+
26
26
  @vcenter_credentials = get_fog_credentials(@options[:dot_fog], @options[:vcenter_instance] || :default)
27
27
  end
28
28
 
29
29
  def connect_to_vsphere
30
30
  @logger.notify "Connecting to vSphere at #{@vcenter_credentials[:vsphere_server]}" +
31
- " with credentials for #{@vcenter_credentials[:vsphere_username]}"
31
+ " with credentials for #{@vcenter_credentials[:vsphere_username]}"
32
32
 
33
- @vsphere_helper = VsphereHelper.new :server => @vcenter_credentials[:vsphere_server],
34
- :user => @vcenter_credentials[:vsphere_username],
35
- :pass => @vcenter_credentials[:vsphere_password]
33
+ @vsphere_helper = VsphereHelper.new server: @vcenter_credentials[:vsphere_server],
34
+ user: @vcenter_credentials[:vsphere_username],
35
+ pass: @vcenter_credentials[:vsphere_password]
36
36
  end
37
37
 
38
- def wait_for_dns_resolution host, try, attempts
38
+ def wait_for_dns_resolution(host, try, attempts)
39
39
  @logger.notify "Waiting for #{host['vmhostname']} DNS resolution"
40
40
  begin
41
41
  Socket.getaddrinfo(host['vmhostname'], nil)
42
- rescue
43
- if try <= attempts
44
- sleep 5
45
- try += 1
42
+ rescue StandardError
43
+ raise "DNS resolution failed after #{@options[:timeout].to_i} seconds" unless try <= attempts
46
44
 
47
- retry
48
- else
49
- raise "DNS resolution failed after #{@options[:timeout].to_i} seconds"
50
- end
45
+ sleep 5
46
+ try += 1
47
+
48
+ retry
51
49
  end
52
50
  end
53
51
 
54
- def booting_host host, try, attempts
52
+ def booting_host(host, try, attempts)
55
53
  @logger.notify "Booting #{host['vmhostname']} (#{host.name}) and waiting for it to register with vSphere"
56
- until
57
- @vsphere_helper.find_vms(host['vmhostname'])[host['vmhostname']].summary.guest.toolsRunningStatus == 'guestToolsRunning' and
58
- @vsphere_helper.find_vms(host['vmhostname'])[host['vmhostname']].summary.guest.ipAddress != nil
59
- if try <= attempts
60
- sleep 5
61
- try += 1
62
- else
63
- raise "vSphere registration failed after #{@options[:timeout].to_i} seconds"
64
- end
54
+ until @vsphere_helper.find_vms(host['vmhostname'])[host['vmhostname']].summary.guest.toolsRunningStatus == 'guestToolsRunning' and
55
+ !@vsphere_helper.find_vms(host['vmhostname'])[host['vmhostname']].summary.guest.ipAddress.nil?
56
+ raise "vSphere registration failed after #{@options[:timeout].to_i} seconds" unless try <= attempts
57
+
58
+ sleep 5
59
+ try += 1
60
+
65
61
  end
66
62
  end
67
63
 
68
64
  # Directly borrowed from openstack hypervisor
69
65
  def enable_root(host)
70
- if host['user'] != 'root'
71
- copy_ssh_to_root(host, @options)
72
- enable_root_login(host, @options)
73
- host['user'] = 'root'
74
- host.close
75
- end
66
+ return unless host['user'] != 'root'
67
+
68
+ copy_ssh_to_root(host, @options)
69
+ enable_root_login(host, @options)
70
+ host['user'] = 'root'
71
+ host.close
76
72
  end
77
73
 
78
- def create_clone_spec host
74
+ def create_clone_spec(host)
79
75
  # Add VM annotation
80
76
  configSpec = RbVmomi::VIM.VirtualMachineConfigSpec(
81
- :annotation =>
82
- 'Base template: ' + host['template'] + "\n" +
83
- 'Creation time: ' + Time.now.strftime("%Y-%m-%d %H:%M") + "\n\n" +
84
- 'CI build link: ' + ( ENV['BUILD_URL'] || 'Deployed independently of CI' ) +
77
+ annotation: 'Base template: ' + host['template'] + "\n" +
78
+ 'Creation time: ' + Time.now.strftime('%Y-%m-%d %H:%M') + "\n\n" +
79
+ 'CI build link: ' + (ENV['BUILD_URL'] || 'Deployed independently of CI') +
85
80
  'department: ' + @options[:department] +
86
81
  'project: ' + @options[:project],
87
- :extraConfig => [
88
- { :key => 'guestinfo.hostname',
89
- :value => host['vmhostname']
90
- }
91
- ]
82
+ extraConfig: [
83
+ { key: 'guestinfo.hostname',
84
+ value: host['vmhostname'], },
85
+ ],
92
86
  )
93
87
 
94
88
  # Are we using a customization spec?
95
- customizationSpec = @vsphere_helper.find_customization( host['template'] )
89
+ customizationSpec = @vsphere_helper.find_customization(host['template'])
96
90
 
97
91
  if customizationSpec
98
92
  # Print a logger message if using a customization spec
@@ -101,45 +95,44 @@ module Beaker
101
95
 
102
96
  # Put the VM in the specified folder and resource pool
103
97
  relocateSpec = RbVmomi::VIM.VirtualMachineRelocateSpec(
104
- :datastore => @vsphere_helper.find_datastore(@options['datacenter'],@options['datastore']),
105
- :pool => @options['resourcepool'] ? @vsphere_helper.find_pool(@options['datacenter'],@options['resourcepool']) : nil,
106
- :diskMoveType => :moveChildMostDiskBacking
98
+ datastore: @vsphere_helper.find_datastore(@options['datacenter'], @options['datastore']),
99
+ pool: if @options['resourcepool']
100
+ @vsphere_helper.find_pool(@options['datacenter'],
101
+ @options['resourcepool'])
102
+ end,
103
+ diskMoveType: :moveChildMostDiskBacking,
107
104
  )
108
105
 
109
106
  # Create a clone spec
110
- spec = RbVmomi::VIM.VirtualMachineCloneSpec(
111
- :config => configSpec,
112
- :location => relocateSpec,
113
- :customization => customizationSpec,
114
- :powerOn => true,
115
- :template => false
107
+ RbVmomi::VIM.VirtualMachineCloneSpec(
108
+ config: configSpec,
109
+ location: relocateSpec,
110
+ customization: customizationSpec,
111
+ powerOn: true,
112
+ template: false,
116
113
  )
117
- spec
118
114
  end
119
115
 
120
116
  def provision
121
117
  connect_to_vsphere
122
118
  begin
123
-
124
119
  try = 1
125
120
  attempts = @options[:timeout].to_i / 5
126
121
 
127
122
  start = Time.now
128
123
  tasks = []
129
- @hosts.each_with_index do |h, i|
130
- if h['name']
131
- h['vmhostname'] = h['name']
132
- else
133
- h['vmhostname'] = generate_host_name
134
- end
124
+ @hosts.each_with_index do |h, _i|
125
+ h['vmhostname'] = (h['name'] || generate_host_name)
135
126
 
136
- if h['template'].nil? and defined?(ENV['BEAKER_vcloud_template'])
137
- h['template'] = ENV['BEAKER_vcloud_template']
127
+ if h['template'].nil? and defined?(ENV.fetch('BEAKER_vcloud_template', nil))
128
+ h['template'] = ENV.fetch('BEAKER_vcloud_template', nil)
138
129
  end
139
130
 
140
- raise "Missing template configuration for #{h}. Set template in nodeset or set ENV[BEAKER_vcloud_template]" unless h['template']
131
+ unless h['template']
132
+ raise "Missing template configuration for #{h}. Set template in nodeset or set ENV[BEAKER_vcloud_template]"
133
+ end
141
134
 
142
- if h['template'] =~ /\//
135
+ if %r{/}.match?(h['template'])
143
136
  templatefolders = h['template'].split('/')
144
137
  h['template'] = templatefolders.pop
145
138
  end
@@ -149,60 +142,60 @@ module Beaker
149
142
  vm = {}
150
143
 
151
144
  if templatefolders
152
- vm[h['template']] = @vsphere_helper.find_folder(@options['datacenter'],templatefolders.join('/')).find(h['template'])
145
+ vm[h['template']] =
146
+ @vsphere_helper.find_folder(@options['datacenter'], templatefolders.join('/')).find(h['template'])
153
147
  else
154
148
  vm = @vsphere_helper.find_vms(h['template'])
155
149
  end
156
150
 
157
- if vm.length == 0
158
- raise "Unable to find template '#{h['template']}'!"
159
- end
151
+ raise "Unable to find template '#{h['template']}'!" if vm.length == 0
160
152
 
161
153
  spec = create_clone_spec(h)
162
154
 
163
155
  # Deploy from specified template
164
- tasks << vm[h['template']].CloneVM_Task( :folder => @vsphere_helper.find_folder(@options['datacenter'],@options['folder']), :name => h['vmhostname'], :spec => spec )
156
+ tasks << vm[h['template']].CloneVM_Task(
157
+ folder: @vsphere_helper.find_folder(@options['datacenter'],
158
+ @options['folder']), name: h['vmhostname'], spec: spec
159
+ )
165
160
  end
166
161
 
167
162
  try = (Time.now - start) / 5
168
163
  @vsphere_helper.wait_for_tasks(tasks, try, attempts)
169
- @logger.notify 'Spent %.2f seconds deploying VMs' % (Time.now - start)
164
+ @logger.notify format('Spent %.2f seconds deploying VMs', (Time.now - start))
170
165
 
171
166
  try = (Time.now - start) / 5
172
167
  duration = run_and_report_duration do
173
- @hosts.each_with_index do |h, i|
168
+ @hosts.each_with_index do |h, _i|
174
169
  booting_host(h, try, attempts)
175
170
  end
176
171
  end
177
- @logger.notify "Spent %.2f seconds booting and waiting for vSphere registration" % duration
172
+ @logger.notify 'Spent %.2f seconds booting and waiting for vSphere registration' % duration
178
173
 
179
174
  try = (Time.now - start) / 5
180
175
  duration = run_and_report_duration do
181
176
  @hosts.each do |host|
182
177
  repeat_fibonacci_style_for 8 do
183
- @vsphere_helper.find_vms(host['vmhostname'])[host['vmhostname']].summary.guest.ipAddress != nil
178
+ !@vsphere_helper.find_vms(host['vmhostname'])[host['vmhostname']].summary.guest.ipAddress.nil?
184
179
  end
185
180
  host[:ip] = @vsphere_helper.find_vms(host['vmhostname'])[host['vmhostname']].summary.guest.ipAddress
186
181
  enable_root(host) unless host.is_cygwin?
187
182
  end
188
183
  end
189
184
 
190
- @logger.notify "Spent %.2f seconds waiting for DNS resolution" % duration
191
-
192
- rescue => e
185
+ @logger.notify 'Spent %.2f seconds waiting for DNS resolution' % duration
186
+ rescue StandardError => e
193
187
  @vsphere_helper.close
194
- report_and_raise(@logger, e, "Vcloud.provision")
188
+ report_and_raise(@logger, e, 'Vcloud.provision')
195
189
  end
196
-
197
190
  end
198
191
 
199
192
  def cleanup
200
- @logger.notify "Destroying vCloud boxes"
193
+ @logger.notify 'Destroying vCloud boxes'
201
194
  connect_to_vsphere
202
195
 
203
- vm_names = @hosts.map {|h| h['vmhostname'] }.compact
196
+ vm_names = @hosts.map { |h| h['vmhostname'] }.compact
204
197
  if @hosts.length != vm_names.length
205
- @logger.warn "Some hosts did not have vmhostname set correctly! This likely means VM provisioning was not successful"
198
+ @logger.warn 'Some hosts did not have vmhostname set correctly! This likely means VM provisioning was not successful'
206
199
  end
207
200
  vms = @vsphere_helper.find_vms vm_names
208
201
  begin
@@ -224,12 +217,11 @@ module Beaker
224
217
  vm.Destroy_Task
225
218
  end
226
219
  @logger.notify "Spent %.2f seconds destroying #{vm.name}" % duration
227
-
228
220
  end
229
- rescue RbVmomi::Fault => ex
230
- if ex.fault.is_a?(RbVmomi::VIM::ManagedObjectNotFound)
231
- #it's already gone, don't bother trying to delete it
232
- name = vms.key(ex.fault.obj)
221
+ rescue RbVmomi::Fault => e
222
+ if e.fault.is_a?(RbVmomi::VIM::ManagedObjectNotFound)
223
+ # it's already gone, don't bother trying to delete it
224
+ name = vms.key(e.fault.obj)
233
225
  vms.delete(name)
234
226
  vm_names.delete(name)
235
227
  @logger.warn "Unable to destroy #{name}, it was not found in vSphere"
@@ -238,6 +230,5 @@ module Beaker
238
230
  end
239
231
  @vsphere_helper.close
240
232
  end
241
-
242
233
  end
243
234
  end
@@ -1,3 +1,3 @@
1
1
  module BeakerVcloud
2
- VERSION = '1.1.0'
2
+ VERSION = '2.0.0'
3
3
  end
@@ -2,43 +2,41 @@ require 'spec_helper'
2
2
 
3
3
  module Beaker
4
4
  describe Vcloud do
5
-
6
- before :each do
7
- MockVsphereHelper.set_config( fog_file_contents )
8
- MockVsphereHelper.set_vms( make_hosts() )
9
- stub_const( "VsphereHelper", MockVsphereHelper )
10
- stub_const( "Net", MockNet )
11
- json = double( 'json' )
12
- allow( json ).to receive( :parse ) do |arg|
5
+ before do
6
+ MockVsphereHelper.set_config(fog_file_contents)
7
+ MockVsphereHelper.set_vms(make_hosts)
8
+ stub_const('VsphereHelper', MockVsphereHelper)
9
+ stub_const('Net', MockNet)
10
+ json = double('json')
11
+ allow(json).to receive(:parse) do |arg|
13
12
  arg
14
13
  end
15
- stub_const( "JSON", json )
16
- allow( Socket ).to receive( :getaddrinfo ).and_return( true )
17
- allow_any_instance_of( Beaker::Shared ).to receive( :get_fog_credentials ).and_return( fog_file_contents )
18
- allow_any_instance_of( VsphereHelper ).to receive( :new ).and_return (MockVsphereHelper)
14
+ stub_const('JSON', json)
15
+ allow(Socket).to receive(:getaddrinfo).and_return(true)
16
+ allow_any_instance_of(Beaker::Shared).to receive(:get_fog_credentials).and_return(fog_file_contents)
17
+ allow_any_instance_of(VsphereHelper).to receive(:new).and_return(MockVsphereHelper)
19
18
  end
20
19
 
21
- describe "#provision" do
22
-
20
+ describe '#provision' do
23
21
  it 'warns about deprecated behavior if pooling_api is provided' do
24
22
  opts = make_opts
25
23
  opts[:pooling_api] = 'testpool'
26
- expect( opts[:logger] ).to receive( :warn ).once
27
- expect{ Beaker::Vcloud.new( make_hosts, opts ) }.to raise_error( /datacenter/ )
24
+ expect(opts[:logger]).to receive(:warn).once
25
+ expect { Beaker::Vcloud.new(make_hosts, opts) }.to raise_error(/datacenter/)
28
26
  end
29
27
 
30
28
  it 'does not instantiate vmpooler if pooling_api is provided' do
31
29
  opts = make_opts
32
30
  opts[:pooling_api] = 'testpool'
33
- expect{ Beaker::Vcloud.new( make_hosts, opts ) }.to raise_error( /datacenter/ )
31
+ expect { Beaker::Vcloud.new(make_hosts, opts) }.to raise_error(/datacenter/)
34
32
  end
35
33
 
36
34
  it 'ignores pooling_api and instantiates self' do
37
35
  opts = make_opts
38
36
  opts[:pooling_api] = 'testpool'
39
37
  opts[:datacenter] = 'testdatacenter'
40
- hypervisor = Beaker::Vcloud.new( make_hosts, opts)
41
- expect( hypervisor.class ).to be Beaker::Vcloud
38
+ hypervisor = Beaker::Vcloud.new(make_hosts, opts)
39
+ expect(hypervisor.class).to be Beaker::Vcloud
42
40
  end
43
41
 
44
42
  it 'provisions hosts and add them to the pool' do
@@ -48,18 +46,17 @@ module Beaker
48
46
  opts[:pooling_api] = nil
49
47
  opts[:datacenter] = 'testdc'
50
48
 
51
- vcloud = Beaker::Vcloud.new( make_hosts, opts )
52
- allow( vcloud ).to receive( :require ).and_return( true )
53
- allow( vcloud ).to receive( :sleep ).and_return( true )
49
+ vcloud = Beaker::Vcloud.new(make_hosts, opts)
50
+ allow(vcloud).to receive(:require).and_return(true)
51
+ allow(vcloud).to receive(:sleep).and_return(true)
54
52
  vcloud.provision
55
53
 
56
- hosts = vcloud.instance_variable_get( :@hosts )
57
- hosts.each do | host |
54
+ hosts = vcloud.instance_variable_get(:@hosts)
55
+ hosts.each do |host|
58
56
  name = host['vmhostname']
59
- vm = MockVsphereHelper.find_vm( name )
60
- expect( vm.toolsRunningStatus ).to be === "guestToolsRunning"
57
+ vm = MockVsphereHelper.find_vm(name)
58
+ expect(vm.toolsRunningStatus).to be === 'guestToolsRunning'
61
59
  end
62
-
63
60
  end
64
61
 
65
62
  it 'does not run enable_root on cygwin hosts' do
@@ -71,44 +68,37 @@ module Beaker
71
68
 
72
69
  hosts = make_hosts
73
70
  hosts.each do |host|
74
- allow( host ).to receive( :is_cygwin? ).and_return( true )
71
+ allow(host).to receive(:is_cygwin?).and_return(true)
75
72
  end
76
- vcloud = Beaker::Vcloud.new( hosts, opts )
77
- allow( vcloud ).to receive( :require ).and_return( true )
78
- allow( vcloud ).to receive( :sleep ).and_return( true )
79
- expect( vcloud ).to receive( :enable_root ).never
73
+ vcloud = Beaker::Vcloud.new(hosts, opts)
74
+ allow(vcloud).to receive(:require).and_return(true)
75
+ allow(vcloud).to receive(:sleep).and_return(true)
76
+ expect(vcloud).not_to receive(:enable_root)
80
77
  vcloud.provision
81
-
82
78
  end
83
-
84
79
  end
85
80
 
86
- describe "#cleanup" do
87
-
88
- it "cleans up hosts not in the pool" do
81
+ describe '#cleanup' do
82
+ it 'cleans up hosts not in the pool' do
89
83
  MockVsphereHelper.powerOn
90
84
 
91
85
  opts = make_opts
92
86
  opts[:pooling_api] = nil
93
87
  opts[:datacenter] = 'testdc'
94
88
 
95
- vcloud = Beaker::Vcloud.new( make_hosts, opts )
96
- allow( vcloud ).to receive( :require ).and_return( true )
97
- allow( vcloud ).to receive( :sleep ).and_return( true )
89
+ vcloud = Beaker::Vcloud.new(make_hosts, opts)
90
+ allow(vcloud).to receive(:require).and_return(true)
91
+ allow(vcloud).to receive(:sleep).and_return(true)
98
92
  vcloud.provision
99
93
  vcloud.cleanup
100
94
 
101
- hosts = vcloud.instance_variable_get( :@hosts )
102
- vm_names = hosts.map {|h| h['vmhostname'] }.compact
103
- vm_names.each do | name |
104
- vm = MockVsphereHelper.find_vm( name )
105
- expect( vm.runtime.powerState ).to be === "poweredOff"
95
+ hosts = vcloud.instance_variable_get(:@hosts)
96
+ vm_names = hosts.map { |h| h['vmhostname'] }.compact
97
+ vm_names.each do |name|
98
+ vm = MockVsphereHelper.find_vm(name)
99
+ expect(vm.runtime.powerState).to be === 'poweredOff'
106
100
  end
107
-
108
101
  end
109
-
110
102
  end
111
-
112
103
  end
113
-
114
104
  end