knife-vsphere 0.1.8 → 0.1.9

Sign up to get free protection for your applications and to get access to all the features.
@@ -22,73 +22,71 @@ class Chef
22
22
  require 'chef/json_compat'
23
23
  end
24
24
 
25
-
26
25
  def self.get_common_options
26
+ $default = Hash.new
27
27
 
28
28
  option :vsphere_user,
29
29
  :short => "-u USERNAME",
30
- :long => "--user USERNAME",
31
- :description => "The username for the host"
30
+ :long => "--vsuser USERNAME",
31
+ :description => "The username for vsphere"
32
32
 
33
33
  option :vsphere_pass,
34
34
  :short => "-p PASSWORD",
35
- :long => "--password PASSWORD",
36
- :description => "The password for the host"
35
+ :long => "--vspass PASSWORD",
36
+ :description => "The password for vsphere"
37
+
38
+ option :vsphere_host,
39
+ :long => "--vshost",
40
+ :description => "The vsphere host"
37
41
 
38
- option :datacenter,
42
+ option :vsphere_dc,
39
43
  :short => "-d DATACENTER",
40
- :long => "--datacenter DATACENTER",
41
- :description => "The Datacenter to create the VM in"
42
-
43
- option :path,
44
- :long => "--path SOAP_PATH",
45
- :description => "The SOAP endpoint path",
46
- :proc => Proc.new { |p| Chef::Config[:knife][:path] = p },
47
- :default => "/sdk"
48
-
49
- option :port,
50
- :long => "--port PORT",
51
- :description => "The VI SDK port number to use",
52
- :proc => Proc.new { |p| Chef::Config[:knife][:port] = p },
53
- :default => 443
54
-
55
- option :use_ssl,
56
- :long => "--ssl USE_SSL",
57
- :description => "Whether to use SSL connection",
58
- :default => true
59
-
60
- option :insecure,
61
- :short => "-i USE_INSECURE_SSL",
62
- :long => "--insecure USE_INSECURE_SSL",
63
- :description => "Determines whether SSL certificate verification is skipped",
64
- :default => true
44
+ :long => "--vsdc DATACENTER",
45
+ :description => "The Datacenter for vsphere"
46
+
47
+ option :vsphere_path,
48
+ :long => "--vspath SOAP_PATH",
49
+ :description => "The vsphere SOAP endpoint path"
50
+ $default[:vsphere_path] = "/sdk"
51
+
52
+ option :vsphere_port,
53
+ :long => "--vsport PORT",
54
+ :description => "The VI SDK port number to use"
55
+ $default[:vsphere_port] = 443
56
+
57
+ option :vshere_ssl,
58
+ :long => "--vsssl USE_SSL",
59
+ :description => "Whether to use SSL connection"
60
+ $default[:vsphere_ssl] = true
61
+
62
+ option :vsphere_insecure,
63
+ :long => "--vsinsecure USE_INSECURE_SSL",
64
+ :description => "Determines whether SSL certificate verification is skipped"
65
65
 
66
66
  option :folder,
67
67
  :short => "-f FOLDER",
68
68
  :long => "--folder FOLDER",
69
- :description => "The folder to get VMs from",
70
- :default => ''
71
-
69
+ :description => "The folder to get VMs from"
70
+ $default[:folder] = ''
72
71
  end
73
72
 
74
- def locate_config_value(key)
73
+ def get_config(key)
75
74
  key = key.to_sym
76
- Chef::Config[:knife][key] || config[key]
75
+ config[key] || Chef::Config[:knife][key] || $default[key]
77
76
  end
78
77
 
79
78
  def get_vim_connection
80
79
 
81
80
  conn_opts = {
82
- :host => locate_config_value(:vsphere_host),
83
- :path => config[:path],
84
- :port => config[:port],
85
- :use_ssl => config[:ssl],
86
- :user => locate_config_value(:vsphere_user),
87
- :password => locate_config_value(:vsphere_pass),
88
- :insecure => config[:insecure]
81
+ :host => get_config(:vsphere_host),
82
+ :path => get_config(:vshere_path),
83
+ :port => get_config(:vsphere_port),
84
+ :use_ssl => get_config(:vsphere_ssl),
85
+ :user => get_config(:vsphere_user),
86
+ :password => get_config(:vsphere_pass),
87
+ :insecure => get_config(:vsphere_insecure)
89
88
  }
