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