8b5e4091ae8acd6efa9e57d399b6812e57597c3b
[packages/precise/mcollective.git] / lib / mcollective / config.rb
1 module MCollective
2   # A pretty sucky config class, ripe for refactoring/improving
3   class Config
4     include Singleton
5
6     attr_accessor :mode
7
8     attr_reader :topicprefix, :daemonize, :pluginconf, :libdir, :configured
9     attr_reader :logfile, :keeplogs, :max_log_size, :loglevel, :logfacility
10     attr_reader :identity, :daemonize, :connector, :securityprovider, :factsource
11     attr_reader :registration, :registerinterval, :topicsep, :classesfile
12     attr_reader :rpcauditprovider, :rpcaudit, :configdir, :rpcauthprovider
13     attr_reader :rpcauthorization, :color, :configfile, :rpchelptemplate
14     attr_reader :rpclimitmethod, :logger_type, :fact_cache_time, :collectives
15     attr_reader :main_collective, :ssl_cipher, :registration_collective
16     attr_reader :direct_addressing, :direct_addressing_threshold, :ttl, :helptemplatedir
17     attr_reader :queueprefix, :default_discovery_method, :default_discovery_options
18
19     def initialize
20       @configured = false
21     end
22
23     def loadconfig(configfile)
24       set_config_defaults(configfile)
25
26       if File.exists?(configfile)
27         File.open(configfile, "r").each do |line|
28
29           # strip blank spaces, tabs etc off the end of all lines
30           line.gsub!(/\s*$/, "")
31
32           unless line =~ /^#|^$/
33             if (line =~ /(.+?)\s*=\s*(.+)/)
34               key = $1
35               val = $2
36
37               case key
38                 when "topicsep"
39                   @topicsep = val
40                 when "registration"
41                   @registration = val.capitalize
42                 when "registration_collective"
43                   @registration_collective = val
44                 when "registerinterval"
45                   @registerinterval = val.to_i
46                 when "collectives"
47                   @collectives = val.split(",").map {|c| c.strip}
48                 when "main_collective"
49                   @main_collective = val
50                 when "topicprefix"
51                   @topicprefix = val
52                 when "queueprefix"
53                   @queueprefix = val
54                 when "logfile"
55                   @logfile = val
56                 when "keeplogs"
57                   @keeplogs = val.to_i
58                 when "max_log_size"
59                   @max_log_size = val.to_i
60                 when "loglevel"
61                   @loglevel = val
62                 when "logfacility"
63                   @logfacility = val
64                 when "libdir"
65                   paths = val.split(File::PATH_SEPARATOR)
66                   paths.each do |path|
67                     raise("libdir paths should be absolute paths but '%s' is relative" % path) unless Util.absolute_path?(path)
68
69                     @libdir << path
70                     unless $LOAD_PATH.include?(path)
71                       $LOAD_PATH << path
72                     end
73                   end
74                 when "identity"
75                   @identity = val
76                 when "direct_addressing"
77                   val =~ /^1|y/i ? @direct_addressing = true : @direct_addressing = false
78                 when "direct_addressing_threshold"
79                   @direct_addressing_threshold = val.to_i
80                 when "color"
81                   val =~ /^1|y/i ? @color = true : @color = false
82                 when "daemonize"
83                   val =~ /^1|y/i ? @daemonize = true : @daemonize = false
84                 when "securityprovider"
85                   @securityprovider = val.capitalize
86                 when "factsource"
87                   @factsource = val.capitalize
88                 when "connector"
89                   @connector = val.capitalize
90                 when "classesfile"
91                   @classesfile = val
92                 when /^plugin.(.+)$/
93                   @pluginconf[$1] = val
94                 when "rpcaudit"
95                   val =~ /^1|y/i ? @rpcaudit = true : @rpcaudit = false
96                 when "rpcauditprovider"
97                   @rpcauditprovider = val.capitalize
98                 when "rpcauthorization"
99                   val =~ /^1|y/i ? @rpcauthorization = true : @rpcauthorization = false
100                 when "rpcauthprovider"
101                   @rpcauthprovider = val.capitalize
102                 when "rpchelptemplate"
103                   @rpchelptemplate = val
104                 when "rpclimitmethod"
105                   @rpclimitmethod = val.to_sym
106                 when "logger_type"
107                   @logger_type = val
108                 when "fact_cache_time"
109                   @fact_cache_time = val.to_i
110                 when "ssl_cipher"
111                   @ssl_cipher = val
112                 when "ttl"
113                   @ttl = val.to_i
114                 when "helptemplatedir"
115                   @helptemplatedir = val
116                 when "default_discovery_options"
117                   @default_discovery_options << val
118                 when "default_discovery_method"
119                   @default_discovery_method = val
120                 else
121                   raise("Unknown config parameter #{key}")
122               end
123             end
124           end
125         end
126
127         I18n.load_path = Dir[File.expand_path(File.join(File.dirname(__FILE__), "locales", "*.yml"))]
128         I18n.locale = :en
129
130         read_plugin_config_dir("#{@configdir}/plugin.d")
131
132         raise 'Identities can only match /\w\.\-/' unless @identity.match(/^[\w\.\-]+$/)
133
134         @configured = true
135
136         @libdir.each {|dir| Log.warn("Cannot find libdir: #{dir}") unless File.directory?(dir)}
137
138         if @logger_type == "syslog"
139           raise "The sylog logger is not usable on the Windows platform" if Util.windows?
140         end
141
142         PluginManager.loadclass("Mcollective::Facts::#{@factsource}_facts")
143         PluginManager.loadclass("Mcollective::Connector::#{@connector}")
144         PluginManager.loadclass("Mcollective::Security::#{@securityprovider}")
145         PluginManager.loadclass("Mcollective::Registration::#{@registration}")
146         PluginManager.loadclass("Mcollective::Audit::#{@rpcauditprovider}") if @rpcaudit
147         PluginManager << {:type => "global_stats", :class => RunnerStats.new}
148
149         Log.logmsg(:PLMC1, "The Marionette Collective version %{version} started by %{name} using config file %{config}", :info, :version => MCollective::VERSION, :name => $0, :config => configfile)
150       else
151         raise("Cannot find config file '#{configfile}'")
152       end
153     end
154
155     def set_config_defaults(configfile)
156       @stomp = Hash.new
157       @subscribe = Array.new
158       @pluginconf = Hash.new
159       @connector = "activemq"
160       @securityprovider = "Psk"
161       @factsource = "Yaml"
162       @identity = Socket.gethostname
163       @registration = "Agentlist"
164       @registerinterval = 0
165       @registration_collective = nil
166       @topicsep = "."
167       @topicprefix = "/topic/"
168       @queueprefix = "/queue/"
169       @classesfile = "/var/lib/puppet/state/classes.txt"
170       @rpcaudit = false
171       @rpcauditprovider = ""
172       @rpcauthorization = false
173       @rpcauthprovider = ""
174       @configdir = File.dirname(configfile)
175       @color = !Util.windows?
176       @configfile = configfile
177       @logger_type = "file"
178       @keeplogs = 5
179       @max_log_size = 2097152
180       @rpclimitmethod = :first
181       @libdir = Array.new
182       @fact_cache_time = 300
183       @loglevel = "info"
184       @logfacility = "user"
185       @collectives = ["mcollective"]
186       @main_collective = @collectives.first
187       @ssl_cipher = "aes-256-cbc"
188       @direct_addressing = false
189       @direct_addressing_threshold = 10
190       @default_discovery_method = "mc"
191       @default_discovery_options = []
192       @ttl = 60
193       @mode = :client
194
195       # look in the config dir for the template so users can provide their own and windows
196       # with odd paths will just work more often, but fall back to old behavior if it does
197       # not exist
198       @rpchelptemplate = File.join(File.dirname(configfile), "rpc-help.erb")
199       @rpchelptemplate = "/etc/mcollective/rpc-help.erb" unless File.exists?(@rpchelptemplate)
200       @helptemplatedir = File.dirname(@rpchelptemplate)
201     end
202
203     def read_plugin_config_dir(dir)
204       return unless File.directory?(dir)
205
206       Dir.new(dir).each do |pluginconfigfile|
207         next unless pluginconfigfile =~ /^([\w]+).cfg$/
208
209         plugin = $1
210         File.open("#{dir}/#{pluginconfigfile}", "r").each do |line|
211           # strip blank lines
212           line.gsub!(/\s*$/, "")
213           next if line =~ /^#|^$/
214           if (line =~ /(.+?)\s*=\s*(.+)/)
215             key = $1
216             val = $2
217             @pluginconf["#{plugin}.#{key}"] = val
218           end
219         end
220       end
221     end
222   end
223 end