90
89
 
91
- # opt :insecure, "don't verify ssl certificate", :short => 'k', :default => (ENV['RBVMOMI_INSECURE'] == '1')
92
90
  # opt :debug, "Log SOAP messages", :short => 'd', :default => (ENV['RBVMOMI_DEBUG'] || false)
93
91
 
94
92
  vim = RbVmomi::VIM.connect conn_opts
@@ -97,7 +95,7 @@ class Chef
97
95
  end
98
96
 
99
97
  def find_folder(folderName)
100
- dcname = config[:vsphere_dc] || Chef::Config[:knife][:vsphere_dc]
98
+ dcname = get_config(:vsphere_dc)
101
99
  dc = config[:vim].serviceInstance.find_datacenter(dcname) or abort "datacenter not found"
102
100
  baseEntity = dc.vmFolder
103
101
  entityArray = folderName.split('/')
@@ -111,14 +109,14 @@ class Chef
111
109
  end
112
110
 
113
111
  def find_network(networkName)
114
- dcname = config[:vsphere_dc] || Chef::Config[:knife][:vsphere_dc]
112
+ dcname = get_config(:vsphere_dc)
115
113
  dc = config[:vim].serviceInstance.find_datacenter(dcname) or abort "datacenter not found"
116
114
  baseEntity = dc.network
117
115
  baseEntity.find { |f| f.name == networkName } or abort "no such network #{networkName}"
118
116
  end
119
117
 
120
118
  def find_pool(poolName)
121
- dcname = config[:vsphere_dc] || Chef::Config[:knife][:vsphere_dc]
119
+ dcname = get_config(:vsphere_dc)
122
120
  dc = config[:vim].serviceInstance.find_datacenter(dcname) or abort "datacenter not found"
123
121
  baseEntity = dc.hostFolder
124
122
  entityArray = poolName.split('/')
@@ -144,7 +142,7 @@ class Chef
144
142
  end
145
143
 
146
144
  def find_datastore(dsName)
147
- dcname = config[:vsphere_dc] || Chef::Config[:knife][:vsphere_dc]
145
+ dcname = get_config(:vsphere_dc)
148
146
  dc = config[:vim].serviceInstance.find_datacenter(dcname) or abort "datacenter not found"
149
147
  baseEntity = dc.datastore
150
148
  baseEntity.find { |f| f.info.name == dsName } or abort "no such datastore #{dsName}"
@@ -46,7 +46,7 @@ class Chef::Knife::VsphereDatastoreList < Chef::Knife::BaseVsphereCommand
46
46
  $stdout.sync = true
47
47
 
48
48
  vim = get_vim_connection
49
- dcname = config[:vsphere_dc] || Chef::Config[:knife][:vsphere_dc]
49
+ dcname = get_config(:vsphere_dc)
50
50
  dc = config[:vim].serviceInstance.find_datacenter(dcname) or abort "datacenter not found"
51
51
  dc.datastore.each do |store|
52
52
  avail = number_to_human_size(store.summary[:freeSpace])
@@ -20,7 +20,7 @@ class Chef::Knife::VsphereTemplateList < Chef::Knife::BaseVsphereCommand
20
20
 
21
21
  vim = get_vim_connection
22
22
 
23
- baseFolder = find_folder(config[:folder]);
23
+ baseFolder = find_folder(get_config(:folder));
24
24
 
25
25
  vms = find_all_in_folder(baseFolder, RbVmomi::VIM::VirtualMachine).
26
26
  select {|v| !v.config.nil? && v.config.template == true }
