chiark / gitweb /
vmtools: use standard imports: os.remove()
[fdroidserver.git] / fdroidserver / vmtools.py
index 2142beb7db0d532bedc24e8ce7fb33b8e17fadeb..568da58a7a7897ec2667cf6c7a242fbadf4a2eff 100644 (file)
@@ -16,8 +16,7 @@
 # You should have received a copy of the GNU Affero General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-from os import remove as rmfile
-from os.path import isdir, isfile, join as joinpath, basename, abspath, expanduser
+from os.path import isdir, isfile, basename, abspath, expanduser
 import os
 import math
 import json
@@ -29,6 +28,9 @@ from .common import FDroidException
 from logging import getLogger
 
 from fdroidserver import _
+import threading
+
+lock = threading.Lock()
 
 logger = getLogger('fdroidserver-vmtools')
 
@@ -54,7 +56,7 @@ def get_clean_builder(serverdir, reset=False):
     if reset:
         logger.info('resetting buildserver by request')
     elif not vm.vagrant_uuid_okay():
-        logger.info('resetting buildserver, bceause vagrant vm is not okay.')
+        logger.info('resetting buildserver, because vagrant vm is not okay.')
         reset = True
     elif not vm.snapshot_exists('fdroidclean'):
         logger.info("resetting buildserver, because snapshot 'fdroidclean' is not present.")
@@ -85,14 +87,14 @@ def get_clean_builder(serverdir, reset=False):
     return sshinfo
 
 
-def _check_call(cmd, shell=False, cwd=None):
+def _check_call(cmd, cwd=None):
     logger.debug(' '.join(cmd))
-    return subprocess.check_call(cmd, shell=shell, cwd=cwd)
+    return subprocess.check_call(cmd, shell=False, cwd=cwd)
 
 
-def _check_output(cmd, shell=False, cwd=None):
+def _check_output(cmd, cwd=None):
     logger.debug(' '.join(cmd))
-    return subprocess.check_output(cmd, shell=shell, cwd=cwd)
+    return subprocess.check_output(cmd, shell=False, cwd=cwd)
 
 
 def get_build_vm(srvdir, provider=None):
@@ -144,10 +146,10 @@ def get_build_vm(srvdir, provider=None):
         logger.debug('could not confirm that either virtualbox or kvm/libvirt are installed')
 
     # try guessing provider from .../srvdir/.vagrant internals
-    has_libvirt_machine = isdir(joinpath(abssrvdir, '.vagrant',
-                                         'machines', 'default', 'libvirt'))
-    has_vbox_machine = isdir(joinpath(abssrvdir, '.vagrant',
-                                      'machines', 'default', 'virtualbox'))
+    has_libvirt_machine = isdir(os.path.join(abssrvdir, '.vagrant',
+                                             'machines', 'default', 'libvirt'))
+    has_vbox_machine = isdir(os.path.join(abssrvdir, '.vagrant',
+                                          'machines', 'default', 'virtualbox'))
     if has_libvirt_machine and has_vbox_machine:
         logger.info('build vm provider lookup found virtualbox and libvirt, defaulting to \'virtualbox\'')
         return VirtualboxBuildVm(abssrvdir)
