Module: OsCtl::Lib::Utils::System

Includes:
Timeout
Included in:
Exporter::Tar, Exporter::Zfs, Zfs::Dataset, Zfs::Stream
Defined in:
lib/libosctl/utils/system.rb

Instance Method Summary collapse

Instance Method Details

#repeat_on_failure(attempts: 3, wait: 5) { ... } ⇒ Object

Attempt to run a block several times

Given block is run repeatedle until it either succeeds, or the number of attempts has been reached. The block is considered successful if it does not raise any exceptions. #repeat_on_failure makes another attempt at calling the block, if it raises Exceptions::SystemCommandFailed. Any other exception will cause an immediate failure.

Parameters:

  • attempts (Integer)

    number of attempts

  • wait (Integer)

    time to wait after a failed attempt, in seconds

Yields:

  • the block to be called



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/libosctl/utils/system.rb', line 73

def repeat_on_failure(attempts: 3, wait: 5)
  ret = []

  attempts.times do |i|
    begin
      return yield

    rescue Exceptions::SystemCommandFailed => err
      log(:warn, "Attempt #{i+1} of #{attempts} failed for '#{err.cmd}'")
      raise err if i == attempts - 1

      ret << err
      sleep(wait)
    end
  end

  ret
end

#syscmd(cmd, opts = {}) ⇒ Hash

Parameters:

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

Options Hash (opts):

  • :valid_rcs (Array<Integer>)

    valid exit codes

  • :stderr (Boolean)

    include stderr in output?

  • :timeout (Integer)

    in seconds

  • :on_timeout (Proc)
  • :input (String)

    data written to the process's stdin

  • :env (Hash)

    environment variables

Returns:

  • (Hash)


16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/libosctl/utils/system.rb', line 16

def syscmd(cmd, opts = {})
  valid_rcs = opts[:valid_rcs] || []
  stderr = opts[:stderr].nil? ? true : opts[:stderr]

  out = ""
  log(:work, cmd)

  IO.popen(
    opts[:env] || ENV,
    "exec #{cmd} #{stderr ? '2>&1' : '2> /dev/null'}",
    opts[:input] ? 'r+' : 'r'
  ) do |io|
    io.write(opts[:input]) if opts[:input]

    if opts[:timeout]
      begin
        timeout(opts[:timeout]) do
          out = io.read
        end

      rescue Timeout::Error
        if opts[:on_timeout]
          opts[:on_timeout].call(io)

        else
          Process.kill('TERM', io.pid)
          raise Exceptions::SystemCommandFailed.new(cmd, 1, '')
        end
      end

    else
      out = io.read
    end
  end

  if $?.exitstatus != 0 && !valid_rcs.include?($?.exitstatus)
    raise Exceptions::SystemCommandFailed.new(cmd, $?.exitstatus, out)
  end

  {output: out, exitstatus: $?.exitstatus}
end

#zfs(cmd, opts, component, cmd_opts = {}) ⇒ Object



58
59
60
# File 'lib/libosctl/utils/system.rb', line 58

def zfs(cmd, opts, component, cmd_opts = {})
  syscmd("zfs #{cmd} #{opts} #{component}", cmd_opts)
end