#!/bin/bash ############################################################################# # create_nodes.sh - Script to create VM nodes for use with Ironic. # # PURPOSE # This script can be used to create VM instances without an operating # system and that are ready for netbooting. They are connected to the # bridge named 'brbm' (created if it does not exist). # # EXAMPLE USAGE # # Use defaults - Create a single node with base name of 'testvm' # sudo create_nodes.sh # # # Create 5 nodes # sudo NODECOUNT=5 create_nodes.sh # # # Create 3 nodes with base name of 'junk' # sudo NODEBASE=junk NODECOUNT=3 create_nodes.sh # # # Create 2 nodes that use KVM acceleration # sudo VM_DOMAIN_TYPE=kvm NODECOUNT=2 create_nodes.sh # # # Create 3 nodes with different naming # sudo TEST_VM_NODE_NAMES="controller00 compute00 compute01" create_nodes.sh # # THANKS # Thanks to the author(s) of the ironic-supporting code within devstack, # from which all of this is derived. # # AUTHOR # David Shrewsbury (shrewsbury.dave@gmail.com) ############################################################################# set -e # exit immediately on command error set -u # treat unset variables as error when substituting LIBVIRT_CONNECT_URI=${LIBVIRT_CONNECT_URI:-"qemu:///system"} export VIRSH_DEFAULT_CONNECT_URI="$LIBVIRT_CONNECT_URI" # VM specs VM_DOMAIN_TYPE=${VM_DOMAIN_TYPE:-qemu} VM_EMULATOR=${VM_EMULATOR:-/usr/bin/qemu-system-x86_64} VM_CPU=${VM_CPU:-1} VM_RAM=${VM_RAM:-3072} VM_DISK=${VM_DISK:-10} VM_MACHINE="pc-1.0" function is_distro { local os_release=false [[ -e /etc/os-release ]] && os_release=true case "$1" in centos) { $os_release && grep -q -i "centos" /etc/os-release; } || [[ -e /etc/centos-release ]] ;; debian) { $os_release && grep -q -i "debian" /etc/os-release; } || [[ -e /etc/debian_version ]] ;; suse) { $os_release && grep -q -i "suse" /etc/os-release; } || [[ -e /etc/SuSE-release ]] ;; *) echo "Unsupported distribution '$1'" >&2; exit 1 ;; esac } # CentOS provides a single emulator package # which differs from other distributions, and # needs to be explicitly set. if is_distro "centos"; then VM_EMULATOR=/usr/libexec/qemu-kvm VM_MACHINE="pc" fi # VM network VM_NET_BRIDGE=${VM_NET_BRIDGE:-default} # VM logging directory VM_LOGDIR=/var/log/libvirt/baremetal_logs ############################################################################# # FUNCTION # create_node # # PARAMETERS # $1: Virtual machine name # $2: Number of CPUs for the VM # $3: Amount of RAM for the VM # $4: Disk size (in GB) for the VM # $5: CPU architecture (i386 or amd64) # $6: Network bridge for the VMs # $7: Path to VM emulator # $8: Logging directory for the VMs # $9: Domain type of the VM ############################################################################# function create_node { NAME=$1 CPU=$2 MEM=$(( 1024 * $3 )) # extra G to allow fuzz for partition table : flavor size and registered # size need to be different to actual size. DISK=$(( $4 + 1)) case $5 in i386) ARCH='i686' ;; amd64) ARCH='x86_64' ;; *) echo "Unsupported arch $5!" >&2; exit 1 ;; esac BRIDGE=$6 EMULATOR=$7 LOGDIR=$8 DOMAIN_TYPE=$9 LIBVIRT_NIC_DRIVER=${LIBVIRT_NIC_DRIVER:-"e1000"} LIBVIRT_STORAGE_POOL=${LIBVIRT_STORAGE_POOL:-"default"} LIBVIRT_CONNECT_URI=${LIBVIRT_CONNECT_URI:-"qemu:///system"} if ! virsh pool-list --all | grep -q $LIBVIRT_STORAGE_POOL; then virsh pool-define-as --name $LIBVIRT_STORAGE_POOL dir --target /var/lib/libvirt/images >&2 virsh pool-autostart $LIBVIRT_STORAGE_POOL >&2 virsh pool-start $LIBVIRT_STORAGE_POOL >&2 fi pool_state=$(virsh pool-info $LIBVIRT_STORAGE_POOL | grep State | awk '{ print $2 }') if [ "$pool_state" != "running" ] ; then [ ! -d /var/lib/libvirt/images ] && mkdir /var/lib/libvirt/images virsh pool-start $LIBVIRT_STORAGE_POOL >&2 fi if [ -n "$LOGDIR" ] ; then mkdir -p "$LOGDIR" if is_distro "centos" || is_distro "suse"; then # NOTE(TheJulia): For some unknown reason, libvirt's log folder # permissions on CentOS ship in an inoperable state. Users must # be able to read a folder to open files in the folder structure. chmod o+rx "$LOGDIR/.." fi fi PREALLOC= if is_distro "debian"; then PREALLOC="--prealloc-metadata" fi VM_LOGGING="$LOGDIR/${NAME}_console.log" VOL_NAME="${NAME}.qcow2" if ! virsh list --all | grep -q $NAME; then virsh vol-list --pool $LIBVIRT_STORAGE_POOL | grep -q $VOL_NAME && virsh vol-delete $VOL_NAME --pool $LIBVIRT_STORAGE_POOL >&2 virsh vol-create-as $LIBVIRT_STORAGE_POOL ${VOL_NAME} ${DISK}G --format qcow2 $PREALLOC >&2 volume_path=$(virsh vol-path --pool $LIBVIRT_STORAGE_POOL $VOL_NAME) # Pre-touch the VM to set +C, as it can only be set on empty files. touch "$volume_path" # NOTE(TheJulia): CentOS default installs with an XFS root, and chattr # fails to set +C on XFS. This could be more elegant, however the use # case is for CI testing. if ! is_distro "centos"; then chattr +C "$volume_path" || true fi vm_xml=" ${NAME} ${MEM} ${CPU} hvm destroy restart restart ${EMULATOR}