vagrant-cloudstack v1.0.0 の新機能紹介

2015/5/5にリリースされた[vagrant-cloudstack](https://github.com/schubergphilis/vagrant-cloudstack) v1.0.0で追加された主な新機能を例を交えて紹介します。

CHANGELOGは下記リンクを参照してください。

[CHANGELOG.md](https://github.com/schubergphilis/vagrant-cloudstack/blob/master/CHANGELOG.md)

# 概要

* スタティックNAT、ポートフォワーディング、ファイアウォールルールの設定
  * 任意のルールの設定が可能に 
  * SSH接続用ルール設定```pf_*``` の改善 
  * スタティックNATを使ったSSH接続
* rsync Synced Folder
  * rsync, rsync-autoコマンド
  * rsyncオプションのサポート
  * rsync自動インストール 

# 導入方法

## インストール

```vagrant plugin install``` コマンドでインストールできます。

```bash
$ vagrant plugin install vagrant-cloudstack
```

## ダミーボックス

レポジトリが変更になったため、ダミーボックスのURLも変更されています。

```bash
$ vagrant box add dummy https://github.com/schubergphilis/vagrant-cloudstack/raw/master/dummy.box
```

# スタティックNAT、ポートフォワーディング、ファイアウォールの作成

## 任意のルールが設定可能に

スタティックNAT、ポートフォワーディング、ファイアウォールルールの設定ができるようになりました。

以前からSSH接続用のポートフォワーディング、ファイアウォールの設定は可能でしたが、v1.0.0では任意のルールの設定が可能になっています。これにより、テスト用のサーバーを構築し社内で公開するといった使い方をしやすくなりました。

ルールの設定は```static_nat``` 、 ```port_forwarding_rules``` 、 ```firewall_rules``` を使用して以下のように行います。

```rb
cloudstack.static_nat = [{ :ipaddress => "X.X.X.X"}]

cloudstack.port_forwarding_rules = [
  { 
    :ipaddress => "X.X.X.X",
    :protocol => "tcp", :publicport => 22, :privateport  => 22,
    :openfirewall => false
  }
]

cloudstack.firewall_rules = [
  {
     :ipaddress => "X.X.X.X",
     :cidrlist  => "Y.Y.Y.Y/Y",
     :protocol => "tcp", :startport => 22, :endport => 22
   }
]
```

Vagrantfileで設定したルールは```vagrant destroy``` 実行時に仮想マシンとともに削除されます。

### 設定例

IDCFクラウドにApacheをインストールし外部に公開するVagrantfileは以下のように書けます。SSH接続用に22番ポート、Apache用に80番ポートを開放し、ポートフォワーディングルールを設定しています。

SSH接続用のルール設定を行った場合、```config.ssh.host``` にSSHに使用するIPを指定する必要があります。（どのルールがSSH接続用か判定できないため）

```rb:Vagrantfile
Vagrant.configure("2") do |config|
  config.vm.provider :cloudstack do |cloudstack, override|
    override.vm.box = "dummy"
    override.vm.box_url = "https://github.com/schubergphilis/vagrant-cloudstack/raw/master/dummy.box"

    cloudstack.host    = "compute.jp-east.idcfcloud.com"
    cloudstack.path    = "/client/api"
    cloudstack.port    = "443"
    cloudstack.scheme  = "https"

    cloudstack.api_key    = "#{ENV['CLOUDSTACK_API_KEY']}"
    cloudstack.secret_key = "#{ENV['CLOUDSTACK_SECRET_KEY']}"

    cloudstack.zone_name             = "pascal"
    cloudstack.template_name         = "CentOS 7.0 64-bit for Vagrant"
    cloudstack.service_offering_name = "light.S1"

    cloudstack.port_forwarding_rules = [
      { 
        :ipaddress => "#{ENV['PUBLIC_IP_ADDRESS']}",
        :protocol => "tcp", :publicport => 22, :privateport  => 22,
        :openfirewall => false
      },
      { 
        :ipaddress => "#{ENV['PUBLIC_IP_ADDRESS']}",
        :protocol => "tcp", :publicport => 80, :privateport  => 80,
        :openfirewall => false
      }
    ]

    cloudstack.firewall_rules = [
      { 
        :ipaddress => "#{ENV['PUBLIC_IP_ADDRESS']}",
        :cidrlist => "#{ENV['CIDR_LIST']}",
        :protocol => "tcp", :startport => 22, :endport  => 22,
      },
      { 
        :ipaddress => "#{ENV['PUBLIC_IP_ADDRESS']}",
        :cidrlist => "#{ENV['CIDR_LIST']}",
        :protocol => "tcp", :startport => 80, :endport  => 80,
      }
    ]

    cloudstack.keypair            = "#{ENV['CLOUDSTACK_SSH_KEYPAIR']}"
    override.ssh.host             = "#{ENV['PUBLIC_IP_ADDRESS']}" # SSHに使用するIPアドレスを指定
    override.ssh.private_key_path = "#{ENV['VAGRANT_SSH_PRIVATE_KEY']}"
  end

  config.vm.provision "shell" do |s|
    s.inline = <<-EOS
      yum -y install httpd
      systemctl start httpd
      echo Hello > /var/www/html/index.html
    EOS
  end
end
```

以下の環境変数を設定して```vagrant up``` してください。

```bash
export CLOUDSTACK_API_KEY='YOUR_API_KEY'
export CLOUDSTACK_SECRET_KEY='YOUR_SECRET_KEY'
export CLOUDSTACK_SSH_KEYPAIR='YOUR_SSH_KEY'                                             
export VAGRANT_SSH_PRIVATE_KEY='~/.ssh/id_rsa'                                     
                                                                                   
export PUBLIC_IP_ADDRESS='X.X.X.X'                                                 
export CIDR_LIST='Y.Y.Y.Y/Y'  
```

## SSH接続用ルール設定方法の改善

従来と同様```pf_*``` を使用してSSH用のルールを作成することも可能です。

v1.0.0では以下の設定が追加で使用可能になりました。

* pf_ip_address : ポートフォワーディングに使用するIPアドレスを指定
  * IDでなくIPアドレスで指定 
* pf_open_firewall : ファイアウォールを自動開放のフラグ(デフォルト: true)
  * ```true``` にした場合```pf_public_port``` で指定したポートが```0.0.0.0/0``` に対して開放されます

### 設定例

IDCFクラウドでApacheを公開する例を```pf_*``` を使って書き直すと以下のようになります。

SSH可能なIPアドレスをファイアウォールで制限するため```pf_open_firewall=false``` を設定したうえで、```firewall_rule``` でCIDRをしぼったルールを設定しています。```pf_*``` を使用した場合、```pf_ip_address_id``` または```pf_ip_address``` で指定したIPアドレスがSSHに使用されるため```config.ssh.host``` の設定は不要です。

```rb:Vagrantfile
Vagrant.configure("2") do |config|
  config.vm.provider :cloudstack do |cloudstack, override|
    override.vm.box = "dummy"
    override.vm.box_url = "https://github.com/schubergphilis/vagrant-cloudstack/raw/master/dummy.box"

    cloudstack.host    = "compute.jp-east.idcfcloud.com"
    cloudstack.path    = "/client/api"
    cloudstack.port    = "443"
    cloudstack.scheme  = "https"

    cloudstack.api_key    = "#{ENV['CLOUDSTACK_API_KEY']}"
    cloudstack.secret_key = "#{ENV['CLOUDSTACK_SECRET_KEY']}"

    cloudstack.zone_name             = "pascal"
    cloudstack.template_name         = "CentOS 7.0 64-bit for Vagrant"
    cloudstack.service_offering_name = "light.S1"

    cloudstack.port_forwarding_rules = [
      { 
        :ipaddress => "#{ENV['PUBLIC_IP_ADDRESS']}",
        :protocol => "tcp", :publicport => 80, :privateport  => 80,
        :openfirewall => false
      }
    ]

    cloudstack.firewall_rules = [
      { 
        :ipaddress => "#{ENV['PUBLIC_IP_ADDRESS']}",
        :cidrlist => "#{ENV['CIDR_LIST']}",
        :protocol => "tcp", :startport => 22, :endport  => 22,
      },
      { 
        :ipaddress => "#{ENV['PUBLIC_IP_ADDRESS']}",
        :cidrlist => "#{ENV['CIDR_LIST']}",
        :protocol => "tcp", :startport => 80, :endport  => 80,
      }
    ]

    cloudstack.pf_ip_address   = "#{ENV['PUBLIC_IP_ADDRESS']}"
    cloudstack.pf_public_port  = 22
    cloudstack.pf_private_port = 22
    cloudstack.pf_open_firewall   = false

    cloudstack.keypair            = "#{ENV['CLOUDSTACK_SSH_KEYPAIR']}"
    override.ssh.private_key_path = "#{ENV['VAGRANT_SSH_PRIVATE_KEY']}"
  end

  config.vm.provision "shell" do |s|
    s.inline = <<-EOS
      yum -y install httpd
      systemctl start httpd
      echo Hello > /var/www/html/index.html
    EOS
  end
end
```

以下の環境変数を設定して```vagrant up``` してください。

```bash
export CLOUDSTACK_API_KEY='YOUR_API_KEY'
export CLOUDSTACK_SECRET_KEY='YOUR_SECRET_KEY'
export CLOUDSTACK_SSH_KEYPAIR='YOUR_SSH_KEY'                                             
export VAGRANT_SSH_PRIVATE_KEY='~/.ssh/id_rsa'                                                                                                             
export PUBLIC_IP_ADDRESS='X.X.X.X'                                                 
export CIDR_LIST='Y.Y.Y.Y/Y'  
```

## スタティックNATを使ったSSH接続

スタティックNATをSSH接続用に使用することも可能です。
GMOクラウドALTUS Basicシリーズの様に外部からのSSH接続にスタティックNATが必要な環境にもVagrantを使って仮想マシンが作成できるようになりました。

### 設定例

GMOクラウド ALTUS BasicシリーズにApacheをインストールし外部に公開するVagrantfileは以下のようになります。

※Vagrantに対応したテンプレートの作成とIPアドレスの取得を行っている必要があります。方法は以下の記事を参照してください

[VagrantでIDCFクラウド、Cloud n、ALTUSを使ってみる - Qiita](http://qiita.com/atsaki/items/f12e82f109193321fb13)

```rb:Vagrantfile
Vagrant.configure("2") do |config|
  config.vm.provider :cloudstack do |cloudstack, override|

    override.vm.box = "dummy"
    override.vm.box_url = "https://github.com/schubergphilis/vagrant-cloudstack/raw/master/dummy.box"

    cloudstack.host   = "tky001b.pf.gmocloud.com"
    cloudstack.path   = "/client/api"
    cloudstack.port   = "443"
    cloudstack.scheme = "https"

    cloudstack.api_key    = "#{ENV['CLOUDSTACK_API_KEY']}"
    cloudstack.secret_key = "#{ENV['CLOUDSTACK_SECRET_KEY']}"

    cloudstack.zone_name             = "Basic_tky001"
    cloudstack.template_name         = "CentOS 6.4 for Vagrant"
    cloudstack.service_offering_name = "Mini Server"
    cloudstack.network_type          = "Basic"

    cloudstack.static_nat = [
      {:ipaddress => "#{ENV['PUBLIC_IP_ADDRESS']}"}
    ]

    cloudstack.security_groups = [
      {
        :name         => "apache-example",
        :description  => "apache-example",
        :rules => [
          {
            :type => "ingress",
            :cidrlist => "#{ENV['CIDR_LIST']}",
            :protocol => "tcp", :startport => 22, :endport => 22
          },
          {
            :type => "ingress",
            :cidrlist => "#{ENV['CIDR_LIST']}",
            :protocol => "tcp", :startport => 80, :endport => 80
          }
        ]
      }
    ]

    override.ssh.host = "#{ENV['PUBLIC_IP_ADDRESS']}"
  end

  config.vm.provision "shell" do |s|
    s.inline = <<-EOS
      yum -y install httpd
      service httpd start
      echo Hello > /var/www/html/index.html
    EOS
  end
end
```

以下の環境変数を設定して```vagrant up``` してください。
テンプレートのSSH鍵に[insecure key](https://github.com/mitchellh/vagrant/tree/master/keys)以外を使っている場合は別途SSH関連の設定が必要です。

```bash
export CLOUDSTACK_API_KEY='YOUR_API_KEY'
export CLOUDSTACK_SECRET_KEY='YOUR_SECRET_KEY'                                                                               
export PUBLIC_IP_ADDRESS='X.X.X.X'                                                 
export CIDR_LIST='Y.Y.Y.Y/Y'  
```
# rsync Synced Folder

vagrant-cloudstackは従来からSynced Folderにrsyncを使用していましたが、プラグイン独自の実装となっていました。

v1.0.0ではSynced FolderにVagrant 1.5.0で導入されたrsync Synced Folderを使うようになりました。

[RSync - Synced Folders - Vagrant Documentation](http://docs.vagrantup.com/v2/synced-folders/rsync.html)

## rsync, rsync-autoコマンド

これまでディレクトリの同期は```vagrant up``` や```vagrant provision``` コマンド実行時に行われていました。

v1.0.0からはrsync Synced Folderの機能によりrsync, rsync-autoコマンドによる同期が可能になっています。

```vagrant rsync``` コマンドはディレクトリを強制的に再同期します。

```vagrant rsync-auto``` コマンドはローカルで変更があった際に自動的に同期を行います。

詳細はVagrantのドキュメントを参照してください。

[RSync - Synced Folders - Vagrant Documentation](http://docs.vagrantup.com/v2/synced-folders/rsync.html)

### 設定例

IDCFクラウドのApacheの例でローカルにあるHTMLファイルを変更した際に自動的に同期されるように変更してみます。

まず同期用のディレクトリとファイルをVagrantfileがあるディレクトリに作成しておきます。

```bash
$ mkdir html
$ echo Hello > html/index.html
```

次にVagrantfileを次のように作成します。```config.vm.synced_folder``` を使用してローカルのディレクトリ```./html``` をリモートの```/var/www/html``` と同期させています。

```rb:Vagrantfile
Vagrant.configure("2") do |config|
  config.vm.provider :cloudstack do |cloudstack, override|
    override.vm.box = "dummy"
    override.vm.box_url = "https://github.com/schubergphilis/vagrant-cloudstack/raw/master/dummy.box"

    cloudstack.host    = "compute.jp-east.idcfcloud.com"
    cloudstack.path    = "/client/api"
    cloudstack.port    = "443"
    cloudstack.scheme  = "https"

    cloudstack.api_key    = "#{ENV['CLOUDSTACK_API_KEY']}"
    cloudstack.secret_key = "#{ENV['CLOUDSTACK_SECRET_KEY']}"

    cloudstack.zone_name             = "pascal"
    cloudstack.template_name         = "CentOS 7.0 64-bit for Vagrant"
    cloudstack.service_offering_name = "light.S1"

    cloudstack.port_forwarding_rules = [
      { 
        :ipaddress => "#{ENV['PUBLIC_IP_ADDRESS']}",
        :protocol => "tcp", :publicport => 80, :privateport  => 80,
        :openfirewall => false
      }
    ]

    cloudstack.firewall_rules = [
      { 
        :ipaddress => "#{ENV['PUBLIC_IP_ADDRESS']}",
        :cidrlist => "#{ENV['CIDR_LIST']}",
        :protocol => "tcp", :startport => 22, :endport  => 22,
      },
      { 
        :ipaddress => "#{ENV['PUBLIC_IP_ADDRESS']}",
        :cidrlist => "#{ENV['CIDR_LIST']}",
        :protocol => "tcp", :startport => 80, :endport  => 80,
      }
    ]

    cloudstack.pf_ip_address   = "#{ENV['PUBLIC_IP_ADDRESS']}"
    cloudstack.pf_public_port  = 22
    cloudstack.pf_private_port = 22
    cloudstack.pf_open_firewall   = false

    cloudstack.keypair            = "#{ENV['CLOUDSTACK_SSH_KEYPAIR']}"
    override.ssh.private_key_path = "#{ENV['VAGRANT_SSH_PRIVATE_KEY']}"
  end

  config.vm.provision "shell" do |s|
    s.inline = <<-EOS
      yum -y install httpd
      systemctl start httpd
    EOS
  end

  config.vm.synced_folder "./html", "/var/www/html"
end
```

以下の環境変数を設定して```vagrant up``` し、ブラウザで```PUBLIC_IP_ADDRESS``` に指定したIPアドレスを開くと「Hello」と表示されたページが開きます。

```bash
export CLOUDSTACK_API_KEY='YOUR_API_KEY'
export CLOUDSTACK_SECRET_KEY='YOUR_SECRET_KEY'
export CLOUDSTACK_SSH_KEYPAIR='YOUR_SSH_KEY'                                             
export VAGRANT_SSH_PRIVATE_KEY='~/.ssh/id_rsa'                                     
                                                                                   
export PUBLIC_IP_ADDRESS='X.X.X.X'                                                 
export CIDR_LIST='Y.Y.Y.Y/Y'  
```

```vagrant rsync-auto``` コマンドを実行すると自動同期が始まります。
この状態でローカルのhtmlファイルに変更を加えると自動的にリモートに同期されます。

別のウィンドウを開きhtmlファイルに変更を加えてみます。

```bash
$ echo Hello2 > index.html
```

```vagrant rsync-auto``` を実行中のウィンドウに同期が実行されたことを示すメッセージが表示されます。ブラウザからページを更新すると表示が「Hello2」に変わります。

同期を終了するには```vagrant rsync-auto``` を実行しているウィンドウでCtrl+Cを押下します。

## rsyncオプションのサポート

rsync Synced Folderの機能によりrsyncのオプションを指定することが可能になりました。

特定のディレクトリやファイルを同期の対象外とするといった設定が可能です。

例えば、.gitディレクトリと.envrcを同期の対象から除外するには以下の様にします。

```rb
  config.vm.synced_folder ".", "/vagrant", type: "rsync",
    rsync__exclude: [".git/", ".envrc"]
```

詳細についてはVagrantのドキュメントを参照してください。

[RSync - Synced Folders - Vagrant Documentation](http://docs.vagrantup.com/v2/synced-folders/rsync.html)

## rsync自動インストール

rsyncをSynced Folderに使用する場合、ゲストにrsyncがインストールされている必要があります。このため、事前にテンプレートにrsyncをインストールしておく必要がありました。

rsync Synced Folderは、作成した仮想マシンにrsyncがインストールされていなかった場合、自動でインストールしてくれるためテンプレートの事前の用意が不要になりました。
ただし、```vagrant up``` した時点で```yum``` や```apt-get```でrsyncがインストールできるように構成しておく必要はあります。

# 最後に

v1.0.0はレポジトリの管理が[Klarna](https://www.klarna.com/us/)から[Schuberg Philis](https://www.schubergphilis.com/)に移ってからの初のリリースでもあります。昨年の後半あたりから、一時的に開発が停滞していましたが現在は再び活発に開発が行われるようになっています。

紹介しなかった細かい所でも色々修正されているので是非バージョンアップして使ってみてください。

# 参考

* [VagrantでIDCFクラウド、Cloud n、ALTUSを使ってみる - Qiita](http://qiita.com/atsaki/items/f12e82f109193321fb13)