knife-xapi 0.4.1 → 0.4.2

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.
@@ -64,6 +64,12 @@ class Chef::Knife
64
64
  :long => "--domain Name",
65
65
  :description => "the domain name for the guest",
66
66
  :proc => Proc.new { |key| Chef::Config[:knife][:domain] = key }
67
+
68
+ option :no_color,
69
+ :long => "--no-color",
70
+ :default => false,
71
+ :description => "Don't colorize the output"
72
+
67
73
  end
68
74
  end
69
75
 
@@ -344,7 +350,6 @@ class Chef::Knife
344
350
  end
345
351
  end
346
352
 
347
-
348
353
  # create vbd and return a ref
349
354
  # defaults to bootable
350
355
  def create_vbd(vm_ref, vdi_ref, position, boot=true)
@@ -365,8 +370,42 @@ class Chef::Knife
365
370
  task = xapi.Async.VBD.create(vbd_record)
366
371
  ui.msg "Waiting for VBD create"
367
372
  vbd_ref = get_task_ref(task)
368
- end
373
+ end
374
+
375
+ #detach_vdi
376
+ def detach_vdi(vdi_ref)
377
+ vbd_refs = xapi.VDI.get_VBDs(vdi_ref)
378
+
379
+ # more than one VBD, so we ned to find the vbd with the vdi
380
+ ref = nil
381
+ Chef::Log.debug "VBD Refs: #{vbd_refs.inspect}"
382
+ if vbd_refs.length > 1
383
+ vbd_refs.each do |vbd|
384
+ record = xapi.VBD.get_record vbd
385
+ Chef::Log.debug "Checking VBD: #{vbd}, #{record["device"]}, #{record["VDI"]}==#{vdi_ref}"
386
+ if record["VDI"] == vdi_ref
387
+ ref = vbd
388
+ break
389
+ end
390
+ end
391
+ else
392
+ # if only vbd use it
393
+ ref = vbd_refs.first
394
+ end
395
+
396
+ unless ref
397
+ raise ArgumentError, "We weren't able to find a VBD for that VDI: #{vdi_ref}"
398
+ end
399
+
400
+ task = xapi.Async.VBD.destroy(ref)
401
+ ui.msg "Waiting for VDI detach"
402
+ task_ref = get_task_ref(task)
403
+ end
369
404
 
405
+ def get_vbd_by_uuid(id)
406
+ xapi.VBD.get_by_uuid(id)
407
+ end
408
+
370
409
  # try to get a guest ip and return it
371
410
  def get_guest_ip(vm_ref)
372
411
  guest_ip = "unknown"
@@ -396,33 +435,62 @@ class Chef::Knife
396
435
  return xapi.VDI.get_by_name_label(name)
397
436
  end
398
437
 
399
- def print_vdi_info(vdi_ref)
400
- puts "#{h.color "VDI name: " + xapi.VDI.get_name_label(vdi_ref), :green}"
401
- puts " -Description: " + xapi.VDI.get_name_description(vdi_ref)
402
- puts " -Type: " + xapi.VDI.get_type(vdi_ref)
403
- end
438
+ def color_kv(key, value, color=[:green, :cyan])
439
+ if config[:no_color]
440
+ color = [ :clear, :clear ]
441
+ end
442
+ ui.msg "#{h.color( key, color[0])} #{ h.color( value, color[1])}"
443
+ end
444
+
445
+ def print_vdi_info(vdi)
446
+ record = xapi.VDI.get_record vdi
447
+ color_kv "VDI Name: ", record['name_label']
448
+ color_kv " UUID: ", record['uuid'], [:magenta, :cyan]
449
+ color_kv " Description: ", record['name_description'], [:magenta, :cyan]
450
+ color_kv " Type: ", record['type'], [:magenta, :cyan]
451
+ color_kv " Size (gb): ", record['virtual_size'].to_i.bytes.to_gb.to_s, [:magenta, :cyan]
452
+ color_kv " Utilized (gb): ", record['physical_utilisation'].to_i.bytes.to_gb.to_s, [:magenta, :cyan]
453
+ record["VBDs"].each do |vbd|
454
+ vm = xapi.VBD.get_VM(vbd)
455
+ color_kv " VM name: ", xapi.VM.get_name_label(vm)
456
+ color_kv " VM state: ", "#{xapi.VM.get_power_state(vm) } \n"
457
+ end
404
458
 
