Class: Y2Network::UdevRule
- Inherits:
-
Object
- Object
- Y2Network::UdevRule
- Defined in:
- src/lib/y2network/udev_rule.rb
Overview
Simple udev rule class
This class represents a network udev rule. The current implementation is quite simplistic, featuring a an API which is tailored to our needs.
Basically, udev rules are kept in two different files under /etc/udev/rules.d
:
- 70-persistent-net.rules ('net' group): rules to assign names to interfaces.
- 79-yast2-drivers.rules ('drivers' group): rules to assign drivers to interfaces.
This class offers a set of constructors to build different kinds of rules. See UdevRule.new_mac_based_rename, UdevRule.new_bus_id_based_rename and UdevRule.new_driver_assignment.
When it comes to write rules to the filesystem, we decided to offer different methods to write to each file. See UdevRule.write_net_rules and UdevRule.write_drivers_rules.
Instance Attribute Summary collapse
-
#parts ⇒ Array<UdevRulePart>
readonly
Parts of the udev rule.
Class Method Summary collapse
-
.all ⇒ Array<UdevRule>
Returns all persistent network rules.
-
.drivers_rules ⇒ Array<UdevRule>
Returns driver rules.
-
.find_for(device) ⇒ UdevRule
Returns the udev rule for a given device.
-
.naming_rules ⇒ Array<UdevRule>
Returns naming rules.
-
.new_bus_id_based_rename(name, bus_id, dev_port = nil) ⇒ Object
Helper method to create a rename rule based on the BUS ID.
-
.new_driver_assignment(modalias, driver_name) ⇒ UdevRule
Returns a module assignment rule.
-
.new_mac_based_rename(name, mac) ⇒ Object
Helper method to create a rename rule based on a MAC address.
-
.new_network_rule(parts = []) ⇒ UdevRule
Returns a network rule.
-
.reset_cache ⇒ Object
Clears rules cache map.
-
.write_drivers_rules(udev_rules) ⇒ Object
Writes drivers specific udev rules to the filesystem.
-
.write_net_rules(udev_rules) ⇒ Object
Writes udev rules to the filesystem.
Instance Method Summary collapse
-
#add_part(key, operator, value) ⇒ Object
Adds a part to the rule.
-
#bus_id ⇒ String?
Returns the BUS ID in the udev rule.
-
#dev_port ⇒ String?
Returns the device port in the udev rule.
-
#device ⇒ String?
Returns the device mentioned in the rule (if any).
-
#driver ⇒ String?
Returns the modalias.
-
#drivers ⇒ String?
Returns the drivers mentioned in the rule (if any).
-
#initialize(parts = []) ⇒ UdevRule
constructor
Constructor.
-
#mac ⇒ String?
Returns the MAC in the udev rule.
-
#original_modalias ⇒ String?
Returns the original modalias.
-
#part_by_key(key, operator = nil) ⇒ Object
Returns the part with the given key.
-
#part_value_for(key, operator = nil) ⇒ String?
Returns the value for a given part.
-
#rename_by_bus_id(name, bus_id_value, dev_port_value = nil) ⇒ Object
Convenience method which takes care of modifing the udev rule using the bus_id and the dev_port when needed as the naming mechanism.
-
#rename_by_mac(name, address) ⇒ Object
Convenience method which takes care of modifing the udev rule using the MAC address as the naming mechanism.
-
#replace_part(key, operator, value) ⇒ Object
Convenience method to replace a specific part by another one.
-
#to_s ⇒ String
Returns an string representation that can be used in a rules file.
Constructor Details
#initialize(parts = []) ⇒ UdevRule
Constructor
210 211 212 |
# File 'src/lib/y2network/udev_rule.rb', line 210 def initialize(parts = []) @parts = parts end |
Instance Attribute Details
#parts ⇒ Array<UdevRulePart> (readonly)
Returns Parts of the udev rule.
205 206 207 |
# File 'src/lib/y2network/udev_rule.rb', line 205 def parts @parts end |
Class Method Details
.all ⇒ Array<UdevRule>
Returns all persistent network rules
65 66 67 |
# File 'src/lib/y2network/udev_rule.rb', line 65 def all naming_rules + drivers_rules end |
.drivers_rules ⇒ Array<UdevRule>
Returns driver rules
79 80 81 |
# File 'src/lib/y2network/udev_rule.rb', line 79 def drivers_rules find_rules(:drivers) end |
.find_for(device) ⇒ UdevRule
Returns the udev rule for a given device
Only the naming rules are considered.
89 90 91 |
# File 'src/lib/y2network/udev_rule.rb', line 89 def find_for(device) naming_rules.find { |r| r.device == device } end |
.naming_rules ⇒ Array<UdevRule>
Returns naming rules
72 73 74 |
# File 'src/lib/y2network/udev_rule.rb', line 72 def naming_rules find_rules(:net) end |
.new_bus_id_based_rename(name, bus_id, dev_port = nil) ⇒ Object
Helper method to create a rename rule based on the BUS ID
117 118 119 120 121 122 |
# File 'src/lib/y2network/udev_rule.rb', line 117 def new_bus_id_based_rename(name, bus_id, dev_port = nil) parts = [UdevRulePart.new("KERNELS", "==", bus_id)] parts << UdevRulePart.new("ATTR{dev_port}", "==", dev_port) if dev_port parts << UdevRulePart.new("NAME", "=", name) new_network_rule(parts) end |
.new_driver_assignment(modalias, driver_name) ⇒ UdevRule
Returns a module assignment rule
148 149 150 151 152 153 154 |
# File 'src/lib/y2network/udev_rule.rb', line 148 def new_driver_assignment(modalias, driver_name) parts = [ UdevRulePart.new("ENV{MODALIAS}", "==", modalias), UdevRulePart.new("ENV{MODALIAS}", "=", driver_name) ] new(parts) end |
.new_mac_based_rename(name, mac) ⇒ Object
Helper method to create a rename rule based on a MAC address
97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'src/lib/y2network/udev_rule.rb', line 97 def new_mac_based_rename(name, mac) new_network_rule( [ # Guard to not try to rename everything with the same MAC address (e.g. vlan devices # inherit the MAC address from the underlying device). # FIXME: it won't work when using predictable network names (openSUSE) # UdevRulePart.new("KERNEL", "==", "eth*"), # The port number of a NIC where the ports share the same hardware device. UdevRulePart.new("ATTR{dev_id}", "==", "0x0"), UdevRulePart.new("ATTR{address}", "==", mac), UdevRulePart.new("NAME", "=", name) ] ) end |
.new_network_rule(parts = []) ⇒ UdevRule
Returns a network rule
The network rule includes some parts by default.
130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'src/lib/y2network/udev_rule.rb', line 130 def new_network_rule(parts = []) base_parts = [ UdevRulePart.new("SUBSYSTEM", "==", "net"), UdevRulePart.new("ACTION", "==", "add"), UdevRulePart.new("DRIVERS", "==", "?*"), # Ethernet devices # https://github.com/torvalds/linux/blob/bb7ba8069de933d69cb45dd0a5806b61033796a3/include/uapi/linux/if_arp.h#L31 # TODO: what about InfiniBand (it is type 32)? UdevRulePart.new("ATTR{type}", "==", "1") ] new(base_parts.concat(parts)) end |
.reset_cache ⇒ Object
Clears rules cache map
185 186 187 |
# File 'src/lib/y2network/udev_rule.rb', line 185 def reset_cache @all = nil end |
.write_drivers_rules(udev_rules) ⇒ Object
Writes drivers specific udev rules to the filesystem
Those rules that does not have an MODALIAS part will be ignored.
171 172 173 174 175 176 177 178 179 180 181 182 |
# File 'src/lib/y2network/udev_rule.rb', line 171 def write_drivers_rules(udev_rules) rules_hash = udev_rules.each_with_object({}) do |rule, hash| driver = rule.driver next unless driver hash[driver] = rule.parts.map(&:to_s) end Yast::SCR.Write(Yast::Path.new(".udev_persistent.drivers"), rules_hash) # Writes changes to the rules file Yast::SCR.Write(Yast::Path.new(".udev_persistent.nil"), []) Yast::SCR.UnmountAgent(Yast::Path.new(".udev_persistent")) end |
.write_net_rules(udev_rules) ⇒ Object
Writes udev rules to the filesystem
159 160 161 162 163 164 |
# File 'src/lib/y2network/udev_rule.rb', line 159 def write_net_rules(udev_rules) Yast::SCR.Write(Yast::Path.new(".udev_persistent.rules"), udev_rules.map(&:to_s)) # Writes changes to the rules file Yast::SCR.Write(Yast::Path.new(".udev_persistent.nil"), []) Yast::SCR.UnmountAgent(Yast::Path.new(".udev_persistent")) end |
Instance Method Details
#add_part(key, operator, value) ⇒ Object
Adds a part to the rule
219 220 221 |
# File 'src/lib/y2network/udev_rule.rb', line 219 def add_part(key, operator, value) @parts << UdevRulePart.new(key, operator, value) end |
#bus_id ⇒ String?
Returns the BUS ID in the udev rule
305 306 307 |
# File 'src/lib/y2network/udev_rule.rb', line 305 def bus_id part_value_for("KERNELS") end |
#dev_port ⇒ String?
Returns the device port in the udev rule
313 314 315 |
# File 'src/lib/y2network/udev_rule.rb', line 313 def dev_port part_value_for("ATTR{dev_port}") end |
#device ⇒ String?
Returns the device mentioned in the rule (if any)
320 321 322 |
# File 'src/lib/y2network/udev_rule.rb', line 320 def device part_value_for("NAME", "=") end |
#driver ⇒ String?
Returns the modalias
334 335 336 |
# File 'src/lib/y2network/udev_rule.rb', line 334 def driver part_value_for("ENV{MODALIAS}", "=") end |
#drivers ⇒ String?
Returns the drivers mentioned in the rule (if any)
341 342 343 |
# File 'src/lib/y2network/udev_rule.rb', line 341 def drivers part_value_for("DRIVERS", "==") end |
#mac ⇒ String?
Returns the MAC in the udev rule
254 255 256 |
# File 'src/lib/y2network/udev_rule.rb', line 254 def mac part_value_for("ATTR{address}") end |
#original_modalias ⇒ String?
Returns the original modalias
327 328 329 |
# File 'src/lib/y2network/udev_rule.rb', line 327 def original_modalias part_value_for("ENV{MODALIAS}", "==") end |
#part_by_key(key, operator = nil) ⇒ Object
Returns the part with the given key
234 235 236 |
# File 'src/lib/y2network/udev_rule.rb', line 234 def part_by_key(key, operator = nil) parts.find { |p| p.key == key && (operator.nil? || p.operator == operator) } end |
#part_value_for(key, operator = nil) ⇒ String?
Returns the value for a given part
243 244 245 246 247 248 |
# File 'src/lib/y2network/udev_rule.rb', line 243 def part_value_for(key, operator = nil) part = part_by_key(key, operator) return nil unless part part.value end |
#rename_by_bus_id(name, bus_id_value, dev_port_value = nil) ⇒ Object
Convenience method which takes care of modifing the udev rule using the bus_id and the dev_port when needed as the naming mechanism
289 290 291 292 293 294 295 296 297 298 299 |
# File 'src/lib/y2network/udev_rule.rb', line 289 def rename_by_bus_id(name, bus_id_value, dev_port_value = nil) parts.delete_if { |p| (p.dev_port? && dev_port_value.nil?) } part = part_by_key("ATTR{address}") part.key = "KERNELS" if part replace_part("KERNELS", "==", bus_id_value) if bus_id != bus_id_value replace_part("ATTR{dev_port}", "==", dev_port_value) if dev_port != dev_port_value ## Ensure the name is always at the end of the rule parts.delete_if(&:name?) add_part("NAME", "=", name) end |
#rename_by_mac(name, address) ⇒ Object
Convenience method which takes care of modifing the udev rule using the MAC address as the naming mechanism
276 277 278 279 280 281 282 283 284 285 |
# File 'src/lib/y2network/udev_rule.rb', line 276 def rename_by_mac(name, address) parts.delete_if(&:dev_port?) part = part_by_key("KERNELS") part.key = "ATTR{address}" if part replace_part("ATTR{address}", "==", address) if mac != address ## Ensure the name is always at the end of the rule parts.delete_if { |p| p.dev_port? || p.name? } add_part("NAME", "=", name) end |
#replace_part(key, operator, value) ⇒ Object
Convenience method to replace a specific part by another one. In case that there is no part to be replaced then a new part is added.
265 266 267 268 269 270 271 272 |
# File 'src/lib/y2network/udev_rule.rb', line 265 def replace_part(key, operator, value) part = part_by_key(key, operator) if part part.value = value else add_part(key, operator, value) end end |
#to_s ⇒ String
Returns an string representation that can be used in a rules file
226 227 228 |
# File 'src/lib/y2network/udev_rule.rb', line 226 def to_s parts.map(&:to_s).join(", ") end |