#!/usr/bin/python
#
# Copyright (c) 2014 Ericsson, Inc.  All Rights Reserved.
#
# This module contains unpublished, confidential, proprietary
# material.  The use and dissemination of this material are
# governed by a license.  The above copyright notice does not
# evidence any actual or intended publication of this material.
#
# Author: Subu V
# Created: Sep 10th, 2014
# Description:
# Script to update a CMS DEV/LAB license to a PROD license

import os
import sys
import getopt
import uuid
import lib.obfuuid as obfuuid
import subprocess
import logging
import xml.etree.ElementTree as ET

# default location of CMS license file
from sys import platform as _platform
if _platform == "linux" or _platform == "linux2":
    # linux
    LICENSE_FOLDER = "/opt/tandbergtv/cms/conf/workflow"
    CONFIG_JSON = "/root/config.json"
    CMS_CONFIG_FILE = "/var/lib/nobody/.cmsconfig"
    TEMP_FOLDER = "/tmp"
    CMS_APP_SRVR_HOST = "app1"
    COPY = "scp"

elif _platform == "win32":
    # Windows...
    DEV_FOLDER = 'C:\\MyCMS\\cms_cloud\\'
    LICENSE_FOLDER = os.path.join(DEV_FOLDER, 'curr');
    TEMP_FOLDER = os.path.join(DEV_FOLDER, 'tmp');
    CONFIG_JSON = os.path.join(TEMP_FOLDER, 'config.json');
    CMS_CONFIG_FILE = '/var/lib/nobody/.cmsconfig'
    CMS_APP_SRVR_HOST = 'app1'
    COPY = 'pscp'

LICENSE_FILE = os.path.join(LICENSE_FOLDER, 'license.xml');
TEMP_LICENSE_FILE = os.path.join(TEMP_FOLDER, 'license.xml');

DEV_FINGERPRINT = "00000000000000000000000000000000";
LAB_FINGERPRINT = "11111111111111111111111111111111";
CMS_CS_SRVR  = "CMS Cluster Services Server";
USER = "root"


def generateFingerprint():
    
    fprint = '';
    #generate a fingerprint
    fprint =  uuid.uuid4().urn[9:].replace("-", "");
    #write the cms config file 
    generateCmsConfigFile(fprint);
    #This fingerprint should be used to generate the PROD license
    print ("\n\tUse fingerprint [ " + fprint + " ] when generating production license");
    print ("\tRun this script again after generating PROD license xml file to update the license\n")


def generateCmsConfigFile(fp):
    if fp:
        # create the fingerprint file
        obfuuid.writefile(fp, os.path.join(TEMP_FOLDER, '.cmsconfig'));
        #print("cmsconfig file created")
    else:
        print("Fingerprint is empty");


def getAppCount():
     
     appCount = 0;
     if (os.path.isfile(CONFIG_JSON)):
         p1 = subprocess.Popen(['grep', 'clusterGroup', CONFIG_JSON], stdout=subprocess.PIPE)
         p2 = subprocess.Popen(['grep', 'app'], stdin=p1.stdout, stdout=subprocess.PIPE)
         p3 = subprocess.Popen(['wc', '-l'], stdin=p2.stdout, stdout=subprocess.PIPE)
         p1.stdout.close()
         p2.stdout.close()
         appCount = int(p3.communicate()[0])
         
     else:
         print ("Cannot get app server count, config file %s NOT found" % CONFIG_JSON)
 
     #print ("App count from %s is %d" %(CONFIG_JSON, appCount))
     return appCount;


def getCurrentLicense():
    
    with open(os.devnull,'w') as fnull:
        retval=subprocess.call([COPY,
                                # Current license file from cms app1 (remote)
                                USER+'@'+CMS_APP_SRVR_HOST+":"+LICENSE_FILE,
                                #temp location; make sure it's a directory
                                os.path.join(TEMP_FOLDER, "")], stdout=fnull,stderr=fnull);
                                
        if retval != 0:
            print('Failed to get license.xml from app1')
            return False
    
    return True;


def copyFileToCmsHost(srcFile, remoteFile, host):
     
     with open(os.devnull,'w') as fnull:
         retval=subprocess.call([COPY, srcFile, USER+'@'+host+":"+remoteFile], stdout=fnull,stderr=fnull);
         if retval != 0:
             print('Failed to copy file %s to %s@%s:%s' %(srcFile, USER, CMS_APP_SRVR_HOST, remoteFile))
             return False
     #chown to nobody
     return subprocess.call(['ssh',host,'chown nobody:nobody '+remoteFile]) == 0
 

def cleanup():
    #remove the DEV/LAB license.xml from /tmp
    try:
        os.remove(TEMP_LICENSE_FILE)
    except OSError:
        pass
    #remove the .cmsconfig file from /tmp
    try:
        os.remove(os.path.join(TEMP_FOLDER, '.cmsconfig'))
    except OSError:
        pass
    
    
