#-*- coding: utf-8 -*-

#Copyright 2008 Calculate Pack, http://www.calculate-linux.ru
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.
import os
import cl_base
import cl_utils
import hashlib

class fillVars(object, cl_base.glob_attr):

    def getHash(self, password, encrypt):
        """Получить хеш пароля

        password - пароль
        encrypt - алгоритм шифрования, например '{SSHA}'
        """
        runStr='slappasswd -s %s -h %s' %(password, encrypt)
        res = self._runos(runStr)
        if res:
            return res.strip()
        print "Error generate hash (slappasswd)"
        exit(1)

    def get_cl_profile_path(self):
        """список накладываемых профилей при установке, наложении профилей"""
        profpath = []
        profPaths = ['/usr/lib/calculate/calculate-server/profile',
                     '/var/calculate/remote/server-profile',
                     '/var/calculate/server-profile']
        for profPath in profPaths:
            if os.path.exists(profPath):
               profpath.append(profPath)
        return profpath

    def get_ld_base_dn(self):
        """базовый DN LDAP"""
        return "dc=%s"%(self.Get('ld_base_root'))

    def get_ld_bind_dn(self):
        """bind DN LDAP"""
        return "cn=%s,%s"% (self.Get('ld_bind_login'),
                self.Get('ld_base_dn'))

    def get_ld_bind_hash(self):
        """hash пароля для пользователя для чтения"""
        return self.getHash(self.Get('ld_bind_pw'), self.Get('ld_encrypt'))

    def get_ld_temp_dn(self):
        #DN временного пользователя root (для инициализации базы данных)
        return "cn=ldaproot,%s"%self.Get('ld_base_dn')

    def get_ld_temp_pw(self):
        """пароль временного пользователя root"""
        return cl_utils.genpassword().strip()

    def get_ld_temp_hash(self):
        """hash пароля временного root"""
        return self.getHash(self.Get('ld_temp_pw'), self.Get('ld_encrypt'))

    def get_ld_admin_dn(self):
        """DN  пользователя root"""
        return "cn=%s,%s"% (self.Get('ld_admin_login'),self.Get('ld_base_dn'))

    def get_ld_admin_hash(self):
        """hash пароля root"""
        return self.getHash(self.Get('ld_admin_pw'), self.Get('ld_encrypt'))

    def get_ld_admin_pw(self):
        """пароль root"""
        return cl_utils.genpassword().strip()

    def get_ld_services_dn(self):
        """DN для всех сервисов"""
        return "ou=%s,%s"%(self.Get('ld_services'), self.Get('ld_base_dn'))

    def get_ld_unix_dn(self):
        """DN сервиса Unix"""
        return "ou=%s,%s" %(self.Get('ld_unix_login'),
            self.Get('ld_services_dn'))

    def get_ld_unix_pw(self):
        """пароль администратора сервиса Unix"""
        return cl_utils.genpassword().strip()

    def get_ld_unix_hash(self):
        """hash пароля администратора сервиса Unix"""
        return self.getHash(self.Get('ld_unix_pw'), self.Get('ld_encrypt'))

    def get_ld_samba_dn(self):
        """DN сервиса Samba"""
        return "ou=%s,%s" %(self.Get('ld_samba_login'),
            self.Get('ld_services_dn'))

    def get_ld_samba_pw(self):
        """пароль администратора сервиса Samba"""
        return cl_utils.genpassword().strip()

    def get_ld_samba_hash(self):
        """hash пароля администратора сервиса Samba"""
        return self.getHash(self.Get('ld_samba_pw'), self.Get('ld_encrypt'))

    def get_sr_samba_netbios(self):
        """netbios имя samba домена"""
        hostname = self.Get('os_net_hostname')
        if hostname:
            return "%s-cds"%self.Get('os_net_hostname')
        return ""

    def get_ld_mail_dn(self):
        """DN сервиса Mail"""
        return "ou=%s,%s" %(self.Get('ld_mail_login'),
            self.Get('ld_services_dn'))

    def get_ld_mail_pw(self):
        """пароль администратора сервиса Mail"""
        return cl_utils.genpassword().strip()

    def get_ld_mail_hash(self):
        """hash пароля администратора сервиса Mail"""
        return self.getHash(self.Get('ld_mail_pw'), self.Get('ld_encrypt'))

    def get_ld_jabber_dn(self):
        """DN сервиса Jabber"""
        return "ou=%s,%s" %(self.Get('ld_jabber_login'),
            self.Get('ld_services_dn'))

    def get_ld_jabber_pw(self):
        """пароль администратора сервиса Jabber"""
        return cl_utils.genpassword().strip()

    def get_ld_jabber_hash(self):
        """hash пароля администратора сервиса Jabber"""
        return self.getHash(self.Get('ld_jabber_pw'), self.Get('ld_encrypt'))

    def get_ld_ftp_dn(self):
        """DN сервиса FTP"""
        return "ou=%s,%s" %(self.Get('ld_ftp_login'),
            self.Get('ld_services_dn'))

    def get_ld_ftp_pw(self):
        """пароль администратора сервиса FTP"""
        return cl_utils.genpassword().strip()

    def get_ld_ftp_hash(self):
        """hash пароля администратора сервиса FTP"""
        return self.getHash(self.Get('ld_ftp_pw'), self.Get('ld_encrypt'))

    def get_ld_proxy_dn(self):
        """DN сервиса Proxy"""
        return "ou=%s,%s" %(self.Get('ld_proxy_login'),
            self.Get('ld_services_dn'))

    def get_ld_proxy_pw(self):
        """пароль администратора сервиса Proxy"""
        return cl_utils.genpassword().strip()

    def get_ld_proxy_hash(self):
        """hash пароля администратора сервиса Proxy"""
        return self.getHash(self.Get('ld_proxy_pw'), self.Get('ld_encrypt'))

    def get_sr_mail_host(self):
        """имя компьютера с настроенным сервисом Mail"""
        fullHostName = "%s.%s"%(self.Get('os_net_hostname'),
                               self.Get('os_net_domain'))
        if fullHostName:
            return fullHostName
        else:
            return ""

    def get_sr_jabber_host(self):
        """имя компьютера с настроенным сервисом Jabber"""
        fullHostName = "%s.%s"%(self.Get('os_net_hostname'),
                               self.Get('os_net_domain'))
        if fullHostName:
            return fullHostName
        else:
            return ""

    def get_ld_repl_host(self):
        """имя компьютера c включенной репликацией"""
        fullHostName = "%s.%s"%(self.Get('os_net_hostname'),
                               self.Get('os_net_domain'))
        if fullHostName:
            return fullHostName
        else:
            return ""

    def get_ld_repl_pw(self):
        """пароль ветки репликации"""
        return cl_utils.genpassword().strip()

    def get_ld_repl_hash(self):
        """hash пароля ветки репликации"""
        return self.getHash(self.Get('ld_repl_pw'),
                            self.Get('ld_encrypt'))

    def get_ld_ldap_dn(self):
        """DN основной служебной ветки LDAP"""
        return "ou=%s,%s"%(self.Get('ld_ldap_login'),
                           self.Get('ld_services_dn'))

    def get_ld_repl_dn(self):
        """DN ветки репликации"""
        return "ou=%s,%s"%(self.Get('ld_repl_login'), self.Get('ld_ldap_dn'))

    def get_ld_repl_worked_dn(self):
        """DN ветки хранения последнего посещенного сервера"""
        return "ou=%s,%s" %(self.Get('ld_repl_worked_login'),
                            self.Get('ld_repl_dn'))

    def get_ld_repl_ids(self):
        """id серверов репликации"""
        replServers = self.Get("ld_repl_servers")
        rids = []
        if not replServers:
            return ""
        replServers = replServers.split(",")
        for replServer in replServers:
            if replServer:
                md5hex = hashlib.md5(replServer).hexdigest()
                dStart = 0
                dEnd = 3
                dMax = 32
                while(dEnd<=dMax and md5hex[dStart:dEnd] in rids):
                    dStart += 1
                    dEnd +=1
                if dEnd>=dMax:
                    return ""
                rids.append(str(int(md5hex[dStart:dEnd],16)))
        return ",".join(rids)

    def get_ld_repl_id(self):
        """id текущего сервера репликации"""
        replServers = self.Get("ld_repl_servers")
        if not replServers:
            return ""
        replServers = replServers.split(",")
        replMailServers = self.Get("ld_repl_mail_servers")
        if replMailServers:
            replMailServers = replMailServers.split(",")
        replSambaServers = self.Get("ld_repl_samba_servers")
        if replSambaServers:
            replSambaServers = replSambaServers.split(",")
        replUnixServers = self.Get("ld_repl_unix_servers")
        if replUnixServers:
            replUnixServers = replUnixServers.split(",")
        if set(replServers) != \
        set(replSambaServers)|set(replUnixServers)|set(replMailServers):
            return ""
        replIds = self.Get("ld_repl_ids")
        replIds = replIds.split(",")
        if len(replServers)!=len(replIds):
            return ""
        hostName = self.Get('os_net_hostname')
        domain = self.Get('os_net_domain')
        fullHostName = "%s.%s"%(hostName,domain)
        i = 0
        repl_id = ""
        for replServer in replServers:
            elemReplServer = replServer.split(".")
            if len(elemReplServer)==1:
                if replServer == hostName:
                    repl_id = replIds[i]
                    break
            else:
                if replServer == fullHostName:
                    repl_id = replIds[i]
                    break
            i += 1
        return repl_id

    def get_ld_repl_servers_ref(self):
        """Текст в slapd.conf, ссылки на серверы репликации"""
        repl_id = self.Get("ld_repl_id")
        if not repl_id:
            return ""
        servers_ref = ""
        replServers = self.Get("ld_repl_servers")
        replServers = replServers.split(",")
        replIds = self.Get("ld_repl_ids")
        replIds = replIds.split(",")
        i = 0
        for replServer in replServers:
            if replIds[i]!= repl_id:
                servers_ref += "updateref ldap://%s:389\n" %replServer
            i += 1
        return servers_ref

    def get_ld_repl_servers_info(self):
        """Текст в slapd.conf,

        в котором находится информация о серверах репликации"""
        repl_id = self.Get("ld_repl_id")
        if not repl_id:
            return ""
        servers_info = ""
        replMailServers = self.Get("ld_repl_mail_servers")
        if replMailServers:
            replMailServers = replMailServers.split(",")
        replSambaServers = self.Get("ld_repl_samba_servers")
        if replSambaServers:
            replSambaServers = replSambaServers.split(",")
        replUnixServers = self.Get("ld_repl_unix_servers")
        if replUnixServers:
            replUnixServers = replUnixServers.split(",")
        replServers = self.Get("ld_repl_servers")
        replServers = replServers.split(",")
        if set(replServers) != \
            set(replSambaServers)|set(replUnixServers)|set(replMailServers):
            return ""
        replIds = self.Get("ld_repl_ids")
        replIds = replIds.split(",")
        i = 0
        for replServer in replServers:
            if replIds[i]!= repl_id:
                if replServer in replSambaServers:
                    if replServer in replMailServers:
                        servers_info += """syncrepl rid=%s
    provider=ldap://%s
    type=refreshAndPersist
    retry="5 5 300 +"
    filter="(|(|(ou:dn:=Samba)(ou:dn:=Unix))(ou:dn:=Replication))"
    searchbase="%s"
    attrs="*,+"
    schemachecking=on
    bindmethod=simple
    binddn="%s"
    credentials=%s\n""" %(replIds[i], 
                        replServer,
                        self.Get("ld_services_dn"),
                        self.Get("ld_repl_dn"),
                        self.Get("ld_repl_pw"))
                    else:
                        servers_info += 'syncrepl rid=%s\n\
    provider=ldap://%s\n\
    type=refreshAndPersist\n\
    retry="5 5 300 +"\n\
    filter="(&(|(|(ou:dn:=Samba)(ou:dn:=Unix))(ou:dn:=Replication))\
(!(&(ou:dn:=Replication)(ou:dn:=Mail))))"\n\
    searchbase="%s"\n\
    attrs="*,+"\n\
    schemachecking=on\n\
    bindmethod=simple\n\
    binddn="%s"\n\
    credentials=%s\n' %(replIds[i], 
                        replServer,
                        self.Get("ld_services_dn"),
                        self.Get("ld_repl_dn"),
                        self.Get("ld_repl_pw"))
                elif replServer in replUnixServers:
                    if replServer in replMailServers:
                        servers_info += 'syncrepl rid=%s\n\
    provider=ldap://%s\n\
    type=refreshAndPersist\n\
    retry="5 5 300 +"\n\
    filter="(&(|(ou:dn:=Unix)(ou:dn:=Replication))(!(&(ou:dn:=Replication)\
(ou:dn:=Worked))))"\n\
    searchbase="%s"\n\
    attrs="*,+"\n\
    schemachecking=on\n\
    bindmethod=simple\n\
    binddn="%s"\n\
    credentials=%s\n' %(replIds[i], 
                        replServer,
                        self.Get("ld_services_dn"),
                        self.Get("ld_repl_dn"),
                        self.Get("ld_repl_pw"))
                    else:
                        servers_info += """syncrepl rid=%s
    provider=ldap://%s
    type=refreshAndPersist
    retry="5 5 300 +"
    filter="(|(ou:dn:=Unix)(ou=Replication))"
    searchbase="%s"
    attrs="*,+"
    schemachecking=on
    bindmethod=simple
    binddn="%s"
    credentials=%s\n""" %(replIds[i], 
                        replServer,
                        self.Get("ld_services_dn"),
                        self.Get("ld_repl_dn"),
                        self.Get("ld_repl_pw"))
                elif replServer in replMailServers:
                    servers_info += """syncrepl rid=%s
    provider=ldap://%s
    type=refreshAndPersist
    retry="5 5 300 +"
    filter="(&(ou:dn:=Replication)(ou:dn:=Mail))"
    searchbase="%s"
    attrs="*,+"
    schemachecking=on
    bindmethod=simple
    binddn="%s"
    credentials=%s\n""" %(replIds[i], 
                        replServer,
                        self.Get("ld_services_dn"),
                        self.Get("ld_repl_dn"),
                        self.Get("ld_repl_pw"))
            i += 1
        return servers_info

    def get_ld_repl_samba_set(self):
        """Включена или нет репликация для сервиса Samba"""
        replSambaServers = self.Get("ld_repl_samba_servers")
        if replSambaServers:
            replSambaServers = replSambaServers.split(",")
        else:
            return "off"
        hostName = self.Get('os_net_hostname')
        domain = self.Get('os_net_domain')
        fullHostName = "%s.%s"%(hostName,domain)
        if fullHostName in replSambaServers:
            return "on"
        return "off"

    def get_sr_samba_net_allow_pass(self):
        """Текст в smb.conf - доступные сети"""
        netAllow = self.Get("sr_samba_net_allow")
        if netAllow:
            netAllow = netAllow.split(",")
            foundLoc = False
            for net in netAllow:
                if net[:4] == '127.':
                    foundLoc = True
                    break
            netAllow = " ".join(netAllow)
            if not foundLoc:
                netAllow += " 127."
            return netAllow
        osNetAllow = self.Get("os_net_allow")
        if osNetAllow:
            return "%s 127." %osNetAllow.replace(","," ")
        return "127."

    def get_sr_mail_net_allow_pass(self):
        """Текст в main.cf - доступные сети"""
        netAllow = self.Get("sr_mail_net_allow")
        if netAllow:
            netAllow = netAllow.split(",")
            foundLoc = False
            for net in netAllow:
                if net[:4] == '127.':
                    foundLoc = True
                    break
            netAllow = ", ".join(netAllow)
            if not foundLoc:
                netAllow += ", 127.0.0.0/8"
            return netAllow
        osNetAllow = self.Get("os_net_allow")
        if osNetAllow:
            return "%s, 127.0.0.0/8" %osNetAllow.replace(",",", ")
        return "127.0.0.0/8"

    def get_sr_proxy_net_allow_pass(self):
        """Текст в squid.conf - доступные сети"""
        netAllow = self.Get("sr_proxy_net_allow")
        if netAllow:
            netAllow = netAllow.split(",")
            netAllow = map(lambda x: "acl localnet src %s"%x,netAllow)
            netAllow = "\n".join(netAllow)
            return netAllow
        netAllow = self.Get("os_net_allow")
        if netAllow:
            netAllow = netAllow.split(",")
            netAllow = map(lambda x: "acl localnet src %s"%x,netAllow)
            netAllow = "\n".join(netAllow)
            return netAllow
        return "acl localnet src 127.0.0.1/32"

    def get_sr_samba_net_allow(self):
        """Доступные сети для сервиса Samba"""
        netAllow = self.Get("os_net_allow")
        if netAllow:
            return netAllow
        return ""

    def get_sr_mail_net_allow(self):
        """Доступные сети для сервиса Mail"""
        netAllow = self.Get("os_net_allow")
        if netAllow:
            return netAllow
        return ""

    def get_sr_proxy_net_allow(self):
        """Доступные сети для сервиса Proxy"""
        netAllow = self.Get("os_net_allow")
        if netAllow:
            return netAllow
        return ""

    def get_ld_repl_mail_dn(self):
        """DN ветки хранения реплицируемых алиасов"""
        return "ou=%s,%s" %(self.Get('ld_repl_mail_login'),
                            self.Get('ld_repl_dn'))

    def get_ld_repl_mail_set(self):
        """Включена или нет репликация для сервиса Mail"""
        replMailServers = self.Get("ld_repl_mail_servers")
        if replMailServers:
            replMailServers = replMailServers.split(",")
        else:
            return "off"
        hostName = self.Get('os_net_hostname')
        domain = self.Get('os_net_domain')
        fullHostName = "%s.%s"%(hostName,domain)
        if fullHostName in replMailServers:
            return "on"
        return "off"

    def get_ld_repl_unix_set(self):
        """Включена или нет репликация для сервиса Unix"""
        replUnixServers = self.Get("ld_repl_unix_servers")
        if replUnixServers:
            replUnixServers = replUnixServers.split(",")
        else:
            return "off"
        hostName = self.Get('os_net_hostname')
        domain = self.Get('os_net_domain')
        fullHostName = "%s.%s"%(hostName,domain)
        if fullHostName in replUnixServers:
            return "on"
        return "off"

    def get_sr_jabber_hosts(self):
        """имена хостов с которыми работает сервис Jabber"""
        return self.Get("sr_jabber_host")

    def get_sr_jabber_hosts_pass(self):
        """Текст в ejabberd.cfg - имена хостов с которыми работает сервис"""
        jabberHosts = self.Get("sr_jabber_hosts")
        if jabberHosts:
            return ", ".join(map(lambda x: '"'+x+'"', jabberHosts.split(",")))
        return ""

    def get_sr_jabber_user_name(self):
        """Имя jabber пользователя (левая часть jabber id)"""
        userJid = self.Get("sr_jabber_user_id")
        if userJid:
            return userJid.partition('@')[0]
        return ""

    def get_ld_dns_dn(self):
        """DN сервиса DNS"""
        return "ou=%s,%s" %(self.Get('ld_dns_login'),
            self.Get('ld_services_dn'))

    def get_ld_dns_pw(self):
        """пароль администратора сервиса DNS"""
        return cl_utils.genpassword().strip()

    def get_ld_dns_hash(self):
        """hash пароля администратора сервиса DNS"""
        return self.getHash(self.Get('ld_dns_pw'), self.Get('ld_encrypt'))

    def get_sr_dns_net_allow(self):
        """Доступные сети для сервиса DNS"""
        netAllow = self.Get("os_net_allow")
        if netAllow:
            return netAllow
        return ""

    def get_sr_dns_net_allow_pass(self):
        """Текст в named.conf - доступные сети"""
        def getNetAllow(netAllow):
            netAllow = netAllow.split(",")
            foundLoc = False
            for net in netAllow:
                if net[:4] == '127.':
                    foundLoc = True
                    break
            if not foundLoc:
                netAllow.append("127.0.0.1")
            netAllow = map(lambda x: "%s;"%x,netAllow)
            netAllow = " ".join(netAllow)
            return "listen-on { %s };"%netAllow
        netAllow = self.Get("sr_dns_net_allow")
        if netAllow:
            return getNetAllow(netAllow)
        netAllow = self.Get("os_net_allow")
        if netAllow:
            return getNetAllow(netAllow)
        return "listen-on { 127.0.0.1; };"