ソースコードから見るVagrantのネットワーク(2)
今回は前回のnetwork_ip.rbと同じくnetwork.rbから外部モジュールとして呼び出されているscoped_hash_override.rbを見てみましょう。
https://github.com/mitchellh/vagrant/blob/8747d938aa37e02abc20c870bb9b866a5726bc6b/lib/vagrant/util/scoped_hash_override.rb
このなかでは1つだけメソッドが定義されています。
scoped_hash_override(origianl,scope)
このメソッドはハッシュを操作するメソッドで、ソースコードには以下の例が記載されています。 ハッシュoriginalからscopeで指定した文字列に一致した要素を抜き出し新たなハッシュを作り出すようです。
# This allows for hash options to be overridden by a scope key # prefix. An example speaks best here. Imagine the following hash: # # original = { # :id => "foo", # :mitchellh__id => "bar", # :mitchellh__other => "foo" # } # # scoped = scoped_hash_override(original, "mitchellh") # # scoped == { # :id => "bar", # :other => "foo" # } #
それではソースコードを見ていきましょう。
まず引数のscopeをto_s
メソッドで文字列に変換し、ハッシュorigianlをコピーしてresultに格納します。次以降で説明する処理でハッシュoriginalの要素に行った処理をここでコピーしたハッシュresultに作用させていきます。
scope = scope.to_s result = original.dup
次に元のハッシュoriginalの各要素に対して繰り返し処理をしていきます。
original.each do |key, value| parts = key.to_s.split("__", 2) # If we don't have the proper parts, then bail next if parts.length != 2 # If this is our scope, then override if parts[0] == scope result[parts[1].to_sym] = value end end
まずkeyをto_s
メソッドで文字列に変換した上でsplit
メソッドで配列にして返します。
split
メソッドはsplit(pattern,[limit])
とptternとlimitを引数にとり、patternを区切り文字で文字列を分割し、limitで指定した数字に配列の要素数を押さえます。ここではsplit("__",2)
なので文字列「__」を区切り文字、要素を2つまでに押さえます。
http://ref.xaio.jp/ruby/classes/string/split
ソースコードのハッシュoriginalの例では以下のように処理されます。
①:id ->:id ②:mitchellh__id ->:mitchellh, :id ③:mitchellh__other ->:mitchellh, :other
次の制御構造のnext
でif以下の条件に合致した場合は繰り返し処理を飛ばします。
next if parts.length != 2
ここではparts.length != 2
という条件なので、keyを分割(split)して作成した配列partsの要素が2以外であれば以降の処理はされずに次のkeyの処理を行います。前述のハッシュ関数の例だと①は要素が1つなので処理が飛ばされ②の処理に移ります。 ②は要素が2つなので次の処理に進みます。
次の処理では配列partsの1つ目の要素がscopeかどうかがifの条件式となっています。
if parts[0] == scope
例ではmitchellhなので②はこの条件式に合致します。その場合は次の処理がされます。
result[parts[1].to_sym] = value
配列の2番目の要素をシンボルにしてハッシュresultにハッシュoriginalのvalueを入れます。②ではresult[:id] = "bar"
となります。このとき:idは①と同じなので、id => "foo"
はid => "bar"
に上書きされます。
③ではresult[:other] = "foo"
なので:otherがハッシュ内で重複しないので単純に追加されます。
最後にscoped_hash_override
メソッドはハッシュresultを返り値として返します。
ハッシュresultは以下になりソースコードのハッシュの比較結果はfalseになってしまいます。。。scoped == {〜となっていてハッシュを比較しているのか、「=」を1つの間違いかなのかはわからなかったです。
# result = { # :id => "bar", # :mitchellh__id => "bar", # :mitchellh__other => "foo", # :other => "foo" # }
testコードをみるとこの動きで正しそうでした。 https://github.com/mitchellh/vagrant/blob/8747d938aa37e02abc20c870bb9b866a5726bc6b/test/unit/vagrant/util/scoped_hash_override_test.rb
ソースコードから見るVagrantのネットワーク(1)
Vagrantはrubyで書かれているのでプログラム経験のないど素人の私でも眺めているとなんとなくわかる部分があります。そこでソースコードからVagrantでどのようにゲストOSのネットワーク設定をしているのか見てみたいと思います。
Vagrantのネットワーク設定はnetwork.rbに記述されています。
https://github.com/mitchellh/vagrant/blob/master/plugins/providers/virtualbox/action/network.rb
500行弱の短いコードですが、今回は肩ならしとしてnetwork.rbから外部モジュールとして呼び出されているnetwork_ip.rbを見てみたいと思います。
https://github.com/mitchellh/vagrant/blob/master/lib/vagrant/util/network_ip.rb
network_ip.rbはネットワークアドレスを取得するためのモジュールです。 network_addressメソッドとip_partsメソッドの2つで構成されています。
ip_partsメソッド
ip_partsメソッドはIPアドレスをオクテットごとの配列として返すメソッドです。
def ip_parts(ip) ip.split(".").map { |i| i.to_i } end
ip.split(".")の部分でsplitメソッドを使って、IPアドレスの文字列を引数に"."を区切り文字として配列を返している。
http://ref.xaio.jp/ruby/classes/string/split
~irbを使用した出力例~ irb(main):001:0> ip = "192.168.1.1" => "192.168.1.1" irb(main):002:0> p ip.split(".") ["192", "168", "1", "1"] => ["192", "168", "1", "1"]
続いてmapメソッドを使い、文字列の配列を数値の配列に変換します。
mapメソッドは配列の各要素(item)を取り出しblockを実行し、blockの戻り値を集めた配列を
作成して返します。
http://ref.xaio.jp/ruby/classes/array/map
array.map{|item|block}
~irbを使用した出力例~ irb(main):003:0> p ip.split(".").map{|i|i.to_i} [192, 168, 1, 1] => [192, 168, 1, 1]
blockで使用しているto_iは文字列を10進数の整数に変換するメソッドです。
http://ref.xaio.jp/ruby/classes/string/to_i
network_addressメソッド
続いてnetwork_addressメソッドです。
def network_address(ip, subnet) ip = ip_parts(ip) netmask = ip_parts(subnet) ip.map { |part| part & netmask.shift }.join(".") end
ipとsubnetの2つの引数をさきほど定義したip_partsメソッドでIPアドレス(もしくはサブネットマスク)
の文字列をオクテットごとの数字の配列に変換しています。
配列ipをip_partsメソッドでも利用したmapメソッドで配列の要素ごとにある処理をしていきます。ここでしている処理とはまず配列netmaskをshiftメソッドで配列の要素をひとつひとつ取り出していきます。
http://ref.xaio.jp/ruby/classes/array/shift
~irbを使用した出力例~ irb(main):002:0> netmask = [255,255,255,0] => [255, 255, 255, 0] irb(main):003:0> netmask.shift => 255 irb(main):004:0> netmask => [255, 255, 0] irb(main):005:0> netmask.shift => 255 irb(main):006:0> netmask => [255, 0]
続いて取り出してきた要素を配列ipとビット演算をします。
http://www9.plala.or.jp/sgwr-t/c/sec14.html
~irbを使用した出力例~ irb(main):001:0> 192 & 255 => 192 irb(main):002:0> 168 & 255 => 168 irb(main):003:0> 1 & 255 => 1 irb(main):004:0> 1 & 0 => 0 irb(main):001:0> ip = [192,168,1,1] => [192, 168, 1, 1] irb(main):002:0> netmask = [255,255,255,0] => [255, 255, 255, 0] irb(main):003:0> ip.map{|part|part & netmask.shift} => [192, 168, 1, 0]
最後に得られた配列をjoinメソッドを用いて結合します。
http://ref.xaio.jp/ruby/classes/array/join
~irbを使用した出力例~ irb(main):008:0> [192,168,1,0].join(".") => "192.168.1.0"
これでIPアドレスとネットマスクからネットワークアドレスが取得できました。
サーバ技術者養成講座をChefでやってみた(4)OSインストールからVagrant用BOXファイル作成まで その2
前回はOSインストールからVagrant用BOXファイル作成の流れをまとめました。今回から実際の流れを見てみます。 まずはVirtualBOXの新規マシンを作成します。
注意するポイントを挙げておきます。
- ディスク:20GB(ファイルタイプはVMDK)で今後十分な領域をアサインできるように「可変サイズ」が推奨されています。
- メモリ:1GB
- ネットワーク:NAT ポートフォワードで接続するため必須
- その他:USBコントローラー、オーディオを無効化
はじめにVirtualBOXの新規ボタンを押して、名前(ここではSETE_originとしました)を入力し、メモリサイズを1024MBと入力して作成ボタンを押します。バージョンはCentOSの32bitをインストールするためRedHat(32bit)を選択します。
続いてファイルサイズを20GBと入力し、ファイルタイプがVMDK、ストレージが可変サイズであることを確認して作成ボタンを押します。
作成した仮想マシンの設定ボタンからその他の項目を設定します。
USBコントローラを有効化のチェックボックスを外す。
さらにオーディオを有効化のチェックボックスを外す。
ネットワークの設定は割り当てをNATにしておきます。
OKを押して仮想マシンの設定を終え、仮想マシンを起動する。
ディスクの選択画面でダウンロードしておいたCentOS 5.5のisoイメージファイルを選択する。
サーバ技術者養成講座をChefでやってみた(3)OSインストールからVagrant用BOXファイル作成まで その1
原著では物理サーバへのインストールとなっていますが、ここではChefで構築していくためVirtual Boxの仮想OSとしてインストールします。また、Immutable Infrastructureっぽくするため作成した仮想OSをVagrantのBase BOX(仮想OSのテンプレート)とします。
大きな流れは以下の通りです。
- Virtual Boxの仮想マシンを新規作成する。
- 仮想マシンにCentOS5.5をインストールする。
- 仮想OSにVagrantのBase BOXとするための設定をする。
- 仮想OSをBase BOX化する。
CentOS5.5のインストールはサーバ技術者養成講座の5章にそって行いますが、Base BOXとするため加えて以下の設定やインストールをしていきます。
- User設定、Permission設定
- Virtual Box Guest Additionsのインストール(Vagrantでのファイル共有、ポートフォワードのため)
- SSHの設定(VagrantからゲストOSへ接続するため)
- Ruby,RubyGemsのインストール(Chefをインストールするため)
- Chefのインストール(プロビジョニングのため)
VagrantのBase Box作成は以下の公式ドキュメントを参考にしています。
https://docs.vagrantup.com/v2/boxes/base.html
v1のdocumentの方が詳細にかかれているのでこちらも参考にしながら。
http://docs-v1.vagrantup.com/v1/docs/base_boxes.html
サーバ技術者養成講座をChefでやってみた(2)Chefの準備(後編)
前回に続いてChefの準備です。今回でChefの準備が完了です。
knife-soloをインストールします。
mba:~ user1$ sudo gem install knife-solo Password: Fetching: mixlib-config-2.1.0.gem (100%) Successfully installed mixlib-config-2.1.0 Fetching: mixlib-cli-1.5.0.gem (100%) Successfully installed mixlib-cli-1.5.0 Fetching: mixlib-log-1.6.0.gem (100%) Successfully installed mixlib-log-1.6.0 Fetching: mixlib-authentication-1.3.0.gem (100%) Successfully installed mixlib-authentication-1.3.0 Fetching: mixlib-shellout-1.4.0.gem (100%) Successfully installed mixlib-shellout-1.4.0 Fetching: mime-types-1.25.1.gem (100%) Successfully installed mime-types-1.25.1 Fetching: systemu-2.5.2.gem (100%) Successfully installed systemu-2.5.2 Fetching: yajl-ruby-1.2.0.gem (100%) Building native extensions. This could take a while... /System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/lib/ruby/2.0.0/rubygems/ext/builder.rb:54: warning: Insecure world writable dir /usr/local/bin in PATH, mode 040777 Successfully installed yajl-ruby-1.2.0 Fetching: ipaddress-0.8.0.gem (100%) Successfully installed ipaddress-0.8.0 Fetching: ohai-7.0.4.gem (100%) Successfully installed ohai-7.0.4 Fetching: rest-client-1.6.7.gem (100%) Successfully installed rest-client-1.6.7 Fetching: net-ssh-2.9.0.gem (100%) Successfully installed net-ssh-2.9.0 Fetching: net-ssh-gateway-1.2.0.gem (100%) Successfully installed net-ssh-gateway-1.2.0 Fetching: net-ssh-multi-1.2.0.gem (100%) Successfully installed net-ssh-multi-1.2.0 Fetching: highline-1.6.21.gem (100%) Successfully installed highline-1.6.21 Fetching: erubis-2.7.0.gem (100%) Successfully installed erubis-2.7.0 Fetching: diff-lcs-1.2.5.gem (100%) Successfully installed diff-lcs-1.2.5 Fetching: hashie-2.1.1.gem (100%) Successfully installed hashie-2.1.1 Fetching: rack-1.5.2.gem (100%) Successfully installed rack-1.5.2 Fetching: chef-zero-2.0.2.gem (100%) Successfully installed chef-zero-2.0.2 Fetching: coderay-1.1.0.gem (100%) Successfully installed coderay-1.1.0 Fetching: slop-3.5.0.gem (100%) Successfully installed slop-3.5.0 Fetching: method_source-0.8.2.gem (100%) Successfully installed method_source-0.8.2 Fetching: pry-0.9.12.6.gem (100%) Successfully installed pry-0.9.12.6 Fetching: chef-11.12.4.gem (100%) Successfully installed chef-11.12.4 Fetching: knife-solo-0.4.1.gem (100%) Thanks for installing knife-solo! If you run into any issues please let us know at: https://github.com/matschaffer/knife-solo/issues If you are upgrading knife-solo please uninstall any old versions by running `gem clean knife-solo` to avoid any errors. See http://bit.ly/CHEF-3255 for more information on the knife bug that causes this. Successfully installed knife-solo-0.4.1 Parsing documentation for mixlib-config-2.1.0 Installing ri documentation for mixlib-config-2.1.0 Parsing documentation for mixlib-cli-1.5.0 Installing ri documentation for mixlib-cli-1.5.0 Parsing documentation for mixlib-log-1.6.0 Installing ri documentation for mixlib-log-1.6.0 Parsing documentation for mixlib-authentication-1.3.0 Installing ri documentation for mixlib-authentication-1.3.0 Parsing documentation for mixlib-shellout-1.4.0 Installing ri documentation for mixlib-shellout-1.4.0 Parsing documentation for mime-types-1.25.1 Installing ri documentation for mime-types-1.25.1 Parsing documentation for systemu-2.5.2 Installing ri documentation for systemu-2.5.2 Parsing documentation for yajl-ruby-1.2.0 unable to convert "\xCA" from ASCII-8BIT to UTF-8 for lib/yajl/yajl.bundle, skipping Installing ri documentation for yajl-ruby-1.2.0 Parsing documentation for ipaddress-0.8.0 Installing ri documentation for ipaddress-0.8.0 Parsing documentation for ohai-7.0.4 Installing ri documentation for ohai-7.0.4 Parsing documentation for rest-client-1.6.7 Installing ri documentation for rest-client-1.6.7 Parsing documentation for net-ssh-2.9.0 Installing ri documentation for net-ssh-2.9.0 Parsing documentation for net-ssh-gateway-1.2.0 Installing ri documentation for net-ssh-gateway-1.2.0 Parsing documentation for net-ssh-multi-1.2.0 Installing ri documentation for net-ssh-multi-1.2.0 Parsing documentation for highline-1.6.21 Installing ri documentation for highline-1.6.21 Parsing documentation for erubis-2.7.0 Installing ri documentation for erubis-2.7.0 Parsing documentation for diff-lcs-1.2.5 Installing ri documentation for diff-lcs-1.2.5 Parsing documentation for hashie-2.1.1 Installing ri documentation for hashie-2.1.1 Parsing documentation for rack-1.5.2 Installing ri documentation for rack-1.5.2 Parsing documentation for chef-zero-2.0.2 Installing ri documentation for chef-zero-2.0.2 invalid options: -SNw2 (invalid options are ignored) Parsing documentation for coderay-1.1.0 Installing ri documentation for coderay-1.1.0 Parsing documentation for slop-3.5.0 Installing ri documentation for slop-3.5.0 Parsing documentation for method_source-0.8.2 Installing ri documentation for method_source-0.8.2 Parsing documentation for pry-0.9.12.6 Installing ri documentation for pry-0.9.12.6 Parsing documentation for chef-11.12.4 Installing ri documentation for chef-11.12.4 Parsing documentation for knife-solo-0.4.1 Installing ri documentation for knife-solo-0.4.1 26 gems installed
gem listで見てみます。
mba:~ user1$ gem list
*** LOCAL GEMS ***
~省略~
chef (11.12.4)
chef-zero (2.0.2)
~省略~
knife-solo (0.4.1)
~省略~
ohai (7.0.4)
~省略~
knifeコマンドの設定をします。いろいろと聞かれますが、デフォルトでよいのでリターンを連打します。
mba:~ user1$ knife configure WARNING: No knife configuration file found /Library/Ruby/Gems/2.0.0/gems/chef-11.12.4/lib/chef/mixin/path_sanity.rb:25: warning: Insecure world writable dir /usr/local/bin in PATH, mode 040777 Where should I put the config file? [/Users/user1/.chef/knife.rb] Please enter the chef server URL: https://mba.local:443 Please enter an existing username or clientname for the API: [user1] Please enter the validation clientname: [chef-validator] Please enter the location of the validation key: [/etc/chef-server/chef-validator.pem] Please enter the path to a chef repository (or leave blank): ***** You must place your client key in: /Users/user1/.chef/user1.pem Before running commands with Knife! ***** You must place your validation key in: /etc/chef-server/chef-validator.pem Before generating instance data with Knife! ***** Configuration file written to /Users/user1/.chef/knife.rb
サーバ技術者養成講座をChefでやってみた(1)Chefの準備(前編)
サーバ技術者養成講座という本があります。この本ではサーバのインストールからさまざまなソフトの構築が学習できるのですが、これをChefで再現してみました。
環境ですが、Mac(OS X 10.9.2)、Virtual Box(4.3.10 r93012)、Vagrant(1.5.2)です。
まずはMacにChefのインストールするところから。
ここを参考にさせてもらいました。
http://dotinstall.com/lessons/basic_chef/24203
rubyとgemのVersionを確認します。
mba:~ user1$ruby -v ruby 2.0.0p451 (2014-02-24 revision 45167) [universal.x86_64-darwin13] mba:~ user1$gem -v 2.0.14
つづいてChefをインストールします。公式サイトのget startedに記述があります。
https://learnchef.opscode.com/get-started/
実際にインストールしたときの出力です。
mba:~ user1$ curl -L https://www.opscode.com/chef/install.sh | sudo bash % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 15934 100 15934 0 0 14192 0 0:00:01 0:00:01 --:--:-- 14201 Downloading Chef for mac_os_x... downloading https://www.opscode.com/chef/metadata?v=&prerelease=false&nightlies=false&p=mac_os_x&pv=10.9&m=x86_64 to file /tmp/install.sh.22409/metadata.txt trying curl... url https://opscode-omnibus-packages.s3.amazonaws.com/mac_os_x/10.7/x86_64/chef-11.12.4-1.dmg md5 255c9c372780c199851e52d8594ac86a sha256 eaaf2a684328d8054bbf84080952d312bbbc34f143df142162b005daf191ff03 downloaded metadata file looks valid... downloading https://opscode-omnibus-packages.s3.amazonaws.com/mac_os_x/10.7/x86_64/chef-11.12.4-1.dmg to file /tmp/install.sh.22409/chef-11.12.4-1.dmg trying curl... Comparing checksum with shasum... Installing Chef installing dmg file... Protective Master Boot Record (MBR : 0) のチェックサムを計算中... Protective Master Boot Record (MBR ::検証済み CRC32 $A63E199D GPT Header (Primary GPT Header : 1) のチェックサムを計算中... GPT Header (Primary GPT Header : 1):検証済み CRC32 $5CEC083F GPT Partition Data (Primary GPT Table : 2) のチェックサムを計算中... GPT Partition Data (Primary GPT Tabl:検証済み CRC32 $21A51859 (Apple_Free : 3) のチェックサムを計算中... (Apple_Free : 3):検証済み CRC32 $00000000 disk image (Apple_HFS : 4) のチェックサムを計算中... .................................................................................................. disk image (Apple_HFS : 4):検証済み CRC32 $83B50227 (Apple_Free : 5) のチェックサムを計算中... (Apple_Free : 5):検証済み CRC32 $00000000 GPT Partition Data (Backup GPT Table : 6) のチェックサムを計算中... GPT Partition Data (Backup GPT Table:検証済み CRC32 $21A51859 GPT Header (Backup GPT Header : 7) のチェックサムを計算中... GPT Header (Backup GPT Header : 7):検証済み CRC32 $C3215791 検証済み CRC32 $7A616D64 /dev/disk2 GUID_partition_scheme /dev/disk2s1 Apple_HFS /Volumes/chef_software installer: Package name is Chef Client installer: Installing at base path / installer: The install was successful. "disk2" unmounted. "disk2" ejected.
つづいてknife-soloのインストールしますが、長くなったので次回へ。