Packer で Scientific Linux 6.5 の base box を作成してみる

VagrantでScientificLinux 6.5を使いたかったんだけど、
[vagrantbox.es](http://www.vagrantbox.es/)には明示的に6.5って書いてあるboxは無かった。 
（Scientific Linux 6はあったけど） 
なので、ScientificLinux 6.5 のvagrant用base boxをpackerで作成してみた。

~~成果物のtemplateは[GitHub: ringohub/packer-template feature/scientifi-6.5](https://github.com/ringohub/packer-templates/tree/feature/scientific-6.5)にあります。~~
成果物のtemplateは[[GitHub: packer-templates/develop](https://github.com/ringohub/packer-templates)]にあります（[shiguredo/packer-templates develop](https://github.com/shiguredo/packer-templates/)にマージされました。ありがとうございます）。

## 事前準備
1. [Packer で Scientific Linux 6.1 の Box を作成してみる](http://hmasuda.github.io/blog/2013/12/25/packer/)に書いてあるように、[shiguredo/packer-templates](https://github.com/shiguredo/packer-templates)を`fork`する
2. `git clone` する
3. 適当に`centos-6.5`なんかをコピーして`scientific-6.5`を作成する

##`template.json`の編集

template.jsonにかかれている内容を変更します。 
主に、osのイメージ名やDL元のURL,checksumのハッシュ値などを変更しました。 
vmwareは使う予定ないけど、templateに入っていたのでついでに変更。

```diff
diff --git a/scientific-6.5/scripts/vagrant.sh b/scientific-6.5/scripts/vagrant.sh
index 76fb7bd..3b39389 100644
--- a/scientific-6.5/scripts/vagrant.sh
+++ b/scientific-6.5/scripts/vagrant.sh
@@ -1,3 +1,5 @@
+#!/bin/sh
+
 date > /etc/vagrant_box_build_time

 mkdir -pm 700 /home/vagrant/.ssh
diff --git a/scientific-6.5/template.json b/scientific-6.5/template.json
index 2ddbe77..e428542 100644
--- a/scientific-6.5/template.json
+++ b/scientific-6.5/template.json
@@ -28,10 +28,10 @@
       "type": "vagrant",
       "override": {
         "virtualbox": {
-          "output": "centos-6-5-x64-virtualbox.box"
+          "output": "scientific-6-5-x64-virtualbox.box"
         },
         "vmware": {
-          "output": "centos-6-5-x64-vmware.box"
+          "output": "scientific-6-5-x64-vmware.box"
         }
       }
     }
@@ -46,9 +46,9 @@
       "disk_size": 40520,
       "guest_os_type": "RedHat_64",
       "http_directory": "http",
-      "iso_checksum": "f21a71e8e31df73297bdd1ccd4a64a36831284bd",
+      "iso_checksum": "a95e182f6ed14a4fb36e448d6eb19a6a59a34778",
       "iso_checksum_type": "sha1",
-      "iso_url": "http://ftp.iij.ad.jp/pub/linux/centos/6.5/isos/x86_64/CentOS-6.5-x86_64-minimal.iso",
+      "iso_url": "http://ftp.riken.jp/Linux/scientific/6.5/x86_64/iso/SL-65-x86_64-2014-01-27-Install-DVD.iso",
       "ssh_username": "vagrant",
       "ssh_password": "vagrant",
       "ssh_port": 22,
@@ -68,11 +68,11 @@
       ],
       "boot_wait": "10s",
       "disk_size": 40520,
-      "guest_os_type": "centos-64",
+      "guest_os_type": "RedHat_64",
       "http_directory": "http",
-      "iso_checksum": "f21a71e8e31df73297bdd1ccd4a64a36831284bd",
+      "iso_checksum": "a95e182f6ed14a4fb36e448d6eb19a6a59a34778",
       "iso_checksum_type": "sha1",
-      "iso_url": "http://ftp.iij.ad.jp/pub/linux/centos/6.5/isos/x86_64/CentOS-6.5-x86_64-minimal.iso",
+      "iso_url": "http://ftp.riken.jp/Linux/scientific/6.5/x86_64/iso/SL-65-x86_64-2014-01-27-Install-DVD.iso",
       "ssh_username": "vagrant",
       "ssh_password": "vagrant",
       "ssh_port": 22,
@@ -87,3 +87,4 @@
     }
   ]
 }
+
```

- ちなみに、`guest_os_type`の一覧は`VBoxManage list ostypes`で一覧できます。
- イメージのおいてあるサーバは[riken](http://ftp.riken.jp/Linux/scientific/6.5/x86_64/iso)にしました。

## packerでbase boxをbuildする

packerでbase boxを作成します。

```bash
$ packer build -only=virtualbox-iso template.json
```

- [Build log](https://gist.github.com/ringohub/87d41aaf8ce14a333bb2)

ビルドすると、ディレクトリにoutputで指定した`scientific-6-5-x64-virtualbox.box`が作成されています。


## vagrantで稼働確認

### vagrant add
作成されたboxをaddしましょう。

```bash
$ vagrant box add sl6.5 scientific-6-5-x64-virtualbox.box
==> box: Adding box 'sl6.5' (v0) for provider:
    box: Downloading: file:///Users/ringo/work/packer-templates/scientific-6.5/scientific-6-5-x64-virtualbox.box
==> box: Successfully added box 'sl6.5' (v0) for 'virtualbox'!
```

追加されたか確認。

```bash
$ vagrant box list
opscode-ubuntu-12.04 (virtualbox, 0)
sl6.5                (virtualbox, 0)
ubuntu14.04          (virtualbox, 0)
```

よしよし。

### vagrnat init

適当なところで`vagrant init`して、適当にVagrantfileを編集します。

```ruby
# -*- mode: ruby -*-
# vi: set ft=ruby :

VAGRANTFILE_API_VERSION = "2"

Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
  config.vm.box = "sl6.5"
  config.vm.network "private_network", ip: "192.168.33.10"
end
```

### vagrant up
upしてみましょう。

```bash
$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'sl6.5'...
==> default: Matching MAC address for NAT networking...
==> default: Setting the name of the VM: sl_default_1401725308602_87916
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
    default: Adapter 1: nat
    default: Adapter 2: hostonly
==> default: Forwarding ports...
    default: 22 => 2222 (adapter 1)
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
    default: SSH address: 127.0.0.1:2222
    default: SSH username: vagrant
    default: SSH auth method: private key
    default: Warning: Connection timeout. Retrying...
==> default: Machine booted and ready!
GuestAdditions 4.3.10 running --- OK.
==> default: Checking for guest additions in VM...
==> default: Configuring and enabling network interfaces...
==> default: Mounting shared folders...
    default: /vagrant => /Users/ringo/work/sl
```

いけた。

```bash
$ vagrant ssh
Last login: Tue Jun  3 00:56:37 2014 from 10.0.2.2
[vagrant@localhost ~]$ cat /etc/system-release
Scientific Linux release 6.5 (Carbon)
```

完成！

## まとめ
packerを使って、OSのイメージからvagrant boxを作成してみました。 
意外に、簡単にできるとおもいきや、下に書いてあるようなエラーでハマってたりしました。 
boxは作れてupもできるんだけど、デフォルトでSSH鍵認証が出来ない状態でした。 
とりあえず、作成できて良かったです。 

ここから下は、興味がある人、同じ罠にはまってる人は御覧ください。 
おわり。

## エラー: vagrant upするとConnection timeoutする件

### 事象

「よしboxできた」と思って`vagrant up`をしてみると、Connection timeoutがでた。 
なんか、この時点でSSHっぽい予感がしてた。

```sh
$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Importing base box 'sl6.5'...
==> default: Matching MAC address for NAT networking...
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
    default: Adapter 1: nat
    default: Adapter 2: hostonly
==> default: Forwarding ports...
  1 # -*- mode: ruby -*-
    default: 22 => 2222 (adapter 1)
==> default: Booting VM...
==> default: Waiting for machine to boot. This may take a few minutes...
    default: SSH address: 127.0.0.1:2222
    default: SSH username: vagrant
    default: SSH auth method: private key
    default: Warning: Connection timeout. Retrying...
    default: Warning: Authentication failure. Retrying...
    default: Warning: Authentication failure. Retrying...
    default: Warning: Authentication failure. Retrying...
    default: Warning: Authentication failure. Retrying...
    default: Warning: Authentication failure. Retrying...
    default: Warning: Authentication failure. Retrying...
    default: Warning: Authentication failure. Retrying...
    default: Warning: Authentication failure. Retrying...
    default: Warning: Authentication failure. Retrying...
    default: Warning: Authentication failure. Retrying...
    default: Warning: Authentication failure. Retrying...
    default: Warning: Authentication failure. Retrying...
    default: Warning: Authentication failure. Retrying...
    default: Warning: Authentication failure. Retrying...
    default: Warning: Authentication failure. Retrying...
    default: Warning: Authentication failure. Retrying...
    default: Warning: Authentication failure. Retrying...
    default: Warning: Authentication failure. Retrying...
    default: Warning: Authentication failure. Retrying...
    default: Warning: Authentication failure. Retrying...
    default: Warning: Authentication failure. Retrying...
    default: Warning: Authentication failure. Retrying...
    default: Warning: Authentication failure. Retrying...
    default: Warning: Authentication failure. Retrying...
    default: Warning: Authentication failure. Retrying...
    default: Warning: Authentication failure. Retrying...
    default: Warning: Authentication failure. Retrying...
    default: Warning: Authentication failure. Retrying...
Timed out while waiting for the machine to boot. This means that
Vagrant was unable to communicate with the guest machine within
the configured ("config.vm.boot_timeout" value) time period.

If you look above, you should be able to see the error(s) that
Vagrant had when attempting to connect to the machine. These errors
are usually good hints as to what may be wrong.

If you're using a custom box, make sure that networking is properly
working and you're able to connect to the machine. It is a common
problem that networking isn't setup properly in these boxes.
Verify that authentication configurations are also setup properly,
as well.

If the box appears to be booting properly, you may want to increase
the timeout ("config.vm.boot_timeout") value.
```

試しに、`vagrant ssh`でログインしてみると、パスワードを聞かれた。 
予定ではSSHの鍵認証が行われ、すっとログインできるはずだった。 
とりあえず、パスワードでログインして、`authorized_keys`の中を見てみると。。。

```html
$ cat authorized_keys
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>400 Bad Request</title>
</head><body>
<h1>Bad Request</h1>
<p>Your browser sent a request that this server could not understand.<br />
</p>
</body></html>
```

`Bad Request`が入ってた(◞‸◟)

### 原因

コピーして持ってきたtemplateの中に`scripts/vagrant.sh`というシェルスクリプトがある。

```bash
date > /etc/vagrant_box_build_time

mkdir -pm 700 /home/vagrant/.ssh
curl -L https://raw.github.com/mitchellh/vagrant/master/keys/vagrant.pub -o /home/vagrant/.ssh/authorized_keys
chmod 0600 /home/vagrant/.ssh/authorized_keys
chown -R vagrant:vagrant /home/vagrant/.ssh
```

このファイルの中で、実行されている`curl`がBad RequestのHTMLをDLしていた。 
しかし、この`curl`で叩いているURLは古く、ブラウザでアクセスすると、
`https://raw.githubusercontent.com/mitchellh/vagrant/master/keys/vagrant.pub`にリダイレクトされる。 
GitHubのrawリソースを示すURLが変わったとのこと。

ということで、次のように変更したら無事鍵が登録された。

```diff
diff --git a/scientific-6.5/scripts/vagrant.sh b/scientific-6.5/scripts/vagrant.sh
index 3b39389..658a8d6 100644
--- a/scientific-6.5/scripts/vagrant.sh
+++ b/scientific-6.5/scripts/vagrant.sh
@@ -3,6 +3,6 @@
 date > /etc/vagrant_box_build_time

 mkdir -pm 700 /home/vagrant/.ssh
-curl -L https://raw.github.com/mitchellh/vagrant/master/keys/vagrant.pub -o /home/vagrant/.ssh/authorized_keys
+curl -L https://raw.githubusercontent.com/mitchellh/vagrant/master/keys/vagrant.pub -o /home/vagrant/.ssh/authorized_keys
 chmod 0600 /home/vagrant/.ssh/authorized_keys
```

### おまけ
Mac OSX 10.9 Mavericks で`curl`を実行した時と、
Scientific Linux 6.5 で`curl`を実行した時の結果を比較してみた。

OSXはBSD系のコマンドが入っているので、GNU系のScientific Linuxとは挙動が違うのかもしれない。

#### まず、OSX
```bash
$ curl --version
curl 7.30.0 (x86_64-apple-darwin13.0) libcurl/7.30.0 SecureTransport zlib/1.2.5
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp smtp smtps telnet tftp
Features: AsynchDNS GSS-Negotiate IPv6 Largefile NTLM NTLM_WB SSL libz
$ curl -I -L https://raw.github.com/mitchellh/vagrant/master/keys/vagrant.pub
HTTP/1.1 301 Moved Permanently
Date: Mon, 02 Jun 2014 16:46:59 GMT
Server: Apache
Location: https://raw.githubusercontent.com/mitchellh/vagrant/master/keys/vagrant.pub
Accept-Ranges: bytes
Via: 1.1 varnish
Age: 0
X-Served-By: cache-ty66-TYO
X-Cache: MISS
X-Cache-Hits: 0
Vary: Accept-Encoding

HTTP/1.1 200 OK
Date: Mon, 02 Jun 2014 16:46:59 GMT
Server: Apache
Content-Security-Policy: default-src 'none'
Access-Control-Allow-Origin: https://render.githubusercontent.com
X-XSS-Protection: 1; mode=block
X-Frame-Options: deny
X-Content-Type-Options: nosniff
Strict-Transport-Security: max-age=31536000
ETag: "18a9c00fd56d378c4cea4ee6e89018df8b41f9fa"
Content-Type: text/plain; charset=utf-8
Cache-Control: max-age=300
Content-Length: 409
Accept-Ranges: bytes
Via: 1.1 varnish
X-Served-By: cache-ty68-TYO
X-Cache: MISS
X-Cache-Hits: 0
Vary: Authorization,Accept-Encoding
Expires: Mon, 02 Jun 2014 16:51:59 GMT
Source-Age: 0
```

#### つぎに、Scientific Linux
```bash
[vagrant@localhost ~]$ curl --version
curl 7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.14.0.0 zlib/1.2.3 libidn/1.18 libssh2/1.4.2
Protocols: tftp ftp telnet dict ldap ldaps http file https ftps scp sftp
Features: GSS-Negotiate IDN IPv6 Largefile NTLM SSL libz
[vagrant@localhost ~]$ curl -I -L https://raw.github.com/mitchellh/vagrant/master/keys/vagrant.pub
HTTP/1.1 301 Moved Permanently
Date: Mon, 02 Jun 2014 16:45:49 GMT
Server: Apache
Location: https://raw.githubusercontent.com/mitchellh/vagrant/master/keys/vagrant.pub
Accept-Ranges: bytes
Via: 1.1 varnish
Age: 0
X-Served-By: cache-ty68-TYO
X-Cache: MISS
X-Cache-Hits: 0
Vary: Accept-Encoding

HTTP/1.1 400 Bad Request
Date: Mon, 02 Jun 2014 16:45:54 GMT
Server: Apache
Connection: close
Content-Type: text/html; charset=iso-8859-1
```

どちらも`-L`でリダイレクト先に飛んでいるが、なぜかSLの方はBadRequest。 
ふーむ。

## 参考
- [Packer で Scientific Linux 6.1 の Box を作成してみる](http://hmasuda.github.io/blog/2013/12/25/packer/)
- [PackerでVagrant Boxを作成する際のトラブルシューティング](http://lab.unicast.ne.jp/2013/09/09/troubleshooting-create-vagrant-box-with-packer/)
- [eigo's packer template](https://github.com/eigo-s/packer_templates)(GitHubにあげてもらいました！ 追記 at 2014/07/07)