#!/bin/bash
#source="/drives/x/sync/onedrive/iSystems Consulting e.K/iSystems Support - SAP/Customers/+++Internal/Support/Proxmox/pSetup.sh";
#source="/drives/x/iSystems Consulting e.K/iSystems Support - SAP/Customers/+++Internal/Support/Proxmox/pSetup.sh";
#destin="root@100.76.48.116:/mnt/files/iso/etc/pSetup.sh"
#scp "$source" "$destin"
#alias pSetupGet='wget -qN - https://files.jezz.systems/etc/pSetup.sh' && alias pSetup='bash pSetup.sh' && clear && echo "use 'pSetupGet' and 'pSetup'"
pSet1() {
 clear
 local variable="This is a variable"
 cat <<EOF
This is a block of text.
It will include any command substitution, like: $(date)
And will also substitute variables, such as: $variable
EOF
}
pSet2() {
 clear
 local variable="This is a variable"
 cat <<'EOF'
This is a block of text.
It will NOT include any command substitution, like: $(date)
And will also NOT substitute variables, such as: $variable
EOF
}
pSet3() {
 echo -e "\nYes or No question.\n"
 while true; do
  read -p "Do you want to continue (y/n)?" yn
  case $yn in
  [Yy]*) break;;
  [Nn]*) exit;;
  *) echo "Please answer with y or n";;
  esac
 done
 echo "Ok. Let us continue here."
}
pSetSshKeys() {
 cat > /root/.ssh/authorized_keys <<'EOF'
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDClquILDs6oqokrkNS4WjKt3mh0rBuXM6VOpjKT5WV3cqiogZ8AP7tHQAIYjEPdkqDi9i7nSLEHsYV8t+Lc7W5A5DBeiSG27Fhf5H/RVbXY1TMmoMpnqAHbFVRiOY1rv9gp7j9Vu7uOYSKnVQnH7dra1N4HdBaGo/uuM3mPZCaOgqLl3RBATb0dU8mTW/eznrb69rYK3gw9U1/u0v6SopPLLBMkYQSx/jadr/L7gAIRa9yu+5sngt4jewAsqC4puU7xunjJndKGnWseYcyOzmYub2p5ce7Gia/j1RbPOF3++vwpiZAfi4clny+Ra8fwlgb9TLU+CS3bVBlBUIlfZjd klaus@Lenovo-P310 
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCz2BbQyhA75M+goDLoQeQqhqQkyoYduweOxxndza8dPhCoWIF2tZFie0SPae8TFOspQ0OMHrwxCNyWsUomSxYmRi7u24+gAcV19/ZN3USlGObJ1tscx1QIucUJ2iikNuAo8pu5PpHvRBvqQ13ZZvRXidLTRK60UkQMOPhCviNIRLn9kh5iOI6NxAbaiojPaMdyr5SS0ExUX0PBXpdFcYeLXfBNA4RMyNBC3vWGalEMcbTvQ+KtMY55oSg+69+jhGPccuY2MmwNdP1aFpBxhSuyIu/wa/lD//zHSraY0QgxuTFzw1oTWlvXApeFNT3WJydrpc1TnEvJ6EZiMooDhjet klaus@X349m 
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDIEJTbMPJbwO4mrllHoshZSEz3TSqkVlAI0d/N1+Jxrwt3E3z98w9kMMc7XkINtN9THBTkmXi2MJorABzLtk6wiDivTfBHTp27BaGkeBYfa9XM6c6I4LSYouiTG3TcGRhd0imtQnTvosGXYJOerrlVcZlBpOz9XEcmjD4Fgfy3n/jRJHkWGgt07f8P+SBEIkeDIsf8DJQ9Bm5Ap04A0JKlJ7NenmBieQNJ0ZKCrfN5L2AdQ1fONBpiet0WnSGqUZnbL7MonwMhLdFusSEbj3eSGOmPxWM9cl9DX2KRqxDwWZfcumBomX01nxyelx9mIPgsFJDRCl43NN+TTUumG/E7 root@dcdus-hcc03
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDiCpHdqyjOlGLAjEpYqhH+Hdrd71e6gRxJN3h1DWgubK0ygP2oltEaO5isFnsw31K4oQJly86XaxiWpBDGYuDawiUTWS4HpLMBJROqiUo3sGGis6/1hxJdsA5aBo99mnVedqLWSOzaGf3gEBMMpaUlI6IlHrQYbAB8IEd8AklqGb8eOv/0eGqPdBzTbcWQF93O/2RDux09aMfDcNaCT3i0pVGKE9eG4n/KTdp7FkwRwEPIhCwc3+Y8KX7B4PzIGlGIQ+wLUG94ebTtItgV2C65g/iXSM6Njg8nBs+whlO+zxpU4i0wy4KWDdt9GfMJedLgfLClLR9K0I3dSheT339H steffen
ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAQEAyh9JmipuyW5kk4LsvtxD5aiwYXQYdWAXMgKGJcOHm5XGP4R62nwjvCPS0JuXMQRyvayy9EjKfnZ4BzF0zacDMNwOgZDubMxy0bHt0XKyO1lpKVQJBWBUeAZtzfMceo/NYPX/WC6FlBFI9p5NIsTCU4BkTaLJt3si7z865hkxxzBvv4KpebyWbdCqRcGbohwbgwZQvmWZSiwfBnlfR0vQWleZVDv8HIHrfKxnuYYzeO0LSNcDn4flknVNZhB3ClDjXAZBpqpjST3nvoUOdtvBzEYSutZ9TiEBzXhuHmHKLrwlpX5s448xXsECXDBuK7Tn5W/z6y0cX0z6BtBz1gyrWQ== michael
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC4EhIIhIf0hyGjDOQMTVWYdcUHqrklNKVX5ldGEg7OJ0SuwWJbZJeAcqgkGVAh7GRchgHC3RrIurITcOQO6Tdpj8Fy7K48oN8AlMd3yAACchuDeXY8ADSSd4mfcsRjdoepif8JMoVATE2fRvyrqHD+KYwppv+zcvb+Dp6kCxDuuwx/3gsUiBlOUQRcQAeK51OQvdxAicxewS95qYFoqVfMNm04zf436XNEyWHo2Fpn/DGzn3m/onBSu5zjcG4xc2LA3yBFmrr0Ba2+1Z0MmZRiCo7JEbK4AjGW68+L8s0h4wyrIh/o0g8NWacFq4pJBtzUh3w+XSJCEP104lOvDMM3 samuel
EOF
}
pSetBullseye() {
 cp /etc/apt/sources.list /etc/apt/sources.list.bak && cat <<EOF > /etc/apt/sources.list
deb http://ftp.de.debian.org/debian bullseye main contrib
deb http://ftp.de.debian.org/debian bullseye-updates main contrib
deb http://security.debian.org bullseye-security main contrib
EOF
 rm /etc/apt/sources.list.d/pve-* > /dev/null 2>&1
 rm /etc/apt/sources.list.d/pbs-* > /dev/null 2>&1
 cat << EOF > /etc/apt/sources.list.d/pve-no-subscription.list
deb http://download.proxmox.com/debian/pve bullseye pve-no-subscription
deb http://download.proxmox.com/debian/pbs bullseye pbs-no-subscription
deb https://pkgs.tailscale.com/stable/debian bullseye main
EOF
}
pSetBookworm() {
 cp /etc/apt/sources.list /etc/apt/sources.list.bak && cat <<EOF > /etc/apt/sources.list
deb http://ftp.debian.org/debian bookworm main contrib
deb http://ftp.debian.org/debian bookworm-updates main contrib
deb http://security.debian.org/debian-security bookworm-security main contrib
EOF
 rm /etc/apt/sources.list.d/pve-* > /dev/null 2>&1
 rm /etc/apt/sources.list.d/pbs-* > /dev/null 2>&1
 cat << EOF > /etc/apt/sources.list.d/pve-no-subscription.list
deb http://download.proxmox.com/debian/pve bookworm pve-no-subscription
deb http://download.proxmox.com/debian/pbs bookworm pbs-no-subscription
deb https://pkgs.tailscale.com/stable/debian bookworm main
EOF
}
pSetRepos() {
#if ! grep -q 'PRETTY_NAME="Debian GNU/Linux 11 (bullseye)"' /etc/os-release; then
# echo "Not Debian GNU/Linux 11 (bullseye). Exiting."
# return 1
#fi
 if  grep -q 'PRETTY_NAME="Debian GNU/Linux 11 (bullseye)"' /etc/os-release; then
  echo "Debian GNU/Linux 11 (bullseye). Setting Repos."
  pSetBullseye
  return 1
 fi
#if ! grep -q 'PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"' /etc/os-release; then
# echo "Not Debian GNU/Linux 12 (bookworm). Exiting."
# return 1
#fi
 if  grep -q 'PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"' /etc/os-release; then
  echo "Debian GNU/Linux 12 (bookworm). Setting Repos."
  pSetBookworm
  return 1
 fi
}
pSetUpdates() {
 apt update -y
 apt dist-upgrade -y
 apt install -y gnupg2
 apt auto-clean -y
 apt autoremove -y
}
pSetPackages() {
 packages=(
  at
  chrony
  curl
  cloud-guest-utils
  ethtool
  fio
  git
  iftop
  ifupdown2
  iotop
  jq
  lshw
  lm-sensors
  mdadm
  net-tools
  nfs-kernel-server
  parted
  proxmox-backup-server
  pve-zsync
  screen
  sshfs
  sudo
  unzip
  whiptail
  zfs-initramfs
  zfs-zed
  zfsutils
  zip
  #ipmitool
  #libsnmp-dev
  #snmpd
  #fail2ban
  #libsasl2-modules
  #mailutils
  #postfix-pcre
 )
 for package in "${packages[@]}"; do
   apt install -y "$package"
 done
 systemctl restart chrony && systemctl enable chrony
 pSetRepos
 apt update; apt dist-upgrade -y; apt auto-clean -y; apt autoremove -y;
}
pSetScreen() {
 cat << 'EOF' > ~/.screenrc
startup_message off
vbell off
defscrollback 10000
hardstatus alwayslastline
hardstatus string '%{= kG}[ %{G}%H %{g}][%= %{= kw}%?%-Lw%?%{r}(%{W}%n*%f%t%?(%u)%?%{r})%{w}%?%+Lw%?%?%= %{g}][%{B} %m-%d %{W}%c %{g}]'
termcapinfo xterm* ti@:te@
EOF
 echo "Logout and back in again to have proper screenrc / screen -dRR"
 echo "open cluster and go to node > updates > upgrades > confirm y"
}
pSetTime() {
 apt purge chrony -y > /dev/null 2>&1
 dpkg-reconfigure tzdata
 if ! dpkg -l | grep -qw "chrony"; then
  apt-get install -y chrony
 fi
 cat << EOF > /etc/chrony/chrony.conf
pool 0.debian.pool.ntp.org iburst maxsources 4 minpoll 6 maxpoll 10
pool 1.debian.pool.ntp.org iburst maxsources 4 minpoll 6 maxpoll 10
pool 2.debian.pool.ntp.org iburst maxsources 4 minpoll 6 maxpoll 10
pool 3.debian.pool.ntp.org iburst maxsources 4 minpoll 6 maxpoll 10
makestep 0.1 3
rtcsync
EOF
 systemctl restart chrony && systemctl enable chrony
 if systemctl is-active --quiet chrony; then
  echo "Chrony is active and running."
  if dpkg -l | grep -qw systemd-timesyncd; then
   echo "Removing systemd-timesyncd..."
   apt-get purge -y systemd-timesyncd
  else
   echo "systemd-timesyncd is not installed. Skipping removal..."
  fi
 else
  echo "Error: Chrony failed to start. Please investigate."
  return
 fi
 sleep 3; chronyc sources -v; sleep 3; chronyc sourcestats -v;
 echo '------------------------------'
 echo "The current date and time is: $(date)"
 echo '------------------------------'
}
pSetNag() {
 apt update -y
 echo "DPkg::Post-Invoke { \"dpkg -V proxmox-widget-toolkit | grep -q '/proxmoxlib\.js$'; if [ \$? -eq 1 ]; then { echo 'Removing subscription nag from UI...'; sed -i '/data.status/{s/\!//;s/Active/NoMoreNagging/}' /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js; }; fi\"; };" > /etc/apt/apt.conf.d/no-nag-script;
 apt-get --reinstall install proxmox-widget-toolkit
 sed -i.bak "s/data.status !== 'Active'/false/g" /usr/share/javascript/proxmox-widget-toolkit/proxmoxlib.js
 systemctl restart pveproxy.service
}
pSetTailscale() {
 if ! dpkg -l | grep -qw "tailscale"; then
  #curl -fsSL https://pkgs.tailscale.com/stable/debian/bullseye.noarmor.gpg | tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null
  #curl -fsSL https://pkgs.tailscale.com/stable/debian/bullseye.tailscale-keyring.list | tee /etc/apt/sources.list.d/tailscale.list
  wget https://pkgs.tailscale.com/stable/debian/bullseye.gpg
  apt-key add bullseye.gpg
  rm bullseye.gpg
  apt update -y
  apt install -y tailscale
 else 
  echo "tailscale is already installed. Skipping..." 
 fi
 read -p "Enter hostname (example: hostname-partner-customer): " tailscale_hostname
 read -p "Enter routes (example: 192.168.0.0/24,192.168.1.0/24): " tailscale_routes
 read -s -p "Enter decryption password for authkey (Hint: I think I spider): " tailscale_password
 #echo 'tskey-XYZ' | openssl enc -aes-256-cbc -md sha512 -a -pbkdf2 -iter 100000 -salt -pass pass:$tailscale_password
 encrypted_authkey="U2FsdGVkX1/ivWcFiL9K3g8BHVfQextwCgbRl8ORASHpbO6GC8f1GFjbqKyc0zGI"
 authkey=$(echo "$encrypted_authkey" | openssl enc -aes-256-cbc -md sha512 -a -pbkdf2 -iter 100000 -salt -pass pass:"$tailscale_password" -d)
 if [ $? -ne 0 ]; then
   echo "Wrong Password. Exiting."
   return 1
 fi
 echo 
 echo 
 echo "Password OK. Enabling Tailscale Service."
 systemctl enable --now tailscaled
 echo 
 echo "Please copy/paste the following tailscale up command:"
 echo tailscale up --authkey="$authkey" --hostname="$tailscale_hostname" --advertise-routes="$tailscale_routes" --accept-routes=false --accept-dns=false
 echo
 echo "Once up, open admin panel and disable key expiry for host: $tailscale_hostname"
 echo 
 echo "Please remember to disable subnet routes at all times."
 echo
}
pSetPvekclean() {
if [ -f "/usr/local/sbin/pvekclean" ]; then
 echo "removing pvekclean now..."
 bash /usr/local/sbin/pvekclean -r
 echo "removing pvekclean done..."
fi
if [ ! -f "/usr/local/sbin/pvekclean" ]; then
 echo "Installing pvekclean now..."
 rm pvekclean*.sh*
 wget https://raw.githubusercontent.com/jordanhillis/pvekclean/master/pvekclean.sh
 chmod +x pvekclean.sh
 bash pvekclean.sh -i
 pvekclean -v
 rm pvekclean.sh && echo "Finished installing pvekclean"
else 
 echo "pvekclean is installed already..."
 echo ""
 pvekclean -v
 echo ""
fi
}
pSetOvftool() {
 wget https://files.jezz.systems/etc/VMware-ovftool-4.5.0-20459872-lin.x86_64.bundle
 chmod +x VM*bundle
 ./VM*bundle --extract ovftools
 mkdir -p /opt/vmware-ovftool
 mv ovftools/vmware-ovftool/* /opt/vmware-ovftool
 chmod +x /opt/vmware-ovftool/ovftool
 chmod +x /opt/vmware-ovftool/ovftool.bin
 alias ovftool=/opt/vmware-ovftool/ovftool
 rm ./VM*bundle
 rm -rf ovftools
}
pSetStorcli() {
 if ! command -v storcli &> /dev/null; then
  echo "storcli not found. Installing now..."
 #cd /tmp
  wget https://files.jezz.systems/etc/storcli.deb
  dpkg --install storcli.deb
  rm storcli.deb
  ln -s /opt/MegaRAID/storcli/storcli64 /usr/local/sbin/storcli
  if ! command -v storcli &> /dev/null; then
   echo "Error: Failed to install storcli."
   return 1
  else
   echo "storcli installed successfully!"
  fi
 else
  echo "storcli is already installed."
 fi
}
pSetSysctl() {
 conf="/etc/sysctl.conf"
 swappiness=0
 sysctl vm.swappiness=$swappiness && { swapoff -a; swapon -a; }
 cp "$conf" "$conf".bak
 cat <<EOF > "$conf"
vm.swappiness          = 0
net.ipv4.ip_forward    = 1
EOF
 sysctl -p "$conf"
 cat <<EOF > /etc/sysctl.d/disable-ipv6.conf
net.ipv6.conf.all.disable_ipv6     = 1
net.ipv6.conf.default.disable_ipv6 = 1
EOF
 sysctl -p /etc/sysctl.d/disable-ipv6.conf
 echo "done updating sysctl.conf"
}
pSetGrub() {
 echo -e "\nCurrent GRUB config\n"
 conf="/etc/default/grub";cat $conf | grep 'GRUB_CMDLINE_LINUX_DEFAULT';
 while true; do
  read -p "Do you want to modify the current GRUB config (y/n)?" yn
  case $yn in
  [Yy]*) break;;
  [Nn]*) exit;;
  *) echo "Please answer with y or n";;
  esac
 done
 cp $conf $conf.bak
 sed -i 's/GRUB_CMDLINE_LINUX_DEFAULT="quiet"/GRUB_CMDLINE_LINUX_DEFAULT="transparent_hugepage=never"/g' $conf
 #hpgen8#intel_iommu=off intremap=off#
 cat $conf | grep 'GRUB_CMDLINE_LINUX_DEFAULT';
 update-grub
 update-initramfs -u -k all
}
pSetModZfs() {
 echo -e "\nCurrent ZFS modprobe\n"
 conf="/etc/modprobe.d/zfs.conf";op="options zfs";touch $conf;cat $conf;
 while true; do
  read -p "Min Memory (example:  1): " minmem
  read -p "Max Memory (example: 32): " maxmem
  read -p "Min Thread (example:  2): " minthread
  read -p "Max Thread (example: 16): " maxthread
  read -p "Do you want to modify the current ZFS modprobe (y/n)?" yn
  case $yn in
  [Yy]*) break;;
  [Nn]*) exit;;
  *) echo "Please answer with y or n";;
  esac
 done
 cp $conf $conf.bak;
 zfs_arc_min=$minmem              ;((zfs_arc_min=$zfs_arc_min*1024*1024*1024))      ;zfs_arc_min="$op zfs_arc_min=$zfs_arc_min"                                                 ;echo $zfs_arc_min >$conf;
 zfs_arc_max=$maxmem              ;((zfs_arc_max=$zfs_arc_max*1024*1024*1024))      ;zfs_arc_max="$op zfs_arc_max=$zfs_arc_max"                                                 ;echo $zfs_arc_max>>$conf;
 zfs_dirty_data_max=2             ;((zfs_dirty_data_max=$zfs_dirty_data_max*1024*1024*1024)) ;zfs_dirty_data_max="$op zfs_dirty_data_max=$zfs_dirty_data_max"                   ;echo $zfs_dirty_data_max>>$conf;
 zfs_dirty_data_max_max=4         ;((zfs_dirty_data_max_max=$zfs_dirty_data_max_max*1024*1024*1024));zfs_dirty_data_max_max="$op zfs_dirty_data_max_max=$zfs_dirty_data_max_max";echo $zfs_dirty_data_max_max>>$conf;
 zfs_dirty_data_max_max_percent=25                                                                                                                                              ;echo "$op ""zfs_dirty_data_max_max_percent=""$zfs_dirty_data_max_max_percent">>$conf;
 zfs_dirty_data_max_percent=10                                                                                                                                                  ;echo "$op ""zfs_dirty_data_max_percent=""$zfs_dirty_data_max_percent">>$conf;
 zfs_dirty_data_sync_percent=20                                                                                                                                                 ;echo "$op ""zfs_dirty_data_sync_percent=""$zfs_dirty_data_sync_percent">>$conf;
 zfs_arc_dnode_limit=0                                                                                                                                                          ;echo "$op ""zfs_arc_dnode_limit=""$zfs_arc_dnode_limit">>$conf;
 zfs_arc_dnode_limit_percent=50                                                                                                                                                 ;echo "$op ""zfs_arc_dnode_limit_percent=""$zfs_arc_dnode_limit_percent">>$conf;
 zfs_arc_meta_limit=0                                                                                                                                                           ;echo "$op ""zfs_arc_meta_limit=""$zfs_arc_meta_limit">>$conf;
 zfs_arc_meta_limit_percent=95                                                                                                                                                  ;echo "$op ""zfs_arc_meta_limit_percent=""$zfs_arc_meta_limit_percent">>$conf;
 zfs_prefetch_disable=1                                                                                                                                                         ;echo "$op ""zfs_prefetch_disable=""$zfs_prefetch_disable">>$conf;
 zfs_nocacheflush=1                                                                                                                                                             ;echo "$op ""zfs_nocacheflush=""$zfs_nocacheflush">>$conf;
 zfs_vdev_sync_write_min_active=$minthread                                                                                                                                               ;echo "$op ""zfs_vdev_sync_write_min_active=""$zfs_vdev_sync_write_min_active">>$conf;
 zfs_vdev_sync_write_max_active=$maxthread                                                                                                                                              ;echo "$op ""zfs_vdev_sync_write_max_active=""$zfs_vdev_sync_write_max_active">>$conf;
 zfs_vdev_sync_read_min_active=$minthread                                                                                                                                                ;echo "$op ""zfs_vdev_sync_read_min_active=""$zfs_vdev_sync_read_min_active">>$conf;
 zfs_vdev_sync_read_max_active=$maxthread                                                                                                                                               ;echo "$op ""zfs_vdev_sync_read_max_active=""$zfs_vdev_sync_read_max_active">>$conf;
 zfs_vdev_async_read_min_active=$minthread                                                                                                                                               ;echo "$op ""zfs_vdev_async_read_min_active=""$zfs_vdev_async_read_min_active">>$conf;
 zfs_vdev_async_read_max_active=$maxthread                                                                                                                                              ;echo "$op ""zfs_vdev_async_read_max_active=""$zfs_vdev_async_read_max_active">>$conf;
 zfs_vdev_async_write_min_active=$minthread                                                                                                                                              ;echo "$op ""zfs_vdev_async_write_min_active=""$zfs_vdev_async_write_min_active">>$conf;
 zfs_vdev_async_write_max_active=$maxthread                                                                                                                                             ;echo "$op ""zfs_vdev_async_write_max_active=""$zfs_vdev_async_write_max_active">>$conf;
 zfs_txg_timeout=5                                                                                                                                                              ;echo "$op ""zfs_txg_timeout=""$zfs_txg_timeout">>$conf;
 update-grub
 update-initramfs -u -k all
}
pSetModNest() {
 [ -f /sys/module/kvm_intel/parameters/nested ] && ( 
  echo "options kvm-intel nested=Y" > /etc/modprobe.d/kvm-intel.conf && modprobe -r kvm_intel && echo "Nested virtualization enabled for INT after the next reboot."
 ) || ( 
  echo "options kvm-amd nested=1" > /etc/modprobe.d/kvm-amd.conf     && modprobe -r kvm_amd   && echo "Nested virtualization enabled for AMD after the next reboot."
 )
}
pNetCheck() {
 for net_dev in `find /sys/class/net/ -type l | sort`; do
  net=`basename $net_dev`
  speed=`ethtool $net | grep Speed | cut -d ':' -f 2 | tr -d " "`;
  link=`ethtool $net | grep "Link detected" | cut -d ':' -f 2 | tr -d " "`;
  if [[ "$link" != "yes" ]]; then
   echo "$net, offline"
  else
   if [[ "$speed" == "" ]]; then
    echo "$net, online, no speed"
   else
    echo "$net, online, $speed"
   fi
  fi
 done
}
pNetPrep() {
 echo "collecting network information..."
 tmp="/etc/network/interfaces.tmp"
 cat  > "$tmp" <<'EOF'
[1] This is a collection of information you can 
[2] use to build your /etc/network/interfaces. 
[3] Please replace these first 5 lines with config. 
[4] Everything after the placeholder 'INTERFACES_END' 
[5] will be deleted for you during the next steps.
#INTERFACES_END
EOF
 cat >> "$tmp" <<'EOF'

# SPEED ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~

EOF
 pNetCheck >> "$tmp"
 echo ""   >> "$tmp"
 cat >> "$tmp" <<'EOF'

# CURRENT ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~

EOF
 cat /etc/network/interfaces >> "$tmp"
 cat >> "$tmp" <<'EOF'

# DCDUS, PVE011 ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~

EOF
 cat >> "$tmp" <<'EOF'
auto lo
iface lo inet loopback

auto eno1
iface eno1 inet manual

auto eno2
iface eno2 inet manual

auto eno3
iface eno3 inet manual

auto eno4
iface eno4 inet manual

auto ens4f0
iface ens4f0 inet manual

auto ens4f1
iface ens4f1 inet manual

auto bond0
iface bond0 inet manual
  bond-slaves ens4f0 eno1
  bond-miimon 100
  bond-mode active-backup
  bond-primary ens4f0

auto bond1
iface bond1 inet manual
  bond-slaves ens4f1 eno2
  bond-miimon 100
  bond-mode active-backup
  bond-primary ens4f1

auto vmbr0
iface vmbr0 inet manual
  bridge-ports bond0
  bridge-stp off
  bridge-fd 0
  bridge-vlan-aware yes
  bridge-vids 2-4094

auto vmbr1
iface vmbr1 inet manual
  bridge-ports bond1
  bridge-stp off
  bridge-fd 0
  bridge-vlan-aware yes
  bridge-vids 2-4094

auto vmbr99
iface vmbr99 inet manual
  bridge-ports none
  bridge-stp off
  bridge-fd 0

auto vlan100
iface vlan100 inet static
  address 172.28.100.11/24
  gateway 172.28.100.1
  vlan-raw-device bond0

auto vlan200
iface vlan200 inet static
  address 172.28.200.11/24
  vlan-raw-device bond1

EOF
 cat >> "$tmp" <<'EOF'

# HOTEL ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~

EOF
 cat >> "$tmp" <<'EOF'
auto lo
iface lo inet loopback

auto eno1
iface eno1 inet manual

auto eno2
iface eno2 inet manual

auto eno3
iface eno3 inet manual

auto eno4
iface eno4 inet manual

auto sfp1
iface sfp1 inet manual

auto sfp2
iface sfp2 inet manual

auto bond0
iface bond0 inet manual
 bond-slaves eno1 eno2
 bond-miimon 100
 bond-mode active-backup
 bond-primary eno1
#clusterAccess

auto bond1
iface bond1 inet manual
 bond-slaves eno3 sfp1
 bond-miimon 100
 bond-mode active-backup
 bond-primary sfp1
#cluster1

auto bond2
iface bond2 inet manual
 bond-slaves eno4 sfp2
 bond-miimon 100
 bond-mode active-backup
 bond-primary sfp2
#cluster2

auto vmbr0
iface vmbr0 inet static
 address 192.168.10.53/24
 gateway 192.168.10.1
 bridge-ports bond0
 bridge-stp off
 bridge-fd 0

auto vmbr1
iface vmbr1 inet static
 address 192.168.21.53/24
 bridge-ports bond1
 bridge-stp off
 bridge-fd 0
 bridge-vlan-aware yes
 bridge-vids 2-4094

auto vmbr2
iface vmbr2 inet static
 address 192.168.22.53/24
 bridge-ports bond2
 bridge-stp off
 bridge-fd 0
 bridge-vlan-aware yes
 bridge-vids 2-4094

auto vmbr3
iface vmbr3 inet manual
 bridge-ports none
 bridge-stp off
 bridge-fd 0

EOF
 cat >> "$tmp" <<'EOF'

# HETZNER ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~

EOF
 cat >> "$tmp" <<'EOF'
EOF
 cat >> "$tmp" <<'EOF'

# DHCP ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~

EOF
 cat >> "$tmp" <<'EOF'
EOF
 echo "done. please update $tmp accordingly."
}
pNetSet() {
 tmp="/etc/network/interfaces.tmp"
 conf="/etc/network/interfaces"
 sed -i '/^#INTERFACES_END/,$d' "$tmp" && cp "$conf" "$conf.bak" && cat "$tmp" > "$conf" && while true; do
 read -p "Applied the network config. Do you want to reboot now (y/n)?" yn
 case $yn in
 [Yy]*) break;;
 [Nn]*) exit;;
 *) echo "Please answer with y or n";;
 esac
done
reboot
}
pStorcliHelp() {
 clear
 cat <<'EOF'
# STORCLI
. storcli show   
. storcli /c0 show  
. storcli /c0 /e134 show     
. storcli /c0 /e134 /sall show     
. storcli /c0 /e134 /s8-13 show    
. storcli /c0 /fall delete      
. storcli /c0 /e134 /s8-13 set good force
. storcli /c0 /e134 /s8-13 set jbod force
EOF
}
pStorcliSn() {
 pSetStorcli
 echo "Fetching controller information..."
 echo "-------------------------------------------"
 storcli show all
 echo "-------------------------------------------"
 read -p "Please specify controller number (e.g., 0): " CONTROLLER_N
 if ! [[ $CONTROLLER_N =~ ^[0-9]+$ ]]; then
  echo "Please provide valid numbers for the disk range."
  return 1
 fi
 echo "Fetching disk information..."
 echo "-------------------------------------------"
 storcli /c$CONTROLLER_N show all
 echo "-------------------------------------------"
 read -p "Please specify the starting disk (e.g., 8): " START_N
 read -p "Please specify the ending disk (e.g., 13): " END_N
 if ! [[ $START_N =~ ^[0-9]+$ ]] || ! [[ $END_N =~ ^[0-9]+$ ]]; then
  echo "Please provide valid numbers for the disk range."
  return 1
 fi
 echo "Fetching serial numbers for disks in the range $START_N-$END_N..."
 DISK_SNS=($(storcli /c0 /eall /s$START_N-$END_N show all | egrep 'Device attributes|SN = ' | grep SN | sed 's/.*SN = //'));
 for ((i=0; i<${#DISK_SNS[@]}; i++)); do
  SN=${DISK_SNS[$i]}
  N=$(($START_N + $i))
  VAR_NAME="SN$(printf "%02d" $N)"
  eval $VAR_NAME=$SN
  echo "$VAR_NAME=$SN"
 done
}
pSetupLinks() {
 clear
 cat <<'EOF'
# LINKS
- https://github.com/Tontonjo/proxmox_toolbox
- https://tteck.github.io/Proxmox
- https://schaal-it.com/script-to-install-proxmox-5-x-and-6-x-on-a-dedicated-hetzner-server
- https://docs.linuxmuster.net/de/latest/installation/proxmox/index.html#bereitstellen-des-proxmox-hosts
- https://github.com/Corsinvest/awesome-proxmox-ve
- https://github.com/extremeshok/xshok-proxmox
- https://gist.github.com/mrpeardotnet/e6bc57ed899c948ba53b3193a202eb2c
- https://www.hungred.com/how-to/server/list-of-useful-proxmox-command
- https://gist.github.com/mrpeardotnet/6bdc4b504f43ce57fa7eaee96d376edf#file-pve-host-backup-md
- https://github.com/DerDanilo/proxmox-stuff
- https://cheatography.com/the-iceman-blog/cheat-sheets/zfs-command-line-reference
- https://www.dlford.io/memory-tuning-proxmox-zfs
- https://lars.timmann.de/wiki/index.php/ZFS_on_Linux
- https://www.thegeekdiary.com/shell-script-to-find-network-interface-link-status-and-speed-centos-rhel
- https://askubuntu.com/questions/988095/how-to-prevent-an-unconnected-iscsi-disk-to-slow-down-my-pc-boot
- https://library.netapp.com/ecmdocs/ECMLP2439710/html/GUID-3DF20F02-AF33-499C-88FB-0BBBE252731D.html
EOF
}
pSetupCheck() {
 clear
 cat <<'EOF'
# CHECK
[ ] Host  > HardwareRaid1,XFS,32GB,hdsize=24GB,swapsize=8GB
[ ] Set   > passwd,SshKeys,Sysctl,Grub,ModZfs,ModNest
[ ] Set   > RemoveDefaultDatastores,RootExpand
[ ] Set   > Updates,Time,Nag,Ovftool,Storcli,Pvekclean
[ ] Net   > hostname,hosts,interfaces,reboot
[ ] Set   > Disks,Zfs,Network
[ ] Set   > Webif,Defaults,Email
[ ] Set   > Groups,Users,Pools,Permissions
[ ] Store > Dir/Nfs,name=pve,path=/mnt/ssd,HardwareRaid
[ ] Store > Zfs,pool=zfs,Raidz1/Mirror
[ ] Store > Pbs,name=pbs,path=/zfs/pbs
[ ] Store > Nfs,name=ISO,Disabled
[ ] Back  > Daily,All,Test,Review
[ ] ...   > ...
[ ] ...   > ...
[ ] ...   > ...
[ ] Set   > Backup,Cleanup,Reboot
EOF
}
pSetupMenu() {
 echo '# MENU'
 local funcs
 local choice
 local count=0
 local column_count=1
 funcs=($(grep -oE '^[a-zA-Z_]+[a-zA-Z_0-9]*\(\)' "$0" | awk -F'(' '{ print $1 }'));
 for (( i=0; i<${#funcs[@]}; i++ )); do
  printf "%3d|%-20s" $((i+1)) ${funcs[$i]};
  count=$((count+1)) 
  if [[ $count -eq $column_count ]]; then
   echo
   count=0
  fi
 done
 if [[ $count -ne 0 ]]; then
  echo
 fi
 read -p "Enter your choice (1-${#funcs[@]}): " choice
 if [[ $choice -ge 1 && $choice -le ${#funcs[@]} ]]; then
  ${funcs[$((choice-1))]}
 else
  echo "Invalid choice"
 fi
}
clear
pSetupCheck
pSetupMenu

