Class: OneVcenterHelper

Inherits:
OpenNebulaHelper::OneHelper show all
Defined in:
lib/one_helper/onevcenter_helper.rb

Overview

Module OneVcenterHelper

Defined Under Namespace

Modules: VOBJECT

Constant Summary collapse

TABLE =

onevcenter helper main constant This will control everything displayed on STDOUT Resources (above) uses this table

struct: [Array] LIST FORMAT for opennebula cli

related methods: * cli_format

columns: [Hash(column => Integer)] Will be used in the list command,

Integer represent nbytes
related methods: * format_list

cli: [Array] with mandatory args, for example image

listing needs a datastore
related methods: * parse_opts

dialogue: [Lambda] Used only for Vobject that require a previous

         dialogue with the user, will be triggered
         on importation process
related methods: * network_dialogue
                 * template_dialogue
{
    VOBJECT::DATASTORE => {
        :struct  => %w[DATASTORE_LIST DATASTORE],
        :columns =>
            { :IMID => 5, :REF => 15, :NAME => 50, :CLUSTERS => 10 },
        :cli     => [:host],
        :dialogue => ->(arg) {}
    },
    VOBJECT::TEMPLATE => {
        :struct  => %w[TEMPLATE_LIST TEMPLATE],
        :columns => { :IMID => 5, :REF => 10, :NAME => 50 },
        :cli     => [:host],
        :dialogue => ->(arg) { OneVcenterHelper.template_dialogue(arg) }
    },
    VOBJECT::NETWORK => {
        :struct  => %w[NETWORK_LIST NETWORK],
        :columns => {
            :IMID => 5,
            :REF => 15,
            :NAME => 30,
            :CLUSTERS => 20
        },
        :cli     => [:host],
        :dialogue => ->(arg) { OneVcenterHelper.network_dialogue(arg) }
    },
    VOBJECT::IMAGE => {
        :struct  => %w[IMAGE_LIST IMAGE],
        :columns => { :IMID => 5, :REF => 35, :PATH => 60 },
        :cli     => [:host, :datastore],
        :dialogue => ->(arg) {}
    },
    VOBJECT::HOST => {
        :struct  => %w[HOST_LIST HOST],
        :columns => { :DATACENTER => 10, :NAME => 30, :REF => 35 },
        :cli     => [],
        :dialogue => ->(arg) {}
    }
}

Instance Attribute Summary

Attributes inherited from OpenNebulaHelper::OneHelper

#client

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from OpenNebulaHelper::OneHelper

#check_orphan, client, #create_resource, #filterflag_to_i, filterflag_to_i_desc, get_client, get_password, #group_name, #initialize, #list_pool, #list_pool_format, #list_pool_table, #list_pool_top, #list_pool_xml, #list_to_id, list_to_id_desc, name_to_id, #perform_action, #perform_actions, #print_page, #retrieve_resource, #set_client, set_endpoint, set_password, set_user, #show_resource, #start_pager, #stop_pager, table_conf, #to_id, to_id_desc, #user_name

Constructor Details

This class inherits a constructor from OpenNebulaHelper::OneHelper

Class Method Details

.network_dialogue(n) ⇒ Object



452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
# File 'lib/one_helper/onevcenter_helper.rb', line 452

