Skip to content

Commit cddcd23

Browse files
committed
dbus: add commands to dynamically create/destroy instances
Signed-off-by: Adriaan Schmidt <adriaan.schmidt@siemens.com>
1 parent 6c48757 commit cddcd23

2 files changed

Lines changed: 117 additions & 0 deletions

File tree

com.redhat.tuned.policy

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,4 +247,24 @@
247247
</defaults>
248248
</action>
249249

250+
<action id="com.redhat.tuned.instance_create">
251+
<description>Create new plugin instance</description>
252+
<message>Authentication is required to create a new plugin instance</message>
253+
<defaults>
254+
<allow_any>auth_admin</allow_any>
255+
<allow_inactive>auth_admin</allow_inactive>
256+
<allow_active>yes</allow_active>
257+
</defaults>
258+
</action>
259+
260+
<action id="com.redhat.tuned.instance_destroy">
261+
<description>Delete a plugin instance</description>
262+
<message>Authentication is required to destroy the instance</message>
263+
<defaults>
264+
<allow_any>auth_admin</allow_any>
265+
<allow_inactive>auth_admin</allow_inactive>
266+
<allow_active>yes</allow_active>
267+
</defaults>
268+
</action>
269+
250270
</policyconfig>

tuned/daemon/controller.py

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,3 +422,100 @@ def instance_get_devices(self, instance_name, caller = None):
422422
rets = "Instance '%s' not found" % instance_name
423423
log.error(rets)
424424
return (False, rets, [])
425+
426+
@exports.export("ssa{ss}", "(bs)")
427+
def instance_create(self, plugin_name, instance_name, options, caller = None):
428+
"""Dynamically create a plugin instance
429+
430+
Parameters:
431+
plugin_name -- name of the plugin
432+
instance_name -- name of the new instance
433+
dict of string-string -- options for the new instance
434+
435+
Return:
436+
bool -- True on success
437+
string -- error message or "OK"
438+
"""
439+
if caller == "":
440+
return (False, "Unauthorized")
441+
plugins = {p.name: p for p in self._daemon._unit_manager.plugins}
442+
if not plugin_name in plugins.keys():
443+
rets = "Plugin '%s' not found" % plugin_name
444+
log.error(rets)
445+
return (False, rets)
446+
plugin = plugins[plugin_name]
447+
if not isinstance(plugin, hotplug.Plugin):
448+
rets = "Plugin '%s' does not support hotplugging or dynamic instances." % plugin.name
449+
log.error(rets)
450+
return (False, rets)
451+
devices = options.pop("devices", None)
452+
devices_udev_regex = options.pop("devices_udev_regex", None)
453+
script_pre = options.pop("script_pre", None)
454+
script_post = options.pop("script_post", None)
455+
priority = int(options.pop("priority", self._daemon._unit_manager._def_instance_priority))
456+
try:
457+
instance = plugin.create_instance(instance_name, priority, devices, devices_udev_regex, script_pre, script_post, options)
458+
plugin.initialize_instance(instance)
459+
self._daemon._unit_manager.instances.append(instance)
460+
except Exception as e:
461+
rets = "Error creating instance '%s': %s" % (instance_name, str(e))
462+
log.error(rets)
463+
return (False, rets)
464+
log.info("Created dynamic instance '%s' of plugin '%s'" % (instance_name, plugin_name))
465+
466+
plugin.assign_free_devices(instance)
467+
plugin.instance_apply_tuning(instance)
468+
# transfer matching devices from other instances, if the priority of the new
469+
# instance is equal or higher (equal or lower priority value)
470+
for other_instance in self._daemon._unit_manager.instances:
471+
if (other_instance == instance or
472+
other_instance.plugin != plugin or
473+
instance.priority > other_instance.priority):
474+
continue
475+
devs_moving = plugin._get_matching_devices(instance, other_instance.processed_devices)
476+
if len(devs_moving):
477+
log.info("Moving devices '%s' from instance '%s' to instance '%s'." % (str(devs_moving),
478+
other_instance.name, instance.name))
479+
plugin._remove_devices_nocheck(other_instance, devs_moving)
480+
plugin._add_devices_nocheck(instance, devs_moving)
481+
return (True, "OK")
482+
483+
@exports.export("s", "(bs)")
484+
def instance_destroy(self, instance_name, caller = None):
485+
"""Destroy a dynamically created plugin instance
486+
487+
Parameters:
488+
instance_name -- name of the new instance
489+
490+
Return:
491+
bool -- True on success
492+
string -- error message or "OK"
493+
"""
494+
if caller == "":
495+
return (False, "Unauthorized")
496+
try:
497+
instance = [i for i in self._daemon._unit_manager.instances if i.name == instance_name][0]
498+
except IndexError:
499+
rets = "Instance '%s' not found" % instance_name
500+
log.error(rets)
501+
return (False, rets)
502+
plugin = instance.plugin
503+
if not isinstance(plugin, hotplug.Plugin):
504+
rets = "Plugin '%s' does not support hotplugging or dynamic instances." % plugin.name
505+
log.error(rets)
506+
return (False, rets)
507+
devices = instance.processed_devices.copy()
508+
try:
509+
plugin._remove_devices_nocheck(instance, devices)
510+
self._daemon._unit_manager.instances.remove(instance)
511+
plugin.instance_unapply_tuning(instance)
512+
plugin.destroy_instance(instance)
513+
except Exception as e:
514+
rets = "Error deleting instance '%s': %s" % (instance_name, str(e))
515+
log.error(rets)
516+
return (False, rets)
517+
log.info("Deleted instance '%s'" % instance_name)
518+
for device in devices:
519+
# _add_device() will find a suitable plugin instance
520+
plugin._add_device(device)
521+
return (True, "OK")

0 commit comments

Comments
 (0)