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)
"""
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,
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:
)
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
(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),
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({
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):