knife-vsphere 1.0.1 → 1.2.0

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 +4 -4
  2. data/lib/chef/knife/base_vsphere_command.rb +383 -371
  3. data/lib/chef/knife/customization_helper.rb +40 -0
  4. data/lib/chef/knife/vsphere_cluster_list.rb +47 -0
  5. data/lib/chef/knife/vsphere_cpu_ratio.rb +41 -45
  6. data/lib/chef/knife/vsphere_customization_list.rb +24 -29
  7. data/lib/chef/knife/vsphere_datastore_list.rb +68 -72
  8. data/lib/chef/knife/vsphere_datastore_maxfree.rb +48 -49
  9. data/lib/chef/knife/vsphere_datastorecluster_list.rb +66 -71
  10. data/lib/chef/knife/vsphere_datastorecluster_maxfree.rb +75 -84
  11. data/lib/chef/knife/vsphere_folder_list.rb +28 -30
  12. data/lib/chef/knife/vsphere_hosts_list.rb +42 -42
  13. data/lib/chef/knife/vsphere_pool_list.rb +46 -48
  14. data/lib/chef/knife/vsphere_pool_query.rb +58 -58
  15. data/lib/chef/knife/vsphere_template_list.rb +30 -32
  16. data/lib/chef/knife/vsphere_vlan_create.rb +51 -0
  17. data/lib/chef/knife/vsphere_vlan_list.rb +35 -37
  18. data/lib/chef/knife/vsphere_vm_clone.rb +834 -581
  19. data/lib/chef/knife/vsphere_vm_config.rb +48 -46
  20. data/lib/chef/knife/vsphere_vm_delete.rb +70 -66
  21. data/lib/chef/knife/vsphere_vm_execute.rb +62 -66
  22. data/lib/chef/knife/vsphere_vm_list.rb +57 -61
  23. data/lib/chef/knife/vsphere_vm_markastemplate.rb +48 -54
  24. data/lib/chef/knife/vsphere_vm_migrate.rb +73 -0
  25. data/lib/chef/knife/vsphere_vm_move.rb +88 -0
  26. data/lib/chef/knife/vsphere_vm_net.rb +57 -0
  27. data/lib/chef/knife/vsphere_vm_property_get.rb +44 -46
  28. data/lib/chef/knife/vsphere_vm_property_set.rb +83 -84
  29. data/lib/chef/knife/vsphere_vm_query.rb +48 -48
  30. data/lib/chef/knife/vsphere_vm_snapshot.rb +124 -130
  31. data/lib/chef/knife/vsphere_vm_state.rb +122 -127
  32. data/lib/chef/knife/vsphere_vm_toolsconfig.rb +54 -52
  33. data/lib/chef/knife/vsphere_vm_vmdk_add.rb +234 -241
  34. data/lib/chef/knife/vsphere_vm_wait_sysprep.rb +54 -0
  35. data/lib/knife-vsphere/version.rb +3 -4
  36. metadata +43 -15
  37. data/lib/chef/knife/vshpere_vm_migrate.rb +0 -80
  38. data/lib/chef/knife/vshpere_vm_move.rb +0 -92
  39. data/lib/chef/knife/vshpere_vm_net.rb +0 -57
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5c6db46d0b70790bceee7a18c1649d07e5880bd5
4
- data.tar.gz: 75f42827a15800b4fef78a8f4db71205c86329c3
3
+ metadata.gz: 539eb7399be7ce9a238ee524f86c4e23109a5eb2
4
+ data.tar.gz: fb56fd05b1dc8018646aee95fd23012af84fbd6b
5
5
  SHA512:
