Class: OsCtld::Devices::Manager
- Inherits:
-
Object
- Object
- OsCtld::Devices::Manager
- Defined in:
- lib/osctld/devices/manager.rb
Direct Known Subclasses
Instance Attribute Summary collapse
-
#devices ⇒ Object
readonly
protected
Returns the value of attribute devices.
-
#owner ⇒ Object
readonly
protected
Returns the value of attribute owner.
Class Method Summary collapse
Instance Method Summary collapse
-
#add(device, parent = nil) ⇒ Object
Add new device and ensure that parent groups provide it.
- #add_new(type, major, minor, mode, opts = {}) ⇒ Object
-
#apply(opts = {}) ⇒ Object
Configure devices in cgroup.
-
#check_availability!(device, group, mode: nil) ⇒ Object
Check whether the device is available in parent groups.
-
#check_descendants!(device, mode: nil) ⇒ Object
Check whether descendants do not have broader mode requirements.
-
#chmod(device, mode, opts = {}) ⇒ Hash
Changes.
- #clear ⇒ Object protected
- #detect(&block) ⇒ Object
- #do_add(device) ⇒ Object protected
- #do_allow_dev(device) ⇒ Object protected
- #do_apply_changes(changes, path: nil) ⇒ Object protected
- #do_deny_all ⇒ Object protected
- #do_deny_dev(device) ⇒ Object protected
-
#dump ⇒ Array<Hash>
Dump device configuration into the config.
- #dup(new_owner) ⇒ Object
- #each(&block) ⇒ Object
-
#export ⇒ Array<Hash>
Export devices to clients.
-
#find(type, major, minor) ⇒ Devices::Device?
Find device by `type` and `major` and `minor` numbers.
-
#get(device) ⇒ Devices::Device?
Find and return device.
-
#include?(device) ⇒ Boolean
Check if we have a particular device.
-
#inherit(device, opts = {}) ⇒ Object
Inherit device from a parent group.
-
#inherit_all_from(parent, opts = {}) ⇒ Object
Inherit all inheritable devices from parent group.
-
#inherit_promoted(device) ⇒ Object
Inherit a promoted device.
-
#init(opts = {}) ⇒ Object
Initialize device list.
-
#initialize(owner, devices: []) ⇒ Manager
constructor
A new instance of Manager.
-
#promote(device) ⇒ Object
Promote device, i.e.
-
#remove(device) ⇒ Object
Remove device from self.
-
#replace(new_devices) ⇒ Object
Replace configured devices by a new set.
- #select(&block) ⇒ Object
-
#set_inherit(device) ⇒ Object
Mark device as inheritable.
- #sync(&block) ⇒ Object protected
-
#unset_inherit(device) ⇒ Object
Remove inheritable mark.
-
#update_inherited_mode(device, mode, changes) ⇒ Object
Called when the access mode of the device in the parent group changes.
-
#used?(device) ⇒ Boolean
Check if device exists and is used, not just inherited.
Constructor Details
#initialize(owner, devices: []) ⇒ Manager
Returns a new instance of Manager.
9 10 11 12 13 |
# File 'lib/osctld/devices/manager.rb', line 9 def initialize(owner, devices: []) @owner = owner @devices = devices @cleared = false end |
Instance Attribute Details
#devices ⇒ Object (readonly, protected)
Returns the value of attribute devices.
291 292 293 |
# File 'lib/osctld/devices/manager.rb', line 291 def devices @devices end |
#owner ⇒ Object (readonly, protected)
Returns the value of attribute owner.
291 292 293 |
# File 'lib/osctld/devices/manager.rb', line 291 def owner @owner end |
Class Method Details
Instance Method Details
#add(device, parent = nil) ⇒ Object
Add new device and ensure that parent groups provide it
40 41 42 43 44 45 |
# File 'lib/osctld/devices/manager.rb', line 40 def add(device, parent = nil) sync do parent.devices.provide(device) if parent do_add(device) end end |
#add_new(type, major, minor, mode, opts = {}) ⇒ Object
33 34 35 |
# File 'lib/osctld/devices/manager.rb', line 33 def add_new(type, major, minor, mode, opts = {}) add(Devices::Device.new(type, major.to_s, minor.to_s, mode, opts)) end |
#apply(opts = {}) ⇒ Object
Configure devices in cgroup
131 132 133 134 135 136 |
# File 'lib/osctld/devices/manager.rb', line 131 def apply(opts = {}) sync do clear devices.each { |dev| do_allow_dev(dev) } end end |
#check_availability!(device, group, mode: nil) ⇒ Object
Check whether the device is available in parent groups
195 196 197 198 199 200 201 202 203 204 205 206 |
# File 'lib/osctld/devices/manager.rb', line 195 def check_availability!(device, group, mode: nil) sync do ([group] + group.parents.reverse).each do |grp| dev = grp.devices.detect { |v| v == device } raise DeviceNotAvailable.new(device, grp) unless dev unless dev.mode.compatible?(mode || device.mode) raise DeviceModeInsufficient.new(device, grp, dev.mode) end end end end |
#check_descendants!(device, mode: nil) ⇒ Object
Check whether descendants do not have broader mode requirements
209 210 211 |
# File 'lib/osctld/devices/manager.rb', line 209 def check_descendants!(device, mode: nil) raise NotImplementedError end |
#chmod(device, mode, opts = {}) ⇒ Hash
Returns changes.
78 79 80 81 82 83 84 85 86 |
# File 'lib/osctld/devices/manager.rb', line 78 def chmod(device, mode, opts = {}) sync do changes = device.chmod(mode) device.inherited = false if opts[:promote] && device.inherited? owner.save_config do_apply_changes(changes) end end |
#clear ⇒ Object (protected)
293 294 295 296 297 298 |
# File 'lib/osctld/devices/manager.rb', line 293 def clear return if @cleared do_deny_all @cleared = true end |
#detect(&block) ⇒ Object
261 262 263 |
# File 'lib/osctld/devices/manager.rb', line 261 def detect(&block) sync { devices.detect(&block) } end |
#do_add(device) ⇒ Object (protected)
343 344 345 |
# File 'lib/osctld/devices/manager.rb', line 343 def do_add(device) devices << device end |
#do_allow_dev(device) ⇒ Object (protected)
314 315 316 317 318 319 |
# File 'lib/osctld/devices/manager.rb', line 314 def do_allow_dev(device) CGroup.set_param( File.join(owner.abs_cgroup_path('devices'), 'devices.allow'), [device.to_s] ) end |
#do_apply_changes(changes, path: nil) ⇒ Object (protected)
323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 |
# File 'lib/osctld/devices/manager.rb', line 323 def do_apply_changes(changes, path: nil) path ||= owner.abs_cgroup_path('devices') changes.each do |action, value| case action when :allow CGroup.set_param( File.join(path, 'devices.allow'), [value] ) when :deny CGroup.set_param( File.join(path, 'devices.deny'), [value] ) end end end |
#do_deny_all ⇒ Object (protected)
300 301 302 303 304 305 |
# File 'lib/osctld/devices/manager.rb', line 300 def do_deny_all CGroup.set_param( File.join(owner.abs_cgroup_path('devices'), 'devices.deny'), ['a'] ) end |
#do_deny_dev(device) ⇒ Object (protected)
307 308 309 310 311 312 |
# File 'lib/osctld/devices/manager.rb', line 307 def do_deny_dev(device) CGroup.set_param( File.join(owner.abs_cgroup_path('devices'), 'devices.deny'), [device.to_s] ) end |
#dump ⇒ Array<Hash>
Dump device configuration into the config
277 278 279 |
# File 'lib/osctld/devices/manager.rb', line 277 def dump sync { devices.reject(&:inherited?).map { |dev| dev.dump } } end |
#dup(new_owner) ⇒ Object
281 282 283 284 285 286 287 288 |
# File 'lib/osctld/devices/manager.rb', line 281 def dup(new_owner) sync do ret = super() ret.instance_variable_set('@owner', new_owner) ret.instance_variable_set('@devices', devices.map(&:clone)) ret end end |
#each(&block) ⇒ Object
257 258 259 |
# File 'lib/osctld/devices/manager.rb', line 257 def each(&block) sync { devices.each(&block) } end |
#export ⇒ Array<Hash>
Export devices to clients
271 272 273 |
# File 'lib/osctld/devices/manager.rb', line 271 def export sync { devices.map { |dev| dev.export } } end |
#find(type, major, minor) ⇒ Devices::Device?
Find device by `type` and `major` and `minor` numbers
218 219 220 221 222 223 224 |
# File 'lib/osctld/devices/manager.rb', line 218 def find(type, major, minor) sync do devices.detect do |dev| dev.type == type && dev.major == major && dev.minor == minor end end end |
#get(device) ⇒ Devices::Device?
Find and return device
The point of this method is to return the manager's own device's instance. Devices equality is tested by comparing its type and major and minor numbers, but its devnode name or mode can be different.
232 233 234 235 236 237 |
# File 'lib/osctld/devices/manager.rb', line 232 def get(device) sync do i = devices.index(device) i ? devices[i] : nil end end |
#include?(device) ⇒ Boolean
Check if we have a particular device
242 243 244 |
# File 'lib/osctld/devices/manager.rb', line 242 def include?(device) sync { devices.include?(device) } end |
#inherit(device, opts = {}) ⇒ Object
Inherit device from a parent group
50 51 52 53 54 55 56 |
# File 'lib/osctld/devices/manager.rb', line 50 def inherit(device, opts = {}) sync do dev = device.clone dev.inherited = true do_add(dev) end end |
#inherit_all_from(parent, opts = {}) ⇒ Object
Inherit all inheritable devices from parent group
24 25 26 27 28 29 30 31 |
# File 'lib/osctld/devices/manager.rb', line 24 def inherit_all_from(parent, opts = {}) sync do parent.devices.each do |dev| next if !dev.inherit? || include?(dev) inherit(dev, opts) end end end |
#inherit_promoted(device) ⇒ Object
Inherit a promoted device
97 98 99 |
# File 'lib/osctld/devices/manager.rb', line 97 def inherit_promoted(device) raise NotImplementedError end |
#init(opts = {}) ⇒ Object
Initialize device list
17 18 19 |
# File 'lib/osctld/devices/manager.rb', line 17 def init(opts = {}) end |
#promote(device) ⇒ Object
Promote device, i.e. remove its inherited status and save it in config
90 91 92 93 |
# File 'lib/osctld/devices/manager.rb', line 90 def promote(device) device.inherited = false owner.save_config end |
#remove(device) ⇒ Object
Remove device from self
60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/osctld/devices/manager.rb', line 60 def remove(device) sync { devices.delete(device) } owner.save_config begin do_deny_dev(device) rescue CGroupFileNotFound # does not matter end end |
#replace(new_devices) ⇒ Object
Replace configured devices by a new set
`new_devices` has to contain devices that are to be promoted. Devices that were promoted but are no longer in `new_devices` will be removed. Devices that are inherited from parent groups are promoted if they're in `new_devices`, otherwire they're left alone.
Note that this method does not enforce nor manage proper parent/descendant dependencies. It is possible to add a device which is not provided by parents or to remove a device that is needed by descendants.
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 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 |
# File 'lib/osctld/devices/manager.rb', line 150 def replace(new_devices) sync do to_add = [] to_inherit = [] to_promote = [] to_chmod = [] # Find devices to promote, chmod and remove/inherit devices.each do |cur_dev| found = new_devices.detect { |new_dev| new_dev == cur_dev } if found.nil? to_inherit << cur_dev unless cur_dev.inherited? elsif found.inherited? if found.mode == cur_dev.mode to_promote << cur_dev else to_chmod << [cur_dev, found.mode] end elsif found.mode != cur_dev.mode to_chmod << [cur_dev, found.mode] end end # Find devices to add new_devices.each do |new_dev| found = devices.detect { |cur_dev| cur_dev == new_dev } to_add << new_dev if found.nil? end # Apply changes to_add.each { |dev| add(dev) } to_promote.each { |dev| promote(dev) } to_chmod.each do |dev, mode| chmod(dev, mode, promote: true, descendants: true, containers: true) end to_inherit.each { |dev| inherit_promoted(dev) } apply(descendants: true, containers: true) end end |
#select(&block) ⇒ Object
265 266 267 |
# File 'lib/osctld/devices/manager.rb', line 265 def select(&block) sync { devices.select(&block) } end |
#set_inherit(device) ⇒ Object
Mark device as inheritable
117 118 119 120 |
# File 'lib/osctld/devices/manager.rb', line 117 def set_inherit(device) device.inherit = true owner.save_config end |
#sync(&block) ⇒ Object (protected)
347 348 349 |
# File 'lib/osctld/devices/manager.rb', line 347 def sync(&block) Devices::Lock.sync(owner.pool, &block) end |
#unset_inherit(device) ⇒ Object
Remove inheritable mark
124 125 126 127 |
# File 'lib/osctld/devices/manager.rb', line 124 def unset_inherit(device) device.inherit = false owner.save_config end |
#update_inherited_mode(device, mode, changes) ⇒ Object
Called when the access mode of the device in the parent group changes
This method should update the mode and pass the information to its own descendants.
109 110 111 112 113 |
# File 'lib/osctld/devices/manager.rb', line 109 def update_inherited_mode(device, mode, changes) device.mode = mode owner.save_config do_apply_changes(changes) end |
#used?(device) ⇒ Boolean
Check if device exists and is used, not just inherited
249 250 251 252 253 254 255 |
# File 'lib/osctld/devices/manager.rb', line 249 def used?(device) sync do dev = devices.detect { |v| v == device } next(false) unless dev !dev.inherited? end end |