Statistics
| Branch: | Tag: | Revision:

one / src / cli / client_utilities.rb @ ae53d437

History | View | Annotate | Download (9.08 KB)

1
# -------------------------------------------------------------------------- #
2
# Copyright 2002-2011, OpenNebula Project Leads (OpenNebula.org)             #
3
#                                                                            #
4
# Licensed under the Apache License, Version 2.0 (the "License"); you may    #
5
# not use this file except in compliance with the License. You may obtain    #
6
# a copy of the License at                                                   #
7
#                                                                            #
8
# http://www.apache.org/licenses/LICENSE-2.0                                 #
9
#                                                                            #
10
# Unless required by applicable law or agreed to in writing, software        #
11
# distributed under the License is distributed on an "AS IS" BASIS,          #
12
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
13
# See the License for the specific language governing permissions and        #
14
# limitations under the License.                                             #
15
#--------------------------------------------------------------------------- #
16

    
17
require 'OpenNebula'
18

    
19
#####################
20
# CONSOLE UTILITIES #
21
#####################
22

    
23
BinarySufix = ["K", "M", "G", "T" ]
24

    
25
def humanize_size(value)
26
    i=0
27

    
28
    while value > 1024 && i < 3 do
29
        value /= 1024.0
30
        i+=1
31
    end
32

    
33
    value = (value * 10).round / 10.0
34

    
35
    value = value.to_i if value - value.round == 0
36
    st = value.to_s + BinarySufix[i]
37

    
38
    return st
39
end
40

    
41
# Sets bold font
42
def scr_bold
43
    print "\33[1m"
44
end
45

    
46
# Sets underline
47
def scr_underline
48
    print "\33[4m"
49
end
50

    
51
# Restore normal font
52
def scr_restore
53
    print "\33[0m"
54
end
55

    
56
# Clears screen
57
def scr_cls
58
    print "\33[2J\33[H"
59
end
60

    
61
# Moves the cursor
62
def scr_move(x,y)
63
    print "\33[#{x};#{y}H"
64
end
65

    
66
# Print header
67
def print_header(format_str, str, underline)
68
    scr_bold
69
    scr_underline if underline
70
    print format_str % str
71
    scr_restore
72
    puts
73
end
74

    
75
##################################
76
# Class show configurable tables #
77
##################################
78

    
79
ShowTableExample={
80
    :id => {
81
        :name => "ID",
82
        :size => 4,
83
        :proc => lambda {|d,e| d["OID"] }
84
    },
85
    :name => {
86
        :name => "NAME",
87
        :size => 8,
88
        :proc => lambda {|d,e| d["DEPLOY_ID"] }
89
    },
90
    :stat => {
91
        :name => "STAT",
92
        :size => 4,
93
        :proc => lambda {|d,e| e[:vm].get_state(d) }
94
    },
95
    :default => [:id, :name, :stat]
96
}
97

    
98
# Class to print tables
99
class ShowTable
100
    attr_accessor :ext, :columns
101

    
102
    # table => definition of the table to print
103
    # ext => external variables (Hash), @ext
104
    def initialize(table, ext=nil)
105
        @table=table
106
        @ext=Hash.new
107
        @ext=ext if ext.kind_of?(Hash)
108
        @columns=@table[:default]
109
    end
110

    
111
    # Returns a formated string for header
112
    def header_str
113
        @columns.collect {|c|
114
            if @table[c]
115
                #{}"%#{@table[c][:size]}s" % [@table[c][:name]]
116
                format_data(c, @table[c][:name])
117
            else
118
                nil
119
            end
120
        }.compact.join(' ')
121
    end
122

    
123
    # Returns an array with header titles
124
    def header_array
125
        @columns.collect {|c|
126
            if @table[c]
127
                @table[c][:name].to_s
128
            else
129
                ""
130
            end
131
        }.compact
132
    end
133

    
134
    def data_str(data, options=nil)
135
        # TODO: Use data_array so it can be ordered and/or filtered
136
        res_data=data_array(data, options)
137

    
138
        res_data.collect {|d|
139
            (0..(@columns.length-1)).collect {|c|
140
                dat=d[c]
141
                col=@columns[c]
142

    
143
                dat = humanize_size( Float(dat) ) if( @table[col][:kbytes] )
144

    
145
                format_data(col, dat) if @table[col]
146
            }.join(' ')
147
        }.join("\n")
148

    
149
        #data.collect {|d|
150
        #    @columns.collect {|c|
151
        #        format_data(c, @table[c][:proc].call(d, @ext)) if @table[c]
152
        #    }.join(' ')
153
        #}.join("\n")
154
    end
155

    
156
    def data_array(data, options=nil)
157
        res_data=data.collect {|d|
158
            @columns.collect {|c|
159
                @table[c][:proc].call(d, @ext).to_s if @table[c]
160
            }
161
        }
162

    
163
        if options
164
            filter_data!(res_data, options[:filter]) if options[:filter]
165
            sort_data!(res_data, options[:order]) if options[:order]
166
        end
167

    
168
        res_data
169
    end
170

    
171
    def format_data(field, data)
172
        minus=( @table[field][:left] ? "-" : "" )
173
        size=@table[field][:size]
174
        "%#{minus}#{size}.#{size}s" % [ data.to_s ]
175
    end
176

    
177
    def get_order_column(column)
178
        desc=column.match(/^-/)
179
        col_name=column.gsub(/^-/, '')
180
        index=@columns.index(col_name.to_sym)
181
        [index, desc]
182
    end
