# osmo_gsm_tester: specifics for running a osmo-pcu for OC-2G
#
# Copyright (C) 2019 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 pcu

class OsmoPcuOC2G(pcu.Pcu):

    REMOTE_DIR = '/osmo-gsm-tester-pcu'
    PCU_OC2G_BIN = 'osmo-pcu'
    PCU_OC2G_CFG = 'osmo-pcu-oc2g.cfg'

    def __init__(self, testenv, btsoc2g, conf):
        super().__init__(testenv, btsoc2g, conf, self.PCU_OC2G_BIN)
        self.run_dir = None
        self.bsc = None
        self.inst = None
        self.remote_inst = None
        self.remote_dir = None
        self.remote_env = {}
        self.remote_user = 'root'

    def start(self, keepalive=False):
        self.run_dir = util.Dir(self.testenv.suite().get_run_dir().new_dir(self.name()))
        self.configure()

        self.inst = util.Dir(os.path.abspath(self.testenv.suite().trial().get_inst('osmo-pcu-oc2g')))
        lib = self.inst.child('lib')
        if not os.path.isdir(lib):
            raise log.Error('No lib/ in', self.inst)
        if not self.inst.isfile('bin', OsmoPcuOC2G.PCU_OC2G_BIN):
            raise log.Error('No osmo-pcu-oc2g binary in', self.inst)

        self.remote_dir = util.Dir(OsmoPcuOC2G.REMOTE_DIR)
        self.remote_inst = util.Dir(self.remote_dir.child(os.path.basename(str(self.inst))))

        self.run_remote('rm-remote-dir', ('test', '!', '-d', OsmoPcuOC2G.REMOTE_DIR, '||', 'rm', '-rf', OsmoPcuOC2G.REMOTE_DIR))
        self.run_remote('mk-remote-dir', ('mkdir', '-p', OsmoPcuOC2G.REMOTE_DIR))
        self.run_local('scp-inst-to-btsoc2g',
            ('scp', '-r', str(self.inst), '%s@%s:%s' % (self.remote_user, self.bts.remote_addr(), str(self.remote_inst))))

        remote_run_dir = self.remote_dir.child(OsmoPcuOC2G.PCU_OC2G_BIN)
        self.run_remote('mk-remote-run-dir', ('mkdir', '-p', remote_run_dir))

        remote_config_file = self.remote_dir.child(OsmoPcuOC2G.PCU_OC2G_CFG)
        self.run_local('scp-cfg-to-btsoc2g',
            ('scp', '-r', self.config_file, '%s@%s:%s' % (self.remote_user, self.bts.remote_addr(), remote_config_file)))

        remote_lib = self.remote_inst.child('lib')
        remote_binary = self.remote_inst.child('bin', OsmoPcuOC2G.PCU_OC2G_BIN)
        self.launch_remote(OsmoPcuOC2G.PCU_OC2G_BIN,
            ('LD_LIBRARY_PATH=%s' % remote_lib,
             remote_binary, '-c', remote_config_file, '-r', '1',
             '-i', self.bts.bsc.addr()),
            remote_cwd=remote_run_dir, keepalive=keepalive)

    def _process_remote(self, name, popen_args, remote_cwd=None):
        run_dir = self.run_dir.new_dir(name)
        return process.RemoteProcess(name, run_dir, self.remote_user, self.bts.remote_addr(), remote_cwd,
                                     popen_args)

    def run_remote(self, name, popen_args, remote_cwd=None):
        proc = self._process_remote(name, popen_args, remote_cwd)
        proc.launch()
        proc.wait()
        if proc.result != 0:
            log.ctx(proc)
            raise log.Error('Exited in error')

    def launch_remote(self, name, popen_args, remote_cwd=None, keepalive=False):
        proc = self._process_remote(name, popen_args, remote_cwd)
        self.testenv.remember_to_stop(proc, keepalive)
        proc.launch()

    def run_local(self, name, popen_args):
        run_dir = self.run_dir.new_dir(name)
        proc = process.Process(name, run_dir, popen_args)
        proc.launch()
        proc.wait()
        if proc.result != 0:
            log.ctx(proc)
            raise log.Error('Exited in error')

    def configure(self):
        self.config_file = self.run_dir.new_file(OsmoPcuOC2G.PCU_OC2G_CFG)
        self.dbg(config_file=self.config_file)

        values = { 'osmo_pcu_oc2g': config.get_defaults('osmo_pcu_oc2g') }
        config.overlay(values, self.testenv.suite().config())
        config.overlay(values, {
                        'osmo_pcu_oc2g': {
                            'bts_addr': self.bts.remote_addr(),
                            'pcu_socket_path': self.bts.pcu_socket_path(),
                            'egprs_enabled': self.egprs_enabled(),
                        }
        })
        config.overlay(values, { 'osmo_pcu_oc2g': self.conf })

        self.dbg('OSMO-PCU-OC2G CONFIG:\n' + pprint.pformat(values))

        with open(self.config_file, 'w') as f:
            r = template.render(OsmoPcuOC2G.PCU_OC2G_CFG, values)
            self.dbg(r)
            f.write(r)

# vim: expandtab tabstop=4 shiftwidth=4
