Class: OsCtld::CGroup::Params

Inherits:
Object
  • Object
show all
Includes:
OsCtl::Lib::Utils::Log, Lockable
Defined in:
lib/osctld/cgroup/params.rb

Direct Known Subclasses

ContainerParams

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Lockable

#exclusively, included, #inclusively, #init_lock, #lock, #unlock

Constructor Details

#initialize(owner, params: []) ⇒ Params

Returns a new instance of Params.

Parameters:



16
17
18
19
20
# File 'lib/osctld/cgroup/params.rb', line 16

def initialize(owner, params: [])
  init_lock
  @owner = owner
  @params = params
end

Instance Attribute Details

#ownerObject (readonly, protected)

Returns the value of attribute owner.



282
283
284
# File 'lib/osctld/cgroup/params.rb', line 282

def owner
  @owner
end

#paramsObject (readonly, protected)

Returns the value of attribute params.



282
283
284
# File 'lib/osctld/cgroup/params.rb', line 282

def params
  @params
end

Class Method Details

.load(owner, cfg) ⇒ Object

Load CGroup parameters from config



10
11
12
# File 'lib/osctld/cgroup/params.rb', line 10

def self.load(owner, cfg)
  new(owner, params: (cfg || []).map { |v| CGroup::Param.load(v) })
end

Instance Method Details

#apply(keep_going: false) {|subsystem| ... } ⇒ Object

Apply configured cgroup parameters into the system

Parameters:

  • keep_going (Boolean) (defaults to: false)

    skip parameters that do not exist

Yield Parameters:

  • subsystem (String)

    cgroup subsystem

Yield Returns:

  • (String)

    absolute path to the cgroup directory



119
120
121
# File 'lib/osctld/cgroup/params.rb', line 119

def apply(keep_going: false, &)
  apply_params_and_retry(usable_params, keep_going:, &)
end

#apply_params(param_list, keep_going: false) ⇒ Array<CGroup::Param> (protected)

Returns parameters that failed to set.

Parameters:

  • param_list (Array<CGroup::Param>)
  • keep_going (Boolean) (defaults to: false)

Returns:



291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
# File 'lib/osctld/cgroup/params.rb', line 291

def apply_params(param_list, keep_going: false)
  failed = []

  param_list.each do |p|
    path = File.join(yield(p.subsystem), p.name)

    begin
      failed << p unless CGroup.set_param(path, p.value)
    rescue CGroupFileNotFound
      raise unless keep_going

      log(
        :info,
        :cgroup,
        "Skip #{path}, group or parameter does not exist"
      )
      next
    end
  end

  failed
end

#apply_params_and_retry(param_list, keep_going: false) ⇒ Object (protected)



314
315
316
317
318
319
320
321
322
323
324
# File 'lib/osctld/cgroup/params.rb', line 314

def apply_params_and_retry(param_list, keep_going: false, &)
  failed = apply_params(
    param_list,
    keep_going:,
    &
  ).select { |p| p.name.start_with?('memory.') }

  return unless failed.any?

  apply_params(failed, keep_going:, &)
end

#detectObject



111
112
113
# File 'lib/osctld/cgroup/params.rb', line 111

def detect(&)
  params.detect(&)
end

#dumpObject

Dump params to config



268
269
270
# File 'lib/osctld/cgroup/params.rb', line 268

def dump
  params.select(&:persistent).map(&:dump)
end

#dup(new_owner) ⇒ Object



272
273
274
275
276
277
278
# File 'lib/osctld/cgroup/params.rb', line 272

def dup(new_owner)
  ret = super()
  ret.init_lock
  ret.instance_variable_set('@owner', new_owner)
  ret.instance_variable_set('@params', params.map(&:clone))
  ret
end

#eachObject



98
99
100
# File 'lib/osctld/cgroup/params.rb', line 98

def each(&)
  params.each(&)
end

#each_usableObject



107
108
109
# File 'lib/osctld/cgroup/params.rb', line 107

def each_usable(&)
  each_version(CGroup.version, &)
end

#each_version(version) ⇒ Object

Parameters:

  • version (1, 2)


103
104
105
# File 'lib/osctld/cgroup/params.rb', line 103

def each_version(version, &)
  params.select { |p| p.version == version }.each(&)
end

#find_cpu_limitInteger?

Find CPU limit

Returns:

  • (Integer, nil)

    CPU limit in percent (100 % for one CPU)



233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
# File 'lib/osctld/cgroup/params.rb', line 233

def find_cpu_limit
  if CGroup.v2?
    each_usable do |p|
      next if p.name != 'cpu.max'

      quota, period = p.value.last.split

      return nil if quota == 'max'

      return (quota.to_i / period.to_i) * 100
    end

    return nil
  end

  quota = nil
  period = nil

  each_usable do |p|
    if p.name == 'cpu.cfs_quota_us'
      quota = p.value.last.to_i
      return nil if quota == -1
    elsif p.name == 'cpu.cfs_period_us'
      period = p.value.last.to_i
    end

    if quota && period
      return (quota / period) * 100
    end
  end

  nil
end

#find_memory_limitInteger?

Find memory limit

Returns:

  • (Integer, nil)

    memory limit in bytes



165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/osctld/cgroup/params.rb', line 165