def updateLicense(licFile):
    
    if validateLicense(licFile):
        #we have a valid license
        app_count = getAppCount()
        if app_count:            
            for i in range(1, app_count+1):
                
                #print ("Please copy file %s to %s on app server %s" %(os.path.join(TEMP_FOLDER, '.cmsconfig'), CMS_CONFIG_FILE, 'app'+str(i)))
                
                if not copyFileToCmsHost(os.path.join(TEMP_FOLDER, '.cmsconfig'),
                                        CMS_CONFIG_FILE, 
                                        'app'+str(i)):
                    break
            
            if (i == app_count):
                #print ("Please copy license file %s to %s on app server %s" %(licFile, LICENSE_FILE, CMS_APP_SRVR_HOST))
                if (copyFileToCmsHost(licFile, LICENSE_FILE, CMS_APP_SRVR_HOST)):                   
                    #clean up temp files
                    cleanup()         
                    print ("License update successful !")
                    return True
        else:
            print("No app servers found in the config file")
                
    return False

    
def validateLicense(licFile):        
    retval = False
    
    #get fingerprint from the obfuscated config file
    fpstr = obfuuid.getUuid(os.path.join(TEMP_FOLDER, '.cmsconfig'))
    #print ("uuid = " + fpstr);
    if not fpstr:
        print ("Cannot validate license %s, cmsconfig file NOT found." %licFile)
    else:
        #read fingerprint from the license file    
        fprint = getFingerprint(licFile)
        if not fprint:
            print ("Failed to read fingerprint from the license file %s" %licFile);
        elif fprint != fpstr:
            print ("Cannot update license, the license fingerprint doesn't match system fingerprint !");
        else:            
            retval = True;
     
    return retval;
 
 
#this will check if the current license is a DEV or LAB license
def getFingerprint(licFile):
    
    fingerprint = '';
    
    # Parse the XML file
    try:
        tree = ET.parse(licFile)
    except:
        print("Unable to parse license file %s" % licFile)
        return fingerprint

    # Walk the elements
    root = tree.getroot()
    if root is None:
        print("Unable to find root node in license file %s" % licFile)
        return fingerprint
    body = root.find('body')
    if body is None:
        print("Unable to find <body> node in license file %s" % licFile)
        return fingerprint

    SWLT = body.find('SWLT')
    if SWLT is None:
        print("Unable to find <SWLT> node in <body> in license file %s" % licFile)
        return fingerprint

    # Validate the product type
    if not 'productType' in SWLT.attrib:
        print("Unable to find productType attribute in <SWLT> in license file %s" % licFile)
        return fingerprint
    if SWLT.attrib['productType'] != 'CMS':
        print("Invalid product type in license file %s - does not match CMS." % licFile)
        return fingerprint

    # get the fingerprint
    fprint = SWLT.find('fingerprint')
    if fprint is None:
        print("Unable to find <fingerprint> node in <SWLT> in license file %s" % licFile)
        return fingerprint
    if not 'print' in fprint.attrib:
        print("Unable to find print attribute in <fingerprint> in license file %s" % licFile)
        return fingerprint

    fingerprint = fprint.attrib['print']

    return fingerprint
 

def canUpdateLicense():
     
     retval = False;
     fprint = getFingerprint(TEMP_LICENSE_FILE);
     
     if not fprint:
        print ("Failed to get fingerprint from the license xml file");
     elif fprint not in (DEV_FINGERPRINT, LAB_FINGERPRINT):
        print "Cannot update a PROD license using this script.";
     else:
        #print ("License update possible as this is a DEV or LAB license");
        retval = True;
     
     return retval;

def main(argv):

    licFile = ''
    fingerprint = ''
    try:
        opts, args = getopt.getopt(argv,"hf:p:",["file=","fprint=", "help"])
    except getopt.GetoptError as err:
        #print 'updateLicense.py -f <licensefile> -p <fingerprint>'
        print 'updateLicense.py [-f licensefile]'
        sys.exit(2)
    for opt, arg in opts:
        if opt == '-h':
            print 'updateLicense.py [-f licensefile]'
            sys.exit()
        elif opt in ("-f", "--file"):
            licFile = arg
        elif opt in ("-p", "--fprint"):
            fingerprint = arg

    #get node type
    nodeType = ''
    if (os.path.isfile('/etc/node-type')):
        with open('/etc/node-type', 'r') as f:
            nodeType = f.readline().rstrip('\n')    
    
    if (nodeType != CMS_CS_SRVR):
        print "Please run this script on the CS node";
        exit(1);
            
    if not getCurrentLicense():
        exit(1);
    
    #check if the current license is DEV or LAB
    can_update = canUpdateLicense()
    if not can_update:
        print "Cannot update license now. Contact Customer Support.";
        exit(1);

    #if fingerprint is provided, generate the cmsconfig file
    if fingerprint:
        generateCmsConfigFile(fingerprint);
    
    if licFile:
        if (os.path.isfile(licFile)):
            updateLicense(licFile);
        else:
            print("License file %s not found..." % licFile)
    elif not fingerprint:
        generateFingerprint();


if __name__ == "__main__":
#   main(sys.argv[1:])
    fp = 'ac2b5296d81a194be79f19d13624ff1d'
    obfuuid.writefile(fp, os.path.join('/tmp', '.cmsconfig'));
    
