Permalink
Browse files

This commit adds support for a gem mirror (either internal or, when c…

…ombined with recent changes to Razor, external). With these changes in place, a list of gems to install is obtained from a gem list (assumed to be accessible via the URI given by the 'mk_gemlist_uri' configuration parameter), and then the versions of the gems listed there that are accessible from the gem mirror that will be used by the Microkernel (assumed to be defined by the 'mk_gem_mirror_uri' configuration parameter) are compared with the versions of those same gems that are installed locally. This comparison is made whenever the Microkernel Controller is restarted (or during the Microkernel Controller initialization process that occurs when the Microkernel first boots). If the stated gems are not available locally, or if the latest version available from the gem mirror is not installed locally, then the stated version of those missing/out of date gems version will be installed from the gem mirror...
  • Loading branch information...
Tom McSweeney
Tom McSweeney committed Nov 14, 2012
1 parent 0a5d118 commit 0dca9be6d1946f763e8382b8fd1bee952ecbd939
@@ -4,14 +4,17 @@
#
require 'yaml'
-require 'json'
require 'singleton'
module RazorMicrokernel
class RzMkConfigurationManager
# make this class a singleton class (only want one)
include Singleton
+ MK_CONF_FILE = '/tmp/mk_conf.yaml'
+ DEF_MK_GEM_MIRROR_URI = "http://localhost:2158/gem-mirror"
+ DEF_MK_GEMLIST_URI = "http://localhost:2158/gem-mirror"
+
attr_reader :mk_checkin_interval
attr_reader :mk_checkin_skew
attr_reader :mk_uri
@@ -26,32 +29,34 @@ class RzMkConfigurationManager
attr_reader :mk_tce_mirror_uri
attr_reader :mk_tce_install_list_uri
attr_reader :mk_kmod_install_list_uri
+ attr_reader :mk_gem_mirror_uri
+ attr_reader :mk_gemlist_uri
def initialize
@default_mk_log_level = Logger::INFO
- @mk_config_file = '/tmp/mk_conf.yaml'
end
def mk_config_has_changed?(new_mk_config_map)
- return true if !File.exists?(@mk_config_file)
- old_mk_config_map = YAML::load(File.open(@mk_config_file, 'r'))
+ return true if !File.exists?(MK_CONF_FILE)
+ old_mk_config_map = YAML::load(File.open(MK_CONF_FILE, 'r'))
return_val = old_mk_config_map != new_mk_config_map
return_val
end
def save_mk_config(mk_config_map)
- File.open(@mk_config_file, 'w') { |file|
+ puts "Saving MK Configuration..."
+ File.open(MK_CONF_FILE, 'w') { |file|
YAML::dump(mk_config_map, file)
}
set_current_config(mk_config_map)
end
def config_file_exists?
- File.exists?(@mk_config_file)
+ File.exists?(MK_CONF_FILE)
end
def load_current_config
- mk_conf = YAML::load(File.open(@mk_config_file))
+ mk_conf = YAML::load(File.open(MK_CONF_FILE))
set_current_config(mk_conf)
end
@@ -81,6 +86,16 @@ def set_current_config(mk_conf)
@mk_tce_mirror_uri = mk_conf['mk_tce_mirror_uri']
@mk_tce_install_list_uri = mk_conf['mk_tce_install_list_uri']
@mk_kmod_install_list_uri = mk_conf['mk_kmod_install_list_uri']
+ if mk_conf['mk_gem_mirror_uri']
+ @mk_gem_mirror_uri = mk_conf['mk_gem_mirror_uri']
+ else
+ @mk_gem_mirror_uri = DEF_MK_GEM_MIRROR_URI
+ end
+ if mk_conf['mk_gemlist_uri']
+ @mk_gemlist_uri = mk_conf['mk_gemlist_uri']
+ else
+ @mk_gemlist_uri = DEF_MK_GEMLIST_URI
+ end
end
end
@@ -5,27 +5,93 @@
#
#
+require 'net/http'
+require 'singleton'
+
module RazorMicrokernel
class RzMkGemController
+ # make this class a singleton class (only want one)
+ include Singleton
+
+ GEM_LIST_PARSE_EXPR = /^(\S*)\s*\((.*)\)$/
- attr_reader :dirName, :listFileName
+ def gemSource=(gemSource)
+ @gemSource = gemSource
+ # get the map of gem versions available from this source (by gem name)
+ @gemVersions = getRemoteGemList
+ # and save a copy of those names for later use
+ @gemNames = @gemVersions.keys
+ end
- def initialize(dirName, listFileName="gem.list")
- @dirName = dirName
- @listFileName = listFileName
+ def gemListURI=(gemListURI)
+ @gemListURI = gemListURI
end
- def installAllGems()
- fileName = @dirName + "/"+ @listFileName
- File.open(fileName, 'r').each { |gemNameFromFile|
- installGem(gemNameFromFile.chomp)
+ def getRemoteGemList
+ output = %x[gem list --clear-sources --source #{@gemSource} --remote]
+ gem_version_map = {}
+ output.split("\n").each { |line|
+ parsed_line = GEM_LIST_PARSE_EXPR.match(line)
+ gem_version_map[parsed_line[1]] = parsed_line[2].split(", ")
}
+ gem_version_map
+ end
+
+ def getLocalVersions(gemName)
+ line = %x[gem list --local --versions #{gemName}]
+ name_versions_match = GEM_LIST_PARSE_EXPR.match(line)
+ return nil unless name_versions_match
+ name_versions_match[2].split(", ")
+ end
+
+ # installs a "new" version of a gem locally from the current @gemSource
+ # (Note; the gem is only installed if it hasn't been installed yet on the
+ # local system or if this version of the gem has not been installed yet)
+ def addToInstalledGems(gemName)
+ # if the named gem is not available from the named mirror, then print out
+ # a warning and return without trying to install this gem
+ unless @gemNames.include?(gemName)
+ puts "WARNING; gem '#{gemName}' is not available from the named mirror (#{@gemSource})"
+ return
+ end
+ # otherwise, determine the most recent version available from the @gemSource mirror
+ # (this is the version that will be installed)
+ newVersion = @gemVersions[gemName][0]
+ # next, get a list of the locally installed version(s) for the named gem (if any)
+ version_array = getLocalVersions(gemName)
+ # and check to see if the "newVersion" of this gem has already been
+ # installed locally; if so just return (nothing to do here...move along)
+ return if version_array && version_array.include?(newVersion)
+ # otherwise the gem is either not installed locally or the latest version of that gem
+ # available from the @gemSource is not installed locally, so install it
+ installGem(gemName, newVersion)
+ end
+
+ def installListedGems
+ uri = URI(@gemListURI)
+ begin
+ response = Net::HTTP.get_response(uri)
+ case response
+ when Net::HTTPSuccess
+ response.body.split.each { |gemNameFromFile|
+ gemName = gemNameFromFile.chomp
+ addToInstalledGems(gemName)
+ }
+ else
+ puts response.body
+ end
+ rescue Exception => e
+ # catches errors that might occur when trying to retrieve the list
+ # of gems to install from the gemSource
+ puts e.message
+ e.backtrace.each { |line| puts line }
+ end
end
- def installGem(gemName)
+ def installGem(gemName, newVersion)
# Can install from the gem mirror now, no need for absolute path
- puts "installing gem #{gemName}"
- %x[gem install --no-ri --no-rdoc #{gemName}]
+ puts "installing gem #{gemName} (#{newVersion})"
+ %x[gem install --no-ri --no-rdoc #{gemName} --source #{@gemSource} --version #{newVersion}]
end
end
View
@@ -19,6 +19,20 @@
require 'razor_microkernel/rz_mk_fact_manager'
require 'razor_microkernel/rz_mk_configuration_manager'
require 'razor_microkernel/rz_mk_kernel_module_manager'
+require 'razor_microkernel/rz_mk_gem_controller'
+
+# load gems in the list available at #{mk_gemlist_uri} from the gem mirror
+# at #{mk_gem_mirror_uri} into the Microkernel (Note; only gems that do not
+# exist yet or gems who's latest version available from the stated gem mirror
+# will be installed; existing versions of these gems will not be reinstalled
+# by this method)
+def load_gems(mk_gem_mirror_uri, mk_gemlist_uri)
+ logger.debug("reloading gems from #{mk_gem_mirror_uri} using list at #{mk_gemlist_uri}")
+ gemController = (RazorMicrokernel::RzMkGemController).instance
+ gemController.gemSource = mk_gem_mirror_uri
+ gemController.gemListURI = mk_gemlist_uri
+ gemController.installListedGems
+end
# this method is used to load a list of Tiny Core Linux extensions
# as the Microkernel Controller is starting up (or restarting).
@@ -181,6 +195,9 @@ def first_checkin_performed
registration_manager = RazorMicrokernel::RzMkRegistrationManager.new(registration_uri,
exclude_pattern, fact_manager)
+ # "load" the appropriate gems into the Microkernel
+ load_gems(config_manager.mk_gem_mirror_uri, config_manager.mk_gemlist_uri)
+
# and load the TCL extensions from the configuration file (if any exist)
load_tcl_extensions(config_manager.mk_tce_install_list_uri, config_manager.mk_tce_mirror_uri)
View
@@ -26,7 +26,7 @@
# mount our servlets as directories under our HTTP server's URI
-s.mount("/gems", HTTPServlet::FileHandler, "/tmp/gem-mirror")
+s.mount("/gem-mirror", HTTPServlet::FileHandler, "/tmp/gem-mirror")
# setup the server to shut down if the process is shut down
View
@@ -5,4 +5,4 @@ gem: --no-ri --no-rdoc
:bulk_threshold: 1000
:update_sources: true
:sources:
-- http://localhost:2158/gems/
+- http://localhost:2158/gem-mirror/
View
@@ -8,16 +8,24 @@
require 'yaml'
require 'razor_microkernel/rz_network_utils'
require 'razor_microkernel/rz_mk_gem_controller'
+require 'razor_microkernel/rz_mk_configuration_manager'
# Start the Gem mirror so we can install from it
%x[sudo /usr/local/bin/rz_mk_gem_mirror.rb 2>&1 > /tmp/rz_mk_gem_mirror.out]
-# First, install the gems that we'll need later on. Note: we are taking
-# advantage of the default values for the second argument to the
-# RzMkGemController constructor here (since our gem list file is called
-# "gem.list", we don't need to specify it's value)
-gemController = RazorMicrokernel::RzMkGemController.new("/opt/gems")
-gemController.installAllGems
+# First, install the gems that we'll need later on. Note: if the parameters
+# needed to find an external mirror are not specified, we'll take advantage
+# of the default values for the two input arguments to the RzMkGemController
+# constructor here (since we use the "http://localhost:2158/gem-mirror" URI
+# for our local gem mirror and the "gem.list" file, which contains the list
+# of gems to install from that mirror, is in the "gems/gem.list" file under
+# that local mirror URI)
+gemController = (RazorMicrokernel::RzMkGemController).instance
+mk_conf_filename = RazorMicrokernel::RzMkConfigurationManager::MK_CONF_FILE
+mk_conf = YAML::load(File.open(mk_conf_filename))
+gemController.gemSource = mk_conf['mk_gem_mirror_uri']
+gemController.gemListURI = mk_conf['mk_gemlist_uri']
+gemController.installListedGems
# Now that we've installed the facter gem, need do do a bit more work
# first, determine where the facter gem's library is at (will need that later,
View
@@ -10,3 +10,5 @@ mk_tce_install_list_uri: http://localhost:2157/tinycorelinux/tce-install-list
mk_checkin_skew: 5
mk_fact_excl_pattern: (^facter.*$)|(^id$)|(^kernel.*$)|(^memoryfree$)|(^operating.*$)|(^osfamily$)|(^path$)|(^ps$)|(^ruby.*$)|(^selinux$)|(^ssh.*$)|(^swap.*$)|(^timezone$)|(^uniqueid$)|(^uptime.*$)|(.*json_str$)
mk_log_level: Logger::INFO
+mk_gem_mirror_uri: http://localhost:2158/gem-mirror
+mk_gemlist_uri: http://localhost:2158/gem-mirror/gems/gem.list
View
@@ -10,3 +10,5 @@ mk_tce_install_list_uri: http://localhost:2157/tinycorelinux/tce-install-list
mk_checkin_skew: 5
mk_fact_excl_pattern: (^facter.*$)|(^id$)|(^kernel.*$)|(^memoryfree$)|(^operating.*$)|(^osfamily$)|(^path$)|(^ps$)|(^ruby.*$)|(^selinux$)|(^ssh.*$)|(^swap.*$)|(^timezone$)|(^uniqueid$)|(^uptime.*$)|(.*json_str$)
mk_log_level: Logger::DEBUG
+mk_gem_mirror_uri: http://localhost:2158/gem-mirror
+mk_gemlist_uri: http://localhost:2158/gem-mirror/gems/gem.list

0 comments on commit 0dca9be

Please sign in to comment.