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)


391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
# File 'lib/cute/taktuk.rb', line 391

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



577
578
579
580
581
582
583
# File 'lib/cute/taktuk.rb', line 577

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.



387
388
389
# File 'lib/cute/taktuk.rb', line 387

def args
  @args
end

#binaryObject

Returns the value of attribute binary.



386
387
388
# File 'lib/cute/taktuk.rb', line 386

def binary
  @binary
end

#commandsObject (readonly)

Returns the value of attribute commands.



387
388
389
# File 'lib/cute/taktuk.rb', line 387

def commands
  @commands
end

#exec_cmdObject (readonly)

Returns the value of attribute exec_cmd.



387
388
389
# File 'lib/cute/taktuk.rb', line 387

def exec_cmd
  @exec_cmd
end

#statusObject (readonly)

Returns the value of attribute status.



387
388
389
# File 'lib/cute/taktuk.rb', line 387

def status
  @status
end

#stderrObject (readonly)

Returns the value of attribute stderr.



387
388
389
# File 'lib/cute/taktuk.rb', line 387

def stderr
  @stderr
end

#stdoutObject (readonly)

Returns the value of attribute stdout.



387
388
389
# File 'lib/cute/taktuk.rb', line 387

def stdout
  @stdout
end

#streamsObject

Returns the value of attribute streams.



386
387
388
# File 'lib/cute/taktuk.rb', line 386

def streams
  @streams
end

Instance Method Details

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



572
573
574
575
# File 'lib/cute/taktuk.rb', line 572

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.



510
511
512
513
514
515
# File 'lib/cute/taktuk.rb', line 510

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



544
545
546
547
548
549
550
# File 'lib/cute/taktuk.rb', line 544

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

#free!Object Also known as: close



472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
# File 'lib/cute/taktuk.rb', line 472

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



564
565
566
567
568
569
# File 'lib/cute/taktuk.rb', line 564

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

#kill!Object



464
465
466
467
468
469
470
# File 'lib/cute/taktuk.rb', line 464

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.



457
458
459
460
461
462
# File 'lib/cute/taktuk.rb', line 457

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



525
526
527
528
529
530
531
# File 'lib/cute/taktuk.rb', line 525

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

#raw!(string) ⇒ Object



492
493
494
495
# File 'lib/cute/taktuk.rb', line 492

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

#run!(opts = {}) ⇒ Object



413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
# File 'lib/cute/taktuk.rb', line 413

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