opennebula-cli 6.0.1 → 6.1.90.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/bin/oneacct +13 -2
  3. data/bin/oneacl +13 -2
  4. data/bin/onecluster +13 -2
  5. data/bin/onedatastore +13 -2
  6. data/bin/oneflow +115 -11
  7. data/bin/oneflow-template +17 -7
  8. data/bin/onegroup +13 -2
  9. data/bin/onehook +17 -6
  10. data/bin/onehost +13 -2
  11. data/bin/oneimage +19 -8
  12. data/bin/onemarket +33 -2
  13. data/bin/onemarketapp +21 -10
  14. data/bin/onesecgroup +13 -2
  15. data/bin/oneshowback +13 -2
  16. data/bin/onetemplate +28 -8
  17. data/bin/oneuser +13 -2
  18. data/bin/onevcenter +29 -9
  19. data/bin/onevdc +13 -2
  20. data/bin/onevm +141 -36
  21. data/bin/onevmgroup +17 -6
  22. data/bin/onevnet +17 -6
  23. data/bin/onevntemplate +17 -6
  24. data/bin/onevrouter +17 -6
  25. data/bin/onezone +34 -3
  26. data/lib/one_helper/oneacct_helper.rb +5 -1
  27. data/lib/one_helper/onecluster_helper.rb +75 -42
  28. data/lib/one_helper/onemarket_helper.rb +12 -1
  29. data/lib/one_helper/onevcenter_helper.rb +2 -2
  30. data/lib/one_helper/onevm_helper.rb +118 -36
  31. data/lib/one_helper/onevnet_helper.rb +173 -151
  32. data/lib/one_helper/onezone_helper.rb +25 -5
  33. data/lib/one_helper.rb +119 -131
  34. data/share/schemas/xsd/api_info.xsd +2 -2
  35. data/share/schemas/xsd/hook_message_api.xsd +1 -1
  36. data/share/schemas/xsd/hook_message_state.xsd +1 -1
  37. data/share/schemas/xsd/host.xsd +21 -1
  38. data/share/schemas/xsd/marketplace.xsd +1 -0
  39. data/share/schemas/xsd/monitoring_data.xsd +23 -11
  40. data/share/schemas/xsd/opennebula_configuration.xsd +1 -0
  41. data/share/schemas/xsd/showback.xsd +1 -0
  42. data/share/schemas/xsd/vm.xsd +64 -10
  43. data/share/schemas/xsd/vm_pool.xsd +3 -26
  44. data/share/schemas/xsd/vnet.xsd +6 -1
  45. data/share/schemas/xsd/zone.xsd +1 -0
  46. data/share/schemas/xsd/zone_pool.xsd +2 -1
  47. metadata +6 -6
data/bin/onevrouter CHANGED
@@ -26,14 +26,25 @@ else
26
26
  GEMS_LOCATION = ONE_LOCATION + '/share/gems'
27
27
  end
28
28
 
29
+ # %%RUBYGEMS_SETUP_BEGIN%%
29
30
  if File.directory?(GEMS_LOCATION)
30
31
  real_gems_path = File.realpath(GEMS_LOCATION)
31
32
  if !defined?(Gem) || Gem.path != [real_gems_path]
32
33
  $LOAD_PATH.reject! {|l| l =~ /vendor_ruby/ }
33
- require 'rubygems'
34
- Gem.use_paths(real_gems_path)
34
+
35
+ # Suppress warnings from Rubygems
36
+ # https://github.com/OpenNebula/one/issues/5379
37
+ begin
38
+ verb = $VERBOSE
39
+ $VERBOSE = nil
40
+ require 'rubygems'
41
+ Gem.use_paths(real_gems_path)
42
+ ensure
43
+ $VERBOSE = verb
44
+ end
35
45
  end
36
46
  end
47
+ # %%RUBYGEMS_SETUP_END%%
37
48
 
38
49
  $LOAD_PATH << RUBY_LIB_LOCATION
39
50
  $LOAD_PATH << RUBY_LIB_LOCATION + '/cli'
@@ -364,9 +375,9 @@ CommandParser::CmdParser.new(ARGV) do
364
375
  [Admin]: locks only Admin actions.
365
376
  EOT
366
377
 
367
- command :lock, lock_desc, :vrouterid,
378
+ command :lock, lock_desc, [:range, :vrouterid_list],
368
379
  :options => [USE, MANAGE, ADMIN, ALL] do
