Python はじめから勉強 Hour10:アプリケーションを作ってみる
- Pythonで何かしようとしたときに、まずサンプルスクリプトを探してなんとなく実行してた私が、
- 自動実行でREST API叩いて、結果の確認、VM操作までやってみたいと思う7時間
- と思ってたら7時間を超えて10回になりました。
- 今回はアプリケーションを作ってみます。もともと考えてたREST APIは叩いてないけどまぁいいでしょう。自動実行でコマンドの結果をもってくるという、運用や構築フェーズでありがちなアプリを作りました。
学習資料
- たった 1日で基本が身に付く! Python超入門
過去の投稿
- Python はじめから勉強 Hour1:Hello World
- Python はじめから勉強 Hour2:制御文
- Python はじめから勉強 Hour3:関数
- Python はじめから勉強 Hour4:オブジェクト指向①
- Python はじめから勉強 Hour5:オブジェクト指向②
- Python はじめから勉強 Hour6:よく使うデータ型:タプル型・セット型・辞書型
- Python はじめから勉強 Hour7:クラスの使い方
- Python はじめから勉強 Hour8:パッケージの利用
- Python はじめから勉強 Hour9:ファイルの読み書き
- Python はじめから勉強 Hour10:アプリケーションの作成
get-cvm.py
applicationの概要
目的
- 特定のサーバ(今回はNutanix CVM)へアクセスして指定したコマンドの実行結果を表示する
- 対象のサーバのIPアドレス/ユーザ名/パスワードを指定したら、指定したコマンドの結果を出力する
- 対象のサーバやコマンドは変更することが多いため設定ファイルファイルとして別ファイルで指定する
想定する環境
- スクリプト実行端末と実行結果が欲しいサーバ
- サーバはNutanix CVM(Cluster IP)を想定 ※他のLinuxで動かなくても仕方なし
- 当然2台の関係はreachable
- Qiitaってフローチャート書けないの?画像貼るのめんどくさい
プログラムの流れ
- 設定ファイルを読み込む
- common.txt
- command_list.txt
- サーバにsshしてしたコマンドを実行する
- command_list.txtがなくなるまで繰り返す(サーバで取得したいコマンドが複数ある場合も想定した作りにしたい)
重要個所をテスト実装する
- まずは完璧を目指さずに主要な機能ができるか試していきます
サーバに接続してコマンドを実行する
-
これはparamikoの出番です。
-
ParamikoとはPythonでSSHを使うためのライブラリです。
'python ssh
でぐぐるといろんな実装がヒットするでしょう。真似していきましょう -
Paramikoのインストール
- Pythonインストール後、コマンドプロンプトから下記を実行すると、paramikoがインストールできます
pip install paramiko
get-cvm.py
- 細かいことは置いといて、拾ってきたスクリプトを加工してやってみましょう
import paramiko
ip = 'X.X.X.1'
user_name = 'nutanix'
password = 'nutanix/4u'
command = '/usr/local/nutanix/bin/acli host.list'
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(ip, username=user_name, password=password, timeout=3.0)
(stdin, stdout, stderr) = client.exec_command(command)
output = stdout.read().decode()
client.close()
print(output)
実行結果
- 結果中身は期待した通り
- ひとまずベーシックな処理はできそうです
C:\script\get-cvm>get-cvm.py
Hypervisor IP Hypervisor DNS Name Host UUID Compute Only Schedulable Hypervisor Type Hypervisor Name
x.x.x.5 x.x.x.5 8dc18013-8ce0-4337-ac60-132e655f1560 False True kKvm AHV
x.x.x.6 x.x.x.6 5817f793-b820-46ed-9faf-de6162a4d2ac False True kKvm AHV
x.x.x.7 x.x.x.7 716216d9-fff6-4137-9e1b-36a0d2812836 False True kKvm AHV
x.x.x.8 x.x.x.8 3fe758b3-6376-4526-b7cd-118e852d492c False True kKvm AHV
C:\script\get-cvm>
Paramikoについて
- Paramikoの使い方はググって欲しいですが(詳しくないので...)、ここで使ったメソッドなどを記載
- ParamikoとはPythonでSSHを使うためのライブラリです。
- 先ほどのコードにコメントを入れてみました。
import paramiko # paramikoのモジュールをインポートし、このプログラムで使えるようにします
# 接続するための準備
client = paramiko.SSHClient() # SSHClientクラスのインスタンスを作成
# hostname hostキーの登録を省略するため(sshでの接続しますか?yes/noの短縮)
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# SSHClientクラスのconnectメソッドを使って接続する
client.connect(ip, username=user_name, password=password, timeout=3.0)
# exec_commandメソッドでコマンドを実行し戻り値に入れる
(stdin, stdout, stderr) = client.exec_command(command)
# ファイル読み込みなどと同じようにreadメソッドが使える
# Readメソッドはバイナリを返すのでデコード(デフォルトUTF-8)して文字列へ
output = stdout.read().decode()
# closeメソッドで切断
client.close()
# 読み込んだ結果を出力
print(output)
本番プログラムを作る
-
先ほどの1ファイルでのスクリプトでもやりたいことは満たすのですが、下記のような欠点があります。
- IPやIDなどがプログラムに直書き:サーバが変わるとプログラムを直接編集する必要があり不要なミスを引き起こす可能性あり
- コマンドも変更する可能性が高い。複数コマンド実行したい
-
上記のことを解決するため
- 設定値は外出しにする:別ファイルで定義(common.json, command_list.txt)
- ※コマンドリストはテキストファイルで1行1コマンドが分かりやすいのかと思いjsonにしていません(違うかな?)
- クラスを作成する
- 処理と振る舞いを分けるためにメイン処理、Paramikoにお任せするところは分けて実装する
- 設定値は外出しにする:別ファイルで定義(common.json, command_list.txt)
-
作るファイルはこちら
-
cvm_get.py :メイン処理(設定ファイルの読み込みと、Paramikoの実行)
-
remote_command.py:paramikoを使った処理(名前思いつかん)
-
common.json :設定ファイル1(サーバ情報を定義)
-
command_list.txt :設定ファイル2(コマンド一覧を定義)
-
設定ファイルの読み込み
- 今までJSONファイル読み込んだことがなかったので、調べてみる
common.json
- なんかNutanix専用の変数名にしてしまった...
{
"cluster_address": "1.1.1.1",
"user_name": "nutanix",
"cvm_password": "hogehoge"
}
get-cvm.py
- jsonモジュールにお任せすれば良さそう
import json
json_open = open('common.json', 'r')
sv_info = json.load(json_open)
print(sv_info)
get-cvm.py実行結果
- おお、なんかそれっぽい。
C:\script\get-cvm>print_json.py
{'prism_address': '1.1.1.1', 'user_name': 'nutanix', 'cvm_password': 'hogehoge'}
- 値も取り出してみましょう
import json
json_open = open('common.json', 'r')
sv_info = json.load(json_open)
print(sv_info)
print(sv_info['cluster_address'])
print(sv_info['user_name'])
print(sv_info['cvm_password'])
- おお、いい感じ。jsonファイルから設定を読み込めそうです。
C:\script\get-cvm>print_json.py
{'cluster_address': '1.1.1.1', 'user_name': 'nutanix', 'cvm_password': 'hogehoge'}
1.1.1.1
nutanix
hogehoge
クラス作成(remote_command.py)
- 良く分からないが関数にしてみた
import paramiko
class RemoteCommand:
def get_df(ip, user, password, command):
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
client.connect(ip, username=user, password=password, timeout=3.0)
(stdin, stdout, stderr) = client.exec_command(command)
output = stdout.read().decode()
client.close()
return output
メイン処理の作成
import json
import remote_command
# ファイルの読み込み
fin = open('command_list.txt', 'r')
json_open = open('common.json', 'r')
# コマンドリストの読み込み
fin = open('command_list.txt', 'r')
command = fin.read()
fin.close()
# サーバ情報の読み込み
sv_info = json.load(json_open)
cluster_ip = sv_info['cluster_address']
user_name = sv_info['user_name']
password = sv_info['cvm_password']
## リモート実行。メイン処理
def main():
remote_obj = remote_command.RemoteCommand()
ret = remote_obj.get_df(cluster_ip, user_name, password, command)
print(ret)
# 分からん。おまじないっぽい
if __name__ == '__main__':
main()
- 実行結果
C:\script\get-cvm>get-cvm.py
Hypervisor IP Hypervisor DNS Name Host UUID Compute Only Schedulable Hypervisor Type Hypervisor Name
x.x.x.5 x.x.x.5 8dc18013-8ce0-4337-ac60-132e655f1560 False True kKvm AHV
x.x.x.6 x.x.x.6 5817f793-b820-46ed-9faf-de6162a4d2ac False True kKvm AHV
x.x.x.7 x.x.x.7 716216d9-fff6-4137-9e1b-36a0d2812836 False True kKvm AHV
x.x.x.8 x.x.x.8 3fe758b3-6376-4526-b7cd-118e852d492c False True kKvm AHV
- おお、動いた。
- 今回の勉強やら、ネットやら調べてここまでできました。
- メイン処理がもっとコンパクトに書けるかと思ったけど、まぁいいでしょう。
改修
-
そういえばcommand list って言っときながら、1コマンドだけだったので改修
-
ファイルを読み込んでlistメソッド取り込む
-
結構インデントに厳しいな
-
変数名むずい。センスいるな
メイン処理:get-cvm.py
import json
import remote_command
# ファイルの読み込み
fin = open('command_list.txt', 'r')
json_open = open('common.json', 'r')
# コマンドリストの読み込み
fin = open('command_list.txt', 'r')
command = fin.readlines()
fin.close()
# サーバ情報の読み込み
sv_info = json.load(json_open)
cluster_ip = sv_info['cluster_address']
user_name = sv_info['user_name']
password = sv_info['cvm_password']
# リモート実行
def main():
# 2行追加。リストの中身がなくなるまで処理する。
for name in command:
print('===========<', name)
remote_obj = remote_command.RemoteCommand()
ret = remote_obj.get_df(cluster_ip, user_name, password, name)
print(ret)
if __name__ == '__main__':
main()
実行結果
- 複数のコマンドを一度に取ってくる。実行したコマンドもわかるようにした。
C:\script\get-cvm>get-cvm.py
===========< /usr/local/nutanix/bin/acli host.list
Hypervisor IP Hypervisor DNS Name Host UUID Compute Only Schedulable Hypervisor Type Hypervisor Name
x.x.x.5 x.x.x.5 8dc18013-8ce0-4337-ac60-132e655f1560 False True kKvm AHV
x.x.x.6 x.x.x.6 5817f793-b820-46ed-9faf-de6162a4d2ac False True kKvm AHV
x.x.x.7 x.x.x.7 716216d9-fff6-4137-9e1b-36a0d2812836 False True kKvm AHV
x.x.x.8 x.x.x.8 3fe758b3-6376-4526-b7cd-118e852d492c False True kKvm AHV
===========< /usr/local/nutanix/cluster/bin/svmips
x.x.x.9 x.x.x.10 x.x.x.11 x.x.x.12
===========< ~/prism/cli/ncli cluster info
Cluster Id : 0005979e-89ec-3815-0000-000000017833::96307
Cluster Uuid : 0005979e-89ec-3815-0000-000000017833
Cluster Name : hogehoge
Cluster Version : 5.15
Cluster Full Version : el7.3-release-euphrates-5.15-stable-4fbdd4d9de331230bb468b3549f530e80ab53bb9
External IP address : x.x.x.13
Node Count : 4
Block Count : 1
Shadow Clones Status : Enabled
Has Self Encrypting Disk : no
Cluster Masquerading I... :
Cluster Masquerading PORT :
Is registered to PC : true
Is LTS : true
External Data Services... : x.x.x.14
Support Verbosity Level : BASIC_COREDUMP
Lock Down Status : Disabled
Password Remote Login ... : Enabled
Timezone : Asia/Tokyo
NCC Version : ncc-3.9.4.1
Common Criteria Mode : Disabled
Degraded Node Monitoring : Enabled
- おお、っぽくなった。
まとめ
- 今回作ったものは、参考となるスクリプトがありましたが、1から勉強することでかなり理解度が高まりました。
- 理解度が高まったことで、自分が行いたいことも、わりとすんなり実装できました。
- これをアプリケーションと呼んでいいか分かりませんが、再利用しやすい形にできたと思います
- まだお作法などが分からず、変数名もイケてないし、書き方も変ですが、自分的には大満足
まとめのまとめ
-
基本めっちゃ大事
-
Python、奥が深いけど簡単!!(と、言い聞かせる)
-
手を動かしながら勉強するのめっちゃ大事
-
たった 1日で基本が身に付く! Python超入門を基に勉強しながら作ってみました。
-
さっと読むと3時間ぐらいで読めますが、じっくり Hello Worldから行うと20時間ぐらいかかりました。
-
が、たった20時間でここまでできるならやった方がいいですね。私のやり方はこんな感じ
- 本を見る
- サンプルのスクリプトを動かす(コピペでも)
- 考えながら2のスクリプトを修正してみる(自分がやってみたいことを書く。背伸びしすぎない)
- ネットでも調べる(言い回しや、メソッドは他のサイトでどんなか見てみる)