1 import flask
2 import sqlalchemy
3
4 from copr_common.enums import StatusEnum
5 from coprs import db, app
6 from coprs import models
7 from coprs.logic import actions_logic
8 from coprs.logic.builds_logic import BuildsLogic
9 from coprs.logic.complex_logic import ComplexLogic, BuildConfigLogic
10 from coprs.logic.packages_logic import PackagesLogic
11 from coprs.logic.coprs_logic import MockChrootsLogic, CoprChrootsLogic
12 from coprs.exceptions import MalformedArgumentException, ObjectNotFound
13
14 from coprs.views import misc
15 from coprs.views.backend_ns import backend_ns
16 from sqlalchemy.sql import false, true
17
18 import logging
19
20 log = logging.getLogger(__name__)
50
85
88 if not task:
89 return None
90
91 build_record = None
92 try:
93 build_record = {
94 "task_id": task.task_id,
95 "build_id": task.build.id,
96 "project_owner": task.build.copr.owner_name,
97 "project_name": task.build.copr_name,
98 "project_dirname": task.build.copr_dirname,
99 "submitter": task.build.submitter[0],
100 "sandbox": task.build.sandbox,
101 "chroot": task.mock_chroot.name,
102 "repos": task.build.repos,
103 "memory_reqs": task.build.memory_reqs,
104 "timeout": task.build.timeout,
105 "enable_net": task.build.enable_net,
106 "git_repo": task.build.package.dist_git_clone_url,
107 "git_hash": task.git_hash,
108 "package_name": task.build.package.name,
109 "package_version": task.build.pkg_version,
110 "uses_devel_repo": task.build.copr.devel_mode,
111 }
112
113
114 if task.build.is_background:
115 build_record['background'] = True
116
117 if short:
118 return build_record
119
120 copr_chroot = CoprChrootsLogic.get_by_name_safe(task.build.copr, task.mock_chroot.name)
121 if copr_chroot.module_toggle_array:
122 array = [{'enable': m} for m in copr_chroot.module_toggle_array]
123 build_record["modules"] = {'toggle': array}
124
125 build_config = BuildConfigLogic.generate_build_config(task.build.copr, task.mock_chroot.name)
126 build_record["repos"] = build_config.get("repos")
127 build_record["buildroot_pkgs"] = build_config.get("additional_packages")
128 build_record["with_opts"] = build_config.get("with_opts")
129 build_record["without_opts"] = build_config.get("without_opts")
130
131 bch_bootstrap = BuildConfigLogic.build_bootstrap_setup(
132 build_config, task.build)
133 build_record.update(bch_bootstrap)
134
135 except Exception as err:
136 app.logger.exception(err)
137 return None
138
139 return build_record
140
143 if not task:
144 return None
145
146 if task.source_type_text == "custom":
147 chroot = task.source_json_dict['chroot']
148 else:
149 chroot = None
150
151 try:
152 build_record = {
153 "task_id": task.task_id,
154 "build_id": task.id,
155 "project_owner": task.copr.owner_name,
156 "project_name": task.copr_name,
157 "project_dirname": task.copr_dirname,
158 "submitter": task.submitter[0],
159 "sandbox": task.sandbox,
160 "source_type": task.source_type,
161 "source_json": task.source_json,
162 "chroot": chroot,
163 }
164
165 except Exception as err:
166 app.logger.exception(err)
167 return None
168
169 return build_record
170
184
188 """
189 Return the list of task IDs to be canceled.
190 """
191 task_ids = [x.what for x in models.CancelRequest.query.all()]
192 return flask.jsonify(task_ids)
193
212
224
225
226
227 @backend_ns.route("/action/<int:action_id>/")
228 -def get_action(action_id):
232
240
241
242 @backend_ns.route("/pending-jobs/")
243 -def pending_jobs():
255
256
257 @backend_ns.route("/get-build-task/<task_id>/")
258 @backend_ns.route("/get-build-task/<task_id>")
259 -def get_build_task(task_id):
260 try:
261 task = BuildsLogic.get_build_task(task_id)
262 except MalformedArgumentException:
263 jsonout = flask.jsonify({'msg': 'Invalid task ID'})
264 jsonout.status_code = 500
265 return jsonout
266 except sqlalchemy.orm.exc.NoResultFound:
267 jsonout = flask.jsonify({'msg': 'Specified task ID not found'})
268 jsonout.status_code = 404
269 return jsonout
270 build_record = get_build_record(task)
271 return flask.jsonify(build_record)
272
273
274 @backend_ns.route("/get-srpm-build-task/<build_id>/")
275 @backend_ns.route("/get-srpm-build-task/<build_id>")
276 -def get_srpm_build_task(build_id):
277 try:
278 task = BuildsLogic.get_srpm_build_task(build_id)
279 except sqlalchemy.orm.exc.NoResultFound:
280 jsonout = flask.jsonify({'msg': 'Specified task ID not found'})
281 jsonout.status_code = 404
282 return jsonout
283 build_record = get_srpm_build_record(task)
284 return flask.jsonify(build_record)
285
290 result = {}
291
292 request_data = flask.request.json
293 for typ, logic_cls in [("actions", actions_logic.ActionsLogic),
294 ("builds", BuildsLogic)]:
295
296 if typ not in request_data:
297 continue
298
299 to_update = {}
300 for obj in request_data[typ]:
301 to_update[obj["id"]] = obj
302
303 existing = {}
304 for obj in logic_cls.get_by_ids(to_update.keys()).all():
305 existing[obj.id] = obj
306
307 non_existing_ids = list(set(to_update.keys()) - set(existing.keys()))
308
309 for i, obj in existing.items():
310 logic_cls.update_state_from_dict(obj, to_update[i])
311
312 db.session.commit()
313 result.update({"updated_{0}_ids".format(typ): list(existing.keys()),
314 "non_existing_{0}_ids".format(typ): non_existing_ids})
315
316 return flask.jsonify(result)
317
338
343 response = {}
344 build_id = flask.request.json.get("build_id")
345 task_id = flask.request.json.get("task_id")
346 chroot = flask.request.json.get("chroot")
347
348 try:
349 build = ComplexLogic.get_build_safe(build_id)
350 except ObjectNotFound:
351 response["result"] = "noop"
352 response["msg"] = "Build {} wasn't found".format(build_id)
353 return flask.jsonify(response)
354
355 if build.canceled:
356 response["result"] = "noop"
357 response["msg"] = "build was cancelled, ignoring"
358 return flask.jsonify(response)
359
360 run_statuses = set([StatusEnum("starting"), StatusEnum("running")])
361
362 if task_id == build.task_id:
363 if build.source_status in run_statuses:
364 log.info("rescheduling source build %s", build.id)
365 BuildsLogic.update_state_from_dict(build, {
366 "task_id": task_id,
367 "status": StatusEnum("pending")
368 })
369 db.session.commit()
370 response["result"] = "done"
371 else:
372 response["result"] = "noop"
373 response["msg"] = "build is not in running states, ignoring"
374 else:
375 build_chroot = build.chroots_dict_by_name.get(chroot)
376 if build_chroot and build_chroot.status in run_statuses:
377 log.info("rescheduling build {} chroot: {}".format(build.id, build_chroot.name))
378 BuildsLogic.update_state_from_dict(build, {
379 "task_id": task_id,
380 "chroot": chroot,
381 "status": StatusEnum("pending")
382 })
383 db.session.commit()
384 response["result"] = "done"
385 else:
386 response["result"] = "noop"
387 response["msg"] = "build chroot is not in running states, ignoring"
388
389 return flask.jsonify(response)
390
394
400