Permalink
Browse files

Refactored the work from last night around dynamic loading of the TCL…

… extensions (and the kernel modules they might contain). The TCE Mirror WEBrick instance now returns the lists as arrays instead of hash maps and both the Microkernel Controller and Kernel Module Manager now deal with these as arrays instead of hash maps. Also cleaned up how the Kernel Module Manager dealt with requests to install a module that is already installed (the module is now removed, then reinstalled) and added code to the Kernel Module Manager to simplify how it handles the "module names" that it receives from the TCE Mirror WEBrick instance (it now searches for the modules under the kernel module directory instead of requiring a full relative pathname to the kernel module in the names of the modules returned by that WEBrick instance). Finally, added the files used by the new WEBrick instance to the project (under the 'tmp/tinycorelinux' sub-directory) and moved the mk_conf.yaml file to that new (tmp) subdirectory since that's where the mk_conf.yaml file will actually be placed during the build process.
  • Loading branch information...
Tom McSweeney
Tom McSweeney committed May 9, 2012
1 parent d635b17 commit c67b13bd5997befe4069d25c65109082cea061fd
@@ -29,13 +29,17 @@
module RazorMicrokernel
class RzMkKernelModuleManager
# make this a singleton object (there should only be one in the system)
include Singleton
# include the RazorMicrokernel::Logging mixin (which enables logging)
# and include the RazorMicrokernel::Logging mixin (which enables logging)
include RazorMicrokernel::Logging
def initialize
@vmware_open_vm_tools_mods = %W[vmblock vmsync vmci vmxnet vmhgfs]
end
# define a few constants that will be used later on
PATHSEP = File::SEPARATOR
KERNEL_MODULE_ROOT = "#{PATHSEP}lib#{PATHSEP}modules#{PATHSEP}" +
"#{%x[uname -r].strip}#{PATHSEP}kernel"
KMOD_GLOB_PATTERN_BASE = "#{KERNEL_MODULE_ROOT}#{PATHSEP}**#{PATHSEP}"
OPEN_VM_TOOLS_MODS = %W[vmblock vmsync vmci vmxnet vmhgfs]
def load_kernel_modules
# get a reference to the Configuration Manager instance (a singleton)
@@ -45,46 +49,88 @@ def load_kernel_modules
# and if that property actually is a URI, then continue
kmod_install_list_uri = config_manager.mk_kmod_install_list_uri
if config_manager.config_file_exists? && kmod_install_list_uri && !(kmod_install_list_uri =~ URI::regexp).nil?
kernel_module_root = "/lib/modules/#{%x[uname -r].strip}/kernel/"
# first, parse the URI and then retrieve the kmod_install_list (an array) from it
install_list_uri = URI.parse(kmod_install_list_uri)
vm_kernel_module_map = {}
kmod_install_list = {}
begin
vm_kernel_module_map = JSON::parse(install_list_uri.read)
logger.debug "received a TCE install list of '#{vm_kernel_module_map.inspect}'"
kmod_install_list = JSON::parse(install_list_uri.read)
logger.debug "received a TCE install list of '#{kmod_install_list.inspect}'"
rescue => e
logger.debug "error while reading from '#{install_list_uri}' => #{e.message}"
return
end
vm_kernel_modules = vm_kernel_module_map['kmod_list']
#vm_kernel_modules = %W[fs/vmblock/vmblock.ko drivers/misc/vmsync.ko
# drivers/misc/vmci.ko drivers/net/vmxnet.ko fs/vmhgfs/vmhgfs.ko]
# initialize a few variables that will be used within the loop...
modules_changed = false
changed_modules = []
lsmod_output = %x[sudo lsmod]
vm_kernel_modules.each { |module_subpath|
module_name = module_subpath.split("/")[-1].split('.')[0]
name_plus_path = kernel_module_root + module_subpath
# determine which of these modules might already be installed (if any);
# if there are modules that are already installed, then remove them
rmmod_list = []
kmod_install_list.each { |module_subpath|
# get the name of the module from the full "module subpath"
module_filename = module_subpath.split("/")[-1]
module_name = module_filename.split('.')[0]
# check to see if the module is already installed, if it is, then remove it
module_regexp = Regexp.new(module_name)
module_loaded = module_regexp.match(lsmod_output)
is_open_vm_mod = @vmware_open_vm_tools_mods.include?(module_name)
# if it's an open-vm-tools module but it's not a VMware-based virtual
# environment, then remove that kernel module from the kernel, otherwise
# install the module
if is_open_vm_mod && (!Facter.is_virtual || !Facter.virtual == 'vmware')
if module_loaded
logger.debug "Removing module: #{module_name}"
%x[sudo rmmod #{name_plus_path}] unless !mod_info || mod_info.length == 0
changed_modules << module_name + "-"
modules_changed = true unless modules_changed
end
if module_regexp.match(lsmod_output)
rmmod_list << module_name
changed_modules << module_name + "-"
end
}
# if there are modules to remove, then remove them (all at once in order
# to avoid issues with dependencies)
if rmmod_list.length > 0
%x[sudo rmmod #{rmmod_list.join(' ')}]
end
# now that we know all of the existing modules (if any) are removed, we
# can move on to (re-)installing them
kmod_install_list.each { |module_subpath|
# get the name of the module from the full "module subpath"
module_filename = module_subpath.split("/")[-1]
module_name = module_filename.split('.')[0]
# determine the full path to the module under the KERNEL_MODULE_ROOT directory;
# if the module is not found, or if more than one matching module is found, then
# skip it (rather than trying to install something we can't find or something for which
# there is more than one possible source). Names can be disambiguated by providing a
# more complete relative directory path as part of the name (names are assumed to
# be relative to the KERNEL_MODULE_ROOT directory)
name_plus_path_array = Dir.glob("#{KMOD_GLOB_PATTERN_BASE}#{module_name}.ko")
unless name_plus_path_array && name_plus_path_array.length > 0
# if we didn't find the module, log that fact and skip to the next one
logger.warn "kernel module '#{module_name}.ko' not found under directory '#{KERNEL_MODULE_ROOT}'"
next
end
if name_plus_path_array.length > 1
# if we found more than one matching, log that fact and skip to the next one
logger.warn "more than one kernel module matching the name '#{module_name}.ko' found under" +
" '#{KERNEL_MODULE_ROOT}', skipping installation of this (ambiguous) module"
next
end
name_plus_path = name_plus_path_array[0]
# if the module is a module from the open_vm_tools.tcz extension, then skip
# installing it unless we are in a VMware-based virtual environment
next unless !OPEN_VM_TOOLS_MODS.include?(module_name) ||
(Facter.is_virtual && Facter.virtual == 'vmware')
# if we've gotten this far, then it's safe to just install the module
logger.debug "Installing module: #{name_plus_path}"
%x[sudo insmod #{name_plus_path}]
removed_mod_index = changed_modules.index(module_name + "-")
if removed_mod_index
changed_modules[removed_mod_index] = module_name + "/"
else
logger.debug "Installing module: #{module_name}"
%x[sudo insmod #{name_plus_path}]
changed_modules << module_name + "+"
modules_changed = true unless modules_changed
end
modules_changed = true unless modules_changed
}
if modules_changed
logger.info "Modules changed: #{changed_modules.join(", ")}"
@@ -94,4 +140,4 @@ def load_kernel_modules
end
end
end
end
View
@@ -62,21 +62,19 @@ def load_tcl_extensions(tce_install_list_uri, tce_mirror_uri, force_reinstall =
begin
# load the list of extensions to install from the URI
install_list_uri = URI.parse(tce_install_list_uri)
tce_install_list_map = {}
tce_install_list = []
begin
tce_install_list_map = JSON::parse(install_list_uri.read)
logger.debug("received a TCE install list of '#{tce_install_list_map.inspect}'")
tce_install_list = JSON::parse(install_list_uri.read)
logger.debug("received a TCE install list of '#{tce_install_list.inspect}'")
rescue => e
logger.debug("error while reading from '#{install_list_uri}' => #{e.message}")
return
end
ext_list_array = tce_install_list_map['extension_list']
logger.debug("TCE install list: '#{ext_list_array.inspect}'")
logger.debug("TCE install list: '#{tce_install_list.inspect}'")
# for each extension on that list, load that extension (using the
# 'tcl-load' command)
# for each extension on that list, load that extension (using the 'tce-load' command)
has_kernel_modules = false
ext_list_array.each { |extension|
tce_install_list.each { |extension|
# if it's in the list of installed extensions, then skip it
next if !force_reinstall && installed_extensions.include?(extension.gsub(/.tcz$/,''))
logger.debug "loading #{extension}"
View
@@ -30,7 +30,7 @@ def do_GET(req, res)
# create a new HTTP Response
config = WEBrick::Config::HTTP
extension_list = YAML::load(File.open('/tmp/tinycorelinux/tce-install-list.yaml'))
return_str = JSON.generate({:extension_list => extension_list})
return_str = JSON.generate(extension_list)
logger.info "Returning JSON string '#{return_str}' to user"
res.content_type = 'application/json'
res.content_length = return_str.length
@@ -46,7 +46,7 @@ def do_GET(req, res)
# create a new HTTP Response
config = WEBrick::Config::HTTP
kmod_list = YAML::load(File.open('/tmp/tinycorelinux/kmod-install-list.yaml'))
return_str = JSON.generate({:kmod_list => kmod_list})
return_str = JSON.generate(kmod_list)
logger.info "Returning JSON string '#{return_str}' to user"
res.content_type = 'application/json'
res.content_length = return_str.length
File renamed without changes.
@@ -0,0 +1,6 @@
---
- vmblock.ko
- vmsync.ko
- vmci.ko
- vmxnet.ko
- vmhgfs.ko
@@ -0,0 +1,2 @@
---
- open_vm_tools.tcz

0 comments on commit c67b13b

Please sign in to comment.