mirror of
https://github.com/kevingruesser/bootstrap-vz.git
synced 2025-08-22 09:50:37 +00:00
VirtualBox integration
This commit is contained in:
parent
0f8dbb7ac3
commit
65b9e10ce3
10 changed files with 188 additions and 53 deletions
|
@ -34,7 +34,7 @@ class SSHRPCManager(object):
|
|||
'-R' + str(self.remote_callback_port) + ':localhost:' + str(self.local_callback_port),
|
||||
self.settings['username'] + '@' + self.settings['address'],
|
||||
'--',
|
||||
'sudo', self.settings['server-bin'],
|
||||
'sudo', self.settings['server_bin'],
|
||||
'--listen', str(self.remote_server_port)]
|
||||
import sys
|
||||
self.ssh_process = subprocess.Popen(args=ssh_cmd, stdout=sys.stderr, stderr=sys.stderr)
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
---
|
||||
virtualbox:
|
||||
guest_additions: /root/images/VBoxGuestAdditions.iso
|
|
@ -1,4 +0,0 @@
|
|||
from bootstrapvz.common.tools import load_data
|
||||
|
||||
# tox makes sure that the cwd is the project root
|
||||
build_settings = load_data('build_settings.yml')
|
|
@ -1,21 +0,0 @@
|
|||
|
||||
|
||||
class Image(object):
|
||||
|
||||
def create_instance(self):
|
||||
return Instance()
|
||||
|
||||
def destroy(self):
|
||||
pass
|
||||
|
||||
|
||||
class Instance(object):
|
||||
|
||||
def boot(self):
|
||||
pass
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def destroy(self):
|
||||
pass
|
|
@ -1,6 +1,7 @@
|
|||
from bootstrapvz.common.tools import load_data
|
||||
from build_servers import LocalBuildServer
|
||||
from build_servers import RemoteBuildServer
|
||||
|
||||
build_servers = load_data('build_servers.yml')
|
||||
|
||||
# Snatched from here: http://stackoverflow.com/a/7205107
|
||||
def merge_dicts(*args):
|
||||
|
@ -21,20 +22,30 @@ def merge_dicts(*args):
|
|||
return reduce(merge, args, {})
|
||||
|
||||
|
||||
def bootstrap(manifest):
|
||||
# if 'build_host' in build_settings:
|
||||
# run = get_remote_run(build_settings)
|
||||
# else:
|
||||
# run = __import__('bootstrapvz.base.run')
|
||||
# run(manifest)
|
||||
from bootstrapvz.base.remote.remote import run
|
||||
run(manifest,
|
||||
build_servers['virtualbox'],
|
||||
debug=True,
|
||||
dry_run=True)
|
||||
def pick_build_server(manifest):
|
||||
if manifest['provider']['name'] == 'ec2':
|
||||
img_type = 'ec2-' + manifest['volume']['backing']
|
||||
else:
|
||||
img_type = manifest['provider']['name']
|
||||
|
||||
from ..image import Image
|
||||
return Image()
|
||||
# tox makes sure that the cwd is the project root
|
||||
build_servers = load_data('build_servers.yml')
|
||||
settings = next((server for name, server in build_servers.iteritems() if img_type in server['can_bootstrap']), None)
|
||||
if settings['type'] == 'local':
|
||||
return LocalBuildServer(settings)
|
||||
else:
|
||||
return RemoteBuildServer(settings)
|
||||
|
||||
def test_instance(instance):
|
||||
|
||||
def bootstrap(manifest, build_server):
|
||||
if isinstance(build_server, LocalBuildServer):
|
||||
from bootstrapvz.base.main import run
|
||||
bootstrap_info = run(manifest)
|
||||
else:
|
||||
from bootstrapvz.base.remote.remote import run
|
||||
bootstrap_info = run(manifest, build_server.settings)
|
||||
return bootstrap_info
|
||||
|
||||
|
||||
def test(instance):
|
||||
pass
|
||||
|
|
40
tests/integration/tools/build_servers.py
Normal file
40
tests/integration/tools/build_servers.py
Normal file
|
@ -0,0 +1,40 @@
|
|||
from bootstrapvz.common.tools import log_check_call
|
||||
|
||||
|
||||
class BuildServer(object):
|
||||
|
||||
def __init__(self, settings):
|
||||
self.settings = settings
|
||||
self.build_settings = settings.get('build_settings', None)
|
||||
self.can_bootstrap = settings['can_bootstrap']
|
||||
self.release = settings.get('release', None)
|
||||
|
||||
|
||||
class LocalBuildServer(BuildServer):
|
||||
pass
|
||||
|
||||
|
||||
class RemoteBuildServer(BuildServer):
|
||||
|
||||
def __init__(self, settings):
|
||||
self.address = settings['address']
|
||||
self.port = settings['port']
|
||||
self.username = settings['username']
|
||||
self.password = settings['password']
|
||||
self.root_password = settings['root_password']
|
||||
self.keyfile = settings['keyfile']
|
||||
self.server_bin = settings['server_bin']
|
||||
super(RemoteBuildServer, self).__init__(settings)
|
||||
|
||||
def download(self, src, dst):
|
||||
src_arg = '{user}@{host}:{path}'.format(self.username, self.address, src)
|
||||
log_check_call(['scp', '-i', self.keyfile, '-P', self.port,
|
||||
src_arg, dst])
|
||||
|
||||
def delete(self, path):
|
||||
ssh_cmd = ['ssh', '-i', self.settings['keyfile'],
|
||||
'-p', str(self.settings['port']),
|
||||
self.username + '@' + self.address,
|
||||
'--',
|
||||
'sudo', 'rm', path]
|
||||
log_check_call(ssh_cmd)
|
25
tests/integration/tools/images.py
Normal file
25
tests/integration/tools/images.py
Normal file
|
@ -0,0 +1,25 @@
|
|||
|
||||
|
||||
class Image(object):
|
||||
|
||||
def __init__(self, manifest):
|
||||
self.manifest = manifest
|
||||
|
||||
def destroy(self):
|
||||
pass
|
||||
|
||||
|
||||
class VirtualBoxImage(Image):
|
||||
|
||||
def __init__(self, manifest, image_path):
|
||||
super(VirtualBoxImage, self).__init__(manifest)
|
||||
self.image_path = image_path
|
||||
self.medium = self.vbox.open_medium(location=self.image.image_path,
|
||||
decive_type=self.vbox.library.DeviceType.HardDisk,
|
||||
access_mode=self.vbox.library.AccessMode.read_only,
|
||||
force_new_uuid=False)
|
||||
|
||||
def destroy(self):
|
||||
self.medium.delete_storage()
|
||||
import os
|
||||
os.remove(self.image_path)
|
69
tests/integration/tools/instances.py
Normal file
69
tests/integration/tools/instances.py
Normal file
|
@ -0,0 +1,69 @@
|
|||
from bootstrapvz.common.tools import log_check_call
|
||||
|
||||
|
||||
class Instance(object):
|
||||
|
||||
def __init__(self, name, image):
|
||||
self.name = name
|
||||
self.image = image
|
||||
|
||||
def boot(self):
|
||||
pass
|
||||
|
||||
def shutdown(self):
|
||||
pass
|
||||
|
||||
def destroy(self):
|
||||
pass
|
||||
|
||||
|
||||
class VirtualBoxInstance(Instance):
|
||||
|
||||
cpus = 1
|
||||
memory = 256
|
||||
|
||||
def __init__(self, name, image):
|
||||
super(VirtualBoxInstance, self).__init__(name, image)
|
||||
import virtualbox
|
||||
self.vbox = virtualbox.VirtualBox()
|
||||
|
||||
def create(self):
|
||||
if self.image.manifest['system']['architecture'] == 'x86':
|
||||
os_type = 'Debian'
|
||||
else:
|
||||
os_type = 'Debian_64'
|
||||
self.machine = self.vbox.create_machine(settings_file='', name=self.name,
|
||||
groups=[], os_type_id=os_type, flags='')
|
||||
self.machine.save_settings()
|
||||
self.machine.cpu_count = self.cpus
|
||||
self.machine.memory_size = self.memory
|
||||
self.machine.attach_device(name='root', controller_port=0, device=0,
|
||||
type_p=self.vbox.library.DeviceType.HardDisk,
|
||||
medium=self.image.medium)
|
||||
self.vbox.register_machine(self.machine)
|
||||
# [self.uuid] = log_check_call(['VBoxManage', 'createvm'
|
||||
# '--name', self.name])
|
||||
# log_check_call(['VBoxManage', 'modifyvm', self.uuid,
|
||||
# '--cpus', self.cpus,
|
||||
# '--memory', self.memory])
|
||||
# log_check_call(['VBoxManage', 'storageattach', self.uuid,
|
||||
# '--storagectl', '"SATA Controller"',
|
||||
# '--device', '0',
|
||||
# '--port', '0',
|
||||
# '--type', 'hdd',
|
||||
# '--medium', self.image.image_path])
|
||||
|
||||
def boot(self):
|
||||
self.session = self.vbox.Session()
|
||||
self.machine.launch_vm_process(self.session, 'headless')
|
||||
# log_check_call(['VBoxManage', 'startvm', self.uuid,
|
||||
# '--type', 'headless'])
|
||||
|
||||
def shutdown(self):
|
||||
self.session.console.power_down()
|
||||
log_check_call(['VBoxManage', 'stopvm', self.uuid,
|
||||
'--type', 'headless'])
|
||||
|
||||
def destroy(self):
|
||||
self.machine.unregister(self.vbox.CleanupMode.full)
|
||||
self.machine.remove(delete=True)
|
|
@ -1,6 +1,5 @@
|
|||
import tools
|
||||
from manifests import partials
|
||||
from . import build_settings
|
||||
|
||||
|
||||
def test_virtualbox_unpartitioned_extlinux():
|
||||
|
@ -8,22 +7,40 @@ def test_virtualbox_unpartitioned_extlinux():
|
|||
specific_settings = yaml.load("""
|
||||
provider:
|
||||
name: virtualbox
|
||||
guest_additions: {guest_additions}
|
||||
system:
|
||||
bootloader: extlinux
|
||||
volume:
|
||||
backing: vdi
|
||||
partitions:
|
||||
type: msdos
|
||||
""".format(guest_additions=build_settings['virtualbox']['guest_additions']))
|
||||
""")
|
||||
manifest = tools.merge_dicts(partials['base'], partials['stable64'],
|
||||
partials['unpartitioned'], specific_settings)
|
||||
|
||||
image = tools.bootstrap(manifest)
|
||||
instance = image.create_instance()
|
||||
instance.boot()
|
||||
build_server = tools.pick_build_server(manifest)
|
||||
manifest['provider']['guest_additions'] = build_server.build_settings['guest_additions']
|
||||
|
||||
tools.test_instance(instance)
|
||||
bootstrap_info = tools.bootstrap(manifest, build_server)
|
||||
|
||||
instance.destroy()
|
||||
image.destroy()
|
||||
if isinstance(build_server, tools.build_servers.LocalBuildServer):
|
||||
image_path = bootstrap_info.volume.image_path
|
||||
else:
|
||||
import tempfile
|
||||
handle, image_path = tempfile.mkstemp()
|
||||
handle.close()
|
||||
build_server.download(bootstrap_info.volume.image_path, image_path)
|
||||
build_server.delete(bootstrap_info.volume.image_path)
|
||||
|
||||
try:
|
||||
image = tools.images.VirtualBoxImage(manifest, image_path)
|
||||
|
||||
instance = tools.instances.VirtualBoxInstance(image)
|
||||
instance.create()
|
||||
instance.boot()
|
||||
|
||||
tools.test(instance)
|
||||
finally:
|
||||
if 'instance' in locals():
|
||||
instance.destroy()
|
||||
if 'image' in locals():
|
||||
image.destroy()
|
||||
|
|
1
tox.ini
1
tox.ini
|
@ -19,6 +19,7 @@ commands = nosetests -v tests/unit --with-coverage --cover-package=bootstrapvz -
|
|||
deps =
|
||||
nose
|
||||
Pyro4 >= 4.26
|
||||
pyvbox >= 0.2.0
|
||||
commands = nosetests -v tests/integration --with-coverage --cover-package=bootstrapvz --cover-inclusive
|
||||
|
||||
[testenv:docs]
|
||||
|
|
Loading…
Add table
Reference in a new issue