@@ -0,0 +1,37 @@
1
+ # Author: Jesse Campbell
2
+ #
3
+ # Permission to use, copy, modify, and/or distribute this software for
4
+ # any purpose with or without fee is hereby granted, provided that the
5
+ # above copyright notice and this permission notice appear in all
6
+ # copies.
7
+ #
8
+ # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
9
+ # WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
10
+ # WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
11
+ # AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
12
+ # DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
13
+ # OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
14
+ # TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15
+ # PERFORMANCE OF THIS SOFTWARE
16
+
17
+ require 'chef/knife'
18
+ require 'chef/knife/BaseVsphereCommand'
19
+
20
+ # Lists all known data stores in datacenter with sizes
21
+ class Chef::Knife::VsphereVlanList < Chef::Knife::BaseVsphereCommand
22
+
23
+ banner "knife vsphere vlan list"
24
+
25
+ get_common_options
26
+ def run
27
+ $stdout.sync = true
28
+
29
+ vim = get_vim_connection
30
+ dcname = get_config(:vsphere_dc)
31
+ dc = config[:vim].serviceInstance.find_datacenter(dcname) or abort "datacenter not found"
32
+ dc.network.each do |network|
33
+ puts "#{ui.color("VLAN", :cyan)}: #{network.name}"
34
+ end
35
+ end
36
+ end
37
+
@@ -84,13 +84,11 @@ class Chef::Knife::VsphereVmClone < Chef::Knife::BaseVsphereCommand
84
84
 
85
85
  option :power,
86
86
  :long => "--start STARTVM",
87
- :description => "Indicates whether to start the VM after a successful clone",
88
- :default => false
87
+ :description => "Indicates whether to start the VM after a successful clone"
89
88
 
90
89
  option :bootstrap,
91
90
  :long => "--bootstrap FALSE",
92
- :description => "Indicates whether to bootstrap the VM",
93
- :default => false
91
+ :description => "Indicates whether to bootstrap the VM"
94
92
 
95
93
  option :fqdn,
96
94
  :long => "--fqdn SERVER_FQDN",
@@ -99,8 +97,8 @@ class Chef::Knife::VsphereVmClone < Chef::Knife::BaseVsphereCommand
99
97
  option :ssh_user,
100
98
  :short => "-x USERNAME",
101
99
  :long => "--ssh-user USERNAME",
102
- :description => "The ssh username",
103
- :default => "root"
100
+ :description => "The ssh username"
101
+ $default[:ssh_user] = "root"
104
102
 
105
103
  option :ssh_password,
106
104
  :short => "-P PASSWORD",
@@ -110,9 +108,8 @@ class Chef::Knife::VsphereVmClone < Chef::Knife::BaseVsphereCommand
110
108
  option :ssh_port,
111
109
  :short => "-p PORT",
112
110
  :long => "--ssh-port PORT",
113
- :description => "The ssh port",
114
- :default => "22",
115
- :proc => Proc.new { |key| Chef::Config[:knife][:ssh_port] = key }
111
+ :description => "The ssh port"
112
+ $default[:ssh_port] = 22
116
113
 
117
114
  option :identity_file,
118
115
  :short => "-i IDENTITY_FILE",
@@ -131,7 +128,7 @@ class Chef::Knife::VsphereVmClone < Chef::Knife::BaseVsphereCommand
131
128
  option :bootstrap_version,
132
129
  :long => "--bootstrap-version VERSION",
133
130
  :description => "The version of Chef to install",
134
- :proc => lambda { |v| Chef::Config[:knife][:bootstrap_version] = v }
131
+ :proc => Proc.new { |v| Chef::Config[:knife][:bootstrap_version] = v }
135
132
 
136
133
  option :bootstrap_proxy,
137
134
  :long => "--bootstrap-proxy PROXY_URL",
@@ -141,26 +138,23 @@ class Chef::Knife::VsphereVmClone < Chef::Knife::BaseVsphereCommand
141
138
  option :distro,
142
139
  :short => "-d DISTRO",
143
140
  :long => "--distro DISTRO",
144
- :description => "Bootstrap a distro using a template",
145
- :default => "ubuntu10.04-gems"
141
+ :description => "Bootstrap a distro using a template"
142
+ $default[:distro] = "ubuntu10.04-gems"
146
143
 
147
144
  option :template_file,
148
145
  :long => "--template-file TEMPLATE",
149
- :description => "Full path to location of template to use",
150
- :default => false
146
+ :description => "Full path to location of template to use"
151
147
 
152
148
  option :run_list,
153
149
  :short => "-r RUN_LIST",
154
150
  :long => "--run-list RUN_LIST",