405
- def yes_no_prompt(str)
406
- print str
407
- choice = STDIN.gets
459
+ if record["VBDs"].length == 0
460
+ ui.msg h.color " No VM Attached", :red
461
+ end
462
+
463
+ ui.msg ""
464
+ end
408
465
 
409
- while !(choice.match(/^yes$|^no$/))
410
- puts "Invalid input! Type \'yes\' or \'no\':"
411
- choice = STDIN.gets
466
+ # return true (yes) false (no)
467
+ # to the asked question
468
+ def yes_no?(msg)
469
+ answer = ui.ask( "#{msg} yes/no ? " ) do |res|
470
+ res.case = :down
471
+ res.validate = /y|n|yes|no/
472
+ res.responses[:not_valid] = "Use 'yes', 'no', 'y', 'n':"
412
473
  end
413
474
 
414
- if choice.match('yes')
415
- return true
416
- else
417
- return false
475
+ case answer
476
+ when "y", "yes"
477
+ true
478
+ when "n", "no"
479
+ false
418
480
  end
419
481
  end
420
482
 
421
483
  def destroy_vdi(vdi_ref)
484
+ vbds = get_vbds_from_vdi(vdi_ref)
485
+ unless vbds.empty?
486
+ detach_vdi(vdi_ref)
487
+ end
422
488
  task = xapi.Async.VDI.destroy(vdi_ref)
423
489
  print "Destroying volume "
424
490
  puts "#{h.color xapi.VDI.get_name_label(vdi_ref), :cyan}"
425
491
  task_ref = get_task_ref(task)
426
492
  end
493
+
494
+
427
495
  end
428
496
  end
@@ -213,7 +213,7 @@ class Chef
213
213
  # get the template vm we are going to build from
214
214
  template_ref = find_template( locate_config_value(:xapi_vm_template) )
215
215
 
216
- Chef::Log.debug "Cloning Guest from Template: #{h.color(template_ref, :bold, :cyan )}"
216
+ Chef::Log.debug "Cloning Guest from Template: #{h.color(template_ref, :bold, :cyan )}"
217
217
  task = xapi.Async.VM.clone(template_ref, fqdn)
218
218
  ui.msg "Waiting on Template Clone"
219
219
  vm_ref = get_task_ref(task)
@@ -283,7 +283,7 @@ class Chef
283
283
  # Attach the VDI to the VM
284
284
  # if its position is 0 set it bootable
285
285
  vbd_ref = create_vbd(vm_ref, vdi_ref, position, position == 0)
286
- fail(vm_ref) unless vbd_ref
286
+ fail(vm_ref) unless vbd_ref
287
287
  end
288
288
 
289
289
 
@@ -0,0 +1,100 @@
1
+ #
2
+ # Author:: Jesse Nelson (<spheromak@gmail.com>)
3
+ #
4
+ # Copyright:: Copyright (c) 2012 Jesse Nelson
5
+ #
6
+ # License:: Apache License, Version 2.0
7
+ #
8
+ # Licensed under the Apache License, Version 2.0 (the "License");
9
+ # you may not use this file except in compliance with the License.
10
+ # You may obtain a copy of the License at
11
+ #
12
+ # http://www.apache.org/licenses/LICENSE-2.0
13
+ #
14
+ # Unless required by applicable law or agreed to in writing, software
15
+ # distributed under the License is distributed on an "AS IS" BASIS,
16
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ # See the License for the specific language governing permissions and
18
+ # limitations under the License.
19
+ #
20
+
21
+
22
+ require 'chef/knife/xapi_base'
23
+
24
+ class Chef
25
+ class Knife
26
+ class XapiVdiAttach < Knife
27
+ include Chef::Knife::XapiBase
28
+
29
+ banner "knife xapi vdi attach VM_name VDI_name (options)"
30
+
31
+ option :uuid,
32
+ :short => "-U",
33
+ :long => "--uuid",
34
+ :description => "Treat the label as a UUID not a name label"
35
+
36
+ option :boot,
37
+ :long => "--boot",
38
+ :default => false,
39
+ :description => "Set the new disk as bootable (default: false)"
40
+
41
+ def run
42
+ vm_name = @name_args[0]
43
+ vdi_name = @name_args[1]
44
+
45
+ # There is no matchs with VM and VDI's name label
46
+ if vm_name.nil? or vdi_name.nil?
47
+ ui.msg "Error: No VM Name or VDI Name specified..."
48
+ ui.msg "Usage: " + banner
49
+ exit 1
50
+ end
51
+
52
+ # Get VM's ref from its name label
53
+ vm_ref = xapi.VM.get_by_name_label(vm_name)
54
+ if vm_ref.empty?
55
+ ui.msg ui.color "Could not find a vm named #{vm_name}", :red
56
+ exit 1
57
+ end
58
+ vm_ref = vm_ref.shift
59
+
60
+
61
+ # Get VDI's ref from its name label or UUID
62
+ vdis = []
63
+ if config[:uuid]
64
+ vdis << xapi.VDI.get_by_uuid(vdi_name)
65
+ else
66
+ vdis = xapi.VDI.get_by_name_label(vdi_name)
67
+ end
68
+
69
+ if vdis.empty?
70
+ ui.msg "VDI not found: #{h.color vdi_name, :red}"
71
+ exit 1
72
+ # When multiple VDI matches
73
+ Chef::Log.debug "VDI Length: #{vdis.inspect}\nType:#{vdi.class}"
74
+ elsif vdis.length > 1
75
+ ui.msg "Multiple VDI matches found use guest list if you are unsure"
76
+ vdi_ref = user_select(vdis)
77
+ else
78
+ vdi_ref = vdis.first
79
+ end
80
+
81
+
82
+ position = xapi.VM.get_VBDs(vm_ref).length
83
+
84
+ # Attach intended VDI to specific VM
85
+ if vdi_ref == :all
86
+ vdis.each do |vdi_ref|
87
+ create_vbd(vm_ref, vdi_ref, position, config[:boot] )
88
+ position += 1
89
+ end
90
+ else
91
+ create_vbd(vm_ref, vdi_ref, position, config[:boot])
92
+ end
93
+
94
+ end
95
+ end
96
+ end
97
+ end
98
+
99
+
100
+
@@ -43,88 +43,84 @@ class Chef
43
43
  :long => "--interactive",
44
44
  :description => "Interactive clean-up of orphaned volumes"
45
45
 
46
- def run
47
- if config[:interactive]
48
- # Get all VDIs known to the system
49
- vdis = get_all_vdis()
50
- first = true
51
-
52
- for vdi_ in vdis do
53
- vbds = get_vbds_from_vdi(vdi_)
54
- if vbds.empty? and xapi.VDI.get_type(vdi_).match('system')
55
- if first
56
- puts "================================================"
57
- first = false
58
- end
59
-
60
- print_vdi_info(vdi_)
61
- ret = yes_no_prompt(" No VM attached! Do you want to destroy this volume? (Type \'yes\' or \'no\'): ")
62
-
63
- if ret
64
- destroy_vdi(vdi_)
65
- end
66
- puts "================================================"
67
- end
68
- end
69
46
 
70
- elsif config[:cleanup]
71
- orphaned_vdis = []
72
- vdis = get_all_vdis()
47
+ def interactive
48
+ # Get all VDIs known to the system
49
+ vdis = get_all_vdis()
50
+ first = true
73
51
 
74
- for vdi_ in vdis do
75
- vbds = get_vbds_from_vdi(vdi_)
76
- if vbds.empty? and xapi.VDI.get_type(vdi_).match('system')
77
- orphaned_vdis << vdi_
52
+ for vdi_ in vdis do
53
+ vbds = get_vbds_from_vdi(vdi_)
54
+ if vbds.empty? and xapi.VDI.get_type(vdi_).match('system')
55
+ if first
56
+ first = false
78
57
  end
79
- end
80
58
 
81
- for item in orphaned_vdis do
82
- print_vdi_info(item)
59
+ prinlt_vdi_info(vdi_)
60
+ destroy_vdi(vdi_) if yes_no?("Destroy this volume? ")
83
61
  end
62
+ end
63
+ end
84
64
 
85
- unless orphaned_vdis.empty?
86
- ret = yes_no_prompt("Do you want to destroy all these volumes? (Type \'yes\' or \'no\'): ")
87
- if ret
88
- for item in orphaned_vdis do
89
- destroy_vdi(item)
90
- end
91
- end
92
- end
65
+ def vdi_cleanup
66
+ orphaned_vdis = []
67
+ vdis = get_all_vdis()
93
68
 
