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) { ... } ⇒ 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



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

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 = {}) ⇒ 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