Stashのバックアップメモ


# バージョンアップの前に、まずバックアップ！

気がついたら、どんどんバージョンが上がるAtlassian製品。
評価段階では、バックアップはあまり意識してなかったのですが、バージョンアップさせようとなると、まずはバックアップをしないとダメ。

単純なリポジトリなら、そのリポジトリのディレクトリだけまずはバックアップすればいいのですが...。
Stashはユーザ管理、プロジェクト管理（パーミッションとか）、フックの設定など色々機能があるので、それらのデータもバックアップが必要です。DBのダンプ、アプリケーションのバイナリのディレクトリやstashのhomeディレクトリのコピーで行けるとは思いますが、一応公式ドキュメントに沿って実施してみたので、そのメモになります。


# Stashはどうやってバックアップするの？
まずはここから...。

* [Data recovery and backups](https://confluence.atlassian.com/display/STASH/Data+recovery+and+backups) (Atlassian)

## どんなデータがあるの？

- StashのHOMEには、リポジトリデータがあります。キャッシュファイルやログファイルなどもあります。
 - Ref. [Stash Home direcroty](https://confluence.atlassian.com/display/STASH/Stash+home+directory)


- StashのDBには、プルリクエストのデータ（リポジトリのブランチへのポインタやコミットへのポインタ、プルリクエストの差分情報など）や、ユーザ管理情報などが入っています。

## Gitのデータ本体はどこ？

上記の説明から、リポジトリ本体のデータはSTASH_HOMEにあることがわかりました。STASH_HOMEは、デフォルトでは、以下の通り。

```setenv.sh
STASH_HOME="/var/atlassian/application-data/stash"
```

STASH_HOMEの下を少し探って行くと、それらしいディレクトリがありました。

```
# pwd 
/var/atlassian/application-data/stash/shared/data/repositories
# tree -L 2 -d
.
├── 1
│   ├── branches
│   ├── hooks
│   ├── info
│   ├── logs
│   ├── objects
│   ├── refs
│   └── stash-refs

.... [Snip] ....

└── 3
    ├── branches
    ├── hooks
    ├── info
    ├── logs
    ├── objects
    ├── refs
    └── stash-refs

50 directories
```

ですが、StashのWeb画面から見るリポジトリ名ではなく、番号...。
本当にここでいいの？

## リポジトリ名はDBから

リポジトリ情報は、stash用DBのrepositoryテーブルに入っているようです。
対応するidが、/var/atlassian/application-data/stash/shared/data/repositories/ のディレクトリの番号に対応するようです。

以下、PostgreSQLの場合の例です。

```source:psql
stashdb=# \d repository
 id           | integer                | not null
 slug         | character varying(128) | not null
 name         | character varying(128) | not null
 state        | integer                | not null
 origin_id    | integer                | 
 project_id   | integer                | not null
 scm_id       | character varying(255) | not null
 hierarchy_id | character varying(20)  | not null
 is_forkable  | boolean                | not null
 is_public    | boolean                | not null
```

## データを確認してみます

本当にここでいいのか、14番のGitリポジトリを、直接参照してみます。（git logでサマリのみ）

```
# pwd
/var/atlassian/application-data/stash/shared/data/repositories/14
# git log --oneline
eb62911 Add readme.
75e513c Initial import.
```
コミットログを見ると、Author情報もちゃんと入っています。
一番大事なのはここ、というので良さそうです。

# Stash Backup Clientでトライ

とりあえず、すぐできる方がいいので、Backup Clientを使うことにします。特徴は、以下の通り。

- コーディングの必要は無く、すぐ使えます
- ローカルファイルシステムにバックアップされます
- バックアップ中は、Stashにロックがかかります
- 利用するDBに依存しない共通の形式でバックアップします

## クライアントのセットアップ

Atlassianからバックアップ用クライアントをダウンロードします。
以下のページのリンクから取得。

- [Using the Stash Backup Client](https://confluence.atlassian.com/display/STASH/Using+the+Stash+Backup+Client)

どこに置いてもいいみたいですが、/opt/atlassian/stash-backup-client/ 以下にしました。
Javaのバージョンに関しては注意書きがありますが、OSでフォルトのJavaは入れていなかったので、Java8にしてみました。

### 設定ファイル

バックアップに当たっては、最低でも下記のパラメータが必要とのこと。backup-config.properties もしくは、javaの引数で指定となります。

- stash.home
- stash.user / stash.password (StashのWebにアクセスするAdminアカウント）
- stash.baseUrl

## バックアップ実行

設定はbackup-config.propertiesに指定したので、いざ実行。
こんな感じで出力が。(token部分は適当に変更しています）

```
# java -jar stash-backup-client.jar 
2014-11-01 23:38:25,491 INFO         Initializing
2014-11-01 23:38:28,103 INFO         Using Stash 3.2.0
2014-11-01 23:38:28,237 INFO         Contacting Stash
2014-11-01 23:38:28,542 INFO         Stash has been locked for maintenance. It may be unlocked with token: xxxxxxxxxxxx
2014-11-01 23:38:28,747 INFO         Starting database backup on Stash. It may be cancelled with token: xxxxxxxxxxxx
2014-11-01 23:38:33,094 INFO   (11%) Verifying Stash home

... [Snip] ...

2014-11-01 23:39:07,801 INFO   (53%) Downloading database backup zip from Stash
2014-11-01 23:39:07,903 INFO  (100%) Backup complete: /opt/atlassian/stash-backup-client-1.5.0/backups/stash-20141101-233907-901.tar
2014-11-01 23:39:07,909 INFO  (100%) Unlocking Stash using token: xxxxxxxxxxxx
```

まだ規模が小さいので、あっという間に終わってしまいました。
この処理の間、こんなことをしているようです。

- JavaのクライアントからStashのWebにアクセスし、画面をメンテナンスモードに切り換える
- DBのバックアップ取得
- StashのWeb(API) 経由で、最新のDBバックアップをダウンロード（GET http://stash_server/admin/backups/latest)
- 上記＋STASH_HOMEの必要な箇所をtarでまとめておしまい

![stash-backup-screen.png](https://qiita-image-store.s3.amazonaws.com/0/27976/c5315630-ba2a-8097-224a-b66afdfcb7c4.png "stash-backup-screen.png")


DBのダンプは、DBの形式に依存しない、StashがインポートできるXML形式の模様です。
tarの中身を覗いてみると、確かに STASH_HOME/shared/data/repositories/ の中身が入っています。

# リストア＆リカバリは？

パラメータ指定をしない場合は、デフォルトではバックアップファイルは、バックアップクライアント/backups/ 以下に保存されます。リストア、リカバリはこんな手順。

- tarを展開
- STASH_HOME以下のデータをバックアップデータで入れ替え。（キャッシュやプラグイン、ログ用のディレクトリは除外）
- stash用のDBのスキーマから、テーブルを削除する（接続情報は変更しない）
- stash-restore-client.jar というリストア用のJava Clientで、XMLデータからDBへデータをリストア

stash-restore-client.jarは、空になったDBにしかデータをリストアしない模様。
バックアップのXMLから、DB本体も違うものに変更する場合は、JDBCの設定が要るようです。

以上、ひととおりAtlassian製のバックアップツールでのバックアップ手順を確認しました。
ダウンタイム＆リカバリは長めになってしまうそうですが、確かに手軽です。

わたしはビルドするネタは持っていないのですが、Bambooでバックアップタスクを管理するのも楽しそうですね。

さて、Stashのアップデートはこれからです....。

## 補足

Java8 (最新）では問題ありませんでした。