Tasking Manager をv2からv3にマイグレーションする

IDCF クラウドで動いていた Tasking Manager 2 を ConoHa VPS に立てた Tasking Manager 3 に移行する話です。
クッソ長い作業メモなので注意。

新しく Tasking Manager 3 を立てる場合はマイグレーション操作を飛ばして代わりにデータベースを初期化するコマンドを実行すればいいはずです。

移行前も移行後も Debian Stretch(9.4) の環境です。

$ cat /etc/debian_version 
9.4

v2 サーバでデータベースのバックアップを取る

まず v2 の動いているサーバーでデータベースのバックアップを取ります。

ここで PostgreSQL にアクセスしている PostgreSQL のユーザー名を控えます。今回は www-data ユーザーでした。

バックアップは pg_dump でサクッっと取れます。

$ sudo -u postgres pg_dump -d osmtm > v2.sql

出来上がった v2.sql は適当な方法で新しいサーバーに移す必要があります。

仮想マシンの設定

ConoHa VPS でイチから仮想マシンを設定します。
あまり使われないタスクマネージャーなので一番安い630円(税抜)のヤツにしました。
セット後に free -h で見たところ used: 347M free:29M みたいな表示でした。割とギリギリです。

仮想マシンの作成時に接続許可ポートを ssh(22) だけにして作成しました。メモリ512MBの一番安いヤツで Debian Stretch を選択しています。
最初に root で ssh 接続するため使うキーを登録できるので、できれば登録しておきます。

仮想マシンが上がってきたらローカルから ssh で接続します。

みたいなことをやりました。

// 更新する
# apt update && apt upgrade -y

// ユーザーを作る
# adduser zoar
# usermod -aG zoar

// ファイアウォールを設定する
# apt install ufw vim

# ufw allow ssh
# ufw allow 10022
# ufw enable

// sshd の設定を変更する
// ポートを 10022 、root ログインを拒否
# vi /etc/ssh/sshd_config

Port 10022
PermitRootLogin No

// 一般ユーザーの設定をする
# su zoar
# cd ~
$ mkdir .ssh
$ chmod 700 .ssh
$ touch ./.ssh/authorized_keys
$ vi ./.ssh/authorized_keys
// ここで一般ユーザー用の公開鍵を貼り付けます。

// ホスト名を変更
$ sudo hostname tm3

sshd を再起動させる前に VPS の管理画面から接続許可ポートをすべて許可に変更しておかないと ssh 接続できなくなるのはお約束。

// sshd の再起動
$ sudo systemctl restart sshd.service

// ufw から 22 ポートの接続許可を削除
$ sudo ufw delete allow 22

Python 3.6 と Node.js のインストール

Launchpad の PPA から入れようとしたら上手くいかなかったのでカッとなってソースからビルドしてインストールしました。

// ビルドに必要なパッケージのインストール
$ sudo apt install -y zlib1g-dev libssl-dev libreadline-dev \
libsqlite3-dev libbz2-dev libncurses5-dev libgdbm-dev \
liblzma-dev tk-dev zlibc

// python 3.6 のビルド・インストール
$ mkdir ~/src
$ cd ~/src
$ wget https://www.python.org/ftp/python/3.6.6/Python-3.6.6.tar.xz
$ tar xf Python-3.6.6.tar.xz
$ cd Python-3.6.6
$ ./configure
$ make
$ sudo make install
$ cd ~

pip を更新してみます。

$ sudo pip3.6 install --upgrade pip

続いて Node.js 8系をインストールします

$ sudo apt install -y curl
$ curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
$ sudo apt install -y nodejs

// npm も更新しておく
$ sudo npm i -g npm

Tasking Manager 3 の取得

git を使ってクローンしてくるだけなのでここは簡単。
python は venv 環境で実行するので venv と pip から必要なパッケージのインストールもします。

$ cd ~
$ sudo apt install -y git 
$ git clone https://github.com/hotosm/tasking-manager.git

// venv 環境で設定していきます
$ cd tasking-manager
$ python3.6 -m venv ./venv
$ source ./venv/bin/activate
$ pip3.6 install -r requirements.txt

データベースの設定

データベースは PostgreSQL とその拡張の PostGIS が使われるのでそれらをインストールします。

$ sudo apt install -y postgresql-9.6 postgresql-contrib-9.6
$ sudo apt install -y postgis postgresql-9.6-postgis-2.3

データベースにユーザーを設定して新しくデータベースを作成します。

// ユーザー作成
$ sudo -u postgres psql -c "CREATE USER hottm WITH PASSWORD 'hottm';"

// データベース作成 & ユーザー割り当て
$ sudo -u postgres createdb -T template0 tasking-manager -E UTF8 -O hottm

