opennebula-cli 4.12.1 → 4.13.80.beta1

Sign up to get free protection for your applications and to get access to all the features.
data/lib/one_helper.rb CHANGED
@@ -649,13 +649,13 @@ user #{self.rname} of the user identified by the username
649
649
  EOT
650
650
  end
651
651
 
652
- def self.table_conf
653
- path = "#{ENV["HOME"]}/.one/cli/#{self.conf_file}"
652
+ def self.table_conf(conf_file=self.conf_file)
653
+ path = "#{ENV["HOME"]}/.one/cli/#{conf_file}"
654
654
 
655
655
  if File.exists?(path)
656
656
  return path
657
657
  else
658
- return "#{TABLE_CONF_PATH}/#{self.conf_file}"
658
+ return "#{TABLE_CONF_PATH}/#{conf_file}"
659
659
  end
660
660
  end
661
661
 
@@ -114,7 +114,7 @@ class AcctHelper < OpenNebulaHelper::OneHelper
114
114
  ACCT_OPTIONS = [START_TIME_ACCT, END_TIME_ACCT, USERFILTER, GROUP, HOST, XPATH, XML, JSON, SPLIT]
115
115
  SHOWBACK_OPTIONS = [START_TIME_SHOWBACK, END_TIME_SHOWBACK, USERFILTER, GROUP, XML, JSON]
116
116
 
117
- ACCT_TABLE = CLIHelper::ShowTable.new("oneacct.yaml", nil) do
117
+ ACCT_TABLE = CLIHelper::ShowTable.new(self.table_conf("oneacct.yaml"), nil) do
118
118
  column :UID, "User ID", :size=>4 do |d|
119
119
  d["UID"]
120
120
  end
@@ -155,20 +155,42 @@ class AcctHelper < OpenNebulaHelper::OneHelper
155
155
  d["VM"]["TEMPLATE"]["CPU"]
156
156
  end
157
157
 
158
- column :NET_RX, "Data received from the network", :size=>6 do |d|
158
+ column :NETRX, "Data received from the network", :size=>6 do |d|
159
159
  # NET is measured in bytes, unit_to_str expects KBytes
160
- OpenNebulaHelper.unit_to_str(d["VM"]["NET_RX"].to_i / 1024.0, {})
160
+ OpenNebulaHelper.unit_to_str(d["VM"]["MONITORING/NETRX"].to_i / 1024.0, {})
161
161
  end
162
162
 
163
- column :NET_TX, "Data sent to the network", :size=>6 do |d|
163
+ column :NETTX, "Data sent to the network", :size=>6 do |d|
164
164
  # NET is measured in bytes, unit_to_str expects KBytes
165
- OpenNebulaHelper.unit_to_str(d["VM"]["NET_TX"].to_i / 1024.0, {})
165
+ OpenNebulaHelper.unit_to_str(d["VM"]["MONITORING/NETTX"].to_i / 1024.0, {})
166
166
  end
167
167
 
168
- default :VID, :HOSTNAME, :ACTION, :REASON, :START_TIME, :END_TIME, :MEMORY, :CPU, :NET_RX, :NET_TX
168
+ column :DISK, "Total disk size used", :size=>6 do |d|
169
+ # DISK size is measured in mb, unit_to_str expects KBytes
170
+ total_disk_size = 0
171
+
172
+ vm_id = d["VM"]["ID"].to_i
173
+
174
+ disks_all = [d["VM"]["TEMPLATE"]["DISK"]].flatten.compact rescue []
175
+ disks_all.each do |disk|
176
+ total_disk_size += disk["SIZE"].to_i
177
+ end
178
+
179
+ snapshots_all = [d["VM"]["SNAPSHOTS"]].flatten.compact rescue []
180
+ snapshots_all.each do |snapshot|
181
+ snapshot_disk = [snapshot["SNAPSHOT"]].flatten.compact rescue []
182
+ snapshot_disk.each do |snapshot|
183
+ total_disk_size += snapshot["SIZE"].to_i
184
+ end
185
+ end
186
+
187
+ OpenNebulaHelper.unit_to_str(total_disk_size * 1024.0, {})
188
+ end
189
+
190
+ default :VID, :HOSTNAME, :ACTION, :REASON, :START_TIME, :END_TIME, :MEMORY, :CPU, :NETRX, :NETTX, :DISK
169
191
  end
170
192
 
171
- SHOWBACK_TABLE = CLIHelper::ShowTable.new("oneshowback.yaml", nil) do
193
+ SHOWBACK_TABLE = CLIHelper::ShowTable.new(self.table_conf("oneshowback.yaml"), nil) do
172
194
  column :UID, "User ID", :size=>4 do |d|
173
195
  d["UID"]
174
196
  end
@@ -167,6 +167,11 @@ class OneHostHelper < OpenNebulaHelper::OneHelper
167
167
 
168
168
  NUM_THREADS = 15
169
169
  def sync(host_ids, options)
170
+ if `id -u`.to_i == 0 || `id -G`.split.collect{|e| e.to_i}.include?(0)
171
+ STDERR.puts("Cannot run 'onehost sync' as root")
172
+ exit -1
173
+ end
174
+
170
175
  begin
171
176
  current_version = File.read(REMOTES_LOCATION+'/VERSION').strip
172
177
  rescue
@@ -406,8 +411,44 @@ class OneHostHelper < OpenNebulaHelper::OneHelper
406
411
 
407
412
  CLIHelper.print_header(str_h1 % "MONITORING INFORMATION", false)
408
413
 
414
+ wilds = host.wilds
415
+
416
+ host.delete_element("TEMPLATE/VM")
417
+ host.delete_element("TEMPLATE_WILDS")
418
+
409
419
  puts host.template_str
410
420
 
421
+ puts
422
+ CLIHelper.print_header("WILD VIRTUAL MACHINES", false)
423
+ puts
424
+
425
+ format = "%30s %36s %4s %10s"
426
+ CLIHelper.print_header(format % ["NAME", "IMPORT_ID", "CPU", "MEMORY"],
427
+ true)
428
+
429
+ wilds.each do |wild|
430
+ if wild['IMPORT_TEMPLATE']
431
+ wild_tmplt = Base64::decode64(wild['IMPORT_TEMPLATE']).split("\n")
432
+ name = wild_tmplt.select { |line|
433
+ line[/^NAME/]
434
+ }[0].split("=")[1].gsub("\"", " ").strip
435
+ import = wild_tmplt.select { |line|
436
+ line[/^IMPORT_VM_ID/]
437
+ }[0].split("=")[1].gsub("\"", " ").strip
438
+ memory = wild_tmplt.select { |line|
439
+ line[/^MEMORY/]
440
+ }[0].split("=")[1].gsub("\"", " ").strip
441
+ cpu = wild_tmplt.select { |line|
442
+ line[/^CPU/]
443
+ }[0].split("=")[1].gsub("\"", " ").strip
444
+ else
445
+ name = wild['DEPLOY_ID']
446
+ import = memory = cpu = "-"
447
+ end
448
+
449
+ puts format % [name, import, cpu, memory]
450
+ end
451
+
411
452
  puts
412
453
  CLIHelper.print_header("VIRTUAL MACHINES", false)
413
454
  puts
@@ -86,10 +86,10 @@ class OneImageHelper < OpenNebulaHelper::OneHelper
86
86
  path=Dir.pwd+"/"+o
87
87
  end
88
88
 
89
- if File.exist?(path)
89
+ if File.readable?(path)
90
90
  [0, path]
91
91
  else
92
- [-1, "File '#{path}' does not exist."]
92
+ [-1, "File '#{path}' does not exist or is not readable."]
93
93
  end
94
94
  end
95
95
  },
@@ -292,6 +292,13 @@ class OneImageHelper < OpenNebulaHelper::OneHelper
292
292
 
293
293
  puts str % [e, mask]
294
294
  }
295
+
296
+ if image.has_elements?("/IMAGE/SNAPSHOTS")
297
+ puts
298
+ CLIHelper.print_header(str_h1 % "IMAGE SNAPSHOTS",false)
299
+ format_snapshots(image)
300
+ end
301
+
295
302
  puts
