salt/salt/modules/butterkvm.py

164 lines
5.1 KiB
Python

'''
Specialized routines used by the butter cloud component
'''
# Import salt modules
import virt
# Import python modules
import os
import shutil
import subprocess
import copy
import tempfile
def _place_image(image, vda):
'''
Moves the image file from the image pool into the final destination.
'''
image_d = image + '.d'
vda_dir = os.path.dirname(vda)
if not os.path.isdir(vda_dir):
os.makedirs(vda_dir)
if not os.path.isdir(image_d):
# No available images in the pool, copying fresh image
shutil.copy(image, vda)
return
images = os.listdir(image_d)
if not images:
# No available images in the pool, copying fresh image
shutil.copy(image, vda)
return
shutil.move(os.path.join(image_d, images[0]), vda)
creds = libvirt_creds()
if not os.path.isdir(vda_dir):
os.makedirs(vda_dir)
tdir = copy.deepcopy(vda_dir)
while not tdir == '/':
os.chmod(tdir, 493)
tdir = os.path.dirname(tdir)
ch_cmd = 'chown ' + creds['user'] + ':' + creds['group'] + ' '\
+ vda
subprocess.call(ch_cmd, shell=True)
def _gen_pin_drives(pins):
'''
Generate the "pinned" vm image
'''
creds = libvirt_creds()
for pin in pins:
dirname = os.path.dirname(pin['path'])
if os.path.exists(pin['path']):
continue
if not os.path.isdir(dirname):
os.makedirs(dirname)
tdir = copy.deepcopy(dirname)
while not tdir == '/':
os.chmod(tdir, 493)
tdir = os.path.dirname(tdir)
i_cmd = 'qemu-img create ' + pin['path'] + ' ' + pin['size'] + 'G'
f_cmd = 'yes | mkfs.' + pin['filesystem'] + ' ' + pin['path']
ch_cmd = 'chown ' + creds['user'] + ':' + creds['group'] + ' '\
+ pin['path']
subprocess.call(i_cmd, shell=True)
subprocess.call(f_cmd, shell=True)
if pin['filesystem'].startswith('ext'):
t_cmd = 'tune2fs -c 0 -i 0 ' + pin['filesystem']
subprocess.call(t_cmd, shell=True)
if pin['format'] == 'qcow2':
q_cmd = 'qemu-img convert -O qcow2 ' + pin['path'] + ' '\
+ pin['path'] + '.tmp'
subprocess.call(q_cmd, shell=True)
shutil.move(pin['path'] + '.tmp', pin['path'])
subprocess.call(ch_cmd, shell=True)
return True
def _apply_overlay(vda, instance):
'''
Use libguestfs to apply the overlay under the specified instance to the
specified vda
'''
overlay = os.path.join(instance, 'overlay')
if not os.path.isdir(overlay):
return False
tmp = tempfile.mkdtemp()
tar = os.path.join(tmp, 'host.tgz')
cwd = os.getcwd()
os.chdir(overlay)
t_cmd = 'tar cvzf ' + tar + ' *'
subprocess.call(t_cmd, shell=True)
os.chdir(cwd)
g_cmd = 'guestfish -i -a ' + vda + ' tgz-in ' + tar + ' /'
subprocess.call(g_cmd, shell=True)
shutil.rmtree(tmp)
return True
def libvirt_creds():
'''
Returns the user and group that the disk images should be owned by
CLI Example:
salt '*' butterkvm.libvirt_creds
'''
g_cmd = 'grep group /etc/libvirt/qemu.conf'
u_cmd = 'grep user /etc/libvirt/qemu.conf'
group = subprocess.Popen(g_cmd,
shell=True,
stdout=subprocess.PIPE).communicate()[0].split('"')[1]
user = subprocess.Popen(u_cmd,
shell=True,
stdout=subprocess.PIPE).communicate()[0].split('"')[1]
return {'user': user, 'group': group}
def local_images(local_path):
'''
return the virtual machine names for all of the images located in the
butter cloud's local_path in a list:
['vm1.boo.com', 'vm2.foo.com']
CLI Example:
salt '*' buttervm.local_images <image_path>
'''
images = os.listdir(local_path)
images.sort()
return images
def full_butter_data(local_path):
'''
Return the full virt info, but add butter data!
CLI Example:
salt '*' buttervm.full_butter_data <image_path>
'''
info = virt.full_info()
info['local_images'] = local_images(local_path)
return info
def create(instance, vda, image, pin):
'''
Create a virtual machine, this is part of the butter vm system and assumes
that the files prepared by butter are available via shared storage.
AKA - don't call this from the command line!
Arguments:
instance - string, The path to the instance directory for the given vm on
shared storage
vda - The location where the virtual machine image needs to be placed
image - The image to move into place
pin - a "pin" data structure defining the myriad of possible vdb-vbz disk
images to generate.
CLI Example:
salt '*' butterkvm.create <instance dir> <root image location>\
<Destination> <pin data>
'''
if not os.path.isfile(vda):
# Check that this is a fresh vm image, if so, copy it into place any
# apply the overlay, otherwise, just start the vm
_place_image(image, vda)
_gen_pin_drives(pin)
_apply_overlay(vda, instance)
virt.create_xml_path(os.path.join(instance, 'config.xml'))