# Copyright 2015 UnitedStack, Inc.
# All Rights Reserved.
#
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

import os
import re
import time
import tempfile
import signal
import shlex
import subprocess
import platform
from threading import Timer
from stetho.agent.common import resource
from stetho.agent.common import log

LOG = log.get_logger()


def execute(cmd, shell=False, root=False, timeout=10):
    try:
        if root:
            cmd.insert(0, 'sudo')
        LOG.info(cmd)
        subproc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE, shell=shell)
        timer = Timer(timeout, lambda proc: proc.kill(), [subproc])
        timer.start()
        subproc.wait()
        stdcode = subproc.returncode
        stdout = subproc.stdout.readlines()
        stderr = subproc.stderr.readlines()
        timer.cancel()

        def list_strip(lines):
            return [line.strip() for line in lines]
        return stdcode, list_strip(stderr) if stdcode else list_strip(stdout)
    except Exception as e:
        LOG.error(e)
        raise


def execute_wait(cmd, shell=False, root=False):
    subproc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
                               stderr=subprocess.PIPE, shell=shell)
    stdout, stderr = subproc.communicate()
    stdcode = subproc.returncode
    return stdcode, stdout, stderr


def create_deamon(cmd, shell=False, root=False):
    """Usage:
        Create servcice process.
    """
    try:
        if root:
            cmd.insert(0, 'sudo')
        LOG.info(cmd)
        subproc = subprocess.Popen(cmd, shell=shell, stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE)
        return subproc.pid
    except Exception as e:
        LOG.error(e)
        raise


def kill_process_by_id(pid):
    pid = int(pid)
    os.kill(pid, signal.SIGILL)
    os.waitpid(pid, 0)


def get_interface(interface):
    """Support Centos standard physical interface,
       such as eth0.
    """
    # Supported CentOS Version
    supported_dists = ['7.0', '6.5']

    def format_centos_7_0(inf):
        pattern = r'<([A-Z]+)'
        state = re.search(pattern, stdout[0]).groups()[0]
        state = 'UP' if not cmp(state, 'UP') else 'DOWN'
        inf.state = state
        stdout.pop(0)
        pattern = r'inet\s(.*)\s\snetmask\s(.*)\s\sbroadcast\s(.*)'
        for line in stdout:
            if line.startswith('inet '):
                tmp = re.search(pattern, line).groups()
                (inf.inet, inf.netmask, inf.broadcast) = tmp
                stdout.remove(line)
                break
        for line in stdout:
            if line.startswith('ether'):
                inf.ether = line[6:23]
                break
        return stdcode, '', inf.make_dict()

    def format_centos_6_5(inf):
        pattern = r'HWaddr\s(.*)'
        inf.ether = re.search(pattern, stdout[0]).groups()[0]
        stdout.pop(0)
        pattern = r'addr:(.*)\s\sBcast:(.*)\s\sMask:(.*)'
        for line in stdout:
            if line.startswith('inet '):
                tmp = re.search(pattern, line).groups()
                (inf.inet, inf.broadcast, inf.netmask) = tmp
                stdout.remove(line)
                break
        inf.state = 'DOWN'
        for line in stdout:
            if 'RUNNING' in line:
                state = line[:2]
                state = 'UP' if not cmp(state, 'UP') else 'DOWN'
                inf.state = state
                break
        return stdcode, '', inf.make_dict()

    linux_dist = platform.linux_distribution()[1][:3]
    if linux_dist in supported_dists:
        try:
            cmd = ['ifconfig', interface]
            stdcode, stdout = execute(cmd)
            inf = resource.Interface(interface)
            if not cmp(linux_dist, '6.5'):
                return format_centos_6_5(inf)
            elif not cmp(linux_dist, '7.0'):
                return format_centos_7_0(inf)
        except Exception as e:
            message = stdout.pop(0)
            return stdcode, message, None

    # Unsupported OS distribute
    message = 'Unsupported OS distribute %s, only support for CentOS %s.'
    message = message % (linux_dist, str(supported_dists))
    return 1, message, None


def register_api(server, api_obj):
    methods = dir(api_obj)
    apis = filter(lambda m: not m.startswith('_'), methods)
    [server.register_function(getattr(api_obj, api)) for api in apis]
    LOG.info("Registered api %s" % apis)


def make_response(code=0, message='', data=dict()):
    response = dict()
    response['code'] = code
    response['message'] = '' if message is None else message
    response['data'] = dict() if data is None else data
    return response


def replace_file(file_name, mode=0o644):
    base_dir = os.path.dirname(os.path.abspath(file_name))
    tmp_file = tempfile.NamedTemporaryFile('w+', dir=base_dir, delete=False)
    os.chmod(tmp_file.name, mode)
    os.rename(tmp_file.name, file_name)

# Copyright 2015 UnitedStack, Inc.
# All Rights Reserved.
#
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
#    not use this file except in compliance with the License. You may obtain
#    a copy of the License at
#
#         http://www.apache.org/licenses/LICENSE-2.0
#
#    Unless required by applicable law or agreed to in writing, software
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
#    License for the specific language governing permissions and limitations
#    under the License.