369
- helper.perform_action(args[0], options, 'VRouter locked') do |vr|
380
+ helper.perform_actions(args[0], options, 'VRouter locked') do |vr|
370
381
  if !options[:use].nil?
371
382
  level = 1
372
383
  elsif !options[:manage].nil?
@@ -387,8 +398,8 @@ CommandParser::CmdParser.new(ARGV) do
387
398
  valid states are: All.
388
399
  EOT
389
400
 
390
- command :unlock, unlock_desc, :vrouterid do
391
- helper.perform_action(args[0], options, 'VRouter unlocked') do |vr|
401
+ command :unlock, unlock_desc, [:range, :vrouterid_list] do
402
+ helper.perform_actions(args[0], options, 'VRouter unlocked') do |vr|
392
403
  vr.unlock
393
404
  end
394
405
  end
data/bin/onezone CHANGED
@@ -26,14 +26,25 @@ else
26
26
  GEMS_LOCATION = ONE_LOCATION + '/share/gems'
27
27
  end
28
28
 
29
+ # %%RUBYGEMS_SETUP_BEGIN%%
29
30
  if File.directory?(GEMS_LOCATION)
30
31
  real_gems_path = File.realpath(GEMS_LOCATION)
31
32
  if !defined?(Gem) || Gem.path != [real_gems_path]
32
33
  $LOAD_PATH.reject! {|l| l =~ /vendor_ruby/ }
33
- require 'rubygems'
34
- Gem.use_paths(real_gems_path)
34
+
35
+ # Suppress warnings from Rubygems
36
+ # https://github.com/OpenNebula/one/issues/5379
37
+ begin
38
+ verb = $VERBOSE
39
+ $VERBOSE = nil
40
+ require 'rubygems'
41
+ Gem.use_paths(real_gems_path)
42
+ ensure
43
+ $VERBOSE = verb
44
+ end
35
45
  end
36
46
  end
47
+ # %%RUBYGEMS_SETUP_END%%
37
48
 
38
49
  $LOAD_PATH << RUBY_LIB_LOCATION
39
50
  $LOAD_PATH << RUBY_LIB_LOCATION + '/cli'
@@ -254,8 +265,28 @@ CommandParser::CmdParser.new(ARGV) do
254
265
  end
255
266
 
256
267
  server = Replicator.new('/var/lib/one/.ssh/id_rsa', args[0])
257
- server.process_files(options.key?(:database))
268
+ server.process_files(options[:db])
258
269
 
259
270
  0
260
271
  end
272
+
273
+ enable_desc = <<-EOT.unindent
274
+ Enable zone
275
+ EOT
276
+
277
+ command :enable, enable_desc, [:range, :zoneid_list] do
278
+ helper.perform_actions(args[0], options, 'enable zone') do |o|
279
+ o.enable
280
+ end
281
+ end
282
+
283
+ disable_desc = <<-EOT.unindent
284
+ Disable zone, disabled zones can execute only readonly commands
285
+ EOT
286
+
287
+ command :disable, disable_desc, [:range, :zoneid_list] do
288
+ helper.perform_actions(args[0], options, 'disable zone') do |o|
289
+ o.disable
290
+ end
291
+ end
261
292
  end
@@ -216,11 +216,15 @@ class AcctHelper < OpenNebulaHelper::OneHelper
216
216
  d["HOURS"]
217
217
  end
218
218
 
219
+ column :RUNNING_HOURS, "Running hours", :size=>7 do |d|
220
+ d["RHOURS"] || '-'
221
+ end
222
+
219
223
  column :COST, "Cost", :size=>15 do |d|
220
224
  d["TOTAL_COST"]
221
225
  end
222
226
 
223
- default :USER_NAME, :GROUP_NAME, :VM_ID, :VM_NAME, :MONTH, :YEAR, :HOURS, :COST
227
+ default :USER_NAME, :GROUP_NAME, :VM_ID, :VM_NAME, :MONTH, :YEAR, :HOURS, :RUNNING_HOURS, :COST
224
228
  end
225
229
 
226
230
  def self.print_start_end_time_header(start_time, end_time)
@@ -16,73 +16,71 @@
16
16
 
17
17
  require 'one_helper'
18
18
 
19
+ # OneCluster CLI command helper
19
20
  class OneClusterHelper < OpenNebulaHelper::OneHelper
20
21
 
21
22
  CLUSTER = {
22
- :name => "cluster",
23
- :short => "-c id|name",
24
- :large => "--cluster id|name" ,
25
- :description => "Selects the cluster",
23
+ :name => 'cluster',
24
+ :short => '-c id|name',
25
+ :large => '--cluster id|name',
26
+ :description => 'Selects the cluster',
26
27
  :format => String,
27
- :proc => lambda { |o, options|
28
- OpenNebulaHelper.rname_to_id(o, "CLUSTER")
28
+ :proc => lambda {|o, _options|
29
+ OpenNebulaHelper.rname_to_id(o, 'CLUSTER')
29
30
  }
30
31
  }
31
32
 
32
33
  def self.rname
33
- "CLUSTER"
34
+ 'CLUSTER'
34
35
  end
35
36
 
36
37
  def self.conf_file
37
- "onecluster.yaml"
38
+ 'onecluster.yaml'
38
39
  end
39
40
 
40
41
  def element_size(ehash, ename)
41
- ids = ehash[ename]["ID"]
42
+ ids = ehash[ename]['ID']
42
43
 
43
44
  if ids.nil?
44
- return 0
45
+ 0
45
46
  elsif ids.class == String
46
- return 1
47
+ 1
47
48
  else
48
- return ids.size
49
+ ids.size
49
50
  end
50
51
  end
51
52
 
52
-
53
- def format_pool(options)
53
+ def format_pool(_options)
54
54
  config_file = self.class.table_conf
55
55
 
56
- table = CLIHelper::ShowTable.new(config_file, self) do
57
- column :ID, "ONE identifier for the Cluster", :size=>5 do |d|
58
- d["ID"]
56
+ CLIHelper::ShowTable.new(config_file, self) do
57
+ column :ID, 'ONE identifier for the Cluster', :size=>5 do |d|
58
+ d['ID']
59
59
  end
60
60
 
61
- column :NAME, "Name of the Cluster", :left, :size=>25 do |d|
62
- d["NAME"]
61
+ column :NAME, 'Name of the Cluster', :left, :size=>25 do |d|
62
+ d['NAME']
63
63
  end
64
64
 
65
- column :HOSTS, "Number of Hosts", :size=>5 do |d|
66
- @ext.element_size(d,"HOSTS") rescue 0
65
+ column :HOSTS, 'Number of Hosts', :size=>5 do |d|
66
+ @ext.element_size(d, 'HOSTS') rescue 0
67
67
  end
68
68
 
69
- column :VNETS, "Number of Networks", :size=>5 do |d|
70
- @ext.element_size(d,"VNETS") rescue 0
69
+ column :VNETS, 'Number of Networks', :size=>5 do |d|
70
+ @ext.element_size(d, 'VNETS') rescue 0
71
71
  end
72
72
 
73
- column :DATASTORES, "Number of Datastores", :size=>10 do |d|
74
- @ext.element_size(d,"DATASTORES") rescue 0
73
+ column :DATASTORES, 'Number of Datastores', :size=>10 do |d|
74
+ @ext.element_size(d, 'DATASTORES') rescue 0
75
75
  end
76
76
 
77
77
  default :ID, :NAME, :HOSTS, :VNETS, :DATASTORES
78
78
  end
79
-
80
- table
81
79
  end
82
80
 
83
81
  private
84
82
 
85
- def factory(id=nil)
83
+ def factory(id = nil)
86
84
  if id
87
85
  OpenNebula::Cluster.new_with_id(id, @client)
88
86
  else
@@ -91,39 +89,74 @@ class OneClusterHelper < OpenNebulaHelper::OneHelper
91
89
  end
92
90
  end
93
91
 
94
- def factory_pool(user_flag=-2)
92
+ def factory_pool(_user_flag = -2)
95
93
  OpenNebula::ClusterPool.new(@client)
96
94
  end
97
95
 
98
- def format_resource(cluster, options = {})
99
- str="%-18s: %-20s"
100
- str_h1="%-80s"
96
+ def format_resource(cluster, _options = {})
97
+ str='%-18s: %-20s'
98
+ str_h1='%-80s'
101
99
 
102
100
  CLIHelper.print_header(str_h1 % "CLUSTER #{cluster['ID']} INFORMATION")
103
- puts str % ["ID", cluster.id.to_s]
104
- puts str % ["NAME", cluster.name]
101
+ puts format(str, 'ID', cluster.id.to_s)
102
+ puts format(str, 'NAME', cluster.name)
103
+
105
104
  puts
105
+ CLIHelper.print_header(str_h1 % 'CLUSTER RESOURCES', false)
106
+ cluster.info!
106
107
 
107
- CLIHelper.print_header(str_h1 % "CLUSTER TEMPLATE", false)
108
- puts cluster.template_str
108
+ hosts = cluster.to_hash['CLUSTER']['HOSTS']['ID']
109
+
110
+ if hosts
111
+ total_cpu = 0
112
+ used_cpu = 0
113
+ total_ram = 0
114
+ used_ram = 0
115
+
116
+ [hosts].flatten.each do |h|
117
+ h = OpenNebula::Host.new_with_id(h, @client)
118
+
119
+ h.info!
120
+
121
+ h = h.to_hash
122
+ h = h['HOST']['HOST_SHARE']
123
+
124
+ total_cpu += h['TOTAL_CPU'].to_i / 100
125
+ used_cpu += h['CPU_USAGE'].to_i / 100
126
+ total_ram += h['TOTAL_MEM'].to_i / 1024 / 1024
127
+ used_ram += h['MEM_USAGE'].to_i / 1024 / 1024
128
+ end
129
+
130
+ puts "TOTAL CPUs: #{total_cpu}"
131
+ puts "OCCUPIED CPUs: #{used_cpu}"
132
+ puts "AVAILABLE CPUs: #{total_cpu - used_cpu}"
133
+ puts
134
+ puts "TOTAL RAM: #{total_ram}"
135
+ puts "OCCUPIED RAM: #{used_ram}"
136
+ puts "AVAILABLE RAM: #{total_ram - used_ram}"
137
+ end
109
138
 
110
139
  puts
140
+ CLIHelper.print_header(str_h1 % 'CLUSTER TEMPLATE', false)
141
+ puts cluster.template_str
111
142
 
112
- CLIHelper.print_header("%-15s" % ["HOSTS"])
143
+ puts
144
+ CLIHelper.print_header(format('%-15s', 'HOSTS'))
113
145
  cluster.host_ids.each do |id|
114
- puts "%-15s" % [id]
146
+ puts format('%-15s', id)
115
147
  end
116
148
 
117
149
  puts
118
- CLIHelper.print_header("%-15s" % ["VNETS"])
150
+ CLIHelper.print_header(format('%-15s', 'VNETS'))
119
151
  cluster.vnet_ids.each do |id|
120
- puts "%-15s" % [id]
152
+ puts format('%-15s', id)
121
153
  end
122
154
 
123
155
  puts
124
- CLIHelper.print_header("%-15s" % ["DATASTORES"])
156
+ CLIHelper.print_header(format('%-15s', 'DATASTORES'))
125
157
  cluster.datastore_ids.each do |id|
126
- puts "%-15s" % [id]
158
+ puts format('%-15s', id)
127
159
  end
128
160
  end
161
+
129
162
  end
@@ -36,6 +36,12 @@ class OneMarketPlaceHelper < OpenNebulaHelper::OneHelper
36
36
  "onemarket.yaml"
37
37
  end
38
38
 
39
+ def self.state_to_str(id)
40
+ state_str = MarketPlace::MARKETPLACE_STATES[id.to_i]
41
+
42
+ MarketPlace::SHORT_MARKETPLACE_STATES[state_str]
43
+ end
44
+
39
45
  def format_pool(options)
40
46
  config_file = self.class.table_conf
41
47
 
@@ -86,7 +92,11 @@ class OneMarketPlaceHelper < OpenNebulaHelper::OneHelper
86
92
  d["ZONE_ID"]
87
93
  end
88
94
 
89
- default :ID, :NAME, :SIZE, :AVAIL, :APPS, :MAD, :ZONE
95
+ column :STAT, 'Markeplace status', :left, :size => 4 do |d|
96
+ OneMarketPlaceHelper.state_to_str(d['STATE'])
97
+ end
98
+
99
+ default :ID, :NAME, :SIZE, :AVAIL, :APPS, :MAD, :ZONE, :STAT
90
100
  end
91
101
 
92
102
  table
@@ -116,6 +126,7 @@ class OneMarketPlaceHelper < OpenNebulaHelper::OneHelper
116
126
  puts str % ["NAME", market.name]
117
127
  puts str % ["USER", market['UNAME']]
118
128
  puts str % ["GROUP", market['GNAME']]
129
+ puts str % ["STATE", market.state_str]
119
130
 
120
131
  puts str % ["MARKET_MAD", market['MARKET_MAD']]
121
132
  puts
@@ -188,14 +188,14 @@ class OneVcenterHelper < OpenNebulaHelper::OneHelper
188
188
 
189
189
  # This method will print a list for a vcenter_resource.
190
190
  #
191
- def list_object(_options, list)
191
+ def list_object(options, list)
192
192
  vcenter_host = list.keys[0]
193
193
  list = cli_format(list.values.first)
194
194
  table = format_list
195
195
 
196
196
  show_header(vcenter_host)
197
197
 
198
- table.show(list)
198
+ table.show(list, options)
199
199
  end
200
200
 
201
201
  # handles :cli section of TABLE
@@ -124,7 +124,8 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
124
124
  :name => 'weekly',
125
125
  :large => '--weekly days',
126
126
  :description => 'Repeats the schedule action the days of the week ' \
127
- 'specified, it can be a number between 0,6 separated with commas.' \
127
+ 'specified, it can be a number between 0 (Sunday) to 6 (Saturday) ' \
128
+ 'separated with commas. ' \
128
129
  'For example: onevm resume 0 --schedule "09/23 14:15" --weekly 0,2,4',
129
130
  :format => String
130
131
  }
@@ -133,8 +134,8 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
133
134
  :name => 'monthly',
134
135
  :large => '--monthly days',
135
136
  :description => 'Repeats the schedule action the days of the month ' \
136
- 'specified, it can be a number between 0,31 separated with commas.' \
137
- 'For example: onevm resume 0 --schedule "09/23 14:15" --monthly 0,14',
137
+ 'specified, it can be a number between 1,31 separated with commas. ' \
138
+ 'For example: onevm resume 0 --schedule "09/23 14:15" --monthly 1,14',
138
139
  :format => String
139
140
  }
140
141
 
@@ -142,7 +143,7 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
142
143
  :name => 'yearly',
143
144
  :large => '--yearly days',
144
145
  :description => 'Repeats the schedule action the days of the year ' \
145
- 'specified, it can be a number between 0,365 separated with commas.' \
146
+ 'specified, it can be a number between 0,365 separated with commas. ' \
146
147
  'For example: onevm resume 0 --schedule "09/23 14:15" --yearly 30,60',
147
148
  :format => String
148
149
  }
@@ -151,7 +152,7 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
151
152
  :name => 'hourly',
152
153
  :large => '--hourly hour',
153
154
  :description => 'Repeats the schedule action each hours specified,' \
154
- 'it can be a number between 0,168 separated with commas.' \
155
+ 'it can be a number between 0,168 separated with commas. ' \
155
156
  'For example: onevm resume 0 --schedule "09/23 14:15" --hourly 1,5',
156
157
  :format => Numeric
157
158
  }
@@ -439,21 +440,6 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
439
440
  str_periodic << ', END_TYPE = 0'
440
441
  end
441
442
 
442
- rc = vm.info
443
-
444
- if OpenNebula.is_error?(rc)
445
- puts rc.message
446
- exit(-1)
447
- end
448
-
449
- ids = vm.retrieve_elements('USER_TEMPLATE/SCHED_ACTION/ID')
450
-
451
- id = 0
452
- if !ids.nil? && !ids.empty?
453
- ids.map! {|e| e.to_i }
454
- id = ids.max + 1
455
- end
456
-
457
443
  sched = options[:schedule]
458
444
 
459
445
  # If the action is set to be executed from VM start to an specific
@@ -463,16 +449,14 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
463
449
  sched = sched.to_i
464
450
  end
465
451
 
466
- tmp_str = vm.user_template_str
467
-
468
- tmp_str << "\nSCHED_ACTION = "
469
- tmp_str << "[ID = #{id}, ACTION = #{action}, "
452
+ tmp_str = "SCHED_ACTION = ["
453
+ tmp_str << "ACTION = #{action}, "
470
454
  tmp_str << "WARNING = #{warning}," if warning
471
455
  tmp_str << "ARGS = \"#{options[:args]}\"," if options[:args]
472
456
  tmp_str << "TIME = #{sched}"
473
457
  tmp_str << str_periodic << ']'
474
458
 
475
- vm.update(tmp_str)
459
+ vm.sched_action_add(tmp_str)
476
460
  end
477
461
  end
478
462
 
@@ -490,7 +474,7 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
490
474
  exit(-1)
