Class: OsCtld::Devices::ContainerManager
- Includes:
- OsCtl::Lib::Utils::Log
- Defined in:
- lib/osctld/devices/container_manager.rb
Instance Attribute Summary
Attributes inherited from Manager
Instance Method Summary collapse
- #abs_all_cgroup_paths ⇒ Array protected
-
#abs_ct_cgroup_paths ⇒ Array
protected
Returns a list of all absolute cgroup paths that need to be configured for this container, from the top down.
-
#abs_ct_chowned_cgroup_paths ⇒ Array
protected
Returns a list of the container's absolute cgroup paths that are to be chowned to the user.
-
#abs_group_cgroup_paths ⇒ Array
protected
Returns a list of absolute paths of the container's group cgroups.
-
#apply(_opts = {}) ⇒ Object
Apply the container's device cgroup settings.
- #apply_devices(devices, path) ⇒ Object protected
-
#check_all_available!(group = nil) ⇒ Object
Check that all devices are provided by parents, or raise an exception.
- #check_descendants!(*_) ⇒ Object
- #chmod(device, mode, opts = {}) ⇒ Object
- #clear_devices(path) ⇒ Object protected
-
#create ⇒ Object
Create cgroups and apply device settings.
-
#ensure_all ⇒ Object
Ensure that all required devices are provided by parent groups.
- #inherit_promoted(device) ⇒ Object
- #init(opts = {}) ⇒ Object
-
#prepare_cgroup(cgpath, create) ⇒ Boolean
protected
`true` if the cgroup exists or was created.
-
#rel_ct_cgroup_paths ⇒ Array
protected
Returns a list of all relative cgroup paths that need to be configured for this container, from the top down.
-
#rel_group_cgroup_paths ⇒ Array
protected
Returns a list of relative paths of the container's group cgroups.
-
#remove_missing ⇒ Object
Remove devices that aren't provided by the parent, or have insufficient access mode.
- #to_abs_paths(rel_paths) ⇒ Object protected
- #update_inherited_mode(device, mode, changes) ⇒ Object
Methods inherited from Manager
#add, #add_new, #check_availability!, #clear, #detect, #do_add, #do_allow_dev, #do_apply_changes, #do_deny_all, #do_deny_dev, #dump, #dup, #each, #export, #find, #get, #include?, #inherit, #inherit_all_from, #initialize, load, #promote, #remove, #replace, #select, #set_inherit, #sync, #unset_inherit, #used?
Constructor Details
This class inherits a constructor from OsCtld::Devices::Manager
Instance Method Details
#abs_all_cgroup_paths ⇒ Array (protected)
257 258 259 |
# File 'lib/osctld/devices/container_manager.rb', line 257 def abs_all_cgroup_paths abs_group_cgroup_paths + abs_ct_cgroup_paths end |
#abs_ct_cgroup_paths ⇒ Array (protected)
Returns a list of all absolute cgroup paths that need to be configured for this container, from the top down.
238 239 240 |
# File 'lib/osctld/devices/container_manager.rb', line 238 def abs_ct_cgroup_paths to_abs_paths(rel_ct_cgroup_paths) end |
#abs_ct_chowned_cgroup_paths ⇒ Array (protected)
Returns a list of the container's absolute cgroup paths that are to be chowned to the user.
245 246 247 248 249 250 251 252 253 254 |
# File 'lib/osctld/devices/container_manager.rb', line 245 def abs_ct_chowned_cgroup_paths to_abs_paths([ # <group>/<user>/<ct>/user-owned [ct.cgroup_path, true], # <group>/<user>/<ct>/user-owned/lxc.payload.<ct> [File.join(ct.cgroup_path, "lxc.payload.#{ct.id}"), false, ct.user.ugid, ct.gid_map.ns_to_host(0)], ]) end |
#abs_group_cgroup_paths ⇒ Array (protected)
Returns a list of absolute paths of the container's group cgroups
231 232 233 |
# File 'lib/osctld/devices/container_manager.rb', line 231 def abs_group_cgroup_paths to_abs_paths(rel_group_cgroup_paths) end |
#apply(_opts = {}) ⇒ Object
Apply the container's device cgroup settings
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
# File 'lib/osctld/devices/container_manager.rb', line 129 def apply(_opts = {}) sync do # group ct.group.devices.apply abs_group_cgroup_paths.each do |cgpath, req| next unless prepare_cgroup(cgpath, req) apply_devices(ct.group.devices, cgpath) end # container groups abs_ct_cgroup_paths.each do |cgpath, req| next unless prepare_cgroup(cgpath, req) apply_devices(self, cgpath) end end end |
#apply_devices(devices, path) ⇒ Object (protected)
183 184 185 186 187 |
# File 'lib/osctld/devices/container_manager.rb', line 183 def apply_devices(devices, path) devices.each do |dev| CGroup.set_param(File.join(path, 'devices.allow'), [dev.to_s]) end end |
#check_all_available!(group = nil) ⇒ Object
Check that all devices are provided by parents, or raise an exception
150 151 152 153 154 |
# File 'lib/osctld/devices/container_manager.rb', line 150 def check_all_available!(group = nil) sync do devices.each { |dev| check_availability!(dev, group || ct.group) } end end |
#check_descendants!(*_) ⇒ Object
174 175 176 |
# File 'lib/osctld/devices/container_manager.rb', line 174 def check_descendants!(*_) # Containers do not have any descendants end |
#chmod(device, mode, opts = {}) ⇒ Object
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 |
# File 'lib/osctld/devices/container_manager.rb', line 56 def chmod(device, mode, opts = {}) sync do # Parents if opts[:parents] dev = device.clone dev.mode = mode ct.group.devices.provide(dev) end # <group>/<user> if opts[:group_changes] # for recursive chmod from the group down abs_group_cgroup_paths.each do |cgpath, req| next unless prepare_cgroup(cgpath, req) do_apply_changes(opts[:group_changes], path: cgpath) end else # when chmodding the container itself abs_group_cgroup_paths.each do |cgpath, req| next unless prepare_cgroup(cgpath, req) apply_devices(ct.group.devices, cgpath) end end # Container cgroups changes = device.chmod(mode) device.inherited = false if opts[:promote] && device.inherited? ct.save_config abs_ct_cgroup_paths.each do |cgpath, req| next unless prepare_cgroup(cgpath, req) do_apply_changes(changes, path: cgpath) end end end |
#clear_devices(path) ⇒ Object (protected)
190 191 192 |
# File 'lib/osctld/devices/container_manager.rb', line 190 def clear_devices(path) CGroup.set_param(File.join(path, 'devices.deny'), ['a']) end |
#create ⇒ Object
Create cgroups and apply device settings
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 |
# File 'lib/osctld/devices/container_manager.rb', line 20 def create sync do rel_group_cgroup_paths.zip(abs_group_cgroup_paths).each do |rel, abs| next if !rel[1] || !abs[1] rel_path = rel[0] abs_path = abs[0] if CGroup.mkpath('devices', rel_path.split('/')) clear_devices(abs_path) apply_devices(ct.group.devices, abs_path) end end rel_ct_cgroup_paths.zip(abs_ct_cgroup_paths).each do |rel, abs| next if !rel[1] || !abs[1] rel_path = rel[0] abs_path = abs[0] if CGroup.mkpath('devices', rel_path.split('/')) clear_devices(abs_path) apply_devices(self, abs_path) end end abs_ct_chowned_cgroup_paths.each do |abs, req, uid, gid| next unless prepare_cgroup(abs, req) File.chown(uid || ct.user.ugid, gid || ct.user.ugid, abs) end end end |
#ensure_all ⇒ Object
Ensure that all required devices are provided by parent groups
157 158 159 160 161 |
# File 'lib/osctld/devices/container_manager.rb', line 157 def ensure_all sync do devices.each { |dev| ct.group.devices.provide(dev) } end end |
#inherit_promoted(device) ⇒ Object
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
# File 'lib/osctld/devices/container_manager.rb', line 92 def inherit_promoted(device) sync do pdev = ct.group.devices.get(device) if pdev.inherit? # We can keep the device and descendants unchanged device.inherited = true # Parent group can have broader access mode, so we need to expand it if device.mode != pdev.mode changes = device.chmod(pdev.mode.clone) abs_all_cgroup_paths.each do |cgpath, req| next unless prepare_cgroup(cgpath, req) do_apply_changes(changes, path: cgpath) end end ct.save_config return end # Parent does not provide the device, remove it remove(device) end end |
#init(opts = {}) ⇒ Object
9 10 11 12 13 14 15 16 17 |
# File 'lib/osctld/devices/container_manager.rb', line 9 def init(opts = {}) sync do super inherit_all_from(ct.group, opts) log(:info, ct, "Configuring cgroup #{ct.cgroup_path} for devices") create end end |
#prepare_cgroup(cgpath, create) ⇒ Boolean (protected)
Returns `true` if the cgroup exists or was created.
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 |
# File 'lib/osctld/devices/container_manager.rb', line 270 def prepare_cgroup(cgpath, create) exists = Dir.exist?(cgpath) if exists true elsif create begin Dir.mkdir(cgpath) rescue Errno::EEXIST true end # uid/gid is inherited from the parent cgroup st = File.stat(File.dirname(cgpath)) File.chown(st.uid, st.gid, cgpath) else false end end |
#rel_ct_cgroup_paths ⇒ Array (protected)
Returns a list of all relative cgroup paths that need to be configured for this container, from the top down.
The returned array contains pairs: `[String, Boolean]`. The `String` is the path itself, while the `Boolean` determines whether this path should be created. Paths that do not need to be created are configured only if they already exist. This is used only for the `./lxc.payload.<ct>` cgroup, which LXC wants to create by itself.
216 217 218 219 220 221 222 223 224 225 226 227 |
# File 'lib/osctld/devices/container_manager.rb', line 216 def rel_ct_cgroup_paths [ # <group>/<user>/<ct> [ct.base_cgroup_path, true], # <group>/<user>/<ct>/user-owned [ct.cgroup_path, true], # <group>/<user>/<ct>/user-owned/lxc.payload.<ct> [File.join(ct.cgroup_path, "lxc.payload.#{ct.id}"), false], ] end |
#rel_group_cgroup_paths ⇒ Array (protected)
Returns a list of relative paths of the container's group cgroups.
These cgroups share the settings of the container's group.
199 200 201 202 203 204 |
# File 'lib/osctld/devices/container_manager.rb', line 199 def rel_group_cgroup_paths [ # <group>/<user> [ct.group.full_cgroup_path(ct.user), true], ] end |
#remove_missing ⇒ Object
Remove devices that aren't provided by the parent, or have insufficient access mode
165 166 167 168 169 170 171 172 |
# File 'lib/osctld/devices/container_manager.rb', line 165 def remove_missing sync do devices.delete_if do |dev| pdev = ct.group.devices.get(dev) pdev.nil? || !pdev.mode.compatible?(dev.mode) end end end |
#to_abs_paths(rel_paths) ⇒ Object (protected)
261 262 263 264 265 |
# File 'lib/osctld/devices/container_manager.rb', line 261 def to_abs_paths(rel_paths) rel_paths.map do |path, req, *args| [File.join(CGroup::FS, CGroup.real_subsystem('devices'), path), req, *args] end end |
#update_inherited_mode(device, mode, changes) ⇒ Object
119 120 121 122 123 124 125 126 |
# File 'lib/osctld/devices/container_manager.rb', line 119 def update_inherited_mode(device, mode, changes) sync do abs_all_cgroup_paths.each do |cgpath, req| next unless prepare_cgroup(cgpath, req) do_apply_changes(changes, path: cgpath) end end end |