155
- :description => "Comma separated list of roles/recipes to apply",
156
- :proc => lambda { |o| o.split(/[\s,]+/) },
157
- :default => []
151
+ :description => "Comma separated list of roles/recipes to apply"
152
+ $default[:run_list] = ''
158
153
 
159
154
  option :no_host_key_verify,
160
155
  :long => "--no-host-key-verify",
161
156
  :description => "Disable host key verification",
162
- :boolean => true,
163
- :default => false
157
+ :boolean => true
164
158
 
165
159
  def run
166
160
  $stdout.sync = true
@@ -176,17 +170,17 @@ class Chef::Knife::VsphereVmClone < Chef::Knife::BaseVsphereCommand
176
170
 
177
171
  vim = get_vim_connection
178
172
 
179
- dcname = config[:vsphere_dc] || Chef::Config[:knife][:vsphere_dc]
173
+ dcname = get_config(:vsphere_dc)
180
174
  dc = vim.serviceInstance.find_datacenter(dcname) or abort "datacenter not found"
181
175
 
182
- src_folder = find_folder(config[:folder]) || dc.vmFolder
176
+ src_folder = find_folder(get_config(:folder)) || dc.vmFolder
183
177
 
184
178
  src_vm = find_in_folder(src_folder, RbVmomi::VIM::VirtualMachine, config[:source_vm]) or
185
179
  abort "VM/Template not found"
186
180
 
187
181
  clone_spec = generate_clone_spec(src_vm.config)
188
182
 
189
- cust_folder = config[:dest_folder] || config[:folder]
183
+ cust_folder = config[:dest_folder] || get_config(:folder)
190
184
 
191
185
  dest_folder = cust_folder.nil? ? src_vm.vmFolder : find_folder(cust_folder)
192
186
 
@@ -195,14 +189,14 @@ class Chef::Knife::VsphereVmClone < Chef::Knife::BaseVsphereCommand
195
189
  task.wait_for_completion
196
190
  puts "Finished creating virtual machine #{vmname}"
197
191
 
198
- if config[:power] || config[:bootstrap]
192
+ if get_config(:power) || get_config(:bootstrap)
199
193
  vm = find_in_folder(dest_folder, RbVmomi::VIM::VirtualMachine, vmname) or
200
194
  fatal_exit("VM #{vmname} not found")
201
195
  vm.PowerOnVM_Task.wait_for_completion
202
196
  puts "Powered on virtual machine #{vmname}"
203
197
  end
204
198
 
205
- if config[:bootstrap]
199
+ if get_config(:bootstrap)
206
200
  print "Waiting for sshd..."
207
201
  print "." until tcp_test_ssh(config[:fqdn])
208
202
  puts "done"
@@ -215,18 +209,18 @@ class Chef::Knife::VsphereVmClone < Chef::Knife::BaseVsphereCommand
215
209
  def generate_clone_spec (src_config)
216
210
 
217
211
  rspec = nil
218
- if config[:resource_pool]
219
- rspec = RbVmomi::VIM.VirtualMachineRelocateSpec(:pool => find_pool(config[:resource_pool]))
212
+ if get_config(:resource_pool)
213
+ rspec = RbVmomi::VIM.VirtualMachineRelocateSpec(:pool => find_pool(get_config(:resource_pool)))
220
214
  else
221
- dcname = config[:vsphere_dc] || Chef::Config[:knife][:vsphere_dc]
215
+ dcname = get_config(:vsphere_dc)
222
216
  dc = config[:vim].serviceInstance.find_datacenter(dcname) or abort "datacenter not found"
223
217
  hosts = find_all_in_folder(dc.hostFolder, RbVmomi::VIM::ComputeResource)
224
218
  rp = hosts.first.resourcePool
225
219
  rspec = RbVmomi::VIM.VirtualMachineRelocateSpec(:pool => rp)
226
220
  end
227
221
 
228
- if config[:datastore]
229
- rspec.datastore = find_datastore(config[:datastore])
222
+ if get_config(:datastore)
223
+ rspec.datastore = find_datastore(get_config(:datastore))
230
224
  end
231
225
 
