runbot/runbot_builder/tools.py
2022-01-27 10:08:39 +01:00

130 lines
4.2 KiB
Python

#!/usr/bin/python3
import argparse
import logging
import os
import sys
import threading
import signal
from logging.handlers import WatchedFileHandler
LOG_FORMAT = '%(asctime)s %(levelname)s %(name)s: %(message)s'
logging.basicConfig(level=logging.INFO, format=LOG_FORMAT)
logging.getLogger('odoo.addons.runbot').setLevel(logging.DEBUG)
logging.addLevelName(25, "!NFO")
_logger = logging.getLogger(__name__)
class RunbotClient():
def __init__(self, env):
self.env = env
self.ask_interrupt = threading.Event()
self.host = None
self.count = 0
self.max_count = 60
def on_start(self):
pass
def main_loop(self):
from odoo import fields
self.on_start()
signal.signal(signal.SIGINT, self.signal_handler)
signal.signal(signal.SIGTERM, self.signal_handler)
signal.signal(signal.SIGQUIT, self.dump_stack)
self.host = self.env['runbot.host']._get_current()
self.host._bootstrap()
logging.info(
'Host %s running with %s slots on pid %s%s',
self.host.name,
self.host.nb_worker,
os.getpid(),
' (assigned only)' if self.host.assigned_only else ''
)
while True:
try:
self.host.last_start_loop = fields.Datetime.now()
self.env.cr.commit()
self.count = self.count % self.max_count
sleep_time = self.loop_turn()
self.count += 1
self.host.last_end_loop = fields.Datetime.now()
self.env.cr.commit()
self.env.clear()
self.sleep(sleep_time)
except Exception as e:
_logger.exception('Builder main loop failed with: %s', e)
self.env.cr.rollback()
self.env.clear()
self.sleep(10)
if self.ask_interrupt.is_set():
return
def loop_turn(self):
raise NotImplementedError()
def signal_handler(self, _signal, _frame):
if self.ask_interrupt.is_set():
_logger.info("Second Interrupt detected, force exit")
os._exit(1)
_logger.info("Interrupt detected")
self.ask_interrupt.set()
def dump_stack(self, _signal, _frame):
import odoo
odoo.tools.misc.dumpstacks()
def sleep(self, t):
self.ask_interrupt.wait(t)
def run(client_class):
# parse args
parser = argparse.ArgumentParser()
parser.add_argument('--odoo-path', help='Odoo sources path')
parser.add_argument('--db_host')
parser.add_argument('--db_port')
parser.add_argument('--db_user')
parser.add_argument('--db_password')
parser.add_argument('-d', '--database', default='runbot', help='name of runbot db')
parser.add_argument('--logfile', default=False)
parser.add_argument('--forced-host-name', default=False)
args = parser.parse_args()
if args.logfile:
dirname = os.path.dirname(args.logfile)
if dirname and not os.path.isdir(dirname):
os.makedirs(dirname)
handler = WatchedFileHandler(args.logfile)
formatter = logging.Formatter(LOG_FORMAT)
handler.setFormatter(formatter)
logging.getLogger().addHandler(handler)
# configure odoo
sys.path.append(args.odoo_path)
import odoo
_logger.info("Starting scheduler on database %s", args.database)
odoo.tools.config['db_host'] = args.db_host
odoo.tools.config['db_port'] = args.db_port
odoo.tools.config['db_user'] = args.db_user
odoo.tools.config['db_password'] = args.db_password
addon_path = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), '..'))
config_addons_path = odoo.tools.config['addons_path']
odoo.tools.config['addons_path'] = ','.join([config_addons_path, addon_path])
odoo.tools.config['forced_host_name'] = args.forced_host_name
# create environment
registry = odoo.registry(args.database)
with odoo.api.Environment.manage():
with registry.cursor() as cr:
env = odoo.api.Environment(cr, odoo.SUPERUSER_ID, {})
client = client_class(env)
# run main loop
client.main_loop()
_logger.info("Stopping gracefully")