New scripts and sudo rules. Implement qemu session mode.

This commit is contained in:
Andreas B. Mundt 2023-04-04 13:29:00 +02:00
parent 91aab8e75b
commit 7871936a67
19 changed files with 176 additions and 67 deletions

View file

@ -23,6 +23,7 @@
vars:
domain: "{{ ansible_domain }}"
rsyncsecret: Muster!
nfs4: false
extra_pkgs:
- vim

View file

@ -5,8 +5,8 @@ set -eu
# if less or more than one arguments supplied, display usage
if [[ $# -ne 1 ]]; then
echo "This script takes as input the name of the VM to clone"
echo "Usage: $0 vm_name"
echo "This script takes as input the name of the VM to clone" >&2
echo "Usage: $0 vm_name" >&2
exit 1
fi
@ -15,22 +15,30 @@ cd /var/lib/libvirt/images
VM_NAME=$1
if [[ ! -f "xml/${VM_NAME}.xml" ]] || [[ ! -f "${VM_NAME}.gcow2" ]]; then
echo "xml or qcow2 File does not exists."
if [[ ! -f "xml/${VM_NAME}.xml" ]] || [[ ! -f "${VM_NAME}.qcow2" ]]; then
echo "xml or qcow2 File does not exists." >&2
exit 1
fi
VM_DIR="/tmp/${UID}/vmimages"
VM_XML="${VM_DIR}/xml/${VM_NAME}-clone.xml"
# Create User-VM-Dir and link system VM-Images
[[ -d "${VM_DIR}/xml" ]] || mkdir -p "${VM_DIR}/xml"
sudo /usr/local/bin/link-images.sh
# Create backing file
cd "${VM_DIR}"
qemu-img create -f qcow2 -F qcow2 -b "${VM_NAME}.qcow2" "${VM_NAME}-clone.qcow2"
cp "xml/${VM_NAME}.xml" "xml/${VM_NAME}-clone.xml"
# Create machine-definition-file
cp "/var/lib/libvirt/images/xml/${VM_NAME}.xml" "${VM_XML}"
# and actually rename the vm: (this also updates the storage path)
sed -i "s/${VM_NAME}/${VM_NAME}-clone/" "xml/${VM_NAME}-clone.xml"
# set VM_DIR:
sed -i "s:VMIMAGEDIR:${VM_DIR}:" "${VM_XML}"
# set Username for mounting data from correct user
sed -i "s/USER/${SUDO_USER}/" "xml/${VM_NAME}-clone.xml"
# and actually rename the vm (this also updates part of the storage path):
sed -i "s/${VM_NAME}/${VM_NAME}-clone/" "${VM_XML}"
# delete the old vm
virsh --connect=qemu:///system undefine "${VM_NAME}-clone" || echo "${VM_NAME}-clone did not exist"
# finally, create the new vm
virsh --connect=qemu:///system define "xml/${VM_NAME}-clone.xml"
# set virtiofs-Socket
sed -i "s:VIRTIOFSSOCKET:${XDG_RUNTIME_DIR}/virtiofs/${VM_NAME}-clone.sock:" "${VM_XML}"

View file

@ -4,8 +4,8 @@
set -eu
# if less than two arguments supplied, display usage
if [[ $# -ne 2 ]]; then
echo "This script takes as input the name of the VM to clone"
echo "Usage: $0 vm_name_orig vm_name_clone"
echo "This script takes as input the name of the VM to clone" >&2
echo "Usage: $0 vm_name_orig vm_name_clone" >&2
exit 1
fi
@ -13,10 +13,11 @@ VM_NAME=$1
VM_CLONE=$2
# change to image-directory
cd /var/lib/libvirt/images
VM_DIR="/tmp/${UID}/vmimages"
cd "${VM_DIR}"
if [[ ! -f "xml/${VM_NAME}.xml" ]] || [[ ! -f "${VM_NAME}.gcow2" ]]; then
echo "xml or qcow2 File does not exists."
if { [[ ! -f "xml/${VM_NAME}.xml" ]] && [[ ! -f "/var/lib/libvirt/images/xml/${VM_NAME}.xml" ]]; } || [[ ! -f "${VM_NAME}.qcow2" ]]; then
echo "xml or qcow2 File does not exists." >&2
exit 1
fi
@ -24,7 +25,15 @@ qemu-img create -f qcow2 -F qcow2 -b "${VM_NAME}.qcow2" "${VM_NAME}-${VM_CLONE}.
chmod a-w "${VM_NAME}-${VM_CLONE}.qcow2"
# virsh --connect=qemu:///system dumpxml "${VM_NAME}" > "xml/${VM_NAME}-${VM_CLONE}.xml"
# copy machine-definition-file
if [[ -f "xml/${VM_NAME}.xml" ]]; then
cp "xml/${VM_NAME}.xml" "xml/${VM_NAME}-${VM_CLONE}.xml"
elif [[ -f "/var/lib/libvirt/images/xml/${VM_NAME}.xml" ]]; then
cp "/var/lib/libvirt/images/xml/${VM_NAME}.xml" "xml/${VM_NAME}-${VM_CLONE}.xml"
else
echo "no machine definition file found" >&2
exit 1
fi
# hardware addresses need to be removed, libvirt will assign
# new addresses automatically

View file

@ -0,0 +1,14 @@
#!/usr/bin/bash
# link VM in Use-Dir in /tmp
set -eu
# change to image-directory
cd /var/lib/libvirt/images
VM_DIR="/tmp/${SUDO_UID}/vmimages"
# link system-VM-Images to User VM Directory
for i in *.qcow2; do
[[ -f "${VM_DIR}/${i}" ]] || ln "${i}" "${VM_DIR}/${i}"
done

View file

@ -1,3 +0,0 @@
%examusers ALL=(root) NOPASSWD: /usr/local/bin/create-clone.sh
%role-student ALL=(root) NOPASSWD: /usr/local/bin/create-clone.sh
%role-teacher ALL=(root) NOPASSWD: /usr/local/bin/create-clone.sh

View file

@ -1 +0,0 @@
%role-teacher ALL=(root) NOPASSWD: /usr/local/bin/create-vm.sh

View file

@ -0,0 +1,3 @@
%examusers ALL=(root) NOPASSWD: /usr/local/bin/link-images.sh
%role-student ALL=(root) NOPASSWD: /usr/local/bin/link-images.sh
%role-teacher ALL=(root) NOPASSWD: /usr/local/bin/link-images.sh

View file

@ -0,0 +1,3 @@
%examusers ALL=(root) NOPASSWD: /usr/local/bin/mounthome.sh
%role-student ALL=(root) NOPASSWD: /usr/local/bin/mounthome.sh
%role-teacher ALL=(root) NOPASSWD: /usr/local/bin/mounthome.sh

View file

@ -1,3 +0,0 @@
%examusers ALL=(root) NOPASSWD: /usr/local/bin/mounthome.sh
%role-student ALL=(root) NOPASSWD: /usr/local/bin/mounthome.sh
%role-teacher ALL=(root) NOPASSWD: /usr/local/bin/mounthome.sh

View file

@ -1 +0,0 @@
%role-teacher ALL=(root) NOPASSWD: /usr/local/bin/rebase-vm.sh

View file

@ -0,0 +1,3 @@
%examusers ALL=(root) NOPASSWD: /usr/local/bin/start-virtiofsd.sh
%role-student ALL=(root) NOPASSWD: /usr/local/bin/start-virtiofsd.sh
%role-teacher ALL=(root) NOPASSWD: /usr/local/bin/start-virtiofsd.sh

View file

@ -0,0 +1 @@
%role-teacher ALL=(root) NOPASSWD: /usr/local/bin/sync-vm.sh

View file

@ -1 +0,0 @@
%role-teacher ALL=(root) NOPASSWD: /usr/local/bin/sync-vm.sh

View file

@ -5,19 +5,19 @@ share="/srv/samba/schools/default-school/share/"
home="$(getent passwd "$SUDO_UID" | cut -d : -f 6)"
if [[ "$#" -gt 0 ]] && [[ "$1" = '-u' ]]; then
[[ -d "/media/${SUDO_USER}/home" ]] && umount "/media/${SUDO_USER}/home" && rmdir "/media/${SUDO_USER}/home"
[[ -d "/media/${SUDO_USER}/share" ]] && umount "/media/${SUDO_USER}/share" && rmdir "/media/${SUDO_USER}/share"
[[ -d "/media/${SUDO_USER}/oldhome" ]] && umount "/media/${SUDO_USER}/oldhome" && rmdir "/media/${SUDO_USER}/oldhome"
findmnt "/media/${SUDO_USER}/home" && umount "/media/${SUDO_USER}/home" && rmdir "/media/${SUDO_USER}/home"
findmnt "/media/${SUDO_USER}/share" && umount "/media/${SUDO_USER}/share" && rmdir "/media/${SUDO_USER}/share"
findmnt "/media/${SUDO_USER}/oldhome" && umount "/media/${SUDO_USER}/oldhome" && rmdir "/media/${SUDO_USER}/oldhome"
elif [ "$#" -gt 0 ] && [ "$1" = '-o' ]; then
read -p "Username: " username
read -s -p "Passwort: " PASSWD
read -pr "Username: " username
read -spr "Passwort: " PASSWD
export PASSWD
mkdir -p "/media/${SUDO_USER}/oldhome"
mount -t cifs -o "username=${username},uid=${SUDO_UID},gid=1010,file_mode=0770,dir_mode=0770,forceuid,forcegid" \
"//192.168.1.2/DOCS/fvs" "/media/${SUDO_USER}/oldhome"
else
mkdir -p "/media/${SUDO_USER}"
chgrp 1010 "/media/${SUDO_USER}"
chown "${SUDO_USER}:1010" "/media/${SUDO_USER}"
chmod 0770 "/media/${SUDO_USER}"
mkdir -p "/media/${SUDO_USER}/home"
mkdir -p "/media/${SUDO_USER}/share"

View file

@ -3,7 +3,7 @@
set -eu
show_help() {
cat << EOF
cat << EOF >&2
Usage: $(basename "$0") [-n newname] vmname"
This script takes as input the name of the VM to rebase one level down
-n new name of the rebased image
@ -31,19 +31,20 @@ if [[ $# -ne 1 ]]; then
fi
# change to Images directory
cd /var/lib/libvirt/images
VM_DIR="/tmp/${UID}/vmimages"
cd "${VM_DIR}"
VM_NAME="$1"
# check if VM-Diskimage exists
if [[ ! -f "${VM_NAME}.qcow2" ]]; then
echo "File not found ${VM_NAME}.qcow2"
echo "File not found ${VM_NAME}.qcow2" >&2
exit 1
fi
# check if new VM-Diskimage exists
if [[ -v NEWNAME ]] && [[ -f "${NEWNAME}.qcow2" ]]; then
echo "New Base already exists: ${NEWNAME}.qcow2"
echo "New Base already exists: ${NEWNAME}.qcow2" >&2
exit 1
fi
@ -52,13 +53,13 @@ NEWBASE=$(qemu-img info --backing-chain "${VM_NAME}.qcow2" | grep image | head
CURRENTBASE=$(qemu-img info --backing-chain "${VM_NAME}.qcow2" | grep image | head -n 2 | tail -n 1 | cut -d' ' -f2)
if [[ ! "${NUMBASES}" -ge 3 ]]; then
echo "Image must have at least 2 backing-files"
echo "Image must have at least 2 backing-files" >&2
exit 1
fi
# check if base Diskimage exists
if [[ ! -f "${NEWBASE}" ]] || [[ ! -f "${CURRENTBASE}" ]]; then
echo "Backingfiles not found ${CURRENTBASE}, ${NEWBASE}"
echo "Backingfiles not found ${CURRENTBASE}, ${NEWBASE}" >&2
exit 1
fi
@ -67,7 +68,14 @@ qemu-img rebase -f qcow2 -b "${NEWBASE}" -F qcow2 "${VM_NAME}.qcow2"
if [[ -v NEWNAME ]]; then
# copy and adapt machine definition file
CURRENTNAME="${CURRENTBASE/.qcow2/}"
if [[ -f "xml/${CURRENTNAME}.xml" ]]; then
cp "xml/${CURRENTNAME}.xml" "xml/${NEWNAME}.xml"
elif [[ -f "/var/lib/libvirt/images/xml/${CURRENTNAME}.xml" ]]; then
cp "/var/lib/libvirt/images/xml/${CURRENTNAME}.xml" "xml/${NEWNAME}.xml"
else
echo "no machine definition file found" >&2
exit 1
fi
sed -i "s/${CURRENTNAME}/${NEWNAME}/" "xml/${NEWNAME}.xml"
NEWNAME="${NEWNAME}.qcow2"
else

View file

@ -3,25 +3,36 @@
set -eu
NEWCLONE=0
show_help() {
cat << EOF
cat << EOF >&2
Usage: $(basename "$0") [-n] vmname"
Create a new clone, start the vm (if not yet running) and run virt-viewer.
Squid-Proxy will be started too.
User Home will be mounted on /media/USERNAME/home
-n new clone will be created, even if exists
-s qemu:///session instead of default qemu:///system
EOF
}
exit_script() {
echo "run-vm.sh ${VM_NAME} terminated by trap!" >> "/tmp/${UID}/exit-run-vm.log"
virsh --connect="${QEMU}" destroy "${VM_NAME}-clone"
trap - SIGHUP SIGINT SIGTERM # clear the trap
kill -- -$$ # Sends SIGTERM to child/sub processes
}
QEMU='qemu:///system'
NEWCLONE=0
while getopts ':n' OPTION; do
while getopts ':ns' OPTION; do
case "$OPTION" in
n)
NEWCLONE=1
;;
s)
QEMU='qemu:///session'
;;
?)
show_help
exit 1
@ -40,7 +51,7 @@ fi
VM_NAME=$1
if [[ ! -f "/var/lib/libvirt/images/${VM_NAME}.qcow2" ]]; then
echo "no base VM disk '${VM_NAME}.qcow2' found"
echo "no base VM disk '${VM_NAME}.qcow2' found" >&2
exit 1
fi
@ -51,17 +62,26 @@ if [[ ! -f "/tmp/squid.pid" ]]; then
fi
# check, if we have to mount home
if [[ ! -d "/media/${USER}/home" ]]; then
if ! findmnt "/media/${USER}/home"; then
echo "mounting home."
sudo mounthome.sh
fi
if ! virsh --connect=qemu:///system list | grep "${VM_NAME}"; then
export XDG_CONFIG_HOME="/tmp/${UID}/.config"
VM_DIR="/tmp/${UID}/vmimages"
if ! virsh --connect="${QEMU}" list | grep "${VM_NAME}-clone"; then
echo "VM not yet running. Try to clone and start."
if [[ "${NEWCLONE}" = 1 ]] || [[ ! -f "/var/lib/libvirt/images/${VM_NAME}-clone.qcow2" ]]; then
sudo create-clone.sh "${VM_NAME}"
if [[ "${NEWCLONE}" = 1 ]] || [[ ! -f "${VM_DIR}/${VM_NAME}-clone.qcow2" ]]; then
create-clone.sh "${VM_NAME}"
fi
virsh --connect=qemu:///system start "${VM_NAME}-clone"
# delete the old vm
virsh --connect=qemu:///session undefine "${VM_NAME}-clone" || echo "${VM_NAME}-clone did not exist"
# finally, create the new vm
virsh --connect=qemu:///session define "${VM_DIR}/xml/${VM_NAME}-clone.xml"
trap exit_script SIGHUP SIGINT SIGTERM
[[ "${QEMU}" = 'qemu:///session' ]] && sudo /usr/local/bin/start-virtiofsd.sh "${VM_NAME}"
virsh --connect="${QEMU}" start "${VM_NAME}-clone"
fi
echo "starting viewer"
virt-viewer --connect=qemu:///system --full-screen "${VM_NAME}-clone"
virt-viewer --connect="${QEMU}" --full-screen "${VM_NAME}-clone"

View file

@ -0,0 +1,28 @@
#!/usr/bin/bash
# if less than one arguments supplied, display usage
if [[ $# -ne 1 ]]; then
echo "This script takes as input the name of the VM " >&2
echo "Usage: $0 vm_name" >&2
exit 1
fi
VM_NAME=$1
export XDG_RUNTIME_DIR="/run/user/${SUDO_UID}"
if ! [[ -d "${XDG_RUNTIME_DIR}/virtiofs" ]]; then
mkdir "${XDG_RUNTIME_DIR}/virtiofs/"
chown "${SUDO_UID}" "${XDG_RUNTIME_DIR}/virtiofs/"
fi
[[ -S "${XDG_RUNTIME_DIR}/virtiofs/${VM_NAME}-clone.sock" ]] && /usr/bin/rm "${XDG_RUNTIME_DIR}/virtiofs/${VM_NAME}-clone.sock"
#sudo /usr/lib/qemu/virtiofsd --socket-path="${XDG_RUNTIME_DIR}/virtiofs/${VM_NAME}-clone.sock" --socket-group="${SUDO_USER}" --announce-submounts -o source="/media/${USER}" -o sandbox=chroot > /dev/null &
#sudo /usr/lib/qemu/virtiofsd --socket-path="${XDG_RUNTIME_DIR}/virtiofs/${VM_NAME}-clone.sock" --socket-group="${SUDO_USER}" -o source="/media/${USER}" -o sandbox=chroot > /dev/null &
/usr/lib/qemu/virtiofsd --socket-path="${XDG_RUNTIME_DIR}/virtiofs/${VM_NAME}-clone.sock" -o source="/media/${SUDO_USER}" -o sandbox=chroot > /dev/null &
# Wait until socket-File exists and chown to user
until [[ -S "${XDG_RUNTIME_DIR}/virtiofs/${VM_NAME}-clone.sock" ]]; do
echo "waiting for ${XDG_RUNTIME_DIR}/virtiofs/${VM_NAME}-clone.sock"
sleep 0.1
done
/usr/bin/chown "${SUDO_USER}" "${XDG_RUNTIME_DIR}/virtiofs/${VM_NAME}-clone.sock"

View file

@ -3,7 +3,7 @@
set -eu
show_help() {
cat << EOF
cat << EOF >&2
Usage: $(basename "$0") [-u vmname] [-d vmname] [-a]"
When using option -u (upload), the disk from VM vmname will be synced on server.
Otherwise the images from images.list and xml-directory will be synced from server.
@ -13,12 +13,12 @@ EOF
upload_image() {
# check if VM-Diskimage exists
if [[ ! -f "/var/lib/libvirt/images/${VM_NAME}.qcow2" ]]; then
echo "File not found ${VM_NAME}.qcow2"
echo "File not found ${VM_NAME}.qcow2" >&2
exit 1
fi
# check if VM-Machine-Definition XML exists
if [[ ! -f "/var/lib/libvirt/images/xml/${VM_NAME}.xml" ]]; then
echo "File not found ${VM_NAME}.xml"
echo "File not found ${VM_NAME}.xml" >&2
exit 1
fi
rsync -av --password-file=/etc/rsync.secret "/var/lib/libvirt/images/${VM_NAME}.qcow2" \

View file

@ -58,11 +58,10 @@
group: root
mode: '0700'
loop:
- lmn-mounthome-sudo
- lmn-create-clone-sudo
- lmn-sync-vm-sudo
- lmn-create-vm-sudo
- lmn-rebase-vm-sudo
- lmn-mounthome
- lmn-sync-vm
- lmn-link-images
- lmn-startvirtiofsd
- name: deploy mount home script
copy:
@ -78,6 +77,27 @@
- create-clone.sh
- run-vm.sh
- sync-vm.sh
- link-images.sh
- start-virtiofsd.sh
- name: Deploy bridge.conf needed for qemu session mode
lineinfile:
path: /etc/qemu/bridge.conf
line: 'allow virbr0'
create: True
mode: '0655'
- name: Deploy rsync.secret
lineinfile:
path: /etc/rsync.secret
line: "{{ rsyncsecret }}"
create: True
mode: '0600'
- name: Allow users to attach to bridge
file:
path: /usr/lib/qemu/qemu-bridge-helper
mode: '4755'
- name: deploy http proxy config
copy: