#!/usr/bin/python2.7
#
# Copyright 2004-2014 Univention GmbH
#
# http://www.univention.de/
#
# All rights reserved.
#
# The source code of this program is made available
# under the terms of the GNU Affero General Public License version 3
# (GNU AGPL V3) as published by the Free Software Foundation.
#
# Binary versions of this program provided by Univention to you as
# well as other copyrighted, protected or trademarked materials like
# Logos, graphics, fonts, specific documentations and configurations,
# cryptographic keys etc. are subject to a license agreement between
# you and Univention and not subject to the GNU AGPL V3.
#
# In the case you use this program under the terms of the GNU AGPL V3,
# the program is provided in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public
# License with the Debian GNU/Linux or Univention distribution in file
# /usr/share/common-licenses/AGPL-3; if not, see
# <http://www.gnu.org/licenses/>.

import getopt, sys, os, socket, copy
import univention.uldap as uuldap
import univention.config_registry

confreg = univention.config_registry.ConfigRegistry()
confreg.load()


class UniventionNagiosLDAP(object):
	def __init__(self, binddn='', bindpwd='', start_tls=2):
		try:
			if binddn:
				self.lo = univention.uldap.access( host = confreg['ldap/master'], port = confreg['ldap/master/port'], base = confreg['ldap/base'], binddn = binddn, bindpw = bindpwd, start_tls = start_tls, decode_ignorelist = [])
			else:
				self.lo = uuldap.getAdminConnection()
		except Exception, e:
			print 'E: cannot connect to ldap server: %s' % str(e)
			sys.exit(1)
		self.dnscache = {}
		self.failedFQDN = {}

	def checkFQDN(self, fqdn):
		try:
			ipaddr = socket.gethostbyname( fqdn )
		except:
			return False
		return True

	def check(self):
		print 'Searching LDAP objects... please wait... ',
		servicednlist = self.lo.searchDn( filter = '(objectClass=univentionNagiosServiceClass)' )
		print 'done'
		print 'Processing LDAP objects... please wait... ',
		for servicedn in servicednlist:
			fqdnlist = self.lo.getAttr( servicedn, 'univentionNagiosHostname' )
			for fqdn in fqdnlist:
				if not self.checkFQDN(fqdn):
					if not fqdn in self.failedFQDN:
						self.failedFQDN[fqdn] = []
					if not servicedn in self.failedFQDN[fqdn]:
						self.failedFQDN[fqdn].append(servicedn)
		print 'done'
		print ''

		if len(self.failedFQDN):
			for key in self.failedFQDN.keys():
				print 'Failed to resolve fqdn %s' % key
				for dn in self.failedFQDN[key]:
					print '   attached to %s' % dn
		else:
			print 'Everything ok.'

	def autofix(self):
		if len(self.failedFQDN):
			print ''
			for key in self.failedFQDN.keys():
				for dn in self.failedFQDN[key]:
					print 'Fixing %s' % dn
					self.removeFQDN( key, dnlist=[ dn ] )


	def removeFQDN(self, fqdn, dnlist=None):
		if not dnlist:
			dnlist = self.lo.searchDn( filter = '(&(objectClass=univentionNagiosServiceClass)(univentionNagiosHostname=%s))' % fqdn )
		for dn in dnlist:
			fqdnlist = self.lo.getAttr( dn, 'univentionNagiosHostname' )
			oldlist = copy.deepcopy(fqdnlist)
			newlist = [ item for item in oldlist if item != fqdn ]
			self.lo.modify(dn, [ ('univentionNagiosHostname', oldlist, newlist) ] )

	def replaceFQDN(self, oldfqdn, newfqdn, dnlist=None):
		if not dnlist:
			dnlist = self.lo.searchDn( filter = '(&(objectClass=univentionNagiosServiceClass)(univentionNagiosHostname=%s))' % oldfqdn )
		for dn in dnlist:
			fqdnlist = self.lo.getAttr( dn, 'univentionNagiosHostname' )
			oldlist = copy.deepcopy(fqdnlist)
			newlist = [ item for item in oldlist if item != oldfqdn ]
			newlist.append(newfqdn)
			print 'Changing %s' % dn
			self.lo.modify(dn, [ ('univentionNagiosHostname', oldlist, newlist) ] )


def usage():
	print 'univention-nagios-ldap-tool [-c] [-m -o <oldfqdn> [-n <newfqdn>]]'
	print '  -a             autofix if problem is detected'
	print '  -c             check nagios service objects'
	print '  -m             modify nagios service objects'
	print '  -o <oldfqdn>   fqdn to be replaced or removed'
	print '  -n <newfqdn>   replacement fqdn'
	print '  -D <binddn>    bind DN'
	print '  -w <bindpwd>   bind password'

def main():
	actions = { 'check': False,
				'modify': False,
				'autofix': False,
				}
	cfg = { 'oldfqdn': None,
			'newfqdn': None,
			'binddn': '',
			'bindpwd': '',
			}

	try:
		(opts, pargs) = getopt.getopt(sys.argv[1:], 'acmo:n:D:w:', [ 'check', 'modify' ])
	except:
		usage()
		sys.exit(0)

	# get command line data
	for opt in opts:
		if opt[0] == '-a':
			actions['autofix'] = True

		if opt[0] == '-c' or opt[0] == '--check':
			actions['check'] = True

		elif opt[0] == '-m' or opt[0] == '--modify':
			actions['modify'] = True

		elif opt[0] == '-o':
			cfg['oldfqdn'] = opt[1]

		elif opt[0] == '-n':
			cfg['newfqdn'] = opt[1]

		elif opt[0] == '-D':
			cfg['binddn'] = opt[1]

		elif opt[0] == '-w':
			cfg['bindpwd'] = opt[1]


	if actions['modify'] and not cfg['oldfqdn']:
		usage()
		sys.exit(1)
	else:
		if not cfg['binddn']:
			if not confreg.get('server/role','') == 'domaincontroller_master':
				print 'E: please run univention-nagios-ldap-tool as user root on'
				print 'E: domaincontroller_master or specify binddn and bindpwd!'
				sys.exit(2)
			elif os.getuid() != 0:
				print 'E: please run univention-nagios-ldap-tool as user root or'
				print 'E: specify binddn and bindpwd!'
				sys.exit(3)

		unl = UniventionNagiosLDAP(cfg['binddn'], cfg['bindpwd'])

		if actions['check']:
			unl.check()
			if actions['autofix']:
				unl.autofix()

		if actions['modify']:
			if cfg['newfqdn']:
				unl.replaceFQDN(cfg['oldfqdn'], cfg['newfqdn'])
			else:
				unl.removeFQDN(cfg['oldfqdn'])

if __name__ == '__main__':
	main()

