opennebula-cli 3.8.0 → 3.9.0.beta
Sign up to get free protection for your applications and to get access to all the features.
- data/bin/oneacct +10 -5
- data/bin/oneacl +5 -1
- data/bin/onecluster +5 -1
- data/bin/onedatastore +5 -1
- data/bin/onegroup +40 -1
- data/bin/onehost +5 -1
- data/bin/oneimage +31 -2
- data/bin/onetemplate +24 -4
- data/bin/oneuser +43 -21
- data/bin/onevm +47 -9
- data/bin/onevnet +15 -1
- data/lib/cli_helper.rb +50 -9
- data/lib/command_parser.rb +79 -37
- data/lib/one_helper/oneacct_helper.rb +4 -4
- data/lib/one_helper/onedatastore_helper.rb +8 -2
- data/lib/one_helper/onegroup_helper.rb +41 -4
- data/lib/one_helper/onehost_helper.rb +9 -0
- data/lib/one_helper/oneimage_helper.rb +15 -10
- data/lib/one_helper/onequota_helper.rb +134 -72
- data/lib/one_helper/oneuser_helper.rb +50 -14
- data/lib/one_helper.rb +210 -16
- metadata +55 -29
data/lib/cli_helper.rb
CHANGED
@@ -31,13 +31,14 @@ module CLIHelper
|
|
31
31
|
# :description => "Order by these columns, column starting with - means decreasing order"
|
32
32
|
#}
|
33
33
|
#
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
34
|
+
FILTER = {
|
35
|
+
:name => "filter",
|
36
|
+
:short => "-f x,y,z",
|
37
|
+
:large => "--filter x,y,z",
|
38
|
+
:format => Array,
|
39
|
+
:description => "Filter data. An array is specified with\n"<<
|
40
|
+
" "*31<<"column=value pairs."
|
41
|
+
}
|
41
42
|
#
|
42
43
|
#HEADER = {
|
43
44
|
# :name => "header",
|
@@ -55,7 +56,7 @@ module CLIHelper
|
|
55
56
|
}
|
56
57
|
|
57
58
|
#OPTIONS = [LIST, ORDER, FILTER, HEADER, DELAY]
|
58
|
-
OPTIONS = [LIST, DELAY]
|
59
|
+
OPTIONS = [LIST, DELAY, FILTER]
|
59
60
|
|
60
61
|
# Sets bold font
|
61
62
|
def CLIHelper.scr_bold
|
@@ -287,7 +288,47 @@ module CLIHelper
|
|
287
288
|
}.compact.join(' ')
|
288
289
|
end
|
289
290
|
|
290
|
-
|
291
|
+
def filter_data!(data, filter)
|
292
|
+
# TBD: add more operators
|
293
|
+
# operators=/(==|=|!=|<|<=|>|>=)/
|
294
|
+
operators=/(=)/
|
295
|
+
|
296
|
+
stems=filter.map do |s|
|
297
|
+
m=s.match(/^(.*?)#{operators}(.*?)$/)
|
298
|
+
if m
|
299
|
+
left, operator, right=m[1..3]
|
300
|
+
index=@default_columns.index(left.to_sym)
|
301
|
+
|
302
|
+
if index
|
303
|
+
{
|
304
|
+
:left => left,
|
305
|
+
:operator => operator,
|
306
|
+
:right => right,
|
307
|
+
:index => index
|
308
|
+
}
|
309
|
+
else
|
310
|
+
STDERR.puts "Column '#{left}' not found"
|
311
|
+
exit(-1)
|
312
|
+
end
|
313
|
+
else
|
314
|
+
STDERR.puts "Expresion '#{s}' incorrect"
|
315
|
+
exit(-1)
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
data.reject! do |d|
|
320
|
+
pass=true
|
321
|
+
|
322
|
+
stems.each do |s|
|
323
|
+
if d[s[:index]]!=s[:right]
|
324
|
+
pass=false
|
325
|
+
break
|
326
|
+
end
|
327
|
+
end
|
328
|
+
|
329
|
+
!pass
|
330
|
+
end
|
331
|
+
end
|
291
332
|
|
292
333
|
# TBD def sort_data!
|
293
334
|
end
|
data/lib/command_parser.rb
CHANGED
@@ -65,6 +65,9 @@ module CommandParser
|
|
65
65
|
@args = args
|
66
66
|
@options = Hash.new
|
67
67
|
|
68
|
+
@before_proc=nil
|
69
|
+
@comm_name=nil
|
70
|
+
|
68
71
|
define_default_formats
|
69
72
|
|
70
73
|
instance_eval(&block)
|
@@ -97,6 +100,12 @@ module CommandParser
|
|
97
100
|
@name = str
|
98
101
|
end
|
99
102
|
|
103
|
+
# Defines a proc to be called before any command
|
104
|
+
# @param [Proc] block
|
105
|
+
def before_proc(&block)
|
106
|
+
@before_proc = block
|
107
|
+
end
|
108
|
+
|
100
109
|
# Defines a block that will be used to parse the arguments
|
101
110
|
# of the command. Formats defined using this method con be used
|
102
111
|
# in the arguments section of the command method, when defining a new
|
@@ -399,7 +408,7 @@ module CommandParser
|
|
399
408
|
comm = @main
|
400
409
|
elsif
|
401
410
|
if @args[0] && !@args[0].match(/^-/)
|
402
|
-
comm_name = @args.shift.to_sym
|
411
|
+
@comm_name = comm_name = @args.shift.to_sym
|
403
412
|
comm = @commands[comm_name]
|
404
413
|
end
|
405
414
|
end
|
@@ -413,6 +422,8 @@ module CommandParser
|
|
413
422
|
parse(extra_options)
|
414
423
|
|
415
424
|
if comm
|
425
|
+
@before_proc.call if @before_proc
|
426
|
+
|
416
427
|
check_args!(comm_name, comm[:arity], comm[:args_format])
|
417
428
|
|
418
429
|
rc = comm[:proc].call
|
@@ -428,9 +439,12 @@ module CommandParser
|
|
428
439
|
private
|
429
440
|
|
430
441
|
def parse(extra_options)
|
442
|
+
with_proc=Array.new
|
443
|
+
|
431
444
|
@cmdparse=OptionParser.new do |opts|
|
432
445
|
merge = @available_options
|
433
446
|
merge = @available_options + extra_options if extra_options
|
447
|
+
|
434
448
|
merge.flatten.each do |e|
|
435
449
|
args = []
|
436
450
|
args << e[:short] if e[:short]
|
@@ -440,16 +454,8 @@ module CommandParser
|
|
440
454
|
|
441
455
|
opts.on(*args) do |o|
|
442
456
|
if e[:proc]
|
443
|
-
|
444
|
-
|
445
|
-
if rc[0] == 0
|
446
|
-
options[e[:name].to_sym] = rc[1]
|
447
|
-
else
|
448
|
-
puts rc[1]
|
449
|
-
puts "option #{e[:name]}: Parsing error"
|
450
|
-
exit -1
|
451
|
-
end
|
452
|
-
end
|
457
|
+
@options[e[:name].to_sym]=o
|
458
|
+
with_proc<<e
|
453
459
|
elsif e[:name]=="help"
|
454
460
|
print_help
|
455
461
|
exit
|
@@ -469,6 +475,19 @@ module CommandParser
|
|
469
475
|
puts e.message
|
470
476
|
exit -1
|
471
477
|
end
|
478
|
+
|
479
|
+
with_proc.each do |e|
|
480
|
+
rc = e[:proc].call(@options[e[:name].to_sym], @options)
|
481
|
+
if rc.instance_of?(Array)
|
482
|
+
if rc[0] == 0
|
483
|
+
@options[e[:name].to_sym] = rc[1]
|
484
|
+
else
|
485
|
+
puts rc[1]
|
486
|
+
puts "option #{e[:name]}: Parsing error"
|
487
|
+
exit -1
|
488
|
+
end
|
489
|
+
end
|
490
|
+
end
|
472
491
|
end
|
473
492
|
|
474
493
|
def check_args!(name, arity, args_format)
|
@@ -479,15 +498,9 @@ module CommandParser
|
|
479
498
|
else
|
480
499
|
puts "one parameter to run"
|
481
500
|
end
|
482
|
-
puts
|
483
|
-
puts "Usage:"
|
484
501
|
|
485
|
-
|
486
|
-
|
487
|
-
else
|
488
|
-
print " #{name} "
|
489
|
-
print_command(@commands[name])
|
490
|
-
end
|
502
|
+
print_command_help(name)
|
503
|
+
|
491
504
|
exit -1
|
492
505
|
else
|
493
506
|
id=0
|
@@ -550,6 +563,14 @@ module CommandParser
|
|
550
563
|
########################################################################
|
551
564
|
|
552
565
|
def print_help
|
566
|
+
if @comm_name
|
567
|
+
print_command_help(@comm_name)
|
568
|
+
else
|
569
|
+
print_all_commands_help
|
570
|
+
end
|
571
|
+
end
|
572
|
+
|
573
|
+
def print_all_commands_help
|
553
574
|
if @usage
|
554
575
|
puts "## SYNOPSIS"
|
555
576
|
puts
|
@@ -570,37 +591,58 @@ module CommandParser
|
|
570
591
|
end
|
571
592
|
end
|
572
593
|
|
594
|
+
def print_command_help(name)
|
595
|
+
command=@commands[name]
|
596
|
+
|
597
|
+
if !command
|
598
|
+
STDERR.puts "Command '#{name}' not found"
|
599
|
+
return print_all_commands_help
|
600
|
+
end
|
601
|
+
|
602
|
+
puts "## USAGE"
|
603
|
+
print "#{name} "
|
604
|
+
print_command(@commands[name])
|
605
|
+
|
606
|
+
puts "## OPTIONS"
|
607
|
+
command[:options].flatten.each do |o|
|
608
|
+
print_option(o)
|
609
|
+
end
|
610
|
+
|
611
|
+
@available_options.each do |o|
|
612
|
+
print_option o
|
613
|
+
end
|
614
|
+
end
|
573
615
|
|
574
616
|
def print_options
|
575
617
|
puts "## OPTIONS"
|
576
618
|
|
577
619
|
shown_opts = Array.new
|
578
|
-
|
579
|
-
|
580
|
-
value[:options].flatten.each { |o|
|
620
|
+
@commands.each do |key,value|
|
621
|
+
value[:options].flatten.each do |o|
|
581
622
|
if shown_opts.include?(o[:name])
|
582
623
|
next
|
583
624
|
else
|
584
625
|
shown_opts << o[:name]
|
585
626
|
|
586
|
-
|
587
|
-
str << o[:short].split(' ').first << ', ' if o[:short]
|
588
|
-
str << o[:large]
|
589
|
-
|
590
|
-
printf opt_format, str, o[:description]
|
591
|
-
puts
|
627
|
+
print_option(o)
|
592
628
|
end
|
593
|
-
|
594
|
-
|
629
|
+
end
|
630
|
+
end
|
595
631
|
|
596
|
-
@available_options.each
|
597
|
-
|
598
|
-
|
599
|
-
|
632
|
+
@available_options.each do |o|
|
633
|
+
print_option o
|
634
|
+
end
|
635
|
+
end
|
600
636
|
|
601
|
-
|
602
|
-
|
603
|
-
|
637
|
+
def print_option(o)
|
638
|
+
opt_format = "#{' '*5}%-25s %s"
|
639
|
+
|
640
|
+
str = ""
|
641
|
+
str << o[:short].split(' ').first << ', ' if o[:short]
|
642
|
+
str << o[:large]
|
643
|
+
|
644
|
+
printf opt_format, str, o[:description]
|
645
|
+
puts
|
604
646
|
end
|
605
647
|
|
606
648
|
def print_commands
|
@@ -33,10 +33,10 @@ class AcctHelper < OpenNebulaHelper::OneHelper
|
|
33
33
|
:format => String # TODO Time
|
34
34
|
}
|
35
35
|
|
36
|
-
|
37
|
-
:name => "
|
36
|
+
USERFILTER = {
|
37
|
+
:name => "userfilter",
|
38
38
|
:short => "-u user",
|
39
|
-
:large => "--
|
39
|
+
:large => "--userfilter user" ,
|
40
40
|
:description => "User name or id to filter the results",
|
41
41
|
:format => String,
|
42
42
|
:proc => lambda { |o, options|
|
@@ -95,7 +95,7 @@ class AcctHelper < OpenNebulaHelper::OneHelper
|
|
95
95
|
:description => "Split the output in a table for each VM"
|
96
96
|
}
|
97
97
|
|
98
|
-
ACCT_OPTIONS = [START_TIME, END_TIME,
|
98
|
+
ACCT_OPTIONS = [START_TIME, END_TIME, USERFILTER, GROUP, HOST, XPATH, XML, JSON, SPLIT]
|
99
99
|
|
100
100
|
|
101
101
|
ACCT_TABLE = CLIHelper::ShowTable.new("oneacct.yaml", nil) do
|
@@ -60,7 +60,12 @@ class OneDatastoreHelper < OpenNebulaHelper::OneHelper
|
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
|
-
column :TYPE, "Datastore
|
63
|
+
column :TYPE, "Datastore type", :left, :size=>4 do |d|
|
64
|
+
type = Datastore::DATASTORE_TYPES[d["TYPE"].to_i]
|
65
|
+
Datastore::SHORT_DATASTORE_TYPES[type]
|
66
|
+
end
|
67
|
+
|
68
|
+
column :DS, "Datastore driver", :left, :size=>8 do |d|
|
64
69
|
d["DS_MAD"]
|
65
70
|
end
|
66
71
|
|
@@ -68,7 +73,7 @@ class OneDatastoreHelper < OpenNebulaHelper::OneHelper
|
|
68
73
|
d["TM_MAD"]
|
69
74
|
end
|
70
75
|
|
71
|
-
default :ID, :NAME, :CLUSTER, :IMAGES, :TYPE, :TM
|
76
|
+
default :ID, :NAME, :CLUSTER, :IMAGES, :TYPE, :DS, :TM
|
72
77
|
end
|
73
78
|
|
74
79
|
table
|
@@ -101,6 +106,7 @@ class OneDatastoreHelper < OpenNebulaHelper::OneHelper
|
|
101
106
|
puts str % ["GROUP", datastore['GNAME']]
|
102
107
|
puts str % ["CLUSTER", OpenNebulaHelper.cluster_str(datastore['CLUSTER'])]
|
103
108
|
|
109
|
+
puts str % ["TYPE", datastore.type_str]
|
104
110
|
puts str % ["DS_MAD", datastore['DS_MAD']]
|
105
111
|
puts str % ["TM_MAD", datastore['TM_MAD']]
|
106
112
|
puts str % ["BASE PATH",datastore['BASE_PATH']]
|
@@ -48,6 +48,13 @@ class OneGroupHelper < OpenNebulaHelper::OneHelper
|
|
48
48
|
def format_pool(options)
|
49
49
|
config_file = self.class.table_conf
|
50
50
|
|
51
|
+
system = System.new(@client)
|
52
|
+
default_quotas = system.get_group_quotas()
|
53
|
+
|
54
|
+
if OpenNebula::is_error?(default_quotas)
|
55
|
+
raise "Error retrieving the default group quotas: #{default_quotas.message}"
|
56
|
+
end
|
57
|
+
|
51
58
|
table = CLIHelper::ShowTable.new(config_file, self) do
|
52
59
|
column :ID, "ONE identifier for the Group", :size=>4 do |d|
|
53
60
|
d["ID"]
|
@@ -67,7 +74,14 @@ class OneGroupHelper < OpenNebulaHelper::OneHelper
|
|
67
74
|
|
68
75
|
column :VMS , "Number of VMS", :size=>9 do |d|
|
69
76
|
if d.has_key?('VM_QUOTA') and d['VM_QUOTA'].has_key?('VM')
|
70
|
-
|
77
|
+
limit = d['VM_QUOTA']['VM']["VMS"]
|
78
|
+
|
79
|
+
if limit == "-1"
|
80
|
+
limit = default_quotas['VM_QUOTA/VM/VMS']
|
81
|
+
limit = "0" if limit.nil? || limit == ""
|
82
|
+
end
|
83
|
+
|
84
|
+
"%3d / %3d" % [d['VM_QUOTA']['VM']["VMS_USED"], limit]
|
71
85
|
else
|
72
86
|
"-"
|
73
87
|
end
|
@@ -75,8 +89,16 @@ class OneGroupHelper < OpenNebulaHelper::OneHelper
|
|
75
89
|
|
76
90
|
column :MEMORY, "Total memory allocated to user VMs", :size=>17 do |d|
|
77
91
|
if d.has_key?('VM_QUOTA') and d['VM_QUOTA'].has_key?('VM')
|
92
|
+
limit = d['VM_QUOTA']['VM']["MEMORY"]
|
93
|
+
|
94
|
+
if limit == "-1"
|
95
|
+
limit = default_quotas['VM_QUOTA/VM/MEMORY']
|
96
|
+
limit = "0" if limit.nil? || limit == ""
|
97
|
+
end
|
98
|
+
|
99
|
+
d['VM_QUOTA']['VM']['MEMORY_USED']
|
78
100
|
"%7s / %7s" % [OpenNebulaHelper.unit_to_str(d['VM_QUOTA']['VM']["MEMORY_USED"].to_i,{},"M"),
|
79
|
-
OpenNebulaHelper.unit_to_str(
|
101
|
+
OpenNebulaHelper.unit_to_str(limit.to_i,{},"M")]
|
80
102
|
else
|
81
103
|
"-"
|
82
104
|
end
|
@@ -84,7 +106,14 @@ class OneGroupHelper < OpenNebulaHelper::OneHelper
|
|
84
106
|
|
85
107
|
column :CPU, "Total CPU allocated to user VMs", :size=>11 do |d|
|
86
108
|
if d.has_key?('VM_QUOTA') and d['VM_QUOTA'].has_key?('VM')
|
87
|
-
|
109
|
+
limit = d['VM_QUOTA']['VM']["CPU"]
|
110
|
+
|
111
|
+
if limit == "-1"
|
112
|
+
limit = default_quotas['VM_QUOTA/VM/CPU']
|
113
|
+
limit = "0" if limit.nil? || limit == ""
|
114
|
+
end
|
115
|
+
|
116
|
+
"%4.0f / %4.0f" % [d['VM_QUOTA']['VM']["CPU_USED"], limit]
|
88
117
|
else
|
89
118
|
"-"
|
90
119
|
end
|
@@ -113,6 +142,13 @@ class OneGroupHelper < OpenNebulaHelper::OneHelper
|
|
113
142
|
end
|
114
143
|
|
115
144
|
def format_resource(group)
|
145
|
+
system = System.new(@client)
|
146
|
+
default_quotas = system.get_group_quotas()
|
147
|
+
|
148
|
+
if OpenNebula::is_error?(default_quotas)
|
149
|
+
raise "Error retrieving the default group quotas: #{default_quotas.message}"
|
150
|
+
end
|
151
|
+
|
116
152
|
str="%-15s: %-20s"
|
117
153
|
str_h1="%-80s"
|
118
154
|
|
@@ -129,6 +165,7 @@ class OneGroupHelper < OpenNebulaHelper::OneHelper
|
|
129
165
|
|
130
166
|
group_hash = group.to_hash
|
131
167
|
|
132
|
-
OneQuotaHelper.
|
168
|
+
helper = OneQuotaHelper.new
|
169
|
+
helper.format_quota(group_hash['GROUP'], default_quotas)
|
133
170
|
end
|
134
171
|
end
|
@@ -15,6 +15,7 @@
|
|
15
15
|
#--------------------------------------------------------------------------- #
|
16
16
|
|
17
17
|
require 'one_helper'
|
18
|
+
require 'one_helper/onevm_helper'
|
18
19
|
|
19
20
|
class OneHostHelper < OpenNebulaHelper::OneHelper
|
20
21
|
def self.rname
|
@@ -192,5 +193,13 @@ class OneHostHelper < OpenNebulaHelper::OneHelper
|
|
192
193
|
CLIHelper.print_header(str_h1 % "MONITORING INFORMATION", false)
|
193
194
|
|
194
195
|
puts host.template_str
|
196
|
+
|
197
|
+
puts
|
198
|
+
CLIHelper.print_header("VIRTUAL MACHINES", false)
|
199
|
+
puts
|
200
|
+
|
201
|
+
onevm_helper=OneVMHelper.new
|
202
|
+
onevm_helper.client=@client
|
203
|
+
onevm_helper.list_pool({:filter=>["HOST=#{host.name}"]}, false)
|
195
204
|
end
|
196
205
|
end
|
@@ -34,14 +34,14 @@ class OneImageHelper < OpenNebulaHelper::OneHelper
|
|
34
34
|
:name => "type",
|
35
35
|
:large => "--type type",
|
36
36
|
:format => String,
|
37
|
-
:description => "Type of the new Image:
|
37
|
+
:description => "Type of the new Image: #{Image::IMAGE_TYPES.join(", ")}",
|
38
38
|
:proc => lambda do |o, options|
|
39
39
|
type=o.strip.upcase
|
40
40
|
|
41
|
-
if
|
41
|
+
if Image::IMAGE_TYPES.include? type
|
42
42
|
[0, type]
|
43
43
|
else
|
44
|
-
[-1, "Type should be
|
44
|
+
[-1, "Type should be: #{Image::IMAGE_TYPES.join(", ")}"]
|
45
45
|
end
|
46
46
|
end
|
47
47
|
},
|
@@ -53,7 +53,8 @@ class OneImageHelper < OpenNebulaHelper::OneHelper
|
|
53
53
|
{
|
54
54
|
:name => "prefix",
|
55
55
|
:large => "--prefix prefix",
|
56
|
-
:description => "Device prefix for the disk (eg. hd, sd, xvd
|
56
|
+
:description => "Device prefix for the disk (eg. hd, sd, xvd\n"<<
|
57
|
+
" "*31<<"or vd)",
|
57
58
|
:format => String,
|
58
59
|
:proc => lambda do |o, options|
|
59
60
|
prefix=o.strip.downcase
|
@@ -76,7 +77,9 @@ class OneImageHelper < OpenNebulaHelper::OneHelper
|
|
76
77
|
:description => "Path of the image file",
|
77
78
|
:format => String,
|
78
79
|
:proc => lambda do |o, options|
|
79
|
-
if o
|
80
|
+
if o.match(/^https?:\/\//)
|
81
|
+
next [0, o]
|
82
|
+
elsif o[0,1]=='/'
|
80
83
|
path=o
|
81
84
|
else
|
82
85
|
path=Dir.pwd+"/"+o
|
@@ -113,7 +116,8 @@ class OneImageHelper < OpenNebulaHelper::OneHelper
|
|
113
116
|
:name => "source",
|
114
117
|
:large => "--source source",
|
115
118
|
:description =>
|
116
|
-
"Source to be used. Useful for not file-based
|
119
|
+
"Source to be used. Useful for not file-based\n"<<
|
120
|
+
" "*31<<"images",
|
117
121
|
:format => String
|
118
122
|
},
|
119
123
|
{
|
@@ -147,8 +151,8 @@ class OneImageHelper < OpenNebulaHelper::OneHelper
|
|
147
151
|
{
|
148
152
|
:name => "fstype",
|
149
153
|
:large => "--fstype fstype",
|
150
|
-
:description => "Type of file system to be built. This can be "<<
|
151
|
-
|
154
|
+
:description => "Type of file system to be built. This can be \n"<<
|
155
|
+
" "*31<<"any value understood by mkfs unix command.",
|
152
156
|
:format => String,
|
153
157
|
:proc => lambda do |o, options|
|
154
158
|
if !options[:type] || !(options[:type].upcase=='DATABLOCK')
|
@@ -157,7 +161,8 @@ class OneImageHelper < OpenNebulaHelper::OneHelper
|
|
157
161
|
[0, o]
|
158
162
|
end
|
159
163
|
end
|
160
|
-
}
|
164
|
+
},
|
165
|
+
OpenNebulaHelper::DRY
|
161
166
|
]
|
162
167
|
|
163
168
|
def self.rname
|
@@ -318,7 +323,7 @@ class OneImageHelper < OpenNebulaHelper::OneHelper
|
|
318
323
|
end
|
319
324
|
|
320
325
|
template=create_image_variables(
|
321
|
-
options, template_options-[:persistent])
|
326
|
+
options, template_options-[:persistent, :dry])
|
322
327
|
|
323
328
|
template<<"PERSISTENT=YES\n" if options[:persistent]
|
324
329
|
|