chiark / gitweb /
build: enable watchdog timer for each build that kills in 2 hours
authorMarcus Hoffmann <bubu@bubu1.eu>
Mon, 15 Jan 2018 00:03:47 +0000 (01:03 +0100)
committerMarcus Hoffmann <bubu@bubu1.eu>
Mon, 22 Jan 2018 15:01:20 +0000 (16:01 +0100)
This introduces locking for the commonly used vagrant functions in
vmtools because vagrant fails when another vagrant command is
already running.

fdroidserver/build.py
fdroidserver/vmtools.py

index 61cda139e88407f5961427824c689b2ef249b45a..cb030ebb4abb8981d697dd67948694bf3495481f 100644 (file)
@@ -25,6 +25,7 @@ import re
 import resource
 import sys
 import tarfile
+import threading
 import traceback
 import time
 import requests
@@ -978,6 +979,13 @@ def trybuild(app, build, build_dir, output_dir, log_dir, also_check_dir,
     return True
 
 
+def force_halt_build():
+    """Halt the currently running Vagrant VM, to be called from a Timer"""
+    logging.error(_('Force halting build after timeout!'))
+    vm = vmtools.get_build_vm('builder')
+    vm.halt()
+
+
 def parse_commandline():
     """Parse the command line. Returns options, parser."""
 
@@ -1143,6 +1151,12 @@ def main():
         first = True
 
         for build in app.builds:
+            if options.server:  # enable watchdog timer
+                timer = threading.Timer(7200, force_halt_build)
+                timer.start()
+            else:
+                timer = None
+
             wikilog = None
             build_starttime = common.get_wiki_timestamp()
             tools_version_log = ''
@@ -1283,6 +1297,9 @@ def main():
                 except Exception as e:
                     logging.error("Error while attempting to publish build log: %s" % e)
 
+            if timer:
+                timer.cancel()  # kill the watchdog timer
+
     for app in build_succeeded:
         logging.info("success: %s" % (app.id))
 
index 6671a3eb8d38274ae161ab2ab82fb008bb0a8fc6..33544ac53798f192b578eb216a26cc28a3e061f3 100644 (file)
@@ -29,6 +29,9 @@ from .common import FDroidException
 from logging import getLogger
 
 from fdroidserver import _
+import threading
+
+lock = threading.Lock()
 
 logger = getLogger('fdroidserver-vmtools')
 
@@ -175,7 +178,6 @@ class FDroidBuildVm():
     This is intended to be a hypervisor independant, fault tolerant
     wrapper around the vagrant functions we use.
     """
-
     def __init__(self, srvdir):
         """Create new server class.
         """
@@ -191,21 +193,27 @@ class FDroidBuildVm():
         self.vgrnt = vagrant.Vagrant(root=srvdir, out_cm=vagrant.stdout_cm, err_cm=vagrant.stdout_cm)
 
     def up(self, provision=True):
-        try:
-            self.vgrnt.up(provision=provision)
-            self.srvuuid = self._vagrant_fetch_uuid()
-        except subprocess.CalledProcessError as e:
-            raise FDroidBuildVmException("could not bring up vm '%s'" % self.srvname) from e
+        global lock
+        with lock:
+            try:
+                self.vgrnt.up(provision=provision)
+                self.srvuuid = self._vagrant_fetch_uuid()
+            except subprocess.CalledProcessError as e:
+                raise FDroidBuildVmException("could not bring up vm '%s'" % self.srvname) from e
 
     def suspend(self):
-        logger.info('suspending buildserver')
-        try:
-            self.vgrnt.suspend()
-        except subprocess.CalledProcessError as e:
-            raise FDroidBuildVmException("could not suspend vm '%s'" % self.srvname) from e
+        global lock
+        with lock:
+            logger.info('suspending buildserver')
+            try:
+                self.vgrnt.suspend()
+            except subprocess.CalledProcessError as e:
+                raise FDroidBuildVmException("could not suspend vm '%s'" % self.srvname) from e
 
     def halt(self):
-        self.vgrnt.halt(force=True)
+        global lock
+        with lock:
+            self.vgrnt.halt(force=True)
 
     def destroy(self):
         """Remove every trace of this VM from the system.