232
226
  clone_spec = RbVmomi::VIM.VirtualMachineCloneSpec(:location => rspec,
@@ -235,16 +229,16 @@ class Chef::Knife::VsphereVmClone < Chef::Knife::BaseVsphereCommand
235
229
 
236
230
  clone_spec.config = RbVmomi::VIM.VirtualMachineConfigSpec(:deviceChange => Array.new)
237
231
 
238
- if config[:customization_cpucount]
239
- clone_spec.config.numCPUs = config[:customization_cpucount]
232
+ if get_config(:customization_cpucount)
233
+ clone_spec.config.numCPUs = get_config(:customization_cpucount)
240
234
  end
241
235
 
242
- if config[:customization_memory]
243
- clone_spec.config.memoryMB = Integer(config[:customization_memory]) * 1024
236
+ if get_config(:customization_memory)
237
+ clone_spec.config.memoryMB = Integer(get_config(:customization_memory)) * 1024
244
238
  end
245
239
 
246
- if config[:customization_vlan]
247
- network = find_network(config[:customization_vlan])
240
+ if get_config(:customization_vlan)
241
+ network = find_network(get_config(:customization_vlan))
248
242
  switch_port = RbVmomi::VIM.DistributedVirtualSwitchPortConnection(:switchUuid => network.config.distributedVirtualSwitch.uuid ,:portgroupKey => network.key)
249
243
  card = src_config.hardware.device.find { |d| d.deviceInfo.label == "Network adapter 1" } or
250
244
  abort "Can't find source network card to customize"
@@ -253,9 +247,9 @@ class Chef::Knife::VsphereVmClone < Chef::Knife::BaseVsphereCommand
253
247
  clone_spec.config.deviceChange.push dev_spec
254
248
  end
255
249
 
256
- if config[:customization_spec]
257
- csi = find_customization(config[:customization_spec]) or
258
- fatal_exit("failed to find customization specification named #{config[:customization_spec]}")
250
+ if get_config(:customization_spec)
251
+ csi = find_customization(get_config(:customization_spec)) or
252
+ fatal_exit("failed to find customization specification named #{get_config(:customization_spec)}")
259
253
 
260
254
  if csi.info.type != "Linux"
261
255
  fatal_exit("Only Linux customization specifications are currently supported")
@@ -266,23 +260,23 @@ class Chef::Knife::VsphereVmClone < Chef::Knife::BaseVsphereCommand
266
260
  cust_spec = RbVmomi::VIM.CustomizationSpec(:globalIPSettings => global_ipset)
267
261
  end
268
262
 
269
- if config[:customization_dns_ips]
270
- cust_spec.globalIPSettings.dnsServerList = config[:customization_dns_ips].split(',')
263
+ if get_config(:customization_dns_ips)
264
+ cust_spec.globalIPSettings.dnsServerList = get_config(:customization_dns_ips).split(',')
271
265
  end
272
266
 
273
- if config[:customization_dns_suffixes]
274
- cust_spec.globalIPSettings.dnsSuffixList = config[:customization_dns_suffixes].split(',')
267
+ if get_config(:customization_dns_suffixes)
268
+ cust_spec.globalIPSettings.dnsSuffixList = get_config(:customization_dns_suffixes).split(',')
275
269
  end
276
270
 
277
271
  if config[:customization_ips]
278
- if config[:customization_gw]
279
- cust_spec.nicSettingMap = config[:customization_ips].split(',').map { |i| generate_adapter_map(i,config[:customization_gw]) }
272
+ if get_config(:customization_gw)
273
+ cust_spec.nicSettingMap = config[:customization_ips].split(',').map { |i| generate_adapter_map(i,get_config(:customization_gw)) }
280
274
  else
281
275
  cust_spec.nicSettingMap = config[:customization_ips].split(',').map { |i| generate_adapter_map(i) }
282
276
  end
283
277
  end
284
278
 
285
- use_ident = !config[:customization_hostname].nil? || !config[:customization_domain].nil? || cust_spec.identity.nil?
279
+ use_ident = !config[:customization_hostname].nil? || !get_config(:customization_domain).nil? || cust_spec.identity.nil?
286
280
 
287
281
  if use_ident
288
282
  # TODO - verify that we're deploying a linux spec, at least warn
@@ -291,14 +285,12 @@ class Chef::Knife::VsphereVmClone < Chef::Knife::BaseVsphereCommand
291
285
  ident.hostName = RbVmomi::VIM.CustomizationFixedName
292
286
  if config[:customization_hostname]
293
287
  ident.hostName.name = config[:customization_hostname]
294
- elsif config[:customization_domain]
295
- ident.hostName.name = config[:customization_domain]
296
288
  else
297
289
  ident.hostName.name = config[:vmname]
298
290
  end
299
291
 
300
- if config[:customization_domain]
301
- ident.domain = config[:customization_domain]
292
+ if get_config(:customization_domain)
293
+ ident.domain = get_config(:customization_domain)
302
294
  else
303
295
  ident.domain = ''
304
296
  end
@@ -355,25 +347,25 @@ class Chef::Knife::VsphereVmClone < Chef::Knife::BaseVsphereCommand
355
347
  Chef::Knife::Bootstrap.load_deps
356
348
  bootstrap = Chef::Knife::Bootstrap.new
357
349
  bootstrap.name_args = [config[:fqdn]]
358
- bootstrap.config[:run_list] = config[:run_list]
359
- bootstrap.config[:ssh_user] = config[:ssh_user]
360
- bootstrap.config[:ssh_password] = config[:ssh_password]
361
- bootstrap.config[:ssh_port] = config[:ssh_port]
362
- bootstrap.config[:identity_file] = config[:identity_file]
363
- bootstrap.config[:chef_node_name] = config[:chef_node_name]
364
- bootstrap.config[:prerelease] = config[:prerelease]
365
- bootstrap.config[:bootstrap_version] = locate_config_value(:bootstrap_version)
366
- bootstrap.config[:distro] = locate_config_value(:distro)
367
- bootstrap.config[:use_sudo] = true unless config[:ssh_user] == 'root'
368
- bootstrap.config[:template_file] = locate_config_value(:template_file)
369
- bootstrap.config[:environment] = config[:environment]
350
+ bootstrap.config[:run_list] = get_config(:run_list).split(/[\s,]+/)
351
+ bootstrap.config[:ssh_user] = get_config(:ssh_user)
352
+ bootstrap.config[:ssh_password] = get_config(:ssh_password)
353
+ bootstrap.config[:ssh_port] = get_config(:ssh_port)
354
+ bootstrap.config[:identity_file] = get_config(:identity_file)
355
+ bootstrap.config[:chef_node_name] = get_config(:chef_node_name)
356
+ bootstrap.config[:prerelease] = get_config(:prerelease)
357
+ bootstrap.config[:bootstrap_version] = get_config(:bootstrap_version)
358
+ bootstrap.config[:distro] = get_config(:distro)
359
+ bootstrap.config[:use_sudo] = true unless get_config(:ssh_user) == 'root'
360
+ bootstrap.config[:template_file] = get_config(:template_file)
361
+ bootstrap.config[:environment] = get_config(:environment)
370
362
  # may be needed for vpc_mode
371
- bootstrap.config[:no_host_key_verify] = config[:no_host_key_verify]
363
+ bootstrap.config[:no_host_key_verify] = get_config(:no_host_key_verify)
372
364
  bootstrap
373
365
  end
374
366
 
375
367
  def tcp_test_ssh(hostname)
376
- tcp_socket = TCPSocket.new(hostname, 22)
368
+ tcp_socket = TCPSocket.new(hostname, get_config(:ssh_port))
377
369
  readable = IO.select([tcp_socket], nil, nil, 5)
378
370
  if readable
379
371
  Chef::Log.debug("sshd accepting connections on #{hostname}, banner is #{tcp_socket.gets}")
@@ -7,33 +7,60 @@ require 'chef/knife'
7
7
  require 'chef/knife/BaseVsphereCommand'
8
8
  require 'rbvmomi'
9
9
 
10
+ # These two are needed for the '--purge' deletion case
11
+ require 'chef/node'
12
+ require 'chef/api_client'
13
+
10
14
  # Delete a virtual machine from vCenter
11
15
  class Chef::Knife::VsphereVmDelete < Chef::Knife::BaseVsphereCommand
12
16
 
13
- banner "knife vsphere vm delete VMNAME"
17
+ banner "knife vsphere vm delete VMNAME"
18
+
19
+ option :purge,
20
+ :short => "-P",
21
+ :long => "--purge",
22
+ :boolean => true,
23
+ :description => "Destroy corresponding node and client on the Chef Server, in addition to destroying the EC2 node itself."
24
+
25
+ get_common_options
26
+
27
+ # Extracted from Chef::Knife.delete_object, because it has a
28
+ # confirmation step built in... By specifying the '--purge'
29
+ # flag (and also explicitly confirming the server destruction!)
30
+ # the user is already making their intent known. It is not
31
+ # necessary to make them confirm two more times.
32
+ def destroy_item(itemClass, name, type_name)
33
+ object = itemClass.load(name)
34
+ object.destroy
35
+ puts "Deleted #{type_name} #{name}"
36
+ end
37
+
38
+ def run
39
+ $stdout.sync = true
14
40
 
15
- get_common_options
16
-
17
- def run
18
- $stdout.sync = true
41
+ vmname = @name_args[0]
19
42
 
20
- vmname = @name_args[0]
43
+ if vmname.nil?
44
+ show_usage
45
+ fatal_exit("You must specify a virtual machine name")
46
+ end
21
47
 
22
- if vmname.nil?
23
- show_usage
24
- fatal_exit("You must specify a virtual machine name")
25
- end
26
-
27
- vim = get_vim_connection
48
+ vim = get_vim_connection
28
49
 
29
- baseFolder = find_folder(config[:folder]);
50
+ baseFolder = find_folder(get_config(:folder));
30
51
 
31
- vm = find_in_folder(baseFolder, RbVmomi::VIM::VirtualMachine, vmname) or
32
- fatal_exit("VM #{vmname} not found")
52
+ vm = find_in_folder(baseFolder, RbVmomi::VIM::VirtualMachine, vmname) or
53
+ fatal_exit("VM #{vmname} not found")
33
54
 
34
- vm.PowerOffVM_Task.wait_for_completion unless vm.runtime.powerState == "poweredOff"
35
- vm.Destroy_Task
36
- puts "Deleted virtual machine #{vmname}"
55
+ vm.PowerOffVM_Task.wait_for_completion unless vm.runtime.powerState == "poweredOff"
56
+ vm.Destroy_Task
57
+ puts "Deleted virtual machine #{vmname}"
37
58
 
38
- end
59
+ if config[:purge]
60
+ destroy_item(Chef::Node, vmname, "node")
61
+ destroy_item(Chef::ApiClient, vmname, "client")
62
+ else
63
+ puts "Corresponding node and client for the #{vmname} server were not deleted and remain registered with the Chef Server"
64
+ end
65
+ end
39
66
  end
@@ -8,25 +8,51 @@ require 'chef/knife/BaseVsphereCommand'
8
8
  # Lists all known virtual machines in the configured datacenter
9
9
  class Chef::Knife::VsphereVmList < Chef::Knife::BaseVsphereCommand
10
10
 
11
- banner "knife vsphere vm list"
11
+ banner "knife vsphere vm list"
12
12
 
13
- get_common_options
14
-
15
- def run
13
+ get_common_options
16
14
 
17
- $stdout.sync = true
15
+ option :recursive,
16
+ :long => "--recursive",
17
+ :short => "-r",
18
+ :description => "Recurse down through sub-folders"
18
19
 
19
- vim = get_vim_connection
20
+ option :only_folders,
21
+ :long => "--only-folders",
22
+ :description => "Print only sub-folders"
20
23
 
21
- baseFolder = find_folder(config[:folder]);
24
+ def traverse_folders(folder)
25
+ puts "#{ui.color("Folder", :cyan)}: "+(folder.path[3..-1].map{|x| x[1]}.*'/')
26
+ print_vms_in_folder(folder) unless get_config(:only_folders)
27
+ folders = find_all_in_folder(folder, RbVmomi::VIM::Folder)
28
+ folders.each do |child|
29
+ traverse_folders(child)
30
+ end
31
+ end
22
32
 
23
- vms = find_all_in_folder(baseFolder, RbVmomi::VIM::VirtualMachine)
24
- vms.each do |vm|
25
- puts "#{ui.color("VM Name", :cyan)}: #{vm.name}"
26
- end
27
- folders = find_all_in_folder(baseFolder, RbVmomi::VIM::Folder)
28
- folders.each do |folder|
29
- puts "#{ui.color("Folder Name", :cyan)}: #{folder.name}"
33
+ def print_vms_in_folder(folder)
34
+ vms = find_all_in_folder(folder, RbVmomi::VIM::VirtualMachine)
35
+ vms.each do |vm|
36
+ puts "#{ui.color("VM Name", :cyan)}: #{vm.name}"
37
+ end
38
+ end
39
+
40
+ def print_subfolders(folder)
41
+ folders = find_all_in_folder(folder, RbVmomi::VIM::Folder)
42
+ folders.each do |subfolder|
43
+ puts "#{ui.color("Folder Name", :cyan)}: #{subfolder.name}"
30
44
  end
31
- end
45
+ end
46
+
47
+ def run
48
+ $stdout.sync = true
49
+ vim = get_vim_connection
50
+ baseFolder = find_folder(get_config(:folder));
51
+ if get_config(:recursive)
52
+ traverse_folders(baseFolder)
53
+ else
54
+ print_subfolders(baseFolder)
55
+ print_vms_in_folder(baseFolder)
56
+ end
57
+ end
32
58
  end
@@ -43,7 +43,7 @@ class Chef::Knife::VsphereVmState < Chef::Knife::BaseVsphereCommand
43
43
 
44
44
  vim = get_vim_connection
45
45
 
46
- baseFolder = find_folder(config[:folder]);
46
+ baseFolder = find_folder(get_config(:folder));
47
47
 
48
48
  vm = find_in_folder(baseFolder, RbVmomi::VIM::VirtualMachine, vmname) or
49
49
  abort "VM #{vmname} not found"
@@ -1,4 +1,4 @@
1
1
  module KnifeVsphere
2
- VERSION = "0.1.8"
2
+ VERSION = "0.1.9"
3
3
  end
4
4
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: knife-vsphere
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.8
4
+ version: 0.1.9
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,12 +9,12 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-03-06 00:00:00.000000000 +01:00
12
+ date: 2012-04-16 00:00:00.000000000 -05:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: netaddr
17
- requirement: &70237366117520 !ruby/object:Gem::Requirement
17
+ requirement: &70231050321420 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ~>
@@ -22,10 +22,10 @@ dependencies:
22
22
  version: 1.5.0
23
23
  type: :runtime
24
24
  prerelease: false
25
- version_requirements: *70237366117520
25
+ version_requirements: *70231050321420
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: chef
28
- requirement: &70237366113920 !ruby/object:Gem::Requirement
28
+ requirement: &70231050320800 !ruby/object:Gem::Requirement
29
29
  none: false
30
30
  requirements:
31
31
  - - ~>
@@ -33,10 +33,10 @@ dependencies:
33
33
  version: 0.10.0
34
34
  type: :runtime
35
35
  prerelease: false
36
- version_requirements: *70237366113920
36
+ version_requirements: *70231050320800
37
37
  - !ruby/object:Gem::Dependency
38
38
  name: rbvmomi
39
- requirement: &70237366111900 !ruby/object:Gem::Requirement
39
+ requirement: &70231050320140 !ruby/object:Gem::Requirement
40
40
  none: false
41
41
  requirements:
42
42
  - - ~>
@@ -44,7 +44,7 @@ dependencies:
44
44
  version: 1.2.3
45
45
  type: :runtime
46
46
  prerelease: false
47
- version_requirements: *70237366111900
47
+ version_requirements: *70231050320140
48
48
  description: VMware vSphere Support for Chef's Knife Command
49
49
  email: ezra@cpan.org
50
50
  executables: []
@@ -55,6 +55,7 @@ files:
55
55
  - lib/chef/knife/vsphere_customization_list.rb
56
56
  - lib/chef/knife/vsphere_datastore_list.rb
57
57
  - lib/chef/knife/vsphere_template_list.rb
58
+ - lib/chef/knife/vsphere_vlan_list.rb
58
59
  - lib/chef/knife/vsphere_vm_clone.rb
59
60
  - lib/chef/knife/vsphere_vm_delete.rb
60
61
  - lib/chef/knife/vsphere_vm_list.rb