Merge pull request #20 from olysonek/udev_pr
Implement udev-based device matching
This commit is contained in:
commit
f775a3cab0
17 changed files with 86 additions and 10 deletions
|
|
@ -24,6 +24,7 @@ class Application(object):
|
|||
monitors_repository = monitors.Repository()
|
||||
hardware_inventory = hardware.Inventory()
|
||||
device_matcher = hardware.DeviceMatcher()
|
||||
device_matcher_udev = hardware.DeviceMatcherUdev()
|
||||
plugin_instance_factory = plugins.instance.Factory()
|
||||
self.variables = profiles.variables.Variables()
|
||||
|
||||
|
|
@ -33,7 +34,8 @@ class Application(object):
|
|||
else:
|
||||
log.info("dynamic tuning is globally disabled")
|
||||
|
||||
plugins_repository = plugins.Repository(monitors_repository, storage_factory, hardware_inventory, device_matcher, plugin_instance_factory, self.config, self.variables)
|
||||
plugins_repository = plugins.Repository(monitors_repository, storage_factory, hardware_inventory,\
|
||||
device_matcher, device_matcher_udev, plugin_instance_factory, self.config, self.variables)
|
||||
def_instance_priority = int(self.config.get(consts.CFG_DEFAULT_INSTANCE_PRIORITY, consts.CFG_DEF_DEFAULT_INSTANCE_PRIORITY))
|
||||
unit_manager = units.Manager(plugins_repository, monitors_repository, def_instance_priority)
|
||||
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ class GuiPluginLoader(PluginLoader):
|
|||
monitors_repository = monitors.Repository()
|
||||
hardware_inventory = hardware.Inventory()
|
||||
device_matcher = hardware.DeviceMatcher()
|
||||
device_matcher_udev = hardware.DeviceMatcherUdev()
|
||||
plugin_instance_factory = plugins.instance.Factory()
|
||||
|
||||
self.repo = repository.Repository(
|
||||
|
|
@ -78,6 +79,7 @@ class GuiPluginLoader(PluginLoader):
|
|||
storage_factory,
|
||||
hardware_inventory,
|
||||
device_matcher,
|
||||
device_matcher_udev,
|
||||
plugin_instance_factory,
|
||||
None,
|
||||
None
|
||||
|
|
|
|||
|
|
@ -1,2 +1,3 @@
|
|||
from inventory import *
|
||||
from device_matcher import *
|
||||
from device_matcher_udev import *
|
||||
|
|
|
|||
18
tuned/hardware/device_matcher_udev.py
Normal file
18
tuned/hardware/device_matcher_udev.py
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
import device_matcher
|
||||
import re
|
||||
|
||||
__all__ = ["DeviceMatcherUdev"]
|
||||
|
||||
class DeviceMatcherUdev(device_matcher.DeviceMatcher):
|
||||
def match(self, regex, device):
|
||||
"""
|
||||
Match a device against the udev regex in tuning profiles.
|
||||
|
||||
device is a pyudev.Device object
|
||||
"""
|
||||
|
||||
properties = ''
|
||||
for key, val in device.items():
|
||||
properties += key + '=' + val + '\n'
|
||||
|
||||
return re.search(regex, properties, re.MULTILINE) is not None
|
||||
|
|
@ -28,6 +28,10 @@ class Inventory(object):
|
|||
|
||||
self._subscriptions = {}
|
||||
|
||||
def get_device(self, subsystem, sys_name):
|
||||
"""Get a pyudev.Device object for the sys_name (e.g. 'sda')."""
|
||||
return pyudev.Devices.from_name(self._udev_context, subsystem, sys_name)
|
||||
|
||||
def get_devices(self, subsystem):
|
||||
"""Get list of devices on a given subsystem."""
|
||||
return self._udev_context.list_devices(subsystem=subsystem)
|
||||
|
|
|
|||
|
|
@ -17,13 +17,14 @@ class Plugin(object):
|
|||
Intentionally a lot of logic is included in the plugin to increase plugin flexibility.
|
||||
"""
|
||||
|
||||
def __init__(self, monitors_repository, storage_factory, hardware_inventory, device_matcher, instance_factory, global_cfg, variables):
|
||||
def __init__(self, monitors_repository, storage_factory, hardware_inventory, device_matcher, device_matcher_udev, instance_factory, global_cfg, variables):
|
||||
"""Plugin constructor."""
|
||||
|
||||
self._storage = storage_factory.create(self.__class__.__name__)
|
||||
self._monitors_repository = monitors_repository
|
||||
self._hardware_inventory = hardware_inventory
|
||||
self._device_matcher = device_matcher
|
||||
self._device_matcher_udev = device_matcher_udev
|
||||
self._instance_factory = instance_factory
|
||||
|
||||
self._instances = collections.OrderedDict()
|
||||
|
|
@ -80,13 +81,13 @@ class Plugin(object):
|
|||
# Interface for manipulation with instances of the plugin.
|
||||
#
|
||||
|
||||
def create_instance(self, name, devices_expression, options):
|
||||
def create_instance(self, name, devices_expression, devices_udev_regex, options):
|
||||
"""Create new instance of the plugin and seize the devices."""
|
||||
if name in self._instances:
|
||||
raise Exception("Plugin instance with name '%s' already exists." % name)
|
||||
|
||||
effective_options = self._get_effective_options(options)
|
||||
instance = self._instance_factory.create(self, name, devices_expression, effective_options)
|
||||
instance = self._instance_factory.create(self, name, devices_expression, devices_udev_regex, effective_options)
|
||||
self._instances[name] = instance
|
||||
|
||||
return instance
|
||||
|
|
@ -133,8 +134,21 @@ class Plugin(object):
|
|||
self._assigned_devices = set()
|
||||
self._free_devices = set()
|
||||
|
||||
def _get_device_objects(self, devices):
|
||||
"""Override this in a subclass to transform a list of device names (e.g. ['sda'])
|
||||
to a list of pyudev.Device objects, if your plugin supports it"""
|
||||
return None
|
||||
|
||||
def _get_matching_devices(self, instance, devices):
|
||||
return set(self._device_matcher.match_list(instance.devices_expression, devices))
|
||||
if instance.devices_udev_regex is None:
|
||||
return set(self._device_matcher.match_list(instance.devices_expression, devices))
|
||||
else:
|
||||
udev_devices = self._get_device_objects(devices)
|
||||
if udev_devices is None:
|
||||
log.error("Plugin '%s' does not support the 'devices_udev_regex' option", self.name)
|
||||
return set()
|
||||
udev_devices = self._device_matcher_udev.match_list(instance.devices_udev_regex, udev_devices)
|
||||
return set(map(lambda x: x.sys_name, udev_devices))
|
||||
|
||||
def assign_free_devices(self, instance):
|
||||
if not self._devices_supported:
|
||||
|
|
|
|||
|
|
@ -2,10 +2,11 @@ class Instance(object):
|
|||
"""
|
||||
"""
|
||||
|
||||
def __init__(self, plugin, name, devices_expression, options):
|
||||
def __init__(self, plugin, name, devices_expression, devices_udev_regex, options):
|
||||
self._plugin = plugin
|
||||
self._name = name
|
||||
self._devices_expression = devices_expression
|
||||
self._devices_udev_regex = devices_udev_regex
|
||||
self._options = options
|
||||
|
||||
self._active = True
|
||||
|
|
@ -40,6 +41,10 @@ class Instance(object):
|
|||
def devices(self):
|
||||
return self._devices
|
||||
|
||||
@property
|
||||
def devices_udev_regex(self):
|
||||
return self._devices_udev_regex
|
||||
|
||||
@property
|
||||
def options(self):
|
||||
return self._options
|
||||
|
|
|
|||
|
|
@ -40,6 +40,9 @@ class CPULatencyPlugin(base.Plugin):
|
|||
|
||||
self._assigned_devices = set()
|
||||
|
||||
def _get_device_objects(self, devices):
|
||||
return map(lambda x: self._hardware_inventory.get_device("cpu", x), devices)
|
||||
|
||||
@classmethod
|
||||
def _get_config_options(self):
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -33,6 +33,9 @@ class DiskPlugin(hotplug.Plugin):
|
|||
|
||||
self._assigned_devices = set()
|
||||
|
||||
def _get_device_objects(self, devices):
|
||||
return map(lambda x: self._hardware_inventory.get_device("block", x), devices)
|
||||
|
||||
@classmethod
|
||||
def _device_is_supported(cls, device):
|
||||
return device.device_type == "disk" and \
|
||||
|
|
|
|||
|
|
@ -33,6 +33,9 @@ class NetTuningPlugin(base.Plugin):
|
|||
|
||||
log.debug("devices: %s" % str(self._free_devices));
|
||||
|
||||
def _get_device_objects(self, devices):
|
||||
return map(lambda x: self._hardware_inventory.get_device("net", x), devices)
|
||||
|
||||
def _instance_init(self, instance):
|
||||
instance._has_static_tuning = True
|
||||
instance._has_dynamic_tuning = True
|
||||
|
|
|
|||
|
|
@ -28,6 +28,9 @@ class DiskPlugin(hotplug.Plugin):
|
|||
|
||||
self._assigned_devices = set()
|
||||
|
||||
def _get_device_objects(self, devices):
|
||||
return map(lambda x: self._hardware_inventory.get_device("scsi", x), devices)
|
||||
|
||||
@classmethod
|
||||
def _device_is_supported(cls, device):
|
||||
return device.device_type == "scsi_host"
|
||||
|
|
|
|||
|
|
@ -21,6 +21,9 @@ class USBPlugin(base.Plugin):
|
|||
|
||||
self._cmd = commands()
|
||||
|
||||
def _get_device_objects(self, devices):
|
||||
return map(lambda x: self._hardware_inventory.get_device("usb", x), devices)
|
||||
|
||||
@classmethod
|
||||
def _get_config_options(self):
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -22,6 +22,9 @@ class VideoPlugin(base.Plugin):
|
|||
|
||||
self._cmd = commands()
|
||||
|
||||
def _get_device_objects(self, devices):
|
||||
return map(lambda x: self._hardware_inventory.get_device("drm", x), devices)
|
||||
|
||||
@classmethod
|
||||
def _get_config_options(self):
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -8,13 +8,14 @@ __all__ = ["Repository"]
|
|||
|
||||
class Repository(PluginLoader):
|
||||
|
||||
def __init__(self, monitor_repository, storage_factory, hardware_inventory, device_matcher, plugin_instance_factory, global_cfg, variables):
|
||||
def __init__(self, monitor_repository, storage_factory, hardware_inventory, device_matcher, device_matcher_udev, plugin_instance_factory, global_cfg, variables):
|
||||
super(self.__class__, self).__init__()
|
||||
self._plugins = set()
|
||||
self._monitor_repository = monitor_repository
|
||||
self._storage_factory = storage_factory
|
||||
self._hardware_inventory = hardware_inventory
|
||||
self._device_matcher = device_matcher
|
||||
self._device_matcher_udev = device_matcher_udev
|
||||
self._plugin_instance_factory = plugin_instance_factory
|
||||
self._global_cfg = global_cfg
|
||||
self._variables = variables
|
||||
|
|
@ -32,7 +33,7 @@ class Repository(PluginLoader):
|
|||
log.debug("creating plugin %s" % plugin_name)
|
||||
plugin_cls = self.load_plugin(plugin_name)
|
||||
plugin_instance = plugin_cls(self._monitor_repository, self._storage_factory, self._hardware_inventory, self._device_matcher,\
|
||||
self._plugin_instance_factory, self._global_cfg, self._variables)
|
||||
self._device_matcher_udev, self._plugin_instance_factory, self._global_cfg, self._variables)
|
||||
self._plugins.add(plugin_instance)
|
||||
return plugin_instance
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ class Merger(object):
|
|||
profile_a.units[unit_name].type = unit.type
|
||||
profile_a.units[unit_name].enabled = unit.enabled
|
||||
profile_a.units[unit_name].devices = unit.devices
|
||||
if unit.devices_udev_regex != None:
|
||||
profile_a.units[unit_name].devices_udev_regex = unit.devices_udev_regex
|
||||
if unit_name == "script" and profile_a.units[unit_name].options.get("script", None) is not None:
|
||||
script = profile_a.units[unit_name].options.get("script", None)
|
||||
profile_a.units[unit_name].options.update(unit.options)
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ class Unit(object):
|
|||
Unit description.
|
||||
"""
|
||||
|
||||
__slots__ = [ "_name", "_type", "_enabled", "_replace", "_devices", "_options" ]
|
||||
__slots__ = [ "_name", "_type", "_enabled", "_replace", "_devices", "_devices_udev_regex", "_options" ]
|
||||
|
||||
def __init__(self, name, config):
|
||||
self._name = name
|
||||
|
|
@ -11,6 +11,7 @@ class Unit(object):
|
|||
self._enabled = config.pop("enabled", True) in [True, "true", 1]
|
||||
self._replace = config.pop("replace", False) in [True, "true", 1]
|
||||
self._devices = config.pop("devices", "*")
|
||||
self._devices_udev_regex = config.pop("devices_udev_regex", None)
|
||||
self._options = dict(config)
|
||||
|
||||
@property
|
||||
|
|
@ -45,6 +46,14 @@ class Unit(object):
|
|||
def devices(self, value):
|
||||
self._devices = value
|
||||
|
||||
@property
|
||||
def devices_udev_regex(self):
|
||||
return self._devices_udev_regex
|
||||
|
||||
@devices_udev_regex.setter
|
||||
def devices_udev_regex(self, value):
|
||||
self._devices_udev_regex = value
|
||||
|
||||
@property
|
||||
def options(self):
|
||||
return self._options
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ class Manager(object):
|
|||
if plugin is None:
|
||||
continue
|
||||
log.debug("creating '%s' (%s)" % (instance_info.name, instance_info.type))
|
||||
new_instance = plugin.create_instance(instance_info.name, instance_info.devices, instance_info.options)
|
||||
new_instance = plugin.create_instance(instance_info.name, instance_info.devices, instance_info.devices_udev_regex, instance_info.options)
|
||||
plugin.assign_free_devices(new_instance)
|
||||
plugin.initialize_instance(new_instance)
|
||||
self._instances.append(new_instance)
|
||||
|
|
|
|||
Loading…
Reference in a new issue