296
303
 
297
304
  CLIHelper.print_header(str_h1 % "IMAGE TEMPLATE",false)
@@ -311,6 +318,44 @@ class OneImageHelper < OpenNebulaHelper::OneHelper
311
318
  end
312
319
  end
313
320
 
321
+ def format_snapshots(image)
322
+ table=CLIHelper::ShowTable.new(nil, self) do
323
+ column :AC , "Is active", :left, :size => 2 do |d|
324
+ if d["ACTIVE"] == "YES"
325
+ "=>"
326
+ else
327
+ ""
328
+ end
329
+ end
330
+ column :ID, "Snapshot ID", :size=>3 do |d|
331
+ d["ID"]
332
+ end
333
+
334
+ column :PARENT, "Snapshot Parent ID", :size=>6 do |d|
335
+ d["PARENT"]
336
+ end
337
+
338
+ column :CHILDREN, "Snapshot Children IDs", :size=>10 do |d|
339
+ d["CHILDREN"]
340
+ end
341
+
342
+ column :NAME, "Snapshot Name", :left, :size=>45 do |d|
343
+ d["NAME"]
344
+ end
345
+
346
+ column :DATE, "Snapshot creation date", :size=>15 do |d|
347
+ OpenNebulaHelper.time_to_str(d["DATE"])
348
+ end
349
+
350
+ default :AC, :ID, :PARENT, :DATE, :CHILDREN, :NAME
351
+ end
352
+
353
+ # Convert snapshot data to an array
354
+ image_hash = image.to_hash
355
+ image_snapshots = [image_hash['IMAGE']['SNAPSHOTS']].flatten.first
356
+ table.show(image_snapshots)
357
+ end
358
+
314
359
  def self.create_image_variables(options, name)
315
360
  if Array===name
316
361
  names=name
@@ -74,7 +74,7 @@ class OneQuotaHelper
74
74
 
75
75
  # Edits the quota template of a resource
76
76
  # @param [XMLElement] resource to get the current info from
77
- # @param [String] path to the new contents. If nil a editor will be
77
+ # @param [String] path to the new contents. If nil a editor will be
78
78
  # used
79
79
  # @param [True|False] is_default To change the help text
80
80
  # @return [String] contents of the new quotas
@@ -122,7 +122,7 @@ class OneQuotaHelper
122
122
 
123
123
  # Retrieves a clean quota template, without any existing resource
124
124
  # information
125
- # @param path [String] path to the new contents. If nil a editor will be
125
+ # @param path [String] path to the new contents. If nil a editor will be
126
126
  # used
127
127
  # @return [String] contents of the new quotas
128
128
  def self.get_batch_quota(path)
@@ -159,7 +159,7 @@ class OneQuotaHelper
159
159
  # Edits the quota template of a resource, adding the quotas set in str
160
160
  # @param resource [PoolElement] to get the current info from
161
161
  # @param str [String] quota template, created by get_batch_quota()
162
- # @return [String, OpenNebula::Error] merged contents of the new quotas on
162
+ # @return [String, OpenNebula::Error] merged contents of the new quotas on
163
163
  # success, Error if the user info could not be retrieved
164
164
  def self.merge_quota(resource, str)
165
165
  rc = resource.info
@@ -14,8 +14,38 @@
14
14
  # limitations under the License. #
15
15
  #--------------------------------------------------------------------------- #
16
16
 
17
+ if !ONE_LOCATION
18
+ MAD_LOCATION = "/usr/lib/one/mads"
19
+ VAR_LOCATION = "/var/lib/one"
20
+ else
21
+ MAD_LOCATION = ONE_LOCATION + "/lib/mads"
22
+ VAR_LOCATION = ONE_LOCATION + "/var"
23
+ end
24
+
25
+ VMS_LOCATION = VAR_LOCATION + "/vms"
26
+
27
+ $: << MAD_LOCATION
28
+
17
29
  require 'one_helper'
18
30
  require 'optparse/time'