def find_memory_limit
  if CGroup.v2?
    each_usable do |p|
      next if p.name != 'memory.max'

      v = p.value.last.to_i
      return v > 0 ? v : nil
    end

    return nil
  end

  mem_limit = 0
  memsw_limit = 0

  each_usable do |p|
    if p.name == 'memory.limit_in_bytes'
      mem_limit = p.value.last.to_i
    elsif p.name == 'memory.memsw.limit_in_bytes'
      memsw_limit = p.value.last.to_i
    end

    break if mem_limit > 0 && memsw_limit > 0
  end

  if memsw_limit > 0 && memsw_limit < mem_limit
    memsw_limit
  elsif mem_limit > 0
    mem_limit
  end
end

#find_swap_limitInteger?

Find swap limit

Returns:

  • (Integer, nil)

    swap limit in bytes



199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
# File 'lib/osctld/cgroup/params.rb', line 199

def find_swap_limit
  if CGroup.v2?
    each_usable do |p|
      next if p.name != 'memory.swap.max'

      v = p.value.last.to_i
      return v > 0 ? v : nil
    end

    return nil
  end

  mem_limit = 0
  memsw_limit = 0

  each_usable do |p|
    if p.name == 'memory.limit_in_bytes'
      mem_limit = p.value.last.to_i
    elsif p.name == 'memory.memsw.limit_in_bytes'
      memsw_limit = p.value.last.to_i
    end

    break if mem_limit > 0 && memsw_limit > 0
  end

  if memsw_limit > 0 && memsw_limit < mem_limit
    memsw_limit
  elsif mem_limit > 0
    memsw_limit - mem_limit
  end
end

#import(new_params) ⇒ Object

Process params from the client and return internal representation. Invalid parameters raise an exception.



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/osctld/cgroup/params.rb', line 24

def import(new_params)
  new_params.map do |hash|
    p = CGroup::Param.import(hash)

    # Check parameter. We can verify it only when the same cgroup version
    # is used.
    if p.version == CGroup.version
      subsys = CGroup.real_subsystem(p.subsystem)
      path = CGroup.abs_cgroup_path(subsys)

      param = File.join(path, 'osctl', p.name)

      unless File.exist?(param)
        raise CGroupParameterNotFound, "CGroup parameter '#{param}' not found"
      end
    end

    p
  end
end

#replace(new_params, save: true) ⇒ Object

Replace all parameters by a new list of parameters

Parameters:

  • new_params (Array<CGroup::Param>)
  • save (Boolean) (defaults to: true)

    update the owner’s config file



126
127
128
129
130
131
132
133
134
135
136
137
# File 'lib/osctld/cgroup/params.rb', line 126

def replace(new_params, save: true, &)
  @params.each do |p|
    found = new_params.detect do |n|
      n.version == p.version && n.subsystem == p.subsystem && n.name == p.name
    end

    reset(p, true, &) unless found
  end

  @params = new_params
  owner.save_config if save
end

#reset(param, keep_going) {|subsystem| ... } ⇒ Object

Reset cgroup parameter to its initial/unlimited value.

Only a limited subset of cgroup parameters is supported.

Parameters:

Yield Parameters:

  • subsystem (String)

    cgroup subsystem

Yield Returns:

  • (String)

    absolute path to the cgroup directory



147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
# File 'lib/osctld/cgroup/params.rb', line 147

def reset(param, keep_going)
  v = reset_value(param)
  return unless v

  path = File.join(yield(param.subsystem), param.name)
  CGroup.set_param(path, v)
rescue CGroupFileNotFound
  raise unless keep_going

  log(
    :info,
    :cgroup,
    "Skip #{path}, group or parameter does not exist"
  )
end

#reset_value(param) ⇒ Object (protected)



326
327
328
329
330
331
332
333
334
335
336
337
# File 'lib/osctld/cgroup/params.rb', line 326

def reset_value(param)
  case param.name
  when 'cpu.cfs_quota_us', 'memory.limit_in_bytes', 'memory.memsw.limit_in_bytes'
    [-1]

  when 'cpu.max', 'memory.high', 'memory.max'
    ['max']

  when 'memory.min', 'memory.low'
    [0]
  end
end

#set(new_params, append: false, save: true) ⇒ Object



45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/osctld/cgroup/params.rb', line 45

def set(new_params, append: false, save: true)
  exclusively do
    new_params.each do |new_p|
      replaced = false

      params.map! do |p|
        if p.version == new_p.version \
           && p.subsystem == new_p.subsystem \
           && p.name == new_p.name
          replaced = true

          new_p.value = p.value + new_p.value if append
          new_p

        else
          p
        end
      end

      next if replaced

      params << new_p
    end
  end

  owner.save_config if save
end

#unset(del_params, save: true, reset: true, keep_going: false) {|subsystem| ... } ⇒ Object

Parameters:

  • save (Boolean) (defaults to: true)

    save config file

  • reset (Boolean) (defaults to: true)

    reset cgroup parameter value

  • keep_going (Boolean) (defaults to: false)

    skip parameters that do not exist

Yield Parameters:

  • subsystem (String)

    cgroup subsystem

Yield Returns:

  • (String)

    absolute path to the cgroup directory



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/osctld/cgroup/params.rb', line 78

def unset(del_params, save: true, reset: true, keep_going: false, &)
  exclusively do
    del_params.each do |del_h|
      del_p = CGroup::Param.import(del_h)

      params.delete_if do |p|
        del = p.version == del_p.version \
              && p.subsystem == del_p.subsystem \
              && p.name == del_p.name
        next(del) unless del

        reset(p, keep_going, &) if reset && p.version == CGroup.version
        true
      end
    end
  end

  owner.save_config if save
end

#usable_paramsObject (protected)



284
285
286
# File 'lib/osctld/cgroup/params.rb', line 284

def usable_params
  params.select { |p| p.version == CGroup.version }
end