mirror of
https://github.com/saltstack/salt.git
synced 2025-04-17 10:10:20 +00:00
164 lines
5.1 KiB
Python
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'))
|