]>
Commit | Line | Data |
---|---|---|
9137135a | 1 | #!/usr/bin/python |
a90bd9b0 | 2 | # encoding: utf-8 |
9137135a MT |
3 | |
4 | import logging | |
51db04b0 | 5 | import multiprocessing |
9137135a MT |
6 | import os.path |
7 | import tornado.httpserver | |
8 | import tornado.locale | |
9 | import tornado.options | |
10 | import tornado.web | |
11 | ||
57859ebc | 12 | from .. import Backend |
5b466834 | 13 | from ..constants import * |
4b9167ef | 14 | from ..decorators import * |
57859ebc | 15 | |
2c909128 | 16 | from .handlers import * |
35c46db4 | 17 | |
16f90605 | 18 | from . import handlers_api |
5b466834 MT |
19 | from . import mirrors |
20 | from . import ui_modules | |
16f90605 | 21 | |
9137135a | 22 | # Enable logging |
97144eb5 | 23 | tornado.options.define("debug", default=False, help="Run in debug mode", type=bool) |
9137135a MT |
24 | tornado.options.parse_command_line() |
25 | ||
26 | class Application(tornado.web.Application): | |
754243af | 27 | def __init__(self, **_settings): |
9137135a | 28 | settings = dict( |
97144eb5 | 29 | debug = tornado.options.options.debug, |
2b229cb1 | 30 | gzip = True, |
9137135a | 31 | login_url = "/login", |
027a662e MT |
32 | template_path = TEMPLATESDIR, |
33 | static_path = STATICDIR, | |
9137135a | 34 | ui_modules = { |
5b466834 MT |
35 | "Text" : ui_modules.TextModule, |
36 | "Modal" : ui_modules.ModalModule, | |
f6e6ff79 | 37 | |
5b466834 | 38 | "Footer" : ui_modules.FooterModule, |
f6e6ff79 MT |
39 | |
40 | # Logging | |
5b466834 MT |
41 | "Log" : ui_modules.LogModule, |
42 | "LogEntry" : ui_modules.LogEntryModule, | |
43 | "LogEntryComment" : ui_modules.LogEntryCommentModule, | |
f6e6ff79 | 44 | |
5b466834 MT |
45 | "BuildHeadline" : ui_modules.BuildHeadlineModule, |
46 | "BuildStateWarnings" : ui_modules.BuildStateWarningsModule, | |
f6e6ff79 | 47 | |
5b466834 MT |
48 | "BugsTable" : ui_modules.BugsTableModule, |
49 | "BuildLog" : ui_modules.BuildLogModule, | |
50 | "BuildOffset" : ui_modules.BuildOffsetModule, | |
51 | "BuildTable" : ui_modules.BuildTableModule, | |
4b1e87c4 MT |
52 | |
53 | # Changelog | |
5b466834 MT |
54 | "Changelog" : ui_modules.ChangelogModule, |
55 | "ChangelogEntry" : ui_modules.ChangelogEntryModule, | |
4b1e87c4 | 56 | |
6e63ed49 | 57 | # Jobs |
5b466834 MT |
58 | "JobsList" : ui_modules.JobsListModule, |
59 | "JobsStatus" : ui_modules.JobsStatusModule, | |
6e63ed49 | 60 | |
5669a87f | 61 | # Packages |
5b466834 MT |
62 | "PackagesDependencyTable" : ui_modules.PackagesDependencyTableModule, |
63 | ||
64 | "CommitMessage" : ui_modules.CommitMessageModule, | |
65 | "CommitsTable" : ui_modules.CommitsTableModule, | |
66 | "JobsBoxes" : ui_modules.JobsBoxesModule, | |
67 | "JobState" : ui_modules.JobStateModule, | |
68 | "JobsTable" : ui_modules.JobsTableModule, | |
69 | "CommentsTable" : ui_modules.CommentsTableModule, | |
70 | "FilesTable" : ui_modules.FilesTableModule, | |
71 | "LogTable" : ui_modules.LogTableModule, | |
72 | "LogFilesTable" : ui_modules.LogFilesTableModule, | |
73 | "Maintainer" : ui_modules.MaintainerModule, | |
74 | "PackagesTable" : ui_modules.PackagesTableModule, | |
75 | "PackageTable2" : ui_modules.PackageTable2Module, | |
76 | "PackageHeader" : ui_modules.PackageHeaderModule, | |
77 | "PackageFilesTable" : ui_modules.PackageFilesTableModule, | |
78 | "RepositoryTable" : ui_modules.RepositoryTableModule, | |
79 | "RepoActionsTable" : ui_modules.RepoActionsTableModule, | |
80 | "SourceTable" : ui_modules.SourceTableModule, | |
81 | "UpdatesTable" : ui_modules.UpdatesTableModule, | |
82 | "UsersTable" : ui_modules.UsersTableModule, | |
83 | "WatchersSidebarTable" : ui_modules.WatchersSidebarTableModule, | |
84 | ||
8b713cc7 MT |
85 | "HeadingDate" : ui_modules.HeadingDateModule, |
86 | ||
5b466834 MT |
87 | "SelectLocale" : ui_modules.SelectLocaleModule, |
88 | "SelectTimezone" : ui_modules.SelectTimezoneModule, | |
9137135a | 89 | }, |
bc293d03 MT |
90 | ui_methods = { |
91 | "format_time" : self.format_time, | |
92 | }, | |
9137135a MT |
93 | xsrf_cookies = True, |
94 | ) | |
754243af | 95 | settings.update(_settings) |
9137135a MT |
96 | |
97 | # Load translations. | |
2b5a3b4d | 98 | tornado.locale.load_gettext_translations(LOCALEDIR, PACKAGE_NAME) |
9137135a | 99 | |
754243af | 100 | tornado.web.Application.__init__(self, [ |
9137135a MT |
101 | # Entry site that lead the user to index |
102 | (r"/", IndexHandler), | |
103 | ||
104 | # Handle all the users logins/logouts/registers and stuff. | |
105 | (r"/login", LoginHandler), | |
106 | (r"/logout", LogoutHandler), | |
107 | (r"/register", RegisterHandler), | |
f6e6ff79 MT |
108 | (r"/password-recovery", PasswordRecoveryHandler), |
109 | ||
110 | # User profiles | |
9137135a | 111 | (r"/users", UsersHandler), |
f6e6ff79 MT |
112 | (r"/user/impersonate", UserImpersonateHandler), |
113 | (r"/user/(\w+)/passwd", UserPasswdHandler), | |
114 | (r"/user/(\w+)/delete", UserDeleteHandler), | |
115 | (r"/user/(\w+)/edit", UserEditHandler), | |
116 | (r"/user/(\w+)/activate", ActivationHandler), | |
9137135a | 117 | (r"/user/(\w+)", UserHandler), |
9137135a | 118 | (r"/profile", UserHandler), |
f6e6ff79 | 119 | (r"/profile/builds", UsersBuildsHandler), |
9137135a MT |
120 | |
121 | # Packages | |
122 | (r"/packages", PackageListHandler), | |
f6e6ff79 | 123 | (r"/package/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})", PackageDetailHandler), |
01197c1d | 124 | (r"/package/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})/download(.*)", PackageFileDownloadHandler), |
de4e09a5 | 125 | (r"/package/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})/view(.*)", PackageFileViewHandler), |
d22eae24 | 126 | (r"/package/([\w\-\+]+)", PackageNameHandler), |
a15d6139 | 127 | (r"/package/([\w\-\+]+)/builds/scratch", PackageScratchBuildsHandler), |
bc293d03 | 128 | (r"/package/([\w\-\+]+)/builds/times", PackageBuildsTimesHandler), |
d22eae24 MT |
129 | (r"/package/([\w\-\+]+)/changelog", PackageChangelogHandler), |
130 | (r"/package/([\w\-\+]+)/properties", PackagePropertiesHandler), | |
9137135a MT |
131 | |
132 | # Files | |
133 | (r"/file/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})", FileDetailHandler), | |
134 | ||
135 | # Builds | |
f6e6ff79 | 136 | (r"/builds", BuildsHandler), |
9137135a | 137 | (r"/builds/filter", BuildFilterHandler), |
f6e6ff79 | 138 | (r"/builds/queue", BuildQueueHandler), |
62c7e7cd MT |
139 | (r"/builds/comments", BuildsCommentsHandler), |
140 | (r"/builds/comments/(\w+)", BuildsCommentsHandler), | |
9137135a | 141 | (r"/build/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})", BuildDetailHandler), |
f6e6ff79 MT |
142 | (r"/build/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})/bugs", BuildBugsHandler), |
143 | (r"/build/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})/manage", BuildManageHandler), | |
144 | (r"/build/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})/comment", BuildDetailCommentHandler), | |
145 | (r"/build/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})/priority", BuildPriorityHandler), | |
146 | (r"/build/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})/state", BuildStateHandler), | |
147 | (r"/build/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})/watch", BuildWatchersAddHandler), | |
148 | (r"/build/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})/watchers", BuildWatchersHandler), | |
149 | (r"/build/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})/delete", BuildDeleteHandler), | |
150 | ||
151 | # Jobs | |
9177f86a MT |
152 | (r"/jobs", JobsIndexHandler), |
153 | (r"/jobs/filter", JobsFilterHandler), | |
f6e6ff79 MT |
154 | (r"/job/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})", JobDetailHandler), |
155 | (r"/job/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})/abort", JobAbortHandler), | |
156 | (r"/job/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})/buildroot", JobBuildrootHandler), | |
157 | (r"/job/([\w]{8}-[\w]{4}-[\w]{4}-[\w]{4}-[\w]{12})/schedule", JobScheduleHandler), | |
9137135a MT |
158 | |
159 | # Builders | |
160 | (r"/builders", BuilderListHandler), | |
161 | (r"/builder/new", BuilderNewHandler), | |
f6e6ff79 MT |
162 | (r"/builder/([A-Za-z0-9\-\.]+)/enable", BuilderEnableHander), |
163 | (r"/builder/([A-Za-z0-9\-\.]+)/disable", BuilderDisableHander), | |
164 | (r"/builder/([A-Za-z0-9\-\.]+)/delete", BuilderDeleteHandler), | |
165 | (r"/builder/([A-Za-z0-9\-\.]+)/edit", BuilderEditHandler), | |
166 | (r"/builder/([A-Za-z0-9\-\.]+)/renew", BuilderRenewPassphraseHandler), | |
9137135a MT |
167 | (r"/builder/([A-Za-z0-9\-\.]+)", BuilderDetailHandler), |
168 | ||
9137135a | 169 | # Distributions |
f6e6ff79 MT |
170 | (r"/distros", DistributionListHandler), |
171 | (r"/distro/([A-Za-z0-9\-\.]+)", DistributionDetailHandler), | |
172 | ||
173 | # XXX THOSE URLS ARE DEPRECATED | |
9137135a MT |
174 | (r"/distribution/delete/([A-Za-z0-9\-\.]+)", DistributionDetailHandler), |
175 | (r"/distribution/edit/([A-Za-z0-9\-\.]+)", DistributionEditHandler), | |
f6e6ff79 MT |
176 | |
177 | (r"/distro/([A-Za-z0-9\-\.]+)/repo/([A-Za-z0-9\-]+)", | |
178 | RepositoryDetailHandler), | |
179 | (r"/distro/([A-Za-z0-9\-\.]+)/repo/([A-Za-z0-9\-]+)\.repo", | |
180 | RepositoryConfHandler), | |
181 | (r"/distro/([A-Za-z0-9\-\.]+)/repo/([A-Za-z0-9\-]+)/mirrorlist", | |
182 | RepositoryMirrorlistHandler), | |
183 | (r"/distro/([A-Za-z0-9\-\.]+)/repo/([A-Za-z0-9\-]+)/edit", | |
184 | RepositoryEditHandler), | |
185 | ||
186 | (r"/distro/([A-Za-z0-9\-\.]+)/source/([A-Za-z0-9\-\.]+)", | |
187 | DistroSourceDetailHandler), | |
188 | (r"/distro/([A-Za-z0-9\-\.]+)/source/([A-Za-z0-9\-\.]+)/commits", | |
189 | DistroSourceCommitsHandler), | |
190 | (r"/distro/([A-Za-z0-9\-\.]+)/source/([A-Za-z0-9\-\.]+)/([\w]{40})", | |
191 | DistroSourceCommitDetailHandler), | |
192 | (r"/distro/([A-Za-z0-9\-\.]+)/source/([A-Za-z0-9\-\.]+)/([\w]{40})/reset", | |
193 | DistroSourceCommitResetHandler), | |
194 | ||
195 | (r"/distro/([A-Za-z0-9\-\.]+)/update/create", | |
196 | DistroUpdateCreateHandler), | |
197 | (r"/distro/([A-Za-z0-9\-\.]+)/update/(\d+)/(\d+)", | |
198 | DistroUpdateDetailHandler), | |
199 | ||
200 | # Updates | |
201 | (r"/updates", UpdatesHandler), | |
202 | ||
203 | # Mirrors | |
16f90605 MT |
204 | (r"/mirrors", mirrors.MirrorListHandler), |
205 | (r"/mirror/new", mirrors.MirrorNewHandler), | |
206 | (r"/mirror/([\w\-\.]+)/delete", mirrors.MirrorDeleteHandler), | |
207 | (r"/mirror/([\w\-\.]+)/edit", mirrors.MirrorEditHandler), | |
208 | (r"/mirror/([\w\-\.]+)", mirrors.MirrorDetailHandler), | |
f6e6ff79 MT |
209 | |
210 | # Key management | |
211 | (r"/keys", KeysListHandler), | |
212 | (r"/key/import", KeysImportHandler), | |
213 | (r"/key/([A-Z0-9]+)", KeysDownloadHandler), | |
214 | (r"/key/([A-Z0-9]+)/delete", KeysDeleteHandler), | |
215 | ||
216 | # Statistics | |
217 | (r"/statistics", StatisticsMainHandler), | |
9137135a MT |
218 | |
219 | # Documents | |
220 | (r"/documents", DocsIndexHandler), | |
221 | (r"/documents/builds", DocsBuildsHandler), | |
222 | (r"/documents/users", DocsUsersHandler), | |
f6e6ff79 | 223 | (r"/documents/what-is-the-pakfire-build-service", DocsWhatsthisHandler), |
9137135a MT |
224 | |
225 | # Search | |
226 | (r"/search", SearchHandler), | |
227 | ||
f6e6ff79 MT |
228 | # Uploads |
229 | (r"/uploads", UploadsHandler), | |
9137135a MT |
230 | |
231 | # Log | |
232 | (r"/log", LogHandler), | |
9137135a | 233 | |
20d7f5eb MT |
234 | # Sessions |
235 | (r"/sessions", SessionsHandler), | |
236 | ||
35c46db4 MT |
237 | # API handlers |
238 | (r"/api/packages/autocomplete", handlers_api.ApiPackagesAutocomplete), | |
754243af | 239 | ], **settings) |
9137135a MT |
240 | |
241 | logging.info("Successfully initialied application") | |
242 | ||
4b9167ef MT |
243 | @lazy_property |
244 | def backend(self): | |
245 | """ | |
246 | Backend connection | |
247 | """ | |
248 | return Backend() | |
f6e6ff79 | 249 | |
9137135a MT |
250 | def __del__(self): |
251 | logging.info("Shutting down application") | |
252 | ||
253 | @property | |
254 | def ioloop(self): | |
255 | return tornado.ioloop.IOLoop.instance() | |
256 | ||
257 | def shutdown(self, *args): | |
258 | logging.debug("Caught shutdown signal") | |
259 | self.ioloop.stop() | |
260 | ||
51db04b0 | 261 | def run(self, port=7001): |
9137135a MT |
262 | logging.debug("Going to background") |
263 | ||
9137135a MT |
264 | http_server = tornado.httpserver.HTTPServer(self, xheaders=True) |
265 | ||
266 | # If we are not running in debug mode, we can actually run multiple | |
267 | # frontends to get best performance out of our service. | |
51db04b0 | 268 | if self.settings.get("debug", False): |
9137135a | 269 | http_server.listen(port) |
51db04b0 MT |
270 | else: |
271 | cpu_count = multiprocessing.cpu_count() | |
272 | ||
273 | http_server.bind(port) | |
274 | http_server.start(num_processes=cpu_count) | |
9137135a | 275 | |
f6e6ff79 MT |
276 | # All requests should be done after 60 seconds or they will be killed. |
277 | self.ioloop.set_blocking_log_threshold(60) | |
278 | ||
9137135a MT |
279 | self.ioloop.start() |
280 | ||
281 | def reload(self): | |
282 | logging.debug("Caught reload signal") | |
bc293d03 MT |
283 | |
284 | ## UI methods | |
285 | ||
7514d7dc | 286 | def format_time(self, handler, s, shorter=False): |
bc293d03 MT |
287 | _ = handler.locale.translate |
288 | ||
289 | hrs, s = divmod(s, 3600) | |
290 | min, s = divmod(s, 60) | |
291 | ||
292 | if s >= 30: | |
293 | min += 1 | |
294 | ||
7514d7dc MT |
295 | if shorter and not hrs: |
296 | return _("%(min)d min") % { "min" : min } | |
297 | ||
bc293d03 | 298 | return _("%(hrs)d:%(min)02d hrs") % {"hrs" : hrs, "min" : min} |
a90bd9b0 MT |
299 | |
300 | def format_time_short(self, handler, s): | |
301 | _ = handler.locale.translate | |
302 | ||
303 | hrs = s / 3600 | |
304 | if hrs >= 1: | |
305 | return _("%dh") % hrs | |
306 | ||
307 | min = s / 60 | |
308 | if min >= 1: | |
309 | return _("%dm") % min | |
310 | ||
311 | return _("%ds") % s |