class OpenNebulaHelper::OneHelper

Attributes

client[RW]

Public Class Methods

client() click to toggle source
# File lib/one_helper.rb, line 641
def self.client
    if defined?(@@client)
        @@client
    else
        get_client
    end
end
filterflag_to_i_desc() click to toggle source
# File lib/one_helper.rb, line 1283
        def self.filterflag_to_i_desc
            desc=<<~EOT
                a, all            all the known #{rname}s
                m, mine           the #{rname} belonging to the user in ONE_AUTH
                g, group          'mine' plus the #{rname} belonging to the groups
                                  the user is member of
                G, primary group  the #{rname} owned the user's primary group
                uid               #{rname} of the user identified by this uid
                user              #{rname} of the user identified by the username
            EOT
        end
get_client(options = {}, force = false) click to toggle source
# File lib/one_helper.rb, line 602
def self.get_client(options = {}, force = false)
    if !force && defined?(@@client)
        @@client
    else

        secret=nil
        password=nil

        if defined?(@@user)
            user=@@user
            password=@@password if defined?(@@password)
        else
            user=options[:user]
        end

        if user
            password=password||options[:password]||get_password
            secret="#{user}:#{password}"
        end

        if defined?(@@endpoint)
            endpoint=@@endpoint
        else
            endpoint=options[:endpoint]
        end

        # This breaks the CLI SSL support for Ruby 1.8.7, but is necessary
        # in order to do template updates, otherwise you get the broken pipe
        # error (bug #3341)
        if RUBY_VERSION < '1.9'
            sync = false
        else
            sync = true
        end
        options[:sync] = sync
        @@client=OpenNebula::Client.new(secret, endpoint, options)
    end
end
get_password() click to toggle source
# File lib/one_helper.rb, line 663
def self.get_password
    print 'Password: '
    pass=nil
    STDIN.noecho {|io| pass=io.gets }
    puts

    pass.chop! if pass
    @@password=pass
    pass
end
list_layout_help() click to toggle source
# File lib/one_helper.rb, line 688
def self.list_layout_help
    "The default columns and their layout can be configured in #{conf_file}"
end
list_to_id_desc() click to toggle source
# File lib/one_helper.rb, line 1243
def self.list_to_id_desc
    "Comma-separated list of OpenNebula #{rname} names or ids"
end
name_to_id(name, pool, ename) click to toggle source
# File lib/one_helper.rb, line 1247
def self.name_to_id(name, pool, ename)
    if ename=='CLUSTER' and name.upcase=='ALL'
        return 0, 'ALL'
    end

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

    return -1, "#{ename} named #{name} not found." unless objects.length>0
    return -1, "There are multiple #{ename}s with name #{name}." if objects.length>1

    result = objects.first.id

    [0, result]
end
new(_secret = nil, _endpoint = nil) click to toggle source
# File lib/one_helper.rb, line 696
def initialize(_secret = nil, _endpoint = nil)
    @client=nil

    @translation_hash = nil
end
set_endpoint(endpoint) click to toggle source
# File lib/one_helper.rb, line 657
def self.set_endpoint(endpoint)
    @@endpoint=endpoint
end
set_password(password) click to toggle source
# File lib/one_helper.rb, line 653
def self.set_password(password)
    @@password=password
end
set_user(user) click to toggle source
# File lib/one_helper.rb, line 649
def self.set_user(user)
    @@user=user
end
table_conf(conf_file = self.conf_file) click to toggle source
# File lib/one_helper.rb, line 1295
def self.table_conf(conf_file = self.conf_file)
    path = "#{ENV['HOME']}/.one/cli/#{conf_file}"

    if File.exist?(path)
        path
    else
        "#{TABLE_CONF_PATH}/#{conf_file}"
    end
end
template_input_help(object_name) click to toggle source
# File lib/one_helper.rb, line 692
def self.template_input_help(object_name)
    "#{TEMPLATE_INPUT}\nWhen using a template add only one #{object_name} instance."
