distcc propagator is a helper script to help propagate a configuration on hosts and clients in a distcc-enabled network ; its features are:
- compute -jN -lM values for each host and client
- propagate /root/.ssh/authorized_keys file on all clients
It makes use of a single /etc/distcc/cluster.conf file that specifies, for each client (whether it will act as a distcc host or not), the number of local cores to use for compilation. It makes two passes on the clients file, first computing the total number of cores available, then propagating the config on all machines.
#!/bin/bash
# small helper script to ease adding participating hosts in a distcc network
#
# Author: JCZD <jczd@engrenage.ch>
# Date: 2021-12-04
#
# format of /etc/distcc/cluster.conf:
#
# n,hostname_or_ip
#
# one per line, where n is the numer of local cores to use for compilation
#
# TODO
# - fix the (slight) redundancy between /etc/distcc/{hosts,clients}
# - use a specific authorized_hosts? this adds complexity..
# - read the comments below for more
#
# Bugs/Limitations
# - does not support any sort of NAT
# - still requires quite a bit of manual file post-processing on each host
# -
NETMASK=24
total_cores=0
echo -e "#\n# cluster status\n#"
while read line
do
# TODO ignore lines starting with '#'
local_cores=`echo ${line} | cut -f 1 -d ','`
hostname=`echo ${line} | cut -f 2 -d ','`
# TODO check host is up and responding
# TODO test network connectivity, ie. with nmap ; port number should be set in /etc/distcc/cluster.conf
#ssh $hostname /usr/bin/distcc-config --get-hosts # TODO kills the script.. why?
# TODO check gcc version
echo "sharing ${local_cores} cores: ${hostname}"
let "total_cores=total_cores+local_cores"
done < /etc/distcc/cluster.conf
echo -e "\ndistcc cluster has ${total_cores} cores available total\n"
let "N=2*total_cores+1"
echo -e "\n#\n# pushing config...\n#"
while read line
do
local_cores=`echo ${line} | cut -f 1 -d ','`
hostname=`echo ${line} | cut -f 2 -d ','`
if [ $hostname != `hostname` ]
then
echo -n "remote: ${hostname}"
# the line below works once,, then script exits.. why?!? the point was to make sure reverse-connection works
#ssh $hostname ssh `hostname` echo "Hello from $hostname"
scp ~/.ssh/authorized_keys $hostname:.ssh >/dev/null
# TODO this is quite dirty security-wise ; also, some sort of authentication is required to already work at this stage
# TODO not good because it relies from a hosts file of an arbitrary host, not network-architecture-aware
scp ~/.ssh/authorized_keys $hostname:.ssh >/dev/null
scp /etc/hosts $hostname:/etc/ >/dev/null
rm /tmp/distcc-hosts
echo -n "DISTCCD_OPTS=\"\${DISTCCD_OPTS} --listen `grep ${hostname} /etc/hosts | tr -s ' ' | cut -f 1 -d ' ' | cut -f 1 -d ' '`" > /tmp/distccd.allow
while read line2
do
# TODO ignore lines starting with '#'
helper_cores=`echo ${line2} | cut -f 1 -d ','`
helper=`echo ${line2} | cut -f 2 -d ','`
if [[ $helper_cores -gt 0 ]]
then
if [ $helper != $hostname ]
then
echo ${helper} >> /tmp/distcc-hosts
echo -n " --allow "`grep ${helper} /etc/hosts | tr -s ' ' | cut -f 1 -d ' ' | cut -f 1 -d ' '`"/${NETMASK}" >> /tmp/distccd.allow
else
echo 127.0.0.1 >> /tmp/distcc-hosts
echo -n " --allow 127.0.0.1/${NETMASK}" >> /tmp/distccd.allow
fi
fi
done < /etc/distcc/cluster.conf
scp /tmp/distcc-hosts $hostname:/etc/distcc/hosts >/dev/null
# TODO merge with /etc/conf.d/distcc
echo "\"" >> /tmp/distccd.allow
scp /tmp/distccd.allow $hostname:/etc/conf.d/distccd.allow >/dev/null # see Note1
# alternative, if distccd is already running:
#scp /tmp/distccd.allow $hostname:/tmp/distccd.allow >/dev/null # see Note1
#ssh $hostname /usr/bin/distcc-config --set-hosts `cat /tmp/distccd.allow`
echo "FEATURES=\"distcc\"" > /tmp/distcc-propagator-makeopts
echo "MAKEOPTS=\"-j${N} -l${local_cores}\"" >> /tmp/distcc-propagator-makeopts
#cat /tmp/distcc-propagator-makeopts
# TODO merge with /etc/portage/make.conf
scp /tmp/distcc-propagator-makeopts $hostname:/etc/distcc/makeopts >/dev/null # see Note1
echo " :-)"
else
echo "local: ${hostname}"
echo "MAKEOPTS=\"-j${N} -l${local_cores}\"" > /etc/distcc/makeopts # see Note1
echo -n "DISTCCD_OPTS=\"\${DISTCCD_OPTS} --listen `grep ${hostname} /etc/hosts | tr -s ' ' | cut -f 1 -d ' ' | cut -f 1 -d ' '`" > /etc/conf.d/distccd.allow
while read line2
do
# TODO ignore lines starting with '#'
helper_cores=`echo ${line2} | cut -f 1 -d ','`
helper=`echo ${line2} | cut -f 2 -d ','`
if [[ $helper_cores -gt 0 ]]
then
if [ $helper != $hostname ]
then
echo ${helper} >> /etc/distcc/hosts
echo -n " --allow "`grep ${helper} /etc/hosts | tr -s ' ' | cut -f 1 -d ' ' | cut -f 1 -d ' '`"/${NETMASK}" >> /etc/conf.d/distccd.allow
else
echo 127.0.0.1 >> /etc/distcc/hosts
echo -n " --allow 127.0.0.1/${NETMASK}" >> /etc/conf.d/distccd.allow
fi
fi
done < /etc/distcc/cluster.conf
echo "\"" >> /etc/conf.d/distccd.allow
fi
done < /etc/distcc/cluster.conf
echo -e "\n\n#\n# Finalization: on every host, merge contents of /etc/distcc/makeopts /etc/portage/make.conf /etc/conf.d/distccd.allow /etc/conf.d/distccd"
# Note1:
# these should be used to set :
# MAKEOPTS in /etc/portage/make.conf
# DISTCC_OPTS in /etc/conf.d/distccd
# but I am trying to avoid too much parsing and replacing.. any suggestion?