test(vm): parted #37
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
name: DEV virtual machine | |
# auto-task.start-build-time = ? | |
env: | |
DEBIAN_FRONTEND: noninteractive | |
on: | |
# schedule: | |
# - cron: '0 11 28 */2 *' | |
push: | |
paths: | |
- .github/workflows/dev_vm.yml | |
jobs: | |
build: | |
runs-on: ubuntu-latest | |
env: | |
DEV_DIR: assets/dev-vm | |
defaults: | |
run: | |
shell: zsh --pipefail -fex {0} | |
steps: | |
- name: install zsh | |
shell: sh -e {0} | |
run: ${{ vars.INSTALL_ZSH }} | |
- uses: actions/checkout@v4 | |
- name: download qemu image | |
env: | |
url: "https://cdimage.debian.org/cdimage/cloud/sid/daily/latest/debian-sid-nocloud-amd64-daily.tar.xz" | |
run: | | |
sudo apt update | |
apt_install() { | |
sudo apt-get install -y $* | |
} | |
apt_install aria2 | |
apt_install qemu-system-x86 systemd-container & | |
aria2c -s5 -x5 -k1m --no-conf -o disk.txz $url | |
tar --use-compress-program='xz -T0 -dv' -xf disk.txz | |
- name: get start offset of rootfs partition | |
id: get_start_offset | |
run: | | |
fdisk_cmd=( | |
sudo env LANG=C /sbin/fdisk --list disk.raw | |
) | |
awk_cmd=( | |
busybox awk | |
'/([0-9]+[[:space:]]+){3,}[0-9]+(\.[0-9]+)?G/ { | |
print($2) | |
}' | |
) | |
fdisk_output=$( | |
$fdisk_cmd | |
) | |
integer start=$( | |
print $fdisk_output | $awk_cmd | |
) | |
print -R "start=$((start * 512))" >> $GITHUB_OUTPUT | |
- name: apt fix-broken | |
run: | | |
while {! sudo apt-get install -f} { | |
sleep 1 | |
} | |
- name: mount rootfs partition | |
run: | | |
mkdir -p rootfs | |
sudo mount -o loop,offset=${{steps.get_start_offset.outputs.start}} ./disk.raw rootfs | |
- name: generate local ssh-key | |
run: | | |
key=vm.ed25519 | |
ssh-keygen -t ed25519 -f $key -N "" | |
ssh_client_d=rootfs/root/.ssh | |
for i ($ssh_client_d) { | |
sudo install -Dm600 ${key}.pub $i/authorized_keys | |
sudo chmod 700 -v $i | |
} | |
- name: run vm rootfs as container | |
run: | | |
sudo rm -vf rootfs/etc/resolv.conf | |
for i (zsh busybox) { | |
sudo cp -vf /usr/local/bin/$i rootfs/bin/ | |
} | |
uuu_keyring=/usr/share/keyrings/ubuntu-archive-keyring.gpg | |
if [[ -e $uuu_keyring ]] { | |
sudo cp -vf $uuu_keyring rootfs$uuu_keyring | |
} | |
sudo cp -vf ${{env.DEV_DIR}}/systemd/* rootfs/etc/systemd/system/ | |
single_arg=$(<<'CTR_ARG' | |
apt update | |
apt-get install -y ifupdown parted | |
printf "%s\n" "auto enp0s2" "iface enp0s2 inet dhcp" >/etc/network/interfaces.d/dhcp.conf | |
ssh-keygen -A | |
printf "%s\n" "TCPKeepAlive yes" "ClientAliveInterval 100" "ClientAliveCountMax 36" >> /etc/ssh/sshd_config.d/keep-alive.conf | |
chsh -s /bin/zsh | |
cd /etc/default/grub.d/ || exit 1 | |
print -R 'GRUB_TIMEOUT=1' > 15_timeout.cfg | |
print -R 'GRUB_TERMINAL="serial"' > 40_serial.cfg | |
CTR_ARG | |
) | |
sudo systemd-nspawn -D rootfs zsh -fexc "$single_arg" | |
sudo umount -lvf rootfs | |
- name: install virtiofsd | |
env: | |
url: "https://gitlab.com/virtio-fs/virtiofsd/uploads/2cf9068046720699531407101f2bcb60/virtiofsd-v1.10.1.zip" | |
file: "target/x86_64-unknown-linux-musl/release/virtiofsd" | |
run: | | |
curl -Lo v.zip $url | |
unzip -o v.zip | |
sudo install -Dm755 $file /usr/libexec/virtiofsd | |
- name: run vm | |
run: | | |
qemu-img create -f qcow2 usr.qcow2 5G | |
qemu-img create -f qcow2 var.qcow2 10G | |
cp ${{env.DEV_DIR}}/run . | |
sudo sysctl -w fs.file-max=1000000 | |
# sudo adduser "$(id -un)" kvm | |
sudo chmod 666 /dev/kvm | |
tmux new-session -d -s run-vm ./run | |
# timeout 10 tmux attach-session -r -t run-vm ||: | |
- name: copy vm ssh config | |
env: | |
conf: vm.sshconf | |
run: | | |
install -m600 ${{env.DEV_DIR}}/$conf ./$conf | |
sudo apt-get install -y autossh | |
autossh -M0 -F vm.sshconf vm echo OK ||: | |
- name: Disk partitioning and mounting | |
uses: 2moe/local-ssh-action@v0 | |
with: | |
host: vm | |
run: | | |
set -fexo pipefail | |
update-grub | |
systemctl enable media-sd.automount | |
systemctl start media-sd.mount | |
ls -lah /media/sd ||: | |
lsblk ||: | |
local -A map=( | |
vdb usr | |
vdc var | |
) | |
for i (mount umount reboot rm) { | |
cp /bin/busybox /tmp/$i | |
} | |
for d (vdc vdb) { | |
value=$map[$d] | |
parted -s /dev/$d mklabel gpt | |
sleep 0.2 | |
parted -s /dev/$d mkpart ${value}-p1 0% 100% | |
lsblk | |
sleep 0.5 | |
mkfs.ext4 -FL vm-$value /dev/${d}1 | |
mkdir -pv /tmp/$value | |
mount /dev/${d}1 /tmp/$value | |
cp -a /$value /tmp | |
print -R "LABEL=vm-$value /$value ext4 defaults 0 0" >> /etc/fstab | |
/tmp/rm -rf /${value}/* ||: | |
/tmp/rm -rf /${value}/.* ||: | |
/tmp/mount /dev/${d}1 /$value || /tmp/mount -o bind /tmp/$value /$value | |
} | |
lsblk ||: | |
/sbin/reboot || /tmp/reboot | |
args: | | |
-F | |
vm.sshconf | |
- name: wait ssh | |
run: | | |
sleep 10 | |
for i ({1..100}) { | |
print $i | |
case $(ssh -F vm.sshconf vm echo OK ||:) { | |
(OK) break ;; | |
(*) sleep 1 ;; | |
} | |
} | |
- uses: 2moe/local-ssh-action@v0 | |
with: | |
host: vm | |
run: | | |
set -fexo pipefail | |
export DEBIAN_FRONTEND=noninteractive | |
df -Th | |
lsblk | |
ls -lah /media/sd ||: | |
sed_args=( | |
-E | |
-e '/Suites/ s@( sid).*@\1 experimental@' | |
-e '$a\Signed-By: /usr/share/keyrings/debian-archive-keyring.gpg' | |
-i.bak /etc/apt/sources.list.d/debian.sources | |
) | |
sed $sed_args | |
printf "%s\n" 'https://cloudflaremirrors.com/debian' >> /etc/apt/mirrors/debian.list | |
apt update | |
apt-get autopurge ^python -y | |
apt-get install apt-utils whiptail qemu-guest-agent -y | |
apt-get upgrade -y | |
apt-get dist-upgrade -fy | |
apt-get install -y debootstrap systemd-container docker.io | |
apt-get install -t experimental -y qemu-user-static | |
old_kernel=$( | |
dpkg --list | awk -v num=0 '/^ii[[:space:]]+linux-image/ && $2 != "linux-image-amd64" { | |
num += 1 | |
arr[num] = $2 | |
} END { | |
if (num >= 2) print arr[1] | |
}' | |
) | |
apt-get autopurge -y $old_kernel | |
apt-get clean | |
for dir (/root /var /usr) { | |
dd if=/dev/zero of=$dir/zero bs=1M || { | |
rm -v $dir/zero | |
} | |
} | |
rm -vf /var/lib/apt/lists/*.* ||: | |
poweroff | |
args: | | |
-F | |
vm.sshconf | |
- name: pack vm to tar+zstd | |
run: | | |
cp -vf /usr/libexec/virtiofsd . | |
for i (Readme.md connect-to-ssh) { | |
cp -vf ${{env.DEV_DIR}}/$i . | |
} | |
while {lsof disk.raw} { | |
print wait disk.raw | |
sleep 1 | |
} | |
for file (*.qcow2) { | |
qemu-img convert -O qcow2 $file _$file | |
ls -lh $file _$file | |
mv -vf _$file $file | |
} | |
qemu-img convert -O qcow2 disk.raw disk.qcow2 | |
qemu-img convert -O raw disk.qcow2 disk.raw | |
unlink disk.qcow2 | |
files=( | |
vm.sshconf | |
vm.ed25519* | |
run | |
disk.raw | |
*.qcow2 | |
virtiofsd | |
Readme.md | |
connect-to-ssh | |
) | |
sha256sum $files > sha256.txt | |
files+=sha256.txt | |
args=( | |
--posix | |
--use-compress-program='zstdmt --long -18v' | |
-cf dev-vm_x64.tar.zst | |
$files | |
) | |
tar $args | |
- name: release | |
uses: softprops/action-gh-release@v2 | |
with: | |
fail_on_unmatched_files: true | |
tag_name: unstable | |
files: | | |
*.tar.zst |