31
+ require 'one_tm'
32
+
33
+ class String
34
+ def red
35
+ colorize(31)
36
+ end
37
+
38
+ def green
39
+ colorize(32)
40
+ end
41
+
42
+ private
43
+
44
+ def colorize(color_code)
45
+ "\e[#{color_code}m#{self}\e[0m"
46
+ end
47
+ end
48
+
19
49
 
20
50
  class OneVMHelper < OpenNebulaHelper::OneHelper
21
51
  MULTIPLE={
@@ -123,6 +153,45 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
123
153
  return short_state_str
124
154
  end
125
155
 
156
+ # Return the IP or several IPs of a VM
157
+ def self.ip_str(vm)
158
+ ips = []
159
+
160
+ vm_nics = []
161
+
162
+ if !vm["TEMPLATE"]["NIC"].nil?
163
+ vm_nics = [vm["TEMPLATE"]['NIC']].flatten
164
+ end
165
+
166
+ vm_nics.each do |nic|
167
+ if nic.has_key?("IP")
168
+ ips.push(nic["IP"])
169
+ end
170
+
171
+ if nic.has_key?("IP6_GLOBAL")
172
+ ips.push(nic["IP6_GLOBAL"])
173
+ end
174
+
175
+ if nic.has_key?("IP6_ULA")
176
+ ips.push(nic["IP6_ULA"])
177
+ end
178
+ end
179
+
180
+ VirtualMachine::EXTERNAL_IP_ATTRS.each do |attr|
181
+ external_ip = vm["MONITORING"][attr]
182
+
183
+ if !external_ip.nil? && !ips.include?(external_ip)
184
+ ips.push(external_ip)
185
+ end
186
+ end
187
+
188
+ if ips.empty?
189
+ return "--"
190
+ else
191
+ return ips.join(",")
192
+ end
193
+ end
194
+
126
195
  def format_pool(options)
127
196
  config_file = self.class.table_conf
128
197
 
@@ -208,6 +277,10 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
208
277
  OpenNebulaHelper.period_to_str(dtime, false)
209
278
  end
210
279
 
280
+ column :IP, "VM IP addresses", :left, :donottruncate, :size=>15 do |d|
281
+ OneVMHelper.ip_str(d)
282
+ end
283
+
211
284
  default :ID, :USER, :GROUP, :NAME, :STAT, :UCPU, :UMEM, :HOST,
212
285
  :TIME
213
286
  end
@@ -247,6 +320,123 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
247
320
  end
248
321
  end
249
322
 
323
+ RECOVER_RETRY_STEPS = {
324
+ :PROLOG_MIGRATE_FAILURE => :migrate,
325
+ :PROLOG_MIGRATE_POWEROFF_FAILURE => :migrate,
326
+ :PROLOG_MIGRATE_SUSPEND_FAILURE => :migrate,
327
+ :PROLOG_FAILURE => :prolog,
328
+ :PROLOG_RESUME_FAILURE => :resume,
329
+ :PROLOG_UNDEPLOY_FAILURE => :resume,
330
+ :EPILOG_FAILURE => :epilog,
331
+ :EPILOG_STOP_FAILURE => :stop,
332
+ :EPILOG_UNDEPLOY_FAILURE => :stop
333
+ }
334
+
335
+ def recover_retry_interactive(vm)
336
+ # Disable CTRL-C in the menu
337
+ trap("SIGINT") { }
338
+
339
+ if !File.readable?(VAR_LOCATION+"/config")
340
+ STDERR.puts "Error reading #{VAR_LOCATION+'/config'}. The " <<
341
+ "TM Debug Interactive Environment must be executed as " <<
342
+ "oneadmin in the frontend."
343
+ exit -1
344
+ end
345
+
346
+ rc = vm.info
347
+ if OpenNebula.is_error?(rc)
348
+ STDERR.puts rc.message
349
+ exit -1
350
+ end
351
+
352
+ if !RECOVER_RETRY_STEPS.include?(vm.lcm_state_str.to_sym)
353
+ STDERR.puts "Current LCM STATE '#{vm.lcm_state_str}' not " <<
354
+ "compatible with RECOVER RETRY action."
355
+ exit -1
356
+ end
357
+
358
+ seq = vm['/VM/HISTORY_RECORDS/HISTORY[last()]/SEQ']
359
+
360
+ tm_action = RECOVER_RETRY_STEPS[vm.lcm_state_str.to_sym]
361
+
362
+ tm_file = "#{VMS_LOCATION}/#{vm.id}/transfer.#{seq}.#{tm_action}"
363
+
364
+ if !File.readable?(tm_file)
365
+ STDERR.puts "Cannot read #{tm_file}"
366
+ exit -1
367
+ end
368
+
369
+ @tm_action_list = File.read(tm_file)
370
+
371
+ puts "TM Debug Interactive Environment.".green
372
+ puts
373
+ print_tm_action_list
374
+
375
+ @tm = TransferManagerDriver.new(nil)
376
+ i=0
377
+ @tm_action_list.lines.each do |tm_command|
378
+ i+=1
379
+ success=false
380
+
381
+ while !success
382
+ puts "Current action (#{i}):".green
383
+ puts tm_command
384
+ puts
385
+
386
+ puts <<-EOF.gsub(/^\s+/,"")
387
+ Choose action:
388
+ (r) Run action
389
+ (n) Skip to next action
390
+ (a) Show all actions
391
+ (q) Quit
392
+ EOF
393
+
394
+ ans = ""
395
+ while !%w(n a r q).include?(ans)
396
+ printf "> "
397
+ ans = STDIN.gets.strip.downcase
398
+
399
+ puts
400
+
401
+ case ans
402
+ when "n"
403
+ success = true
404
+ when "a"
405
+ print_tm_action_list
406
+ when "q"
407
+ exit -1
408
+ when "r"
409
+ result, result_message = @tm.do_transfer_action(@id, tm_command.split)
410
+
411
+ if result == "SUCCESS"
412
+ success = true
413
+ puts "#{result}"
414
+ puts
415
+ else
416
+ puts
417
+ puts "#{result}. Repeat command.".red
418
+ puts
419
+ end
420
+ end
421
+ end
422
+ end
423
+ end
424
+
425
+ puts "If all the TM actions have been successful and you want to"
426
+ puts "recover the Virtual Machine to the RUNNING state execute this command:"
427
+ puts "$ onevm recover #{vm.id} --success"
428
+ end
429
+
430
+ def print_tm_action_list
431
+ puts "TM Action list:".green
432
+ i=0
433
+ @tm_action_list.lines.each do |line|
434
+ i+=1
435
+ puts "(#{i}) #{line}"
436
+ end
437
+ puts
438
+ end
439
+
250
440
  private
251
441
 
252
442
  def factory(id=nil)
@@ -312,22 +502,37 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
312
502
  puts
313
503
 
314
504
  CLIHelper.print_header(str_h1 % "VIRTUAL MACHINE MONITORING",false)
315
- poll_attrs = {
316
- "USED MEMORY" => "MEMORY",
317
- "USED CPU" => "CPU",
318
- "NET_TX" => "NET_TX",
319
- "NET_RX" => "NET_RX"
320
- }
321
505
 
322
- poll_attrs.each { |k,v|
323
- if k == "USED CPU"
324
- puts str % [k,vm[v]]
325
- elsif k == "USED MEMORY"
326
- puts str % [k, OpenNebulaHelper.unit_to_str(vm[v].to_i, {})]
506
+ vm_monitoring = vm.to_hash['VM']['MONITORING']
507
+
508
+ order_attrs = %w(CPU MEMORY NETTX NETRX)
509
+
510
+ vm_monitoring_sort = []
511
+ order_attrs.each do |key|
512
+ if (val = vm_monitoring.delete(key))
513
+ vm_monitoring_sort << [key, val]
514
+ end
515
+ end
516
+
517
+ vm_monitoring_sort.sort{|a,b| a[0]<=>b[0]}
518
+
519
+ filter_attrs = %w(STATE DISK_SIZE SNAPSHOT_SIZE)
520
+ vm_monitoring.each do |key, val|
521
+ if !filter_attrs.include?(key)
522
+ vm_monitoring_sort << [key, val]
523
+ end
524
+ end
525
+
526
+ vm_monitoring_sort.each do |k,v|
527
+ if k == "MEMORY"
528
+ puts str % [k, OpenNebulaHelper.unit_to_str(v.to_i, {})]
529
+ elsif k =~ /NET.X/
530
+ puts str % [k, OpenNebulaHelper.unit_to_str(v.to_i/1024, {})]
327
531
  else
328
- puts str % [k, OpenNebulaHelper.unit_to_str(vm[v].to_i/1024, {})]
532
+ puts str % [k, v]
329
533
  end
330
- }
534
+ end
535
+
331
536
  puts
332
537
 
333
538
  CLIHelper.print_header(str_h1 % "PERMISSIONS",false)
@@ -341,7 +546,33 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
341
546
  puts str % [e, mask]
342
547
  }
