9c3b203644
Move distribution detection code into a function and query the /etc/os-release file which should exist on all recent distributions. If that fails, use the old method instead. Finally, we add support for SUSE based distributions. Change-Id: I34fc704fc79d1ad130f716007c5cf704772ac6e6 Signed-off-by: Markos Chandras <mchandras@suse.de>
275 lines
8.4 KiB
Bash
Executable File
275 lines
8.4 KiB
Bash
Executable File
#!/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="
|
|
<domain type='${DOMAIN_TYPE}'>
|
|
<name>${NAME}</name>
|
|
<memory unit='KiB'>${MEM}</memory>
|
|
<vcpu>${CPU}</vcpu>
|
|
<os>
|
|
<type arch='${ARCH}' machine='${VM_MACHINE}'>hvm</type>
|
|
<boot dev='network'/>
|
|
<bootmenu enable='no'/>
|
|
<bios useserial='yes'/>
|
|
</os>
|
|
<features>
|
|
<acpi/>
|
|
<apic/>
|
|
<pae/>
|
|
</features>
|
|
<clock offset='utc'/>
|
|
<on_poweroff>destroy</on_poweroff>
|
|
<on_reboot>restart</on_reboot>
|
|
<on_crash>restart</on_crash>
|
|
<devices>
|
|
<emulator>${EMULATOR}</emulator>
|
|
<disk type='file' device='disk'>
|
|
<driver name='qemu' type='qcow2' cache='writeback'/>
|
|
<source file='${volume_path}'/>
|
|
<target dev='vda' bus='virtio'/>
|
|
<address type='pci' domain='0x0000' bus='0x00' slot='0x06' function='0x0'/>
|
|
</disk>
|
|
<controller type='ide' index='0'>
|
|
<address type='pci' domain='0x0000' bus='0x00' slot='0x01' function='0x1'/>
|
|
</controller>
|
|
<interface type='network'>
|
|
<source network='${BRIDGE}'/>
|
|
</interface>
|
|
<input type='mouse' bus='ps2'/>
|
|
<graphics type='vnc' port='-1' autoport='yes'/>
|
|
<video>
|
|
<model type='cirrus' vram='9216' heads='1'/>
|
|
<address type='pci' domain='0x0000' bus='0x00' slot='0x02' function='0x0'/>
|
|
</video>
|
|
<serial type='file'>
|
|
<source path='${VM_LOGGING}'/>
|
|
<target port='0'/>
|
|
<alias name='serial0'/>
|
|
</serial>
|
|
<serial type='pty'>
|
|
<source path='/dev/pts/49'/>
|
|
<target port='1'/>
|
|
<alias name='serial1'/>
|
|
</serial>
|
|
<console type='file'>
|
|
<source path='${VM_LOGGING}'/>
|
|
<target type='serial' port='0'/>
|
|
<alias name='serial0'/>
|
|
</console>
|
|
<memballoon model='virtio'>
|
|
<address type='pci' domain='0x0000' bus='0x00' slot='0x07' function='0x0'/>
|
|
</memballoon>
|
|
</devices>
|
|
</domain>
|
|
"
|
|
|
|
echo ${vm_xml} > /tmp/vm.xml
|
|
# NOTE(TheJulia): the create command powers on a VM that has been defined,
|
|
# where as define creates the VM, but does not change the power state.
|
|
virsh define /tmp/vm.xml 2>&1 >/dev/null
|
|
if [ $? != 0 ]
|
|
then
|
|
echo "failed to create VM $NAME" >&2
|
|
rm -f /tmp/vm.xml
|
|
exit 1
|
|
fi
|
|
rm -f /tmp/vm.xml
|
|
|
|
fi
|
|
|
|
# echo mac
|
|
local macaddr=`virsh dumpxml $NAME | grep "mac address" | head -1 | cut -d\' -f2`
|
|
|
|
echo $macaddr
|
|
}
|
|
|
|
|
|
####################
|
|
# Main script code
|
|
####################
|
|
|
|
NODEBASE=${NODEBASE:-testvm}
|
|
NODECOUNT=${NODECOUNT:-1}
|
|
TEST_VM_NODE_NAMES=${TEST_VM_NODE_NAMES:-""}
|
|
NODEOUTPUT=${NODEOUTPUT:-"/tmp/baremetal.csv"}
|
|
TEMPFILE=`mktemp`
|
|
|
|
# must be root
|
|
user=`whoami`
|
|
if [ "$user" != "root" ]
|
|
then
|
|
echo "Must be run as root. You are $user." >&2
|
|
exit 1
|
|
fi
|
|
|
|
|
|
for (( i=1; i<=${NODECOUNT}; i++ ))
|
|
do
|
|
if [ -z "${TEST_VM_NODE_NAMES}" ]; then
|
|
name=${NODEBASE}${i}
|
|
else
|
|
names=($TEST_VM_NODE_NAMES)
|
|
arrayindex=$(($i-1))
|
|
name=${names[$arrayindex]}
|
|
fi
|
|
|
|
mac=$(create_node $name $VM_CPU $VM_RAM $VM_DISK amd64 $VM_NET_BRIDGE $VM_EMULATOR $VM_LOGDIR $VM_DOMAIN_TYPE)
|
|
|
|
printf "$mac,root,undefined,192.168.122.1,$VM_CPU,$VM_RAM,$VM_DISK,flavor,type,a8cb6624-0d9f-c882-affc-046ebb96ec0${i},$name,192.168.122.$((i+1))\n" >>$TEMPFILE
|
|
done
|
|
|
|
mv "${TEMPFILE}" "${NODEOUTPUT}"
|