knife-xapi 0.5.4 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|