// PostGIS 拡張の組み込み
$ sudo -u postgres psql -d tasking-manager -c "CREATE EXTENSION postgis;"

データベースへのアクセス情報を環境変数に組み込んでおきます。

$ export TM_DB="postgresql://hottm:hottm@localhost/tasking-manager"

v2 で使っていたデータを v3 にマイグレーションします。
マイグレーションスクリプトによると、旧データのスキーマhotold に設定しておくといいようです。

マイグレーションではなく新しい Tasking Manager 3 を立てる場合は ./venv/bin/python3.6 manage.py db upgrade を実行してその他の環境変数設定まで飛べばOKのはずです。

SQL のファイルに対して sed を使っていますが、この方法が正しい方法なのかどうかは知りません。

// v2.sql にあるオーナー情報を変更
// 以前は www-data、今回は hottm のため
$ sed "s/www-data/hottm/g" -i ~/v2.sql

// tasking-manager データベースに v2.sql をリストア
$ psql -U hottm -h localhost -d tasking-manager < ~/v2.sql

// hotold スキーマを作成する
$ psql -U hottm -h localhost -d tasking-manager -c "CREATE SCHEMA hotold;"

テーブルのスキーマを変更するわけですが、1つずつ SQL 文が表示されるので全部実行してスキーマを変更するパターンとワンライナーでいっぺんに変更するパターンを作りました。
作業はワンライナーの方でやってます。

// テーブルのスキーマを1つずつ手動で変更する場合
$ psql -U hottm -h localhost -d tasking-manager -c "SELECT 'ALTER TABLE ' || schemaname || '.' || tablename || ' SET SCHEMA hotold;' FROM pg_tables WHERE tableowner ='hottm';"

// ワンライナーで一度に変更する場合
// ユーザーパスワードを間違えるとどこで間違えたのか見当が難しい
$ psql -U hottm -h localhost -d tasking-manager -c "SELECT 'ALTER TABLE ' || schemaname || '.' || tablename || ' SET SCHEMA hotold;' FROM pg_tables WHERE tableowner ='hottm';" | grep ALTER | xargs -IXX psql -U hottm -h localhost -d tasking-manager -c XX

// 点検する
$ psql -U hottm -h localhost -d tasking-manager -c "\dt"
// spatial_ref_sys だけが出てくれば OK

点検して spatial_ref_sys 以外のテーブルが出ていたら psql -U hottm -h localhost -d -c "ALTER TABLE public.%テーブル名% SET SCHEMA hotold;" して手動でスキーマを変更すればOK。

スキーマを変更したらv3用のテーブルをセットアップしてマイグレーションスクリプトを実行します。

// v3用テーブルの初期セットアップ
$ ./venv/bin/python3.6 manage.py db upgrade

// スクリプトのダウンロード
$ curl https://raw.githubusercontent.com/hotosm/tasking-manager/master/devops/tm2-pg-migration/migrationscripts.sql -o ~/migrationscripts.sql

// スキーマ情報の修正
// v3 用のスキーマを hotnew から public に変更
$ sed "s/hotnew/public/g" -i ~/migrationscripts.sql

# マイグレーションスクリプトの適用
$ psql -U hottm -h localhost -d tasking-manager < ~/migrationscripts.sql

Tasking Manager 2 で登録されたユーザーのロールが3のままだと User GET - unhandled error: 3 is not a valid UserRole みたいなエラーが出て動かなかったのでロールの値を1に変更します。

$ psql -U hottm -h localhost -d tasking-manager -c "SELECT id, username, role FROM users;" 
$ psql -U hottm -h localhost -d tasking-manager -c "UPDATE users SET role = 1 WHERE role = 3;"

動作した Tasking Manager 3 でロールを変更して値を確認したところロールと値の関係は次のような感じになっていました。

ロール
マッパー 0
管理者 1
プロジェクトマネージャ 2
確認者(Validator) 4
ブロックユーザー -1

なんで 3 を飛ばしたし。

必要な環境変数の設定

TM_ENV は開発環境か実稼働状態かのスイッチです。とりあえず dev にセットしておきます。
コンシューマーキーとコンシューマーシークレットは osm.org で設定してコピーしておく必要があります。 TM_SECRET は適当な文字列でいいっぽいです。

$ export TM_ENV="Dev"
$ export TM_SECRET=%pick any value%
$ export TM_CONSUMER_KEY="%SET YOUR CONSUMER KEY%"
$ export TM_CONSUMER_SECRET="%SET YOUR CONSUMER SECRET%"
$ export PYTHONUNBUFFERED=1

フロントエンド・サーバーの設定

Angular で書かれたフロントエンドのビルドします。

$ cd client
$ sudo npm install -g glup
$ npm install
$ gulp build
cd ..

サーバー側に用意されているアカウント認証でコールバックされる URL を設定します。
これを忘れるとアカウント認証しようとしても HOT の Tasking Manager に飛んだり 127.0.0.1 に帰ってきたりしてしまいます。
URL を変更した場合はこのファイルの修正をしてサービスを再起動させてあげた方がよさそう。

$ vi server/config.py
class ProdConfig(EnvironmentConfig):
 APP_BASE_URL = 'http://%Your machine IP address%'
    API_DOCS_URL = f'{APP_BASE_URL}/api-docs/swagger-ui/index.html?' + \
                   'url={APP_BASE_URL}/api/docs'
    LOG_DIR = '/var/log/tasking-manager-logs'
    LOG_LEVEL = logging.DEBUG

ここまで設定するとサーバーを起動できるはずなので試しに起動してアクセスしてみます。

// サーバーが 5000 で開くので ufw でポートを開けておく
$ sudo ufw allow 5000

// サーバーの起動
$ python3.6 manage.py runserver -d -r -h 0.0.0.0

アクセスしてみてログインとか出来れば大丈夫です。
sudo ufw delete 5000 するのを忘れないでください。

Nginx の設定

フロントエンドを表示してくれたりする Nginx を設定します。 まずは Nginx をインストールします。

$ sudo apt install -y nginx

Tasking Manager 3 用の設定ファルを用意します。

$ sudo touch /etc/nginx/sites-available/tm3
$ sudo vi /etc/nginx/sites-available/tm3

設定ファイルはユーザーのホームディレクトリに合わせて2カ所書き直します。

server {
    listen 80;
    location / {
     root /home/%replace_user_here%/tasking-manager/server/web/static/dist;
     try_files $uri $uri/ @api;
     expires max;
        client_max_body_size 200M;
     access_log off;
 }
 location @api {
     include proxy_params;
     proxy_pass http://unix:/home/%replace_user_here%/tasking-manager/tm3.sock;
 }
}

作った設定ファイルのシンボリックリンクを enabled 側に作ってデフォルトの設定を enabled から削除したら Nginx を再起動します。

$ sudo ln -s /etc/nginx/sites-available/tm3 /etc/nginx/sites-enabled/tm3
$ sudo rm /etc/nginx/sites-enabled/default
$ sudo service nginx restart

gunicorn の設定

サーバーを自動的に上げるために gunicorn を使って systemctl に登録します。

まずはログファイルの作成。
トラブった時にはここを見るので覚えておくこと。

$ sudo mkdir /var/log/tasking-manager-logs
$ sudo chmod a+rwx /var/log/tasking-manager-logs

systemctl の設定ファイルを作ります。

$ sudo vi /etc/systemd/system/tm3.service

デフォルトから書き換えないといけない場所がたくさんあって、ユーザー名に合わせて書き換える場所が4カ所、TM_SECRETを適当にセットするのが1カ所、OSM API のクライアントキーをセットするのがキーとシークレットでそれぞれ1カ所ずつと全部設定してあげる必要がある。
ここにある TM_ENV は実環境用の Prod を設定しておく。

[Unit]
Description=tm3 gunicorn daemon
After=network.target
[Service]
User=%replace_user_here%
Group=www-data
WorkingDirectory=/home/%replace_user_here%/tasking-manager
Environment=TM_DB=postgresql://hottm:hottm@localhost/tasking-manager
Environment=TM_SECRET=%pick any value%
Environment=TM_CONSUMER_KEY=%SET YOUR CONSUMER KEY%
Environment=TM_CONSUMER_SECRET=%SET YOUR CONSUMER SECRET%
Environment=TM_ENV=Prod
ExecStart=/home/%replace_user_here%/tasking-manager/venv/bin/gunicorn -b unix:/home/%replace_user_here%/tasking-manager/tm3.sock -w 7 --timeout 179 manage:application
Restart=always
[Install]
WantedBy=multi-user.target

設定ファイルができたらサービスをスタートさせる。

$ sudo systemctl start tm3.service
$ sudo systemctl enable tm3.service

これでアクセスしてみてログインできたりすれば完了。

なんだけど日本語 UI だと Tasking Manager 2 の頃のタスクが2回ずつ出てるの何でだろ…。
→ フロントエンドに問題があった様ですが、現在のバージョンではこの問題が解決されているのでこの現象は起こらないはずです。

f:id:k-side:20180707090136p:plain

英語 UI にすると1件になる。

f:id:k-side:20180707090236p:plain