lib/sfpagent/agent.rb in sfpagent-0.3.10 vs lib/sfpagent/agent.rb in sfpagent-0.4.0

- old
+ new

@@ -11,25 +11,25 @@ module Sfp module Agent NetHelper = Object.new.extend(Sfp::Helper::Net) - CacheDir = (Process.euid == 0 ? '/var/sfpagent' : File.expand_path(Dir.home + '/.sfpagent')) - Dir.mkdir(CacheDir, 0700) if not File.exist?(CacheDir) + Home = ((Process.euid == 0 and File.directory?('/var')) ? '/var/sfpagent' : File.expand_path(Dir.home + '/.sfpagent')) + Dir.mkdir(Home, 0700) if not File.exist?(Home) DefaultPort = 1314 - PIDFile = "#{CacheDir}/sfpagent.pid" - LogFile = "#{CacheDir}/sfpagent.log" - ModelFile = "#{CacheDir}/sfpagent.model" - AgentsDataFile = "#{CacheDir}/sfpagent.agents" + PIDFile = "#{Home}/sfpagent.pid" + LogFile = "#{Home}/sfpagent.log" + ModelFile = "#{Home}/sfpagent.model" + AgentsDataFile = "#{Home}/sfpagent.agents" - CacheModelFile = "#{CacheDir}/cache.model" + CacheModelFile = "#{Home}/cache.model" - BSigFile = "#{CacheDir}/bsig.model" - BSigPIDFile = "#{CacheDir}/bsig.pid" - BSigThreadsLockFile = "#{CacheDir}/bsig.threads.lock.#{Time.now.to_i}" + BSigFile = "#{Home}/bsig.model" + BSigPIDFile = "#{Home}/bsig.pid" + BSigThreadsLockFile = "#{Home}/bsig.threads.lock.#{Time.now.to_i}" @@logger = WEBrick::Log.new(LogFile, WEBrick::BasicLog::INFO || WEBrick::BasicLog::ERROR || WEBrick::BasicLog::FATAL || WEBrick::BasicLog::WARN) @@ -76,11 +76,11 @@ Process.daemon if opts[:daemon] and not opts[:mock] begin # check modules directory, and create it if it's not exist - opts[:modules_dir] = File.expand_path(opts[:modules_dir].to_s.strip != '' ? opts[:modules_dir].to_s : "#{CacheDir}/modules") + opts[:modules_dir] = File.expand_path(opts[:modules_dir].to_s.strip != '' ? opts[:modules_dir].to_s : "#{Home}/modules") Dir.mkdir(opts[:modules_dir], 0700) if not File.exist?(opts[:modules_dir]) # load modules from cached directory load_modules(opts) @@ -106,24 +106,26 @@ server.mount("/", Sfp::Agent::Handler, Sfp::Agent.logger) # create maintenance object maintenance = Maintenance.new(opts) - # trap signal - ['INT', 'KILL', 'HUP'].each { |signal| - trap(signal) { - maintenance.stop + if not is_windows + # trap signal + ['INT', 'KILL', 'HUP'].each do |signal| + trap(signal) { + maintenance.stop - Sfp::Agent.logger.info "Shutting down web server and BSig engine..." - bsig_engine.stop - loop do - break if bsig_engine.status == :stopped - sleep 1 - end - server.shutdown - } - } + Sfp::Agent.logger.info "Shutting down web server and BSig engine..." + bsig_engine.stop + loop do + break if bsig_engine.status == :stopped + sleep 1 + end + server.shutdown + } + end + end File.open(PIDFile, 'w', 0644) { |f| f.write($$.to_s) } bsig_engine.start @@ -195,10 +197,14 @@ return model[name] if model.has_key?(name) end nil end + def self.is_windows + (RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/) + end + def self.set_cache_model(p={}) File.open(CacheModelFile, File::RDWR|File::CREAT, 0600) do |f| f.flock(File::LOCK_EX) json = f.read model = (json.length >= 2 ? JSON[json] : {}) @@ -412,35 +418,55 @@ logger.error "Executing #{action_string} [Failed] #{e}\n#{e.backtrace.join("\n")}" end false end - # Load all modules in given directory. + ############### # + # Load all modules in given agent's module directory. + # # options: - # :dir => directory that holds all modules + # :dir => directory that contains all modules # + ############### def self.load_modules(p={}) dir = p[:modules_dir] - @@modules = [] + @@modules = {} counter = 0 - if dir != '' and File.exist?(dir) + if dir != '' and File.directory?(dir) Sfp::Agent.logger.info "Modules directory: #{dir}" - Dir.entries(dir).each { |name| - next if name == '.' or name == '..' or File.file?("#{dir}/#{name}") - module_file = "#{dir}/#{name}/#{name}.rb" - next if not File.exist?(module_file) - begin - load module_file # use 'load' than 'require' - Sfp::Agent.logger.info "Loading module #{dir}/#{name} [OK]" + Dir.entries(dir).each do |name| + module_dir = "#{dir}/#{name}" + next if name == '.' or name == '..' or not File.directory?(module_dir) + module_file = "#{module_dir}/#{name}.rb" + if File.exist?(module_file) + begin + ### use 'load' than 'require' to rewrite previous definitions + load module_file + Sfp::Agent.logger.info "Loading module #{module_dir} [OK]" + counter += 1 + @@modules[name] = { + :type => :ruby, + :home => module_dir, + :hash => get_module_hash(name) + } + rescue Exception => e + Sfp::Agent.logger.warn "Loading module #{dir}/#{name} [Failed]\n#{e}" + end + elsif File.exist?("#{module_dir}/main") + Sfp::Agent.logger.info "Loading module #{module_dir} [OK]" + @@modules[name] = { + :type => :shell, + :home => module_dir, + :hash => get_module_hash(name) + } counter += 1 - @@modules << name - rescue Exception => e - Sfp::Agent.logger.warn "Loading module #{dir}/#{name} [Failed]\n#{e}" + else + logger.warn "Module #{module_dir} is invalid." end - } + end end Sfp::Agent.logger.info "Successfully loading #{counter} modules." end def self.get_sfp(module_name) @@ -465,33 +491,17 @@ end nil end def self.get_modules - return [] if not (defined? @@modules and @@modules.is_a? Array) - data = {} - @@modules.each { |m| data[m] = get_module_hash(m) } - data + #return [] if not (defined? @@modules and @@modules.is_a?(Hash)) + #data = {} + #@@modules.each_key { |m| data[m] = get_module_hash(m) } + #data + (defined?(@@modules) ? @@modules : {}) end - # Push a list of modules to an agent using a script in $SFPAGENT_HOME/bin/install_module. - # - # parameters: - # :address => address of target agent - # :port => port of target agent - # :modules => an array of modules' name that will be pushed - # - def self.push_modules(p={}) - fail "Incomplete parameters." if !p[:modules] or !p[:address] or !p[:port] - - install_module = File.expand_path('../../../bin/install_module', __FILE__) - modules = p[:modules].join(' ') - cmd = "cd #{@@config[:modules_dir]}; #{install_module} #{p[:address]} #{p[:port]} #{modules}" - result = `#{cmd}` - (result =~ /status: ok/) - end - def self.uninstall_all_modules(p={}) return true if @@config[:modules_dir] == '' if system("rm -rf #{@@config[:modules_dir]}/*") load_modules(@@config) Sfp::Agent.logger.info "Deleting all modules [OK]" @@ -660,18 +670,18 @@ class Handler < WEBrick::HTTPServlet::AbstractServlet def initialize(server, logger) @logger = logger end - # Process HTTP Get request + # Process HTTP GET request # # uri: - # /pid => save daemon's PID to a file (only requested from localhost) - # /state => return the current state - # /model => return the current model - # /sfp => return the SFP description of a module - # /modules => return a list of available modules + # /pid => save daemon's PID to a file (only requested from localhost) + # /state => return the current state + # /model => return the current model + # /sfp => return the SFP description of a module + # /modules => return a list of available modules # /agents => return a list of agents database # /log => return last 100 lines of log file # def do_GET(request, response) status = 400 @@ -706,11 +716,13 @@ elsif path =~ /^\/sfp\/.+/ status, content_type, body = get_sfp({:module => path[10, path.length-10]}) elsif path == '/modules' - status, content_type, body = [200, 'application/json', JSON.generate(Sfp::Agent.get_modules)] + mods = {} + Sfp::Agent.get_modules.each { |name,data| mods[name] = data[:hash] } + status, content_type, body = [200, 'application/json', JSON.generate(mods)] elsif path == '/agents' status, content_type, body = [200, 'application/JSON', JSON.generate(Sfp::Agent.get_agents)] elsif path == '/log' @@ -722,11 +734,11 @@ response.status = status response['Content-Type'] = content_type response.body = body end - # Handle HTTP Post request + # Handle HTTP POST request # # uri: # /execute => receive an action's schema and execute it # def do_POST(request, response) @@ -744,20 +756,20 @@ response.status = status response['Content-Type'] = content_type response.body = body end - # Handle HTTP Put request + # Handle HTTP PUT request # # uri: - # /model => receive a new model and then save it + # /model => receive a new model and then save it # /model/cache => receive a "cache" model and then save it - # /modules => save the module if parameter "module" is provided - # /agents => save the agents' list if parameter "agents" is provided + # /modules => save the module if parameter "module" is provided + # /agents => save the agents' list if parameter "agents" is provided # /bsig => receive BSig model and receive it in cached directory # /bsig/satisfier => receive goal request from other agents and then start - # a satisfier thread to try to achieve it + # a satisfier thread in order to achieve it # def do_PUT(request, response) status = 400 content_type = body = '' if not self.trusted(request) @@ -798,18 +810,18 @@ response.status = status response['Content-Type'] = content_type response.body = body end - # Handle HTTP Delete request + # Handle HTTP DELETE request # # uri: - # /model => delete existing model + # /model => delete existing model # /model/cache => delete all cache models # /model/cache/name => delete cache model of agent "name" - # /modules => delete all modules from module database - # /modules/name => delete module "name" from module database - # /agents => delete all agents from agent database + # /modules => delete all modules from module database + # /modules/name => delete module "name" from module database + # /agents => delete all agents from agent database # /agents/name => delete "name" from agent database # /bsig => delete existing BSig model # def do_DELETE(request, response) status = 400