def self.network_dialogue(n)
    ask = lambda {|question, default = ''|
        STDOUT.print question
        answer = STDIN.gets.strip

        answer = default if answer.empty?

        return answer
    }

    STDOUT.print "\n- Network: \e[92m#{n[:name]}\e[39m\n\n"\

    opts = { :size => '255', :type => 'ether' }

    question =  '    How many VMs are you planning'\
                ' to fit into this network [255]? '
    opts[:size] = ask.call(question, '255')

    question = '    What type of Virtual Network'\
               ' do you want to create (IPv[4],IPv[6], [E]thernet)? '
    type_answer = ask.call(question, 'ether')

    supported_types = %w[4 6 ether e ip4 ip6]
    if !supported_types.include?(type_answer)
        type_answer = 'e'
        STDOUT.puts "    Type [#{type_answer}] not supported,"\
                    ' defaulting to Ethernet.'
    end
    question_ip =
        '    Please input the first IP in the range: '
    question_mac =
        '    Please input the first MAC in the range [Enter for default]: '

    case type_answer.downcase
    when '4', 'ip4'
        opts[:ip]  = ask.call(question_ip)
        opts[:mac] = ask.call(question_mac)
        opts[:type] = 'ip'
    when '6', 'ip6'
        opts[:mac] = ask.call(question_mac)

        question =   '    Do you want to use SLAAC '\
                     'Stateless Address Autoconfiguration? ([y]/n): '
        slaac_answer = ask.call(question, 'y').downcase

        if slaac_answer == 'n'
            question =
                '    Please input the IPv6 address (cannot be empty): '
            opts[:ip6] = ask.call(question)

            question =
                '    Please input the Prefix length (cannot be empty): '
            opts[:prefix_length] = ask.call(question)
            opts[:type] = 'ip6_static'
        else
            question = '    Please input the GLOBAL PREFIX '\
                        '[Enter for default]: '
            opts[:global_prefix] = ask.call(question)

            question= '    Please input the ULA PREFIX '\
                       '[Enter for default]: '
            opts[:ula_prefix] = ask.call(question)
            opts[:type] = 'ip6'
        end
    when 'e', 'ether'
        opts[:mac] = ask.call(question_mac)
    end

    opts
end

.template_dialogue(t) ⇒ Object

CLI DIALOGUES



349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
# File 'lib/one_helper/onevcenter_helper.rb', line 349

def self.template_dialogue(t)
    rps_list = lambda {
        return '' if t[:rp_list].empty?

        puts
        t[:rp_list].each do |rp|
            puts "      #{rp[:name]}"
        end
        puts

        return STDIN.gets.strip.downcase
    }

    # default opts
    opts = {
        :linked_clone => '0',
        :copy => '0',
        :name => '',
        :folder => '',
        :resourcepool => [],
        :type => ''
    }

    STDOUT.print "\n- Template: \e[92m#{t[:template_name]}\e[39m\n\n"\

    # LINKED CLONE OPTION
    STDOUT.print "\n    For faster deployment operations"\
                 ' and lower disk usage, OpenNebula'\
                 ' can create new VMs as linked clones.'\
                 "\n    Would you like to use Linked Clones"\
                 ' with VMs based on this template (y/[n])? '

    if STDIN.gets.strip.downcase == 'y'
        opts[:linked_clone] = '1'

        # CREATE COPY OPTION
        STDOUT.print "\n    Linked clones requires that delta"\
                     ' disks must be created for '\
                     'each disk in the template.'\
                     ' This operation may change the template contents.'\
                     " \n    Do you want OpenNebula to "\
                     'create a copy of the template,'\
                     ' so the original template remains untouched ([y]/n)? '

        if STDIN.gets.strip.downcase != 'n'
            opts[:copy] = '1'

            # NAME OPTION
            STDOUT.print "\n    The new template will be named"\
                         ' adding a one- prefix to the name'\
                         " of the original template. \n"\
                         '    If you prefer a different name'\
                         ' please specify or press Enter'\
                         ' to use defaults: '

            template_name = STDIN.gets.strip.downcase
            opts[:name] = template_name

            STDOUT.print "\n    WARNING!!! The cloning "\
                         'operation can take some time'\
                         " depending on the size of disks.\n"
        end
    end

    sdtout_print = "\n\n    Do you want to specify a folder where"\
    ' the deployed VMs based on this template will appear'\
    " in vSphere's VM and Templates section?"\
    "\n    If no path is set, VMs will be placed in the same"\
    ' location where the template lives.'\
    "\n    Please specify a path using slashes to separate folders"\
    ' e.g /Management/VMs or press Enter to use defaults: '\

    STDOUT.print sdtout_print

    vcenter_vm_folder = STDIN.gets.strip
    opts[:folder] = vcenter_vm_folder

    STDOUT.print "\n\n    This template is currently set to "\
        'launch VMs in the default resource pool.'\
        "\n    Press y to keep this behaviour, n to select"\
        ' a new resource pool or d to delegate the choice'\
        ' to the user ([y]/n/d)? '

    answer = STDIN.gets.strip.downcase

    case answer.downcase
    when 'd' || 'delegate'
        opts[:type]='list'
        puts "separate with commas ',' the list that you want to deleate:"

        opts[:resourcepool] = rps_list.call.gsub(/\s+/, '').split(',')

    when 'n' || 'no'
        opts[:type]='fixed'
        puts 'choose the proper name'
        opts[:resourcepool] = rps_list.call
    else
        opts[:type]='default'
    end

    opts
