0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

基本的なNetplanのyamlファイルを対話で作成するbashシェルスクリプト

Last updated at Posted at 2025-01-01

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出力
netplan_config.sh (Ver.2025.1.3)
#!/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上)

netplan_config.sh_動作の様子.gif

1.3. 動作の様子(生成AIプラットフォーム上)

上記の通りシェルスクリプトで作ってみたのですが、結局メンテナンスは必要になりますし、、
おそらく、生成AIのRAGでNetplanのリファレンスと、書かせたいyamlフォーマットを読み込ませた出力を書かせれば良いのではないか?と思いつつ、
(追伸 2025.1.3 既に実践されている方がいらっしゃいましたね! 1
とりあえず作ったシェルスクリプトをRAGにいれてシミュレート動作させてみました。

  • 入力したプロンプト
「netplan_config.sh」の動作を、正確にシミュレートして、
都度ユーザー入力は、私からのインプットを待ってください。
最後、yamlの出力は「```pre」~「```」のコードブロックとして囲ってください。
  • miiboチャットでの動作の様子
    miiboでシミュレートさせた様子.gif

以上です。
  1. Raspberry PiでUbuntu ServerのIPアドレスをNetPlanで固定する方法(LLMを活用して効率的に設定ファイルを生成) #RaspberryPi - Qiita

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?