class OpenNebulaHelper::OneHelper

Attributes

client[RW]

Public Class Methods

client() click to toggle source
# File lib/one_helper.rb, line 496
def self.client
    if defined?(@@client)
        @@client
    else
        self.get_client
    end
end
filterflag_to_i_desc() click to toggle source
# File lib/one_helper.rb, line 1132
        def self.filterflag_to_i_desc
            desc=<<-EOT
a, all            all the known #{self.rname}s
m, mine           the #{self.rname} belonging to the user in ONE_AUTH
g, group          'mine' plus the #{self.rname} belonging to the groups
                  the user is member of
G, primary group  the #{self.rname} owned the user's primary group
uid               #{self.rname} of the user identified by this uid
user              #{self.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 457
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]||self.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 518
def self.get_password
    print "Password: "
    pass=nil
    STDIN.noecho {|io| pass=io.gets }
    puts

    pass.chop! if pass
    @@password=pass
    pass
end
list_to_id_desc() click to toggle source
# File lib/one_helper.rb, line 1086
def self.list_to_id_desc
    "Comma-separated list of OpenNebula #{self.rname} names or ids"
end
name_to_id(name, pool, ename) click to toggle source
# File lib/one_helper.rb, line 1090
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 }

    if objects.length>0
        if objects.length>1
            return -1, "There are multiple #{ename}s with name #{name}."
        else
            result = objects.first.id
        end
    else
        return -1, "#{ename} named #{name} not found."
    end

    return 0, result
end
new(secret=nil, endpoint=nil) click to toggle source
# File lib/one_helper.rb, line 543
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 512
def self.set_endpoint(endpoint)
    @@endpoint=endpoint
end
set_password(password) click to toggle source
# File lib/one_helper.rb, line 508
def self.set_password(password)
    @@password=password
end
set_user(user) click to toggle source
# File lib/one_helper.rb, line 504
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 1144
def self.table_conf(conf_file=self.conf_file)
    path = "#{ENV["HOME"]}/.one/cli/#{conf_file}"

    if File.exists?(path)
        return path
    else
        return "#{TABLE_CONF_PATH}/#{conf_file}"
    end
end
to_id_desc() click to toggle source
# File lib/one_helper.rb, line 1058
def self.to_id_desc
    "OpenNebula #{self.rname} name or id"
end

Public Instance Methods

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 952
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 557
def create_resource(options, &block)
    resource = factory

    rc = block.call(resource)
    if OpenNebula.is_error?(rc)
        return -1, rc.message
    else
        puts "ID: #{resource.id.to_s}"
        return 0
    end
end
filterflag_to_i(str) click to toggle source
# File lib/one_helper.rb, line 1110
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")
            if rc.first==-1
                return rc
            else
                rc[1]
            end
        end
    end

    return 0, filter_flag
end
group_name(resource, options={}) click to toggle source
# File lib/one_helper.rb, line 1035
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 901
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]
        list_pool_format(pool, options, filter_flag) do |pool|
            hash        = check_resource_xsd(pool, pname)
            puts ::JSON.pretty_generate(hash)
        end
    elsif options[:yaml]
        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

    return 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 812
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

    return 0
end
list_pool_table(table, pool, options, filter_flag) click to toggle source
# File lib/one_helper.rb, line 650
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

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

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

        array
    }

    return 0
end
list_pool_xml(pool, options, filter_flag) click to toggle source
# File lib/one_helper.rb, line 728
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 "<#{pname}>"

        puts page

        if elements < size
            puts "</#{pname}>"
            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

    return 0
end
list_to_id(names) click to toggle source
# File lib/one_helper.rb, line 1062
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 { |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
    }

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

    rc = block.call(resource)
    if OpenNebula.is_error?(rc)
        return -1, rc.message
    else
        if options[:verbose]
            puts "#{self.class.rname} #{id}: #{verbose}"
        end
        return 0
    end
end
perform_actions(ids,options,verbose,&block) click to toggle source
# File lib/one_helper.rb, line 1010
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 1154
def retrieve_resource(id)
    factory(id)
end
set_client(options, client=nil) click to toggle source
# File lib/one_helper.rb, line 549
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 966
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]
        return 0, resource.to_xml(true)
    elsif options[:json]
        # If body is set, the resource contains a JSON inside
        if options[:body]
            return 0, check_resource_xsd(resource)
        else
            return 0, ::JSON.pretty_generate(
                check_resource_xsd(resource)
            )
        end
    elsif options[:yaml]
        return 0, check_resource_xsd(resource).to_yaml(:indent => 4)
    else
        format_resource(resource, options)
        return 0
    end
end
start_pager() click to toggle source
# File lib/one_helper.rb, line 572
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

    return lpid
end
stop_pager(lpid) click to toggle source
# File lib/one_helper.rb, line 602
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 1046
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 1027
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 1221
def check_resource_xsd(resource, ename = nil)
    hash  = resource.to_hash
    ename = hash.keys.first unless ename
    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 1340
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
                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 1200
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 1183
def get_pool
    user_flag = OpenNebula::Pool::INFO_ALL
    pool = factory_pool(user_flag)

    rc = pool.info
    if OpenNebula.is_error?(rc)
        if rc.message.empty?
            return -1, "OpenNebula #{self.class.rname} name not " <<
                   "found, use the ID instead"
        else
            return -1,rc.message
        end
    end

    return 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 1301
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 1160
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 = Array.new
    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 1268
def read_xsd(ename)
    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 nil
    end

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

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

    hash = replace_refs(hash)

    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 1248
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?
        return 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 1328
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 1315
def xsd_complex_sequence?(x)
    x['complexType']['sequence']['element'] rescue return false
    true
end