class VCenterDriver::VcImporter

Class VcImporter

Constants

MESS

ABSTRACT INTERFACE

This Interface should be implemented by the specific importer.

Attributes

list[RW]

Public Class Methods

import_clusters(con_ops, options) click to toggle source
# File lib/vcenter_importer.rb, line 240
def self.import_clusters(con_ops, options)
    begin
        STDOUT.print "\nConnecting to vCenter: #{options[:vcenter]}..."

        use_defaults = options.key?(:defaults)

        vi_client = VCenterDriver::VIClient.new(con_ops)

        STDOUT.print "done!\n\n"

        STDOUT.print 'Exploring vCenter resources...'

        dc_folder = VCenterDriver::DatacenterFolder.new(vi_client)

        vcenter_instance_name = vi_client.vim.host

        # OpenNebula's ClusterPool
        cpool = VCenterDriver::VIHelper
                .one_pool(OpenNebula::ClusterPool, false)
        if cpool.respond_to?(:message)
            raise "Could not get OpenNebula ClusterPool: \
                  #{cpool.message}"
        end

        cluster_list = {}
        cpool.each do |c|
            name = VCenterDriver::VcImporter.sanitize(
                c['NAME']
            )
            cluster_list[c['ID']] = name if c['ID'].to_i != 0
        end

        # Get OpenNebula's host pool
        hpool = VCenterDriver::VIHelper
                .one_pool(OpenNebula::HostPool, false)
        if hpool.respond_to?(:message)
            raise "Could not get OpenNebula HostPool: #{hpool.message}"
        end

        rs = dc_folder.get_unimported_hosts(hpool,
                                            vcenter_instance_name)

        # Select just cluster with this reference
        if options[:cluster_ref]
            rs.each do |_, clusters|
                clusters.select! do |c|
                    c[:cluster_ref] == options[:cluster_ref]
                end
            end
        end

        STDOUT.print "done!\n\n"

        rs.each do |dc, clusters|
            if !use_defaults
                # rubocop:disable Layout/LineLength
                STDOUT.print "Do you want to process datacenter #{dc} (y/[n])? "
                # rubocop:enable Layout/LineLength
                next if STDIN.gets.strip.downcase != 'y'
            end

            if clusters.empty?
                STDOUT.puts "\n    No new clusters found in #{dc}..."
                next
            end

            clusters.each do |cluster|
                one_cluster_id = nil
                rpool = nil

                # Handle OpenNebula cluster creation or reuse
                if !use_defaults
                    # rubocop:disable Layout/LineLength
                    STDOUT.print "\n  * vCenter cluster found:\n"\
                                 "      - Name       : \e[92m#{cluster[:simple_name]}\e[39m\n"\
                                 "      - Location   : #{cluster[:cluster_location]}\n"\
                                 '    Import cluster (y/[n])? '
                    # rubocop:enable Layout/LineLength
                    next if STDIN.gets.strip.downcase != 'y'

                    if !cluster_list.empty?
                        # rubocop:disable Layout/LineLength
                        STDOUT.print "\n    In which OpenNebula cluster do you want the vCenter cluster to be included?\n "
                        # rubocop:enable Layout/LineLength

                        cluster_list_str = "\n"
                        cluster_list.each do |key, value|
                            name = VCenterDriver::VcImporter.sanitize(
                                value
                            )
                            cluster_list_str << "      - \e[94mID: " \
                                             << key \
                                             << "\e[39m - NAME: " \
                                             << name << "\n"
                        end

                        STDOUT.print "\n    #{cluster_list_str}"
                        # rubocop:disable Layout/LineLength
                        STDOUT.print "\n    Specify the ID of the cluster or press Enter if you want OpenNebula to create a new cluster for you: "
                        # rubocop:enable Layout/LineLength
                        answer = STDIN.gets.strip

                        if !answer.empty?
                            one_cluster_id = answer
                        end
                    end
                end

                cluster_name = VCenterDriver::VcImporter.sanitize(
                    cluster[:cluster_name]
                )

                # Check if the OpenNebula Cluster exists, and reuse it
                one_cluster_id ||= cluster_list
                                   .key(cluster_name)

                if !one_cluster_id
                    one_cluster = VCenterDriver::VIHelper
                                  .new_one_item(OpenNebula::Cluster)
                    rc = one_cluster
                         .allocate(cluster_name.to_s)
                    if ::OpenNebula.is_error?(rc)
                        # rubocop:disable Layout/LineLength
                        STDOUT.puts "    Error creating OpenNebula cluster: #{rc.message}\n"
                        # rubocop:enable Layout/LineLength
                        next
                    end
                    one_cluster_id = one_cluster.id
                end

                # Generate host template and allocate new host
                one_host = VCenterDriver::ClusterComputeResource
                           .to_one(cluster,
                                   con_ops,
                                   rpool,
                                   one_cluster_id)
                # rubocop:disable Layout/LineLength
                STDOUT.puts "\n    OpenNebula host \e[92m#{cluster_name}\e[39m with"\
                            " ID \e[94m#{one_host.id}\e[39m successfully created."
                STDOUT.puts
                # rubocop:enable Layout/LineLength
            end
        end
    rescue Interrupt
        puts "\n"
        exit 0 # Ctrl+C
    rescue StandardError => e
        error_msg = "\nError: #{e.message}\n"
        error_msg << "#{e.backtrace}\n" \
                      if VCenterDriver::CONFIG[:debug_information]
        STDERR.puts error_msg
        raise_error = true
    ensure
        vi_client.close_connection if vi_client
        raise if raise_error
    end
end
new(one_client, vi_client) click to toggle source

Builds a vCenter importer

@param one_client [OpenNebula::Client] OpenNebula ruby Client @param vi_client [VCenterDriver::VIClient] vCenter driver Client

# File lib/vcenter_importer.rb, line 58
def initialize(one_client, vi_client)
    @vi_client  = vi_client
    @one_client = one_client

    @list = {}

    @info = {}
    @info[:clusters] = {}
    @info[:success] = []
    @info[:error]   = []
end
new_child(one_client, vi_client, type) click to toggle source

Allow us to spawn a specific importer child

@param one_client [OpenNebula::Client] OpenNebula ruby Client @param vi_client [VCenterDriver::VIClient] vCenter driver Client @param type [String] to choose the specific child

@return [VCImporter] the vCenter importer that will handle

any operation
# File lib/vcenter_importer.rb, line 80
def self.new_child(one_client, vi_client, type)
    case type.downcase
    when 'hosts'
        VCenterDriver::VcImporter.new(one_client, vi_client)
    when 'datastores'
        VCenterDriver::DsImporter.new(one_client, vi_client)
    when 'templates'
        VCenterDriver::VmImporter.new(one_client, vi_client)
    when 'networks'
        VCenterDriver::NetImporter.new(one_client, vi_client)
    when 'images'
        VCenterDriver::ImageImporter.new(one_client, vi_client)
    else
        raise 'unknown object type'
    end
end
sanitize(text) click to toggle source
# File lib/vcenter_importer.rb, line 398
def self.sanitize(text)
    bad_chars = ['|']
    bad_chars.each do |bad_char|
        text.gsub!(bad_char, '_')
    end
    text
end

Public Instance Methods

get_indexes(args = nil) click to toggle source

Parse arguments usually given by command line interface with the purpose of retrieve a list of selected indexes by the users.

@param args [nil | Array | String] range, names or nil

@ return [Aarray] the list of selected indexes

# File lib/vcenter_importer.rb, line 144
def get_indexes(args = nil)
    raise 'the list is empty' if list_empty?

    list = @list.values[0]
    indexes = ''
    keys = list.keys

    return keys.join(',') unless args

    if args.include?('..')
        range = Range.new(*args.split('..').map(&:to_i))

        if range.first != range.last
            range.each do |i|
                indexes << "#{keys[i]}, "
            end

            return indexes
        end
    end

    if args !~ /\D/
        ind = args.to_i

        return keys[ind]
    end

    args
end
one_str() click to toggle source

@return [String] the object type of the importer

# File lib/vcenter_importer.rb, line 100
def one_str
    return @one_class.to_s.split('::').last if @one_class

    'OpenNebula object'
end
output() click to toggle source

Importer return value

