Refactor. Locking a vbox is now quite a bit easier

This commit is contained in:
Anders Ingemann 2014-12-20 01:21:00 +01:00
parent 6f23bcaafc
commit 6a0bef147a
7 changed files with 165 additions and 115 deletions

View file

@ -0,0 +1,10 @@
class Image(object):
def __init__(self, manifest):
self.manifest = manifest
def destroy(self):
pass

View file

@ -0,0 +1,18 @@
from __future__ import absolute_import
from . import Image
import virtualbox as vboxapi
class VirtualBoxImage(Image):
def __init__(self, manifest, image_path):
super(VirtualBoxImage, self).__init__(manifest)
self.image_path = image_path
self.vbox = vboxapi.VirtualBox()
self.medium = self.vbox.open_medium(self.image_path, # location
vboxapi.library.DeviceType.hard_disk, # decive_type
vboxapi.library.AccessMode.read_only, # access_mode
False) # force_new_uuid
def destroy(self):
self.medium.close()

View file

@ -0,0 +1,16 @@
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

View file

@ -0,0 +1,95 @@
from __future__ import absolute_import
from . import Instance
import virtualbox as vboxapi
class VirtualBoxInstance(Instance):
cpus = 1
memory = 256
def __init__(self, name, image):
super(VirtualBoxInstance, self).__init__(name, image)
self.vbox = vboxapi.VirtualBox()
manager = vboxapi.Manager()
self.session = manager.get_session()
def create(self):
# create machine
os_type = {'x86': 'Debian',
'amd64': 'Debian_64'}.get(self.image.manifest.system['architecture'])
self.machine = self.vbox.create_machine(settings_file='', name=self.name,
groups=[], os_type_id=os_type, flags='')
self.machine.cpu_count = self.cpus
self.machine.memory_size = self.memory
self.machine.save_settings() # save settings, so that we can register it
self.vbox.register_machine(self.machine)
# attach image
with self.Lock(self.machine, self.session) as machine:
strg_ctrl = machine.add_storage_controller('SATA Controller',
vboxapi.library.StorageBus.sata)
strg_ctrl.port_count = 1
machine.attach_device(name='SATA Controller', controller_port=0, device=0,
type_p=vboxapi.library.DeviceType.hard_disk,
medium=self.image.medium)
machine.save_settings()
# redirect serial port
with self.Lock(self.machine, self.session) as machine:
serial_port = machine.get_serial_port(0)
serial_port.enabled = True
import tempfile
handle, self.serial_port_path = tempfile.mkstemp()
import os
os.close(handle)
serial_port.path = self.serial_port_path
serial_port.host_mode = vboxapi.library.PortMode.host_pipe
# serial_port.server = True
machine.save_settings()
def boot(self):
self.machine.launch_vm_process(self.session, 'headless').wait_for_completion(-1)
def shutdown(self):
self.session.console.power_down().wait_for_completion(-1)
self.Lock(self.machine, self.session).unlock()
def destroy(self):
if hasattr(self, 'machine'):
try:
with self.Lock(self.machine, self.session) as machine:
machine.detach_device(name='SATA Controller', controller_port=0, device=0)
machine.save_settings()
except vboxapi.library.VBoxErrorObjectNotFound:
pass
self.machine.unregister(vboxapi.library.CleanupMode.unregister_only)
self.machine.remove(delete=True)
class Lock(object):
def __init__(self, machine, session):
self.machine = machine
self.session = session
def __enter__(self):
return self.lock()
def __exit__(self, type, value, traceback):
return self.unlock()
def lock(self):
self.unlock()
self.machine.lock_machine(self.session, vboxapi.library.LockType.write)
return self.session.machine
def unlock(self):
from ..tools import waituntil
if self.machine.session_state == vboxapi.library.SessionState.unlocked:
return
if self.machine.session_state == vboxapi.library.SessionState.unlocking:
waituntil(lambda: self.machine.session_state == vboxapi.library.SessionState.unlocked)
return
if self.machine.session_state == vboxapi.library.SessionState.spawning:
waituntil(lambda: self.machine.session_state == vboxapi.library.SessionState.locked)
self.session.unlock_machine()
waituntil(lambda: self.machine.session_state == vboxapi.library.SessionState.unlocked)

View file

@ -1,25 +0,0 @@
import virtualbox
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.vbox = virtualbox.VirtualBox()
self.medium = self.vbox.open_medium(self.image_path, # location
virtualbox.library.DeviceType.hard_disk, # decive_type
virtualbox.library.AccessMode.read_only, # access_mode
False) # force_new_uuid
def destroy(self):
self.medium.close()

View file