end
to_id_desc() click to toggle source
# File lib/one_helper.rb, line 1215
def self.to_id_desc
    "OpenNebula #{rname} name or id"
end

Public Instance Methods

backup_mode_valid?(sus_backup_mode) click to toggle source
# File lib/one_helper.rb, line 722
def backup_mode_valid?(sus_backup_mode)
    BACKUP_MODES.each do |backup_mode|
        return true if backup_mode.casecmp?(sus_backup_mode)
    end

    false
end
check_orphan(pool, xpath, resource_name, attributes) click to toggle source

Check if a resource defined by attributes is referenced in pool

@param pool pool to search in @param xpath xpath to search in pool @param resource_name name of the resource to search (e.g IMAGE) @attributes hash with resource attributes, must contains :id, :name and :uname

atributes {uname => …, name => …, id => …}

# File lib/one_helper.rb, line 1109
def check_orphan(pool, xpath, resource_name, attributes)
    return false if attributes.empty?

    return false unless pool["#{xpath}[#{resource_name}_ID = "\
                             "#{attributes[:id]}]"].nil?

    return false unless pool["#{xpath}[#{resource_name} = "\
                             "'#{attributes[:name]}' and "\
                             "#{resource_name}_UNAME = "\
                             "'#{attributes[:uname]}']"].nil?

    true
end
create_resource(_options, &block) click to toggle source
# File lib/one_helper.rb, line 710
def create_resource(_options, &block)
    resource = factory

    rc = block.call(resource)
    if OpenNebula.is_error?(rc)
        [-1, rc.message]
    else
        puts "ID: #{resource.id}"
        0
    end
end
filterflag_to_i(str) click to toggle source
# File lib/one_helper.rb, line 1262
def filterflag_to_i(str)
    filter_flag = case str
                  when 'a', 'all'   then OpenNebula::Pool::INFO_ALL
                  when 'm', 'mine'  then OpenNebula::Pool::INFO_MINE
                  when 'g', 'group' then OpenNebula::Pool::INFO_GROUP
                  when 'G', 'primary group' then OpenNebula::Pool::INFO_PRIMARY_GROUP
                  else
                      if str.match(/^[0123456789]+$/)
                          str.to_i
                      else
                          rc = OpenNebulaHelper.rname_to_id(str, 'USER')
                          return rc if rc.first==-1

                          rc[1]

                      end
                  end

    [0, filter_flag]
end
group_name(resource, options = {}) click to toggle source
# File lib/one_helper.rb, line 1192
def group_name(resource, options = {})
    if options[:numeric]
        resource['GID']
    else
        resource['GNAME']
    end
end
list_pool(options, top = false, filter_flag = nil) click to toggle source
# File lib/one_helper.rb, line 1058
def list_pool(options, top = false, filter_flag = nil)
    # Capture Broken pipe
    Signal.trap('PIPE', 'EXIT')

    table = format_pool(options)

    if options[:describe]
        table.describe_columns

        return 0
    end

    filter_flag ||= OpenNebula::Pool::INFO_ALL

    pool  = factory_pool(filter_flag)
    pname = pool.pool_name
    ename = pool.element_name

    if top
        return list_pool_top(table, pool, options)
    elsif options[:xml]
        return list_pool_xml(pool, options, filter_flag)
    elsif options[:json]
        return list_pool_format(pool, options, filter_flag) do |pool|
            hash = check_resource_xsd(pool, pname)
            puts ::JSON.pretty_generate(hash)
        end
    elsif options[:yaml]
        return list_pool_format(pool, options, filter_flag) do |pool|
            hash = check_resource_xsd(pool, pname)
            puts hash.to_yaml(:indent => 4)
        end
    else
        return list_pool_table(table, pool, options, filter_flag)
    end

    0
rescue SystemExit, Interrupt
    # Rescue ctrl + c when paginated
    0
end
list_pool_format(pool, options, _filter_flag) { |pool| ... } click to toggle source
# File lib/one_helper.rb, line 970
def list_pool_format(pool, options, _filter_flag)
    extended = options.include?(:extended) && options[:extended]

    if $stdout.isatty and (!options.key? :no_pager)
        size = $stdout.winsize[0] - 1

        # ----------- First page, check if pager is needed -------------
        rc = pool.get_page(size, 0, extended, options[:state])
        ps = ''

        return -1, rc.message if OpenNebula.is_error?(rc)

        elements = get_format_size(pool, options)
        ppid     = -1

        if elements >= size
            ppid = start_pager
        end

        yield(pool) if block_given?

        if elements < size
            return 0
        end

        if elements < size
            return 0
        elsif !pool.is_paginated?
            stop_pager(ppid)
            return 0
        end

        # ------- Rest of the pages in the pool, piped to pager --------
        current = size

        loop do
            rc = pool.get_page(size, current, extended, options[:state])

            return -1, rc.message if OpenNebula.is_error?(rc)

            current += size

            begin
                Process.waitpid(ppid, Process::WNOHANG)
            rescue Errno::ECHILD
                break
            end

            elements = get_format_size(pool, options)

            break if elements < size

            yield(pool) if block_given?

            $stdout.flush
        end

        stop_pager(ppid)
    else
        if pool.pool_name == 'VM_POOL' && extended
            rc = pool.info_all_extended
        else
            rc = pool.info
        end

        return -1, rc.message if OpenNebula.is_error?(rc)

        yield(pool) if block_given?
    end

    0
end
list_pool_table(table, pool, options, _filter_flag) click to toggle source
# File lib/one_helper.rb, line 811
def list_pool_table(table, pool, options, _filter_flag)
    if $stdout.isatty and (!options.key? :no_pager)
        size = $stdout.winsize[0] - 1

        # ----------- First page, check if pager is needed -------------
        rc = pool.get_page(size, 0, false, options[:state])
        ps = ''

        return -1, rc.message if OpenNebula.is_error?(rc)

        elements, hash = print_page(pool, options)

        ppid = -1

        if elements >= size
            ppid = start_pager
        end

        table.show(hash, options)

        if elements < size
            return 0
        elsif !pool.is_paginated?
            stop_pager(ppid)
            return 0
        end

        # ------- Rest of the pages in the pool, piped to pager --------
        current = size

        options[:no_header] = true

        loop do
            rc = pool.get_page(size, current, false, options[:state])

            return -1, rc.message if OpenNebula.is_error?(rc)

            current += size

            begin
                Process.waitpid(ppid, Process::WNOHANG)
            rescue Errno::ECHILD
                break
            end

            elements, hash = print_page(pool, options)

            table.show(hash, options)

            $stdout.flush

            break if elements < size
        end

        stop_pager(ppid)
    else
        rc = pool.info

        return -1, rc.message if OpenNebula.is_error?(rc)

        elements, hash = print_page(pool, options)

        if options[:ids] && elements
            hash = [hash[pool.pool_name][pool.element_name]].flatten
            hash.reject! do |element|
                !options[:ids].include?(element['ID'].to_i)
            end
        end

        table.show(hash, options)
    end

    0
end
list_pool_top(table, pool, options) click to toggle source
# File lib/one_helper.rb, line 1046
def list_pool_top(table, pool, options)
    table.top(options) do
        array = pool.get_hash

        return -1, array.message if OpenNebula.is_error?(array)

        array
    end

    0
