summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Klozik <martinx.klozik@intel.com>2016-03-15 15:30:42 +0000
committerMaryam Tahhan <maryam.tahhan@intel.com>2016-03-21 15:30:24 +0000
commit3d4f372012624b95c9d6709805fce1908700ff13 (patch)
tree6ffd451d7144aa14e6c8a976603a72462af78051
parentb55c8beb6003f07f025fc0edbc08c3e0fcaed064 (diff)
bugfix: Fix errors related to removal of kernel modules
Internal module manager is responsible for removal of all vsperf specific kernel modules. Order of modules has been changed to respect possible dependencies among modules. Manager has been improved to detect modules automatically loaded by modprobe to solve dependecies. These modules are automatically removed. Code of module manager has been refactored. Change-Id: I4484f3bea7d9900db688f96edd5c3c6d4a304742 JIRA: VSPERF-259 Signed-off-by: Martin Klozik <martinx.klozik@intel.com> Reviewed-by: Maryam Tahhan <maryam.tahhan@intel.com> Reviewed-by: Al Morton <acmorton@att.com> Reviewed-by: Christian Trautman <ctrautma@redhat.com> Reviewed-by: Brian Castelli <brian.castelli@spirent.com>
-rw-r--r--src/dpdk/dpdk.py5
-rw-r--r--tools/module_manager.py177
2 files changed, 89 insertions, 93 deletions
diff --git a/src/dpdk/dpdk.py b/src/dpdk/dpdk.py
index 127ecaf2..f8cbbd81 100644
--- a/src/dpdk/dpdk.py
+++ b/src/dpdk/dpdk.py
@@ -111,13 +111,14 @@ def insert_vhost_modules():
mod_path_prefix = os.path.join(settings.getValue('RTE_SDK'),
'lib',
'librte_vhost')
- _DPDK_MODULE_MANAGER.insert_module_group('VHOST_MODULE', mod_path_prefix)
+ _DPDK_MODULE_MANAGER.insert_module_group(settings.getValue('VHOST_MODULE'), mod_path_prefix)
def remove_vhost_modules():
"""Removes all VHOST related kernel modules
"""
- _DPDK_MODULE_MANAGER.remove_module_group(settings.getValue('VHOST_MODULE'))
+ # all modules are removed automatically by _remove_modules() method
+ pass
#
diff --git a/tools/module_manager.py b/tools/module_manager.py
index 565bac51..2eb4c63d 100644
--- a/tools/module_manager.py
+++ b/tools/module_manager.py
@@ -20,7 +20,6 @@ import logging
from tools import tasks
-_LOGGER = logging.getLogger(__name__)
class ModuleManager(object):
"""Simple module manager which acts as system wrapper for Kernel Modules.
"""
@@ -32,119 +31,115 @@ class ModuleManager(object):
"""
self._modules = []
- def insert_modules(self, modules):
- """Method inserts list of modules. In case that module name ends
- with .ko suffix then insmod will be used for its insertion. Otherwise
- modprobe will be called.
+ def insert_module(self, module):
+ """Method inserts given module.
+
+ In case that module name ends with .ko suffix then insmod will
+ be used for its insertion. Otherwise modprobe will be called.
- :returns: None
+ :param module: a name of kernel module
"""
+ module_base_name = os.path.basename(os.path.splitext(module)[0])
- for module in modules:
- if self.is_module_inserted(module):
- continue
+ if self.is_module_inserted(module):
+ self._logger.info('Module already loaded \'%s\'.', module_base_name)
+ # add it to internal list, so we can try to remove it at the end
+ self._modules.append(module)
+ return
+
+ try:
+ if module.endswith('.ko'):
+ tasks.run_task(['sudo', 'insmod', module], self._logger,
+ 'Insmod module \'%s\'...' % module_base_name, True)
+ else:
+ tasks.run_task(['sudo', 'modprobe', module], self._logger,
+ 'Modprobe module \'%s\'...' % module_base_name, True)
+ self._modules.append(module)
+ except subprocess.CalledProcessError:
+ # in case of error, show full module name
+ self._logger.error('Unable to insert module \'%s\'.', module)
+ raise # fail catastrophically
- try:
- if module.endswith('.ko'):
- tasks.run_task(['sudo', 'insmod', module], self._logger,
- 'Insmod module \'%s\'...' % module, True)
- else:
- tasks.run_task(['sudo', 'modprobe', module], self._logger,
- 'Modprobe module \'%s\'...' % module, True)
- _LOGGER.info("Inserted Module %s", module)
- self._modules.append(module)
- except subprocess.CalledProcessError:
- self._logger.error('Unable to insert module \'%s\'.', module)
- raise # fail catastrophically
+ def insert_modules(self, modules):
+ """Method inserts list of modules.
- def insert_module_group(self, module_group, group_path_prefix):
+ :param modules: a list of modules to be inserted
+ """
+ for module in modules:
+ self.insert_module(module)
+
+ def insert_module_group(self, module_group, path_prefix):
"""Ensure all modules in a group are inserted into the system.
:param module_group: A name of configuration item containing a list
- of module names
+ of module names
+ :param path_prefix: A name of directory which contains given
+ group of modules
+ """
+ for (path_suffix, module) in module_group:
+ self.insert_module(os.path.join(path_prefix, path_suffix, '%s.ko' % module))
+
+ def remove_module(self, module):
+ """Removes a single module.
+
+ :param module: a name of kernel module
"""
- for module in module_group:
- # first check if module is loaded
- if self.is_module_inserted(module[1]):
- continue
+ if self.is_module_inserted(module):
+ # get module base name, i.e strip path and .ko suffix if possible
+ module_base_name = os.path.basename(os.path.splitext(module)[0])
try:
- mod_path = os.path.join(group_path_prefix, module[0],
- '%s.ko' % module[1])
- tasks.run_task(['sudo', 'insmod', mod_path], _LOGGER,
- 'Inserting module \'%s\'...' % module[1], True)
- self._modules.append(module)
+ self._logger.info('Removing module \'%s\'...', module_base_name)
+ subprocess.check_call('sudo rmmod {}'.format(module_base_name),
+ shell=True, stderr=subprocess.DEVNULL)
+ # in case that module was loaded automatically by modprobe
+ # to solve dependecies, then it is not in internal list of modules
+ if module in self._modules:
+ self._modules.remove(module)
except subprocess.CalledProcessError:
- _LOGGER.error('Unable to insert module \'%s\'.', module[1])
- raise # fail catastrophically
+ # in case of error, show full module name...
+ self._logger.info('Unable to remove module \'%s\'.', module)
+ # ...and list of dependend modules, if there are any
+ module_details = self.get_module_details(module_base_name)
+ if module_details:
+ mod_dep = module_details.split(' ')[3].rstrip(',')
+ if mod_dep[0] != '-':
+ self._logger.debug('Module \'%s\' is used by module(s) \'%s\'.',
+ module_base_name, mod_dep)
def remove_modules(self):
"""Removes all modules that have been previously inserted.
"""
- for module in self._modules:
- # first check if module is loaded
- if not self.is_module_inserted(module):
- continue
+ # remove modules in reverse order to respect their dependencies
+ for module in reversed(self._modules):
+ self.remove_module(module)
- try:
- # rmmod supports both simple module name and full module path
- # with .ko suffix
- tasks.run_task(['sudo', 'rmmod', module], self._logger,
- 'Removing module \'%s\'...' % module, True)
- self._modules.remove(module)
- except subprocess.CalledProcessError:
- self._logger.error('Unable to remove module \'%s\'.', module)
- continue
- @staticmethod
- def is_module_inserted(module):
+ def is_module_inserted(self, module):
"""Check if a module is inserted on system.
+
+ :param module: a name of kernel module
"""
- if module.endswith('.ko'):
- # get module base name, i.e strip path and .ko suffix if possible
- module_base_name = os.path.basename(os.path.splitext(module)[0])
- else:
- module_base_name = module
+ module_base_name = os.path.basename(os.path.splitext(module)[0])
+
+ return self.get_module_details(module_base_name) != None
+
+ @staticmethod
+ def get_module_details(module):
+ """Return details about given module
+ :param module: a name of kernel module
+ :returns: In case that module is loaded in OS, then corresponding
+ line from /proc/modules will be returned. Otherwise it returns None.
+ """
# get list of modules from kernel
with open('/proc/modules') as mod_file:
loaded_mods = mod_file.readlines()
- # first check if module is loaded
+ # check if module is loaded
for line in loaded_mods:
- if line.startswith(module_base_name):
- return True
- return False
+ # underscores '_' and dashes '-' in module names are interchangeable, so we
+ # have to normalize module names before comparision
+ if line.split(' ')[0].replace('-', '_') == module.replace('-', '_'):
+ return line
- def remove_module(self, module):
- """Removes a single module.
- """
- if self.is_module_inserted(module):
- # get module base name, i.e strip path and .ko suffix if possible
- module_base_name = os.path.basename(os.path.splitext(module)[0])
-
- try:
- # rmmod supports both simple module name and full module path
- # with .ko suffix
- tasks.run_task(['sudo', 'rmmod', module_base_name], self._logger,
- 'Removing module \'%s\'...' % module, True)
- self._modules.remove(module)
- except subprocess.CalledProcessError:
- self._logger.error('Unable to remove module \'%s\'.', module_base_name)
-
- def remove_module_group(self, module_group):
- """Removes all modules in the modules group.
- """
- for module in module_group:
- if not self.is_module_inserted(module[1]):
- continue
- # get module base name, i.e strip path and .ko suffix if possible
- module_base_name = os.path.basename(os.path.splitext(module)[0])
-
- try:
- # rmmod supports both simple module name and full module path
- # with .ko suffix
- tasks.run_task(['sudo', 'rmmod', module_base_name], self._logger,
- 'Removing module \'%s\'...' % module, True)
- self._modules.remove(module)
- except subprocess.CalledProcessError:
- self._logger.error('Unable to remove module \'%s\'.', module_base_name)
+ return None