#!/usr/bin/python
# Copyright 2015,2016,2017,2018,2019,2020 Cumulus Networks, Inc.  All rights reserved.
#
# datapath-config --
#
#
#
#
#
#
#

import sys
import argparse
from argparse import RawTextHelpFormatter
import os
import subprocess
import re
import time
import logging
import logging.handlers
import traceback
import cumulus.platforms

# initialize the global logger
global logger
logger = logging.getLogger('switchd')
fmt = logging.Formatter(fmt='%(name)s %(levelname)s: %(message)s')
handler = logging.handlers.SysLogHandler('/dev/log')
handler.setFormatter(fmt)
logger.setLevel(logging.INFO)
logger.addHandler(handler)

# ----------------------------------------------------------
#
#                         m a i n
#
# ----------------------------------------------------------

def main(argv) :

    if (os.geteuid() != 0) :
        logger.error('You need to have root privileges to run this script.')
        return

    # check the chip type
    platform_object = cumulus.platforms.probe()
    chip = platform_object.switch.chip
    if not (isinstance(chip, cumulus.platform.TridentChip) or \
            isinstance(chip, cumulus.platform.TridentTwo_56850_Chip) or \
            isinstance(chip, cumulus.platform.TridentTwo_56854_Chip) or \
            isinstance(chip, cumulus.platform.TridentTwoPlus_56860_Chip) or \
            isinstance(chip, cumulus.platform.TridentTwoPlus_56864_Chip) or \
            isinstance(chip, cumulus.platform.TridentThreeX5Chip) or \
            isinstance(chip, cumulus.platform.TridentThreeX5_56771_Chip) or \
            isinstance(chip, cumulus.platform.TridentThreeX7Chip) or \
            isinstance(chip, cumulus.platform.TridentThreeX7_56870_Chip) or \
            isinstance(chip, cumulus.platform.TridentThreeX7_56873_Chip) or \
            isinstance(chip, cumulus.platform.Helix4Chip) or \
            isinstance(chip, cumulus.platform.MaverickChip) or \
            isinstance(chip, cumulus.platform.TomahawkChip) or \
            isinstance(chip, cumulus.platform.TomahawkPlus_56965_Chip) or \
            isinstance(chip, cumulus.platform.TomahawkPlus_56967_Chip) or \
            isinstance(chip, cumulus.platform.QumranChip) or \
            isinstance(chip, cumulus.platform.Qumran_88370_Chip) or \
            isinstance(chip, cumulus.platform.Qumran_88375_Chip)):
        # this script is not used for the chip
        return

    # useful pathnames
    script_dir          = '/usr/lib/cumulus/'
    usr_config_dir      = '/etc/cumulus/'
    bcm_dir             = '/etc/bcm.d/'
    bcm_config_dir      = '/etc/bcm.d/datapath/'

    # backend-specific file prefixes
    register_file_prefix = '/var/lib/cumulus/rc.datapath'

    # input file names
    backend_map     = bcm_dir + 'backend_map'
    traffic_file    = usr_config_dir + 'datapath/traffic.conf'
    datapath_file   = bcm_config_dir + 'datapath.conf'
    forwarding_file = bcm_config_dir + 'rc.forwarding'
    hw_desc_file    = bcm_config_dir + 'hw_desc'

    # output file
    parameter_file = bcm_dir + 'config.d/03datapath.bcm'

    descr  = "datapath-config is the datapath configuration manager.\n"
    descr += "It will invoke datapath-update to generate the \n"
    descr += "/etc/cumulus/rc.datapath_<n> file(s), one for each backend on the platform.\n"
    arg_parser = argparse.ArgumentParser(description=descr, formatter_class=RawTextHelpFormatter)    

    # parse the command line argumetns
    cmdline_args = arg_parser.parse_args()

    register_file = register_file_prefix
    if not os.path.isfile(datapath_file) :
        # don't try to build a register file for this platform
        logger.info('Skipping rc.datapath generation: no datapath.conf found in %s' % bcm_config_dir)
        return
    if not os.path.isfile(backend_map) :
        logger.error('Error: no backend map found in %s' % bcm_dir)
        return

    # read in the backend index list
    backend_map_re = re.compile('backend (?P<idx>\d+)')
    backend_list = []
    f = open(backend_map)
    for line in f:
        m = backend_map_re.match(line)
        if m :
            backend_list.append(m.group('idx'))

    # set the traffic configuration file
    if not os.path.isfile(traffic_file) :
        logger.error('Error: traffic configure file %s not found' % traffic_file)
        return

    # verify the input files exist
    if not os.path.isfile(hw_desc_file) :
        logger.error('Error: hardware description file %s not found' % hw_desc_file)
        return
    if not os.path.isfile(forwarding_file) :
        logger.error('Error: forwarding file %s not found' % forwarding_file)
        return

    # generate the register file and parameter file for each backend
    for backend_idx in backend_list :
        backend_register_file = register_file_prefix + '_%s' % backend_idx
        logger.info('generating register file %s' % backend_register_file)
        if os.path.isfile(backend_register_file) :
            # remove the existing file
            os.unlink(backend_register_file)
        logger.info('generating parameter file %s' % parameter_file)
        command_str = [ script_dir + 'datapath-update',
            '-c', hw_desc_file, '-t', traffic_file,
            '-d', datapath_file, '-f', forwarding_file,
            '-r', backend_register_file, '-g', parameter_file ]
        subprocess.call(command_str);

        # verify the register file
        if not os.path.isfile(backend_register_file) :
            logger.error('Error: backend register file %s not found' % backend_register_file)
            return

        # verify the parameter file
        if not os.path.isfile(parameter_file) :
            logger.error('Error: backend parameter file %s not found' % parameter_file)
            return

# ----------------------------------------------------------
#
#                         e n t r y
#
# ----------------------------------------------------------

if __name__ == "__main__":
    main(sys.argv[1:])
