5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Bluemix(SoftLayer)Advent Calendar 2016

Day 7

Vyatta(VyOS)のコンフィグをXML化する

Last updated at Posted at 2017-02-01

このエントリは、Bluemix(SoftLayer) Advent Calendar 2016の7日目の記事です。

#Vyatta(VyOS)とは
Bluemix Infrastructure(旧SoftLayer)で柔軟なネットワークを構築したいときに、ソフトウェアルータであるVyatta(VyOS)がよく利用されます。
ルーティングはもちろん、ステートフルファイアウォールやVPNなどの機能が使えます。

#Vyattaのコンフィグ
Vyattaの設定は、プロンプトから"show configuration"を実行するといわゆるrunning-configが表示されます。なんかJSONっぽい!

vyatta@vy01:~$ show configuration 
firewall {
    all-ping enable
    broadcast-ping disable
    config-trap disable
    group {
        address-group ipsec-peer {
      ・・・
        }
    }
}
interfaces {
      ・・・
}
・・・

完全にJSONだったら楽だったのですが、残念ながらJSONとも違う謎の記述法で書かれています。少なくとも木構造ではあるようです。
そこでこのコンフィグを扱いやすいデータ記述法に変換して、自動でExcelなどに貼り付けられたら、管理表が最新でないだの、実機と設定が違うだの、運用でありがちな問題から開放されるなーということで、変換ツールを作ってみます。開放されたい!

#コンフィグ変換の方針
変換するツールはどんなのが便利か考えてみました。

形式
なんでもよいのですが、VBAでExcelに貼りたかったので今回はMSXMLなどパーサが充実しているXMLにします。
ポータビリティ
ツールは特定の環境に依存せず使えることが理想です。もっと言えばVyattaの上で実行できれば文句なしです。VyattaはDebianベースのLinuxなので、ある程度のコマンドが使えます。
環境を汚さない
Vyattaの上で実行するとなれば、一時ファイルとかは残したくないです。あまりゴリゴリ重いこともやりたくないです。

上記方針を加味した結果、sedとtrだけでいこうとおもいます
Vyatta上でも実行できるし、コンフィグを取ってきてローカルのcygwinやMacで実行してもよし。
やってみてだめだったら大人しくパールのようなものを使って書きます。(PythonはVyattaに入っていました。Rubyはなかった。)

XML化するにあたってルール決めが必要なところは以下のようにしました。

・要素名にハイフンは使わない
要素名にハイフンが含まれるとXMLが扱いにくくなる言語があるため、ハイフンはアンダースコアに変換します。

host-name vy01
   ↓
<host_name>vy01</host_name>

・名前っぽいところには属性を使う

ethernet eth1 {
    address 172.16.0.1/24
}
   ↓
<ethernet name="eth1">
    <address>172.16.0.1/24</address>
</ethernet>

・宣言だけのところは適宜単語を補う

rfc3768-compatibility
   ↓
<rfc3768_compatibility>true</rfc3768_compatibility>

#呪文
上記ルールに沿うようsedのコマンドを機械的に追加していった結果、よくわからないものが出来上がりました。真面目にPythonで書けばよかった!

"show configuration"の結果をパイプで食わせてあげればXMLが出てきます。

