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.logic import actions_logic
9 from coprs.logic.builds_logic import BuildsLogic
10 from coprs.logic.complex_logic import ComplexLogic, BuildConfigLogic
11 from coprs.logic.packages_logic import PackagesLogic
12 from coprs.logic.coprs_logic import MockChrootsLogic, CoprChrootsLogic
13 from coprs.exceptions import MalformedArgumentException, ObjectNotFound
14
15 from coprs.views import misc
16 from coprs.views.backend_ns import backend_ns
17 from sqlalchemy.sql import false, true
18
19 import json
20 import logging
21
22 log = logging.getLogger(__name__)
52
87
90 if not task:
91 return None
92
93 build_record = None
94 try:
95 copr_chroot = CoprChrootsLogic.get_by_name_safe(task.build.copr, task.mock_chroot.name)
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
120 if copr_chroot.module_toggle_array:
121 array = [{'enable': m} for m in copr_chroot.module_toggle_array]
122 build_record["modules"] = {'toggle': array}
123
124 if short:
125 return build_record
126
127 build_config = BuildConfigLogic.generate_build_config(task.build.copr, task.mock_chroot.name)
128 build_record["repos"] = build_config.get("repos")
129 build_record["buildroot_pkgs"] = build_config.get("additional_packages")
130 build_record["use_bootstrap_container"] = build_config.get("use_bootstrap_container")
131 build_record["with_opts"] = build_config.get("with_opts")
132 build_record["without_opts"] = build_config.get("without_opts")
133
134 except Exception as err:
135 app.logger.exception(err)
136 return None
137
138 return build_record
139
142 if not task:
143 return None
144
145 if task.source_type_text == "custom":
146 chroot = task.source_json_dict['chroot']
147 else:
148 chroot = None
149
150 try:
151 build_record = {
152 "task_id": task.task_id,
153 "build_id": task.id,
154 "project_owner": task.copr.owner_name,
155 "project_name": task.copr_name,
156 "project_dirname": task.copr_dirname,
157 "submitter": task.submitter[0],
158 "sandbox": task.sandbox,
159 "source_type": task.source_type,
160 "source_json": task.source_json,
161 "chroot": chroot,
162 }
163
164 except Exception as err:
165 app.logger.exception(err)
166 return None
167
168 return build_record
169
183
191
192
193 @backend_ns.route("/action/<int:action_id>/")
194 -def get_action(action_id):
198
206
207
208 @backend_ns.route("/pending-jobs/")
209 -def pending_jobs():
220
221
222 @backend_ns.route("/get-build-task/<task_id>")
223 -def get_build_task(task_id):
224 try:
225 task = BuildsLogic.get_build_task(task_id)
226 except MalformedArgumentException:
227 jsonout = flask.jsonify({'msg': 'Invalid task ID'})
228 jsonout.status_code = 500
229 return jsonout
230 except sqlalchemy.orm.exc.NoResultFound:
231 jsonout = flask.jsonify({'msg': 'Specified task ID not found'})
232 jsonout.status_code = 404
233 return jsonout
234 build_record = get_build_record(task)
235 return flask.jsonify(build_record)
236
237
238 @backend_ns.route("/get-srpm-build-task/<build_id>")
239 -def get_srpm_build_task(build_id):
240 try:
241 task = BuildsLogic.get_srpm_build_task(build_id)
242 except sqlalchemy.orm.exc.NoResultFound:
243 jsonout = flask.jsonify({'msg': 'Specified task ID not found'})
244 jsonout.status_code = 404
245 return jsonout
246 build_record = get_srpm_build_record(task)
247 return flask.jsonify(build_record)
248
253 result = {}
254
255 request_data = flask.request.json
256 for typ, logic_cls in [("actions", actions_logic.ActionsLogic),
257 ("builds", BuildsLogic)]:
258
259 if typ not in request_data:
260 continue
261
262 to_update = {}
263 for obj in request_data[typ]:
264 to_update[obj["id"]] = obj
265
266 existing = {}
267 for obj in logic_cls.get_by_ids(to_update.keys()).all():
268 existing[obj.id] = obj
269
270 non_existing_ids = list(set(to_update.keys()) - set(existing.keys()))
271
272 for i, obj in existing.items():
273 logic_cls.update_state_from_dict(obj, to_update[i])
274
275 db.session.commit()
276 result.update({"updated_{0}_ids".format(typ): list(existing.keys()),
277 "non_existing_{0}_ids".format(typ): non_existing_ids})
278
279 return flask.jsonify(result)
280
301
325
330 response = {}
331 build_id = flask.request.json.get("build_id")
332 task_id = flask.request.json.get("task_id")
333 chroot = flask.request.json.get("chroot")
334
335 try:
336 build = ComplexLogic.get_build_safe(build_id)
337 except ObjectNotFound:
338 response["result"] = "noop"
339 response["msg"] = "Build {} wasn't found".format(build_id)
340 return flask.jsonify(response)
341
342 if build.canceled:
343 response["result"] = "noop"
344 response["msg"] = "build was cancelled, ignoring"
345 return flask.jsonify(response)
346
347 run_statuses = set([StatusEnum("starting"), StatusEnum("running")])
348
349 if task_id == build.task_id:
350 if build.source_status in run_statuses:
351 log.info("rescheduling srpm build {}".format(build.id))
352 BuildsLogic.update_state_from_dict(build, {
353 "task_id": task_id,
354 "status": StatusEnum("pending")
355 })
356 db.session.commit()
357 response["result"] = "done"
358 else:
359 response["result"] = "noop"
360 response["msg"] = "build is not in running states, ignoring"
361 else:
362 build_chroot = build.chroots_dict_by_name.get(chroot)
363 if build_chroot and build_chroot.status in run_statuses:
364 log.info("rescheduling build {} chroot: {}".format(build.id, build_chroot.name))
365 BuildsLogic.update_state_from_dict(build, {
366 "task_id": task_id,
367 "chroot": chroot,
368 "status": StatusEnum("pending")
369 })
370 db.session.commit()
371 response["result"] = "done"
372 else:
373 response["result"] = "noop"
374 response["msg"] = "build chroot is not in running states, ignoring"
375
376 return flask.jsonify(response)
377
381
387