@ -1,71 +0,0 @@
import virtualbox
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)
self.vbox = virtualbox.VirtualBox()
manager = virtualbox.Manager()
self.session = manager.get_session()
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.cpu_count = self.cpus
self.machine.memory_size = self.memory
self.machine.save_settings() # save settings, so that we can register it
self.vbox.register_machine(self.machine)
self.machine.lock_machine(self.session, virtualbox.library.LockType.write)
strg_ctrl = self.session.machine.add_storage_controller('SATA Controller',
virtualbox.library.StorageBus.sata)
strg_ctrl.port_count = 1
self.session.machine.attach_device(name='SATA Controller', controller_port=0, device=0,
type_p=virtualbox.library.DeviceType.hard_disk,
medium=self.image.medium)
self.session.machine.save_settings() # save changes to the controller
self._unlock_machine()
def boot(self):
self.machine.launch_vm_process(self.session, 'headless').wait_for_completion(-1)
def shutdown(self):
self.session.console.power_down().wait_for_completion(-1)
self._unlock_machine()
def destroy(self):
if hasattr(self, 'machine'):
self.machine.lock_machine(self.session, virtualbox.library.LockType.shared)
self.session.machine.detach_device(name='SATA Controller', controller_port=0, device=0)
self.session.machine.save_settings()
self._unlock_machine()
self.machine.unregister(virtualbox.library.CleanupMode.unregister_only)
self.machine.remove(delete=True)
def _unlock_machine(self):
from . import waituntil
self.session.unlock_machine()
waituntil(lambda: self.machine.session_state != virtualbox.library.SessionState.locked)

View file

@ -1,10 +1,10 @@
import tools import tools
import tools.images
import tools.instances
from manifests import partials from manifests import partials
from bootstrapvz.base.manifest import Manifest from bootstrapvz.base.manifest import Manifest
from bootstrapvz.remote.build_servers import pick_build_server from bootstrapvz.remote.build_servers import pick_build_server
from . import build_servers from . import build_servers
from images.virtualbox import VirtualBoxImage
from instances.virtualbox import VirtualBoxInstance
def test_virtualbox_unpartitioned_extlinux(): def test_virtualbox_unpartitioned_extlinux():
@ -19,42 +19,49 @@ volume:
partitions: partitions:
type: msdos type: msdos
""") """)
manifest_data = tools.merge_dicts(partials['base'], partials['stable64'], manifest_data = tools.merge_dicts(partials['base'], partials['stable64'], partials['unpartitioned'],
partials['unpartitioned'], partials['root_password'], partials['root_password'], partials['apt_proxy'],
manifest_data) manifest_data)
build_server = pick_build_server(build_servers, manifest_data) build_server = pick_build_server(build_servers, manifest_data)
manifest_data = build_server.apply_build_settings(manifest_data) manifest_data = build_server.apply_build_settings(manifest_data)
manifest = Manifest(data=manifest_data) manifest = Manifest(data=manifest_data)
bootstrap_info = tools.bootstrap(manifest, build_server) # bootstrap_info = tools.bootstrap(manifest, build_server)
from bootstrapvz.base.bootstrapinfo import BootstrapInformation
bootstrap_info = BootstrapInformation(manifest)
bootstrap_info.volume.image_path = '/target/debian-wheezy-amd64-141218.vdi'
from bootstrapvz.remote.build_servers import LocalBuildServer from bootstrapvz.remote.build_servers import LocalBuildServer
if isinstance(build_server, LocalBuildServer): if isinstance(build_server, LocalBuildServer):
image_path = bootstrap_info.volume.image_path image_path = bootstrap_info.volume.image_path
else: else:
import tempfile # import tempfile
handle, image_path = tempfile.mkstemp() # handle, image_path = tempfile.mkstemp()
import os # import os
os.close(handle) # os.close(handle)
build_server.download(bootstrap_info.volume.image_path, image_path) # build_server.download(bootstrap_info.volume.image_path, image_path)
build_server.delete(bootstrap_info.volume.image_path) # build_server.delete(bootstrap_info.volume.image_path)
image_path = '/Users/anders/Workspace/cloud/images/debian-wheezy-amd64-141130.vmdk'
image = VirtualBoxImage(manifest, image_path)
lines = []
try: try:
image = tools.images.VirtualBoxImage(manifest, image_path) instance = VirtualBoxInstance('unpartitioned_extlinux', image)
try: try:
instance = tools.instances.VirtualBoxInstance('unpartitioned_extlinux', image)
instance.create() instance.create()
try: try:
instance.boot() instance.boot()
lines = instance.get_console_output()
# tools.reachable_with_ssh(instance) # tools.reachable_with_ssh(instance)
finally: finally:
instance.shutdown() instance.shutdown()
finally: finally:
if 'instance' in locals():
instance.destroy() instance.destroy()
finally: finally:
if 'image' in locals(): # pass
image.destroy() if len(lines) > 0:
import os raise Exception('\n'.join(lines))
os.remove(image_path) # image.destroy()
# import os
# os.remove(image_path)