2 #Copyright (C) 2009-2011 :
3 # Gabes Jean, naparuba@gmail.com
4 # Gerhard Lausser, Gerhard.Lausser@consol.de
5 # Hartmut Goebel <h.goebel@goebel-consult.de>
6 #First version of this file from Maximilien Bersoult
8 #This file is part of Shinken.
10 #Shinken is free software: you can redistribute it and/or modify
11 #it under the terms of the GNU Affero General Public License as published by
12 #the Free Software Foundation, either version 3 of the License, or
13 #(at your option) any later version.
15 #Shinken is distributed in the hope that it will be useful,
16 #but WITHOUT ANY WARRANTY; without even the implied warranty of
17 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 #GNU Affero General Public License for more details.
20 #You should have received a copy of the GNU Affero General Public License
21 #along with Shinken. If not, see <http://www.gnu.org/licenses/>.
24 # Shinken requires Python 2.4, but does not support Python 3.x yet.
27 python_version
= sys
.version_info
29 python_version
= (1,5)
30 if python_version
< (2, 4):
31 sys
.exit("Shinken require as a minimum Python 2.4.x, sorry")
32 elif python_version
>= (3,):
33 sys
.exit("Shinken is not yet compatible with Python3k, sorry")
35 from setuptools
import setup
, find_packages
44 # assume non-unix platform
47 DEFAULT_OWNER
= 'shinken'
48 DEFAULT_GROUP
= 'shinken'
50 from distutils
import log
51 from distutils
.core
import Command
52 from distutils
.command
.build
import build
as _build
53 from distutils
.command
.install
import install
as _install
54 from distutils
.util
import change_root
55 from distutils
.errors
import DistutilsOptionError
58 sub_commands
= _build
.sub_commands
+ [
59 ('build_config', None),
61 user_options
= _build
.user_options
+ [
62 ('build-config', None, 'directory to build the config files to'),
64 def initialize_options(self
):
65 _build
.initialize_options(self
)
66 self
.build_config
= None
68 def finalize_options (self
):
69 _build
.finalize_options(self
)
70 if self
.build_config
is None:
71 self
.build_config
= os
.path
.join(self
.build_base
, 'etc')
73 class install(_install
):
74 sub_commands
= _install
.sub_commands
+ [
75 ('install_config', None),
77 user_options
= _install
.user_options
+ [
78 ('etc-path=', None, 'read-only single-machine data'),
79 ('var-path=', None, 'modifiable single-machine data'),
80 ('plugins-path=', None, 'program executables'),
81 ('owner=', None, ('change owner for etc/* and var '
82 '(default: %s)' % DEFAULT_OWNER
)),
83 ('group=', None, ('change group for etc/* and var '
84 '(default: %s)' % DEFAULT_GROUP
)),
87 def initialize_options(self
):
88 _install
.initialize_options(self
)
91 self
.plugins_path
= None
95 def finalize_options(self
):
96 _install
.finalize_options(self
)
97 if self
.etc_path
is None:
98 self
.etc_path
= default_paths
['etc']
99 if self
.var_path
is None:
100 self
.var_path
= default_paths
['var']
101 if self
.plugins_path
is None:
102 self
.plugins_path
= default_paths
['libexec']
103 if self
.owner
is None:
104 self
.owner
= DEFAULT_OWNER
105 if self
.group
is None:
106 self
.group
= DEFAULT_GROUP
109 for attr
in ('etc_path', 'var_path', 'plugins_path'):
110 setattr(self
, attr
, change_root(self
.root
, getattr(self
, attr
)))
113 class build_config(Command
):
114 description
= "build the shinken config files"
117 ('build-dir=', None, "directory to build the config files to"),
120 def initialize_options (self
):
121 self
.build_dir
= None
122 self
.build_base
= None
125 self
.plugins_path
= None
127 self
._install
_scripts
= None
129 def finalize_options (self
):
130 self
.set_undefined_options('build',
131 ('build_base', 'build_base'),
132 ('build_config', 'build_dir'),
134 self
.set_undefined_options('install',
135 ('install_scripts', '_install_scripts'),
137 self
.set_undefined_options('install_config',
138 ('etc_path', 'etc_path'),
139 ('var_path', 'var_path'),
140 ('plugins_path', 'plugins_path'),
142 if self
.build_dir
is None:
143 self
.build_dir
= os
.path
.join(self
.build_base
, 'etc')
148 self
.mkpath(self
.build_dir
)
149 self
.generate_default_shinken_file()
150 self
.update_configfiles()
152 def generate_default_shinken_file(self
):
153 # The default file must have good values for the directories:
154 # etc, var and where to push scripts that launch the app.
155 templatefile
= "bin/default/shinken.in"
156 outfile
= os
.path
.join(self
.build_base
, "bin/default/shinken")
158 log
.info('generating %s from %s', outfile
, templatefile
)
160 self
.mkpath(os
.path
.dirname(outfile
))
161 # Read the template file
162 f
= open(templatefile
)
166 buf
= buf
.replace("$ETC$", self
.etc_path
)
167 buf
= buf
.replace("$VAR$", self
.var_path
)
168 buf
= buf
.replace("$SCRIPTS_BIN$", self
._install
_scripts
)
169 # write out the new file
170 f
= open(outfile
, "w")
174 def update_configfiles(self
):
175 # Here, even with --root we should change the file with good values
176 # then update the /etc/*d.ini files ../var value with the real var one
178 # Open a /etc/*d.ini file and change the ../var occurence with a
179 # good value from the configuration file
180 for name
in daemon_ini_files
:
181 inname
= os
.path
.join('etc', name
)
182 outname
= os
.path
.join(self
.build_dir
, name
)
183 log
.info('updating path in %s', outname
)
184 update_file_with_string(inname
, outname
,
185 "../var", self
.var_path
)
187 # And now the resource.cfg path with the value of libexec path
188 # Replace the libexec path by the one in the parameter file
189 for name
in resource_cfg_files
:
190 inname
= os
.path
.join('etc', name
)
191 outname
= os
.path
.join(self
.build_dir
, name
)
192 log
.info('updating path in %s', outname
)
193 update_file_with_string(inname
, outname
,
194 "/usr/local/shinken/libexec",
197 # And update the nagios.cfg file for all /usr/local/shinken/var
198 # value with good one
199 for name
in main_config_files
:
200 inname
= os
.path
.join('etc', name
)
201 outname
= os
.path
.join(self
.build_dir
, name
)
202 log
.info('updating path in %s', outname
)
203 update_file_with_string(inname
, outname
,
204 "/usr/local/shinken/var",
208 class install_config(Command
):
209 description
= "install the shinken config files"
212 ('install-dir=', 'd', "directory to install config files to"),
213 ('build-dir=','b', "build directory (where to install from)"),
214 ('force', 'f', "force installation (overwrite existing files)"),
215 ('skip-build', None, "skip the build steps"),
218 boolean_options
= ['force', 'skip-build']
220 def initialize_options(self
):
221 self
.build_dir
= None
223 self
.skip_build
= None
228 self
.etc_path
= None # typically /etc on Posix systems
229 self
.var_path
= None # typically /var on Posix systems
230 self
.plugins_path
= None # typically /libexec on Posix systems
232 def finalize_options(self
):
233 self
.set_undefined_options('build',
234 ('build_config', 'build_dir'))
235 self
.set_undefined_options('install',
237 ('etc_path', 'etc_path'),
238 ('var_path', 'var_path'),
239 ('plugins_path', 'plugins_path'),
244 #log.warn('>>> %s', self.lib)
245 log
.warn('>>> %s', self
.etc_path
)
246 if not self
.skip_build
:
247 self
.run_command('build_config')
248 self
.outfiles
= self
.copy_tree(self
.build_dir
, self
.etc_path
)
252 # assume a posix system
253 uid
= self
.get_uid(self
.owner
)
254 gid
= self
.get_gid(self
.group
)
255 for file in self
.get_outputs():
256 log
.info("Changing owner of %s to %s:%s", file, self
.owner
, self
.group
)
258 os
.chown(file, uid
, gid
)
259 # recursivly changing permissions for etc/shinken and var/lib/shinken
260 self
.recursive_chown(self
.etc_path
, uid
, gid
, self
.owner
, self
.group
)
261 self
.recursive_chown(self
.var_path
, uid
, gid
, self
.owner
, self
.group
)
264 def get_inputs (self
):
265 return self
.distribution
.configs
or []
267 def get_outputs(self
):
268 return self
.outfiles
or []
270 def recursive_chown(self
, path
, uid
, gid
, owner
, group
):
271 log
.info("Changing owner of %s to %s:%s", path
, owner
, group
)
273 os
.chown(path
, uid
, gid
)
274 for dirname
, dirs
, files
in os
.walk(path
):
275 for path
in itertools
.chain(dirs
, files
):
276 path
= os
.path
.join(dirname
, path
)
277 os
.chown(path
, uid
, gid
)
280 def get_uid(user_name
):
282 return pwd
.getpwnam(user_name
)[2]
283 except KeyError, exp
:
284 raise DistutilsOptionError("The user %s is unknown. "
285 "Maybe you should create this user"
289 def get_gid(group_name
):
291 return grp
.getgrnam(group_name
)[2]
292 except KeyError, exp
:
293 raise DistutilsOptionError("The group %s is unknown. "
294 "Maybe you should create this group"
298 def update_file_with_string(infilename
, outfilename
, match
, new_string
):
302 buf
= buf
.replace(match
, new_string
)
303 f
= open(outfilename
, "w")
308 # Set the default values for the paths
310 default_paths
= {'var': "c:\\shinken\\var",
311 'etc': "c:\\shinken\\etc",
312 'libexec': "c:\\shinken\\libexec",
315 default_paths
= {'var': "/var/lib/shinken/",
316 'etc': "/etc/shinken",
317 'libexec': "/usr/lib/shinken/plugins",
321 if sys
.version_info
< (2, 5):
322 required_pkgs
.append('pyro<4')
324 required_pkgs
.append('pyro')
325 if sys
.version_info
< (2, 6):
326 required_pkgs
.append('multiprocessing')
328 etc_root
= os
.path
.dirname(default_paths
['etc'])
330 # nagios/shinken global config
331 main_config_files
= ('nagios.cfg',
332 'nagios-windows.cfg',
333 'shinken-specific.cfg',
334 'shinken-specific-high-availability.cfg',
335 'shinken-specific-load-balanced-only.cfg',
339 daemon_ini_files
= ('brokerd.ini',
340 'brokerd-windows.ini',
342 'receiverd-windows.ini',
344 'pollerd-windows.ini',
347 'schedulerd-windows.ini',
350 resource_cfg_files
= ('resource.cfg', )
355 cmdclass
= {'build': build
,
357 'build_config': build_config
,
358 'install_config': install_config
},
361 packages
= find_packages(),
362 package_data
= {'':['*.py','modules/*.py','modules/*/*.py']},
363 description
= "Shinken is a monitoring tool compatible with Nagios configuration and plugins",
364 long_description
=open('README').read(),
365 author
= "Gabes Jean",
366 author_email
= "naparuba@gmail.com",
367 license
= "GNU Affero General Public License",
368 url
= "http://www.shinken-monitoring.org",
370 classifiers
=['Development Status :: 5 - Production/Stable',
371 'Environment :: Console',
372 'Intended Audience :: System Administrators',
373 'License :: OSI Approved :: GNU Affero General Public License v3',
374 'Operating System :: MacOS :: MacOS X',
375 'Operating System :: Microsoft :: Windows',
376 'Operating System :: POSIX',
377 'Programming Language :: Python',
378 'Topic :: System :: Monitoring',
379 'Topic :: System :: Networking :: Monitoring',
386 scripts
= glob('bin/shinken-[!_]*'),
387 data_files
=[(default_paths
['etc'],
390 'etc/contactgroups.cfg',
391 'etc/dependencies.cfg',
392 'etc/escalations.cfg',
393 'etc/hostgroups.cfg',
394 #'etc/resource.cfg', # see above
395 'etc/servicegroups.cfg',
397 'etc/timeperiods.cfg',
399 (os
.path
.join(default_paths
['etc'], 'objects', 'hosts'),
400 glob('etc/objects/hosts/[!_]*.cfg')),
401 (os
.path
.join(default_paths
['etc'], 'objects', 'services'),
402 glob('etc/objects/services/[!_]*.cfg')),
403 (os
.path
.join(default_paths
['etc'], 'objects', 'contacts'),
404 glob('etc/objects/contacts/[!_]*.cfg')),
405 (os
.path
.join(default_paths
['etc'], 'objects', 'discovery'), tuple() ),
406 (os
.path
.join(default_paths
['etc'], 'certs') ,
407 glob('etc/certs/[!_]*.pem')),
408 (os
.path
.join('/etc', 'init.d'),
409 ['bin/init.d/shinken',
410 'bin/init.d/shinken-arbiter',
411 'bin/init.d/shinken-broker',
412 'bin/init.d/shinken-receiver',
413 'bin/init.d/shinken-poller',
414 'bin/init.d/shinken-reactionner',
415 'bin/init.d/shinken-scheduler']),
416 (os
.path
.join(etc_root
, 'default',),
417 ['build/bin/default/shinken']),
418 (default_paths
['var'], ['var/void_for_git']),
419 (default_paths
['libexec'], ['libexec/check.sh']),