From d99fe2e480377b4b268248c8cfca746ac3fc34d4 Mon Sep 17 00:00:00 2001 From: bin456789 Date: Wed, 12 Jun 2024 22:40:22 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=20ipv4=20/=20ipv6=20?= =?UTF-8?q?=E5=88=86=E5=88=AB=E5=9C=A8=E4=B8=8D=E5=90=8C=E7=9A=84=E7=BD=91?= =?UTF-8?q?=E5=8D=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.en.md | 4 +- README.md | 4 +- alpine-network.sh | 148 ++++++++++++++------- debian.cfg | 4 +- reinstall.sh | 324 ++++++++++++++++++++++------------------------ trans.sh | 268 ++++++++++++++++++++++---------------- 6 files changed, 412 insertions(+), 340 deletions(-) diff --git a/README.en.md b/README.en.md index a57ca8f..ee0db79 100644 --- a/README.en.md +++ b/README.en.md @@ -32,7 +32,7 @@ Reinstall server with one-click [中文](README.md) | Alma | 8, 9 | 512 MB \* | 5 GB | | Rocky | 8, 9 | 512 MB \* | 5 GB | | Fedora | 39, 40 | 512 MB \* | 5 GB | -| openSUSE | 15.5, Tumbleweed (Rolling) | 512 MB \* | 5 GB | +| openSUSE | 15.5, 15.6, Tumbleweed (Rolling) | 512 MB \* | 5 GB | | Arch | Rolling | 512 MB | 5 GB | | Gentoo | Rolling | 512 MB | 5 GB | | Windows (DD) | Any | 512 MB | Depending on the image | @@ -142,9 +142,9 @@ bash reinstall.sh centos 7|9 (9 is stream version) rocky 8|9 fedora 39|40 debian 10|11|12 - opensuse 15.5|tumbleweed ubuntu 20.04|22.04|24.04 alpine 3.17|3.18|3.19|3.20 + opensuse 15.5|15.6|tumbleweed kali arch gentoo diff --git a/README.md b/README.md index 0c1f954..9fe9f34 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ | Alma | 8, 9 | 512 MB \* | 5 GB | | Rocky | 8, 9 | 512 MB \* | 5 GB | | Fedora | 39, 40 | 512 MB \* | 5 GB | -| openSUSE | 15.5, Tumbleweed (滚动) | 512 MB \* | 5 GB | +| openSUSE | 15.5, 15.6, Tumbleweed (滚动) | 512 MB \* | 5 GB | | Arch | 滚动 | 512 MB | 5 GB | | Gentoo | 滚动 | 512 MB | 5 GB | | Windows (DD) | 任何 | 512 MB | 取决于镜像 | @@ -143,9 +143,9 @@ bash reinstall.sh centos 7|9 (9 为 stream 版本) rocky 8|9 fedora 39|40 debian 10|11|12 - opensuse 15.5|tumbleweed ubuntu 20.04|22.04|24.04 alpine 3.17|3.18|3.19|3.20 + opensuse 15.5|15.6|tumbleweed kali arch gentoo diff --git a/alpine-network.sh b/alpine-network.sh index 58f3d66..5b494a8 100644 --- a/alpine-network.sh +++ b/alpine-network.sh @@ -9,16 +9,6 @@ ipv6_addr=$4 ipv6_gateway=$5 is_in_china=$6 -# 3.16-3.18 $device -# 3.19 $iface -# debian $iface -# shellcheck disable=SC2154 -if [ -n "$iface" ]; then - ethx="$iface" -else - ethx="$device" -fi - if $is_in_china; then ipv4_dns1='119.29.29.29' ipv4_dns2='223.5.5.5' @@ -31,16 +21,27 @@ else ipv6_dns2='2001:4860:4860::8888' fi +# 找到主网卡 +# debian 11 initrd 没有 xargs awk +# debian 12 initrd 没有 xargs +get_ethx() { + if false; then + ip -o link | grep "$mac_addr" | awk '{print $2}' | cut -d: -f1 + else + ip -o link | grep "$mac_addr" | cut -d' ' -f2 | cut -d: -f1 + fi +} + get_ipv4_gateway() { # debian 11 initrd 没有 xargs awk # debian 12 initrd 没有 xargs - ip -4 route show default | head -1 | cut -d ' ' -f3 + ip -4 route show default dev "$ethx" | head -1 | cut -d ' ' -f3 } get_ipv6_gateway() { # debian 11 initrd 没有 xargs awk # debian 12 initrd 没有 xargs - ip -6 route show default | head -1 | cut -d ' ' -f3 + ip -6 route show default dev "$ethx" | head -1 | cut -d ' ' -f3 } get_first_ipv4_addr() { @@ -87,24 +88,6 @@ is_have_ipv6() { is_have_ipv6_addr && is_have_ipv6_gateway } -# 开启 ethx -ip link set dev "$ethx" up - -# 等待slaac -# 有ipv6地址就跳过,不管是slaac或者dhcpv6 -# 因为会在trans里判断 -# 这里等待5秒就够了,因为之前尝试获取dhcp6也用了一段时间 -for i in $(seq 5 -1 0); do - is_have_ipv6 && break - echo "waiting slaac for ${i}s" - sleep 1 -done - -# 记录是否有动态地址 -# 由于还没设置静态ip,所以有条目表示有动态地址 -is_have_ipv4_addr && dhcpv4=true || dhcpv4=false -is_have_ipv6_addr && dhcpv6_or_slaac=true || dhcpv6_or_slaac=false - add_missing_ipv4_config() { if [ -n "$ipv4_addr" ] && [ -n "$ipv4_gateway" ]; then if ! is_have_ipv4_addr; then @@ -131,14 +114,6 @@ add_missing_ipv6_config() { fi } -# 设置静态地址,或者设置udhcpc无法设置的网关 -add_missing_ipv4_config -add_missing_ipv6_config - -# 检查 ipv4/ipv6 是否连接联网 -ipv4_has_internet=false -ipv6_has_internet=false - is_need_test_ipv4() { is_have_ipv4 && ! $ipv4_has_internet } @@ -182,6 +157,79 @@ flush_ipv6_config() { ip -6 route flush dev "$ethx" } +# dhcp v4 /v6 +# debian / kali +if [ -f /usr/share/debconf/confmodule ]; then + # shellcheck source=/dev/null + . /usr/share/debconf/confmodule + + # 开启 ethx + dhcpv4/v6 + ethx=$(get_ethx) + ip link set dev "$ethx" up + sleep 1 + db_progress STEP 1 + + # dhcpv4 + db_progress INFO netcfg/dhcp_progress + udhcpc -i "$ethx" -f -q -n || true + db_progress STEP 1 + + # slaac + dhcpv6 + db_progress INFO netcfg/slaac_wait_title + # https://salsa.debian.org/installer-team/netcfg/-/blob/master/autoconfig.c#L148 + cat </var/lib/netcfg/dhcp6c.conf +interface $ethx { + send ia-na 0; + request domain-name-servers; + request domain-name; + script "/lib/netcfg/print-dhcp6c-info"; +}; + +id-assoc na 0 { +}; +EOF + dhcp6c -c /var/lib/netcfg/dhcp6c.conf "$ethx" + sleep 10 + # kill-all-dhcp + kill -9 "$(cat /var/run/dhcp6c.pid)" + db_progress STEP 1 + + # 静态 + 检测网络提示 + db_subst netcfg/link_detect_progress interface "$ethx" + db_progress INFO netcfg/link_detect_progress +else + # alpine + ethx=$(get_ethx) + echo "$ethx" + ip link set dev "$ethx" up + sleep 1 + udhcpc -i "$ethx" -f -q -n || true + udhcpc6 -i "$ethx" -f -q -n || true +fi + +# 等待slaac +# 有ipv6地址就跳过,不管是slaac或者dhcpv6 +# 因为会在trans里判断 +# 这里等待5秒就够了,因为之前尝试获取dhcp6也用了一段时间 +for i in $(seq 5 -1 0); do + is_have_ipv6 && break + echo "waiting slaac for ${i}s" + sleep 1 +done + +# 记录是否有动态地址 +# 由于还没设置静态ip,所以有条目表示有动态地址 +is_have_ipv4_addr && dhcpv4=true || dhcpv4=false +is_have_ipv6_addr && dhcpv6_or_slaac=true || dhcpv6_or_slaac=false + +# 设置静态地址,或者设置udhcpc无法设置的网关 +add_missing_ipv4_config +add_missing_ipv6_config + +# 检查 ipv4/ipv6 是否连接联网 +ipv4_has_internet=false +ipv6_has_internet=false + test_internet # 处理云电脑 dhcp 获取的地址无法上网 @@ -242,14 +290,16 @@ if $ipv6_has_internet && ! grep ':' /etc/resolv.conf; then fi # 传参给 trans.start -$dhcpv4 && echo 1 >/dev/dhcpv4 || echo 0 >/dev/dhcpv4 -$should_disable_ra_slaac && echo 1 >/dev/should_disable_ra_slaac || echo 0 >/dev/should_disable_ra_slaac -$is_in_china && echo 1 >/dev/is_in_china || echo 0 >/dev/is_in_china -echo "$ethx" >/dev/ethx -echo "$mac_addr" >/dev/mac_addr -echo "$ipv4_addr" >/dev/ipv4_addr -echo "$ipv4_gateway" >/dev/ipv4_gateway -echo "$ipv6_addr" >/dev/ipv6_addr -echo "$ipv6_gateway" >/dev/ipv6_gateway -$ipv4_has_internet && echo 1 >/dev/ipv4_has_internet || echo 0 >/dev/ipv4_has_internet -$ipv6_has_internet && echo 1 >/dev/ipv6_has_internet || echo 0 >/dev/ipv6_has_internet +netconf="/dev/netconf/$ethx" +mkdir -p "$netconf" +$dhcpv4 && echo 1 >"$netconf/dhcpv4" || echo 0 >"$netconf/dhcpv4" +$should_disable_ra_slaac && echo 1 >"$netconf/should_disable_ra_slaac" || echo 0 >"$netconf/should_disable_ra_slaac" +$is_in_china && echo 1 >"$netconf/is_in_china" || echo 0 >"$netconf/is_in_china" +echo "$ethx" >"$netconf/ethx" +echo "$mac_addr" >"$netconf/mac_addr" +echo "$ipv4_addr" >"$netconf/ipv4_addr" +echo "$ipv4_gateway" >"$netconf/ipv4_gateway" +echo "$ipv6_addr" >"$netconf/ipv6_addr" +echo "$ipv6_gateway" >"$netconf/ipv6_gateway" +$ipv4_has_internet && echo 1 >"$netconf/ipv4_has_internet" || echo 0 >"$netconf/ipv4_has_internet" +$ipv6_has_internet && echo 1 >"$netconf/ipv6_has_internet" || echo 0 >"$netconf/ipv6_has_internet" diff --git a/debian.cfg b/debian.cfg index 5fe14f2..99c319f 100644 --- a/debian.cfg +++ b/debian.cfg @@ -148,9 +148,9 @@ d-i partman/early_command string true; \ ttys=$(sh /ttys.sh console=); \ debconf-set debian-installer/add-kernel-opts "$ttys"; \ - ethx=$(cat /dev/ethx); \ + eths=$(cd /dev/netconf/ && ls); \ - sh /can_use_cloud_kernel.sh "$xda" "$ethx" || debconf-set base-installer/kernel/image "$(debconf-get base-installer/kernel/image | sed 's/-cloud//')"; \ + sh /can_use_cloud_kernel.sh "$xda" $eths || debconf-set base-installer/kernel/image "$(debconf-get base-installer/kernel/image | sed 's/-cloud//')"; \ [ -d /sys/firmware/efi ] && debconf-set partman-auto/expert_recipe "$(debconf-get partman-auto/expert_recipe_efi)"; \ [ -d /sys/firmware/efi ] || debconf-set partman-auto/expert_recipe "$(debconf-get partman-auto/expert_recipe_bios)"; \ diff --git a/reinstall.sh b/reinstall.sh index 08f2e8d..cfb5e7a 100644 --- a/reinstall.sh +++ b/reinstall.sh @@ -36,9 +36,9 @@ Usage: $reinstall____ centos 7|9 rocky 8|9 fedora 39|40 debian 10|11|12 - opensuse 15.5|tumbleweed ubuntu 20.04|22.04|24.04 alpine 3.17|3.18|3.19|3.20 + opensuse 15.5|15.6|tumbleweed kali arch gentoo @@ -1109,7 +1109,7 @@ setos() { fi # debian/kali <=256M 必须使用云内核,否则不够内存 - if is_distro_like_debian && [ "$ram_size" -le 256 ]; then + if is_distro_like_debian && ! is_in_windows && [ "$ram_size" -le 256 ]; then exit_if_cant_use_cloud_kernel fi @@ -1120,21 +1120,6 @@ setos() { fi } -exit_if_cant_use_cloud_kernel() { - find_main_disk - collect_netconf - - for driver in $(get_disk_drivers); do - echo "using disk driver: $driver" - done - for driver in $(get_net_drivers); do - echo "using net driver: $driver" - done - if ! can_use_cloud_kernel; then - error_and_exit "Can't use cloud kernel. And not enough RAM to run normal kernel." - fi -} - is_distro_like_redhat() { if [ -n "$1" ]; then _distro=$1 @@ -1166,9 +1151,9 @@ verify_os_name() { 'rocky 8|9' \ 'fedora 39|40' \ 'debian 10|11|12' \ - 'opensuse 15.5|tumbleweed' \ 'ubuntu 20.04|22.04|24.04' \ 'alpine 3.17|3.18|3.19|3.20' \ + 'opensuse 15.5|15.6|tumbleweed' \ 'kali' \ 'arch' \ 'gentoo' \ @@ -1562,7 +1547,7 @@ find_main_disk() { fi } -# TODO: 多网卡 单网卡多IP +# TODO: 单网卡多IP collect_netconf() { if is_in_windows; then convert_net_str_to_array() { @@ -1578,12 +1563,22 @@ collect_netconf() { # 否 手动 0 0.0.0.0/0 19 192.168.1.1 # 否 手动 0 0.0.0.0/0 59 nekoray-tun - ids=" - $(netsh int ipv4 show route | grep --text -F '0.0.0.0/0' | awk '$6 ~ /\./ {print $5}') - $(netsh int ipv6 show route | grep --text -F '::/0' | awk '$6 ~ /:/ {print $5}') - " - ids=$(echo "$ids" | sort -u) - for id in $ids; do + + for v in 4 6; do + if [ "$v" = 4 ]; then + # 或者 route print + route=$(netsh int ipv4 show route | awk '$4 == "0.0.0.0/0"' | head -1 | del_cr) + else + route=$(netsh int ipv6 show route | awk '$4 == "::/0"' | head -1 | del_cr) + fi + + if [ -z "$route" ]; then + continue + fi + + id=$(awk '{print $5}' <<<"$route") + gateway=$(awk '{print $6}' <<<"$route") + config=$(wmic nicconfig where "InterfaceIndex='$id'" get MACAddress,IPAddress,IPSubnet,DefaultIPGateway /format:list | del_cr) # 排除 IP/子网/网关/MAC 为空的 if grep -q '=$' <<<"$config"; then @@ -1597,45 +1592,53 @@ collect_netconf() { # IPv4 # shellcheck disable=SC2154 - for ((i = 0; i < ${#ips[@]}; i++)); do - ip=${ips[i]} - subnet=${subnets[i]} - if [[ "$ip" = *.* ]]; then - cidr=$(ipcalc -b "$ip/$subnet" | grep Netmask: | awk '{print $NF}') - ipv4_addr="$ip/$cidr" - break - fi - done - - # IPv6 - ipv6_type_list=$(netsh interface ipv6 show address $id normal) - for ((i = 0; i < ${#ips[@]}; i++)); do - ip=${ips[i]} - cidr=${subnets[i]} - if [[ "$ip" = *:* ]]; then - ipv6_type=$(grep "$ip" <<<"$ipv6_type_list" | awk '{print $1}') - # Public 是 slaac - # 还有类型 Temporary,不过有 Temporary 肯定还有 Public,因此不用 - if [ "$ipv6_type" = Public ] || - [ "$ipv6_type" = Dhcp ] || - [ "$ipv6_type" = Manual ]; then - ipv6_addr="$ip/$cidr" + if [ "$v" = 4 ]; then + for ((i = 0; i < ${#ips[@]}; i++)); do + ip=${ips[i]} + subnet=${subnets[i]} + if [[ "$ip" = *.* ]]; then + cidr=$(ipcalc -b "$ip/$subnet" | grep Netmask: | awk '{print $NF}') + ipv4_addr="$ip/$cidr" + ipv4_gateway="$gateway" + ipv4_mac="$mac_addr" break fi - fi - done + done + fi + + # IPv6 + if [ "$v" = 6 ]; then + ipv6_type_list=$(netsh interface ipv6 show address $id normal) + for ((i = 0; i < ${#ips[@]}; i++)); do + ip=${ips[i]} + cidr=${subnets[i]} + if [[ "$ip" = *:* ]]; then + ipv6_type=$(grep "$ip" <<<"$ipv6_type_list" | awk '{print $1}') + # Public 是 slaac + # 还有类型 Temporary,不过有 Temporary 肯定还有 Public,因此不用 + if [ "$ipv6_type" = Public ] || + [ "$ipv6_type" = Dhcp ] || + [ "$ipv6_type" = Manual ]; then + ipv6_addr="$ip/$cidr" + ipv6_gateway="$gateway" + ipv6_mac="$mac_addr" + break + fi + fi + done + fi # 网关 # shellcheck disable=SC2154 - for gateway in "${gateways[@]}"; do - if [ -n "$ipv4_addr" ] && [[ "$gateway" = *.* ]]; then - ipv4_gateway="$gateway" - elif [ -n "$ipv6_addr" ] && [[ "$gateway" = *:* ]]; then - ipv6_gateway="$gateway" - fi - done - - break + if false; then + for gateway in "${gateways[@]}"; do + if [ -n "$ipv4_addr" ] && [[ "$gateway" = *.* ]]; then + ipv4_gateway="$gateway" + elif [ -n "$ipv6_addr" ] && [[ "$gateway" = *:* ]]; then + ipv6_gateway="$gateway" + fi + done + fi done else # linux @@ -1654,23 +1657,22 @@ collect_netconf() { for v in 4 6; do if ethx=$(ip -$v route show default | awk '$4=="dev"' | head -1 | awk '{print $5}' | grep .); then - mac_addr=$(ip link show dev $ethx | grep link/ether | head -1 | awk '{print $2}') - break - fi - done - - for v in 4 6; do - if ip -$v route show default | awk '$5=="'$ethx'"' | head -1 | grep -q .; then - eval ipv${v}_gateway="$(ip -$v route show default | awk '$5=="'$ethx'"' | head -1 | awk '{print $3}')" - eval ipv${v}_addr="$(ip -$v -o addr show scope global dev $ethx | head -1 | awk '{print $4}')" + if ip -$v route show default | awk '$5=="'$ethx'"' | head -1 | grep -q .; then + eval ipv${v}_ethx="$ethx" # can_use_cloud_kernel 要用 + eval ipv${v}_mac="$(ip link show dev $ethx | grep link/ether | head -1 | awk '{print $2}')" + eval ipv${v}_gateway="$(ip -$v route show default | awk '$5=="'$ethx'"' | head -1 | awk '{print $3}')" + eval ipv${v}_addr="$(ip -$v -o addr show scope global dev $ethx | head -1 | awk '{print $4}')" + fi fi done fi info "Network Info" - echo "MAC Address: $mac_addr" + echo "IPv4 MAC: $ipv4_mac" echo "IPv4 Address: $ipv4_addr" echo "IPv4 Gateway: $ipv4_gateway" + echo "---" + echo "IPv6 MAC: $ipv6_mac" echo "IPv6 Address: $ipv6_addr" echo "IPv6 Gateway: $ipv6_gateway" echo @@ -2035,48 +2037,9 @@ mod_initrd_debian_kali() { . /usr/share/debconf/confmodule db_progress START 0 5 debian-installer/netcfg/title - # 找到主网卡 - # debian 11 initrd 没有 xargs awk - # debian 12 initrd 没有 xargs - if false; then - iface=$(ip -o link | grep "@mac_addr" | awk '{print $2}' | cut -d: -f1) - else - iface=$(ip -o link | grep "@mac_addr" | cut -d' ' -f2 | cut -d: -f1) - fi - db_progress STEP 1 + : get_ip_conf_cmd - # dhcpv4 - db_progress INFO netcfg/dhcp_progress - udhcpc -i "$iface" -f -q -n - db_progress STEP 1 - - # slaac + dhcpv6 - db_progress INFO netcfg/slaac_wait_title - # https://salsa.debian.org/installer-team/netcfg/-/blob/master/autoconfig.c#L148 - cat </var/lib/netcfg/dhcp6c.conf -interface $iface { - send ia-na 0; - request domain-name-servers; - request domain-name; - script "/lib/netcfg/print-dhcp6c-info"; -}; - -id-assoc na 0 { -}; -EOF - dhcp6c -c /var/lib/netcfg/dhcp6c.conf "$iface" - sleep 10 - # kill-all-dhcp - kill -9 "$(cat /var/run/dhcp6c.pid)" - db_progress STEP 1 - - # 静态 + 检测网络 - db_subst netcfg/link_detect_progress interface "$iface" - db_progress INFO netcfg/link_detect_progress - . /alpine-network.sh @netconf - db_progress STEP 1 - - # 运行trans.sh,保存配置 + # 运行 trans.sh,保存配置 db_progress INFO base-installer/progress/netcfg sh /trans.sh db_progress STEP 1 @@ -2085,13 +2048,10 @@ EOF # 直接覆盖 net-retriever,方便调试 # curl -Lo /usr/lib/debian-installer/retriever/net-retriever $confhome/net-retriever - collect_netconf - is_in_china && is_in_china=true || is_in_china=false - netconf="'$mac_addr' '$ipv4_addr' '$ipv4_gateway' '$ipv6_addr' '$ipv6_gateway' '$is_in_china'" - - get_function_content netcfg | - sed "s|@mac_addr|$mac_addr|" | - sed "s|@netconf|$netconf|" >var/lib/dpkg/info/netcfg.postinst + postinst=var/lib/dpkg/info/netcfg.postinst + get_function_content netcfg >$postinst + get_ip_conf_cmd | insert_into_file $postinst after ": get_ip_conf_cmd" + # cat $postinst # shellcheck disable=SC2317 expand_packages() { @@ -2239,7 +2199,8 @@ EOF download_and_extract_udeb fdisk-udeb $tmp/fdisk cp -f $tmp/fdisk/usr/sbin/fdisk usr/sbin/ - if [ $ram_size -gt 256 ]; then + # >256M 或者当前系统是 windows + if [ $ram_size -gt 256 ] || is_in_windows; then sed -i '/^pata-modules/d' $net_retriever sed -i '/^sata-modules/d' $net_retriever sed -i '/^scsi-modules/d' $net_retriever @@ -2326,11 +2287,11 @@ EOF } get_disk_drivers() { - get_drivers "/sys/block/$xda" + get_drivers "/sys/block/$1" } get_net_drivers() { - get_drivers "/sys/class/net/$ethx" + get_drivers "/sys/class/net/$1" } # 不用在 windows 判断是哪种硬盘/网络驱动,因为 256M 运行 windows 只可能是 xp,而脚本本来就不支持 xp @@ -2366,13 +2327,44 @@ get_drivers() { ) } +exit_if_cant_use_cloud_kernel() { + find_main_disk + collect_netconf + + # shellcheck disable=SC2154 + if ! can_use_cloud_kernel "$xda" $ipv4_ethx $ipv6_ethx; then + error_and_exit "Can't use cloud kernel. And not enough RAM to run normal kernel." + fi +} + can_use_cloud_kernel() { + # initrd 下也要使用,不要用 <<< + # 有些虚拟机用了 ahci,但云内核没有 ahci 驱动 - # shellcheck disable=SC2317 - get_disk_drivers | grep -Ewq \ - 'ata_generic|ata_piix|pata_legacy|nvme|virtio_blk|virtio_scsi|xen_blkfront|xen_scsifront|hv_storvsc|vmw_pvscsi' && - ! get_disk_drivers | grep -Ewq 'pata_.*|sata_.*|ahci|mpt.*' && - ! get_net_drivers | grep -Ewq 'e1000' + cloud_eth_modules='ena|gve|mana|virtio_net|xen_netfront|hv_netvsc|vmxnet3|mlx4_en|mlx4_core|mlx5_core|ixgbevf' + cloud_blk_modules='ata_generic|ata_piix|pata_legacy|nvme|virtio_blk|virtio_scsi|xen_blkfront|xen_scsifront|hv_storvsc|vmw_pvscsi' + + # disk + drivers="$(get_disk_drivers $1)" + shift + for driver in $drivers; do + echo "using disk driver: $driver" + done + echo "$drivers" | grep -Ewq "$cloud_blk_modules" || return 1 + + # net + # v4 v6 eth 相同,只检查一次 + if [ "$1" = "$2" ]; then + shift + fi + while [ $# -gt 0 ]; do + drivers="$(get_net_drivers $1)" + shift + for driver in $drivers; do + echo "using net driver: $driver" + done + echo "$drivers" | grep -Ewq "$cloud_eth_modules" || return 1 + done } create_can_use_cloud_kernel_sh() { @@ -2381,12 +2373,28 @@ create_can_use_cloud_kernel_sh() { $(get_function get_net_drivers) $(get_function get_disk_drivers) $(get_function can_use_cloud_kernel) - xda=\$1 - ethx=\$2 - can_use_cloud_kernel + + can_use_cloud_kernel "\$@" EOF } +get_ip_conf_cmd() { + collect_netconf >&2 + is_in_china && is_in_china=true || is_in_china=false + + sh=/alpine-network.sh + if [ -n "$ipv4_mac" ] && [ -n "$ipv6_mac" ] && [ "$ipv4_mac" = "$ipv6_mac" ]; then + echo "'$sh' '$ipv4_mac' '$ipv4_addr' '$ipv4_gateway' '$ipv6_addr' '$ipv6_gateway' '$is_in_china'" + else + if [ -n "$ipv4_mac" ]; then + echo "'$sh' '$ipv4_mac' '$ipv4_addr' '$ipv4_gateway' '' '' '$is_in_china'" + fi + if [ -n "$ipv6_mac" ]; then + echo "'$sh' '$ipv6_mac' '' '' '$ipv6_addr' '$ipv6_gateway' '$is_in_china'" + fi + fi +} + mod_initrd_alpine() { # hack 1 v3.19 和之前的 virt 内核需添加 ipv6 模块 if virt_dir=$(ls -d $tmp_dir/lib/modules/*-virt 2>/dev/null); then @@ -2407,43 +2415,8 @@ mod_initrd_alpine() { fi fi fi - insert_into_file init after 'configure_ip\(\)' <>$conf_file auto lo iface lo inet loopback +EOF + + # ethx + for ethx in $(get_eths); do + if [ -f /etc/network/devhotplug ] && grep -wo "$ethx" /etc/network/devhotplug; then + mode=allow-hotplug + else + mode=auto + fi + cat <>$conf_file $mode $ethx EOF - # ipv4 - if is_dhcpv4; then - echo "iface $ethx inet dhcp" >>$conf_file + # ipv4 + if is_dhcpv4; then + echo "iface $ethx inet dhcp" >>$conf_file - elif is_staticv4; then - get_netconf_to ipv4_addr - get_netconf_to ipv4_gateway - cat <>$conf_file + elif is_staticv4; then + get_netconf_to ipv4_addr + get_netconf_to ipv4_gateway + cat <>$conf_file iface $ethx inet static address $ipv4_addr gateway $ipv4_gateway EOF - # dns - if list=$(get_current_dns_v4); then - for dns in $list; do - cat <>$conf_file + # dns + if list=$(get_current_dns_v4); then + for dns in $list; do + cat <>$conf_file dns-nameservers $dns EOF - done + done + fi fi - fi - # ipv6 - if is_slaac; then - echo "iface $ethx inet6 auto" >>$conf_file + # ipv6 + if is_slaac; then + echo "iface $ethx inet6 auto" >>$conf_file - elif is_dhcpv6; then - echo "iface $ethx inet6 dhcp" >>$conf_file + elif is_dhcpv6; then + echo "iface $ethx inet6 dhcp" >>$conf_file - elif is_staticv6; then - get_netconf_to ipv6_addr - get_netconf_to ipv6_gateway - cat <>$conf_file + elif is_staticv6; then + get_netconf_to ipv6_addr + get_netconf_to ipv6_gateway + cat <>$conf_file iface $ethx inet6 static address $ipv6_addr gateway $ipv6_gateway EOF - fi + fi - # dns - # 有 ipv6 但需设置 dns 的情况 - if is_need_manual_set_dnsv6 && list=$(get_current_dns_v6); then - for dns in $list; do - cat <>$conf_file + # dns + # 有 ipv6 但需设置 dns 的情况 + if is_need_manual_set_dnsv6 && list=$(get_current_dns_v6); then + for dns in $list; do + cat <>$conf_file dns-nameserver $dns EOF - done - fi + done + fi - # 禁用 ra - if should_disable_ra_slaac; then - if [ "$distro" = alpine ]; then - cat <>$conf_file + # 禁用 ra + if should_disable_ra_slaac; then + if [ "$distro" = alpine ]; then + cat <>$conf_file pre-up echo 0 >/proc/sys/net/ipv6/conf/$ethx/accept_ra EOF - else - cat <>$conf_file + else + cat <>$conf_file accept_ra 0 EOF + fi fi - fi + done } install_alpine() { @@ -1509,88 +1520,113 @@ get_yq_name() { create_cloud_init_network_config() { ci_file=$1 - get_netconf_to ethx - get_netconf_to mac_addr apk add "$(get_yq_name)" - # shellcheck disable=SC2154 - yq -i ".network.version=1 | - .network.config[0].type=\"physical\" | - .network.config[0].name=\"$ethx\" | - .network.config[0].mac_address=\"$mac_addr\" | - .network.config[1].type=\"nameserver\" + need_set_dns4=false + need_set_dns6=false + + config_id=0 + for ethx in $(get_eths); do + get_netconf_to mac_addr + + # shellcheck disable=SC2154 + yq -i ".network.version=1 | + .network.config[$config_id].type=\"physical\" | + .network.config[$config_id].name=\"$ethx\" | + .network.config[$config_id].mac_address=\"$mac_addr\" " $ci_file - ip_index=0 + subnet_id=0 - # ipv4 - if is_dhcpv4; then - yq -i ".network.config[0].subnets[$ip_index] = {\"type\": \"dhcp4\"}" $ci_file - ip_index=$((ip_index + 1)) - elif is_staticv4; then - get_netconf_to ipv4_addr - get_netconf_to ipv4_gateway - yq -i ".network.config[0].subnets[$ip_index] = { + # ipv4 + if is_dhcpv4; then + yq -i ".network.config[$config_id].subnets[$subnet_id] = {\"type\": \"dhcp4\"}" $ci_file + subnet_id=$((subnet_id + 1)) + elif is_staticv4; then + need_set_dns4=true + get_netconf_to ipv4_addr + get_netconf_to ipv4_gateway + yq -i ".network.config[$config_id].subnets[$subnet_id] = { \"type\": \"static\", \"address\": \"$ipv4_addr\", \"gateway\": \"$ipv4_gateway\" } " $ci_file - # 旧版 cloud-init 有 bug - # 有的版本会只从第一种配置中读取 dns,有的从第二种读取 - # 因此写两种配置 - if dns4_list=$(get_current_dns_v4); then - for cur in $dns4_list; do - yq -i ".network.config[0].subnets[$ip_index].dns_nameservers += [\"$cur\"]" $ci_file - yq -i ".network.config[1].address += [\"$cur\"]" $ci_file - done + # 旧版 cloud-init 有 bug + # 有的版本会只从第一种配置中读取 dns,有的从第二种读取 + # 因此写两种配置 + if dns4_list=$(get_current_dns_v4); then + for cur in $dns4_list; do + yq -i ".network.config[$config_id].subnets[$subnet_id].dns_nameservers += [\"$cur\"]" $ci_file + done + fi + subnet_id=$((subnet_id + 1)) fi - ip_index=$((ip_index + 1)) - fi - # ipv6 - if is_slaac; then - if is_enable_other_flag; then - type=ipv6_dhcpv6-stateless - else - type=ipv6_slaac - fi - yq -i ".network.config[0].subnets[$ip_index] = {\"type\": \"$type\"}" $ci_file + # ipv6 + # slaac: ipv6_slaac + # └─enable_other_flag: ipv6_dhcpv6-stateless + # dhcpv6: ipv6_dhcpv6-stateful - elif is_dhcpv6; then - yq -i ".network.config[0].subnets[$ip_index] = {\"type\": \"ipv6_dhcpv6-stateful\"}" $ci_file + # ipv6 + if is_slaac; then + if is_enable_other_flag; then + type=ipv6_dhcpv6-stateless + else + type=ipv6_slaac + fi + yq -i ".network.config[$config_id].subnets[$subnet_id] = {\"type\": \"$type\"}" $ci_file - elif is_staticv6; then - get_netconf_to ipv6_addr - get_netconf_to ipv6_gateway - # centos7 不认识 static6,但可改成 static,作用相同 - # https://github.com/canonical/cloud-init/commit/dacdd30080bd8183d1f1c1dc9dbcbc8448301529 - if [ -f /os/etc/system-release-cpe ] && - grep -E 'centos:7|oracle:linux:7' /os/etc/system-release-cpe; then - type_ipv6_static=static - else - type_ipv6_static=static6 - fi - yq -i ".network.config[0].subnets[$ip_index] = { + elif is_dhcpv6; then + yq -i ".network.config[$config_id].subnets[$subnet_id] = {\"type\": \"ipv6_dhcpv6-stateful\"}" $ci_file + + elif is_staticv6; then + get_netconf_to ipv6_addr + get_netconf_to ipv6_gateway + # centos7 不认识 static6,但可改成 static,作用相同 + # https://github.com/canonical/cloud-init/commit/dacdd30080bd8183d1f1c1dc9dbcbc8448301529 + if [ -f /os/etc/system-release-cpe ] && + grep -E 'centos:7|oracle:linux:7' /os/etc/system-release-cpe; then + type_ipv6_static=static + else + type_ipv6_static=static6 + fi + yq -i ".network.config[$config_id].subnets[$subnet_id] = { \"type\": \"$type_ipv6_static\", \"address\": \"$ipv6_addr\", \"gateway\": \"$ipv6_gateway\" } " $ci_file - if should_disable_ra_slaac; then - yq -i ".network.config[0].accept-ra = false" $ci_file + if should_disable_ra_slaac; then + yq -i ".network.config[$config_id].accept-ra = false" $ci_file + fi fi - fi - # 有 ipv6 但需设置 dns 的情况 - if is_need_manual_set_dnsv6 && dns6_list=$(get_current_dns_v6); then - for cur in $dns6_list; do - yq -i ".network.config[0].subnets[$ip_index].dns_nameservers += [\"$cur\"]" $ci_file - yq -i ".network.config[1].address += [\"$cur\"]" $ci_file - done - fi + # 有 ipv6 但需设置 dns 的情况 + if is_need_manual_set_dnsv6 && dns6_list=$(get_current_dns_v6); then + need_set_dns6=true + for cur in $dns6_list; do + yq -i ".network.config[$config_id].subnets[$subnet_id].dns_nameservers += [\"$cur\"]" $ci_file + done + fi - # 如果 network.config[1] 没有 address,则删除,避免低版本 cloud-init 报错 - yq -i 'del(.network.config[1] | select(has("address") | not))' $ci_file + config_id=$((config_id + 1)) + done + + if $need_set_dns4 || $need_set_dns6; then + yq -i ".network.config[$config_id].type=\"nameserver\"" $ci_file + if $need_set_dns4 && dns4_list=$(get_current_dns_v4); then + for cur in $dns4_list; do + yq -i ".network.config[$config_id].address += [\"$cur\"]" $ci_file + done + fi + if $need_set_dns6 && dns6_list=$(get_current_dns_v6); then + for cur in $dns6_list; do + yq -i ".network.config[$config_id].address += [\"$cur\"]" $ci_file + done + fi + # 如果 network.config[$config_id] 没有 address,则删除,避免低版本 cloud-init 报错 + yq -i "del(.network.config[$config_id] | select(has(\"address\") | not))" $ci_file + fi apk del "$(get_yq_name)" } @@ -1657,9 +1693,12 @@ modify_windows() { # 下载共同的子脚本 # 可能 unattend.xml 已经设置了ExtendOSPartition,不过运行resize没副作用 - bats="windows-set-netconf.bat windows-resize.bat" + bats="windows-resize.bat" download $confhome/windows-resize.bat $os_dir/windows-resize.bat - create_win_set_netconf_script $os_dir/windows-set-netconf.bat + for ethx in $(get_eths); do + create_win_set_netconf_script $os_dir/windows-set-netconf-$ethx.bat + bats="$bats windows-set-netconf-$ethx.bat" + done if $use_gpo; then # 使用组策略 @@ -1811,9 +1850,10 @@ EOF # 检测机器是否能用 cloud 内核 axx64=$(get_axx64) - ethx=$(cat /dev/ethx) - # shellcheck source=/dev/null - if ls $os_dir/boot/vmlinuz-*-cloud-$axx64 2>/dev/null && ! sh /can_use_cloud_kernel.sh "$xda" "$ethx"; then + eths=$(get_eths) + if ls $os_dir/boot/vmlinuz-*-cloud-$axx64 2>/dev/null && + ! sh /can_use_cloud_kernel.sh "$xda" $eths; then + cp_resolv_conf $os_dir chroot $os_dir apt update DEBIAN_FRONTEND=noninteractive chroot $os_dir apt install -y linux-image-$axx64 @@ -3238,7 +3278,9 @@ install_windows() { # 使用 autounattend.xml # win7 在此阶段找不到网卡 download $confhome/windows-resize.bat /wim/windows-resize.bat - create_win_set_netconf_script /wim/windows-set-netconf.bat + for ethx in $(get_eths); do + create_win_set_netconf_script /wim/windows-set-netconf-$ethx.bat + done else modify_windows /wim fi