Class: OsCtl::Image::Operations::Builder::ControlledExec

Inherits:
OsCtl::Image::Operations::Base show all
Includes:
Lib::Utils::Log, Lib::Utils::System
Defined in:
lib/osctl/image/operations/builder/controlled_exec.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods inherited from OsCtl::Image::Operations::Base

run

Constructor Details

#initialize(builder, command, id: nil, client: nil) ⇒ ControlledExec

Returns a new instance of ControlledExec.

Parameters:

  • builder (Builder)
  • command (Array<String>)
  • id (nil, String) (defaults to: nil)

    optional run identifier

  • client (nil, OsCtldClient) (defaults to: nil)


20
21
22
23
24
25
26
# File 'lib/osctl/image/operations/builder/controlled_exec.rb', line 20

def initialize(builder, command, id: nil, client: nil)
  super()
  @builder = builder
  @command = command
  @id = id || SecureRandom.hex(10)
  @client = client || OsCtldClient.new
end

Instance Attribute Details

#builderBuilder (readonly)

Returns:



11
12
13
# File 'lib/osctl/image/operations/builder/controlled_exec.rb', line 11

def builder
  @builder
end

#clientObject (readonly, protected)

Returns the value of attribute client.



44
45
46
# File 'lib/osctl/image/operations/builder/controlled_exec.rb', line 44

def client
  @client
end

#commandArray<String> (readonly)

Returns:

  • (Array<String>)


14
15
16
# File 'lib/osctl/image/operations/builder/controlled_exec.rb', line 14

def command
  @command
end

#idObject (readonly, protected)

Returns the value of attribute id.



44
45
46
# File 'lib/osctl/image/operations/builder/controlled_exec.rb', line 44

def id
  @id
end

Instance Method Details

#cgroup_nameObject (protected)



92
93
94
# File 'lib/osctl/image/operations/builder/controlled_exec.rb', line 92

def cgroup_name
  "osctl-image.exec.#{id}"
end

#clear_cgroupObject (protected)



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
# File 'lib/osctl/image/operations/builder/controlled_exec.rb', line 56

def clear_cgroup
  cgroup = outer_cgroup_path

  unless Dir.exist?(cgroup)
    log(:info, 'cgroup not found, nothing to kill')
    return
  end

  log(:info, "clearing cgroup #{cgroup}")

  if kill_all(cgroup, 'TERM')
    sleep(5)
    kill_all(cgroup, 'KILL')
  end

  Dir.rmdir(cgroup)
rescue Errno::ENOENT
  # ignore
end

#executeInteger

Returns exit status.

Returns:

  • (Integer)

    exit status



29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/osctl/image/operations/builder/controlled_exec.rb', line 29

def execute
  begin
    rc = Operations::Builder::RunscriptFromString.run(
      builder,
      start_script
    )
  ensure
    clear_cgroup
  end

  rc || 1
end

#inner_cgroup_pathObject (protected)



96
97
98
99
100
101
102
# File 'lib/osctl/image/operations/builder/controlled_exec.rb', line 96

def inner_cgroup_path
  if OsCtl::Lib::CGroup.v2?
    File.join('/sys/fs/cgroup', cgroup_name)
  else
    File.join('/sys/fs/cgroup/systemd', cgroup_name)
  end
end

#kill_all(cgroup, signal) ⇒ Object (protected)



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
# File 'lib/osctl/image/operations/builder/controlled_exec.rb', line 76

def kill_all(cgroup, signal)
  killed = false

  File.open(File.join(cgroup, 'cgroup.procs'), 'r') do |f|
    f.each_line do |line|
      pid = line.strip.to_i

      log(:info, "kill -SIG#{signal} #{pid}")
      Process.kill(signal, pid)
      killed = true
    end
  end

  killed
end

#outer_cgroup_pathObject (protected)



104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# File 'lib/osctl/image/operations/builder/controlled_exec.rb', line 104

def outer_cgroup_path
  if OsCtl::Lib::CGroup.v2?
    File.join(
      '/sys/fs/cgroup',
      builder.attrs[:group_path],
      "lxc.payload.#{builder.ctid}",
      cgroup_name
    )
  else
    File.join(
      '/sys/fs/cgroup/systemd',
      builder.attrs[:group_path],
      "lxc.payload.#{builder.ctid}",
      cgroup_name
    )
  end
end

#start_scriptObject (protected)



46
47
48
49
50
51
52
53
54
# File 'lib/osctl/image/operations/builder/controlled_exec.rb', line 46

def start_script
  <<~EOF
    #!/bin/sh
    cgroup="#{inner_cgroup_path}"
    mkdir "$cgroup"
    echo $$ >> "$cgroup/cgroup.procs"
    exec #{command.join(' ')}
  EOF
end