execができないYAMAHAルーターへssh接続でステータス取得


YAMAHAルーターへSSH接続してコマンドを実行させるのに、小技を使ったという話。
こちらの続きになります。

 共通ユーザーでtelnet接続してステータス取得をcronで回しているとしてると時々失敗していることに気がついた。失敗しているタイミングでは、他の人がネットワーク構成の変更のためにログインしているということがわかり、やはりtelnetでもユーザー名指定のほうがいいよね→それもうsshでよくね?ということでtelnet接続をやめることにした。

tasks/main(telnet).yml
- name: ルーター情報取得
  telnet:
    password: soge
    prompts:
      - "[$|>]|Password: "
    command:
      - console character en.ascii
      - show status dhcpc

 ⇓

tasks/main(ssh).yml
- name: ルーター情報取得
  shell: |
      console character en.ascii
      show status dhcpc

動作確認用テスト環境で問題ないことと、ルーターにもSSHで入れることを確認した後、ansible-playbookを起動すると、 "Failed to connect to the host via ssh:" でunreachableとなってしまった。verboseログレベルを上げながら確認していくと、"-vvvv"まで来たところで、以下のログが吐き出されて原因が判明した。

Received disconnect from www.xxx.yyy.zzz port 22:2: Channel request 'exec' is not supported

RTX1210 「 exec ? な に そ れ 」

 ルーターのOSはLinuxじゃないので予想して然るべきだったが、execができないので対応を検討。expectモジュールを使用することにしました。

expect(ssh).yml
- name: ルーター情報取得
  local_action:
    module: expect
    command: ssh hoge@{{ inventory_hostname }}
    responses:
      "[P|p]assword: ":
        - soge
      "[#|$|>] ":
        - console character en.ascii
        - show status dhcpc
        - exit

一応telnetでもステータスは取れたけど、rc=2 "Connection closed by foreign host." となってエラー扱いされてしまったので、ignore_errorsをつけないと先に進めなくなってしまった。素直にtelnetモジュール使え。

expect(telnet).yml
- name: ルーター情報取得
  local_action:
    module: expect
    command: telnet {{ inventory_hostname }}
    responses:
      "Username: ":
        - hoge
      "[P|p]assword: ":
        - soge
      "[#|$|>] ":
        - console character en.ascii
        - show status dhcpc
        - exit
  ignore_errors: True # 嫌すぎる