# osmo_gsm_tester: specifics for running an osmo-bts-octphy
#
# Copyright (C) 2016-2017 by sysmocom - s.f.m.c. GmbH
#
# Author: Pau Espin Pedrol <pespin@sysmocom.de>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

import os
import pprint
from ..core import log, config, util, template, process
from . import bts_osmo

class OsmoBtsOctphy(bts_osmo.OsmoBtsMainUnit):

##############
# PROTECTED
##############

    BIN_BTS_OCTPHY = 'osmo-bts-octphy'
    CONF_BTS_OCTPHY = 'osmo-bts-octphy.cfg'

    def __init__(self, testenv, conf):
        super().__init__(testenv, conf, OsmoBtsOctphy.BIN_BTS_OCTPHY, 'osmo_bts_octphy')
        self.run_dir = None
        self.inst = None
        self.env = {}
        self.values = {}

    def launch_process(self, binary_name, *args):
        binary = os.path.abspath(self.inst.child('bin', binary_name))
        run_dir = self.run_dir.new_dir(binary_name)
        if not os.path.isfile(binary):
            raise RuntimeError('Binary missing: %r' % binary)
        proc = process.Process(binary_name, run_dir,
                               (binary,) + args,
                               env=self.env)
        self.testenv.remember_to_stop(proc)
        proc.launch()
        return proc

    def allocate_phy_instances(self, c):
        '''
        Generate match trx Z <-> phy X inst Y to use in vty config

        We create a new phy for each trx found with a new hwaddr. If hwaddr is
        already there, increase num_instances and give last instance index to
        the current trx.
        '''
        phy_list = []
        for trx in c.get('trx_list', []):
            hwaddr = trx.get('hw_addr', None)
            netdev = trx.get('net_device', None)
            if hwaddr is None:
                raise log.Error('Expected hw-addr value not found!')
            found = False
            phy_idx = 0
            for phy in phy_list:
                if phy['hw_addr'] == hwaddr:
                    phy['num_instances'] += 1
                    found = True
                    break
                phy_idx += 1
            if not found:
                phy_list.append({'hw_addr': hwaddr, 'net_device': netdev, 'num_instances': 1})
            trx['phy_idx'] = phy_idx
            trx['instance_idx'] = phy_list[phy_idx]['num_instances'] - 1
        c['phy_list'] = phy_list

    def configure(self):
        if self.bsc is None:
            raise RuntimeError('BTS needs to be added to a BSC or NITB before it can be configured')
        self.config_file = self.run_dir.new_file(OsmoBtsOctphy.CONF_BTS_OCTPHY)
        self.dbg(config_file=self.config_file)

        values = dict(osmo_bts_octphy=config.get_defaults('osmo_bts_octphy'))
        config.overlay(values, self.testenv.suite().config())
        config.overlay(values, {
                        'osmo_bts_octphy': {
                            'oml_remote_ip': self.bsc.addr(),
                            'pcu_socket_path': self.pcu_socket_path(),
                        }
        })
        config.overlay(values, { 'osmo_bts_octphy': self.conf })

        self.allocate_phy_instances(values['osmo_bts_octphy'])

        self.dbg('OSMO-BTS-OCTPHY CONFIG:\n' + pprint.pformat(values))
        self.values = values
        with open(self.config_file, 'w') as f:
            r = template.render(OsmoBtsOctphy.CONF_BTS_OCTPHY, values)
            self.dbg(r)
            f.write(r)

########################
# PUBLIC - INTERNAL API
########################
    def conf_for_bsc(self):
        values = self.conf_for_bsc_prepare()
        self.dbg(conf=values)
        return values

###################
# PUBLIC (test API included)
###################
    def start(self):
        if self.bsc is None:
            raise RuntimeError('BTS needs to be added to a BSC or NITB before it can be started')
        self.testenv.poll()

        self.log('Starting to connect to', self.bsc)
        self.run_dir = util.Dir(self.testenv.test().get_run_dir().new_dir(self.name()))
        self.configure()

        self.inst = util.Dir(os.path.abspath(self.testenv.suite().trial().get_inst('osmo-bts')))
        btsoct_path = self.inst.child('bin', OsmoBtsOctphy.BIN_BTS_OCTPHY)
        lib = self.inst.child('lib')
        if not os.path.isdir(lib):
            raise RuntimeError('No lib/ in %r' % self.inst)

        # setting capabilities will later disable use of LD_LIBRARY_PATH from ELF loader -> modify RPATH instead.
        self.log('Setting RPATH for', OsmoBtsOctphy.BIN_BTS_OCTPHY)
        util.change_elf_rpath(btsoct_path, util.prepend_library_path(lib), self.run_dir.new_dir('patchelf'))
        # osmo-bty-octphy requires CAP_NET_RAW to open AF_PACKET socket:
        self.log('Applying CAP_NET_RAW capability to', OsmoBtsOctphy.BIN_BTS_OCTPHY)
        util.setcap_net_raw(btsoct_path, self.run_dir.new_dir('setcap_net_raw'))

        self.proc_bts = self.launch_process(OsmoBtsOctphy.BIN_BTS_OCTPHY, '-r', '1',
                            '-c', os.path.abspath(self.config_file),
                            '-i', self.bsc.addr(), '-t', str(self.num_trx()))
        self.testenv.poll()

# vim: expandtab tabstop=4 shiftwidth=4
