Instantly share code, notes, and snippets.

Embed
What would you like to do?
Script to create/start/stop/destroy many CoreOS VMs running on a KVM host (referenced from http://www.beginswithdata.com/2016/12/30/centos7-kvm-coreos/)
#! /usr/bin/python
################################################################################
# Manage (create/start/stop/undefine) CoreOS VMs on CentOS 7 using #
# QEMU/KVM/libvirt. Makes it easy to create/undefine container hosts #
# for lab purposes. #
# #
# For more info see this blog post: #
# http://beginswithdata.com/2016/12/30/centos7-kvm-coreos/ #
# #
# Copyright (c) Chris Madden. All rights reserved. #
# Specifications subject to change without notice. #
################################################################################
import sys, argparse, os, shutil, subprocess, errno, socket, logging
parser = argparse.ArgumentParser(description='Manage some container host VMs.')
parser.add_argument('--prefix', dest='prefix', help='Prefix hostname for managed VMs', required=True)
parser.add_argument('--start', dest='start', type=int, help='Suffix number for managed VMs', required=True)
parser.add_argument('--count', dest='count', type=int, help='Count of VMs to manage', required=True)
parser.add_argument('--action',dest='action', help='Action to take [create|start|stop|undefine]', required=True)
parser.add_argument('--ip', dest='ip', help='Starting IP address if creating VMs or keyword "dns"')
args = parser.parse_args()
img_name = 'os.img'
dir_path = os.path.dirname(os.path.realpath(__file__))
logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.DEBUG)
# Loop though for quantity of VMs to manage
for i in range(args.count):
vmname = str(args.prefix) + str(args.start + i )
vm_path = dir_path + '/../' + vmname
# create logic
if args.action == 'create':
logging.info(vmname + ": Creating...")
# Determine IP address for VM
if args.ip == 'dns':
try:
ip = socket.gethostbyname(vmname)
except Exception as exc:
logging.error(vmname + ': DNS lookup failed.')
continue
else:
try:
ip_list = args.ip.split('.')
except Exception as exc:
logging.error(vmname + ': IP address not provided or not parsable')
exit()
ip = '.'.join(ip_list[:3]) + '.' + str(int(ip_list[3]) + i)
logging.info(vmname + ": Using IP " + ip)
# Check if IP is in use before starting just in case...
if (os.system("ping -c 1 -W 3 " + vmname + "> /dev/null") == 0):
logging.error(vmname + ': IP address is pingable; skipping creation')
continue
# Create subdir
try:
os.makedirs(vm_path)
except OSError as exc:
if exc.errno == errno.EEXIST:
logging.warning(vmname + ': Skipping creation because the storage directory already exists')
continue
else:
raise
# Create cloud-config file for VM doing a search/replace from template
logging.info(vmname + ": Creating cloud-config")
with open(dir_path + '/user_data', 'r') as file :
filedata = file.read()
filedata = filedata.replace('@@IP@@', ip)
filedata = filedata.replace('@@VMNAME@@', vmname)
with open(vm_path + '/user_data', 'w') as file:
file.write(filedata)
# Generate ISO
logging.info(vmname + ": Creating ISO image of cloud-config")
os.makedirs('/tmp/new-drive/openstack/latest')
shutil.copy(vm_path + '/user_data', '/tmp/new-drive/openstack/latest/user_data')
subprocess.call(['mkisofs', '-quiet', '-input-charset', 'iso8859-1', '-R', '-V', 'config-2', '-o', vm_path + '/configdrive.iso', '/tmp/new-drive'])
shutil.rmtree('/tmp/new-drive')
# Copy master image in place
logging.info(vmname + ": Copying master boot image for VM")
shutil.copyfile(dir_path + '/' + img_name, vm_path + '/' + img_name)
# Create and start VM
vi_cmd = []
vi_cmd.extend(['virt-install','--connect', 'qemu:///system'])
vi_cmd.extend(['--import', '--name', vmname])
vi_cmd.extend(['--ram', '1024', '--vcpus', '1'])
vi_cmd.extend(['--os-type=linux', '--os-variant=virtio26'])
vi_cmd.extend(['--disk', 'path=' + vm_path + '/' + img_name + ',format=raw,bus=virtio'])
vi_cmd.extend(['--disk', 'path=' + vm_path + '/configdrive.iso,device=cdrom,format=raw,bus=ide'])
vi_cmd.extend(['--network=bridge=bridge0'])
vi_cmd.extend(['--accelerate'])
vi_cmd.extend(['--graphics', "vnc,listen=0.0.0.0"])
vi_cmd.extend(['--noautoconsole'])
subprocess.call(vi_cmd)
logging.info(vmname + ": VM created and booting...")
# stop logic (incl undefine)
if args.action in [ 'stop', 'undefine']:
logging.info(vmname + ": Stopping...")
subprocess.call(['virsh', 'shutdown', vmname])
# undefine logic
if args.action == 'undefine':
logging.info(vmname + ": Undefining...")
subprocess.call(['virsh', 'undefine', vmname])
shutil.rmtree(vm_path)
# start logic
if args.action == 'start':
logging.info(vmname + ": Starting...")
subprocess.call(['virsh', 'start', vmname])
### CLI equivalents of the above
#mkdir -p /tmp/new-drive/openstack/latest
#cp coreos1/user_data /tmp/new-drive/openstack/latest/user_data
#mkisofs -R -V config-2 -o coreos1/configdrive.iso /tmp/new-drive
#rm -fr /tmp/new-drive
#virt-install --connect qemu:///system \
#--import --name coreos1 \
#--ram 1024 --vcpus 1 \
#--os-type=linux --os-variant=virtio26 \
#--disk path=/vm-storage/coreos1/os.img,format=raw,bus=virtio \
#--disk path=/vm-storage/coreos1/configdrive.iso,device=cdrom,format=raw,bus=ide \
#--network=bridge=bridge0 \
#--accelerate \
#--graphics vnc,listen=0.0.0.0 \
#--noautoconsole
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment