1
0
mirror of https://gitlab.com/fdroid/fdroidserver.git synced 2024-09-15 17:50:10 +02:00

auto-lookup vm provider based on available executables; more fault tolerant vagrant package

This commit is contained in:
Michael Pöhn 2017-04-01 12:27:26 +02:00 committed by Hans-Christoph Steiner
parent bba6b8ab0a
commit 8abd3f1cbc

View File

@ -31,6 +31,16 @@ from logging import getLogger
logger = getLogger('fdroidserver-vmtools')
def _check_call(cmd, shell=False):
logger.debug(' '.join(cmd))
return subprocess.check_call(cmd, shell=shell)
def _check_output(cmd, shell=False):
logger.debug(' '.join(cmd))
return subprocess.check_output(cmd, shell=shell)
def get_build_vm(srvdir, provider=None):
"""Factory function for getting FDroidBuildVm instances.
@ -43,6 +53,8 @@ def get_build_vm(srvdir, provider=None):
:returns: FDroidBuildVm instance.
"""
abssrvdir = abspath(srvdir)
# use supplied provider
if provider:
if provider == 'libvirt':
logger.debug('build vm provider \'libvirt\' selected')
@ -52,6 +64,32 @@ def get_build_vm(srvdir, provider=None):
return VirtualboxBuildVm(abssrvdir)
else:
logger.warn('build vm provider not supported: \'%s\'', provider)
# try guessing provider from installed software
try:
kvm_installed = 0 == _check_call(['which', 'kvm'])
except subprocess.CalledProcessError:
kvm_installed = False
try:
kvm_installed |= 0 == _check_call(['which', 'qemu'])
except subprocess.CalledProcessError:
pass
try:
vbox_installed = 0 == _check_call(['which', 'VBoxHeadless'], shell=True)
except subprocess.CalledProcessError:
vbox_installed = False
if kvm_installed and vbox_installed:
logger.debug('both kvm and vbox are installed.')
elif kvm_installed:
logger.debug('libvirt is the sole installed and supported vagrant provider, selecting \'libvirt\'')
return LibvirtBuildVm(abssrvdir)
elif vbox_installed:
logger.debug('virtualbox is the sole installed and supported vagrant provider, selecting \'virtualbox\'')
return VirtualboxBuildVm(abssrvdir)
else:
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',
@ -128,12 +166,16 @@ class FDroidBuildVm():
except Exception as e:
logger.debug("could not delete vagrant dir: %s, %s", vgrntdir, e)
try:
self._check_call(['vagrant', 'global-status', '--prune'])
_check_call(['vagrant', 'global-status', '--prune'])
except subprocess.CalledProcessError as e:
logger.debug('pruning global vagrant status failed: %s', e)
def package(self, output=None, keep_box_file=None):
self.vgrnt.package(output=output)
def package(self, output=None, vagrantfile=None, keep_box_file=None):
previous_tmp_dir = joinpath(self.srvdir, '_tmp_package')
if isdir(previous_tmp_dir):
logger.info('found previous vagrant package temp dir \'%s\', deleting it', previous_tmp_dir)
shutil.rmtree(previous_tmp_dir)
self.vgrnt.package(output=output, vagrantfile=vagrantfile)
def box_add(self, boxname, boxfile, force=True):
"""Add vagrant box to vagrant.
@ -149,20 +191,12 @@ class FDroidBuildVm():
def box_remove(self, boxname):
try:
self._check_call(['vagrant', 'box', 'remove', '--all', '--force', boxname])
_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)
# TODO: remove box files manually
# nesessary when Vagrantfile in ~/.vagrant.d/... is broken.
def _check_call(self, cmd, shell=False):
logger.debug(' '.join(cmd))
return subprocess.check_call(cmd, shell=shell)
def _check_output(self, cmd, shell=False):
logger.debug(' '.join(cmd))
return subprocess.check_output(cmd, shell=shell)
class LibvirtBuildVm(FDroidBuildVm):
def __init__(self, srvdir):
@ -182,7 +216,7 @@ class LibvirtBuildVm(FDroidBuildVm):
# this is way more easy and therefore fault tolerant.
# (eg. lookupByName only works on running VMs)
try:
self._check_call(('virsh', '-c', 'qemu:///system', 'destroy', self.srvname))
_check_call(('virsh', '-c', 'qemu:///system', 'destroy', self.srvname))
logger.info("...waiting a sec...")
time.sleep(10)
except subprocess.CalledProcessError as e:
@ -190,7 +224,7 @@ class LibvirtBuildVm(FDroidBuildVm):
try:
# libvirt python bindings do not support all flags required
# for undefining domains correctly.
self._check_call(('virsh', '-c', 'qemu:///system', 'undefine', self.srvname, '--nvram', '--managed-save', '--remove-all-storage', '--snapshots-metadata'))
_check_call(('virsh', '-c', 'qemu:///system', 'undefine', self.srvname, '--nvram', '--managed-save', '--remove-all-storage', '--snapshots-metadata'))
logger.info("...waiting a sec...")
time.sleep(10)
except subprocess.CalledProcessError as e:
@ -217,10 +251,10 @@ class LibvirtBuildVm(FDroidBuildVm):
vol = storagePool.storageVolLookupByName(self.srvname + '.img')
imagepath = vol.path()
# TODO use a libvirt storage pool to ensure the img file is readable
self._check_call(['sudo', '/bin/chmod', '-R', 'a+rX', '/var/lib/libvirt/images'])
_check_call(['sudo', '/bin/chmod', '-R', 'a+rX', '/var/lib/libvirt/images'])
shutil.copy2(imagepath, 'box.img')
self._check_call(['qemu-img', 'rebase', '-p', '-b', '', 'box.img'])
img_info_raw = self._check_output(['qemu-img', 'info', '--output=json', 'box.img'])
_check_call(['qemu-img', 'rebase', '-p', '-b', '', 'box.img'])
img_info_raw = _check_output(['qemu-img', 'info', '--output=json', 'box.img'])
img_info = json.loads(img_info_raw.decode('utf-8'))
metadata = {"provider": "libvirt",
"format": img_info['format'],
@ -258,7 +292,7 @@ class LibvirtBuildVm(FDroidBuildVm):
def box_remove(self, boxname):
super().box_remove(boxname)
try:
self._check_call(['virsh', '-c', 'qemu:///system', 'vol-delete', '--pool', 'default', '%s_vagrant_box_image_0.img' % (boxname)])
_check_call(['virsh', '-c', 'qemu:///system', 'vol-delete', '--pool', 'default', '%s_vagrant_box_image_0.img' % (boxname)])
except subprocess.CalledProcessError as e:
logger.info('tired removing \'%s\', file was not present in first place: %s', boxname, e)