knife-xapi 0.4.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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