vyatta@vy01:~$ show configuration | 呪文
呪文
sed 's/enable-default-log/enable_default_log true/' |\
sed 's/rfc3768-compatibility/rfc3768_compatibility true/' |\
sed 's/repository supported/repository_supported/' |\
sed 's/local-zone$/local_zone true/' |\
sed 's/system$/forward_to system/' |\
sed 's@^\( *\)\([^ {}]\+\) \([^ {}]\+\)\( *\)$@\1<\2>\3</\2>\4@' | \
tr '\n' '~' | \
sed 's@\(~ *\)\([^{}~]*\) {~\([^{}]*~*\)\( *\)}~@\1<\2>~\3\4</\2>~@g' | \
sed 's@\(~ *\)\([^{}~]*\) {~\( *\)}~@\1<\2></\2>~@g' | \
sed 's@\(~ *\)\([^{}~]*\) {~\([^{}]*~\)\( *\)}~@\1<\2>~\3\4</\2>~@g' | \
sed 's@\(~ *\)\([^{}~]*\) {~\([^{}]*~\)\( *\)}~@\1<\2>~\3\4</\2>~@g' | \
sed 's@\(~ *\)\([^{}~]*\) {~\([^{}]*~\)\( *\)}~@\1<\2>~\3\4</\2>~@g' | \
sed 's@\(~ *\)\([^{}~]*\) {~\([^{}]*~\)\( *\)}~@\1<\2>~\3\4</\2>~@g' | \
sed 's@\(~ *\)\([^{}~]*\) {~\([^{}]*~\)\( *\)}~@\1<\2>~\3\4</\2>~@g' | \
sed 's@\(~ *\)\([^{}~]*\) {~\([^{}]*~\)\( *\)}~@\1<\2>~\3\4</\2>~@g' | \
sed 's@\(~ *\)\([^{}~]*\) {~\([^{}]*~\)\( *\)}~@\1<\2>~\3\4</\2>~@g' | \
sed 's@^\( *\)\([^{}~]*\) {~\([^{}]*~\)\( *\)}~@\1<\2>~\3\4</\2>~@g' | \
tr '~' '\n' | \
sed 's@<address-group \([^>]\+\)>@<address_group name="\1">@' |\
sed 's@</address-group [^>]\+>@</address_group>@' |\
sed 's@<name \([^>]\+\)>@<rule_set name="\1">@' |\
sed 's@</name [^>]\+>@</rule_set>@' |\
sed 's@<rule \([^>]\+\)>@<rule priority="\1">@' |\
sed 's@</rule [^>]\+>@</rule>@' |\
sed 's@<bonding \([^>]\+\)>@<bonding name="\1">@' |\
sed 's@</bonding [^>]\+>@</bonding>@' |\
sed 's@<vif \([^>]\+\)>@<vif name="\1">@' |\
sed 's@</vif [^>]\+>@</vif>@' |\
sed 's@<vrrp-group \([^>]\+\)>@<vrrp_group name="\1">@' |\
sed 's@</vrrp-group [^>]\+>@</vrrp_group>@' |\
sed 's@<ethernet \([^>]\+\)>@<ethernet name="\1">@' |\
sed 's@</ethernet [^>]\+>@</ethernet>@' |\
sed 's@<loopback \([^>]\+\)>@<loopback name="\1">@' |\
sed 's@</loopback [^>]\+>@</loopback>@' |\
sed 's@<vti \([^>]\+\)>@<vti name="\1">@' |\
sed 's@</vti [^>]\+>@</vti>@' |\
sed 's@<interface-route \([^>]\+\)>@<interface_route network="\1">@' |\
sed 's@</interface-route [^>]\+>@</interface_route>@' |\
sed 's@<next-hop-interface \([^>]\+\)>@<next_hop_interface name="\1">@' |\
sed 's@</next-hop-interface [^>]\+>@</next_hop_interface>@' |\
sed 's@<route \([^>]\+\)>@<route network="\1">@' |\
sed 's@</route [^>]\+>@</route>@' |\
sed 's@<route6 \([^>]\+\)>@<route6 network="\1">@' |\
sed 's@</route6 [^>]\+>@</route6>@' |\
sed 's@<next-hop \([^>]\+\)>@<next_hop address="\1">@' |\
sed 's@</next-hop [^>]\+>@</next_hop>@' |\
sed 's@<remote-router \([^>]\+\)>@<remote_router address="\1">@' |\
sed 's@</remote-router [^>]\+>@</remote_router>@' |\
sed 's@<sync-map \([^>]\+\)>@<sync_map name="\1">@' |\
sed 's@</sync-map [^>]\+>@</sync_map>@' |\
sed 's@<community \([^>]\+\)>@<community name="\1">@' |\
sed 's@</community [^>]\+>@</community>@' |\
sed 's@<device \([^>]\+\)>@<device name="\1">@' |\
sed 's@</device [^>]\+>@</device>@' |\
sed 's@<user \([^>]\+\)>@<user name="\1">@' |\
sed 's@</user [^>]\+>@</user>@' |\
sed 's@<server \([^>]\+\)>@<server name="\1">@' |\
sed 's@</server [^>]\+>@</server>@' |\
sed 's@<repository \([^>]\+\)>@<repository name="\1">@' |\
sed 's@</repository [^>]\+>@</repository>@' |\
sed 's@<facility \([^>]\+\)>@<facility name="\1">@' |\
sed 's@</facility [^>]\+>@</facility>@' |\
sed 's@<esp-group \([^>]\+\)>@<esp_group name="\1">@' |\
sed 's@</esp-group [^>]\+>@</esp_group>@' |\
sed 's@<ike-group \([^>]\+\)>@<ike_group name="\1">@' |\
sed 's@</ike-group [^>]\+>@</ike_group>@' |\
sed 's@<proposal \([^>]\+\)>@<proposal number="\1">@' |\
sed 's@</proposal [^>]\+>@</proposal>@' |\
sed 's@<peer \([^>]\+\)>@<peer name="\1">@' |\
sed 's@</peer [^>]\+>@</peer>@' |\
sed 's@<zone \([^>]\+\)>@<zone name="\1">@' |\
sed 's@</zone [^>]\+>@</zone>@' |\
sed 's@<from \([^>]\+\)>@<from zone="\1">@' |\
sed 's@</from [^>]\+>@</from>@' |\
sed 's@<\([^-<>"]\+\)-\([^>]\+\)>@<\1_\2>@' |\
sed 's@</\([^-<>"]\+\)-\([^>]\+\)>@</\1_\2>@' |\
sed 's@<\([^-<>"]\+\)-\([^>]\+\)>@<\1_\2>@' |\
sed 's@</\([^-<>"]\+\)-\([^>]\+\)>@</\1_\2>@' |\
sed 's@<\([^-<>"]\+\)-\([^>]\+\)>@<\1_\2>@' |\
sed 's@</\([^-<>"]\+\)-\([^>]\+\)>@</\1_\2>@' |\
sed 's@^@    @' |\
sed '1i\<root>' |\
sed '$a\</root>'

