2021-12-03 08:05:29 +01:00
#!/bin/bash
# Description: This simple Scripts creates an Virtualmachine on Proxmox, with the Qemu-Cli.
# Usage: Just Execute the script, it's a guided Script (chmod +x CreateCloudInitVM.sh && ./ CreateCloudInitVM.sh)
#
# Creator: Janic Joël Voser, Mettmenstetten - CH
# Date of Creation: 03.12.2021
#
# Active Maintainer: Janic Joël Voser
# Date of Last Maintenance: 03.12.2021
#
# Current State: Development
2021-12-03 18:14:36 +01:00
# Version: 1.0.0
2021-12-03 08:05:29 +01:00
# Version History:
# v0.0.1 - Basic Script Structure
2021-12-03 08:57:32 +01:00
# v0.1.0 - Get the User input
# v0.2.0 - Gather Virtual Machine ID
2021-12-03 10:55:01 +01:00
# v0.3.0 - Get & Select the Image of the Virtualmachine
2021-12-03 14:15:27 +01:00
# v0.4.0 - Create the VM & Gather additional Information
2021-12-03 18:05:12 +01:00
# v0.5.0 - Add proper Comments
2021-12-03 18:14:36 +01:00
# v1.0.0 - First Properly Working Version
2021-12-03 08:05:29 +01:00
# Planned Features:
2021-12-03 14:15:27 +01:00
# - [X] Guided VM Creation
# - [X] Image Download URL
# - [X] Image Selection
2021-12-03 08:57:32 +01:00
# - [X] VM-ID check
2021-12-03 14:15:27 +01:00
# - [X] Choose Memorysize
# - [X] Choose CPU cores
# - [X] Choose Network
# - [X] IMG & ISO & qcow2 support
2021-12-03 08:05:29 +01:00
2021-12-03 08:57:32 +01:00
# Global Constants
2021-12-03 18:05:12 +01:00
IMAGE_STORAGE_LOCATION = "/var/lib/vz/template/iso/" # Enter here the location of your iso-Templates - This is not adjustable while running the script
DEFAULT_VM_STORAGE = "tank-vms" # Enter here the default Storage Location, so you can Skip it by pressing enter
DEFAULT_DOWNLOAD_IMG_yn = "n" # Set the default value for the "Download new Image"-Questing
DEFAULT_VM_NAME = "cloudinit-vm" # Set the default value for the Virtual Machine Name
DEFAULT_VM_RAM = "2048" # Set the default value of Memory for the Virtual Machine
DEFAULT_VM_CORES = "2" # Set the default amount of cpu-cores for the Virtual Machine
DEFAULT_VM_NET = "vmbr0" # Set the default network interface for the Virtual Machine
2021-12-03 08:05:29 +01:00
# Functions
2021-12-03 10:55:01 +01:00
## Gather the ID of the Virtual machine
2021-12-03 08:57:32 +01:00
function gather_vmid {
echo "Already used IDs"
2021-12-03 10:55:01 +01:00
qm list | tr -s ' ' | cut -d ' ' -f 2,3 # Get the already used VMIDs & VM-Name
2021-12-03 08:57:32 +01:00
echo "Enter the new ID of your Virtual Machine (It must be unused)"
2021-12-03 10:55:01 +01:00
read VM_ID # Get the User Input(This VMID will be used for the new created VM)
readarray -t VMID_ARRAY < <( qm list | tail -n +2 | tr -s ' ' | cut -d ' ' -f 2)
2021-12-03 18:05:12 +01:00
if [ [ " ${ VMID_ARRAY [*] } " = ~ " $VM_ID " ] ] ; then # Check if Virtual Machine ID is alredy in use
2021-12-03 08:57:32 +01:00
echo "Your selected Virtual Machine ID is already in use, choose an other ID"
gather_vmid
fi
2021-12-03 10:55:01 +01:00
}
## Download a new Image in to the Image Storage
function get_img {
echo "Do you wish to download an Image? (yes/no)"
read DOWNLOAD_IMG_yn
2021-12-03 18:05:12 +01:00
case " ${ DOWNLOAD_IMG_yn : =DEFAULT_DOWNLOAD_IMG_yn } " in # Case Statement to switch based on the User Input
yes| YES| Yes| y| Y) # The Yes case enables the possibility to download an Image
2021-12-03 10:55:01 +01:00
echo "Please enter the URL of your Image"
read DOWNLOAD_IMG_URL
2021-12-03 18:05:12 +01:00
wget " $DOWNLOAD_IMG_URL " --directory-prefix= " $IMAGE_STORAGE_LOCATION " # Download the Image in to the default Image-Storage
if [ $? -eq 0 ] ; then # Check if last command (Download) was successful
2021-12-03 10:55:01 +01:00
echo "Download was Successful"
else
echo "Download failed"
echo "Retry or Downloadfile manually"
get_img
fi
2021-12-03 14:15:27 +01:00
; ;
2021-12-03 18:05:12 +01:00
no| NO| No| n| N) # The No Case skips the Image Download step
2021-12-03 10:55:01 +01:00
echo "Carrying on without a new Image"
2021-12-03 14:15:27 +01:00
; ;
2021-12-03 10:55:01 +01:00
*)
echo "Invalid Argument: Please type \"yes\" or \"no\""
2021-12-03 18:05:12 +01:00
get_img # Question again if the Answer was not an possible Option
2021-12-03 14:15:27 +01:00
; ;
esac
2021-12-03 10:55:01 +01:00
}
## Select an Image
2021-12-03 14:15:27 +01:00
function sel_img {
2021-12-03 10:55:01 +01:00
echo "The following list represents all Images which exist on the Hoststorage"
2021-12-03 18:05:12 +01:00
ls $IMAGE_STORAGE_LOCATION -l | tr -s ' ' | cut -d' ' -f 6-9 # List all files in the Image Location and their Age of Creation
readarray -t OS_IMG_ARRAY < <( ls $IMAGE_STORAGE_LOCATION -l | tr -s ' ' | cut -d' ' -f 9) # Create an Array of all Images
2021-12-03 10:55:01 +01:00
echo "Please enter the correct Image Name(shown above)"
read OS_IMG_NAME
2021-12-03 18:05:12 +01:00
if ! [ [ " ${ OS_IMG_ARRAY [*] } " = ~ " $OS_IMG_NAME " ] ] ; then # Check if Selected Image is in the Array, else go back to the selection
2021-12-03 10:55:01 +01:00
echo "Your selected Image does not exist"
echo "Maybe it was a Typo, Please check:"
echo " - Upper/Lowercase writing"
echo " - Fileextension(needs to be appended)"
echo "ProTip: Copy & Paste"
sleep 3
sel_img
fi
}
## Get the prepared Cloud-Init Image
function gather_img {
get_img
sel_img
2021-12-03 08:57:32 +01:00
}
2021-12-03 14:15:27 +01:00
## Gather Virtualmachine Network
function gather_vm_net {
2021-12-03 18:05:12 +01:00
ip -o link show | awk -F': ' '{print $2}' | grep vmbr # Get all the Virtual Bridge Interfaces of the Hostsystem
2021-12-03 14:15:27 +01:00
echo "Enter one of the above shown Network-Interfaces to add to your VM"
read VM_NET
2021-12-03 18:05:12 +01:00
readarray -t VM_NET_ARRAY < <( ip -o link show | awk -F': ' '{print $2}' | grep vmbr) # Create an array of all Virtual Bridge Interfaces of the Hostsystem
if ! [ [ " ${ VM_NET_ARRAY [*] } " = ~ " $VM_NET " ] ] ; then # Check if Selected Network is an existing network else go back to the Selection
2021-12-03 14:15:27 +01:00
echo "Your selected Network does not exist"
echo "Maybe it was a Typo, Please check:"
echo " - Upper/Lowercase writing"
echo "ProTip: Copy & Paste"
sleep 3
gather_vm_net
fi
}
## Gather hardware
function gather_hardware {
echo "Enter the amount of memory in MegaBytes"
echo "Example for 2GB = \"2048\""
read VM_RAM
echo "Enter the amount of Cpu-Cores you want to give to the Virtual machine"
read VM_CORES
gather_vm_net
}
## Gather all aditional Data
function gather_additional {
gather_vmid
echo "Enter the name of the new Virtualmachine"
read VM_NAME
}
## Gather VM_Storage
function gather_vm_storage {
echo " Please enter the Virtual Machine Storage Pool:[ $DEFAULT_VM_STORAGE ] "
read VM_STORAGE
2021-12-03 18:05:12 +01:00
VM_STORAGE = ${ VM_STORAGE : = $DEFAULT_VM_STORAGE } # Get the Storage of the VM, if nothing is set just use the Default
2021-12-03 14:15:27 +01:00
}
2021-12-03 10:55:01 +01:00
## Get all the Variables from the User
2021-12-03 08:57:32 +01:00
function get_user_input {
2021-12-03 10:55:01 +01:00
gather_img
2021-12-03 14:15:27 +01:00
gather_hardware
gather_vm_storage
gather_additional
}
2021-12-03 18:05:12 +01:00
# Import the Cloudinit image and append it to the Virtual Machine
2021-12-03 14:15:27 +01:00
function vm_import_cloudinit_img {
2021-12-03 18:05:12 +01:00
IMG_TYPE = $( echo " $OS_IMG_NAME " | rev | cut -d "." -f 1 | rev) # Get the Image Fileending for further operations
if [ $IMG_TYPE = = "iso" ] || [ $IMG_TYPE = = "img" ] ; then # If the Image Fileending is "iso" or img" do the following
qm importdisk " $VM_ID " " $IMAGE_STORAGE_LOCATION $OS_IMG_NAME " " $VM_STORAGE " -format qcow2 # Convert the Image to qcow2 format and write it to the VM-Storage
2021-12-03 14:15:27 +01:00
if ! [ $? -eq 0 ] ; then
echo "It was not possible to convert a new Image with your values"
echo "Read the error message above"
exit
fi
2021-12-03 18:05:12 +01:00
elif [ $IMG_TYPE = = "qcow2" ] ; then # If the Image Fileending is "qcow2" do the following
qm importdisk " $VM_ID " " $IMAGE_STORAGE_LOCATION $OS_IMG_NAME " " $VM_STORAGE " #import a copy of the Image to the VM, safe the copy in the set Storagepath
if ! [ $? -eq 0 ] ; then
2021-12-03 14:15:27 +01:00
echo "It was not possible to convert a new Image with your values"
echo "Read the error message above"
exit
fi
else
echo "Your OS-Image does not have a fileending which is supported by this scirpt"
echo "only iso & img are Supported"
exit
fi
}
2021-12-03 18:05:12 +01:00
# Create the Virtual Machine with Set-Values
2021-12-03 14:15:27 +01:00
function create_qm_vm {
2021-12-03 18:05:12 +01:00
qm create " $VM_ID " --name " ${ VM_NAME : = $DEFAULT_VM_NAME } " --memory " ${ VM_RAM : = $DEFAULT_VM_RAM } " --cores " ${ VM_CORES : = $DEFAULT_VM_CORES } " --net0 virtio,bridge= " ${ VM_NET : = $DEFAULT_VM_NET } " # Create the Virtualmachine with the set hardware specification
2021-12-03 14:15:27 +01:00
if ! [ $? -eq 0 ] ; then
echo "It was not possible to create a Virtual machine with your values"
echo "Read the error message above"
exit
fi
2021-12-03 18:05:12 +01:00
vm_import_cloudinit_img # Import the Image to the Virtual Machine
qm set $VM_ID --scsihw virtio-scsi-pci --scsi0 $VM_STORAGE :vm-$VM_ID -disk-0 #Add the Image to the Virtual Machine
2021-12-03 14:15:27 +01:00
if ! [ $? -eq 0 ] ; then
echo "It was not possible to add the custom Image to your Virtual machine"
echo "Read the error message above"
exit
fi
2021-12-03 18:05:12 +01:00
qm set $VM_ID --ide2 $VM_STORAGE :cloudinit --boot c --bootdisk scsi0 --serial0 socket --vga serial0 #Add the Cloud-Initdrive & set the Bootdrive & Add a serial console(is needed for cloud-init)
2021-12-03 14:15:27 +01:00
if ! [ $? -eq 0 ] ; then
echo "It was not possible to add an cloudinit drive to your Virtual machine"
echo "Read the error message above"
exit
fi
2021-12-03 08:57:32 +01:00
}
2021-12-03 08:05:29 +01:00
# Main Script
2021-12-03 08:57:32 +01:00
get_user_input
2021-12-03 18:14:36 +01:00
create_qm_vm
echo "Script was Successful"
echo "Have fun with your newly deployed Virtual Machine"