#!/opt/vmware/bin/python
# Copyright 2015 VMware, Inc.  All rights reserved. -- VMware Confidential

"""
Main class which performs end to end Certificate Manager Workflow
"""

__author__ = 'Charudath Gopal (cgopal@vmware.com)'
__copyright__ = 'Copyright 2015, VMware Inc.'
__version__ = 1.0

import sys
import os
import getpass
import tempfile
import shutil
import time

sys.path.append(os.environ['VMWARE_PYTHON_PATH'])
from cis.certificateManagerOps import *
from cis.certificateManagerHelper import *
from cis.certificateManagerUtils import *
from cis.defaults import get_cis_log_dir
from cis.utils import *

global server
global vecs
node_type = ''
vmca = VmcaOps()
dir_cli = DirCliOps()
isLinux = os.name == 'posix'
if not isLinux:
    import pywintypes
    import win32service as w32s
    import win32serviceutil as w32su

class VMCACSRException(Exception):
    pass

def check_and_request_server_ip(ip=Constants.IP_LOCALHOST):
    """
    Function to request server IP in case of distributed setup
    :param ip: Provide PSC/Infra IP in case of distributed env else 'localhost'
    """
    global server
    global node_type
    if len(ip) > 0:
        server = ip
    else:
        server = Constants.IP_LOCALHOST
    try:
        if vecs._management_node:
            node_type = "management_node"
            log_info_msg('Performing operation on distributed setup, Please provide valid Infrastructure Server IP.')
            server = raw_input("Server : ")
        else:
            node_type = "embedded_node"
            logging.info('Performing operation on embedded setup using \'localhost\' as server')
    except EOFError:
        log_info_msg(Constants.TERMINATE_OP)
        exit(0)
    except Exception as e:
        log_error_msg(
            'Error while trying to check and get server IP Address, Infrastructure IP is required in distributed setup')
        logging.error(e)
        exit(1)


def confirm_operation(msg):
    """
    Function to get user confirmation before proceeding to next step
    :param msg: Message to be presented to user
    """
    log_info_msg(msg)
    if get_user_confirmation(Constants.CONTINUE_OPERATION):
        logging.info('Backup all certs to BACKUP_STORE to use in case of failures')
        backup_all_certs(vecs, get_rollback_cert_dir())
        logging.info('Certificate backup created successfully')
        return
    else:
        logging.info(Constants.TERMINATE_OP)
        exit(0)


def initialize_services():
    """
    Function to start all required services for Certificate Management
    """
    try:
        if isLinux:
            start_service(Constants.VMAFD_SERVICE_LIN)
            if not is_management_node():
                start_service(Constants.VMCA_SERVICE_LIN)
                start_service(Constants.VMDIRD_SERVICE_LIN)
        else:
            start_service(Constants.VMAFD_SERVICE_WIN)
            if not is_management_node():
                start_service(Constants.VMCA_SERVICE_WIN)
                start_service(Constants.VMDIRD_SERVICE_WIN)
    except EOFError:
        log_info_msg(Constants.TERMINATE_OP)
        exit(0)
    except Exception as e:
        log_error_msg('Failed to start services required for Certificate Management')
        logging.error(e)
        exit(1)

def print_customcert_replace_options(certType):
    print ("\t 1. Generate Certificate Signing Request(s) and Key(s) for " + certType + "\n")
    print ("\t 2. Import custom certificate(s) and key(s) to replace existing "+ certType + "\n")

    isCSR = raw_input('Option [1 or 2]: ')

    if isCSR.strip() not in ['1','2']:
        raise VMCACSRException ('Unsupported operation selected')
    return isCSR.strip()

def print_post_customcert_csr_options(certType):
    print ("\t 1. Continue to importing Custom certificate(s) and key(s) for " +  certType + "\n")
    print ("\t 2. Exit certificate-manager \n")

    isCSR = raw_input('Option [1 or 2]: ')

    if isCSR.strip() not in ['1','2']:
        raise VMCACSRException ('Unsupported operation selected')
    if isCSR.strip() == '2':
        exit(0)

