From e2afd9597fd19ea81070b045ffe14b5b7542a122 Mon Sep 17 00:00:00 2001 From: Christophe Monniez Date: Thu, 30 Jun 2022 23:23:21 +0200 Subject: [PATCH] [IMP] runbot: get host basic informations --- runbot/controllers/frontend.py | 2 ++ runbot/models/host.py | 46 +++++++++++++++++++++++++++++++++- runbot/models/runbot.py | 2 ++ runbot/templates/build.xml | 1 + runbot/views/host_views.xml | 24 +++++++++++++++++- 5 files changed, 73 insertions(+), 2 deletions(-) diff --git a/runbot/controllers/frontend.py b/runbot/controllers/frontend.py index a9fcf053..b8dd97c9 100644 --- a/runbot/controllers/frontend.py +++ b/runbot/controllers/frontend.py @@ -291,6 +291,7 @@ class Runbot(Controller): if not build.exists(): return request.not_found() siblings = (build.parent_id.children_ids if build.parent_id else from_batch.slot_ids.build_id if from_batch else build).sorted('id') + host_id = request.env['runbot.host'].search([('name', '=', build.host)]) context = { 'build': build, 'from_batch': from_batch, @@ -302,6 +303,7 @@ class Runbot(Controller): 'prev_bu': next((b for b in reversed(siblings) if b.id < build.id), Build), 'next_bu': next((b for b in siblings if b.id > build.id), Build), 'next_ko': next((b for b in siblings if b.id > build.id and b.global_result != 'ok'), Build), + 'host_id': host_id, } return request.render("runbot.build", context) diff --git a/runbot/models/host.py b/runbot/models/host.py index bf57fb77..376e195b 100644 --- a/runbot/models/host.py +++ b/runbot/models/host.py @@ -1,8 +1,21 @@ import logging -from odoo import models, fields, api +import os +import platform +from pathlib import Path + +import docker +from odoo import api, fields, models +from odoo.modules import get_module_path from odoo.tools import config + from ..common import fqdn, local_pgadmin_cursor, os from ..container import docker_build + +try: + import lsb_release +except ImportError: + lsb_release = None + _logger = logging.getLogger(__name__) forced_host_name = None @@ -27,9 +40,12 @@ class Host(models.Model): ) nb_testing = fields.Integer(compute='_compute_nb') nb_running = fields.Integer(compute='_compute_nb') + testing_build_ids = fields.Many2many('runbot.build', compute='_compute_build_ids') + running_build_ids = fields.Many2many('runbot.build', compute='_compute_build_ids') last_exception = fields.Char('Last exception') exception_count = fields.Integer('Exception count') psql_conn_count = fields.Integer('SQL connections count', default=0) + host_infos = fields.Char('Host Infos') def _compute_nb(self): groups = self.env['runbot.build'].read_group( @@ -45,6 +61,12 @@ class Host(models.Model): host.nb_testing = count_by_host_state[host.name].get('testing', 0) host.nb_running = count_by_host_state[host.name].get('running', 0) + def _compute_build_ids(self): + build_ids = self.env['runbot.build'].search([('host', 'in', self.mapped('name')), ('local_state', 'in', ('testing', 'running'))]) + for host in self: + host.testing_build_ids = build_ids.filtered(lambda rec: rec.host == self.name and rec.local_state == 'testing') + host.running_build_ids = build_ids.filtered(lambda rec: rec.host == self.name and rec.local_state == 'running') + @api.model_create_single def create(self, values): if 'disp_name' not in values: @@ -123,3 +145,25 @@ class Host(models.Model): nb_reserved = self.env['runbot.host'].search_count([('assigned_only', '=', True)]) if nb_reserved < (nb_hosts / 2): self.assigned_only = True + + @staticmethod + def _get_sources_head(sources_path): + head_path = sources_path / '.git/HEAD' + if not head_path.exists(): + return '' + ref = head_path.read_text().strip().split('ref: ')[-1] + commit = (head_path.parent / ref).read_text().strip() + return f'{ref.split("/")[-1]} -- {commit[:8]}' + + def _set_host_infos(self): + """ Gater host informations """ + self.ensure_one() + infos = {} + infos['OS'] = lsb_release.get_distro_information().get('DESCRIPTION', '') if lsb_release else '' # e.g. 'Debian GNU/Linux 11 (bullseye)' + infos['Platform'] = f'{platform.system()}-{platform.release()}' # e.g. 'Linux-5.10.0-13-amd64' + infos['Docker Lib'] = docker.__version__ # e.g. '4.1.0' + infos['Python'] = platform.python_version() # e.g. '3.9.2' + infos['Odoo Head'] = self._get_sources_head(Path(config['root_path']).parent) # e.g. '15.0 -- ff027d13' + infos['Runbot Head'] = self._get_sources_head(Path(get_module_path('runbot')).parent) + infos['Sys Load'] = f'{os.getloadavg()[0] / os.cpu_count() * 100:.02f}' # 1 min load average percentage + self.host_infos = ' / '.join(f'{k}: {v}' for k,v in infos.items()) diff --git a/runbot/models/runbot.py b/runbot/models/runbot.py index 499c6b00..4331de16 100644 --- a/runbot/models/runbot.py +++ b/runbot/models/runbot.py @@ -38,6 +38,7 @@ class Runbot(models.AbstractModel): def _scheduler(self, host): self._gc_testing(host) + host._set_host_infos() self._commit() for build in self._get_builds_with_requested_actions(host): build._process_requested_actions() @@ -230,6 +231,7 @@ class Runbot(models.AbstractModel): def _fetch_loop_turn(self, host, pull_info_failures, default_sleep=1): with self.manage_host_exception(host) as manager: + host._set_host_infos() repos = self.env['runbot.repo'].search([('mode', '!=', 'disabled')]) processing_batch = self.env['runbot.batch'].search([('state', 'in', ('preparing', 'ready'))], order='id asc') preparing_batch = processing_batch.filtered(lambda b: b.state == 'preparing') diff --git a/runbot/templates/build.xml b/runbot/templates/build.xml index 32072a89..fd99fd64 100644 --- a/runbot/templates/build.xml +++ b/runbot/templates/build.xml @@ -156,6 +156,7 @@ Host: +
Total time: diff --git a/runbot/views/host_views.xml b/runbot/views/host_views.xml index 767dc3a2..8b3a671c 100644 --- a/runbot/views/host_views.xml +++ b/runbot/views/host_views.xml @@ -18,7 +18,28 @@ + + + + + + + + + + + + + + + + + + + + +
@@ -33,10 +54,11 @@ runbot.host - + +