From 768a4e80911d0af7c1a6c928d7bee1926769d03b Mon Sep 17 00:00:00 2001 From: Dyrkon Date: Thu, 30 Mar 2023 15:25:54 +0200 Subject: [PATCH] Fixes #35378 - Add systemd first boot service for host provisioning --- .../provision/kickstart_default.erb | 7 ++-- .../snippet/first_boot_service.erb | 20 ++++++++++ .../snippet/first_boot_setup.erb | 29 ++++++++++++++ .../snippet/fist_boot_initd.erb | 34 ++++++++++++++++ .../Kickstart_default.host4and6dhcp.snap.txt | 40 ++++++++++++++----- .../Kickstart_default.host4dhcp.snap.txt | 40 ++++++++++++++----- .../Kickstart_default.host4static.snap.txt | 40 ++++++++++++++----- .../Kickstart_default.host6dhcp.snap.txt | 40 ++++++++++++++----- .../Kickstart_default.host6static.snap.txt | 40 ++++++++++++++----- .../Kickstart_default.rhel9_dhcp.snap.txt | 40 ++++++++++++++----- 10 files changed, 266 insertions(+), 64 deletions(-) create mode 100644 app/views/unattended/provisioning_templates/snippet/first_boot_service.erb create mode 100644 app/views/unattended/provisioning_templates/snippet/first_boot_setup.erb create mode 100644 app/views/unattended/provisioning_templates/snippet/fist_boot_initd.erb diff --git a/app/views/unattended/provisioning_templates/provision/kickstart_default.erb b/app/views/unattended/provisioning_templates/provision/kickstart_default.erb index da7b7b12d79..d9a8e875d79 100644 --- a/app/views/unattended/provisioning_templates/provision/kickstart_default.erb +++ b/app/views/unattended/provisioning_templates/provision/kickstart_default.erb @@ -361,6 +361,8 @@ sed -e 's/DEFAULTKERNEL=kernel-uek/DEFAULTKERNEL=kernel/g' -i /etc/sysconfig/ker <%= snippet 'insights' if host_param_true?('host_registration_insights') && os_major < 9 -%> +<%= snippet 'first_boot_setup' %> + touch /tmp/foreman_built <% if host_param_true?('use_graphical_installer') -%> @@ -387,10 +389,7 @@ The last post section halts Anaconda to prevent endless loop in case HTTP reques <%= snippet 'eject_cdrom' -%> -if test -f /tmp/foreman_built; then - echo "calling home: build is done!" - <%= indent(2, skip1: true) { snippet('built', :variables => { :endpoint => 'built', :method => 'POST', :body_file => '/root/install.post.log' }) } -%> -else +if ! test -f /tmp/foreman_built; then echo "calling home: build failed!" <%= indent(2, skip1: true) { snippet('built', :variables => { :endpoint => 'failed', :method => 'POST', :body_file => '/root/install.post.log' }) } -%> fi diff --git a/app/views/unattended/provisioning_templates/snippet/first_boot_service.erb b/app/views/unattended/provisioning_templates/snippet/first_boot_service.erb new file mode 100644 index 00000000000..6924cf9f8de --- /dev/null +++ b/app/views/unattended/provisioning_templates/snippet/first_boot_service.erb @@ -0,0 +1,20 @@ +<%# +kind: snippet +name: first_boot_service +model: ProvisioningTemplate +snippet: true +description: | + Post replacement service +-%> +[Unit] +Description=Initial setup callback +Wants=network-online.target +After=network-online.target + +[Service] +ExecStart=/bin/bash /root/first_boot_script.sh +Type=oneshot +ExecStartPost=/usr/bin/systemctl disable first_boot_service + +[Install] +WantedBy=multi-user.target diff --git a/app/views/unattended/provisioning_templates/snippet/first_boot_setup.erb b/app/views/unattended/provisioning_templates/snippet/first_boot_setup.erb new file mode 100644 index 00000000000..e7885ad5246 --- /dev/null +++ b/app/views/unattended/provisioning_templates/snippet/first_boot_setup.erb @@ -0,0 +1,29 @@ +<%# +kind: snippet +name: first_boot_setup +model: ProvisioningTemplate +snippet: true +description: | + Post replacement for both systemd and non-systemd platforms +-%> +<% + os_major = @host.operatingsystem.major.to_i + rhel_compatible = @host.operatingsystem.family == 'Redhat' && @host.operatingsystem.name != 'Fedora' + has_systemd = (@host.operatingsystem.name == 'Fedora' && os_major >= 20) || (rhel_compatible && os_major >= 7) || (@host.operatingsystem.name == 'Ubuntu' && os_major >= 15) || (@host.operatingsystem.name == 'Debian' && os_major >= 8) +-%> +<% if has_systemd -%> + <%= save_to_file('/etc/systemd/system/first_boot_service.service', snippet('first_boot_service')) %> + <%= save_to_file('/root/first_boot_script.sh', snippet('built', :variables => { :endpoint => 'built', :method => 'POST', :body_file => '/root/install.post.log' })) %> + + systemctl enable first_boot_service +<% else -%> + <%= save_to_file('/root/first_boot_script.sh', snippet('built', :variables => { :endpoint => 'built', :method => 'POST', :body_file => '/root/install.post.log' }) + + "\nmv /root/first_boot_script.sh /root/first_boot_script.disabled") %> + <%= save_to_file('/etc/init.d/first_boot_setup', snippet('first_boot_initd')) %> + + chmod +x /etc/init.d/first_boot_setup + chkconfig --add /etc/init.d/first_boot_setup + chkconfig --level 2345 first_boot_setup on +<% end -%> + +chmod +x /root/first_boot_script.sh diff --git a/app/views/unattended/provisioning_templates/snippet/fist_boot_initd.erb b/app/views/unattended/provisioning_templates/snippet/fist_boot_initd.erb new file mode 100644 index 00000000000..b468e6c1335 --- /dev/null +++ b/app/views/unattended/provisioning_templates/snippet/fist_boot_initd.erb @@ -0,0 +1,34 @@ +<%# +kind: snippet +name: first_boot_initd +model: ProvisioningTemplate +snippet: true +description: | + Post replacement initd script +-%> +#! /bin/bash + +### BEGIN INIT INFO +# Provides: RedHat +# Required-Start: $local_fs $network +# Required-Stop: $local_fs +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Execute first boot script +# Description: Execute first boot script which executes after machine is successfully built for the first time. +### END INIT INFO + +# Source function library +. /etc/rc.d/init.d/functions + +##Service start/stop functions## +start() { +/tmp/first_boot_script +chkconfig --del first_boot_setup +} + +start + +exit 5 +esac +exit $? \ No newline at end of file diff --git a/test/unit/foreman/renderer/snapshots/ProvisioningTemplate/provision/Kickstart_default.host4and6dhcp.snap.txt b/test/unit/foreman/renderer/snapshots/ProvisioningTemplate/provision/Kickstart_default.host4and6dhcp.snap.txt index c52b7232b07..78246060da3 100644 --- a/test/unit/foreman/renderer/snapshots/ProvisioningTemplate/provision/Kickstart_default.host4and6dhcp.snap.txt +++ b/test/unit/foreman/renderer/snapshots/ProvisioningTemplate/provision/Kickstart_default.host4and6dhcp.snap.txt @@ -164,6 +164,35 @@ systemctl enable ansible-callback + cat << EOF-782969c0 > /etc/systemd/system/first_boot_service.service +[Unit] +Description=Initial setup callback +Wants=network-online.target +After=network-online.target + +[Service] +ExecStart=/bin/bash /root/first_boot_script.sh +Type=oneshot +ExecStartPost=/usr/bin/systemctl disable first_boot_service + +[Install] +WantedBy=multi-user.target +EOF-782969c0 + cat << EOF-76fe21d9 > /root/first_boot_script.sh +if [ -x /usr/bin/curl ]; then + /usr/bin/curl -o /dev/null --noproxy \* -H 'Content-Type: text/plain' --data @/root/install.post.log --silent 'http://foreman.example.com/unattended/built' +elif [ -x /usr/bin/wget ]; then + /usr/bin/wget -q -O /dev/null --no-proxy --method POST --header 'Content-Type: text/plain' --body-file=/root/install.post.log 'http://foreman.example.com/unattended/built' +else + wget -q -O /dev/null --header 'Content-Type: text/plain' 'http://foreman.example.com/unattended/built' +fi +EOF-76fe21d9 + + systemctl enable first_boot_service + +chmod +x /root/first_boot_script.sh + + touch /tmp/foreman_built chvt 1 @@ -179,16 +208,7 @@ cp -vf /tmp/*.pre.*.log /mnt/sysimage/root/ %post --erroronfail --log=/root/install-callhome.post.log -if test -f /tmp/foreman_built; then - echo "calling home: build is done!" - if [ -x /usr/bin/curl ]; then - /usr/bin/curl -o /dev/null --noproxy \* -H 'Content-Type: text/plain' --data @/root/install.post.log --silent 'http://foreman.example.com/unattended/built' - elif [ -x /usr/bin/wget ]; then - /usr/bin/wget -q -O /dev/null --no-proxy --method POST --header 'Content-Type: text/plain' --body-file=/root/install.post.log 'http://foreman.example.com/unattended/built' - else - wget -q -O /dev/null --header 'Content-Type: text/plain' 'http://foreman.example.com/unattended/built' - fi -else +if ! test -f /tmp/foreman_built; then echo "calling home: build failed!" if [ -x /usr/bin/curl ]; then /usr/bin/curl -o /dev/null --noproxy \* -H 'Content-Type: text/plain' --data @/root/install.post.log --silent 'http://foreman.example.com/unattended/failed' diff --git a/test/unit/foreman/renderer/snapshots/ProvisioningTemplate/provision/Kickstart_default.host4dhcp.snap.txt b/test/unit/foreman/renderer/snapshots/ProvisioningTemplate/provision/Kickstart_default.host4dhcp.snap.txt index 7d50d54e6f5..d4bd2e8dc29 100644 --- a/test/unit/foreman/renderer/snapshots/ProvisioningTemplate/provision/Kickstart_default.host4dhcp.snap.txt +++ b/test/unit/foreman/renderer/snapshots/ProvisioningTemplate/provision/Kickstart_default.host4dhcp.snap.txt @@ -164,6 +164,35 @@ systemctl enable ansible-callback + cat << EOF-782969c0 > /etc/systemd/system/first_boot_service.service +[Unit] +Description=Initial setup callback +Wants=network-online.target +After=network-online.target + +[Service] +ExecStart=/bin/bash /root/first_boot_script.sh +Type=oneshot +ExecStartPost=/usr/bin/systemctl disable first_boot_service + +[Install] +WantedBy=multi-user.target +EOF-782969c0 + cat << EOF-76fe21d9 > /root/first_boot_script.sh +if [ -x /usr/bin/curl ]; then + /usr/bin/curl -o /dev/null --noproxy \* -H 'Content-Type: text/plain' --data @/root/install.post.log --silent 'http://foreman.example.com/unattended/built' +elif [ -x /usr/bin/wget ]; then + /usr/bin/wget -q -O /dev/null --no-proxy --method POST --header 'Content-Type: text/plain' --body-file=/root/install.post.log 'http://foreman.example.com/unattended/built' +else + wget -q -O /dev/null --header 'Content-Type: text/plain' 'http://foreman.example.com/unattended/built' +fi +EOF-76fe21d9 + + systemctl enable first_boot_service + +chmod +x /root/first_boot_script.sh + + touch /tmp/foreman_built chvt 1 @@ -179,16 +208,7 @@ cp -vf /tmp/*.pre.*.log /mnt/sysimage/root/ %post --erroronfail --log=/root/install-callhome.post.log -if test -f /tmp/foreman_built; then - echo "calling home: build is done!" - if [ -x /usr/bin/curl ]; then - /usr/bin/curl -o /dev/null --noproxy \* -H 'Content-Type: text/plain' --data @/root/install.post.log --silent 'http://foreman.example.com/unattended/built' - elif [ -x /usr/bin/wget ]; then - /usr/bin/wget -q -O /dev/null --no-proxy --method POST --header 'Content-Type: text/plain' --body-file=/root/install.post.log 'http://foreman.example.com/unattended/built' - else - wget -q -O /dev/null --header 'Content-Type: text/plain' 'http://foreman.example.com/unattended/built' - fi -else +if ! test -f /tmp/foreman_built; then echo "calling home: build failed!" if [ -x /usr/bin/curl ]; then /usr/bin/curl -o /dev/null --noproxy \* -H 'Content-Type: text/plain' --data @/root/install.post.log --silent 'http://foreman.example.com/unattended/failed' diff --git a/test/unit/foreman/renderer/snapshots/ProvisioningTemplate/provision/Kickstart_default.host4static.snap.txt b/test/unit/foreman/renderer/snapshots/ProvisioningTemplate/provision/Kickstart_default.host4static.snap.txt index 57d92894b60..ffc8bf2a0f5 100644 --- a/test/unit/foreman/renderer/snapshots/ProvisioningTemplate/provision/Kickstart_default.host4static.snap.txt +++ b/test/unit/foreman/renderer/snapshots/ProvisioningTemplate/provision/Kickstart_default.host4static.snap.txt @@ -164,6 +164,35 @@ systemctl enable ansible-callback + cat << EOF-782969c0 > /etc/systemd/system/first_boot_service.service +[Unit] +Description=Initial setup callback +Wants=network-online.target +After=network-online.target + +[Service] +ExecStart=/bin/bash /root/first_boot_script.sh +Type=oneshot +ExecStartPost=/usr/bin/systemctl disable first_boot_service + +[Install] +WantedBy=multi-user.target +EOF-782969c0 + cat << EOF-76fe21d9 > /root/first_boot_script.sh +if [ -x /usr/bin/curl ]; then + /usr/bin/curl -o /dev/null --noproxy \* -H 'Content-Type: text/plain' --data @/root/install.post.log --silent 'http://foreman.example.com/unattended/built' +elif [ -x /usr/bin/wget ]; then + /usr/bin/wget -q -O /dev/null --no-proxy --method POST --header 'Content-Type: text/plain' --body-file=/root/install.post.log 'http://foreman.example.com/unattended/built' +else + wget -q -O /dev/null --header 'Content-Type: text/plain' 'http://foreman.example.com/unattended/built' +fi +EOF-76fe21d9 + + systemctl enable first_boot_service + +chmod +x /root/first_boot_script.sh + + touch /tmp/foreman_built chvt 1 @@ -179,16 +208,7 @@ cp -vf /tmp/*.pre.*.log /mnt/sysimage/root/ %post --erroronfail --log=/root/install-callhome.post.log -if test -f /tmp/foreman_built; then - echo "calling home: build is done!" - if [ -x /usr/bin/curl ]; then - /usr/bin/curl -o /dev/null --noproxy \* -H 'Content-Type: text/plain' --data @/root/install.post.log --silent 'http://foreman.example.com/unattended/built' - elif [ -x /usr/bin/wget ]; then - /usr/bin/wget -q -O /dev/null --no-proxy --method POST --header 'Content-Type: text/plain' --body-file=/root/install.post.log 'http://foreman.example.com/unattended/built' - else - wget -q -O /dev/null --header 'Content-Type: text/plain' 'http://foreman.example.com/unattended/built' - fi -else +if ! test -f /tmp/foreman_built; then echo "calling home: build failed!" if [ -x /usr/bin/curl ]; then /usr/bin/curl -o /dev/null --noproxy \* -H 'Content-Type: text/plain' --data @/root/install.post.log --silent 'http://foreman.example.com/unattended/failed' diff --git a/test/unit/foreman/renderer/snapshots/ProvisioningTemplate/provision/Kickstart_default.host6dhcp.snap.txt b/test/unit/foreman/renderer/snapshots/ProvisioningTemplate/provision/Kickstart_default.host6dhcp.snap.txt index d1ae06cc0a2..25600bbcd92 100644 --- a/test/unit/foreman/renderer/snapshots/ProvisioningTemplate/provision/Kickstart_default.host6dhcp.snap.txt +++ b/test/unit/foreman/renderer/snapshots/ProvisioningTemplate/provision/Kickstart_default.host6dhcp.snap.txt @@ -164,6 +164,35 @@ systemctl enable ansible-callback + cat << EOF-782969c0 > /etc/systemd/system/first_boot_service.service +[Unit] +Description=Initial setup callback +Wants=network-online.target +After=network-online.target + +[Service] +ExecStart=/bin/bash /root/first_boot_script.sh +Type=oneshot +ExecStartPost=/usr/bin/systemctl disable first_boot_service + +[Install] +WantedBy=multi-user.target +EOF-782969c0 + cat << EOF-76fe21d9 > /root/first_boot_script.sh +if [ -x /usr/bin/curl ]; then + /usr/bin/curl -o /dev/null --noproxy \* -H 'Content-Type: text/plain' --data @/root/install.post.log --silent 'http://foreman.example.com/unattended/built' +elif [ -x /usr/bin/wget ]; then + /usr/bin/wget -q -O /dev/null --no-proxy --method POST --header 'Content-Type: text/plain' --body-file=/root/install.post.log 'http://foreman.example.com/unattended/built' +else + wget -q -O /dev/null --header 'Content-Type: text/plain' 'http://foreman.example.com/unattended/built' +fi +EOF-76fe21d9 + + systemctl enable first_boot_service + +chmod +x /root/first_boot_script.sh + + touch /tmp/foreman_built chvt 1 @@ -179,16 +208,7 @@ cp -vf /tmp/*.pre.*.log /mnt/sysimage/root/ %post --erroronfail --log=/root/install-callhome.post.log -if test -f /tmp/foreman_built; then - echo "calling home: build is done!" - if [ -x /usr/bin/curl ]; then - /usr/bin/curl -o /dev/null --noproxy \* -H 'Content-Type: text/plain' --data @/root/install.post.log --silent 'http://foreman.example.com/unattended/built' - elif [ -x /usr/bin/wget ]; then - /usr/bin/wget -q -O /dev/null --no-proxy --method POST --header 'Content-Type: text/plain' --body-file=/root/install.post.log 'http://foreman.example.com/unattended/built' - else - wget -q -O /dev/null --header 'Content-Type: text/plain' 'http://foreman.example.com/unattended/built' - fi -else +if ! test -f /tmp/foreman_built; then echo "calling home: build failed!" if [ -x /usr/bin/curl ]; then /usr/bin/curl -o /dev/null --noproxy \* -H 'Content-Type: text/plain' --data @/root/install.post.log --silent 'http://foreman.example.com/unattended/failed' diff --git a/test/unit/foreman/renderer/snapshots/ProvisioningTemplate/provision/Kickstart_default.host6static.snap.txt b/test/unit/foreman/renderer/snapshots/ProvisioningTemplate/provision/Kickstart_default.host6static.snap.txt index 5b812a31206..4c92670f93b 100644 --- a/test/unit/foreman/renderer/snapshots/ProvisioningTemplate/provision/Kickstart_default.host6static.snap.txt +++ b/test/unit/foreman/renderer/snapshots/ProvisioningTemplate/provision/Kickstart_default.host6static.snap.txt @@ -164,6 +164,35 @@ systemctl enable ansible-callback + cat << EOF-782969c0 > /etc/systemd/system/first_boot_service.service +[Unit] +Description=Initial setup callback +Wants=network-online.target +After=network-online.target + +[Service] +ExecStart=/bin/bash /root/first_boot_script.sh +Type=oneshot +ExecStartPost=/usr/bin/systemctl disable first_boot_service + +[Install] +WantedBy=multi-user.target +EOF-782969c0 + cat << EOF-76fe21d9 > /root/first_boot_script.sh +if [ -x /usr/bin/curl ]; then + /usr/bin/curl -o /dev/null --noproxy \* -H 'Content-Type: text/plain' --data @/root/install.post.log --silent 'http://foreman.example.com/unattended/built' +elif [ -x /usr/bin/wget ]; then + /usr/bin/wget -q -O /dev/null --no-proxy --method POST --header 'Content-Type: text/plain' --body-file=/root/install.post.log 'http://foreman.example.com/unattended/built' +else + wget -q -O /dev/null --header 'Content-Type: text/plain' 'http://foreman.example.com/unattended/built' +fi +EOF-76fe21d9 + + systemctl enable first_boot_service + +chmod +x /root/first_boot_script.sh + + touch /tmp/foreman_built chvt 1 @@ -179,16 +208,7 @@ cp -vf /tmp/*.pre.*.log /mnt/sysimage/root/ %post --erroronfail --log=/root/install-callhome.post.log -if test -f /tmp/foreman_built; then - echo "calling home: build is done!" - if [ -x /usr/bin/curl ]; then - /usr/bin/curl -o /dev/null --noproxy \* -H 'Content-Type: text/plain' --data @/root/install.post.log --silent 'http://foreman.example.com/unattended/built' - elif [ -x /usr/bin/wget ]; then - /usr/bin/wget -q -O /dev/null --no-proxy --method POST --header 'Content-Type: text/plain' --body-file=/root/install.post.log 'http://foreman.example.com/unattended/built' - else - wget -q -O /dev/null --header 'Content-Type: text/plain' 'http://foreman.example.com/unattended/built' - fi -else +if ! test -f /tmp/foreman_built; then echo "calling home: build failed!" if [ -x /usr/bin/curl ]; then /usr/bin/curl -o /dev/null --noproxy \* -H 'Content-Type: text/plain' --data @/root/install.post.log --silent 'http://foreman.example.com/unattended/failed' diff --git a/test/unit/foreman/renderer/snapshots/ProvisioningTemplate/provision/Kickstart_default.rhel9_dhcp.snap.txt b/test/unit/foreman/renderer/snapshots/ProvisioningTemplate/provision/Kickstart_default.rhel9_dhcp.snap.txt index afcc93123d0..3fc03693337 100644 --- a/test/unit/foreman/renderer/snapshots/ProvisioningTemplate/provision/Kickstart_default.rhel9_dhcp.snap.txt +++ b/test/unit/foreman/renderer/snapshots/ProvisioningTemplate/provision/Kickstart_default.rhel9_dhcp.snap.txt @@ -157,6 +157,35 @@ systemctl enable ansible-callback + cat << EOF-782969c0 > /etc/systemd/system/first_boot_service.service +[Unit] +Description=Initial setup callback +Wants=network-online.target +After=network-online.target + +[Service] +ExecStart=/bin/bash /root/first_boot_script.sh +Type=oneshot +ExecStartPost=/usr/bin/systemctl disable first_boot_service + +[Install] +WantedBy=multi-user.target +EOF-782969c0 + cat << EOF-76fe21d9 > /root/first_boot_script.sh +if [ -x /usr/bin/curl ]; then + /usr/bin/curl -o /dev/null --noproxy \* -H 'Content-Type: text/plain' --data @/root/install.post.log --silent 'http://foreman.example.com/unattended/built' +elif [ -x /usr/bin/wget ]; then + /usr/bin/wget -q -O /dev/null --no-proxy --method POST --header 'Content-Type: text/plain' --body-file=/root/install.post.log 'http://foreman.example.com/unattended/built' +else + wget -q -O /dev/null --header 'Content-Type: text/plain' 'http://foreman.example.com/unattended/built' +fi +EOF-76fe21d9 + + systemctl enable first_boot_service + +chmod +x /root/first_boot_script.sh + + touch /tmp/foreman_built chvt 1 @@ -172,16 +201,7 @@ cp -vf /tmp/*.pre.*.log /mnt/sysimage/root/ %post --erroronfail --log=/root/install-callhome.post.log -if test -f /tmp/foreman_built; then - echo "calling home: build is done!" - if [ -x /usr/bin/curl ]; then - /usr/bin/curl -o /dev/null --noproxy \* -H 'Content-Type: text/plain' --data @/root/install.post.log --silent 'http://foreman.example.com/unattended/built' - elif [ -x /usr/bin/wget ]; then - /usr/bin/wget -q -O /dev/null --no-proxy --method POST --header 'Content-Type: text/plain' --body-file=/root/install.post.log 'http://foreman.example.com/unattended/built' - else - wget -q -O /dev/null --header 'Content-Type: text/plain' 'http://foreman.example.com/unattended/built' - fi -else +if ! test -f /tmp/foreman_built; then echo "calling home: build failed!" if [ -x /usr/bin/curl ]; then /usr/bin/curl -o /dev/null --noproxy \* -H 'Content-Type: text/plain' --data @/root/install.post.log --silent 'http://foreman.example.com/unattended/failed'