343
548
 
549
+ vm_disks = []
550
+
344
551
  if vm.has_elements?("/VM/TEMPLATE/DISK")
552
+ vm_disks = [vm.to_hash['VM']['TEMPLATE']['DISK']].flatten
553
+ end
554
+
555
+ if vm.has_elements?("/VM/TEMPLATE/CONTEXT")
556
+ context_disk = vm.to_hash['VM']['TEMPLATE']['CONTEXT']
557
+
558
+ context_disk["IMAGE"] = "CONTEXT"
559
+ context_disk["DATASTORE"] = "-"
560
+ context_disk["TYPE"] = "-"
561
+ context_disk["READONLY"] = "-"
562
+ context_disk["SAVE"] = "-"
563
+ context_disk["CLONE"] = "-"
564
+ context_disk["SAVE_AS"] = "-"
565
+
566
+ vm_disks.push(context_disk)
567
+ end
568
+
569
+ # get monitoring data
570
+ vm_disks.each do |disk|
571
+ disk_id = disk["DISK_ID"]
572
+ disk["MONITOR_SIZE"] = vm["MONITORING/DISK_SIZE[ID='#{disk_id}']/SIZE"]
573
+ end
574
+
575
+ if !vm_disks.empty?
345
576
  puts
346
577
  CLIHelper.print_header(str_h1 % "VM DISKS",false)
