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 52
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 162
def self.parse_actions_list(str)
    actions = {}
    str_splitted = str.split(/\s*,\s*/).map {|s| s.strip }

    str_splitted.each do |a|
        m=a.match(/([^=]+)(=(.*))?/)
        next unless 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 @option ops [Bool] :zip compress 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,
        :zip => false,
        :no_extra_params => false
    }.merge(ops)

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

    # if options[:is_local] is not specified (nil)
    # we rely uniquely in actions_is_local?
    if action_is_local?(aname) or options[:is_local]
        stdin = Base64.strict_encode64(options[:stdin].to_s)
        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 = Zlib::Deflate.deflate(info, Zlib::BEST_COMPRESSION) if options[:zip]
        info = Base64.strict_encode64(info) 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 146
def start_driver
    Thread.new { loop }
    start_listener
end

Private Instance Methods

init() click to toggle source
# File lib/OpenNebulaDriver.rb, line 187
def init
    send_message('INIT', RESULT[:success])
end
loop() click to toggle source
# File lib/OpenNebulaDriver.rb, line 191
def loop
    Kernel.loop do
        exit!(-1) if STDIN.eof?

        str = STDIN.gets
        next unless str

        args = str.split(/\s+/)
        next if args.empty?

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

        action = args.shift.upcase.to_sym

        if args.empty? || !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