import os
import re
import time
import tempfile
import signal
import shlex
import subprocess
import platform
from threading import Timer
from stetho.agent.common import resource
from stetho.agent.common import log

LOG = log.get_logger()


def execute(cmd, shell=False, root=False, timeout=10):
    try:
        if root:
            cmd.insert(0, 'sudo')
        LOG.info(cmd)
        subproc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE, shell=shell)
        timer = Timer(timeout, lambda proc: proc.kill(), [subproc])
        timer.start()
        subproc.wait()
        stdcode = subproc.returncode
        stdout = subproc.stdout.readlines()
        stderr = subproc.stderr.readlines()
        timer.cancel()

        def list_strip(lines):
            return [line.strip() for line in lines]
        return stdcode, list_strip(stderr) if stdcode else list_strip(stdout)
    except Exception as e:
        LOG.error(e)
        raise


def execute_wait(cmd, shell=False, root=False):
    subproc = subprocess.Popen(cmd, stdout=subprocess.PIPE,
                               stderr=subprocess.PIPE, shell=shell)
    stdout, stderr = subproc.communicate()
    stdcode = subproc.returncode
    return stdcode, stdout, stderr


def create_deamon(cmd, shell=False, root=False):
    """Usage:
        Create servcice process.
    """
    try:
        if root:
            cmd.insert(0, 'sudo')
        LOG.info(cmd)
        subproc = subprocess.Popen(cmd, shell=shell, stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE)
        return subproc.pid
    except Exception as e:
        LOG.error(e)
        raise


def kill_process_by_id(pid):
    pid = int(pid)
    os.kill(pid, signal.SIGILL)
    os.waitpid(pid, 0)


def get_interface(interface):
    """Support Centos standard physical interface,
       such as eth0.
    """
    # Supported CentOS Version
    supported_dists = ['7.0', '6.5']

    def format_centos_7_0(inf):
        pattern = r'<([A-Z]+)'
        state = re.search(pattern, stdout[0]).groups()[0]
        state = 'UP' if not cmp(state, 'UP') else 'DOWN'
        inf.state = state
        stdout.pop(0)
        pattern = r'inet\s(.*)\s\snetmask\s(.*)\s\sbroadcast\s(.*)'
        for line in stdout:
            if line.startswith('inet '):
                tmp = re.search(pattern, line).groups()
                (inf.inet, inf.netmask, inf.broadcast) = tmp
                stdout.remove(line)
                break
        for line in stdout:
            if line.startswith('ether'):
                inf.ether = line[6:23]
                break
        return stdcode, '', inf.make_dict()

    def format_centos_6_5(inf):
        pattern = r'HWaddr\s(.*)'
        inf.ether = re.search(pattern, stdout[0]).groups()[0]
        stdout.pop(0)
        pattern = r'addr:(.*)\s\sBcast:(.*)\s\sMask:(.*)'
        for line in stdout:
            if line.startswith('inet '):
                tmp = re.search(pattern, line).groups()
                (inf.inet, inf.broadcast, inf.netmask) = tmp
                stdout.remove(line)
                break
        inf.state = 'DOWN'
        for line in stdout:
            if 'RUNNING' in line:
                state = line[:2]
                state = 'UP' if not cmp(state, 'UP') else 'DOWN'
                inf.state = state
                break
        return stdcode, '', inf.make_dict()

    linux_dist = platform.linux_distribution()[1][:3]
    if linux_dist in supported_dists:
        try:
            cmd = ['ifconfig', interface]
            stdcode, stdout = execute(cmd)
            inf = resource.Interface(interface)
            if not cmp(linux_dist, '6.5'):
                return format_centos_6_5(inf)
            elif not cmp(linux_dist, '7.0'):
                return format_centos_7_0(inf)
        except Exception as e:
            message = stdout.pop(0)
            return stdcode, message, None

    # Unsupported OS distribute
    message = 'Unsupported OS distribute %s, only support for CentOS %s.'
    message = message % (linux_dist, str(supported_dists))
    return 1, message, None


def register_api(server, api_obj):
    methods = dir(api_obj)
    apis = filter(lambda m: not m.startswith('_'), methods)
    [server.register_function(getattr(api_obj, api)) for api in apis]
    LOG.info("Registered api %s" % apis)


def make_response(code=0, message='', data=dict()):
    response = dict()
    response['code'] = code
    response['message'] = '' if message is None else message
    response['data'] = dict() if data is None else data
    return response


def replace_file(file_name, mode=0o644):
    base_dir = os.path.dirname(os.path.abspath(file_name))
    tmp_file = tempfile.NamedTemporaryFile('w+', dir=base_dir, delete=False)
    os.chmod(tmp_file.name, mode)
    os.rename(tmp_file.name, file_name)

# Copyright 2015 UnitedStack, Inc. # All Rights Reserved. # #    Licensed under the Apache License, Version 2.0 (the "License"); you may #    not use this file except in compliance with the License. You may obtain #    a copy of the License at # #         http://www.apache.org/licenses/LICENSE-2.0 # #    Unless required by applicable law or agreed to in writing, software #    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the #    License for the specific language governing permissions and limitations #    under the License. Usage:         Create servcice process. Support Centos standard physical interface,        such as eth0. # Supported CentOS Version # Unsupported OS distribute