Class: Cute::TakTuk::TakTuk

Inherits:
Object
  • Object
show all
Defined in:
lib/cute/taktuk.rb

Overview

This class wraps the command TakTuk and generates automatically the long CLI options for taktuk command.

Constant Summary collapse

VALID_STREAMS =
[:output, :error, :status, :connector, :state, :info, :message, :taktuk ]

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(hostlist, options = {:connector => 'ssh'}) ⇒ TakTuk

Returns a new instance of TakTuk.

Raises:

  • (ArgumentError)


333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
# File 'lib/cute/taktuk.rb', line 333

def initialize(hostlist,options = {:connector => 'ssh'})
  raise ArgumentError.new("options parameter has to be a hash") unless options.is_a?(Hash)

  @binary = 'taktuk'
  @options = Options[options.merge({ :streams => [:output, :error, :status ]})] if options[:streams].nil?
  @options.merge!({:connector => 'ssh'}) if options[:connector].nil?
  @streams = Stream.new(@options[:streams])
  # @streams = Stream.new([:output,:error,:status, :state])

  @hostlist = Hostlist.new(hostlist)
  @commands = Commands.new

  @args = nil
  @stdout = nil
  @stderr = nil
  @status = nil

  @exec_cmd = nil
  @curthread = nil
  @connector = @options[:connector]
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(meth, *args) ⇒ Object



519
520
521
522
523
524
525
# File 'lib/cute/taktuk.rb', line 519

def method_missing(meth,*args)
  @commands << (meth.to_s.gsub(/_/,' ').strip.downcase)
  args.each do |arg|
    @commands.push(arg.strip.downcase)
  end
  self
end

Instance Attribute Details

#argsObject (readonly)

Returns the value of attribute args.



329
330
331
# File 'lib/cute/taktuk.rb', line 329

def args
  @args
end

#binaryObject

Returns the value of attribute binary.



328
329
330
# File 'lib/cute/taktuk.rb', line 328

def binary
  @binary
end

#commandsObject (readonly)

Returns the value of attribute commands.



329
330
331
# File 'lib/cute/taktuk.rb', line 329

def commands
  @commands
end

#exec_cmdObject (readonly)

Returns the value of attribute exec_cmd.



329
330
331
# File 'lib/cute/taktuk.rb', line 329

def exec_cmd
  @exec_cmd
end

#statusObject (readonly)

Returns the value of attribute status.



329
330
331
# File 'lib/cute/taktuk.rb', line 329

def status
  @status
end

#stderrObject (readonly)

Returns the value of attribute stderr.



329
330
331
# File 'lib/cute/taktuk.rb', line 329

def stderr
  @stderr
end

#stdoutObject (readonly)

Returns the value of attribute stdout.



329
330
331
# File 'lib/cute/taktuk.rb', line 329

def stdout
  @stdout
end

#streamsObject

Returns the value of attribute streams.



328
329
330
# File 'lib/cute/taktuk.rb', line 328

def streams
  @streams
end

Instance Method Details

#[](command, prefix = '[', suffix = ']') ⇒ Object



514
515
516
517
# File 'lib/cute/taktuk.rb', line 514

def [](command,prefix='[',suffix=']')
  @commands << "#{prefix} #{command} #{suffix}"
  self
end

#exec(cmd) ⇒ Object

It executes a command on multiple hosts. All output is printed via stdout and stderr. Note that this method returns immediately, and requires a call to the loop method in order for the command to actually execute. The execution is done by TakTuk using broadcast exec.

Example

tak.exec("hostname")
tak.exec("mkdir ~/test")
tak.loop() # to trigger the execution of commands

Parameters:

  • cmd (String)

    Command to execute.



452
453
454
455
456
457
# File 'lib/cute/taktuk.rb', line 452

def exec(cmd)
  mode = "broadcast"
  @commands << "#{mode} exec"
  @commands << "[ #{cmd} ]"
  @commands << ';' # TakTuk command separator
end

#exec!(cmd) ⇒ Hash

It executes a command on multiple hosts capturing the output, and other information related with the execution. It blocks until the command finishes.

Example

