knife-vsphere 0.9.6 → 0.9.7

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.
@@ -1,311 +1,324 @@
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
-
10
- # Base class for vsphere knife commands
11
- class Chef
12
- class Knife
13
- class BaseVsphereCommand < Knife
14
-
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.get_common_options
26
- unless defined? $default
27
- $default = Hash.new
28
- end
29
-
30
- option :vsphere_user,
31
- :short => "-u USERNAME",
32
- :long => "--vsuser USERNAME",
33
- :description => "The username for vsphere"
34
-
35
- option :vsphere_pass,
36
- :short => "-p PASSWORD",
37
- :long => "--vspass PASSWORD",
38
- :description => "The password for vsphere"
39
-
40
- option :vsphere_host,
41
- :long => "--vshost HOST",
42
- :description => "The vsphere host"
43
-
44
- option :vsphere_dc,
45
- :short => "-d DATACENTER",
46
- :long => "--vsdc DATACENTER",
47
- :description => "The Datacenter for vsphere"
48
-
49
- option :vsphere_path,
50
- :long => "--vspath SOAP_PATH",
51
- :description => "The vsphere SOAP endpoint path"
52
- $default[:vsphere_path] = "/sdk"
53
-
54
- option :vsphere_port,
55
- :long => "--vsport PORT",
56
- :description => "The VI SDK port number to use"
57
- $default[:vsphere_port] = 443
58
-
59
- option :vshere_nossl,
60
- :long => "--vsnossl",
61
- :description => "Disable SSL connectivity"
62
-
63
- option :vsphere_insecure,
64
- :long => "--vsinsecure",
65
- :description => "Disable SSL certificate verification"
66
-
67
- option :folder,
68
- :short => "-f FOLDER",
69
- :long => "--folder FOLDER",
70
- :description => "The folder to get VMs from"
71
-
72
- option :proxy_host,
73
- :long => '--proxyhost PROXY_HOSTNAME',
74
- :description => 'Proxy hostname'
75
-
76
- option :proxy_port,
77
- :long => '--proxyport PROXY_PORT',
78
- :description => 'Proxy port'
79
-
80
- $default[:folder] = ''
81
- end
82
-
83
- def get_config(key)
84
- key = key.to_sym
85
- rval = config[key] || Chef::Config[:knife][key] || $default[key]
86
- Chef::Log.debug("value for config item #{key}: #{rval}")
87
- rval
88
- end
89
-
90
- def get_vim_connection
91
-
92
- conn_opts = {
93
- :host => get_config(:vsphere_host),
94
- :path => get_config(:vshere_path),
95
- :port => get_config(:vsphere_port),
96
- :use_ssl => !get_config(:vsphere_nossl),
97
- :user => get_config(:vsphere_user),
98
- :password => get_config(:vsphere_pass),
99
- :insecure => get_config(:vsphere_insecure),
100
- :proxyHost => get_config(:proxy_host),
101
- :proxyPort => get_config(:proxy_port)
102
- }
103
-
104
- # Grab the password from the command line
105
- # if tt is not in the config file
106
- if not conn_opts[:password]
107
- conn_opts[:password] = get_password
108
- end
109
-
110
- # opt :debug, "Log SOAP messages", :short => 'd', :default => (ENV['RBVMOMI_DEBUG'] || false)
111
-
112
- vim = RbVmomi::VIM.connect conn_opts
113
- config[:vim] = vim
114
- return vim
115
- end
116
-
117
- def get_password
118
- @password ||= ui.ask("Enter your password: ") { |q| q.echo = false }
119
- end
120
-
121
- def get_vm(vmname)
122
- vim = get_vim_connection
123
- baseFolder = find_folder(get_config(:folder));
124
- retval = traverse_folders_for_vm(baseFolder, vmname)
125
- return retval
126
- end
127
-
128
- def traverse_folders_for_vm(folder, vmname)
129
- # not sure why @vm is necessary, but it returns class Array
130
- # instead of class VirtualMachine without it... ugh
131
- @vm = nil
132
- folders = find_all_in_folder(folder, RbVmomi::VIM::Folder)
133
- folders.each do |child|
134
- traverse_folders_for_vm(child, vmname)
135
- vms = find_all_in_folder(folder, RbVmomi::VIM::VirtualMachine)
136
- vms.each do |vm|
137
- if vm.name == vmname
138
- @vm = vm
139
- return @vm
140
- end
141
- end
142
- end
143
- return @vm
144
- end
145
-
146
- def get_datacenter
147
- dcname = get_config(:vsphere_dc)
148
- config[:vim].rootFolder.children.find { |child| child.name == dcname && child.class == RbVmomi::VIM::Datacenter } or abort "datacenter not found"
149
- end
150
-
151
- def find_folder(folderName)
152
- dc = get_datacenter
153
- baseEntity = dc.vmFolder
154
- entityArray = folderName.split('/')
155
- entityArray.each do |entityArrItem|
156
- if entityArrItem != ''
157
- baseEntity = baseEntity.childEntity.grep(RbVmomi::VIM::Folder).find { |f| f.name == entityArrItem } or
158
- abort "no such folder #{folderName} while looking for #{entityArrItem}"
159
- end
160
- end
161
- baseEntity
162
- end
163
-
164
- def find_network(networkName)
165
- dc = get_datacenter
166
- baseEntity = dc.network
167
- baseEntity.find { |f| f.name == networkName } or abort "no such network #{networkName}"
168
- end
169
-
170
- def find_pool(poolName)
171
- dc = get_datacenter
172
- baseEntity = dc.hostFolder
173
- entityArray = poolName.split('/')
174
- entityArray.each do |entityArrItem|
175
- if entityArrItem != ''
176
- if baseEntity.is_a? RbVmomi::VIM::Folder
177
- baseEntity = baseEntity.childEntity.find { |f| f.name == entityArrItem } or
178
- abort "no such pool #{poolName} while looking for #{entityArrItem}"
179
- elsif baseEntity.is_a? RbVmomi::VIM::ClusterComputeResource or baseEntity.is_a? RbVmomi::VIM::ComputeResource
180
- baseEntity = baseEntity.resourcePool.resourcePool.find { |f| f.name == entityArrItem } or
181
- abort "no such pool #{poolName} while looking for #{entityArrItem}"
182
- elsif baseEntity.is_a? RbVmomi::VIM::ResourcePool
183
- baseEntity = baseEntity.resourcePool.find { |f| f.name == entityArrItem } or
184
- abort "no such pool #{poolName} while looking for #{entityArrItem}"
185
- else
186
- abort "Unexpected Object type encountered #{baseEntity.type} while finding resourcePool"
187
- end
188
- end
189
- end
190
-
191
- baseEntity = baseEntity.resourcePool if not baseEntity.is_a?(RbVmomi::VIM::ResourcePool) and baseEntity.respond_to?(:resourcePool)
192
- baseEntity
193
- end
194
-
195
- def choose_datastore(dstores, size)
196
- vmdk_size_kb = size.to_i * 1024 * 1024
197
- vmdk_size_B = size.to_i * 1024 * 1024 * 1024
198
-
199
- candidates = []
200
- dstores.each do |store|
201
- avail = number_to_human_size(store.summary[:freeSpace])
202
- cap = number_to_human_size(store.summary[:capacity])
203
- puts "#{ui.color("Datastore", :cyan)}: #{store.name} (#{avail}(#{store.summary[:freeSpace]}) / #{cap})"
204
-
205
- # vm's can span multiple datastores, so instead of grabbing the first one
206
- # let's find the first datastore with the available space on a LUN the vm
207
- # is already using, or use a specified LUN (if given)
208
-
209
-
210
- if (store.summary[:freeSpace] - vmdk_size_B) > 0
211
- # also let's not use more than 90% of total space to save room for snapshots.
212
- cap_remains = 100 * ((store.summary[:freeSpace].to_f - vmdk_size_B.to_f) / store.summary[:capacity].to_f)
213
- if (cap_remains.to_i > 10)
214
- candidates.push(store)
215
- end
216
- end
217
- end
218
- if candidates.length > 0
219
- vmdk_datastore = candidates[0]
220
- else
221
- puts "Insufficient space on all LUNs designated or assigned to the virtual machine. Please specify a new target."
222
- vmdk_datastore = nil
223
- end
224
- return vmdk_datastore
225
- end
226
-
227
-
228
- def find_datastores_regex(regex)
229
- stores = Array.new()
230
- puts "Looking for all datastores that match /#{regex}/"
231
- dc = get_datacenter
232
- baseEntity = dc.datastore
233
- baseEntity.each do |ds|
234
- if ds.name.match /#{regex}/
235
- stores.push ds
236
- end
237
- end
238
- return stores
239
- end
240
-
241
- def find_datastore(dsName)
242
- dc = get_datacenter
243
- baseEntity = dc.datastore
244
- baseEntity.find { |f| f.info.name == dsName } or abort "no such datastore #{dsName}"
245
- end
246
-
247
- def find_device(vm, deviceName)
248
- vm.config.hardware.device.each do |device|
249
- return device if device.deviceInfo.label == deviceName
250
- end
251
- nil
252
- end
253
-
254
- def find_all_in_folder(folder, type)
255
- if folder.instance_of?(RbVmomi::VIM::ClusterComputeResource) or folder.instance_of?(RbVmomi::VIM::ComputeResource)
256
- folder = folder.resourcePool
257
- end
258
- if folder.instance_of?(RbVmomi::VIM::ResourcePool)
259
- folder.resourcePool.grep(type)
260
- elsif folder.instance_of?(RbVmomi::VIM::Folder)
261
- folder.childEntity.grep(type)
262
- else
263
- puts "Unknown type #{folder.class}, not enumerating"
264
- nil
265
- end
266
- end
267
-
268
- def find_in_folder(folder, type, name)
269
- folder.childEntity.grep(type).find { |o| o.name == name }
270
- end
271
-
272
- def fatal_exit(msg)
273
- ui.fatal(msg)
274
- exit 1
275
- end
276
-
277
- def tcp_test_port_vm(vm, port)
278
- ip = vm.guest.ipAddress
279
- if ip.nil?
280
- sleep 2
281
- return false
282
- end
283
- tcp_test_port(ip, port)
284
- end
285
-
286
- def tcp_test_port(hostname, port)
287
- tcp_socket = TCPSocket.new(hostname, port)
288
- readable = IO.select([tcp_socket], nil, nil, 5)
289
- if readable
290
- Chef::Log.debug("sshd accepting connections on #{hostname}, banner is #{tcp_socket.gets}") if port == 22
291
- true
292
- else
293
- false
294
- end
295
- rescue Errno::ETIMEDOUT
296
- false
297
- rescue Errno::EPERM
298
- false
299
- rescue Errno::ECONNREFUSED
300
- sleep 2
301
- false
302
- rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH
303
- sleep 2
304
- false
305
- ensure
306
- tcp_socket && tcp_socket.close
307
- end
308
-
309
- end
310
- end
311
- 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
+
10
+ # Base class for vsphere knife commands
11
+ class Chef
12
+ class Knife
13
+ class BaseVsphereCommand < Knife
14
+
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.get_common_options
26
+ unless defined? $default
27
+ $default = Hash.new
28
+ end
29
+
30
+ option :vsphere_user,
31
+ :short => "-u USERNAME",
32
+ :long => "--vsuser USERNAME",
33
+ :description => "The username for vsphere"
34
+
35
+ option :vsphere_pass,
36
+ :short => "-p PASSWORD",
37
+ :long => "--vspass PASSWORD",
38
+ :description => "The password for vsphere"
39
+
40
+ option :vsphere_host,
41
+ :long => "--vshost HOST",
42
+ :description => "The vsphere host"
43
+
44
+ option :vsphere_dc,
45
+ :short => "-d DATACENTER",
46
+ :long => "--vsdc DATACENTER",
47
+ :description => "The Datacenter for vsphere"
48
+
49
+ option :vsphere_path,
50
+ :long => "--vspath SOAP_PATH",
51
+ :description => "The vsphere SOAP endpoint path"
52
+ $default[:vsphere_path] = "/sdk"
53
+
54
+ option :vsphere_port,
55
+ :long => "--vsport PORT",
56
+ :description => "The VI SDK port number to use"
57
+ $default[:vsphere_port] = 443
58
+
59
+ option :vshere_nossl,
60
+ :long => "--vsnossl",
61
+ :description => "Disable SSL connectivity"
62
+
63
+ option :vsphere_insecure,
64
+ :long => "--vsinsecure",
65
+ :description => "Disable SSL certificate verification"
66
+
67
+ option :folder,
68
+ :short => "-f FOLDER",
69
+ :long => "--folder FOLDER",
70
+ :description => "The folder to get VMs from"
71
+
72
+ option :proxy_host,
73
+ :long => '--proxyhost PROXY_HOSTNAME',
74
+ :description => 'Proxy hostname'
75
+
76
+ option :proxy_port,
77
+ :long => '--proxyport PROXY_PORT',
78
+ :description => 'Proxy port'
79
+
80
+ $default[:folder] = ''
81
+ end
82
+
83
+ def get_config(key)
84
+ key = key.to_sym
85
+ rval = config[key] || Chef::Config[:knife][key] || $default[key]
86
+ Chef::Log.debug("value for config item #{key}: #{rval}")
87
+ rval
88
+ end
89
+
90
+ def get_vim_connection
91
+
92
+ conn_opts = {
93
+ :host => get_config(:vsphere_host),
94
+ :path => get_config(:vshere_path),
95
+ :port => get_config(:vsphere_port),
96
+ :use_ssl => !get_config(:vsphere_nossl),
97
+ :user => get_config(:vsphere_user),
98
+ :password => get_config(:vsphere_pass),
99
+ :insecure => get_config(:vsphere_insecure),
100
+ :proxyHost => get_config(:proxy_host),
101
+ :proxyPort => get_config(:proxy_port)
102
+ }
103
+
104
+ # Grab the password from the command line
105
+ # if tt is not in the config file
106
+ if not conn_opts[:password]
107
+ conn_opts[:password] = get_password
108
+ end
109
+
110
+ # opt :debug, "Log SOAP messages", :short => 'd', :default => (ENV['RBVMOMI_DEBUG'] || false)
111
+
112
+ vim = RbVmomi::VIM.connect conn_opts
113
+ config[:vim] = vim
114
+ return vim
115
+ end
116
+
117
+ def get_password
118
+ @password ||= ui.ask("Enter your password: ") { |q| q.echo = false }
119
+ end
120
+
121
+ def get_vm(vmname)
122
+ vim = get_vim_connection
123
+ baseFolder = find_folder(get_config(:folder));
124
+ retval = traverse_folders_for_vm(baseFolder, vmname)
125
+ return retval
126
+ end
127
+
128
+ def traverse_folders_for_vm(folder, vmname)
129
+ # not sure why @vm is necessary, but it returns class Array
130
+ # instead of class VirtualMachine without it... ugh
131
+ @vm = nil
132
+ folders = find_all_in_folder(folder, RbVmomi::VIM::Folder)
133
+ folders.each do |child|
134
+ traverse_folders_for_vm(child, vmname)
135
+ vms = find_all_in_folder(folder, RbVmomi::VIM::VirtualMachine)
136
+ vms.each do |vm|
137
+ if vm.name == vmname
138
+ @vm = vm
139
+ return @vm
140
+ end
141
+ end
142
+ end
143
+ return @vm
144
+ end
145
+
146
+ def traverse_folders_for_dc(folder, dcname)
147
+ children = folder.children.find_all
148
+ children.each do |child|
149
+ if child.class == RbVmomi::VIM::Datacenter && child.name == dcname
150
+ return child
151
+ elsif child.class == RbVmomi::VIM::Folder
152
+ dc = traverse_folders_for_dc(child, dcname)
153
+ if dc then return dc end
154
+ end
155
+ end
156
+ return false
157
+ end
158
+
159
+ def get_datacenter
160
+ dcname = get_config(:vsphere_dc)
161
+ traverse_folders_for_dc(config[:vim].rootFolder, dcname) or abort "datacenter not found"
162
+ end
163
+
164
+ def find_folder(folderName)
165
+ dc = get_datacenter
166
+ baseEntity = dc.vmFolder
167
+ entityArray = folderName.split('/')
168
+ entityArray.each do |entityArrItem|
169
+ if entityArrItem != ''
170
+ baseEntity = baseEntity.childEntity.grep(RbVmomi::VIM::Folder).find { |f| f.name == entityArrItem } or
171
+ abort "no such folder #{folderName} while looking for #{entityArrItem}"
172
+ end
173
+ end
174
+ baseEntity
175
+ end
176
+
177
+ def find_network(networkName)
178
+ dc = get_datacenter
179
+ baseEntity = dc.network
180
+ baseEntity.find { |f| f.name == networkName } or abort "no such network #{networkName}"
181
+ end
182
+
183
+ def find_pool(poolName)
184
+ dc = get_datacenter
185
+ baseEntity = dc.hostFolder
186
+ entityArray = poolName.split('/')
187
+ entityArray.each do |entityArrItem|
188
+ if entityArrItem != ''
189
+ if baseEntity.is_a? RbVmomi::VIM::Folder
190
+ baseEntity = baseEntity.childEntity.find { |f| f.name == entityArrItem } or
191
+ abort "no such pool #{poolName} while looking for #{entityArrItem}"
192
+ elsif baseEntity.is_a? RbVmomi::VIM::ClusterComputeResource or baseEntity.is_a? RbVmomi::VIM::ComputeResource
193
+ baseEntity = baseEntity.resourcePool.resourcePool.find { |f| f.name == entityArrItem } or
194
+ abort "no such pool #{poolName} while looking for #{entityArrItem}"
195
+ elsif baseEntity.is_a? RbVmomi::VIM::ResourcePool
196
+ baseEntity = baseEntity.resourcePool.find { |f| f.name == entityArrItem } or
197
+ abort "no such pool #{poolName} while looking for #{entityArrItem}"
198
+ else
199
+ abort "Unexpected Object type encountered #{baseEntity.type} while finding resourcePool"
200
+ end
201
+ end
202
+ end
203
+
204
+ baseEntity = baseEntity.resourcePool if not baseEntity.is_a?(RbVmomi::VIM::ResourcePool) and baseEntity.respond_to?(:resourcePool)
205
+ baseEntity
206
+ end
207
+
208
+ def choose_datastore(dstores, size)
209
+ vmdk_size_kb = size.to_i * 1024 * 1024
210
+ vmdk_size_B = size.to_i * 1024 * 1024 * 1024
211
+
212
+ candidates = []
213
+ dstores.each do |store|
214
+ avail = number_to_human_size(store.summary[:freeSpace])
215
+ cap = number_to_human_size(store.summary[:capacity])
216
+ puts "#{ui.color("Datastore", :cyan)}: #{store.name} (#{avail}(#{store.summary[:freeSpace]}) / #{cap})"
217
+
218
+ # vm's can span multiple datastores, so instead of grabbing the first one
219
+ # let's find the first datastore with the available space on a LUN the vm
220
+ # is already using, or use a specified LUN (if given)
221
+
222
+
223
+ if (store.summary[:freeSpace] - vmdk_size_B) > 0
224
+ # also let's not use more than 90% of total space to save room for snapshots.
225
+ cap_remains = 100 * ((store.summary[:freeSpace].to_f - vmdk_size_B.to_f) / store.summary[:capacity].to_f)
226
+ if (cap_remains.to_i > 10)
227
+ candidates.push(store)
228
+ end
229
+ end
230
+ end
231
+ if candidates.length > 0
232
+ vmdk_datastore = candidates[0]
233
+ else
234
+ puts "Insufficient space on all LUNs designated or assigned to the virtual machine. Please specify a new target."
235
+ vmdk_datastore = nil
236
+ end
237
+ return vmdk_datastore
238
+ end
239
+
240
+
241
+ def find_datastores_regex(regex)
242
+ stores = Array.new()
243
+ puts "Looking for all datastores that match /#{regex}/"
244
+ dc = get_datacenter
245
+ baseEntity = dc.datastore
246
+ baseEntity.each do |ds|
247
+ if ds.name.match /#{regex}/
248
+ stores.push ds
249
+ end
250
+ end
251
+ return stores
252
+ end
253
+
254
+ def find_datastore(dsName)
255
+ dc = get_datacenter
256
+ baseEntity = dc.datastore
257
+ baseEntity.find { |f| f.info.name == dsName } or abort "no such datastore #{dsName}"
258
+ end
259
+
260
+ def find_device(vm, deviceName)
261
+ vm.config.hardware.device.each do |device|
262
+ return device if device.deviceInfo.label == deviceName
263
+ end
264
+ nil
265
+ end
266
+
267
+ def find_all_in_folder(folder, type)
268
+ if folder.instance_of?(RbVmomi::VIM::ClusterComputeResource) or folder.instance_of?(RbVmomi::VIM::ComputeResource)
269
+ folder = folder.resourcePool
270
+ end
271
+ if folder.instance_of?(RbVmomi::VIM::ResourcePool)
272
+ folder.resourcePool.grep(type)
273
+ elsif folder.instance_of?(RbVmomi::VIM::Folder)
274
+ folder.childEntity.grep(type)
275
+ else
276
+ puts "Unknown type #{folder.class}, not enumerating"
277
+ nil
278
+ end
279
+ end
280
+
281
+ def find_in_folder(folder, type, name)
282
+ folder.childEntity.grep(type).find { |o| o.name == name }
283
+ end
284
+
285
+ def fatal_exit(msg)
286
+ ui.fatal(msg)
287
+ exit 1
288
+ end
289
+
290
+ def tcp_test_port_vm(vm, port)
291
+ ip = vm.guest.ipAddress
292
+ if ip.nil?
293
+ sleep 2
294
+ return false
295
+ end
296
+ tcp_test_port(ip, port)
297
+ end
298
+
299
+ def tcp_test_port(hostname, port)
300
+ tcp_socket = TCPSocket.new(hostname, port)
301
+ readable = IO.select([tcp_socket], nil, nil, 5)
302
+ if readable
303
+ Chef::Log.debug("sshd accepting connections on #{hostname}, banner is #{tcp_socket.gets}") if port == 22
304
+ true
305
+ else
306
+ false
307
+ end
308
+ rescue Errno::ETIMEDOUT
309
+ false
310
+ rescue Errno::EPERM
311
+ false
312
+ rescue Errno::ECONNREFUSED
313
+ sleep 2
314
+ false
315
+ rescue Errno::EHOSTUNREACH, Errno::ENETUNREACH
316
+ sleep 2
317
+ false
318
+ ensure
319
+ tcp_socket && tcp_socket.close
320
+ end
321
+
322
+ end
323
+ end
324
+ end
@@ -1,4 +1,4 @@
1
1
  module KnifeVsphere
