chiark / gitweb /
added box handling to vmtools
authorHans-Christoph Steiner <hans@eds.org>
Mon, 22 May 2017 15:14:48 +0000 (17:14 +0200)
committerHans-Christoph Steiner <hans@eds.org>
Tue, 23 May 2017 18:06:06 +0000 (20:06 +0200)
fdroidserver/vmtools.py
makebuildserver

index c64e99940d12cbeacaecf283b99618e4d7fefe4a..5eedbaa7abb6ff3bf89e1b18f9f7a0235b460c29 100644 (file)
@@ -105,6 +105,9 @@ class FDroidBuildVm():
         except subprocess.CalledProcessError as e:
             logger.info('could not bring vm up: %s', e)
 
+    def halt(self):
+        self.vgrnt.halt(force=True)
+
     def destroy(self):
         """Remove every trace of this VM from the system.
 
@@ -125,13 +128,37 @@ class FDroidBuildVm():
         except Exception as e:
             logger.debug("could not delete vagrant dir: %s, %s", vgrntdir, e)
         try:
-            subprocess.check_call(['vagrant', 'global-status', '--prune'])
+            self._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 box_add(self, boxname, boxfile, force=True):
+        """Add vagrant box to vagrant.
+
+        :param boxname: name assigned to local deployment of box
+        :param boxfile: path to box file
+        :param force: overwrite existing box image (default: True)
+        """
+        boxfile = abspath(boxfile)
+        if not isfile(boxfile):
+            raise FDroidBuildVmException('supplied boxfile \'%s\' does not exist', boxfile)
+        self.vgrnt.box_add(boxname, abspath(boxfile), force=force)
+
+    def box_remove(self, boxname):
+        try:
+            self._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):
+        logger.debug(' '.join(cmd))
+        return subprocess.check_call(cmd)
+
 
 class LibvirtBuildVm(FDroidBuildVm):
     def __init__(self, srvdir):
@@ -141,7 +168,7 @@ class LibvirtBuildVm(FDroidBuildVm):
         try:
             self.conn = libvirt.open('qemu:///system')
         except libvirt.libvirtError as e:
-            logger.critical('could not connect to libvirtd: %s', e)
+            raise FDroidBuildVmException('could not connect to libvirtd: %s' % (e))
 
     def destroy(self):
 
@@ -151,8 +178,7 @@ class LibvirtBuildVm(FDroidBuildVm):
         # this is way more easy and therefore fault tolerant.
         # (eg. lookupByName only works on running VMs)
         try:
-            logger.debug('virsh -c qemu:///system destroy %s', self.srvname)
-            subprocess.check_call(('virsh', '-c', 'qemu:///system', 'destroy', self.srvname))
+            self._check_call(('virsh', '-c', 'qemu:///system', 'destroy', self.srvname))
             logger.info("...waiting a sec...")
             time.sleep(10)
         except subprocess.CalledProcessError as e:
@@ -160,14 +186,13 @@ class LibvirtBuildVm(FDroidBuildVm):
         try:
             # libvirt python bindings do not support all flags required
             # for undefining domains correctly.
-            logger.debug('virsh -c qemu:///system undefine %s --nvram --managed-save --remove-all-storage --snapshots-metadata', self.srvname)
-            subprocess.check_call(('virsh', '-c', 'qemu:///system', 'undefine', self.srvname, '--nvram', '--managed-save', '--remove-all-storage', '--snapshots-metadata'))
+            self._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:
             logger.info("could not undefine libvirt domain '%s': %s", self.srvname, e)
 
-    def package(self, output=None, keep_box_file=False):
+    def package(self, output=None, vagrantfile=None, keep_box_file=False):
         if not output:
             output = "buildserver.box"
             logger.debug('no output name set for packaging \'%s\',' +
@@ -197,20 +222,9 @@ class LibvirtBuildVm(FDroidBuildVm):
                         "virtual_size": math.ceil(img_info['virtual-size'] / (1024. ** 3)) + 1,
                         }
 
-            vagrantfile = """Vagrant.configure("2") do |config|
-  config.ssh.username = "vagrant"
-  config.ssh.password = "vagrant"
-
-  config.vm.provider :libvirt do |libvirt|
-
-    libvirt.driver = "kvm"
-    libvirt.host = ""
-    libvirt.connect_via_ssh = false
-    libvirt.storage_pool_name = "default"
+            if not vagrantfile:
+                vagrantfile = 'Vagrant.configure("2") do |config|\nend'
 
-  end
-end
-"""
             with open('metadata.json', 'w') as fp:
                 fp.write(json.dumps(metadata))
             with open('Vagrantfile', 'w') as fp:
@@ -230,6 +244,13 @@ end
             logger.warn('could not connect to storage-pool \'default\',' +
                         'skipping packaging buildserver box')
 
+    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)])
+        except subprocess.CalledProcessError as e:
+            logger.info('tired removing \'%s\', file was not present in first place: %s', boxname, e)
+
 
 class VirtualboxBuildVm(FDroidBuildVm):
     pass
index 469e8f1c5de908a95a63bf9c528ce7381a5d1d9e..c88d665a47f1ce771b5ed810edc717e4565a51f3 100755 (executable)
@@ -12,6 +12,7 @@ import hashlib
 import yaml
 import json
 import logging
+import textwrap
 from clint.textui import progress
 from optparse import OptionParser
 import fdroidserver.tail
@@ -525,12 +526,27 @@ def main():
     if os.path.exists(boxfile):
         os.remove(boxfile)
 
-    vm.package(output=boxfile, debug_keep_box_file=options.debug_keep_box_file)
+    vagrantfile = textwrap.dedent("""\
+                  Vagrant.configure("2") do |config|
+                    config.ssh.username = "vagrant"
+                    config.ssh.password = "vagrant"
+
+                    config.vm.provider :libvirt do |libvirt|
+
+                      libvirt.driver = "kvm"
+                      libvirt.host = ""
+                      libvirt.connect_via_ssh = false
+                      libvirt.storage_pool_name = "default"
+
+                    end
+                  end""")
+
+    vm.package(output=boxfile, vagrantfile=vagrantfile, keep_box_file=options.keep_box_file)
 
     logger.info("Adding box")
-    v.box_add('buildserver', boxfile, force=True)
+    vm.box_add('buildserver', boxfile, force=True)
 
-    if not 'buildserver' in subprocess.check_output(['vagrant', 'box', 'list']).decode('utf-8'):
+    if 'buildserver' not in subprocess.check_output(['vagrant', 'box', 'list']).decode('utf-8'):
         logger.critical('could not add box \'%s\' as \'buildserver\', terminating', boxfile)
         sys.exit(1)