OSMI simple views をビルドしてローカルで OSM データのエラーを確認する
OpenStreetMap のエラー訂正をするにあたって、エラーの確認と編集のスタートを OSM Inspector で行っています。
しばらく前から OSM Inspector で表示されているエラーを検出するためのプログラム OSMI Simple Views が GitHub で公開されていて、これを使えば不定期に更新される OSM Inspector からではなく、自分で任意に更新できるローカルデータベースからエラー訂正できると思いビルドを試してみました。
ビルドを試した環境は docker の ubuntu:latest で、実行時は Ubuntu 16.04.2 LTS
でした。
横着して全部 root で実行しています。
環境構築
最初に必要なパッケージ類をインストールします。
# apt-get update # apt-get install wget git build-essential cmake libexpat1-dev zlib1g-dev libbz2-dev libsparsehash-dev libboost-dev libgdal-dev libproj-dev doxygen graphviz libsqlite3-dev sqlite3 cppcheck -y
osmium のビルド
OSMI Simple Views のバックエンドで動く osmium をビルドします。
# cd /mnt # git clone https://github.com/osmcode/libosmium.git # cd libosmium # mkdir build # cd build # cmake .. # make cd ../../
osmi_simple_views のビルド
続いて osmi_simple_views をビルドします。
# git clone https://github.com/geofabrik/osmi_simple_views.git # cd osmi_simple_views # ln -s ../libosmium/include libosmium # mkdir build # cd build # cmake .. # make
make
した時にいくつか hpp ファイルが見つからなくてビルドが停止することがありましたが、この手順で入れるとビルドが通りました。
よくわかりません。
osmi_simple_views/build/src
に実行ファイルがあるので、それを叩くとエラー情報の入った SQLite のファイルが出来上がります。
# cd src # wget http://download.geofabrik.de/asia/japan/kanto-latest.osm.pbf # ./osmi_simple_views -t geometry kanto-latest.osm.pbf kanto_error.sqlite
出来上がった kanto_error.sqlite
を QGIS にツッコむとエラーが出ているポイントやウェイを表示することができました。
d3-hexbin でポイントデータを表示する
ポイントの点密度を六角形で表示してくれる d3 のプラグインがあったので試してみました。
今回は OpenStreetMap から埼玉県内のコンビニのデータを取り出して表示しました。
コードなんかはこちら
なんかカッコイイから使ってみたんですが、冷静に考えて自分の用途ではこのプラグインを使うことはなさそうですね…。
ローカルサーバに Gogs をインストールする
ちょっとローカルに Git のリポジトリを置いておくサーバが欲しかったので docker コンテナにインストールしました。
今回は http によるアクセスのみで、SSH によるアクセスはできない設定です。
# cat /etc/debian_version 8.8
コンテナの3000ポートとホストの3000ポートを繋いでいます。
Gogs のインストールはドキュメントを読むと楽勝です。
今回はバイナリ版を入れています。
ざっくり環境を整える
sudo と vim と wget を入れておきます。なぜか curl も気分で入れました。
# apt-get install sudo vim wget curl -y # adduser zoar # usermod -aG sudo zoar # su zoar
MySQL Server のインストール
$ sudo apt-get install mysql-server -y $ sudo /etc/init.d/mysql start
コントロールするユーザーとデータを格納するデータベースを作ります。
$ mysql -uroot -p mysql> CREATE DATABASE gogs; mysql> CREATE USER zoar@localhost IDENTIFIED BY '%パスワード%'; mysql> use mysql mysql> SELECT User FROM user WHERE User = 'zoar'; +------+ | User | +------+ | zoar | +------+ mysql> GRANT all ON gogs.* TO zoar@localhost; mysql> \q
Go言語のインストール
apt-get で入れようとすると 1.3 が落ちてくるので godeb を使って 1.8 をインストールします。
$ cd /tmp $ wget https://godeb.s3.amazonaws.com/godeb-amd64.tar.gz $ tar xvf godeb-amd64.tar.gz $ sudo mv godeb /usr/local/bin/
godeb から Go 言語をインストールする。
$ godeb list | more $ godeb install 1.8
Gogs バイナリのインストール
バイナリを落としてきて展開すればOK。
横着なのでホームディレクトリに直接展開しています。
$ cd /tmp $ wget https://cdn.gogs.io/0.11.19/linux_amd64.tar.gz $ cd ~ $ tar xvf /tmp/linux_amd64.tar.gz
Gogs を起動してウェブインターフェイスにアクセスすれば完了
$ cd gogs $ ./gogs web
変更したのは次の部分。
最後に Gogs をインストール
をクリックしておしまい。
最初に作成したユーザーが Gogs のサイト管理もできる権限に設定されます。
普通の(?) http で接続できるようにする
操作するときに :3000
を付けるのが面倒な感じだったので docker ホストで動いてる apache2 にプロキシ設定を追加して /gogs でもアクセスできるようにしました。
まずはコンテナにアタッチして設定を変更します。
host$ docker attach %hash% container$ vi ./custom/conf/app.ini ROOT_URL = http://%サーバーIP%:3000 ↓ ROOT_URL = http://%サーバーIP%/gogs
再度起動しておく
container$ ./gogs web
Ctrl+p q
でデタッチしてホストの設定をいじる
host$ sudo vi /etc/apache2/mods-enabled/proxy.conf ProxyPass /gogs http://%サーバーIP%:3000 ProxyPassReverse /gogs http://%サーバーIP%:3000 host $ sudo service apache2 reload
これで http://%サーバーIP%/gogs
にアクセスして gogs を使えるようになりました。
SELinux を有効にしたまま CentOS 7 で OpenStreetMap のタイルサーバを構築する
Qiita で OpenStreetMap のタイルサーバを構築する記事が公開されていました。
OS が CentOS なので SELinux を無効にする記述がありましたので、とりあえず SELinux を有効にしたままタイルサーバを動かせないか試してみました。
とりあえず動くことは動いたんですが、rendoer.sock
の SELinux コンテキストを意義的に正しく設定できてないのでセキュリティホールになっている可能性が否めません。
目的を達成できているか不明確ですが、隠して置いても正しい設定が見つかるわけじゃないのでとりあえず公開してみます。
最初には SELinux を有効にして動かす差分的なもの、後半には自分が試した記録を載せています。
SELinux の設定
先の設定方法でブラウザから地図を確認できたら SELinux を再度有効にします。
$ sudo vi /etc/selinux/config SELINUX=enforcing #SELINUX=disabled
再起動すると /var/run
に作成したディレクトリが消されてしまうので設定ファイルを書きます。
$ sudo vi /etc/tmpfiles.d/renderd.conf d /var/run/renderd 0777 root root
再起動
$ sudo reboot
サーバが上がってきたら動作確認のために一時的に SELinux の状態を確認して Permissive にします。
$ getenforce Enforcing $ sudo setenforce 0 $ getenforce Permissive
フォアグランドで動かして試します。
$ sudo /usr/local/bin/renderd -f
http://%サーバーIP%/
へアクセスして地図が表示されれば OK。
動作していることがわかったら SELinux を Enforcing に戻します。
$ sudo setenforce 1 $ getenforce Enforcing
そのまま http://%サーバーIP%/
へアクセスするとタイル画像へアクセスできない Openlayers の地図もどきが表示されます。
audit.log の中で `type=AVC‘ から始まる denied された renderd のログを確認できるはずです。
$ sudo cat /var/log/audit/audit.log | grep renderd
renderd.sock へのアクセスが制限されないように SELinux への登録を行います。
まずは必要なパッケージのインストール
$ sudo yum -y install policycoreutils-python
ログから renderd に関する記述を抜き出して audit2allow
で設定ファイルを作成します。
できた設定ファイルを semodule に食わせると SELinux 側に登録されます。
$ cd ~/src $ sudo ausearch -m avc | grep renderd | audit2allow -M renderd $ sudo semodule -i renderd.pp
もう一度 renderd を動かしてタイルが表示されるか確認します。
$ sudo /usr/local/bin/renderd -f
タイルが表示されたら renderd をバックグラウンドで走らせておけばOKです。
$ sudo sh -c "/usr/local/bin/renderd -f > /var/log/renderd.log 2> /var/log/renderd.log &"
こんな感じで SELinux が有効でもタイルサーバを動かすことができました。
試した記録
ここからは自分が今回テストした環境と設定の全部です。全部見る必要はないです、長いし。
VirtualBox で新しい CentOS をセットして試しています。
Ruby から Slack の WebHooks URI を叩いてメッセージをポストする
Ruby スクリプトで Slack の WebHooks URI を叩いてスクリプトの実行結果などをポストさせたかった時に調べました。
Ruby Gems には WebHooks を叩くための gems がいくつかあります。例えば slcak-notifier などなど。
今回は本当にスクリプトから Slack に対してポストできれば良かったので
res = Net::HTTP.post_form(URI.parse('http://www.example.com/'), {'payload'=> %JSON%})
とかやっちゃえばおしまいです。
実際に実装した時はクラスとか作りましたがこんな雰囲気で。
WebHooks は URI 叩けば反応してくれるので楽でいいですね。
コマンドの終了を通知(?)してくれるコマンド
1000個ある Excel のファイルを PDF に変換するとか結構時間かかるんだけど、それが終わったら別のコマンド実行したいとかたまにあるので、コマンドレットの後ろに付けて一連の実行終了を教えてくれるような PowerShell スクリプトです。
Push-Notification
を実行すると Invoke-RestMethod で Slack の Webhook を殴ってるだけです。
Slack 側の設定でスマホなりデスクトップ通知なりをやっておけばコマンドの終了を知ることができるはず。
PS> . .\Push-Notification.ps1 PS> Get-ChildItem -Recurse | Out-File ..\list.txt -Encoding utf8 | Push-Notification
あー、終了時刻を入れさせたけど Slack のタイムスタンプ見れば一目瞭然かー。
自分の管理下にある Tasking Manager でログインできなくなった話
OpenStreetMap でそれなりに広いエリアを編集したい時は HOT の Tasking Manager を利用しています。
OSC 2017 Tokyo Spring で出展中にこの自分の管理下にある Tasking Manager を使って編集をしようと思いましたが、ログインしようとするとエラーになるので使うのを一時的にあきらめました。
原因の調査
落ち着いて作業できる状況になったところで動作のログを確認すると次のようなものが表示されていました。
SSLHandshakeError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:590)
SSL の証明書関係でエラーが出ているようです。
そういえば先月あたりに OpenStreetMap Foundation が管理する Web サイトの証明書が Let’s Encrypt のものになったというニュースがありました。きっとこれです。
問題の修正
Tasking Manager のリポジトリでも同じエラーによる issue が上がっていて解決法も示されていました。
virtualenv の環境で pip パッケージの更新をすればよいようです。
$ ./env/bin/pip install --upgrade httplib2 $ ./env/bin/pip install --upgrade urllib3[secure]
さらに起こった悲劇(?)
これで無事にログインできるようになったのですが、ここで「Tasking Manager も更新しちゃえ」と git pull
したのが運の尽き、今度は Tasking Manager 自体が動かなくなってしまいました。
git pull
以後のログを確認すると「project
テーブルに requires_validator_role
カラムなんてねーよ」という感じのエラーが出ていました。
解決方法の模索
カラムがないならカラムを追加すればいいじゃないと思ったのですが、カラムの型がわからないので手の出し様がありません。
仕方なく docker で一時的な Tasking Manager を立ち上げてデータベースを比較します。構造の比較方法なんて知らないので手動で確認しました。
ざっくり次のような形で新しい Tasking Manager で使われている project テーブルを確認しました。
new$ sudo -u postgres psql -d newosmtm newosmtm=# \d project; <snip> id | integer | not null default nextval('project_id_seq'::regclass) status | integer | area_id | integer | created | timestamp without time zone | author_id | bigint | last_update | timestamp without time zone | license_id | integer | zoom | integer | imagery | character varying | priority | integer | done | double precision | validated | double precision | entities_to_map | character varying | changeset_comment | character varying | private | boolean | josm_preset | character varying | due_date | timestamp without time zone | requires_validator_role | boolean | not null default false requires_experienced_mapper_role | boolean | not null default false <snip>
既存の Tasking Manager には requires_validator_role
と requires_experienced_mapper_role
のカラムがありません、これを boolean で false を持った状態で追加させればなんとかなりそうです。
current$ sudo -u postgres psql -d osmtm osmtm=# ALTER TABLE project ADD requires_validator_role boolean DEFAULT false NOT NULL, ADD requires_experienced_mapper_role boolean DEFAULT false NOT NULL;
\dt;
を実行したところ新しい方の Tasking Manager ではテーブルも3つ増えていました。
プロジェクトへラベルを付与できるようになったのかそんな感じの名前のテーブルがありました。これらのテーブルスキーマを取り出してやればよさそうです。
new$ sudo -u postgres pg_dump -d osmtm -s -t project_labels > project_labels.sql new$ sudo -u postgres pg_dump -d osmtm -s -t labels > labels.sql new$ sudo -u postgres pg_dump -d osmtm -s -t labels_translation > labels_translation.sql
3つのファイルをどうにかして既存のサーバーにコピーして取り込みます。
current$ sudo -u postgres psql -d osmtm < project_labels.sql current$ sudo -u postgres psql -d osmtm < labels.sql current$ sudo -u postgres psql -d osmtm < labels_translation.sql
これでやっと動くようになりました。ながかった…。