opennebula-cli 5.11.80.pre → 5.12.0.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.
@@ -115,7 +115,7 @@ class OneAclHelper < OpenNebulaHelper::OneHelper
115
115
  def format_pool(_options)
116
116
  config_file = self.class.table_conf
117
117
 
118
- table = CLIHelper::ShowTable.new(config_file, self) do
118
+ CLIHelper::ShowTable.new(config_file, self) do
119
119
  column :ID,
120
120
  'Rule Identifier',
121
121
  :size => 5 do |d|
@@ -157,8 +157,6 @@ class OneAclHelper < OpenNebulaHelper::OneHelper
157
157
 
158
158
  default :ID, :USER, :RES_VHNIUTGDCOZSvRMAPt, :RID, :OPE_UMAC, :ZONE
159
159
  end
160
-
161
- table
162
160
  end
163
161
  # rubocop:enable Lint/IneffectiveAccessModifier
164
162
 
@@ -63,15 +63,15 @@ class OneClusterHelper < OpenNebulaHelper::OneHelper
63
63
  end
64
64
 
65
65
  column :HOSTS, "Number of Hosts", :size=>5 do |d|
66
- @ext.element_size(d,"HOSTS")
66
+ @ext.element_size(d,"HOSTS") rescue 0
67
67
  end
68
68
 
69
69
  column :VNETS, "Number of Networks", :size=>5 do |d|
70
- @ext.element_size(d,"VNETS")
70
+ @ext.element_size(d,"VNETS") rescue 0
71
71
  end
72
72
 
73
73
  column :DATASTORES, "Number of Datastores", :size=>10 do |d|
74
- @ext.element_size(d,"DATASTORES")
74
+ @ext.element_size(d,"DATASTORES") rescue 0
75
75
  end
76
76
 
77
77
  default :ID, :NAME, :HOSTS, :VNETS, :DATASTORES
@@ -19,6 +19,11 @@ require 'one_helper'
19
19
  # Oneflow command helper
20
20
  class OneFlowHelper < OpenNebulaHelper::OneHelper
21
21
 
22
+ # Configuration file
23
+ def self.conf_file
24
+ 'oneflow.yaml'
25
+ end
26
+
22
27
  # Get client to make request
23
28
  #
24
29
  # @options [Hash] CLI options
@@ -33,8 +38,9 @@ class OneFlowHelper < OpenNebulaHelper::OneHelper
33
38
 
34
39
  # Get service pool table
35
40
  def format_service_pool
36
- # TODO: config file
37
- CLIHelper::ShowTable.new(nil, self) do
41
+ config_file = self.class.table_conf
42
+
43
+ CLIHelper::ShowTable.new(config_file, self) do
38
44
  column :ID, 'ID', :size => 10 do |d|
39
45
  d['ID']
40
46
  end
@@ -400,7 +406,11 @@ class OneFlowHelper < OpenNebulaHelper::OneHelper
400
406
 
401
407
  column :TIME, '', :left, :size => 67 do |d|
402
408
  if d['start_time']
403
- Time.parse(d['start_time']).to_s
409
+ if !d['start_time'].match(/^\d+$/)
410
+ Time.parse(d['start_time']).to_s
411
+ else
412
+ d['start_time']
413
+ end
404
414
  else
405
415
  d['recurrence']
406
416
  end
@@ -19,6 +19,11 @@ require 'one_helper'
19
19
  # Oneflow Template command helper
20
20
  class OneFlowTemplateHelper < OpenNebulaHelper::OneHelper
21
21
 
22
+ # Configuration file
23
+ def self.conf_file
24
+ 'oneflowtemplate.yaml'
25
+ end
26
+
22
27
  # Get client to make request
23
28
  #
24
29
  # @options [Hash] CLI options
@@ -33,8 +38,9 @@ class OneFlowTemplateHelper < OpenNebulaHelper::OneHelper
33
38
 
34
39
  # Get service template pool