491
475
  end
492
476
 
493
- xpath = "USER_TEMPLATE/SCHED_ACTION[ID=#{action_id}]"
477
+ xpath = "TEMPLATE/SCHED_ACTION[ID=#{action_id}]"
494
478
 
495
479
  unless vm.retrieve_elements(xpath)
496
480
  STDERR.puts "Sched action #{action_id} not found"
@@ -508,12 +492,11 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
508
492
  vm.delete_element(xpath)
509
493
 
510
494
  # Add the modified sched action
511
- tmp_str = vm.user_template_str
512
- tmp_str << "\nSCHED_ACTION = ["
495
+ tmp_str = "\nSCHED_ACTION = ["
513
496
  tmp_str << str.split("\n").join(',')
514
497
  tmp_str << ']'
515
498
 
516
- rc = vm.update(tmp_str)
499
+ rc = vm.sched_action_update(action_id, tmp_str)
517
500
 
518
501
  if OpenNebula.is_error?(rc)
519
502
  STDERR.puts "Error updating: #{rc.message}"
@@ -669,6 +652,78 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
669
652
  YAML.load_file(self.class.table_conf)[:charters]
670
653
  end
671
654
 
655
+ # SSH into a VM
656
+ #
657
+ # @param args [Array] CLI arguments
658
+ # @param options [Hash] CLI parameters
659
+ def ssh(args, options)
660
+ perform_action(args[0], options, 'SSH') do |vm|
661
+ rc = vm.info
662
+
663
+ if OpenNebula.is_error?(rc)
664
+ STDERR.puts rc.message
665
+ exit(-1)
666
+ end
667
+
668
+ if vm.lcm_state_str != 'RUNNING'
669
+ STDERR.puts 'VM is not RUNNING, cannot SSH to it'
670
+ exit(-1)
671
+ end
672
+
673
+ # Get user to login
674
+ username = vm.retrieve_xmlelements('//TEMPLATE/CONTEXT/USERNAME')[0]
675
+
676
+ if !username.nil?
677
+ login = username.text
678
+ elsif !args[1].nil?
679
+ login = args[1]
680
+ else
681
+ login = 'root'
682
+ end
683
+
684
+ # Get CMD to run
685
+ options[:cmd].nil? ? cmd = '' : cmd = options[:cmd]
686
+
687
+ # Get NIC to connect
688
+ if options[:nic_id]
689
+ nic = vm.retrieve_xmlelements(
690
+ "//TEMPLATE/NIC[NIC_ID=\"#{options[:nic_id]}\"]"
691
+ )[0]
692
+ else
693
+ nic = vm.retrieve_xmlelements('//TEMPLATE/NIC[SSH="YES"]')[0]
694
+ end
695
+
696
+ nic = vm.retrieve_xmlelements('//TEMPLATE/NIC[1]')[0] if nic.nil?
697
+
698
+ if nic.nil?
699
+ STDERR.puts 'No NIC found'
700
+ exit(-1)
701
+ end
702
+
703
+ # If there is node port
704
+ if nic['EXTERNAL_PORT_RANGE']
705
+ ip = vm.to_hash['VM']['HISTORY_RECORDS']['HISTORY']
706
+ ip = [ip].flatten[-1]['HOSTNAME']
707
+ port = Integer(nic['EXTERNAL_PORT_RANGE'].split(':')[0]) + 21
708
+ else
709
+ ip = nic['IP']
710
+ port = 22
711
+ end
712
+
713
+ options[:ssh_opts].nil? ? opts = '' : opts = options[:ssh_opts]
714
+
715
+ if opts.empty?
716
+ exec(*%W[ssh #{login}@#{ip} -p #{port} #{cmd}])
717
+ else
718
+ exec('ssh', *opts.split, *%W[#{login}@#{ip} -p #{port} #{cmd}])
719
+ end
720
+ end
721
+
722
+ # rubocop:disable Style/SpecialGlobalVars
723
+ $?.exitstatus
724
+ # rubocop:enable Style/SpecialGlobalVars
725
+ end
726
+
672
727
  private
673
728
 
674
729
  def factory(id = nil)
@@ -1086,6 +1141,26 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
1086
1141
  end
1087
1142
  end
1088
1143
 
1144
+ if vm_hash['VM']['TEMPLATE']['NIC']
1145
+ nic = [vm_hash['VM']['TEMPLATE']['NIC']]
1146
+ nic = nic.flatten
1147
+ nic = nic.select {|v| !v['EXTERNAL_PORT_RANGE'].nil? }[0]
1148
+
1149
+ if nic
1150
+ ip = vm_hash['VM']['HISTORY_RECORDS']['HISTORY']
1151
+ ip = [ip].flatten[-1]['HOSTNAME']
1152
+ port = Integer(nic['EXTERNAL_PORT_RANGE'].split(':')[0]) + 21
1153
+
1154
+ puts
1155
+ CLIHelper.print_header(str_h1 % 'PORT FORWARD', false)
1156
+
1157
+ puts "[#{nic['EXTERNAL_PORT_RANGE']}]:" \
1158
+ "[#{nic['INTERNAL_PORT_RANGE'].split('/')[0]}]"
1159
+
1160
+ puts "SSH on #{ip} at port #{port}"
1161
+ end
1162
+ end
1163
+
1089
1164
  if !options[:all]
1090
1165
  while vm.has_elements?('/VM/TEMPLATE/NIC')
1091
1166
  vm.delete_element('/VM/TEMPLATE/NIC')
@@ -1207,7 +1282,7 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
1207
1282
  format_history(vm)
1208
1283
  end
1209
1284
 
1210
- if vm.has_elements?('/VM/USER_TEMPLATE/SCHED_ACTION')
1285
+ if vm.has_elements?('/VM/TEMPLATE/SCHED_ACTION')
1211
1286
  puts
1212
1287
  CLIHelper.print_header(str_h1 % 'SCHEDULED ACTIONS', false)
1213
1288
 
@@ -1225,7 +1300,10 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
1225
1300
  end
1226
1301
 
1227
1302
  column :SCHEDULED, '', :adjust => true do |d|
1228
- OpenNebulaHelper.time_to_str(d['TIME'], false) \
1303
+ t2 = d['TIME'].to_i
1304
+ t2 += vm['STIME'].to_i unless d['TIME'] =~ /^[0-9].*/
1305
+
1306
+ OpenNebulaHelper.time_to_str(t2, false) \
1229
1307
  unless d.nil?
1230
1308
  end
1231
1309
 
@@ -1276,7 +1354,10 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
1276
1354
 
1277
1355
  column :CHARTER, '', :left, :adjust, :size => 15 do |d|
1278
1356
  t1 = Time.now
1279
- t2 = Time.at(vm['STIME'].to_i + d['TIME'].to_i)
1357
+ t2 = d['TIME'].to_i
1358
+ t2 += vm['STIME'].to_i unless d['TIME'] =~ /^[0-9].*/
1359
+
1360
+ t2 = Time.at(t2)
1280
1361
 
1281
1362
  days = ((t2 - t1) / (24 * 3600)).round(2)
1282
1363
  hours = ((t2 - t1) / 3600).round(2)
@@ -1284,7 +1365,7 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
1284
1365
 
1285
1366
  if days > 1
1286
1367
  show = "In #{days} days"
1287
- elsif days < 1 && hours > 1
1368
+ elsif days <= 1 && hours > 1
1288
1369
  show = "In #{hours} hours"
1289
1370
  elsif minutes > 0
1290
1371
  show = "In #{minutes} minutes"
@@ -1292,18 +1373,19 @@ class OneVMHelper < OpenNebulaHelper::OneHelper
1292
1373
  show = 'Already done'
1293
1374
  end
1294
1375
 
1295
- if (t1 - vm['STIME'].to_i).to_i > d['WARNING'].to_i
1376
+ wrn = d['WARNING']
1377
+ if !wrn.nil? && (t1 - vm['STIME'].to_i).to_i > wrn.to_i
1296
1378
  "#{show} *"
1297
1379
  else
1298
1380
  show
1299
1381
  end
1300
1382
  end
1301
- end.show([vm_hash['VM']['USER_TEMPLATE']['SCHED_ACTION']].flatten,
1383
+ end.show([vm_hash['VM']['TEMPLATE']['SCHED_ACTION']].flatten,
1302
1384
  {})
1303
1385
  end
1304
1386
 
1305
1387
  if !options[:all]
1306
- vm.delete_element('/VM/USER_TEMPLATE/SCHED_ACTION')
1388
+ vm.delete_element('/VM/TEMPLATE/SCHED_ACTION')
1307
1389
  end
1308
1390
 
1309
1391
  if vm.has_elements?('/VM/USER_TEMPLATE')