@@ -175,13 +177,12 @@ 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.
         """
         self.srvdir = srvdir
         self.srvname = basename(srvdir) + '_default'
-        self.vgrntfile = joinpath(srvdir, 'Vagrantfile')
+        self.vgrntfile = os.path.join(srvdir, 'Vagrantfile')
         self.srvuuid = self._vagrant_fetch_uuid()
         if not isdir(srvdir):
             raise FDroidBuildVmException("Can not init vagrant, directory %s not present" % (srvdir))
@@ -191,21 +192,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.
@@ -221,7 +228,7 @@ class FDroidBuildVm():
             logger.debug('vagrant destroy completed')
         except subprocess.CalledProcessError as e:
             logger.exception('vagrant destroy failed: %s', e)
-        vgrntdir = joinpath(self.srvdir, '.vagrant')
+        vgrntdir = os.path.join(self.srvdir, '.vagrant')
         try:
             shutil.rmtree(vgrntdir)
             logger.debug('deleted vagrant dir: %s', vgrntdir)
@@ -245,17 +252,17 @@ class FDroidBuildVm():
         return name.replace('/', '-VAGRANTSLASH-')
 
     def _vagrant_fetch_uuid(self):
-        if isfile(joinpath(self.srvdir, '.vagrant')):
+        if isfile(os.path.join(self.srvdir, '.vagrant')):
             # Vagrant 1.0 - it's a json file...
-            with open(joinpath(self.srvdir, '.vagrant')) as f:
+            with open(os.path.join(self.srvdir, '.vagrant')) as f:
                 id = json.load(f)['active']['default']
                 logger.debug('vm uuid: %s', id)
             return id
-        elif isfile(joinpath(self.srvdir, '.vagrant', 'machines',
-                             'default', self.provider, 'id')):
+        elif isfile(os.path.join(self.srvdir, '.vagrant', 'machines',
+                                 'default', self.provider, 'id')):
             # Vagrant 1.2 (and maybe 1.1?) it's a directory tree...
-            with open(joinpath(self.srvdir, '.vagrant', 'machines',
-                               'default', self.provider, 'id')) as f:
+            with open(os.path.join(self.srvdir, '.vagrant', 'machines',
+                                   'default', self.provider, 'id')) as f:
                 id = f.read()
                 logger.debug('vm uuid: %s', id)
             return id
@@ -280,8 +287,8 @@ class FDroidBuildVm():
             _check_call(['vagrant', 'box', 'remove', '--all', '--force', boxname])
         except subprocess.CalledProcessError as e:
             logger.debug('tried removing box %s, but is did not exist: %s', boxname, e)
-        boxpath = joinpath(expanduser('~'), '.vagrant',
-                           self._vagrant_file_name(boxname))
+        boxpath = os.path.join(expanduser('~'), '.vagrant',
+                               self._vagrant_file_name(boxname))
         if isdir(boxpath):
             logger.info("attempting to remove box '%s' by deleting: %s",
                         boxname, boxpath)
@@ -295,11 +302,13 @@ class FDroidBuildVm():
         """
         import paramiko
         try:
-            _check_call(['vagrant ssh-config > sshconfig'],
-                        cwd=self.srvdir, shell=True)
+            sshconfig_path = os.path.join(self.srvdir, 'sshconfig')
+            with open(sshconfig_path, 'wb') as fp:
+                fp.write(_check_output(['vagrant', 'ssh-config'],
+                                       cwd=self.srvdir))
             vagranthost = 'default'  # Host in ssh config file
             sshconfig = paramiko.SSHConfig()
-            with open(joinpath(self.srvdir, 'sshconfig'), 'r') as f:
+            with open(sshconfig_path, 'r') as f:
                 sshconfig.parse(f)
             sshconfig = sshconfig.lookup(vagranthost)
             idfile = sshconfig['identityfile']
@@ -366,11 +375,11 @@ class LibvirtBuildVm(FDroidBuildVm):
         if storagePool:
 
             if isfile('metadata.json'):
-                rmfile('metadata.json')
+                os.remove('metadata.json')
             if isfile('Vagrantfile'):
-                rmfile('Vagrantfile')
+                os.remove('Vagrantfile')
             if isfile('box.img'):
-                rmfile('box.img')
+                os.remove('box.img')
 
             logger.debug('preparing box.img for box %s', output)
             vol = storagePool.storageVolLookupByName(self.srvname + '.img')
@@ -420,9 +429,9 @@ class LibvirtBuildVm(FDroidBuildVm):
 
             if not keep_box_file:
                 logger.debug('box packaging complete, removing temporary files.')
-                rmfile('metadata.json')
-                rmfile('Vagrantfile')
-                rmfile('box.img')
+                os.remove('metadata.json')
+                os.remove('Vagrantfile')
+                os.remove('box.img')
 
         else:
             logger.warn('could not connect to storage-pool \'default\',' +