From 781fe3dd9eab04ecbf36fa298889cb6a74c24ddd Mon Sep 17 00:00:00 2001 From: ytshih Date: Mon, 16 Dec 2024 20:28:52 +0800 Subject: [PATCH] Initial commit --- .gitea/workflows/build.yml | 52 ++++++++++++++++++++++++++++++++++++++ PKGBUILD | 33 ++++++++++++++++++++++++ src/etc/config.jsonnet | 41 ++++++++++++++++++++++++++++++ src/lib/qemu.libsonnet | 37 +++++++++++++++++++++++++++ src/share/startvm.sh | 24 ++++++++++++++++++ src/share/stopvm.sh | 12 +++++++++ src/vm | 15 +++++++++++ src/vm.sysusers | 1 + src/vm@.service | 17 +++++++++++++ 9 files changed, 232 insertions(+) create mode 100644 .gitea/workflows/build.yml create mode 100644 PKGBUILD create mode 100644 src/etc/config.jsonnet create mode 100644 src/lib/qemu.libsonnet create mode 100644 src/share/startvm.sh create mode 100644 src/share/stopvm.sh create mode 100755 src/vm create mode 100644 src/vm.sysusers create mode 100644 src/vm@.service diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml new file mode 100644 index 0000000..5fc37f4 --- /dev/null +++ b/.gitea/workflows/build.yml @@ -0,0 +1,52 @@ +name: Build package +on: [push] + +jobs: + build-package: + runs-on: imgbuilder + container: + image: gitea.konchin.com/image/archmakepkg + credentials: + username: ${{ secrets.REGISTRY_USERNAME }} + password: ${{ secrets.REGISTRY_PASSWORD }} + options: --dns 192.168.68.254 --dns-search konchin.com --dns-option ndots:15 + env: + REPO_NAME: custom + MINIO_BUCKET: archrepo + MINIO_ENDPOINT: https://minio.konchin.com + MINIO_ACCESSKEY: ${{ secrets.MINIO_ACCESSKEY }} + MINIO_SECRETKEY: ${{ secrets.MINIO_SECRETKEY }} + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Build package + run: | + chown -R builder . + sudo -u builder makepkg -sc --needed --noconfirm + + - name: Setup MinIO + run: | + mcli alias set m "${{ env.MINIO_ENDPOINT }}" \ + "${{ env.MINIO_ACCESSKEY }}" "${{ env.MINIO_SECRETKEY }}" + echo "Set endpoint to ${{ env.MINIO_ENDPOINT }}" + + - name: Copy repo db from MinIO + run: | + mkdir repo + mcli cp "m/${{ env.MINIO_BUCKET }}/${{ env.REPO_NAME }}.db" "repo/${{ env.REPO_NAME }}.db.tar.zst" + mcli cp "m/${{ env.MINIO_BUCKET }}/${{ env.REPO_NAME }}.files" "repo/${{ env.REPO_NAME }}.files.tar.zst" + echo "Copy ${{ env.REPO_NAME }}.db and ${{ env.REPO_NAME }}.files from MinIO" + + - name: Add pkgs to repo db + run: | + repo-add "repo/${{ env.REPO_NAME }}.db.tar.zst" *.pkg.tar.zst + mv *.pkg.tar.zst repo + echo "Add $(ls *.pkg.tar.zst) to repo" + + - name: Update repo to MinIO + run: | + mcli mv repo/${{ env.REPO_NAME }}.db.tar.zst "m/${{ env.MINIO_BUCKET }}/${{ env.REPO_NAME }}.db" + mcli mv repo/${{ env.REPO_NAME }}.files.tar.zst "m/${{ env.MINIO_BUCKET }}/${{ env.REPO_NAME }}.files" + mcli mv repo/*.pkg.tar.zst "m/${{ env.MINIO_BUCKET }}" + echo "Update ${{ env.REPO_NAME }}.db adn ${{ env.REPO_NAME }}.files to MinIO" diff --git a/PKGBUILD b/PKGBUILD new file mode 100644 index 0000000..60289b2 --- /dev/null +++ b/PKGBUILD @@ -0,0 +1,33 @@ +# Maintainer: Yi-Ting Shih +pkgname=vm +pkgver=1.0.0rc1 +pkgrel=1 +pkgdesc="A QEMU VM management tool" +arch=("x86_64") +url="https://gitea.konchin.com/package/vm" +license=("Apache") +makedepends=() +depends=('jsonnet' 'qemu-base') +provides=('vm') +source=() + +package() { + cd "$srcdir" || exit 1 + install -Dm755 share/startvm.sh share/stopvm.sh \ + -t "$pkgdir/usr/share/$pkgname/" + install -Dm644 lib/qemu.libsonnet \ + -t "$pkgdir/usr/lib/$pkgname/" + + install -Dm644 etc/config.jsonnet \ + -t "$pkgdir/etc/$pkgname/" + + install -Dm755 vm "$pkgdir/usr/bin/vm" + + install -Dm644 "${pkgname}@.service" \ + -t "$pkgdir/var/lib/.config/systemd/user/" + install -Dm644 "${pkgname}.sysusers" "$pkgdir/usr/lib/sysusers.d/${pkgname}.conf" + + install -Dm755 -d "$pkgdir/var/lib/$pkgname/pflash" + install -Dm755 -d "$pkgdir/var/lib/$pkgname/iso" + install -Dm755 -d "$pkgdir/var/lib/$pkgname/img" +} diff --git a/src/etc/config.jsonnet b/src/etc/config.jsonnet new file mode 100644 index 0000000..1235a0b --- /dev/null +++ b/src/etc/config.jsonnet @@ -0,0 +1,41 @@ +import 'qemu.libsonnet'; + +{ + [obj.name]: + default(obj.name) + + resource(obj.cpu, obj.ram) + + net(obj.mac) + + monitor(obj.mac) + for obj in [ + { + name: 'k0scontroller' + i, + cpu: 2, + ram: '2G', + mac: '08:00:00:20:01:1' + i, + } + for i in std.range(1, 3) + ] + [ + { + name: 'k0sworker' + i, + cpu: 4, + ram: '4G', + mac: '08:00:00:20:01:2' + i, + } + for i in std.range(1, 3) + ] + [ + { + name: 'ostest', + cpu: 4, + ram: '8G', + mac: '08:00:00:20:01:73', + }, + ] + [ + { + name: 'test' + i, + cpu: 1, + ram: '2G', + mac: '08:00:00:20:00:7' + i, + } + for i in std.range(1, 9) + ] +} diff --git a/src/lib/qemu.libsonnet b/src/lib/qemu.libsonnet new file mode 100644 index 0000000..6e0dd82 --- /dev/null +++ b/src/lib/qemu.libsonnet @@ -0,0 +1,37 @@ +local default(name) = [ + '-enable-kvm', + '-cpu host', + '-drive if=pflash,format=raw,readonly=on,file=/usr/share/edk2/x64/OVMF_CODE.4m.fd', + '-drive if=pflash,format=raw,file=pflash/' + name + '.4m.fd', + '-drive file=img/' + name + '.qcow2,format=qcow2', +]; + +local resource(cpu, ram) = [ + '-smp ' + cpu + ',sockets=1', + '-m ' + ram, +]; + +local monitor(mac) = [ + '-monitor telnet:localhost:2' + std.split(mac, ':')[4] + std.split(mac, ':')[5] + ',server,nowait,nodelay', +]; + +local net(mac, area='test') = [ + '-nic bridge,br=' + area + ',mac=' + mac, +]; + +local spice() = [ + '-vga virtio', + '-device virtio-serial-pci', + '-spice port=5555,disable-ticketing=on', + '-device virtserialport,chardev=spicechannel0,name=com.redhat.spice.0', + '-chardev spicevmc,id=spicechannel0,name=vdagent', +]; + +local vnc(display=0) = [ + '-vnc :' + display, +]; + +local iso(file) = [ + '-boot d', + '-cdrom ' + file, +]; diff --git a/src/share/startvm.sh b/src/share/startvm.sh new file mode 100644 index 0000000..9e770aa --- /dev/null +++ b/src/share/startvm.sh @@ -0,0 +1,24 @@ +#!/usr/bin/env -S bash + +CONFIG_FILE='/etc/vm/config.jsonnet' +LIB_DIR='/usr/lib/vm/' + +vm="$1" +shift + +settings=$(jsonnet "$CONFIG_FILE" -J "$LIB_DIR") + +args=() +for i in $(seq 0 $(($(jq -r ".${vm} | length" <<< "$settings") - 1))); do + arg="$(jq -r ".${vm}[${i}]" <<< "$settings")" + args+=("${arg}") +done + + +while [[ "$#" -ge 1 ]]; do + args+=("$1") + shift +done + +echo qemu-system-x86_64 ${args[*]} +exec qemu-system-x86_64 ${args[@]} diff --git a/src/share/stopvm.sh b/src/share/stopvm.sh new file mode 100644 index 0000000..bc8490e --- /dev/null +++ b/src/share/stopvm.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env -S bash + +CONFIG_FILE='/etc/vm/config.jsonnet' + +vm="$1" +shift + +mapfile -t endPoint <<< "$(jsonnet "$CONFIG_FILE" | jq -r ".${vm}[]" | sed -nr 's/^-monitor telnet:(\w+):(\w+).*$/\1\n\2/p')" + +nc "${endPoint[0]}" "${endPoint[1]}" <<'EOF' +system_powerdown +EOF diff --git a/src/vm b/src/vm new file mode 100755 index 0000000..23bfeb1 --- /dev/null +++ b/src/vm @@ -0,0 +1,15 @@ +#!/usr/bin/env -S bash + +helpmsg(){ + echo 'usage [image] [option]' +} + +if [[ "$1" == "--help" ]]; then + helpmsg + exit 0 +fi + +image="$1" +option="$2" + +systemctl --user -M vm@ "$option" "vm@$image" diff --git a/src/vm.sysusers b/src/vm.sysusers new file mode 100644 index 0000000..5c3eda9 --- /dev/null +++ b/src/vm.sysusers @@ -0,0 +1 @@ +u vm - - /var/lib/vm diff --git a/src/vm@.service b/src/vm@.service new file mode 100644 index 0000000..874bf54 --- /dev/null +++ b/src/vm@.service @@ -0,0 +1,17 @@ +[Unit] +Description=Virtual Machine %i +After=network.target + +[Service] +WorkingDirectory=%h +ExecStart=/usr/share/vm/startvm.sh %i -nographic +ExecStop=/usr/share/vm/stopvm.sh %i +#ExecStop=/usr/bin/kill -INT $MAINPID +StandardError=journal +StandardOutput=null +StandardInput=null +Restart=on-failure +RestartSec=300s + +[Install] +WantedBy=default.target