Source code for backend.frontend

import json
from requests import post, RequestException
import time


[docs]class FrontendClient(object): """ Object to send data back to fronted """ def __init__(self, opts, logger=None): super(FrontendClient, self).__init__() self.frontend_url = "{}/backend".format(opts.frontend_base_url) self.frontend_auth = opts.frontend_auth self.msg = None self.log = logger
[docs] def _post_to_frontend(self, data, url_path): """ Make a request to the frontend """ headers = {"content-type": "application/json"} url = "{}/{}/".format(self.frontend_url, url_path) auth = ("user", self.frontend_auth) self.msg = None try: response = post(url, data=json.dumps(data), auth=auth, headers=headers) if response.status_code >= 400: self.msg = "Failed to submit to frontend: {0}: {1}".format( response.status_code, response.text) raise RequestException(self.msg) except RequestException as e: self.msg = "Post request failed: {0}".format(e) raise return response
[docs] def _post_to_frontend_repeatedly(self, data, url_path, max_repeats=10): """ Make a request max_repeats-time to the frontend """ for i in range(max_repeats): try: if i and self.log: self.log.warning("failed to post data to frontend, repeat #{0}".format(i)) return self._post_to_frontend(data, url_path) except RequestException: time.sleep(5) else: raise RequestException("Failed to post to frontend for {} times".format(max_repeats))
[docs] def update(self, data): """ Send data to be updated in the frontend """ self._post_to_frontend_repeatedly(data, "update")
[docs] def starting_build(self, build_id, chroot_name): """ Announce to the frontend that a build is starting. Return: True if the build can start False if the build can not start (can be cancelled or deleted) """ data = {"build_id": build_id, "chroot": chroot_name} response = self._post_to_frontend_repeatedly(data, "starting_build") if "can_start" not in response.json(): raise RequestException("Bad respond from the frontend") return response.json()["can_start"]
[docs] def defer_build(self, build_id, chroot_name): """ Tell the frontend that the build task should be deferred (put aside for some time until there are resources for it). """ was_deferred = False data = {"build_id": build_id, "chroot": chroot_name} try: response = self._post_to_frontend_repeatedly(data, "defer_build") was_deferred = response.json()["was_deferred"] except (RequestException, ValueError, KeyError) as e: self.log.exception("Failed to defer build task (build_id {} and chroot {}) with error {}" .format(build_id, chroot_name, e)) if not was_deferred: self.log.exception("Frontend refused to defer build task: build_id {} and chroot {}" .format(build_id, chroot_name))
[docs] def reschedule_build(self, build_id, chroot_name): """ Announce to the frontend that a build should be rescheduled (set pending state). """ data = {"build_id": build_id, "chroot": chroot_name} self._post_to_frontend_repeatedly(data, "reschedule_build_chroot")
[docs] def reschedule_all_running(self, attempts): response = self._post_to_frontend_repeatedly({}, "reschedule_all_running", attempts) if response.status_code != 200: raise RequestException("Failed to reschedule all running jobs")