Package coprs :: Package views :: Package backend_ns :: Module backend_general
[hide private]
[frames] | no frames]

Source Code for Module coprs.views.backend_ns.backend_general

  1  import flask 
  2  import time 
  3   
  4  from coprs import db, app 
  5  from coprs import helpers 
  6  from coprs import models 
  7  from coprs.helpers import StatusEnum 
  8  from coprs.logic import actions_logic 
  9  from coprs.logic.builds_logic import BuildsLogic 
 10  from coprs.logic.complex_logic import ComplexLogic 
 11  from coprs.logic.coprs_logic import CoprChrootsLogic 
 12  from coprs.logic.packages_logic import PackagesLogic 
 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  log = logging.getLogger(__name__) 
20 21 22 @backend_ns.route("/importing/") 23 # FIXME I'm commented 24 #@misc.backend_authenticated 25 -def dist_git_importing_queue():
26 """ 27 Return list of builds that are waiting for dist git to import the sources. 28 """ 29 builds_list = [] 30 builds_for_import = BuildsLogic.get_build_importing_queue().filter(models.Build.is_background == false()).limit(200).all() 31 if not builds_for_import: 32 builds_for_import = BuildsLogic.get_build_importing_queue().filter(models.Build.is_background == true()).limit(30) 33 34 for task in builds_for_import: 35 copr = task.build.copr 36 37 task_dict = { 38 "task_id": task.import_task_id, 39 "user": copr.owner_name, # TODO: user -> owner 40 "project": task.build.copr.name, 41 "branch": helpers.chroot_to_branch(task.mock_chroot.name), 42 "source_type": task.build.source_type, 43 "source_json": task.build.source_json, 44 } 45 if task_dict not in builds_list: 46 builds_list.append(task_dict) 47 48 response_dict = {"builds": builds_list} 49 50 return flask.jsonify(response_dict)
51 52 53 @backend_ns.route("/import-completed/", methods=["POST", "PUT"])
54 @misc.backend_authenticated 55 -def dist_git_upload_completed():
56 """ 57 Mark BuildChroot in a Build as uploaded, which means: 58 - set it to pending state 59 - set BuildChroot.git_hash 60 - if it's the last BuildChroot in a Build: 61 - delete local srpm 62 BuildChroot is identified with task_id which is build id + git branch name 63 - For example: 56-f22 -> build 55, chroots fedora-22-* 64 """ 65 result = {"updated": False} 66 67 if "task_id" in flask.request.json: 68 app.logger.debug(flask.request.data) 69 task_id = flask.request.json["task_id"] 70 build_chroots = BuildsLogic.get_chroots_from_dist_git_task_id(task_id) 71 build = build_chroots[0].build 72 73 # Is it OK? 74 if "git_hash" in flask.request.json and "repo_name" in flask.request.json: 75 git_hash = flask.request.json["git_hash"] 76 pkg_name = flask.request.json["pkg_name"] 77 pkg_version = flask.request.json["pkg_version"] 78 79 # Now I need to assign a package to this build 80 package = PackagesLogic.get(build.copr.id, pkg_name).first() 81 if not package: 82 package = PackagesLogic.add(build.copr.user, build.copr, pkg_name, build.source_type, build.source_json) 83 db.session.add(package) 84 db.session.flush() 85 86 build.package_id = package.id 87 build.pkg_version = pkg_version 88 89 for ch in build_chroots: 90 ch.status = helpers.StatusEnum("pending") 91 ch.git_hash = git_hash 92 93 # Failed? 94 elif "error" in flask.request.json: 95 error_type = flask.request.json["error"] 96 97 try: 98 build.fail_type = helpers.FailTypeEnum(error_type) 99 except KeyError: 100 build.fail_type = helpers.FailTypeEnum("unknown_error") 101 102 for ch in build_chroots: 103 ch.status = helpers.StatusEnum("failed") 104 105 # is it the last chroot? 106 if not build.has_importing_chroot: 107 BuildsLogic.delete_local_srpm(build) 108 109 db.session.commit() 110 111 result.update({"updated": True}) 112 113 return flask.jsonify(result)
114
115 116 @backend_ns.route("/waiting/") 117 #@misc.backend_authenticated 118 -def waiting():
119 """ 120 Return a single action and a single build. 121 """ 122 action_record = None 123 build_record = None 124 125 action = actions_logic.ActionsLogic.get_waiting().first() 126 if action: 127 action_record = action.to_dict(options={ 128 "__columns_except__": ["result", "message", "ended_on"] 129 }) 130 131 task = BuildsLogic.get_build_task() 132 if task: 133 try: 134 build_record = { 135 "task_id": task.task_id, 136 "build_id": task.build.id, 137 "project_owner": task.build.copr.owner_name, 138 "project_name": task.build.copr.name, 139 "submitter": task.build.user.name if task.build.user else None, # there is no user for webhook builds 140 "pkgs": task.build.pkgs, # TODO to be removed 141 "chroot": task.mock_chroot.name, 142 143 "repos": task.build.repos, 144 "memory_reqs": task.build.memory_reqs, 145 "timeout": task.build.timeout, 146 "enable_net": task.build.enable_net, 147 "git_repo": task.build.package.dist_git_repo, 148 "git_hash": task.git_hash, 149 "git_branch": helpers.chroot_to_branch(task.mock_chroot.name), 150 "package_name": task.build.package.name, 151 "package_version": task.build.pkg_version 152 } 153 154 copr_chroot = CoprChrootsLogic.get_by_name_safe(task.build.copr, task.mock_chroot.name) 155 if copr_chroot: 156 build_record["buildroot_pkgs"] = copr_chroot.buildroot_pkgs 157 else: 158 build_record["buildroot_pkgs"] = "" 159 160 except Exception as err: 161 app.logger.exception(err) 162 163 response_dict = {"action": action_record, "build": build_record} 164 return flask.jsonify(response_dict)
165 166 167 @backend_ns.route("/update/", methods=["POST", "PUT"])
168 @misc.backend_authenticated 169 -def update():
170 result = {} 171 172 request_data = flask.request.json 173 for typ, logic_cls in [("actions", actions_logic.ActionsLogic), 174 ("builds", BuildsLogic)]: 175 176 if typ not in request_data: 177 continue 178 179 to_update = {} 180 for obj in request_data[typ]: 181 to_update[obj["id"]] = obj 182 183 existing = {} 184 for obj in logic_cls.get_by_ids(to_update.keys()).all(): 185 existing[obj.id] = obj 186 187 non_existing_ids = list(set(to_update.keys()) - set(existing.keys())) 188 189 for i, obj in existing.items(): 190 logic_cls.update_state_from_dict(obj, to_update[i]) 191 192 db.session.commit() 193 result.update({"updated_{0}_ids".format(typ): list(existing.keys()), 194 "non_existing_{0}_ids".format(typ): non_existing_ids}) 195 196 return flask.jsonify(result)
197 198 199 @backend_ns.route("/starting_build/", methods=["POST", "PUT"])
200 @misc.backend_authenticated 201 -def starting_build():
202 """ 203 Check if the build is not cancelled and set it to running state 204 """ 205 206 result = {"can_start": False} 207 208 if "build_id" in flask.request.json and "chroot" in flask.request.json: 209 build = ComplexLogic.get_build_safe(flask.request.json["build_id"]) 210 chroot = flask.request.json.get("chroot") 211 212 if build and chroot and not build.canceled: 213 log.info("mark build {} chroot {} as starting".format(build.id, chroot)) 214 BuildsLogic.update_state_from_dict(build, { 215 "chroot": chroot, 216 "status": StatusEnum("starting") 217 }) 218 db.session.commit() 219 result["can_start"] = True 220 221 return flask.jsonify(result)
222 223 224 @backend_ns.route("/defer_build/", methods=["POST", "PUT"])
225 @misc.backend_authenticated 226 -def defer_build():
227 """ 228 Defer build (keep it out of waiting jobs for some time). 229 """ 230 231 result = {"was_deferred": False} 232 233 if "build_id" in flask.request.json and "chroot" in flask.request.json: 234 build = ComplexLogic.get_build_safe(flask.request.json["build_id"]) 235 chroot = flask.request.json.get("chroot") 236 237 if build and chroot: 238 log.info("Defer build {}, chroot {}".format(build.id, chroot)) 239 BuildsLogic.update_state_from_dict(build, { 240 "chroot": chroot, 241 "last_deferred": int(time.time()), 242 }) 243 db.session.commit() 244 result["was_deferred"] = True 245 246 return flask.jsonify(result)
247 248 249 @backend_ns.route("/reschedule_all_running/", methods=["POST"])
250 @misc.backend_authenticated 251 -def reschedule_all_running():
252 """ 253 Add-hoc handle. Remove after implementation of persistent task handling in copr-backend 254 """ 255 to_reschedule = \ 256 BuildsLogic.get_build_tasks(StatusEnum("starting")).all() + \ 257 BuildsLogic.get_build_tasks(StatusEnum("running")).all() 258 259 if to_reschedule: 260 for build_chroot in to_reschedule: 261 build_chroot.status = StatusEnum("pending") 262 db.session.add(build_chroot) 263 264 db.session.commit() 265 266 return "OK", 200
267 268 269 @backend_ns.route("/reschedule_build_chroot/", methods=["POST", "PUT"])
270 @misc.backend_authenticated 271 -def reschedule_build_chroot():
272 response = {} 273 if "build_id" in flask.request.json and "chroot" in flask.request.json: 274 build = ComplexLogic.get_build_safe(flask.request.json["build_id"]) 275 else: 276 response["result"] = "bad request" 277 response["msg"] = "Request missing `build_id` and/or `chroot`" 278 return flask.jsonify(response) 279 280 if build: 281 if build.canceled: 282 response["result"] = "noop" 283 response["msg"] = "build was cancelled, ignoring" 284 else: 285 chroot = flask.request.json["chroot"] 286 build_chroot = build.chroots_dict_by_name.get(chroot) 287 run_statuses = set([StatusEnum("starting"), StatusEnum("running")]) 288 if build_chroot and build_chroot.status in run_statuses: 289 log.info("rescheduling build {} chroot: {}".format(build.id, build_chroot.name)) 290 BuildsLogic.update_state_from_dict(build, { 291 "chroot": chroot, 292 "status": StatusEnum("pending") 293 }) 294 db.session.commit() 295 response["result"] = "done" 296 else: 297 response["result"] = "noop" 298 response["msg"] = "build is not in running states, ignoring" 299 300 else: 301 response["result"] = "noop" 302 response["msg"] = "Build {} wasn't found".format(flask.request.json["build_id"]) 303 304 return flask.jsonify(response)
305