def replace_ssl_cert_with_custom_cert():
    logging.info('Selected operation: Replace SSL certificate with Custom CA Certificate')
    perform_ssl_cert_ops(False)

def prepare_all_config_file():
    cfg_filenames = ['root','MACHINE_SSL_CERT']
    pnid = vmafd_get_pnid()
    cfg_filenames.extend(vecs._solution_user_stores)
    machine_id = vmafd_machine_id()
    prepare_cfg_file(cfg_filenames, machine_id, pnid)

def replace_root_cert_with_custom_cert():
    logging.info(
        'Selected operation: Replace VMCA Root certificate with Custom CA Certificate and replace all certificates (signed by Custom CA root')
    prepare_all_config_file()
    perform_root_cert_ops(False)


def replace_ssl_cert_with_vmca_cert():
    logging.info('Selected operation: Replace SSL certificate with VMCA Certificate')
    prepare_all_config_file()
    perform_ssl_cert_ops(True)

def regenerate_root_cert_and_replace_all_certs():
    logging.info(
        'Selected operation: Regenerate a new VMCA root cert and replace all certificates (signed by the new root)')
    prepare_all_config_file()
    perform_root_cert_ops(True)


def replace_solution_user_certs_with_custom_cert():
    logging.info('Selected operation: Replace Solution user certs with Custom CA')
    perform_solution_user_cert_ops(False)


def replace_solution_user_certs_with_vmca_cert():
    logging.info('Selected operation: Replace Solution user certs with VMCA Certificate')
    prepare_all_config_file()
    perform_solution_user_cert_ops(True)


def read_custom_certs_for_solution_user():
    cert_file_list = []
    key_file_list = []
    store_list = []
    for store in vecs._solution_user_stores:
        store_list.append(store)
        cert_file_list.append(ask_for_file_and_validate(Constants.READ_SOLUTION_USER_CRT + store))
        key_file_list.append(ask_for_file_and_validate(Constants.READ_SOLUTION_USER_KEY + store))
    return store_list, cert_file_list, key_file_list


def read_custom_certs_for_ssl(option_val):
    if option_val == Constants.MACHINE_SSL_STORE:
        cert_text = Constants.READ_MACHINE_SSL_CRT
        key_text = Constants.READ_MACHINE_SSL_KEY
    else:
        logging.error('Read custom certs for ssl option not found')
    cert_file = ask_for_file_and_validate(cert_text)
    key_file = ask_for_file_and_validate(key_text)
    return cert_file, key_file


def restart_service(service, task_msg, status_msg='Status', showlog=True):
    show_progress(70, Constants.STOPPING_SERVICES, status_msg)
    logging.info(stop_services(service))
    time.sleep(10)
    show_progress(85, Constants.STARTING_SERVICES, status_msg)
    logging.info(start_services(service))
    show_progress(100, task_msg, status_msg)
    print('')
    if vecs._infra_node and showlog:
        log_info_msg('Please restart all services in associated vCenter Server/s for changes made in Platform Service Controller machine to reflect')
        log_info_msg('Perform restart operation on the vCenter Server/s by using \'service-control --stop --all\' and \'service-control --start --all\'')

def get_csr_output_paths():
    privKeyPath = ""
    csrPath = ""
    try:
        privKeyPath = ask_for_output_file_path(Constants.READ_PRIVATEKEY_OP_PATH)
        csrPath = ask_for_output_file_path(Constants.READ_CSR_OP_PATH)
    except Exception as e:
        log_error_msg('Error in file path')
        logging.error(e)
        raise VMCACSRException('Please see log file at {0} for more information'.format(get_log_file()))
    return privKeyPath,csrPath

