#!/usr/bin/python

#
# Copyright 2013 Zynga Inc.
# 
# 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.
# 


from global_preset_paths import global_preset_paths
import os.path
import os
import socket
import sys
import syslog
import traceback
import md5
import urllib2

#
# The auto-generated zperfmon.ini file starts with
#

### GENERATED BY ZPERFMON SERVER
### MD5: 32 hex digits


AUTO_HEADER = "### GENERATED BY ZPERFMON SERVER"
AUTO_LENGTH = len(AUTO_HEADER) * 2


def on_zrt():
    if os.path.isfile(global_preset_paths["ZRUNTIME_LIVE_REV"]):
        print "zRuntime is enabled"
        return True
    else:
        return False

def can_replace_ini():
    # File does not exist we can put our own
    if not os.path.isfile(global_preset_paths["ZPERFMON_INI_FILE"]):
        print "zperfmon.ini does not exist, can pull"
        return True

    config = open(global_preset_paths["ZPERFMON_INI_FILE"]).read()

    # File exists but was not auto generated 
    if not config.startswith("### GENERATED BY ZPERFMON SERVER"):
        print "zperfmon.ini exists, but was not generated by server"
        return False

    try:
        digest_start = config.find("\n") + 1
        config_start = config.find("\n", digest_start) + 1
        infile_digest = config[digest_start:config_start].split("\001")[1]

        digest = md5.md5(config[config_start:]).hexdigest()

        # If ini was edited after delivery, must not replace it
        if digest != infile_digest:
            print "zperfmon.ini was generated by server, but was edited locally"
            return False
    except:
        print "zperfmon.ini may have bad format, aborting ini replace"
        return False

    return True


def get_my_ip():
    all_ips = [ip for ip in socket.gethostbyname_ex(socket.gethostname())[2]
               if not ip.startswith("127.")]
    ten_ips = [ip for ip in all_ips if ip.startswith("10.")]

    if ten_ips:
        return ten_ips[0]
    elif all_ips:
        return all_ips[0]

    print "Could not extract IP for this machine"
    return None


def pull_config():
    try:
        url_param = ""
        ip = get_my_ip()
        if ip:
            url_param = "?ip=" + ip

        socket.setdefaulttimeout(10)

        domain = open("/etc/zynga/dns_zone").read().strip()
        if "ec2" in domain:
            url_to_hit = global_preset_paths["ZPERFMON_CONF_URL_EC2"]
        else:
            url_to_hit = global_preset_paths["ZPERFMON_CONF_URL"]
        print "Fetching config from " + url_to_hit + url_param
        get_conf_hndl = urllib2.urlopen(url_to_hit + url_param)
            
        config = get_conf_hndl.read()
    except:
        print "Error while fetching INI file"
        return ("", "")

    if len(config) < AUTO_LENGTH:
        print "zperfmon.ini seems truncated, aborting replace"
        return ("", "")

    return (config, url_to_hit + url_param)


def check_replace_config():

    if on_zrt() or not can_replace_ini():
        return

    #Remove the ini file before the pull
    if os.path.isfile(global_preset_paths["ZPERFMON_INI_FILE"]):
        os.remove(global_preset_paths["ZPERFMON_INI_FILE"])

    config, ini_url = pull_config()
    if not config.startswith(AUTO_HEADER):
        err_msg = "zPerfmon ini generation request to %s failed" % ini_url

	if os.path.isfile(global_preset_paths["ZPERFMON_CONFIG_PATH"]):
            os.remove(global_preset_paths["ZPERFMON_CONFIG_PATH"])
        print err_msg
        raise err_msg

    cnf_hndl = open(global_preset_paths["ZPERFMON_INI_FILE"], "w")
    cnf_hndl.write(config)


def main():
    check_replace_config()


if __name__ == "__main__":
    try:
        main()
    except:
        info = sys.exc_info()
        syslog.syslog(str(info[0]))
        syslog.syslog(traceback.format_exc())