347
578
  CLIHelper::ShowTable.new(nil, self) do
@@ -374,6 +605,30 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
374
605
  end
375
606
  end
376
607
 
608
+ column :SIZE, "", :left, :size=>9 do |d|
609
+ if d["SIZE"]
610
+ size = OpenNebulaHelper.unit_to_str(
611
+ d['SIZE'].to_i,
612
+ {},
613
+ "M"
614
+ )
615
+ else
616
+ size = "-"
617
+ end
618
+
619
+ if d["MONITOR_SIZE"]
620
+ monitor_size = OpenNebulaHelper.unit_to_str(
621
+ d['MONITOR_SIZE'].to_i,
622
+ {},
623
+ "M"
624
+ )
625
+ else
626
+ monitor_size = "-"
627
+ end
628
+
629
+ "#{monitor_size}/#{size}"
630
+ end
631
+
377
632
  column :TYPE, "", :left, :size=>4 do |d|
378
633
  d["TYPE"].downcase
379
634
  end
@@ -390,20 +645,21 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
390
645
  d["CLONE"]
391
646
  end
392
647
 
393
- column :"SAVE_AS", "", :size=>7 do |d|
394
- d["SAVE_AS"] || "-"
395
- end
396
-
397
-
398
- default :ID, :TARGET, :IMAGE, :TYPE,
399
- :SAVE, :SAVE_AS
400
- end.show([vm.to_hash['VM']['TEMPLATE']['DISK']].flatten, {})
648
+ default :ID, :DATASTORE, :TARGET, :IMAGE, :SIZE, :TYPE,
649
+ :SAVE
650
+ end.show(vm_disks, {})
401
651
 