def perform_csr_ops(privKeyPath,csrPath,solution_user_csr):
    try:
        if solution_user_csr:
            prepare_all_config_file()
            csrDirPath = ask_for_output_file_path(Constants.READ_CSR_OP_DIR_PATH, True)
            for store in vecs._solution_user_stores:
                cfgFile = get_dest_config_file_loc(store)
                privKeyPath = os.path.join(csrDirPath,store+'.key')
                csrPath = os.path.join(csrDirPath,store+'.csr')
                vmca.generateCSR(cfgFile,privKeyPath,csrPath,server,False)
        else:
            cfgFile = get_dest_config_file_loc('certool')
            isRoot = True
            if var.strip() == '1':
                isRoot = False
                prepare_all_config_file()
            vmca.generateCSR(cfgFile,privKeyPath,csrPath,server,isRoot)
        log_info_msg('CSR generated at: '+csrPath)
    except Exception as e:
        log_error_msg('Error while generating CSR')
        logging.error(e)
        raise VMCACSRException('Please see log file at {0} for more information'.format(get_log_file()))

def perform_cert_csr_ops():
    csrDirPath = ""
    privKeyPath = ""
    csrPath = ""
    try:
        csrDirPath = ask_for_output_file_path(Constants.READ_CSR_OP_DIR_PATH, True)
    except Exception as e:
        log_error_msg('Error in output directory path')
        logging.error(e)
        raise VMCACSRException('Please see  log file at {0} for more information'.format(get_log_file()))

    privKeyPath = os.path.join(csrDirPath,Constants.PRIVATE_KEY_OUTPUT_FILENAME)
    csrPath =  os.path.join(csrDirPath,Constants.CSR_OUTPUT_FILENAME)
    perform_csr_ops(privKeyPath,csrPath, False)
    return

def perform_soluser_csr_ops():
    try:
        perform_csr_ops(None, None, True)
    except Exception as e:
        log_error_msg('Error in generating CSR for solution user certificates')
        logging.error(e)
        raise VMCACSRException('Please see log file at {0} for more information'.format(get_log_file()))

def perform_ssl_cert_ops(is_vmca):
    try:
        if is_vmca:
            confirm_operation(Constants.SSL_CONFIRM_MESSAGE)
            show_progress(0, Constants.REPLACE_MACHINE_SSL)
            generate_machine_ssl_and_replace(Constants.MACHINE_SSL_STORE, Constants.MACHINE_SSL_ALIAS, server)
            restart_service(Constants.SERVICES_ALL, Constants.TASK_COMPLETED)
        else:
            isCSR = print_customcert_replace_options('Machine SSL certificate')
            if isCSR == '1':
                perform_cert_csr_ops()
                print_post_customcert_csr_options('Machine SSL certificate')

            (cert_file, key_file) = read_custom_certs_for_ssl(Constants.MACHINE_SSL_STORE)
            root_cert_file = ask_for_file_and_validate(Constants.READ_ROOT_SIGNING_CRT + 'Machine SSL certificate')
            confirm_operation(Constants.SSL_CUSTOM_CONFIRM_MESSAGE)
            validate_custom_cert(cert_file)
            ret_val = verify_cert_with_ca(root_cert_file, cert_file)
            if ret_val:
                show_progress(0, Constants.PUBLISHING_ROOT_CERT)
                dir_cli.trusted_cert_publish(root_cert_file)
                show_progress(10, Constants.REPLACE_MACHINE_SSL)
                replace_cert(Constants.MACHINE_SSL_STORE, Constants.MACHINE_SSL_ALIAS, cert_file, key_file)
                restart_service(Constants.SERVICES_ALL, Constants.TASK_COMPLETED)
    except EOFError:
        log_info_msg(Constants.TERMINATE_OP)
    except VMCACSRException as csrError:
        log_error_msg(csrError)
    except Exception as e:
        show_progress('0', Constants.ROLLBACK_MSG)
        log_error_msg('Error while replacing Machine SSL Cert, please see {0} for more information.'.format(get_log_file()))
        logging.error(e)
        roll_back('0')


