summaryrefslogtreecommitdiffstats
path: root/scripts/trex_daemon_server
blob: 35dad86cbb6d2ae3df9980b508937f5b01c73580 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#!/usr/bin/python

import os, sys
import tempfile
from time import time, sleep
import subprocess, shlex, multiprocessing
from argparse import ArgumentParser
from distutils.dir_util import mkpath
import signal

def fail(msg):
    print(msg)
    sys.exit(-1)

if os.getuid() != 0:
    fail('Please run this program as root/with sudo')

cur_dir = os.path.abspath(os.path.dirname(__file__))

server_path = os.path.join(cur_dir, 'automation', 'trex_control_plane', 'server')
if server_path not in sys.path:
    sys.path.append(server_path)

ext_libs_path = os.path.join(cur_dir, 'external_libs')
if ext_libs_path not in sys.path:
    sys.path.append(ext_libs_path)

if 'start-live' not in sys.argv:
    import CCustomLogger
    CCustomLogger.setup_daemon_logger('TRexServer', '/var/log/trex/trex_daemon_server.log')

import trex_server
import netstat

try:
    from termstyle import termstyle
except ImportError:
    import termstyle


def get_daemon_pid():
    pid = None
    for conn in netstat.netstat():
        if conn[2] == '0.0.0.0' and int(conn[3]) == args.daemon_port and conn[6] == 'LISTEN':
            pid = conn[7]
            if pid is None:
                raise Exception('Found the connection, but could not determine pid: %s' % conn)
            break
    return pid


# faster variant of get_daemon_pid
def is_running():
    for conn in netstat.netstat(with_pid = False):
        if conn[2] == '0.0.0.0' and int(conn[3]) == args.daemon_port and conn[6] == 'LISTEN':
            return True
    return False


def show_daemon_status():
    if is_running():
        print(termstyle.green('TRex server daemon is running'))
    else:
        print(termstyle.red('TRex server daemon is NOT running'))


def start_daemon():
    if is_running():
        print(termstyle.red('TRex server daemon is already running'))
        return
    # Usual daemon will die with current process, detach it with double fork
    # https://www.safaribooksonline.com/library/view/python-cookbook/0596001673/ch06s08.html
    pid = os.fork()
    if pid > 0:
        for i in range(50):
            if is_running():
                print(termstyle.green('TRex server daemon is started'))
                os._exit(0)
            sleep(0.1)
        fail(termstyle.red('TRex server daemon failed to run'))
    os.setsid()
    pid = os.fork()
    if pid > 0:
        os._exit(0)
    trex_server.do_main_program()


def start_live():
    if is_running():
        fail(termstyle.red('TRex server daemon is already running'))
    trex_server.do_main_program()


def restart_daemon():
    if is_running():
        kill_daemon()
        sleep(0.5)
    start_daemon()


def kill_daemon():
    pid = get_daemon_pid()
    if not pid:
        print(termstyle.red('TRex server daemon is NOT running'))
        return True
    pid = int(pid)
    for sig in (signal.SIGTERM, signal.SIGKILL):
        os.kill(pid, sig)
        for i in range(50):
            if not is_running():
                print(termstyle.green('TRex server daemon is killed'))
                return True
            sleep(0.1)
    fail('Failed to kill trex_daemon, even with -9. Please review manually.\n' \
         'Return code: %s\nStdout: %s\nStderr: %s' % return_code, stdout, stderr) # should not happen

### Main ###

actions_help = '''Specify action command to be applied on server.
    (*) start      : start the application in as a daemon process.
    (*) show       : prompt an updated status of daemon process (running/ not running).
    (*) stop       : exit the daemon process.
    (*) restart    : stop, then start again the application as daemon process
    (*) start-live : start the application in live mode (no daemon process).
    '''
action_funcs = {'start': start_daemon,
                'show': show_daemon_status,
                'stop': kill_daemon,
                'restart': restart_daemon,
                'start-live': start_live,
                }
trex_server.trex_parser.add_argument('action', choices=action_funcs.keys(),
                        action='store', help=actions_help)
trex_server.trex_parser.usage = None
args = trex_server.trex_parser.parse_args()

daemon_dir = os.path.dirname(os.path.realpath(__file__))
mkpath('/var/log/trex')
mkpath('/var/run/trex')

action_funcs[args.action]()