end
list_pool_xml(pool, options, _filter_flag) click to toggle source
# File lib/one_helper.rb, line 889
def list_pool_xml(pool, options, _filter_flag)
    extended = options.include?(:extended) && options[:extended]

    if $stdout.isatty and (!options.key? :no_pager)
        size = $stdout.winsize[0] - 1

        # ----------- First page, check if pager is needed -------------
        rc = pool.get_page(size, 0, extended, options[:state])
        ps = ''

        return -1, rc.message if OpenNebula.is_error?(rc)

        pname = pool.pool_name

        elements, page = print_page(pool, options)

        ppid = -1

        if elements >= size
            ppid = start_pager
        end

        puts page

        if elements < size
            return 0
        end

        if elements < size
            return 0
        elsif !pool.is_paginated?
            stop_pager(ppid)
            return 0
        end

        # ------- Rest of the pages in the pool, piped to pager --------
        current = size

        loop do
            rc = pool.get_page(size, current, extended, options[:state])

            return -1, rc.message if OpenNebula.is_error?(rc)

            current += size

            begin
                Process.waitpid(ppid, Process::WNOHANG)
            rescue Errno::ECHILD
                break
            end

            elements, page = print_page(pool, options)

            puts page

            $stdout.flush

            break if elements < size
        end

        puts "</#{pname}>"

        stop_pager(ppid)
    else
        if pool.pool_name == 'VM_POOL' && extended
            rc = pool.info_all_extended
        else
            rc = pool.info
        end

        return -1, rc.message if OpenNebula.is_error?(rc)

        puts pool.to_xml(true)
    end

    0
end
list_to_id(names) click to toggle source
# File lib/one_helper.rb, line 1219
def list_to_id(names)
    rc = get_pool
    return rc if rc.first != 0

    pool     = rc[1]
    poolname = self.class.rname

    result = names.split(',').collect do |name|
        if name.match(/^[0123456789]+$/)
            name.to_i
        else
            rc = OneHelper.name_to_id(name, pool, poolname)

            if rc.first == -1
                return rc[0], rc[1]
            end

            rc[1]
        end
    end

    [0, result]
end
perform_action(id, options, verbose, &block) click to toggle source
# File lib/one_helper.rb, line 1153
def perform_action(id, options, verbose, &block)
    resource = retrieve_resource(id)

    rc = block.call(resource)
    if OpenNebula.is_error?(rc)
        [-1, rc.message]
    else
        if options[:verbose]
            puts "#{self.class.rname} #{id}: #{verbose}"
        end
        0
    end
end
perform_actions(ids, options, verbose, &block) click to toggle source
# File lib/one_helper.rb, line 1167
def perform_actions(ids, options, verbose, &block)
    exit_code = 0
    ids.each do |id|
        rc = perform_action(id, options, verbose, &block)

        unless rc[0]==0
            STDERR.puts rc[1]
            exit_code=rc[0]
        end
    end

    exit_code
end
print_page(pool, options) click to toggle source
retrieve_resource(id) click to toggle source
# File lib/one_helper.rb, line 1305
def retrieve_resource(id)
    factory(id)
end
set_client(options, client = nil) click to toggle source
# File lib/one_helper.rb, line 702
def set_client(options, client = nil)
    if client.nil?
        @client=OpenNebulaHelper::OneHelper.get_client(options, true)
    else
        @client = client
    end
end
show_resource(id, options) click to toggle source
# File lib/one_helper.rb, line 1123
def show_resource(id, options)
    resource = retrieve_resource(id)

    if !options.key? :decrypt
        rc = resource.info
    else
        rc = resource.info(true)
    end

    return -1, rc.message if OpenNebula.is_error?(rc)

    if options[:xml]
        [0, resource.to_xml(true)]
    elsif options[:json]
        # If body is set, the resource contains a JSON inside
        if options[:body]
            [0, check_resource_xsd(resource)]
        else
            [0, ::JSON.pretty_generate(
                check_resource_xsd(resource)
            )]
        end
    elsif options[:yaml]
        [0, check_resource_xsd(resource).to_yaml(:indent => 4)]
    else
        format_resource(resource, options)
        0
    end
end
start_pager() click to toggle source
# File lib/one_helper.rb, line 733
def start_pager
    pager = ENV['ONE_PAGER'] || 'more'

    # Start pager, defaults to less
    p_r, p_w = IO.pipe

    Signal.trap('PIPE', 'SIG_IGN')
    Signal.trap('PIPE', 'EXIT')

    lpid = fork do
        $stdin.reopen(p_r)

        p_r.close
        p_w.close

        Kernel.select [$stdin]

        exec([pager, pager])
    end

    # Send listing to pager pipe
    $stdout.close
    $stdout = p_w.dup

    p_w.close
    p_r.close

    lpid
end
stop_pager(lpid) click to toggle source
# File lib/one_helper.rb, line 763
def stop_pager(lpid)
    $stdout.close

    begin
        Process.wait(lpid)
    rescue Interrupt
        Process.kill('TERM', lpid)
        Process.wait(lpid)
    rescue Errno::ECHILD
    end
end
to_id(name) click to toggle source

Formatters for arguments

# File lib/one_helper.rb, line 1203
def to_id(name)
    return 0, name.to_i if name.match(/^[0123456789]+$/)

    rc = get_pool
    return rc if rc.first != 0

    pool     = rc[1]
    poolname = self.class.rname

    OneHelper.name_to_id(name, pool, poolname)
end
user_name(resource, options = {}) click to toggle source

Id translation

# File lib/one_helper.rb, line 1184
def user_name(resource, options = {})
    if options[:numeric]
        resource['UID']
    else
        resource['UNAME']
    end
end

Private Instance Methods

check_resource_xsd(resource, ename = nil) click to toggle source

Check XSD values for a single resource

@param resource [OpenNebula::Object] Resource to check @param ename [String] Resource name

@return [Object] Hash with correct values

# File lib/one_helper.rb, line 1371
def check_resource_xsd(resource, ename = nil)
    hash  = resource.to_hash
    ename ||= hash.keys.first
    xsd   = read_xsd(ename)

    return hash unless xsd

    if xsd.keys.include?('complexType')
        xsd = xsd['complexType']['sequence']['element']
    else
        xsd = xsd['element']
    end

    xsd = [xsd] unless xsd.is_a? Array

    check_xsd(hash[ename], xsd)

    hash
end
check_xsd(hash, xsd) click to toggle source

Recursively traverse the OpenNebula resource (in Hash) and it’s XSD Where array is required in XSD, there encapsulate the entry into [ ] Typically usefull for single disk, snapshots etc.

@param hash [Hash] Resource information in hash format @param xsd [Hash] XSD of the resource, transformed into hash

# File lib/one_helper.rb, line 1489
def check_xsd(hash, xsd)
    return unless hash or hash.empty?

    hash.each do |k, v|
        # find the elem definition in xsd array
        xsd_elem = xsd.select {|e| e['name'] == k }.first unless xsd.nil?

        if xsd_complex_sequence?(xsd_elem) || xsd_complex_all?(xsd_elem)

            # go deeper in xsd, xsd is ehter complex sequence or all
            begin
                inner_xsd = xsd_elem['complexType']['sequence']['element']
            rescue StandardError
                inner_xsd = xsd_elem['complexType']['all']['element']
            end

            # recursively traverse resource - hash
            if v.is_a? Hash
                hash[k] = check_xsd(v, inner_xsd)

            # recursively traverse resource - array
            elsif v.is_a? Array
                hash[k] = []
                v.each do |e|
                    hash[k] << check_xsd(e, inner_xsd)
                end
            end
        end

        # if XSD requires array, do so in resource if missing
        if is_array?(xsd_elem) && (!v.is_a? Array)
            hash[k] = [v]
        end
    end
end
get_format_size(pool, options) click to toggle source
# File lib/one_helper.rb, line 1350
def get_format_size(pool, options)
    if options[:json]
        ::JSON.pretty_generate(pool.to_hash).split("\n").size
    elsif options[:yaml]
        pool.to_hash.to_yaml.split("\n").size
    else
        STDERR.puts 'ERROR: Format not found'
        exit(-1)
    end
