1 import flask
2 import time
3 import sqlalchemy
4
5 from coprs import db, app
6 from coprs import helpers
7 from coprs import models
8 from coprs import exceptions
9 from coprs.helpers import StatusEnum
10 from coprs.logic import actions_logic
11 from coprs.logic.builds_logic import BuildsLogic, BuildChrootsLogic
12 from coprs.logic.complex_logic import ComplexLogic
13 from coprs.logic.coprs_logic import CoprChrootsLogic
14 from coprs.logic.packages_logic import PackagesLogic
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 urllib
22 import logging
23
24 log = logging.getLogger(__name__)
52
57 app.logger.debug(flask.request.json)
58 build_id = flask.request.json.get("build_id")
59 pkg_name = flask.request.json.get("pkg_name")
60 pkg_version = flask.request.json.get("pkg_evr")
61
62 try:
63 build = ComplexLogic.get_build_safe(build_id)
64 except ObjectNotFound:
65 return flask.jsonify({"updated": False})
66
67 collected_branch_chroots = []
68 for branch, git_hash in flask.request.json.get("branch_commits", {}).items():
69 branch_chroots = BuildsLogic.get_buildchroots_by_build_id_and_branch(build_id, branch)
70
71 if not PackagesLogic.get(build.copr.id, pkg_name).first():
72 try:
73 package = PackagesLogic.add(build.copr.user, build.copr, pkg_name, build.source_type, build.source_json)
74 db.session.add(package)
75 db.session.commit()
76 except (sqlalchemy.exc.IntegrityError, exceptions.DuplicateException) as e:
77 db.session.rollback()
78
79 package = PackagesLogic.get(build.copr.id, pkg_name).first()
80 build.package_id = package.id
81 build.pkg_version = pkg_version
82
83 for ch in branch_chroots:
84 ch.status = StatusEnum("pending")
85 ch.git_hash = git_hash
86 db.session.add(ch)
87 collected_branch_chroots.append((ch.task_id))
88
89 final_source_status = StatusEnum("succeeded")
90 for ch in build.build_chroots:
91 if ch.task_id not in collected_branch_chroots:
92 final_source_status = StatusEnum("failed")
93 ch.status = StatusEnum("failed")
94 db.session.add(ch)
95
96 build.source_status = final_source_status
97 db.session.add(build)
98 db.session.commit()
99
100 BuildsLogic.delete_local_source(build)
101 return flask.jsonify({"updated": True})
102
105 if not task:
106 return None
107
108 build_config = helpers.generate_build_config(task.build.copr, task.mock_chroot.name)
109 build_record = None
110 try:
111 build_record = {
112 "task_id": task.task_id,
113 "build_id": task.build.id,
114 "project_owner": task.build.copr.owner_name,
115 "project_name": task.build.copr.name,
116 "submitter": task.build.user.name if task.build.user else None,
117 "chroot": task.mock_chroot.name,
118
119 "repos": task.build.repos,
120 "memory_reqs": task.build.memory_reqs,
121 "timeout": task.build.timeout,
122 "enable_net": task.build.enable_net,
123 "git_repo": task.build.package.dist_git_repo,
124 "git_hash": task.git_hash,
125 "source_type": helpers.BuildSourceEnum("scm"),
126 "source_json": json.dumps(
127 {'clone_url': task.build.package.dist_git_clone_url, 'committish': task.git_hash}),
128 "fetch_sources_only": True,
129 "package_name": task.build.package.name,
130 "package_version": task.build.pkg_version,
131 "repos": build_config.get("repos"),
132 "buildroot_pkgs": build_config.get("additional_packages"),
133 "use_bootstrap_container": build_config.get("use_bootstrap_container")
134 }
135
136 except Exception as err:
137 app.logger.exception(err)
138
139 return build_record
140
143 if not task:
144 return None
145
146 try:
147 build_record = {
148 "task_id": task.task_id,
149 "build_id": task.id,
150 "project_owner": task.copr.owner_name,
151 "project_name": task.copr.name,
152 "source_type": task.source_type,
153 "source_json": task.source_json,
154 }
155
156 except Exception as err:
157 app.logger.exception(err)
158
159 return build_record
160
174
175
176 @backend_ns.route("/pending-jobs/")
177 -def pending_jobs():
185
186
187 @backend_ns.route("/get-build-task/<task_id>")
188 -def get_build_task(task_id):
189 try:
190 task = BuildsLogic.get_build_task(task_id)
191 except exceptions.MalformedArgumentException:
192 jsonout = flask.jsonify({'msg': 'Invalid task ID'})
193 jsonout.status_code = 500
194 return jsonout
195 except sqlalchemy.orm.exc.NoResultFound:
196 jsonout = flask.jsonify({'msg': 'Specified task ID not found'})
197 jsonout.status_code = 404
198 return jsonout
199 build_record = get_build_record(task)
200 return flask.jsonify(build_record)
201
202
203 @backend_ns.route("/get-srpm-build-task/<build_id>")
204 -def get_srpm_build_task(build_id):
205 try:
206 task = BuildsLogic.get_srpm_build_task(build_id)
207 except sqlalchemy.orm.exc.NoResultFound:
208 jsonout = flask.jsonify({'msg': 'Specified task ID not found'})
209 jsonout.status_code = 404
210 return jsonout
211 build_record = get_srpm_build_record(task)
212 return flask.jsonify(build_record)
213
218 result = {}
219
220 request_data = flask.request.json
221 for typ, logic_cls in [("actions", actions_logic.ActionsLogic),
222 ("builds", BuildsLogic)]:
223
224 if typ not in request_data:
225 continue
226
227 to_update = {}
228 for obj in request_data[typ]:
229 to_update[obj["id"]] = obj
230
231 existing = {}
232 for obj in logic_cls.get_by_ids(to_update.keys()).all():
233 existing[obj.id] = obj
234
235 non_existing_ids = list(set(to_update.keys()) - set(existing.keys()))
236
237 for i, obj in existing.items():
238 logic_cls.update_state_from_dict(obj, to_update[i])
239
240 db.session.commit()
241 result.update({"updated_{0}_ids".format(typ): list(existing.keys()),
242 "non_existing_{0}_ids".format(typ): non_existing_ids})
243
244 return flask.jsonify(result)
245
266
290
295 response = {}
296 build_id = flask.request.json.get("build_id")
297 task_id = flask.request.json.get("task_id")
298 chroot = flask.request.json.get("chroot")
299
300 try:
301 build = ComplexLogic.get_build_safe(build_id)
302 except ObjectNotFound:
303 response["result"] = "noop"
304 response["msg"] = "Build {} wasn't found".format(build_id)
305 return flask.jsonify(response)
306
307 if build.canceled:
308 response["result"] = "noop"
309 response["msg"] = "build was cancelled, ignoring"
310 return flask.jsonify(response)
311
312 run_statuses = set([StatusEnum("starting"), StatusEnum("running")])
313
314 if task_id == build.task_id:
315 if build.source_status in run_statuses:
316 log.info("rescheduling srpm build {}".format(build.id))
317 BuildsLogic.update_state_from_dict(build, {
318 "task_id": task_id,
319 "status": StatusEnum("pending")
320 })
321 db.session.commit()
322 response["result"] = "done"
323 else:
324 response["result"] = "noop"
325 response["msg"] = "build is not in running states, ignoring"
326 else:
327 build_chroot = build.chroots_dict_by_name.get(chroot)
328 if build_chroot and build_chroot.status in run_statuses:
329 log.info("rescheduling build {} chroot: {}".format(build.id, build_chroot.name))
330 BuildsLogic.update_state_from_dict(build, {
331 "task_id": task_id,
332 "chroot": chroot,
333 "status": StatusEnum("pending")
334 })
335 db.session.commit()
336 response["result"] = "done"
337 else:
338 response["result"] = "noop"
339 response["msg"] = "build chroot is not in running states, ignoring"
340
341 return flask.jsonify(response)
342