てくなべ (tekunabe)

ansible / network / automation

[Ansible] ipaddr フィルターでプレフィックス表記とネットマスク表記を変換する

■ はじめに

Ansible には、IP アドレスに対してさまざまフィルターをかける ipaddrというフィルタープラグインがあります。

このフィルターを使って、プレフィックス表記とネットマスク表記を相互に変換する方法をまとまめす。

  • プレフィックス表記からネットマスク表記
    • 例: 172.16.1.1/24 → 172.16.1.1/255.255.255.0
  • ネットマスク表記からプレフィックス表記
    • 例: 172.16.1.1/255.255.255.0 → 172.16.1.1/24

ipaddr('netmask')でネットマスクを、ipaddr('prefix')プレフィックスを取得するのがポイントです。

  • 動作確認環境: Ansible 2.8.4
  • 要 netaddr (pip install netaddr でインストール)


■ フィルターの書き方

プレフィックス表記からネットマスク表記

 "{{ '172.16.1.1/24' | replace(item | ipaddr('prefix'), '') }}{{ item | ipaddr('netmask') }}"

変換後: 172.16.1.1/255.255.255.0

ホストアドレスにもネットワークアドレスにも対応させるために、少々まどろこっしい書き方になっています。

本当は、ipaddr フィルターで直接 172.16.1.1/24172.16.1.1 にしてからネットマスクを付加したかったのですが、コードを見てもやり方が見つかりませんでした。そのため、まず replaceプレフィックスを削除しています。

なお、スラッシュ区切りではなく、スペース区切りで良ければ以下のようにシンプルなフィルターでOKです。

"{{ '172.16.1.1/24' | ipaddr('ip_netmask') }}"

変換後: 172.16.1.1 255.255.255.0

ただし、ネットワークアドレスをフィルタすると空になってしまうので、以下のようにする必要があります。

"{{ '172.16.1.0/24' | ipaddr('network_netmask') }}"

変換後: 172.16.1.0 255.255.255.0

ネットマスク表記からプレフィックス表記

 "{{ '172.16.1.1/255.255.255.0' | replace(item | ipaddr('netmask'), '') }}{{ item | ipaddr('prefix') }}"

変換後: 172.16.1.1/24

少々まどろっこしくなっているのは前述の事情のとおりです。

なお、ホストアドレスだけが対象であれば、以下のようにシンプルなフィルターでOKです。

"{{ '172.16.1.1/255.255.255.0' | ipaddr('ip/prefix') }}"

変換後: 172.16.1.1/24

ネットワークアドレスだけが対象であれば、以下のとおりです。

"{{ '172.16.1.0/255.255.255.0' | ipaddr('network/prefix') }}"

変換後: 172.16.1.0/24


■ サンプル

いくつかインプットのパターンを用意した Playbook で試します。

Playbook

Playbook はこちらです。

  • netconv.yml
- hosts: localhost
  gather_facts: no
  connection: local

  tasks:
    - name: prefix > netmask
      debug:
        msg: "{{ item | replace(item | ipaddr('prefix'), '') }}{{ item | ipaddr('netmask') }}"
      loop:
        - 172.16.1.0/24     # ネットワークアドレス
        - 172.16.1.1/24
        - 172.16.1.254/24
        - 172.16.1.255/24   # ブロードキャストアドレス

    - name: mask > netprefix
      debug:
        msg: "{{ item | replace(item | ipaddr('netmask'), '') }}{{ item | ipaddr('prefix') }}"
      loop:
        - 172.16.1.0/255.255.255.0     # ネットワークアドレス
        - 172.16.1.1/255.255.255.0
        - 172.16.1.254/255.255.255.0
        - 172.16.1.255/255.255.255.0   # ブロードキャストアドレス

実行結果

実行します。

$ ansible-playbook -i localhost, netconv.yml 

(抜粋)

TASK [prefix > netmask] ***********************************
ok: [localhost] => (item=172.16.1.0/24) => {
    "msg": "172.16.1.0/255.255.255.0"
}
ok: [localhost] => (item=172.16.1.1/24) => {
    "msg": "172.16.1.1/255.255.255.0"
}
ok: [localhost] => (item=172.16.1.254/24) => {
    "msg": "172.16.1.254/255.255.255.0"
}
ok: [localhost] => (item=172.16.1.255/24) => {
    "msg": "172.16.1.255/255.255.255.0"
}

TASK [mask > netprefix] ***********************************
ok: [localhost] => (item=172.16.1.0/255.255.255.0) => {
    "msg": "172.16.1.0/24"
}
ok: [localhost] => (item=172.16.1.1/255.255.255.0) => {
    "msg": "172.16.1.1/24"
}
ok: [localhost] => (item=172.16.1.254/255.255.255.0) => {
    "msg": "172.16.1.254/24"
}
ok: [localhost] => (item=172.16.1.255/255.255.255.0) => {
    "msg": "172.16.1.255/24"
}


■ まとめ

ipaddr フィルタープラグインを使って、プレフィックス表記とネットマスク表記を相互に変換する方法をまとめました。ipaddr フィルタープラグインには、他にもさまざまな機能がありますので、IP アドレスに対してなにか加工したい場合は、このフィルターを調べてみると良いかもしれません。

※ もっと良い方法をご存知の方、@akira6592 までご連絡いただけると幸いです。


参考