94
- else
95
- vdi_name = @name_args[0]
96
- if vdi_name.nil?
97
- puts "Error: No VDI Name specified..."
98
- puts "Usage: " + banner
99
- exit 1
69
+ for vdi_ in vdis do
70
+ vbds = get_vbds_from_vdi(vdi_)
71
+ if vbds.empty? and xapi.VDI.get_type(vdi_).match('system')
72
+ orphaned_vdis << vdi_
100
73
  end
74
+ end
101
75
 
102
- vdis = []
103
- if config[:uuid]
104
- vdis << get_vdi_by_uuid(vdi_name)
105
- else
106
- vdis << get_vdi_by_name_label(vdi_name)
107
- end
108
- vdis.flatten!
109
-
110
- if vdis.empty?
111
- puts "VDI not found: #{h.color vdi_name, :red}"
112
- exit 1
113
- elsif vdis.length > 1
114
- puts "Multiple VDI matches found. Use vdi list if you are unsure"
115
- vdi = user_select(vdis)
116
- else
117
- vdi = vdis.first
76
+ orphaned_vdis.each { |item| print_vdi_info(item) }
77
+ unless orphaned_vdis.empty?
78
+ if yes_no?("Destroy all these volumes? ")
79
+ orphaned_vdis.each { |item| destroy_vdi(item) }
118
80
  end
81
+ end
82
+ end
119
83
 
120
- vbds = get_vbds_from_vdi(vdi)
84
+ def run
85
+ if config[:interactive]
86
+ interactive
87
+ return
88
+ elsif config[:cleanup]
89
+ vdi_cleanup
90
+ return
91
+ end
121
92
 
122
- if vbds.empty?
123
- destroy_vdi(vdi)
124
- else
125
- puts "ERROR! The VDI is still in use."
126
- end
93
+ vdi_name = @name_args[0]
94
+ if vdi_name.nil?
95
+ puts "Error: No VDI Name specified..."
96
+ puts "Usage: " + banner
97
+ exit 1
127
98
  end
99
+
100
+ vdis = []
101
+ if config[:uuid]
102
+ vdis << get_vdi_by_uuid(vdi_name)
103
+ else
104
+ vdis << get_vdi_by_name_label(vdi_name)
105
+ end
106
+ vdis.flatten!
107
+
108
+ if vdis.empty?
109
+ ui.msg "VDI not found: #{h.color vdi_name, :red}"
110
+ exit 1
111
+ elsif vdis.length > 1
112
+ ui.msg "Multiple VDI matches found. Use vdi list if you are unsure"
113
+ vdi = user_select(vdis)
114
+ else
115
+ vdi = vdis.first
116
+ end
117
+
118
+ if vdi == :all
119
+ vdis.each {|vdi| destroy_vdi(vdi)}
120
+ else
121
+ destroy_vdi(vdi)
122
+ end
123
+
128
124
  end
129
125
  end
130
126
  end
@@ -0,0 +1,80 @@
1
+ #
2
+ # Author:: Jesse Nelson (<spheromak@gmail.com>)
3
+ #
4
+ # Copyright:: Copyright (c) 2012 Jesse Nelson
5
+ #
6
+ # License:: Apache License, Version 2.0
7
+ #
8
+ # Licensed under the Apache License, Version 2.0 (the "License");
9
+ # you may not use this file except in compliance with the License.
10
+ # You may obtain a copy of the License at
11
+ #
12
+ # http://www.apache.org/licenses/LICENSE-2.0
13
+ #
14
+ # Unless required by applicable law or agreed to in writing, software
15
+ # distributed under the License is distributed on an "AS IS" BASIS,
16
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ # See the License for the specific language governing permissions and
18
+ # limitations under the License.
19
+ #
20
+
21
+
22
+ require 'chef/knife/xapi_base'
23
+
24
+ class Chef
25
+ class Knife
26
+ class XapiVdiDetach < Knife
27
+ include Chef::Knife::XapiBase
28
+
29
+ banner "knife xapi vdi detach NAME_LABEL (options)"
30
+
31
+ option :uuid,
32
+ :short => "-U",
33
+ :long => "--uuid",
34
+ :description => "Treat the label as a UUID not a name label"
35
+
36
+ def run
37
+ vbd_name = @name_args[0]
38
+
39
+ if vbd_name.nil?
40
+ ui.msg "Error: No VDI Name specified..."
41
+ ui.msg "Usage: " +banner
42
+ exit 1
43
+ end
44
+
45
+ vdis = []
46
+ # detach vdi with VDI's UUID
47
+ if config[:uuid]
48
+ vdis << xapi.VDI.get_by_uuid(vbd_name)
49
+ else
50
+ # detach with VDI's Name
51
+ vdis = xapi.VDI.get_by_name_label(vbd_name)
52
+ end
53
+
54
+ if vdis.empty?
55
+ ui.msg "VDI not found: #{h.color vbd_name, :red}"
56
+ exit 1
57
+ # When multiple VDI matches
58
+ elsif vdis.length > 1
59
+ ui.msg "Multiple VDI matches found use guest list if you are unsure"
60
+ vdi_ref = user_select(vdis)
61
+ else
62
+ vdi_ref = vdis.first
63
+ end
64
+
65
+ # Detach VDI
66
+ if vdi_ref == :all
67
+ vdis.each{|vdi_ref| detach_vdi(vdi_ref)}
68
+ else
69
+ detach_vdi(vdi_ref)
70
+ end
71
+
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+
78
+
79
+
80
+
@@ -28,31 +28,39 @@ class Chef
28
28
 
