From 762e81cea72efdc37688a2dcd75756d63c68b82c Mon Sep 17 00:00:00 2001 From: emdee Date: Fri, 29 Dec 2023 19:40:31 +0000 Subject: [PATCH] added roles/ansible-gentoo_install/ --- Makefile | 198 +++++++++++++++-- READMD.md | 3 - README.md | 155 +++++++++++++ bin/toxcore_create-vm.bash | 1 + bin/toxcore_delete-vm.bash | 12 +- bin/toxcore_get-vm-ip.bash | 9 +- roles/ansible-gentoo_install/README.md | 30 +++ .../ansible-gentoo_install/defaults/main.yml | 36 +++ .../ansible-gentoo_install/handlers/main.yml | 2 + roles/ansible-gentoo_install/meta/main.yml | 18 ++ .../tasks/bootloader.yml | 108 +++++++++ roles/ansible-gentoo_install/tasks/chroot.yml | 55 +++++ roles/ansible-gentoo_install/tasks/copy.yml | 114 ++++++++++ .../ansible-gentoo_install/tasks/daemons.yml | 44 ++++ roles/ansible-gentoo_install/tasks/disk.yml | 63 ++++++ roles/ansible-gentoo_install/tasks/finish.yml | 35 +++ roles/ansible-gentoo_install/tasks/kernel.yml | 31 +++ roles/ansible-gentoo_install/tasks/local.yml | 170 ++++++++++++++ roles/ansible-gentoo_install/tasks/main.yml | 72 ++++++ roles/ansible-gentoo_install/tasks/misc.yml | 112 ++++++++++ .../ansible-gentoo_install/tasks/network.yml | 56 +++++ .../ansible-gentoo_install/tasks/portage.yml | 52 +++++ .../ansible-gentoo_install/tasks/tarball.yml | 156 +++++++++++++ .../templates/chroot_wrapper.sh | 4 + .../templates/etc/libvirt/qemu/gentoo.xml | 210 ++++++++++++++++++ roles/ansible-gentoo_install/vars/Devuan5.yml | 3 + roles/ansible-gentoo_install/vars/Gentoo2.yml | 3 + roles/ansible-gentoo_install/vars/Linux.yml | 15 ++ .../vars/target_Gentoo2.yml | 94 ++++++++ 29 files changed, 1838 insertions(+), 23 deletions(-) delete mode 100644 READMD.md create mode 100644 README.md create mode 100644 roles/ansible-gentoo_install/README.md create mode 100644 roles/ansible-gentoo_install/defaults/main.yml create mode 100644 roles/ansible-gentoo_install/handlers/main.yml create mode 100644 roles/ansible-gentoo_install/meta/main.yml create mode 100644 roles/ansible-gentoo_install/tasks/bootloader.yml create mode 100644 roles/ansible-gentoo_install/tasks/chroot.yml create mode 100644 roles/ansible-gentoo_install/tasks/copy.yml create mode 100644 roles/ansible-gentoo_install/tasks/daemons.yml create mode 100644 roles/ansible-gentoo_install/tasks/disk.yml create mode 100644 roles/ansible-gentoo_install/tasks/finish.yml create mode 100644 roles/ansible-gentoo_install/tasks/kernel.yml create mode 100644 roles/ansible-gentoo_install/tasks/local.yml create mode 100644 roles/ansible-gentoo_install/tasks/main.yml create mode 100644 roles/ansible-gentoo_install/tasks/misc.yml create mode 100644 roles/ansible-gentoo_install/tasks/network.yml create mode 100644 roles/ansible-gentoo_install/tasks/portage.yml create mode 100644 roles/ansible-gentoo_install/tasks/tarball.yml create mode 100644 roles/ansible-gentoo_install/templates/chroot_wrapper.sh create mode 100644 roles/ansible-gentoo_install/templates/etc/libvirt/qemu/gentoo.xml create mode 100644 roles/ansible-gentoo_install/vars/Devuan5.yml create mode 100644 roles/ansible-gentoo_install/vars/Gentoo2.yml create mode 100644 roles/ansible-gentoo_install/vars/Linux.yml create mode 100644 roles/ansible-gentoo_install/vars/target_Gentoo2.yml diff --git a/Makefile b/Makefile index 6a504b9..7405af8 100644 --- a/Makefile +++ b/Makefile @@ -1,31 +1,199 @@ ROLES=base proxy toxcore SHELLCHECK_OPTS=SC2003,SC2006,SC2010,SC2039,SC2181,SC2046,SC2086,SC2048,SC2162,SC2034,SC2030,SC2166,SC2242,SC2223,SC2319,SC3009,SC3011,SC3030,SC3043,SC3054,SC2009,SC1090,SC2164,SC3044 +# FixMe +ANSIBLE_PLUGINS=/usr/local/lib/python3.11/site-packages/ansible-2.9.22-py3.11.egg/ansible/plugins -devuan:: - sudo sh ansible_local.bash --diff -i ${PWD}/hosts.yml -l devuan -c local --verbose $(ROLES) > .check-`cat /etc/hostname` 2>&1 +# Edit this to be one of pentoo or devuan depending on your host platform +# Find the corresponding host in hosts.yml and edit the settings, then +# change this to be that hostname +LOCALHOST=`cat /etc/hostname` -pentoo:: - sudo sh ansible_local.bash --diff -i ${PWD}/hosts.yml -l $@ -c local --verbose $(ROLES) > .check-`cat /etc/hostname` 2>&1 +BOX_NBD_BASE_DIR=/a/tmp/GentooImgr +BOX_NBD_BASE_FILE=gentoo.qcow2 +BOX_NBD_BASE_QCOW=${BOX_NBD_BASE_DIR}/${BOX_NBD_BASE_FILE} +# set this to the name linux_local_group host in hosts.yml +LOCAL_HOSTS_NAME=pentoo +# set this to the name linux_chroot_group host in hosts.yml +YAML_CHROOT_NAME=linuxGentoo +# set this to the libvirt name of the linux_libvirt_group host in hosts.yml +YAML_BOX_NAME=gentoo1 +INST_BOX_NAME=gentoo1 -check:: - . /usr/local/bin/usr_local_tput.bash - grep -n 'shell: *$$' roles/*/tasks/*.yml && { ERROR "shell: in .yml" ; false ; } - grep -n '^[a-z ]*: {{' roles/*/tasks/*.yml && { WARN "{{ in .yml" ; false ; } || true - bash .pylint.sh ; cat .pylint.err - shellcheck -s bash -W 0 -x -a -e ${SHELLCHECK_OPTS} bin/*sh +#INST_BOX_DIR=/mnt/o/home/root/vms/virsh +INST_BOX_DIR=${BOX_NBD_BASE_DIR}/create-vm +PWD=/o/var/local/src/play_tox/ +NETWORK=default +VERBOSE=2 + +all: install lint build check run test + +# groddy but works for me +install:: +# ( /usr/local/src ; ansible-galaxy collection install \ +# file:///usr/local/src/community.general ) + [ -e $(ANSIBLE_PLUGINS)/connection/libvirt_qemu.py ] \ + || ln -s ${PWD}/lib/plugins/libvirt_qemu.py \ + $(ANSIBLE_PLUGINS)/connection/q || true lint:: - sudo xmllint -noout etc/libvirt/qemu/gentoo.xml - yamllint -c .yamllint.yml -f standard *.yml roles/*/*s/*yml 2>&1| \ + @sudo xmllint -noout roles/ansible-gentoo_install/templates/etc/libvirt/qemu/gentoo.xml + @yamllint -c .yamllint.yml -f standard *.yml roles/*/*s/*yml 2>&1| \ grep -v 'truthy\|indentation' | \ sed -e '/^$$/d' | tee .yamllint.out | \ grep -B 2 error | tee .yamllint.err || true grep Error .yamllint.out || true -test:: - bash .pyanal.sh - sudo sh ansible_local.bash --diff --check -i ${PWD}/hosts.yml -l `cat /etc/hostname -c local --verbose $(ROLES) > .check-`cat /etc/hostname 2>&1 +build:: build_base + sudo $(MAKE) -$(MAKEFLAGS) build_overlay + +build_base:: + echo $@ "${BOX_NBD_BASE_QCOW}" +# @[ ! -f "${BOX_NBD_BASE_QCOW}" ] || exit 0 || true +# @[ "`grep nbd /proc/partitions | wc -l`" -eq 0 ] && \ +# echo WARN looks like theres NO nbd mount && \ +# exit 0 + [ ! -f ${BOX_NBD_BASE_QCOW} ] || exit 1 + echo INFO running the toxcore role will build ${BOX_NBD_BASE_QCOW} + sudo sh ansible_local.bash --diff -i ${PWD}/hosts.yml \ + -l ${LOCALHOST} -c local --verbose ${VERBOSE} \ + $(ROLES) > .build-local-${LOCALHOST} 2>&1 + [ -f ${BOX_NBD_BASE_QCOW} ] + +build_overlay:: + @virsh list | grep "${INST_BOX_NAME}.*running" && \ + virsh destroy ${INST_BOX_NAME} ; true +# @virsh list | grep "${INST_BOX_NAME}.*running" && exit 1 + @virsh list --all | grep ${INST_BOX_NAME} && \ + virsh undefine ${INST_BOX_NAME} && \ + rm -f /a/tmp/GentooImgr/create-vm/xml/gentoo1.xml \ + ${INST_BOX_DIR}/xml/${INST_BOX_NAME}.xml \ + ${INST_BOX_DIR}/images/${INST_BOX_NAME}.img ; true +# ! virsh list --all | grep "${INST_BOX_NAME}" && exit 2 + [ ! -f ${INST_BOX_DIR}/images/${INST_BOX_NAME}.img ] || { \ + echo WARN ; echo rm -f ${INST_BOX_DIR}/images/${INST_BOX_NAME}.img ; \ + exit 3 ; } + [ ! -f ${INST_BOX_DIR}/xml/${INST_BOX_NAME}.xml ] || { \ + echo WARN ; echo rm -f ${INST_BOX_DIR}/xml/${INST_BOX_NAME}.xml ; \ + exit 4 ; } + PLAY_ANSIBLE_SRC=${PWD} bash /usr/local/bin/toxcore_build_overlay_qcow.bash + [ -f ${INST_BOX_DIR}/xml/${INST_BOX_NAME}.xml ] + xmllint -noout ${INST_BOX_DIR}/xml/${INST_BOX_NAME}.xml + +check:: + grep -n 'shell: *$$' roles/*/tasks/*.yml && { echo ERROR: "shell: in .yml" ; false ; } || true + grep -n '^[a-z ]*: {{' roles/*/tasks/*.yml && { echo WARN: "{{ in .yml" ; false ; } || true + @bash .pylint.sh ; cat .pylint.err ; true + @shellcheck -s bash -W 0 -x -a -e ${SHELLCHECK_OPTS} bin/*sh || true + $(MAKE) -$(MAKEFLAGS) check_base + @[ -d /mnt/gentoo/lost+found ] && \ + sudo $(MAKE) -$(MAKEFLAGS) $@_chroot + @[ -f ${INST_BOX_DIR}/images/${INST_BOX_NAME}.img ] && \ + sudo $(MAKE) -$(MAKEFLAGS) $@_overlay + +check_localhost:: + sudo sh ansible_local.bash --diff -i hosts.yml -l ${LOCALHOST} \ + --check -c local --verbose ${VERBOSE} \ +s $(ROLES) > .run-$@-${LOCALHOST} 2>&1 + +check_base:: + ls ${BOX_NBD_BASE_QCOW} + ls ${INST_BOX_DIR}/images/${INST_BOX_NAME}.img + ls ${INST_BOX_DIR}/xml/${INST_BOX_NAME}.xml + ps axf | grep 'qemu-system-x86_64 -name guest='${INST_BOX_NAME} ; \ + true + +check_chroot:: + [ -d /mnt/gentoo/lost+found ] || exit 0 + ansible -c chroot -l ${YAML_CHROOT_NAME} -i hosts.yml \ + -m setup -vvv ${YAML_CHROOT_NAME} + sudo sh ansible_local.bash --diff -i hosts.yml -l ${YAML_CHROOT_NAME} \ + --check -c chroot --verbose ${VERBOSE} \ + $(ROLES) > .check-${YAML_CHROOT_NAME}-${LOCALHOST} 2>&1 + +check_overlay:: + sudo /var/local/sbin/hostvms_libvirt_test_ga.bash ${INST_BOX_NAME} ls / +# domain-*-gentoo/org.qemu.guest_agent.0 || true + sudo find /var/lib/libvirt/qemu/channel/target/ | \ + grep org.qemu.guest_agent.0 + sudo find /var/lib/libvirt/qemu/channel/target/ -type s | \ + grep ${INST_BOX_NAME} + ansible -c libvirt_qemu -l ${YAML_BOX_NAME} -i hosts.yml \ + -m setup -vvv ${YAML_BOX_NAME} + sudo virsh list | grep -q ${INST_BOX_NAME} || exit 0 + sudo sh ansible_local.bash --diff -i hosts.yml -l ${INST_BOX_NAME} \ + --check -c libvirt_qemu --verbose ${VERBOSE} \ + $(ROLES) > .check-${INST_BOX_NAME}-${LOCALHOST} 2>&1 + +# Edit hosts.yml and customize this target if you are on a Debianish +devuan:: + sudo sh ansible_local.bash --diff -i ${PWD}/hosts.yml \ + -l devuan -c local --verbose ${VERBOSE} $(ROLES) \ + > .check-${LOCALHOST} 2>&1 + +# Edit hosts.yml and customize this target if you are on a Gentoo +pentoo:: + sudo sh ansible_local.bash --diff -i ${PWD}/hosts.yml \ + -l pentoo -c local --verbose ${VERBOSE} $(ROLES) \ + > .check-${LOCALHOST} 2>&1 + +run:: + @[ ! -f ${BOX_NBD_BASE_QCOW} ] && \ + $(MAKE) -$(MAKEFLAGS) $@_local + @[ -d /mnt/gentoo/lost+found ] && \ + sudo $(MAKE) -$(MAKEFLAGS) $@_chroot + @[ ! -f ${INST_BOX_DIR}/images/${INST_BOX_NAME}.img ] && \ + sudo $(MAKE) -$(MAKEFLAGS) $@_libvirt + +run_local:: lint + A=`grep nbd /proc/partitions | wc -l` + @[ $${A} -eq 0 ] && echo WARN looks like theres no nbd mount && \ + exit 0 + @[ -f ${BOX_NBD_BASE_QCOW} ] && \ + echo WARN ${BOX_NBD_BASE_QCOW} exists - delete or rename \ + && exit 0 + BOX_NBD_DEV=$( /usr/local/bin/ansible_get_inventory.bash BOX_NBD_DEV $BOX) + A=`grep $BOX_NBD_DEV /proc/partitions | wc -l` + @[ $${A} -eq 0 ] && echo WARN looks like theres no $BOX_NBD_DEV nbd mount && \ + exit 0 + sudo sh ansible_local.bash --diff -i hosts.yml -l ${LOCALHOST} \ + -c local --verbose ${VERBOSE} $(ROLES) \ + > .run-$@-${LOCALHOST} 2>&1 + +run_chroot:: + [ -d /mnt/gentoo/lost+found ] || exit 0 + sudo sh ansible_local.bash --diff -i hosts.yml -l ${YAML_CHROOT_NAME} \ + -c chroot --verbose ${VERBOSE} $(ROLES) \ + > .$@-${YAML_CHROOT_NAME}-${LOCALHOST} 2>&1 + +run_libvirt:: + [ -f ${INST_BOX_DIR}/images/${INST_BOX_NAME}.img ] + @virsh net-list | grep "${NETWORK}.*active" || \ + sudo virsh net-start "${NETWORK}" + @virsh list | grep ${INST_BOX_NAME} && \ + virsh define ${INST_BOX_DIR}/xml/${INST_BOX_NAME}.xml + @virsh list | grep "${INST_BOX_NAME}.*running" || \ + virsh start ${INST_BOX_NAME} + sh ansible_local.bash --diff -i hosts.yml -l ${INST_BOX_NAME} \ + -c libvirt_qemu --verbose ${VERBOSE} $(ROLES) \ + > .run-${INST_BOX_NAME}-${LOCALHOST} 2>&1 + +test:: + @[ -d /mnt/gentoo/lost+found ] && \ + sudo $(MAKE) -$(MAKEFLAGS) $@_chroot + @[ -f ${INST_BOX_DIR}/images/${INST_BOX_NAME}.img ] && \ + sudo $(MAKE) -$(MAKEFLAGS) $@_overlay + +weekly:: test_overlay +test_overlay:: +# bash .pyanal.sh & +# check if ${INST_BOX_NAME} is running + ! sudo virsh list | grep -q ${INST_BOX_NAME} && exit 0 + sudo sh ansible_local.bash --diff -i ${PWD}/hosts.yml \ + -l ${INST_BOX_NAME} -c libvirt_qemu \ + --verbose ${VERBOSE} -t weekly \ + $(ROLES) > .check-${LOCALHOST} 2>&1 + clean:: find . -name \*~ -delete diff --git a/READMD.md b/READMD.md deleted file mode 100644 index 9bc9076..0000000 --- a/READMD.md +++ /dev/null @@ -1,3 +0,0 @@ - -Spin up libvrt instances from a cloud-init capable base that can be maintained using chroot on qcow2. - diff --git a/README.md b/README.md new file mode 100644 index 0000000..a9dbe40 --- /dev/null +++ b/README.md @@ -0,0 +1,155 @@ + +Spin up libvrt instances from a cloud-init capable base that can be +maintained using chroot on qcow2, and by ansible using libvirt_qemu. + +This builds on two projects: +1) bash scripts to take a Gentoo qcow2 nightly box and use it as a base layer +for another qcow image that you spin up in libvirt, overlaying the base layer +for testing. You can then throw away that image for each test (if you like); +it takes less than a minute to make the base qcow2 layer, and other minute +to make the overlay layer and spin it up. +https://github.com/earlruby/create-vm/ + +2) python scripts to take a Gentoo stage3 and portage to build a qcow2 box and +use it as a base layer for a cloud-init capable qcow image. +https://github.com/NucleaPeon/gentooimgr/ + +The huge advantage of this is that you can maintain the base image +under chroot, so you can build test instances that have no incoming +network and still maintain them using tools like ansible, which +support maintaing chroot instances. The problem of using 1) gentooimgr +is that the configuration code of the install step is written in +Python, rather than handled by a more capable tool like ansible. + +The problem of using 2) gentooimgr is that the base box may be old (it +is) and you may want to use an existing gentoo kernel and initramfs, +and the base box may be missing qemu-quest-agent (it is). *Much* worse +is that to use cloud-init you have to load rust and 344 crates from +God only knows where that you'll never audit, just to get oauth: no +thanks Google. + +You can use ansible to maintain the base layer using chroot, and use +it again to create and spin up the test instance. And as we install +qemu-quest-agent in the base layer, you can manage the test instance +with ansible using libvirt guest-agent, even if the test instance +allows no incoming network. + +For now, the code is written to build Gentoo base images, but it could +be extended to other bases. It can build a Gentoo base image from a +Gentoo system. or another system with a Gentoo system mounted on some +directory, that can be chrooted into, and files copied from. It may be +able to build from a Debian without a mounted Gentoo filesystem, but this +is currently untested. + +## Workflow + +1) We build the qcow2 base image that we can maintain by chroot +mounting the disk, so we can sort out problems conveniently. We started +doing that by using EarlRuby's python approach, but later rewrote an +old ansible role by https://github.com/agaffney/ansible-gentoo_install/ +That ansible role is in roles/ansible-gentoo_install/tasks/ which is +executed as an included role by the toxcore role. + +It's a very basic piece of coding that works on a local connection +and is run on the host by the build_base Makefile target. It starts +out as a local connection play, and run chroot internally when it needs it. +You must set these variable in a host in hosts.yml in the linux_chroot_group: + BOX_NBD_DEV: nbd1 + BOX_NBD_MP: /mnt/gentoo + BOX_NBD_FILES: "/i/data/Agile/tmp/Topics/GentooImgr" + BOX_NBD_BASE_QCOW: "/g/Agile/tmp/Topics/GentooImgr/gentoo.qcow2" +It will build the BOX_NBD_BASE_QCOW. + +2) We build the qcow2 overlay image that we can maintain by libvirt. + + +## Roles + +There are 3 ansible roles: + +1. base : The base role sets up the basics and is required to be run. + +2. proxy : The proxy role sets up the networking with proxies, + and is required to be run, even if you don't use a proxy. + +3. toxcore : + +Each role has been conditionalized to run with different connections. + +## Connection Types + +There are 3 ansible connection types: + +1. localhost : ( ansible_connection == local ) + Running the roles with a local connection will setup the host to + be able to run the software. The toxcore role will build the + toxcore software on the localhost and runs tests on it. It will also + build the base qcow2 image that will underly the overlay box. + +2. chroot : ( ansible_connection == chroot ) + When you have built the base box, you can chroot mount the qcow2 image + with qemu-nbd, so all of the configuring of the base can be done without + a network. A local bash script then builds the overlay qcow2 instance, + in less than a minute. + +3. remote : ( ansible_connection == libvirt_qemu ) + The base box provides the libvirt_qemu connection that is be used + to run ansible roles on the overlay image. The toxcore role will + build the toxcore software in the overlay and runs tests on it. + +All of the 3 roles can all be run with all 3 connection types. + +## Stages + +There are 4 stages to building an instance: + +1. Setup the localhost : + set up the host up with the software and settings needed to build boxes. + +2. Build the base qcow2 base box : + +3. Build the overlay qcow2 instance : + +4. Test the overlay instance : + +## Hosts.yml targets + +## Makefile targets + +all: install lint build check run test + +1. install + +2. lint + +3. build + +4. check + +5. run + +6. test + +## Simplest usage + +On Ansibles from 2.10 and later, you will need the community plugins installed. + +### Downloaded base qcow + +### Created and copuied base qcow on a Gentoo system + +### Created and copied base qcow on a non-Gentoo system with a Gentoo mounted + +## Advanced Usage + +### ansible_local.bash + +[ -l limit ] +[ -c connection ] +[ --skip comma,separated] +[ --tags comma,separated] +[ --check] +[ --diff] +[ --step] +[ --verbose 0-3] higher number, more debugging +roles - base and proxy roles will always be run. diff --git a/bin/toxcore_create-vm.bash b/bin/toxcore_create-vm.bash index 535614a..4ce9bac 100755 --- a/bin/toxcore_create-vm.bash +++ b/bin/toxcore_create-vm.bash @@ -1,5 +1,6 @@ #!/bin/bash # -*- mode: sh; fill-column: 75; tab-width: 8; coding: utf-8-unix -*- +# from https://github.com/earlruby/create-vm/ [ -f /usr/local/bin/usr_local_tput.bash ] && \ . /usr/local/bin/usr_local_tput.bash || { diff --git a/bin/toxcore_delete-vm.bash b/bin/toxcore_delete-vm.bash index 5980b63..f693250 100755 --- a/bin/toxcore_delete-vm.bash +++ b/bin/toxcore_delete-vm.bash @@ -1,15 +1,19 @@ #!/bin/bash # -*- mode: sh; fill-column: 75; tab-width: 8; coding: utf-8-unix -*- +# from https://github.com/earlruby/create-vm/ -. /usr/local/bin/usr_local_tput.bash +[ -f /usr/local/bin/usr_local_tput.bash ] && \ + . /usr/local/bin/usr_local_tput.bash || { + DBUG() { echo DEBUG $* ; } + INFO() { echo INFO $* ; } + WARN() { echo WARN $* ; } + ERROR() { echo ERROR $* ; } + } prog=`basename $0 .bash` PREFIX=/usr/local ROLE=toxcore -. /usr/local/etc/testforge/testforge.bash -[ -n "$HOSTVMS_VAR_LOCAL" ] && PREFIX=$HOSTVMS_VAR_LOCAL - # delete-vm - Delete a virtual machine created with create-vm # Copyright 2018-2023 Earl C. Ruby III diff --git a/bin/toxcore_get-vm-ip.bash b/bin/toxcore_get-vm-ip.bash index afe30f8..4b0f42a 100755 --- a/bin/toxcore_get-vm-ip.bash +++ b/bin/toxcore_get-vm-ip.bash @@ -1,7 +1,14 @@ #!/bin/bash # -*- mode: sh; fill-column: 75; tab-width: 8; coding: utf-8-unix -*- +# from https://github.com/earlruby/create-vm/ -. /usr/local/bin/usr_local_tput.bash +[ -f /usr/local/bin/usr_local_tput.bash ] && \ + . /usr/local/bin/usr_local_tput.bash || { + DBUG() { echo DEBUG $* ; } + INFO() { echo INFO $* ; } + WARN() { echo WARN $* ; } + ERROR() { echo ERROR $* ; } + } prog=`basename $0 .bash` PREFIX=/usr/local diff --git a/roles/ansible-gentoo_install/README.md b/roles/ansible-gentoo_install/README.md new file mode 100644 index 0000000..652f906 --- /dev/null +++ b/roles/ansible-gentoo_install/README.md @@ -0,0 +1,30 @@ +# Ansible role: Gentoo_install + +Performs an installation of Gentoo Linux against an InstallCD environment. + +This role handles all steps required to install Gentoo Linux when run against +the InstallCD environment. It will partition, format/mount filesystems, +download/extract the stage tarball, configure locales and timezone, build a +kernel (using genkernel), install/configure syslog and cron daemons, install +grub, unmount filesystems, and reboot. + +In order to use this role, you will need to boot the InstallCD image with +parameters like: + + gentoo dosshd passwd=some_root_pass + +create a playbook: + + --- + - hosts: all + remote_user: root + vars: + # The 'portage' module breaks on py3, which is the default in the stage + # tarball + ansible_python_interpreter: /usr/bin/python2 + roles: + - gentoo_install + +and then run ansible with something like: + + $ ansible-playbook -i , -e ansible_password=some_root_pass -e gentoo_install_hostname=myhostname gentoo_install.yml diff --git a/roles/ansible-gentoo_install/defaults/main.yml b/roles/ansible-gentoo_install/defaults/main.yml new file mode 100644 index 0000000..fd9d091 --- /dev/null +++ b/roles/ansible-gentoo_install/defaults/main.yml @@ -0,0 +1,36 @@ +# -*- mode: yaml; indent-tabs-mode: nil; tab-width: 2; coding: utf-8-unix -*- +--- +AGI_NBD_DEV: "{{BOX_NBD_DEV}}" +AGI_NBD_DISK: "/dev/{{AGI_NBD_DEV}}" +AGI_install_disk: "{{AGI_NBD_DISK}}" +AGI_NBD_PART: "{{AGI_NBD_DEV}}p1" +AGI_NBD_MP: "{{BOX_NBD_MP|default('/mnt/gentoo')}}" +AGI_NBD_FILES: "{{BOX_NBD_FILES|default('/g/Agile/tmp/Topics/GentooImgr')}}" +AGI_GENTOO_FROM_MP: "{{BOX_GENTOO_FROM_MP}}" + +AGI_PROXY_MODE: "{{PROXY_MODE|default('')}}" + +AGI_install_disklabel: msdos +AGI_install_timezone: UTC +AGI_install_locales: + - en_US ISO-8859-1 + - en_US.UTF-8 UTF-8 + - en_GB.UTF-8 UTF-8 +AGI_install_locale_default: en_US.utf8 +AGI_install_hostname: localhost +AGI_install_network_interfaces: + enp0s3: + config: dhcp + ens3: + config: dhcp +AGI_container_disk: /dev/vda + +AGI_install_root_password: root +AGI_install_syslog_daemon: syslog-ng # app-admin/sysklogd +AGI_install_cron_daemon: sys-process/cronie + +AGI_bootstrap_mountpoints: [] + +# for --check +latest_stage_tarball: "{{AGI_NBD_FILES}}/stage3-amd64-openrc-20231217T170203Z.tar.xz" +latest_portage_tarball: "{{AGI_NBD_FILES}}/portage-20231223.tar.xz" diff --git a/roles/ansible-gentoo_install/handlers/main.yml b/roles/ansible-gentoo_install/handlers/main.yml new file mode 100644 index 0000000..d541d8e --- /dev/null +++ b/roles/ansible-gentoo_install/handlers/main.yml @@ -0,0 +1,2 @@ +--- +# handlers file for AGI_install diff --git a/roles/ansible-gentoo_install/meta/main.yml b/roles/ansible-gentoo_install/meta/main.yml new file mode 100644 index 0000000..c606538 --- /dev/null +++ b/roles/ansible-gentoo_install/meta/main.yml @@ -0,0 +1,18 @@ +galaxy_info: + author: Andrew Gaffney + description: Performs an installation of Gentoo Linux against an InstallCD environment + + license: BSD + + min_ansible_version: 2.2 + + platforms: + - name: GenericLinux + versions: + - all + - any + + galaxy_tags: + - gentoo + +dependencies: [] diff --git a/roles/ansible-gentoo_install/tasks/bootloader.yml b/roles/ansible-gentoo_install/tasks/bootloader.yml new file mode 100644 index 0000000..714f016 --- /dev/null +++ b/roles/ansible-gentoo_install/tasks/bootloader.yml @@ -0,0 +1,108 @@ +# -*- mode: yaml; indent-tabs-mode: nil; tab-width: 2; coding: utf-8-unix -*- +--- +- name: "DEBUG: ansible-gentoo_install bootloader" + debug: + verbosity: 1 + msg: "DEBUG: ansible-gentoo_install bootloader" + +- name: test we are in the chroot + shell: | + df | grep {{AGI_NBD_MP}} && exit 1 + check_mode: false + +- name: install grub + portage: + package: sys-boot/grub:2 + state: installed + +- name: install grub to MBR + command: grub-install {{ AGI_install_disk }} + args: + creates: /boot/grub + +- name: generate grub config + shell: grub-mkconfig -o /boot/grub/grub.cfg + args: + creates: /boot/grub/grub.cfg + +- name: edit grub config + shell: | + [ -f /etc/default/grub.dst ] || cp -p /etc/default/grub /etc/default/grub.dst + a=$(cat /proc/cmdline | sed -e 's/ BOOT_IMAGE=[^ ]*/ /' \ + -e 's/ initrd=[^ ]*/ /' + -e 's/ resume=[^ ]*/ /' + -e 's/ root=[^ ]*/ /') + sed -e "s/^#*GRUB_CMDLINE_LINUX=\"\"/GRUB_CMDLINE_LINUX=\"$a\"/" \ + -i /etc/default/grub + grub-script-check /etc/default/grub + +- name: fstab root + lineinfile: + dest: /etc/fstab + line: '{{AGI_container_disk}}3 / ext4 defaults,noatime 0 1' + regexp: '^{{AGI_container_disk}}3' + +- name: fstab boot + lineinfile: + dest: /etc/fstab + line: '{{AGI_container_disk}}1 /boot ext3 defaults,noatime 0 1' + regexp: '^{{AGI_container_disk}}3' + +- name: fstab swap + lineinfile: + dest: /etc/fstab + line: '{{AGI_container_disk}}2 none swap nofail,sw 0 0' + regexp: '^{{AGI_container_disk}}2' + +- name: fstab shm + lineinfile: + dest: /etc/fstab + line: 'tmpfs /run/shm tmpfs defaults,noexec,size=5% 0 0' + regexp: '^tmpfs */run/shm' + +# linuxPen19 /mnt/linuxPen19 virtiofs defaults,dirsync 0 0 + +- name: /etc/security/passwdqc.conf + lineinfile: + dest: /etc/security/passwdqc.conf + line: 'enforce=none' + regexp: '^enforce=.*' + +- name: /etc/security/passwdqc.conf + lineinfile: + dest: /etc/security/passwdqc.conf + line: 'enforce=none' + regexp: '^enforce=.*' + +- name: /etc/conf.d/consolefont + lineinfile: + dest: /etc/conf.d/consolefont + line: 'consolefont="ter-v{{AGI_consolefont_font_size}}b"' + regexp: '^consolefont=.*' + +- name: roles/ansible-gentoo_install/tasks/ + shell: | + LINE="rd.skipfsck=1 ipv6.disable=1 console=tty1 lang=en keymap=us " + # LINE="$LINE pti=on doscsi iommu=pt amd_iommu=on debugfs=off efi=disable_early_pci_dma extra_latent_entropy init_on_free=1 kvm.nx_huge_pages=force l1tf=full,force mce=0 mds=full,nosmt nosmt=force page_alloc.shuffle=1 pti=on random.trust_cpu=off slab_nomerge slub_debug=FZ spec_store_bypass_disable=on spectre_v2=on tsx_async_abort=full,nosmt vsyscall=none " + LINE="$LINE intel_iommu=on vga=0x315 text + df | grep /boot || mount /dev/vda1 /boot + [ -d /boot/grub ] || exit 2 + [ -f /boot/grub/grub.cfg ] || exit 3 + sed -e "s@ ro *$@ $LINE ro@" -i /boot/grub/grub.cfg + +- name: consolefont + shell: | + rc-update add consolefont + cat >> /etc/rc.local << EOF + /etc/init.d consolefont stop + /etc/init.d consolefont start + stty -F /dev/tty1 cols 80 rows 24 + EOF + bash /etc/rc.local + ignore_errors: true + +- name: rc-update add bootlogd boot + shell: | + rc-update | grep -q 'bootlogd .* boot' || \ + rc-update add bootlogd boot + exit 0 diff --git a/roles/ansible-gentoo_install/tasks/chroot.yml b/roles/ansible-gentoo_install/tasks/chroot.yml new file mode 100644 index 0000000..ea769a0 --- /dev/null +++ b/roles/ansible-gentoo_install/tasks/chroot.yml @@ -0,0 +1,55 @@ +# -*- mode: yaml; indent-tabs-mode: nil; tab-width: 2; coding: utf-8-unix -*- +--- +- name: "DEBUG: ansible-gentoo_install chroot.yml" + debug: + verbosity: 1 + msg: "DEBUG: ansible-gentoo_install chroot.yml" + +- name: test we are NOT in the chroot + shell: | + df | grep "{{AGI_NBD_MP}}" || exit 1 + [ -n "{{AGI_NBD_MP}}" ] || exit 2 + [ -d "{{AGI_NBD_MP}}" ] || exit 3 + [ "{{ansible_distribution}}" == 'Gentoo' ] || \ + ( {{AGI_GENTOO_FROM_MP}} != '' && "{{AGI_GENTOO_FROM_MP}}" != '/' ) || \ + exit 4 + [ -d "{{AGI_GENTOO_FROM_MP}}" ] || exit 5 + check_mode: false + +- name: copy resolv.conf into chroot + copy: + src: /etc/resolv.conf + dest: "{{AGI_NBD_MP}}/etc/resolv.conf" + remote_src: yes + when: not ansible_check_mode + +- name: mount /proc in chroot + mount: + name: "{{AGI_NBD_MP}}/proc" + src: proc + fstype: proc + state: mounted + check_mode: false + +- name: bind-mount dirs in chroot + mount: + name: "{{AGI_NBD_MP}}/{{ item }}" + src: /{{ item }} + fstype: auto + opts: bind + state: mounted + with_items: + - sys + - dev + - dev/pts + - dev/shm + check_mode: false + +- name: chroot wrapper script + template: + src: chroot_wrapper.sh + dest: "/var/tmp/chroot_wrapper.sh" + owner: 'root' + mode: '0755' + check_mode: false + diff --git a/roles/ansible-gentoo_install/tasks/copy.yml b/roles/ansible-gentoo_install/tasks/copy.yml new file mode 100644 index 0000000..d9b84ad --- /dev/null +++ b/roles/ansible-gentoo_install/tasks/copy.yml @@ -0,0 +1,114 @@ +# -*- mode: yaml; indent-tabs-mode: nil; tab-width: 2; coding: utf-8-unix -*- +--- +- name: "DEBUG: ansible-gentoo_install copy.yml" + debug: + verbosity: 1 + msg: "DEBUG: ansible-gentoo_install copy.yml" + +- name: test we are NOT in the chroot + shell: | + df | grep "{{AGI_NBD_MP}}" || exit 1 + [ -n "{{AGI_NBD_MP}}" ] || exit 2 + [ -d "{{AGI_NBD_MP}}" ] || exit 3 + [ "{{ansible_distribution}}" == 'Gentoo' ] || \ + ( {{AGI_GENTOO_FROM_MP}} != '' && "{{AGI_GENTOO_FROM_MP}}" != '/' ) || \ + exit 4 + [ -d "{{AGI_GENTOO_FROM_MP}}" ] || exit 5 + check_mode: false + +- name: install to mp from source + delegate_to: localhost + shell: | + cd {{AGI_GENTOO_FROM_MP}}/usr/src/linux || exit 1 + [ -d "{{AGI_NBD_MP}}/lib/modules" ] || mkdir "{{AGI_NBD_MP}}/lib/modules" + make INSTALL_PATH={{AGI_NBD_MP}}/boot install || exit 4 + make INSTALL_MOD_PATH={{AGI_NBD_MP}} modules_install || exit 5 + when: AGI_use_local_kernel + +- name: resolve kernel symlink + shell: | + [ -h {{AGI_GENTOO_FROM_MP}}/usr/src/linux ] && \ + echo $(readlink /usr/src/linux | sed -e 's@/$@@' ) && \ + exit 0 + echo linux + register: kernel_out + check_mode: false + +- name: copy kernel sources + copy: + src: "{{AGI_GENTOO_FROM_MP}}/usr/src/{{kernel_out.stdout}}" + dest: "{{AGI_NBD_MP}}/usr/src" + remote_src: no + creates: "{{AGI_NBD_MP}}/usr/src/" + when: + - kernel_out.rc|default(1) == 0 + - AGI_use_local_kernel + - false # dunno where it went to + +- name: resolve kver + shell: | + kernel="{{kernel_out.stdout}}" + kver=$( echo $kernel | sed -e 's/.*-6\.\([0-9]\)/6.\1/' -e 's/-.*//' ) + echo $kver + register: kver_out + check_mode: false + when: + - kernel_out.rc|default(1) == 0 + +- name: resolve kmods + shell: | + ls -d {{AGI_GENTOO_FROM_MP}}/lib/modules/{{kver_out.stdout}}* | head -1 + register: mods_out + check_mode: false + when: + - kver_out.rc|default(1) == 0 + +- name: resolve vmlinux + shell: | + kver="{{kver_out.stdout}}" + ls {{AGI_GENTOO_FROM_MP}}/boot/vmlinuz-${kver}* | head -1 + register: vmlinux_out + check_mode: false + when: + - kver_out.rc|default(1) == 0 + +- name: copy kernel vmlinux + copy: + src: "{{AGI_GENTOO_FROM_MP}}{{vmlinux_out.stdout}}" + dest: "{{AGI_NBD_MP}}/boot" + remote_src: no + when: + - AGI_use_local_kernel + check_mode: false + +- name: resolve ramfs + shell: | + kver="{{kver_out.stdout}}" + ls {{AGI_GENTOO_FROM_MP}}/boot/initramfs-pentoo-x86_64-${kver}* | head -1 + register: ramfs_out + check_mode: false + when: + - kver_out.rc|default(1) == 0 + +- name: copy kernel vmlinux + copy: + src: "{{AGI_GENTOO_FROM_MP}}{{ramfs_out.stdout}}" + dest: "{{AGI_NBD_MP}}/boot" + remote_src: no + when: + - AGI_use_local_kernel + - ramfs_out.rc|default(1) == 0 + +- name: make directories + shell: | + cd {{AGI_GENTOO_FROM_MP}} || exit 1 + for dir in {{AGI_bootstrap_dirs}}; do + [ -d "{{AGI_NBD_MP}}/{{dir}}" ] && continue + mkdir -p "{{AGI_NBD_MP}}/{{dir}}" + done + for file in {{AGI_bootstrap_files}}; do + [ -f "{{AGI_NBD_MP}}/{{file}}" ] && continue + cp -np "$file" "{{AGI_NBD_MP}}/{{file}}" + done + +# dracut diff --git a/roles/ansible-gentoo_install/tasks/daemons.yml b/roles/ansible-gentoo_install/tasks/daemons.yml new file mode 100644 index 0000000..39eceda --- /dev/null +++ b/roles/ansible-gentoo_install/tasks/daemons.yml @@ -0,0 +1,44 @@ +# -*- mode: yaml; indent-tabs-mode: nil; tab-width: 2; coding: utf-8-unix -*- +--- +- name: "DEBUG: ansible-gentoo_install daemons" + debug: + verbosity: 1 + msg: "DEBUG: ansible-gentoo_install daemons" + +- name: test we are in the chroot + shell: | + df | grep {{AGI_NBD_MP}} && exit 1 + +- name: merge packages + shell: | + MODE={{AGI_PROXY_MODE|default('')}} + . /usr/local/bin/proxy_export.bash + emerge -v {{AGI_bootstrap_pkgs}} + when: "'AGI_bootstrap_pkgs' != []" + +- name: start syslog daemon at boot + service: + name: "{{ AGI_install_syslog_daemon.split('/')[1] }}" + enabled: true + +- name: start cron daemon at boot + service: + name: "{{ AGI_install_cron_daemon.split('/')[1] }}" + enabled: true + +- name: configure sshd + lineinfile: + dest: /etc/ssh/sshd_config + line: 'PermitRootLogin yes' + regexp: '^PermitRootLogin' + +- name: start sshd at boot + service: + name: sshd + enabled: true + +- name: start qemu-guest-agent daemon at boot + service: + name: qemu-guest-agent + enabled: true + diff --git a/roles/ansible-gentoo_install/tasks/disk.yml b/roles/ansible-gentoo_install/tasks/disk.yml new file mode 100644 index 0000000..f0272c9 --- /dev/null +++ b/roles/ansible-gentoo_install/tasks/disk.yml @@ -0,0 +1,63 @@ +# -*- mode: yaml; indent-tabs-mode: nil; tab-width: 2; coding: utf-8-unix -*- +--- +- name: "DEBUG: ansible-gentoo_install disk.yml" + debug: + verbosity: 1 + msg: "DEBUG: ansible-gentoo_install disk.yml" + +- name: test we are NOT in the chroot + shell: | + grep '/dev/{{AGI_NBD_DEV}}' /proc/mounts && exit 1 + [ -n "{{AGI_NBD_MP}}" ] || exit 2 + [ -d "{{AGI_NBD_MP}}" ] || exit 3 + [ "{{ansible_distribution}}" == 'Gentoo' ] || \ + ( {{AGI_GENTOO_FROM_MP}} != '' && "{{AGI_GENTOO_FROM_MP}}" != '/' ) || \ + exit 4 + [ -d "{{AGI_GENTOO_FROM_MP}}" ] || exit 5 + check_mode: false + +- name: create disklabel + command: parted -s {{ AGI_install_disk }} mklabel {{ AGI_install_disklabel }} + +# We need to leave a small gap at the beginning of the disk, or grub won't be +# able to install to the MBR +- name: create boot partition + shell: | + parted -s {{ AGI_install_disk }} mkpart primary ext2 1M 200M + e2label {{ AGI_install_disk }}p1 boot + args: + creates: "{{ AGI_install_disk }}p2" + +- name: mark boot partition as active + shell: | + parted -s {{ AGI_install_disk }} set 1 boot on + +- name: create swap partition + shell: | + parted -s {{ AGI_install_disk }} -- mkpart primary linux-swap 201M 2200M + mkswap -L swap "{{ AGI_install_disk }}p2" + args: + creates: "{{ AGI_install_disk }}p2" + +- name: create root partition + shell: | + parted -s {{ AGI_install_disk }} -- mkpart primary ext4 2201M 20070M + e2label {{ AGI_install_disk }}p3 root + args: + creates: "{{ AGI_install_disk }}p3" + +- name: format boot partition + filesystem: dev={{ AGI_install_disk }}p1 fstype=ext2 force=yes + check_mode: false + when: not ansible_check_mode + +- name: format swap partition + filesystem: dev={{ AGI_install_disk }}p2 fstype=swap force=yes + check_mode: false + when: false + +- name: format root partition + filesystem: dev={{ AGI_install_disk }}p3 fstype=ext4 force=yes + check_mode: false + when: not ansible_check_mode + diff --git a/roles/ansible-gentoo_install/tasks/finish.yml b/roles/ansible-gentoo_install/tasks/finish.yml new file mode 100644 index 0000000..df80bf0 --- /dev/null +++ b/roles/ansible-gentoo_install/tasks/finish.yml @@ -0,0 +1,35 @@ +# -*- mode: yaml; indent-tabs-mode: nil; tab-width: 2; coding: utf-8-unix -*- +--- +- name: "DEBUG: ansible-gentoo_install finish.yml" + debug: + verbosity: 1 + msg: "DEBUG: ansible-gentoo_install finish.yml" + +- name: unmount filesystems + mount: + name: "{{AGI_NBD_MP}}/{{ item }}" + state: unmounted + with_items: + - proc + - sys + - dev/pts + - dev/shm + - dev + - boot + - '' + loop_control: + label: "{{AGI_NBD_MP}}/{{ item }}" + +- name: df umount failsafe + shell: | + grep /mnt/gentoo /proc/mounts|tac|while read a b c ;do sudo umount $b;done + grep /mnt/gentoo/ /proc/mounts|tac|while read a b c ;do sudo umount $b;done + # leave this to be done + grep nbd /proc/mounts || true + +- name: reboot + command: reboot + async: 0 + poll: 0 + ignore_errors: true + when: false diff --git a/roles/ansible-gentoo_install/tasks/kernel.yml b/roles/ansible-gentoo_install/tasks/kernel.yml new file mode 100644 index 0000000..7a18af4 --- /dev/null +++ b/roles/ansible-gentoo_install/tasks/kernel.yml @@ -0,0 +1,31 @@ +# -*- mode: yaml; indent-tabs-mode: nil; tab-width: 2; coding: utf-8-unix -*- +--- +- name: "DEBUG: ansible-gentoo_install portage" + debug: + verbosity: 1 + msg: "DEBUG: ansible-gentoo_install kernel" + +- name: test we are in the chroot + shell: | + df | grep /mnt/gentoo && exit 1 + +- name: install kernel sources + portage: + package: gentoo-sources + state: installed + +- name: install genkernel + portage: + package: sys-kernel/genkernel + state: installed + +- name: build kernel + environment: + # The install guide implies that the kernel build will get angry without + # the locale set + LOCALE: "{{ AGI_install_locale_default }}" + command: genkernel --virtio all + args: + creates: /boot/kernel-genkernel-* + + diff --git a/roles/ansible-gentoo_install/tasks/local.yml b/roles/ansible-gentoo_install/tasks/local.yml new file mode 100644 index 0000000..f0d3156 --- /dev/null +++ b/roles/ansible-gentoo_install/tasks/local.yml @@ -0,0 +1,170 @@ +# -*- mode: yaml; indent-tabs-mode: nil; tab-width: 2; coding: utf-8-unix -*- +--- +- name: "DEBUG: ansible-gentoo_install local" + debug: + verbosity: 0 + msg: "DEBUG: ansible-gentoo_install local BOX_NBD_DEV={{BOX_NBD_DEV}}" + check_mode: no + +- assert: + that: + - "'{{BOX_NBD_DEV}}' != ''" + when: ansible_connection in ['local', 'chroot'] + +- set_fact: + AGI_use_local_kernel: true + when: + - ansible_distribution == 'Gentoo' or BOX_GENTOO_FROM_MP != '' + +- set_fact: + AGI_PROXY_MODE: "{{PROXY_MODE|default('')}}" + when: + - PROXY_MODE|default('') != '' + check_mode: no + +- set_fact: + AGI_PROXY_MODE: "{{BOX_PROXY_MODE|default('')}}" + when: + - AGI_PROXY_MODE == '' + check_mode: no + +- block: + + - name: check for mounted disk + shell: | + grep '/dev/{{AGI_NBD_DEV}}' /proc/mounts + failed_when: false + changed_when: false + register: check_mounted_disk + check_mode: no + + - name: partition if disk not mounted + include: disk.yml + when: + - check_mounted_disk.rc != 0 + check_mode: no + + - name: mount root partition + mount: + name: "{{AGI_NBD_MP}}" + src: "{{ AGI_install_disk }}p3" + fstype: ext4 + state: mounted + check_mode: false + + - name: create /boot mountpoint + file: + path: "{{AGI_NBD_MP}}/boot" + state: directory + check_mode: false + + - name: mount boot partition + mount: + name: "{{AGI_NBD_MP}}/boot" + src: "{{ AGI_install_disk }}p1" + fstype: ext2 + state: mounted + check_mode: false + + - name: mount distfiles + delegate_to: localhost + shell: | + [ -d "{{MOUNT_GENTOO_DISTFILES_ARCHIVES}}" ] || exit 1 + grep {{MOUNT_GENTOO_DISTFILES_ARCHIVES}} /proc/mounts && exit 0 + [ -d {{AGI_NBD_MP}}/usr/portage/ ] || exit 0 + [ -d {{AGI_NBD_MP}}/usr/portage/distfiles ] || mkdir {{AGI_NBD_MP}}/usr/portage/distfiles + mount --bind {{MOUNT_GENTOO_DISTFILES_ARCHIVES}} {{AGI_NBD_MP}}/usr/portage/distfiles + when: + - "MOUNT_GENTOO_DISTFILES_ARCHIVES != ''" + - "AGI_NBD_MP != ''" + - false # let the tester take care of this + + - include: tarball.yml + - include: copy.yml + when: AGI_use_local_kernel + - include: chroot.yml + + delegate_to: localhost + when: ansible_connection in ['chroot', 'local'] # libvirt? + +- block: + + - name: check chroot wrapper installed + shell: | + [ -x /var/tmp/chroot_wrapper.sh ] || exit 1 + df /mnt/gentoo || exit 2 + /var/tmp/chroot_wrapper.sh df | grep /mnt/gentoo && exit 4 + exit 0 + register: chroot_out + check_mode: false + + - name: enable chroot wrapper + set_fact: + ansible_shell_executable: /var/tmp/chroot_wrapper.sh + old_ansible_python_interpreter: "{{ansible_python_interpreter}}" + ansible_python_interpreter: "/usr/bin/python3" + check_mode: false + + when: ansible_connection in ['local'] + +- block: + + - include: portage.yml + - include: misc.yml + + - include: network.yml + + - include: kernel.yml + when: not AGI_use_local_kernel + + - include: bootloader.yml + - include: daemons.yml + + # - include: finish.yml + + check_mode: false + when: + - "ansible_connection in ['chroot'] or chroot_out.rc|default(1) == 0" + rescue: + - debug: + msg: "ERROR: " + +- name: disable chroot wrapper + set_fact: + ansible_shell_executable: /bin/sh + ansible_python_interpreter: "{{old_ansible_python_interpreter}}" + when: + - "ansible_connection in ['local'] and chroot_out.rc|default(1) == 0" + check_mode: false + +- name: unmount filesystems + mount: + name: "{{AGI_NBD_MP}}/{{ item }}" + state: unmounted + with_items: + - proc + - sys + - dev/pts + - dev/shm + - dev + - boot + - '' + loop_control: + label: "{{AGI_NBD_MP}}/{{ item }}" + when: + - "ansible_connection in ['local'] and chroot_out.rc|default(1) == 0" + - false # leave it mounted for testing + +- name: dismount any other mounts + shell: | + if [ -z "{{MOUNT_GENTOO_DISTFILES_ARCHIVES}}" ] && \ + [ -d "{{MOUNT_GENTOO_DISTFILES_ARCHIVES}}" ] && \ + grep {{MOUNT_GENTOO_DISTFILES_ARCHIVES}} /proc/mounts ; then + umount {{MOUNT_GENTOO_DISTFILES_ARCHIVES}} + fi + df -a | grep "{{AGI_NBD_MP}}" | sed -e 's/.* //' | tac | while read elt;do + umount $elt + done + when: + - "ansible_connection in ['chroot'] or chroot_out.rc|default(1) == 0" + - false # leave it mounted for testing diff --git a/roles/ansible-gentoo_install/tasks/main.yml b/roles/ansible-gentoo_install/tasks/main.yml new file mode 100644 index 0000000..6a9e929 --- /dev/null +++ b/roles/ansible-gentoo_install/tasks/main.yml @@ -0,0 +1,72 @@ +# -*- mode: yaml; indent-tabs-mode: nil; tab-width: 2; coding: utf-8-unix -*- +--- +- name: "DEBUG: ansible-gentoo_install nbd_disk ansible_connection" + debug: + verbosity: 1 + msg: "DEBUG: ansible-gentoo_install nbd_disk={{ nbd_disk }} ansible_connection={{ ansible_connection }}" + check_mode: false + +- set_fact: + AGI_target: Gentoo2 + +- name: look for nbd partitions + shell: | + grep nbd /proc/partitions | head -1 + register: nbd_out + failed_when: false + check_mode: false + +- name: "include base by-platform vars" + include_vars: "{{item}}.yml" + with_items: + - "Linux" + - "{{ ansible_distribution }}{{ ansible_distribution_major_version }}" + - "target_{{AGI_target}}" + tags: always + +- name: find module gentooimgr + shell: | + echo nbd_disk={{ nbd_disk }} ansible_connection={{ ansible_connection }} + echo ansible_distribution={{ansible_distribution}} BOX_GENTOO_FROM_MP={{BOX_GENTOO_FROM_MP}} + [ -d '/mnt/o/var/local/src/play_tox/src/ansible_gentooimgr' ] || exit 1 + [ -f '/mnt/o/var/local/src/play_tox/src/ansible_gentooimgr/__init__.py' ] || exit 2 + [ -d '/mnt/o/var/local/src/play_tox/src/ansible_gentooimgr/gentooimgr' ] || exit 3 + [ -f '/mnt/o/var/local/src/play_tox/src/ansible_gentooimgr/gentooimgr/__init__.py' ] || exit 4 + {{ansible_python_interpreter}} \ + -c "import sys; sys.path.append('/mnt/o/var/local/src/play_tox/src/ansible_gentooimgr'); import gentooimgr; print(gentooimgr.__file__)" + register: gentooimgr_out + check_mode: false + ignore_errors: true + +- block: + + - set_fact: + AGI_gentooimgr_configs: "{{gentooimgr_out.stdout}}/configs" + + - name: ansible_gentooimgr nbd status + ansible_gentooimgr: + action: status + loglevel: 10 + threads: 1 + config: cloud.config + profile: openrc + kernel_dir: /usr/src/linux + portage: '{{AGI_NBD_FILES}}/portage-20231223.tar.xz' + stage3: '{{AGI_NBD_FILES}}/stage3-amd64-openrc-20231217T170203Z.tar.xz' + temporary_dir: "{{AGI_NBD_FILES}}" + download_dir: "{{AGI_NBD_FILES}}" + + ignore_errors: true + check_mode: false + + check_mode: false + when: + - ansible_connection in ['chroot', 'local', 'libvirt_qemu'] + - ansible_distribution == 'Gentoo' or BOX_GENTOO_FROM_MP != '' +# - nbd_disk|default('') == AGI_NBD_DISK + +- include_tasks: local.yml + when: + - ansible_connection in ['chroot', 'local'] + - ansible_distribution == 'Gentoo' or BOX_GENTOO_FROM_MP != '' + - nbd_disk|default('') == AGI_NBD_DISK diff --git a/roles/ansible-gentoo_install/tasks/misc.yml b/roles/ansible-gentoo_install/tasks/misc.yml new file mode 100644 index 0000000..1307537 --- /dev/null +++ b/roles/ansible-gentoo_install/tasks/misc.yml @@ -0,0 +1,112 @@ +# -*- mode: yaml; indent-tabs-mode: nil; tab-width: 2; coding: utf-8-unix -*- +--- +- name: "DEBUG: ansible-gentoo_install/tasks/ misc.yml" + debug: + verbosity: 1 + msg: "DEBUG: ansible-gentoo_install/tasks/ misc.yml" + +- name: test we are in the chroot + shell: | + df | grep /mnt/gentoo && exit 1 + +- name: "make /mnt mountpoints" + shell: | + [ -d /mnt ] || mkdir /mnt || exit 1 + for elt in {{ AGI_bootstrap_mountpoints|join(' ') }} ; do + [ -d $elt ] || mkdir $elt + done + exit 0 + when: AGI_bootstrap_mountpoints|default([])|length > 0 + +- name: configure timezone + lineinfile: + dest: /etc/timezone + line: "{{ AGI_install_timezone }}" + regexp: '^' + create: yes + owner: root + mode: '0644' + +- name: timezone symlink + file: + dest: /etc/localtime + src: /usr/share/zoneinfo/{{ AGI_install_timezone }} + state: link + force: yes + +- name: configure locales + lineinfile: + dest: /etc/locale.gen + line: "{{ item }}" + with_items: "{{ AGI_install_locales }}" + +- name: generate locales + command: locale-gen + +- name: set default locale + command: eselect locale set {{ AGI_install_locale_default }} + +- name: configure root mount + mount: + name: / + src: "{{ AGI_install_disk }}p3" + fstype: ext4 + state: present + opts: noatime + passno: 1 + +- name: configure boot mountpoint + mount: + name: /boot + src: "{{ AGI_install_disk }}p1" + fstype: ext2 + state: present + opts: noatime,ro + dump: 1 + passno: 2 + +- name: scramble root password + shell: | + echo "{{ AGI_install_root_password|default('root') }}" | \ + openssl password -1 -stdin + register: root_password_out + +- name: set root password + user: + name: root + password: "{{ root_password_out.stdout }}" + +- name: scramble gentoo password + shell: | + echo "{{ AGI_install_gentoo_password|default('gentoo') }}" | \ + openssl password -1 -stdin + register: gentoo_password_out + +- name: set gentoo password + user: + name: gentoo + password: "{{ gentoo_password_out.stdout }}" + +- name: configure sudoers + lineinfile: + dest: /etc/sudoers + line: "%wheel ALL=(ALL:ALL) ALL" + regexp: '^# %wheel ALL=(ALL:ALL) ALL' + create: yes + owner: root + mode: '0640' + +- block: + + - name: make symlinks + shell: | + {% for elt in AGI_bootstrap_pkgs %} + [ -h {{ elt.to }} ] && continue + [ -d {{ elt.to }} ] && echo "WARN: {{ elt.to }} exists as a directory" && continue + parent=`dirname {{ elt.to }}` + [ -d $parent ] || mkdir -p $parent + #? -h-e + [ -h {{ elt.to }} ] || \ + ln -s {{ elt.from }} {{ elt.to }} + {% endfor %} + when: AGI_bootstrap_pkgs|default([])|length > 0 diff --git a/roles/ansible-gentoo_install/tasks/network.yml b/roles/ansible-gentoo_install/tasks/network.yml new file mode 100644 index 0000000..e795e98 --- /dev/null +++ b/roles/ansible-gentoo_install/tasks/network.yml @@ -0,0 +1,56 @@ +# -*- mode: yaml; indent-tabs-mode: nil; tab-width: 2; coding: utf-8-unix -*- +--- +- name: "DEBUG: ansible-gentoo_install network" + debug: + verbosity: 1 + msg: "DEBUG: ansible-gentoo_install network" + +- name: test we are in the chroot + shell: | + df | grep /mnt/gentoo && exit 1 + +- name: configure hostname + lineinfile: + dest: /etc/conf.d/hostname + line: 'hostname="{{ AGI_install_hostname }}"' + regexp: '^hostname=' + +- name: install netifrc + portage: + package: net-misc/netifrc + state: installed + +- name: install DHCP client + portage: + package: net-misc/dhcpcd + state: installed + +- name: configure network interfaces + lineinfile: + dest: /etc/conf.d/net + create: yes + owner: root + mode: '0644' + line: 'config_{{ item.key }}="{{ item.value.config }}"' + regexp: '^config_{{ item.key }}=' + with_dict: "{{ AGI_install_network_interfaces }}" + loop_control: + label: "{{ item.key }}" + +- name: create network interface init symlink + file: + path: /etc/init.d/net.{{ item.key }} + src: net.lo + force: yes + state: link + with_dict: "{{ AGI_install_network_interfaces }}" + loop_control: + label: "{{ item.key }}" + +- name: start network interface at boot + service: + name: net.{{ item.key }} + enabled: true + with_dict: "{{ AGI_install_network_interfaces }}" + loop_control: + label: "{{ item.key }}" diff --git a/roles/ansible-gentoo_install/tasks/portage.yml b/roles/ansible-gentoo_install/tasks/portage.yml new file mode 100644 index 0000000..00f4298 --- /dev/null +++ b/roles/ansible-gentoo_install/tasks/portage.yml @@ -0,0 +1,52 @@ +# -*- mode: yaml; indent-tabs-mode: nil; tab-width: 2; coding: utf-8-unix -*- +--- +- name: "DEBUG: ansible-gentoo_install portage ansible_shell_executable={{ansible_shell_executable}}" + debug: + verbosity: 1 + msg: "DEBUG: ansible-gentoo_install portage ansible_shell_executable={{ansible_shell_executable}}" + +- name: reenable chroot wrapper + set_fact: + ansible_shell_executable: /var/tmp/chroot_wrapper.sh + ansible_python_interpreter: "/usr/bin/python3" + +- name: test we are in the chroot + shell: | + df | grep /mnt/gentoo && exit 1 + +- name: portage make.conf settings + lineinfile: + dest: /etc/portage/make.conf + line: '{{ item.key }}="{{ item.value }}"' + regexp: '^{{ item.key }}=' + with_dict: "{{ AGI_install_portage_makeconf_default | combine( AGI_install_portage_makeconf | default({}) ) }}" + loop_control: + label: "{{ item.key }}" + +# Using blockinfile as a workaround to 'copy' not working with the chroot hack +- name: other portage config files + blockinfile: + dest: /etc/portage/{{ item.key }} + content: "{{ item.value }}" + owner: root + mode: '0644' + create: yes + with_dict: "{{ AGI_install_portage_conf_files | default({}) }}" + loop_control: + label: "{{ item.key }}" + when: false + +- name: install portage tree snapshot + command: emerge-webrsync + when: false + +#- name: update portage tree +# command: emerge --sync + +# The 'portage' module doesn't work without the 'equery' command available, +# which is provided by the gentoolkit package +- name: install gentoolkit package + command: emerge app-portage/gentoolkit + args: + creates: /var/db/pkg/app-portage/gentoolkit-* + when: false # old bug in portage? diff --git a/roles/ansible-gentoo_install/tasks/tarball.yml b/roles/ansible-gentoo_install/tasks/tarball.yml new file mode 100644 index 0000000..f6eb388 --- /dev/null +++ b/roles/ansible-gentoo_install/tasks/tarball.yml @@ -0,0 +1,156 @@ +# -*- mode: yaml; indent-tabs-mode: nil; tab-width: 2; coding: utf-8-unix -*- +# localhost +--- +- name: "DEBUG: ansible-gentoo_install tarball" + debug: + verbosity: 1 + msg: "DEBUG: ansible-gentoo_install tarball" + +- name: test we are NOT in the chroot + shell: | + [ -n "{{AGI_NBD_MP}}" ] || exit 2 + [ -d "{{AGI_NBD_MP}}" ] || exit 3 + check_mode: false + +- name: gpg keys system + # Option --keyserver must be used to + environment: "{{proxy_env}}" + shell: | + /usr/bin/gpg --list-keys | grep "{{ item.uid }}" || \ + /usr/bin/gpg --recv-keys \ + --keyserver "{{ AGI_GPG_SERVER }}" "{{ item.uid }}" + with_items: "{{ agi_gpg_keys_system }}" + when: + - agi_gpg_keys_system|length > 0 + - BASE_ARE_CONNECTED|default('') != '' + # FixMe: + ignore_errors: true + +- name: check files dir + environment: "{{shell_env}}" + shell: | + AGI_NBD_FILES="{{AGI_NBD_FILES}}" + [ -n "$AGI_NBD_FILES" ] || exit 1 + [ -d "$AGI_NBD_FILES" ] || exit 2 + +- name: determine latest stage tarball + environment: "{{proxy_env}}" + uri: + url: "{{ AGI_install_baseurl }}{{ AGI_install_latest_stage_pointer }}" + return_content: yes + dest: "{{AGI_NBD_FILES}}/latest-stage3-amd64-openrc.txt" + creates: "{{AGI_NBD_FILES}}/latest-stage3-amd64-openrc.txt" + register: latest_stage + +- name: read tarball + environment: "{{shell_env}}" + shell: | + AGI_NBD_FILES="{{AGI_NBD_FILES}}" + filename=$(grep ^stage "$AGI_NBD_FILES/latest-stage3-amd64-openrc.txt" | \ + sed -e 's/ .*//' ) ; + suffix=$(echo $filename | sed -e 's/.*\././' ); + prefix=$(echo $filename | sed -e "s/$suffix//" ); + echo $filename + register: tarball_out + +- set_fact: + latest_stage_tarball_url_suffix: "{{ ( latest_stage.content.splitlines() | reject('match', '#') | first ).split(' ')[0] }}" + latest_stage_tarball: "{{ ( latest_stage.content.splitlines() | reject('match', '#') | first ).split(' ')[0].split('/')[1] }}" + when: + - not ansible_check_mode + - false + +- set_fact: + latest_stage_tarball_url_suffix: "{{tarball_out.stdout}}" + # there's not directory now + latest_stage_tarball: "{{tarball_out.stdout}}" + latest_portage_tarball: portage-20231223.tar.xz + when: + - not ansible_check_mode + - tarball_out.rc|default(1) == 0 + +- name: fetch latest stage tarball + environment: "{{proxy_env}}" + delegate_to: localhost + uri: + url: "{{ item.url }}" + dest: "{{ item.dest }}" + creates: "{{ item.creates }}" + with_items: + - + url: "{{ AGI_install_baseurl }}{{ latest_stage_tarball_url_suffix }}" + dest: "{{AGI_NBD_FILES}}/{{ latest_stage_tarball }}" + creates: "{{AGI_NBD_FILES}}/{{ latest_stage_tarball }}" + - + url: "{{ AGI_install_baseurl }}{{ latest_stage_tarball_url_suffix }}.sha256" + dest: "{{AGI_NBD_FILES}}/{{ latest_stage_tarball }}.sha256" + creates: "{{AGI_NBD_FILES}}/{{ latest_stage_tarball }}.sha256" + when: + - not ansible_check_mode + +- name: check stage tarball + environment: "{{shell_env}}" + shell: | + cd "{{AGI_NBD_FILES}}" || exit 1 + sha256sum "{{ latest_stage_tarball }}.sha256" + when: + - not ansible_check_mode + +- name: extract stage tarball + unarchive: + src: "{{AGI_NBD_FILES}}/{{ latest_stage_tarball }}" + dest: "{{AGI_NBD_MP}}" + remote_src: no + creates: "{{AGI_NBD_MP}}/var" + +- name: fetch latest portage tarball + environment: "{{proxy_env}}" + delegate_to: localhost + uri: + url: "{{ AGI_install_baseurl }}{{ latest_portage_tarball }}" + dest: "{{AGI_NBD_FILES}}/{{ latest_portage_tarball }}" + creates: "{{AGI_NBD_FILES}}/{{ latest_portage_tarball }}" + + +- name: test portage tarball + environment: "{{shell_env}}" + shell: | + cd "{{AGI_NBD_FILES}}" + md5sum -c "{{ latest_portage_tarball }}.md5sum" + +- name: test gpg not GENTOO + environment: "{{shell_env}}" + shell: | + # E1D6ABB63BFCFB4BA02FDF1CEC590EEAC9189250 + [ -f /usr/local/share/openpgp-keys/gentoo-release.asc ] || exit 1 + gpg --list-keys | grep E1D6ABB63BFCFB4BA02FDF1CEC590EEAC9189250 || \ + gpg --import /usr/local/share/openpgp-keys/gentoo-release.asc || exit 2 + when: + - "ansible_distribution != 'Gentoo'" + +- name: test gpg GENTOO + shell: | + # E1D6ABB63BFCFB4BA02FDF1CEC590EEAC9189250 + [ -f /usr/share/openpgp-keys/gentoo-release.asc ] || \ + emerge -v sec-keys/openpgp-keys-gentoo-release || exit 1 + gpg --list-keys | grep E1D6ABB63BFCFB4BA02FDF1CEC590EEAC9189250 || \ + gpg --import /usr/share/openpgp-keys/gentoo-release.asc || exit 2 + when: + - "ansible_distribution == 'Gentoo'" + +- name: test portage tarball gpg our copy + environment: "{{shell_env}}" + shell: | + # E1D6ABB63BFCFB4BA02FDF1CEC590EEAC9189250 + gpg --list-keys | grep E1D6ABB63BFCFB4BA02FDF1CEC590EEAC9189250 || exit 2 + gpg --verify "{{AGI_NBD_FILES}}/{{ latest_portage_tarball }}.gpgsig" \ + "{{AGI_NBD_FILES}}/{{ latest_portage_tarball }}" || exit 3$? + +- name: extract portage tarball + unarchive: + src: "{{AGI_NBD_FILES}}/{{ latest_portage_tarball }}" + dest: "{{AGI_NBD_MP}}/usr" + remote_src: no + creates: "{{AGI_NBD_MP}}/usr/portage" + + diff --git a/roles/ansible-gentoo_install/templates/chroot_wrapper.sh b/roles/ansible-gentoo_install/templates/chroot_wrapper.sh new file mode 100644 index 0000000..9acd60f --- /dev/null +++ b/roles/ansible-gentoo_install/templates/chroot_wrapper.sh @@ -0,0 +1,4 @@ +#!/bin/bash +#bash -x /usr/local/sbin/base_chroot.bash {{AGI_NBD_MP|default('/mnt/gentoo')}} "$@" + +chroot {{AGI_NBD_MP|default('/mnt/gentoo')}} /bin/sh "$@" diff --git a/roles/ansible-gentoo_install/templates/etc/libvirt/qemu/gentoo.xml b/roles/ansible-gentoo_install/templates/etc/libvirt/qemu/gentoo.xml new file mode 100644 index 0000000..8a53134 --- /dev/null +++ b/roles/ansible-gentoo_install/templates/etc/libvirt/qemu/gentoo.xml @@ -0,0 +1,210 @@ + + + + gentoo + gentoo by libvirt_cloud + + + + + + 2097152 + 2097152 + + + + + 1 + + hvm + + + + + + + + + + + + + + destroy + restart + destroy + + + + + + /usr/bin/qemu-system-x86_64 + + + + +
+ + +
+ + + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + + +
+ + + +
+ + +
+ + +
+ + + + + +
+ + + + + +
+ + + + + +
+ + + + + + + + + + + +
+ + + +
+ + +
+ + + + + + + + +
+ +