402
652
  while vm.has_elements?("/VM/TEMPLATE/DISK")
403
653
  vm.delete_element("/VM/TEMPLATE/DISK")
404
654
  end if !options[:all]
405
655
  end
406
656
 
657
+ if vm.has_elements?("/VM/SNAPSHOTS")
658
+ puts
659
+ CLIHelper.print_header(str_h1 % "VM DISK SNAPSHOTS",false)
660
+ format_snapshots(vm)
661
+ end
662
+
407
663
  sg_nics = []
408
664
 
409
665
  if (vm.has_elements?("/VM/TEMPLATE/NIC/SECURITY_GROUPS"))
@@ -730,4 +986,91 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
730
986
 
731
987
  table.show(history)
732
988
  end
989
+
990
+ def format_snapshots(vm)
991
+ table=CLIHelper::ShowTable.new(nil, self) do
992
+ column :AC , "Is active", :left, :size => 2 do |d|
993
+ if d["ACTIVE"] == "YES"
994
+ "=>"
995
+ else
996
+ ""
997
+ end
998
+ end
999
+ column :ID, "Snapshot ID", :size=>3 do |d|
1000
+ d["ID"]
1001
+ end
1002
+
1003
+ column :DISK, "Disk ID", :size=>4 do |d|
1004
+ d["DISK_ID"]
1005
+ end
1006
+
1007
+ column :PARENT, "Snapshot Parent ID", :size=>6 do |d|
1008
+ d["PARENT"]
1009
+ end
1010
+
1011
+ column :CHILDREN, "Snapshot Children IDs", :size=>10 do |d|
1012
+ d["CHILDREN"]
1013
+ end
1014
+
1015
+ column :SIZE, "", :left, :size=>9 do |d|
1016
+ if d["SIZE"]
1017
+ size = OpenNebulaHelper.unit_to_str(
1018
+ d['SIZE'].to_i,
1019
+ {},
1020
+ "M"
1021
+ )
1022
+ else
1023
+ size = "-"
1024
+ end
1025
+
1026
+ if d["MONITOR_SIZE"]
1027
+ monitor_size = OpenNebulaHelper.unit_to_str(
1028
+ d['MONITOR_SIZE'].to_i,
1029
+ {},
1030
+ "M"
1031
+ )
1032
+ else
1033
+ monitor_size = "-"
1034
+ end
1035
+
1036
+ "#{monitor_size}/#{size}"
1037
+ end
1038
+
1039
+ column :NAME, "Snapshot Name", :left, :size=>26 do |d|
1040
+ d["NAME"]
1041
+ end
1042
+
1043
+ column :DATE, "Snapshot creation date", :size=>10 do |d|
1044
+ OpenNebulaHelper.time_to_str(d["DATE"])
1045
+ end
1046
+
1047
+ default :AC, :ID, :DISK, :PARENT, :DATE, :CHILDREN, :SIZE, :NAME
1048
+ end
1049
+
1050
+ # Convert snapshot data to an array
1051
+ vm_hash = vm.to_hash
1052
+ vm_snapshots = [vm_hash['VM']['SNAPSHOTS']].flatten
1053
+
1054
+ snapshots = []
1055
+
1056
+ vm_snapshots.each do |disk|
1057
+ disk_id = disk['DISK_ID']
1058
+
1059
+ sshots = [disk['SNAPSHOT']].flatten
1060
+ sshots.each do |snapshot|
1061
+ data = snapshot.merge({ 'DISK_ID' => disk_id })
1062
+ snapshots << data
1063
+ end
1064
+ end
1065
+
1066
+ # get monitoring data
1067
+ snapshots.each do |snapshot|
1068
+ disk_id = snapshot["DISK_ID"]
1069
+ snap_id = snapshot["ID"]
1070
+ xpath = "MONITORING/SNAPSHOT_SIZE[ID='#{snap_id}' and DISK_ID='#{disk_id}']/SIZE"
1071
+ snapshot["MONITOR_SIZE"] = vm[xpath]
1072
+ end
1073
+
1074
+ table.show(snapshots)
1075
+ end
733
1076
  end