def perform_root_cert_ops(is_vmca):
    try:
        if is_vmca:
            confirm_operation(Constants.ROOT_CONFIRM_MSG)
            show_progress(0, Constants.REPLACE_ROOT_CERT)
            replace_root_cert(None, None, server)
        else:
            isCSR = print_customcert_replace_options('VMCA Root Signing certificate')
            if isCSR == '1':
                perform_cert_csr_ops()
                print_post_customcert_csr_options('VMCA Root Signing certificate')

            cert = ask_for_file_and_validate(Constants.READ_ROOT_CRT)
            key = ask_for_file_and_validate(Constants.READ_ROOT_KEY)
            confirm_operation(Constants.CUSTOM_ROOT_CONFIRM_MSG)
            validate_custom_cert(cert)
            show_progress(0, Constants.REPLACE_ROOT_CERT)
            replace_root_cert(cert, key, server)
            show_progress(35, Constants.REPLACED_ROOT_CERT)

        show_progress(35, Constants.REPLACE_MACHINE_SSL)
        generate_machine_ssl_and_replace(Constants.MACHINE_SSL_STORE, Constants.MACHINE_SSL_ALIAS, server)
        percent_complete = 45
        for store in vecs._solution_user_stores:
            show_progress(percent_complete, Constants.REPLACE_SOLUTION_CERT.format(store))
            generate_solution_user_cert_and_replace(store, store, server)
            percent_complete += 5
        restart_service(Constants.SERVICES_ALL, Constants.TASK_COMPLETED)
    except EOFError:
        log_info_msg(Constants.TERMINATE_OP)
    except VMCACSRException as csrError:
        log_error_msg(csrError)
    except Exception as e:
        if vecs._management_node:
            show_progress('0', Constants.MGMT_ROLLBACK_MSG.format(server))
            log_error_msg('Error while performing Cert Replacement operation, please see {0} for more information.'.format(get_log_file()))
            logging.error(e)
            return
        show_progress('0', Constants.ROLLBACK_MSG)
        log_error_msg('Error while performing Cert Replacement operation, please see {0} for more information.'.format(get_log_file()))
        logging.error(e)
        roll_back('1')


def perform_solution_user_cert_ops(isvmca):
    try:
        if isvmca:
            percent_complete = 10
            confirm_operation(Constants.SOL_CONFIRM_MSG)
            for store in vecs._solution_user_stores:
                show_progress(percent_complete, Constants.REPLACE_SOLUTION_CERT.format(store))
                generate_solution_user_cert_and_replace(store, store, server)
                percent_complete += 10
            restart_service(Constants.SERVICES_ALL, Constants.TASK_COMPLETED)
        else:
            isCSR = print_customcert_replace_options('Solution User Certificates')
            if isCSR == '1':
                perform_soluser_csr_ops()
                print_post_customcert_csr_options('Solution User Certificates')

            (store_list, cert_file_list, key_file_list) = read_custom_certs_for_solution_user()
            root_cert_file = ask_for_file_and_validate(Constants.READ_ROOT_SIGNING_CRT + 'Solution User Certificates')
            validate_custom_cert(root_cert_file)
            for s_cert in cert_file_list:
                if not(verify_cert_with_ca(root_cert_file, s_cert)):
                    logging.error('Custom CA and solution user certificates not matching')
                    exit(0)
            confirm_operation(Constants.SOL_CUSTOM_CONFIRM_MSG)
            show_progress(0, Constants.PUBLISHING_ROOT_CERT)
            dir_cli.trusted_cert_publish(root_cert_file)
            index = 0
            percent_complete = 30
            for store in store_list:
                show_progress(percent_complete, Constants.REPLACE_SOLUTION_CERT.format(store))
                replace_solution_user_certs(store, store, cert_file_list[index], key_file_list[index])
                index += 1
                percent_complete += 5
            restart_service(Constants.SERVICES_ALL, Constants.TASK_COMPLETED)
    except EOFError:
        log_info_msg(Constants.TERMINATE_OP)
    except VMCACSRException as csrError:
        log_error_msg(csrError)
    except Exception as e:
        show_progress('0', Constants.ROLLBACK_MSG)
        logging.error(e)
        roll_back('2')