@ return [Hash{:sucess =>[[]] , :error => {}}

# File lib/vcenter_importer.rb, line 131
def output
    { :success => @info[:success], :error => @info[:error] }
end
process_import(indexes, opts = {}, &block) click to toggle source

This method handles all the importation. Will be in charge of call the specific import operation of the specific importer.

@param indexes [Array] Array with all the indexes that points to the selected object of the list. @param opts [Hash] Hash with the options. In sunstone context this options will contain every index associated to his own resource opt

Example: {“vm-343” => {:linked_clone: '0', :copy: '0'…}

@ return [Hash] the list of unimported resources

# File lib/vcenter_importer.rb, line 209
def process_import(indexes, opts = {}, &block)
    raise 'the list is empty' if list_empty?

    indexes = indexes.gsub(/\s*\,\s*/, ',').strip.split(',')

    indexes.each do |index|
        begin
            @rollback = []
            @info[index] = {}

            selected = get_element(index)

            if block_given?
                @info[index][:opts] = block.call(selected)
            elsif opts[index]
                @info[index][:opts] = opts[index]
            else
                @info[index][:opts] = defaults
            end

            # import the object
            @info[:success] << import(selected)
        rescue StandardError => e
            @info[:error] << { index => e.message }
            @info[index][:e] = e

            apply_rollback
        end
    end
end
retrieve_resources(opts = {}) click to toggle source

Wrapper of #get_list, needed for clean the cache #get_list populates @ref_hash cache at vCenter driver level, with this function you still can reuse the importer.

@param opts [Hash] Hash with the needed arguments

@ return [Hash] the list of unimported resources

# File lib/vcenter_importer.rb, line 183
def retrieve_resources(opts = {})
    VCenterDriver::VIHelper.clean_ref_hash

    list = get_list(opts)

    @defaults = opts[:config] if opts[:config]

    list
end
stdout() click to toggle source

Prints feedback of the realized import operations throught STDOUT

# File lib/vcenter_importer.rb, line 110
def stdout
    @info[:success].each do |o|
        o[:id].each do |id|
            puts "ID: #{id}"
        end
    end

    puts

    @info[:error].each do |error|
        index = error.first[0]
        e = @info[index][:e]
        puts "Error: Couldn't import #{index} due to #{e.message}!"
        puts
    end
end

Protected Instance Methods

add_cluster(_cid, _eid) click to toggle source

Add certain resource to OpenNebula Cluster.

@param cid [Int] opennebula cluster id @param eid [Int] the id of the imported opennebula resource

# File lib/vcenter_importer.rb, line 482
def add_cluster(_cid, _eid)
    raise MESS
end
add_clusters(one_id, clusters) click to toggle source

Add the imported resources to n OpenNebula Clusters. And remove the default one(0).

@param one_id [Int] The id of the imported OpenNebula object. @param clusters [Array] Array with all the ids of the desired OpenNebula clusters.

# File lib/vcenter_importer.rb, line 560
def add_clusters(one_id, clusters)
    clusters.each do |cid|
        next if cid < 0

        @info[:clusters][cid] ||= VCenterDriver::VIHelper
                                  .one_item(OpenNebula::Cluster,
                                            cid.to_s,
                                            false)
        rc = add_cluster(cid, one_id.to_i)
        VCenterDriver::VIHelper
            .check_error(rc, 'add element to cluster')
    end
    remove_default(one_id)
end
apply_rollback() click to toggle source

Call this function to use the rollback Stack, and delete every corrupted object created by the importer.

# File lib/vcenter_importer.rb, line 579
def apply_rollback
    return if @rollback.empty?

    @rollback.each do |action|
        action.apply
    end
end
create(info, &block) click to toggle source

Create and allocate a OpenNebula Object.

@param info [String] Info passed to OpenNebula Core.

@return [&block] the allocated object through a block.

# File lib/vcenter_importer.rb, line 515
def create(info, &block)
    resource = VCenterDriver::VIHelper.new_one_item(@one_class)
    message = 'Error creating the OpenNebula resource'

    rc = resource.allocate(info)
    VCenterDriver::VIHelper.check_error(rc, message)

    resource.info
    id = resource['ID']
    @rollback << Raction.new(resource, :delete)
    block.call(resource, id)
end
create_pools() click to toggle source
# File lib/vcenter_importer.rb, line 596
def create_pools
    dpool = VCenterDriver::VIHelper.one_pool(OpenNebula::DatastorePool)
    if dpool.respond_to?(:message)
        raise "Could not get OpenNebula DatastorePool: \
              #{dpool.message}"
    end

    ipool = VCenterDriver::VIHelper.one_pool(OpenNebula::ImagePool)
    if ipool.respond_to?(:message)
        raise "Could not get OpenNebula ImagePool: #{ipool.message}"
    end

    npool = VCenterDriver::VIHelper
            .one_pool(OpenNebula::VirtualNetworkPool)
    if npool.respond_to?(:message)
        raise "Could not get OpenNebula VirtualNetworkPool: \
              #{npool.message}"
    end

    hpool = VCenterDriver::VIHelper.one_pool(OpenNebula::HostPool)
    if hpool.respond_to?(:message)
        raise "Could not get OpenNebula VirtualNetworkPool: \
              #{hpool.message}"
    end

    [dpool, ipool, npool, hpool]
end
defaults() click to toggle source

Default opts

# File lib/vcenter_importer.rb, line 590
def defaults
    return @defaults if @defaults

    {}
end
get_element(ref) click to toggle source

Gets a certain element from the list, ref given.

@param ref [String] vCenter reference and index of importer list.

@return [Hash] Hash with all the info related to the reference

# File lib/vcenter_importer.rb, line 542
def get_element(ref)
    raise 'the list is empty' if list_empty? || @list.values[0].empty?

    list = @list.values[0]

    return list[ref] if list[ref]

    raise "#{ref} not found!"
end
get_list(_args = {}) click to toggle source

Retrieves a list with the unimported resources The importer needs to perform this operation before any import operation,

@param args [Hash] Hash with the needed arguments

@return [Hash{String => Hash}] operation results.

# File lib/vcenter_importer.rb, line 472
def get_list(_args = {})
    raise MESS
end
import(_selected) click to toggle source

Retrieves information about the run-time state of a virtual machine.

@param selected [Hash] Hash with the info of the

vCenter object that will

be imported

@return [Hash{:id => [], :name => String}] operation results.

# File lib/vcenter_importer.rb, line 504
def import(_selected)
    raise MESS
end
list_empty?() click to toggle source

Asks if @list is empty

# File lib/vcenter_importer.rb, line 531
def list_empty?
    @list == {}
end
remove_default(_id) click to toggle source

Remove the imported resource from the default cluster

@param id [Int] id of the imported resource

# File lib/vcenter_importer.rb, line 491
def remove_default(_id)
    raise MESS
end