Merge pull request #16 from olysonek/instance_priority_pr
Implement instance priority
This commit is contained in:
commit
9cf6c3f45c
6 changed files with 54 additions and 41 deletions
|
|
@ -26,3 +26,6 @@ recommend_command = 1
|
||||||
# If enabled these sysctls will be re-appliead after Tuned sysctls are
|
# If enabled these sysctls will be re-appliead after Tuned sysctls are
|
||||||
# applied, i.e. Tuned sysctls will not override system sysctls.
|
# applied, i.e. Tuned sysctls will not override system sysctls.
|
||||||
reapply_sysctl = 1
|
reapply_sysctl = 1
|
||||||
|
|
||||||
|
# Default priority assigned to instances
|
||||||
|
default_instance_priority = 0
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,7 @@ CFG_SLEEP_INTERVAL = "sleep_interval"
|
||||||
CFG_UPDATE_INTERVAL = "update_interval"
|
CFG_UPDATE_INTERVAL = "update_interval"
|
||||||
CFG_RECOMMEND_COMMAND = "recommend_command"
|
CFG_RECOMMEND_COMMAND = "recommend_command"
|
||||||
CFG_REAPPLY_SYSCTL = "reapply_sysctl"
|
CFG_REAPPLY_SYSCTL = "reapply_sysctl"
|
||||||
|
CFG_DEFAULT_INSTANCE_PRIORITY = "default_instance_priority"
|
||||||
|
|
||||||
# no_daemon mode
|
# no_daemon mode
|
||||||
CFG_DEF_DAEMON = True
|
CFG_DEF_DAEMON = True
|
||||||
|
|
@ -69,6 +70,8 @@ CFG_DEF_UPDATE_INTERVAL = 10
|
||||||
CFG_DEF_RECOMMEND_COMMAND = True
|
CFG_DEF_RECOMMEND_COMMAND = True
|
||||||
# reapply system sysctl
|
# reapply system sysctl
|
||||||
CFG_DEF_REAPPLY_SYSCTL = True
|
CFG_DEF_REAPPLY_SYSCTL = True
|
||||||
|
# default instance priority
|
||||||
|
CFG_DEF_DEFAULT_INSTANCE_PRIORITY = 0
|
||||||
|
|
||||||
PATH_CPU_DMA_LATENCY = "/dev/cpu_dma_latency"
|
PATH_CPU_DMA_LATENCY = "/dev/cpu_dma_latency"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,8 @@ class Application(object):
|
||||||
log.info("dynamic tuning is globally disabled")
|
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, plugin_instance_factory, self.config, self.variables)
|
||||||
unit_manager = units.Manager(plugins_repository, monitors_repository)
|
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)
|
||||||
|
|
||||||
profile_factory = profiles.Factory()
|
profile_factory = profiles.Factory()
|
||||||
profile_merger = profiles.Merger()
|
profile_merger = profiles.Merger()
|
||||||
|
|
|
||||||
|
|
@ -102,11 +102,10 @@ class Plugin(object):
|
||||||
self._destroy_instance(instance)
|
self._destroy_instance(instance)
|
||||||
del self._instances[instance.name]
|
del self._instances[instance.name]
|
||||||
|
|
||||||
def initialize_instances(self):
|
def initialize_instance(self, instance):
|
||||||
"""Initialize all created instances."""
|
"""Initialize an instance."""
|
||||||
for (instance_name, instance) in self._instances.items():
|
log.debug("initializing instance %s (%s)" % (instance.name, self.name))
|
||||||
log.debug("initializing instance %s (%s)" % (instance_name, self.name))
|
self._instance_init(instance)
|
||||||
self._instance_init(instance)
|
|
||||||
|
|
||||||
def destroy_instances(self):
|
def destroy_instances(self):
|
||||||
"""Destroy all instances."""
|
"""Destroy all instances."""
|
||||||
|
|
@ -140,21 +139,20 @@ class Plugin(object):
|
||||||
def _get_matching_devices(self, instance, devices):
|
def _get_matching_devices(self, instance, devices):
|
||||||
return set(self._device_matcher.match_list(instance.devices_expression, devices))
|
return set(self._device_matcher.match_list(instance.devices_expression, devices))
|
||||||
|
|
||||||
def assign_free_devices(self):
|
def assign_free_devices(self, instance):
|
||||||
if not self._devices_supported():
|
if not self._devices_supported():
|
||||||
return
|
return
|
||||||
|
|
||||||
log.debug("assigning devices to all instances")
|
log.debug("assigning devices to instance %s" % instance.name)
|
||||||
for instance_name, instance in reversed(self._instances.items()):
|
to_assign = self._get_matching_devices(instance, self._free_devices)
|
||||||
to_assign = self._get_matching_devices(instance, self._free_devices)
|
instance.active = len(to_assign) > 0
|
||||||
instance.active = len(to_assign) > 0
|
if not instance.active:
|
||||||
if not instance.active:
|
log.warn("instance %s: no matching devices available" % instance.name)
|
||||||
log.warn("instance %s: no matching devices available" % instance_name)
|
else:
|
||||||
else:
|
log.info("instance %s: assigning devices %s" % (instance.name, ", ".join(to_assign)))
|
||||||
log.info("instance %s: assigning devices %s" % (instance_name, ", ".join(to_assign)))
|
instance.devices.update(to_assign) # cannot use |=
|
||||||
instance.devices.update(to_assign) # cannot use |=
|
self._assigned_devices |= to_assign
|
||||||
self._assigned_devices |= to_assign
|
self._free_devices -= to_assign
|
||||||
self._free_devices -= to_assign
|
|
||||||
|
|
||||||
def release_devices(self, instance):
|
def release_devices(self, instance):
|
||||||
if not self._devices_supported():
|
if not self._devices_supported():
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,10 @@ class Instance(object):
|
||||||
|
|
||||||
# properties
|
# properties
|
||||||
|
|
||||||
|
@property
|
||||||
|
def plugin(self):
|
||||||
|
return self._plugin
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
return self._name
|
return self._name
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import collections
|
||||||
import tuned.exceptions
|
import tuned.exceptions
|
||||||
import tuned.logs
|
import tuned.logs
|
||||||
import tuned.plugins.exceptions
|
import tuned.plugins.exceptions
|
||||||
|
|
@ -11,10 +12,11 @@ class Manager(object):
|
||||||
Manager creates plugin instances and keeps a track of them.
|
Manager creates plugin instances and keeps a track of them.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, plugins_repository, monitors_repository):
|
def __init__(self, plugins_repository, monitors_repository, def_instance_priority):
|
||||||
super(self.__class__, self).__init__()
|
super(self.__class__, self).__init__()
|
||||||
self._plugins_repository = plugins_repository
|
self._plugins_repository = plugins_repository
|
||||||
self._monitors_repository = monitors_repository
|
self._monitors_repository = monitors_repository
|
||||||
|
self._def_instance_priority = def_instance_priority
|
||||||
self._instances = []
|
self._instances = []
|
||||||
self._plugins = []
|
self._plugins = []
|
||||||
|
|
||||||
|
|
@ -27,22 +29,25 @@ class Manager(object):
|
||||||
return self._instances
|
return self._instances
|
||||||
|
|
||||||
def create(self, instances_config):
|
def create(self, instances_config):
|
||||||
|
instance_info_list = []
|
||||||
# group instances by plugin
|
|
||||||
|
|
||||||
instances_by_plugin = {}
|
|
||||||
for instance_name, instance_info in instances_config.items():
|
for instance_name, instance_info in instances_config.items():
|
||||||
if not instance_info.enabled:
|
if not instance_info.enabled:
|
||||||
log.debug("skipping disabled instance '%s'" % instance_name)
|
log.debug("skipping disabled instance '%s'" % instance_name)
|
||||||
continue
|
continue
|
||||||
instances_by_plugin.setdefault(instance_info.type, [])
|
instance_info.options.setdefault("instance_priority", self._def_instance_priority)
|
||||||
instances_by_plugin[instance_info.type].append(instance_info)
|
instance_info.options["instance_priority"] = int(instance_info.options["instance_priority"])
|
||||||
|
instance_info_list.append(instance_info)
|
||||||
|
|
||||||
# create all plugin instances at once
|
instance_info_list.sort(key=lambda x: x.options["instance_priority"])
|
||||||
|
plugins_by_name = collections.OrderedDict()
|
||||||
|
for instance_info in instance_info_list:
|
||||||
|
instance_info.options.pop("instance_priority")
|
||||||
|
plugins_by_name[instance_info.type] = None
|
||||||
|
|
||||||
for plugin_name, instances_info in instances_by_plugin.items():
|
for plugin_name, none in plugins_by_name.items():
|
||||||
try:
|
try:
|
||||||
plugin = self._plugins_repository.create(plugin_name)
|
plugin = self._plugins_repository.create(plugin_name)
|
||||||
|
plugins_by_name[plugin_name] = plugin
|
||||||
self._plugins.append(plugin)
|
self._plugins.append(plugin)
|
||||||
except tuned.plugins.exceptions.NotSupportedPluginException:
|
except tuned.plugins.exceptions.NotSupportedPluginException:
|
||||||
log.info("skipping plugin '%s', not supported on your system" % plugin_name)
|
log.info("skipping plugin '%s', not supported on your system" % plugin_name)
|
||||||
|
|
@ -52,21 +57,20 @@ class Manager(object):
|
||||||
log.exception(e)
|
log.exception(e)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
created_instances = []
|
for instance_info in instance_info_list:
|
||||||
for instance_info in instances_info:
|
plugin = plugins_by_name[instance_info.type]
|
||||||
log.debug("creating '%s' (%s)" % (instance_info.name, instance_info.type))
|
if plugin is None:
|
||||||
new_instance = plugin.create_instance(instance_info.name, instance_info.devices, instance_info.options)
|
continue
|
||||||
created_instances.append(new_instance)
|
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)
|
||||||
plugin.assign_free_devices()
|
plugin.assign_free_devices(new_instance)
|
||||||
plugin.initialize_instances()
|
plugin.initialize_instance(new_instance)
|
||||||
|
self._instances.append(new_instance)
|
||||||
self._instances.extend(created_instances)
|
|
||||||
|
|
||||||
def destroy_all(self):
|
def destroy_all(self):
|
||||||
for plugin in self._plugins:
|
for instance in self._instances:
|
||||||
log.debug("cleaning plugin '%s'" % plugin.name)
|
log.debug("destroying instance %s" % instance.name)
|
||||||
plugin.cleanup()
|
instance.plugin.destroy_instance(instance)
|
||||||
|
|
||||||
del self._plugins[:]
|
del self._plugins[:]
|
||||||
del self._instances[:]
|
del self._instances[:]
|
||||||
|
|
@ -93,5 +97,5 @@ class Manager(object):
|
||||||
|
|
||||||
# profile_switch is helper telling plugins whether the stop is due to profile switch
|
# profile_switch is helper telling plugins whether the stop is due to profile switch
|
||||||
def stop_tuning(self, profile_switch = False):
|
def stop_tuning(self, profile_switch = False):
|
||||||
for instance in self._instances:
|
for instance in reversed(self._instances):
|
||||||
instance.unapply_tuning(profile_switch)
|
instance.unapply_tuning(profile_switch)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue