Nervesを複数台準備していろいろ遊んでみようとした時に「あれ?これってIPアドレス以外同じやん。Nerves毎にmix nerves.new
するのって管理面倒やん。」って思ったのでmix firmware
した時にIPアドレスなどを引数として渡してIPアドレスを指定できるようにしてみました。
これは「Nervesのnode_nameとnode_hostとcookieを設定した」の続編になります。
環境
ハードウェア
- Mac OSX
- NervesをRaspberryPi 3で稼働
ネットワーク
-
Mac OSX
- 有線LAN→メンテナンス用、固定IPアドレス(192.168.5.100/24)
-
ラズパイ
- 有線LAN(eth0)→メンテナンス用、固定IPアドレス(192.168.5/24の範囲)
- 無線LAN(wlan0)→インターネット接続用、DHCP(192.168.46/24から自動割当)
- 192.168.5.240(default)は後述
各ファイルへの設定(これまでのまとめ含む)
前提としてmix nerves.new
しているプロジェクトがあることとします。
mix.exs
mix.exs
に必要なライブラリを追加します。
:nerves_firmware_ssh
は今回は不要ですが、まとめとして記載しておきます。
defp deps do
...
# 追加
{:nerves_network, "~> 0.5", targets: @all_targets},
{:nerves_firmware_ssh, "~> 0.3", targets: @all_targets},
...
config/target.exs
ネットワークまわりの設定が多くなりすぎたので別ファイルnetwork.exs
に分けることにします。
import_config("network.exs")
config/network.exs
$ mix firmware <IPアドレス> <サブネットマスク> <デフォルトゲートウェイ>
とすると各設定が入ったNervesイメージを作成するようにconfig/network.exs
を作成します。
直前の引数が指定されていることが必須で、引数が設定されていない場合のデフォルトの値は以下のようにしました。
- IPアドレス:192.168.5.240
- サブネットマスク:255.255.255.0
- デフォルトゲートウェイ:(設定なし)
$ mix firmware <IPアドレス> <サブネットマスク> <デフォルトゲートウェイ>
(例)
$ mix firmware "192.168.5.55" "255.255.255.0" "192.168.5.1"
$ mix firmware "192.168.5.150" "255.255.255.128"
$ mix firmware "192.168.5.200"
$ mix firmware ←この場合はデフォルト設定
#
# ライブラリ読み込み
#
import Config
#
# 変数の設定
#
arg_2nd = 1
arg_3rd = 2
arg_4th = 3
arg_ip = System.argv() |> Enum.at(arg_2nd)
arg_subnet = System.argv() |> Enum.at(arg_3rd)
arg_gateway = System.argv() |> Enum.at(arg_4th)
default_ip = "192.168.5.240"
default_subnet = "255.255.255.0"
default_gateway = ""
wired_ip = case arg_ip do
nil -> default_ip
_ -> arg_ip
end
wired_subnet = case arg_subnet do
nil -> default_subnet
_ -> arg_subnet
end
wired_gateway = case arg_gateway do
nil -> default_gateway
_ -> arg_gateway
end
#
# ネットワーク設定
#
settings = [
networks: [
[ssid: "SSIDの設定", psk: "PSKの設定", key_mgmt: :"WPA-PSK", priority: 0,
ipv4_address_method: :dhcp,
nameservers: ["8.8.8.8", "8.8.4.4"]
]
]
]
config :nerves_network, default: [
wlan0: settings,
eth0: [
ipv4_address_method: :static,
ipv4_address: wired_ip,
ipv4_subnet_mask: wired_subnet,
ipv4_gateway: wired_gateway
]
]
参考
System.argv()
するとfirmware
を第一引数としてリストが生成されるのでEnum.at/2
で場所を指定して利用しています。
(例)
$ mix firmware "192.168.5.55" "255.255.255.128" "192.168.5.1"
iex> System.argv()
["firmware", "192.168.5.55", "255.255.255.128", "192.168.5.1"]
確認
引数をすべて指定している場合とIPアドレスのみ指定している場合で確認します。
すべての引数がある場合
$ mix deps.get
$ mix firmware "192.168.5.55" "255.255.255.128" "192.168.5.1"
$ mix firmware.burn
$ ssh 192.168.5.150
iex> Nerves.NetworkInterface.settings("eth0")
{:ok,
%{
ipv4_address: "192.168.5.55",
ipv4_broadcast: "192.168.5.127",
ipv4_gateway: "192.168.5.1",
ipv4_subnet_mask: "255.255.255.128",
mac_address: "b8:27:eb:96:da:51"
}}
IPアドレスのみ指定している場合
IPアドレスが設定されているのでupload.sh
を使ってNervesイメージを更新します。
サブネットマスクとデフォルトゲートウェイは指定していなのでデフォルトの値が設定されます。
$ mix deps.get
$ mix firmware "192.168.5.55"
$ ./upload.sh 192.168.5.55
$ ssh 192.168.5.55
iex> Nerves.NetworkInterface.settings("eth0")
{:ok,
%{
ipv4_address: "192.168.5.55",
ipv4_broadcast: "192.168.5.255",
ipv4_gateway: "",
ipv4_subnet_mask: "255.255.255.0",
mac_address: "b8:27:eb:96:da:51"
}}
まとめ
mix firmware
の際、引数を与えてNervesのイメージを変更できました。
これまではNervesプロジェクトの設定ファイルを確認すればIPアドレスが判断できてました。が、今回のように設定ファイルにIPアドレスを記載しない方法にすると、どのNervesがどのIPアドレスを設定しているかが分からなくなる副作用があることがわかりました\(^o^)/