1 import flask
2 import sqlalchemy
3
4 from copr_common.enums import StatusEnum
5 from coprs import db, app
6 from coprs import helpers
7 from coprs import models
8 from coprs import exceptions
9 from coprs.logic import actions_logic
10 from coprs.logic.builds_logic import BuildsLogic
11 from coprs.logic.complex_logic import ComplexLogic, BuildConfigLogic
12 from coprs.logic.packages_logic import PackagesLogic
13 from coprs.logic.coprs_logic import MockChrootsLogic
14 from coprs.exceptions import MalformedArgumentException
15
16 from coprs.views import misc
17 from coprs.views.backend_ns import backend_ns
18 from sqlalchemy.sql import false, true
19
20 import json
21 import logging
22
23 log = logging.getLogger(__name__)
53
88
91 if not task:
92 return None
93
94 build_record = None
95 try:
96 build_record = {
97 "task_id": task.task_id,
98 "build_id": task.build.id,
99 "project_owner": task.build.copr.owner_name,
100 "project_name": task.build.copr_name,
101 "project_dirname": task.build.copr_dirname,
102 "submitter": task.build.submitter[0],
103 "sandbox": task.build.sandbox,
104 "chroot": task.mock_chroot.name,
105 "repos": task.build.repos,
106 "memory_reqs": task.build.memory_reqs,
107 "timeout": task.build.timeout,
108 "enable_net": task.build.enable_net,
109 "git_repo": task.build.package.dist_git_repo,
110 "git_hash": task.git_hash,
111 "source_type": helpers.BuildSourceEnum("scm"),
112 "source_json": json.dumps(
113 {'clone_url': task.build.package.dist_git_clone_url, 'committish': task.git_hash}),
114 "fetch_sources_only": True,
115 "package_name": task.build.package.name,
116 "package_version": task.build.pkg_version,
117 "uses_devel_repo": task.build.copr.devel_mode,
118 }
119 if short:
120 return build_record
121
122 build_config = BuildConfigLogic.generate_build_config(task.build.copr, task.mock_chroot.name)
123 build_record["repos"] = build_config.get("repos")
124 build_record["buildroot_pkgs"] = build_config.get("additional_packages")
125 build_record["use_bootstrap_container"] = build_config.get("use_bootstrap_container")
126 build_record["with_opts"] = build_config.get("with_opts")
127 build_record["without_opts"] = build_config.get("without_opts")
128
129 except Exception as err:
130 app.logger.exception(err)
131 return None
132
133 return build_record
134
137 if not task:
138 return None
139
140 if task.source_type_text == "custom":
141 chroot = task.source_json_dict['chroot']
142 else:
143 chroot = None
144
145 try:
146 build_record = {
147 "task_id": task.task_id,
148 "build_id": task.id,
149 "project_owner": task.copr.owner_name,
150 "project_name": task.copr_name,
151 "project_dirname": task.copr_dirname,
152 "submitter": task.submitter[0],
153 "sandbox": task.sandbox,
154 "source_type": task.source_type,
155 "source_json": task.source_json,
156 "chroot": chroot,
157 }
158
159 except Exception as err:
160 app.logger.exception(err)
161 return None
162
163 return build_record
164
178
186
187
188 @backend_ns.route("/action/<int:action_id>/")
189 -def get_action(action_id):
193
201
202
203 @backend_ns.route("/pending-jobs/")
204 -def pending_jobs():
215
216
217 @backend_ns.route("/get-build-task/<task_id>")
218 -def get_build_task(task_id):
219 try:
220 task = BuildsLogic.get_build_task(task_id)
221 except exceptions.MalformedArgumentException:
222 jsonout = flask.jsonify({'msg': 'Invalid task ID'})
223 jsonout.status_code = 500
224 return jsonout
225 except sqlalchemy.orm.exc.NoResultFound:
226 jsonout = flask.jsonify({'msg': 'Specified task ID not found'})
227 jsonout.status_code = 404
228 return jsonout
229 build_record = get_build_record(task)
230 return flask.jsonify(build_record)
231
232
233 @backend_ns.route("/get-srpm-build-task/<build_id>")
234 -def get_srpm_build_task(build_id):
235 try:
236 task = BuildsLogic.get_srpm_build_task(build_id)
237 except sqlalchemy.orm.exc.NoResultFound:
238 jsonout = flask.jsonify({'msg': 'Specified task ID not found'})
239 jsonout.status_code = 404
240 return jsonout
241 build_record = get_srpm_build_record(task)
242 return flask.jsonify(build_record)
243
248 result = {}
249
250 request_data = flask.request.json
251 for typ, logic_cls in [("actions", actions_logic.ActionsLogic),
252 ("builds", BuildsLogic)]:
253
254 if typ not in request_data:
255 continue
256
257 to_update = {}
258 for obj in request_data[typ]:
259 to_update[obj["id"]] = obj
260
261 existing = {}
262 for obj in logic_cls.get_by_ids(to_update.keys()).all():
263 existing[obj.id] = obj
264
265 non_existing_ids = list(set(to_update.keys()) - set(existing.keys()))
266
267 for i, obj in existing.items():
268 logic_cls.update_state_from_dict(obj, to_update[i])
269
270 db.session.commit()
271 result.update({"updated_{0}_ids".format(typ): list(existing.keys()),
272 "non_existing_{0}_ids".format(typ): non_existing_ids})
273
274 return flask.jsonify(result)
275
296
320
325 response = {}
326 build_id = flask.request.json.get("build_id")
327 task_id = flask.request.json.get("task_id")
328 chroot = flask.request.json.get("chroot")
329
330 try:
331 build = ComplexLogic.get_build_safe(build_id)
332 except ObjectNotFound:
333 response["result"] = "noop"
334 response["msg"] = "Build {} wasn't found".format(build_id)
335 return flask.jsonify(response)
336
337 if build.canceled:
338 response["result"] = "noop"
339 response["msg"] = "build was cancelled, ignoring"
340 return flask.jsonify(response)
341
342 run_statuses = set([StatusEnum("starting"), StatusEnum("running")])
343
344 if task_id == build.task_id:
345 if build.source_status in run_statuses:
346 log.info("rescheduling srpm build {}".format(build.id))
347 BuildsLogic.update_state_from_dict(build, {
348 "task_id": task_id,
349 "status": StatusEnum("pending")
350 })
351 db.session.commit()
352 response["result"] = "done"
353 else:
354 response["result"] = "noop"
355 response["msg"] = "build is not in running states, ignoring"
356 else:
357 build_chroot = build.chroots_dict_by_name.get(chroot)
358 if build_chroot and build_chroot.status in run_statuses:
359 log.info("rescheduling build {} chroot: {}".format(build.id, build_chroot.name))
360 BuildsLogic.update_state_from_dict(build, {
361 "task_id": task_id,
362 "chroot": chroot,
363 "status": StatusEnum("pending")
364 })
365 db.session.commit()
366 response["result"] = "done"
367 else:
368 response["result"] = "noop"
369 response["msg"] = "build chroot is not in running states, ignoring"
370
371 return flask.jsonify(response)
372
376
382