Vyatta上にファイル置いちゃってもいいよという人は、スクリプトにして/tmpの下とかに置くといいとおもいます。

いろいろサニタイズして大幅に削っていますが、XMLは以下のようなものが出力されます。

<root>
    <interfaces>
        <ethernet name="eth0">
            <address>192.168.0.1/24</address>
            <duplex>auto</duplex>
            <hw_id>XX:XX:XX:XX:XX:XX</hw_id>
            <smp_affinity>auto</smp_affinity>
            <speed>auto</speed>
            <vrrp>
                <vrrp_group name="1">
                    <advertise_interval>1</advertise_interval>
                    <preempt>true</preempt>
                    <priority>254</priority>
                    <rfc3768_compatibility>true</rfc3768_compatibility>
                    <sync_group>vgroup1</sync_group>
                    <virtual_address>192.168.0.3/24</virtual_address>
                </vrrp_group>
            </vrrp>
        </ethernet>
        <ethernet name="eth1">
            <address>172.16.0.1/24</address>
            <duplex>auto</duplex>
            <hw_id>XX:XX:XX:XX:XX:XX</hw_id>
            <smp_affinity>auto</smp_affinity>
            <speed>auto</speed>
            <vrrp>
                <vrrp_group name="1">
                    <advertise_interval>1</advertise_interval>
                    <preempt>true</preempt>
                    <priority>254</priority>
                    <rfc3768_compatibility>true</rfc3768_compatibility>
                    <sync_group>vgroup1</sync_group>
                    <virtual_address>172.16.0.3/24</virtual_address>
                </vrrp_group>
            </vrrp>
        </ethernet>
        <loopback name="lo">
        </loopback>
    </interfaces>
    <service>
        <dns>
            <forwarding>
                <cache_size>150</cache_size>
                <listen_on>eth1</listen_on>
                <forward_to>system</forward_to>
            </forwarding>
        </dns>
        <ssh>
            <port>22</port>
        </ssh>
    </service>
    <system>
        <config_management>
            <commit_revisions>20</commit_revisions>
        </config_management>
        <console>
            <device name="ttyS0">
                <speed>9600</speed>
            </device>
        </console>
        <gateway_address>192.168.0.1</gateway_address>
        <host_name>vy01</host_name>
        <login>
            <user name="vyatta">
                <authentication>
                    <encrypted_password>****************</encrypted_password>
                </authentication>
                <level>admin</level>
            </user>
        </login>
        <name_server>192.168.0.1</name_server>
        <ntp>
            <server name="ntp.nict.jp">
            </server>
        </ntp>
        <package>
            <auto_sync>1</auto_sync>
            <repository_supported>
                <components>main</components>
                <distribution>stable</distribution>
                <password>****************</password>
                <url>http://packages.vyatta.com/vyatta_supported</url>
                <username>""</username>
            </repository_supported>
        </package>
        <syslog>
            <global>
                <facility name="all">
                    <level>notice</level>
                </facility>
                <facility name="protocols">
                    <level>debug</level>
                </facility>
            </global>
        </syslog>
        <time_zone>Asia/Tokyo</time_zone>
    </system>
</root>

これを使ってVBAでExcelにぺたぺた貼ると、図のようなドキュメントが自動で作れました。便利。
spreadsheet.png

よく設定変更するところしかテストできていないので、不足がいっぱいあると思います。基本的にsedの行を追加すれば対応できると思いますが、コメントなどで教えていただけますと幸いです。
VBAのコードは来年のアドベントカレンダーにでも。。

5
3
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
5
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?