クラウド時代の分散マシン操作ライブラリ Svengali - サンプルコード

( クラウド時代の分散マシン操作ライブラリ Svengali )


以下のような構成のマシン群があったとします。

  • ・管理用マシン: 1台
    • ・ここで下のプログラムを実行
  • ・被管理(操作?)マシン: 3台
    • ・sunagimo01: 192.168.2.1
    • ・sunagimo02: 192.168.2.2
    • ・sunagimo03: 192.168.2.3
    • < 全てのマシンに,ユーザ:taro,パスワード:bar でログインできる >
    • < 被管理マシンではsshとsftpさえ通れば良い >


ここで,全てのマシンに対して

  • 1.全てのマシンに対してパッケージをインストール
  • 2.設定ファイルの編集
  • 3.実験プログラムの実行
    • ・管理用マシンの/home/taro/scenario.shを転送し実行
      • ・echo "`hostname`: Hello svengali!!"
  • #各ステップは各マシンについて逐次で実行


を行うプログラムは以下のように書けます。

#! /bin/ruby

require "rubygems"
require "svengali"

user_name = "taro"
password = "bar"
#連番でアクセスするためにあえてIPアドレスで指定
IPADDR_BASE = CLibIPAddr.new("192.168.2.1")

MACHINE_NUM = 3
nodes = Array.new(MACHINE_NUM)

tmp_ipaddr = IPADDR_BASE.dup()
MACHINE_NUM.times{ |n|
  #ホストネームでの指定も可
  nodes[n] = Machine.new(tmp_ipaddr)
  nodes[n].set_auth_info(user_name,password)
  #コマンドの発行が可能な通信路を確保する
  nodes[n].establish_session() 
  #インストールするパッケージは適当
  puts nodes[n].install_package("openmpi") 
  tmp_ipaddr.inc!()
}

nodes.each{ |a_node|
    #設定ファイル(sshd_config)を編集
    sshd_conf = a_node.get_config_file("/etc/ssh/sshd_config")
    #行う設定も適当
    sshd_conf.replace_col("X11Forwarding yes","X11Forwarding no") 
    sshd_conf.save()
}

#実験開始
nodes.each{ |a_node|
   #おまけ
   puts a_node.exec!("uname -a")
   #実験用のスクリプトを実行
   puts a_node.exec_script_on("/home/taro/scenario.sh","","/home/taro")
}


実行結果

$ruby test_svengali.rb
(yumの出力が延々と続くので省略)


Linux sunagimo01 2.6.32-22-generic #33-Ubuntu SMP Wed Jan 21 10:44:23 EST 2009
sunagimo01: Hello svengali!!
Linux sunagimo02 2.6.32-22-generic #33-Ubuntu SMP Wed Jan 21 10:44:35 EST 2009
sunagimo02: Hello svengali!!
Linux sunagimo03 2.6.32-22-generic #33-Ubuntu SMP Wed Jan 21 10:44:47 EST 2009
sunagimo03: Hello svengali!!


ネットワーク回りの設定処理は,以下のように書けます。

(上のコードと一緒の部分は省略)


gateway_addr = CLibIPAddr.new("xxx.xxx.xxx.xxx")
dns_addr = CLibIPAddr.new("xxx.xxx.xxx.xxx")
netmask_addr = CLibIPAddr.new("xxx.xxx.xxx.xxx")

CHANGED_IPADDR_BASE = CLibIPAddr.new("xxx.xxx.xxx.xxx")
tmp_ipaddr = CHANGED_IPADDR_BASE.dup()
nodes.each{ |a_node|
   #連番でIPアドレスを(静的に)設定
   a_node.config_nw_interface(:ipaddr => tmp_ipaddr , :interface => "eth0", :netmask => netmask_addr, :gateway => gateway_addr, :onboot => "yes")
   a_node.set_resolver(:primary_ip => dns_addr)

   #各ノード上のネットワーク設定をリロードさせる
   #10秒後にnilを返して抜ける(タイムアウトは実装上の問題を回避するため)
   puts a_node.exec!("/sbin/service network restart", 10)
   tmp_ipaddr.inc!()
}

#新しいアドレスを用いて再接続
tmp_ipaddr = CHANGED_IPADDR_BASE.dup()
nodes_changed = Array.new(MACHINE_NUM)
nodes_changed.each{ |a_node|
 a_node = Machine.new(tmp_ipaddr.to_s)
 a_node.set_auth_info(user_name,password)
 a_node.establish_session()
 tmp_ipaddr.inc!()

 puts a_node.exec!("/sbin/ifconfig eth0")
}