diff --git a/src/vmm_mad/exec/one_vmm_exec.rb b/src/vmm_mad/exec/one_vmm_exec.rb index 5502fbcccc..b15fcb1fb9 100755 --- a/src/vmm_mad/exec/one_vmm_exec.rb +++ b/src/vmm_mad/exec/one_vmm_exec.rb @@ -18,22 +18,22 @@ # Set up the environment for the driver -ONE_LOCATION = ENV["ONE_LOCATION"] +ONE_LOCATION = ENV['ONE_LOCATION'] if !ONE_LOCATION - RUBY_LIB_LOCATION = "/usr/lib/one/ruby" - MAD_LOCATION = "/usr/lib/one/mads" - ETC_LOCATION = "/etc/one/" + RUBY_LIB_LOCATION = '/usr/lib/one/ruby' + MAD_LOCATION = '/usr/lib/one/mads' + ETC_LOCATION = '/etc/one/' else - RUBY_LIB_LOCATION = ONE_LOCATION + "/lib/ruby" - MAD_LOCATION = ONE_LOCATION + "/lib/mads" - ETC_LOCATION = ONE_LOCATION + "/etc/" + RUBY_LIB_LOCATION = ONE_LOCATION + '/lib/ruby' + MAD_LOCATION = ONE_LOCATION + '/lib/mads' + ETC_LOCATION = ONE_LOCATION + '/etc/' end -$: << RUBY_LIB_LOCATION -$: << MAD_LOCATION +$LOAD_PATH << RUBY_LIB_LOCATION +$LOAD_PATH << MAD_LOCATION -require "VirtualMachineDriver" +require 'VirtualMachineDriver' require 'one_vnm' require 'one_tm' require 'getoptlong' @@ -59,7 +59,7 @@ class VmmAction @main_action = action @xml_data = @vmm.decode(xml_data) - @data = Hash.new + @data = {} get_data(:host) get_data(:deploy_id) @@ -85,25 +85,24 @@ class VmmAction # Initialize streams and vnm @ssh_src = @vmm.get_ssh_stream(action, @data[:host], @id) @vnm_src = VirtualNetworkDriver.new(src_drvs, - :local_actions => @vmm.options[:local_actions], - :message => src_xml.to_s, - :ssh_stream => @ssh_src) + :local_actions => @vmm.options[:local_actions], + :message => src_xml.to_s, + :ssh_stream => @ssh_src) - if @data[:dest_host] and !@data[:dest_host].empty? + if @data[:dest_host] && !@data[:dest_host].empty? dst_drvs, dst_xml = get_vnm_drivers(vm_template) @ssh_dst = @vmm.get_ssh_stream(action, @data[:dest_host], @id) @vnm_dst = VirtualNetworkDriver.new(dst_drvs, - :local_actions => @vmm.options[:local_actions], - :message => dst_xml.to_s, - :ssh_stream => @ssh_dst) + :local_actions => @vmm.options[:local_actions], + :message => dst_xml.to_s, + :ssh_stream => @ssh_dst) end @tm = TransferManagerDriver.new(nil) end - - #Execute a set of steps defined with + # Execute a set of steps defined with # - :driver :vmm or :vnm to execute the step # - :action for the step # - :parameters command line paremeters for the action @@ -118,17 +117,17 @@ class VmmAction @ssh_src.close if @ssh_src @ssh_dst.close if @ssh_dst - #Prepare the info for the OpenNebula core + # Prepare the info for the OpenNebula core if !extra_info.nil? - info = extra_info + " " + info = extra_info + ' ' else - info = "" + info = '' end if DriverExecHelper.failed?(result) - info << ( @data[:failed_info] || "-" ) - elsif !@data["#{@main_action.to_s}_info".to_sym].nil? - info << @data["#{@main_action.to_s}_info".to_sym] + info << (@data[:failed_info] || '-') + elsif !@data["#{@main_action}_info".to_sym].nil? + info << @data["#{@main_action}_info".to_sym] end @vmm.send_message(VirtualMachineDriver::ACTION[@main_action], @@ -136,19 +135,20 @@ class VmmAction end private + # List of xpaths required by the VNM driver actions. TEMPLATE/NIC is # also required but added separately to the driver xml - XPATH_LIST = %w( + XPATH_LIST = %w[ ID DEPLOY_ID TEMPLATE/CONTEXT USER_TEMPLATE TEMPLATE/SECURITY_GROUP_RULE HISTORY_RECORDS/HISTORY/HOSTNAME HISTORY_RECORDS/HISTORY/VM_MAD - ) + ] DRIVER_NAMES = { - :vmm => "virtualization driver", - :vnm => "network driver", - :tm => "transfer manager driver" + :vmm => 'virtualization driver', + :vnm => 'network driver', + :tm => 'transfer manager driver' } # Prepares the list of drivers executed on the host and the xml that will @@ -169,9 +169,9 @@ class VmmAction end end - ["NIC", "NIC_ALIAS"].each do |r| + %w[NIC NIC_ALIAS].each do |r| vm_template_xml.elements.each("TEMPLATE/#{r}") do |element| - vn_mad = element.get_text("VN_MAD").to_s + vn_mad = element.get_text('VN_MAD').to_s next if vn_mad.empty? @@ -181,7 +181,7 @@ class VmmAction end end - return [vnm_drivers, vm_vnm_xml] + [vnm_drivers, vm_vnm_xml] end # Executes a set of steps. If one step fails any recover action is performed @@ -223,7 +223,8 @@ class VmmAction params = get_parameters(step[:parameters]) - result, info = vnm.do_action(@id, step[:action], :parameters => params) + result, info = vnm.do_action(@id, step[:action], + :parameters => params) when :tm result, info = @tm.do_transfer_action(@id, step[:parameters]) @@ -256,7 +257,7 @@ class VmmAction end end - return result + result end # Prepare the parameters for the action step generating a blank separated @@ -266,10 +267,10 @@ class VmmAction parameters = step_params || [] parameters.map do |param| - if Symbol===param - "\'#{@data[param].to_s}\'" + if Symbol === param + "\'#{@data[param]}\'" else - "\'#{param}\'" + "\'#{param}\'" end end.join(' ') end @@ -278,15 +279,15 @@ class VmmAction # @param [Symbol] corresponding to a XML element # @param [String] an xpath for the XML element # @return [String] the element value - def get_data(name, xml_path=nil) + def get_data(name, xml_path = nil) if xml_path - path=xml_path.to_s + path = xml_path.to_s else - path=name.to_s.upcase + path = name.to_s.upcase end if (elem = @xml_data.elements[path]) - @data[name]=elem.text + @data[name] = elem.text end end @@ -304,40 +305,41 @@ class VmmAction xml.add_element(element) root end -end +end # The main class for the Sh driver class ExecDriver < VirtualMachineDriver + attr_reader :options # Initializes the VMM driver # @param [String] hypervisor name identifies the plugin # @param [OpenNebulaDriver::options] - def initialize(hypervisor, options={}) - @options={ + def initialize(hypervisor, options = {}) + @options = { :threaded => true }.merge!(options) if options[:shell] - @shell=options[:shell] + @shell = options[:shell] else - @shell='bash' + @shell = 'bash' end super("vmm/#{hypervisor}", @options) - @hypervisor = hypervisor + @hypervisor = hypervisor end # Creates an SshStream to execute commands on the target host # @param[String] the hostname of the host # @param[String] id of the VM to log messages # @return [SshStreamCommand] - def get_ssh_stream(aname, host, id) + def get_ssh_stream(_aname, host, id) SshStreamCommand.new(host, - @remote_scripts_base_path, - log_method(id), nil, @shell) + @remote_scripts_base_path, + log_method(id), nil, @shell) end #--------------------------------------------------------------------------- @@ -352,11 +354,11 @@ class ExecDriver < VirtualMachineDriver # ---------------------------------------------------------------------- # Initialization of deployment data # ---------------------------------------------------------------------- - local_dfile=action.data[:local_dfile] + local_dfile = action.data[:local_dfile] if !local_dfile || File.zero?(local_dfile) - send_message(ACTION[:deploy],RESULT[:failure],id, - "Cannot open deployment file #{local_dfile}") + send_message(ACTION[:deploy], RESULT[:failure], id, + "Cannot open deployment file #{local_dfile}") return end @@ -397,7 +399,7 @@ class ExecDriver < VirtualMachineDriver :driver => :vmm, :action => :deploy, :parameters => [dfile, :host], - :stdin => domain, + :stdin => domain }, # Execute post-boot networking setup { @@ -408,7 +410,7 @@ class ExecDriver < VirtualMachineDriver { :driver => :vmm, :action => :cancel, - :parameters => [:deploy_info, :host] + :parameters => %i[deploy_info host] } ] } @@ -421,62 +423,28 @@ class ExecDriver < VirtualMachineDriver # SHUTDOWN action, graceful shutdown and network clean up # def shutdown(id, drv_message) - - action = VmmAction.new(self, id, :shutdown, drv_message) - - steps=[ - # Shutdown the Virtual Machine - { - :driver => :vmm, - :action => :shutdown, - :parameters => [:deploy_id, :host] - }, - # Execute networking clean up operations - { - :driver => :vnm, - :action => :clean - } - ] - - action.run(steps) + destroy(id, drv_message, :shutdown) end # # CANCEL action, destroys a VM and network clean up # def cancel(id, drv_message) - action = VmmAction.new(self, id, :cancel, drv_message) - - steps=[ - # Cancel the Virtual Machine - { - :driver => :vmm, - :action => :cancel, - :parameters => [:deploy_id, :host] - }, - # Execute networking clean up operations - { - :driver => :vnm, - :action => :clean - } - ] - - action.run(steps) + destroy(id, drv_message, :cancel) end # # SAVE action, stops the VM and saves its state, network is cleaned up # def save(id, drv_message) - xml_data = decode(drv_message) action = VmmAction.new(self, id, :save, drv_message) - steps=[ + steps = [ # Save the Virtual Machine state { :driver => :vmm, :action => :save, - :parameters => [:deploy_id, :checkpoint_file, :host] + :parameters => %i[deploy_id checkpoint_file host] }, # Execute networking clean up operations { @@ -507,7 +475,7 @@ class ExecDriver < VirtualMachineDriver } end - action=VmmAction.new(self, id, :restore, drv_message) + action = VmmAction.new(self, id, :restore, drv_message) steps.concat([ # Execute pre-boot networking setup @@ -519,7 +487,7 @@ class ExecDriver < VirtualMachineDriver { :driver => :vmm, :action => :restore, - :parameters => [:checkpoint_file, :host, :deploy_id] + :parameters => %i[checkpoint_file host deploy_id] }, # Execute post-boot networking setup { @@ -530,9 +498,9 @@ class ExecDriver < VirtualMachineDriver { :driver => :vmm, :action => :cancel, - :parameters => [:deploy_id, :host] + :parameters => %i[deploy_id host] } - ], + ] } ]) @@ -544,15 +512,15 @@ class ExecDriver < VirtualMachineDriver # def migrate(id, drv_message) action = VmmAction.new(self, id, :migrate, drv_message) - pre = "PRE" - post = "POST" - failed = "FAIL" + pre = 'PRE' + post = 'POST' + failed = 'FAIL' - pre << action.data[:tm_command] << " " << action.data[:vm] - post << action.data[:tm_command] << " " << action.data[:vm] - failed << action.data[:tm_command] << " " << action.data[:vm] + pre << action.data[:tm_command] << ' ' << action.data[:vm] + post << action.data[:tm_command] << ' ' << action.data[:vm] + failed << action.data[:tm_command] << ' ' << action.data[:vm] - steps=[ + steps = [ # Execute a pre-migrate TM setup { :driver => :tm, @@ -569,7 +537,7 @@ class ExecDriver < VirtualMachineDriver { :driver => :vmm, :action => :migrate, - :parameters => [:deploy_id, :dest_host, :host], + :parameters => %i[deploy_id dest_host host], :fail_actions => [ { :driver => :tm, @@ -601,7 +569,7 @@ class ExecDriver < VirtualMachineDriver :action => :tm_postmigrate, :parameters => post.split, :no_fail => true - }, + } ] action.run(steps) @@ -617,33 +585,22 @@ class ExecDriver < VirtualMachineDriver host = data.elements['HOST'].text deploy_id = data.elements['DEPLOY_ID'].text - do_action("#{deploy_id} #{host}", id, host, ACTION[:poll], {:stdin => xml_data}) + do_action("#{deploy_id} #{host}", id, host, ACTION[:poll], + :stdin => xml_data) end # # REBOOT action, reboots a running VM # def reboot(id, drv_message) - xml_data = decode(drv_message) - - data = decode(drv_message) - host = data.elements['HOST'].text - deploy_id = data.elements['DEPLOY_ID'].text - - do_action("#{deploy_id} #{host}", id, host, ACTION[:reboot], {:stdin => xml_data}) + restart(id, drv_message, :reboot) end # # RESET action, resets a running VM # def reset(id, drv_message) - xml_data = decode(drv_message) - - data = decode(drv_message) - host = data.elements['HOST'].text - deploy_id = data.elements['DEPLOY_ID'].text - - do_action("#{deploy_id} #{host}", id, host, ACTION[:reset], {:stdin => xml_data}) + restart(id, drv_message, :reboot) end # @@ -654,10 +611,10 @@ class ExecDriver < VirtualMachineDriver xml_data = decode(drv_message) tm_command = ensure_xpath(xml_data, id, action, 'TM_COMMAND') || return - tm_rollback= xml_data.elements['TM_COMMAND_ROLLBACK'].text.strip + tm_rollback = xml_data.elements['TM_COMMAND_ROLLBACK'].text.strip target_xpath = "VM/TEMPLATE/DISK[ATTACH='YES']/TARGET" - target = ensure_xpath(xml_data, id, action, target_xpath) || return + target = ensure_xpath(xml_data, id, action, target_xpath) || return target_index = target.downcase[-1..-1].unpack('c').first - 97 @@ -675,11 +632,11 @@ class ExecDriver < VirtualMachineDriver :driver => :vmm, :action => :attach_disk, :parameters => [ - :deploy_id, - :disk_target_path, - target, - target_index, - drv_message + :deploy_id, + :disk_target_path, + target, + target_index, + drv_message ], :fail_actions => [ { @@ -704,7 +661,7 @@ class ExecDriver < VirtualMachineDriver tm_command = ensure_xpath(xml_data, id, action, 'TM_COMMAND') || return target_xpath = "VM/TEMPLATE/DISK[ATTACH='YES']/TARGET" - target = ensure_xpath(xml_data, id, action, target_xpath) || return + target = ensure_xpath(xml_data, id, action, target_xpath) || return target_index = target.downcase[-1..-1].unpack('c').first - 97 @@ -716,10 +673,10 @@ class ExecDriver < VirtualMachineDriver :driver => :vmm, :action => :detach_disk, :parameters => [ - :deploy_id, - :disk_target_path, - target, - target_index + :deploy_id, + :disk_target_path, + target, + target_index ] }, # Perform an EPILOG on the disk @@ -746,11 +703,11 @@ class ExecDriver < VirtualMachineDriver snap_id = xml_data.elements[snap_id_xpath].text.to_i do_action("#{deploy_id} #{snap_id}", - id, - host, - ACTION[:snapshot_create], - :script_name => "snapshot_create", - :stdin => xml_data) + id, + host, + ACTION[:snapshot_create], + :script_name => 'snapshot_create', + :stdin => xml_data) end # @@ -766,11 +723,11 @@ class ExecDriver < VirtualMachineDriver snapshot_name = xml_data.elements[snap_id_xpath].text do_action("#{deploy_id} #{snapshot_name}", - id, - host, - ACTION[:snapshot_revert], - :script_name => "snapshot_revert", - :stdin => xml_data) + id, + host, + ACTION[:snapshot_revert], + :script_name => 'snapshot_revert', + :stdin => xml_data) end # @@ -786,11 +743,11 @@ class ExecDriver < VirtualMachineDriver snapshot_name = xml_data.elements[snap_id_xpath].text do_action("#{deploy_id} #{snapshot_name}", - id, - host, - ACTION[:snapshot_delete], - :script_name => "snapshot_delete", - :stdin => xml_data) + id, + host, + ACTION[:snapshot_delete], + :script_name => 'snapshot_delete', + :stdin => xml_data) end # @@ -822,17 +779,18 @@ class ExecDriver < VirtualMachineDriver :driver => :vmm, :action => :resize_disk, :parameters => [ - :deploy_id, - disk_id, - size, - drv_message, - :host + :deploy_id, + disk_id, + size, + drv_message, + :host ] } ] action.run(steps) end + # # CLEANUP action, frees resources allocated in a host: VM and disk images # @@ -844,56 +802,60 @@ class ExecDriver < VirtualMachineDriver deploy_id = xml_data.elements['DEPLOY_ID'].text action = VmmAction.new(self, id, :cleanup, drv_message) - steps = Array.new + steps = [] # Cancel the VM at host (only if we have a valid deploy-id) if deploy_id && !deploy_id.empty? steps << - { - :driver => :vmm, - :action => :cancel, - :parameters => [:deploy_id, :host], - :no_fail => true - } + { + :driver => :vmm, + :action => :cancel, + :parameters => %i[deploy_id host], + :no_fail => true + } steps << - { - :driver => :vnm, - :action => :clean, - :no_fail => true - } + { + :driver => :vnm, + :action => :clean, + :no_fail => true + } end # Cancel the VM at the previous host (in case of migration) if mhost && !mhost.empty? steps << - { - :driver => :vmm, - :action => :cancel, - :parameters => [:deploy_id, :dest_host], - :destination => true, - :no_fail => true - } + { + :driver => :vmm, + :action => :cancel, + :parameters => %i[deploy_id dest_host], + :destination => true, + :no_fail => true + } steps << - { - :driver => :vnm, - :action => :clean, - :destination => true, - :no_fail => true - } + { + :driver => :vnm, + :action => :clean, + :destination => true, + :no_fail => true + } end # Cleans VM disk images and directory - tm_command.each_line { |tc| - tc.strip! + if tm_command + tm_command.each_line {|tc| + tc.strip! - steps << - { - :driver => :tm, - :action => :tm_delete, - :parameters => tc.split, - :no_fail => true - } if !tc.empty? - } if tm_command + next if tc.empty? + + steps << + { + :driver => :tm, + :action => :tm_delete, + :parameters => tc.split, + :no_fail => true + } + } + end action.run(steps) end @@ -936,22 +898,22 @@ class ExecDriver < VirtualMachineDriver mac = mac.text.strip target = target.text.strip vn_mad = vn_mad.text.strip - rescue + rescue StandardError send_message(action, RESULT[:failure], id, - "Missing VN_MAD, BRIDGE, TARGET or MAC in VM NIC") + 'Missing VN_MAD, BRIDGE, TARGET or MAC in VM NIC') return end model = xml_data.elements["#{base_tmpl}/MODEL"] - model = model.text if !model.nil? - model = model.strip if !model.nil? - model = "-" if model.nil? + model = model.text unless model.nil? + model = model.strip unless model.nil? + model = '-' if model.nil? action = VmmAction.new(self, id, :attach_nic, drv_message) if !nic_alias - steps=[ + steps = [ # Execute pre-attach networking setup { :driver => :vnm, @@ -978,7 +940,7 @@ class ExecDriver < VirtualMachineDriver } ] elsif nic_alias && external - steps=[ + steps = [ # Execute pre-attach networking setup { :driver => :vnm, @@ -1049,16 +1011,16 @@ class ExecDriver < VirtualMachineDriver begin mac = xml_data.elements["#{base_tmpl}/MAC"] mac = mac.text.strip - rescue + rescue StandardError send_message(action, RESULT[:failure], id, - "Error in #{ACTION[:detach_nic]}, MAC needed in NIC") + "Error in #{ACTION[:detach_nic]}, MAC needed in NIC") return end action = VmmAction.new(self, id, :detach_nic, drv_message) if !nic_alias - steps=[ + steps = [ # Detach the NIC { :driver => :vmm, @@ -1072,7 +1034,7 @@ class ExecDriver < VirtualMachineDriver } ] elsif nic_alias && external - steps=[ + steps = [ # Clean networking setup { :driver => :vnm, @@ -1117,12 +1079,12 @@ class ExecDriver < VirtualMachineDriver vmm_driver_path = 'VM/HISTORY_RECORDS/HISTORY/VM_MAD' tm_driver_path = "VM/TEMPLATE/DISK[DISK_SNAPSHOT_ACTIVE='YES']/TM_MAD" - vmm_driver = ensure_xpath(xml_data, id, action, vmm_driver_path)||return - tm_driver = ensure_xpath(xml_data, id, action, tm_driver_path) ||return + vmm_driver = ensure_xpath(xml_data, id, action, vmm_driver_path) || return + tm_driver = ensure_xpath(xml_data, id, action, tm_driver_path) || return if !LIVE_DISK_SNAPSHOTS.include?("#{vmm_driver}-#{tm_driver}") send_message(action, RESULT[:failure], id, - "Cannot perform a live #{action} operation") + "Cannot perform a live #{action} operation") return end @@ -1130,7 +1092,7 @@ class ExecDriver < VirtualMachineDriver tm_command = ensure_xpath(xml_data, id, action, 'TM_COMMAND') || return tm_command_split = tm_command.split - tm_command_split[0] += "_LIVE" + tm_command_split[0] += '_LIVE' action = VmmAction.new(self, id, :disk_snapshot_create, drv_message) @@ -1154,7 +1116,7 @@ class ExecDriver < VirtualMachineDriver action = VmmAction.new(self, id, :update_sg, drv_message) - steps=[ + steps = [ # Execute update networking action { :driver => :vnm, @@ -1166,19 +1128,48 @@ class ExecDriver < VirtualMachineDriver action.run(steps, sg_id) end -private + private def ensure_xpath(xml_data, id, action, xpath) - begin - value = xml_data.elements[xpath].text.strip - raise if value.empty? - value - rescue - send_message(action, RESULT[:failure], id, - "Cannot perform #{action}, expecting #{xpath}") - nil - end + value = xml_data.elements[xpath].text.strip + raise if value.empty? + + value + rescue StandardError + send_message(action, RESULT[:failure], id, + "Cannot perform #{action}, expecting #{xpath}") + nil end + + def restart(id, drv_message, signal) + data = decode(drv_message) + host = data.elements['HOST'].text + deploy_id = data.elements['DEPLOY_ID'].text + + do_action("#{deploy_id} #{host}", id, host, ACTION[signal], + :stdin => data) + end + + def destroy(id, drv_message, signal) + action = VmmAction.new(self, id, signal, drv_message) + + steps = [ + # Shutdown the Virtual Machine + { + :driver => :vmm, + :action => signal, + :parameters => %i[deploy_id host] + }, + # Execute networking clean up operations + { + :driver => :vnm, + :action => :clean + } + ] + + action.run(steps) + end + end ################################################################################ @@ -1194,12 +1185,12 @@ else end opts = GetoptLong.new( - [ '--retries', '-r', GetoptLong::OPTIONAL_ARGUMENT ], - [ '--threads', '-t', GetoptLong::OPTIONAL_ARGUMENT ], - [ '--local', '-l', GetoptLong::REQUIRED_ARGUMENT ], - [ '--shell', '-s', GetoptLong::REQUIRED_ARGUMENT ], - [ '--parallel', '-p', GetoptLong::NO_ARGUMENT ], - [ '--timeout', '-w', GetoptLong::OPTIONAL_ARGUMENT ] + ['--retries', '-r', GetoptLong::OPTIONAL_ARGUMENT], + ['--threads', '-t', GetoptLong::OPTIONAL_ARGUMENT], + ['--local', '-l', GetoptLong::REQUIRED_ARGUMENT], + ['--shell', '-s', GetoptLong::REQUIRED_ARGUMENT], + ['--parallel', '-p', GetoptLong::NO_ARGUMENT], + ['--timeout', '-w', GetoptLong::OPTIONAL_ARGUMENT] ) hypervisor = '' @@ -1213,21 +1204,21 @@ timeout = nil begin opts.each do |opt, arg| case opt - when '--retries' - retries = arg.to_i - when '--threads' - threads = arg.to_i - when '--local' - local_actions = OpenNebulaDriver.parse_actions_list(arg) - when '--shell' - shell = arg - when '--parallel' - single_host = false - when '--timeout' - timeout = arg.to_i + when '--retries' + retries = arg.to_i + when '--threads' + threads = arg.to_i + when '--local' + local_actions = OpenNebulaDriver.parse_actions_list(arg) + when '--shell' + shell = arg + when '--parallel' + single_host = false + when '--timeout' + timeout = arg.to_i end end -rescue Exception => e +rescue StandardError exit(-1) end @@ -1238,11 +1229,11 @@ else end exec_driver = ExecDriver.new(hypervisor, - :concurrency => threads, - :retries => retries, - :local_actions => local_actions, - :shell => shell, - :single_host => single_host, - :timeout => timeout) + :concurrency => threads, + :retries => retries, + :local_actions => local_actions, + :shell => shell, + :single_host => single_host, + :timeout => timeout) exec_driver.start_driver