def revert_certificate(store, alias, isSolutionUserCert=True):
    """
    Method to revert current certificate by reading backup from BACKUP_STORE
    """
    try:
        #Export certs from BACKUP_STORE to file
        cert = get_rollback_cert_dir() + store + Constants.BKP_CERT_EXT
        key = get_rollback_cert_dir() + store + Constants.BKP_KEY_EXT
        vecs.get_key_file(Constants.BACKUP_STORE, 'bkp_' + alias, key, True)
        vecs.get_cert_file(Constants.BACKUP_STORE, 'bkp_' + alias, cert, True)
        if isSolutionUserCert:
            replace_solution_user_certs(store, alias, cert, key, True, False)
        else:
            replace_cert(store, alias, cert, key, False)
        #Delete exported certs from file system once operation is completed
        remove_file(cert)
        remove_file(key)
    except EOFError:
        log_info_msg(Constants.TERMINATE_OP)
    except Exception as e:
        if 'status : 216' in str(e):
            log_info_msg(
                'Backup certificate not found in {0} store, Skipping revert operation of {0} certificate'.format(store))
            return
        else:
            msg = 'Error while reverting certificate for store : ' + store
            log_info_msg(msg)
            raise Exception(msg)


def revert_root_certificate():
    """
    Method to revert root certificate using VMCA backup
    """
    try:
        cert = get_root_cert_dir() + Constants.BKP_ROOT_CERT
        key = get_root_cert_dir() + Constants.BKP_ROOT_KEY
        if not check_file_exists(cert) or not check_file_exists(key):
            log_info_msg(
                'Root certificate backup not found, looks like Root Signing certificate was never changed.\nSkipping revert operation of Root Certificate')
            return
        vmca.rootca(cert, key, server)
    except EOFError:
        log_info_msg(Constants.TERMINATE_OP)
    except Exception as e:
        msg = 'Error while reverting Root certificate, please see {0} for more information.'.format(get_log_file())
        log_info_msg(msg)
        logging.error(e)
        raise Exception(msg)


def revert():
    """
        Method to revert last performed operation by re-publishing old certs
    """
    try:
        if vecs._management_node:
            log_info_msg(Constants.MGMT_REVERT_MSG.format(server))
            if not get_user_confirmation(Constants.CONTINUE_OPERATION):
                log_info_msg(Constants.TERMINATE_OP)
                return
            show_progress(30, Constants.REVERT_MACHINE_SSL, Constants.REVERT_STATUS)
            revert_certificate(Constants.MACHINE_SSL_STORE, Constants.MACHINE_SSL_ALIAS, False)
            percent_complete = 40
            for store in vecs._solution_user_stores:
                show_progress(percent_complete, Constants.REVERT_SOLUTION_CERT.format(store), Constants.REVERT_STATUS)
                revert_certificate(store, store)
                percent_complete += 5
        else:
            log_info_msg(Constants.REVERT_MSG)
            if not get_user_confirmation(Constants.CONTINUE_OPERATION):
                log_info_msg(Constants.TERMINATE_OP)
                return
            show_progress(0, Constants.REVERT_ROOT_CERT, Constants.REVERT_STATUS)
            revert_root_certificate()
            show_progress(30, Constants.REVERT_MACHINE_SSL, Constants.REVERT_STATUS)
            revert_certificate(Constants.MACHINE_SSL_STORE, Constants.MACHINE_SSL_ALIAS, False)
            percent_complete = 40
            for store in vecs._solution_user_stores:
                show_progress(percent_complete, Constants.REVERT_SOLUTION_CERT.format(store), Constants.REVERT_STATUS)
                revert_certificate(store, store)
                percent_complete += 5
        restart_service(Constants.SERVICES_ALL, Constants.REVERT_TASK_COMPLETED, Constants.REVERT_STATUS)
    except EOFError:
        log_info_msg(Constants.TERMINATE_OP)
    except Exception as e:
        show_progress('0', Constants.REVERT_ERROR_MSG, Constants.REVERT_STATUS)
        logging.error(e)
        log_error_msg('please see {0} for more information.'.format(get_log_file()))

