From: Michael Tremer Date: Wed, 26 Apr 2023 10:35:21 +0000 (+0000) Subject: builders: Create a new kind of control connection X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=46a7bd16471dfb64a29940b46514cd16abf8eb7c;p=pbs.git builders: Create a new kind of control connection Signed-off-by: Michael Tremer --- diff --git a/src/buildservice/builders.py b/src/buildservice/builders.py index 8d47f9bf..945af1a5 100644 --- a/src/buildservice/builders.py +++ b/src/buildservice/builders.py @@ -13,6 +13,9 @@ from .decorators import * log = logging.getLogger("pbs.builders") class Builders(base.Object): + # Stores any control connections to builders + connections = {} + def _get_builder(self, query, *args): res = self.db.get(query, *args) @@ -204,16 +207,11 @@ class Builder(base.DataObject): """ Returns True if the builder is online """ - if self.stats: + if self.connection: return True return False - def set_online_until(self, online_until): - self._set_attribute("online_until", online_until) - - online_until = property(lambda s: s.data.online_until, set_online_until) - def log_stats(self, cpu_model=None, cpu_count=None, cpu_arch=None, pakfire_version=None, os_name=None, cpu_user=None, cpu_nice=None, cpu_system=None, cpu_idle=None, cpu_iowait=None, cpu_irq=None, cpu_softirq=None, cpu_steal=None, cpu_guest=None, @@ -441,19 +439,6 @@ class Builder(base.DataObject): def host_key_id(self): return self.data.host_key_id - @property - def state(self): - if not self.enabled: - return "disabled" - - if self.data.time_keepalive is None: - return "offline" - - #if self.data.updated >= 5*60: - # return "offline" - - return "online" - def is_ready(self): # If the builder is not enabled, we are obviously not ready if not self.enabled: @@ -631,3 +616,42 @@ class Builder(base.DataObject): ) return res.t + + # Connections + + def connected(self, connection): + """ + Called when a builder has connected + """ + # Replace any old connections + if self.connection: + log.warning("Closing connection to %s because it is being replaced" % self) + + # Close the previous connection + self.connection.close(code=1000, reason="Replaced by a new connection") + + log.debug("%s has connected" % self) + + # Store the connection + self.backend.builders.connections[self] = connection + + def disconnected(self): + """ + Called when a builder has disconnected + """ + log.debug("%s has disconnected" % self) + + try: + del self.backend.builders.connections[self] + except IndexError: + pass + + @property + def connection(self): + """ + Easy access to the control connection to a builder + """ + try: + return self.backend.builders.connections[self] + except KeyError: + pass diff --git a/src/web/__init__.py b/src/web/__init__.py index f877a791..ae0ec960 100644 --- a/src/web/__init__.py +++ b/src/web/__init__.py @@ -151,7 +151,7 @@ class Application(tornado.web.Application): (r"/builders/([A-Za-z0-9\-\.]+)/delete", builders.BuilderDeleteHandler), (r"/builders/([A-Za-z0-9\-\.]+)/edit", builders.BuilderEditHandler), (r"/builders/([A-Za-z0-9\-\.]+)", builders.BuilderDetailHandler), - (r"/api/v1/builders/stats", builders.APIv1StatsHandler), + (r"/api/v1/builders/control", builders.APIv1ControlHandler), # Distributions (r"/distros", distributions.IndexHandler), diff --git a/src/web/base.py b/src/web/base.py index 77d79775..271040ee 100644 --- a/src/web/base.py +++ b/src/web/base.py @@ -313,6 +313,16 @@ class APIMixin(KerberosAuthMixin, BackendMixin): def get_user_locale(self): return self.get_browser_locale() + @property + def builder(self): + """ + This is a convenience handler to access a builder by a better name + """ + if isinstance(self.current_user, builders.Builder): + return self.current_user + + raise AttributeError + def write_error(self, code, **kwargs): # Send a JSON-encoded error message self.finish({ diff --git a/src/web/builders.py b/src/web/builders.py index f9606dbd..a0c3e16a 100644 --- a/src/web/builders.py +++ b/src/web/builders.py @@ -4,31 +4,25 @@ import tornado.web from . import base -class APIv1StatsHandler(base.APIMixin, tornado.websocket.WebSocketHandler): +class APIv1ControlHandler(base.APIMixin, tornado.websocket.WebSocketHandler): @tornado.web.authenticated - def __open(self): - args = { - # CPU info - "cpu_model" : self.get_argument("cpu_model", None), - "cpu_count" : self.get_argument("cpu_count", None), - "cpu_arch" : self.get_argument("cpu_arch", None), - - # Pakfire - "pakfire_version" : self.get_argument("pakfire_version", None), - - # OS - "os_name" : self.get_argument("os_name", None), - } - - with self.db.transaction(): - self.builder.update_info(**args) - - def on_message(self, message): - # Decode message - message = self._decode_json_message(message) - - with self.db.transaction(): - self.current_user.log_stats(**message) + async def open(self): + # The builder has opened a new connection + self.current_user.connected(self) + + # After the builder has connected, try to dispatch some jobs + await self.backend.jobqueue.dispatch_jobs() + + def on_close(self): + # Drop the connection to the builder + self.current_user.disconnected() + + #def on_message(self, message): + # # Decode message + # message = self._decode_json_message(message) + # + # with self.db.transaction(): + # self.current_user.log_stats(**message) class BuilderListHandler(base.BaseHandler):