2
- VERSION = "0.9.6"
2
+ VERSION = "0.9.7"
3
3
  end
4
4
 
metadata CHANGED
@@ -1,56 +1,60 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: knife-vsphere
3
- version: !ruby/object:Gem::Version
4
- version: 0.9.6
3
+ version: !ruby/object:Gem::Version
5
4
  prerelease:
5
+ version: 0.9.7
6
6
  platform: ruby
7
- authors:
7
+ authors:
8
8
  - Ezra Pagel
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-12-05 00:00:00.000000000 -06:00
12
+
13
+ date: 2013-12-09 00:00:00 -06:00
13
14
  default_executable:
14
- dependencies:
15
- - !ruby/object:Gem::Dependency
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
16
17
  name: netaddr
17
- requirement: &70243821493560 !ruby/object:Gem::Requirement
18
+ prerelease: false
19
+ requirement: &id001 !ruby/object:Gem::Requirement
18
20
  none: false
19
- requirements:
21
+ requirements:
20
22
  - - ~>
21
- - !ruby/object:Gem::Version
23
+ - !ruby/object:Gem::Version
22
24
  version: 1.5.0
23
25
  type: :runtime
24
- prerelease: false
25
- version_requirements: *70243821493560
26
- - !ruby/object:Gem::Dependency
26
+ version_requirements: *id001
27
+ - !ruby/object:Gem::Dependency
27
28
  name: chef
