0. きっかけ
0.1. Netplanのフォーマットはちょいちょい変わり、yamlのインデントルールが厳しい。。
Ubintu - Configuring network
当然、定義はあるのですが、OSバージョンが変わる度にちょっとずつ推奨の書き方が変わっていて、
以前設定したNetplan構文が、次のOSバージョンだと”非推奨です。”と言われることも多々あり。。
1. Netplanコンフィグ生成bashスクリプト
1.1. とりあえず作っておきました
(minetaro12さんブログ) NetplanでUbuntuのネットワーク設定をする
初期設定の00-installer-config.yamlや50-cloud-init.yamlは直接編集しないようにする。
必ずコピーして99-config.yamlのようなファイルで設定をする。
(Qiita) 【Ubuntu】 /etc/netplan/50-cloud-init.yamlを編集するの止めろ
netplanは/etc/netplan/*.yamlを全部参照する
以上の前提にて、次の動作をするスクリプトを書きます。
(1)設定するネットワークインターフェース名を選択(入力)する。
(2)/etc/netplan/99-config-[インターフェース名].yaml
でファイルを作ってしまう。
(3)netplan apply
で全てのyamlファイルを読み込む。
-
実行例
$ sudo bash netplan_config.sh
- ソースコード ※これもほとんど生成AI出力
#!/bin/bash
# YAMLファイルのテンプレート関数 #
yaml_template() {
cat << EOL > "${CONFIG_FILE}"
network:
version: 2
ethernets:
${interface}:
optional: true
${write_ip}
${write_gateway}
${write_nameservers}
EOL
}
# ネットワークインターフェースを取得する関数 #
get_interfaces() {
ip link show | awk -F: '/^[0-9]+: [^lo]/ {print $2}' | tr -d ' '
}
# ネットマスクをプレフィックス値に変換する関数 #
netmask_to_cidr() {
local netmask=$1
local cidr=0
# Check if the input is a valid CIDR format
if [[ $netmask =~ ^[0-9]+$ ]] && [ "$netmask" -ge 0 ] && [ "$netmask" -le 32 ]; then
echo "$netmask"
return
fi
# Validate IPv4 netmask format
if [[ $netmask =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
IFS='.' read -r -a octets <<< "$netmask"
for octet in "${octets[@]}"; do
# Ensure each octet is between 0 and 255
if [[ $octet -lt 0 || $octet -gt 255 ]]; then
echo "Error: Invalid netmask - octet out of range (0-255)."
return 1
fi
# Count the number of 1 bits in the binary representation of the octet
while [ $octet -gt 0 ]; do
cidr=$((cidr + (octet & 1)))
octet=$((octet >> 1))
done
done
echo "$cidr"
else
echo "Error: Invalid netmask format."
fi
}
# ネットワーク設定の編集関数 #
edit_interface() {
local interface=$1
echo "$interface の設定を編集します。"
# IPアドレスを固定するか? #
read -p "このインターフェースに固定IPアドレスを設定しますか? (y/n): " staticip_enable
if [[ $staticip_enable = [yY] ]]; then
# IPアドレス #
local default_ip="192.168.1.100"
read -p "IPアドレスを入力してください (例: ${default_ip}): " ip_address
ip_address=${ip_address:-$default_ip}
if ! [[ $ip_address =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
echo "無効なIPアドレス形式です: $ip_address"
return 1
fi
# ネットマスク #
local default_netmask="255.255.255.0"
read -p "ネットマスクを入力してください (例: ${default_netmask} または $(netmask_to_cidr "$default_netmask")): " netmask
netmask=${netmask:-$default_netmask}
cidr=$(netmask_to_cidr "$netmask")
if [[ $cidr =~ ^Error ]]; then
echo "無効なネットマスク形式です: $netmask"
return 1
fi
write_ip="dhcp4: false
addresses:
[$ip_address/$cidr]"
# デフォルトゲートウェイ #
read -p "このインターフェースにデフォルトゲートウェイを設定しますか? (y/n): " dgw_enable
if [[ $dgw_enable = [yY] ]]; then
local default_gateway="192.168.1.254"
read -p "ゲートウェイアドレスを入力してください (例: ${default_gateway}): " gateway
gateway=${gateway:-$default_gateway}
if ! [[ $gateway =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
echo "無効なゲートウェイアドレス形式です: $gateway"
return 1
fi
write_gateway="routes:
- to: default
via: $gateway"
fi
# DNSサーバアドレス #
read -p "プライマリDNSサーバアドレスを設定しますか? (y/n): " dns_enable
if [[ $dns_enable = [yY] ]]; then
local default_dns=${gateway:-192.168.1.254}
read -p "プライマリDNSサーバアドレスを入力してください (例: ${default_dns}): " primary_dns
primary_dns=${primary_dns:-$default_dns}
read -p "セカンダリDNSサーバアドレスを設定しますか? (y/n): " dns_enable
if [[ $dns_enable = [yY] ]]; then
local default_dns="8.8.8.8, 8.8.4.4, 1.1.1.1, 1.0.0.1"
read -p "セカンダリDNSサーバアドレスを入力してください (例: ${default_dns}): " secondary_dns
secondary_dns=", ${secondary_dns:-$default_dns}"
fi
write_nameservers="nameservers:
addresses:
[$primary_dns$secondary_dns]"
fi
else
# IPアドレスを固定しない場合はDHCPクライアントを有効にする #
write_ip="dhcp4: true"
fi
# ネットワーク設定をYAMLファイルに書き込む(yaml_template関数実行) #
# /etc/netplan/99-config-{$インターフェース名}.yaml のフルパス #
CONFIG_FILE="/etc/netplan/99-config-${interface}.yaml"
echo -e "${interface} 用の設定を \n ${CONFIG_FILE} へ上書きしています..."
yaml_template
chmod 600 $CONFIG_FILE
echo "現在の設定内容:"
cat "$CONFIG_FILE"
}
# メニュー表示関数 #
show_menu() {
echo ""
echo "===== netplan ネットワーク設定メニュー(IPv4) ====="
echo "1) ネットワークインターフェースを編集する"
echo "2) 設定を適用する (netplan apply)"
echo "q) 終了"
echo -n "選択してください: "
}
# メイン処理関数 #
main() {
while true; do
show_menu
read choice
case $choice in
1)
echo "現在のIPアドレス状態:"
ip addr show | grep 'inet'
interfaces=$(get_interfaces)
echo "利用可能なネットワークインターフェース:"
echo "$interfaces"
echo -n "設定するインターフェース名を入力してください(test指定も可能です): "
read interface_name
if [[ $interfaces =~ $interface_name || $interface_name == "test" ]]; then
edit_interface "$interface_name"
else
echo "無効なインターフェース名です。"
fi
;;
2)
echo "最終確認: 新たに設定した $CONFIG_FILE は次の通りです。"
cat "$CONFIG_FILE"
echo -n "この内容を適用しますか? (y/n): "
read apply_choice
if [[ $apply_choice == [yY] ]]; then
rm /etc/netplan/99-config-test.yaml 2>/dev/null
netplan apply &
wait
while true; do
result0=$(ip addr show | grep "$interface_name" | grep -o inet)
if [[ -n "$result0" || $interface_name == "test" ]]; then
break
fi
echo "$interface_name 情報更新の待機中..."
sleep 1
if ip addr show "$interface_name" 2>/dev/null | grep -q "state DOWN"; then
echo "[注意!]設定は更新しましたが $interface_name はリンクが確立できていません。(ケーブル抜け、接続先ネットワーク無し、等)"
break
fi
done
while true; do
result1=$(ip addr show | grep 'inet')
sleep 1
result2=$(ip addr show | grep 'inet')
if [[ "$result1" == "$result2" ]]; then
break
fi
echo "インターフェース情報更新の待機中..."
done
echo "設定が適用されました。"
echo "現在のIPアドレス状態:"
ip addr show | grep 'inet'
else
echo "設定の適用をキャンセルしました。"
rm /etc/netplan/99-config-test.yaml 2>/dev/null
fi
;;
q)
echo "終了します。"
rm /etc/netplan/99-config-test.yaml 2>/dev/null
exit 0
;;
*)
echo "無効な選択です。もう一度入力してください。"
;;
esac
done
}
# スクリプト実行時の権限チェック #
if [[ $EUID -ne 0 ]]; then
echo "このスクリプトは root 権限で実行する必要があります。(例: sudo bash `echo "$0"`)"
exit 1
fi
# Ubuntuのバージョンチェック #
version=$(grep VERSION_ID /etc/os-release | cut -d '=' -f 2 | tr -d '"')
if (( $(echo "$version <= 20.00" | bc -l) )); then
echo "Ubuntuのバージョンが20.00以前のため、このツールは対応しません。終了します。"
exit 1
fi
# メイン処理の呼び出し #
main
Ver.2025.1.3 の注意点
各変数のリセットが出来ていないので、連続してインターフェースの設定ができません。
1つのインターフェース設定毎に「q)終了」を行ってください。
1.2. 動作の様子(Ubuntu22.04上)
1.3. 動作の様子(生成AIプラットフォーム上)
上記の通りシェルスクリプトで作ってみたのですが、結局メンテナンスは必要になりますし、、
おそらく、生成AIのRAGでNetplanのリファレンスと、書かせたいyamlフォーマットを読み込ませた出力を書かせれば良いのではないか?と思いつつ、
(追伸 2025.1.3 既に実践されている方がいらっしゃいましたね! 1)
とりあえず作ったシェルスクリプトをRAGにいれてシミュレート動作させてみました。
- 事前に「ナレッジデータストア」(miiboでの呼称)に「netplan_config.sh」を「テキストデータ」として登録しておく。
- 入力したプロンプト
「netplan_config.sh」の動作を、正確にシミュレートして、
都度ユーザー入力は、私からのインプットを待ってください。
最後、yamlの出力は「```pre」~「```」のコードブロックとして囲ってください。
以上です。