6
- metadata.gz: 5a90ce096ba9a99b1a943d6939aa21df37f7614092c4301f9fffb5ea8ee454567afb3ce555ea29a259b52a3e0ea3d8164e97931aa66ed989db9dce612bc97bdf
7
- data.tar.gz: 5bc6f5f732f1f5bbca00a88d4a3f27f6f430b847ed33685294e6b32dad791e65e309ac4fc2c10dcf90e6b3dafe3a5cbfd6e506538ef19f8871d4ff1c2fefb63f
6
+ metadata.gz: b005a0e1388543dff4b62bd8cac3c5575a485e8a526b4f07dfad98cf63962581ad64c7375a68ae898c1f8b5e40f364c020e3676d15783f43a05874c958cf22f6
7
+ data.tar.gz: 9ed960117048b20a243537d5e088f56cf6b4e0438abee01497b0e83ee3ab4c1b309f31b480bf803be49374588ee5a9541897645ffb27a42f2ac19029765fbdc4
@@ -1,371 +1,383 @@
1
- #
2
- # Author:: Ezra Pagel (<ezra@cpan.org>)
3
- # Contributor:: Jesse Campbell (<hikeit@gmail.com>)
4
- # License:: Apache License, Version 2.0
5
- #
6
-
7
- require 'chef/knife'
8
- require 'rbvmomi'
9
- require 'base64'
10
-
11
- # Base class for vsphere knife commands
12
- class Chef
13
- class Knife
14
- class BaseVsphereCommand < Knife
15
-
16
- deps do
17
- require 'chef/knife/bootstrap'
18
- Chef::Knife::Bootstrap.load_deps
19
- require 'fog'
20
- require 'socket'
21
- require 'net/ssh/multi'
22
- require 'readline'
23
- require 'chef/json_compat'
24
- end
25
-
26
- def self.get_common_options
27
- unless defined? $default
28
- $default = Hash.new
29
- end
30
-
31
- option :vsphere_user,
32
- :short => "-u USERNAME",
33
- :long => "--vsuser USERNAME",
34
- :description => "The username for vsphere"
35
-
36
- option :vsphere_pass,
37
- :short => "-p PASSWORD",
38
- :long => "--vspass PASSWORD",
39
- :description => "The password for vsphere"
40
-
41
- option :vsphere_host,
42
- :long => "--vshost HOST",
43
- :description => "The vsphere host"
44
-
45
- option :vsphere_dc,
46
- :short => "-D DATACENTER",
47
- :long => "--vsdc DATACENTER",
48
- :description => "The Datacenter for vsphere"
49
-
50
- option :vsphere_path,
51
- :long => "--vspath SOAP_PATH",
52
- :description => "The vsphere SOAP endpoint path"
53
- $default[:vsphere_path] = "/sdk"
54
-
55
- option :vsphere_port,
56
- :long => "--vsport PORT",
57
- :description => "The VI SDK port number to use"
58
- $default[:vsphere_port] = 443
59
-
60
- option :vshere_nossl,
61
- :long => "--vsnossl",
62
- :description => "Disable SSL connectivity"
63
-
64
- option :vsphere_insecure,
65
- :long => "--vsinsecure",
66
- :description => "Disable SSL certificate verification"
67
-
68
- option :folder,
69
- :short => "-f FOLDER",
70
- :long => "--folder FOLDER",
71
- :description => "The folder to get VMs from"
72
-
73
- option :proxy_host,
74
- :long => '--proxyhost PROXY_HOSTNAME',
75
- :description => 'Proxy hostname'
76
-
77
- option :proxy_port,
78
- :long => '--proxyport PROXY_PORT',
79
- :description => 'Proxy port'
80
-
81
- $default[:folder] = ''
82
- end
83
-
84
- def get_config(key)
85
- key = key.to_sym
86
- rval = config[key] || Chef::Config[:knife][key] || $default[key]
87
- Chef::Log.debug("value for config item #{key}: #{rval}")
88
- rval
89
- end
90
-
91
- def get_vim_connection
92
-
93
- conn_opts = {
94
- :host => get_config(:vsphere_host),
95
- :path => get_config(:vshere_path),
96
- :port => get_config(:vsphere_port),
97
- :use_ssl => !get_config(:vsphere_nossl),
98
- :user => get_config(:vsphere_user),
99
- :password => get_config(:vsphere_pass),
100
- :insecure => get_config(:vsphere_insecure),
101
- :proxyHost => get_config(:proxy_host),
102
- :proxyPort => get_config(:proxy_port)
103
- }
104
-
105
- if !conn_opts[:password]
106
- # Password is not in the config file - grab it
107
- # from the command line
108
- conn_opts[:password] = get_password
109
- elsif conn_opts[:password].start_with?('base64:')
110
- conn_opts[:password] = Base64.decode64(conn_opts[:password][7..-1]).chomp
111
- end
112
-
113
- # opt :debug, "Log SOAP messages", :short => 'd', :default => (ENV['RBVMOMI_DEBUG'] || false)
114
-
115
- vim = RbVmomi::VIM.connect conn_opts
116
- config[:vim] = vim
117
- return vim
118
- end
119
-
120
- def get_password
121
- @password ||= ui.ask("Enter your password: ") { |q| q.echo = false }
122
- end
123
-
124
- def get_vm(vmname)
125
- vim = get_vim_connection
126
- baseFolder = find_folder(get_config(:folder));
127
- retval = traverse_folders_for_vm(baseFolder, vmname)
128
- return retval
129
- end
130
-
131
- def traverse_folders_for_vm(folder, vmname)
132
- children = folder.children.find_all
133
- children.each do |child|
134
- if child.class == RbVmomi::VIM::VirtualMachine && child.name == vmname
135
- return child
136
- elsif child.class == RbVmomi::VIM::Folder
137
- vm = traverse_folders_for_vm(child, vmname)
138
- if vm then return vm end
139
- end
140
- end
141
- return false
142
- end
143
-
144
- def get_vms(vmname)
145
- vim = get_vim_connection
146
- baseFolder = find_folder(get_config(:folder));
147
- retval = traverse_folders_for_vms(baseFolder, vmname)
148
- return retval
149
- end
150
-
151
- def traverse_folders_for_vms(folder, vmname)
152
- retval = []
153
- children = folder.children.find_all
154
- children.each do |child|
155
- if child.class == RbVmomi::VIM::VirtualMachine && child.name == vmname
156
- retval << child
157
- elsif child.class == RbVmomi::VIM::Folder
158
- retval.concat(traverse_folders_for_vms(child, vmname))
159
- end
160
- end
161
- return retval
162
- end
163
-
164
- def traverse_folders_for_dc(folder, dcname)
165
- children = folder.children.find_all
166
- children.each do |child|
167
- if child.class == RbVmomi::VIM::Datacenter && child.name == dcname
168
- return child
169
- elsif child.class == RbVmomi::VIM::Folder
170
- dc = traverse_folders_for_dc(child, dcname)
171
- if dc then return dc end
172
- end
173
- end
174
- return false
175
- end
176
-
177
- def get_datacenter
178
- dcname = get_config(:vsphere_dc)
179
- traverse_folders_for_dc(config[:vim].rootFolder, dcname) or abort "datacenter not found"
180
- end
181
-
182
- def find_folder(folderName)
183
- dc = get_datacenter
184
- baseEntity = dc.vmFolder
185
- entityArray = folderName.split('/')
186
- entityArray.each do |entityArrItem|
187
- if entityArrItem != ''
188
- baseEntity = baseEntity.childEntity.grep(RbVmomi::VIM::Folder).find { |f| f.name == entityArrItem } or
189
- abort "no such folder #{folderName} while looking for #{entityArrItem}"
190
- end
191
- end
192
- baseEntity
193
- end
194
-
195
- def find_network(networkName)
196
- dc = get_datacenter
197
- baseEntity = dc.network
198
- baseEntity.find { |f| f.name == networkName } or abort "no such network #{networkName}"
199
- end
200
-
201
- def find_pool(poolName)
202
- dc = get_datacenter
203
- baseEntity = dc.hostFolder
204
- entityArray = poolName.split('/')
205
- entityArray.each do |entityArrItem|
206
- if entityArrItem != ''
207
- if baseEntity.is_a? RbVmomi::VIM::Folder
208
- baseEntity = baseEntity.childEntity.find { |f| f.name == entityArrItem } or
209
- abort "no such pool #{poolName} while looking for #{entityArrItem}"
210
- elsif baseEntity.is_a? RbVmomi::VIM::ClusterComputeResource or baseEntity.is_a? RbVmomi::VIM::ComputeResource
211
- baseEntity = baseEntity.resourcePool.resourcePool.find { |f| f.name == entityArrItem } or
212
- abort "no such pool #{poolName} while looking for #{entityArrItem}"
213
- elsif baseEntity.is_a? RbVmomi::VIM::ResourcePool
214
- baseEntity = baseEntity.resourcePool.find { |f| f.name == entityArrItem } or
215
- abort "no such pool #{poolName} while looking for #{entityArrItem}"
216
- else
217
- abort "Unexpected Object type encountered #{baseEntity.type} while finding resourcePool"
218
- end
219
- end
220
- end
221
-
222
- baseEntity = baseEntity.resourcePool if not baseEntity.is_a?(RbVmomi::VIM::ResourcePool) and baseEntity.respond_to?(:resourcePool)
223
- baseEntity
224
- end
225
-
226
- def choose_datastore(dstores, size)
227
- vmdk_size_kb = size.to_i * 1024 * 1024
228
- vmdk_size_B = size.to_i * 1024 * 1024 * 1024
229
-
230
- candidates = []
231
- dstores.each do |store|
232
- avail = number_to_human_size(store.summary[:freeSpace])
233
- cap = number_to_human_size(store.summary[:capacity])
234
- puts "#{ui.color("Datastore", :cyan)}: #{store.name} (#{avail}(#{store.summary[:freeSpace]}) / #{cap})"
235
-
236
- # vm's can span multiple datastores, so instead of grabbing the first one
237
- # let's find the first datastore with the available space on a LUN the vm
238
- # is already using, or use a specified LUN (if given)
239
-
240
-
241
- if (store.summary[:freeSpace] - vmdk_size_B) > 0
242
- # also let's not use more than 90% of total space to save room for snapshots.
243
- cap_remains = 100 * ((store.summary[:freeSpace].to_f - vmdk_size_B.to_f) / store.summary[:capacity].to_f)
244
- if (cap_remains.to_i > 10)
245
- candidates.push(store)
246
- end
247
- end
248
- end
249
- if candidates.length > 0
250
- vmdk_datastore = candidates[0]
251
- else
252
- puts "Insufficient space on all LUNs designated or assigned to the virtual machine. Please specify a new target."
253
- vmdk_datastore = nil
254
- end
255
- return vmdk_datastore
256
- end
257
-
258
-
259
- def find_datastores_regex(regex)
260
- stores = Array.new()
261
- puts "Looking for all datastores that match /#{regex}/"
262
- dc = get_datacenter
263
- baseEntity = dc.datastore
264
- baseEntity.each do |ds|
265
- if ds.name.match /#{regex}/
266
- stores.push ds
267
- end
268
- end
269
- return stores
270
- end
271
-
272
- def find_datastore(dsName)
273
- dc = get_datacenter
274
- baseEntity = dc.datastore
275
- baseEntity.find { |f| f.info.name == dsName } or abort "no such datastore #{dsName}"
276
- end
277
-
278
- def find_datastorecluster(dsName, folder = nil)
279
- if ! folder
280
- dc = get_datacenter
281
- folder = dc.datastoreFolder
282
- end
283
- folder.childEntity.each do |child|
284
- if child.class.to_s == 'Folder'
285
- ds = find_datastorecluster(dsName, child)
286
- if ds then return ds end
287
- elsif child.class.to_s == 'StoragePod' && child.name == dsName
288
- return child
289
- end
290
- end
291
- return nil
292
- end
293
-
294
- def find_device(vm, deviceName)
295
- vm.config.hardware.device.each do |device|
296
- return device if device.deviceInfo.label == deviceName
297
- end
298
- nil
299
- end
300
-
301
- def find_all_in_folder(folder, type)
302
- if folder.instance_of?(RbVmomi::VIM::ClusterComputeResource) or folder.instance_of?(RbVmomi::VIM::ComputeResource)
303
- folder = folder.resourcePool
304
- end
305
- if folder.instance_of?(RbVmomi::VIM::ResourcePool)
306
- folder.resourcePool.grep(type)
307
- elsif folder.instance_of?(RbVmomi::VIM::Folder)
308
- folder.childEntity.grep(type)
309
- else
310
- puts "Unknown type #{folder.class}, not enumerating"
311
- nil
312
- end
313
- end
314
-
315
- def get_path_to_object(object)
316
- if object.is_a?(RbVmomi::VIM:: ManagedEntity)
317
- if object.parent.is_a?(RbVmomi::VIM:: ManagedEntity)
318
- return get_path_to_object(object.parent) + "/" + object.parent.name
319
- else
320
- return ""
321
- end
322
- else
323
- puts "Unknown type #{object.class}, not enumerating"
324
- nil
325
- end
326
- end
327
-
328
- def find_in_folder(folder, type, name)
329
- folder.childEntity.grep(type).find { |o| o.name == name }
330
- end
331
-
332
- def fatal_exit(msg)
333
- ui.fatal(msg)
334
- exit 1
335
- end
336
-
337
- def tcp_test_port_vm(vm, port)
338
- ip = vm.guest.ipAddress
339
- if ip.nil?
340
- sleep 2
341
- return false
342
- end
343
- tcp_test_port(ip, port)
344
- end
345
-
346
- def tcp_test_port(hostname, port)
347
- tcp_socket = TCPSocket.new(hostname, port)
348
- readable = IO.select([tcp_socket], nil, nil, 5)
349
- if readable
350
- Chef::Log.debug("sshd accepting connections on #{hostname}, banner is #{tcp_socket.gets}") if port == 22
351
- true
352
- else
353
- false
354
- end
355
- rescue Errno::ETIMEDOUT
356
- false
357
- rescue Errno::EPERM
358
- false
359
- rescue Errno::ECONNREFUSED
360
- sleep 2
361
- false
362
- rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH
363
- sleep 2
364
- false
365
- ensure
366
- tcp_socket && tcp_socket.close
367
- end
368
-
369
- end
370
- end
371
- end
1
+ #
2
+ # Author:: Ezra Pagel (<ezra@cpan.org>)
3
+ # Contributor:: Jesse Campbell (<hikeit@gmail.com>)
4
+ # License:: Apache License, Version 2.0
5
+ #
6
+
7
+ require 'chef/knife'
8
+ require 'rbvmomi'
9
+ require 'base64'
10
+
11
+ # Base class for vsphere knife commands
12
+ class Chef
13
+ class Knife
14
+ class BaseVsphereCommand < Knife
15
+ deps do
16
+ require 'chef/knife/bootstrap'
17
+ Chef::Knife::Bootstrap.load_deps
18
+ require 'fog'
19
+ require 'socket'
20
+ require 'net/ssh/multi'
21
+ require 'readline'
22
+ require 'chef/json_compat'
23
+ end
24
+
25
+ def self.common_options
26
+ option :vsphere_user,
27
+ short: '-u USERNAME',
28
+ long: '--vsuser USERNAME',
29
+ description: 'The username for vsphere'
30
+
31
+ option :vsphere_pass,
32
+ short: '-p PASSWORD',
33
+ long: '--vspass PASSWORD',
34
+ description: 'The password for vsphere'
35
+
36
+ option :vsphere_host,
37
+ long: '--vshost HOST',
38
+ description: 'The vsphere host'
39
+
40
+ option :vsphere_dc,
41
+ short: '-D DATACENTER',
42
+ long: '--vsdc DATACENTER',
43
+ description: 'The Datacenter for vsphere'
44
+
45
+ option :vsphere_path,
46
+ long: '--vspath SOAP_PATH',
47
+ description: 'The vsphere SOAP endpoint path',
48
+ default: '/sdk'
49
+
50
+ option :vsphere_port,
51
+ long: '--vsport PORT',
52
+ description: 'The VI SDK port number to use',
53
+ default: '443'
54
+
55
+ option :vsphere_nossl,
56
+ long: '--vsnossl',
57
+ description: 'Disable SSL connectivity'
58
+
59
+ option :vsphere_insecure,
60
+ long: '--vsinsecure',
61
+ description: 'Disable SSL certificate verification'
62
+
63
+ option :folder,
64
+ short: '-f FOLDER',
65
+ long: '--folder FOLDER',
66
+ description: 'The folder to get VMs from',
67
+ default: ''
68
+
69
+ option :proxy_host,
70
+ long: '--proxyhost PROXY_HOSTNAME',
71
+ description: 'Proxy hostname'
72
+
73
+ option :proxy_port,
74
+ long: '--proxyport PROXY_PORT',
75
+ description: 'Proxy port'
76
+ end
77
+
78
+ def get_config(key)
79
+ key = key.to_sym
80
+ rval = config[key] || Chef::Config[:knife][key]
81
+ Chef::Log.debug("value for config item #{key}: #{rval}")
82
+ rval
83
+ end
84
+
85
+ def vim_connection
86
+ conn_opts = {
87
+ host: get_config(:vsphere_host),
88
+ path: get_config(:vsphere_path),
89
+ port: get_config(:vsphere_port),
90
+ use_ssl: !get_config(:vsphere_nossl),
91
+ user: get_config(:vsphere_user),
92
+ password: get_config(:vsphere_pass),
93
+ insecure: get_config(:vsphere_insecure),
94
+ proxyHost: get_config(:proxy_host),
95
+ proxyPort: get_config(:proxy_port)
96
+ }
97
+
98
+ if !conn_opts[:password]
99
+ # Password is not in the config file - grab it
100
+ # from the command line
101
+ conn_opts[:password] = password
102
+ elsif conn_opts[:password].start_with?('base64:')
103
+ conn_opts[:password] = Base64.decode64(conn_opts[:password][7..-1]).chomp
104
+ end
105
+
106
+ # opt :debug, "Log SOAP messages", :short => 'd', :default => (ENV['RBVMOMI_DEBUG'] || false)
107
+
108
+ vim = RbVmomi::VIM.connect conn_opts
109
+ config[:vim] = vim
110
+ vim
111
+ end
112
+
113
+ def password
114
+ @password ||= ui.ask('Enter your password: ') { |q| q.echo = false }
115
+ end
116
+
117
+ def get_vm(vmname)
118
+ vim_connection
119
+ base_folder = find_folder(get_config(:folder))
120
+ traverse_folders_for_vm(base_folder, vmname)
121
+ end
122
+
123
+ def get_vms(vmname)
124
+ vim_connection
125
+ base_folder = find_folder(get_config(:folder))
126
+ traverse_folders_for_vms(base_folder, vmname)
127
+ end
128
+
129
+ def traverse_folders_for_vm(folder, vmname)
130
+ children = folder.children.find_all
131
+ children.each do |child|
132
+ if child.class == RbVmomi::VIM::VirtualMachine && child.name == vmname
133
+ return child
134
+ elsif child.class == RbVmomi::VIM::Folder
135
+ vm = traverse_folders_for_vm(child, vmname)
136
+ return vm if vm
137
+ end
138
+ end
139
+ false
140
+ end
141
+
142
+ def traverse_folders_for_computeresources(folder)
143
+ retval = []
144
+ children = folder.children.find_all
145
+ children.each do |child|
146
+ if child.class == RbVmomi::VIM::ComputeResource || child.class == RbVmomi::VIM::ClusterComputeResource
147
+ retval << child
148
+ elsif child.class == RbVmomi::VIM::Folder
149
+ retval.concat(traverse_folders_for_computeresources(child))
150
+ end
151
+ end
152
+ retval
153
+ end
154
+
155
+ def traverse_folders_for_vms(folder, vmname)
156
+ retval = []
157
+ children = folder.children.find_all
158
+ children.each do |child|
159
+ if child.class == RbVmomi::VIM::VirtualMachine && child.name == vmname
160
+ retval << child
161
+ elsif child.class == RbVmomi::VIM::Folder
162
+ retval.concat(traverse_folders_for_vms(child, vmname))
163
+ end
164
+ end
165
+ retval
166
+ end
167
+
168
+ def traverse_folders_for_dc(folder, dcname)
169
+ children = folder.children.find_all
170
+ children.each do |child|
171
+ if child.class == RbVmomi::VIM::Datacenter && child.name == dcname
172
+ return child
173
+ elsif child.class == RbVmomi::VIM::Folder
174
+ dc = traverse_folders_for_dc(child, dcname)
175
+ return dc if dc
176
+ end
177
+ end
178
+ false
179
+ end
180
+
181
+ def datacenter
182
+ dcname = get_config(:vsphere_dc)
183
+ traverse_folders_for_dc(config[:vim].rootFolder, dcname) || abort('datacenter not found')
184
+ end
185
+
186
+ def find_folder(folderName)
187
+ dc = datacenter
188
+ base_entity = dc.vmFolder
189
+ entity_array = folderName.split('/')
190
+ entity_array.each do |entityArrItem|
191
+ if entityArrItem != ''
192
+ base_entity = base_entity.childEntity.grep(RbVmomi::VIM::Folder).find { |f| f.name == entityArrItem } ||
193
+ abort("no such folder #{folderName} while looking for #{entityArrItem}")
194
+ end
195
+ end
196
+ base_entity
197
+ end
198
+
199
+ def find_network(networkName)
200
+ dc = datacenter
201
+ base_entity = dc.network
202
+ base_entity.find { |f| f.name == networkName } || abort("no such network #{networkName}")
203
+ end
204
+
205
+ def find_pool(poolName)
206
+ dc = datacenter
207
+ base_entity = dc.hostFolder
208
+ entity_array = poolName.split('/')
209
+ entity_array.each do |entityArrItem|
210
+ next if entityArrItem == ''
211
+ if base_entity.is_a? RbVmomi::VIM::Folder
212
+ base_entity = base_entity.childEntity.find { |f| f.name == entityArrItem } ||
213
+ abort("no such pool #{poolName} while looking for #{entityArrItem}")
214
+ elsif base_entity.is_a?(RbVmomi::VIM::ClusterComputeResource) || base_entity.is_a?(RbVmomi::VIM::ComputeResource)
215
+ base_entity = base_entity.resourcePool.resourcePool.find { |f| f.name == entityArrItem } ||
216
+ abort("no such pool #{poolName} while looking for #{entityArrItem}")
217
+ elsif base_entity.is_a? RbVmomi::VIM::ResourcePool
218
+ base_entity = base_entity.resourcePool.find { |f| f.name == entityArrItem } ||
219
+ abort("no such pool #{poolName} while looking for #{entityArrItem}")
220
+ else
221
+ abort "Unexpected Object type encountered #{base_entity.type} while finding resourcePool"
222
+ end
223
+ end
224
+
225
+ base_entity = base_entity.resourcePool if !base_entity.is_a?(RbVmomi::VIM::ResourcePool) && base_entity.respond_to?(:resourcePool)
226
+ base_entity
227
+ end
228
+
229
+ def choose_datastore(dstores, size)
230
+ vmdk_size_b = size.to_i * 1024 * 1024 * 1024
231
+
232
+ candidates = []
233
+ dstores.each do |store|
234
+ avail = number_to_human_size(store.summary[:freeSpace])
235
+ cap = number_to_human_size(store.summary[:capacity])
236
+ puts "#{ui.color('Datastore', :cyan)}: #{store.name} (#{avail}(#{store.summary[:freeSpace]}) / #{cap})"
237
+
238
+ # vm's can span multiple datastores, so instead of grabbing the first one
239
+ # let's find the first datastore with the available space on a LUN the vm
240
+ # is already using, or use a specified LUN (if given)
241
+
242
+ next unless (store.summary[:freeSpace] - vmdk_size_b) > 0
243
+ # also let's not use more than 90% of total space to save room for snapshots.
244
+ cap_remains = 100 * ((store.summary[:freeSpace].to_f - vmdk_size_b.to_f) / store.summary[:capacity].to_f)
245
+ candidates.push(store) if cap_remains.to_i > 10
246
+ end
247
+ if candidates.length > 0
248
+ vmdk_datastore = candidates[0]
249
+ else
250
+ puts 'Insufficient space on all LUNs designated or assigned to the virtual machine. Please specify a new target.'
251
+ vmdk_datastore = nil
252
+ end
253
+ vmdk_datastore
254
+ end
255
+
256
+ def find_datastores_regex(regex)
257
+ stores = []
258
+ puts "Looking for all datastores that match /#{regex}/"
259
+ dc = datacenter
260
+ base_entity = dc.datastore
261
+ base_entity.each do |ds|
262
+ stores.push ds if ds.name.match(/#{regex}/)
263
+ end
264
+ stores
265
+ end
266
+
267
+ def find_datastore(dsName)
268
+ dc = datacenter
269
+ base_entity = dc.datastore
270
+ base_entity.find { |f| f.info.name == dsName } || abort("no such datastore #{dsName}")
271
+ end
272
+
273
+ def find_datastorecluster(dsName, folder = nil)
274
+ unless folder
275
+ dc = datacenter
276
+ folder = dc.datastoreFolder
277
+ end
278
+ folder.childEntity.each do |child|
279
+ if child.class.to_s == 'Folder'
280
+ ds = find_datastorecluster(dsName, child)
281
+ return ds if ds
282
+ elsif child.class.to_s == 'StoragePod' && child.name == dsName
283
+ return child
284
+ end
285
+ end
286
+ nil
287
+ end
288
+
289
+ def find_device(vm, deviceName)
290
+ vm.config.hardware.device.each do |device|
291
+ return device if device.deviceInfo.label == deviceName
292
+ end
293
+ nil
294
+ end
295
+
296
+ def find_all_in_folder(folder, type)
297
+ if folder.instance_of?(RbVmomi::VIM::ClusterComputeResource) || folder.instance_of?(RbVmomi::VIM::ComputeResource)
298
+ folder = folder.resourcePool
299
+ end
300
+ if folder.instance_of?(RbVmomi::VIM::ResourcePool)
301
+ folder.resourcePool.grep(type)
302
+ elsif folder.instance_of?(RbVmomi::VIM::Folder)
303
+ folder.childEntity.grep(type)
304
+ else
305
+ puts "Unknown type #{folder.class}, not enumerating"
306
+ nil
307
+ end
308
+ end
309
+
310
+ def get_path_to_object(object)
311
+ if object.is_a?(RbVmomi::VIM:: ManagedEntity)
312
+ if object.parent.is_a?(RbVmomi::VIM:: ManagedEntity)
313
+ return get_path_to_object(object.parent) + '/' + object.parent.name
314
+ else
315
+ return ''
316
+ end
317
+ else
318
+ puts "Unknown type #{object.class}, not enumerating"
319
+ nil
320
+ end
321
+ end
322
+
323
+ def find_in_folder(folder, type, name)
324
+ folder.childEntity.grep(type).find { |o| o.name == name }
325
+ end
326
+
327
+ def fatal_exit(msg)
328
+ ui.fatal(msg)
329
+ exit 1
330
+ end
331
+
332
+ def tcp_test_port_vm(vm, port)
333
+ ip = vm.guest.ipAddress
334
+ if ip.nil?
335
+ sleep 2
336
+ return false
337
+ end
338
+ tcp_test_port(ip, port)
339
+ end
340
+
341
+ def tcp_test_port(hostname, port)
342
+ tcp_socket = TCPSocket.new(hostname, port)
343
+ readable = IO.select([tcp_socket], nil, nil, 5)
344
+ if readable
345
+ Chef::Log.debug("sshd accepting connections on #{hostname}, banner is #{tcp_socket.gets}") if port == 22
346
+ true
347
+ else
348
+ false
349
+ end
350
+ rescue Errno::ETIMEDOUT
351
+ false
352
+ rescue Errno::EPERM
353
+ false
354
+ rescue Errno::ECONNREFUSED
355
+ sleep 2
356
+ false
357
+ rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH
358
+ sleep 2
359
+ false
360
+ ensure
361
+ tcp_socket && tcp_socket.close
362
+ end
363
+
364
+ def windows?(config)
365
+ is_win_bool = config.guestId.downcase.include?('windows')
366
+ Chef::Log.debug('Identified os as windows.') if is_win_bool
367
+ is_win_bool
368
+ end
369
+
370
+ def linux?(config)
371
+ gid = config.guestId.downcase
372
+ # This makes the assumption that if it isn't mac or windows it's linux
373
+ is_linux_bool = !gid.include?('windows') && !gid.include?('darwin')
374
+ Chef::Log.debug('Identified os as linux.') if is_linux_bool
375
+ is_linux_bool
376
+ end
377
+ end
378
+
379
+ def log_verbose?(level = 1)
380
+ config[:verbosity] >= level
381
+ end
382
+ end
383
+ end