def factory_reset_all_certs():
    """
    Function to factory reset certificates using VMCA, there is no rollback operation performed in case of failures
    """
    try:
        if vecs._management_node:
            log_info_msg(Constants.MGMT_RESET_MSG.format(server))
            prepare_all_config_file()
            if not get_user_confirmation(Constants.CONTINUE_OPERATION):
                log_info_msg(Constants.TERMINATE_OP)
                return
            confirm_operation(Constants.MGMT_RESET_MSG)
            show_progress(0, Constants.RESET_MACHINE_SSL)
            generate_machine_ssl_and_replace(Constants.MACHINE_SSL_STORE, Constants.MACHINE_SSL_ALIAS, server)
            percent_complete = 45
            for store in vecs._solution_user_stores:
                show_progress(percent_complete, Constants.RESET_SOLUTION_CERT.format(store))
                generate_solution_user_cert_and_replace(store, store, server)
                percent_complete += 5
        else:
            prepare_all_config_file()
            if not get_user_confirmation(Constants.CONTINUE_OPERATION):
                log_info_msg(Constants.TERMINATE_OP)
                return
            confirm_operation(Constants.RESET_MSG)
            show_progress(0, Constants.RESET_ROOT_CERT)
            replace_root_cert(None, None, server)
            show_progress(30, Constants.RESET_MACHINE_SSL)

            # Once root cert is replaced then replace Machine SSL cert and Solution user certs
            generate_machine_ssl_and_replace(Constants.MACHINE_SSL_STORE, Constants.MACHINE_SSL_ALIAS, server)
            percent_complete = 45
            for store in vecs._solution_user_stores:
                show_progress(percent_complete, Constants.RESET_SOLUTION_CERT.format(store))
                generate_solution_user_cert_and_replace(store, store, server)
                percent_complete += 5
        restart_service(Constants.SERVICES_ALL, Constants.RESET_TASK_COMPLETED, Constants.RESET_STATUS)
    except EOFError:
        log_info_msg(Constants.TERMINATE_OP)
    except Exception as e:
        show_progress('0', Constants.RESET_ERROR_MSG)
        logging.error(e)
        log_error_msg('please see {0} for more information.'.format(get_log_file()))


def roll_back(operation):
    """
    Function to perform automatic rollback in case of failures
    """
    if operation == '0':
        try:
            log_info_msg(Constants.SSL_ROLLBACK_MSG)
            show_progress(0, Constants.ROLLBACK_MACHINE_SSL, Constants.ROLLBACK_STATUS)
            revert_certificate(Constants.MACHINE_SSL_STORE, Constants.MACHINE_SSL_ALIAS, False)
            restart_service(Constants.SERVICES_NON_CORE, Constants.ROLLBACK_TASK_COMPLETED, Constants.ROLLBACK_STATUS, False)
        except Exception as e:
            show_progress('0', Constants.ROLLBACK_ERROR_MSG, Constants.ROLLBACK_STATUS)
            log_error_msg(Constants.ROLLBACK_FAILED_MSG)
            log_error_msg('please see {0} for more information.'.format(get_log_file()))
    elif operation == '1':
        try:
            log_info_msg(Constants.ROOT_ROLLBACK_MSG)
            show_progress(0, Constants.ROLLBACK_ROOT_CERT, Constants.ROLLBACK_STATUS)
            revert_root_certificate()

            # Once root cert is replaced then replace Machine SSL cert and Solution user certs
            show_progress(30, Constants.ROLLBACK_MACHINE_SSL, Constants.ROLLBACK_STATUS)
            revert_certificate(Constants.MACHINE_SSL_STORE, Constants.MACHINE_SSL_ALIAS, False)

            percent_complete = 40
            for store in vecs._solution_user_stores:
                show_progress(percent_complete, Constants.ROLLBACK_SOLUTION_CERT.format(store), Constants.ROLLBACK_STATUS)
                revert_certificate(store, store)
                percent_complete += 10
            restart_service(Constants.SERVICES_ALL, Constants.ROLLBACK_TASK_COMPLETED, Constants.ROLLBACK_STATUS, False)
        except Exception as e:
            show_progress('0', Constants.ROLLBACK_ERROR_MSG, Constants.ROLLBACK_STATUS)
            log_error_msg(Constants.ROLLBACK_FAILED_MSG)
            log_error_msg('please see {0} for more information.'.format(get_log_file()))
    elif operation == '2':
        try:
            percent_complete = 10
            for store in vecs._solution_user_stores:
                show_progress(percent_complete, Constants.ROLLBACK_SOLUTION_CERT, Constants.ROLLBACK_STATUS)
                revert_certificate(store, store)
                percent_complete += 5
            restart_service(Constants.SERVICES_ALL, Constants.ROLLBACK_TASK_COMPLETED, Constants.ROLLBACK_STATUS, False)
        except Exception as e:
            show_progress('0', Constants.ROLLBACK_ERROR_MSG, Constants.ROLLBACK_STATUS)
            log_error_msg(Constants.ROLLBACK_FAILED_MSG)
            log_error_msg('please see {0} for more information.'.format(get_log_file()))


