install text %include /tmp/source.ks {{reboot}} lang en_US.UTF-8 keyboard us rootpw r00tme timezone --utc Etc/UTC firewall --disabled selinux --permissive # ignore unsupported hardware warning unsupported_hardware # SKIP CONFIGURING X skipx # NEVER ever place zerombr here, it breaks automated installation %include /tmp/bootloader.ks %include /tmp/partition.ks %include /tmp/post_partition.ks # This eliminates a security risk where an attacker # could SSH into Fuel Admin node before a user has an # opportunity to change the root password. services --disabled=sshd %packages --nobase @Core -firewalld -postfix -tuned %end # PREINSTALL SECTION # HERE ARE COMMANDS THAT WILL BE LAUNCHED BEFORE # INSTALLATION PROCESS ITSELF %pre #!/bin/sh # hard drives drives="" removable_drives="" for drv in `ls -1 /sys/block | grep "sd\|hd\|vd\|cciss"`; do if !(blkid | grep -q "${drv}.*Fuel"); then if (grep -q 0 /sys/block/${drv}/removable); then drives="${drives} ${drv}" else removable_drives="${removable_drives} ${drv}" fi fi done default_drive=`echo ${drives} ${removable_drives} | awk '{print $1}'` installdrive=${installdrive:-undefined} forceformat=${forceformat:-no} for I in $(cat /proc/cmdline); do case "$I" in *=*) if ! [[ "${I}" =~ "." ]]; then eval "$I"; fi ;; esac done set ${drives} ${removable_drives} numdrives=`echo $#` tgtdrive="${installdrive}" function confirm_format { check_drive="$1" local confirm_format="no" if [[ "$forceformat" == "yes" ]] ; then return 0 fi if parted -s /dev/$check_drive print &>/dev/null ; then echo echo "$check_drive drive contains partition table:" parted -s /dev/$check_drive print echo read -p "Are you sure you want to erase ALL data on disk $check_drive? (y/N)" confirm_format if [[ "$confirm_format" == "y" ]] || [[ "$confirm_format" == "Y" ]] || [[ "$forceformat" == "yes" ]]; then return 0 else return 1 fi else return 0 fi } format_confirmed="no" if [ $numdrives -lt 1 ]; then exec < /dev/tty3 > /dev/tty3 2>&1 chvt 3 clear echo echo '********************************************************************' echo '* E R R O R *' echo '* *' echo '* There is no suitable media available for installation. *' echo '* Please attach a drive and try again. *' echo '* *' echo '********************************************************************' echo read -p "Press Enter to shut down the system: " _ poweroff fi if [ ${numdrives} -gt 1 ] || [ `echo ${drives} | wc -w` -eq 0 ] ; then exec < /dev/tty3 > /dev/tty3 2>&1 chvt 3 while [ "${tgtdrive}" = "undefined" ]; do clear echo echo '********************************************************************************' echo '* W A R N I N G *' echo '* *' echo '* Which of the detected hard drives do you want to be used as *' echo '* the installation target? *' echo '* *' echo '********************************************************************************' echo echo "Possible choices" echo "Persistent drives: ${drives}" echo "Removable drives: ${removable_drives}" echo if [ `echo ${drives} | wc -w` -eq 1 ] ; then read -t 30 -p "Choose hard drive: " tgtdrive || tgtdrive=$default_drive else read -p "Choose hard drive: " tgtdrive fi match="no" for drive in ${drives[@]} ${removable_drives[@]}; do if [[ "$drive" == "$tgtdrive" ]] && match="yes" ; then if confirm_format $tgtdrive ; then format_confirmed="yes" break else tgtdrive="undefined" read -p "You may select another disk. Press Enter to continue." _ fi fi done if [[ "$match" == "no" ]]; then tgtdrive="undefined" read -p "Invalid choice. Press Enter to continue." _ fi done clear chvt 1 else tgtdrive=`echo ${drives} | sed -e "s/^\s*//" -e "s/\s*$//"` fi if [ "$format_confirmed" != "yes" ] ; then exec < /dev/tty3 > /dev/tty3 2>&1 chvt 3 if ! confirm_format $tgtdrive ; then clear echo echo '********************************************************************' echo '* E R R O R *' echo '* *' echo '* Disk $tgtdrive contains active partition(s). *' echo '* Installation cannot continue without confirmation. *' echo '* *' echo '********************************************************************' echo read -p "Press Enter to restart: " _ reboot fi chvt 1 fi # verify tgtdrive is at least 50GB tgtdrivesize=$(( $(cat "/sys/class/block/${tgtdrive}/size") / 2 / 1024 )) if [ $tgtdrivesize -lt 51200 ]; then exec < /dev/tty3 > /dev/tty3 2>&1 chvt 3 clear echo echo '********************************************************************' echo '* E R R O R *' echo '* *' echo '* Your disk is under 50GB in size. Installation cannot continue. *' echo '* Restart installation with a larger disk. *' echo '* *' echo '********************************************************************' echo read -p "Press Enter to restart: " _ reboot fi # paths in /dev have "/" instead of "!" for cciss devices tgtdrive=$(echo $tgtdrive | sed -e 's/!/\//') # source iso_volume_id=will_be_substituted_with_ISO_VOLUME_ID cdrom_device= if [ -e /proc/sys/dev/cdrom/info ]; then cdrom_device=$(cat /proc/sys/dev/cdrom/info | awk '/drive name:/{print $3}') fi if [ -e /dev/disk/by-label/${iso_volume_id} ]; then real_device=$(readlink -e /dev/disk/by-label/${iso_volume_id}) if [ "${real_device}" == "/dev/${cdrom_device}" ]; then echo "cdrom" > /tmp/source.ks else echo "harddrive --partition=LABEL=${iso_volume_id} --dir=/" > /tmp/source.ks fi else echo "cdrom" > /tmp/source.ks fi vgdisplay -c | cut -d':' -f1 | xargs vgremove -ff dd if=/dev/zero of=/dev/${tgtdrive} bs=10M count=10 sleep 3 hdparm -z /dev/${tgtdrive} parted -s /dev/${tgtdrive} mklabel gpt parted -a none -s /dev/${tgtdrive} unit MiB mkpart primary 0% 24 parted -s /dev/${tgtdrive} set 1 bios_grub on parted -a none -s /dev/${tgtdrive} unit MiB mkpart primary fat16 24 224 parted -s /dev/${tgtdrive} set 2 boot on parted -a none -s /dev/${tgtdrive} unit MiB mkpart primary 224 424 sleep 3 hdparm -z /dev/${tgtdrive} # partition # This adds support for the p seperator required for cciss devices if echo ${tgtdrive} | grep -q -e cciss ; then bootdev=${tgtdrive}p else bootdev=${tgtdrive} fi cat << EOF > /tmp/partition.ks part /boot --onpart=/dev/${bootdev}3 part /boot/efi --onpart=/dev/${bootdev}2 part pv.001 --ondisk=${tgtdrive} --size=25000 --grow part pv.002 --ondisk=${tgtdrive} --size=10000 volgroup os pv.001 volgroup docker pv.002 logvol swap --vgname=os --recommended --name=swap logvol / --vgname=os --size=10000 --name=root --fstype=ext4 logvol /var --vgname=os --grow --percent 40 --name=var --fstype=ext4 logvol /var/log --vgname=os --grow --percent 60 --name=varlog --fstype=ext4 EOF # bootloader echo "bootloader --driveorder=${tgtdrive} --append=' biosdevname=0 crashkernel=none'" > /tmp/bootloader.ks # Anaconda can not install grub 0.97 on disks which are >4T. # The reason is that grub does not support such large geometries # and it simply thinks that the cylinder number has negative value. # Here we just set geometry manually so that grub thinks that disk # size is equal to 1G. # 130 cylinders * (16065 * 512 = 8225280 bytes) = 1G echo "%post --nochroot --log=/mnt/sysimage/root/anaconda-post-partition.log" > /tmp/post_partition.ks echo "echo \"device (hd0) /dev/${tgtdrive}\" >> /tmp/grub.script" >> /tmp/post_partition.ks echo "echo \"geometry (hd0) 130 255 63\" >> /tmp/grub.script" >> /tmp/post_partition.ks echo "echo \"root (hd0,2)\" >> /tmp/grub.script" >> /tmp/post_partition.ks echo "echo \"install /grub/stage1 (hd0) /grub/stage2 p /grub/grub.conf\" >> /tmp/grub.script" >> /tmp/post_partition.ks echo "echo quit >> /tmp/grub.script" >> /tmp/post_partition.ks echo "cat /tmp/grub.script | chroot /mnt/sysimage /sbin/grub --no-floppy --batch" >> /tmp/post_partition.ks echo "%end" >> /tmp/post_partition.ks %end # POSTINSTALL SECTIONS # HERE ARE COMMANDS THAT WILL BE LAUNCHED JUST AFTER # INSTALLATION ITSELF COMPLETED # Parse /proc/cmdline and save for next steps %post --log=/root/anaconda-parse-cmdline.log #!/bin/bash set -x # Parse cmdline to alter keys which contains dot in their names # Such keys can't be used as variables in bash, # so every dot is replaced with double underscore. # Double underscore needed to avoid possible naming collisions. for item in $(cat /proc/cmdline); do if [[ "${item}" =~ '=' ]]; then key="${item%%=*}" value="${item#*=}" else key="${item}" value='yes' fi key="${key//\./__}" value="${value:-'yes'}" echo "${key}=${value}" >> /root/anaconda.cmdline.vars done source /root/anaconda.cmdline.vars if [[ ! -z $ifname ]]; then echo "adminif=$(udevadm info --query=property -p /sys/class/net/${ifname%%:*} | \ awk -F\= '$1 == "ID_NET_NAME_ONBOARD" {s=$2; exit}; $1 == "ID_NET_NAME_SLOT" {s=$2; exit}; $1 == "ID_NET_NAME_PATH" {s=$2; next}; END {print s}')" >> /root/anaconda.cmdline.vars fi # Add self entry to /etc/hosts ipaddr=$(echo $ip | cut -d: -f1) hostname=$(echo $ip | cut -d: -f5) # Use default hostname if missing from parameters [ -z "$hostname" ] && hostname="fuel.domain.tld" short=$(echo $hostname | cut -d. -f1) echo -e "${ipaddr} ${hostname} ${short}" >> /etc/hosts %end # Mount installation media in chroot %post --nochroot --log=/mnt/sysimage/root/anaconda-post-before-chroot.log #!/bin/bash set -x source "/mnt/sysimage/root/anaconda.cmdline.vars" SOURCE="/mnt/sysimage/tmp/source" mkdir -p "${SOURCE}" case "${repo}" in nfs:*) nfs_url="${repo#nfs:}" mount -t nfs "${nfs_url}" "${SOURCE}" ;; *) if [ -d "/mnt/source" ]; then mount -o bind "/mnt/source" "${SOURCE}" fi ;; esac # If not mounted, try to bind /run/install/repo since # anaconda shoud mount installation repo to that folder. if ! mountpoint -q "${SOURCE}"; then if [ -d '/run/install/repo' ] && mountpoint -q '/run/install/repo'; then mount -o bind '/run/install/repo' "${SOURCE}" fi fi # If still not mounted, try to mount from LABEL / UUID. # It was moved from next phase here to keep all mounting stuff # in one place. All other scripts should use SOURCE variable # for access to dist files. iso_volume_id=will_be_substituted_with_ISO_VOLUME_ID FS="/mnt/sysimage/tmp/fs" if ! mountpoint -q "${SOURCE}"; then if [ -e "/dev/disk/by-label/${iso_volume_id}" ]; then mount "/dev/disk/by-label/${iso_volume_id}" "${SOURCE}" fi fi # Sleep to capture full log sleep 1 %end %post --log=/root/anaconda-post-configure-repos.log #!/bin/bash set -x SOURCE=/tmp/source # this file is provided by fuel-openstack-metadata package OPENSTACK_VERSION=`rpm2cpio ${SOURCE}/mos-centos/Packages/fuel-openstack-metadata*.rpm | \ cpio -i --to-stdout ./etc/fuel_openstack_version 2>/dev/null` # build identifiers test -e ${SOURCE}/fuel_build_number && cp ${SOURCE}/fuel_build_number /etc/fuel_build_number test -e ${SOURCE}/fuel_build_id && cp ${SOURCE}/fuel_build_id /etc/fuel_build_id # Copy repos config test -e ${SOURCE}/default_deb_repos.yaml && cp ${SOURCE}/default_deb_repos.yaml /root/default_deb_repos.yaml # ---------------------- # UNPACKING REPOSITORIES # ---------------------- wwwdir="/var/www/nailgun" repodir="${wwwdir}/${OPENSTACK_VERSION}" # Copying Centos files mkdir -p ${repodir}/centos/x86_64 mkdir -p ${repodir}/mos-centos/x86_64 cp -r ${SOURCE}/images ${repodir}/centos/x86_64 cp -r ${SOURCE}/isolinux ${repodir}/centos/x86_64 cp -r ${SOURCE}/repodata ${repodir}/centos/x86_64 cp -r ${SOURCE}/Packages ${repodir}/centos/x86_64 cp -r ${SOURCE}/mos-centos/repodata ${repodir}/mos-centos/x86_64 cp -r ${SOURCE}/mos-centos/Packages ${repodir}/mos-centos/x86_64 cp -r ${SOURCE}/extra-repos ${repodir}/ cp ${SOURCE}/.treeinfo ${repodir}/centos/x86_64 # Copying Ubuntu files mkdir -p ${repodir}/ubuntu/x86_64/images cp -r ${SOURCE}/ubuntu/dists ${repodir}/ubuntu/x86_64 cp -r ${SOURCE}/ubuntu/pool ${repodir}/ubuntu/x86_64 # make links for backward compatibility ln -s ${repodir}/centos ${wwwdir}/centos ln -s ${repodir}/ubuntu ${wwwdir}/ubuntu #Make a symlink for mos-centos in /var/www/nailgun in iso/ks.template ln -s ${repodir}/mos-centos ${wwwdir}/mos-centos ln -s ${repodir}/extra-repos ${wwwdir}/extra-repos # Prepare local repository specification rm /etc/yum.repos.d/CentOS*.repo cp ${SOURCE}/extra-repos/extra.repo /etc/yum.repos.d/ cat > /etc/yum.repos.d/nailgun.repo << EOF [nailgun] name=Nailgun Local Repo baseurl=file:/var/www/nailgun/${OPENSTACK_VERSION}/centos/x86_64 gpgcheck=0 [mos] name=MOS Local Repo baseurl=file:/var/www/nailgun/${OPENSTACK_VERSION}/mos-centos/x86_64 gpgcheck=0 EOF %end %post --log=/root/anaconda-post-configure-sysconfig.log #!/bin/bash set -x source "/root/anaconda.cmdline.vars" SOURCE=/tmp/source # Prepare bootstrap_admin_node config mkdir -p /etc/fuel cat > /etc/fuel/bootstrap_admin_node.conf << EOF #Set to yes to run Fuel Setup #Set to no to accept default settings ADMIN_INTERFACE=${adminif} showmenu=${showmenu:-yes} wait_for_external_config=${wait_for_external_config:-no} EOF # Unmounting source umount -f ${SOURCE} rm -rf ${SOURCE} umount -f ${FS} || true rm -rf ${FS} %end %post --log=/root/anaconda-post-install-extrapackages.log #!/bin/bash set -x MASTER_NODE_EXTRA_PACKAGES="" source "/root/anaconda.cmdline.vars" if [ -n "${MASTER_NODE_EXTRA_PACKAGES}" ]; then for pkg in ${MASTER_NODE_EXTRA_PACKAGES}; do yum -y install ${pkg} done fi %end %post --log=/root/anaconda-post-configure-autologon.log #!/bin/bash set -x # Enable once root autologin for initial setup mkdir -p /etc/systemd/system/getty@tty1.service.d/ cat > /etc/systemd/system/getty@tty1.service.d/autologin.conf << 'EOF' [Service] ExecStart= ExecStart=-/sbin/agetty --autologin root --noclear %I 115200 linux EOF # Exec bootstrap_admin_node.sh if autologin enabled cat >> /root/.bashrc << 'EOF' if [[ "$(tty)" == "/dev/tty1" && -f /etc/systemd/system/getty@tty1.service.d/autologin.conf ]]; then rm -Rf "/etc/systemd/system/getty@tty1.service.d" /bin/systemctl daemon-reload yum makecache yum install -y fuel-setup if [ -x /usr/sbin/bootstrap_admin_node.sh ]; then exec /usr/sbin/bootstrap_admin_node.sh fi fi EOF %end %post --nochroot --log=/mnt/sysimage/root/anaconda-post-interface-settings.log #!/bin/bash set -x source "/mnt/sysimage/root/anaconda.cmdline.vars" if [[ ! -z $adminif ]]; then rm -f /mnt/sysimage/etc/sysconfig/network-scripts/ifcfg-${ifname%%:*} sed "s/${ifname%%:*}/${adminif}/g" \ /etc/sysconfig/network-scripts/ifcfg-${ifname%%:*} > \ /mnt/sysimage/etc/sysconfig/network-scripts/ifcfg-${adminif} fi %end