29
29
  banner "knife xapi vdi list"
30
30
 
31
+ option :vdi_name,
32
+ :short => "-N",
33
+ :long => "--vdi-name",
34
+ :default => false,
35
+ :description => "Indicates this is a vdi name not a guest name"
36
+
37
+
31
38
  def run
32
- # Get all VDIs known to the system
33
- vdis = xapi.VDI.get_all()
34
-
35
- puts "================================================"
36
- for vdi_ in vdis do
37
- puts "#{h.color "VDI name: " + xapi.VDI.get_name_label(vdi_), :green}"
38
- puts " -UUID: " + xapi.VDI.get_uuid(vdi_)
39
- puts " -Description: " + xapi.VDI.get_name_description(vdi_)
40
- puts " -Type: " + xapi.VDI.get_type(vdi_)
41
-
42
- vbds = xapi.VDI.get_VBDs(vdi_)
43
- for vbd in vbds do
44
- vm = xapi.VBD.get_VM(vbd)
45
- state = xapi.VM.get_power_state(vm)
46
- puts " -VM name: " + xapi.VM.get_name_label(vm)
47
- puts " -VM state: " + state + "\n"
48
- end
49
-
50
- if vbds.empty? and xapi.VDI.get_type(vdi_).match('system')
51
- puts " No VM attached!"
52
- #puts " No VM attached! Use vdi delete --cleanup to delete this volume."
53
- end
54
- puts "================================================"
39
+ # Get all VDIs known to the system
40
+ name = @name_args[0]
41
+
42
+ # if we were passed a guest name find its vdi's
43
+ # otherwise do it for everything
44
+ vdis = Array.new
45
+ if name.nil? or name.empty?
46
+ vdis = xapi.VDI.get_all
47
+
48
+ elsif config[:vdi_name]
49
+ vdis = xapi.VDI.get_by_name_label( name )
50
+
51
+ else
52
+ ref = xapi.VM.get_by_name_label( name )
53
+ vm = xapi.VM.get_record( ref.first )
54
+
55
+ vm["VBDs"].each do |vbd|
56
+ vdis << xapi.VBD.get_record( vbd )["VDI"]
55
57
  end
58
+ end
59
+
60
+ vdis.each do |vdi|
61
+ print_vdi_info vdi
62
+ end
63
+
56
64
  end
57
65
  end
58
66
  end
@@ -1,3 +1,3 @@
1
1
  module KnifeXenserver
2
- VERSION = "0.4.1"
2
+ VERSION = "0.4.2"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: knife-xapi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.4.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-07-23 00:00:00.000000000 Z
12
+ date: 2012-08-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: chef
@@ -87,8 +87,10 @@ files:
87
87
  - lib/chef/knife/xapi_guest_create.rb
88
88
  - lib/chef/knife/xapi_guest_delete.rb
89
89
  - lib/chef/knife/xapi_guest_list.rb
90
+ - lib/chef/knife/xapi_vdi_attach.rb
90
91
  - lib/chef/knife/xapi_vdi_create.rb
91
92
  - lib/chef/knife/xapi_vdi_delete.rb
93
+ - lib/chef/knife/xapi_vdi_detach.rb
92
94
  - lib/chef/knife/xapi_vdi_list.rb
93
95
  - lib/knife-xapi/version.rb
94
96
  homepage: https://github.com/spheromak/knife-xapi