CentOS 7にCobblerをインストールする

# Cobblerって？

[Cobbler](http://www.cobblerd.org/)はOSの自動インストールのためのあれこれを用意してくれるミドルウェアである。
「あれこれ」の内容は、

* ネットワークブートを受け付け、OSのインストールを行ってくれるPXEサーバの提供（DHCPサーバ、TFTPサーバ、HTTPサーバ）
* OSインストール時の自動応答ファイルであるkickstartやpreseedのテンプレートの提供
* yumやaptのパッケージリポジトリのミラーリング
* ネットワークブートが利用できないコンピュータのためのインストールイメージISO作成機能

などである。

ちなみに、Cobblerの元々の作者は現在Ansibleの一番えらい人であるMichael DeHaanであり、現在の開発リーダーであるJames CammarataもAnsible社の人である、と以下のURLに書かれている。
http://docs.ansible.com/intro_dynamic_inventory.html

**2015-04-05追記**： Michael DeHaanは2015-01をもってAnsible社を退職している。

# Cobblerのセットアップ

## Cobblerのインストール

CobblerはEPELにあるので、EPELを使えるようにしてからインストールする。

```
# yum install epel-release
# yum install cobbler xinetd
```

**2015-08-04追記**： Cobblerの公式サイトのドメインが変更されたため、Cobblerのバージョンが2.4.9/2.6.9未満の場合Cobblerのサイトからファイルを取得する操作（`cobbler get-loaders`や`cobbler signature update`）が失敗するので、以降の作業を行う場合2.6.9より古いバージョンを使用しているならアップデートする必要がある。

**2016-05-06追記**: いつからか調べていないがcobblerの依存性によってxinetdがインストールされなくなったのでxinetdも明示的にインストールする必要がある。

## SELinuxへの対応

SELinuxが有効になっている場合、いくらかSELinuxに関する調整をする必要がある。
→ [「SELinuxのせいで動かない」撲滅ガイド](http://qiita.com/yunano/items/857ab36faa0d695573dd)参照

SELinuxブール値：httpd_can_network_connect_cobblerをオンにする。

```
# setsebool -P httpd_can_network_connect_cobbler 1
```

**2015-07-18注記**: 当初はSELinuxブール値：httpd_can_network_connect_cobblerが存在しなかったので代わりに`setsebool -P httpd_can_network_connect 1`としていた。

次のようにcobbler_addition.teを作成する。

```txt:cobbler_addition.te
module cobbler_addition 1.0;

require {
  type var_log_t;
  type var_run_t;
  type cert_t;
  type cobbler_etc_t;
  type cobblerd_t;
  type rpm_var_cache_t;
  type rpm_var_lib_t;
  type lib_t;
  type tftpdir_rw_t;
  type rpm_log_t;
  class dir { read write getattr remove_name open add_name search create rmdir };
  class file { rename setattr read lock create write getattr unlink open };
}

#============= cobblerd_t ==============
allow cobblerd_t cobbler_etc_t:file write;
allow cobblerd_t cert_t:dir write;
allow cobblerd_t cert_t:file write;
allow cobblerd_t rpm_var_cache_t:dir { write getattr read remove_name open add_name search create };
allow cobblerd_t rpm_var_cache_t:file { rename setattr read lock create write getattr unlink open };
allow cobblerd_t rpm_var_lib_t:dir { write read getattr open search };
allow cobblerd_t rpm_var_lib_t:file { read write getattr open lock };
allow cobblerd_t var_log_t:file open;
allow cobblerd_t var_run_t:dir { write remove_name add_name };
allow cobblerd_t var_run_t:file { write create unlink open };
allow cobblerd_t lib_t:dir { write add_name };
allow cobblerd_t lib_t:file { write create };
allow cobblerd_t tftpdir_rw_t:dir rmdir;
allow cobblerd_t rpm_log_t:file open;
```

作ったTEファイルをコンパイルしてSELinuxのモジュールとして登録する。

```
# yum install selinux-policy-devel
# make -f /usr/share/selinux/devel/Makefile cobbler_addition.pp
# semodule -i cobbler_addition.pp
```

## Web UIのインストール

Cobblerはすべてコマンドラインで操作できるが、Web UIを利用することもできる。
必要なら次でCobblerのWeb UIをインストールする。

```
# yum install cobbler-web
```

SELinuxが有効ならSELinuxブール値：httpd_serve_cobbler_filesをオンにする。

```
# setsebool -P httpd_serve_cobbler_files 1
```

HTTPSの分のファイアウォールを開けておく。

```
# firewall-cmd --add-service=https
# firewall-cmd --permanent --add-service=https
```

## Cobblerの起動と設定

Cobblerの設定を変更してもcobblerdを再起動しなくても良いように設定ファイル /etc/cobbler/settings のallow_dynamic_settings項を有効にしておく。

```
# sed -ri "s/(^allow_dynamic_settings: ).*/\11/" /etc/cobbler/settings
```

ここから先はCooblerのAPIを叩くのでcobblerdとhttpdを起動しておく。

```
# systemctl start cobblerd httpd
```

Cobblerに他のコンピュータからアクセスできるように、待ち受けIPアドレスをローカルホストから他のコンピュータからアクセスできる、Cobbler機のIPアドレスに変更する。

「cobbler setting edit」コマンドはCobblerの設定ファイル /etc/cobbler/settings を変更するが、上でallow_dynamic_settings項を有効にしたので動的に設定変更できる。

```
# cobbler setting edit --name server --value <このコンピュータのIPアドレス>
```

OSをインストールした際にユーザのログインパスワードとなる文字列を、ソルト付きのSHA512でハッシュしたものをCobbler設定ファイル /etc/cobbler/settings にセットする。
この設定値はkickstartやpreseedのテンプレート（後述）の中で`$default_password_crypted`と記述した箇所にセットされる。

以下ではパスワード文字列をソルト付きのSHA512でハッシュするのにpythonのワンライナーを使用した。
ソルトはランダムな8文字になるようにしている。例えばソルトの文字数を変えたければ「xrange(8)」の数字を変更する。

```
# cobbler setting edit --name default_password_crypted --value `python -c 'import crypt, random, string; print "%s" % crypt.crypt("ここにパスワード文字列", "$6$%s" % "".join([random.choice(string.ascii_letters + string.digits) for x in xrange(8)]))'`
```

HTTPとTFTPの分のファイアウォールを開けておく。

```
# firewall-cmd --add-service=http
# firewall-cmd --add-service=tftp
# firewall-cmd --permanent --add-service=http
# firewall-cmd --permanent --add-service=tftp
```

## Web UIのログインユーザとパスワードの設定

cobblerdとhttpdを起動した時点で https://<このコンピュータのIPアドレス>/cobbler_web/ にアクセスすればWeb UIへアクセスできる。
ログインユーザとパスワードはともに「cobbler」である。

新たにログインユーザとパスワードを追加したい場合は /etc/cobbler/users.digest にDigest認証するための1行を追加すれば良い。レルム名は「Cobbler」なので`htdigest /etc/cobbler/users.digest Cobbler <ログインユーザ名>`を実行する。あるいは、htdigestだとインタラクティブ入力になるので、これを避けるならpythonのワンライナーを使って次のようになる。

```
# python -c 'import hashlib; user = "ここにユーザ名を書く"; realm = "Cobbler"; print "%s:%s:%s" % (user, realm, (hashlib.md5("%s:%s:ここにパスワードを書く" % (user, realm)).hexdigest()))' >> /etc/cobbler/users.digest
```

以下で元々の「cobbler」ユーザを削除しても良い。

```
# sed -i "/^cobbler:Cobbler:/d" /etc/cobbler/users.digest
```

## DHCPサーバの設定

Cobblerで使用するDHCPサーバをインストールする。

```
# yum install dhcp
```

CobblerがDHCPサーバと連携するようにCobblerの設定を変更する。

```
# cobbler setting edit --name manage_dhcp --value 1
```

/etc/cobbler/dhcp.template がdhcpd.confのテンプレートである。
このファイルを自分の環境に合わせて書き換える。書き換えるものは次の通りである。

* ネットワークアドレス
* サブネットマスク（255.255.255.0などの形式）
* ルータのIPアドレス
* DNSサーバのIPアドレス
* DHCPサーバが配布するIPアドレスの範囲

```
# sed -ri "s/(^subnet ).+( netmask ).+/\1<ネットワークアドレス>\2<サブネットマスク> {/" /etc/cobbler/dhcp.template
# sed -ri "s/(^ +option routers +).*/\1<ルータのIPアドレス>;/" /etc/cobbler/dhcp.template
# sed -ri "s/(^ +option domain-name-servers +).*/\1<DNSサーバのIPアドレス（複数の場合はスペース区切り）>;/" /etc/cobbler/dhcp.template
# sed -ri "s/(^ +option subnet-mask +).*/\1<サブネットマスク>;/" /etc/cobbler/dhcp.template
# sed -ri "s/(^ +range dynamic-bootp +).*/\1<DHCPサーバが配布するIPアドレスの範囲の始め> <DHCPサーバが配布するIPアドレスの範囲の終わり>;/" /etc/cobbler/dhcp.template
```

DHCPサーバのnext-server（TFTPサーバのIPアドレス）を他のコンピュータからアクセスできる、Cobbler機のIPアドレスに変更する。
この設定値はdhcpd.confテンプレートの中で`$next_server`と記述した箇所にセットされる。

```
# cobbler setting edit --name next_server --value <このコンピュータのIPアドレス>
```

DHCPの分のファイアウォールを開けておく。

```
# firewall-cmd --add-service=dhcp
# firewall-cmd --permanent --add-service=dhcp
```

## ブートローダファイルの取得

PXEブート時に使用するブートローダファイルを取得する。

```
# cobbler get-loaders
```

## TFTPサーバ、DHCPサーバの起動

ここまで行った操作をTFTPサーバ、DHCPサーバに反映し、起動する。

```
# cobbler sync
# systemctl start xinetd
```

各サービスが起動時に立ち上がるようにしておく。
（xinetdは元からenableになっている）

```
# systemctl enable cobblerd httpd dhcpd
```

これでCobblerのセットアップは完了である。

ここまでをAnsibleで構築するようにしている。
https://github.com/yunano/ansible-centos7-roles

# OSイメージの追加

Cobblerのセットアップが完了しても、PXEサーバとしてはインストールしてやるOSのイメージがないと働くことはできない。
そこでOSイメージを取り込んでやる。以下ではCentOS 7を取り込む例を示す。

**2015-04-05追記**： 現在私は別の方法でOSイメージの追加を行っている。→[Cobblerの省力化のためにプロキシと組み合わせる](http://qiita.com/yunano/items/51c08fdbd2ff9cacef40)

## OSイメージの取り込み

wgetなどでインストールISOをダウンロードしてマウントする。
DVD.isoは省かれたパッケージが結構あって困ることがあるのでEverything.isoにしておく方が良い。

```
# yum install wget
# wget http://ftp.iij.ad.jp/pub/linux/centos/7.0.1406/isos/x86_64/CentOS-7.0-1406-x86_64-Everything.iso
# mount CentOS-7.0-1406-x86_64-Everything.iso /mnt
```

ISOファイルの中身をCobblerにインポートする。

```
# cobbler import --name c7 --path /mnt
```

インポートが終わったらISOファイルはアンマウントして良い。

```
# umount /mnt
```

### ISOファイルの取り込み直し

(2016-05-06)
元々はrsyncで取り込み直す方法を記載していたが、この方法だとその後新しいOSを作る際に上手く行かなくなることがあるようだ。
「そのdistroを使っているプロファイルのdistroを一旦別のものに変更する」→「distroを削除する」→「importし直す」→「distroを一旦変更したプロファイルを元に戻す」などとした方が良いだろう。

例えばc7-x86_64というdistroの取り込み直しを行う際に、このdistroを使っているプロファイルは同名のc7-x86_64だけであり、このdistro以外にc6-x86_64というdistroがある場合、以下のようになる。

```
# cobbler profile edit --name c7-x86_64 --distro c6-x86_64
# cobbler distro remove --name c7-x86_64
# mount /vagrant/CentOS-7-x86_64-Everything-1511.iso /mnt
# cobbler import --name c7 --path /mnt
# umount /mnt
# cobbler profile edit --name c7-x86_64 --distro c7-x86_64
```

## パッケージリポジトリのミラーリング

Cobblerを使用してインストールしたCentOS 7をインストール直後でも（ほぼ）最新にするために、updatesリポジトリをCobblerに取り込むと良い。

次のコマンドで取り込み元を設定することができる。

```
# cobbler repo add --name c7-updates --mirror http://ftp.iij.ad.jp/pub/linux/centos/7.0.1406/updates/x86_64
```

URLさえわかっていれば任意のyumリポジトリを取り込むことができる。
ここではついでにextrasリポジトリとepelも取り込むことにしてみる。

```
# cobbler repo add --name c7-extras --mirror http://ftp.iij.ad.jp/pub/linux/centos/7.0.1406/extras/x86_64
# cobbler repo add --name epel7 --mirror http://ftp.iij.ad.jp/pub/linux/fedora/epel/7/x86_64
```

オプションとして「--yumopts "enabled=0"」を付けると、インストールしたOS上で明示的に有効にしないと利用できないリポジトリも追加することができる。
ここではepel-testingを「--yumopts "enabled=0"」付きで取り込むことにする。

```
# cobbler repo add --name epel7-testing --mirror http://ftp.iij.ad.jp/pub/linux/fedora/epel/testing/7/x86_64 --yumopts "enabled=0"
```

以下を実行すると取り込みを開始する。

```
# cobbler reposync
```

cobbler reposyncはcronに設定しておくと良い。
「--tries 2」は失敗時のリトライ回数（正確には、リトライを含めた実行回数。つまり設定値が"2"なら1回までリトライする）、「--no-fail」は1つのリポジトリでエラーになった時は通常次のリポジトリに行かずにその時点で終了するが、そうせずにエラーになっても次のリポジトリに行くようにするオプションである。

ただし、CentOSはポイントリリースが行われるたびにupdatesリポジトリが空になるので、先に上記ISOファイルの取り込み直しを行うべきであることに注意。

```
echo "48 2 * * * cobbler reposync --tries 2 --no-fail" >> /var/spool/cron/root
```

なお、cobbler reposyncに`--only <cobbler repo addの際に設定した名称>`というオプションを付けると、単一のリポジトリのみのミラーリングを行う。

## cobbler profileの設定変更

Cobblerは取り込んだOSをdistroという単位で、OSをどのようにインストールするかをprofileという単位で扱っている。
「c7」という名前でインポートした場合、自動的に「c7-x86_64」という名前のdistroとprofileが作成される。これは`cobbler distro list`や`cobbler profile list`で名称を得ることができる。

distroの設定をいじることはあまりないが、profileの方はいくらかいじる必要がある。特に変更されるのは「どのような内容でインストールすることにするか」と「どのリポジトリを利用するか」である。

RHEL系では自動インストール時にどのような内容でインストールするかはkickstartファイルに記述する。
CobblerにおいてRHEL系標準のkickstartファイルのテンプレートは /var/lib/cobbler/kickstarts/sample_end.ks であり、これは「c7-x86_64」プロファイルが作られた時点でこれを使うように設定されている（`cobbler profile report --name c7-x86_64`のKickstart項で確認できる）。

ここではこのファイルをコピーして、このプロファイル用に1つ作ることにしよう。

```
# cp /var/lib/cobbler/kickstarts/sample_end.ks /var/lib/cobbler/kickstarts/c7.ks
```

kickstartテンプレートの修正は説明がちょっと長いので別に章立てて行う。

作ったkickstartファイルのテンプレートと利用するリポジトリをプロファイルに紐づける。利用可能なリポジトリは前項でミラーしたものである。

```
# cobbler profile edit --name c7-x86_64 --repos "c7-updates c7-extras epel7 epel7-testing" --kickstart /var/lib/cobbler/kickstarts/c7.ks
```

## kickstartテンプレートの修正

kickstartファイルのテンプレートを修正することにより、どのような内容でインストールするかを決めることができる。

kickstartファイルのオプションは以下を参照すれば良い。
https://access.redhat.com/documentation/ja-JP/Red_Hat_Enterprise_Linux/7/html/Installation_Guide/sect-kickstart-syntax.html

今作業しているのがCentOS 7上なので、インストールした時の設定である /root/anaconda-ks.cfg を参考にするのも良いだろう。

とりあえず /var/lib/cobbler/kickstarts/sample_end.ks から変更しておきたいのは以下のようなものだ。

* auth: shadowファイルにユーザのパスワードを保存する時のハッシュアルゴリズムがmd5になっているので、最近の標準であるsha512にしておく。
* keyboard: 日本語106キーボードに。
* timezone: 東京に。

```
# sed -ri "s/(^auth ).*/\1--enableshadow --passalgo=sha512/" /var/lib/cobbler/kickstarts/c7.ks
# sed -ri "s/(^keyboard ).*/\1--vckeymap=jp106 --xlayouts='jp'/" /var/lib/cobbler/kickstarts/c7.ks
# sed -ri "s|(^timezone ).*|\1--utc Asia/Tokyo|" /var/lib/cobbler/kickstarts/c7.ks
```

kickstartファイルの%packagesと%endの間にはインストールさせたいパッケージを記述することができる。
Cobblerのkickstartテンプレートには、ここに`$SNIPPET('func_install_if_enabled')`という行があるが、何もしない限りこれは空白に変換されるので無視して良い。

%packagesと%endの間が空白でもcoreパッケージグループは指定されたものとなり、「最小限のインストール」相当となる。
ここはbaseパッケージグループもインストールさせることにする。パッケージ名ではなくパッケージグループ名を指定する場合には、パッケージグループ名の前に"@"を付ける。

何にせよ、coreパッケージグループにはwgetは含まれないが、Cobblerの恩恵を十分に享受するためにはwgetは必要なので追加しておいた方が良い。
wgetはbaseパッケージグループには含まれるので、これを追加した場合はそれで良い。

```
# sed -i '/^%packages$/a\@base' /var/lib/cobbler/kickstarts/c7.ks
```

**2015-04-05追記**： Cobbler 2.6.7にてwgetの代わりにcurlが使われるようになったので、特にwgetをインストールしなくても良くなった。

kickstartファイルの%postと%endの間には、インストール完了直前に実行させたいコマンドを記述する。Cobblerのkickstartテンプレートにはここにいろいろ書いてあるが、良いようにしてくれる部分なので削除しないで良い。

Cobblerでインストールしたコンピュータは、リポジトリとしてCobblerにあるミラーを使うように設定されているが、元々のOS標準のリポジトリが無効になっているわけではないので、同じ内容のリポジトリが2箇所に設定された状態になる。
以下の例では、よりネットワーク的に遠い /etc/yum.repos.d/CentOS-Base.repo に書かれた元々のOS標準のリポジトリ(base, updates, extras)を無効にしている。

これをsedでやるには%postと%endの間に次の3行を追加すれば良い。

```
sed -i '/^\[base\]$/a\enabled=0' /etc/yum.repos.d/CentOS-Base.repo
sed -i '/^\[updates\]$/a\enabled=0' /etc/yum.repos.d/CentOS-Base.repo
sed -i '/^\[extras\]$/a\enabled=0' /etc/yum.repos.d/CentOS-Base.repo
```

この3行を /var/lib/cobbler/kickstarts/c7.ks にsedで追加する例。

```
# sed -i "/^# End yum configuration$/i\sed -i '/^\\\[base\\\]$/a\\\enabled=0' /etc/yum.repos.d/CentOS-Base.repo" /var/lib/cobbler/kickstarts/c7.ks
# sed -i "/^# End yum configuration$/i\sed -i '/^\\\[updates\\\]$/a\\\enabled=0' /etc/yum.repos.d/CentOS-Base.repo" /var/lib/cobbler/kickstarts/c7.ks
# sed -i "/^# End yum configuration$/i\sed -i '/^\\\[extras\\\]$/a\\\enabled=0' /etc/yum.repos.d/CentOS-Base.repo" /var/lib/cobbler/kickstarts/c7.ks
```

あるいはyum-utilsパッケージを追加しているなら（baseパッケージグループに含まれている）、yum-utilsパッケージに含まれているyum-config-managerを使った方がよりきれいで正式っぽい手順になる。
この場合、%postと%endの間に次の3行を追加すれば良い。

```
yum-config-manager --disable base
yum-config-manager --disable updates
yum-config-manager --disable extras
```

この3行を /var/lib/cobbler/kickstarts/c7.ks にsedで追加する例。

```
# sed -i "/^# End yum configuration$/i\yum-config-manager --disable base" /var/lib/cobbler/kickstarts/c7.ks
# sed -i "/^# End yum configuration$/i\yum-config-manager --disable updates" /var/lib/cobbler/kickstarts/c7.ks
# sed -i "/^# End yum configuration$/i\yum-config-manager --disable extras" /var/lib/cobbler/kickstarts/c7.ks
```

# cobbler systemの作成

CobblerはOSインストール対象をsystemという単位で扱っている。

## すべてのOSインストールのデフォルト値を設定する

defaultという名前のsystemにセットした値はすべてのOSインストールのデフォルト値になる。

**2015-07-18注記**： 条件が良く分からないが`exception on server: "it seems unwise to overwrite this object, try 'edit'"`というエラーが返ってくることがある。その場合はメッセージ通りaddをeditにして`cobbler system edit --name default --profile c7-x86_64`を実行する。

```
# cobbler system add --name default --profile c7-x86_64
```

systemを追加変更した際はcobbler syncを実行する。

```
# cobbler sync
```

この状態だと、すべてのOSインストールは「c7-x86_64」プロファイルを使用して行われる（ただし、起動画面中に選択は可能）。

## 個々のOSインストールについて設定する

加えて任意で、MACアドレスをキーにして個々のコンピュータのインストール内容を変更することができる。
以下はMACアドレスが08:00:27:4B:14:B7のコンピュータがインストールしようとすると、IPアドレスが固定になり、hostnameが指定されるようにする例である。
このコンピュータではプロファイルは選択する余地なく「c7-x86_64」が選ばれる。

```
# cobbler system add --mac 08:00:27:4B:14:B7 --name test1 --profile c7-x86_64 --hostname test1.localdomain1 --interface enp0s3 --static 1 --ip-address 10.0.3.80 --subnet 255.255.255.0 --if-gateway 10.0.3.1 --name-servers 8.8.8.8
```

Cobbler 2.6.3辺りではバグでCentOS 7のインストール中に「--if-gateway」オプションを使用するとエラーになっていたが2.6.9時点で直っている。その場合は /etc/sysconfig/network にゲートウェイアドレスが書かれる「--gateway」オプションを使用する。「--if-gateway」オプションは /etc/sysconfig/network-scripts/ifcfg-xxx にゲートウェイアドレスが書かれる。

なお、プロファイルのコピーは以下で行うことができるので、新しいプロファイルを設定変更することによってコンピュータごとのインストール内容の変更もできる。

```
# cobbler profile copy --name c7-x86_64 --newname c7-x86_64-2
```

また、Cobbler設定ファイルのpxe_just_onceを以下で有効にしておくと、cobbler system addでMACアドレスを設定されたコンピュータは、一度PXEブートした後、PXEブートしないようになる。つまり、誤ってPXEブートしてOSがクリーンインストールされてしまうのを防ぐことができる。

```
# cobbler setting edit --name pxe_just_once --value 1
```

再度PXEブートさせたい場合は以下を実行してからネットワークブートする。

```
# cobbler system edit --name test1 --netboot-enabled True
```

systemを追加変更した際はcobbler syncを実行する。

```
# cobbler sync
```

これですべて完了である。
ネットワークブートしてCobblerのPXEサーバに問い合わせてくるコンピュータがあれば、自動でCentOS 7のインストールが行われる。