Merge branch 'master' of ssh://shinken.git.sourceforge.net/gitroot/shinken/shinken
[shinken.git] / setup.py
blobda9069373b8c61b879d007f9f8b252f4eb090cdf
1 #!/usr/bin/env python
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/>.
23 from setuptools import setup, find_packages
24 from glob import glob
25 import os, sys
26 import ConfigParser
27 try:
28 import pwd
29 import grp
30 except ImportError:
31 # assume non-unix platform
32 pass
34 # Shinken requires Python 2.4, but does not support Python 3.x yet.
35 try:
36 python_version = sys.version_info
37 except:
38 python_version = (1,5)
41 ## Make sure people are using Python 2.4 or higher
42 if python_version < (2, 4):
43 sys.exit("Shinken require as a minimum Python 2.4.x, sorry")
44 elif python_version >= (3,):
45 sys.exit("Shinken is not yet compatible with Python3k, sorry")
48 from distutils import log
49 from distutils.core import Command
50 from distutils.command.build import build as _build
51 from distutils.command.install import install as _install
52 from distutils.util import change_root
54 class build(_build):
55 sub_commands = _build.sub_commands + [
56 ('build_config', None),
58 user_options = _build.user_options + [
59 ('build-config', None, 'directory to build the configfiles to'),
61 def initialize_options(self):
62 _build.initialize_options(self)
63 self.build_config = None
65 def finalize_options (self):
66 _build.finalize_options(self)
67 if self.build_config is None:
68 self.build_config = os.path.join(self.build_base, 'etc')
70 class install(_install):
71 sub_commands = _install.sub_commands + [
72 ('install_config', None),
74 user_options = _install.user_options + [
75 ('etc-path=', None, 'read-only single-machine data'),
76 ('var-path=', None, 'modifiable single-machine data'),
77 ('plugins-path=', None, 'program executables'),
80 def initialize_options(self):
81 _install.initialize_options(self)
82 self.etc_path = None
83 self.var_path = None
84 self.var_owner = None
85 self.var_group = None
86 self.plugins_path = None
88 def finalize_options(self):
89 _install.finalize_options(self)
90 if self.etc_path is None:
91 self.etc_path = paths_and_owners['etc']['path']
92 if self.var_path is None:
93 self.var_path = paths_and_owners['var']['path']
94 self.var_owner = paths_and_owners['var']['owner']
95 self.var_group = paths_and_owners['var']['group']
96 if self.plugins_path is None:
97 self.plugins_path = paths_and_owners['libexec']['path']
98 if self.root:
99 for attr in ('etc_path', 'var_path', 'plugins_path'):
100 setattr(self, attr, change_root(self.root, getattr(self, attr)))
103 class build_config(Command):
104 description = "build the shinken config files"
106 user_options = [
107 ('build-dir=', None, "directory to build the configfiles to"),
110 def initialize_options (self):
111 self.build_dir = None
112 self.build_base = None
113 self.etc_path = None
114 self.var_path = None
115 self.var_owner = None
116 self.var_group = None
117 self.plugins_path = None
119 self._install_scripts = None
121 def finalize_options (self):
122 self.set_undefined_options('build',
123 ('build_base', 'build_base'),
124 ('build_config', 'build_dir'),
126 self.set_undefined_options('install',
127 ('install_scripts', '_install_scripts'),
129 self.set_undefined_options('install_config',
130 ('etc_path', 'etc_path'),
131 ('var_path', 'var_path'),
132 ('plugins_path', 'plugins_path'),
133 ('var_owner', 'var_owner'),
134 ('var_group', 'var_group'),
136 if self.build_dir is None:
137 self.build_dir = os.path.join(self.build_base, 'etc')
138 #self.etc_path = os.path.join(self.etc_path, 'shinken')
139 #self.var_path = os.path.join(self.var_path, 'lib', 'shinken')
140 print "TOTO"*100
141 print self.etc_path, self.var_path
144 def run(self):
145 if not self.dry_run:
146 self.mkpath(self.build_dir)
147 self.generate_default_shinken_file()
148 self.update_configfiles()
150 def generate_default_shinken_file(self):
151 # The default file must have good values for the directories:
152 # etc, var and where to push scripts that launch the app.
153 templatefile = "bin/default/shinken.in"
154 outfile = os.path.join(self.build_base, "bin/default/shinken")
156 log.info('generating %s from %s', outfile, templatefile)
157 if not self.dry_run:
158 self.mkpath(os.path.dirname(outfile))
159 # Read the template file
160 f = open(templatefile)
161 buf = f.read()
162 f.close
163 # substitute
164 buf = buf.replace("$ETC$", self.etc_path)
165 buf = buf.replace("$VAR$", self.var_path)
166 buf = buf.replace("$SCRIPTS_BIN$", self._install_scripts)
167 # write out the new file
168 f = open(outfile, "w")
169 f.write(buf)
170 f.close()
172 def update_configfiles(self):
173 # Here, even with --root we should change the file with good values
174 # then update the /etc/*d.ini files ../var value with the real var one
176 # Open a /etc/*d.ini file and change the ../var occurence with a
177 # good value from the configuration file
178 for name in ('brokerd.ini',
179 'schedulerd.ini',
180 'pollerd.ini',
181 'reactionnerd.ini'):
182 inname = os.path.join('etc', name)
183 outname = os.path.join(self.build_dir, name)
184 log.info('updating path in %s', outname)
185 update_file_with_string(inname, outname,
186 "../var", self.var_path)
188 # And now the resource.cfg path with the value of libexec path
189 # Replace the libexec path by the one in the parameter file
190 for name in ('resource.cfg', ):
191 inname = os.path.join('etc', name)
192 outname = os.path.join(self.build_dir, name)
193 log.info('updating path in %s', outname)
194 update_file_with_string(inname, outname,
195 "/usr/local/shinken/libexec",
196 self.plugins_path)
198 # And update the nagios.cfg file for all /usr/local/shinken/var
199 # value with good one
200 for name in ('nagios.cfg',
201 'shinken-specific.cfg',
202 'shinken-specific-high-availability.cfg',
203 'shinken-specific-load-balanced-only.cfg',
205 inname = os.path.join('etc', name)
206 outname = os.path.join(self.build_dir, name)
207 log.info('updating path in %s', outname)
208 update_file_with_string(inname, outname,
209 "/usr/local/shinken/var",
210 self.var_path)
213 class install_config(Command):
214 description = "install the shinken config files"
216 user_options = [
217 ('install-dir=', 'd', "directory to install config files to"),
218 ('build-dir=','b', "build directory (where to install from)"),
219 ('force', 'f', "force installation (overwrite existing files)"),
220 ('skip-build', None, "skip the build steps"),
223 boolean_options = ['force', 'skip-build']
225 def initialize_options(self):
226 self.build_dir = None
227 self.force = None
228 self.skip_build = None
229 self.owner = None
230 self.group = None
232 self.root = None
233 self.etc_path = None # typically /etc on Posix systems
234 self.var_path = None # typically /var on Posix systems
235 self.var_owner = None # typically shinken
236 self.var_group = None # typically shinken too
237 self.plugins_path = None # typically /libexec on Posix systems
239 def finalize_options(self):
240 self.set_undefined_options('build',
241 ('build_config', 'build_dir'))
242 self.set_undefined_options('install',
243 ('root', 'root'),
244 ('etc_path', 'etc_path'),
245 ('var_path', 'var_path'),
246 ('var_owner', 'var_owner'),
247 ('var_group', 'var_group'),
248 ('plugins_path', 'plugins_path'))
249 if self.owner is None and pwd:
250 self.owner = pwd.getpwuid(os.getuid())[0]
251 if self.group is None and grp:
252 self.group = grp.getgrgid(os.getgid())[0]
255 def run(self):
256 #log.warn('>>> %s', self.lib)
257 log.warn('>>> %s', self.etc_path)
258 if not self.skip_build:
259 self.run_command('build_config')
260 self.outfiles = self.copy_tree(self.build_dir, self.etc_path)
263 if pwd:
264 # assume a posix system
265 uid = self.get_uid(self.owner)
266 gid = self.get_gid(self.group)
267 for file in self.get_outputs():
268 log.info("Changing owner of %s to %s:%s", file, self.owner, self.group)
269 if not self.dry_run:
270 os.chown(file, uid, gid)
271 # And set the /var/lib/shinken in correct owner too
272 # TODO : (j gabes) I can't access to self.var_owner (None) and
273 # I don't know how to change it o I use the global variables
274 var_uid = self.get_uid(var_owner)
275 var_gid = self.get_uid(var_group)
276 if not self.dry_run:
277 os.chown(self.var_path, var_uid, var_gid)
280 def get_inputs (self):
281 return self.distribution.configs or []
283 def get_outputs(self):
284 return self.outfiles or []
286 @staticmethod
287 def _chown(path, owner, group):
288 log.info("Changing owner of %s to %s:%s", path, owner, group)
289 if not self.dry_run:
290 os.chown(path, uid, gid)
291 for root, dirs, files in os.walk(path):
292 for path in itertools.chain(dirs, files):
293 path = os.path.join(root, path)
297 @staticmethod
298 def get_uid(user_name):
299 try:
300 return pwd.getpwnam(user_name)[2]
301 except KeyError, exp:
302 raise DistutilsOptionError("The user %s is unknown."
303 "Maybe you should create this user"
304 % user_name)
306 @staticmethod
307 def get_gid(group_name):
308 try:
309 return grp.getgrnam(group_name)[2]
310 except KeyError, exp:
311 raise DistutilsOptionError("The group %s is unknown."
312 "Maybe you should create this group"
313 % group_name)
316 def update_file_with_string(infilename, outfilename, match, new_string):
317 f = open(infilename)
318 buf = f.read()
319 f.close()
320 buf = buf.replace(match, new_string)
321 f = open(outfilename, "w")
322 f.write(buf)
323 f.close()
326 #Set the default values for the paths
327 #owners and groups
328 if os.name == 'nt':
329 paths_and_owners = {'var':{'path': "c:\\shinken\\var",
330 'owner': None,
331 'group': None },
332 'etc': {'path': "c:\\shinken\\etc",
333 'owner': None,
334 'group': None},
335 'libexec': {'path': "c:\\shinken\\libexec",
336 'owner': None,
337 'group': None},
339 else:
340 paths_and_owners = {'var': {'path': "/var/lib/shinken/",
341 'owner' : 'shinken',
342 'group' : 'shinken' },
343 'etc': {'path': "/etc/shinken",
344 'owner': 'shinken',
345 'group': 'shinken'},
346 'libexec': {'path': "/usr/lib/shinken/plugins",
347 'owner': 'shinken',
348 'group': 'shinken'},
351 required_pkgs = []
352 if sys.version_info < (2, 5):
353 required_pkgs.append('pyro<4')
354 else:
355 required_pkgs.append('pyro')
356 if sys.version_info < (2, 6):
357 required_pkgs.append('multiprocessing')
359 etc_path = paths_and_owners['etc']['path']
360 etc_root = os.sep.join(etc_path.split(os.sep)[:-1])
361 libexec_path = paths_and_owners['libexec']['path']
362 var_path = paths_and_owners['var']['path']
363 var_owner = paths_and_owners['var']['owner']
364 var_group = paths_and_owners['var']['group']
366 setup(
367 cmdclass = {'build': build,
368 'install': install,
369 'build_config': build_config,
370 'install_config': install_config},
371 name = "Shinken",
372 version = "0.5",
373 packages = find_packages(),
374 package_data = {'':['*.py','modules/*.py','modules/*/*.py']},
375 description = "Shinken is a monitoring tool compatible with Nagios configuration and plugins",
376 long_description=open('README').read(),
377 author = "Gabes Jean",
378 author_email = "naparuba@gmail.com",
379 license = "GNU Affero General Public License",
380 url = "http://www.shinken-monitoring.org",
381 zip_safe=False,
382 classifiers=['Development Status :: 5 - Production/Stable',
383 'Environment :: Console',
384 'Intended Audience :: System Administrators',
385 'License :: OSI Approved :: GNU Affero General Public License v3',
386 'Operating System :: MacOS :: MacOS X',
387 'Operating System :: Microsoft :: Windows',
388 'Operating System :: POSIX',
389 'Programming Language :: Python',
390 'Topic :: System :: Monitoring',
391 'Topic :: System :: Networking :: Monitoring',
394 install_requires = [
395 required_pkgs
398 scripts = glob('bin/shinken-[!_]*'),
399 data_files=[(etc_path,
400 [# nagios/shinken global config
401 #"etc/nagios.cfg",
402 'etc/nagios-windows.cfg',
403 #'etc/shinken-specific.cfg',
404 #'etc/shinken-specific-high-availability.cfg',
405 #'etc/shinken-specific-load-balanced-only.cfg',
407 # daemon configs
408 #'etc/brokerd.ini',
409 'etc/brokerd-windows.ini',
410 #'etc/pollerd.ini',
411 'etc/pollerd-windows.ini',
412 #'etc/reactionnerd.ini',
413 #'etc/schedulerd.ini',
414 'etc/schedulerd-windows.ini',
416 # other configs
417 'etc/commands.cfg',
418 'etc/contactgroups.cfg',
419 'etc/dependencies.cfg',
420 'etc/escalations.cfg',
421 'etc/hostgroups.cfg',
422 'etc/resource.cfg',
423 'etc/servicegroups.cfg',
424 'etc/templates.cfg',
425 'etc/timeperiods.cfg',
427 (os.path.join(etc_path, 'objects', 'hosts'),
428 glob('etc/objects/hosts/[!_]*.cfg')),
429 (os.path.join(etc_path, 'objects', 'services'),
430 glob('etc/objects/services/[!_]*.cfg')),
431 (os.path.join(etc_path, 'objects', 'contacts'),
432 glob('etc/objects/contacts/[!_]*.cfg')),
433 (os.path.join(etc_path, 'certs') ,
434 glob('etc/certs/[!_]*.pem')),
435 (os.path.join('/etc', 'init.d'),
436 ['bin/init.d/shinken',
437 'bin/init.d/shinken-arbiter',
438 'bin/init.d/shinken-broker',
439 'bin/init.d/shinken-poller',
440 'bin/init.d/shinken-reactionner',
441 'bin/init.d/shinken-scheduler']),
442 (os.path.join(etc_root, 'default',),
443 ['bin/default/shinken']),
444 (var_path, ['var/void_for_git']),
445 (libexec_path, ['libexec/check.sh']),
450 # We will chown shinken:shinken for all /etc/shinken
451 # and /var/lib/shinken.
454 #if os.name != 'nt' and ('install' in sys.argv or 'sdist' in sys.argv):
455 # for dir in ['etc', 'var']:
456 # _chown(paths_and_owners[dir]['path'],
457 # paths_and_owners[dir]['owner'],
458 # paths_and_owners[dir]['owner'])