end
get_pool() click to toggle source
# File lib/one_helper.rb, line 1334
def get_pool
    user_flag = OpenNebula::Pool::INFO_ALL
    pool = factory_pool(user_flag)

    rc = pool.info
    if OpenNebula.is_error?(rc)
        return -1, rc.message unless rc.message.empty?

        return -1, "OpenNebula #{self.class.rname} name not " <<
               'found, use the ID instead'

    end

    [0, pool]
end
is_array?(e) click to toggle source

Decides if given xsd definiton should be array in xml Must be hash and contain either ‘maxOccurs’ => unbounded’

or 'maxOccurs' => >1

@param e [Hash] XSD definition transfomred in hash

@return [Boolean]

# File lib/one_helper.rb, line 1449
def is_array?(e)
    return false if e.nil?
    return false unless e.is_a? Hash

    e['maxOccurs'] == 'unbounded' || e['maxOccurs'].to_i > 1
end
pool_to_array(pool) click to toggle source
# File lib/one_helper.rb, line 1311
def pool_to_array(pool)
    if !pool.instance_of?(Hash)
        phash = pool.to_hash
    else
        phash = pool
    end

    rname = self.class.rname

    if phash["#{rname}_POOL"] &&
            phash["#{rname}_POOL"]["#{rname}"]
        if phash["#{rname}_POOL"]["#{rname}"].instance_of?(Array)
            phash = phash["#{rname}_POOL"]["#{rname}"]
        else
            phash = [phash["#{rname}_POOL"]["#{rname}"]]
        end
    else
        phash = []
    end

    phash
end
read_xsd(ename) click to toggle source

Read XSD file and parse to XML

@param ename [String] Element name to read XSD

@return [Hash] XSD in hash format, nil if not found

# File lib/one_helper.rb, line 1417
def read_xsd(ename)
    require 'active_support'
    require 'active_support/core_ext/hash/conversions'

    # Try GEM directory
    file = File.expand_path(
        "../share/schemas/xsd/#{ename.downcase}.xsd",
        File.dirname(__FILE__)
    )

    file = "#{XSD_PATH}/#{ename.downcase}.xsd" unless File.exist?(file)

    unless File.exist?(file)
        STDERR.puts "WARNING: XSD for #{ename} not found, skipping check"
        return
    end

    hash = Hash.from_xml(Nokogiri::XML(File.read(file)).to_s)

    hash = hash['schema']['element']

    replace_refs(hash)
end
replace_refs(h) click to toggle source

Replaces refs in xsd definition limited func: only traverse hashes (not arrays), but works well for pools

@param h [Hash] XSD in hash format

@return [Object] XSD but where ref were, there inner XSD is loaded

# File lib/one_helper.rb, line 1397
def replace_refs(h)
    return h unless h.is_a? Hash

    if h.keys.include? 'ref'
        ref_xsd = read_xsd(h['ref'])
        return ref_xsd unless ref_xsd.nil?

        h
    else
        h.each do |k, v|
            h[k] = replace_refs(v)
        end
    end
end
xsd_complex_all?(x) click to toggle source

Decides if given xsd definiton is complex type all Must be hash and contain nested hash

['complexType']['all']['element']

@param [Hash] XSD definition transfomred in hash

@return [Boolean]

# File lib/one_helper.rb, line 1477
def xsd_complex_all?(x)
    x['complexType']['all']['element'] rescue return false
    true
end
xsd_complex_sequence?(x) click to toggle source

Decides if given xsd definiton is complex type sequence Must be hash and contain nested hash

['complexType']['sequence']['element']

@param [Hash] XSD definition transfomred in hash

@return [Boolean]

# File lib/one_helper.rb, line 1464
def xsd_complex_sequence?(x)
    x['complexType']['sequence']['element'] rescue return false
    true
end