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
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 }
118 if short:
119 return build_record
120
121 build_config = helpers.generate_build_config(task.build.copr, task.mock_chroot.name)
122 build_record["repos"] = build_config.get("repos")
123 build_record["buildroot_pkgs"] = build_config.get("additional_packages")
124 build_record["use_bootstrap_container"] = build_config.get("use_bootstrap_container")
125 build_record["with_opts"] = build_config.get("with_opts")
126 build_record["without_opts"] = build_config.get("without_opts")
127
128 except Exception as err:
129 app.logger.exception(err)
130 return None
131
132 return build_record
133
136 if not task:
137 return None
138
139 if task.source_type_text == "custom":
140 chroot = task.source_json_dict['chroot']
141 else:
142 chroot = None
143
144 try:
145 build_record = {
146 "task_id": task.task_id,
147 "build_id": task.id,
148 "project_owner": task.copr.owner_name,
149 "project_name": task.copr_name,
150 "project_dirname": task.copr_dirname,
151 "submitter": task.submitter[0],
152 "sandbox": task.sandbox,
153 "source_type": task.source_type,
154 "source_json": task.source_json,
155 "chroot": chroot,
156 }
157
158 except Exception as err:
159 app.logger.exception(err)
160 return None
161
162 return build_record
163
177
185
186
187 @backend_ns.route("/action/<int:action_id>/")
188 -def get_action(action_id):
192
200
201
202 @backend_ns.route("/pending-jobs/")
203 -def pending_jobs():
214
215
216 @backend_ns.route("/get-build-task/<task_id>")
217 -def get_build_task(task_id):
218 try:
219 task = BuildsLogic.get_build_task(task_id)
220 except exceptions.MalformedArgumentException:
221 jsonout = flask.jsonify({'msg': 'Invalid task ID'})
222 jsonout.status_code = 500
223 return jsonout
224 except sqlalchemy.orm.exc.NoResultFound:
225 jsonout = flask.jsonify({'msg': 'Specified task ID not found'})
226 jsonout.status_code = 404
227 return jsonout
228 build_record = get_build_record(task)
229 return flask.jsonify(build_record)
230
231
232 @backend_ns.route("/get-srpm-build-task/<build_id>")
233 -def get_srpm_build_task(build_id):
234 try:
235 task = BuildsLogic.get_srpm_build_task(build_id)
236 except sqlalchemy.orm.exc.NoResultFound:
237 jsonout = flask.jsonify({'msg': 'Specified task ID not found'})
238 jsonout.status_code = 404
239 return jsonout
240 build_record = get_srpm_build_record(task)
241 return flask.jsonify(build_record)
242
247 result = {}
248
249 request_data = flask.request.json
250 for typ, logic_cls in [("actions", actions_logic.ActionsLogic),
251 ("builds", BuildsLogic)]:
252
253 if typ not in request_data:
254 continue
255
256 to_update = {}
257 for obj in request_data[typ]:
258 to_update[obj["id"]] = obj
259
260 existing = {}
261 for obj in logic_cls.get_by_ids(to_update.keys()).all():
262 existing[obj.id] = obj
263
264 non_existing_ids = list(set(to_update.keys()) - set(existing.keys()))
265
266 for i, obj in existing.items():
267 logic_cls.update_state_from_dict(obj, to_update[i])
268
269 db.session.commit()
270 result.update({"updated_{0}_ids".format(typ): list(existing.keys()),
271 "non_existing_{0}_ids".format(typ): non_existing_ids})
272
273 return flask.jsonify(result)
274
295
319
324 response = {}
325 build_id = flask.request.json.get("build_id")
326 task_id = flask.request.json.get("task_id")
327 chroot = flask.request.json.get("chroot")
328
329 try:
330 build = ComplexLogic.get_build_safe(build_id)
331 except ObjectNotFound:
332 response["result"] = "noop"
333 response["msg"] = "Build {} wasn't found".format(build_id)
334 return flask.jsonify(response)
335
336 if build.canceled:
337 response["result"] = "noop"
338 response["msg"] = "build was cancelled, ignoring"
339 return flask.jsonify(response)
340
341 run_statuses = set([StatusEnum("starting"), StatusEnum("running")])
342
343 if task_id == build.task_id:
344 if build.source_status in run_statuses:
345 log.info("rescheduling srpm build {}".format(build.id))
346 BuildsLogic.update_state_from_dict(build, {
347 "task_id": task_id,
348 "status": StatusEnum("pending")
349 })
350 db.session.commit()
351 response["result"] = "done"
352 else:
353 response["result"] = "noop"
354 response["msg"] = "build is not in running states, ignoring"
355 else:
356 build_chroot = build.chroots_dict_by_name.get(chroot)
357 if build_chroot and build_chroot.status in run_statuses:
358 log.info("rescheduling build {} chroot: {}".format(build.id, build_chroot.name))
359 BuildsLogic.update_state_from_dict(build, {
360 "task_id": task_id,
361 "chroot": chroot,
362 "status": StatusEnum("pending")
363 })
364 db.session.commit()
365 response["result"] = "done"
366 else:
367 response["result"] = "noop"
368 response["msg"] = "build chroot is not in running states, ignoring"
369
370 return flask.jsonify(response)
371
375
381