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_config = helpers.generate_build_config(task.build.copr, task.mock_chroot.name)
95 build_record = None
96 try:
97 build_record = {
98 "task_id": task.task_id,
99 "build_id": task.build.id,
100 "project_owner": task.build.copr.owner_name,
101 "project_name": task.build.copr_name,
102 "project_dirname": task.build.copr_dirname,
103 "submitter": task.build.submitter[0],
104 "sandbox": task.build.sandbox,
105 "chroot": task.mock_chroot.name,
106 "repos": task.build.repos,
107 "memory_reqs": task.build.memory_reqs,
108 "timeout": task.build.timeout,
109 "enable_net": task.build.enable_net,
110 "git_repo": task.build.package.dist_git_repo,
111 "git_hash": task.git_hash,
112 "source_type": helpers.BuildSourceEnum("scm"),
113 "source_json": json.dumps(
114 {'clone_url': task.build.package.dist_git_clone_url, 'committish': task.git_hash}),
115 "fetch_sources_only": True,
116 "package_name": task.build.package.name,
117 "package_version": task.build.pkg_version,
118 "repos": build_config.get("repos"),
119 "buildroot_pkgs": build_config.get("additional_packages"),
120 "use_bootstrap_container": build_config.get("use_bootstrap_container"),
121 "with_opts": build_config.get("with_opts"),
122 "without_opts": build_config.get("without_opts"),
123 }
124
125 except Exception as err:
126 app.logger.exception(err)
127 return None
128
129 return build_record
130
133 if not task:
134 return None
135
136 if task.source_type_text == "custom":
137 chroot = task.source_json_dict['chroot']
138 else:
139 chroot = None
140
141 try:
142 build_record = {
143 "task_id": task.task_id,
144 "build_id": task.id,
145 "project_owner": task.copr.owner_name,
146 "project_name": task.copr_name,
147 "project_dirname": task.copr_dirname,
148 "submitter": task.submitter[0],
149 "sandbox": task.sandbox,
150 "source_type": task.source_type,
151 "source_json": task.source_json,
152 "chroot": chroot,
153 }
154
155 except Exception as err:
156 app.logger.exception(err)
157 return None
158
159 return build_record
160
174
182
183
184 @backend_ns.route("/pending-jobs/")
185 -def pending_jobs():
194
195
196 @backend_ns.route("/get-build-task/<task_id>")
197 -def get_build_task(task_id):
198 try:
199 task = BuildsLogic.get_build_task(task_id)
200 except exceptions.MalformedArgumentException:
201 jsonout = flask.jsonify({'msg': 'Invalid task ID'})
202 jsonout.status_code = 500
203 return jsonout
204 except sqlalchemy.orm.exc.NoResultFound:
205 jsonout = flask.jsonify({'msg': 'Specified task ID not found'})
206 jsonout.status_code = 404
207 return jsonout
208 build_record = get_build_record(task)
209 return flask.jsonify(build_record)
210
211
212 @backend_ns.route("/get-srpm-build-task/<build_id>")
213 -def get_srpm_build_task(build_id):
214 try:
215 task = BuildsLogic.get_srpm_build_task(build_id)
216 except sqlalchemy.orm.exc.NoResultFound:
217 jsonout = flask.jsonify({'msg': 'Specified task ID not found'})
218 jsonout.status_code = 404
219 return jsonout
220 build_record = get_srpm_build_record(task)
221 return flask.jsonify(build_record)
222
227 result = {}
228
229 request_data = flask.request.json
230 for typ, logic_cls in [("actions", actions_logic.ActionsLogic),
231 ("builds", BuildsLogic)]:
232
233 if typ not in request_data:
234 continue
235
236 to_update = {}
237 for obj in request_data[typ]:
238 to_update[obj["id"]] = obj
239
240 existing = {}
241 for obj in logic_cls.get_by_ids(to_update.keys()).all():
242 existing[obj.id] = obj
243
244 non_existing_ids = list(set(to_update.keys()) - set(existing.keys()))
245
246 for i, obj in existing.items():
247 logic_cls.update_state_from_dict(obj, to_update[i])
248
249 db.session.commit()
250 result.update({"updated_{0}_ids".format(typ): list(existing.keys()),
251 "non_existing_{0}_ids".format(typ): non_existing_ids})
252
253 return flask.jsonify(result)
254
275
299
304 response = {}
305 build_id = flask.request.json.get("build_id")
306 task_id = flask.request.json.get("task_id")
307 chroot = flask.request.json.get("chroot")
308
309 try:
310 build = ComplexLogic.get_build_safe(build_id)
311 except ObjectNotFound:
312 response["result"] = "noop"
313 response["msg"] = "Build {} wasn't found".format(build_id)
314 return flask.jsonify(response)
315
316 if build.canceled:
317 response["result"] = "noop"
318 response["msg"] = "build was cancelled, ignoring"
319 return flask.jsonify(response)
320
321 run_statuses = set([StatusEnum("starting"), StatusEnum("running")])
322
323 if task_id == build.task_id:
324 if build.source_status in run_statuses:
325 log.info("rescheduling srpm build {}".format(build.id))
326 BuildsLogic.update_state_from_dict(build, {
327 "task_id": task_id,
328 "status": StatusEnum("pending")
329 })
330 db.session.commit()
331 response["result"] = "done"
332 else:
333 response["result"] = "noop"
334 response["msg"] = "build is not in running states, ignoring"
335 else:
336 build_chroot = build.chroots_dict_by_name.get(chroot)
337 if build_chroot and build_chroot.status in run_statuses:
338 log.info("rescheduling build {} chroot: {}".format(build.id, build_chroot.name))
339 BuildsLogic.update_state_from_dict(build, {
340 "task_id": task_id,
341 "chroot": chroot,
342 "status": StatusEnum("pending")
343 })
344 db.session.commit()
345 response["result"] = "done"
346 else:
347 response["result"] = "noop"
348 response["msg"] = "build chroot is not in running states, ignoring"
349
350 return flask.jsonify(response)
351
355
361