From 47ecc17b92d1557b71aa83cd89e2b32ed598c575 Mon Sep 17 00:00:00 2001 From: victor Date: Wed, 23 Oct 2024 20:48:05 +0200 Subject: [PATCH] serveral changes to improve legibility --- README.md | 22 ++++ base_scripts/vim_functions.sh | 112 ++++++++++++++++++++ base_scripts/vm_list.sh | 2 - env_scripts/newer_os.sh | 2 + env_scripts/older_os.sh | 2 + kvm_cloudimage.sh | 0 base_scripts/vm_connect.sh => vm_connect.sh | 2 +- base_scripts/vm_create.sh => vm_create.sh | 45 ++++++-- base_scripts/vm_delete.sh => vm_delete.sh | 2 +- base_scripts/vm_get_ip.sh => vm_get_ip.sh | 2 +- base_scripts/vm_install.sh => vm_install.sh | 2 +- vm_list.sh | 2 + base_scripts/vm_set_ip.sh => vm_set_ip.sh | 3 +- 13 files changed, 181 insertions(+), 17 deletions(-) create mode 100644 base_scripts/vim_functions.sh delete mode 100755 base_scripts/vm_list.sh create mode 100644 env_scripts/newer_os.sh create mode 100644 env_scripts/older_os.sh create mode 100644 kvm_cloudimage.sh rename base_scripts/vm_connect.sh => vm_connect.sh (95%) rename base_scripts/vm_create.sh => vm_create.sh (77%) rename base_scripts/vm_delete.sh => vm_delete.sh (98%) rename base_scripts/vm_get_ip.sh => vm_get_ip.sh (98%) rename base_scripts/vm_install.sh => vm_install.sh (99%) create mode 100755 vm_list.sh rename base_scripts/vm_set_ip.sh => vm_set_ip.sh (99%) diff --git a/README.md b/README.md index 09d735b..c92ebf0 100644 --- a/README.md +++ b/README.md @@ -5,11 +5,33 @@ Use cloud images on baremetal using libvirt/kvm - openssh - mkpass (whois) - arp + ## Links - [https://blog.programster.org/create-debian-12-kvm-guest-from-cloud-image](https://blog.programster.org/create-debian-12-kvm-guest-from-cloud-image) - [https://earlruby.org/2023/02/quickly-create-guest-vms-using-virsh-cloud-image-files-and-cloud-init/](https://earlruby.org/2023/02/quickly-create-guest-vms-using-virsh-cloud-image-files-and-cloud-init/) - [https://sumit-ghosh.com/posts/create-vm-using-libvirt-cloud-images-cloud-init/)](https://sumit-ghosh.com/posts/create-vm-using-libvirt-cloud-images-cloud-init/) +## Preparing host + +### Create bridge network + +```shell +sudo virsh --connect qemu:///session net-define /dev/stdin << EOF + + bridged-network + + + +EOF +``` + +#### AppArmor exception + +```shell +ln -s /etc/apparmor.d/usr.sbin.libvirtd /etc/apparmor.d/disable/ +apparmor_parser -R /etc/apparmor.d/usr.sbin.libvirtd +``` + ## Creating VMs ### Usage ```shell diff --git a/base_scripts/vim_functions.sh b/base_scripts/vim_functions.sh new file mode 100644 index 0000000..d24d554 --- /dev/null +++ b/base_scripts/vim_functions.sh @@ -0,0 +1,112 @@ +#!/bin/env bash + +# Variables +VM_USER="user" +VM_BASE_DIR=${VM_BASE_DIR:-"${HOME}/vms"} +VM_IMAGE_PATH="${VM_BASE_DIR}/images/$1.img" +CI_IMAGE_PATH="${VM_BASE_DIR}/images/$1-cidata.iso" + +# Functions +## List Installed VMS +vm_list() +{ + virsh list +} + +vm_net_get_mac() +{ + local VM=$1 + MAC_VM=$(virsh domiflist "$VM" | awk '{ print $5 }' | tail -2 | head -1) + echo $MAC_VM +} +## Get VM ip (only on NAT) +vm_net_get_ip() +{ + local VM="$1" + # Obtener la dirección MAC de la interfaz de red + MAC_VM=$(vm_net_get_mac $VM) + if [[ -z "$MAC_VM" ]]; then + echo "Error: No se pudo encontrar la dirección MAC para '$VM'" + return 1 + fi + # Obtener la dirección IP a partir de la dirección MAC + VM_IP_ADDRESS=$(arp -a | grep "$MAC_VM" | awk '{ print $2 }' | sed 's/[()]//g') + if [[ -z "$VM_IP_ADDRESS" ]]; then + echo "Error: No se pudo encontrar la dirección IP para la dirección MAC '$MAC_VM'" + return 1 + fi + echo "$VM_IP_ADDRESS" +} + +vm_net_create_netplan() +{ + local VM=$1 + local MAV_VM=$2 +cat < "$VM_BASE_DIR/init/${VM}-netplan" +# This file is generated from information provided by the datasource. Changes +# to it will not persist across an instance reboot. To disable cloud-init's +# network configuration capabilities, write a file +# /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg with the following: +# network: {config: disabled} +network: + ethernets: + enp1s0: + addresses: + - ${IP}/24 + nameservers: + addresses: + - 208.67.222.222 + - 208.67.220.220 + match: + macaddress: ${MAC_VM} + set-name: enp1s0 + version: 2 +EOF +} + +vm_net_bridge_set_ip() +{ + local VM="$1" + local IP="$2" + MAC_VM=$(vm_net_get_mac "$VM") + CURRENT_IP=$(vm_net_get_ip "$VM") + define_netplan + # Obtener la dirección IP de la máquina virtual + scp -i ${VM_BASE_DIR}/ssh/${VM} \ + -r $VM_BASE_DIR/init/${VM}-netplan \ + ${VM_USER}@${CURRENT_IP}:50-cloud-init.yaml + ssh -i ${VM_BASE_DIR}/ssh/${VM} -l${VM_USER} ${CURRENT_IP} "bash -s" -- < ../vm_example_scripts/apply_netplan.sh +} +## Connect to an existent VM using ssh +vm_connect() +{ + local VM=$1 + local VM_IP=$(get_vm_ip_address "$VM") + ssh -i ${VM_BASE_DIR}/ssh/${VM} -l${VM_USER} ${VM_IP} +} + +## Delete VM +vm_delete () +{ + local VM=$1 + if [[ -f "$VM_IMAGE_PATH" ]]; then + # Safely remove the VM with confirmation + read -p "Are you sure you want to remove the VM '$VM' (y/N)? " confirm + if [[ "$confirm" =~ ^[Yy]$ ]]; then + # Attempt to stop the VM before deleting + virsh destroy "$VM" 2>/dev/null || true + # Delete VM definition and associated images + virsh undefine "$VM" 2>/dev/null || true + rm -fv "$VM_IMAGE_PATH" "$CI_IMAGE_PATH" + rm ${VM_BASE_DIR}/xml/$1.xml + rm ${VM_BASE_DIR}/ssh/$1* + rm ${VM_BASE_DIR}/init/$1-user-data + rm ${VM_BASE_DIR}/init/$1-meta-data + else + echo "VM removal cancelled." + fi + else + # Handle case where VM image is not found + echo "Cannot find VM image file '$VM_IMAGE_PATH'. No action taken." + fi +} \ No newline at end of file diff --git a/base_scripts/vm_list.sh b/base_scripts/vm_list.sh deleted file mode 100755 index fc5cceb..0000000 --- a/base_scripts/vm_list.sh +++ /dev/null @@ -1,2 +0,0 @@ -#!/bin/bash -virsh list \ No newline at end of file diff --git a/env_scripts/newer_os.sh b/env_scripts/newer_os.sh new file mode 100644 index 0000000..e3c05bf --- /dev/null +++ b/env_scripts/newer_os.sh @@ -0,0 +1,2 @@ +#!/bin/env bash +GUEST_OS_TYPE_DEBIAN="debian12" \ No newline at end of file diff --git a/env_scripts/older_os.sh b/env_scripts/older_os.sh new file mode 100644 index 0000000..6514c25 --- /dev/null +++ b/env_scripts/older_os.sh @@ -0,0 +1,2 @@ +#!/bin/env bash +GUEST_OS_TYPE_DEBIAN="debian11" \ No newline at end of file diff --git a/kvm_cloudimage.sh b/kvm_cloudimage.sh new file mode 100644 index 0000000..e69de29 diff --git a/base_scripts/vm_connect.sh b/vm_connect.sh similarity index 95% rename from base_scripts/vm_connect.sh rename to vm_connect.sh index 0e780af..fd7e872 100755 --- a/base_scripts/vm_connect.sh +++ b/vm_connect.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/env bash #Variables VM="$1" VM_BASE_DIR=${VM_BASE_DIR:-"${HOME}/vms"} diff --git a/base_scripts/vm_create.sh b/vm_create.sh similarity index 77% rename from base_scripts/vm_create.sh rename to vm_create.sh index 1171878..ff6d07d 100755 --- a/base_scripts/vm_create.sh +++ b/vm_create.sh @@ -1,6 +1,4 @@ -#!/bin/bash - -# Variables +#!/bin/env bash VM_HOSTNAME= VM_BASE_DIR=${VM_BASE_DIR:-"${HOME}/vms"} VM_DISK_SIZE=20 @@ -11,7 +9,8 @@ VM_BASE_IMAGE= VM_OS_VARIANT= VM_USERNAME="user" VM_BRIDGE_INT= -LIBVIRT_NET_OPTION="network=default,model=e1000" +VM_NET_USED="default" +LIBVIRT_NET_OPTION="network=$VM_NET_USED,model=e1000" # Functions usage() { @@ -31,17 +30,43 @@ OPTIONS: EOF } +HOST_OS=$(cat /etc/os-release | grep -v VERSION_ID |grep "ID=" | awk -F'=' '{print $2}') +if [ $HOST_OS == "debian" ]; then + source < env_scripts/older_os.sh +else + source > env_scripts/newer_os.sh +fi + +case $answer in + [1]* ) VM_OS_VARIANT=${GUEST_OS_TYPE_DEBIAN} + VM_BASE_IMAGE='https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-generic-amd64.qcow2' + break;; + [2]* ) VM_OS_VARIANT='ubuntu20.04' + VM_BASE_IMAGE='https://cloud-images.ubuntu.com/focal/current/focal-server-cloudimg-amd64.img' + break;; + [3]* ) VM_OS_VARIANT='ubuntu22.04' + VM_BASE_IMAGE='https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img' + break;; + [4]* ) VM_OS_VARIANT='ubuntu24.04' + VM_BASE_IMAGE='https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img' + break;; + [5]* ) VM_OS_VARIANT='freebsd14.0' + VM_BASE_IMAGE='https://download.freebsd.org/releases/VM-IMAGES/14.0-RELEASE/amd64/Latest/FreeBSD-14.0-RELEASE-amd64.qcow2.xz' + break;; + * ) echo "Please answer 1,2,3,4,5.";; + esac + done download_base_image() { -if ! test -f "$HOME/vms/base/$VM_OS_VARIANT.qcow2"; then +if ! test -f "${VM_BASE_DIR}/base/$VM_OS_VARIANT.qcow2"; then if [[ "$VM_OS_VARIANT" == "freebsd14.0" ]]; then VM_DISK_FORMAT=".qcow2.xz" - wget -v -O "$HOME/vms/base/$VM_OS_VARIANT.${VM_DISK_FORMAT}" ${VM_BASE_IMAGE} - cd $HOME/vms/base/ + wget -v -O "${VM_BASE_DIR}/base/$VM_OS_VARIANT.${VM_DISK_FORMAT}" ${VM_BASE_IMAGE} + cd ${VM_BASE_DIR}/base/ xz -d $VM_OS_VARIANT.${VM_DISK_FORMAT} cd - else - wget -v -O "$HOME/vms/base/$VM_OS_VARIANT.${VM_DISK_FORMAT}" ${VM_BASE_IMAGE} + wget -v -O "${VM_BASE_DIR}/base/$VM_OS_VARIANT.${VM_DISK_FORMAT}" ${VM_BASE_IMAGE} fi fi } @@ -163,9 +188,9 @@ else fi -echo "Creating a qcow2 image file ${VM_BASE_DIR}/images/${VM_HOSTNAME}.img that uses the cloud image file $HOME/vms/base/$VM_OS_VARIANT.${VM_DISK_FORMAT} as its base" +echo "Creating a qcow2 image file ${VM_BASE_DIR}/images/${VM_HOSTNAME}.img that uses the cloud image file ${VM_BASE_DIR}/base/$VM_OS_VARIANT.${VM_DISK_FORMAT} as its base" if ! test -f "${VM_BASE_DIR}/images/${VM_HOSTNAME}.img"; then - qemu-img create -b "$HOME/vms/base/${VM_OS_VARIANT}.qcow2" -f qcow2 -F qcow2 "${VM_BASE_DIR}/images/${VM_HOSTNAME}.img" "${VM_DISK_SIZE}G" + qemu-img create -b "${VM_BASE_DIR}/base/${VM_OS_VARIANT}.qcow2" -f qcow2 -F qcow2 "${VM_BASE_DIR}/images/${VM_HOSTNAME}.img" "${VM_DISK_SIZE}G" else echo "El fichero ${VM_BASE_DIR}/images/${VM_HOSTNAME}.img ya existe" exit 1 diff --git a/base_scripts/vm_delete.sh b/vm_delete.sh similarity index 98% rename from base_scripts/vm_delete.sh rename to vm_delete.sh index b3f3d53..fec4d1c 100755 --- a/base_scripts/vm_delete.sh +++ b/vm_delete.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/env bash # Function for usage message usage() { diff --git a/base_scripts/vm_get_ip.sh b/vm_get_ip.sh similarity index 98% rename from base_scripts/vm_get_ip.sh rename to vm_get_ip.sh index 51a8105..eec5cf7 100755 --- a/base_scripts/vm_get_ip.sh +++ b/vm_get_ip.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/env bash usage() { cat << EOF USO: $0 VM diff --git a/base_scripts/vm_install.sh b/vm_install.sh similarity index 99% rename from base_scripts/vm_install.sh rename to vm_install.sh index 243f64a..cdca0cc 100755 --- a/base_scripts/vm_install.sh +++ b/vm_install.sh @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/env bash VM_BASE_DIR=${VM_BASE_DIR:-"${HOME}/vms"} VM_USER="user" VM=$1 diff --git a/vm_list.sh b/vm_list.sh new file mode 100755 index 0000000..842ea73 --- /dev/null +++ b/vm_list.sh @@ -0,0 +1,2 @@ +#!/bin/env bash +virsh list \ No newline at end of file diff --git a/base_scripts/vm_set_ip.sh b/vm_set_ip.sh similarity index 99% rename from base_scripts/vm_set_ip.sh rename to vm_set_ip.sh index fc7a214..afc2821 100755 --- a/base_scripts/vm_set_ip.sh +++ b/vm_set_ip.sh @@ -1,4 +1,5 @@ -#!/bin/bash +#!/bin/env bash + VM_BASE_DIR=${VM_BASE_DIR:-"${HOME}/vms"} VM_USER="user" MAC_VM=