#!/usr/bin/env python 

# Copyright (c) Istituto Nazionale di Fisica Nucleare (INFN). 2006-2010.
#
# 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 argparse
import logging
import logging.config
import os
import exceptions
import time
import pwd

from info_provider.configuration import Configuration
from info_provider.storm_gateway import StormGateway
from info_provider.utils.ldap_utils import LDIFExporter
from symbol import argument
from info_provider.storm_info_provider import StormInfoProvider
from info_provider.glue.utils import get_issuer_ca

CONFIG_FILE = "/etc/storm/info-provider/storm-yaim-variables.conf"
LOG_FORMAT = "%(asctime)s %(name)-12s: %(levelname)s %(message)s"
EXPORT_TO_JSON_FILE = "/etc/storm/info-provider/site-report.json"

def parse_args():
    parser = argparse.ArgumentParser(description = 'storm-info-provider args')
    parser.add_argument('-v', action = 'store', dest = 'log_level', 
        required = False, default=20, type=int)
    parser.add_argument('-o', action = 'store', dest = 'log_filename',
        required = False)
    subparsers = parser.add_subparsers()
    # create parser for "init" command
    parser_init = subparsers.add_parser('configure')
    parser_init.add_argument('-f', action = 'store', dest = 'filepath', 
        required = False, default=CONFIG_FILE)
    parser_init.add_argument('-g', action = 'store', dest = 'glue_protocol', 
        required = False, choices=['glue13', 'glue2', 'all'], default='all')
    parser_init.add_argument('-o', action = 'store', dest = 'exported_json_file_path', 
        required = False, default=EXPORT_TO_JSON_FILE)
    parser_init.set_defaults(action=configure)
    # create parser for "get-update-ldif" command
    parser_update = subparsers.add_parser('get-update-ldif')
    parser_update.add_argument('-f', action = 'store', dest = 'filepath', 
        required = False, default=CONFIG_FILE)
    parser_update.add_argument('-g', action = 'store', dest = 'glue_protocol', 
        required = False, choices=['glue13', 'glue2'], default='glue2')
    parser_update.set_defaults(action=get_update_ldif)
    # create parser for "get-static-ldif" command
    parser_static = subparsers.add_parser('get-static-ldif')
    parser_static.add_argument('-f', action = 'store', dest = 'filepath', 
        required = False, default=CONFIG_FILE)
    parser_static.add_argument('-g', action = 'store', dest = 'glue_protocol', 
        required = False, choices=['glue13', 'glue2'], default='glue2')
    parser_static.set_defaults(action=get_static_ldif)
    # create parser for "build-report" command
    parser_report = subparsers.add_parser('get-report-json')
    parser_report.add_argument('-f', action = 'store', dest = 'filepath', 
        required = False, default=CONFIG_FILE)
    parser_report.add_argument('-o', action = 'store', dest = 'exported_json_file_path', 
        required = False, default=EXPORT_TO_JSON_FILE)
    parser_report.set_defaults(action=get_report_json)
    return parser.parse_args()

def is_backend_running(endpoint):
    logging.debug("Checking if backend is running ...")
    gateway = StormGateway(endpoint)
    return gateway.is_online()

def get_current_serving_state(configuration):
    logging.debug("Getting serving state ...")
    if not is_backend_running(configuration.get_backend_rest_endpoint()):
        return (1, "closed")
    return (4, "production")

def get_implementation_version():
    cmd = "rpm -q --queryformat='%{VERSION}' storm-backend-server"
    return os.popen(cmd).read()

def init_configuration(yaim_filepath):
    # load configuration from file    
    configuration = Configuration(yaim_filepath)
    # get current serving state (used by GLUE2)
    (value_int, value_str) = get_current_serving_state(configuration)
    configuration.set("STORM_SERVING_STATE_VALUE", value_int)
    configuration.set("STORM_SERVING_STATE", value_str)
    configuration.set("STORM_IMPLEMENTATION_VERSION", get_implementation_version())
    configuration.set("ISSUER_CA", get_issuer_ca())
    return configuration

def configure(arguments):
    logging.debug("Configure ...")
    info_provider.configure(arguments.glue_protocol, arguments.exported_json_file_path);
    return

def get_report_json(arguments):
    logging.debug("Build JSON report ...")
    info_provider.get_report_json(arguments.exported_json_file_path)
    return

def get_static_ldif(arguments):
    logging.debug("Get static LDIF ...")
    info_provider.get_static_ldif(arguments.glue_protocol)
    return

def get_update_ldif(arguments):
    info_provider.get_update_ldif(arguments.glue_protocol)
    return

def initialize_logger(arguments):
    if arguments.log_filename:
        logging.basicConfig(filename=arguments.log_filename, filemode='a',
            format=LOG_FORMAT, level=arguments.log_level)
    else:
        logging.basicConfig(stream=sys.stderr, format=LOG_FORMAT,
            level=arguments.log_level)


if __name__ == '__main__':

    # command line parsing
    arguments = parse_args()

    # initialize logging
    initialize_logger(arguments)

    # load configuration
    configuration = init_configuration(arguments.filepath)

    # create info_provider
    info_provider = StormInfoProvider(configuration=configuration)

    start = time.clock()
    # do ...
    try:
        arguments.action(arguments)
    except Exception, e:
        print str(e)
        sys.exit(1)

    elapsed = time.clock() - start
    logging.info("Received %s - It took %s sec", arguments.action.__name__, elapsed)

    sys.exit()