module MCollective # A pretty sucky config class, ripe for refactoring/improving class Config include Singleton attr_accessor :mode attr_reader :daemonize, :pluginconf, :configured attr_reader :logfile, :keeplogs, :max_log_size, :loglevel, :logfacility attr_reader :identity, :daemonize, :connector, :securityprovider, :factsource attr_reader :registration, :registerinterval, :classesfile attr_reader :rpcauditprovider, :rpcaudit, :configdir, :rpcauthprovider attr_reader :rpcauthorization, :color, :configfile attr_reader :rpclimitmethod, :logger_type, :fact_cache_time, :collectives attr_reader :main_collective, :ssl_cipher, :registration_collective attr_reader :direct_addressing, :direct_addressing_threshold, :ttl attr_reader :default_discovery_method, :default_discovery_options attr_reader :publish_timeout, :threaded, :soft_shutdown, :activate_agents attr_reader :registration_splay, :discovery_timeout, :soft_shutdown_timeout attr_reader :connection_timeout, :default_batch_size, :default_batch_sleep_time def initialize @configured = false end def loadconfig(configfile) set_config_defaults(configfile) if File.exists?(configfile) libdirs = [] File.readlines(configfile).each do |line| # strip blank spaces, tabs etc off the end of all lines line.gsub!(/\s*$/, "") unless line =~ /^#|^$/ if (line =~ /(.+?)\s*=\s*(.+)/) key = $1.strip val = $2 begin case key when "registration" @registration = val.capitalize when "registration_collective" @registration_collective = val when "registerinterval" @registerinterval = Integer(val) when "registration_splay" @registration_splay = Util.str_to_bool(val) when "collectives" @collectives = val.split(",").map {|c| c.strip} when "main_collective" @main_collective = val when "logfile" @logfile = val when "keeplogs" @keeplogs = Integer(val) when "max_log_size" @max_log_size = Integer(val) when "loglevel" @loglevel = val when "logfacility" @logfacility = val when "libdir" paths = val.split(File::PATH_SEPARATOR) paths.each do |path| raise("libdir paths should be absolute paths but '%s' is relative" % path) unless Util.absolute_path?(path) libdirs << path end when "identity" @identity = val when "direct_addressing" @direct_addressing = Util.str_to_bool(val) when "direct_addressing_threshold" @direct_addressing_threshold = Integer(val) when "color" @color = Util.str_to_bool(val) when "daemonize" @daemonize = Util.str_to_bool(val) when "securityprovider" @securityprovider = val.capitalize when "factsource" @factsource = val.capitalize when "connector" @connector = val.capitalize when "classesfile" @classesfile = val when /^plugin.(.+)$/ @pluginconf[$1] = val when "discovery_timeout" @discovery_timeout = Integer(val) when "publish_timeout" @publish_timeout = Integer(val) when "connection_timeout" @connection_timeout = Integer(val) when "rpcaudit" @rpcaudit = Util.str_to_bool(val) when "rpcauditprovider" @rpcauditprovider = val.capitalize when "rpcauthorization" @rpcauthorization = Util.str_to_bool(val) when "rpcauthprovider" @rpcauthprovider = val.capitalize when "rpclimitmethod" @rpclimitmethod = val.to_sym when "logger_type" @logger_type = val when "fact_cache_time" @fact_cache_time = Integer(val) when "ssl_cipher" @ssl_cipher = val when "threaded" @threaded = Util.str_to_bool(val) when "ttl" @ttl = Integer(val) when "default_discovery_options" @default_discovery_options << val when "default_discovery_method" @default_discovery_method = val when "soft_shutdown" @soft_shutdown = Util.str_to_bool(val) when "soft_shutdown_timeout" @soft_shutdown_timeout = Integer(val) when "activate_agents" @activate_agents = Util.str_to_bool(val) when "default_batch_size" @default_batch_size = Integer(val) when "default_batch_sleep_time" @default_batch_sleep_time = Float(val) when "topicprefix", "topicsep", "queueprefix", "rpchelptemplate", "helptemplatedir" Log.warn("Use of deprecated '#{key}' option. This option is ignored and should be removed from '#{configfile}'") else raise("Unknown config parameter '#{key}'") end rescue ArgumentError => e raise "Could not parse value for configuration option '#{key}' with value '#{val}'" end end end end read_plugin_config_dir("#{@configdir}/plugin.d") raise 'Identities can only match /\w\.\-/' unless @identity.match(/^[\w\.\-]+$/) @configured = true libdirs.each do |dir| unless File.directory?(dir) Log.debug("Cannot find libdir: #{dir}") end # remove the old one if it exists, we're moving it to the front $LOAD_PATH.reject! { |elem| elem == dir } $LOAD_PATH.unshift dir end if @logger_type == "syslog" raise "The sylog logger is not usable on the Windows platform" if Util.windows? end PluginManager.loadclass("Mcollective::Facts::#{@factsource}_facts") PluginManager.loadclass("Mcollective::Connector::#{@connector}") PluginManager.loadclass("Mcollective::Security::#{@securityprovider}") PluginManager << {:type => "global_stats", :class => RunnerStats.new} Log.info("The Marionette Collective version #{MCollective::VERSION} started by #{$0} using config file #{configfile}") else raise("Cannot find config file '#{configfile}'") end end def set_config_defaults(configfile) @stomp = Hash.new @subscribe = Array.new @pluginconf = Hash.new @connector = "base" @securityprovider = "Base" @factsource = "Yaml" @identity = Socket.gethostname @registration = "Base" @registerinterval = 0 @registration_collective = nil @registration_splay = false @classesfile = "/var/lib/puppet/state/classes.txt" @rpcaudit = false @rpcauditprovider = "" @rpcauthorization = false @rpcauthprovider = "" @configdir = File.dirname(configfile) @color = !Util.windows? @configfile = configfile @logger_type = "file" @keeplogs = 5 @max_log_size = 2097152 @rpclimitmethod = :first @fact_cache_time = 300 @loglevel = "info" @logfacility = "user" @collectives = ["mcollective"] @main_collective = @collectives.first @ssl_cipher = "aes-256-cbc" @direct_addressing = true @direct_addressing_threshold = 10 @default_discovery_method = "mc" @default_discovery_options = [] @ttl = 60 @mode = :client @publish_timeout = 2 @threaded = false @soft_shutdown = false @soft_shutdown_timeout = nil @activate_agents = true @connection_timeout = nil @default_batch_size = 0 @default_batch_sleep_time = 1 end def libdir $LOAD_PATH end def read_plugin_config_dir(dir) return unless File.directory?(dir) Dir.new(dir).each do |pluginconfigfile| next unless pluginconfigfile =~ /^([\w]+).cfg$/ plugin = $1 File.open("#{dir}/#{pluginconfigfile}", "r").each do |line| # strip blank lines line.gsub!(/\s*$/, "") next if line =~ /^#|^$/ if (line =~ /(.+?)\s*=\s*(.+)/) key = $1.strip val = $2 @pluginconf["#{plugin}.#{key}"] = val end end end end end end