February 23, 2009

Gaebarを使ってみた


先日 App Gallery という GAE 上のサービスを始めてみました。サービスをやるからにはデータをバックアップしたいと思い、Gaebar を試してみたのでご紹介します。

なんと Gaebar の画面は django pony です!

Gaebar は Google App Engine Backup And Restore の略で、文字通り Google App Engine 用のバックアップ・リストアツールです。ゲイバーと読むそうです。この名前が良いですねw

Gaebar は Django のアプリケーションで簡単に使えます。GAE上で動く既存の Django アプリケーションにプラグインする事で、バックアップ・リストア機能を追加する事ができます。

残念ながら今は Django で動いているアプリケーションでしか使えませんが、少し頑張れば同じ事は別のフレームワークでも可能だと思います。

準備する

まずは Gaebar をダウンロードします。
Gaebar github から Download 機能を使ってアーカイブをダウンロードするか、下記のように git で clone しても良いです。

$ git clone git://github.com/aral/gaebar.git

またはあなたのプロジェクトが git を使っているなら下記のコマンドが良いかもしれません。

$ git submodule add git://github.com/aral/gaebar.git


方法はともあれ、プロジェクト直下に gaebar というディレクトリができていれば大丈夫です。

次に GAE の SDK にパッチを当てます。これは Gaebar がデータを python のファイルとしてダウンロードしてきてローカルのファイルシステムに保存するために必要なのです。方法が AralのBlog Entry に乗っていますが、この情報は少し古いので、SDK-1.1.9では下記のパッチを使ってください。

--- ../google_appengine/google/appengine/tools/dev_appserver.py.org 2009-02-26 11:33:33.000000000 +0900
+++ ../google_appengine/google/appengine/tools/dev_appserver.py 2009-02-20 17:04:46.000000000 +0900
@@ -1274,6 +1274,7 @@
allowed_symbols = self._WHITE_LIST_PARTIAL_MODULES[module.__name__]
for symbol in set(module.__dict__) - set(allowed_symbols):
if not (symbol.startswith('__') and symbol.endswith('__')):
+ module.__dict__['old_'+symbol] = module.__dict__[symbol]
del module.__dict__[symbol]

if module.__name__ in self._MODULE_OVERRIDES:


注意) app-engine-patch を使う場合は、settings.py で DJANGO_STYLE_MODEL_KIND = False にしないと動きませんでした。(少なくとも私は動かせませんでした。)動かせた方がいたら教えてください :-)

1. settings.py は下記のようにします。

INSTALLED_APPS = (
# Other apps...
'gaebar',
)


2. urls.py は下記のとおりです

urlpatterns = patterns('',

# ...other URLs

url(r'^gaebar/', include('gaebar.urls')),
)


3. app.yaml に static folder を追加します。

# Static: Gaebar
- url: /gaebar/static
static_dir: gaebar/static


4. index.yaml にインデックスを追加します。一回 dev server で Gaebar を動かせば自動で追加されます。

- kind: GaebarCodeShard
properties:
- name: backup
- name: created_at


5. Gaebar の設定を settings.py に追加します。

GAEBAR_LOCAL_URL: ローカル開発サーバの絶対 URL を書きます。
GAEBAR_SECRET_KEY: 秘密の文字列を記入します。誰にも秘密にしてください。
GAEBAR_SERVERS: dict でサーバーを列挙します。
GAEBAR_MODELS: tuple でバックアップするモデルを列挙します。

App Gallery で使用している設定のサンプルを下記に掲載します。

GAEBAR_LOCAL_URL = 'http://localhost:8000'
GAEBAR_SECRET_KEY = 'replace_with_your_secret_key'

GAEBAR_SERVERS = {
u'Deployment': u'http://app-gallery.appspot.com',
u'Staging': u'http://app-gallery-staging.appspot.com',
u'Local Test': u'http://localhost:8080',
}

GAEBAR_MODELS = (
(
'appgallery.models',
(u'Application', u'ThumbnailImage'),
),
(
'tags.models',
(u'Tag', u'TagApplication')
),
(
'favorites.models',
(u'Favorite',)
),
(
'ragendja.auth.custom_models',
(u'User',),
),
)


あと注意点がもう一つ。ローカル開発サーバーで django.contrib.csrf.middleware.CsrfMiddleware を使っているとバックアップがうまく行きませんでした。なので私はローカル開発サーバーでだけ CsrfMiddleware をオフにしています。

やった!これで Gaebar が使用できます。使う前に、Gaebar がどんな風に動くか説明しておきますね。

Gaebar は datastore のデータを Python code としてバックアップします。その Python code を実行する事でリストアします。バックアップは長くかかりますが、GAE はそれを許さないので、Gaebar は バックアップとリストアのプロセスを細切れにして ajax を使って繰り返し呼び出します。

デフォルトでは Gaebar は 5 つの Entity をバックアップし Python code に変換し、1MB の制限を回避するために 300KB くらいのコード断片として datastore に保存します。バックアップの過程では、このすぐ後に、コード断片をローカルサーバー側にダウンロードして保存する事になります。

もしあなたがもっと高い Quota を持っているなら、views.py をいじる事でこれらのデフォルト値を変えられます。

Gaebar を使う時は、十分にテストしてから使ってくださいね。万が一データが消失しても、私や Aral は責任を持てませんので。

使い方

A. リモートバックアップを取るには

1. Gaebar をあなたのアプリケーションと一緒に GAE にデプロイします

注意: デプロイする時に、gaebar/backups フォルダ内のバックアップデータも一緒にアップロードされる事を頭にいれておいてください。不必要ならバックアップデータは別の場所に移動した状態でデプロイすると良いでしょう。

2. 本番サーバで Gaebar にアクセスします。(例: http://myapp.appspot.com/gaebar/ )

3. Create New Backup ボタンをクリックします。

* バックアップをする時に、ローカル開発サーバーが動作している必要があります。

注意: reference error が発生した場合(存在しない Entity への ReferenceProperty)は、バックアップ時には無視されます。リストアすれば reference error は消滅します。

注意: 今までバックアップした一番大きなデータストアは 18995 行で 223 code 断片、35MB ありました。ローカル開発サーバーへのリストアは一晩中かかりました(ローカル開発サーバーの datastore は激遅なので)。もし記録を破ったら aral@aralbalkan.com に教えてあげてください :-)

注意2: バックアップ中の例外を詳しく見たい場合は、本番サーバーの settings.py で DEBUG_PROPAGATE_EXCEPTIONS = True と設定してください。


B. ローカルでリストアする

開発中に、リアル世界のデータを使ってテストするために、ローカルの開発サーバーにデータをリストアできます。

1. ローカル開発サーバの Gaebar ページに行きます。(例: http://localhost:8000/gaebar/ )
2. リストからリストアしたいバックアップデータを選びます。
3. 終わるまで待ちます。

tips: あらかじめ /var/tmp/ にある datastore の history ファイルのバックアップを取った方が良いです。

ローカルのデータストアは非常に遅いので、覚悟してください。

C. ステージング環境にリストアする

GAE にはバージョニング機能がありますが、datastore は別バージョン間でも共通です。ですからステージング用の別アプリを使用するのは良い考えでしょう。

本番とは別のアプリケーションスロットを用意して、そこにリストアしたいバックアップデータと一緒に Gaebar をデプロイします。後はローカル開発サーバーでのリストアと同じです。

D. 本番環境にリストアする

本番環境でトラブルがあった場合などは、バックアップからリストアできます。データストアのデータは上書きされるので注意してください。


実際に App Gallery でもバックアップ・リストアしてみましたが、完璧に動いています。Gaebar はかなり便利なのでみなさんも使ってみてはいかがでしょうか。

February 11, 2009

Mercurial deps extension

Mercurial で svn:externals みたいな事できないのか #mercurial irc で聞いてみたところ、deps extensionを使うと良いらしい。

Mercurial に同梱されてないので別途このへんから落として来て使う。

設定


deps.py を適当なところに置いて、hgrc に下記のように設定する。
[extensions]
hgext.deps =
# 又は deps.py を hgext dir 以外に置いたなら下記のようにする
# deps = /path/to/deps.py


ロケーション設定


依存関係のロケーションを設定する。これも hgrc に書く。ここで紹介する例は libfoo が外部 Mercurial リポジトリにあって、libbar は外部の CVS で管理されている場合。

[deps]
aliases = libfoo, libbar
alias.libfoo = /path/to/libfoo
alias.libbar = :pserver:anonymous@cvs.server.org:/sources/bar
alias.libbar.command = cvs -z3 -d$source co -r $rev -d $dest bar


実際の依存関係を設定


これはコマンドで行う。
$ hg deps -a libfoo -r 3a9b061bada1 -d lib/foo 0.9.1
$ hg deps -a libbar -r v0r7_8 -d lib/bar 0.9.1

$ hg deps -a libfoo -r f24139319bdb -d lib/foo 1.0
$ hg deps -a libbar -r v0r8_0 -d lib/bar 1.0


書式はこう

hg deps -a <ロケーション設定のalias名> -r <外部のリビジョン> -d  <本体のバージョン>


本体のバージョンに応じて外部リポジトリのリビジョンを変えたりできるわけか。

で、これをすると下記のような .hgdeps というファイルが出来る。これも hg add するのが良いみたい。
[1.0]
f24139319bdb libfoo lib/foo
v0r8_0 libbar lib/bar

[0.9.1]
3a9b061bada1 libfoo lib/foo
v0r7_8 libbar lib/bar


依存関係を持ってくる



下記のようにして clone するくらいしか機能は無いみたい。
$ hg depsclone 1.0


この例では、バージョン 1.0 用の外部依存関係を取ってくる事ができる。

まあすごく便利っていうわけでも無いし、使いたい人も限られてるだろうけど、Mercurial で svn:externals みたいな事がしたい人は試してみてください。