Class: OsCtld::Group
Instance Attribute Summary collapse
Instance Method Summary
collapse
#define_assets
#acquire_manipulation_lock, #init_manipulable, #is_being_manipulated?, #manipulate, #manipulated_by, #release_manipulation_lock
Methods included from Lockable
#exclusively, included, #inclusively, #init_lock, #lock, #unlock
Constructor Details
#initialize(pool, name, load: true, config: nil, devices: true, root: false) ⇒ Group
Returns a new instance of Group.
14
15
16
17
18
19
20
21
22
23
24
25
|
# File 'lib/osctld/group.rb', line 14
def initialize(pool, name, load: true, config: nil, devices: true, root: false)
init_lock
init_manipulable
@pool = pool
@name = name
@root = root
@cgparams = nil
@devices = nil
@attrs = Attributes.new
load_config(config) if load
devices.init if load && devices
end
|
Instance Attribute Details
#attrs ⇒ Object
Returns the value of attribute attrs.
12
13
14
|
# File 'lib/osctld/group.rb', line 12
def attrs
@attrs
end
|
#cgparams ⇒ Object
Returns the value of attribute cgparams.
12
13
14
|
# File 'lib/osctld/group.rb', line 12
def cgparams
@cgparams
end
|
#devices ⇒ Object
Returns the value of attribute devices.
12
13
14
|
# File 'lib/osctld/group.rb', line 12
def devices
@devices
end
|
#name ⇒ Object
Returns the value of attribute name.
12
13
14
|
# File 'lib/osctld/group.rb', line 12
def name
@name
end
|
#pool ⇒ Object
Returns the value of attribute pool.
12
13
14
|
# File 'lib/osctld/group.rb', line 12
def pool
@pool
end
|
Instance Method Details
#abs_cgroup_path(subsystem) ⇒ Object
131
132
133
|
# File 'lib/osctld/group.rb', line 131
def abs_cgroup_path(subsystem)
CGroup.abs_cgroup_path(subsystem, cgroup_path)
end
|
#abs_full_cgroup_path(subsystem, user) ⇒ Object
135
136
137
|
# File 'lib/osctld/group.rb', line 135
def abs_full_cgroup_path(subsystem, user)
CGroup.abs_cgroup_path(subsystem, full_cgroup_path(user))
end
|
#any_container_running? ⇒ Boolean
Return ‘true` if any container from this or any descendant group is running.
240
241
242
243
244
245
246
247
248
|
# File 'lib/osctld/group.rb', line 240
def any_container_running?
groups = [self] + descendants
DB::Containers.get.each do |ct|
return true if ct.pool == pool && groups.include?(self) && ct.running?
end
false
end
|
#assets ⇒ Object
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
# File 'lib/osctld/group.rb', line 51
def assets
define_assets do |add|
add.file(
config_path,
desc: "osctld's group config",
user: 0,
group: 0,
mode: 0o400
)
users.each do |u|
add.directory(
userdir(u),
desc: "LXC path for #{u.name}:#{name}",
user: 0,
group: u.ugid,
mode: 0o751
)
end
devices.assets(add)
end
end
|
#cgroup_path ⇒ Object
115
116
117
118
119
120
121
122
123
124
125
|
# File 'lib/osctld/group.rb', line 115
def cgroup_path
if root?
path
else
File.join(
DB::Groups.root(pool).path,
*name.split('/').drop(1).map { |v| "group.#{v}" }
)
end
end
|
#children ⇒ Array<Group>
Return all groups that are direct descendants
188
189
190
191
192
193
194
195
196
197
198
199
200
|
# File 'lib/osctld/group.rb', line 188
def children
DB::Groups.get.select do |grp|
next if grp.pool != pool || grp.name == name
s = if root?
'/'
else
"#{name}/"
end
grp.name.start_with?(s) && grp.name[s.size..].index('/').nil?
end.sort! { |a, b| a.name <=> b.name }
end
|
#config_dir ⇒ Object
107
108
109
|
# File 'lib/osctld/group.rb', line 107
def config_dir
File.join(pool.conf_path, 'group', id)
end
|
#config_path ⇒ Object
111
112
113
|
# File 'lib/osctld/group.rb', line 111
def config_path
File.join(pool.conf_path, 'group', id, 'config.yml')
end
|
43
44
45
46
47
48
49
|
# File 'lib/osctld/group.rb', line 43
def configure(path: nil, devices: true)
@path = path if root?
@cgparams = CGroup::Params.new(self)
@devices = Devices::Manager.new_for(self)
@devices.init if devices
save_config
end
|
#containers ⇒ Object
226
227
228
229
230
231
232
233
234
235
236
|
# File 'lib/osctld/group.rb', line 226
def containers
ret = []
DB::Containers.get.each do |ct|
next if ct.pool != pool || ct.group != self || ret.include?(ct)
ret << ct
end
ret
end
|
#descendants ⇒ Array<Group>
Return all groups below the current group’s path
204
205
206
207
208
209
210
211
212
213
|
# File 'lib/osctld/group.rb', line 204
def descendants
groups = DB::Groups.get.select { |grp| grp.pool == pool }
if root?
groups.drop(1)
else
groups.select { |grp| grp.name.start_with?("#{name}/") }
end.sort! { |a, b| a.name <=> b.name }
end
|
#export ⇒ Object
316
317
318
319
320
321
322
323
324
325
326
327
328
|
# File 'lib/osctld/group.rb', line 316
def export
inclusively do
{
pool: pool.name,
name:,
path:,
full_path: cgroup_path,
cpu_limit: find_cpu_limit(parents: false),
memory_limit: find_memory_limit(parents: false),
swap_limit: find_swap_limit(parents: false)
}
end
end
|
#find_cpu_limit(parents: true) ⇒ Integer?
Returns CPU limit in percent (100 % for one CPU).
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
|
# File 'lib/osctld/group.rb', line 299
def find_cpu_limit(parents: true)
limit = cgparams.find_cpu_limit
if limit
return limit
elsif !parents
return
end
self.parents.each do |grp|
grp_limit = grp.find_cpu_limit(parents: true)
return grp_limit if grp_limit
end
nil
end
|
#find_memory_limit(parents: true) ⇒ Integer?
Returns memory limit in bytes.
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
|
# File 'lib/osctld/group.rb', line 263
def find_memory_limit(parents: true)
limit = cgparams.find_memory_limit
if limit
return limit
elsif !parents
return
end
self.parents.each do |grp|
grp_limit = grp.find_memory_limit(parents: true)
return grp_limit if grp_limit
end
nil
end
|
#find_swap_limit(parents: true) ⇒ Integer?
Returns swap limit in bytes.
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
|
# File 'lib/osctld/group.rb', line 281
def find_swap_limit(parents: true)
limit = cgparams.find_swap_limit
if limit
return limit
elsif !parents
return
end
self.parents.each do |grp|
grp_limit = grp.find_swap_limit(parents: true)
return grp_limit if grp_limit
end
nil
end
|
#full_cgroup_path(user) ⇒ Object
127
128
129
|
# File 'lib/osctld/group.rb', line 127
def full_cgroup_path(user)
File.join(cgroup_path, "user.#{user.name}")
end
|
#groups_in_path ⇒ Array<Group>
Return all groups leading to this group’s path, i.e. all parents and the group itself.
182
183
184
|
# File 'lib/osctld/group.rb', line 182
def groups_in_path
parents + [self]
end
|
#has_containers?(user = nil) ⇒ Boolean
216
217
218
219
220
221
222
223
224
|
# File 'lib/osctld/group.rb', line 216
def has_containers?(user = nil)
any_ct = DB::Containers.get.detect do |ct|
ct.pool.name == pool.name \
&& ct.group.name == name \
&& (user.nil? || ct.user.name == user.name)
end
any_ct ? true : false
end
|
#id ⇒ Object
27
28
29
|
# File 'lib/osctld/group.rb', line 27
def id
@name
end
|
#ident ⇒ Object
31
32
33
|
# File 'lib/osctld/group.rb', line 31
def ident
inclusively { "#{pool.name}:#{id}" }
end
|
#load_config(config = nil) ⇒ Object
358
359
360
361
362
363
364
365
366
367
368
369
|
# File 'lib/osctld/group.rb', line 358
def load_config(config = nil)
cfg = if config
OsCtl::Lib::ConfigFile.load_yaml(config)
else
OsCtl::Lib::ConfigFile.load_yaml_file(config_path)
end
@path = cfg['path'] if root?
@cgparams = CGroup::Params.load(self, cfg['cgparams'])
@devices = Devices::Manager.load(self, cfg['devices'] || [])
@attrs = Attributes.load(cfg['attrs'] || {})
end
|
#log_type ⇒ Object
330
331
332
|
# File 'lib/osctld/group.rb', line 330
def log_type
"group=#{pool.name}:#{name}"
end
|
#manipulation_resource ⇒ Object
334
335
336
|
# File 'lib/osctld/group.rb', line 334
def manipulation_resource
['group', "#{pool.name}:#{name}"]
end
|
#parent ⇒ Group?
Return the closest parent group
173
174
175
176
177
|
# File 'lib/osctld/group.rb', line 173
def parent
return if root?
parents.last
end
|
#parents ⇒ Array<Group>
Return all parent groups, from the root group to the closest parent
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
|
# File 'lib/osctld/group.rb', line 153
def parents
return [] if root?
ret = []
t = ''
name.split('/')[0..-2].each do |n|
t = File.join('/', t, n)
g = DB::Groups.by_path(pool, t)
raise GroupNotFound, "group '#{t}' not found" if g.nil?
ret << g
end
ret
end
|
#path ⇒ Object
39
40
41
|
# File 'lib/osctld/group.rb', line 39
def path
root? ? @path : File.join(DB::Groups.root(pool).path, name)
end
|
#root? ⇒ Boolean
35
36
37
|
# File 'lib/osctld/group.rb', line 35
def root?
@root
end
|
#save_config ⇒ Object
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
|
# File 'lib/osctld/group.rb', line 338
def save_config
FileUtils.mkdir_p(config_dir)
cfg = {
'cgparams' => cgparams.dump,
'devices' => devices.dump,
'attrs' => attrs.dump
}
cfg['path'] = path if root?
File.open(config_path, 'w', 0o400) do |f|
f.write(OsCtl::Lib::ConfigFile.dump_yaml(cfg))
end
File.chown(0, 0, config_path)
end
|
#set(opts) ⇒ Object
77
78
79
80
81
82
83
84
85
86
87
88
89
|
# File 'lib/osctld/group.rb', line 77
def set(opts)
opts.each do |k, v|
case k
when :attrs
attrs.update(v)
else
raise "unsupported option '#{k}'"
end
end
save_config
end
|
#setup_for?(user) ⇒ Boolean
147
148
149
|
# File 'lib/osctld/group.rb', line 147
def setup_for?(user)
Dir.exist?(userdir(user))
end
|
#unset(opts) ⇒ Object
93
94
95
96
97
98
99
100
101
102
103
104
105
|
# File 'lib/osctld/group.rb', line 93
def unset(opts)
opts.each do |k, v|
case k
when :attrs
v.each { |attr| attrs.unset(attr) }
else
raise "unsupported option '#{k}'"
end
end
save_config
end
|
#userdir(user) ⇒ Object
139
140
141
142
143
144
145
|
# File 'lib/osctld/group.rb', line 139
def userdir(user)
File.join(
user.userdir,
*name.split('/').drop(1).map { |v| "group.#{v}" },
'cts'
)
end
|
#users ⇒ Object
250
251
252
253
254
255
256
257
258
259
260
|
# File 'lib/osctld/group.rb', line 250
def users
ret = []
DB::Containers.get.each do |ct|
next if ct.pool != pool || ct.group != self || ret.include?(ct.user)
ret << ct.user
end
ret
end
|