This repository has been archived by the owner on May 12, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 233
/
http_observer.py
138 lines (120 loc) · 4.63 KB
/
http_observer.py
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
#
# 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.
#
"""HTTP interface to the Thermos TaskObserver
This modules provides an HTTP server which exposes information about Thermos tasks running on a
system. To do this, it relies heavily on the Thermos TaskObserver.
"""
import socket
from twitter.common import log
from twitter.common.http import HttpServer
from .file_browser import TaskObserverFileBrowser
from .json import TaskObserverJSONBindings
from .static_assets import StaticAssets
from .templating import HttpTemplate
class BottleObserver(HttpServer, StaticAssets, TaskObserverFileBrowser, TaskObserverJSONBindings):
"""
A bottle wrapper around a Thermos TaskObserver.
"""
def __init__(self, observer):
self._observer = observer
StaticAssets.__init__(self)
TaskObserverFileBrowser.__init__(self)
TaskObserverJSONBindings.__init__(self)
HttpServer.__init__(self)
@HttpServer.route("/")
@HttpServer.view(HttpTemplate.load('index'))
def handle_index(self):
return dict(hostname=socket.gethostname())
@HttpServer.route("/main")
@HttpServer.route("/main/:type")
@HttpServer.route("/main/:type/:offset")
@HttpServer.route("/main/:type/:offset/:num")
@HttpServer.mako_view(HttpTemplate.load('main'))
def handle_main(self, type=None, offset=None, num=None):
if type not in (None, 'all', 'finished', 'active'):
HttpServer.abort(404, 'Invalid task type: %s' % type)
if offset is not None:
try:
offset = int(offset)
except ValueError:
HttpServer.abort(404, 'Invalid offset: %s' % offset)
if num is not None:
try:
num = int(num)
except ValueError:
HttpServer.abort(404, 'Invalid count: %s' % num)
return self._observer.main(type, offset, num)
@HttpServer.route("/task/:task_id")
@HttpServer.mako_view(HttpTemplate.load('task'))
def handle_task(self, task_id):
task = self.get_task(task_id)
processes = self._observer.processes([task_id])
if not processes.get(task_id, None):
HttpServer.abort(404, 'Unknown task_id: %s' % task_id)
processes = processes[task_id]
state = self._observer.state(task_id)
return dict(
task_id=task_id,
task=task,
statuses=self._observer.task_statuses(task_id),
user=task['user'],
ports=task['ports'],
processes=processes,
chroot=state.get('sandbox', ''),
launch_time=state.get('launch_time', 0),
hostname=state.get('hostname', 'localhost'),
)
def get_task(self, task_id):
task = self._observer._task(task_id)
if not task:
HttpServer.abort(404, "Failed to find task %s. Try again shortly." % task_id)
return task
@HttpServer.route("/rawtask/:task_id")
@HttpServer.mako_view(HttpTemplate.load('rawtask'))
def handle_rawtask(self, task_id):
task = self.get_task(task_id)
state = self._observer.state(task_id)
return dict(
hostname=state.get('hostname', 'localhost'),
task_id=task_id,
task_struct=task['task_struct']
)
@HttpServer.route("/process/:task_id/:process_id")
@HttpServer.mako_view(HttpTemplate.load('process'))
def handle_process(self, task_id, process_id):
all_processes = {}
current_run = self._observer.process(task_id, process_id)
if not current_run:
HttpServer.abort(404, 'Invalid task/process combination: %s/%s' % (task_id, process_id))
process = self._observer.process_from_name(task_id, process_id)
if process is None:
msg = 'Could not recover process: %s/%s' % (task_id, process_id)
log.error(msg)
HttpServer.abort(404, msg)
current_run_number = current_run['process_run']
all_processes[current_run_number] = current_run
for run in range(current_run_number):
all_processes[run] = self._observer.process(task_id, process_id, run)
template = {
'task_id': task_id,
'process': {
'name': process_id,
'status': all_processes[current_run_number]["state"],
'cmdline': process.cmdline().get()
},
}
template['process'].update(**all_processes[current_run_number].get('used', {}))
template['runs'] = all_processes
log.debug('Rendering template is: %s', template)
return template