knife-xapi 0.5.4 → 0.6.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.
- checksums.yaml +7 -0
- data/lib/chef/knife/xapi_base.rb +168 -152
- data/lib/chef/knife/xapi_guest_create.rb +186 -167
- data/lib/chef/knife/xapi_guest_delete.rb +28 -30
- data/lib/chef/knife/xapi_guest_list.rb +13 -15
- data/lib/chef/knife/xapi_guest_start.rb +5 -6
- data/lib/chef/knife/xapi_guest_stop.rb +4 -7
- data/lib/chef/knife/xapi_network_list.rb +10 -13
- data/lib/chef/knife/xapi_vdi_attach.rb +33 -40
- data/lib/chef/knife/xapi_vdi_create.rb +24 -26
- data/lib/chef/knife/xapi_vdi_delete.rb +30 -33
- data/lib/chef/knife/xapi_vdi_detach.rb +36 -43
- data/lib/chef/knife/xapi_vdi_list.rb +17 -21
- data/lib/chef/knife/xapi_vlan_list.rb +6 -9
- data/lib/chef/knife/xapi_vmselect.rb +7 -9
- data/lib/knife-xapi/version.rb +1 -1
- data/lib/xenapi/xenapi.rb +2 -3
- data/lib/xenapi/xenapi/async_dispatcher.rb +2 -2
- data/lib/xenapi/xenapi/client.rb +53 -55
- data/lib/xenapi/xenapi/errors.rb +3 -3
- data/lib/xenapi/xenapi/xmlrpc_client.rb +3 -3
- metadata +19 -33
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 3a42422d7442a441d55873e861341983b697377f
|
4
|
+
data.tar.gz: 492d3348d76186aca651c58a0908f1230f555cee
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: fa650d0b5f80f0ecb0f21906c805b1c403f3cc8d7477c9ca6cf54afeb44cf35ae355ffb00fb4d6b6c1de27888ebeb87e22755f48a5de69a1167d86f9bd370f7c
|
7
|
+
data.tar.gz: d3d60baf33159d7a5319a782e82dee3c32b1da5aa3903ee14b63d26cec7bd1ab525deb967a12e95e317f7981887ce948fad46572f67d37990a7b3f2b5ccb69d6
|
data/lib/chef/knife/xapi_base.rb
CHANGED
@@ -29,15 +29,13 @@ unless Kernel.respond_to?(:require_relative)
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
-
|
33
32
|
require 'chef/knife'
|
34
33
|
|
35
34
|
require_relative '../../xenapi/xenapi.rb'
|
36
35
|
|
37
36
|
class Chef::Knife
|
38
|
-
|
39
|
-
|
40
|
-
attr :defaults
|
37
|
+
module XapiBase
|
38
|
+
attr_reader :defaults
|
41
39
|
|
42
40
|
def self.included(includer)
|
43
41
|
includer.class_eval do
|
@@ -50,54 +48,52 @@ class Chef::Knife
|
|
50
48
|
end
|
51
49
|
|
52
50
|
option :xapi_host,
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
51
|
+
short: '-h SERVER_URL',
|
52
|
+
long: '--host SERVER_URL',
|
53
|
+
proc: proc { |key| Chef::Config[:knife][:xapi_host] = key },
|
54
|
+
description: 'The url to the xenserver, http://somehost.local.lan/'
|
57
55
|
|
58
56
|
option :xapi_password,
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
57
|
+
short: '-K PASSWORD',
|
58
|
+
long: '--xapi-password PASSWORD',
|
59
|
+
proc: proc { |key| Chef::Config[:knife][:xapi_password] = key },
|
60
|
+
description: 'Your xenserver password'
|
63
61
|
|
64
62
|
option :xapi_username,
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
63
|
+
short: '-A USERNAME',
|
64
|
+
long: '--xapi-username USERNAME',
|
65
|
+
proc: proc { |key| Chef::Config[:knife][:xapi_username] = key },
|
66
|
+
description: 'Your xenserver username'
|
69
67
|
|
70
68
|
option :domain,
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
69
|
+
short: '-f Name',
|
70
|
+
long: '--domain Name',
|
71
|
+
description: 'the domain name for the guest',
|
72
|
+
proc: proc { |key| Chef::Config[:knife][:domain] = key }
|
75
73
|
|
76
74
|
option :no_color,
|
77
|
-
|
78
|
-
|
79
|
-
|
75
|
+
long: '--no-color',
|
76
|
+
default: false,
|
77
|
+
description: "Don't colorize the output"
|
80
78
|
|
81
79
|
option :xapi_ssl_verify,
|
82
|
-
|
83
|
-
|
84
|
-
|
80
|
+
long: '--xapi-ssl-verify',
|
81
|
+
default: false,
|
82
|
+
description: "Enable SSL cert verification, Disabled by defaul because xenservers don't ship with proper certs"
|
85
83
|
|
86
84
|
end
|
87
85
|
end
|
88
86
|
|
89
|
-
|
90
|
-
|
91
87
|
def self.set_defaults(config)
|
92
|
-
@defaults ||=
|
88
|
+
@defaults ||= {}
|
93
89
|
@defaults.merge!(config)
|
94
90
|
end
|
95
91
|
|
96
92
|
# set the default template
|
97
|
-
|
93
|
+
set_defaults(template_regex: /^CentOS 5.*\(64-bit\)/)
|
98
94
|
|
99
95
|
def self.defaults
|
100
|
-
@defaults ||=
|
96
|
+
@defaults ||= {}
|
101
97
|
end
|
102
98
|
|
103
99
|
def self.get_default(key)
|
@@ -112,16 +108,16 @@ class Chef::Knife
|
|
112
108
|
def xapi
|
113
109
|
@xapi ||= begin
|
114
110
|
|
115
|
-
ui.fatal
|
111
|
+
ui.fatal 'Must provide a xapi host with --host ' unless locate_config_value(:xapi_host)
|
116
112
|
verify = :verify_none
|
117
113
|
verify = :verify_peer if locate_config_value(:xapi_ssl_verify) == true
|
118
|
-
session = XenApi::Client.new(
|
114
|
+
session = XenApi::Client.new(locate_config_value(:xapi_host), 10, verify)
|
119
115
|
|
120
116
|
# get the password from the user
|
121
117
|
password = locate_config_value(:xapi_password) || nil
|
122
|
-
username = locate_config_value(:xapi_username) ||
|
123
|
-
if password.nil?
|
124
|
-
password = h.ask("Enter password for user #{username}: "
|
118
|
+
username = locate_config_value(:xapi_username) || 'root'
|
119
|
+
if password.nil? || password.empty?
|
120
|
+
password = h.ask("Enter password for user #{username}: ") { |input| input.echo = '*' }
|
125
121
|
end
|
126
122
|
session.login_with_password(username, password)
|
127
123
|
|
@@ -168,19 +164,19 @@ class Chef::Knife
|
|
168
164
|
# Wish there was a better API method for this, and there might be
|
169
165
|
# but i couldn't find it
|
170
166
|
Chef::Log.debug "Using regex: #{template}"
|
171
|
-
xapi.VM.get_all_records
|
172
|
-
if vm[
|
173
|
-
Chef::Log.debug "Matched: #{h.color(vm[
|
167
|
+
xapi.VM.get_all_records.each_value do |vm|
|
168
|
+
if vm['is_a_template'] && vm['name_label'] =~ template
|
169
|
+
Chef::Log.debug "Matched: #{h.color(vm['name_label'], :yellow)}"
|
174
170
|
found = vm # we're gonna go with the last found
|
175
171
|
end
|
176
172
|
end
|
177
173
|
|
178
174
|
# ensure return values
|
179
175
|
if found
|
180
|
-
ui.msg "Using Template: #{h.color(found[
|
181
|
-
return get_template(found[
|
176
|
+
ui.msg "Using Template: #{h.color(found['name_label'], :cyan)}"
|
177
|
+
return get_template(found['name_label']) # get the ref to this one
|
182
178
|
end
|
183
|
-
|
179
|
+
nil
|
184
180
|
end
|
185
181
|
|
186
182
|
# present a list of options for a user to select
|
@@ -188,7 +184,7 @@ class Chef::Knife
|
|
188
184
|
def user_select(items)
|
189
185
|
h.choose do |menu|
|
190
186
|
menu.index = :number
|
191
|
-
menu.prompt =
|
187
|
+
menu.prompt = 'Please Choose One:'
|
192
188
|
menu.select_by = :index_or_name
|
193
189
|
items.each do |item|
|
194
190
|
menu.choice item.to_sym do |command|
|
@@ -204,46 +200,50 @@ class Chef::Knife
|
|
204
200
|
# destroy/remove VM refs and exit
|
205
201
|
def cleanup(vm_ref)
|
206
202
|
# shutdown and dest
|
207
|
-
unless xapi.VM.get_power_state(vm_ref) ==
|
208
|
-
ui.msg
|
203
|
+
unless xapi.VM.get_power_state(vm_ref) == 'Halted'
|
204
|
+
ui.msg 'Shutting down Guest'
|
209
205
|
task = xapi.Async.VM.hard_shutdown(vm_ref)
|
210
|
-
get_task_ref(task) unless task ==
|
206
|
+
get_task_ref(task) unless task == 'Halted'
|
211
207
|
end
|
212
208
|
|
213
|
-
ui.msg
|
209
|
+
ui.msg 'Removing disks attached to Guest'
|
214
210
|
Chef::Log.debug "getting vbds attached to #{vm_ref}"
|
215
211
|
wait_tasks = []
|
216
212
|
xapi.VM.get_VBDs(vm_ref).to_a.each do |vbd|
|
217
213
|
next unless vbd
|
218
214
|
|
219
215
|
Chef::Log.debug "removing vbd: #{vbd}"
|
220
|
-
wait_tasks << xapi.Async.VDI.destroy(
|
216
|
+
wait_tasks << xapi.Async.VDI.destroy(xapi.VBD.get_record(vbd)['VDI'])
|
221
217
|
wait_tasks << xapi.Async.VBD.destroy(vbd)
|
222
218
|
end
|
223
219
|
|
224
220
|
# wait for disk cleanup to finish up
|
225
221
|
unless wait_tasks.empty?
|
226
|
-
ui.msg
|
222
|
+
ui.msg 'waiting for disks to cleanup'
|
227
223
|
wait_tasks.each do |task|
|
228
224
|
wait_on_task(task)
|
229
225
|
end
|
230
226
|
end
|
231
227
|
|
232
|
-
ui.msg
|
228
|
+
ui.msg 'Destroying Guest'
|
233
229
|
task = xapi.Async.VM.destroy(vm_ref)
|
234
230
|
wait_on_task(task)
|
235
231
|
end
|
236
232
|
|
237
233
|
# cleanup a vm and exit (fail)
|
238
|
-
def fail(ref=nil)
|
239
|
-
ui.warn
|
234
|
+
def fail(ref = nil)
|
235
|
+
ui.warn 'Error encountered clenaing up and exiting'
|
240
236
|
cleanup ref if ref
|
241
237
|
exit 1
|
242
238
|
end
|
243
239
|
|
244
240
|
# generate a random mac address
|
245
241
|
def generate_mac
|
246
|
-
(
|
242
|
+
if locate_config_value(:macaddress).nil?
|
243
|
+
('%02x' % (rand(64) * 4 | 2)) + (0..4).reduce('') { |s, _x|s + ':%02x' % rand(256) }
|
244
|
+
else
|
245
|
+
locate_config_value(:macaddress)
|
246
|
+
end
|
247
247
|
end
|
248
248
|
|
249
249
|
# add a new vif
|
@@ -252,25 +252,25 @@ class Chef::Knife
|
|
252
252
|
network_ref = xapi.network.get_by_name_label(net_name).first
|
253
253
|
if network_ref.nil?
|
254
254
|
if net_name =~ /Network (\d)+$/ # special handing for 'Network X' As displayed by XenCenter
|
255
|
-
add_vif_by_name(vm_ref, dev_num, "Pool-wide network associated with eth#{
|
255
|
+
add_vif_by_name(vm_ref, dev_num, "Pool-wide network associated with eth#{Regexp.last_match[1]}")
|
256
256
|
else
|
257
|
-
ui.warn "#{h.color(net_name
|
257
|
+
ui.warn "#{h.color(net_name, :red)} not found, moving on"
|
258
258
|
end
|
259
259
|
return
|
260
260
|
end
|
261
261
|
|
262
262
|
mac = generate_mac
|
263
|
-
Chef::Log.debug "Provisioning: #{h.color(net_name, :cyan)}, #{h.color(mac
|
263
|
+
Chef::Log.debug "Provisioning: #{h.color(net_name, :cyan)}, #{h.color(mac, :green)}, #{h.color(network_ref, :yellow)}"
|
264
264
|
|
265
265
|
vif = {
|
266
266
|
'device' => dev_num.to_s,
|
267
267
|
'network' => network_ref,
|
268
268
|
'VM' => vm_ref,
|
269
269
|
'MAC' => generate_mac,
|
270
|
-
'MTU' =>
|
271
|
-
|
272
|
-
|
273
|
-
|
270
|
+
'MTU' => '1500',
|
271
|
+
'other_config' => {},
|
272
|
+
'qos_algorithm_type' => '',
|
273
|
+
'qos_algorithm_params' => {}
|
274
274
|
}
|
275
275
|
vif_ref = xapi.VIF.create(vif)
|
276
276
|
vif_ref
|
@@ -278,25 +278,40 @@ class Chef::Knife
|
|
278
278
|
|
279
279
|
# remove all vifs on a record
|
280
280
|
def clear_vm_vifs(record)
|
281
|
-
record[
|
281
|
+
record['VIFs'].each do |vif|
|
282
282
|
Chef::Log.debug "Removing vif: #{h.color(vif, :red, :bold)}"
|
283
283
|
xapi.VIF.destroy(vif)
|
284
284
|
end
|
285
285
|
end
|
286
286
|
|
287
|
+
# returns true if uuid is a uuid
|
288
|
+
def is_uuid?(uuid)
|
289
|
+
uuid =~ /[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}/i
|
290
|
+
end
|
291
|
+
|
287
292
|
# returns sr_ref to the default sr on pool
|
288
|
-
def find_default_sr
|
289
|
-
xapi.pool.get_default_SR(
|
293
|
+
def find_default_sr
|
294
|
+
xapi.pool.get_default_SR(xapi.pool.get_all[0])
|
290
295
|
end
|
291
296
|
|
292
297
|
# return an SR record from the name_label
|
293
298
|
def get_sr_by_name(name)
|
294
|
-
sr_ref = xapi.SR.get_by_name_label(name)
|
295
|
-
if sr_ref.empty?
|
296
|
-
ui.error "SR name #{h.color(
|
299
|
+
sr_ref = xapi.SR.get_by_name_label(name)[0]
|
300
|
+
if sr_ref.empty? || sr_ref.nil?
|
301
|
+
ui.error "SR name #{h.color(name) } not found"
|
297
302
|
return nil
|
298
303
|
end
|
299
|
-
|
304
|
+
sr_ref
|
305
|
+
end
|
306
|
+
|
307
|
+
# return SR record from uuid
|
308
|
+
def get_sr_by_uuid(uuid)
|
309
|
+
sr_ref = xapi.SR.get_by_uuid(uuid)
|
310
|
+
if sr_ref.empty? || sr_ref.nil?
|
311
|
+
ui.error "SR not found #{h.color(uuid)} "
|
312
|
+
return nil
|
313
|
+
end
|
314
|
+
sr_ref
|
300
315
|
end
|
301
316
|
|
302
317
|
# convert 1g/1m/1t to bytes
|
@@ -304,39 +319,39 @@ class Chef::Knife
|
|
304
319
|
def input_to_bytes(size)
|
305
320
|
case size
|
306
321
|
when /m|mb/i
|
307
|
-
size.to_i * (1024
|
322
|
+
size.to_i * (1024**2)
|
308
323
|
when /t|tb/i
|
309
|
-
size.to_i * (1024
|
324
|
+
size.to_i * (1024**4)
|
310
325
|
else
|
311
326
|
# default is gigabytes
|
312
|
-
size.to_i * (1024
|
327
|
+
size.to_i * (1024**3)
|
313
328
|
end
|
314
329
|
end
|
315
330
|
|
316
331
|
# create a vdi return ref
|
317
332
|
def create_vdi(name, sr_ref, size)
|
318
333
|
vdi_record = {
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
334
|
+
'name_label' => "#{name}",
|
335
|
+
'name_description' => "Root disk for #{name} created by #{ENV['USER']} with knfie xapi",
|
336
|
+
'SR' => sr_ref,
|
337
|
+
'virtual_size' => input_to_bytes(size).to_s,
|
338
|
+
'type' => 'system',
|
339
|
+
'sharable' => false,
|
340
|
+
'read_only' => false,
|
341
|
+
'other_config' => {}
|
327
342
|
}
|
328
343
|
|
329
344
|
# Async create the VDI
|
330
345
|
task = xapi.Async.VDI.create(vdi_record)
|
331
|
-
ui.msg
|
346
|
+
ui.msg 'waiting for VDI Create'
|
332
347
|
vdi_ref = get_task_ref(task)
|
348
|
+
vdi_ref
|
333
349
|
end
|
334
350
|
|
335
|
-
|
336
351
|
# sit and wait for taks to exit pending state
|
337
352
|
def wait_on_task(task)
|
338
|
-
while xapi.task.get_status(task) ==
|
339
|
-
|
353
|
+
while xapi.task.get_status(task) == 'pending'
|
354
|
+
xapi.task.get_progress(task)
|
340
355
|
sleep 1
|
341
356
|
end
|
342
357
|
end
|
@@ -349,46 +364,47 @@ class Chef::Knife
|
|
349
364
|
status_ = xapi.task.get_status(task)
|
350
365
|
|
351
366
|
case status_
|
352
|
-
when
|
367
|
+
when 'success'
|
353
368
|
puts "#{h.color "#{status_}", :green }"
|
354
369
|
# xapi task record returns result as <value>OpaqueRef:....</value>
|
355
370
|
# we want the ref. this way it will work if they fix it to return jsut the ref
|
356
371
|
ref = xapi.task.get_result(task).match(/OpaqueRef:[^<]+/).to_s
|
357
372
|
|
358
|
-
#cleanup our task
|
373
|
+
# cleanup our task
|
359
374
|
xapi.task.destroy(task)
|
360
375
|
return ref
|
361
376
|
else
|
362
|
-
ui.msg(
|
363
|
-
ui.msg(
|
377
|
+
ui.msg("#{h.color "#{status_}", :red } ")
|
378
|
+
ui.msg("#{h.color 'ERROR:', :red } #{xapi.task.get_error_info(task)}")
|
364
379
|
end
|
365
380
|
end
|
366
381
|
|
367
382
|
# create vbd and return a ref
|
368
383
|
# defaults to bootable
|
369
|
-
def create_vbd(vm_ref, vdi_ref, position, boot=true)
|
384
|
+
def create_vbd(vm_ref, vdi_ref, position, boot = true)
|
370
385
|
vbd_record = {
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
386
|
+
'VM' => vm_ref,
|
387
|
+
'VDI' => vdi_ref,
|
388
|
+
'empty' => false,
|
389
|
+
'other_config' => { 'owner' => '' },
|
390
|
+
'userdevice' => position.to_s,
|
391
|
+
'bootable' => boot,
|
392
|
+
'mode' => 'RW',
|
393
|
+
'qos_algorithm_type' => '',
|
394
|
+
'qos_algorithm_params' => {},
|
395
|
+
'qos_supported_algorithms' => [],
|
396
|
+
'type' => 'Disk'
|
382
397
|
}
|
383
398
|
|
384
399
|
task = xapi.Async.VBD.create(vbd_record)
|
385
|
-
ui.msg
|
400
|
+
ui.msg 'Waiting for VBD create'
|
386
401
|
vbd_ref = get_task_ref(task)
|
387
|
-
|
402
|
+
vbd_ref
|
403
|
+
end
|
388
404
|
|
389
|
-
|
390
|
-
|
391
|
-
|
405
|
+
# detach_vdi
|
406
|
+
def detach_vdi(vdi_ref)
|
407
|
+
vbd_refs = xapi.VDI.get_VBDs(vdi_ref)
|
392
408
|
|
393
409
|
# more than one VBD, so we ned to find the vbd with the vdi
|
394
410
|
ref = nil
|
@@ -396,8 +412,8 @@ class Chef::Knife
|
|
396
412
|
if vbd_refs.length > 1
|
397
413
|
vbd_refs.each do |vbd|
|
398
414
|
record = xapi.VBD.get_record vbd
|
399
|
-
Chef::Log.debug "Checking VBD: #{vbd}, #{record[
|
400
|
-
if record[
|
415
|
+
Chef::Log.debug "Checking VBD: #{vbd}, #{record['device']}, #{record['VDI']}==#{vdi_ref}"
|
416
|
+
if record['VDI'] == vdi_ref
|
401
417
|
ref = vbd
|
402
418
|
break
|
403
419
|
end
|
@@ -408,94 +424,95 @@ class Chef::Knife
|
|
408
424
|
end
|
409
425
|
|
410
426
|
unless ref
|
411
|
-
|
427
|
+
fail ArgumentError, "We weren't able to find a VBD for that VDI: #{vdi_ref}"
|
412
428
|
end
|
413
429
|
|
414
430
|
task = xapi.Async.VBD.destroy(ref)
|
415
|
-
ui.msg
|
431
|
+
ui.msg 'Waiting for VDI detach'
|
416
432
|
task_ref = get_task_ref(task)
|
417
|
-
|
433
|
+
task_ref
|
434
|
+
end
|
418
435
|
|
419
|
-
|
420
|
-
|
421
|
-
|
436
|
+
def get_vbd_by_uuid(id)
|
437
|
+
xapi.VBD.get_by_uuid(id)
|
438
|
+
end
|
422
439
|
|
423
440
|
# try to get a guest ip and return it
|
424
441
|
def get_guest_ip(vm_ref)
|
425
|
-
guest_ip =
|
442
|
+
guest_ip = 'unknown'
|
426
443
|
vgm = xapi.VM.get_guest_metrics(vm_ref)
|
427
|
-
unless
|
444
|
+
unless 'OpaqueRef:NULL' == vgm
|
428
445
|
networks = xapi.VM_guest_metrics.get_networks(vgm)
|
429
|
-
if networks.
|
430
|
-
guest_ip = networks[
|
446
|
+
if networks.key?('0/ip')
|
447
|
+
guest_ip = networks['0/ip']
|
431
448
|
end
|
432
449
|
end
|
433
|
-
|
450
|
+
guest_ip
|
434
451
|
end
|
435
452
|
|
436
453
|
def get_vbds_from_vdi(vdi_ref)
|
437
|
-
|
454
|
+
xapi.VDI.get_VBDs(vdi_ref)
|
438
455
|
end
|
439
456
|
|
440
|
-
def get_all_vdis
|
441
|
-
|
457
|
+
def get_all_vdis
|
458
|
+
xapi.VDI.get_all
|
442
459
|
end
|
443
460
|
|
444
461
|
def get_vdi_by_uuid(id)
|
445
|
-
|
462
|
+
xapi.VDI.get_by_uuid(id)
|
446
463
|
end
|
447
464
|
|
448
465
|
def get_vdi_by_name_label(name)
|
449
|
-
|
466
|
+
xapi.VDI.get_by_name_label(name)
|
450
467
|
end
|
451
468
|
|
452
|
-
def color_kv(key, value, color=[:green, :cyan])
|
469
|
+
def color_kv(key, value, color = [:green, :cyan])
|
453
470
|
if config[:no_color]
|
454
|
-
color = [
|
471
|
+
color = [:clear, :clear]
|
455
472
|
end
|
456
|
-
ui.msg "#{h.color(
|
473
|
+
ui.msg "#{h.color(key, color[0])} #{ h.color(value, color[1])}"
|
457
474
|
end
|
458
475
|
|
459
476
|
def print_vdi_info(vdi)
|
460
477
|
record = xapi.VDI.get_record vdi
|
461
|
-
color_kv
|
462
|
-
color_kv
|
463
|
-
color_kv
|
464
|
-
color_kv
|
465
|
-
color_kv
|
466
|
-
color_kv
|
467
|
-
record[
|
478
|
+
color_kv 'VDI Name: ', record['name_label']
|
479
|
+
color_kv ' UUID: ', record['uuid'], [:magenta, :cyan]
|
480
|
+
color_kv ' Description: ', record['name_description'], [:magenta, :cyan]
|
481
|
+
color_kv ' Type: ', record['type'], [:magenta, :cyan]
|
482
|
+
color_kv ' Size (gb): ', (record['virtual_size'].to_i / (1024**3)).to_s, [:magenta, :cyan]
|
483
|
+
color_kv ' Utilized (gb): ', (record['physical_utilisation'].to_i / (1024**3)).to_s, [:magenta, :cyan]
|
484
|
+
record['VBDs'].each do |vbd|
|
468
485
|
vm = xapi.VBD.get_VM(vbd)
|
469
|
-
color_kv
|
470
|
-
color_kv
|
486
|
+
color_kv ' VM name: ', xapi.VM.get_name_label(vm)
|
487
|
+
color_kv ' VM state: ', "#{xapi.VM.get_power_state(vm) } \n"
|
471
488
|
end
|
472
489
|
|
473
|
-
if record[
|
474
|
-
ui.msg h.color
|
490
|
+
if record['VBDs'].length == 0
|
491
|
+
ui.msg h.color ' No VM Attached', :red
|
475
492
|
end
|
476
493
|
|
477
|
-
ui.msg
|
494
|
+
ui.msg ''
|
478
495
|
end
|
479
496
|
|
480
497
|
def print_record(record)
|
481
|
-
puts
|
498
|
+
puts ''
|
482
499
|
PP.pp record
|
483
500
|
end
|
484
501
|
|
485
502
|
# return true (yes) false (no)
|
486
503
|
# to the asked question
|
487
504
|
def yes_no?(msg)
|
488
|
-
answer = ui.ask(
|
505
|
+
answer = ui.ask("#{msg} yes/no ? ") do |res|
|
489
506
|
res.case = :down
|
490
507
|
res.validate = /y|n|yes|no/
|
491
508
|
res.responses[:not_valid] = "Use 'yes', 'no', 'y', 'n':"
|
492
509
|
end
|
493
510
|
|
494
511
|
case answer
|
495
|
-
when
|
496
|
-
|
497
|
-
when
|
498
|
-
|
512
|
+
when 'y', 'yes'
|
513
|
+
true
|
514
|
+
when 'n', 'no'
|
515
|
+
false
|
499
516
|
end
|
500
517
|
end
|
501
518
|
|
@@ -505,12 +522,12 @@ class Chef::Knife
|
|
505
522
|
detach_vdi(vdi_ref)
|
506
523
|
end
|
507
524
|
task = xapi.Async.VDI.destroy(vdi_ref)
|
508
|
-
print
|
525
|
+
print 'Destroying volume '
|
509
526
|
puts "#{h.color xapi.VDI.get_name_label(vdi_ref), :cyan}"
|
510
527
|
task_ref = get_task_ref(task)
|
528
|
+
task_ref
|
511
529
|
end
|
512
530
|
|
513
|
-
|
514
531
|
def get_host_ref(hostname)
|
515
532
|
xapi.host.get_all.each do |ref|
|
516
533
|
name = xapi.host.get_name_label ref
|
@@ -519,29 +536,28 @@ class Chef::Knife
|
|
519
536
|
nil
|
520
537
|
end
|
521
538
|
|
522
|
-
def start(vm_ref, host=nil)
|
539
|
+
def start(vm_ref, host = nil)
|
523
540
|
if host
|
524
541
|
host_ref = get_host_ref(host)
|
525
542
|
unless host_ref
|
526
543
|
ui.msg "Host not found #{host}"
|
527
544
|
exit 1
|
528
545
|
end
|
529
|
-
ui.msg(
|
546
|
+
ui.msg("Starting #{vm_ref} on #{host}")
|
530
547
|
task = xapi.Async.VM.start_on(vm_ref, host_ref, false, true)
|
531
548
|
else
|
532
|
-
ui.msg(
|
549
|
+
ui.msg("Starting #{vm_ref} ")
|
533
550
|
task = xapi.Async.VM.start(vm_ref, false, true)
|
534
551
|
end
|
535
552
|
wait_on_task(task)
|
536
|
-
ui.msg(
|
553
|
+
ui.msg("#{ h.color 'OK!', :green}")
|
537
554
|
end
|
538
555
|
|
539
556
|
def stop(vm_ref)
|
540
|
-
ui.msg(
|
557
|
+
ui.msg("Stopping #{vm_ref}")
|
541
558
|
task = xapi.Async.VM.clean_shutdown(vm_ref)
|
542
559
|
wait_on_task(task)
|
543
|
-
ui.msg(
|
560
|
+
ui.msg("#{ h.color 'OK!', :green}")
|
544
561
|
end
|
545
|
-
|
546
|
-
end
|
562
|
+
end
|
547
563
|
end
|