class OpenNebulaDriver

This class provides basic messaging and logging functionality to implement OpenNebula Drivers. A driver is a program that specialize the OpenNebula behavior by interfacing with specific infrastructure functionalities.

A Driver inherits this class and only has to provide methods for each action it wants to receive. The method must be associated with the action name through the register_action function

Attributes

local_scripts_base_path[R]

@return [String] Base path for scripts

local_scripts_path[R]

@return [String] Path for scripts

remote_scripts_base_path[R]

@return [String] Base path for scripts

remote_scripts_path[R]

@return [String] Path for scripts

Public Class Methods

new(directory, options={}) click to toggle source

Initialize OpenNebulaDriver object

@param [String] directory path inside the remotes directory where the

scripts are located

@param [Hash] options named options to change the object's behaviour @option options [Number] :concurrency (10) max number of threads @option options [Boolean] :threaded (true) enables or disables threads @option options [Number] :retries (0) number of retries to copy scripts

to the remote host

@option options [Hash] :local_actions ({}) hash with the actions

executed locally and the name of the script if it differs from the
default one. This hash can be constructed using {parse_actions_list}
Calls superclass method ActionManager.new
# File lib/OpenNebulaDriver.rb, line 51
def initialize(directory, options={})
    @options={
        :concurrency => 10,
        :threaded    => true,
        :retries     => 0,
        :local_actions => {},
        :timeout     => nil
    }.merge!(options)

    super(@options[:concurrency], @options[:threaded])

    @retries = @options[:retries]
    @timeout = @options[:timeout]

    #Set default values
    initialize_helper(directory, @options)

    register_action(:INIT, method("init"))
end
parse_actions_list(str) click to toggle source

This function parses a string with this form:

'deploy,shutdown,poll=poll_ganglia, cancel '

and returns a hash:

{"POLL"=>"poll_ganglia", "DEPLOY"=>nil, "SHUTDOWN"=>nil,
  "CANCEL"=>nil}

@param [String] str imput string to parse @return [Hash] parsed actions

# File lib/OpenNebulaDriver.rb, line 158
def self.parse_actions_list(str)
    actions=Hash.new
    str_splitted=str.split(/\s*,\s*/).map {|s| s.strip }

    str_splitted.each do |a|
        m=a.match(/([^=]+)(=(.*))?/)
        next if !m

        action=m[1].upcase

        if m[2]
            script=m[3]
            script.strip! if script
        else
            script=nil
        end

        actions[action]=script
    end

    actions
end

Public Instance Methods

do_action(parameters, id, host, aname, ops={}) click to toggle source

Calls remotes or local action checking the action name and @local_actions. Optional arguments can be specified as a hash

@param [String] parameters arguments passed to the script @param [Number, String] id action identifier @param [String] host hostname where the action is going to be executed @param [String, Symbol] aname name of the action @param [Hash] ops extra options for the command @option ops [String] :stdin text to be writen to stdin @option ops [String] :script_name default script name for the action,

action name is used by defaults

@option ops [Bool] :respond if defined will send result to ONE core @option ops [Bool] :base64 encode the information sent to ONE core

# File lib/OpenNebulaDriver.rb, line 86
def do_action(parameters, id, host, aname, ops={})
    options={
        :stdin       => nil,
        :script_name => nil,
        :respond     => true,
        :ssh_stream  => nil,
        :base64      => false
    }.merge(ops)

    params  = parameters + " #{id} #{host}"
    command = action_command_line(aname, params, options[:script_name])

    if action_is_local?(aname)
        stdin = Base64::encode64(options[:stdin].to_s.gsub("\n",""))
        execution = LocalCommand.run(command,
                                     log_method(id),
                                     stdin,
                                     @timeout)
    elsif options[:ssh_stream]
        if options[:stdin]
            cmdin = "cat << EOT | #{command}"
            stdin = "#{options[:stdin]}\nEOT\n"
        else
            cmdin = command
            stdin = nil
        end

        execution = options[:ssh_stream].run(cmdin,
                                             stdin,
                                             command,
                                             @timeout)

    else
        execution = RemotesCommand.run(command,
                                       host,
                                       @remote_scripts_base_path,
                                       log_method(id),
                                       options[:stdin],
                                       @retries,
                                       @timeout)
    end

    result, info = get_info_from_execution(execution)

    if options[:respond]
        info = Base64::encode64(info).strip.delete("\n") if options[:base64]
        send_message(aname, result, id, info)
    end

    [result, info]
end
start_driver() click to toggle source

Start the driver. Reads from STDIN and executes methods associated with the messages

# File lib/OpenNebulaDriver.rb, line 141
def start_driver
    loop_thread = Thread.new { loop }
    start_listener
    loop_thread.kill
end

Private Instance Methods

init() click to toggle source
# File lib/OpenNebulaDriver.rb, line 183
def init
    send_message("INIT",RESULT[:success])
end
loop() click to toggle source
# File lib/OpenNebulaDriver.rb, line 187
def loop
    while true
        exit(-1) if STDIN.eof?

        str=STDIN.gets
        next if !str

        args   = str.split(/\s+/)
        next if args.length == 0

        if args.first.empty?
            STDERR.puts "Malformed message: #{str.inspect}"
            next
        end

        action = args.shift.upcase.to_sym

        if (args.length == 0) || (!args[0])
            action_id = 0
        else
            action_id = args[0].to_i
        end

        if action == :DRIVER_CANCEL
            cancel_action(action_id)
            log(action_id,"Driver command for #{action_id} cancelled")
        else
            trigger_action(action,action_id,*args)
        end
    end
end