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
31 # assume non-unix platform
34 # Shinken requires Python 2.4, but does not support Python 3.x yet.
36 python_version
= sys
.version_info
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
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
)
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']
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"
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
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')
141 print self
.etc_path
, self
.var_path
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
)
158 self
.mkpath(os
.path
.dirname(outfile
))
159 # Read the template file
160 f
= open(templatefile
)
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")
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',
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",
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",
213 class install_config(Command
):
214 description
= "install the shinken config files"
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
228 self
.skip_build
= 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',
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]
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
)
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
)
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
)
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 []
287 def _chown(path
, owner
, group
):
288 log
.info("Changing owner of %s to %s:%s", path
, owner
, group
)
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
)
298 def get_uid(user_name
):
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"
307 def get_gid(group_name
):
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"
316 def update_file_with_string(infilename
, outfilename
, match
, new_string
):
320 buf
= buf
.replace(match
, new_string
)
321 f
= open(outfilename
, "w")
326 #Set the default values for the paths
329 paths_and_owners
= {'var':{'path': "c:\\shinken\\var",
332 'etc': {'path': "c:\\shinken\\etc",
335 'libexec': {'path': "c:\\shinken\\libexec",
340 paths_and_owners
= {'var': {'path': "/var/lib/shinken/",
342 'group' : 'shinken' },
343 'etc': {'path': "/etc/shinken",
346 'libexec': {'path': "/usr/lib/shinken/plugins",
352 if sys
.version_info
< (2, 5):
353 required_pkgs
.append('pyro<4')
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']
367 cmdclass
= {'build': build
,
369 'build_config': build_config
,
370 'install_config': install_config
},
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",
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',
398 scripts
= glob('bin/shinken-[!_]*'),
399 data_files
=[(etc_path
,
400 [# nagios/shinken global config
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',
409 'etc/brokerd-windows.ini',
411 'etc/pollerd-windows.ini',
412 #'etc/reactionnerd.ini',
413 #'etc/schedulerd.ini',
414 'etc/schedulerd-windows.ini',
418 'etc/contactgroups.cfg',
419 'etc/dependencies.cfg',
420 'etc/escalations.cfg',
421 'etc/hostgroups.cfg',
423 'etc/servicegroups.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'])