К сожалению, при использовании "VM Customization Specifications" при развертывании ОС Debian скрипты "open-vm-toos" не могут корректно сконфигурировать некоторые параметры для данной системы.
Чтобы решить эту проблему, применим скрипт, который возьмет на себя функционал, не корректно работающий в самих тулзах.
Выполним следующие шаги для настройки "VM Customization Specifications":
1. Подготавливаем шаблон ОС Debian с установкой необходимого ПО, которое уже должно быть в комплекте с новыми хостами.
2. Обязательно устанавливаем "open-vm-tools" и проверяем, что служба "vmtoolsd" находится в автозапуске:
sudo apt-get install open-vm-tools
sudo systemctl enable vmtoolsd && sudo systemctl start vmtoolsd
3. Включаем поддержку скриптов для кастомизации:
sudo vmware-toolbox-cmd config set deployPkg enable-custom-scripts true
Для проверки текущего состояния параметра выполните:
sudo vmware-toolbox-cmd config get deployPkg enable-custom-scripts
4. Далее настраиваем "VM Customization Specifications" на vCenter Server. При настройке указываем: тип ОС - Linux, правило формирования имени хоста, часовой пояс, TCP/IP настройки и добавляем следующий скрипт:
#!/bin/bash
# Функция для преобразования маски подсети в префикс CIDR
mask2cidr() {
local mask=$1
local n=0
IFS=.
for byte in $mask; do
case $byte in
255) n=$((n+8));;
254) n=$((n+7));;
252) n=$((n+6));;
248) n=$((n+5));;
240) n=$((n+4));;
224) n=$((n+3));;
192) n=$((n+2));;
128) n=$((n+1));;
0);;
*) echo 24; return 1;;
esac
done
echo $n
}
# Функция определения метода управления сетью с приоритетом: NM -> SystemD -> Ifupdown
get_network_manager() {
local interface=$1
# 1. Проверяем NetworkManager в первую очередь
if command -v nmcli >/dev/null 2>&1; then
# Проверяем, управляется ли интерфейс через NetworkManager
if nmcli -t -f DEVICE device 2>/dev/null | grep -q "^${interface}$"; then
echo "NetworkManager"
return
fi
# Проверяем, активен ли NetworkManager как служба
if systemctl is-active NetworkManager >/dev/null 2>&1; then
echo "NetworkManager"
return
fi
# Проверяем, есть ли соединение NetworkManager для этого интерфейса
if nmcli -t -f NAME,DEVICE connection show 2>/dev/null | grep -q ":${interface}$"; then
echo "NetworkManager"
return
fi
fi
# 2. Проверяем systemd-networkd
if systemctl is-active systemd-networkd >/dev/null 2>&1 && \
systemctl is-active systemd-resolved >/dev/null 2>&1; then
echo "SystemD"
return
fi
# 3. Проверяем ifupdown (традиционный метод Debian)
if [ -f "/etc/network/interfaces" ]; then
# Проверяем, упоминается ли интерфейс в конфигурации
if grep -q -E "^(auto|allow-hotplug|iface|mapping).*${interface}" /etc/network/interfaces; then
echo "Ifupdown"
return
fi
# Проверяем наличие конфигов в interfaces.d
if [ -d "/etc/network/interfaces.d" ]; then
for config in /etc/network/interfaces.d/*; do
if [ -f "$config" ] && grep -q "${interface}" "$config"; then
echo "Ifupdown"
return
fi
done
fi
fi
# Проверяем, активна ли служба networking (ifupdown)
if systemctl is-active networking >/dev/null 2>&1; then
echo "Ifupdown"
return
fi
# 4. Если ничего не найдено, проверяем по наличию служб
if systemctl is-enabled NetworkManager >/dev/null 2>&1; then
echo "NetworkManager"
elif systemctl is-enabled systemd-networkd >/dev/null 2>&1; then
echo "SystemD"
elif systemctl is-enabled networking >/dev/null 2>&1; then
echo "Ifupdown"
else
# Если ничего не определено, используем ifupdown как запасной вариант
echo "Ifupdown"
fi
}
# Функция настройки NetworkManager
configure_networkmanager() {
local interface=$1
local bootproto=$2
local ipaddr=$3
local netmask=$4
local gateway=$5
local dns_servers=$6
local domain=$7
# Удаляем существующее соединение для этого интерфейса
nmcli connection delete "$interface" 2>/dev/null || true
nmcli connection delete "Wired connection 1" 2>/dev/null || true
nmcli connection delete "System ${interface}" 2>/dev/null || true
# Создаем новое соединение
if [ "$bootproto" = "static" ]; then
local prefix_length=$(mask2cidr "$netmask")
nmcli con add type ethernet con-name "$interface" ifname "$interface" ipv4.method manual \
ipv4.addresses "${ipaddr}/${prefix_length}" \
ipv4.gateway "$gateway" \
ipv4.dns "$dns_servers" \
ipv4.dns-search "$domain" \
autoconnect yes
else
nmcli con add type ethernet con-name "$interface" ifname "$interface" \
ipv4.method auto autoconnect yes
fi
# Активируем соединение
nmcli con up "$interface"
}
# Функция настройки SystemD networkd
configure_systemd() {
local interface=$1
local bootproto=$2
local ipaddr=$3
local netmask=$4
local gateway=$5
local dns_servers=$6
local domain=$7
local dns_from_dhcp=$8
# Убедимся, что служба активна
systemctl enable systemd-networkd 2>/dev/null || true
systemctl start systemd-networkd 2>/dev/null || true
# Очищаем каталог /etc/systemd/network
rm -rf /etc/systemd/network/*
# Создаем базовую конфигурацию для loopback-интерфейса
mkdir -p /etc/systemd/network
cat > /etc/systemd/network/00-loopback.network <<EOF
[Match]
Name=lo
[Network]
Address=127.0.0.1/8
Address=::1/128
EOF
# Создаем конфигурацию для основного интерфейса
CONFIG_FILE="/etc/systemd/network/10-${interface}.network"
if [ "$bootproto" = "static" ]; then
if [ -z "$ipaddr" ] || [ -z "$netmask" ]; then
echo "Ошибка: для статической настройки нужны IPADDR и NETMASK"
exit 1
fi
prefix_length=$(mask2cidr "$netmask")
if [ -z "$prefix_length" ]; then
prefix_length=24
fi
# Создаем конфиг для статического IP
cat > "$CONFIG_FILE" <<EOF
[Match]
Name=$interface
[Network]
Address=$ipaddr/$prefix_length
EOF
if [ -n "$gateway" ]; then
echo "Gateway=$gateway" >> "$CONFIG_FILE"
fi
# Добавляем DNS серверы
if [ -n "$dns_servers" ]; then
for dns in $dns_servers; do
echo "DNS=$dns" >> "$CONFIG_FILE"
done
fi
else
# Создаем конфиг для DHCP
cat > "$CONFIG_FILE" <<EOF
[Match]
Name=$interface
[Network]
DHCP=ipv4
[DHCPv4]
UseDomains=true
EOF
# Настраиваем использование DNS
if [ "$dns_from_dhcp" = "yes" ]; then
echo "UseDNS=yes" >> "$CONFIG_FILE"
else
echo "UseDNS=no" >> "$CONFIG_FILE"
if [ -n "$dns_servers" ]; then
for dns in $dns_servers; do
echo "DNS=$dns" >> "$CONFIG_FILE"
done
fi
fi
fi
# Настраиваем systemd-resolved если нужно
if [ -n "$dns_servers" ] || [ -n "$domain" ]; then
mkdir -p /etc/systemd/resolved.conf.d
cat > /etc/systemd/resolved.conf.d/10-${interface}.conf <<EOF
[Resolve]
EOF
if [ -n "$dns_servers" ]; then
echo "DNS=$dns_servers" >> /etc/systemd/resolved.conf.d/10-${interface}.conf
fi
if [ -n "$domain" ]; then
echo "Domains=$domain" >> /etc/systemd/resolved.conf.d/10-${interface}.conf
fi
systemctl enable systemd-resolved 2>/dev/null || true
systemctl start systemd-resolved 2>/dev/null || true
# Создаем симлинк для resolv.conf
ln -sf /run/systemd/resolve/stub-resolv.conf /etc/resolv.conf 2>/dev/null || true
fi
systemctl restart systemd-networkd
if systemctl is-active systemd-resolved >/dev/null 2>&1; then
systemctl restart systemd-resolved
fi
}
# Функция настройки Ifupdown (/etc/network/interfaces)
configure_ifupdown() {
local interface=$1
local bootproto=$2
local ipaddr=$3
local netmask=$4
local gateway=$5
local dns_servers=$6
local domain=$7
echo "Configuring interface $interface using ifupdown" >&2
# Создаем базовый файл interfaces если его нет
if [ ! -f /etc/network/interfaces ]; then
mkdir -p /etc/network
cat > /etc/network/interfaces <<EOF
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).
source /etc/network/interfaces.d/*
# The loopback network interface
auto lo
iface lo inet loopback
EOF
fi
# Удаляем ВСЮ конфигурацию для этого интерфейса
# Создаем временный файл без конфигурации текущего интерфейса
tmpfile=$(mktemp)
in_block=0
while IFS= read -r line; do
# Проверяем, начинается ли новый блок интерфейса
if [[ "$line" =~ ^(auto|allow-hotplug|iface)[[:space:]]+$interface([[:space:]]|$) ]]; then
in_block=1
continue
fi
# Если мы внутри блока и встречаем начало другого блока, выходим из блока
if [[ $in_block -eq 1 && "$line" =~ ^(auto|allow-hotplug|iface)[[:space:]]+ ]]; then
in_block=0
fi
# Если мы не внутри блока удаляемого интерфейса, сохраняем строку
if [[ $in_block -eq 0 ]]; then
echo "$line" >> "$tmpfile"
fi
done < /etc/network/interfaces
# Копируем обратно и удаляем временный файл
mv "$tmpfile" /etc/network/interfaces
chmod 644 /etc/network/interfaces
# Удаляем возможные повторяющиеся пустые строки
sed -i '/^$/N; /^\n$/D' /etc/network/interfaces
sed -i -e :a -e '/^\n*$/{$d;N;ba' -e '}' /etc/network/interfaces
# Добавляем новую конфигурацию
{
echo ""
echo "auto $interface"
if [ "$bootproto" = "static" ]; then
echo "iface $interface inet static"
echo " address $ipaddr"
echo " netmask $netmask"
[ -n "$gateway" ] && echo " gateway $gateway"
[ -n "$dns_servers" ] && echo " dns-nameservers $dns_servers"
[ -n "$domain" ] && echo " dns-search $domain"
else
echo "iface $interface inet dhcp"
fi
} >> /etc/network/interfaces
# Настраиваем DNS через resolvconf если установлен
if command -v resolvconf >/dev/null 2>&1; then
# Создаем временный файл для resolvconf
TMP_RESOLV="/tmp/resolv.conf.${interface}"
echo "# Generated by network configuration script" > "$TMP_RESOLV"
if [ -n "$domain" ]; then
echo "domain $domain" >> "$TMP_RESOLV"
echo "search $domain" >> "$TMP_RESOLV"
fi
if [ -n "$dns_servers" ]; then
for dns in $dns_servers; do
echo "nameserver $dns" >> "$TMP_RESOLV"
done
fi
# Обновляем resolvconf
resolvconf -a "${interface}" < "$TMP_RESOLV" 2>/dev/null || true
rm -f "$TMP_RESOLV"
else
# Прямая настройка /etc/resolv.conf
if [ -n "$dns_servers" ] || [ -n "$domain" ]; then
echo "# Generated by network configuration script" > /etc/resolv.conf
if [ -n "$domain" ]; then
echo "domain $domain" >> /etc/resolv.conf
echo "search $domain" >> /etc/resolv.conf
fi
if [ -n "$dns_servers" ]; then
for dns in $dns_servers; do
echo "nameserver $dns" >> /etc/resolv.conf
done
fi
fi
fi
# Перезапускаем сетевую службу
if systemctl is-active networking >/dev/null 2>&1; then
systemctl restart networking
else
# Старый метод перезапуска сети
ifdown "$interface" 2>/dev/null || true
ifup "$interface" 2>/dev/null || true
fi
}
# --- Функция очистки логов и временных файлов ---
clean_system() {
# Очистка логов (с сохранением структуры каталогов)
find /var/log -type f -name "*.log" -exec truncate -s 0 {} \; 2>/dev/null || true
find /var/log -type f -name "*.gz" -delete 2>/dev/null || true
find /var/log -type f -name "*.old" -delete 2>/dev/null || true
find /var/log -type f -name "lastlog" -exec rm -f {} \; 2>/dev/null || true
# Очистка временных файлов
rm -rf /tmp/* 2>/dev/null || true
rm -rf /var/tmp/* 2>/dev/null || true
# Очистка истории команд и пользовательских данных
for user_home in /home/*; do
if [[ -d "$user_home" ]]; then
user=$(basename "$user_home")
# Очистка bash_history и других историй
truncate -s 0 "$user_home/.bash_history" 2>/dev/null || true
# Очистка кэшей приложений
rm -rf "$user_home/.cache/*" 2>/dev/null || true
fi
done
# Очистка root
truncate -s 0 /root/.bash_history 2>/dev/null || true
rm -rf /root/.cache/* 2>/dev/null || true
# Удаление случайных seed-файлов
rm -f /var/lib/systemd/random-seed 2>/dev/null || true
}
# --- Функция удаления SSH host keys ---
reset_ssh_keys() {
rm -f /etc/ssh/ssh_host_* 2>/dev/null || true
# Регенерация ключей SSH-сервера
if command -v dpkg-reconfigure >/dev/null 2>&1; then
dpkg-reconfigure -f noninteractive openssh-server 2>/dev/null || true
fi
# Альтернативный способ для Debian
if [ -x /usr/sbin/sshd ]; then
/usr/sbin/sshd-keygen -A 2>/dev/null || true
fi
}
# ============================================================
# Основная логика скрипта
# ============================================================
if [ "$1" = "precustomization" ]; then
# Выполняем очистку системы
clean_system
# Проверяем и создаем /etc/network/interfaces
if [ ! -f /etc/network/interfaces ]; then
echo "Creating /etc/network/interfaces file"
mkdir -p /etc/network
cat > /etc/network/interfaces <<EOF
# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).
source /etc/network/interfaces.d/*
# The loopback network interface
auto lo
iface lo inet loopback
EOF
fi
# Проверяем и создаем директорию /etc/sysconfig/network-scripts если нужно
if [ ! -d "/etc/sysconfig/network-scripts" ]; then
mkdir -p /etc/sysconfig/network-scripts 2>/dev/null || true
fi
# Этап предварительной настройки
VMCUST_DIR=$(ls -d /var/run/.vmware-imgcust* 2>/dev/null | head -n 1)
if [ -n "$VMCUST_DIR" ]; then
CUST_CFG_PATH="$VMCUST_DIR/cust.cfg"
if [ -f "$CUST_CFG_PATH" ]; then
cp "$CUST_CFG_PATH" "/root/cust.cfg"
fi
fi
elif [ "$1" = "postcustomization" ]; then
# Этап пост-настройки
reset_ssh_keys
if [ ! -f "/root/cust.cfg" ]; then
echo "Ошибка: файл конфигурации /root/cust.cfg не найден"
exit 1
fi
CFG_FILE="/root/cust.cfg"
# Парсим параметры конфигурации
BOOTPROTO=$(awk -F' = ' '/^BOOTPROTO/ {line=$2} END{print tolower(line)}' "$CFG_FILE")
IPADDR=$(awk -F' = ' '/^IPADDR/ {line=$2} END{print line}' "$CFG_FILE")
NETMASK=$(awk -F' = ' '/^NETMASK/ {line=$2} END{print line}' "$CFG_FILE")
GATEWAY=$(awk -F' = ' '/^GATEWAY/ {line=$2} END{print line}' "$CFG_FILE")
HOSTNAME=$(awk -F' = ' '/^HOSTNAME/ {line=$2} END{print line}' "$CFG_FILE")
DOMAIN=$(awk -F' = ' '/^DOMAINNAME/ {line=$2} END{print line}' "$CFG_FILE")
MACADDR=$(awk -F' = ' '/^MACADDR/ {line=$2} END{print tolower(line)}' "$CFG_FILE")
DNS_SERVERS=$(awk -F' = ' '/^NAMESERVER\|[0-9]/ {print $2}' "$CFG_FILE" | tr '\n' ' ' | sed 's/ $//')
DNS_FROM_DHCP=$(awk -F' = ' '/^DNSFROMDHCP/ {line=$2} END{print tolower(line)}' "$CFG_FILE")
TIMEZONE=$(awk -F' = ' '/^TIMEZONE/ {line=$2} END{print line}' "$CFG_FILE")
UTC=$(awk -F' = ' '/^UTC/ {line=$2} END{print tolower(line)}' "$CFG_FILE")
# Определяем сетевой интерфейс
INTERFACE=$(ip -o link | awk -v mac="$MACADDR" 'tolower($0) ~ mac {gsub(":", "", $2); print $2}')
if [ -z "$INTERFACE" ]; then
INTERFACE=$(ip route | awk '/default/ {print $5; exit}')
fi
if [ -z "$INTERFACE" ]; then
# Последняя попытка: берем первый Ethernet интерфейс
INTERFACE=$(ip -o link | awk -F': ' '$2 !~ /^lo|virbr|docker|veth/ {print $2; exit}' | sed 's/@.*//')
fi
if [ -z "$INTERFACE" ]; then
echo "Ошибка: не удалось определить сетевой интерфейс"
exit 1
fi
# Определяем метод управления сетью
NET_MGR=$(get_network_manager "$INTERFACE")
echo "Определен метод управления сетью: $NET_MGR для интерфейса $INTERFACE"
case "$NET_MGR" in
"NetworkManager")
configure_networkmanager "$INTERFACE" "$BOOTPROTO" "$IPADDR" "$NETMASK" \
"$GATEWAY" "$DNS_SERVERS" "$DOMAIN"
;;
"SystemD")
configure_systemd "$INTERFACE" "$BOOTPROTO" "$IPADDR" "$NETMASK" \
"$GATEWAY" "$DNS_SERVERS" "$DOMAIN" "$DNS_FROM_DHCP"
;;
"Ifupdown")
configure_ifupdown "$INTERFACE" "$BOOTPROTO" "$IPADDR" "$NETMASK" \
"$GATEWAY" "$DNS_SERVERS" "$DOMAIN"
;;
*)
echo "Неизвестный метод управления сетью, используем ifupdown как запасной вариант"
configure_ifupdown "$INTERFACE" "$BOOTPROTO" "$IPADDR" "$NETMASK" \
"$GATEWAY" "$DNS_SERVERS" "$DOMAIN"
;;
esac
# Общие настройки
hostnamectl set-hostname "$HOSTNAME" 2>/dev/null || echo "$HOSTNAME" > /etc/hostname
sed -i "/127\.0\.1\.1/d" /etc/hosts
echo "127.0.1.1 $HOSTNAME.$DOMAIN $HOSTNAME" >> /etc/hosts
# Настройка часового пояса
if [ -n "$TIMEZONE" ]; then
timedatectl set-timezone "$TIMEZONE" 2>/dev/null || true
# Альтернативный способ для Debian
if [ -f "/usr/share/zoneinfo/$TIMEZONE" ]; then
cp "/usr/share/zoneinfo/$TIMEZONE" /etc/localtime 2>/dev/null || true
echo "$TIMEZONE" > /etc/timezone 2>/dev/null || true
fi
fi
# Настройка формата времени BIOS (UTC или локальное)
if [ -n "$UTC" ]; then
if [ "$UTC" = "yes" ]; then
# Устанавливаем UTC время в BIOS
timedatectl set-local-rtc 0 2>/dev/null || true
else
# Устанавливаем локальное время в BIOS
timedatectl set-local-rtc 1 2>/dev/null || true
fi
fi
# Сохраняем конфигурацию
CONFIG_LOG="/root/vm-customization.log"
{
echo "=========================================="
echo "Настройка завершена: $(date)"
echo "=========================================="
echo "CONFIG_SOURCE=$CFG_FILE"
echo "BOOTPROTO=$BOOTPROTO"
echo "INTERFACE=$INTERFACE"
echo "NETWORK_MANAGER=$NET_MGR"
echo "HOSTNAME=$HOSTNAME"
echo "DOMAIN=$DOMAIN"
echo "TIMEZONE=$TIMEZONE"
echo "UTC=$UTC"
[ -n "$DNS_FROM_DHCP" ] && echo "DNS_FROM_DHCP=$DNS_FROM_DHCP"
[ -n "$DNS_SERVERS" ] && echo "DNS_SERVERS=\"$DNS_SERVERS\""
if [ "$BOOTPROTO" = "static" ]; then
echo "IP_ADDRESS=$IPADDR"
echo "NETMASK=$NETMASK"
[ -n "$GATEWAY" ] && echo "GATEWAY=$GATEWAY"
fi
} > "$CONFIG_LOG"
rm -f "/root/cust.cfg"
# Синхронизируем изменения на диск
sync
echo "Настройка завершена успешно. Метод управления сетью: $NET_MGR"
##############################################################################################
# МЕСТО ДЛЯ ДОПОЛНИТЕЛЬНОЙ НАСТРОЙКИ СИСТЕМЫ
# Здесь можно добавить команды для окончательной настройки машины:
# - Доустановка необходимого программного обеспечения
# - Настройка через Ansible или другие системы управления конфигурациями
# - Выполнение пользовательских скриптов
# - Настройка мониторинга, логирования и других сервисов
# Пример: установка базовых пакетов
# apt-get update && apt-get install -y curl wget net-tools
##############################################################################################
fi
Данный скрипт охватывает все возможные варианты настройки сети: IfUpDown, NetworkManager, Systemd-Networkd, как со статическим IP, так и с DHCP.
Комментариев нет:
Отправить комментарий