Module: OsCtl::Cli::CGroupParams

Included in:
Container, Group, Top::Measurement, Tree
Defined in:
lib/osctl/cli/cgroup_params.rb

Constant Summary collapse

CGPARAM_FIELDS =
%i[
  version
  subsystem
  parameter
  value
  group
  abs_path
].freeze
CGPARAM_FILTERS =
%i[
  subsystem
].freeze
CGPARAM_DEFAULT_FIELDS =
%i[
  version
  parameter
  value
].freeze
CGPARAM_STATS =
%i[
  memory
  memory_pct
  kmemory
  cpu_us
  cpu_user_us
  cpu_system_us
  cpu_hz
  cpu_user_hz
  cpu_system_hz
  nproc
].freeze

Instance Method Summary collapse

Instance Method Details

#cg_add_raw_cgroup_params(data, path, params) ⇒ Hash, Array

Read and add cgroup parameters to ‘data`

#cg_init_subsystems must be called before this method can be used.

Parameters:

  • data (Hash, Array)

    hash/array to which the stats are added

  • path (String, Proc)

    path of the chosen group

  • params (Array)

    selected cgroup parameters

Returns:

  • (Hash, Array)

    data extended with cgroup params



328
329
330
331
332
333
334
335
336
337
338
339
340
# File 'lib/osctl/cli/cgroup_params.rb', line 328

def cg_add_raw_cgroup_params(data, path, params)
  if data.is_a?(::Hash)
    cg_reader = OsCtl::Lib::CGroup::PathReader.new(@cg_subsystems, path)
    data.update(cg_reader.read_params(params))
    data

  elsif data.is_a?(::Array)
    data.map do |v|
      cg_reader = OsCtl::Lib::CGroup::PathReader.new(@cg_subsystems, path.call(v))
      v.update(cg_reader.read_params(params))
    end
  end
end

#cg_add_stats(data, path, params, precise) ⇒ Hash, Array

Add runtime stats from CGroup parameters to ‘data`

#cg_init_subsystems must be called before this method can be used.

Parameters:

  • data (Hash, Array)

    hash/array to which the stats are added

  • path (String)

    path of the chosen group

  • params (Array)

    selected stat parameters

  • precise (Boolean)

    humanize parameter values?

Returns:

  • (Hash, Array)

    data extended with stats



293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
# File 'lib/osctl/cli/cgroup_params.rb', line 293

def cg_add_stats(data, path, params, precise)
  fields = CGPARAM_STATS & params

  if data.is_a?(::Hash)
    cg_reader = OsCtl::Lib::CGroup::PathReader.new(@cg_subsystems, path)

    data.update(cg_reader.read_stats(fields, precise))
    data

  elsif data.is_a?(::Array)
    data.map do |v|
      cg_reader = OsCtl::Lib::CGroup::PathReader.new(@cg_subsystems, path.call(v))
      v.update(cg_reader.read_stats(fields, precise))
    end
  end
end

#cg_init_subsystems(client) ⇒ Object

Parameters:



275
276
277
278
279
280
281
282
# File 'lib/osctl/cli/cgroup_params.rb', line 275

def cg_init_subsystems(client)
  @cg_subsystems ||= if OsCtl::Lib::CGroup.v2?
                       { nil => OsCtl::Lib::CGroup::FS }
                     else
                       client.cmd_data!(:group_cgsubsystems)
                     end
  nil
end

#cg_list_raw_cgroup_paramsArray<String>

Return a list of readable cgroup parameters from all subsystems

#cg_init_subsystems must be called before this method can be used.

Returns:

  • (Array<String>)


315
316
317
318
# File 'lib/osctl/cli/cgroup_params.rb', line 315

def cg_list_raw_cgroup_params
  cg_reader = OsCtl::Lib::CGroup::PathReader.new(@cg_subsystems, 'osctl')
  cg_reader.list_available_params
end

#do_cgparam_apply(cmd, cmd_opts) ⇒ Object



