#!/usr/bin/python
# Copyright (c) Members of the EGEE Collaboration. 2004. 
# See http://www.eu-egee.org/partners/ for details on the copyright
# holders.  
#
# 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 sys
import re
import socket
import time
import shlex
import subprocess
import glob

def trunc(inStr):
    tmps = inStr.strip()
    if len(tmps) > 240:
        return tmps[0:239] + "...4444"
    else:
        return tmps

def main():

    pRegex = re.compile('^\s*([^=\s]+)\s*=([^$]+)$')

    config = {}

    infoprovVersion = "1.1"
    hostname = socket.getfqdn()
    now = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
        
    conffile = None
    foundErr = False
    try:
        if len(sys.argv) <> 2:
            raise Exception("Usage: glite-ce-glue2-endpoint-static <config-file>")
            
        conffile = open(sys.argv[1])
        for line in conffile:
            parsed = pRegex.match(line)
            if parsed:
                config[parsed.group(1)] = parsed.group(2).strip(' \n\t"')
            else:
                tmps = line.strip()
                if len(tmps) > 0 and not tmps.startswith('#'):
                    raise Exception("Error parsing configuration file " + sys.argv[1])
    
        for mItem in ['ComputingServiceId',
                      'InterfaceVersion',
                      'ServingState',
                      'Owner']:
            if not mItem in config:
                raise Exception("Missing attribute %s" % mItem)
        if not "HostCertificatePath" in config:
            config["HostCertificatePath"] = "/etc/grid-security/hostcert.pem"
        if not "TrustedCAPath" in config:
            config["TrustedCAPath"] = "/etc/grid-security/certificates"
        if not "EMIVersionPath" in config:
            config["EMIVersionPath"] = '/etc/emi-version'
        if not "Argus" in config:
            config["Argus"] = "yes"
        if not "EMIES" in config:
            config["EMIES"] = "no"
        if not "ACBR" in config or len(config["ACBR"].strip()) == 0:
            config["ACBR"] = "ALL"
        if not "ESComputingServiceId" in config and config["EMIES"] == "yes":
            config["ESComputingServiceId"] = hostname + "_ESComputingElement"
        if not "ESInterfaceVersion" in config and config["EMIES"] == "yes":
            config["ESInterfaceVersion"] = "1.15"
        if not "ImplementationVersion" in config:
            config["ImplementationVersion"] = "Undefined"

    
    except Exception, ex:
        sys.stderr.write(str(ex) + '\n')
        foundErr = True

    if conffile:
        conffile.close()
    if foundErr:
        sys.exit(1)

    out = sys.stdout
    
    hostDN = None
    issuerDN = None
    try:
        cmdargs = shlex.split('openssl x509 -in %s -noout -subject -issuer -nameopt RFC2253' % config["HostCertificatePath"])
        process = subprocess.Popen(cmdargs, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        pOut, pErr = process.communicate()
        if process.returncode > 0:
            raise Exception("Error parsing host certificate: " + pErr)

        for pLine in pOut.split('\n'):
            parsed = pRegex.match(pLine)
            if not parsed:
                continue
            if parsed.group(1) == 'subject':
                hostDN = trunc(parsed.group(2).strip(' \n\t"'))
            if parsed.group(1) == 'issuer':
                issuerDN = trunc(parsed.group(2).strip(' \n\t"'))
    except Exception, ex:
        sys.stderr.write(str(ex) + '\n')
        sys.exit(1)

    EMIVersion = None
    emiversionfile = None
    try:
        emiversionfile = open(config["EMIVersionPath"])
        for line in emiversionfile:
            tmps = line.strip()
            if len(tmps) > 0:
                EMIVersion = tmps
                break
    except Exception, ex:
        sys.stderr.write(str(ex) + '\n')
    if emiversionfile:
        emiversionfile.close()
    
    #trustedCAs = ['IGTF']
    trustedCAs = list()
    
    for CAFile in glob.glob(config["TrustedCAPath"] + '/*.pem'):
        try:
            cmdargs = shlex.split('openssl x509 -in %s -noout -subject -nameopt RFC2253' % CAFile)
            process = subprocess.Popen(cmdargs, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
            pOut, pErr = process.communicate()
            if process.returncode > 0:
                raise Exception("Error parsing host certificate: " + pErr)

            parsed = pRegex.match(pOut)
            if parsed:
                trustedCAs.append(parsed.group(2).strip(' \n\t"'))
        except Exception, ex:
            sys.stderr.write(str(ex) + '\n')
    
    
    
    
    acbrList = config["ACBR"].split()
    ownList = config['Owner'].split()
    
    
    
    srvTable = {}
    
    srvTable[hostname + "_org.glite.ce.CREAM"] = {
        'srvID' : config['ComputingServiceId'],
        'url' : "https://%s:8443/ce-cream/services" % hostname,
        'wsdl' : "https://%s:8443/ce-cream/services/CREAM2?wsdl" % hostname,
        'capabilities' : ['executionmanagement.jobexecution'],
        'ifname' : 'org.glite.ce.CREAM',
        'profile' : 'http://www.ws-i.org/Profiles/BasicProfile-1.0.html',
        'semantic' : 'http://wiki.italiangrid.org/twiki/bin/view/CREAM/UserGuide',
        'jdescr' : 'glite:jdl',
        'pubcomp' : True
    }
    
    if config['EMIES'] == 'yes':
        srvTable[hostname + "_org.ogf.glue.emies.activitycreation"] = {
            'srvID' : config['ESComputingServiceId'],
            'url' : "https://%s:8443/ce-cream-es/services/ActivityCreationService" % hostname,
            'wsdl' : "https://%s:8443/ce-cream-es/services/ActivityCreationService?wsdl" % hostname,
            'capabilities' : ['executionmanagement.jobcreation',
                              'executionmanagement.jobdescription',
                              'data.access.stageindir.gridftp',
                              'data.access.stageoutdir.gridftp'],
            'ifname' : 'org.ogf.glue.emies.activitycreation',
            'profile' : 'https://twiki.cern.ch/twiki/bin/view/EMI/EmiExecutionService',
            'semantic' : 'https://twiki.cern.ch/twiki/bin/view/EMI/EmiExecutionService',
            'jdescr' : 'emies:adl',
            'pubcomp' : True
        }
    
        srvTable[hostname + "_org.ogf.glue.emies.activitymanagement"] = {
            'srvID' : config['ESComputingServiceId'],
            'url' : "https://%s:8443/ce-cream-es/services/ActivityManagementService" % hostname,
            'wsdl' : "https://%s:8443/ce-cream-es/services/ActivityManagementService?wsdl" % hostname,
            'capabilities' : ['executionmanagement.jobmanagement',
                              'information.lookup.job',
                              'data.access.stageindir.gridftp',
                              'data.access.stageoutdir.gridftp',
                              'data.transfer.cepull.gridftp',
                              'data.transfer.cepush.gridftp'],
            'ifname' : 'org.ogf.glue.emies.activitymanagement',
            'profile' : 'https://twiki.cern.ch/twiki/bin/view/EMI/EmiExecutionService',
            'semantic' : 'https://twiki.cern.ch/twiki/bin/view/EMI/EmiExecutionService',
            'jdescr' : 'emies:adl',
            'pubcomp' : True
        }
        
        srvTable[hostname + "_org.ogf.glue.emies.delegation"] = {
            'srvID' : config['ESComputingServiceId'],
            'url' : "https://%s:8443/ce-cream-es/services/DelegationService" % hostname,
            'wsdl' : "https://%s:8443/ce-cream-es/services/DelegationService?wsdl" % hostname,
            'capabilities' : ['security.delegation'],
            'ifname' : 'org.ogf.glue.emies.delegation',
            'profile' : 'https://twiki.cern.ch/twiki/bin/view/EMI/EmiExecutionService',
            'semantic' : 'https://twiki.cern.ch/twiki/bin/view/EMI/EmiExecutionService',
            'jdescr' : 'emies:adl',
            'pubcomp' : False
        }

        srvTable[hostname + "_org.ogf.glue.emies.activityinfo"] = {
            'srvID' : config['ESComputingServiceId'],
            'url' : "https://%s:8443/ce-cream-es/services/ActivityInfoService" % hostname,
            'wsdl' : "https://%s:8443/ce-cream-es/services/ActivityInfoService?wsdl" % hostname,
            'capabilities' : ['information.monitoring', 'information.discovery', 'information.lookup.job'],
            'ifname' : 'org.ogf.glue.emies.activityinfo',
            'profile' : 'https://twiki.cern.ch/twiki/bin/view/EMI/EmiExecutionService',
            'semantic' : 'https://twiki.cern.ch/twiki/bin/view/EMI/EmiExecutionService',
            'jdescr' : 'emies:adl',
            'pubcomp' : True
        }

        srvTable[hostname + "_org.ogf.glue.emies.resourceinfo"] = {
            'srvID' : config['ESComputingServiceId'],
            'url' : "https://%s:8443/ce-cream-es/services/ResourceInfoService" % hostname,
            'wsdl' : "https://%s:8443/ce-cream-es/services/ResourceInfoService?wsdl" % hostname,
            'capabilities' : ['information.discovery.resource', 'information.query.xpath1'],
            'ifname' : 'org.ogf.glue.emies.resourceinfo',
            'profile' : 'https://twiki.cern.ch/twiki/bin/view/EMI/EmiExecutionService',
            'semantic' : 'https://twiki.cern.ch/twiki/bin/view/EMI/EmiExecutionService',
            'jdescr' : 'emies:adl',
            'pubcomp' : False
        }

    #end if for EMIES
    
    for endPointID in srvTable:
    
        srvDefs = srvTable[endPointID]
        
        out.write("dn: GLUE2EndpointID=%s,GLUE2ServiceID=%s,GLUE2GroupID=resource,o=glue\n" 
                   % (endPointID, srvDefs['srvID']))
    
        out.write("objectClass: GLUE2Entity\n")
        out.write("objectClass: GLUE2Endpoint\n")
        if srvDefs['pubcomp']:
            out.write("objectClass: GLUE2ComputingEndpoint\n")
    
        out.write("GLUE2EntityName: %s\n" % endPointID)
        out.write("GLUE2EntityCreationTime: %s\n" % now)
        out.write("GLUE2EntityOtherInfo: HostDN=%s\n" % hostDN)
        out.write("GLUE2EntityOtherInfo: InfoProviderName=glite-ce-glue2-endpoint-static\n")
        out.write("GLUE2EntityOtherInfo: InfoProviderVersion=%s\n" % infoprovVersion)
        out.write("GLUE2EntityOtherInfo: InfoProviderHost=%s\n" % hostname)
        if EMIVersion:
            out.write("GLUE2EntityOtherInfo: MiddlewareName=EMI\n")
            out.write("GLUE2EntityOtherInfo: MiddlewareVersion=%s\n" % EMIVersion)
        if config["Argus"] == "yes":
            out.write("GLUE2EntityOtherInfo: This CREAM-CE is using Argus\n")
        else:
            out.write("GLUE2EntityOtherInfo: This CREAM-CE is not using Argus\n")
    
        out.write("Glue2EndpointStartTime: %s\n" % now)
        out.write("GLUE2EndpointID: %s\n" % endPointID)
        out.write("GLUE2EndpointURL: %s\n" % srvDefs['url'])
        for capaItem in srvDefs['capabilities']:
            out.write("GLUE2EndpointCapability: %s\n" % capaItem)
        out.write("GLUE2EndpointTechnology: webservice\n")
        out.write("GLUE2EndpointInterfaceName: %s\n" % srvDefs['ifname'])
        if config['EMIES'] == 'yes':
           out.write("GLUE2EndpointInterfaceVersion: %s\n" % config['ESInterfaceVersion'])
        else:
           out.write("GLUE2EndpointInterfaceVersion: %s\n" % config['InterfaceVersion'])
        out.write("GLUE2EndpointWSDL: %s\n" % srvDefs['wsdl'])
        out.write("GLUE2EndpointSupportedProfile: %s\n" % srvDefs['profile'])
        out.write("GLUE2EndpointSemantics: %s\n" % srvDefs['semantic'])
        out.write("GLUE2EndpointImplementor: gLite\n")
        out.write("GLUE2EndpointImplementationName: CREAM\n")
        out.write("GLUE2EndpointImplementationVersion: %s\n" % config["ImplementationVersion"])
        out.write("GLUE2EndpointQualityLevel: production\n")
    
        # Hardwired value for GLUE2EndpointHealthState and GLUE2EndpointHealthStateInfo
        # The real values are supposed to be provided by the dynamic plugin
        out.write("GLUE2EndpointHealthState: unknown\n")
        out.write("GLUE2EndpointHealthStateInfo: N/A\n")
        out.write("GLUE2EndpointServingState: %s\n" % config['ServingState'].lower())
    
        out.write("GLUE2EndpointIssuerCA: %s\n" % issuerDN)
        for tCA in trustedCAs:
            out.write("GLUE2EndpointTrustedCA: %s\n" % tCA)
    
        out.write("GLUE2EndpointDownTimeInfo: See the GOC DB for downtimes: https://goc.egi.eu/\n")
        out.write("GLUE2EndpointServiceForeignKey: %s\n" % srvDefs['srvID'])
    
        if srvDefs['pubcomp']:
            out.write("GLUE2ComputingEndpointStaging: staginginout\n")
            out.write("GLUE2ComputingEndpointJobDescription: %s\n" % srvDefs['jdescr'])
            out.write("GLUE2ComputingEndpointComputingServiceForeignKey: %s\n" % srvDefs['srvID'])
        
        out.write("\n")
    
    
        out.write("dn: GLUE2PolicyID=%s_Policy,GLUE2EndpointID=%s,GLUE2ServiceID=%s,GLUE2GroupID=resource,o=glue\n"
                   % (endPointID, endPointID, srvDefs['srvID']))

        out.write("objectClass: GLUE2Entity\n")
        out.write("objectClass: GLUE2Policy\n")
        out.write("objectClass: GLUE2AccessPolicy\n")
    
        out.write("GLUE2EntityCreationTime: %s\n" % now)
        out.write("GLUE2EntityName: Access control rules for Endpoint %s\n" % endPointID)
        out.write("GLUE2EntityOtherInfo: InfoProviderName=glite-ce-glue2-endpoint-static\n")
        out.write("GLUE2EntityOtherInfo: InfoProviderVersion=%s\n" % infoprovVersion)
        out.write("GLUE2EntityOtherInfo: InfoProviderHost=%s\n" % hostname)

        out.write("GLUE2PolicyID: %s_Policy\n" % endPointID)
        # The policy scheme needs a name: arbitrarily define this as org.glite.standard
        out.write("GLUE2PolicyScheme: org.glite.standard\n")
        for acbrItem in acbrList:
            out.write("GLUE2PolicyRule: %s\n" % acbrItem)
        for owner in ownList:
            out.write("GLUE2PolicyUserDomainForeignKey: %s\n" % owner)

        out.write("GLUE2AccessPolicyEndpointForeignKey: %s\n" % endPointID)
        out.write("\n")
        
    #end iteration on srvTable

if __name__ == "__main__":
    main()