35
40
  def format_service_template_pool
36
- # TODO: config file
37
- CLIHelper::ShowTable.new(nil, self) do
41
+ config_file = self.class.table_conf
42
+
43
+ CLIHelper::ShowTable.new(config_file, self) do
38
44
  column :ID, 'ID', :size => 10 do |d|
39
45
  d['ID']
40
46
  end
@@ -94,7 +94,7 @@ class OneHookHelper < OpenNebulaHelper::OneHelper
94
94
  def format_pool(_options)
95
95
  config_file = self.class.table_conf
96
96
 
97
- table = CLIHelper::ShowTable.new(config_file, self) do
97
+ CLIHelper::ShowTable.new(config_file, self) do
98
98
  column :ID, 'ONE identifier for the Hook', :size => 5 do |d|
99
99
  d['ID']
100
100
  end
@@ -109,8 +109,6 @@ class OneHookHelper < OpenNebulaHelper::OneHelper
109
109
 
110
110
  default :ID, :NAME, :TYPE
111
111
  end
112
-
113
- table
114
112
  end
115
113
 
116
114
  # Function to print Execution Log records as sent by oned using:
@@ -163,7 +161,11 @@ class OneHookHelper < OpenNebulaHelper::OneHelper
163
161
  end
164
162
  end
165
163
 
166
- default :HOOK, :ID, :TIMESTAMP, :RC, :EXECUTION
164
+ if !header
165
+ default :HOOK, :ID, :TIMESTAMP, :RC, :EXECUTION
166
+ else
167
+ default :ID, :TIMESTAMP, :RC, :EXECUTION
168
+ end
167
169
  end
168
170
 
169
171
  table.show(execs, :stat_column => :EXECUTION)
@@ -17,6 +17,7 @@
17
17
  require 'one_helper'
18
18
  require 'one_helper/onevm_helper'
19
19
  require 'rubygems'
20
+ require 'time'
20
21
 
21
22
  # implements onehost command
22
23
  class OneHostHelper < OpenNebulaHelper::OneHelper
@@ -75,6 +76,15 @@ class OneHostHelper < OpenNebulaHelper::OneHelper
75
76
 
76
77
  VERSION_XPATH = "#{TEMPLATE_XPATH}/VERSION"
77
78
 
79
+ MONITORING = {
80
+ 'FREE_CPU' => 'CAPACITY',
81
+ 'FREE_MEMORY' => 'CAPACITY',
82
+ 'USED_CPU' => 'CAPACITY',
83
+ 'USED_MEMORY' => 'CAPACITY',
84
+ 'NETRX' => 'SYSTEM',
85
+ 'NETTX' => 'SYSTEM'
86
+ }
87
+
78
88
  def self.rname
79
89
  'HOST'
80
90
  end
@@ -93,7 +103,7 @@ class OneHostHelper < OpenNebulaHelper::OneHelper
93
103
  def format_pool(options)
94
104
  config_file = self.class.table_conf
95
105
 
96
- table = CLIHelper::ShowTable.new(config_file, self) do
106
+ CLIHelper::ShowTable.new(config_file, self) do
97
107
  column :ID, 'ONE identifier for Host', :size => 4 do |d|
98
108
  d['ID']
99
109
  end
@@ -223,8 +233,6 @@ class OneHostHelper < OpenNebulaHelper::OneHelper
223
233
  default :ID, :NAME, :CLUSTER, :TVM,
224
234
  :ALLOCATED_CPU, :ALLOCATED_MEM, :STAT
225
235
  end
226
-
227
- table
228
236
  end
229
237
 
230
238
  def set_hybrid(type, path)
@@ -425,8 +433,7 @@ class OneHostHelper < OpenNebulaHelper::OneHelper
425
433
  rc = pool.info
426
434
  return -1, rc.message if OpenNebula.is_error?(rc)
427
435
 
428
- # Assign hosts to threads
429
- queue = []
436
+ host_errors = []
430
437
 
431
438
  pool.each do |host|
432
439
  if host_ids
@@ -435,7 +442,6 @@ class OneHostHelper < OpenNebulaHelper::OneHelper
435
442
  next if host['CLUSTER_ID'].to_i != cluster_id
436
443
  end
437
444
 
438
- vm_mad = host['VM_MAD'].downcase
439
445
  state = host['STATE']
440
446
 
441
447
  # Skip this host from remote syncing if it's a PUBLIC_CLOUD host
@@ -444,60 +450,104 @@ class OneHostHelper < OpenNebulaHelper::OneHelper
444
450
  # Skip this host from remote syncing if it's OFFLINE
445
451
  next if Host::HOST_STATES[state.to_i] == 'OFFLINE'
446
452
 
447
- # Skip this host if it is a vCenter cluster
448
- next if vm_mad == 'vcenter'
453
+ rc = host.forceupdate
449
454
 
450
- queue << host
455
+ host_errors << host['NAME'] if OpenNebula.is_error?(rc)
451
456
  end
452
457
 
453
- # Run the jobs in threads
454
- host_errors = []
455
- queue_lock = Mutex.new
456
- error_lock = Mutex.new
457
- total = queue.length
458
+ if host_errors.empty?
459
+ puts 'All hosts updated successfully.'
460
+ 0
461
+ else
462
+ STDERR.puts 'Failed to update the following hosts:'
463
+ host_errors.each {|h| STDERR.puts "* #{h}" }
464
+ -1
465
+ end
466
+ end
458
467
 
459
- if total.zero?
460
- puts 'No hosts are going to be forced.'
461
- exit(0)
468
+ def monitoring(host, attr, options)
469
+ unit = options[:unit] || 'G'
470
+ start_d = options[:start]
471
+ end_d = options[:end]
472
+ n_elems = options[:n_elems] || 8
473
+
474
+ # Different available size units
475
+ units = %w[K M G T]
476
+
477
+ # Attrs that need units conversion
478
+ attrs = %w[FREE_MEMORY USED_MEMORY]
479
+
480
+ if unit && !units.include?(unit)
481
+ STDERR.puts "Invalid unit `#{unit}`"
482
+ exit(-1)
462
483
  end
463
484
 
464
- ts = (1..NUM_THREADS).map do |_t|
465
- Thread.new do
466
- loop do
467
- host = nil
468
- size = 0
485
+ attr = attr.upcase
486
+ start_d = Time.parse(start_d) if start_d
487
+ end_d = Time.parse(end_d) if end_d
469
488
 
470
- queue_lock.synchronize do
471
- host = queue.shift
472
- size = queue.length
473
- end
489
+ # Get monitoring data from user path
490
+ #
491
+ # 0 -> timestamp
492
+ # 1 -> data retrieved
493
+ monitoring_data = host.monitoring(["#{MONITORING[attr]}/#{attr}"])
494
+ monitoring_data = monitoring_data["#{MONITORING[attr]}/#{attr}"]
474
495
 
475
- break unless host
496
+ if monitoring_data.empty?
497
+ STDERR.puts 'No monitoring data found'
498
+ return
499
+ end
476
500
 
477
- cmd = 'cat /tmp/one-monitord-client.pid | xargs kill -HUP'
478
- system("ssh #{host['NAME']} \"#{cmd}\" 2>/dev/null")
501
+ # Get data max and min date
502
+ start_d ||= Time.at(monitoring_data.min {|v| v[0].to_i }[0].to_i)
503
+ end_d ||= Time.at(monitoring_data.max {|v| v[0].to_i }[0].to_i)
479
504
 
480
- if !$CHILD_STATUS.success?
481
- error_lock.synchronize do
482
- host_errors << host['NAME']
483
- end
484
- else
485
- puts "#{host['NAME']} monitoring forced"
486
- end
487
- end
505
+ # Filter data betwen dates
506
+ monitoring_data.reject! do |v|
507
+ v[0].to_i < start_d.to_i || v[0].to_i > end_d.to_i
508
+ end
509
+
510
+ if monitoring_data.empty?
511
+ STDERR.puts "No monitoring data found between #{start_d} " \
512
+ "and #{end_d}"
513
+ return
514
+ end
515
+
516
+ start_d = start_d.strftime('%d/%m/%Y %H:%M')
517
+ end_d = end_d.strftime('%d/%m/%Y %H:%M')
518
+
519
+ # Parse dcollected data
520
+ x = monitoring_data.collect {|v| Time.at(v[0].to_i).strftime('%H:%M') }
521
+ y = monitoring_data.collect do |v|
522
+ if attrs.include?(attr)
523
+ # GB is the default unit
524
+ v = OpenNebulaHelper.bytes_to_unit(v[1].to_i, unit).round(2)
525
+ "#{v} #{unit}B"
526
+ else
527
+ v[1]
488
528
  end
489
529
  end
490
530
 
491
- # Wait for threads to finish
492
- ts.each {|t| t.join }
531
+ title = ''
532
+ title << "Host #{host.id} #{attr} "
533
+ title << "in #{unit}B " if unit && attrs.include?(attr)
534
+ title << "from #{start_d} to #{end_d}"
493
535
 
494
- if host_errors.empty?
495
- puts 'All hosts updated successfully.'
496
- 0
536
+ x = x.last(n_elems)
537
+ y = y.last(n_elems)
538
+
539
+ if options[:table]
540
+ print_monitoring_table(x, y, title)
541
+ elsif options[:csv]
542
+ csv = ''
543
+
544
+ csv << "TIME#{options[:csv]}VALUE\n"
545
+
546
+ x.zip(y) {|x_v, y_v| csv << "#{x_v}#{options[:csv]}#{y_v}\n" }
547
+
548
+ puts csv
497
549
  else
498
- STDERR.puts 'Failed to update the following hosts:'
499
- host_errors.each {|h| STDERR.puts "* #{h}" }
500
- -1
550
+ puts OpenNebulaHelper.get_plot(x, y, attr, title)
501
551
  end
502
552
  end
503
553
 
@@ -664,7 +714,7 @@ class OneHostHelper < OpenNebulaHelper::OneHelper
664
714
  .split("\n")
665
715
  name = wild['VM_NAME']
666
716
  import = wild_tmplt.select do |line|
667
- line[/IMPORT_VM_ID/]
717
+ line[/DEPLOY_ID/]
668
718
  end[0].split('=')[1].tr('"', ' ').strip
669
719
  memory = wild_tmplt.select do |line|
670
720
  line[/MEMORY/]
@@ -920,4 +970,30 @@ class OneHostHelper < OpenNebulaHelper::OneHelper
920
970
  table.show(hugepages)
921
971
  end
922
972
 
973
+ def print_monitoring_table(x, y, title)
974
+ puts
975
+ CLIHelper.print_header(title, true)
976
+ puts
977
+
978
+ table = CLIHelper::ShowTable.new(nil, self) do
979
+ column :TIME, 'Timestamp', :size => 8, :left => false do |d|
980
+ d['TIME']
981
+ end
982
+
983
+ column :VALUE, 'Value', :size => 8, :left => false do |d|
984
+ d['VALUE']
985
+ end
986
+
987
+ default :TIME, :VALUE
988
+ end
989
+
990
+ data = []
991
+
992
+ x.zip(y) do |x_v, y_v|
993
+ data << { 'TIME' => x_v, 'VALUE' => y_v }
994
+ end
995
+
996
+ table.show(data)
997
+ end
998
+
923
999
  end
@@ -192,7 +192,7 @@ class OneImageHelper < OpenNebulaHelper::OneHelper
192
192
  def format_pool(options)
193
193
  config_file = self.class.table_conf
194
194
 
195
- table = CLIHelper::ShowTable.new(config_file, self) do
195
+ CLIHelper::ShowTable.new(config_file, self) do
196
196
  column :ID, 'ONE identifier for the Image', :size=>4 do |d|
197
197
  d['ID']
198
198
  end
@@ -246,8 +246,6 @@ class OneImageHelper < OpenNebulaHelper::OneHelper
246
246
  default :ID, :USER, :GROUP, :NAME, :DATASTORE, :SIZE, :TYPE,
247
247
  :PERSISTENT, :STAT, :RVMS
248
248
  end
249
-
250
- table
251
249
  end
252
250
 
253
251
  def check_orphans
@@ -49,7 +49,7 @@ class OneProvisionHelper < OpenNebulaHelper::OneHelper
49
49
  def format_pool
50
50
  config_file = self.class.table_conf
51
51
 
52
- table = CLIHelper::ShowTable.new(config_file, self) do
52
+ CLIHelper::ShowTable.new(config_file, self) do
53
53
  column :ID, 'Identifier for the Provision', :size => 36 do |p|
54
54
  p['ID']
55
55
  end
@@ -80,8 +80,6 @@ class OneProvisionHelper < OpenNebulaHelper::OneHelper
80
80
 
81
81
  default :ID, :NAME, :CLUSTERS, :HOSTS, :NETWORKS, :DATASTORES, :STAT
82
82
  end
83
-
84
- table
85
83
  end
86
84
 
87
85
  #######################################################################
@@ -228,11 +226,9 @@ class OneProvisionHelper < OpenNebulaHelper::OneHelper
228
226
  end
229
227
 
230
228
  def names_to_ids(objects, type)
231
- objects = [objects].flatten.map do |obj|
229
+ [objects].flatten.map do |obj|
232
230
  OpenNebulaHelper.rname_to_id(obj.to_s, type)[1]
233
231
  end
234
-
235
- objects
236
232
  end
237
233
 
238
234
  def get_list(provision_list)
@@ -237,11 +237,11 @@ class OneVcenterHelper < OpenNebulaHelper::OneHelper
237
237
  d[:import_id]
238
238
  end
239
239
 
240
- column :REF, "ref", :left, :size=>config[:REF] || 15 do |d|
240
+ column :REF, "ref", :left, :adjust, :size=>config[:REF] || 15 do |d|
241
241
  d[:ref]
242
242
  end
243
243
 
244
- column :NAME, "Name", :left, :size=>config[:NAME] || 20 do |d|
244
+ column :NAME, "Name", :left, :expand, :size=>config[:NAME] || 20 do |d|
245
245
  d[:name] || d[:simple_name]
246
246
  end
247
247
 
@@ -250,7 +250,7 @@ class OneVcenterHelper < OpenNebulaHelper::OneHelper
250
250
  d[:one_ids] || d[:cluster].to_s
251
251
  end
252
252
 
253
- column :PATH, "PATH", :left, :size=>config[:PATH] || 10 do |d|
253
+ column :PATH, "PATH", :left, :expand, :size=>config[:PATH] || 10 do |d|
254
254
  d[:path]
255
255
  end
256
256
 
@@ -354,7 +354,7 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
354
354
 
355
355
  column :MEM, 'Memory asigned to the VM', :size => 7 do |d|
356
356
  OpenNebulaHelper.unit_to_str(d['TEMPLATE']['MEMORY'].to_i,
357
- options)
357
+ options, 'M')
358
358
  end
359
359
 
360
360
  column :HOST, 'Host where the VM is running',
@@ -402,7 +402,7 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
402
402
  table
403
403
  end
404
404
 
405
- def schedule_actions(ids, options, action)
405
+ def schedule_actions(ids, options, action, warning = nil)
406
406
  # Verbose by default
407
407
  options[:verbose] = true
408
408
 
@@ -453,18 +453,74 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
453
453
  id = ids.max + 1
454
454
  end
455
455
 
456
+ sched = options[:schedule]
457
+
458
+ # If the action is set to be executed from VM start to an specific
459
+ # amount of time later, we should preserve the + symbol
460
+ if ((sched.is_a? String) && !sched.include?('+')) ||
461
+ !(sched.is_a? String)
462
+ sched = sched.to_i
463
+ end
464
+
456
465
  tmp_str = vm.user_template_str
457
466
 
458
467
  tmp_str << "\nSCHED_ACTION = "
459
468
  tmp_str << "[ID = #{id}, ACTION = #{action}, "
469
+ tmp_str << "WARNING = #{warning}," if warning
460
470
  tmp_str << "ARGS = \"#{options[:args]}\"," if options[:args]
461
- tmp_str << "TIME = #{options[:schedule].to_i}"
471
+ tmp_str << "TIME = #{sched}"
462
472
  tmp_str << str_periodic << ']'
463
473
 
464
474
  vm.update(tmp_str)
465
475
  end
466
476
  end
467
477
 
478
+ # Update schedule action
479
+ #
480
+ # @param vm_id [Integer] Virtual Machine ID
481
+ # @param action_id [Integer] Sched action ID
482
+ # @param file [String] File path with update content
483
+ def update_schedule_action(vm_id, action_id, file)
484
+ perform_action(vm_id, {}, 'Sched action updated') do |vm|
485
+ rc = vm.info
486
+
487
+ if OpenNebula.is_error?(rc)
488
+ STDERR.puts "Error #{rc.message}"
489
+ exit(-1)
490
+ end
491
+
492
+ xpath = "USER_TEMPLATE/SCHED_ACTION[ID=#{action_id}]"
493
+
494
+ unless vm.retrieve_elements(xpath)
495
+ STDERR.puts "Sched action #{action_id} not found"
496
+ exit(-1)
497
+ end
498
+
499
+ # Get user information
500
+ if file
501
+ str = File.read(file)
502
+ else
503
+ str = OpenNebulaHelper.update_template(vm_id, vm, nil, xpath)
504
+ end
505
+
506
+ # Delete the current sched action
507
+ vm.delete_element(xpath)
508
+
509
+ # Add the modified sched action
510
+ tmp_str = vm.user_template_str
511
+ tmp_str << "\nSCHED_ACTION = ["
512
+ tmp_str << str.split("\n").join(',')
513
+ tmp_str << ']'
514
+
515
+ rc = vm.update(tmp_str)
516
+
517
+ if OpenNebula.is_error?(rc)
518
+ STDERR.puts "Error updating: #{rc.message}"
519
+ exit(-1)
520
+ end
521
+ end
522
+ end
523
+
468
524
  RECOVER_RETRY_STEPS = {
469
525
  :PROLOG_MIGRATE_FAILURE => :migrate,
470
526
  :PROLOG_MIGRATE_POWEROFF_FAILURE => :migrate,
@@ -602,6 +658,16 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
602
658
  end
603
659
  end
604
660
 
661
+ # Get charters configuration
662
+ #
663
+ # @return [Array]
664
+ # - action
665
+ # - time
666
+ # - warning
667
+ def get_charters
668
+ YAML.load_file(self.class.table_conf)[:charters]
669
+ end
670
+
605
671
  private
606
672
 
607
673
  def factory(id = nil)
@@ -1144,24 +1210,24 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
1144
1210
  CLIHelper.print_header(str_h1 % 'SCHEDULED ACTIONS', false)
1145
1211
 
1146
1212
  CLIHelper::ShowTable.new(nil, self) do
1147
- column :ID, '', :size => 2 do |d|
1213
+ column :ID, '', :adjust => true do |d|
1148
1214
  d['ID'] unless d.nil?
1149
1215
  end
1150
1216
 
1151
- column :ACTION, '', :left, :size => 15 do |d|
1217
+ column :ACTION, '', :adjust => true do |d|
1152
1218
  d['ACTION'] unless d.nil?
1153
1219
  end
1154
1220
 
1155
- column :ARGS, '', :left, :size => 15 do |d|
1221
+ column :ARGS, '', :adjust => true do |d|
1156
1222
  d['ARGS'] ? d['ARGS'] : '-'
1157
1223
  end
1158
1224
 
1159
- column :SCHEDULED, '', :size => 12 do |d|
1225
+ column :SCHEDULED, '', :adjust => true do |d|
1160
1226
  OpenNebulaHelper.time_to_str(d['TIME'], false) \
1161
1227
  unless d.nil?
1162
1228
  end
1163
1229
 
1164
- column :REPEAT, '', :size => 20 do |d|
1230
+ column :REPEAT, '', :adjust => true do |d|
1165
1231
  str_rep = ''
1166
1232
  if !d.nil? && d.key?('REPEAT')
1167
1233
  if d['REPEAT'] == '0'
@@ -1180,7 +1246,7 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
1180
1246
  str_rep unless d.nil?
1181
1247
  end
1182
1248
 
1183
- column :END, '', :size => 20 do |d|
1249
+ column :END, '', :adjust => true do |d|
1184
1250
  str_end = ''
1185
1251
  if !d.nil? && d.key?('END_TYPE')
1186
1252
  if d['END_TYPE'] == '0'
@@ -1197,25 +1263,50 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
1197
1263
  str_end unless d.nil?
1198
1264
  end
1199
1265
 
1200
- column :DONE, '', :size => 12 do |d|
1266
+ column :DONE, '', :adjust => true do |d|
1201
1267
  OpenNebulaHelper.time_to_str(d['DONE'], false) \
1202
1268
  unless d.nil?
1203
1269
  end
1204
1270
 
1205
- column :MESSAGE, '', :left, :adjust, :size => 35 do |d|
1206
- d['MESSAGE'] unless d.nil?
1271
+ column :MESSAGE, '', :size => 35 do |d|
1272
+ d['MESSAGE'] ? d['MESSAGE'] : '-'
1273
+ end
1274
+
1275
+ column :CHARTER, '', :left, :adjust, :size => 15 do |d|
1276
+ t1 = Time.now
1277
+ t2 = Time.at(vm['STIME'].to_i + d['TIME'].to_i)
1278
+
1279
+ days = ((t2 - t1) / (24 * 3600)).round(2)
1280
+ hours = ((t2 - t1) / 3600).round(2)
1281
+ minutes = ((t2 - t1) / 60).round(2)
1282
+
1283
+ if days > 1
1284
+ show = "In #{days} days"
1285
+ elsif days < 1 && hours > 1
1286
+ show = "In #{hours} hours"
1287
+ elsif minutes > 0
1288
+ show = "In #{minutes} minutes"
1289
+ else
1290
+ show = 'Already done'
1291
+ end
1292
+
1293
+ if (t1 - vm['STIME'].to_i).to_i > d['WARNING'].to_i
1294
+ "#{show} *"
1295
+ else
1296
+ show
1297
+ end
1207
1298
  end
1208
1299
  end.show([vm_hash['VM']['USER_TEMPLATE']['SCHED_ACTION']].flatten,
1209
1300
  {})
1210
1301
  end
1211
1302
 
1303
+ if !options[:all]
1304
+ vm.delete_element('/VM/USER_TEMPLATE/SCHED_ACTION')
1305
+ end
1306
+
1212
1307
  if vm.has_elements?('/VM/USER_TEMPLATE')
1213
1308
  puts
1214
1309
 
1215
- if !options[:all]
1216
- vm.delete_element('/VM/USER_TEMPLATE/SCHED_ACTION')
1217
- end
1218
-
1219
1310
  CLIHelper.print_header(str_h1 % 'USER TEMPLATE', false)
1220
1311
  puts vm.template_like_str('USER_TEMPLATE')
1221
1312
  end