tak.exec!("uname -r") #=> {"node2"=>{:output=>"3.2.0-4-amd64", :status=>0}, "node3"=>{:output=>"3.2.0-4-amd64", :status=>0}, ...}

Parameters:

  • cmd (String)

    Command to be executed

Returns:

  • (Hash)

    Result data structure



486
487
488
489
490
491
492
# File 'lib/cute/taktuk.rb', line 486

def exec!(cmd)
  loop() unless @commands.empty?
  exec(cmd)
  results = run!()
  @commands = Commands.new
  return results
end

#free!Object Also known as: close



414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
# File 'lib/cute/taktuk.rb', line 414

def free!()
  @binary = nil
  @options = nil
  # if @streams
  #   @streams.each_value do |stream|
  #     stream.free if stream
  #     stream = nil
  #   end
  # end
  @hostlist.free if @hostlist
  @hostlist = nil
  @commands = nil
  @args = nil
  @stdout = nil
  @stderr = nil
  @status = nil
  @exec = nil
  @curthread = nil
end

#input(opts = {}) ⇒ Object

Manages the taktuk command input

Example

tak.exec("wc -w")
tak.input(:data => "data data data data")

tak.exec("tar xvf -")
tak.input(:file => "test_file.tar")

Parameters:

  • opts (Hash) (defaults to: {})

    Options for the type of data

Options Hash (opts):

  • :data (String)

    Raw data to be used as the input of a command

  • :filename (String)

    a file to be used as the input of a command



506
507
508
509
510
511
# File 'lib/cute/taktuk.rb', line 506

def input(opts = {})
  mode = "broadcast"
  @commands << "#{mode} input #{opts.keys.first.to_s}"
  @commands << "[ #{opts.values.first} ]"
  @commands << ';'
end

#kill!Object



406
407
408
409
410
411
412
# File 'lib/cute/taktuk.rb', line 406

def kill!()
  unless @exec.nil?
    @exec.kill
    @exec = nil
  end
  free!()
end

#loopObject

It executes the commands so far stored in the @commands variable and reinitialize the variable for post utilization.



399
400
401
402
403
404
# File 'lib/cute/taktuk.rb', line 399

def loop ()
  run!()
  $stdout.print(@stdout)
  $stderr.print(@stderr)
  @commands = Commands.new
end

#put(source, dest) ⇒ Object

It transfers a file to all the machines in parallel.

Example

tak.put("hosts.allow_template", "/etc/hosts.allow")

Parameters:

  • source (String)

    Source path for the file to be transfer

  • dest (String)

    Destination path for the file to be transfer



467
468
469
470
471
472
473
# File 'lib/cute/taktuk.rb', line 467

def put(source,dest)
  mode = "broadcast"
  @commands << "#{mode} put"
  @commands << "[ #{source} ]"
  @commands << "[ #{dest} ]"
  @commands << ';' # TakTuk command separator
end

#raw!(string) ⇒ Object



434
435
436
437
# File 'lib/cute/taktuk.rb', line 434

def raw!(string)
  @commands << string.strip
  self
end

#run!(opts = {}) ⇒ Object



355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
# File 'lib/cute/taktuk.rb', line 355

def run!(opts = {})
  @curthread = Thread.current
  @args = []
  @args += @options.to_cmd

  @streams.types.each{ |name|
    @args << '-o'
    @args << "#{name.to_s}=#{@streams.to_cmd}"
  }

  connector = build_connector
  @args += ["--connector", "#{connector}"] unless connector.nil?

  @args += @hostlist.to_cmd
  @args += @commands.to_cmd

  hosts = @hostlist.to_a
  outputs_size = opts[:outputs_size] || 0
  @exec_cmd = Cute::Execute[@binary,*@args].run!(
                                       :stdout_size => outputs_size * hosts.size,
                                       :stderr_size => outputs_size * hosts.size,
                                       :stdin => false
                                          )
  @status, @stdout, @stderr, emptypipes = @exec_cmd.wait({:checkstatus=>false})

  unless @status.success?
    @curthread = nil
    return false
  end

  unless emptypipes
    @curthread = nil
    @stderr = "Too much data on the TakTuk command's stdout/stderr"
    return false
  end

  results = @streams.parse(@stdout)
  @curthread = nil

  results
end