end

Instance Method Details

#cli_dialogue(object_info) ⇒ Object

handles :cli section of TABLE used for executing the dialogue in some VOBJECTS



265
266
267
# File 'lib/one_helper/onevcenter_helper.rb', line 265

def cli_dialogue(object_info)
    TABLE[@vobject][:dialogue].call(object_info)
end

#cli_format(hash) ⇒ Object



189
190
191
192
193
194
195
196
197
# File 'lib/one_helper/onevcenter_helper.rb', line 189

def cli_format(hash)
    {
        TABLE[@vobject][:struct].first =>
            {
                TABLE[@vobject][:struct].last =>
                    hash.values
            }
    }
end

#connection_options(object_name, options) ⇒ Object

Handles connection to vCenter.



172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
# File 'lib/one_helper/onevcenter_helper.rb', line 172

def connection_options(object_name, options)
    if  options[:vuser].nil? || options[:vcenter].nil?
        raise 'vCenter connection parameters are mandatory to import'\
              " #{object_name}:\n"\
              "\t --vcenter vCenter hostname\n"\
              "\t --vuser username to login in vcenter"
    end

    password = options[:vpass] || OpenNebulaHelper::OneHelper.get_password
    {
        :user     => options[:vuser],
        :password => password,
        :host     => options[:vcenter],
        :port     => options[:port]
    }
end

#datastore(arg) ⇒ Object

these methods will be used by table :cli property the purpose is to inject code when -d option in this case is used



108
109
110
111
112
113
114
115
# File 'lib/one_helper/onevcenter_helper.rb', line 108

def datastore(arg)
    ds = VCenterDriver::VIHelper.one_item(OpenNebula::Datastore, arg)

    {
        :ds_ref => ds['TEMPLATE/VCENTER_DS_REF'],
        :one_item => ds
    }
end

#format_listObject

Use the attributes provided by TABLE with the purpose of build a complete CLI list OpenNebula way



309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
# File 'lib/one_helper/onevcenter_helper.rb', line 309

def format_list
    config = TABLE[@vobject][:columns]
    CLIHelper::ShowTable.new do
        column :DATACENTER,
               'Object datacenter',
               :size => config[:DATACENTER] || 15 do |d|
            d[:datacenter]
        end

        column :IMID, 'identifier for ...', :size=>config[:IMID] || 4 do |d|
            d[:import_id]
        end

        column :REF, 'ref', :left, :adjust, :size=>config[:REF] || 15 do |d|
            d[:ref] || d[:cluster_ref]
        end

        column :NAME, 'Name', :left, :expand,
               :size=>config[:NAME] || 20 do |d|
            d[:name] || d[:simple_name]
        end

        column :CLUSTERS, 'CLUSTERS', :left,
               :size=>config[:CLUSTERS] || 10 do |d|
            d = d[:clusters] if d[:clusters]
            d[:one_ids] || d[:cluster].to_s
        end

        column :PATH, 'PATH', :left, :expand,
               :size=>config[:PATH] || 10 do |d|
            d[:path]
        end

        default(*config.keys)
    end
end

#host(arg) ⇒ Object



117
118
119
# File 'lib/one_helper/onevcenter_helper.rb', line 117

def host(arg)
    arg
end

#list(options, args) ⇒ Object

