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

Includes:
Timeout
Included in:
Exporter::Tar, Exporter::Zfs, Zfs::Dataset, Zfs::PropertyReader, Zfs::PropertyState, Zfs::Stream, Zfs::ZpoolStatus
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



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

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

  attempts.times do |i|
    return [true, yield]
  rescue Exceptions::SystemCommandFailed => e
    log(:warn, "Attempt #{i + 1} of #{attempts} failed for '#{e.cmd}'")
    ret << e

    break if i == attempts - 1

    sleep(wait)
  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
# 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:



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

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