125
126
127
# File 'lib/osctl/cli/cgroup_params.rb', line 125

def do_cgparam_apply(cmd, cmd_opts)
  osctld_fmt(cmd, cmd_opts:)
end

#do_cgparam_list(cmd, cmd_opts) ⇒ Object



37
38
39
40
41
42
43
44
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/osctl/cli/cgroup_params.rb', line 37

def do_cgparam_list(cmd, cmd_opts)
  param_selector = OsCtl::Lib::Cli::ParameterSelector.new(
    all_params: CGPARAM_FIELDS,
    default_params: CGPARAM_DEFAULT_FIELDS
  )

  if opts[:list]
    puts param_selector
    return
  end

  fmt_opts = { layout: :columns }

  case opts[:version]
  when '1', '2'
    cmd_opts[:version] = opts[:version].to_i
  when 'all'
    # nothing to do
  else
    raise GLI::BadCommandLine, "invalid cgroup version '#{opts[:version]}'"
  end

  cmd_opts[:parameters] = args[1..] if args.count > 1
  cmd_opts[:subsystem] = opts[:subsystem].split(',') if opts[:subsystem]
  cmd_opts[:all] = true if opts[:all]
  fmt_opts[:header] = false if opts['hide-header']

  cols = param_selector.parse_option(opts[:output])

  if opts[:output].nil? && opts[:all]
    cols.insert(0, :group)
  end

  fmt_opts[:opts] = {
    value: {
      label: 'VALUE',
      align: 'right',
      display: proc do |values|
        values.map do |v|
          if gopts[:parsable] \
             || gopts[:json] \
             || (!v.is_a?(Integer) && /^\d+$/ !~ v)
            next v
          end

          humanize_data(v.to_i)
        end.join('; ')
      end
    }
  }

  fmt_opts[:cols] = cols

  osctld_fmt(
    cmd,
    cmd_opts:,
    fmt_opts:
  )
end

#do_cgparam_replace(cmd, cmd_opts) ⇒ Object



129
130
131
132
133
# File 'lib/osctl/cli/cgroup_params.rb', line 129

def do_cgparam_replace(cmd, cmd_opts)
  osctld_fmt(cmd, cmd_opts: cmd_opts.merge(
    parameters: JSON.parse($stdin.read)['parameters']
  ))
end

#do_cgparam_set(cmd, cmd_opts, params = nil) ⇒ Object



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
# File 'lib/osctl/cli/cgroup_params.rb', line 97

def do_cgparam_set(cmd, cmd_opts, params = nil)
  params ||= [{
    version: opts[:version],
    subsystem: parse_subsystem(args[1]),
    parameter: args[1],
    value: args[2..].map { |v| parse_data(v) }
  }.compact]

  cmd_opts.update({
    parameters: params,
    append: opts[:append]
  })

  osctld_fmt(cmd, cmd_opts:)
end

#do_cgparam_unset(cmd, cmd_opts, params = nil) ⇒ Object



113
114
115
116
117
118
119
120
121
122
123
# File 'lib/osctl/cli/cgroup_params.rb', line 113

def do_cgparam_unset(cmd, cmd_opts, params = nil)
  params ||= [{
    version: opts[:version],
    subsystem: parse_subsystem(args[1]),
    parameter: args[1]
  }.compact]

  cmd_opts.update(parameters: params)

  osctld_fmt(cmd, cmd_opts:)
end

#do_set_cpu_limit(cmd, cmd_opts) ⇒ Object



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/osctl/cli/cgroup_params.rb', line 135

def do_set_cpu_limit(cmd, cmd_opts)
  quota = args[1].to_f / 100 * opts[:period]

  params = [
    # cgroup v2
    {
      version: 2,
      subsystem: 'cpu',
      parameter: 'cpu.max',
      value: ["#{quota.round} #{opts[:period]}"]
    },
    # cgroup v1
    {
      version: 1,
      subsystem: 'cpu',
      parameter: 'cpu.cfs_period_us',
      value: [opts[:period]]
    },
    {
      version: 1,
      subsystem: 'cpu',
      parameter: 'cpu.cfs_quota_us',
      value: [quota.round]
    }
  ]

  do_cgparam_set(cmd, cmd_opts, params)
