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

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

Instance Method Summary collapse

Instance Method Details

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

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) (defaults to: 3)

    number of attempts

  • wait (Integer) (defaults to: 5)

    time to wait after a failed attempt, in seconds

Yields:

  • the block to be called

Returns:

  • (true, any)

    return value

  • (false, Array)

    list of errors



89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/libosctl/utils/system.rb', line 89

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

  attempts.times do |i|
    begin
      return [true, yield]

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

      break if i == attempts - 1

      sleep(wait)
    end
  end

  [false, ret]
end

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

Parameters:

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

Options Hash (opts):

  • :valid_rcs (Array<Integer>, :all)

    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:



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
57
58
59
# 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|
    if opts[:input]
      io.write(opts[:input])
      io.close_write
    end

    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 != :all && !valid_rcs.include?($?.exitstatus))
    raise Exceptions::SystemCommandFailed.new(cmd, $?.exitstatus, out)
  end

  SystemCommandResult.new($?.exitstatus, out)
end

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

Parameters:

  • cmd (String)

    zfs command

  • opts (String)

    zfs options

  • component (String)

    zfs dataset

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

Options Hash (cmd_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:



72
73
74
# File 'lib/libosctl/utils/system.rb', line 72

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