#!/bin/bash # Heavily Modified Script By: Brielle Bruns # Date: 02/19/2020 # URL: https://git.sosdg.org/brielle/virt-install-cloud # Version: 1.1.3 # # Originally based on: # virt-install-cloud.sh : script to start an OpenStack cloud image on kvm # version : 1.2.1 # # Author : Claude Durocher # License : GPLv3 # # ref. http://mojodna.net/2014/05/14/kvm-libvirt-and-ubuntu-14-04.html # # requires the following packages on Ubuntu host: # wget qemu-kvm libvirt-bin virtinst bridge-utils genisoimage|xorriso # requires the following packages on CentOS host: # wget qemu-kvm libvirt virt-install bridge-utils genisoimage|xorriso # # check if the script is run as root user if [[ $USER != "root" ]]; then echo "This script must be run as root!" && exit 1 fi WORKING_DIR=$(cd -P -- "$(dirname -- "$0")" && pwd -P) usage() { echo "${0} Help" echo -e "\t-h show this help" echo -e "\t-n hostname *" echo -e "\t-d domainame *" echo -e "\t-s disk size (num + count size - M=Megabytes G=Gigabytes) *" echo -e "\t-r ram size (in megabytes) *" echo -e "\t-c number of vcpus" echo -e "\t-b bridge to attach to *" echo -e "\t-x network info" echo -e "\t (type:ip:netmask:gateway - type=eni/1, ip=dhcp or address, default 1:dhcp)" echo -e "\t-i distribution to use" echo -e "\t (see script for supported options) - default is stretch" echo -e "\t-o OS type and variant (default: generic:generic - also set by distro option when available)" } while getopts "c:r:s:n:d:i:o:b:x:h" opt; do case $opt in c) cpucount=$OPTARG;; r) ram=$OPTARG;; s) storage=$OPTARG;; n) hostname=$OPTARG;; d) domain=$OPTARG;; i) distro=$OPTARG;; o) ostype=$OPTARG;; b) bridge=$OPTARG;; x) netinfo=$OPTARG;; h) help="yes";; esac done if [[ -z $ram || -z $storage || -z $hostname || -z $domain || -z $bridge || $help == "yes" ]]; then echo "Error: Incorrect command usage, must provide all * flags." usage exit 1 fi if [[ -f ${WORKING_DIR}/config ]]; then source ${WORKING_DIR}/config else echo "Error: Missing ${WORKING_DIR}/config !" exit 1 fi if [[ -f ${WORKING_DIR}/config.local ]]; then source ${WORKING_DIR}/config.local fi if [[ -z $distro ]]; then distro="stretch" fi if [[ -z $cpucount ]]; then cpucount="2" fi if [[ -z $netinfo ]]; then netinfo="1:dhcp" fi if [[ ! -z $netinfo ]]; then OIFS=${IFS} IFS=: read -ra netinfo_config <<< "$netinfo" virt_netinfo_type=${netinfo_config[0]} virt_netinfo_address=${netinfo_config[1]} virt_netinfo_netmask=${netinfo_config[2]} virt_netinfo_gateway=${netinfo_config[3]} IFS=${OIFS} echo "Configuring network as type=${virt_netinfo_type} addr=${virt_netinfo_address}/${virt_netinfo_netmask}/${virt_netinfo_gateway}" fi if [[ ! -z $ostype ]]; then OIFS=${IFS} IFS=: read -ra virt_os <<< "$ostype" virt_ostype=${virt_os[0]} virt_osvariant=${virt_os[1]} IFS=${OIFS} else virt_ostype="generic" virt_osvariant="generic" fi arch="amd64" source distros sed -e "s/%GUEST_NAME%/${hostname}/g" ${WORKING_DIR}/meta-data > ${WORKING_DIR}/output/meta-data sed -e "s/%FQDN%/${hostname}.${domain}/g" -e "s/%DOMAIN%/${domain}/g" -e "s/%NAMESERVER1%/${nameserver1}/g" -e "s/%NAMESERVER2%/${nameserver2}/g" ${WORKING_DIR}/user-data > ${WORKING_DIR}/output/user-data if [[ ${virt_netinfo_type} == "eni" ]]; then cat ${WORKING_DIR}/network/legacy-eni >> ${WORKING_DIR}/output/meta-data if [[ ${virt_netinfo_address} == "dhcp" ]]; then echo -e "\n iface eth0 inet dhcp" >> ${WORKING_DIR}/output/meta-data else echo -e "\n iface eth0 inet static" >> ${WORKING_DIR}/output/meta-data echo " address ${virt_netinfo_address}" >> ${WORKING_DIR}/output/meta-data echo " netmask ${virt_netinfo_netmask}" >> ${WORKING_DIR}/output/meta-data echo " gateway ${virt_netinfo_gateway}" >> ${WORKING_DIR}/output/meta-data fi elif [[ $virt_netinfo_type == "1" ]]; then if [[ ${virt_netinfo_address} == "dhcp" ]]; then sed -e "s/%DOMAIN%/${domain}/" ${WORKING_DIR}/network/network-config-dhcp-v1 > ${WORKING_DIR}/output/network-config extra_iso_files=" -map $WORKING_DIR/output/network-config network-config" else sed -e "s/%DOMAIN%/${domain}/g" -e "s/%IP_ADDRESS%/${virt_netinfo_address}/g" -e "s/%NETMASK%/${virt_netinfo_netmask}/g" \ -e "s/%GATEWAY%/${virt_netinfo_gateway}/g" -e "s/%NAMESERVER1%/${nameserver1}/g" -e "s/%NAMESERVER2%/${nameserver2}/g" \ ${WORKING_DIR}/network/network-config-v1 > ${WORKING_DIR}/output/network-config extra_iso_files_xorriso=" -map $WORKING_DIR/output/network-config network-config" extra_iso_files_genisoimage="${WORKING_DIR}/output/network-config" extra_iso_files_cloud_localds="--network-config ${WORKING_DIR}/output/network-config" fi elif [[ $virt_netinfo_type == "2" ]]; then echo "Not implemented yet!" fi if [[ ! -f images/${IMG_NAME} ]]; then echo "Downloading image ${IMG_NAME}..." wget ${IMG_URL}/${IMG_NAME} -O images/${IMG_NAME} chmod 644 ${IMG_NAME} else echo "Using existing image ${IMG_NAME}..." fi # check if pool exists, otherwise create it if [[ "$(virsh pool-list|grep ${POOL} -c)" -ne "1" ]]; then echo "Creating pool ${POOL}..." virsh pool-define-as --name ${POOL} --type dir --target ${POOL_PATH} virsh pool-autostart ${POOL} virsh pool-build ${POOL} virsh pool-start ${POOL} fi # write the two cloud-init files into an ISO echo "Preparing ISO file required by cloud-init..." case $iso_method in genisoimage) genisoimage -input-charset utf8 -output configuration.iso -volid cidata -joliet -rock ${WORKING_DIR}/output/user-data ${WORKING_DIR}/output/meta-data ${extra_iso_files_genisoimage} ;; xorriso) xorriso -in_charset utf8 -outdev configuration.iso -volid cidata -joliet on -rockridge on -map output/user-data user-data -map output/meta-data meta-data ${extra_iso_files_xorriso} ;; cloud-localds) cloud-localds ${extra_iso_files_cloud_localds} ${WORKING_DIR}/configuration.iso ${WORKING_DIR}/output/user-data ${WORKING_DIR}/output/meta-data ;; esac # keep a backup of the files for future reference if [[ "${BACKUP_ISO_FILES}" == "yes" ]]; then cp -f ${WORKING_DIR}/output/user-data ${WORKING_DIR}/backups/${hostname}.${domain}.user-data cp -f ${WORKING_DIR}/output/meta-data ${WORKING_DIR}/backups/${hostname}.${domain}.meta-data if [[ -f ${WORKING_DIR}/output/network-config ]]; then cp -f ${WORKING_DIR}/output/network-config ${WORKING_DIR}/backups/${hostname}.${domain}.network-config chmod 640 ${WORKING_DIR}/backups/${hostname}.${domain}.network-config fi chmod 640 ${WORKING_DIR}/backups/${hostname}.${domain}.user-data ${WORKING_DIR}/backups/${hostname}.${domain}.meta-data fi # copy ISO into libvirt's directory cp configuration.iso ${POOL_PATH}/${hostname}.${domain}.configuration.iso virsh pool-refresh ${POOL} # copy image to libvirt's pool if [[ ! -f ${POOL_PATH}/${IMG_NAME} ]]; then cp images/${IMG_NAME} ${POOL_PATH} virsh pool-refresh ${POOL} fi # clone cloud image virsh vol-clone --pool ${POOL} ${IMG_NAME} ${hostname}.${domain}.root.img virsh vol-resize --pool ${POOL} ${hostname}.${domain}.root.img ${storage} # convert image format if [[ "${CONVERT}" == "yes" ]]; then echo "Converting image to format ${FORMAT}..." qemu-img convert -O ${FORMAT} ${POOL_PATH}/${hostname}.${domain}.root.img ${POOL_PATH}/${hostname}.${domain}.root.img.${FORMAT} rm ${POOL_PATH}/${hostname}.${domain}.root.img mv ${POOL_PATH}/${hostname}.${domain}.root.img.${FORMAT} ${POOL_PATH}/${hostname}.${domain}.root.img virsh pool-refresh ${POOL} fi echo "Creating guest ${hostname}.${domain}..." virt-install \ --name ${hostname}.${domain} \ --cpu ${cpumodel} \ --machine pc \ --memory ${ram} \ --vcpus=${cpucount} \ --noautoconsole \ --nographics \ --video=vga \ --memballoon virtio \ --network ${net_interface} \ --boot hd \ --disk vol=${POOL}/${hostname}.${domain}.root.img,format=${FORMAT},bus=virtio,cache=none \ --disk vol=${POOL}/${hostname}.${domain}.configuration.iso,device=cdrom \ --console pty,target_type=serial \ --os-type=${virt_ostype} --os-variant=${virt_osvariant} sleep 5 virsh change-media ${hostname}.${domain} hda --eject --config # cleanup rm configuration.iso output/meta-data output/user-data output/network-config