#!/usr/bin/python2.7
# -*- coding: utf-8 -*-
#
# Univention Directory Manager Modules
#  check univentionHost objects for missing associatedDomain
#  attribute and set if dnsZone is obvious
#
# 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 sys
import univention.admin.uldap as uldap
from optparse import OptionParser

usage = '''
%prog [-v] [-a] [-c]

Script will only add missing associatedDomain with [-a]
without that missing Attributes will only be shown

Use -v to also get a list of computer objects, which have mutliple
DNSZones and so cannot be associated to one asscoiatedDomain entry
'''
parser = OptionParser(usage)
parser.add_option("-v", "--verbose",
                    action="store_true", dest="verbose",
                    help=("print more output"))
parser.add_option("-a", "--auto-add",
                    action="store_true", dest="auto_add",
                    help=("automatically add missing associatedDomain"))
parser.add_option("-c", "--complete-search",
                    action="store_true", dest="complete_search",
                    help=("search complete ldap for computer objects"))
(options, args) = parser.parse_args()

lo, position = uldap.getAdminConnection()
ldap_base = position.getBase()

if options.complete_search:
	computers_base = ldap_base
else:
	computers_base = 'cn=computers,'+ldap_base
dns_base = ldap_base

# get computer objects without associatedDomain
# computers = {{'cn': ['dn']}
computers = {}
for dn, attribute in lo.search('(&(objectClass=univentionHost)(!(associatedDomain=*)))', attr=['cn'], base=computers_base):
	cn = attribute['cn'][0]
	if cn not in computers:
		computers[cn] = []
	computers[cn].append(dn)

if len(computers) == 0:
	print "No Hosts with missing associatedDomain found"
	sys.exit(0)

# get dnszones for computer objects
# computer_zones = {{'cn': ['zone', 'zone', '...']}
computer_zones = {}
for dn, attribute in lo.search('objectClass=dNSZone', attr=['relativeDomainName', 'zoneName'], base=dns_base):
	computer = attribute['relativeDomainName'][0]
	if computer in computers:
		if computer not in computer_zones:
			computer_zones[computer] = []
		computer_zones[computer].append(attribute['zoneName'][0])

if len(computer_zones) == 0:
	print "No Hosts with associated DNSZOne found."
	sys.exit(0)

# add missing associatedDomain attribute if dnszone is obvious
modified_objects = 0
objects_to_modify = 0
for computer in computers:
	dn = computers[computer][0]
	try:
		if len(computer_zones[computer]) == 1:
			if options.auto_add:
				lo.modify(dn, [('associatedDomain', '', computer_zones[computer])])
				modified_objects += 1
				if options.verbose:
					print "Added associatedDomain %s to Host %s" % (computer_zones[computer][0], dn)
			else:
				objects_to_modify += 1
				print "Missing associatedDomain %s at Host %s" % (computer_zones[computer][0], dn)
		else:
			if options.verbose:
				print "Multiple DNSZones for Host %s:" % dn
				for dns_zone in computer_zones[computer]:
					print "DNSZone: %s" % dns_zone
	except:
		pass # no zone for host - nothing to do 

if options.auto_add:
	print "%s Objects modified" % modified_objects
else:
	print "%s Objects could be modified" % objects_to_modify
