knife-vsphere 1.0.1 → 1.2.0

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.
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