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 if ch.status == helpers.StatusEnum("importing"): 91 ch.status = helpers.StatusEnum("pending") 92 ch.git_hash = git_hash 93 94 # Failed? 95 elif "error" in flask.request.json: 96 error_type = flask.request.json["error"] 97 98 try: 99 build.fail_type = helpers.FailTypeEnum(error_type) 100 except KeyError: 101 build.fail_type = helpers.FailTypeEnum("unknown_error") 102 103 for ch in build_chroots: 104 ch.status = helpers.StatusEnum("failed") 105 106 # is it the last chroot? 107 if not build.has_importing_chroot: 108 BuildsLogic.delete_local_srpm(build) 109 110 db.session.commit() 111 112 result.update({"updated": True}) 113 114 return flask.jsonify(result)
115
116 117 @backend_ns.route("/waiting/") 118 #@misc.backend_authenticated 119 -def waiting():
120 """ 121 Return a single action and a single build. 122 """ 123 action_record = None 124 build_record = None 125 126 action = actions_logic.ActionsLogic.get_waiting().first() 127 if action: 128 action_record = action.to_dict(options={ 129 "__columns_except__": ["result", "message", "ended_on"] 130 }) 131 132 task = BuildsLogic.get_build_task() 133 if task: 134 try: 135 build_record = { 136 "task_id": task.task_id, 137 "build_id": task.build.id, 138 "project_owner": task.build.copr.owner_name, 139 "project_name": task.build.copr.name, 140 "submitter": task.build.user.name if task.build.user else None, # there is no user for webhook builds 141 "pkgs": task.build.pkgs, # TODO to be removed 142 "chroot": task.mock_chroot.name, 143 144 "repos": task.build.repos, 145 "memory_reqs": task.build.memory_reqs, 146 "timeout": task.build.timeout, 147 "enable_net": task.build.enable_net, 148 "git_repo": task.build.package.dist_git_repo, 149 "git_hash": task.git_hash, 150 "git_branch": helpers.chroot_to_branch(task.mock_chroot.name), 151 "package_name": task.build.package.name, 152 "package_version": task.build.pkg_version 153 } 154 155 copr_chroot = CoprChrootsLogic.get_by_name_safe(task.build.copr, task.mock_chroot.name) 156 if copr_chroot: 157 build_record["buildroot_pkgs"] = copr_chroot.buildroot_pkgs 158 else: 159 build_record["buildroot_pkgs"] = "" 160 161 except Exception as err: 162 app.logger.exception(err) 163 164 response_dict = {"action": action_record, "build": build_record} 165 return flask.jsonify(response_dict)
166 167 168 @backend_ns.route("/update/", methods=["POST", "PUT"])
169 @misc.backend_authenticated 170 -def update():
171 result = {} 172 173 request_data = flask.request.json 174 for typ, logic_cls in [("actions", actions_logic.ActionsLogic), 175 ("builds", BuildsLogic)]: 176 177 if typ not in request_data: 178 continue 179 180 to_update = {} 181 for obj in request_data[typ]: 182 to_update[obj["id"]] = obj 183 184 existing = {} 185 for obj in logic_cls.get_by_ids(to_update.keys()).all(): 186 existing[obj.id] = obj 187 188 non_existing_ids = list(set(to_update.keys()) - set(existing.keys())) 189 190 for i, obj in existing.items(): 191 logic_cls.update_state_from_dict(obj, to_update[i]) 192 193 db.session.commit() 194 result.update({"updated_{0}_ids".format(typ): list(existing.keys()), 195 "non_existing_{0}_ids".format(typ): non_existing_ids}) 196 197 return flask.jsonify(result)
198 199 200 @backend_ns.route("/starting_build/", methods=["POST", "PUT"])
201 @misc.backend_authenticated 202 -def starting_build():
203 """ 204 Check if the build is not cancelled and set it to running state 205 """ 206 207 result = {"can_start": False} 208 209 if "build_id" in flask.request.json and "chroot" in flask.request.json: 210 build = ComplexLogic.get_build_safe(flask.request.json["build_id"]) 211 chroot = flask.request.json.get("chroot") 212 213 if build and chroot and not build.canceled: 214 log.info("mark build {} chroot {} as starting".format(build.id, chroot)) 215 BuildsLogic.update_state_from_dict(build, { 216 "chroot": chroot, 217 "status": StatusEnum("starting") 218 }) 219 db.session.commit() 220 result["can_start"] = True 221 222 return flask.jsonify(result)
223 224 225 @backend_ns.route("/defer_build/", methods=["POST", "PUT"])
226 @misc.backend_authenticated 227 -def defer_build():
228 """ 229 Defer build (keep it out of waiting jobs for some time). 230 """ 231 232 result = {"was_deferred": False} 233 234 if "build_id" in flask.request.json and "chroot" in flask.request.json: 235 build = ComplexLogic.get_build_safe(flask.request.json["build_id"]) 236 chroot = flask.request.json.get("chroot") 237 238 if build and chroot: 239 log.info("Defer build {}, chroot {}".format(build.id, chroot)) 240 BuildsLogic.update_state_from_dict(build, { 241 "chroot": chroot, 242 "last_deferred": int(time.time()), 243 }) 244 db.session.commit() 245 result["was_deferred"] = True 246 247 return flask.jsonify(result)
248 249 250 @backend_ns.route("/reschedule_all_running/", methods=["POST"])
251 @misc.backend_authenticated 252 -def reschedule_all_running():
253 """ 254 Add-hoc handle. Remove after implementation of persistent task handling in copr-backend 255 """ 256 to_reschedule = \ 257 BuildsLogic.get_build_tasks(StatusEnum("starting")).all() + \ 258 BuildsLogic.get_build_tasks(StatusEnum("running")).all() 259 260 if to_reschedule: 261 for build_chroot in to_reschedule: 262 build_chroot.status = StatusEnum("pending") 263 db.session.add(build_chroot) 264 265 db.session.commit() 266 267 return "OK", 200
268 269 270 @backend_ns.route("/reschedule_build_chroot/", methods=["POST", "PUT"])
271 @misc.backend_authenticated 272 -def reschedule_build_chroot():
273 response = {} 274 if "build_id" in flask.request.json and "chroot" in flask.request.json: 275 build = ComplexLogic.get_build_safe(flask.request.json["build_id"]) 276 else: 277 response["result"] = "bad request" 278 response["msg"] = "Request missing `build_id` and/or `chroot`" 279 return flask.jsonify(response) 280 281 if build: 282 if build.canceled: 283 response["result"] = "noop" 284 response["msg"] = "build was cancelled, ignoring" 285 else: 286 chroot = flask.request.json["chroot"] 287 build_chroot = build.chroots_dict_by_name.get(chroot) 288 run_statuses = set([StatusEnum("starting"), StatusEnum("running")]) 289 if build_chroot and build_chroot.status in run_statuses: 290 log.info("rescheduling build {} chroot: {}".format(build.id, build_chroot.name)) 291 BuildsLogic.update_state_from_dict(build, { 292 "chroot": chroot, 293 "status": StatusEnum("pending") 294 }) 295 db.session.commit() 296 response["result"] = "done" 297 else: 298 response["result"] = "noop" 299 response["msg"] = "build is not in running states, ignoring" 300 301 else: 302 response["result"] = "noop" 303 response["msg"] = "Build {} wasn't found".format(flask.request.json["build_id"]) 304 305 return flask.jsonify(response)
306