Merge pull request 'develop pull requesy' (#1) from develop into main
Reviewed-on: #1
This commit is contained in:
12
README.md
12
README.md
@ -113,3 +113,15 @@ VM 'ubuntuTest' removed successfully.
|
|||||||
## TODO
|
## TODO
|
||||||
|
|
||||||
- FreeBSD support is still in progress
|
- FreeBSD support is still in progress
|
||||||
|
- Check if used commands are available
|
||||||
|
./vm_create.sh: línea 52: mkpasswd: orden no encontrada
|
||||||
|
./vm_create.sh: línea 259: virt-install: orden no encontrada
|
||||||
|
./vm_create.sh: línea 261: virsh: orden no encontrada
|
||||||
|
qemu-img wget curl mkpass arp
|
||||||
|
sudo apt install --no-install-recommends qemu-system libvirt-clients libvirt-daemon-system whois virtinst net-tools
|
||||||
|
sudo chmod 750 /home/victor
|
||||||
|
sudo usermod -a -G libvirt $(whoami)
|
||||||
|
sudo usermod --append --groups earl libvirt-qemu
|
||||||
|
|
||||||
|
- Refactoring variables, functions and scripts calls for legibility and maintenance
|
||||||
|
- add script for create default files (network, variables etc)
|
||||||
|
|||||||
16
env_scripts/common.sh
Normal file
16
env_scripts/common.sh
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#!/bin/env bash
|
||||||
|
LIBVIRT_NET_MODEL="virtio"
|
||||||
|
LIBVIRT_NET_OPTION="network=$VM_NETWORK,model=$LIBVIRT_NET_MODEL"
|
||||||
|
OS_JSON_FILE="files/os_options.json"
|
||||||
|
#VM_BASE_DIR=${VM_BASE_DIR:-"${HOME}/.local/share/libvirt"}
|
||||||
|
#VM_BASE_DIR=${VM_BASE_DIR:-"${HOME}/var/lib/libvirt"}
|
||||||
|
VM_BASE_DIR="${HOME}/vms"
|
||||||
|
VM_BASE_IMAGES="base"
|
||||||
|
VM_DISK_EXTENSION="img"
|
||||||
|
VM_USERNAME="user"
|
||||||
|
|
||||||
|
VM_IMAGE_PATH="${VM_BASE_DIR}/images/$1.img"
|
||||||
|
CI_IMAGE_PATH="${VM_BASE_DIR}/images/$1-cidata.iso"
|
||||||
|
VM_NETWORK="vmnetwork"
|
||||||
|
REPO_BRANCH="main"
|
||||||
|
REPO_SOURCE="https://raw.githubusercontent.com/vgenguita/kvm-cloudimage/refs/heads/${REPO_BRANCH}/env_scripts/"
|
||||||
279
env_scripts/functions.sh
Normal file
279
env_scripts/functions.sh
Normal file
@ -0,0 +1,279 @@
|
|||||||
|
#!/bin/env bash
|
||||||
|
|
||||||
|
# Functions
|
||||||
|
|
||||||
|
check_host_os()
|
||||||
|
{
|
||||||
|
local 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
|
||||||
|
}
|
||||||
|
|
||||||
|
show_vm_menu()
|
||||||
|
{
|
||||||
|
# Show dinamic menu
|
||||||
|
echo "Select VM OS:"
|
||||||
|
for entry in $(jq -r '.os_variants[] | @base64' "$OS_JSON_FILE"); do
|
||||||
|
decoded=$(echo "$entry" | base64 --decode)
|
||||||
|
id=$(echo "$decoded" | jq -r .id)
|
||||||
|
name=$(echo "$decoded" | jq -r .name)
|
||||||
|
echo "$id. $name"
|
||||||
|
done
|
||||||
|
|
||||||
|
# ID_MAX calculation
|
||||||
|
ID_MAX=$(jq -r '[.os_variants[].id] | max' "$OS_JSON_FILE")
|
||||||
|
|
||||||
|
# Read input
|
||||||
|
read -r -p "Enter your choice [1-${ID_MAX}]: " answer
|
||||||
|
if ! [[ "$answer" =~ ^[0-9]+$ ]] || (( answer < 1 || answer > ID_MAX )); then
|
||||||
|
echo "Invalid option. Please enter a number between 1 and ${ID_MAX}."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
selected=$(jq -r ".os_variants[] | select(.id == $answer)" "$OS_JSON_FILE")
|
||||||
|
|
||||||
|
if [ -z "$selected" ]; then
|
||||||
|
echo "Invalid option."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Asignar variables
|
||||||
|
VM_OS_VARIANT=$(echo "$selected" | jq -r .variant)
|
||||||
|
VM_BASE_IMAGE_URL=$(echo "$selected" | jq -r .url)
|
||||||
|
VM_BASE_IMAGE=$(echo "$selected" | jq -r .origin_image_name)
|
||||||
|
VM_BOOT_TYPE=$(echo "$selected" | jq -r .boot_type)
|
||||||
|
VM_CHECKSUMS_URL=$(echo "$selected" | jq -r .md5sum)
|
||||||
|
}
|
||||||
|
|
||||||
|
compare_checksum()
|
||||||
|
{
|
||||||
|
CHECKSUM_TMP_FOLDER=$(mktemp)
|
||||||
|
curl -s -o "${CHECKSUM_TMP_FOLDER}" "${VM_CHECKSUMS_URL}"
|
||||||
|
VM_BASE_IMAGE_CHECKSUM=$(grep "$VM_BASE_IMAGE_NAME.${VM_BASE_IMAGE_EXTENSION}" "${CHECKSUM_TMP_FOLDER}" | awk '{print $1}')
|
||||||
|
if [[ "${VM_CHECKSUMS_URL}" == *"SHA256SUMS"* ]]; then
|
||||||
|
HASH_CMD="sha256sum"
|
||||||
|
elif [[ "${VM_CHECKSUMS_URL}" == *"SHA512SUMS"* ]]; then
|
||||||
|
HASH_CMD="sha512sum"
|
||||||
|
else
|
||||||
|
echo "ERROR: Unknown checksum type in URL: $CHECKSUM_URL"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
BASE_FILE_CHECKSUM=$(${HASH_CMD} ${VM_BASE_IMAGE_LOCATION} | awk '{print $1}')
|
||||||
|
if [ "${BASE_FILE_CHECKSUM}" = "${VM_BASE_IMAGE_CHECKSUM}" ]; then
|
||||||
|
echo "Checksum OK: ${BASE_FILE_CHECKSUM}"
|
||||||
|
else
|
||||||
|
echo "ERROR: MD5 checksum does NOT match!"
|
||||||
|
echo "Expected: ${VM_BASE_IMAGE_CHECKSUM}"
|
||||||
|
echo "Got: ${BASE_FILE_CHECKSUM}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
## 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 <<EOF > "$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_USERNAME}@${CURRENT_IP}:50-cloud-init.yaml
|
||||||
|
ssh -i ${VM_BASE_DIR}/ssh/${VM} -l${VM_USERNAME} ${CURRENT_IP} "bash -s" -- < ../vm_example_scripts/apply_netplan.sh
|
||||||
|
}
|
||||||
|
|
||||||
|
vm_net_set_bridge_mode()
|
||||||
|
{
|
||||||
|
if [[ -n $VM_BRIDGE_INT ]]; then
|
||||||
|
LIBVIRT_NET_OPTION="model=virtio,bridge=${VM_BRIDGE_INT}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
## Connect to an existent VM using ssh
|
||||||
|
vm_connect()
|
||||||
|
{
|
||||||
|
local VM=$1
|
||||||
|
local VM_IP=$(vm_net_get_ip "$VM")
|
||||||
|
ssh -i ${VM_BASE_DIR}/ssh/${VM} -l${VM_USERNAME} ${VM_IP}
|
||||||
|
}
|
||||||
|
|
||||||
|
## Delete VM
|
||||||
|
vm_delete ()
|
||||||
|
{
|
||||||
|
local VM=$1
|
||||||
|
echo "VM: $VM"
|
||||||
|
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}/ssh/$1.pub
|
||||||
|
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
|
||||||
|
}
|
||||||
|
vm_download_base_image()
|
||||||
|
{
|
||||||
|
VM_BASE_IMAGE_NAME=${VM_BASE_IMAGE%%.*}
|
||||||
|
VM_BASE_IMAGE_EXTENSION=${VM_BASE_IMAGE#*.}
|
||||||
|
VM_BASE_IMAGE_LOCATION="${VM_BASE_DIR}/${VM_BASE_IMAGES}/${VM_BASE_IMAGE_NAME}.${VM_BASE_IMAGE_EXTENSION}"
|
||||||
|
if ! test -f "${VM_BASE_IMAGE_LOCATION}"; then
|
||||||
|
wget -O "${VM_BASE_IMAGE_LOCATION}" ${VM_BASE_IMAGE_URL}
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
vm_create_guest_image()
|
||||||
|
{
|
||||||
|
echo "Creating a qcow2 image file ${VM_BASE_DIR}/images/${VM_HOSTNAME}.${VM_DISK_EXTENSION} that uses the cloud image file ${VM_BASE_IMAGE_LOCATION} as its base"
|
||||||
|
if ! test -f "${VM_BASE_DIR}/images/${VM_HOSTNAME}.${VM_DISK_EXTENSION}"; then
|
||||||
|
qemu-img convert \
|
||||||
|
-O qcow2 \
|
||||||
|
"${VM_BASE_IMAGE_LOCATION}" \
|
||||||
|
"${VM_BASE_DIR}/images/${VM_HOSTNAME}.${VM_DISK_EXTENSION}"
|
||||||
|
qemu-img resize \
|
||||||
|
"${VM_BASE_DIR}/images/${VM_HOSTNAME}.${VM_DISK_EXTENSION}" \
|
||||||
|
"${VM_DISK_SIZE}G"
|
||||||
|
sudo chown -R $USER:libvirt-qemu "${VM_BASE_DIR}/images/${VM_HOSTNAME}.${VM_DISK_EXTENSION}"
|
||||||
|
else
|
||||||
|
echo "${VM_BASE_DIR}/images/${VM_HOSTNAME}.${VM_DISK_EXTENSION} already exists. Delete VM with "delete" option"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
vm_generate_ssh_hey()
|
||||||
|
{
|
||||||
|
ssh-keygen -t rsa -b 4096 -N '' -f "${VM_BASE_DIR}/ssh/${VM_HOSTNAME}"
|
||||||
|
chmod 600 ${VM_BASE_DIR}/ssh/${VM_HOSTNAME}.pub
|
||||||
|
SSH_PUB_KEY=$(cat "${VM_BASE_DIR}/ssh/${VM_HOSTNAME}.pub")
|
||||||
|
#ssh-keygen -y -f "${VM_BASE_DIR}/ssh/${VM_HOSTNAME}" > "${VM_BASE_DIR}/ssh/${VM_HOSTNAME}".pub.txt
|
||||||
|
#SSH_PUB_KEY=$(cat "${VM_BASE_DIR}/ssh/${VM_HOSTNAME}".pub.txt)
|
||||||
|
#rm "${VM_BASE_DIR}/ssh/${VM_HOSTNAME}".pub.txt
|
||||||
|
}
|
||||||
|
|
||||||
|
vm_gen_linux_user_data()
|
||||||
|
{
|
||||||
|
VM_USER_PASS=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 8; echo)
|
||||||
|
VM_USER_PASS_HASH=$(mkpasswd --method=SHA-512 --rounds=4096 ${VM_USER_PASS})
|
||||||
|
cat <<EOF > "$VM_BASE_DIR/init/${VM_HOSTNAME}-user-data"
|
||||||
|
#cloud-config
|
||||||
|
hostname: ${VM_HOSTNAME}
|
||||||
|
# manage_etc_hosts: false
|
||||||
|
ssh_pwauth: true
|
||||||
|
disable_root: true
|
||||||
|
users:
|
||||||
|
- name: ${VM_USERNAME}
|
||||||
|
hashed_passwd: ${VM_USER_PASS_HASH}
|
||||||
|
sudo: ALL=(ALL) NOPASSWD:ALL
|
||||||
|
shell: /bin/bash
|
||||||
|
lock-passwd: false
|
||||||
|
ssh_authorized_keys:
|
||||||
|
- ${SSH_PUB_KEY}
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
vm_gen_user_data()
|
||||||
|
{
|
||||||
|
VM_USER_PASS=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 8; echo)
|
||||||
|
VM_USER_PASS_HASH=$(mkpasswd --method=SHA-512 --rounds=4096 ${VM_USER_PASS})
|
||||||
|
cp files/user-data "$VM_BASE_DIR/init/${VM_HOSTNAME}-user-data"
|
||||||
|
sed -i "s|__SSH_KEY__|${SSH_PUB_KEY}|g" "$VM_BASE_DIR/init/${VM_HOSTNAME}-user-data"
|
||||||
|
sed -i "s| __USER_PASSWORD__|${VM_USER_PASS_HASH}|g" "$VM_BASE_DIR/init/${VM_HOSTNAME}-user-data"
|
||||||
|
}
|
||||||
|
|
||||||
|
vm_gen_meta_data()
|
||||||
|
{
|
||||||
|
cp files/meta-data "$VM_BASE_DIR/init/${VM_HOSTNAME}-meta-data"
|
||||||
|
sed -i "s|__VMname__|${VM_HOSTNAME}|g" "$VM_BASE_DIR/init/${VM_HOSTNAME}-meta-data"
|
||||||
|
}
|
||||||
|
|
||||||
|
vm_guest_install()
|
||||||
|
{
|
||||||
|
VM_INSTALL_OPTS=""
|
||||||
|
VM_INSTALL_OPTS="${VM_INSTALL_OPTS} --name ${VM_HOSTNAME}"
|
||||||
|
VM_INSTALL_OPTS="${VM_INSTALL_OPTS} --memory ${VM_MEM_SIZE}"
|
||||||
|
VM_INSTALL_OPTS="${VM_INSTALL_OPTS} --vcpus ${VM_VCPUS}"
|
||||||
|
VM_INSTALL_OPTS="${VM_INSTALL_OPTS} --os-variant=${VM_OS_VARIANT}"
|
||||||
|
VM_INSTALL_OPTS="${VM_INSTALL_OPTS} --disk ${VM_BASE_DIR}/images/${VM_HOSTNAME}.img,device=disk,bus=virtio"
|
||||||
|
VM_INSTALL_OPTS="${VM_INSTALL_OPTS} --network ${LIBVIRT_NET_OPTION}"
|
||||||
|
VM_INSTALL_OPTS="${VM_INSTALL_OPTS} --autostart"
|
||||||
|
VM_INSTALL_OPTS="${VM_INSTALL_OPTS} --import --noautoconsole"
|
||||||
|
VM_INSTALL_OPTS="${VM_INSTALL_OPTS} --cloud-init user-data=${VM_BASE_DIR}/init/${VM_HOSTNAME}-user-data,meta-data=$VM_BASE_DIR/init/${VM_HOSTNAME}-meta-data"
|
||||||
|
if [ "$VM_BOOT_TYPE" = "UEFI" ]; then
|
||||||
|
VM_INSTALL_OPTS="${VM_INSTALL_OPTS} --boot uefi"
|
||||||
|
fi
|
||||||
|
eval virt-install $VM_INSTALL_OPTS
|
||||||
|
|
||||||
|
virsh dumpxml "${VM_HOSTNAME}" > "${VM_BASE_DIR}/xml/${VM_HOSTNAME}.xml"
|
||||||
|
|
||||||
|
}
|
||||||
2
files/meta-data
Normal file
2
files/meta-data
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
instance-id: __VMname__
|
||||||
|
local-hostname: __VMname__
|
||||||
14
files/network.xml
Normal file
14
files/network.xml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<network>
|
||||||
|
<name>YOURNETWORK</name>
|
||||||
|
<forward mode='nat'>
|
||||||
|
<nat>
|
||||||
|
<port start='1024' end='65535'/>
|
||||||
|
</nat>
|
||||||
|
</forward>
|
||||||
|
<bridge name='virbr1' stp='on' delay='0'/>
|
||||||
|
<ip address='192.168.100.1' netmask='255.255.255.0'>
|
||||||
|
<dhcp>
|
||||||
|
<range start='192.168.100.100' end='192.168.100.254'/>
|
||||||
|
</dhcp>
|
||||||
|
</ip>
|
||||||
|
</network>
|
||||||
68
files/os_options.json
Normal file
68
files/os_options.json
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
{
|
||||||
|
"os_variants": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"name": "Debian 12",
|
||||||
|
"variant": "$GUEST_OS_TYPE_DEBIAN",
|
||||||
|
"url": "https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-generic-amd64.qcow2",
|
||||||
|
"origin_image_name": "debian-12-generic-amd64.qcow2",
|
||||||
|
"md5sum": "https://cdimage.debian.org/images/cloud/bookworm/latest/SHA512SUMS",
|
||||||
|
"boot_type": "bios"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"name": "Ubuntu 20.04 server",
|
||||||
|
"variant": "ubuntu20.04",
|
||||||
|
"url": "https://cloud-images.ubuntu.com/focal/current/focal-server-cloudimg-amd64.img",
|
||||||
|
"origin_image_name": "focal-server-cloudimg-amd64.img",
|
||||||
|
"md5sum": "https://cloud-images.ubuntu.com/focal/current/SHA256SUMS",
|
||||||
|
"boot_type": "bios"
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"name": "Ubuntu 20.04 minimal",
|
||||||
|
"variant": "ubuntu20.04",
|
||||||
|
"url": "https://cloud-images.ubuntu.com/minimal/releases/focal/release/ubuntu-20.04-minimal-cloudimg-amd64.img",
|
||||||
|
"origin_image_name": "ubuntu-20.04-minimal-cloudimg-amd64.img",
|
||||||
|
"md5sum": "https://cloud-images.ubuntu.com/minimal/releases/focal/release/SHA256SUMS",
|
||||||
|
"boot_type": "bios"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4,
|
||||||
|
"name": "Ubuntu 22.04 server",
|
||||||
|
"variant": "ubuntu22.04",
|
||||||
|
"url": "https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img",
|
||||||
|
"origin_image_name": "jammy-server-cloudimg-amd64.img",
|
||||||
|
"md5sum": "https://cloud-images.ubuntu.com/jammy/current/SHA256SUMS",
|
||||||
|
"boot_type": "uefi"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 5,
|
||||||
|
"name": "Ubuntu 22.04 minimal",
|
||||||
|
"variant": "ubuntu22.04",
|
||||||
|
"url": "https://cloud-images.ubuntu.com/minimal/releases/jammy/release/ubuntu-22.04-minimal-cloudimg-amd64.img",
|
||||||
|
"origin_image_name": "ubuntu-22.04-minimal-cloudimg-amd64.img",
|
||||||
|
"md5sum": "https://cloud-images.ubuntu.com/minimal/releases/jammy/release/SHA256SUMS",
|
||||||
|
"boot_type": "uefi"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 6,
|
||||||
|
"name": "Ubuntu 24.04 server",
|
||||||
|
"variant": "ubuntu22.04",
|
||||||
|
"url": "https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img",
|
||||||
|
"origin_image_name": "noble-server-cloudimg-amd64.img",
|
||||||
|
"md5sum": "https://cloud-images.ubuntu.com/noble/current/SHA256SUMS",
|
||||||
|
"boot_type": "uefi"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 7,
|
||||||
|
"name": "Ubuntu 24.04 minimal",
|
||||||
|
"variant": "ubuntu22.04",
|
||||||
|
"url": "https://cloud-images.ubuntu.com/minimal/releases/noble/release/ubuntu-24.04-minimal-cloudimg-amd64.img",
|
||||||
|
"origin_image_name": "ubuntu-24.04-minimal-cloudimg-amd64.img",
|
||||||
|
"md5sum": "https://cloud-images.ubuntu.com/minimal/releases/noble/release/SHA256SUMS",
|
||||||
|
"boot_type": "uefi"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
12
files/user-data
Normal file
12
files/user-data
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
ssh_pwauth: true
|
||||||
|
disable_root: true
|
||||||
|
users:
|
||||||
|
- name: user
|
||||||
|
ssh_authorized_keys:
|
||||||
|
- __SSH_KEY__
|
||||||
|
sudo: ["ALL=(ALL) NOPASSWD:ALL"]
|
||||||
|
groups: sudo
|
||||||
|
shell: /bin/bash
|
||||||
|
hashed_passwd: __USER_PASSWORD__
|
||||||
|
lock-passwd: false
|
||||||
|
|
||||||
13
install.sh
Normal file
13
install.sh
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#!/bin/env bash
|
||||||
|
#Define variable names on env_scripts/common.sh
|
||||||
|
#VM_NETWORK=
|
||||||
|
#VM_BASE_DIR=
|
||||||
|
#Install dependencies - TODO
|
||||||
|
source variables/common.sh
|
||||||
|
|
||||||
|
mkdir -p "${VM_BASE_DIR}"/{images,xml,init,base,ssh}
|
||||||
|
cp files/network.xml ${VM_BASE_DIR}/xml/network.xml
|
||||||
|
sed -i "s/YOURNETWORK/${VM_NETWORK}/g" ${VM_BASE_DIR}/xml/network.xml
|
||||||
|
virsh net-define ${VM_BASE_DIR}/xml/network.xml
|
||||||
|
virsh net-autostart ${VM_NETWORK}
|
||||||
|
virsh net-start ${VM_NETWORK}
|
||||||
68
os_option_test.json
Normal file
68
os_option_test.json
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
{
|
||||||
|
"os_variants": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"name": "Debian 12",
|
||||||
|
"variant": "$GUEST_OS_TYPE_DEBIAN",
|
||||||
|
"url": "https://cloud.debian.org/images/cloud/bookworm/latest/debian-12-generic-amd64.qcow2",
|
||||||
|
"origin_image_name": "debian-12-generic-amd64.qcow2",
|
||||||
|
"md5sum": "https://cdimage.debian.org/images/cloud/bookworm/latest/SHA512SUMS",
|
||||||
|
"boot_type": "bios"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 2,
|
||||||
|
"name": "Ubuntu 20.04 server",
|
||||||
|
"variant": "ubuntu20.04",
|
||||||
|
"url": "https://cloud-images.ubuntu.com/focal/current/focal-server-cloudimg-amd64.img",
|
||||||
|
"origin_image_name": "focal-server-cloudimg-amd64.img",
|
||||||
|
"md5sum": "https://cloud-images.ubuntu.com/focal/current/SHA256SUMS",
|
||||||
|
"boot_type": "bios"
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 3,
|
||||||
|
"name": "Ubuntu 20.04 minimal",
|
||||||
|
"variant": "ubuntu20.04",
|
||||||
|
"url": "https://cloud-images.ubuntu.com/minimal/releases/focal/release/ubuntu-20.04-minimal-cloudimg-amd64.img",
|
||||||
|
"origin_image_name": "ubuntu-20.04-minimal-cloudimg-amd64.img",
|
||||||
|
"md5sum": "https://cloud-images.ubuntu.com/minimal/releases/focal/release/SHA256SUMS",
|
||||||
|
"boot_type": "bios"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 4,
|
||||||
|
"name": "Ubuntu 22.04 server",
|
||||||
|
"variant": "ubuntu22.04",
|
||||||
|
"url": "https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img",
|
||||||
|
"origin_image_name": "jammy-server-cloudimg-amd64.img",
|
||||||
|
"md5sum": "https://cloud-images.ubuntu.com/jammy/current/SHA256SUMS",
|
||||||
|
"boot_type": "uefi"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 5,
|
||||||
|
"name": "Ubuntu 22.04 minimal",
|
||||||
|
"variant": "ubuntu22.04",
|
||||||
|
"url": "https://cloud-images.ubuntu.com/minimal/releases/jammy/release/ubuntu-22.04-minimal-cloudimg-amd64.img",
|
||||||
|
"origin_image_name": "ubuntu-22.04-minimal-cloudimg-amd64.img",
|
||||||
|
"md5sum": "https://cloud-images.ubuntu.com/minimal/releases/jammy/release/SHA256SUMS",
|
||||||
|
"boot_type": "uefi"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 6,
|
||||||
|
"name": "Ubuntu 24.04 server",
|
||||||
|
"variant": "ubuntu22.04",
|
||||||
|
"url": "https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.img",
|
||||||
|
"origin_image_name": "noble-server-cloudimg-amd64.img",
|
||||||
|
"md5sum": "https://cloud-images.ubuntu.com/noble/current/SHA256SUMS",
|
||||||
|
"boot_type": "uefi"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": 7,
|
||||||
|
"name": "Ubuntu 24.04 minimal",
|
||||||
|
"variant": "ubuntu22.04",
|
||||||
|
"url": "https://cloud-images.ubuntu.com/minimal/releases/noble/release/ubuntu-24.04-minimal-cloudimg-amd64.img",
|
||||||
|
"origin_image_name": "ubuntu-24.04-minimal-cloudimg-amd64.img",
|
||||||
|
"md5sum": "https://cloud-images.ubuntu.com/minimal/releases/noble/release/SHA256SUMS",
|
||||||
|
"boot_type": "uefi"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -1,23 +0,0 @@
|
|||||||
#!/bin/env bash
|
|
||||||
#Variables
|
|
||||||
VM="$1"
|
|
||||||
VM_BASE_DIR=${VM_BASE_DIR:-"${HOME}/vms"}
|
|
||||||
VM_USER="user"
|
|
||||||
#Functions
|
|
||||||
usage() {
|
|
||||||
cat << EOF
|
|
||||||
USO: $0 VM
|
|
||||||
|
|
||||||
Este script conecta por ssh con la maquina virtual seleccionada.
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
connect_vm() {
|
|
||||||
local VM_IP=$(./vm_get_ip.sh ${VM})
|
|
||||||
ssh -i ${VM_BASE_DIR}/ssh/${VM} -l${VM_USER} ${VM_IP}
|
|
||||||
}
|
|
||||||
if [[ -z "$VM" ]]; then
|
|
||||||
usage
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
connect_vm
|
|
||||||
289
vm_create.sh
289
vm_create.sh
@ -1,289 +0,0 @@
|
|||||||
#!/bin/env bash
|
|
||||||
VM_HOSTNAME=
|
|
||||||
VM_BASE_DIR=${VM_BASE_DIR:-"${HOME}/vms"}
|
|
||||||
VM_DISK_SIZE=20
|
|
||||||
VM_DISK_FORMAT=qcow2
|
|
||||||
VM_MEM_SIZE=2048
|
|
||||||
VM_VCPUS=2
|
|
||||||
VM_BASE_IMAGE=
|
|
||||||
VM_OS_VARIANT=
|
|
||||||
VM_USERNAME="user"
|
|
||||||
VM_BRIDGE_INT=
|
|
||||||
VM_NET_USED="PU-internalTests"
|
|
||||||
LIBVIRT_NET_OPTION="network=$VM_NET_USED,model=e1000"
|
|
||||||
HAT_STREAM="stable"
|
|
||||||
# Functions
|
|
||||||
usage()
|
|
||||||
{
|
|
||||||
cat << EOF
|
|
||||||
usage: $0 options
|
|
||||||
|
|
||||||
Quickly create guest VMs using cloud image files and cloud-init.
|
|
||||||
|
|
||||||
OPTIONS:
|
|
||||||
-h Show this message
|
|
||||||
-n Host name (required)
|
|
||||||
-b bridge interface name (bridge network is used)
|
|
||||||
-r RAM in MB (defaults to ${VM_MEM_SIZE})
|
|
||||||
-c Number of VCPUs (defaults to ${VM_VCPUS})
|
|
||||||
-s Amount of storage to allocate in GB (defaults to ${VM_DISK_SIZE})
|
|
||||||
-v Verbose
|
|
||||||
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
|
|
||||||
|
|
||||||
download_base_image()
|
|
||||||
{
|
|
||||||
if ! test -f "${VM_BASE_DIR}/base/$VM_OS_VARIANT.qcow2"; then
|
|
||||||
if [[ "$VM_OS_VARIANT" == "freebsd14.2" ]]; then
|
|
||||||
VM_DISK_FORMAT="qcow2.xz"
|
|
||||||
cd ${VM_BASE_DIR}/base/
|
|
||||||
wget -v -O "${VM_BASE_DIR}/base/$VM_OS_VARIANT.${VM_DISK_FORMAT}" ${VM_BASE_IMAGE}
|
|
||||||
xz -d $VM_OS_VARIANT.${VM_DISK_FORMAT}
|
|
||||||
mv $VM_OS_VARIANT.${VM_DISK_FORMAT} $VM_OS_VARIANT.img
|
|
||||||
cd -
|
|
||||||
elif [[ "$VM_OS_VARIANT" == "fedora-coreos-stable" ]]; then
|
|
||||||
podman run --pull=always --rm \
|
|
||||||
-v /dev:/dev -v /run/udev:/run/udev \
|
|
||||||
-v $VM_BASE_DIR/base:/data -w /data \
|
|
||||||
quay.io/coreos/coreos-installer:release \
|
|
||||||
download -s ${HAT_STREAM} -p qemu -f qcow2.xz --decompress -C .
|
|
||||||
mv $VM_BASE_DIR/base/fedora-coreos-*.qcow2 $VM_BASE_DIR/base/"$VM_OS_VARIANT".qcow2
|
|
||||||
else
|
|
||||||
wget -v -O "${VM_BASE_DIR}/base/$VM_OS_VARIANT.${VM_DISK_FORMAT}" ${VM_BASE_IMAGE}
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
gen_coreos_data()
|
|
||||||
{
|
|
||||||
cat <<EOF > "$VM_BASE_DIR/init/${VM_HOSTNAME}-user-data.bu"
|
|
||||||
variant: fcos
|
|
||||||
version: 1.6.0
|
|
||||||
passwd:
|
|
||||||
users:
|
|
||||||
- name: core
|
|
||||||
ssh_authorized_keys:
|
|
||||||
- ${SSH_PUB_KEY}
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
gen_linux_user_data()
|
|
||||||
{
|
|
||||||
VM_USER_PASS=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 8; echo)
|
|
||||||
VM_USER_PASS_HASH=$(mkpasswd --method=SHA-512 --rounds=4096 ${VM_USER_PASS})
|
|
||||||
cat <<EOF > "$VM_BASE_DIR/init/${VM_HOSTNAME}-user-data"
|
|
||||||
#cloud-config
|
|
||||||
hostname: ${VM_HOSTNAME}
|
|
||||||
# manage_etc_hosts: false
|
|
||||||
ssh_pwauth: true
|
|
||||||
disable_root: true
|
|
||||||
users:
|
|
||||||
- name: ${VM_USERNAME}
|
|
||||||
hashed_passwd: ${VM_USER_PASS_HASH}
|
|
||||||
sudo: ALL=(ALL) NOPASSWD:ALL
|
|
||||||
shell: /bin/bash
|
|
||||||
lock-passwd: false
|
|
||||||
ssh_authorized_keys:
|
|
||||||
- ${SSH_PUB_KEY}
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
gen_freebsd_user_data()
|
|
||||||
{
|
|
||||||
#VM_ROOT_PASS=$(tr -dc A-Za-z0-9 </dev/urandom | head -c 16; echo)
|
|
||||||
VM_ROOT_PASS="changeme"
|
|
||||||
echo "Generated root passwd: ${VM_ROOT_PASS}"
|
|
||||||
VM_ROOT_PASS_HASH=$(mkpasswd --method=SHA-512 --rounds=4096 ${VM_ROOT_PASS})
|
|
||||||
# Write FreeBSD 13.2 user-data
|
|
||||||
VM_USER_PASS="sasasa123"
|
|
||||||
VM_USER_PASS_HASH=$(mkpasswd --method=SHA-512 --rounds=4096 ${VM_USER_PASS})
|
|
||||||
cat <<EOF > "$VM_BASE_DIR/init/${VM_HOSTNAME}-user-data"
|
|
||||||
#cloud-config
|
|
||||||
users:
|
|
||||||
- name: root
|
|
||||||
lock_passwd: false
|
|
||||||
hashed_passwd: ${VM_ROOT_PASS}
|
|
||||||
- name: ${VM_USERNAME}
|
|
||||||
ssh_authorized_keys:
|
|
||||||
- ssh-rsa ${SSH_PUB_KEY}
|
|
||||||
groups: wheel
|
|
||||||
ssh_pwauth: true
|
|
||||||
hashed_passwd: ${VM_USER_PASS_HASH}
|
|
||||||
write_files:
|
|
||||||
- path: /usr/local/etc/sudoers
|
|
||||||
content: |
|
|
||||||
%wheel ALL=(ALL) NOPASSWD: ALL
|
|
||||||
append: true
|
|
||||||
EOF
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
while getopts "h:n:net:b:r:c:s:v" option; do
|
|
||||||
case "${option}"
|
|
||||||
in
|
|
||||||
h)
|
|
||||||
usage
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
n) VM_HOSTNAME=${OPTARG};;
|
|
||||||
b) VM_BRIDGE_INT=${OPTARG};;
|
|
||||||
r) VM_MEM_SIZE=${OPTARG};;
|
|
||||||
c) VM_VCPUS=${OPTARG};;
|
|
||||||
s) VM_DISK_SIZE=${OPTARG};;
|
|
||||||
v) VERBOSE=1;;
|
|
||||||
*)
|
|
||||||
usage
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
if [[ -z $VM_HOSTNAME ]]; then
|
|
||||||
echo "ERROR: Host name is required"
|
|
||||||
usage
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -n $VERBOSE ]]; then
|
|
||||||
echo "Building ${VM_HOSTNAME} in $VM_IMAGE_DIR"
|
|
||||||
set -xv
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -n $VM_BRIDGE_INT ]]; then
|
|
||||||
LIBVIRT_NET_OPTION="model=virtio,bridge=${VM_BRIDGE_INT}"
|
|
||||||
fi
|
|
||||||
|
|
||||||
mkdir -p "$VM_BASE_DIR"/{images,xml,init,base,ssh}
|
|
||||||
|
|
||||||
## VM Base image
|
|
||||||
if [ -n "$VM_BASE_IMAGE" ] && [ -f "$VM_BASE_IMAGE" ]; then
|
|
||||||
download_base_image
|
|
||||||
else
|
|
||||||
while true; do
|
|
||||||
read -r -p $'Select VM OS:\n 1.Debian12\n 2.Ubuntu 20.04\n 3.Ubuntu 22.04\n 4.Ubuntu 24.04 \n 5.FreeBSD 14\n 6.Alpine Linux\n 7.Fedora CoreOS' -n1 answer
|
|
||||||
case $answer in
|
|
||||||
[1]* ) VM_OS_VARIANT='debian11'
|
|
||||||
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.2'
|
|
||||||
VM_BASE_IMAGE='https://download.freebsd.org/ftp/releases/VM-IMAGES/14.2-RELEASE/amd64/Latest/FreeBSD-14.2-RELEASE-amd64-BASIC-CLOUDINIT.ufs.qcow2.xz'
|
|
||||||
break;;
|
|
||||||
[6]* ) VM_OS_VARIANT='alpinelinux3.20'
|
|
||||||
VM_BASE_IMAGE='https://dl-cdn.alpinelinux.org/alpine/v3.21/releases/cloud/generic_alpine-3.21.2-x86_64-bios-tiny-r0.qcow2"'
|
|
||||||
break;;
|
|
||||||
[7]* ) VM_OS_VARIANT='fedora-coreos-stable'
|
|
||||||
#VM_BASE_IMAGE='https://dl-cdn.alpinelinux.org/alpine/v3.21/releases/cloud/generic_alpine-3.21.2-x86_64-bios-tiny-r0.qcow2"'
|
|
||||||
break;;
|
|
||||||
* ) echo "Please answer 1,2,3,4,5,6,7.";;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
download_base_image
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
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 "${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
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
# VM ssh keys gen
|
|
||||||
if [ -f "${VM_BASE_IMAGE}/ssh/${VM_HOSTNAME}" ]; then
|
|
||||||
echo "Ya existe una clave ssh para la maquina ${VM_HOSTNAME}"
|
|
||||||
else
|
|
||||||
ssh-keygen -t rsa -b 4096 -N '' -f "${VM_BASE_DIR}/ssh/${VM_HOSTNAME}"
|
|
||||||
chmod 600 ${VM_BASE_DIR}/ssh/${VM_HOSTNAME}.pub
|
|
||||||
ssh-keygen -y -f "${VM_BASE_DIR}/ssh/${VM_HOSTNAME}" > "${VM_BASE_DIR}/ssh/${VM_HOSTNAME}".pub.txt
|
|
||||||
SSH_PUB_KEY=$(cat "${VM_BASE_DIR}/ssh/${VM_HOSTNAME}".pub.txt)
|
|
||||||
rm "${VM_BASE_DIR}/ssh/${VM_HOSTNAME}".pub.txt
|
|
||||||
fi
|
|
||||||
#cloud-init VM meta-data
|
|
||||||
cat > "$VM_BASE_DIR/init/${VM_HOSTNAME}-meta-data" << EOF
|
|
||||||
instance-id: ${VM_HOSTNAME}
|
|
||||||
local-hostname: ${VM_HOSTNAME}
|
|
||||||
EOF
|
|
||||||
#cloud-init VM user-data
|
|
||||||
if [[ "$VM_OS_VARIANT" == "freebsd14.2" ]]; then
|
|
||||||
gen_freebsd_user_data
|
|
||||||
# genisoimage \
|
|
||||||
# -output ${VM_BASE_DIR}/images/${VM_HOSTNAME}-cidata.iso \
|
|
||||||
# -V cidata -r \
|
|
||||||
# -J ${VM_BASE_DIR}/init/${VM_HOSTNAME}-user-data ${VM_BASE_DIR}/init/${VM_HOSTNAME}-meta-data
|
|
||||||
# virt-install \
|
|
||||||
# --name ${VM_HOSTNAME} \
|
|
||||||
# --memory ${VM_MEM_SIZE} \
|
|
||||||
# --vcpus="${VM_VCPUS}" \
|
|
||||||
# --os-variant=${VM_OS_VARIANT} \
|
|
||||||
# --disk ${VM_BASE_DIR}/images/${VM_HOSTNAME}.img,device=disk,bus=virtio \
|
|
||||||
# --disk path=${VM_BASE_DIR}/images/${VM_HOSTNAME}-cidata.iso,device=cdrom \
|
|
||||||
# --network ${LIBVIRT_NET_OPTION} \
|
|
||||||
# --autostart \
|
|
||||||
# --import --noautoconsole \
|
|
||||||
# --cloud-init root-password-generate=on,user-data=${VM_BASE_DIR}/init/${VM_HOSTNAME}-user-data
|
|
||||||
elif [[ "$VM_OS_VARIANT" == "fedora-coreos-stable" ]]; then
|
|
||||||
gen_coreos_data
|
|
||||||
else
|
|
||||||
gen_linux_user_data
|
|
||||||
fi
|
|
||||||
if [[ "$VM_OS_VARIANT" == "fedora-coreos-stable" ]]; then
|
|
||||||
IGNITION_CONFIG="${VM_BASE_DIR}/init/${VM_HOSTNAME}.ign"
|
|
||||||
BUTANE_CONFIG="$VM_BASE_DIR/init/${VM_HOSTNAME}-user-data.bu"
|
|
||||||
IGNITION_DEVICE_ARG=(--qemu-commandline="-fw_cfg name=opt/com.coreos/config,file=${IGNITION_CONFIG}")
|
|
||||||
#Generate ignition config
|
|
||||||
podman run --interactive --rm quay.io/coreos/butane:release \
|
|
||||||
--pretty --strict < ${BUTANE_CONFIG} > ${IGNITION_CONFIG}
|
|
||||||
chown ${USERNAME}:libvirt-qemu /home/victor/vms/init/*
|
|
||||||
#Install
|
|
||||||
virt-install \
|
|
||||||
--connect="qemu:///system" \
|
|
||||||
--name ${VM_HOSTNAME} \
|
|
||||||
--memory ${VM_MEM_SIZE} \
|
|
||||||
--vcpus="${VM_VCPUS}" \
|
|
||||||
--os-variant=${VM_OS_VARIANT} \
|
|
||||||
--disk ${VM_BASE_DIR}/images/${VM_HOSTNAME}.img,device=disk,bus=virtio \
|
|
||||||
--autostart \
|
|
||||||
--import --noautoconsole \
|
|
||||||
--network ${LIBVIRT_NET_OPTION} "${IGNITION_DEVICE_ARG[@]}"
|
|
||||||
#https://unix.stackexchange.com/questions/578086/virt-install-error-cant-load-ignit
|
|
||||||
else
|
|
||||||
virt-install \
|
|
||||||
--name ${VM_HOSTNAME} \
|
|
||||||
--memory ${VM_MEM_SIZE} \
|
|
||||||
--vcpus="${VM_VCPUS}" \
|
|
||||||
--os-variant=${VM_OS_VARIANT} \
|
|
||||||
--disk ${VM_BASE_DIR}/images/${VM_HOSTNAME}.img,device=disk,bus=virtio \
|
|
||||||
--network ${LIBVIRT_NET_OPTION} \
|
|
||||||
--autostart \
|
|
||||||
--import --noautoconsole \
|
|
||||||
--cloud-init root-password-generate=on,user-data=${VM_BASE_DIR}/init/${VM_HOSTNAME}-user-data
|
|
||||||
# cloud-localds \
|
|
||||||
# ${VM_BASE_DIR}/images/${VM_HOSTNAME}.iso \
|
|
||||||
# ${VM_BASE_DIR}/init/${VM_HOSTNAME}-user-data
|
|
||||||
fi
|
|
||||||
virsh dumpxml "${VM_HOSTNAME}" > "${VM_BASE_DIR}/xml/${VM_HOSTNAME}.xml"
|
|
||||||
|
|
||||||
if [ -n $VERBOSE ]; then
|
|
||||||
set +xv
|
|
||||||
fi
|
|
||||||
# Show running VMs
|
|
||||||
virsh list
|
|
||||||
42
vm_delete.sh
42
vm_delete.sh
@ -1,42 +0,0 @@
|
|||||||
#!/bin/env bash
|
|
||||||
|
|
||||||
# Function for usage message
|
|
||||||
usage() {
|
|
||||||
cat << EOF
|
|
||||||
Usage: $0 vm_name
|
|
||||||
|
|
||||||
This script removes a virtual machine managed by virsh.
|
|
||||||
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
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"
|
|
||||||
|
|
||||||
# Validate VM name argument
|
|
||||||
if [[ -z "$1" ]]; then
|
|
||||||
usage
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check if VM exists
|
|
||||||
if [[ -f "$VM_IMAGE_PATH" ]]; then
|
|
||||||
# Safely remove the VM with confirmation
|
|
||||||
read -p "Are you sure you want to remove the VM '$1' (y/N)? " confirm
|
|
||||||
if [[ "$confirm" =~ ^[Yy]$ ]]; then
|
|
||||||
# Attempt to stop the VM before deleting
|
|
||||||
virsh destroy "$1" 2>/dev/null || true
|
|
||||||
# Delete VM definition and associated images
|
|
||||||
virsh undefine "$1" 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
|
|
||||||
41
vm_get_ip.sh
41
vm_get_ip.sh
@ -1,41 +0,0 @@
|
|||||||
#!/bin/env bash
|
|
||||||
usage() {
|
|
||||||
cat << EOF
|
|
||||||
USO: $0 VM
|
|
||||||
|
|
||||||
Este script recupera la dirección IP de una máquina virtual administrada por virsh.
|
|
||||||
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
# Función para obtener la dirección IP de la máquina virtual
|
|
||||||
get_vm_ip_address() {
|
|
||||||
local VM="$1"
|
|
||||||
|
|
||||||
# Obtener la dirección MAC de la interfaz de red
|
|
||||||
MAC_VM=$(virsh domiflist "$VM" | awk '{ print $5 }' | tail -2 | head -1)
|
|
||||||
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"
|
|
||||||
}
|
|
||||||
|
|
||||||
# Obtener el nombre del host de la máquina virtual
|
|
||||||
VM="$1"
|
|
||||||
|
|
||||||
if [[ -z "$VM" ]]; then
|
|
||||||
usage
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Obtener la dirección IP de la máquina virtual
|
|
||||||
get_vm_ip_address "$VM"
|
|
||||||
@ -1,88 +0,0 @@
|
|||||||
#!/bin/env bash
|
|
||||||
VM_BASE_DIR=${VM_BASE_DIR:-"${HOME}/vms"}
|
|
||||||
VM_USER="user"
|
|
||||||
VM=$1
|
|
||||||
VM_IP=''
|
|
||||||
SCRIPT=''
|
|
||||||
VM_DISTRO=''
|
|
||||||
VM_VERSION=''
|
|
||||||
usage() {
|
|
||||||
cat << EOF
|
|
||||||
USO: $0 VM
|
|
||||||
|
|
||||||
Este script instala algunos programas en la VM seleccionada
|
|
||||||
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
# Función para obtener la dirección IP de la máquina virtual
|
|
||||||
get_vm_ip_address() {
|
|
||||||
local VM="$1"
|
|
||||||
|
|
||||||
# Obtener la dirección MAC de la interfaz de red
|
|
||||||
MAC_VM=$(virsh domiflist "$VM" | awk '{ print $5 }' | tail -2 | head -1)
|
|
||||||
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"
|
|
||||||
}
|
|
||||||
|
|
||||||
obtener_info_vm() {
|
|
||||||
# Obtener el ID del sistema operativo
|
|
||||||
# Obtener el ID del sistema operativo
|
|
||||||
OS_ID=$(grep -o 'id="[^"]*"' "$1" | tr -d '"' | awk '{print $1}')
|
|
||||||
|
|
||||||
# Eliminar el protocolo y el dominio del ID
|
|
||||||
OS_ID=$(echo "$OS_ID" | cut -d '/' -f 2-)
|
|
||||||
echo $OS_ID
|
|
||||||
# Convertir la URL a un nombre de distribución y versión
|
|
||||||
VM_DISTRO=$(echo "$OS_ID" | awk -F '/' '{print $3}')
|
|
||||||
VM_VERSION=$(echo "$OS_ID" | awk -F '/' '{print $4}')
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
# Obtener el nombre del host de la máquina virtual
|
|
||||||
VM="$1"
|
|
||||||
|
|
||||||
if [[ -z "$VM" ]]; then
|
|
||||||
usage
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Obtener la dirección IP de la máquina virtual
|
|
||||||
VM_IP=$(get_vm_ip_address "$VM")
|
|
||||||
obtener_info_vm ${VM_BASE_DIR}/xml/${VM}.xml
|
|
||||||
while true; do
|
|
||||||
read -r -p $'Select software to install:\n 1.Docker\n 2.Gitlab CE\n 3.Gitlab runner\n 4.Kubernetes Single cluster\n' -n1 answer
|
|
||||||
case $answer in
|
|
||||||
[1]* )
|
|
||||||
if [[ "$VM_DISTRO" == "debian" ]]; then
|
|
||||||
SCRIPT='../vm_example_scripts/docker_debian.sh'
|
|
||||||
elif [[ "$VM_DISTRO" == "ubuntu" ]]; then
|
|
||||||
SCRIPT='../vm_example_scripts/docker_ubuntu.sh'
|
|
||||||
fi
|
|
||||||
break;;
|
|
||||||
[2]* ) SCRIPT='../vm_example_scripts/gitlab_ce.sh'
|
|
||||||
break;;
|
|
||||||
[3]* ) SCRIPT='../vm_example_scripts/gitlab_runner.sh'
|
|
||||||
break;;
|
|
||||||
[4]* ) cd ../vm_example_scripts/
|
|
||||||
./k8s.sh $VM
|
|
||||||
break;;
|
|
||||||
* ) echo "Please answer 1,2,3 or 4.";;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
if [[ -z "$SCRIPT" ]]; then
|
|
||||||
exit 0
|
|
||||||
else
|
|
||||||
ssh -i ${VM_BASE_DIR}/ssh/${VM} -l${VM_USER} ${VM_IP} "bash -s" -- < ${SCRIPT}
|
|
||||||
fi
|
|
||||||
@ -1,2 +0,0 @@
|
|||||||
#!/bin/env bash
|
|
||||||
virsh list
|
|
||||||
143
vm_manage.sh
Executable file
143
vm_manage.sh
Executable file
@ -0,0 +1,143 @@
|
|||||||
|
#!/bin/env bash
|
||||||
|
|
||||||
|
source env_scripts/common.sh
|
||||||
|
source env_scripts/functions.sh
|
||||||
|
# Default values for VM creation parameters
|
||||||
|
VM_MEM_SIZE=1024
|
||||||
|
VM_VCPUS=1
|
||||||
|
VM_DISK_SIZE=10
|
||||||
|
|
||||||
|
# Function to display usage message
|
||||||
|
usage() {
|
||||||
|
echo "Usage: $0 create -n NAME [-b BRIDGE] [-r RAM] [-c VCPUS] [-s DISK] [-v]"
|
||||||
|
echo " $0 delete -n NAME"
|
||||||
|
echo " $0 info -n NAME"
|
||||||
|
echo " $0 connect -n NAME"
|
||||||
|
echo " $0 list"
|
||||||
|
echo ""
|
||||||
|
echo "Actions:"
|
||||||
|
echo " create Create a new virtual machine"
|
||||||
|
echo " delete Delete a virtual machine"
|
||||||
|
echo " list List all defined virtual machines"
|
||||||
|
echo " info Show information about a virtual machine"
|
||||||
|
echo " connect Connect to the console of a virtual machine"
|
||||||
|
echo ""
|
||||||
|
echo "Options for 'create':"
|
||||||
|
echo " -h Show this help message"
|
||||||
|
echo " -n NAME Host name (required)"
|
||||||
|
echo " -b BRIDGE Bridge interface name"
|
||||||
|
echo " -r RAM RAM in MB (default: ${VM_MEM_SIZE})"
|
||||||
|
echo " -c VCPUS Number of VCPUs (default: ${VM_VCPUS})"
|
||||||
|
echo " -s DISK Disk size in GB (default: ${VM_DISK_SIZE})"
|
||||||
|
echo " -v Verbose mode"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Check if at least one argument is provided
|
||||||
|
if [ $# -eq 0 ]; then
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
|
||||||
|
ACTION="$1"
|
||||||
|
shift
|
||||||
|
|
||||||
|
case "${ACTION}" in
|
||||||
|
create)
|
||||||
|
# Parse options for create command
|
||||||
|
VERBOSE=false
|
||||||
|
NAME_SET=false
|
||||||
|
|
||||||
|
while getopts ":hn:b:r:c:s:v" opt; do
|
||||||
|
case "${opt}" in
|
||||||
|
h)
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
n)
|
||||||
|
VM_HOSTNAME="${OPTARG}"
|
||||||
|
NAME_SET=true
|
||||||
|
;;
|
||||||
|
b)
|
||||||
|
BRIDGE_INTERFACE="${OPTARG}"
|
||||||
|
;;
|
||||||
|
r)
|
||||||
|
VM_MEM_SIZE="${OPTARG}"
|
||||||
|
;;
|
||||||
|
c)
|
||||||
|
VM_VCPUS="${OPTARG}"
|
||||||
|
;;
|
||||||
|
s)
|
||||||
|
VM_DISK_SIZE="${OPTARG}"
|
||||||
|
;;
|
||||||
|
v)
|
||||||
|
VERBOSE=true
|
||||||
|
;;
|
||||||
|
\?)
|
||||||
|
echo "Invalid option: -${OPTARG}" >&2
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
:)
|
||||||
|
echo "Option -${OPTARG} requires an argument." >&2
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
# Check that required parameter (-n) was provided
|
||||||
|
if ! ${NAME_SET}; then
|
||||||
|
echo "Error: The -n option is required for create action." >&2
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
source env_scripts/common.sh
|
||||||
|
#Check network type
|
||||||
|
vm_net_set_bridge_mode
|
||||||
|
#Check host os for guest debian type
|
||||||
|
check_host_os
|
||||||
|
#Read os_options.json and generate guests menu
|
||||||
|
#Select guest
|
||||||
|
show_vm_menu
|
||||||
|
#Download cloud image
|
||||||
|
vm_download_base_image
|
||||||
|
#Compare hashes
|
||||||
|
compare_checksum
|
||||||
|
#Create guest image
|
||||||
|
vm_create_guest_image
|
||||||
|
#Generate ssh key
|
||||||
|
vm_generate_ssh_hey
|
||||||
|
#Generate meta-data file for VM
|
||||||
|
vm_gen_meta_data
|
||||||
|
#Generate user-data file for VM
|
||||||
|
vm_gen_linux_user_data
|
||||||
|
#Install VM
|
||||||
|
vm_guest_install
|
||||||
|
;;
|
||||||
|
|
||||||
|
delete|info|connect)
|
||||||
|
# These actions require a NAME directly as first argument after ACTION
|
||||||
|
if [ $# -ne 1 ]; then
|
||||||
|
echo "Error: ${ACTION} requires a VM name as argument." >&2
|
||||||
|
usage
|
||||||
|
fi
|
||||||
|
VM_HOSTNAME="$1"
|
||||||
|
source env_scripts/common.sh
|
||||||
|
echo "Action: ${ACTION}"
|
||||||
|
echo "VM Name: ${VM_HOSTNAME}"
|
||||||
|
if [[ "${ACTION}" == 'delete' ]]; then
|
||||||
|
vm_delete ${VM_HOSTNAME}
|
||||||
|
elif [[ "${ACTION}" == 'info' ]]; then
|
||||||
|
vm_net_get_ip ${VM_HOSTNAME}
|
||||||
|
elif [[ "${ACTION}" == 'connect' ]]; then
|
||||||
|
vm_connect ${VM_HOSTNAME}
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
|
||||||
|
list)
|
||||||
|
#echo "Action: list"
|
||||||
|
vm_list
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
echo "Unknown action: ${ACTION}" >&2
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
exit 0
|
||||||
80
vm_set_ip.sh
80
vm_set_ip.sh
@ -1,80 +0,0 @@
|
|||||||
#!/bin/env bash
|
|
||||||
|
|
||||||
VM_BASE_DIR=${VM_BASE_DIR:-"${HOME}/vms"}
|
|
||||||
VM_USER="user"
|
|
||||||
MAC_VM=
|
|
||||||
usage() {
|
|
||||||
cat << EOF
|
|
||||||
USO: $0 VM
|
|
||||||
|
|
||||||
Este script setea la dirección IP de una máquina virtual administrada por virsh.
|
|
||||||
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
# Función para obtener la dirección IP de la máquina virtual
|
|
||||||
get_vm_ip_address() {
|
|
||||||
local VM="$1"
|
|
||||||
|
|
||||||
# Obtener la dirección MAC de la interfaz de red
|
|
||||||
MAC_VM=$(virsh domiflist "$VM" | awk '{ print $5 }' | tail -2 | head -1)
|
|
||||||
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"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
define_netplan()
|
|
||||||
{
|
|
||||||
cat <<EOF > "$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
|
|
||||||
}
|
|
||||||
# Obtener el nombre del host de la máquina virtual
|
|
||||||
VM="$1"
|
|
||||||
IP="$2"
|
|
||||||
if [[ -z "$VM" ]]; then
|
|
||||||
usage
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -z "$IP" ]]; then
|
|
||||||
usage
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
MAC_VM=$(virsh domiflist "$VM" | awk '{ print $5 }' | tail -2 | head -1)
|
|
||||||
CURRENT_IP=$(get_vm_ip_address "$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
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user