28
- requirement: &70243821493060 !ruby/object:Gem::Requirement
29
+ prerelease: false
30
+ requirement: &id002 !ruby/object:Gem::Requirement
29
31
  none: false
30
- requirements:
31
- - - ! '>='
32
- - !ruby/object:Gem::Version
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
33
35
  version: 0.10.0
34
36
  type: :runtime
35
- prerelease: false
36
- version_requirements: *70243821493060
37
- - !ruby/object:Gem::Dependency
37
+ version_requirements: *id002
38
+ - !ruby/object:Gem::Dependency
38
39
  name: rbvmomi
39
- requirement: &70243821492260 !ruby/object:Gem::Requirement
40
+ prerelease: false
41
+ requirement: &id003 !ruby/object:Gem::Requirement
40
42
  none: false
41
- requirements:
43
+ requirements:
42
44
  - - ~>
43
- - !ruby/object:Gem::Version
45
+ - !ruby/object:Gem::Version
44
46
  version: 1.5.1
45
47
  type: :runtime
46
- prerelease: false
47
- version_requirements: *70243821492260
48
+ version_requirements: *id003
48
49
  description: VMware vSphere Support for Chef's Knife Command
49
50
  email: ezra@cpan.org
50
51
  executables: []
52
+
51
53
  extensions: []
54
+
52
55
  extra_rdoc_files: []
53
- files:
56
+
57
+ files:
54
58
  - lib/chef/knife/base_vsphere_command.rb
55
59
  - lib/chef/knife/vshpere_vm_move.rb
56
60
  - lib/chef/knife/vsphere_customization_list.rb
@@ -71,28 +75,31 @@ files:
71
75
  - lib/knife-vsphere/version.rb
72
76
  has_rdoc: true
73
77
  homepage: http://github.com/ezrapagel/knife-vsphere
74
- licenses:
78
+ licenses:
75
79
  - Apache
76
80
  post_install_message:
77
81
  rdoc_options: []
78
- require_paths:
82
+
83
+ require_paths:
79
84
  - lib
80
- required_ruby_version: !ruby/object:Gem::Requirement
85
+ required_ruby_version: !ruby/object:Gem::Requirement
81
86
  none: false
82
- requirements:
83
- - - ! '>='
84
- - !ruby/object:Gem::Version
85
- version: '0'
86
- required_rubygems_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: "0"
91
+ required_rubygems_version: !ruby/object:Gem::Requirement
87
92
  none: false
88
- requirements:
89
- - - ! '>='
90
- - !ruby/object:Gem::Version
91
- version: '0'
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: "0"
92
97
  requirements: []
98
+
93
99
  rubyforge_project:
94
100
  rubygems_version: 1.6.2
95
101
  signing_key:
96
102
  specification_version: 3
97
103
  summary: vSphere Support for Knife
98
104
  test_files: []
105
+