makebuildserver: package up KVM VM as a vagrant box

`vagrant package` does not work with KVM, so we have to hack together our
own until someone implements it (suppose we should do it). This is a hacked
up version based on:
d7d440ea8f/tools/create_box.sh

#238
This commit is contained in:
Hans-Christoph Steiner 2017-02-14 22:58:35 +01:00
parent 988ac21e7f
commit 69e4b91d3f

View file

@ -4,9 +4,11 @@ import os
import pathlib import pathlib
import re import re
import requests import requests
import shutil
import stat import stat
import sys import sys
import subprocess import subprocess
import tarfile
import vagrant import vagrant
import hashlib import hashlib
import yaml import yaml
@ -56,6 +58,7 @@ if os.path.isfile('/usr/bin/systemd-detect-virt'):
if virt == 'qemu' or virt == 'kvm' or virt == 'bochs': if virt == 'qemu' or virt == 'kvm' or virt == 'bochs':
print('Running in a VM guest, defaulting to QEMU/KVM via libvirt') print('Running in a VM guest, defaulting to QEMU/KVM via libvirt')
config['vm_provider'] = 'libvirt' config['vm_provider'] = 'libvirt'
config['domain'] = 'buildserver_default'
elif virt != 'none': elif virt != 'none':
print('Running in an unsupported VM guest (' + virt + ')!') print('Running in an unsupported VM guest (' + virt + ')!')
@ -302,9 +305,8 @@ def destroy_current_image(v, serverdir):
if config['vm_provider'] == 'libvirt': if config['vm_provider'] == 'libvirt':
import libvirt import libvirt
try: try:
domain = 'buildserver_default'
virConnect = libvirt.open('qemu:///system') virConnect = libvirt.open('qemu:///system')
virDomain = virConnect.lookupByName(domain) virDomain = virConnect.lookupByName(config['domain'])
if virDomain: if virDomain:
virDomain.undefineFlags(libvirt.VIR_DOMAIN_UNDEFINE_MANAGED_SAVE virDomain.undefineFlags(libvirt.VIR_DOMAIN_UNDEFINE_MANAGED_SAVE
| libvirt.VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA | libvirt.VIR_DOMAIN_UNDEFINE_SNAPSHOTS_METADATA
@ -317,6 +319,52 @@ def destroy_current_image(v, serverdir):
print(e) print(e)
def kvm_package(boxfile):
'''
Hack to replace missing `vagrant package` for kvm, based on the script
`tools/create_box.sh from vagrant-libvirt
'''
import libvirt
virConnect = libvirt.open('qemu:///system')
storagePool = virConnect.storagePoolLookupByName('default')
if storagePool:
vol = storagePool.storageVolLookupByName(config['domain'] + '.img')
imagepath = vol.path()
# TODO use a libvirt storage pool to ensure the img file is readable
subprocess.check_call(['sudo', '/bin/chmod', '-R', 'a+rX', '/var/lib/libvirt/images'])
shutil.copy2(imagepath, 'box.img')
subprocess.check_call(['qemu-img', 'rebase', '-p', '-b', '', 'box.img'])
metadata = """{
"provider": "libvirt",
"format": "qcow2",
"virtual_size": 1000
}
"""
vagrantfile = """Vagrant.configure("2") do |config|
config.vm.provider :libvirt do |libvirt|
libvirt.driver = "kvm"
libvirt.host = ""
libvirt.connect_via_ssh = false
libvirt.storage_pool_name = "default"
end
end
"""
with open('metadata.json', 'w') as fp:
fp.write(metadata)
with open('Vagrantfile', 'w') as fp:
fp.write(vagrantfile)
with tarfile.open(boxfile, 'w:gz') as tar:
tar.add('metadata.json')
tar.add('Vagrantfile')
tar.add('box.img')
os.remove('metadata.json')
os.remove('Vagrantfile')
os.remove('box.img')
def run_via_vagrant_ssh(v, cmdlist): def run_via_vagrant_ssh(v, cmdlist):
if (isinstance(cmdlist, str) or isinstance(cmdlist, bytes)): if (isinstance(cmdlist, str) or isinstance(cmdlist, bytes)):
cmd = cmdlist cmd = cmdlist
@ -493,7 +541,11 @@ def main():
boxfile = os.path.join(os.getcwd(), 'buildserver.box') boxfile = os.path.join(os.getcwd(), 'buildserver.box')
if os.path.exists(boxfile): if os.path.exists(boxfile):
os.remove(boxfile) os.remove(boxfile)
v.package(output=boxfile)
if config['vm_provider'] == 'libvirt':
kvm_package(boxfile)
else:
v.package(output=boxfile)
print("Adding box") print("Adding box")
v.box_add('buildserver', boxfile, force=True) v.box_add('buildserver', boxfile, force=True)