end

#do_set_memory(set_cmd, _unset_cmd, cmd_opts) ⇒ Object



188
189
190
191
192
193
194
195
196
197
198
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
230
231
232
233
234
235
236
237
238
239
240
241
242
243
# File 'lib/osctl/cli/cgroup_params.rb', line 188

def do_set_memory(set_cmd, _unset_cmd, cmd_opts)
  mem = parse_data(args[1])
  swap = parse_data(args[2]) if args[2]

  limits = []

  # cgroup v2
  limits << {
    version: 2,
    subsystem: 'memory',
    parameter: 'memory.max',
    value: [mem]
  }

  limits << if swap
              {
                version: 2,
                subsystem: 'memory',
                parameter: 'memory.swap.max',
                value: [swap]
              }
            else
              {
                version: 2,
                subsystem: 'memory',
                parameter: 'memory.swap.max',
                value: ['0']
              }
            end

  # cgroup v1
  limits << {
    version: 1,
    subsystem: 'memory',
    parameter: 'memory.limit_in_bytes',
    value: [mem]
  }

  limits << if swap
              {
                version: 1,
                subsystem: 'memory',
                parameter: 'memory.memsw.limit_in_bytes',
                value: [mem + swap]
              }
            else
              {
                version: 1,
                subsystem: 'memory',
                parameter: 'memory.memsw.limit_in_bytes',
                value: [mem]
              }
            end

  do_cgparam_set(set_cmd, cmd_opts, limits)
end

#do_unset_cpu_limit(unset_cmd, cmd_opts) ⇒ Object



164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
# File 'lib/osctl/cli/cgroup_params.rb', line 164

def do_unset_cpu_limit(unset_cmd, cmd_opts)
  params = [
    # cgroup v2
    {
      version: 2,
      subsystem: 'cpu',
      parameter: 'cpu.max'
    },
    # cgroup v1
    {
      version: 1,
      subsystem: 'cpu',
      parameter: 'cpu.cfs_period_us'
    },
    {
      version: 1,
      subsystem: 'cpu',
      parameter: 'cpu.cfs_quota_us'
    }
  ]

  do_cgparam_unset(unset_cmd, cmd_opts, params)
end

#do_unset_memory(unset_cmd, cmd_opts) ⇒ Object



245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
# File 'lib/osctl/cli/cgroup_params.rb', line 245

def do_unset_memory(unset_cmd, cmd_opts)
  params = [
    # cgroup v2
    {
      version: 2,
      subsystem: 'memory',
      parameter: 'memory.swap.max'
    },
    {
      version: 2,
      subsystem: 'memory',
      parameter: 'memory.max'
    },
    # cgroup v1
    {
      version: 1,
      subsystem: 'memory',
      parameter: 'memory.memsw.limit_in_bytes'
    },
    {
      version: 1,
      subsystem: 'memory',
      parameter: 'memory.limit_in_bytes'
    }
  ]

  do_cgparam_unset(unset_cmd, cmd_opts, params)
end

#parse_cgparamsObject (protected)



344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
# File 'lib/osctl/cli/cgroup_params.rb', line 344

def parse_cgparams
  opts[:cgparam].map do |v|
    parts = v.split('=')

    unless parts.count == 2
      raise "invalid cgparam '#{v}': expected <parameter>=<value>"
    end

    k, v = parts

    {
      subsystem: parse_subsystem(k),
      parameter: k,
      value: parse_data(v)
    }
  end
end

#parse_subsystem(param) ⇒ Object (protected)



362
363
364
# File 'lib/osctl/cli/cgroup_params.rb', line 362

def parse_subsystem(param)
  param.split('.').first
end