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
144
145
146
|
#!/usr/bin/python
import outer_packages
import lockfile
from daemon import runner,daemon
from daemon.runner import *
import os, sys
from argparse import ArgumentParser
from trex_server import trex_parser
try:
from termstyle import termstyle
except ImportError:
import termstyle
def daemonize_parser(parser_obj, action_funcs, help_menu):
"""Update the regular process parser to deal with daemon process options"""
parser_obj.description += " (as a daemon process)"
parser_obj.usage = None
parser_obj.add_argument("action", choices=action_funcs,
action="store", help=help_menu)
class ExtendedDaemonRunner(runner.DaemonRunner):
""" Controller for a callable running in a separate background process.
The first command-line argument is the action to take:
* 'start': Become a daemon and call `app.run()`.
* 'stop': Exit the daemon process specified in the PID file.
* 'restart': Stop, then start.
"""
help_menu = """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).
"""
def __init__(self, app, parser_obj):
""" Set up the parameters of a new runner.
THIS METHOD INTENTIONALLY DO NOT INVOKE SUPER __init__() METHOD
:param app: The application instance; see below.
:return: ``None``.
The `app` argument must have the following attributes:
* `stdin_path`, `stdout_path`, `stderr_path`: Filesystem paths
to open and replace the existing `sys.stdin`, `sys.stdout`,
`sys.stderr`.
* `pidfile_path`: Absolute filesystem path to a file that will
be used as the PID file for the daemon. If ``None``, no PID
file will be used.
* `pidfile_timeout`: Used as the default acquisition timeout
value supplied to the runner's PID lock file.
* `run`: Callable that will be invoked when the daemon is
started.
"""
super(runner.DaemonRunner, self).__init__()
# update action_funcs to support more operations
self.update_action_funcs()
daemonize_parser(parser_obj, self.action_funcs, ExtendedDaemonRunner.help_menu)
args = parser_obj.parse_args()
self.action = unicode(args.action)
self.app = app
self.daemon_context = daemon.DaemonContext()
self.daemon_context.stdin = open(app.stdin_path, 'rt')
try:
self.daemon_context.stdout = open(app.stdout_path, 'w+t')
except IOError as err:
# catch 'tty' error when launching server from remote location
app.stdout_path = "/dev/null"
self.daemon_context.stdout = open(app.stdout_path, 'w+t')
self.daemon_context.stderr = open(app.stderr_path,
'a+t', buffering=0)
self.pidfile = None
if app.pidfile_path is not None:
self.pidfile = make_pidlockfile(app.pidfile_path, app.pidfile_timeout)
self.daemon_context.pidfile = self.pidfile
# mask out all arguments that aren't relevant to main app script
def update_action_funcs(self):
self.action_funcs.update({u'start-live': self._start_live, u'show': self._show}) # add key (=action), value (=desired func)
@staticmethod
def _start_live(self):
self.app.run()
@staticmethod
def _show(self):
if self.pidfile.is_locked():
print termstyle.red("TRex server daemon is running")
else:
print termstyle.red("TRex server daemon is NOT running")
def do_action(self):
self.__prevent_duplicate_runs()
self.__prompt_init_msg()
try:
super(ExtendedDaemonRunner, self).do_action()
if self.action == 'stop':
self.__verify_termination()
except runner.DaemonRunnerStopFailureError:
if self.action == 'restart':
# error means server wasn't running in the first place- so start it!
self.action = 'start'
self.do_action()
def __prevent_duplicate_runs(self):
if self.action == 'start' and self.pidfile.is_locked():
print termstyle.green("Server daemon is already running")
exit(1)
elif self.action == 'stop' and not self.pidfile.is_locked():
print termstyle.green("Server daemon is not running")
exit(1)
def __prompt_init_msg(self):
if self.action == 'start':
print termstyle.green("Starting daemon server...")
elif self.action == 'stop':
print termstyle.green("Stopping daemon server...")
def __verify_termination(self):
pass
# import time
# while self.pidfile.is_locked():
# time.sleep(2)
# self._stop()
#
if __name__ == "__main__":
pass
|