def get_machine_ssl_cert_to_dir():
    oldcert = os.path.join(get_cis_tmp_dir(), Constants.BKP_MACHINE_CERT)
    if check_file_exists(oldcert):
        remove_file(oldcert)
    vecs.get_cert_file(Constants.MACHINE_SSL_STORE, Constants.MACHINE_SSL_ALIAS, oldcert)

# Scripts responsible for cert replacement

def replace_cert(store_name, alias, cert_file, key_file, verify=True):
    logging.info('Replacing cert for : {0}'.format(store_name))
    logging.info('Get existing cert details for alias {0} in store : {1}'.format(alias, store_name))
    (serial_number, thumb_print) = parse_cert(vecs.get_cert(store_name, alias))
    vecs.entry_delete(store_name, alias)
    logging.info('Ensure that the cert is deleted by doing list again')
    logging.info(vecs.list_entries(store_name))
    logging.info('Create a entry using Key and File generated earlier')
    vecs.entry_create(store_name, alias, cert_file, key_file)
    logging.info('Ensure that the Machine SSL cert is created by doing list again')
    logging.info(vecs.list_entries(store_name))
    if verify:
        verify_cert_changed(vecs, serial_number, thumb_print, store_name, alias, server)
    if store_name == "MACHINE_SSL_CERT":
        user, password = get_credentials()
        oldcert = os.path.join(get_cis_tmp_dir(), Constants.BKP_MACHINE_CERT)
        machine_sslthumbprint = get_cert_thumbprint(oldcert)
        iscomparerequired = True
        if var.strip() in ['1']:
            iscomparerequired = compare_certificate_san(oldcert, cert_file)
        if iscomparerequired:
            update_service_endpoints(node_type, user, password, cert_file, machine_sslthumbprint)
            remove_file(oldcert)
        else:
            log_error_msg(Constants.SAN_MSG)
            roll_back('0')


def generate_machine_ssl_and_replace(store_name, alias, server):
    cfg_file = 'MACHINE_SSL_CERT'
    vmca.generate_cert(store_name, server, cfg_file)
    cert = get_cert_dir() + store_name + Constants.CERT_EXT
    key = get_cert_dir() + store_name + Constants.KEY_EXT
    replace_cert(store_name, alias, cert, key)

def generate_solution_user_cert_and_replace(store_name, alias, server):
    if (cfg_flag):
        cfg_filename = store_name
        vmca.generate_cert(store_name, server, cfg_filename)
    else:
        vmca.generate_solution_user_cert(store_name, server)
    cert = get_cert_dir() + store_name + Constants.CERT_EXT
    key = get_cert_dir() + store_name + Constants.KEY_EXT
    replace_solution_user_certs(store_name, alias, cert, key)

