diff options
author | Lars Wirzenius <lars.wirzenius@codethink.co.uk> | 2013-01-24 15:41:11 +0000 |
---|---|---|
committer | Lars Wirzenius <lars.wirzenius@codethink.co.uk> | 2013-02-06 20:58:46 +0000 |
commit | dfd854a0c1ce312ec20b91762be9a344d9c47417 (patch) | |
tree | 75d74bc59577de2d4dea965896eab6dc146c490e /morphlib | |
parent | a77e0639a0b5521105e0bdc4d8021ee99de8f72f (diff) | |
download | morph-dfd854a0c1ce312ec20b91762be9a344d9c47417.tar.gz |
Add a write extension for kvm+libvirt
Diffstat (limited to 'morphlib')
-rwxr-xr-x | morphlib/exts/kvm.write | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/morphlib/exts/kvm.write b/morphlib/exts/kvm.write new file mode 100755 index 00000000..ed85b17e --- /dev/null +++ b/morphlib/exts/kvm.write @@ -0,0 +1,140 @@ +#!/usr/bin/python +# Copyright (C) 2012-2013 Codethink Limited +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + + +'''A Morph deployment write extension for deploying to KVM+libvirt.''' + + +import os +import re +import urlparse + +import morphlib.writeexts + + +class KvmPlusSshWriteExtension(morphlib.writeexts.WriteExtension): + + '''Create a KVM/LibVirt virtual machine during Morph's deployment. + + The location command line argument is the pathname of the disk image + to be created. The user is expected to provide the location argument + using the following syntax: + + kvm+ssh://HOST/GUEST/PATH + + where: + + * HOST is the host on which KVM/LibVirt is running + * GUEST is the name of the guest virtual machine on that host + * PATH is the path to the disk image that should be created, + on that host + + The extension will connect to HOST via ssh to run libvirt's + command line management tools. + + ''' + + def process_args(self, args): + if len(args) != 2: + raise cliapp.AppException('Wrong number of command line args') + + temp_root, location = args + ssh_host, vm_name, vm_path = self.parse_location(location) + + self.status( + msg='Temporary system root: %(temp_root)s', + temp_root=temp_root) + self.status( + msg='libvirt server: %(ssh_host)s', + ssh_host=ssh_host) + self.status( + msg='libvirt guest: %(vm_name)s', + vm_name=vm_name) + self.status( + msg='libvirt disk image: %(vm_path)s', + vm_path=vm_path) + + size = self.get_disk_size() + self.status(msg='Disk size is %(size)d bytes', size=size) + + raw_disk = tempfile.mkstemp() + self.create_raw_disk_image(raw_disk, size) + try: + self.mkfs_btrfs(raw_disk) + mp = self.mount(raw_disk) + except BaseException: + self.status(msg='EEEK') + os.remove(raw_disk) + raise + try: + self.create_factory(mp, temp_root) + self.create_fstab(mp) + self.install_extlinux(mp) + except BaseException, e: + self.status(msg='EEK') + self.unmount(mp) + os.remove(raw_disk) + raise + else: + self.unmount(mp) + + try: + self.transfer(raw_disk, size, ssh_host, vm_path) + self.create_libvirt_guest(ssh_host, vm_name, vm_path) + except BaseException: + self.status(msg='EEEK') + os.remove(raw_disk) + raise + else: + os.remove(raw_disk) + + self.status( + msg='Virtual machine %(vm_name)s has been created', + vm_name=vm_name) + + def parse_location(self, location): + '''Parse the location argument to get relevant data.''' + + x = urlparse.urlparse(location) + if x.scheme != 'kvm+ssh': + raise cliapp.AppException( + 'URL schema must be vbox+ssh in %s' % location) + m = re.match('^/(?P<guest>[^/]+)(?P<path>/.+)$', x.path) + if not m: + raise cliapp.AppException('Cannot parse location %s' % location) + return x.netloc, m.group('guest'), m.group('path') + + def transfer(self, raw_disk, size, ssh_host, vm_path): + '''Transfer raw disk image to libvirt host.''' + + self.status(msg='Transfer disk image') + target = '%s:%s' % (ssh_host, vm_path) + with open(raw_disk, 'rb') as f: + cliapp.runcmd(['rsync', '-zS', raw_disk, target]) + + def create_libvirt_guest(self, ssh_host, vm_name, vm_path): + '''Create the libvirt virtual machine.''' + + self.status(msg='Create libvirt/kvm virtual machine') + cliapp.runcmd( + ['ssh', ssh_host, + 'virt-install', '--connect qemu:///system', '--import', + '--name', vm_name, '--ram', '1024', '--vnc', '--noreboot', + '--disk path=%s,bus=ide' % vm_path]) + + +KvmPlusSshWriteExtension().run() + |