183

    
184
    def sort_data!(data, order)
185
        data.sort! {|a,b|
186
            # rows are equal by default
187
            res=0
188
            order.each {|o|
189
                # compare
190
                pos, dec=get_order_column(o)
191
                break if !pos
192

    
193
                r = (b[pos]<=>a[pos])
194

    
195
                # if diferent set res (return value) and exit loop
196
                if r!=0
197
                    # change sign if the order is decreasing
198
                    r=-r if dec
199
                    res=r
200
                    break
201
                end
202
            }
203
            res
204
        }
205
    end
206

    
207
    def filter_data!(data, filters)
208
        filters.each {|key, value|
209
            pos=@columns.index(key.downcase.to_sym)
210
            if pos
211
                data.reject! {|d|
212
                    if !d[pos]
213
                        true
214
                    else
215
                        !d[pos].downcase.match(value.downcase)
216
                    end
217
                }
218
            end
219
        }
220
    end
221

    
222
    def print_help
223
        text=[]
224
        @table.each {|option, data|
225
            next if option==:default
226
            text << "%9s (%2d) => %s" % [option, data[:size], data[:desc]]
227
        }
228
        text.join("\n")
229
    end
230

    
231
end
232

    
233

    
234
################
235
# Miscelaneous #
236
################
237

    
238
def get_one_client(session=nil)
239
    OpenNebula::Client.new(session)
240
end
241

    
242
def is_error?(result)
243
    OpenNebula.is_error?(result)
244
end
245

    
246
def is_successful?(result)
247
    !OpenNebula.is_error?(result)
248
end
249

    
250
def check_parameters(name, number)
251
    if ARGV.length < number
252
        print "Command #{name} requires "
253
        if number>1
254
            puts "#{number} parameters to run."
255
        else
256
            puts "one parameter to run"
257
        end
258
        exit -1
259
    end
260
end
261

    
262

    
263

    
264
def get_entity_id(name, pool_class)
265
    return name if name.match(/^[0123456789]+$/)
266

    
267
    # TODO: get vm's from the actual user
268
    pool=pool_class.new(get_one_client)
269
    result=pool.info
270

    
271
    class_name=pool_class.name.split('::').last.gsub(/Pool$/, '')
272

    
273
    if( OpenNebula.is_error?(result) )
274
        puts "Error: #{class_name} Pool info could not be retrieved. " +
275
            result.message
276
        exit -1
277
    end
278

    
279
    objects=pool.select {|object| object.name==name }
280

    
281
    if objects.length>0
282
        if objects.length>1
283
            puts "There are multiple #{class_name}s with name #{name}."
284
            exit -1
285
        else
286
            result=objects.first.id
287
        end
288
    else
289
        puts "#{class_name} named #{name} not found."
290
        exit -1
291
    end
292

    
293
    result
294
end
295

    
296
def get_vm_id(name)
297
    get_entity_id(name, OpenNebula::VirtualMachinePool)
298
end
299

    
300
def get_host_id(name)
301
    get_entity_id(name, OpenNebula::HostPool)
302
end
303

    
304
def get_vn_id(name)
305
    get_entity_id(name, OpenNebula::VirtualNetworkPool)
306
end
307

    
308
def get_user_id(name)
309
    get_entity_id(name, OpenNebula::UserPool)
310
end
311

    
312
def get_image_id(name)
313
    get_entity_id(name, OpenNebula::ImagePool)
314
end
315

    
316
def get_cluster_id(name)
317
    get_entity_id(name, OpenNebula::ClusterPool)
318
end
319

    
320
def get_template_id(name)
321
    get_entity_id(name, OpenNebula::TemplatePool)
322
end
323

    
324
def get_group_id(name)
325
    get_entity_id(name, OpenNebula::GroupPool)
326
end
327

    
328
def str_running_time(data)
329
    stime=Time.at(data["STIME"].to_i)
330
    if data["ETIME"]=="0"
331
        etime=Time.now
332
    else
333
        etime=Time.at(data["ETIME"].to_i)
334
    end
335
    dtime=Time.at(etime-stime).getgm
336

    
337
    "%02d %02d:%02d:%02d" % [dtime.yday-1, dtime.hour, dtime.min, dtime.sec]
338
end
339

    
340
def str_register_time(data)
341
    regtime=Time.at(data["REGTIME"].to_i).getgm
342
    regtime.strftime("%b %d, %Y %H:%M")
343
end
344

    
345

    
346
REG_RANGE=/(.*)\[(\d+)([+-])(\d+)\](.*)/
347

    
348
def expand_range(param)
349
    if match=param.match(REG_RANGE)
350
        pre=match[1]
351
        start=match[2]
352
        operator=match[3]
353
        last=match[4]
354
        post=match[5]
355
        size=0
356

    
357
        result=Array.new
358

    
359
        if operator=='-'
360
            range=(start.to_i..last.to_i)
361
            size=last.size
362
        elsif operator=='+'
363
            size=(start.to_i+last.to_i-1).to_s.size
364
            range=(start.to_i..(start.to_i+last.to_i-1))
365
        end
366

    
367
        if start[0]==?0
368
            range.each do |num|
369
                result<<sprintf("%s%0#{size}d%s", pre, num, post)
370
            end
371
        else
372
            range.each do |num|
373
                result<<sprintf("%s%d%s", pre, num, post)
374
            end
375
        end
376

    
377
        result
378
    else
379
        param
380
    end
381
end
382

    
383
def expand_args(args)
384
    args.collect {|arg| expand_range(arg) }.flatten
385
end