# 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
from logging import getLogger
from fdroidserver import _
+import threading
+
+lock = threading.Lock()
logger = getLogger('fdroidserver-vmtools')
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):
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)
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))
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.
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)
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
_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)
"""
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']
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')
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\',' +