General method to list vCenter objects



203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
# File 'lib/one_helper/onevcenter_helper.rb', line 203

def list(options, args)
    if !options[:host]
        # This case is to list available hosts, instead other object
        list_hosts(options)
    else
        vi_client = VCenterDriver::VIClient.new_from_host(
            options[:host]
        )
        importer = VCenterDriver::VcImporter.new_child(
            @client,
            vi_client,
            options[:object]
        )

        list_object(options, importer.retrieve_resources(args))
    end
end

#list_hosts(options) ⇒ Object

List unimported hosts



236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
# File 'lib/one_helper/onevcenter_helper.rb', line 236

def list_hosts(options)
    con_ops   = connection_options('hosts', options)
    vi_client = VCenterDriver::VIClient.new(con_ops)
    dc_folder = VCenterDriver::DatacenterFolder.new(vi_client)
    hpool     = VCenterDriver::VIHelper.one_pool(OpenNebula::HostPool,
                                                 false)

    VCenterDriver::VIHelper.set_client(nil, @client)

    list  = []
    hosts = dc_folder.get_unimported_hosts(hpool, vi_client.vim.host)

    hosts.each do |key, value|
        value.each do |v|
            v[:datacenter] = key
            list << v
        end
    end

    format_list.show(hosts, options)
end

#list_object(options, list) ⇒ Object

This method will print a list for a vcenter_resource.



223
224
225
226
227
228
229
230
231
# File 'lib/one_helper/onevcenter_helper.rb', line 223

def list_object(options, list)
    vcenter_host = list.keys[0]
    list = cli_format(list.values.first)
    table = format_list

    show_header(vcenter_host)

    table.show(list, options)
end

#object_update(type) ⇒ Object

Using for parse a String into a VOBJECT We will use VOBJECT instances for handle any operatiion



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/one_helper/onevcenter_helper.rb', line 140

def object_update(type)
    raise 'you need to use -o option!' unless type

    type = type.downcase
    case type
    when 'datastores'
        @vobject = VOBJECT::DATASTORE
    when 'templates'
        @vobject = VOBJECT::TEMPLATE
    when 'networks'
        @vobject = VOBJECT::NETWORK
    when 'images'
        @vobject = VOBJECT::IMAGE
    when 'hosts'
        @vobject = VOBJECT::HOST
    else
        puts "unknown #{type} type option"
        puts '  -o options:'
        puts '      datastores'
        puts '      templates'
        puts '      networks'
        puts '      images'
        puts '      hosts'

        exit 0
    end
end

#parse_file(path) ⇒ Object

This method will parse a yaml Only used for a feature that adds the posibility of import resources with custom params (bulk)



295
296
297
298
299
300
301
302
303
# File 'lib/one_helper/onevcenter_helper.rb', line 295

def parse_file(path)
    begin
        _config = YAML.safe_load(File.read(path))
    rescue StandardError => _e
        str_error="Unable to read '#{path}'. Invalid YAML syntax:\n"

        raise str_error
    end
end

#parse_opts(opts) ⇒ Object

This method iterates over the possible options for certain resources and will raise an error in case of missing mandatory param



274
275
276
277
278
279
280
281
282
283
284
285
286
287
# File 'lib/one_helper/onevcenter_helper.rb', line 274

def parse_opts(opts)
    object_update(opts[:object])

    res = {}
    TABLE[@vobject][:cli].each do |arg|
        raise "#{arg} it's mandadory for this op" if opts[arg].nil?

        res[arg] = method(arg).call(opts[arg])
    end

    res[:config] = parse_file(opts[:configuration]) if opts[:configuration]

    res
end

#show_header(vcenter_host) ⇒ Object

In list command you can use this method to print a header



127
128
129
130
131
132
133
# File 'lib/one_helper/onevcenter_helper.rb', line 127

def show_header(vcenter_host)
    CLIHelper.scr_bold
    CLIHelper.scr_underline
    puts "# vCenter: #{vcenter_host}".ljust(50)
    CLIHelper.scr_restore
    puts
end