diff --git a/bootstrapvz/base/remote/ssh_rpc_manager.py b/bootstrapvz/base/remote/ssh_rpc_manager.py index 8d280f6..39fd037 100644 --- a/bootstrapvz/base/remote/ssh_rpc_manager.py +++ b/bootstrapvz/base/remote/ssh_rpc_manager.py @@ -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) diff --git a/build_settings.yml b/build_settings.yml deleted file mode 100644 index 87b0ba2..0000000 --- a/build_settings.yml +++ /dev/null @@ -1,3 +0,0 @@ ---- -virtualbox: - guest_additions: /root/images/VBoxGuestAdditions.iso diff --git a/tests/integration/__init__.py b/tests/integration/__init__.py index ed30250..e69de29 100644 --- a/tests/integration/__init__.py +++ b/tests/integration/__init__.py @@ -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') diff --git a/tests/integration/image/__init__.py b/tests/integration/image/__init__.py deleted file mode 100644 index 67bc2b1..0000000 --- a/tests/integration/image/__init__.py +++ /dev/null @@ -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 diff --git a/tests/integration/tools/__init__.py b/tests/integration/tools/__init__.py index d057444..dbe0446 100644 --- a/tests/integration/tools/__init__.py +++ b/tests/integration/tools/__init__.py @@ -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 diff --git a/tests/integration/tools/build_servers.py b/tests/integration/tools/build_servers.py new file mode 100644 index 0000000..c103624 --- /dev/null +++ b/tests/integration/tools/build_servers.py @@ -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) diff --git a/tests/integration/tools/images.py b/tests/integration/tools/images.py new file mode 100644 index 0000000..928338b --- /dev/null +++ b/tests/integration/tools/images.py @@ -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) diff --git a/tests/integration/tools/instances.py b/tests/integration/tools/instances.py new file mode 100644 index 0000000..075fc20 --- /dev/null +++ b/tests/integration/tools/instances.py @@ -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) diff --git a/tests/integration/virtualbox_tests.py b/tests/integration/virtualbox_tests.py index 3fc641a..21bc847 100644 --- a/tests/integration/virtualbox_tests.py +++ b/tests/integration/virtualbox_tests.py @@ -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() diff --git a/tox.ini b/tox.ini index 4529ea9..0b5ef44 100644 --- a/tox.ini +++ b/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]