snapperで遊ぼう

# snapperとは？

lvmとかbtrfsでsnapshot取るのに便利なopenSUSE由来の便利なツール。
openSUSEではYaST2とかと連動していてGUIで便利〜な感じで使えるが、他では無理っぽい。yast2-snapperパッケージだそうで、移植できないかなー

GUIはともかく、YaSTのような共通の設定変更フレームワークが無いから無理か...YaSTで変更の前後に設定差分を取る、ような形が出来ないとダメか。GNOMEとかKDEではそういうのないのかね。

## Debianでのインストールと初期設定
```
sudo apt install snapper/experimental
```
このメモを書いている時にはDebianでの最新のsnapperパッケージはexperimentalにぶち込まれてる（というかメンテナの許可もらってぶち込んだ）ので、experimentalを明示的に付けてインストール。

```
sudo snapper create-config /
```
/etc/snapper/configs 以下に設定をし、そのファイル名を/etc/default/snapperで指定する...のだけど、snapper create-configでやったほうが面倒がなくて良い。デフォルトでは設定は/etc/snapper/configs/rootに出力される。


うまくいけば特に何もメッセージ出力されない。ログが /var/log/snapper.log に出力されるようになるので確認。

```
$ sudo cat /var/log/snapper.log 
2016-08-13 14:14:13 MIL libsnapper(22943) snapperd.cc(main):270 - Requesting DBus name
2016-08-13 14:14:13 MIL libsnapper(22943) snapperd.cc(main):274 - Loading snapper configs
2016-08-13 14:14:13 MIL libsnapper(22943) Snapper.cc(getConfigs):269 - Snapper get-configs
2016-08-13 14:14:13 MIL libsnapper(22943) Snapper.cc(getConfigs):270 - libsnapper version 0.3.3
2016-08-13 14:14:13 MIL libsnapper(22943) AsciiFile.cc(reload):114 - loading file /etc/default/snapper
2016-08-13 14:14:13 MIL libsnapper(22943) AsciiFile.cc(getValue):235 - key:SNAPPER_CONFIGS value:
2016-08-13 14:14:13 MIL libsnapper(22943) snapperd.cc(main):278 - Listening for method calls and signals
2016-08-13 14:14:13 MIL libsnapper(22943) Snapper.cc(createConfig):310 - Snapper create-config
2016-08-13 14:14:13 MIL libsnapper(22943) Snapper.cc(createConfig):311 - libsnapper version 0.3.3
2016-08-13 14:14:13 MIL libsnapper(22943) Snapper.cc(createConfig):313 - config_name:root subvolume:/ fstype:btrfs template_name:default
2016-08-13 14:14:13 MIL libsnapper(22943) Snapper.cc(getConfigs):269 - Snapper get-configs
2016-08-13 14:14:13 MIL libsnapper(22943) Snapper.cc(getConfigs):270 - libsnapper version 0.3.3
2016-08-13 14:14:13 MIL libsnapper(22943) AsciiFile.cc(reload):114 - loading file /etc/default/snapper
2016-08-13 14:14:13 MIL libsnapper(22943) AsciiFile.cc(getValue):235 - key:SNAPPER_CONFIGS value:
2016-08-13 14:14:13 MIL libsnapper(22943) AsciiFile.cc(reload):114 - loading file /etc/default/snapper
2016-08-13 14:14:13 MIL libsnapper(22943) AsciiFile.cc(getValue):235 - key:SNAPPER_CONFIGS value:
2016-08-13 14:14:13 MIL libsnapper(22943) AsciiFile.cc(save):139 - saving file /etc/default/snapper
2016-08-13 14:14:13 MIL libsnapper(22943) AsciiFile.cc(reload):114 - loading file /etc/snapper/config-templates/default
2016-08-13 14:14:13 MIL libsnapper(22943) AsciiFile.cc(save):139 - saving file /etc/snapper/configs/root
2016-08-13 14:14:13 MIL libsnapper(22943) AsciiFile.cc(reload):114 - loading file /etc/snapper/configs/root
2016-08-13 14:14:13 MIL libsnapper(22943) AsciiFile.cc(getValue):235 - key:SUBVOLUME value:/
2016-08-13 14:14:13 MIL libsnapper(22943) AsciiFile.cc(getValue):235 - key:ALLOW_USERS value:
2016-08-13 14:14:13 MIL libsnapper(22943) AsciiFile.cc(getValue):235 - key:ALLOW_GROUPS value:
```