def replace_solution_user_certs(store_name, alias, cert_file, key_file, ignore_error=False, verify=True):
    service_name = dir_cli.get_service_name_for_solution_user(store_name)
    logging.info('service name {0}'.format(service_name))
    dir_cli.update_lotus(service_name, cert_file, ignore_error)
    replace_cert(store_name, alias, cert_file, key_file, verify)


def replace_root_cert(cert, key, server, verify=True):
    (serial_number, thumb_print) = parse_cert(vmca.get_root_ca(server))
    if cert is None or key is None:
        logging.info('Regenerating Root Cert using VMCA...')
        cfg_file = 'root'
        vmca.selfca(server, cfg_file)
    else:
        logging.info('Replacing Root Cert using Custom CA...')
        vmca.rootca(cert, key, server)
    logging.info('Get existing cert details for alias root.')
    if verify:
        verify_cert_changed(vecs, serial_number, thumb_print, None, None, server, True)


operations = {
    '1': replace_ssl_cert_with_custom_cert,
    '2': replace_root_cert_with_custom_cert,
    '3': replace_ssl_cert_with_vmca_cert,
    '4': regenerate_root_cert_and_replace_all_certs,
    '5': replace_solution_user_certs_with_custom_cert,
    '6': replace_solution_user_certs_with_vmca_cert,
    '7': revert,
    '8': factory_reset_all_certs
}


def parse_arguments():
    print("\t\t _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ ")
    print("\t\t|                                                                     |")
    print("\t\t|      *** Welcome to the vSphere 6.0 Certificate Manager  ***        |")
    print("\t\t|                                                                     |")
    print("\t\t|                   -- Select Operation --                            |")
    print("\t\t|                                                                     |")
    print("\t\t|      1. Replace Machine SSL certificate with Custom Certificate     |")
    print("\t\t|                                                                     |")
    print("\t\t|      2. Replace VMCA Root certificate with Custom Signing           |")
    print("\t\t|         Certificate and replace all Certificates                    |")
    print("\t\t|                                                                     |")
    print("\t\t|      3. Replace Machine SSL certificate with VMCA Certificate       |")
    print("\t\t|                                                                     |")
    print("\t\t|      4. Regenerate a new VMCA Root Certificate and                  |")
    print("\t\t|         replace all certificates                                    |")
    print("\t\t|                                                                     |")
    print("\t\t|      5. Replace Solution user certificates with                     |")
    print("\t\t|         Custom Certificate                                          |")
    print("\t\t|                                                                     |")
    print("\t\t|      6. Replace Solution user certificates with VMCA certificates   |")
    print("\t\t|                                                                     |")
    print("\t\t|      7. Revert last performed operation by re-publishing old        |")
    print("\t\t|         certificates                                                |")
    print("\t\t|                                                                     |")
    print("\t\t|      8. Reset all Certificates                                      |")
    print("\t\t|_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _|")
    print(Constants.EXIT_MSG)
    global var
    var = raw_input("Option[1 to 8]: ")
    if var.strip() not in ['1', '2', '3', '4', '5', '6', '7', '8']:
        log_info_msg("Unsupported operation selected, Please select any one of Option[1/2/3/4/5/6/7/8]")
    else:
        # Init logging and certificate manager directory
        initialize_ops()
        global cfg_flag
        if var.strip() in ['2', '4', '6', '8']:
            cfg_flag = get_user_confirmation('Do you wish to generate all certificates using configuration file')
        read_and_validate_password()
        global vecs
        vecs = VecsOps()
        if vecs._management_node and var.strip() in ['2','4']:
            log_info_msg('PSC certificate operations are not supported from Management machine, please perform from Platform Service Controller machine')
            return
        initialize_services()
        check_and_request_server_ip()
        get_machine_ssl_cert_to_dir()
        operations[var.strip()]()


#
# The work starts here.
#
def main():
    try:
        parse_arguments()
    except EOFError:
        log_info_msg(Constants.TERMINATE_OP)


if __name__ == '__main__':
    exit(main())
