diff options
Diffstat (limited to 'tools/module_manager.py')
-rw-r--r-- | tools/module_manager.py | 177 |
1 files changed, 86 insertions, 91 deletions
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 |