]>
git.ipfire.org Git - pbs.git/blob - src/web/builders.py
9 log
= logging
.getLogger("pbs.web.builders")
11 class APIv1ControlHandler(base
.APIMixin
, base
.BackendMixin
, tornado
.websocket
.WebSocketHandler
):
13 async def prepare(self
):
14 # This is here to require authentication before
15 # the websocket connection is being negotiated.
18 self
.builder
= await self
.get_current_user()
21 # The builder has opened a new connection
22 self
.builder
.connected(self
, address
=self
.current_address
)
24 # Update the builder information
25 async with
await self
.db
.transaction():
27 self
.builder
.arch
= self
.get_argument("arch")
29 # Update system information
30 self
.builder
.sys_vendor
= self
.get_argument("sys_vendor", None)
31 self
.builder
.sys_name
= self
.get_argument("sys_name", None)
33 # Update CPU information
34 self
.builder
.cpu_model
= self
.get_argument("cpu_model", None)
35 self
.builder
.cpu_count
= self
.get_argument_int("cpu_count", None)
37 # Update Pakfire & OS information
38 self
.builder
.version
= self
.get_argument("version")
39 self
.builder
.os_name
= self
.get_argument("os_name", None)
41 # Manually perform a database commit because this won't happen
42 # until the builder disconnects again.
43 await self
.db
.commit()
45 # After the builder has connected, try to dispatch some jobs
46 await self
.backend
.jobs
.queue
.dispatch()
48 def on_ping(self
, data
):
49 log
.debug("%s has pinged us" % self
.builder
)
52 # Drop the connection to the builder
53 self
.builder
.disconnected()
55 async def on_message(self
, message
):
57 message
= self
._decode
_json
_message
(message
)
59 # Fetch the message type & data
60 type = message
.get("type")
61 data
= message
.get("data")
63 # Fast path for log messages
65 return self
.backend
.logstreams
.log(message
)
67 # Fetch the builder again, because this is being executed as a separate task
68 # and therefore we cannot use the object from the previous session.
69 builder
= await self
.backend
.builders
.get_by_name(self
.builder
.name
)
73 async with
await self
.db
.transaction():
74 await builder
.log_stats(**data
)
76 # Log an error and ignore any other messages
78 log
.error("Received message of type '%s' which we cannot handle here" % type)
81 class StatsHandler(base
.BaseHandler
, tornado
.websocket
.WebSocketHandler
):
82 # No authentication required
83 async def open(self
, name
):
84 builder
= await self
.backend
.builders
.get_by_name(name
)
86 raise tornado
.web
.HTTPError(404, "Could not find builder %s" % name
)
88 # Register to receive updates
89 self
.backend
.builders
.stats
.join(builder
=builder
, connection
=self
)
91 # Initially send the stats that we currently have
92 stats
= await builder
.get_stats()
94 await self
.submit_stats(stats
)
97 self
.backend
.builders
.stats
.leave(self
)
99 async def submit_stats(self
, stats
):
100 await self
.write_message({
101 "cpu_usage" : stats
.cpu_usage
,
102 "mem_usage" : stats
.mem_usage
,
103 "swap_usage" : stats
.swap_usage
,
107 class IndexHandler(base
.BaseHandler
):
109 await self
.render("builders/index.html", builders
=self
.backend
.builders
)
112 class ShowHandler(base
.BaseHandler
):
113 async def get(self
, hostname
):
114 builder
= await self
.backend
.builders
.get_by_name(hostname
)
116 raise tornado
.web
.HTTPError(404, "Could not find builder %s" % hostname
)
120 "is_running" : await builder
.is_running(),
121 "is_shutting_down" : await builder
.is_shutting_down(),
122 "is_shut_down" : await builder
.is_shut_down(),
125 await self
.render("builders/show.html", builder
=builder
, **args
)
128 class CreateHandler(base
.AdminHandler
):
130 await self
.render("builders/create.html")
132 async def post(self
):
133 # Create a new builder
134 async with
await self
.db
.transaction():
135 builder
= await self
.backend
.builders
.create(
136 name
= self
.get_argument("name"),
137 created_by
= self
.current_user
,
140 self
.redirect("/builders/%s/edit" % builder
.name
)
143 class EditHandler(base
.BaseHandler
):
145 async def get(self
, name
):
146 builder
= await self
.backend
.builders
.get_by_name(name
)
148 raise tornado
.web
.HTTPError(404, "Builder not found")
151 if not builder
.has_perm(self
.current_user
):
152 raise tornado
.web
.HTTPError(403)
154 await self
.render("builders/edit.html", builder
=builder
)
157 async def post(self
, name
):
158 builder
= await self
.backend
.builders
.get_by_name(name
)
160 raise tornado
.web
.HTTPError(404, "Builder not found: %s" % name
)
163 if not builder
.has_perm(self
.current_user
):
164 raise tornado
.web
.HTTPError(403)
166 async with
await self
.db
.transaction():
167 builder
.enabled
= self
.get_argument_bool("enabled")
168 builder
.maintenance
= self
.get_argument_bool("maintenance")
169 builder
.max_jobs
= self
.get_argument_int("max_jobs")
171 # Try to dispatch more jobs
172 await self
.backend
.jobs
.queue
.dispatch()
174 self
.redirect("/builders/%s" % builder
.name
)
177 class DeleteHandler(base
.BaseHandler
):
179 async def get(self
, name
):
180 builder
= await self
.backend
.builders
.get_by_name(name
)
182 raise tornado
.web
.HTTPError(404, "Builder not found: %s" % name
)
185 if not builder
.has_perm(self
.current_user
):
186 raise tornado
.web
.HTTPError(403)
188 await self
.render("builders/delete.html", builder
=builder
)
191 async def post(self
, name
):
192 builder
= await self
.backend
.builders
.get_by_name(name
)
194 raise tornado
.web
.HTTPError(404, "Builder not found: %s" % hostname
)
197 if not builder
.has_perm(self
.current_user
):
198 raise tornado
.web
.HTTPError(403)
201 async with
await self
.db
.transaction():
202 await builder
.delete(deleted_by
=self
.current_user
)
204 self
.redirect("/builders")
207 class StartHandler(base
.BaseHandler
):
209 async def get(self
, name
):
210 builder
= await self
.backend
.builders
.get_by_name(name
)
212 raise tornado
.web
.HTTPError(404, "Builder not found: %s" % name
)
215 if not builder
.has_perm(self
.current_user
):
216 raise tornado
.web
.HTTPError(403)
218 # Builders must be in maintenance mode
219 if not builder
.maintenance
:
220 raise tornado
.web
.HTTPError(400, "%s is not in maintenance mode" % builder
)
222 await self
.render("builders/start.html", builder
=builder
)
225 async def post(self
, name
):
226 builder
= await self
.backend
.builders
.get_by_name(name
)
228 raise tornado
.web
.HTTPError(404, "Builder not found: %s" % name
)
231 if not builder
.has_perm(self
.current_user
):
232 raise tornado
.web
.HTTPError(403)
234 # Builders must be in maintenance mode
235 if not builder
.maintenance
:
236 raise tornado
.web
.HTTPError(400, "%s is not in maintenance mode" % builder
)
240 await builder
.start(wait
=False)
242 # XXX what do we do when this fails?
246 self
.redirect("/builders/%s" % builder
.name
)
249 class StopHandler(base
.BaseHandler
):
251 async def get(self
, name
):
252 builder
= await self
.backend
.builders
.get_by_name(name
)
254 raise tornado
.web
.HTTPError(404, "Builder not found: %s" % name
)
257 if not builder
.has_perm(self
.current_user
):
258 raise tornado
.web
.HTTPError(403)
260 # Builders must be in maintenance mode
261 if not builder
.maintenance
:
262 raise tornado
.web
.HTTPError(400, "%s is not in maintenance mode" % builder
)
264 await self
.render("builders/stop.html", builder
=builder
)
267 async def post(self
, name
):
268 builder
= await self
.backend
.builders
.get_by_name(name
)
270 raise tornado
.web
.HTTPError(404, "Builder not found: %s" % name
)
273 if not builder
.has_perm(self
.current_user
):
274 raise tornado
.web
.HTTPError(403)
276 # Builders must be in maintenance mode
277 if not builder
.maintenance
:
278 raise tornado
.web
.HTTPError(400, "%s is not in maintenance mode" % builder
)
282 await builder
.stop(wait
=False)
284 # XXX what do we do when this fails?
288 self
.redirect("/builders/%s" % builder
.name
)