createしたらsnapshotが取られる。

```
$ sudo snapper create
$ sudo snapper list
種類 | # | 前 # | 日付                            | ユーザ | クリーンアップ | 説明  | ユーザデータ
-------+---+-------+-----------------------------------+-----------+-----------------------+---------+-------------------
single | 0 |       |                                   | root      |                       | current |                   
single | 1 |       | 2016年08月13日 14時21分39秒 | root      |                       |         |     
```
0はcreate-configした時？

```
$ sudo ls -al /.snapshots/1
合計 20
drwxr-xr-x 1 root root  32  8月 13 14:21 .
drwxr-x--- 1 root root   2  8月 13 14:21 ..
-rw------- 1 root root 117  8月 13 14:21 info.xml
drwxr-xr-x 1 root root 236  8月 13 14:02 snapshot
```

ここでは /.snapshots に先ほどの１に8月 13 14:21時点でのsnapshotが取られているのがわかる。このsnapshotの位置は/etc/snapper/configs/* なファイルでどこにsubvolumeを指定しているかでわかる、のかな。

```
# subvolume to snapshot
SUBVOLUME="/"
```


## ユーザー追加する
毎度sudo指定もアホらしいので、/etc/snapper/configs/rootでユーザー指定。

```
$ snapper list                                                                                                                                                                                                 
許可がありません。
$ snapper list
許可がありません。
```

あれ？ダメっぽい。

```
$ man snapper
...（ちょっとmanを読んでた）
$ snapper list
種類 | # | 前 # | 日付                            | ユーザ | クリーンアップ | 説明  | ユーザデータ
-------+---+-------+-----------------------------------+-----------+-----------------------+---------+-------------------
single | 0 |       |                                   | root      |                       | current |                   
single | 1 |       | 2016年08月13日 14時21分39秒 | root      |                       |         |       
```

時間が経ったら問題なくなった。

## aptでパッケージ入れた時とかに動くようにしたら？

https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=770938 のアイデア。
aptが走るときにpreとpostでsnapshot取って差分をサクッと取れるようにするというもの。

/etc/apt/apt.conf.d/80snapper とかに書けばいいんだけども、どうやってpost snapshot時にpreのsnapshotを指定するのか、って考えておかないとダメやね。

```
$ snapper create -p
8
```

これで、番号が取れるなら、どっかに吐いといてそれを参照すればいいかーと思いついた。問題はどこに吐くのがいいのか、の一点。/var以下かな、と思うのだけどもどこが適当かが思いつかない。一時的に/var/tmp/snapper-aptとかにするか、ということで/etc/apt/apt.conf.d/80snapperとしてこんな設定で動いた。

```
# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=770938
  DPkg::Pre-Invoke       { "if [ -x /usr/bin/snapper ]; then snapper create -d apt -t pre -p > /var/tmp/snapper-apt ; fi"; };
  DPkg::Post-Invoke      { "if [ -x /usr/bin/snapper ]; then snapper create -d apt -t post --pre-number=`cat /var/tmp/snapper-apt` ; fi"; };
```

残ってる問題は、デフォルトでconfigurationが存在しないためにこれをそのまま入れちゃうと、エラー吐くだけという。

### Gentooの方がスマートだな
https://wiki.gentoo.org/wiki/Snapper みると
* 単なるシェルスクリプトなので番号が変数で取れる
* descriptionに変更点を突っ込めてる
これは真似したい...。


## snapper list -t pre指定ではダメ。-t pre-postが正解
```
$ snapper list -a
種類 | # | 前 # | 日付                            | ユーザ | クリーンアップ | 説明  | ユーザデータ
-------+---+-------+-----------------------------------+-----------+-----------------------+---------+-------------------
single | 0 |       |                                   | root      |                       | current |                   
single | 1 |       | 2016年08月13日 14時21分39秒 | root      |                       |         |                   
pre    | 2 |       | 2016年08月13日 14時57分39秒 | root      |                       |         |                   
post   | 3 | 2     | 2016年08月13日 15時02分44秒 | henrich   |                       |         |                   

$ snapper list -t single
# | 日付                            | ユーザ | 説明  | ユーザデータ
--+-----------------------------------+-----------+---------+-------------------
0 |                                   | root      | current |                   
1 | 2016年08月13日 14時21分39秒 | root      |         |                   

$ snapper list -t pre
不明なスナップショットの種類です。
```
なんでtype指定がpreだとダメなのかが不明。。。と思ったら、指定は「pre-post」にしないとダメだった。

## openSUSEを参考に設定するとしたら

* 「既定では、 YaST と zypper のスナップショットは最大 100 個までを保持する 設定」

　これはsnapperの設定じゃない気がする。どこにあるんだ、これ。

* 「YaST のスナップショットには 説明 内に yast モジュール名 と書かれるほか、 zypper のスナップショットは zypp (zypper) と 書かれます」

　zypperについては apt でも同様に出来た。yastは無理だなぁ。

* 「/var/log などの特定のディレクトリについては、スナップショットの 対象から外しています。これらのディレクトリにはログファイルなどが含まれるため、 ログを削除してしまうと問題の追跡が困難になってしまうためです。スナップショット対象から 外す目的で、これらのディレクトリにはサブボリュームを設定して対応しています。」

　うーん、そもそもがデフォルトインストールで / が btrfs にしてるopenSUSEとは違うよなぁ。あと複数のsubvolumeが設定されているようだし、そこの設定の合意を取らないと難しい。

　お、mksubvolumeコマンドを使うと良いっぽい。

https://en.opensuse.org/openSUSE:Snapper_Tutorial も参照

## RHEL7の場合
https://access.redhat.com/documentation/ja-JP/Red_Hat_Enterprise_Linux/7/html/Storage_Administration_Guide/ch-snapper.html

```
/home ディレクトリーを Snapper 設定に含める必要があります。これを実行するには、以下を true にする必要があります。
```
これ、訳と説明おかしくない？

# オプション指定が頭に浮かばない

bash-completion書こう→一旦書いた。
でも、snapshot番号の取得があれだな

 * /etc/snapper/configs ファイルは root しか読めないのでどこにSUBVOLUMEあるのか読み取れないよね…
 * /etc/fstabのbtrfsファイルシステムのやつから引っ張る？
 * lvmの場合はどうするんだよ

.snapshotsディレクトリからの取得は権限の関係でopenSUSEだと出来なかったので、無し。というかなんでDebianだと/.snapshots見れるのよ、良くないんじゃない？

ということはsnapper listコマンドからの取得にすると良さそうな。


# SUSE specificな記述は無くしたいな

snapper(8) says "see also snapper-zypp-plugin(8)" but it exists only in openSUSE and SUSE.

>>/etc/sysconfig/snapper
>>Global configuration file.

global configuration directory is configurable, it should be changed with in it.


# なんかエラーが出てる
```
$ sudo grep fail /var/log/snapper.log                                                                     
2016-09-14 00:55:36 WAR libsnapper(25901) FileUtils.cc(SDir):88 - THROW: open failed path://.snapshots errno:2 (No such file or directory)
2016-09-14 00:55:38 WAR libsnapper(25901) FileUtils.cc(SDir):88 - THROW: open failed path://.snapshots errno:2 (No such file or directory)
2016-09-14 01:00:14 WAR libsnapper(29847) FileUtils.cc(SDir):88 - THROW: open failed path://.snapshots errno:2 (No such file or directory)
2016-09-14 01:20:33 WAR libsnapper(12350) FileUtils.cc(SDir):88 - THROW: open failed path://.snapshots errno:2 (No such file or directory)
2016-09-14 01:20:34 WAR libsnapper(12350) FileUtils.cc(SDir):88 - THROW: open failed path://.snapshots errno:2 (No such file or directory)
2016-09-14 01:21:51 WAR libsnapper(13688) FileUtils.cc(SDir):88 - THROW: open failed path://.snapshots errno:2 (No such file or directory)
2016-09-14 01:22:03 WAR libsnapper(13688) FileUtils.cc(SDir):88 - THROW: open failed path://.snapshots errno:2 (No such file or directory)
2016-09-14 14:13:39 WAR libsnapper(31356) FileUtils.cc(SDir):88 - THROW: open failed path://.snapshots errno:2 (No such file or directory)
2016-09-14 14:39:03 WAR libsnapper(18083) FileUtils.cc(SDir):88 - THROW: open failed path://.snapshots errno:2 (No such file or directory)
2016-09-14 14:39:48 WAR libsnapper(18083) FileUtils.cc(SDir):88 - THROW: open failed path://.snapshots errno:2 (No such file or directory)
2016-09-14 15:00:47 WAR libsnapper(3610) FileUtils.cc(SDir):88 - THROW: open failed path://.snapshots errno:2 (No such file or directory)
2016-09-14 16:53:29 WAR libsnapper(20688) FileUtils.cc(SDir):88 - THROW: open failed path://.snapshots errno:2 (No such file or directory)
2016-09-14 17:00:31 WAR libsnapper(25977) FileUtils.cc(SDir):88 - THROW: open failed path://.snapshots errno:2 (No such file or directory)
2016-09-14 17:23:02 WAR libsnapper(10474) FileUtils.cc(SDir):88 - THROW: open failed path://.snapshots errno:2 (No such file or directory)
2016-09-14 17:23:03 WAR libsnapper(10474) FileUtils.cc(SDir):88 - THROW: open failed path://.snapshots errno:2 (No such file or directory)
2016-09-14 18:00:05 WAR libsnapper(30673) FileUtils.cc(SDir):88 - THROW: open failed path://.snapshots errno:2 (No such file or directory)
2016-09-14 18:38:01 WAR libsnapper(18338) FileUtils.cc(SDir):88 - THROW: open failed path://.snapshots errno:2 (No such file or directory)
2016-09-14 18:38:04 WAR libsnapper(18338) FileUtils.cc(SDir):88 - THROW: open failed path://.snapshots errno:2 (No such file or directory)
2016-09-14 19:00:02 WAR libsnapper(16164) FileUtils.cc(SDir):88 - THROW: open failed path://.snapshots errno:2 (No such file or directory)
2016-09-14 19:53:48 WAR libsnapper(2587) FileUtils.cc(SDir):88 - THROW: open failed path://.snapshots errno:2 (No such file or directory)
2016-09-14 19:54:05 WAR libsnapper(2587) FileUtils.cc(SDir):88 - THROW: open failed path://.snapshots errno:2 (No such file or directory)
2016-09-14 19:54:55 WAR libsnapper(2587) FileUtils.cc(SDir):88 - THROW: open failed path://.snapshots errno:2 (No such file or directory)
2016-09-14 19:54:57 WAR libsnapper(2587) FileUtils.cc(SDir):88 - THROW: open failed path://.snapshots errno:2 (No such file or directory)
2016-09-14 20:00:09 WAR libsnapper(10429) FileUtils.cc(SDir):88 - THROW: open failed path://.snapshots errno:2 (No such file or directory)
2016-09-14 21:00:07 WAR libsnapper(21089) FileUtils.cc(SDir):88 - THROW: open failed path://.snapshots errno:2 (No such file or directory)
```