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
53 from distutils
.errors
import DistutilsOptionError
56 sub_commands
= _build
.sub_commands
+ [
57 ('build_config', None),
59 user_options
= _build
.user_options
+ [
60 ('build-config', None, 'directory to build the configfiles to'),
62 def initialize_options(self
):
63 _build
.initialize_options(self
)
64 self
.build_config
= None
66 def finalize_options (self
):
67 _build
.finalize_options(self
)
68 if self
.build_config
is None:
69 self
.build_config
= os
.path
.join(self
.build_base
, 'etc')
71 class install(_install
):
72 sub_commands
= _install
.sub_commands
+ [
73 ('install_config', None),
75 user_options
= _install
.user_options
+ [
76 ('etc-path=', None, 'read-only single-machine data'),
77 ('var-path=', None, 'modifiable single-machine data'),
78 ('plugins-path=', None, 'program executables'),
81 def initialize_options(self
):
82 _install
.initialize_options(self
)
87 self
.plugins_path
= None
89 def finalize_options(self
):
90 _install
.finalize_options(self
)
91 if self
.etc_path
is None:
92 self
.etc_path
= paths_and_owners
['etc']['path']
93 if self
.var_path
is None:
94 self
.var_path
= paths_and_owners
['var']['path']
95 self
.var_owner
= paths_and_owners
['var']['owner']
96 self
.var_group
= paths_and_owners
['var']['group']
97 if self
.plugins_path
is None:
98 self
.plugins_path
= paths_and_owners
['libexec']['path']
100 for attr
in ('etc_path', 'var_path', 'plugins_path'):
101 setattr(self
, attr
, change_root(self
.root
, getattr(self
, attr
)))
104 class build_config(Command
):
105 description
= "build the shinken config files"
108 ('build-dir=', None, "directory to build the configfiles to"),
111 def initialize_options (self
):
112 self
.build_dir
= None
113 self
.build_base
= None
116 self
.plugins_path
= None
118 self
._install
_scripts
= None
120 def finalize_options (self
):
121 self
.set_undefined_options('build',
122 ('build_base', 'build_base'),
123 ('build_config', 'build_dir'),
125 self
.set_undefined_options('install',
126 ('install_scripts', '_install_scripts'),
128 self
.set_undefined_options('install_config',
129 ('etc_path', 'etc_path'),
130 ('var_path', 'var_path'),
131 ('plugins_path', 'plugins_path'),
133 if self
.build_dir
is None:
134 self
.build_dir
= os
.path
.join(self
.build_base
, 'etc')
139 self
.mkpath(self
.build_dir
)
140 self
.generate_default_shinken_file()
141 self
.update_configfiles()
143 def generate_default_shinken_file(self
):
144 # The default file must have good values for the directories:
145 # etc, var and where to push scripts that launch the app.
146 templatefile
= "bin/default/shinken.in"
147 outfile
= os
.path
.join(self
.build_base
, "bin/default/shinken")
149 log
.info('generating %s from %s', outfile
, templatefile
)
151 self
.mkpath(os
.path
.dirname(outfile
))
152 # Read the template file
153 f
= open(templatefile
)
157 buf
= buf
.replace("$ETC$", self
.etc_path
)
158 buf
= buf
.replace("$VAR$", self
.var_path
)
159 buf
= buf
.replace("$SCRIPTS_BIN$", self
._install
_scripts
)
160 # write out the new file
161 f
= open(outfile
, "w")
165 def update_configfiles(self
):
166 # Here, even with --root we should change the file with good values
167 # then update the /etc/*d.ini files ../var value with the real var one
169 # Open a /etc/*d.ini file and change the ../var occurence with a
170 # good value from the configuration file
171 for name
in ('brokerd.ini',
175 inname
= os
.path
.join('etc', name
)
176 outname
= os
.path
.join(self
.build_dir
, name
)
177 log
.info('updating path in %s', outname
)
178 update_file_with_string(inname
, outname
,
179 "../var", self
.var_path
)
181 # And now the resource.cfg path with the value of libexec path
182 # Replace the libexec path by the one in the parameter file
183 for name
in ('resource.cfg', ):
184 inname
= os
.path
.join('etc', name
)
185 outname
= os
.path
.join(self
.build_dir
, name
)
186 log
.info('updating path in %s', outname
)
187 update_file_with_string(inname
, outname
,
188 "/usr/local/shinken/libexec",
191 # And update the nagios.cfg file for all /usr/local/shinken/var
192 # value with good one
193 for name
in ('nagios.cfg',
194 'shinken-specific.cfg',
195 'shinken-specific-high-availability.cfg',
196 'shinken-specific-load-balanced-only.cfg',
198 inname
= os
.path
.join('etc', name
)
199 outname
= os
.path
.join(self
.build_dir
, name
)
200 log
.info('updating path in %s', outname
)
201 update_file_with_string(inname
, outname
,
202 "/usr/local/shinken/var",
206 class install_config(Command
):
207 description
= "install the shinken config files"
210 ('install-dir=', 'd', "directory to install config files to"),
211 ('build-dir=','b', "build directory (where to install from)"),
212 ('force', 'f', "force installation (overwrite existing files)"),
213 ('skip-build', None, "skip the build steps"),
216 boolean_options
= ['force', 'skip-build']
218 def initialize_options(self
):
219 self
.build_dir
= None
221 self
.skip_build
= None
226 self
.etc_path
= None # typically /etc on Posix systems
227 self
.var_path
= None # typically /var on Posix systems
228 self
.var_owner
= None # typically shinken
229 self
.var_group
= None # typically shinken too
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 ('var_owner', 'var_owner'),
240 ('var_group', 'var_group'),
241 ('plugins_path', 'plugins_path'))
242 if self
.owner
is None and pwd
:
243 self
.owner
= pwd
.getpwuid(os
.getuid())[0]
244 if self
.group
is None and grp
:
245 self
.group
= grp
.getgrgid(os
.getgid())[0]
249 #log.warn('>>> %s', self.lib)
250 log
.warn('>>> %s', self
.etc_path
)
251 if not self
.skip_build
:
252 self
.run_command('build_config')
253 self
.outfiles
= self
.copy_tree(self
.build_dir
, self
.etc_path
)
257 # assume a posix system
258 uid
= self
.get_uid(self
.owner
)
259 gid
= self
.get_gid(self
.group
)
260 for file in self
.get_outputs():
261 log
.info("Changing owner of %s to %s:%s", file, self
.owner
, self
.group
)
263 os
.chown(file, uid
, gid
)
264 # And set the /var/lib/shinken in correct owner too
265 # TODO : (j gabes) I can't access to self.var_owner (None) and
266 # I don't know how to change it o I use the global variables
267 var_uid
= self
.get_uid(var_owner
)
268 var_gid
= self
.get_uid(var_group
)
270 os
.chown(self
.var_path
, var_uid
, var_gid
)
273 def get_inputs (self
):
274 return self
.distribution
.configs
or []
276 def get_outputs(self
):
277 return self
.outfiles
or []
280 def _chown(path
, owner
, group
):
281 log
.info("Changing owner of %s to %s:%s", path
, owner
, group
)
283 os
.chown(path
, uid
, gid
)
284 for root
, dirs
, files
in os
.walk(path
):
285 for path
in itertools
.chain(dirs
, files
):
286 path
= os
.path
.join(root
, path
)
289 def get_uid(user_name
):
291 return pwd
.getpwnam(user_name
)[2]
292 except KeyError, exp
:
293 raise DistutilsOptionError("The user %s is unknown. "
294 "Maybe you should create this user"
298 def get_gid(group_name
):
300 return grp
.getgrnam(group_name
)[2]
301 except KeyError, exp
:
302 raise DistutilsOptionError("The group %s is unknown. "
303 "Maybe you should create this group"
307 def update_file_with_string(infilename
, outfilename
, match
, new_string
):
311 buf
= buf
.replace(match
, new_string
)
312 f
= open(outfilename
, "w")
317 #Set the default values for the paths
320 paths_and_owners
= {'var':{'path': "c:\\shinken\\var",
323 'etc': {'path': "c:\\shinken\\etc",
326 'libexec': {'path': "c:\\shinken\\libexec",
331 paths_and_owners
= {'var': {'path': "/var/lib/shinken/",
333 'group' : 'shinken' },
334 'etc': {'path': "/etc/shinken",
337 'libexec': {'path': "/usr/lib/shinken/plugins",
343 if sys
.version_info
< (2, 5):
344 required_pkgs
.append('pyro<4')
346 required_pkgs
.append('pyro')
347 if sys
.version_info
< (2, 6):
348 required_pkgs
.append('multiprocessing')
350 etc_path
= paths_and_owners
['etc']['path']
351 etc_root
= os
.path
.dirname(etc_path
)
352 libexec_path
= paths_and_owners
['libexec']['path']
353 var_path
= paths_and_owners
['var']['path']
354 var_owner
= paths_and_owners
['var']['owner']
355 var_group
= paths_and_owners
['var']['group']
358 cmdclass
= {'build': build
,
360 'build_config': build_config
,
361 'install_config': install_config
},
364 packages
= find_packages(),
365 package_data
= {'':['*.py','modules/*.py','modules/*/*.py']},
366 description
= "Shinken is a monitoring tool compatible with Nagios configuration and plugins",
367 long_description
=open('README').read(),
368 author
= "Gabes Jean",
369 author_email
= "naparuba@gmail.com",
370 license
= "GNU Affero General Public License",
371 url
= "http://www.shinken-monitoring.org",
373 classifiers
=['Development Status :: 5 - Production/Stable',
374 'Environment :: Console',
375 'Intended Audience :: System Administrators',
376 'License :: OSI Approved :: GNU Affero General Public License v3',
377 'Operating System :: MacOS :: MacOS X',
378 'Operating System :: Microsoft :: Windows',
379 'Operating System :: POSIX',
380 'Programming Language :: Python',
381 'Topic :: System :: Monitoring',
382 'Topic :: System :: Networking :: Monitoring',
389 scripts
= glob('bin/shinken-[!_]*'),
390 data_files
=[(etc_path
,
391 [# nagios/shinken global config
393 'etc/nagios-windows.cfg',
394 #'etc/shinken-specific.cfg',
395 #'etc/shinken-specific-high-availability.cfg',
396 #'etc/shinken-specific-load-balanced-only.cfg',
400 'etc/brokerd-windows.ini',
402 'etc/pollerd-windows.ini',
403 #'etc/reactionnerd.ini',
404 #'etc/schedulerd.ini',
405 'etc/schedulerd-windows.ini',
409 'etc/contactgroups.cfg',
410 'etc/dependencies.cfg',
411 'etc/escalations.cfg',
412 'etc/hostgroups.cfg',
414 'etc/servicegroups.cfg',
416 'etc/timeperiods.cfg',
418 (os
.path
.join(etc_path
, 'objects', 'hosts'),
419 glob('etc/objects/hosts/[!_]*.cfg')),
420 (os
.path
.join(etc_path
, 'objects', 'services'),
421 glob('etc/objects/services/[!_]*.cfg')),
422 (os
.path
.join(etc_path
, 'objects', 'contacts'),
423 glob('etc/objects/contacts/[!_]*.cfg')),
424 (os
.path
.join(etc_path
, 'certs') ,
425 glob('etc/certs/[!_]*.pem')),
426 (os
.path
.join('/etc', 'init.d'),
427 ['bin/init.d/shinken',
428 'bin/init.d/shinken-arbiter',
429 'bin/init.d/shinken-broker',
430 'bin/init.d/shinken-poller',
431 'bin/init.d/shinken-reactionner',
432 'bin/init.d/shinken-scheduler']),
433 (os
.path
.join(etc_root
, 'default',),
434 ['bin/default/shinken']),
435 (var_path
, ['var/void_for_git']),
436 (libexec_path
, ['libexec/check.sh']),
441 # We will chown shinken:shinken for all /etc/shinken
442 # and /var/lib/shinken.
445 #if os.name != 'nt' and ('install' in sys.argv or 'sdist' in sys.argv):
446 # for dir in ['etc', 'var']:
447 # _chown(paths_and_owners[dir]['path'],
448 # paths_and_owners[dir]['owner'],
449 # paths_and_owners[dir]['owner'])